[
  {
    "path": ".gitignore",
    "content": "\n# Visual Studio files\n.vs/\n*.user\n\n# Output object and binary folders\n[Dd]ebug/\n[Rr]elease/\n[Bb]in/\n"
  },
  {
    "path": "CnCRemastered.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.1022\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"TiberianDawn\", \"TiberianDawn\\TiberianDawn.vcxproj\", \"{1380ED08-82A3-49C2-A171-1915574B3382}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"RedAlert\", \"RedAlert\\RedAlert.vcxproj\", \"{DA948ED9-EF67-4813-94B7-995BE956786E}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{1380ED08-82A3-49C2-A171-1915574B3382}.Release|x86.ActiveCfg = Release|Win32\n\t\t{1380ED08-82A3-49C2-A171-1915574B3382}.Release|x86.Build.0 = Release|Win32\n\t\t{DA948ED9-EF67-4813-94B7-995BE956786E}.Release|x86.ActiveCfg = Release|Win32\n\t\t{DA948ED9-EF67-4813-94B7-995BE956786E}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {712D2733-25EE-407D-AEF8-B2342757E119}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "CnCTDRAMapEditor/App.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n    <configSections>\n        <sectionGroup name=\"applicationSettings\" type=\"System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n            <section name=\"MobiusEditor.Properties.Settings\" type=\"System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" requirePermission=\"false\"/>\n        </sectionGroup>\n        <sectionGroup name=\"userSettings\" type=\"System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n            <section name=\"MobiusEditor.Properties.Settings\" type=\"System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" allowExeDefinition=\"MachineToLocalUser\" requirePermission=\"false\"/>\n        </sectionGroup>\n    </configSections>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6.2\"/>\n    </startup>\n    <applicationSettings>\n        <MobiusEditor.Properties.Settings>\n            <setting name=\"Quality\" serializeAs=\"String\">\n                <value>2</value>\n            </setting>\n        </MobiusEditor.Properties.Settings>\n    </applicationSettings>\n    <userSettings>\n        <MobiusEditor.Properties.Settings>\n            <setting name=\"ToolDialogPosition\" serializeAs=\"String\">\n                <value>0, 0</value>\n            </setting>\n            <setting name=\"ShowInviteWarning\" serializeAs=\"String\">\n                <value>True</value>\n            </setting>\n        </MobiusEditor.Properties.Settings>\n    </userSettings>\n    <runtime>\n      <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n        <probing privatePath=\"bin\" />\n      </assemblyBinding>\n    </runtime>\n</configuration>\n"
  },
  {
    "path": "CnCTDRAMapEditor/CnCTDRAMapEditor.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" ToolsVersion=\"15.0\">\n  <Import Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProjectGuid>{397CEF00-8930-4EC8-B15F-F7CF7193FB22}</ProjectGuid>\n    <OutputType>WinExe</OutputType>\n    <RootNamespace>MobiusEditor</RootNamespace>\n    <AssemblyName Condition=\"'$(Configuration)'=='Debug'\">CnCTDRAMapEditorD</AssemblyName>\n    <AssemblyName Condition=\"'$(Configuration)'=='Release'\">CnCTDRAMapEditor</AssemblyName>\n    <AssemblyName Condition=\"'$(Configuration)'=='Gold'\">CnCTDRAMapEditor</AssemblyName>\n    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>\n    <FileAlignment>512</FileAlignment>\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\n    <Deterministic>true</Deterministic>\n    <SccProjectName>SAK</SccProjectName>\n    <SccLocalPath>SAK</SccLocalPath>\n    <SccAuxPath>SAK</SccAuxPath>\n    <SccProvider>SAK</SccProvider>\n    <TargetFrameworkProfile />\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <PlatformTarget>x64</PlatformTarget>\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>TRACE;DEBUG;STEAMWORKS_WIN;STEAMWORKS_X64;DEVELOPER</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>7.3</LangVersion>\n    <Prefer32Bit>false</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <PlatformTarget>x64</PlatformTarget>\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE;STEAMWORKS_WIN;STEAMWORKS_X64;DEVELOPER</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>7.3</LangVersion>\n    <Prefer32Bit>false</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Gold|AnyCPU'\">\n    <OutputPath>bin\\Gold\\</OutputPath>\n    <DefineConstants>TRACE;STEAMWORKS_WIN;STEAMWORKS_X64</DefineConstants>\n    <Optimize>true</Optimize>\n    <DebugType>pdbonly</DebugType>\n    <PlatformTarget>x64</PlatformTarget>\n    <LangVersion>7.3</LangVersion>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <Prefer32Bit>false</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup>\n    <ApplicationIcon>Resources\\GameIcon00.ico</ApplicationIcon>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Core\" />\n    <Reference Include=\"System.IO.Compression\" />\n    <Reference Include=\"System.IO.Compression.FileSystem\" />\n    <Reference Include=\"System.Numerics\" />\n    <Reference Include=\"System.Xml.Linq\" />\n    <Reference Include=\"System.Data.DataSetExtensions\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Deployment\" />\n    <Reference Include=\"System.Drawing\" />\n    <Reference Include=\"System.Windows.Forms\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"Controls\\BasicSettings.cs\">\n      <SubType>UserControl</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\BasicSettings.Designer.cs\">\n      <DependentUpon>BasicSettings.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\BriefingSettings.cs\">\n      <SubType>UserControl</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\BriefingSettings.Designer.cs\">\n      <DependentUpon>BriefingSettings.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\ImageTooltip.cs\">\n      <SubType>Component</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\ImageTooltip.Designer.cs\">\n      <DependentUpon>ImageTooltip.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\MapPanel.cs\">\n      <SubType>Component</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\MapPanel.Designer.cs\">\n      <DependentUpon>MapPanel.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\MenuButton.cs\">\n      <SubType>Component</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\MenuButton.Designer.cs\">\n      <DependentUpon>MenuButton.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\PropertiesComboBox.cs\">\n      <SubType>Component</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\PropertiesComboBox.Designer.cs\">\n      <DependentUpon>PropertiesComboBox.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\TerrainProperties.cs\">\n      <SubType>UserControl</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\TerrainProperties.Designer.cs\">\n      <DependentUpon>TerrainProperties.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\ObjectProperties.cs\">\n      <SubType>UserControl</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\ObjectProperties.Designer.cs\">\n      <DependentUpon>ObjectProperties.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\PlayerSettings.cs\">\n      <SubType>UserControl</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\PlayerSettings.Designer.cs\">\n      <DependentUpon>PlayerSettings.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Controls\\TypeComboBox.cs\">\n      <SubType>Component</SubType>\n    </Compile>\n    <Compile Include=\"Controls\\TypeComboBox.Designer.cs\">\n      <DependentUpon>TypeComboBox.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\ErrorMessageBox.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\ErrorMessageBox.Designer.cs\">\n      <DependentUpon>ErrorMessageBox.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\InviteMessageBox.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\InviteMessageBox.Designer.cs\">\n      <DependentUpon>InviteMessageBox.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\MapSettingsDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\MapSettingsDialog.Designer.cs\">\n      <DependentUpon>MapSettingsDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\NewMapDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\NewMapDialog.Designer.cs\">\n      <DependentUpon>NewMapDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\SteamDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\SteamDialog.Designer.cs\">\n      <DependentUpon>SteamDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\TriggersDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\TriggersDialog.Designer.cs\">\n      <DependentUpon>TriggersDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Dialogs\\TeamTypesDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Dialogs\\TeamTypesDialog.Designer.cs\">\n      <DependentUpon>TeamTypesDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Event\\RenderEventArgs.cs\" />\n    <Compile Include=\"Event\\UndoRedoEventArgs.cs\" />\n    <Compile Include=\"Globals.cs\" />\n    <Compile Include=\"Interface\\IBrowsableType.cs\" />\n    <Compile Include=\"Interface\\ICellOccupier.cs\" />\n    <Compile Include=\"Interface\\ICellOverlapper.cs\" />\n    <Compile Include=\"Interface\\IGamePlugin.cs\" />\n    <Compile Include=\"Interface\\INamedType.cs\" />\n    <Compile Include=\"Interface\\ITechnoType.cs\" />\n    <Compile Include=\"Interface\\ITool.cs\" />\n    <Compile Include=\"Interface\\IWidget.cs\" />\n    <Compile Include=\"MainForm.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"MainForm.Designer.cs\">\n      <DependentUpon>MainForm.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Model\\BasicSection.cs\" />\n    <Compile Include=\"Model\\BriefingSection.cs\" />\n    <Compile Include=\"Model\\Building.cs\" />\n    <Compile Include=\"Model\\CellGrid.cs\" />\n    <Compile Include=\"Model\\CellMetrics.cs\" />\n    <Compile Include=\"Model\\CellTrigger.cs\" />\n    <Compile Include=\"Model\\DirectionType.cs\" />\n    <Compile Include=\"Model\\House.cs\" />\n    <Compile Include=\"Model\\HouseType.cs\" />\n    <Compile Include=\"Model\\BuildingType.cs\" />\n    <Compile Include=\"Model\\Infantry.cs\" />\n    <Compile Include=\"Model\\Map.cs\" />\n    <Compile Include=\"Model\\MapSection.cs\" />\n    <Compile Include=\"Model\\OccupierSet.cs\" />\n    <Compile Include=\"Model\\OverlapperSet.cs\" />\n    <Compile Include=\"Model\\Overlay.cs\" />\n    <Compile Include=\"Model\\OverlayType.cs\" />\n    <Compile Include=\"Model\\Smudge.cs\" />\n    <Compile Include=\"Model\\SmudgeType.cs\" />\n    <Compile Include=\"Model\\SteamSection.cs\" />\n    <Compile Include=\"Model\\TeamType.cs\" />\n    <Compile Include=\"Model\\Template.cs\" />\n    <Compile Include=\"Model\\TemplateType.cs\" />\n    <Compile Include=\"Model\\Terrain.cs\" />\n    <Compile Include=\"Model\\TerrainType.cs\" />\n    <Compile Include=\"Model\\TheaterType.cs\" />\n    <Compile Include=\"Model\\Trigger.cs\" />\n    <Compile Include=\"Model\\InfantryType.cs\" />\n    <Compile Include=\"Model\\TypeItem.cs\" />\n    <Compile Include=\"Model\\Unit.cs\" />\n    <Compile Include=\"Model\\UnitType.cs\" />\n    <Compile Include=\"Model\\Waypoint.cs\" />\n    <Compile Include=\"Program.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"RedAlert\\ActionDataTypes.cs\" />\n    <Compile Include=\"RedAlert\\ActionTypes.cs\" />\n    <Compile Include=\"RedAlert\\BasicSection.cs\" />\n    <Compile Include=\"RedAlert\\BuildingTypes.cs\" />\n    <Compile Include=\"RedAlert\\Constants.cs\" />\n    <Compile Include=\"RedAlert\\DirectionTypes.cs\" />\n    <Compile Include=\"RedAlert\\EventTypes.cs\" />\n    <Compile Include=\"RedAlert\\GamePlugin.cs\" />\n    <Compile Include=\"RedAlert\\House.cs\" />\n    <Compile Include=\"RedAlert\\HouseTypes.cs\" />\n    <Compile Include=\"RedAlert\\InfantryTypes.cs\" />\n    <Compile Include=\"RedAlert\\MissionTypes.cs\" />\n    <Compile Include=\"RedAlert\\OverlayTypes.cs\" />\n    <Compile Include=\"RedAlert\\SmudgeTypes.cs\" />\n    <Compile Include=\"RedAlert\\TeamMissionTypes.cs\" />\n    <Compile Include=\"RedAlert\\TemplateTypes.cs\" />\n    <Compile Include=\"RedAlert\\TerrainTypes.cs\" />\n    <Compile Include=\"RedAlert\\TheaterTypes.cs\" />\n    <Compile Include=\"RedAlert\\UnitTypes.cs\" />\n    <Compile Include=\"Render\\MapRenderer.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamapplist.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamapps.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamclient.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamcontroller.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamfriends.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserver.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverapps.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverclient.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverhttp.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverinventory.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameservernetworking.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverstats.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverugc.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamgameserverutils.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamhtmlsurface.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamhttp.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteaminput.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteaminventory.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteammatchmaking.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteammusic.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteammusicremote.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamnetworking.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamparentalsettings.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamremoteplay.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamremotestorage.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamscreenshots.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamugc.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamunifiedmessages.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamuser.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamuserstats.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamutils.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\isteamvideo.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\NativeMethods.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\SteamCallbacks.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\SteamConstants.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\SteamEnums.cs\" />\n    <Compile Include=\"Steamworks.NET\\autogen\\SteamStructs.cs\" />\n    <Compile Include=\"Steamworks.NET\\CallbackDispatcher.cs\" />\n    <Compile Include=\"Steamworks.NET\\CallbackIdentity.cs\" />\n    <Compile Include=\"Steamworks.NET\\InteropHelp.cs\" />\n    <Compile Include=\"Steamworks.NET\\ISteamMatchmakingResponses.cs\" />\n    <Compile Include=\"Steamworks.NET\\Packsize.cs\" />\n    <Compile Include=\"Steamworks.NET\\Steam.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\MatchmakingTypes\\gameserveritem_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\MatchmakingTypes\\servernetadr_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClientPublic\\CGameID.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClientPublic\\CSteamID.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClientPublic\\HAuthTicket.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClient\\SteamAPIWarningMessageHook_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClient\\SteamAPI_CheckCallbackRegistered_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamClient\\SteamAPI_PostAPIResultInProcess_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamController\\ControllerActionSetHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamController\\ControllerAnalogActionHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamController\\ControllerDigitalActionHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamController\\ControllerHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamFriends\\FriendsGroupID_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamHTMLSurface\\HHTMLBrowser.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamHTTP\\HTTPCookieContainerHandle.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamHTTP\\HTTPRequestHandle.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInput\\InputActionSetHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInput\\InputAnalogActionHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInput\\InputDigitalActionHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInput\\InputHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInventory\\SteamInventoryResult_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInventory\\SteamInventoryUpdateHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInventory\\SteamItemDef_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamInventory\\SteamItemInstanceID_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamMatchmaking\\HServerListRequest.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamMatchmaking\\HServerQuery.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamNetworking\\SNetListenSocket_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamNetworking\\SNetSocket_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamRemoteStorage\\PublishedFileId_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamRemoteStorage\\PublishedFileUpdateHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamRemoteStorage\\UGCFileWriteStreamHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamRemoteStorage\\UGCHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamScreenshots\\ScreenshotHandle.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\AccountID_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\AppId_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\DepotId_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\ManifestId_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\PartyBeaconID_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\RTime32.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\SiteId_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamTypes\\SteamAPICall_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamUGC\\UGCQueryHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamUGC\\UGCUpdateHandle_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamUnifiedMessages\\ClientUnifiedMessageHandle.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamUserStats\\SteamLeaderboardEntries_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\SteamUserStats\\SteamLeaderboard_t.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\Steam_api_common\\HSteamPipe.cs\" />\n    <Compile Include=\"Steamworks.NET\\types\\Steam_api_common\\HSteamUser.cs\" />\n    <Compile Include=\"TiberianDawn\\ActionTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\BasicSection.cs\" />\n    <Compile Include=\"TiberianDawn\\Constants.cs\" />\n    <Compile Include=\"TiberianDawn\\DirectionTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\EventTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\GamePlugin.cs\" />\n    <Compile Include=\"TiberianDawn\\House.cs\" />\n    <Compile Include=\"TiberianDawn\\HouseTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\BuildingTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\MissionTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\OverlayTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\SmudgeTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\TeamMissionTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\TemplateTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\TerrainTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\TheaterTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\InfantryTypes.cs\" />\n    <Compile Include=\"TiberianDawn\\UnitTypes.cs\" />\n    <Compile Include=\"Tools\\BuildingTool.cs\" />\n    <Compile Include=\"Tools\\Dialogs\\ResourcesToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\ResourcesToolDialog.Designer.cs\">\n      <DependentUpon>ResourcesToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\ObjectToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\ObjectToolDialog.Designer.cs\">\n      <DependentUpon>ObjectToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\GenericToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\GenericToolDialog.Designer.cs\">\n      <DependentUpon>GenericToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\TerrainToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\TerrainToolDialog.Designer.cs\">\n      <DependentUpon>TerrainToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\TemplateToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\TemplateToolDialog.Designer.cs\">\n      <DependentUpon>TemplateToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\CellTriggersToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\CellTriggersToolDialog.Designer.cs\">\n      <DependentUpon>CellTriggersToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\WaypointsToolDialog.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Tools\\Dialogs\\WaypointsToolDialog.Designer.cs\">\n      <DependentUpon>WaypointsToolDialog.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"Tools\\InfantryTool.cs\" />\n    <Compile Include=\"Tools\\OverlaysTool.cs\" />\n    <Compile Include=\"Tools\\ResourcesTool.cs\" />\n    <Compile Include=\"Tools\\SmudgeTool.cs\" />\n    <Compile Include=\"Tools\\TemplateTool.cs\" />\n    <Compile Include=\"Tools\\TerrainTool.cs\" />\n    <Compile Include=\"Tools\\UnitTool.cs\" />\n    <Compile Include=\"Tools\\ViewTool.cs\" />\n    <Compile Include=\"Tools\\WallsTool.cs\" />\n    <Compile Include=\"Tools\\CellTriggersTool.cs\" />\n    <Compile Include=\"Tools\\WaypointsTool.cs\" />\n    <Compile Include=\"Utility\\CRC.cs\" />\n    <Compile Include=\"Utility\\ExtensionMethods.cs\" />\n    <Compile Include=\"Utility\\GameTextManager.cs\" />\n    <Compile Include=\"Utility\\INI.cs\" />\n    <Compile Include=\"Utility\\Megafile.cs\" />\n    <Compile Include=\"Utility\\MegafileBuilder.cs\" />\n    <Compile Include=\"Utility\\MegafileManager.cs\" />\n    <Compile Include=\"Utility\\MRU.cs\" />\n    <Compile Include=\"Utility\\PropertyTracker.cs\" />\n    <Compile Include=\"Utility\\SteamworksUGC.cs\" />\n    <Compile Include=\"Utility\\TeamColor.cs\" />\n    <Compile Include=\"Utility\\TeamColorManager.cs\" />\n    <Compile Include=\"Utility\\TextureManager.cs\" />\n    <Compile Include=\"Utility\\TGASharpLib.cs\" />\n    <Compile Include=\"Utility\\Tileset.cs\" />\n    <Compile Include=\"Utility\\TilesetManager.cs\" />\n    <Compile Include=\"Utility\\UndoRedoList.cs\" />\n    <Compile Include=\"Utility\\WWCompression.cs\" />\n    <Compile Include=\"Widgets\\NavigationWidget.cs\" />\n    <EmbeddedResource Include=\"Controls\\BasicSettings.resx\">\n      <DependentUpon>BasicSettings.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Controls\\BriefingSettings.resx\">\n      <DependentUpon>BriefingSettings.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Controls\\MapPanel.resx\">\n      <DependentUpon>MapPanel.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Controls\\TerrainProperties.resx\">\n      <DependentUpon>TerrainProperties.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Controls\\ObjectProperties.resx\">\n      <DependentUpon>ObjectProperties.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Controls\\PlayerSettings.resx\">\n      <DependentUpon>PlayerSettings.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\ErrorMessageBox.resx\">\n      <DependentUpon>ErrorMessageBox.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\InviteMessageBox.resx\">\n      <DependentUpon>InviteMessageBox.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\MapSettingsDialog.resx\">\n      <DependentUpon>MapSettingsDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\NewMapDialog.resx\">\n      <DependentUpon>NewMapDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\SteamDialog.resx\">\n      <DependentUpon>SteamDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\TriggersDialog.resx\">\n      <DependentUpon>TriggersDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Dialogs\\TeamTypesDialog.resx\">\n      <DependentUpon>TeamTypesDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"MainForm.resx\">\n      <DependentUpon>MainForm.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Properties\\Resources.resx\">\n      <Generator>ResXFileCodeGenerator</Generator>\n      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\n      <SubType>Designer</SubType>\n    </EmbeddedResource>\n    <Compile Include=\"Properties\\Resources.Designer.cs\">\n      <AutoGen>True</AutoGen>\n      <DependentUpon>Resources.resx</DependentUpon>\n      <DesignTime>True</DesignTime>\n    </Compile>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\ResourcesToolDialog.resx\">\n      <DependentUpon>ResourcesToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\ObjectToolDialog.resx\">\n      <DependentUpon>ObjectToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\GenericToolDialog.resx\">\n      <DependentUpon>GenericToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\TerrainToolDialog.resx\">\n      <DependentUpon>TerrainToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\TemplateToolDialog.resx\">\n      <DependentUpon>TemplateToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\CellTriggersToolDialog.resx\">\n      <DependentUpon>CellTriggersToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Tools\\Dialogs\\WaypointsToolDialog.resx\">\n      <DependentUpon>WaypointsToolDialog.cs</DependentUpon>\n    </EmbeddedResource>\n    <None Include=\"Properties\\Settings.settings\">\n      <Generator>SettingsSingleFileGenerator</Generator>\n      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\n    </None>\n    <Compile Include=\"Properties\\Settings.Designer.cs\">\n      <AutoGen>True</AutoGen>\n      <DependentUpon>Settings.settings</DependentUpon>\n      <DesignTimeSharedInput>True</DesignTimeSharedInput>\n    </Compile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"App.config\" />\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"Resources\\GameIcon00.ico\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"Resources\\UI_CustomMissionPreviewDefault.png\" />\n    <Content Include=\"Steamworks.NET\\redist\\steam_api.dll\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Newtonsoft.Json\">\n      <Version>12.0.3</Version>\n    </PackageReference>\n    <PackageReference Include=\"Pfim\">\n      <Version>0.9.1</Version>\n    </PackageReference>\n    <PackageReference Include=\"System.ValueTuple\">\n      <Version>4.5.0</Version>\n    </PackageReference>\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  </Project>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BasicSettings.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class BasicSettings\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.label10 = new System.Windows.Forms.Label();\n            this.loseComboBox = new System.Windows.Forms.ComboBox();\n            this.isSinglePlayerCheckBox = new System.Windows.Forms.CheckBox();\n            this.win4ComboBox = new System.Windows.Forms.ComboBox();\n            this.win3ComboBox = new System.Windows.Forms.ComboBox();\n            this.win2ComboBox = new System.Windows.Forms.ComboBox();\n            this.winComboBox = new System.Windows.Forms.ComboBox();\n            this.actionComboBox = new System.Windows.Forms.ComboBox();\n            this.briefComboBox = new System.Windows.Forms.ComboBox();\n            this.introComboBox = new System.Windows.Forms.ComboBox();\n            this.win4Label = new System.Windows.Forms.Label();\n            this.win3Label = new System.Windows.Forms.Label();\n            this.win2Label = new System.Windows.Forms.Label();\n            this.label9 = new System.Windows.Forms.Label();\n            this.label8 = new System.Windows.Forms.Label();\n            this.label7 = new System.Windows.Forms.Label();\n            this.label1 = new System.Windows.Forms.Label();\n            this.buildLevelLabel = new System.Windows.Forms.Label();\n            this.label2 = new System.Windows.Forms.Label();\n            this.label3 = new System.Windows.Forms.Label();\n            this.label4 = new System.Windows.Forms.Label();\n            this.label5 = new System.Windows.Forms.Label();\n            this.nameTxt = new System.Windows.Forms.TextBox();\n            this.playerComboBox = new System.Windows.Forms.ComboBox();\n            this.buidLevelNud = new System.Windows.Forms.NumericUpDown();\n            this.percentNud = new System.Windows.Forms.NumericUpDown();\n            this.carryOverMoneyNud = new System.Windows.Forms.NumericUpDown();\n            this.label6 = new System.Windows.Forms.Label();\n            this.authorTxt = new System.Windows.Forms.TextBox();\n            this.baseLabel = new System.Windows.Forms.Label();\n            this.baseComboBox = new System.Windows.Forms.ComboBox();\n            this.tableLayoutPanel1.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.buidLevelNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.percentNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.carryOverMoneyNud)).BeginInit();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.AutoSize = true;\n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.label10, 0, 15);\n            this.tableLayoutPanel1.Controls.Add(this.loseComboBox, 1, 15);\n            this.tableLayoutPanel1.Controls.Add(this.isSinglePlayerCheckBox, 1, 16);\n            this.tableLayoutPanel1.Controls.Add(this.win4ComboBox, 1, 14);\n            this.tableLayoutPanel1.Controls.Add(this.win3ComboBox, 1, 13);\n            this.tableLayoutPanel1.Controls.Add(this.win2ComboBox, 1, 12);\n            this.tableLayoutPanel1.Controls.Add(this.winComboBox, 1, 11);\n            this.tableLayoutPanel1.Controls.Add(this.actionComboBox, 1, 10);\n            this.tableLayoutPanel1.Controls.Add(this.briefComboBox, 1, 9);\n            this.tableLayoutPanel1.Controls.Add(this.introComboBox, 1, 8);\n            this.tableLayoutPanel1.Controls.Add(this.win4Label, 0, 14);\n            this.tableLayoutPanel1.Controls.Add(this.win3Label, 0, 13);\n            this.tableLayoutPanel1.Controls.Add(this.win2Label, 0, 12);\n            this.tableLayoutPanel1.Controls.Add(this.label9, 0, 11);\n            this.tableLayoutPanel1.Controls.Add(this.label8, 0, 10);\n            this.tableLayoutPanel1.Controls.Add(this.label7, 0, 9);\n            this.tableLayoutPanel1.Controls.Add(this.label1, 0, 8);\n            this.tableLayoutPanel1.Controls.Add(this.buildLevelLabel, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2);\n            this.tableLayoutPanel1.Controls.Add(this.label4, 0, 3);\n            this.tableLayoutPanel1.Controls.Add(this.label5, 0, 4);\n            this.tableLayoutPanel1.Controls.Add(this.nameTxt, 1, 2);\n            this.tableLayoutPanel1.Controls.Add(this.playerComboBox, 1, 4);\n            this.tableLayoutPanel1.Controls.Add(this.buidLevelNud, 1, 0);\n            this.tableLayoutPanel1.Controls.Add(this.percentNud, 1, 3);\n            this.tableLayoutPanel1.Controls.Add(this.carryOverMoneyNud, 1, 1);\n            this.tableLayoutPanel1.Controls.Add(this.label6, 0, 5);\n            this.tableLayoutPanel1.Controls.Add(this.authorTxt, 1, 5);\n            this.tableLayoutPanel1.Controls.Add(this.baseLabel, 0, 6);\n            this.tableLayoutPanel1.Controls.Add(this.baseComboBox, 1, 6);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 17;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(300, 403);\n            this.tableLayoutPanel1.TabIndex = 1;\n            // \n            // label10\n            // \n            this.label10.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label10.Location = new System.Drawing.Point(2, 355);\n            this.label10.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label10.Name = \"label10\";\n            this.label10.Size = new System.Drawing.Size(87, 25);\n            this.label10.TabIndex = 35;\n            this.label10.Text = \"Lose\";\n            this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // loseComboBox\n            // \n            this.loseComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.loseComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.loseComboBox.FormattingEnabled = true;\n            this.loseComboBox.Location = new System.Drawing.Point(93, 357);\n            this.loseComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.loseComboBox.Name = \"loseComboBox\";\n            this.loseComboBox.Size = new System.Drawing.Size(205, 21);\n            this.loseComboBox.TabIndex = 34;\n            // \n            // isSinglePlayerCheckBox\n            // \n            this.isSinglePlayerCheckBox.AutoSize = true;\n            this.isSinglePlayerCheckBox.Location = new System.Drawing.Point(93, 382);\n            this.isSinglePlayerCheckBox.Margin = new System.Windows.Forms.Padding(2);\n            this.isSinglePlayerCheckBox.Name = \"isSinglePlayerCheckBox\";\n            this.isSinglePlayerCheckBox.Size = new System.Drawing.Size(87, 17);\n            this.isSinglePlayerCheckBox.TabIndex = 32;\n            this.isSinglePlayerCheckBox.Text = \"Single-Player\";\n            this.isSinglePlayerCheckBox.UseVisualStyleBackColor = true;\n            this.isSinglePlayerCheckBox.CheckedChanged += new System.EventHandler(this.isSinglePlayerCheckBox_CheckedChanged);\n            // \n            // win4ComboBox\n            // \n            this.win4ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win4ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.win4ComboBox.FormattingEnabled = true;\n            this.win4ComboBox.Location = new System.Drawing.Point(93, 332);\n            this.win4ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.win4ComboBox.Name = \"win4ComboBox\";\n            this.win4ComboBox.Size = new System.Drawing.Size(205, 21);\n            this.win4ComboBox.TabIndex = 31;\n            // \n            // win3ComboBox\n            // \n            this.win3ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win3ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.win3ComboBox.FormattingEnabled = true;\n            this.win3ComboBox.Location = new System.Drawing.Point(93, 307);\n            this.win3ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.win3ComboBox.Name = \"win3ComboBox\";\n            this.win3ComboBox.Size = new System.Drawing.Size(205, 21);\n            this.win3ComboBox.TabIndex = 30;\n            // \n            // win2ComboBox\n            // \n            this.win2ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win2ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.win2ComboBox.FormattingEnabled = true;\n            this.win2ComboBox.Location = new System.Drawing.Point(93, 282);\n            this.win2ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.win2ComboBox.Name = \"win2ComboBox\";\n            this.win2ComboBox.Size = new System.Drawing.Size(205, 21);\n            this.win2ComboBox.TabIndex = 29;\n            // \n            // winComboBox\n            // \n            this.winComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.winComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.winComboBox.FormattingEnabled = true;\n            this.winComboBox.Location = new System.Drawing.Point(93, 257);\n            this.winComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.winComboBox.Name = \"winComboBox\";\n            this.winComboBox.Size = new System.Drawing.Size(205, 21);\n            this.winComboBox.TabIndex = 28;\n            // \n            // actionComboBox\n            // \n            this.actionComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.actionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.actionComboBox.FormattingEnabled = true;\n            this.actionComboBox.Location = new System.Drawing.Point(93, 232);\n            this.actionComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.actionComboBox.Name = \"actionComboBox\";\n            this.actionComboBox.Size = new System.Drawing.Size(205, 21);\n            this.actionComboBox.TabIndex = 27;\n            // \n            // briefComboBox\n            // \n            this.briefComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.briefComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.briefComboBox.FormattingEnabled = true;\n            this.briefComboBox.Location = new System.Drawing.Point(93, 207);\n            this.briefComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.briefComboBox.Name = \"briefComboBox\";\n            this.briefComboBox.Size = new System.Drawing.Size(205, 21);\n            this.briefComboBox.TabIndex = 26;\n            // \n            // introComboBox\n            // \n            this.introComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.introComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.introComboBox.FormattingEnabled = true;\n            this.introComboBox.Location = new System.Drawing.Point(93, 182);\n            this.introComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.introComboBox.Name = \"introComboBox\";\n            this.introComboBox.Size = new System.Drawing.Size(205, 21);\n            this.introComboBox.TabIndex = 25;\n            // \n            // win4Label\n            // \n            this.win4Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win4Label.Location = new System.Drawing.Point(2, 330);\n            this.win4Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.win4Label.Name = \"win4Label\";\n            this.win4Label.Size = new System.Drawing.Size(87, 25);\n            this.win4Label.TabIndex = 24;\n            this.win4Label.Text = \"Win4\";\n            this.win4Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // win3Label\n            // \n            this.win3Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win3Label.Location = new System.Drawing.Point(2, 305);\n            this.win3Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.win3Label.Name = \"win3Label\";\n            this.win3Label.Size = new System.Drawing.Size(87, 25);\n            this.win3Label.TabIndex = 23;\n            this.win3Label.Text = \"Win3\";\n            this.win3Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // win2Label\n            // \n            this.win2Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.win2Label.Location = new System.Drawing.Point(2, 280);\n            this.win2Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.win2Label.Name = \"win2Label\";\n            this.win2Label.Size = new System.Drawing.Size(87, 25);\n            this.win2Label.TabIndex = 22;\n            this.win2Label.Text = \"Win2\";\n            this.win2Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label9\n            // \n            this.label9.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label9.Location = new System.Drawing.Point(2, 255);\n            this.label9.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label9.Name = \"label9\";\n            this.label9.Size = new System.Drawing.Size(87, 25);\n            this.label9.TabIndex = 21;\n            this.label9.Text = \"Win\";\n            this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label8\n            // \n            this.label8.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label8.Location = new System.Drawing.Point(2, 230);\n            this.label8.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label8.Name = \"label8\";\n            this.label8.Size = new System.Drawing.Size(87, 25);\n            this.label8.TabIndex = 20;\n            this.label8.Text = \"Action\";\n            this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label7\n            // \n            this.label7.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label7.Location = new System.Drawing.Point(2, 205);\n            this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label7.Name = \"label7\";\n            this.label7.Size = new System.Drawing.Size(87, 25);\n            this.label7.TabIndex = 19;\n            this.label7.Text = \"Brief\";\n            this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label1\n            // \n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(2, 180);\n            this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(87, 25);\n            this.label1.TabIndex = 18;\n            this.label1.Text = \"Intro\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // buildLevelLabel\n            // \n            this.buildLevelLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.buildLevelLabel.Location = new System.Drawing.Point(3, 0);\n            this.buildLevelLabel.Name = \"buildLevelLabel\";\n            this.buildLevelLabel.Size = new System.Drawing.Size(85, 26);\n            this.buildLevelLabel.TabIndex = 0;\n            this.buildLevelLabel.Text = \"Build Level\";\n            this.buildLevelLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label2\n            // \n            this.label2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label2.Location = new System.Drawing.Point(3, 26);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(85, 26);\n            this.label2.TabIndex = 2;\n            this.label2.Text = \"Carryover Money\";\n            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label3\n            // \n            this.label3.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label3.Location = new System.Drawing.Point(3, 52);\n            this.label3.Name = \"label3\";\n            this.label3.Size = new System.Drawing.Size(85, 26);\n            this.label3.TabIndex = 3;\n            this.label3.Text = \"Name\";\n            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label4\n            // \n            this.label4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label4.Location = new System.Drawing.Point(3, 78);\n            this.label4.Name = \"label4\";\n            this.label4.Size = new System.Drawing.Size(85, 26);\n            this.label4.TabIndex = 4;\n            this.label4.Text = \"Percent\";\n            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label5\n            // \n            this.label5.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label5.Location = new System.Drawing.Point(3, 104);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(85, 27);\n            this.label5.TabIndex = 5;\n            this.label5.Text = \"Player\";\n            this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // nameTxt\n            // \n            this.nameTxt.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.nameTxt.Location = new System.Drawing.Point(94, 55);\n            this.nameTxt.Name = \"nameTxt\";\n            this.nameTxt.Size = new System.Drawing.Size(203, 20);\n            this.nameTxt.TabIndex = 7;\n            // \n            // playerComboBox\n            // \n            this.playerComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.playerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.playerComboBox.FormattingEnabled = true;\n            this.playerComboBox.Location = new System.Drawing.Point(94, 107);\n            this.playerComboBox.Name = \"playerComboBox\";\n            this.playerComboBox.Size = new System.Drawing.Size(203, 21);\n            this.playerComboBox.TabIndex = 9;\n            // \n            // buidLevelNud\n            // \n            this.buidLevelNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.buidLevelNud.Location = new System.Drawing.Point(94, 3);\n            this.buidLevelNud.Name = \"buidLevelNud\";\n            this.buidLevelNud.Size = new System.Drawing.Size(203, 20);\n            this.buidLevelNud.TabIndex = 10;\n            // \n            // percentNud\n            // \n            this.percentNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.percentNud.Location = new System.Drawing.Point(94, 81);\n            this.percentNud.Name = \"percentNud\";\n            this.percentNud.Size = new System.Drawing.Size(203, 20);\n            this.percentNud.TabIndex = 11;\n            // \n            // carryOverMoneyNud\n            // \n            this.carryOverMoneyNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.carryOverMoneyNud.Location = new System.Drawing.Point(94, 29);\n            this.carryOverMoneyNud.Name = \"carryOverMoneyNud\";\n            this.carryOverMoneyNud.Size = new System.Drawing.Size(203, 20);\n            this.carryOverMoneyNud.TabIndex = 12;\n            // \n            // label6\n            // \n            this.label6.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label6.Location = new System.Drawing.Point(2, 131);\n            this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label6.Name = \"label6\";\n            this.label6.Size = new System.Drawing.Size(87, 24);\n            this.label6.TabIndex = 13;\n            this.label6.Text = \"Author\";\n            this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // authorTxt\n            // \n            this.authorTxt.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.authorTxt.Location = new System.Drawing.Point(93, 133);\n            this.authorTxt.Margin = new System.Windows.Forms.Padding(2);\n            this.authorTxt.Name = \"authorTxt\";\n            this.authorTxt.Size = new System.Drawing.Size(205, 20);\n            this.authorTxt.TabIndex = 14;\n            // \n            // baseLabel\n            // \n            this.baseLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.baseLabel.Location = new System.Drawing.Point(2, 155);\n            this.baseLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.baseLabel.Name = \"baseLabel\";\n            this.baseLabel.Size = new System.Drawing.Size(87, 25);\n            this.baseLabel.TabIndex = 15;\n            this.baseLabel.Text = \"Base\";\n            this.baseLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // baseComboBox\n            // \n            this.baseComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.baseComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.baseComboBox.FormattingEnabled = true;\n            this.baseComboBox.Location = new System.Drawing.Point(93, 157);\n            this.baseComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.baseComboBox.Name = \"baseComboBox\";\n            this.baseComboBox.Size = new System.Drawing.Size(205, 21);\n            this.baseComboBox.TabIndex = 16;\n            // \n            // BasicSettings\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Name = \"BasicSettings\";\n            this.Size = new System.Drawing.Size(300, 403);\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.buidLevelNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.percentNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.carryOverMoneyNud)).EndInit();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.Label buildLevelLabel;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.Label label3;\n        private System.Windows.Forms.Label label4;\n        private System.Windows.Forms.Label label5;\n        private System.Windows.Forms.TextBox nameTxt;\n        private System.Windows.Forms.ComboBox playerComboBox;\n        private System.Windows.Forms.NumericUpDown buidLevelNud;\n        private System.Windows.Forms.NumericUpDown percentNud;\n        private System.Windows.Forms.NumericUpDown carryOverMoneyNud;\n        private System.Windows.Forms.Label label6;\n        private System.Windows.Forms.TextBox authorTxt;\n        private System.Windows.Forms.Label baseLabel;\n        private System.Windows.Forms.ComboBox baseComboBox;\n        private System.Windows.Forms.Label win4Label;\n        private System.Windows.Forms.Label win3Label;\n        private System.Windows.Forms.Label win2Label;\n        private System.Windows.Forms.Label label9;\n        private System.Windows.Forms.Label label8;\n        private System.Windows.Forms.Label label7;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.CheckBox isSinglePlayerCheckBox;\n        private System.Windows.Forms.ComboBox win4ComboBox;\n        private System.Windows.Forms.ComboBox win3ComboBox;\n        private System.Windows.Forms.ComboBox win2ComboBox;\n        private System.Windows.Forms.ComboBox winComboBox;\n        private System.Windows.Forms.ComboBox actionComboBox;\n        private System.Windows.Forms.ComboBox briefComboBox;\n        private System.Windows.Forms.ComboBox introComboBox;\n        private System.Windows.Forms.ComboBox loseComboBox;\n        private System.Windows.Forms.Label label10;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BasicSettings.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class BasicSettings : UserControl\n    {\n        public BasicSettings(IGamePlugin plugin, dynamic basicSection)\n        {\n            InitializeComponent();\n\n            playerComboBox.DataSource = plugin.Map.Houses.Select(h => h.Type.Name).ToArray();\n            baseComboBox.DataSource = plugin.Map.Houses.Select(h => h.Type.Name).ToArray();\n            introComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            briefComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            actionComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            winComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            win2ComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            win3ComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            win4ComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n            loseComboBox.DataSource = plugin.Map.MovieTypes.ToArray();\n\n            carryOverMoneyNud.DataBindings.Add(\"Value\", basicSection, \"CarryOverMoney\");\n            nameTxt.DataBindings.Add(\"Text\", basicSection, \"Name\");\n            percentNud.DataBindings.Add(\"Value\", basicSection, \"Percent\");\n            playerComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Player\");\n            authorTxt.DataBindings.Add(\"Text\", basicSection, \"Author\");\n            isSinglePlayerCheckBox.DataBindings.Add(\"Checked\", basicSection, \"SoloMission\");\n            introComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Intro\");\n            briefComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Brief\");\n            actionComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Action\");\n            winComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Win\");\n            loseComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Lose\");\n\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    buidLevelNud.DataBindings.Add(\"Value\", basicSection, \"BuildLevel\");\n                    baseLabel.Visible = baseComboBox.Visible = false;\n                    win2Label.Visible = win2ComboBox.Visible = false;\n                    win3Label.Visible = win3ComboBox.Visible = false;\n                    win4Label.Visible = win4ComboBox.Visible = false;\n                    break;\n                case GameType.RedAlert:\n                    buidLevelNud.Visible = buildLevelLabel.Visible = false;\n                    baseComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"BasePlayer\");\n                    win2ComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Win2\");\n                    win3ComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Win3\");\n                    win4ComboBox.DataBindings.Add(\"SelectedItem\", basicSection, \"Win4\");\n                    break;\n            }\n\n            introComboBox.Enabled = briefComboBox.Enabled = actionComboBox.Enabled = loseComboBox.Enabled = isSinglePlayerCheckBox.Checked;\n            winComboBox.Enabled = win2ComboBox.Enabled = win3ComboBox.Enabled = win4ComboBox.Enabled = isSinglePlayerCheckBox.Checked;\n        }\n\n        private void isSinglePlayerCheckBox_CheckedChanged(object sender, EventArgs e)\n        {\n            introComboBox.Enabled = briefComboBox.Enabled = actionComboBox.Enabled = loseComboBox.Enabled = isSinglePlayerCheckBox.Checked;\n            winComboBox.Enabled = win2ComboBox.Enabled = win3ComboBox.Enabled = win4ComboBox.Enabled = isSinglePlayerCheckBox.Checked;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BasicSettings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BriefingSettings.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class BriefingSettings\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.briefingTxt = new System.Windows.Forms.TextBox();\n            this.SuspendLayout();\n            // \n            // briefingTxt\n            // \n            this.briefingTxt.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.briefingTxt.Location = new System.Drawing.Point(0, 0);\n            this.briefingTxt.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.briefingTxt.Multiline = true;\n            this.briefingTxt.Name = \"briefingTxt\";\n            this.briefingTxt.Size = new System.Drawing.Size(600, 400);\n            this.briefingTxt.TabIndex = 0;\n            // \n            // BriefingSettings\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.Controls.Add(this.briefingTxt);\n            this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.Name = \"BriefingSettings\";\n            this.Size = new System.Drawing.Size(600, 400);\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TextBox briefingTxt;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BriefingSettings.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class BriefingSettings : UserControl\n    {\n        public BriefingSettings(IGamePlugin plugin, dynamic briefingSection)\n        {\n            InitializeComponent();\n\n            briefingTxt.DataBindings.Add(\"Text\", briefingSection, \"Briefing\");\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/BriefingSettings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/ImageTooltip.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class ImageTooltip\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            components = new System.ComponentModel.Container();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/ImageTooltip.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Drawing;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class ImageTooltip : ToolTip\n    {\n        public Size MaxSize { get; set; } = Size.Empty;\n\n        public ImageTooltip()\n        {\n            InitializeComponent();\n\n            OwnerDraw = true;\n            Popup += ImageTooltip_Popup;\n            Draw += ImageTooltip_Draw;\n        }\n\n        private void ImageTooltip_Popup(object sender, PopupEventArgs e)\n        {\n            if (e.AssociatedControl.Tag is Image image)\n            {\n                var size = image.Size;\n                if (MaxSize.Width > 0)\n                {\n                    size.Width = Math.Min(MaxSize.Width, size.Width);\n                }\n                if (MaxSize.Height > 0)\n                {\n                    size.Height = Math.Min(MaxSize.Height, size.Height);\n                }\n\n                e.ToolTipSize = size;\n            }\n            else\n            {\n                e.Cancel = true;\n            }\n        }\n\n        private void ImageTooltip_Draw(object sender, DrawToolTipEventArgs e)\n        {\n            if (e.AssociatedControl.Tag is Image image)\n            {\n                e.Graphics.DrawImage(image, e.Bounds);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/MapPanel.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class MapPanel\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.SuspendLayout();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/MapPanel.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class MapPanel : Panel\n    {\n        private bool updatingCamera;\n        private Rectangle cameraBounds;\n        private Point lastScrollPosition;\n\n        private (Point map, SizeF client)? referencePositions;\n\n        private Matrix mapToViewTransform = new Matrix();\n        private Matrix viewToPageTransform = new Matrix();\n\n        private Matrix compositeTransform = new Matrix();\n        private Matrix invCompositeTransform = new Matrix();\n\n        private readonly HashSet<Point> invalidateCells = new HashSet<Point>();\n        private bool fullInvalidation;\n\n        private Image mapImage;\n        public Image MapImage\n        {\n            get => mapImage;\n            set\n            {\n                if (mapImage != value)\n                {\n                    mapImage = value;\n                    UpdateCamera();\n                }\n            }\n        }\n\n        private int minZoom = 1;\n        public int MinZoom\n        {\n            get => minZoom;\n            set\n            {\n                if (minZoom != value)\n                {\n                    minZoom = value;\n                    Zoom = zoom;\n                }\n            }\n        }\n\n        private int maxZoom = 8;\n        public int MaxZoom\n        {\n            get => maxZoom;\n            set\n            {\n                if (maxZoom != value)\n                {\n                    maxZoom = value;\n                    Zoom = zoom;\n                }\n            }\n        }\n\n        private int zoomStep = 1;\n        public int ZoomStep\n        {\n            get => zoomStep;\n            set\n            {\n                if (zoomStep != value)\n                {\n                    zoomStep = value;\n                    Zoom = (Zoom / zoomStep) * zoomStep;\n                }\n            }\n        }\n\n        private int zoom = 1;\n        public int Zoom\n        {\n            get => zoom;\n            set\n            {\n                var newZoom = Math.Max(MinZoom, Math.Min(MaxZoom, value));\n                if (zoom != newZoom)\n                {\n                    zoom = newZoom;\n\n                    var clientPosition = PointToClient(MousePosition);\n                    referencePositions = (ClientToMap(clientPosition), new SizeF(clientPosition.X / (float)ClientSize.Width, clientPosition.Y / (float)ClientSize.Height));\n\n                    UpdateCamera();\n                }\n            }\n        }\n\n        private int quality = Properties.Settings.Default.Quality;\n        public int Quality\n        {\n            get => quality;\n            set\n            {\n                if (quality != value)\n                {\n                    quality = value;\n                    Invalidate();\n                }\n            }\n        }\n\n        [Category(\"Behavior\")]\n        [DefaultValue(false)]\n        public bool FocusOnMouseEnter { get; set; }\n\n        public event EventHandler<RenderEventArgs> PreRender;\n        public event EventHandler<RenderEventArgs> PostRender;\n\n        public MapPanel()\n        {\n            InitializeComponent();\n            DoubleBuffered = true;\n        }\n\n        public Point MapToClient(Point point)\n        {\n            var points = new Point[] { point };\n            compositeTransform.TransformPoints(points);\n            return points[0];\n        }\n\n        public Size MapToClient(Size size)\n        {\n            var points = new Point[] { (Point)size };\n            compositeTransform.VectorTransformPoints(points);\n            return (Size)points[0];\n        }\n\n        public Rectangle MapToClient(Rectangle rectangle)\n        {\n            var points = new Point[] { rectangle.Location, new Point(rectangle.Right, rectangle.Bottom) };\n            compositeTransform.TransformPoints(points);\n            return new Rectangle(points[0], new Size(points[1].X - points[0].X, points[1].Y - points[0].Y));\n        }\n\n        public Point ClientToMap(Point point)\n        {\n            var points = new Point[] { point };\n            invCompositeTransform.TransformPoints(points);\n            return points[0];\n        }\n\n        public Size ClientToMap(Size size)\n        {\n            var points = new Point[] { (Point)size };\n            invCompositeTransform.VectorTransformPoints(points);\n            return (Size)points[0];\n        }\n\n        public Rectangle ClientToMap(Rectangle rectangle)\n        {\n            var points = new Point[] { rectangle.Location, new Point(rectangle.Right, rectangle.Bottom) };\n            invCompositeTransform.TransformPoints(points);\n            return new Rectangle(points[0], new Size(points[1].X - points[0].X, points[1].Y - points[0].Y));\n        }\n\n        public void Invalidate(Map invalidateMap)\n        {\n            if (!fullInvalidation)\n            {\n                invalidateCells.Clear();\n                fullInvalidation = true;\n                Invalidate();\n            }\n        }\n\n        public void Invalidate(Map invalidateMap, Rectangle cellBounds)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            var count = invalidateCells.Count;\n            invalidateCells.UnionWith(cellBounds.Points());\n            if (invalidateCells.Count > count)\n            {\n                var overlapCells = invalidateMap.Overlappers.Overlaps(invalidateCells).ToHashSet();\n                invalidateCells.UnionWith(overlapCells);\n                Invalidate();\n            }\n        }\n\n        public void Invalidate(Map invalidateMap, IEnumerable<Rectangle> cellBounds)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            var count = invalidateCells.Count;\n            invalidateCells.UnionWith(cellBounds.SelectMany(c => c.Points()));\n            if (invalidateCells.Count > count)\n            {\n                var overlapCells = invalidateMap.Overlappers.Overlaps(invalidateCells).ToHashSet();\n                invalidateCells.UnionWith(overlapCells);\n                Invalidate();\n            }\n        }\n\n        public void Invalidate(Map invalidateMap, Point location)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            Invalidate(invalidateMap, new Rectangle(location, new Size(1, 1)));\n        }\n\n        public void Invalidate(Map invalidateMap, IEnumerable<Point> locations)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            Invalidate(invalidateMap, locations.Select(l => new Rectangle(l, new Size(1, 1))));\n        }\n\n        public void Invalidate(Map invalidateMap, int cell)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            if (invalidateMap.Metrics.GetLocation(cell, out Point location))\n            {\n                Invalidate(invalidateMap, location);\n            }\n        }\n\n        public void Invalidate(Map invalidateMap, IEnumerable<int> cells)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            Invalidate(invalidateMap, cells\n                .Where(c => invalidateMap.Metrics.GetLocation(c, out Point location))\n                .Select(c =>\n                {\n                    invalidateMap.Metrics.GetLocation(c, out Point location);\n                    return location;\n                })\n            );\n        }\n\n        public void Invalidate(Map invalidateMap, ICellOverlapper overlapper)\n        {\n            if (fullInvalidation)\n            {\n                return;\n            }\n\n            var rectangle = invalidateMap.Overlappers[overlapper];\n            if (rectangle.HasValue)\n            {\n                Invalidate(invalidateMap, rectangle.Value);\n            }\n        }\n\n        protected override void OnMouseEnter(EventArgs e)\n        {\n            base.OnMouseEnter(e);\n\n            if (FocusOnMouseEnter)\n            {\n                Focus();\n            }\n        }\n\n        protected override void OnMouseWheel(MouseEventArgs e)\n        {\n            Zoom += ZoomStep * Math.Sign(e.Delta);\n        }\n\n        protected override void OnClientSizeChanged(EventArgs e)\n        {\n            base.OnClientSizeChanged(e);\n\n            UpdateCamera();\n        }\n\n        protected override void OnScroll(ScrollEventArgs se)\n        {\n            base.OnScroll(se);\n\n            InvalidateScroll();\n        }\n\n        protected override void OnPaintBackground(PaintEventArgs e)\n        {\n            base.OnPaintBackground(e);\n\n            e.Graphics.Clear(BackColor);\n        }\n\n        protected override void OnPaint(PaintEventArgs pe)\n        {\n            base.OnPaint(pe);\n\n            InvalidateScroll();\n\n            PreRender?.Invoke(this, new RenderEventArgs(pe.Graphics, fullInvalidation ? null : invalidateCells));\n\n            if (mapImage != null)\n            {\n                pe.Graphics.Transform = compositeTransform;\n\n                var oldCompositingMode = pe.Graphics.CompositingMode;\n                var oldCompositingQuality = pe.Graphics.CompositingQuality;\n                var oldInterpolationMode = pe.Graphics.InterpolationMode;\n                if (Quality > 1)\n                {\n                    pe.Graphics.CompositingMode = CompositingMode.SourceCopy;\n                    pe.Graphics.CompositingQuality = CompositingQuality.HighSpeed;\n                }\n\n                pe.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;\n                pe.Graphics.DrawImage(mapImage, 0, 0);\n\n                pe.Graphics.CompositingMode = oldCompositingMode;\n                pe.Graphics.CompositingQuality = oldCompositingQuality;\n                pe.Graphics.InterpolationMode = oldInterpolationMode;\n            }\n\n            PostRender?.Invoke(this, new RenderEventArgs(pe.Graphics, fullInvalidation ? null : invalidateCells));\n\n#if DEVELOPER\n            if (Globals.Developer.ShowOverlapCells)\n            {\n                var invalidPen = new Pen(Color.DarkRed);\n                foreach (var cell in invalidateCells)\n                {\n                    pe.Graphics.DrawRectangle(invalidPen, new Rectangle(cell.X * Globals.TileWidth, cell.Y * Globals.TileHeight, Globals.TileWidth, Globals.TileHeight));\n                }\n            }\n#endif\n\n            invalidateCells.Clear();\n            fullInvalidation = false;\n        }\n\n        private void UpdateCamera()\n        {\n            if (mapImage == null)\n            {\n                return;\n            }\n\n            if (ClientSize.IsEmpty)\n            {\n                return;\n            }\n\n            updatingCamera = true;\n\n            var mapAspect = (double)mapImage.Width / mapImage.Height;\n            var panelAspect = (double)ClientSize.Width / ClientSize.Height;\n            var cameraLocation = cameraBounds.Location;\n\n            var size = Size.Empty;\n            if (panelAspect > mapAspect)\n            {\n                size.Height = mapImage.Height / zoom;\n                size.Width = (int)(size.Height * panelAspect);\n            }\n            else\n            {\n                size.Width = mapImage.Width / zoom;\n                size.Height = (int)(size.Width / panelAspect);\n            }\n\n            var location = Point.Empty;\n            var scrollSize = Size.Empty;\n            if (size.Width < mapImage.Width)\n            {\n                location.X = Math.Max(0, Math.Min(mapImage.Width - size.Width, cameraBounds.Left));\n                scrollSize.Width = mapImage.Width * ClientSize.Width / size.Width;\n            }\n            else\n            {\n                location.X = (mapImage.Width - size.Width) / 2;\n            }\n\n            if (size.Height < mapImage.Height)\n            {\n                location.Y = Math.Max(0, Math.Min(mapImage.Height - size.Height, cameraBounds.Top));\n                scrollSize.Height = mapImage.Height * ClientSize.Height / size.Height;\n            }\n            else\n            {\n                location.Y = (mapImage.Height - size.Height) / 2;\n            }\n\n            cameraBounds = new Rectangle(location, size);\n            RecalculateTransforms();\n\n            if (referencePositions.HasValue)\n            {\n                var mapPoint = referencePositions.Value.map;\n                var clientSize = referencePositions.Value.client;\n\n                cameraLocation = cameraBounds.Location;\n                if (scrollSize.Width != 0)\n                {\n                    cameraLocation.X = Math.Max(0, Math.Min(mapImage.Width - cameraBounds.Width, (int)(mapPoint.X - (cameraBounds.Width * clientSize.Width))));\n                }\n                if (scrollSize.Height != 0)\n                {\n                    cameraLocation.Y = Math.Max(0, Math.Min(mapImage.Height - cameraBounds.Height, (int)(mapPoint.Y - (cameraBounds.Height * clientSize.Height))));\n                }\n                if (!scrollSize.IsEmpty)\n                {\n                    cameraBounds.Location = cameraLocation;\n                    RecalculateTransforms();\n                }\n\n                referencePositions = null;\n            }\n\n            SuspendDrawing();\n            AutoScrollMinSize = scrollSize;\n            AutoScrollPosition = (Point)MapToClient((Size)cameraBounds.Location);\n            lastScrollPosition = AutoScrollPosition;\n            ResumeDrawing();\n\n            updatingCamera = false;\n\n            Invalidate();\n        }\n\n        private void RecalculateTransforms()\n        {\n            mapToViewTransform.Reset();\n            mapToViewTransform.Translate(cameraBounds.Left, cameraBounds.Top);\n            mapToViewTransform.Scale(cameraBounds.Width, cameraBounds.Height);\n            mapToViewTransform.Invert();\n\n            viewToPageTransform.Reset();\n            viewToPageTransform.Scale(ClientSize.Width, ClientSize.Height);\n\n            compositeTransform.Reset();\n            compositeTransform.Multiply(viewToPageTransform);\n            compositeTransform.Multiply(mapToViewTransform);\n\n            invCompositeTransform.Reset();\n            invCompositeTransform.Multiply(compositeTransform);\n            invCompositeTransform.Invert();\n        }\n\n        private void InvalidateScroll()\n        {\n            if (updatingCamera)\n            {\n                return;\n            }\n\n            if ((lastScrollPosition.X != AutoScrollPosition.X) || (lastScrollPosition.Y != AutoScrollPosition.Y))\n            {\n                var delta = ClientToMap((Size)(lastScrollPosition - (Size)AutoScrollPosition));\n                lastScrollPosition = AutoScrollPosition;\n\n                var cameraLocation = cameraBounds.Location;\n                if (AutoScrollMinSize.Width != 0)\n                {\n                    cameraLocation.X = Math.Max(0, Math.Min(mapImage.Width - cameraBounds.Width, cameraBounds.Left + delta.Width));\n                }\n                if (AutoScrollMinSize.Height != 0)\n                {\n                    cameraLocation.Y = Math.Max(0, Math.Min(mapImage.Height - cameraBounds.Height, cameraBounds.Top + delta.Height));\n                }\n                if (!AutoScrollMinSize.IsEmpty)\n                {\n                    cameraBounds.Location = cameraLocation;\n                    RecalculateTransforms();\n                }\n\n                Invalidate();\n            }\n        }\n\n        [DllImport(\"user32.dll\")]\n        private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);\n\n        private const int WM_SETREDRAW = 11;\n\n        private void SuspendDrawing()\n        {\n            SendMessage(Handle, WM_SETREDRAW, false, 0);\n        }\n\n        private void ResumeDrawing()\n        {\n            SendMessage(Handle, WM_SETREDRAW, true, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/MapPanel.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"$this.TrayLargeIcon\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </metadata>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/MenuButton.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class MenuButton\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            components = new System.ComponentModel.Container();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/MenuButton.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class MenuButton : Button\n    {\n        public const int DefaultSplitWidth = 20;\n\n        [DefaultValue(null), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]\n        public ContextMenuStrip Menu { get; set; }\n\n        [DefaultValue(DefaultSplitWidth), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]\n        public int SplitWidth { get; set; } = DefaultSplitWidth;\n\n        public MenuButton()\n        {\n            InitializeComponent();\n        }\n\n        protected override void OnMouseDown(MouseEventArgs mevent)\n        {\n            var splitRect = new Rectangle(Width - SplitWidth, 0, SplitWidth, Height);\n\n            if ((Menu != null) && (mevent.Button == MouseButtons.Left) && splitRect.Contains(mevent.Location))\n            {\n                Menu.Show(this, 0, Height);\n            }\n            else\n            {\n                base.OnMouseDown(mevent);\n            }\n        }\n\n        protected override void OnPaint(PaintEventArgs pevent)\n        {\n            base.OnPaint(pevent);\n\n            if ((Menu != null) && (SplitWidth > 0))\n            {\n                int arrowX = ClientRectangle.Width - 14;\n                int arrowY = ClientRectangle.Height / 2 - 1;\n\n                var arrowBrush = Enabled ? SystemBrushes.ControlText : SystemBrushes.ButtonShadow;\n                var arrows = new[] { new Point(arrowX, arrowY), new Point(arrowX + 7, arrowY), new Point(arrowX + 3, arrowY + 4) };\n                pevent.Graphics.FillPolygon(arrowBrush, arrows);\n\n                int lineX = ClientRectangle.Width - SplitWidth;\n                int lineYFrom = arrowY - 4;\n                int lineYTo = arrowY + 8;\n                using (var separatorPen = new Pen(Brushes.DarkGray) { DashStyle = DashStyle.Dot })\n                {\n                    pevent.Graphics.DrawLine(separatorPen, lineX, lineYFrom, lineX, lineYTo);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/ObjectProperties.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class ObjectProperties\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.label2 = new System.Windows.Forms.Label();\n            this.directionLabel = new System.Windows.Forms.Label();\n            this.missionLabel = new System.Windows.Forms.Label();\n            this.label5 = new System.Windows.Forms.Label();\n            this.houseComboBox = new MobiusEditor.Controls.PropertiesComboBox();\n            this.strengthNud = new System.Windows.Forms.NumericUpDown();\n            this.directionComboBox = new MobiusEditor.Controls.PropertiesComboBox();\n            this.missionComboBox = new MobiusEditor.Controls.PropertiesComboBox();\n            this.triggerComboBox = new MobiusEditor.Controls.PropertiesComboBox();\n            this.basePriorityNud = new System.Windows.Forms.NumericUpDown();\n            this.prebuiltCheckBox = new System.Windows.Forms.CheckBox();\n            this.basePriorityLabel = new System.Windows.Forms.Label();\n            this.sellableCheckBox = new System.Windows.Forms.CheckBox();\n            this.rebuildCheckBox = new System.Windows.Forms.CheckBox();\n            this.tableLayoutPanel1.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.strengthNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.basePriorityNud)).BeginInit();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 31.25F));\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 68.75F));\n            this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.directionLabel, 0, 2);\n            this.tableLayoutPanel1.Controls.Add(this.missionLabel, 0, 3);\n            this.tableLayoutPanel1.Controls.Add(this.label5, 0, 4);\n            this.tableLayoutPanel1.Controls.Add(this.houseComboBox, 1, 0);\n            this.tableLayoutPanel1.Controls.Add(this.strengthNud, 1, 1);\n            this.tableLayoutPanel1.Controls.Add(this.directionComboBox, 1, 2);\n            this.tableLayoutPanel1.Controls.Add(this.missionComboBox, 1, 3);\n            this.tableLayoutPanel1.Controls.Add(this.triggerComboBox, 1, 4);\n            this.tableLayoutPanel1.Controls.Add(this.basePriorityNud, 1, 5);\n            this.tableLayoutPanel1.Controls.Add(this.prebuiltCheckBox, 1, 7);\n            this.tableLayoutPanel1.Controls.Add(this.basePriorityLabel, 0, 5);\n            this.tableLayoutPanel1.Controls.Add(this.sellableCheckBox, 1, 8);\n            this.tableLayoutPanel1.Controls.Add(this.rebuildCheckBox, 1, 9);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 11;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(299, 262);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(4, 0);\n            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(85, 32);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"House\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label2\n            // \n            this.label2.AutoSize = true;\n            this.label2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label2.Location = new System.Drawing.Point(4, 32);\n            this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(85, 30);\n            this.label2.TabIndex = 1;\n            this.label2.Text = \"Strength\";\n            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // directionLabel\n            // \n            this.directionLabel.AutoSize = true;\n            this.directionLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.directionLabel.Location = new System.Drawing.Point(4, 62);\n            this.directionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.directionLabel.Name = \"directionLabel\";\n            this.directionLabel.Size = new System.Drawing.Size(85, 32);\n            this.directionLabel.TabIndex = 2;\n            this.directionLabel.Text = \"Direction\";\n            this.directionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // missionLabel\n            // \n            this.missionLabel.AutoSize = true;\n            this.missionLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.missionLabel.Location = new System.Drawing.Point(4, 94);\n            this.missionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.missionLabel.Name = \"missionLabel\";\n            this.missionLabel.Size = new System.Drawing.Size(85, 32);\n            this.missionLabel.TabIndex = 3;\n            this.missionLabel.Text = \"Mission\";\n            this.missionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label5\n            // \n            this.label5.AutoSize = true;\n            this.label5.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label5.Location = new System.Drawing.Point(4, 126);\n            this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(85, 32);\n            this.label5.TabIndex = 4;\n            this.label5.Text = \"Trigger\";\n            this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // houseComboBox\n            // \n            this.houseComboBox.DisplayMember = \"Name\";\n            this.houseComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.houseComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.houseComboBox.FormattingEnabled = true;\n            this.houseComboBox.Location = new System.Drawing.Point(97, 4);\n            this.houseComboBox.Margin = new System.Windows.Forms.Padding(4);\n            this.houseComboBox.Name = \"houseComboBox\";\n            this.houseComboBox.Size = new System.Drawing.Size(198, 24);\n            this.houseComboBox.TabIndex = 5;\n            this.houseComboBox.ValueMember = \"Type\";\n            this.houseComboBox.SelectedIndexChanged += new System.EventHandler(this.comboBox_SelectedValueChanged);\n            // \n            // strengthNud\n            // \n            this.strengthNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.strengthNud.Location = new System.Drawing.Point(97, 36);\n            this.strengthNud.Margin = new System.Windows.Forms.Padding(4);\n            this.strengthNud.Maximum = new decimal(new int[] {\n            256,\n            0,\n            0,\n            0});\n            this.strengthNud.Minimum = new decimal(new int[] {\n            1,\n            0,\n            0,\n            0});\n            this.strengthNud.Name = \"strengthNud\";\n            this.strengthNud.Size = new System.Drawing.Size(198, 22);\n            this.strengthNud.TabIndex = 6;\n            this.strengthNud.Value = new decimal(new int[] {\n            256,\n            0,\n            0,\n            0});\n            this.strengthNud.ValueChanged += new System.EventHandler(this.nud_ValueChanged);\n            // \n            // directionComboBox\n            // \n            this.directionComboBox.DisplayMember = \"Name\";\n            this.directionComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.directionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.directionComboBox.FormattingEnabled = true;\n            this.directionComboBox.Location = new System.Drawing.Point(97, 66);\n            this.directionComboBox.Margin = new System.Windows.Forms.Padding(4);\n            this.directionComboBox.Name = \"directionComboBox\";\n            this.directionComboBox.Size = new System.Drawing.Size(198, 24);\n            this.directionComboBox.TabIndex = 7;\n            this.directionComboBox.ValueMember = \"Type\";\n            this.directionComboBox.SelectedIndexChanged += new System.EventHandler(this.comboBox_SelectedValueChanged);\n            // \n            // missionComboBox\n            // \n            this.missionComboBox.DisplayMember = \"Name\";\n            this.missionComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.missionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.missionComboBox.FormattingEnabled = true;\n            this.missionComboBox.Location = new System.Drawing.Point(97, 98);\n            this.missionComboBox.Margin = new System.Windows.Forms.Padding(4);\n            this.missionComboBox.Name = \"missionComboBox\";\n            this.missionComboBox.Size = new System.Drawing.Size(198, 24);\n            this.missionComboBox.TabIndex = 8;\n            this.missionComboBox.ValueMember = \"Type\";\n            this.missionComboBox.SelectedIndexChanged += new System.EventHandler(this.comboBox_SelectedValueChanged);\n            // \n            // triggerComboBox\n            // \n            this.triggerComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.triggerComboBox.FormattingEnabled = true;\n            this.triggerComboBox.Location = new System.Drawing.Point(97, 130);\n            this.triggerComboBox.Margin = new System.Windows.Forms.Padding(4);\n            this.triggerComboBox.Name = \"triggerComboBox\";\n            this.triggerComboBox.Size = new System.Drawing.Size(198, 24);\n            this.triggerComboBox.TabIndex = 9;\n            this.triggerComboBox.SelectedIndexChanged += new System.EventHandler(this.comboBox_SelectedValueChanged);\n            // \n            // basePriorityNud\n            // \n            this.basePriorityNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.basePriorityNud.Location = new System.Drawing.Point(96, 160);\n            this.basePriorityNud.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);\n            this.basePriorityNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.basePriorityNud.Minimum = new decimal(new int[] {\n            1,\n            0,\n            0,\n            -2147483648});\n            this.basePriorityNud.Name = \"basePriorityNud\";\n            this.basePriorityNud.Size = new System.Drawing.Size(200, 22);\n            this.basePriorityNud.TabIndex = 11;\n            this.basePriorityNud.ValueChanged += new System.EventHandler(this.nud_ValueChanged);\n            // \n            // prebuiltCheckBox\n            // \n            this.prebuiltCheckBox.AutoSize = true;\n            this.prebuiltCheckBox.Location = new System.Drawing.Point(96, 186);\n            this.prebuiltCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);\n            this.prebuiltCheckBox.Name = \"prebuiltCheckBox\";\n            this.prebuiltCheckBox.Size = new System.Drawing.Size(78, 21);\n            this.prebuiltCheckBox.TabIndex = 12;\n            this.prebuiltCheckBox.Text = \"Prebuilt\";\n            this.prebuiltCheckBox.UseVisualStyleBackColor = true;\n            this.prebuiltCheckBox.CheckedChanged += new System.EventHandler(this.checkBox_CheckedChanged);\n            // \n            // basePriorityLabel\n            // \n            this.basePriorityLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.basePriorityLabel.Location = new System.Drawing.Point(3, 158);\n            this.basePriorityLabel.Name = \"basePriorityLabel\";\n            this.basePriorityLabel.Size = new System.Drawing.Size(87, 26);\n            this.basePriorityLabel.TabIndex = 13;\n            this.basePriorityLabel.Text = \"Base Priority\";\n            this.basePriorityLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // sellableCheckBox\n            // \n            this.sellableCheckBox.AutoSize = true;\n            this.sellableCheckBox.Location = new System.Drawing.Point(96, 211);\n            this.sellableCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);\n            this.sellableCheckBox.Name = \"sellableCheckBox\";\n            this.sellableCheckBox.Size = new System.Drawing.Size(80, 21);\n            this.sellableCheckBox.TabIndex = 14;\n            this.sellableCheckBox.Text = \"Sellable\";\n            this.sellableCheckBox.UseVisualStyleBackColor = true;\n            this.sellableCheckBox.CheckedChanged += new System.EventHandler(this.checkBox_CheckedChanged);\n            // \n            // rebuildCheckBox\n            // \n            this.rebuildCheckBox.AutoSize = true;\n            this.rebuildCheckBox.Location = new System.Drawing.Point(96, 236);\n            this.rebuildCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);\n            this.rebuildCheckBox.Name = \"rebuildCheckBox\";\n            this.rebuildCheckBox.Size = new System.Drawing.Size(78, 21);\n            this.rebuildCheckBox.TabIndex = 15;\n            this.rebuildCheckBox.Text = \"Rebuild\";\n            this.rebuildCheckBox.UseVisualStyleBackColor = true;\n            this.rebuildCheckBox.CheckedChanged += new System.EventHandler(this.checkBox_CheckedChanged);\n            // \n            // ObjectProperties\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Margin = new System.Windows.Forms.Padding(4);\n            this.Name = \"ObjectProperties\";\n            this.Size = new System.Drawing.Size(299, 262);\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.strengthNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.basePriorityNud)).EndInit();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.Label directionLabel;\n        private System.Windows.Forms.Label missionLabel;\n        private System.Windows.Forms.Label label5;\n        private MobiusEditor.Controls.PropertiesComboBox houseComboBox;\n        private System.Windows.Forms.NumericUpDown strengthNud;\n        private MobiusEditor.Controls.PropertiesComboBox directionComboBox;\n        private MobiusEditor.Controls.PropertiesComboBox missionComboBox;\n        private MobiusEditor.Controls.PropertiesComboBox triggerComboBox;\n        private System.Windows.Forms.NumericUpDown basePriorityNud;\n        private System.Windows.Forms.CheckBox prebuiltCheckBox;\n        private System.Windows.Forms.Label basePriorityLabel;\n        private System.Windows.Forms.CheckBox sellableCheckBox;\n        private System.Windows.Forms.CheckBox rebuildCheckBox;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/ObjectProperties.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class ObjectProperties : UserControl\n    {\n        private bool isMockObject;\n\n        public IGamePlugin Plugin { get; private set; }\n\n        private INotifyPropertyChanged obj;\n        public INotifyPropertyChanged Object\n        {\n            get => obj;\n            set\n            {\n                if (obj != value)\n                {\n                    if (obj != null)\n                    {\n                        obj.PropertyChanged -= Obj_PropertyChanged;\n                    }\n\n                    obj = value;\n\n                    if (obj != null)\n                    {\n                        obj.PropertyChanged += Obj_PropertyChanged;\n                    }\n\n                    Rebind();\n                }\n            }\n        }\n\n        public ObjectProperties()\n        {\n            InitializeComponent();\n        }\n\n        public void Initialize(IGamePlugin plugin, bool isMockObject)\n        {\n            this.isMockObject = isMockObject;\n\n            Plugin = plugin;\n            plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;\n\n            houseComboBox.DataSource = plugin.Map.Houses.Select(t => new TypeItem<HouseType>(t.Type.Name, t.Type)).ToArray();\n            missionComboBox.DataSource = plugin.Map.MissionTypes;\n\n            UpdateDataSource();\n\n            Disposed += (sender, e) =>\n            {\n                Object = null;\n                plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;\n            };\n        }\n\n        private void Triggers_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n        {\n            UpdateDataSource();\n        }\n\n        private void UpdateDataSource()\n        {\n            triggerComboBox.DataSource = Trigger.None.Yield().Concat(Plugin.Map.Triggers.Select(t => t.Name).Distinct()).ToArray();\n        }\n\n        private void Rebind()\n        {\n            houseComboBox.DataBindings.Clear();\n            strengthNud.DataBindings.Clear();\n            directionComboBox.DataBindings.Clear();\n            missionComboBox.DataBindings.Clear();\n            triggerComboBox.DataBindings.Clear();\n            basePriorityNud.DataBindings.Clear();\n            prebuiltCheckBox.DataBindings.Clear();\n            sellableCheckBox.DataBindings.Clear();\n            rebuildCheckBox.DataBindings.Clear();\n\n            if (obj == null)\n            {\n                return;\n            }\n\n            switch (obj)\n            {\n                case Infantry infantry:\n                    {\n                        houseComboBox.Enabled = true;\n                        directionComboBox.DataSource = Plugin.Map.DirectionTypes\n                            .Where(t => t.Facing != FacingType.None)\n                            .Select(t => new TypeItem<DirectionType>(t.Name, t)).ToArray();\n\n                        missionComboBox.DataBindings.Add(\"SelectedItem\", obj, \"Mission\");\n                        missionLabel.Visible = missionComboBox.Visible = true;\n                        basePriorityLabel.Visible = basePriorityNud.Visible = false;\n                        prebuiltCheckBox.Visible = false;\n                        sellableCheckBox.Visible = false;\n                        rebuildCheckBox.Visible = false;\n                    }\n                    break;\n                case Unit unit:\n                    {\n                        houseComboBox.Enabled = true;\n                        directionComboBox.DataSource = Plugin.Map.DirectionTypes.Select(t => new TypeItem<DirectionType>(t.Name, t)).ToArray();\n                        missionComboBox.DataBindings.Add(\"SelectedItem\", obj, \"Mission\");\n                        missionLabel.Visible = missionComboBox.Visible = true;\n                        basePriorityLabel.Visible = basePriorityNud.Visible = false;\n                        prebuiltCheckBox.Visible = false;\n                        sellableCheckBox.Visible = false;\n                        rebuildCheckBox.Visible = false;\n                    }\n                    break;\n                case Building building:\n                    {\n                        houseComboBox.Enabled = building.IsPrebuilt;\n                        directionComboBox.DataSource = Plugin.Map.DirectionTypes.Select(t => new TypeItem<DirectionType>(t.Name, t)).ToArray();\n                        directionComboBox.Visible = (building.Type != null) && building.Type.HasTurret;\n                        missionLabel.Visible = missionComboBox.Visible = false;\n                        basePriorityLabel.Visible = basePriorityNud.Visible = true;\n                        prebuiltCheckBox.Visible = true;\n                        prebuiltCheckBox.Enabled = building.BasePriority >= 0;\n\n                        basePriorityNud.DataBindings.Add(\"Value\", obj, \"BasePriority\");\n                        prebuiltCheckBox.DataBindings.Add(\"Checked\", obj, \"IsPrebuilt\");\n\n                        switch (Plugin.GameType)\n                        {\n                            case GameType.TiberianDawn:\n                                {\n                                    sellableCheckBox.Visible = false;\n                                    rebuildCheckBox.Visible = false;\n                                } break;\n                            case GameType.RedAlert:\n                                {\n                                    sellableCheckBox.DataBindings.Add(\"Checked\", obj, \"Sellable\");\n                                    rebuildCheckBox.DataBindings.Add(\"Checked\", obj, \"Rebuild\");\n                                    sellableCheckBox.Visible = true;\n                                    rebuildCheckBox.Visible = true;\n                                } break;\n                        }\n                    }\n                    break;\n            }\n\n            houseComboBox.DataBindings.Add(\"SelectedValue\", obj, \"House\");\n            strengthNud.DataBindings.Add(\"Value\", obj, \"Strength\");\n            directionComboBox.DataBindings.Add(\"SelectedValue\", obj, \"Direction\");\n            triggerComboBox.DataBindings.Add(\"SelectedItem\", obj, \"Trigger\");\n        }\n\n        private void Obj_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"Type\":\n                    {\n                        Rebind();\n                    }\n                    break;\n                case \"BasePriority\":\n                    {\n                        if (obj is Building building)\n                        {\n                            prebuiltCheckBox.Enabled = building.BasePriority >= 0;\n                        }\n                    }\n                    break;\n                case \"IsPrebuilt\":\n                    {\n                        if (obj is Building building)\n                        {\n                            if (!building.IsPrebuilt)\n                            {\n                                var basePlayer = Plugin.Map.HouseTypes.Where(h => h.Equals(Plugin.Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Plugin.Map.HouseTypes.First();\n                                building.House = basePlayer;\n                            }\n                            houseComboBox.Enabled = building.IsPrebuilt;\n                        }\n                    } break;\n            }\n\n            if (!isMockObject)\n            {\n                Plugin.Dirty = true;\n            }\n        }\n\n        private void comboBox_SelectedValueChanged(object sender, EventArgs e)\n        {\n            foreach (Binding binding in (sender as ComboBox).DataBindings)\n            {\n                binding.WriteValue();\n            }\n        }\n\n        private void nud_ValueChanged(object sender, EventArgs e)\n        {\n            foreach (Binding binding in (sender as NumericUpDown).DataBindings)\n            {\n                binding.WriteValue();\n            }\n        }\n\n        private void checkBox_CheckedChanged(object sender, EventArgs e)\n        {\n            foreach (Binding binding in (sender as CheckBox).DataBindings)\n            {\n                binding.WriteValue();\n            }\n        }\n    }\n\n    public class ObjectPropertiesPopup : ToolStripDropDown\n    {\n        private readonly ToolStripControlHost host;\n\n        public ObjectProperties ObjectProperties { get; private set; }\n\n        public ObjectPropertiesPopup(IGamePlugin plugin, INotifyPropertyChanged obj)\n        {\n            ObjectProperties = new ObjectProperties();\n            ObjectProperties.Initialize(plugin, false);\n            ObjectProperties.Object = obj;\n\n            host = new ToolStripControlHost(ObjectProperties);\n            Padding = Margin = host.Padding = host.Margin = Padding.Empty;\n            MinimumSize = ObjectProperties.MinimumSize;\n            ObjectProperties.MinimumSize = ObjectProperties.Size;\n            MaximumSize = ObjectProperties.MaximumSize;\n            ObjectProperties.MaximumSize = ObjectProperties.Size;\n            Size = ObjectProperties.Size;\n            Items.Add(host);\n            ObjectProperties.Disposed += (sender, e) =>\n            {\n                ObjectProperties = null;\n                Dispose(true);\n            };\n        }\n\n        protected override void OnClosed(ToolStripDropDownClosedEventArgs e)\n        {\n            base.OnClosed(e);\n\n            ObjectProperties.Object = null;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/ObjectProperties.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/PlayerSettings.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class PlayerSettings\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.iqNud = new System.Windows.Forms.NumericUpDown();\n            this.techLevelNud = new System.Windows.Forms.NumericUpDown();\n            this.maxVesselsNud = new System.Windows.Forms.NumericUpDown();\n            this.maxInfantryNud = new System.Windows.Forms.NumericUpDown();\n            this.iqLbl = new System.Windows.Forms.Label();\n            this.techLevelLbl = new System.Windows.Forms.Label();\n            this.maxVesselsLbl = new System.Windows.Forms.Label();\n            this.maxInfantryLbl = new System.Windows.Forms.Label();\n            this.label1 = new System.Windows.Forms.Label();\n            this.edgeComboBox = new System.Windows.Forms.ComboBox();\n            this.label2 = new System.Windows.Forms.Label();\n            this.creditsNud = new System.Windows.Forms.NumericUpDown();\n            this.label3 = new System.Windows.Forms.Label();\n            this.label4 = new System.Windows.Forms.Label();\n            this.maxBuildingsNud = new System.Windows.Forms.NumericUpDown();\n            this.maxUnitsNud = new System.Windows.Forms.NumericUpDown();\n            this.label5 = new System.Windows.Forms.Label();\n            this.playersListBox = new System.Windows.Forms.ListBox();\n            this.playerControlLbl = new System.Windows.Forms.Label();\n            this.playerControlCheckBox = new System.Windows.Forms.CheckBox();\n            this.tableLayoutPanel1.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.iqNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.techLevelNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxVesselsNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxInfantryNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.creditsNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxBuildingsNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxUnitsNud)).BeginInit();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.AutoSize = true;\n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.Controls.Add(this.playerControlLbl, 0, 8);\n            this.tableLayoutPanel1.Controls.Add(this.iqNud, 1, 7);\n            this.tableLayoutPanel1.Controls.Add(this.techLevelNud, 1, 6);\n            this.tableLayoutPanel1.Controls.Add(this.maxVesselsNud, 1, 5);\n            this.tableLayoutPanel1.Controls.Add(this.maxInfantryNud, 1, 4);\n            this.tableLayoutPanel1.Controls.Add(this.iqLbl, 0, 7);\n            this.tableLayoutPanel1.Controls.Add(this.techLevelLbl, 0, 6);\n            this.tableLayoutPanel1.Controls.Add(this.maxVesselsLbl, 0, 5);\n            this.tableLayoutPanel1.Controls.Add(this.maxInfantryLbl, 0, 4);\n            this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.edgeComboBox, 1, 0);\n            this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.creditsNud, 1, 1);\n            this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2);\n            this.tableLayoutPanel1.Controls.Add(this.label4, 0, 3);\n            this.tableLayoutPanel1.Controls.Add(this.maxBuildingsNud, 1, 2);\n            this.tableLayoutPanel1.Controls.Add(this.maxUnitsNud, 1, 3);\n            this.tableLayoutPanel1.Controls.Add(this.label5, 0, 9);\n            this.tableLayoutPanel1.Controls.Add(this.playersListBox, 1, 9);\n            this.tableLayoutPanel1.Controls.Add(this.playerControlCheckBox, 1, 8);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 10;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(329, 372);\n            this.tableLayoutPanel1.TabIndex = 2;\n            // \n            // iqNud\n            // \n            this.iqNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.iqNud.Location = new System.Drawing.Point(81, 186);\n            this.iqNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.iqNud.Name = \"iqNud\";\n            this.iqNud.Size = new System.Drawing.Size(245, 20);\n            this.iqNud.TabIndex = 26;\n            // \n            // techLevelNud\n            // \n            this.techLevelNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.techLevelNud.Location = new System.Drawing.Point(81, 160);\n            this.techLevelNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.techLevelNud.Name = \"techLevelNud\";\n            this.techLevelNud.Size = new System.Drawing.Size(245, 20);\n            this.techLevelNud.TabIndex = 25;\n            // \n            // maxVesselsNud\n            // \n            this.maxVesselsNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.maxVesselsNud.Location = new System.Drawing.Point(81, 134);\n            this.maxVesselsNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.maxVesselsNud.Name = \"maxVesselsNud\";\n            this.maxVesselsNud.Size = new System.Drawing.Size(245, 20);\n            this.maxVesselsNud.TabIndex = 24;\n            // \n            // maxInfantryNud\n            // \n            this.maxInfantryNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.maxInfantryNud.Location = new System.Drawing.Point(81, 108);\n            this.maxInfantryNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.maxInfantryNud.Name = \"maxInfantryNud\";\n            this.maxInfantryNud.Size = new System.Drawing.Size(245, 20);\n            this.maxInfantryNud.TabIndex = 23;\n            // \n            // iqLbl\n            // \n            this.iqLbl.AutoSize = true;\n            this.iqLbl.Location = new System.Drawing.Point(3, 183);\n            this.iqLbl.Name = \"iqLbl\";\n            this.iqLbl.Size = new System.Drawing.Size(18, 13);\n            this.iqLbl.TabIndex = 22;\n            this.iqLbl.Text = \"IQ\";\n            // \n            // techLevelLbl\n            // \n            this.techLevelLbl.AutoSize = true;\n            this.techLevelLbl.Location = new System.Drawing.Point(3, 157);\n            this.techLevelLbl.Name = \"techLevelLbl\";\n            this.techLevelLbl.Size = new System.Drawing.Size(61, 13);\n            this.techLevelLbl.TabIndex = 21;\n            this.techLevelLbl.Text = \"Tech Level\";\n            // \n            // maxVesselsLbl\n            // \n            this.maxVesselsLbl.AutoSize = true;\n            this.maxVesselsLbl.Location = new System.Drawing.Point(3, 131);\n            this.maxVesselsLbl.Name = \"maxVesselsLbl\";\n            this.maxVesselsLbl.Size = new System.Drawing.Size(66, 13);\n            this.maxVesselsLbl.TabIndex = 20;\n            this.maxVesselsLbl.Text = \"Max Vessels\";\n            // \n            // maxInfantryLbl\n            // \n            this.maxInfantryLbl.AutoSize = true;\n            this.maxInfantryLbl.Location = new System.Drawing.Point(3, 105);\n            this.maxInfantryLbl.Name = \"maxInfantryLbl\";\n            this.maxInfantryLbl.Size = new System.Drawing.Size(65, 13);\n            this.maxInfantryLbl.TabIndex = 19;\n            this.maxInfantryLbl.Text = \"Max Infantry\";\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Location = new System.Drawing.Point(3, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(32, 13);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"Edge\";\n            // \n            // edgeComboBox\n            // \n            this.edgeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.edgeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.edgeComboBox.FormattingEnabled = true;\n            this.edgeComboBox.Location = new System.Drawing.Point(81, 3);\n            this.edgeComboBox.Name = \"edgeComboBox\";\n            this.edgeComboBox.Size = new System.Drawing.Size(245, 21);\n            this.edgeComboBox.TabIndex = 10;\n            // \n            // label2\n            // \n            this.label2.AutoSize = true;\n            this.label2.Location = new System.Drawing.Point(3, 27);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(39, 13);\n            this.label2.TabIndex = 11;\n            this.label2.Text = \"Credits\";\n            // \n            // creditsNud\n            // \n            this.creditsNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.creditsNud.Location = new System.Drawing.Point(81, 30);\n            this.creditsNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.creditsNud.Name = \"creditsNud\";\n            this.creditsNud.Size = new System.Drawing.Size(245, 20);\n            this.creditsNud.TabIndex = 12;\n            // \n            // label3\n            // \n            this.label3.AutoSize = true;\n            this.label3.Location = new System.Drawing.Point(3, 53);\n            this.label3.Name = \"label3\";\n            this.label3.Size = new System.Drawing.Size(72, 13);\n            this.label3.TabIndex = 13;\n            this.label3.Text = \"Max Buildings\";\n            // \n            // label4\n            // \n            this.label4.AutoSize = true;\n            this.label4.Location = new System.Drawing.Point(3, 79);\n            this.label4.Name = \"label4\";\n            this.label4.Size = new System.Drawing.Size(54, 13);\n            this.label4.TabIndex = 14;\n            this.label4.Text = \"Max Units\";\n            // \n            // maxBuildingsNud\n            // \n            this.maxBuildingsNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.maxBuildingsNud.Location = new System.Drawing.Point(81, 56);\n            this.maxBuildingsNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.maxBuildingsNud.Name = \"maxBuildingsNud\";\n            this.maxBuildingsNud.Size = new System.Drawing.Size(245, 20);\n            this.maxBuildingsNud.TabIndex = 15;\n            // \n            // maxUnitsNud\n            // \n            this.maxUnitsNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.maxUnitsNud.Location = new System.Drawing.Point(81, 82);\n            this.maxUnitsNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.maxUnitsNud.Name = \"maxUnitsNud\";\n            this.maxUnitsNud.Size = new System.Drawing.Size(245, 20);\n            this.maxUnitsNud.TabIndex = 16;\n            // \n            // label5\n            // \n            this.label5.AutoSize = true;\n            this.label5.Location = new System.Drawing.Point(3, 229);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(31, 13);\n            this.label5.TabIndex = 17;\n            this.label5.Text = \"Allies\";\n            // \n            // playersListBox\n            // \n            this.playersListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Left)));\n            this.playersListBox.FormattingEnabled = true;\n            this.playersListBox.Location = new System.Drawing.Point(81, 232);\n            this.playersListBox.Name = \"playersListBox\";\n            this.playersListBox.SelectionMode = System.Windows.Forms.SelectionMode.MultiSimple;\n            this.playersListBox.Size = new System.Drawing.Size(100, 134);\n            this.playersListBox.TabIndex = 18;\n            // \n            // playerControlLbl\n            // \n            this.playerControlLbl.AutoSize = true;\n            this.playerControlLbl.Location = new System.Drawing.Point(3, 209);\n            this.playerControlLbl.Name = \"playerControlLbl\";\n            this.playerControlLbl.Size = new System.Drawing.Size(72, 13);\n            this.playerControlLbl.TabIndex = 27;\n            this.playerControlLbl.Text = \"Player Control\";\n            // \n            // playerControlCheckBox\n            // \n            this.playerControlCheckBox.AutoSize = true;\n            this.playerControlCheckBox.Location = new System.Drawing.Point(81, 212);\n            this.playerControlCheckBox.Name = \"playerControlCheckBox\";\n            this.playerControlCheckBox.Size = new System.Drawing.Size(15, 14);\n            this.playerControlCheckBox.TabIndex = 28;\n            this.playerControlCheckBox.UseVisualStyleBackColor = true;\n            // \n            // PlayerSettings\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Name = \"PlayerSettings\";\n            this.Size = new System.Drawing.Size(329, 372);\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.iqNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.techLevelNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxVesselsNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxInfantryNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.creditsNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxBuildingsNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxUnitsNud)).EndInit();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.ComboBox edgeComboBox;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.NumericUpDown creditsNud;\n        private System.Windows.Forms.Label label3;\n        private System.Windows.Forms.Label label4;\n        private System.Windows.Forms.NumericUpDown maxBuildingsNud;\n        private System.Windows.Forms.NumericUpDown maxUnitsNud;\n        private System.Windows.Forms.Label label5;\n        private System.Windows.Forms.ListBox playersListBox;\n        private System.Windows.Forms.Label techLevelLbl;\n        private System.Windows.Forms.Label maxVesselsLbl;\n        private System.Windows.Forms.Label maxInfantryLbl;\n        private System.Windows.Forms.Label iqLbl;\n        private System.Windows.Forms.NumericUpDown maxVesselsNud;\n        private System.Windows.Forms.NumericUpDown maxInfantryNud;\n        private System.Windows.Forms.NumericUpDown iqNud;\n        private System.Windows.Forms.NumericUpDown techLevelNud;\n        private System.Windows.Forms.Label playerControlLbl;\n        private System.Windows.Forms.CheckBox playerControlCheckBox;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/PlayerSettings.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class PlayerSettings : UserControl\n    {\n        private readonly PropertyTracker<House> houseSettingsTracker;\n        private readonly dynamic house;\n\n        public PlayerSettings(IGamePlugin plugin, PropertyTracker<House> houseSettingsTracker)\n        {\n            this.houseSettingsTracker = houseSettingsTracker;\n            house = houseSettingsTracker;\n\n            InitializeComponent();\n\n            edgeComboBox.Items.Clear();\n            edgeComboBox.Items.AddRange(new string[] { \"North\", \"South\", \"West\", \"East\" });\n\n            creditsNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"Credits\");\n            maxBuildingsNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"MaxBuilding\");\n            maxUnitsNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"MaxUnit\");\n            edgeComboBox.DataBindings.Add(\"SelectedItem\", houseSettingsTracker, \"Edge\");\n\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    maxInfantryNud.Visible = maxInfantryLbl.Visible = false;\n                    maxVesselsNud.Visible = maxVesselsLbl.Visible = false;\n                    techLevelNud.Visible = techLevelLbl.Visible = false;\n                    iqNud.Visible = iqLbl.Visible = false;\n                    playerControlCheckBox.Visible = playerControlLbl.Visible = false;\n                    break;\n                case GameType.RedAlert:\n                    maxInfantryNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"MaxInfantry\");\n                    maxVesselsNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"MaxVessel\");\n                    techLevelNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"TechLevel\");\n                    iqNud.DataBindings.Add(\"Value\", houseSettingsTracker, \"IQ\");\n                    playerControlCheckBox.DataBindings.Add(\"Checked\", houseSettingsTracker, \"PlayerControl\");\n                    break;\n            }\n\n            playersListBox.Items.Clear();\n            playersListBox.Items.AddRange(plugin.Map.Houses.Select(h => h.Type.Name).ToArray());\n\n            var selectedIndices = new List<int>();\n            foreach (var id in house.Allies)\n            {\n                playersListBox.SetSelected(id, true);\n            }\n\n            playersListBox.SelectedIndexChanged += playersListBox_SelectedIndexChanged;\n        }\n\n        private void playersListBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            var allies = 0;\n            foreach (int selectedIndex in playersListBox.SelectedIndices)\n            {\n                allies |= 1 << selectedIndex;\n            }\n            house.Allies = new AlliesMask(allies);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/PlayerSettings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/PropertiesComboBox.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class PropertiesComboBox\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            components = new System.ComponentModel.Container();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/PropertiesComboBox.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class PropertiesComboBox : ComboBox\n    {\n        private bool savedAutoClose;\n\n        private ToolStripDropDown DropDownHost\n        {\n            get\n            {\n                var parent = Parent;\n                while ((parent != null) && !(parent is ToolStripDropDown))\n                {\n                    parent = parent.Parent;\n                }\n                return parent as ToolStripDropDown;\n            }\n        }\n\n        public PropertiesComboBox()\n        {\n            InitializeComponent();\n        }\n\n        protected override void OnDropDownClosed(EventArgs e)\n        {\n            var dropDownHost = DropDownHost;\n            if (dropDownHost != null)\n            {\n                dropDownHost.AutoClose = savedAutoClose;\n            }\n\n            base.OnDropDownClosed(e);\n        }\n\n        protected override void OnDropDown(EventArgs e)\n        {\n            var dropDownHost = DropDownHost;\n            if (dropDownHost != null)\n            {\n                savedAutoClose = dropDownHost.AutoClose;\n                dropDownHost.AutoClose = false;\n            }\n\n            base.OnDropDown(e);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/TerrainProperties.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class TerrainProperties\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.label5 = new System.Windows.Forms.Label();\n            this.triggerComboBox = new MobiusEditor.Controls.PropertiesComboBox();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 31.25F));\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 68.75F));\n            this.tableLayoutPanel1.Controls.Add(this.label5, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.triggerComboBox, 1, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 1;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(336, 38);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // label5\n            // \n            this.label5.AutoSize = true;\n            this.label5.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label5.Location = new System.Drawing.Point(4, 0);\n            this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(97, 38);\n            this.label5.TabIndex = 4;\n            this.label5.Text = \"Trigger\";\n            this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // triggerComboBox\n            // \n            this.triggerComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.triggerComboBox.FormattingEnabled = true;\n            this.triggerComboBox.Location = new System.Drawing.Point(109, 5);\n            this.triggerComboBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.triggerComboBox.Name = \"triggerComboBox\";\n            this.triggerComboBox.Size = new System.Drawing.Size(223, 28);\n            this.triggerComboBox.TabIndex = 9;\n            this.triggerComboBox.SelectedIndexChanged += new System.EventHandler(this.comboBox_SelectedValueChanged);\n            // \n            // TriggerProperties\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.Name = \"TriggerProperties\";\n            this.Size = new System.Drawing.Size(336, 38);\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.Label label5;\n        private MobiusEditor.Controls.PropertiesComboBox triggerComboBox;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/TerrainProperties.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class TerrainProperties : UserControl\n    {\n        private bool isMockObject;\n\n        public IGamePlugin Plugin { get; private set; }\n\n        private Terrain terrain;\n        public Terrain Terrain\n        {\n            get => terrain;\n            set\n            {\n                if (terrain != value)\n                {\n                    terrain = value;\n                    Rebind();\n                }\n            }\n        }\n\n        public TerrainProperties()\n        {\n            InitializeComponent();\n        }\n\n        public void Initialize(IGamePlugin plugin, bool isMockObject)\n        {\n            this.isMockObject = isMockObject;\n\n            Plugin = plugin;\n            plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;\n\n            UpdateDataSource();\n\n            Disposed += (sender, e) =>\n            {\n                Terrain = null;\n                plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;\n            };\n        }\n\n        private void Triggers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)\n        {\n            UpdateDataSource();\n        }\n\n        private void UpdateDataSource()\n        {\n            triggerComboBox.DataSource = Trigger.None.Yield().Concat(Plugin.Map.Triggers.Select(t => t.Name).Distinct()).ToArray();\n        }\n\n        private void Rebind()\n        {\n            triggerComboBox.DataBindings.Clear();\n\n            if (terrain == null)\n            {\n                return;\n            }\n\n            triggerComboBox.DataBindings.Add(\"SelectedItem\", terrain, \"Trigger\");\n        }\n\n        private void Obj_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"Type\":\n                    {\n                        Rebind();\n                    }\n                    break;\n            }\n\n            if (!isMockObject)\n            {\n                Plugin.Dirty = true;\n            }\n        }\n\n        private void comboBox_SelectedValueChanged(object sender, EventArgs e)\n        {\n            foreach (Binding binding in (sender as ComboBox).DataBindings)\n            {\n                binding.WriteValue();\n            }\n        }\n\n        private void nud_ValueChanged(object sender, EventArgs e)\n        {\n            foreach (Binding binding in (sender as NumericUpDown).DataBindings)\n            {\n                binding.WriteValue();\n            }\n        }\n    }\n\n    public class TerrainPropertiesPopup : ToolStripDropDown\n    {\n        private readonly ToolStripControlHost host;\n\n        public TerrainProperties TerrainProperties { get; private set; }\n\n        public TerrainPropertiesPopup(IGamePlugin plugin, Terrain terrain)\n        {\n            TerrainProperties = new TerrainProperties();\n            TerrainProperties.Initialize(plugin, false);\n            TerrainProperties.Terrain = terrain;\n\n            host = new ToolStripControlHost(TerrainProperties);\n            Padding = Margin = host.Padding = host.Margin = Padding.Empty;\n            MinimumSize = TerrainProperties.MinimumSize;\n            TerrainProperties.MinimumSize = TerrainProperties.Size;\n            MaximumSize = TerrainProperties.MaximumSize;\n            TerrainProperties.MaximumSize = TerrainProperties.Size;\n            Size = TerrainProperties.Size;\n            Items.Add(host);\n            TerrainProperties.Disposed += (sender, e) =>\n            {\n                TerrainProperties = null;\n                Dispose(true);\n            };\n        }\n\n        protected override void OnClosed(ToolStripDropDownClosedEventArgs e)\n        {\n            base.OnClosed(e);\n\n            TerrainProperties.Terrain = null;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/TerrainProperties.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/TypeComboBox.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Controls\n{\n    partial class TypeComboBox\n    {\n        /// <summary> \n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary> \n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Component Designer generated code\n\n        /// <summary> \n        /// Required method for Designer support - do not modify \n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            components = new System.ComponentModel.Container();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Controls/TypeComboBox.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Controls\n{\n    public partial class TypeComboBox : ComboBox\n    {\n        [Category(\"Behavior\")]\n        public Image MissingThumbnail { get; set; } = SystemIcons.Error.ToBitmap();\n\n        public IEnumerable<IBrowsableType> Types\n        {\n            get => Items.Cast<TypeItem<IBrowsableType>>().Select(t => t.Type);\n            set\n            {\n                DataSource = value.Select(t => new TypeItem<IBrowsableType>(t.DisplayName, t)).ToArray();\n                DropDownHeight = Math.Max(DropDownHeight, value.Max(t => (t.Thumbnail?.Height ?? MissingThumbnail.Height) * 3));\n                Invalidate();\n            }\n        }\n\n        public IBrowsableType SelectedType => SelectedValue as IBrowsableType;\n\n        public TypeComboBox()\n        {\n            InitializeComponent();\n\n            DisplayMember = \"Name\";\n            ValueMember = \"Type\";\n        }\n\n        protected override void OnMeasureItem(MeasureItemEventArgs e)\n        {\n            base.OnMeasureItem(e);\n\n            var typeItem = Items[e.Index] as TypeItem<IBrowsableType>;\n            if (typeItem?.Type != null)\n            {\n                e.ItemHeight = typeItem.Type.Thumbnail?.Height ?? MissingThumbnail.Height;\n            }\n        }\n\n        protected override void OnDrawItem(DrawItemEventArgs e)\n        {\n            base.OnDrawItem(e);\n\n            e.DrawBackground();\n\n            if ((e.Index >= 0) && (e.Index < Items.Count))\n            {\n                var typeItem = Items[e.Index] as TypeItem<IBrowsableType>;\n                if (typeItem?.Type != null)\n                {\n                    StringFormat stringFormat = new StringFormat\n                    {\n                        LineAlignment = StringAlignment.Center\n                    };\n\n                    var textColor = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? SystemBrushes.HighlightText : SystemBrushes.WindowText;\n                    var textSize = e.Graphics.MeasureString(typeItem.Name, Font, e.Bounds.Width, stringFormat);\n                    e.Graphics.DrawString(typeItem.Name, Font, textColor, e.Bounds, stringFormat);\n\n                    if ((e.State & DrawItemState.ComboBoxEdit) == DrawItemState.None)\n                    {\n                        var thumbnail = typeItem.Type.Thumbnail ?? MissingThumbnail;\n                        var thumbnailWidth = (int)Math.Min(e.Bounds.Width - textSize.Width, thumbnail.Width);\n                        var thumbnailSize = new Size(thumbnailWidth, thumbnailWidth * thumbnail.Height / thumbnail.Width);\n                        var thumbnailBounds = new Rectangle(new Point(e.Bounds.Right - thumbnailSize.Width, e.Bounds.Top), thumbnailSize);\n                        e.Graphics.DrawImage(thumbnail, thumbnailBounds);\n                    }\n                }\n            }\n\n            e.DrawFocusRectangle();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/ErrorMessageBox.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class ErrorMessageBox\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.lblMessage = new System.Windows.Forms.Label();\n            this.txtErrors = new System.Windows.Forms.TextBox();\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.btnCopy = new System.Windows.Forms.Button();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.lblMessage, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.txtErrors, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 2);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 3;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(447, 285);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // lblMessage\n            // \n            this.lblMessage.AutoSize = true;\n            this.lblMessage.Location = new System.Drawing.Point(3, 0);\n            this.lblMessage.Name = \"lblMessage\";\n            this.lblMessage.Size = new System.Drawing.Size(191, 13);\n            this.lblMessage.TabIndex = 1;\n            this.lblMessage.Text = \"The following errors were encountered:\";\n            // \n            // txtErrors\n            // \n            this.txtErrors.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.txtErrors.Location = new System.Drawing.Point(3, 16);\n            this.txtErrors.Multiline = true;\n            this.txtErrors.Name = \"txtErrors\";\n            this.txtErrors.ReadOnly = true;\n            this.txtErrors.ScrollBars = System.Windows.Forms.ScrollBars.Both;\n            this.txtErrors.Size = new System.Drawing.Size(441, 231);\n            this.txtErrors.TabIndex = 0;\n            this.txtErrors.WordWrap = false;\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.AutoSize = true;\n            this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Controls.Add(this.btnCopy);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 253);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(441, 29);\n            this.flowLayoutPanel1.TabIndex = 1;\n            // \n            // btnOK\n            // \n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnOK.Location = new System.Drawing.Point(363, 3);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(75, 23);\n            this.btnOK.TabIndex = 0;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // btnCopy\n            // \n            this.btnCopy.Location = new System.Drawing.Point(246, 3);\n            this.btnCopy.Name = \"btnCopy\";\n            this.btnCopy.Size = new System.Drawing.Size(111, 23);\n            this.btnCopy.TabIndex = 1;\n            this.btnCopy.Text = \"&Copy to Clipboard\";\n            this.btnCopy.UseVisualStyleBackColor = true;\n            this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click);\n            // \n            // ErrorMessageBox\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnOK;\n            this.ClientSize = new System.Drawing.Size(447, 285);\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"ErrorMessageBox\";\n            this.ShowInTaskbar = false;\n            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;\n            this.Text = \"Error Report\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.TextBox txtErrors;\n        private System.Windows.Forms.Label lblMessage;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.Button btnCopy;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/ErrorMessageBox.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class ErrorMessageBox : Form\n    {\n        public string Message\n        {\n            set\n            {\n                lblMessage.Text = value;\n            }\n        }\n\n        public IEnumerable<string> Errors\n        {\n            set\n            {\n                txtErrors.Text = string.Join(Environment.NewLine, value);\n            }\n        }\n\n        public ErrorMessageBox()\n        {\n            InitializeComponent();\n        }\n\n        private void btnCopy_Click(object sender, EventArgs e)\n        {\n            Clipboard.SetText(txtErrors.Text);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/ErrorMessageBox.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/InviteMessageBox.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class InviteMessageBox\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.checkBoxDontShowThisAgain = new System.Windows.Forms.CheckBox();\n            this.pictureBoxIcon = new System.Windows.Forms.PictureBox();\n            this.label1 = new System.Windows.Forms.Label();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel2.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxIcon)).BeginInit();\n            this.SuspendLayout();\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.Controls.Add(this.flowLayoutPanel2);\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Controls.Add(this.checkBoxDontShowThisAgain);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(425, 97);\n            this.flowLayoutPanel1.TabIndex = 0;\n            // \n            // flowLayoutPanel2\n            // \n            this.flowLayoutPanel2.AutoSize = true;\n            this.flowLayoutPanel2.Controls.Add(this.pictureBoxIcon);\n            this.flowLayoutPanel2.Controls.Add(this.label1);\n            this.flowLayoutPanel2.Location = new System.Drawing.Point(3, 3);\n            this.flowLayoutPanel2.Name = \"flowLayoutPanel2\";\n            this.flowLayoutPanel2.Size = new System.Drawing.Size(419, 38);\n            this.flowLayoutPanel2.TabIndex = 0;\n            // \n            // btnOK\n            // \n            this.btnOK.Anchor = System.Windows.Forms.AnchorStyles.None;\n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;\n            this.btnOK.Location = new System.Drawing.Point(175, 47);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(75, 23);\n            this.btnOK.TabIndex = 1;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // checkBoxDontShowThisAgain\n            // \n            this.checkBoxDontShowThisAgain.AutoSize = true;\n            this.flowLayoutPanel1.SetFlowBreak(this.checkBoxDontShowThisAgain, true);\n            this.checkBoxDontShowThisAgain.Location = new System.Drawing.Point(3, 76);\n            this.checkBoxDontShowThisAgain.Name = \"checkBoxDontShowThisAgain\";\n            this.checkBoxDontShowThisAgain.Size = new System.Drawing.Size(127, 17);\n            this.checkBoxDontShowThisAgain.TabIndex = 2;\n            this.checkBoxDontShowThisAgain.Text = \"Don\\'t show this again\";\n            this.checkBoxDontShowThisAgain.UseVisualStyleBackColor = true;\n            // \n            // pictureBoxIcon\n            // \n            this.pictureBoxIcon.Location = new System.Drawing.Point(3, 3);\n            this.pictureBoxIcon.Name = \"pictureBoxIcon\";\n            this.pictureBoxIcon.Size = new System.Drawing.Size(32, 32);\n            this.pictureBoxIcon.TabIndex = 0;\n            this.pictureBoxIcon.TabStop = false;\n            // \n            // label1\n            // \n            this.label1.Anchor = System.Windows.Forms.AnchorStyles.None;\n            this.label1.AutoSize = true;\n            this.label1.Location = new System.Drawing.Point(41, 12);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(375, 13);\n            this.label1.TabIndex = 1;\n            this.label1.Text = \"To join a game session or accept game invites, please first exit the Map Editor.\";\n            // \n            // CheckMessageBox\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnOK;\n            this.ClientSize = new System.Drawing.Size(425, 97);\n            this.Controls.Add(this.flowLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"CheckMessageBox\";\n            this.ShowInTaskbar = false;\n            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;\n            this.Text = \"Map Editor\";\n            this.Load += new System.EventHandler(this.InviteMessageBox_Load);\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.flowLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel2.ResumeLayout(false);\n            this.flowLayoutPanel2.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxIcon)).EndInit();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.CheckBox checkBoxDontShowThisAgain;\n        private System.Windows.Forms.PictureBox pictureBoxIcon;\n        private System.Windows.Forms.Label label1;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/InviteMessageBox.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Drawing;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class InviteMessageBox : Form\n    {\n        public bool DontShowAgain => checkBoxDontShowThisAgain.Checked;\n\n        public InviteMessageBox()\n        {\n            InitializeComponent();\n        }\n\n        private void InviteMessageBox_Load(object sender, EventArgs e)\n        {\n            using (var infoIcon = new Icon(SystemIcons.Information, pictureBoxIcon.Width, pictureBoxIcon.Height))\n            {\n                pictureBoxIcon.Image = infoIcon.ToBitmap();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/InviteMessageBox.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/MapSettingsDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class MapSettingsDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnCancel = new System.Windows.Forms.Button();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.settingsTreeView = new System.Windows.Forms.TreeView();\n            this.settingsPanel = new System.Windows.Forms.Panel();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F));\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 80F));\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.settingsTreeView, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.settingsPanel, 1, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 2;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(784, 561);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.AutoSize = true;\n            this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 2);\n            this.flowLayoutPanel1.Controls.Add(this.btnCancel);\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 524);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(778, 34);\n            this.flowLayoutPanel1.TabIndex = 1;\n            // \n            // btnCancel\n            // \n            this.btnCancel.AutoSize = true;\n            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnCancel.Location = new System.Drawing.Point(708, 2);\n            this.btnCancel.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnCancel.Name = \"btnCancel\";\n            this.btnCancel.Size = new System.Drawing.Size(68, 30);\n            this.btnCancel.TabIndex = 2;\n            this.btnCancel.Text = \"&Cancel\";\n            this.btnCancel.UseVisualStyleBackColor = true;\n            // \n            // btnOK\n            // \n            this.btnOK.AutoSize = true;\n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;\n            this.btnOK.Location = new System.Drawing.Point(654, 2);\n            this.btnOK.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(50, 30);\n            this.btnOK.TabIndex = 3;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // settingsTreeView\n            // \n            this.settingsTreeView.CheckBoxes = true;\n            this.settingsTreeView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.settingsTreeView.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;\n            this.settingsTreeView.HideSelection = false;\n            this.settingsTreeView.Location = new System.Drawing.Point(3, 3);\n            this.settingsTreeView.Name = \"settingsTreeView\";\n            this.settingsTreeView.Size = new System.Drawing.Size(150, 515);\n            this.settingsTreeView.TabIndex = 2;\n            this.settingsTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.settingsTreeView_AfterCheck);\n            this.settingsTreeView.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.settingsTreeView_DrawNode);\n            this.settingsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.settingsTreeView_AfterSelect);\n            // \n            // settingsPanel\n            // \n            this.settingsPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.settingsPanel.Location = new System.Drawing.Point(166, 10);\n            this.settingsPanel.Margin = new System.Windows.Forms.Padding(10, 10, 10, 10);\n            this.settingsPanel.Name = \"settingsPanel\";\n            this.settingsPanel.Size = new System.Drawing.Size(608, 501);\n            this.settingsPanel.TabIndex = 3;\n            // \n            // MapSettingsDialog\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnCancel;\n            this.ClientSize = new System.Drawing.Size(784, 561);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"MapSettingsDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n            this.Text = \"Map Settings\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.flowLayoutPanel1.PerformLayout();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.Button btnCancel;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.TreeView settingsTreeView;\n        private System.Windows.Forms.Panel settingsPanel;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/MapSettingsDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class MapSettingsDialog : Form\n    {\n        private const int TVIF_STATE = 0x8;\n        private const int TVIS_STATEIMAGEMASK = 0xF000;\n        private const int TV_FIRST = 0x1100;\n        private const int TVM_SETITEM = TV_FIRST + 63;\n\n        [DllImport(\"user32.dll\")]\n        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);\n\n        private struct TVITEM\n        {\n            public int mask;\n            public IntPtr hItem;\n            public int state;\n            public int stateMask;\n            [MarshalAs(UnmanagedType.LPTStr)]\n            public String lpszText;\n            public int cchTextMax;\n            public int iImage;\n            public int iSelectedImage;\n            public int cChildren;\n            public IntPtr lParam;\n        }\n\n        private readonly IGamePlugin plugin;\n        private readonly PropertyTracker<BasicSection> basicSettingsTracker;\n        private readonly PropertyTracker<BriefingSection> briefingSettingsTracker;\n        private readonly IDictionary<House, PropertyTracker<House>> houseSettingsTrackers;\n        private readonly TreeNode playersNode;\n\n        public MapSettingsDialog(IGamePlugin plugin, PropertyTracker<BasicSection> basicSettingsTracker, PropertyTracker<BriefingSection> briefingSettingsTracker,\n            IDictionary<House, PropertyTracker<House>> houseSettingsTrackers)\n        {\n            InitializeComponent();\n\n            this.plugin = plugin;\n            this.basicSettingsTracker = basicSettingsTracker;\n            this.briefingSettingsTracker = briefingSettingsTracker;\n            this.houseSettingsTrackers = houseSettingsTrackers;\n\n            settingsTreeView.BeginUpdate();\n            settingsTreeView.Nodes.Clear();\n            settingsTreeView.Nodes.Add(\"BASIC\", \"Basic\");\n            settingsTreeView.Nodes.Add(\"BRIEFING\", \"Briefing\");\n\n            playersNode = settingsTreeView.Nodes.Add(\"Players\");\n            foreach (var player in plugin.Map.Houses)\n            {\n                var playerNode = playersNode.Nodes.Add(player.Type.Name, player.Type.Name);\n                playerNode.Checked = player.Enabled;\n            }\n            playersNode.Expand();\n\n            settingsTreeView.EndUpdate();\n            settingsTreeView.SelectedNode = settingsTreeView.Nodes[0];\n        }\n\n        private void settingsTreeView_AfterSelect(object sender, TreeViewEventArgs e)\n        {\n            settingsPanel.Controls.Clear();\n\n            switch (settingsTreeView.SelectedNode.Name)\n            {\n                case \"BASIC\":\n                    {\n                        settingsPanel.Controls.Add(new BasicSettings(plugin, basicSettingsTracker));\n                    }\n                    break;\n                case \"BRIEFING\":\n                    {\n                        settingsPanel.Controls.Add(new BriefingSettings(plugin, briefingSettingsTracker));\n                    }\n                    break;\n                default:\n                    {\n                        var player = plugin.Map.Houses.Where(h => h.Type.Name == settingsTreeView.SelectedNode.Name).FirstOrDefault();\n                        if (player != null)\n                        {\n                            settingsPanel.Controls.Add(new PlayerSettings(plugin, houseSettingsTrackers[player]));\n                        }\n                    }\n                    break;\n            }\n        }\n\n        private void settingsTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)\n        {\n            if (!playersNode.Nodes.Contains(e.Node))\n            {\n                HideCheckBox(e.Node);\n                e.DrawDefault = true;\n            }\n            else\n            {\n                e.Graphics.DrawString(e.Node.Text, e.Node.TreeView.Font, new SolidBrush(settingsTreeView.ForeColor), e.Node.Bounds.X, e.Node.Bounds.Y);\n            }\n        }\n\n        private void HideCheckBox(TreeNode node)\n        {\n            TVITEM tvi = new TVITEM\n            {\n                hItem = node.Handle,\n                mask = TVIF_STATE,\n                stateMask = TVIS_STATEIMAGEMASK,\n                state = 0,\n                lpszText = null,\n                cchTextMax = 0,\n                iImage = 0,\n                iSelectedImage = 0,\n                cChildren = 0,\n                lParam = IntPtr.Zero\n            };\n            IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(tvi));\n            Marshal.StructureToPtr(tvi, lparam, false);\n            SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, lparam);\n        }\n\n        private void settingsTreeView_AfterCheck(object sender, TreeViewEventArgs e)\n        {\n            var player = plugin.Map.Houses.Where(h => h.Type.Name == e.Node.Name).FirstOrDefault();\n            if (player != null)\n            {\n                ((dynamic)houseSettingsTrackers[player]).Enabled = e.Node.Checked;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/MapSettingsDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/NewMapDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class NewMapDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnCancel = new System.Windows.Forms.Button();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();\n            this.groupBox1 = new System.Windows.Forms.GroupBox();\n            this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel();\n            this.radioTD = new System.Windows.Forms.RadioButton();\n            this.radioRA = new System.Windows.Forms.RadioButton();\n            this.groupBox2 = new System.Windows.Forms.GroupBox();\n            this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();\n            this.radioTheater1 = new System.Windows.Forms.RadioButton();\n            this.radioTheater2 = new System.Windows.Forms.RadioButton();\n            this.radioTheater3 = new System.Windows.Forms.RadioButton();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel2.SuspendLayout();\n            this.groupBox1.SuspendLayout();\n            this.flowLayoutPanel3.SuspendLayout();\n            this.groupBox2.SuspendLayout();\n            this.flowLayoutPanel4.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 0, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 2;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 13F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(356, 324);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.AutoSize = true;\n            this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.flowLayoutPanel1.Controls.Add(this.btnCancel);\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(2, 295);\n            this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(352, 27);\n            this.flowLayoutPanel1.TabIndex = 0;\n            // \n            // btnCancel\n            // \n            this.btnCancel.AutoSize = true;\n            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnCancel.Location = new System.Drawing.Point(300, 2);\n            this.btnCancel.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnCancel.Name = \"btnCancel\";\n            this.btnCancel.Size = new System.Drawing.Size(50, 23);\n            this.btnCancel.TabIndex = 1;\n            this.btnCancel.Text = \"&Cancel\";\n            this.btnCancel.UseVisualStyleBackColor = true;\n            // \n            // btnOK\n            // \n            this.btnOK.AutoSize = true;\n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;\n            this.btnOK.Location = new System.Drawing.Point(246, 2);\n            this.btnOK.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(50, 23);\n            this.btnOK.TabIndex = 0;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // flowLayoutPanel2\n            // \n            this.flowLayoutPanel2.Controls.Add(this.groupBox1);\n            this.flowLayoutPanel2.Controls.Add(this.groupBox2);\n            this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;\n            this.flowLayoutPanel2.Location = new System.Drawing.Point(2, 2);\n            this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.flowLayoutPanel2.Name = \"flowLayoutPanel2\";\n            this.flowLayoutPanel2.Size = new System.Drawing.Size(352, 289);\n            this.flowLayoutPanel2.TabIndex = 1;\n            // \n            // groupBox1\n            // \n            this.groupBox1.Controls.Add(this.flowLayoutPanel3);\n            this.groupBox1.Location = new System.Drawing.Point(2, 2);\n            this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.groupBox1.Name = \"groupBox1\";\n            this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.groupBox1.Size = new System.Drawing.Size(339, 70);\n            this.groupBox1.TabIndex = 2;\n            this.groupBox1.TabStop = false;\n            this.groupBox1.Text = \"Game Type\";\n            // \n            // flowLayoutPanel3\n            // \n            this.flowLayoutPanel3.AutoSize = true;\n            this.flowLayoutPanel3.Controls.Add(this.radioTD);\n            this.flowLayoutPanel3.Controls.Add(this.radioRA);\n            this.flowLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;\n            this.flowLayoutPanel3.Location = new System.Drawing.Point(2, 15);\n            this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.flowLayoutPanel3.Name = \"flowLayoutPanel3\";\n            this.flowLayoutPanel3.Size = new System.Drawing.Size(335, 53);\n            this.flowLayoutPanel3.TabIndex = 0;\n            // \n            // radioTD\n            // \n            this.radioTD.AutoSize = true;\n            this.radioTD.Checked = true;\n            this.radioTD.Location = new System.Drawing.Point(2, 2);\n            this.radioTD.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.radioTD.Name = \"radioTD\";\n            this.radioTD.Size = new System.Drawing.Size(94, 17);\n            this.radioTD.TabIndex = 0;\n            this.radioTD.TabStop = true;\n            this.radioTD.Text = \"Tiberian Dawn\";\n            this.radioTD.UseVisualStyleBackColor = true;\n            this.radioTD.CheckedChanged += new System.EventHandler(this.radioGameType_CheckedChanged);\n            // \n            // radioRA\n            // \n            this.radioRA.AutoSize = true;\n            this.radioRA.Location = new System.Drawing.Point(2, 23);\n            this.radioRA.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.radioRA.Name = \"radioRA\";\n            this.radioRA.Size = new System.Drawing.Size(69, 17);\n            this.radioRA.TabIndex = 1;\n            this.radioRA.Text = \"Red Alert\";\n            this.radioRA.UseVisualStyleBackColor = true;\n            this.radioRA.CheckedChanged += new System.EventHandler(this.radioGameType_CheckedChanged);\n            // \n            // groupBox2\n            // \n            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));\n            this.groupBox2.Controls.Add(this.flowLayoutPanel4);\n            this.groupBox2.Location = new System.Drawing.Point(2, 76);\n            this.groupBox2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.groupBox2.Name = \"groupBox2\";\n            this.groupBox2.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.groupBox2.Size = new System.Drawing.Size(339, 89);\n            this.groupBox2.TabIndex = 3;\n            this.groupBox2.TabStop = false;\n            this.groupBox2.Text = \"Theater\";\n            // \n            // flowLayoutPanel4\n            // \n            this.flowLayoutPanel4.AutoSize = true;\n            this.flowLayoutPanel4.Controls.Add(this.radioTheater1);\n            this.flowLayoutPanel4.Controls.Add(this.radioTheater2);\n            this.flowLayoutPanel4.Controls.Add(this.radioTheater3);\n            this.flowLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel4.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;\n            this.flowLayoutPanel4.Location = new System.Drawing.Point(2, 15);\n            this.flowLayoutPanel4.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.flowLayoutPanel4.Name = \"flowLayoutPanel4\";\n            this.flowLayoutPanel4.Size = new System.Drawing.Size(335, 72);\n            this.flowLayoutPanel4.TabIndex = 0;\n            // \n            // radioTheater1\n            // \n            this.radioTheater1.AutoSize = true;\n            this.radioTheater1.Checked = true;\n            this.radioTheater1.Location = new System.Drawing.Point(2, 2);\n            this.radioTheater1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.radioTheater1.Name = \"radioTheater1\";\n            this.radioTheater1.Size = new System.Drawing.Size(56, 17);\n            this.radioTheater1.TabIndex = 0;\n            this.radioTheater1.TabStop = true;\n            this.radioTheater1.Text = \"Desert\";\n            this.radioTheater1.UseVisualStyleBackColor = true;\n            // \n            // radioTheater2\n            // \n            this.radioTheater2.AutoSize = true;\n            this.radioTheater2.Location = new System.Drawing.Point(2, 23);\n            this.radioTheater2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.radioTheater2.Name = \"radioTheater2\";\n            this.radioTheater2.Size = new System.Drawing.Size(76, 17);\n            this.radioTheater2.TabIndex = 1;\n            this.radioTheater2.Text = \"Temperate\";\n            this.radioTheater2.UseVisualStyleBackColor = true;\n            // \n            // radioTheater3\n            // \n            this.radioTheater3.AutoSize = true;\n            this.radioTheater3.Location = new System.Drawing.Point(2, 44);\n            this.radioTheater3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.radioTheater3.Name = \"radioTheater3\";\n            this.radioTheater3.Size = new System.Drawing.Size(56, 17);\n            this.radioTheater3.TabIndex = 2;\n            this.radioTheater3.TabStop = true;\n            this.radioTheater3.Text = \"Winter\";\n            this.radioTheater3.UseVisualStyleBackColor = true;\n            // \n            // NewMapDialog\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnCancel;\n            this.ClientSize = new System.Drawing.Size(356, 324);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;\n            this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"NewMapDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n            this.Text = \"New Map\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.flowLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel2.ResumeLayout(false);\n            this.groupBox1.ResumeLayout(false);\n            this.groupBox1.PerformLayout();\n            this.flowLayoutPanel3.ResumeLayout(false);\n            this.flowLayoutPanel3.PerformLayout();\n            this.groupBox2.ResumeLayout(false);\n            this.groupBox2.PerformLayout();\n            this.flowLayoutPanel4.ResumeLayout(false);\n            this.flowLayoutPanel4.PerformLayout();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.Button btnCancel;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;\n        private System.Windows.Forms.GroupBox groupBox1;\n        private System.Windows.Forms.GroupBox groupBox2;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3;\n        private System.Windows.Forms.RadioButton radioTD;\n        private System.Windows.Forms.RadioButton radioRA;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4;\n        private System.Windows.Forms.RadioButton radioTheater1;\n        private System.Windows.Forms.RadioButton radioTheater2;\n        private System.Windows.Forms.RadioButton radioTheater3;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/NewMapDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class NewMapDialog : Form\n    {\n        private GameType gameType = GameType.TiberianDawn;\n        public GameType GameType\n        {\n            get => gameType;\n            set\n            {\n                if (gameType != value)\n                {\n                    gameType = value;\n                    UpdateGameType();\n                }\n            }\n        }\n\n        public string TheaterName\n        {\n            get\n            {\n                if (radioTheater1.Checked) return radioTheater1.Text;\n                if (radioTheater2.Checked) return radioTheater2.Text;\n                if (radioTheater3.Checked) return radioTheater3.Text;\n                return null;\n            }\n        }\n\n        public NewMapDialog()\n        {\n            InitializeComponent();\n        }\n\n        private void UpdateGameType()\n        {\n            switch(GameType)\n            {\n                case GameType.TiberianDawn:\n                    {\n                        radioTheater1.Text = \"Desert\";\n                        radioTheater2.Text = \"Temperate\";\n                        radioTheater3.Text = \"Winter\";\n                    } break;\n                case GameType.RedAlert:\n                    {\n                        radioTheater1.Text = \"Temperate\";\n                        radioTheater2.Text = \"Snow\";\n                        radioTheater3.Text = \"Interior\";\n                    }\n                    break;\n            }\n        }\n\n        private void radioGameType_CheckedChanged(object sender, EventArgs e)\n        {\n            if (radioTD.Checked)\n            {\n                GameType = GameType.TiberianDawn;\n            }\n            else if (radioRA.Checked)\n            {\n                GameType = GameType.RedAlert;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/NewMapDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/SteamDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class SteamDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SteamDialog));\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.label2 = new System.Windows.Forms.Label();\n            this.label3 = new System.Windows.Forms.Label();\n            this.label4 = new System.Windows.Forms.Label();\n            this.descriptionTxt = new System.Windows.Forms.TextBox();\n            this.titleTxt = new System.Windows.Forms.TextBox();\n            this.visibilityComboBox = new System.Windows.Forms.ComboBox();\n            this.panel1 = new System.Windows.Forms.Panel();\n            this.previewTxt = new System.Windows.Forms.TextBox();\n            this.previewBtn = new System.Windows.Forms.Button();\n            this.panel2 = new System.Windows.Forms.Panel();\n            this.btnClose = new System.Windows.Forms.Button();\n            this.btnGoToSteam = new System.Windows.Forms.Button();\n            this.publicMapContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);\n            this.publishAsNewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.statusLbl = new System.Windows.Forms.Label();\n            this.label5 = new System.Windows.Forms.Label();\n            this.btnPublishMap = new MobiusEditor.Controls.MenuButton();\n            this.imageTooltip = new MobiusEditor.Controls.ImageTooltip();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.tableLayoutPanel2.SuspendLayout();\n            this.panel1.SuspendLayout();\n            this.panel2.SuspendLayout();\n            this.publicMapContextMenuStrip.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.label5, 0, 2);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 3;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(500, 385);\n            this.tableLayoutPanel1.TabIndex = 1;\n            // \n            // tableLayoutPanel2\n            // \n            this.tableLayoutPanel2.ColumnCount = 2;\n            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel2.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel2.Controls.Add(this.label2, 0, 1);\n            this.tableLayoutPanel2.Controls.Add(this.label3, 0, 2);\n            this.tableLayoutPanel2.Controls.Add(this.label4, 0, 3);\n            this.tableLayoutPanel2.Controls.Add(this.descriptionTxt, 0, 4);\n            this.tableLayoutPanel2.Controls.Add(this.titleTxt, 1, 0);\n            this.tableLayoutPanel2.Controls.Add(this.visibilityComboBox, 1, 1);\n            this.tableLayoutPanel2.Controls.Add(this.panel1, 1, 2);\n            this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel2.Location = new System.Drawing.Point(2, 2);\n            this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.tableLayoutPanel2.Name = \"tableLayoutPanel2\";\n            this.tableLayoutPanel2.RowCount = 5;\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 13F));\n            this.tableLayoutPanel2.Size = new System.Drawing.Size(496, 233);\n            this.tableLayoutPanel2.TabIndex = 2;\n            // \n            // label1\n            // \n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(2, 0);\n            this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(69, 24);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"Title\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label2\n            // \n            this.label2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label2.Location = new System.Drawing.Point(2, 24);\n            this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(69, 25);\n            this.label2.TabIndex = 1;\n            this.label2.Text = \"Visibility\";\n            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label3\n            // \n            this.label3.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label3.Location = new System.Drawing.Point(2, 49);\n            this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label3.Name = \"label3\";\n            this.label3.Size = new System.Drawing.Size(69, 27);\n            this.label3.TabIndex = 2;\n            this.label3.Text = \"Preview\";\n            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label4\n            // \n            this.label4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label4.Location = new System.Drawing.Point(2, 76);\n            this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label4.Name = \"label4\";\n            this.label4.Size = new System.Drawing.Size(69, 13);\n            this.label4.TabIndex = 3;\n            this.label4.Text = \"Description\";\n            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // descriptionTxt\n            // \n            this.tableLayoutPanel2.SetColumnSpan(this.descriptionTxt, 2);\n            this.descriptionTxt.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.descriptionTxt.Location = new System.Drawing.Point(2, 91);\n            this.descriptionTxt.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.descriptionTxt.Multiline = true;\n            this.descriptionTxt.Name = \"descriptionTxt\";\n            this.descriptionTxt.Size = new System.Drawing.Size(492, 202);\n            this.descriptionTxt.TabIndex = 4;\n            this.descriptionTxt.TextChanged += new System.EventHandler(this.descriptionTxt_TextChanged);\n            // \n            // titleTxt\n            // \n            this.titleTxt.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.titleTxt.Location = new System.Drawing.Point(75, 2);\n            this.titleTxt.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.titleTxt.Name = \"titleTxt\";\n            this.titleTxt.Size = new System.Drawing.Size(419, 20);\n            this.titleTxt.TabIndex = 5;\n            // \n            // visibilityComboBox\n            // \n            this.visibilityComboBox.DisplayMember = \"Name\";\n            this.visibilityComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.visibilityComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.visibilityComboBox.FormattingEnabled = true;\n            this.visibilityComboBox.Location = new System.Drawing.Point(75, 26);\n            this.visibilityComboBox.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.visibilityComboBox.Name = \"visibilityComboBox\";\n            this.visibilityComboBox.Size = new System.Drawing.Size(419, 21);\n            this.visibilityComboBox.TabIndex = 6;\n            this.visibilityComboBox.ValueMember = \"Value\";\n            // \n            // panel1\n            // \n            this.panel1.Controls.Add(this.previewTxt);\n            this.panel1.Controls.Add(this.previewBtn);\n            this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.panel1.Location = new System.Drawing.Point(75, 51);\n            this.panel1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.panel1.Name = \"panel1\";\n            this.panel1.Size = new System.Drawing.Size(419, 23);\n            this.panel1.TabIndex = 7;\n            // \n            // previewTxt\n            // \n            this.previewTxt.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Left) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.previewTxt.Location = new System.Drawing.Point(2, 2);\n            this.previewTxt.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.previewTxt.Name = \"previewTxt\";\n            this.previewTxt.Size = new System.Drawing.Size(392, 20);\n            this.previewTxt.TabIndex = 2;\n            this.previewTxt.TextChanged += new System.EventHandler(this.previewTxt_TextChanged);\n            // \n            // previewBtn\n            // \n            this.previewBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.previewBtn.AutoSize = true;\n            this.previewBtn.Location = new System.Drawing.Point(392, 2);\n            this.previewBtn.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.previewBtn.Name = \"previewBtn\";\n            this.previewBtn.Size = new System.Drawing.Size(26, 23);\n            this.previewBtn.TabIndex = 3;\n            this.previewBtn.Text = \"...\";\n            this.previewBtn.UseVisualStyleBackColor = true;\n            this.previewBtn.Click += new System.EventHandler(this.previewBtn_Click);\n            // \n            // panel2\n            // \n            this.panel2.Controls.Add(this.btnClose);\n            this.panel2.Controls.Add(this.btnGoToSteam);\n            this.panel2.Controls.Add(this.btnPublishMap);\n            this.panel2.Controls.Add(this.statusLbl);\n            this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.panel2.Location = new System.Drawing.Point(2, 239);\n            this.panel2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.panel2.Name = \"panel2\";\n            this.panel2.Size = new System.Drawing.Size(496, 34);\n            this.panel2.TabIndex = 3;\n            // \n            // btnClose\n            // \n            this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.btnClose.AutoSize = true;\n            this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnClose.Location = new System.Drawing.Point(426, 2);\n            this.btnClose.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnClose.Name = \"btnClose\";\n            this.btnClose.Size = new System.Drawing.Size(68, 30);\n            this.btnClose.TabIndex = 6;\n            this.btnClose.Text = \"&Close\";\n            this.btnClose.UseVisualStyleBackColor = true;\n            // \n            // btnGoToSteam\n            // \n            this.btnGoToSteam.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.btnGoToSteam.AutoSize = true;\n            this.btnGoToSteam.Location = new System.Drawing.Point(346, 2);\n            this.btnGoToSteam.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.btnGoToSteam.Name = \"btnGoToSteam\";\n            this.btnGoToSteam.Size = new System.Drawing.Size(76, 30);\n            this.btnGoToSteam.TabIndex = 7;\n            this.btnGoToSteam.Text = \"Go to &Steam\";\n            this.btnGoToSteam.UseVisualStyleBackColor = true;\n            this.btnGoToSteam.Click += new System.EventHandler(this.btnGoToSteam_Click);\n            // \n            // publicMapContextMenuStrip\n            // \n            this.publicMapContextMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.publicMapContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.publishAsNewToolStripMenuItem});\n            this.publicMapContextMenuStrip.Name = \"publicMapContextMenuStrip\";\n            this.publicMapContextMenuStrip.Size = new System.Drawing.Size(157, 26);\n            // \n            // publishAsNewToolStripMenuItem\n            // \n            this.publishAsNewToolStripMenuItem.Name = \"publishAsNewToolStripMenuItem\";\n            this.publishAsNewToolStripMenuItem.Size = new System.Drawing.Size(156, 22);\n            this.publishAsNewToolStripMenuItem.Text = \"Publish As New\";\n            this.publishAsNewToolStripMenuItem.Click += new System.EventHandler(this.publishAsNewToolStripMenuItem_Click);\n            // \n            // statusLbl\n            // \n            this.statusLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Left) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.statusLbl.Location = new System.Drawing.Point(7, 1);\n            this.statusLbl.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.statusLbl.Name = \"statusLbl\";\n            this.statusLbl.Size = new System.Drawing.Size(264, 31);\n            this.statusLbl.TabIndex = 9;\n            this.statusLbl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label5\n            // \n            this.label5.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label5.Location = new System.Drawing.Point(3, 275);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(494, 110);\n            this.label5.TabIndex = 4;\n            this.label5.Text = resources.GetString(\"label5.Text\");\n            // \n            // btnPublishMap\n            // \n            this.btnPublishMap.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.btnPublishMap.AutoSize = true;\n            this.btnPublishMap.Location = new System.Drawing.Point(234, 2);\n            this.btnPublishMap.Margin = new System.Windows.Forms.Padding(2);\n            this.btnPublishMap.Menu = this.publicMapContextMenuStrip;\n            this.btnPublishMap.Name = \"btnPublishMap\";\n            this.btnPublishMap.Size = new System.Drawing.Size(111, 30);\n            this.btnPublishMap.TabIndex = 8;\n            this.btnPublishMap.Text = \"&Publish Map\";\n            this.btnPublishMap.UseVisualStyleBackColor = true;\n            this.btnPublishMap.Click += new System.EventHandler(this.btnPublishMap_Click);\n            // \n            // imageTooltip\n            // \n            this.imageTooltip.MaxSize = new System.Drawing.Size(0, 0);\n            this.imageTooltip.OwnerDraw = true;\n            this.imageTooltip.ShowAlways = true;\n            // \n            // SteamDialog\n            // \n            this.AcceptButton = this.btnPublishMap;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.AutoSize = true;\n            this.CancelButton = this.btnClose;\n            this.ClientSize = new System.Drawing.Size(500, 385);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(516, 357);\n            this.Name = \"SteamDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n            this.Text = \"Steam Workshop: Publish Custom Map\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel2.ResumeLayout(false);\n            this.tableLayoutPanel2.PerformLayout();\n            this.panel1.ResumeLayout(false);\n            this.panel1.PerformLayout();\n            this.panel2.ResumeLayout(false);\n            this.panel2.PerformLayout();\n            this.publicMapContextMenuStrip.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.Label label3;\n        private System.Windows.Forms.Label label4;\n        private System.Windows.Forms.TextBox descriptionTxt;\n        private System.Windows.Forms.TextBox titleTxt;\n        private System.Windows.Forms.ComboBox visibilityComboBox;\n        private System.Windows.Forms.Panel panel1;\n        private System.Windows.Forms.TextBox previewTxt;\n        private System.Windows.Forms.Button previewBtn;\n        private System.Windows.Forms.Panel panel2;\n        private System.Windows.Forms.Button btnClose;\n        private System.Windows.Forms.Button btnGoToSteam;\n        private MobiusEditor.Controls.MenuButton btnPublishMap;\n        private System.Windows.Forms.Label statusLbl;\n        private System.Windows.Forms.ContextMenuStrip publicMapContextMenuStrip;\n        private System.Windows.Forms.ToolStripMenuItem publishAsNewToolStripMenuItem;\n        private Controls.ImageTooltip imageTooltip;\n        private System.Windows.Forms.Label label5;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/SteamDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing Steamworks;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.IO;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class SteamDialog : Form\n    {\n        private static readonly string PreviewDirectory = Path.Combine(Path.GetTempPath(), \"CnCRCMapEditor\");\n\n        private readonly IGamePlugin plugin;\n        private readonly Timer statusUpdateTimer = new Timer();\n\n        public SteamDialog(IGamePlugin plugin)\n        {\n            this.plugin = plugin;\n\n            InitializeComponent();\n\n            visibilityComboBox.DataSource = new []\n            {\n                new { Name = \"Public\", Value = ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPublic },\n                new { Name = \"Friends Only\", Value = ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityFriendsOnly },\n                new { Name = \"Private\", Value = ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPrivate }\n            };\n\n            statusUpdateTimer.Interval = 500;\n            statusUpdateTimer.Tick += StatusUpdateTimer_Tick;\n\n            Disposed += (o, e) => { (previewTxt.Tag as Image)?.Dispose(); };\n        }\n\n        protected override void OnLoad(EventArgs e)\n        {\n            base.OnLoad(e);\n\n            titleTxt.Text = plugin.Map.SteamSection.Title;\n            descriptionTxt.Text = plugin.Map.SteamSection.Description;\n            previewTxt.Text = plugin.Map.SteamSection.PreviewFile;\n            visibilityComboBox.SelectedValue = plugin.Map.SteamSection.Visibility;\n\n            btnPublishMap.SplitWidth = (plugin.Map.SteamSection.PublishedFileId != PublishedFileId_t.Invalid.m_PublishedFileId) ? MenuButton.DefaultSplitWidth : 0;\n\n            Directory.CreateDirectory(PreviewDirectory);\n            var previewPath = Path.Combine(PreviewDirectory, \"Minimap.png\");\n            plugin.Map.GenerateWorkshopPreview().ToBitmap().Save(previewPath, ImageFormat.Png);\n\n            if (plugin.Map.BasicSection.SoloMission)\n            {\n                var soloBannerPath = Path.Combine(PreviewDirectory, \"SoloBanner.png\");\n                Properties.Resources.UI_CustomMissionPreviewDefault.Save(soloBannerPath, ImageFormat.Png);\n                previewTxt.Text = soloBannerPath;\n            }\n            else\n            {\n                previewTxt.Text = previewPath;\n            }\n\n            imageTooltip.SetToolTip(previewTxt, \"Preview.png\");\n\n            statusUpdateTimer.Start();\n\n            UpdateControls();\n        }\n\n        private void StatusUpdateTimer_Tick(object sender, EventArgs e)\n        {\n            var status = SteamworksUGC.CurrentOperation?.Status;\n            if (!string.IsNullOrEmpty(status))\n            {\n                statusLbl.Text = status;\n            }\n        }\n\n        protected override void OnClosed(EventArgs e)\n        {\n            base.OnClosed(e);\n\n            statusUpdateTimer.Stop();\n            statusUpdateTimer.Dispose();\n        }\n\n        protected virtual void OnPublishSuccess()\n        {\n            statusLbl.Text = \"Done.\";\n            EnableControls(true);\n        }\n\n        protected virtual void OnOperationFailed(string status)\n        {\n            statusLbl.Text = status;\n            EnableControls(true);\n        }\n\n        private void EnableControls(bool enable)\n        {\n            titleTxt.Enabled = enable;\n            visibilityComboBox.Enabled = enable;\n            previewTxt.Enabled = enable;\n            previewBtn.Enabled = enable;\n            descriptionTxt.Enabled = enable;\n            btnPublishMap.Enabled = enable;\n            btnClose.Enabled = enable;\n        }\n\n        private void btnGoToSteam_Click(object sender, EventArgs e)\n        {\n            var workshopUrl = SteamworksUGC.WorkshopURL;\n            if (!string.IsNullOrEmpty(workshopUrl))\n            {\n                Process.Start(workshopUrl);\n            }\n        }\n\n        private void btnPublishMap_Click(object sender, EventArgs e)\n        {\n            if (string.IsNullOrEmpty(plugin.Map.BasicSection.Name))\n            {\n                plugin.Map.BasicSection.Name = titleTxt.Text;\n            }\n\n            if (string.IsNullOrEmpty(plugin.Map.BasicSection.Author))\n            {\n                plugin.Map.BasicSection.Author = SteamFriends.GetPersonaName();\n            }\n\n            plugin.Map.SteamSection.PreviewFile = previewTxt.Text;\n            plugin.Map.SteamSection.Title = titleTxt.Text;\n            plugin.Map.SteamSection.Description = descriptionTxt.Text;\n            plugin.Map.SteamSection.Visibility = (ERemoteStoragePublishedFileVisibility)visibilityComboBox.SelectedValue;\n\n            var tempPath = Path.Combine(Path.GetTempPath(), \"CnCRCMapEditorPublishUGC\");\n            Directory.CreateDirectory(tempPath);\n            foreach (var file in new DirectoryInfo(tempPath).EnumerateFiles()) file.Delete();\n\n            var pgmPath = Path.Combine(tempPath, \"MAPDATA.PGM\");\n            plugin.Save(pgmPath, FileType.PGM);\n\n            var tags = new List<string>();\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    tags.Add(\"TD\");\n                    break;\n                case GameType.RedAlert:\n                    tags.Add(\"RA\");\n                    break;\n            }\n\n            if (plugin.Map.BasicSection.SoloMission)\n            {\n                tags.Add(\"SinglePlayer\");\n            }\n            else\n            {\n                tags.Add(\"MultiPlayer\");\n            }\n\n            if (SteamworksUGC.PublishUGC(tempPath, plugin.Map.SteamSection, tags, OnPublishSuccess, OnOperationFailed))\n            {\n                statusLbl.Text = SteamworksUGC.CurrentOperation.Status;\n                EnableControls(false);\n            }\n        }\n\n        private void previewBtn_Click(object sender, EventArgs e)\n        {\n            var ofd = new OpenFileDialog\n            {\n                AutoUpgradeEnabled = false,\n                RestoreDirectory = true,\n                Filter = \"Preview Files (*.png)|*.png\",\n                CheckFileExists = true,\n                InitialDirectory = Path.GetDirectoryName(previewTxt.Text),\n                FileName = Path.GetFileName(previewTxt.Text)\n            };\n            if (!string.IsNullOrEmpty(previewTxt.Text))\n            {\n                ofd.FileName = previewTxt.Text;\n            }\n            if (ofd.ShowDialog() == DialogResult.OK)\n            {\n                previewTxt.Text = ofd.FileName;\n            }\n        }\n\n        private void publishAsNewToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            plugin.Map.SteamSection.PublishedFileId = PublishedFileId_t.Invalid.m_PublishedFileId;\n            btnPublishMap.PerformClick();\n        }\n\n        private void previewTxt_TextChanged(object sender, EventArgs e)\n        {\n            try\n            {\n                (previewTxt.Tag as Image)?.Dispose();\n\n                Bitmap preview = null;\n                using (Bitmap b = new Bitmap(previewTxt.Text))\n                {\n                    preview = new Bitmap(b.Width, b.Height, b.PixelFormat);\n                    using (Graphics g = Graphics.FromImage(preview))\n                    {\n                        g.DrawImage(b, Point.Empty);\n                        g.Flush();\n                    }\n                }\n\n                previewTxt.Tag = preview;\n            }\n            catch (Exception)\n            {\n                previewTxt.Tag = null;\n            }\n\n            UpdateControls();\n        }\n\n        private void descriptionTxt_TextChanged(object sender, EventArgs e)\n        {\n            UpdateControls();\n        }\n\n        private void UpdateControls()\n        {\n            btnPublishMap.Enabled = (previewTxt.Tag != null) && !string.IsNullOrEmpty(descriptionTxt.Text);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/SteamDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"publicMapContextMenuStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n  <data name=\"label5.Text\" xml:space=\"preserve\">\n    <value>Respect the rights of others. Provide only content (1) that is not defamatory, obscene, offensive or indecent, (2) that is not confidential or proprietary and (3) that does not violate or infringe any third-party rights. By providing content, you grant EA all licenses needed to enable EA’s use of the content for any purpose. EA’s User Agreement applies.\n\nEA does not pre-screen, endorse or specifically support any C&amp;&amp;C mod.  Please use mods with caution and understand there may be a risk.  EA reserves the right to address any inappropriate use of our C&amp;&amp;C content.</value>\n  </data>\n  <metadata name=\"imageTooltip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>314, 17</value>\n  </metadata>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TeamTypesDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class TeamTypesDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnCancel = new System.Windows.Forms.Button();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.settingsPanel = new System.Windows.Forms.Panel();\n            this.teamTypeTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();\n            this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.houseComboBox = new System.Windows.Forms.ComboBox();\n            this.roundaboutCheckBox = new System.Windows.Forms.CheckBox();\n            this.learningCheckBox = new System.Windows.Forms.CheckBox();\n            this.suicideCheckBox = new System.Windows.Forms.CheckBox();\n            this.autocreateCheckBox = new System.Windows.Forms.CheckBox();\n            this.mercernaryCheckBox = new System.Windows.Forms.CheckBox();\n            this.reinforcableCheckBox = new System.Windows.Forms.CheckBox();\n            this.prebuiltCheckBox = new System.Windows.Forms.CheckBox();\n            this.label2 = new System.Windows.Forms.Label();\n            this.label3 = new System.Windows.Forms.Label();\n            this.label4 = new System.Windows.Forms.Label();\n            this.initNumNud = new System.Windows.Forms.NumericUpDown();\n            this.maxAllowedNud = new System.Windows.Forms.NumericUpDown();\n            this.fearNud = new System.Windows.Forms.NumericUpDown();\n            this.waypointLabel = new System.Windows.Forms.Label();\n            this.triggerLabel = new System.Windows.Forms.Label();\n            this.waypointComboBox = new System.Windows.Forms.ComboBox();\n            this.triggerComboBox = new System.Windows.Forms.ComboBox();\n            this.label9 = new System.Windows.Forms.Label();\n            this.recruitPriorityNud = new System.Windows.Forms.NumericUpDown();\n            this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();\n            this.label7 = new System.Windows.Forms.Label();\n            this.label8 = new System.Windows.Forms.Label();\n            this.teamsDataGridView = new System.Windows.Forms.DataGridView();\n            this.teamsTypeColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();\n            this.teamsCountColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();\n            this.missionsDataGridView = new System.Windows.Forms.DataGridView();\n            this.missionsMissionColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();\n            this.missionsArgumentColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();\n            this.teamTypesListView = new System.Windows.Forms.ListView();\n            this.nameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.teamTypesContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);\n            this.addTeamTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.removeTeamTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.settingsPanel.SuspendLayout();\n            this.teamTypeTableLayoutPanel.SuspendLayout();\n            this.tableLayoutPanel2.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.initNumNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxAllowedNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.fearNud)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.recruitPriorityNud)).BeginInit();\n            this.tableLayoutPanel3.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.teamsDataGridView)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.missionsDataGridView)).BeginInit();\n            this.teamTypesContextMenuStrip.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F));\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 80F));\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.settingsPanel, 1, 0);\n            this.tableLayoutPanel1.Controls.Add(this.teamTypesListView, 0, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 2;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(1313, 640);\n            this.tableLayoutPanel1.TabIndex = 1;\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.AutoSize = true;\n            this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 2);\n            this.flowLayoutPanel1.Controls.Add(this.btnCancel);\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(4, 583);\n            this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(1305, 52);\n            this.flowLayoutPanel1.TabIndex = 1;\n            // \n            // btnCancel\n            // \n            this.btnCancel.AutoSize = true;\n            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnCancel.Location = new System.Drawing.Point(1200, 3);\n            this.btnCancel.Name = \"btnCancel\";\n            this.btnCancel.Size = new System.Drawing.Size(102, 46);\n            this.btnCancel.TabIndex = 2;\n            this.btnCancel.Text = \"&Cancel\";\n            this.btnCancel.UseVisualStyleBackColor = true;\n            // \n            // btnOK\n            // \n            this.btnOK.AutoSize = true;\n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;\n            this.btnOK.Location = new System.Drawing.Point(1119, 3);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(75, 46);\n            this.btnOK.TabIndex = 3;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // settingsPanel\n            // \n            this.settingsPanel.Controls.Add(this.teamTypeTableLayoutPanel);\n            this.settingsPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.settingsPanel.Location = new System.Drawing.Point(277, 15);\n            this.settingsPanel.Margin = new System.Windows.Forms.Padding(15);\n            this.settingsPanel.Name = \"settingsPanel\";\n            this.settingsPanel.Size = new System.Drawing.Size(1021, 548);\n            this.settingsPanel.TabIndex = 3;\n            // \n            // teamTypeTableLayoutPanel\n            // \n            this.teamTypeTableLayoutPanel.ColumnCount = 3;\n            this.teamTypeTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.teamTypeTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.teamTypeTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.teamTypeTableLayoutPanel.Controls.Add(this.tableLayoutPanel2, 0, 0);\n            this.teamTypeTableLayoutPanel.Controls.Add(this.tableLayoutPanel3, 2, 0);\n            this.teamTypeTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.teamTypeTableLayoutPanel.Location = new System.Drawing.Point(0, 0);\n            this.teamTypeTableLayoutPanel.Name = \"teamTypeTableLayoutPanel\";\n            this.teamTypeTableLayoutPanel.RowCount = 1;\n            this.teamTypeTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.teamTypeTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 548F));\n            this.teamTypeTableLayoutPanel.Size = new System.Drawing.Size(1021, 548);\n            this.teamTypeTableLayoutPanel.TabIndex = 0;\n            // \n            // tableLayoutPanel2\n            // \n            this.tableLayoutPanel2.AutoSize = true;\n            this.tableLayoutPanel2.ColumnCount = 2;\n            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel2.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel2.Controls.Add(this.houseComboBox, 1, 0);\n            this.tableLayoutPanel2.Controls.Add(this.roundaboutCheckBox, 1, 1);\n            this.tableLayoutPanel2.Controls.Add(this.learningCheckBox, 1, 2);\n            this.tableLayoutPanel2.Controls.Add(this.suicideCheckBox, 1, 3);\n            this.tableLayoutPanel2.Controls.Add(this.autocreateCheckBox, 1, 4);\n            this.tableLayoutPanel2.Controls.Add(this.mercernaryCheckBox, 1, 5);\n            this.tableLayoutPanel2.Controls.Add(this.reinforcableCheckBox, 1, 6);\n            this.tableLayoutPanel2.Controls.Add(this.prebuiltCheckBox, 1, 7);\n            this.tableLayoutPanel2.Controls.Add(this.label2, 0, 9);\n            this.tableLayoutPanel2.Controls.Add(this.label3, 0, 10);\n            this.tableLayoutPanel2.Controls.Add(this.label4, 0, 11);\n            this.tableLayoutPanel2.Controls.Add(this.initNumNud, 1, 9);\n            this.tableLayoutPanel2.Controls.Add(this.maxAllowedNud, 1, 10);\n            this.tableLayoutPanel2.Controls.Add(this.fearNud, 1, 11);\n            this.tableLayoutPanel2.Controls.Add(this.waypointLabel, 0, 12);\n            this.tableLayoutPanel2.Controls.Add(this.triggerLabel, 0, 13);\n            this.tableLayoutPanel2.Controls.Add(this.waypointComboBox, 1, 12);\n            this.tableLayoutPanel2.Controls.Add(this.triggerComboBox, 1, 13);\n            this.tableLayoutPanel2.Controls.Add(this.label9, 0, 8);\n            this.tableLayoutPanel2.Controls.Add(this.recruitPriorityNud, 1, 8);\n            this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 3);\n            this.tableLayoutPanel2.Name = \"tableLayoutPanel2\";\n            this.tableLayoutPanel2.RowCount = 15;\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel2.Size = new System.Drawing.Size(307, 542);\n            this.tableLayoutPanel2.TabIndex = 0;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(3, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(100, 34);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"House\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // houseComboBox\n            // \n            this.houseComboBox.DisplayMember = \"Name\";\n            this.houseComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.houseComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.houseComboBox.FormattingEnabled = true;\n            this.houseComboBox.Location = new System.Drawing.Point(109, 3);\n            this.houseComboBox.Name = \"houseComboBox\";\n            this.houseComboBox.Size = new System.Drawing.Size(195, 28);\n            this.houseComboBox.TabIndex = 1;\n            this.houseComboBox.ValueMember = \"Type\";\n            // \n            // roundaboutCheckBox\n            // \n            this.roundaboutCheckBox.AutoSize = true;\n            this.roundaboutCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.roundaboutCheckBox.Location = new System.Drawing.Point(109, 37);\n            this.roundaboutCheckBox.Name = \"roundaboutCheckBox\";\n            this.roundaboutCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.roundaboutCheckBox.TabIndex = 2;\n            this.roundaboutCheckBox.Text = \"Roundabout\";\n            this.roundaboutCheckBox.UseVisualStyleBackColor = true;\n            // \n            // learningCheckBox\n            // \n            this.learningCheckBox.AutoSize = true;\n            this.learningCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.learningCheckBox.Location = new System.Drawing.Point(109, 67);\n            this.learningCheckBox.Name = \"learningCheckBox\";\n            this.learningCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.learningCheckBox.TabIndex = 3;\n            this.learningCheckBox.Text = \"Learning\";\n            this.learningCheckBox.UseVisualStyleBackColor = true;\n            // \n            // suicideCheckBox\n            // \n            this.suicideCheckBox.AutoSize = true;\n            this.suicideCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.suicideCheckBox.Location = new System.Drawing.Point(109, 97);\n            this.suicideCheckBox.Name = \"suicideCheckBox\";\n            this.suicideCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.suicideCheckBox.TabIndex = 4;\n            this.suicideCheckBox.Text = \"Suicide\";\n            this.suicideCheckBox.UseVisualStyleBackColor = true;\n            // \n            // autocreateCheckBox\n            // \n            this.autocreateCheckBox.AutoSize = true;\n            this.autocreateCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.autocreateCheckBox.Location = new System.Drawing.Point(109, 127);\n            this.autocreateCheckBox.Name = \"autocreateCheckBox\";\n            this.autocreateCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.autocreateCheckBox.TabIndex = 5;\n            this.autocreateCheckBox.Text = \"Auto-create\";\n            this.autocreateCheckBox.UseVisualStyleBackColor = true;\n            // \n            // mercernaryCheckBox\n            // \n            this.mercernaryCheckBox.AutoSize = true;\n            this.mercernaryCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.mercernaryCheckBox.Location = new System.Drawing.Point(109, 157);\n            this.mercernaryCheckBox.Name = \"mercernaryCheckBox\";\n            this.mercernaryCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.mercernaryCheckBox.TabIndex = 6;\n            this.mercernaryCheckBox.Text = \"Mercernary\";\n            this.mercernaryCheckBox.UseVisualStyleBackColor = true;\n            // \n            // reinforcableCheckBox\n            // \n            this.reinforcableCheckBox.AutoSize = true;\n            this.reinforcableCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.reinforcableCheckBox.Location = new System.Drawing.Point(109, 187);\n            this.reinforcableCheckBox.Name = \"reinforcableCheckBox\";\n            this.reinforcableCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.reinforcableCheckBox.TabIndex = 7;\n            this.reinforcableCheckBox.Text = \"Reinforcable\";\n            this.reinforcableCheckBox.UseVisualStyleBackColor = true;\n            // \n            // prebuiltCheckBox\n            // \n            this.prebuiltCheckBox.AutoSize = true;\n            this.prebuiltCheckBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.prebuiltCheckBox.Location = new System.Drawing.Point(109, 217);\n            this.prebuiltCheckBox.Name = \"prebuiltCheckBox\";\n            this.prebuiltCheckBox.Size = new System.Drawing.Size(195, 24);\n            this.prebuiltCheckBox.TabIndex = 8;\n            this.prebuiltCheckBox.Text = \"Prebuilt\";\n            this.prebuiltCheckBox.UseVisualStyleBackColor = true;\n            // \n            // label2\n            // \n            this.label2.AutoSize = true;\n            this.label2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label2.Location = new System.Drawing.Point(3, 276);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(100, 32);\n            this.label2.TabIndex = 9;\n            this.label2.Text = \"Init Num\";\n            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label3\n            // \n            this.label3.AutoSize = true;\n            this.label3.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label3.Location = new System.Drawing.Point(3, 308);\n            this.label3.Name = \"label3\";\n            this.label3.Size = new System.Drawing.Size(100, 32);\n            this.label3.TabIndex = 10;\n            this.label3.Text = \"Max Allowed\";\n            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // label4\n            // \n            this.label4.AutoSize = true;\n            this.label4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label4.Location = new System.Drawing.Point(3, 340);\n            this.label4.Name = \"label4\";\n            this.label4.Size = new System.Drawing.Size(100, 32);\n            this.label4.TabIndex = 11;\n            this.label4.Text = \"Fear\";\n            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // initNumNud\n            // \n            this.initNumNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.initNumNud.Location = new System.Drawing.Point(109, 279);\n            this.initNumNud.Maximum = new decimal(new int[] {\n            255,\n            0,\n            0,\n            0});\n            this.initNumNud.Name = \"initNumNud\";\n            this.initNumNud.Size = new System.Drawing.Size(195, 26);\n            this.initNumNud.TabIndex = 12;\n            // \n            // maxAllowedNud\n            // \n            this.maxAllowedNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.maxAllowedNud.Location = new System.Drawing.Point(109, 311);\n            this.maxAllowedNud.Maximum = new decimal(new int[] {\n            255,\n            0,\n            0,\n            0});\n            this.maxAllowedNud.Name = \"maxAllowedNud\";\n            this.maxAllowedNud.Size = new System.Drawing.Size(195, 26);\n            this.maxAllowedNud.TabIndex = 13;\n            // \n            // fearNud\n            // \n            this.fearNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.fearNud.Location = new System.Drawing.Point(109, 343);\n            this.fearNud.Maximum = new decimal(new int[] {\n            255,\n            0,\n            0,\n            0});\n            this.fearNud.Name = \"fearNud\";\n            this.fearNud.Size = new System.Drawing.Size(195, 26);\n            this.fearNud.TabIndex = 14;\n            // \n            // waypointLabel\n            // \n            this.waypointLabel.AutoSize = true;\n            this.waypointLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.waypointLabel.Location = new System.Drawing.Point(3, 372);\n            this.waypointLabel.Name = \"waypointLabel\";\n            this.waypointLabel.Size = new System.Drawing.Size(100, 34);\n            this.waypointLabel.TabIndex = 15;\n            this.waypointLabel.Text = \"Waypoint\";\n            this.waypointLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // triggerLabel\n            // \n            this.triggerLabel.AutoSize = true;\n            this.triggerLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggerLabel.Location = new System.Drawing.Point(3, 406);\n            this.triggerLabel.Name = \"triggerLabel\";\n            this.triggerLabel.Size = new System.Drawing.Size(100, 34);\n            this.triggerLabel.TabIndex = 16;\n            this.triggerLabel.Text = \"Trigger\";\n            this.triggerLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // waypointComboBox\n            // \n            this.waypointComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.waypointComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.waypointComboBox.FormattingEnabled = true;\n            this.waypointComboBox.Location = new System.Drawing.Point(109, 375);\n            this.waypointComboBox.Name = \"waypointComboBox\";\n            this.waypointComboBox.Size = new System.Drawing.Size(195, 28);\n            this.waypointComboBox.TabIndex = 17;\n            // \n            // triggerComboBox\n            // \n            this.triggerComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.triggerComboBox.FormattingEnabled = true;\n            this.triggerComboBox.Location = new System.Drawing.Point(109, 409);\n            this.triggerComboBox.Name = \"triggerComboBox\";\n            this.triggerComboBox.Size = new System.Drawing.Size(195, 28);\n            this.triggerComboBox.TabIndex = 18;\n            // \n            // label9\n            // \n            this.label9.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label9.Location = new System.Drawing.Point(3, 244);\n            this.label9.Name = \"label9\";\n            this.label9.Size = new System.Drawing.Size(100, 32);\n            this.label9.TabIndex = 19;\n            this.label9.Text = \"Priority\";\n            this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // recruitPriorityNud\n            // \n            this.recruitPriorityNud.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.recruitPriorityNud.Location = new System.Drawing.Point(109, 247);\n            this.recruitPriorityNud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.recruitPriorityNud.Minimum = new decimal(new int[] {\n            -2147483648,\n            0,\n            0,\n            -2147483648});\n            this.recruitPriorityNud.Name = \"recruitPriorityNud\";\n            this.recruitPriorityNud.Size = new System.Drawing.Size(195, 26);\n            this.recruitPriorityNud.TabIndex = 20;\n            // \n            // tableLayoutPanel3\n            // \n            this.tableLayoutPanel3.ColumnCount = 2;\n            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));\n            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));\n            this.tableLayoutPanel3.Controls.Add(this.label7, 0, 0);\n            this.tableLayoutPanel3.Controls.Add(this.label8, 1, 0);\n            this.tableLayoutPanel3.Controls.Add(this.teamsDataGridView, 0, 1);\n            this.tableLayoutPanel3.Controls.Add(this.missionsDataGridView, 1, 1);\n            this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel3.Location = new System.Drawing.Point(316, 3);\n            this.tableLayoutPanel3.Name = \"tableLayoutPanel3\";\n            this.tableLayoutPanel3.RowCount = 2;\n            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel3.Size = new System.Drawing.Size(702, 542);\n            this.tableLayoutPanel3.TabIndex = 1;\n            // \n            // label7\n            // \n            this.label7.AutoSize = true;\n            this.label7.Location = new System.Drawing.Point(3, 0);\n            this.label7.Name = \"label7\";\n            this.label7.Size = new System.Drawing.Size(57, 20);\n            this.label7.TabIndex = 0;\n            this.label7.Text = \"Teams\";\n            // \n            // label8\n            // \n            this.label8.AutoSize = true;\n            this.label8.Location = new System.Drawing.Point(354, 0);\n            this.label8.Name = \"label8\";\n            this.label8.Size = new System.Drawing.Size(70, 20);\n            this.label8.TabIndex = 1;\n            this.label8.Text = \"Missions\";\n            // \n            // teamsDataGridView\n            // \n            this.teamsDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;\n            this.teamsDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;\n            this.teamsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;\n            this.teamsDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {\n            this.teamsTypeColumn,\n            this.teamsCountColumn});\n            this.teamsDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.teamsDataGridView.Location = new System.Drawing.Point(3, 23);\n            this.teamsDataGridView.Name = \"teamsDataGridView\";\n            this.teamsDataGridView.RowTemplate.Height = 28;\n            this.teamsDataGridView.Size = new System.Drawing.Size(345, 516);\n            this.teamsDataGridView.TabIndex = 2;\n            this.teamsDataGridView.VirtualMode = true;\n            this.teamsDataGridView.CancelRowEdit += new System.Windows.Forms.QuestionEventHandler(this.teamsDataGridView_CancelRowEdit);\n            this.teamsDataGridView.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.teamsDataGridView_CellValueNeeded);\n            this.teamsDataGridView.CellValuePushed += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.teamsDataGridView_CellValuePushed);\n            this.teamsDataGridView.NewRowNeeded += new System.Windows.Forms.DataGridViewRowEventHandler(this.teamsDataGridView_NewRowNeeded);\n            this.teamsDataGridView.RowDirtyStateNeeded += new System.Windows.Forms.QuestionEventHandler(this.teamsDataGridView_RowDirtyStateNeeded);\n            this.teamsDataGridView.RowValidated += new System.Windows.Forms.DataGridViewCellEventHandler(this.teamsDataGridView_RowValidated);\n            this.teamsDataGridView.UserAddedRow += new System.Windows.Forms.DataGridViewRowEventHandler(this.teamsDataGridView_UserAddedRow);\n            this.teamsDataGridView.UserDeletedRow += new System.Windows.Forms.DataGridViewRowEventHandler(this.teamsDataGridView_UserDeletedRow);\n            this.teamsDataGridView.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.teamsDataGridView_UserDeletingRow);\n            // \n            // teamsTypeColumn\n            // \n            this.teamsTypeColumn.HeaderText = \"Type\";\n            this.teamsTypeColumn.Name = \"teamsTypeColumn\";\n            this.teamsTypeColumn.Width = 54;\n            // \n            // teamsCountColumn\n            // \n            this.teamsCountColumn.HeaderText = \"Count\";\n            this.teamsCountColumn.Name = \"teamsCountColumn\";\n            this.teamsCountColumn.Width = 88;\n            // \n            // missionsDataGridView\n            // \n            this.missionsDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;\n            this.missionsDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;\n            this.missionsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;\n            this.missionsDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {\n            this.missionsMissionColumn,\n            this.missionsArgumentColumn});\n            this.missionsDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.missionsDataGridView.Location = new System.Drawing.Point(354, 23);\n            this.missionsDataGridView.Name = \"missionsDataGridView\";\n            this.missionsDataGridView.RowTemplate.Height = 28;\n            this.missionsDataGridView.Size = new System.Drawing.Size(345, 516);\n            this.missionsDataGridView.TabIndex = 3;\n            this.missionsDataGridView.VirtualMode = true;\n            this.missionsDataGridView.CancelRowEdit += new System.Windows.Forms.QuestionEventHandler(this.missionsDataGridView_CancelRowEdit);\n            this.missionsDataGridView.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.missionsDataGridView_CellValueNeeded);\n            this.missionsDataGridView.CellValuePushed += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.missionsDataGridView_CellValuePushed);\n            this.missionsDataGridView.NewRowNeeded += new System.Windows.Forms.DataGridViewRowEventHandler(this.missionsDataGridView_NewRowNeeded);\n            this.missionsDataGridView.RowDirtyStateNeeded += new System.Windows.Forms.QuestionEventHandler(this.missionsDataGridView_RowDirtyStateNeeded);\n            this.missionsDataGridView.RowValidated += new System.Windows.Forms.DataGridViewCellEventHandler(this.missionsDataGridView_RowValidated);\n            this.missionsDataGridView.UserAddedRow += new System.Windows.Forms.DataGridViewRowEventHandler(this.missionsDataGridView_UserAddedRow);\n            this.missionsDataGridView.UserDeletedRow += new System.Windows.Forms.DataGridViewRowEventHandler(this.missionsDataGridView_UserDeletedRow);\n            this.missionsDataGridView.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.missionsDataGridView_UserDeletingRow);\n            // \n            // missionsMissionColumn\n            // \n            this.missionsMissionColumn.HeaderText = \"Mission\";\n            this.missionsMissionColumn.Name = \"missionsMissionColumn\";\n            this.missionsMissionColumn.Width = 68;\n            // \n            // missionsArgumentColumn\n            // \n            this.missionsArgumentColumn.HeaderText = \"Argument\";\n            this.missionsArgumentColumn.Name = \"missionsArgumentColumn\";\n            this.missionsArgumentColumn.Width = 115;\n            // \n            // teamTypesListView\n            // \n            this.teamTypesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {\n            this.nameColumnHeader});\n            this.teamTypesListView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.teamTypesListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;\n            this.teamTypesListView.HideSelection = false;\n            this.teamTypesListView.LabelEdit = true;\n            this.teamTypesListView.Location = new System.Drawing.Point(3, 3);\n            this.teamTypesListView.MultiSelect = false;\n            this.teamTypesListView.Name = \"teamTypesListView\";\n            this.teamTypesListView.ShowItemToolTips = true;\n            this.teamTypesListView.Size = new System.Drawing.Size(256, 572);\n            this.teamTypesListView.TabIndex = 4;\n            this.teamTypesListView.UseCompatibleStateImageBehavior = false;\n            this.teamTypesListView.View = System.Windows.Forms.View.Details;\n            this.teamTypesListView.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.teamTypesListView_AfterLabelEdit);\n            this.teamTypesListView.SelectedIndexChanged += new System.EventHandler(this.teamTypesListView_SelectedIndexChanged);\n            this.teamTypesListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.teamTypesListView_KeyDown);\n            this.teamTypesListView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.teamTypesListView_MouseDown);\n            // \n            // teamTypesContextMenuStrip\n            // \n            this.teamTypesContextMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.teamTypesContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.addTeamTypeToolStripMenuItem,\n            this.removeTeamTypeToolStripMenuItem});\n            this.teamTypesContextMenuStrip.Name = \"teamTypesContextMenuStrip\";\n            this.teamTypesContextMenuStrip.Size = new System.Drawing.Size(237, 64);\n            // \n            // addTeamTypeToolStripMenuItem\n            // \n            this.addTeamTypeToolStripMenuItem.Name = \"addTeamTypeToolStripMenuItem\";\n            this.addTeamTypeToolStripMenuItem.Size = new System.Drawing.Size(236, 30);\n            this.addTeamTypeToolStripMenuItem.Text = \"&Add Team Type\";\n            this.addTeamTypeToolStripMenuItem.Click += new System.EventHandler(this.addTeamTypeToolStripMenuItem_Click);\n            // \n            // removeTeamTypeToolStripMenuItem\n            // \n            this.removeTeamTypeToolStripMenuItem.Name = \"removeTeamTypeToolStripMenuItem\";\n            this.removeTeamTypeToolStripMenuItem.Size = new System.Drawing.Size(236, 30);\n            this.removeTeamTypeToolStripMenuItem.Text = \"&Remove Team Type\";\n            this.removeTeamTypeToolStripMenuItem.Click += new System.EventHandler(this.removeTeamTypeToolStripMenuItem_Click);\n            // \n            // TeamTypesDialog\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnCancel;\n            this.ClientSize = new System.Drawing.Size(1313, 640);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"TeamTypesDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n            this.Text = \"Team Types\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.flowLayoutPanel1.PerformLayout();\n            this.settingsPanel.ResumeLayout(false);\n            this.teamTypeTableLayoutPanel.ResumeLayout(false);\n            this.teamTypeTableLayoutPanel.PerformLayout();\n            this.tableLayoutPanel2.ResumeLayout(false);\n            this.tableLayoutPanel2.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.initNumNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.maxAllowedNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.fearNud)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.recruitPriorityNud)).EndInit();\n            this.tableLayoutPanel3.ResumeLayout(false);\n            this.tableLayoutPanel3.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.teamsDataGridView)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.missionsDataGridView)).EndInit();\n            this.teamTypesContextMenuStrip.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.Button btnCancel;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.Panel settingsPanel;\n        private System.Windows.Forms.ListView teamTypesListView;\n        private System.Windows.Forms.ColumnHeader nameColumnHeader;\n        private System.Windows.Forms.ContextMenuStrip teamTypesContextMenuStrip;\n        private System.Windows.Forms.ToolStripMenuItem addTeamTypeToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem removeTeamTypeToolStripMenuItem;\n        private System.Windows.Forms.TableLayoutPanel teamTypeTableLayoutPanel;\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.ComboBox houseComboBox;\n        private System.Windows.Forms.CheckBox roundaboutCheckBox;\n        private System.Windows.Forms.CheckBox learningCheckBox;\n        private System.Windows.Forms.CheckBox suicideCheckBox;\n        private System.Windows.Forms.CheckBox autocreateCheckBox;\n        private System.Windows.Forms.CheckBox mercernaryCheckBox;\n        private System.Windows.Forms.CheckBox reinforcableCheckBox;\n        private System.Windows.Forms.CheckBox prebuiltCheckBox;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.Label label3;\n        private System.Windows.Forms.Label label4;\n        private System.Windows.Forms.NumericUpDown initNumNud;\n        private System.Windows.Forms.NumericUpDown maxAllowedNud;\n        private System.Windows.Forms.NumericUpDown fearNud;\n        private System.Windows.Forms.Label waypointLabel;\n        private System.Windows.Forms.Label triggerLabel;\n        private System.Windows.Forms.ComboBox waypointComboBox;\n        private System.Windows.Forms.ComboBox triggerComboBox;\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;\n        private System.Windows.Forms.Label label7;\n        private System.Windows.Forms.Label label8;\n        private System.Windows.Forms.DataGridView teamsDataGridView;\n        private System.Windows.Forms.DataGridView missionsDataGridView;\n        private System.Windows.Forms.Label label9;\n        private System.Windows.Forms.NumericUpDown recruitPriorityNud;\n        private System.Windows.Forms.DataGridViewComboBoxColumn teamsTypeColumn;\n        private System.Windows.Forms.DataGridViewTextBoxColumn teamsCountColumn;\n        private System.Windows.Forms.DataGridViewComboBoxColumn missionsMissionColumn;\n        private System.Windows.Forms.DataGridViewTextBoxColumn missionsArgumentColumn;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TeamTypesDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class TeamTypesDialog : Form\n    {\n        private readonly IGamePlugin plugin;\n        private readonly int maxTeams;\n        private readonly IEnumerable<ITechnoType> technoTypes;\n\n        private readonly List<TeamType> teamTypes;\n        public IEnumerable<TeamType> TeamTypes => teamTypes;\n\n        private ListViewItem SelectedItem => (teamTypesListView.SelectedItems.Count > 0) ? teamTypesListView.SelectedItems[0] : null;\n\n        private TeamType SelectedTeamType => SelectedItem?.Tag as TeamType;\n\n        private TeamTypeClass mockClass;\n        private TeamTypeMission mockMission;\n        private int classEditRow = -1;\n        private int missionEditRow = -1;\n\n        public TeamTypesDialog(IGamePlugin plugin, int maxTeams)\n        {\n            this.plugin = plugin;\n            this.maxTeams = maxTeams;\n            technoTypes = plugin.Map.InfantryTypes.Cast<ITechnoType>().Concat(plugin.Map.UnitTypes.Cast<ITechnoType>());\n\n            InitializeComponent();\n\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    triggerLabel.Visible = triggerComboBox.Visible = false;\n                    waypointLabel.Visible = waypointComboBox.Visible = false;\n                    break;\n                case GameType.RedAlert:\n                    learningCheckBox.Visible = false;\n                    mercernaryCheckBox.Visible = false;\n                    break;\n            }\n\n            teamTypes = new List<TeamType>(plugin.Map.TeamTypes.Select(t => t.Clone()));\n\n            teamTypesListView.BeginUpdate();\n            {\n                foreach (var teamType in this.teamTypes)\n                {\n                    var item = new ListViewItem(teamType.Name)\n                    {\n                        Tag = teamType\n                    };\n                    teamTypesListView.Items.Add(item).ToolTipText = teamType.Name;\n                }\n            }\n            teamTypesListView.EndUpdate();\n\n            houseComboBox.DataSource = plugin.Map.Houses.Select(t => new TypeItem<HouseType>(t.Type.Name, t.Type)).ToArray();\n            waypointComboBox.DataSource = \"(none)\".Yield().Concat(plugin.Map.Waypoints.Select(w => w.Name)).ToArray();\n            triggerComboBox.DataSource = Trigger.None.Yield().Concat(plugin.Map.Triggers.Select(t => t.Name)).ToArray();\n\n            teamsTypeColumn.DisplayMember = \"Name\";\n            teamsTypeColumn.ValueMember = \"Type\";\n            teamsTypeColumn.DataSource = technoTypes.Select(t => new TypeItem<ITechnoType>(t.Name, t)).ToArray();\n\n            missionsMissionColumn.DataSource = plugin.Map.TeamMissionTypes;\n\n            teamTypeTableLayoutPanel.Visible = false;\n        }\n\n        private void teamTypesListView_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            houseComboBox.DataBindings.Clear();\n            roundaboutCheckBox.DataBindings.Clear();\n            learningCheckBox.DataBindings.Clear();\n            suicideCheckBox.DataBindings.Clear();\n            autocreateCheckBox.DataBindings.Clear();\n            mercernaryCheckBox.DataBindings.Clear();\n            reinforcableCheckBox.DataBindings.Clear();\n            prebuiltCheckBox.DataBindings.Clear();\n            recruitPriorityNud.DataBindings.Clear();\n            initNumNud.DataBindings.Clear();\n            maxAllowedNud.DataBindings.Clear();\n            fearNud.DataBindings.Clear();\n            waypointComboBox.DataBindings.Clear();\n            triggerComboBox.DataBindings.Clear();\n\n            if (SelectedTeamType != null)\n            {\n                houseComboBox.DataBindings.Add(\"SelectedValue\", SelectedTeamType, \"House\");\n                roundaboutCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsRoundAbout\");\n                learningCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsLearning\");\n                suicideCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsSuicide\");\n                autocreateCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsAutocreate\");\n                mercernaryCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsMercenary\");\n                reinforcableCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsReinforcable\");\n                prebuiltCheckBox.DataBindings.Add(\"Checked\", SelectedTeamType, \"IsPrebuilt\");\n                recruitPriorityNud.DataBindings.Add(\"Value\", SelectedTeamType, \"RecruitPriority\");\n                initNumNud.DataBindings.Add(\"Value\", SelectedTeamType, \"InitNum\");\n                maxAllowedNud.DataBindings.Add(\"Value\", SelectedTeamType, \"MaxAllowed\");\n                fearNud.DataBindings.Add(\"Value\", SelectedTeamType, \"Fear\");\n                waypointComboBox.DataBindings.Add(\"SelectedIndex\", SelectedTeamType, \"Origin\");\n                triggerComboBox.DataBindings.Add(\"SelectedItem\", SelectedTeamType, \"Trigger\");\n\n                mockClass = null;\n                mockMission = null;\n                classEditRow = -1;\n                missionEditRow = -1;\n\n                teamsDataGridView.Rows.Clear();\n                missionsDataGridView.Rows.Clear();\n\n                teamsDataGridView.RowCount = SelectedTeamType.Classes.Count + 1;\n                missionsDataGridView.RowCount = SelectedTeamType.Missions.Count + 1;\n\n                updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);\n                updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);\n\n                teamTypeTableLayoutPanel.Visible = true;\n            }\n            else\n            {\n                teamTypeTableLayoutPanel.Visible = false;\n            }\n        }\n\n        private void teamTypesListView_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (e.Button == MouseButtons.Right)\n            {\n                var hitTest = teamTypesListView.HitTest(e.Location);\n\n                bool canAdd = (hitTest.Item == null) && (teamTypesListView.Items.Count < maxTeams);\n                bool canRemove = hitTest.Item != null;\n                addTeamTypeToolStripMenuItem.Visible = canAdd;\n                removeTeamTypeToolStripMenuItem.Visible = canRemove;\n\n                if (canAdd || canRemove)\n                {\n                    teamTypesContextMenuStrip.Show(Cursor.Position);\n                }\n            }\n        }\n\n        private void teamTypesListView_KeyDown(object sender, KeyEventArgs e)\n        {\n            if ((e.KeyData == Keys.F2) && (teamTypesListView.SelectedItems.Count > 0))\n            {\n                teamTypesListView.SelectedItems[0].BeginEdit();\n            }\n        }\n\n        private void addTeamTypeToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var nameChars = Enumerable.Range(97, 26).Concat(Enumerable.Range(48, 10));\n\n            string name = string.Empty;\n            foreach (var nameChar in nameChars)\n            {\n                name = new string((char)nameChar, 4);\n                if (!teamTypes.Where(t => t.Equals(name)).Any())\n                {\n                    break;\n                }\n            }\n\n            var teamType = new TeamType { Name = name, House = plugin.Map.HouseTypes.First() };\n            var item = new ListViewItem(teamType.Name)\n            {\n                Tag = teamType\n            };\n            teamTypes.Add(teamType);\n            teamTypesListView.Items.Add(item).ToolTipText = teamType.Name;\n\n            item.Selected = true;\n            item.BeginEdit();\n        }\n\n        private void removeTeamTypeToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            if (SelectedItem != null)\n            {\n                teamTypes.Remove(SelectedTeamType);\n                teamTypesListView.Items.Remove(SelectedItem);\n            }\n        }\n\n        private void teamTypesListView_AfterLabelEdit(object sender, LabelEditEventArgs e)\n        {\n            int maxLength = int.MaxValue;\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    maxLength = 8;\n                    break;\n                case GameType.RedAlert:\n                    maxLength = 23;\n                    break;\n            }\n\n            if (string.IsNullOrEmpty(e.Label))\n            {\n                e.CancelEdit = true;\n            }\n            else if (e.Label.Length > maxLength)\n            {\n                e.CancelEdit = true;\n                MessageBox.Show(string.Format(\"Team name is longer than {0} characters.\", maxLength), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n            else if (teamTypes.Where(t => (t != SelectedTeamType) && t.Equals(e.Label)).Any())\n            {\n                e.CancelEdit = true;\n                MessageBox.Show(string.Format(\"Team with name '{0]' already exists\", e.Label), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n            else\n            {\n                SelectedTeamType.Name = e.Label;\n                teamTypesListView.Items[e.Item].ToolTipText = SelectedTeamType.Name;\n            }\n        }\n\n        private void teamsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)\n        {\n            if (SelectedTeamType == null)\n            {\n                return;\n            }\n\n            TeamTypeClass teamTypeClass = null;\n            if (e.RowIndex == classEditRow)\n            {\n                teamTypeClass = mockClass;\n            }\n            else if (e.RowIndex < SelectedTeamType.Classes.Count)\n            {\n                teamTypeClass = SelectedTeamType.Classes[e.RowIndex];\n            }\n\n            if (teamTypeClass == null)\n            {\n                return;\n            }\n\n            switch (e.ColumnIndex)\n            {\n                case 0:\n                    e.Value = teamTypeClass.Type;\n                    break;\n                case 1:\n                    e.Value = teamTypeClass.Count;\n                    break;\n            }\n        }\n\n        private void teamsDataGridView_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)\n        {\n            if (SelectedTeamType == null)\n            {\n                return;\n            }\n\n            if (mockClass == null)\n            {\n                mockClass = (e.RowIndex < SelectedTeamType.Classes.Count) ?\n                    new TeamTypeClass { Type = SelectedTeamType.Classes[e.RowIndex].Type, Count = SelectedTeamType.Classes[e.RowIndex].Count } :\n                    new TeamTypeClass { Type = technoTypes.First(), Count = 0 };\n            }\n            classEditRow = e.RowIndex;\n\n            switch (e.ColumnIndex)\n            {\n                case 0:\n                    mockClass.Type = e.Value as ITechnoType;\n                    break;\n                case 1:\n                    mockClass.Count = int.TryParse(e.Value as string, out int value) ? (byte)Math.Max(0, Math.Min(255, value)) : (byte)0;\n                    break;\n            }\n        }\n\n        private void teamsDataGridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e)\n        {\n            mockClass = new TeamTypeClass { Type = technoTypes.First(), Count = 0 };\n            classEditRow = teamsDataGridView.RowCount - 1;\n        }\n\n        private void teamsDataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)\n        {\n            if ((mockClass != null) && (e.RowIndex >= SelectedTeamType.Classes.Count) && ((teamsDataGridView.Rows.Count > 1) || (e.RowIndex < (teamsDataGridView.Rows.Count - 1))))\n            {\n                SelectedTeamType.Classes.Add(mockClass);\n                mockClass = null;\n                classEditRow = -1;\n            }\n            else if ((mockClass != null) && (e.RowIndex < SelectedTeamType.Classes.Count))\n            {\n                SelectedTeamType.Classes[e.RowIndex] = mockClass;\n                mockClass = null;\n                classEditRow = -1;\n            }\n            else if (teamsDataGridView.ContainsFocus)\n            {\n                mockClass = null;\n                classEditRow = -1;\n            }\n        }\n\n        private void teamsDataGridView_RowDirtyStateNeeded(object sender, QuestionEventArgs e)\n        {\n            e.Response = teamsDataGridView.IsCurrentCellDirty;\n        }\n\n        private void teamsDataGridView_CancelRowEdit(object sender, QuestionEventArgs e)\n        {\n            if ((classEditRow == (teamsDataGridView.Rows.Count - 2)) && (classEditRow == SelectedTeamType.Classes.Count))\n            {\n                mockClass = new TeamTypeClass { Type = technoTypes.First(), Count = 0 };\n            }\n            else\n            {\n                mockClass = null;\n                classEditRow = -1;\n            }\n        }\n\n        private void teamsDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)\n        {\n            if (e.Row.Index < SelectedTeamType.Classes.Count)\n            {\n                SelectedTeamType.Classes.RemoveAt(e.Row.Index);\n            }\n\n            if (e.Row.Index == classEditRow)\n            {\n                mockClass = null;\n                classEditRow = -1;\n            }\n        }\n\n        private void teamsDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)\n        {\n            updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);\n        }\n\n        private void teamsDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)\n        {\n            updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);\n        }\n\n        private void missionsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)\n        {\n            if (SelectedTeamType == null)\n            {\n                return;\n            }\n\n            TeamTypeMission teamMissionType = null;\n            if (e.RowIndex == missionEditRow)\n            {\n                teamMissionType = mockMission;\n            }\n            else if (e.RowIndex < SelectedTeamType.Missions.Count)\n            {\n                teamMissionType = SelectedTeamType.Missions[e.RowIndex];\n            }\n\n            if (teamMissionType == null)\n            {\n                return;\n            }\n\n            switch (e.ColumnIndex)\n            {\n                case 0:\n                    e.Value = teamMissionType.Mission;\n                    break;\n                case 1:\n                    e.Value = teamMissionType.Argument;\n                    break;\n            }\n        }\n\n        private void missionsDataGridView_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)\n        {\n            if (SelectedTeamType == null)\n            {\n                return;\n            }\n\n            if (mockMission == null)\n            {\n                mockMission = (e.RowIndex < SelectedTeamType.Missions.Count) ?\n                    new TeamTypeMission { Mission = SelectedTeamType.Missions[e.RowIndex].Mission, Argument = SelectedTeamType.Missions[e.RowIndex].Argument } :\n                    new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };\n            }\n            missionEditRow = e.RowIndex;\n\n            switch (e.ColumnIndex)\n            {\n                case 0:\n                    mockMission.Mission = e.Value as string;\n                    break;\n                case 1:\n                    mockMission.Argument = int.TryParse(e.Value as string, out int value) ? value : 0;\n                    break;\n            }\n        }\n\n        private void missionsDataGridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e)\n        {\n            mockMission = new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };\n            missionEditRow = missionsDataGridView.RowCount - 1;\n        }\n\n        private void missionsDataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)\n        {\n            if ((mockMission != null) && (e.RowIndex >= SelectedTeamType.Missions.Count) && ((missionsDataGridView.Rows.Count > 1) || (e.RowIndex < (missionsDataGridView.Rows.Count - 1))))\n            {\n                SelectedTeamType.Missions.Add(mockMission);\n                mockMission = null;\n                missionEditRow = -1;\n            }\n            else if ((mockMission != null) && (e.RowIndex < SelectedTeamType.Missions.Count))\n            {\n                SelectedTeamType.Missions[e.RowIndex] = mockMission;\n                mockMission = null;\n                missionEditRow = -1;\n            }\n            else if (missionsDataGridView.ContainsFocus)\n            {\n                mockMission = null;\n                missionEditRow = -1;\n            }\n        }\n\n        private void missionsDataGridView_RowDirtyStateNeeded(object sender, QuestionEventArgs e)\n        {\n            e.Response = missionsDataGridView.IsCurrentCellDirty;\n        }\n\n        private void missionsDataGridView_CancelRowEdit(object sender, QuestionEventArgs e)\n        {\n            if ((missionEditRow == (missionsDataGridView.Rows.Count - 2)) && (missionEditRow == SelectedTeamType.Missions.Count))\n            {\n                mockMission = new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };\n            }\n            else\n            {\n                mockMission = null;\n                missionEditRow = -1;\n            }\n        }\n\n        private void missionsDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)\n        {\n            if (e.Row.Index < SelectedTeamType.Missions.Count)\n            {\n                SelectedTeamType.Missions.RemoveAt(e.Row.Index);\n            }\n\n            if (e.Row.Index == missionEditRow)\n            {\n                mockMission = null;\n                missionEditRow = -1;\n            }\n        }\n\n        private void missionsDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)\n        {\n            updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);\n        }\n\n        private void missionsDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)\n        {\n            updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);\n        }\n\n        private void updateDataGridViewAddRows(DataGridView dataGridView, int maxItems)\n        {\n            dataGridView.AllowUserToAddRows = dataGridView.Rows.Count <= maxItems;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TeamTypesDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"teamsTypeColumn.UserAddedColumn\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n  <metadata name=\"teamsCountColumn.UserAddedColumn\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n  <metadata name=\"missionsMissionColumn.UserAddedColumn\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n  <metadata name=\"missionsArgumentColumn.UserAddedColumn\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n  <metadata name=\"teamTypesContextMenuStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TriggersDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Dialogs\n{\n    partial class TriggersDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();\n            this.btnCancel = new System.Windows.Forms.Button();\n            this.btnOK = new System.Windows.Forms.Button();\n            this.settingsPanel = new System.Windows.Forms.Panel();\n            this.triggersTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.houseComboBox = new System.Windows.Forms.ComboBox();\n            this.typeLabel = new System.Windows.Forms.Label();\n            this.event1Label = new System.Windows.Forms.Label();\n            this.event2Label = new System.Windows.Forms.Label();\n            this.action1Label = new System.Windows.Forms.Label();\n            this.action2Label = new System.Windows.Forms.Label();\n            this.action1ComboBox = new System.Windows.Forms.ComboBox();\n            this.action2ComboBox = new System.Windows.Forms.ComboBox();\n            this.existenceLabel = new System.Windows.Forms.Label();\n            this.existenceComboBox = new System.Windows.Forms.ComboBox();\n            this.typeComboBox = new System.Windows.Forms.ComboBox();\n            this.event1ComboBox = new System.Windows.Forms.ComboBox();\n            this.event2ComboBox = new System.Windows.Forms.ComboBox();\n            this.teamLabel = new System.Windows.Forms.Label();\n            this.teamComboBox = new System.Windows.Forms.ComboBox();\n            this.event1Flp = new System.Windows.Forms.FlowLayoutPanel();\n            this.event1Nud = new System.Windows.Forms.NumericUpDown();\n            this.event1ValueComboBox = new System.Windows.Forms.ComboBox();\n            this.event2Flp = new System.Windows.Forms.FlowLayoutPanel();\n            this.event2Nud = new System.Windows.Forms.NumericUpDown();\n            this.event2ValueComboBox = new System.Windows.Forms.ComboBox();\n            this.action1Flp = new System.Windows.Forms.FlowLayoutPanel();\n            this.action1Nud = new System.Windows.Forms.NumericUpDown();\n            this.action1ValueComboBox = new System.Windows.Forms.ComboBox();\n            this.action2Flp = new System.Windows.Forms.FlowLayoutPanel();\n            this.action2Nud = new System.Windows.Forms.NumericUpDown();\n            this.action2ValueComboBox = new System.Windows.Forms.ComboBox();\n            this.triggersListView = new System.Windows.Forms.ListView();\n            this.nameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.triggersContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);\n            this.addTriggerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.removeTriggerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.flowLayoutPanel1.SuspendLayout();\n            this.settingsPanel.SuspendLayout();\n            this.triggersTableLayoutPanel.SuspendLayout();\n            this.event1Flp.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.event1Nud)).BeginInit();\n            this.event2Flp.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.event2Nud)).BeginInit();\n            this.action1Flp.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.action1Nud)).BeginInit();\n            this.action2Flp.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.action2Nud)).BeginInit();\n            this.triggersContextMenuStrip.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 2;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.settingsPanel, 1, 0);\n            this.tableLayoutPanel1.Controls.Add(this.triggersListView, 0, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 2;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(562, 499);\n            this.tableLayoutPanel1.TabIndex = 1;\n            // \n            // flowLayoutPanel1\n            // \n            this.flowLayoutPanel1.AutoSize = true;\n            this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 2);\n            this.flowLayoutPanel1.Controls.Add(this.btnCancel);\n            this.flowLayoutPanel1.Controls.Add(this.btnOK);\n            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;\n            this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 462);\n            this.flowLayoutPanel1.Name = \"flowLayoutPanel1\";\n            this.flowLayoutPanel1.Size = new System.Drawing.Size(556, 34);\n            this.flowLayoutPanel1.TabIndex = 1;\n            // \n            // btnCancel\n            // \n            this.btnCancel.AutoSize = true;\n            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.btnCancel.Location = new System.Drawing.Point(486, 2);\n            this.btnCancel.Margin = new System.Windows.Forms.Padding(2);\n            this.btnCancel.Name = \"btnCancel\";\n            this.btnCancel.Size = new System.Drawing.Size(68, 30);\n            this.btnCancel.TabIndex = 2;\n            this.btnCancel.Text = \"&Cancel\";\n            this.btnCancel.UseVisualStyleBackColor = true;\n            // \n            // btnOK\n            // \n            this.btnOK.AutoSize = true;\n            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;\n            this.btnOK.Location = new System.Drawing.Point(432, 2);\n            this.btnOK.Margin = new System.Windows.Forms.Padding(2);\n            this.btnOK.Name = \"btnOK\";\n            this.btnOK.Size = new System.Drawing.Size(50, 30);\n            this.btnOK.TabIndex = 3;\n            this.btnOK.Text = \"&OK\";\n            this.btnOK.UseVisualStyleBackColor = true;\n            // \n            // settingsPanel\n            // \n            this.settingsPanel.Controls.Add(this.triggersTableLayoutPanel);\n            this.settingsPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.settingsPanel.Location = new System.Drawing.Point(149, 10);\n            this.settingsPanel.Margin = new System.Windows.Forms.Padding(10);\n            this.settingsPanel.Name = \"settingsPanel\";\n            this.settingsPanel.Size = new System.Drawing.Size(403, 439);\n            this.settingsPanel.TabIndex = 3;\n            // \n            // triggersTableLayoutPanel\n            // \n            this.triggersTableLayoutPanel.AutoSize = true;\n            this.triggersTableLayoutPanel.ColumnCount = 4;\n            this.triggersTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.triggersTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.triggersTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.triggersTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.triggersTableLayoutPanel.Controls.Add(this.label1, 0, 0);\n            this.triggersTableLayoutPanel.Controls.Add(this.houseComboBox, 1, 0);\n            this.triggersTableLayoutPanel.Controls.Add(this.typeLabel, 0, 9);\n            this.triggersTableLayoutPanel.Controls.Add(this.event1Label, 0, 10);\n            this.triggersTableLayoutPanel.Controls.Add(this.event2Label, 0, 11);\n            this.triggersTableLayoutPanel.Controls.Add(this.action1Label, 0, 12);\n            this.triggersTableLayoutPanel.Controls.Add(this.action2Label, 0, 13);\n            this.triggersTableLayoutPanel.Controls.Add(this.action1ComboBox, 1, 12);\n            this.triggersTableLayoutPanel.Controls.Add(this.action2ComboBox, 1, 13);\n            this.triggersTableLayoutPanel.Controls.Add(this.existenceLabel, 0, 8);\n            this.triggersTableLayoutPanel.Controls.Add(this.existenceComboBox, 1, 8);\n            this.triggersTableLayoutPanel.Controls.Add(this.typeComboBox, 1, 9);\n            this.triggersTableLayoutPanel.Controls.Add(this.event1ComboBox, 1, 10);\n            this.triggersTableLayoutPanel.Controls.Add(this.event2ComboBox, 1, 11);\n            this.triggersTableLayoutPanel.Controls.Add(this.teamLabel, 0, 14);\n            this.triggersTableLayoutPanel.Controls.Add(this.teamComboBox, 1, 14);\n            this.triggersTableLayoutPanel.Controls.Add(this.event1Flp, 2, 10);\n            this.triggersTableLayoutPanel.Controls.Add(this.event2Flp, 2, 11);\n            this.triggersTableLayoutPanel.Controls.Add(this.action1Flp, 2, 12);\n            this.triggersTableLayoutPanel.Controls.Add(this.action2Flp, 2, 13);\n            this.triggersTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggersTableLayoutPanel.Location = new System.Drawing.Point(0, 0);\n            this.triggersTableLayoutPanel.Margin = new System.Windows.Forms.Padding(2);\n            this.triggersTableLayoutPanel.Name = \"triggersTableLayoutPanel\";\n            this.triggersTableLayoutPanel.RowCount = 17;\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.triggersTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.triggersTableLayoutPanel.Size = new System.Drawing.Size(403, 439);\n            this.triggersTableLayoutPanel.TabIndex = 1;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(2, 0);\n            this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(67, 25);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"House\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // houseComboBox\n            // \n            this.houseComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.houseComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.houseComboBox.FormattingEnabled = true;\n            this.houseComboBox.Location = new System.Drawing.Point(73, 2);\n            this.houseComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.houseComboBox.Name = \"houseComboBox\";\n            this.houseComboBox.Size = new System.Drawing.Size(141, 21);\n            this.houseComboBox.TabIndex = 1;\n            // \n            // typeLabel\n            // \n            this.typeLabel.AutoSize = true;\n            this.typeLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.typeLabel.Location = new System.Drawing.Point(2, 50);\n            this.typeLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.typeLabel.Name = \"typeLabel\";\n            this.typeLabel.Size = new System.Drawing.Size(67, 25);\n            this.typeLabel.TabIndex = 9;\n            this.typeLabel.Text = \"Type\";\n            this.typeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // event1Label\n            // \n            this.event1Label.AutoSize = true;\n            this.event1Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event1Label.Location = new System.Drawing.Point(2, 75);\n            this.event1Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.event1Label.Name = \"event1Label\";\n            this.event1Label.Size = new System.Drawing.Size(67, 57);\n            this.event1Label.TabIndex = 10;\n            this.event1Label.Text = \"Event 1\";\n            this.event1Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // event2Label\n            // \n            this.event2Label.AutoSize = true;\n            this.event2Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event2Label.Location = new System.Drawing.Point(2, 132);\n            this.event2Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.event2Label.Name = \"event2Label\";\n            this.event2Label.Size = new System.Drawing.Size(67, 57);\n            this.event2Label.TabIndex = 11;\n            this.event2Label.Text = \"Event 2\";\n            this.event2Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // action1Label\n            // \n            this.action1Label.AutoSize = true;\n            this.action1Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action1Label.Location = new System.Drawing.Point(2, 189);\n            this.action1Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.action1Label.Name = \"action1Label\";\n            this.action1Label.Size = new System.Drawing.Size(67, 57);\n            this.action1Label.TabIndex = 15;\n            this.action1Label.Text = \"Action 1\";\n            this.action1Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // action2Label\n            // \n            this.action2Label.AutoSize = true;\n            this.action2Label.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action2Label.Location = new System.Drawing.Point(2, 246);\n            this.action2Label.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.action2Label.Name = \"action2Label\";\n            this.action2Label.Size = new System.Drawing.Size(67, 57);\n            this.action2Label.TabIndex = 16;\n            this.action2Label.Text = \"Action 2\";\n            this.action2Label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // action1ComboBox\n            // \n            this.action1ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action1ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.action1ComboBox.FormattingEnabled = true;\n            this.action1ComboBox.Location = new System.Drawing.Point(73, 191);\n            this.action1ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.action1ComboBox.Name = \"action1ComboBox\";\n            this.action1ComboBox.Size = new System.Drawing.Size(141, 21);\n            this.action1ComboBox.TabIndex = 17;\n            this.action1ComboBox.SelectedIndexChanged += new System.EventHandler(this.trigger1ComboBox_SelectedIndexChanged);\n            // \n            // action2ComboBox\n            // \n            this.action2ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action2ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.action2ComboBox.FormattingEnabled = true;\n            this.action2ComboBox.Location = new System.Drawing.Point(73, 248);\n            this.action2ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.action2ComboBox.Name = \"action2ComboBox\";\n            this.action2ComboBox.Size = new System.Drawing.Size(141, 21);\n            this.action2ComboBox.TabIndex = 18;\n            this.action2ComboBox.SelectedIndexChanged += new System.EventHandler(this.trigger2ComboBox_SelectedIndexChanged);\n            // \n            // existenceLabel\n            // \n            this.existenceLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.existenceLabel.Location = new System.Drawing.Point(2, 25);\n            this.existenceLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.existenceLabel.Name = \"existenceLabel\";\n            this.existenceLabel.Size = new System.Drawing.Size(67, 25);\n            this.existenceLabel.TabIndex = 19;\n            this.existenceLabel.Text = \"Existence\";\n            this.existenceLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // existenceComboBox\n            // \n            this.existenceComboBox.DisplayMember = \"Name\";\n            this.existenceComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.existenceComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.existenceComboBox.FormattingEnabled = true;\n            this.existenceComboBox.Location = new System.Drawing.Point(73, 27);\n            this.existenceComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.existenceComboBox.Name = \"existenceComboBox\";\n            this.existenceComboBox.Size = new System.Drawing.Size(141, 21);\n            this.existenceComboBox.TabIndex = 20;\n            this.existenceComboBox.ValueMember = \"Value\";\n            // \n            // typeComboBox\n            // \n            this.typeComboBox.DisplayMember = \"Name\";\n            this.typeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.typeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.typeComboBox.FormattingEnabled = true;\n            this.typeComboBox.Location = new System.Drawing.Point(73, 52);\n            this.typeComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.typeComboBox.Name = \"typeComboBox\";\n            this.typeComboBox.Size = new System.Drawing.Size(141, 21);\n            this.typeComboBox.TabIndex = 21;\n            this.typeComboBox.ValueMember = \"Value\";\n            this.typeComboBox.SelectedValueChanged += new System.EventHandler(this.typeComboBox_SelectedValueChanged);\n            // \n            // event1ComboBox\n            // \n            this.event1ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event1ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.event1ComboBox.FormattingEnabled = true;\n            this.event1ComboBox.Location = new System.Drawing.Point(73, 77);\n            this.event1ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.event1ComboBox.Name = \"event1ComboBox\";\n            this.event1ComboBox.Size = new System.Drawing.Size(141, 21);\n            this.event1ComboBox.TabIndex = 22;\n            this.event1ComboBox.SelectedIndexChanged += new System.EventHandler(this.trigger1ComboBox_SelectedIndexChanged);\n            // \n            // event2ComboBox\n            // \n            this.event2ComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event2ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.event2ComboBox.FormattingEnabled = true;\n            this.event2ComboBox.Location = new System.Drawing.Point(73, 134);\n            this.event2ComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.event2ComboBox.Name = \"event2ComboBox\";\n            this.event2ComboBox.Size = new System.Drawing.Size(141, 21);\n            this.event2ComboBox.TabIndex = 23;\n            this.event2ComboBox.SelectedIndexChanged += new System.EventHandler(this.trigger2ComboBox_SelectedIndexChanged);\n            // \n            // teamLabel\n            // \n            this.teamLabel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.teamLabel.Location = new System.Drawing.Point(2, 303);\n            this.teamLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);\n            this.teamLabel.Name = \"teamLabel\";\n            this.teamLabel.Size = new System.Drawing.Size(67, 25);\n            this.teamLabel.TabIndex = 32;\n            this.teamLabel.Text = \"Team\";\n            this.teamLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // teamComboBox\n            // \n            this.teamComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.teamComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.teamComboBox.FormattingEnabled = true;\n            this.teamComboBox.Location = new System.Drawing.Point(73, 305);\n            this.teamComboBox.Margin = new System.Windows.Forms.Padding(2);\n            this.teamComboBox.Name = \"teamComboBox\";\n            this.teamComboBox.Size = new System.Drawing.Size(141, 21);\n            this.teamComboBox.TabIndex = 33;\n            // \n            // event1Flp\n            // \n            this.event1Flp.AutoSize = true;\n            this.event1Flp.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.event1Flp.Controls.Add(this.event1Nud);\n            this.event1Flp.Controls.Add(this.event1ValueComboBox);\n            this.event1Flp.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event1Flp.Location = new System.Drawing.Point(219, 78);\n            this.event1Flp.Name = \"event1Flp\";\n            this.event1Flp.Size = new System.Drawing.Size(172, 51);\n            this.event1Flp.TabIndex = 36;\n            // \n            // event1Nud\n            // \n            this.event1Nud.Location = new System.Drawing.Point(2, 2);\n            this.event1Nud.Margin = new System.Windows.Forms.Padding(2);\n            this.event1Nud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.event1Nud.Minimum = new decimal(new int[] {\n            -2147483648,\n            0,\n            0,\n            -2147483648});\n            this.event1Nud.Name = \"event1Nud\";\n            this.event1Nud.Size = new System.Drawing.Size(70, 20);\n            this.event1Nud.TabIndex = 31;\n            // \n            // event1ValueComboBox\n            // \n            this.event1ValueComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.event1ValueComboBox.FormattingEnabled = true;\n            this.event1ValueComboBox.Location = new System.Drawing.Point(3, 27);\n            this.event1ValueComboBox.Name = \"event1ValueComboBox\";\n            this.event1ValueComboBox.Size = new System.Drawing.Size(166, 21);\n            this.event1ValueComboBox.TabIndex = 32;\n            // \n            // event2Flp\n            // \n            this.event2Flp.AutoSize = true;\n            this.event2Flp.Controls.Add(this.event2Nud);\n            this.event2Flp.Controls.Add(this.event2ValueComboBox);\n            this.event2Flp.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.event2Flp.Location = new System.Drawing.Point(219, 135);\n            this.event2Flp.Name = \"event2Flp\";\n            this.event2Flp.Size = new System.Drawing.Size(172, 51);\n            this.event2Flp.TabIndex = 37;\n            // \n            // event2Nud\n            // \n            this.event2Nud.Location = new System.Drawing.Point(2, 2);\n            this.event2Nud.Margin = new System.Windows.Forms.Padding(2);\n            this.event2Nud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.event2Nud.Minimum = new decimal(new int[] {\n            -2147483648,\n            0,\n            0,\n            -2147483648});\n            this.event2Nud.Name = \"event2Nud\";\n            this.event2Nud.Size = new System.Drawing.Size(70, 20);\n            this.event2Nud.TabIndex = 30;\n            // \n            // event2ValueComboBox\n            // \n            this.event2ValueComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.event2ValueComboBox.FormattingEnabled = true;\n            this.event2ValueComboBox.Location = new System.Drawing.Point(3, 27);\n            this.event2ValueComboBox.Name = \"event2ValueComboBox\";\n            this.event2ValueComboBox.Size = new System.Drawing.Size(166, 21);\n            this.event2ValueComboBox.TabIndex = 33;\n            // \n            // action1Flp\n            // \n            this.action1Flp.AutoSize = true;\n            this.action1Flp.Controls.Add(this.action1Nud);\n            this.action1Flp.Controls.Add(this.action1ValueComboBox);\n            this.action1Flp.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action1Flp.Location = new System.Drawing.Point(219, 192);\n            this.action1Flp.Name = \"action1Flp\";\n            this.action1Flp.Size = new System.Drawing.Size(172, 51);\n            this.action1Flp.TabIndex = 38;\n            // \n            // action1Nud\n            // \n            this.action1Nud.Location = new System.Drawing.Point(2, 2);\n            this.action1Nud.Margin = new System.Windows.Forms.Padding(2);\n            this.action1Nud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.action1Nud.Minimum = new decimal(new int[] {\n            -2147483648,\n            0,\n            0,\n            -2147483648});\n            this.action1Nud.Name = \"action1Nud\";\n            this.action1Nud.Size = new System.Drawing.Size(70, 20);\n            this.action1Nud.TabIndex = 31;\n            // \n            // action1ValueComboBox\n            // \n            this.action1ValueComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.action1ValueComboBox.FormattingEnabled = true;\n            this.action1ValueComboBox.Location = new System.Drawing.Point(3, 27);\n            this.action1ValueComboBox.Name = \"action1ValueComboBox\";\n            this.action1ValueComboBox.Size = new System.Drawing.Size(166, 21);\n            this.action1ValueComboBox.TabIndex = 33;\n            // \n            // action2Flp\n            // \n            this.action2Flp.AutoSize = true;\n            this.action2Flp.Controls.Add(this.action2Nud);\n            this.action2Flp.Controls.Add(this.action2ValueComboBox);\n            this.action2Flp.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.action2Flp.Location = new System.Drawing.Point(219, 249);\n            this.action2Flp.Name = \"action2Flp\";\n            this.action2Flp.Size = new System.Drawing.Size(172, 51);\n            this.action2Flp.TabIndex = 39;\n            // \n            // action2Nud\n            // \n            this.action2Nud.Location = new System.Drawing.Point(2, 2);\n            this.action2Nud.Margin = new System.Windows.Forms.Padding(2);\n            this.action2Nud.Maximum = new decimal(new int[] {\n            2147483647,\n            0,\n            0,\n            0});\n            this.action2Nud.Minimum = new decimal(new int[] {\n            -2147483648,\n            0,\n            0,\n            -2147483648});\n            this.action2Nud.Name = \"action2Nud\";\n            this.action2Nud.Size = new System.Drawing.Size(70, 20);\n            this.action2Nud.TabIndex = 32;\n            // \n            // action2ValueComboBox\n            // \n            this.action2ValueComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.action2ValueComboBox.FormattingEnabled = true;\n            this.action2ValueComboBox.Location = new System.Drawing.Point(3, 27);\n            this.action2ValueComboBox.Name = \"action2ValueComboBox\";\n            this.action2ValueComboBox.Size = new System.Drawing.Size(166, 21);\n            this.action2ValueComboBox.TabIndex = 33;\n            // \n            // triggersListView\n            // \n            this.triggersListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {\n            this.nameColumnHeader});\n            this.triggersListView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggersListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;\n            this.triggersListView.HideSelection = false;\n            this.triggersListView.LabelEdit = true;\n            this.triggersListView.Location = new System.Drawing.Point(2, 2);\n            this.triggersListView.Margin = new System.Windows.Forms.Padding(2);\n            this.triggersListView.MultiSelect = false;\n            this.triggersListView.Name = \"triggersListView\";\n            this.triggersListView.ShowItemToolTips = true;\n            this.triggersListView.Size = new System.Drawing.Size(135, 455);\n            this.triggersListView.TabIndex = 4;\n            this.triggersListView.UseCompatibleStateImageBehavior = false;\n            this.triggersListView.View = System.Windows.Forms.View.Details;\n            this.triggersListView.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.teamTypesListView_AfterLabelEdit);\n            this.triggersListView.SelectedIndexChanged += new System.EventHandler(this.triggersListView_SelectedIndexChanged);\n            this.triggersListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.teamTypesListView_KeyDown);\n            this.triggersListView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.teamTypesListView_MouseDown);\n            // \n            // triggersContextMenuStrip\n            // \n            this.triggersContextMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.triggersContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.addTriggerToolStripMenuItem,\n            this.removeTriggerToolStripMenuItem});\n            this.triggersContextMenuStrip.Name = \"teamTypesContextMenuStrip\";\n            this.triggersContextMenuStrip.Size = new System.Drawing.Size(157, 48);\n            // \n            // addTriggerToolStripMenuItem\n            // \n            this.addTriggerToolStripMenuItem.Name = \"addTriggerToolStripMenuItem\";\n            this.addTriggerToolStripMenuItem.Size = new System.Drawing.Size(156, 22);\n            this.addTriggerToolStripMenuItem.Text = \"&Add Trigger\";\n            this.addTriggerToolStripMenuItem.Click += new System.EventHandler(this.addTriggerToolStripMenuItem_Click);\n            // \n            // removeTriggerToolStripMenuItem\n            // \n            this.removeTriggerToolStripMenuItem.Name = \"removeTriggerToolStripMenuItem\";\n            this.removeTriggerToolStripMenuItem.Size = new System.Drawing.Size(156, 22);\n            this.removeTriggerToolStripMenuItem.Text = \"&Remove Trigger\";\n            this.removeTriggerToolStripMenuItem.Click += new System.EventHandler(this.removeTriggerToolStripMenuItem_Click);\n            // \n            // TriggersDialog\n            // \n            this.AcceptButton = this.btnOK;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.btnCancel;\n            this.ClientSize = new System.Drawing.Size(562, 499);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.Margin = new System.Windows.Forms.Padding(2);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"TriggersDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n            this.Text = \"Triggers\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.tableLayoutPanel1.PerformLayout();\n            this.flowLayoutPanel1.ResumeLayout(false);\n            this.flowLayoutPanel1.PerformLayout();\n            this.settingsPanel.ResumeLayout(false);\n            this.settingsPanel.PerformLayout();\n            this.triggersTableLayoutPanel.ResumeLayout(false);\n            this.triggersTableLayoutPanel.PerformLayout();\n            this.event1Flp.ResumeLayout(false);\n            ((System.ComponentModel.ISupportInitialize)(this.event1Nud)).EndInit();\n            this.event2Flp.ResumeLayout(false);\n            ((System.ComponentModel.ISupportInitialize)(this.event2Nud)).EndInit();\n            this.action1Flp.ResumeLayout(false);\n            ((System.ComponentModel.ISupportInitialize)(this.action1Nud)).EndInit();\n            this.action2Flp.ResumeLayout(false);\n            ((System.ComponentModel.ISupportInitialize)(this.action2Nud)).EndInit();\n            this.triggersContextMenuStrip.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;\n        private System.Windows.Forms.Button btnCancel;\n        private System.Windows.Forms.Button btnOK;\n        private System.Windows.Forms.Panel settingsPanel;\n        private System.Windows.Forms.ListView triggersListView;\n        private System.Windows.Forms.ColumnHeader nameColumnHeader;\n        private System.Windows.Forms.ContextMenuStrip triggersContextMenuStrip;\n        private System.Windows.Forms.ToolStripMenuItem addTriggerToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem removeTriggerToolStripMenuItem;\n        private System.Windows.Forms.TableLayoutPanel triggersTableLayoutPanel;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.ComboBox houseComboBox;\n        private System.Windows.Forms.Label typeLabel;\n        private System.Windows.Forms.Label event1Label;\n        private System.Windows.Forms.Label event2Label;\n        private System.Windows.Forms.Label action2Label;\n        private System.Windows.Forms.ComboBox action2ComboBox;\n        private System.Windows.Forms.Label existenceLabel;\n        private System.Windows.Forms.ComboBox existenceComboBox;\n        private System.Windows.Forms.ComboBox typeComboBox;\n        private System.Windows.Forms.ComboBox event1ComboBox;\n        private System.Windows.Forms.ComboBox event2ComboBox;\n        private System.Windows.Forms.ComboBox action1ComboBox;\n        private System.Windows.Forms.Label action1Label;\n        private System.Windows.Forms.Label teamLabel;\n        private System.Windows.Forms.ComboBox teamComboBox;\n        private System.Windows.Forms.FlowLayoutPanel event1Flp;\n        private System.Windows.Forms.NumericUpDown event1Nud;\n        private System.Windows.Forms.FlowLayoutPanel event2Flp;\n        private System.Windows.Forms.NumericUpDown event2Nud;\n        private System.Windows.Forms.FlowLayoutPanel action1Flp;\n        private System.Windows.Forms.NumericUpDown action1Nud;\n        private System.Windows.Forms.FlowLayoutPanel action2Flp;\n        private System.Windows.Forms.NumericUpDown action2Nud;\n        private System.Windows.Forms.ComboBox event1ValueComboBox;\n        private System.Windows.Forms.ComboBox event2ValueComboBox;\n        private System.Windows.Forms.ComboBox action1ValueComboBox;\n        private System.Windows.Forms.ComboBox action2ValueComboBox;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TriggersDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Data;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Dialogs\n{\n    public partial class TriggersDialog : Form\n    {\n        private readonly IGamePlugin plugin;\n        private readonly int maxTriggers;\n\n        private readonly List<Trigger> triggers;\n        public IEnumerable<Trigger> Triggers => triggers;\n\n        private ListViewItem SelectedItem => (triggersListView.SelectedItems.Count > 0) ? triggersListView.SelectedItems[0] : null;\n\n        private Trigger SelectedTrigger => SelectedItem?.Tag as Trigger;\n\n        public TriggersDialog(IGamePlugin plugin, int maxTriggers)\n        {\n            this.plugin = plugin;\n            this.maxTriggers = maxTriggers;\n\n            InitializeComponent();\n\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    existenceLabel.Text = \"Loop\";\n                    event1Label.Text = \"Event\";\n                    action1Label.Text = \"Action\";\n                    typeLabel.Visible = typeComboBox.Visible = false;\n                    event2Label.Visible = event2ComboBox.Visible = event2Flp.Visible = false;\n                    action2Label.Visible = action2ComboBox.Visible = action2Flp.Visible = false;\n                    break;\n                case GameType.RedAlert:\n                    teamLabel.Visible = teamComboBox.Visible = false;\n                    break;\n            }\n\n            triggers = new List<Trigger>(plugin.Map.Triggers.Select(t => t.Clone()));\n\n            triggersListView.BeginUpdate();\n            {\n                foreach (var trigger in triggers)\n                {\n                    var item = new ListViewItem(trigger.Name)\n                    {\n                        Tag = trigger\n                    };\n                    triggersListView.Items.Add(item).ToolTipText = trigger.Name;\n                }\n            }\n            triggersListView.EndUpdate();\n\n            string[] existenceNames = Enum.GetNames(typeof(TriggerPersistantType));\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    existenceNames = new string[] { \"No\", \"And\", \"Or\" };\n                    break;\n                case GameType.RedAlert:\n                    existenceNames = new string[] { \"Temporary\", \"Semi-Constant\", \"Constant\" };\n                    break;\n            }\n\n            string[] typeNames = new string[]\n            {\n                \"E => A1 [+ A2]\",\n                \"E1 && E2 => A1 [+ A2]\",\n                \"E1 || E2 => A1 [+ A2]\",\n                \"E1 => A1; E2 => A2\",\n            };\n\n            houseComboBox.DataSource = \"None\".Yield().Concat(plugin.Map.Houses.Select(t => t.Type.Name)).ToArray();\n            existenceComboBox.DataSource = Enum.GetValues(typeof(TriggerPersistantType)).Cast<int>()\n                .Select(v => new { Name = existenceNames[v], Value = (TriggerPersistantType)v })\n                .ToArray();\n            typeComboBox.DataSource = Enum.GetValues(typeof(TriggerMultiStyleType)).Cast<int>()\n                .Select(v => new { Name = typeNames[v], Value = (TriggerMultiStyleType)v })\n                .ToArray();\n            event1ComboBox.DataSource = plugin.Map.EventTypes.Where(t => !string.IsNullOrEmpty(t)).ToArray();\n            event2ComboBox.DataSource = plugin.Map.EventTypes.Where(t => !string.IsNullOrEmpty(t)).ToArray();\n            action1ComboBox.DataSource = plugin.Map.ActionTypes.Where(t => !string.IsNullOrEmpty(t)).ToArray();\n            action2ComboBox.DataSource = plugin.Map.ActionTypes.Where(t => !string.IsNullOrEmpty(t)).ToArray();\n            teamComboBox.DataSource = \"None\".Yield().Concat(plugin.Map.TeamTypes.Select(t => t.Name)).ToArray();\n\n            triggersTableLayoutPanel.Visible = false;\n        }\n\n        private void triggersListView_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            houseComboBox.DataBindings.Clear();\n            existenceComboBox.DataBindings.Clear();\n            typeComboBox.DataBindings.Clear();\n            event1ComboBox.DataBindings.Clear();\n            event2ComboBox.DataBindings.Clear();\n            action1ComboBox.DataBindings.Clear();\n            action2ComboBox.DataBindings.Clear();\n            teamComboBox.DataBindings.Clear();\n\n            if (SelectedTrigger != null)\n            {\n                houseComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger, \"House\");\n                existenceComboBox.DataBindings.Add(\"SelectedValue\", SelectedTrigger, \"PersistantType\");\n                event1ComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger.Event1, \"EventType\");\n                action1ComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger.Action1, \"ActionType\");\n\n                UpdateTriggerControls(SelectedTrigger,\n                    SelectedTrigger?.Event1, SelectedTrigger?.Action1,\n                    event1ComboBox, event1Nud, event1ValueComboBox,\n                    action1ComboBox, action1Nud, action1ValueComboBox);\n\n                switch (plugin.GameType)\n                {\n                    case GameType.TiberianDawn:\n                        teamComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger.Action1, \"Team\");\n                        break;\n                    case GameType.RedAlert:\n                        typeComboBox.DataBindings.Add(\"SelectedValue\", SelectedTrigger, \"EventControl\");\n                        event2ComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger.Event2, \"EventType\");\n                        action2ComboBox.DataBindings.Add(\"SelectedItem\", SelectedTrigger.Action2, \"ActionType\");\n                        UpdateTriggerControls(SelectedTrigger,\n                            SelectedTrigger?.Event2, SelectedTrigger?.Action2,\n                            event2ComboBox, event2Nud, event2ValueComboBox,\n                            action2ComboBox, action2Nud, action2ValueComboBox);\n                        break;\n                }\n\n                triggersTableLayoutPanel.Visible = true;\n            }\n            else\n            {\n                triggersTableLayoutPanel.Visible = false;\n            }\n        }\n\n        private void teamTypesListView_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (e.Button == MouseButtons.Right)\n            {\n                var hitTest = triggersListView.HitTest(e.Location);\n\n                bool canAdd = (hitTest.Item == null) && (triggersListView.Items.Count < maxTriggers);\n                bool canRemove = hitTest.Item != null;\n                addTriggerToolStripMenuItem.Visible = canAdd;\n                removeTriggerToolStripMenuItem.Visible = canRemove;\n\n                if (canAdd || canRemove)\n                {\n                    triggersContextMenuStrip.Show(Cursor.Position);\n                }\n            }\n        }\n\n        private void teamTypesListView_KeyDown(object sender, KeyEventArgs e)\n        {\n            if ((e.KeyData == Keys.F2) && (triggersListView.SelectedItems.Count > 0))\n            {\n                triggersListView.SelectedItems[0].BeginEdit();\n            }\n        }\n\n        private void addTriggerToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var nameChars = Enumerable.Range(97, 26).Concat(Enumerable.Range(48, 10));\n\n            string name = string.Empty;\n            foreach (var nameChar in nameChars)\n            {\n                name = new string((char)nameChar, 4);\n                if (!triggers.Where(t => t.Equals(name)).Any())\n                {\n                    break;\n                }\n            }\n\n            var trigger = new Trigger { Name = name, House = plugin.Map.HouseTypes.First().Name };\n            var item = new ListViewItem(trigger.Name)\n            {\n                Tag = trigger\n            };\n            triggers.Add(trigger);\n            triggersListView.Items.Add(item).ToolTipText = trigger.Name;\n\n            item.Selected = true;\n            item.BeginEdit();\n        }\n\n        private void removeTriggerToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            if (SelectedItem != null)\n            {\n                triggers.Remove(SelectedTrigger);\n                triggersListView.Items.Remove(SelectedItem);\n            }\n        }\n\n        private void teamTypesListView_AfterLabelEdit(object sender, LabelEditEventArgs e)\n        {\n            int maxLength = int.MaxValue;\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    maxLength = 4;\n                    break;\n                case GameType.RedAlert:\n                    maxLength = 23;\n                    break;\n            }\n\n            if (string.IsNullOrEmpty(e.Label))\n            {\n                e.CancelEdit = true;\n            }\n            else if (e.Label.Length > maxLength)\n            {\n                e.CancelEdit = true;\n                MessageBox.Show(string.Format(\"Trigger name is longer than {0} characters.\", maxLength), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n            else if (triggers.Where(t => (t != SelectedTrigger) && t.Equals(e.Label)).Any())\n            {\n                e.CancelEdit = true;\n                MessageBox.Show(string.Format(\"Trigger with name '{0]' already exists\", e.Label), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n            else\n            {\n                SelectedTrigger.Name = e.Label;\n                triggersListView.Items[e.Item].ToolTipText = SelectedTrigger.Name;\n            }\n        }\n\n        private void typeComboBox_SelectedValueChanged(object sender, EventArgs e)\n        {\n            if (plugin.GameType == GameType.RedAlert)\n            {\n                var eventType = (TriggerMultiStyleType)typeComboBox.SelectedValue;\n                event2Label.Visible = event2ComboBox.Visible = event2Flp.Visible = eventType != TriggerMultiStyleType.Only;\n            }\n        }\n\n        private void trigger1ComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            UpdateTriggerControls(SelectedTrigger,\n                SelectedTrigger?.Event1, SelectedTrigger?.Action1,\n                event1ComboBox, event1Nud, event1ValueComboBox,\n                action1ComboBox, action1Nud, action1ValueComboBox);\n        }\n\n        private void trigger2ComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            UpdateTriggerControls(SelectedTrigger,\n                SelectedTrigger?.Event2, SelectedTrigger?.Action2,\n                event2ComboBox, event2Nud, event2ValueComboBox,\n                action2ComboBox, action2Nud, action2ValueComboBox);\n        }\n\n        private void UpdateTriggerControls(Trigger trigger, TriggerEvent triggerEvent, TriggerAction triggerAction, ComboBox eventComboBox, NumericUpDown eventNud, ComboBox eventValueComboBox, ComboBox actionComboBox, NumericUpDown actionNud, ComboBox actionValueComboBox)\n        {\n            eventNud.Visible = false;\n            eventNud.DataBindings.Clear();\n            eventValueComboBox.Visible = false;\n            eventValueComboBox.DataBindings.Clear();\n            eventValueComboBox.DataSource = null;\n            eventValueComboBox.DisplayMember = null;\n            eventValueComboBox.ValueMember = null;\n\n            if (triggerEvent != null)\n            {\n                switch (plugin.GameType)\n                {\n                    case GameType.TiberianDawn:\n                        switch (eventComboBox.SelectedItem)\n                        {\n                            case TiberianDawn.EventTypes.EVENT_TIME:\n                            case TiberianDawn.EventTypes.EVENT_CREDITS:\n                            case TiberianDawn.EventTypes.EVENT_NUNITS_DESTROYED:\n                            case TiberianDawn.EventTypes.EVENT_NBUILDINGS_DESTROYED:\n                                eventNud.Visible = true;\n                                eventNud.DataBindings.Add(\"Value\", triggerEvent, \"Data\");\n                                break;\n                            case TiberianDawn.EventTypes.EVENT_BUILD:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = plugin.Map.BuildingTypes.Select(t => new { Name = t.DisplayName, Value = (long)t.ID }).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            default:\n                                break;\n                        }\n                        break;\n                    case GameType.RedAlert:\n                        switch (eventComboBox.SelectedItem)\n                        {\n                            case RedAlert.EventTypes.TEVENT_LEAVES_MAP:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DataSource = plugin.Map.TeamTypes.Select(t => t.Name).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedItem\", triggerEvent, \"Team\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_PLAYER_ENTERED:\n                            case RedAlert.EventTypes.TEVENT_CROSS_HORIZONTAL:\n                            case RedAlert.EventTypes.TEVENT_CROSS_VERTICAL:\n                            case RedAlert.EventTypes.TEVENT_ENTERS_ZONE:\n                            case RedAlert.EventTypes.TEVENT_LOW_POWER:\n                            case RedAlert.EventTypes.TEVENT_THIEVED:\n                            case RedAlert.EventTypes.TEVENT_HOUSE_DISCOVERED:\n                            case RedAlert.EventTypes.TEVENT_BUILDINGS_DESTROYED:\n                            case RedAlert.EventTypes.TEVENT_UNITS_DESTROYED:\n                            case RedAlert.EventTypes.TEVENT_ALL_DESTROYED:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = new { Name = \"None\", Value = (long)-1 }.Yield().Concat(plugin.Map.Houses.Select(t => new { t.Type.Name, Value = (long)t.Type.ID })).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_BUILDING_EXISTS:\n                            case RedAlert.EventTypes.TEVENT_BUILD:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = plugin.Map.BuildingTypes.Select(t => new { Name = t.DisplayName, Value = (long)t.ID }).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_BUILD_UNIT:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = plugin.Map.UnitTypes.Where(t => t.IsUnit).Select(t => new { Name = t.DisplayName, Value = (long)t.ID }).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_BUILD_INFANTRY:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = plugin.Map.InfantryTypes.Select(t => new { Name = t.DisplayName, Value = (long)t.ID }).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_BUILD_AIRCRAFT:\n                                eventValueComboBox.Visible = true;\n                                eventValueComboBox.DisplayMember = \"Name\";\n                                eventValueComboBox.ValueMember = \"Value\";\n                                eventValueComboBox.DataSource = plugin.Map.UnitTypes.Where(t => t.IsAircraft).Select(t => new { Name = t.DisplayName, Value = (long)t.ID }).ToArray();\n                                eventValueComboBox.DataBindings.Add(\"SelectedValue\", triggerEvent, \"Data\");\n                                break;\n                            case RedAlert.EventTypes.TEVENT_NUNITS_DESTROYED:\n                            case RedAlert.EventTypes.TEVENT_NBUILDINGS_DESTROYED:\n                            case RedAlert.EventTypes.TEVENT_CREDITS:\n                            case RedAlert.EventTypes.TEVENT_TIME:\n                            case RedAlert.EventTypes.TEVENT_GLOBAL_SET:\n                            case RedAlert.EventTypes.TEVENT_GLOBAL_CLEAR:\n                                eventNud.Visible = true;\n                                eventNud.DataBindings.Add(\"Value\", triggerEvent, \"Data\");\n                                break;\n                            default:\n                                break;\n                        }\n                        break;\n                }\n            }\n\n            actionNud.Visible = false;\n            actionNud.DataBindings.Clear();\n            actionNud.Minimum = long.MinValue;\n            actionNud.Maximum = long.MaxValue;\n            actionValueComboBox.Visible = false;\n            actionValueComboBox.DataBindings.Clear();\n            actionValueComboBox.DataSource = null;\n            actionValueComboBox.DisplayMember = null;\n            actionValueComboBox.ValueMember = null;\n\n            if (triggerAction != null)\n            {\n                switch (plugin.GameType)\n                {\n                    case GameType.RedAlert:\n                        switch (actionComboBox.SelectedItem)\n                        {\n                            case RedAlert.ActionTypes.TACTION_CREATE_TEAM:\n                            case RedAlert.ActionTypes.TACTION_DESTROY_TEAM:\n                            case RedAlert.ActionTypes.TACTION_REINFORCEMENTS:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DataSource = plugin.Map.TeamTypes.Select(t => t.Name).ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedItem\", triggerAction, \"Team\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_WIN:\n                            case RedAlert.ActionTypes.TACTION_LOSE:\n                            case RedAlert.ActionTypes.TACTION_BEGIN_PRODUCTION:\n                            case RedAlert.ActionTypes.TACTION_FIRE_SALE:\n                            case RedAlert.ActionTypes.TACTION_AUTOCREATE:\n                            case RedAlert.ActionTypes.TACTION_ALL_HUNT:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = new { Name = \"None\", Value = (long)-1 }.Yield().Concat(plugin.Map.Houses.Select(t => new { t.Type.Name, Value = (long)t.Type.ID })).ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_FORCE_TRIGGER:\n                            case RedAlert.ActionTypes.TACTION_DESTROY_TRIGGER:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DataSource = plugin.Map.Triggers.Select(t => t.Name).ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedItem\", triggerAction, \"Trigger\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_DZ:\n                            case RedAlert.ActionTypes.TACTION_REVEAL_SOME:\n                            case RedAlert.ActionTypes.TACTION_REVEAL_ZONE:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = new { Name = \"None\", Value = (long)-1 }.Yield().Concat(plugin.Map.Waypoints.Select((t, i) => new { t.Name, Value = (long)i })).ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_1_SPECIAL:\n                            case RedAlert.ActionTypes.TACTION_FULL_SPECIAL:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.SpecialWeaponType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.SpecialWeaponType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_PLAY_MUSIC:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.ThemeType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.ThemeType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_PLAY_MOVIE:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.VQType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.VQType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_PLAY_SOUND:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.VocType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.VocType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_PLAY_SPEECH:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.VoxType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.VoxType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_PREFERRED_TARGET:\n                                actionValueComboBox.Visible = true;\n                                actionValueComboBox.DisplayMember = \"Name\";\n                                actionValueComboBox.ValueMember = \"Value\";\n                                actionValueComboBox.DataSource = Enum.GetValues(typeof(RedAlert.ActionDataTypes.QuarryType)).Cast<int>()\n                                    .Select(v => new { Name = Enum.GetName(typeof(RedAlert.ActionDataTypes.QuarryType), v), Value = (long)v })\n                                    .ToArray();\n                                actionValueComboBox.DataBindings.Add(\"SelectedValue\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_TEXT_TRIGGER:\n                                actionNud.Visible = true;\n                                actionNud.Minimum = 1;\n                                actionNud.Maximum = 209;\n                                actionNud.DataBindings.Add(\"Value\", triggerAction, \"Data\");\n                                break;\n                            case RedAlert.ActionTypes.TACTION_ADD_TIMER:\n                            case RedAlert.ActionTypes.TACTION_SUB_TIMER:\n                            case RedAlert.ActionTypes.TACTION_SET_TIMER:\n                            case RedAlert.ActionTypes.TACTION_SET_GLOBAL:\n                            case RedAlert.ActionTypes.TACTION_CLEAR_GLOBAL:\n                            case RedAlert.ActionTypes.TACTION_BASE_BUILDING:\n                                actionNud.Visible = true;\n                                actionNud.DataBindings.Add(\"Value\", triggerAction, \"Data\");\n                                break;\n                            default:\n                                break;\n                        }\n                        break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Dialogs/TriggersDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"triggersContextMenuStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Event/RenderEventArgs.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\n\nnamespace MobiusEditor.Event\n{\n    public class RenderEventArgs : EventArgs\n    {\n        public Graphics Graphics { get; private set; }\n\n        public ISet<Point> Cells { get; private set; }\n\n        public RenderEventArgs(Graphics graphics, ISet<Point> cells)\n        {\n            Graphics = graphics;\n            Cells = cells;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Event/UndoRedoEventArgs.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Model;\n\nnamespace MobiusEditor.Event\n{\n    public class UndoRedoEventArgs\n    {\n        public MapPanel MapPanel { get; private set; }\n\n        public Map Map { get; private set; }\n\n        public UndoRedoEventArgs(MapPanel mapPanel, Map map)\n        {\n            MapPanel = mapPanel;\n            Map = map;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Globals.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\nusing System.IO;\n\nnamespace MobiusEditor\n{\n    public static class Globals\n    {\n        static Globals()\n        {\n            TileScale = Properties.Settings.Default.Quality;\n        }\n\n        public const string TilesetsXMLPath = @\"DATA\\XML\\TILESETS.XML\";\n        public const string TexturesPath = @\"DATA\\ART\\TEXTURES\\SRGB\";\n        public const string MegafilePath = @\"DATA\";\n        public const string GameTextFilenameFormat = @\"DATA\\TEXT\\MASTERTEXTFILE_{0}.LOC\";\n\n        public const int OriginalTileWidth = 128;\n        public const int OriginalTileHeight = 128;\n        public static readonly Size OriginalTileSize = new Size(OriginalTileWidth, OriginalTileHeight);\n\n        public static int TileScale { get; set; }\n        public static int TileWidth => OriginalTileWidth / TileScale;\n        public static int TileHeight => OriginalTileHeight / TileScale;\n        public static Size TileSize => new Size(TileWidth, TileHeight);\n\n        public const int PixelWidth = 24;\n        public const int PixelHeight = 24;\n\n        public static readonly Size MapPreviewSize = new Size(512, 512);\n        public static readonly Size WorkshopPreviewSize = new Size(512, 512);\n\n        public static readonly string[] Edges = new string[] { \"North\", \"South\", \"West\", \"East\" };\n        public const int NumInfantryStops = 5;\n\n        public const int MaxTeamClasses = 5;\n        public const int MaxTeamMissions = 20;\n\n        public const long MaxMapSize = 131072;\n\n        public static MegafileManager TheMegafileManager;\n        public static TextureManager TheTextureManager;\n        public static TilesetManager TheTilesetManager;\n        public static TeamColorManager TheTeamColorManager;\n        public static GameTextManager TheGameTextManager;\n\n        public static readonly string RootSaveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), @\"CnCRemastered\\Local_Custom_Maps\");\n\n#if DEVELOPER\n        public static class Developer\n        {\n            public static bool ShowOverlapCells = false;\n        }\n#endif\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/IBrowsableType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Drawing;\n\nnamespace MobiusEditor.Interface\n{\n    public interface IBrowsableType\n    {\n        string DisplayName { get; }\n\n        Image Thumbnail { get; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/ICellOccupier.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Interface\n{\n    public interface ICellOccupier\n    {\n        bool[,] OccupyMask { get; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/ICellOverlapper.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Drawing;\n\nnamespace MobiusEditor.Interface\n{\n    public interface ICellOverlapper\n    {\n        Rectangle OverlapBounds { get; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/IGamePlugin.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\n\nnamespace MobiusEditor.Interface\n{\n    public enum FileType\n    {\n        None,\n        INI,\n        BIN,\n        MEG,\n        PGM\n    }\n\n    public enum GameType\n    {\n        None,\n        TiberianDawn,\n        RedAlert\n    }\n\n    public interface IGamePlugin : IDisposable\n    {\n        GameType GameType { get; }\n\n        Map Map { get; }\n\n        Image MapImage { get; }\n\n        bool Dirty { get; set; }\n\n        void New(string theater);\n\n        IEnumerable<string> Load(string path, FileType fileType);\n\n        bool Save(string path, FileType fileType);\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/INamedType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Interface\n{\n    public interface INamedType\n    {\n        string Name { get; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/ITechnoType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Interface\n{\n    public interface ITechnoType\n    {\n        sbyte ID { get; }\n\n        string Name { get; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/ITool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MobiusEditor.Interface\n{\n    public interface ITool : IDisposable\n    {\n        MapLayerFlag Layers { get; set; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Interface/IWidget.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MobiusEditor.Interface\n{\n    public interface IWidget : IDisposable\n    {\n        void Render(Graphics graphics);\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/License.txt",
    "content": "Electronic Arts Inc. released only TiberianDawn.dll, RedAlert.dll and \nthe Command & Conquer Map Editor and their corresponding source code \nunder the GPL V3 below, with additional terms at the bottom.\n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n\nADDITIONAL TERMS per GNU GPL Section 7\nNo trademark or publicity rights are granted. This license does NOT give you\nany right, title or interest in \"Command & Conquer\" or any other Electronic Arts trademark. You may not distribute any\nmodification of this program using any Electronic Arts trademark or claim any affiliation or association with Electronic Arts Inc.\nor its affiliates or their employees.\n\nAny propagation or conveyance of this program must include this copyright\nnotice and these terms.\n\nIf you convey this program (or any modifications of it) and assume\ncontractual liability for the program to recipients of it, you agree to\nindemnify Electronic Arts for any liability that those contractual\nassumptions impose on Electronic Arts.\n\nYou may not misrepresent the origins of this program; modified versions of\nthe program must be marked as such and not identified as the original program.\n\nThis disclaimer supplements the one included in the General Public License.\nTO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS PROGRAM IS\nPROVIDED TO YOU \"AS IS,\" WITH ALL FAULTS, WITHOUT WARRANTY OF ANY KIND, AND\nYOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF SATISFACTORY QUALITY AND\nPERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS DISCLAIMS ANY AND ALL EXPRESS,\nIMPLIED OR STATUTORY WARRANTIES, INCLUDING IMPLIED WARRANTIES OF\nMERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE,\nNONINFRINGEMENT OF THIRD PARTY RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A\nCOURSE OF DEALING, USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT\nAGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL\nMEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR\nERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE WITH THIRD PARTY SOFTWARE\nOR THAT ANY ERRORS IN THE PROGRAM WILL BE CORRECTED. NO ORAL OR WRITTEN ADVICE\nPROVIDED BY ELECTRONIC ARTS OR ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A\nWARRANTY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON\nIMPLIED WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A\nCONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY NOT APPLY\nTO YOU.\n"
  },
  {
    "path": "CnCTDRAMapEditor/MainForm.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor\n{\n    partial class MainForm\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                activeTool?.Dispose();\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));\n            this.mainMenuStrip = new System.Windows.Forms.MenuStrip();\n            this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.fileNewMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.fileOpenMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.fileSaveMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.fileSaveAsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();\n            this.fileExportMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.filePublishMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();\n            this.fileRecentFilesMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();\n            this.fileExitMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.editUndoMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.editRedoMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.settingsMapSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.settingsTeamTypesMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.settingsTriggersMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.layersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersBoundariesMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersOverlayMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersTerrainMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersWaypointsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersObjectTriggersMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.viewLayersCellTriggersMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.developerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.developerGenerateMapPreviewMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.developerGenerateMapPreviewDirectoryMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.developerGoToINIMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();\n            this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.developerDebugShowOverlapCellsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.mainStatusStrip = new System.Windows.Forms.StatusStrip();\n            this.toolStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();\n            this.cellStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();\n            this.mouseToolTip = new System.Windows.Forms.ToolTip(this.components);\n            this.mainToolStrip = new System.Windows.Forms.ToolStrip();\n            this.mapToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.smudgeToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.overlayToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.terrainToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.infantryToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.unitToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.buildingToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.resourcesToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.wallsToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.waypointsToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.cellTriggersToolStripButton = new System.Windows.Forms.ToolStripButton();\n            this.mapPanel = new MobiusEditor.Controls.MapPanel();\n            this.copyrightStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();\n            this.mainMenuStrip.SuspendLayout();\n            this.mainStatusStrip.SuspendLayout();\n            this.mainToolStrip.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // mainMenuStrip\n            // \n            this.mainMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.fileToolStripMenuItem,\n            this.editToolStripMenuItem,\n            this.settingsToolStripMenuItem,\n            this.viewToolStripMenuItem,\n            this.developerToolStripMenuItem});\n            this.mainMenuStrip.Location = new System.Drawing.Point(0, 0);\n            this.mainMenuStrip.Name = \"mainMenuStrip\";\n            this.mainMenuStrip.Padding = new System.Windows.Forms.Padding(8, 2, 0, 2);\n            this.mainMenuStrip.Size = new System.Drawing.Size(1369, 28);\n            this.mainMenuStrip.TabIndex = 1;\n            this.mainMenuStrip.Text = \"menuStrip1\";\n            // \n            // fileToolStripMenuItem\n            // \n            this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.fileNewMenuItem,\n            this.fileOpenMenuItem,\n            this.fileSaveMenuItem,\n            this.fileSaveAsMenuItem,\n            this.toolStripMenuItem4,\n            this.fileExportMenuItem,\n            this.filePublishMenuItem,\n            this.toolStripMenuItem3,\n            this.fileRecentFilesMenuItem,\n            this.toolStripMenuItem1,\n            this.fileExitMenuItem});\n            this.fileToolStripMenuItem.Name = \"fileToolStripMenuItem\";\n            this.fileToolStripMenuItem.Size = new System.Drawing.Size(44, 24);\n            this.fileToolStripMenuItem.Text = \"&File\";\n            // \n            // fileNewMenuItem\n            // \n            this.fileNewMenuItem.Name = \"fileNewMenuItem\";\n            this.fileNewMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileNewMenuItem.Text = \"&New...\";\n            this.fileNewMenuItem.Click += new System.EventHandler(this.fileNewMenuItem_Click);\n            // \n            // fileOpenMenuItem\n            // \n            this.fileOpenMenuItem.Name = \"fileOpenMenuItem\";\n            this.fileOpenMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileOpenMenuItem.Text = \"&Open...\";\n            this.fileOpenMenuItem.Click += new System.EventHandler(this.fileOpenMenuItem_Click);\n            // \n            // fileSaveMenuItem\n            // \n            this.fileSaveMenuItem.Name = \"fileSaveMenuItem\";\n            this.fileSaveMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileSaveMenuItem.Text = \"&Save\";\n            this.fileSaveMenuItem.Click += new System.EventHandler(this.fileSaveMenuItem_Click);\n            // \n            // fileSaveAsMenuItem\n            // \n            this.fileSaveAsMenuItem.Name = \"fileSaveAsMenuItem\";\n            this.fileSaveAsMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileSaveAsMenuItem.Text = \"Save &As...\";\n            this.fileSaveAsMenuItem.Click += new System.EventHandler(this.fileSaveAsMenuItem_Click);\n            // \n            // toolStripMenuItem4\n            // \n            this.toolStripMenuItem4.Name = \"toolStripMenuItem4\";\n            this.toolStripMenuItem4.Size = new System.Drawing.Size(159, 6);\n            // \n            // fileExportMenuItem\n            // \n            this.fileExportMenuItem.Name = \"fileExportMenuItem\";\n            this.fileExportMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileExportMenuItem.Text = \"&Export...\";\n            this.fileExportMenuItem.Click += new System.EventHandler(this.fileExportMenuItem_Click);\n            // \n            // filePublishMenuItem\n            // \n            this.filePublishMenuItem.Name = \"filePublishMenuItem\";\n            this.filePublishMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.filePublishMenuItem.Text = \"&Publish...\";\n            this.filePublishMenuItem.Click += new System.EventHandler(this.filePublishMenuItem_Click);\n            // \n            // toolStripMenuItem3\n            // \n            this.toolStripMenuItem3.Name = \"toolStripMenuItem3\";\n            this.toolStripMenuItem3.Size = new System.Drawing.Size(159, 6);\n            // \n            // fileRecentFilesMenuItem\n            // \n            this.fileRecentFilesMenuItem.Name = \"fileRecentFilesMenuItem\";\n            this.fileRecentFilesMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileRecentFilesMenuItem.Text = \"&Recent Files\";\n            // \n            // toolStripMenuItem1\n            // \n            this.toolStripMenuItem1.Name = \"toolStripMenuItem1\";\n            this.toolStripMenuItem1.Size = new System.Drawing.Size(159, 6);\n            // \n            // fileExitMenuItem\n            // \n            this.fileExitMenuItem.Name = \"fileExitMenuItem\";\n            this.fileExitMenuItem.Size = new System.Drawing.Size(162, 26);\n            this.fileExitMenuItem.Text = \"&Exit\";\n            this.fileExitMenuItem.Click += new System.EventHandler(this.fileExitMenuItem_Click);\n            // \n            // editToolStripMenuItem\n            // \n            this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.editUndoMenuItem,\n            this.editRedoMenuItem});\n            this.editToolStripMenuItem.Name = \"editToolStripMenuItem\";\n            this.editToolStripMenuItem.Size = new System.Drawing.Size(47, 24);\n            this.editToolStripMenuItem.Text = \"&Edit\";\n            // \n            // editUndoMenuItem\n            // \n            this.editUndoMenuItem.Name = \"editUndoMenuItem\";\n            this.editUndoMenuItem.ShortcutKeyDisplayString = \"Ctrl + Z\";\n            this.editUndoMenuItem.Size = new System.Drawing.Size(179, 26);\n            this.editUndoMenuItem.Text = \"&Undo\";\n            this.editUndoMenuItem.Click += new System.EventHandler(this.editUndoMenuItem_Click);\n            // \n            // editRedoMenuItem\n            // \n            this.editRedoMenuItem.Name = \"editRedoMenuItem\";\n            this.editRedoMenuItem.ShortcutKeyDisplayString = \"Ctrl + Y\";\n            this.editRedoMenuItem.Size = new System.Drawing.Size(179, 26);\n            this.editRedoMenuItem.Text = \"&Redo\";\n            this.editRedoMenuItem.Click += new System.EventHandler(this.editRedoMenuItem_Click);\n            // \n            // settingsToolStripMenuItem\n            // \n            this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.settingsMapSettingsMenuItem,\n            this.settingsTeamTypesMenuItem,\n            this.settingsTriggersMenuItem});\n            this.settingsToolStripMenuItem.Name = \"settingsToolStripMenuItem\";\n            this.settingsToolStripMenuItem.Size = new System.Drawing.Size(74, 24);\n            this.settingsToolStripMenuItem.Text = \"&Settings\";\n            // \n            // settingsMapSettingsMenuItem\n            // \n            this.settingsMapSettingsMenuItem.Name = \"settingsMapSettingsMenuItem\";\n            this.settingsMapSettingsMenuItem.Size = new System.Drawing.Size(180, 26);\n            this.settingsMapSettingsMenuItem.Text = \"&Map Settings...\";\n            this.settingsMapSettingsMenuItem.Click += new System.EventHandler(this.settingsMapSettingsMenuItem_Click);\n            // \n            // settingsTeamTypesMenuItem\n            // \n            this.settingsTeamTypesMenuItem.Name = \"settingsTeamTypesMenuItem\";\n            this.settingsTeamTypesMenuItem.Size = new System.Drawing.Size(180, 26);\n            this.settingsTeamTypesMenuItem.Text = \"&Team Types...\";\n            this.settingsTeamTypesMenuItem.Click += new System.EventHandler(this.settingsTeamTypesMenuItem_Click);\n            // \n            // settingsTriggersMenuItem\n            // \n            this.settingsTriggersMenuItem.Name = \"settingsTriggersMenuItem\";\n            this.settingsTriggersMenuItem.Size = new System.Drawing.Size(180, 26);\n            this.settingsTriggersMenuItem.Text = \"T&riggers...\";\n            this.settingsTriggersMenuItem.Click += new System.EventHandler(this.settingsTriggersMenuItem_Click);\n            // \n            // viewToolStripMenuItem\n            // \n            this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.layersToolStripMenuItem});\n            this.viewToolStripMenuItem.Name = \"viewToolStripMenuItem\";\n            this.viewToolStripMenuItem.Size = new System.Drawing.Size(53, 24);\n            this.viewToolStripMenuItem.Text = \"&View\";\n            // \n            // layersToolStripMenuItem\n            // \n            this.layersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.viewLayersBoundariesMenuItem,\n            this.viewLayersOverlayMenuItem,\n            this.viewLayersTerrainMenuItem,\n            this.viewLayersWaypointsMenuItem,\n            this.viewLayersObjectTriggersMenuItem,\n            this.viewLayersCellTriggersMenuItem});\n            this.layersToolStripMenuItem.Name = \"layersToolStripMenuItem\";\n            this.layersToolStripMenuItem.Size = new System.Drawing.Size(125, 26);\n            this.layersToolStripMenuItem.Text = \"&Layers\";\n            // \n            // viewLayersBoundariesMenuItem\n            // \n            this.viewLayersBoundariesMenuItem.Checked = true;\n            this.viewLayersBoundariesMenuItem.CheckOnClick = true;\n            this.viewLayersBoundariesMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersBoundariesMenuItem.Name = \"viewLayersBoundariesMenuItem\";\n            this.viewLayersBoundariesMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersBoundariesMenuItem.Text = \"&Boundaries\";\n            this.viewLayersBoundariesMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // viewLayersOverlayMenuItem\n            // \n            this.viewLayersOverlayMenuItem.Checked = true;\n            this.viewLayersOverlayMenuItem.CheckOnClick = true;\n            this.viewLayersOverlayMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersOverlayMenuItem.Name = \"viewLayersOverlayMenuItem\";\n            this.viewLayersOverlayMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersOverlayMenuItem.Text = \"&Overlay\";\n            this.viewLayersOverlayMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // viewLayersTerrainMenuItem\n            // \n            this.viewLayersTerrainMenuItem.Checked = true;\n            this.viewLayersTerrainMenuItem.CheckOnClick = true;\n            this.viewLayersTerrainMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersTerrainMenuItem.Name = \"viewLayersTerrainMenuItem\";\n            this.viewLayersTerrainMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersTerrainMenuItem.Text = \"&Terrain\";\n            this.viewLayersTerrainMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // viewLayersWaypointsMenuItem\n            // \n            this.viewLayersWaypointsMenuItem.Checked = true;\n            this.viewLayersWaypointsMenuItem.CheckOnClick = true;\n            this.viewLayersWaypointsMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersWaypointsMenuItem.Name = \"viewLayersWaypointsMenuItem\";\n            this.viewLayersWaypointsMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersWaypointsMenuItem.Text = \"&Waypoints\";\n            this.viewLayersWaypointsMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // viewLayersObjectTriggersMenuItem\n            // \n            this.viewLayersObjectTriggersMenuItem.Checked = true;\n            this.viewLayersObjectTriggersMenuItem.CheckOnClick = true;\n            this.viewLayersObjectTriggersMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersObjectTriggersMenuItem.Name = \"viewLayersObjectTriggersMenuItem\";\n            this.viewLayersObjectTriggersMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersObjectTriggersMenuItem.Text = \"O&bject Triggers\";\n            this.viewLayersObjectTriggersMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // viewLayersCellTriggersMenuItem\n            // \n            this.viewLayersCellTriggersMenuItem.Checked = true;\n            this.viewLayersCellTriggersMenuItem.CheckOnClick = true;\n            this.viewLayersCellTriggersMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.viewLayersCellTriggersMenuItem.Name = \"viewLayersCellTriggersMenuItem\";\n            this.viewLayersCellTriggersMenuItem.Size = new System.Drawing.Size(185, 26);\n            this.viewLayersCellTriggersMenuItem.Text = \"&Cell Triggers\";\n            this.viewLayersCellTriggersMenuItem.CheckedChanged += new System.EventHandler(this.viewLayersMenuItem_CheckedChanged);\n            // \n            // developerToolStripMenuItem\n            // \n            this.developerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.developerGenerateMapPreviewMenuItem,\n            this.developerGoToINIMenuItem,\n            this.toolStripMenuItem2,\n            this.debugToolStripMenuItem});\n            this.developerToolStripMenuItem.Name = \"developerToolStripMenuItem\";\n            this.developerToolStripMenuItem.Size = new System.Drawing.Size(90, 24);\n            this.developerToolStripMenuItem.Text = \"&Developer\";\n            // \n            // developerGenerateMapPreviewMenuItem\n            // \n            this.developerGenerateMapPreviewMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.developerGenerateMapPreviewDirectoryMenuItem});\n            this.developerGenerateMapPreviewMenuItem.Name = \"developerGenerateMapPreviewMenuItem\";\n            this.developerGenerateMapPreviewMenuItem.Size = new System.Drawing.Size(234, 26);\n            this.developerGenerateMapPreviewMenuItem.Text = \"&Generate map preview\";\n            this.developerGenerateMapPreviewMenuItem.Click += new System.EventHandler(this.developerGenerateMapPreviewMenuItem_Click);\n            // \n            // developerGenerateMapPreviewDirectoryMenuItem\n            // \n            this.developerGenerateMapPreviewDirectoryMenuItem.Name = \"developerGenerateMapPreviewDirectoryMenuItem\";\n            this.developerGenerateMapPreviewDirectoryMenuItem.Size = new System.Drawing.Size(154, 26);\n            this.developerGenerateMapPreviewDirectoryMenuItem.Text = \"&Directory...\";\n            this.developerGenerateMapPreviewDirectoryMenuItem.Click += new System.EventHandler(this.developerGenerateMapPreviewDirectoryMenuItem_Click);\n            // \n            // developerGoToINIMenuItem\n            // \n            this.developerGoToINIMenuItem.Name = \"developerGoToINIMenuItem\";\n            this.developerGoToINIMenuItem.Size = new System.Drawing.Size(234, 26);\n            this.developerGoToINIMenuItem.Text = \"Go to &INI\";\n            this.developerGoToINIMenuItem.Click += new System.EventHandler(this.developerGoToINIMenuItem_Click);\n            // \n            // toolStripMenuItem2\n            // \n            this.toolStripMenuItem2.Name = \"toolStripMenuItem2\";\n            this.toolStripMenuItem2.Size = new System.Drawing.Size(231, 6);\n            // \n            // debugToolStripMenuItem\n            // \n            this.debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.developerDebugShowOverlapCellsMenuItem});\n            this.debugToolStripMenuItem.Name = \"debugToolStripMenuItem\";\n            this.debugToolStripMenuItem.Size = new System.Drawing.Size(234, 26);\n            this.debugToolStripMenuItem.Text = \"&Debug\";\n            // \n            // developerDebugShowOverlapCellsMenuItem\n            // \n            this.developerDebugShowOverlapCellsMenuItem.CheckOnClick = true;\n            this.developerDebugShowOverlapCellsMenuItem.Name = \"developerDebugShowOverlapCellsMenuItem\";\n            this.developerDebugShowOverlapCellsMenuItem.Size = new System.Drawing.Size(209, 26);\n            this.developerDebugShowOverlapCellsMenuItem.Text = \"Show &Overlap cells\";\n            this.developerDebugShowOverlapCellsMenuItem.CheckedChanged += new System.EventHandler(this.developerDebugShowOverlapCellsMenuItem_CheckedChanged);\n            // \n            // mainStatusStrip\n            // \n            this.mainStatusStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.mainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStatusLabel,\n            this.cellStatusLabel,\n            this.copyrightStatusLabel});\n            this.mainStatusStrip.Location = new System.Drawing.Point(0, 651);\n            this.mainStatusStrip.Name = \"mainStatusStrip\";\n            this.mainStatusStrip.Padding = new System.Windows.Forms.Padding(2, 0, 19, 0);\n            this.mainStatusStrip.Size = new System.Drawing.Size(1369, 25);\n            this.mainStatusStrip.TabIndex = 2;\n            this.mainStatusStrip.Text = \"statusStrip1\";\n            // \n            // toolStatusLabel\n            // \n            this.toolStatusLabel.Name = \"toolStatusLabel\";\n            this.toolStatusLabel.Size = new System.Drawing.Size(0, 20);\n            // \n            // cellStatusLabel\n            // \n            this.cellStatusLabel.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Left;\n            this.cellStatusLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Etched;\n            this.cellStatusLabel.Name = \"cellStatusLabel\";\n            this.cellStatusLabel.Size = new System.Drawing.Size(4, 20);\n            // \n            // mainToolStrip\n            // \n            this.mainToolStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            this.mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.mapToolStripButton,\n            this.smudgeToolStripButton,\n            this.overlayToolStripButton,\n            this.terrainToolStripButton,\n            this.infantryToolStripButton,\n            this.unitToolStripButton,\n            this.buildingToolStripButton,\n            this.resourcesToolStripButton,\n            this.wallsToolStripButton,\n            this.waypointsToolStripButton,\n            this.cellTriggersToolStripButton});\n            this.mainToolStrip.Location = new System.Drawing.Point(0, 28);\n            this.mainToolStrip.Name = \"mainToolStrip\";\n            this.mainToolStrip.Padding = new System.Windows.Forms.Padding(0, 0, 2, 0);\n            this.mainToolStrip.Size = new System.Drawing.Size(1369, 31);\n            this.mainToolStrip.TabIndex = 3;\n            this.mainToolStrip.Text = \"toolStrip1\";\n            this.mainToolStrip.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mainToolStrip_MouseMove);\n            // \n            // mapToolStripButton\n            // \n            this.mapToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"mapToolStripButton.Image\")));\n            this.mapToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.mapToolStripButton.Name = \"mapToolStripButton\";\n            this.mapToolStripButton.Size = new System.Drawing.Size(67, 28);\n            this.mapToolStripButton.Text = \"Map\";\n            this.mapToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // smudgeToolStripButton\n            // \n            this.smudgeToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"smudgeToolStripButton.Image\")));\n            this.smudgeToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.smudgeToolStripButton.Name = \"smudgeToolStripButton\";\n            this.smudgeToolStripButton.Size = new System.Drawing.Size(92, 28);\n            this.smudgeToolStripButton.Text = \"Smudge\";\n            this.smudgeToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // overlayToolStripButton\n            // \n            this.overlayToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"overlayToolStripButton.Image\")));\n            this.overlayToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.overlayToolStripButton.Name = \"overlayToolStripButton\";\n            this.overlayToolStripButton.Size = new System.Drawing.Size(87, 28);\n            this.overlayToolStripButton.Text = \"Overlay\";\n            this.overlayToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // terrainToolStripButton\n            // \n            this.terrainToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"terrainToolStripButton.Image\")));\n            this.terrainToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.terrainToolStripButton.Name = \"terrainToolStripButton\";\n            this.terrainToolStripButton.Size = new System.Drawing.Size(82, 28);\n            this.terrainToolStripButton.Text = \"Terrain\";\n            this.terrainToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // infantryToolStripButton\n            // \n            this.infantryToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"infantryToolStripButton.Image\")));\n            this.infantryToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.infantryToolStripButton.Name = \"infantryToolStripButton\";\n            this.infantryToolStripButton.Size = new System.Drawing.Size(87, 28);\n            this.infantryToolStripButton.Text = \"Infantry\";\n            this.infantryToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // unitToolStripButton\n            // \n            this.unitToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"unitToolStripButton.Image\")));\n            this.unitToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.unitToolStripButton.Name = \"unitToolStripButton\";\n            this.unitToolStripButton.Size = new System.Drawing.Size(70, 28);\n            this.unitToolStripButton.Text = \"Units\";\n            this.unitToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // buildingToolStripButton\n            // \n            this.buildingToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"buildingToolStripButton.Image\")));\n            this.buildingToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.buildingToolStripButton.Name = \"buildingToolStripButton\";\n            this.buildingToolStripButton.Size = new System.Drawing.Size(102, 28);\n            this.buildingToolStripButton.Text = \"Structures\";\n            this.buildingToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // resourcesToolStripButton\n            // \n            this.resourcesToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"resourcesToolStripButton.Image\")));\n            this.resourcesToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.resourcesToolStripButton.Name = \"resourcesToolStripButton\";\n            this.resourcesToolStripButton.Size = new System.Drawing.Size(103, 28);\n            this.resourcesToolStripButton.Text = \"Resources\";\n            this.resourcesToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // wallsToolStripButton\n            // \n            this.wallsToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"wallsToolStripButton.Image\")));\n            this.wallsToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.wallsToolStripButton.Name = \"wallsToolStripButton\";\n            this.wallsToolStripButton.Size = new System.Drawing.Size(72, 28);\n            this.wallsToolStripButton.Text = \"Walls\";\n            this.wallsToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // waypointsToolStripButton\n            // \n            this.waypointsToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"waypointsToolStripButton.Image\")));\n            this.waypointsToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.waypointsToolStripButton.Name = \"waypointsToolStripButton\";\n            this.waypointsToolStripButton.Size = new System.Drawing.Size(106, 28);\n            this.waypointsToolStripButton.Text = \"Waypoints\";\n            this.waypointsToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // cellTriggersToolStripButton\n            // \n            this.cellTriggersToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject(\"cellTriggersToolStripButton.Image\")));\n            this.cellTriggersToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;\n            this.cellTriggersToolStripButton.Name = \"cellTriggersToolStripButton\";\n            this.cellTriggersToolStripButton.Size = new System.Drawing.Size(119, 28);\n            this.cellTriggersToolStripButton.Text = \"Cell Triggers\";\n            this.cellTriggersToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);\n            // \n            // mapPanel\n            // \n            this.mapPanel.BackColor = System.Drawing.Color.Black;\n            this.mapPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.mapPanel.FocusOnMouseEnter = true;\n            this.mapPanel.Location = new System.Drawing.Point(0, 59);\n            this.mapPanel.MapImage = null;\n            this.mapPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.mapPanel.MaxZoom = 8;\n            this.mapPanel.MinZoom = 1;\n            this.mapPanel.Name = \"mapPanel\";\n            this.mapPanel.Quality = 2;\n            this.mapPanel.Size = new System.Drawing.Size(1369, 592);\n            this.mapPanel.TabIndex = 4;\n            this.mapPanel.Zoom = 1;\n            this.mapPanel.ZoomStep = 1;\n            this.mapPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mapPanel_MouseMove);\n            // \n            // copyrightStatusLabel\n            // \n            this.copyrightStatusLabel.Name = \"copyrightStatusLabel\";\n            this.copyrightStatusLabel.Size = new System.Drawing.Size(1305, 20);\n            this.copyrightStatusLabel.Spring = true;\n            this.copyrightStatusLabel.Text = \"©2020 Electronic Arts Inc.\";\n            this.copyrightStatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;\n            // \n            // MainForm\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(1369, 676);\n            this.Controls.Add(this.mapPanel);\n            this.Controls.Add(this.mainToolStrip);\n            this.Controls.Add(this.mainStatusStrip);\n            this.Controls.Add(this.mainMenuStrip);\n            this.Icon = ((System.Drawing.Icon)(resources.GetObject(\"$this.Icon\")));\n            this.KeyPreview = true;\n            this.MainMenuStrip = this.mainMenuStrip;\n            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.Name = \"MainForm\";\n            this.Text = \"CnC TDRA Map Editor\";\n            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;\n            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);\n            this.mainMenuStrip.ResumeLayout(false);\n            this.mainMenuStrip.PerformLayout();\n            this.mainStatusStrip.ResumeLayout(false);\n            this.mainStatusStrip.PerformLayout();\n            this.mainToolStrip.ResumeLayout(false);\n            this.mainToolStrip.PerformLayout();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n        private System.Windows.Forms.MenuStrip mainMenuStrip;\n        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem fileOpenMenuItem;\n        private System.Windows.Forms.StatusStrip mainStatusStrip;\n        private System.Windows.Forms.ToolStripStatusLabel cellStatusLabel;\n        private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem fileSaveAsMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;\n        private System.Windows.Forms.ToolStripMenuItem fileExitMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem fileNewMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem developerToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem developerGenerateMapPreviewMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem fileExportMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem developerGenerateMapPreviewDirectoryMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem settingsMapSettingsMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem editUndoMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem editRedoMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;\n        private System.Windows.Forms.ToolStripMenuItem debugToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem developerDebugShowOverlapCellsMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem filePublishMenuItem;\n        private System.Windows.Forms.ToolTip mouseToolTip;\n        private System.Windows.Forms.ToolStrip mainToolStrip;\n        private System.Windows.Forms.ToolStripButton mapToolStripButton;\n        private System.Windows.Forms.ToolStripButton smudgeToolStripButton;\n        private System.Windows.Forms.ToolStripButton overlayToolStripButton;\n        private System.Windows.Forms.ToolStripButton terrainToolStripButton;\n        private System.Windows.Forms.ToolStripButton infantryToolStripButton;\n        private System.Windows.Forms.ToolStripButton unitToolStripButton;\n        private System.Windows.Forms.ToolStripButton buildingToolStripButton;\n        private System.Windows.Forms.ToolStripButton resourcesToolStripButton;\n        private System.Windows.Forms.ToolStripButton wallsToolStripButton;\n        private System.Windows.Forms.ToolStripButton waypointsToolStripButton;\n        private Controls.MapPanel mapPanel;\n        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;\n        private System.Windows.Forms.ToolStripMenuItem fileRecentFilesMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem fileSaveMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;\n        private System.Windows.Forms.ToolStripMenuItem developerGoToINIMenuItem;\n        private System.Windows.Forms.ToolStripButton cellTriggersToolStripButton;\n        private System.Windows.Forms.ToolStripMenuItem settingsTeamTypesMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem settingsTriggersMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem layersToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersBoundariesMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersObjectTriggersMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersCellTriggersMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersWaypointsMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersTerrainMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem viewLayersOverlayMenuItem;\n        private System.Windows.Forms.ToolStripStatusLabel toolStatusLabel;\n        private System.Windows.Forms.ToolStripStatusLabel copyrightStatusLabel;\n    }\n}\n\n"
  },
  {
    "path": "CnCTDRAMapEditor/MainForm.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Dialogs;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Tools;\nusing MobiusEditor.Tools.Dialogs;\nusing MobiusEditor.Utility;\nusing Steamworks;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor\n{\n    public partial class MainForm : Form\n    {\n        [Flags]\n        private enum ToolType\n        {\n            None        = 0,\n            Map         = 1 << 0,\n            Smudge      = 1 << 1,\n            Overlay     = 1 << 2,\n            Terrain     = 1 << 3,\n            Infantry    = 1 << 4,\n            Unit        = 1 << 5,\n            Building    = 1 << 6,\n            Resources   = 1 << 7,\n            Wall        = 1 << 8,\n            Waypoint    = 1 << 9,\n            CellTrigger = 1 << 10\n        }\n\n        private static readonly ToolType[] toolTypes;\n\n        private ToolType availableToolTypes = ToolType.None;\n\n        private ToolType activeToolType = ToolType.None;\n        private ToolType ActiveToolType\n        {\n            get => activeToolType;\n            set\n            {\n                var firstAvailableTool = value;\n                if ((availableToolTypes & firstAvailableTool) == ToolType.None)\n                {\n                    var otherAvailableToolTypes = toolTypes.Where(t => (availableToolTypes & t) != ToolType.None);\n                    firstAvailableTool = otherAvailableToolTypes.Any() ? otherAvailableToolTypes.First() : ToolType.None;\n                }\n\n                if (activeToolType != firstAvailableTool)\n                {\n                    activeToolType = firstAvailableTool;\n                    RefreshActiveTool();\n                }\n            }\n        }\n\n        private MapLayerFlag activeLayers;\n        public MapLayerFlag ActiveLayers\n        {\n            get => activeLayers;\n            set\n            {\n                if (activeLayers != value)\n                {\n                    activeLayers = value;\n                    if (activeTool != null)\n                    {\n                        activeTool.Layers = ActiveLayers;\n                    }\n                }\n            }\n        }\n\n        private ITool activeTool;\n        private Form activeToolForm;\n\n        private IGamePlugin plugin;\n        private string filename;\n\n        private readonly MRU mru;\n\n        private readonly UndoRedoList<UndoRedoEventArgs> url = new UndoRedoList<UndoRedoEventArgs>();\n\n        private readonly Timer steamUpdateTimer = new Timer();\n\n        static MainForm()\n        {\n            toolTypes = ((IEnumerable<ToolType>)Enum.GetValues(typeof(ToolType))).Where(t => t != ToolType.None).ToArray();\n        }\n\n        public MainForm()\n        {\n            InitializeComponent();\n\n            mru = new MRU(\"Software\\\\Petroglyph\\\\CnCRemasteredEditor\", 10, fileRecentFilesMenuItem);\n            mru.FileSelected += Mru_FileSelected;\n\n            foreach (ToolStripButton toolStripButton in mainToolStrip.Items)\n            {\n                toolStripButton.MouseMove += mainToolStrip_MouseMove;\n            }\n\n#if !DEVELOPER\n            fileExportMenuItem.Visible = false;\n            developerToolStripMenuItem.Visible = false;\n#endif\n\n            url.Tracked += UndoRedo_Updated;\n            url.Undone += UndoRedo_Updated;\n            url.Redone += UndoRedo_Updated;\n            UpdateUndoRedo();\n\n            steamUpdateTimer.Interval = 500;\n            steamUpdateTimer.Tick += SteamUpdateTimer_Tick;\n        }\n\n        private void SteamUpdateTimer_Tick(object sender, EventArgs e)\n        {\n            if (SteamworksUGC.IsInit)\n            {\n                SteamworksUGC.Service();\n            }\n        }\n\n        protected override void OnLoad(EventArgs e)\n        {\n            base.OnLoad(e);\n\n            RefreshAvailableTools();\n            UpdateVisibleLayers();\n\n            filePublishMenuItem.Visible = SteamworksUGC.IsInit;\n\n            steamUpdateTimer.Start();\n        }\n\n        protected override void OnClosed(EventArgs e)\n        {\n            base.OnClosed(e);\n\n            steamUpdateTimer.Stop();\n            steamUpdateTimer.Dispose();\n        }\n\n        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)\n        {\n            if (keyData == Keys.Q)\n            {\n                mapToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.W)\n            {\n                smudgeToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.E)\n            {\n                overlayToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.R)\n            {\n                terrainToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.T)\n            {\n                infantryToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.Y)\n            {\n                unitToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.A)\n            {\n                buildingToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.S)\n            {\n                resourcesToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.D)\n            {\n                wallsToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.F)\n            {\n                waypointsToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == Keys.G)\n            {\n                cellTriggersToolStripButton.PerformClick();\n                return true;\n            }\n            else if (keyData == (Keys.Control | Keys.Z))\n            {\n                if (editUndoMenuItem.Enabled)\n                {\n                    editUndoMenuItem_Click(this, new EventArgs());\n                }\n                return true;\n            }\n            else if (keyData == (Keys.Control | Keys.Y))\n            {\n                if (editRedoMenuItem.Enabled)\n                {\n                    editRedoMenuItem_Click(this, new EventArgs());\n                }\n                return true;\n            }\n\n            return base.ProcessCmdKey(ref msg, keyData);\n        }\n\n        private void UpdateUndoRedo()\n        {\n            editUndoMenuItem.Enabled = url.CanUndo;\n            editRedoMenuItem.Enabled = url.CanRedo;\n        }\n\n        private void UndoRedo_Updated(object sender, EventArgs e)\n        {\n            UpdateUndoRedo();\n        }\n\n        private void fileNewMenuItem_Click(object sender, EventArgs e)\n        {\n            if (!PromptSaveMap())\n            {\n                return;\n            }\n\n            NewMapDialog nmd = new NewMapDialog();\n            if (nmd.ShowDialog() == DialogResult.OK)\n            {\n                if (plugin != null)\n                {\n                    plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;\n                    plugin.Dispose();\n                }\n                plugin = null;\n\n                Globals.TheTilesetManager.Reset();\n                Globals.TheTextureManager.Reset();\n\n                if (nmd.GameType == GameType.TiberianDawn)\n                {\n                    Globals.TheTeamColorManager.Reset();\n                    Globals.TheTeamColorManager.Load(@\"DATA\\XML\\CNCTDTEAMCOLORS.XML\");\n\n                    plugin = new TiberianDawn.GamePlugin();\n                    plugin.New(nmd.TheaterName);\n                }\n                else if (nmd.GameType == GameType.RedAlert)\n                {\n                    Globals.TheTeamColorManager.Reset();\n                    Globals.TheTeamColorManager.Load(@\"DATA\\XML\\CNCRATEAMCOLORS.XML\");\n\n                    plugin = new RedAlert.GamePlugin();\n                    plugin.New(nmd.TheaterName);\n                }\n\n                if (SteamworksUGC.IsInit)\n                {\n                    plugin.Map.BasicSection.Author = SteamFriends.GetPersonaName();\n                }\n\n                plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;\n                mapPanel.MapImage = plugin.MapImage;\n\n                filename = null;\n                Text = \"CnC TDRA Map Editor\";\n                url.Clear();\n\n                ClearActiveTool();\n                RefreshAvailableTools();\n                RefreshActiveTool();\n            }\n        }\n\n        private void fileOpenMenuItem_Click(object sender, EventArgs e)\n        {\n            if (!PromptSaveMap())\n            {\n                return;\n            }\n\n            var pgmFilter =\n#if DEVELOPER\n                \"|PGM files (*.pgm)|*.pgm\"\n#else\n                string.Empty\n#endif\n            ;\n\n            OpenFileDialog ofd = new OpenFileDialog\n            {\n                AutoUpgradeEnabled = false,\n                RestoreDirectory = true\n            };\n            ofd.Filter = \"Tiberian Dawn files (*.ini;*.bin)|*.ini;*.bin|Red Alert files (*.mpr)|*.mpr\" + pgmFilter  + \"|All files (*.*)|*.*\";\n            if (plugin != null)\n            {\n                switch (plugin.GameType)\n                {\n                    case GameType.TiberianDawn:\n                        ofd.InitialDirectory = TiberianDawn.Constants.SaveDirectory;\n                        ofd.FilterIndex = 1;\n                        break;\n                    case GameType.RedAlert:\n                        ofd.InitialDirectory = RedAlert.Constants.SaveDirectory;\n                        ofd.FilterIndex = 2;\n                        break;\n                }\n            }\n            else\n            {\n                ofd.InitialDirectory = Globals.RootSaveDirectory;\n            }\n            if (ofd.ShowDialog() == DialogResult.OK)\n            {\n                var fileInfo = new FileInfo(ofd.FileName);\n                if (LoadFile(fileInfo.FullName))\n                {\n                    mru.Add(fileInfo);\n                }\n                else\n                {\n                    mru.Remove(fileInfo);\n                    MessageBox.Show(string.Format(\"Error loading {0}.\", ofd.FileName), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n                }\n            }\n        }\n\n        private void fileSaveMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            if (string.IsNullOrEmpty(filename))\n            {\n                fileSaveAsMenuItem.PerformClick();\n            }\n            else\n            {\n                var fileInfo = new FileInfo(filename);\n                if (SaveFile(fileInfo.FullName))\n                {\n                    mru.Add(fileInfo);\n                }\n                else\n                {\n                    mru.Remove(fileInfo);\n                }\n            }\n        }\n\n        private void fileSaveAsMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            SaveFileDialog sfd = new SaveFileDialog\n            {\n                AutoUpgradeEnabled = false,\n                RestoreDirectory = true\n            };\n            var filters = new List<string>();\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    filters.Add(\"Tiberian Dawn files (*.ini;*.bin)|*.ini;*.bin\");\n                    sfd.InitialDirectory = TiberianDawn.Constants.SaveDirectory;\n                    break;\n                case GameType.RedAlert:\n                    filters.Add(\"Red Alert files (*.mpr)|*.mpr\");\n                    sfd.InitialDirectory = RedAlert.Constants.SaveDirectory;\n                    break;\n            }\n            filters.Add(\"All files (*.*)|*.*\");\n\n            sfd.Filter = string.Join(\"|\", filters);\n            if (!string.IsNullOrEmpty(filename))\n            {\n                sfd.InitialDirectory = Path.GetDirectoryName(filename);\n                sfd.FileName = Path.GetFileName(filename);\n            }\n            if (sfd.ShowDialog() == DialogResult.OK)\n            {\n                var fileInfo = new FileInfo(sfd.FileName);\n                if (SaveFile(fileInfo.FullName))\n                {\n                    mru.Add(fileInfo);\n                }\n                else\n                {\n                    mru.Remove(fileInfo);\n                }\n            }\n        }\n\n        private void fileExportMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            SaveFileDialog sfd = new SaveFileDialog\n            {\n                AutoUpgradeEnabled = false,\n                RestoreDirectory = true\n            };\n            sfd.Filter = \"MEG files (*.meg)|*.meg\";\n            if (sfd.ShowDialog() == DialogResult.OK)\n            {\n                plugin.Save(sfd.FileName, FileType.MEG);\n            }\n        }\n\n        private void fileExitMenuItem_Click(object sender, EventArgs e)\n        {\n            Close();\n        }\n\n        private void editUndoMenuItem_Click(object sender, EventArgs e)\n        {\n            if (url.CanUndo)\n            {\n                url.Undo(new UndoRedoEventArgs(mapPanel, plugin.Map));\n            }\n        }\n\n        private void editRedoMenuItem_Click(object sender, EventArgs e)\n        {\n            if (url.CanRedo)\n            {\n                url.Redo(new UndoRedoEventArgs(mapPanel, plugin.Map));\n            }\n        }\n\n        private void settingsMapSettingsMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            var basicSettings = new PropertyTracker<BasicSection>(plugin.Map.BasicSection);\n            var briefingSettings = new PropertyTracker<BriefingSection>(plugin.Map.BriefingSection);\n            var houseSettingsTrackers = plugin.Map.Houses.ToDictionary(h => h, h => new PropertyTracker<House>(h));\n\n            MapSettingsDialog msd = new MapSettingsDialog(plugin, basicSettings, briefingSettings, houseSettingsTrackers);\n            if (msd.ShowDialog() == DialogResult.OK)\n            {\n                basicSettings.Commit();\n                briefingSettings.Commit();\n                foreach (var houseSettingsTracker in houseSettingsTrackers.Values)\n                {\n                    houseSettingsTracker.Commit();\n                }\n                plugin.Dirty = true;\n            }\n        }\n\n        private void settingsTeamTypesMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            int maxTeams = 0;\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    {\n                        maxTeams = TiberianDawn.Constants.MaxTeams;\n                    }\n                    break;\n                case GameType.RedAlert:\n                    {\n                        maxTeams = RedAlert.Constants.MaxTeams;\n                    }\n                    break;\n            }\n\n            TeamTypesDialog ttd = new TeamTypesDialog(plugin, maxTeams);\n            if (ttd.ShowDialog() == DialogResult.OK)\n            {\n                plugin.Map.TeamTypes.Clear();\n                plugin.Map.TeamTypes.AddRange(ttd.TeamTypes.Select(t => t.Clone()));\n                plugin.Dirty = true;\n            }\n        }\n\n        private void settingsTriggersMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            int maxTriggers = 0;\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    {\n                        maxTriggers = TiberianDawn.Constants.MaxTriggers;\n                    }\n                    break;\n                case GameType.RedAlert:\n                    {\n                        maxTriggers = RedAlert.Constants.MaxTriggers;\n                    }\n                    break;\n            }\n\n            TriggersDialog td = new TriggersDialog(plugin, maxTriggers);\n            if (td.ShowDialog() == DialogResult.OK)\n            {\n                var oldTriggers =\n                    from leftTrigger in plugin.Map.Triggers\n                    join rightTrigger in td.Triggers\n                    on leftTrigger.Name equals rightTrigger.Name into result\n                    where result.Count() == 0\n                    select leftTrigger;\n                var newTriggers =\n                    from leftTrigger in td.Triggers\n                    join rightTrigger in plugin.Map.Triggers\n                    on leftTrigger.Name equals rightTrigger.Name into result\n                    where result.Count() == 0\n                    select leftTrigger;\n                var sameTriggers =\n                    from leftTrigger in plugin.Map.Triggers\n                    join rightTrigger in td.Triggers\n                    on leftTrigger.Name equals rightTrigger.Name\n                    select new\n                    {\n                        OldTrigger = leftTrigger,\n                        NewTrigger = rightTrigger\n                    };\n\n                foreach (var oldTrigger in oldTriggers.ToArray())\n                {\n                    plugin.Map.Triggers.Remove(oldTrigger);\n                }\n\n                foreach (var newTrigger in newTriggers.ToArray())\n                {\n                    plugin.Map.Triggers.Add(newTrigger.Clone());\n                }\n\n                foreach (var item in sameTriggers.ToArray())\n                {\n                    plugin.Map.Triggers.Add(item.NewTrigger.Clone());\n                    plugin.Map.Triggers.Remove(item.OldTrigger);\n                }\n\n                plugin.Dirty = true;\n            }\n        }\n\n        private void Mru_FileSelected(object sender, FileInfo e)\n        {\n            if (!PromptSaveMap())\n            {\n                return;\n            }\n\n            if (LoadFile(e.FullName))\n            {\n                mru.Add(e);\n            }\n            else\n            {\n                mru.Remove(e);\n                MessageBox.Show(string.Format(\"Error loading {0}.\", e.FullName), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n        }\n\n        private void mapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (plugin != null)\n            {\n                var mapPoint = mapPanel.ClientToMap(e.Location);\n                var location = new Point((int)Math.Floor((double)mapPoint.X / Globals.TileWidth), (int)Math.Floor((double)mapPoint.Y / Globals.TileHeight));\n                if (plugin.Map.Metrics.GetCell(location, out int cell))\n                {\n                    var sb = new StringBuilder();\n                    sb.AppendFormat(\"X = {0}, Y = {1}, Cell = {2}\", location.X, location.Y, cell);\n\n                    var template = plugin.Map.Templates[cell];\n                    var templateType = template?.Type;  \n                    if (templateType != null)\n                    {\n                        sb.AppendFormat(\", Template = {0} ({1})\", templateType.DisplayName, template.Icon);\n                    }\n\n                    var smudge = plugin.Map.Smudge[cell];\n                    var smudgeType = smudge?.Type;\n                    if (smudgeType != null)\n                    {\n                        sb.AppendFormat(\", Smudge = {0}\", smudgeType.DisplayName);\n                    }\n\n                    var overlay = plugin.Map.Overlay[cell];\n                    var overlayType = overlay?.Type;\n                    if (overlayType != null)\n                    {\n                        sb.AppendFormat(\", Overlay = {0}\", overlayType.DisplayName);\n                    }\n\n                    var terrain = plugin.Map.Technos[location] as Terrain;\n                    var terrainType = terrain?.Type;\n                    if (terrainType != null)\n                    {\n                        sb.AppendFormat(\", Terrain = {0}\", terrainType.DisplayName);\n                    }\n\n                    if (plugin.Map.Technos[location] is InfantryGroup infantryGroup)\n                    {\n                        var subPixel = new Point(\n                            (mapPoint.X * Globals.PixelWidth / Globals.TileWidth) % Globals.PixelWidth,\n                            (mapPoint.Y * Globals.PixelHeight / Globals.TileHeight) % Globals.PixelHeight\n                        );\n\n                        var i = InfantryGroup.ClosestStoppingTypes(subPixel).Cast<int>().First();\n                        if (infantryGroup.Infantry[i] != null)\n                        {\n                            sb.AppendFormat(\", Infantry = {0}\", infantryGroup.Infantry[i].Type.DisplayName);\n                        }\n                    }\n\n                    var unit = plugin.Map.Technos[location] as Unit;\n                    var unitType = unit?.Type;\n                    if (unitType != null)\n                    {\n                        sb.AppendFormat(\", Unit = {0}\", unitType.DisplayName);\n                    }\n\n                    var building = plugin.Map.Technos[location] as Building;\n                    var buildingType = building?.Type;\n                    if (buildingType != null)\n                    {\n                        sb.AppendFormat(\", Building = {0}\", buildingType.DisplayName);\n                    }\n\n                    cellStatusLabel.Text = sb.ToString();\n                }\n                else\n                {\n                    cellStatusLabel.Text = string.Empty;\n                }\n            }\n        }\n\n        private bool LoadFile(string loadFilename)\n        {\n            FileType fileType = FileType.None;\n            switch (Path.GetExtension(loadFilename).ToLower())\n            {\n                case \".ini\":\n                case \".mpr\":\n                    fileType = FileType.INI;\n                    break;\n                case \".bin\":\n                    fileType = FileType.BIN;\n                    break;\n#if DEVELOPER\n                case \".pgm\":\n                    fileType = FileType.PGM;\n                    break;\n#endif\n            }\n\n            if (fileType == FileType.None)\n            {\n                return false;\n            }\n\n            GameType gameType = GameType.None;\n            switch (fileType)\n            {\n                case FileType.INI:\n                    {\n                        var ini = new INI();\n                        try\n                        {\n                            using (var reader = new StreamReader(loadFilename))\n                            {\n                                ini.Parse(reader);\n                            }\n                        }\n                        catch (FileNotFoundException)\n                        {\n                            return false;\n                        }\n                        gameType = File.Exists(Path.ChangeExtension(loadFilename, \".bin\")) ? GameType.TiberianDawn : GameType.RedAlert;\n                    }\n                    break;\n                case FileType.BIN:\n                    gameType = GameType.TiberianDawn;\n                    break;\n#if DEVELOPER\n                case FileType.PGM:\n                    {\n                        try\n                        {\n                            using (var megafile = new Megafile(loadFilename))\n                            {\n                                if (megafile.Any(f => Path.GetExtension(f).ToLower() == \".mpr\"))\n                                {\n                                    gameType = GameType.RedAlert;\n                                }\n                                else\n                                {\n                                    gameType = GameType.TiberianDawn;\n                                }\n                            }\n                        }\n                        catch (FileNotFoundException)\n                        {\n                            return false;\n                        }\n                    }\n                    break;\n#endif\n            }\n\n            if (gameType == GameType.None)\n            {\n                return false;\n            }\n\n            if (plugin != null)\n            {\n                plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;\n                plugin.Dispose();\n            }\n            plugin = null;\n\n            Globals.TheTilesetManager.Reset();\n            Globals.TheTextureManager.Reset();\n\n            switch (gameType)\n            {\n                case GameType.TiberianDawn:\n                    {\n                        Globals.TheTeamColorManager.Reset();\n                        Globals.TheTeamColorManager.Load(@\"DATA\\XML\\CNCTDTEAMCOLORS.XML\");\n                        plugin = new TiberianDawn.GamePlugin();\n                    }\n                    break;\n                case GameType.RedAlert:\n                    {\n                        Globals.TheTeamColorManager.Reset();\n                        Globals.TheTeamColorManager.Load(@\"DATA\\XML\\CNCRATEAMCOLORS.XML\");\n                        plugin = new RedAlert.GamePlugin();\n                    }\n                    break;\n            }\n\n            try\n            {\n                var errors = plugin.Load(loadFilename, fileType).ToArray();\n                if (errors.Length > 0)\n                {\n                    ErrorMessageBox errorMessageBox = new ErrorMessageBox { Errors = errors };\n                    errorMessageBox.ShowDialog();\n                }\n            }\n            catch (Exception)\n            {\n#if DEVELOPER\n                throw;\n#else\n                return false;\n#endif\n            }\n\n            plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;\n            mapPanel.MapImage = plugin.MapImage;\n\n            plugin.Dirty = false;\n            filename = loadFilename;\n            Text = string.Format(\"CnC TDRA Map Editor - {0}\", filename);\n\n            url.Clear();\n\n            ClearActiveTool();\n            RefreshAvailableTools();\n            RefreshActiveTool();\n\n            return true;\n        }\n\n        private bool SaveFile(string saveFilename)\n        {\n            FileType fileType = FileType.None;\n            switch (Path.GetExtension(saveFilename).ToLower())\n            {\n                case \".ini\":\n                case \".mpr\":\n                    fileType = FileType.INI;\n                    break;\n                case \".bin\":\n                    fileType = FileType.BIN;\n                    break;\n            }\n\n            if (fileType == FileType.None)\n            {\n                return false;\n            }\n\n            if (string.IsNullOrEmpty(plugin.Map.SteamSection.Title))\n            {\n                plugin.Map.SteamSection.Title = plugin.Map.BasicSection.Name;\n            }\n\n            if (!plugin.Save(saveFilename, fileType))\n            {\n                return false;\n            }\n\n            if (new FileInfo(saveFilename).Length > Globals.MaxMapSize)\n            {\n                MessageBox.Show(string.Format(\"Map file exceeds the maximum size of {0} bytes.\", Globals.MaxMapSize), \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n\n            plugin.Dirty = false;\n            filename = saveFilename;\n            Text = string.Format(\"CnC TDRA Map Editor - {0}\", filename);\n\n            return true;\n        }\n\n        private void RefreshAvailableTools()\n        {\n            availableToolTypes = ToolType.None;\n            if (plugin != null)\n            {\n                availableToolTypes |= ToolType.Waypoint;\n\n                if (plugin.Map.TemplateTypes.Any()) availableToolTypes |= ToolType.Map;\n                if (plugin.Map.SmudgeTypes.Any()) availableToolTypes |= ToolType.Smudge;\n                if (plugin.Map.OverlayTypes.Any(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater)))) availableToolTypes |= ToolType.Overlay;\n                if (plugin.Map.TerrainTypes.Any(t => t.Theaters.Contains(plugin.Map.Theater))) availableToolTypes |= ToolType.Terrain;\n                if (plugin.Map.InfantryTypes.Any()) availableToolTypes |= ToolType.Infantry;\n                if (plugin.Map.UnitTypes.Any()) availableToolTypes |= ToolType.Unit;\n                if (plugin.Map.BuildingTypes.Any()) availableToolTypes |= ToolType.Building;\n                if (plugin.Map.OverlayTypes.Any(t => t.IsResource)) availableToolTypes |= ToolType.Resources;\n                if (plugin.Map.OverlayTypes.Any(t => t.IsWall)) availableToolTypes |= ToolType.Wall;\n                if (plugin.Map.Triggers.Any()) availableToolTypes |= ToolType.CellTrigger;\n            }\n\n            mapToolStripButton.Enabled = (availableToolTypes & ToolType.Map) != ToolType.None;\n            smudgeToolStripButton.Enabled = (availableToolTypes & ToolType.Smudge) != ToolType.None;\n            overlayToolStripButton.Enabled = (availableToolTypes & ToolType.Overlay) != ToolType.None;\n            terrainToolStripButton.Enabled = (availableToolTypes & ToolType.Terrain) != ToolType.None;\n            infantryToolStripButton.Enabled = (availableToolTypes & ToolType.Infantry) != ToolType.None;\n            unitToolStripButton.Enabled = (availableToolTypes & ToolType.Unit) != ToolType.None;\n            buildingToolStripButton.Enabled = (availableToolTypes & ToolType.Building) != ToolType.None;\n            resourcesToolStripButton.Enabled = (availableToolTypes & ToolType.Resources) != ToolType.None;\n            wallsToolStripButton.Enabled = (availableToolTypes & ToolType.Wall) != ToolType.None;\n            waypointsToolStripButton.Enabled = (availableToolTypes & ToolType.Waypoint) != ToolType.None;\n            cellTriggersToolStripButton.Enabled = (availableToolTypes & ToolType.CellTrigger) != ToolType.None;\n\n            ActiveToolType = activeToolType;\n        }\n\n        private void ClearActiveTool()\n        {\n            activeTool?.Dispose();\n            activeTool = null;\n\n            if (activeToolForm != null)\n            {\n                activeToolForm.ResizeEnd -= ActiveToolForm_ResizeEnd;\n                activeToolForm.Close();\n                activeToolForm = null;\n            }\n\n            toolStatusLabel.Text = string.Empty;\n        }\n\n        private void RefreshActiveTool()\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            if (activeTool == null)\n            {\n                activeLayers = MapLayerFlag.None;\n            }\n\n            ClearActiveTool();\n\n            switch (ActiveToolType)\n            {\n                case ToolType.Map:\n                    {\n                        TemplateToolDialog toolDialog = new TemplateToolDialog();\n\n                        activeTool = new TemplateTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TemplateTypeListView, toolDialog.TemplateTypeMapPanel, mouseToolTip, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    } break;\n                case ToolType.Smudge:\n                    {\n                        GenericToolDialog toolDialog = new GenericToolDialog\n                        {\n                            Text = \"Smudge\"\n                        };\n\n                        toolDialog.GenericTypeComboBox.Types = plugin.Map.SmudgeTypes.Where(t => (t.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None).OrderBy(t => t.Name);\n\n                        activeTool = new SmudgeTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Overlay:\n                    {\n                        GenericToolDialog toolDialog = new GenericToolDialog\n                        {\n                            Text = \"Overlay\"\n                        };\n\n                        toolDialog.GenericTypeComboBox.Types = plugin.Map.OverlayTypes.Where(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))).OrderBy(t => t.Name);\n\n                        activeTool = new OverlaysTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Resources:\n                    {\n                        ResourcesToolDialog toolDialog = new ResourcesToolDialog();\n\n                        activeTool = new ResourcesTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TotalResourcesLbl, toolDialog.ResourceBrushSizeNud, toolDialog.GemsCheckBox, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Terrain:\n                    {\n                        TerrainToolDialog toolDialog = new TerrainToolDialog(plugin);\n\n                        toolDialog.TerrainTypeComboBox.Types = plugin.Map.TerrainTypes.Where(t => t.Theaters.Contains(plugin.Map.Theater)).OrderBy(t => t.Name);\n\n                        activeTool = new TerrainTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TerrainTypeComboBox, toolDialog.TerrainTypeMapPanel, toolDialog.TerrainProperties, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Infantry:\n                    {\n                        ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)\n                        {\n                            Text = \"Infantry\"\n                        };\n\n                        toolDialog.ObjectTypeComboBox.Types = plugin.Map.InfantryTypes.OrderBy(t => t.Name);\n\n                        activeTool = new InfantryTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Unit:\n                    {\n                        ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)\n                        {\n                            Text = \"Units\"\n                        };\n\n                        toolDialog.ObjectTypeComboBox.Types = plugin.Map.UnitTypes\n                            .Where(t => !t.IsFixedWing)\n                            .OrderBy(t => t.Name);\n\n                        activeTool = new UnitTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Building:\n                    {\n                        ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)\n                        {\n                            Text = \"Structures\"\n                        };\n\n                        toolDialog.ObjectTypeComboBox.Types = plugin.Map.BuildingTypes\n                            .Where(t => (t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))\n                            .OrderBy(t => t.IsFake)\n                            .ThenBy(t => t.Name);\n\n                        activeTool = new BuildingTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Wall:\n                    {\n                        GenericToolDialog toolDialog = new GenericToolDialog\n                        {\n                            Text = \"Walls\"\n                        };\n\n                        toolDialog.GenericTypeComboBox.Types = plugin.Map.OverlayTypes.Where(t => t.IsWall).OrderBy(t => t.Name);\n\n                        activeTool = new WallsTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.Waypoint:\n                    {\n                        WaypointsToolDialog toolDialog = new WaypointsToolDialog();\n\n                        toolDialog.WaypointCombo.DataSource = plugin.Map.Waypoints.Select(w => w.Name).ToArray();\n\n                        activeTool = new WaypointsTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.WaypointCombo, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n                case ToolType.CellTrigger:\n                    {\n                        CellTriggersToolDialog toolDialog = new CellTriggersToolDialog();\n\n                        toolDialog.TriggerCombo.DataSource = plugin.Map.Triggers.Select(t => t.Name).ToArray();\n\n                        activeTool = new CellTriggersTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TriggerCombo, plugin, url);\n                        activeToolForm = toolDialog;\n                        activeToolForm.Show(this);\n                    }\n                    break;\n            }\n\n            if (activeToolForm != null)\n            {\n                activeToolForm.ResizeEnd += ActiveToolForm_ResizeEnd;\n                clampActiveToolForm();\n            }\n\n            switch (plugin.GameType)\n            {\n                case GameType.TiberianDawn:\n                    mapPanel.MaxZoom = 8;\n                    mapPanel.ZoomStep = 1;\n                    break;\n                case GameType.RedAlert:\n                    mapPanel.MaxZoom = 16;\n                    mapPanel.ZoomStep = 2;\n                    break;\n            }\n\n            mapToolStripButton.Checked = ActiveToolType == ToolType.Map;\n            smudgeToolStripButton.Checked = ActiveToolType == ToolType.Smudge;\n            overlayToolStripButton.Checked = ActiveToolType == ToolType.Overlay;\n            terrainToolStripButton.Checked = ActiveToolType == ToolType.Terrain;\n            infantryToolStripButton.Checked = ActiveToolType == ToolType.Infantry;\n            unitToolStripButton.Checked = ActiveToolType == ToolType.Unit;\n            buildingToolStripButton.Checked = ActiveToolType == ToolType.Building;\n            resourcesToolStripButton.Checked = ActiveToolType == ToolType.Resources;\n            wallsToolStripButton.Checked = ActiveToolType == ToolType.Wall;\n            waypointsToolStripButton.Checked = ActiveToolType == ToolType.Waypoint;\n            cellTriggersToolStripButton.Checked = ActiveToolType == ToolType.CellTrigger;\n\n            Focus();\n\n            UpdateVisibleLayers();\n            mapPanel.Invalidate();\n        }\n\n        private void clampActiveToolForm()\n        {\n            if (activeToolForm == null)\n            {\n                return;\n            }\n\n            Rectangle bounds = activeToolForm.DesktopBounds;\n            Rectangle workingArea = Screen.FromControl(this).WorkingArea;\n            if (bounds.Right > workingArea.Right)\n            {\n                bounds.X = workingArea.Right - bounds.Width;\n            }\n            if (bounds.X < workingArea.Left)\n            {\n                bounds.X = workingArea.Left;\n            }\n            if (bounds.Bottom > workingArea.Bottom)\n            {\n                bounds.Y = workingArea.Bottom - bounds.Height;\n            }\n            if (bounds.Y < workingArea.Top)\n            {\n                bounds.Y = workingArea.Top;\n            }\n            activeToolForm.DesktopBounds = bounds;\n        }\n\n        private void ActiveToolForm_ResizeEnd(object sender, EventArgs e)\n        {\n            clampActiveToolForm();\n        }\n\n        private void Triggers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)\n        {\n            RefreshAvailableTools();\n        }\n\n        private void mainToolStripButton_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            if (sender == mapToolStripButton)\n            {\n                ActiveToolType = ToolType.Map;\n            }\n            else if (sender == smudgeToolStripButton)\n            {\n                ActiveToolType = ToolType.Smudge;\n            }\n            else if (sender == overlayToolStripButton)\n            {\n                ActiveToolType = ToolType.Overlay;\n            }\n            else if (sender == terrainToolStripButton)\n            {\n                ActiveToolType = ToolType.Terrain;\n            }\n            else if (sender == infantryToolStripButton)\n            {\n                ActiveToolType = ToolType.Infantry;\n            }\n            else if (sender == unitToolStripButton)\n            {\n                ActiveToolType = ToolType.Unit;\n            }\n            else if (sender == buildingToolStripButton)\n            {\n                ActiveToolType = ToolType.Building;\n            }\n            else if (sender == resourcesToolStripButton)\n            {\n                ActiveToolType = ToolType.Resources;\n            }\n            else if (sender == wallsToolStripButton)\n            {\n                ActiveToolType = ToolType.Wall;\n            }\n            else if (sender == waypointsToolStripButton)\n            {\n                ActiveToolType = ToolType.Waypoint;\n            }\n            else if (sender == cellTriggersToolStripButton)\n            {\n                ActiveToolType = ToolType.CellTrigger;\n            }\n        }\n\n        private void UpdateVisibleLayers()\n        {\n            MapLayerFlag layers = MapLayerFlag.All;\n            if (!viewLayersBoundariesMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.Boundaries;\n            }\n            if (!viewLayersOverlayMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.OverlayAll;\n            }\n            if (!viewLayersTerrainMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.Terrain;\n            }\n            if (!viewLayersWaypointsMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.Waypoints;\n            }\n            if (!viewLayersCellTriggersMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.CellTriggers;\n            }\n            if (!viewLayersObjectTriggersMenuItem.Checked)\n            {\n                layers &= ~MapLayerFlag.TechnoTriggers;\n            }\n            ActiveLayers = layers;\n        }\n\n        private void viewLayersMenuItem_CheckedChanged(object sender, EventArgs e)\n        {\n            UpdateVisibleLayers();\n        }\n\n        private void toolTabControl_Selected(object sender, TabControlEventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n        }\n\n        private void developerGenerateMapPreviewMenuItem_Click(object sender, EventArgs e)\n        {\n#if DEVELOPER\n            if ((plugin == null) || string.IsNullOrEmpty(filename))\n            {\n                return;\n            }\n\n            plugin.Map.GenerateMapPreview().Save(Path.ChangeExtension(filename, \".tga\"));\n#endif\n        }\n\n        private void developerGoToINIMenuItem_Click(object sender, EventArgs e)\n        {\n#if DEVELOPER\n            if ((plugin == null) || string.IsNullOrEmpty(filename))\n            {\n                return;\n            }\n\n            var path = Path.ChangeExtension(filename, \".mpr\");\n            if (!File.Exists(path))\n            {\n                path = Path.ChangeExtension(filename, \".ini\");\n            }\n\n            try\n            {\n                Process.Start(path);\n            }\n            catch (Win32Exception)\n            {\n                Process.Start(\"notepad.exe\", path);\n            }\n            catch (Exception) { }\n#endif\n        }\n\n        private void developerGenerateMapPreviewDirectoryMenuItem_Click(object sender, EventArgs e)\n        {\n#if DEVELOPER\n            FolderBrowserDialog fbd = new FolderBrowserDialog\n            {\n                ShowNewFolderButton = false\n            };\n            if (fbd.ShowDialog() == DialogResult.OK)\n            {\n                var extensions = new string[] { \".ini\", \".mpr\" };\n                foreach (var file in Directory.EnumerateFiles(fbd.SelectedPath).Where(file => extensions.Contains(Path.GetExtension(file).ToLower())))\n                {\n                    GameType gameType = GameType.None;\n\n                    var ini = new INI();\n                    using (var reader = new StreamReader(file))\n                    {\n                        ini.Parse(reader);\n                    }\n                    gameType = ini.Sections.Contains(\"MapPack\") ? GameType.RedAlert : GameType.TiberianDawn;\n\n                    if (gameType == GameType.None)\n                    {\n                        continue;\n                    }\n\n                    IGamePlugin plugin = null;\n                    switch (gameType)\n                    {\n                        case GameType.TiberianDawn:\n                            {\n                                plugin = new TiberianDawn.GamePlugin(false);\n                            }\n                            break;\n                        case GameType.RedAlert:\n                            {\n                                plugin = new RedAlert.GamePlugin(false);\n                            }\n                            break;\n                    }\n\n                    plugin.Load(file, FileType.INI);\n                    plugin.Map.GenerateMapPreview().Save(Path.ChangeExtension(file, \".tga\"));\n                    plugin.Dispose();\n                }\n            }\n#endif\n        }\n\n        private void developerDebugShowOverlapCellsMenuItem_CheckedChanged(object sender, EventArgs e)\n        {\n#if DEVELOPER\n            Globals.Developer.ShowOverlapCells = developerDebugShowOverlapCellsMenuItem.Checked;\n#endif\n        }\n\n        private void filePublishMenuItem_Click(object sender, EventArgs e)\n        {\n            if (plugin == null)\n            {\n                return;\n            }\n\n            if (!PromptSaveMap())\n            {\n                return;\n            }\n\n            if (plugin.Dirty)\n            {\n                MessageBox.Show(\"Map must be saved before publishing.\", \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n                return;\n            }\n\n            if (new FileInfo(filename).Length > Globals.MaxMapSize)\n            {\n                return;\n            }\n\n            using (var sd = new SteamDialog(plugin))\n            {\n                sd.ShowDialog();\n            }\n\n            fileSaveMenuItem.PerformClick();\n        }\n\n        private void mainToolStrip_MouseMove(object sender, MouseEventArgs e)\n        {\n            mainToolStrip.Focus();\n        }\n\n        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\n        {\n            e.Cancel = !PromptSaveMap();\n        }\n\n        private bool PromptSaveMap()\n        {\n            bool cancel = false;\n            if (plugin?.Dirty ?? false)\n            {\n                var message = string.IsNullOrEmpty(filename) ? \"Save new map?\" : string.Format(\"Save map '{0}'?\", filename);\n                var result = MessageBox.Show(message, \"Save\", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);\n                switch (result)\n                {\n                    case DialogResult.Yes:\n                        {\n                            if (string.IsNullOrEmpty(filename))\n                            {\n                                fileSaveAsMenuItem.PerformClick();\n                            }\n                            else\n                            {\n                                fileSaveMenuItem.PerformClick();\n                            }\n                        }\n                        break;\n                    case DialogResult.No:\n                        break;\n                    case DialogResult.Cancel:\n                        cancel = true;\n                        break;\n                }\n            }\n            return !cancel;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/MainForm.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"mainMenuStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n  <metadata name=\"mainStatusStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>152, 17</value>\n  </metadata>\n  <metadata name=\"mouseToolTip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>289, 17</value>\n  </metadata>\n  <metadata name=\"mainToolStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>418, 17</value>\n  </metadata>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"mapToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"smudgeToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"overlayToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"terrainToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"infantryToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"unitToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"buildingToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"resourcesToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"wallsToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"waypointsToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"cellTriggersToolStripButton.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\n        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG\n        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9\n        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw\n        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc\n        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9\n        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32\n        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo\n        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+\n        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D\n        TgDQASA1MVpwzwAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"$this.Icon\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        1v9Ebpz/RG+f/0qIzv9LitH/OGOS/ywzP/8sM0P/JSsy/yQqO/8hKDj/HyYt/iUsNu0WGrf/CAre/yUs\n        b/8ICtT/Fhqi/zlae/9VkdX/VI3N/0lsk/9FZYf/UX+y/1F/sv9FZoj/RWiO/1OMzf9Pi9D/OFp//y40\n        QP8tM0L/Jiwz/yYsPf8kKjj/HyYs8SYtMMkfJJ3/BQbp/yMpe/8RFLb/DA3K/zRGaf9SgbT/S2J8/0ZP\n        W/9FYX//UHaf/05znP9FYX//Rk9b/0xiff9RgLX/NEdb/zI3Rf8vNUH/Jyw1/yguP/8mLDn/ISguzict\n        LIkpL3X/Bwjo/xkcp/8hJoH/BAXl/yMpi/8/S1T/SE1W/0lYav9kls3/cKnn/3Os6v9lmND/SVhr/0hO\n        Vv89SVb/Nz5J/zg+Tf8vNTz/KzA7/yowQf8nLTb/IyowjyguMDovNU3oFhnM/wkL2/8oLW7/Exa8/wgK\n        2f8zN3b/RE1T/16Gr/94sOz/fLTu/3y18P97tPD/X4iz/0FKUv8+Q0v/QUZU/zo/S/8tMjj/MDVE/y0z\n        Qf8oLjXqJSwzPy85RQYvNTeeLzSN/wgJ6P8VF7T/LTJu/xAS0f8KC9n/MjeU/1Rnh/9pjKz/dJ7F/3Wf\n        xf9pi6z/UmWL/0VLcf9JTln/Q0hV/zM4P/8yN0P/MzhH/zA1P/8pLzWiLTZBBy81OwAuNDgxOT5P4CYp\n        vP8GBuj/Gx2h/zQ4dP8dH8f/Bgfm/xcXzP8xM67/P0Oi/z9Dov8uMK7/EhPP/xoczf9MUWn/OD1B/zY6\n        RP86Pk3/NjtH/y80OuMrMTg1KzE4ADhASgAQAAAANDk7ZD9EZfQkJsz/Bgfn/xcZr/83OnX/PUCe/ygp\n        0P8UFeP/DQ7m/w0O5v8VFuL/KCrM/zo9lP8+Qmf/SE1Z/0BEUv8+Q0//NjtC9S81O2j///8AMzpEAAAA\n        AAA4P0gANDxIBTk+QHdJTm/0MTTI/wsM6P8KC9L/HiCb/zw+hP9XWZX/YmSl/19iov9RVI7/Nzl9/xgZ\n        lv8QEc7/TlKg/0hNVf88QUj1Mzg+ezY9RwY2PUUAAAAAAAAAAAAAAAAAQEZPAD1FUQVARUdjT1Rm4UtP\n        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\n        KioaIiTfISt2/wUH6P8EBer/JC6L/yQtbP8FB+P/BAbo/yIri/85Q0//RE9d/zhkmP82esv/OX3O/zZ5\n        yP82ecb/NHfE/zN2wf83ZJb/RVFf/zU+Sf8jLDr/ISk9/yApO/8hKDD/Hycy/x4mOv8cIzj/HCUv/xkh\n        J+IcJCwwGB8mbR4mLvsXHbD/AQLv/w8Tz/8tOFj/EBW4/wEB8P8ZH6n/LzxL/0VOWP9NU1z/RlNi/zds\n        qv84e8n/O37L/z2Azf86fcr/O3Gu/0hUZP9OU1z/RU1Y/yo2Q/8kLDv/Iis//yMqOP8gJy3/HiY4/x0l\n        Of8dJTT/GiIp/BskK3UZICStIStG/w0Q1P8CAu7/Hiaf/yUuZf8FBuT/CArb/yw4ZP8yXYr/PVyB/0hP\n        WP9MUVn/PVp+/zh1uv88eL3/PHi8/zh0t/8/XoH/TFFZ/0ZMVv83Vnj/L1uK/yQtOf8kLD7/Iyw9/yIp\n        L/8fJjT/HiY6/x4mN/8dJS3/GyMqtRsiJNkiK2P/Bwjk/wUG6P8mMHT/GiCN/wEC8P8VGq//Kz5T/zl1\n        vP9Af8n/OGCP/zxPZP80QlH/Lklk/zBKZ/8vSWX/Lkhj/zRBUf85TGD/M1uH/z19xf86ecD/JzlN/yQr\n        Ov8kLD//JCs1/yAmL/8gJzv/Hyc6/x8nMf8cIyrfHCQl8SEpe/8EBer/CQve/yo0X/8SFq3/AQLv/x4k\n        hv8sSmj/PX7I/0aG0P9Bgcv/PXKu/zFKZf8+drX/RH2+/0F6uf8+drP/MElk/ztup/8+fsb/QoPM/0KE\n        zv8sS2z/Jy04/ycvQv8mLTn/IScu/yEpO/8fJzr/ICgz/xwjKfceJCb7HyeH/wME7P8MDtf/KzVZ/w4S\n        vP8CA+v/Iilx/zJWe/9Cgcn/S4nQ/0WDyf9DeLT/NVBs/0iEyf9PjdT/SYbK/0eBw/81Tmr/P3Os/0SD\n        yf9Hhs//R4nS/zBXgP8qMDr/KzNF/ykwPf8iKS//Iyo8/yEoO/8hKTT/HSQq/x8lJ/sgJ4n/AwTs/wwO\n        1f8rNFj/DhG+/wID6v8jKm7/NFl9/0aDyv9QjdL/SobL/0h7tf86VG//UozO/1eT2P9SjdH/TofH/zlT\n        bv9HerT/SYbL/0qIzv9KitH/MliC/ysxO/8tNEb/KjE+/yMpL/8kKzz/ISg7/yIpNP8dJCr/ICco8SQr\n        gv8EBer/Cwzb/yszWv8RFbT/AQLs/yEnff80U2//S4bK/1aR1P9RjND/UIO7/z5Wcf9YkdH/XJfa/1uW\n        2f9Wj8//PFVv/01/uP9RjdL/SoXI/0yJzv80VHb/LTM9/y40Rf8rMT3/JCkv/yYtPv8jKTz/Iik0/x4k\n        KvYhJynYKTBv/wcI5f8HCOP/KC9o/xkemP8AAe//GR2f/zNHV/9QiMj/XJfZ/1GBt/9KaIf/PUta/0Fd\n        fP9EYYH/Q2CA/0Ngf/88Sln/RmOB/1KDuv9WkNP/TYbH/zFFWv8wNUH/LzVG/ywyO/8kKjH/KC4//yUr\n        Pf8kKzT/HiQq3iIpLKssNFX/DhHZ/wME6v8hJov/Iypv/wME6P8MDsz/MDlU/0hzov9TeaP/RVFe/0hN\n        Vf9EVmr/T3mn/1eDsf9Tfqz/TXel/0NWa/9JTlb/SFNg/1F3of9Kdqj/LzdB/zM5R/8yOEf/KzE4/yYs\n        Nv8pL0H/Jiw9/yUsM/8gJy2zJSwyaywzPvscIL//AgPs/xUXvf8sM1H/DhHK/wEC6f8jKIz/N0VP/0ZP\n        Wv9JT1j/Rk1W/1N4oP9ro+H/cann/3St6v9tpuT/VXuk/0VMVv9JT1j/Rk9b/zRCUP83PEf/OD5N/zU7\n        SP8pLjP/LDE+/yowQf8oLjz/JSsx/CQrMnMrMzspKS8x3S0zj/8GBuj/CAni/ygtbP8jKIT/AwTp/wkL\n        1v80OWz/QEZI/0ZNVv9OZoH/bqTd/3Oq5f92ref/eLDr/3Wt6P9vpeD/TGaD/0ZMVv89Q0n/PEFI/z5E\n        Uv87QU//NDpB/ykuNf8wNUX/LDFB/ysxPP8kKjDhJy84LkBQYQIpLzOWNTxX/xcZ0/8DBOr/FRe6/zA2\n        T/8ZHbf/AAHs/xASzP89QXL/QkxT/1+Is/93run/fbXw/4K79P+Bu/P/f7jy/3qy7P9ijbn/P0pS/0BE\n        TP9FSlj/QkdW/zxBTP8rMTX/MTZC/zE2Rv8uNEL/LDI5/yYsM5wxPkwEMDc/AC41PTcwNjnoNTuZ/wgI\n        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\n        xf8CA+3/AwTs/wYI4v8uPH3/KzY8/xcdrv8BAu//AgPt/wYI4f8pNIH/MDxH/z5HVf9DUWH/M2GX/zZ6\n        y/83fM3/O3/R/zd8zf8zdsP/M3bD/zJ1wf8ydMH/MnXA/zBzvv80ZZn/RFNj/0BJVf8pMz7/Iis4/yEp\n        PP8hKT3/ICg8/yIqN/8gJir/Hycx/x4nOv8dJTr/HCQ4/xsjM/8eJy7/GCAm/xwkK34SGR4AGyQsDhkh\n        J7waIST/KTZ2/wYI5f8DBOv/AgPt/xkhuf8yPkX/Iitx/wUG5/8CA+3/AwTq/yMslP8xPUT/PkdS/01U\n        Xv9NU1z/RFBf/zZnn/81esn/NXjG/zd7yv86fcr/O33K/zl9y/83esX/N3rG/zZpof9FUmH/TVNc/01U\n        Xv9ASVT/KTI7/yMrOv8hKj3/ISk9/yApO/8kKzL/HyYq/x8oOP8dJTr/HCQ5/xsjNv8eJzH/GCAl/xoj\n        KcQeJzATGyMqOBceJOkhKzD/HSWn/wIC7f8DBOv/BAbm/y05gf8rNTz/Ehe8/wEC7/8BAu7/FBm8/zE9\n        TP8pN0X/Rk5Z/01TXf9MU13/TVJc/z9TbP83dLr/OHzJ/zl8yf88f8z/PoHO/zx/zP86fMb/O3nA/0NZ\n        dP9NUlv/TFNd/01TXf9FTVf/KThH/yYvOP8kLT7/JCw//yIrPv8jKzj/ICYq/yAnMv8eJjr/HSY6/xwk\n        Of8dJTP/HCQr/xohKO4eJy9BHCQrcBcdIvwoNEf/EBXL/wIC7P8CA+z/EBTO/zNAU/8jLGL/Bgfk/wID\n        7f8EBuP/LDZ1/zJBSf8vYZr/OFR0/0pQWP9NUlz/TVJc/0hPXP84Y5b/On7M/zl7xv8/gc3/P4HN/zl6\n        w/87fcj/Omeb/0lRXf9MUlz/TVNd/0VLU/8vSWX/MmWd/yUzP/8kLDf/JCw//yQsP/8jKz3/Iyow/x8m\n        K/8fJzj/HiY6/x4mOv8dJTX/Hygv/xkgJv4eJy98HCQrpRgfIv8rN2b/CArg/wMD6/8CAuz/Hyar/y45\n        Of8aIZj/AQLu/wEC7v8SF73/LzlD/zJPcP85fMr/PnzF/zVUd/9ASVP/Sk9X/0tRW/82TWn/NGCR/zVg\n        j/84ZJP/OGOU/zRejf81YZH/OFBr/0tRWv9ITlb/PEVO/y5MbP87esD/OX7L/ytLbf8jKS//JCs8/yQs\n        P/8jKz7/Ji44/x8lKP8gJzb/HiY6/x8mOv8eJTj/ISoz/xohJ/8eJi2vHSQrzRwjJf8oMoL/BAXp/wME\n        6v8DBOn/KTOI/ykyOP8RFcH/AQLu/wEC7P8iK47/KTI2/y5clP88fsv/RYfU/zx7xf80Y5n/M05s/zVB\n        T/8tOEP/KjxO/ys9T/8rPE7/KjtM/yk6S/8qO03/LThD/zI+S/8vSmb/L12Q/zp6wf9DhtD/PYHN/zNl\n        nf8jKzL/JS06/yQsP/8lLD//Ji48/yEnKv8gJzL/ICc7/yAoO/8eJjn/Iio1/xwjKf8dJSzWGyMp5iAo\n        Kv8kLZj/AgPr/wME6v8GCOL/Lzlt/yYuR/8KDdj/AQLt/wQG4/8rNWn/JTRB/zVws/8+f8r/SYnS/0GA\n        yf9Agcv/QoLK/zFPcP8wSWP/PXm8/0B8v/9Df8L/QXy+/z55u/8+erz/MUpm/zBLaf9Bgcn/PHvC/0GC\n        yv9Dhc7/Q4XQ/zx5vP8kM0H/Jy03/ycuQP8nLkH/Ji49/yMpLf8gJi//ISg7/yAoO/8fJjr/ISk1/x0k\n        Kv8cJCruHCIp9CIqLv8gKKj/AgPs/wME6v8KDdr/Mj1d/yMrV/8HCeL/AQLt/wgK1f8uN1L/JzxT/zp4\n        v/9Af8j/TIzU/0OByv9Dgcn/SYjR/zVTdf80TGf/RIPL/0iFy/9Pjtb/R4TJ/0WBxf9Fgsb/NE5q/zFM\n        af9Dg8n/P33C/0B/x/8/gMj/R4jR/z9/xv8nPlX/KC82/yoyQ/8pMUP/KC9A/yUsMf8hJy3/Iyo8/yEp\n        PP8gJzr/ISk2/x4lLP8cIyr8GyIo+yQsMf8dI67/AgPs/wMD6v8MD9X/Mj1V/yIpYf8FBuX/AQLt/wsO\n        y/8uN0f/K0Vh/z99xP9CgMf/T47V/0WCyP9Fgsf/SYfO/zVScv82Tmn/SofN/02L0f9PjtX/SYXJ/0eD\n        xv9IhMf/NlBt/zJMaf9Gg8j/RYLH/0iHzv9KitL/S4vT/0GCy/8qRmT/KS82/y00Rf8rM0T/KTFB/yct\n        NP8hJyz/JCs9/yIpPP8gJzv/ISk3/yAnLf8cIyn/HCIo+yUsMf8dI67/AgPs/wMD6v8ND9X/MjxT/yIp\n        Zf8EBub/AQLt/wwPyv8vOEX/LEZi/0F9w/9HhMr/UpDV/0qGzP9JhMn/TInO/zhUdP86U23/Uo/U/1OP\n        0/9Wk9j/UY3Q/06Iy/9Pisz/OlRw/zZRbf9MidD/SIXK/0iGzf9Ni9L/TIzT/0B+xf8rSGX/KjA2/y42\n        Rv8sM0X/KjFC/ycuNP8gJiv/JSs9/yIpPP8gJzr/ISk3/yAnLf8cIyn/HiUr8yUtMf8gJ67/AgPr/wMD\n        6v8MDtb/MTpU/yMrXv8FB+P/AQLs/woMz/8wOE3/LERb/0J8v/9IhMj/VpHU/0+Kzf9Lhcn/VZHV/zxY\n        d/87U2z/VZHV/1mU1/9altr/WJXZ/1SOz/9Ri8z/OlNu/zxWc/9Vktf/S4bK/0WAxP9Hg8j/T4zR/0WC\n        yP8rRV7/KzA3/y82Rv8tNEX/KjFB/yctM/8hJy3/Jy0//yQqPf8hKDv/Iik2/yAnLf8dJCv8ICYt5SUs\n        Lv8mLqL/AwPq/wQE6f8JC9//MDhh/ycvUP8ICt3/AQLs/wUH2/8vN13/KztI/0N7uf9Oic3/WpbY/1ON\n        z/9Ri87/WJXY/z9bef8/Vm//W5bZ/1qV2f9emdz/Xpre/1eS1f9bl9r/Pldz/zhSbf9Wk9f/VpHV/06I\n        yv9Khcf/TYnP/0aAwf8rPU7/LzQ8/y82Rv8tM0T/LDJC/yguM/8iJy7/Jy4//yUsPv8iKTv/JCo3/x8l\n        K/8eJSvtIikwzCMpK/8uNpL/BATp/wQE6P8GB+X/LDN2/yoxPv8OEc3/AQLr/wID5v8pMHn/LDY5/0Nz\n        qP9SjdH/XZja/1iS1P9Vjcz/UoCx/0BUaP87S1z/Sm6W/0xwmP9Ocpr/TXGZ/0twl/9Qdp7/PU9g/zlK\n        XP9Kdqf/WJHS/1WQ0/9Vj9L/TYnN/0J1rf8pMzz/MjdC/zA2Rv8uNEX/LTNB/yYsMP8kKTL/KC5A/yYs\n        Pv8kKjz/Ji04/x4kKv8fJi3UJS00oyAlJ/81Pnj/CAnj/wQF6P8DBOn/JSqW/ywzMv8YHa3/AQLs/wEC\n        7P8aH6P/Mjk6/zlaf/9Yk9f/ZJ/g/097rf9DV23/RU1W/0lPV/85Q07/MUJU/zRFV/81Rlj/NEVX/zND\n        Vf8wQFL/NkFM/0lQWP9HUFn/SV1y/056q/9cl9n/WJPW/zldg/8rMTX/MjhG/zE3R/8wNkf/LzVA/yMo\n        K/8nLDf/KS9A/yctP/8kKjz/KTA5/x4kKf8hKTCtKDA4bR8lKfs4QV7/ERPW/wME6f8DBOr/GRy9/y41\n        OP8lK37/AwTp/wIC6/8JC9D/Nj1a/y08Sf9RhcD/VHqk/0NNWf9ITVb/SU9Z/0hNVf9EYH//XZXR/2Sb\n        1/9ro9//Y5rW/1+V0P9cks//RGKD/0dNVf9JT1n/SU5X/0ZPW/9Qd6H/VYzJ/y09Tf8yNj7/NDpJ/zM5\n        Sf8yOEf/MTc+/yEmKv8qMD7/Ki9B/yctP/8lKzv/KjE5/x4kKv0kLTV5KzM8NiEnLegzO0P/Iie9/wID\n        6f8EBej/DA3c/y40XP8tNEv/DQ/S/wEC6v8BAun/IieW/zY+P/80SWD/RVBb/0pPWP9JT1n/SU9Z/0NL\n        Vv9UgLD/aKDe/2uj4P9wqOb/c6vn/2+n4/9rouD/V4S1/0FLVv9KT1n/SU9Z/0lPWP9GT1v/Nk1k/y80\n        Ov84Pkr/Nz1M/zY7S/80Okf/LTM3/yQpLv8uNEP/KjBB/ygtP/8nLTr/KC40/yEnLe0nMDk/LjhCDSct\n        NLkpLjD/Nj6W/wUG5/8FBef/BAXp/yQpmf8uNTL/Iiea/wIC6v8CA+n/BwnW/zg+bf80Ojr/QkhQ/0lQ\n        Wf9JT1n/RkxU/0hif/9sot7/bqTg/22k3/9yqeX/e7Pv/3Kq5v9vpuP/b6bi/0Zjgf9FSlL/SU9Z/0lP\n        Wf9ESlL/MDQ4/ztASf88QlH/O0FQ/zk/Tf83PUb/JSot/yswOv8vNUX/LDJC/yguPv8sMjz/JCku/yUr\n        MsIoMTsRLDM5ACwzO3AjKCv/QEhn/xMW1/8EBOj/BAXo/xET0v8uM07/MjhS/w8Sz/8BAur/AQLq/xMV\n        vv9DSmD/OD4//0NJUv9HTVb/RFht/2eZ0P93sOv/dazo/3Go4v97suv/ebLt/3Oq5f94sOv/eLDt/2eb\n        1P9BV23/RUtU/0VLVP80OT7/P0RM/0FHVP8+Q1L/O0FQ/zpATP8yODz/JCgt/zI3Rv8vNUT/LTJC/yow\n        Pv8vNT3/ISYr/ygvN3oqMDUALTU9AC84QScnLTPgNDo+/zI4r/8EBOj/BQbn/wUG6P8jJp3/LzQy/y81\n        g/8GB+P/AgPp/wEC6f8bHbX/S1Fl/z1CQv87SFf/ZZTH/3ix7f92ren/fbXu/3yz7P+Fv/b/hL70/3mx\n        6v+CvPP/frbx/3ew7/9qndH/OkpZ/zY6Pv8/REz/RUpX/0RKWP9ARlT/PEFP/zk/R/8lKiz/LzQ+/zQ5\n        SP8wNUT/LDFC/zA2Qf8rMDb/JSsx5SszPC4pMDkALzdAACs4RwEvNj6PJywv/0hQdf8UFtn/BAXn/wUG\n        5/8MDN3/Ki5o/zY8PP8pLaT/AwTo/wID6P8BAuj/GBq//01Ref9JUFD/Rllq/1+Frf91qN//f7bw/361\n        8P+CuvT/hb/3/3217/9+tfD/dqng/16Fr/9JXm7/SVBQ/0xRVf9HTFj/RktZ/0VKWP9CSFX/QEVP/y40\n        N/8oLTP/NzxL/zQ5SP8wNUX/LjRC/zQ7Q/8lKS7/KzI5mCcxPwMqMjwAAAAAADA3QAAyOkMtKzE34Dg+\n        Qv8+RKv/Bgfm/wYG5v8FBej/FBXI/yswS/8+Q0z/KSyx/wME6P8BAuj/AQLp/wwN1P88P6D/W15x/1JY\n        V/9MWWD/Vm2B/2B+nf9liaz/aIyu/2KCn/9Ua4H/TFhg/1FWVv9TVnT/PD+e/1dcdf9MUVj/R01a/0RJ\n        V/9CSFL/NTo//yYqLv84PUr/NzxL/zQ5SP8xNkX/NTtF/y0yOP8nLTPlLTU+NSw0PAAAAAAAAAAAAC83\n        QAAAABIAMjlBeiouM/1OVWj/KSzN/wQE5/8GBub/BQXo/xkat/8tMUT/REpT/zI1sP8HB+X/AQLo/wEC\n        6P8BAuX/FBbO/z0/r/9cX5P/Zml9/2Zpcf9jZmv/Y2Zr/2RncP9iZX3/VVeU/zQ2sv8PENT/AAHn/zE0\n        rv9ZXmP/SU5Z/0ZLVf84PUL/Jiot/zg9SP87QE7/OD1L/zU6Sf8zOET/Nz1E/ycsMf4uNT2DICs1ASwz\n        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\n        7f8DBO3/AgPw/wkM3/8gKaz/NEN5/ztLX/83RVD/MD1H/y07Rf8rOkb/KjpI/yk6Sf8sO0j/Lz1H/zNA\n        SP87S1X/QFBp/zVDh/8cJL3/Bgfp/xohxP84RlP/Hygu/x0mN/8dJjr/Iis4/x8mK/8dJCj/ISs0/x8o\n        Of8eJzv/HSY6/x0mOv8cJTr/GyM3/x0mMP8fKTD/Fh0j/xskK+IcJS0yGyQsAAAAAAAAAAAAAAAAACMt\n        NQA5RlQCGiIqiRoiKf8XHiP/NUVX/xYdwf8CAu7/AwTs/wME7P8CA+7/DA/U/zdJdv8qNjj/LjpL/xcd\n        tP8BAu7/AwPt/wME7f8DA+//BAXq/xkgt/81Q3X/NURU/yw4SP8nNkj/KEJf/ypQfv8sXJX/LWOl/yxl\n        qf8rZav/L2aq/zFjn/8rU4H/KURh/yo6S/8xP0r/Pk1e/zdEh/86SHH/JS8z/x4mM/8eJzv/Hic7/x0m\n        Ov8hKjj/HyYr/x4kKP8gKTP/Hic6/x0mO/8cJTr/HSU6/xwlOv8cJDT/ISsz/xkgJf8ZISf/GyMrligz\n        PwQhKzQAAAAAAAAAAAAcJCwAHCQsKRoiKd8UGiD/JzQ5/ys4jf8EBen/AwTs/wME7P8DBO3/BAbl/zA+\n        jv8vPUH/LDc//xsiq/8BAu7/AgPt/wMD7f8CAu//CArf/ygzkv84R17/KjZL/yU1Sf8pTXj/Lmaq/zN2\n        x/8yeMz/N3/T/zZ80P8ydsj/NXnM/zyD2f89hd7/NHvQ/y9zwf8sZaX/KU53/yc5TP8zQE3/LztH/yAo\n        Mf8fJzr/ICk9/yApPf8fJzv/HSU5/yIrN/8eJCf/HyYr/x8oNP8dJjr/Hic7/x0mOv8cJTn/HCQ4/xwl\n        MP8eKDD/FBsg/xsjKuYbJCwyGyMrAAAAAAAlLzcACw8SABoiKXkaISj/Fh0i/zNDWv8RFsv/AgPt/wME\n        6/8DBOz/AgPt/x4nsf85SVX/KDEy/yMtkP8DBOv/AgPt/wID7f8CAu//Cw3X/y88fv8zQlD/KDNH/ydA\n        XP8varD/NXnP/zN3y/81ecr/O4DT/z+F1/84ftL/M3fH/zuA0/87gdX/PIHW/zZ8zv80ecf/MnfE/zB1\n        w/8vbLD/KUVh/ygzQf8mLzz/Iis3/yApPP8iKj7/ISo+/yAoPf8fJzr/Iys1/x0iJf8gKC//Hic2/x4n\n        O/8eJzv/HCU5/xsjOP8bIjP/ICky/xgeJP8ZISf/GyMqhgAAAAAmMDcAHicvAB4mLhQaIinIFRsg/yYx\n        Nv8rOIz/BAXp/wME6/8DBOv/AgPt/woN1v85SnT/JzEy/ys2Zv8ICt3/AQLu/wID7P8BAu7/CQva/zA8\n        eP8xPUf/LjlK/0ZPW/8/UGT/L1+W/zZ6zP81ecr/OH3O/zuA0/87gNL/NHjJ/zJ0wf8ydcP/MXTA/zJ1\n        wf8xdMH/MnXC/zF0wP8vc7//M2ad/0FTZv9IUVz/MTxJ/yYvOv8iKzf/ISk8/yEpPf8hKj7/ICg9/x8o\n        OP8lLTP/HSIl/yApMv8eJzr/HiY6/x0lOf8cJDn/GyM3/xwlL/8fKC//Fh0j/xwkLNIdJS0bHicuABkg\n        JwAbIipIGiIo9RQaH/8yQU//Fh3B/wID7f8DBOv/AwTr/wID7P8lL6D/M0FG/yk0PP8VG7n/AQLv/wID\n        7P8CA+3/BAbk/yo2hP8zQEf/LTdE/0pSXf9OVF3/TFNd/z5LWv81ZZz/NnvK/zZ6y/82ecj/NnrK/zZ6\n        yP84esT/OHrF/zV6xv80d8L/M3W//zN1vv8zdsD/MmSa/0JRYP9NU13/TlNd/0pSXf8wOkX/Ji84/yEq\n        N/8hKT3/ISk9/yApPP8fJzv/Iyw5/yIoK/8fJir/ICg2/x4nO/8dJTr/HCQ5/xsjOP8aIjL/ICoy/xYd\n        Iv8aIin5HCQrVRggJwAAAAAAGiEojBceJP8cJCj/MD5y/wcJ4f8DBOv/AwTr/wMD7f8KDNf/Okpw/ygx\n        L/8mMHr/BAXo/wID7P8CA+z/AQLt/x4mof84RUv/KzQ9/0hQW/9NU13/TFNd/0xTXf9MVF7/Pk9k/zNs\n        rv82esj/NXjF/zd6x/87fs7/PX/N/z6Azv88gdD/PYPT/zp9x/88f8v/OnW5/0BUaf9NU13/TFNd/0xT\n        Xf9NU13/SVFc/y03QP8oMTn/Iys7/yIrPv8iKj7/ISk9/yApO/8mLjb/HSMl/yEpMv8eJjn/HSU6/x0l\n        Of8cJDj/HCM2/x4nMP8aIij/GB8l/xwlLJoxP0wDHiYtFBoiKMYUGh//KDM3/yMtm/8CAu3/AwTq/wME\n        6/8CAu3/Hiau/zZES/8oMTn/Exi9/wEC7/8CA+z/AQLu/w0Qy/82RFz/JzE4/yc4Sv9FTVf/TVNd/0xS\n        XP9MUl3/TFJc/0pSXf83Vnz/OXvH/zl8yf85fMj/OXzK/zx+y/8/gc7/PIDM/zl7x/84esL/O3zH/z1g\n        if9MUl3/TFJc/0xTXf9MUlz/TVNd/0JKU/8nOEr/JjA4/ycvOv8kLD//JC1A/yQsP/8iKj3/Iys4/yIo\n        K/8fJiv/Hyc3/x4mOv8eJjr/HSU5/xwkOP8cJDD/ICox/xYdIv8dJi3RHykyGxwkKzoaIijqFBof/y89\n        Sv8UGsD/AgLt/wME6v8DBOv/BAXk/zRBhf8qNDT/KDJm/wUH5P8CA+z/AgPs/wID6f8nMYj/NUFD/yk8\n        UP8uZqb/Mkpk/0pRWf9NU13/TFJc/0xSXP9NU13/Pktf/zlvrP86fcr/OXrE/zl6xP9Agcz/P4DL/zt8\n        xf83dr3/O33H/zhxsf9CUWT/TVNc/0xSXP9MUlz/TVNd/0NJUf8oPlT/M2yq/yc8Uf8jKzH/JCw6/yQs\n        P/8kLED/JCxA/yIrO/8mLjP/HSIk/yEpNP8fJjr/HiY6/x4mOv8dJTr/HCQz/yIrM/8XHSL/HSUs8B4n\n        L0YcJCxqGSAn+xkgI/8zQWb/Cgzb/wMD6/8DBOr/AgPs/w0Qzv87SWL/JS4t/x0ln/8BAu7/AgPr/wEC\n        7v8NEMn/NUJW/zE6Pv89ZpT/NnzM/zx4v/84UW3/QkhP/01SXP9NU13/TVNd/0RLWf80XIn/OnzF/zl4\n        v/87eb//QYDI/0B/yP86ecD/OHa7/z1+xv82YZD/Rk5Z/01TXf9NU13/TFJc/z1DSv8rQlr/N3O1/zqB\n        z/8wXY//ISgt/yUtNv8jKz3/Iys+/yQsP/8iKjz/Ji44/x8lJ/8gKC7/HiY4/x4mOv8eJjr/HiY6/x0l\n        N/8iKzT/GiEn/xsjKf0eJy94HSYtmRgfJP8fKCv/Lzt//wUG5/8DA+r/AwTq/wIC7f8cI7H/NEFH/ycw\n        PP8QFcj/AQLu/wID6/8BAu3/HyiZ/zI8Pf8jMEL/NG+0/zp9y/9ChdP/OnnC/y1ReP81Qk7/Q0lQ/0lP\n        V/9HT1z/Lz1N/y9EWf8wRFr/MEVa/zBFWv8wRFr/LkNY/y5CV/8vRFn/MD5O/0dOWv9HTVX/P0VL/zA7\n        Rv8nSW3/N3a8/0KH0/86fsn/NnW6/yY1Rv8jKS7/JCs7/yMrPv8kLD//Iys+/yYuPP8jKi3/HyUp/yAo\n        N/8fJzr/Hyc7/x8nO/8eJjn/ISo0/x4mLf8ZICb/Hicvpx8nLr8XHSP/JjAz/yYwmf8DA+z/AwTq/wME\n        6v8CA+r/KTOX/ys1M/8oMVn/Bwng/wID7P8CA+z/BAXj/y86cP8oLzD/J0Ro/zV2wP8+f8v/SIjU/0KD\n        z/87fMb/NGqo/y5ReP8tQVb/LjY+/yk1Qf8oO07/KTtO/yk7Tv8pOk3/KDpM/yc5S/8oOUv/KDtN/yk1\n        Qv8tNDv/Kz5R/ytNcf8wZZ//OHjA/0KEzf9Dhc//PH/K/zt/yv8rSm3/Iicq/yYuOv8kLD//JSw//yUt\n        QP8lLT3/Ji40/x0iJf8hKTX/ICc7/yEoPP8gJzv/HiY6/yAoNP8iKzP/GB8k/x8oMMseJi3aFhwg/y04\n        Pv8fJ6v/AgLs/wME6v8DBOr/AwTk/zM/gf8mLin/JS14/wME6v8CA+v/AQLt/woMzv82Qlb/IScu/y5Z\n        jv86fMf/Pn/J/0qL1P9Dg8z/P37G/0GBy/9Dg83/OnGv/yoyO/8yU3X/PXzB/z16vv9CgMb/Q4DE/0F9\n        wf8/e8D/PXm7/z99wf80VXn/KC81/z5yrf9Cg8z/O3rA/z59xf9Fhs//Q4bQ/0GDzv9Dh9P/MWGU/yEn\n        K/8nLjf/Ji4//yYuQP8mLkD/JSw9/ygvN/8dIiT/ISkz/yAnO/8hKDv/ICc7/x4mOv8fJzT/Iy00/xcd\n        Iv8eJy7lHycu6hUaH/8yPUb/GyG7/wIC7P8DBOn/AwTr/wcI3v85RnL/JCsn/yEpkP8BAu3/AgPr/wEC\n        7v8SFrb/NkJH/x8oM/80aab/PH3G/z5+yP9MjNX/RITN/z9/yP9Dgsn/SYnQ/z91s/8sNT7/NFR2/0SE\n        zf9Egcf/SIbM/02L0v9Gg8j/RYLH/0OAw/9Fg8n/N1l9/ykwNv87bqb/RITM/z58wf8+fsX/QIHJ/z1+\n        x/9EhtD/RojS/zVtqf8hKzT/KC82/ykxQf8oMEL/KDBC/yYuQP8oMDn/HyQm/yIpMv8hKTv/ISk8/yAo\n        O/8fJjr/HyY0/yUuNv8XHCH/Hycu9h8mLvQWGyD/Mj1L/xYbxv8CA+v/AwTp/wME6/8KDNP/PEln/yMr\n        KP8cI6H/AQLu/wID6v8BAe7/GB6k/zQ+P/8hLz7/O3W4/zx7wv9BgMf/UI/X/0iHzv9BfsX/RYLJ/0yK\n        0v9AdbH/LTU+/zZVdv9Hhs7/RoPJ/06N1f9Sktr/SITI/0aCxf9GgsX/R4TI/zdYfP8qMTf/PG+m/0SD\n        yv9BfcL/QH/G/0KByf9Cg8z/SIjQ/0iJ0v84dLb/JDNC/ykvNf8sM0P/KzNE/yoyRP8oMEL/KTE7/yAl\n        KP8jKjH/Iys9/yIqPf8hKDv/ICc7/yAnNv8lLjb/GB4j/x8nLv4eJSz6Fhsg/zM+T/8TGMf/AgPr/wME\n        6f8DA+v/Cw3R/zxIY/8kLCr/GiCo/wEC7f8CA+r/AQHu/xwilv8zPDr/JDRG/z97v/8+e8H/Q4HH/1KQ\n        2P9Jhsz/Qn/E/0aCx/9Kh8//QHSv/y42Pv83Vnj/TIvS/0uHzP9SkNn/TYvR/0mFyf9JhMf/RoLF/0qG\n        yv86XID/KzI4/zxto/9Hhcr/R4TJ/0aFy/9MjNT/S4vU/0uK0v9JitT/Oni8/yY5TP8pLzT/LTRE/yw0\n        Rf8rM0T/KTFC/yoyPP8iJyr/Iikv/yQrPP8iKj3/Iik8/yAnOv8gJzb/Ji83/xkfJP8eJi3/HyYt+hcc\n        IP8zPk7/ExfG/wID6/8DBOn/AwPr/wwO0/87R2H/JSws/xkerf8BAe3/AgPq/wEB7v8dI5X/Mzw6/yM0\n        Rf9Aer3/QX3D/0iFzP9Uktj/TIjO/0eEyv9Jhcn/S4jM/0F1r/8vNz//PFt9/1WT2f9Nh8r/V5PY/1SR\n        1v9RjND/UIzP/0uFxv9QjM//PmCF/y40Ov9Acaj/TIvT/0mGy/9HhMn/TYzT/06M0v9NjNT/Q4LK/zt2\n        uP8mOUz/Ki80/y82Rf8uNUb/LDNE/yoxQ/8rMjz/Iygr/yEnLf8lKz3/Iyo9/yEoO/8gJzr/Hyc2/yYv\n        N/8ZHyT/HyYu/yAoL/QXHCD/ND9P/xUayP8CA+v/AwTp/wMD6/8MDdH/OkVf/yQsKv8aIKT/AQLt/wID\n        6v8BAe7/GyCY/zU+Pf8mNUT/QXq6/0F9wf9IhMn/VZHU/1KO0/9Ig8j/TIbK/1SQ1P9Kfbf/MTlA/z1b\n        e/9Xldz/VI/T/12a3v9al9z/U4/T/1SP0v9Ri8z/UY3O/zxcf/8xOD7/Snuy/1GP1v9IhMj/RIDE/0WC\n        x/9LiMz/UY7U/0mIz/89eLr/JjhJ/yovNP8vNkX/LzZH/ywzRP8qMUP/KjE7/yIoKv8iKC7/Ji0+/yQr\n        Pf8jKTz/ISc7/yAmNv8nLzf/GR8k/x8nLv4jKzLpFxwg/zZBTf8aH8P/AgPr/wME6f8EBOr/CgvY/zlE\n        Zf8kLCj/HiWc/wEC7f8CA+r/AQLt/xUaqP84QkT/Iy44/z91sP9DfsD/S4bK/1eT1P9VkdT/S4XH/02H\n        yv9Xk9b/TH61/zI5Qf8/XHv/V5PX/1eR0/9ZlNf/WpXX/12Z3/9Zldn/UYrJ/1SP0f89XYD/MDY8/01+\n        tP9Zltr/UYzP/0mDxP9GgMP/RYHF/06Lzv9Oi9D/QHi3/yUyPf8sMjj/LjVE/y82Rv8tNEX/KzFC/ysy\n        O/8iJyn/JCox/ycuP/8lLD7/Iyo8/yEoO/8gJzX/Jy83/xkeI/8hKTD1JCsz2BgdIf82QEb/ICa2/wIC\n        6/8EBOj/BATp/wYH4P84QXX/JCsl/yQsiv8CAuv/AgPq/wEC7f8OEb3/OkRN/yQrL/89a57/SYPH/1CM\n        0P9bl9r/WZPV/06Iyv9TjdD/WJPV/1CCuv80PEP/QV9+/1+b3/9aldf/Wpba/2Gc3v9emt3/WZTY/1iS\n        1P9fneH/QmOG/y40Ov9Gdqr/VpPW/1eU2P9SjM7/T4nL/0qFx/9Mic7/SofM/0Bxpv8kLDL/MTc//zA2\n        Rv8vNUb/LDNE/ysyQv8uNT7/ICUn/yQqMv8nLT//Ji0//yQrPf8iKTz/Iig1/ycuNf8YHSH/ISkx4yQs\n        NL0aHyT/Mjs//ykwqf8DA+r/BATo/wQE6P8EBOb/MjqH/yYsJ/8rM3D/BAbm/wID6f8CA+v/BgjT/zZA\n        Xf8oLi7/Nll//06JzP9Ri8//XJja/1qU1P9Vj9L/WpXX/1mPzP9OeKT/Nj5F/ztSbP9Rf7T/UX+y/1SC\n        tv9VgrX/UoCz/1J/sf9SgLT/XIzA/0Jcdf8wNjv/P2WP/06Ewf9bmd//VZDU/1WP0f9UjtH/TIjN/0qG\n        yv86YYv/JSot/zM6Q/8wNkb/MDZG/y00RP8sMkH/LzU8/x4jJf8nLTf/KC5A/yYtPv8mLD7/JCo8/yQq\n        Nv8nLjX/GR4j/yEpMckmLjaWHSIn/ysyNP81PpX/BATo/wQE6P8EBej/AgPq/ycuof8pMC7/LjdT/woM\n        1/8BAur/AgPp/wID5v8qMnn/Mzo4/yo9UP9Qicr/VpDS/2Od3/9fmdv/UITA/0Vni/9AUWH/Q0xV/0ZO\n        Vf82PEL/MTc8/zI4P/8yOT//MzlA/zQ6Qf81O0L/Mzk//zE3Pf80Oj//Rk5V/0RNVv9DU2L/TnCU/0+E\n        v/9altn/WJLU/1OO0P9LhMb/LURb/ysvM/8yOEP/MDZH/zE3R/8vNUb/LTNA/y00Of8dISP/KTA8/ygv\n        QP8nLT//Jiw+/yQqPP8mLjj/JSwz/xsgJf8iKjKkKDE6ZyIoLvoiKCr/Pkl8/wkK4f8EBOj/BAXo/wME\n        6v8ZHb7/MThA/y01Of8WGrn/AQLs/wID6f8BAuz/Fhql/z5HSv8kLDL/SHes/1mU2P9ppOX/UH2v/zxN\n        Xf9ESlH/SU9Y/0pQWf9LUFn/M0dc/ztgh/89YYj/QmaL/0Jli/9AY4n/PF+E/zpdgv85XYP/Mkdd/0lP\n        V/9KUFr/SlBZ/0lOVv9BUWD/T3qq/2Cc3/9dmdz/Snux/yQtNP8zOT//MzlH/zE3R/8xN0f/MTdH/zA2\n        Qf8qMDT/HiIm/ysxP/8pL0H/KC4//yYtPv8kKjv/KjI7/yIoLf8fJSr9Iyw0dSkxOjclLDLoHSIm/0RP\n        Zv8TFtH/AwTp/wQF6P8EBen/CwzY/zc/Yv8nLSj/Jy6M/wID6v8CA+n/AgPq/wYH1f84QGX/MDU1/zFK\n        ZP9Wjs7/VHyn/0BLVf9ITVX/SU9a/0lPWf9KUFr/Q0lQ/0dslf9noeH/Zp7d/3Ou7f90r+//bKXk/2ih\n        3/9lntz/ZJ7d/0pxnf9BSE7/SlBa/0lPWf9JT1n/Sk9Y/0NNV/9Pd6H/W5XX/zdTcv8nKy3/NTpE/zQ6\n        Sf80Okn/MzlJ/zI4R/8zOUH/JCot/yQpLv8rMUH/KjBB/yguP/8nLD7/JSo5/y42Pv8eIyj/Iikw7yQt\n        N0MqMzwSKTA4wxsfJP8/SE//Jyy3/wID6v8EBef/BQXo/wQE5/8vNZH/Jisn/zM8Wv8KDNf/AQLq/wID\n        6f8BAuv/HCCb/0NMTf8lLTP/PVyA/0FMV/9KUFn/SU9Z/0lPWf9JT1n/SlBZ/zxIVf9Zi8L/Z5/e/2ed\n        2v9tpeP/babk/2+n4/9yqub/aqLf/2ig3f9dj8f/OklY/0pQWP9JT1n/SU9Z/0lPWf9KT1n/QkxW/z5f\n        g/8mMDj/NTpA/zc8Sv83PUz/NjtL/zU7Sv80OUb/MzpA/x4iJP8rMTv/LTND/yswQf8pLkD/Jyw+/yYr\n        OP8uNT3/HCAl/yYtNc4lLjcZGRoZACszO4ggJCn/MDc5/z1Flv8FBub/BAXn/wUF5/8EA+r/Gh3B/zE4\n        QP8wNzf/HySm/wEC7P8CA+j/AgPq/wUG2P83Pm//OkFB/yswNP9JUFj/SU9Z/0lPWf9JT1n/SU9Z/0RK\n        Uf9HaIv/aaDe/2qh3v9rot7/cKfk/3Or5/99tvH/dq/q/26l4v9tpeH/bqbj/0lskf9ARk3/SlBa/0lP\n        Wf9JT1n/SU9Z/0pQWf8sMzb/MDU5/zxCTP87QVD/OkBP/zk+Tv83PEz/NTtE/y0zN/8fIyX/MDVD/y40\n        RP8sMkL/KS9A/ycsPf8qMDr/KS81/x8kKf8oLziWKTVBAioyOgAsND1EJy008yEmKf9LVHH/EhXV/wQE\n        6P8FBef/BQXo/wcI4f80O3n/Jisn/zY+Z/8JC9r/AQLp/wID6P8BAuv/ERO4/0dQX/81Oz3/OD1D/0lQ\n        Wf9IT1j/SE9Z/0dMVP8+Umf/Y5fR/3ev6/9xqOT/baPe/22j3v9xp+P/e7Pv/3Sr5/9xqOT/cajk/3iw\n        7P9kmtX/O1Fo/0VKUf9JUFn/SE9Y/0lQWf88QUj/MDU5/z5ETP89QlD/PUNS/zxBUP86QE//OT9L/zg+\n        RP8hJif/KS41/zE2Rv8vNUX/LTND/yswQf8oLTz/MThA/yElKv8kKjH4KDA5USYuNwAsND0AKzQ9Eiwz\n        O8UeIib/Q0tQ/y82tP8DA+n/BQXn/wUG5/8DBOn/HyK5/y4zOv80Ozr/Jyyd/wID6v8CA+j/AgPo/wEC\n        6P8fIaH/UFhd/zQ6PP86QEb/SVBa/0dMVP89TFz/X4/D/3Wt6f94sOv/eK/q/3Go4v90q+X/gLnx/3uz\n        7/9zquX/dazn/3mx7P97s+//cann/2OWzP83SFr/RElQ/0pQWv89Qkr/LzM3/0JIT/9DSVX/QEZU/z5D\n        Uf88QVD/OkBO/zk/R/8wNjr/HiIk/zM5Rv8xNkb/LzRE/y0yQv8rMEH/KzE8/zI5QP8dISX/KC83ziYv\n        OBgnLzgALTU+AC42PQAuNj90Jisx/yswM/9NVob/Dg/e/wQF5/8FBuf/BQbn/wcI4v8yN3//Jion/z9H\n        Wf8VGMb/AQLr/wID6P8CA+n/AgPk/ycqmf9XX2P/OT9B/zY6P/8/UGL/YpPH/3au6v93rur/dKrl/361\n        7/96ser/gbnx/4fB+P+Gv/X/fLTt/3uz6/+EvvT/gbny/3Ss6P94sfD/Z5vS/z1RZP83Oz//NDg8/0FG\n        Tv9ESVX/REpY/0NJV/8/RFP/O0BP/zpASv84PkT/HyQl/ywxOP81Okn/MjdG/y80RP8tMkL/KzFA/zQ6\n        Q/8pLjP/Iygu/yoyO4AzMjoAKjM7AAAAAAAuNj8ALjZAJS82PdsfIib/TFVd/y8zu/8DBOj/BQbm/wUG\n        5/8FBen/FRfK/zE1TP8uNDH/PUR2/wsN2v8BAun/AgPo/wID6f8CAuP/Jiii/1xibv9GS0r/LzlC/1Z2\n        mP9wotf/ebHt/3qy7v9+tfD/frXu/3qx6/+BufP/iMH2/3uy6/95sOr/g7z1/4C58/93ruv/c6fe/1x/\n        of8zPkf/ODw+/0dMVP9FSlb/Rkxa/0ZMWv9ESlj/QkdW/z9EUP89Q0r/KjAz/yImKv83PEr/NTpJ/zI3\n        Rv8vNUT/LTJD/y0zPv83Pkb/HyMn/ysyOeIqMjstKjE6AAAAAAAAAAAAMjpDAC4/TQExOUKDKC0y/zA1\n        OP9VXor/EBLc/wQF5/8FBub/Bgbm/wUF6P8lKKj/Ki4x/ztBQP85Po3/CAnh/wEC6f8CA+j/AgPo/wEC\n        5v8aG7f/VlqB/2FmZP89QkH/N0NO/1Nvjf9umsj/fK/m/4G48f99tO//hL33/4W+9/+FvvX/e7Ls/3mt\n        5P9umcj/UW6N/zlFUf8+QkH/XmNj/2Npbf9KT1b/SE5a/0ZLWf9FS1j/Q0hW/0JHVP9BRk7/NDs//x4i\n        JP80OUT/OD1L/zY7Sv8zOEf/MDZF/y80Qv84Pkf/KzA1/yQpLv8sNDyQJC05AiszPAAAAAAAAAAAAAAA\n        AAAuNkAALzdAJDI5QdUiJir/TlVa/z9Fs/8FBuf/Bgbm/wYG5v8GBuf/CAjj/ywvif8nKyn/RUtM/zs/\n        l/8JCuH/AQLo/wID5/8CA+f/AQHp/wkK0/83OaL/aGyD/2lta/9MUE3/PEJF/0NPWv9QZXf/WXSP/2B+\n        nP9gf5z/X3uU/05jeP9CT1v/PUNF/0xQTP9mamn/XGGG/ygqrP9HSpT/W2Fh/0lOV/9JTlv/RktZ/0NI\n        Vf9CR1D/OT9E/x4iJP8yNj7/O0BO/zg9S/81Okn/MzhH/zE1Rf8zOEP/OUBH/yAjJ/8tNDveLDM8LSsz\n        OwAAAAAAAAAAAAAAAAAAAAAAMTlCADk9RQAyOUJsLjM5+iouMv9gan//JSjP/wQE5/8GBub/Bgbm/wUF\n        5/8MDNz/LTF2/yktKv9KUVL/Q0eY/w0O3v8AAen/AgPn/wID5/8BAun/AAHm/w4Pzf84Oqz/ZWiY/3l9\n        if92enj/am5p/19iXf9ZW1b/WFtW/19iXf9qbWn/c3d3/3N3iP9ZW5j/Ky2y/wgJ1v8AAOr/ERLQ/15j\n        ff9SV1v/Sk9a/0dMWP9FSlL/PEJH/yEkJv8vMzr/PUJQ/zo/Tf84PUz/NzxK/zM4R/8wNkH/PkRM/ygs\n        Mf8pLjT9LzY/eAABAAAtNDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAvNj8ALTQ9ETU8RLQoLDH/P0VI/15m\n        m/8TFd3/BQXn/wYG5v8GBub/BQbo/w8P2P8tMHP/KS0r/0tRUP9TV47/HiDT/wEC6f8BAuf/AgPn/wID\n        5/8BAun/AADo/wQF3f8VFsv/LS66/0RGsf9WWK7/W16t/1terf9TVa3/P0Cx/ycovf8PEM7/AgPg/wAB\n        6f8CA+j/AgPn/wAB6P8qLLP/YGZt/0tQV/9HTFP/O0BF/yAlJv8vMzn/P0RR/z1BUP87QE7/OD1L/zY6\n        Sf80OEb/O0JK/zQ5P/8kKCz/MThAvSsyOxYsMzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzpCADM6\n        RAAzOkM4Nz1F4CUoLf9UWl7/Ulmt/woL4/8FBeb/Bgfm/wcH5v8GBuf/DhDc/ysufv8qLS3/RUtI/2No\n        fv8/Qb3/Dg/i/wAA6f8BAuf/AgPn/wID5/8CA+j/AQLp/wAA6f8AAOj/AADk/wAA4/8AAOP/AADl/wAA\n        6P8AAen/AQLp/wID5/8CA+f/AgPn/wEC6P8BAen/GRrV/2Nohv9RVlr/OD1B/yAkJf8zNz7/QUZT/z9E\n        Uv8+Q1H/O0BO/zk+TP82Okj/Oj9I/z9FTP8kJyv/MTc+5i81PkEvNT4ALjQ8AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAA1PEYA////ADg/SGQ1O0L0KCwv/2BncP9HTLr/CAjk/wUG5v8HB+X/Bwjm/wYH\n        5/8LC+H/JSeZ/yksOf84PDn/Ymlr/2hsn/87Pcz/DxDj/wEB6P8AAOf/AQLn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8BAuf/AADo/wID5/8XGN//RkjA/2ZqjP9VW1//Mzc4/ygr\n        LP89QUj/R0xZ/0JHVf8+QlD/PkJQ/ztATv85PUv/PUJM/0VLUv8mKi7/MTc99zQ7RHAZGycBLzU+AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ7QwAwN0AHOUBIiDI3PfsvMjb/a3N9/0lO\n        w/8JCeT/Bgbl/wcI5f8HCOX/Bwjm/wgI5v8aG77/KCpd/ywvL/9KUE3/cHZ6/3d7pv9YWsn/Li/e/xAR\n        5f8DBOf/AADn/wAA5/8AAOf/AADn/wAA5/8AAOf/AADn/wAB5/8FBuf/FRbk/zU22P9dX7//dHeW/2Vq\n        bP9CR0X/JScp/zU4Wv+GjZr/T1Rc/0ZKV/9ESVf/QEVT/z5CUP88QU7/P0RO/0pQWP8rLzT/LzM5/TY8\n        RZQtNDwKMDc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjlBADA3\n        PxA6QEifMjY8/jE0OP9wd4P/UVbF/wsL5P8GBuX/Bwjl/wgI5f8ICOX/Bwjo/w0O3P8fIJz/ICFF/y8y\n        Mv9LUEz/b3V0/4WJlv+Eh7T/dHbJ/11e1/9KTN7/QEHi/zY34/81NuP/QEHg/0xO3P9hYtT/dXjD/4OG\n        qv99gov/ZWpp/0JHRP8mKSn/ExQ6/xMUlP8QEdX/cXbC/3R7gP9ESVL/QkZT/z9EUv89Qk//QkdS/05V\n        Xf8vMzj/LTE2/zc+RqoxOEEVMjlCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAA2PEUANDpDFj5FTaY1OT/9MjY5/3V9h/9jacX/FRbg/wUF5f8ICOX/CAjl/wgJ\n        5f8ICeb/CAjo/w0O1v8ZGp3/GBpT/ykrN/9BREL/Wl9a/25zb/98gYD/hIqM/4qPlf+LkJv/i5Cb/4qP\n        lf+Ch4r/d3x8/2VqaP9QVVH/ODs5/yEjMP8RE0v/CwyR/wkK0/8HCOj/Bgbn/x0f1P+Ei6n/VFle/0FF\n        UP8/RFD/RUpT/05UXP8wMzj/MDQ5/zg+RrEvNT0dMjhAACsrNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALykmADc9RQA0OkIWQUhQnzs/RfsxNTn/bnV6/3mA\n        vf8sLt3/Bgbl/wcI5f8ICeX/CAnl/wkJ5f8JCeb/CAno/woK3/8NDbv/FhaO/ykpb/9CQ2X/WVtq/2tt\n        cv90dnf/dnl5/3N2d/9sbm//XV9k/0pLWv80NVf/HyBk/xESif8LDLr/CQne/wgJ6f8ICeb/CAjl/wgI\n        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\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAOkNHAAAAAAAiLDMNGyQsOxghKIIWHybDFh8m7BghKP0dJi3/Hygu/yAp\n        Lv8eJSj/GyEj/xgeH/8UGBn/ERQV/xEUFf8RFBT/ERMU/xATE/8QExP/EhQU/xIUFf8SFBX/EhUW/xUY\n        Gv8ZHiD/HSIl/yAnK/8jKzD/Hygu/x0mLf8aJCv+GCEo7xcfJsgXICaIGyQpQiMtMhD6//8AQEpNAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQvNgAoMzsBHygvHRkiKWQXICe1Fx8m7Bkj\n        Kv4eJy3/Hycs/x4lKP8WGh3/EhUW/w8REv8QEhP/EhUW/xYbHf8bICL/HiQn/yEoLP8mLTH/KDAz/ygx\n        M/8nMTP/KTE0/ycvMv8iKS3/HyUp/xwhJP8YHB7/ExUW/xASE/8QEhP/EhQW/xcbHf8dJCf/ICgt/x8o\n        Lv8ZIin+Fh8m7xYfJbwYIShrHSUsIh8oLQIYIicAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        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\n        1P8CA+z/AQLy/wID8P8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8CA/D/AQLy/wID\n        7f8KDtX/Himq/zZJfP8+VWL/NklS/yc1P/8YISf/EBUa/xcfJf8gKzT/HCYu/xYfJeYYICZ7HygxFBEZ\n        HQA2QU8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAMDhCAAACCQAdJi4lGCAopBcgJ/cdKDD/GiQr/xAWGv8TGiD/Iy85/zVH\n        UP8/VmL/MUN//xggtv8GCOP/AQLx/wID8P8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8CA/D/AQLx/wYI4v8YILT/MUJ+/z5UYf81SFL/JTI8/xUc\n        Iv8QFhr/GiQs/x8qM/8YISj6Fx8msB0lLS4AAAAALThAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApMzgARFJVARsjKkEWHiXIGSIp/h0o\n        MP8UHCH/DhQY/xslLf8vQEn/PFJa/zRGd/8ZI7X/BQfl/wIC8f8DBO//AwTt/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO//AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wMD\n        7/8CAvH/BQfk/xkhtf81SHn/PlRc/zFCTf8fKjL/EBYb/xQcIf8fKjP/GyUs/xYeJdIaIypOLDQ/Aycw\n        OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMs\n        NQAqND0EGCIpWRYeJN8aJCv/HCYu/xEWG/8TGh//JTM8/zhMU/85Tmr/Hyqi/wYJ3/8BAvH/AwTu/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTv/wID8f8BAvL/AQLy/wEB\n        8/8BAfP/AQHw/wEC6/8CAun/AQHt/wEB8v8BAfP/AQHy/wEC8f8CA/D/AwTv/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTu/wIC8f8HCt7/ICyf/z1Saf8yQ0//ISw1/xUd\n        I/8QFhv/HSgw/x0nL/8WHiXoGCEoaCs0OwcfJy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAISsyACYwNwcaIyptFh4l6xwmLv8ZIin/DhMX/xggJ/8uPkn/PlNe/y9A\n        g/8OE8v/AQHw/wID7/8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO//AgPw/wIC\n        8P8DBO7/Bgji/w4S1f8WHcH/HSe5/yc0pv8tPKn/Lz+l/zFBlf8yQ4//L0Ca/y08p/8pNqb/Hyq2/xYd\n        wv8OE9b/Bgji/wME7f8BAvH/AgPx/wME7/8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME\n        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\n        mf9EW2v/OUtZ/yQwQ/8oNkX/PFBY/z5UdP8lMaD/Cw/U/wID7v8CA/H/AwXv/wQF7v8EBe7/BAXu/wQG\n        7v8EBu7/BAbu/wQG7v8FBu7/BQbu/wUG7v8FBu7/BQbu/wUG7v8FBu7/BAbu/wQG7v8EBu7/BAbu/wQF\n        7v8EBe7/AwTw/wID8f8EBej/ExvD/zNFkf9EXGz/M0VM/x8rNf8lMUD/LTtI/xwlLP8dJi//GyQ4/xwl\n        Ov8cJTr/GyU6/xskOf8aIjj/GSI3/xkhN/8ZIjj/GyM3/xskLf8fKTH/ICsz/w4TF/8bJCv/GiMq/xce\n        JbAgKjIUHicvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAApMz0Ai6XAABskK2oYISj2HScv/w8VGf8ZIin/NUdP/zZIdf8LD9T/AgLw/wME7P8DBOz/AwTt/wME\n        7f8DBO3/AwTt/wIC8P8LDtT/M0SI/0VcZf8uPEz/Iy5A/zRGTv9CWW3/KzqX/wwQ0v8CAvD/AgTw/wMF\n        7v8DBe7/BAXu/wQF7v8EBe7/BAbu/wQG7v8FBu7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FCO7/BQju/wUH\n        7v8FB+7/BQfu/wUH7v8FBu7/BAbu/wQG7v8EBu7/BAXu/wQF7v8EBe7/AgPx/wMF6f8VHLz/N0qH/0JZ\n        av8jLjj/GyQv/yMuOv8dJy7/HCUw/xskOP8cJTr/HCU6/xwmOv8cJTr/HCQ5/xsjOf8aIzj/GiI4/xoj\n        Nf8bIyv/ISw0/x0mLf8PFBj/HCYt/xcfJfsYISh8Lz5GAyMvNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1CUgAaJCwAHigwMhghKNweKDD/FBog/xUcIf8xQkz/O09o/xMZ\n        xf8CAvD/AwTs/wME7P8DBOz/AwTt/wME7f8DBO3/AgLw/w8Uxv85THv/QFVe/yczQP8kMDz/PVNb/zhM\n        f/8UG8H/AgPs/wID8P8DBe3/AwXu/wMF7v8EBe7/BAXu/wQF7v8EBu7/BAbu/wQG7/8EBvD/BAXy/wMF\n        8v8EBfP/BAXz/wQF8v8EBfL/BAXz/wQF8/8DBfL/BAXx/wQG8P8FB+7/BQbu/wQG7v8EBu7/BAXu/wQF\n        7v8EBe7/BAXt/wMF7v8BAvT/GiO+/0dgc/8xP0v/HCQs/xggKP8iLDb/Hygw/x0mMP8cJTf/HSY7/xwm\n        Ov8dJjv/HSY7/x0nO/8cJTr/GiM4/xoiOP8bIzT/HCUs/yUwOf8YICf/ERcc/xwmLf8XHiTmGyMqQBYc\n        IgAlMDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIsNgAlMDoMGSIqphwm\n        Lf8ZISj/EBUZ/yo5Q/8/U2D/HSau/wIC7/8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8CAvH/ERfC/z5R\n        dP8/U1z/LjlD/zpJUf9PZnP/KjiZ/wgK3f8CA/H/AwXu/wMF7f8DBe7/AwXu/wQF7v8EBe7/BAXu/wQF\n        7/8DBPH/AwTx/wYI5/8MENr/Fh3G/yAruf8qN6r/LTuu/y48qf8uPar/LDqs/yc0qv8dJ7z/FBnM/wsO\n        3/8FBu3/AwTy/wQF8f8EBu7/BAbu/wQF7v8EBe7/BAXu/wME7/8KDeH/PlGI/zRGTv8dJi3/JzE8/yIr\n        Nf8WHSL/JC43/yErM/8fKTP/Hic6/x0nO/8dJzv/HSY6/xwmOv8dJjv/HSY7/xskOf8bIzn/GyQx/xwl\n        Lf8nMz3/Ehgc/xcfJf8cJSz/GCAntSIrNBMfKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAALjo/AA4UHQAdJi5bGiIq9B4oMP8PFBj/Hykx/ztPVv8rOZP/BAXq/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wIC8P8QFcP/PlNz/ztNVv8jKzL/SFZZ/4efs/8/Ssz/Bgfr/wUG7/8EBe3/AwTt/wME\n        7f8DBO3/AwTt/wMF7f8DBPD/AgPw/wgK4/8WHcH/KDSb/zhHfP9AUmn/RFZh/0NVXP9GWFz/RVZc/0NV\n        XP9DVlz/RFZb/0VYXv9FV1//R1lm/0FScf81Q4j/Iy2s/xEW0f8GB+r/AwTx/wQF7v8EBe3/BAXt/wME\n        7/8sNp//QVJU/x8oL/8eJzD/HSU1/yQtOv8nMDf/GBwe/yEoLP8lLzb/ICo0/x8oOv8eJzz/HSc7/xwl\n        Ov8dJjv/HSc7/xwmOv8bIzn/GiI3/xoiLf8gKjL/Ii01/w8UGP8dJi3/GiIq+RskLG0AAAAAKDM8AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHykyACErNBoZIinHHScv/xQbIP8WHSP/NkdR/zdK\n        c/8LD9j/AgPu/wME7P8DBOz/AwTs/wME7P8DBOz/AgPw/wwQzf88T3b/PE9X/yAoLf8rNjb/PEti/x8l\n        w/8FBe//BQbu/wMF7f8DBO3/AwTt/wME7f8DBO3/AgTv/wIE8P8MD9n/Iiyh/zlKdf9DVV//QVJa/ztK\n        Wf8zQVP/LzxO/y47Sv8rOET/KDM9/ygzPv8oMz3/KDQ+/yw5Rf8xPk3/MkBR/zdFVP9CVGD/SFph/0ZZ\n        bP82RIX/HCS4/wcK5v8CA/H/AgLy/xgdxf9GWGX/KDM4/x0mLf8dJjX/HSU7/xwlOf8hKzn/Jy83/xgc\n        Hf8eJCf/Iy00/yApM/8fKDv/Hic8/x0mO/8dJjr/HSY7/x0mOv8dJjv/GyQ5/xoiNf8aIyr/JTA5/xsk\n        Kv8SGR3/Higv/xkiKNQgKjMlHicwAGF8fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtNz8AAAAAABwl\n        LHIaIyr8GyUs/w8UGP8oNj//QFRh/xoit/8BAvD/AwTr/wME7P8DBOz/AwTs/wME7P8CA+//BwnZ/zZH\n        f/9AU1z/Hygu/yo0NP84R2H/ERW+/wEB7/8DBO3/AwTt/wME7f8DBO3/AwTt/wME7v8CAvL/CAvc/yQu\n        n/89Tmv/QFFX/zhIW/8vPVf/KjZK/yYxPf8nMzz/JjVA/yc6TP8qQ1v/KUZn/ylJbf8pSW//KUdp/ypD\n        Xf8oPVD/JjZC/yczPP8oMz7/LjpM/zhHXf9BUl7/SFtj/ztKf/8aILv/Cw7c/z1Mgf81Q0T/HSUs/x4n\n        Mf8eJzr/HiY7/x4nO/8dJjn/ICk2/ygxOv8WGhz/ICcq/yIsM/8fKDP/Hic7/x4nPP8dJjr/HCU6/x0l\n        Ov8dJTr/HSY6/xwlOv8bJDL/HSYt/ygzPP8RFhr/GiIp/xskKv8bJCyFRVNkAiYxPAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAeKC8AICkyIRggJ9EdJy//Ehcc/xkhKP85S1L/LjyJ/wQF6f8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7f8DBOX/KzmO/0VaY/8jLDL/JzAx/zlJXv8SF7z/AQHx/wID7f8DA+3/AwPt/wMD\n        7f8DBO3/AgPv/wME7P8YH7T/OUlv/0FSWf8yQVb/KDRO/yQvP/8lMTn/JThJ/ytMc/8qWpX/Lmeu/y9t\n        uv8uccP/LnHE/y1xwf8tccP/LXHF/zJ2y/82d8n/M2+4/ytcl/8rTnX/JzxQ/yYyO/8nMj7/LzxR/0BR\n        X/9IWmj/QVF2/0FRWP8gKC//Hycu/x4mN/8fJzv/Hic7/x4nO/8eJzv/HSY6/yApN/8oMDn/Fhoc/x8m\n        Kv8iKzP/Hyg0/x8oPP8eJzv/HSY6/xwlOv8cJTr/HCU6/x0lOv8cJTn/HCUu/yEsNP8gKTD/EBUZ/x0m\n        Lf8ZISneICkyLB8nMAAAAAAAAAAAAAAAAAAAAAAAAAAAACMsNgAAAAAAGyMqcxghJ/0YICf/DxQY/yw6\n        Q/88T2T/ERfI/wIC7/8DBOv/AwTs/wME7P8DBOz/AwTs/wEC7v8dJqj/R1xo/yk1Pf8gKCr/OklW/xUb\n        tv8BAfH/AgPt/wID7f8CA+3/AwPt/wMD7f8CA/D/CArd/yg0j/9BU13/OEZb/ygzVP8iLDv/JDE6/yhE\n        Y/8rW5j/MHC+/zR60/8vdsr/MnrM/zZ90P82fM7/MnXG/zBzxf8wc8P/NnrL/z2D2P8/heD/OIDX/zJ4\n        zf8xeMr/LWy3/ytdl/8pRmT/JTQ//yQvOv8yP1X/RVVm/yk0O/8fJy//Hyg2/x8nO/8hKT3/ISo+/x8o\n        PP8eJjr/HSY6/x0kOP8hKTX/Jy82/xYZGv8iKS//ICoy/x0mNf8dJjv/HSY7/x4nPP8dJjr/HSY6/xwl\n        Of8cJTn/HCU1/xwkK/8kMDn/ERcb/xggJv8bIyv/GyMrhVRnfQEjLDYAAAAAAAAAAAAAAAAAAAAAAB8p\n        MQAhKzMYGSAnyh0mLv8QFhr/GiIp/zpMU/8oNJb/AwTs/wME6/8DBOv/AwTr/wME7P8DBOz/AgPv/w0R\n        y/9CV3T/N0ZQ/xshJf85SEv/Hyef/wEC7/8CA+3/AgPt/wID7f8CA+3/AwPt/wIC8f8MD8//M0F2/z9R\n        Vf8wPFr/Ii1J/yEtOP8oRGD/LWKi/zN2zf8zeM//MXbG/zZ7zf81ecz/O4DS/zyC1/87gdf/NXnM/zR4\n        xv85ftD/QYje/0CG2/8+g9n/PYPZ/zR6zP8xdsX/MXbF/y90w/8vcsD/LWSk/yhIaP8jLzn/JC8//yYw\n        Qv8kLTb/ISo2/yAoPP8gKDz/ISo+/yIrP/8hKj7/Hyc8/x4mO/8dJTj/Iyw2/yQqL/8WGhv/JC0z/x8o\n        Mf8dJjj/HSY6/x4nPP8eJzv/HSU6/xskOP8bIzj/GyM3/xsjLv8hKzP/HScu/w8UGP8dJSz/GSAn1iAp\n        MiIeJy8AAAAAAAAAAAAAAAAAAAAAABggJgAbIytZGSEo+BsjKv8PExf/KjdA/zpMZP8PE87/AgLu/wME\n        6/8DBOv/AwTr/wME6/8DBOz/BAXk/zE/iP9EWGH/GyIn/zE8O/8qNYP/AwTo/wID7f8CA+z/AgPt/wID\n        7f8DA+3/AgHw/w8TxP84SG3/PE1V/yk1T/8jLkD/KTZC/ylRff8xd8r/NHvP/zh70P80d8z/MnXD/zZ6\n        zf88gtb/QITU/z+G2P86gtf/MXXG/zR4x/88gNP/OoDT/zp/0v88gdX/O4DV/zR6y/80ecX/N3zL/zFz\n        v/8xdMH/MXfG/zJ3yP8tWIn/KzlE/yYyQP8nMkL/Ji84/yEpNf8gKTz/ISo+/yIqPv8iKz//ISo+/yAp\n        Pf8fJzz/HiY3/ycwOP8gJCj/Gh8h/yMsM/8eJzL/HiY6/x4nO/8eJzv/HSY7/xwlOf8bJDj/GiI4/xsi\n        M/8cJSv/JTA5/xIWG/8aISj/GyMq/BsjLGsKDxgAN0BFAAAAAAAAAAAAIiszACcxOwgZICeqGyQr/xIX\n        HP8ZICf/OktT/yo3j/8DBOv/AwPr/wME6/8DBOv/AwTr/wME6/8CAu7/GB+w/0lebf8oMzv/Iysr/zZE\n        Yv8LDdT/AQLw/wID7P8CA+z/AgPt/wID7P8BAfD/DhLI/zlIZf86SE//KDNJ/yYxQf9ET1z/SVVk/zRJ\n        Yv8tYJz/NHjL/zd6y/80d8j/NHrL/zl8zf86ftL/PYLW/zt/0v82esz/MXTD/zF0wf8ydsX/MHPB/zBy\n        v/8ydcL/MXXD/zBzwf8ydsP/M3jG/zF0v/8wc8D/MHXD/zJqqP83UGf/SVRg/0dRXv8rNkP/JzFA/ycw\n        Ov8hKjb/ISk9/yEpPf8hKT3/ISk9/yEqPv8gKT3/HiY7/x8nNf8rNDr/GR0f/x8mKv8gKTH/Hic3/x4m\n        O/8eJjr/HSU6/x0lOf8dJTn/GyM3/xsjN/8bIy3/ISsz/x0mLf8SFxz/Hicv/xoiKLskLjYQIiszAAAA\n        AAA9SFAAHiYuAB8nMDEYICfmGyQq/w4TFv8mMjr/PVBi/xMYx/8CAu7/AwTr/wME6/8DBOv/AwTr/wMD\n        7f8GCNr/OUl4/z1OVv8YHiD/N0VJ/xkfrv8BAfD/AgPs/wID7P8CA+z/AgPs/wEC8P8KDNL/NkRv/zxL\n        Uf8mLz7/KDNC/0hSX/9OVF7/TVRd/0lSXv8yQVD/L2CY/zl+0v84fMz/NnzM/zqA0v86f9H/OX7P/zd8\n        zf81ecj/NHbB/zR1vv80dsD/MnXA/zN2wf8xc7v/MnO+/zJ0vf8xc73/MHK8/zByvP8wc7//LmKa/ztO\n        X/9LU1z/TVNd/05UXv9LVGD/KjY//yUvO/8kLjb/ICk1/yApPP8hKT3/ISk9/yEqPv8hKj7/Hyc7/x8n\n        Ov8jKzb/LjQ5/xYaG/8iLDH/Hicx/x8nO/8eJjv/HSU5/x0lOf8cJDn/GyM4/xoiOP8bIzP/HCQr/yUw\n        Ov8QFRn/HCQr/xoiKe8eJi5BHCUsACQuOAAfKTEADBEYABoiKnMaIin+Fx0j/xIXHP80REr/MUB+/wUH\n        5/8DBOv/AwTr/wME6/8DBOv/AwTr/wEC7/8bIqf/SV1l/yIqMP8pMzD/LTl3/wQF5v8CA+3/AgPs/wID\n        7P8CA+z/AgLu/wUG4f8tOnv/Pk5Q/yo0Qf8lLzr/SFJf/05UXv9NU13/TFNd/01UXf9IUl3/NEVX/zZq\n        pv81esj/NHjH/zV5yP80d8X/NXfF/zd7y/83esj/N3rH/zl7xv87fcn/N3vH/zZ8y/81eMX/NXfD/zJ0\n        vf8zdb7/NXfA/zR3wv8xaaX/OExe/0xVX/9OU13/TVNd/01TXf9OVF7/SlRf/yo0Pv8pMjz/JS01/yEp\n        N/8hKT3/ISk9/yAoPP8hKDz/ICg7/x8nO/8fJzf/KDE5/x8kJv8cIiT/Iiwy/x8nN/8fJzv/HiY6/x0l\n        Ov8dJjr/GyM4/xsjOP8bIjb/GiEq/yUwOf8WHiP/FBsg/xwkK/8bJCuHAAAAACErNAAjKzMAJC43DBgg\n        J7YcJCv/EBUZ/x4mLf87TFT/Hiar/wEC7/8DBOr/AwTr/wME6/8DBOv/AwTt/wUG3v84SHr/Pk9W/xsg\n        Iv83RVD/ERXB/wEB8P8CA+z/AgPs/wID7P8CA+z/AQLu/yAplf9AUVL/LjhC/yUuOP9GUFz/TVRd/0xT\n        Xf9MU13/TFNd/0xTXf9NVF7/SlVh/zZLYv8zcLb/NXrJ/zZ5x/81d8X/NXjF/zZ5x/87f87/O3/O/z6A\n        zf8+gMz/PIDO/zt/zf89gtH/PYDO/zp7wv85e8f/PYHO/zl3v/83Um3/S1Rf/0xTXf9MU13/TVNd/01T\n        Xf9MU13/TVRe/0hRXf8pMzz/LDU+/yQtNf8hKTr/Iis+/yIqPf8hKT3/ISo9/yApPP8gKDz/Iio2/y01\n        Ov8WGhv/JCwy/x8oMv8eJjr/HSU5/x0kOf8dJTr/HCQ5/xsjOP8cJDj/HCQx/x8oL/8gKTD/DxQY/x0m\n        Lf8bIyrHIy43FCMtNgAdJS0AHiYuLxgfJuQaIij/DhMW/yk1Pf84SGX/Cw/V/wIC7P8DBOr/AwTr/wME\n        6/8DBOv/AQLv/xUbsv9KXWn/JCwz/ygyLv8qNX7/AwPr/wID7P8CA+z/AgPs/wID7P8BAfD/DxS9/z5O\n        W/84Q0r/ISkw/zE8Rv9OVWD/TFJc/0xTXf9MU13/TFNd/0xTXf9MUl3/TVRe/0JOXf8wU3v/N3vJ/zh7\n        x/81eMb/OXzI/zd6xv87fs7/O3/N/z1+y/8/gtD/PYLR/z6E1P8/h9n/On7M/zx/yP8+gMr/QIXV/zdg\n        jv9IU1//TVNd/0xTXf9MU13/TFNd/0xTXf9MU13/TFJc/05VYP8zPkf/Iywz/y44QP8lLjj/JC1A/yQt\n        P/8kLED/Iys//yIqPv8iKj3/Hyc4/ycwOP8gJij/HCIk/yIrMv8eJjb/HiU6/x4nO/8dJjr/HSU5/xwk\n        OP8cJDj/HCQ1/xsjKv8lMDn/ERUZ/xsjKv8bJCvvICkyPx8oMQAZICcAGyMrYhohKPsXHSL/Ehcc/zRD\n        SP8tO4L/AwTq/wMD6v8DA+r/AwTr/wME6/8DBOv/AgPo/y46h/9EVl3/Fx0f/zZCSf8TF7v/AQHw/wID\n        7P8CA+z/AgPs/wID7f8EBeP/Ljp2/z1LTv8kLDT/IC46/yU6Uv8+R1D/TlRe/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJb/05WY/85SFz/Nm6r/zp9y/85fMn/PH/M/zl7x/84fMr/OXzJ/z1/y/9Ag9D/PX/J/zx9\n        x/82d8H/Nne//zh4wP85esT/OXS3/z5RZ/9OVV//TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TlRf/zhA\n        Sf8hNkv/IzJA/yQsM/8pMjn/JCw6/yQtQP8lLUD/JC1A/yQtQP8jKz7/ICk8/yIqNf8qMzf/Fhka/yQs\n        Mv8gKDT/HiY6/x4mOv8eJjr/HiY6/x0lOv8cJDj/GyQ3/xsjLP8mMTr/Fx4j/xYdIv8dJi3/HicvdRUd\n        IwA2Q1ADGiEomBwkKv8SFxz/GiEn/zhITf8eJ6f/AQHv/wMD6v8DA+r/AwTr/wME6/8CA+3/Cg3M/0VX\n        cf8wPEP/ICcm/zA8bf8FBuT/AgPs/wID7P8CA+z/AgPs/wEB8P8WHKv/QFBT/y04QP8dJSv/LFB6/y1o\n        rv8oOkz/Q0tT/01TXv9MUlz/TFJc/0xSXP9MUlz/TFJc/05UXv9DTV7/MlJ3/z6Bzv85e8f/OnvF/zl6\n        xP83eMP/OnvF/0CBy/89f8n/PX/K/zx9xv82dr7/N3e+/zx9xf87fsn/M1mD/0lTYf9NU1z/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9OVF//PUVN/x8uPP8ybbD/MVqG/x8nLf8mMDf/JC01/yMsPf8kLED/JC1A/yUt\n        QP8kLD//Iyw//yEpOf8pMzn/HSIj/x4lKP8iKzP/Hyc5/x4mOv8eJjr/HiY6/x4mOv8eJjr/HCQ4/xwk\n        MP8iKzL/Hygv/xEXG/8eJy7/HCQsqyg1QwciLDUVGiIpxBwjKv8PExf/JS82/zpLXf8QFcn/AgHt/wMD\n        6v8DBOr/AwTq/wME6v8BAu7/GyKk/0xfaP8cIyj/Lzs5/x8mn/8BAfD/AgPr/wID7P8CA+z/AgPt/wQF\n        4P8vPG7/O0lM/zY/RP8+Tl7/Mm2z/zd9zv8yZ6f/Okpb/0tSWf9NU13/TFJc/0xSXP9MUlz/TFJc/01S\n        W/9KU2P/MD9S/zt3uf86fMj/OnzI/zd3wP85ecH/P3/J/0aH1P9ChND/O3zF/zh5wv83drv/OXi+/0GD\n        zv88e8T/MkVc/01VYP9MUlv/TFJc/0xSXP9MUlz/TFJd/01UXv88Q0n/ICw2/yxelf89gs7/OnnA/yg6\n        TP8eJCf/JS41/yQsOv8kLD//Iys+/yQsP/8kLUD/JCw//yIpPP8kLDX/Ji4x/xccHf8kLDP/HiY1/x4m\n        Ov8eJjr/HiU6/x4mOv8eJjr/HSU6/x0kNP8eJi7/JTA4/xEVGf8eJy7/HCUt1SMtOB8gKDIyGyIq4xoi\n        KP8QFBf/LzxD/zZFcf8ICeH/AwLr/wMD6v8DBOr/AwTq/wME6v8CA+b/LzuG/0FRV/8WHB3/NkNR/w0R\n        zv8BAu7/AgPr/wID6/8CA+v/AQLv/xIWsf8/T1T/KzQ6/y81OP9FapL/M3fE/zd9y/9AhNb/PXW6/yo/\n        U/86QEX/TFJc/01TXf9MUlz/TFJc/0xSW/9NVGH/Mz1N/zZqpP86fcn/O33I/zp6wv86esP/Pn/I/0GC\n        y/9Bgs3/Pn/K/zp6w/84eL//OnvE/z+By/84bqj/NUFQ/05VYP9MUlv/TFJc/0xSXP9OVF7/SlFa/zI4\n        PP8gMUD/N3Gx/z+G1f85fsv/N37N/zBaif8gJCn/JCwx/yUtNv8jKz3/Iys+/yMrPv8kLD//Iys+/yEp\n        PP8jKzf/LTY7/xcbHP8jKi//Hycy/x4lOf8eJTn/HiY6/x4mOv8eJjr/HiU6/x0lOP8eJi7/KDQ9/xIX\n        HP8bIyn/HSYt7SAqMkAfKDBWGyMq9RgfJf8TGBz/NUNJ/y46iP8EBer/AwPq/wMD6v8DBOr/AwTq/wME\n        7P8ICtP/QFBx/zA7QP8eJSL/Lztw/wUG5f8CA+z/AgPr/wID6/8CA+v/AgLq/ycxgP8+TEz/HiQo/yYw\n        Qf8yaqz/OHvK/zt+zP9Ags//RIjZ/zVzvP8lQ2P/Ljg+/0JIT/9MUlz/TlRe/01TXf9OVWH/OkNV/y1C\n        Vv8wTGf/MUtm/zFLZv8xTGf/M05p/zJNaP8zTWj/M05q/zBLZv8vSGP/MUxn/zFMaP8uRFr/O0RS/09W\n        Yv9OVF7/TVRe/0lRWv87Qkf/Ji4y/yA9Wv8xbrH/Qorc/0GF0f87gMv/M3fC/zZ0uP8oNkX/HSIl/yYt\n        NP8jKjr/JCs+/yMrPv8lLUD/JCw//yMrPv8kLDv/KzQ8/x0iJP8eIyf/Iioz/x8mOf8fJjr/Hyc7/x8n\n        O/8fJzv/HiY6/x4mOf8eJi//KDI7/xcdI/8ZHyX/HiYt+x8oMWoeJy9+Hicu/RQaHv8XHSP/PEtQ/yMs\n        ov8CAu3/AwTq/wME6v8DBOr/AwTq/wID7v8QFLv/SVtq/x8lKf8qNDH/IyyW/wEC7v8CA+v/AgPr/wID\n        6/8BAu3/BwnU/zhGXv81QET/Gh4i/ypDZf8yc77/NnfC/z2Azf9DhND/QoPQ/z+Azf84ecT/LWGa/yU7\n        Uv8rNTr/NTs//zxDSf9DTFb/Nj9M/yYqLf8qLTD/Ki4x/yovMv8qLjH/KCwu/ygrLv8oKy7/Jyos/yYp\n        LP8nKiz/KSwv/ygrLv8nKy//Nj5K/z5HUf82PUP/LjQ3/yQsMP8gNUr/KlqN/zN0u/87fcf/Q4PM/0CB\n        yv9Ag87/On3I/zt/yv8tSmv/HSEj/ycvNP8lLTj/JCw//yMqPf8kKz7/JCw//yQsP/8kLD7/JzA4/yYs\n        MP8YHB//JC00/x8nN/8fJzv/ICg7/yAoO/8fJzv/Hyc6/x4mOv8eJjH/JzE5/x8nLf8TGBz/Hygw/x4n\n        MJAfJy6hHygv/xMYHP8dJSv/PExX/xkfuv8CAu3/AwTp/wME6v8DBOr/AwTq/wIC7v8dJKT/R1he/xYb\n        Hf8yPj7/Fhy2/wEB7/8CA+v/AgPr/wID6/8BAfD/Ehet/z9OUf8pMTb/HCEq/y5ZjP82d8L/OHnE/0GC\n        zv9KitT/SYrY/0GBy/88fMX/Pn/K/zt5wf8yZaD/KUxy/yY8Uv8lLDP/KTA2/yY4Sf8nP1b/Jj5V/yc+\n        Vf8oP1b/Jz5W/yg+Vv8oPlX/Jz1T/yc9VP8nPVP/Jz1U/yg/Vv8nOkz/KS81/yUrMP8lOU3/Kkxw/y5g\n        mP82dLn/OXvD/zp6wv9BhM7/SIrT/0KF0P86fcn/PH/L/zp/y/8vXpH/ISYr/yMqLv8nLzf/JS0+/yUs\n        P/8lLD//Ji1A/yUtQP8lLT//JS04/yoyN/8XGhz/JCwx/x8mNf8gJzv/ISk8/yEpPP8gJzv/HyY6/x4m\n        Ov8eJjT/JC01/yMtNP8SFxv/ICkx/x0mLrUeJS2+HSUr/xIXGv8kLTT/PExd/xIWxv8CAuz/AwTp/wME\n        6v8DBOr/AwTq/wEC6f8qM5D/QlFU/xUZGf80QFL/DRDN/wEC7v8CA+v/AgPr/wID6/8BAe3/HyeL/0BN\n        TP8hJir/ISs+/zJpqv84ecT/PX3H/z+AzP9Njdb/SIjU/0KByf8/fsb/PX3H/0CByv9EhM//QILN/zt1\n        tP8oMDj/KjA0/zdmmP8+f8j/PHrA/z19xf9Dg83/QoHI/0SCyP9CgMb/P33C/z99xf89e7//PXzB/z9/\n        x/85aZ3/Ki80/yctMv87b6r/TJDc/z5/x/86eLz/OnrA/z18xP9Ehc3/R4jQ/0SG0P8/gMv/QoXP/0SI\n        0/80cbT/JTI//x8kJ/8oLzf/Ji09/ycuQP8nLkD/Ji5A/yYuQP8lLT//JCs3/yw0Ov8XGxz/Iyou/yAn\n        NP8gJzv/ISg7/yAoO/8gKDv/Hyc6/x4lOv8fJzb/Iisy/yYwOP8RFhr/HiYt/x4mLs8eJi7RHSUr/w8T\n        Fv8qMzr/Pk1n/w0Q1/8CA+v/AwTp/wME6v8DBOr/AwTq/wID5P80P4H/OkdK/xkdHP8zPmL/Bwjg/wID\n        7P8CA+v/AgPr/wID6/8CA+j/KzVv/zxISf8aHyH/JTlU/zZ0uv88fMb/PX7J/zp7xf9MjNP/R4fR/0KB\n        yv9Af8f/P3/I/0ODy/9Jh8z/QYHJ/zpyr/8qMjv/LDE1/zZjlf9Cg8z/Qn/E/0J/xP9Hhs3/R4bM/0mH\n        zv9Fg8j/RoTL/0SBx/9BfcD/QoDF/0ODyf87ap3/KjA0/yctMv85aqD/SIrT/0F/xf87er7/PHrA/0KC\n        y/9Gh8//Q4bQ/z+By/9EiNX/RYbN/0eK1P83d77/KT9V/xwgIf8pMDf/KC88/ycuQf8nL0H/Jy9B/ycu\n        Qf8lLUD/JCs5/ys0Ov8cISP/ICYp/yIpNP8gKDv/ISk8/yAoO/8gJzr/Hyc6/x4lOf8eJjb/ISkw/ygy\n        O/8QFBj/HiYs/x4nLuMfJy7gHiUs/w8TFv8uOD7/O0lu/woM3v8CA+r/AwTp/wME6f8DBOr/AwTq/wUG\n        4P9ATnv/Mj1A/xwiH/8wO2//BQbn/wID6/8CA+v/AgPr/wID7f8EBdb/NEBe/zdCRf8YGx7/Kkht/zh4\n        wP88e8P/PHzF/0CAyf9Pj9j/S4rT/0KDzf8/fsf/P3/J/0SCyf9LitD/SYnS/z50sP8qMjr/LTI3/zhj\n        kv9EhtH/RYPK/0WCx/9Fgcb/To3U/06N0/9EgcT/RoTJ/0SBxf9Df8P/RYHF/0aDyP89bJ7/KzE1/ygu\n        M/82Zpr/Q4PL/0WFzP9Af8X/PHm9/z5+x/8/fsX/O3zE/zx7wf9DhM//SInQ/0aI0v85eL//LE5z/xse\n        Hv8qMjj/KjI9/yoxRP8pMUP/KTBC/ygwQv8oL0L/Ji49/yoyOf8hJyj/HSIk/yUtN/8hKTv/Iio9/yEp\n        PP8hKDv/Hyc6/x8mOv8eJjf/Hycu/yo1Pv8SFhr/HSUr/x4nLvQeJS3rHiUs/xEUGP8vOj//N0R8/wgK\n        5P8DBOr/AwTp/wME6f8DBOn/AwPs/wcIz/9IV3b/KjM3/yEoJf8pM4T/AgPr/wID6v8CA+v/AgPr/wEC\n        7v8ICsv/OUZa/zE6Pv8ZHR//L1WA/z1+x/88e8L/O3nA/0ODzP9Qj9f/T43V/0WEy/9Bf8X/QH7F/0WD\n        yf9Ni9P/SYfP/z90sP8qMjr/LzQ5/zpllP9HiNH/Q4HH/0WCx/9Nic//Vpjh/1ST2f9Hg8j/R4TI/0WA\n        xP9Fgsf/RoLF/0aEyP88a53/LDE2/ykuM/85aZ7/RobN/0OCyf9BfsP/PXu+/0CByv9Cgcj/QYDI/z+A\n        yv9Gh9H/SYrT/0WFzf86e8P/LleE/x0hIv8pMDb/LDQ+/yszRP8rMkT/KjJE/yoxQ/8oMEL/Jy4+/yky\n        Of8kKi3/GR0f/ycwOf8jKjz/Iyo9/yIqPP8hKTz/ICc7/yAnO/8gJzn/ICgw/yo0Pf8TGBz/HSUr/x4m\n        Lf4eJS3zHSQr/xEUGf8wOz//Mz+A/wUH5f8DBOr/AwTp/wME6f8DBOn/AwPs/wgJyP9IV3H/JS4x/yUt\n        Kf8nL4b/AQLs/wID6v8CA+r/AgPq/wEC7/8LDrv/O0lO/y42O/8aHyP/N2KU/z9/yf89e8L/PXrA/0KA\n        xv9SkNn/UI/X/0iFzP9Cf8X/QX/F/0mGy/9MitH/SIbO/zxvqP8rMzr/LzQ5/zhij/9Li9P/SYjQ/0qH\n        zv9OjNT/UJLe/02M1P9Gg8f/SYTG/0iDxf9GgcT/R4LE/0mFyf87apz/LTI3/ykuNP85aZ3/RoTI/0N/\n        w/9Df8T/QX7C/0ODzP9Ghc3/SIfO/0mK1f9Ih83/T47V/0uN2P86e8X/M2KT/x8lKf8oLjT/LTU//ywz\n        Rf8sM0X/KzNF/ysyRP8pMUP/KDBA/yoyOv8nLjH/GB0e/ygwOP8kKz3/Iyo9/yIpPP8iKTz/ICc7/yAn\n        Ov8gJzr/ICgw/yo0Pf8UGR3/HSQr/x4mLf8fJi34HCMp/xEVGv8zP0T/ND9//wUG5f8DBOr/AwTp/wME\n        6f8DBOn/AwPs/wkKyv9MW3X/JCsu/ycvK/8lLY7/AQLt/wID6v8CA+r/AgPq/wEC7/8NELb/PUpL/y42\n        O/8YHSH/Omea/0GByv8+esD/PnvB/0SDyf9UlN3/TovQ/0eDyP9Cf8T/Qn7D/0aCxv9Ihs3/SYfO/0By\n        q/8rMzr/MDU5/ztmlf9Pj9j/SITI/0yHy/9Uktr/UY/Y/0uGy/9Khsv/SITI/0iEx/9Ggsb/R4LE/0uI\n        zP9BcKT/LjQ5/yovNf84Z5r/RoTH/0qHzf9Jhsr/SIXL/0eFzP9Pj9j/S4zU/02N1f9Li9T/S4vU/0iJ\n        0/87e8P/NWee/x4kKP8oLjP/LjZA/y00Rf8tNEb/LDRF/yszRP8qMUP/KTBB/yoxOf8oLjL/GB0d/ycv\n        N/8jKjz/Iyk8/yMqPf8iKTz/ISg7/yAnOv8fJzn/ICcw/yw2P/8VGh7/HCMp/x4mLf8fJy74HSMo/xIW\n        Gf80P0T/Mz19/wQG5P8DBOn/AwTp/wME6f8DBOn/AwPs/woMy/9MW3X/ISgq/yoyLv8jK5f/AQHu/wID\n        6v8CA+r/AgPq/wEC7/8OEbf/PktM/y42PP8XHB//OWaX/0KByv9BfcP/Q4DG/0mHzf9Wlt//T4zP/0mF\n        y/9Ih8//RoLH/0mEx/9Khsv/SYbL/z9xqv8sNDv/MTY7/z5qmv9ZmOH/TIfL/0uGyP9VkdX/VJHW/1WS\n        2P9SjdD/Uo7S/0+Kzf9Jg8X/SoTF/1GN0P9Hd6v/LzU5/ysxNv86aZz/SIXL/0yL1P9Mic7/SYXJ/0iG\n        y/9Sktr/T43T/0uJz/9Mjdb/RYbP/0CAyP87er7/Nmec/x0jJ/8pLzT/LzdA/y41Rv8tNEb/LTRG/ysz\n        RP8qMkP/KjFB/yoxOf8pMDT/Fxsc/yYuNf8kKzz/Iyo9/yIpPP8hKDv/ISc6/yAnOv8gJzn/ICcv/yw2\n        Pv8VGh7/HCMp/x8nL/8gJy7zHiQr/xIVGf8yPEH/ND9+/wUG5P8DBOn/AwTp/wME6f8EBOn/AwPs/wkK\n        yf9MWnP/ICcp/yozMP8kLI3/AQLs/wID6v8CA+r/AgPq/wEC7/8NELX/PUlK/zA4Pf8aHyH/OmaW/0B9\n        w/8/e77/QX7D/0uHzv9Uktb/VZLX/06Kz/9IhMr/R4PI/0+Kzf9Ri83/TYnP/0J0rv8tNDv/Mzg8/0Fs\n        mf9dnOP/UIvQ/1GLzv9bmN3/Xpvi/1KP1v9Oicz/VZHV/1GMzv9Mhsj/U43P/1GN0f9DcKP/Mjg8/y0y\n        N/9Ec6b/UI3U/06M1P9Hg8j/Q4DF/0OAxP9EhM3/SobK/1GP1v9Tktj/TYzS/0OByP89er7/N2aZ/x8m\n        Kf8pLzP/MDdB/y41Rv8uNUb/LTRF/ywzRP8rMkP/KTBB/yoxOf8qMjX/Fhsb/ycuNv8lLD3/JCs+/yMq\n        Pf8iKTz/ISg6/yAnOv8fJjn/ICcw/yw1Pv8VGh7/HCMq/x8nL/8gKDDqHyYr/xEVGP8zPUL/OESD/wYI\n        5f8DBOn/AwTp/wQE6f8EBOn/BAPs/wgJyP9JVm//Iikr/ygwLf8mLoP/AgLr/wID6v8CA+r/AgPq/wEC\n        7/8LDbv/PEhO/zI7P/8bICL/OmWV/0OAxf9BfcD/RH/D/0qGy/9UkNP/V5TW/1KO0v9JhMj/R4HE/02H\n        yv9Uj9T/Wpfb/0l7s/8tNDv/Mzg9/z9olf9ameH/VZHW/1SQ1P9em97/XZne/12a3v9Sj9P/VpHV/1SO\n        0P9PiMn/VY/Q/0+Ly/8/bJv/Mzk+/y40Of9Gdar/VZHX/1GP1/9Lh8n/RoLF/0WAw/9EgMb/R4PI/0mF\n        yv9PjdP/UY/V/0iHzv8/fcP/N2SW/x4kJ/8oLjP/LzZA/y82R/8vN0f/LTRF/ysyQ/8rMkP/KS8//ygv\n        N/8oLzP/Fxsc/ygvN/8mLT7/JSw+/yQrPf8jKjz/Iik8/yEoO/8fJjn/ISgw/yw2Pv8VGR3/HSUr/yAn\n        L/0jKzPfISgu/xEUGP8yPEH/PEl9/wkK4/8DA+n/AwTo/wME6f8EBOn/BATr/wcI0v9GU3P/JS0u/yYu\n        K/8qMoL/AgPr/wID6v8CA+r/AgPq/wEC7f8GCMr/OERY/zdARP8aHR7/NFd8/0OAxP9CfL3/RYDD/0qG\n        zP9WktP/VpLT/1OP0v9Mh8n/SIPF/0yHy/9TjtH/W5fZ/0h4rv8uNTv/NDg9/0Jqlf9Wktj/VI/T/1eR\n        0v9emd3/Uo3Q/1yW2f9bmN//XJnf/1uW2P9Qicn/UYrK/1OO0P9BbZ3/Mjc8/y4zOP9Id6r/YZ7i/1KO\n        0v9Ois//SoTG/0eBw/9Ff8L/RYHG/0aCxf9Lh8n/U4/T/0qHzP9Cgcj/NVyH/x0gIP8sMzn/LjU//y40\n        Rf8vNkb/LjRF/ywzRP8rMUP/KS8+/yoxN/8oLzL/GBwd/ykwOf8nLT//Ji0//yUrPv8jKjz/Iig7/yEo\n        O/8fJjf/ISgv/y03P/8UGBz/HyYs/yAoMPIkLDXQISgt/xAUF/8yPEL/Qk9w/wsN3f8DA+n/BATo/wQE\n        6f8EBOn/BATp/wUG4P9BTXr/KjMz/yMqKP8xO2z/BQbl/wID6v8CA+r/AgPq/wID7P8EBdb/Mjxb/z1I\n        S/8bHR7/MUxo/0N+wf9Dfb7/SILG/0+Kz/9aldb/Xpnc/1eS1v9Nh8f/SoTF/1OO0v9YlNb/WZXX/0h5\n        r/8vNjz/Njo//0ZumP9gm93/V5HT/1iS0/9YlNf/V5LU/2Cb3f9fmt7/Xpvg/1WR1f9Sisr/UorJ/12a\n        4f9GcqP/MTY6/ywyNv9Cb6D/Xpzf/1qV2P9altv/VI7P/0uFxf9IgcL/RoHD/0WAw/9LiM7/VpXb/0mG\n        yf9FgsX/NVV1/xseHv8xOD7/LzVA/y40Rf8vNkb/LjVG/y00Rf8sM0T/KzJA/y00O/8oLjH/GBwd/yow\n        Ov8nLT//Jy4//yYsPv8kKz3/Iik7/yEnOv8hJzj/Iikw/yw1Pf8SFRj/HyYs/yEqMuEkLDS8Iykw/xIW\n        Gf8tNjz/RVNq/w8S1P8CA+r/BATo/wQE6P8EBOj/BAXp/wID5P87RIr/Mjs7/x0jIf81QGP/Bwjf/wIC\n        6v8CA+r/AgPq/wID6v8BAuf/KDBs/0JNTf8hJSf/KDlI/0R8vP9JhMf/TIbH/1OR2P9altn/Xpnb/1aQ\n        0P9Picr/T4jL/1WP0f9Vjs//WZTW/05/tf8wNz3/NzxA/0Rsmf9joOT/WpPV/1qU1v9aldr/W5XV/2Wf\n        3/9dmNr/WpTV/1mT1f9YktX/XJXV/2Oh5/9Kd6f/MDY6/ywyNv8+apv/VI/R/1GMzv9Xldv/VpHT/1ON\n        z/9TjtH/UIrM/0uFx/9IhMn/S4jO/0aBxP9HgcL/LUJW/x8jJP80O0L/MThE/zA3R/8vNUX/LTNE/ysx\n        Qv8qMEL/LDNA/y83Pv8kKSv/Gh4f/ykvOv8mLD7/Ji0+/yYtP/8lKz7/JCo8/yMpPP8iKDf/JCsy/yoz\n        O/8RFRj/ICct/yEoMc0kLTWdJCsy/xUZHP8oLzX/SVZm/xcaxv8CAuv/BATo/wQE6P8EBOj/BAXo/wID\n        6P8vNpX/PEZG/xkeHv85RFT/DxLL/wEC7P8CA+n/AgPp/wID6f8AAez/HSKH/0RQTf8qMDP/ISow/0N1\n        r/9Ois3/TYfI/1GM0P9altr/XJbX/1mS0/9Vj9D/VpHV/1uV1f9bldf/Y5/i/1GCtf8wNz7/OT1C/z9l\n        j/9altr/W5PU/1qS0v9fmNn/X5na/16X1P9ZktL/XpfY/1iPzP9Zk9P/YZze/2yp6f9Qfaj/MDQ4/ysw\n        NP8+aZj/U43P/1KNz/9ZmN//Wpba/1ON0P9UjtD/VpDR/1KN0f9NitD/TonN/0mFyP9Hfbv/JTE6/yUq\n        LP82PUT/MThG/zA2R/8wNkb/MDdH/ywyQ/8sMkP/LTQ+/zE4Pv8fJCb/HiIl/ykwPP8oLkD/Jy0//yYs\n        Pv8mLD7/JCs9/yMqPP8iKDb/Jy41/ygwOP8SFhn/Iikw/yAoMbIkKzV7JSwz/RYZHf8iKC3/TFpj/yEn\n        uv8CAuv/BATo/wQE6P8EBej/BAXo/wID7P8eIqf/RlFU/xMXGP87RUX/GB2y/wEB7v8CA+n/AgPp/wID\n        6f8BAu7/DxKr/0FMT/82PkL/GRwc/zpgif9Oicz/T4nL/1KM0P9ineH/YJrc/1uU1f9Vjs//V5LX/1mR\n        zv9Md6f/RmOC/z1QYv85QEb/PEJI/zVCUf88UGT/PlFl/z1QZP8+UWX/P1No/0BTaP8+UWb/QVVr/0BU\n        aP8+UGX/PlJm/0JWa/85SVj/Nz1D/zlARf82SFf/PFh0/0Rtmv9cltf/YJ3k/1CJy/9UjtH/W5XW/1WQ\n        0/9Oic3/SYPG/0mFyv89aJf/HSEj/y40Of8zOUH/MDVF/y81Rv8vNUX/LzZG/y0zRP8sMkP/LTM8/zE4\n        Pf8ZHR7/Iygs/yoxP/8oL0D/Jy0//yctPv8mLT7/JSs9/yQqPP8iKDX/KzM7/yUsM/8TFxr/Iyox/x8n\n        MI0nMDlTJi009BsfJP8aHiP/SFRY/y42pP8DA+r/BATo/wQF6P8EBej/BAXo/wME6/8RFL7/S1hk/xUY\n        Gf82QD7/JCuP/wIC7f8CA+n/AgPp/wID6f8CA+v/BgfS/zZAWP9BS03/HCAh/y1CVv9Ris3/VY/S/1eQ\n        0/9jnt//ZJ7d/1+Z2/9Ti8v/Rm6c/zhKW/87Q0f/QUdL/0hOVP9MU1v/SE9Y/zA0N/8vMTP/MTM1/zI0\n        Nv8yNTb/MjQ2/zI0Nv8zNjj/MzU4/zQ2Of8zNTf/MDIz/y8xMv8uMTP/Q0pS/05WX/9LUVj/SU9T/0RM\n        UP9DVWT/S3Od/0+Gxf9bmN3/XZjZ/1aP0P9WkNP/U43P/0mDx/8yTGb/HB8f/zQ7Qf8xN0H/MDZG/zE3\n        R/8xN0j/MTdI/zA2Rv8uNEP/LTM6/zA3PP8VGBn/Jy0y/yowP/8pL0D/KC9A/yctP/8mLD7/JSs9/yQq\n        PP8jKTP/MDlB/x8lKv8XHCD/Iioy+iApMWYqMz0wJzA34SEnLP8UGBv/QUxQ/zxGiv8GB+f/BATn/wQF\n        6P8EBej/BAXo/wQF6f8HCNX/R1F1/x4jI/8sNDL/Mjxt/wUG4/8CA+r/AgPp/wID6f8CA+n/AQLo/yIo\n        eP9HUlD/Ki8z/yAoLv9LfbT/VZDT/1uV2P9rpuX/ZqLl/1OHwf84Tmb/OkBF/0dNU/9LUlv/SlBa/0pP\n        Wv9MUlz/Q0lR/yI0Rv8pRF//K0dj/ylCXf8qRF7/LUdg/yxFYP8rRmL/KkNc/ylBXP8oQFv/KEFc/ydB\n        XP8jN0v/O0FI/05UXv9JT1n/Sk9a/0xRW/9MUVj/REtQ/zlOYv9Qg7z/YZ3h/16Y2v9cltn/XZja/0l8\n        tf8kLzf/Jios/zg+Rf8zOUb/MjhI/zE2Rv8xN0f/MTdH/zE3R/8vNUL/LzU8/ywzNv8VGBn/KjE5/yow\n        Qf8pL0D/KC5A/yctP/8nLT//JSs9/yQqPP8kKzP/MzxF/xgdIf8dIif/Iysy6yIsND0sND4SJy83wSQr\n        MP8TFxr/OkRK/0hUef8MDdz/AwTo/wQF6P8EBej/BAXo/wQF6P8CA+X/Nj6Q/zA4N/8eIyT/PUhS/w8S\n        yf8BAez/AgPp/wID6f8CA+n/AQLt/w4RsP9CTFH/PkdM/xodHf85VnT/UYvN/1iS1f9uquv/VYO2/zdF\n        U/8/RUn/SlBZ/0pQWv9JT1n/SU9Z/0lPWf9MUlz/O0NJ/0Rvn/9gm9z/ZaHh/2Kc3f9vq+z/dLDt/2um\n        5f9rpeX/ZZ/d/2Ob2/9gmdj/XpfW/1+Z2f9Leq7/MztD/05VXf9JT1n/SU9Z/0lPWf9JT1n/S1Fa/0hO\n        U/87SFP/T3qq/2mp7/9emNn/WJPW/zxdgf8bHR3/Mjg+/zU7Q/80OUn/MzlI/zI4SP8yN0f/MTdH/zE3\n        SP8xOEL/MzpA/yQpLP8aHiD/LDI9/yowQf8rMUH/KS9A/yctP/8nLT7/Jiw+/yUqOv8nLjX/ND1G/xQY\n        G/8hKC3/JCw00iQuNxw8R1ECJy83kycuNf8VGBv/LjU8/1Jea/8ZHcf/AgLq/wQF5/8EBej/BAXo/wQF\n        6P8DA+v/HyOu/0dSVf8TFhf/PkhF/yEnmf8BAe3/AgPp/wID6f8CA+n/AgPq/wID3/8sM2r/SVRU/ykt\n        Mf8gKC//SXmu/1eR0v9XgrD/OkVN/0dNUv9KUFr/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9MUVr/LzpF/1aI\n        wf9pod//YpnV/2Wb2P9tpuP/erXy/3Ot6/9spOH/Z57c/2ee2v9lnNn/ZJzZ/2Oa2P9aj8n/Lj1L/0pQ\n        Vv9JT1r/SU9Z/0lPWf9JT1n/SU9Z/0pQWv9KUFf/PUdO/0x2pP9dmNr/UYbB/yczPv8jJij/NTtA/zM4\n        RP80Okr/NDpJ/zQ6Sv80Okn/MzlJ/zI3Rv8xNz7/NTxC/xkdHv8iJyv/LDJA/yswQf8qMEH/KS9A/ygu\n        P/8nLT7/Jis9/yQqN/8tNDz/LjY+/xMXGv8lLDP/JCw1pyo2QAYoMDoAKTE6XCkwOPobHyP/ICUq/1Fd\n        Yf8wNqj/AgLr/wQF5/8EBef/BAXo/wUF6P8FBer/CgvP/0pUcf8XGxr/MTk3/zU+av8GB+H/AgPq/wID\n        6f8CA+n/AgPp/wEC7f8RE6f/RlBT/0FKTv8ZHBz/NlBs/0p4rv82QUz/S1FW/0pRW/9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0pQWv9ESE3/NE9q/2ae3f9ooN//ZJvX/2ee2v9qot//bafm/2uk4v9qod7/b6bj/3Ss\n        6P9qot7/Z5/d/2Sb1/9nn93/OVh6/z9DR/9MUlz/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1r/S1BY/zhC\n        Sv9Idaj/PV1//xsdHf81OkD/NjtD/zY8S/83PUz/NjxL/zU7S/81O0v/NDpJ/zM5Rv80OkD/MDc7/xQX\n        F/8sMjj/LjRE/ywyQ/8rMEH/KS9A/yguP/8oLT7/JSs8/yQpNP8zO0P/JCsw/xgcIP8nLzb+JS02cCIq\n        NAArND4AKzM9KioxOuEhJiv/Fhod/0dSVf9GT43/Bwjl/wQF5/8EBef/BAXn/wUF5/8FBef/AgLn/zc+\n        lP8yOTb/HiMl/0FLTv8XG7b/AQHt/wID6P8CA+n/AgPp/wID6v8CAuH/KzFv/05ZVv8wNjr/HSMo/zFA\n        Tv9FTFH/S1Fb/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0tRWf81Pkb/Tnyv/2mi4f9nn93/Zp7a/2uh\n        3f9yqub/babj/3Cn4/99tfD/dq7q/3Os5/9rot//bqXi/22k4f9ro9//V4i+/y44Qv9LUVj/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/Sk9Z/0pPVv80Qk//HiYr/yswM/89Q0r/OT9L/zk/Tv85Pk3/Nz5M/zY8\n        S/82O0v/NTpK/zQ6Q/82PUP/JCos/xkdHv8xN0H/LzRF/y0zQ/8sMkL/KjBB/ykvQP8oLT7/Jis8/ycs\n        M/82Pkf/GR0h/x8kKf8oLzfsJi84OigwOQAvNz8AMTpECiszO7ApLzX/FBYZ/zY+RP9UX3X/FRjR/wID\n        6f8EBef/BQXn/wUF5/8FBef/AwPr/xgbuv9JU1r/ExcX/zxFQ/8wOHn/BAXn/wIC6f8CA+j/AgPo/wID\n        6P8BAu3/Cwy7/0RLWf9LVFf/JCgq/zE1OP9MU1z/SE9Y/0lPWf9JT1n/SU9Z/0lPWf9JT1j/SlBa/0FG\n        S/88WXj/aKDe/2qh3f9rod3/baTg/2yi3f9vpuL/cKjm/3au6v9/uPP/fLXw/3ev6/9vpuL/bqXi/2yk\n        4f9vpuL/cKnm/z5egv85PUH/S1Jb/0lPWP9JT1n/SU9Z/0lPWf9JT1n/SU9Y/0tSXP81Oj7/ICQl/z1D\n        Sf87QEn/PEFQ/zxBUP87QE//O0BP/zk/Tv83PU3/NjxJ/zQ6Qf82PUL/Fxob/yUqLv8wNUT/MDVF/y40\n        RP8tMkP/KzBB/yguP/8nLT7/Jis5/ywyOf8zO0P/FBca/yctM/8mLjbCKTI7EikxOQAtNj8AJi83ACoz\n        O2wsMzv9Gh4i/yQoLf9XYmj/MTet/wIC6v8EBef/BQXn/wUF5/8FBef/BQbo/wQF3/9BSYX/JSon/yYs\n        Lv9BS1P/Fhq7/wEB7f8CA+j/AgPo/wID6P8CA+j/AQHq/xsekP9RWln/RU1S/yImKP87QEb/SlFa/0hP\n        WP9IT1j/SE9Y/0hPWP9JT1n/SU1T/zJDU/9ekcr/baTi/3qy7f9xqOT/a6Ld/2yj3v9to97/baPe/3Go\n        4/98tfD/ebLu/3Or5/9zqub/b6fj/2yi3v94sOz/dKzq/1+U0f8tQVX/Q0dL/0pRWv9IT1j/SE9Y/0lP\n        WP9IT1j/SlFa/z9FTf8iJij/Oj9F/z1DS/88QU7/PUNS/z1DUv88QlH/O0FQ/zo/Tv85P07/OD5H/zg/\n        Rf8rMTT/FRkZ/y81Pf8wNUb/MDVF/y81Rf8tM0P/LDFC/yovQP8oLj//Jiw2/zU9RP8nLTP/Fxse/yox\n        Of8nLziBGRojACYvOAAAAAAAKzQ9ACs0PSwsNDzhJSou/xcaHf9IUVb/TVaI/wkL4f8EBOf/BQXn/wUF\n        5/8FBuf/BQbn/wME6/8eIrT/R09T/xMWF/8+R0X/NT11/wYH4/8CAun/AgPo/wID6P8CA+j/AgPq/wID\n        3v8sMXf/WGFe/0BHS/8gIyb/QEVM/0pRWv9ITlj/SE5Y/0hPWf9KTlX/MjtG/1F+r/9vp+P/cKfj/4G7\n        9f91ren/baPe/2+l4P9vpd//b6Xg/3Sr5/96su//d6/q/2yj3v9wp+L/c6rm/3u07/9+t/L/b6Xi/2yj\n        4v9Yir//KTVA/0ZLUP9KUFr/SE5Y/0hPWP9JUFr/Q0lR/yQoKv87QEX/RUtT/z9FUP8/RFP/P0VT/z1C\n        Uf87QVD/OkBP/ztAT/86P0z/OD5F/zg/RP8YGxv/JCks/zQ5R/8xNkb/MDVF/y80RP8uM0P/LDFB/yow\n        Qf8pLz7/KzE4/zpCS/8ZHCD/ISYr/ygwOOsmLjg7Jy84ACUuNwAAAAAALTU+AC43QQYrMzykLDM5/xYZ\n        HP8zOUD/XWh0/yInxf8CA+r/BQXn/wUG5/8FBuf/BQbn/wUG6P8GB9z/Q0qD/yMnJf8oLS//R1FR/yEl\n        qP8BAu3/AgPo/wID6P8CA+j/AgPo/wEC6/8FBs//O0Bs/15nZP9AR0v/Iycp/z9FTP9KUFv/SU9Z/0lN\n        VP8xOkL/Tnaj/3Oq5/94r+r/dq7r/3au6f97s+3/dq3o/3Go4v9zqeT/frfu/4nD+f99tvH/dq7p/3Or\n        5v92rej/eK/q/3ev6/9/uPP/dKvo/3Kq5/94svD/UX2t/ygyPf9DR0v/SlBa/0pQWv9DSVH/JCgr/zQ5\n        Pv9ES1H/Q0lU/0RJWP9BR1X/P0RT/z1CUf88QlD/PEFQ/zpATv85Pkb/OT9F/ysxM/8UGBj/MzhA/zQ6\n        Sf8xNkb/LzVE/y4zQ/8tMkL/LDJC/yowQf8pLjr/MzpB/zM6Qf8UFxr/KS81/ycvN7QoMToNKDA6AAAA\n        AAAAAAAAAAAAACw1PQAsND1TLzc/9SAkKP8eISX/VV5i/0lSmf8ICOb/BQXm/wUG5/8FBuf/BQbn/wUG\n        5/8DBOr/Gh28/0dOWP8UFhb/PUVF/0JLY/8RE8//AQHr/wID6P8CA+j/AgPo/wID6P8BAuz/CQrE/0JH\n        av9kbGr/Q0tO/yMnKf88QUf/SU5V/zdFVf9Peqn/dq7q/3Ws5/94sOz/dKvm/3Ko4/96sev/gLny/3Sq\n        5f9+te//kMv9/4bB9/+Cu/P/gLjy/3uy7f92reb/icX2/3627/+Du/P/erLt/3Go5P91ru3/e7Ty/1OD\n        t/8uQlX/QUdM/0FGTf8nKi3/ODxB/0VKUf9CR1H/Q0hV/0RJV/9DSVf/QUZV/z1DUf87QE7/OkBP/ztA\n        Sv85P0X/Nj1C/xYaGv8mKy7/NTpI/zQ5Sf8yOEf/MTZF/y4zQ/8tMkL/LDJC/ywxQf8sMTr/PkZP/yIm\n        K/8dICX/LDM7+icwOWQmLDYAMjpBAAAAAAAAAAAAAAAAAC42PwAtNT8ULzc/wy4zOv8VFxr/OT9G/19q\n        ef8fIsn/AwPp/wUG5v8FBub/BQbn/wUG5/8GBuf/BATk/zk+lP8sMS7/HyMl/0hRTv84PoH/Bwjk/wEC\n        6f8CA+j/AgPo/wID6P8CA+j/AQLs/wkKwv9DSHH/aXFt/01UWP8oLC7/JCYo/0hmh/91rOf/dq3p/3Op\n        5P95sOr/dazn/3iv6v98s+3/h8D2/3mv6f99tO7/grv1/4C48/+Oyfn/jsj4/3mw6v90quT/g730/4vF\n        +/+CuvP/frbw/3Oq5/90rev/frfy/3+48P9Wepv/IiYo/ycqLP9ARUv/SE1V/0NIUv9GS1n/R01b/0ZM\n        Wv9GS1n/Q0hW/0BGVP89Q1H/O0BM/zo/Rv87Qkj/Iykq/xcbHP80OkT/NjtK/zU6Sf8yN0f/MTZF/y80\n        RP8uM0P/LDFC/ysxPf81O0P/OUBI/xUYG/8pLzX/KzI70CkxOx0qMjsAAAAAAAAAAAAAAAAAAAAAAC01\n        PgAsNj4ALjY/aTI5QfsgIyf/ISQp/11nbP9JUJ7/Bwfl/wUG5v8FBub/BQbm/wUG5/8GBuf/BQXp/w0O\n        0f9GTW//Gh0a/zA2Of9NVlX/LjKd/wMD6v8CA+j/AgPo/wID6P8CA+j/AgPo/wEC6/8HCMv/Oz97/291\n        cv9dZGb/MTY5/yEjJP9AUWH/Z465/3Wq5P95se3/erLw/3qx7P95sOz/grr0/3yy7P95sOr/ebDq/4S8\n        9f+HwPf/e7Lt/3iu6f93rej/gLjy/4G58v+BuPL/e7Lt/3Ss6f91rOn/bprD/0RZa/8hJSb/LzM0/0VL\n        UP9KT1f/RUlU/0RJV/9FS1n/Rkxa/0ZMWv9FSlj/Q0lX/0JIV/9ARVP/PkNK/z1ESv8xODv/EhUV/y80\n        Ov84PUz/NjxL/zU6Sf8yN0f/MDVF/y80RP8uM0P/LDFB/y0yOv9ASFH/JSou/xwfI/8vNj3+KjE7ewYG\n        GwArMzsAAAAAAAAAAAAAAAAAAAAAAAAAAAAxOUMAMDlCGzA4QcouMzr/Fxkc/0BGTf9ncn//JirF/wID\n        6f8FBub/BQbm/wUG5v8GBub/Bgbm/wQD6f8gIrT/QklO/xYYGP8+RUf/TlZd/yQntP8CAuv/AgPn/wID\n        6P8CA+j/AgPo/wID5/8BAuv/AwTZ/ystj/9pbnT/cnp3/05VV/8pLC3/Jior/0JSYv9ihav/d6nf/3y0\n        7v9+tvH/f7fy/3617/97sev/e7Lt/4fA9v+Jwvb/f7bv/4O88v94rur/eK/q/3uz7/98s+//dafd/2CF\n        rP9EVmn/Jisu/yYpKP9QVVb/dXt6/1hfY/9ITVT/SU9Z/0hNW/9GS1n/RUtZ/0VLWf9DSFb/QUdV/0JH\n        Vf9ARk7/P0VL/zpBRv8XGxv/Iycr/zg9Sv83PUv/OD1M/zU6Sf8zOEf/MjdG/zA1RP8vNET/LzM//zg+\n        R/87Qkr/Fhkc/ykuNP8sMzvYKTE6JioyOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1PEMAJi87AC82\n        QGg0O0P5Iycr/yAjJ/9cZmr/Vl+X/wsN4f8EBef/BQbm/wYG5v8GBub/Bgbm/wYG5/8EBOX/MTSc/zM3\n        Nf8cHyD/Rk1P/1JZZf8iJbv/AQLr/wID5/8CA+f/AgPn/wID5/8CA+f/AgPp/wAB5v8TFLD/UFR//36D\n        gP90e3r/SlBS/ysuLv8lJib/OUJJ/1Npfv9pi63/fKnW/4Cz5P99sur/gLfx/4O89f+Cu/T/g7v0/43G\n        9P96ruH/dqPU/2qNsv9TaH//Nz9H/yMlJf8qLSz/T1RV/3d9ev9uc3v/UVV9/3B2d/9MUlj/Sk9X/0lP\n        W/9HTFr/RUtY/0VKWP9DSFb/QkdU/0JIUf9BRk3/PURK/x4iJP8aHh//Oj9K/zk+TP83O0r/NjxK/zY7\n        Sv80OUj/MjdG/zA1Rf8wNUP/Mjc//0RMVf8iJir/HiEl/zA3Pv0qMTp8KT5CACoyOgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAALzdAAC42PxUxOUG9MzlA/xkcH/84PkX/bXd+/zk/uf8DBOj/BQbm/wYG\n        5v8GBub/Bgbm/wYG5v8GBuj/Bwjd/zxAh/8nKiX/Iyco/01UVf9VW2z/JCa//wIC6/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID6P8BAev/AwTX/yMlnv9fYoH/h4yJ/4KHhf9hZ2j/QERG/yosLP8qKyv/MjY3/z1F\n        TP9KV2X/UmN0/1Zpev9Ya3v/VGZ3/09daf89Rk7/MDM2/yosK/8rLCz/QUVF/2Rqaf+DiIP/fICE/0lM\n        h/8SE7T/BgbR/1VZhv9qcW7/SE5U/0pPWP9LUF3/SE1a/0VLWf9DSFb/Q0hS/0BGTP8+RUv/JCgr/xUY\n        Gf83PET/PEBP/zo/Tv85Pk3/NztK/zQ5SP80OEf/MjdG/zE1Rf8wND7/PkVN/zc+Rf8XGRz/LTI4/y01\n        Pc0sNDwfLTQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDpDAC00PQAvNj9RNTxE8Sou\n        M/8cHyL/VV1j/2x2kP8eIdT/AwTo/wYG5v8GBub/Bgbm/wYG5v8GBub/BQXo/w0O1P89Q3f/ISQe/yku\n        MP9PV1j/XGJv/yotvP8CA+r/AQLo/wID5/8CA+f/AgPn/wID5/8CA+f/AgPp/wAB6f8FBdH/JSaj/1lb\n        jP+Hi5D/lJmT/4uRjv90enn/X2Rl/01RU/8+QEH/Nzk4/zAxMP8vMTD/Njg3/z1AQP9PUlP/YGVl/3V7\n        ef+Nko3/j5OP/3V4if9FR4//Fhez/wEC3v8BAur/AAHr/xkavf9vc3r/W2Fk/0pQVv9LUFr/SU5c/0ZL\n        Wf9GS1T/RElP/0BHTP8pLjD/FBYX/zU5QP89QlD/Oj9O/zk+Tf85PUz/OD1M/zY7Sv80OUj/MTZF/zA1\n        Qf83PUT/Rk5W/x4hJP8jKCz/MThA9yszO2InMjoALDE6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAC81PgAtNDwJMDdAnDc9Rf8fIiX/Ki4z/2t1ev9bY6X/DA3h/wUF5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wUF6f8QEc//Q0dy/x8hHP8pLTD/UFhZ/2Nocf85PLH/Bwjm/wAB6f8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+n/AAHp/wEC2/8REr3/MTKi/1pclP96fZb/kZSZ/5qem/+gpJ//oKWh/6Ck\n        oP+fo5//oKSg/52hnf+VmZf/i46Z/25xkv9KTJb/IySp/wkJyP8AAOL/AQLq/wID6P8CA+f/AgPn/wEB\n        5v84Opv/c3hz/05UWv9LUVj/R0xY/0dMVP9FSVD/P0ZM/yovMf8UFhb/Mzc9/z9EUv88QU//PEFP/zo/\n        Tf84PUv/NzxL/zc8S/81Okn/MTZE/zI3P/9HTlf/LDE2/xsdIP8zOUD/LjU+rC01Pg8tNT4AAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC41RAAxOD8AMDc/KjQ7Q9Q1OkD/GRwe/0BF\n        TP92gIf/RUu2/wYG5v8FBeb/Bgbm/wYG5v8GBub/Bgfm/wcH5v8FBej/ERLM/z9Cc/8iJR//Jiss/01U\n        V/9obm3/UlWi/xYW2/8AAer/AQLn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID6P8BAur/AADp/wEB\n        4P8FBs//DxC9/x4ft/8uL6n/NTes/zc5p/84Oqf/NDar/ykqqv8ZGrj/CwvB/wME1v8AAOP/AAHq/wEC\n        6v8CA+f/AgPn/wID5/8CA+f/AgPn/wEC6f8ICdb/V1uE/2Vsa/9ITlT/Sk9V/0RKUP8/Rkv/Jywt/xMX\n        Fv80OD7/QUZT/z1CUP88QU//PUJQ/ztATv85PUz/NjtJ/zU5SP80OUf/MzhA/0NKUv88Qkn/Fxkb/y4z\n        OP8yOUHfLDI6NywyOwAxNjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAzOkIAKjM/ADE4QV45QEnyLTI3/xseIf9TWmH/eYOP/zM3xv8DA+j/Bgbl/wYG5f8GB+b/Bgfm/wcH\n        5v8HB+b/BQbp/xET1f8/Q33/JCYh/yMmJv9IT1P/Z21q/2xxj/8yNMf/Bgfm/wAB6P8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+n/AQLr/wAB6/8AAOn/AADo/wAA6P8AAOf/AADo/wAA\n        6f8AAev/AQLr/wID6P8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wEC5/8AAO3/Jym3/3Z7\n        ff9UWV7/RUpS/0BGS/8iJyf/FRgY/zg8Qv9CR1X/P0RS/z9EUv9ARVL/PUJQ/zs/Tv86P03/ODxL/zU5\n        SP80OEL/QEZO/0lQWP8dICL/Jiou/zQ6QvctMzxuM0FHAS82PgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANj1HADY9Rwk1PEWSPEJL/iUpLP8kJyr/Ymlv/3F6\n        lv8jJdH/AwPo/wYG5f8GB+X/Bgfm/wcH5v8HB+b/Bwjl/wYH6P8MDdr/NTiP/zI0M/8dIB3/PkRI/19m\n        Zv95foL/YmWt/yQl1/8DA+j/AAHo/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8BAuf/AADp/wsL5P82OMj/a2+X/2lucf9NU1n/O0FE/xseHv8cHyD/P0NL/0dMWf9BRlT/P0NR/z1C\n        UP8/Q1H/PEFP/ztATv85Pkz/OT1M/zc7Rv87QEf/TVRc/yYpLf8hJCf/OUBH/zE3QKMsMjsPLjQ9AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ7\n        RAA0O0MbNz5HuTxCSv8hIyf/LDA1/212e/9udp7/HR/U/wMD5v8GB+X/Bwfl/wcH5f8HB+X/Bwjm/wcI\n        5f8HB+f/CAjj/ykrqP82OUn/HB4Y/y8zNf9SWV3/cXd2/4OHlf9hZLr/JifX/wYG5/8AAOj/AQHn/wID\n        5v8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8BAuf/AAHn/wAA6P8ODuP/OjvO/3BzqP97f4H/X2Rm/0ZNUv8uMjT/FxkZ/you\n        MP9JTVX/SE1a/0ZLWP9ESVf/P0RS/z5CUP8/Q1H/PUFP/zs/Tf85PUz/OD1J/z5DS/9SWWL/LzM3/xse\n        If83PUT/NDtEyDA3QCYwNz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADpBSAAyOUIANDtDMzg/SNQ6P0X/HiAj/zk9Qv94gYb/cXmm/x0f\n        2v8DBOb/Bwfl/wcH5f8HCOX/Bwjl/wcI5f8ICOX/CAjm/wUG5/8YGcj/OTt2/yYoJf8iJSL/QEZJ/1xj\n        Z/98gX//jpKc/3Z4vf9ERdL/GBni/wQE5/8AAOf/AAHn/wEC5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wEC5v8BAub/AADn/wEB5/8ICeX/IyTc/1JTyv9/ga3/hoqL/2ht\n        bf9NVFn/O0BE/yEjIf8bHR3/foSM/3+HkP9JTlX/R0xX/0VKWP9FSlf/QkdV/z9DUf89QU//PUJQ/ztA\n        Tv86P0r/P0RM/1RbZP83PEL/Gh0f/zU5QP82PEXeLzY+QSswOgAzO0MAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5QEYAKzI7ADI5\n        QUs6QUnjOT1D/xweIP87P0T/fYaL/3Z/rv8gItj/BAPm/wcH5f8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgJ\n        5f8GB+j/DAzf/yUmpP8uMEz/IyUd/ygqKP9ESk7/XmVo/3qAfv+Xm5v/mJu3/3t9yv9OUNj/Kivg/xMT\n        5f8GB+b/AAHm/wAA5/8AAOf/AADn/wAA5/8AAOf/AADn/wAA5/8AAOf/AQLm/woK5v8XGOP/Njfd/1tc\n        0/+Chb//l5uo/4mNiv9pbm//T1Zb/0FHSv8qLSv/FhgS/yMkQf8ZGpv/X2TB/7K8wv9cYmr/RktS/0ZK\n        V/9ESVb/Q0dV/0FFU/8/Q1H/P0NR/z1BTf9CSE//WGBp/zxARv8aGx7/Mzc9/zpBSesyOEFaMzM6ADQ6\n        QgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAANjxEADc/RAE0OkJdPENL6zg8Qv8dHyL/PEBG/32Gi/9/h7H/JijZ/wMD\n        5v8HB+X/Bwjl/wcI5f8HCOX/CAjl/wgI5f8ICeX/CAnm/wcH6P8TE9T/JyiP/x4fN/8hIx3/LTAs/0JH\n        Sf9WXWL/a3J1/4SKif+eoqH/p6q4/6Kkxv+MjdL/eHrZ/2Rm3P9ZW+D/UFHi/0FC4f9BQeH/Tk/h/1pb\n        3f9patv/e33W/5OVzf+hpL//oqWr/5KXlP93fHz/X2Vq/05UWv8+Q0X/KCwn/xQVEf8NDij/DxB8/w8P\n        0v8GBur/Dw/W/4WMuP+UnKL/SE1T/0VKUv9BRlP/P0RR/z5CUP89QlD/PkJN/0NJUf9ZYWn/P0RL/xsd\n        IP8yNTr/OT9H8TE3P242P0UENDxDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg9RwA4PkcENjxFZkFI\n        UOw6PkT/HiAj/zs/Rf+EjJH/i5S1/zg81f8FBuX/Bgfl/wcI5f8ICOX/CAjl/wgI5f8ICOX/CAnl/wkJ\n        5f8ICOf/Bwfo/w8Q0f8nKZr/HB5F/xobHP8qKyX/PUA+/05TVf9XXWL/Ymlt/292eP+Bh4f/kZWT/56i\n        n/+nqqj/qq6v/6uus/+rrrP/qq6v/6Sopv+coJ3/jJGR/3yBgv9obnL/XGJo/1BWW/9HTE7/Nzs5/yIk\n        Hv8SExT/Dg83/w4Ogv8KC83/CAnp/wcI5/8ICOX/BAXm/ykrw/+gqLb/bnR8/0FGS/9DSFL/QUVT/z5D\n        UP89QUz/RUpS/1tia/89QUf/HB4h/zM3Pf87QUnzMTc/dzA3PgcwNz4AAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAA4PUUAOD5FBDY8RGZCSFHrP0RK/yIkJ/85PkP/foaM/5iis/9RVc3/Cwzj/wUF\n        5f8ICOT/CAjl/wgJ5f8ICeX/CAnl/wgJ5f8JCeX/CQnl/wgJ5/8HCOn/Cgva/xITrv8WF2r/HB06/yss\n        Lv9BQjr/UFJM/11gXf9gY2P/X2Rn/11jZ/9cYmb/XWRp/2BmbP9fZWv/XmRp/1xiaP9ZX2P/WF1g/1db\n        XP9QU1H/QkM+/zM0LP8eHyH/FBUy/w8QZP8NDab/Cgra/wgJ6/8ICej/CAnl/wgI5f8ICOX/CAjl/wUF\n        4v9UWbT/m6On/05TWv9BRkz/QUVR/0FGT/9MUlr/WmFp/zg8QP8dHyL/NztB/z1DS/EyOEB2MTg/CDI4\n        QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANz1FADU6QAQ5P0hdRUtU40NI\n        T/8kJir/LjI2/3F4f/+dpq//cXfJ/x8h3/8EBOX/Bwfk/wgJ5P8ICeX/CAnl/wgJ5f8JCeX/CQnl/wkK\n        5f8JCuX/CQnm/wgI6f8ICef/CwvU/xARsP8bHIj/Kyxu/0FBYP9YWGb/bW1t/35+ef+GhoD/iYqD/4mK\n        g/+FhoD/gYJ7/3h4cf9ra2X/WVlY/0NDUf8xMU//ISFg/xYWgv8PD63/CwvT/wkK5/8JCer/CQnm/wgJ\n        5f8ICeX/CAnl/wgI5f8ICOX/CAjk/wYH5v8PENL/foSq/4aOlP9DR03/QUVM/1VbZP9bYmr/LzI2/x4h\n        I/85PUP/PURM6zQ6QmwzOkEHNDpCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAD1CTAA6P0gCPENLSkVMVdRJT1b/LTA0/yYoLP9dYmn/nKSq/5qiyP9GStj/Cgrj/wQF\n        5f8ICeT/CAnk/wgJ5P8ICeX/CAnl/wgJ5f8JCeX/CAnl/wkJ5f8JCuX/CQrm/wkJ6f8JCen/CQrj/wsL\n        1/8QEMf/GBi6/yMktP8tLaX/MzOj/zk5p/84Oaf/MjOi/ykqoP8gILD/Fha2/w8Pxf8LDNf/CQrj/wkK\n        6f8JCun/CQrm/wkK5f8JCeX/CQnl/wgJ5f8ICeX/CAnl/wgI5f8ICOT/CAjk/wcI5P8CAub/LzG//5qi\n        rv9obnf/X2dw/1RaYf8nKi3/Jyot/0JHT/8/RU7eNTtDWDY6QwQ2PEQAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFS1IAKjM8ADxDSzNESlO6TVNc/TY5\n        Pv8iJCf/Q0dN/4ePlf+nr7r/eH7N/ywt3/8GB+T/BQbk/wgJ5P8ICeT/CAnk/wgJ5P8ICeT/CQnl/wkJ\n        5f8JCuX/CQrl/woK5f8KC+X/Cgvl/woL5v8JCuf/CQno/wgI6P8HCOf/Bwfn/wcH5/8HB+f/Bwfn/wgI\n        6P8ICen/CQrp/wkK5/8KCub/Cgrl/woK5f8KCuX/CQrl/wkK5f8JCuX/CQnl/wgJ5P8ICeT/CAjk/wgI\n        5P8ICOT/BQbl/wYG5f8oKtz/cHbC/5aeqf91e4X/QkZM/yAjJf8vMjb/RkxT/j9FTsQ6QEk/Nz9FATpA\n        SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAPUZPAD1DSgA+RUwbQEdPkktRWvJGSlD/KCot/ywuMv9ma3L/n6is/6uzyv9qb9b/ISPg/wYG\n        4/8GBuT/CQnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQrk/woK5f8KCuX/Cgvk/woL5f8KC+T/Cgvl/woL\n        5f8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+X/Cgvk/woL5P8KC+T/Cgvl/woK5f8KCuT/CQrk/wkK\n        5P8JCuT/CQnk/wgJ5P8ICeT/CAjk/wUF5P8GBuT/ISPg/2hs1f+gqL//k5uf/2Bmbf8sLjL/IiQn/z5C\n        SP9GS1T2PUNLnzpASSIyNj8AQ0lRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Q0sAPEJJCTxCS15GTFTVT1Rb/zo9\n        Qv8jJSn/P0JI/32Ei/+vt7z/srra/3N44f8qLOP/Bwjj/wQE4/8ICOT/CQrk/wkJ5P8JCeT/CQnk/wkK\n        5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgrk/woK5P8KCuT/Cgrk/wkK5P8JCuT/CQnk/wcI5P8DBOT/Bwjj/ygq4f9obNf/o6rJ/6Or\n        sP9yeH7/PEBF/yEjJv8xNDj/Sk9W/0RKUt06P0hqNDpCDTU8QwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAOT1FADs8RAE3PEQqQUdPnFFXX/FOU1n/MjU5/yYpLP9PU1n/j5ad/8LK0P/Dy+b/jpPr/0lM\n        6P8WF+T/BAXj/wQF4/8HCOT/CQnk/wkK5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woK5P8KCuT/Cgrk/woK5P8KCuT/CQrk/wcI5P8EBeP/BAXj/xQV\n        4/9DRuT/g4fe/7O60/+ss7j/gYiO/0hLUf8lJyr/LC8y/0ZLUf9LUFj0P0VNpjU7QzI8Rk0BOUBJAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wA7Q0sAPUVNCD9GTlBJT1i9Vlxk+U5T\n        Wf8zNjr/KSwv/05RV/+Mkpr/vsbL/9Xc6v+9wvT/gYXu/0pM6f8eIOT/Cwzj/wUF4v8GBuP/Bwfj/wkJ\n        5P8JCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KCuT/Cgrk/woK5P8JCeT/CAfj/wYG\n        4/8FBeP/Cwzj/x0e5f9ERef/foHp/7K46f/J0d7/sbm9/3+GjP9JTVL/KCsu/ywuMv9FSU7/T1Rc+0VL\n        Usc5P0dbNjtCDDI3PgBCSFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAQEdTADM5NAA9Q0oVQUdQaFFXYMpaYGj6UVVc/zc6Pv8qLTD/PUBF/21yev+psLf/z9fe/97k\n        8v/M0Pj/o6X1/3V17v9PUOr/Kyvm/xoa5P8PD+P/CAni/wYH4v8GB+L/BQbj/wUG4/8FBuP/BQbi/wYG\n        4v8GB+L/Bwfi/wwM4/8YGeT/KCnl/0hJ6f9wcu3/n6Pz/8TJ9P/U2uv/xczT/6Cnrv9pb3b/PkFG/ygr\n        Lv8vMjb/SUxS/1NZYPxJT1fSPEJKcjc8QxszPzYANz1DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCR00ASEpOAD1CShtDSVFoUlhhw15j\n        a/ZaX2X/RUlO/zAyNv8vMTX/SEtR/3B2fP+mrbP/ydDU/+Hn7P/j6PT/3N75/8rM+v+xs/f/mJnz/46P\n        8v+EhPH/b3Dv/2lq7/9nae//aGnu/3l68P+NjvL/lZby/6qs9f/FyPj/2Nz4/9zi8v/a4Of/v8bN/5yi\n        qv9tcnn/SExS/y8yNv8uMDP/QUVK/1VaYf9ZX2f4TFNbyj1DS3M3PUUgOD1FATk/RgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAEVLUgBNUlcAPkNLFEVLU1JPVV6kXGJr4mNocPxYXWP/RUhN/zI1Of8wMzf/P0JG/1RY\n        Xv9vdXv/l5yi/7G2uv++w8f/1dvg/+Dk5v/h5en/3+Lp/9rd5P/a3eT/3+Lq/+Xp7v/h5uj/193h/7/F\n        yv+ssrf/lZuh/3B1fP9PVFn/PD9D/y0vMv8wMjX/QkZK/1VaYP9hZ2/9XGNs5k5UXatFS1NZQEZPGDhB\n        RAE+RUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJJUgBCSFEHREpTLExS\n        W21WXGWxXWNr4WRqcvpkaXD/XWJo/0tOU/9AQkb/NTg7/zc6Pf9CRUj/Sk1R/1FUWP9YXGD/XWFm/2Jl\n        av9iZWv/XmFn/1hcYP9NUFT/RUlN/z9CRv80Nzv/MjU4/zw/Q/9GSU7/Vlpg/15jav9kaXL7XmVu5Vdd\n        ZrZJUFlzQklRMT9GTglBSFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAQUhQAEhOWgA7QkoKRUtUKkpQWFxYX2iTXmRuwWlveOFvdX70bHJ6/W1z\n        ev9qbnT/Y2dt/1ZZXv9XWV7/Wl1i/1teY/9aXWL/WFth/1RYXf9TV1z/XmJo/2dsc/9udHv/bHJ6/Wxy\n        e/VmbHXjWWBpxFNZYphIT1dhQkhRLzk/SAwyMz4AOD1HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY8\n        QwAnLTQDQEdPEkZNVS9NVF1TVVxle1hfaJ1YX2e8Y2pz0Glwed9rcnzqbnV/83B3gfhwd4H4b3aA8210\n        fetqcXrgY2pz0Vpha71bYmugVl1nfk1UXVZFTFUyQkhRFSwzOQNjansAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAD/////8AAAD///////////AAAAAP/////////8AAAAAD/////////gAAAAAAf///////+AAAAAAAH/\n        //////8AAAAAAAB///////wAAAAAAAA///////AAAAAAAAAP/////+AAAAAAAAAH/////8AAAAAAAAAD\n        /////wAAAAAAAAAA/////gAAAAAAAAAAf////AAAAAAAAAAAP///+AAAAAAAAAAAH///8AAAAAAAAAAA\n        D///4AAAAAAAAAAAB///4AAAAAAAAAAAA///wAAAAAAAAAAAA///gAAAAAAAAAAAAf//AAAAAAAAAAAA\n        AP//AAAAAAAAAAAAAH/+AAAAAAAAAAAAAH/8AAAAAAAAAAAAAD/8AAAAAAAAAAAAAD/4AAAAAAAAAAAA\n        AB/4AAAAAAAAAAAAAA/wAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAfgAAAAAAAAAAAA\n        AAfAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAGAAAAAAAAAAAAA\n        AAGAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AACAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAPAAAAAAAAAAAAA\n        AAPAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAfwAAAAAAAAAAAAAA/wAAAAAAAAAAAA\n        AA/4AAAAAAAAAAAAAB/4AAAAAAAAAAAAAB/8AAAAAAAAAAAAAD/8AAAAAAAAAAAAAD/+AAAAAAAAAAAA\n        AH//AAAAAAAAAAAAAH//AAAAAAAAAAAAAP//gAAAAAAAAAAAAf//wAAAAAAAAAAAA///4AAAAAAAAAAA\n        B///4AAAAAAAAAAAB///8AAAAAAAAAAAD///+AAAAAAAAAAAH////AAAAAAAAAAAP////gAAAAAAAAAA\n        f////4AAAAAAAAAA/////8AAAAAAAAAD/////+AAAAAAAAAH//////AAAAAAAAAP//////wAAAAAAAA/\n        //////8AAAAAAAD////////AAAAAAAH////////wAAAAAAf////////8AAAAAD//////////gAAAAf//\n        ////////8AAAD/////8oAAAAgAAAAAABAAABACAAAAAAAAAAAQATCwAAEwsAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAPUpOAFBfYgApNDoIGiUrFiEpMDIcJCxVFx8ndxcgJpkZIym1GiIpyxYfJd4XICbwFx8m/BYe\n        Jf8WHiX/Fh4l/xYeJf8XHyf/FyAn/xcgJ/0XHybxFyAn4BojKs4aIyq4GSIpnRcgJ3sbJCpZISowNxoi\n        KBgmLjUKSFJUATlCRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACQrNgAkKTcAIy00CCQtNB8bJCxHGiMqdhokK6QXISjIFh8m5RUd\n        JfEVHSX6FR4l/xcfJv8YISj/GCEn/xghKP8YIin/GSIp/xwkK/8cJSz/HSYt/x0mLf8aIyr/GSIp/xki\n        Kf8ZIin/GSIp/xcgJ/8WHyb/Fh8m+xYfJvIWHyboFh8mzBokK6kaIip7GSIoTCApMCMiLDQJRk1TATA4\n        PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAISkzAC41QQEiKzMMGyMrMh0l\n        LGgYISikFyAn1BcgJ/EXICf9FyEo/xkiKf8bJCv/Hygv/yApMP8hKjD/ISov/yIqLv8iKi3/Iiot/yIq\n        Lf8eJSj/Iigr/x4kJv8dIyb/Iyks/yAnKv8iKS3/Iyou/yMrL/8jLDH/Iisw/yMsMv8iKzL/Iiw0/x0n\n        Lv8ZIyr/GCIq/xYfJv4WHibzFyAo2RkiKqocJSxwGyQrNyQtNA8gKjUBHygyAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAC2v7UAAAAEADQ+QwcdJi0qHCUsaBggJ64WHybhFR0k+hUeJf8YISj/Higw/yIrMv8jLTL/JC0x/yAn\n        Kf8aHyH/Fxwd/xQZGf8RExT/DQ8P/wsNDv8LDg3/Cw4N/wsNDf8LDQ3/Cw0N/wsNDf8LDQ3/DA0N/wwN\n        Dv8MDg7/DA0O/w4PEP8RExT/FRka/xcbHf8cICP/ISgr/ycvM/8mLjT/ICkv/x8pMf8bJSz/FyAo/xUe\n        JfsXHyblFh8mtRojKXEdJywxMTxBCQAAAAB3hoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QkkAZXJ6ACIrMhIcJixLGSIpmBYeJtoWHiX5FyAn/xsl\n        K/8fKC//Iywy/yQsMP8bICP/Fhoc/xASE/8NDg//CwwN/wwNDf8OEhL/ERUW/xQWGP8YHB3/GB4g/x4k\n        Jv8jKSv/Iyot/yYtMP8lLTD/JS0x/yYuMf8kKy7/Iyks/x8lKP8aHyL/GBwe/xUYGv8TFhf/EBIT/wwN\n        Dv8MDQ7/Dg8Q/xESE/8WGhv/HCEk/yIqLv8lLjT/ISox/xwmLf8WHyb/FR4k+xUeJOAYISehGyQrUyEq\n        MRZndXwBOkVMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuOEIATVZjASMt\n        NBsbJCtiGSIpuBYfJvAXHyb/GSIp/x4nLv8hKjD/HiUo/xwgIv8QExX/DQ8Q/wsMDf8OERH/ExYX/xcb\n        Hf8gJyr/JS0x/ygxNv8uOT7/MTxC/zdDSf82Q0j/OEVK/ztITP88SU3/O0hK/zpHSP85R0f/O0lK/z1K\n        TP89S0//OUdL/zhFSf86Rkv/NEBF/zA6QP8pMjb/Ji0x/yEnKv8YHR//EhUW/xASE/8MDQ3/DQ8P/xEU\n        FP8aHiD/HyYp/yIrMf8gKTH/GSMq/xYeJf8VHSTzFx8mwRghJ28gKS8iMjxDAiYwNgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAvOEEAVV5oAR8pMB4ZIiluFyAnyBYfJfgXICf/HCUs/yEqMP8gJyz/GR0f/xAS\n        Ev8MDAz/DA4O/xASE/8ZHh//ISgq/ykxNv8xO0D/Mz5E/zdER/89TEz/QlFO/0FQTv9AT1H/QFBS/0BP\n        Vf8+TFT/PEpQ/zhFUv80QmH/NEFu/zRAcv80QG7/NUJg/zpHUf8/TVT/QVBY/0JRVP9CUVP/QlFQ/0NS\n        T/8/TU7/OUZJ/zZBR/8zPkP/KjM3/yIpK/8aHyH/ERQU/w4PD/8NDQ7/EBIT/xkdH/8hKCv/Iisx/x0m\n        LP8XHyb/FR0k+hcfJtIYISd6HictJEBHTwIuNT0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKjIAPlNcACIrMxYaJCpoFyAnyRUd\n        I/kXICb/HSgw/yIsM/8dJCj/ExgZ/w0PEf8MDxD/ERQW/xsiJv8jLDH/LDc+/zNBSf88TFL/QVJU/0JU\n        Vv9CVFX/O0pa/zI/bP8pNHz/ICmJ/xkgpv8TF6z/DRHJ/wsO0v8KDc//CArQ/wYI2v8FB+L/BQbk/wUG\n        4v8GCNn/CQrP/wwP0f8NEc//EhWu/xgdqP8gKI7/KzV9/zI+bf87Sl//Q1RW/0JUVv9BU1X/PU5T/zRC\n        Sv8wO0P/JS0y/xsiJv8SFhn/DQ8Q/w0PEP8TFxn/HSUp/yMtNP8fKjP/GCIp/xQdI/sWHiXRGSIpcx4p\n        MR05TE8AIi41AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAIioxACcvNQkcJSxOGCAnuRYeJfYXICf/Higx/yIuOP8cJi7/Ehgd/w0SFf8PFRn/Fx8l/yIv\n        Of8sO0j/NEdT/zxSW/9BWV7/Q1xi/zxScv8xQ4b/Hyug/xQcuv8LEM7/BAbf/wID7v8CAvH/AQL0/wEB\n        9P8CAvP/AgPy/wID8v8CA/L/AgTx/wIE8f8CA/H/AgPx/wID8f8CA/H/AgPy/wID8/8BAvT/AQH0/wEC\n        8v8DA+7/BAbe/wsP0f8UG7z/Hyqc/y9Af/86T3D/Qlph/0JZX/87UFn/MUNO/yo5Rf8iLzn/GSIp/w8U\n        Gv8LEBT/ERcb/xskK/8iLjf/Hikx/xcgJ/8UHSP5FyAmxBwlLFwoMjkPAAAAAHSBiAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALTg/AGl2fQEeJy4sGSIplhYeJesWHiT/HCYu/yIu\n        OP8aJCv/EBcb/wwRFf8QFhv/GiQq/yc0P/8wQk3/OU5a/0NcYv9EXWr/OU11/yY0k/8XILT/CgzS/wQF\n        6/8BAvH/AQLy/wID8v8CA/D/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DA/D/AgPy/wIC8v8BAvD/AwXr/wgM\n        0f8VHLP/JTOR/zhNcf9BWGT/Qlpe/zlPWf8zRVL/KDVB/x0nL/8RFxv/DBAU/xAWGv8ZIyr/Iy85/x4p\n        Mf8XHyb/Fx8m8hghKKMcJSw2N0JKAyUvNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtsbSAAoR\n        GAAkKzQNHCQsYxcgJ9MWHyb+GiQs/yIuN/8dJy//Ehgd/wwQE/8QFhr/HCYu/yk4Q/8zRVL/PFJb/0Nc\n        Y/89VG//KTmK/xYeuP8GCOD/AgLv/wEB8/8CA/H/AwTv/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AQPx/wEB8/8CAu//Bgjc/xQcuP8pOIv/PlRv/0Ze\n        Zv9AVl//M0VS/yk3Qv8eKTD/Ehke/wwSFf8SGB3/Hykx/yMvOP8dJy//Fx8m/xYfJtwaIilyHycuFAAA\n        AABATVIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0pMQAgS2AAHicuKRkhKJ0WHiX0GCAo/yAsNf8gLDX/FRwi/w0R\n        FP8PFBj/HScv/yg2Qf8yRFD/PlVd/0JZZP81R3j/HSii/woO1f8CAuz/AQHz/wID8P8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8CA/D/AQH0/wIC7P8KDdT/Himg/zdLeP9DW2b/P1Ve/zRGUv8qOEP/Hikx/xEX\n        HP8NEhX/Fh0i/yEtNv8iLjj/GSIp/xUdI/cXICatHicuNTY/UAIlLjkAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkLTUALDU8BR0m\n        LlAYICjMFh4l/RslLf8hLTb/GSMq/w4TF/8OEhf/GSEo/yYzPf8zRVL/QFdf/0JaZP8xQ3r/GCKv/wYI\n        4P8BAfP/AgLy/wME7/8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTu/wIC\n        8v8BAfP/Bgjd/xggrf8xQ3n/Qllj/z9VXv8zRFH/KDdC/xokK/8OFBj/DhMX/xkhKf8jLzn/HSgw/xYe\n        Jf8WHiXYHCQtYCw1PAglLjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAHycvACEpMQ8aIyp2FR4l5hcfJv8eKTL/Hioy/xIZHv8LDxP/Exof/yIu\n        OP8vQU3/O1BY/0JYX/81SHr/GCGy/wUH4v8BAvP/AgPx/wME7f8DBO3/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8CA/H/AQLz/wUH4P8YIK7/NEZ6/0Na\n        Yv89U13/MUJP/yUyPf8VHSP/DBEU/xIZHv8fKzP/IS02/xgiKP8VHSTvGSIqhyMuNRgeKC0AJC86AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALjtAAA4THAAhKzEdGSEomBUd\n        I/YYISf/ISw1/xojKv8OExf/DhMX/xkiKf8pOET/NkpU/0FYXP83S23/HCaj/wYJ4P8BAvP/AgPw/wME\n        7f8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7/8DBO//AwTv/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7f8DBO3/AgPw/wEC8v8GCOD/HCak/zpOa/9CWmD/N0pX/y08SP8eKTH/DxQZ/w0S\n        Fv8aIyr/IzA5/xskLP8VHST5GCAnqx8oMCkAAAgAKDQ9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAC43QAAAAAAAHigwKxcfJrIVHSP8GiMq/yEtNv8WHSP/DBEU/xIYHf8iLzj/MEFO/z1T\n        W/8/VWX/JTKQ/wkN1v8AAfL/AQPw/wME7f8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTv/wID7/8CA/L/AQLz/wEC9P8BAfX/AAD1/wAA\n        9P8AAPH/AADt/wAB6/8AAO3/AADx/wAA9f8AAPb/AQH0/wEC8/8CA/H/AgPv/wME7/8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7f8DBO3/AwTt/wID\n        8P8BAfL/Cg7S/yY0jP9CWWj/N0tZ/yMwOv8kMDn/FRsi/wwQFP8VHSL/IzA5/x0oL/8WHST/Fh8mxB4m\n        LTiJm54AKjM6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmMTkAY3x+AB8oMDoXICfEFB0k/hwm\n        L/8fKjL/ERgc/wwQE/8XHiT/KTdC/zdJVf9DWmH/Nkh1/xMauP8CAu7/AQHy/wID7v8DBO3/AwTt/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8CA/D/AgLz/wEB\n        8v8CA+7/BQbr/wcK1f8NEc3/FBrD/x0msv8hLLr/Iy+3/yQxqv8nNJf/KTeQ/yYzmf8jL6z/ISy4/x4n\n        tP8WHb7/DhPN/wcK1v8FBuv/AgPv/wEB8f8CAvP/AgPw/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7f8DBO3/AwTt/wME7v8BAvX/Hymn/0NaZP8pOEP/FyAm/x4p\n        Mf8oNUD/GyUs/w0RFf8QFxv/Hysz/x8qMv8WHiX/Fx4m0SApMElLVl4CLzlAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAJS83AExWYwEfKC9CGCEn0BYeJf8eKjL/HCYu/w8UGP8NERX/GiMq/ys6Rv88UVr/Qlln/yY0\n        kP8IC9n/AAHz/wID7/8DBO3/AwTt/wME7f8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wID8f8BAfL/AgPu/wcJ3P8SGMb/HSex/yo5l/86ToP/RFt//0lhfv9LZHf/Tmhs/09p\n        bf9OaW3/Tmlv/01nbv9MZ27/Tmlw/05obf9NaGz/UGtu/05od/9KY37/RFp+/ztPhP8rOZj/HSiu/xEY\n        x/8HCdz/AgPu/wEB8v8CA/H/AwTv/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7f8DBO3/AQHz/w8Vzv8/VXD/OEtV/xoiKv8aJCv/GiMq/xwnLv8nNED/ISw2/w8TGP8OExb/GyQs/x8r\n        M/8WHyb/GCEo2yAqMlM1REwDKDQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIsNABJV2MBHCUtRBggJ9QXHyX/ICsz/x0n\n        L/8NEhb/DhQY/x8qM/8uP0v/PlRZ/ztQav8aI6//AgTs/wEC8v8CA+3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AgPw/wEB8/8CA+//Cw7U/xkitf8rOZP/PlOB/0hh\n        cf9MZ23/SGFp/0RbZP88UVv/NUdR/zJDT/8uPUv/LDtI/yw6SP8rOUf/KjhF/yk4RP8rOkf/LDtJ/y08\n        Sf8uPUv/MUJP/zZIUv89U1z/RFxj/0hhaf9MZm3/SGFy/z5TgP8tO5D/GSG2/wsO1/8CA+3/AQHz/wID\n        8f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wID8P8FBun/MEGF/0JYXP8fKjL/GiMq/xoj\n        LP8aIzD/GyQs/xskK/8kMDr/JDE7/xEXG/8MERT/GSMq/yEtNf8YICf/GCEo3x0nL1YyPkMDJC82AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAoMDoA9fP/AB0mLkEXHybTFh8l/yAsNf8bJSv/DREV/w8VGv8iLjf/M0VR/0FYXv81R3P/DxXE/wEC\n        8f8CA+7/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AwTt/wME7f8DBO7/AgLx/wEB\n        8f8GCOP/FRu5/yw8lv9CWXj/TGZv/0lia/9BV2D/NUZT/y07SP8mMz//JTFA/yUxP/8kLzz/JTA8/yUx\n        Pf8lMT3/JDA8/yUyP/8lMT7/IzA8/yUxPv8kMD3/KDM+/yQwO/8lMj7/JTE9/yUxPv8lMT3/JzM//y08\n        SP80RlL/QFVe/0pja/9PaXb/Rl6A/y8/mP8VG7j/BQfh/wEB8/8CAvH/AwTu/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AQHz/x8pq/9FXWX/KjlB/xggJ/8dJi3/GiIy/xkiN/8aIzT/GyQt/xkiKP8gLDX/JTM8/xIZ\n        Hv8LDxP/GSEo/yArNP8XICb/FyAm3x8pMFNOWmMCLTc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDxDAAAAAAAhKjI4GCAnzhYeJP8gKzT/GiMq/wwQ\n        FP8SGR3/JTI8/zRGUf9BV17/LDuE/wkN1/8BAfL/AgPt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO7/AgLx/wEB8f8ICtn/ICuo/z9Uhf9NZ3X/S2Vs/z9UYP8vP0v/JzNA/yUw\n        P/8jLjz/Ii05/yg1Qv8uPkn/MUNO/zhMWf89U1z/Q1tj/0dgaP9IYmj/SmVq/0tlav9JZGj/R2Fl/0Zf\n        ZP9GXmb/P1Ze/ztQWv81SFP/LDxH/yg2QP8nM0D/Ii05/yQvO/8mMUD/KDRC/zJDUP9AVmL/T2lx/05o\n        dv87T4H/Hyqu/wgK2v8BAfD/AgLy/wME7f8DBO3/AwTt/wEC8/8PFNL/QFVx/zlMVP8ZISj/GiMq/xsj\n        L/8ZIjf/GSI4/xkhN/8ZITT/GiQu/xojKf8fKTL/KDQ//xQbIP8MEBP/GCAm/yEsNP8XHyX/GCAm2yAp\n        MUl8k5UAKzY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADE6\n        QAATHSUAHigvKhggJ8IWHiT/Hyoz/xskK/8MEBP/Ehgd/yg2Qf84S1b/QVdg/yYykf8FBuH/AQHy/wID\n        7f8DBO3/AwTt/wIE7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AgPw/wEC8P8KDdX/Ii2h/z5U\n        e/9OaXD/Rl5m/zdJVf8qN0j/JDBB/yIuPf8nM0D/KzlF/zZJVP8/Vlz/RV5l/0lkb/9IYnH/Qllt/zxR\n        hP80R4L/Lj+N/y4+nP8sO5//Kjmc/yo5mv8pOJz/LDyY/zBChP82SoT/O1B5/0RdbP9KZXP/SGNt/0Rd\n        ZP88UVv/MUNP/yYzPv8hLDn/Ii07/yUxQP8tPE3/OExZ/0dfaP9MZ2//P1R5/yEsnv8JDNP/AQLx/wID\n        8P8CA+//BQfp/zNEj/9FXGL/ICoz/xkhJ/8aIyz/GSI2/xskOv8aIzj/GSI3/xkiOP8ZITb/GSIu/xkh\n        KP8eKDD/JzU//xYdJP8MEBT/GSIo/yMuNv8WHiX/FiAl0h0mLjgLFRgAKjM9AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHigwACErMxwYISiwFR0j/x8pMv8bJS3/DRIV/xIZ\n        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\n        7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8FBu7/BQbu/wUG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG\n        7v8EBu7/BAXu/wQF7v8EBe7/BAXu/wME7/8CA/P/AQLv/wcJ3P8bJav/O1CA/05qdf9EXWb/KDdA/xsk\n        MP8hLTr/LDpL/z5SYv8vPkr/GiMq/x0nLv8bJDT/HCU7/xwlO/8cJTr/GyQ5/xojOP8aIzj/GiM4/xki\n        N/8ZITb/GSE3/xkiOP8aIjf/HCQw/xsjKv8hLDX/JTI8/w4UGP8OFBj/ICsz/xwkK/8VHCPuGyQrYD1G\n        WAEiKzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+uvQAaIysAISozJRgfJscXHiX/ISw1/xQbIf8MEBT/HCUs/zND\n        T/9AVVz/KDaK/wQF5f8CA/D/AwTs/wME7P8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AgPx/wME\n        6P8fKaD/RVxt/0dfZv8yQlH/JS9G/x8qOP8wQU3/Rl5m/0Zeb/8pOJH/DRHK/wIC7v8BAvT/AwTv/wMF\n        7f8DBe7/BAXu/wQF7v8EBe7/BAXu/wQG7v8EBu7/BAbu/wQG7v8FBu7/BQbu/wUH7v8FB+7/BQfu/wUH\n        7v8FB+7/BQfu/wUH7v8FB+7/BQbu/wUG7v8FBu7/BAbu/wQG7v8EBu7/BAbu/wQF7v8EBe7/BAXu/wQF\n        7v8EBe7/AwTx/wEB8/8FB+D/GiOr/ztPfP9LZm//O1Fa/yEtNv8aIi3/JjFA/yApNP8cJiz/HScv/xsk\n        M/8bJDj/GyQ5/xskOf8cJTr/HCU6/xskOf8bIzn/GiM4/xoiN/8aIjf/GSE3/xoiOP8bJDj/HCUv/xki\n        KP8jLzj/IS01/w0RFP8SGB3/ISw0/xYeJP8WHiXYHykxNhQcJAA3REsAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICozACUv\n        OQwbJCyXFh4l/SAqM/8YICb/CxAT/xggJv8uPkr/P1Va/zFBgf8HCd//AgLx/wME7P8DBOz/AwTs/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTs/wIC8v8GCN3/KTeM/0tjbf9CWGP/KzhK/yApP/8mMj//PlNc/0lj\n        bv8zRYX/Ehi9/wID7P8CAvP/AwXu/wMF7f8DBe7/AwXu/wQF7v8EBe7/BAXu/wQF7v8EBu7/BAbu/wQG\n        7v8FBu7/BQbu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQju/wUI7v8FCO7/BQju/wUH7v8FB+7/BQfu/wUH\n        7v8FB+7/BQbu/wQG7v8EBu7/BAbu/wQG7v8EBe7/BAXu/wQF7v8EBe7/BAXt/wME8f8BAvP/BgnZ/x8r\n        n/9BWH3/SmV1/yo5Q/8SGB7/JC49/yUwPf8cJi3/HSYt/xwlMf8bJDn/GyQ6/xwlOv8cJTr/HSY7/x0m\n        O/8cJTr/HCQ5/xwkOf8aIzn/GiI3/xohOP8aIzb/HCUu/xojKf8mMjz/Hicu/wwQE/8WHSP/Hyoy/xUc\n        Iv8YICesIi00FR4oMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACYxOgAAAAAAHigwXBgfJvEdJi7/Hikx/w0RFf8UGyD/LDtH/z1S\n        Wv85THH/DRLQ/wEC8v8DBOz/AwTs/wME7P8DBOz/AwTt/wME7f8DBO3/AwTt/wME7P8BAvL/CQzQ/zBA\n        gf9MZGv/O05b/ygzQf8eJzT/LT5J/0hhZ/9AVnL/HCWq/wQF5P8BAvP/AwTv/wMF7f8DBe3/AwXu/wMF\n        7v8EBe7/BAXu/wQF7v8EBe7/BAbu/wQG7v8EBu7/BQbu/wUH7v8FB+7/BAbv/wQG8P8FBvH/BQbx/wUG\n        8f8EB/H/BAbx/wUH8f8FB/H/BQfx/wUH8P8FB+//BQfu/wUH7v8FB+7/BQbu/wUG7v8EBu7/BAbu/wQG\n        7v8EBe7/BAXu/wQF7v8EBe7/BAXt/wMF7f8CBPL/AgPv/yw7mv9MZ3T/OUpZ/yApMv8QFhr/HSUv/ycy\n        Pf8dJi3/HCUs/xwlMf8bJDf/HCU7/x0mO/8cJTr/HCY6/x0mO/8dJzz/HSY7/xskOf8bIzj/GiI3/xkh\n        OP8bIzT/HCUt/xwlLf8qNkH/GB8m/wwQFP8bJCv/HCUt/xUcIfgbIypyN0JOAiMsNAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHigxACEr\n        NScYIinNGSEo/yArNP8RFxv/DxQY/yczPv87Tlj/P1Rm/xUcu/8BAfH/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTt/wME7P8DBOz/AQLz/wsPyv82SHX/SmJp/zdIVv8iLDn/GiUu/zRHUv9IYmn/Lz+F/wwR\n        yv8BAvH/AwTw/wMF7f8DBe3/AwXt/wMF7v8DBe7/BAXu/wQF7v8EBe7/BAXu/wQG7v8EBu7/BAbv/wQF\n        8P8DBPP/AgP1/wID8v8GCOz/CAvp/wwQ4v8OEuX/DhPk/w8T2/8PFNz/DhPk/w0R4/8LD+P/Bwnq/wQG\n        7f8CA/X/AwT0/wQF8f8EBu//BQfu/wUH7v8EBu7/BAbu/wQG7v8EBe7/BAXu/wQF7v8EBe3/AwXt/wEC\n        8/8VHcj/SGJ8/zpOWf8dJS3/LDdD/ygzP/8TGh7/Fh0j/ycyPv8kLjf/Higv/x8oM/8dJjn/HSY7/x0m\n        O/8dJzv/HSY7/x0mOv8dJzv/HSc8/x0mO/8bJDn/GiM4/xsjOf8cJTT/GyQr/x8oMf8rOEP/Ehcb/w4T\n        F/8fKjL/GSEo/xceJdwdJy82ExwmAEVOTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACUvNwAuOEAHHCYujRcgJv0hLTX/Fx8k/wwQE/8dKDD/NkhU/0NZ\n        Yv8gK6T/AgPv/wME7f8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wEB9P8MD8n/OUt0/0pi\n        av82RVL/Mz1F/z1JUf9uhYz/b4mW/ys4o/8EBuL/AwTz/wQF7v8DBe3/AwXt/wMF7f8DBO7/AwXu/wQF\n        7v8EBe7/BAXu/wQF7f8EBu7/AwXw/wID8/8DA/D/Bwnm/xAVyv8cJbL/KTSd/zREjP88T4T/Rltw/0pg\n        df9KYHX/SmFz/0phdf9KYHX/SF1w/0NXcv84Sor/MT+R/yYwpv8ZH73/Cw7a/wUG7f8CBPL/AwXy/wUG\n        7v8EBu7/BAbu/wQF7v8EBe7/BAXu/wQF7f8CBPD/CQvj/z1Nhv9HXGH/Iiw1/x0lLP8dJi7/JC05/y04\n        Rf8ZHyL/FRod/yYvNv8iLDP/ICsy/x8qNf8eJzv/Hic8/x0nO/8dJjr/HCY6/xwlOv8dJTr/HSc7/x0m\n        O/8bJTn/GyM4/xojOP8aIy//GiMp/yYyPP8lMTr/DREU/xUcIf8hLDT/GCAn/xojK6MmMDkPIiszAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtOT0AGSEqACAq\n        MkUYICjnHSYv/x4oMP8NERX/FRwh/y49Sf8/VVv/MECH/wUH5v8CA+7/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7P8BAvP/Cw7L/zhJdP9KY2r/MkFM/yAmK/8oLzT/douO/5KrxP87Rc//Bgfv/wUG\n        8P8FB+3/BATt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wMF7f8EBe7/AwPx/wID8P8ICuL/Fx67/yk1\n        lf87THT/RVdl/0hcXf9IXFn/RFZX/0BSVf9CUlz/Q1Jf/z9OWv8/T17/P1Be/z9PW/9BUV//Q1Rg/0RV\n        WP9IW1r/TmFe/0pdZP9EVmz/NkSE/yIrrf8QFNH/BQbr/wMD8v8DBfD/BAXt/wQF7f8EBe3/BAXu/wID\n        8f8oMqH/TmBe/yw3Pv8cJCr/Hygw/x4mNf8cIzb/Iio3/y44Qf8gJir/EBIS/yYtMv8nMTn/ICsz/yAq\n        NP8fKDv/Hig9/x4nPP8dJjv/HSY6/x0mO/8dJzv/HSc7/x0mOv8bJDn/GiI3/xoiNv8aIyz/GiMq/yk3\n        Qf8aIin/DBAT/xskK/8eKDH/Fx8m8h4oMVsAAAAAKTM8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACIsNAAlMDkQHCQsrxggJ/8iLTf/Ehcc/w8UGP8pNkH/O09Z/ztP\n        bP8PE87/AQLx/wME6/8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AgLy/wgK1f8zRHj/SmJp/zND\n        Tv8fJSn/ICcq/z5OTP8+TWr/HSLJ/wMD8P8GB+7/BQbt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBe7/AgPy/wME8P8OEc//JC6X/ztMdP9HW17/R1tY/0NTWf89TF3/NEJV/zJAV/8zQVf/Lz1Q/y07\n        TP8oNUL/KDRA/yczQP8nNED/JzRA/yk3Q/8uPE3/M0FU/zZEW/82RFr/OUhX/0VXZP9LXWL/TGBc/0ZZ\n        bP80QoT/GyK1/wgK5P8CBPP/AwTw/wQF7f8CAvP/FRrH/0pca/87Sk3/HCUs/x8oLv8dJzL/HSU6/x0m\n        O/8cJTj/Hyk2/yw2QP8gJiv/ERMT/yEnKv8kLTX/ICoy/yApM/8fKDv/Hyg9/x4nO/8dJjv/HSY7/x0m\n        O/8dJjv/HCU6/x0mO/8cJTr/GyI4/xoiM/8aIyr/Hicv/ys5Q/8SGBz/EBUY/yArNP8ZISj/GiMrxCMu\n        Nx0hKzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtOD0AAAALAB4o\n        MVsYICfzHigx/xojKf8MEBP/HCUt/zdKVv9EWWL/Hiip/wEC8f8DBOv/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wID8P8EBt//LTyE/0tja/82RlP/HCMn/x0kJ/8/UE7/NUNm/w0Qw/8BAfH/BAXu/wUG\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AgPx/wID8f8PE87/KzaU/0BSZv9HW1j/QVNZ/zlH\n        XP80QmH/MD1Z/yk1Sv8qN0b/JTA4/yMuM/8oMzf/KjU4/yYyOf8nNT//KDZB/yc2Qf8nNkD/JjM7/yo1\n        Of8pNDn/JTA1/yQvNv8qOEb/LTpN/zRDW/8+TWf/Rldo/0pdYP9MYGD/PEx7/x0ls/8GCOT/AQH2/wgK\n        5/88SoL/SFtY/yIsM/8eJy3/Hicv/x0mOP8dJjv/HSY6/x0mO/8cJTn/HSYx/ys1QP8iKS//DhEQ/yEo\n        K/8mMDf/Hykx/x8oNf8eKDz/Hic8/x0mO/8dJTr/HCU6/x0mOv8dJjr/HSY7/x0mO/8cJTr/GyQ5/xsk\n        MP8bIyn/JjI7/ykzPP8NERT/Fx8l/yAqMv8YICX6HScwdGJwfQEpMzwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACEqMgAlLjYYGiMqvhkhKP8hKzT/DxUY/xIYHP8tO0b/QFRa/zJC\n        gf8FB+b/AgPu/wME6/8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DA+7/AgPq/yMukv9MZGn/OkxZ/x0l\n        Kv8dJCj/Pk5M/zZEZf8LD8j/AQHz/wMD7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwPv/wEC\n        8/8JC9r/Iy6U/0BTZP9FWVf/OkpT/zI/Xf8tOlz/KDVO/yMuOv8jLTL/JjI2/yY1P/8qPk//KkVj/ydK\n        c/8rVon/KluX/yxfnf8rX53/Kl+j/ypeoP8qXJr/LFeM/ylOe/8qSGn/KT9V/yY1P/8mMTb/JjE2/yUx\n        PP8sOVD/MkBY/z1NYv9KW2H/TF9g/zlIfP8WG77/KDCj/05hY/8sOD7/GyMq/x8oLv8eJjT/Hyc8/x4n\n        O/8eJzv/Hic7/x4nO/8dJjr/HSYy/ys2QP8hKC3/EhQU/yIqLv8iLDT/Hykw/x8oNf8eJzz/Hic8/x0m\n        O/8cJTr/HCU5/xwlOf8cJTr/HCU6/x0mOv8dJTr/GyM3/xwlLf8bJSz/KTZA/xcdIv8OEhb/Hygw/xoi\n        Kf8aIirRIiw2JSApMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApMjwAAAAAAB0m\n        LmMWHiT2Hykx/xcfJf8NEBT/Higw/zhJU/8/U2X/EhjD/wEB8f8DBOv/AwTr/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wEB7/8YH6f/SF5q/0NWY/8iKzD/GR8i/ztKSv84R2P/DhLD/wAB8v8CA+3/AgPt/wMD\n        7f8DA+3/AwPt/wME7f8DBO3/AwTt/wID8f8CA+7/Fh2w/zlKbf9IW1j/Pk5Z/y88Wf8pNFX/JC9F/yEr\n        Mv8mMDP/JzU//ydBX/8uVor/KmKo/yxswf8wdMb/MHXL/y93zP8uc8f/LnPK/y5zwv8uc8b/LXPI/y92\n        y/81fdf/OYDb/zuA1f8wdMX/LGSr/y1ajv8pRWX/KTlG/yYwNf8kLzb/JTFB/zE+WP8/TmT/TF9k/0pc\n        ZP9MX2j/PEtR/x0kK/8fJy7/Hycx/x4mOv8eJzv/Hyg8/x4nO/8eJzv/Hic7/x4nO/8dJjr/Hicz/yw2\n        QP8gJSr/EBIS/yMqLv8iLDT/Hygw/x4oN/8fKDz/Hic8/x0mO/8dJTr/HCU6/x0lOv8cJTn/HCU6/x0m\n        Ov8dJTr/HSY1/xskKv8hLDT/KjU9/w4SFf8TGR7/Hygx/xgfJvweJi96Q1BgASUvOQAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACEqMwAkLjcWGSEovxcfJf8dJy//DRIW/xMZHv8vPUn/QVVY/yo3\n        jv8DBOz/AwPt/wME6/8DBOv/AwTs/wME7P8DBOz/AwTs/wME6/8BAvL/DRDE/0FUbf9HXGf/JzM6/xYa\n        HP81Q0T/O0pf/xAUvv8AAfP/AgPt/wID7f8CA+3/AgPt/wMD7f8DA+3/AwTt/wME7f8CAvP/Bwnc/yYy\n        jP9EV17/QlNV/zI/XP8pNVz/Ii5E/yEqMP8lLzT/KD1T/ylPgv8sZq//NHjO/zV81/8vdsv/L3fI/zR6\n        yv81fM3/Nn7R/zJ1xP8xc8X/L3LD/y9xwf8wcsP/N3vL/z2D2f8+hOD/PYTe/zJ6zf8zec//MnzQ/y5x\n        wf8rZav/KVOF/yk/Vf8oNDr/ISsx/yQwP/80Qlz/RlZs/0ZYYP8kLTP/Hycv/yApMf8eJzj/Hic7/yAp\n        Pf8hKz//ICk9/x4nO/8dJjr/HSY6/x0lOv8dJDj/HiYx/y03QP8dIib/ExUV/yUtM/8hKzL/Higx/x0l\n        OP8dJjv/HSY7/x4nO/8eJzv/HSY6/x0lOv8dJjr/HCU6/xwlOf8cJTn/HCUw/xojKf8nMz7/GB8l/wwQ\n        E/8eKC//GyMq/xkhKdEiLDYjHykyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArNjsAFh0nAB4n\n        L1gXHiX1HSYu/xUdIv8MDxL/ICs0/zpMVv89UGr/DhPP/wEC8P8DBOv/AwTr/wME6/8DBOz/AwTs/wME\n        7P8DBOv/AgPv/wQF4P8wP4D/T2Zu/zA9Sf8VGRz/Ljk+/0BRVv8YH6r/AAHz/wID7f8CA+z/AgPt/wID\n        7f8CA+3/AwPt/wMD7f8DA+3/AQLy/w0Rxv8zQnP/RlpW/ztLW/8uOWT/JTBW/x0nL/8jLTD/KD9V/ypY\n        jv8wccX/MXbP/zJ5y/8zd8v/NnzQ/zB0xP8yecn/O4LV/zl/1v85ftP/N3zP/zR5zP8zdsb/NXrL/z6D\n        1v9BiuD/P4bZ/z2D2/89hNv/N33P/zJ3yP8xd8b/L3O//zB2xv8udcf/LG22/ytakP8pQ17/JDA1/x4n\n        Lf8qNUv/MDxW/yEpM/8iKjD/ISo1/yApPP8fJzz/ISk9/yEqPv8iKz//ISs+/yApPf8eJjv/HSY6/x0l\n        Ov8dJTf/ICgy/y02Pv8XGhz/Fhob/ycwNv8gKTD/HSUx/x0mOv8dJTr/Hic7/x4oPP8eJzv/HSU6/xwl\n        Ov8bJDj/GyQ4/xskOf8bJDT/HCQr/yAqMv8lMTr/DBEU/xQaH/8fKC//GB8l+x0mL28AAAAAJC82AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACErMwAlMTkMGiMqrhkfJv8hKzT/DhMX/xIYHP8uPEj/QFNY/yQu\n        m/8CA+//AwTs/wME6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME7P8BAu//HSWg/0xka/8/UV7/GR4i/yMr\n        L/9CUlD/IiuQ/wID7v8CAu7/AgPs/wID7f8CA+3/AgPt/wMD7f8DA+3/AwPu/wIC8v8SF7v/OUpm/0NX\n        Vv8zQVT/KTRZ/x4oP/8fKi7/JjpM/ytWiv8vccD/NHrS/zZ60/80dsz/MXbI/zF0v/83fND/OX/T/zt/\n        1P9Bhdb/PILY/z6H3P82etD/MnbF/zV4xP85fdD/QIXa/z+G3v8/hdn/PoLW/z+E2/88gtj/NHvL/zF4\n        xf8zecf/MXbE/y5xu/8xdcT/MHfI/y9zwP8rW5P/KT9U/yArL/8eKDT/KjRM/ygxP/8iKzH/ISo2/yAo\n        O/8fJzz/ICg8/yEqPv8iLD//IyxA/yEqPv8fKDz/Hyc8/x4nO/8dJTb/Iyw0/yw0O/8SFBX/HSEl/yYv\n        N/8fKDD/HSY1/x0mO/8eJjr/Hic8/x8oPP8dJjv/HCU6/xsjOP8bIzf/GiI3/xojN/8cJC//GyMq/yk2\n        Qf8XHiT/DA8T/x4nLv8ZISf/GiEpwSQuOBchKjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCUtAB0n\n        MD4XHyXqHSYu/xkgJ/8MDxL/Hygw/zdJU/87TWf/DhLR/wIC7/8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AgPx/wwPxP9CVW7/SV5r/yIrM/8WGx3/PUxJ/y46df8FBuP/AQLw/wID7P8CA+z/AgPt/wID\n        7f8CA+3/AwPt/wMD7v8BAfD/Fhys/z5QYP9CVFf/MT5U/yYxT/8dKDT/LTtH/yk7TP8qYaD/M37V/zJ7\n        zf83es7/OHzQ/zV3zf8xdMX/NHfF/zd60P88gtb/P4TW/0GF0f8/h9z/O4TZ/zN2yf8xdMT/NXjI/zyB\n        0/88gtX/N3zO/zl/0v87gNT/PYLY/zd8z/80ecn/NHrF/zd9yv82e8r/MXK+/zF0wP8xdcL/MnfF/zN8\n        0f8waqz/K0BU/zA+Sf8hKzf/JzFD/ys2RP8iKzH/ISo1/yApPP8hKj7/ISk9/yEqPv8hKj7/ISo+/yEq\n        Pv8gKT3/ICg8/x8mO/8dJjP/JzA4/ykwNf8QEhL/Iikt/yIsNP8eJzD/HSY4/x4nO/8eJzv/Hic7/x4n\n        O/8dJjr/HCU5/xwlOf8bIzj/GiI4/xoiM/8bIyr/ISsz/yUvOP8OERX/Fx0j/x8pMf8YHybzHicwUxEZ\n        IwA1PkQAAAAAAAAAAAAAAAAAAAAAACQuNQA4RUsDGyQsihYeJP8eKDD/DxMX/xIXHP8uPEf/QFNZ/yk1\n        kf8DA+7/AwPr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME7f8DA+f/KjeG/09nb/8zQU3/EhYY/zE+\n        Pv87Slr/DhLH/wEB8/8CA+z/AgPs/wID7P8CA+3/AgPt/wID7P8CA+3/AQHy/xUbrv8/UFn/QFFT/zE8\n        U/8lMEj/Hik2/z9LWf9PW2r/P05g/y1EX/8uZab/MXbL/zd5y/83esn/M3bG/zJ2yf83e83/OHnL/zl8\n        0P89gtj/PoHS/zuA0/83fdD/MXXE/zF0wv8xdMH/M3fJ/zF0w/8vcr//MHO//zJ1w/8ydsb/L3PB/zBz\n        wv8zd8P/NHjH/zV5xv8xc77/MHTB/y9zv/8yecj/M2+z/zBNZ/9BUF7/Tlhk/0VRYP8kLzr/JjBA/yw2\n        RP8lLjT/ISo1/yEqPf8hKT3/ISo+/yEpPf8gKT3/ISk9/yEpPv8hKT3/Hyc7/x4mOv8eJjH/Ljg//x8l\n        J/8SFBb/JS40/x8oL/8fKDT/Hic7/x4mO/8eJjr/HSY6/x0lOv8eJjr/HiU6/xsjN/8bIzf/GyI3/xsj\n        Lv8aIif/KjdA/xceI/8OExb/ISsz/xkhKP8bJCuhLDY9CSUuNQAAAAAAAAAAAAAAAAAAAAAAHygxACMr\n        NB8YICfPGiIp/xsjKv8LDxH/HCQr/zhKVP8+Umf/ERXK/wEC7/8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AgLw/xIXtP9GW2r/RFhl/xkfI/8gJyr/QFBR/x0knf8BAvH/AgPt/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wEB8v8RFbz/PU5g/0FRVf8tN0X/ISo6/yItO/9FUWD/T1Zh/01TXP9PWGP/QUxa/ys7\n        TP8tYJn/N3zT/zh8z/83esr/NHvM/zl/zf89gdT/PIDV/zuB1P86gNP/N3vN/zV5yv8ydcL/M3W//zJz\n        v/8xc7//MXO+/zBzv/8xcrz/L3K5/zBzvf8xc8D/MXO9/zB0wP8vcr//L3K9/y9xvP8vcbz/MHTB/y9n\n        pf8zSl3/Q09Y/05VX/9NU1z/T1Zg/0pVZP8mMTv/Iiw4/yw1Qv8hKjD/ICk0/yAoPP8gKT3/ICk8/yEp\n        PP8hKj3/Iis//yEqPv8fKDz/Hyc7/x4nOP8hKjL/NT1E/xocHv8aHyH/JC0z/x4nL/8eJjj/Hyc8/x4m\n        Ov8dJTn/HSU5/xwkOP8dJDn/GyM4/xsjN/8bIzj/HCQ0/xoiKf8jLjb/Iy02/wwQE/8aIin/Hicv/xkh\n        KOAhKjIxHicwAAAAAAAAAAAAAAAAACgyOgAZHycAHycvVxceJfYeJy//Exgd/w0SFf8nND3/PlFV/y49\n        iP8EBev/AwPr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME7f8EBOD/MD92/01iav8sN0D/EhYX/zhH\n        Rf8wPXH/BQfj/wEC7/8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8BAfP/Cw7J/zhHZP9CVFb/MjxM/yQt\n        PP8iLDr/SVNl/09VX/9NU13/TVNd/0xTXP9NVmD/P0tX/yo6Sf8zZ6b/OoDV/zl8yv81fMv/NnrL/zh+\n        0P84fc7/N3rG/zh8zf82fMv/NnrJ/zV4xv81d7//N3i+/zh5xP81d8H/M3fF/zZ6x/8ydL3/M3O9/zN0\n        v/8ydLz/MnO8/zJzuv8xc7v/MXO7/zJ1wf8uZqL/MkdZ/0lVYP9PVV//TVNd/01TXf9NU1z/T1Vf/0lV\n        Yf8kLzf/Iy03/ys1QP8hKjD/ISk2/yAoPP8hKj3/ISk9/yEpPf8hKT3/Iio+/yAoPP8fKDv/ICc8/x4m\n        Nf8pMjr/LDM3/xASEv8kLTH/ISox/x8nM/8fJzv/Hyc7/x4mOv8dJTr/HSU5/x0lOf8bIzj/GiI3/xoi\n        N/8aIjb/GiIr/xwkK/8rOEP/ERca/xEWG/8gKzL/Fx8l+x4mLnAAAAAAJC03AAAAAAAAAAAAIyw0ACs1\n        PQcaIyqdGB8m/x8oL/8OERX/FBsg/zJCTP9AVFz/GSC0/wEB8f8DBOr/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AQLx/xIXsP9IXGb/QVJf/xUaHP8mLzD/Pk5S/xMYs/8BAfL/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AQLw/wUH3P8uO3P/Q1ZV/zVAS/8nMD3/HScv/0RQXf9PVmD/TVNd/01TXf9NU13/TFNd/0xT\n        Xf9OVmD/P0xZ/y9CVP83b7H/NXnG/zN3xf81ecj/M3jH/zN2w/81dsX/NXfG/zd8zP83ecj/N3rI/zh7\n        xv85fMj/O37L/zp8yP82fMn/N33M/zR5xf83esf/M3XA/zJ0vf8zdcD/NXe//zd5xP8zd8P/Mm6x/zBJ\n        YP9EUFr/TlVg/01TXP9NU13/TVNd/01TXf9NU13/TlVf/0pUYv8jLTb/KTI8/yozPP8iKjH/ISk4/yAp\n        Pf8hKT3/ISk9/yAoO/8hKDz/ICg8/x8oO/8fJzv/Hyc6/x8oMv8vOD7/HCAh/xcbG/8mMDX/ICkw/x8o\n        OP8fJzz/Hyc7/x0lOv8eJjr/HiY7/xwkOf8bIzj/HCM4/xsiOP8aIjD/GSEn/yg0Pv8bJCn/DBAS/xwl\n        K/8aIyn/GyQrtSYxOg4iLTUAAAAAAAAAAAAdJi4AHykxJBgfJtQbIyr/GSAn/wwQE/8gKTL/OUpR/zhJ\n        bf8JC97/AgPt/wME6v8DBOv/AwTr/wME6/8DBOv/AwTr/wME7f8CA+X/LTp7/1Bnbv8tOEH/Fhkb/zxL\n        R/8pM3//AgPq/wID7f8CA+z/AgPs/wID7P8CA+z/AgPs/wID7v8BAu3/IiuI/0VXVP81Qkz/KjM+/x8n\n        MP9DT13/T1Vf/0xTXP9MU13/TFNd/0xTXf9MU13/TFNd/0xTXP9PWWT/RFBe/zFKZP80dL3/NHvL/zZ5\n        x/82ecf/NXjF/zV3xP81d8P/NnrI/zx/z/87fs7/PIDO/z+B0P8+f8v/PX/N/zt/zf87fcr/OX7L/z+D\n        0v85e8X/OHm//zd6xv84esX/QITS/zh5xP8xUnP/RVJd/05WYP9MU1z/TFNd/01TXf9NU13/TVNd/0xT\n        Xf9MU13/TlVf/0ZRXf8hKzL/LTU//yozO/8iKjP/ISg6/yIqPf8iKj7/Iio9/yEoPP8hKT3/ISo9/yAo\n        PP8gKD3/ICg4/ycwN/8yOj7/EBMS/yMrMP8iKzL/Hycz/x4mO/8eJjr/HSU5/xwkOP8dJTn/HSU6/xwj\n        OP8bIzj/GyM4/xwkNv8bIyr/ICox/yUwOf8NERP/Fx4j/x4nL/8aIinlISs0Nx8pMQAAAAAAIiwyABoh\n        KgAeJi5WFh0j9R8oMP8RFhr/DxMX/ys3Qv8+UFT/JTCW/wIC7f8DBOv/AwTq/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AQLx/w8TuP9HWmn/Rlhl/xYaHf8mLzD/PEtV/w8Tw/8BAfP/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AQHy/xEWsf9AUVj/PkxS/zA6RP8cJCz/N0RQ/09XYv9MUlv/TFNd/0xTXf9MU13/TFNd/0xT\n        Xf9MU13/TFNd/0xSXP9MV2T/NkJS/y9XhP81e8v/N3rF/zd6xv80eMb/N3nG/zh8yf81eMX/OX7N/zyB\n        0v87fsv/PX7J/z+B0P8+g9L/PoHQ/z+G1/9DjN7/QIfZ/zuBzf8/gcn/PoLP/z+C0P9BiNn/M2CT/z5O\n        W/9OV2L/TFJc/0xTXf9MU13/TFNd/0xTXf9MU13/TFNd/0xTXf9MUlz/UVhj/0BNW/8eJy7/MzxG/ygx\n        OP8kLDf/JC1A/yMsP/8jLD//JCw//yMrP/8iKj7/Iio+/yEqPv8hKTz/Hycy/y43Pv8eIiT/Fxoc/yYv\n        Nv8eJi7/HiY4/x0lOv8eJTn/HiY7/x4mOv8dJTn/HCQ4/xwkOP8cJDj/HCQ5/xwkL/8bIij/KDQ+/xMY\n        HP8QFBj/ICoy/xkgJ/sgKTFvEhYdACMuNgAnLzcAOEFKBBsjKpEXHyT/HCQr/w4SFf8WHSL/MkBJ/zxO\n        XP8TGcD/AQHx/wMD6v8DA+r/AwTr/wME6/8DBOv/AwTr/wME6/8BAev/JS+L/1BlbP8vOkT/ERUW/zlH\n        Qv8pNHr/AgPr/wID7f8CA+z/AgPs/wID7P8CA+z/AgPs/wEC8P8FB9r/MkBm/0RVVf8zPUf/Iysz/xwl\n        LP8zPkn/TFRf/01SXP9MUlz/TFNd/0xTXf9MU13/TFNd/0xTXf9MUl3/TFJc/05TXf9JVWf/Lz9S/zRt\n        rv87gND/OHrH/zV5xf86fcn/O3zG/zl7yP88gM//OnzL/z1/zf89f8z/QIPR/z2AzP89gtH/PIHP/zuB\n        0f85fMj/NnjB/zp8xf87fMT/PoHO/z59xf82TGb/Tlhk/01TXP9MUlz/TFNd/0xTXf9MU13/TFNd/0xT\n        Xf9MU13/TFJc/01TXf9JU13/KzY+/yApMP8kLDT/MDpE/yYvNv8kLTz/JC1A/yQtQP8kLUD/JCxA/yMr\n        P/8jKz3/Iio9/yAnPP8eJjX/JS41/y02Ov8QExP/Iyou/yMrMv8eJjP/HiU6/x4mOv8fJzv/HSY6/x0l\n        Of8dJTn/HSU5/xwkOP8bIzj/HCMy/xoiJ/8oMz3/HSUt/w0QFP8eJy7/HCQr/x0mLqopNT8KJC84ACAp\n        MQAiKzQWGSEoxBohKP8bIij/DA4R/x0mLv86SlH/N0ds/wcJ4P8CAu3/AwPq/wMD6v8DBOv/AwTr/wME\n        6/8DBOr/AgPu/wcI0v89TGv/TmFt/xkfI/8fJyj/PUtQ/xIXt/8AAfL/AgPr/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AQHw/xsilv9EVlX/N0RM/yQtNP8bISf/Jz9Y/yA2UP82P0j/TlZg/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFFb/1BYZf8+SVz/MFFz/zt/zv86e8j/OHzI/z2Bz/87fcr/N3nG/zd9\n        yv84e8f/On7K/z1/yv9ChdT/Pn/H/z6Ayv87e8T/NXW9/zd4v/82d77/OHnB/zh5w/86fMn/NV6N/0JO\n        Xf9PVWD/TFJb/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9NU1z/TVVh/y42PP8bL0T/KUVi/x0k\n        Kf8kLTX/KjM7/yUtNv8jKz3/JC1A/yUtQP8kLUD/JC1B/yUtQP8jLD//Iio+/yAoO/8hKTH/Lzk//xsf\n        If8WGxz/JzA3/yAoMf8fJzr/HiY6/x4mOv8eJzv/HiY6/x4mOv8dJTr/HCQ4/xskOP8cJDX/GyMq/yMt\n        Nv8mMTn/DREU/xkhJ/8eJy7/HCQs2SQvOCMiLTUAHSUtAB8oMDgYHyXnHSYs/xUbIf8OERT/JjE6/ztM\n        T/8pNIz/AwPt/wMD6/8DA+r/AwPq/wME6/8DBOv/AwTr/wME6v8BAfH/Fx2j/05ia/8+TVj/DxMV/zE9\n        O/8xPWv/BQbl/wEC7f8CA+v/AgPs/wID7P8CA+z/AgPr/wEC8P8JC83/OEdc/0BQU/8pND3/Fx8l/yUy\n        Pv8vZqf/KmKl/yYyPv88Rk7/TVRe/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TlNd/0lU\n        af8tO03/O3S0/z+B0P84e8f/OHrF/zt7w/84esT/NnjE/zd4wf86e8T/QIDK/z1+yf88fsn/PoHM/zx8\n        xf82dr//Nna8/zh5v/88fMP/O37I/zZytf80SWH/Tllm/0xSW/9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TVJc/05WYf8zPEP/GSQt/y5lpP82c7f/JzZE/xsiJ/8oMjv/Ji41/yMrOP8kLD//JCw//yQt\n        QP8lLUD/JS1A/yQsP/8jLD//Iys//yEpNv8nMTf/KzI1/xETE/8lLjL/Iioy/yAoN/8fJzv/HiU5/x0l\n        Of8eJjr/HiY6/x4mOv8eJjr/HCQ5/xsjN/8cJC3/Hict/yo2QP8RFRn/Exoe/yApMP8aIinzHykzTB4n\n        MAAdJS0AICkwYRgfJfkfKDD/DhIW/xIYG/8vPEb/PU9S/xkfsv8BAPD/AwPq/wMD6v8DA+r/AwTq/wME\n        6v8DBOr/AwTs/wID5P8tOYD/Umdv/ycwOP8VGhz/Pk1H/x4mm/8AAfH/AgPr/wID6/8CA+z/AgPs/wID\n        7P8CA+z/AQHv/x4mi/9DVVP/OERL/y03Pv8tNTr/L092/zN5yv83e8z/KliO/yk0Pv9IUln/UFdi/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9NUlv/Tlhn/zI7Tf80WH3/QITT/zl6xv86fcf/OHvF/zd4\n        wP84eML/PH3H/0KD0P9Hidb/QYTP/zx9xv89fcb/OXrC/zd3vf83drr/OnvF/0CCzv9Bhtf/Ml2L/zlD\n        Uv9QWWX/TFFb/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/01TXf9OVmD/NT1E/xohJf8mUX//O4DM/z6D\n        z/8xV4H/ISgs/x4nLf8mLzb/Iysz/yQsPf8lLUD/Iys+/yMsP/8kLUD/JS1A/yQtQP8kLUD/Iio8/yEq\n        Mf8wOT7/ExcX/x0jJf8kLTT/HiYx/x8mOv8fJjr/HiY6/x0lOf8eJTn/HiY6/x4mOv8eJjr/HSQ5/x0k\n        Mf8bIyn/KjZA/xgeJP8OExb/Iyw0/xsjKv8gKjR7DxgjACUuOgQdJS2QGiEn/x0lK/8NEBP/GiEo/zdG\n        Tv87TGf/DhHQ/wIB7v8DA+r/AwTq/wME6v8DBOr/AwTq/wME6v8CA+//BwnM/z5Oaf9MX2r/FBkc/yUu\n        Lv86R1n/DRDO/wEC8P8CA+v/AgPr/wID7P8CA+z/AgPr/wEC8P8ICs3/NkRb/z5NUf8xOkH/O0NG/1Fg\n        bf82ba7/M3fF/zl+zf88gdT/Omag/z1KVf9CSU3/TFJc/01TXf9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        W/9OVmP/O0RW/yxCV/87fcb/OnrE/zx+y/85ecP/OHe//zd3v/88fML/Pn7G/0WH0/9EhtP/O3vE/zp7\n        xf83eMD/N3a7/zd2uv87e8P/RITM/z6Bzf8rSWj/QEhW/1BWYP9MUlv/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9OVF7/SlJc/zA3O/8cJCn/Jk99/zh8x/88gMv/PYTR/zh1vP8rOkn/GRwd/yUtM/8mLjX/JSw5/yQs\n        P/8jKz7/Iyo9/yMrPv8kLD//JCw//yIrPv8gKDv/ICgz/y02PP8hKCr/FBcY/ycwNv8gKDD/HiU4/x4m\n        Ov8eJjr/HiY6/x4mOv8eJjr/HiY6/x4mOf8dJTn/HSU2/xwkK/8nMjv/Iisz/w0RFP8eJy3/HCQr/x4n\n        MKglMDsKKDA7EBsjK7gcJCv/GiEm/wwQEv8hKjL/PE1T/zRCd/8GBub/AwLq/wMD6v8DA+r/AwTq/wME\n        6v8DBOr/AwTq/wIC7/8UGKv/TWFq/zpJUv8NEBD/NEE+/y46df8EBer/AgPs/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AAHv/xgel/9DVVL/N0JK/xwiJv8xNjn/SmmM/zJ2w/81d8P/OH/O/z+C0f9EiN3/NGin/yAx\n        QP8yODn/SVBZ/05UX/9NUl3/TFJc/0xSXP9MUlz/TFJc/05VXv9CS13/KThJ/zt7wv85fcj/O3/O/zt9\n        yP87fMb/OnvF/z+Czv8/gcv/QoTP/0KE0P9Ags//PoLO/zp7xP84esT/O37G/zp+yf9AhM//PX3D/yk6\n        S/9GUF//TlRe/0xSXP9MUlz/TFJc/0xSXP9NU17/TlVg/0NLU/8mKy3/GyYt/zFmof9GkeT/QIbV/zl+\n        yv80e8j/Nn3L/zBXgv8kJyz/HSMn/ygwNv8kLDT/Iyo8/yMqPv8jKz7/Iys+/yQsP/8kLD7/Iio9/yIp\n        Pf8jKjn/KTE4/y01Of8QExP/JCov/yEpMP8eJTX/HiU6/x4lOf8eJjn/HiY6/x4mOv8eJjr/HiU6/x4l\n        Ov8eJTj/HiUu/yQuN/8nMjv/DRAU/xogJv8gKDD/HCUszCUxORglLjcjGyMq1xwkLP8YHiT/DhEU/yYw\n        Of8/UFX/LDeO/wQE7f8DA+r/AwPq/wMD6v8DBOr/AwTq/wME6v8DBOr/AgLs/yQthP9RZmz/KDE3/xIW\n        F/87SUb/HiWc/wEC8P8CA+v/AgPr/wID6/8CA+v/AgPr/wID7f8DBOL/LTlq/0JTUv8sNTv/Fhoc/ys0\n        Rf8xZKL/NXnJ/zp9zP86f83/P4HM/0WI1v9Ei9//MG20/yE6U/8oLjD/PURI/0tTXP9OVF//TVNe/01T\n        Xf9MUlz/TVNc/0hRZ/8sNUD/MU9s/zFRcf8xUHD/MVFx/zFQcP8yUHH/NFV2/zRUc/80VHT/NVR0/zVU\n        dv81Vnn/MVBw/zBObv8yUnP/MVFy/zNTdP8zUnH/KzU//0tUZP9NU13/TVNd/01TXf9OVV//TlZg/0ZP\n        WP80Oj7/HiMl/x01Tf8tZaL/PYjc/0SM3P9BhdL/PYPP/zJ2wv8zeMP/NHG0/y05R/8YGx3/JCwx/yUs\n        M/8jKjn/JCs//yMrPv8jKz7/JS1A/yUtQP8jKz7/Iys+/yQsPf8lLTb/MjtB/xQXF/8dIST/Ji41/x8m\n        M/8fJjr/HiY6/x8mOv8fJzv/Hyc7/x8mOv8eJjv/HiY6/x4lOf8eJjD/ISox/ys3Qf8QFBn/Fx0i/yEq\n        Mf8bIyvnJC44NyAqM0UbIyrqHygv/xQZHf8PExf/LjpF/0FSV/8eJqr/AQLu/wME6v8DBOr/AwTq/wME\n        6v8DBOr/AwTq/wME7P8EBdr/NUN0/01gZ/8YHB//HyYn/zxLUv8RFsP/AQHw/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AQHy/w4Ruv88TVP/PUtQ/yIpLf8aHSH/K0Fi/zBwu/81d8L/OHnF/z6Azf9Bg9H/QoPQ/z+A\n        zv88fsv/NXS9/yZWiv8gMkL/Ki8w/zlARP9FTVX/SlFb/0xUXv9OVV7/TVhs/y00Pv8pLzP/LTM4/y40\n        Ov8tMzn/LjU6/y40Ov8sMjf/KzE2/ysxNv8rMDX/Ki80/yovM/8qLzP/KS4z/ysxNf8sMTf/Ki80/yov\n        Nf8uNT//TFZn/0tSXP9KUlz/RU5Y/zxES/8vNTj/ICQl/xwqNP8lTXn/MG+3/zh7xv9Ag8//QYHJ/z9/\n        xv9Bg8r/OXvE/zp+yv87f8r/LUlo/x8hJP8hJyz/Jy41/yQrN/8kKz7/Iyo9/yMrPf8lLD//JSw//yMq\n        Pf8kLD//JC0//yQsNv8uNz7/HyQm/xYZG/8nMDb/ICgy/x8mOv8fJzv/ICg7/yAoO/8fJzv/Hyc7/x8n\n        O/8fJjr/HiY6/x8mMv8fJy7/LjpF/xUaH/8SFhr/ISkw/xwlLPIhKzVZIiw0ZBwkK/UhKjH/DxIW/xMY\n        HP8zQUv/QFFZ/xUbxP8BAe7/AwTp/wME6v8DBOr/AwTq/wME6v8DBOr/AgPu/wgKx/9CUm3/RVZe/w0Q\n        Ef8qNDL/NEFo/wcJ3f8BAu7/AgPr/wID6/8CA+v/AgPr/wID6/8AAO//GiGR/0NUUP82QEj/GR8h/yEm\n        M/8sU4L/NHbD/zV2wf83eMP/QYTS/0SFzv9FhdL/RIbV/0CBzP88e8b/PoLQ/zNvtf8nTXb/ITNF/yEo\n        Lf8mKy3/KzEz/zM7Qv82P0n/Jy0z/yMmKP8mKCr/JSkq/yUoKv8mKSv/JSgq/yQnKf8kJyn/JCcp/yQn\n        Kf8kJij/IyYn/yMmJ/8jJif/JCcp/yUoKv8kJyn/JCgp/yctM/8zPEX/LTU8/yUpK/8fIyP/HSMn/x4u\n        Pf8lSXH/MW2w/zd6xf83eMH/OnvE/0WFz/9EhMr/QYTQ/0CG1f88fcf/On/M/zp/y/8uW43/JSox/xsg\n        If8qMjn/Ji42/yYuP/8kKz7/Iyo9/yMqPf8lLT//JCw//yUsP/8lLUD/JCs4/yozOv8oLzP/EBIT/yYv\n        NP8hKTH/HyY4/x8mOv8gKDv/ISk8/yAoPP8gJzv/Hyc7/x8mOv8eJjv/HyY1/x4mLP8uOkT/HCQq/w0R\n        FP8hKjL/HSUt+yAqM3siKzOCGyMq/SIrM/8OEhT/GB8k/zdETf87Smr/DRDW/wIC7f8DA+n/AwTq/wME\n        6v8DBOr/AwTq/wME6v8CAu//Ehe1/0tcY/83Q0v/DA4P/zRAPP8rNnn/AwTt/wID7P8CA+v/AgPr/wID\n        6/8CA+v/AgPt/wID5v8rNGf/Q1NS/y01O/8WGh3/JjBE/y9mpv82dsH/N3jD/zt7xv9DhND/SorT/0yO\n        3f9Hh9P/P3/I/zt6wv8+fcf/PX3H/0CBzf85ecP/LmCa/yxRev8lP1j/IScs/yowN/8nLjT/KEJb/ydF\n        Yf8mRGD/J0Rg/ydEYP8oRWH/KERi/ydDYf8pRWL/KUVh/yhEX/8oQ1//J0Nf/ydDXv8nQ17/KENf/ylF\n        Y/8oQ1//Jy81/ykvNv8jJyv/JTxS/y1QeP8wYZj/M3G2/zh6w/87e8P/N3e9/zt8w/9ChdH/R4nT/0mM\n        2P9Ag87/OHvF/zt9yP89gc3/On7I/zFsrP8pNUP/Gx4g/yYtMv8nLzb/JS07/yUtP/8lLT//JS0//yYt\n        QP8mLUD/Ji1A/yUtQP8lLDz/Jy82/y01Ov8SFRb/Iyot/yIpMf8fJjf/ICc7/yAoO/8hKTz/ISk8/yAo\n        O/8fJjr/HyY6/x4mOv8fJzb/HiYt/yo1P/8hKjH/DREU/yIrM/8cJCv/ICkynSEpMZ8aISf/Hygu/w4R\n        FP8eJi3/OUhO/zdFcP8ICtv/AgPs/wME6f8DBOr/AwTq/wME6v8DBOr/AwTq/wEB6/8cIpj/U2Zr/ykz\n        Of8QExP/OkdG/yAol/8BAvD/AgPr/wID6/8CA+v/AgPr/wID6/8BAvD/BgfK/zhGWP9ATVD/Ji0y/xcY\n        Hf8qQWT/M3C3/zd4wv89fcf/PHzH/0GCz/9Ojtf/TIzY/0WEz/9Cgcn/Pn3F/z5+x/88fcj/QYHL/0OD\n        z/9AgMr/Q4jW/zt1tP8lKzD/LDI5/ykyN/89eLn/PoDL/zx8xP87e8T/Pn/J/0OEz/9Cg83/QYHJ/0SD\n        y/9Cgcn/Pn3C/z5+x/89fsf/PHvB/z18w/89fcP/P4DI/z55vf8qNT7/KzA3/yQpK/84aqL/TJLh/0mM\n        2P87fML/Oni7/zt5v/85ecD/PHzD/0OEy/9Gh8//R4nP/0SGz/8/gMr/Pn7H/0mM2P9BhdD/NXjD/y5J\n        Z/8bHR3/Iyou/ykwN/8mLTn/Ji5A/ycuQP8nLkH/Ji1A/yYuQP8nLkH/JS0//yQsPP8kKzP/MDk//xUY\n        Gf8dIiX/JS40/x8mNP8gJzv/ISg7/yEoO/8gKDv/ICg7/yAoO/8fJjr/HiU5/x8nOP8fJy7/KDI7/yUv\n        N/8NERT/HiYt/xwjKv8gKTK4ICgwtBwjKv8bIyn/DBAT/yMrM/8/T1T/NUF+/wUG5f8CA+v/AwTp/wME\n        6f8DBOr/AwTq/wME6v8DBOr/AQHq/yMsiv9SZmv/ICcq/xcbHP87SUr/FRu1/wAB8P8CA+v/AgPr/wID\n        6/8CA+v/AgPr/wEB8/8NEK//Pk1T/ztHS/8dIyb/HCAo/ypMd/83eMD/OHjB/0CBy/85ecP/PH7J/02M\n        0v9KitL/QoPO/0SCyP9Afsb/Pn7G/z59x/9Eg8v/SYfN/0OByf8+f8n/O3Ow/ycsMv8vNTz/KDA2/zx2\n        uP9Bgcf/QX3A/0B8v/9BgMb/SIjR/0iHz/9Ihsv/SojO/0iFy/9Dgcf/R4XN/0OByf9AfcD/QX/E/0GA\n        xv9Egsj/QHq6/yo0PP8sMjj/JSkr/zdmm/9NkNv/SInS/zx6v/87ebz/O3q//z19xf9Cgcn/SIfQ/0iJ\n        0P9Ehc//QITR/0SJ1/9Agsv/RYjR/0eJ0v83fMn/LFN7/yEkJf8eIyf/KTA2/ycuOP8nLj//Ji0//ycu\n        QP8mLkD/Jy5A/yYuQP8lLT//JCs9/yQrNP8vOD7/GyAh/xcbHP8nMDb/HyYz/yAnOv8hKDv/ISg7/yAo\n        O/8gJzv/ICc7/x8mOv8eJTn/HiY4/x8mLv8lLjf/KTM8/w0QE/8bIyj/Hicu/x4nL84fKC/GHycu/xge\n        I/8MDxH/JS41/0NSVf8xPIv/AwTu/wME6f8DBOn/AwTp/wME6v8DBOr/AwTq/wME6v8CA+f/Lzl0/1Jl\n        a/8ZHiD/HSMk/zxKTf8QE8r/AQHv/wID6v8CA+v/AgPr/wID6/8CA+v/AADz/xgelf9CUUr/OENJ/xcb\n        Hf8eJDD/MFyQ/zl6xf87e8P/QYTR/zl3v/87fcf/TY3W/06N1f9Dg87/QYHL/0B/yP9AgMv/P3/J/0WE\n        zf9Jh8r/R4XM/0CBy/86b6r/Jy0y/zA2Pf8pMDX/OnGu/0OF0P9Dgcn/RIHG/0J/xP9Egsj/RoXM/0mH\n        zv9Jh8//Q4DE/0SCx/9Hhsz/Qn/E/0F9wP9Df8P/QoDH/0SBxP9Be7v/KjQ9/y0yOP8lKSv/NGCP/0OF\n        zv9FhMz/Q4HG/zx8wf87eb3/PHvA/0OFz/9EhMr/QIPO/z+Byf89fcT/RIjV/0iIzv9KitD/R4rY/zp7\n        w/8vYJT/JCwz/xcaG/8rMzr/KTA4/ygwQf8oL0L/KC9C/ygvQf8nL0H/Jy9B/ycuQf8lLD//JSw2/y02\n        PP8kKi3/FBgY/yYuNP8hKDP/ISg7/yEpPP8hKTz/ICc7/yAnOv8fJzr/HiY5/x4lOf8eJTj/HiUu/yQt\n        NP8sN0D/DhEU/xYcIf8iKjL/HSYu4R8mLtUhKTH/Fx0j/w4RFP8pMjv/QlJW/ys1lP8DA+7/AwTp/wME\n        6f8DBOn/AwTp/wME6v8DBOr/AwPq/wQF5P87SHb/UWRp/xATFf8iKir/OkhY/w0P0f8BAu7/AgPq/wID\n        6/8CA+v/AgPr/wID7P8AAOj/HyZ5/0RTT/80PUP/Fhoc/yEqN/80aaj/OXjA/zp5wP89fMX/PHvD/0KC\n        zP9Pjtf/UJDa/0WFz/9ChM7/P33E/z1+yP9CgMn/RILI/0uJz/9Njdj/SYjQ/z5zrv8mLDH/MTc+/yox\n        N/8+c67/RIXQ/0SDzP9Gg8n/RoPI/0SAw/9Kh87/VZPa/06N0v9EgcT/RIDD/0eGzf9Df8P/Q3/D/0aB\n        xP9Fgcb/RoLF/0R9vP8qND3/LTM5/yUpK/8zX5D/QoPK/0OByP9Ghs//QoLK/z15u/88e8H/PX3F/z99\n        w/87e8T/O3rA/zx7wf9Dg8z/RYfQ/0iK0/9Fh9H/Oni+/zJsq/8mMj7/GRsb/yw0Of8rMzr/KjFC/yoy\n        RP8qMkP/KTFD/ykxQ/8oMEL/KDBC/ygvQv8mLTj/KTI4/ygwMv8RFBT/KDA1/yMrNv8hKDv/Iio8/yIq\n        Pf8iKTz/ISk8/yAoO/8fJzr/HyY6/x8mOf8eJi//ISkx/y86RP8RFRn/FBoe/yIsM/8dJS3yHiUu4SEp\n        MP8YHSL/DxIW/ykzO/9CUlj/Ji+p/wID7v8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8CA+3/BQfN/0NS\n        cf9PX2b/DA4P/ygyL/80QGz/Bwnf/wEC7f8CA+r/AgPr/wID6/8CA+r/AgPs/wEB5f8mL3L/Q1JQ/y01\n        O/8XGxz/Ii48/zp2uv88e8P/O3vC/zx5v/87esH/RYfS/0+O1v9Rktv/SojO/0WEzf9BfsT/P33F/0F/\n        xf9Fgsn/TYzU/0uJ0f9Ih9D/PnOv/yYsMf8yNz//KzM5/0B2s/9KitT/QoHI/0OAxf9Fgsn/TInO/1KR\n        2P9bneb/U5LY/0aDyf9HhMn/RoLH/0SAw/9Egcj/SITI/0WBw/9Gg8f/Q329/yo0PP8vMzr/JSkr/zVi\n        lP9Ghs7/RIPL/0ODy/9BfsT/Pnq7/z18w/9Cgsr/RIPL/z9+xf9Agcv/PH7I/0aJ1f9HiNH/R4jR/0OD\n        yv85ecD/NXO4/yU2Rf8aHR3/KTE2/y01PP8rMkD/KzJE/yoyRP8qMkT/KjJE/ykxQ/8oMEL/KC9B/yYu\n        Ov8pMjj/LTQ3/w4QEP8nLjP/JS43/yMrPf8jKj3/Iyo9/yIqPP8hKTz/ISc7/yAoO/8gKDv/ICc6/yAn\n        Mv8hKTD/LjlD/xMXHP8VGh//Iywz/xwlLP0eJS3rISgw/xccIv8QExf/KjQ7/0JRWv8fJq//AgLu/wME\n        6f8DBOn/AwTp/wME6f8DBOn/AwTp/wID7/8GB7//RlRs/0dXXv8LDg//LDY0/zE8bP8FB9//AQLt/wID\n        6v8CA+r/AgPr/wID6v8CAu3/AwPe/yw2X/9BT0//KjE3/xYZGv8nO1H/QX/G/z17w/8+fcX/P33E/zx5\n        v/9Dgcf/UI3T/1SU3v9Mic7/RoPJ/0OAx/9AfsX/Qn/F/0mHzv9Oi9L/SobM/0aFzf86bKP/Jy0x/zM5\n        Qf8rMjf/PXGq/0eFy/9Ihs7/RoTK/0iEyf9Lh8z/VJbi/1GS3f9SkNf/R4PG/0iDxf9Khcn/RoHD/0WA\n        wv9HgsT/RoLD/0eDx/8+d7f/KTQ8/zA1PP8mKSz/N2SV/0iHzf9Fg8b/QX7C/0N/xP9BfL//P37C/0GC\n        zf9BgMj/Q4HF/0iI0f9FhtD/RoTK/06N0/9PkNj/SYrV/zl6w/83drv/K0Na/xsdHv8nLjP/LjY9/ysz\n        Qf8sNEb/KzNF/yszRf8rMkT/KjJE/ykxQ/8oL0L/Jy88/yoxOf8vNzz/EBIT/yQsMP8mLjf/JCw9/yMq\n        Pv8iKjz/Iik8/yIpPP8hKDv/ICc6/yAnOv8gJzv/ICgz/yIqMP8tOEL/Exgd/xUaHv8jLDT/HCQs/x4l\n        LfIgJy//Fhsh/xATGP8rNT3/Q1Fa/x0krf8BAu//AwTp/wME6f8DBOn/AwTp/wME6f8DBOn/AgPv/wcI\n        v/9KWHH/RFNY/wwPEP8vOTb/MDpt/wQG4f8BAuz/AgPq/wID6v8CA+r/AgPq/wIC7v8EBNf/LzlL/0JP\n        Uv8qMTb/FRcX/y1FXv9Egsv/PHvC/zx5v/8+er//PXvB/0OCyP9Uktv/UZDZ/0yM1f9HhMr/Qn7D/z99\n        w/9Fgsf/SofK/0yK0f9Jh9D/SIfQ/zpspP8nLTH/NTtC/yoxN/8+c63/T47X/02M1P9Jhs7/TIrS/06K\n        0v9TleP/SYfP/0qJ0v9GhMr/RYDC/0qFyP9Ig8X/RYLH/0eCxf9HgsX/SobJ/0V+vf8qNT3/MTY9/yYp\n        LP81YZD/RoTJ/0WCxf9FgcX/Q3/D/0eEy/9AfsP/R4fR/0yM1v9IiM//S4zV/0yN1/9KidD/SojN/1CQ\n        2f9KjNj/OnnB/zh4v/8vS2f/Ghwc/yctMv8wNz7/LDNB/ywzRv8tNEX/LDRF/yszRP8rMkT/KjJD/ykw\n        Q/8pMD7/KjE4/y83O/8SFRX/JCsu/ycuN/8kKz3/Iyo9/yMqPf8jKj3/Iik8/yEoO/8gJzr/ICc6/yAn\n        O/8gKDP/Iiow/y86RP8VGh7/FBkd/yMrM/8cJSz/HyYu9SAnLf8WGx//ERUZ/y86Qv9EU1v/HSOs/wEC\n        7v8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8DA+//CAnC/01ddv9DUFb/DA8Q/zA7Nv8uOHb/AwTm/wIC\n        6/8CA+r/AgPq/wID6v8CA+r/AQLu/wQF2P8xPEz/Qk9T/yoxNv8SExP/LUVg/0SDyv8/fsX/Pnq//0B+\n        xP88er//R4bM/1aW4P9QjtT/TIfL/0aBxf9DgMT/QX7D/0R/wv9Ggcb/R4TK/0iEy/9Lic7/Pm+m/yct\n        MP81O0L/KjI3/0F3tP9Pj9j/SYXJ/0eBw/9Nicz/VJHX/1eY4/9Mh8v/TIbK/02Izf9Hg8j/SYXK/0eD\n        xv9Gg8n/RoHC/0iExf9Mh8r/SILE/ys1Pv8zOD//Jiks/zRgj/9Ihcn/RoLG/06L0f9IhMj/TIrP/0aC\n        x/9Hhcz/T47X/0yN1v9Li9P/T43V/0yN1/9IiND/TI/a/0aGz/87eb//OnrD/zBPb/8YGRj/Jiwy/zE4\n        QP8sNEH/LTRG/y00Rv8tNEX/LDNF/ysyRP8qMkP/KTBD/ykwPv8qMDf/LjY6/xMXFv8iKCv/Jy42/yMq\n        PP8jKjz/Iik8/yMqPf8iKTz/ISg7/yAnOv8fJjr/ICY6/yAnM/8iKTD/MTxG/xYbH/8TGB3/Iioy/x0l\n        LP8fJy/1ICct/xYaHv8RFRn/MTxE/0RSWf8bIav/AQLu/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wMD\n        7v8JC8P/Tl53/z5LUP8NEBH/Mz45/yw2f/8CA+v/AgPq/wID6v8CA+r/AgPq/wID6v8BAu7/BQbZ/zI+\n        Tv9CUFP/KTE2/xAREP8uR2L/Q4DF/0OByv8/fML/RoTL/0J+xP9LitD/V5jj/1OQ1P9LiMv/R4TK/0mJ\n        0v9Fgsf/R4PI/0eCxv9KiM7/SIXL/0uIzf89b6b/Jy0x/zc9Rf8rMjf/Q3u6/1ub5P9Qi9D/SoXI/0uG\n        yf9Tj9L/V5Tb/1CM0v9Zl9//VZDT/06Iy/9Vkdf/TIfJ/0qExv9JgsP/S4XH/1KNzv9RjM7/LDY//zM5\n        P/8nKy3/NGGR/0eFzP9Gg8j/TozW/0uIzv9Oi87/RoLH/0uJzv9Xlt7/VJLY/02L0/9Jh8z/TY7Y/0eJ\n        0/9Dhc//P3/I/zt5vf86eL3/MVBw/xYXFv8nLTL/MjpA/y00Qf8uNUf/LTRF/y00Rv8sNEX/KzNE/yoy\n        Q/8pMUP/KTE+/ykwN/8vNjz/FRgY/x8kJ/8nLjb/JCs8/yMqPf8jKj3/Iik8/yEoO/8hKDv/ICc6/yAn\n        Ov8gJzv/ICcz/yEpL/8xPEb/Fhsf/xMYHP8iKjH/HSUu/yAoL/EhKTD/Fxsh/xEUGP8sNT3/QlBX/xwi\n        q/8BAu7/AwTo/wME6f8DBOn/AwTp/wME6f8EBOn/AwPv/wcIwf9PXnf/PUlN/w0PEP81Pzv/LDZ4/wME\n        6P8CAuv/AgPq/wID6v8CA+r/AgPq/wEC7v8EBdj/MTxL/0JPUv8rMzj/EhQT/y9HX/9AfMD/PnvA/z96\n        vv8/fML/Q3/G/0qHzv9Xldz/U5HX/06L0f9Lhs3/SofO/0aCx/9Lh83/TYfK/06Hyf9Khcr/SYfN/zxs\n        o/8nLDD/OT9G/yoyN/9Ifbn/YJ7j/1GO0v9Lhcf/TYfI/1OP1P9gneL/Uo7T/1GO0v9Ri87/TonL/1qZ\n        3/9Oicr/SoTG/02HyP9Picv/Uo7R/02Hx/8sNj//NjxC/ygsLf89aJb/T4zS/02K0P9Qj9f/SIXL/0SB\n        xv9EgMT/RIHF/0aI1P9Ihsz/TIjM/1GQ2P9Tkdb/SojM/0aFzP9AfMP/PHe6/zt4u/8wT23/GRoa/ygu\n        Mv8yOkH/LjVC/y82SP8uNUb/LTRG/y00Rf8sMkT/KzJD/ysyQ/8pMT7/KjE4/zE5Pv8VGRn/HiQm/ycu\n        N/8lKz3/JCs+/yMrPf8iKTz/Iig7/yEnOv8gJzr/ICc6/yAnO/8gJzP/Iikv/zA6Q/8WGh7/FBkd/yIr\n        Mv8eJi7/Hycu6iEpL/8YHCH/ERQY/y02Pv9GVVz/HiWu/wEC7v8DBOj/AwTp/wME6f8EBOn/BATp/wQE\n        6f8DA+//Bwi//01bdP8+Sk7/DQ8Q/zM+PP8uN27/BAXi/wIC7P8CA+r/AgPq/wID6v8CA+r/AQLu/wQE\n        1/8wOkv/Qk9R/yw0OP8VFxb/MUhf/0SBx/8/e77/QHy+/0F9wf9FgMX/TYnP/1OQ0v9YlNb/WJXa/06K\n        z/9IhMn/RYHG/0iDx/9RjND/VpHT/1CKzP9TkNj/RHWu/yctMP87QUj/KzI2/0l+uP9goOb/VJHY/1ON\n        0v9Vkdb/XZre/2Oh6P9fneT/U5Ha/02Jzf9Qi87/V5TY/0+Iyv9Mhcf/WJPV/1OOz/9Pisz/SYC+/yw2\n        Pv85P0b/KCst/0Jun/9VlNv/TYrQ/06M1P9JhMj/RYHF/0SBxv9Df8P/QoHI/0aEyv9MiMr/T4/W/1OT\n        3P9Vk9n/TY3Y/0SCyv88eb3/PXu//zFNaf8aHRz/Ji0x/zE5QP8uNUL/LjVH/y82R/8uNUb/LDNE/ysy\n        Q/8sM0T/KjFD/ygvPf8pMDb/MDg9/xQZGf8eJCf/KC84/yUtPv8mLD//JSs+/yQqPf8jKjz/Iik7/yEo\n        Ov8fJjn/HyY6/yAnMv8iKjD/MDtE/xUaHv8UGR3/Iisy/x4mLv8hKTHgIysx/xgdIf8QExf/LTY+/0hX\n        Xv8iKbH/AgLu/wME6P8DBOj/AwTp/wQE6f8EBOn/BATp/wMD7v8GB7//SVVu/0BNUf8MDxD/MDs5/y86\n        aP8FBt7/AQLs/wID6v8CA+r/AgPq/wID6v8CAu3/AwPb/yw1Vf9EUVL/Lzc8/xYZGP8tQVb/RoLJ/0F8\n        v/9BfMD/Q3/E/0WAxP9Khsz/VJDT/1eT1/9VkdT/UY7S/0uFyf9HgcX/SYLF/0yGyf9Tj9X/VpLY/2Ge\n        4/9Dc6n/Jy0w/ztASP8rMjf/Rnmy/1qY3v9Ylt7/U4zO/1SQ1P9emdz/Xpre/12Y2v9gm93/VJHX/1ON\n        z/9Zldv/UozO/02Gxv9Vj9D/UYvK/0+Kyv9Hfrn/KzU9/zxCSP8pLS//QGub/1yZ4P9Pi9D/U5Pb/02J\n        y/9IgsP/RoLI/0V/wf9EgMX/RoPJ/0eCxv9Hg8f/T4zS/0+M0P9Rj9b/RoXM/z56v/8+fcP/LUZf/xkc\n        G/8nLTL/MDc+/y41Qv8wN0n/MDdH/y41Rv8sM0T/KzJD/ysyQ/8pMEL/KC47/ycuNP8uNjr/ExcX/yAm\n        Kf8oLzj/Ji0+/yYtP/8lLD7/JCs9/yMqPP8iKTz/Iik8/yEoO/8fJTr/ISgz/yMrMf8wO0T/FBkd/xUa\n        Hv8jLDP/HiYu/CIrM9QlLTT/GR8j/xATF/8sNT3/R1Zb/ygwrP8CA+7/AwTo/wME6P8DBOn/AwTp/wQE\n        6f8EBOn/AwPt/wYHyv9FUm//Q1FU/wsPD/8vOTb/Mjxr/wYI4P8BAuz/AgPq/wID6v8CA+r/AgPq/wID\n        7P8BAeP/Ji5t/0RTUP8zO0H/Fxob/yQxPP9Ce7v/QX2//0J8vf9Efb//RoDF/0qHzf9WktT/V5HQ/1OP\n        0/9TjtD/TojJ/0eCxv9Jg8b/TYfM/1GLzf9ZlNf/Xprc/0Rzp/8oLTD/O0FI/ysyNv9KfLP/VJDW/1OO\n        0/9UjtD/VpHS/2Kd4P9Uj9P/UozP/2Cb3f9cmuH/VpPZ/1+b3/9cltj/UIjI/1KLyv9Qicr/UYvM/0d+\n        uv8qNDv/Oj9G/yksLv8/a5v/Z6Xq/1eS1f9PjNH/SofN/0iDxf9HgcP/RYDC/0V/wv9FgcX/RoPJ/0iD\n        xf9Lhsn/TYfJ/1KQ1f9Hg8j/QX7C/0F+w/8oOEj/Gh0c/ywzOP8wNz7/LTNB/y41Rv8vNkb/LjVG/ywz\n        RP8sM0T/KzFD/ykvQv8oLjr/KjA2/y82O/8TFhX/Iygr/ykwOv8nLT//Ji0//yYsP/8lKz7/Iyo8/yMp\n        PP8iKDv/ISg7/x8lOf8gJzH/Iysx/zA7RP8TFxv/Fhof/yUtNP8fJy7wJCw2xCUsNP8ZHiL/DxIV/y02\n        Pv9KWF3/LjeZ/wME7v8DBOj/AwTo/wQE6P8EBOn/BATp/wQE6f8EBOr/BAXi/z9Jd/9JWFn/DA8P/y44\n        OP85RFz/Cw7V/wEC7P8CA+n/AgPq/wID6v8CA+r/AgPr/wAB5f8gJnL/Q1JO/zlCSf8YGx3/Iywy/0F1\n        sf9DfsH/Qny8/0R+wP9Khcz/TonN/1iT0/9bltf/XJfb/1SQ1f9Oicr/SYLC/0yGx/9Qi8//V5PV/1iT\n        1P9XktP/QnGk/ygtMf89Q0r/LTM3/1CBt/9cl9v/WJLU/1WQ0v9Zk9P/X5vf/1KN0P9XktT/W5ba/1qV\n        2P9kouf/W5rh/1aQ0f9Qicj/UInI/1GJyv9dmuD/T4XB/yozOv84PkT/KCst/z5plv9hoeb/Xprd/1iS\n        1P9bl9r/V5LU/06Hx/9Jg8P/R4DA/0V/wv9EgMT/Q37C/0mFyv9Yltr/WZjg/0iDxv9CgMX/Q3u6/yg1\n        Pv8YHBv/MTg+/zA2Pf8tNEP/LjRF/zA3R/8vNkf/LjVG/y00Rf8tNET/KzJD/yoxO/8rMjn/MTk8/xEU\n        FP8kKi3/KS86/ycuQP8nLkD/Jy0//yUsPv8kKz3/Iyo8/yEnOv8hJzr/ICc5/yAnMP8lLTT/MTtE/xIV\n        GP8WGh//JC00/yAoMd8lLTayJCsy/xwiJ/8NEBP/KjI5/0pYW/8zPYv/AwTt/wME6P8EBOj/BATo/wQE\n        6P8EBOn/BATp/wQE6f8DA+b/NT52/1JhY/8MDQ7/KTEy/z1KTP8OEcn/AQLt/wID6f8CA+r/AgPq/wID\n        6v8CA+n/AADx/xcci/9BT0f/P0lP/xsfIf8gJij/OmWU/0SAxP9EfsD/RoHE/0qFyP9Sj9b/W5XW/16a\n        3v9dmNv/VpHU/0+Ix/9Jg8X/TojK/1iU2v9ZlNb/VZDT/1+c4P9Hdqv/KC0x/z9FTP8tMzj/UIK4/2Sg\n        4P9cldX/Vo/P/1mT1f9Yk9f/VY/R/12Y2f9ppeb/YZ3h/1qW2P9cmNz/VJDV/1OMzP9Wjsz/U4zM/2Ki\n        6f9PhcP/KjM6/zg+Q/8nKyz/OGKP/1WS1v9dmdv/WJPW/1eU3P9YlNf/UYrL/02Gx/9Mhcf/SILD/0mE\n        yP9GgML/SYXJ/0+P1/9OjNH/RYDC/0WCxv9Bcqb/JCwx/xkcHf80PEP/MDY9/y82Rf8uNEX/LjVF/y0z\n        Rf8tNEX/LDJE/ysxQ/8rMkP/LDM9/y00O/8vNjr/DxER/yYsMP8oLzr/Ji0//yctP/8nLj//Ji0//yQr\n        Pf8kKjz/Iig7/yIoO/8hJzr/IScv/ycvNv8sNT3/DhAT/xkeI/8jKzL/ISkyyyYuN5wjKjL/ICct/w4R\n        FP8mLjT/SFVZ/zpFhf8FBub/AwPp/wQE6P8EBOj/BATo/wQE6P8EBOj/BAXp/wEC6f8rMo3/Wmls/w0P\n        EP8kKyz/P0xN/xMYvv8AAe7/AgPp/wID6f8CA+r/AgPq/wID6f8BAfL/DhCk/z5KS/9CTVH/JCou/xse\n        Hf81Vnn/R4PH/0qDx/9Nh8v/TYfH/1eX4P9ZlNf/XZjb/1yX1/9Ujc3/UYrM/06Iy/9Ri83/VY/Q/1WO\n        z/9Si8v/Xpve/0t5rP8pLjH/QUdO/y0zOP9Kfrj/ZaHm/1qU1/9ak9P/WpPW/1uX3f9YktT/XpfW/2Wf\n        3f9bldb/WZPU/1mS0/9ZktT/VY/T/2Gb3P9aktH/Z6bs/1WMyP8pMjn/OT5E/ycrLP86Yo7/Uo3Q/1GL\n        zP9OiMr/WZbd/1mU1/9Vj9D/VI7Q/1aS1v9SjM//UIvO/0qExf9GgcX/TInQ/0iDx/9GgcT/SITI/zti\n        jP8fIiL/Iicq/zY9RP8yOUH/MThI/zA3SP8vNkb/LjRE/y0zRP8qMEH/KjBB/ywzQ/8tMz3/MDg+/ysy\n        Nf8OERD/KC4y/ygtOv8mLD7/Jiw+/yYtPv8mLD//JSw+/yQrPf8jKjz/Iyk8/yIoOv8hJy7/KzQ8/ysz\n        PP8NEBL/HSMo/yEoMP8hKTK1JjA5fiIpMP0kKzH/DxMW/yEoLv9GU1n/QU15/woL2v8DA+r/BATo/wQE\n        6P8EBOj/BATo/wQE6P8EBen/AgLq/yEmlv9baWz/Fxsd/x4jJf8+S0n/HiWe/wEC7/8CA+n/AgPp/wID\n        6f8CA+n/AgPp/wEC7/8GB7//OEJQ/0RQUv8wNzz/FBYU/zNLYv9HgsX/T4rN/06Jy/9Mhsf/U4/T/1mV\n        2v9cltf/XJbW/1iS0/9Ujc7/Uo3S/1qV2P9ak9H/WZLS/1uW2P9opej/Tn+z/ygtMP9DSFD/LjQ5/0l8\n        tv9fnuj/Xprf/2Cc3/9emt7/Y5/j/2aj6f9inuL/Y5/g/12Y2/9in+P/YJve/1uW1f9emt7/Y6Pr/2ml\n        6P9ys/f/Yp3V/yoyOf84PUL/Jikr/ztlk/9Vktb/UYrK/1CKzP9YmOD/Wpfb/1iU2v9SjM7/U47Q/1eQ\n        z/9WkdP/Uo3R/06L0f9Tkdf/TojL/0iExv9LiM3/OFVz/xcYFf8pLzP/Nz5F/zI5Q/8xN0j/MTdI/zA2\n        R/8xOEj/LzZH/ysxQv8sMkP/LTRD/y00Ov8yOUD/Jiwv/xEUFP8pLzX/KC47/yguQP8nLT//Jiw+/yYs\n        Pv8mLD7/JSs9/yQqPP8jKjz/Iyg6/yEnLv8uNz//Jy41/w0RE/8hJy7/ICcu/yIrNJkmLjhgIikx9Ccu\n        NP8QExb/HSIo/0VSWv9IVXf/EBLY/wMD6v8EBOj/BATo/wQE6P8EBej/BAXo/wQF6P8CA+7/FBav/1Vj\n        Z/8iKCz/Fhkb/z5KRf8rMn3/AwTt/wID6f8CA+n/AgPp/wID6f8CA+n/AgPs/wID4P8rMlj/RVJR/zhA\n        Rf8WGRr/JjA2/0N3sv9Mh8n/T4jJ/02GyP9Qi8//YJzg/16Y2v9cltX/WpLS/1qU1f9SjdD/XJfb/1+b\n        2/9emNn/XJLP/1qJuv8/YIH/LDE2/0FHT/8tMzj/OFZ3/0VqlP9Ga5P/RmqS/0RokP9HbJT/Rm2X/0px\n        mv9IbZT/RGiQ/0dumP9Lcpr/RGiO/0Jnjv9HbJT/THOd/1R7o/9Hao3/KjE3/zk+Rf8qLjH/Lkpl/0Rv\n        n/9Mf7j/U43N/1ya4v9koef/VZDU/1GKyv9TjtL/VY/R/1aQ0v9Pis7/SYXK/0WAw/9GgcT/SYXJ/0Z/\n        v/8tPUz/GRsa/zI5Pv81PEL/MTdD/y81Rv8vNUX/LjRE/zA2Rv8vNkb/LTND/ywyRP8tM0H/LTQ6/zM6\n        QP8gJSf/FBcZ/ywzOf8pMD7/KS9B/ycuP/8nLT//Jy0//yYtPv8lLD3/JCo8/yMpPP8jKTj/Iigu/zI7\n        Rf8iKS//DhAT/yMqMP8gJy76ICkydiYvOEEjKjLpJiwz/xIWGf8WGRz/Qk5Y/1BeZ/8aHsj/AgLs/wQE\n        5/8EBOj/BAXo/wQF6P8EBej/BAXo/wME7f8ICsH/Ul51/zA4Ov8MDg//PEZE/zI8aP8GB+D/AQLr/wID\n        6f8CA+n/AgPp/wID6f8CA+r/AADq/xsggP9GUk3/QUtQ/x0iJP8cICH/PGSQ/0+Kzf9SjdH/UInM/1WP\n        0/9jn+L/ZJ/h/2Ca3f9bldb/UovK/1SO0v9YktT/THmp/ztVc/80QU3/Nj5D/zxDSP9ASE3/QktR/z1D\n        S/83PEP/OD1C/ztARf88QEb/O0BG/zpARf87QEX/PEJH/z1CSP89Qkj/PUJJ/z5ESv9ARkz/PkJJ/zo/\n        Rf84PUL/OD1D/zc9Qv83PEL/Rk5W/0VOUv8/R0v/OkJF/zVBSf83UWn/T32w/2im6v9Wktf/T4jK/1SN\n        0f9dmNj/YJvc/1aR1P9Uj9P/UozR/0mEx/9Jhcr/Pmue/yIpLP8aHR//Nz1E/zI3Pv8vNUP/MDZG/zE3\n        R/8wNkb/MDZG/y81Rf8tM0T/LDJD/ywyPv8sMjj/NDtB/xYaGv8YHB7/LTU8/ykvP/8oLkD/KC5A/yct\n        Pv8mLD7/Jy0+/yYsPv8lKz3/JCo9/yMpNv8jKjD/NkFL/xwhJv8PEhb/JCsy/yAoMPEgKTJVLDQ+ISYt\n        NtQmLTT/GR0h/xIVGP83QEn/UV5i/yYssv8CAuz/BATn/wQE6P8EBej/BAXo/wQF6P8EBej/BAXr/wQF\n        1f9ET3z/QUxL/wsMDf80PT//OkZT/w8TyP8BAu7/AgPp/wID6f8CA+n/AgPp/wID6f8BAfD/DhCr/z5K\n        Sf9FUFT/LDM3/xUXFv8wRlv/UIrN/1WR1v9Wjs7/WJHU/2Od3v9moN//Ypvb/2Ca2/9Vj9L/THuy/zdO\n        Z/8yOkD/PEJD/0RLTv9JUVf/TFNa/01UXP9TW2X/PEJK/ywwMv8uMDP/LzI0/zAyNf8xMzb/MTU3/zE0\n        N/8xMzb/MTM2/zE1N/8yNTj/MTQ3/zI1OP8xNDf/MDI0/y4xM/8tMTL/LC8x/zQ5Pv9RWmX/TVNc/01T\n        W/9PVl7/TVRa/0lPUf8+Rkn/QFdr/0h1qP9TjMz/Wpje/16b3v9ZktP/VY3N/1ONzv9alNX/TYXG/0mF\n        yv82U3L/GBoZ/yctMf84PkT/MTdA/zA2Rv8xN0f/MTdH/zE3R/8yOEn/MjhI/zA2R/8uNEX/LTM8/y40\n        Ov8zOz//EhQV/x8kJv8sMjz/KS9A/ykvQP8oL0D/KC9A/yctP/8mLD7/JSs9/yQqPf8kKj3/Iyk0/yYu\n        NP83Qkv/Fhoe/xUZHf8kKzL/ICgw5SMsNDItNUAOJzA5tCgwNv8eJCn/DxMV/y41Pf9QXWH/NT6W/wUF\n        6/8EBOf/BAXo/wQF6P8EBej/BAXo/wQF6P8EBej/AgLp/ywzhf9SX2D/Cw4O/ykxNP9BTkf/GiCo/wEB\n        7/8CA+n/AgPp/wID6f8CA+n/AgPp/wID7P8DBNX/LjVW/0hUUv87Q0j/Fhka/yYwN/9Mfrf/VpLY/1aP\n        0P9cl9r/bqjo/2eh3/9koOX/VpDR/zpZe/8wOUD/PEFD/0lRVv9MVFz/S1Jc/0pPWv9JT1r/SE5Y/1NZ\n        Zf8uNDn/GCcz/x0uPf8cLj7/HS4//xssO/8bKzv/Hi08/x0tPP8eLT3/HS4//x0tPP8cKzn/HCw7/xsr\n        Ov8cLDz/HCw8/xwsO/8aKjj/Jiww/05VXv9LUVv/SU5Z/0lPWf9JT1r/TVJc/05VXP9JT1L/OUJH/zdS\n        bv9Ti8r/ZKLo/1yV1/9clNT/WJLU/2Kf4/9Ujc//SH25/ys4RP8XGRj/Mzk//zc+RP8zOUX/MjhI/zE3\n        R/8xNkb/MTdG/zE3R/8yOEj/MTdH/y81RP8tMzv/MDY9/y41OP8PERL/Jisv/ywxPv8qMEH/KS9A/ykv\n        QP8oLkD/Jy0//ycuP/8mLD7/JCo9/yQqPP8kKjP/KzQ7/zQ+R/8SFRj/Gh4i/yYtNP8gKTLIJS84Fisz\n        PwMoMTmLKTA3/yMoLv8PEhX/KC41/09cYP9CToD/Bwjl/wME6P8EBef/BAXo/wQF6P8EBej/BAXo/wQF\n        5/8CA+z/GR2n/11qcP8TGBn/GyEi/0FNSP8sNHj/AwTr/wIC6v8CA+n/AgPp/wID6f8CA+n/AgPp/wEB\n        6/8ZHoH/R1NN/0ZPVP8mKy//GBsZ/zxdfv9TjtH/UYrN/1uW2/9rpub/a6js/1eLyP81SV//Mzg5/0RK\n        T/9LUlv/SlBa/0lPWf9JT1n/SU9Z/0lPWf9JT1n/UVhg/ys1Pv9DdKv/U43O/1qW1v9emNj/VI3L/12X\n        1f9oot7/YpvX/16W1f9fmdn/XZXS/1ePy/9Xjs3/VIzJ/1KKyP9Ricf/UorJ/0uAu/8nM0H/S1BX/01U\n        Xv9ITlj/SU9Z/0lPWf9JT1n/SU9Z/0tRXP9MU1r/PkRG/zVHWP9Sgrn/Z6Xt/2mo7/9cltf/X5na/1iU\n        2P8/Y4v/HSAg/yEkJ/86QEf/NTtD/zQ5SP80Okn/MTdH/zI3R/8xN0f/MjdH/zE2Rv8xN0j/MTdE/y81\n        O/80PEL/JCos/xARE/8rMTb/KzA//ysxQv8qMEH/KTBB/yguQP8nLT//Jy0+/yYtPv8lKz3/JCo7/yQq\n        Mf8yO0T/LjY//w8RE/8eJCj/Ji01/yIrM6QlLzcIKTE6ACoyO1wlLTT4Ji0y/xIVGP8hJiz/SlZe/01a\n        dP8RFNL/AgLr/wQF5/8EBej/BAXo/wQF6P8EBej/BAXn/wQE7P8JCcb/UVxy/y84OP8OEBH/PUdH/zlD\n        W/8LDdX/AQHt/wID6f8CA+n/AgPp/wID6f8CA+n/AQLu/wgJv/85Q0//SlZY/zpCR/8UFhb/KjU//0t/\n        uf9Risr/V5DR/3Ku7/9djcD/MT9M/zxBQ/9HTlX/SlBa/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0tR\n        W/9KT1T/JzZF/1eMx/9lndr/ZJ3b/2ad2/9ooeD/cq7v/3+69/91ruz/cKrp/3Gq6P9qot//aaHe/2if\n        3P9mntz/ZZza/2Sb2P9knNn/XpXT/yk8UP9ARUf/TlVe/0hOWP9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9OVF3/RUtO/zQ/SP9QfrD/aqvw/1+Y2v9Yk9X/TYXE/y4+T/8VFhX/MDU7/zc8Q/8zOEL/MzlI/zQ6\n        Sf8zOUj/MzlJ/zI4R/8xN0f/MjhI/zI4SP8yOEL/Mjg+/zc/RP8ZHB3/GR0e/y40PP8pLz//KjBA/ysx\n        Qv8qMEH/KC4//ygtP/8nLT7/Jiw+/yUrPv8lKzr/JSsy/zdBSv8oLjT/EBMV/yQqMf8jKjL+JC43dSAq\n        NQAqMzwAKzQ9MyYtNeMqMTj/FRgb/xcbHv9ETlj/V2Ro/yEmu/8BAe3/BAXn/wQF5/8EBef/BAXo/wQF\n        6P8FBej/BQXq/wMC3f9ASYr/SFRS/wcICf8xOTz/QU1I/xwhqP8AAe//AgPp/wID6f8CA+n/AgPp/wID\n        6f8CA+r/AQHn/yAkdP9KVVH/RU5T/yUpLf8WGBf/OVh4/1KLy/9YkdH/WYe6/zhDTf8/REb/TVRc/0pQ\n        Wv9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/TlRe/zo9P/8vSWX/Ypvc/22k4v9jm9j/YpnU/2Sb\n        1/9mndr/erTx/3iz7/9zrev/bKTi/2ae2/9on9z/ZZzY/2Sc2P9lndn/Y5rZ/2Oa1v9kndz/OVl8/zA0\n        Nv9QV1//SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9LUVv/SE9T/zM+Rv9LeKr/XJfZ/1qV\n        2P9DaZP/HSEh/x8jJf81O0H/Mzg//zQ5R/81Okr/NDlJ/zU7Sv80Okr/NTtK/zU7Sv8yOEj/MTdG/zE3\n        Pv8yOD//NDtA/w8REv8gJij/LjQ//yswQf8rMUH/KzFB/ykvQP8oL0D/KC4//yctPv8mLD3/JSo9/yUq\n        Nv8oLjX/PEZQ/xsgJP8SFRn/KC83/yQsNPEmLzlIJS84ACs0PQAsNT4SKDA5viowOP8eIib/ERQX/zY9\n        Rv9XZGf/Nz+Z/wME6f8DBOj/BAXn/wQF5/8EBef/BQXo/wUF6P8FBef/AgLt/x4hnf9aZ2r/EBMU/x4j\n        Jf9DTkn/Lzd0/wQF6P8BAur/AgPp/wID6f8CA+n/AgPp/wID6P8BAu//CQu2/z1FT/9NWFn/PUVK/xYX\n        GP8jLDP/UIG6/01/uf8uO0r/RElL/05VXf9KT1r/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9NU1v/KjA1/0Vwof9ooeH/aKDe/2Sa2f9km9b/Zp3a/2ig3P9vqen/b6np/2uk4/9on9z/aaDc/3Or\n        5/9zq+f/a6Pg/2ee3P9lndv/Y5rV/2ig3v9Rgbf/Iy01/01SWP9LUVv/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9MU13/R0xQ/y86Q/9JeK7/VYzL/ys4RP8WFxb/Mzg+/zg9Q/80OEL/NzxM/zc9\n        TP82O0v/NjxL/zY7S/81O0v/NTtK/zM5SP8zOUX/Mjg+/zc+Rf8nLS//DxER/ysyNv8vNEH/LTNE/ywx\n        Qv8rMUH/KS9A/yguP/8nLT7/KC0//yYsPf8lKTz/JCky/y00PP85Q0z/FBca/xoeI/8oMDf/JCw11Ccv\n        OR8mLjgALTU8ADY+QQIpMTuIKTA4/yMpL/8QExb/KC40/1NgZf9OWYH/Cgzg/wME6f8EBef/BAXn/wQF\n        5/8FBef/BQXo/wUF5/8EBOz/CQrM/1VgeP8sMjL/DxIS/z1HR/8+SU//ERTG/wAB7v8CA+j/AgPp/wID\n        6f8CA+n/AgPo/wID6v8BAej/HyN3/05YUv9JU1j/KzA0/xMUE/85Umv/MUlk/zk+QP9PVl7/Sk9a/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/S1Fb/0RIS/8oPVL/XpXR/22m5v9pouL/ZZzZ/2ac\n        2P9so+D/cajl/2mh3v9nntz/aqHe/3at6f9xqOX/eLHt/3Wt6f9so9//aqHe/2yk4P9ontv/aqHd/2ae\n        3P8uSGT/Nzo7/09WX/9JTln/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9MUlv/RUpM/zBE\n        Wf83VXX/FxkY/ycsLv8+RUv/Oj9H/zc9S/84P07/OD5N/zg+Tf82PEv/NTpK/zU6Sv81O0r/MzlJ/zU7\n        RP80OkD/OEBG/xgcHf8WGRr/MTg//y81Rf8uNET/LDJD/ysxQv8qMEH/KjBB/ykvP/8pLT//Jis9/yUr\n        Ov8lKjD/Nj9I/y41PP8PEhX/ISYr/ykwOP8lLTajKTE6CCcvOAAoMDgALDQ+ACw1Pk4qMTnyKC40/xQX\n        Gf8cICT/SVNb/1hkc/8bH8f/AQLs/wQF5/8EBef/BAXn/wUF5/8FBef/BQXn/wUF6f8BAeT/Nz2N/09b\n        WP8JCgv/LjY4/0ROSf8oL4j/AgPs/wID6f8CA+j/AgPp/wID6f8CA+j/AgPo/wEC7/8FBsP/OUBT/1Jc\n        W/9ETFL/HiIk/xoeH/82PUP/TFNa/0pQWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0hP\n        WP9OU1r/LTQ4/0ZxoP9poeD/Zp3a/2ac2v9poNz/Z5/c/2uh3f9xqeX/d7Lu/26m4/94sOv/hcD6/3qy\n        7f92run/canl/2ui3/9upOD/cqvo/2+n4/9to9//a6Lf/1OCtf8iKjH/SU5T/0tRW/9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWP9NU1z/PUVJ/xwhIv8bHh//O0FH/zxCSf86P0r/O0FQ/zk/\n        Tv85PU3/OT9O/zg+Tf83PUz/NjxL/zY8S/80Okj/Mzg//zQ7Qf8xODz/DhER/yQqLP8xN0L/LzVF/y40\n        RP8tM0P/LTND/ysxQf8qL0D/KS4//ygtPv8mKz3/Jyw4/ycsMv85Qkz/Iigs/xIVGP8oLjT/Ji01+igw\n        OWgmKzcAJzI5AAAAAAAtNkAALjhBHykyOs4uNTv/GR0g/xMWGf89Rk//W2hq/zQ7pf8CA+r/BAXn/wQF\n        5/8FBef/BQXn/wUF5/8FBef/BQXn/wMD7v8VF7D/XGhv/xoeHv8aHh//QkxM/z1HV/8PEdD/AQHu/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPp/wAB7f8UFpL/TVVR/1BaXf86QUb/Fxob/zs/RP9NVF7/SE9Y/0lP\n        WP9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9IT1j/TFNc/zxAQ/8xSmb/aqHg/2if2/9so9//a6Hd/26l\n        4f9vpeD/bKLc/22k3/9xqeb/baXi/3ew6/9+ufP/erLt/3+59P92rur/b6bj/2+m4v9qod7/a6Lf/3Cn\n        4/9yqOP/cKno/zRTdf8uMTP/TlVc/0hPWP9JT1j/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1j/SE9Y/0tS\n        XP8+RUr/Fxoa/zM5Pv8/RUz/O0BI/ztATv89QlH/PEJR/ztBUP87QVD/O0FQ/zpAT/84Pk3/NzxL/zY8\n        Rf80OT//OkJI/yImKf8QEhL/LTM4/y80Q/8wNUX/MDVF/y40RP8tMkP/LDFC/ykvQP8oLT7/KC4+/yYs\n        Pf8mKzP/LTM6/zxFT/8XGh3/Fxkd/y00PP8lLTXgKDE5MigwOQAAAAAAAAAAAC02PgAxOkIFKzM7lCwz\n        O/8mKjD/ERMW/yowNv9YY2r/UFqE/wsN4P8CA+j/BAXn/wUF5/8FBef/BQXn/wUF5/8FBuf/BQbq/wMD\n        3f9DS4X/QUpH/woLDf80PD//RE9L/yctkf8CAu3/AgLp/wID6P8CA+j/AgPo/wID6P8CA+j/AgPs/wEC\n        3v8nLGr/Vl9Z/05XXP8yOD3/GRwd/z9FTP9LUlz/SE9Y/0hPWP9JT1j/SU9Y/0lPWP9IT1j/SE5Y/0pQ\n        W/9JTVH/JzVC/1eJwP9vqOj/a6Hd/3218P9xqOT/a6Hd/2yi3f9so97/baTe/22j3v9uo9//cqrl/363\n        8v99tvH/eLHu/3Ss5/9zquf/cqrn/2yi3/9rodz/dazo/3y18f9tpOP/XZLO/yQ2SP88P0D/TVRe/0hO\n        WP9IT1j/SU9Y/0hPWP9JT1j/SU9Y/0hPWP9KUVr/REtT/xwgIv8rMDL/QEZN/zxCSf87QU3/PUNR/z5E\n        U/89Q1L/PEJR/zxCUP86QE//OT9O/zk/Tv85P0z/Nz1E/zc9RP83PkL/EhQU/x0iI/8yOEH/MDVF/zA1\n        Rf8wNUX/LzVF/y0zQ/8sMkL/KzFB/yovQP8oLj//Jy07/yYsMv84QEn/MTg//xETFf8hJiv/KjI6/ycv\n        OK4pMzwMKTI7AAAAAAAAAAAALTQ+ACo0OwArNDxPKjI78ywxOP8WGBv/HCAk/0tUXf9daXH/Iya+/wEC\n        6/8FBeb/BQXn/wUF5/8FBef/BQbn/wUG5/8FBuf/AwPs/xodrf9eaW3/FBcY/xsfIv9CTEz/QElW/xIU\n        yf8AAe7/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AQLu/wYIwv86QVv/WmRh/0xWW/8qMDP/GRwe/0RK\n        Uf9KUVv/SE9Y/0hPWP9IT1j/SE9Y/0hOWP9JUFr/S1BW/yoxOP9GcJ//babk/2qg3P90q+X/iML6/3au\n        7P9qoNz/baPe/26k3/9upN7/baPe/22j3v9wpuP/eLDs/3628f9wp+P/baTf/3Go4v9zquf/b6bi/3au\n        6f99tvH/dq7s/2ie2/9ro+P/THuv/yAqMv9CRkr/TFNe/0hOWP9IT1j/SE9Y/0hPWP9IT1j/SlBa/0lQ\n        WP8iJin/KCwv/0VLUv9BR07/PEJN/z1DUf8+RFP/PURS/zxCUf87QVD/O0FQ/zpAT/87QE//Oj9O/zk/\n        R/83PUP/OkJI/yQpKv8PERH/LTQ5/zI3Rf8xNkb/MDZG/zA1Rf8vNUX/LjND/ywyQv8rMUH/KzBB/ykv\n        QP8oLjn/KzI3/z9IUv8gJSr/EhUX/yguNf8nLzj5Ji84aCQqNQAnMDkAAAAAAAAAAAAAAAAALDQ+AC42\n        PxkqMjrILzc9/x4iJv8SFRf/OUBI/15pbP9ASJv/BAXp/wQE5/8FBef/BQXn/wUG5/8FBuf/BQbn/wUG\n        5/8FBur/BQXX/0pShP89REL/CQsM/zU8QP9HUkz/MDeC/wQF6f8CAun/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AAHu/w0Op/9HTlX/XWZl/0xTWP8mKy7/HiIj/0dNVf9KUFv/SE5Y/0hOWP9ITlj/SVBa/0xR\n        V/8sMDP/O1+F/2yl4v9xqOP/cqjk/3av7P9+t/P/dq/r/3Ko5P9vpeD/cafi/3Cm4f9vpeD/dazn/3y0\n        7/96su//e7Tv/3Co5P9so97/bqXg/3Sr6P93run/grz2/4K79f94sOv/ap/c/26l4/94tPT/QWmV/x8l\n        Kf9FSU3/TFNd/0hOWP9ITlj/SE9Y/0lQWv9IT1j/Jios/yIlJ/9FTFL/SE5V/0JIUv9BR1X/QEZU/0BG\n        VP8+RFL/PUJR/zxBUP87QE//Oj9O/zpAUP86P0v/OT5E/zlARv82PkL/ERMT/x0gIf82PEb/NDlJ/zI3\n        Rv8wNUX/LzVE/y80RP8uM0P/LDJC/ysxQP8qL0D/KS8//yguNf80PEP/O0NM/xMVGP8aHiL/LTQ7/yUt\n        NdkoMDoqJzA5AAAAAAAAAAAAAAAAAAAAAAAuNj4AOUJFASw0PYAsNDv+KzA1/xIUF/8nLDH/V2Bo/1xn\n        ff8XGtT/AgLq/wUF5v8FBef/BQbn/wUG5/8FBuf/BQbn/wUG5v8DA+v/Gh2r/1xmav8UFxf/HCAi/0ZO\n        Uf9GT1H/HCCz/wEB7/8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+n/AAHr/xYXlP9TWVr/Ymtq/01W\n        Wv8nLC7/ICMl/0VLUv9LUVv/SE5Y/0pQWv9LT1T/Ky8y/zdYfP9yquf/c6nl/3mw6v98s+//c6vo/3at\n        6P97su3/frfx/3Ko4/9yqOP/cqnk/3iv6v+Kxff/i8b8/3+49P94sOr/d67p/3Ss5/92rOj/fbXv/3Kp\n        5f90rOj/f7fz/3uz7/9wpuX/dq7r/3ev7f90rez/PGGK/x4jKf9AREX/TFJb/0hOWP9KUFr/SU9Y/yUq\n        LP8hJCb/QEVL/0NKUP9CSFD/REpX/0RKWP9CSFb/QEVU/z5EUv89QlH/PEJQ/zxCUP87QVD/OT9N/zk/\n        R/83PEL/O0JI/yQpKv8NEBD/LjQ4/zY7Sf8zOUn/MjdH/zA1Rf8vNUT/LjND/y0yQv8tMkL/LDFC/yow\n        Qf8pLjz/Ki81/z9HUf8sMzn/EBMV/yUqL/8qMTn/Jy84mCszPQYpMTsAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAtNT4ALTU+Ny01PeQwNj3/GBwf/xcaHf9FTFb/ZXBy/z1EqP8EBOv/BQXm/wUF5v8FBuf/BQbn/wUG\n        5/8FBuf/BQbn/wUG6f8DBN3/QUiM/0NLR/8ICQr/Mzk8/0lST/8/SGn/Dg/Y/wEB7P8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+r/AQHm/xsdif9YX13/Z29v/1FZXv8qLzH/HSAh/0JHTv9OVV7/SExS/y41\n        Pf87X4b/cajl/3iv6/91rOj/d6/r/3iw7f9wpuH/cKfh/3at5v+CuvT/ebHs/3Op4/97suv/jcj8/5XR\n        /f+Gwfj/gLn0/3qx7f+BufX/erHr/3Go4/+IxPb/h8Lz/3eu6v+BufH/gbnz/3Cm4/9xqeT/dq/t/322\n        8/91ru7/P2qa/yEuOv85PUH/T1Ve/0ZMVP8lKCr/Jyos/0FGTP9FS1L/QUZO/0FGU/9DSFb/RElX/0NJ\n        V/9CR1b/P0VT/z1CUP87QE7/O0BP/ztAT/87QEr/OT5E/zk/Rf8zOj3/EBMS/x8kJP81O0T/MzlI/zM5\n        Sf8zOEf/MTZG/zA1RP8uM0P/LDFB/ywxQf8tMkP/LDFB/yswOf8zOUH/Q0xV/xsfIv8WGRz/LTM6/ykx\n        OfAoMTlKJi84ADE5PwAAAAAAAAAAAAAAAAAAAAAAAAAAAC02PwAuN0EJLTU+pTI5Qf8mKzD/EhMW/yww\n        Nv9aZGr/W2aC/xUX1v8DA+n/BQXm/wUG5v8FBuf/BQbn/wUG5/8FBuf/Bgbm/wQE7P8SFLz/W2V1/x0h\n        H/8UFxj/QkpP/0tVTv8yOIv/BATq/wEC6v8CA+j/AgPo/wID6P8CA+j/AgPo/wID5/8CA+v/AAHi/xwe\n        hf9bYWH/a3Ny/1NcYP8yNzr/HB4f/zc7PP8xOUH/TXqs/3Ot7P93run/c6nj/3Op5P95sOv/eK7q/3Ko\n        4/93rur/fLLt/4W+9f+FvfP/dKrk/32z7f+Iwfn/hb/4/3yz8P+NyPj/l9L7/4O88/92rej/cqjh/3u0\n        7P+Pzfz/iML5/4S89P+Gv/f/erHt/3Co5v9vqen/eLDr/3qx7v99uvf/XpLE/yo3Qv81ODn/IiUn/y0w\n        NP9ITVT/RUpR/0JHT/9FS1j/RktZ/0VLWf9FS1n/RUtZ/0RJV/9BRlT/P0RT/ztAT/85Pk3/OT9L/zo/\n        Rv85P0X/O0NI/xwgIf8QExP/Mjc9/zY7Sf81Okr/NDpK/zI4R/8yN0b/MDZF/y80Q/8tM0P/LDJC/ysw\n        Qf8sMT//LTI4/0FJU/8zOUD/ERMW/yMnLP8vNj//KDA5uCozPRIqMjwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAALjI9AC43QAAuNj9OLjc/8TM6QP8YGh3/Fxod/0hQWv9nc3X/OD6s/wMD6f8FBeb/BQbm/wUG\n        5v8FBub/BQbn/wYG5/8GBuf/Bgbo/wMC5v8uMpr/TlZV/wsMDP8oLS//R1BS/01VVf8kKK7/AQLu/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID5/8CA+v/AQHl/xkakP9ZX2L/cnl1/15mav89Qkb/Ghwe/xwe\n        IP9HXHL/bZrJ/3iw7P90rOj/dKrk/3iv6f93rur/dq7q/3qx6/95r+r/grry/4a/9v93ref/e7Ls/321\n        7/9/t/L/g7r2/4bB+P+Lxvj/hLzz/3iu6f91q+X/fLPu/4nC+/+Iwvr/gLfy/3628f92rej/c6rm/3at\n        7P9/uPP/grvz/3an1f9Vb4X/ICQn/xkbGv81ODz/S1BX/0lPVv9FSlL/RUpX/0VLWf9HTlz/R05c/0ZM\n        Wv9GTFr/RUpY/0JIVv9BR1X/QEZU/z1CT/88QUn/Oj9G/z1DSv8rMTP/DA8O/yYrLf83PUj/NTtL/zU7\n        Sv81Okn/MjdH/zA2Rv8wNUX/LzRE/y4zQ/8tMkL/KzBB/ywxOv8zOUH/RU5X/xwgI/8VFxr/LjU7/ysy\n        O/gpMTtjKDA7ACoyOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDhAADA4QRAuNj+0MzpC/yYr\n        L/8TFRf/MTY9/2Rvdv9dZ4b/FBbX/wID6f8FBub/BQbm/wUG5v8FBub/Bgbn/wYG5/8GBub/BQXr/wYG\n        1v9KUIP/Oj85/woMDP82PUH/TFRT/01UYf8ZG8T/AAHu/wID5/8CA+j/AgPo/wID6P8CA+j/AgPo/wID\n        5/8CA+r/AAHo/xITof9PVGX/eX94/2pxc/9KUVX/KCwu/xYWE/8sMjb/Vm+J/26czv93r+v/eLDr/3u0\n        8P96su7/ebDs/3iv6/9+tvH/grnz/3qx6v95r+n/ea/q/3mv6v+Hv/b/jcb6/3yy7f94run/d63o/3et\n        5/97su7/grv0/3217v+CufP/f7fx/3at6f9zrOn/da/u/3Gi1f9efJf/MDlA/xQUEv8lKCj/REpN/0lP\n        Vv9LUFf/RUlS/0NIVv9ESVf/RUtY/0VLWf9GTFr/Rkxa/0VKWP9DSFf/Q0lX/0JIV/9ARVP/P0RN/z1D\n        SP89REv/OD9D/xEUFP8aHR7/OD1G/zg9TP84PUz/NjtK/zU6Sf8zN0f/MTZF/zA1RP8vNEP/LjND/y0y\n        Qv8sMT7/LDI4/0JLVP84PkX/ExUX/yEmKv8xOED/KjE7xywzPBwsMzwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAA0PEQAKTI+ADA4QlgvNz/zMzlA/xgbHv8bHiH/T1dh/214ev9DSqn/BAXn/wQF\n        5/8FBub/BQbm/wUG5v8FBub/Bgbm/wYG5v8GBub/BAPs/xQVuf9ZYW7/HyIe/xYZGf9ASE3/UFdU/0ZM\n        c/8QEdb/AAHt/wID5/8CA+f/AgPo/wID6P8CA+j/AgPo/wID5/8CA+n/AAHs/woLuP8+Qm7/dntz/3qB\n        gP9dZWn/QEZJ/yEkJP8cHRv/NTtB/1JpgP9slsP/dqvm/4C59v98tfD/e7Ls/3617/99tO3/fLPt/3qx\n        6v94r+n/f7bw/4vF+f+Pyfv/gLfw/4C48P+BuO//d6zn/3as5/93ref/ebDr/3y08P99tfL/dKrl/2mV\n        xP9Ubon/N0BI/xwdG/8aHBv/PEFD/2hvcv9yeHv/TFJX/0hNVP9KT1f/R0xa/0dNW/9HTFr/RUpY/0VL\n        Wf9FS1n/RElX/0FGVP9CR1X/QUdV/0BFT/9ARUv/PURK/z5GS/8cISL/DxIS/zE3PP84PUv/NzxL/zg+\n        TP83PEv/NTpJ/zM4SP8yOEf/MTdG/zA1RP8vNET/LzRD/y4zO/82PET/R1Ba/x4iJv8VFxr/LjQ7/ywz\n        O/opMTpvS3dpACozOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxOEEAMjlCEy82\n        P7M1PEX/KCwx/xQWGP8uMzn/Y211/2dzg/8dIM3/AgLq/wUG5v8FBub/BQbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBuf/AgLn/ygrov9SWVj/DxEP/yEmJ/9FTVH/U1tW/0ZMfv8PEdn/AAHs/wID5/8CA+f/AgPn/wID\n        6P8CA+j/AgPn/wID5/8CA+j/AQLt/wMD0v8jJIf/ZGlu/4aMhP96gYL/W2Nm/zc9QP8dIB//HB0b/y0v\n        MP9NW2r/ZIOi/3Ofzv9+s+n/g7r0/4S++P+Cu/b/f7fy/3207/+AuPL/gLjy/4C48f97su3/icP4/4/K\n        +/99tfH/e7Tx/3y07/9+s+v/c6DR/2F/oP9MXGz/LTAz/x0eHP8dHh7/OT5A/2Joa/9/hYP/eX97/3h+\n        ff9mbG//RUpR/0tRWP9MUlz/SlBd/0ZLWf9FS1j/RkxZ/0VKWP9DSFb/QkdV/0FHVf9CSFL/QkdO/0BF\n        TP8/R03/Jist/wsODf8pLjH/O0FM/zc8S/83O0r/NzxL/zc8S/82O0r/NDlI/zI3Rv8xN0b/MDVE/zA1\n        RP8wNUH/MTc+/0hQW/8yOT//ERMW/yImKv8xNz//KTA5yCoyOh8qMjoAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADU8QwAnMTwALjdATzA4Qe03PUT/HB8j/xgaHf9JUFn/b3p8/1FZ\n        oP8ICeX/BAXn/wUG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8FBen/BATf/zk+kP9GTEf/Cw0M/y0y\n        NP9IT1X/WWBZ/0VKhv8NDt7/AAHs/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AQLs/wAA\n        5v8NDbH/PUB5/3h9ev+Ok47/fYSF/15laf9ARkn/KSst/xwcG/8lJiT/Nzo8/0dSXP9ieI//dpay/3Sc\n        wP93o9L/e6zh/4C06/+EuvD/h73w/3+06/+EuOv/hrba/3Gbwv9rjK//ZX2W/0tXY/82Ojz/IyMi/xgZ\n        F/8lKCj/P0RH/2Vrbf+Eion/hoyE/1tfcP8eIIz/PUCF/32DfP9XXmL/RUtR/0pPVv9ITVn/SE5c/0ZL\n        WP9FSlj/RUpY/0NIVv9CR1X/QUdR/0JITv9ARk3/P0ZN/y4zNv8NDw//ISQm/zxCTP88QVD/OD1M/zc8\n        Sv82O0r/NjtJ/zU7Sf80OUj/NDlH/zE2Rv8wNET/MDVD/zA1PP88Qkv/Rk9X/xkcH/8XGRz/Mjg//y41\n        PvcsMzxnRAAAACw1PQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA3\n        QAAwOEELLzY/oTY9Rf8vNDr/FRca/ygtMf9hanP/cnyE/zM4v/8CA+n/BQbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8FBer/CAjT/0dMgv82OzT/CwwM/zU7Pf9NVVn/XWNd/0hNi/8PEdr/AAHs/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPp/wEB7v8BAdv/FBWd/0dKdv9/g4D/mJ2W/42S\n        kv9yeXv/Vlxf/zxCRf8mKSr/IyQj/yEhH/8jIh//MTM0/z5CRf9GTFL/SVBX/0xUW/9OVlv/SVBX/0lR\n        V/8+Q0f/MjQ2/yMiIP8eHRv/ISIh/yUoKP89QkT/WV9h/3p/gf+SlpP/jpOL/2dreP8sLoX/Bge//wAA\n        7P8LDMn/YGR4/3h+ev9NU1n/SE1U/0tQWf9MUV7/SU5c/0dNWv9FSlj/Q0hW/0NIU/9ESVD/P0RK/z5F\n        TP8yODz/DhES/xkdHf88QUn/PEBP/zo/Tv86P07/Oj9O/zg8S/82Okn/NDlI/zQ4SP8yN0b/MjZG/zA1\n        Rf8wND7/MzlA/0tTXf8uMzj/ExUX/ycrMP8xOED/KjI7uS01PRYsNDwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzlCAC83QQAwOEE6MDdA4Dk/R/8hJCj/Fhkb/0BG\n        Tf9ven//anST/xkc2P8DA+j/Bgbl/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8EBOv/Dg/I/0tS\n        d/8rLyj/DxAQ/zpAQ/9NVlr/YWhh/1BVif8SE9r/AAHt/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID6f8AAez/AQLW/xUWpP9ERn3/eHuD/5uflf+hp6D/kpiW/4CGiP9nbXD/Ullb/0dN\n        UP85PD7/LC8v/ycpKf8hIyL/GhsZ/xobGv8hIiH/JScm/ysuL/86PT7/R0xP/1JXWv9qcHL/hoyN/5ec\n        mf+eopr/io2I/19ifP8qLIj/CQm//wAA5v8BAuz/AgPo/wAA6/8iI6b/eH14/2hvcf9JTlX/TVJZ/0tQ\n        Wv9JTl3/SU5c/0VKWP9FSlX/RUpR/0JHT/9AR03/Njw+/xIUFf8WGRr/OT5F/z5CUf87P07/OT5N/zk9\n        TP84PUz/OT5M/zg9S/81Okn/NTlI/zI2Rf8wNUX/MDVB/zE3PP9FTVb/Q0pR/xgaHf8bHyL/NDtC/y00\n        POwsMztOLDU9ACwxOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAMDY/ADE4QAQuNT2ANTxE/DY7Qv8ZGx7/HyIl/1dfaf95hIj/VFyp/wkK5f8FBeb/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8DBOz/EhPD/1BWdP8rLyj/DhAR/zpBRP9OVlv/ZGtl/1ld\n        if8bHdH/AADs/wEC6P8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+r/AAHr/wEB\n        3f8KCrf/Ky2W/1JVf/9+gYr/naGY/6irof+rr6n/oqel/5idnP+NkpL/hoyM/4OIif+AhYb/foSF/4KH\n        iP+HjY3/jpST/5menP+lqqb/q6+n/6Clmv+PkpL/aWyB/zs9gv8XF6P/BATK/wAB5/8BAuz/AgPo/wID\n        5/8CA+f/AQLp/wID3v9ER4X/foR7/1dcYf9JT1b/S1FY/0dNWf9GS1n/R0xV/0hMVP9DSE7/P0ZN/zk/\n        Q/8VGBj/ExUV/zg8Q/9ARVL/PUJQ/ztATv87QE7/Oj9N/zk+TP84PUv/NzxL/zc8S/81Okn/MjdG/zA1\n        Q/8wNTz/PENL/09WYP8iJin/FRcZ/y40Of8yOUL+LDM9ljA4PgkuNj0AAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALzY/AC82Px8wNz/COUFJ/y0x\n        Nf8WFxr/LjI3/2hyfP96hYz/OT2+/wQE6P8FBeX/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgfm/wYH\n        5v8EA+r/Fhe8/1JXcP8lKCH/Dg8Q/zlAQv9NVVr/ZWtm/2dsf/8uL8H/BAXq/wAB6v8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPo/wEC7f8AAOf/AQHc/wkKuv8dHp//NziR/1NV\n        h/9ucIL/goSP/5eZm/+hpKX/o6eo/6eqqf+nqqn/o6an/56hov+OkZX/eHuI/2Fjgf9ISYz/KSuV/w8Q\n        p/8FBcz/AADi/wAB7P8BAur/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AQHs/w8Qxf9jZ3f/dXp3/0xS\n        WP9MUln/S1BY/0dMVf9HTFL/QkdO/0BHTP82PD//ExYW/xMVFP84PEH/QUZT/z1BUP88QU//PUJQ/zxB\n        T/86P03/ODxL/zc7Sv83PEv/NztK/zU6Sf80OEj/MTY//zU7Qv9OVmD/Mjc8/xMVF/8mKS3/OD9H/ywz\n        O9MtMzwsLDI8AEE8RgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAyOUEALzY+ADE4P08xOUHqPkRL/yIlKP8XGRv/Q0lQ/3R+hf90fpP/JinO/wIC\n        6f8GBuX/Bgbl/wYG5v8GBub/Bgbm/wYH5v8GB+b/Bwfm/wcH5v8EA+n/FBW//1BUd/8sLyj/DhAP/zU7\n        Pf9LU1n/Ymhl/3R5fP9HSq//DxDh/wAB6/8BAuf/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+n/AQLr/wAA7v8AAOX/AADX/wMD0/8ICcX/EBGt/xUWrf8WF6r/Fxij/xcZ\n        o/8WF6r/ExSs/wwNsv8GBs3/AQHT/wAA3P8AAOr/AAHu/wEC6v8CA+j/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AADq/yUnof93fHf/Ymlr/0VKUf9KT1b/SE5U/0JHTv9AR03/NDo8/xIV\n        FP8TFxb/OT1D/0NHVP8/RFH/PUJQ/ztATv88QU//PUJQ/ztATv86Pkz/NzxK/zU6SP80OUf/NDhI/zM4\n        Qv80OT//SlJc/0NJUf8XGRv/Gx0g/zc8Q/8xOEDzLTM7Yy4tMwEtMzsAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzOkIANDtDBzE4\n        QYc3Pkf7O0BH/xocH/8dICL/U1li/3yGif9sdJz/GBna/wID6P8GBuX/Bgbl/wYG5v8GB+b/Bgfm/wcH\n        5v8HB+b/Bwfm/wcI5v8EBev/FBbJ/1FWf/8uMin/DQ4N/zE1N/9KUlf/XGJk/3uAeP9obJn/JijQ/wMD\n        6v8AAen/AgPm/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID\n        5/8CA+n/AQLq/wEC6/8BAez/AAHs/wAB7P8AAez/AAHs/wAB7P8AAez/AQLr/wEC6/8CA+r/AgPp/wID\n        5/8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8BAur/AgPi/0hL\n        jP98gX3/VVpf/0VKUf9ESlH/Q0lP/zA1Nv8OEBD/Fxoa/zxBR/9DSFX/P0RS/z9EUv8/RFL/QEVT/z9E\n        Uv88QE//Oj9N/zs/Tv85Pkz/NjtJ/zQ4R/80OUX/NDlA/0dPV/9QV2H/ICMm/xUXGf8xNjv/NDpC/iwz\n        O5wtNj4NLTU9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1PEYANj1GHTQ7RLo+Rk7/MjY7/xYYG/8nKi7/YGhy/3+J\n        i/9bYaj/DQ3i/wQE5/8GBuX/Bgbl/wYH5v8GB+b/Bwfm/wcH5v8HB+b/Bwjl/wcI5f8FBev/EBHO/z9D\n        g/8+Qjr/EBIO/yYqK/9HTlL/VVxh/3V7df+AhI3/TlG1/xcY3v8AAer/AQHo/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8BAuf/AADq/wUG6P8sLs3/aGyT/3p+ff9ZXmT/RUtT/0JITP8pLS7/DA8O/x0g\n        If9BRUz/RUpX/0FGVP9ARFL/P0RS/z5DUf8/RFL/PkNQ/zxAT/87P07/Oj5N/zk+TP85PUz/NjpH/zM4\n        P/9AR0//VVxl/ysuMv8UFxj/LTE2/ztCSv8uND3MLTM8KS00PQAyKSwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY9\n        RwAyO0IANDxEOzU8RdlBR0//LDA0/xYYGv8xNTr/Z294/36IjP9LUbP/CAjk/wQE5/8GB+X/Bgfl/wYH\n        5f8HB+b/Bwfm/wcH5v8HCOb/Bwjl/wcI5f8FBur/CQnb/zc5m/9KTk3/FhkR/xodHf9ARkj/UFhe/2du\n        b/+IjYb/f4Of/0NGxf8QEeL/AADq/wAB6P8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8BAuf/AADp/wUG6P8nKNT/X2Ku/4OH\n        iv90eXb/UFZd/0RLUf8+Q0b/HCAg/wwODf8qLS//R0tU/0hNW/9GTFn/Q0dV/z9EUv89QU//PEFP/z9E\n        Uv89Qk//PEFO/ztATv86Pkz/OD1L/zg8Sv83PEP/PEJK/1RcZf80OT7/Fhga/yYpLP89REz/MjlC5jA3\n        QFA5PVIAMDc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU8RAA3PUUCNTxEYDc+R+1CSFD/Jikt/xca\n        HP88QUf/c3yE/4KLkf9HTLf/Bgfk/wQF5v8GB+X/Bgfl/wcH5f8HB+X/Bwfl/wcI5v8HCOb/Bwjl/wgI\n        5f8HB+n/BATj/yQlrv9IS2P/JSgf/w8QDv8wMzX/TVRZ/1hgZv92e3r/k5iS/4KGqv9ISsX/FBTg/wID\n        6f8AAOj/AQLn/wID5v8CA+b/AgPm/wID5/8CA+f/AgPm/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8CA+b/AgPm/wEC\n        5v8AAef/AADp/wgI5v8qK9b/ZWe2/4yPl/+Dh4D/YGVo/0pRWP9ES1D/MTU3/w8QEP8VFhf/OT1A/09V\n        XP9ITVr/RUpY/0VKWP9FSlj/QkZU/z5CUP8/Q1H/P0NR/z5CUP89QU//Oj5N/zk9TP85Pkz/OT1G/0BF\n        Tf9aYWv/QUZN/xYYGv8eICT/PENJ/zU8RfYxOEB2MzhCBTI4QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAADY9RQA4P0cINDtEgzlASPhARkz/ICMm/xocH/9JT1X/fISN/4aQlv9GS73/Bgfm/wUF\n        5v8HB+X/Bwfl/wcH5f8HCOX/Bwjl/wcI5f8HCOX/CAjl/wgI5f8ICOf/BATp/xITy/8/Qor/P0FA/xMU\n        Dv8eISH/QUdJ/1FZX/9fZmz/gIWC/5ygmP+Rk6//X2HI/y4v1v8LDOX/AQLo/wAA6P8BAef/AQLm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8CA+f/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AQLm/wAB5/8AAOj/BAXn/xUW4P9BQtD/dXe3/5aZn/+MkIj/aGxu/01T\n        Wv9HTVP/PkJF/x8iIv8NDgr/RUhG/6Cnr/9mbHX/SE1U/0lOV/9GS1j/RUpX/0RJV/9ESVf/QEVT/z5C\n        UP88QE7/PEBO/zxBT/87QE7/OT5M/zk+R/9ARk3/WmJs/0hOVv8aHR//Gx0g/zk+Rf83Pkb8LzY+mDM5\n        QRAyOEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU7RAA2PEUSMzlCnTtD\n        S/w+Q0n/HyEk/x0fIf9LUVj/foeP/42XoP9ITsf/Bgfk/wUF5v8HB+X/Bwfl/wcI5f8HCOX/Bwjl/wcI\n        5f8HCOX/CAjl/wgI5f8ICeX/Bgfq/wgJ4P8qK67/P0Fe/yQmHf8TFRD/KSws/0ZMUP9TW2L/XmZs/4GG\n        hP+hpZv/qKuv/4yOwv9XWdL/MTHc/w8P4/8DBOj/AADn/wAA5/8AAef/AQLn/wEC5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CAub/AQLm/wAB5/8AAOf/AADn/wEC6P8HCOf/Gxzh/z4/\n        1v9ucMT/lpmz/6Klov+OkYv/aG1w/05UXP9KUVf/RUtO/ysuL/8SFA//GxwU/yUmS/9MT57/w83Y/5+p\n        tP9MUlj/SE1U/0dLVv9GSlj/RUtX/0VKV/9CR1X/QUVT/z9DUf9ARFL/PkNR/zxBTv89Qkr/QkhP/1ph\n        a/9KUFf/Gx0g/xkbHv84PEL/PURN/zE3QbIxN0AdMThAADIVHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAQERGADM5QgA0OkMfMzlBsj9FTv46P0X/Gx0g/xwfIf9MUln/goqS/5Ca\n        of9PVML/CAjl/wUE5f8HB+X/Bwfl/wcI5f8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgJ5f8ICeX/Bwjn/wUG\n        6f8PD9L/LS+T/0JFUf8dHhT/ERIO/ywuLv9JT1H/VV1i/1piaP9zeHv/lpuW/7G0rP+ytLr/nJ7I/3d5\n        0f9QUdn/MzTf/xwd4v8MDeT/BQbm/wAB6P8AAOf/AADn/wAA5/8AAOf/AADn/wAA5/8AAOf/AADo/wIC\n        6P8HB+X/EhPj/yYn4v86O9z/YGHT/4mLyP+jpcD/rrGt/6Glnv+Ch4X/YWZr/05VXP9LUlf/RUtN/y8y\n        M/8WFxP/CgwE/yMlNP8nKI3/DQ3T/wcH2/9scbD/v8nN/3d/if9DSU//SU1V/0VJVv9CR1T/QkZU/0FF\n        U/9ARVP/PkNQ/z5CUP8+QlD/PEJK/0NJUP9eZ3D/U1lh/x8hJP8ZGh3/NTo//z1ETP8zOULEMzpCKzE7\n        QgA2OUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOUBGADI3\n        QQA1O0MrNTtDvkFIUP88QUf/HR4h/x0gI/9MUVn/gImR/5egpv9XXcX/Cgvj/wME5v8HCOX/Bwjl/wcI\n        5f8HCOX/Bwjl/wgI5f8ICOX/CAjl/wgJ5f8ICeX/CAnl/wgI6P8HB+j/FxjI/ycof/8lJzX/ICIX/xka\n        Ff8tLy7/Q0dJ/1RbX/9WXmT/YWhv/3R5fv+SlpT/rrGs/77AvP/AwsP/sLLO/6Ci1P+Rk9n/fH/X/3Fz\n        3P9qbOD/W13f/0xM3f9MTd7/WFne/2hq3v9zddf/goTX/5SW1v+kptD/t7rH/72/vf+ztrH/naCb/4KH\n        h/9mbHL/VFxj/1BYXv9OVFn/QUVI/ysuLP8UFhD/DA0F/w8PIf8OD2r/Cw3A/wcH6f8HB+j/BQXo/xkZ\n        xv+VnLL/rba+/1hdZf9DR03/RkpT/0BGU/9ARFL/PkJQ/z1CUP8+QlD/PUJP/z5CTP9FS1P/X2dx/1BW\n        Xf8hIyf/GBoc/zQ3PP89Q0z/MTc/0DE2PjohHzEANT1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOT9JADQ5QAA3PUYxNz1GxEdNVv89Qkj/HR8i/x4g\n        I/9KUFf/h5CY/56nrf9obsP/Fhjg/wID5v8HCOT/Bwjl/wcI5f8ICOX/CAjl/wgI5f8ICOX/CAjl/wgJ\n        5f8ICeX/CQnl/wkJ5f8HB+n/Bwfn/xESyf8yNJX/MTNK/xITEP8XGA//Jick/z5BQf9OUlT/V11h/1Zd\n        ZP9ZYGf/Y2tx/3R7gP+Kj5D/m5+c/6uuqP+3urH/v8G6/8PFwP/Fx8T/xsjH/8XHx//Fx8X/wcW//7q9\n        tv+ztq7/pqqm/5OXl/+Ahon/bHJ4/1xiaf9TW2L/TlVb/1JYW/9KT1H/OTw9/yEiIP8QEQn/DQ8K/xAR\n        LP8QEHT/CwzC/wgJ6v8HCOr/CAjl/wgI5f8ICOX/AwPl/zo8sf+utrv/jZWf/0RJT/9ESE7/Q0hS/0JH\n        Vf8/RFH/PUFP/z1BTf8+Qkr/RktT/2JqdP9PVFz/HyEk/xocHv81OT7/QEdO/zE3P9QxNz9DLjs8ADA4\n        PgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAOT9IADQ7QgA3PkUyNz5GxEZMVf9ARkz/ISMm/x4gI/9MUlj/ho+Y/6Cqrf9/h77/JinZ/wMD\n        5v8GB+X/Bwjk/wgI5f8ICOX/CAjl/wgI5f8ICOX/CAnl/wgJ5f8JCeX/CQnl/wkJ5f8JCeb/Bwjq/wYH\n        6P8OD9L/EBGY/yIjYv8fICr/GxwW/ykqIf83NzL/SktL/1hbXP9YXWD/Vl1g/1ZdYf9VXGL/UFhf/1Nb\n        Yv9XXmX/WmFo/15mbP9haG7/YGdt/19mbP9cY2v/WGBo/1RbY/9QWF//U1ph/1heY/9SWFz/UldZ/1JV\n        V/9BQ0L/KSol/x4fF/8SEwz/EhMe/xESTv8PD5T/CwvR/wgJ6/8ICev/CAnl/wgJ5f8ICOX/CAjl/wgI\n        5P8HB+f/BgfY/2dtp/+vuLr/aG94/z5CR/9DSE//QUZS/0FGVP9BRlD/QEVN/0tRWf9haHH/S1BX/x4g\n        I/8cHiH/OT5E/0FHT/8zOUHTMTc/RDhJSgEzO0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD5GADA2PgA1O0MwOD5Gv0hP\n        WP5HTFL/JCcq/x0fIv9AREr/foWQ/6Grrv+Rmbj/PUHU/wcH5f8EBeX/CAjk/wgI5P8ICOT/CAnl/wgJ\n        5f8ICeX/CAnl/wgJ5f8JCeX/CQnl/wkJ5f8JCuX/CQrl/wgJ6P8ICO7/CAni/wwNv/8TE4v/GhtZ/yUm\n        PP80NC7/QEA4/1FQSP9jY1z/Z2dj/21ubP9zdnb/c3Z3/25yc/9uc3X/bHJ1/25ydv9rcHP/a3By/2tw\n        cv9rbnD/aWxt/2dpav9eX13/U1RQ/01NR/88OzP/Kysi/yMkHf8aGzD/FRZS/xARh/8MDcH/CQri/wgI\n        7v8JCen/CAnl/wgJ5f8ICeX/CAnl/wgI5f8ICOX/CAjl/wgI5P8EBOn/GRvD/46UqP+aoqn/TVJZ/0FG\n        S/9BRU7/QERO/0NJT/9TWmP/ZGt0/0FFS/8bHR//HB4h/zs/Rf9DSVL/NDpCzjI4QEE4PkgBMzlCAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAO0FJADo/SQA7QUkqO0BKskhPWPxJT1b/KCsu/xsdH/81ODz/cnqD/52m\n        q/+krLr/YWbO/xYY4P8DA+b/Bwfk/wgI5P8ICeT/CAnl/wgJ5f8ICeX/CAnl/wkJ5f8JCeX/CQnl/wkK\n        5f8JCuX/CQrl/wkJ5P8JCeb/CAnq/wgJ7P8JCeT/DAzK/xITqP8dHoj/Kytp/z09XP9TVGL/ZWVo/3V1\n        a/+Dg3f/jIuB/5CPhv+RkYf/kZCG/42Ng/+KioH/g4N5/3p5b/9ubWL/X19U/09PT/9AP07/Ly9N/yIi\n        Xf8YGYH/ERKm/wwNyP8JCeT/CAns/wkJ6v8JCeb/CQnk/wkJ5P8ICeX/CAnl/wgJ5f8ICeX/CAjl/wgI\n        5f8ICOX/CAjk/wcI5f8CA+T/Oz6o/6ixsv+Hj5j/QkZM/z9DSP9ESlD/XmVu/2Ztdv83O0D/GBoc/yEj\n        Jv8/Q0r/QUdP/jU7Q8I0O0M3TmNsADY9RQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQkVRADRB\n        QwA8Q0ogPURNnUdOV/hQVV3/MzY6/xweIf8qLDD/YGZu/5Wep/+uuLv/kpnM/zc62/8FBuX/BATl/wgI\n        5P8ICeT/CAnk/wgJ5P8ICeT/CAnl/wkJ5f8ICeX/CQnl/wkJ5f8JCeX/CQnl/wkJ5f8JCuT/CQrk/woK\n        5f8KCun/CQnr/wgJ6P8ICeX/CQrW/w0Owv8TE7P/Hx+p/ysro/81NZL/OzuP/0JCkv9HR5b/RkaW/0FC\n        kv85Oov/MDGM/ycnnv8dHaX/EhOt/w0Owf8KC9b/CQrm/wkK6f8JCuv/Cgrp/woK5f8JCuT/CQrk/wkJ\n        5f8JCeX/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8ICOX/CAjl/wgI5P8HCOT/Bwjk/wUG5v8GBtb/ZGmm/6aw\n        tf9lanP/TVNc/2pyfP9cYmr/LC80/xocH/8rLjL/SE1V/0FHUPs2PESwNTtDKicxOQA7P0cAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS1FPAD9FTwBCSFARPURNg0RKU+5UWmP/PkFH/x4g\n        I/8hIyb/TFBX/4WNl/+ttrr/q7PC/2Nozv8bHOD/AwLl/wYG5P8ICeT/CAnk/wgJ5P8ICeT/CAnk/wgJ\n        5P8ICeT/CAnl/wgJ5f8ICeX/CQnl/wkK5f8JCuX/Cgrl/woK5f8KC+T/Cgvl/woL5f8KC+f/CQrp/wgJ\n        6v8HCOz/Bgbp/wYG4/8FBeL/BQbh/wUG4v8FBuL/BQbi/wYG4v8GBuT/Bwfq/wgI7f8ICev/CQrp/woK\n        5/8KCuX/Cgrl/woK5P8KCuT/Cgrl/wkK5f8JCuX/CQnl/wkJ5f8JCeX/CAnl/wgJ5f8ICOT/CAjk/wgI\n        5P8ICOT/CAjk/wcI5P8FBuT/AgLl/xka3/9nbLb/oamu/4ePmv9sc33/UFVb/yIkJ/8bHB//NTg9/0tR\n        Wf9AR1D1OkBJljg/Rxw6QkoANz1FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAD5ETAA+RE0JPURMYEJJUdlQVl//SExS/ygqLv8cHR//MzY6/2xxev+bo6v/sbm8/5ui\n        yf9SVtr/ExPj/wMD5P8GB+T/CAnk/wgJ5P8JCeT/CQnk/wgJ5P8ICeT/CQnk/wkJ5P8JCeT/CQnl/wkK\n        5f8KCuX/Cgrl/woL5f8KC+X/Cgvl/woL5f8KC+T/Cgvk/woL5P8LC+T/Cwvl/wsL5f8KC+X/Cwvm/wsL\n        5f8LC+X/Cgvl/woL5f8KC+X/Cgvk/woL5P8KC+T/Cgrk/woK5f8KCuX/Cgrl/woK5f8KCuX/CQrl/wkK\n        5f8JCuX/CQnk/wkJ5P8ICeT/CAnk/wgJ5P8ICOT/CAjk/wgI5P8HB+T/AwPl/xIT4/9NUdT/kJa9/6Or\n        sP+Kkpz/Zmx0/zU4Pf8aHB7/IiQn/z1CR/9MUVr/PURM4zk/SG8/RU0OPUNLAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENKUgBMVFsCPkVMOz5E\n        TLpLUlv6VFph/zo9Qf8dHyH/IiQm/1BUWv+Ei5X/rLW5/7zEyf+Rl8//QEPb/w4P4v8DBOT/Bwfk/wkJ\n        5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkK5P8KCuX/Cgrl/woL5P8KC+T/Cgvk/woL\n        5P8KC+X/Cgvl/woL5f8KC+X/Cgvl/woL5f8KC+T/Cgvk/woL5f8KC+X/Cgvl/woL5f8KC+X/Cgvl/woL\n        5P8KC+T/Cgvl/woK5f8KCuT/Cgrk/woK5P8JCuT/CQrk/wkK5P8JCeT/CQnk/wgJ5P8ICeT/CAnk/wgI\n        5P8GBuT/AwPl/w4P4v9BRNz/jZPO/7G6vv+fp6z/eoKK/05TWv8jJSj/Ghsd/zAyNv9MUVj/R0xW/DpA\n        SMc7QUlKQ0lTBD9ETgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJIUAAaICsAPkRLHDxCSodDSVHrVFpi/01RV/8qLDD/Gx0g/y8y\n        Nv9jaHD/l5+o/7a/wv/AydP/mJ/d/0hL3/8TE+P/AwPk/wYG5P8ICOT/CQrk/wkK5P8JCuT/CQnk/wkJ\n        5P8JCeT/CQrk/wkK5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgrk/woK5P8KCuT/Cgrk/wkK\n        5P8JCuT/CQrk/wkJ5P8JCeT/CAnk/wgJ5P8FBuT/AwPk/xIT4v9DRdz/i5HQ/7W9xv+qsrX/ho2V/1pf\n        Zv8xNDj/Ghwf/yIlKP9DR0z/UVZe/0JIUfE5PkeYNz1EJQAAAAA5P0kAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAA9QkkAP0NLCDk+Rk47QUnDT1Ve+lpfZ/9BREn/JCcp/x8hJP86PUL/cXd//6iwu//L1Nr/0trj/6mv\n        5v9bX+b/ICHk/wUF4v8CAuP/Bgfk/wkK5P8JCuT/CQrk/wkK5P8JCeT/CQrk/woK5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woK5P8KCuT/Cgrk/woK5P8JCuT/CQrk/wkK5P8JCuT/CQnk/wYG5P8CAuP/BAXj/xsc\n        4f9ZXd7/nKPY/7vCyv+0vMD/k5qj/2ludv85PEH/HiAi/x8iJf83Oj7/UFZd/01TW/07QUnNNz1FXD1F\n        TQs4PkgAZH9yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8QUkAJRUeAD1CSh49REyARk1V4Vdd\n        Zf9aXmb/Oz5C/yEjJv8lJin/REhN/3N4gv+rs73/z9fc/9rj6v/K0vH/jJDu/0dK6P8UFeL/BQXi/wID\n        4v8GB+P/CAnk/woK5P8JCuT/Cgrk/woK5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgrk/woK5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/wkK\n        5P8ICeT/Bgfj/wID4/8FBeL/FBXi/0FE4v+Eien/uL/f/8nR1/+5wcX/lp2m/291ff9BREn/ISIl/x0f\n        Iv80Njv/UFRa/1NZYf9BR0/oOT9GjTk+RiY9RkwAOT9HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAREtTAEhQVwVARk86QEZOoUtSW+5eZG3/Wl9l/zw/RP8iJCj/IiQo/0BC\n        R/91eoP/n6ax/8bO1v/g5+z/4+n5/77D9P+EiO7/U1Xp/yEi4/8NDeL/BATi/wQE4v8GBuP/CAjj/wkK\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgrk/woK\n        5P8KCuT/Cgrk/woK5P8KCuT/CAjj/wcH4/8EBOL/BAXi/wwN4v8fIeX/Skzo/32A6P+7wO3/1dzr/9Tc\n        3v+7w8r/k5ul/2txef89QUX/ISQn/x8hJP8yNTn/TVJX/1heZv9HTVXzO0FIsDg+RkY5P0cIOT9GAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS1NfADk9\n        QABESlIMPkRMT0JJUbNUWmTyYmlx/1tgZ/8+QUb/Jigr/yEjJv80Njr/VVlg/4qQmv+2vsn/2+Pr/+Xs\n        8f/r8Pv/ztL4/6ir9f9vcO3/TEzo/y8w5v8TFOP/CQri/wYG4v8EBOL/BAXi/wYH4v8HB+L/Bwji/wgI\n        4/8ICeT/CAnk/wgJ4/8ICeP/CAnj/wcI4/8HB+P/Bgbj/wQE4v8DA+L/BQbi/wkJ4v8QEeL/KCnl/0ZI\n        6P9tcOz/pajy/8jN9//h5vb/3OLo/8vT2v+rs73/g4mS/1dcYv82OT3/ICIl/yAiJf81ODz/VFhe/1th\n        af9MUlv2PENLvjg+Rlw7QUcRDQoQAD1DSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAElTVwAAAAAARUtSEkBFTVdDSVGzUlhh8GVr\n        c/9kaXD/SU1R/zI0N/8hIyb/Jykt/0NFSv9kaXD/kZmi/7a+x//X3+b/8ff5/+7y+f/t8fv/3d/8/7q7\n        9v+envP/fH3w/2Nl7f9GSOr/MzTm/y8w5v8qKub/ICDl/xgY5P8XGOT/Fhfk/xYX5P8ZGeT/JCTl/y4v\n        5v8yM+b/QEDo/1ha6v91d+3/mpvy/7O09v/T1vr/5+z6/+bs9P/i6fD/ydHa/6y0vv+NlJ3/Zmtz/0RH\n        Tf8nKSz/ICIl/ystMf9ER0z/WmBm/1xiav9MUlr0PUNMvzpAR2M8QkoYXGBoAEBFTQAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAABESFEAS0dTAENIUBBBR09NRkxUpVBWXuViaHH9Z210/15jaP9AREn/LC4y/yEj\n        Jv8mKCz/OTxB/2Fmbf+Bh4//o6u0/8PL0//Q2N7/4ujr//j7/P/3+v7/8fP6/+vt+//n6Pv/5uf7/9/g\n        +//P0Pr/w8T5/8HD+v/Awvr/v8H5/8TF+P/W1vv/5eb8/+fo+//q6/v/7/D6//P3+//0+Pn/4ejs/8rR\n        2f+7xM3/nKOu/3uAif9cYWf/PD9D/yYoK/8hIyb/KSwv/zw/Q/9cYGb/ZWpy/2BncP5QVl/qRk1Vrj5E\n        TFg8QkoWUVVXAEBFTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR01VAAAA\n        AABDSVEKREpTNkNJU4BMUlzJWmBp8mxye/9pbnb/XWFn/0ZJTv8vMjX/KCkt/ycpLP8yNDf/Oj5C/1RY\n        Xf9yeH//jpSb/5+lrf+or7b/xMvV/9Xb4//b4eX/2+Hm/9/k6f/a3+L/19ve/9fb3v/b4OP/4ufs/+Tq\n        7//e4+j/1t3j/8fP2f+qsbr/mqCq/4qQmP9yeH//V1tg/zg7P/8tMDP/JScq/yIlKP8sLjH/QURI/1tg\n        Zv9la3L/a3F7/1tha/VOVV3QQUdPikJHTz5FSlMNV2dpAElRVwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPVV0AVlxjAkZMVRlHTVZPSE5YlVJY\n        Yc9dY2vyZGpz/nF2fv9nbHP/XGBm/1BUWP85Oz//LS8z/yosL/8qKy7/NDY6/z5AQ/9JS0//TVFV/1ld\n        Yf9gY2n/Z2pw/2pudf9wdHv/cHR7/21xeP9manH/YWVr/1RYXP9ITFD/RUhL/zs9Qf8xMzf/Jyks/yYp\n        K/8qLC//MzY6/0lMUP9VWF7/YWVs/3B2fv9obnf+X2Vv9VNZY9RFTFSdREtTWENKUx9KUFkER05XAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAbXN8AENJUQBRV2AFRUxUH0VLVE5JT1iJTFNbvl9mb+NtdH74bnR+/3l/\n        h/99g4r/bHF4/1hcYv9VWV7/U1Za/0tNUf9AQkb/NDU4/zU3Of82ODr/Njg6/zc4O/82Nzr/NDU4/zM0\n        OP8xMzX/MDE1/zk7P/9ER0v/UFNY/1NXXP9XW2D/am51/3h9hP91e4P/anB5/2VsdfpaYWrmTFJbw0hO\n        V5FDSVJWQkhRJEdOVQc3NUkASFFWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAB5f40AAAUAAFRaYANLUVgSR01VM0ZMVVxLUluKU1litFdeZ9RjanPob3aA9HZ9h/xyeIH/dnuD/3uB\n        iv91e4L/e3+H/4CFjf+Ch4//hImR/4SJkP+Cho7/gIaO/3uAiP91e4L/eH6G/3N5gv9zeoP/eYCK/XJ5\n        gvVja3TqVl5n11FXYbhKUFmQREtTYUJIUDhHTVUWRk5VBF9YagBLUFkAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkd3MAQURQAEtS\n        WgRMU1sOT1ZfIEtSW0FJT1hgSVFafktSWpxSWmKzWV9pxVtibNNcYmzgXWRv6l9mcPFgZ3H1YGdy9V9n\n        cfJeZm/rXmVu4V1lbtVZYGnHVFpktU9WX59NVFyCS1JbY0xSXEVOVV0jTVNcEFBVXgWimqMAXF9oAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAP///////8AAAAH///////////////wAAAAAH//////////////AAAAAAAP/////////\n        ////AAAAAAAA/////////////AAAAAAAAB///////////+AAAAAAAAAH//////////+AAAAAAAAAAf//\n        ////////AAAAAAAAAAD//////////AAAAAAAAAAAP/////////AAAAAAAAAAAA/////////gAAAAAAAA\n        AAAH////////wAAAAAAAAAAAAf///////wAAAAAAAAAAAAD///////4AAAAAAAAAAAAAf//////8AAAA\n        AAAAAAAAAD//////+AAAAAAAAAAAAAAf//////AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAP/////\n        gAAAAAAAAAAAAAAB/////4AAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAD////+AAAAAAAAAAAAAAAA\n        f////AAAAAAAAAAAAAAAAD////gAAAAAAAAAAAAAAAAf///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAA\n        AAAAAAf//+AAAAAAAAAAAAAAAAAH///AAAAAAAAAAAAAAAAAA///wAAAAAAAAAAAAAAAAAH//4AAAAAA\n        AAAAAAAAAAAB//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//gAAAAAAAAAAAAAAAAAAf/4A\n        AAAAAAAAAAAAAAAAAD/8AAAAAAAAAAAAAAAAAAA//AAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAA\n        AB/4AAAAAAAAAAAAAAAAAAAf8AAAAAAAAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAA/gAAAAAAAAAAAA\n        AAAAAAAH4AAAAAAAAAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAfAAAAAAAAAAAAAAAAAAAADwAAAAAAA\n        AAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAYAA\n        AAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA\n        AAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAA\n        AAHAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAA\n        AAAAAAAH4AAAAAAAAAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAfwAAAAAAAAAAAAAAAAAAAP8AAAAAAA\n        AAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAB/4AAAAAAAAAAAAAAAAAAAf/AAAAAAAAAAAAAAAAAAAP/wA\n        AAAAAAAAAAAAAAAAAD/+AAAAAAAAAAAAAAAAAAB//gAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA\n        AP//AAAAAAAAAAAAAAAAAAD//4AAAAAAAAAAAAAAAAAB///AAAAAAAAAAAAAAAAAAf//wAAAAAAAAAAA\n        AAAAAAP//+AAAAAAAAAAAAAAAAAH///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////gAAAAA\n        AAAAAAAAAAAf///8AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAD/////\n        gAAAAAAAAAAAAAAB/////8AAAAAAAAAAAAAAAf/////gAAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAP\n        //////gAAAAAAAAAAAAAH//////8AAAAAAAAAAAAAD///////gAAAAAAAAAAAAB///////8AAAAAAAAA\n        AAAA////////wAAAAAAAAAAAA////////+AAAAAAAAAAAAf////////4AAAAAAAAAAAf/////////AAA\n        AAAAAAAAP/////////8AAAAAAAAAAP//////////wAAAAAAAAAP///////////AAAAAAAAAP////////\n        ///8AAAAAAAAP////////////wAAAAAAAP/////////////gAAAAAAf//////////////AAAAAA/////\n        ///////////AAAAD////////KAAAAMAAAACAAQAAAQAgAAAAAAAAQAIAEwsAABMLAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAD///8ALTc+AEFKUAMuOD8UHiYuJBcgKTUXICZKGyQsYx4nLoIgKTCaHSYtsRghJ8UYICfZGCIo6hgg\n        KPkXHyX/Fh4l/xYfJv8XHyb/Fx8m/xcfJf8XHyb/FyAn/xcgJ/8YISf/GCEo+xkhKO0ZICfbGCEoyR4n\n        LrUhKjGeICkwhyApMGoZIilOFyAnOR0lKyctNjwXU11jB////wCCi5EAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjLzcAMz1BCygyOCkdJy1HGCIpZRsj\n        KowbJCuqGSAowxcfJ9oWHiXxFR0k/RUeJP4VHib+FR0k/xQdI/8VHST/Fh4k/xYeJf8VHiX/Fh4l/xYe\n        Jf8WHiX/FR4l/xYeJf8WHyb/Fh8n/xcgJ/8XICf/Fh4l/xYeJf8WHiX/Fh4l/xYfJv8VHiT+FR0k/hUe\n        Jf4XHyb1Fx8m3hggJ8YbIyquGyQqkxcfJmsaIypNJzA3LjQ9QQ8eJy8AAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAlLDgAKCs7ACMsNQQoMjgLJzA3KB0mLlUZIiqBGiMqsxokK9MYIinkFyAn9hUeJf8UHST/FBwk/xUd\n        JP8VHST/Fh4l/xYeJv8XHyb/FyAn/xYgJv8XICb/FyAm/xcgJ/8XISj/GiIp/xwkK/8dJiz/Hikv/x8p\n        L/8eKS//Hygv/xojKv8XICf/GCEo/xghKf8XISj/GCEo/xgiKf8WICf/Fh8m/xYfJ/8WHyb/Fh8m/xUe\n        Jf8VHiX/FR4l/xYeJvkYISnoGiQr1hoiKrsYISiIGiMqXSQsMy8jLTUNJC00BSMsMgAjLDMAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApNDwARVFbAB0nLwkfJy4dJi81QRsk\n        K3caIyuqGiMq2hgiKfEXICj7FR4l/xUeJf8WHiX/FR4l/xYfJv8YISn/GSIq/xsjK/8cJSz/Hygv/yIs\n        Mv8nMDf/KjQ5/ys1Ov8rNjr/KjQ5/ys1Of8pMjf/Iysv/yozN/8rMjb/Iiot/yIqLf8oLzP/LzY5/yYv\n        Mv8pMjf/KjQ4/ys0Ov8tNjv/LTY9/yw3Pf8oMzn/Iy41/yIrMv8eJy//HCUt/x0mL/8bJS3/GCEp/xYe\n        Jv8VHyb/Fh8n/xUeJf8VHiX8FyAn9BkhKeAZIyyzGyQsgiQtM0sfKC4hHigvDDdGSQEoNDkAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAIisyACUvNQQaIysfICgvSxsjLIYXHya6GCEo4xYfJvkTHCP/FBwj/xYe\n        Jf8XICf/GiQr/x0oLv8fKjH/Iiwz/yUuNP8mLzX/KjM4/ygyNv8oMTT/JSwv/x0kJv8aHyH/FBcY/xIV\n        Fv8SFhb/ERUV/xIWFv8SFRX/EBMT/xIUFP8SFBT/DxIS/w8SEv8RExT/ExUV/xIUE/8TFRb/ExYW/xMV\n        Fv8TFhf/ExUW/xYZGv8ZHh//HSMm/yUsL/8rMzf/KTI2/y43Pf8pNDr/JzE2/yQtNP8jLTT/Hykx/xoj\n        Kv8VHib/FR4l/xUeJf8VHib/FyAn+xghKOkXICbDHCUrjyEqMFIaIyomIy00BwoUGwBKVVwAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0hNAFNb\n        XwEkLTQTHCUtPSIrMnwYISm7Fx8l5hYfJfkVHST/FBwj/xQcI/8UHST/GiMq/yItNP8kLjb/JjA2/ycx\n        Nf8mLzP/KDAz/yMpKv8UGBr/FBcX/w8SEv8NEBD/DRAP/wwODv8MDg3/CgwM/woLDP8JCwv/CAoK/wgK\n        Cf8JCgn/CAoJ/wgJCf8ICgn/CAoK/wgKCv8ICgn/CAkI/wkJCf8KCgv/CQoK/wkKCv8KCwv/CwsL/wsN\n        Df8MDg7/DQ4P/w4QEP8OERH/DhER/xQVF/8XGhz/Iigp/ykxNP8rMjf/KDI2/yMuM/8jLTT/JTA4/x4o\n        L/8YISj/FR8l/xQdJP8VHiX/Fh4m+xUdJOoWHyXFICkuiB4oLUkhKzEYbXt9AwAAAADU7OIAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA7QAAxO0EIISwyJx4nLmEcJSypFR4l4hUd\n        JfoVHiX/Fh8m/xYfJv8WHib/HCQr/yQuNf8oNDr/KTM3/yEpLf8gJin/GyAh/xIVFv8MDg7/CwsM/woL\n        DP8KCwz/CwwM/wsNDP8KDQz/Cg0M/wsLDf8ODw//ERQT/xMXGP8WGxz/HCEj/yAkJv8cIiP/HyYo/yIp\n        K/8jKiz/Iyks/yIqLP8iKiz/Iykr/yEnKv8cISP/ICQl/x4jJP8XHB7/FRga/xASFP8QEBD/DA0O/wsM\n        Dv8LDQ3/DA0N/wsNDf8LDAz/CwwN/wwMDf8NDg7/EhQV/xkdH/8hJyn/JCsv/ycwNP8oMjn/JzE5/x4p\n        L/8ZIin/Fh8m/xUdJP8UHCP/FB0i/BUdIuobJCq2Hyctbx0nLjA1QUcLIR8jAENYXwAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAvOUAAJzI5CSQuNTwZIimEGSIpyBYeJvEVHST/FR0k/xYfJv8XICj/GyUt/yQv\n        Nf8sNjv/KTI1/x4kKP8dIiX/Gh0e/wwNDv8KCgv/CgsL/woMDP8LDQ3/DA4P/w0PD/8PEBD/ExYX/xgf\n        IP8gJyn/JS4x/ycvMv8rMjf/LTY7/ycwNf8lLjP/LDQ6/zE6Pv8wOT7/MzxB/zI8Qf8wOkH/Lzo//y45\n        P/8wOkH/Mj1D/zM+RP8xO0D/ND1C/y03PP8mLzT/KTM4/y02Ov8tNTn/KTI2/ygwNP8iKCv/HCAi/xIW\n        Fv8ODxD/Dg8R/w4PEP8NDw//DAwN/wsMDf8LCwz/DA0N/xYYGf8cISP/ICcq/yUtMf8sNTz/JjE3/x0m\n        Lv8YISn/Fh8n/xQcI/8THCL/FBwj9xggJ9AZISiQISoxRycwNxEvOD8AAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVHyoAl5uoACky\n        Og8jLTRIGSIpmRkiKdwWHyb4Fh4l/xYfJv8YISj/GiQq/x8pMP8mMDf/Ji8z/xofIv8XGxz/FBcY/wwN\n        Dv8JCgv/CQoK/woMDP8NEBD/EBIT/xUXGP8WGhz/HSIm/ykyNv8tODz/Ljk9/yk0Ov8vOD7/MDtB/zA7\n        Qf82Qkr/OkdO/ztJT/89S1L/PkxU/z5MU/8/TlX/P05T/z9NUP8+TU//PkxM/z5LTP8+TU3/P05P/z9O\n        Uf9BT1X/QE9W/z9NVP89TFP/PUtR/z5LUf87R07/M0BG/zE8Qv8vOT7/KjQ5/y44Pv8wOj7/KTE1/x8l\n        J/8WGx3/EhUV/xEUFf8OEBH/DA0N/woLC/8KDAz/DQ8O/xIVFf8YGhz/HCEj/yUuMv8qNDv/Iiwz/xoj\n        K/8YISj/FR0k/xUdJP8VHST7GB8n4xYeJaseJy1YKDE3FkFNVAINFBwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALjlAADdDSgIfKjEVHyguUhghKqkXISfqFyAm/RYe\n        Jf8VHiX/GiMr/x8pMP8jLTT/JzE3/yEnK/8VGBn/EBIS/wwNDv8KCgv/CQoK/woLDP8PERL/FBgZ/xkd\n        Hv8gJyr/KjQ4/zI8Qv8wOkD/Ljg+/zE6QP8yPkT/O0lP/0BOVv9BUFb/QVBT/0JRT/9EVFD/RVZP/0dY\n        TP9HWEn/R1ZI/0VVRv9EVEX/QlJH/0BQT/9AUVT/QVBa/0FQWv9BUFr/QVBY/0FQUv9CUkn/RVRG/0dX\n        SP9IWUr/SFhM/0hYUP9GVlL/RFNR/0NSVP9DUlj/QU9W/ztJUP80QEf/MTxC/zA6Qf8yPkX/NEBE/y44\n        PP8gJyr/GR0f/xQYGv8QExT/CwwL/woLCv8LDAz/DQ4P/xASE/8TFhj/ISgq/yo0OP8lLzX/ICox/xok\n        Kv8UHCP/FBwj/xUeJf4XHybzGCAnuR0mLGIhKzAcLjc/AyozOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAbIy0AKDI4EyApMFIZIiiqFR4k6hUdJf8VHiT/FR0k/xoiKf8hKzH/JC0y/yQs\n        L/8bICL/ERMU/w0OD/8MDQz/CgsL/wsLC/8RExP/GR0e/x4jJP8hJyr/LDU4/zM9Qv8zPEP/MTtB/zVA\n        Rv86R0z/QU9U/0NSVP9DVFD/RlZN/0ZXSP9CUkH/PUxN/zlHYv82Q2L/MT1l/ys1ef8nMIH/JS19/yMr\n        ev8gKHb/GyF9/xcdkf8WHJ7/FRqu/xUZr/8VGqz/Fhqn/xcdmf8bIYH/HyZ2/yUue/8oM4L/KzWA/zA7\n        aP81QV//OUZm/z1LVP9DUkH/R1hJ/0hZUP9GVlL/RFRW/0NSV/8/TFL/NkNI/zE8Qv80P0T/NUBE/y02\n        Of8kLC7/HyQm/xwgIf8SFBT/DAwM/wwMDP8MDg3/DhAQ/xASEv8ZHR7/Ji4x/yYwNP8jLDP/HCQs/xUd\n        JP8WHiT/FR4k/xQdI/IXHya4HiYuXykyOBoXHCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        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\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAyPEEAcH5/ACw1OxseJixvGCEoyhUdJPwUHCL/Fh4l/xskLP8jLzn/JjQ9/x0o\n        MP8WHST/DhMX/woOEf8MEBP/DxUY/xUdIv8jLzf/KjhD/yo7R/8xQ1H/Ok5f/z9WZP9GX2X/SGRj/0Zg\n        aP9AWGn/NUlp/yIujP8VHbP/DhPP/wUH3v8AAef/AQH0/wEC9/8BAvb/AQP0/wID7/8DBO3/AwTt/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8CBO7/AwTv/wID9P8BAvb/AQL2/wEB\n        9v8BAuj/BQfc/w0Syv8VHbP/ICyJ/y9Baf8/VWT/RV9n/0pkY/9DXGH/O1Bd/zdLWf8vQE3/KTpF/y4+\n        S/8kMDv/Fh0k/xAWGv8MERP/Cw8R/wwQFP8UGh//HCUs/yUyO/8kMTz/HCYu/xYeJP8UGyL/FR0k/Rki\n        KNccJSyDKjQ7J1diaQE0PkUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAA\n        AAAqNTsGHygvSBkiKa0WHybwFR4k/xUcIv8ZIin/ICs1/yc2Qv8fKzP/ERkd/w0SFv8LEBP/CxAT/xAV\n        Gv8YICj/IS01/yw8SP8tPUn/MkRQ/zxRYP9DW2X/SWVm/0lkZv9AV3H/MEJ0/x0olP8OFMD/CQzb/wMD\n        6f8AAPL/AQH2/wIC9P8CA/L/AwTu/wME7f8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AwTt/wME7v8CA/H/AgL0/wEB\n        9/8AAPL/AgPp/wcJ3P8NEr3/HCeV/zFEbv88Umr/RV9f/0ljYv9CW2T/PVNh/zVHVv8tPEn/Lj5M/ycz\n        Pv8aIin/EBYb/wsQFP8LEBL/DRIV/xEYHf8dKDD/KThD/yMxOv8bJCz/Fh4k/xceJf8WHyb1Fx8mvB0n\n        LlgiLDQO////AGFwcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApMjoANUBIASUvNyUdJi2AFyAn4xYe\n        Jv8VHiT/FyAm/yAsNP8mMz7/Ii44/xUcIv8NEhb/CxAT/wsPEv8PFhr/GyMr/yUxO/8wQU3/L0BN/zNF\n        Uv9AWGX/R2Fp/0lkYf9BWWT/M0Z0/yIvkf8NEsL/AwTo/wEC9P8AAPT/AQH0/wID8v8DBO//AwTt/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8CBO//AQPy/wEC\n        9P8AAPT/AQL0/wME5P8LEb3/IC2T/zJFdv9CWmX/S2Zj/0lkbf9EW2r/NkhW/y49S/8uPkv/JTI8/xsl\n        LP8SGB3/DBEU/wwRFf8OExf/FBsg/yUxO/8nNUD/IS02/xkiKf8WHiT/Fh4l/xYeJesbIyuVJCw0MDE6\n        QwMlLDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAC03PgAuOD8JHiUuSRoiKbwWHib0Fx8m/xYfJv8cJy//JTM9/yUx\n        PP8ZIij/DhIW/w0RFP8NDxP/DxQY/xskKv8iLjf/KzpG/zFDUP82SVb/QVdl/0ZgZ/9GX1//OU5o/yg2\n        j/8UHLD/BQfP/wAA9P8BAfb/AQLy/wID8P8DBO7/AwTu/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7v8DBO//AgPw/wEC\n        8/8BAfb/AAD4/wMF0/8UG6z/JjSP/zpPZv9JZGH/SmVu/0JZZv81R1b/MUFP/yw7R/8nNT//Higw/w8W\n        Gf8MERT/DhIW/w8TF/8XICb/JjI7/yg2Qf8gKzT/GCEo/xYfJf8VHSP6GCAmyhoiKWApNDkQKTQ5AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAeKjEAKiwyACIsMxocJSx7GCAn3BYeJf8VHST/GCAn/yMvOf8mND7/HScu/xAXHP8LEBP/DRAT/wwR\n        E/8XHyX/KTdC/yo5RP8vP0z/NkpX/0BXYv9HYGb/RV1g/zRGb/8dKJn/CxDF/wID6v8AAPv/AQH1/wID\n        8P8DBO7/AwTt/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO7/AgPx/wIC\n        9f8AAPn/AQLq/wsQw/8eKZb/Nkls/0dhZP9IYmj/Qlpl/zdJWP8wQk//KjhD/yg3Qv8cJS3/DhMY/w0R\n        Ff8NEhT/Ehcb/xwnLv8mNT//JTQ+/xokK/8VHiT/FR0i/xUeJOkbJSqRIys0KEdRYwEhKDMAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADpDSQA9RkwEIis0OBki\n        Kq0WHyX0FR4k/xYfJv8cJi7/JjQ+/yIuNv8TGyD/DBEU/wsQFP8OEhb/FRsh/yItN/8rOkX/MUJP/zlN\n        Xf9CWmT/SGFj/0JZYP8yQ3H/GSOl/wgL1v8BAe//AAD6/wEC8/8DBO7/AwTt/wME7f8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO7/AgLz/wAA\n        +v8BAe7/CAvT/xkgof8xQW//Qlph/0hgY/9CWWX/OEtb/y4+S/8sO0j/JTM+/xYeJP8OFBf/CxET/wwR\n        FP8TGiD/ICs0/yk3Qv8fKjT/FyAn/xUdJP8VHiT7FyAowSApMk08R00IOkZMAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKVVwAIywyACs1OgodJi5ZGCEpyxcfJ/4WHiX/FyAo/yAr\n        Nv8lMz3/GSQr/w4UGP8LEBP/DBAU/xEXHf8eKTH/KztH/y09Sf80RlP/P1Vh/0ljZP9FXmX/MUN0/xYe\n        pP8HCtj/AQLy/wEC9/8CA/L/AwTt/wME7f8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7f8CA/L/AQL3/wEB\n        7/8ICdb/Fx6f/zFBcf9EW2T/SWNl/0BWY/81SVf/Lj9L/y49Sf8iLTb/Exof/wwRFP8MERT/DRMY/xki\n        Kf8nNED/JDE7/xojK/8WHSP/FR0j/xcfJ9wdJi5uKzU7EwAAAAA2QkcAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAgKDAAIyw0Fh0mLXwVHybhFBwj/xYdI/8aJS3/IzA7/yEuNf8TGyD/CxEU/wsP\n        Ev8NERX/GSIo/yY0P/8sPEj/MkRR/z1TYP9EXWD/RV1d/zVHcv8aJaH/Bwrc/wEB8/8BAvX/AgPx/wME\n        7f8DBO3/AwTt/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AwTt/wMD8f8BAvX/AQHy/wcJ\n        1/8ZI5//NEZz/0VdXv9IYmb/QVdl/zFCUP8vP0z/KzlG/xwmLv8OFBj/CxAT/wwSFf8SGR7/IS02/yg2\n        QP8fKjL/FyAm/xQdI/8UHCTuGyUtkiYwOCUsN0QBKDM+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARE1PAMDG\n        swEiLTQnGiIqmxUdI/UUHSL/FR0i/x4pMv8lMj3/GyUs/w4UF/8NERT/DBAU/xAVGf8fKjL/KjpG/y9A\n        Tf83S1f/RFxi/0VdXP81SWT/HyyX/wcL1f8BAfX/AQL1/wIE8P8DBO3/AwTt/wME7f8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTt/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7f8DBO3/AwTw/wEC9f8BAvX/BwnU/x8p\n        mP85TGT/R2Bd/0ZgZ/85Tlr/MEBN/y4+Sv8lMTv/FBsh/wwQFP8MERT/DRIW/xokKv8nNkH/IzA5/xcg\n        J/8VHCT/FR0k+RkiKbMeJi87V2FoAzlCSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiLTMAMD9EAR4oLjkZIimyFh4l+RUd\n        Iv8WHiT/Ii43/yQxO/8XHiX/DBEU/wwRFP8NEhb/GCEn/yUzPf8sPEj/M0VS/z5VYP9GX2D/PlNb/yQx\n        i/8MEcX/AQHu/wAC9v8CA+//AwTt/wME7f8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7f8DBO7/AwTv/wME7/8DBPD/AgPy/wID\n        8v8CA/L/AwTx/wME8P8DBO//AwTu/wME7v8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AwTt/wME7f8DBO//AQL3/wEC8P8MEcD/JjWA/z5W\n        Xv9EXWb/P1Vk/zRGU/8uPkr/KzpG/xslLP8OExb/DREV/wwRFf8UHCL/JTI8/yc0Pv8aIyr/Fh4j/xUd\n        JP0XHyfKHicwTjA+RQMgKzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADE6QgA0PkcDICoyRxYfJscUHCP8FRwh/xghJ/8kMDr/IzA5/xMZ\n        Hv8MEBT/DREU/xAVGf8eKDH/KztG/zBATf85TVv/RFxi/0VdX/8wQnT/Ehiy/wME6f8AAPv/AQLx/wIE\n        7f8DBO3/AwTt/wME7f8DBO3/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        8f8CA/T/AQL0/wEC9P8BAff/AAD3/wAA9/8AAPf/AAD2/wAA8/8AAPH/AADv/wAA7v8AAO7/AADw/wAA\n        8v8AAPX/AAD2/wAA9/8AAPf/AQH1/wEC8/8CA/P/AwTx/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7f8DBO3/AwTt/wID8f8AAfn/BAXm/xIZsf8zRG7/R15q/0Ja\n        av8kMTz/Higx/yw7Rv8lMTr/EhYd/wwQE/8MERT/ERgc/yEuN/8nN0H/HCUs/xYdI/8UHSP/FR4l3CAn\n        Ll0wOkAKLzk/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AABTWmEAHygzAC84QgkgKTJaFyAn1RQcI/8UHCP/GyQt/yUxO/8dKC//DhQX/wsQE/8LDxP/FRsg/yc0\n        Pf8rOkb/M0VS/0FXZP9IYGT/P1Rj/x8qkv8GCNj/AAD2/wEB9f8CA+7/AgPt/wME7f8DBO3/AwTt/wME\n        7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7v8DBO//AgPz/wIC9P8AAff/AAD5/wAA7f8BAuT/AwTn/wYI\n        5f8KDdj/DRHX/w8U3P8QFdv/EBbR/xEXwv8SGLH/Fx2b/xkglP8WHpn/Ehim/xAWvf8QFdL/DxTb/w4S\n        2f8LD9f/Bwng/wQG6P8CAuX/AADu/wAA+P8AAff/AgL0/wID8/8DBO//AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AAD7/wwQ1P82SW3/R2Bn/zRHVf8ZIyn/Fh4k/xsl\n        LP8pNkH/KzpG/xcfJf8NERX/DBET/w0TF/8cJi3/JzU//x4pMf8WHiT/FR0j/xYeJeUeJy5yMDtBEgAL\n        EABASlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfKzIAKjQ7Cx4o\n        L2gXICfeFB0j/xQcIv8dKDH/JTI9/xskK/8NEhb/DBAU/wwQFP8XHyX/JjM+/y8/TP85TVv/Rl5n/0Zf\n        YP8xQnf/Exmx/wEB6v8BAfX/AgPw/wID7f8CBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTu/wME\n        7f8CA/D/AgL1/wEC9/8BAff/AQHj/wcJ2P8PFMn/Fx+//x4op/8lMo3/KzqW/zFBi/87Tmj/RFpk/0hh\n        cP9LZXX/TWh2/05peP9Panf/T2p0/1Brdf9QbHb/T2t2/01odf9LZXT/SGBu/0ZcaP9AVGb/NEaA/y49\n        lv8mM5D/HCWp/xggwf8QFcn/BwnZ/wEB4f8BAfX/AQL3/wIC9f8CA/D/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME\n        7f8DBO3/AwTt/wME7f8BAvH/BAXr/yk3jv9HYWX/QVZk/yArNP8WHiT/GyUt/xkiKv8ZIir/JjM+/y4/\n        TP8eKDH/DhIX/wwQFP8NERX/FyAm/yUyO/8gLDX/Fx4l/xUdJP8XHybpICkwgC85QRYfKC8AAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcwOAAoMTkNHygvbBchJ+UVHiT/FR0k/yAr\n        NP8kMjr/FBsh/wwQFP8LEBP/DRIW/xsjK/8qOEP/Lz9N/ztQXf9HYWb/QVhl/yMwi/8HCtP/AAH3/wEC\n        8/8CA+7/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME8P8CAvL/AAH1/wEB9v8CA+v/CArP/xQa\n        uP8fKqj/KTeT/zRFg/9AVm3/S2Vk/1Nvcv9VcXf/VnJ6/1Vye/9UcXn/U3B4/1Judv9Qa3P/T2py/09p\n        c/9NZ3L/S2Zx/0pkcf9MZnP/T2l0/09pc/9NaHD/UG11/1Rxev9XdH3/WHZ+/1d1fP9Vcnb/Um5x/01n\n        Zv9AV23/NEWE/yk4j/8fKqj/Exq6/wcJ0f8CA+j/AQH2/wAB9v8CA/L/AwTw/wME7/8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AwTt/wID\n        8P8AAPf/GSKz/0NaZP9HYGj/LTxJ/xYeJf8bJCv/GyYs/xolK/8aJCr/GSIp/yEtN/8uPkz/JDA7/xAU\n        GP8MEBL/DBAT/xMZHv8kMDr/IS02/xYeJf8WHiX/GCAo7h8pMYcqNj0ZHCkuAD1HVAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAtOz0AGyIsACIsNA0dJi1yGSEo6BYfJf8WHiT/ISw1/yc0P/8UHCL/DBAU/wsP\n        E/8QFhr/ICw0/yk5RP8wQk//PVRf/0ZfXv85Tmn/GCGt/wID6/8AAfb/AgTw/wID7f8CA+3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME\n        7v8DBO3/AwTt/wID8P8CA/P/AQH1/wEB8/8FB+P/CxDG/xkho/8sOY//Ok18/0Rca/9Qa2P/U3Bx/1Jv\n        c/9Sbnj/TWh1/0ZfbP9BV2T/O1Bd/zhMWf81RlX/Lz9M/yw7R/8qOkX/KjdE/yk2Qv8pNkL/KDZB/yc0\n        P/8oNkD/KTdC/yo4Rf8qOET/LDxI/y4+S/8yQ1H/N0pW/ztQXP9BV2X/SGFu/09pdv9RbXb/Um90/1Nw\n        cP9PamX/RFxt/zhMff8tPI3/GyOf/wsPwv8FBun/AQHy/wEB9P8CA/P/AgPx/wME7v8DBO7/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AwTu/wAA+f8LENL/N0pv/0pk\n        Yv81SFb/GCEo/xkiKf8cJSz/GCIq/xkiL/8cJS3/HCUr/xkhKP8eKDD/LDtI/yg2Qv8TGh//CxAS/wwQ\n        Ev8SGB3/Ii85/yIvOf8YISj/Fh4l/xghKPAdKDCMJC43Gg8WKAApNToAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAdJy8AJS83DBwlLnEXICfnFR4k/xcgJv8hLTX/JTE7/xUbIf8MEBT/Cw8T/xEYHf8iLzf/LTxJ/zRH\n        Vf9BV2D/RV5Z/y8/df8PFMD/AQLy/wEC9P8DBO3/AgTt/wIE7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBO7/AwTu/wME7v8DBO3/AwTt/wME7v8CA/H/AQL1/wAA\n        8f8DA+j/DBDT/x0nnf8zRXz/QVd7/0pibf9Tb2z/U291/05pdf9IYXD/PlNi/zRGU/8uPkv/KTdD/yYz\n        Pv8iLjj/Hikz/yEsOP8jLTz/Iy48/yczQv8oN0b/KjdG/yo3R/8qOEj/KDVE/yYzQv8qOEf/KjhI/ys3\n        Sf8qOEn/KjZE/yQwPv8iLT3/ISw6/yIrNf8kMDr/JjQ//yk3Qv8tPEj/NEZS/z5SYf9HX27/TWh0/1Ju\n        cv9UcG3/SmNr/0FXe/80RYr/Hiie/wwQz/8CA+n/AADx/wEC9v8CA/L/AwTu/wME7f8DBO3/AwTu/wME\n        7v8DBO7/AwTu/wME7v8DBO7/AwTt/wME7f8DBO3/AQL1/wQF7f8oNZP/SGJh/0BXY/8gKzP/Fh0j/x0o\n        L/8cJS3/GSEw/xkiNv8aIzT/GiQu/xwlLP8ZIij/GiMq/yg3Qv8qOkX/FR4j/woPEv8LDxP/DxYa/yMv\n        OP8kMDr/Fx8m/xUdI/8XICfwHCYtjScxOBgaJCsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkxOwAqMjsLHiYuaxcf\n        J+cVHCP/Fh4l/yIvOf8kMjv/Ehkc/wwQE/8KDxP/Ehke/yUyPf8tPkn/OEtY/0VdY/9CWV3/KTiA/wgM\n        1P8AAPT/AQPw/wME6/8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AgLz/wAA9/8BAez/Bwng/xUbsP8qOID/QFd2/0xn\n        cP9Sbm3/UGty/0pjcf9DWmr/NklW/ys5RP8lMT3/Iy03/yArNv8jLj3/KDRF/yo3SP8pNkb/KTZF/yk1\n        Qf8lMTz/JDE7/yMtNv8dJy//HSgw/x4pMv8fKTP/Hiky/x0nMf8dKTH/Higx/x0mMf8dKC//KDE5/yIt\n        N/8iMDv/LDhF/ys5R/8oNkX/KjdI/yc0QP8kLzv/ISw2/yMuOf8kMTz/KjlE/zRGUv9CWGj/S2V0/1Rw\n        eP9XdHj/Um55/0Zee/8rOoP/FBut/wYI2/8BAO//AAD4/wIC8v8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8CAvD/AQD3/xghtP9EW2P/SWFp/yo6RP8WHSP/GyMr/x0nLf8cIy7/GSE1/xki\n        OP8ZIjj/GSI1/xwkL/8bJCr/GCIo/xghKP8lMz3/LDtG/xcfJf8LDhL/Cw8T/xAVGv8hLDX/Iy84/xgg\n        Jv8WHSL/Fx8m8B8pMIYtNz8WGCIqAIaVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKTU7AC88QgghKTJkGCAn5BUdI/8WHSP/Ii44/yMx\n        Of8QFxz/Cw8T/wsQE/8WHyT/JzU//y08SP83S1j/Rl5h/z5UYv8eKZn/BQbk/wAA9v8CA+7/AgPt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTu/wID8/8AAfn/AQHr/wsPyf8iL5//PVJ5/01nbv9SbnX/Um93/0xlc/8/U2H/Lj5J/yYy\n        Pf8jLjv/Iy48/yMuPf8lMED/JjFA/yg1RP8oNUD/JTI7/yEtNf8lMjz/LT1I/zBCTv82SVX/P1Ri/0Nc\n        a/9FXWz/R2Bv/0lkdP9LZXX/TGZ2/0tldP9JY3L/R2Bv/0RdbP9CWmn/QFdl/zlMWf8zRVD/MEFM/yg3\n        Qf8hLDX/HScv/x4oMP8pNT//KTVE/yc0Rf8pNUT/JzJB/yQwPf8jLTr/JjI+/zJET/9AVmb/TGd1/1d0\n        fP9Wc3r/Tmhu/zhJbv8eKKX/CxDQ/wAB7P8AAfn/AgPz/wME7v8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7v8BAfb/Cw7X/zhLb/9MZWj/OExZ/xghJ/8XHiX/GyUs/xslK/8ZIjT/GSE4/xkiN/8ZIjf/GSE4/xkh\n        Nf8ZIy//GyUs/xokKv8ZISj/JC86/y8+Sv8aIir/Cw8S/wwQE/8PFBj/ISw1/yUxOv8YICb/FR0j/xcg\n        Ju4gKDB/MTtDEhcgKwBIUVYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAoMzoAOkdMAyEsM1gZISncFh0j/xYeJP8hLTX/JDA7/xAWGf8MDxP/DA8T/xkh\n        J/8rOUT/MEBN/zpOW/9FXWD/O05k/xcepP8CA+3/AQH1/wID7f8CA+z/AgPt/wME7f8CBO3/AgTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7v8CA/H/AAH3/wAB\n        6v8MEcL/Iy+X/z5UcP9RbnH/V3N7/1Jtev9EW2n/NUdS/yg1Qv8kMD//JTE//yUwQP8kLj7/Iy4+/yQy\n        Pv8kMTn/JDE6/y0+Sf83Slj/Qlpo/0pldf9Pa3r/UW59/1Jwev9Rb3b/Um91/1Jvc/9RbnD/UnBu/1Fu\n        a/9Pa2f/Tmlm/01pZP9NaGP/TGhk/05qaP9Qbm//U3F1/1Jvdv9QbHP/T2t3/09ref9MZ3b/RV5s/zpR\n        Xf80RlL/KTdC/yEsNf8fKC//ISw3/yUxP/8kMD//JzND/yk2Rv8mMkL/KDVA/zZJVv9HX27/Um57/1Rx\n        ef9SbnD/PlR0/yMumf8NEb//AAHn/wEB9/8CA/H/AwTu/wME7f8DBO3/AwTt/wIC8/8EBu7/KTea/0xl\n        aP9CWGX/Ii02/xUcIv8bJCv/GyQq/xoiMP8aIjn/GiM5/xokOP8ZIjf/GCE3/xgiN/8ZIjb/GiIx/xsk\n        LP8ZIyr/Fx8m/yMuOf8vPkv/GyQr/wsPE/8NERT/DhMX/yAsNP8jMDj/Fx4k/xUcIv8XHybpHykwcjE9\n        QwogKzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU8\n        QQBAR0oBHygwRRghKNMVHCP/FR0j/yArNP8kMTv/Ehgd/wsPEv8LDxL/Fh4l/ys6Rv8xQk//PVFf/0Zf\n        X/84S2z/Ehiy/wEB8f8BAfT/AgPs/wME7f8DBO3/AwTt/wME7f8CBO3/AgTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwPw/wEB9f8BAu3/DhO//yk4j/89UXD/UGts/1Nw\n        d/9MZnT/O1Bc/y09R/8jLzz/JjFH/yg1Sv8hLT7/ICo4/yQwPP8oNkD/LT5J/zpOW/9DXGj/S2dx/09r\n        dP9QbHX/UG1y/0tmav9EW1v/Ok9a/zVIgP8uP4j/JTJ7/x4qjv8dKaP/HSiw/x0mt/8aJLT/GSKy/xsk\n        sf8aI7H/GiO0/xwmr/8eKZf/Ii59/yo5gP8vQIf/NEZp/z9WVf9KZWf/UG1y/1Budf9QbHX/T2t1/0lj\n        cf9AVmb/NkpX/yc0Pf8fKjL/HCUv/yApN/8iLDv/KzhK/ys4Tf8mM0L/Lz5L/z5TYf9KZHH/Um10/1Bq\n        av8+U23/JjSM/wsPvP8BAuv/AQH2/wME8P8DBO3/AwPv/wEB9v8YIbn/R15s/0tkbP8tPUf/Fhwi/xoi\n        Kf8cJCv/GSIt/xkiNv8aJDn/GyQ6/xskOf8aIzj/GSI3/xojOf8ZIjn/GSA3/xghMf8aIyr/GiIo/xge\n        Jf8iLTX/Lj9K/x4oMf8NERX/DBEU/w8VGv8lMDj/JzM8/xYdJP8UHSP/FR8l5B0nLl0xOkYDLTZBAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOENGAAAAAAAhKzM3FyAnxhUc\n        I/8VHSL/ICo0/yQyPP8TGh//DBAU/wwRE/8XICb/KzlE/zFDUP89Ul7/Rl5a/zZJbv8PFMH/AAD1/wEC\n        8/8CA+z/AgTs/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME8P8BAvf/AgLw/wsPx/8iLo3/P1Ru/1Fsaf9RbHL/SmJv/zhLWf8pNUL/ICw3/yUx\n        Rf8oNUv/Iy4//yEtOv8qOUT/NklX/0FYZ/9KZG//UGxx/05qbv9KZG//QVln/zRHYP8qN4T/HSiQ/xMa\n        sv8OFMT/CQ3C/wYI2f8DBN7/AgLX/wEB4/8BAfD/AQH3/wEB+f8BAfn/AQH5/wEB+f8BAfn/AQH5/wEB\n        9/8BAen/AQHZ/wID2/8EBt//BwnM/w0Rwv8SGL3/GSGW/yQxi/8uP2z/PlRj/0plcP9PbHT/Um9y/01q\n        cv9GXmz/OExa/yc0Pv8bJCz/GiMs/x8pNv8nM0X/LTtQ/yc1Q/8oNkP/NkdU/0hgbf9TbnT/UW1s/0JX\n        b/8lMZH/Cw/O/wEB7/8BAvX/AAH2/w0R2/88UYL/UGtv/ztOXP8aIin/FyAn/xwlLP8aIiv/GSIz/xki\n        OP8aIjj/GiM5/xojOP8aIzj/GiM4/xskOf8bJDn/GiI5/xghN/8YIDD/GSMq/xoiKP8XHyT/ICs0/zBA\n        Tf8dJy7/Cw8S/wwQE/8SGBz/JTE6/yIuOP8VHSP/FBwi/xUdJd0dJi9OV2VfAi86PgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiKjMAGiUsACApMiQaIyuwFh4k/RUdI/8fKjL/JTI8/xQa\n        IP8MERT/DBAT/xcfJf8rOkX/MUJP/z5TYf9GXVz/NUdt/w8Uxv8AAPX/AgPx/wME7P8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AgL1/wEB\n        9P8HCdj/HSah/z1Scf9OaGr/UW1y/0ZfbP81SFP/KTZH/yYwSP8nMk7/JTJF/x0oMv8lMTz/MUJN/0FY\n        Zv9OaXb/U3By/0xoaP9FXnL/Ok9v/yg2e/8YIKD/DhLI/wgL1f8EBeL/AQHn/wIC8f8CAvf/AgL3/wIC\n        9f8CA/X/BAT2/wQF9P8EBfH/BAXv/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7/8EBfL/BAX1/wMD\n        9v8CAvb/AgL3/wIC9/8CAvT/AQHp/wIC5v8FCNn/DBDO/xMbov8gLIn/MUNq/0FZcv9LZWv/Um5u/1Bs\n        df9GYG//NEdT/yIuNf8bJCv/GyQt/yUwRP8sOlr/JjFG/yk2RP82SVb/SWJx/1ZyeP9RbHH/PFFx/xoj\n        nv8GB+L/AgPt/yw7nf9Qa27/Rl1r/yItNv8XHiT/GyUt/xwlK/8ZIjD/GSI3/xkiN/8aIjf/GiI3/xki\n        N/8aIzj/GiM5/xojOP8bJDn/GyM4/xoiOP8XIDb/GCIw/xskK/8bJCr/GCAm/yItNv8wQU3/HCYs/wsP\n        Ev8MEBT/ERYb/yIuOP8iLDb/Fh0j/xQbIf8XICjMHygvO06BtgAfKTEAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAdJS4AJi83ExsjLJYWHiX5FRwi/x0nL/8kMTv/FBsg/wwQEv8MDxL/Exof/yo4\n        Qv8yQ1H/P1Vi/0pjYf81RnX/DhPK/wAA9v8CA/D/AwTs/wME7P8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wMD7/8BAfb/AgLr/xMZuP8zRHX/TWVp/1Nu\n        dP9KYm//OExY/yk3R/8lMUj/JjFU/yczT/8hLTj/JTQ+/zlOW/9JY3D/UW10/1FubP9HYW3/OEt8/yAs\n        gv8QF63/CAzX/wQF5/8AAfD/AQL1/wID9f8CA/P/AwTz/wQF7/8EBez/BAXt/wQF7f8EBe3/BAXt/wQF\n        7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe3/BAXt/wQF7f8EBe3/BAXt/wQF\n        7f8EBe7/BAXy/wME8/8DA/T/AgL2/wEA7/8CA+v/Bgjb/w0Ruf8dJo3/M0N9/0JZcv9NaWf/VHF1/09r\n        ef9AV2X/LDtF/xskK/8VHCT/Iy1C/yo4Tf8mMj//KTZE/zhLWf9MZXL/VXF1/0xlbf8uPYb/Ii6c/0de\n        d/9PaXL/MEBL/xYeJP8bIyv/HCUs/xskLf8aIzf/GiM5/xoiN/8aIjf/GiI4/xoiOP8aIzj/GiM4/xoj\n        OP8aIzj/GiI4/xkiN/8ZITf/GSI4/xojMv8bIyv/GyMq/xgiKP8lMTz/MkRQ/xojKf8LDxL/DA8T/xIY\n        Hv8lMTv/Hysz/xQcIv8VHCL9GSEosiYuNiQWHiYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC43\n        PgAvOEAJHScvdBcfJfIVHCH/GiIq/yYzPP8WHSP/Cw8S/wsPE/8TGR//JjU//zBBTv89UmD/SmNg/zlM\n        df8QFMz/AAD0/wID7/8DBOz/AwTs/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO7/AgPz/wAA+f8HCdD/IS2M/0Vcbf9UcXX/T2l2/z1RXv8pNkP/JC9J/yUx\n        Tv8jLkb/ICs2/yg2Pv89U2D/TGh0/1JvdP9NaGn/Ok9y/yY1hP8UG6r/BQfZ/wEC8v8BAfX/AQL0/wIE\n        8f8DBfD/AwXt/wMF7P8EBe3/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQG7v8EBu7/BAbu/wQG\n        7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAXu/wQF7v8EBe7/BAXu/wQF\n        7v8EBe7/BAXu/wQF8P8DBPH/AwPz/wIC9f8CAvT/BAXj/w0Rtv8gLIv/NUl4/0liaP9UcXP/U3J+/0hh\n        cP8vPkr/GSEo/xMbIP8hLDr/JzRG/yc0R/8tOkn/PlNh/1BqeP9Ra3T/T2lx/1Jue/9AVWT/HSYt/xoh\n        KP8dJy7/HCYt/xskNf8bJTr/GyU5/xojOf8aIjj/GiI4/xojOP8aIzj/GiM4/xoiOP8aIjj/GSE3/xki\n        N/8ZIjf/GSI3/xkiOP8ZITH/GiMq/xskKv8aISn/JjI9/zA/TP8XHiX/Cg4R/wwPE/8UGh//JTE6/x0m\n        Lv8VGyH/FRwi+R0lLZIuOD4ULTc+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALDU7AFRaWQEeKTFQGCEo2xUc\n        Iv8XHyX/Iy85/xwlLP8NEhX/Cg8R/xEXG/8kMjr/Lj5K/zlMWf9GXV3/OEtv/xAVxf8AAfP/AgPv/wME\n        7P8DBOz/AwTs/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7/8BAvX/AQHp/xEXtf8zRHr/TGVn/1Ftdv9GXWv/MD9L/yItPv8lMUX/Iy1F/x4oNv8nNDz/O1Bc/0xm\n        cf9Pa3H/R2Bm/zFBcv8dJqb/Cw/G/wAB4v8BAfr/AQP0/wIE8P8DBe7/AwXu/wMF7f8DBe3/BAXu/wQF\n        7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG\n        7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBe7/BAbu/wQF7v8EBe7/BAXu/wQF\n        7v8EBe3/BAXu/wQF7v8EBO//AgPy/wEC+P8AAe//BgjP/xcfrv8tPIX/Rl5m/1VyeP9Vcn//R2Bv/y1A\n        S/8WICT/FR0k/yMvRf8pNU7/JjJA/zJDTv9HX27/Umx+/0pidP8mMz3/GCEn/x4nLf8dJi3/GyUy/xwk\n        O/8dJjv/HSY7/xwmOv8bJDn/GiI4/xojOP8aJDj/GyU5/xsjOf8ZIjf/GSE3/xkhNv8ZIjf/GSI3/xki\n        N/8ZITf/GiEx/xskK/8cJCv/GiEo/yczPv8tPEf/FRwi/woOEv8NERT/FyAm/yYzPP8aIin/FRwh/xYe\n        Je0eJi5tMjxBBykyOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkLDQADRccACApMDIYISjFFR0j/xYdI/8iLjb/ICw0/w4T\n        F/8LDxL/DxQX/yIuN/8tPEj/OEpX/0ZdX/84S2r/EBW8/wAB9f8CA/D/AwTs/wME7P8DBOz/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwPw/wAB9/8EBd7/HiiS/0BW\n        ZP9SbHH/Tmh2/ztPX/8lMj//JjJT/yQwTP8aJC3/Ii42/zlNW/9JZHH/T2pv/0dfZ/8vQHP/FRyt/wUH\n        1/8AAPT/AQH5/wIE8v8DBe7/AwXu/wMF7v8DBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAbu/wQG\n        7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8FBu7/BQbu/wUG7v8FBu7/BQbu/wUG\n        7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAXu/wQF7v8EBe7/BAXu/wQF\n        7v8EBe3/BAXt/wQF7v8DBPH/AQL3/wAA+P8DBeL/DxW8/yk4gP9HX2z/VHJ3/1Nwe/9DW2r/KTlB/xMb\n        H/8YIir/JDE9/ys3Tv8pOEf/PFFe/zBBTf8YHyX/HSUt/x8pMP8bJC//GyQ4/xwlO/8cJTr/HCU6/xwl\n        Ov8cJTr/HCU6/xskOf8aIzj/GiI4/xoiOP8aIjf/GSI3/xkhNv8ZITb/GSE3/xkiN/8aIjn/GyI5/xsk\n        M/8dJS3/GyMq/xkhKP8oNkH/KjhC/xAVGf8LEBL/DBAU/xwnLv8oNT7/GSEn/xQaIP8XHybcHygwTUVL\n        WwEjLDUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAaIisAJi44FhoiKqQVHSP+FRwi/yArM/8kLzr/EBYb/wsQE/8NERT/HSYt/zFA\n        S/83SFb/Q1pf/ztQZP8TGq//AADz/wIC8f8DBOz/AwTs/wME7P8DBOz/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8CA/L/AAH2/wsPyP8tPHf/SWFk/09qb/9FXGn/MD9L/yYw\n        Sf8jL0T/GyYz/yEuOf80RlP/SGFx/1Fsb/9HYGv/L0B5/xMZrv8EBeL/AAD1/wEB+f8DBPD/AwXt/wMF\n        7f8DBe3/AwXu/wMF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG\n        7v8EBu7/BQbu/wUG7v8FBu7/BQbu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQbu/wUG\n        7v8FBu7/BQbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF\n        7v8EBe3/BAXt/wMF7v8CAvb/AAD3/wID5/8NEr7/KDZ+/0Zdbf9RbnH/Tmt4/ztQYP8gLDP/FBof/xgf\n        Kv8mMkP/KDRE/xsjK/8YISb/Higv/x4oL/8cJTD/GyQ2/xskOf8bJDn/GyQ5/xskOf8bJDn/HCU6/xwl\n        Ov8bJDn/GyQ4/xsiOP8aIjj/GiI3/xkiN/8ZIjf/GSE3/xkhN/8ZITf/GiM4/xskOv8cJTP/HCUs/xoi\n        KP8YISf/KzlE/yYzPP8NEhX/DA8T/w4SFv8gLDT/Iy84/xQbIP8UGyH/GSEpwCQuNikWHScAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgy\n        PAAqND0HHygxchcfJvAVHCL/HSUt/yUxOv8TGyD/Cw8T/wwQE/8aIyn/KThE/zNFUv9CV1//PlNh/xki\n        o/8BAu//AgLz/wME7P8DBOz/AwTs/wME7P8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBOz/AwTt/wIC9P8BAe7/EBa1/zVGcv9Qamv/T2p1/z1RYP8pNUb/JC5E/yQuSf8cJTD/KDc//0Ja\n        aP9QbHT/TWhr/zZKcP8YIaH/BAbg/wEB9f8CAvb/AwTw/wMF7P8DBe3/AwXt/wMF7v8DBe7/BAXu/wQF\n        7v8EBe7/BAXu/wQF7v8EBe7/BAbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BQbu/wUG7v8FB+7/BQfu/wUH\n        7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH\n        7v8FB+7/BQbu/wUG7v8EBu7/BAbu/wQG7v8EBu7/BAbu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF\n        7f8FBez/AwXu/wID9f8BAvX/AgTo/xAVsf8tPHr/R2Bq/1Fvcv9KZXX/NEdV/xghJ/8UGiL/JC89/ys3\n        Sv8jLDr/GyUr/x0mLv8dJy7/HCUu/xskNP8bJDr/HCQ6/xwlOv8cJTr/HCU6/xwlOv8cJTr/HSY7/xwl\n        Ov8cJDn/GyQ5/xsjOP8aITb/GyI4/xojOP8aIjf/GiI4/xoiOf8aIzj/HCUw/xwmK/8ZISj/HCYt/y49\n        Sf8gKTH/DBAT/wwQE/8RFxv/Iy44/x0nLv8TGh//FR0j+xwmLZEpNDsQKDM6AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALDY/AAkSHQAfKTJEGiMq2BUd\n        I/8YIin/JzM+/xggJv8MEBP/CxAS/xQbIP8rOUT/MUJR/0BWX/9FXFz/Iy6b/wMD7v8BAvP/AwTs/wME\n        7P8DBOz/AwTs/wME7P8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTs/wME7P8DBO3/AQL2/wIC\n        6v8YH6X/P1Nk/1Fsbv9MZXT/NkhV/yYyQf8lMEv/HSU5/x8qMf84S1f/TGZz/1Bsbv89U23/ISyT/wgL\n        zf8BAfP/AQL1/wME8f8DBe3/AwXt/wMF7f8DBe7/AwXu/wMF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF\n        7v8EBu7/BAbu/wQG7v8EBu7/BQbu/wUG7v8FBu7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH\n        7v8FCO7/BQju/wUI7v8FCO7/BQju/wUI7v8FCO7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH\n        7v8FBu7/BQbu/wQG7v8EBu7/BAbu/wQG7v8EBu7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXt/wQF\n        7P8DBe//AgT0/wAB9f8EBdz/GCCg/zZJfv9KZHj/Um6A/z9WZf8RFhv/Cw8S/x8pNf8tOk3/JzI//xoi\n        Kf8cJiz/Hict/x0mLv8bJDT/HCU6/xskOv8bJDn/HSY7/xwlOv8cJTr/HSc7/x0nO/8dJjv/HSY7/x0l\n        O/8cJTn/HCU6/xskOf8aIzj/GiI3/xkhNv8ZITj/GiI3/xwlMP8cJiz/GCAm/x8oMv8vPUn/HCQr/wwQ\n        FP8NERT/FBwh/yQyO/8aIyr/Exkf/xYeJekdJy5gNkRMAyYyOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3QUEAHCYyACgyOh4dJi6zFx4l/xcfJf8kMTv/ICs0/w0R\n        Ff8MEBP/Exke/yg2QP8xQVD/PVJe/0ZdW/8tO4P/Bwnj/wEB9v8DBOz/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTs/wME7f8BAfb/AwTh/x0nlP9EW2b/Umxx/0Zd\n        bf8wP03/KTNB/yErOf8ZIiz/KDdB/0NbaP9QbHL/R2Fi/ys7g/8NEcD/AQHv/wEB+P8CA/H/AwXt/wME\n        7f8DBe3/AwXt/wMF7v8DBe7/AwXu/wMF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBu7/BAbu/wQG\n        7v8EBu7/BQbu/wUG7v8FB+7/BQfu/wUH7v8FB+3/BQjt/wYI7f8GCO3/Bgjt/wYI7f8GCe7/Bgnv/wYJ\n        7/8GCe7/Bgnt/wYJ7f8GCe3/Bgjt/wYI7v8FB+7/BQfu/wUH7v8FB+7/BQfu/wUH7v8FB+7/BQbu/wQG\n        7v8EBu7/BAbu/wQG7v8EBu7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXt/wQF7f8DBe3/AwXt/wMF\n        7/8BAvb/AAD4/xcesf9GX3P/Tmt6/0VbbP8vOUb/ERcb/wkOEP8UGyL/KTVC/yw4Rf8cJi3/GiMp/x0m\n        LP8cJi7/GyQz/xojOP8bJDr/HSY7/xwmOv8cJTr/HSU7/xwmOv8dJjv/HSY7/x0nPP8eKD3/HSY7/xsk\n        Of8aIzf/GiI3/xkiN/8ZIjf/GSE4/xoiNf8cJC7/HCUr/xkhKf8lMDr/MD9K/xQaIf8LEBP/DBAU/xsl\n        LP8lMTr/Fh0j/xQaIP8ZISfKIy00MAcRGgAxOkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAhLDUAJzM/BR4oMXUYISnyFh0j/x8pMf8kMDn/Ehcc/w0RFP8NERX/JC84/zFC\n        T/87Tlz/R2Bd/zNEef8KDdP/AAD0/wME7f8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBOz/AwTu/wEB+P8FB9j/Ii2C/0ZdY/9OaHD/Qldn/yw5Rv8oM0D/ISo1/xwk\n        LP8xQk7/SWRw/05pbP89Um3/GyWX/wQF3P8BAff/AwPx/wME7f8DBe3/AwXt/wMF7f8DBe3/AwXu/wMF\n        7v8DBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAbu/wQG7v8EBu7/BAbu/wQG7v8FB+7/BQfu/wUH\n        7v8FB+7/BQbw/wQF8v8DBPL/AwT0/wME9v8DBPb/AwT2/wME9v8DBPX/AwTz/wME9P8DBPX/AwT2/wME\n        9v8DBPb/AwT1/wQF8/8EBfL/BAbx/wUI7/8FB+7/BQfu/wUH7v8FB+7/BQfu/wUG7v8FBu7/BAbu/wQG\n        7v8EBu7/BAbu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7f8DBe3/AwXt/wMF7f8BAvX/CArj/zNE\n        k/9QbHb/Q1tq/yUwOv8wO0n/NUJR/x0mLv8KDhH/DxUZ/yYwO/8oND//ICoy/xwlLP8eJy3/Hicu/xwl\n        M/8cJTn/HCY7/x0mO/8cJjr/HCY6/xwmOv8dJjv/HSY7/x0mOv8eJzz/HSc8/x0mO/8cJTr/HCU6/xsk\n        Of8aIzj/GSE4/xoiOf8bJDb/HScu/x0mLP8aIin/KTZB/yw6Rv8RFhr/DA8T/w4SFv8fKjL/ICoy/xUb\n        If8VHCL6GiIqlSErNA4cJS0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAVHyYAIyw2PhojK9sVHSP/GiMp/yUyO/8WHiP/DREU/wwQE/8cJy7/Lz5L/zhKV/9HXWH/PFBl/xMZ\n        uf8AAfX/AgPu/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7f8DBO3/AwTs/wME\n        7P8DBO7/AAH5/wUH2P8nNHz/SmJj/01ncv8+U2P/KzhF/yYwP/8VHyf/FR8o/zVIWP9MZnH/SWNj/y08\n        dv8OEsH/AQLv/wEC9f8DBO7/AwTt/wMF7f8DBe3/AwXt/wMF7f8DBe7/AwXu/wMF7v8DBe7/BAXu/wQF\n        7v8EBe7/BAXu/wQF7v8EBu7/BAbu/wQG7v8EBu7/BQbu/wUG7v8EBvH/AwT0/wEC9/8AAfr/AQHz/wUH\n        7P8GCO//CAvo/wsP4v8NEeT/DRLn/w0R5v8OEt7/DhPS/w4T1f8NE9//DRHm/wwR5P8MEOH/CQ3j/wUI\n        7P8FB+3/AgTu/wAB+f8BAfn/AwT1/wQF8v8FB+//BQfu/wUH7v8FB+7/BQfu/wUG7v8EBu7/BAbu/wQG\n        7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQF7v8EBe3/AwXt/wIE8f8BAvH/Ii6p/09rcP9NaHf/LTtG/xYc\n        Iv8dJS3/KzZC/zRBUP8lLzr/DhQX/wsQEv8bJC3/MT5N/yk0QP8dJi3/ICkx/yAqMf8eKDX/HCY7/x0m\n        O/8dJjv/HSY7/x0nO/8dJzv/HSY7/xwmOv8dJjv/HSc8/x0nPP8dJzz/HSY7/xwlOv8bJDn/GyM4/xsk\n        Of8bJDr/HCUz/xwmLP8aIin/HCQs/zBATP8lMDn/DRAT/wsPEv8TGR7/JjM7/xslLP8VHCH/Fx8m6h4o\n        MVhibm0BRE1PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkyOwApMzsUHSgxoRcf\n        Jv0XHyX/JTM8/x8oMP8NEhX/DBAT/xMaIf8rO0b/NklW/0RaYv9DWGH/HCSo/wIC8/8CA+//AwTr/wME\n        7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wMD7v8BAfj/BgfW/yg1\n        d/9LY2T/Tmdz/zpNXf8zP0r/N0NM/yAoLf83Q0v/WnF//2uIjf9XcXn/JjOQ/wQG2/8BAfb/BATy/wMF\n        7f8DBe3/AwXt/wMF7f8DBe3/AwXt/wMF7v8DBe7/AwXu/wQF7v8EBe7/BAXu/wQF7v8EBe7/BAXu/wQG\n        7v8EBu3/BAbu/wMG7v8EBPH/AgL2/wAB+/8CA+//Bgjg/wsQ1v8SF8r/GyKz/yk2lv8uPpz/OUuE/0Vb\n        af9KYnH/TWd3/05oeP9QaXn/UGt5/1FsfP9Qa3v/Tmd3/0tjcf9IX2r/QFRv/zFBlf8sOpn/ISuj/xYc\n        xv8QFdH/CQvf/wME6/8AAPv/AQP3/wQF8f8EBu//BQfu/wUG7v8FBu7/BAbu/wQG7v8EBu7/BAXu/wQF\n        7v8EBe7/BAXu/wQF7f8EBe3/AwXv/wEB9v8UGs7/Rlx4/1Jrcf84S1n/HCUs/x0kK/8eJy//HCQs/yAp\n        Mv8zQE//LTlE/xQaHf8LDhD/GiEn/zA7Rv8lMDj/HCYt/yArMv8hLDP/Hik3/x4nPP8eJzz/HSc7/x0m\n        O/8dJjv/HSY6/xwmOv8cJTr/HCU6/xwkOv8dJjv/HSc7/x0mO/8cJTr/GyQ4/xsjOP8aIzj/GiM4/xoj\n        L/8bJCr/GiIp/yIuNv8zRFD/GyMq/wsOEv8NERX/GiIp/yYzPP8aISf/Fx8l/xsjLL0lLjYmJC01AC48\n        QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKjQ5ADhCQgMhKzRkGSIq7RYdJP8gKzP/JTI6/xEX\n        G/8MEBP/DxMX/yQvOf8xQU7/PVFd/0hgY/8oNI//BAXp/wEC8v8DBOv/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwPt/wEB+f8GB9n/KDV7/0tlZf9PaHT/Okxc/ygy\n        PP8vNj7/LjQ4/1tqcv+ivcj/s9LO/46nt/87RcH/BQbp/wID9f8GCO//Bgft/wUF7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7v8DBO7/AwTu/wME7v8DBe7/AwXu/wQF7v8EBe3/BAXt/wQF7v8DBe//AgTz/wEC\n        +f8DBOz/Cg3T/xceuv8kL53/MD2C/zxNbf9JXFr/TWJf/05kYf9OZGP/UGdm/1BkY/9PY2L/TmFf/0lb\n        Wv9IW1r/RVhX/0VYVv9IW1n/SV1b/0teXf9NYmD/TmRj/09lZf9QZWT/T2Vi/05iXP9FV2L/NkSB/yg0\n        l/8dJLX/EBTL/wMF6v8BAvj/AgP1/wQF8P8FBu7/BAbt/wQG7f8EBu3/BAXu/wQF7v8EBe7/BAXt/wQF\n        7f8DBe3/AQLz/wcJ4v80QoT/VGdg/0RTWv8iKjH/GiIo/x8pMP8fKC7/HiYy/xsjMv8eJzH/MjtK/zE7\n        Q/8cICD/DQ8O/xQYGP8mLzP/KTM6/yEqMv8gKzP/ISwz/x8pN/8fKD3/Hig8/x4nPP8eJjv/HSc7/x0m\n        O/8cJTr/HCU5/x0lOv8dJjv/HSc7/x4nO/8dJzv/HCU6/xsjOP8aIjf/GiI5/xoiNv8bIy3/GyQq/xoj\n        Kv8qOEP/Lj1I/xEXGv8LEBP/DxQY/yAqMv8iLTb/Fx4l/xgfJ/cdJzCDMTxDCikzOwAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAArNzsAICozACQvNyUdJS7BFx4k/xojKv8nMz3/GCAm/wwQE/8MERT/GyQq/zBA\n        TP82SFX/RV1g/zhKcv8MENP/AQH1/wME6/8DBOv/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7P8DBO3/AQH4/wQG2f8mMnv/SmJi/05ocv86TFv/KDI6/yIpLv8SFRf/KDI3/2h9\n        hf+duLT/fpW9/ykwy/8EBe3/BAT0/wcI7v8GCO3/BAbt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBe3/AwXt/wQF7f8EBe//AwPy/wEC9f8DBPP/CAvb/xsjrP8sOYj/OEl2/0VZ\n        W/9OY1j/TmNd/01iYP9KX2D/Q1ZZ/z1NUv86SU3/NkVO/zlHV/8/TWD/QE1i/zpIXP88S2L/P05o/z9Q\n        aP88TGL/O0pe/z1MYv89TGL/Pkxf/z1MVP86Sk7/RVZa/0xfYf9PZGT/UWdi/1FnXf9NYVj/QFFw/zI/\n        jv8iK6X/DRHQ/wQF7/8CAvX/AwTz/wQF7/8EBu3/BAXt/wQF7f8EBe3/BAXt/wQF7f8DBPD/AgL1/yMr\n        p/9OYV7/TmBh/yw4QP8ZICb/Hicu/x8pMP8eJzL/HiY5/x0lO/8bIzT/HSYw/ys2P/82Qk3/ISUr/wsL\n        Cv8SFBX/LzY7/y85Qf8eKDH/Iiw0/yEqMv8fKDX/Hyg8/x8oPv8fKD3/Hic8/x0nO/8dJjr/HSY7/x0m\n        O/8dJzv/HSc7/x0mO/8dJjv/HSY6/xwlOv8aIzj/GiI3/xoiOP8aIjP/GiMp/xkhKP8aIyr/Lz5K/yMu\n        N/8MERT/DBAT/xQaHv8lMTv/HScv/xYcI/8aJCvXIy03PgADDAApMzwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAlMDcALjpABSAqMoEYICf6Fh0j/yMvOP8jLTb/DREW/wwPE/8VGyD/Lj1I/zRGU/9BV1//QVdf/xce\n        tP8BAfX/AgPv/wME6/8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME\n        7f8BAvb/AgTh/yEtgv9IYGD/Tmdx/ztOXP8sN0D/Iyks/xMYGf8nMDX/RFVY/0dZUf9ATH3/GBzS/wEB\n        8/8FBPD/CAjt/wcH7f8EBe3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wMF\n        7f8DBe3/AwTv/wID9P8BAvX/BQbo/xAVuP8nM4v/OUp1/0dbXv9OZFX/TGFZ/0lcXf9HWF//OklT/zE+\n        Sv8yP1T/N0Rg/zpJaP84Rl3/MD5U/zI/Vv8tO0z/KjdF/yo3Rv8qNkf/KTZH/yk3SP8pNkb/KTZF/ys5\n        Sf8tO03/M0FW/zhGXP84R13/QE5t/z1MaP84RVn/OEZP/0JUXf9NYWb/UGRh/1JnWP9NYlv/QlR0/zA+\n        hv8YHqz/CQvf/wID9P8CA/X/Awbw/wQF7f8EBe3/BAXt/wME7v8BAff/ExfM/0VWbv9TZ2H/OUhP/xoj\n        Kf8dJSz/ICkv/x4nLv8dJjb/HSU7/x0lO/8dJjz/HCU3/x0mMf8pMz//ND5L/yAmKv8KDQv/EhQT/ycv\n        Mf8mMDf/ISoz/yArM/8gKzH/Hyg1/x8oPP8fKD3/Hig8/x4nPP8dJjv/HSY7/x0mO/8dJzv/HSY7/x0m\n        O/8cJTr/HCU6/x0mO/8cJjv/GyQ5/xsiN/8ZIjf/GiIw/xskKv8YICb/Hyky/zNDT/8aIin/Cg4S/w0Q\n        E/8cJi3/IzA5/xcfJf8XHyX+HygxoikzPBAiLDUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcJSsAISs1Mxwl\n        LNcXHiT/GiMr/yYzPf8TGB3/DBAT/w4SFv8mMz3/NEZU/z9UYf9GXl3/JjOR/wME7P8CA/L/AwTr/wME\n        6/8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wID9P8CAun/HCWV/0de\n        ZP9OZ3H/PlJh/ygzPf8eJCf/ExUX/yo0Of9FVlj/RVdO/yo2b/8ICcn/AQHy/wQF8P8HCe3/Bwft/wQE\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wMF7v8CA/T/AQL2/wgK\n        5f8WG7r/LTp7/0FUYP9LYlv/TWJZ/0VZWv9BUl3/OUha/zM/Uv80P17/NkVq/zRCYf8uO1H/JjND/yQw\n        Pv8oNkL/KThE/yc1QP8jMTj/Ii4z/yMvM/8jLjH/ISst/yErLv8jLjH/IzAy/yIvM/8jMTj/JzU//yo5\n        RP8qOUb/JTJA/yUxPv8tOk7/N0Zg/zxLbf9BUG3/PUxf/0JTYf9MYGf/T2Nb/1FnXP9LXmT/O0py/x8n\n        q/8KDtz/AgPz/wID9v8DBO//BAXt/wEC9v8GCOX/NEKE/1NoXv9FV1z/Iywz/xsiKf8gKTD/Hygu/x0m\n        Mv8dJjr/HSU6/x0mOv8dJjv/HSY7/xwlOf8bJC//Iy00/zQ/S/8kKi//DA0M/w4REP8iKCz/JzE4/yEq\n        Mv8hKjL/Hykx/x8oN/8fKDz/Hig8/x4nPP8dJjv/HSY7/x0mOv8dJTr/HSY6/x0mO/8cJjr/HSY6/x0m\n        O/8dJjz/HSY7/xwkOf8aIzn/GiI4/xokLf8bJCv/GSEn/ys4Q/8vPUn/FRse/wwQFP8PFBj/JDA5/x4p\n        MP8WHSP/GyQr6SAqNVEXICUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC44PQAuOT4LHigykRcfJ/wXHiX/JDE7/xwm\n        LP8NEhX/DBAT/xggJ/8vP0v/O09d/0hfYP83SXL/Cw/Q/wAB9v8DBOv/AwTr/wME6/8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AgPw/wAA7v8UG6P/Q1hk/1BocP9BVWb/KjhC/x4m\n        Kf8QExT/JS8z/0VYWv9EVk//JzJx/wcJ0f8BAff/AwTw/wQF7f8EBu3/BAXt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AQPz/wAA+f8FB+X/Fh23/zJAff9FWF7/TGFb/0pe\n        W/9AU1f/Okla/zVCXP8vPFr/NURw/zVDZ/8pNUv/ISw3/yUxO/8lMzv/IS0y/yMtL/8nMTP/KTQ0/y02\n        Nv8qNDX/JzM6/yo2Qf8qOUX/LDtH/ys6Rv8rOkX/KjhC/yg0Pv8qMzf/Ljc3/ys0Nf8oNDX/JTAx/yIt\n        MP8lMjr/JjM9/yMuOP8rOUv/NENg/ztKa/9CT3D/Q1Jp/0VXZf9KXl7/Umhd/05jYP89TXH/HiWs/wgK\n        3P8BAfb/AgH4/wEC9/8iK67/T2Ji/09iYv8uOUH/GiEo/yAoL/8gKS7/HSYv/x4nOv8eJjv/HSY6/x4m\n        O/8dJjr/HSY6/x0mO/8dJjn/GyMu/yQsNf82QU//Iyov/wsNDP8OERD/KC8y/ys1Pf8gKTL/ICox/x8o\n        Mf8eJzj/Hyg9/x4nO/8eJzv/HSY7/x0mOv8cJTr/HCU6/x0lOv8dJjr/HSU6/x0lOv8dJjv/HSY6/x0m\n        Ov8cJTr/GyQ6/xojM/8cJSz/GyMp/xslLP8zQk//LDY9/wwQE/8MEBT/GCAn/yUyPP8ZISb/Fx8k/x0m\n        L7QpND0aKTQ9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAKzU7ABUdJwAkLTVDGyQs3hUcIv8dJy//JjE7/xEXGv8MEBP/EBUa/yk1\n        QP80RVL/Qlde/0NYYf8ZIrD/AAD3/wMD7v8DBOv/AwTr/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME7P8DA+7/AAD3/w4Ts/88T2D/UGpt/0RZaf8sOUP/Hycr/xIVF/8nMDb/Q1VY/0VX\n        Tf8mMHb/BQfY/wEA9/8DA+7/AwTs/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO3/AwTt/wME\n        7f8DBO3/AwTt/wID8P8BAfn/AgPt/w8Uu/8sOH3/RVlY/0xiXf9IXFv/OktP/zI/Uv8yP2T/LDlg/y89\n        Zv8rOlX/Hyoy/yAqL/8jLzP/JTE0/ycyNP8rNTX/LDc8/ys8TP8mOUz/IzxZ/y1Ka/8rTnb/KlKG/ypV\n        iv8oVo7/KFeQ/yhWlP8nVpL/KVWL/ylTh/8rT3z/Lktr/yZAYP8lOVH/KT1O/yo4Q/8qNDX/KDI0/yQv\n        M/8kMDX/Ii4z/x8qMf8tOlT/NUNl/zNBXf88TGb/QlJi/0tdYP9SZmL/UGNa/zhHc/8ZILL/AwPp/xAT\n        zv9EVHH/VGhl/zlIT/8aIij/GyQq/x8pL/8eJy3/HSU2/x8oPf8fJzz/Hic7/x4nO/8eKDv/Hic7/x4m\n        O/8eJzv/HSU5/xsiLf8jLTT/NEBO/yIpLv8MDgz/FRcX/ygwNf8mMDj/Hygw/yApMP8fKDL/Hic5/x4n\n        PP8eJzz/Hic8/x0mO/8cJTr/HCU5/xwlOf8dJTr/HCU5/xwlOf8dJjv/HSY7/x0mO/8dJjv/HCU5/xsj\n        OP8bJDD/HCUr/xghKP8jLzj/LjxH/xEWGv8MEBP/DhIW/yMtNf8gKjL/Fh0j/xojKu4iKzRgVoeWACYx\n        OwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAJjA4ACs1PQ8dJi6ZFx8l/RcfJf8mMjz/GSEn/w0RFP8LEBP/HCUt/zFATP88Tlr/RVxb/yw6\n        g/8FB+T/AQHy/wME6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME\n        7f8BAfb/CQzJ/zJCb/9PZ2v/S2Jx/zJDTv8gKCz/DxMU/yQsM/9BUlj/RVhN/ys2b/8HCdL/AAD2/wID\n        7v8DA+z/AwPt/wMD7f8DA+3/AwPt/wMD7f8DA+3/AwTt/wME7f8DBO3/AwTt/wME7f8DBO7/AgL0/wAA\n        8v8JDM7/JC+S/z9RWP9LYFb/SFxe/zpLUf8wPEv/LTpb/y05Y/8tOmH/JDBC/xwnKP8jLjH/Iiwx/yIt\n        L/8qNTf/LTxK/yM+YP8lSXj/KleQ/yxhoP8rZaj/K22+/ypvyP8pcs7/LHTM/y91zf8vdcX/LnTB/y51\n        yv8tddL/LXTN/yx0zP8tddT/LHPL/y9yy/8xb7b/MWmr/y1dnP8lTHf/JT5g/ys8Tv8tNjr/KjQ5/yYy\n        OP8jLzT/Higs/yUxPP8sOVH/MT5c/z5Ma/9CUWH/Sl1g/1JnYf9KXF//LzqF/zZCfv9SZmP/Rlhe/yIs\n        Mv8ZICf/ICgv/x8oLv8dJTL/HiY6/x8nO/8eJzv/HiY7/x4nO/8fKDv/Hyc8/x8nPP8eJzv/Hic7/x0m\n        Of8cJC//JC83/zVATf8iJyz/DAwM/xIVFf8lLTH/JS83/x8pMP8gKjD/Hycx/x4nOv8fKD3/Hyg8/x4o\n        PP8dJzz/HSY6/xwlOf8cJDn/HCU5/xwlOf8cJTn/HCU4/xwlOf8dJjr/HSY6/xwlOv8bJDf/HSYv/xsk\n        Kv8bIyr/LDpE/ys2Pv8UFxr/Cg4S/xQaH/8lMDr/GSAo/xYeJf8cJi64JjA7HCQtNwAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApMTwAAAAAACEq\n        M0YZISnfFBog/x8qMv8gLDT/EBUZ/wwPE/8TGB3/JjI9/zREUv9DV1z/P1Jn/xAVw/8BAfb/AwPs/wME\n        6/8DBOv/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wME7P8DBOz/AwTs/wEC8/8DA9n/JzN7/01l\n        Y/9MZHL/OkpZ/yMsMP8RFBT/Hycq/z9PVf9FWE//LTps/wgL0P8AAfb/AgPu/wID7f8CA+3/AgPt/wMD\n        7f8DA+3/AwPt/wMD7f8DA+3/AwTt/wME7f8DBO3/AwTt/wME7/8BAfb/AgLx/xMarf82RWj/SV5X/0tg\n        Xf9FVl//NEBS/yw3Xf8sOGT/JzNR/yEsPf8bJij/ISot/yozOP8rNTn/KDU+/yZBYv8qVJH/MGev/y1v\n        vv8rcc7/L3fY/zJ60v8zedH/MXbP/zJ5yv8wdcP/LnHA/y5xyv8tcML/LXG//y5xwf8uccD/LnHE/y5z\n        w/80es7/OoHa/z2D4P8+huL/QIji/zSB2/8tdc3/MnHF/y9ts/8pWZL/J0Rr/yo7Sv8qNDr/KjQ4/yYz\n        N/8eKS7/IS04/yk1TP82RWX/PUxq/0dYZ/9PYmT/UWVe/1BkYf9NYWj/LzpD/xogJv8fJy7/ISkv/x8n\n        L/8eJjj/HiY7/x4mO/8fKDv/ICk9/x4mO/8eJjv/Hic7/x4nO/8eJzv/Hic7/x4nPP8eJjr/HCQv/yUw\n        OP80QEv/HyQn/woMCv8TFxf/KDA1/yQvN/8fKDD/Hygv/x4nNP8fKDz/Hyg8/x4nO/8eJjv/HSY6/x0m\n        Ov8cJTr/HCU6/x0mOv8dJjr/HCU6/xwlOv8cJTr/HCU6/x0mOv8dJTv/HSY0/x0mLf8ZIif/ICoz/zJB\n        TP8bIyj/Cg4Q/w0RFP8cJCz/Iiw1/xYcI/8aIiryISozYz5KWAImLzkAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiLTYAKzY/DB4nL5kVHCP/FRwj/yIt\n        Nv8YICb/Cw8S/wwQE/8fJy//MUBN/ztOWP9FW1v/JjSO/wID7/8CAvD/AwTr/wME6/8DBOv/AwTs/wME\n        7P8DBOz/AwPs/wMD7P8DBOz/AwTs/wME7P8DBOv/AgPy/wEB6/8cJJH/SV9g/09ncv88Tl3/JjE4/xMX\n        F/8XHR//O0tQ/0dZUv8vPGf/CQzM/wAA+P8CA+//AgPs/wID7f8CA+3/AgPt/wID7f8DA+3/AwPt/wMD\n        7f8DA+3/AwTt/wME7f8DBO3/AgPy/wEA+P8HCtP/Iy6K/0FTXf9MYVj/RFdY/zZDUP8rNVX/Lztu/yk2\n        Wv8eKTf/HScq/yIsLf8pMjf/JzM+/yc+Wv8nUIb/KmSw/zJ2zP83fd7/NH7Z/zF5z/8uc8b/MHbI/zN4\n        x/82esX/NXrL/ziC1f8zeMr/MHLB/zByxf8vc8T/L3HE/y9wwf8ucb//LnHC/zJ1xP86ftD/PYPe/z+E\n        3/8+hOH/PYPe/zR8zv8vdcj/NXzU/zSA2f8ues7/LW/B/yplrf8mU4n/J0Ri/yk3QP8rNj3/JzI1/x0o\n        LP8fKjP/KjdN/ztKbf8/Tmb/TF1r/1Bka/87SlP/HiUs/x8lLf8iKzL/ICgv/x4mNv8eJzz/Hic7/yAn\n        O/8hKj7/ISs+/yAoPf8eJzz/HiY6/xwmOv8dJjr/HSU6/x0lOv8dJTv/HSQ3/xsjLP8lLzj/NkBM/x0i\n        Jf8KCwr/GR4e/ykxOP8jKzT/ICkw/x8pMP8dJjX/HSU7/x0mOv8dJjv/HSY7/x4nO/8eJzv/Hic7/x0m\n        Ov8dJTr/HSY6/x0mOv8cJTn/HCU6/xwlOf8cJTr/HCU4/x0mMf8cJCr/GCAm/yg1Qf8lMjz/DRIV/wsO\n        Ef8UGyD/JTE6/xkiKf8WHiT/HCUuuCUxOhYeJzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZIikAICkzPBojKuETGh//HScu/x8qMf8OEhX/Cw4S/xIZ\n        Hv8sOkX/OEhW/0VbXf87TWn/DhPL/wAB8/8DA+z/AwTr/wME6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME\n        7P8DBOz/AwTs/wME6/8CA+3/AAD0/w4SuP8/UWb/U2xw/0FVZv8qNj//Fxwe/xMWGv80Qkj/RlhT/zZF\n        Xf8NEMD/AAD3/wEC8P8CA+z/AgPt/wID7f8CA+3/AgPt/wID7f8CA+3/AwPt/wMD7f8DA+3/AwTs/wME\n        7P8CA/L/AQHy/w8UwP8vPG//R1xS/0tgYP8/T1X/MTxU/y05cP8oNGn/HSg5/xslKP8hLCz/KjM4/yc1\n        Qf8rSGj/Klyd/ytrwP8xdtD/M3zT/zN6zv85f9b/NHnO/y5zxf8udML/MHrJ/zR9zP84gNL/NX7Q/zd+\n        0/82e8//NHfE/zR3xv8ydMj/MHLB/zB1xf8yc8T/NnrL/z2D1v9AhNT/PoXa/z6D3v8+hdz/PYTa/zN7\n        zf8vcsX/M3bK/zN4xv8vdMD/L3XD/zB2zP8udcr/LG/B/yhblv8rSGj/KTpJ/yk0Of8iLC7/HCYq/x0n\n        M/8vO1v/QU90/0JSZv8kLTP/GyIn/yIrM/8gKjH/Hyc0/yAnPP8fJzz/HyY7/yEqPf8jLED/ISw//yIr\n        QP8hKj7/Hyg8/x4nO/8dJjr/HSY6/x0mOv8dJTr/HSU6/x0lNf8cJSz/KDM8/zU/SP8XGhz/CgsK/x0j\n        JP8pMjj/ISoz/x8oMP8dJi7/HSM2/x4mO/8dJjr/HSY6/x4mO/8eKD3/Hig8/x4nO/8dJTr/HSU6/x0m\n        Ov8cJjr/GyQ5/xskOf8cJTn/HCU6/xskNf8cJiz/GiIn/x4oMf8vPkj/GSEm/woOEf8MEhX/Higv/yMt\n        Nv8VGyH/GSIq8iEqM1kSHCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAACs2OwAuOT4DHygxihcdJPwWHST/ISw1/xghJv8LDxL/DBAT/x0mLv8yQk//PVBb/0Vb\n        W/8gKqT/AgLw/wEC7v8DBOv/AwTr/wME6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME7P8DBOz/AwTr/wME\n        6/8BAvX/BAbW/y49cP9Ra27/TWN0/zJATf8aICP/DhAS/y86Q/9FV1f/Pk5R/xYdpv8BAfT/AQLy/wID\n        7P8CA+z/AgPt/wID7f8CA+3/AgPt/wID7f8CA+3/AwPt/wMD7f8DA+3/AwTs/wEC8/8BAe3/Fhul/zpK\n        Xf9KX1f/R1pc/zhGVf8uOWH/LDhy/yYzWv8ZIiv/Hico/yYuLv8pN0H/JkVo/ylcmv8vdc//NH3c/zJ3\n        0f80d8n/MXjE/y9yxP82fNH/N37Q/zB0xP8wc8T/NHvL/zyB0/9Bht7/N3zT/zl+1P86gNT/N33R/zR7\n        0P81ecv/NHjH/zR7zf89gNP/Q4rf/0KO5/9BieD/P4XV/z2C2v89hNv/PoTb/zqB1P80ecn/MXfI/zJ7\n        zP8tccD/L3O8/zB1wv8vdMP/L3bG/y53yP8scb//KmGj/ylMdf8pO0v/JzAx/x4nKf8aIyj/JjFD/zA8\n        YP8nMEf/Hygu/yIqL/8iKzP/Iio3/yEqPf8gKDz/HyY7/yAoPf8hKT7/ISk9/yIrP/8iLD//Iis//yIq\n        Pv8fJzz/HiY7/x4mOv8dJTr/HSU6/x0mO/8dJTX/HSUs/yw1P/8vOD//ERQV/wwNDf8jKi3/KTQ7/yAp\n        Mf8fJy7/HSUx/x0mOf8dJjv/HSU6/x0mOv8eKDz/Hig8/x4nO/8dJjr/HCU6/xwlOv8bJDn/GiM3/xsj\n        N/8cJDr/GyQ4/xojN/8cJC//HSUr/xkhKP8qOEL/JjE7/w0RFf8KDhH/FBsg/yIsNf8ZICb/Fx4k/x4m\n        L6skLzcRJC83AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMu\n        NQAjLjUwGyQr1RYbIf8eJy//JTE6/w4TFv8MEBT/EBYY/ys5RP82RVL/Q1ha/zREcv8LDtf/AQLz/wME\n        6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME7P8DBOv/AwTr/wID8f8BAe//HCSQ/0ti\n        Y/9RaXX/Pk9f/yIqL/8NDxD/JSw0/0RVV/9BUkv/HyiP/wIC8f8BAvT/AgPs/wID7P8CA+z/AgPt/wID\n        7f8CA+3/AgPt/wID7f8DA+3/AwPt/wMD7f8DA+7/AQH2/wQE6f8bIpn/P1BW/0pfW/9BUlr/MDxK/yw3\n        Xf8rN2r/HSY9/xojIv8iLC3/KTU+/yhCY/8tX5z/LXPH/zN71f81edP/NXjP/zN1yf80dsz/MHfJ/zF0\n        vv8zd8b/OoDV/zh+0P84ec3/PIDX/0GG2P9Bhdn/OX7V/z+J3f8+htz/M3fM/zF2xv82eL//NHjE/zV5\n        zv8+g9r/QIXa/z+G3/8/iOD/PoPV/z6C1/89gtj/QIXc/z+F3f83fc//MXnJ/zN8zP8vcb7/NXzN/zF3\n        x/8ucLr/LnG5/zB1xf8xdsX/MXjM/zB3y/8rZKb/KEpx/yo3Qf8mLjD/GyQl/xslL/8rN1D/MDtX/yYu\n        O/8iKjD/Iywz/yEqNv8hKTv/Hyg9/x8nO/8eJzv/ICg8/yIqPv8iKz//Iiw//yMsQP8iKz//ICk9/x8o\n        PP8eJzv/Hic7/x4mO/8eJjr/HSUy/x8nL/8xO0T/KjI3/wwNDf8RERP/KC81/ycxOf8fKTD/Higv/x0m\n        NP8dJjv/HSY7/x0mOv8eJzv/Hic8/x8oPP8fKDz/HCU7/xwlOv8bIzj/GiM3/xsjN/8aIjj/GiI3/xsj\n        N/8bIzT/HSUs/xoiKf8fKDH/MUFN/xYeJP8LDhD/DA8T/x8oMP8gKjD/FBog/xoiKeQhKjNIGSErACw5\n        PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJi83ADxCSQIeKDByFx8m9Rcd\n        I/8kLzf/HSUs/wsPEv8NEBT/HCUr/zA/TP88T1z/RFlX/x4mpv8BAfD/AgPt/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AwTr/wME7P8DBOz/AwTs/wME6/8DBOv/AwTt/wAB8/8OErL/P1Bn/1Jrc/9FWWn/KzY//w8T\n        FP8YHR//PU1S/0RVSv8pM3n/BQbg/wAB9f8CA+z/AgPs/wID7P8CA+3/AgPt/wID7f8CA+3/AgPt/wMD\n        7f8DA+3/AwPs/wMD7v8BAfb/BQbj/yIrjP9BVFb/SV5d/zxNVf8tOUv/LThk/yUwUP8XICX/GiQn/ycx\n        OP8oPlT/J1WP/y5uv/80gdn/MXvN/zZ6z/84fNH/OXvU/zd40f8ydsz/MHTE/zJ0uf80d8P/NnvU/zyG\n        3P8+g9n/PoLX/0CFzf9Bh9b/PIXb/z2H3P87gdr/MnTH/zF1xP80dsX/NnrI/zp+zf8/g9T/P4TY/z2D\n        1/8+hNT/PoTb/z2C1f8/g9P/QIXc/z2B2f83e87/NHrL/zR9yf8wcbb/OYHR/zV6x/8vcb3/L3G9/zF0\n        wv8ydL//MHXD/zR5yP8xeMr/MHbK/y1iof8qQl3/JzM6/x0pLv8XICb/JjBF/zA7Vf8nMTv/Iisw/yIr\n        Mf8hKTT/Hyg7/x8nPP8fJzz/ICk9/yEpPv8hKj7/Iis//yMsQP8iKz//ISo+/yEqPv8hKj7/ICk9/x8n\n        PP8fJzz/HiY6/x0lMP8hKjD/ND5I/yQqLv8LCgv/Fxoc/yw1O/8iLDT/Hykw/x4nMP8dJTf/HSY7/x4m\n        Ov8eJjr/Hic7/x8oPP8fKDv/Hic7/x0nOv8cJDn/GyQ4/xskOP8aIzf/GiM3/xoiOP8aITf/GyMu/xwk\n        Kv8aIyn/LTtG/yUwOf8OERX/Cw4S/xceJP8jLjb/GCEn/xcdJf0fKDGRLDg/DCcxOgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHygyACEqNRsbIyu4FR0i/xojKf8kMDr/EBUZ/wsP\n        Ev8PExj/KTVB/zREUf9AVVn/N0ls/w4R0P8BAfT/AwPr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AwTr/wME6/8DBOv/AgP0/wME1/8sOHT/UWlp/0xic/81Q0//Fhwf/w0PEf8xPEL/RlhP/zRB\n        YP8LD8n/AAD4/wIC7v8CA+z/AgPs/wID7P8CA+3/AgPt/wID7f8CA+3/AgPt/wID7f8DA+z/AwPt/wAA\n        9/8EBtr/JC99/0RYUf9KXl//O0tV/y04TP8wPGP/Ii1E/xQcIP8rOUP/OUxh/yk1Qv8oTXb/LXXH/zSB\n        2f80f9H/MXbF/zd6zf84e9T/OHzM/zV3yf8zds3/MHPA/zR3x/85fdP/NnnO/zqA1P8/hdL/P4XY/0GF\n        0f9BhtX/P4jg/z2G2/82e9D/MHTE/zB1xP8ydcb/NnnK/z6C1v8+hdj/OoHV/zV5y/81esr/OX/T/zqA\n        1P89gNX/PYTb/zZ90P8ydcX/NHnJ/zZ/zf8ydLz/OoLU/ziAz/8zdcT/MHK7/zF0v/8xdcP/MHTB/zJ2\n        xP8zd8X/NH7U/zV9zv8sV4f/KjtJ/zpLWv8yQVL/FyAm/x8oNP80QVr/KzZE/yIrMP8iLDH/ISk0/x8p\n        O/8hKz7/Iis//yEpPf8hKT7/ISo+/yEqPv8hKT7/ISo9/yEqPv8hKj7/ICk9/yApPf8fJzz/HiY8/x4m\n        Of8dJS7/Jy83/zZASP8bHiD/CgwL/xwhI/8pMjr/ICky/x4nL/8dJjH/HSY6/x4nO/8eJzv/Hic7/x4n\n        O/8eJjv/Hic7/x4nO/8cJTn/HSU5/x0mOv8cJDj/GyM4/xoiN/8aIjj/GiMz/xskKv8aIyj/Hygv/y89\n        SP8YHSL/DBAT/w4SFv8kLzj/Higw/xUcIv8bIyzQISozLxMcJwAyO0EAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAqNDkAAAATACAqM0wYICjrFBsh/yAsNf8aISj/DA8T/wwPEv8eJy7/Lj1J/zxP\n        W/9DWFb/JC+Y/wIC8/8CAu3/AwPr/wMD6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBO7/AQHx/xYdm/9HXGP/Ump3/0FTZP8gKC3/CQwM/yUuMv9DVFL/P1BO/xcdp/8AAPf/AQLw/wID\n        7P8CA+z/AgPs/wID7P8CA+z/AgPt/wID7f8CA+3/AgPs/wID7P8DA+z/AQD3/wUG3v8kL3j/RVhM/0hc\n        Xf86SVX/LjhR/zI+Yf8dJjj/FB0j/zFATP9RXnL/UV5u/z1OY/8uPE3/KEZn/y9tuP8weND/MXTH/zh5\n        xv85e8r/NnrG/zJ2x/8zdsv/MXTI/zV6zf83es//NnfG/zh5zv88gNX/PYPa/z+D1v89gM3/O4DX/zp/\n        1f80ecr/MHPC/zB0w/8wc7//MXXC/zR5zf80d8n/MHTD/y5ywf8vcb7/MHPA/zJ1xv80d8f/M3jI/y50\n        wv8ucL//MXTF/zV6x/81d8H/N3zN/zh9zf81d8D/MXO//zF1wv8xdcT/L3G9/zB1vv80ftH/NXbC/y1S\n        dv8wQ1L/QlJh/01YY/9TXm3/PEtc/xokLf8cIy//Mz9V/yw2RP8kLTT/JS4z/yEqNf8hKjz/IitA/yEq\n        Pf8hKT7/ISo+/yEpPf8hKT3/ISk9/yEpPf8gKT3/ICk9/yEpPf8fKDz/HiY7/x4mPP8eJjf/HSQs/y85\n        Qf80PkP/EBMT/w0PD/8kKy//JjA4/x4nLv8fKC//Hyg3/x4nPP8eJzv/HiY7/x4mO/8eJjr/HSY6/x0m\n        Ov8dJTn/HiY6/x4mO/8cJDn/GiI3/xsjN/8bIzj/GiI3/xsjL/8aIif/GB8l/yw5Q/8oNDz/DREU/w0Q\n        FP8ZICf/JjA6/xgfJf8WHiX3ISoyb0dPUwMrNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAgKjIAJS44CB0mLpcXHiT/Fh0j/yUxOv8SGBz/Cw4R/xAUF/8qN0D/OElX/0RYXP87TG7/EBTK/wEB\n        9P8DA+r/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8CAvT/BwjM/zJC\n        bv9Ram3/SmFy/y06RP8OERL/Fxwf/z1MT/9EVUz/Ji95/wQE5/8BAvP/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wID7P8CA+z/AgPs/wMD7P8CAfT/AwPm/yIrh/9EVlH/SVtd/zZDTP8qMkL/LjlX/xwm\n        Nf8XISr/Oklf/09aaf9PVV//TlRc/1Bcaf9EUmT/LjdC/yk+Vf8tZqX/MHfO/zV50v83e9D/NnrM/zR3\n        xP8zdcX/MnjL/zmB0P86fMn/On3R/zl9z/86f9T/PILZ/zyA1P86fMz/On7S/zZ8zv8ydcT/MXTD/zN2\n        xf8xdMD/MHK//y9ywf8vcr7/L3K9/y9yvv8vcb3/MHK5/y5xuf8vcr3/MHLB/zBywf8vcsD/L3K//zB0\n        wP8wc8D/MHPC/zBzwP8vcrz/LnG9/y5yvv8vc7//L3O9/zB6zP80dr7/L09t/zE/Rv9EU13/UFhj/01T\n        XP9PVF3/Ulxq/0JSY/8fKTT/GiIs/zA7UP8tNkX/JS41/yIrMP8hKTT/ISk8/yApPf8hKT3/ISo+/yAo\n        PP8gKDv/ICk8/yApPf8hKj//Iio//yEqPf8gKTz/Hyc7/x4mOv8eJjv/HiUz/x8oLv80P0f/KjA1/woL\n        C/8WGRr/KDA1/yErMf8eJy3/Hygy/x0mOv8eJjv/HyY7/x4mOv8dJjr/HSU6/x0lOf8dJTn/HSU5/x0l\n        Ov8cJDn/GiI3/xsjN/8bIzf/GyM5/xwkNP8dJSr/GSAm/yMtNf8xQEv/Ehgd/wsPEv8PFRj/KTU//xwk\n        LP8XHyX/HSYutiIsMxcfKC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZIS0AJS01KRoi\n        K9YVHCH/Hicv/x4oL/8PFBf/Cg4P/xgfJf8sOkX/PE9b/0VbXf8nMpH/AwTu/wID7v8DBOr/AwTr/wME\n        6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wMD8P8BAef/GyOR/0pgX/9PZXX/PE1b/xoh\n        JP8KDAz/Lzk//0VXUf8zQGD/Cw7M/wAA9/8CA+3/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wIC8v8BAe3/GyKV/0JVUf9KXV7/OUhR/ykzQP8rNEb/Fx8n/xkkL/8+TWL/UVtn/09U\n        Xv9NUlz/S1Jc/05UXf9RWmf/QlFh/yw1Pv8nO0v/Lmak/zZ+1f85ftD/OH3O/zh7zf84fc//M3vK/zh/\n        zv87gc7/QIXa/z+D2f85ftH/O4LV/zyD1/82esz/NXvN/zV6yv80dsX/MnTB/zR1vf8zc77/M3O//zJ0\n        wP8yc73/MnXA/zFzwP8xcr7/MXO9/zBzt/8vc73/MXO7/zF0wP8xdL//MXO5/zB0wP8wc8H/L3K//y9y\n        vP8vcr//MHG6/y5xuv8vcr3/MHbE/y9qrv8sR2H/NEJI/0dUX/9NVWD/TVNd/0xTXf9MUlz/TVNc/1Nc\n        aP9GVWb/Hiox/xUdJP8uOkv/LTZD/yApL/8gKi//ICgz/yAoO/8gKD3/ICk8/yApPP8hKTz/ISk8/yEp\n        Pf8hKz7/Iis+/yIrPv8hKT7/Hyc7/x8nO/8fJzz/Hyg6/x0mLv8mLzb/QkpT/ycqLP8JCwv/HiMl/ycy\n        N/8eJy//HiYt/x4lNf8eKDz/Hyg8/x4nO/8dJjn/HSU5/x0lOf8cJTj/HCQ3/xwkOP8cJDn/GyM4/xsj\n        N/8aIzf/GiM5/xwkOP8dJS//GSEo/xoiKf8uPEj/Iis0/wsPEf8OExb/HSUt/yEsNf8YICX/GiEq6yMs\n        NEkTGicAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4rMwAsPEYAIioyZhkhKPYUGyD/JTA4/xYd\n        Iv8LDhH/CxAT/yIsM/8zQ0//P1NY/z9SZ/8TGcX/AAD1/wME6/8DBOr/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AwTr/wME6/8DBOv/AwTr/wEB9f8KDr7/OUlb/1Fobf9GWmv/KjQ8/wsMC/8cIyX/P1BR/0BR\n        Tv8XHqX/AAH0/wIC7/8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AQLx/wEB\n        8P8VHJr/P1BV/0leXf87SlT/LjdH/zE8Uv8ZICr/HSY1/0RRaP9SWmf/TlNd/01TXf9NU13/TVNd/0xS\n        XP9NU1z/Tlhj/0FQYP8qMzv/JzlI/zVutP87gtr/O3/V/zl9zP85f87/NH3M/zd6zP82es3/O4PW/zyC\n        1/82ecP/OHzI/zl+0P86fc7/M3rJ/zZ8y/81ecj/NHfF/zV2wP81drv/OHm+/zd5xf83d7//NHfA/zF1\n        wv82esb/NXfC/zJzu/8yc7n/MnO8/zN0v/80dL3/MnS7/zJzu/8yc7z/MXK5/zFyu/8xc73/MXO7/zFy\n        vP8wdsP/MGut/ytEW/84Rk7/Tlxq/1BWYf9NUlz/TVNd/01TXf9NU13/TVNc/01TXP9TW2f/RFVi/xwp\n        Lv8VHST/LzxL/ygyPP8fKS7/ISow/yEpNf8gKDz/ICk8/yEqPf8hKj3/ISk9/yEpPf8hKj3/ISk9/yIr\n        P/8iKT7/Hyc7/x8nO/8fKDv/ICc8/x8nN/8eJS3/LzlB/ztESP8PEhL/EBIS/ykyNv8jLjX/Hyct/x8n\n        Mf8eJzr/Hyg8/x8nO/8eJjr/HSU5/x0lOf8dJDj/HCQ5/xwkOP8cJDn/GyM4/xoiN/8aIjf/GiI3/xoh\n        OP8bIzL/GiIo/xgfJv8pND//LjtH/w8TFv8MEBP/Ehgc/yczPf8XHyX/Fx4l+yApMIgjLDcGIio2AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAACcxOQAoMTkQHCUuphYdI/8aIij/Iis0/xIXG/8KDRD/Exkd/yk2\n        QP84Slb/Q1hY/zFAd/8GCOj/AQLx/wME6v8DBOr/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AwTw/wEB5/8eJYf/TGJe/01hb/83RlL/FRka/w4REf8yQET/RVdN/yw4bP8HCN7/AQH0/wID\n        7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+//AAH3/w4Tt/84SFn/SV1Y/z1O\n        V/8sNkH/MjxR/xskLv8VHST/P05j/1Nca/9OU1z/TVNd/01TXf9NU13/TVNd/0xTXf9MU1z/TVNd/09Z\n        Y/9BUF7/KzU+/yo/Vv80cLH/OoHW/zd5xf81ecH/M3nJ/zV4yP81d8j/NHjJ/zR4yP8zdcH/NnfF/zR3\n        xf84fs//N33M/zV4x/82eMf/NnnI/zZ5xP82eL7/OXrC/zp7yf86e8f/NnjD/zN3xP84gNH/OH/O/zJ1\n        wf80dsL/NXXC/zN1wv8ydb//MnS9/zF0v/8zc7v/M3S4/zJ0vf8xc73/MXO7/zR4xf8xcbb/K0ll/zRB\n        SP9MWmf/UFhj/05SXP9NU13/TVNd/01TXf9NU13/TVNd/01TXf9NU13/UVpk/0VUYf8dJzD/GCAm/zpE\n        Vf8tNkH/ICkv/yMrMv8hKTj/ICk8/yEpPf8hKj3/ISk9/yEpPf8gJzv/ICg8/yIqPv8iKT7/Hyg7/x8n\n        O/8fJzv/ICc8/x8oO/8eJjH/ISsx/zM+Rf8gJij/CQsJ/xshIP8oMjj/ICox/x8oLv8fJzb/Hyc8/x8n\n        O/8fJzv/Hyc7/x0lO/8eJTr/Hyc8/x4nO/8dJTn/GyM4/xsjOP8bIzj/GyM3/xohN/8aIjT/GiIq/xgf\n        JP8hKjL/MT9L/xghJv8LDhH/DxQY/yEsM/8dJi7/Fh0j/xskLMUkLzglJC83AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAERkiACUuNQAjLTQ3GiIp2RQaIP8iLDT/HiYt/w4RFP8KDRH/GSEn/zNCT/88Tlb/Q1dc/xwk\n        qv8BAPL/AgPt/wME6v8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOz/AQH0/wkL\n        yv84R17/UWdr/0daav8mMDb/CgsK/yEoLf9BUlP/PU1M/xEWrv8BAfT/AgPu/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7f8AAfb/CAnN/y88Zv9IXFT/QFFZ/zA7RP83QU//HiYv/xIa\n        IP85R1X/UFtn/01TXP9MU13/TVNd/01TXf9NU13/TVNd/0xTXf9MU13/TFNd/01TXf9OWGP/QVJj/y02\n        P/80Tmf/N3fE/zV4x/8zdsD/MnfG/zV3x/83fMv/MnbF/zJ2w/80dsP/NnjH/zR2xP82ecj/OH3M/zd5\n        yP82eMb/OHzK/zp9yf84e8b/O33M/zt/zf88f8n/PH3K/zV7yP82fsv/N3zL/zN4xP84fcv/OHvJ/zJ1\n        wf8xc7z/MnS8/zN3w/81dsD/N3nC/zp9yf82d8H/M3fF/zN3wP8uUXX/MkBJ/0ZTYP9OVWD/TFJc/01T\n        Xf9NU13/TVNd/01TXf9NU13/TVNd/01TXf9MU13/TVNc/1JbZ/9FUmP/GSMp/xwiKf83QU3/Ji83/yEp\n        MP8iKzL/ISk4/yAoPf8hKT3/ISo9/yEpPf8gKTz/ICg6/yAnO/8gKDz/ICk8/yAoO/8fJzv/Hyc7/x8n\n        PP8fJzj/Hicv/yszO/82QET/FhkY/w0PDv8mLjD/JzA3/x8pL/8fKDH/ICg6/x8oPP8fJzv/Hic6/x0l\n        Ov8dJjr/HSY6/x4nO/8eJjr/HCM4/xsjOP8cIzj/HSQ4/xsjOP8bIjj/GyIu/xkhJ/8ZISn/LTtH/yQv\n        N/8LDxH/DA8S/xYcIf8kMDj/Fh0j/xsjK+ojLTVSJC82AB0nMQAAAAAAAAAAAAAAAAAAAAAAISoyADE7\n        PwIcJS5rGB8l8hYdIv8iLDX/GB8k/wsOEf8QFBn/JC43/zREUP9AVFb/PE5n/wwO2v8BAfP/AwTq/wME\n        6v8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME6/8DA+//AAHv/xgghv9LYGT/Umh1/z5O\n        Wv8UGBr/EhQV/zhGSv9DVUn/JC2D/wIC6P8BAvL/AgPr/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wEB9f8DBOH/JS90/0ZaS/9EVV3/MDxG/y85Rf8mLjj/FBsi/zxJWv9SW2n/TlNd/0xT\n        Xf9MU13/TFNd/01TXf9NU13/TFNd/0xTXf9MU13/TFNd/0xTXP9NVF3/Ul9r/0ZVZ/88Q0z/MFN3/zR2\n        w/81fc//M3nI/zV4x/83esn/NHfF/zV4xf80d8T/NHbE/zR3w/8zdsX/N3vK/z6A0P87fcz/On3M/zyA\n        zf8/gs//QILT/z1/zP88fsn/PoHQ/zl/zv87fcj/OXvH/zR4xP87gc//PoHQ/zd5xf82d7z/Nne+/zV4\n        w/81d8P/N3jB/0CD0f8/gc//N3vK/zBdjf8yQk//Sllm/09YYv9MUlz/TFNd/0xTXf9MU13/TVNd/01T\n        Xf9NU13/TVNd/01TXf9MU13/TFNd/01TXf9RWmb/PkxZ/xYfJf8iKjD/NkFN/ykxOv8iKzH/ISo0/x8n\n        Ov8hKTz/ISk9/yEqPv8iKj7/ISk7/yAnO/8gKDz/ISk9/yEqPf8gKDz/Hyc7/x8nPP8gKD3/ICg1/yAo\n        L/8+SE//MTc6/wgLCf8XHR3/LTc+/yApMP8fKC//Hyc3/x4nPP8eJjr/HiY5/x0lOf8cJDj/HCM4/xwk\n        Of8dJTr/HSQ5/xsjOP8bIzf/GyM4/xsjOP8cJDn/HCMz/xwkK/8YICX/JC84/y06Rf8SGBz/Cw4Q/xMa\n        Hv8kLzf/GSIo/xkhKPweKDGOJS85CyIsNgAAAAAAAAAAAAAAAAAAAAAAJS41ACkzORIcJS2jFRsh/x0l\n        LP8gKTH/DhMW/wsOEf8VGyH/LjxH/zdHUf9DVln/KjWG/wQE6f8CAvD/AwTp/wME6v8DBOv/AwTr/wME\n        6/8DBOv/AwTr/wME6/8DBOv/AwTr/wME7P8BAvL/BQbQ/zZGZf9RZ2r/TGJz/ykyOf8LCwv/Ji4x/0JS\n        UP85Rlb/DxPA/wAA+f8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AQLw/wAA\n        8f8WG57/QFBP/0ldXv83RE7/LjdC/ys0QP8SGB3/MTxJ/1Bda/9OVF7/TFFb/0xTXf9MU13/TFNd/0xT\n        Xf9MU13/TFNd/0xTXf9MU13/TFNd/0xTXf9MU13/TVRd/01aaP86R1n/KTVB/zJjmv83f9T/M3jG/zZ4\n        xv84esf/N3nH/zZ4x/81eMb/NnjE/zd6xP80eMX/NnnG/zp/z/8+g9P/O4DR/zuB0f89f8v/P4HM/z+A\n        y/8+f8v/Pn/N/z2Az/8+gdH/P4PT/z6D0f9DiNj/RIfZ/zyAz/8+gMT/Pn7E/zp+zP87fs3/O3zI/0KH\n        1v8+hdj/M2qn/zBGV/9CUV3/UVtm/01TXf9MU1z/TFNd/0xTXf9MU13/TFNd/0xTXf9NU13/TFNd/0xT\n        Xf9MU13/TFNd/0xSXP9NU1z/U11q/z5MW/8UHCL/LTZA/zQ+SP8kLTP/JS00/yIqNv8iKj7/Iyw//yIr\n        Pv8iKz7/Iyw+/yMrP/8iKj7/Iio+/yIqPv8iKj7/ISk9/yApPf8hKj7/ISk7/x8nL/8oMTj/ND5E/xYZ\n        Gv8NDg7/JCww/ycxOf8eJy7/HiYw/x4mOf8eJjv/HiY6/x0lOf8cJDj/HSQ6/x0mOv8dJjr/HSU5/xwk\n        Of8cIzn/HCM4/xsjN/8cJTn/HSU5/x0mLv8aIyj/GyQr/y48R/8cIyr/Cw4P/w4SFv8eJi7/ISw0/xcd\n        JP8eJy/DJzE6ISUuNwAAAAAAAAAAAAAAAAAhKzIAICcwACIpMi4bIyrQExke/x8oMP8eJy7/Cg0Q/wwP\n        E/8bIyr/MkFO/z1OVP9AU1r/FBm8/wAA8/8DA+z/AwTq/wME6v8DBOv/AwTr/wME6/8DBOv/AwTr/wME\n        6/8DBOv/AwTr/wID7v8AAPH/FhyR/0ldYv9RZnL/Pk5d/xUYGv8NEBD/NUJF/0NTSP8lLYT/AgPu/wEC\n        8f8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+7/AAD2/wkMwf80QVn/SVxW/0BO\n        V/8vOEH/NkBK/xYdI/8iLjf/Slln/1BXYP9MUVv/TFJc/0xSXP9MU13/TFNd/0xTXf9MU13/TFNd/0xT\n        Xf9MU13/TFNd/0xTXf9MU13/TFFb/05VXv9LW23/MjxL/ypCWf82c7z/NXzN/zd7xv84esH/NnvI/zR5\n        yP8zdsL/OHvH/zl/zv82ecb/NHjE/zZ6yP88gdP/PIHS/zp9y/87e8T/PX3J/z6A0P9Ahdb/P4XV/z2B\n        0P8/gtD/QInb/0SQ4/9Fj+L/PIPV/ziAz/9AhMz/P4HK/z+D0v9Bg9H/QIPR/0OL3v86fMn/LUxt/zxK\n        Vf9QXGn/TVNd/0xSXP9MU13/TFNd/0xTXf9MU13/TFNd/0xTXf9MU13/TFNd/0xTXf9MU13/TFNd/0xS\n        XP9MUVv/UFZg/1Nicv8qOUL/FRog/zhCTf8zPUb/JC00/yUuNf8kLT3/JS5C/yQtQP8jLD//JCw//yQs\n        P/8kLED/Iyw//yIqPv8iKj3/Iis+/yIrPv8iKj3/ICg8/x8nNP8fJy3/NT9H/ysxNP8MDQz/GRwe/yw1\n        PP8fJy7/Hyct/x4mN/8eJjv/HSU5/x4lOv8eJzr/Hyc8/x4nO/8dJTn/HCQ4/xwkOP8cJDj/HCQ4/xwk\n        OP8cJDj/HCQ5/xsjMf8cJCn/GB4k/yk2QP8kLzf/DhEV/wsOEP8aISj/Iy43/xYcIf8cJSzoIi01Shkj\n        KwAjLjcAAAAAAAAAAAAmLjYAWGFmAR8nL10YHyXwFR0i/x4nL/8YHyT/DA8S/w8UF/8mMDn/MkBL/0FU\n        Vv8zQnL/CQzd/wAA9P8DA+r/AwPq/wMD6v8DBOr/AwTr/wME6/8DBOv/AwTr/wME6/8DBOv/AwTq/wID\n        8f8BAtn/Lzty/1FnZ/9NYXP/KzU9/wgJCP8gJyr/QFBM/zlHVP8PE7f/AAD5/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wID7P8CA+z/AgPs/wID6/8BAfP/AgLk/yUvcP9FWEz/SVlf/zU+SP81P0r/Hycu/xQc\n        If8mMj3/PUpZ/1BXYv9NUlz/TFJc/0xSXP9MUlz/TFNd/0xTXf9MU13/TFNd/0xTXf9MU13/TFNd/0xT\n        Xf9MUlz/TFJc/0xRWv9RWmf/RVRr/ykyPv8vVoH/NXvM/zuA0f88fMj/NnrH/zR5xv81d8T/OnzJ/zt9\n        xP85ecP/OHzJ/z1/zv8+f8//OnzK/z1/zv8/gM7/PX/N/z6A0P8+gdD/PIDP/zyD1f8/hNL/O4LR/zyF\n        1/8/htf/N3nE/zR3wP86fcj/O33G/z1+xv89fcT/P4PR/0WM3v81Zp7/M0JR/05ca/9QVmD/TFFb/0xS\n        XP9MUlz/TFNd/0xTXf9MU13/TFNd/0xTXf9MU13/TFNd/0xTXf9MUlz/TFJc/0xSXP9OVF3/TVdi/zM/\n        Sf8nMzr/GyQq/x0lLP88SFP/LTY//yYuNf8lLjj/JCw//yQtQP8kLUD/JC1A/yMsP/8kLED/JCw//yMr\n        Pv8iKj3/Iio9/yIqPf8hKD3/ICc8/x4nOP8fJi7/JzA3/zhCR/8VGRr/DQ8O/yQsL/8oMTn/ICgu/x4m\n        Mf8eJTr/HSU6/x4lOf8fJzv/Hic7/x0lOv8dJTn/HSU5/x0lOf8dJTn/HCQ4/xwkOP8bIzj/GyM5/xsj\n        NP8cJCr/GSAl/yUwOf8uO0f/Exgd/wsOEf8WHCL/Ii01/xojKP8aIir8ICozgSo3PwUjLjcAAAAAAAAA\n        AAAmLjYALzhAByAoMI8WHCL/GiEn/yApMf8PEhb/DA8S/xAWGv8uPEb/OEdS/0JVUv8kLo//AwPo/wIC\n        7v8DA+r/AwPq/wMD6v8DA+r/AwTr/wME6/8DBOv/AwTr/wME6/8DBOr/AwTr/wAA9/8MD63/QVFl/1Rp\n        c/9CUmD/Fhoc/wsNDv8xPUH/Q1NJ/ygzcv8BAur/AQHy/wID6/8CA+z/AgPs/wID7P8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wIC7v8AAPX/DxSo/z5PUf9GWlv/OEVO/yw1Pv8nMDj/FBof/yUxOv8lLzn/Iyw3/0FN\n        Wf9QV2H/TVJc/0xSXP9MUlz/TFJc/0xSXP9MU13/TFNd/0xTXf9MU13/TFJd/0xSXP9MUlz/TFJc/0xR\n        W/9OU1z/UF5w/zlFWv8tPEn/NnKy/zyC1v87e8n/OHvH/zd5xf87fsv/PoHQ/zx+y/86e8f/OXvI/zuD\n        0f86fcv/NnnF/zyAzv88fsr/PH/K/0WH1/9Bg87/PHzA/zx/zP8+gcv/OHnF/zR1v/82eMH/OHnD/zV1\n        vP81db7/OHnA/zl6wv83d73/O4DP/0CCzf8wSmf/QExc/1Ndaf9MUVr/TFJc/0xSXP9MUlz/TFJc/0xT\n        Xf9MU13/TFNd/0xTXf9MU13/TFNc/0xSXP9MUlz/TFJc/05SXP9QV2L/O0dS/xggJf8eKzX/KTY//xUb\n        If8hKTH/MTtF/ygwN/8mLzb/JCw6/yMrP/8kLD//JS1A/yUuQP8lLUD/Iy1A/yMsQP8kLED/Iyw//yMr\n        Pv8iKT3/ICg8/x4nO/8gKDP/ICku/zZAR/8mLjH/CwsM/xkeH/8pMTj/Iisy/x8nLv8fJzn/HiU6/x4l\n        Of8eJzv/Hyc7/x4nO/8dJjr/HiY6/x4mOv8eJjr/HSU6/xwkN/8bIzf/HCQ5/xwjNv8cJCz/GiIn/x8p\n        MP80Qk//GiEm/wsPEv8PExf/Iiw0/yErM/8YHyb/ISs0syk0PQ0lLzgAAAAAAAAAAAAfKDAAICoxGR0l\n        LcEVGyD/HCQr/yMsNP8NDxL/DA8S/xgfJv8wPkn/PE5W/0JVU/8aIbb/AAD3/wMD6/8DA+r/AwPq/wMD\n        6v8DBOr/AwTr/wME6/8DBOv/AwTr/wME6/8DBOn/AwPv/wAA7P8gKIT/TWBc/1NpeP84RlD/CQoL/xkf\n        Iv89S0r/PUtQ/xIXsP8AAPX/AgLt/wID6/8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+z/AgPr/wEB\n        9P8EBtn/KzZm/0ZZU/9CU1v/MDpD/ygxOv8WGyH/HSQo/yk+VP8jT4H/Gy9E/yYuM/9JVWD/UFZg/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUFr/UVpl/0hY\n        cf8vNkP/MFV3/zqA0P88fs7/OXvG/zZ6xv88gc//PYHQ/zx/zP84esf/NXbE/zZ8yv84esf/OHvI/zp/\n        zP87fcf/PH7J/0KG1/9Bg9D/PH7E/z6AzP8/f8j/OnrB/zZ1vP82dr3/N3m//zd4wP84d77/OXrE/zh7\n        x/84eMH/O3/O/zRil/8zQE//TFho/09UXv9MUVv/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TVJc/1FYZP9CTlr/HCEj/xkkMf8lUYb/LEhk/yQrLf8VGyD/KTQ7/ys0\n        Pv8oMTf/JCw1/yMqO/8jLED/JC1A/yUtQP8lLUD/JC1A/yQuQf8lLkH/JS1B/yQsQP8jLD//Iys+/yAo\n        Pf8hKTn/ICgu/ykzOf83QUb/ExUW/w0QDv8mLjL/JzI6/x8oL/8gKDX/Hyc7/x4mOv8eJjn/HyY6/x8n\n        O/8eJjr/Hic6/x4mOv8dJTn/HiY7/x4mOf8bIzj/GyM3/xskOP8cJDH/HCQp/xsjKf8wPkn/Iy00/w4S\n        Ff8LEBL/Hygv/yErM/8WHSP/Hykx4iQvOC4gKzIAAAAAAAAAAAAXHyYAHicwPhkgJ+EWHSH/Hykw/xwj\n        K/8NEBT/DRAT/yItNf8vPUj/P1FS/zhHZ/8QFcv/AAD0/wMD6v8DA+r/AwPq/wMD6v8DBOr/AwTr/wME\n        6/8DBOv/AwTr/wME6v8DBOn/AQH2/wYHw/81Q2r/VWpv/01hcP8kLTL/BwgI/ycxNv9CUkz/MDxm/wQG\n        5v8BAfL/AgPr/wID6/8CA+z/AgPs/wID7P8CA+z/AgPs/wID7P8CA+v/AgLv/wAB9P8XHo7/QVJN/0ZZ\n        W/82Q0r/KjQ+/xkhKf8XHSH/LDdA/yxVhv8wetL/I0+G/yQqL/8wOkD/SlVh/09VXv9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUVv/TlNc/1Bddf8zPVP/KjdD/zt4\n        vf9AhNL/PH7K/zZ5xf83ecb/OHrF/zx8w/87fMX/N3nF/zV4xv82d8P/N3e+/zd5wv88fcX/QIHM/zx/\n        y/88fcj/O4DN/z2Czv9AgMn/OnvF/zZ2wf82dr7/NXa7/zh4v/87er7/OnvC/zp8xf85e8T/N3e//y1F\n        YP9ATV//U15q/0xRWv9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9NUlz/UFhi/0RQXf8iKS3/FRse/yVNff87hd3/MGOd/yo3Qv8cISX/GyIo/yw4Qv8nLzb/JS40/yIr\n        N/8jKz7/JCw//yQsP/8kLUD/JS1A/yUuQf8lLUD/JSw//yMsP/8jLD//Iyw//yMrP/8hKT3/ICgy/yIq\n        MP82QUb/JCkq/wsLC/8gJyj/KTM6/yEpMf8gKDL/ICg7/x8nO/8eJTn/HiU5/x4mOv8eJjr/Hic6/x4m\n        Ov8eJjr/Hyc7/x4mOv8dJTr/GyM3/xsjN/8bJDT/HSUq/xsiKP8pND3/LDhC/xAUGf8LEBL/GSEm/yIr\n        NP8ZHyX/GiMq9B8qNFwWHyMAAAAAAAAAAAALEhkAIiszZRgfJfYZICb/Iy42/xAVGf8MEBP/DhIU/yk1\n        Pv8zQk7/QFNL/yg0hf8DBOb/AQHv/wMD6v8DA+r/AwPq/wMD6v8DA+r/AwTq/wME6/8DBOv/AwTr/wME\n        6v8DBOv/AAH2/xMYpv9GWFr/VGl3/0FRXv8OEhT/EBQW/zZDRf9AUEv/HSWQ/wEB8f8BAu//AgPq/wID\n        6/8CA+z/AgPs/wID7P8CA+z/AgPs/wID6/8CA+v/AAH2/wYHz/8vPGH/SFpT/z5NVf8sNz//Ii02/xEZ\n        Hv8lLDH/KUBZ/zBzwP83ftH/MHHA/yhIa/8cIiX/MTtC/0xXYf9NU17/S1Fb/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFFZ/1Jcaf8/S2T/KDA8/zRdh/9DhdH/QITT/zp9\n        yv85esT/OHnB/zp6wv84ecH/OnrC/zh6wv83d8P/OnrB/z19yP9Cgcv/RITM/z19x/88fMP/PX3G/z+A\n        yv8/gMf/OXrE/zZ3v/82drv/N3W7/zd5wf87fcb/P3/J/z+Cz/88gM7/M2KU/y05SP9MWm7/UVlj/0tR\n        Wv9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/01SXP9QV2L/RVJf/yQr\n        L/8WGRj/HzpY/zR2wf9Bi97/On/K/ytKav8oMDb/FBsg/yItNf8qNT3/JC0z/yMrM/8iKjr/JCxA/yQs\n        P/8kLD//JCw//yQsP/8kLUD/JC1A/yUtQP8kLD//JCw//yQtQP8jKz//Iis4/yAoLv8tNz3/ND1B/w0N\n        Dv8RFBT/KDE2/yQtNf8fJy//ICg3/yAoPP8gJzv/HiY6/x0lOf8dJTn/HiU6/x4mOv8eJTn/HiY6/x4m\n        Ov8eJjr/HSU5/xwkOf8cJDb/HSUs/xoiKP8hKzL/MkBM/xMZHf8MEBL/EBUY/yUvOf8fJy7/GSAn/CAq\n        NIgAAAAAAAAAACUtNAAnMDcDISoykxceJP0ZICf/JC43/w0RFP8MDxL/Fh0h/y06RP86S1f/QVRM/yAp\n        nv8AAPb/AgLr/wMD6v8DA+r/AwPq/wMD6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6v8CA/H/AQLc/yQt\n        f/9RZ2b/UmZ3/zA7Q/8HCAn/HSUp/0FSTf86SE3/DhLL/wAA9f8CA+z/AgPr/wID6/8CA+z/AgPs/wID\n        7P8CA+z/AgPs/wID6/8CAu3/AQH0/xcckv9AUUj/RFZb/zZBSP84Q0v/LDY8/zE5Pf88SFT/KliS/zN9\n        0P82e8r/On7Q/zBwvP8jP2H/Ki8w/0NOU/9TXmr/T1Vf/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFFb/1BXYP9JWHP/KjE9/yxATv9Bgcn/PYLT/zh5w/84ecX/O4HN/zh9\n        yf82eMP/N3a//zh4wv86esT/P4HM/0OG1P9GiNb/S43c/0aJ1/88gMr/PH3H/zx+yP85er//N3jC/zh3\n        vf83drr/N3W6/zh4wf8/gtH/QYLP/0SH2P8+gtH/LUli/y80QP9RXm7/TlVe/0tRW/9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TVNd/1BYYv9FUl7/JSsx/xYXFP8eNk3/Lmuv/z2C\n        zP88gMr/QIXQ/zNppf8uPk3/HiUm/xceIv8pMzr/JC00/yMrMv8iKjb/JS1A/yUtQf8kLD//Iio9/yMr\n        Pv8kLD//JS1A/yUuQf8lLkH/JC1A/yQtQP8kLD//Iio8/x8nL/8mLzX/NT9E/xccHP8LDAz/Jiww/yYv\n        Nv8eJiz/HiYy/x4mOv8eJTr/Hyc6/x8nO/8eJTn/HSU5/x4lOf8eJTn/HiY6/x4mOv8eJjr/HiY6/x0l\n        Ov8dJDf/HSQv/xsiKP8dJSz/MT9K/x0lLP8NERX/DRAT/yUvOP8hKTH/GCAm/yEsNrsoMzsPKDI6AB8o\n        MQAfKDEbHScvuhgeJf8cJCr/Hyct/w0QFP8MDhH/ICkw/zI/S/9AUlf/PE5k/xQav/8BAPP/AwPq/wMD\n        6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6f8BAvX/BAbH/zM/YP9VanL/T2Ny/xoh\n        JP8JCwz/KzY6/0NTTP8pMnr/Bgfn/wAB8f8CA+v/AgPr/wID6/8CA+z/AgPs/wID7P8CA+z/AgPr/wID\n        6/8BAfX/BQbN/yw3X/9GWFP/PEtT/zE6Qf9ASlD/OEBC/1hhZ/9LY3//MXC8/zR5x/80dcP/O3/P/z2F\n        2f84dsX/Old7/z9GSP9LVVj/TVZf/01UXv9NU13/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJb/05TXP9NWXH/MjlI/ycyN/86bqX/PILS/zh5wf89fsn/O3/N/zl5w/84d8H/Nna9/zd3\n        wP84eL7/PX7E/z5+xv9AgMn/SIzb/0mM2f8+gMv/O3rB/zt8yP84ecT/N3jC/zZ2u/83drn/OHe7/zp5\n        wf9Ehcz/RYbN/0KH2P84drz/JzlK/zY9TP9SWmf/TVNb/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xS\n        XP9MUlz/TFJc/0xSXP9OVF7/TlZh/0FLVP8jKCr/FhcT/xwzSv8sZ6n/O4HO/z6BzP87gc3/P4TS/zuC\n        1f8tTW//LDI0/xEUFP8dJCf/KTM7/yUtM/8lLTX/JS08/yQsQP8kLD//Iys+/yMqPv8jKz7/Iyw//yQs\n        P/8kLD//JCw//yQsP/8hKTz/ICc7/yAnM/8iKS//MTxC/yozNP8KDAz/Gx8g/ys0O/8iKzH/ICYx/x0l\n        OP8eJTn/HiY6/x4mOv8eJjr/HiY6/x4mOv8eJjr/HiY6/x4mOv8eJjn/HSY5/x0lOf8dJTr/HSU0/x0k\n        Kv8cIyv/LDhE/yg0Pf8PExb/DRAT/x8pL/8gKTD/GSEn/x8oMtYiKzYvIis2ACApMwAgKTM1HCQs1xce\n        Jf8hKjL/GSAl/w4RE/8MDxH/JS84/zZFU/9CVFL/NUN3/wgK2/8CAe7/AwPq/wMD6v8DA+r/AwTq/wME\n        6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6/8BAvL/DxKt/0NTUv9Uanf/P09a/wwODv8SFxj/OUdI/0BP\n        R/8WHKv/AADz/wID7f8CA+v/AgPr/wID6/8CA+z/AgPs/wID7P8CA+v/AgPr/wID7f8BAfH/FBid/z5O\n        RP9FVl3/N0JK/yYvNv8dIyX/QkpM/1tncP87aJ7/MXfF/zR2wP8zdsH/PYXU/z+D0/8+gtf/P4DU/zdZ\n        hv8mLC3/Ki0s/0JLUv9PVmH/TVNe/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/01S\n        W/9OWWr/OkJZ/yUsNv8yXo3/PYXW/zd3vf88fMb/PH/M/zl5wv88ecD/OXnA/zh3vv86eL//PHvC/zx8\n        xP9Af8X/QoTQ/0KEzv89fcf/OnrC/zt8x/84ecD/OXe8/zZ3wP84drj/N3e8/zd3v/89fcL/QYHG/z2B\n        zP8yZJj/JC84/0FLX/9TW2f/TFJa/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TVJc/09W\n        YP9MVV//OEFI/xwfH/8XGxr/KUho/zl5wf84f8//P4LN/zt+yP82fcn/PILP/zyF1/8waan/LjpH/yQm\n        Kv8VGRr/JzA2/ygwN/8mLTT/JCw3/yMrPv8jKz7/Iyo9/yIqPf8jKz7/Iys+/yQsPv8jKz//Iys+/yIq\n        Pf8gKTv/ICg8/yIpOf8hKTD/Lzg//zQ9Qv8PExP/DhAR/yoyN/8kLTP/Hycu/x4mNv8eJTr/HiU5/x4l\n        Of8eJTn/HiY6/x4mOv8eJjr/HiY6/x4mOv8eJjr/HiU5/x0lOf8dJTr/HSU2/x8nLf8cJCv/KTQ+/zA+\n        SP8PExb/DRAT/xgfJP8kLjb/GiIo/x0mLugiLTZMIi02ACQsNgAlLTZRGiIq6hceJP8kLjb/Exgc/wwQ\n        Ev8QFBj/KzZA/zpKWP9DVU7/LjqF/wME8P8CAur/AwPp/wMD6v8DA+r/AwPq/wMD6v8DBOr/AwTq/wME\n        6v8DBOr/AwTq/wME7/8BAeX/HCKM/1BkZP9TaHf/LTc+/wcIB/8bIiX/QVBN/zdGWf8PE8v/AAD1/wID\n        6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wEC8/8BAtn/Iyxu/0daUf9DU1n/LjhA/yIq\n        L/8MEA3/PURK/1JphP8zcrb/MnnJ/zd4xf8ydsT/OYLT/z1/0P9Cg9H/SI7l/zp90P8kUoT/Gycw/yUo\n        Jf88Q0n/TFVf/09WYP9NU13/TFJc/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/01SW/9RWmP/Pkde/yYr\n        M/8xVnv/QI7m/zl/zP86fs3/PYTX/zyB0f87gMz/O4DP/zt+y/89gdD/RIvd/0CE0v9AhdH/RIjW/0SI\n        1/9Dhtb/QYbY/0KJ2v88gM3/On7K/zl/z/85fMT/P4bV/zyE1v85fcv/RIvc/0OP4/8yW4b/Iygr/0VQ\n        Yv9RWGT/TFJa/0xSXP9MUlz/TFJc/0xSXP9MUlz/TFJc/01TXf9PVF//UFdi/0ZQWP8tNDj/GBsY/xke\n        Hf8iR23/PIjd/1Oh9/9Citv/QojY/zyBzP8weMb/MnjH/zZ7x/8zecT/LlB0/zA0PP8TFBb/Iiot/yoz\n        Of8kLTL/JCw0/yMqO/8jKj3/JCs+/yQrPv8jKz7/JCw//yQsP/8kLD7/JCw//yIqPf8iKj3/Iyo9/yMq\n        PP8jKzP/KDE4/zY/Rv8dIyT/Cw0N/yMpLP8mLjX/Hycs/x0lM/8eJTr/HiY5/x4lOf8eJTn/HiY6/x8n\n        Ov8fJzv/HiY6/x4mOv8eJjr/HSU5/x4mOf8eJTr/HiU3/x8mL/8dJCv/JS84/zNBTf8SFhv/DBAT/xIW\n        Gv8nMjv/HCMq/xsjKvkiLTVrICszACIpNAAkLTZvGSIp+hYdI/8lMDn/ERYa/wwPEf8VGiD/KzZA/zxM\n        WP9EVlf/JzGa/wMD8/8DA+n/AwTp/wMD6v8DA+r/AwPq/wMD6v8DBOr/AwTq/wME6v8DBOr/AwTp/wID\n        8f8EBdT/KzZj/1Nobv9OYXD/HCEl/wcIB/8nMTT/QlFJ/yo1dv8GCN7/AQLy/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AgPr/wID6/8CA+v/AgPr/wAB9v8MD73/NkNK/0ZZWP87R03/KTE3/xYbHP8aHib/MjhG/zFa\n        jf8zecr/NnjG/zyA0P80ecf/O4LR/z2AzP9DhMz/R4rc/0iQ5P8+ieD/J16c/x0vP/8fIiD/MDQz/0RN\n        Vf9NVmD/TlVg/05UXv9NUlz/TFJc/0xSXP9MUlz/TFJc/0xSW/9NVF7/RE9r/yswOf8tQU//OGWW/zNc\n        hv8yWYL/M1uE/zRdh/8zW4X/NFyG/zRbhv81XYj/OmSQ/zdfiP83YYz/OWKM/zlhi/87Yoz/OWKO/ztn\n        lf83YYz/NFuE/zRbhv8zWYP/NmCN/zZgi/8zWoP/OWOO/zpomf8uR17/Jy0x/0pVaf9PVmH/TFFa/0xS\n        XP9MUlv/TFJc/01TXf9OVF7/T1Vf/09XYf9LVF//OUJJ/yElJf8XGBX/Gyw7/ydWhv83e8n/PYzl/0aR\n        5P9Ditr/QYbV/0GI2P80esn/MHO//zJ0vP81fc3/Mmqp/y42QP8kJy3/ExYY/yQsMf8mLjX/JCwy/yMq\n        N/8jKj7/JCxA/yQrPv8jKj3/Iys+/yUtQP8lLUD/JS1B/yMrPv8iKj3/Iys+/yQsP/8lLTj/Iywz/zdB\n        SP8pLzL/CgsK/xgbHv8sNDv/Iiow/x4lMf8fJjn/Hyc6/x8mOv8eJTn/HiY6/x8nO/8fJzv/Hyc6/x8m\n        Ov8fJzv/HSU6/x4mOv8eJjr/HiU4/x8mMf8eJSz/ICkx/zNBTf8bIin/DA8T/xEUGP8nMjv/HCQr/xkh\n        KP8jLDaTNkJHBiMrNQogKTKSGiEo/xsiKP8iLDP/EBUa/wsOEP8bIij/LjpF/z5OVf9AUWL/GR+z/wEB\n        8v8DBOr/AwTq/wMD6v8DA+r/AwPq/wME6v8DBOr/AwTq/wME6v8DBOr/AwTq/wIC8v8LDsP/O0pW/1Nn\n        cP9DVF//EhUW/wwOD/80QUb/Q1JD/x0km/8AAPH/AgLt/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AgPv/wEB6v8aIIv/QlRM/0RVWf8zPEP/Ji4z/w4REP8kJjH/Lj9e/ylipP8zecj/NnfD/zt9\n        zP87fcr/QYLQ/z6Azf9Cg8//Q4XU/0GE0v9Ag9L/OH3O/y5nqP8gQ2f/GyYu/yImJP8zOj3/RE5X/0xU\n        Xv9OVWD/T1Zh/05UX/9NU13/TVNd/0xRW/9PVV//TVp6/y00QP8mLS//KjI5/ysyN/8rMzf/LDQ5/ywy\n        OP8sMjf/LDM4/ywzOf8rMzj/KzI3/ysyN/8rMzj/KjE2/yowNf8qMDb/KjA1/yoxNv8qMTb/KTA0/ykv\n        NP8pLzX/KTE2/ykxNv8pMDX/KC8z/yoxNv8oLzT/LDM+/05Zb/9QV2P/TVNc/09UXv9PVmD/TlVg/01V\n        X/9NVmH/SFJb/zZBSP8lKiz/GRoV/xkgJP8gP2D/KmSl/zN5xP86gdL/QYbW/0KDyv8+f8j/Pn7H/0CC\n        x/87gMz/M3W//zNzu/86hNX/NnjA/y1FXv8rLzX/DxAR/yQsMf8oLzf/JCsx/yMqNf8jKj7/JCw//yMr\n        Pf8jKj3/Iys+/yUuQf8lLUD/JS1A/yMrPv8iKj3/Iys+/yQtQP8kLTr/Iywz/zA5Qf8tNDj/DxER/xES\n        FP8qMzj/JC0z/yAoMP8fJjj/HyY6/x8mOv8fJjr/Hyg7/x8nO/8fJzv/Hyc7/x8mOv8fJzv/Hyc6/x8m\n        Ov8eJjr/HiU6/x8nM/8eJiv/Hicu/zE+Sf8iKzT/DQ8S/w8SFf8iLDP/Hycu/xohKP8gKjOuJC03FyIs\n        NhkfKTGvGSAm/yEqMf8eJSv/DxMW/woND/8fJy3/NkRQ/0JTVf89TGr/DhLK/wAB8P8DBOn/AwTq/wME\n        6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6v8DBOr/AwTs/wEB6/8RFpv/R1lh/1Rqdf80P0f/CQoK/xYb\n        Hf88S0z/PEtQ/xQZuf8BAfb/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AAH0/wYH\n        2/8rNlr/RFhR/0FPVv8vOD//GyIl/xMXGv8rLzv/KUlz/zJ0xP81eMP/NXbA/zd3w/85esX/P4LQ/0CE\n        0/9Dg9H/QoLO/z9/zf88fcn/PXzG/zt8yf8zd8b/J2Gh/x44U/8cIyb/IiMg/y81Nv88Rkz/Rk9X/0lS\n        W/9MVF//TVVg/05VX/9SWmP/Tlt0/y00P/8oLjL/LDI5/y41PP8vNT3/LzY+/y41Pf8uNj3/MDg//zA4\n        P/8uNjz/LTQ7/ywzOv8sMzn/LDM6/y0zOv8sMjn/KzA3/yswN/8rMDf/KzA3/yowNv8rMTf/LjQ7/y40\n        PP8tMzr/KzI4/ywyOf8qMTn/LjQ//05Zbv9OVmL/SVFb/0pUXv9IU13/QU1W/zhCSf8tNDn/IiUm/xoa\n        Fv8YHR3/IDNF/ydVh/8ucLn/NXjF/zl5v/88fsj/QoXQ/0KDy/89fsb/QH/G/0ODyP9Ag83/OHnB/zp8\n        xf9CiNj/On7I/ypTgf8uMjn/Gx8i/xwiJP8oMTf/Ji40/yQrNP8kKzz/JCs//yMrPf8jKj3/Iys9/yUt\n        P/8lLD//JSw//yMrPf8jKj7/JS0//yUtQP8kLD3/Iywz/ygyOv81P0T/GRwe/w8PEP8mLTH/JzA3/yAp\n        L/8fJzf/Hyc7/x8nOv8gJzz/ISg8/yAoO/8gJzv/Hyc7/yAnO/8fJzv/Hyc7/x8nOv8eJjr/HiY7/x8n\n        Nf8eJi3/HiUt/zA8SP8rNkD/DRAT/w4RFP8bIyj/Iy01/xoiKf8fKTLGIiw2JyQvOCchKTHHGSAm/yQu\n        N/8YHiT/DA8S/w0PEv8iKzL/OEZT/0NVUv83RnL/CQvl/wEB7v8DBOn/AwTq/wME6v8DBOr/AwTq/wME\n        6v8DBOr/AwTq/wME6v8DBOr/AwTt/wAA6f8cIov/T2Jp/1Nodf8nLzT/BQQE/yAnK/9AT0j/MT5q/wkM\n        0/8BAfP/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID6/8CA+z/AADz/wsNvf84R07/RlhV/zpF\n        Tf8tNTz/ERYV/xkcJP8wO1T/KFaJ/zR5yP81dcH/N3bB/zV1v/87fsr/QYbV/0OFzf9FhM7/Q4PQ/0OG\n        1f9ChtT/P3/H/zt6xP88fsv/QYfY/zV2xP8lU4b/IDdK/xslK/8dHhv/ISMg/yguL/8vNzz/MzxD/zlE\n        Sv8+SVL/O0ZT/ykvN/8lKS7/Jisw/ykuM/8pLjT/KC40/ygtM/8oLjT/KTA1/yguNP8nLDL/Jiwy/yYs\n        Mf8mKzH/Jywy/ycsMf8mKzD/Jiov/yUqL/8lKi//JSov/yUqLv8lKy//Jy0y/yctMv8nLTL/Jywx/ycs\n        Mf8mLDL/KS83/zZAS/82QUn/Lzg//ygvNP8iJyr/HiIi/x0eHP8aGxf/GiEk/x80SP8mUYD/MXO9/zd9\n        yv84esT/Nna8/zR1vP9Ags3/RITN/0SDx/9Bgcj/QYTS/0aN3/8+f8v/PX7H/zyBz/8+g9D/OX7K/yxk\n        oP8vPE7/ISQn/xEVFP8sNTr/KjE4/yYuNP8mLjv/Ji1A/yQrP/8jKj3/Iyo9/yMpPf8kKj3/JSw//yQs\n        Pv8jKz//JS0//yUtQP8kLD7/JCs1/yQsM/83Qkn/ICQn/woLCv8dIiT/LDY9/yAoLv8gJzX/ICc7/x8m\n        Ov8fJzr/ISk7/yEpPP8hKTz/ICc7/yAnO/8fJzv/Hyc6/x8nOv8eJjr/HiY7/x4mN/8fJy7/HiUr/yw4\n        Qv8zQEr/EBYZ/wwPEv8TFxz/KDM8/xsiKf8eKDHeIi43OSYwODUgKTDdGSAm/ycyO/8WHSL/Cw4P/xAV\n        Gf8mMDj/OklW/0JVVP8uOoH/Bgfr/wIC7f8DA+n/AwTp/wME6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME\n        6v8DBOn/AgPu/wME4f8nMGr/UmVn/0tdav8bIST/BgcG/ykyOP9CUUT/KDOA/wME6/8BAu7/AgPr/wID\n        6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID6/8BAu7/AADv/xQYg/9AT07/RVZZ/zU+Rv8kLDD/ERUX/yMl\n        Mv8sQF//L2qr/zV2wv81dcD/NHbB/zd3wv9Bgs//RYfV/0aFy/9JidT/SYrZ/0iI1f9Fh9P/QIHM/zt5\n        w/88e8X/QIDJ/zx8xv87fcv/N3W7/y5fmP8lSHD/HTBE/xokK/8dHhz/Gx0b/x0jJv8nLTT/KTA2/yYs\n        Mv8fIyT/HyAe/yAhHf8gIh7/ICId/yAhHv8gIR//ICIf/yAiHv8gIR7/ICEf/yEiH/8gIh//ICEg/yAh\n        H/8gIh//ICIf/yAiH/8gIh//ICIf/yAiIP8hIiD/ISIg/yEhH/8hIR//ICIe/yAjIP8gJCP/Jisx/yow\n        N/8oLTT/HyQo/x0gHv8eHx7/HCMn/xwuP/8kRWf/KlmM/y5ssv84esb/PH7G/zh6wP84eMD/OnrF/zp8\n        x/9Fh9L/R4fQ/0aJ0v9HidH/PIDO/zuE1P85e8X/OX3J/zR5w/83fMn/OX3H/zJxtf8pQmD/Jigq/xQY\n        Gf8mLTL/KTA3/ygvNf8mLjn/Ji5A/yUtP/8jKz7/Iyo+/yQrPv8lLD//Ji5A/yYtQP8kLD//JS1A/yUt\n        QP8lLED/JCw4/yQsMv8yO0L/KC8z/w0OD/8XGxz/KzU7/yAoLv8fJjH/HyY5/x8mOf8fJjn/ICg7/yEp\n        PP8hKTz/ISk8/yAoO/8fJjv/HyY6/x8mOv8eJjr/HiY7/x4mOP8fJzD/HSUr/yYwOf8zQEv/Fx0h/wwP\n        Ef8UGR3/KjY//xoiKP8dJi/1Iiw3TiUvN0gfJy/yFx4k/ygyPP8YHiT/Cw4Q/xMZHf8oMjv/PEpU/0JU\n        W/8iKqH/AwTw/wIC6/8DA+n/AwPp/wME6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6v8DBOn/AgLw/wcJ\n        2/81QmL/VGhq/0FRXf8TFhf/CQoK/zM+Q/9CUUL/ICeN/wIC9f8CA+z/AgPr/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AgPr/wID6/8BAfH/AgLt/ycvYf9DVUz/QFBW/zA5P/8cIiX/EhUX/yovQP8mRm3/M3fD/zV1\n        v/83d8H/OXrF/zx7xf89fcn/RIXS/0uL0/9Ojtn/TZHi/0mJ1P9Af8j/PnzF/zx7wv87esP/P37J/zx8\n        xv8+fcb/RYbS/0GH2f85fMz/M22w/zNloP8yYJP/JUZo/yAlJ/8oLjb/LTM7/ykuMv8nOkn/LFeH/ylS\n        fP8pUHn/KFN9/yhRev8qUXz/KlF6/ypRe/8sVH//KVF9/yhPfP8qUXz/LFJ9/ytSe/8rUnv/KlB4/ypQ\n        eP8qUHv/KU93/ylPdv8pT3b/KVB4/ylQef8qUXj/K1N//ytWh/8oQFX/KCwu/yswOP8oLTX/IiUl/ydB\n        Wf8tWo//NWad/zhxsv82eMb/OHzH/zt9xP87fMT/OXi+/zh3vf83d7v/Pn7G/0WJ1v9EiNX/SYvU/0mO\n        2/9Gi9r/PX/J/zd4wf84ecP/PX/M/0KF0P8/g9H/OXrA/zV7xv8nTXf/LzQ8/xocIP8ZHiD/KjI4/ycu\n        Nf8mLDX/JSw9/yUtP/8lLT//Ji1A/yYtP/8lLT//Ji1A/yYtP/8mLUD/Ji5A/yUtQP8lLUD/JS07/yQs\n        M/8sNDv/MTo+/xIUFf8UFxf/KTE1/yIpMP8eJTH/ICY6/yAoPP8gKDz/ISk8/yEpPP8hKTz/ISk8/yAo\n        PP8gJzv/HyY6/x8mOv8eJjr/HiY6/x4mOf8gKDH/HiYs/yQuNv8zQEv/GiEm/wsPEf8UGR3/KjZA/xoh\n        J/8dJS3+JC44aiUuNmIdJSz7Fx0i/yQvNv8WHCH/Cw4Q/xcdIv8tOEP/O0pS/0JTXP8dJKX/AgLw/wMD\n        6/8DA+n/AwPp/wME6v8DBOr/AwTq/wME6v8DBOr/AwTq/wME6v8DBOr/AQLv/wsNrv9CUGX/WG1z/zlH\n        UP8LDQv/DxMT/zlGR/89SlP/Fx2s/wEB9v8CA+v/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wID\n        7P8BAfH/BAXH/zNAU/9GWFH/PUlR/y43Pf8WGx3/ExQX/y45U/8pWJD/NnjF/zZ3wP84eMP/P3/J/z59\n        xv85e8f/RIXS/06O2P9Ojtn/S43c/0iH1P9Cgcv/QYHK/z19xf87e8T/QYDL/zx9yv88fsj/QIHM/0B/\n        zP9CgMv/QIDJ/0OF0v9Ile3/N26o/yIkJf8pLjb/LjU8/ycrLP8wSmL/RI7h/z2C0P89fcb/On7K/zl8\n        yP87fcv/PYHO/z+Cz/9EiNf/PoHM/z5/yP9Bgsz/Q4TN/0CCzP8/gMn/Pn3B/zt8x/88fsv/O33G/zt7\n        w/88fMP/PHzF/zx9xv88fcX/PoHM/0OJ3P8yVnv/Jygo/ysyOf8pLzf/ISMg/zReiv9Fkev/TpDa/02Q\n        2/9ChtL/Onm9/zl3uf86eb//O3m+/zl4v/84ecH/PXzB/0SFy/9Bg83/R4nS/0mL0v9HiMv/RYXL/0KC\n        zP86esP/QYDI/0uN2f9IkN//O37I/zd+zf8uY5v/MkBQ/xwdHv8TFhb/LTU8/ygwN/8nLjT/Ji08/yYt\n        Qf8mLkD/Jy9B/ycvQf8mLkD/JS1A/yUtP/8nLkH/Jy9B/yYuQP8kLD//JCw8/yQrMv8nLzb/N0FG/xUY\n        Gf8PERH/Jiwx/ycwN/8eJi7/HyY4/yAoPP8hKDv/ISg7/yEoO/8hKDv/ICg7/yAoO/8gKDv/ICc7/x8n\n        Ov8fJjn/HiU5/x4mOv8gKDP/HiYs/yMsNP80QUz/HSYs/wsOEf8TGBz/JS83/xkgJv8cJCz+JC84hyQt\n        NXgcJCv8GB8l/yErMv8TGR3/Cw4Q/xogJv8zQEz/PU1V/0JTXP8ZH6r/AQHv/wME6/8DBOn/AwTp/wME\n        6f8DBOr/AwTq/wME6v8DBOr/AwTq/wME6f8DBOr/AADw/w4RnP9HV2X/V2x0/zA8Q/8FBQT/GR4g/z1K\n        Rv83Q13/DRHA/wAB9f8CA+r/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wIC7f8BAPP/CAqk/zlI\n        U/9GV1b/OkJJ/yYtM/8TFxn/HyAq/yo6WP8vaq3/N3a9/zZ3v/86e8b/QIDJ/zx9x/83eMX/QoXT/0+O\n        1f9Ni8//S4vT/0OEzv9Af8T/R4TK/0KAyP89fMT/P33G/zt6w/8+gMn/RYPI/0iGz/9GhdD/Pn3E/z17\n        vv9FjuD/O22k/yIjJP8rMDj/LjU8/yYpKf8wS2X/RY7h/0CAxv9BfcH/QX/D/0B+wP9AfsH/Q4PL/0qJ\n        0v9JiM//R4bP/0qIzv9JiND/SonM/0uIzf9Egsr/QoDC/0WDyv9IhtL/QoLJ/0F+wv9CgMX/QoDG/0KB\n        yP9CgMP/RILG/0eJ1P80Vnj/Jicn/ywzOf8qMTj/ISIf/zVdiP9Jkub/U5PZ/0yQ2/89fcX/O3e5/zt3\n        uf86d7v/O3rA/zt7w/87fMT/Pn3E/0SDyv9EhMz/SIfL/0SEy/9Chs//QYjY/0OG1P88fcf/PH/J/0KG\n        0f9Mjtj/Q4XO/zd9zP8xcrj/K0FY/yMlJP8VGBn/Jy4z/ykvN/8oLjT/Ji06/ycuQP8nLkD/Jy5A/ycv\n        Qf8nLkH/Ji5A/ycuQP8mLkD/Ji5A/yQtP/8kKz//JCs7/yQqM/8mLDP/OENJ/xsfIf8KCwr/HyUn/yw3\n        PP8eJiz/HyY3/x8mOv8gJzr/ISg7/yEoO/8gKDv/ICc7/yAnO/8gKDv/ICg7/x8nOv8eJTn/HiU5/x4m\n        Ov8gKDP/HiYs/yAoMP8zQEv/Iisz/woOEf8RFRn/Iisy/x0lK/8bJCv+Iiw1nyMsNIwcIyv+HSQr/yAp\n        MP8RFhr/Cw4Q/xshJ/83RFH/QVJY/0NTZf8TF8r/AADx/wME6f8DBOn/AwTp/wME6f8DBOr/AwTq/wME\n        6v8DBOr/AwTq/wME6f8DBOr/AAHx/xUalP9LXWb/VGhx/ykzN/8FBQT/ICYq/z9ORf8yPmv/Bwnc/wAB\n        8f8CA+r/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wIC7f8AAPX/ExeM/z5NTf9FVVf/NkBG/yEn\n        K/8SFxf/JCg2/yM6WP80dLz/OHm//zd3wP87e8T/Q4XP/zh5xf80c7v/PIDM/02M0v9MitD/SYrT/0KF\n        0/9BgMn/RYPJ/0B+x/88fcX/QH/I/z58xf9Agcv/RITK/0iGyv9LiM//QoHK/zx5vv9BiNr/OG2l/yMk\n        JP8uMzz/MDg//ycpKf8rRmH/QYnc/0OBx/8/e7z/QX7C/0B8v/8/e7//QYHI/0eI0v9JiM//SIfP/0aD\n        yP9Ihsz/SojO/0mHy/9Dgcj/RIHI/0iGz/9HhMv/QX/G/z98vv9AfL7/QX/E/0CAyP9BfsL/RIPK/0OH\n        1P8yVHb/Jicm/y0zOf8rMTn/IiMg/zFXf/9Fitv/TY3V/0uM1P8/gMn/PHm8/zt6vv86eb//O3vA/z5+\n        xv8+fcb/RYTM/0uK1P9IiNP/SovS/0aI1P8+f8r/P4PQ/0eP3/9DhtP/QILL/0GFzv9Ljdb/R4fQ/zd6\n        xv80eMP/JkJc/yksK/8XGhz/ICcr/ykwN/8oMDX/Ji04/ycvQP8mLT//Ji0+/yYuQP8mLkD/Ji5A/ycu\n        QP8nL0H/Jy5B/yYtQP8lLD//JCs9/yQrNv8lLTT/Mz1D/yMqLf8LDA3/HSIj/yw1PP8gJy7/HyU2/yAn\n        Ov8gKDv/ISk8/yEpPP8hKDv/ICc6/x8nOv8gJzv/ICc7/x8nOv8eJTn/HiU5/x4mOv8fJzT/HyYs/x8m\n        Lf8yPkr/JS43/wsOD/8QFBf/ICkw/yErMf8bIyn/ISoztSMsNJ8cIyr+ISkw/x0kKv8OEhX/Cw4Q/xsj\n        J/86R1P/RFRY/0JSZ/8OEdv/AQHx/wME6f8DBOn/AwTp/wME6f8DBOr/AwTq/wME6v8DBOr/AwTq/wME\n        6f8CA+v/AQHv/x4kc/9TZGT/UmVy/yMqLf8GBgT/JS4y/0BQQv8tOHb/BAbu/wEB7f8CA+r/AgPr/wID\n        6/8CA+v/AgPr/wID6/8CA+v/AgPq/wEC7/8AAPb/Hydr/0JSQv9CUFf/Nj9G/xwiJf8ODxD/Jy09/ypL\n        cv84ecL/OXrF/zp5w/9AgMr/Q4jY/zd2v/83db3/On/K/0yM0/9Pjtn/TIrT/0ODz/9Bgs3/QoHJ/z9+\n        x/9AgMj/QYLN/z19x/9Bg83/RobR/0iFyP9LiMz/Q4DH/z18wv9Bh9j/OGqf/yIlJP8uNDz/MTg//ykr\n        K/8rRFn/QIXT/0SG0v9Af8X/Q4HK/0OBx/9BfcD/QYDG/0aEzP9Hhc7/Q4LK/0aDyv9KiND/SYnS/0SB\n        xf9Cf8L/RoTK/0aGzP9EgcX/QX7E/0B8v/9CfsD/Q3/E/0GAyP9Cf8L/Q4DB/0WJ1P8zVXj/Jigm/y4z\n        Ov8qMTn/IiMh/y9Td/9ChdD/Q4TL/0SDzP9Hhs3/QH7C/zt7wf87esH/Oni9/zt5vP9Bgcn/SIrU/0iH\n        zv9Eg8r/QofX/0KH1P8+f8T/PX3G/0SL2/9Hi9j/R4XH/0mHyf9Kjtj/RonW/zt7wf81eMD/KlF7/y43\n        Pf8TFBX/Gh4h/y01PP8pMTf/KC85/ygwQf8oL0L/Jy5A/ycuQf8nL0H/Jy9B/ycuQf8nLkH/Jy9B/ycu\n        Qf8kLT//JCs+/yQsN/8lLjT/MDpB/yw0OP8NDxD/GR0d/ykxN/8iKDD/ICc1/yEoO/8hKTz/ISk8/yEp\n        PP8hKTv/ICc6/x8mOv8gJzr/ICc6/x4mOf8eJTn/HiU5/x4lOf8eJTX/HyYt/x4mLP8yP0r/KDI7/wwO\n        EP8NERX/GiEo/yYvN/8aIij/ICoyyiIrNLEbIin/JC01/xsiKf8MDxL/DBAS/yAnLf87SVT/Q1RW/z5M\n        Zv8LDtv/AgLw/wME6P8DBOn/AwTp/wME6f8DBOn/AwTq/wME6v8DBOr/AwTq/wME6f8CA+z/AgLv/ycv\n        bf9ZbGj/UGJw/xgeIP8HBwb/KzQ5/0JRRP8qM3f/BATu/wEC7f8CA+n/AgPr/wID6/8CA+v/AgPr/wID\n        6/8CA+v/AgPq/wEC8v8AANz/JzFk/0VVSv9ATFP/NDxC/xgeIf8ODw//KTFB/y9cj/86e8b/N3a+/zl3\n        vv9Bgcv/QILQ/zt4vv87ecD/P4HN/02N1/9Sktv/Uo/T/0aEzP8+gMz/QoXP/0F+xv9Af8n/QIDL/0B/\n        yP9Fg8z/RoLI/0iGyP9OjtT/SYrW/0KAxv9Gidf/OWid/yIkJP8tNDv/MThA/ykrLP8sRFn/QIPQ/0OE\n        z/9Cgsz/RYXP/0eEy/9HgsX/RIDD/0F+v/9DfsH/S4nR/1GP2P9LidD/SIXJ/0J/wf9Df8H/RIHF/0mJ\n        0v9Hhcv/QX3A/0J9wv9Ef8H/Q3/B/0SCyf9Fgcb/RIDB/0mL1/80Vnr/Jygn/y41PP8rMTj/IiMg/y9T\n        eP9Bgsz/QoHH/0OByv9Jh8r/RIHI/0B/x/8+e77/PHi7/zp4vv86fsj/PYDM/z9+wv89f8b/OXzG/zp4\n        uv87er7/O3nA/z9/x/9GiNT/S4vS/0qKzf9KkeD/RYjV/z17v/81d73/LWGZ/yw5Rf8UFRP/FRkb/y43\n        Pf8rMzn/KTA4/ykxQf8qMkX/KjJF/ykxRP8pMEL/KTBC/ygwQv8oL0L/KDBC/ygvQv8nLkH/Ji5B/yYt\n        Ov8lLDL/LTU8/zI8QP8PEhH/FRgZ/ykxNv8lLDT/ISg0/yEoO/8iKTz/Iio9/yIpPP8hKDz/ISc6/yAo\n        O/8hKTv/HyY6/x4mOf8eJTn/HiU5/x4lOf8eJTT/HyYt/x0kKv8vO0b/LjlD/w8SFv8MDxL/Fhwh/ygy\n        O/8bISj/ICky3SIqM78aICf/Ji84/x0kKv8MDhH/DxMW/yQsNP86SFP/Q1VX/zhEeP8KDOH/AgLv/wME\n        6P8DBOn/AwTp/wME6f8DBOn/AwTq/wME6v8DBOr/AwTp/wME6f8CA+z/AwTr/zA6dP9ecm//TmBs/w4S\n        E/8HCAn/Lzk8/0FRS/8kLIr/AwPx/wIC7P8CA+r/AgPr/wID6/8CA+v/AgPr/wID6/8CA+v/AgPr/wEC\n        9P8BAbj/LTdW/0ZXUf8+SlH/MDg+/xccH/8XGRr/Ji8//zFnqP85esL/OHa6/zl5wP87ecD/O3rD/zx8\n        xf88fcj/RYbO/0+N0v9Qkt7/UJDc/0aF0P9ChM//RIXO/0B8wP88fcb/PH3I/0GAx/9Eg8r/Q4DF/0qH\n        zv9Qkdv/TI3Z/0iEyP9NkN7/Om2l/yEkI/8tMzv/MjlB/yosLv8tRVv/SIjS/0WDzP9BgMr/RoXL/0OA\n        xf9Ihc3/R4TK/0R/xP9Fgcf/SojR/1aV3P9Yltr/To7V/0WCxv9EgML/Q3/B/0eGzf9Fg8f/QX3A/0N/\n        w/9HgsX/RoLE/0WCxv9FgcP/RYHC/0mL1f81Vnf/Jygn/y81PP8rMjn/IiMh/y5Tef8/gs3/Q4HF/0F/\n        xv9DhM3/R4jT/0SG0v8+fcL/PXi5/z16v/88fcb/PXvC/0F+wv88e8T/OnrE/zx7wv86esD/PHvC/0WD\n        y/9DhdD/RIXO/0aH0f9JjNb/RIPK/zp3vP82drz/Mm2w/yk5Sf8eHx3/Fxsd/y42O/8sNTv/KzI5/yox\n        Qv8qMUT/KjJD/yoyQ/8qMUP/KTFD/yoxQ/8pMEL/KDBC/ygwQv8oMEL/KDBC/ycvPP8kLDL/KDA3/zZA\n        RP8QEhL/ERQU/ykyNv8oMjn/ISg0/yEpO/8iKTz/Iio8/yIqPf8iKT3/Iik8/yIpPP8hKTz/ICg7/yAn\n        O/8gJzr/ICc6/x8nO/8fJjb/Hycu/xwjKf8sNkL/MTxH/xIWG/8MDxH/Fx0i/yk0PP8aISf/Hygx7iIq\n        M80ZHyb/Ji83/x0kKv8MDhH/EBQY/yMsM/85RlD/RVVX/zVBjv8JC+f/AgLt/wME6P8DBOn/AwTp/wME\n        6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6v8CA+//BAXK/zdEbP9idnb/S1tn/wgICf8NDxD/Mz8//z5N\n        U/8bIar/AQL0/wID6/8CA+r/AgPq/wID6/8CA+v/AgPr/wID6/8CA+r/AgPr/wAB9f8GB7b/Mz5Y/0dW\n        Uv87R03/KTE3/xQaG/8bHSH/ISs3/zd1u/88fsn/O3m//zp5wf88eL//O3i9/zt5vv89f8n/SIzZ/0+P\n        1v9Pj9n/UZHa/0yK0f9Hhs//RIXP/0B/w/89esL/P37H/0F/xf9BfsT/RILI/02K0v9OjdX/SojQ/0aC\n        x/9Lj97/O2yk/yEjIv8tMjr/MzpD/ywuMP8sRF3/So3b/0+Q2f9EhM3/QX/G/0J/xf9Fgsr/RILJ/0yJ\n        z/9RjM//T4/W/12h7P9enN7/UJDZ/0aDy/9HhMn/R4XK/0aDyf9FgMP/RIDE/0KAyP9HhMv/SIXJ/0aC\n        xP9GgcL/R4TH/0qO2/81V3f/Jicm/y81O/8tMjn/IiIg/y9Uev9ChNH/RoPJ/0WEy/9Cg83/RobP/0B+\n        xf8+e8D/PXm6/zt7wP9AgMj/Q4LI/0eGzv9BfsL/P3/H/0OF0f87e8T/PH7J/0mN2/9Fitj/RYTJ/0iK\n        1P9FhMv/QoPK/zh4vv82drz/NXa+/yQ2R/8hIyD/Fhob/yoyN/8tNT3/LTQ7/yoyP/8qMkP/KjJE/yoy\n        RP8qMUP/KjJD/yoyRP8qMUP/KDBC/ygwQv8oL0L/Jy5C/yYuPP8lLTP/KDE4/zpDR/8TFhX/CwwM/yYt\n        Mf8tNj3/Iio0/yMrPf8jKT3/Iio8/yMqPf8jKj3/Iik8/yEpPP8hKDv/ICc7/yAoO/8gKDv/ICg7/yAn\n        O/8fJjj/ICgw/x4lK/8qNT7/MD1G/xQZHv8MDhH/Fx0i/ykzPP8ZISb/Hycw+yIqM9cZHiX/JS43/xwj\n        Kf8MDBD/EhUZ/yUuNf85Rk//RVZZ/y05lv8GCOn/AgPs/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME\n        6f8DBOn/AwTp/wME6v8CAvL/BAWw/ztIYv9gdXj/RVRf/wYICP8QFBX/NUJA/z1KVP8VGqz/AAHz/wID\n        6/8CA+r/AgPq/wID6/8CA+v/AgPr/wID6v8CA+r/AgPr/wAA9/8LDbL/NUNW/0RVUv86Q0r/Jy40/xMY\n        GP8dICT/IzVJ/0J/xv9Dg83/O3m+/zx9xP9Agcv/PHm//zt3vP8+f8j/R4bP/06Kzv9Sk93/VZXc/0yI\n        yP9Ef8X/RoXO/0SBxf9CfsP/QH/H/0F9xP9EgcX/SIbP/0+O1v9PjNP/SIXL/0SBx/9JjNv/OGec/yEk\n        JP8uNDv/NDtC/y0vMP8sRFv/RIbU/0eFy/9Fgsj/RITM/0N/w/9Ef8P/RYDF/0qHzv9RjtH/Vpnk/1id\n        6v9Wldn/T43T/0aBxf9HgsP/SYbL/0iDyP9GgcP/RIDD/0SBxf9Hg8f/R4PF/0WBwv9EgMH/RoHE/0WI\n        1f8wU3X/Jykn/zE2Pv8uMzr/ISIf/zFYgP9GidX/SIXI/0eHzf9Cf8b/QX/E/0J/w/9CfsD/P3q6/zx7\n        wP9Ag87/P4LN/0SF0P9Cgcj/PnzB/0WGzv9Agcv/PH7J/0SFzP9Ih9D/TY7X/0uN2P9GhMj/RYjR/zt7\n        w/84d77/OXnC/yY/WP8hJSX/FRgZ/ycvNP8uNj3/LTU8/ysyP/8sM0X/KzNF/yszRP8qMkT/KzNF/ysz\n        RP8qMkT/KjFD/ykxQ/8oL0H/KC5B/yYuPf8mLjX/KDA4/zlCR/8aHh//CgoK/yMqLv8tNj3/Iyoz/yQs\n        Pv8kKz7/Iyo9/yMqPf8jKjz/Iik8/yIpPP8iKTv/ICc6/yAnOv8gJzv/ICc7/yAnO/8gJzn/ISgw/x8m\n        LP8pMz3/MTxG/xUaH/8LDhL/Fx0j/yk0PP8ZISb/Hicw/yEpMuAZHiX/Ji83/xsjKf8LDBD/EhUa/yYu\n        Nf85RlD/R1da/yYwmf8EBen/AgPs/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME\n        6v8BAvP/BAWr/z5KY/9dcXb/PUxV/wYICP8TGBn/N0ND/z1JU/8UGar/AAHz/wID6/8CA+r/AgPq/wID\n        6v8CA+v/AgPr/wID6v8CA+r/AgPr/wAA+P8PEpP/OUdE/0NTVf85Qkj/Jiwy/xAUFP8hJCr/KEFe/0KC\n        zf9ChM7/One9/z18wv9Bgcr/PnzD/zx4vf89e8P/RYHF/0+Lzv9Tk97/VJTe/06L0f9KiM//RYHG/0OA\n        yP9Dgcf/P33D/z9+xf9Hg8n/SonQ/02L0f9NiM7/SYXL/0SBxv9IiND/NWGR/yIlJf8xNj7/NTxE/ywu\n        L/8sQlf/RITK/0aDxv9HhMr/SYjQ/0iH0P9Fg8j/S4fN/0qFyf9MitH/V5zs/02P2/9QjdP/VZXd/0eF\n        yf9Ffr7/SoXH/0uGyv9Khcj/RYDA/0V/wP9HgsP/R4LE/0aBw/9Hg8b/R4LF/0SG0f8vUXL/Jyoo/zE3\n        P/8uMzv/ISIg/zFWe/9HidT/R4TF/0aDxv9DgML/QX3B/0SAxv9Df8T/QHu+/z57vP9Cg83/QIHM/z16\n        wP9FhMr/Q3/B/0iJ0P9Mjtn/RobR/0SDyP9KiMr/UI/V/1KS2v9Pktv/SYzZ/zl5w/83d77/OXrA/yxL\n        a/8pLzL/ExYW/yQsMf8vNj7/LjY8/ysyP/8sNEb/LDRG/ywzRf8rNEX/LDNF/ysyRP8rMkT/KjJE/yoy\n        Q/8pMEL/KTBD/ygwP/8oLzf/KTA4/zZARv8fJCf/CgsK/yIqK/8sNjz/Iysz/yQsPv8kKz//Iyo9/yIq\n        PP8iKTz/Iik8/yIpPP8iKTz/ISg7/yAnOv8fJjr/ICc6/yAnO/8gJjr/ISkx/x8mLP8pMzz/MDxF/xUb\n        IP8LDhH/Fx0i/yo0Pf8aISf/Hicw/yEqMugZHyX/JS01/xshKP8KDA//EhYa/yYvN/85Rk//SFdb/ycw\n        lv8DBOj/AgPt/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6v8BAvP/BAWr/0FO\n        aP9fcnf/OkdP/wYHB/8WGxz/OEVE/zxJUv8TGK7/AAHz/wID6/8CA+r/AgPq/wID6v8CA+v/AgPq/wID\n        6v8CA+r/AgPs/wAA+f8SFYL/Okg5/0NSWP86REn/JSsv/w4QEP8kKS7/LUtp/0SDzv9Bgc3/One9/zx5\n        wP89er//Pnq+/z16vv8+fsf/RYPH/1ST2/9VleT/UY/Y/02O1v9Ki9b/R4LG/0J/xf9Af8X/P33C/0SC\n        yf9IhMj/TIrO/1CN1P9KidL/S4nR/0aDyv9Hidb/NWOU/yIlI/8yOD//NTxE/ystLv8qQ1r/RobO/02M\n        0/9Uktz/TIzV/0uJ0v9KiNH/To7Y/02J0P9OjNb/VJro/0mI0P9MiM//TY/c/0aGzv9DfsH/RoHB/0yG\n        yf9Mh8n/R4LD/0SBx/9GgsX/R4PG/0eBxf9KhMX/SoXH/0uM1f8yVHT/Jyko/zI4P/8uNDv/IiEg/y5S\n        d/9EhdD/RYDC/0SAw/9FgcX/Q37D/0F9v/9Fgsj/SITL/z57v/9Bgcn/SYnT/02M1v9KidD/S4nN/0qM\n        1v9Mjtj/S4vW/0qI0f9KiMv/SonQ/1GP1f9PlOT/SYrX/zp5wf83eL7/OXrA/y1Qc/8qMTT/EhMU/yUq\n        Lv8xOED/LzY9/ysyP/8sM0X/LDNG/y0zRf8tNEX/LDRF/ysyRP8rMkT/KjJE/yoyQ/8pMUP/KTBD/ygw\n        QP8pLzj/KjE3/zQ9Qv8iKCr/CgsK/yIoKv8sNjz/JSsz/yUsPf8kKz7/Iyo9/yMqPf8jKj3/Iik8/yIp\n        PP8iKTz/ISg7/yAnOv8gJzr/ICc6/yAnO/8fJzv/ISkx/x8mLP8pMjv/Mz5J/xgdIf8LDhD/Fx0h/yoz\n        PP8aISf/Higw/yIqNO4ZHyT/JCw0/xoiJ/8KDA//Excc/ykyO/86R1D/SFda/yYwlP8DBej/AgPu/wME\n        6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wQE6v8CAvP/BQWr/0VTbf9idXr/OUZO/wYH\n        B/8XGx3/OUZC/ztIVP8RFbb/AADz/wID6/8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA\n        +f8TFoH/O0k5/0NSWP88Rkz/JSsx/w0ODf8iJir/ME1t/0qJ0P9Eh9T/Ona8/zt4vf8+e8H/PXm9/zx6\n        wf88fcT/RILH/1aT2/9Vk9v/TovR/02L0f9Khs7/R4LF/0N9wP8+e8H/P33D/0WBx/9GgcT/SITH/0mG\n        y/9HhtD/R4XO/0iDx/9Njtv/NmOV/yEjIv8xOD7/Nj1E/ystLf8rRFv/SYrW/06M0v9NjNT/SYTI/0aB\n        xv9JhMf/TovQ/1GM0v9VlN7/V5vq/0aCx/9HgcX/RYLI/0qGyv9Gg8n/Q37A/0eEyP9Hg8X/RoLE/0SE\n        zP9FgcP/R4HD/0aDxv9Hg8P/SoXI/1CT4f83WX3/KCko/zQ6Qv8vNTz/IiIf/y5TeP9HiND/SILB/0WC\n        xf9Jh83/S4bK/0N/w/9Ghcz/TInP/0OAxf9Af8X/SorU/1GT3f9Kjdf/RYfS/0mI0P9Oj9f/TY7Y/0yM\n        1v9IiM7/R4PK/0+N0/9Okt7/R4bN/zt5v/84ecL/PYDM/zFXgf8oLzL/ERIR/yQpLv8xOkL/LzY9/ywz\n        P/8sM0b/LTRG/y00Rf8tNEb/LDRF/yszRP8rM0T/KzJE/yoyQ/8pMUL/KTBD/ykwQP8pMDj/KTE3/zM7\n        QP8kKiz/CQwL/yEnKf8sNTv/JCoz/yQqPP8jKz7/Iyo9/yIpPP8jKj3/Iyw9/yIqPf8hKTz/ISg7/yAn\n        O/8fJzr/HyY6/yAnOv8fJjr/ISgx/x8mLP8pMzz/NUJM/xkfI/8LDRD/Fxwh/ygxOv8aISb/Hygv/yMq\n        M/AaHyX/JCwy/xsgJv8LDA//Ehcb/yw2P/89S1T/SFlc/yYulP8DBOj/AgPt/wME6f8DBOn/AwTp/wME\n        6f8DBOn/AwTp/wME6f8DBOn/BATp/wQE6v8CAvL/Bgev/0dWcP9hdHn/N0JJ/wUGBv8YHR//OkZD/zpH\n        V/8PE8T/AADy/wID6v8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA+f8VGYP/PEs6/0NR\n        V/88Rkz/JCow/woLCv8gJSn/L05z/0OByf9Ehc7/PnvA/z55vf9AfsX/QoDI/zt3uv8+fcH/TYvS/1iZ\n        4v9Ul+L/UIzQ/0yHyP9IhMj/RH/B/0SAxP9EgMb/QX3B/0N+wP9Ff8T/RYHI/0aDyP9Khsz/SITK/0iE\n        xP9Rkdn/N2SW/yAkIv8xNz7/Nz1G/ywvLv8qQ1v/TI7c/1CO1v9KidD/SILE/0eBwv9Ig8X/UIvO/1SQ\n        1f9XluD/WJrm/02Iy/9Oh8n/TYjM/0+Jzf9Lh83/RoPJ/0mGzP9Jhcj/R4LE/0eEzP9FgMP/RoHB/0mE\n        xv9Lhsf/TIbI/06Q3/8yVXn/KSoo/zU8Q/8wNj7/IiIg/y1Rdv9Fhs//SIPE/0R/wf9KidD/UpDX/0mD\n        xv9MiM3/TovQ/0iFyv9DgcX/SYbL/0yL1P9QkNj/To7X/0uL1P9NjNP/UY7U/0yN1/9Ljdj/R4fP/02R\n        3v9Ljdr/RILJ/zt5v/85d77/O33I/zBZhP8oMDT/Dw4N/yInLP8zPET/Lzc9/ywzP/8tNUb/LTRG/y00\n        Rv8tNEb/LTRF/yw0Rf8rM0X/KzJE/yoyQ/8qMUL/KTBD/ykwQP8pMDj/KS82/zE5P/8mLC7/CwwL/x8k\n        Jv8rNDr/JCsz/yQqPP8jKj3/Iik8/yIpO/8iKTz/Iyo9/yMqPP8iKDv/ISg7/yEoO/8gJjr/HyY6/yAn\n        Ov8fJjr/ISgx/x8mK/8pMzz/NkJN/xkfI/8LDRD/Fhwh/ygyOv8bISf/Hykw/yIrM/AaISf/Iysx/xof\n        JP8LDQ//FBgc/y86Q/8+S1X/SFdZ/yQsk/8DA+j/AgPs/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME\n        6f8DBOn/AwTp/wQE6v8CAvL/CAqy/0lYcf9ecXb/Mz5E/wUHBv8cIiT/PEhE/zhGWv8OENH/AADy/wID\n        6f8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA+v8WHIb/Pk07/0JRV/89SE7/Iiku/wcH\n        Bv8hJin/MVF1/0SBxv9Hhs//Q4HL/z96v/9Dgcj/S4jQ/0F8wf9EgMf/T47U/1ib5/9VlN3/Uo3P/06J\n        zP9Ihcr/RYLH/0eH0f9Mi9T/Qn3B/0aCxf9GgMX/RYDD/0mI0P9Lic//RoPJ/0mEyP9Qkdr/OGaa/yEj\n        Iv8zOT//OD9I/y0vL/8pQ1r/TZLh/1yc5f9Xk9r/TIfL/0uGyv9Jhcj/TIfM/1KNz/9bl9v/VJLZ/1CM\n        0v9Wk9r/W5vl/1eS1f9Risv/TYjL/1WQ1f9SjtL/SoTF/0yHyf9Kg8X/SILD/0qFyP9Mh8f/U43M/12g\n        7P86XoL/Jygm/zQ7Qv8xNz7/IiMg/y1Tev9ChdH/RYPH/0N/w/9JidL/T43X/0mGzP9Qjc//UIzP/0aC\n        yP9Egcj/UY7U/1ua4f9Zltz/VpXb/06P2f9Jhcj/SIbL/0uM1/9Pk+H/RofQ/0aI0/9Bg87/P37G/zx7\n        wf85drj/O3rC/zFZg/8qMDT/CwoJ/yAmKv83P0b/Lzc9/y00Pv8uNUf/LTVH/y00Rf8tNEX/LTRG/yw0\n        Rf8rMkT/KzNE/yozQ/8pMEL/KTBD/ykwQP8pMTn/KTA2/zE4Pv8pMDL/DA0M/xsgIf8qMTf/JSw0/yQr\n        PP8kKj3/Iyo9/yMqPf8jKTz/Iik8/yIpPP8hKDv/ISg7/yAnOv8gJjr/ICc6/yAnOv8fJjr/ICcw/x4l\n        Kv8pMjr/N0NO/xkfJP8LDQ//Fhsf/ycwN/8bISj/Hygx/yMsNe0bISj/JS00/xshJ/8LDQ//Exca/yo0\n        Pf87R1D/R1VX/yQskv8DA+j/AgPs/wME6f8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8DBOn/BATp/wQE\n        6v8CAvL/Bgiv/0lXcP9gcnf/MDo//wUGBv8dIiX/PUlE/zlFWv8OEdH/AADy/wID6f8CA+r/AgPq/wID\n        6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA+v8VGYT/PUs6/0NRV/8/SE7/JCsw/wgJCP8hJij/MlFz/0N/\n        w/9Eg8r/PnzD/z15vv9Df8X/Q4HH/0F/yP9EgMf/S4nP/1mZ4/9Zl97/UY/T/0qHy/9LiND/S4bO/0qJ\n        1P9JidP/Q37C/0yJ0P9Mh8z/SoTF/02IzP9Lh8v/SYTL/0eBwv9KitL/NmOV/yAjIv80OkD/OkBK/y0v\n        L/8pQln/UJTk/2Cf5P9bltj/TorR/0qFyf9Jg8P/TIfL/0yHyf9al9z/Wpje/0uHy/9SjtP/W5vi/1WR\n        1f9NiMn/TYfK/1ya4f9Wktf/SYPC/0qExP9Kg8P/SoPC/02Hyf9Oicr/UYzN/1qe6/85XoP/KCgn/zY7\n        Q/8yOD//IiMg/zFUd/9JitT/SoPG/0mCxv9Li9T/UY/Y/0qI0P9Ihcn/S4jN/0aCxf9Df8H/SojN/1CS\n        3v9PkNr/TYrP/0yJ0f9MidD/SonS/0+M0v9LjNb/QYDJ/0KByP8/gMr/PXzD/zx5u/87d7j/O3vE/zJa\n        hv8qMTX/Dg0M/yMpLP82Pkb/MDc+/y00Pv8uNUf/LzZH/y41Rv8tNEb/LTRH/y01Rv8sM0T/KzJE/ysy\n        Q/8qMUP/KzJD/ykxQf8qMTn/KTA2/zE4P/8qMDP/Cw0M/xsgIv8qMTj/JSw0/yUrPf8kKz7/JCs9/yMq\n        Pf8iKj3/Iig7/yEoO/8hJzr/ISc6/yAnOv8gJzr/ICc6/yAnOv8gJzr/ISgw/x8mK/8pMjr/NEBJ/xkd\n        Iv8LDRD/Fhwh/ygxOf8bIij/ICky/yMsNOccISf/Ji42/xwiKP8LDBD/ExYb/ycvN/85RU3/R1dY/yUt\n        k/8DBOj/AgPt/wME6P8DBOn/AwTp/wME6f8DBOn/AwTp/wME6f8EBOn/BATp/wQE6v8CAvL/BQWs/0lW\n        cP9idXn/Ljk+/wUGBf8dIyb/PUlG/zlEVf8OEsH/AADy/wID6v8CA+r/AgPq/wID6v8CA+r/AgPq/wID\n        6v8CA+r/AgPs/wAA+v8VGIL/PEo4/0NRVv89Rk3/Ji4z/wsNDP8jJin/MVBv/z99wf8/fcP/PHi7/z55\n        uv8/fML/PHm+/0J+xP9Ggcf/SonR/1aW3f9Wk9j/U5DX/1CN0/9NidD/SoTI/0uGzf9Ig8j/RYHF/0qH\n        zP9Nis3/TIbI/0+IyP9Nhsj/SobM/0eDyP9MjNf/NmGS/yAiIP81OkD/O0FK/y0vL/8qQVb/Vpjj/2Oh\n        5f9aldb/TYvS/0uFxv9NhsX/TojK/0+Kz/9fm+H/Y6Dk/1WS2P9MiMz/UIvN/1KLz/9Mhsb/TonM/1yc\n        5f9YlNb/S4XH/0qFyP9LhMb/T4nL/0+Jyv9Ri87/UYzP/1aX4f81Vnr/Kisp/zk/Rv80O0L/ISIf/zda\n        fv9Tk9v/TovO/1CN0/9NjtX/UpLa/0qHzf9CfcH/QoDF/0OAxv9Df8H/Q3/F/0CE0P9Fh9H/RYHF/0uH\n        yf9Pi8//Vpbf/1iW2/9Qi83/TIjL/0mHzf9FhMz/P3m9/zx3uf88ebv/PHm9/y9Wff8qMjb/EREP/yQp\n        Lf80PUT/MThA/y41P/8uNUf/LzZI/y82R/8uNUb/LTRF/y00Rf8sM0T/KzJD/ysyQ/8rMkP/KzJE/ykw\n        QP8qMTn/KTE3/zM7Qf8rMjT/Cw0M/xofIf8qMTf/Jiw1/yUsPf8lKz7/JCs9/yMrPf8iKj3/Iyk8/yMp\n        PP8iKDv/ISg6/yEnOv8gJzr/ICY6/yAnOv8fJzr/ICcw/x8mK/8pMjv/ND9I/xgeI/8LDhD/Fhwh/ygx\n        Ov8bIij/ICkx/yIrM98aICb/JS01/x0iKP8MDRD/Excb/ygwOf87SFH/Slpc/ygwlf8EBej/AgPt/wME\n        6P8DBOj/AwTp/wME6f8DBOn/BATp/wQE6f8EBOn/BATp/wQE6v8CAvL/BQWr/0hUbv9hdHj/MDo//wUG\n        Bv8dIyb/PElG/zlEUv8QFbj/AADy/wID6v8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA\n        +f8UFoL/PEg5/0NRVv88RUv/KC40/w0PDv8lKCr/M1Bu/0aEyv9Df8b/Pni6/z97vP9DfsD/QXzA/0WB\n        xf9JhMz/UI7V/1SS1P9QjdD/W5bY/1yY3/9RjtX/S4jN/0iFyP9Gg8n/RIDF/0WAxP9OitH/VI/S/1eS\n        0/9Ujc3/TYfL/0yHzf9Xl+f/PWqe/x8iIP82O0L/PERL/y0wMP8pP1P/WJvl/2Sl7P9Wkdb/UY/X/1GL\n        z/9WkNb/VI/S/1iU2f9op+7/YZ/m/2Gg6f9XluD/TYvV/0+L0P9Nhsf/UIvP/1mX2/9Uj8//TIbJ/0uE\n        yP9PiMn/XZne/1WQ0v9OiMn/TonL/1OS3f8zVHX/Ki0q/zpBSP81O0P/IB8e/zlehP9cnun/UY3P/0yJ\n        zv9Mi9T/SojP/0aCyP9DgMP/Q4DF/0OBx/9Df8P/Q3/E/0KByf9Fhc3/R4TJ/0+KzP9PjM7/UpTg/1WX\n        4/9SkNT/V5bc/0yM1f9KidX/QX7F/zx3u/8+e8H/PnzB/zBVev8rNDf/ERMR/yMpLf8yOkH/MTg//y00\n        P/8uNUf/LjVG/y82R/8vNkb/LTRF/y00Rf8sMkT/KzJE/ywzRP8rM0P/KTBD/ygvP/8oLzf/KTA2/zI7\n        QP8qMjX/Cg0M/xogIf8qMjf/Ji02/yUtPv8lLD//Jiw//yQrPv8kKj3/Iyo9/yMqPP8iKTz/Iig7/yEo\n        Ov8fJjn/HyY5/x8mOv8fJjn/ICcw/x4lK/8qND3/NEBJ/xgeIv8LDhH/Fhwh/ygxOv8bIij/ISky/yMs\n        NNUbIif/Ji81/x0jKP8LDRD/EhYa/ygwOP8+S1T/TF1f/yozm/8EBen/AgPs/wME6P8DBOj/AwTp/wME\n        6f8EBOn/BATp/wQE6f8EBOn/BATp/wQE6v8CAvP/BAWq/0NOaf9gcnb/Mj1D/wUGBv8bIST/OkdG/zpH\n        T/8TGKv/AADy/wID6/8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPs/wAA+f8RFIP/Okc5/0RR\n        Vv89Rkv/KTA1/w8REf8mKSr/Mk9t/0mJ1P9Egsr/Pni5/0B7v/9DgMX/QH7D/0R/w/9Ff8T/TIjL/1OP\n        zv9Uj9H/W5na/1mV1/9VktX/UYzO/0iDx/9Ggsv/RYDF/0eAwf9Mhsj/TonL/1WS1/9Yldj/UIvN/1mU\n        1f9dnef/PWqd/x4iIP82O0L/PUNM/y4wMP8pQFb/VJXg/2Gg4/9Zlt3/WZfh/1KMz/9YlNn/VZTc/1mV\n        1/9mper/XZvh/16a3f9lo+f/VpXe/0uJ0f9Picr/VI7S/1iW3v9Vj9L/TobF/0yFxf9Qisr/XJja/1WP\n        0P9MhsX/TojH/1CP1v8yUXD/Ky0s/z1ES/84Pkb/ISEf/zNXev9cn+7/U47T/0uFyP9VluD/VJDW/1CK\n        zf9Mh8f/SYPF/0eDx/9FgcT/RH7A/0N+w/9DgMj/RoPJ/0mEyP9Gg8f/SojN/1OT3P9Rj9T/V5bf/1KR\n        2v9Mjtr/QoHI/zx4uv8/fcb/P3/F/zBSdf8sMjX/EBQS/yMpLP8wOD7/MDc+/y00QP8vNkj/LzZI/zA3\n        R/8vNkf/LjVG/y00Rf8rMkP/KzJD/yszRP8rMkT/KTBD/ykvP/8nLzb/Jy80/zE5P/8oLzL/Cg0M/xsh\n        Iv8rMjj/Ji02/yYtPv8mLkD/Jiw//yUsPv8kKz3/Iyo9/yMqPP8iKTz/Iik7/yIpO/8gJzr/Hyc6/x8l\n        Ov8fJjn/ISkw/yAnLP8rNT7/Mz5I/xcdIf8LDxD/Fx0h/ygzO/8bISf/ISky/yUuNsscIyr/KDE4/x0k\n        Kf8KDQ//EhUZ/ycvN/8+SlT/TFxf/y44nP8FBun/AgPs/wME6P8DBOj/AwTp/wME6f8DBOn/BATp/wQE\n        6f8EBOn/BATp/wQE6v8CAvL/BAWs/0BKZP9fcXT/NUBH/wUHBv8YHiD/OUVE/zpITv8UGKj/AAHy/wID\n        6/8CA+r/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPr/wAA+f8ND5T/N0RC/0VTVP9ASVD/KzI5/xEU\n        FP8gJCX/LERe/0eGzv9GhMv/P3m6/0F7vv9DgMb/Q3/D/0eBxP9Fgcj/TInR/1aS1f9VkNX/VpTZ/1OO\n        0P9Tkdf/UIzR/02Gyf9KhMj/R4DD/0iCxP9Mhcj/SoPG/1KN0/9Ukdr/VpPZ/2ai5P9cm+T/OGST/x4i\n        H/82O0L/PUNL/y0wMP8qQVb/UZDX/1mW2f9Vk9v/Wpnj/1GKyf9Ri8z/Uo7T/1yW2P9jnuH/Wpba/1qV\n        2P9fmtr/Ypzc/1mW3f9Tj9T/U4zM/1qW2/9altr/UInL/0uFxf9Picn/VY/Q/1GKyv9Nh8b/UIvJ/1CQ\n        1f8xUXD/Kiwr/z1ES/87QEn/IiIg/zNWe/9en+z/XJXY/0yHyf9Qkt7/VJPa/06Lzf9IhMT/RoDC/0eC\n        yf9Gg8j/RX+//0WBxf9Gg8v/R4PJ/0iCxv9FgcX/R4LF/0+M0v9Micz/TInM/1SQ1f9MjNT/RIPK/z15\n        u/8/fcb/QIDH/yxLav8lKiz/ExYV/yUsMf8vNj3/Lzc9/y40QP8wN0j/MDhJ/zA3SP8vNkf/LjVG/y00\n        Rf8rMkP/KzJD/ysyQ/8qMUL/KTBC/ykuPf8mLTT/Jy0z/zE4Pv8mLS//CQwL/x0jJf8sNDr/Ji02/yct\n        Pv8nLj//JSw+/yUsPv8lKz7/JCo9/yMqPP8jKTz/Iik8/yIpPP8iKjz/ISg7/x8lOf8fJjn/Iikx/yAn\n        K/8sNj//ND9J/xYbIP8MDxH/GB4j/yo0Pf8bIif/ICkx+SUvOL0eJSz/KjI6/x8lKv8LDhH/ERUZ/yYt\n        Nf88SVL/Slpb/zVAlv8HCej/AgLt/wME6P8DBOj/AwTo/wME6f8DBOn/AwTp/wME6f8EBOn/BATp/wQE\n        6f8DA/H/BAW1/zxHZP9gcXL/N0RK/wUHBv8WHB3/OURC/zxIUP8VGa3/AADy/wID6v8CA+r/AgPq/wID\n        6v8CA+r/AgPq/wID6v8CA+r/AgPq/wAA9/8HCbH/ND9U/0VVUf8+SlH/LzY8/xQYGf8bHh7/JDRC/0R+\n        wP9Egsb/P3q7/0F8vP9DfL7/RH7A/0WAw/9Egcj/TYnQ/1eS1f9YktP/VpDQ/1KO0v9Uj9P/UozN/06I\n        yf9KhMf/RoHF/0eCxf9Lhsv/T4nP/1CJyv9SjdL/W5fa/2Ca2P9dneP/PWeV/x8iIP83PUP/PUNL/y0u\n        L/8sQVX/VZLZ/1OP1P9Qis//UpDV/1OMzv9RjMz/VpDS/2Kd4P9emtr/Uo3Q/1KMz/9ZkdH/Z6Li/2Ge\n        5f9Tktr/T4vN/1+a3v9hneH/WZPV/0+IyP9Picf/U4zL/1GKy/9Oh8b/TojH/0+O1v8wUHD/KSop/ztB\n        SP85P0b/ISIf/zJXff9goev/aqXl/1iR1P9PjNH/TYzS/0eGzv9Ggsj/RoDA/0aAwv9GgMP/RH/C/0R/\n        wv9EgMT/RYHE/0eDyv9Ggsf/SYPD/02IyP9Ig8b/SoTE/1GO0P9OjNP/RYHH/z96u/9Bf8f/QYHI/yc8\n        Uv8hIyL/FRkZ/yoyN/8xOD//Lzc9/y0zP/8uM0X/LzVG/y82Rv8vNkb/LjRF/ywyQ/8rMkP/KzJD/ysx\n        Q/8qL0L/KS9C/yguO/8oLjT/KS40/zI7QP8kKiz/CgwK/x8kJv8uNTv/Ji03/ycuP/8nLT//Ji0//yYs\n        Pv8lLD7/JCo9/yQqPf8jKTz/Iyk8/yMpPP8iKTz/ISc7/x8lOf8eJTf/ISgv/x8mKv8sN0D/Mj1H/xUa\n        HP8NDhL/GB4j/ys1Pf8cIij/ISoy6yYvOa0fJi7/KjI6/x8mK/8MDxL/EBQX/yUtNP8/TVf/Slpc/zhE\n        i/8JC+b/AgLt/wME6P8DBOj/AwTo/wME6P8DBOn/BATp/wQE6f8EBOn/BATp/wQE6P8DA+7/BATW/zhB\n        cP9hcm//O0hQ/wUHB/8XHB3/OUNE/z5LUP8cIqn/AgLz/wID6v8CA+n/AgPq/wID6v8CA+r/AgPq/wID\n        6v8CA+r/AgPq/wEB9P8EBLL/MTtT/0ZVT/8+SlD/MzpB/xgcH/8YGxr/Ji81/0N7u/9Dgcb/QHu7/0J8\n        vP9CfL//Q32+/0iDyf9Hgcb/TIjM/1WS0/9YktD/WJLQ/1iT1P9UkdX/VI/Q/0+Jyv9KhMj/R4LF/0yF\n        xf9Lhcr/TIjN/1GMzP9Zk9T/WJLT/1aQzv9Xltz/O2aW/x8hIP84PUP/PkRM/y4vMP8uQ1f/Xpzi/1eT\n        2P9Si87/VZHV/1mU2P9Vjs7/W5XX/2im7P9aldn/TojN/0+Kzv9Vj9H/X53l/1eS2f9hn+f/YaLq/1yb\n        4/9ind7/WZPV/1CIyP9Qicj/UovK/1CKyv9Ri87/WJLU/1aT2v8xUG//KCko/zpAR/83PUT/ISEe/zFV\n        ef9dn+n/aafr/16a3f9Ujs//VI7R/1KMz/9SjdL/TojL/0yEw/9JgsP/RoDC/0Z+v/9Ff8H/RoHE/0WC\n        x/9Fgcf/R4LD/0mFyf9QjNL/VZDQ/1iY4f9Sj9X/Q3y+/0B9wv9Gh9L/Q4HH/ys5SP8fIBz/Fhob/y41\n        O/8yOUD/LzY8/ywzQP8tMkT/LjRF/zA3Rv8vNkb/LjVG/y41Rf8tNEX/LTRE/y0zQ/8rMUL/KTBC/ygv\n        Pf8qMDb/KjE3/zU+RP8jKSr/CgsK/yAmJ/8uNjz/Ji04/ycuQP8nLkH/Jy4//yYtP/8lLD7/JCs9/yQq\n        Pf8jKjz/Iig7/yEnOv8hJzr/ISc6/yAnOv8fJjb/ISgu/x8mKv8wOkX/Mz5H/xQYG/8NDxL/GB0j/ys0\n        PP8dIyr/Iioz2ScxO5whKDH+JzA3/x0kKP8NEBL/DxMV/yUsM/9DUFz/TFpd/z9LdP8LDd//AgLv/wME\n        6P8DBOj/BATo/wQE6P8EBOn/BATp/wQE6f8EBOn/BATp/wQE6P8DA+v/AgPu/y40cf9hcmz/QlBY/wYH\n        B/8VGRr/OURH/0FORv8lLIX/AwTw/wIC6/8CA+n/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPq/wEC\n        8/8BArz/KzRU/0VUTf9BTVP/OUJJ/xsfI/8SExH/KjQ5/0B0rv9Egcf/Q329/0N8vP9DfL7/RH7A/0yJ\n        0P9Lhcr/Uo3R/1qU1P9Zk9P/XZjc/2Cc3/9Zlt3/UY7U/1GMzv9KhMT/SYHA/02Fxf9MiM3/U47R/1iV\n        2P9bltj/V5HS/1WOzP9WlNj/O2aT/x8hH/85PkX/QEdO/y8xMv8tQ1b/X5zf/16Z3P9ZktP/WZTV/1WR\n        1v9Si8n/XJbW/2Ke4/9RjM7/VI/T/1qW2P9alNT/W5XY/1aP0f9gmtr/aKfr/1ub5P9Vkdf/U4zN/1CI\n        x/9Ph8f/UIjI/1CIx/9UjtH/ZKPr/1yb5P8yT27/KSop/zpAR/82PEP/ISEe/zRVd/9am+L/YZ7e/2Cd\n        4P9bltn/WZPV/1+b3/9gnN7/WJPU/1CIyP9Mhcf/SYPD/0iBwv9Gf8D/RH/C/0R/wf9CfsL/QXy//0N/\n        w/9Qj9f/XZve/12c5P9Tkdr/RX/B/0B8v/9GhMn/QXm1/y49Sf8ZGRb/Fxwd/zQ8Qv8yOD//LjQ6/y41\n        Q/8uNEb/LjVF/zA4R/8wN0j/LzdI/y82R/8vNUb/LjRF/y41Rf8tM0X/KzJE/yoxPv8qMTb/KjE4/zlC\n        Rv8hJyf/CQoJ/yInKv8uNj3/JSw4/ycuQP8nLkD/Jy4//yctP/8mLT//JCs9/yQrPf8kKz3/Iyk8/yEn\n        Ov8hJzr/ISc6/yEnO/8gJzb/IScv/yAmLP8zPkj/MDpD/xEUF/8OEBP/GB0i/yozPP8dJSz/Iiw1xicw\n        OokiKTH+JS00/x8nLP8QFBb/DA8R/yAmK/9DUFz/Slpc/0NQZf8MDtr/AgLw/wME6P8DBOj/BATo/wQE\n        6P8EBOj/BATp/wQE6f8EBOn/BATp/wQE6P8DBOv/AgLu/yQqaf9ic27/S1lh/wYICP8RFBT/NUBD/0JQ\n        Qf8pMXD/AwTt/wIC7P8CA+j/AgPq/wID6v8CA+r/AgPq/wID6v8CA+r/AgPp/wEC8P8AAOP/Iilg/0JR\n        Q/9CT1b/QEhO/yAlKf8LCwn/LDM1/zdch/9Fgsb/RH6//0N8vP9Ff8L/RX/C/0qFyf9Hg8r/U4/W/1uV\n        1P9bltn/YJzj/12X2f9altv/VpDS/1CJyP9HgcH/SIPH/0yGx/9TjtL/W5jf/1uW1/9YktL/V5PX/1+a\n        3P9ioej/PGiX/x8gH/86P0b/QUdP/y8wMf8uQlf/YJ7i/2Wf3v9fmNf/XZbV/1WOz/9TjMz/W5XX/1qW\n        2f9Si8z/WpTV/1yX2P9moeD/a6jr/2Kg5f9em97/WJPW/12Z3v9XlNv/UYrO/1SMy/9Vjcz/VY3L/1KK\n        yP9WkdT/aKfw/1qZ4f8wT27/KSop/zlARv81O0L/ISEd/y9Qdf9Qjtb/V5LU/2Cd4f9gm93/VpHV/1eV\n        3P9amN7/WZXU/1GKyf9Mhcf/SoPD/0qCw/9IgcL/RoC//0qFyf9Jhcv/Rn/A/0yGyP9PkNn/VJTb/1SR\n        1P9Kh8z/RH+//0N/wP9KiM3/PWud/y45QP8QEA3/Gx8i/zdASP8yOD//LzU7/zA2Rf8uNUf/LjRF/y41\n        Rf8vNUb/LjRF/y00Rf8sNEX/KzJD/ysyQ/8rMUT/KzFE/ywzP/8rMjj/KjI5/zlBRf8dISL/CAoK/yMp\n        LP8vNz3/JSs4/yctP/8nLT//Jy0//ycuP/8nLT//JSw+/yQrPf8kKz3/Iyk8/yIoO/8hKDr/ISc6/yEn\n        O/8hKDf/IScu/yAmLP80P0j/KDE4/wwOEP8QEhX/GyEm/ycwN/8fJi7/Iyw1sScwOXQjKjH7JCsy/yQs\n        Mv8TFxr/DA4Q/x4jKP9BTFj/SVhb/0ZUaf8PEtr/AQHw/wME6P8EBOj/BATo/wQE6P8EBOj/BATo/wQE\n        6P8EBOn/BATo/wQF6P8EBer/AQHv/xsffP9jc3X/U2Jq/wcICP8LCwz/MzxA/0NSRP8sNnT/BQbu/wEC\n        7P8CA+n/AgPp/wID6v8CA+r/AgPq/wID6v8CA+n/AgPp/wEC7v8AAPX/GR5p/0BMP/9EUVb/P0lO/yYt\n        Mf8PERD/KS4u/y5KaP9EgcX/RX7A/0V+wf9Ig8v/SYPF/1CHxv9KiMz/XZ7q/1uX2P9WkdT/YZ3g/1+a\n        2f9Yk9f/VY7O/1OLy/9Nh8j/S4XI/06Hyv9TjM//WJTa/1qV2f9Ri8z/UIrM/1yX2P9kpOv/P2mZ/x4g\n        Hv86QEf/QUhP/y8xMf8rQFb/XJ3l/2ej5P9fmtv/WJLV/1iS0/9ak9L/WZTZ/1yZ4P9UjtP/U47R/1eR\n        0v9ln9//bKfn/2Gd4P9ZlNn/WpTV/1uV1/9emt7/VpLY/1CKzf9YkM7/XJTT/1SMy/9Yltv/aKjx/1qZ\n        4v8wUHH/KCon/zpAR/82PEP/ICEd/y9Qcf9Oi9P/UYvM/1eS0/9XkdH/Uo3Q/1SQ2f9Tktr/VpLW/1WO\n        z/9Qicz/UozP/1SP0/9PjND/SoTH/0uFyP9KhMf/RH6+/0N+wf9GhM3/R4bR/0aEyv9Egsf/Qn29/0N9\n        v/9Mi9H/OF2F/ykxM/8TFBT/Iicq/zU9RP80O0D/MDY//zA4R/8vNkf/LjVF/y41Rf8tM0T/LDFC/y0z\n        RP8tM0T/LDBD/yowQf8qMEL/LDJD/y00Pv8sMzn/LTU8/zlCR/8WGhr/CgsL/yUqLv8uNTz/JSs5/ycs\n        P/8mLD//Ji0//yctP/8nLT//Ji0//yUsPv8kKzz/JCo8/yMpPP8iKDv/Iig7/yIoO/8iKDX/ICYs/yEo\n        L/81QUv/Ji40/wsMD/8RFBf/ICYs/yQrM/8eJS3+Iyw1migyO14kLDT6Iigv/yYtNf8VGh7/DA8R/x0i\n        J/89SVP/SFdd/0xZZ/8ZHsL/AADu/wME6f8DBOj/BATo/wQE6P8EBOj/BATo/wQE6P8EBOj/BAXo/wQF\n        6P8EBer/AQHw/xETlv9fbnz/Wmlv/w4PEf8HCAf/MDo+/0JRR/8xPGj/CQvc/wAA7/8CA+n/AgPp/wID\n        6f8CA+r/AgPq/wID6v8CA+n/AgPp/wID7P8AAfT/DhGK/zxISf9GVFT/QUtQ/y41O/8TFhf/HyIf/yw/\n        Uf9Ig8b/RoDD/0qDw/9OitD/TYfK/06Hxv9Lic7/XJ7p/1uV1/9Vj9H/YZzf/12Z2f9Ujs7/VIzL/1KM\n        zf9Oic7/TojL/1GLzv9Tjc3/VI3M/1SMzf9Tisr/U4zM/1qU1v9lo+j/Q2yZ/x4hHv88Qkj/Q0pS/zI0\n        NP8oPVP/V5fi/2ej5/9emdr/WZPX/1mS0/9bk9L/V5HU/1yY3/9bl9v/WZLR/16X0/9jndv/ZJ3Z/1uU\n        0/9VkNL/W5TV/1eQ0P9YkM//WZHS/1WO0v9bl9v/aKPj/1ySzv9bldf/b63z/2al6v8yUG//KCkn/ztB\n        R/82PEP/ICAd/zFSc/9SkNf/UYnJ/1CKy/9Lh8n/SoTD/1uY3f9hnuP/WJLS/1aQz/9TjtD/VY/Q/1mU\n        2P9Vktf/VI3O/1ON0P9Qi8//SoPD/0Z/wf9Khs3/UIvR/0iBw/9HhMr/SIPE/0eBwf9KiMz/MUxo/yQm\n        Iv8VGBn/KjE2/zc/Rv81PEL/MjhC/zE5SP8xOEn/MThI/zA3Rv8uNUX/LzRF/y0zRP8rMUL/KS9A/ykv\n        QP8rMUL/LTNE/y00Pv8sMzn/MDk//zhBRf8QExH/DhEQ/ygvMv8rMjj/JSo7/yYsP/8mLD7/Jiw+/yYs\n        Pv8mLD7/Jiw//yYsPv8lKz3/JSs9/yQqPf8jKTz/Iyk8/yMoPP8jKDT/IScs/yUtNP86RlH/JSwz/wsN\n        D/8RFRj/Iyow/yIpL/8fJi/+JC03giczO0IkLjbvHyUs/ygwN/8YHSL/DA8S/xofI/84Q0v/SVdf/05c\n        Zf8gJKf/AgHs/wMD6v8EBOj/BATo/wQE6P8EBOj/BATo/wQE6P8EBOj/BAXo/wQF6P8EBer/AgPv/w0P\n        mP9XZHT/Xm5y/xkeH/8GBwb/KzI1/z9MSP83Qlj/ERXB/wEB8/8CA+n/AgPp/wID6f8CA+n/AgPq/wID\n        6v8CA+n/AgPp/wID6/8BAfH/Bgai/zdAS/9GVFD/QkxT/zpCSP8WGhz/FBUR/zE+Sf9DeLX/SIXL/1CJ\n        y/9QjM//TYjI/0yGx/9NiMv/WJbc/1mW2/9alNf/Xpnb/12Y2P9Zk9T/VpDS/1GKyf9PiMr/Uo7V/1qU\n        2P9blNP/WJHQ/1iQ0f9WkM//V5HS/2Ga2f9qqOz/Q26d/x0fHf89Q0n/RUxV/zI0Nf8qP1L/V5bf/2Cf\n        6P9cmNz/Xpnd/2Gc3v9fmtz/X5nc/2Ca2/9ppOn/aKPn/2Kc3v9hm93/ZaDg/12X2P9bl9z/ZJ/f/16Y\n        2v9Zk9L/XZXT/1+Z2v9fn+j/Y6Pr/2ah4v9nouL/crT6/3a8+f84V3X/Jycl/zpARv81PEL/IB8c/zFT\n        dv9Vk9v/U4vM/0+Hxv9Ph8b/TYfJ/1iZ4/9bnOX/V5LU/1uX3f9TkNb/UovK/1GNz/9Ujcz/WZHQ/1qU\n        1f9YlNr/VI3Q/0+Kzv9Tkdv/Wpfd/1ONzv9Ig8f/SYPD/0yJzv9Kg8X/M0dZ/xkaFf8RFRb/Mjk+/zg/\n        R/80OkH/MjhE/zE4SP8xN0j/MjhJ/zE3SP8wN0b/MThI/zA2R/8sMkP/KjBB/yswQv8sNET/LTRD/y00\n        Ov8sMzn/MztB/zM7P/8PEBD/EhUV/yowNf8pMDb/Jy08/ycuP/8nLT//Jiw+/yYsPv8mLD7/JSw9/yYs\n        Pv8lLD7/JSs9/yQqPf8jKjz/Iyo8/yMoPP8jKDT/ICcs/ycvNv86RE//HyYs/wsOD/8TFxv/KC82/x8l\n        K/8hKTH9Ji84ZCgxOjMlLjfZHyUs/y01O/8bICT/DQ4S/xccIP8zPUb/Slhg/1BfaP8lK6z/AwPt/wMD\n        6f8EBOj/BATo/wQE6P8EBOj/BATo/wQE6P8EBOj/BAXo/wQF6P8EBen/AgPv/wkKuv9GUGj/YG9x/yMr\n        L/8FBQX/JSot/z9LTP89SUv/HCGo/wEC9f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID\n        6v8BAvD/AwTO/y42TP9FUkr/Q05V/z5HTP8dIiX/DxEP/y84PP83X4z/S4nQ/02GyP9Nis//TojJ/06G\n        x/9Kg8f/UYvO/1mW3P9XlNj/WpPR/12W1f9clNX/W5TX/1uU1v9Zk9X/UI3T/1uX2/9inN3/WZLQ/1uV\n        1f9gm+D/Y6Dm/26q7P9ur/L/RHKj/xwdHP88QUj/REpS/zAyM/8qPVL/VZLX/1mW3P9cltr/XZfb/1+Z\n        2v9bldf/W5bZ/2Cb3P9kn+P/Xp3k/2Cc4f9hm9z/YJva/1uU1P9bldn/ZKHm/2aj5/9dl9f/V5HP/1eR\n        0f9dmNr/YZ7i/2il6/9zsPL/cK/v/2yv7/84VnX/JiYl/zk+Rf80OkD/Hh0b/y5Pcf9SkNb/VI/R/1WQ\n        0v9Vjs//U47S/1WT3P9altz/YJve/1uY3/9Pis//UovL/1OP1P9Uj9L/VpDP/1KLzP9Qi9D/T4vQ/0yJ\n        z/9KidL/S4fM/0qFxv9Jhsz/R4PE/0yK0v9Cc6z/M0BK/xUXFP8YHB3/Nz5F/zg+Rf8zOD//MjlG/zE3\n        SP8vNUX/LzVG/y81Rv8wNkb/MThJ/zE4SP8uNUX/LDJD/y0yRP8tNEX/LjVC/y81Ov8sMjn/ND1E/y41\n        Of8MDw7/FRga/ywzOP8pMDr/KS8//ykxQf8pL0D/Jy4//yctP/8nLT//Jiw+/yYsPv8lLD3/JSs9/yQq\n        PP8jKTv/Iyo8/yMoPP8iKDP/ICYr/ykxOv84Qk3/HCIm/wsOD/8UGRz/KjM7/x0jKf8gKDHxIyw1SSUt\n        NiUlLTjEICYt/yw1PP8aHyP/DQ8S/xUZHP8yOkT/TFlk/1JhZv8xOaD/BQbt/wMD6f8EBOf/BATo/wQE\n        6P8EBOj/BAXo/wQF6P8EBej/BAXo/wQF6P8EBej/AwTv/wQF2v8zO2D/ZHNy/y85P/8DBAT/Gx8h/z1I\n        Tf9CTj3/JCuM/wIC9P8CAur/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8BAu//AQHs/x0i\n        Vv9DT0b/RVFW/0BITf8oLTL/EBIT/yIjHv8uSGH/SofM/0uFxf9Mhcb/UYnJ/0+Jy/9KhMj/U47T/2Wh\n        5f9jnuD/X5nd/12X1/9ak9H/WJDP/1uV1f9VkdP/UInN/1mU2P9hnN3/X5vc/2Cc3v9fmNj/W4/K/1eE\n        sv9JbZH/MUlg/yQnKP8+REv/QkhR/zI2Of8jLzn/NVNx/zpWdP88WHX/PFh1/ztYdv84VHL/OVVy/ztY\n        dv87WHb/OVd2/0Bfff9BX33/Old0/zhVc/85VXT/O1p6/0Fffv89Wnb/OFRw/zdTcP85VXH/PVl2/zxa\n        ef9CYH//R2SB/0RjhP8rO0n/KS0u/zpAR/84PkX/JSco/yM1Rv82V3r/P2eS/0l7sv9Qh8T/V5LT/1ya\n        4P9ioOj/Z6Pp/1aR1P9Oh8j/U4vJ/1ON0P9TkNb/Vo/P/1iS1P9VkdT/TYjL/0iDxv9Ggsf/Q3y8/0R+\n        vv9Ihcn/SYTG/0qIzv85X4f/Jysr/xQVFf8mLC//OUBG/zY8Qv8xNz//MTdF/y81Rv8uNET/LzVF/y40\n        RP8uNET/MDZG/y82Rv8tNET/LDJD/ywyQ/8sMkT/LjRA/y41Ov8rMjn/OD9F/yctMf8LDA3/GR0f/y83\n        PP8qMDr/KjBA/ykvQf8oLkD/Jy4//yctP/8nLT//Jy0//yctP/8mLD7/JSw+/yQqPf8jKTz/Iyk8/yMp\n        Ov8jKTL/IScs/y84Qv84Q03/GB0h/wwOEf8UGBv/KzQ7/x4kKv8fKDHaICkyNSQsNhcmLjerICYt/yox\n        Of8bICX/DxIT/w8RE/8sNDv/TFlm/1NiYP89R4H/CAnq/wMC6v8EBOf/BATo/wQE6P8EBOj/BAXo/wQF\n        6P8EBej/BAXo/wQF6P8EBej/BATt/wEC4f8kKHH/aXl8/z5JTv8CAwP/ERUV/zxGS/9DUEH/LDR5/wQF\n        6P8BAe3/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+z/AADu/w4Qif8/S0v/R1RV/0NM\n        Uv82P0P/DxMU/xQUEf8yRVf/Q3m2/0+Jy/9Si83/UYzP/02HyP9Pis//VpDT/2ai5v9loeb/ZaDi/2Ca\n        3f9bltv/WpPU/1SMy/9NhcT/VIzO/1uX3f9fm93/U4jB/0Nrmf84UGv/LDY+/y4yNv82Oz//OkBF/z5G\n        TP9BSU//P0dN/z1DS/83PEL/NTk+/zU5Pf82Oz7/OT1A/zk9Qf85PUH/ODxB/zc7P/83Oz7/ODw//zk9\n        Qf86PkP/Oz5D/zo9Qv86PUL/Oj5C/ztARP89QUb/PkJH/zxARf85PEL/Njs//zU6Pf81ODz/Njk+/zY6\n        P/80OT7/NjtB/0JJUf9FT1T/QUpN/ztDRv84PkH/LzU2/ykyN/8uQ1b/O1+G/1KJx/9trfX/b7H6/1aQ\n        1P9Oh8j/T4jK/1GJzv9XkdP/XZbU/2Kc3P9cmd7/VY7Q/1OMz/9Ukdj/TofL/0iCxv9IhMj/SITI/0N8\n        vf80TWb/Hh8c/w8QEf8uNDn/OUBH/zM5Pv8vND7/MDRF/y81Rf8wNkb/MDZH/zA2Rv8uNEX/LzVF/y40\n        RP8tM0T/LDJD/ywxQv8rMUL/LDE8/ywyOP8rMjn/OUFG/xwhIv8JCgr/HSIl/zE5P/8pLjv/KS9B/ygu\n        QP8oLkD/Jy1A/yYsPv8mLD7/Jiw+/yctP/8nLT//Jiw+/yUrPf8lKz3/Iyk9/yMpOf8jKTD/Iigu/zU/\n        Sv82P0r/EhUZ/w0QE/8VGR3/LDM8/x4lLP8gKDLCISkzJCcxOggoMTqNIyox/ykwN/8iKC3/ERQX/w0O\n        Ef8nLDL/RlJe/1JhX/9IVXv/DhDf/wEB7P8EBOf/BATo/wQE6P8EBej/BAXo/wQF6P8EBej/BATo/wQF\n        6P8EBej/BAXr/wEB5/8WGYf/ZnZ8/0xZXv8HCQj/CQsL/zdARf9BTkn/MTxf/woOzf8BAfL/AgPp/wID\n        6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+r/AADx/wkKu/81PkP/R1VO/0RPVP88RUr/GR4g/xMV\n        Ff8qMjX/N16I/1CM0f9Uj9T/VZHX/1OLyv9VjtH/VY/R/16Z2v9ind//ZJ7d/2Od3P9hm97/X5jY/1OM\n        y/9Ri9D/XJjg/1CGwf8+YYj/MEBQ/youL/8yNTj/OT9A/z9HS/9FTVD/R05S/0hQVf9IUFb/TFVb/0VL\n        Vf89Q0r/PEFH/zxBR/8/REv/QUVM/0FGTf9BRk3/QUdO/0JITv9CSE//QkhP/0FHTf9CR07/Q0hP/0RJ\n        UP9FSlH/RUpR/0RJUP9FS1L/RkxT/0VJUv9CR07/P0VL/z1DSf89Qkj/PENI/ztBRv86P0X/OT9G/09Z\n        Zv9RWmL/TFRb/05VW/9NVVn/S1NV/0hPUP9AR0f/Mjg4/zJCTv9Iaov/X5TP/1mX3/9TjtH/UInK/1ON\n        0v9em+H/Y57e/2Cb3P9YlNb/VI/S/1aR1f9YlNj/W5TV/06Hyf9HgcX/TIrO/z9upP8tOUP/GBsZ/xYZ\n        G/8zOkH/OD5G/zE3Pf8vNUH/MDZH/zA2Rv8yOEj/MTdI/zI4R/8yOEn/MjhJ/zE3R/8wNkf/LjRG/y40\n        Rf8tM0L/LDI7/ysyN/8wNz3/OUNH/xQXGP8KDAv/Iyks/zA4Pv8oLjz/KS9B/ykvQP8pL0D/KC9A/ygv\n        P/8oLj//Jyw+/yYsPv8mLD3/JSs9/yUrPf8lKz3/Iyk9/yMpN/8jKTD/JCsy/zpFT/8xOUH/DhAT/w8S\n        Fv8dIij/KDA4/x8mLv8gKjKqIyw0FCoxPAAsND1qJS029yMqMf8nLjX/FBcb/w4QE/8fJCn/O0VQ/1Bd\n        YP9MWnH/GBvD/wEB7v8EBOf/BATn/wQE6P8EBOj/BAXo/wQF6P8EBej/BAXo/wQF6P8EBej/BAXp/wIC\n        7f8QE6f/VmNq/1ZkaP8WGhv/BwgI/y84O/9BTU7/PElJ/xYbtP8AAfX/AgPp/wID6f8CA+n/AgPp/wID\n        6f8CA+n/AgPp/wID6f8CA+n/AQLy/wID2v8iJ1X/R1RL/0ZSVv8/SE7/KzI2/w0QEf8dHhr/NU5p/06I\n        yv9Vk9v/VI7R/1iQz/9UjM7/WZPW/2Se3/9noOD/Z6Hg/2Kb2/9gmNf/YJrb/1eU2f9Ti83/RWuY/zBB\n        Uf8pLS3/Njo7/0NLTf9HUFP/SlJY/0tTWv9OVV7/TlVe/05VXv9RV2D/W2Rw/0BGT/8nKy3/Jyst/ygr\n        Lf8pLC7/KSwu/yotL/8qLS//Ky4w/ywvMf8rLzH/Ki4w/yotMP8rLTD/Ki0w/youMP8qLzH/Ki4x/yst\n        MP8qLTD/Ki4x/youMP8qLS//KSsu/ygrLf8oLC3/KCwt/ygrLf8mKi3/Mzk+/1Rdaf9SWWP/SE5Y/0xQ\n        Wv9PVV7/UFhh/09WYP9RWV//Ulpe/0dMS/80ODX/N0ZS/z1hh/9OhL//WJPV/1mU2f9hour/WpXW/1aP\n        0f9XkND/U4rJ/1CIx/9WkNL/W5XW/06Fxf9HgsX/S4jO/zpehf8lJyj/DxAP/yctMP85P0b/Nz1D/zI3\n        P/8wNUT/MTZH/zE3R/8xN0f/MTdH/zE3R/8xN0j/MjhJ/zI4SP8xN0f/LzVG/y81Rv8tM0H/LTQ6/ywy\n        OP8zOkD/NDxA/xETFP8PEhL/KC4x/y0zO/8oLj3/KS9A/ykvQP8oLj//KC9A/ygvQP8oLkD/Jy0//yct\n        Pv8mLD3/JSs9/yQqPP8kKjz/JCo9/yQqNv8jKS7/Ji42/z1JU/8qMjj/DhET/xATFv8kKzH/Iiow/x8n\n        L/8iKzOMQUhKAys0PgArND5MJzE75yIpL/8uNz7/Fhse/w4SE/8YHSH/N0BI/05bY/9QXmj/KC6w/wMD\n        8P8EA+j/BATn/wQE5/8EBej/BAXo/wQF6P8EBej/BAXo/wQF6P8EBej/BAXm/wMD8f8HCMf/QEhb/2Jy\n        dP8iKSv/AwUE/yUsLv9ATFH/QU46/yEomP8BAfP/AQLq/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID\n        6f8CA+n/AgPs/wAA6v8SFIr/Pkg//0hVVv9FTlP/Nz5F/xATFf8aHBv/LTxI/0l6sv9dnOX/VI/U/1uV\n        1v9Ris7/Ypzf/3Cr7f9spuT/ZqDd/2Oc3f9gneH/W5ri/0h2qv8vQ1j/KzA0/zQ3Nv9CSUz/TFVb/05W\n        Xv9NVV7/TVNd/0pPWf9KT1r/SU5Z/0dNV/9JTln/WGBt/zg9Qv8UFxb/ExgY/xQYF/8TFxb/EhcX/xMW\n        GP8TFxb/EhcX/xIWFv8SFRX/ExUW/xMWFv8TFhb/ExYX/xMWGP8SFhj/ExYW/xMWFv8TFhb/ExYW/xMW\n        Fv8TFhf/FBcX/xUYGP8VGBf/FRgY/xQZGf8UGBb/LDAy/1BYYv9PV2D/SE5Y/0lOWf9ITlj/SE5Y/0hO\n        Wf9LUFv/T1Re/1FXYP9SWV7/RUpK/zM5Of8tPk//QWqY/1eT1/9kpvH/YJrb/1iR0/9ak9L/WI7L/1OL\n        y/9enOL/YqDl/1CHxf9OiMz/Rn29/zBDVf8iJSL/DxEQ/y82O/87Qkn/NjxC/zM5Qv8yOEf/MjhH/zI4\n        SP8xNkb/MTZG/zE3Rv8wNkb/MTdH/zI5Sf8yOEj/MDZG/y81Rv8tMz//LTM6/ywxOf82PkT/LjU4/w4Q\n        EP8UFhj/LTM3/ysxO/8qMEH/KS9A/ykvQP8pL0D/KS9A/yguQP8nLT//Jy0//ycuP/8mLT7/JSs9/yUr\n        Pf8kKjz/JCo9/yQrN/8iKi7/KjQ8/z9LVf8iKC7/DxIT/xEUF/8qMjn/ISgu/yApMvYkLTZlIiw1ACkx\n        OwApMTswKTM70iQsMv8wOED/GBwf/w8SFP8SFRn/Nj5H/01aZv9TYlv/NDyS/wQE8f8DA+j/BATn/wQF\n        5/8EBej/BAXo/wQF6P8EBej/BAXo/wQF6P8EBej/BAXm/wME7/8BAdb/KC5z/3GBhf8xOD3/AAAA/xcc\n        HP9ASk//QU5D/ys0c/8ICdv/AQHw/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wEB\n        9P8GB7X/LjY8/0pXVP9GUFX/P0dN/yInKv8REhL/Iycl/z9ljP9Ukdf/T4rK/1aOzv9Qi8//YJzg/2+q\n        6/9qo+D/Y57f/2en8/9fm97/PmaR/ygyO/8uMC//PEFD/0lRWP9NVFz/TFNc/0pQWv9ITlj/SE5Y/0lP\n        Wf9JT1n/SU9Z/0hOWP9KUFr/WGBq/zM3Ov8bLkL/L16Q/zRilP8yYZL/Nmec/zxrof81YZH/MV6R/zJf\n        kf84ZJP/Pmqa/zlnlv84ZJX/OGaY/zZmnf85Z5v/N2KT/zJejf8yXo7/NGGT/zFdjf8vXIv/MV+T/zBe\n        kv8vW4z/L1yP/zFhl/8iO1f/KCot/01SWv9SWWL/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9ITlj/SE5Y/0lP\n        Wf9MUlz/UVdh/05VWf86PT3/JzA0/zVVd/9dmt7/aqnv/2Gc3v9joOj/ZaHn/1qT1f9gnuP/aKTl/1yW\n        2P9Xktb/Q2+e/yguMf8VFxb/HSEj/zg/Rf86QEf/NjxC/zM5Rv80Okr/MzlI/zE3R/8wNUX/MjdH/zE3\n        R/8xNkb/MTdH/zE3R/8xN0f/MTdH/zE2Rv8wNT7/LjM5/y0zOv86Q0j/Iico/wgJCv8YGx3/MDc7/yow\n        PP8rMUP/KjFB/ykwQP8pL0D/KS9A/ykuQP8nLT//Jy0//ycuP/8nLT7/Jiw+/yUrPf8kKT3/JCo7/yUs\n        M/8jKS//MjtF/z5IVP8WGh7/DxIU/xMWGf8sNDv/Iikv/yErM+QjLTVHIy01ACgwOgApMToWKjI7tSUs\n        M/8tNjz/HyQq/xETF/8OERT/MTlB/0tYZP9XZVz/P0qI/wUG6f8DAur/BAXn/wQF5/8EBej/BAXo/wQF\n        6P8EBej/BAXo/wQF6P8EBej/BAXn/wQF6/8CAuX/Gh2U/2t6ef9DTVP/BQgH/w0REP84QUX/Q09K/ztG\n        TP8TFsX/AAD1/wIC6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPo/wID7/8BAdr/HSJs/0hU\n        R/9IU1j/R1BV/zQ8Qv8NEBD/HiAd/zBCUP9PhsX/U47Q/1GKzP9Ri9D/X5vh/2ql5/9qpeT/bq/1/1yV\n        1/84U3P/KS80/zU4N/9CS03/SlFZ/0tSXP9KUFv/SU5Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0hO\n        WP9LUVv/WGBn/yovMf8qRmX/X5zh/2Gd4v9fnN//bq3y/3Sx9f9jnd7/Y5/h/2uo6/94tfT/fLn4/3Sw\n        7/9vq+r/bKjp/2+s7/9wrO3/a6bm/2ej4v9ln9//ZqHk/2Wf3/9gmtr/YZvb/2Ca2/9fmNn/X5rb/2Sj\n        6P85XYf/ISQq/0dMU/9VXmb/SVBZ/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9ITln/SU9a/0xT\n        XP9OVVz/REpM/y80NP8ySGH/VIjC/2em7f9tr/n/aajw/1qT0/9bldX/XJXU/1iT1/9PiMn/Mklh/yMl\n        I/8NDw//LDA2/z1DSv83PUP/NDpB/zQ5SP80Okv/NDpJ/zI3R/8yN0f/MzhI/zE3R/8yN0f/MjhI/zA1\n        Rf8wNkb/MjhI/zE3R/8yOD//LzQ6/zE4P/86Q0j/GBwd/woLDP8hJin/Lzc8/ykvPP8rMUL/KzFC/ysx\n        Qv8qMEH/KTBB/ycuQf8nLT7/Jy0//yctP/8mLT7/Jy0+/yYsPf8kKj3/JCo6/yQrMf8lKzH/OEJN/zxG\n        Uf8RFBf/DxEU/xofIv8rMzr/Iykw/yMsNdMjLTUpIy01ACwyPAAyNkIBKzM8iyQtNfwnLjT/Jy0z/xIV\n        GP8QEhT/KzE4/0dSXv9WZWT/SVV6/xIUzv8BAe7/BATn/wQF5/8EBef/BAXo/wQF6P8EBej/BAXo/wQF\n        6P8EBej/BAXn/wQF5/8CAvP/CQu2/01XYP9cam//FBka/wYICP8rMjX/RE9Q/0BNQf8cIaj/AQDx/wEC\n        6/8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8BAfX/Cw2h/zlDPv9MWFj/SVNY/0FK\n        UP8gJCj/Dg8O/yYpKP9FbZv/UozR/1KJyv9Qicj/WpXY/22o6f92s/T/YZjV/zFGW/8sLzD/PEJF/0VM\n        Uv9LU1v/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lOWP9NVF7/UFdc/yAm\n        Kf8zV33/ZJ7f/2KY1f9gl9P/ZZ/e/2ig3v9hmNf/a6Xl/3Ct8f98uPb/f7r2/3Su6/9vqOX/bqfn/3Kr\n        6f9spOD/aqHd/2qj4P9nn9z/Z53a/2if3P9imtn/ZJvX/2Sa1v9jmdb/ZZvY/2ei4v9Dapj/HCMq/zs/\n        Qv9VXWX/SlBZ/0hOWP9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9KUFr/Ulhi/0xS\n        Vv8xNTP/Lj1M/1OEvP9us/v/aafr/12V1v9emd3/VI7P/1GN0v9Ecqf/KjE2/xMSEP8bHiH/NzxD/zg+\n        RP81OkD/MzhC/zM5Sf80Okn/NDlJ/zM4SP8zOUn/MzpJ/zI3R/8xN0f/MTdI/zE3R/8yOEj/MjhI/zE4\n        RP8yOj//MTY8/zc/Rf8zOz7/EhQV/xASEv8sMzb/LTM8/yguPv8qMED/KjBA/ysxQv8rMUL/KjBB/ygu\n        QP8nLT//Jy0//yctPv8mLD7/Jy0+/yYsPv8kKj3/JSs5/yUrMf8mLjT/PUhS/zQ9Rf8RFBf/DxIU/yMp\n        L/8mLTT/ISkx/yUuOLIpMTkKKTE5AAAAAAAlLzsALDQ9XSYtNvIjKi//LTQ7/xIVGP8RExX/ICUq/0NN\n        Wf9VY2n/U2Bp/yEnt/8BAfL/BAPn/wQF5/8EBef/BAXn/wQF6P8EBej/BAXo/wQF6P8EBej/BAXn/wUF\n        5v8EBPL/AgLE/zc/b/91h4j/JCos/wEAAP8fIyb/RE9T/0FNRP8vN2v/CAng/wAA8P8CA+n/AgPp/wID\n        6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID5/8BAvH/AgLR/yMpXv9JVUv/SVVa/0VOU/8yOD7/Dg8Q/xwd\n        G/8sPUz/S4C8/1KLy/9PhsP/VY7O/3Sx8/9sn9P/N0lb/ykrKv9ASEr/TFVb/0tQWv9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9SWWP/PkJD/xshJ/9Ecqf/Y53d/2qh\n        3P9nn93/X5bS/2CX0/9kmtf/Z57b/2Wd3v90r+z/gLv4/3Wv7v9wqeb/cKvs/2+o5/9qot7/ZZzY/2Wc\n        2f9mndn/Zp3Z/2Sc2f9jm9f/Zp7b/2Sb2/9hmNX/YJjV/2Se3/9Pgrv/Hyw5/zAyMv9RWWD/S1Fb/0hO\n        WP9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9a/0xTXf9LU1f/Nzw6/yw6\n        R/9Th73/bKzx/2GZ2f9bldf/WJTW/1KN0v82UG3/JCYl/w8REf8oLjL/Nz5E/zQ7QP8yOD//MzhH/zM4\n        Sf8zOkj/MzlJ/zQ6Sf80Okn/NDlJ/zM6SP8zOUj/MjlI/zM4SP8yOEj/MTZH/zE3Qf8yNzz/MTc+/ztE\n        S/8nLS//CgsL/xQWGP8yODz/LDI8/ykvQP8qMEH/KjBA/yowQf8qMEH/KS9A/ykvQP8pL0D/KC4//ycu\n        P/8nLD3/Jiw9/yUrPf8lKjz/Jis3/yUqMP8sNDz/QUxX/yctM/8RExf/DxIW/ygwN/8mLDT/ISkz+yYw\n        OYAeJjUAAAAAAAAAAAAqMz0AKzM9NycvONwnLTT/Lzg//xUYGv8SFBb/FBcb/z9IUv9TYGv/XGpf/zE4\n        ov8BAPH/AwPo/wQF5/8EBef/BAXn/wQF5/8EBej/BAXo/wQF6P8EBej/BQXn/wUF5/8FBez/AQHj/yQp\n        kf9xgn3/OEJF/wMDA/8SFBX/OkNH/0NPSf87R03/EhXI/wAA8f8BAun/AgPp/wID6f8CA+n/AgPp/wID\n        6f8CA+n/AgPp/wID6P8CA+r/AADy/w0Pj/89RUT/TVhZ/0dRVf9ASU7/ISUp/w0NDP8kKSn/PGCG/1SO\n        z/9Ti8r/WpTV/12Qy/82SFr/MzMy/0FITP9OVl3/TVNd/0pPWv9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0pQWv9VW2P/Kiwr/x4vQP9ck9H/ZZ/f/2+m5P9tpeT/YZjV/2OZ\n        1P9lnNf/Y5nV/2KY1P9speP/f7j1/3m07/97tfH/cavr/2yk4v9rpOH/ZJzZ/2qi4P9ontr/Y5rW/2Wc\n        2f9lm9f/ZJ3Y/2Ka2v9km9j/Y5rV/2ac2f9kndv/LEdj/yAiIf9MUVb/Ulli/0hOWP9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lOWf9NVF3/T1dd/zU4N/8qOEf/TH22/12Z\n        3f9XkM//XZrd/0ZypP8tNz3/ExMQ/xodH/82O0H/NTpA/zM4Pf8xN0L/NTpL/zY7S/80OUn/NDlJ/zU7\n        S/82O0v/MzpK/zU7Sv83PUv/NjxK/zM5SP8xN0f/MTZF/zE3Pv8wNTr/MThA/zxFSv8eIyT/CQoL/xwh\n        Iv8wNz3/LDE+/ywxQ/8rMUH/LDJB/ywyQv8qMED/KC4//yguQP8oLj//KC4//ygtP/8nLT7/Jis9/yUq\n        Pf8kKjv/JSsz/yQqL/8zPEX/Q05a/xkdIf8PEhX/EhQY/ysyOv8oLzf/Iys08iYvOFUlLzoAAAAAAAAA\n        AAArND0AKzU9EykyO7goLzj/LDM7/yAlKv8SFRf/EBMV/zI5QP9MV2P/XGpn/0FLhP8LDNb/AQHt/wQF\n        5/8EBef/BAXn/wQF5/8EBef/BAXo/wQF6P8FBej/BQXo/wUF5/8FBej/AQH1/wsMpP9VX2z/W2ls/w0Q\n        EP8GCAn/LDM1/0VQUP8/S0b/JSqS/wIC7/8BAuz/AgPo/wID6f8CA+n/AgPp/wID6f8CA+n/AgPp/wID\n        6f8CA+j/AQLz/wIDzf8lKln/S1ZN/01YXP9IUVf/Nz1D/xIVFv8TExD/LDlF/0+Dvv9ZlNn/T4TC/y5B\n        Wf8tLzD/SE5S/1BYX/9NUlz/SE5Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/01TXf9LUFT/HiEh/zFVfv9lnd3/ZZzb/2ef3f9mndz/Y5rY/2Oa1f9lm9b/Zp3b/2if\n        2/9qo+P/ebX1/3Kt7P9yre7/bKXj/2ef2/9qod7/Z57a/3Go5f90quf/b6bi/22m4/9mnNr/Z57b/2Sb\n        2v9imdX/ZJvW/2Wc2P9po+L/Qm6g/xggJP88P0H/V15n/0lOWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/T1Zf/05UWv8zNjT/KDZF/0+Auf9Zltz/V5DS/zVK\n        X/8aGRX/ERMT/y4yN/85P0b/NjtA/zM3Pf80OUf/Nz1N/zc9TP82O0v/NTtK/zU7Sv82PEv/NjtL/zU7\n        S/81O0v/NTtK/zM4SP8yOEn/MzlD/zI4Pv8wNz3/OEBH/zQ7P/8TFRb/DA4O/yoxM/8vNj3/LTJB/y0z\n        RP8sMUP/LDFC/ywyQf8qL0D/KS8//yguP/8nLT7/Jy0+/ygtP/8mLD7/Jis9/yUpPP8kKTn/JCow/yQr\n        Mv85Q03/PUhS/xQYG/8PEhT/HCEm/ysyOf8lLTT/JSw22ycwOScmLTcAAAAAAAAAAAAtNT0AMTg8BSw0\n        PYQmLTf9KC41/yoyOP8RFBb/ERMX/yUrMf9HUV3/Wmdr/1Vidf8dIMn/AADw/wQF5/8EBef/BAXn/wQF\n        5/8EBef/BAXn/wUF5/8FBej/BQXn/wUF5/8FBef/BAXw/wEByv87Qnv/cYB8/x4iJP8BAwL/HiQl/0JM\n        Uf9DT0L/OEBZ/wcJ4f8AAfD/AgPn/wID6P8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+j/AgPs/wAA\n        8v8MDo//PkdH/1BcWf9LVVn/RU5T/yYqLf8LDAr/HyIh/z9fgv9emd7/MlB0/yQmKf9ESk7/U1th/0xT\n        XP9ITlj/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SE5Y/1Na\n        Y/84Ozv/GCQv/1CEvP9moN7/bqfm/2yn5v9jmdf/ZJvZ/2Wc1/9lm9f/a6Lg/22l4f9nndr/ZZ/g/2ae\n        3f9mnd3/ZZzZ/2me3P9so9//a6He/3au6/9+uPP/dq/r/2+o5f9nntn/a6Pj/2yk4/9km9f/Y5rX/2if\n        3f9pouD/XJPS/yAzSP8nKSj/U1lg/01TXv9ITlj/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9ITlj/SU9Z/01UXP9KUlX/LzIv/yxCWv9VkNX/SXSk/yUrLf8PDwz/ISUm/z1E\n        Sv89Qkn/Nz1D/zQ6RP83PEz/OT9O/zg+Tf84Pk3/Nz1M/zY7S/81O0r/NjtL/zQ6S/81Okr/NDpJ/zM4\n        Sf80Okn/NTtE/zU6QP8yOED/PEVL/ygvMP8JCgr/EhUV/zI6Pv8xOEH/LzRF/y80Rf8tM0T/KzFC/ysx\n        Qf8qMEH/KjBA/yowQf8oLz//Jy4+/ykuP/8nLT7/JSs9/yUqPP8kKTf/JCku/ysxOf9CTFf/LTU9/xIV\n        GP8PEBP/Ji0z/ywzOv8iKjH/Ji44qSgtNwsnLjcAAAAAAAAAAAAsNDsAeF0AACs0PVMnLzjqKTA3/yw0\n        O/8SFhn/ERMW/xkdIf9DT1f/VWJq/2BtaP8rMbH/AADu/wME6P8EBef/BAXn/wQF5/8EBef/BAXn/wQF\n        5/8FBej/BQXo/wUF5/8FBef/BQXq/wAA8v8bH5D/a3h3/0NNT/8FBwf/EBMU/zlBRv9FUU3/P0pI/xsg\n        qv8AAPP/AQLq/wID5/8CA+n/AgPp/wID6f8CA+n/AgPp/wID6f8CA+j/AgPo/wEC8/8BAdj/ICVZ/05Z\n        Tv9QWl3/SFFW/zpBR/8WGRz/Dg4L/zI/Sf86Wn7/JDA8/zg8Pf9PWF3/TlRe/0lOWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9ITlj/S1Jb/09VWf8kJyb/LExv/2Oc\n        2v9mntz/cavs/2yn5/9jmtf/aJ/b/2ed2v9lm9f/cajm/3Wt6/9upeH/aqDd/2mg3v9lnNr/bqXh/3y0\n        8P95sOz/b6jl/3iy7v95su3/b6fj/26l4f9on9r/aqHe/26l4P9qoN3/aJ7d/2uh3v9poNv/a6Xl/z1k\n        k/8WGx7/PkJE/1RcZP9ITlj/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lOWP9QVl7/S1FU/ygwNf8vT3P/MURX/xQTD/8UFhf/Nj1B/z9GTP89Q0r/OT5H/zg+\n        TP84P07/OT9O/zk9TP85Pk3/OD5N/zY8S/80O0r/NDpK/zQ6Sv81O0r/NjxL/zM5Sv80O0b/NjxC/zQ6\n        P/81PET/O0RI/xogIP8ICgn/HyMk/zI4Pv8xN0T/LjRF/y40RP8uM0T/LTJD/ywyQv8rMEL/KjBB/yow\n        Qf8pMEH/KS4//ykuP/8nLD7/JSs8/yUsPP8nKzT/JCkv/zA5QP9FUFv/HyQq/w4RFP8RExb/KS82/yw0\n        PP8jKjP5KDA6dyUwNgQmMDgAAAAAAAAAAAAoMDkALjc/AC42PyYrMzzJKTA4/ysyOP8cISX/ERMV/xQX\n        Gf82P0f/UFtk/19tbP8/R5b/CQri/wEC6/8EBef/BAXn/wQF5/8EBef/BAXn/wQF5/8FBef/BQXn/wUF\n        5/8FBef/BQXo/wMD8f8FBrP/U1x4/2h3dP8RFBX/BQYG/ywzNv9DT1L/Q05C/zI5cP8GB+L/AQDv/wID\n        6P8CA+j/AgPo/wID6f8CA+n/AgPp/wID6f8CA+j/AgPo/wID6/8BAfL/BQel/zlBQf9UXln/Tlld/0ZO\n        VP8zOj7/DxAQ/xodHf8kKi7/Mzk//01UWf9NVFz/SU5Y/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0hPWP9HTlf/U1lh/zs9PP8ZKDT/UIO8/2qj5P9lm9f/ZJzb/2Ob\n        2v9mnNr/Z5/c/2Wd3P9nntj/bKPe/2+n4/96s/D/ebPv/2+o5v9to97/fbXw/4nE/v+Bu/X/d6/q/3Ss\n        6P90rOb/b6fj/2qh4P9tot7/baTf/3Or6P91rer/baPe/26k3/9ontr/a6Th/1+W0f8iNEn/IiMg/09V\n        W/9OVV7/SE5Y/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lO\n        WP9KT1n/UFdf/z9HSv8lKy7/HCAf/w4QDv8sMTT/P0VM/z5DSv86QEf/Oj5L/zxBUP86QE//OT5N/zg9\n        TP84PU3/OD5N/zc9S/83PEz/NzxM/zY8S/82PEv/NjxM/zQ6Sf80OUT/NDk+/zE3PP85QUj/NDs+/w4R\n        Ef8NEA//LDM2/zI4Qf8vNUX/LzRF/y80RP8tM0T/LTNE/y0zQ/8sMkL/KzBB/yovQP8qL0D/KS4//ygu\n        Pv8nKz7/Jis9/yYsO/8oLDL/JSkv/zU/R/89R1D/GR0g/w8RFP8aHyT/KzI5/yYtNP8mLTfiKjM6QCox\n        PAAoMjkAAAAAAAAAAAAAAAAAMDhAADE5QA4tNkCaKC84/iwzOP8nLDL/EBIU/xIUFv8pLjX/TVlj/1to\n        av9RXHj/EhTU/wAA7/8EBef/BAXn/wQF5/8EBef/BAXn/wUF5/8FBef/BQXn/wUF5/8FBef/BQXn/wQE\n        7f8AAOH/MDR1/3GAev8sMzb/AgID/xofIP9AR0z/RExK/z5KT/8aHbH/AAD1/wID6f8CA+j/AgPo/wID\n        6P8CA+j/AgPp/wID6P8CA+j/AgPo/wID6P8BAvD/AADl/xgbbP9KU0n/VmBg/01WW/9CTFL/JSot/wsM\n        Df8tMDL/TlZc/1BXYP9IT1j/SE9Y/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lP\n        Wf9JT1n/SU9Y/0dOV/9OVV7/TFBU/x4iJP84XIL/aaPj/2qh3f9pntn/aZ/a/2ed2f9roNz/bqXh/2ui\n        3/9sotz/bKLd/2qh3v9zq+n/drHv/22m5P9wp+L/fLbw/4O/+f9/uPT/ebDr/3qz7v94sOv/canm/2qh\n        4f9tpN//b6bj/2+n5v9up+f/bqXh/3Or6P9qoNv/a6Hc/3Kt7f9Ic6P/Ehgc/zk8O/9RWWL/SVBZ/0hP\n        WP9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWP9ITlf/SlBa/1FZ\n        Yf81PD3/DhEP/x8jJP8+REr/P0VM/ztBRv85Pkb/O0BP/z1BUf87QVD/OT9P/zs/Tv86P07/O0FQ/ztB\n        UP86QE//OD5N/zc9TP82PEz/NjtM/zU7SP80OkH/Mjc9/zM5QP88REr/JCgq/wkKCf8YHR3/MDc8/zA1\n        QP8vNET/MDVG/y81Rf8uM0T/LTND/y0zQ/8tM0P/LDFC/yovQP8nLT7/Jy0+/yguPv8nLT7/Jis9/ycs\n        Of8mLDH/Jy0z/z5IUv8yOkH/ExcZ/xASE/8iKC7/Lzc+/yIoMP8oMDm6KjI5HSkxOQAAAAAAAAAAAAAA\n        AAAAAAAALTU/ADoqOAAtNj9hKTE57i42Pf8rMTb/ExUY/w8SFP8dISX/SVJd/1hka/9ebGz/KS+z/wEB\n        6/8CA+j/BAXn/wQF5/8EBef/BQXn/wUF5/8FBef/BQXn/wUF5/8FBef/BQXn/wUF6v8CAu//Dg+e/2Vx\n        ef9SXl3/CAoL/wsNDv82PEH/RE9T/0RQQv8vNn7/Bgfp/wAA7/8CAuj/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+n/AAH0/wQEw/8sMFD/Vl9T/1RdYf9IUVb/PkZK/xkdH/8XGBn/RUpQ/05V\n        X/9IT1n/SE9Y/0hPWP9JT1j/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWP9IT1j/SE9Y/0pQ\n        Wv9RV17/LjEv/yE1TP9hltL/cqrq/2ec1/9ontr/cKjk/2yk3v9qoNz/cKjk/3Gn4v9upN7/a6Hc/2yi\n        3f9xqOP/cKfk/2qh3v9yqef/eLHs/4C59P94sOz/eLDr/4XA+v9+tvL/dq3p/3Go5P9wp+P/b6bi/2if\n        2/9lnNj/a6Lg/3Go5f9vpuH/dq3o/3av7P9ln9//KkVl/xsbGf9ITlH/UFdg/0dOWP9IT1j/SU9Y/0lP\n        Wf9JT1n/SU9Z/0lPWf9JT1n/SU9Z/0lPWf9JT1j/SU9Y/0lPWP9HT1j/TVRe/0hPVv8aHh//ExYW/zU7\n        QP9AR0//PkRK/ztAR/87QEv/PEFQ/z1CUf89Q1L/PEJR/zxCUf87QlH/O0FQ/ztBUP87QE//OkBP/zg/\n        Tv83PUz/NzxL/zY8Rf82PEH/Mzk//zlBSP86Q0b/FBYY/woKCv8jKCn/Mjg+/y4zQv8vNUX/MDVF/zA1\n        Rf8wNUX/LjND/y0yQv8tMkP/LDFC/yowQP8oLj7/KC0+/yguPv8oLT7/Jis9/yYrNP8lKi//MDc//0dT\n        Xf8mLDL/DxEU/xITFv8mLDH/MDhA/yMrM/onMDmFJi02CCcvNwAAAAAAAAAAAAAAAAAAAAAAFx8uAC42\n        PwAuNj4vKzI80ioxOf8wNz7/HyMo/xASFf8VGBv/NjxE/1ZgbP9hbm//R1GO/wcI5f8CAuv/BAXm/wQF\n        5/8FBef/BQXn/wUF5/8FBef/BQXn/wUF5/8FBef/BQXn/wUG5/8DBO7/AQLc/zlAcv9te3f/IScp/wMD\n        BP8fJCf/QktP/0NOSf8+SFX/Fhm7/wAA9f8CAun/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPs/wAA8v8LDJf/PUND/1pkX/9SW1//SFFW/zg+Rf8RExT/Gx4f/0ZMU/9MU13/SE9Z/0hP\n        WP9IT1j/SU9Y/0lPWP9JT1j/SU9Y/0lPWP9JT1j/SE9Y/0hPWP9ITlj/SE5Y/1JYYf9AQ0L/FyIr/0h0\n        pv9yru//b6jo/2ie2/9upeH/gLn3/3Sr5/9ondr/baPe/2ui3v9rot3/baTf/26k3/9uo97/baPe/26k\n        3/9wpuD/dKzn/3+49P+Evff/e7Tw/3y49v95su3/c6vm/3St6/9yqOP/c6vo/2yj4P9roNv/a6Hd/2+l\n        4v97s+7/frfz/2yi4f9upub/U4fB/xssPv8nJyP/T1Ra/05VX/9HTlf/SE9Y/0lPWP9JT1j/SU9Y/0lP\n        WP9JT1j/SU9Y/0lPWP9JT1j/SU9Y/0hPWP9KUVv/S1Jb/yYrLv8OERD/MDQ3/0JGTv8/RUv/PEFI/zpA\n        Sv88QlD/PUNS/z5EU/8/RFP/PUNS/z1DUf88QlH/O0JQ/ztAT/85P07/OT9O/zk/Tv85P07/OT9M/zg+\n        RP82O0L/NjxD/z5ITf8qMDH/CwwL/xQWFf8uNDf/MzhC/zA0Rf8wNUX/MDVF/zA1Rf8vNUX/LjVF/y0z\n        Q/8tMkL/LDFC/ysxQf8rMEH/KS4//yguP/8oLT//Jiw7/yYsMv8mLDL/PUVP/0BJU/8aHiH/EBET/xkc\n        If8uNj3/KDA4/ycvOOUpMjtKKjM8ACQsNgAAAAAAAAAAAAAAAAAAAAAAAAAAAC42PwAuNj8KKzU8mScv\n        N/0yOUL/Jiow/xIUF/8RExb/KC0y/1Jcaf9daWz/XGhz/xgaz/8AAO3/AwTm/wQF5v8FBef/BQXn/wUF\n        5/8FBef/BQXn/wUF5/8FBuf/BQbn/wUG5/8FBur/AQHs/xIUn/9odXn/TVdV/wQFBv8MDhH/Nj1B/0NN\n        UP9FUEX/Mjl4/wgJ4f8BAfD/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wIC\n        7/8AAOL/Fxty/0xVSf9cZmX/Ulxf/0lSWP80O0D/DA4P/yIlJ/9KUFj/S1Jc/0hPWP9IT1j/SE9Y/0hP\n        WP9IT1j/SE9Y/0hPWP9IT1j/SE9Y/0hOWP9HTVj/T1Vg/0tNTv8hJSf/MlZ//2eg4P9spOL/aqHe/2qg\n        3P97suv/icL7/3Wt6v9qoN3/bKLe/2uh3v9rodz/baTf/22k3v9totz/bKLc/2yi3v9tot3/cajk/3au\n        6v9/uPP/ebHs/2+m4f9wp+P/b6bi/3Sr5/9yqeT/da/t/22k4f9poNv/bqXf/3at6f+Evfn/ebLw/2ad\n        3f9on93/a6bo/ztlk/8XHyX/MzU0/1BXX/9LUlz/R05X/0hPWP9IT1j/SE9Y/0hPWP9IT1j/SU9Y/0hP\n        WP9IT1j/SE9Y/0pRW/9NVF7/LTI2/w0PEP8qLjD/Q0pP/0JIT/89Qkn/Oj9J/zxBT/89QlH/PUNR/z1D\n        Uf8+RFP/PUNS/zxCUf88QlD/PEJR/ztBUP86Pk3/OT5N/zo/T/85Pk7/OT9I/zg+RP82O0L/OUFI/ztD\n        R/8XGRn/CQoJ/yAmKP81PEL/MDVD/zA1Rv8wNkb/MDZG/zA1Rv8vNUX/LzVF/y40RP8sM0L/LDJC/ywx\n        Qv8sMUL/Ki9A/ykuP/8oLT//KC04/yctMv8rMzn/RE5Y/zA3P/8QEhT/ERMW/x8kKf8yOkP/JCs0/ycv\n        ObsoMToeJzE6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMbJAAsNkEALDU9WSkyO/MsMzv/LDM4/xkc\n        H/8QEhX/HSIl/0RMVv9YY2z/YW5u/zY8of8DA+r/AwPp/wQF5v8FBef/BQXn/wUF5/8FBef/BQXn/wUG\n        5/8FBuf/BQbn/wUG5/8FBub/BAXv/wEB0P8/RnX/cX97/xwgIv8DBAX/HiMl/0NMUP9DTUz/RlBL/xsf\n        sf8AAfL/AQLq/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8BAfP/AgLK/yUp\n        W/9WYFT/XGZn/09ZXf9HUFX/KzA1/wgKCv8nKy7/TVJb/0tRXP9IT1j/SE9Y/0hPWP9IT1j/SE9Y/0hP\n        WP9IT1j/SE5Y/0hNWP9OVV//TVFW/yIjJP8mQF//X5jW/3Gq5/9sot3/aqDa/3Gn4f+DvPb/jMj+/322\n        9f9rod//aqHc/22j3v9vpd//b6Xf/22j3v9vpd//baTe/22j3v9wpuH/cKbk/3Sr6P+BuvX/f7fy/3Kp\n        5f9tpOH/bKPd/2+m4P90q+f/canl/3Cm4/9zqub/fLbx/3228v99tfL/cKfm/2if2/9nndr/baXk/2Oe\n        4P8vUnf/FRgX/zg6Ov9TW2T/SlFb/0dNV/9ITlj/SE9Y/0hPWP9IT1j/SE9Y/0hPWP9IT1j/SlBb/1BW\n        X/82PEH/DhES/ycrLv9HTVT/R01V/0NJT/8+Q0r/PUNQ/z5DUv8/RFL/P0VT/z5EUv89Q1H/PEFQ/ztB\n        T/87QE//O0FQ/zo/Tv87QU//O0FQ/ztAUP85Pkv/OD5E/zc9Q/84PkX/PkdL/ygtLv8LDAz/ERQU/y83\n        Ov81OkX/MTZF/zE2Rv8xNkb/MDZG/zA2Rf8vNUX/LzRE/y40RP8tMkP/LDFB/ysxQf8rMEH/KjBA/yow\n        QP8pLj7/KS42/ykvM/82Pkf/RlBa/yMpLv8OERP/FBca/ykuNf8qMTn/JS02+ScwOXwmLTYEJS02AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArMz4ALzY/ICw0PcsoLzX/Nj5F/x8kJ/8RFBb/ERQW/zI4\n        P/9WYG3/YW1s/1BahP8MDeH/AgLs/wQF5v8FBeb/BQXn/wUF5/8FBef/BQbn/wUG5/8FBuf/BQbn/wUG\n        5/8FBuf/BQbq/wIC6f8YG5r/cHx8/0hRU/8DBAX/DQ8R/zc+Qf9ETlH/R1JH/zlBa/8LDNz/AAHx/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AAH0/wUGtP8uNEv/XWVa/19n\n        av9QWF3/Rk1T/ykuMf8JCwz/LTE0/1BWX/9KUVv/SE5Y/0hOWP9ITlj/SE5Y/0hOWP9ITlj/R01Y/05V\n        X/9NUlb/JiYj/x0zSv9Wi8f/carn/26k3/9vpeD/bqTh/3Or6f+Auff/gLn0/3av7P9vpeL/bqTg/2+k\n        3/9wpuH/cabh/3Cm4P9wpuD/cKbg/3Gn4v93rur/d6/s/3at6v9/uPT/f7fy/3Kq5/9so97/a6Hd/2uh\n        2/9xqOT/cqro/3ar5/99tPD/hsH7/4C69f98tO7/dKzo/2mg3P9ondn/bKPh/4C7+/9ln9v/Ij1c/xUW\n        E/89QED/U1pi/0tRXP9HTVf/SE5Y/0hOWP9IT1j/SE9Y/0hOWP9JUFr/TlVf/zk+Q/8QExP/HyMl/0VM\n        Uf9LUVj/SE5U/0NIUP9ARVL/QUZV/z9FU/8/RlP/QEZV/z9FVP89Q1H/PUFQ/zxBUP87QU//OkBO/zo+\n        Tf87QE//O0FR/zo/Tv85P0f/OT5E/zc9Q/87Q0n/OkJF/xYZGf8ICQn/HyMk/zlBR/80OUf/NDhJ/zI4\n        R/8xNkb/LzVF/y81RP8vNUT/LjRE/y4zQ/8tM0P/LDFB/ysyQP8qL0D/Ki9A/yovQf8pLzv/KC80/ywy\n        N/9FTlj/PERN/xIUF/8RExb/GR0h/zQ7Q/8lLTL/JS424ikxOj0lLTgAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAsNT0ALTY/Biw0PYsqMjn/MTg//ykvM/8VGRv/DxET/yYrMP9LVF//X2pw/19s\n        eP8kKrz/AQHw/wME5/8FBeb/BQXn/wUF5/8FBuf/BQbn/wUG5/8FBuf/BQbn/wUG5/8FBuf/BQbm/wQF\n        8f8CAsX/QUh3/215c/8bHyH/AwQE/yAkJv9ETVL/R1BR/0lSSv8lK5z/AwTv/wEC6/8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+f/AgPr/wAA7/8KC57/PEFK/2JrYf9haWz/VFxf/0VN\n        Uv8mKi3/DA4O/zA0N/9OVF3/SlFb/0hOWP9ITlj/SE5Y/0hOWP9HTlj/T1Vg/01RVv8oKCb/Gis9/1aH\n        vP94sO7/cKXh/3Op5P98tO7/ebDt/3Kr6f94se3/ebHr/3eu6v+BuvT/dq7q/3Cl4v9xp+H/cqnl/3Cn\n        4/9vpN//cKbi/3iw7f+Iwvf/hsD5/3y08v96su3/c6vm/3Cn4v9xqOL/b6bi/3Cn4v93rur/ebHs/3Wr\n        5v98s+3/gbn0/4K79f+HwPj/ebHt/2uh3/9touD/dq7t/3iy8f97tfT/XJLO/x41T/8VFRT/Oz4+/1FY\n        YP9MUlz/R01X/0hOWP9ITlj/SE5Y/0lPWv9NVF//Nz5C/xASE/8dISL/PEFH/0ZNVP9GTVT/RUtS/0NJ\n        VP9ESln/REpY/0FHVv9ARlT/QEVT/z5EUv8+Q1L/PUJR/z1CUf88QlD/PEFP/zpBTv86P07/OT9P/zk/\n        S/85P0X/OD1D/zc9RP8/SE7/KS8w/woMC/8QEhL/MDU5/zc9R/81Okr/MzlJ/zM3R/8xNUX/LzVE/y81\n        RP8vNEP/LjND/y4zQ/8tM0P/LTND/ysxQf8qLz//Ki9A/ykuP/8pLjj/KC4y/zA3P/9GUFv/LTM4/w4Q\n        Ev8SFRj/JCkv/y82Pv8mLjb/Ji43qSgwOhEnLzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAwOD8AKjI9AC41PkArND3kKC82/zc+Rf8bHyH/ERMV/xkdIf9ASFD/XGZx/2h0b/9IUpT/CQvo/wEB\n        6v8FBeb/BQXm/wUF5/8FBuf/BQbn/wUG5/8FBuf/BQbn/wUG5/8FBuf/BQbm/wUG6P8CAu3/EhSc/2t2\n        d/9KU1L/BAUF/w0PEP83PUD/SVJY/0lSSv9CSlr/ExbH/wAA9P8CA+n/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPn/wEC7v8AAOn/DxCM/0ZLS/9nb2f/ZGxv/1VfY/9HT1T/Jywu/wwO\n        Dv8tMTT/TVNb/0tSXf9ITlj/SE5X/0hOWP9QVl//TE9S/yUlIv8YKj7/T4C3/3249v92ren/cabh/3eu\n        6P+BuPP/erHt/3Gp5/93run/da3o/3et5/+Evvf/fLTu/3Kp4/9zqeL/cafi/3Ko4v92rOj/e7Lu/43I\n        +f+V0f7/icP6/4C69/9+t/D/eLDp/3iv6v98tO7/c6rm/3Sq5v9/t/L/fLTv/2+l4/9upeH/cKfl/3qy\n        8P+Bu/b/dazp/3Or6/9xqOb/ebLv/3au6/90q+j/fLf2/1mNx/8dNFD/FBMT/zc5Nv9OVFr/TVNd/0dN\n        WP9ITlj/SlBb/1BWX/84PUL/ERQU/x4gIv8+Q0j/RktT/0JKT/9ARkz/QkdR/0RKV/9ESlj/RUtY/0NJ\n        V/9BR1X/P0RT/z5EUv8+Q1L/PUFQ/zxBUP88Qk//PUJR/zxDUf86QVD/OT9M/zk/Rv84PkP/NTpA/ztC\n        SP85QEP/Fxsa/wcKCf8fJCX/OD5E/zU6SP81Okr/MzlI/zI3R/8wNUb/MDVF/zA1Rf8uM0T/LTJC/ywx\n        Qf8tMkL/LTJC/ywyQv8rMUH/KzBB/ykuPv8qLjX/KS81/z5HUf9GT1r/HiMm/xAUFf8UFxr/MTg//ygu\n        Nv8mLjfyKDE6YTo9SAErMzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALTU+AC00\n        PhYtNT6tKzQ7/zU9RP8iJyv/ExYZ/xEUFv8vNDv/UVpl/2Rvc/9jb3z/JSrC/wIC8f8FBeb/BQXm/wUF\n        5v8FBuf/BQbn/wUG5/8FBuf/BQbn/wUG5/8FBuf/BQbm/wUG5v8EBe7/AgPU/zg+g/9yfnj/ISUm/wEB\n        Af8eISL/Q0xQ/0dQU/9MVUj/OEB8/wkK5f8BAe//AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID5v8BAvD/AADk/xUWgf9KUE//aXJq/2dwcv9YYWb/SVJW/yswM/8KDAv/Jyst/0xS\n        Wv9OVF7/SE9Z/1BWXv9ISkr/JyYk/x0zSv9Rg7v/eLDv/3ev7P90q+b/dq3o/3St6f99tvP/d7Ds/2+l\n        4f9upN//bqXf/3Gn4f99tO3/hL33/3qy7v9zqeP/c6rk/3et5/+Fvvb/kcv//53b//+Oy/v/icb7/4O+\n        +f96suz/eLDr/3+49P+Iwfr/davl/22k3/9/uPH/jsz7/4K78P93ruv/cajl/3mw6v+HwPb/eK/s/26k\n        4/9upN7/dazm/3uz8P94r+//gLr2/3649/9Zj83/IkJl/xQZG/8vLyz/S1BW/05VXv9LUlz/TVNc/zY5\n        Pf8TFRX/JCco/z5DSP9GTVT/RUpS/0BGTP8/RE3/QUZU/0JIVv9DSFb/Q0lX/0NIVv9CSFb/QUZV/0BF\n        VP89RFH/PEFQ/ztAT/87QE7/PEJQ/zxBUP87P07/Oz9I/zo/Rf83PEL/NzxD/z1FSv8lLC3/CgsK/xIV\n        Ff8xOTv/NTpF/zM4SP8zOUj/MzlI/zM5SP8yN0b/MTZF/zA2Rf8uNEP/LTJC/y0yQv8sMUH/LTJC/y0z\n        Q/8tM0P/LDFC/yswPP8qLzX/MDc//0tUXv84QEf/ExUY/xIUF/8dISb/MzpA/ykwOP8nLzjHKDM5JiYx\n        OAAvNz4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALzc/AD08OAAuN0BlLTY+8C41\n        Pf8zOkH/FRgb/xITFv8aHCH/RU1W/1xmcf9reHH/REyg/wgI6P8DA+n/BQXm/wUF5v8FBeb/BQbn/wUG\n        5/8FBuf/BQbn/wUG5/8FBuf/BQbn/wUG5v8FBuf/AgLy/w0Oq/9eaHz/WGJe/wYHCP8ICAn/LzQ3/0dP\n        Vv9IUU//TFZQ/ycsoP8CAu7/AQHr/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID\n        5/8CA+j/AQLz/wAA3f8UFXb/TVNP/211bf9rcnX/WmJn/0hSVv8vNTj/DxER/yIlJf9HS1H/Vl1l/0JF\n        R/8iKzX/L05z/1qOyf95s/H/e7Pr/3iu5/92rej/dazp/3Sr5v96su7/dKvn/3Gn4f9xp+L/dazn/3yy\n        6/96sez/h8D3/4O78/9yqeT/dKnk/3iu6f+Gvvj/jsr+/5HN/f+AuPL/fLTv/3+28v+CuvP/frXy/3y1\n        8v+BuvT/dKvl/2+l3/9yqeT/jMr4/5zd//+Pyvv/fbTw/4O78v+Tzv//hr/5/3Sr5/9vpuD/bqbk/3Cq\n        7P9yrOv/fLXx/3y19P91rez/YJ7i/zljkv8WJjb/Jikq/05TWP9SWF//LTAz/w0PEP8rLzL/REpQ/0VK\n        Uf9FS1L/Q0hP/0NIUv9ESVf/QkhW/0NIVv9ESlj/RUpZ/0VLWf9ESlj/QkhW/0FGVf8/RFP/PUJR/zo/\n        T/85Pk3/OT5N/zk+Tv86P0r/PEBH/zo/Rv83PkT/PUVL/zQ7Pf8QExL/CgsL/ycsLv84PUX/NDlH/zM4\n        SP80Okr/NDpJ/zI4R/8zN0b/MjZF/zA2Rf8vNUT/LjND/y0yQv8sMUH/LDFB/ywxQv8rMUL/LDFA/ywx\n        OP8sMjn/PkZQ/0tTXv8gJCj/ERMW/xQWGf8uNTz/LzY9/ygvOPopMTyEKzY8Byo0PAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC01PgAtNT4mLTU+yy42P/84Pkb/IiYq/xIU\n        F/8SFBf/MDU7/1NcZv9jb3P/YWx6/yAjx/8CAu//BQXm/wUF5v8FBub/BQbm/wUG5/8FBuf/BQbn/wUG\n        5/8FBuf/BQbn/wYG5/8GBub/BQXs/wAA4P8qLoj/doOB/y4zM/8BAQH/FRka/0FJTP9HUFb/TFVK/0dP\n        X/8XGcf/AAD0/wED6f8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+f/AgPo/wEC\n        8/8AANr/ExR6/05TUf9weG//bnZ5/1pjZv9LVFn/OT9C/xMVFv8XGRn/OTw9/ywtLP86XYT/a6nq/3ey\n        8P91q+f/c6nj/3Gn4f9yp+H/caji/3iv6f+At/L/dazn/3Go4v92rej/ebDs/3yz7f98tPD/isT4/5DK\n        +f93run/dKnk/3qw6v+Eu/X/hsD5/4bB+/97s/D/fbTw/43I+f+m5f7/odz+/4rE9v94sOv/davm/3Wq\n        4/9xp+D/erHt/4bE+P+Sz/3/hr/5/4G68/+Cu/P/hL31/4C69f90q+j/canp/3Cp6/9xqeX/e7Ls/3mw\n        7P95r+z/isb8/4PD+P9KdaP/JSsu/zE0M/8jJSf/FBUX/y8yNv9LUVj/SU9X/0VLUv9BRkz/QUZQ/0ZM\n        Wf9HTFv/Rkxa/0ZLWf9GS1n/RUtZ/0ZMWv9FS1n/Q0hX/0FGVP9ARVP/P0ZT/zxBUP86P03/OT5N/zk/\n        TP86QEf/Oj5G/zg9Q/87Q0r/PEZK/x0iI/8HCQn/Fhoa/zQ7Pv83PEn/NjpK/zY7Sv82O0v/NDpK/zI3\n        R/8yN0b/MTdF/zE2Rf8wNET/LjND/y4zQ/8tM0P/LDFB/yswQP8rMEL/LDI9/ywxNv8yOED/SlNf/zlB\n        Sf8UFxr/EBIV/x8iJ/80O0L/LDM7/ykxOtwqMjs8KjI8ACouOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8zPQAvMTwCLjY/eiw0PfkzPEP/NTxC/xUWGf8SFRf/GBoe/0lR\n        Wv9dZ3P/bHlx/0BHoP8HB+X/AwPp/wUF5v8FBub/BQbm/wUG5v8FBub/BQbn/wUG5/8FBuf/Bgbn/wYG\n        5/8GBub/Bgbn/wMD8f8GB8L/SVB2/2Vwav8REhL/AwQE/ycrLf9FTlP/Rk9S/1FbTf8+RHf/DQ/Z/wAA\n        8f8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPn/wID5/8BAvP/AADh/xES\n        hv9IS1H/c3tu/3R7ff9ja2//Ulxg/z9GS/8eISL/CgsM/xoaGv88R1L/XH6i/3Sp4P98tvP/eLHt/3Ko\n        4v9yqOL/c6nj/3iv6f96sez/dKvo/3Sr6P95sOn/erHs/3mv6f96sOr/hb71/4vF+v96sev/dKrj/3mw\n        6f+AuPH/fLPt/4G59P+DvPf/g7v3/4W/+P+Pzvz/k878/4vE+f98s+3/dqzn/3Wq5P91q+X/fbPu/4O8\n        +P+Oyf7/h7/6/4K58/96sev/f7bw/3mw7P9wpuH/dq3o/3iv7P92rOn/gbjz/4G68f9/uvb/g73s/3GZ\n        vv9GVWT/HyEh/w4QDv8YGRr/Njo+/0tQV/9MUln/Sk9W/0VKUf9DSFL/RUpY/0VLWf9GTVz/SE9d/0hO\n        XP9GTFr/RUtZ/0VMWv9GTFr/RUpY/0JIVv9BRlT/QUdV/0BGVP8+RFL/PEBP/ztASf87QUb/OT5E/zo/\n        R/8+Rkz/LDI0/wsNDf8LDw7/KzEy/zk/R/80Okn/NTtL/zU7Sv81Okn/NTpK/zM4R/8xN0b/MTZG/zE2\n        Rv8wNUT/LzRD/y4zQ/8uM0P/LjNC/ywxQf8rMED/LTI5/ywxOP8+Rk//Tlhi/yEkKf8RExX/EhQW/ywy\n        OP8zOkL/Jy43/SoyO5kqMjsJKjI7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAvN0AALjY/LS01PtcvOED/Nz1E/yMnK/8TFRf/FBYY/zI4Pv9cZnL/and6/2Fr\n        f/8cHsz/AADt/wQE5v8FBub/BQbm/wUG5v8FBub/BQbm/wUG5v8GBuf/Bgbn/wYG5/8GBub/Bgbm/wYF\n        6/8CAev/EhSk/2Nsdv9KUU7/BgcH/woLDP8zOTv/Rk9W/0tTU/9TXE//NTuR/wcH5/8AAe3/AgPn/wID\n        5/8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID5/8CA+j/AgLx/wAA5P8NDpT/QEVT/3F3\n        af96gID/bHN2/1hfY/9GTFD/LDAz/xITFP8RDwv/LC0s/0dYZ/9tlb7/c6jh/3ex8f94se3/dqzm/3es\n        5f96ser/eLDu/3iw7/96sez/e7Lt/3qw6/94r+j/g7z1/4e/+f+At/H/d63n/3iv6f99tfD/ea/q/3iv\n        6f9/tfD/h773/4S99/95sO//eK7t/3uz7v98s+3/eK3o/3Sr5f96sez/gbn2/4vE+/+Oyf3/frXx/4G4\n        8v+Evff/gLjz/3at6P9wpuD/c6rn/3Wt7P92r/H/hcL7/4S98P9tm8f/TGN6/zA1Nv8UEg7/Dg4O/yQn\n        KP9BRkr/S1BX/0xRWf9JTVX/RUpR/0RJVP9GS1n/RUtZ/0NJV/9FS1n/R01b/0dOXP9HTVv/RktZ/0VL\n        Wf9FSln/RUpY/0NJV/9CSFf/QkdW/0FHVv9ARlT/P0NN/z1CSf87Qkf/OkFH/0BHTv83PkH/EhUV/wgK\n        Cf8gJSX/OT9G/zg9S/83PEz/NjxK/zU7Sv81Okn/NjtK/zM3R/8wNUX/MDVF/zA1Rf8vNET/LzRE/y4z\n        Q/8tMkL/LDFB/yovQf8rMTz/LDE2/zE4P/9KVF7/PENL/xYYG/8QExX/HSEl/zM6Qf8sNTz/KjE76Ssy\n        PEgrMT0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAxOUEANDtBBjA4QoksND3+NT1E/zE4Pf8WGRv/ExUY/x0fI/9SW2X/ZnF7/255dv9DSqD/CAnn/wEC\n        6v8FBub/BQbm/wUG5v8FBub/BQbm/wUG5v8FBub/BQbn/wYG5/8GBuf/Bgbm/wYG5v8FBe7/AQHf/yww\n        h/90fnb/MDQy/wEBAv8WGRn/P0dK/0dPVv9QWFP/VVxT/ycrpf8DA/D/AQHs/wID5v8CA+f/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+j/AgPo/wID6P8CA+f/AgPn/wID7v8AAez/Bwim/zI1Vv9tc2b/gYeD/3Z9\n        gP9fZWn/TVVZ/zpARP8dHyH/DAwJ/xYWEv81ODn/Vml9/2qQu/9yqOH/e7b0/3au6/97su3/fLTx/3qy\n        7v96sez/dq3r/3iv7P96su3/f7fz/4G58/99tO3/ea/p/3mu6P94r+n/eK/p/3mu6f97se3/jMX6/5fR\n        /v+Iv/X/e7Hr/3et5/92rOb/d63m/3et6P94rej/erHs/3628v9+t/D/ebDq/4K48v+Fvfb/fbPs/3ev\n        6/9zquT/c63r/3i19v9xqOX/apXB/112jP86QUX/HRwZ/wkJBv8WGRn/NTo8/05UWP9IT1T/SU9X/0xR\n        WP9HTFP/Q0hS/0NIV/9DSFb/Q0hW/0VLWP9GTFr/REpY/0VLWf9GTFr/RktZ/0VLWf9DSVf/QkhW/0NJ\n        V/9DSVf/QkdX/z9EVP8+Q0//P0RK/z5ESf88QUj/PkVN/z9IS/8fJCX/BwkJ/xUXF/81Oz//OkBK/zc8\n        S/84Pkz/OD1M/zY7Sv81Okn/NTpJ/zM4SP8yNkb/MTZE/zA1Rf8vNEP/LzRD/y4zQ/8uM0P/LTJD/ywy\n        QP8sMjj/LDI4/z9IUv9RW2b/KC0y/xIUFv8TFhj/Ki82/zc/R/8oLzf/KzM9qC41PQ8rMjsAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0PEQALjdBADI6\n        RDcuN0HVLjY+/zc+Rf8kJyz/ExUY/xUYGv83PEP/YGl2/2x3ev9rdoH/KCvG/wEB7P8EBef/BQbm/wUG\n        5v8FBub/BQbm/wUG5v8FBub/BQbn/wYG5/8GBub/Bgbm/wYG5v8GBuf/AwPw/wUFwv9KUXr/aHJp/xUY\n        F/8FBgb/JSoq/0RNUv9IT1b/VFtU/1BXYP8dIL3/AQH0/wEC6/8CA+f/AgPn/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPo/wID6P8CA+f/AgPn/wID5/8CA+z/AADy/wMEvv8mKGn/XmRa/4KIff+CiIj/b3Z6/1Zg\n        ZP9GTlH/NDk8/xkbHP8ODgz/JyYi/zw+P/9UZ3r/YIOn/2+i2f99t/b/erT0/3639f+BufL/ebDq/3mv\n        6P9+tO7/f7bw/3217v99tOz/fLPt/3qx6/95r+j/eK7p/3uy7v+Iwfj/j8r9/5XQ//+Oxvr/fbXv/3qx\n        6/+Cu/L/fLHr/3it5/92rOf/dazm/3ar5f92rOb/eK7o/3ux6/97s+3/erLu/3my8f93se//bqLb/2CF\n        sP9XbYb/OkBG/yQkIf8QEA3/DQ8O/yYqK/9JUFL/Zm5w/3V7fv9ZYGP/QkhO/0lPVv9LUFf/SE1W/0VK\n        WP9FS1n/R0tZ/0hMW/9HS1r/REpY/0RLWf9FS1n/RktZ/0VKWP9DSFb/QUZT/0JGVf9DSFb/QUdW/z9F\n        UP9ARUz/QERL/z1CSP89RUz/QkpQ/yoxMf8KDQ3/Cw0O/ysxM/86P0n/NztL/zc8S/84Pkz/OD5M/zc8\n        S/81Okn/NDlI/zM4SP8zOEf/MjhH/zE3R/8wNUX/LzRD/y80RP8vNET/LjNE/y80Pf8sMTf/MzpD/09Z\n        ZP8+RU7/Fxod/xIUFv8cICX/NTtC/yw0Ov8qMTrqKjI7U1BhOwAqMzsAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMztEADY+RQsvN0GKLDQ9+jg/\n        SP8wNTv/Fhoc/xMVF/8eISX/S1Nc/2Vwe/9xfXr/VF2S/woL4P8CAun/BQbm/wUG5v8FBub/BQbm/wUG\n        5v8FBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbp/wEB7P8QEqP/ZG15/1BYUP8JCgr/CQoK/y80\n        N/9FT1P/SlFV/1dfVv9KUW3/Gx3D/wEB8v8BAun/AgPn/wID5/8CA+f/AgPo/wID6P8CA+j/AgPo/wID\n        6P8CA+j/AgPn/wID5/8CA+f/AgPq/wEC8/8AAM7/FBWE/0dKVv96gHL/ipCL/36Eh/9ocHP/WGBk/0ZN\n        UP8uMzT/DxER/xESEP8fHRn/Nzo5/1dkc/9Zc47/apbF/3218P+AuvT/e7Tv/3218f9/t/H/f7bv/360\n        7f9/te7/fbTv/32z7f96sOn/ebDq/3618P+FvfX/g7zz/4nD+P+At/D/erHs/4S88v+V0P//grnx/3as\n        5/94rej/d67p/3mw6v97su3/fbby/3218/98tfL/fbPv/22ay/9YdpX/UmJx/z5CRf8lJCH/FhcV/w8R\n        EP8nKy3/PkRG/1xiZv92fX//hIqL/4KIif9xeHv/SlBV/0JHTv9NUVn/TVJZ/0tRXP9MUmD/S1Be/0ZM\n        Wf9FSlj/RktY/0dMWv9GS1n/RUpY/0NIVv9CR1X/QUdU/0FGVP9CR1X/QUdU/0FHTv9DSE7/QEVL/zxE\n        S/9BSk//NDw+/xEUE/8HCgr/ICUm/zpBR/84PUv/ODxM/zc8Sv83PEv/OD5M/zg+TP82O0r/NTpJ/zQ5\n        SP8zOEf/MjhH/zI4R/8yN0b/MDVE/zA1RP8wNUX/MDVD/zA1PP8wNT3/Q0xW/0xWX/8iJir/EBIU/xQX\n        Gf8oLDL/NT1F/ycuNv8qMTqqKjI8FioyOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMztBADE2QQAyOEE2LzZA0zA4QP88REv/JCcr/xUX\n        Gf8UFxn/MDY7/15mc/9teX3/bXl9/y8zuf8BAev/BATo/wUG5v8FBub/BQbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wUF7P8BAeP/ISSU/2t1c/85Pjj/AwME/xEUFP85P0L/Rk5T/01V\n        Vv9cZFf/TlRy/xkbyv8AAPH/AQLp/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID6P8CA+j/AgPn/wID\n        5/8CA+f/AgPn/wID6P8BAvH/AADp/wYGqv8sLV//aW1k/4yShf+PlJL/gIaI/2dvc/9RWV3/QEhL/ykt\n        L/8SFBT/ExQT/xgVEf8uLSv/U1pg/1hpef9ffp7/dKHR/4C27f+Du/T/hsD6/4O++v+Hwfv/grr2/4G4\n        9P9/tvD/fbXu/4G48f+BuPL/fbTu/3+28P98suz/erHr/4S79P+Uzv7/kMv8/3638/98tPH/e7Xz/3y1\n        9P+At/L/gbfx/3el1v9ffqD/U2Jy/05WXP8wMTH/GhcT/xQVE/8OEBD/Jikr/0BGSf9aYWT/dn2B/4eN\n        jf+Ij4f/c3hy/3F2c/+Bh4b/ZGpt/0JITv9GS1P/TVJZ/01TW/9MUl7/SU9c/0ZMWf9FS1j/RUtY/0ZM\n        Wf9FS1n/RElX/0NIVv9CSFX/QkdV/0JHVf9CR1X/Q0hQ/0NIT/9BRUz/PkRM/0FJUP85QUP/Fhka/wYI\n        CP8XGxv/Nz5D/zxCTf84Pkz/NzxK/zY7Sv82O0r/NzxL/zc8S/83PEv/NjtL/zQ5SP8zOEf/MTZG/zE2\n        Rv8xNkX/MDRE/y80RP8wNUT/MTY//y80Ov87Qkv/VF1o/zlAR/8SFBf/EhQW/x0hI/83PUT/LDM6/ykw\n        OecqMjpSKDE1ACoyOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADU8QwA1PUQHLzdAfy02P/g3P0j/OD1E/xocIP8TFxn/GRse/0hP\n        WP9ncn7/cn97/19okf8VGNn/AADs/wUG5v8FBub/BQbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8EBO7/AgLZ/zI2g/9sdW7/KSwp/wICAv8aHR3/QEdJ/0ZOVf9RV1r/YWhZ/0tR\n        eP8WGM7/AQHy/wEC6f8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPt/wAA8f8BAc//EhOF/0NFX/95fXL/k5iP/5OZmv+DiYz/aXJ1/1FaXf9JUFP/MTU4/xsd\n        Hv8WFhb/EBAN/yMiH/9AQ0L/TFBQ/1FcZf9dc4n/dJa7/4ay2/+GuOD/f7Lk/3606/99tO7/fbbz/4C6\n        9/+Cvfr/hMD7/4TA+v+Ev/v/fbj2/4XA+v+NyPr/k8zv/3615v91p9v/eqbW/3acxf9kfJX/UmBs/0pO\n        UP86Ozv/JCMg/xEQDf8REhH/FhkZ/yovMP9FS07/WmBj/3h9gf+LkZP/kZeS/4CFdv9PVGP/Fxlu/zE0\n        dv99g3r/foSD/1ZdYf9BR03/SE1U/0pPVv9ITVb/RkxZ/0hNW/9HTFr/RUpX/0RKV/9FSlj/RElX/0NI\n        Vv9DSFb/QkdV/0FGU/9CSE//Q0lP/0JHTv8/REz/QEdO/zxER/8eIiP/BwgJ/xEUE/8yNzr/QEVQ/z1C\n        Uf85Pk3/NjtK/zY7Sf82O0n/NjtK/zY7Sv83PEr/NjtK/zQ5SP80OUj/NDlH/zE2Rv8wNET/LzRD/zA0\n        Rf8xNkL/MDU6/zI3Pv9JUlz/TVVe/xsfIv8SFBb/FRcZ/zA2O/82PET/LDM7/i00PaMtNj4TLDY+AAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAvN0AALzdAJS42P8gvNz//PkZN/ykuMv8WGRz/ExUY/yovM/9YYWv/bnh//3aA\n        gP9DSa//BQbp/wID6P8FBuX/BQbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBuf/BAPv/wYHyf9ESoD/Z29o/xocG/8DBAT/JCco/0JJTf9GTlb/VFpa/2RqXP9LUIT/FhjS/wAB\n        8f8BAun/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        6f8BAu//AADt/wMDvP8cHXT/UFNh/4CEdP+Znpb/mp6f/4iPkf9yeHz/XmVq/1VbX/8+Q0b/Jyst/x8i\n        I/8WFhb/DAoH/x0bGP8zMzH/Pj8+/0tMSv9RWF7/VmNx/2J1iv9shaH/cZCy/3eYvP97nsP/gabI/4ar\n        yf+Bpsf/dpi8/3mau/94lrL/Z32N/1Znd/9QWmT/RkdI/0FBQP82NjT/IB8b/xAOCv8XFhb/Gx0e/yAk\n        Jf84Pj//Vl1f/2Vsb/9+g4b/kpeY/5ecmv+IjX7/XWFj/ycpaf8HB6L/AADo/wkJwv9RVW//hYt9/3N5\n        e/9NVFn/RUpQ/0pPVv9JTlX/SU1a/0tQX/9KT1z/R0xZ/0VKWP9FS1n/RUpY/0RJVv9DSFb/QUZU/0JH\n        UP9DSE3/QEZM/z5ES/8+RU3/PkVK/yQoKv8JCgv/DhAQ/y8zNf8+RE3/O0BP/zxBUP87QE//Oj9O/zo/\n        Tf84PUv/NjpK/zU6Sf80Okj/NDlI/zQ5SP80OUj/NDlI/zM3R/8xNkX/MDVE/zA0Q/8xNj7/MDY7/z1E\n        Tf9RW2X/MTg8/xIVFv8UFRj/ISMn/zlASP8uNT7/KzM74C02PUEsNTwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAxOEEAMjpDAzA4QWwvN0DyNTxE/z5ETP8cHyP/FBcZ/xcaHP9FTFT/Z3B7/3N+gP9ve4r/JyzH/wEB\n        7P8EBeb/BQbl/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbo/wIC\n        7v8LDLP/VFt3/1piV/8NDg3/BAQE/ygsLP9NVVn/SVBY/1ZdXP9nbl//TlSA/xkbzP8BAfH/AQLq/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgLs/wEC\n        8v8AAOP/Bgaj/yEjc/9RVGD/g4Z3/6Onnv+kqKb/mJ2f/4CHiv9tdHb/YGhs/09XWf82PED/MDU3/ygq\n        K/8eHx//FhcW/w0LCf8aGhj/JSMh/ywpJv8zMC7/NTEt/zYzLv84NS//OTYy/zk2MP83NC//NTEt/zc0\n        L/80MS7/KSck/yMiIP8fHxz/DgwK/w4ODf8cHRz/IiUl/ygtLv85PkH/UFZZ/2hwcv91e37/jJKU/6Ck\n        o/+gpJ7/jZKC/2JmYv8vMnH/CwuW/wAA2P8BAfD/AQLw/wAA7P8dHpb/cHRt/4WLhf9lbHD/RkxT/0hN\n        VP9MUVf/TFFZ/0xSX/9LUF7/SU5c/0hOW/9ITVv/RElX/0NIVv9DSFb/RElS/0VKUf9CR0//PUFI/z1D\n        Sv9ASUz/KS4w/wkLDP8JCwz/Jior/0BFTf8+QlH/Oj9N/zk+Tf85Pk3/Oz9O/ztAT/85Pk7/ODxL/zc7\n        Sf80OUj/NDlI/zU5SP8yN0b/MTZF/zI2Rf8yNkX/MDVF/zE0P/8wNTr/NDlB/05WYf9LU1z/Gx4g/xQW\n        GP8WGRz/Mzk+/zI4QP8pMTn8KzM7jy0yOwosMjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyOEEAMTlCADI6\n        QxsvN0GxMDdA/z1DS/8wNTr/Fxkb/xUXGf8kKCv/Vl5n/2t2gf96hoP/X2ia/xET3v8CAuz/BQbl/wYG\n        5f8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbl/wYG6v8CAuz/EhSo/1tj\n        df9NVEn/CQoI/wcICP8wNDT/SVJW/0hRV/9YX2D/anFg/1ZcfP8eH8n/AQHy/wEC6v8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5/8BA+3/AAHz/wAA\n        4P8DBKv/ICF//09SYP97fnT/n6KX/6uwpv+qrqv/mqCh/4mOkf93foH/bnZ5/1thZP9ETE7/QUhK/zpA\n        Qv81Ojv/KCss/yMlJf8iIyP/Ghsa/xYXFv8MDQz/CQgH/wkJCP8NDQ3/FBQU/xcZGP8eHh//ISMk/yot\n        Lf8xNDb/Nzs//zk/Qv9FS03/XmRo/3R7fv+Bh4r/kJaY/6Onpf+prab/oqaa/4aKf/9WWV3/LC5x/woL\n        of8BAdL/AADy/wEC7v8CA+j/AgPm/wEC7/8BAdv/ODp+/4CFdf9+g4T/WF9k/0VLUf9MUVj/TlNZ/0xR\n        W/9KT13/Sk9e/0pPXf9ITVv/RElX/0NIVv9ESVL/RUpQ/0RJUP9ARU3/PUVK/0BHS/8uMjX/Cw0O/wgK\n        C/8jKCn/PUNK/z9DUf88QE//Oz9N/zk+Tf85PUz/OT1M/zg8TP84PUz/OT5N/zk9TP81Okn/NDlI/zU5\n        SP8zOEf/MTZF/zA2Rf8wNUX/MDVB/zE2O/8xOD7/RU5X/1VfaP8rMDX/FBYZ/xQWGf8nLTH/OUBG/y0z\n        O/8sMzvLLzU8LjA2PQAtMzsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMztEAEhTXQEvNz9SLjU95jU7\n        RP8/Rk3/IyYr/xQXGv8VFxr/Mzg+/2Ruef9zfYf/fYiI/0dNtf8ICOf/AwTo/wYG5f8GBub/Bgbm/wYG\n        5v8GBub/Bgfm/wYH5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5f8FBez/AQLr/xkcpf9gZ3f/Sk9F/wkK\n        CP8HCAn/LTM0/0tUWP9JUVn/W2Fj/250Z/9aX37/ISLH/wEB8v8BAez/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8CA+b/AgPm/wID7P8BAvT/AADe/wME\n        t/8YGY7/NTZo/2Vobf+RlY3/paqa/6+zqP+xtbD/pqur/5yhov+Qlpj/gomL/3h/gv9tdHf/W2Fk/0xS\n        Vf9IT1H/R05Q/0hOUf9FS03/RElK/0NJS/9GS03/R05Q/0dNT/9HTlL/T1ZZ/19lZ/9wdXj/gIaJ/4yT\n        lP+Vm5z/n6Ol/6uwrf+vs6r/p6ud/5GVjP9rbW7/P0Bh/yAhgf8ICav/AADS/wAB8v8BAu//AgPn/wID\n        5v8CA+b/AgPm/wID5/8AAfL/Cwu6/1tfbf+GjID/cnh7/01TWP9HTFP/TVNa/0tPVv9ITVj/SE1b/0hN\n        W/9GS1n/RUpX/0hNVv9JTlT/RUpQ/0BFTP9ARk3/Q0tQ/zA1Nv8PERH/BwkJ/yIlJv8/REr/QUZT/zxB\n        UP88QE7/O0BP/zo/T/86P03/Oj9N/zg9Tf84PUv/OD1L/zg9Tf83PEv/NjtK/zU6Sv80OEf/MTZF/zA1\n        Rf8wNUP/MTY9/zE2PP8+RU7/WmNt/z5ESv8WGBr/ExUX/xoeIf83PUT/NDxF/ysyPPEtNT1wMztBBjA4\n        PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADE2PgAwNj4LLjU+kC82Pvw8Q0z/OkBG/xoc\n        H/8WGBr/Gx4h/0lQWP9td4P/eoWJ/3V/jv8pLMr/AQHt/wUF5v8GBuX/Bgbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBuT/BQbt/wEB5/8bHJz/aXB4/0lQRf8ICQj/CAkK/zA1\n        Nv9KUlf/SVFY/1xiZP9vdmr/Z2x9/y0wvP8DBOv/AADu/wID6P8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8CA+b/AgPs/wEC8v8AAOX/AQHV/wwN\n        sf8cHXv/Nzll/2Fkcv+Mj4z/oqaU/6uvoP+3uq//ur24/7S4t/+wtbX/r7Kz/6itr/+ip6j/m6Gj/5id\n        n/+Vm53/k5eZ/5CWmP+Sl5n/mJ2e/5+jpf+kqar/qa6u/62ysf+xtbT/trq2/7i8sv+vs6X/oaaU/5CT\n        i/9xc3v/RUdl/x4fbf8PD57/AgLO/wAA3/8BAfD/AgPu/wID5/8CA+b/AgPn/wID5/8CA+f/AgPn/wID\n        5v8BAun/AADp/yAhkP9yd23/hIqE/2Fmav9ES1H/S1FY/01SWf9JT1b/RkxZ/0ZLWf9GS1X/SE1U/0lN\n        VP9FSVH/QEVM/z1ETP9ASE3/NDk7/xIUFP8HCQn/Gx0e/z1BR/9BRVP/PkNR/z5DUf87QU7/O0BO/ztA\n        Tv86P07/Oj9N/zk+TP84PUv/NzxL/zc8S/84PEv/NzxL/zY7Sf80OUf/MjZG/y81RP8vND7/MTU6/zY9\n        RP9SWmT/TVVe/x4hJP8TFRf/Fhga/zA1Ov86QUn/LDM9/iw0PqwvNT0bLzU9AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxOEEALzY/MDA3P80xOEH/QEhP/y4yN/8XGRv/FRYZ/yQn\n        LP9ZYWv/c32J/3+Lif9lbp7/FhjZ/wEB6/8FBeX/Bgbl/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG\n        5v8GBub/Bgbm/wYG5v8GB+b/Bgfl/wYF7P8BAeL/IiSZ/251ef9CRz3/BQYF/wcICf8uMzX/SlJW/0lR\n        V/9aYGL/c3ht/3J3c/89P6r/Dg7i/wAB7/8BAun/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5/8CA+r/AQLv/wAB7f8AAOf/AQHh/wUF\n        sf8PD4X/Jyly/0JEc/9iZH3/e32E/5CSgv+bnoz/pqiZ/7K1p/+7v7H/vcG0/7/Dt//AxLj/w8a8/8PG\n        vf+/w7j/vsG2/7u+sv+2uav/qa2e/5ygkP+TlYP/gYOC/2xuhP9OUHb/LS9v/w4Pd/8HB6L/AgLT/wAA\n        6P8AAOv/AQLv/wID6/8CA+f/AgPm/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AQLu/wQF\n        3P88P3n/gYZ2/3uAgP9VXF//RkxT/05UXP9NU1r/SU5Y/0ZLVv9HTFL/SE1U/0VJT/8/REv/PkZL/0BI\n        S/8uNDX/DxER/wcJB/8bHR7/PkJH/0JHVP89QlH/PUFQ/z1CUP88QU//PUJQ/zxBT/87QE7/OT5N/zc9\n        TP83PEr/NzxK/zc8Sv83PEv/NzxK/zU6Sf81Okr/MzhI/zE1Qv8xNTz/Mjg+/0hQWf9WX2n/KzA0/xIT\n        Fv8UFhj/Jikt/z9GTv8vNj7/LDI74y00PUgXHycAOztJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAwN0AALzZCAjE4QGIwNz7rNj5G/0RKUv8lKCv/FRca/xYYGv81OkD/Zm56/3iC\n        iv9/ioj/T1Wp/wsM5v8CAun/Bgbl/wYG5f8GBub/Bgbm/wYG5v8GBub/Bgbm/wYG5v8GBub/Bgbm/wYH\n        5v8GB+b/Bwfm/wcH5v8FBev/AQHe/yEil/9gZ3H/REc//wYHBv8HCAj/LTIy/0lRVP9HT1X/VVth/3J3\n        b/98gHT/Vlqb/xkb1/8AAPD/AQHq/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+b/AgPm/wID6P8CA+r/AQLt/wEC7f8AAe3/AADu/wAA\n        0P8AAK7/AgKS/xUVg/8kJY3/MDGE/0JDev9SVIL/VliI/1pciv9bX4b/X2GD/2Bjhf9cX4X/WVyJ/1RW\n        hf9JS33/Nzl6/ycoiP8aG4b/BgaI/wAApf8AAMD/AADn/wAA7/8BAe3/AQLt/wID6/8CA+j/AgPn/wID\n        5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+b/AgPn/wAA7/8OD7b/WFxp/4WL\n        gv9udHb/SE9U/0dMU/9OUln/S1BW/0lPVf9ITVP/RElQ/0BGTv8+Rkz/QElL/zA0Nf8NEBD/BQgH/xwf\n        Hv8+Qkj/RktW/0BFU/8+Q1D/PEBO/zs/Tf88QU//PkNR/z1CUP88Qk//O0BO/zk9TP83O0r/NztK/zY7\n        Sv82O0r/NTlI/zQ5SP80OUn/NDlF/zI3Pf8yOD3/QUhR/1hgav88QUj/FRcZ/xMVF/8bHiH/O0FH/zg/\n        R/8tMzz0LDI6gCwyOgcsMjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAA/RkcAMThAADI5QRUxOECfLjU+/D9GTv89QUf/Gx4g/xYXGv8aGx//S1FZ/212g/98hor/gIqN/z1C\n        uv8DA+j/AwPo/wYG5f8GBuX/Bgbl/wYG5f8GBub/Bgbm/wYG5v8GB+b/Bgfm/wYH5v8GB+b/Bwfm/wcH\n        5v8HB+b/BQXs/wEA4v8fIaL/aG59/01SR/8JCwj/BQcG/ycrK/9JUFT/SFFX/1FXXf9wdXD/gIV3/2lt\n        jv8xM8T/CAjp/wAA7P8BAuj/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+b/AgPm/wID5/8CA+n/AQLr/wEC7v8BAvD/AAHx/wAA\n        9P8AAPH/AADb/wAAxP8AAL//AAC+/wAAvP8AALb/AACv/wAAsP8AALX/AAC7/wAAv/8AAMH/AADO/wAA\n        6f8AAPT/AAHy/wEC8P8BAu7/AQLr/wID6v8CA+j/AgPn/wID5v8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID6/8AAej/IiSV/3N4av+BhoT/XWVn/0FH\n        TP9HS1P/S1BX/0pQVf9ESVD/P0RM/z9GTP9CSEz/Ki8w/wsODf8GCQn/HiIh/0FFSv9FSlb/QERS/z5D\n        Uf8+Q1H/PUJQ/ztATv88QU//PEFP/zxBT/88QU//O0BO/zo/Tf85Pkz/NzxK/zU6SP80OUf/NDhH/zQ5\n        SP80OEf/NDk//zI4PP87Qkr/Vl9q/0xUXf8cHyL/ExUX/xYYGv8wNDn/PEJL/y41Pf8uNT26LzQ8JCwy\n        PAAyNz0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzpCADM6\n        QgAzOkIzMThByjE5Qf9ESlL/Mzc8/xcZHP8UFhn/IiUo/1RaY/9yfIn/gYyK/3qEkP8wNMj/AgLs/wME\n        5/8GBuX/Bgbl/wYG5f8GBuX/Bgbm/wYH5v8GB+b/Bgfm/wYH5v8HB+b/Bwfm/wcH5v8HB+b/Bwjl/wYG\n        7f8CAuj/HB6s/2lugv9SWEv/DA4L/wQEBP8jJif/RkxO/0tUWf9NVFv/aG5u/4SJef9/g4T/UlWp/xUW\n        3v8BAe7/AAHq/wEC5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8CA+f/AgPo/wID6P8CA+n/AgPs/wID\n        8P8BAvH/AQLx/wED8f8BA/L/AQPz/wED8/8BA/L/AQPx/wED8f8CA/D/AgPu/wID6v8CA+j/AgPo/wID\n        5/8CA+b/AgPm/wID5v8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8BAfH/AgPZ/zk8g/99g3r/eH5+/1JYXP9DSE//SExT/0ZL\n        Uf9BR0//QklP/z9GR/8mKiv/CQoJ/wcJCP8lKCj/QkhM/0ZLV/9ARFP/P0RS/z9EUv8/Q1H/P0RS/0BF\n        U/8/RFL/PkNR/z1BT/87P07/Oz9O/zs/Tv87P07/OD1L/zU7SP80OEf/NDhH/zQ5SP81OUL/Mzg9/zpA\n        SP9VXWj/WGBr/ycrL/8TFhf/ExUX/ycrLv89Q0v/MDY//y00PNwtNT1IKjM7AC42PgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY9RQA4P0YCNj1FWzM5\n        Q+c6QUr/SVFZ/yYqLv8VFxr/FBcZ/ysvNP9iaXT/dH2J/4WQjP9tdpv/HyHT/wEB6/8FBeb/Bgbl/wYG\n        5f8GBuX/Bgbl/wYH5v8GB+b/Bgfm/wcH5v8HB+b/Bwfm/wcH5v8HB+b/Bwjl/wcI5f8GB+z/AgPq/xwd\n        sP9ZXn7/S1BC/xocFv8EBAT/Gx0d/0JISv9MVVn/SlBX/15kaf9+g3v/i5CB/25xmP8uL8j/CAnm/wAA\n        7f8BAuj/AgPm/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+X/AgPl/wID\n        5f8CA+X/AgPl/wID5f8CA+X/AgPl/wID5f8CA+X/AgPl/wID5v8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+b/AgPm/wEB5/8AAO7/AwPw/ysuq/9zd3r/hIiH/2xxdf9HS1P/RElQ/0JJUP9FTFD/QEdJ/yEl\n        Jf8GCQj/CAoK/ygrK/9ER07/RUpW/0BFVP9ARFL/QEVS/0BFU/9ARVL/QEVT/0FGVP9BRlT/QEVS/z1B\n        UP86Pk3/Oj5N/zo+Tf87QE7/OT5M/zg8S/82Okr/NDhH/zQ5Q/80OT//Nz1E/09XYP9fZ3D/NDc9/xQX\n        GP8VFxj/HiEl/z5ETP83PkX/LTI79CwzO3ouMzoJLjM6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1PEcANz5JDzQ7RZAzOkP7P0ZQ/0JI\n        Tv8gISX/Fhka/xgaG/86PkT/Z296/3mCi/+DjYv/YGai/xIT3/8BAez/Bgbl/wYG5f8GBuX/Bgfl/wYH\n        5f8GB+b/Bgfm/wYH5v8HB+b/Bwfm/wcH5v8HCOb/Bwjl/wcI5f8HCOX/Bgfs/wME6/8OD7v/SEyE/2Fn\n        Wv8oKyL/AwMC/xASEv85P0D/TlRZ/0pSWP9VW2P/dXt5/5CUhP+Hioz/Wl2s/yUm1v8DBOr/AADt/wEC\n        6P8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+b/AgPm/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5v8BAuf/AADr/wEB\n        7v8UFd3/RUi2/3h9jv+DiIT/dXh6/1xgZv9GS1T/RUxU/0ZMUP84PD3/GRsb/wQHB/8OEBD/LTIz/0hM\n        VP9ITFr/Q0hW/0JIVf9ARVP/P0RR/z9EUv8+Q1H/PUJQ/z5DUf8+Q1D/PUFP/ztATv88QE//O0BO/zo+\n        Tf85Pkz/OT1M/zo9TP84PEv/NTpF/zM4Pf80OUD/SFBY/15ncf8+Q0n/GBoc/xUXGf8bHSH/PUNK/0BI\n        UP8vNj7+LzQ9rC41PRowND4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1PEUANT9FADY+RiE0O0SyNTtF/URKU/89Q0n/HSAi/xYZ\n        Gv8aHB7/REhP/2tzfv94gYf/hI+M/1BWsP8LDOH/AgLq/wYG5f8GBuX/Bgfl/wYH5f8GB+X/Bgfm/wYH\n        5v8HB+b/Bwfm/wcH5v8HCOb/Bwjm/wcI5f8HCOX/Bwjl/wcI6v8DA+3/BwjQ/zs+kf9pbWz/Oz8x/wYH\n        Bf8KCwv/LTAx/0pSU/9PVlz/T1de/2ducv+FiYT/mp6N/4iMmf9OULn/GRrc/wEB7P8AAOr/AQLo/wIC\n        5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+b/AQLn/wAA6v8CAu3/EhLg/z1Aw/9vc5z/j5SF/4WL\n        g/9qb3H/TVNa/z9GTv9FTFL/RkxO/zA0Nf8OERD/BAUF/xUYF/87PkH/TFBZ/0lOW/9ITVv/R0xZ/0NI\n        Vv9ARFP/P0RR/z5CUf88QE7/PEFP/z9DUv8/Q1D/PEBO/ztATv88QU//O0BO/zo+TP84PUv/OD1L/zk8\n        S/85PUn/Nz1D/zY7Qf9AR0//XGVu/0lPV/8dHyL/FRga/xkbHP80OT7/QkpS/zE4Qf8wN0DLMjlBOD1A\n        UAAwNz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAOD9HAC82QQA1PEU9NDtEzTg+R/9JUFj/NztB/xkbHv8XGBv/HSAj/0xT\n        Wf9ud4L/foeM/4OMjf9JTbP/CQnk/wIC6f8GBuX/Bgbl/wYH5f8GB+X/Bgfl/wcH5f8HB+X/Bwfl/wcH\n        5v8HB+b/Bwjm/wcI5v8HCOX/Bwjl/wcI5f8HCOf/BQXt/wMC2v8mKJ7/YWVw/0dMPv8QEgz/AgQD/xse\n        Hv9AREX/T1Zb/0tUW/9YYGf/dHl8/5KWjv+eopL/gISl/01Rwf8YGdz/AAHq/wAA6v8BAej/AQLm/wID\n        5v8CA+b/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID\n        5v8CA+b/AQLm/wEB5/8AAen/AADs/xIT4/9AQcb/cnSm/5KXjv+RlYj/eH18/1xhZ/9HTlb/QElP/0VM\n        UP8+Q0X/ISMk/wYHB/8GCAf/IyYn/0ZKTv9OU13/R0xZ/0VKWP9GS1j/RktZ/0VKV/9CRlT/QERS/z1B\n        T/87QE3/P0RR/0FGVP9ARFL/PkJQ/z1BT/87QE7/Oj9N/zo+TP85Pkz/OD1M/zg8Sv83PEP/OD1C/0JI\n        Uf9aY2z/Ulli/yAiJv8UFhj/Fxkb/y0yNf9FS1P/Nj5G/zA4QOExOEFZMT1EAzE6QgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAADc7QgA3O0IFNz1FXzM6Q+Y5P0n/SlFa/zE0Of8ZGx7/Fxod/yUoLP9aYmv/d4CL/4OL\n        j/+FjpD/Rky1/wYG5P8CAuf/Bgbl/wYH5f8GB+X/Bwfl/wcH5f8HB+X/Bwfl/wcH5f8HCOX/Bwjl/wcI\n        5v8HCOX/Bwjl/wgI5f8ICOX/Bwjm/wYG7v8CAuH/Fhe1/01Rff9ZXVH/ISQa/wIDAv8MDAz/LzIz/1JZ\n        XP9PWF3/T1hf/2Blbf+AhIX/naOV/6SnnP+HjKf/Vlm5/xcY3P8GBun/AQHq/wAA6f8BAuf/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID5/8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wEC5/8AAOn/AADq/wMD\n        6f8SE+P/Q0XH/3p9qf+Ym5j/m56P/4WIhf9jZ2z/TVNb/0VMVP9ETVL/SlFT/zQ3OP8RExT/AQEC/w4O\n        D/8wMjP/TFFV/1NZYf9LUFr/R0xZ/0ZLWf9FSlf/RUpY/0ZLWf9FSln/QkZU/z5CUP8/Q1H/QEVS/z5D\n        UP89QU//PUFQ/z1CUP88QE7/OT1M/zk9S/86PU3/Oj9M/zo/R/86P0X/REpT/2Bncv9fZ3H/Ki4z/xQW\n        GP8UFxn/IyUp/0VMU/84QEj/MDc/9TI6QnwyN0ALMjdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAA1PEUANz5HCTY9Rn4zOkPzO0JK/0pQV/8oKy7/GBod/xgaHP8pLTD/ZGt0/3yFkv+IkpP/iJOT/0NI\n        uP8ICOT/AgPn/wYH5f8GB+X/Bwfl/wcH5f8HB+X/Bwfl/wcI5f8HCOX/Bwjl/wcI5f8HCOX/Bwjl/wgI\n        5f8ICOX/CAjl/wgI5f8HB+r/AgLr/wgI0P8yNJb/YWVx/0JFOP8REg7/AwQF/x0fIP9ESEn/U1te/09Y\n        Xv9QV2H/Zmxz/4qNjP+jp5j/qq2g/5aZqv9nacH/LjDZ/xUW4f8EBOb/AADq/wAB6P8BAub/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+f/AgPn/wID\n        5/8CA+f/AgPn/wID5/8CA+f/AgPm/wID5v8CA+f/AgPn/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wIC5v8BAej/AADq/wEB6v8NDeX/JSXb/1RWwf+Hiqn/oKSf/6Gk\n        lP+Mj4r/a29z/09TXP9ESlP/RUxT/0xRVf9CRkj/ICMk/wgJCv8JCgj/Nzk3/5OZn/+JkZr/SU5W/0lO\n        Vf9MUVj/R0xW/0ZLWP9GS1n/RUpW/0RJV/9ESVj/Q0hW/0BFU/8/RFH/PUFP/zxATv87P03/Oz9N/zxB\n        T/88QE//Oz9N/zg+Tf84PUv/OT5G/zo/Rv9ES1P/YGhy/2Nrdf8uMjf/Fhgb/xYYGv8fIST/QkdO/zxD\n        S/8vNj75MTc/mzM5QRUyN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANj1FADc+\n        RhM1O0SWMzpC+EFJUf9ES1H/JScq/xgZHP8YGhz/Njk8/2dud/99h5L/jJaX/4uUnf9GS8f/Bwjp/wID\n        5/8GB+X/Bwfl/wcH5f8HB+X/Bwfl/wcI5f8HCOX/Bwjl/wcI5f8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgI\n        5f8ICOX/CAno/wQF7P8EBOP/Gx20/1VXg/9SVUz/Jicd/wcIBv8LDAz/Kiwt/05SVP9TW2D/UVli/1FZ\n        Y/9mbHT/iY2M/6ernf+ztqr/rK+u/4aKtf9TVMn/Li/d/xAR4/8AAOr/AADq/wAB6P8BAeb/AQLm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AQLm/wEC\n        5v8AAef/AAHq/wAA7P8ICeT/Jifc/0JDzf9sb7r/nZ+u/62wpf+jppn/jI+L/21xdv9RVV3/QkpS/0VN\n        VP9NVVj/RUpM/ysuLv8PERH/BAUE/xQVC/8wMjL/kJaj/+Dr8v+7xdP/aG55/0NHTf9LUFb/SU5W/0ZL\n        V/9GSlj/RktX/0VKVv9FSlj/RElW/0JHVP9ARVP/P0JQ/z5CUP8/QlH/P0NR/z5CUP88QE//O0BO/ztB\n        Tf87QEf/O0BH/0NKUv9bY23/YWhx/zE1Ov8VGBr/FRga/x4gI/8+Q0n/Q0lS/zI3Qf0wNz+yMTdAJy83\n        QQAyN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU7RAA1O0QjMzlCrjM6\n        Qv1ES1P/RktS/yQmKv8XGhv/Fxkb/zM3Ov9kbHX/f4mV/5Kdnf+Nl6P/RkzH/wYG5P8DAuf/Bwfk/wcH\n        5f8HB+X/Bwfl/wcH5f8HCOX/Bwjl/wcI5f8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgI5f8ICeX/CAnl/wgJ\n        5f8HCOv/AgPs/wwNzf8zNJv/TVBi/zk8LP8YGhD/BgcF/xESEv8yNTb/S1FS/1hgZP9RWmH/TVVe/2du\n        dP+Fiov/oKOc/7m7rv/Bw7T/qKq6/3t+xv9WV9P/NzjW/w8Q4P8EBer/AQLp/wAA6f8AAOj/AAHn/wEB\n        5/8BAub/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID5v8CA+b/AgPm/wID\n        5v8CA+b/AgPm/wID5v8CA+b/AgPm/wIC5/8BAuf/AAHn/wAA5/8AAOj/AQHq/wMD6v8MDOb/JSbb/0lL\n        0v9rbsL/mJy1/7W4q/+1uKr/o6Wc/4iLiv9rb3X/UVZf/0RKUv9GTlX/U1te/0xSU/83Ozz/GBgZ/wYH\n        Bf8UFg3/Kiwd/zEyR/8gIpX/PD+j/7fAw//P2uT/nqi0/05UWv9ESU//Sk9W/0dLVf9GSlj/RktY/0ZL\n        WP9GS1j/RElX/0NIVf9CR1T/QUVT/z9DUf8/Q1L/QERS/z9EUv89QVD/PUFO/z5DSv8/Q0n/RExU/11l\n        b/9ianP/Njo//xYXGv8WFxr/Gxwg/ztARf9GTVX/NTxF/zI3QcgyOEE5Ewg/ADY+QgAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExSRAAhJz8ANTtDMjI4QL40OkL9SE9Z/0JG\n        TP8eHyL/Fxkc/xcaG/8xNTn/Zm13/4OMmP+SnJv/k52j/0xQv/8JCuP/AgLo/wYG5P8HB+X/Bwfl/wcH\n        5f8HCOX/Bwjl/wcI5f8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgI5f8ICOX/CAnl/wgJ5f8ICeX/CAnn/wUF\n        7v8EBOb/ERK+/zQ1h/9QU1b/RUc4/xITCv8FBQT/FxcY/zQ3N/9MUlP/W2Nm/1FaYP9LVFz/XGNs/3Z7\n        gP+SlZX/sbSs/8fKuP/LzLn/tba9/5CTx/9zddD/S03X/ywt2v8YGOT/Cgrn/wUF5/8BAej/AADn/wAA\n        6P8AAOj/AAHo/wAB5/8AAef/AAHn/wAB5/8BAuf/AQLn/wEC5/8BAuf/AAHn/wAB5/8AAef/AAHo/wAB\n        6P8AAOj/AADn/wAA6P8EBOn/CAjp/w4O5v8hItz/REXX/2dpzP+Hisj/oqS//72/s//BxbD/sras/5ec\n        mP97f4L/YWRs/0xRWv9GTlX/R09V/1FZW/9MUlL/ODo8/x8gIP8ICgf/BgcB/x8hE/8+P0P/LzGC/xIS\n        v/8DA+z/BQXQ/2JmoP/Dzcj/vsjU/3yEkP9CSE7/RkpS/0pPVf9HS1b/RElW/0JHVP9DSFX/QkZU/0JG\n        VP9BRlT/QEVU/z9DT/88Qk7/P0JP/z5CUf89Qk//PUJK/z1DSP9HTVb/YWp0/2lxe/8+QUf/GBoc/xYX\n        Gf8cHSD/OT1D/0VNVf81PEX/MjlB1TM7Q0c2OUEBNTlBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2PUQAO0RIATU8REMzOUHKNjxF/khPVv88QUf/HiAk/xkb\n        Hv8ZGx3/Mzc8/2huef+AipX/lZ6g/5ihpP9UWcP/Cwvj/wEB5/8GBuT/Bwfl/wcH5f8HCOX/Bwjl/wcI\n        5f8HCOX/Bwjl/wcI5f8HCOX/CAjl/wgI5f8ICOX/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8ICen/BQXv/wYG\n        3f8hI7j/Rkl//0VHRP8aHBD/DA0E/wcIBv8WFxf/MzQ2/1dbXP9eZWj/T1hc/09XX/9YX2j/Z251/3uA\n        hf+VmJv/sbSv/8nMvf/O0b7/wsTF/7S2y/+jps//jI3N/2ps1P9ISdj/OTrZ/yor4v8WF+T/Dg/l/wwN\n        5v8LDOb/Cgvm/wcI5v8DBOb/AQHm/wIC5v8CA+b/Bgfn/woK5v8MDeb/DQ7l/xIT5P8gIeT/MDHc/0FC\n        1v9iY9f/f4HP/5WXy/+prMn/u73D/8jJuP/Gybb/t7qx/5uenf+AhIj/aW51/1lgZ/9MU1z/SVFY/0lR\n        Vv9WXV//S09Q/zM2Nv8cHh//CQkI/wgJAf8OEAX/DxEY/xocWf8bHLf/Bwfh/wQE7/8HB+n/AwPs/xka\n        uf+KkKb/xc/R/6qzwP9gZ2//P0RK/0lNVP9JTVX/REhV/0BFU/9ARVL/P0VR/z9DUf8/Q1H/P0NS/z5D\n        UP89QlD/PUJQ/z5CUP8+Qkv/PEJJ/0dPVv9gaXP/aXF8/0FGTf8bHSD/Fhga/xsdH/84PEH/Rk5W/zU7\n        Q/8wNT3eMzlBWjdDRgM0PEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAANz5GADdARwM2PEVNNDpD0zg/R/9OVV3/QkZN/x4gI/8ZGx3/GBod/zM2\n        O/9lbXf/gImV/5agov+gqaz/WF7C/wwN4f8AAOj/BQbl/wcI5P8HCOX/Bwjl/wcI5f8HCOX/Bwjl/wcI\n        5f8ICOX/CAjl/wgI5f8ICOX/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8JCeX/CQnk/wgI6/8DA+r/CQra/xka\n        q/8sLWX/NTc7/ywuHv8bHBH/CgsJ/xYXFv8nKSj/SEtM/2FmaP9WXWH/UVpg/1RbZP9XXmf/XGRt/291\n        ff+Pkpf/q66s/8HDu//Lz7//09XD/9DSyv/LzdH/ycvS/8TG1P+3utP/qazO/56h1P+Xmdz/kJLc/4CC\n        2/9tbtr/YmPX/2Vl2f9qa9r/e33a/4yO2/+WmtT/oqXO/6+xzf+8v9P/w8bR/8fJzv/Nz8r/0NPD/8vO\n        vP/BxLn/rK+r/5GUlv94fYP/Y2hw/1VdZf9NVF3/SlNa/09XXP9RWFz/WF1g/0dKTP8pLCz/FhgW/wsN\n        CP8ICgD/DhAD/xITG/8REk3/DA2h/wYI3P8DBO3/Bwjr/wgI5f8ICOT/Bwfo/wEB4P82OKD/q7Ox/7/J\n        0f+QmKP/SU1U/0BESf9ITFL/RkpR/0FGU/9ARVL/QERR/z5CT/89QU//PkFP/z5CUP8+QlD/PUJO/z9C\n        S/8/REv/SU9Y/2Vtd/9nb3j/Oz9E/xocH/8WGBr/GBod/zU4Pf9HTFT/NTtE/y81PeYxNz9oMzVBCTI2\n        QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAADg/SAA5QEkEOT9HUTU7RNg6QUr/U1pi/0BFS/8eICP/GRse/xkbHf8wNTn/Y2pz/4iQ\n        m/+cpan/pK6s/2hvwv8bHd3/AgLo/wQF5f8HCOT/Bwjk/wcI5f8HCOX/Bwjl/wgI5f8ICOX/CAjl/wgI\n        5f8ICOX/CAjl/wgJ5f8ICeX/CAnl/wgJ5f8JCeX/CQnl/wkJ5f8JCeb/Bwfr/wQE7P8ICeT/ExSv/0NE\n        h/9VWGL/LjAh/w8QBf8LDQj/EBEP/x0eHv8+Pz//V1tc/1lfYv9TWl3/WGBk/1VdZf9QWGH/VFxl/1xj\n        bP9xd37/h4uS/56ho/+vsrD/ury3/8LEvP/JzMH/z9LE/9TWyv/X2M7/2NvQ/9nc0v/a3NP/3N7W/9vd\n        1f/a29T/2dvS/9fazv/T1sr/z9HE/8rMwP/FyL7/vb+5/7Gzsf+go6P/j5SX/3p/hf9ma3P/VFpj/01V\n        Xf9JUVn/TFRb/1NbX/9RWFr/U1lb/1JWV/8/QUL/HR0d/w0ODf8KDAf/Cw0B/xASBv8TFCT/ExRY/w0O\n        pv8ICeX/Bwjw/wgJ7f8ICeb/CAjk/wgI5f8ICOX/CAjk/wQF6/8HCNL/XWGW/7rCv/+zvMf/cniD/zxB\n        R/9CRkz/R0pQ/0JHUf9CRlX/Q0dV/z9EUP89Qk//PEBP/zxATv89QUz/P0NJ/0BES/9JUVn/aHF7/2hv\n        ef83OkD/GRse/xcYG/8bHSD/NDg8/0tSWv83PEX/LzU96DI4QG0wNz4MMDc+AAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAA4PkYAOkBIAzg9RVY3PkbYPENL/1JYYf9DSE3/ICIl/xsdIP8bHCD/MTM4/2tyev+MlKD/nKas/6iz\n        r/99hbv/LTDY/wIC6P8DBOX/Bwjk/wcI5P8HCOX/Bwjl/wcI5f8ICOX/CAjl/wgI5f8ICOX/CAjl/wgI\n        5f8ICOX/CAnl/wgJ5f8JCeX/CQnl/wkJ5f8JCeX/CQnl/wkJ5/8HCOr/BQbv/wUH5f8XGLb/KiuG/xob\n        RP8ZGhX/Kisd/x4fF/8XGBX/Gxsa/zEyMf9NTk7/V1hZ/1hcXf9cYmT/XGRn/1tkaf9NWF3/SVJa/0xU\n        Xf9OVl7/Vl1m/2VrdP9zeID/fIGI/4WJjv+KjpL/j5KX/5SYm/+YnJ3/naCh/5qdnv+ZnZ7/l5qd/5CU\n        mP+JjZL/gIWM/3h9hf9xdoD/Y2lz/1RbZf9PVmD/TVRd/0hRWP9KU1r/V19k/19mav9ZYGP/UFZW/0xP\n        UP9HSEj/MTEx/xETEf8ODwz/DhAI/xAQBP8SFA3/ExQ6/xESc/8NDbD/CQnl/wcI8v8ICez/CAnm/wgJ\n        5P8ICeT/CAjl/wgI5f8ICOX/CAjk/wcI5v8CAuj/FRa2/4mQn/+7xMf/oam1/1ZdZP88QEX/RUpP/0VK\n        Uf9CR1T/Q0dV/0FGU/8/RFL/P0NR/z9DTf8+Qkr/P0VL/0pRWf9kbHX/aXB6/zc6Pv8aGx7/GBoc/x0f\n        Iv85PkP/TFNc/zpASP8xNj7nMjhAcjI7QA0yOkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD1FADg8\n        RAU4P0dXNTtD2DpBSf9SWWP/RkxS/yQmKf8bHSD/Gx0f/y8yNv9nb3j/h5Cc/5mhqP+ps7H/kZu5/0BE\n        z/8FBeP/AgPn/wYH5P8HCOT/Bwjk/wgI5P8ICOX/CAjl/wgI5f8ICOX/CAnl/wgJ5f8ICeX/CAnl/wgJ\n        5f8JCeX/CQnl/wkJ5f8JCeX/CQnl/wkJ5f8JCuT/CQrm/wYH6f8FBu//Bgfp/wkKyP8TFKD/KCpz/yMj\n        Mf8dHxP/Hh8U/yMkGf8nJyL/KSkm/z07PP9WVlb/VVZX/1hbXf9fZGX/YGVl/15jZf9haWz/Vl5i/0hQ\n        Vv9CS1H/QkxS/0NLU/9DTFP/RE5V/0ZPWP9HUFj/R09Y/0dOWP9HT1j/R09X/0ZPV/9GUFj/R1BX/0VN\n        Vf9ETFP/SFFW/1NbYP9gaGv/Y2hs/11iZP9XXF3/UVVW/01PUP9KS03/NDQ0/xobGP8VFhH/FBUM/xMU\n        Cf8VFwv/Fhcn/xITWv8QEJT/DAzK/wgI7f8ICPP/CAnr/wgJ5v8ICeT/CAnk/wgJ5f8ICeX/CAjl/wgI\n        5f8ICOX/CAjk/wgI5P8GBun/AQLg/zk9oP+kraf/tLzD/4KJlP9CRk3/PUFH/0NITv9BRk7/QEVS/0FG\n        Vf9CR1T/QkZP/0FGTP9DSVD/Ulli/2hveP9ka3T/MjY6/xgaHP8aGx7/HiAj/z5DSP9MUlr/OD5G/zA2\n        PugyOUBxNDpDDTQ6QgAyOEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg9RQA4PUUENjxEUTU7\n        Q9M9Q0z+U1pj/05UWf8oKy7/HB4h/xweIf8nKi3/WF9m/4WNmf+Zo63/qrSx/5+os/9VWsv/EhPi/wIC\n        5/8GB+X/Bwjk/wgI5P8ICOT/CAjk/wgI5f8ICeX/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8ICeX/CAnl/wgJ\n        5f8JCeX/CQnl/wkJ5f8JCuX/CQrl/wkK5P8JCuX/CAno/wgJ8f8GB/X/Bgfc/wsMu/8SE4//GBhd/x8g\n        Mf8nJyX/MDAn/zc2KP87PDH/QEA5/0pJRv9eXl3/aGdn/2VmZv9lZmj/a2xt/25wcf9vdHT/am9w/2Zr\n        bf9ma23/Z25w/2Zucf9pcHP/bHN2/2txdf9ob3L/aG9x/2ducf9obXD/aGxu/2drbP9maWr/Zmlr/2Bj\n        Y/9XWVn/VVVW/1NUVP9JSUn/NzYy/ygnIP8lJRn/IiMT/x8fFv8cHhv/GRoo/xQVV/8QEY7/DQ3C/woK\n        3f8ICPP/CAjx/wkJ6f8JCeX/CAnk/wgJ5f8ICeX/CAnl/wgJ5f8ICOX/CAjl/wgI5f8ICOX/CAjl/wgI\n        5P8ICOX/AwPs/wgIy/9hZZn/sLi1/6Ortv9la3P/ODxC/0NHTf9ESU//P0NO/0BFUf9CRk//Q0hN/0ZM\n        Vf9aYWv/bnV//1pgaP8pLTD/GBoc/xcZHP8eISP/P0NJ/01VXv85P0j/Mjc/5DQ6Qms0OUINMzlCAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5P0cANjxGAjtBSE05P0fJPUNN/VNa\n        Yv9QVlz/Ky8y/xsdH/8aGx//ISQn/09TWv+AiJP/lJ6p/6avr/+psbb/c3nC/yIk3f8CAub/AwTl/wcI\n        5P8ICOT/CAjk/wgI5P8ICeT/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8ICeX/CAnl/wkJ5f8JCeX/CQnl/wkJ\n        5f8JCeX/CQrl/wkK5f8JCuX/CQrk/wkJ4/8JCeX/CQjs/wgJ8/8HCOz/Cgre/wwMyP8QEJ//GBly/yQl\n        SP8wMUD/Pj5C/0pJQf9SUj//W1tM/2ZlWf9tbWT/eHlz/4ODgf+Kion/i4qK/4mJif+JiYn/iImJ/4OF\n        hf+Dg4P/fn5//3t7fP98fX7/fX5//31+f/98e3z/eXl5/3d2dv9ycXH/bGtp/2BfWv9SUkn/SUg9/0FB\n        Mv85Oif/NDMp/ywtL/8mJjP/Hh9D/xYWa/8QEJz/CwzF/woL3f8ICez/CAjz/wkI7P8JCeX/CQnj/wkJ\n        4/8JCeT/CAnl/wgJ5f8ICeX/CAnl/wgJ5f8ICOX/CAjl/wgI5f8ICOX/CAjl/wgI5P8ICOT/Bwjn/wEA\n        6f8bHLL/g4qW/7O8vP+Wnqr/U1hg/z1CR/9FSVD/QERK/z9DSv9BRkz/S1FZ/2Nrdf9udX//Ulde/yMl\n        KP8WGBr/GBoc/yEiJv9AQ0r/S1FZ/zk/R/8zOUHcNTtDZDU8RAo1PEQAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPkRMAD5FTAQ9QkxDOkBJvz1ETfxQV2H/U1lg/zAz\n        N/8dHyL/Gx0g/x4gIv9CRkr/eYKL/5Kbp/+krbL/s7y7/5OaxP9BRdL/Cwzi/wEB5/8GBuX/CAjk/wgI\n        5P8ICeT/CAnk/wgJ5P8ICeX/CAnl/wgJ5f8ICeX/CAnl/wkJ5f8JCeX/CQnl/wkJ5f8JCeX/CQrl/wkK\n        5f8JCuX/CQnl/wkJ5f8JCeT/CQnk/wkK5P8JCuf/CQns/wkJ7/8ICOz/CAjn/wkK2v8MDbr/EhOd/xoa\n        ef8oKWP/Nzhc/0tMXf9aWmf/ZGVg/3BwXf96emX/hYRy/42NfP+SkoP/lpWH/5iYif+bmoz/mpmK/5eX\n        iP+UlIb/kJCC/4qKe/+CgnP/enpp/3BwXP9lZFD/WltG/09PRv9HR1H/PDxO/y0tUf8jI1v/GRly/xIS\n        mf8NDrr/Cgvb/wkK5v8JCO3/CAnv/wgJ7P8JCuf/CQnj/wkJ4/8JCeT/CQnk/wgJ5f8JCeX/CAnl/wgJ\n        5f8ICeX/CAnl/wgJ5f8ICOX/CAjl/wgI5f8ICOX/CAjl/wgI5P8ICOT/Bwjk/wUG6P8BAdz/Oj6V/6Os\n        pv+3wcn/hI2Y/0JGTP89P0T/P0NJ/0FHTf9QV1//bXR+/3R8hv9HTFL/HyIk/xgZG/8YGhz/Jiot/0hN\n        U/9JUFn/OD5G/zQ5QdM2PERXNT1EBzU9RQA1FR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEFDTwBCQ1ACPURMMjxETK0/RU73TFRd/1pgaf8+QUb/HyEk/xwe\n        IP8cHSH/MjU6/2hvd/+NlaL/n6my/7O8u/+yvMP/dHrR/x8h3/8CAub/BATm/wcH5P8ICOT/CAnk/wgJ\n        5P8ICeT/CAnk/wgJ5P8ICeT/CAnl/wgJ5f8JCeX/CQnl/wkJ5f8JCeX/CQnl/wkJ5f8JCeX/CQnl/wkJ\n        5f8JCeX/CQnk/wkK5P8JCuT/CQrj/woK5P8KCuX/Cgro/wkJ6/8ICez/CAnt/wcI7f8HB+z/BwfO/woL\n        s/8NDaz/FhWS/yQkhf8vMIr/PDyE/0dHev9NTXj/UlN6/1hYff9eXoP/YWGF/2Bghf9cXYH/WFl+/1BR\n        d/9HSXD/P0Bz/zY2ff8rLIX/IiKA/xUVif8OD6f/Cwy1/wgIzv8ICez/CAnu/wgK7v8JCu3/CQrr/woK\n        6P8KCub/CQrk/wkK4/8JCuT/CQnk/wkJ5f8JCeX/CQnl/wgJ5f8ICeX/CAnl/wgJ5f8ICeX/CAnl/wgJ\n        5f8ICeX/CAjl/wgI5f8ICOT/CAjk/wgI5P8HCOT/Bwjk/wcI5P8DA+r/BwjJ/2Bll/+ttrX/pa+6/2dt\n        dv86PkX/SU9X/19mcf9yeoT/am94/zk9Qv8cHSD/Gx0g/xweIv8xNTn/UFZe/0lPWP83Pkb8NTtCxTY8\n        REU7P0cDOj5GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAA+RUsAGSoUAEFHTyRAR0+WPURN9EhPWP9cYmz/SU1T/yUnKv8dHyP/Gx0f/ycp\n        LP9YXWP/iJCb/5ujr/+wusD/wcvI/5efyP9FSdP/CQrk/wAA5/8FBOX/Bwfk/wgJ5P8ICeT/CAnk/wgJ\n        5P8ICeT/CAnk/wgJ5P8ICeX/CAnl/wgJ5P8ICeX/CAnl/wkJ5f8JCeX/CAnl/wgJ5f8ICeX/CQnl/wkK\n        5f8JCuX/Cgrl/woK5P8KCuT/Cgrk/woK5P8KC+T/Cgvl/woL5v8JCuf/CQrq/wgJ7f8ICO7/Bgfv/wUF\n        8v8EBPL/AwPf/wMDy/8DBMP/AwTB/wUFv/8GB8D/BwjB/wcIwv8HCMH/BgfC/wUFwf8EBcP/AwTM/wQE\n        4P8GBvL/Bwb0/wcH8P8ICe//CArt/wkK6v8JCuj/Cgvm/woL5v8KC+X/Cgvk/woK5P8KCuT/Cgrk/wkK\n        5f8JCuX/CQrl/wkJ5f8JCeX/CQnl/wkJ5f8ICeX/CAnl/wgJ5f8ICOX/CAjl/wgJ5f8ICOX/CAjk/wgI\n        5P8ICOT/Bwjk/wcI5P8HCOT/Bwjk/wcH4/8DA+b/AADr/x4gr/+MlKT/qbG2/4yUnv9dY23/aHB7/3+I\n        kv9dZGv/Kyww/xgaHf8bHSD/HyEk/zs/Rf9WXGX/SE9Z/zg/SPk3PkawNz1FNy81PQE1O0MAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAEBGTwBARk8UP0VOfjxCSudFTFT/XGNs/1VZYf8qLDD/HB4g/xsdIP8iJCb/QkVL/3h+\n        iP+Vnar/p7C6/7zFwP+stb//cnfK/ygp3f8EBOX/AQDl/wYH5P8ICeT/CAnk/wgJ5P8ICeT/CAnk/wgJ\n        5P8ICeT/CAnk/wgJ5P8ICeT/CAnk/wgJ5P8ICeX/CAnl/wgJ5f8ICeX/CQnl/wkJ5f8JCuX/CQrl/wkK\n        5f8KCuX/Cgrl/woL5f8KC+X/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+X/Cgvl/woL5f8KCub/Cgro/woK\n        6/8KCuz/CQnt/wkJ7f8ICe3/CAnt/wgJ7f8ICe3/CQjt/wkJ7f8KCu3/Cgrs/woK6P8KCub/Cgvl/woL\n        5f8KC+X/Cgvl/woL5P8KCuT/Cgrk/woK5P8KCuT/Cgrl/woK5f8KCuX/Cgrl/wkK5f8JCuX/CQrl/wkJ\n        5f8JCeX/CQnl/wkJ5f8JCeX/CAnl/wgJ5P8ICOT/CAjk/wgI5P8ICOT/CAjk/wgI5P8ICOT/CAjk/wgI\n        5P8HCOT/BQbl/wAB5f8EBOX/Jynb/2txu/+dpa//oKiw/4+Xo/96gIv/cXeA/0pPVP8kJin/GBoc/xob\n        Hv8lJyr/SExS/1RaYv9CSFH/OD5G8zxDS5Y8REwlR0RLAD5ETAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAA9REwAPkRNCj5FTV8+RU3NQ0pR/FVbZf9ZXmb/Njk+/yAiJf8cHSD/Gxwe/y0vM/9eY2r/iZGc/52l\n        sP+ttbf/usK+/6Ssxv9fY9L/ISLi/wMD5f8DA+X/Bwjk/wgJ5P8ICeT/CAnk/wgJ5P8JCeT/CQnk/wkJ\n        5P8ICeT/CAnk/wgJ5P8ICeT/CQnk/wkJ5P8JCeT/CQnl/wkJ5f8JCuX/CQrl/woK5f8KCuX/Cgrl/woL\n        5f8KC+X/Cgvl/woL5f8KC+X/Cgvl/woL5P8KC+T/Cgvk/woL5P8LC+T/Cwvj/wsL5P8LC+T/Cwvk/woL\n        5P8LC+T/Cwvk/wsL5P8LC+T/Cwvk/wsL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woK\n        5P8KCuX/Cgrk/woK5f8KCuX/Cgrl/woK5f8KCuX/Cgrl/wkK5f8JCuX/CQrl/wkK5f8JCuX/CQnk/wkJ\n        5P8JCeT/CAnk/wgJ5P8ICeT/CAnk/wgI5P8ICOT/CAjk/wgI5P8ICOT/CAnk/wcH5P8DA+X/AwPm/x4g\n        3/9XWsv/mJ66/6+4tP+fp67/iI+b/3uCjP9gZWz/MTQ4/xocHv8ZGx3/HB4g/yktL/9PVFz/UVdg/z5E\n        Tf44PkbbO0FKc0BGTxI8QUoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQklRAENK\n        UgVBSFA9PkRMsj1DTPlNVFz/X2Vu/0hNU/8pKy//HR4g/xsdH/8hIyb/RUhO/3l/if+Vnan/p7C5/7nC\n        wf/AyMn/nqXR/1BT2f8UFN//AQHl/wQE5P8HB+T/CAnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ\n        5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQrl/woK5f8KCuX/Cgrl/woK5f8KC+X/Cgvl/woL\n        5f8KC+X/Cgvl/woL5f8KC+X/Cgvl/woL5f8KC+X/Cgvk/woL5f8KC+X/Cgvl/woL5P8KC+X/Cgvl/woL\n        5f8KC+X/Cgvl/woL5P8KC+X/Cgvl/woL5f8KC+X/Cgvl/woL5f8KC+X/Cgvk/woL5f8KC+X/Cgvl/woK\n        5f8KCuX/Cgrl/woK5f8KCuX/CQrk/wkK5P8JCuT/CQrk/wkK5P8JCuT/CQnk/wkJ5P8JCeT/CAnk/wgJ\n        5P8ICeT/CAnk/wgI5P8ICOT/CAjk/wgI5P8HCOT/BAXl/wIC5/8VFuL/TFDZ/5ieyf+1vb7/rLSz/5ae\n        pf+Hj5v/cnmD/0hNU/8iJSj/GRsd/xkbHf8hIyb/PkJG/1VaYv9LUVr/PEJK/jpAScU+Q01QPkZNCD5F\n        TQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Q00AQUlQIT5E\n        TY88QkrmRkxW/11lbP9bYGb/Oj1C/x4fIv8bHR7/Ghsd/zM1Of9fZGz/g4qW/6Cptf+xub//xM3K/8DI\n        yP+Fis//REfa/w8Q4f8CAuT/AwTk/wkI4/8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ\n        5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkK5P8KCuT/Cgrk/woK5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5f8KC+T/Cgvl/woL5P8KC+T/Cgvk/woL5f8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5f8KC+T/Cgvl/woL5f8KC+X/Cgvk/woL5f8KC+X/Cgvk/woL5P8KC+T/Cgvk/woL5P8KCuT/Cgrk/woK\n        5P8KCuT/Cgrk/wkK5P8JCuT/CQrk/wkK5P8JCuT/CQnk/wkJ5P8JCeT/CAnk/wgJ5P8ICeT/CAnk/wgI\n        5P8ICOT/Bwfk/wMD5f8CA+X/EBDg/0RH2f+GjNP/usPG/7rDwP+mr7X/kpum/3uCi/9dYmr/Njk+/xoc\n        H/8YGRv/Ghod/y4wNP9OUlj/WmBp/0RJU/83PUXwOD9HpD5DSzE6P0kCOj9JAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDSE8APURNAEJITw89Q0tbO0FLyj5E\n        TP1TWmL/Ymhw/09SWP8qLC//HB4h/xodIP8dHyL/PUBF/2xxev+Wnqv/qLK9/7e/xP/L1M7/xc3T/4+V\n        2/9LT9r/EhPg/wIC5P8DA+T/Bwfk/wkJ5P8JCuT/CQnk/wkJ5P8JCeT/CQnk/wkJ5P8JCeT/CQnk/wkJ\n        5P8JCeT/CQnk/wkK5P8JCuT/Cgrk/woK5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5f8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5f8KC+T/Cgvk/woL\n        5f8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woK5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/wkK\n        5P8JCuT/CQrk/wkK5P8JCeT/CQnk/wkJ5P8ICeT/CAnk/wgJ5P8JCuT/CAnk/wYG5P8CAuT/AwPl/xMT\n        4/9GSNj/h4zO/7vDyP/Fzsj/qrO3/5KapP+CiJL/ZGlx/0JGS/8gIiT/GBod/xocHv8fISP/Q0ZL/1th\n        aP9SWGH/PkRN/jk+R9g5PkVyOD9HFjg/PgA4PkoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1DSgA9Q0oDPkRMMzxBSZ84PUXrREpS/2Bl\n        b/9kaXH/Oz9E/yEkJ/8dHyL/Gx4g/ycqLf9KTlP/d32G/5igrP+stMD/xs/X/97o4//Q2eL/m6He/1lc\n        4f8bG+T/AwPj/wMD4v8EBeP/CAfk/wkJ5P8KC+T/CQrk/wkK5P8JCuT/CQnk/wkJ5P8JCeT/CQnk/wkJ\n        5P8JCeT/CQrk/woK5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgrk/woK5P8KCuT/Cgrk/woK5P8JCuT/Cgrk/woK5P8JCuT/CQrk/wkK\n        5P8JCuT/CQnk/wkJ5P8JCuT/CAnk/wcI5P8EBeT/AgPk/wQE4/8eH+H/UVXZ/4+U0v+5wM3/x9DK/7O7\n        wf+ao63/ipGc/3F3gP9FSU7/JSgr/xodH/8cHR//HR8h/zAzN/9UWWD/XmRs/0dNVf82PETyOT9IsjxD\n        S0Q6QEcIOkBHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5P0cAMThAADtASBU7QEhjOT9Hzj9FTvtTWmL/aW95/1hd\n        Y/8xNDf/IiUn/xweIf8dHyL/Kiww/1NYXf+OlaD/p6+9/7rC0f/T3OP/4erk/9nh6P+0u+n/ZWrl/yYn\n        5P8LC+H/AQHh/wAA4v8EBeT/CQrk/wkK5P8JCuT/CQrk/wkK5P8JCuT/CQrk/wkK5P8JCuT/CQrk/wkK\n        5P8KCuT/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KCuT/Cgrk/woK\n        5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/woK5P8JCuT/CQrk/wkK5P8JCuT/CQrk/wkK5P8JCuT/CQrk/wgJ\n        5P8FBeP/AQDj/wEB4/8ICOL/ICHf/2Zp2/+rstn/x8/W/8nQyv+4wMP/pK24/42VoP98gov/U1dd/ysu\n        Mf8dHyH/Gxwf/x0fIv8rLTH/R0tR/19lbf9TWmL/P0VN/Tc9Rdw4PkV3OkBIHz9FUQE7QUoAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADxBSQA7QEgDP0RMLz5FTZA+RU3lRk1V/V1ja/9rcXj/UVVb/zAy\n        Nv8dHyL/HiEk/yMkJ/8vMTX/XGBn/4WMlf+iqrf/wsvY/9Pb4f/f5+b/5O3x/9ri9P+boer/TlHm/yQl\n        5f8JCeH/AADh/wIC4/8GB+T/CAnk/wkK5P8JCuT/CQrk/woK5P8JCuT/CQrk/wkK5P8KCuT/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KCuT/Cgvk/woK5P8KCuT/Cgrk/woK\n        5P8KCuT/Cgrk/woK5P8KCuT/CQrk/wkK5P8JCuT/CQrk/wgJ4/8GB+P/AgLj/wAA4v8GB9//ICLi/0lM\n        5v+NkuL/wcjb/9Tc3//O19b/u8PI/6Sstv+PlqL/goqS/1tfZf8rLTH/HyAj/xsdH/8bHiH/Kisv/0FE\n        Sf9kaXH/WmBo/0JIUP86QEjtOT5GoTpASD45P0cFOT9HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAABVXGQARE1VAEZPVwtCSlJSP0ZOsEBGTvFKUFn/aW95/2htdf9LTlP/Kiww/x8g\n        I/8iIyf/IiQn/yotMf9UWF7/hoyW/6qxvv/Bydb/zNTc/97n6f/v9/j/7/T9/8LI9/9/g+r/S07l/yEj\n        4v8CA9//AQLh/wME4v8FBuP/CAnk/wkK4/8KCuT/Cgrk/woK5P8KCuT/Cgrk/woK5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/woK5P8KCuT/Cgrk/woK\n        5P8JCuT/CQrk/wgJ4/8FBeP/AwPj/wEB4/8CAuH/ICDf/05R5f91euL/tLvn/+Ps8P/l7e3/z9fY/7e/\n        xv+rtMD/l56p/3l/h/9aXmT/LzI1/x4hI/8eHyL/Gx0f/yEjJv9CRUr/XWFp/2Fmbv9MUVn/PEJK+jg+\n        RsE5P0dkO0BIEzM2QAA9Q0oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAElMVABKTVUCRktUG0FHUGtARk3IQEdQ+FVbZf9tdH3/a3J4/1JXXP8oLC//ICEl/yAi\n        Jv8gISX/LC8y/1hcYv94fof/m6Ku/7zE0//Dy9b/197m//P6/P/0+Pr/4+j5/7vA9f+QlfH/aGzs/ykr\n        4f8MDeH/Bwjh/wIC4v8CAuL/Bgbi/wcH4/8JCeP/CQnj/woK5P8KCuP/Cgvk/woM4/8KC+T/Cgvk/woL\n        5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woL5P8KC+T/Cgvk/woK\n        5P8KCuT/Cgrk/woK5P8KCuT/Cgrj/woK5P8KCuT/Cgrk/woK4/8JCeP/CAjj/wYG4v8BAuL/AgLi/wcI\n        4f8MDeH/KCrl/1ld6f+Dhun/sLXq/+Ln8//v8/P/5Ozt/8rS2P+4wMv/sLjF/5Obp/9wdn7/VVle/y0v\n        Mv8cHiD/Gx4h/xwfIf8lJyr/QERI/11iZ/9kanH/U1pj/z1DS/w6P0bXOkBGgTxCSSY9QkkFPUJJAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AABSXGYAQURLAExSWwNDSVAmP0VOfz1ETNJHTVb5YGdx/210ff9tc3v/UFNZ/ystMf8jJSn/HyEj/xwe\n        If8nKS3/QkVJ/1tfZv+EipT/srrH/8LL2P/R2+f/7PX6//L3+f/z9vr/8/X9/8zR9/+sr/X/gITw/0lK\n        5/8mJuP/Gxvi/w8Q4v8EBOH/AQHh/wQE4f8FBeL/Bwfi/wcH4v8ICOL/CQrj/woM4/8KC+P/Cgvj/woL\n        4/8KDOP/Cwzk/wsM5P8LDOT/Cwzk/wsM5P8LDOP/Cwzk/wsM5P8LDOP/Cgvj/woK5P8KCuT/Cgrj/wkK\n        4/8ICOP/CAjj/wcH4/8GBuL/BATi/wIC4f8DA+H/Cwvh/xYX4f8lJ+T/SEvl/4CE7f+mqvH/yc/6/+bs\n        /P/v8vb/7O/y/9rh6P/CydX/sbrH/6Wtuf+CiJL/YGVs/0VITv8qLTD/Ghwf/xodIP8eICP/Jigs/0dJ\n        Tv9pbnT/Y2py/1deaP9BSFD7Nz5F3jpASJA8QUg2P0VLBzQ6NgBARk8AAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AABFTlMAQ0tSB0VMUzZESVGJPkRM1UdOVftZYGj/bHN9/3R6gv9SVVv/ODo+/ycpLf8fISP/HB4h/yAi\n        Jv80Njr/Sk1T/3R5gf+hqbP/tb7K/7rE0f/U3uj/7PP4//L3+f/5/Pz/+fz+/+Pk+//Kyvj/uLn2/5ib\n        9P9naer/Q0Xn/yor5f8eHuT/ERHj/woL4v8EBuL/AgLh/wQF4P8EBeD/BAXg/wQF4f8FBeH/BQXi/wUG\n        4v8FBuL/BQbi/wUG4v8FBuL/BQbi/wUG4v8FBeL/BQXh/wQE4f8EBOH/BATg/wIC4P8CAuL/Bgfh/w0O\n        4v8bHOP/Jyjj/zo75v9dYOv/hIjv/66w9P/Gyff/3uH5//X5/v/v9Pj/6O3y/+Hn7v/J0t3/sbnG/6at\n        uv+bo67/d3yE/0pOU/8zNzr/Jicq/xsdH/8cHiD/JSYq/zAzNv9ER0v/ZWpx/2Vqc/9UWmP/Q0pS/jg+\n        RuA7QUmaPkRLQz5ETA0+REwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARlVnAEhL\n        SgBHTlMLRktTN0FHT4c/RU3VSE5X+VlfZ/91fIT/eoCI/1peZP9HSk7/MzQ4/yAiJf8eICP/ICMm/yst\n        MP8xMzb/TFBV/36Ejf+dpK7/qrO+/8HK1//h6vX/7fT6//D1+P/1+vn//f/8//z8///w8f3/4uP8/9XV\n        +v/Bwvj/nJ7z/4iL8P92efD/UFHq/zs85/82N+b/MzPn/y8v5/8oKOb/Hh7k/xYX4/8XF+T/FRbk/xUW\n        5P8UFuT/FBbk/xUW4/8dHeP/KCnm/zIz5/82N+f/OTrn/0hJ6P9lZuz/en3s/5GU8P+8vfX/09P5/93e\n        +//r7v3/9vn///r9/f/u9fb/5ezy/93k7//M1eP/srvI/6CotP+Tm6T/f4WO/1ddY/80Nzv/Kyww/yAi\n        Jf8dICL/HiAj/yorMP9AQkf/VFhe/21ze/9sdHz/Ulpi/0NJUvw5P0fhOkBHmT9FTUVBR08QPUNOAT9F\n        TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFSVIAQkFNAEZL\n        UwZGTFQtQ0lRekNJUctITlbwTVRb/250ff9/hY3/a3B3/1ldYf9BRUj/JScr/yAjJv8iIyf/IyQn/yMl\n        KP8kJin/REhM/3Z7gv+SmKL/oKiy/6+4xP/L1eL/3+jx/+Xt9f/o7vD/8vX2//v8+v/+//7//v7///z9\n        ///6+v//9PT+//Hx/v/v8P7/7e7+/+Xm/f/V1vr/v7/3/7Cx9v+vsfb/rK72/6uu9v+qrfb/qq31/66v\n        9P++vvX/1dX6/+rr/f/v7/3/8PD+//Pz/v/4+P//+/v///z9///9/v3/+Pv4/+/19v/h6e7/2+Pt/9fg\n        6//DzNj/pq67/5adqf+Hjpf/dHmA/09SV/8nKCz/IiMn/yIkKP8hIyf/ISQn/yEkJv87PUH/Vltg/2No\n        bv94f4f/bnV//1FXYf9JT1j1Q0pS1UBGTYo/RU48QUZNDDtLQABARkwAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABESlIAREpSAkRK\n        UiZGS1VkRUtUrURLVORHTVb/YGZw/3d+hv91fIP/bXJ6/1hcYf83OT3/IiQn/yMlKP8lJyv/Jiks/yMl\n        KP8kJyr/QUVI/15jZ/9xdXv/foSL/46WoP+dpa//wszZ/9/l7//k6/T/4ebu/9vg5v/e5Or/5uzz/+vv\n        9P/w8vT/8/X2//X3+P/5+/z//v///////////////////////////////////////////////P7+//b4\n        +v/x8/b/7PDz/+nu9f/h5u3/2d7l/9vh6f/b4+3/2ODq/8XN2/+gqLT/jZOd/3l/h/9pb3X/XmFn/0VI\n        TP8kJyn/Hh8i/yAjJf8iJCf/IiQn/yEjJv8uMDP/UFRZ/2pvdf9zeIH/eH+I/2hud/9KUFj/QUdQ60RK\n        UrhGS1NyRkxVL0VPVQNFTVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5WWwBPVlsCSU9ZFUdN\n        VkBHTVeKRktVy0ZMVfNYX2j9bXR9/3F3f/96gIj/eX6F/2Fkav80Nzv/Kiww/ystMP8nKSz/JScq/yQl\n        KP8gIiX/JSgr/zs+Qf9LTlL/W15k/2ZrcP98goj/iY+Z/5Oaov+qsrr/x8/c/9La5//a4en/2eDo/9Pc\n        5v/U3Of/09rl/8jQ2f/Fy9T/wMbP/8DFzv/Fy9X/ytHb/9Tb5f/d5fD/3ebw/9vj6//a4ur/1d3o/8jR\n        3/+xucX/k5um/4eNmP94fYb/ZWpw/1dcYf9MUFT/P0JF/yYoK/8aHB//HiAj/yEiJv8iJSj/Jigr/ygq\n        Lf8xMzb/VVld/3l+hv97gYj/b3V//210fv9bYmz9Rk1W9kZMVdZFS1OXQkhQTENJURtBR1AEQUdQAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGpuAHZ8fABRV14GSU9YIEpQ\n        WVlITleaRUtU0kxRW+9cYmv8Y2lx/2txef99gov/hYuR/2ludP9IS1D/PkFE/zs/Qv80Njr/KSsv/yIj\n        J/8hIyb/IiQm/yUnKv8yNDf/PD5C/0RGSf9MTlH/U1Za/1JVWv9bX2P/ZGhs/2ltc/9wdHr/dnqC/3h9\n        hf9+gor/g4iR/4OIkf+AhY3/fYOL/3V6gv9wdX3/bHF3/2Jma/9SVlr/T1JX/01QVP9KTE//QUJH/zo8\n        QP8wMjb/IyUo/x0fIv8eISP/HyEk/yUnK/8uMDT/Njg9/zk7P/9BREj/YmZs/4GGjv+Bh5D/cXiA/2Vs\n        df9hZ3H+TVRd8kFIUNhDSlKmRk1VZkZNVilJUVoJUFVdAU5UXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT1VeAFBWXwFPVV4MTlRdLklP\n        WGFESlKaREpSyUtRWulVXGX8XGNr/3B4gf+LkZv/lp2m/4WLk/9zd37/Wl5k/1VXXP9NUFT/P0FF/y8x\n        Nf8nKSv/Jigq/yYoKv8oKiz/KSst/yosLv8wMjX/Njc5/zg6PP87PD7/Pj9B/0BBRf9CQ0b/RUZJ/0RG\n        SP9BQ0b/P0FE/zs9QP84Ojz/NTc5/zAxNP8pKy3/JScq/yQnKf8kJij/IiQn/yAjJv8iJCf/LC4x/zw/\n        Q/9IS0//T1FX/1VYX/9pbXT/fYGJ/4mPmP+FipT/bXR9/1xjbf9YXmf/TVRd70NJUtBDSVKjRUtUa0dP\n        VjZIT1cRSVBYAUlQWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVFpmAFVaaAJSWmIOUVdgJktR\n        WlRFS1OERkxUuE5VXdtWXGbyV11o/F1ibP91fIX/iZGa/5efqP+LkZn/foOL/2tyd/9kaG3/bHB1/2ls\n        cf9fYWX/V1ld/0pNUf84Oj3/Li8y/zAyNP8wMTT/LzAz/y4wMv8uMDH/LS8x/ywuMP8sLTD/Ky0v/ywt\n        Mf8sLjH/Kiwv/yssL/81Njr/QkRI/05RVf9ZXGD/Z2tw/2pudP9laW7/am91/3yAif+Gi5P/kZeg/4iP\n        mf9yeYL/W2Jr/1FYYf1PVV72SlBZ4EVLU79CSVCPREpTXUpQWS9OVV4SVlpkA0ZVVQBZWmgAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AWF5iAGxxdAFcYmkGUFZeFEpQ\n        WDdJT1heSU9Yi0pQWbNLUVrSTVNc6E5VXvdWXmf/bXR9/36Gj/+Hj5n/kZii/4uRmv+Bh4//iIyU/4eN\n        lf98gYj/cnd8/3t/hf9+gon/g4eO/4SHjv+DiI//hYmQ/4WKkP+Cho3/goaN/4GGjv9+gon/en+F/3R5\n        f/96fob/gYeP/4OIkf+Aho7/jJOc/5KZpP+OlZ//gIeR/211f/9YX2n/TlVe+ktRW+tITlfXSU9YuUhO\n        V5NES1NlRkxTPktSWRpRWmEHYGhvAf///wBscnsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMUlsAS1JaAU1T\n        XBZOVl0xUVdgS1JZYmpRWGGMTVNcqklQWcRKUFnZSlFa70pQWflPVl/8XmVu/mtyfP51fYb/eYCK/32D\n        jv9/hZD/g4qV/4SLlv+EjJb/ho2Y/4eOmf+FjJb/hYyX/4WNl/+BiJL/gIeR/3uDjP90e4X/bHN9/mBm\n        cP5TWmT8TVRe+k1UXfJNVF3dS1Fbx01UXa9PWF+SUVhgb1BXYFFPVV42TlRdG1FXYANNU1wAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU15nAFVn\n        cABSWWIIU1liF1NZYiVTWWIzUlliQlBXX11QV191TlZeikxSW5xJT1iuSU9YvEhPWMlJT1nVSlFb30xT\n        XedNVF3tTFRd8E1UXvBNVF7tTFNd6EtSW+FKUVrXSlFazExTXL9MUlywS1JboE9UXo1SWWN4VFtlYVVc\n        ZEdVXGU1VFpkJ1RZZBlTWWMKVllmAVVZZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////wAAAAAP///////////////\n        /////////8AAAAAAA///////////////////////+AAAAAAAAB//////////////////////wAAAAAAA\n        AAH////////////////////+AAAAAAAAAAB////////////////////wAAAAAAAAAAAP////////////\n        ///////AAAAAAAAAAAAD//////////////////8AAAAAAAAAAAAA//////////////////wAAAAAAAAA\n        AAAAH////////////////+AAAAAAAAAAAAAAB////////////////8AAAAAAAAAAAAAAA///////////\n        /////wAAAAAAAAAAAAAAAP///////////////AAAAAAAAAAAAAAAAD//////////////+AAAAAAAAAAA\n        AAAAAA//////////////4AAAAAAAAAAAAAAAAAf/////////////gAAAAAAAAAAAAAAAAAH/////////\n        ////AAAAAAAAAAAAAAAAAAD////////////+AAAAAAAAAAAAAAAAAAA////////////4AAAAAAAAAAAA\n        AAAAAAAf///////////wAAAAAAAAAAAAAAAAAAAP///////////gAAAAAAAAAAAAAAAAAAAD////////\n        //+AAAAAAAAAAAAAAAAAAAAB//////////8AAAAAAAAAAAAAAAAAAAAA//////////4AAAAAAAAAAAAA\n        AAAAAAAAf/////////wAAAAAAAAAAAAAAAAAAAAAP/////////gAAAAAAAAAAAAAAAAAAAAAH///////\n        //AAAAAAAAAAAAAAAAAAAAAAD////////+AAAAAAAAAAAAAAAAAAAAAAB////////8AAAAAAAAAAAAAA\n        AAAAAAAAA////////4AAAAAAAAAAAAAAAAAAAAAAAf///////wAAAAAAAAAAAAAAAAAAAAAAAP//////\n        /gAAAAAAAAAAAAAAAAAAAAAAAH///////AAAAAAAAAAAAAAAAAAAAAAAAD///////AAAAAAAAAAAAAAA\n        AAAAAAAAAB//////+AAAAAAAAAAAAAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAAAAAAAAAAAA//////\n        4AAAAAAAAAAAAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAA\n        AAAAAAAAAAH/////gAAAAAAAAAAAAAAAAAAAAAAAAAH/////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////\n        AAAAAAAAAAAAAAAAAAAAAAAAAAB////+AAAAAAAAAAAAAAAAAAAAAAAAAAB////8AAAAAAAAAAAAAAAA\n        AAAAAAAAAAA////8AAAAAAAAAAAAAAAAAAAAAAAAAAAf///4AAAAAAAAAAAAAAAAAAAAAAAAAAAf///w\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///gAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAH///gAAAAAAAAAAAAAAAAAAAAAAAAAAAH///AAAAAAAAAAAAAAAAAAAAAAAAAAAAD///A\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAD//+AAAAAAAAAAAAAAAAAAAAAAAAAAAAB//+AAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA//4A\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAf/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/wAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+AA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/AA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wA\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAP/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/8A\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+AAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAB//+AAAAAAAAAAAAAAAAAAAAAAAAAAAAB///AAAAAAAAAAAAAAAAAAAAAAAAAAAAD///A\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAD///gAAAAAAAAAAAAAAAAAAAAAAAAAAAH///gAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAH///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4\n        AAAAAAAAAAAAAAAAAAAAAAAAAAAf///8AAAAAAAAAAAAAAAAAAAAAAAAAAA////8AAAAAAAAAAAAAAAA\n        AAAAAAAAAAA////+AAAAAAAAAAAAAAAAAAAAAAAAAAB/////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////\n        AAAAAAAAAAAAAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAA\n        AAAAAAAAAAP/////4AAAAAAAAAAAAAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAAAAAAAAAAAAf/////\n        8AAAAAAAAAAAAAAAAAAAAAAAAA//////+AAAAAAAAAAAAAAAAAAAAAAAAB///////AAAAAAAAAAAAAAA\n        AAAAAAAAAD///////gAAAAAAAAAAAAAAAAAAAAAAAD///////gAAAAAAAAAAAAAAAAAAAAAAAH//////\n        /wAAAAAAAAAAAAAAAAAAAAAAAP///////4AAAAAAAAAAAAAAAAAAAAAAAf///////8AAAAAAAAAAAAAA\n        AAAAAAAAA////////+AAAAAAAAAAAAAAAAAAAAAAB/////////AAAAAAAAAAAAAAAAAAAAAAD///////\n        //gAAAAAAAAAAAAAAAAAAAAAH/////////wAAAAAAAAAAAAAAAAAAAAAP/////////4AAAAAAAAAAAAA\n        AAAAAAAAf/////////+AAAAAAAAAAAAAAAAAAAAA///////////AAAAAAAAAAAAAAAAAAAAD////////\n        ///gAAAAAAAAAAAAAAAAAAAH///////////wAAAAAAAAAAAAAAAAAAAP///////////8AAAAAAAAAAAA\n        AAAAAAAf///////////+AAAAAAAAAAAAAAAAAAB/////////////AAAAAAAAAAAAAAAAAAD/////////\n        ////wAAAAAAAAAAAAAAAAAH/////////////4AAAAAAAAAAAAAAAAAf/////////////+AAAAAAAAAAA\n        AAAAAB///////////////AAAAAAAAAAAAAAAAD///////////////wAAAAAAAAAAAAAAAP//////////\n        /////8AAAAAAAAAAAAAAA/////////////////AAAAAAAAAAAAAAB/////////////////wAAAAAAAAA\n        AAAAP/////////////////8AAAAAAAAAAAAA///////////////////AAAAAAAAAAAAD////////////\n        ///////4AAAAAAAAAAAP///////////////////+AAAAAAAAAAB/////////////////////wAAAAAAA\n        AAP/////////////////////+AAAAAAAAB///////////////////////8AAAAAAA///////////////\n        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\n</value>\n  </data>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Model/BasicSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Globalization;\nusing System.Runtime.CompilerServices;\n\nnamespace MobiusEditor.Model\n{\n    public class BooleanTypeConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\n        {\n            return (context is MapContext) && (sourceType == typeof(string));\n        }\n\n        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)\n        {\n            return (context is MapContext) && (destinationType == typeof(string));\n        }\n\n        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)\n        {\n            if (!(value is bool boolean) || !CanConvertTo(context, destinationType))\n            {\n                return null;\n            }\n\n            return boolean ? \"1\" : \"0\";\n        }\n\n        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n        {\n            if (!(value is string str) || !CanConvertFrom(context, value?.GetType()))\n            {\n                return null;\n            }\n\n            var first = (str.Length > 0) ? str.ToUpper()[0] : 0;\n            return (first == 'T') || (first == 'Y') || (first == '1');\n        }\n    }\n\n    public class PercentageTypeConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\n        {\n            return (context is MapContext) && (sourceType == typeof(string));\n        }\n\n        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)\n        {\n            return (context is MapContext) && (destinationType == typeof(string));\n        }\n\n        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)\n        {\n            if (!(value is int percent) || !CanConvertTo(context, destinationType))\n            {\n                return null;\n            }\n\n            var mapContext = context as MapContext;\n            return mapContext.FractionalPercentages ? (percent / 100M).ToString(\"D2\") : percent.ToString();\n        }\n\n        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n        {\n            if (!(value is string str) || !CanConvertFrom(context, value?.GetType()))\n            {\n                return null;\n            }\n\n            var mapContext = context as MapContext;\n            if (mapContext.FractionalPercentages && str.Contains(\".\"))\n            {\n                if (!decimal.TryParse(str, out decimal percent))\n                {\n                    return null;\n                }\n                return (int)(percent * 100);\n            }\n            else\n            {\n                if (!int.TryParse(str, out int percent))\n                {\n                    return null;\n                }\n                return percent;\n            }\n        }\n    }\n\n    public class BasicSection : INotifyPropertyChanged\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private string name;\n        [DefaultValue(null)]\n        public string Name { get => name; set => SetField(ref name, value); }\n\n        private int carryOverCap;\n        [TypeConverter(typeof(PercentageTypeConverter))]\n        [DefaultValue(-1)]\n        public int CarryOverCap { get => carryOverCap; set => SetField(ref carryOverCap, value); }\n\n        private int carryOverMoney;\n        [TypeConverter(typeof(PercentageTypeConverter))]\n        [DefaultValue(100)]\n        public int CarryOverMoney { get => carryOverMoney; set => SetField(ref carryOverMoney, value); }\n\n        private string intro;\n        [DefaultValue(null)]\n        public string Intro { get => intro; set => SetField(ref intro, value); }\n\n        private string theme;\n        [DefaultValue(\"No Theme\")]\n        public string Theme { get => theme; set => SetField(ref theme, value); }\n\n        private int percent;\n        [TypeConverter(typeof(PercentageTypeConverter))]\n        [DefaultValue(100)]\n        public int Percent { get => percent; set => SetField(ref percent, value); }\n\n        public string player;\n        [DefaultValue(null)]\n        public string Player { get => player; set => SetField(ref player, value); }\n\n        private string action;\n        [DefaultValue(\"x\")]\n        public string Action { get => action; set => SetField(ref action, value); }\n\n        private string lose;\n        [DefaultValue(\"x\")]\n        public string Lose { get => lose; set => SetField(ref lose, value); }\n\n        private string win;\n        [DefaultValue(\"x\")]\n        public string Win { get => win; set => SetField(ref win, value); }\n\n        private string brief;\n        [DefaultValue(\"x\")]\n        public string Brief { get => brief; set => SetField(ref brief, value); }\n\n        private string author;\n        [DefaultValue(null)]\n        public string Author { get => author; set => SetField(ref author, value); }\n\n        private string basePlayer;\n        [NonSerializedINIKey]\n        [DefaultValue(null)]\n        public string BasePlayer { get => basePlayer; set => SetField(ref basePlayer, value); }\n\n        private bool soloMission;\n        [DefaultValue(false)]\n        public bool SoloMission { get => soloMission; set => SetField(ref soloMission, value); }\n\n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/BriefingSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.ComponentModel;\n\nnamespace MobiusEditor.Model\n{\n    public class BriefingSection\n    {\n        [DefaultValue(null)]\n        public string Briefing { get; set; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Building.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Runtime.CompilerServices;\n\nnamespace MobiusEditor.Model\n{\n    public class Building : ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private BuildingType type;\n        public BuildingType Type { get => type; set => SetField(ref type, value); }\n\n        public Rectangle OverlapBounds => Type.OverlapBounds;\n\n        public bool[,] OccupyMask => Type.OccupyMask;\n\n        private HouseType house;\n        public HouseType House { get => house; set => SetField(ref house, value); }\n\n        private int strength;\n        public int Strength { get => strength; set => SetField(ref strength, value); }\n\n        private DirectionType direction;\n        public DirectionType Direction { get => direction; set => SetField(ref direction, value); }\n\n        private string trigger = Model.Trigger.None;\n        public string Trigger { get => trigger; set => SetField(ref trigger, value); }\n\n        private int basePriority = -1;\n        public int BasePriority { get => basePriority; set => SetField(ref basePriority, value); }\n\n        private bool isPrebuilt = true;\n        public bool IsPrebuilt { get => isPrebuilt; set => SetField(ref isPrebuilt, value); }\n\n        private bool sellable;\n        public bool Sellable { get => sellable; set => SetField(ref sellable, value); }\n\n        private bool rebuild;\n        public bool Rebuild { get => rebuild; set => SetField(ref rebuild, value); }\n\n        public ISet<int> BibCells { get; private set; } = new HashSet<int>();\n\n        private Color tint = Color.White;\n        public Color Tint\n        {\n            get => IsPrebuilt ? tint : Color.FromArgb((int)(tint.A * 0.75f), tint.R, tint.G, tint.B);\n            set => tint = value;\n        }\n\n        public Building Clone()\n        {\n            return new Building()\n            {\n                Type = Type,\n                House = House,\n                Strength = Strength,\n                Direction = Direction,\n                Trigger = Trigger,\n                BasePriority = BasePriority,\n                IsPrebuilt = IsPrebuilt,\n                Sellable = Sellable,\n                Rebuild = Rebuild,\n                Tint = Tint\n            };\n        }\n\n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/BuildingType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Render;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class BuildingType : ICellOverlapper, ICellOccupier, ITechnoType, IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName { get; private set; }\n\n        public string Tilename { get; private set; }\n\n        public Rectangle OverlapBounds => new Rectangle(Point.Empty, new Size(OccupyMask.GetLength(1), OccupyMask.GetLength(0)));\n\n        public bool[,] OccupyMask { get; private set; }\n\n        public bool[,] BaseOccupyMask { get; private set; }\n\n        public Size Size { get; private set; }\n\n        public bool HasBib { get; private set; }\n\n        public string OwnerHouse { get; private set; }\n\n        public TheaterType[] Theaters { get; private set; }\n\n        public bool IsFake { get; private set; }\n\n        public bool HasTurret { get; private set; }\n\n        public string FactoryOverlay { get; private set; }\n\n        public Image Thumbnail { get; set; }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse, TheaterType[] theaters, bool isFake, bool hasTurret, string factoryOverlay)\n        {\n            ID = id;\n            Name = isFake ? (name.Substring(0, name.Length - 1) + \"f\") : name;\n            DisplayName = Globals.TheGameTextManager[textId];\n            Tilename = name;\n            BaseOccupyMask = occupyMask;\n            Size = new Size(BaseOccupyMask.GetLength(1), BaseOccupyMask.GetLength(0));\n            HasBib = hasBib;\n            OwnerHouse = ownerHouse;\n            Theaters = theaters;\n            IsFake = isFake;\n            HasTurret = hasTurret;\n            FactoryOverlay = factoryOverlay;\n\n            if (HasBib)\n            {\n                OccupyMask = new bool[BaseOccupyMask.GetLength(0) + 1, BaseOccupyMask.GetLength(1)];\n                for (var i = 0; i < BaseOccupyMask.GetLength(0) - 1; ++i)\n                {\n                    for (var j = 0; j < BaseOccupyMask.GetLength(1); ++j)\n                    {\n                        OccupyMask[i, j] = BaseOccupyMask[i, j];\n                    }\n                }\n                for (var j = 0; j < OccupyMask.GetLength(1); ++j)\n                {\n                    OccupyMask[OccupyMask.GetLength(0) - 2, j] = true;\n                    OccupyMask[OccupyMask.GetLength(0) - 1, j] = true;\n                }\n            }\n            else\n            {\n                OccupyMask = BaseOccupyMask;\n            }\n        }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse, bool isFake, bool hasTurret, string factoryOverlay)\n            : this(id, name, textId, occupyMask, hasBib, ownerHouse, null, isFake, hasTurret, factoryOverlay)\n        {\n        }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse)\n            : this(id, name, textId, occupyMask, hasBib, ownerHouse, null, false, false, null)\n        {\n        }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse, TheaterType[] theaters)\n            : this(id, name, textId, occupyMask, hasBib, ownerHouse, theaters, false, false, null)\n        {\n        }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse, bool isFake)\n            : this(id, name, textId, occupyMask, hasBib, ownerHouse, null, isFake, false, null)\n        {\n        }\n\n        public BuildingType(sbyte id, string name, string textId, bool[,] occupyMask, bool hasBib, string ownerHouse, bool isFake, bool hasTurret)\n            : this(id, name, textId, occupyMask, hasBib, ownerHouse, null, isFake, hasTurret, null)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is BuildingType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(GameType gameType, TheaterType theater, HouseType house, DirectionType direction)\n        {\n            var mockBuilding = new Building()\n            {\n                Type = this,\n                House = house,\n                Strength = 256,\n                Direction = direction\n            };\n\n            var render = MapRenderer.Render(gameType, theater, Point.Empty, Globals.TileSize, Globals.TileScale, mockBuilding);\n            if (!render.Item1.IsEmpty)\n            {\n                var buildingPreview = new Bitmap(render.Item1.Width, render.Item1.Height);\n                using (var g = Graphics.FromImage(buildingPreview))\n                {\n                    render.Item2(g);\n                }\n                Thumbnail = buildingPreview;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/CellGrid.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public enum FacingType\n    {\n        None,\n        North,\n        NorthEast,\n        East,\n        SouthEast,\n        South,\n        SouthWest,\n        West,\n        NorthWest\n    }\n\n    public class CellChangedEventArgs<T> : EventArgs\n    {\n        public readonly int Cell;\n\n        public readonly Point Location;\n\n        public readonly T OldValue;\n\n        public readonly T Value;\n\n        public CellChangedEventArgs(CellMetrics metrics, int cell, T oldValue, T value)\n        {\n            Cell = cell;\n            metrics.GetLocation(cell, out Location);\n            OldValue = oldValue;\n            Value = value;\n        }\n\n        public CellChangedEventArgs(CellMetrics metrics, Point location, T oldValue, T value)\n        {\n            Location = location;\n            metrics.GetCell(location, out Cell);\n            OldValue = oldValue;\n            Value = value;\n        }\n    }\n\n    public class CellGrid<T> : IEnumerable<(int Cell, T Value)>, IEnumerable\n    {\n        private readonly CellMetrics metrics;\n        private readonly T[,] cells;\n\n        public T this[int x, int y]\n        {\n            get => cells[y, x];\n            set\n            {\n                if (!EqualityComparer<T>.Default.Equals(cells[y, x], value))\n                {\n                    var lastValue = cells[y, x];\n                    cells[y, x] = value;\n                    OnCellChanged(new CellChangedEventArgs<T>(metrics, new Point(x, y), lastValue, cells[y, x]));\n                }\n            }\n        }\n\n        public T this[Point location] { get => this[location.X, location.Y]; set => this[location.X, location.Y] = value; }\n\n        public T this[int cell] { get => this[cell % metrics.Width, cell / metrics.Width]; set => this[cell % metrics.Width, cell / metrics.Width] = value; }\n\n        public Size Size => metrics.Size;\n\n        public int Length => metrics.Length;\n\n        public event EventHandler<CellChangedEventArgs<T>> CellChanged;\n        public event EventHandler<EventArgs> Cleared;\n\n        public CellGrid(CellMetrics metrics)\n        {\n            this.metrics = metrics;\n\n            cells = new T[metrics.Height, metrics.Width];\n        }\n\n        public void Clear()\n        {\n            Array.Clear(cells, 0, cells.Length);\n            OnCleared();\n        }\n\n        public T Adjacent(Point location, FacingType facing)\n        {\n            return metrics.Adjacent(location, facing, out Point adjacent) ? this[adjacent] : default;\n        }\n\n        public T Adjacent(int cell, FacingType facing)\n        {\n            if (!metrics.GetLocation(cell, out Point location))\n            {\n                return default;\n                \n            }\n            return metrics.Adjacent(location, facing, out Point adjacent) ? this[adjacent] : default;\n        }\n\n        public bool CopyTo(CellGrid<T> other)\n        {\n            if (metrics.Length != other.metrics.Length)\n            {\n                return false;\n            }\n\n            for (var i = 0; i < metrics.Length; ++i)\n            {\n                other[i] = this[i];\n            }\n\n            return true;\n        }\n\n        protected virtual void OnCellChanged(CellChangedEventArgs<T> e)\n        {\n            CellChanged?.Invoke(this, e);\n        }\n\n        protected virtual void OnCleared()\n        {\n            Cleared?.Invoke(this, new EventArgs());\n        }\n\n        public IEnumerable<(int Cell, T Value)> IntersectsWith(ISet<int> cells)\n        {\n            foreach (var i in cells)\n            {\n                if (metrics.Contains(i))\n                {\n                    var cell = this[i];\n                    if (cell != null)\n                    {\n                        yield return (i, cell);\n                    }\n                }\n            }\n        }\n\n        public IEnumerable<(int Cell, T Value)> IntersectsWith(ISet<Point> locations)\n        {\n            foreach (var location in locations)\n            {\n                if (metrics.Contains(location))\n                {\n                    var cell = this[location];\n                    if (cell != null)\n                    {\n                        metrics.GetCell(location, out int i);\n                        yield return (i, cell);\n                    }\n                }\n            }\n        }\n\n        public IEnumerator<(int Cell, T Value)> GetEnumerator()\n        {\n            for (var i = 0; i < metrics.Length; ++i)\n            {\n                var cell = this[i];\n                if (cell != null)\n                {\n                    yield return (i, cell);\n                }\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/CellMetrics.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MobiusEditor.Model\n{\n    public class CellMetrics\n    {\n        public static readonly FacingType[] AdjacentFacings = new FacingType[] {\n            FacingType.North, FacingType.NorthEast, FacingType.East, FacingType.SouthEast, FacingType.South, FacingType.SouthWest, FacingType.West, FacingType.NorthWest\n        };\n\n        public int Width { get; private set; }\n\n        public int Height { get; private set; }\n\n        public Point TopLeft => Point.Empty;\n\n        public Size Size => new Size(Width, Height);\n\n        public Rectangle Bounds => new Rectangle(TopLeft, Size);\n\n        public int Length => Width * Height;\n\n        public bool Contains(Point location) => ((location.X >= 0) && (location.X < Width) && (location.Y >= 0) && (location.Y < Height));\n\n        public bool Contains(int cell) => ((cell >= 0) && (cell < Length));\n\n        public CellMetrics(int width, int height)\n        {\n            Width = width;\n            Height = height;\n        }\n\n        public CellMetrics(Size size)\n            : this(size.Width, size.Height)\n        {\n        }\n\n        public bool GetCell(Point location, out int cell)\n        {\n            cell = (location.Y * Width) + location.X;\n            return Contains(location);\n        }\n\n        public bool GetLocation(int cell, out Point location)\n        {\n            location = new Point(cell % Width, cell / Width);\n            return Contains(cell);\n        }\n\n        public bool Adjacent(Point location, FacingType facing, out Point adjacent)\n        {\n            adjacent = location;\n            switch (facing)\n            {\n                case FacingType.North:\n                    adjacent.Y--;\n                    break;\n                case FacingType.NorthEast:\n                    adjacent.X++;\n                    adjacent.Y--;\n                    break;\n                case FacingType.East:\n                    adjacent.X++;\n                    break;\n                case FacingType.SouthEast:\n                    adjacent.X++;\n                    adjacent.Y++;\n                    break;\n                case FacingType.South:\n                    adjacent.Y++;\n                    break;\n                case FacingType.SouthWest:\n                    adjacent.X--;\n                    adjacent.Y++;\n                    break;\n                case FacingType.West:\n                    adjacent.X--;\n                    break;\n                case FacingType.NorthWest:\n                    adjacent.X--;\n                    adjacent.Y--;\n                    break;\n            }\n\n            return Contains(adjacent);\n        }\n\n        public bool Adjacent(int cell, FacingType facing, out int adjacent)\n        {\n            if (!GetLocation(cell, out Point location) || !Adjacent(location, facing, out Point adjacentPoint))\n            {\n                adjacent = -1;\n                return false;\n            }\n            else\n            {\n                return GetCell(adjacentPoint, out adjacent);\n            }\n        }\n\n        public void Clip(ref Point location)\n        {\n            location.X = Math.Max(0, Math.Min(Width - 1, location.X));\n            location.Y = Math.Max(0, Math.Min(Height - 1, location.Y));\n        }\n\n        public void Clip(ref Point location, Size margin)\n        {\n            Clip(ref location, margin, margin);\n        }\n\n        public void Clip(ref Point location, Size topLeftMargin, Size bottomRightMargin)\n        {\n            location.X = Math.Max(topLeftMargin.Width, Math.Min(Width - bottomRightMargin.Width - 1, location.X));\n            location.Y = Math.Max(topLeftMargin.Height, Math.Min(Height - bottomRightMargin.Height - 1, location.Y));\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/CellTrigger.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Model\n{\n    public class CellTrigger\n    {\n        public string Trigger { get; set; } = Model.Trigger.None;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/DirectionType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\n\nnamespace MobiusEditor.Model\n{\n    public class DirectionType\n    {\n        public byte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public FacingType Facing { get; private set; }\n\n        public DirectionType(byte id, string name, FacingType facing)\n        {\n            ID = id;\n            Name = name;\n            Facing = facing;\n        }\n\n        public DirectionType(byte id, string name)\n            : this(id, name, FacingType.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is DirectionType)\n            {\n                return this == obj;\n            }\n            else if (obj is byte)\n            {\n                return ID == (byte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n            else if (obj is FacingType)\n            {\n                return Facing == (FacingType)obj;\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/House.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Globalization;\nusing System.Linq;\n\nnamespace MobiusEditor.Model\n{\n    public struct AlliesMask : IEnumerable<int>\n    {\n        public int Value { get; private set; }\n\n        public AlliesMask(int value)\n        {\n            Value = value;\n        }\n\n        public void Set(int id)\n        {\n            if ((id < 0) || (id > 31))\n            {\n                throw new ArgumentOutOfRangeException();\n            }\n\n            Value |= (1 << id);\n        }\n\n        public void Clear(int id)\n        {\n            if ((id < 0) || (id > 31))\n            {\n                throw new ArgumentOutOfRangeException();\n            }\n\n            Value &= ~(1 << id);\n        }\n\n        public override bool Equals(object obj)\n        {\n            return Value.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return Value.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Value.ToString();\n        }\n\n        public IEnumerator<int> GetEnumerator()\n        {\n            for (int i = 0, mask = 1; i < 32; ++i, mask <<= 1)\n            {\n                if ((Value & mask) != 0)\n                {\n                    yield return i;\n                }\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    public class AlliesMaskTypeConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\n        {\n            return (context is MapContext) && (sourceType == typeof(string));\n        }\n\n        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)\n        {\n            return (context is MapContext) && (destinationType == typeof(string));\n        }\n\n        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)\n        {\n            if (!(value is AlliesMask) || !CanConvertTo(context, destinationType))\n            {\n                return null;\n            }\n\n            var map = (context as MapContext).Map;\n            var alliesMask = (AlliesMask)value;\n\n            var allies = new List<string>(map.Houses.Length);\n            foreach (var id in alliesMask)\n            {\n                if (map.Houses.Where(h => h.Type.Equals((sbyte)id)).FirstOrDefault() is House house)\n                {\n                    allies.Add(house.Type.Name);\n                }\n            }\n\n            return string.Join(\",\", allies);\n        }\n\n        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n        {\n            if (!CanConvertFrom(context, value?.GetType()))\n            {\n                return null;\n            }\n\n            var map = (context as MapContext).Instance as Map;\n            var alliesMask = new AlliesMask(0);\n\n            var allies = (value as string).Split(',');\n            foreach (var ally in allies)\n            {\n                if (map.Houses.Where(h => h.Type.Equals(ally)).FirstOrDefault() is House house)\n                {\n                    alliesMask.Set(house.Type.ID);\n                }\n            }\n\n            return alliesMask;\n        }\n    }\n\n    public class House\n    {\n        public readonly HouseType Type;\n\n        [NonSerializedINIKey]\n        [DefaultValue(true)]\n        public bool Enabled { get; set; }\n\n        [TypeConverter(typeof(AlliesMaskTypeConverter))]\n        public AlliesMask Allies { get; set; }\n\n        [DefaultValue(150)]\n        public int MaxBuilding { get; set; }\n\n        [DefaultValue(150)]\n        public int MaxUnit { get; set; }\n\n        [DefaultValue(\"North\")]\n        public string Edge { get; set; }\n\n        [DefaultValue(0)]\n        public int Credits { get; set; } = 0;\n\n        public House(HouseType type)\n        {\n            Type = type;\n            Allies = new AlliesMask(1 << Type.ID);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/HouseType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MobiusEditor.Model\n{\n    public class HouseType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string UnitTeamColor { get; private set; }\n\n        public string BuildingTeamColor { get; private set; }\n\n        public IDictionary<string, string> OverrideTeamColors { get; private set; }\n\n        public HouseType(sbyte id, string name, string unitTeamColor, string buildingTeamColor, params (string type, string teamColor)[] overrideTeamColors)\n        {\n            ID = id;\n            Name = name;\n            UnitTeamColor = unitTeamColor;\n            BuildingTeamColor = buildingTeamColor;\n            OverrideTeamColors = overrideTeamColors.ToDictionary(x => x.type, x => x.teamColor);\n        }\n\n        public HouseType(sbyte id, string name, string teamColor)\n            : this(id, name, teamColor, teamColor)\n        {\n        }\n\n        public HouseType(sbyte id, string name)\n            : this(id, name, null)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is HouseType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Infantry.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Linq;\nusing System.Numerics;\nusing System.Runtime.CompilerServices;\n\nnamespace MobiusEditor.Model\n{\n    public enum InfantryStoppingType\n    {\n        Center = 0,\n        UpperLeft = 1,\n        UpperRight = 2,\n        LowerLeft = 3,\n        LowerRight = 4\n    }\n\n    public class Infantry : INotifyPropertyChanged, ICloneable\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        public InfantryGroup InfantryGroup { get; set; }\n\n        private InfantryType type;\n        public InfantryType Type { get => type; set => SetField(ref type, value); }\n\n        private HouseType house;\n        public HouseType House { get => house; set => SetField(ref house, value); }\n\n        private int strength;\n        public int Strength { get => strength; set => SetField(ref strength, value); }\n\n        private DirectionType direction;\n        public DirectionType Direction { get => direction; set => SetField(ref direction, value); }\n\n        private string mission;\n        public string Mission { get => mission; set => SetField(ref mission, value); }\n\n        private string trigger = Model.Trigger.None;\n        public string Trigger { get => trigger; set => SetField(ref trigger, value); }\n\n        public Color Tint { get; set; } = Color.White;\n\n        public Infantry(InfantryGroup infantryGroup)\n        {\n            InfantryGroup = infantryGroup;\n        }\n\n        public Infantry Clone()\n        {\n            return new Infantry(InfantryGroup)\n            {\n                Type = Type,\n                House = House,\n                Strength = Strength,\n                Direction = Direction,\n                Trigger = Trigger,\n                Mission = Mission,\n            };\n        }\n    \n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n\n    public class InfantryGroup : ICellOverlapper, ICellOccupier\n    {\n        private static readonly Point[] stoppingLocations = new Point[Globals.NumInfantryStops];\n\n        public Rectangle OverlapBounds => new Rectangle(-1, -1, 3, 3);\n\n        public bool[,] OccupyMask => new bool[1, 1] { { true } };\n\n        public readonly Infantry[] Infantry = new Infantry[Globals.NumInfantryStops];\n\n        static InfantryGroup()\n        {\n            stoppingLocations[(int)InfantryStoppingType.Center] = new Point(Globals.PixelWidth / 2, Globals.PixelHeight / 2);\n            stoppingLocations[(int)InfantryStoppingType.UpperLeft] = new Point(Globals.PixelWidth / 4, Globals.PixelHeight / 4);\n            stoppingLocations[(int)InfantryStoppingType.UpperRight] = new Point(3 * Globals.PixelWidth / 4, Globals.PixelHeight / 4);\n            stoppingLocations[(int)InfantryStoppingType.LowerLeft] = new Point(Globals.PixelWidth / 4, 3 * Globals.PixelHeight / 4);\n            stoppingLocations[(int)InfantryStoppingType.LowerRight] = new Point(3 * Globals.PixelWidth / 4, 3 * Globals.PixelHeight / 4);\n        }\n\n        public static IEnumerable<InfantryStoppingType> ClosestStoppingTypes(Point subPixel)\n        {\n            var stoppingDistances = new (InfantryStoppingType type, float dist)[stoppingLocations.Length];\n            for (int i = 0; i < stoppingDistances.Length; ++i)\n            {\n                stoppingDistances[i] = ((InfantryStoppingType)i, new Vector2(subPixel.X - stoppingLocations[i].X, subPixel.Y - stoppingLocations[i].Y).LengthSquared());\n            }\n            return stoppingDistances.OrderBy(sd => sd.dist).Select(sd => sd.type);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/InfantryType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class InfantryType : ITechnoType, IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName { get; private set; }\n\n        public string OwnerHouse { get; private set; }\n\n        public Size RenderSize { get; set; }\n\n        public Image Thumbnail { get; set; }\n\n        public InfantryType(sbyte id, string name, string textId, string ownerHouse)\n        {\n            ID = id;\n            Name = name;\n            DisplayName = Globals.TheGameTextManager[textId];\n            OwnerHouse = ownerHouse;\n        }\n\n        public InfantryType(sbyte id, string name, string textId)\n            : this(id, name, textId, null)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is InfantryType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(GameType gameType, TheaterType theater, HouseType house, DirectionType direction)\n        {\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, 4, out Tile tile))\n            {\n                RenderSize = new Size(tile.Image.Width / Globals.TileScale, tile.Image.Height / Globals.TileScale);\n            }\n\n            var mockInfantry = new Infantry(null)\n            {\n                Type = this,\n                House = house,\n                Strength = 256,\n                Direction = direction\n            };\n            var infantryThumbnail = new Bitmap(Globals.TileWidth, Globals.TileHeight);\n            using (var g = Graphics.FromImage(infantryThumbnail))\n            {\n                MapRenderer.Render(theater, Point.Empty, Globals.TileSize, mockInfantry, InfantryStoppingType.Center).Item2(g);\n            }\n            Thumbnail = infantryThumbnail;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Map.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Linq;\nusing TGASharpLib;\n\nnamespace MobiusEditor.Model\n{\n    [Flags]\n    public enum MapLayerFlag\n    {\n        None            = 0,\n        Basic           = 1 << 0,\n        Map             = 1 << 1,\n        Template        = 1 << 2,\n        Terrain         = 1 << 3,\n        Resources       = 1 << 4,\n        Walls           = 1 << 5,\n        Overlay         = 1 << 6,\n        Smudge          = 1 << 7,\n        Waypoints       = 1 << 8,\n        CellTriggers    = 1 << 9,\n        Houses          = 1 << 10,\n        Infantry        = 1 << 11,\n        Units           = 1 << 12,\n        Buildings       = 1 << 13,\n        Boundaries      = 1 << 14,\n        TechnoTriggers  = 1 << 15,\n\n        OverlayAll = Resources | Walls | Overlay,\n        Technos = Terrain | Walls | Infantry | Units | Buildings,\n\n        All = int.MaxValue\n    }\n\n    public class MapContext : ITypeDescriptorContext\n    {\n        public IContainer Container { get; private set; }\n\n        public object Instance { get; private set; }\n\n        public PropertyDescriptor PropertyDescriptor { get; private set; }\n\n        public Map Map => Instance as Map;\n\n        public readonly bool FractionalPercentages;\n\n        public MapContext(Map map, bool fractionalPercentages)\n        {\n            Instance = map;\n            FractionalPercentages = fractionalPercentages;\n        }\n\n        public object GetService(Type serviceType) => null;\n\n        public void OnComponentChanged() { }\n\n        public bool OnComponentChanging() => true;\n    }\n\n    public class Map : ICloneable\n    {\n        private int updateCount = 0;\n        private bool updating = false;\n        private IDictionary<MapLayerFlag, ISet<Point>> invalidateLayers = new Dictionary<MapLayerFlag, ISet<Point>>();\n        private bool invalidateOverlappers;\n\n        public readonly BasicSection BasicSection;\n\n        public readonly MapSection MapSection = new MapSection();\n\n        public readonly BriefingSection BriefingSection = new BriefingSection();\n\n        public readonly SteamSection SteamSection = new SteamSection();\n\n        public TheaterType Theater { get => MapSection.Theater; set => MapSection.Theater = value; }\n\n        public Point TopLeft\n        {\n            get => new Point(MapSection.X, MapSection.Y);\n            set { MapSection.X = value.X; MapSection.Y = value.Y; }\n        }\n\n        public Size Size\n        {\n            get => new Size(MapSection.Width, MapSection.Height);\n            set { MapSection.Width = value.Width; MapSection.Height = value.Height; }\n        }\n\n        public Rectangle Bounds\n        {\n            get => new Rectangle(TopLeft, Size);\n            set { MapSection.X = value.Left; MapSection.Y = value.Top; MapSection.Width = value.Width; MapSection.Height = value.Height; }\n        }\n\n        public readonly Type HouseType;\n\n        public readonly HouseType[] HouseTypes;\n\n        public readonly List<TheaterType> TheaterTypes;\n\n        public readonly List<TemplateType> TemplateTypes;\n\n        public readonly List<TerrainType> TerrainTypes;\n\n        public readonly List<OverlayType> OverlayTypes;\n\n        public readonly List<SmudgeType> SmudgeTypes;\n\n        public readonly string[] EventTypes;\n\n        public readonly string[] ActionTypes;\n\n        public readonly string[] MissionTypes;\n\n        public readonly List<DirectionType> DirectionTypes;\n\n        public readonly List<InfantryType> InfantryTypes;\n\n        public readonly List<UnitType> UnitTypes;\n\n        public readonly List<BuildingType> BuildingTypes;\n\n        public readonly string[] TeamMissionTypes;\n\n        public readonly CellMetrics Metrics;\n\n        public readonly CellGrid<Template> Templates;\n\n        public readonly CellGrid<Overlay> Overlay;\n\n        public readonly CellGrid<Smudge> Smudge;\n\n        public readonly OccupierSet<ICellOccupier> Technos;\n\n        public readonly OccupierSet<ICellOccupier> Buildings;\n\n        public readonly OverlapperSet<ICellOverlapper> Overlappers;\n\n        public readonly Waypoint[] Waypoints;\n\n        public readonly CellGrid<CellTrigger> CellTriggers;\n\n        public readonly ObservableCollection<Trigger> Triggers;\n\n        public readonly List<TeamType> TeamTypes;\n\n        public House[] Houses;\n\n        public readonly List<string> MovieTypes;\n\n        public int TiberiumOrGoldValue { get; set; }\n\n        public int GemValue { get; set; }\n\n        public int TotalResources\n        {\n            get\n            {\n                int totalResources = 0;\n                foreach (var (cell, value) in Overlay)\n                {\n                    if (value.Type.IsResource)\n                    {\n                        totalResources += (value.Icon + 1) * (value.Type.IsGem ? GemValue : TiberiumOrGoldValue);\n                    }\n                }\n                return totalResources;\n            }\n        }\n\n        public Map(BasicSection basicSection, TheaterType theater, Size cellSize, Type houseType,\n            IEnumerable<HouseType> houseTypes, IEnumerable<TheaterType> theaterTypes, IEnumerable<TemplateType> templateTypes,\n            IEnumerable<TerrainType> terrainTypes, IEnumerable<OverlayType> overlayTypes, IEnumerable<SmudgeType> smudgeTypes,\n            IEnumerable<string> eventTypes, IEnumerable<string> actionTypes, IEnumerable<string> missionTypes,\n            IEnumerable<DirectionType> directionTypes, IEnumerable<InfantryType> infantryTypes, IEnumerable<UnitType> unitTypes,\n            IEnumerable<BuildingType> buildingTypes, IEnumerable<string> teamMissionTypes, IEnumerable<Waypoint> waypoints,\n            IEnumerable<string> movieTypes)\n        {\n            BasicSection = basicSection;\n\n            HouseType = houseType;\n            HouseTypes = houseTypes.ToArray();\n            TheaterTypes = new List<TheaterType>(theaterTypes);\n            TemplateTypes = new List<TemplateType>(templateTypes);\n            TerrainTypes = new List<TerrainType>(terrainTypes);\n            OverlayTypes = new List<OverlayType>(overlayTypes);\n            SmudgeTypes = new List<SmudgeType>(smudgeTypes);\n            EventTypes = eventTypes.ToArray();\n            ActionTypes = actionTypes.ToArray();\n            MissionTypes = missionTypes.ToArray();\n            DirectionTypes = new List<DirectionType>(directionTypes);\n            InfantryTypes = new List<InfantryType>(infantryTypes);\n            UnitTypes = new List<UnitType>(unitTypes);\n            BuildingTypes = new List<BuildingType>(buildingTypes);\n            TeamMissionTypes = teamMissionTypes.ToArray();\n            MovieTypes = new List<string>(movieTypes);\n\n            Metrics = new CellMetrics(cellSize);\n            Templates = new CellGrid<Template>(Metrics);\n            Overlay = new CellGrid<Overlay>(Metrics);\n            Smudge = new CellGrid<Smudge>(Metrics);\n            Technos = new OccupierSet<ICellOccupier>(Metrics);\n            Buildings = new OccupierSet<ICellOccupier>(Metrics);\n            Overlappers = new OverlapperSet<ICellOverlapper>(Metrics);\n            Triggers = new ObservableCollection<Trigger>();\n            TeamTypes = new List<TeamType>();\n            Houses = HouseTypes.Select(t => { var h = (House)Activator.CreateInstance(HouseType, t); h.SetDefault(); return h; }).ToArray();\n            Waypoints = waypoints.ToArray();\n            CellTriggers = new CellGrid<CellTrigger>(Metrics);\n\n            MapSection.SetDefault();\n            BriefingSection.SetDefault();\n            SteamSection.SetDefault();\n            Templates.Clear();\n            Overlay.Clear();\n            Smudge.Clear();\n            Technos.Clear();\n            Overlappers.Clear();\n            CellTriggers.Clear();\n\n            TopLeft = new Point(1, 1);\n            Size = Metrics.Size - new Size(2, 2);\n            Theater = theater;\n\n            Overlay.CellChanged += Overlay_CellChanged;\n            Technos.OccupierAdded += Technos_OccupierAdded;\n            Technos.OccupierRemoved += Technos_OccupierRemoved;\n            Buildings.OccupierAdded += Buildings_OccupierAdded;\n            Buildings.OccupierRemoved += Buildings_OccupierRemoved;\n            Triggers.CollectionChanged += Triggers_CollectionChanged;\n        }\n\n        public void BeginUpdate()\n        {\n            updateCount++;\n        }\n\n        public void EndUpdate()\n        {\n            if (--updateCount == 0)\n            {\n                Update();\n            }\n        }\n\n        public void InitTheater(GameType gameType)\n        {\n            foreach (var templateType in TemplateTypes)\n            {\n                templateType.Init(Theater);\n            }\n\n            foreach (var smudgeType in SmudgeTypes)\n            {\n                smudgeType.Init(Theater);\n            }\n\n            foreach (var overlayType in OverlayTypes)\n            {\n                overlayType.Init(Theater);\n            }\n\n            foreach (var terrainType in TerrainTypes)\n            {\n                terrainType.Init(Theater);\n            }\n\n            foreach (var infantryType in InfantryTypes)\n            {\n                infantryType.Init(gameType, Theater, HouseTypes.Where(h => h.Equals(infantryType.OwnerHouse)).FirstOrDefault(), DirectionTypes.Where(d => d.Facing == FacingType.South).First());\n            }\n\n            foreach (var unitType in UnitTypes)\n            {\n                unitType.Init(gameType, Theater, HouseTypes.Where(h => h.Equals(unitType.OwnerHouse)).FirstOrDefault(), DirectionTypes.Where(d => d.Facing == FacingType.North).First());\n            }\n\n            foreach (var buildingType in BuildingTypes)\n            {\n                buildingType.Init(gameType, Theater, HouseTypes.Where(h => h.Equals(buildingType.OwnerHouse)).FirstOrDefault(), DirectionTypes.Where(d => d.Facing == FacingType.North).First());\n            }\n        }\n\n        private void Update()\n        {\n            updating = true;\n\n            if (invalidateLayers.TryGetValue(MapLayerFlag.Resources, out ISet<Point> locations))\n            {\n                UpdateResourceOverlays(locations);\n            }\n\n            if (invalidateLayers.TryGetValue(MapLayerFlag.Walls, out locations))\n            {\n                UpdateWallOverlays(locations);\n            }\n\n            if (invalidateOverlappers)\n            {\n                Overlappers.Clear();\n                foreach (var (location, techno) in Technos)\n                {\n                    if (techno is ICellOverlapper)\n                    {\n                        Overlappers.Add(location, techno as ICellOverlapper);\n                    }\n                }\n            }\n\n            invalidateLayers.Clear();\n            invalidateOverlappers = false;\n            updating = false;\n        }\n\n        private void UpdateResourceOverlays(ISet<Point> locations)\n        {\n            var tiberiumCounts = new int[] { 0, 1, 3, 4, 6, 7, 8, 10, 11 };\n            var gemCounts = new int[] { 0, 0, 0, 1, 1, 1, 2, 2, 2 };\n\n            foreach (var (cell, overlay) in Overlay.IntersectsWith(locations).Where(o => o.Value.Type.IsResource))\n            {\n                int count = 0;\n                foreach (var facing in CellMetrics.AdjacentFacings)\n                {\n                    var adjacentTiberium = Overlay.Adjacent(cell, facing);\n                    if (adjacentTiberium?.Type.IsResource ?? false)\n                    {\n                        count++;\n                    }\n                }\n\n                overlay.Icon = overlay.Type.IsGem ? gemCounts[count] : tiberiumCounts[count];\n            }\n        }\n\n        private void UpdateWallOverlays(ISet<Point> locations)\n        {\n            foreach (var (cell, overlay) in Overlay.IntersectsWith(locations).Where(o => o.Value.Type.IsWall))\n            {\n                var northWall = Overlay.Adjacent(cell, FacingType.North);\n                var eastWall = Overlay.Adjacent(cell, FacingType.East);\n                var southWall = Overlay.Adjacent(cell, FacingType.South);\n                var westWall = Overlay.Adjacent(cell, FacingType.West);\n\n                int icon = 0;\n                if (northWall?.Type == overlay.Type)\n                {\n                    icon |= 1;\n                }\n                if (eastWall?.Type == overlay.Type)\n                {\n                    icon |= 2;\n                }\n                if (southWall?.Type == overlay.Type)\n                {\n                    icon |= 4;\n                }\n                if (westWall?.Type == overlay.Type)\n                {\n                    icon |= 8;\n                }\n\n                overlay.Icon = icon;\n            }\n        }\n\n        private void RemoveBibs(Building building)\n        {\n            var bibCells = Smudge.IntersectsWith(building.BibCells).Where(x => (x.Value.Type.Flag & SmudgeTypeFlag.Bib) != SmudgeTypeFlag.None).Select(x => x.Cell).ToArray();\n            foreach (var cell in bibCells)\n            {\n                Smudge[cell] = null;\n            }\n            building.BibCells.Clear();\n        }\n\n        private void AddBibs(Point location, Building building)\n        {\n            if (!building.Type.HasBib)\n            {\n                return;\n            }\n\n            var bib1Type = SmudgeTypes.Where(t => t.Flag == SmudgeTypeFlag.Bib1).FirstOrDefault();\n            var bib2Type = SmudgeTypes.Where(t => t.Flag == SmudgeTypeFlag.Bib2).FirstOrDefault();\n            var bib3Type = SmudgeTypes.Where(t => t.Flag == SmudgeTypeFlag.Bib3).FirstOrDefault();\n\n            SmudgeType bibType = null;\n            switch (building.Type.Size.Width)\n            {\n                case 2:\n                    bibType = bib3Type;\n                    break;\n                case 3:\n                    bibType = bib2Type;\n                    break;\n                case 4:\n                    bibType = bib1Type;\n                    break;\n            }\n            if (bibType != null)\n            {\n                int icon = 0;\n                for (var y = 0; y < bibType.Size.Height; ++y)\n                {\n                    for (var x = 0; x < bibType.Size.Width; ++x, ++icon)\n                    {\n                        if (Metrics.GetCell(new Point(location.X + x, location.Y + building.Type.Size.Height + y - 1), out int subCell))\n                        {\n                            Smudge[subCell] = new Smudge\n                            {\n                                Type = bibType,\n                                Icon = icon,\n                                Data = 0,\n                                Tint = building.Tint\n                            };\n                            building.BibCells.Add(subCell);\n                        }\n                    }\n                }\n            }\n        }\n\n        public Map Clone()\n        {\n            var map = new Map(BasicSection, Theater, Metrics.Size, HouseType,\n                HouseTypes, TheaterTypes, TemplateTypes, TerrainTypes, OverlayTypes, SmudgeTypes,\n                EventTypes, ActionTypes, MissionTypes, DirectionTypes, InfantryTypes, UnitTypes,\n                BuildingTypes, TeamMissionTypes, Waypoints, MovieTypes)\n            {\n                TopLeft = TopLeft,\n                Size = Size\n            };\n\n            map.BeginUpdate();\n\n            MapSection.CopyTo(map.MapSection);\n            BriefingSection.CopyTo(map.BriefingSection);\n            SteamSection.CopyTo(map.SteamSection);\n            Templates.CopyTo(map.Templates);\n            Overlay.CopyTo(map.Overlay);\n            Smudge.CopyTo(map.Smudge);\n            CellTriggers.CopyTo(map.CellTriggers);\n            Array.Copy(Houses, map.Houses, map.Houses.Length);\n\n            foreach (var trigger in Triggers)\n            {\n                map.Triggers.Add(trigger);\n            }\n\n            foreach (var (location, occupier) in Technos)\n            {\n                if (occupier is InfantryGroup infantryGroup)\n                {\n                    var newInfantryGroup = new InfantryGroup();\n                    Array.Copy(infantryGroup.Infantry, newInfantryGroup.Infantry, newInfantryGroup.Infantry.Length);\n                    map.Technos.Add(location, newInfantryGroup);\n                }\n                else if (!(occupier is Building))\n                {\n                    map.Technos.Add(location, occupier);\n                }\n            }\n\n            foreach (var (location, building) in Buildings)\n            {\n                map.Buildings.Add(location, building);\n            }\n\n            map.TeamTypes.AddRange(TeamTypes);\n\n            map.EndUpdate();\n\n            return map;\n        }\n\n        public TGA GeneratePreview(Size previewSize, bool sharpen)\n        {\n            var mapBounds = new Rectangle(\n                Bounds.Left * Globals.OriginalTileWidth,\n                Bounds.Top * Globals.OriginalTileHeight,\n                Bounds.Width * Globals.OriginalTileWidth,\n                Bounds.Height * Globals.OriginalTileHeight\n            );\n            var previewScale = Math.Min(previewSize.Width / (float)mapBounds.Width, previewSize.Height / (float)mapBounds.Height);\n            var scaledSize = new Size((int)(previewSize.Width / previewScale), (int)(previewSize.Height / previewScale));\n\n            using (var fullBitmap = new Bitmap(Metrics.Width * Globals.OriginalTileWidth, Metrics.Height * Globals.OriginalTileHeight))\n            using (var croppedBitmap = new Bitmap(previewSize.Width, previewSize.Height))\n            {\n                var locations = Bounds.Points().ToHashSet();\n                using (var g = Graphics.FromImage(fullBitmap))\n                {\n                    MapRenderer.Render(GameType.None, this, g, locations, MapLayerFlag.Template | MapLayerFlag.Resources, 1);\n                }\n\n                using (var g = Graphics.FromImage(croppedBitmap))\n                {\n                    Matrix transform = new Matrix();\n                    transform.Scale(previewScale, previewScale);\n                    transform.Translate((scaledSize.Width - mapBounds.Width) / 2, (scaledSize.Height - mapBounds.Height) / 2);\n\n                    g.Transform = transform;\n                    g.Clear(Color.Black);\n                    g.DrawImage(fullBitmap, new Rectangle(0, 0, mapBounds.Width, mapBounds.Height), mapBounds, GraphicsUnit.Pixel);\n                }\n\n                fullBitmap.Dispose();\n\n                if (sharpen)\n                {\n                    using (var sharpenedImage = croppedBitmap.Sharpen(1.0f))\n                    {\n                        croppedBitmap.Dispose();\n                        return TGA.FromBitmap(sharpenedImage);\n                    }\n                }\n                else\n                {\n                    return TGA.FromBitmap(croppedBitmap);\n                }\n            }\n        }\n\n        public TGA GenerateMapPreview()\n        {\n            return GeneratePreview(Globals.MapPreviewSize, false);\n        }\n\n        public TGA GenerateWorkshopPreview()\n        {\n            return GeneratePreview(Globals.WorkshopPreviewSize, true);\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        private void Overlay_CellChanged(object sender, CellChangedEventArgs<Overlay> e)\n        {\n            if (e.OldValue?.Type.IsWall ?? false)\n            {\n                Buildings.Remove(e.OldValue);\n            }\n\n            if (e.Value?.Type.IsWall ?? false)\n            {\n                Buildings.Add(e.Location, e.Value);\n            }\n\n            if (updating)\n            {\n                return;\n            }\n\n            foreach (var overlay in new Overlay[] { e.OldValue, e.Value })\n            {\n                if (overlay == null)\n                {\n                    continue;\n                }\n\n                MapLayerFlag layer = MapLayerFlag.None;\n                if (overlay.Type.IsResource)\n                {\n                    layer = MapLayerFlag.Resources;\n                }\n                else if (overlay.Type.IsWall)\n                {\n                    layer = MapLayerFlag.Walls;\n                }\n                else\n                {\n                    continue;\n                }\n\n                if (!invalidateLayers.TryGetValue(layer, out ISet<Point> locations))\n                {\n                    locations = new HashSet<Point>();\n                    invalidateLayers[layer] = locations;\n                }\n\n                locations.UnionWith(Rectangle.Inflate(new Rectangle(e.Location, new Size(1, 1)), 1, 1).Points());\n            }\n\n            if (updateCount == 0)\n            {\n                Update();\n            }\n        }\n\n        private void Technos_OccupierAdded(object sender, OccupierAddedEventArgs<ICellOccupier> e)\n        {\n            if (e.Occupier is ICellOverlapper overlapper)\n            {\n                if (updateCount == 0)\n                {\n                    Overlappers.Add(e.Location, overlapper);\n                }\n                else\n                {\n                    invalidateOverlappers = true;\n                }\n            }\n        }\n\n        private void Technos_OccupierRemoved(object sender, OccupierRemovedEventArgs<ICellOccupier> e)\n        {\n            if (e.Occupier is ICellOverlapper overlapper)\n            {\n                if (updateCount == 0)\n                {\n                    Overlappers.Remove(overlapper);\n                }\n                else\n                {\n                    invalidateOverlappers = true;\n                }\n            }\n        }\n\n        private void Buildings_OccupierAdded(object sender, OccupierAddedEventArgs<ICellOccupier> e)\n        {\n            if (e.Occupier is Building building)\n            {\n                Technos.Add(e.Location, e.Occupier, building.Type.BaseOccupyMask);\n                AddBibs(e.Location, building);\n            }\n            else\n            {\n                Technos.Add(e.Location, e.Occupier);\n            }\n        }\n\n        private void Buildings_OccupierRemoved(object sender, OccupierRemovedEventArgs<ICellOccupier> e)\n        {\n            if (e.Occupier is Building building)\n            {\n                RemoveBibs(building);\n            }\n\n            Technos.Remove(e.Occupier);\n        }\n\n        private void Triggers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)\n        {\n            foreach (var (_, building) in Buildings.OfType<Building>())\n            {\n                if (!string.IsNullOrEmpty(building.Trigger))\n                {\n                    if (Triggers.Where(t => building.Trigger.Equals(t.Name)).FirstOrDefault() == null)\n                    {\n                        building.Trigger = Trigger.None;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/MapSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace MobiusEditor.Model\n{\n    public class TheaterTypeConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\n        {\n            return (context is MapContext) && (sourceType == typeof(string));\n        }\n\n        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)\n        {\n            return (context is MapContext) && (destinationType == typeof(string));\n        }\n\n        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)\n        {\n            if (!(value is TheaterType) || !CanConvertTo(context, destinationType))\n            {\n                return null;\n            }\n\n            return (value as TheaterType)?.Name;\n        }\n\n        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n        {\n            if (!CanConvertFrom(context, value?.GetType()))\n            {\n                return null;\n            }\n\n            var map = (context as MapContext).Map;\n            return map.TheaterTypes.Where(t => t.Equals(value)).FirstOrDefault() ?? map.TheaterTypes.First();\n        }\n    }\n\n    public class MapSection : INotifyPropertyChanged\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private int x;\n        [DefaultValue(0)]\n        public int X { get => x; set => SetField(ref x, value); }\n\n        private int y;\n        [DefaultValue(0)]\n        public int Y { get => y; set => SetField(ref y, value); }\n\n        private int width;\n        [DefaultValue(0)]\n        public int Width { get => width; set => SetField(ref width, value); }\n\n        private int height;\n        [DefaultValue(0)]\n        public int Height { get => height; set => SetField(ref height, value); }\n\n        private TheaterType theater;\n        [TypeConverter(typeof(TheaterTypeConverter))]\n        [DefaultValue(null)]\n        public TheaterType Theater { get => theater; set => SetField(ref theater, value); }\n\n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/OccupierSet.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\n\nnamespace MobiusEditor.Model\n{\n    public class OccupierAddedEventArgs<T> : EventArgs\n    {\n        public readonly int Cell;\n\n        public readonly Point Location;\n\n        public readonly T Occupier;\n\n        public OccupierAddedEventArgs(CellMetrics metrics, int cell, T occupier)\n        {\n            Cell = cell;\n            metrics.GetLocation(cell, out Location);\n            Occupier = occupier;\n        }\n\n        public OccupierAddedEventArgs(CellMetrics metrics, Point location, T occupier)\n        {\n            Location = location;\n            metrics.GetCell(location, out Cell);\n            Occupier = occupier;\n        }\n    }\n\n    public class OccupierRemovedEventArgs<T> : EventArgs\n    {\n        public readonly int Cell;\n\n        public readonly Point Location;\n\n        public readonly T Occupier;\n\n        public OccupierRemovedEventArgs(CellMetrics metrics, int cell, T occupier)\n        {\n            Cell = cell;\n            metrics.GetLocation(cell, out Location);\n            Occupier = occupier;\n        }\n\n        public OccupierRemovedEventArgs(CellMetrics metrics, Point location, T occupier)\n        {\n            Location = location;\n            metrics.GetCell(location, out Cell);\n            Occupier = occupier;\n        }\n    }\n\n    public class OccupierSet<T> : IEnumerable<(Point Location, T Occupier)>, IEnumerable where T : class, ICellOccupier\n    {\n        private readonly CellMetrics metrics;\n        private readonly Dictionary<T, Point> occupiers = new Dictionary<T, Point>();\n        private readonly T[,] occupierCells;\n\n        public T this[Point location] => this[location.X, location.Y];\n\n        public T this[int x, int y] => Contains(x, y) ? occupierCells[y, x] : null;\n\n        public T this[int cell] => metrics.GetLocation(cell, out Point location) ? this[location] : null;\n\n        public Point? this[T occupier] => occupiers.ContainsKey(occupier) ? occupiers[occupier] : default;\n\n        public IEnumerable<T> Occupiers => occupiers.Keys;\n\n        public event EventHandler<OccupierAddedEventArgs<T>> OccupierAdded;\n        public event EventHandler<OccupierRemovedEventArgs<T>> OccupierRemoved;\n        public event EventHandler<EventArgs> Cleared;\n\n        public OccupierSet(CellMetrics metrics)\n        {\n            this.metrics = metrics;\n            occupierCells = new T[metrics.Height, metrics.Width];\n        }\n\n        public bool CanAdd(Point location, T occupier, bool[,] occupyMask)\n        {\n            if ((occupier == null) || Contains(occupier))\n            {\n                return false;\n            }\n\n            var occupyPoints = GetOccupyPoints(location, occupyMask).ToArray();\n            return !occupyPoints.Any(p => !Contains(p) || (this[p] != null));\n        }\n\n        public bool CanAdd(int x, int y, T occupier, bool[,] occupyMask) => CanAdd(new Point(x, y), occupier, occupyMask);\n\n        public bool CanAdd(int cell, T occupier, bool[,] occupyMask) => metrics.GetLocation(cell, out Point location) ? CanAdd(location, occupier, occupyMask) : false;\n\n        public bool CanAdd(Point location, T occupier) => (occupier != null) ? CanAdd(location, occupier, occupier.OccupyMask) : false;\n\n        public bool CanAdd(int x, int y, T occupier) => (occupier != null) ? CanAdd(x, y, occupier, occupier.OccupyMask) : false;\n\n        public bool CanAdd(int cell, T occupier) => (occupier != null) ? CanAdd(cell, occupier, occupier.OccupyMask) : false;\n\n        public bool Add(Point location, T occupier, bool[,] occupyMask)\n        {\n            if (!DoAdd(location, occupier, occupyMask))\n            {\n                return false;\n            }\n\n            OnOccupierAdded(new OccupierAddedEventArgs<T>(metrics, location, occupier));\n            return true;\n        }\n\n        public bool Add(int x, int y, T occupier, bool[,] occupyMask) => Add(new Point(x, y), occupier, occupyMask);\n\n        public bool Add(int cell, T occupier, bool[,] occupyMask) => metrics.GetLocation(cell, out Point location) ? Add(location, occupier, occupyMask) : false;\n\n        public bool Add(Point location, T occupier) => (occupier != null) ? Add(location, occupier, occupier.OccupyMask) : false;\n\n        public bool Add(int x, int y, T occupier) => (occupier != null) ? Add(x, y, occupier, occupier.OccupyMask) : false;\n\n        public bool Add(int cell, T occupier) => (occupier != null) ? Add(cell, occupier, occupier.OccupyMask) : false;\n\n        public void Clear()\n        {\n            occupiers.Clear();\n            Array.Clear(occupierCells, 0, occupierCells.Length);\n            OnCleared();\n        }\n\n        public bool Contains(int x, int y) => ((x >= 0) && (x < occupierCells.GetLength(1)) && (y >= 0) && (y < occupierCells.GetLength(0)));\n\n        public bool Contains(Point location) => Contains(location.X, location.Y);\n\n        public bool Contains(int cell) => metrics.GetLocation(cell, out Point location) ? Contains(location) : false;\n\n        public bool Contains(T occupier) => occupiers.ContainsKey(occupier);\n\n        public IEnumerator<(Point Location, T Occupier)> GetEnumerator() => occupiers.Select(kv => (kv.Value, kv.Key)).GetEnumerator();\n\n        public bool Remove(T occupier)\n        {\n            var oldLocation = this[occupier];\n            if (!DoRemove(occupier))\n            {\n                return false;\n            }\n\n            OnOccupierRemoved(new OccupierRemovedEventArgs<T>(metrics, oldLocation.Value, occupier));\n            return true;\n        }\n\n        public bool Remove(Point location) => Remove(this[location]);\n\n        public bool Remove(int x, int y) => Remove(new Point(x, y));\n\n        public bool Remove(int cell) => metrics.GetLocation(cell, out Point location) ? Remove(location) : false;\n\n        public IEnumerable<(Point Location, U Occupier)> OfType<U>() where U : T => this.Where(i => i.Occupier is U).Select(i => (i.Location, (U)i.Occupier));\n\n        protected virtual void OnOccupierAdded(OccupierAddedEventArgs<T> e)\n        {\n            OccupierAdded?.Invoke(this, e);\n        }\n\n        protected virtual void OnOccupierRemoved(OccupierRemovedEventArgs<T> e)\n        {\n            OccupierRemoved?.Invoke(this, e);\n        }\n\n        protected virtual void OnCleared()\n        {\n            Cleared?.Invoke(this, new EventArgs());\n        }\n\n        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();\n\n        private bool DoAdd(Point location, T occupier, bool[,] occupyMask)\n        {\n            if ((occupier == null) || Contains(occupier))\n            {\n                return false;\n            }\n\n            var occupyPoints = GetOccupyPoints(location, occupyMask).ToArray();\n            if (occupyPoints.Any(p => !Contains(p) || (this[p] != null)))\n            {\n                return false;\n            }\n\n            occupiers[occupier] = location;\n            foreach (var p in occupyPoints)\n            {\n                occupierCells[p.Y, p.X] = occupier;\n            }\n            return true;\n        }\n\n        private bool DoRemove(T occupier)\n        {\n            if ((occupier == null) || !occupiers.TryGetValue(occupier, out Point location))\n            {\n                return false;\n            }\n\n            occupiers.Remove(occupier);\n            for (var y = location.Y; y < metrics.Height; ++y)\n            {\n                for (var x = location.X; x < metrics.Width; ++x)\n                {\n                    if (occupierCells[y, x] == occupier)\n                    {\n                        occupierCells[y, x] = null;\n                    }\n                }\n            }\n            return true;\n        }\n\n        private static IEnumerable<Point> GetOccupyPoints(Point location, bool[,] occupyMask)\n        {\n            for (var y = 0; y < occupyMask.GetLength(0); ++y)\n            {\n                for (var x = 0; x < occupyMask.GetLength(1); ++x)\n                {\n                    if (occupyMask[y, x])\n                    {\n                        yield return location + new Size(x, y);\n                    }\n                }\n            }\n        }\n\n        private static IEnumerable<Point> GetOccupyPoints(Point location, T occupier) => GetOccupyPoints(location, occupier.OccupyMask);\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/OverlapperSet.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\n\nnamespace MobiusEditor.Model\n{\n    public class OverlapperSet<T> : IEnumerable<(Point Location, T Overlapper)>, IEnumerable where T : class, ICellOverlapper\n    {\n        private readonly CellMetrics metrics;\n        private readonly Dictionary<T, Rectangle> overlappers = new Dictionary<T, Rectangle>();\n\n        public Rectangle? this[T overlapper] => Contains(overlapper) ? overlappers[overlapper] : default;\n\n        public IEnumerable<T> Overlappers => overlappers.Keys;\n\n        public OverlapperSet(CellMetrics metrics)\n        {\n            this.metrics = metrics;\n        }\n\n        public bool Add(Point location, T overlapper)\n        {\n            if ((overlapper == null) || Contains(overlapper))\n            {\n                return false;\n            }\n\n            var rectangle = overlapper.OverlapBounds;\n            rectangle.Offset(location);\n            overlappers[overlapper] = rectangle;\n            return true;\n        }\n\n        public bool Add(int x, int y, T occupier) => Add(new Point(x, y), occupier);\n\n        public bool Add(int cell, T overlapper) => metrics.GetLocation(cell, out Point location) ? Add(location, overlapper) : false;\n\n        public void Clear() => overlappers.Clear();\n\n        public bool Contains(T occupier) => overlappers.ContainsKey(occupier);\n\n        public void CopyTo(OverlapperSet<T> other)\n        {\n            foreach (var (Location, Occupier) in this)\n            {\n                other.Add(Location, Occupier);\n            }\n        }\n\n        public IEnumerator<(Point Location, T Overlapper)> GetEnumerator() => overlappers.Select(kv => (kv.Value.Location, kv.Key)).GetEnumerator();\n\n        public bool Remove(T overlapper)\n        {\n            if ((overlapper == null) || !overlappers.TryGetValue(overlapper, out Rectangle overlapRect))\n            {\n                return false;\n            }\n\n            overlappers.Remove(overlapper);\n            return true;\n        }\n\n        public ISet<Point> Overlaps(IEnumerable<Rectangle> rectangles)\n        {\n            var rectangleSet = new HashSet<Rectangle>(rectangles);\n            while (true)\n            {\n                var count = rectangleSet.Count;\n                var overlap = overlappers.Values.Where(x => rectangleSet.Any(y => x.IntersectsWith(y))).ToArray();\n                rectangleSet.UnionWith(overlap);\n                if (rectangleSet.Count == count)\n                {\n                    break;\n                }\n            }\n\n            return rectangleSet.SelectMany(x => x.Points()).ToHashSet();\n        }\n\n        public ISet<Point> Overlaps(Rectangle rectangle) => Overlaps(rectangle.Yield());\n\n        public ISet<Point> Overlaps(IEnumerable<Point> points) => Overlaps(points.Select(p => new Rectangle(p, new Size(1, 1))));\n\n        public ISet<Point> Overlaps(Point point) => Overlaps(point.Yield());\n\n        public IEnumerable<(Point Location, U Overlapper)> OfType<U>() where U : T => this.Where(i => i.Overlapper is U).Select(i => (i.Location, (U)i.Overlapper));\n\n        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Overlay.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class Overlay : ICellOccupier\n    {\n        public OverlayType Type { get; set; }\n\n        public int Icon { get; set; }\n\n        public Size OverlapSize => new Size(1, 1);\n\n        public bool[,] OccupyMask => Type.OccupyMask;\n\n        public Color Tint { get; set; } = Color.White;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/OverlayType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    [Flags]\n    public enum OverlayTypeFlag\n    {\n        None            = 0,\n        TiberiumOrGold  = (1 << 0),\n        Gems            = (1 << 1),\n        Wall            = (1 << 2),\n        Crate           = (1 << 3),\n        Flag            = (1 << 4),\n    }\n\n    public class OverlayType : ICellOccupier, IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName { get; private set; }\n\n        public TheaterType[] Theaters { get; private set; }\n\n        public OverlayTypeFlag Flag { get; private set; }\n\n        public Image Thumbnail { get; set; }\n\n        public bool[,] OccupyMask => new bool[1, 1] { { true } };\n\n        public bool IsResource => (Flag & (OverlayTypeFlag.TiberiumOrGold | OverlayTypeFlag.Gems)) != OverlayTypeFlag.None;\n\n        public bool IsTiberiumOrGold => (Flag & OverlayTypeFlag.TiberiumOrGold) != OverlayTypeFlag.None;\n\n        public bool IsGem => (Flag & OverlayTypeFlag.Gems) != OverlayTypeFlag.None;\n\n        public bool IsWall => (Flag & OverlayTypeFlag.Wall) != OverlayTypeFlag.None;\n\n        public bool IsCrate => (Flag & OverlayTypeFlag.Crate) != OverlayTypeFlag.None;\n\n        public bool IsFlag => (Flag & OverlayTypeFlag.Flag) != OverlayTypeFlag.None;\n\n        public bool IsPlaceable => (Flag & ~OverlayTypeFlag.Crate) == OverlayTypeFlag.None;\n\n        public OverlayType(sbyte id, string name, string textId, TheaterType[] theaters, OverlayTypeFlag flag)\n        {\n            ID = id;\n            Name = name;\n            DisplayName = Globals.TheGameTextManager[textId];\n            Theaters = theaters;\n            Flag = flag;\n        }\n\n        public OverlayType(sbyte id, string name, string textId, OverlayTypeFlag flag)\n            : this(id, name, textId, null, flag)\n        {\n        }\n\n        public OverlayType(sbyte id, string name, string textId, TheaterType[] theaters)\n            : this(id, name, textId, theaters, OverlayTypeFlag.None)\n        {\n        }\n\n        public OverlayType(sbyte id, string name, OverlayTypeFlag flag)\n            : this(id, name, name, null, flag)\n        {\n        }\n\n        public OverlayType(sbyte id, string name, string textId)\n            : this(id, name, textId, null, OverlayTypeFlag.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is OverlayType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(TheaterType theater)\n        {\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, 0, out Tile tile))\n            {\n                Thumbnail = new Bitmap(tile.Image, tile.Image.Width, tile.Image.Height);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Smudge.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class Smudge\n    {\n        public SmudgeType Type { get; set; }\n\n        public int Icon { get; set; }\n\n        public int Data { get; set; }\n\n        public Color Tint { get; set; } = Color.White;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/SmudgeType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    [Flags]\n    public enum SmudgeTypeFlag\n    {\n        None = 0,\n        Bib = 1,\n        Bib1 = 3,\n        Bib2 = 5,\n        Bib3 = 9,\n    }\n\n    public class SmudgeType : IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName => Name;\n\n        public Size Size { get; set; }\n\n        public SmudgeTypeFlag Flag { get; private set; }\n\n        public Size RenderSize { get; set; }\n\n        public Image Thumbnail { get; set; }\n\n        public SmudgeType(sbyte id, string name, Size size, SmudgeTypeFlag flag)\n        {\n            ID = id;\n            Name = name;\n            Size = size;\n            Flag = flag;\n        }\n\n        public SmudgeType(sbyte id, string name, Size size)\n            : this(id, name, size, SmudgeTypeFlag.None)\n        {\n        }\n\n        public SmudgeType(sbyte id, string name)\n            : this(id, name, new Size(1, 1), SmudgeTypeFlag.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is SmudgeType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(TheaterType theater)\n        {\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, 0, out Tile tile))\n            {\n                if ((tile.Image.Width * Globals.TileHeight) > (tile.Image.Height * Globals.TileWidth))\n                {\n                    RenderSize = new Size(\n                        tile.Image.Width * Globals.TileWidth / tile.Image.Width,\n                        tile.Image.Height * Globals.TileWidth / tile.Image.Width\n                    );\n                }\n                else\n                {\n                    RenderSize = new Size(\n                        tile.Image.Width * Globals.TileHeight / tile.Image.Height,\n                        tile.Image.Height * Globals.TileHeight / tile.Image.Height\n                    );\n                }\n                Thumbnail = new Bitmap(tile.Image, tile.Image.Width, tile.Image.Height);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/SteamSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing Steamworks;\nusing System.ComponentModel;\n\nnamespace MobiusEditor.Model\n{\n    public class SteamSection\n    {\n        [DefaultValue(null)]\n        public string Title { get; set; }\n\n        [DefaultValue(null)]\n        public string Description { get; set; }\n\n        [DefaultValue(null)]\n        public string PreviewFile { get; set; }\n\n        [DefaultValue(ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPublic)]\n        public ERemoteStoragePublishedFileVisibility Visibility { get; set; }\n\n        [DefaultValue(typeof(ulong), \"0\")]\n        public ulong PublishedFileId { get; set; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/TeamType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace MobiusEditor.Model\n{\n    public class TeamTypeClass : ICloneable\n    {\n        public ITechnoType Type { get; set; }\n\n        public byte Count { get; set; }\n\n        public TeamTypeClass Clone()\n        {\n            return new TeamTypeClass()\n            {\n                Type = Type,\n                Count = Count\n            };\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n\n    public class TeamTypeMission : ICloneable\n    {\n        public string Mission { get; set; }\n\n        public int Argument { get; set; }\n\n        public TeamTypeMission Clone()\n        {\n            return new TeamTypeMission()\n            {\n                Mission = Mission,\n                Argument = Argument\n            };\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n\n    public class TeamType : INamedType, ICloneable\n    {\n        public static readonly string None = \"None\";\n\n        public string Name { get; set; }\n\n        public HouseType House { get; set; }\n\n        public bool IsRoundAbout { get; set; }\n\n        public bool IsLearning { get; set; }\n\n        public bool IsSuicide { get; set; }\n\n        public bool IsAutocreate { get; set; }\n\n        public bool IsMercenary { get; set; }\n\n        public int RecruitPriority { get; set; }\n\n        public byte MaxAllowed { get; set; }\n\n        public byte InitNum { get; set; }\n\n        public byte Fear { get; set; }\n\n        public bool IsReinforcable { get; set; }\n\n        public bool IsPrebuilt { get; set; }\n\n        public int Origin { get; set; }\n\n        public string Trigger { get; set; } = Model.Trigger.None;\n\n        public List<TeamTypeClass> Classes { get; } = new List<TeamTypeClass>();\n\n        public List<TeamTypeMission> Missions { get; } = new List<TeamTypeMission>();\n\n        public TeamType Clone()\n        {\n            var teamType = new TeamType()\n            {\n                Name = Name,\n                House = House,\n                IsRoundAbout = IsRoundAbout,\n                IsLearning = IsLearning,\n                IsSuicide = IsSuicide,\n                IsAutocreate = IsAutocreate,\n                IsMercenary = IsMercenary,\n                RecruitPriority = RecruitPriority,\n                MaxAllowed = MaxAllowed,\n                InitNum = InitNum,\n                Fear = Fear,\n                IsReinforcable = IsReinforcable,\n                IsPrebuilt = IsPrebuilt,\n                Origin = Origin,\n                Trigger = Trigger\n            };\n\n            teamType.Classes.AddRange(Classes.Select(c => c.Clone()));\n            teamType.Missions.AddRange(Missions.Select(m => m.Clone()));\n\n            return teamType;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is TeamType)\n            {\n                return this == obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return Name.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Template.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class Template : ICellOccupier\n    {\n        public TemplateType Type { get; set; }\n\n        public int Icon { get; set; }\n\n        public Size OverlapSize => new Size(1, 1);\n\n        public bool[,] OccupyMask => new bool[1, 1] { { true } };\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/TemplateType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    [Flags]\n    public enum TemplateTypeFlag\n    {\n        None    = 0,\n        Clear   = (1 << 1),\n        Water   = (1 << 2),\n        OreMine = (1 << 3),\n    }\n\n    public class TemplateType : IBrowsableType\n    {\n        public ushort ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName => Name;\n\n        public int IconWidth { get; private set; }\n\n        public int IconHeight { get; private set; }\n\n        public Size IconSize => new Size(IconWidth, IconHeight);\n\n        public int NumIcons => IconWidth * IconHeight;\n\n        public bool[,] IconMask { get; set; }\n\n        public Image Thumbnail { get; set; }\n\n        public TheaterType[] Theaters { get; private set; }\n\n        public TemplateTypeFlag Flag { get; private set; }\n\n        public TemplateType(ushort id, string name, int iconWidth, int iconHeight, TheaterType[] theaters, TemplateTypeFlag flag)\n        {\n            ID = id;\n            Name = name;\n            IconWidth = iconWidth;\n            IconHeight = iconHeight;\n            Theaters = theaters;\n            Flag = flag;\n        }\n\n        public TemplateType(ushort id, string name, int iconWidth, int iconHeight, TheaterType[] theaters)\n            : this(id, name, iconWidth, iconHeight, theaters, TemplateTypeFlag.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is TemplateType)\n            {\n                return this == obj;\n            }\n            else if (obj is byte)\n            {\n                return ID == (byte)obj;\n            }\n            else if (obj is ushort)\n            {\n                return ID == (ushort)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(TheaterType theater)\n        {\n            var size = new Size(Globals.OriginalTileWidth / 4, Globals.OriginalTileWidth / 4);\n            var iconSize = Math.Max(IconWidth, IconHeight);\n            var thumbnail = new Bitmap(iconSize * size.Width, iconSize * size.Height);\n            var mask = new bool[IconWidth, IconHeight];\n            Array.Clear(mask, 0, mask.Length);\n\n            bool found = false;\n            using (var g = Graphics.FromImage(thumbnail))\n            {\n                g.Clear(Color.Transparent);\n\n                int icon = 0;\n                for (var y = 0; y < IconHeight; ++y)\n                {\n                    for (var x = 0; x < IconWidth; ++x, ++icon)\n                    {\n                        if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, icon, out Tile tile))\n                        {\n                            g.DrawImage(tile.Image, x * size.Width, y * size.Height, size.Width, size.Height);\n                            found = mask[x, y] = true;\n                        }\n                    }\n                }\n            }\n\n            Thumbnail = found ? thumbnail : null;\n            IconMask = mask;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Terrain.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Runtime.CompilerServices;\nusing MobiusEditor.Interface;\n\nnamespace MobiusEditor.Model\n{\n    public class Terrain : ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private TerrainType type;\n        public TerrainType Type { get => type; set => SetField(ref type, value); }\n\n        private int icon;\n        public int Icon { get => icon; set => SetField(ref icon, value); }\n\n        public Rectangle OverlapBounds => Type.OverlapBounds;\n\n        public bool[,] OccupyMask => Type.OccupyMask;\n\n        private string trigger = Model.Trigger.None;\n        public string Trigger { get => trigger; set => SetField(ref trigger, value); }\n\n        public Color Tint { get; set; } = Color.White;\n\n        public Terrain Clone()\n        {\n            return new Terrain()\n            {\n                Type = Type,\n                Icon = Icon,\n                Trigger = Trigger\n            };\n        }\n\n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/TerrainType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public class TerrainType : ICellOverlapper, ICellOccupier, IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName => Name;\n\n        public Rectangle OverlapBounds => new Rectangle(\n            Point.Empty,\n            new Size(((RenderSize.Width + Globals.TileWidth - 1) / Globals.TileWidth), ((RenderSize.Height + Globals.TileHeight - 1) / Globals.TileHeight))\n        );\n\n        public bool[,] OccupyMask { get; private set; }\n\n        public Size Size => new Size(OccupyMask.GetLength(1), OccupyMask.GetLength(0));\n\n        public TheaterType[] Theaters { get; private set; }\n\n        public bool IsTransformable { get; private set; }\n\n        public TemplateTypeFlag TemplateType { get; private set; }\n\n        public Size RenderSize { get; set; }\n\n        public Image Thumbnail { get; set; }\n\n        public TerrainType(sbyte id, string name, TheaterType[] theaters, bool[,] occupyMask, bool isTransformable, TemplateTypeFlag templateType)\n        {\n            ID = id;\n            Name = name;\n            Theaters = theaters;\n            OccupyMask = occupyMask;\n            IsTransformable = isTransformable;\n            TemplateType = templateType;\n        }\n\n        public TerrainType(sbyte id, string name, TheaterType[] theaters, bool[,] occupyMask, bool isTransformable)\n            : this(id, name, theaters, occupyMask, isTransformable, TemplateTypeFlag.None)\n        {\n        }\n\n        public TerrainType(sbyte id, string name, TheaterType[] theaters, bool[,] occupyMask, TemplateTypeFlag templateType)\n            : this(id, name, theaters, occupyMask, false, templateType)\n        {\n        }\n\n        public TerrainType(sbyte id, string name, TheaterType[] theaters, bool[,] occupyMask)\n            : this(id, name, theaters, occupyMask, false, TemplateTypeFlag.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is TerrainType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(TheaterType theater)\n        {\n            string tileName = Name;\n            if ((TemplateType & TemplateTypeFlag.OreMine) != TemplateTypeFlag.None)\n            {\n                tileName = \"OREMINE\";\n            }\n\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, tileName, IsTransformable ? 22 : 0, out Tile tile))\n            {\n                RenderSize = new Size(tile.Image.Width / Globals.TileScale, tile.Image.Height / Globals.TileScale);\n                Thumbnail = new Bitmap(tile.Image, tile.Image.Width / 2, tile.Image.Height / 2);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/TheaterType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\n\nnamespace MobiusEditor.Model\n{\n    public class TheaterType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public IEnumerable<string> Tilesets { get; private set; }\n\n        public TheaterType(sbyte id, string name, IEnumerable<string> tilesets)\n        {\n            ID = id;\n            Name = name;\n            Tilesets = tilesets;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is TheaterType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Trigger.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\n\nnamespace MobiusEditor.Model\n{\n    public enum TriggerPersistantType\n    {\n        Volatile = 0,\n        SemiPersistant = 1,\n        Persistant = 2\n    }\n\n    public enum TriggerMultiStyleType\n    {\n        Only = 0,\n        And = 1,\n        Or = 2,\n        Linked = 3\n    }\n\n    public class TriggerEvent : ICloneable\n    {\n        public static readonly string None = \"None\";\n\n        public string EventType { get; set; }\n\n        public string Team { get; set; }\n\n        public long Data { get; set; }\n\n        public TriggerEvent Clone()\n        {\n            return new TriggerEvent()\n            {\n                EventType = EventType,\n                Team = Team,\n                Data = Data\n            };\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n\n    public class TriggerAction : ICloneable\n    {\n        public static readonly string None = \"None\";\n\n        public string ActionType { get; set; }\n\n        public string Trigger { get; set; }\n\n        public string Team { get; set; }\n\n        public long Data { get; set; }\n\n        public TriggerAction Clone()\n        {\n            return new TriggerAction()\n            {\n                ActionType = ActionType,\n                Trigger = Trigger,\n                Team = Team,\n                Data = Data\n            };\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n\n    public class Trigger : INamedType, ICloneable\n    {\n        public static readonly string None = \"None\";\n\n        public string Name { get; set; }\n\n        public TriggerPersistantType PersistantType { get; set; } = TriggerPersistantType.Volatile;\n\n        public string House { get; set; }\n\n        public TriggerMultiStyleType EventControl { get; set; } = TriggerMultiStyleType.Only;\n\n        public TriggerEvent Event1 { get; private set; } = new TriggerEvent { EventType = TriggerEvent.None };\n\n        public TriggerEvent Event2 { get; private set; } = new TriggerEvent { EventType = TriggerEvent.None };\n\n        public TriggerAction Action1 { get; private set; } = new TriggerAction { ActionType = TriggerEvent.None };\n\n        public TriggerAction Action2 { get; private set; } = new TriggerAction { ActionType = TriggerEvent.None };\n\n        public Trigger Clone()\n        {\n            return new Trigger()\n            {\n                Name = Name,\n                PersistantType = PersistantType,\n                House = House,\n                EventControl = EventControl,\n                Event1 = Event1.Clone(),\n                Event2 = Event2.Clone(),\n                Action1 = Action1.Clone(),\n                Action2 = Action2.Clone()\n            };\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is Trigger)\n            {\n                return this == obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return Name.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/TypeItem.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Model\n{\n    public class TypeItem<T>\n    {\n        public string Name { get; private set; }\n\n        public T Type { get; private set; }\n\n        public TypeItem(string name, T type)\n        {\n            Name = name;\n            Type = type;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Unit.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Runtime.CompilerServices;\n\nnamespace MobiusEditor.Model\n{\n    public class Unit : ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private UnitType type;\n        public UnitType Type { get => type; set => SetField(ref type, value); }\n\n        public Rectangle OverlapBounds => Type.OverlapBounds;\n\n        public bool[,] OccupyMask => Type.OccupyMask;\n\n        private HouseType house;\n        public HouseType House { get => house; set => SetField(ref house, value); }\n\n        private int strength;\n        public int Strength { get => strength; set => SetField(ref strength, value); }\n\n        private DirectionType direction;\n        public DirectionType Direction { get => direction; set => SetField(ref direction, value); }\n\n        private string mission;\n        public string Mission { get => mission; set => SetField(ref mission, value); }\n\n        private string trigger = Model.Trigger.None;\n        public string Trigger { get => trigger; set => SetField(ref trigger, value); }\n\n        public Color Tint { get; set; } = Color.White;\n\n        public Unit Clone()\n        {\n            return new Unit()\n            {\n                Type = Type,\n                House = House,\n                Strength = Strength,\n                Direction = Direction,\n                Mission = Mission,\n                Trigger = Trigger\n            };\n        }\n\n        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(field, value))\n            {\n                return false;\n            }\n            field = value;\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/UnitType.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Drawing;\n\nnamespace MobiusEditor.Model\n{\n    public static class UnitTypeIDMask\n    {\n        public const sbyte Aircraft   = 1 << 5;\n        public const sbyte Vessel     = 1 << 6;\n    }\n\n    public class UnitType : ICellOverlapper, ICellOccupier, ITechnoType, IBrowsableType\n    {\n        public sbyte ID { get; private set; }\n\n        public string Name { get; private set; }\n\n        public string DisplayName { get; private set; }\n\n        public Rectangle OverlapBounds => new Rectangle(-1, -1, 3, 3);\n\n        public bool[,] OccupyMask => new bool[1, 1] { { true } };\n\n        public string OwnerHouse { get; private set; }\n\n        public bool HasTurret { get; private set; }\n\n        public bool IsFixedWing { get; private set; }\n\n        public bool IsUnit => !IsAircraft && !IsVessel;\n\n        public bool IsAircraft => (ID & UnitTypeIDMask.Aircraft) != 0;\n\n        public bool IsVessel => (ID & UnitTypeIDMask.Vessel) != 0;\n\n        public Size RenderSize { get; set; }\n\n        public Image Thumbnail { get; set; }\n\n        public UnitType(sbyte id, string name, string textId, string ownerHouse, bool hasTurret, bool isFixedWing)\n        {\n            ID = id;\n            Name = name;\n            DisplayName = Globals.TheGameTextManager[textId];\n            OwnerHouse = ownerHouse;\n            HasTurret = hasTurret;\n            IsFixedWing = isFixedWing;\n        }\n\n        public UnitType(sbyte id, string name, string textId, string ownerHouse, bool hasTurret)\n            : this(id, name, textId, ownerHouse, hasTurret, false)\n        {\n        }\n\n        public UnitType(sbyte id, string name, string textId)\n            : this(id, name, textId, null, false)\n        {\n        }\n\n        public UnitType(sbyte id, string name, string textId, string ownerHouse)\n            : this(id, name, textId, ownerHouse, false)\n        {\n        }\n\n        public UnitType(sbyte id, string name, string textId, bool hasTurret)\n            : this(id, name, textId, null, hasTurret)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is UnitType)\n            {\n                return this == obj;\n            }\n            else if (obj is sbyte)\n            {\n                return ID == (sbyte)obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return ID.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n\n        public void Init(GameType gameType, TheaterType theater, HouseType house, DirectionType direction)\n        {\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, 0, out Tile tile))\n            {\n                RenderSize = new Size(tile.Image.Width / Globals.TileScale, tile.Image.Height / Globals.TileScale);\n            }\n\n            var mockUnit = new Unit()\n            {\n                Type = this,\n                House = house,\n                Strength = 256,\n                Direction = direction\n            };\n            var unitThumbnail = new Bitmap(Globals.TileWidth * 3, Globals.TileHeight * 3);\n            using (var g = Graphics.FromImage(unitThumbnail))\n            {\n                MapRenderer.Render(gameType, theater, new Point(1, 1), Globals.TileSize, mockUnit).Item2(g);\n            }\n            Thumbnail = unitThumbnail;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Model/Waypoint.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing System;\n\nnamespace MobiusEditor.Model\n{\n    public enum WaypointFlag\n    {\n        None,\n        PlayerStart\n    }\n\n    public class Waypoint : INamedType\n    {\n        public string Name { get; private set; }\n\n        public WaypointFlag Flag { get; private set; }\n\n        public int? Cell { get; set; }\n\n        public Waypoint(string name, WaypointFlag flag)\n        {\n            Name = name;\n            Flag = flag;\n        }\n\n        public Waypoint(string name)\n            : this(name, WaypointFlag.None)\n        {\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj is Waypoint)\n            {\n                return this == obj;\n            }\n            else if (obj is string)\n            {\n                return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);\n            }\n\n            return base.Equals(obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return Name.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Program.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Dialogs;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Globalization;\nusing System.IO;\nusing System.Threading;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor\n{\n    static class Program\n    {\n        /// <summary>\n        /// The main entry point for the application.\n        /// </summary>\n        [STAThread]\n        static void Main()\n        {\n            // Change current culture to en-US\n            if (Thread.CurrentThread.CurrentCulture.Name != \"en-US\")\n            {\n                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(\"en-US\");\n            }\n\n            // Initialize megafiles\n            var runPath = Environment.CurrentDirectory;\n            Globals.TheMegafileManager = new MegafileManager(runPath);\n\n            var megafilesLoaded = true;\n            var megafilePath = Path.Combine(runPath, \"DATA\");\n            megafilesLoaded &= Globals.TheMegafileManager.Load(Path.Combine(megafilePath, \"CONFIG.MEG\"));\n            megafilesLoaded &= Globals.TheMegafileManager.Load(Path.Combine(megafilePath, \"TEXTURES_COMMON_SRGB.MEG\"));\n            megafilesLoaded &= Globals.TheMegafileManager.Load(Path.Combine(megafilePath, \"TEXTURES_RA_SRGB.MEG\"));\n            megafilesLoaded &= Globals.TheMegafileManager.Load(Path.Combine(megafilePath, \"TEXTURES_SRGB.MEG\"));\n            megafilesLoaded &= Globals.TheMegafileManager.Load(Path.Combine(megafilePath, \"TEXTURES_TD_SRGB.MEG\"));\n#if !DEVELOPER\n            if (!megafilesLoaded)\n            {\n                MessageBox.Show(\"Required data is missing or corrupt, please validate your installation.\", \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n                return;\n            }\n#endif\n\n            // Initialize texture, tileset, team color, and game text managers\n            Globals.TheTextureManager = new TextureManager(Globals.TheMegafileManager);\n            Globals.TheTilesetManager = new TilesetManager(Globals.TheMegafileManager, Globals.TheTextureManager, Globals.TilesetsXMLPath, Globals.TexturesPath);\n            Globals.TheTeamColorManager = new TeamColorManager(Globals.TheMegafileManager);\n\n            var cultureName = CultureInfo.CurrentUICulture.Name;\n            var gameTextFilename = string.Format(Globals.GameTextFilenameFormat, cultureName.ToUpper());\n            if (!Globals.TheMegafileManager.Exists(gameTextFilename))\n            {\n                gameTextFilename = string.Format(Globals.GameTextFilenameFormat, \"EN-US\");\n            }\n            Globals.TheGameTextManager = new GameTextManager(Globals.TheMegafileManager, gameTextFilename);\n\n            // Initialize Steam if this is a Steam build\n            if (SteamworksUGC.IsSteamBuild)\n            {\n                if (!SteamworksUGC.Init())\n                {\n#if !DEVELOPER\n                    MessageBox.Show(\"Unable to initialize Steam interface.\", \"Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n                    return;\n#endif\n                }\n            }\n\n            Application.EnableVisualStyles();\n            Application.SetCompatibleTextRenderingDefault(false);\n\n            if (Properties.Settings.Default.ShowInviteWarning)\n            {\n                var inviteMessageBox = new InviteMessageBox();\n                inviteMessageBox.ShowDialog();\n\n                Properties.Settings.Default.ShowInviteWarning = !inviteMessageBox.DontShowAgain;\n                Properties.Settings.Default.Save();\n            }\n\n            Application.Run(new MainForm());\n\n            if (SteamworksUGC.IsSteamBuild)\n            {\n                SteamworksUGC.Shutdown();\n            }\n\n            Globals.TheMegafileManager.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Properties/AssemblyInfo.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following\n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"CnC TDRA Map Editor\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"Electronic Arts Inc.\")]\n[assembly: AssemblyProduct(\"CnC TDRA Map Editor\")]\n[assembly: AssemblyCopyright(\"© 2020 Electronic Arts Inc. All rights reserved.\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible\n// to COM components.  If you need to access a type in this assembly from\n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"397cef00-8930-4ec8-b15f-f7cf7193fb22\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version\n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers\n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "CnCTDRAMapEditor/Properties/Resources.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code was generated by a tool.\n//     Runtime Version:4.0.30319.42000\n//\n//     Changes to this file may cause incorrect behavior and will be lost if\n//     the code is regenerated.\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace MobiusEditor.Properties {\n    using System;\n    \n    \n    /// <summary>\n    ///   A strongly-typed resource class, for looking up localized strings, etc.\n    /// </summary>\n    // This class was auto-generated by the StronglyTypedResourceBuilder\n    // class via a tool like ResGen or Visual Studio.\n    // To add or remove a member, edit your .ResX file then rerun ResGen\n    // with the /str option, or rebuild your VS project.\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"15.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Resources {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Resources() {\n        }\n        \n        /// <summary>\n        ///   Returns the cached ResourceManager instance used by this class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"MobiusEditor.Properties.Resources\", typeof(Resources).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   Overrides the current thread's CurrentUICulture property for all\n        ///   resource lookups using this strongly typed resource class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized resource of type System.Drawing.Bitmap.\n        /// </summary>\n        internal static System.Drawing.Bitmap UI_CustomMissionPreviewDefault {\n            get {\n                object obj = ResourceManager.GetObject(\"UI_CustomMissionPreviewDefault\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Properties/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"UI_CustomMissionPreviewDefault\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        zvHmvsmGvsmKlvGKlrGqDujuaHHzcFHTUGHjQG713pyqbmSKGwfzAW7e8k4taksv7cyv6y3rGKnqQgQw\n        VtQwXFA3VNo0XNE6XNo6WNY2WNU2VLN3qLZ3pK5/pKZnqKKrn22gvLO/onOgsmOwvH2orHWopKm/rKm/\n        om2grLW3rLWvCL3UDKKFys7+qs6e6s7eyraeqva+yo7eoqbukobuorqO4sauitaeytaeipbu4qaO4qb2\n        iubO6pa9Vc1dNc1dTW1765q7ihtaCutbK5o6qhs7Kurbaxrbq+vbKuqay2qbyhtayhuBYPAdmdbq5o7a\n        ls46tNDQXtnQVlbfUlTbXFTXWtbQVo1ajW0V9S0V9c1VDS0VDc3F9U1FdU2lDajV3tja0dDUXtPQUlXX\n        XFXbVF3fVN3QXFHfVFXXVFvfipLiqvrCyrqq2pa6po5aWGNbTUNrXUNbXWN7fVN7HdVtra5vqaxvwagq\n        65trmttgVc1t6BrKkVvZWFjTWFzTVFLTWFpTX1RVn19Vn1dRW1xVV1bTWFDblF3TkN/Y1jowNDI9Oz57\n        8MDBI/vn5vtGxpq7Bxo6+uta2itq60ur6strGstrGypqGipqG8urG0qrGkqR1jTiosrRdV1LSV1rcWNr\n        TiUW7k2pxQ0pJfWwtOL63MqGwuqGYnRdWV9SRZZbUZNTUYNC0DazvCGzojGjoiG9tDa9vCGvqrmgprGw\n        tjGjsjGpoDEpqy61oAGqkAEZK29MK6knqcivT8mrTcqtScyvTiqoTcmvhUqlFdelldakFtfGZVdj6R+b\n        XQXNyyivSyuvTS6sSSmoTS2pSyqpSYISFDWkFNelltWmlNQl5tbEp1ckZlWlFNdmVNbnVTdhulJLa5OK\n        apKKq4uau+p7hjwDQ9XUNTVlCl19I31DE7Vf/Pq3Jy7eLGgYTqvbf/72w//+9wtowJdfQwO++cfX3zzz\n        6nc7Z1caxo60zZyGADTuO9U0daJxdLlldKV14kT39JmJpetzZ54+eOH5hQsPFy48P3fm3hRC/sM39x2/\n        e+jyo0OXXjxw5rn9p+7sO3Fn6uTdmTNPz5wmmzv77OLlRwsXHyIzdezO+JEbE0vXJpZvjB+9PnH06uQK\n        8tdnT96eP/PM5PL1wYNnRw5dnD5+Z/b00xPLV4cWEJufHF5E4aX+g+cGF85NLF85cOaZgxefmz97D+MZ\n        O3xxAog/cmVq6cr40uWplWszx2/Nnrwzd+ru3JlnyDCGE3emT9zcB1u5uf/orQOn7y1ffnT85ndOwq69\n        ePj8/dlTTy2ce3rpynMLZ5+dOXZrdPFSY99sedPQ7MqV197/+KV3f3D+6VeWLj84cOrpmWO3p489NbmM\n        MV+D5+zKnX0rN0aXrvQvnOucPAY0Nw8vtk0cHVzAqG5ApfYdvz22dG1w4Xw/icHp3v0nu6dXhKRh8TFK\n        AnZu9BDWKNfHsIo6cA4+PTMnu6ZPdI0f6xw/CoHsnbswsHCxdw7B/vG9k6eG5i+MLF6CW9fkSufk8b3T\n        p9EUlKln5nTn+PHmgYNAPKx27yxWJIjNmwYXW0ehtSd7Z050ThxtGT4MmrcNHmkfPgprw5IF8fvIoY6J\n        5Z59x3umTzQNLVZ27qvs2FfdjXZmGxCY9y+0jRxpGzrcPrK0d+Z4z8zxrqmVwbkTE4dPjRw83j+3MnRg\n        Zezg8dGDx/tmIWaHuiYW904tdZNyH24fW2wcPIiRYLlQ3zOH1VJR40hx03Bp80hV5/7mkUWsGBogZsMH\n        O6ewjJiv7d1f3bmveXC+d/rw0Bw0Boun/fW9s53jB7snDnaOLXROLPTtPzw4CzU92Dw4W0/+M3V752q7\n        Zyvb9tXu3d88NN8+ilPz5a0TRY1DZU1jRbWDWEPkVQ0UNwzjuhpoJLOQopzqwZxqrC1Gqtsnqjqnarqm\n        q7uwHoL4TVbvna7qxMpprLBhEIgvbOgvbx2r6tqHs8VNQ7k1ezPL29OKWhJz61MQdlV1F9QNFjcNFjb2\n        5dX2FNT1FTb2FzUPYilT2jpS3o5Ox6q7sKaBVqH90cqO0YqOsbI2OlXSMlDQ1A8rhn/LYCHq1veVYFlT\n        P1jciEx/RetQRctwfm1/QV1/EQZT25uLtUVld15Fd27F3ryKvchnVXbkVnXmV/eUNvaVN/VWtPTVdgzW\n        dMB5L9YNpVTSW94Cteitau4pb+wqrMM6oKu4vhvLhbyarrzqzuI6iEp3IZYUDV0FtV3ZFR0ZpVhnNGWW\n        teKwpA7WgaVAaW1nQWV7YVVHYU1nflVbTnlzTkVzcW17eUNXWUNHaUN7aW0HVgNYARTXtlU3d9e27KX1\n        RE1rRT2w3tXcNdDSPdTYMVDX1lvb2gOraempbtxbUd9VUtORW96YU9KQV9ZchBVJVXtmRVNyUV1SXh2W\n        GtkVzYi+CyqasQhIx4KgpBERfSbWByWNGSUtuRUdZY0DVR3DFR2Q0t6COvTYXtrUXdXWiwVHcV17UU1L\n        sbDqlsJKrGOasTiAobXsiqasisbUwlrE0Yn5WNLVJmRVJ2RXJWTXxGdVx2ZUxmbWJOTVpxZiCYKum5FJ\n        LWhML2pMKWqIy66JSq6ISi2PSiuLSCqNSC6JzsCioRrrEiwQUR4Wnx8aXxiWWAoLTSwNTysPTy4Jjc4P\n        icwNTyiJTquKTK4ISyiMTCmNzKjEQiEyoTwktjg4rigsvjgqoTwyrSIyszIyrRJu0Wk1cVl1tA3LW3bo\n        JSGnLiK5PDAmLzSuNCaN9u5ismvicuojUipCkksK6roq2/u27/FWU1OXK7RBfx09QxKA//nlb64+/aix\n        Z9wjrABv/Xc+/ME//vVvaABWAJCCP//7y6sPXm2bXq4dmq8fP9q473Tz9Jn68WM1/Yu1fQdr+w/W9M7V\n        7J2u65up70PYuNg4MF/bs7+qCxHcHCiD4B3RKz7Dtb2zNX2zNT1whs3U9Mw0DC409C9Ud83gFELO6s6p\n        kqbhgob+0paRyk6KN+FW1ztX1T1d2jZe2jFe0TmFhXxJ8yhWdvj4lbQMl7YMFiFKah/FZwkfTnzym4cW\n        6vbOlDYPIfjCqBCxVnRJn976vtmmoQNNQ3M1PdNVHYSz8s7Jio7JGsojM15D0fFsw965ht4DdX2IhSfB\n        nZrOmaq28Yrmoeq28drufWlYaJe0HDh549K9V2aP3+yaON48RGRp6l9opPB8pqaLYmSEiuVtoANBpKJz\n        EqMFBQrr+8ubh8vbxmtAjc7x8raRstYRXGxRQ39BfS8uqrxlpKJ9vLyTIk1EoKhb3TVd0TpW0jhY1DAA\n        ChTUoZHekqbB0ubhkubBosY+VARcMG8AaEFtX1YFMNSRVdmeVdmVVdGVXtqaWtiYnF+fkFtD7+DcmqT8\n        +qS8BkAqubghvbwlq6ozu6orvawtpRhr1ZbM0rbMsraMUqx8m9OLWtKL2tKKmvC2RguxmeWxGWVYCyfk\n        4N1cnVxQk4q4o6AhJa+ePAtb8BnILO0oqB0oqh/IqujMKO0gDFV00qMgeQ3JuXVJ2Yhx6lMKmvBBismo\n        iE4vj0wtC08qCknMDYnPCUvIC0vKD08uik6vjMmoik4vS8ypxfhTCpvjMmuw+o7PqksvbsXVpRY2x6SV\n        RaeVxGfVJOfUJuc2JOVhLd+WXtSalN8Qk16JD09Uahk+qNEZZeGJhfhcRSbT7nN0anlITG5gZGZgZFZw\n        bHZwTGZQFCwjBKvyhNKIxOKg2GxfelQjHZng2Jyg2JzQhIKwxIKw+Dwy5BPykQmKyfKPTAuMzghPyo9M\n        KQxLwtmckNisgMhUn9AEr+BYz6BYz+AEn9Bkv8jUwFi0hjZT/aPS0WZIXA5SbjwzOC43NAEsKAxNyA1J\n        yAmJzw2KyQ6MyQqMzgyIzkAKt8CoDO+QJO+QRN/wZN+IJJ+wBL/wtIDITP+wDJ/QFO+QZO/gFJhXcLJX\n        UJJXYKJnQDzMKzDBMzDJwz/BMwBVUv3CU33DUwNwsTE53oFpngEp/uGZQdG5gbFZPmHJPnQKV5TpFZzi\n        EZToFZKCpjxh/gkB4Wke/nG7/WM9AxPcfWN3+0a7eYe5eUXs9o/bExC3xz/eMzjRMyh+j3+cFyoGJ+7y\n        idi002+Dm+82j+A9gXE+oUnemJCgeFTc6R3h7hflHZIQGJUWGJkWEJbiFRjrERgTkZAXk1wcjmmJTvcP\n        T/YPofu9fiGJPsGJHv4xaNDNM8LdJ3K3b9Qub1i4m1ewm2fITp+wXX4Ru3yid/nGuPvG7PGL8fCP3RMY\n        j6Hu8o10847c6R3l5hW10ycKnbr5RO3yjXbHgHFRocleIcleYcmeoQkedIs43iMoAReCRvgeMqqgR1xj\n        yFaPoK3ugdt2B2/3CNnhEbzTM2ynR/iO3SHbdwdt3x220yt6t28cbBffg3XziHLzjN7lFe22J2zTzoAN\n        O/zWb/Vev8Vr3RaP9Tt8tuwM2LY7ZOuu4M1ufpt2eG3c4bthu8/6bd5IN+703ejmC7d1W7027QrYvid0\n        y66gjTv8Nu8K2LwnePOuwI3bvNdv9Vy/zWfjdt9NKN8ZuGVn8KZdQZvcg3bsCdu5J3zrzqBN4pRb0Jbd\n        IVt2BW52C9ziHrR1VxA8N7uFrN3ku9k9BNJY3NixYasb6K/Q0hH0lwTgpz//5a0Hr+xfOReXA0xUHD9/\n        /cHLb/72D3+GBkAAsA749Wd/P3n7QdXA/ty2kdK++YapU037TpX3HMhtGMxr6EesEZsFHcuPSM6LTM2P\n        Ti2ISoMVxqQXxWQUx2ZDmspiMqGExSiMTi+OSS+OTiuiNL0kNqMEhZGpRVGpxRHJBeFJueGJOeFJechH\n        pRVFpRdFp8GZqsSQZxHajyIriEwDKUpiM8mi0wtjs0oScsrjYdkV9GxZFp/ifmMyitA1MnEZpfFZQFgp\n        KqLlSIwztTA6tTA2s5jGhjGgRzinl4rRRmJgKfj8A0y5Ecm5sWklKbm1wXEZO71RVtc0cKCmcyKloB6t\n        YWwxGaWxmbjScmSi0VQKGi+KTi2OwfjpektwGJFaEJFCg0en3F0h5oGegUtGR4WRaQViHqhKWmF4Sh4K\n        MUKk4Sn5YaBkXFZoQnZoAliZExyXGRiTERKfFZaQjTQ4jnAWGAM0pPhHJPtHJvtFJPmGJ2Kk3mFxXiGx\n        XkGxXgExPiFxPuGJvgSRRJhPWDwO4UnGJb5hKEyA+YahOtiR6BUaT9WD8VlFI/icx3kFo8E4fLDJQuIB\n        O4/AaLYo5PFp9wqO9wiI2e0Xuds/ao9flLt3xE6v0B1eITu8Qnd6r1oIUjfvkG0egds9gpAR5W4+ITu8\n        g7d7BuMTuMsnzN030t0fH/7IXT7h+MyTD1KvkO2otQeflqAdnsHb9wRvx6d0D5oK2rYnYNueID4VuMMz\n        yM0zCB9d5Lfv9ke6dbf/lp1+W3chpczmnX5It+BwFz5vOPTd5Oa1aYcnfUTdvDfs8Ny4w2vLLl8q3+69\n        cZvXhm2eG7Z7bSTz3kCHXhvchKcXnDe5ecPgALeN2/Zs2Lpn3ZY967d6oBHY+m34DHts3O5Jxk2t3+7J\n        FXHWkw63eazftmfd1t3rtsA8CBzcwrpN7ms3urlu2rF2k9vaTbtcN+2Cj+uW3a6bd+Fw7eadaza6uazf\n        sWbDdrit2YAM5V02bHPZsN15/TYX1y1OrludkK7Z7Lh2m5PrdifXbY5rtziu2eKwZjPMzmmTvfMGBxfK\n        2ztvtHPc4OC80cF5k53zRgtbl10e/oGhMbaOG60d1uOsrdN6tnW2juttHTfYOW1AIarbu2ywX7PJYc0m\n        W8d15taOpuYOFtZONg7r0Ii9M9pHutHOeQMqWtu7Wtm52ji42jq4Wtm42Dtvdlm/03HNNtS1d9no4EJu\n        MBxSntpH4xthaMrWCS3QWTunjbbOG2wc16ELG0dXmJ0TDY96cUI5lcBsHdfaUrrOzgm2HrXIBy04oaNN\n        uEaMDRfuiAvnkVs7SP7UrMM6jBa1KHVG4xgSVbdB+w587bgcHDquxzBEyw4YFc7SINfjAq3s1ljZrrGy\n        Wwuztl9Lo2VnG3tMwnprSlGCuhvQmnSITh3XW2Mk9pgiDBh9rUM7qC6Zg6s1jW09ZeCDBkV3MLwifMrG\n        XgyPZhLtG5s7OK/bllVWW1jX7OS6UU1NQ6mtt0p/SQB+/stfP/3otYPnbha2jEIo5lZOH7t0486Lr/3q\n        93/8L2vAV99885NP/3To6v3y4QPpLSP5PQcqRlcqho6U9s5V9M1V9x+o6J4qaR8qbhsobOopaOwqqO/K\n        r+vMr23PrWkjq4a15la15Fa2Uqa6lW+etOVUtORUtmRXtWRXNmeXN+VUNedWteZUteRUNOEwu7wxt6IJ\n        hkMuacwpb8yuaMiubMqras2racuvbc2vQcjZXlDTml+Nw/a82ja0QI3XttNhNe3fUb9V1Ht2JXUHQ3lu\n        NXfKLWdVYdHXnCXdXGrILG3MKG3IKKnLKKnPKK5JK6pMLaxKK65BCdxSCipD4tMhOdUdgy39ExmldaB/\n        XHYpVCchtzIxtzoprzopvzo5vzqlgK2wJqWoNrW4Pg0RdyndEUImtag+pbAutRCryHrkUwvrUgprkwtr\n        kwprqbwAp6gkpQB1a5ILa5IKEHRXJeYihK+ExedUxGVXxGVVJuTAKuJyKmKzy2OzSiG3UDXSkhRIaV4Y\n        pBTqlYgwMzM0ISs8KQcKHZGMoJXkGZ5QWQhbBMlbfkRSXnhiLpxRSwheWFJOSCKpSygMwhOfDdUhi+eU\n        AliyoJiMgKjUgGhEkSmIdpH3g/yEJ/mFJfuGJvmEJnoH09N4pB8QhkBEjjEeQYi8UBLtERC9x58NmUAy\n        uCFPykFnoygfEIVDd5ITMsR97r4RiARZEsJ3+UrC4OYdCtmAHgjbDu57BK3att1B29whAAFbdvtTivBq\n        J5F9805/Nt9NyLMMbHLzAdORbtrhs9nNB6cI9xLxwWiiP0BPMoASlO/gszu8WQm8GfTAPYwIzilozmKw\n        bff6Le7rSRXocAMEYDucRTkxndG/x5XMnRC/xV0Qf+3G3a6bdq/d7I7UdTOVu24h9K/duHPthl1rNu50\n        2bjDZYMbHW7C4a41G3auWe/msmGH07rtzmTbnNZvdUKK/PrtyDi6bnVw3cJg3Qyzc9lk57LBDpBFSvwF\n        OzaBZSZWjlt3emfll2x18zS3cQFimD4ELEbPesmZMkIYyAAyIN6K8cS83kTaAIFBX+Cs8wYQzcLGwdTC\n        DjFvQHTelt2B4BTIS625gKrUrCA+gd5R9EKCJDolGRADELwD6x0Ir6J3G6d1bAREdmZ/ztAFrhEXKC4W\n        V01jc1y71X7tFhsntI8GWdtEOywDVCgRliUHza4a9Y5TaJ9mjLWHHDA80SPLJBkmjcqldkBq4cMyxlPH\n        rfFFkQ6hX9fVFjAGoZrWMKETKKdaaIFEiExqATO/Vsw8DPptYGK9fqt7eXNXUV2rpY29mpqalo7+k/SX\n        BOCTX/7mmRdeP3D6eknnVH793rnjF49ff/rMnQd3X3rjp7/6zefffA0BgAx8/5e/O3r7hfaFsw0zJ+r3\n        n6qeOF49drR2YqVh37GWmZW2/Sst+1eap5dbpo607DvcPHGwZWy+ZfRAy8hs88hMy9B048AkrGlwX9Pg\n        VPPAPlhjPw6nmgammwammob2NQ/NIN9APpNNA+w2PN08AJtqHJiAc/PgRDP84Tm8v3VktnV0pn1ktm10\n        tn1srmN0rmPsQMfEXPvEfMf4fMfEAZHpnFjomoQhM981xXkqoXzn5MGOiYWOifn2sYXO0QVUbx3Z3zo8\n        2zI00zgw1dA/Wd87Xtc7VtczXrcX6WhtzzBKqjtHsyoakgvKUdI3fbi6azS/riu/vrOoobu4saeksbe0\n        ua+8fbi8AzZU0TlY2TlMh51DFV3DlZ2jVV1jVV2jlZ0jFXBoHyprHyK3dtggrJytrK2/pKW/rI3ypbDW\n        gZKWvmJYc39xS39p2wDS4ubeosaewsa9hQ17ixooJdGt7cyv6cyp7siuasuCsla2ZJXDWrPKWjKRqWzN\n        rmhFSSZKKluzqpAi35xe1khW2phW0gChSi2uSy2BUSaZhScB2pMH1eEFFiyXvrzDix4sy2jxRJlMLJ6w\n        iIH25EekYM2UA80ISciCWgTFZbBlBsVmBMSmB0anB8akB0Sn+UVgmYLFSgpbql9Eil84lCOZ9jrCk7yx\n        EAmN9xHrjNAEWnOEYC2CBQeUIwY6wRbDyhFDFhBJwkBGwgCDJPCyg2y7JxYNUAKsLZAP3ro7aIt7gLCt\n        MEiCuz8ySDe7+0unsFxwZ0nY6bMJ2uAGgyRAM2itgPwmN6wYSDnoLLlhLe+zcQf0g4yEAQG+JB6I8ZEX\n        RtwnFdnhhQUHrQ/cUOKxDusDXnOItcI6iAd0goxUASWQn3VYItApD9etEAmxDoBIsE5AGNigE0IGXLAy\n        2IDFgZvz+h3OGzhdTzqBFErguG67w9qtYB9Sti3CgELJ1mwyt3UBieob28oq6yxs15jZuIA1ALE9h8yP\n        DRhlkq6mxG7Gqx2iZnAfCw6Y61acBayt7F30jExxqqR5pLJzfod3FOJZsEw0S7H/WthmHg/0CVJE7BZn\n        uVk0zvIg0lUT5eTJYxDrBkqlEYoVjz21LBrfhtQRayOI4nrMBhRRjJxaA5ph6I6WJtS1kEmcfWIAgP7q\n        oVSiyqNcGi07iFMkY9yF5CnOqlqG6JKxMEBRRKHLRhuIBIX861SyQYstXIVon6Z3DY2cliOkvmutWQNM\n        rRwNzWx3+QQ39Y4W1TabmFuC/gqltpa2rpaOnrauvrauwWMBeOGN9y/efTCyeCyrpjezsnNi+fzJWw8v\n        3H/x4v0Xbz187aOf/fLvX30FDfj319988Mlvr7707srTLy7dejR/5bnh4zebZk9XTx5tmDneNHuyafYE\n        2f4TLXMn2maPt82utO8/1r7/aPvMcvfM0sD8sb4DK72w2WO9s0f75o/2HVjumyUbOLCCs/3zxwYPHENm\n        8OCxocXjI4snRw6dGT18dvTwmZHDZ8aPnJtYPjexdH58+cz40fNTRy9MrpyfPHZh8ujFqWOXZk5emTlx\n        Zebk1dnT12dP3Zg7fWP/2RszZ67Pwk5dmz11fe7UjfnTN5DZf+oaOZ+8PHvq6sypq9Mnr+w/fnX/iSvT\n        Jy5PHbswtXJh4ui58eVz40tnhw+fGlo8NXzw9NDCiaGF40MHjw8ePN6zf7mhd7Ksra917AAKu/cdah6e\n        axzcX98H6Zqu75+u65us74d6zTQOztQPTNf176vtnarumajpnazvm6rv2wcfONf27qvtmarpmazpEXcC\n        J6uR0rM6E1XdY7DKjrGqzvGKjtHy9hEyCEYnPjBjlTjVNYYMdKWsbQhGOtFGdwuLm/qKGmG9hfU9BXWk\n        Cvl13aRPdd15tZAHslxWiJzqdhjrBIlBRnkzPalWLhYoTVipQBLSShuhByn5tUn5NZAB2ltjo22uTKw2\n        YCWxSGkrDzJQAotKwxKkKDK1MCKlAEY7V8l5oUnZoYk5oZAELCnEqiIhOyg2U8iAf3RaQIyQBN4ohxJE\n        QglSfMKSfMKTcOgbkexDG1OJUAUShpBE2roNhhIkeARiSRG7OwD0j6HFgW/ETp+InUi9sSYIc/MOI/rz\n        btJ22jUK2bYnmLaJPIIgAJt3Bm7aGbBlJ+iPlUEQbwT5b0bKSkCF7oFU6B6wGUbPbpPxKoHcNu702+gG\n        ow3cjbyAgE5s2EG2cYcvZGDDdpg35SU31gYyrBW8aM1BJbyDxEsHLqcUIsEaIOhPAgDcg/u0XNjuuW6b\n        JwSATKwVoAS0JkBeWmdQOSsBLQVIBrAgQMYNCwWsDFw27HKGrXdzgh6s2+Hout2BdoSwJkAqyQCYCEkA\n        8ixsnJS6hnmFZQcXl32CItdsct/q7o+FBbkBOuApqrhupfWECvFYWCDlklVRgcxsc1q7He0jWreyczIy\n        tTQ0tcopqdt35EJ6UdvaLV6Ic4Fm9PuEoToAzY2s2UomtUb9MvVUUGaqEuKZ1BgYVyG1cESbdEg6R21S\n        SqsfpE7rcPm0GAL6cUU0IXRKqkhKwMrx5OVwit55AJIJbZC6fqKQD3l19dhf0iEwHcMWniS0dmu24JAD\n        +U20CgH6pbgeTOdyRPdYE9DGDvJCP1g2WEtUXfDSyn6tiaWdroGZnoEF5jyzuGZ0frmkrsXYzBz0V2rr\n        KrS0ZHKFXK7Q0tXT1jOEEii1dHX0DNSWrtzvn13OqWwMSytKKmzomlk+dOXeyTsPLtx/6dL9l68//+ob\n        P/zZH//9OTTg71989d7Pfn3njffuvP7eg+9+dP/dD66/9NbFB29cfPjG+edfP/vg1XMPX7/24tu3X33/\n        mbc+fPad7z967wcP3vn+zRffufborTuvvP/0K+/ffvm7T33n3RuP3r7xwls3X3j7xqM3bjx68+YLb974\n        zps3X3zzqRffufXiu0+99O6tl96F552X37vz6vt3X/vgmdc/uv/GR/df/+jea5x586NnOb2HzFvff/at\n        H9x/6/v33/z+PdgbSHH4A85/dO+ND59+/cOnX/ne3de+d/eV9+688h4N4KV30P6tl757AwP7DkbyNoZ3\n        9dEbVx++fvXB69ceIvMGMpeff+3Ss2QX779y4f4r5595+fTd75y6/ejEjeeXr9w7duO507cfHb/54Oi1\n        Z49cfmb+3N3pkzfHV64MHzk/sHhu6ND5ocPnBw+dQ35w8ezAwbODi2eGD0unhg9dGFqkkoHF03z2TN/8\n        qZ4DJ3tmT/bMnUC6d/+x7umVvdPHuqaXO/cttU8e6ZhaRr5j8nD7xGL75KGOiUNtowdbRuabh+ebhuYa\n        B2Yb+mZqe6ehJdWd41Udo5VdoxWdo1hGQBVIAGq68mo7c6s7OPZvyShrQuxP6C9rTCmuT6Ynz+qS8qvj\n        cyvjs6UtppjMsqj0koiUovCkgrBkstDEvJB4unMYGJMZGJsZFJ0RxJnAmIyAmEzkCeJRab6gNiAemULf\n        zo9MAcdBc28Y3RJM8gpN8giKp1uIAbG7/aN3+4PdZDjc5Ru10ycS5uaN+D1il1/ULr/oXT5c6BvpRuV0\n        artn6A6PsO2eYds9QhHRczgfRDfNdgUQpvkm5EY3ZPw3Ab5AKkHWZ/12r3XbvFy3eLpu8XLd6uW6yWPN\n        BlByz9otHkxPlHuu3Qy8CvNat8WbPLd4raVyD5dN7mx7XDbucd7gDoy6bBCH7s7g7Ab3NZt2M1vdndfv\n        clq3U5jD2h12Lttsnbeumh2lW2DIOACLrjuc1u90AoCA43U7HNZtg9kTf4EGRHmU2rhstnEGNbbYstm5\n        bKW80yYUWjtvsXHaLJnjJhvHzbZOOEWpteNmK4cN1rRxQeU28EfquMXGYbOV/Xor+3VW9hss7TZY2rpa\n        2Lpa2rla2q6l1N7VymG9vQuCSrg5K7QNbBzXTuybHZmYS0gvDIvNxJWaWrmYWbmYWDqZWTmbW7vg0NTK\n        2czayczaGZlvmSWZtT34jjFvsLB11EW8qS73C4mZWTiWnlNpYbvByMzBxMLRxMLBxBwZB1NLJ5ixhaMx\n        SiydbJy3rt3iZ++yw9TS0cTS3sTKiZ2RpypGZvZYSxia2huhriX5G1s6oCKbvamFI5oys3o8MBqwlQvG\n        bGGzhkfubGrjbE75NXAzhVHX9sbmZOgCcTRfHczJGEZjcKKuyQ1GvcB4PFROw0ZdjIoNhyYWTkZUSJdj\n        ZI5x0lBhfIGOnHEws3Yxt3U15zUW8ny4FmaBlEpwCY40ZpTYraGlmDVdCA3VzMHA2EbPwErXwMrAxNbE\n        wt4Sr9bGrTFJGWMHlo5cvJlTXm9m7ajQMtI3NFMotTQ0ZGrqGgotbWNzK0MTC0iCTK4FGVBbufawtG3I\n        NzI+MD4Na/+WkQMzp28cvvrMqbuPrjx47eKzr1598NrbH//sT/wN4c/+/cVPP/3Dx7/9/S/+8OdPP/vr\n        Z//69+dffvX3L77807//8/t//PtP//z8H198jbXCv//7zedf08bRf7755h9fffPZl9/85T/f/PWLb/76\n        Jdkf/vX1b/7+5af/+OqP//4G9rt/ff3pP2H//fQfX3/6D0p/R/bf3/3zv5zSKWT4FOwr2G///tVv/wb7\n        8td/+/JXf/3yl5/9B/aLz/7zyZ//8z9/+fynf/rPx3/494//+K8f/eHfP/jdv7//6b++/7t/fvjpPz/8\n        7T8/IPvHh7/9x/u//ud3f/WP7/7qr+/+8q/vfPLZ2598hvTdX5C9/YvP3vnFX97+5C+v//zPr/3sj6/9\n        5A8vf/z77/zwdy98/1O23z34/m8ffPTrhx99+vwHv3n4wa8ffvir5773q2fe/cXTb//P7Td+8tTr9BNJ\n        t9748e3Xf/zUaz+++foPn3rtR7de/+GNV394/ZUfPvX6j2698SMU3nj1B2Sv/fAG8q99//qrH11/+cMb\n        L3947SUYlPWDGy99cO3F71176f2rL7137cX3r37nu1deePfKo+9efvTu5UdvX3zw1oXnXj93/7Wz9147\n        d++VM8+8dObpF888/Z0TkKhbD0/efnj85vPHrj179Mozhy/cWjx3c+HM1XnYqSuwAycuzR2/MHfs4v6j\n        F/Ytn508cnry8OmxgydGDx4fXTg+OHe0f/9S7/ThvfsW904t8qbZwc7xhZaR/c2D9FR+Q/9kTddoVftg\n        eWt/RVtfZXt/eQuWHRAYuteSQzdUGrJKYfXIZJc3ZJfVZxTXZRTVZhXVZhbXphdWC0stqEwrrM4orEkv\n        rMkoQlqdjhLJqlBChZxKZ2FFsCquCJ8KWHphJQ5T8itTciuSc8qTcsqT88pT8ipS8iuS8suT85EvT86t\n        SMopTcotS8ouTcriNLskIas4PgtpSWJ2SVJOWWJOKQxuiVmwEuQTskoTMkson1WckFFEP1+TURyXlh+T\n        mhuTlheXURSXXhibli9ZegGVp+RGp+RFJ+cKC0/IDIxM8gtP8Kd77An+EYn+WMeE0u5WYERiWGx6eHxm\n        ZEJ2ZGJ2WEJGaFxaaHxqUExyUHRycExKSExycCzySQGRCXAODE/k6vH+obE+bL6hsd7B0Z4BUXv8I/b4\n        Ruzxi9jtF77bN2ynZ6gb3QgJ3O7hv8MrwM0rcMfjHbDg7Xuw1vHZCtvtt9Xdd8tO7827vJFuRerus2WX\n        99pNuxBdWtOGsrOxubWahjIzr+zs5Zu9o/vjM0q27QncsG3PDs8A37B478BItIClz+ad3mhz805U991M\n        GbTpw8367PAIROPO6yBL60yt7HRNzDds29XYMdjRN4Ghrt20Y5Ob5yZUp7pUfYs7WvDevNNzyy4vNO4d\n        khyRWu4TmrQNQ93ljXQbhr3bDymP1ouqu3ludvPettt3u7giKvfZ5i7y7L+Hqmzd7b8dPnv8aFo8A9w8\n        AlFlqztGGLDDw1/kaQzuuBaM32uzu/fW3b7bPPwxY6iFPA2PHHy3IC/GucsT3fHFcjmmYofX5h0Yj9eW\n        Hd5bcVHuuBbvzdux5sP0omWaH7TP7eAl8N7u4efuF+YRHO0RFOURJNIIz5AYzxDkIzxhwZGewVFeodHe\n        oVj4RnsEhu/xC3P3CXXzwkLWB1fn7h0cEB6fnFNSWFlf27Z3cGZh6dzVc7fvg/5WjuvN7FxtXTbrGZpq\n        qGtoaGhq6+hZ2jnauaw1s7LRNzTWMzIxNrNQO/PUIwhAQGxSeGpOZmVj4+D09Ikry9efPXbr4dn7L994\n        4c27r7177+0P3//k079/9V9owN8+/+IXf/jLb//8V8D9//nva+n//49/kITPv/nmn2iEU7S2ajgFE3m0\n        vGrw/zcb/GH/wEKEq/+V08+++eYvX5H98ctvfvfFN59+8c2v/vXNJ3//+md/++onf/vqx5/99wd/+uLD\n        P/zngz98/sHvP3//d5+/97t/v/e7f70P+/Tf7/3mX+/9Vtg/3/3NP9/99T/fFYe/+dd3f/PPd379D9i7\n        nL75y7+98clfX/vks1d//tlrP6eMMCgE7A3YJ3968xd/eQvi8UvoB8Tjz2/9/M9v/+LPb33yp7eQ/+TP\n        b8J+zvlf/OVNKvyT6vDPVOWXf0Eetd7+BZ1CIZf/5d1fwT5T2V/e+fVnsHdhv0H5n9/55Z/ehqHKL/4I\n        e5vsD0jfIfvDmz///Zv/8+k7P//t27D/YfvZb9766a9hb//s12/+7Ndv/ORXb3z8yzd+8svXfvKLV3/4\n        81d++D+v/ujnr/zo5y99/2ff+einjz748cMPfvzow4+RPnj/h8+++9G9tz545s0Pnv3uR8jfffN7WAXe\n        evWd26++8/Qb7z395nu3X3v3xktvXn3htcsPXr747IsXnn3x/LPfufDsCxefe/HCcy9egj3/0sVnX7r8\n        /EuXH7x0he3y8y9fev7lKw9evvrolSsPX7768JVrL7x27YVXrz569SoOKX312qPXrj16FYXXHr1y7eEr\n        11947fqjV7n6y1cecZVHryC9ikO0/DyXi/Yfvgyjvh6i8VcuPXiR7PmXLj33nYs0KhoYDeZ5Hu39Rxfu\n        vXCBBvydC/dfgJ2/9+j8vYfn7j5/7u6Dc888OHPnudN3nj99+9nTt+8jc+6ZF8/cfXj8xtMnbj5z4vrT\n        x67fXbl+98SNZ45ff/r49Tsr126vXL21cu0Oyo8hvXZn5eqd5au3j169jXT5yi3Y0uWnli49deTSTcpc\n        vnX4wvVD568dunh98dy1g2dhVxdOXz5w6tLcifOzJ87tP34eNnP8/L6jZ/YtnZo8cnJi6dTEYQj2ysjC\n        0aG5pf7ZI337D/VML+6dXOgcm2sbnm4ZnGzun2zqn2rsm6jvGa3dO1rTPVzTNVTVMVDR2lve2lPeRt8D\n        KGvqLm3qLmtG2lXc0FlQ0wolw2rJysHVwgYhuY2+iSWka/nc1YvPPGoZnitp2ts8MD66eAzThcvpnz3c\n        t/9g/+yh/v2H+mcWhw8sjRw8OrywDBuaPzJx5Pjo4nJ6UfmaTVuNLGxtnFxT84pnjpyYOnKypGVvVUdv\n        59i+7qm5vZNzvZMH+qmdxcHZxYH9iwOUOYTM6MLR8cMnRuaXB3A4dxjtD83Rd0GG55eGDxwZOnBkcO4I\n        PFEysrCM2RhdWB6ZXxo6QIfDC0two5KFo6MHkS7B0ODoQbZFUbg8toiKR+HGDR6WbG6R2pxfQtdoBB1R\n        nrrj3vcfGkaG3JAuDc5iDMhjEhYHZjD+Q337F/v2zfdPL+KiBqYXBpDuR4NHRg5wL3NUHdciBsADO8Kj\n        Wh45yIPB2FTD47MopMGPHVyeOLQydfj41JETk4ePzaycPnv73u0XX7367KPjV2/Nnzg/c/TU+MHlfYeP\n        17b3rN/m7uC62WnjdlNLG7lSKVcoTS2t123ZsXnn7nVbtjmv22DvvMbWydlhjSsJQHX3WFhKZnxucW5t\n        a13/xMTy+ZUbzx279ejozUdXHr763Hc/vPfuj174/i8++exfIPJf/v3vn//uT7//6z+///NfP3r93XuP\n        Xrp59/6pC9eu37n/ndfeevXNd1998727z794+tKNM5dvXrh+68L125du3r14/e75G89cuHUf6Zlrd05c\n        emrl3LXlM1eWTl9aOn155dyVY+evrly4dvLijRMXry+fvji3dGr/kRMLy6cOHj21ePzskZMXYIdPXDxy\n        6uLymctHz1w5evbqyvmrJy5cP33x5qnLt05evnXq0lMnLt1cOX996fTVI6cuHzlxefHYxYVj5w6snJ9f\n        uUh29Pzc8rkDy+dml87MLp0+sHx27ujZAyvnUDi3fJbK2RZWzi8cPT+7BM+z88vn4TO3fGYenkfPzK+c\n        nT92fuH4hYPHLh48hvQ8fNDa/qXT1ODK2YWVc/PLZw4gv3QG/nOUOT2PikepizkUouTomQNoEG7U4LmD\n        bAtHqTs4kC2fweHCsQsLx88fPH5h8cRFtvML6B3tw46dP3gMtdDd2YXls3BG+wcwzhW6OuqIRnV65sjJ\n        /YdPzh45PX345L5DJ6YPnZhaPD518Pi+xRP7Dp6YXDg2Pn90Yn4FNn5geYxsaWxuaXT2yPD+w0Mzi4P7\n        FoenkR4cmFron5zvHT/QNzk/OH0QJf1TC337Fvr3HRzcvzg8i3f20ujc0tD+Q3i7k+cE2/iBnom5nvG5\n        vZzpRWZsVjLOd4/t7xqdgZHP2Fz36P7u8VnKTxyAAzLdwhN5qgWHub2js10jM7Du0ZlOSvfvRa0R2HTn\n        6HQH0pF9XSP7OpCOzuxF4yPk1jG8r31oXwdsZLp9cKp9gA+Hp5G2D0629k8094+19E+2Dky1DICbOJxs\n        7J1o7BmD1XUP1+8dqeseqekYqG7rrenobx1dGFq80D46X97cXdGyt7KlpwI8bd4LgBbWthfWteTXthbU\n        tuZXt+bXtAKpBTX0Cwr0cFp1S251U15VU351S16VsGb40M8JVDbmVjblVjRml9PTaLR+Kqmnx97KG7LK\n        6rJK6rCcyiypxSpKZTUpBdWJueWJObCyhOwyrGbiMotjsUbJLI7JKIpKLYhKyY9Mzg9Pyg9PzA1Pyg2l\n        dUZWaFxmsHTTJSUQFpkSEJEcEJXiH5GEjF940h7/yA3bfexctpjbOJpa2lnYOm1y82nZO3Hs2v3yjuGY\n        tEKsqMob944fXOken8uvbM4pq8+taMgtb8iraODfe2jBJedVNuZVNRbXtsRn5K3f4mZsYWNp75SRV9zZ\n        O1bT0oMFmW9YQlRyFi2tsA7LLozLyIvPLEjKLkYki9UYrcNySpNzS5PzkCnGco1XaVSSlFNM5XDLLubF\n        GdZwRWgHDnDOKKzKLqnNLqnOLqvJKavLLq3JKa3LKa3PLqXC3NK6vPL6/PJ6pGQVjbDc8noYO8C5Bilq\n        oXpeWR1awNVll9ahMLe0lhosqc0prskprs3BIToqFrVqs0qxtK3JKKjEEjazsCqDVqUVqfllaXnlZPnl\n        qViV5pal5Vem5WOdWoLVZGxaQWxaHi8fC+LSyfgwD0tMFPIh1pr50Sk50alYViLNiUvPTcwqTC8ozyzC\n        8rcsp6S6sKqppKa5Ze9I1/BUe//owL650blDzXsHPP1DzO3W2LlsNjazUmhpK7X1jE2tNmxzA/3tXVyt\n        bR2t7RzNLG1w1tzSRu3cnRcb+/eFpWbG5UEA2qp7R4YOnTx05f6x2985+tQLZ++98sxbH73w0f88+uGv\n        3//NZ3/74r//+OIrxPi37z7r6x9mi7eIlpaZmpqumpqxmpqVprqjQtNRKbdWVzNQU9NXUzNSUzNkw1kT\n        NTVzNTULNTX4m3KJ8BEGn9U8WtNSU9PmjA6nOIumhKEuGhFmq6Zmr6bmoK7mqKHmDNNUd9LUWKOpsU5T\n        Y72muouG+hqZ+ga55ka55ma55na55la55ia5pqtMY61MY71Cc61cA/kNchgKNddw+Sa5xka5Bp2Sa6yT\n        a7jI1OGDiuymsYH8qbVNCjpEyziLuqi1Ra6B8g0yana9XBN118nVRfk29K7Q3KKgilvZjVqgclGL2t+k\n        0Nyg4KEqNLcqZJuUdIgqW5XIy1CI/EYF1ULX1I6C2kQ5LmS9XLYO41GSwwbKwzTXKnAVmq5y2Rq5prNc\n        w0mu6STTcJYhQ+Yo03SQacDsNZHRtEe5Jhny5EMZdZijJhw07DQ1rGVkVpoaNmyU0dCw1NQw01C31FC3\n        0tCw0lC3UVe3oby6NRfCkDFXVzdVVzNXV7PQUDNTVzdTVzPVUEOJCTJsxqoSZEzU1ZGSaaiZaKoba6ij\n        BJ5G6mqGnBqpq3MqlRhoqBmoqxsgo66mr66mh/cP5dX1NdSR0VdX11PX0ONyXeQ11HXVNXQ0NXSF4VBD\n        TUdDTVtDTUtDXVtDHXlkZDItTZm2pkxLJocpkWrCZEpNTbmmTKGlY2hgYq2ta4S8pkwuUyhRpiFXqNEe\n        K0yTjPdb1dRgmo+NTqFE/YlycSgyqyYdqqvLNDTlGhowGafCFGQo11Soa8hhGpo4q9DURCGMq6gMI9Sg\n        QQpTUiq5oRHypCuCp+wJf02FvqGZjeM6S1tna4c1VnYujq7bk/JrI5Nz9Y3MMAD4K5Ta2rr6Wto6mppK\n        MR40K9qXUapEpxgJXyyuT9PEwjYlLTsnr8TBeYOmXFsm05ZjYnlI6JTmSgMzI2YPJue5kj+eTHWZugZd\n        rFQinB/PFQxzSD3Bh4ZBLxkNBteiqSmTrp3ycplcQa+pQhuXoFDo4LVUKHVxqKngyaHpEtW15QoduVJH\n        ruChsuH9wNfIJteicgXeGFJHYgLFK0KTzJfGhgxmCeWa6qrJ5/GrXn1ckXQV4oq4ULqi1fyq/T/+KXWM\n        tu7yq2xsP3TyHNZqWcUVVg5O+obmWjpGuF6FUkfP0NTOed2ajVuMzS1xsRg2CrV09PEe1tU3Urt07+WO\n        sQOR6XmJ+aW5NS3VvaMDh88cuHh36cbzx269eOnhu8+8/fGj7//ixZ/+/t1ff/aHf2AN8M3vfvd7n127\n        0TdeK2AayAbKBbWFCWSjECl4jRSfQHEoysWhMDB9Ff3APWz1LDL00WUTh8ggRSNCWoQkQEtWDd1ZsjYg\n        hdJAcqxZJ2A2bOKsOAVDRuRRaMXOIi8MJUhRxYGVBtXRDvJOTzQIwyk7laFctAM3RzU1Zzb4Iy8awaHI\n        I+PCGVQhGVNVQSqaEs2iLgzOwkHUEi0jAx/0JQYm2kGV1VGhBIMXjaBEDAwlwsQhLhCpqCvOiuooX50f\n        5EVGzNWqYbbFWZiYKwuAXp3zAvow1n4wXVRHnowpj9cOGTqrapzQ/+2XFRm89HhviDcPyYDqcPUdAhM+\n        Ik9KoBIDXTbk6Z3D5fQeU5ULQ4l43+LNrKWuJpPJQDmZjIAITsnkDEoAAhk5Q4QQoHLgDHxEOfmTMzyB\n        HhjnYSARwUgc8ik6JCNcIiV2w1Cs8uQqdEryF4yWjDsVvfMAVCadEgODKSBRwkeUgG5UEeOnayHqPW6T\n        DYkSyLa0cbKwdXbasGNPcJx/bIa+MV4cNR4tjRNwB9GkYZM+adLIacA0V+qahGk4oIq6pnyH+57QiBgd\n        XbxiKKZhyDEMhRJ0ot0JpZZcqU0GMLHhLERGmEIJWqEQvCbjQgU8uZYWhbdKEE11adJlkiSrCsnIE/7E\n        cfAaEyK6Uyq0dfjxGDpkISdPwr0MztoKnNLWpY6oNWoQOoFT3D6mEXOrLVPqsDawDMghpYx+Sll10J2c\n        D+VsXE7V6QKpWXEVZFAU7ghXRzNDDpRBL/we4+4oTy8PCTa1Rt1hYBA+vDJue3wXT5w9f+t+YESsJiQN\n        feFVgZTp6JtZ2dmtcTUysyRJU2JBoANRgCzoGZjoGZqoXbn/as/UYmJ+WXp5bV59W03f+OCRM7Pnn1q4\n        fG/p+qPLL7x3++2Pn3rzxw9+8Ou3f/WX3/7zSwjA4uAAXkt8bMxk6iZydWOZhoVc00KhidRMrmmugMnM\n        lHJLpcJKqbTSUlpqKSy1lNZaShuYNvIKS6UMhiqWMJmmuVyDTKZpJkNGHXlk0LipTJ1TDZiJZJpI4Wkl\n        p07haSHXsJGrW1Je01quaSPXtJNr2srhQHlbOquBQxSiBD7wxKENda2BPAphGAbq2rGnKMEhuVGJhr1c\n        E0YRtELTQanpjFWOQtMeec7AUII8SuCwhlMUuihkyMNcuEQ4OMulEqRryeAjI08lHSLjrJShizVamsiQ\n        m1K2Vilbp5S5KjVdqERyxllHpaaTkgeAVEkVnchohPZ0lvJI2Q1tyuyVmnZKmR0NQ4aR2HLGCXkqRy2q\n        AgdrhaaNUmarkNkoZJYwpcyKM0jJ4KCUwQEp8rZsOBQGB3HWSim3UciRscALzdUtcIpbQAbGr74M7xPK\n        qwrN2Pj9Q28hYaLQWCEzZUPG5P+kRpyKjGRKMmM2ZAw5FWaokMxAqamvlOlzHinyegoq0aZPiK6Wjg49\n        N02GcAmHulq6epSKEjLKgyCP81o6MC1haASHhBg2PsWmzSYdUhAqDDEpPpyEKo5PtURryHzLVCV8Sika\n        edwgO2jRoTj1uGuVz/86JE82OgRPCZSgho6uAX2b12n9xp1+wQl5azfvUkf4KlgsdQrDtYuKGCoGI0ZO\n        PrgKQqqSaGtiYua8dh09baKmgVpa2npkOmyUQSMYlZhVXR1dfR09RKY4xSU023raOmRa2ijXB844L/mj\n        EX6qXZ9eGqqlgwvXUtKLwn3pkjO/dsjgonjhQiV8qA9NokKKhQ209Q219Qyl9nlsyGhjMHoGVI5UR0+5\n        OnLKoxcaFUJpmFJLDy+KXAtyIl5QZDAGGgkJifTSiEkjBx6hrhaMrwJG3VFT1DIVcnXRGg55kmHifcLq\n        CA3T0qa62phbNaC+f3L/2afurd+yg4QW8IdYIcg3t7SwsTeix370MWBqXJoQTJoBrQAgAL1Ti6nFlVnV\n        jXn17TX94/2HT06fvjZ/8e7i5WfPPf/2tdc+OvPg3dvv/uTNT/7w6ed0i7ckLgZ9YJFuCVLLQWdNKwAU\n        SAX0teQWWgqYlbbSRkfLVlvbUkfHWkfbRkfbWkfLQkdpoa1loaWFs1YkA3L6kAvxwGeeQS8EQOBeaMCT\n        AmAqV0ePgD66JnBTXh2kZlgT5QltKg2gQ07pUMGDFG7sgwET7BR0SCUKGTUiDuXEaxhKUJHaYXzDIANI\n        4SMccOgMajNSYcAxWA9ws0jIcOggl8GNQMynBP1xFnlhqAumI8MOBHEXpabAPU6B9dAA5HGK66IdojlD\n        n/zROHUNxOMUQx8tcIbcAHSkkARkbCEMNE5RBY2rWuMG4SARXGXIC3YLaosM4R7awM4C/SA+TlEVEg9V\n        hpsSWBd1V1sQeQF35CXWKzXNlMR3FgApFSaVKCUlWOW+MCEJAvqSBsg1jeWSG1EeqRKsp5S4zxkcgvh6\n        bIT+J0xXoUkcoU8gUnzAxEcUGkBMf8K0v31IJqhKFYngKlBKzF01AU3V4eOzKmojZSJzCyLDJvC6midY\n        E7sp5QZVPaoaB53/V9cqz8f2ZO+kHBSAU4wsU5iYW7tscnPzCVu3ZY+2jgGIQ27Uwur1gkfc2irLuB0a\n        m9hjgRJo6+rq6iGwxWoDsiqgJgGO6MkpIUxMMkMZqNVlGkqngGyc1QGwBMHpLDmIRqgWF/IpoqfohS4K\n        LQhPNkFYlBhQL5SXFEUHpkdfjKJGdEQXAuton98AGJJKHric2qGxCaNx6it19RFW84oBFy4EgGGNkWBU\n        YkhAP1GbmU4mJIR0hQYjtEfXgIwYjRnQFzMmZoDnDU2hEV4q0eKJ+sIbhlZjmorGrr79y6esbB14pUVx\n        jJGphamlrYGxmS49+M/N8oytjlxXz0AIwKHU0qrM6sacWgjARN/C0amTlw9cuDV/6emTz7xy/tHbs1ee\n        O/3ondd//ukf/v3fL778Ojc9C31g8Q4WswmCI9xD1C8311Ja6SgBfWtdXRs9PSt9PWt9fWtK9Sx1dc11\n        dCAJVrraFtq0MrBQKswUcjO5DO2A+wA9Yn8TlQB826TVAAsAQn51FgDSAKwGQGp7pAxlwXeCvkoDAH0s\n        F+AvUA7KIy9Yz4GwlIFBEhyY/gLoZExwOAh/Wg0IWMspRR5ngW+kOARPea2wynQirCM8qURaHBDlKU9A\n        X60oGhGIR8gvAn/4QAMQ2pMMcEXBawFxnIIzMjDVMEgYxAoAtWgwCiI7AnwasyjBUoDLxaEdlZA/Re5M\n        ZBCclICNOP7tMH8V+uT2BO5FXoI++zDc/zf94SMOYaowX5O4D75DA1SB/5MCYM5rBbQpFEKQHRmBfmEo\n        fBz7sxnKpTBfD3E9iK+Qi0NCv8qeFACRwQoAAiCgpgW6aeNzusq7Vfvf6Ic/FZI/5+kziSiYabuaquDL\n        +F4FrihUmcqH2yHQU14y5r4oZDc+KzgrarEesOdqFaQMZZXBQXIWhmETWShV+aMRmUKppq5uaGq5wzvU\n        desu2qXBf1IjdI1SFRCEWqA8CwD6opkRkyC1L2ilhTNchY2pJ/oFoxnNDGU6JPARf3EoQMwGWgmCP6EB\n        dCjoL2WkAB+HUvuiimhfleE8x/7cCLdDh6Q61BeAyGLAJq0G0LgunSUN4PFII6Q1AV8OGdBPI4cScLyP\n        2FzBkb54vWg8HNqTHqimSCpcFRUWIV0DIx19QzEA9IJyssdXRJJAysovBzK8J0b6CiCX1bX0Tc6ZmFsg\n        j/eDgZGJsbmVgYm5rp4RRsu90LVIbfJ40IvalXuv9Ow7kl5Wm1XVmFvfXt0/2TO3NHXy4oGLt+Yu3l56\n        6sHK7Uc9h87PP/XwtU9++/t/ffnPz7/MycyV8f4suGwq14RRdKZE7A/TMif061jp6Vro6Vvq6VsbGFoZ\n        GlkZUmqpb2DFYmCJszo65tpaUAsSAHye5Zom1BSB3limLqBvLNMwQqq5qgG8NcRSoVoBIKjXgPFuj0xA\n        HJgG6FWFnMfqhFNAHIVIH3OffcQKhvjOJIWtOlAjIuWlA/jOqCVqC3/wHSwGfEVcD/0A7sFWhjvRX2zU\n        4JAbJ0+Am+Eu9UVhO8p5zweFwkgJJDcyOBCsWQNwCHw7MMoxBtEI90iN0CkGPfxF41zCKVUhTzgIlNNW\n        j1LTWkkzgLyEdeY+zvK6gZpCxVX0kzCwp2QqPQDZH5tKFUTID1uN/Rn9lJfQrwI9yoUAILPqyYUyU6Wm\n        ifJxyC80wEgusZ7yDHdDhZzifU5hADoRnzVAlJBx+C+MBEBOqQ5zn/VACABj7v8R9QtjAWC6SdTjDNdi\n        sBJkWQC+RVvJBLLZaLdE8PFxnuwJ1pOt8lRlEkFWS7599vEhA0gSG1RZPUslPACRl65LUAljRvCoKVc4\n        b9i+OzDKzNIWqwE6K9oklgl/ieYq42v/v+XUr6plUSIYRDEvEZnYylzT1hMsBvWYuaKQ0IwoVaItOXCh\n        lF+FODfLiwCuSLUY0+S2ijyuKFWR8mhcaAClevq6+oYkAKwHRGEQXyiKREzgUo/RbAgxgCedRbm0w8MX\n        CMjqUkTPJbzW0RHXLu0iokRMBZ9io2EbgP7Uu76RroGxvqGpgaGZnqGxJANCnHgMYvDEbh3VCoPfMzK5\n        Qk1dIz2/pL6r38iE7tboG5oYm1kZGJujQQxYjJ9TGFqQGtHRN1C7/MzLfTNLWZUN2VWNOXWtVX3jvQeO\n        Tp26PMcCcOSp55duPtt+4MTMpXuvfvzL3/3933/7/PPsnHyluF9HAgAiI0xDLE/bO5ZAvz6ifn0Q38nM\n        zNXa2tXGbq2NrYuVtb25pa2pua2xiZWRkZWBoaW+vrmurpm2tpmW0hzrBqXcVA4ZkMJ/sedD9GcxELtA\n        xtLdAtoFomUHCwD4DroR+hnQtgoN2spnoANq8LGGMAD6zH1Ljv3BYhCW4A7ecTmcUWW1KQqKOSNOkWDw\n        KQr5eUmBvHBAxoW39dGgUAWiPGmARGQqEQE4n4IbmM4Iprow1gMO8HkDx5nFQFAeGoBDqithHf7EboFy\n        xPUYPygPNxiqsJE/hIEuhzaRSEjoLIX50iIA7YDmq+yGAAj9Yz2gNnHWlm8MCAFASnLCebp5wxUB9FW+\n        oylkaN9fKbdVyh8LA/nQITguyL7KdwF9ihsoQ8tHoQcw1SGjX4X7VVs9BPQBdBHpiyheIB6npGB/NYN4\n        X+v/bAE9IQC6vPOzaiomqmCHTw4+riIvcEZGMGXuq+j/LRO7JawBFK8JU50ScH8sA5zS/c/VEt7qUZ2V\n        mnrcC3cqqAoT46G9AqFAq27ohSNQ0bXEaMK0qiLBSFzCarlMJtfQ0LSyX+MeELlm4zbiJm0dULRIzIIn\n        ZIN64aiWC1GRxZJxRoWPI1aeMUp550dMINwo0pd2eATXJFIzbQVVibwC1gRBDsyZy3qru/bkCVjrkgO4\n        THWpfTQuykk2qDp3RI2zQjBMGesoIdaz8QBE4ziEBvBvpVHIT/yVfLhH6ASgSbdPEaqvyowQrdUQW9eA\n        NAArAJocmg0xSzxRnJe2/mkkMFwdAn89QxjT38jM0MTcwBgaYAKO6xsYoy9aGYhbFFwF0yXeIfy662CJ\n        pqamHpWUVt2218TcUkMmxwLO0NRKR88Il8x7SmKqBfqFUQlUR+3S0yQA2ZWN2dWNWTUtVb1j/QePT5++\n        CgGYv3Jv+dbDo7ce9B69OHv9uVd+8Mnv/vavf3z1VX5hqZZ4lkNG4b+5AvhWmGtp0d6Ovr6lgYGDqdk2\n        R0d3V9etzmvWOThtcHJea+/gaG3tYGXjaGVta2ZhZWRqSRpgYKGnZ64LDdCiFkgDqEFTvhvMSwEp6icB\n        kG4OC/rTIsCcsS7CcKREf9IDum1rJZYIiChJJ4jygDtSK7kMAgCCC1AKvrMScCO8FIBIoAQQpzZZHpBB\n        FSEPcOPQnrvmEoYspWiTGY08kRek5nKx5UJ6QOzm6jiEm+A+e7J4MOWdlHJnhRzlgtR0h5ZPgfh0SEat\n        ieheQB9dQDNYZgBc8nfmxQQvLEhOcIgWAHGSAQa3MEkAOC/4TgLwRMi/aiL2F2RfXQcQ9AXrRWt8Chog\n        Ci0x1VRCAiAi+lX68+Eq5fH+oTwyAvcwUgXlY+KbyMmMOeRHCVgPZIPm5I9yUjuaBzSLvMR9AXqRRxWl\n        HNBHiZFSU4T/pAHcFKL+VcOhjlzaAmJuCmCxCZAJUBLRKINCcqZFAD6K/Amnf4xUQW3hyT6qjCqvEgDh\n        qSI+lZAY0KFYHEgCIJ0SkoCxUcuEEs6QEf5W0yc7WjUCt2pvCmdXSSTwBI4olOrq6ibm1ts8g9Zt2w0C\n        wgfsk/DxmGVcnfqSZoMbEdDnnWspL+aNcU/VUZELqZzHKaFf8JfvsUv7NoAsEEzl7MOI1Kc7lvxjliIo\n        proCzfDkeJyb0sUKgIisyyjX1qUoHodMcKCcaM4OEru5RBTikNcZLDBYagguw8TOD8uPaIp+URmwBj1R\n        Vws9kqSJinS9/Iah4cGkdw64z6SmGRDXS7LEQ9I3BN/BfX0joB/cNzc0sTAyhVkamsAsjEws9Y3M4AA9\n        4EUJDw/9Sq8FvXZyBXisFhaXUlTXYmhsirWdnpEZYn94PkF8vkZWVj6kAdBNYEkAqhqyq5uya1pq+iYG\n        Dp/af+76/KU7B68/t3z7O0dvPT9y5ubCre+8+uNf/u5fX3zxzTclJZWqFYCmmUR/paC/tYGho5mF25q1\n        21zW2FhYYra0cbmQGkyenp6VmYW9jYO9tZ2thZWlMWTOyNLQwEJfz0JbB+sAUy2FqYI0gHRFtQhQ0V/c\n        /lXHIdDPN4G/tacPsAqmQwA48CfQA+7W7EZ5VUoY5TxqUZjM/EVFDn5JAGBixbDKfaTkwLtAjFSSB/ij\n        XAT7hG/G/Ro5FgSUwWCouiQG0lIAJvoSjQD9YmefGM3lUAg4I2DHWaquitlxShyqNnZIVJCKusjjSnEW\n        1IZhJbEWxm2iroPYAuJwHnXhCS7THW8RthO7qXGcFRxHhjhO0kg+SMWTPMJ5VTOEHpAblyC/apKnMNUp\n        lFAjqnsDhH45gZ65L0yK91cFYPVQGAQA8T6YDrXALJFK8WIFLdNlci+YDbQPHwT4Isw3UGjCDGGqx4Gg\n        B+QgGaBPmz8I/HkLiLaD8BlWcU2gTRgfElsJoIxaLqdYmNYKArKUF7SVDqkW54mYq+XMgtU8GbGecS8Z\n        S4Lq1OpZJRsKSZxUDSIFXIQzd6cauXRIfXF3j3tcHQlrAMkASrTUNTRAhI07vTbv9kXsKZOjnkRhNrhx\n        KjI8J6ud0qHYz2EfFf5EXsI6kVdqh+qSURXBSolK3CMjEiZIrUtb1RTpw/QM9EgGEJ5zLI+mcBbBu460\n        ShCFKsRLVSicp1QSDD7FCgF/khlWEVILUhEaEtpERZTTvhCrDnX3uDUeFckARsK6RVdKg6Ex4yr4kiEV\n        3DgpIu23UMuYLlw79UiKhTEbQUj0iP6I+i2MzKyMza1NLGzNrRwsbRwtrO3NLGxMzKyNTSyNTCwMTCwg\n        Enhd9EgGeCXEoT3eD3TbRk09NC4lr6oROgFVwMD4clZxzyMR1/5YAOgS1C7efbl3+khWZT0JQG1rdf/k\n        wJHTBy7cXrx6/9DNh0fvvnj01sPx83emrtx/+p0f/vY/X//3m2/yC0rlCP811EwAa4Wc9nB0dKz19WwM\n        DJzNLbatWbvW3l4fc4erhIRiiPQMr462lq6JsZm1pa2djYODrb21uSUkz4LuDWApoGehow0VgZaIWI/X\n        AaA/lgJPPgWkidifHwClGwBgNExAXLolS7sivJuBqJ/3x+Eg0M93C4jgQifEPWFkiOO8zcJkZFVg9JN4\n        8FkIAEpE3kFOiEEL9EionO/3Ul7GzwIRzdfSV64YykI/GPo4ZGSTsxAAaAaUA1UEozmlUywVJANsUuDP\n        rEfvhDza4mfeoZAiepUAwJBZQ0+LUorWyI0dMA+2Sk2xpSOwTvPDk4Y8neVLE5gWZOfoHj5UAp4CuDAc\n        coAvBAALBUI/qQiYLlcpBM2qivVcHUblMKW0qyPoL4J3U9XjOjiEEsBwuMp9KfznEsT+oDMyaxSy3UrZ\n        Vr465HGxmCu+CuoU3WEOkYEzhfnEek19OWmAkAQp9uedHzIsCFgPdBQyLTasA1RwF1xbtVWaU3QvRdko\n        oX+r0BdbPbTloipRwVfkpUKVMZQlvksBvoj3qQUy5BnNQg/IhDZIblyRPKllKqQMG3XKw6ML4dCbNqCl\n        gF1qfNWZdpO1ZDIZOOi8fvtWj0AzazvAnzZhQDQ0QpxlcBPaCBwiL82SmC5BPVEu2E1M5IyI60VrqnKu\n        zhPLbaqgz+yWOC5KCKNMbboBAOqBWXoGtF2ux1E/sxs0ZMTrM6AF2XkwXFGitjglQZBif97Q5zuu1JG2\n        6pBYL61F4K+rh75oO0hHpQRkKp7S2HhzZlUaUUiXD+OuqXekqwIgTvF2kx5t95sYIPA3MQPcQX9zawcr\n        excLGwdzazsLK1szC2szSxtogClUwczS2NQCImFgbKZvZEIj4WHzOkBHRjeB1cMT0guqm6ElCqywmP5i\n        kI8FQGXfEoALd1/umT6cVVGfVd2UWd1U0Ts2cOTM/MWnD998cPTOiyfuvXLs7ncmL97tP3Xz7Avvfvr1\n        NxCA1IQkTf4SAD6QiNnNtLWs9PSs9Q3szcy3uqxxtrVV4j2rpa2vb2xqauni7Lxxw/pNG9evW7vW0d7B\n        0tLGysrW3tbJ0c7JztLa3MjYgu4SG1rq6Zpra5lqKaAojAa+0yvT5C8H0LP/xmyQHN7WB2jo3i8RR6EB\n        pALT1oQhcE3wUcOWjCgPA7DgY0tVNEEH4hcyMiI74U+kq/bEIXly4wLoMBG5C3Az3IndpAR0J4BQzmsC\n        whDyKIcJuAv6I0+bM+xPmW8bzgJhYJmLUnMtfeGAlYMYx9091gO6RiEwIu9Ku0bUKa0eJAFgOaQb4yyE\n        5Cz2cyhPcsKXw9fIcOd+RYSOMeBQQHzVyEe1HWRFtw0en+LdHjn86VsdqsLVRvjbHhL9YUJO6J3DAoAM\n        o/9xhqDP4T8LAEkCMmhhnUK2iW+MI4MUBs0TXeDSkMFLvzoktIMAX0T6HN1LAT4O9ZS0g8TliJzoFBQR\n        Q0IvqGUs1wRVBegF5Rn9Ev0lY74/aSqkAtx471Oe5IFMmx8KEqdW3f6fpto1EnnOMNxFhlYAIk+HLANP\n        ZriKVEs6lFjPxoAWn3nSAyFRjG9kFArQXw6qOrlu3bjDy8LGUS5HJSCMESNxDdhCMEuNMMtg0l6HaFNo\n        AJkq/wT3YQJ8LADUFFVEuY5Ul/ircgCzyEGgSpQQmmmj3xA4JogztcFlPX1j2qghspPx/QAyXi4Q4qWm\n        OBhnDaDAmYwORUp7+rokIRASPcoD9JJ+iMHADRpgzOVkqMjrBpYN0iepU2098Zwl3iHoUXDfAOE/dQEK\n        g9SkKOKmAssY0G9sbgismyLWd7F32WDtsBZZAyO6wcBXamBoYm5maWuKdYA51gHmhsamhqhCGmDK20E0\n        AMykXIHVm2ZkUmZ+VZOugTEOWRTFBD42oQSS8aqFBOD87Rf3Ti5mVtRnVjVkVDWWdQ32Lp48cPHu4RsP\n        j95+6cyzr5+898r05fvDZ+6ce/H9P3zzzedf/TfCbbs6BIA+n/TQp4WOjoW+vo2RyUZHp7UOjjoINLCw\n        1DVYu2ZNoJ9ndERAfExoZHhgUID3Hne3jetdbW1szEwtNqzbtHndJnsrWyM9fQsDA5ipjraJltJUKR4K\n        AiY0AHdE7ub8/TJeAWApQM992vAWEH0FjFkG1ou7uzgEDZ2UcrBAoA2FgD6xmzWD7hvjAy9ifI7rYRTt\n        MvRRHUZn2UGUCHVRcZwDbYa1FMLznpJgN5iOFM44RQ5MWKSoJXzgD+hTLb43u1qCjDDqlxokiPOz/5q4\n        FrGBI5YRok0MDIfwoW0fHhJaW6OkNqEBNGBoAJ0iT3EvF7VYAOiQCnmrR5gI0gWvKfxX0CY+5Z8s55TK\n        ecuFsY6MmEA6FCZOcYbKBejN8FLSY76kAUx/2vRHuQjtRfq/jZcLpASsEOA4BryDJQoQR5wOWOPCcb0o\n        wbtFLIBIwLi66MhATnE97fMw5VcFQGwB4RQyGAk0Bhm0vxECw7eLNEWkTPRnvj8pAKAe4VVE/ZTSTdHH\n        2KXAHNE0oZzKxT+VAAi+cypF8SIloxhcciBjan/Lvn1K9MKNq5SGNnz+t9sTGS3xMCKZuBCRl3aQoRA2\n        DmtdNuwAa+RyBZbs0mYOoZy/Y0WwA0RW8xR74ixDkIUBpgtnCi2ZnqL9J3w46ObdFYqsma0U0fMpXVIC\n        NlU5OeugQXqwhwsFwQnWxFMGtyHdIOV9GD16LIdqcXWwj2N2aa+G1YsyBF++l4AoHtXpsR8itQ61yYUM\n        TV0DtAmjKnylGKQwnAIxmbx8imRAWt/oGFCPfNUkANKFaMPEbNAhtQCd4Kd96AYvbfvQrVp753Wum7Zb\n        2ToampgZGpnqG5hicWCMNYGxOWJ/KzsnGzsXcyt7LAKMSABMpVvEBo/XAXgzqGsqopKzhADI5Hh5H4+Z\n        Z5jsCQGQJkTfwEjt3O3vdLEAZFTWp1c2lHUOdB84uv/crYUr97AIgACcvv/q7NUHo+eevvDK9yAA//j8\n        88C1ThokAHJjCIC20kpPz9LQwMXKeoODo5GhoQ5eTF39LZs2pCVFZKbExESFhIUG+Pp4u7vv3LN7l6/3\n        nnVr1+ho61haWG3ftMNt0zZnGzu8hlgHmOvpYTFhplTQXWX+cNKXdWUaFgR92vyBANANANVtAHxWKc5l\n        jiMPviMlWCupBGGpeP5HbOBARWCAO3tKrIeJPGoJnAnio01kUNFOoQGa4xAwFeDm0J5DbBYAF05BaorQ\n        eTyEZiYvWgN2kV+9JYCKxHTeLBKFyMCQQftI0RTnZQ5aFOwT2Qnlqru4qEsb+vSk0Bot3gDhPRAhFQ70\n        FTCqboMYn8hOnigB4umQr4vRL6WEft7qEcgGr4VRmM+ZJ+n/2IeXCDBxVlQHbVcLVRqAmJq2dEBnvI7i\n        Nq/w5KUASigDA6+f1ADSfi7h8OLxU54oRHciLwrRGri/WSHboGqZ+6XBoxyHYDoOAX2wXpd2gVhRuFNc\n        lMjDx1Uuc5HL1sllO+QyD8prqku4/z/0p9WAysBWjvYJrxK4OUKXBEDQXATa1JQ4xW7w12J80yEyUp4q\n        rvqw22O4/z8MQR5SYo0okeJ9WnmgR/ZZbUrqS2U4JTglVUS/wAH99qehCehPevC4+uoePTFdgIwP2TiK\n        VEX6T2SY6aQxpBM8XeTGX7li+lPIrA8AERPZWBLgQ9UlWpGbYLfgFx3yjVkgD1U4jmY3Az1DY4TKWMEQ\n        DQl55EyBNhvfG+BCYJoe5aRtfQiJnoGBDt3gBbVxlinPCwvuSLRPPXJr5MAbUygXI+HxqwYMpHJ0T4oC\n        B0QJmFVcNV8yiyhpGOrSCobkiujP4b+JpbX9GteN241NEUWDmoYQADNzSxMzcwNDIxtbG3sHB0trGysb\n        Rxs7JyiEuZUdPHGx0AYDujNMGoCWEUBoyhRRKdkQAIiHTAZB50E+Nh62EFHafTLSNzbXNzI3MDBRO3Pr\n        O10TBx8LQPdg19zS9Knr85eePnTj+dP3Xzv33Otz1x6On7t78eXv/ZFWAF+FbN6AFYC5Um6iVFhoa9sY\n        GNiZmq63d7CzsMIU6+sZbljnmpEak5mREBUdGRwSFBQS5OPrs2P7Nj8/bx9vTytrayNDaKyui/PaQC+/\n        XZu24AU0p68IGJjTnQAtC9YAIEBs/pjT174oeMehuYwCf3EngOJlYhl9C8yGfhwC8T6ZwDr4i3KAFeDD\n        ISQEJkJsYAt4ggMtAlgSSBWYjBS8g/iMSAK6XCZKXBQaguwiYAdnRSwvgA5kkwCoqiBDTbEbzjLupbqk\n        GSiRSz/8gFpwg8EfzmJtwU2RoUdqExkWAGqNmC79OITYBgH9cQj6g/s8G7TdT3kWAHrsR/pqGK0AYBT7\n        k84JrPNODisBDon7nBEGHxgKkQqyw0Q5V8QESrhfPSue7RHGOGbu02KOMsIZ/EVeSAJeYlGOQjAdlF+N\n        4onXfJeYnvfne78I3lclQeAbkTuc18vponAoWsbwUAvlKMQEIq5HionFVWPAmEyxXIB2oi+8WEA//ZSe\n        XOYspxUAXkENQW0RNQOfAmFk4h89achMf3LTBia4T2E5Mxf/iO9USzwMTiUsDJI8cIZ9pAzlV1sTVVYP\n        V02Ui/FgGIRywo2K+6QHqgGzJw+Gbwg/UR0Z6lEy6d4A975al0tULTPpKEInrDOOpXUAAxq2SkNaInCe\n        In0+yzJAoTHLA/kIwgoesRiQEW25nGtpE6zhrIIXMkIk2I1Ce1UtGD1IY4zVgD6oYmBMmyf0rQJealC4\n        zRtHRHZqWVTX0aMn7ukhHzTFsqFaWJC/uBwcckVCJxmLDechKuS2eogMTwuqUCHvIHGUDcNV0zKIRILH\n        SSPUMwT9zYxMLE0s7VzWb7GwtGWVNbCwtFq/3nWXu5uLiwteps1bN3p771nj4mJhbmGCpZmds73Tems7\n        ZyNjM/GoKAuAMXqETqtryCMTM/KqGnFRQgDEwGg8YhJ4dwu9GxqbG5tZm5jbYgBoR+3MUy90ji9kCAGo\n        aCjtHuycOzJ54srBK/eWn3p4+umXztx/9eDNh1MX7i7fe/kP/6W/DRm2bZOmmpqlkm7/QrmsDQ0dzS3X\n        2jtYmJjp6hpYWlrFRQXmZCbExMaERIT7+Pv5BQb6ePv4+3oHBPjY2NqZmlu4uW11cbK3sLD03uPj5+5h\n        a2FuJgmAroUkAPyUiExO0OcH/xG/g+MkA7z7j6icYAeWMcSJ4/wJFxv98LRXwEcDOACd4UbhPMfydJYj\n        /dWKpBZswgfEFymxmHbzaZ8HBnYQrPnZSrEOILAyWVDC8kD4EKoDZyBGqAURnxlEAsArBrhRs1wFhUIw\n        0A7F+E+0BoTRRgcvBWBYByDeB/qhHER/WhnQE59QBfCdcM9NMfQ1VOE/0x8tUyGhn6YC8EUgz/dyAUpM\n        EcqRwgTuIQNiDUG45wxtFiHPN3tRKAx1cSgILg5hTHZpVYEXkYw3f4j13KnAtFgEAPSgOWqhcaQ4hJto\n        XDy8CyjjJUC/3DIRX6wAhBLo8YOhyIsxIEVFISrCAYaJ2iKnMJ/0fvVlQspf1ltLP9pKPlhGILOOYwXZ\n        twRAFf6z0R1RVSpgykogwZSqMFsJmpRHIlUkk84+Yd/CvVSdaomKj0/9H2Rzv9ws8MqwJh9+KJC6ZmGQ\n        4lC40aHKRwyGVQHtkBrxXQTOoDpH8UR5iV/gGmsMQ1wIAAoF7smTN1gEH3mrgYRBAj3xV3Imf64ryQCh\n        lggu8I2M2LQRGQKxqgplmMti68aQMEqEJVVAXX0DQ33eBqFCXSM9wrqhgSHvC4nGJeOWAXpRkRuE6QmO\n        8wNF/FAQHMhfV5eXBXQ5VAimAabiolhCqClai9BKgnaKRJvwp8nR1SN50MXaAlXoBaJLQJ6vjh77MTAB\n        /Q1NLY1MEdmvdXBZh8uAQtjbOwQEePn5e/n5+WzZshlivHXblti4CE8vj81bNvFTk2YOzq5rN2y1d14H\n        cIsVAAmeviFeVjU1jbD41NzKBsgMVgNi6vilkQSAx2wI2TM0tkDXqE5iYGKhdvrmC50TEIA6WGp5XWlH\n        f9fskfFjlxYu3T1269Hpuy8dferB/NX705fvTl25/fO/ff7Xr74O3rxeRgKgMNFSAvmWBoZOFlau9o6m\n        RqZY5W3bsjEzJTohLto/KMjT29vXz9fHxycoyN/P19vcwtLY1Mzf3zMuNnTb1k16evru23fmJCSvcXDC\n        K0a3gnV1saQwVyrxaaf4EcSnm8Ayfv6HDymQp5AfETGowQKADz99tq2lD7m6gDsMbkR2BisZFwrQU0al\n        H1hMYHGADG31UAhPCEaKQwq6mdqEIW4EvBbBO/mAuSwMxHRVLM+HHJtz/C78hSHvIhoX1bmi2AJCy1xI\n        VOLGKUMLC+I7NUhywrs9rmLPR2z48KOfSKEE4hB6gDxF/Twe0TKwiLkCx1kjOeV9HuY+ZoMy4vYvCvk2\n        LxEfgqHKY6Lo8mHgrNAAAVxmPQmqKBeYFuXIEMdVsTnykq5wXixHMEuuPF24XoTqyKMQF44McCwE24Ue\n        sqLwfDOfwgpPtAnlgB7wPj4vFxj9kBAxDLGGwFlkIGnkTF8xofYxM9QLr+1AfLGJhOnFYPCi4G2muq0K\n        Fgtc/v8YM5RSjt8BUMIqlaOudIoPhTPBnSn8ZOOqDFJqk3w4z4ecJwc6hYrcy7cbYWOyU7TOp8Rz94go\n        KfDEP/GUp/j+kdQUt8YNCgGglNskbdPVhj/BTpCa2Erop/19LufVwGOac3eACzGOQKmSBEKhUALe+WE9\n        EBX5qXkGE2OU6xKeiNRESSYXP9kJ4xZQhZ/LJM1AyiLBX/6CgfXMQboHwLBDCfnQPr4B/QQCDXi1LlFb\n        Ct6pLy6nEt7BxzDEyBnoPBJ0AeLTJaOv1bPCgY1GrlILXB3mVpo3uiLx9Wa+WNIAuodMo4IAUAxuamln\n        5+xqbmkNH0trm7CIwLDw4F3uOz299uzYsU2h0N60ZWNqWmxISJCXj/fmLZvNzGh3aP3mHes27zA1txbf\n        DKBr1DPEKwgBCI1NyatswLVo0gO8/GKxAIjLpFeHp502oAxNed2jb2Rsrnbq5qMuCEB5XXp5bWpZbUl7\n        f9d+CMDFuXNPrTz16Mwzry5fvz9/6c6+y3fGL9/60Z/+8ccv/hu4eT09BaQSAAt9Aycra1cHSQC8PXbl\n        ZCSGhoZ4eHl4QQB8fQKD/HfvcTcxNzezsIiIDMzOTAwNCdy8aQPegls3be6oafTe6YnXytLQSDwLhIUF\n        /5goPW1C8SPv/MDoS2e8kyMgTh9mpdyOtn2I4ALotO9PUCM3ehhUFdcL1gtDdSvaMlo9lKGEfFTQl1Cu\n        elAHeSEhyNOT/sjQs57kyWpBoBe0xSFwJrAOE0rgSvSnFYA4BTchGGgBrEdedCeqoHC1R7QM1oPpCPb5\n        +U7Bd6K/g8qIZaoSCIDY8KFDwhytKkR0DyaK+cGhSEWnuF6aLv41CAAa3Bc7SEA/Rf2sE9KagIUEjag2\n        fyjMF80iA4MbiwoJD5ydWfPQEUaIFNfCly9br5RtpD9vINuukLkrZHvINLcwhQWLt/KDnji1lnfk7elG\n        DmBNGoCLEn0B+kID9LlfNC56hwYg6sdZDAOpkUJTh0uonB85hXigEdI5bhCzipdGbBOhCt4wpjJNuYqq\n        Ei4FkR9jmsDHjCbAY4lAGCV6qohMeoBiFc1REcjjf6IdJjhaowYJyjA6JW7McrnU72rv3CkfCsSvOvA4\n        OboXjQuy8xqFI3euRRXFCgADW62+uiZQ6YroiIJWKd5n7IJlq6ykfQxqUxIA8I71gLdW6Hl8EfLTIRFf\n        SAUKOVgmagtREQ5I6RSTkXAv4lNmNDlIFOazEBK+Fi6EA29oCPEQYCWqGuob0f4GbdpwF0Cwrr6xuFPK\n        HBet0Ta9JAD0PA8yJCTwEV+1FeqCSeALJ39kxA4YtaxnJEAvSIpUQJY0gK9INTnkwDNG2KUn8XkdwAE4\n        CQDibmNzawsbJxt7FyMTU4xzp7tbYmJkUEiAl7eXl5cnBECu0HZd75qTkxKfEBMQHLh7z24nJyesFZzW\n        bNjqtsfWwQUQN8QiwMAEveO1U1PXDIuDANAW0P+vANAhhmGkxxtHGJKBkanayZsPnxCAupKOAV4BXJw9\n        e+Pw1WdPP/PSsRv3D129PXn51tSVOz/57F9//PLroM0bIQDmSoUpCYCOuYG+k5WVs529sYGJvp6Bj+fO\n        9NQ4f3+/3bvdEfUHBwW47dyhb2hs42CXkhpdWpIdFxft6+u7dfMmvMEc7R07atpyEnOsjI0hJJZ0H1jb\n        DCsA+q1QhQghAX0L3gISKwBkIAZmMpALfJTjY2wto4WCrULDgR8JBdEQJ9Kziby9A6zDBOt5t0cqh0II\n        Q7lAP8FR3DbgLRoAV9wPQAmoDRiB70Q00gAJ+uIsjLRBGMf4MCYg36TlQ6SiCnxARgFo+LAz+bAbkUjs\n        FwHiiP1RHcRE6sxYRwmn1I4oAf0hCQ7swGrBZ3nDhx/6JBxjogBNTAvKMQaGMrUATCNUB8pZAKSbAaA/\n        sG7B94dFIaoD4iAsw5fOklqQDJCRWjDlIWnCE4Nfz3+7hr4VoZBt0lI4KeU4hbgevYPvsHVMf3B/k0Lm\n        ppDthDCoLpwe9+Qn/eFPE8jcRyHOivkRkT4MAiBwj4GJFYDQBoQOIPs68XsP/M0vXCacsSagr5jwO4Rm\n        GNCn+WHl4AUQwgIjXgFQIEyUxD8BUzIJ09KhAC4DHRAVECf6kwBQRpwiH0bqqpG/xH2JuVI5iQadXS1k\n        4msLGSACcobDYSY+HdLnnE9JGRqA5Mx85x0hyVPgns8Su0VF5FWbPDgF410LGK0YRHeETiKmCtwcF4PF\n        qrCXjdph8NHzPFRFbJ0TB+nHfOgZm9VCapDozwJDoKQWACnCOvAEN4nsKmfen0Ff/JwlHdJCQQgGG+pi\n        KWBgrE9PhQLTQjyIejhkVTCiBz1FOE+nWD/0aTxcKDoiaZFQzhdFCxc+y23CWHtobKRYYmB81bq0syRG\n        S8LAE0LvH0wdPbpKawtxIaiubwRqG5lYmVjYWNmvsbJzBIMR14eEBcbFRUAAghDwBwa4YQWg1HF2cSko\n        SM/JTY2KCff399mydYu+gYGVjb1fUKTrJjcDQ1PaxDc2x/DwoqupaYbFp5IA6BvzFhCGQZ1+WwCE0Tgx\n        IZgZAxMztZM3HtIWkBCA8vrSTiEAl/afuT5/8e7x2y8cvXb/8JW7E5dvTV+7/dPP/vOXL7/227hejVYA\n        chYAXQsDAwdLKycbWyMDTLS+x+4d8TFh7rt27vHYHRoSsG37NqxTnNc452YnVlfm5uSmRURFQui2bt6I\n        wMjZwamjqq0yu9TRwooEQNwG0FZaKBVWcjmgAwGgJwjpToBEbeTxQQXxYQgP8TEGzsAywTWEwLb01BDt\n        FSCuh//jPR9uge4Sc15wHxlQjBDGrMc6wJnu0FL4CUbw1j+loDNgLbgpWE8PfUItGKmrxEc57dWogA4x\n        oLCdT4kWhJvIoyL8OS+tDHAtqMsrBvoeALhP3+nlXSBE97ShDx/e8KGzqCht+9DKwIUeA9UENCED4JrY\n        xqEQXkVw2lPiRmiu+BQqogoOcV3bFDIPwFf1VTI0iPkUkmCpIHwDlGgT6MeLwuG2akpZBjB+oWpCszHJ\n        0AkzFoD12gp7vE+YwugL14iRiJmEACDuhj+vGwjBSNEyII4M6qIcKzy8yhg/SjA5eGkgD9ADEH/1loCe\n        QlPJX+IF4tGRiVJTqdTU5l+QxjAMFRQu0I/8cPRgzA+h4oXAhNMdC/4VQpzFWhMvKA4VRG3e3BACwIjk\n        /VwCNJcThSWwEsqfyFBAzQLAhd82IjsJCVOeQS+qCEOejDHNeVWPojpVpMEQX6g6H64KgNbqY6BUTlQi\n        gqNE8hGdclPSyCVeiwY5T6EuXzin6F3oBPmzM9FEFRfriwBc0IQaIUDTDQBaBEjoNKBU1GIlIEoKLWEQ\n        i7rUrwRNVJSAS9vunCcH7tFAD3VZRVQNsrO4rcqEFW5iNSDxGr2wm54+7ZVTCcqpd/4FITa6Ch4ktUYm\n        1eWx0Re+4MmaJARADMYIV8EDJsTj0rTgicsRU4S6fC3iJRC6wvJDLYDOCP9Bf1MLWyuHNZY2DhiAnYND\n        UnJUfHxUUEiQX2BgQFCg247tqGvv6JCXm5KbkxIbGx4S6ufu7mZiamZiah4Zn7E7MM7YjL4ebGhsjiUF\n        XmV1dVlYXKr0FBAtAIjyT2qAhH4SLf4ZOD1DQ2NLNKJ2SrUCSCMBkO4BjB27uO/U1QMXbtNfBr52b+nq\n        3SlaATz1k88+/+uXX3ttcIUAmChIAMx1dQBuO3PLNfYOJkbGeJNt27IxJNDHy2N3UKDfJoT5+oZOzs64\n        jOqK3OTkmISkqLDwoD273detcVEo5JvWb+5r7KnOLHA0t7IyMLTRN7DV1bXT1rLWUlIcSgSngB0Z2v9h\n        9CPex1IdgbwlHTLdaCcEQMEKgGQAEAdoAHcYIlbBd0ErGPLwQSEJBvughEy1/yMAjQxwIABNh6rdFcIu\n        w8tB3OyVfqhZqoUMUt7uJ/1ACLzaAu02IDxnT+EMN9EaCjF+lOAQ9F9HziRCxLsntncE+pGBoSkOiqUB\n        c3RMbpwS6OHDGdrSwWoADmITiUYF4z8zuVupmanQzFJoBig0dyk0fRWaHkrZTjZ3pWybUhOLj/XcFFSE\n        +uVxYt6EIvJsQwykKbVX0NcvMLG0aOO1ggnd/tXcqiW3oe92aGqzvyO5yZ3w5uG9I3gC5VAUnDInZMNT\n        bqGQA/pY3KAcGTgA2ZAWaAAGsJ7+fCapBd4S9PsQjHgjfupUqdBUcEda/EcAcUh3m5WaRjJNHTl9JRid\n        WqjuIpiwABjIZSg3pKYopIAnCQBBf5W5ZJRhjHI5CYA4y4AmpErUfmx8VrQgZSRRobygvCh/7Kk6RUuB\n        J89Sa4xvjq8JLsKfYI3BiLBdSV81IlILjnMJuYmKrATCeHXCTEcqNmoIZEwHhpeghgQLybg7mAR3oiGj\n        jaBGcBEIFi3wnol4ZJN34alB4UwmyMv+q52KfllFeNEgcEx0lviL6pSKFqg1cuYbA/Q9ACM9PfpGGAGa\n        fxMCGqBHN4elKtQ1fGhHiL/NK1qAoVygmdYE4nEgqIUYJIYBBwFNcTminMbP94oNtLRoWnjkdI10OSQG\n        0gVi0kgAaG7RCOryOA1p/8fUws7Myp6+9GtlizbtHZ0SkiKT05JCwsN9/fwCggLc3LZjqq2sbXNykrOy\n        ksLCgr19PXfs2GpuYWFsbBoamx6WVGTj6GpoTN8N1jc0gbO6xv8RADGxlKEXiE061OKliYGRBSSE7wFM\n        HhQrgBS6B9DXuf/w2MrFqZNX5y7cOQ4BuH5v5frT01duT1269VMWAO/1kgDQ97Z0dMz1DWxMTF0dnCzM\n        zPG2dnaw9/XaHRzot2btGrwYzi7OiQkRBQVpMbGRoWHBYWEBoUE+O3dst7K0UCiUHru8emrbC2MSHczM\n        bQ2M7Q0MHXR17XW0HbSVNlpy/kkfEgCAW8T+1jKK60F/aAB4De6oAlIikY2ctoCcKYCVI2akzX2OOvmU\n        RH84CGNmUQpEIkVEL+gMtCFDJGW8Ul4SGMkHDo4KDegBomk4EMQRSoOJjHsQfD1H4iiEIYMSkJce3KSU\n        4E72REcAPaJd0TKASxGuUs4CQO0LjovtIBGbSxqgRcE+Lg0VyZkK5XZakEM5etmi1NyolMPclfIApcxf\n        CbiT7VFquiH0VmpuJQdNH4UsUanpp9TczlV2KOW7lHKk9FeIyQcygIxsA68wxGxgijCGtUo5DRvXyBNo\n        QSJBPwVqKfaRGNBAKiZ8u1IOcGOhwM9xYjEht+LUQSE3pm/8YrQkdVAF6ISJQmGlUEAeMNti1x7cR4o8\n        pgh5of14vSBjaBzhvJAH0Bzxvhb9BT1N/NOSk2nIyAHyACVAaiAj0CPSt5HLgX4sHcRWEgqxCMB6hf6Y\n        DP0WEECNDzNTXigBaQDyxFN82MSCgGmuo03fVBIbNcgw90V0v0pwqo7zzFw6RIbPwo33fMhB8uQqqkJu\n        4XEjwgj3lFktpxFSkE7jZDFAocRrOsuGQ96750JSBRYMMgnWuiAaGUOZg1xiHB/y3gvvg8ME0RiO4izo\n        b6hLD1+KCBcVCTpolt0QyAsacju8EQQIUkpc5icvibDMWQquqWWaT5pqyrMn7fDQ4zrcvhgn/HUNWHge\n        iw3hlQFNrRHZea+fuY9yVgV+/l3PkB/dodbYk4YHB6gC5VkI6aYFq4UJ3xigKyWS6qA1+mllePIw+Lqk\n        29SP5VP6eWdxSEsizAYyfCEGxvpGpsamkgBY2jqbWVqja2tb+9i48LSM5ODwcC8fH/9AfwT7RkbGZuaW\n        aWmxWVnJvn6+bjt3bt68GfE/qkck5SVkVzus2WxgbGFAKwBjTIKGhiw8HgJAvwX0WAAk40mWZkZcMpUj\n        A/GgFUDHxMH0slohAMXtvasCcODinZO3H5248ezxG89AAPZdvvXzv/3nr1997bVuLQTAGAKgVFjo6lgZ\n        GFgaGbvY2Dnb2tGGnz59C2zt2jV6+gau69fGxYYlJUb7B/l7enrt3r3Lx3uPj8futQj/lQosQvKT0hZa\n        21P8g6wNTRyNTez19W11dWx0tB21lc7aiPjkoDZt/iDS500bGxnpAVTBlh7jI+DSTi4iemm3h7Z3wI41\n        CrmzXO5AWwd0CoZlAcrFWkFgF7VgaETEtoLdSOEGI8yxQiAvwAe+ixKkOEQhMgLigBH/ZXb6M+5EdtX+\n        zBotSQAQSm9QymEIw8X2tBAA+NCvPoj9boq4yVxBf6UcmoFTTuJvQ8JfSxRCA+SQN74ZILaGyFwI+qC2\n        fL0WQX+bUr6VUe6rlEcoFZFKeYhStotCfjmi+x0KTaRuStkWCAaJBFEeI8SyYD3qYlmmlAP6KBclGI+r\n        gnAP/jpitpUEerw0MLEzA32yQgkkQanAWSw4MDMIvUFVWn6xGCPAB9bpPUPf8kP4j64V8MeCAJfDVyS3\n        pr8QRzKARvAKYn6EAAD9WCiINhH1ixcOM4zGqYS3dEB/ZFAOJVDKNZUyTYiBDu0OyeVymZ6Wpq6SVgB4\n        J/B3ktGXzFCpqS3X1JFp6jH98Y7CclMfAkC4x0ca63fmPv2Pic8awBH341PEX+YyPTyzSnahAbyDRGcB\n        XBYMFYVV+Ca1+F+gV9F/9ZBSid2P7UkfIQDUy6poQQnolMAZUYnBzZ70a8kEJvqSreAa72MQ5ohiEiP4\n        kGHB7CaTvjBF/GWCqKSC0A/UcnAtqCr8BWsoTz0KoAPB5CkidAY0yQCriD41yGPgS8D8on2xjEAVfUN9\n        TnEoBEPXgP92ihg2NU6jlWRAivFpGYESqS++LtIDAyN9A3oMBnwXI6dLEIPh33vAyEkA2A1sZW3AZUIk\n        jFVrCLRmxFG/uEa6TJLS1cmkEfJVk/ECiN5O9NuiBkamRqZWppZ2ZpZ2VvT9XqwADMD00DB/gD4kLMzD\n        y9M/wM/T08PSin77ITIyKCklbrfHnh1uO9avW2doYGBqbhubXpZWUGvr6Mq/DUf3kFkA5GHxafnVTXqG\n        pjI5XnChQ5LRRdEFisHTodBpXI7a6ZuPOscX0srq0itq08rritv7OmYOjx69MHXyysLFO6duPzp549mT\n        T93bf/XOzNVbv/znfz778msPFgAsvY2VcisdbWsDfUtDQzszC1dHZ2v6LpiOPqTF0NDFyTE4wDsyLNDH\n        13uH284dO3bsdNvutn3bGmcXA30DNXXNXTt2nhkeHisucrGytTUyXWNi7GCgZ6+rba+jxQIAQMjBfXw4\n        EfsT8cU3e2WaTHba+eHYWY5yJ75ViM+/wD1t5sgRRANJJAN2dJbukQJVTHNCJ0oEzVEC1oh9GxwK4pO0\n        8F0B9CIcYPToDhMcyCa+S5E+4RsxMogJIzdmN86C6TDE+8ArqArgAtNshHv+u4+8maPU2CAF/hRZA7jA\n        Lo2Qt31AfIK7lnyNNoFyvQK8Jr4jsk5SKjKVCorZteSeWnJfLbkXgZ7Qv12hAO69tSAG1DWqIIWhfSgE\n        6gqFCGT4okc4cAbxvhwrCRH1QwAwgYjNgeONID58mNeC2nCjQJ5kiUaIMQPcOIShF7xAUG7Q3JzcaG5R\n        y5a+CkANmgvNkFMeGaAfZsrOOLQg+iu28J4S2lmnur1M20T0itDriKWGsVgcMPShK3qslHhxdSjkp7/Q\n        rqUl11XS3wLTVlJoj1cWRnt9GJKW3IAWGaQKaMFSIXeSy9cp5MgrBEOJ+PQ4iEAnkKrCKzEXGd6NAfeZ\n        7Mx33t5hZNNePGXEhg9phpAQCejszO1TMC40gJjO1cUuE/UoOmXjLlgJVo18VtFPQxLopAwxkc4KpFIh\n        05y+pIqzQC3xkfFEngw4wV8R0hK5iN18S1ZCJ1GDt/4FMYkpIhhHHs7sw+hk0BBruEeu9bg1PYF7gjIT\n        nJFEVEKwSLv8YhiES65CVyHdQ9ZHFX5uhySESM0/zrPaF4+HR0uBNgoBIQCORkW/GKHqSNIq+iIu/wyn\n        sT59aYBaoEaQ8o/vcwkGzGE7qxqui3ZvjE35h9h444guWTUDeob8o5t4FchYIzFypj+jFrMqRgLaG5qY\n        A+LQAKwALG0d+eqMQcecnKSYuGgvH28vb08IgJW1jYGRiX+Ad2xsxO7du7dv2+pgb4d3o4vrppSciqik\n        HHNrB336NgAEgL4egUVvREJ6fnUzJEEIgHhRyDhPwxaTwM90CQEjATh147EApFfUlXT2d+4/AgHYd/Lq\n        /IXbJ24+OHHj3unb92ev3Zm6dOOTf/znL1/+18N1DQQAK2h8/OgP/OrpWRroW/EiwNXRBesUAwMDExNj\n        R3u7LRvWb964YcuWTdu2bt66edMGV1crS0stpZaGTO7k5Drb1XV5qG/X2vX6St01ZmZrjI0d9fUcdUF/\n        hZ2WEhEixZt85xahGdb+4LiI5RESAkwU/wIHdNuW9kwQIxPiaddYjkKkLjCgimUAkEJKGd6ABoxwirfF\n        aX8ceIKhHPgAuGGMe5IKMBqqANyjcSgKYmEiuBbHxXw3EmTk0J5srRbBHQ4goHhwBQwVIT98wF84Qy1w\n        CoW8LKAUefjDMBj4ozqccYgeUSJaRuF2LQI3bI+W3F9Lnq4lb9GStysVyUp5uFIWqiUP0JLt1CLcb9SS\n        +yjlnkp5GDcl0M+iQvE1AI0GBalTlfJQJUX0m7XkW3mRIa4FfMdIkEK0AHoYWsAYMI3rad5oBsRaBOC2\n        QKEWNIPYDYgD8bQXxIG5jbbCRou+1A3CAuvoHVWgE6hiQDcGKAN/Ez4UAoASG4Uc9EcXloR+aIl0CuA2\n        UxnILqqY0NM+cjnPIVQN1Q2VcpQgw0aaYaGgLa/NFDHQdhwuHK3ZQO3kmlukF5rChd30MBIWBYxOhilt\n        NFOGd0IY+vzZlmJ/gWZhEtY5Qxz/9inWDOSfEAAhCcKNGhQV+exqufgnjYG1hDKcJwfKC2EAKLkLGhud\n        ogY5xhc8JaSKgJ2wJaAmAUJFZ1Ve0IF+3kcFXwFB3hwXRlgER6RGeCeHOsLMSAjWN9LXN9anLRciO6kC\n        9fvYmYFOwbhktIkvyI48ebKQkPZAMEgMBD3RLP+CJv2OgvTDyBSV02CEJlEvXIt+LpSHxwQXh+A+PTjP\n        v+PPg+SmDNEO3T+QjBGJIXF1etHhSYesCvpG9GVjnOL5JH8SUW2eNOnxISED/ELQ5IuZpAvnkfCVGpoY\n        mViaWTlY2rpYO6w1NjVH/G5pZRsXH5GbnxYSGrxnz57du90hALhMb589kZHBu3btWrdurYmJCRoPDo+u\n        qm32Cwoz4EeADLCU0TdSautqypQRiel51c2rK4DHLxO/pmIOxQVi5KIQgsQCMLEgtoDSK+rLugY6Z4+M\n        HD0/derq7NkbRy7fPXb9mTN3npu9dnvi/LX/+exff/riqz2uLiQA/Lc46Kd7dLTNSQMMbE1M19jZO9rY\n        GxuZ0DeOzcyRGhkaWJiZWlqamxgZKZVKDZmmrq7elk1bm0tK55obA7fvwEw7mJo6GZs4Gxo66es662o5\n        aSvstenTTpv7cor3eeeXtoA4ZgesxRaB3FGG8J+elgFWYKAzCsnkKKcA0xkawDAVwSwygJfIAGeIhcE7\n        pi0jmOuiNV4fSCXUEcX1zH3uAi1AbABuoj8jkvZJIAn8jArO0iGtCQiaACsORRc4hSXCBpn6erkmGE2k\n        VokHhuQM/kI/SEK4C+4OdWFgKwzRvY8W0R9xPYJ95N205R5aCmQ82Bk+aHazNqRClqQFSVBAFbZq09h4\n        BsjHTkturSUHlDG98ESnWFts1FKA4Fu0ZE5YMbDMOGspHLWIkg5okNQOc0JD4qmmPD3ZqSWHDxwE9NEg\n        xAAop7++QnsymiZaCjtdaLlcj/d8QG1rJT0SChkwQ6EI9lkGjBjxUAgE8jiL2UBraNwaJbRfTyMhDaDf\n        HKV2VpUAPSLwlzHN9/BrgZFgStEC5g3LGowZiN+u0HRXaropKYNDd0ydDr/6FCjQ5uF6ucxNLveU0QJC\n        Rp9hXs5L3GR00kcdVJWEAcb3IelWJGDNTOfyJzkuGRUC41L5490bLpfiehHgk4laLCHCVNBnH1GFalHs\n        L0bChSL8p70dacOHDbUo5BeH4stTHKdTKM0ZxhxwQNgVSkCoAvjIaBdFYFEoAbODIMJ7OERJY4Tt+DgD\n        JcwU0QKMaU67KGRcRfCd6gqR0DMUZ1FowNwHdhGqkzDQFg1ttjD0V1HOCONmxQ/psCGQl9onGUAILwZM\n        l8C8Q7N8ljol8aAQnjZ/+B4AmqKNfgT1rCKiFzFI1gzaYqISXX6IiDriecMF8nyuThc9LIThMfFV0Kd3\n        DvJiNUbqiEOafKgIrSTMTMytLaydIABWds6YBPomsKNzXEJEalp8QCA9QA8BMDQydd+9y9/fa8OGDZbW\n        1nKl9uatuzq6+vIKiixtHfT5BgDmChcOAVBT1wyKTsijm8DSPQBMsni9aOr43jhPBUoeCwDmRO3kzUer\n        9wDSKurLO0kAhpfPTp64vP/0tcXzTx27+vTZpx/sv3Zr9MzlH/3us9/96z971pIAGNMdM7oNYEJ/B1iH\n        /vyvoZGdmbmLrYO9pY2RgaGzo8vObbtcnFxMTej7AQgh7Gzs3bbvyk/P6attaMrOdlu3Hm89exNTR2MT\n        R0PjNYb6Lno6TjraoM9aLYBGAQpDAOwY5bb81VCK4DiER1wPo8CN2Q2s0L6ESgDEWZTAwUWLtEFsDoAL\n        gKBAMwgORggNEIU4RFQrAl70QvE+l8AEjpEy6CkKRvWNHP6L4Bo+8F/PsoFDsQ4AgABl0TIG4CrXcDPQ\n        9bC2dtPR2iLXAKxFs1QXxlKBDA5RiPwmBMI8QhgmZJ02wRq438U6Af8NgDVYBgHQUgDTu7SRV4BuvtqK\n        3drynSjXVmzjWkgxCdQmP5MDnqJNhPw0Bm2+c6AlW0M0V1g9blyBeRArBsTsmDpUMVfK7LVkKAd54Qkh\n        gWagNR0Fxd0gMoAODeDf2tS00VI4a1N1hOooZGTT332zVSpQ3VhSDhnyhHVeIogUzdphJEx8vMfgCVFB\n        dcwMqmAwuBDMLTL2vHDB4U4eIeiPKQ3gDTHMobtS5quUeSrknvTlA81tfKsGKXQxSJeXU3LNrXLNnQrQ\n        X7ZHLg+hZ39JAPjjTXyX4Avc45CegQHsmKqihHyQoQfwQWHkieaU0q4O8VtUl7DOpzhC/zbrORVbQILm\n        VIhEgF5qhHbtabOIBYBrrTZCmdWW6aY0dwoAid/VoXGqNIAYzcwS3BegZBriWpgRfAqkoHKOpslNdYp2\n        D4in0j6+kRFvoUiIJ7LQQzVCaZg4VAtkp20WfWIfqMoVDQXZCfp69A94APeNif4IzA2MDdiEYAghoWEI\n        qNGiAT7SIgADUGkMPQuEKnRdRGGx902XwAsF3t4xNNIzAsp5ESAuBxm0T6pAhfRNApYc7oWkCCkPA2fJ\n        0BSp7JMCQITFmoBmGNOIESLPDvT2YAFg+gthgFLq050AhMcmFrYWts62TuusbB0Mjeivd1lY2nh5e4SF\n        B3n7eNja2Rkam7iuwz9XI2NjuULHznldRU1jY1P7uo3bdPRNjEylZ0AxBnSnpiYLjIwXfxCGBYBfZYwN\n        gyclEMb0F5LARgJwCgIwPp9eyt8DqKjDCqBrbolWACcuz5y+tnD2xrGrdy/cezh37dbI6Yvf++Xvf/HZ\n        3zzXOEEATOQaxnINehZIqTDTVlro6loZGFgbGduZWbjY2DlYWZsbm65zWeuzB5fjHejlnx6b3FhSWVtQ\n        VpGZkxoSut7OwUzfwMbY1MHE1MnQ0EXfYI2e3hpdbWdtcEcJrODT7oQAn3cAaBOfv3PLOzMU3UvbOxz4\n        g/WAMvgL3DuwvxADGKAg4RWtsTYgA2QLsDLTidQgCDAt3AT6YdQCDrVoWwCIhNLAk6vAnwJ8tIBU8J3q\n        MpFFObhPAT47S54YpKbaTiODKJ+QkPWb1qqpOcrUUQWKghGiI2S28C1c4S+0AQ0CzTjcih615MFacn/o\n        FoX5Chwi7AWsQXxPLcUebQUUwlYb2qnA2XXaJAk7EXFzFzx+GtI6uvvKCsfspsUBMuiRxWCNlgJIdVHS\n        ggAOa7WpOu3DsMSCyJyRgebIox1E9+KpHrHrArWA6QLTCrmuanuHuK9FDsacN8K7Baal0GXlAN9BfweF\n        wlyh0FMqjLhZrFGstMgN7aBxQB9LAbxkeDUxsQA3Zma3Uu6roEM/GMsA8igPUMqDWPk8aGEkg7PQg030\n        g9K0mwdtDtBWBKKKQg7ue8mhDfLtCvlWuXynXGOtQlNG0bSAOwkA8ZQ5y/TnqP/xOkB8zvWJ3cxsifIg\n        Mt3aFXE6CvFPkg2J6eKfCu6QFvjTfWM+S1VUpxj3lBGnyJkGwM2yw2NFob5UJqrrih9poJAcGRoqo5lS\n        gIkyRAGBBuQlTIgM/ToC0x+XzGqxCjIAhZnIiKRf4qSNEcCdGboaXWKpQTODivrw5GZBanaGIdjn8By0\n        Bf1JACi6B48MEZKL/RZunFLCPQXg3I4xM52WI2LLXp/+iK4J/0HdVcYhpZFLrw7JGIOPmI61BRqRLlk8\n        C6SnT4sAmAF/t5aaorO4HAyAG6dB4rpQSOKBaFo8ekTTIkJ+VfhP10vTxSXcO5WTNrAnCwBeCwwDGkB/\n        AcbG0dLOhTTAxt7QyMTIxMrS2tHOzsHB0cHS2grrIYQUYLmJmeU2N4/s/LKc/JJ1m7brGdIvSUAApAUQ\n        fxNYXUMWEpeaV/mtm8B8z0ZAf9XohZDOii2gEzcedozNp5c9FoDu2eXx4xenT1+j74Kdvb5y5c6FZx7O\n        Xb89cvrS+598+tO/fOa5xlEIgCk9P0dP8pkqlWbaWuasATbGxramZo6W1nb0N78MzKFjjs7uW7YG7fHy\n        2bFzi8taBwtLvN0gpnbGxg4QAEMjZwMDF31dF10dZx0tEMeRHiZR8B4Oon7CvSPf7HVRkAzYMPrBREAK\n        RKAwXy7tCIH+4vlCKmReoJyM8yCg0AmBewFuXgdIuz1IBeKRoUUGcxl1CcSU0oqBd+2JpCghRnP4KVgP\n        N2REyI9DwSOB3a18uFGuuUGm4bVhS3x4vKezs726motMneWEHPbwXVloAA7RL+qK6B7pZi0ZcAZAh2vJ\n        d7PGbNNSbNFS0HYNq44zIV6BiBvcROxsD+5rS6ExmgJSQXmwWwzYRUe+VUduglraCrQJTCPwh+ECQX/q\n        GlqlRXdrcQigg7+C7HqqSXPAWoFDeCwCEL/DQYT/yIP+CmY9zoqoH0yHg9jGgb+5UmGoBYOE0NOiIDte\n        IGg2JhxdQFfE1KF9B14N4AXdrJAHKWibC5PjzftdCP8R8rsr5AjegfUtShkEEsE+Trkr5W6YSV4qBWnL\n        fbTlYToKTBpOwRkygGkJ1KZOsXrbCV2RyzfLQX/69aEd/CyvjO79qlj/2ETIr4+8RGf6qWQgmFjAKYkE\n        SoSzoDNtAuAE/cOhQDY8RZ4KqZxQLkLFVaWhLZ3HjXAhGx+K3R70IqrQPoNomQrBJhF+ijb5wX/6DWRQ\n        iVJ9vgTCEB8yoAUumYkERA66mYBMUvggrqdTKiXQlVYMnGFnAyNEtUx2YJ0ZJ9rkugjwKQ/s4iwJBmSA\n        dnsAdJIB8UAn33SFEKDAELG/pAGGLBgsAKQxWHAQiwEvjATGXKYVg4mhkTndnqXWJHGiCyTgwujpWIwc\n        sAMceRtHX4f0Bug00YchzMfg+Yka/pE13vDhYJ+1iv4yO6kCcExXZKhLj43SNbKOCpjSrFJfvOTi6aX5\n        oReCXiMsCIQ2YB5YhFgAjM0szSztzKwcLGydbB3XWljZ2TuuXbN+m73zBgeXDfZO613Wbd6603O3T2hi\n        ZnFJbWtMfJq983o9I9DfCnUNTSz0DOnbbbq6BgqFUk1DIywuLa+qCVchF38PQHpNxdqF0S+9KI8Nk8AC\n        QPcAxDeB60o7+7oPLE+evLL/zI0D559avHjr2LW75595MHv99tjpS9/95Lc//vNf97g6kwDw3+cypp/o\n        weecYjpzHS1LPV1rfQMrQyMbE1NHc0tnK2snSysnSxs7cysbUzP6GwcGxlZGxjZYKID+RsaOhkZOenpO\n        urrOujpOWloOSqWdUon41IFu5FLgDwGQWExYp/vAKAGUN/DWNgqBCaQwuMHEIT7e5M8cl5SA8Qd+wUgJ\n        GKPCAD4q4e14inxVggFFQRXhjHKADyZu2yLDGoAAXLaJw0+wWKwqcBa1uH3yRAngDnKB1Mislak7KTS8\n        tmxPjk72WLsea4LNmmoI4UErHx4MKuIwjB7flO/RUuzgxrdqU7QOc+HAHBA31ZLbaSsQye7QVthqKRAy\n        I3hHxlVLsVabtlzA342kEPSVLowBg4RZasl36cp36SnX62GtgBKF2PaxAZdp14X4i5bRkbmWDG1CG7SU\n        ciUyDHocAuKgv6MWB/Va1AsM9McpVNTXkiOu11bKDXh3CPRHjzAoB4ZEWz3cAl7NDfT0FL2gG5UybzYs\n        s7YoZIEshN50w4N2wHyAfqU8WqEIVlDIj0KkmGcIAAQSGrCLb9pvUGhs5L2ddXyb11Uh20Z3dGnqsBrY\n        o017YlFadLMEcwvhhEjYKKi1XXit5fLtpAGam/hPArjKZJpAsIAjPswMVsoDuHq6+McRPQFXi8JsgWM9\n        3plhIrMkMJqJztQCN8KyIaJ1ISeiUFAeCbvRz+mghJtlfzaSCin/LQGAPe5i1Z8PhSDRF4ZlvB0AFqzG\n        oUDAqqn6FYXEViI+GMp8JOONeBFB82Y9UUMV6lIkLmVUcTqBmzccmO8EcarC9BdyAgP9WQNoY0csHWj1\n        wGyipQCvGPgUrS2gLpwHMWEkALQaAM4IpuhaNA6d4Lu7pBO8WS/WB8RojrsxG/QNL0gI3QfmuJh2lsg4\n        qKfwHwIA+tN9BTO6s0prDuod7egZiEeGUFE8boRO6dIgbfw+oQlh0NOiir9Nxi8uz4zqxZKkiK4RAiB+\n        DtrUwtjMxszC1sTCxsKG9oLMre3MLGzWb93l7hOyxy80PD4zvbA6IbM4NDbVzcPX3NrR0MTKxNzaiOhv\n        zuMhwUa0L5cr1NU1+THQZoxfrsBYVsP/VQGQoP/Y8FoYm6kEQPotoJqS9l4IwNRJugN84PzNI5fvnrh5\n        /8K9hweu3R49c/G9Tz798e//7O7sQPcAZBqGmhqGMvoKpQl9jZP+OAz9mr8ONEDfzsjQ3sTEwdTU0dTM\n        2dJyrZU1zNnCytncYo2pqbOxiZORkb2BgZ2eroOOrr2Ojp2W0l6ptFUqQXDAF3RABhrgzAKARQDCfNrY\n        kSsAaKBZ4B6G4BGHQgngQGeZ5ojoHXnfH00BFkA2UgF0ZDjMpE0V0B+4F4XgLyJigiyvEmDCn+kv3dSl\n        Z2AIwUxVJegv28zoF6SGzwaui2Zhgv44BXmAAcGIxB1lavaaagGbt6REJ3qsWbNVQ81NrgF5gAMiX4T8\n        7tqIcxHMyiAbADTGg3HuQNCKurTJQ6mNtnyjtgwhvI02oE9QtudNISwF7BHda8vXa6NBmSc/L4R+bbkd\n        XN0WCv8VW3TpHi8QD+ija5xCsE+NsBIA7kgRrYPd4Ls+/ZYDLSBAebERhNUDEI8UbkhN6Zl6KjFiAQBb\n        xcP+cMYLYcU6aq+K7jE5bkqZJ0frIeJ335SasQpZsFIWBFPIAhR0rxt0xgxACXbLSQ98kRH31XkvS9xc\n        IUFFHksE/tm4tfwnIhzlmlhpidRJLttOX86QYW7xKkAMMCF4sfBWwbtiBxYBvHbk8B8CQPcDnPgvgtFX\n        JSX7/+j6DyiprjRLFE4yrom4NyIyvEvvvfeZkIZMMvHee4GwwiNhBMjgEUg4AcJ7KwOSkMXIVqmkclIZ\n        le2q7qnunu6p6Xkz763V8/711pr+9/5OJFLN+3/1qegbJ84998YNcu/9mfMdAO7AMV3hkNhM1lTADTJg\n        PyQeyIAHAsHyOtCI9Rj+yDMDDsAAafwoObO0gXOFRcgxSUyXG5ADzmNxzRQaHT7KUFCsw8bJFe5YFkDB\n        4dCqmjpbh45M84e5Hlh9SqxXBgFQgImMaIRmwiU6me1DOBbxiGNiumA34VKdwktIVMBLDhhonEFog1gv\n        2plmAaBZPhLs4yRpTPhxMyTAT2E6eH1pgNdHJCHWA5mANECxPEAGAeU+AhNQkpOTaH/I1+Ftg6VkL62g\n        pHLS3ST+JXxKoBfBjjHKsUOjQWBRMQHmDDHF0w9TAJfjnlzkG3/Aw4CB3DC+O/OFmHOpqPTRFxeOEasL\n        vyB+KT6iRzqAz1l9SiOAXiNFHvg6uGLYF4wGwwl/OO4PszRQRm5pPCM3FE2PJLKz8oryiyty8kpi6TmB\n        SHpaIO4PcW9IfzDqC4Q9ft4J57c9IHhNN1Q56HnL12Naw0Q3HiOJcAD95XENQD+tFhiDoJFYFglg096j\n        U6QUxCQSwDNPHzq598Ktg1fuHLn+5ombb1+48/6NDz46/AYI4OY3/+lff/cv/7UuOx0E4HWk+tA0rvcJ\n        ogEXDJaHi7qc6baV7rbTve4MrzcTMt/vzw4GsgM4CGT7fDlp3myvJ9NjZ9lWhu3KcDmznK5MEAB9F0wM\n        J5TLetck1gv6A+vzTIPiGjAE40CjlQDERyfGQEvS7SPiHaCAMTjIF3DHsWToswc2AegBkE3PCWDaaShi\n        kMEC94ZBJgBW4ixZwEW4J/qzdoLCL8Zj1RjKScIQ8Ajoj2PAEyYBSeCKQKjqAfmPT4txlvjccW5uakpR\n        asrwiorR/WObC0vqXBjmoA0hAwjiLkAzQ9ZAK8yJnmaXXuGi3QPIznLpOKVOLtfi1BpdVPF+MITLACJD\n        v+MLFrko/3G3AGjod8wADsiShVqYAXdCanGRbMrFlQRpjB5QQtQ06KznAX0yeGL028hbvOJ0CH80KHpT\n        dD2+b7nJh4a7hehuEdcKs5sMpuV0iZtllKH3yUGdoQHZodxbnYB7Ins7y8M5gMVDaPFoaL1OrRO0yooU\n        AvTMmmVWaDXmlGh2hTjEJOrLR4QnLB58lm8q0CUOLxEjcECenipkoOFfFH6Ueq594zLj9AHRUC4ckEHL\n        Use51RpP1AUoB0BN/siTCY48wIeEXeWiQT96FI4rsCZM85UoQIwekO1sSsh/T9EPHJAPkqiBxjl5rOK9\n        3x/M0IJ6K8diiwDWBwaQEgD00lwOhyO/tHb9ruOzlm2CgDXQJeuqXB7KYQFNakBiOu5fvixeFZ7SaSMc\n        QOUL9FTHXr+SnPIcJJtI8QRNB3UivfnqQUGqi1NIYTc1Pg6S9DDABMBoL508FPU0CMQjRLuBDijOD5Tn\n        DIoACM0yId5SRDOLH0ia1LaqAAP1NQYHhDwYyJXvggm5glcIlaCsxoAncC7xnTfJ7CCemOyUqIDy/yQj\n        zPj6it7kcqRYYqj6svITUPiT4AnKtAnYyX8ncswfC1fnc+Ojw9dX28H7Q6wMSoc+pX0sg4mh0Yz8SCIn\n        FM/yA+7DsA8yQQAsHxTmzsDAd9wtzR1QGj1+3NDNoekpg1J7x0yCBTBAAAr0/7f2PQ6w8LyDsYz8lPN3\n        SACwAKYsWTF5MUtBbD54ggRw9c6xm3dPvvbuhbc+uHXv4yO37+6+fPPn//Cvv/vrvzXlZoAA3ER/tEHc\n        qlcW1gd0PWjSDR23zLjlTFiuhNtK99jA+gyvBy3ba2d57HTbznRbWZYzy2WmW2bCCeFPt3WmYaQbyXTP\n        hJFcyQUIg4rMNwyYAgUSnAS+428Yf7Hp8octnUa+00C/4DhMBIMHgsWU5AJSCujRcMDOgU+B6ThAIybK\n        DOjBpxipcjRLnUR/EgBEN6FT0B/YJDgLZK8y6VbGMawBorzJIC2gucY0IOeB6RivjAa84kKc3zRyB6Vg\n        2Mju/tHd/Q1uV4OWUiUOH46hJCeUQzLXigGB60L151tJOwC8VSoesDaXPoxi3ygUKM+19AwZAIoKu4yg\n        i6ocTRMCwOVUbmXASV8/nw+sBJdeIByQA6tCfD4xSdGhe8fU3eJrSndqOHCK50d5+V2mbhHE6ZAZYuij\n        DcZjge+dhj4SEl78V+2U8AaUe7uhN8un7YbWZkB3swZRDZMy8dzoAqqW+qDlpgMPEMSAaaHTs8QKxFPF\n        d4cOAAHgmeNJ4oGUOg08XuA+fkrI/xrhgErYGQajF/j1E/znpEPU5+upeOAYgH9IoIpq1sjDvzGKDDTc\n        SbnuKNTVikJ6nKrEktBsIDDgTEBfkP17BCA932/843+E0aLrBfSVZicBoB8jiAUqQVNFa8kiPBYcT/IE\n        Vb/MIH/Y6u33Jyd+4dzkkjE5kcYITiW0YQAAyDS5fbxD08KxzDEzl61+9nDr0LG6AZTABQnuSjVLAxIR\n        jIhKooXlWwM0RTgDpAiFCo4JfANvCfTSKOrFEY/TQQA8YOOJzA3Fq0B2WprPD32tJLwbRoOgv1xOWRts\n        Xj8hnq4h5RHCK/pxCfqERLbTmAjKcgEvp4I8F4DmVLxbbu8l0+IeML9YCewh6gnwUYDjovz6eA60D/Cp\n        XyUFCaOgkV3E3Y9zueCL7iY2mdlL9CQTSMNV+MwH/mHg2YqTR6wB+dH5c8tPluyUht9AHhFmkJmFxsA9\n        af6Ixx/yhWKhaAZ+OLz6QvG0UBSvQXBAOMGQr2wE5kkLKerCzYBU8LPip4W1BwLoGT1x9tI1//8JAGeR\n        NlTD74XvGIzEWQpi094jU7kIgBvCSCmI43vOsRroyzffPvXaexfe+vDWvU+OvKEI4F++/Zf/WpVFAvBq\n        qWkkgFQ/XwfsAFnyAw6IuUw0MEEUry5nAkrfTb2fbjszLGcmGvrFeQ30B8TgLzZXAr8ggIis5oXMV3hd\n        AHyH9ndC/lMM5gHOxEGvnD8F4lcBBwApSiyCWpFJZwgAvdg0oMHLBEowQ6lJqQv8VZZBiZwiqpy+BUUM\n        dPIIAeAjNEASenAKFb1LQw8gHq+EfpH2kPkKpDAGH6GhB/1VuJZJnELDtABrEAlEKO4fV8QN58O8cKQ0\n        FZZO7u4bEQqWwCYQuwRwjwmVEcOaCrKalzEAi94bCH/o91zgNalFw5ets7hCOA9639IbxL2D47BLj7p0\n        EIAtPhnAd1TsgHJ8UxcdRND+tS5GC2pdBHFcBYZClvh5APEZTNRhD+wAGAHKI4R763Ry5TDkdjNeTX2E\n        qc819bEi8IHsAFk8BJgswH0QAJR+g9QRQj+eYQHUt6F1EHNZhQLfLtd01Ms6Z/TX0thygJPwwGuc1P4Y\n        gOeGWyoCPwm4KzsPxwB03KfwKH8s3D8MBeA7TsHN418UTBY8YfzjwWMEYYBuMR6sWS/WT8TQo+L5qZBC\n        1iWGA5ZKOpcROMpMVg80qBMBbfJnzL9kIQBRzYIvHptADDIgUpMP6ARQAK2KRihXjJgIBHrFEwPEwE/p\n        EBBqIdBT1OMj9aogQ6E/GOLRAWeTSZKGRZIVhAnwQgIA7nA2mxNqup5XXNk9anpZbasvGCb+0/8gN4+/\n        f8Ev0fuEfjkQPlC6XmHEACUovFMjiVz4iI8i2XgWYBrwSlcSbw+dMABoQ8gTA6qm+QJpjNMGQAWA+kex\n        XBmprAEOIwGkpXFHLyEMYjF3d0kmCJEDyB88phHAUC3DDMqPJKk7zODkfVKYg0VoMRDK05ThQtgl6BPf\n        1dVZroBKH+hPbiMi4zYElCWiMHBR1YQARMLzXLWKQkwB+e7yL0Qpa9oB+Gnkl8IDSS6pw/MXmwAcII9X\n        mmJioDM4QNxQIR8NghjEPjft4qbBYV8g6gtGMQDDXMJAYs3ILj1S8BW2na6bKSmDOvvGkAACERAAwxWP\n        QP8RAag0re81PHNVDvowYwCPCODF43vO3njx0mtHrr918tV3Lr75wc0PxQK4dPPnf/7nr//hn0oSsSQB\n        ONiEA7h5L5ggqDaANTX8EUrKB7M+IhKfzBC9nyEOZbSEi4neLBwmjoVsKQvDBVzMU0zN4IaOdMgA9wFP\n        aPjzxh+tknJQeUrvE0kFxBUoA22LQQAuo9TiKifgAqAH4CuDwR+CyCIk0YAL4ADoYgwA4gNNgN00JohZ\n        DiAX1DGQl/gumfIC/Q6YAsR3l7wKASSNCRH76KkW1gGOwywgnQhhVNBxwYvyWG61yakP0QY1W86u+ta+\n        huYipyNPG8SpBLzwfYFlmBYj6116h6WXWXqRxW+XYWl4hgAyKGW8LbUM0F4uYJ1jjHbbyJO3GBN2GiGX\n        7ofGl6fkA57iIcN0cNF0ALDiAPNwhcQAdIIklOWB6+Kp9kpWJb7UWKc+S74doBnSfphTH0OgZ+uQsC0O\n        hEFJ1XjazMNRap0XpTxvMxwZugG5XaprDUzfpO6uk+J0lWYq3uKx4x8D7gdM0CgRF8yDfycZLg1ci7dQ\n        6JDthbL4Ds8HdI7XOnHN4VeAesC3gI3iNTUv3uKfDUlLq2Hha9o0mAQPH4yCf5OwIOUfAL94icE4Qb5U\n        YSqSGn8msRJ/nwLxxHel8phuAdRmPwY8Muc5TBGAgHVSlQ+gv0JtFYeUTqETxSjo51mPCIaATuzgJFCK\n        +J8ijIFT5FjeCh+wSVCBpoDcAJvCHdN0ZeeXlFU14COQgcUtdnmr/BaC/kAfJWMFHOlM4NeR7yLfXdBN\n        DSPmUuM/UrvyWDhAOWoG+GBAC4u0B2zjFXeCQxW5FUyHrod+FzcOcJzoTyKUqZj8Ix4hIQCxBgT309w2\n        rQGcK1SBY3ElKdmOs5R3SMIVdPpTGkshINw28A4XIupJdtCA6ieaC/iiH58ygEw6kUaOoWHBRb9yAwoo\n        xQigbaR+dAFu9QDpWQIW44HQOySfEuX500g1VvmJyc1CwKQBKatHj5AiDzmRdgAbPVHiFwLuA/2Z6Cmm\n        Ce+KuE+CofeG0K/cfdzQzSkxgJQhvSOSBIB/E3gO/IIkADnmF5EH8jc0gPlTLt5+uHHPkSkDQeDHnty6\n        6cUTe85cP3DxtcNX77xy6+6ltz+4df+jI3fu7rp842d//qef/d1fyhJRRQBeIQDgPjOC2FhrN2qkqu2i\n        QAMhLhXmARP+lBsarwa3BkQPCSBZxZMOH+XBB+oV4y9TSjZmEe7p4gf0A1lypE4k/uzBAUCHJFYKsBKm\n        hRKgcIHXQP8aOs0BKwYsBmBTKZ1FgtScXwl/AhY4ABYD3gp+cQyPdS7WBVtA9VdYWg3VtwMSHqK7jPXo\n        mUaJTohiXlSIp5aqn4gPMKLr3wWtTajCWzqIXPwIBzgFsNhmMnO/GSCemlIejQ4Z0tuSX5DlSMkQ4gRi\n        4ikBxfAV2sXzUw70d+lZlh6BiZNkAloYoKh0y8i0+JqwjKh8CqqotvAcQLQgXeZ6YjYAK54VDqj9LT2H\n        nh/GgdNk9a+Cfoj9TLlis4v81CIp9jNc+hhLBwklGU6eUoMgOxoO8GUVC6IfPwSecHayGWALfIqvA/Ou\n        iyn5TM5plmSbYjMVchsN1gAYKEwa0HOcLJ8HIwAzw2KImQ6PRCBAPHhixHdpKp+11Gkw9j7wj0H9uPgi\n        afhXxyJ6DEsUSBFvITmGTPBPBV+f/x4MUgIMSjBNDv/5kX5wGwVmao6pOeWvRUAQf58AKBGP/FslZAv8\n        CawD85LoT/Qk/hLOhQZ4PADHAweSNQiwQ4MJgU5IQozEObiCQIxgq3rPy5EbRJUriS2gD0CXW8L/8Jb/\n        D2+VbwF6Wp2IV1zRH4gEwzFenf4odD5CahzgCxJPcUxdz8QVwFMSiOXLopPoxh6c4pXiCjIm2dRUcq46\n        i3FdAW9CNpHdzXmY0oNj4K8XyI9+JoAqsOMBQ7VMG+XMnJC3xDpijA143DQWANDSaDTIp8oTxc40SGZJ\n        hCdEekAYdNzjIzEFVPV/Na0IeRWQAOITTBXQAwFx29T4pBBm/nCTxQHTQWgAwzAbNTu/BSPP4jzBTfIt\n        vyD4ZkAN8FGIPJd/EoLRsiGPZIjxN2JelmVw4x9QQrIHg5PPHP/kCM2kNxzzrkiZ/CLM2ZeHicFgFDaX\n        jXkA/aqB40kAw0bOWboGFoPhxG8l3h6ZSnE8n4wQCZrqx+Vgc6RcfPOjjXuPTpGVwJMXrVjw1NZNLx3f\n        feb6/ou3Dl154/gNBoFv3vvk0Bt3d1668ZM//+XL3/99aZwE4BECUC6goLSQzhYxUmFHh3XuwgEa4DH5\n        wBGV7UTUTlXQenG1t5SRmkBjqU6WW8DfMP5uiyVAJ7nhRGcoNQjwPKeqEgwgo9MfcKYaEx/5p06Bj7cY\n        CZiudWrA3ALoXMFoIBT6QQ9iB+DvnDEDnKhAH8KQF1X0oA2qi4RaCkvKbGe+lgI6KSMBaNUWDAJWzQSK\n        0SwQhwwuUepiFhDApc4EHuEYep/qlXOqVBw0GQk0hChudWqdzHuhVsW9lRmpOUZqXV5RY+Pggmi4SB8k\n        nnEANxM066HBxUsD2MJsBTbJAA0EgAZwB9XhDkEAuSQA0IOR4zKKxCaAugemp4MhaGyJ44hmAfvR6XPp\n        MVbpYTAACDtc8lD7nPpES59g6SMtZt1A1wN5W8EHQhi4YfXrFIoSh+KG3QZkxzNXSUSYBz8EzTJxBKHh\n        h5MkVIefFUPBB0xtgilQo7PEKQszyL8HLgigs4shd/xwtS7GUQDZ2VQJuHOGRupYM46/F9lR7BVQjiyJ\n        QCe1PwgjnamrsI2g6x0V8q8CVAFOZVRcjLkyqW+BO8SPKAUt+GviS6UbRgZTjBxFemquobkIWFLkgE1Q\n        VY4J4vJ3LrAiaM6mcDDN5v4h/JOWV+IymED++InoAr4YJsgu6IlhkG8YiX4FRjxRUoy4KIwxW9KG3ACv\n        hXeYCgDKc4n/OBEgqyakTYC3El9N+lVwFVGmvJagKmGXNCNwQzBN4rt8NR4T0WQAFTphKAmgmI1nAcrF\n        xyIqWLEFGoFeoSHgmnp8AKx5GwT977w9+E+pfhoBdMXQF8SZ5WYe8ZM8T7EbMFsaIwdAQ4A+p5K74hOQ\n        qfiN6ALyS5Ios3fEL6S+qfxMUqwN1ghdPVD6uJyEptUwngVMBD7SgGDPd3FgWgyYhLmh6BHvv3pcpBAp\n        HUHeUo+OP6hAOagRb4XP8PDR6RImEMsMP6cxsHso4BusLLQtYQPaZ5iKml2Rh+rnw6eET8NIsSEwj3L7\n        AP25lb+gv2kYpqYpAhg1Z+k6fzAmBCD/ovgkFQ0ov5b6dkkCwDHTQLkSmEFgFQNY8diGrRtfPM5icBdf\n        PXT1jRM33j4PAvjwk8O339l16eZXf/iHH377xxJFAN/5f5TzR9BfHwQLIKyhDYpwu6jUmK4MAsp8VcgX\n        f+1Sph/9+JTu/nT0s+gmwRp/kNmi9PEHjD9vwDSAUvlG8gwDxACxRtkubg3AOqFWsAmSFoALOCZAu+gf\n        B9ADiwfQ38jXAQrMIwKpAEowP8gABwA1ydrkQX5qSlk4Ombk5JFV1aWpKQCvKkuMAJdRCw6wyCuVLqPS\n        MsptvKXwV0FISGNct4KEId4V3BtGiqFQZ+lDAKkuImynlPEBouHqoAogbAVAB2iVk1+VmVFhppY7HRgf\n        x8wuemCg4gHxnQB6Sy+F8LdpBDCP0zLCFpEdJAftj/GFNp9ANVjBNsrBBJYRchkFIAOhKwwrEBzH6fgK\n        DZJIWufSp7uYJzodzaV3WfpwW++08KkG7oG9ggH4jvhSYBrMDJzF40J7lCDEhyZfBzYQ9DVUOX4vnNjK\n        ZQ1cBgELAJQmRfEcoIQ6un3YU8OPGAoulI1rYB6ViQaHhYRnAizmhr1i+YEJ8Cn+AeAAvyYaYD2bnjpe\n        FP8GYGqAD3B1HCeYt2qUC7LTfSSZV0VOo1riPWhRkx5IcA9+cfw7xDfCv4FyVuTGPz9HoQ45whiAeAwI\n        iMQjojBhC8CEv3n8lSZxin/5xHr85au8RgX99M8Qr+nKB/bzz5vQRoQlXoiIw58uUF7+wpPODZyLHt3Q\n        HQ4HPgVUoYfnC81wWssKBIM+n89SfiHhmGSVHoCFRCOEtHAtBmDl5nnPKm4BYz8twC1kCYKic5kew8av\n        RnwHFg98a4rlAd3NV+AvcYTDpHlxAV6LPTyQSQDx6kSJ+gJeyToyIe+KV8GXHbgxemAE4hUHwFDASE7C\n        e5avQKqgwYCpANlCGFwuoGbgNwIEJ68oiC8RZj83J+AxoJwwJ6ud8WTk0pTA7AcHEPd5BQZgAYsMfcsA\n        PhYOwPNhD4GSN4mHFlS/PkaSJ3AhhdT8FYQA2EAAOJZ/JGrfGBmjkJp7L6tggEsaf9AkDShkp8yX8fh3\n        QY3PfrdCcBqLBH2u6UPDhGARTAj0Z8z/kQto2MjZsABCURUEFqqWf67AevWL/y0BDFgA3A9A1gFIFtCC\n        DVs37D+289TVA5deO3L1zombIID3YAEcvvPurss3f/T7v3/4828LoxFFAMoFpPw/IICwtKA2KKSlRrgv\n        IxpoIDWKJkwAvZ8uB+gBASj5T0qQvXyJ+CLc6OQRNAGaQ2CKWifQAL5BDOAJdNLnAHAUJgA0QP4XuYwy\n        cftQF1vMk5ExQHYuHQD6gz+UiSAyljodjTMTxZJvc7TUTEdqZ0PLgqlzhsajpY6UCstRA/gTGqgW3wuA\n        uMHSGiUkC4BDA7QpMY4bIDcArAU06yyj3TImiazuAw1Iig7uChZDpQuKlSQBeM2TbaqyLTMPN6+nlLoc\n        hRZ0t9EmRRrIfHQEGdkM2xogGDTYASCDuOh6YHSObTTZBu4Hsh3MUcx74G2UWFoOCMk2ssQ7BBICE0DU\n        T5K4whjLmGLpo9Bv0VKpBV3ZElRgNSGSloLjPPkUvwUQH/eTh19BoLZZyAxj0HCrEN2wXfDVKpIPWflV\n        wI7KcsJTYvi3VFbtttP5Ay7BRw4ofYwEauc4cQARwCrZeCbF3KhHFmnLQ8M/iSwhTlgAVU4Nx1nU+3pI\n        bEp8iruiP9Bp0JlDbxKtllwmX/EbwRzBLcFkka+QrC8NGlP1RfCPkBwAEePUCZrEHi5YFTCiJh0AR+Wm\n        QCdwjR8pd7xALYFAEJ9yD3/J6CUTSLVIQjX+IAEHugnYCoVjXBkZjgL48BH1Hc7BPEDocCy/uCw7N5+e\n        AukDUuBTvz/oCwRhH5BWeJUB20LdoehQJs3QX4G3BEeF5gpSiW4q2klxTecvU0o8AX5ZBfoK8QVMlfqW\n        VVFQ1qKyIYTxEAS10XgWgVigX/w86OSxEAbQ3+cLpPn9Pmhzivfv3QmfpKCtQDlPhEHA08EW/IiNz0Qe\n        HTGaswkiE5QV3KufQDmvhAa4mAD/R5gT9w5ThvwCdvK7kG9ErctFcTOcx2ZcF99UYgAcKc8N90YC4MPh\n        MR8dziIxYAAxGsNkBnTirQhzILXCfbx+h+NAXqftBjrrQH82qfhNfKf7Hv9suGyYlgEJgA2swH9O8o+B\n        08r2bcz4YlVXnKisB0F/5f0n9EsMALrBJAH0jpy5eLUvGMEYPBzeiexVSf8Pnx6pDt9UOEDRmxCA2hQe\n        BDBN9gN47KmtGw68vPPU5QMXGQR+5ebd83feBQEcIQHc+OFv//TuD3+a6/c/sgAUAQDxIf9pBIgvCKAP\n        vS87uRPu5WBQxBhEtw9YQRO3D80CckAmOYDBN+A70Bx/t0ABUdCUb0pU4o+2QMJ6wCDW+BS4qRICKGM9\n        A6PKZTQAsMTFIcFeBZQaEJZRBB3yX6YVbxIG4BhKFtaAIA4AC1PBsODSsLxBKUUe99Qpc2d09dbrg0rN\n        VJAK7YABlwuYoMnW2l0EO3CGhArYT8kPSoAihsS29CZLb7T1kbY+VSyANksDwuI+MR5KHPcJkZ5hQaQT\n        lO3UFL/taimr6M9MFGkp+S5YHhTvQF58KZwIXqmyzCqBcqel+2w9wyZ54HQYByW2UWSbMYul3IC/2ZaR\n        S8TnbeNccBUYCPcw16VPc+mNLn2spQ+TfqFM3C2vhWMwAaaKWqQc9OD5o7OIEQXir4Asa7fh1+lyGrAS\n        YLsQWwXxGWAQZz04AyYRFH2BlI3DMwfoA7iLBvYdwwG0f4XYZ2Wy32REtrXJ4G8BBSDmoESJgfWgEFpv\n        Jpcr47nhEmALAXHcDKiInqgQK9kxo6yB0XXN53TgPkEbMSlKgRvDPyqgf44EmWE94IrZDD5xE0owQUT2\n        loEZGjRSQ4ZGzUhABAgS5dmAUExXx1++gIhKVVQ6VOwAqnWlBCnxVKYmZZ0CBdNF2x/SHiAQS2TmFlTE\n        03Nsr1cpOMBcIBj2B4KhcKSwuKKkvC6RmQPkI7oLdsPGp3fH7YXQAy6I55/mxfcIgK+4Fl6FloiJym9D\n        H7cKkOJuZbAyO6ATQ9G41x+SrU4A4pTSCmd5osJxgLiURgATpAHK0clQLSakNhdMFz4QXFbpm2h8aBLR\n        ZXEbP5N/SAOAYwwmVainRy8QzgJKwtri88WJPl5RnEgkDNwVlwSryVWSaBpnU54chdeiuHG22CtpMBVw\n        rRAZQvEEkC5ZUlSgnFCovr5iGqAhGqAQjwu3JsTDB07hT/8Pe3gh8SPhIx5bfIxo+I7kD3wESU6pzip4\n        fPICuCQnGB+C4ND+IG3AN4+pDATcqfrxb4OWEEPW7EkKf86mGuFe8D3ZIx5F0f4kAPWRcICTaaApgwb3\n        jpqxaGVaIKzjwjKzTE4jQHA/if7fI4A0uoAu3BYCkFIQU5asmv/Utg0Hju04fWX/hVePXHvz+I23Tr9+\n        9+a9j4+++e7uSzd/8Nu/v/Pw80yPGwSg0B/NP+D9B/TT+SN6Py7an8cDBCDBYR6Lz4fQj7foxDGsb8A6\n        FDoQB1BC0ScoA+gH7uNPHao/V8K/+MvPopwn7AL9Af2VLqPaMlssY4hl1FL4072D/gocC3IpoC80jEJD\n        5iTE0KSg14iCMenWIBgJGhYbqTmpKcOaB8/s6oUMrzEH1Qn6ExAJ8RqQHZdrsOlvwVmAJMxDL780HAC1\n        W11amwugb4y1jaFAajbGErpdNCN8lp4hSTtgL8A3gDviTA3YVn11w5TRk7tzchoGpUCTYuYGKHEX/UgQ\n        9RW2kes2PBZbjGdJ2qul+0EhtlFqm3585DTyyYUGTIRKS+/CDVg6TRCnNsalj7eMEayLQLc+zg0Jf4jV\n        oudhBokeVyjzgtFjEs9gyxjsTC5owE8DZC8UzxUkP24vTlamgwXPM5+7EdAnhpEQ+5LJQ1d7JtejaWX4\n        ifGNJOqLfmhw2RpT/abcoR5YjFfaDaLNMQDkAbIB7gPBody5DA1ALzGMiEEeIpRLHQs0KH1YACDyHKcj\n        3cnQAiwDr2lE6K3CMWYw4nIzKi6S7mSs2GtyT4sY95Ph9mF+4QAY0PzjxN8509tFzSmXhGQcQpLLYizl\n        8JVP6QoAQIs3QyULiqUPDqAANJxeD/A2XlBSXdPQXlRWGwjGYAcAjiORWCIjJ5aeBdSLZ2SVVdZA+AMi\n        HQ4NpxP+PB5d13Dd+pbBRSVl4XAsGAgl7RJqZP4fEV/cREIDvE/iPkU6b0bq6gwUbSZCEdSAp4FwNBiO\n        AdkJcyQJ+liYXC9YiVe0NF8QjcjLA3+SADCMtpHgI3mCPfxUXCuKADiGrht5FcOFTawBziwEgJuUqwj3\n        UL8T4kk5AdZ59gVDMkPAFxSnjdAJFxPILQVCUgdtoG6o0BueMU7H5cRQ4L1JI53wO2IA8E4wUewGPkOA\n        OMbwiwglqDAJaWBgGAeQACSjX8w4RSFK7JNISAly7LLT8JMpOwP9MCBwjH8VrM4tIWL8Y2CPePP4lvvH\n        gb9JxgOqXzhAIsYYlgT6AQpRkgIDaAcI9ONTFmkxTPk3BgvAAQKYuXiVLxg1nHio4vCRPSz5RZK/l8SB\n        aQfgK7PRApBSEKoY3MopS1YueGqbxACu7b8IArhz/Pqbp169e+NDEsDOSzc/+82f3vr0qyxfGgjAKy4g\n        NOX8UXHgJPoD2UX7x4QGVMNHTPAXqUXXv0A/XlVgALAOUSaITI9NDn39PCbiAyYMg9t1QQwCaAjl7Fdv\n        FX4B+psss56QSuHJcyUfUaS9GApCGIB+hf6ynotuH1BFsWj/MtOgfx+Qiktog9pjkdH5+fW2WeV01ItL\n        p8QFGtCg7oGJHaLlxdFBCsGcuA3wAV0lcgDgBnr2uPShAt+NltFqaS2WVmppeZbutZjXj1PKbEJwPm7b\n        NnKMVHzTrob2BeNmtMeisZSUiEurldliLiPNoq+/1DLzLCNoGbbECXBuhARgQLY32YZfchxhVQwXD1KH\n        ZfRY+liXPgrUaDC5fpzLAC11uvR68QXBCkkwg4jEBjYCx9SJ4wjyH1YCvjVaB8tq0q0P5MU3BfTDxCmV\n        Ay5EAOayFgXD8vi0VaK4FQx3A98p6gHECSeEPNflFuoEffTkU+Nzv7MsE+Ar2Z98K9Ea2WCS6wHFIIgC\n        oJ2aV1alBZz4ghoj206OB7ID/WHxJFwGnkm20IMEJ/gpTgfoYwyMgyCMA+ESnwScIzid2a5aAATAPSNJ\n        AD7DgQO8+nQHCABwKf8B3/wALyBLMBQFUsfTMyOJ9GA46veHfKJt/cEg/oyAScFQJByJhaNx7oXB/4Cb\n        hI94PLumtr22saWzd2zrkGHx9Ay/L1RYWDG4c0R7Z19lXXN1XUtDXXNja3tOXgH3tdF1AAPAAhfHH7xh\n        6NW1Tf1jplTU1oEwoJMJ9N/z/GAYGjqVNUD0p/AnwgpYAwEp6gFMwFZAJ5A0HI1FE+n+QIQfUW4TMfFN\n        qbWT+C4H/ApcwKVoQPAaHw2QCn07RPPkKRgsByQDlonmhOiRt376r/wst0CHPmO/fmb4iCdHWEQ0O2cT\n        wqA9FPIHSAY45lliGYCf0tAfDDNZPhj1+fFdWL2Hc9ICwOm0YHjPQgOEvDTcP26e1X5UuVBAIwhPqWMi\n        o1hIvAGQgZvqWPqpmvETSP4M4V5pc5ECuOfvorUc4/ap46RnX5QBfWtuHyCbCC6N87gJ9LAAOBKNzj2o\n        BzkXVEFKQOMxGk4RSoA1aRPxnU7DRYePaUoEWIS/uIPoCBICSB08DASw2h+KuyxKDk8aq2LQkcXHq5Y6\n        yyu4k9sd86PvEcDi1dOWrOKWkEIAu0kAr4EATtx8+/Rr75AA7ryz6+KNT379+7e++CY3HEq6gMT7D+2v\n        wgBoUPoxAw3Q70hQ7CsaSBJAlGFhh+IGoH+CZEDvP4x9oH8uvbG05QH30IAqrEdLnxnfDN5StgtD5EkO\n        OF064pYpl5wfIHKdy6iy9SILU7GIEE4pZmqQAYCjuQCME4cS4J6hY5IECQDnYhISiVgApS6tODWlLSt7\n        dFtnvc9bZgyqso06m+qevh2oe9totsxqFyGvaMCLQjSX+CpENEwEoHazrY+wGPUFiIMYGl1aHz516Vm2\n        FrMZmAUx4G7BBFHxAuGjvNSUHN3R390/Y8KMar8nnpKS5XRkiB8fej+bcWDciRG2DYdEcRtwuo3TzU7c\n        ks1lbv0mbsAYZxkzXHq3RUMEeh83jNtj2MPAfWqgyXbbUDGMYiGAHDIfCaDXMmC1wDrB/cBEwACgf5Va\n        LSHOrhLR40BeAC6AuMxptLhoc+DximlFbw8EfhsTomgT4P6h5fNkB3/WaRCND27AT4AfF0gNnR40HQBu\n        MDr6GbkVEA/iI8khBkwHDc02NVuKDsUo/JnOpNaaQMsDzbOY6opbYlwXY/xiT/i4BkULOx2gkChLk2Iq\n        vIVZoEmqKOfHzFHZcBh2AD6NgBK0VKB9JBIPhkOhcASIn52dG4+lA3eCwWhefmlTW3dLW1d+YXEwFAoE\n        gv6ALz0jt6i4PBqNhIJhgCsoIRQOJxLZWVm5xcVlzW29LUP6Kqrr44mczMzc+oaG7qHDR02YOW7q/Kah\n        I3JLytraO0b2j8/NL6N7R5kO+NOnrnQ7NEdRYcmwvgllFfVgJVj6TuCH/EfpDwKgG4oiWpEBN+GibiUl\n        yAHpYSA5Mg0UFQKF4JtEE4mMrEA4LAjI8coFQ6xXOE7shuimoFZ2QDKNUmE9mYAqnj0kAx7RPsAkGED0\n        lzoQXoCvEAZhHdNyDPE9ACZgmj/6Ma141bzitJFpMd4H0g0HwwB6yYgPsZGBQMbCB0B5SZPHp8E0ELAf\n        5gKYIOAh7uNCQQ9sBQlgkBLEOiHEc3JyDDqB9UysZIokqVGxJt4qh4l4ewY4gGmvCu5pDsrvoiS/gLik\n        2BKyaZAB3wHZLrwlT+AswXFgtOrhp+LCw2/n5CtOVLpeEYAgfjIeIE1WEgx4e7jAm8Kf/R7BfVMIgNaA\n        BIEHtfcwBhAIx50gAKlnJyjPhrcM+bCRBvgRvjh+gu9cQIwBgABWPPbklg0vHtt5+ioJ4CqrgZ567e6N\n        +x+//OY7uy5cf/DL373xg59lh0gAKgdU4b5aCiAan01BPNA/LkpfEQCgH8dqAOwAZQGoAECWrgGvgdpA\n        dmB0HglAvL0w7VVMWMQ+0B/AzU5BIgp2UdyAbyAU4KlMqmOWE4zonEEDAWBCorMaBhwEAVDOM2UIxKAc\n        95WAMBfjxjgXMr9gUEpbafms8dMGhwNVekqNbcAUAG4SNAHutlFpmzUWRhL6q10aGg5U7BcDoP1bBoQ2\n        bq+BzmtCGwR1p02nTQFwXD7FJIBggDuYDMwBlR1OSYl53DPGTp0/flptPBZypGQMSslypMSNQSAAn637\n        YStYRsxFP1IzPTZgI2OxbfTarHEPEQ2N3y44jrvtBKa7GIhucRvQ+Pl6ao6WkufUmm1zpGV0y9fHPcN+\n        qgfJ0YriimLcIe6qVO4KDxwoL6uuuKKiRiLz6KmWCkJ4XCAAPL0a+aUkssIMnHZZwMxVFLgEfj5u2kzP\n        PpgejSmYTBsFRmsQ9XGDm/0CkcEHaJlU6wBxh/oUEh44ngZ5DvjmLvBawgVxACgnprNmEWlGi7oMmAsY\n        CUzHKzgA492sigrJ7xC9L6APImE/tb9P7Ayc5TE0vpX507QUCPlERm56Rk5hQUlmFlR/RnN7Z1NrN9C/\n        oqKqpqqurKIymp4uno0QDOqm9iHllbXhSCQSjYbCicKiivLKmoLisuKiitqa+orK2mg0UVhc0dzSObij\n        r2fE5PbOnu6+UTUN7YmM7IbGDvBBfl6p04W/alGHNt3E0PimacYSmc2t3UXFNUATvE36efgh4YMUIOif\n        RHwvA6pkArrF0Y9X0dcD5dhgxcACgC4GMgbDMdw8kB+nKBAH/jKznpWKZR0WUJuuIsFr2gGU8wBwwWiB\n        eDac6CN/+HzAfnKAQD/Owgx09xPNOYx8kMb4BNDZz1VO5AbaE8QjoRY6KOh64mAqU0B8SEyBsD/ExbGB\n        YDQQjAD06dUhzYS8ASA+LQaumE024j7xnY4OXJR7b/FOWPkH94bB4AmJaig0lBiA4h6eIpFqabgZsiYI\n        kv4ZC48dD5CWARiCcC/wTQRnpIdCXmK/+AjHCsTpJSRtqDVfAwsFBNzp+YHwB8QrfEcT5lC4z2MJGADr\n        Vb98BDIADYAE5HI810kHI3oGLAAQwPAZi1b5Q1F8RMp/RACC9fiHKuVO+S+WPdLw/GUl8J6j3BB46arJ\n        i1fMe/Lppw6QAF64cOvQldtHr9x55dbbN0kA7+4EAXzzu1c/+SozEFAxgEcEgAY7AASgOAAEoLQ/cR+N\n        C8SS/REmCJEYMpQRoMsm3QbXAUD4A0HQgFAQj8IHdK/jLd0yAvqVdDUIvotyV5odKEZnDp34rJIPeAJI\n        oXENAThDVmBVANTEiw2eENogK+BENOI4hTzXVUHjQyPnpqS0F5XOGT+tMxqs11MagI+Csw22VmNrEMvg\n        AGA3b8BJda8oBAcA38H09hjDqKYJ8UUuuq3pWLeNLBIJgxMZEOAQ7Ay90i7JlAyfIpvxgAp88ZSUQr+/\n        u3fM+LEzprZ3ja6pay4qTsefEjlAK8RZbKz8A4jvlYjuFMvow+QAO51ejm7LmGbxDnGrsAaGA+stY7Cl\n        1UbDVZlZBXiqjhRgPe4TXwEGCqwK3A8GV+AVz42BX5JBhyQsAehpRclThcFUL840kIFEBcQrRS8QfiN6\n        b2TbHDb8aplSKhVjgNoewwHYTSOsQ+8Dox1BJyS8+GRMR0SWDdLtA2Ug7n4/PfJEZ/QDzaHrhRXQ8Cnj\n        vaLxHX6nAxwQd5qsXARDQc7CMGh8UEjA6fA4da+L6I9OvKLfIwdeJ3tgMaAHJ1qq6Q5rUEokmsgtKIql\n        Z0ajGYlYZnVj04ixE3q6R9bVt2TkZQJ7AVLp6dmxRMzvDa16YssTq58CY/iCkYrqpgnjZnQM7s7PL44n\n        Er4A5XNmdm5nV//QvvHNLV2tQzrLqpsKikrLymsi0Yzi4oohHf0lpcB3+voBDJgZMA2ogo4MBAKdQ/uq\n        G9qAGIAD6n3x8gsBQEQK1lP0E/09aq2WivSSGQDsotABlxS5DEtCL/uDYYpTjBM3DlW8l/lOGAYFLXuM\n        0NUDXKDrxhuALeSHAAdoMluGbn2hCrKFqHs/zieFgDyAxdTawFtwRoT4jn4332PypMQGxtOwEF8/3TVp\n        YA7CtGRnEn/l0tLo7fH5QQDBQCgaCMeCeAXE48bAW5wTMpbxZDCWz4ebjOBWwQHitpLkTpopnJyNnUJp\n        PpgLYW8wlCbU4vOFaSLgW4D5AhFYfrgxfGvYE2oGhg3stIF1Xnj+zCYirAuCCz0ki/5jgG3jsdClpnqS\n        JIExltcUVuASZYh3AXowB0FcvENEfC4OSMI9oV8asZ7VfoQA1DIC5oCy9oPwEBTDgHFgOFMdWueIcdMX\n        rfR9jwDIAfz1adwII4I1+ZUF/dlJAlDVQCH/SQBLV0kW0LFdIIDzNw9deePIldsnbrx588OPjr757o4L\n        Vx/84nc3Pvphus9HAhgoBBRwJNEfNKDiwFwBIHAf1djCGheFoT+qOdgkCJwJAsAwjesD0oUA6OU3mKqR\n        72JWH2tBq7CtRFmLBP3FZa/kPxdkkQwkEaXCpBrFABxjJHAHIEXEF+tBmQ40AgYS+QH66AH+FogdAIBW\n        OF5NbtAKB6XU5ReP7R/THvI36CkASjTQAMZgkiqbEWCoZqr+JPqTUQD3w1zK3W8Ms9FMYGgn83/0cpte\n        /lzbKLfNcrpx9BYygZluGyAGHEDUl4ASXDqYIN2luVNSbNMoL67o6x45atTkiVPmdXT0+dxmrpbSIq75\n        bksf7uKGJ0MsbZSl90tQOtel48kDhWEGjYLqp51hdFjmGFgDLr3LHDQ2J3vMiPGd1Q1RxyArJSUD4E5u\n        oyOrkk4hA18NTz4Lcp4GijHMabQxs5O0iifP1VV8aHxWCakUDSzOdRk5El8F6AP9cQCwBmoL2jqyndxN\n        TBDZYYkqB3Crag0A33yBYKhyjAdJQKcHTQfe+mgcOHAWCABv0QnCAKCnmbrPaUSkSBFwHMcQ+GhpToMb\n        EcvMbnm1oOUxLYS/E8ST7MSEaIB76n1cwiVWgqG5JAJsGJqup6ampJTX1BWVleJfeDSW3tM7umf4mBik\n        eGZWeWWlPxQMR8KlZZUtLZ1ef9rQvuF/+dO/TJ40y+l0FmYXDR06auS48SXFJZFwBH+D8Vhm99AJjy1/\n        esHSFe1dPXn5ZZk5OcVVlbWN7emZOfFERkVtPbggzeO3LDeBPxQNRxL+AN30QI/GlrZhw0YCT3XTAJhC\n        7NMdwfgE8Iggb3vYA6gnDSjpKiEBwj2NA0hu4jUgiWwgaIj/z1RRjCSOD6yPxbHXB5T3h6PQyMRNSach\n        2qIzpLCSMQ+F5jKe9oGoeNoEmA3o6efSXPH20O8vWUOEHjYGtMUJg0sLeQj9qFABpuUpamZ8lDyWcgjA\n        5VAgEA5FYqFoAmYLDAj0o8lgcpvHG0xLCynWUWuDVRgZk1Dd83KKcvhd6OPygQUjPhIGyy0AAWEHKGKg\n        ucCIAkaSS3CWcADD5gr0SQCkAcaTxQ4gvqt1wnQcEU/x9MgcyU/5S4EwwAcDjn5aAyLnCfHfd/iACZTk\n        V+Ff8AGdQgOILyvITK4gw0eM/Ur6GPlD5tF0IzVV6x45cdrCFZIGittRBICfMhyKZwXCGW7x/JA4hQAg\n        CDAIz3CAABavogto6eoFG7ZtfPHYzlNXXrgAArh99OrtE9fv3PiAFgAJ4Fe/v/LhpzHbHqRcQI5Uv4PV\n        QFUWUEAqAoWZ6OmAzKc14OBxkgAcJICYwH2mAfSH/Id9wMKfGSzmzPTtZHE3F5cBK5cCTAFof6CSkv+Q\n        kyWuZGHOSibS0KUDoAfiP6IHKFyYCHTQK8e0pP/jo2oAMe0AOn/IBEIA4AYQgKA/FxDgoMrUivVBdeXV\n        /R29g73uFmNQi82M/ipqfF6iGuoYBEAJT+gH2qIft1fjZOwUI1tts9sGDdA/A1k9wdYxuNIyYRwAZ0sJ\n        9ETbQtsoECLBmGybq3nRuBu+VPl3OlKMVNCAFrOcxYWlPWNmdFXVtjlThzkdI7m8gMYKCza4tH5L76GE\n        NzFtQKofQ5sPlvjtSBcdOyCk0bBanBjpWFhTPXvGwtamIUbqIFdKChPnbTr9s5iPROsEyB4Ws6BJVD++\n        LzigRrYMy5RMXNKDGGTQ6cBijKE/Z2BtLQ7QgPJgAowMMdmGCZ14C0oANwBzgcI4FxZAVNQ6+mOmDgJQ\n        4j1qcqkgJkE/VbwwAY59BitDULkT8QHfnDwgzeN0WE6iPGgDuA+sVwc+VkDSXNLQKc4fJfk53pZT+KmY\n        DmAFp5aKf9iFpeVF1XVl1XWdQ4b2Dh/R3D40kciMpMcz8gpq6ltGjByH7rLKKsDN22/c/eDtd52mnV1Q\n        2N8/vqmxPRgLR2OZkUj66BH9WzdvXbBo7aSpj9W3NJZUlFU1NufnFVfXtcIUyEhkVtbUNrd1Ymb8Ecbj\n        WbnZMBrS4/FEVkZeMBQuKCuYMGVGbk5JyqBBAHtgNsBdAIXef9GkEgcG9Cdd2MQpoj/XK9FtjbfARwKx\n        QDZUOumB1gI9LYLaKvUFx2yAvwCxHtJbPCeAQkni9IdC4CbBUPpb6JyhKcCPgK2cnPk8ikKC/kAoif4k\n        AF5F4I/fQCCbeUS8nNCA9JAtcCYgmDKc1dAE9yVUQIwmTONA7IBIDMBNsCYx0BqQNFMV2OSqBZ7FE8OM\n        B+D2uHaBOU7MIoXw97G6DicMRTAGtyq0AfsGvAITh1YFNTKpgsFnMIr4iACjKoouAWHaWHy2+Eb4akJv\n        RFVbFc2mOw4PxE8TgaCvIges3ElfEC0DD5Gd2l+hvBCAZASJIwj0IGsLwAROqRsB3Jdh6kDOwkgSgC4k\n        4HQyBsBy0KmpncPHTV2wHJTJbGER+LgffziRXVyZWVjhCyeSMW18ERwoAkgLpJx/4+HmPbAAVk5bsloI\n        4JlNL52gC+j8rUNX7xy9duf4jTdv3PuEBHD+2kff/v7snfdCJtcdgAD8DiC+I6wPCuqyGJgEwCIQwP0w\n        GiQ/jgX6yQdiAagcUKj+uLiAMk007vOVyXosrH9Q6BRTAHLSxW3QRcuTFYDUUNmQ6kWMvjLXE5IfeA2w\n        AxmInFeg/8hi4DCcW6oivcRZzlZsSs67RRYpUYFN0fVKzuMS5bKEtSW/sLekFDDd5HLUA7XFs1RrmcBr\n        EIB4gaDECd81ZA6GmnEt4GaXpY+AiSAx1TLLLLWMoZbRAT6wjbEixqtto5BfxMhisia9LgW2GbaNgGXE\n        XEacJX2MoGUGwQemHtAH2akpYWNQW3Xj1NEzJhaXjjNTu9ST4ZJdXhFk0GcbY2x6gfK5i44DTwOgDzlf\n        A/MC1OLiPYB+GsxBo82U6bXV8+YtHtoxDL8j7ICENqgM+h3cYxuggTwXRL3G5c1OFsxgrj3jJUaU9aW5\n        3yQsKjZJvsSneI1KSQmgNnN+pPpCFHfOyjwszwB1HxEQF7c+My8ByiEnXUBx2SXGZ2hSR9aRliQApgaB\n        KoQwcArEPiv84G0AMC0FgkAAmE2YwPQAymFegAbEvQNMB9DjKmgYQAIwNFPGuHUH4B7a36tD8tMiYRaQ\n        jMeYoEE/FQggI6No3IRZTz29pWf46MLigt5hwxvbOwsqyhpam2cvfHzushW5uUWDUh2DWzu++clvps6b\n        4zTMpo7O9mEj8guKI5FwXWPr1HmLnn9m5+qVqypr6iPheCSWKCmvKq6ozMsraGnuLiuvzs0vrm/uqq1u\n        TiQy4lmZOXkFmVnZBUXFMCwqyxvjmTnPPbN94bzF+MOG/BelT78N3TtJ7z9lvuh9EbnAHaCqQLmwAn3W\n        7Pf56EgBXNI5Qzim34aoDWIgdqfJWXQi4X+AdupiRmiZ40QRTVwOhMOBYETOSktjqr6fICu+dR5jjKC/\n        2Bj8SEAcp6sr4vbAULhP3hUNEXUDBFkmKQqFiDcpjVicBm1Op1PUR8qhQscBHVDM/wEo089Dv1AwFAjH\n        AqFYEDccINlQ3oKTeM/U8rCi5P6DniSyUw4D7Dib+H8A7snmBwGAVCD/ZR51SzQjaBzwGYqOFlNArBmG\n        doHp4E70MIuJj5pWCwdbLLKkjAY/EZaBAQwmWys/EuW/y5aAgUr9lObklm0gEjERYBbQvweqEEpI+nxE\n        /pMkjKSzyFYJoOQA1vtjOejOEeO/IwCJZrvw6H3haFZBPK/EH8nAjdEWkY/4XWgfhIQA6AJaOW0pCGAV\n        awEdPLHrzLUXLr56+OodxoFhAdz7+Oidd3edv/bJt398+drrft0BSzkNiO+QlV+yBExFAtRasJBDHEHa\n        oJjgPnpgBERE7Av045XoD1OAKwBkO46c5JpPLc/Jzd8B4oAhvAW+A6MJ6CZjlUA9mAU4VkYA5DwQn+gv\n        x1D0OGBGijIaxDlTypwfylucQl+NjIehwJCvix4hLhlTI128EGaAuG62zTbbrHMx5PtoxVkNEyWTI2sk\n        jQe0USYhClwatwrVP9o2QACgBMh5UEWOCPBp0OC2Pt42JgH3uWiLAYB0Cn8j12biptcywxZLAIEA8t3E\n        7gTEuMvwSOC30BjUCvKorG0vqejifmGOFhcEPqEfNgdYsMc2h7mNdrfsKIDnCRZxmxm2XsyEJQbG8ySM\n        0Wgb1WZqg54yp6xg5fQ5Y/rHJ3wBcEDUkUpfFm4GtyfLlTOo8UEGZhhWhbBCtnAAOtXyLhgB2UzPp/wH\n        pEZ5TKwH9CuND3i1yQHU6QDxNJHk6Fc+feA1IB74jgbct3SHRzIyvQZ9+mEgu0A5RgLTMY8Cd2A9hkGt\n        gwzAE7AGPNxeOAnieEXDMMA6xvB0MgSB/pHM5wwkA17R5E2SEjAe94CZ0Qll0903asHjS5qam8vrG3qG\n        jezo6NEtV3Njy+LHV46bNnf8lNnZmXkYNmb85KMXzuWVVhQUlo6dMLG8qhaQ1NTWumjJqqefPjCkZwzU\n        ejAYyyssq6ipj8Uz8rPKly/ZPG7SVF+ap6y8ecS4x/IKynyBQElZWX5+cXpGVkf38J4Rk3ILyob1jzl1\n        5np1VeOg1FTJQgF2cMEUvUAEESCCqdNjxQYggCal4uZqqYE1X+IIEg88da4gI13heO8TP4mAuDg9qNZp\n        OuDTYBh4CjnsTwsAykOU+UxwZegYIwnoBEd6VOiKYa4OOUABfRrNAkI5ZuDl6HhRI4Gewk/KSQW2wCQk\n        CabP4pheeB9OxP1Lzg+1OXU6NT55iEsBfKEQZTvvFieGgf6haCIYiQsHRPEpsd7r9zLviEECoRDaAT7A\n        fYDbBUPLs+GWQG9yFfJNQGwOcIBc0RsIgVDxtMkWUP2kDSFI0hiJVniX+aN0+gvu0xTgl8IT4PwcyRUG\n        oGFFD6AEiQcwJMCwgUr9xDEQXOLDwgcSTuDMSX8ROJ6/Nfqp95X3XwLFEGzM/BETgf6f5LYQtmGYqala\n        53AQwAqQqKwXVPRDvW/zi4fBkfT8JDuFAGiHwQK4/fDpfS8ns4CWrHzsya0bXzoGAtjPctBvHpW1YNdl\n        IdiOC9ce/uoPp19/J+p04g9FwT2Ev89B1z+a35EaECYg4ku8V2IANAJwTMQH+muOhLQMVmPX0iVBEASQ\n        zR0EufwH8r8Q0C+VZ+j/kVVgrAMMTWoR7sETRSYlOdd8CZQD6IH+ZVLtGVhMJlDEwPoNgHuOBGQr0Adc\n        CkOQD4B6QG21+kmmwnhHA732RoNLq3JqNbZZ4TSZGiSqH+NBD5gZByAJMEExbtVkSkyT6HEg8mjLGGmZ\n        nZKGj3kKLObkQJt328Yo2xgOCBbLAFiMOWEBlNhcDSCFPBkQRieQGgyRZummi2u1cMODXfh2Dgj/Gsss\n        lBzTWieLK+D75uOWcP+2OUSiuDHhlQzLzHAzupAJEhL5D/5jmEGySDtdju5BKVPjocfGTRw9dnplTVMi\n        ngEc78FXcLNUDlCbaaAuGgTpLlbwDon/B8/N5zSA9RgQkGz6NMH3TObaE9nFWQ90NoCwwFkfP6XST+Me\n        MsR0DFCufCA4FDrBWhJynER/ckDAdERka0kvQF+8PRigYN2SHhwAx4VjaBag4RhMAJJQHIBp0YmeJBkI\n        Fam3xHpukCBsAcSXj9DplLdophDA4K4hQ/v68FcXjWbUtQ6pbmitrmxcsWjV4wvWJnIKKioahg7tyyko\n        ahvaP2zEpMLCmlmPL5s8eXZTc1tLR/fUuYumT52Xn11sAWwCwaKSktrG9szMHH8oPGP2ynOX3+ruHREJ\n        xStqG4b09jMSEM8pLCrJzMysqW4cPWF6XWNLTkbuuo1bZy9ZrmmQfUADqn4oOvxrSHXwPyBGKBLJzsvP\n        KyjOKyzPyi0EqAG2BHAJqQMplYRjYjQbPTMAO38w6g8lHSwER1H6UOuU9nSGBIjj0MI8AFUEobWD4RBr\n        EFGJMx8UH0lAWEG/agGZBITBBB4/owUhwrFwgOIkACXxkRiaBmjDjZGE6EQCNjE1BXeCATgFN8bIM+8z\n        CizDMN6kaH/KfzqFQlwlwMhwJBCOggMI91wATIaTVzEmQBh0XgXTcOei9HHbvA15DjItE414DCLEQSAi\n        biKM8Sr3CC0XGgRU9zhQ0MkADGmYYwj9HvERibOFeCoE4BYCIFuLmwiiG58qFxDdLwLrAG4VDCAHqDwi\n        fspYvSVLw5gJ5vExJGAot49aC0a4V8XgJGAgjiPxFDk087sYACiCVyf641ZxaVH9ak3Ddw2dYCxaAFv2\n        vSwuoFVTl65+7KltG/a/vPPUlQMXXzt67a3jN99+5dV3btz75Njb7+68eP3eN7957eMvcyULCFgP9Gcu\n        kCwIEAJw4DjAWkAOvAUNAPdVUSC1/kuivkwKUoFfZRBkyj7vsAOyTQc4oMgggucAVgwGCQH3rAItyaAF\n        BjGINoF4dRQBoAfHdOsP4D40PhrTgQT9id303UvJB4kNlHH9MFU/TQRR9OiE7C1ljjyz5uuZOM/5q1zi\n        8xFPPZriG/TT+4SZuXaMaaONrA6kD7a0obY2mLhv9tvmCFvvxltb67KMLmaO6uVuwD3DA4D4OgkRF4hB\n        UMZVuPQIAbsDFtV6hm1EJDUId04rBJRgGVWmBu1fK7dd5NIT9JtzWWyBm7PBZAHTDHYbtW4TvIIJYWSU\n        igUAe6IAZofkBZVaJg7aXFq1I6XSZ42trh5dW9+SkZErheRgK0Djgx3TXUZmUvWbEP54WyCl5QyXwXx8\n        gX4wQUzwHTANRQ+QjUgUVwGrU1gBzYVPBZSJywRuBzAdHKDUPWCdbKFwXJAdk2A8DujzAXC7iN0wIADx\n        bkPHRzyQS6jGt7LvvCUaHz24Im4Sc+Iq6PcIc7gF99GpEF+xBQajhwdyrikuoJy8grau/pyCklgsEYmE\n        c/Pzn9m2/8Z7H06YN99pujSHPmL46IkzpzcP6W5qHzysf+TmrTs3bXqut2/4iFETpk97vKSs3HA609Oz\n        oevLqirLq2p0zdnQ1nPr/c9WbNjmdqZVVrV19o3MK8wPBkNFhVUFReXZuQXDR00cMWpcRnpmZUXtnMVL\n        C8srDUN3u/GnS/8v/uwhdXPzikpLq6prmutbh9Q1tdY2ttY0theX1UBo28AYorYPcp6qmUofAEcEBwoD\n        H+nKDwPNYwHm10MaK/e6gD6ZA6ApuTQMACST9AGLgVA4HI0GIvSQBIJgAskIogFBPw9lu/KY053CqGnS\n        OEgaHEmLgahKKU0+AKkw+Qd2AAfgQnhLfwtUv1+qOKDfFwoHQlF/QJCdQl6Iit6boD+MzhiuBQ6QqEBc\n        uIEI7iE50aAR1gGHKVgPSoIQuQTTKpoRs4McSRuIYxjxFkcQbsYnC9xwwwB3QDxlfpovglsV1cyIgiA7\n        VwXTIEAPQJ8HpAQwnFpTjU6AOEBWjAYVNxZElm28BMqp4rkmgPX9uZ6A9CCNnKF6VN0Ip8oWTbqAVJNA\n        ggoCgw8sWIFQ/b1jp05ftBLPhx4g8fDgi1D1A/qp91VdaOK+upPvEcD+49OXrJq2dDXawg3bNh5gMbj9\n        IIDrIIC7J269fePex8feenfnhWv3vv72zhdf50dZDdQn2h8EAMkv0WBFAIwDB/EqZoF4/7n4C1ivUoNA\n        ADjOJBlItiiONSNd09GTy+IHWrHFgjy5svo/13QAwStFrYMJwAHAJuXwAb5Xu0wBfRJGuRNSnQSAHjQQ\n        AGA9meojwQNmgmKepBFg1EoiEKZFw3iYFBT14tIBbgJwawD9LhOAWCuedEAnER9NWKGewQCTx06z1tbr\n        ba3V1jttY6StDbW0FuGAZpuaGqBcbhlDbaPDrTczdGwCizEh+rMF63PcRpQVfkzAK3rAAa0uCvkM1nJg\n        Jg+9+ZyQU+FmYByUia4HN0D+Z8k6r3a32ew2x7jNBbYxUVYAcFdhl9HmNnog+d1MSwUTgHLKYYIw6ktf\n        U5YxiKsc9JQSlwPMlOUyc8XjXwiGI/TrMZcZwIFs6xYW9xTeurgkBUaAEeemYw6fACvg3uuC5HcAZ8NC\n        CehPQ3MZXtmYDOgPnHUJdqsdJTGAUdwkiIM/DLUHmdfQXXTgMGwAU0BIgg0nAutxIrF+oFMad6mExYAT\n        AeKC/uwH0OMVlANpj/lVj+rEK3p4LCOZAEr0T1oAVbUNncNGZWZBYhdGo9HiyorZi594csdz89evbBk8\n        LBiOFhdXjR07ed3q9avXPNE1on/K9FlLl60YNmJkR3tnY0NjZlZ2dWVDfk4hIDs9Iy8WT09kZM+b98TV\n        m3ca27vSPIGOrv7+UZNz8oszcvILSitxUFRSC+6oq6kPB2MV1fXdQ0dk5xTG0hOhcCQcjecXljc1dQzp\n        6u3oHdXVPb6xuSs9Kwd/45quazD+TacHmArMJWqnMRGT0M8G9GdUFmCnsi3RHxQcD4T5yvxOlViZXGwV\n        hKaGECZEUqFDcQfRCVshBHwUVxKd+wBKelHELwTopzcJB2hgDHrnI1FfOEoLQxJDmeoD80KsCq8YCrwx\n        cUx5/YR7UIgf55KNohDj9Kczq4cp/xT7IVkHAMSnMwen4CCKwbRjyGEqYIDB6EfDAaU9SAi8wsgw+UlR\n        HQgAdxVlGoywEQhTzBR18xI/8Kv9AMhYeAVkc48z8ZPIeBUGoDsIBwR38aIIMZDSAPSAWvWpnaybTdy3\n        6f0Xq8L2qMQeor8odwC9kupgC4kAwwgQZBfPDwlArATmApkunZWfmfWPT5X7SJkFeItOTTe7Rk6YsXhV\n        IByXNFCgf4BOKmamgs+STYLVQgZSfRpf7REBEP2nLlkFAnj64Cu7uSPY60evv3nsxtvHrr917YOPX37r\n        vR3nr334zbdvfvkLRQBqHcCjZNA0xyDhAwcjw2AFIQZwAHCfoWDxCIEAWPXBdGTo9AJJqiiOtUwhAFgA\n        9PUT6+lVx3GuySW74mwB8ppQ7uKBoURFf7XTVHmfGCy5/wRovIIG0AmgBwdI1FfDKRj/KGcfKF8hq3Yh\n        53EucBzqns59KR7HkS6jwWUOdjmbbLNO/PUlUsSNLAJWAPoLPTRJ1Z0WG/CqA+JHWybQFpKfSA2zw9Yb\n        mQyq59pM+GmymYwP+V/tNjvdJjgAQFxs01cTE70f5YowWANmvW2GJIbcKX6nIbbRb1Oz47Yh3svcZjFm\n        Y+0jZpTCyoHNgQvVuJ1NbmeDZXY79eHMSSVXcfGXbfbaxhTxIxXx65htthN81kGPkJ7totsNDFphc0Fv\n        hsuE6o9A+3N1ghl0mWCmPMYnTLfUIPFzs2IDYA0jIOLibm7AaCA10NlJAqDQpmwXgwC6O83FgC3+fUJ0\n        4y3QFjhrC7h7mEhKxxEGQ8J7XYbP1tMsoLkByKZTiB+RMBR8q7wdDw0Iin3At5AKyQCvSvLzRCA7AF2u\n        aPAjXo5TmTq5QXoUB3BOOcWri+mAG9NT8Q+7p2dMZ9ewYDBQUFQCKBw8bNjEGVNLykunzJm54qnN06bP\n        6Rw8dOzk2Rcu3jh94vz8Favaensj8awRY8dNnTkrp6QoFM3IyyspKamoq29uautMZORGopHlKzasWbfV\n        5XVn5BVMnv5Ye3sP0DY3rzi3qCQzJ7u0rKq+uaOmur6utqmxeUhXz/ChfaPbu3sbmod0dA/vHza6q6uv\n        unFwbn5ZRlZeRl5hemZBJJYBwUv4sD2yhMoLGlCLs8gBkNr049NND4BGJ+O0XK9LZBe9T4NAHDt4Dfsj\n        4AMIfLr70cMB/kggGAmEIe0hwAnllOFEfLyllUCGkHQadCoN7ksLgh1D0XgwDGFOo4FOHqIttDbshoCX\n        uB9NS6Mrn4gPTKcqDzIsoTwwhGMco5MxWH4UjAbDrFqBawWiEPKAcrKaALowE6S9ePAlLMzosUcsBop9\n        FftlopGPMp82ClhBzA6goQD6o6gvn5vkDgn6p+FT4rLK4WFEnelSxNAk4jMYII7+JAEA993iY0E/fhH5\n        lAfAfdhwouuZ3kNkB/RzjVhS6eMjjGR1iuQGQZT8gHtBedscqAmqUB4EwFwg1cAQA+lD6B/k0AYPGwkC\n        8CcJQBA/SQB/wwGP3jII7AuCAB5seeH4tO8IYOvmgyf2nLvx0mUQwFsvX3/r6PU7V95/eOwOXUD3v/nt\n        W1/+suB7BKDsADKB1AUSU4C5QHQBOZgSygxRcQehxXWiPywAJoPS80OnEEwBcQE5cp2OApcDiJwvZUFZ\n        n4fJ/hrULjQ7gLsayC5oJRk+FP4Q74B+eSU0Q5uLEQAQhxkBGkgW+SmSlWUVLg3zlDFQzH5MApMiz6DQ\n        BjoDQ4HaIAwVRQB6Ntpmk+2sc9HFr6iFDKQWviY5A696i2Rbjra1qRbtgCqbJdj6LX2022hxO3ptR79b\n        LwAKu/UW+mr0ao/Z6zEh24HmWYB+WQrgcekOp+Gy9Dj63VT9gHjcUvuADwd8hgbEB3+AEoaAeGgYseg/\n        7n8wWAq8YjtbhZb6XLgBA4iPe2u0zEZhAvQ30oYwIfbBGZgWSj+Dq7Ho/mqVpwqNXyAEEGOwwQxaoCIz\n        m1v8mz6XYRH3jQjjrgy9Mm1fOfpNFdelpyXN6WB6JbDepXoMgLhpQqBoeKWcF287hL9b1jAGZNkXhoEA\n        /BapBeMB2SAAhoWB1BJC8IjMx1sf+5PeHqh7TEiNz9n4ilMYAZYeHGCY0AOPZQZ+9MikUFRB+4BLAYD+\n        GE8C6OsZP2HK7Fh2ZgbLQOSPGTVl6qz5ta0tK9au3XXkyBPrnnxhz4FLN64fPXPl0vk3Xr/6GiB64oRp\n        c+YuimVmZuQX1jS0AqTau7qfWLluzOQZ+cXlJWVls2YuGtI5rLKufv2WXYvXbATgV9U0NrQNaWnsrK1t\n        Kq+qa2/qHNbbP3rC9EVrnpq1cFFv36jmtiFDO0d0Dx1bW9WUnVuQkVUIWwGcVFBYnldUnl9UlpWbH0tk\n        RWJZ0Vg6wB6AwvQRincobknXwRH9PwHgH93TRDG6RyhpaQ1QQZMPxFYIsvqCID59/WER3RDaTAGSHgIo\n        O2FS+AGjrNJMR02QsMtqptTmdN0Ewwl/IKYizHTQByO4NJgAwApKIFX4gPUkj0BQHDgU+DAmIl4IfMYV\n        wBOShUlkZzwAk4A2AqFEKJIejMQh+QNhsQNUGIAkRB8O3sLkCoF7QtG0EE0NuU+KdzqFgkItwltAPe4F\n        DwJg0hSQGtwpvAjOYEIRSJRBaQF3ccqTAJR/f2BdlWrJRCA2oQG8lfCvxA9kuUZS3QPoCeKSxAnIVk5/\n        0sPAGPKK5AUpoDelABxPYRO4V2mgaikAU4N4wGkZRbB03RyUqrX3jpyxaFUwmnBaHlX0X7D+OwKwFQGQ\n        FWDrBFn4WtUCehoEsJQuIBAAF4JxT+DrIACg/wABPDh25+6uSzfu/+L3b37xTX6E+wEo/49y/ij0F2uA\n        XiDZItihQsGPCEA5fOKsE8dyQAlqf2UKMA00RwIAgOlCVoFm/g9AvMKpAX9rXGY5FDdhnbUiCgnoBH2h\n        AeIyWo14hACIaKxAIByASWQMuQRTAUCVwFf1nwn0AwlFUMQDPh8aBGVOs5RAj4uqTnp70MQQMeqdorht\n        Xan4etvotPUxtt4rlR6abK7SmmLrfYz96m22NpaFeszBbr3VrQ9x61VuvdjNxNBcSw9LIhBa2NaDluG3\n        DZgmAH2YHYD4Ngh/9rAKRa3cOSwYKHecK+XP+GXT8Sgss8HWWyyzwsbdsvYDCKBaHFkAffKHRJsB9ziu\n        xjBQAl1M9PYIp3LxV4nTzJQ9hBNchWAmLBMcgBaxuJMzDrwM/HK7lZj4agC4CfHRK++/qHgofYZYPS7G\n        WpUF4HPpNpogL7S/IQodmMs4MC0J3XJB+1O/YxjeEqZFy1PjC3wrBBfgZsIoIF5FcTFGQTksCRwwhVRM\n        BFwXcI8WUINxrsyjzBTcg2IgEIxEntmI/jxFd5qMAeTlFfWMHgXhX1xS1T18xMvHTm/duW/W0oXXbt64\n        c//+cztOPPv8S4dePnTp/PWrF19//tld85c9cf36a/v3vRTPiCcS2S0tbbF4tKa+bvb8RdkF+YCz2fOX\n        j5kwY/K0ebdf/eD1q3c3Pbdr3MwZ8+evHDtlbueQnta2oWNnL5w1b8mUqTPWb92648VDMxctqm9oLi2t\n        qqlqKC4tyysoKiqqzskpiGdk5eaUVFTW5xaX5RVVVtc1oZWW1peX1JdW1ufkF0WjcclCAXYBsYOAW4W8\n        QDQ6telhp86luE5TkWGing+vPop6nJKswENfDVCVJBEIxijAFRaHccxIKQlAfERkBRZpiAUo2+nnARDj\n        IyAamAYDBKZBA7AemJOD+6GXBoTBgm7Kt0MnvqTihD1JpxBgGgQAiJfrglrCkWAkgXm4HhisE8GcrAwB\n        C0AIgDdMrgqBjRJB3HBIUoAweSjCVQKwA8hzsBu4VFieA+6f3IAnpVZySfSYdoMsqKbbR0wEOvHBAcT0\n        JL5LYqjyBZEAuBQDnaQK4QAZxiwseQv0F4e+7QFkozEeK4Ff2BY4IA1ItQkJGHhckvAjBACsT3p7VOOx\n        9MsANjWJCgYYppnq0AcPGz1zyZpQLAPWxgABKL2fbKoyBL4+0J+PJY2ZtSQAWADTJQAAAuBCsJdekU3h\n        aQEcvfbmkat3Lr/38OU339l98caDX/7+zR9+nR8OKwJQ8p/+H24POUj5gviaXB8gBCCOILyqCnEMCah1\n        wsllAVq6LgEA0yG1HyDwKfyLXXT+AKah2enBp7d9IAFRynlyYxZgH4s90BFfR/lPJlAwDYMAoA85Lw4i\n        6nqpYSlLxgRJ6SNyMq9UiWu8FRvCaIBMJtyTSwCmDdwVywRogiSEA8gH7YBvN8CUp6uCbkDkkZY51DJH\n        kAwY9R1ia0NYgt/osvTBttbMMSb976LrC2wj062nu7lCuNZt5MkiYSByFn39BH3odFgAwHpcopQp/CQV\n        WgAurvACQ8AUwMMBB+A5ZAjtDWEUl/PXOSn/cWJCjAyQDZosg+BBHm6DMV5WGFXPkFzoMqJcVUtEdjvN\n        iMsM2KZb5D8IAC1gU6HbhH7Dz92G6fEH4KoIcJrodAC3X5Z3AdDdLlmrJRwAYsAABeWmTlMAQOwzGUlG\n        g9530gLQYVV4TYNoLst6Acq6wDfB2nQYhsOUfCE0dKoVAxhGU0D4APYBLAPMhhnw1mfoIADAOriBk5ha\n        SJYKu3CsA/EdhuYwdAcGKA4ghcDCkCBwdn5RU3tPW/uQERMmPHtg1823X/340wf3H37y3vv33nv44MyV\n        23t2Hntu6/Z37r139srro+bN2X/s2De//PYnP/3pjr0Hho0YU1VTU1FakZObG01kOC13KBZp6hr2xObn\n        v/71H+6+9sG8aYtWb9i4ZdwFNk8AAP/0SURBVO/2xxetqKtvrWpsGjN6yokTZ0+cOXf+ytkjFy4uXLly\n        8rzZHUPHNg3uae8a2tg6pLymuqS0qri4qqCgojCvvKC4PDu/OCu3pKqurbVjWH1TR1lpQ15hVUFJRTEj\n        CiXpWTmBUJDuByAxsFW8/4BIwit9QQLB4u4gbjJJBphOE4HFfyQ2kMb1UIDyYCgWD0WBqhDaUUB8MBwT\n        2iCyQ4yzoJAofXHRRPER55dk0OSrl+XbIrGMEDkAY4DyuDRTfdCfhmtJiT0CPV1PEu8NEvF9aeLJkeuS\n        CcLJMawIROcPLZUk9DNOIDPjgHOK6RCMKmuDPVLymqFm4Zg0ITCGuEl+CuWTDnFgMWlggBgE5Qn0eBUh\n        TzcO+4n7aMR3HnCdl3L+MDIMJpCz0Hg8kP7vNgw6bYj7gGzFCkIMKkLLrE1VHQhKX1V3SCL+dwQgfiE2\n        dSzhARUJYF3oVGUBLF4NpjRdsED+BvoH2t9YAHgm+FEkBvDC8RlLV09ftmbqUsYANh08sfvs9RcuvHrw\n        yu3DV+68dOn1q+8/PPb2ezsvXn/wqz+8+vCLHB/LQUP4K8+PsgO+a0IAsigsVXxBdAeFJQAQF/RX8p/W\n        AFcCawldYwqQVH/LpfeftdUgeAG4guOE+DKnA9gNLQ/oF0UvkC16HA2gTOyTV7BF0iMkgQGMV+SB8TAC\n        JJ4s/AEmoJueiltlkWIAKKSRWTfgElwdbzkh2AVnAXk5j2XUu412j7PLNltsvdKm9YBPh0J3s/YyY78N\n        4ADivjmUWUCOFnKMXu7WWmyjCUBsU4CXCgek20aOcADsj3xZNwCl30zXE6PEwO4iy8QVWyyYEXQKFeHL\n        SqyiQaR9O96S2GiRAPTbBNAxT6aUFQL3VMgSsyK3WeY2YWRk2maW28xx05rJwpOU8QWS4ZPrMsLEYnIA\n        Ud5F77/fMtPsJAF40NDDjwwX8F1yeJTwxysQVhz0DOGGWH6HxddCYhwAnQGsLih9aHBJt8dgQVtaCcB6\n        GBNeqn45YMCALEKkHrAAMB6ojVd0QqSL/0eSiCRWnAwVkCd0qHvQAwMDTvQ7TGOAMKQR5cVbFcRZOgnA\n        1B1gAn4k94+78kgQuLC0atqcZeNnzZg4b+aFa5d/8LOfPPz4s5Mnzm/YsnX/S3uPnX3l+KlLp0+eP3f5\n        4qHDJ46fPHn/wcOHH9575+57F169vfapzaPGT5w9ffbk6TOG9IweM3JKRUVlIiv37PnXb91+q3/8+I07\n        Dy5ev2Hc9CnFpRWBSMbm1dtvnLjxwbsPfvW7Px44dKS5vbOlvXXstJkjJk1pHNzd0dc/aebivrGT8otL\n        8/LLaupbamrqcwsLMwsLcwsqCgorc/PL0rPz8RHsgMzsAlBOIjM3t6isqKyysLgsEom63W4JxlL1A9rk\n        jx+gzGgwfUSAY7wCNIGMLKpDTPQFWJzHB3XN6tbRUCQSJPKK80fCv6FwIhxND8czQ5GEuPsBuMy0ARAD\n        3LncjK52Fh5Aw+ShcJSqPMyUHnp1AlHgjo/RXfaIKQCITwDcGX5AY0gAOA7hT9vCH4r7g3HlkpILyf1w\n        eRrMkZiP1gmmBeLjNkAGMC/wTRkkwEiaMiSbEHP8JfAr5gIX6/L2kgUq1M6RyS2d2SkEQOBW3nyguSxp\n        lkV2TNOUBBuiv1vKPoM/OIzxGHr2B0LBQgBJx474cBjXVbgvTQ4sZuPQEYS3BHc1kuhPma8QX2p/DrBC\n        khKYFOSkMcEUYVgAjlSNFoAEgdWWkEms/9/Qn03+GUinWABvPNiy/8SMpWtAANOWroEFsOmlE7tPX9t3\n        jkbAixde33fu1rUPP3rlnfd3Xrh+/1e/u/rOgwy3jb8Tr0R6SQAqDDDABDACZF2YIyAZQXQEDbTIQJE4\n        tRogJnyQrnMtGGvH61wClufSAPdVAGsBuCKpMlZiArshXYn+igAgYyslS4cRXXETNYgRANAH+quROBHH\n        ynmCeWBY4G2RqOYyKHc0wf0iLubiiYByFW94RCRoJUw2xafM/AEQt9uwAMw2j9nkxi3xThqg9JnVw2Bs\n        s0j4MW4uBh5u6WPcjmpW/Neqba3e7ah36y020T/HbTS6Wb2n2c3cfKB2TBxBKg5RIin8DB3j0paJGQa7\n        WY40C8AtCwvwFSpkk5YaKc/ZDp5gNVM9h+57E2MyXCw4Cslf4Nbz3Wauxwncj5JpzE7LLHGZGZLomS2E\n        wc0GQAAuMy4yHMeWi3AfsAxlAWRaZtxlgiG84v33if/HT7883f2ATuA70F/lhiokBQ3AAgA3oMfnYicQ\n        HODrEbcMBgD0wRDAerAOjQCitsSTRcID95Uwx1lEZ3kNqiQfIQOMAQkB3CnzFZ1Idc8wJ2eoQHGDV2c/\n        3tL1BD6QpQO4AXxkag6nJuuBB66CV1ssgPT0zMVPrHvuxaMrN6zd/dLeczdee/nwqXFjp7YPG7Fr1/5j\n        p18+eeXCqes35y9bMnb85PNXLl25cfXZ7TtWrX5q/9Fjt9965/Kt1w+8cvLMpZtvvPPh67defW7zrgMH\n        T+/eeySWkTNxxpwXTp0trqmCKi6tri6prps2Zs7xfce+/sUvrrzxWm1tG4tAlBRVVjc3dw6tbmioqm3q\n        Hz2ld8yUsor67FxAelVFdWN+WW1OUXl+SXlhaUVmdh4UeigUjadnZ2YXZeQUZOYVp+cUZ+aAAmqqquoL\n        C0r9gaCsAWbGPR0+dLVT50oCKKU6FwqgBzKZIWI5lhxQACuENhQ89DWQVHnJQ5F4JJIB3JccfNoB6KGv\n        n/qak5NLxAUEGPX5g2QO4LK4egjfwGVMGAGygwaECfgapxOJcwLTBcr9hG+R9lzxizG+EAgmJtYGjAYG\n        J1QYQGl8fi/micpVoPFh3zBWwaRVfBHQCZ37EgVxp6WBEgW704QGKPCZG8O9fZi2TwkPvc8Ufmn00tD/\n        wyZ7l1GwywJgsQPo8acLCAjOs4RIxPkjBMDyn8Rr8f4LfCd99+IC4uScn9RCAhBnDoFe2QEK/ZM0IHww\n        QADkEmYTOXGKrBExTIdmdI2cMHPJaqaBCgGQpRgGT2L99wjgUQvAlko5f/vB1gMnZixLEsDCp7ZuBAGc\n        ubb37I0XL76+/9yrO05cufbBx6fe+XD3hev3fvHb6+9/kp1GC0C2hGTif9LtI68q80eWg1H4q1flCCIB\n        KP+PLAWQBWJMCc3WWfct3dCzdC2PiUDcFgYKXYQ/qzUUOR3ljN8yZ1962C9gDYFsKgcRjAA0sALOUtgN\n        xAd/sK4Dp1IOJbIC0RPiHbOZRoVJXz8gHicywItXnIsJJc+Sk4AbxPdSY7P4fpNbb3cTjlvdTqbZcB8Y\n        Bn7R0N9ucw+AwbbR7zZGeBxj6PzRayyuLQBbNHu0Erde6TbQijw8qLHNAjfjrj5bT9hcAAxuAJfgWrAP\n        8i0jBxYGQBzcICsGCiwzB8QgfIZHBBWvwgBtLmJ6NqCfQp4ppHlScRoWBngFfJBpOTMss9il40u1WiZA\n        H4o7Kvk8QTSeZaq3Pln3C9APWrQA0GLiCAJbxCXgDM2Oc1W2D7FYfEGS8Untb7nQyZXAyvnDGADXCuhB\n        0wGIRwOUQ8hz2S0kvFgMjBaItAcBKPnvcxoAZcA0CABTAZrRIPxdkqvDSs6C40q5ByQBlKpfOEDNzKtg\n        QnH34ybxVjz+3PKF0E/bQof8FwuAVMGpSFEOp2QBDRsx4tDJo0vWPLl+09Z9Bw9u37Nv98EXn9+xc/OW\n        7adPnX7l9Mv7Dx7c8vz28VPmjJ80Z8e+g5evXTl96fLJM+c+uv/gd3/8069+9/t3Hz744VdffvObbz/7\n        wQ9//Ztf/+Wf/3n9xq3dfRNu3rgzb97CsrqanMyCUeOnr1q/Oq+oeNysOb/+3W+2PfN8emZBbVNrTVtL\n        flFJRW1zfVNzWWlNblF5QWlleWV9cUVNQWlVRUVzVXVrcXFNbnFJfll5XlFZRm5BJJ6IxuLRcCIWz8kt\n        qojGc8OxrFhGZiKRUVpSVVBcCkBk1Wjuq8XSabD9odABnQGp8wMyEAHL6nJ0ldAbHlSJoWgMC8t6WoAs\n        0ZzJlMRlMQuA+CEwATiAheTwqT+Mfi8QFkoaxgWTc8gfPGA4ly6d7zz4zN6he0dwn8eBUHownIDlEQSj\n        kE5CHC/Q74+AObgIQBxBIBuMJweIV4fEQ19WMEgekpUK9PWzwBEIicuYwUZMhfKxaI/CbtwfcNzNlckQ\n        7EymomB3u5n6qVQ5FT09P+LGAQdQ45MSZJhS92gMusjSLb4l7ov856cQ+KwVaiV3dU7aAcRxp0uhv2SF\n        sr4fBoMYlD9H4T4OCO5ylmh/RQBJVqD2V4FlppPasBh0PbkOAI9RBzmQAJIo//8mAAYDxAYiAZx7HRbA\n        8RnL1k1ftpYEQBfQK3vO3dh3/taBi6+9cO7VbUcvXPngo9Pv3t918ca9r7+9+eCLfNkPQCQ/CYAHEgag\n        9lcEkDxgJIAckKwMQac/oD+saREpCAHtnymLgbke2GTMtszlKHZxHQD0LOt0CmpzgS79+NTvkPbQ+0B8\n        keomDpQjqIq1OamLKfy5RFaCuhjPSXgiwL1U9o2pdDl5luqhKZB0IlW4zELhALyF2EfDzGIccH1ALfW7\n        o8HtaPEA681Wl7PaaZZZWp2lNTC5k2mgJRIPGGkbQ93maLcx1ObG6x2WVg5A9zDwW+TW4249YGt1xHoz\n        YZtut5EGvQ9WsOiSKpSs02bLUSpLgpnuKTZBMVQ879OEuZAndokiMxwDmnHDjS5nqWRw5nH5rgkVDw4o\n        lHoSEdIYnhIZItdlgkVAAGAOwH2aacSdJgYk6NbXwQQeFziAOT/gALqALNOHA7KCDvQPM/Gfzv0Akd1h\n        Eb4Z8sXbpMPHRR0Ne1RxA3Q6zAIWasanJABivVLrHtPg6S7Da3DZsM90gCrQA2OCTCCYbiahn+N9BsBa\n        B77DDvAT3NVaAbEbTAMHeEstr15N2go4MAyHLr4gHPtxUV2zGABgo3khY9Dw1imBAXzqSEkpKikdPXZ0\n        T//ohU88vWrNxueff/7yO+9+/NlnJ0+cWPXU+qMHD149f2Prtmef337o9usfXLny2tkrN65fu/bh/U9+\n        9YtffPH5D7/44sefffmjazdvXLvx+ht3Htx+8+7N26/funXnvQefPf/cS31DJ/WNmjS0d+QrJ8598vD+\n        xo2bP/riR7/945/HTJ6VkZtXVdVUVd9YXltTAqyvrKuoa8wvLk/Pys7KBYxXl9e21DZ11jd2lFTWF5RU\n        lsEgqG0sqW4sKKkqLKworayvrO8a0jOuvWd4WX1jRUVDTX1TaUNdcVl1MBg1TUvTzdRBmpZqDHI4HIbh\n        8TFCIHgdkAJnqqSBHwIZAApgFdxXsVPKakpsOtCDxFkcixgHsnOtAD3y1O/BCMggAeCXMnNM6fEFA8p3\n        r/xI4ADBcQXrAHGyi5CEkAF5JRYKJ4LRdPAETQpcJck6TEKFwMclHlkktFGCMTEOxOEjGUpi37AmBAwa\n        3APQX0wE9APy2EPoJweoyK3UU8K3JojbeDvgnElqf8K6yy3OfcUH3B5ABigHDp1CtCEkDqyOuVhMJuew\n        galcIvyB/E6F4GqHSII+cVyhf5IkpMCPDEijASFl4/7WLGCGKK6uPsIM+FTTjaGjJ8tK4KgUBxkA+gHQ\n        H2hJPlAfgddTzr9xf+t+WADrpi9XBPDM5kMn95y7+YIigLOvbjty/qoQwA5YAN/89voHn+UGWA7apw1C\n        Ew5wQPs/aqCBAQIYaA5wgCOkaaL9Kf9V42aQuiZxYFaAANAXubQiy1FsOUpcDgAcc4EE1ktNLdfQCwz6\n        5dVyrXKiP10fqlVbZh0gW3Z7L5RsmQaJiFZZWiXrvollQFZgaBfWgziFGB8G8koJT07Fa6kUTzqXnDid\n        xCPzVHK/FMxptthGi202W2aNW6u1udV7ve0YJ7vvllusz9xvmVPc5kTbiZHtbmC9o0qcP3luKH0zza07\n        3TAFcLoRcethN5cIwGjIt5n4D/TPdzO5iMVHxSBgjBqQzdxN7vkFKOeKXCcrMOMb4Ri4DNlexKg16/Jn\n        Q7BLalCB0wQ9YEAuWQHMYYZpIjhxjB4V9YWcT0haZwAGgQQD0OmSGABvVTgA/wK9siDA79LRgOlece/Q\n        gSPZO4Bsorbk+6MBzT3AesnqAaCDOeK0ANhJkU6sZ4Nst6D0hQBUuTdMBTRHcwqXYLzQAOQ8vT3Aa4A+\n        INtjSHk4yiEGh/FRgATAaLAaoLw60PsYAOgHAUD1oz+N8YMk4qOHBzopAZ2KEnCKrbHIVWNTe3t3Tyge\n        LyqtKC4qbmxofWzh6kMnTp06e3bvwaMPPvnhH/7yL7fuvvn87gMHD5169c03T507v+aJ1ZufeubWa28+\n        /OjT9+7de+O9u/tfPr7z2Z1nL5x6fv+htq7Ry5asfvu992cuXjtu3OJlK5+69ebtn/30l1cv3fjVr3/1\n        wSefVtW0aKadnpWTy8IQlQV5RYlEZllNfWFFVVZOcUv70NKyaq8nVFRRXVhZXVLe1Ddi2uipswePGVPX\n        0V/TPKSla3T38Jm942cNn7po6uwnps5d1D5iwuC+yZPnLZ40e3Zvz+Qh3ePqh/TUNne2dnTXNbcWVTZk\n        55UFIxEgzaCUVN00PR6/z69q5vg9zJ70e7iJCnNG6U+n1pbGhWOSLM8coSCzbsQXxPxLAHckHowlIvHM\n        EHebAUaHvaxCQUcQCCNIrz09/viI6E8PPoQ8ffQhGgEEcbqSAjiGPcF0T1xRefNlNinmzO3WOBjMhGmF\n        k+T2QjEfvUaMHHh9PIsc4Jc9woB6dOvDrAHwMRWKyEi8VsAN5sOXDQK7CejKlS+1NwCsSV1vy14LdBMp\n        GgCgi6iXdH4AvYSOYWSw1gUGMwbAhWBJr84AByjPD14J90BwmYfmBQwFunQUDSizgECPt/jzS64DGCAA\n        +ogGCIMD2Cw386w1fejoSdMWrvSFYo/WAfz/IADGfnGrtALdzAQLp5x748HWA6/MpAWwRlYCP7vl8Mm9\n        52+9cI4EsP/sq88cvUAX0Hv3tl+49uCXv7v89r0MLzeFp/YfIAAF+mg44JJgwX3VE5KmOCCsNgMQ+S9N\n        Yw6oxvqRj/Z+yWN8UpPVW8zWh2YHcBebusoRwlsgNcAOrVJ26BWwBmIyV6fI5JreMtIDPuJevrVSDkgI\n        g06kWlY7oKhn9ifDyDAIGHCuBOAC6G2TYWHMYAL0WXa/QTIyK216n0AbdU6z2UVVDjug0a012ZT/zZbe\n        T++QBmbqZuoOF14NcxvDPGabW4fqr7C1fLdW6NbAAXluPdut57r1mCwOqHCbDW6ty9ZqbD3P1rMtLdut\n        Vbq55UDc1otsJjtFLTNDspVwkyCAHBerNeRZVPcZ4sFPAGR5QIFPn75kBwHlcZxFg4YbyheysISJU0Ki\n        /SH5MQDM4ZfNVcAEAFS/0wyw6RHgshBGSDggBD5wmV4SAMEaKA8E96stWcTJA9SmL0jcQbQD0GMxlqDy\n        fJjpL9ofmA7LwAOxz5RNXjRtoI4/ZkBPmsQS0INhuvAEwN1FOQ/tT8mPGWwWj2MomB4e7jFAknCzUARh\n        XYCeTOCUmDAwXSE+BuNvhOuQeZb06CodiK+yAoBjnAwBpGx7fvvXv/vlM3ufX7T+yclTZ9Q2tupOV+ew\n        kYePX168aMO4qVOf27f39nsf3nr1jQO7Dhw4cPzo2fNrn9y8bvVTp69cPnXr+uHT569cvX3qzIW9L+7b\n        c/zgzMWrRo+deuHi1Y8ffvLE2nUtQ3u3bN3//r3P3nj3vXdef//2zbfqB7f4w6HautZEei6MgNy8/Ory\n        lv6xs3NKSqHwGjvaJy1Y3DpydMfo8V1942KZRRl5ZRNnrVq+dfeMZSu6hk9v6xjTP3bu+GmLRkyaNbh3\n        fEN7f03L0Lqu8T0TFsxetGL+guWPzXliztI1M1evW7ZxwxPPPL1gy9NrNr+0fsP+BUtXDZ0wtby2KZae\n        BZ43QANpENyAUUpsjz8k3gxmc1JZM4sfipthVSCdx6vW9DIqG4gyFBySNPxgOBGJZYaiGbADQuE44wdh\n        Whhp/oCEbcXpz+hChKFgcc7gLXGfDcaExHvpCxL3PYMWuATlv6h7DAZhBGkQcNUYEz1pkfh5h7gxMU0Y\n        P8CJyudD3xdQnomeUhnbHyIHAAeTXhru4iJhAKI/nfiAe/r0GRAmFlO22y5IeyEAEoZqYiioAXjFhIxa\n        B/hNmdVDnhBLwgbQq9W8A3aA2iQSqO3EAatkgzAwidL19PngmJ9yqTA7v+8UEgJ4xA3ShDCkMqim6z2j\n        J8+QUhCmE7f0Nz4fFfyXJmukpeE4LRBJOXf7wbYDJxUBTF26asGGZ7YcOb3vAglAYgC3nn0ZBPDw9Hv3\n        1EKwy+/cy/S68YdC779jkIcrADRVAeIRASjcBwfgFccqAiylQx0xSn6iP6A/oekJyH+Ndd9AAKoWEAlA\n        tD8aOUA2/wITgAPQTzcOQY07MgLcK0X+N1pmvcusoOOIvpEyKf8JxOdmjZJTxNW/lgZroJq1H7h6ALNV\n        SD84QAl/TIWZy02m/TDd09KA6Q0eTZbUOqX0P51OjS6j3dZbuKoLBKA3WFqHZfQxs57F4DolyxOsAOao\n        9xqdHrPZzWycErcWsR1Zbq3RrXe4GZstdBtBt5nHEg50HMGYAH9k245sDwgDzch0axhfbHMv+LjFvKBy\n        i8WZofGjjPRy/wDgOECcVZq5l4CZaTuzRPiDDzJhJQhh4JlA9edwYZczz3LGpaCb32XGXDq3UZT9VdDj\n        cRk2/r0RtY0wprXMgMXVAND+QSfQn/1gC6A2tH8kWezBgeOQi2WZXRISAIj7Lc3HihF6Gl1DXDoADoiK\n        ox+AnsZGCQ+sx0cS75UsfvIHg8wgABgHwGLMJjED4D7VPQaAGID1OBeWRBLrecwFYsB0TAI+wIlAf5Us\n        BHA3BqQ9Xi3dAaBHP1R/moA+OmEi4AAckPQOSQxg6qxZJ8+d27Zz55EzJ9+6++5rb7+7ZPW6/Nz8CTPm\n        7X/pVEdbRyDNN27a1FfOXHjz9t07731w5ear5y5cP3T8+K5Du7fs3PPC3sPnr934wZc/+c1v/3Dv/heP\n        r3xq3oonzlw6d+b8+QcPPj517pXXXn/ni69+ce2NN377uz8fO3U2q7h44rR54yfPL6ioK61tzM0v7B8x\n        ddSkheFE3oRpc199984zLxxc/NS2c9evv3zq6vhZK3LL6tNzyof0j5k1f8Wk6Su7+if3jp4+burCkTMX\n        jZw6v71nZG3TkLbeMT2j5/aMnNY3evqwkRP6xk8Zv2De/LUrF67eOP2JTRPmL5u9eO2aDXvXb39x8dZn\n        p85d1tk/Oq+owsndxixAeYA+/RgENRDNzfI4AA6ujSLIMklUHCyy3zoQ3B+Ki6c+AuUeiqUz6TOaHkSj\n        Kz8CVoDSZ64R1x9QyJM2WLEZByADqnu8qkr9QHZYEsz1hJb3E558kjIkvn6wBe8HUOv1cf0aAZ113zCG\n        /ORVCT/ScJ/4yCt7s4AAuDeOh3sY8Jj14KSKpwrVkhvSFJLKWwZ+qfqVu592AGQ+YVqkPRurAJEDmBdE\n        /JUoLmYWX5Pst6UI4JELSNkKKuQryl1xAMAds0GsA9zRT6An9NNi4EU5UrJCSQDyKQngOy+QurSQlluH\n        XNLN3rFTZUvImKSBJhHfwwdFvT8A+t8jBloA3xHA2mkkANYCevrwKVoA51998eJrL5y5+czh81dBAO9/\n        SBfQ17+5cf/zXL9fEQBwP+kCksVfgHhVAQJNoX9Y6kUrAsBBRHaAEfR3xDUdLVPqgOYZeg4L2XMnd6n5\n        Y9AUMB35hlZkENMZBqApAPTHAT0zUOisz2OxyE8d0Z8Ijo8A/VL2hyPBBFwBQCZghR8AKI0DCQwA/QX6\n        cUyqqHJpAMp8kwsLVNlkrr0iYRDxZQGtDgsDkwDZW2yj1YMDZzvTPR0drP/DOqAdlgZTAHzQzhpweqtH\n        6/Fo7W4tXRZ/Qdq73Xq5G7aCkWHrOW49022UkkUcGFxo62Gb8h8mQonbLPI4cYAx+W4j5DZtm8K/FbLd\n        yZo86Tb3bwF84zVdyvXADiiwnPkuZ9DlDEkuULo4gqIuHQc5dOs7w/T+m4lkJg/dPjAFMBuQHUIbk/gp\n        203LyaoPAZajYAUIUAUG+wDoJtU6CAAoHyX608sP6Ifw51IACQuH8ZGL+8lgDP3+EPWkKMI0o7JgCMkF\n        om9HWEGVfSZ885Y4OQgAb+nzodgnB9CrgzHCEBhAZCfZqBR+Jf9hAZMGQDDU+wB0FT2WeC8gXtMdLoF4\n        rzh8GIEQYlCqHwSAqSQAAP5gGmhxec3o8dOmzF60bff+W2+88ckXX7370YMRY8Y1d/fsP3p8waI1nZ19\n        g4d0NQxunr1g4SuXrhw/cvLitet3P3pw69brp06ffPvdd37zu1//4he//ujjT05evLRg/ZNz1qzeun3n\n        tRtX/o//8m9/+uOfPv7hZ+8/+HTVpt1L1m0dN3/W4BFjrlx/7fy5y71jp8/btGHeE+tqatr6xs16+fS1\n        X3z75w8++8GxVy59/NHP/vGf/vOlG6+/cPT4qfNXFq98Kre4LBxNNLX39oya2t43tq1vTPvQsZ39E+vb\n        usprW9o6RnePntreP661a3TrkJFlDV2F5TVVtS0dPeO7h81t7xs3asrkqfPXz162ec0ze9dvfmn0lMdb\n        +8bjqhnZ+abTCegHjFKSR5n4L65z8Z670+hkZ7EdoDklts9HNOciL64SiIdjwP30UDTGdVtBlRoEWA/z\n        LBaqAyrhICS7btFtQv4IMNdTXEDcjwyXxjwsWicZnxT7QSbv8xjQzzJBarmAZCUxxoBPmfWP26MrhtaA\n        8vjTEeTxMk1TPqKXXyLh3EgSWC8QT3+OcukwEz/px1deIDpwpCVxnOYCHUSPxgwEfjGYuZ7o9oEAYHzg\n        KvyUM9DtwwBvsgo0kJ3KXfFKEvEtgr7ofdoB/HTADmBPEvFxPEAAjAew0UNFDqAbSjecuu4aNn76dEUA\n        sAAo+dlUsdVHBPA3HMCEYBAAXUAnZi5fN335mmlLuRJ48+GT+86/9sK5my9ceHXPqevbDp+jBfD+PaaB\n        fv2bWx9/mRcKKQIA+vvZGAcOyIGS/8r1D8Qf2BiADQdRjXUgMgxHusj/dFaAoG8nCwdgApOrAbJBA6zQ\n        oOUZDin9Ty98Ed019OEA01X8Fq94W8eyPEaZbA5TJ+HcUgaKGe8tMR1Aedl7nVXyxQvE0+k4kgqgJbQV\n        hBgkrwbEwHXCUgVoiNRsIFvIDu/1LsYJlEivBTcA/d1OmAXA/SluR7ftaLS0XlvrcztG2PpQqf1Z78ZI\n        rdR21HiI6RH6gjSfxwjZWoZby7X1mEcv8XDMYIsVQ0EAkPzpHi3T1vNtM89j4sQqieIG3Lrf1gH6BThL\n        8DpbnD/pTmZ8FlkmRH3MydgvQV9VbcMYydsBdmN8FiuAckEvevA2RLeP4XWaYAIJ7bIAA1GefEDcBw2g\n        4Tgq/h+AOEaqIg2SDAp8T1Z8CxLBibwhpyPGwAA/pUOfLn6mdQL9PVynwh60AAlAyEAmhP0RGBjME13J\n        FQMwAsTbQwsAbwHQhHtFABg/4NsBjuPGQAA+08ApMBpUp19SQpOwLjTgFPRPxoHxEUcaNv5oWN4UpELP\n        EsjAo9EC6Bg2btXmZx5fuXLekjUTp0+dv2T5M3v2Tpg3c+r8hRcu3di6e1fXyBH5meU5hXljZ09ZtHJt\n        b/+Ivbuff/jppz/40Tc//ulPf/arr3/881//7KffvPrW3e0vHT556sLRYxcvnr318Sefbd/xwto12y/e\n        fP3y9TcOHjm/d//RrXteenLHrrsfvvuf//Ffr16+u/3kqTXbt1fWDZm/bM17n31y9PDJ6bOXrNm47aXT\n        Zzbu3TNu+uwFy5/Y/fLJldt2dPdPKittDsfTiyqaG3pGVzS11dS21zb3VTb3VLd0tHaP7Z0wY+iUaSNm\n        LVj91PZpC1blFtQWFNdU17XW1XW3DB45atLkMbMfa+2b1Nw2ZuHyZ1c9+8LgYSOLy5v6Js6uaGjUGSLm\n        2lroemAuwBca3+MPAkwFOxgrZraoXwoEUYAHvN5AMBCj24eLA6IRvIaisiKM/hnANBQ90ZlMwK0cid2Q\n        6sodJG59yfxhNTfxBXHFL31K9BpF1QIxLh0gKwDxge9B3I+6Oms/YAAuBIBj8R/cGwMGshiNXIVPPUxM\n        InDTIyShWhH17MEBRf2A60Y+FflvWwBSJeSByErme2QVGEdiGKEf+J6MJaATH8kulbKbPBCfXiDhD86G\n        A4+EFpKsgFfR8grfCf3U9RD+Cu7JEEr481M2IQBBfykKpFxA4g7CH5immT1jpjALSO0JzK+vEJ+kqzw/\n        jItIdCT5kQ8cH30UA1g/ffk6IYAtmw++su/Ca/vO3nzh3K3dJ69tPXT22od0Ae26eO3+N7+59cmP88Jh\n        EIDA/SB5ZS4QD77n9P8b4c+kT1kBQOHPfWAyZP1Xps6VveCAhIZjrgLLYlKQAWsANoHaH7hIwL0EgE4C\n        YA3OWsuJt4VOBzQ+cJzqnsn+Rp1Lq7AkumvSjIDRIEECcgBexYnPEv/Q+xhTgmkxoaA/aKDYhN2gggRm\n        k8vZwBgsTneWMobsqHYaDZZe59bIN7YUknOaVS7nKFufbWsj3Fq7FP4c4tbaKOe1NkvvplfHUWJpJSQM\n        vSbNKPEa6R49aGvV9P/olR59iEcf6tYa3FqBrRVY4AmxAGAHWPT+l3toIqRbgH5HhtuRbRs+20gDJdDL\n        z7oREVbpcaYnF08ZmS4z22bdniyR9nhlVo+ALCyADEnoDALf6cen/BcPDJf1ovEAZ5nkBlgPAZfT5+Rg\n        qQXNt8BrxgZkoxgodxxD+OM20uniJ55C78MsgPCnn91kpSC/5Avh3iIuhoKZFQroF0c/OAC0gbeYVkl4\n        tWIAn5IYSACM7gL6YQGACWQfMcNvMgKBT4UASAM0FJysUIQDzAYCQCcEPggGul48SCQAJfbxEQmDpgCw\n        3oBqkrxSE3dLQlIDxAU0dPSkiXPm1NbVtXd0D+keNrx71LCh40oaaoePH3n54pWbr70+9/HH2zt6xs6d\n        t+KpJ6c9Nm/YpPFDe4e3D+7a9NwzX/30x1/++KenL944cuLkjv0v7dl/9Pr1148cPH/i+JU3P7y3bcfe\n        XbuPfvPLb//61//6X//6b9/+9k+//NWfPv3i64PHTr64/+SVm++dOH/52JmzJ85f33Xw0PTFi9q7R4wY\n        O629d1QoMzcl1RmK55Y3thfXtJVV1PWPmT538ZbeUTOq6jurGoZWNHc0tHY1dg6vbeutrmsvq2yqquuo\n        aOqsbIEZMH1wz5ialqGdvVP6R07rGz+jq298b/+kcZMXjp22ZMiIyZ1jJz25bd/ufafHTJiWU1LeNXpC\n        cVUdRGsowrwdQX80ZluKPyEgGEdkJ5SLI54uHUJzjMpddm3EW9CALxCE4iYHqNW/4sYRhY63Yhz4gwG8\n        MiTAdFIuLwANiAsoCLMAl2YiKelBzg2yJgRsAq5IwCVoCgBtcRVYGPTCM2wgqa4gJCl6IZfGccDtVou/\n        BP1ZxA3inVXYlJZPbuAlIA4OQCNGCxkIdj+yAFg/2e2lo194gj0kBokni97nbl7kGBKA2BY418VzFRMk\n        5b9QglzlkZNnAP2Vj4iIr5KC5KOk9udxkgDkrXiWOB6EnerQu0dOVGmgBi4gBEDoF6Wv3kpgPFkEgj8l\n        3XdCANtAAMvXqiygBRu2bT54cu+5W/vO3Xrh3Ku7X7m29fDZqx8+PEUCuP7gF7+9+fGXBeGwJhvC0OMv\n        TXmBHnl+vt+g/fEa5hIwOn9isgyYCaC6lmU6IPxhB3BrMNkQGBZApriDcCwcoBcy3YUKvVgSQMXDzqW5\n        UP0VTBultAdeE/1V5R8WC5LBhHuiPJijmDt/kQ+qZAsw2BPFYh9UWbAnjFJyjPIFmQ0ursWtlpBAldPJ\n        +W1Hlc2dWGptE0ZGjcssNbmUrMs2Z7jN8W6ty+0Y5tHG2dpIm5WZG2xHk621WCSeJstkmaA0rSfgrPC5\n        8jx6FitAGKVufbJHH+7RqzxgAi3bdsQ8jgIuMjBqSAOOHI8e9egRFgjSYrYWtY242xm3YQ1A15vA94ib\n        BAB0joioR8MBNH4+I8bcThK6PuA0Cdw0C1jcLdOSGg8uE3AP1PObdNdA4APowQeQ0n4nU31sp2G7nFGX\n        MyYfxV1Ov9MZTCK+BsQPubRgstqPDsKgdwg9TkYCQAwMA4AVXKzjD8MUV8G5MAVki0eMARPwEsB9SQbl\n        W5aCkPgB7gE0INwgpMLkTp3ufvp/qPGVNQBAR0O/U6wH1UA86ASOS7SZlKAwnbk9Av2gB/T4DYcK/7p1\n        h2SgQv4zE8llqlXBdAE1tXZPmTu3rWtY++C+ro6e0b2jaioaM/Pzi0oKu4cPO3zy3A+//NnDz364dc8L\n        3UP7ahuaZ8xdNG7a1Ky8vPKqBqj1s+evXDhzdun6TRNmzxo5Y1LDkM4n1mz69Ic/+fmvf/H3f/n7v/6P\n        //53//TPX/7s648ffrXtmSPrN+14+OkXr969u37b/jffe/D//D///t4HD6fNWrZkxealyzfWtQ1vHT5+\n        zNzZ06c/1jtycnlLd1FFe11Tf0v38OrB/c394ybMWDx84oLGtlHl1S3lzR11g/vrmnqaO0c1d44d0j9h\n        SP/kigZw2Pjqxo6M4qrymqG1LaNqWkfUtPW2d0+cMGfFwg3PPvnMnrnL1sxese3wmZvnbt4aPml6Skpq\n        S+fwrOx827aDkrMPNPf5gdUh2S2d6ZhA1WSYkVuJ+ZmOyYygKIu1YbDwBMZwzVcQYtzPepyMITNoTL1P\n        x06EMdtAQFA+QpQXxA+GEswsCkWo/ekdinChQCgWDCaYQvqILWgfMNfI4wEh+dMCAS/tCXquaJEw9guk\n        TpPUT65MZtBCHFki+enGASgrxOdIinq8HeiXJnu/yBg5UFvBiNKnL0j6VTFnGc9pPeLS4YJhtVCA/EEX\n        DbU/mIA5oOL3Z3BYeYQEvgXZld7HgKQpIKCv5L+sCk4aCmhJMsBUMglrS+i66dBMCBcJAoMAcLMK95Ou\n        Hrp9lB0gi7TZWCwPBCAuoO8TwPwnt24+dIoEcPbmPiGALQfPMAbw3ocggPvf/PbGwx8WRUJGSgpgfYAA\n        mAvE+j/f4wDxAg0KaYOU80e8/4R+WQgG+Z/KotCGGAEGhT/eAvdzTDRHrq7nC/TnqbROKnou1FK1GYD+\n        sAmI5lKfGRZAvUXxXsxNyRk/KBajAYq+2nZU21qp6ShyaqWWA3Bfy9W/XBpWBRXvMssx0uD2MpzN1hst\n        o95l1tkM/FYxs0gFkI1am/n+eK2E/JeMoxq33ufWJrj1EW4u3ep0a9PcjrluvYtF/7VOzIBm6aWs26M1\n        e408n1Hl1XFWhltzenS/G9pfB21UcxGAHrMdUY+W5dELPUa2R08A+j16jofOooDNgnFptuZz61E3DAg9\n        ZNGv4pd1XnHLDNvOmJOUAOx2O+mxCQsBBKm7lbtfUvgltT9mGX7LCTAFRAL70iR3KOpkFAFQjmFei157\n        r4upn2kup5cRBdPrZBgAcO8SRzyQOihxYAh8l4u5/+CGgBMiHZDNkHKClACwprQHJTAgTCZwSBCYtIGG\n        HqB50CQ3sAzcAI5Lmql48wXrodzRGCeQ8s4AfYp9UJQpjh2aCDiXNo1CfJzlJoUwqqESh9AwjyIDW9dt\n        TbfwauheXXl+lDsIw5gtile6gDqHvXD46Lotz4wcOX5w15D5yxYNHz8hnp6RmZU/dfr03YdefPHElTff\n        /mjv0RfLaiqBhtV1zfNXLZs6Y0pjbXtNa2dHd//mtc9dfe3ua2+9/cyOZ7LyMof29r331gfvv/PwJz//\n        5V/+6Z/v3r//8qmLxw6d2/bMgWNXb371zTcPPv/s/o9+9Nb9j+99/OXb7366Zt1ze/a+8sad+y+8curY\n        +cs//Pqbb3/755/85Dcff/aTPXsvrN12eP/5q8cuvrH35dMTZi9s7h7V2NafnlmQzqXCtdW1vd3Dp06a\n        u3L+6q2bXzi6/cDLL7z8yuHTl7duP/Tc7mN79x1bOH/15MkrHlux7bFN25ds3DV71a65K5978umdV2+8\n        euuNd89duROKxhwOrbphcDCccMvGAF76CsQJ4ydMA2IYeoXcFucP821EkhO+JcdfkQRLSnCVFkFZ5DkT\n        QwHfAG7MLGJfhDyZg8t9AevE9yBYBKYAiIdRaGI9WYEkJMNYNJRJpRGwBciG8+Me6F+i6g8w2EDuIdzb\n        Uu5YrQbAPeC7AK9Fs4tyZ6PrhkbAd34hAH1yDEV60s+jmIBNRXFpEJADFMqzEDSIELBuytJcC+aFshi8\n        jBOgKX89zlVvbYkrAP2Za0RXDwBdLe4VfJc4AUGfqZ+WWjfwvSZjFAGIaYIDwzAdOl1ALAURSZAAYOXQ\n        WTfQBgiALiCBftWSBEAXEGMAa7kjGAlALICzjAPvOnn16YNnrrz/8Mz793ddunHvm99cf/hFcZgEAIgX\n        IwDQT0cQ0Z+vSQIA6IMAhAN4rGK/aFGNG0NmmqncJUaqQGdzKxgt16QRkMvmAI4XGvT+A83xCkAXGpDY\n        LyO9JiR8EXS9cgHJaizIecj8ImYKMTwARU/xbmmggXKDNRu4IheDaSg4ShkBxrRGmaA/bQiX2cZKD+AS\n        bgGGxqo7dmqDzYpv9ZYDDFFmaeUWlwQ3u/U6j9bp0ca4tdFSCa7brQ2ztUm2Ptyt1dgOGAE9MBrcWrrt\n        yLe5Y1eDRyv1MAE0BBD36BVevc2jo7NGrIECqH5bi3uNsEdPI/TrGAxiyPBoCbcetnXbdrhpB+gA/SCO\n        CbssIJphA7XNmMsJaS+V9wmO0PiEdZIEDAgTyA5uQKfiBp+U9AGgK7cPUN6Dc0X+hwnuJugkwvAA5T+Y\n        ANaAG2PoVmKtHqA5ZgNA+9EE+rkMmFmYtABIDywzxztJE+BmeR86nXAK1wMTcAXiMaEl9gFHivCH6kcD\n        i+ASMGig6GXJLicBbQC+leqnkWGxMh3Q3xQCEA4gDQDxCeWSlio95Bg6fziDJH1Kqg97xINEvz/rTifD\n        CbicKgfdNKTjpUNnXjh0aMGyBf1jR4+bNae1szcQiBSWV8xfvHLpE+tmPbZs187Dz+/dM2LmrFhmXloo\n        1Dtx4poNTy1YvLitsyuelVnT0P7K6fM/+/U3H7z7wdoNmyfOmnft8u0TZ89PnL90/4Hj//jn//Sf/vCP\n        Hz34wVvvf/bwi58//Oyrc7fufvCjzzfvOfz4wq3/9l/+23/8x3/8j//r3//uH/7y1Y9//uOvfv35J19e\n        fO3u7U9+8Od/+Jdvfvl3V1579fOvfoox//zX/3Pek1vzKmpKa7qrmrqbh/a0dA8DGQweOmHqvNVP7zn0\n        wpHTx89dufXuu+998sW9dz9/8+0HHz78wZ23799+5/6Hn3z+1oOHh46eX7vpyIEz166+fvvN19/55Adf\n        /v6Pfzxy4hQeAsA6u6CMfh5ZFCYeHubksOpOMkQMhc5Kogp8AfocQ20uiT1p3PVFiAH9oA02n48xUjAH\n        tw0Ix4UJon7AejjOrFBCfLL4RIidoAQmfQZwLV46zDVikQSvy9oSQiqYk9EFbiQgQWbVGAxIk01dgH14\n        i2+hljgwL97Dcg5c2MUUfuUOosdGhHnyLeU831Jf8yOitrhxxIejwraEeK6dZlBBMQQ1PpGXtSJcLnIM\n        KUTRhpLqKp7MDB+8JXzjREC5yvEHjhPKoe6VEUCZL42mwPehnwOUH+lR2ihrAWkGCWDpmlA0w7K5kZla\n        BJCkASEAQX9Zn8H2twQwa7nEAJZJLSAuBLu19+ytfedv7nrlypaDp69+KEHgi9fvff3trY9/UhKJggAU\n        xIMDfJLjjyYcwDZAAEkmYBBYtD/QP6alZhqpGQN8kKFr6QbLQWezJFwqrIEckIGhFxuU/CUmGpfyggAK\n        JB4gtaC5ICDL1LJdWglEOtGfJR+Y88OMfnp76Nm3xLdjMAWowU1DAcOUox+flmK8ySXHatuWNhZ3Y6pl\n        Pfda4VozMEQNU/4h2x3gErytsrUGyHm31kQC0Ls8+ky3Ns7Nnn5bm0IjQJvKLE9Hk9tRbmtZbDpQO9+j\n        V3sp6iH8A249y230evQej97h0VsE6LlO2ObKAIyJQf679SKPnuXVw5T8WsithW0taOmwBjJpEGhplhaR\n        UtJoAFy/rBWgNcCUGwJ9RIp9olOt7KWiJyVIjQfxIIEVYAcwEiCZ/gEgPsU7Go4p/BNOxpZBG2CIkLzF\n        KW7WCGL6PxDcKdIeTOAWeAVwM8MHaC6VhYCwAF+YCMBrCd5yJAggIOeKXcKQskWrhUiNGTAG/RDyOAtj\n        QA+Eb+I4J7fEF+TROSEZhYFrWgw4XTl/xP7AGAdd/zQRkn4kvMUrPiWFEO4p84VOuMckLoFT1HbE0k8C\n        KK+qXr1q26ad21c+vXrk2ClV5Q2JRFZ+YWlz++CCkuLK2pq9u3e9+9q7J07e2H38lVFjxkYj8ZqmwUvX\n        PTX9sdn1bYOrG5shmjs6e9Zt2LFn/6n3P/n8oy8+/+1vf//+J5/OXLRyw9O7b7957/qN25eu3H7p3K0F\n        T2wZNW7B0OEz1zy95+XTN86cvfGHv/vTn/7hn776+pvf/eFPt994sO/FC4sXr13+5NZtx08fPvPq2ctv\n        bn5693Pbj1248u6F197f9fKJZavWP7Zy+8qtR5dv2DFrxcaOMTPK6ptau0YtWLl+yRObu0fNGz1/6ab9\n        h184fmX55l2TFqyfv+L56U+sfnLTtlNnLh45c+H46Yt7Xjq+4bmjm7e+tHXXCx88fPjX//rf5y1ajudg\n        GAbAC5gbiMTofFcCXMpCMPOHoEzEVzBNzwwDBiz+E8RH9PXT+QMDQrll2GAW4C2XBDNCEIqkR6Pp0UR6\n        KJ5OdQ/bQqgFmI4Dho45Jy/q83EXM5lfeZmA+BT1+NTHRg8SKUFcTyrnhzsAc1tHup4kJdQPhqBaF4MA\n        sA7JrwR+sp6zigkrApBILwFdNDtBnAuAk6mZJADm6rCEA8mD3n9A+SMDAuNpXvBE1cgNlrh9ZBKZh68D\n        8t9g9X/I/+9QXhkZTpdHwgCyBCz5UdJEkNPlZoQAdIPloDtZC4gEYHuY3+nG16QZpFxAeCaSVhuM4vV/\n        twCYBkoLQBHA1s2HT+05d3PPmet7Tt/YeeLylpfOXP3wozPv39tNC+DbVz/9WXk88YgAxAVEz4+EgrVH\n        dUAfaf9IsiL0IFUJLlO2hwQZyIYwGqwBvmoqEUjLxADdkSVbwEPFl0ptBm68Lpn7IIN8WRKcbxglLq3U\n        oiqHEVDOxFByABR6OesnM5+nnJ4ickOVrdfRdcMNBiplURhpAPPLHlv1Niv5NLmMWrej0q2BABosZy2j\n        wUa1rVfbmN8ss7Uqy1FvE/rBJQ0eo9mrA8RnuLUx3AySceAlXm2hW+9064M9er3bAfQvsjWo+yw3CSDf\n        S13vFoivEfLopAWgV3j0EvqFuF6skJKfw3xobj3h5VLhNLeGlrCZ1B+3yQfQ9WmkAWbceywtZOlRBoSd\n        6ZazwHImmLippbm0uMvIt0zuMia4D6AP0zIAZ9C5DzSX9HxGFGLyEcAXrwkGCWgWZHEvePQ7MSDbpYMb\n        WCZaIgrQ436xBjADEN9HYAX4sgIorAQaHAL3wHEYB3FJDZIkHw1GACQ/iAfojzGAcqEB2CI0FxgScFKb\n        A5S/5wviMFwRM7hgahj08IDS1G14DRX71Vk0QqpNMD1UtD/6uYZAuAFN2QH4CChvSVEgdoJsRPujU40B\n        GQzinsB5Le2De4cNn7VwyWNr102d99jgjq7a2ubmpvZILOqyvBOmzz9//erpq1deOHBo09PbhvT2QPGV\n        ltYM7u4orW3sHjFi1KTRIIxIrGDeE+ve/+CjO2/cPXPh4r1PPv/q61/sP34qp6SmtnVUz+QFk5csOn7y\n        xIFDL63dvOPMpTtffPmbt9+//+6H96++8eGmZ/afu3D1q29+8f6DL159+96DTz4/eurqc3tOHjt98+rr\n        7928/cGCDTsnPf7Uzl2HN215ceXWfcueeXne8ufnrNgybtGq4VMntw8fO2z8/PlL1k5f9vTkpVsXLt+9\n        +ul9q57eu2br/md3HV+x7qUVG3es33No8eati9at37Xz6PFDlxau2pRT094/buaenQfu3PlgzIRpDJm6\n        8QftCMUyfHTch8OxWCDCcv905qjyPsB6FZINAdC5HRhXewnoA4sBu6wuJ/UkeOBjrR6eFZJkoVA0HI3H\n        0zMT6TnRRCaRnZ6lYLKkM6wNDGZ2qZgafuaMkk7AQBKa5kjJPQWKsbEEdATEgNv20PnD7QegeVVqEHHf\n        xzRW2/YB5SHbMRJMQHeNcvtwR9/k4gAMJqy71RZd1PJgCALugOOFlEBRT3qAFeAhkQj6CxmIq4cLvsRK\n        EF8TowVMFRUCoPBXpw/UcsCBDRpwJnOB2MMKo14/bAUSAIeh/ztnEW+DM4iDSIp8OHRn18iJY2c+DtaE\n        3gcvenxB0Bg3BhAjAG8l7hJLEoD4goQAbj/Ysv+RC2gN00APvbL7zI1dJ6/uOXVt5/HLtAA+eAgC2HXx\n        xgc/+/Wrn39dnpGhXEAqBqBogHFgHkD+OyT7k97/qGwJoIyAGPeDpOs/IeUfgPuqZekOyn8pCYeDTNoE\n        TA1iDihx34Dwx3G+uIDo2+H2v9wDvZG5+cRxaHnoeuA1ffRCCSXQ7IZECGx6h5g8SgeOhIKdmkR9tVqL\n        K7bqJNGTSwrAIjhwmTVOFnprdDMLE9Si+jG42a3XclUXF4gN9mi4+hhL63drnbZjgluf6dWHegnoNeLW\n        r/RooBNI+Di0PAS+vPo9eplbH+XhEoFWt16GtzAOwBAi7Us9WjEMBeC+R8+W8XHQAGZg4WgeY0zUdsAU\n        iFn0m4MMuKkATAdJD00DQFtmwnZCmDPHXywAEECEBoHps5xS1SeZ3ykwTQ4IOQn0YjTARADcc0lBJnOH\n        mPyTJgrdJ/ANREZnXEA5Ar0vCC7RY/CB5pEALz6VTuYLhZjxydSgGAcopU//D6Ac1w0IiwjZ0AtEX5As\n        FLCdDqA2fTIcBr5hbijzfOgjYp4PPVfMXBL5L0APZFf0QBznlvTsx1Ro9BHR4aMgntDPRsOCcK9yhNDw\n        kQ0jQKwBR0pKPJHIg9QvqeofMXry3Jl9kyd19g6vqKwtKi/JLyxOz8jqHD5yw4btzz6/b+3abRt37R8x\n        ZXJJcfngrpGDh/X1jZ+ydM26NRu2VTa0lddWbXxm17M7DqxYuX7b87tOX7ry0rWLExctmThpxs7dx49d\n        eX3Nk1tOX7j6429+/u///v/5j//4jx9/+9uffPP1x599uf/Iuee3H3nh6MmNLx5+7MnnH/7wp//+P//n\n        i0dOzV+04f6nX2Hkv/71r6euXFu09Mme4dMLy9v6J81du/WFCfOXNwwZXt8+dPi02X2PLW7tG9PRM37c\n        nLWrnto7e/aq/KLavPxa9EycMW/Fmu3Lt25/Ysf+PQfPPL9z99yVG9Y/vXv/0XMbnz3aPWZWeV3ryBHj\n        Zi54YuaSdWs27g1GM2ANeNLCwUg0HON2j7JAV6Xwh+nkoUHAt6xJl54VDMV94pd3e7zif2eoACYCSEIW\n        DUDLR0Lh9HAsIxxNh1wNhmIxVrHOw9ukkwfyn1Qhqp+2BVNFaT0wrsAZBMgkNE1iYIVqbiDDNCHWoZMk\n        HFYiUo4jL3f6FUoADtLRT0BnQqeEBBRqgxjEp8+3ii0YEhCzAK9M8oGit2yp2kaBz7fi8yGaW0z7wUjm\n        7ysnT1Kb01DgJZgORIND6XpwhkzFYYbTlIx+IDsdQWIKiOsfzEMqSsP//1v5L22ASORC/FTTDd1wdo+c\n        NHzyPI8vBLhPCzB3Ngn9KudHfimumSABMAUoSQDnSQAnuBJYEcCTWze9lCSA3Sev7Dh6UYLAH52WGMAH\n        P/vVzU9/Wp6eroLAUPoBVgTiOgCfYxCjAuICCkulT275otMCwGtU5wYAGdwRDASgEB/o74DeB+6L9tdU\n        /k+2oTMBFAfi0C8yjXzpV5QAPqjiKjCp9aY2AOAiYQ24X8P1Viqxhy6jQib20OlfJklEoIFKqTBRIp4f\n        wLpkjnInGa4BtplQVG5yzuT2kLK5I8uCMnRMtmh0OxqB+25YDI4aWyu2tW43tL/ebWsTbW2uR5/r1ad4\n        tR630UYrgfdT4DEKPVq2Ryvx6kVeI0gHkT7WrZUQ65keWuiB9jfy3EYC13JrtV4GgWExFErOKLS/39Yz\n        LK4A8Ls1rw29rwUtLdPSopZGT5GtZ9uGH4YCzAKnFiHoO5VfiEFgy/DYdPKADDzi/Q9YzqCUfwiKnMcB\n        dD2AXjI1zaDLyV3JGCQwbdO0xZUUJsQzywjqPuqS2DJUOYtAsMwngF5hPR01Ti3BJnBPrw43/lUD0OI8\n        xQE0Z6InLs01XFTlwGLMhkuANoI8S6ckp1tJ7AwhDLwFiJM/GCcgA8FcAL6zJoTofUp7pgzRtyMskiQA\n        VRcIeh/IbigOGEB/SH7OKfGAJAfQQUQXUGZWdl1ja0VlXV1jXXVVbUFheWl5ZW5hUUFxUWNLS+eI0fOW\n        rHj50Nlbr3+wZ+eeVRuf6h42uqq4qryioam1c8O2nXMXLC0sqCyrrVu+ce2GbbvXb9h269a1c1duvXz8\n        3LoDe5988dj1197/8ic/B46/d+/L1c8dWbzpmXlrn5r62LpJS1bte/nMzdffOHP+8ovHzz936PTGF4+v\n        2/7ivgOvvHj02rMvndhx8NCHP/jy9rsPjp2/du3WGy+eOLXv6MUn1z23Zv32AyfPL9z6/PAJc4tqmspb\n        h3WMmzekf3Jrz4TOEVMXLX967tINE2c9MXXqgpr6wcFIbiiaVVzZ2DZ09IyZS9dteG7y42sH908fN3PZ\n        5uf3HTl5ZtW2bf2jJlYW19Y39s5esn7r/oOtHR14LA7dAFJD4wNEiLmS0AkQAb4Ql2UBVyQOIc+CbpD5\n        Xr94HrwBcAM99bAYWMk56g/FIPYB97F4ZjSeGWD1t0g4kgjBLIhKQSGm90C503rwc9OYkF9Vd2A+D0vY\n        SyIQjA9WE+LkuDrXA4fTvFxk4Pb5PbJUDTjORQBcyCalQAXZifhuL+ahk4dATNc/YV1UOT8Vrw5Tgxja\n        9bF8NPhALANpZBcqehkmZKASQDkVSzgk83yg98VZDxNBPEgMOQj0Jz1L4sYBvg/kdNLRb9AdRAJQ5MGl\n        ADhI4r6igSQTqCiCU7aExFVAAJhk6JipY2Yuwq+DW2LSJ1c/qMzdsFe2XOYxqJr0ybcDBCALwWYsYxbQ\n        1KWr56/fsvGlV3adubHz5JVdr1x5/uj5zS+euvohCODeniQB/LgsPV3/LgjMAnDqQDw/bOAG2AFRSf8X\n        GhDcN2VLSE1tBknnD9B/YFtgHOgZupEpGUGyLxjRH3APHM8VVmBsQGLCMAJYL9rUy0yznGUbmOhZxKKb\n        QH8u78ozQAAE9GomjJoSEzYqJG20CDPjLKkjjROrmD/KMnCsHmrr9YB+N0MCtTaFP1C+ztbrWMpNa7Ad\n        tXT3M3kfIA5rA6bAULc22mMMd+sTbMcUW5vqNmZ5jbEeBngz3QBoLc+j53k0KPpMDx395Uz+oR+pyaM3\n        egyaBXT7GLASoOXzmQDK9H8QQFSMgLBHd9vMqAlyZ3kNTXw+Wsh2RGwtzMXDsAnIBEHuKqyFXHo2AwNO\n        n4uZQswQdWkR24xzey8jAuaw6fChfUBfvxGh35+1/tPp/GEiaZrl9MqyAHzqcZpAaoh64HuQaf5cARAn\n        JdDDky5CHjQAxI8B3A1H0HRgAPrxCvAlJYgnx0UJ/10WEIW/NBnDMKwFBJcsI3yEkczYEc++qd5C+zNm\n        S9eQChRjPJpPwbcYAcoOgIoHpgPNhVd0U1w96AH6K4gXBxGNABw7dS79VePVp9KfOiglJTu3sKmlo6y8\n        srSqKq+4LJaelZGZmV9cCpugrLSiuaN3xJSZ+04c/82f/+78mQvjx06tbW7JLyqGbi0pr9y4Y/fEaXMy\n        MvKHDhvXN35cQW3F5LHTTxw/c+mt13701c+u3rk7dv7ytbv2HL1468CRixNmL52xesPBS6+PmrXU5U9v\n        ae8bP3PF1peOXL369syFWybOWXPu1htf/+Z3dx58eu7G3et373/+42/euPPR2k271mzavnnXS/M27Hh6\n        9/k77z48f/HauNmPT1i4+tCZ66s27ejpmTpv9sqN218cN3txY2v36NFzFq19fvGTO2YtWLdq0575i58r\n        rG5Pzy4AY1XXdU5cuOr5F49s2L5v8pqNU+cuX7Ro1crNOzfvPPz85j0zJi4oKKscNWP6vnNn5yxdA0B3\n        Op3ReEZAtnZRAlxqusVYMpqFORnaVaU9JVQblfIPDCMzbIvxav+AaDwUioXDGcT6aDySyArTrY8B4VAk\n        FopGg2G8xnAS489S3llZGFTxdP2z+A8oQUUd6P1n3hGuQsLAAOaDBmGCQPky/AugBxoyCurzqYXBlP8s\n        ESEWgBvCXNbTKk0NjCZDCPSDBpIl9YU2kgRA6wFN0J9sQbgnrFPdE+U5pxgElOf01bi99A7xEmIxKOXO\n        EIJF4gHc6/gfRT2tB+XSEfRXoM9j9dZI0gDfPpqH1oPL0gwDnw6bMHPcnGVpwbiFL0isB+4D9Kn0RfUr\n        AsATSwQjGf5QHAZTYIAAXlHloKcsXjVvHQjgxI6TV58/dnHH8cvPv3xx88FTl997cPr9D3dfuv7+z351\n        46MvS+IxtQ5AtQFHEH1BaBIbgAWgxcQOQEvoqZlmarpBMgAByGoAgn6WNKEBuoCg8bO4FowHkv5v0v8j\n        +7nnyua95SZTgLgujPEAB3AfFkCdSy+ztXyoe2p/xopZRIjZPkYtN/NyVjCjX69gmQdmFgHZq7kbjMEN\n        YdAA9FJqrd7inr3N3DUlqf1rWWEUNOBokLpvOKhz65DtQzzGEK/e5uYi3iFAf48xgRvBax22hk8H07lv\n        FHhYAI6N6A+Ih043BpMzmO9f5tFrPTqMAKA8QD/LwwhwDkGf49M99ALhrQoCQ+Bbbj1mafkgAPHvgwl8\n        khQUt40MYLpt4DjEDE5mfIYkIwhGAPQ7JTxeuSUAlw1jPKwB8ctrgPi4oD8kf0TCA1HSBn1EabKAgK55\n        QjMhOI3FnzVMlSmgD2kPRU/NDnVv6mEpvRAzSQ9A/7AEhBUBANbRANOEWuCyyH+MgU2A+XEbAH3If9yt\n        GzzBRiZQSUoYCQJgE0BXKG8lvfyyLMDQDIn9wiZws/obPTloGE+zQJEBX1WYl68gAAxwJTcDUC0VA9Ap\n        PJGKf9iJjOyy8pqc/JL84rKi8oqCsvLCsqqqqvqKyqri0orSypr07KyRk8d+/sWP7t37fPmKpzv7RuaX\n        FAb80bbu/iXrtrX1jGlr6x01YnpWVlE4ligqr65q756/cdNPf/PLr77+ZVlDZ255XcfIabWD+8OZuXmV\n        NXNWblywdtvoabMGDx1RUFjZMXzK0jV7V27at2L7rhHzFw6fNv/wqYt/+Zd//W//4//6uz//5cSFN3Yf\n        Obd648aK1iFTlz6159jlV67efOHo8bZhwzvGT91/7tqJCzcfn7rmiYXbr91658zl6/Mf3zhn3tozF67t\n        2v9y8/DZjV2TJ85fvXDVnmH908IZ2ZGsgub+/k279124+daNDz46ce7Guqd2LVyyYd22/Wevvn3u6us7\n        9h3pHTmzqLlj74mzZy6/YdjcCASYLsgbAwoHCChx1g5igj9YAWDtpzxnYbhoIMTYb5qfOTk+IDo6of1j\n        iVA0AfRndDcYCYfTYzGSgc8f5F5loAGQQCwOVpBzuZkXOSAQ9IsXCBBPyyAUARVFoumyKRhIgv0eSUai\n        KeBjoQjcp4fxT5oCXBUseaIwI1QxH4XLbBTssjIraQqohcEC9FJKKKnohSTYIwYBThGsF0cQaEPgXtkQ\n        0k/DQmV/gk7wFqfTIFD5oDQXcIqHdfxNk5IfwxilCFDvq8KfxHp6hJTk/35jKELRlVwUPZqm4bVv4uyx\n        s5Z6/RFwXhp9X6zox+QfFfJV1kCSANJ9oSiOky6gRwQwadHKeWIB7HjlyjNHzz338vlnj5zb/BIIgDGA\n        3ZcZA7hy/4uiaERZAID7RwQQkKgvevAqS38dQU1j+U8hADS1C1hcPEKMB4j8f+QLAhNwBYAsDM5hDiiM\n        AHr/ZREAXTeVLr3BNqucZiljAHTplLsctS6zwXKW2jpIgtWkReOXuriJGPM7pWYyWAT2hBSHSOr6Wtsh\n        6M+35VLjodHDhP12N9eU1TJlyCiTIDDUOj6tt7VGCQJX4ly33uIx2j16D6wBW2uxmQw6mZEAtjbQADNE\n        wRPkgBy3A+Be6qWcL3XrPfTzEP0B+gD3bC+gn1VCSyQInCEckPDQ+YOPYmAC2dc3wNgvTAHNYzvCyagv\n        S8tl2Kwol2ClICb+JyQ1yOcyAKN+l5bO5VoO+oKAtrSQnAnb9IEkLH7qc9FXk+5iPDbE+kLM9sngJpEg\n        DMh/0+/kfu4+5oYCo1n/GZCdLfjuMyn2xcVPzc44raz2kgiwlqFsArUnu7iAYgPhXLzFAajFz3QjnsuU\n        IbEYcIeycpi+Jryl3UBiINmw3LTkCME0wbHkbsqJpgFWEEynQcAqpLKYCziOV5gXYjcQ2WEHAP29QgAS\n        JOAqMOnHK9FfDAWeBQIwHSmhcDQ3tzg7pzAzLyenCCK4uqq2pbyqMS+/tKyiurKm1rTchYXF105dvvvR\n        va0HX5o4fVZGQVZamn/Bqk1nr73eOGRIJJZeWdNYXt1UVdeaW1SeU1iaX9m0fN2OW+9+tPL554vKWspq\n        WheuWj9vyab2/hmtHWM6x4xv6u9t65vQ0NbbOKSnc8z0po7epq5h7WMnjJ29cML0BRmldbv3Hf/Hf/7P\n        G3cfnrlo047DJ/qmz+yaOPP4xZsz5j2eFs/OKa4tqRzS0jmqoXNYVWNHdfOwsTMX7jx+9JkXDi1/eveW\n        A4cuXH397KW3H39qy9g580+9fO3mG/efO3Js+4uH1z65df3qZ57c+MKuoyff/OC94xeur1n//L5DZ3e9\n        +MrevS+//tq9q9feeXLD9uf2H/n0hz9Z/eTGSJzVhh0OPAPIbjriQQZEduYIRblymP56SeYR3z1jwipt\n        NBgOR2LRSDwaTw/RjGB6DwDIF+CaL/p/glxCnOYL+f2hUDgGAhigEK7slfJBElKmWcCi0OFoejwjGzRA\n        ZxRDzcA7AByDDRjMIhDc2IBlJ9xurlZjahBf8RYIDgkviG/Rh0MhjwZQFlgHvkueKBN4JGwggC4re7mc\n        mL4jheOAfmlK+6skUchzOZE0ALuBi85YOgJgDUDnVjAC/TBELMtjGER/oDzzRxUBsCzro7xP1b6P/mpF\n        WDJNiGlFsp2ApnGv7e7Rk0EAdAFJdVLgu4A+0F+O6RGSTFDW24BBAEoI4uE/IoC105etnrRoBQhgEwng\n        6jNHzz9z5NyWF08+uffYlfeZBgoC+PBnv7760Y+KYzEQQFjQH7jvl4MBC4A2AUAfn8IOAAHIPsDM/qTn\n        h0UgGAPAAMUBOQZNgZgjJcMxCASQxZVcWoGhwQKAYC9jGihX9pY4HVyQxY26iOOlKhLANVkGVDk0fqVk\n        AQn6E+sLceDE6VqZywHVn2OamBCmA2aosrlDSwWTR1k7qIahXb3Dqw/za0O8LCxa5XJWs0y0xIQp6hn1\n        BWeU21oFyUBv8eqD07TBsjtYv6312VqPW5vq0Ud6uUSg36N1ebQyt1HIsm4aID7Ty/3fWUCUNGBUkx5Y\n        Hi6XG4TRL4R7qHYbmQz8GiCMPCkTlMG1vkbc0gH0CZUACuFvaQFLgzUQJxMY6W4jykwhPUJTAIQBDa4F\n        XFpUFD3GRFyOGF1DjBnEbeYLBbi7C7Q800MT9O0w1uqV7WLyaQRQkoedRq6T+0rCgIhKGg/AHRgNEwHH\n        UOJCAKABRgIA02gi21VUQEuHbUGnEMQNx9NlhH6QgYSOMRJojuuGnI6gTJ5wYmYjbOkJ8JbMhgEYSeeP\n        uIaI/sl+RoNdLlhCeMucUcA6gVsYAjcGI8CV9PngIJX1QQXxYQegAfGd4gUCHyhu8NKPxMHSQAapRmpK\n        MBQWrK/KLyvNhRVQUVtcUVNcUQ8zAJ3VtXXxzKy6lo5ndu5fv+W5+vaWopKyzJx8IMmc5Svfe/Dp8HFj\n        NUPPLiguLK+sax5SVtWUV1he29Be3z5s2uPrF2/a98TGvUvWbN5z/Mz8ZU/3TV0+Z93ufUfOjZ88M6+g\n        ubZ5+MylK3e/dKK7Z0xpdXPvrAVjpi4cN3Fpa9fkm3fe/eD+/YnTHyut7QAlLFixZsLMpUM6xtZ2jJq9\n        Yt22XQcXrdrW3D0qr7i6tLG1tWNE/eDxJU2dNd29LcMmNfVPnbpxy/Ebrz54+MXN63cOHTl+8dbddz75\n        6de//u3XX//x17/8/a13P3z+xWPvvv/B17/69vTF22vWbH9q244VG55dvuzZu3fu/9tf/8+///O//Oyb\n        n//s57968cjJaUueKK9u1Bx6qiPV6XQFuDggDPQPR+NRavl0rhqjbA8H/HQTBaDpuVFMLBZPRwtxl3kg\n        O2PFASk3xEgvJbzsMaAWHNBrgUNVIIiFfbxe2bQyLY3RXdmX2BdgUDorNz+WyOLyAh+5xyubXDLv0yeb\n        ALM4TxrOxVnQ/gwDyAF9OMB9uoO89PVzE+Ak4gP9ceBkuieXdJEMOBKvHloSyv9DUe95VOqZIQGaAh5Q\n        I3BZyXMSQDKMTL4hAbiY8ckggdgZGCb+/WRtH+XMYSSZGUEC9EkmEOj/zinEHozmVRhOIAHohsE9gXtH\n        j5+z3B9Od+NZCfqzkYyjacz+pORXNEAmSMNTBbkmXUDHZ5IA1kxetGLu2s0bD5zYfuLKM0fObzt8dtO+\n        E2t2HL70zr3T7324+9KN93/26+sff1kSi0kaqCIAQr9ftn5UBBAeWARA7z83ftEiDsK9OPqZ85OhaVwT\n        ID2ZeDW0hGUl8DfjSAEf5EiiJ7R/CUCcpfkh5EEAjNyWS41PfFRgEM0bmLAPqa5VmUY9hDwH6Cz8YDJC\n        AOFfIYvCCk2z1CBhiNsHBED3PegB8p8xAC7sokunI81s9HIdAEhFbdiLg2q6fVgUusxGozXQ5DGGpOlo\n        jW6tVRaCjbCZ0d/F3B59sFcf4yXQF4tbv0LgPsEVv4wVA+6B9fkeLUM2CCsQ7c8dYGAWwCCQNcAQ/jjI\n        94AejKBNoM8FsjMTlKsBIpT5hHLo/bDNVQUJmA42NwqGhZFrm2GLdUPjjPpqIIMcl57JNQE4Jj1ky/7D\n        wPQwlb6ZScEO6IT0ZgGJdFuKOcOASO4ooMVwLmMAsq0jVwuzeoTk/NDJkzCZ9gN8Dwg64ziLbxXK0zvv\n        MpJOHkAzxoMwYEmgqRhA2OmAmZLhAktxSYFt6zYsGIF7IQAWBcK9YSRegfuKA2RAst9PpxBlPkeSDJIJ\n        oLbkg9IaYBEhxh4UxMMmUHyAA0u8QIoASAaMDdAagLKJJDJKaxubW4d09fQ1NLcXl1bnF5ZmZGSVVJTX\n        tw4pLK4oLq9sH9o3a8XK1ZufS6SnR2Pp1XXtLsvqnzj5uX3HqmpaACiVta15+cX5pVUNQ/oa23t6Rk0Y\n        /9iciY8tbeubOmn+iqbBnfmlpdHsgsKyxsLaplVP73nt1scXLtx94fD53S+f2Xno/OTHnlry1NZpj6/y\n        hGO9wyf/t7/++3/7v//niJnz5i1fO+PxtQvWrt/03Lae/om1Dd09E+e9fPn6f/zHf/zhT/+wbvvBjTuP\n        HL1w/f33Ptt3+PKEqYsnT5m7eOG6Nav3z1y2ef6KLSdeuXXxytXHV6ydOHfV8qeeX/bE07MXrt2448D1\n        N9+8/+DjO+9++NHnP/n2t39///6PLly7ffLyle07Di1bv+2lV8788NPPf/DVD1+9/d71m+8dOv/q0ief\n        aWzqzi/hCgmHA+rTCTkfjkbD8XgkJr4d6nRAuAoXq1guCCIRS2Ry+xdZWcZ+X0hKPkCQApW4aAvnBCNx\n        lTgUJDcAyETgQ7mrwCzkvNcvgQEQSzwzOzeeyPL7GXIIBOPCEMz950oom2ANsJNMmDSuFGNxOmp/ToVO\n        jxf2AaS3uIOA+8oaIAEIgtPvD10P0Y4eor+c7lE5QlJNCLCOkTYJgHYDaQP/Dga8QJgQA4QeaEA4hVdM\n        QLhgPZpYDJL2I69oihVUKJgV35KILzSQHI/GMkF8FbJBv1oH0NYzatzMxWnBmOVh0qeEPejzkXB9kgDE\n        KRRAk7gIVwaknHvjfpIAlq9hDGDt00/uP/bcsYvbDp5B2/TCidU7Dl66++GZ9+7vvngTBHD1/g/LohHn\n        9wiAiUCOR0ZAsoEDKPx1R0T2gIxpFP4J8fZI4/ov9MQcgzJNvTy/uKKsJtfnzxqUkqWlcCEYJTygHATA\n        dbxcusXVWMzgVHmclZapPEKwElj8GTTg0quZJEqqUIuBK5zOMqez3GScoM7Wqm1m+6iqcBgAZIfAb7C0\n        Zi4UgPZ31ru590utbQz2GrAJ2m1nE0tyckuZUp7OmDCgvz9Nb+fGkFqL7ehz6+Pc+iSuBHYM8ejDZIkv\n        WqOHxZwDHqPSawDNyz16txugTycP7Aao/hwYB7YjzKL/jgy3FnNrRbL+i1EBj14gTqG4bAsT4l4CdPp7\n        bAeEPHCchaNt1giKu/UQlwezhJwwhOmRnVgAsmGXA2BNBCcT8CCDWwhwowWI9IhTBzewn2IcKMxCoelM\n        LtJ9FoEYoByS+EGCjiANNkG6rC7GPFnM6GeKJ2R+lEKe0Iw5cSzuHap7anMu+2J0F0hNLxATdQTEOSFT\n        gIDaaS7aNLicBzcv3i1AfMBkqVHaJbQYuO9YQLGIlLXAMb4d+mVbSuI+OIDb00vqJ97KqwagF8lP1S9h\n        A+b74yPchrq6RwpEA/rFGlAZRGipjpSUrNy8Sgj2ho5h3X3VtQ2Z2QW5+UW5RcVF5dUl5dW5uYVVtXUV\n        tfh4/OL1m8qr67JyC8oqajKzSxas3rT66Z1FlY15JRWV9c3Dxo9btOaZrvGPF5TX5leWwUKf+viKIX3d\n        VU1t4eyCzjFjVm7ZNmv+qlA0NxDPmjp39bWbH/z6N/9p6ebnfPlFM5Zv/ewXf7xz92Fle/fGXbuA7//l\n        v//bglVPT5u7ZtjYWfUd3VXNTQXldWVVLSUVNe1DO165cPmjn3z70qkbqzYfeG7f/nPXri/d8szcBWu3\n        P3fszLVrp05fffKpF5/dcmjfy+eeeGbX8Alzqlp6Rox/bMGiZ+ct3VpUObiitvn5/Ucuvf728QuXr7/x\n        9q9+/Ydf/eL3nz74/MaVN5Zufrakaej4WU9cuv363kNHVm/de/L8a5dv3N330unVTx6cu2LjkKF9sUjC\n        AKr50pw2q6G5XF4BNRx6/P5wMJyAzI9E4pFoIhJJgAeCkQSQHSAeYP04pv+DDAD6NALwn9L+wTDoASwC\n        8U4C8MsGLx4W9WT1NYp6jMpIz85mOCEYgzUQCEQ83N4rQIz2EpHps/FK9X8GfjkDpsJbYDTjwGxcIUwc\n        V84fCnwp9kmRToc+egTW3ZLVyuJCOBH94vyhkCdVSLk3W2gDg8klKkggTiE8B45JDiBeQ7/z+Sg/j+C+\n        ID71vhovqv9voB8MIcKfNgfT/3lLmEpowGWr/QC6RkwYM32h1x9x0aYhyoMAkolASe2fRH9aPLJIGJ2y\n        JeSB4+ICAgGsnv/k1qdeOLbtyLmnXzq19eDpzftfWbOTFgAIYNfFGx/+/NeXP/isMhoFAQDl/eL/oQtI\n        ckAlBkA+wKs4eej8iXP1LzeATAgHQPWrlqezCARjwo5BhcFgfUV9XVVTUSKdiUCDUvIdKUV6SqkOKDdK\n        6NUhoMMaACsA7htFtjdYRpPTrDLNYikOWsr6oAwUF/NVr3GCGLhzL1iBmf5unGhyIZhTLzIMSRvVam1M\n        xY3DyiXqC5OiyjLrLWdXmtkX1Du9zibbrHRrZTiL+p0JPF1evTNNb/Oy9meT7ejkGmB9tlsf4+aagC5Z\n        GFwvEA/tX+pl8k+h26iVZV/NUuOhwWN0MikIiE/gznMzVBB1a7msCaHneYxSD3cPBm1A3WfazBD121rI\n        1mAQSCaozpXAblCCA4Id3AD0dFua13IELECtGeAGXg7AbpA+HNCAlskYgF5s0RpIDIh0QDw3FHM6o04j\n        j0APyY8e5t1zn3chAJwLvMZITAUywDHf0oPP3E3guywqpsxHj1cit3TUMNsH9oEDNgGEPK6IMawKJ6EC\n        eqg42CE1G7Q03rbmYnorbp7pRvRKyfovRS3A+vTk2mASAK6FpigBk4CKyAEi8Cn8aXkwLAyND3UvXn5+\n        xB5OgrO4SBhMwEoVOl9hbTDIrCIEQgAZ2QVl1U0NzW0dncMKy2vi2TkZOfmF5ZWF5VWJ9OycnILymrrM\n        ggJo/Onzl3eNGFtWXed223nFdW/f+8F7H33e2jMqPaegbfToBdueP3XuzuLHN6YF0zPyCzp6RgwbOalp\n        aE/v2KndkxfuPnnps6++vf7BJxPnr7fd/mA8PuGxDcvW7j5w7MKLx072jp++78D5S9ff6Z322Lkbt/7X\n        //pf//Qv/7xp496mtnENXSPyC6vyCsra+8bAACgsr05PL4yk5xbVt3f3T+jqm1Df3dUza8rslWuWr9ny\n        xFN7pi7f2DpsTHVL98pNT+87+vL0x9dMXLT26T0vbt55eM7aLY+v2z1r4eq8iqqitrYNz+65cOP1F8+c\n        P3Ty0r2Pv/z6F7/79Ac/Onvj1oT5T+Q0dk+esWjV5m2zlm1+fOXmgydPHDtz5cDeV+avfHr2409PXbC6\n        bfjowT299XVthcXVucXlINGc/JLc/NJEZm40npWZlZ+dVcT00FA4JPvGhGMJaH/xBSXQKfKcJgP+R9OB\n        28tEQB7cUYApQIG0oNoAUvas9wUi0fRINB5NZMTTs8EoIABVTQgUwuAtBT73fBeXjtoGgOYFPgXcMzLM\n        dQD0JqEfbEJfikXlLtJeOf15rsvyOlVRTxoE3MALpCKOHQ/AV8bzWDL96RGSqK9y9xO7lVo3odZl0TAG\n        kzaU7x4y3zANRgWEAL7T+0mnEBGfNR6SRgB9PgruQQBiB3y/HxYAThw2bvqY6YvSviMAoj9Vv4/oz3iA\n        yoZS7REBXLj9cOuBE9OTBMAsIBLA4bObD7yy5aWTm/adWLfryKV3/79svQV4XFl6LVp2VR1JxSVmKKmY\n        SwViZrAsW5IlGWRmZmZ2G9t2t9vQbmbmaRhm5pnMZJJM4IUzSW5u8u59X+at9Z+yZ+77Xr6d853aZ9c5\n        pzTutdaPGwTw6an7L37uBz975nNf9uXlGaQOIJfozzTQh7gvdgATgUAAagoQvf9M/vnDFmBiCmgrwAEK\n        YwA4L4DsUnS1NZ7Otv5YOFGVk+cwG73GzIB+tleZ5cnUStInE/w9GXTdpEz6ZJY+kcltcsN0FoEYQAA4\n        UVw80cEs8GVmRDAY6QUHMKIbkJIxtQAYSj9s1IIAWCkmGp9NIIDRBqXJmNllzWq3ZTZblXrBbh8XsI4M\n        i0EALTYdCCAkWN8pRQC7TMpGs36SlcDcIriSZcBEfL9ZlyMb/3oszA5qNbFSDByABzlhKBh17SoBmNMl\n        XaUmpcyiBBk80OeblRwzJx0G5npC5mNIbziKZaspHROu4G4BbM+Jc6hp6Hc67sXnkyve/8IsXQ0zZfXl\n        7B7B9BvJ6dRhDR1BRHN2VigQAijCnVmcpeASPrK+TJxI+GgxKGIWsFdPboZ6H2YKAZSpqdNgzRPgKQiA\n        SZ9iDQDWmemvTqbhm+9A/Q4CECOAlGNgvNcgm8VnkWbIBAYaDUxPEr1PwsC3bJLwykYUQiR4B4A+tbxY\n        FXQKZVLsi6LnoMYHK5CZSG9GWc/ArxCAQQwFLMsEB+i1GbM0+YWlbl8kWt+U6hjyBhNlVVUlZZVFpeUV\n        Tme1219d43O4A8XlNYHa1PTqFXNnlpVVuxVFae4bev8LX3nvo4+WrNpYWuH21daPLtp85syt8ycv9s1d\n        PGdyefucsaGJ5VPLNs1fsWF01ebRhcvnLFh56JHLH3/8jfGJdaU1gUWb93ctWLVyx/7PPv/N6aVbo5Hu\n        weHl5ryiFRu3wwL4zZ/+NlrXHGzumb90W2Nrd2P3nIF5C4cml06s2ToyuiKa6GweHlq7Z8+uM2eOX73+\n        xLPPvv3Wh6++9e7jTz62as3esYXbt+8++OSLL33u0y9dvXJv88nTN1577szVWzPrt67bs3/PuXNr9h6Y\n        O7V0ZMHKJZv2bNp/6PiZa0899fznPvnqj3/yy+//6E/e+vxnMzs3W3KrarzRqYUrmlr6hhZMHzhxfe26\n        g+s37plcvivU2NnQPjAyMTl3ZHFHz3jH0PyeodGWzgFHjdfKxJ7cwqISxodZAwyDIC+vqCivqDiXFQDk\n        AIYBIFHpYbfY6S+SRE/pGKEO5gJx/xkYB2w0nVtQUlJeVVpamVdQQKuioESNRVu5XSXDvFZpQw2Bj6/A\n        WJCMfmh/yn+aEZIeKgtIFYLIFN1AZ6PZRsEOsKYRQLDOpFufbhwCvTCBcIBa1cVLHLQGxBsjOZrAZSKy\n        CHzhAM7wVvTvq2EDC1YS+qWMS3z9MAiA9WSCP7IJ1BOeq9BPOiGjqLwi+ULyCKYSZWZ1Di8YnFgBAgCy\n        A+uN+Jlp7Z8mAFBCmhjE/wMOgNWlBoGFANZuHV+1afG2fTvOXj909d6+i49j7Dl3c8vJa0+9+7nbH3xy\n        5ukXP/nhL+6/94knxw4CyH+A+OpQAwCwBvJ0syD8VQJQ4wG0BnDU6wp1+iLWfNELhCPQHzSAc9oHszQO\n        vaa2rLwp2dTQ2Flf34aThMvtMWW5tBq3frb4dnS+LCAsy7WimdynJcomEMwK9WYo/gzp7kn3DnnCn5kR\n        k/bR4ICAbBnmz9RiPiD5nRG6etgB1GdgaJf5/lL8FTdC3We1YZgymswZ9RayAqA/lCWbyxt1TRal16Zv\n        MOndkgLUa9R2mnWjZt1K8f+wstesJGFtGLXA63w2f9bnWmgKdJvkW6ABIQPQQKU4gtwmHcwFfMSliOov\n        ElOg2KTks/UbvT1lrAQGl+jKDRz5Bj14pdCo95AzdCYT5D9dQJDS+GcDcMwnuJMV1LTR8iy9A2LfQPXN\n        KLG4gEpgCpAAdFX0F2XAGgBPlBgycvHvX/aaB3NglIBvaAGQS0AJxQbGZi0ZdA2BDwDK2QzMMlSLkUcC\n        oPslK0Or8MjFQNt8FoURhdkQQlaWUdczuQickWvQgcNgzeANWYUgzy1mOFqHOwC16Qjit1gfwBCCvIyF\n        OU78dXJP6RJBDkjHA/CsrHRiD2Ed3ABiAJ2AYzLEHYSZTIF+VoRJd+gscRwZZmnyigrdgbA3GHEHoxUO\n        TzHRvyIvv9jp9kSTULihimpXVY3HG6wdWLhkZNnqnIKK2qbO+YvWnD1z+8TJK4tXrOvoG7fn5flqA8du\n        PrHzzM1Fy7aevXB358Gz7b1z2tuH5i1bv2T7/l1nLwwtWto5Z/5Xv/W1Nz750u6zl1547b11+y5qTLnz\n        Z1a++sEX1+89MTKzItzcc+PxZ0AA73/81UJXeMPB4+sPnC6pcNZ4fdWekNMb7RqZ1z0yL97SP7hw+ZLt\n        2xds2bbv7KOP33/5qTfffPyFF2/cfvKjL3ztRz//s1///Je//s1f/PxP/+KzL33r9hPPHz55eeOB03sO\n        XLl47f7Fe0/sfeSRjXuOd4+MF1a5Q7GORdObjx6/9Njdlz743Fe+9b0f/eIXf/LTX/3iwqN33K6I3ZIb\n        CiccrtDI/OWrN5zcue/Mxh0HiooqLNYcex53fs/NL8LfCgIfgAspDciGroeEt+XkCPqTAyjwyQcFOflq\n        PqiaO5QDAmBggCgvqZ/S5hNkYLEBs2wm+nPYAogNJIrKCgpKYBNYc3NtuGdeIe/MEmIm/5jIFvhuLmO8\n        FrpugNrgAxDJA5IgARBSVS8NAJWOe7p0DMYHW32pWluNuIobRwV6gzR5lu9SsOOroAcs4BBVLsCtOnke\n        6Pf0Xr6yXlw6D/FdnVSXpaFfHTAI8BV1pXoTWgB4EI5CKiQDLsCJHv+oM40dQ+O985eY7Xn0a9ly1EZA\n        DwngwUbwfzyYOpUmALqA1m6dv2rj4m17d5y9duDK7b0Xbu678NjuM9e3nbr2zPufPPHBx2effuHjH/7i\n        iVfeqbGY1BgALADiPreCmQULQGUCWAYsABbcVwfPJfWzhNqfJWBqBUCl2AEyyWOZblYZaCArI15W3uBy\n        N4ZjjU2d4VCtIye3StHWaDU+ZVYtO7IpUSj6TCWSpUtIzx9of4xAhj5M6Nc5M/XBDNkixpARljqvUJa4\n        ksAT0iXCy+Qf7sMeFPkfNulrZYQMik86QzSYMxotGa2WjGabUmuivyhkoLnANH+LvsdKVggZdZDwbQZd\n        p0nfYdZNm/RDJsaBm7lfvN4hXnuYAlXi2a8z6eeY9T1yNUTvEP08FWYlILtFQvID/avoMtJVmxWwiER0\n        9ZXM/yGyF+OEvUV1lVm6CikGLjWSOSqM7BAHjsnHpJFIDVAG+mMQsg3MllHhEvo6G5aEXGIWkOhrUeLU\n        8pgvJEkwSICnQHHjPpjJy9KqWpt+fFYg0yagBpeK34p0Rr+uSG4CjMbdANBQ5UZBfLraM+ifNGdqiyUh\n        hzJcXDrSGZQEUAQGksJmDBBbLriN+aDixgF5ULYzp1OYhiYF6EE8VIB+LY54KGiA9CCIDxWPJ7JNED/S\n        HQSgxwyMEpxj4CRTLgHu2Yxato/PZKNQUAUm6QIqLqvyhFNQr6UVlblFxfklpeXVLofbF61NReOpCpfX\n        Ew75w9H8/EJPsGFsxY5E60Dv6EysrvPK4y8+/tzrVa5AS9f81oGp3JKitUf3PPLMc4FEfUvnnOMXn5g7\n        vjjV3D13yfq6jjnzlixbv/vg5IZdW4+c3nrk5MvvfPzf//3fz739fsfcpbsOnPz8N7/2l//8D1effikx\n        PHn03PW//Iu/+8qPfrz5xNUvf/0n124/G6htdXr9znAkv6raklfsDEW8yWRNpKNjdAXYZWB0UUvHnO75\n        E/Onl3QNTK/acezEuavXbt868ciVHccv337hzfu3Xj9z5Pq5q7fW7D49ML7qxNWLK/fsjncPdY0u8Iea\n        nZ7U3JEF08vX9Y0uXb/pwEef/9JXv/6tr37zO9/76S+ef/Wtnu4Ri7XQYikqq/KNLl+7c/uRXeu3rVix\n        tq27t6rGDdwEMtJXLnn33A9AxXq1aIuOHe4QaWM3/4KCwmJuICzpnmr9sI0RS6kay5ZKYPZ+yLHYqOJx\n        UxNIgHwClOcOw7AMbOz9kC3LWIkGtgABgCSMRnr8VS8/jngfDipiWhKclLQfFbJxBOCqeZ/AXHp+qP1h\n        BIAGgLZYkCWpPuLwEW8PgwRkDpUY2AE0XZqbRmfm+0ucVpBazAJckqpd9ZwDRoJKAOpRHWn0T5MHwR33\n        eaD0/3B/FfqzWFFswlC/0to39/+HAOgFUv0/DwkA5McICv4athxmAX3CdtDrtk2t2zq2GgSwb8eZq/su\n        PbH77I09527sPPXodhLAx0+8//GZp2AB/Pze2x+7sm1ZDwiAoK8F7kskQHxBudL97aH2L07Lfw4AfZF4\n        gYD7KgdA/mOyVOF5maKryAANaCpna7xaTTBjdqKosCmaDNc2VDs8Fdn2amWWZ7YmotPUZmh9gPhMfVLy\n        gtyyXQzzhTKVGskfjbB9vxI3Uf4zIJyhdyt6D904LDBmxFjcPnJkz4YGs9JupTbHJGR+nASQ2ZGd0WpV\n        YowMSxWYUZcw69vsSqddabQo9YB7ozZl4HZgIybdHBPxvQ4ob4LYx6PZ/9llYtsGj0m/WLZ/STFyQNYB\n        xFea9UD/FjaDY8Kow6wvsOhLLWALpUI2jakyE+Wh9ytZwQv01zsAkUA9cZqDXbJNulxWAiulQgA2YGiW\n        FgvYpk2AHrCek6WFKWDnt8T/w0IBOmEwALI4FkiCDSAe+F5hYKY/vghwxyiUIzDdLKHdAnADPUh005MP\n        MvUwLGBGFGVqcRMAdKl4e+yZ2uzM2cB3dQDl2TdCjRhLGRfII5epOLOz+GiaI/iBReLXoinA/E5iNHA/\n        WxarwF2YqVUfrRYx5BnwS/lQLIYRABOBdoCK8swF4s6R3BxYNUGkkgDnRpoUXINjhtgKMGX0qhGgcNtI\n        o6LVz9KUljl8oWSVy1daWV1QUlJcUeGPpeKN3ZF4Y4XTWVJTHYynfKG4wWwqKCnasvvc1KIt9pyiUKL9\n        yrNvbjl6xJZbWFLhmli6M9E2EE4kNu87kWwbMNkKm4YWbDp69vKNZ1es3R2INueXO5au23rjlTfresaM\n        tuJTpx/9v//n//M3f/+Pb3z8pWdfeefM5dsvv/u5x2+/ZLLnGexlZ6889X/90z/95Ge/fO2dLx65effc\n        408ePffY3ZfffuG9z27cfv7WnWfPPXbn3ovvv/bxp7svn5pevnp60cYmkFDXyIqlu8YXrm7un982NN3U\n        M+CPt/saBsAKU9OrV67dvvX4kantm+dOr56/ZENn/7zeudPLN+6dM748Ekn2DIxMrd6+ec+JCzeeuPP8\n        M/dfevntdz/7zg9++bOf/ObAvrN5hQ4ly+YJxles3rBswfrevvlTS9cMzZvwh2MFhUzKBC7n5hdk57NV\n        J8uGs/OyWR3Gtp105efklVRUVTvdxWWlbP7MbWcKWdObk2+HSKevxmbNZu4QNT4TV9i2AXJetQmYMkSK\n        gUnBe9ps7DSnHqnuQT8i+SHnTWa72WxVtzCTRKMcRghkXzDIfNzzIXAzVCDxXmnbyRlKfsK9BIctEhnG\n        /+Qm8eNnsbxLdfuQD8RlBDgWSiBGE5r/4BpipiZvS6tCjR4L2QDuFal3f1ANkBb7DziAg8aBsBTmhTbS\n        5gKFPz7yTfBEcIlOyWzumTMwvoyFYCA//FIaQ5IOq2YEpYd6rhYEqIVgr3964MLDIDAJYPvZayCAnWce\n        3XX2+o6TV7Ycu/TUux/dllYQn/vez5777BuBkqIHBEDJr1aBEfplEPplK+CHzh8OaQckSl9XzL5v9P+U\n        Kw+bQgP3QQAPtwRgJZdb4D5szIyVlzfU1jW2dKWiKV9RoTNLqdFpvLM1MZCEluHiKq3GpZvNJj8ciltR\n        wkz7YYon5DxMhFCmLiaVX+zBYOK+j6HMDD+3eyQlAOIB6N1WpnICuPER34XYT1qVFovSatXXWxVAPywA\n        2A0477IrPVbmgNYatc2yo+98k+6AWb/IrB+UaHCrZP0HQABGuo+KhB66Zf8vmAhhk65RGkTX4m6coWHR\n        jhOL3gNeMbMpUKGZXeRgAZRSF+sKjDoW8TIaTAIAXIIbgJhF3BKAVQJ2WAmCoaL3QQB04KheIEAkJgvB\n        DbjKCIEaUxUCSPMEfUFlEmyoEId+ruTmQ5tD4OelPfvkAMyrvns18AuCqZIIszjoAdBaSntgdIa2QOBb\n        ci61OYouR4E1QCYA4pN7aBwQmvHRJD8QR5g1dgPVPd4Wd1CdOWJDwJiYjRmgfA6DzFwAA8WaRacQ15NF\n        YEykIxBm6RoE6wHn4vYB9HPQCBAyYJCAHECfDwbmeaKGkRVdxixNYVF5JFkfqk1W13hy8/OKysqbekZa\n        +yerPZG84spyh8fpC5RWVJeWO4LJpmMXn1y6ZqdGr483tS7ddKy5b6LK47fnFITqmluH5haWOcKNHZ1D\n        E5XOYKU3Gm1s3Xng5I79R6dW7129+czMnv0z+04lm3qt+YW981Z87we//v3vf/+5z3954/FTI+tgWAwu\n        WLXBW9uYk1+1cMXmn/3i1//4L/86f92W6obGTafPbt9/Yt/hkzfuPv3qB5+898WvPvPeh59+5Wtf/9oP\n        d524MLl6w627rx4891jb3ImVm3dv2XVgycptM1uOr9x3aN3evYs3bW0bm27sG+3on7P9yInX3/v0wqUn\n        V2w5NDqzu31s09ErV7707R/cuP9KqK6lrqF/xcY9hx659tLrb9956sUDR88/9fRLP/7RT7/xtR+ev3hn\n        YmpljSPqj9VNzmxdsHTNqt07N+090N07Fo42udyR3PwSwLGo+0I6XlSdbidkA+XzCgodTldltRsGAbA+\n        R3L/uWNwdrZIfnZtY8YOhoVbB2PSbCVAW605OVJvTECneylXnEjsHwdEs0m7COA7dwC2qNs3MmXTZGR6\n        jxmAaM9WN2kR4AYQsx2/oL8FFoNkBz1w5mDQySPJoCASSQ8FdhtMpiwzU/7JCjihZUA0JzQ/dPKo6E8u\n        wUppEiduH8yoi/FdmQdw09WjYr18VwbdR6AEOeFVMAIIIG1JiDtIRX8OlQ+kGVxWa9/owNgyiy2frSAe\n        FgCDPm3Zxj8QAIcEhzkeEMD565D/C9ZKHcDWvdvPPgoC2HH62s5TV7cfv7zp6IWn3v3wzkcfn33mhY++\n        8+PnPvtWqLRUXECEeCB+jvh/VOh/yAHqMV9OGApOZ/1T7OOIIa3/6flhpyBxAZVm6EoydA5p5ODMYCon\n        AN2h07iA9WZDq8s90j24YP6ikeGxzsbW1lC00e2NFJc4bTanxeLKynRqNU69xpfBCq9gFhuFkgYM+oQB\n        cKw0WTLqzQpwOcGGzwoDCSZaAH6jLmVWOiz6Niv784SM/BaoAlfjBn2TBZaB0mRV6syAZl2MYK3rsuoH\n        bErcAlbgPjDNRoaCF5pAA3oAfQfbwHF332JJ9KyWLX/bjTrYByCYMDuAKj6rvsqiiwofgAxw7DTp8Row\n        Gmo4lCo69+kUcphAA+LeYQSYTFBgpDOnzKCFbQGzQFqE0lAoAYZm6RwgAMnlB/rnZmmBlYBmqmPx5kPF\n        gx6A+0BhqHgsg/aH6q+gZ4knpZKoA+hk3g4BmgRQJsW6+Ejhn8FOD7kZujye8FawKnCTPEF2YDSdS1Im\n        RsgWLxDAF0fhA9IDFgCyQTDA7izVpSPUhY9GeW0oegA0HTViItgkcz8zk5uC4f7qU4DvBgnnmqWHBFQU\n        TjBAZnhPADoW8IVJOdJQCDPiEcIjjFlSQUZqUVlBbk7LQGvUa3UaTVGFIxCvq3C5yquq3YFIpL6juXc0\n        mmopLa8pLnVW1gTKHc4qjzeSam7tnd5+4u6iTbuKK6odNd7W9uFU86jDHy2pqsFNKv1+On9659S2dje0\n        dU1s3GYrqcjNL1y6fnNT92D/wMz+c4+v3HOisWdict1mb6rlwKkLIIAf//xPuxcu65meaRlemOyet3TD\n        gUWrN/ctWHzz6Zf/4d/+R+/osEajcUcTTT3zRpetbRuZF63rb+ye60rEkx2Dp8/cufbUy+Ob1q9et3Hf\n        ibMrd+3vn1oRre9u6BwZmtqw6eAj5248vvfM5Y0Hzy3deXBs05ahqXWrtx974o23n3jqpcOXbq3YfmZ6\n        1d7n33/vp7/9uxNX7pU6YqHatgWL1w6PL9l1+Oz9l1+9+sT1Czfuffjel7733R9//bs/uXD1ji+SmF62\n        cvnmLfHW9pPnbh0+cdPtq60OhDyh2soatz2bDpmcvOJs9mrOkYYQ2dm5BYUlpaXllfmFJYBwe3aONHxm\n        /TDh2wqpznR7kwmwa2EZFzcfhrRn3o6V5WHSHo7lBXT4sNyMdcjsUcqGz+zhw4QfxgwYAZY0f+nroDqR\n        QAwkgEwGeLNMZuAp8Zpbu1DgA0xFvJMh1LwgIj5zeCyy/xeTPgnu0tsZbAHmoPaHxicWCzTzhnJP1QXE\n        hB9x46iX0hYDuQQPygAH0NcP9E/HfuXrUiAmdCLcoN5W7q/aBDQyQFTCK7JMJ0GA9v7RgfGlFlueQZrB\n        SQQ4DfQ4f+j/MePv+WA+TQAHz9+YfkgA2/ZuP31t38Untp+6uvPUte3Hr2w6BgJgEPj00y989N0fPfPx\n        133FxRlCAAB3iQMzEqBCvzBB+vwhH6jxgMIH3h62ddPryhVFCgI4SctAIQFUSiefGgp5Fn858TGLPR68\n        Oo1nliZqNba5XHObW5fOmb9sbHrB/MmB3jltzd3trd1NyUZ/cbEjQ+ucpfFnzPJl6gIGdvWJZOqA40kG\n        ZjGY7umD5DdCfSsByHP2hNA1mJVui9Jio8Xg45YySi3gmFQBg4ClYXETe0JAp+OkwaLvs+k7bfqoWWmE\n        rjfq2lgNwM6gdYR+doyoNumLTFqnSVssrUDjbCChTZn1Q2ZWEQPx1eYQIbPikqZAmME7uMUpVC1VYF4j\n        Q8QOqRdzSOZPgWwODA7IYUmwkmvUW8kKeotJwbzDQKwHAZRk0Z0ijiDW2WIGmChtOHWFBtaLFdHJzvpe\n        sAIAvSRLKRXPewn9OWALpnViHugJU0C1BirBAVI0gJNyZnOqBEBFj6v5Ena24+t4AfEpVQKmRcID9yHY\n        8/mRhWMgBlgPBvHYlOH1snQZfA3+Ohg0UgXGlXqR5A9lO2wFcBJWAqlxf7w2C8GYq8oKA9oBWZI4lKkF\n        H5CK6ERizijrBhhIUDAv+E4LACulnoBX5SMnSScSdTCBAGZpAN81/og9N6+s2tXaP9wzd9Jfmyotry6u\n        rCmtrKmq8dV4gg2dg3XtfRAhI0u2LNlzoqLGVVhc6Q5GKp0edzDu8ARxE2co5nD6GjsGeiZXNXYPrjlw\n        YmLTAX+ipaNzzqLJZan2oZlN+1748NM9J648/fKHB85dDjYMfOWr3wcHnLn2VKp/PNjW53Am50+uXbv7\n        YOvQvOmtO/7l3/7jlbfeCbd0V3n9PaPjp64+s2nvmabu+fG67ppgrSfZNLxw3fYTV/snl3kCtVMz6w6e\n        vzi2Zmdz78JYW3+qa3D+wrUrdh6ZXLFvy9YTx67ePvzo7W0Hji7fd2DriQvHztx85M5TkPm79z4yvHDp\n        6NTyk6funrlyr7FrPMNQMDvL2tI1cvvx577wha89+tiTxy8++tqnH3z0ha9+8es/vv7Yrb6ROb3D8ypr\n        QnPHZt5874PD5y7OW7gumWgvLC6p9viy8woAzXl5RcB6iehKX2jpDAHgzpVUzlx2mS7MzYWtkGME9KeL\n        tuwwA2AImJmXaWX5F107uMQAL46MJVDy0+2DL+Ijk3+w0oivPEjxFF0PcBf0Z3tqbgxJSqDYJ8ICbs1m\n        GA0AdxHURFt6eyDeRcur+aCC8tT1RjEacEIDQgIDuMqmzX9Af1w1PAgA0I+EIwO2XKCyi4mOIAk+sxuo\n        iuzptj8qeXAZzskHpAQs4BrVUBAuAUOoniXyCu6vU0AThvaBeeICyjOCAOw50hiDu/fIyJWNwGCKsRqA\n        3CBGgF3dFP7ABSGAdQwCgwCg/fecf2z7ycsggG3HL288+ggJ4EMQwIsffe/HT330Za8UgqlZQMD3h84f\n        9QS4/3AIPZAAMPARNFCmn10l5b4V4vcHAaTlv+wNCfnvyGAvT+kBx+5AOAEBgBL4La3GodF4ZmuSlsz2\n        fFtnaWGfq6bH7Wz0eFvqm1va+1Lxem9+ASuKNRoYBGFlNkyBkIEVvGwBZGIRAAyLMGDdxD7PPtlQrM6s\n        VzV+JIt5NUHuC8YQMdbHOOjux5qIhb37Wy36bpu+3oq7sXdQn1HXzZ6gehxTJl1cqgFaCOVs8uMzM8Wz\n        RjigWbJ9cKlL9oQBuMMgwAngHjTgk46hVSbFh6eI88dl1OHpYIVCynxdEXOB6OehNSB7A4ADMMAT4BKo\n        fquk/BeLVwfCHPAKnKVDnx4hom0++wUxEkDtT1GvxYC6B2ICECsI3FT6xVLQCwLAealEd0EMYBFgq3qV\n        m7pIWS8wHUZAWQbDxbg/SKJCwgBQ9/l02sxms0/x2IAqILfBCsB3lZYg5HEHOuXBOuA2Ew0XXAJMK/wW\n        XUbMyVFTRRkVAA1oYToAwbkXgoFvSChXO1TDDhAJD5PCImyEo/SSYzAARgDDwmLQCPqTIUwZIAAyh0yy\n        sahFIQEoszVFpWXuYNjh9nvD0VhdKhJvqHD6SyqcZVXO0uqaympvtTNc3zLU0NlbVFEZamzecvaJULId\n        sFLhCdR4g45qX2FJZaUz4A815BdV1rcPzJ1Z4QiGovG2yTV7J3btT7Z1vfr6Z/uOnlPMtkVbdz756tvX\n        Hn/+s69/f+muA1sPs+brmz/46ciKTa1zxvyhlDuaGplZv2DllvZ5877/s1/h6sFTj1Z5a6MNnam2/pa+\n        kcbeub1zZqa2HG2fWFgTikdTffWd89qHJ6dXbhxasLplzqLB6ZV9MCkWzAzMXzIwObNmy+lDx64dvXzt\n        yI1bFx69de7WM9eeeu305Xvnrt29/9xrT7306uKNWz21Td3DC89eeuLUxZtrtx9qGJiXV1iTbOi/cunx\n        T978+PCJy/OWbbr94htf/PJ3nnzq9YHpqfq2rjmjU81d/XtOnXz7s8+/+urHJw8+Eoo0mbPzQYEFhWWA\n        Y9X5Q9zPyVMRXAiAuwLkFRTnFZXk5BcC1GkBsBgsl0Fdtpu2Wm1SuwvpyliuOHbEjw+ND6VvYaWYDXZG\n        NvOLGBPGMixgEJh9e0gGXMyYsGoZkBWo9ynt6Y3BCe6JqxIPENSWGi4V4um6AVgb6MAhDYi3R1Q8d2Pn\n        kQGDdDyWSC2eGbkVoZ9XZQGRXUhCzhkNVosAuEDdFZIpoQ8cPtD4klSqssIfDZVaGGEWUhE/FQhAD0PC\n        2D44NjCxnARghhWV1viC/vlqJbAMdgGifSAmgg0WgBDATbEAtqitILadurrr3M0txy5tP3ll67GLG45c\n        uP/O525/xDTQz33vx0++/0VPAesAgOYq6DMOLCcYf4z+WPDwhF4g1RSQPb+A+LQG5Cj1YumsUBADBoQ/\n        BmgAZAACcEp/f8yDElyZ2hpldo1O49MyUOzXaqJ6Ta1e02DJ7HY6pvqHpicXtzW2eSurqqwWh17LarIM\n        TTBrdtioDXCXYDCBEjbTgZPEiWwhkDAqKSp9wn1Ecn78Bi0zf4ws3ZLNexW1jAs2QYIeG7AFlXvKrOsz\n        YbDKd9Skox1g5EzcpE2Y6AiqozVAI2DQpB02Uuc6jLoQ+8FB7ytRC60KvAPLviRhtMKklLMKTHEa9RWM\n        /TIXCExQaKCfBMdqOeaL9x/rCzmUQrPsDpapBe4Xig8d8Ac9zhRJ+YgBbiD0iwUA8M0juNPBAuwrFKyH\n        cge4l2Yq6kfgPnAcM9D4IAmwCEQ34BWwCz0O7M5j+0+OfGkIwW9JHRnIAPeH/LdlzAbiwwigx0YEOE6A\n        4OAkspF4ckzi/8G7wWrJNTICjF/BwABBfzYAHSdiqZAbsB4gjhcgvvM/Gcr8bHIAPvKtcAnzoIcsmQHW\n        Yz0EfiZ/pkoA7DCq3gczYALMsNTAQP7IklwgIYCKQDTujcRc4dpqX7jSFQT65xWXFJdVuN3RCoc3O6/Y\n        F0zUdw7kVzqKK13rdl9o6hzNzSstrXKXVLqKy6oLy6oqXD5wAJggUtfR0jPeNrgg3tCdoRiiPUMnbjz5\n        whsfdQwM2wvyy/2BR26/8Pi9l5989tVLd547evHuF77+g69+7ds/+snPX33/c/1TyxoH5y7ZcXjRpuOl\n        1f5NO/aDAB69/Uy5K9w5OJ5o6XQEgoF4I+uW2wbC9T01oVg01Rar6wwmWvzJOqc3GEg2dM4ZH1m+qXPB\n        0va+BfPnr5g7ubxrdMnwxKrR5Zun1u4ZWrBlxb6zN599+8lnXj514fHH77z83Mtv7Nt/vqVv4Zptx97/\n        4NOvfvMH567f9UTrSzwRf7Tt5JHLn37hy+u37e6bN/3si289fueV5dsP1XUOLVm9ac/+s5Mbtl164smX\n        X377+TfeW7Jhf3m1H7reG4iWVzrEY1+QD7gvLMnJzbdaH+ztzkAudwjIKSiy2fNpH+QwfcjGTNBsiHow\n        gaSBAriFACDnpUcb5Dw5gAaBzWrNZv4ob8XGREz4IQcwFGw0PegDSpOCqUEYMg8KyRZ3fJoAgJvqR6Az\n        gwFqFFcQljhL1a92BhUXDRCd4WKaETgKE5BRZAawnj4njtNjI0wgkds/oLl4+TnJc6p7uv5pCggJ8Q60\n        Eh6uV8MAHA+0/4NLbAYHS6J9YH7aAmDCq+j9dB+IfPYC4v7JDwlArQnIkToAxgBuToIA1myZv2LDzI79\n        205f2Xn2xuajFzYfu7j58IX1h87ef/tDEMDpp0AAP3n6wy/5C/IlCJwmAHX8f4yAP1b9GIXSFgJiX3X4\n        qLifLwEAnIAPmBIKm0BAX/aF50lNGv0ZFlY/ggDcMrxZCiyDqozZsBLcGdqgThPXajrtpsWpxKbpRSuX\n        LBvon5NKNvoqHZWmrDI9M4uqtBp3ljYiop44jiPsAGZ/6qXtDz08SRPbRHsMbCkKtgDoQ/4nzErSwvOU\n        ahBYMOiuaSTo6ztM+jGTfi6ZQDtq1DUQ+rVJoD9b/WhLTFqHmdwwwrIDVu2CBuJG2gEeyH+TDrZCpUnL\n        vE+gvzSEqAIfGJnuWW5gEYDboMeJmRygLZHdYHDETWAxVJj0+Sbq+kI2VmNiDCAVeFoiKf8i2zkD7FZZ\n        odColAAcpUmnSxzu2Rn6AhHyvEroZ2YnBLK4/ukjArAWya4ATPwXbiDOivzPZ2IPxTXQuUSoAmiL79JL\n        Q+eP1g6jJGM2XsyYST8+rtLdz7AEIwHgAFAUyADDTgOF1QAmQ1qq2yV0YcRrg9hwK7ICGIjuJkh+1W+D\n        lUB/ddjZ3k5vNigmVhJgAT08ZBTx+GMxPqq7DmAZXhIzMCzwCBoTdCLpDLJTfNZsTQGkfihcVlFRUFRW\n        4fS5Q7HSKkd2QWFReXW1O1hYUm4wmx3uQF1bL6jCbMnpm1rZOb64JhAtqnTkFpUXlTrKq1wlFY7SaqfJ\n        DBFc1Dd/5fjaQ9WBpEajCde13Hn2zWNnr3fNXxpv7cqy560+eOLbP/3JrSdeOXfxheN3Xjh+697Pf/nn\n        f/Znf7V0y7a2sYn1+08NTa+JNfWaLMXReO9///73z7zxcW5hjTcaq+/sr/aG3ZGkJxovczo9yfpoU2e8\n        uSdSV+/1JWqCKXeoNhhvbuwamb9o3aJN2xPNncn69r65U/1zJzqGJ3pHV45Obluz4mT3yOKGkYndR85v\n        2nN456FLb3z42VtvfW79puN9C9bsPf3o0y+++63v/+Dey6+5/XGNRtc9PPGdn/z8O9/9scsdyc+rPnXu\n        6pXHH5vZuH/n0StHzlxunzs2tXHHqSuPv/nRxzuPHGpqHxieMxUKxZ2uQH5RKXeMKSzLLyjlnu+57A6U\n        nZMPVlA5IDdPagLy80X406UDxrBxc2CygtUOHKeix5+UNbkMExP6AdxW4rsdNgDDxex9xsIxCn/WDai2\n        QjYjwKAKaY3ApFKofloGQHzcTTJ8xJufVv30whiZ6Anhr7p61Owdg1FKf0Xaq5XA0ueZYJ0mABW1ic6g\n        BUkVJVswXYd8ID3mBNMp+QXo8fEhB4gjiPNZDFHAyLDiXIhB0n5Uhw8tAIK+eP/JB0pmFgkgI6utf97g\n        +DKrPV8qvMCgRHwV9NNDrQjDUIvCZK8ezd3XP9537gaDwGu2zFuxcWb7/h1nr+2+cHPz0Uc2H7mw8eC5\n        NftPP0kCkCyg7/7kmU++GioqynxQCfwQ/VU+eIj+6jklv2h/lQCY6ClBYCA+PgL91QgwZqqEACoydGXs\n        IkA7AOeVmcIBD1ihiumeLAfzSvMfXJJ5OohcWcwHhU0QmqVps2SNOsoWNyTXzhuZmjvW2dmXSjb4KqrK\n        DRlFGk2FXuPJ0gaNko/PTSW5K2TEwNpgbikj1WEY7NDJOmHWB8AIaDQrMVHrdWal3ZbRaGWST4tJ12XS\n        95r0A+AAs36hWABghai4bvxU9MzWLxeq6DaxjswrnpwqEzeTGZSOEV5GC7CGNb2F7PDMxkGwANgdE0Av\n        3n8QAHATct5u4M4wBUbqaMBlqVmpwVOkvrdISnaLpb2aU0wBYCVQG2YBvshcSZwbWVWroiEWeyRqSpRX\n        COui+in8SyUMAEzHwAnDtryP3iXWABW0OOhz8b8Uv0hUBTHgCDIAowDZYRlkCyeBmSxZWpAB0ZYBW4aj\n        QQB4TxCMkRlBYhBIMTOUvo21YFwG6Mc7q0aMOG1gASiQ6vgVeFWQATtPMKLL9WqPCtwB6K9+xIkBa8Rw\n        IQEwLKxw3zTxd8GwYDAA3+XP4fbCGPib4EdZdJqcQmB9BRvR5Ba4I4nW3qFQvK6k0ptXUmowWzLxn05h\n        mcsb84RiRWWV5TW+eYtmlm7c447U5ZeVlrt8MBEqqtz5ReWuEAyIEKyByfU7Rhat1esyG9p7plavDwC7\n        O0YXbTk6sWpbffNQuTf4zmcf3Hvx7f2X7+y6fG1m165f/+a3H3725YbugcGpRRu2H23oGQw3NzPfP5j6\n        8rd+efn6S8UV/rySkrqWXlgVobqG2uYuX7w5XIfREG/ubOjujzd1BxOdvmiLJ9zkjTWnWjtn1m+bu2hN\n        TTAYae4eHF85vm7HnJXru+evmpnZfuTQ8bljSwOJjoFFK5fvOX759t0Pvvzpm+98vHrLIX/r6NCitW9+\n        +Aleaf/xqzmlHoc39Pi957767R9ev/Oc2VIc9EfPn7uw48wj+x65cOH61eGxpY1doz3jixeuXn/kzKVt\n        u872Do21dQ6XlXuravy5BezyDyMgN591Wzl5eTl56h4yhWzvnFOI+WxeKmKM15oDnsgpYB8hEAA9SLn5\n        jAbTv0/tL1o+HdqVnQDEW8QNimExZJusVOtprxHMBeEAbhYm8WF+iwlCNBGkUQTvYzRL1iaRnagtHEDc\n        B+JjmYC7eIHkBJMGtXkcwwkyKVShorwgNdU9jrQYOGnGmUoGgHuCPge9Pfz4QObLJXqT6OdhUPoBAWTi\n        WxhpxOdKCf+qQ69IFlD/3MEJlQCy8U/XlluYHtkFYgqoTiHuEkMjQHJDaQHcff2Tfeeu0wUEAli5YemO\n        gzvOXd994bFNRy6AADYcOLtm/5kn3/nozkefnH36xY++++OnP/16qKQEFoAK8Tn6P/h/HoK+evJQ/ssm\n        MOSAUkVXJh2hH5oCqlmAGdUFVKJogR3gACA7BrQ/BL6gvB4EAMRnZDhT62GpF5M+azK1LraI0DPth+me\n        +kCmDtZATKtJKJpBu36Jt3JVV/va+RNTY1N9vcMRt688QykGDWg1NVmkjRC3GVArBvRug9ZvIHxH1e49\n        TBOi5Ifwh2YHVUSMumabvtWWkbQqcTM3AHiwK6R+3KRfiq9wCwFd0sxYMbR8hYl9HcA0nbAATLqQiTsK\n        eKTTQ1iC0lHWDLMbRCnrvPRuPg5koIAJciU7vpi7vujLjYqa4gkIc4sfKSNLazdos1lsrOQywV8AF0gq\n        0A+2KABiirhmzo/MAMQZOBWPOSAVsA7OgJqmolfS2/xC+AO+QQMgBg7R+1wgOIuP+CJ4AouByNILiMKf\n        Mwwgc++wEjA3KISJ/9o88drbMmZjgAPSr8HC4/RLAoiNGZDk4v9hFhPwXTVZ8Ev5wlDrJhHseAf1zQXc\n        uW+MkVgvmwOL3sfr4Sp+rwr69OrIJXEiAd+5GIP5PyL/6SDKkOZFGRw4AQFYJAso2tA0uXRDz7yFXfOm\n        Jhdv2rzryMINWzuHFwajqYoaf7xpsG9sebJ9MLuwWKvXl1Y412zdcej0JUdNpKC4ONpYXxOMFFVWl1V7\n        KpzewiqHwx3q6Z9MNfXUtnScuPHk4OTC/KKKjrkLJzZsTHX2zl24xh9q2bH/+OuffXrh3v05SzZGmoZu\n        3nvxH/7lX957/5PO/qlk2+D2o8fX7jxcGYqDURYuOzA4tDwcb3QFU7GG7mC0yR+tj7Z0eGNNkWh7NNUB\n        u6C2sTfU3BKI1kdqW6N1HcFYg8PrDdY1T6zZOTC2zB2MhePNbf3jw5PL+qZm5ixasXrTvoOHbixYtKap\n        b3r9rgubtp185Oozb7z10bsffXb08vW2OePzFq56/P6b3//5n5+4cqvYGVuzbfvzL738xruf7Dx4ua5z\n        rHtk+tCjNy49+cT5S1cu3XxmxYq9bncyt7Ssd97inUevRuMNbn+ornMwv6iKuJ+bX1AIAiiy5+TZ8/Ny\n        C7k7GC0AsQYA8ewUlF+SnSe+oGxaCcwRkq5B9Bfl5QO+QcNGi9VKRZ+tRndpHDDnh83aQB709tjo+ZEI\n        MMBdjQpImyBSAuPAHEIeYAIMo4VGAEGcsQHgL4U5TujuZ0UYYZ3zan6nKH1x+6gpPWlpj6OQgVkc+oR1\n        uQmXKQwdsxpAQPyhPycr0yh2gEh7cevjHLf6o8Fl6iUSANA/TQB/NHR6vT4jUwhghTW7yGzNAe7bZagc\n        QO+/ahtJJAA0AEY0WWEo5Gruvf7JfjUNlASwHgSw69yN3edubjh4FmPdvtOqBXD3w0/OPvPSR9/9ydOf\n        fA0EkE4D1bPs64/R/6E1oA4V/WEByJ4wxPpyqQLDiTpgCrAETE7UwABnJBigEgAEvhwhPyn81Ziw2AFa\n        NTgsm72AAHQxg1IrG4SFM/Uxs5Ky6OqNs6J6TVSrabFmTngcW0fm7Fy7ecG8ybjHA2ujVKOpVGbhhirE\n        czNhtoWg7z4CI0D2BUswO5PRYAYPSAM6fGy0K3UWkkGTUdsuFgA4AEbAsInr27hRDNONQAABE4O09eAG\n        k35aTnBP6P1KI6O+IAAI/2KYBSY9OAAWgNOoo6I3KoUS7AUmwlygcSDt/guMerPUBJSxDRx7KVsNWtXn\n        46bnna0RqKNF7OOoGgTqxxKxD4DpAP1qiRAAzcEBuITb2o3iBGf7frp96AISyQ/YpU9fde4L+mOmiPEY\n        hgHAMfT8CLUAl4Uw6NuhxYBLtAbIE3YFmAt2YSZSjoGRatw8R8oIcgxpuLeJ/4dH+nzE1pHXVunHDLNA\n        kpf4bvIslRvsWdypGIDOWK7MSFIpQx2sfCZzgGMUsIVVHEQWCQjDdMAPxIxFUXBz7isg6I9LRgX4r+kf\n        mzx+5YlD126dvvXUyct3Hrn1zJknnj15+/6Fm0+duv7kxduvnHn0zootBztG5kOzYv3oik3n778cSTYU\n        l1Yl6hrcoViZ0+eNxAtKSqrcfm80GU02bdh2Yu2hC3NWbqhwuH3hJB6xZM0OkMfSLbv3XLjb1D9x/4Xn\n        rt591hGsc4UaDp+6/jd/8U/vfu7b7nBTqct58MLljbuON/dMeEMNDl/cFW2K1nclmvqCda3BRFMw3u2J\n        NftC9bF4T7yhzxOud/pj4caWWF17jTPiCsRgvriC4XKvL9beN718z8DIMl+03uWLhGJ1iZbOhv7x0WV7\n        1u84t/Xg5bmL9wzPX7dw4+6ZNYeeeemdZ15+58rN564+8crA0MLGzrE33vv453/yZ9Or9q3euue5V145\n        f/XGgUuXB1dvb5+/Ymr55kcu3Fq4dOP2I4/s23N+asmWqUWrY7G6pvaeOWMzHT2jI4uWFldU6/WGvMKS\n        bEF8e3auPTcnOzs3h14glolBotrZLKiQ20yyUQRdQHTu23LSZWLcURJYBtBnZ01x8MAaUN36guNEeWYE\n        EeKp8fkRTGAWawBfYZIoaEBFfCEGDDZ3k5BvWsgD5anTVQJ46IvniZF7ALAUQALIWE8vUBakvSwAEGcy\n        dmDlfaj9cQcsk6IB2R0sk7fiMg4JAPBEIsYP4J7CX1w9GKq3R60oVmeMGWpLiQyhFrkPjAOYCDp25M5q\n        G5g/vGCVPbfIbIfxmiYA+dMVYfIhGcAgsNjyWBCgNoN78rVP9567PrluyyQIYDkIgM3gdp29sW7fGaA/\n        xqp9p+698f6dDz8++8yLH33nR/c//qq/uBgWAER9/h+h/x9xAJvBqTSgWgBpR5AgPpW+SH5xAbEvED6q\n        HICrmAc94JxDQgJCADACKP99UvQrR3awAXb7spgtqvqFcAQNJOjSUcJGJWHOqDNl1LOqSxc2zEroNa1Z\n        moUB1/7FC0/tObBq0dJAUX6eRlOl0fj17DzqztAEDHQNqZsDRwwQ76wGAB9AwkcxY2IzuIQxo86SkZB6\n        rnqTttOs9Fm4z/tio25SrIFhk9IqzYWqTfqC9AYA+g6zfrtJP2hhkk+VicDnl3qxJHeZp02QIyn/5czq\n        0XmkyU8l8z7ZmAEcUCENIXJxQ6mWguSvkmBAnqROAnYB0DWEaSprjHLApUFfaNCXGpjlCRBXQdMpBAD0\n        xwxkO2AaI9/AtqOUyVJCZc1ia4ca8ftjlPMrjAzXiH0gAWTaCkBV4GyF3JCAK+hMUhHQh+7Owf3BEw+I\n        xJqR9kTlwXaRoC6NlQe4n2vQWuUEfIBlIC2IdPw0Uo6YKYB1fBf3hLrHb1En+QgMA8EdmK5aBmALdk5l\n        WpSYAlzPPxrYgnYMCUC9OQe+BeiXwmMQj0QC9LPyiktq/KGBsfGFG3YML1mzaO3OnccfOXnj/s0X3rj2\n        ykv7bl7deOjwqUcff/6dj/cfPeUNRdr6F1x+7I3uOROljppgqC4QTHoi0Sq3z+mPVlT7iytrVu7Zd/Ol\n        D+Yt3lzp8ZdWOFzBUKiubs2Ww01dPWv2H7z0wtvTm4+cPnttzfods7NMjb0jr73+uaNHr06vPTS8cH2V\n        ywcbonVg/sI1h2OpzpLK8nCqLRBtCiZbA3XNye7B2uYelz8ZTrT4oo2uUMITiUdSLdFUmydY7wnVecIJ\n        bzjuiyQ9wVSZ059s6J+a3N7YOe6M1PoiEWegNljb0tw5PrZy/fbtp/buvd45OJ7sHp7asH/H6UvPvvbO\n        gSNX1289ffbSE9cuXTt67OwnX/3Wm+98Zf++yy+99c5Tr7128trNVXjzU7f2HD6Z6JizbNXBx+69duXx\n        V4+curJ44bpwbcrhdjf3zJlZs2fJ8q3xxla9zpCbXcy9gkkABdwAEtBP/w8RX3qFsnIYNCBin7uMYZAJ\n        8vKZKprPbWyB+FabHZqfwQAzCwVoCqhOITVDVK4axacPJqBTyJZjocubDEG/kMQDcM6or0oA4t+n2Fe1\n        vAR+BV5xmvb/4EQAmhj/wFMkRoBMZkr6pnxXzAiIfZU8VASHzpfdAnBPUfTAbrr7lQwDhmA9bQV+Xdar\n        BADJLx95lR/TnPHwBOSRzg3VcUcGQ8fA2Mj0KnteEXs8PIB7oH9OfjFGdl6xPa/Yxn14QADpygCruiHM\n        3rMqAWweBQFs2w8C2H3+5roDZ9YfOLN236mVu0/cBQFIM7gPvv3DJz/6iq+4GBZA4f8PAajQny4KA+6r\n        AxYAaUBqwTDU5J98npMAVF8QLzFCQO8/BiihWMeZMvlIg0AgPiCxWVcmDQKAvoebAGtxEuAm8gwR1xqo\n        rAG7QW7/wmKuhElJ2hQ6bQyzY7M1yQzNomjgxMaNh9asXTU82O6pcZoNVQalJmOWY5amerbGm6HFIwJs\n        58l6YB+bQ5AVwC4+EIxZ12DBPLhBB/huNzMMIPiu22zSDZl0c5kJSqOh0qQ4zOAh2gpdRh2MgEZpAgo+\n        gKgHLUXNjBCEgO/cOUBfyI+kHL+Jxb3FEgG2iMe/2qjFMY+9oKUdEPS7tAgFSQDBofqh9B1S6gU4BuhX\n        M26sgAMkiiBNICRBHrgPTAciF2YpTOwRDgBeYwYLwBDs8pZB1z+wvpLbolH745zunQdB4DzaGYwuqB4k\n        OWFUGZcAx3Z2cmaWJ+Abj+M2MvJoIC9JAgQgQV0aCvwVIADaH/n8gVoQAMBaTBYaIvgWXgmGBe4AdMbX\n        VccUbmUUDrAK8YAbcMT726D0xVaw4J7i7jdlKaplQNtCtQzUWDFdQ4R+tSoY1g8+ggx4Z/0sAERNpBaA\n        5QyEiyurKmqCnQMTI2MrEu1DqY6e5u7+VTuPvPXZ57/z41+88cFXH7l4b/GG/TMbD7n8MWturj9W39DS\n        F65rLHXWBGsbcvNLfMHYvVc/Onz5iVKHt9LhSTZ2lle7K9yePacuzmzbHmyo7x9b1NY/PjazZXDOzGzF\n        uGnPwQ8//Vrr8FT94LzhRUuDifqSMl8g0tbYO9cbbqisDtTWdbpDta5wJJxqjTV1xRvaQ/EmIH44Xu+P\n        1/mizf5Yc6i22RtLepP13lDS6Y35Ig2+cGONt7bKGWrrHRuZWheu7/KEU2AOny/hC8RrWzrmja5at/7C\n        tr3no3WD/fNn9h86cfzc9SOXby1dv3Vm+ba9u04+duv+3dfe+OYPfvj8S28fv3br+tOvffyFryxZsm7D\n        it1vf/DBtsMHoqnefScvfuOXv3ry9XdSrX0do+NzJ5bmFJTFGjomF24dnLeosASCwZyTU0QftJU1XHa2\n        BgLiF0iHuCKgFXAqt6A4R7qEitunSDUacnMZNsBi2gpS80Uc546P9PtY7dlQ+qZ0ng+FLS6RA/AhpyCv\n        oNTOvWLYAA6UIGVlpApcBS7T8wP0h6gXWFeRHTNAZIAsTnAfeoHEFCC4i48eoh5i/4EfH6Cswrcq23FO\n        9xHkP7P1paAXlEACEOymD0ea+QjKq4PIjsVCD3KTP9DAwwUc/C5VP6H/waQB+I8X6BgamzO1Cr/UZMsB\n        DcgfsyhHdgB+QABFQgCyH6S6I1iObAiz75zqAtoMC2DJVhLAnvOPbzh0bv3B02v2nFyx69jdNz4AAZx7\n        9qX3v/3De+9/KVhcbNBoCvRE+T8S/mwJB/mvgv5DApBNwegI4rbAD+D+oTWAobJCkRSCQddD8gPugfv5\n        iq5Y0cEIYDRY7ADgO/u+sQOoPpTFgLBDEkZF/sNEYNEAkDrOtg1K1AAOoGOHAV7QgFnfYslImhWPovFr\n        NPWWjEV18XM7dlw5cerknn3b12/csHT54q6OYLYlB9ym0dRkzfYbdF4Dk0f9WXTdhIUVai1Km1XKAiQ+\n        3GzStht1sADWmvQz9P/oGs1MAwWyYwGWlUs0eI64ierFFGiQTQIg/BuNdP3ncIcyNgiq4v7AjEV7xeBw\n        mXRMADXp8kwsAgCEqeVgMAUg8AU6GSLGf1LA2TI6+rWQvaXcyUspkUZysABwCX8uEAAwFFq+AKKb/n3C\n        IrAbMzgCB4G2WGCS5PryDEZ6MfBdh5HJQoBaoDwfJPIflxxicFSIfUACELAGNJcxt4eOF+A4IBXwjauA\n        ZtyBul5ykyD/MaSIjL9ILXIuEQKw4jeK6od9gHsCpoHaoBm8CYAbdg+ewruJE5/6nRmf+C9CbzBIR1KY\n        AkYFdALmUyMBtCQYDBDtD/SXvW5sRp6nIwRYliHQn0UvkBnGtEZTVuGeO7N+ztJV/lhDaZWjqMIRqetM\n        tvdV+6Nlle6yMmfnwBjg+9Tjz1x/9s0X33h/66GLizYfi7YM5JVXl1ZVJxuamrsGE42tXn/IbM/pm7Pg\n        5bc+t/XgaXtRaUW1J1jbVCIbDs9fuK5/clm1L1LpcVdWOnrmLom39FY4vBt2H1m8YYs3UtfaO1rX1uui\n        SO+IpXpKa5zOSNyXbHZH6r2BSDzVGEu1eaPJUKI5mmqNxNtiDW3RxvZArN0XSAUTjf66Rqc/VOMMOZxB\n        jz/h9SacntpKZ8AZjvSPL69rG3W4IjXehCtS54kkqmvCbl+yd3TZtt0nVm3c1dgxvHhy84bt5/YcuXj8\n        zOm7jz+1eu3h7fsfuXnvxefeeu+LX//myRM3l6zccezihYklq8PJ4d1Hrz3zwssuX8wTTDxx//6zL7+5\n        b9/xeUtWn7x6d9HK7WZ7cWP74MYd+5Opdo1GYzTlghctdiK4muVJqMopstkLcgtL7WwWJI1CMVnA9FBc\n        ZXpPbi7TRnMZIWDNML38D4YZkp97RgLtpVyA8V5RuGwEZM8tyC0usecWSuKjBJBBEuwtypgBOAAQDyzO\n        ZN2vquV5niXuHWp/wXqDGZYBE3tIACL86TuSojAMXJITIrLYAUBwuQ8QX+7GBcz0J46rmf6ykvgua7hM\n        nVHFvkoAJAMShnh+ZP6PoJ/CH0fVdAABwJIAAQxPrrDlFEDaA+tlpC0A/oXVkAD372Q6kNobDue0AEAA\n        k+u2Tq7ZOm/5hplt+3ecfXT3uZvrD55Zt+/kmt0nV+099eQ7H7Id9DMvwQK4887n/UWFJloAWtH7fxh2\n        oQEB/fRg/o9OixlpBSEEAF0vHACNT9wXVw9GMR0+LBIuV2ZXcHNg5gKBEnBemaFVZ5yZWid9EdD7zAIC\n        7nthBKSLBkgAfibwcP+WqIGt/BNGBVreKS7yWguzOWOYydKHs3R+nQajLtc6mYzvGhnYt2D0zNrVV44d\n        P75n31Rnp9uYYddorBpuTxbIYk0A7hwWx04dm0boUpIGWmvSNtMCYIZPi0npljBACzeP1IUlt6farCuS\n        jR6Xm5XFFjaDY08hafYJ6MeyGqPWYUqnnwZMbOvml3qxAnH+VHFfAdoBOMcxG1gpHACAg01Qho/S3rmc\n        YQC9ge5vJlMCqcuM+lIzvs6QLxATMA18B1xCj5dwRm26oPfDlpKO/+IOEteKZAeVsW8oe1GUcb9JHYik\n        WEyuYknNBDSDA3DEYjwLd86mzNfhQTgHowCdIaVhN9Ck4AwtBsCxjTsSM0jLbbm4Mxf7GgH9C8W+ocOK\n        RQlcoHp4INXxS3FCD5K8MN4fM7gqqUQs6aIdIO574DgRXIQ/1tAy4PuQTlT0x8BVDLqMDLQV0qYAWIHo\n        TwIwZOh1Go3HG5peu31w6WpPOFFZ7azxBUPx5qbuwdaBufGGzrIqZ7nDGWtu7Z+/YO/xM0+9+NKVC7dv\n        333lwu3nRpZvxaXK6qpoHLI65I+lws1do8s2PPbka4eOPlrjC9W4Pc5ArSuYKHe5g6mmjqGR1sE57mCk\n        otpb3zHkjbatmtm+a++x4mq3wxfr6FsQj7dUOcPeUEOsobPKDT7qbOoeL6/2u9zRRLI9GG7w1TaG6loi\n        qdYwjo0dkXpYAy2hWFMw2eKNN9aEo85AosaddHqSbnekutpb442WOt3+OChqzOWJ1wSi7tokPUX+eocn\n        7I7UDY4v3LF17+jCdS0d0zPLdu/fd3xm/YZDF66888Gn5288de3xZ5997v3Pf/nrn/voC0ePXh6av7C+\n        rW90avOCdduWrdu6feshoIw/Wrdy095Tp07vOHxy2dEzr73/pcULNylGy4a9O7fvO2HLLdVotPac4tyi\n        Ukn1ybVnF2ZLEQD0vj2Hnh+JEEh6aJ70kmO7CJKEPV8gLL09AOS8xWyF+gfii0+frd+A99ngDyk0Y42Y\n        RYqEuZ7tz9g6AiuZ+skNHR8kbj7AaJoCRmp2FeUF6CXPR1I/yROSti91ABIQJqzLDKsEcC493QSXBa9V\n        jMZFupVkRu3+hi8JQ6TJgzYHxf5DDlCJQV0AAlA4VI8/H4dJRe7/YD3eXyelwO2D84enVlpzCsFwVsh8\n        Kv088EG2Kv/T6M8hMWESgLSDThPAFraDBgFsPbDzzKM7zjxK9N9zfNXOY2v2n3vqvc/dkTTQD77zo9tv\n        f+rLzzM/sAAeBIHZDggEgBmVFR7SgPoRi4H1GIXSAK70QRhANQXYDTSDNFChw/xs+agrpfznPAaMgHLW\n        BrMswMssIKC/1idxYKC/SzjAC2Q3AOu5DNCWMuqTRsUne0lKy2WF24FJ2o/sEMlebEE9rYGYRtOmaNqN\n        s4Yqig8vnn726tVnzp49NLOoxenI12hsGk0RDAK9xpc5G+wCEG+36hMW6nqo+AazvtWsbzLpp836KTNl\n        /qiR6aE+E3N7qtTQLi5Z9Bts3DDAz51kSB4YUoYGAmDLaJahWRSnhf1/mODPVqDMCq0wsKc0LAAwAbDY\n        LL2AimWyzEC4BJqDAyC0AZSldP1rAZTc+4WZRUTwPKModMFKwB9UsArTJoOSjz+INIGgBSAuGqhsYrGR\n        6UYmoz6XdQaSkyooDJ6QWgHejVlGmBGCARwTsjOZk4OPXIx3yBT3kdwfpKICupAQbsXEpBz2c9bmQvWT\n        27j/pepuwhowh6wnOWEAwXEkrwjHgJykrSnhm6xA9BegFzcR7QYZWIzfCyrCAsxzEr9doiNYwz+FSiQm\n        mgi4ueoUytRpfMFw75z5wVgiv7Co2ukORBLhRCrZ1JZob481Nzm9wcoad43b6/OHO3uHp1etX7/j6PU7\n        z7z17kdnHn062dVbWe32BkLFZUU9c+dPbdhcP9i3+ejZA4euON2hGp8vlEylmntDcXBDa/vovLb+vlA0\n        6Y3UO4PRueOrbt58YWrJyryiCn9dW2P3qM8X9fii1d6AJ5RINXTXtfTMmVzf0Do3WtcXr++Ecg/Em6J1\n        rcF4faC2IQyboK4jlGoNpVKRZH0w3hiub400tPqizc5I0het9XpCLn+yyh2vdIRSTYMN7aPOQNIXq/cE\n        ki5/wuWtdXjDoXjb9NjGNVsODy/ZPrxg84pdp5dtP9TWO7Jx7/l1+849+eKrX/nitz768Evf+NFP33r/\n        89t2noglOzfsOfnI9SdWb9525c7T9V0dgabW5dsOTa0CeJzZeOjs/tO3nnvpnd6hsTJn4Mi5i3Mml2Wa\n        bCZTLqsBAPQM/EKilqi4T3jKycsrhMxnfzfoU5s4grJzi3PyWEGGZbYcdrARI8AG+Q9MB5AB3OniZ7MI\n        QXw6/dU+EAwRgwxwDkPBKidGs03FdxVqCeiAc2aX5kDyU3pnmTLF9a8SAO4pe4GlA8KEfiCvADRwV1CY\n        UE6wJkar6C9KX6ICjABLbQEnpfUbsFsiB8R6Gfiu3EGMhjS1pFlEvSexPj0j+UXyLPUr/AkqAbQNzMM/\n        R1tukdQBgCOF87JzaQfQkPpjAihkNMX+YFN4cQExCDx/+fqZbSQAjLV7T67ec3zljiMrdh+7//YHd1gJ\n        /NKH3/nRnXc/CxYVGDWa/D9KAVJHtmC9ivg4Av1xgnmeSx2AmvgP4V+q577wRbI3AAgA8p9VYJIGivNi\n        yRbFgAVQ8iArtCqTbm5I/mimjj0bMtk3AlifjgBjBnoW0hjWAGaydNLTjR78MFtB0GLwGpj5HmWQQLp7\n        GpSY1PQmLQoWBDJmRWZpmvWaab/z6LIl98+fe/3G9RtHDm1bON0R8OOVsjWaSo0mbpgN9A+blTB3iNQR\n        /c1M6l9v1g+Y6RSqAyuYtCFpCeeXai88ZcisLDTrR2RbmLiUIOCLUekFVGPiXsEVMAu4WwC3EgMfeEz6\n        GnrG08mgQHPIfxbxyqTdxPiwGukFihkBo5laECT+IKWsA2BlgAN/ChNbihpgTIAmHwSEqXzFNZQt/pBC\n        kAdFsehuwLqBL1Osbk9GMFXMsEvMfCjOifsG2gdF1N2S6sMgAfPxhQaI2iWAVPH8gFEAvpjHs3IlEgBY\n        xyUwFtBf9fVjPY+ZbGqUY+YCwDSwGEpfBXEwE94W9wc027No8ahPsctDDXICU8DCjtOcZwxAfRP+cVSn\n        k7QMIjdI0wj8BYysRcDf027ievwxSRXqyNRl6jUl3BIyWlxaWlxeHoonYskmZyBSXuOudEJ5h5yBgNPj\n        9/gjNS5fcXFlTl5BUZljcsnKG88+e+/l94YnFpVVVsdbOhet2bZy9Wanz2XPLtiy68yhy485/AFfNN7Y\n        1d/QN1rX2h9tbI62tvgigPhwKJIoqqzcc/LS6av3q13hanck3jwQSba6fIFIXZPDGwrXta/Zc7Z33vTq\n        PUfX7zjf2jM31tgWbmkLp9pr4x3hVJMv3hxNNKXirbFUYygRjyabYsnm2lRTtAnWQLMnFIc54vXVev1J\n        WAyeQNzjT7WPLIh3DLhC9b5wwuWPerxJlzvp9ceSLUPzV+9effj4/EVrlq7eeejkNZ8/UZscjLXM7xqe\n        vn3/xS9/69tf+sa3f/yTX95+9sXlG3cMLlp54fFbx67daBlbtvf42b0HT2w/cGr3kZN7T549f/Xe3Jmd\n        W46cevuDz3u8zc1d8xav3BRLtFts+SaT3Q5pn5tP+Q91T6Wfn81gQD4IIKewlOkr+QU5hbjE4DAELPsF\n        FZbkFIIbWEisCnxYADZ2O8izAPdxtADErZC3VlsulbvkAkmlWI4JxGOhCwhYL4mbkM7CASrsmsAUuSAM\n        Kn1iOi7CUEgXChiMVrEM2M9Z9bowqV80uAzB4jQTqDPs+8bbSrsIQXk1/CvSHh8zJTgsT09n+KRvIsED\n        gfUHd+YRtAGMF5MC9srDxTwBXdEFlGnoGJw/Z3qlBIFzQJws/WXepxgB4gJiUZidOaBsBCRxYMYASABn\n        bkyuhgUglcDb9u88c33XmRur95xctevYiu1HZrYduvvmu3ckDfT9b/3g1tufBIqL0jEAaf2PoUI/VD+w\n        Xh1Af3zkkEbQ+XptnhyLRfsT9IUJcMQ5Toj4GUT84jToa3FUhziCGAaoYtIns/4DQHzYBJykEeDNoovG\n        C5mcxVAw0J+xYtlEnr57k+IxsGKgOlMPnmBkWHowhDLZI6jOqtRZJcZrooum3jSrdrYmqtG0FlhXdzZf\n        3bLhrYvnXrz8yIX9+1fPmx8rKYRNUK7R+LM0Qe4STO3fAuEvm730coN4aQhh0jaZta1sHaoEzUqjVb/I\n        wr3jm82sGeaWACZ2AQpJQLjUxCag1RZaDC42ENVVmpj5A60KkIIYL5FRYOIoMWjzuT8wo8QwAmAlcG/3\n        TCIabAW31A1UYEh1WCV+lEVfAyjMBDsqbtIJkdEkNIBzDDpeQC3cYJK4CfMiZOKGBHlm8bxDXBv1VpMe\n        MtlCMOUC9h+Fvqa7n/2fYV6oUh1iHMj+EOjVmCrmbVkZqtxWrwLWgekyL+c4qgRgokUCwsAaK+sVuC0l\n        PmINjQDV8pBLFgPRnzXDRnHvpPv8UMVjHjNYD6CH3lcR3yhVxGCLLKwxKHZjuiIMZgdYhy/D12P2kTlD\n        a9JpSisqfaFQjcfrCyejjY3eaBTQX1LhrK72+uN1NaGIw+MNRlLRZKs/GCkvKy0qqwiGU819vRNrV/f0\n        DweTjR1zJpas3dveM2bMsECPX3vulWOX7+QXl5Q7aqLNnaFUW7J5uCYQdkdCAN8aT9jp9hVXVs9dvnHu\n        5DqHIxBr7Eo29vujCW8sHq7vcEeb6ntH1h67NDS9bsGqXQvX7nMH/A6Xv6FjKNXal2yg9z9U3xKva4+n\n        WmMNDcFYQyjeGEm2wD4IJFP+WB1+iD+UcPoSDk802tyMycrqULy1Y3ByabSux+2PekP1nlDK7Ym5PNFQ\n        oql9aGr17oOLl65buHLXnnNPeEL1lVX+mZU7w3V9Dlds57FTN5967me/+MVXv/WNI+eur95//PTN26cu\n        POoNxYeGp7ftObFw7c69xy+funr9kdvPPHLl7tCCVQdOnD1+9HqkYbhjaGrB2NqCgnKtPgNy3k4/T1Eu\n        CCCXNasWK3cOyC8qzisso94HN+QXEu6Z0W8323JzCopz8rkY+M5cIJZ9SfUvd4bJMZsh9nPMFvp/zIzx\n        0sUPYMcJ7ANJFVWzRWGC0IMvuExEBugD3LneZBE+UIEYup8BAyIyd/qVVE5CMyiABCDYnZb8/Eo6918m\n        07eFGaF2n+akuHGI2lzDRwsBcBLrjcpDXz99SqCHdNkXZhTaEyAAnvCF0/QgPiIejSAA3LZzaJxBYEkD\n        zZbYL7S/lMWxpNHGaoB8FkKLGaQOcQG98eneM9fTBLBy48y2fTvPPrrr9M11e0+t3nV0+dbDS7YevPvG\n        u2odwPvf/MFjb30SKCqCBQACAL6rGl8dOAf0qzSgHkEDD4U/0J/engegr9IAruKEqZ+i9+nqEbFfAXDh\n        Rz0GZmAE4CoIwPWgMwT4QAiADYJUoIfGd4IhspjOHzEoENops9JAda/UyLe8mVru8M5NYBQgfkw6vjHF\n        06RLmFjoG4M8l4rfiGF2RK8JaTR1Os1QTtbGuPfJlQvfu/LIk1cub1y0pLO6wiWB4iqdJmJgm885Fv0G\n        C11ArUZ9O+/GrnAwBUgzloyIRd9l0Q0LAbQwZ5QPrTApAW4azF4OQFtpGUQ+wMsD7r0mCn+LQWsDB0iF\n        MGA6FxzALkCqw0TvMGqZ7WNkzg9MH6xhcS8sAxM/Au7zDPQ+NYqWh3JPGEAbCswIR5a+UpoCEWENSiV7\n        zwFtGWAAbWRzE2MQgGI1EsrzDToQADmA2Mq2E6wbgFh+0NuHXhS5hCFVCGlYp5BXffTitcc8HgfmIJqn\n        3S+0bwDT+IhXxZ1xjjWwHnCiupJABgBoYLrqoYLJAgKwggCEjTBjkicC6LEGKG9ixS8rCWQZ7sy4iFG6\n        ihLccZQb5oDt8DgSADdtBknwKfilis44W1Pjdqeamn3RmC9c740kK9z+alfA7Q27fFF/bao6ECyrcbl9\n        UeB8U2d/or41EEk4vZHiispqf6DKHQ6l2pv7RpPNAy09Y3MnV+47f+7e596e3rFPqzVotbr80vJgbX3X\n        8ITTH/aGk/Udc8J1TdVOt8uXgOR3+hM1vkSitSvR0ukJ1ToDte5goiYYi7S0jy09sGztsYGhBWu2727p\n        n+MOJFs7RlJtXZHmpmRje22yvbYBo7U20QiDIFTXFKtrBUX5YnXeWL0/kQpE425frMobCsYbAPEV1WG3\n        P94xNNY+d8KfaHYHk75oyh2KVHsi3mB9sqFnzsza5Tv3jy3ftmn7uVRjb00oMX/BuoVLtrr8SacnvnjN\n        7pdee+fnv/zV5VvP7zt08cz5x0+ev7Rm5x5nsKm2uWvD/kPTG3ds2nv0qefeePPjr+w8eaEiWLv94MXx\n        6dVdQ9NzxlbWVEcgqOnhsdHPQ32aV8jtw8ABAK/cgvzC4sLikrz8YoaC1eIvI1A9j4lAOZS0sKso89ON\n        H8AQ+MiNBOgXYnSXXT+Z4aMGcunA4V4urAszWaW/P5NEGd1V3f3c8R1UwT1eBH+ZCYoj1mA91uA+QhgA\n        XKCumieaRmdAL1s6C74TnckWAtBsJ2GixQA0T69nM2dFvDcyqdJJmgDEmYNzeo7+6CMH28ZJ+JdfJG3w\n        uw+ezsFWQFmmjqFxtoO255lt2fiT5uQXgylZ8WuxgxJYAMw2GMR9o1kG3WXSC2jfmevTa7dMrts6zv0A\n        9m07eXXHqWvrxAJYtuXgkq2wAN4HAZx55sX3vvE9EIC/uNj8IAislgHjBMfsP0oBwlD5IFcsAAxV+6vo\n        L3pfp24PCfTHoEHwQNSTACTw68jQYwgrMCpQk8HEf694hCQyrLqAuB0YcB+qn/QAE8HA7V/qjEqDmX17\n        ak0K00ZhJchGYLgKowH2QYJwz9BuBDaBOGoCRsYJQtz8nc4cNus3aeuyNL06zYBeM7fEfnje0LvXLr79\n        xK0jq1a0O6s8Og2YIDRb05Q1e51Zv4R7uTADtVHCA0mmA+lCFn2fhd6hCDeT0c+xcsuwFmk3XWnS15h1\n        MFActAN0VUZ91MxeEYBmSHIYAUQlo7aU9WJcUGnQCvpzLzCAdYlBBw5gSIABZAYAAHkggxLc2UALI99E\n        AAWmO6n0me9fYQSCc4tgTJbjI+QwG4vSNVQgkWRgIm5eaVJqoMfxdQYhFIcJiMm0eoKySY+v2AzEUxAA\n        kBdKHBBMh49gPcC0REDZKHEFoDm4B1+ElUDEFybAMvVuKhmUmCnG8XW67OVuuIQjbpULdDZm8DxLZ5Cr\n        kP84SqoPuz1n01/EZB4ro8r0LJEAMnSYwYvhiNtisIdoptBAprSSBgeYdeBduzwa9gfYDgMrjVqNxx+s\n        a+ut8YWdwYArEK5w+qq8AV+41hdKggNAAA6v3+ONRGKJcALCOeoOxCLJ5mh9A+YLix31naNN3XOcLn9L\n        98jkhp0nb9678cyLS/ft75o3WVBSlWXO7lywYGr99kiiyR+tA9YDmqscnkiqraFv1BOpKywud9c2tc5d\n        WFvX5grGgnWNxVVOhze0ff8jN+6+2tA7dOP5Z++8+Eb30IQvGg/XteAO8bq2WKI92tyWamiprW3xJ9rw\n        rWRjc7yx1RuIeyPxUH1ruLbF5Y1WewLeUEMk0eoN1dZ4w43Nvb1jk6neucFog8sX80ZSYB2HJxyKtnYP\n        Ti3evHvt7t07Nh0K13bUBEKuUHzbvoubd53GgppAbM2Ow9/7yS8/+NznJxZv2bxr36XbN45fvrFpze5U\n        a8/Y2g3Lt+wdGZk5f+n606++9fpbn0xMzwRT7dPTm8YWbOibvyIaa8rOLrRauRe81ZZjT9crcYvgbFaB\n        FQD6i4qLQQN0/rAdUA5AzcaCAPKERAWKxO0j3S7Fl00agNplgj/BnXrfrFZ4mVVHkDoPJjBIyj+umrgx\n        JE0BDJ6QEtj/Waq3mPpJ2pAqYpIE0RyQrWpw+usJzVDlzMTPYDBAAsIY9O+rmUVpvBYoV9cDx0XOpzmA\n        lzivLsskxIMBuJi3Uj0/nEwDPYcsxgvji3IfkMrDXkCjPXMXAtYNdILlWdlCA2SQg5+ZHir6c9hwxPkD\n        Ajh7fXrNlql128ZXbQIBbD52adPhi6t2Hl258+iyLYeW0AX0/h0hgHe/8d3H3vo0UFZmYiGY9qHzR4V7\n        jIfoj6FGgDEKhQNU1S+uf9XXr8PHchkqMYAAVHc/sB4DBAClr1oAgPtqhQk/0gWIzhxof+h6DKC5uHe0\n        niw6fxglztIFswDr3DTYl6n1Sx5nQGA9SBpIkwHEftKSkZJt36HiYyZuIxOQnFHuJsZaYu4ek7Doh7KV\n        HpvSkKFpn62ZV2TZOzr46rXL7z9198KObQsa6lqzrQ2zNa2zNEOZmjGTboKN4bjte5J9RrkhTJ/Eh+MW\n        fZ1F6ZfGonNNugEJAjtNeh9bgeqAR1UGnd+sgxFQRJcLsF4L1V9p0NWYGP4lAUhekNuoc0pAuFh1DQlD\n        lNCTQ/FulMaiQSNd+QW4TyZjsBT7gobAYqwkXIrzx0GbgCgMQK8UZ71F3YiGTUbpILLQLNBXGWg3WEWt\n        kxV4W8h/Fh4Dl03irwdk58jdQEjAazNd87AAVC8/tDxPSDCi1ukISkt+BWIcjKVKctY/ix2ABZD/Npga\n        lgy7iQ0+gdpkF/FEqTxhgh3Abs98kM2gpQMHa+Q+zECFdcLgAW0F0oZRga3AMK+YEZjJt+jzLPpsizwF\n        DxXLwGbSWTM05cDjcG2l01vtd1e5akqrqqo8blcozN4+/rAjEAHoB+P1kdoGrydQ5XAGE3Xgicoad1FF\n        eUWNs39iDXRuXkFuuaPaF2uet2znK29/+p0f/ujtz7584vz1/YfObj94on1oQaS+M5xqDiab/LXN+fkV\n        /dNT4zu2l1a583Lz5s1sXbvvfCTV5A4l2udOxuo78vIqN+85+sEXvpUcHL5y9+7Nu88lm3sqnN5woqm+\n        ZSCaagskm8N1bXXN7XVNPbGG1nhDR7KxK9nUEo4nQ4l4ON4aiLU5AzGHF5SWqm/pijc1VzmDybru/rlT\n        bcOTDe0jNZ5aTzgVqG3AD/KFm1qGpkeWrNu2/cjJ4xci8fYaT7zCFVm4fO+KtQdhBOQWltR29N198eVf\n        /+rnpy/d3rXnwuXHbm3ae3j1ln2TM5tjTd2jC1eOTa0am1n7yGP3X331o+defL1+cKhneHrFsq1Tqzc2\n        dA2yGoDQz/Y+VltuDh3WhG8QAAsCCorzCosLisgKNnuBTHIbYckKLbSx9T+1v4Ut77Ot1lyGBKw5VhtM\n        AUaDzWbKfDrxWX5FDlBxnMXAAuvQ9YKGAH11m0Y1KYjJ/mrCD9BZSgRAHuloMPfwEnUv0Kyqcu7mqH/I\n        AeIb4tW0E18EO1HeQDdRWsKnB40GDC4jB/BbIIA/RAJkmXwLJypP8OtpDqDBwWWkHDqU1G6grX0jvaPT\n        QHYaNNLflAQpJRcq9JukBTRpT2iABJDOAjp7fRIEsBYWAAlg4+Hz6/afXbbt0Irth5fSAjh49433QADn\n        nn0JFsCjr38UKi2xiAsIiP/Q/0PEB9A/4ACVDDAwo6I/BlAeAxyAQcR/AP34CEoA+qu+ftXvLxzAE8xA\n        2ruZ6ymNgLIY/oVNAPRX4d4lFQBeSVWEKQCID3NfF6K8VIqRJyD51SwgTAYM3PsFEB+zsC90rewTGQb0\n        S4SAFWR0DemikveJI0iiw541lJs5nKPvNWgatZqBQsvO4d7H9u999cqlF0+dOjAxMVJZ1qXXtM/SNOk0\n        ySyNy8SmEe3ipo+BEoQA4iaSjdeig5XQIDvMAEyLTdqghc3jyiRvJyS7wxeb9eVGxgOcRn0NgF6y/qth\n        vmANC8Sg5UkAGPlZTCLymLj9pMuszzExYFvG/B+l3Ey4B44DTIGGgDkQQBXBjnIeepw2AU0NYrHqn8EC\n        C3ezIZTn0r9Pr32WqGN8HRAJmwAmCEDcmqnLkOJenGMe6JwJyU8Lg4iP+2O+SJXnAq84KZUjEBm3wkvm\n        S6laofAWCEANSGAG6Ix3AxthDXgox0SCwSOyYZRYodkJ9LgnoFwaulHswx6y4QSvgVcVKySPkV7eGX9h\n        PBT3pHEDjQ+GYESdf6hss94md4Pwx2J8McesNes1nkjUF6nNySsoLK2sdLqqfJ5KVxB2ANPqA1Gc13gj\n        vlAENkGNy1ft8ARqk2WO6rLyKnyscnm7508NTIxXu1xFZRUGoz3V1vfup1/89Z/+9js//Olf/+Vf/+bP\n        /3rX4Wul1dDcrVVeX7UvEmvutuYWH7x4/cCpM9ztyxO7d//t42cfKyytdvpSo0u3Lly3taLKPWd6+Vuf\n        fHF4fPrao3e37b9Q6U+4I5FQNBGpbQzUgUhaI3Xttc2d9a2diea2ZHNHorEz1dRZ19kRrmv2xRq9sXpX\n        IIqXrfHHWgfG67v6K2s8oVRr9/wF/WPTrQNj/toGXyQVSXT6Q/V+XOgZG5y7anzxvpMXbtQ1dTvcqVTn\n        cLKlL57oSDb1ByPJ0rLS+VMz3/jWjz/45CvHTz1x8dEnLt56auHGA4vX7Gpq7qxxBdfuPLZw04H1Ww/f\n        ferF1z/48slLt7zR+rHpVcu3H+9fuNFkskNuS+pnATjAZmP/BovFzrowqH5JYOcO8vlMALVmF9jz2EUu\n        r6AY6G/JZpdQiQTkmK02C+MBbB4nRoDsFkk7gF4j8fhbCfd0enATGBH7NjVCIB+J7zJsoAFgK8O2suEX\n        VLwsVgmDBAC0zcoy0A6giifiy/gDAQhYp40DFhOQLYQwOKMK9nSyEGS7Po3vD+AeQ5bJVW4VoEYXZPBE\n        AgB0ND14IuPU6g11OgUM0NI70jtvocmWzXgGCMBqp5ONgd88s7oXmHTK+2NKIAHcEwKYWr15EgSwevPM\n        tv0bD51fu+/00m2Hlm8/NLN5/+ItB++8TgI4/9zL7339e5deetdfVKQSgAr0D40AdajngP6HkyCAh1hf\n        LPk/GPhYKimh+aqDSGq+oPRBA3JCawAnKg2w3ydrxPSS7890l6pMeopAAEB8zDAOnKWHBSC+IDbuB+x6\n        JQcUhIHv4hLWMEKQRfdOQjJ2IkZFMkRBDNT+oAfQQNiksJ7AoAMZhKU5KJNKLUqbTd9pVwZzMjpt+jq9\n        JqXR1Ju0M6GaF5ct+O7pE++eOrN/ZumqULA110rHjk4T1muSxtkeC9N7ekxKv0Xfa+HOwJ1MEGKzubCF\n        jR9qLLqURQcGCrAfnLZGdg3zgJlkT3lQAl7Py0gAg8DlzP9hEFgNDqf7vhn1TrMCS8IlW55VA+zM+koL\n        U4wYChZ3fznsHp4ToNXKYVwqAkNYFKwEB+SyCjfteDGaGJXNw2KpCSiCLmYJAs0Isojkp0L7yx5b3ImM\n        UVkjdbdVYgy4CfCUdCLK3SIRXdwWQAyQVf3+wHrpd0RPjp0wTcGOBThiAPHx6HJYNlZ9sZWt8TgPEgJq\n        i8teXUyPjYHd/3Hb/EyivAn4DvLA3cxkCCwuMCngsxyTLt+sg97HPH4L7CS75UH+j/iUQDwcRu0sjaZz\n        7vi8lRsqnK68Aih6ny+ehEVQ6fR5wzFXsLbaE3E4/Y5ql8NV43B5nN5gMBZ3BSNQ1h5/bVW1s2f++PDC\n        mUg0UVgMrZo7vHTmwM17y7ceffTWU7/9i99++NVvzF+7I5RsaRsaivf1R+tbSytxy/oPP/vmqVOPzJ6l\n        TbX2v/3hVw+evmzJK4vXd89sO7zhyPnSqpr6zu6Ld+9PL9/wnW9+/8PPvt49tCCQavHh0Z6Y2x/3hGq9\n        sUS8pbOxa6CubSDR0Fabqos3NSXbWmBJ+BJJfyIZiNa5gklXEAQw1dY3UuP3+SLxxt6RsWUbe+ZMBZON\n        oWhdvL4/0TYQSjV39AyPDq9o6li4ZsexutZuXyjVMTydaO5t6ugbGFva1TMSDYMUPWcu3f7q17777POv\n        vPDa28++/NbpCxfGF61J1PU1NXVNrdowteFA3+iyAyfPvP7GJ1/85FtdbUPBeOf0qv1L1x8tc7h1Oi0L\n        viDqcwsttjwzt/8l+uNjthgE7ACRz+pfk4XIhZWqX9sunYKA++K0YTd/U7q8i3lB6h5hULjMc2eg2Arl\n        azLniN+cjnmGAZgJmq4DMEovOXwFuA/MBWQD98Vrz/JgcQpR+HMlk0RVtS4wLQTAGEB6Y3d+G1DNGTVQ\n        DGOCceM0+nOoHh55DXUS51yQviEvUUmJT4nOogdPkUtck2GQW4n1kCmZrND+sABIALAA5i8027K5JSSr\n        4VjnxfBvTj7OVZtACICVwOADo1l6AYEA9p59FAQAC2DBmq3Ldx7efPTiuv1nlm47sGz7wTQBvPnebVgA\n        z7z07te+c/GFN72FTAN9mAUEiJcAwB8hvrh9MHCOSZwA7tWcH/WIwTCAEACtAUUN+XKUp5mAvaBx4kgH\n        A9IEUJmhB/oD91UawMBK0IMK/SrKA80Z3c1iEQCwm6IeV4UD1AVMBDIrwFmoe7p9jHqvgR0mcE7VL9wQ\n        lJ1bYEa4hUUgvX1GXdKiNNmVOhvbATWalZRxVoNOszFD80y5/aXBjje2bb5/4NDxrTuOLV2xvK21vqww\n        atA0ZGo6jbMWWPTTEiVW64Fbzcqw7AMcMQPrGaotNXEjSaeJhWN+3NmsK7OwjzQGDIIa4L6JLTOtEOyy\n        yTCELYwAWANm4CnENZOCmL2Dm8A+YO4/29gpXpgCQgBATFgD5VTxrAIDNNcYWaXstmX4rBnQxRDm4AZW\n        mQkK4yMAETM2yQqFfAZKArWh03G3Eup3SRNiZS/x18Aohb7EpFBc0wJgziX4CbgMGwK3KpCAMNAfwl8t\n        Z+MdxKSwGBWbQHyRuIAg9mWlvtyquHIzKrMV6RfE57KwS7aOwVWst0n5Lh5E+wBHcf2DVHAJrwRuMIrt\n        UmTW5YrDJ9emtwH3zUxt4lM4FD6dXikwkM6WqYUGH1my7Py9l5Yu397S1FtVUVNSTl+L019b6fY5gkEg\n        fo3DW+HwghI8gWgklvL4gu5wNJBocvnCpWVVXYMj85dsSNa12mxWfzw2s+9Q78y6Aoc7muw6c/25s7ef\n        aezsDda3zVu95bPv/vDc7TsavTIxuex7P//5orXrdPrM0ZXrv/Dln+4/8mh1tGlg3oolm4/MmV5pzrZ7\n        gqHJ5Rt6p1b82V/+zV/88s+G5i7yxFrqWvrbuocbugddicZSt8fjj9U1t7cNDLZ0Dtc3tUZTyUhdYyjZ\n        DHUfxHmqIRxr8gRrO+dM9IwtqfbWOoPhxu6BiRUbeudOSui4OZxs90cSobqWoXkrli/ZG010tvYvaBkY\n        D8Sbo/EOXyDe1D2wadPBFas3+IIhS07OxNr1n377+8+98fadp1+8f++VV158a8GKddNr9ly7fDfV0OKK\n        1HWNTM5ftPLxu89/9Ts/evreC6FQ3byJ5Ss27GjuGcjMNNlsuYLmajeIQnqEqO4L7dnc49eel19Uxt2D\n        zbY8A2U7E9st9mw2/pQMHyAsJTYkOZ02AG52+Wc6EHe8YkmwxWLFMwB2WWytDLRlXqYK3ypAg0LoHbIy\n        QYh+HtxKiq1wN4C++IWwHlo7XQTAVB9gMRs5AJpl/5a0HsfN02gO7BeeyAJA078kIl1FbZUkmAhEFlHV\n        vXpDlSTSHCD2BAlAHEQPlrH6jD8W59L6geeqr0mr02ZmmXrmToGbLdwRDH8EZr6qjjJJ/gEF0u9PpxDJ\n        tcBmzwMvPowBPDq5ZsvkGhLAqt1Ht5+6uuHg+aVbDyzbdgAEsGTLwXuqC+i5l9/52nceefYNb0G+WeoA\n        VOcPIF49STt/6PH/45H2/+Snc/+15XodBpiAZEAaSCd9qllAFP6ZaTtALQED1rsE5UkAks8DAqhWCQAG\n        gbiGqlkiwHQguvuB15lM+cfHIHv907mvXvUZHnCA+HZi5AmuDxkU8RqROVImdoeGAQECcNFflG7a7ARD\n        0LBQIswUUlJWpdmm9Nj0y7N1+4ya1VrNmmz9qpjn0FDPE0sXXtm9a9/WXQtG5jW5HS1m3bIMzQaDZh7U\n        PbsD8c51oBmzUmFRKszcE4aZoGaIcX2lXI1w1zBWhBWbCcEl3H6STYEAUtUmLewSkJbbpMPiIiO3dC9n\n        fQA3Cgb00yAAH5hYrADroZTBXn2Vkf6WHANLxoB3drEbSsxKtZWJqgB6SHUwBNYYiM70umAxABoiGvcE\n        WGcJNONBAGIKeTap5oZleAFIaWhzOlVMZA4bQV9RA7mVmel6Bab0sBaBXwcB5EtLOyB1Dn8UCEaB9UDy\n        kB6o2WA7cJ5F77BmlFkh22kr0JmDZ0lYolhOoN8xYLgQxw1pTw6eRW+PcJjZrLeYdTYofcxA/tso/MEE\n        eJzaQJQtK2Tg5+O7tiwSwPDixY8//c75U0/uO3Zm7sLpmoA/t7CsqNRR5nDCLHC4Ak5fqMrlrqh2Ot2h\n        UKjWE4o4/GFPuBYzRSVlHT0DUyu3RVOtxoyM/vGxZbtOBaJNufkFGRlGf6pzbPVWR02Nr7b18p3nf//7\n        31+9/7xGM2vH3hNf+O73q2vDtiLH8+997pMvf33r0fNTa3YNLVg5sXo7qKNzZCKSbHK4vJ5o/Ls/+ekv\n        fv0XyabenNKSeGNX5+jCwZn1I4s3DkyurG3rq3C6SxxVLi+3BovWtYfizcFogyeaCibqY42N0WSd2xMe\n        nLtofMlGbyjl8EUaOgamVm/om5gGxHvDdS5frKLSmWjpHlu+ZcHSXcFQczzV1Tk44Q6nwBw13mA43rFi\n        xcGdB853zpmqqQl09c9987NPnn/nrVu3nrt+4+kn7r5y4dbTe07cvH7r9d0nj0Wam8J1TYmOgS0Hzr36\n        3kc//uWv5o4uDkRTyzbuGJ1cWlpRA1CD0gegW9kYriA7n4W+4tnP49a19tzicoc/FC0sKTXReZ0NtZ8l\n        bn3odzPUvbR4I1jTFU5xD52LGaI/Y57SDI5q167KZ8Fx4wO8FmvAaJWIKNE/DfcPqnzFCEg7/XEJgygs\n        ZEDWIWSLoldFOgAbU7iD6imS4LPKGZhOo7+ayK867mX/yAcaXxX7vCHJQOBefUlV+GM97g6S4PsIwag/\n        J33VYJyt1cKmGVqwbHhyBeAe5/jVEPviAhIvkATMzZD/8pEjtxBMAHOKBEALAAQgMYAVuw7tPPPolqOX\n        l247uHTr/iWbQAAHVAK48Nwrb3/12+eefs2T/wcCAPoD99UTVf7DLFDbRGNBscKyXoC+qvpBBuCAciXd\n        B6JErfJlERMRHwSAIwZm1BhApSyoydQT7qXZA0Y1G0KkvUDcBZ4VYfoqloNpgdfAfXCAWgCMI8wCpwh/\n        VgbQmaOEJNUH53GzPqlaAFn6sJHzoAR6h9ibgU0j3JD/Rl2tmdv/ggC8GOrGA2Z93KqkbKwHDlv1wzbl\n        bI6y1w5Fr5nM1GxTNCuss9Y5Czf3tu/fvOXY/kNzxxeMel0rTLrxDM2oUdtuZT6o30qsrzTrIPCDLAHT\n        hy16wHENcZ+hYJ9ZKbfSOADUwjKACVIuwQAX84V0FdxzWMsZk1JuVCplXzDAcR4rkPnrPCbWAVA1C+zW\n        ZNE1BEAvF/c6jABgIrRwvolZpKUigQH9AEGYDvgKUFV1jMDIAJhiQJ7j6+AATOJZxVDrsh9ZhZkuFzwU\n        Kt7AvhQMOxcadAw8iOqXLxK18UWQCtDfKngNgMY7QL+rxINJPJf0IO4aEADNAvCZhQHbXDNhHUwD0wFP\n        Byfx/aV+jdgNxlKDB8JkeDE8jgQAXjEpFoaOdVlZWu4/gwdZGOeQKAJ3n8/K0BoNGOwjnWMiAXTOG9t/\n        9vGDZx6//uqLF599anrDtoJyl9FkLSipLCgsLy2vcfhC1R5PVZWz2hXwRSKB2rgjEKn2B8uqcbW8rXvu\n        ko3bw9FEaVnZ0i07xlZsd/lrXYHa4nJnZZUzlmrKLatctn7bv//n//z+z//cHW7NNGc///J7X/jGD93h\n        xOjk8t/923+99fGHCzfvWrr6UHv/ZKpvqHVk7Js//tPFS1fP0uiM1rz3P/+Vf/7X/xqYsyjLZnOGagO1\n        rcmOOeMzm1bsP73u5LmlW/YMjk+GahMVla6o7AcQiKT84US4tqm2qTWSqnP7ggOjk9NL12JNldudaOlZ\n        uHbv3OkN8cZBT6DeE6hzBeo6BxZML9vS2jvhdtf7w/VN3UPhWEesvi+U6qioiVR6kzPb91+88VRv5xy7\n        Jfvs1cdef/fja9dvP3H/pUfvvvjcC2+v33Vs+Y6Tz7317u0XX5s3tarcEVy9Yd+9J5/99vd/ePXRZ8ur\n        QlPLto+vWBdONABtKVSlVYPNnpOdl5+dXwACkGYG4q225TjcwWCktqCo1JrD8iWshPY3At1tOWoyqMXG\n        cC4bcBrNRiaMmg0Ebih7K3NDud5KQE8X2TJqKoNQjvvQnrDYmPlDehC0lQUEYn6LTn8xDoDaIu3pfOet\n        1BkCsQSE8UUuo4XBp6tDnmsA5uuVTL0eFIDvSvs5o5khXxXl5esq7j8kAN6WBoG8htgQfDRTjDgjTAAm\n        I5fgKTq9AoE/TAJYDtzH76X2F6Cnx4ypU2pr6CIcpdyaBIAjrC4SwJ4zQgBrto6t3Lh0+4Gdpx/dfvLq\n        ih2Hl209MLNp3+KtB+69+f4TH3x8/tmX3/rKt8499Yonv0B6AaUd/epQLQAcgf6AfgzZBEZFf/Z1UAkA\n        uM+dv/SS9c90zzTuq75+diKTMmCcq8n+ku4JhqBHSC3xdYsLCJcwD+MAH10qK4i0Z4MgtX2bQRc1KuAD\n        cAY+xmU3x7CBx5AQQNIibf2htQ10nbODkARmSQwmtgzCfaKc1AL9/UY+Gi8QMSkNVn3KpiRsiuTwMO1n\n        h1XfaVU6bcqxnIzltowus7YvSzOYqVldZlvZ27R33eqTO3avmj/eUVbYotVMZ2jajLMLLDqHVY+beNkf\n        gk0gyiyM4oIVHIwNgAaUIpnxMhaqM6Z3DRP0ly6h+VT32mKGB0AAdP7AJiAxGLmjJGMG0gWoSoVCAzu7\n        ucUOgHYGXBKOJWSaK74aQKdR8Be0UUw/u5JFbAV2KzgnjksXCqsxnV6J2xaIfVAooewKkg0xFGTDYC/h\n        lcvE3U/UZqc2njC0ALzGOS6RTkAAYmSAGOj0Nyk5RH9SDp6VAxvIqiu06rItCp6ebWZqU5kYOkB5vDwf\n        oca08Z5GkhB+KU5wB3zdbBDDwowT7jWfqZ+dqegy8TK0CbjpWKaEkWkiCIFlm2eDAAYnV1y5+/LZSzcv\n        3Hnu2u2XTl24u3T7/nhnZza7VBbmFRaVVbuqvSGXLxyIJ6JNLaFkg8Mdgjqu9Dorq6vrO/pWbDuUSrbH\n        6hsnVm0IxpJgjnKn31+b8HnChfllOSUVizds+93/+M93Pvy2vdDROWfOz3/9F/dfenvuoqWvvvz2X/z2\n        b59789M5i7d1z5latHZLZSCx/cC5//797197/xNHdUQzK+vSzbv/+m//tWzzjuyyMn9tqra+Ld7cGogl\n        423tyzftvP3Cey+8/vHuUye6RkcDwWQ40RZKNAUiySA7hrZGIvXVTlfn6Pjkmm21qbaqGn9tU8fUut2L\n        Vmxpaet3+iKBWCrZ2N8/d+3wgjXRui5PtAnaP9XUU986UN850tw56g7FbTllPeNLrt56ctHSZTmFRWu3\n        H7j19FvHj19/4cW3bz/1yu0bTy+YmhlduPLslbv3nnpz596T7kjX9IpNj99+4umX3vz089+cP7kh0TN/\n        bMOWWEtfXkEZQJNlq5IPylrfAgkL0wggdgPNSyqcbT1DLq/PLrFfLBNHP2uAJWIMecuoJviAwQDJ9Kfv\n        XjxCEum1CGKmIRsAmoZmBmm5gANfYakX16jKXVQ29f6DL6r0IOQhd8jkjAVPEYAGfDP7U9Cf9gFP6Ofh\n        TYRsDCAA1QIAMZmsLFHGpBotIPqrPiKxAAT3hQ8wo2BGzg3AfQ5AP+7P26aZwJiVYdTrM4xm+9DEDIwA\n        KH1aAKr3H+jP7CnGTnILinML2RSPzAoCYFONNAF8tuf0oywEIwFsWrbj4I7Tj247cWXFjiPLth4CASzZ\n        evDemx/c/vCT88++BAI4e/8V7wMLAHr/ofbHkTMC/Q/9PwB9uvj17OupkgFd/0IDxH1x/ReTAGgNkBJk\n        8/eHAQDQADBXJQZx/WsB8UBzIQCAPkEZ5yAA6fim9aeDvSQAYH3ESHWPc9W3Q3w3sUtogD0hdFD9SStd\n        PUF6/In1rAYQDsDimOwIDwoB/gLl3VDQGVqPUZewKM2WjHo7LABuxxgy6taa9fOtbPW81qq0ZitOmzJs\n        V0Ztylybdsqs6TRqBgoyLzZE39+6+cSuffPbW1uK7KEsjUOvKc3ShC2zR2z6dpu+zKrAmAAZOKQ6rIjJ\n        oPTwAOVLTLo8s5QBm3UVZm0lBLKaAiRmAcip2MiOOvnM39cGTNwzEpZBAUgiU1vEYC+NA2pw2W8AjIhJ\n        GAGQ8/liH0DLQ/6DLdTsnSIjSagIIj2LSI0FgG/cH2wBsQ9zBARgYBYmVTb+SkBkwD1uZRcZDlDOyeJ6\n        inGp2MIy4D6lt7AO/f44l+6ehWZdvkVXAoEvFAWNj5fMkRAug70myv8KCzhAn2thdIT0YFTYFtusrkzb\n        AbAeAPds+g+4F1MAd8ixQOyTk6zAd2h8WACwAyD5M7UgAKtRa8LHTAmimHU2JlApNiGABSs3Pv/mJ488\n        cufwhccPXbx55PITjz73yoFHbnYOjDsDwdJSh8PlqwmGa3w+byAca2iOJhvLHe5qb7DGHy6vcQdqEzPr\n        9rd1j9Q2tA6NL6p0VxeUV1a5Q75QrT8cLa2qLip31oQaDp+8ufng6a7R8dvPvPidn/3s4o3Hzly7/p0f\n        /uIXf/qbl9//4tyl2xav2QjVvPXQ6ceee/X19z/+67/73cSyzRnZeScuXPm///f/c+DkyUqPuzZZH00k\n        403tDW3dtfX1wVC8rn14zoJ1q3YeWbrnYCDR6I82xlItoXiCnYLqOwLR5tIKV9/QokVrdidaup3BcLK5\n        c8GKLdOr1yfqWjzeeCjR0NI3PL54U+fI4nBDuzcSD9Q2ppoHEy1doYb21o55rQPDibaBupaR6WWrl23d\n        Xt/RPThvYvmmAxu2HX/m/mu377106+lXl6/fMmd8xdETVzft3H/88o0jF6/MnVpy8MS5R24+/uwbrx+7\n        8liqf+7ooq0d/ZO5BSVWG+DbjqPFyr3g2fefXYvz2SvUnm+22IBTjR0DDa0duXkFdG1LczfxbLDPATjA\n        xj2E2d4SdoA0B2UJGCMEDwS4uGeI44B1On5U/a6m9tPzg5UwGszgAO7vaAKFiBnBXCCqbBoW6cphJvZI\n        9JiDMhzn6S0eCfoPCUDCEgRodai0oep9Wh5GXOW3xMsvRsCDQQsABCBWhfpdTuJIM8KYQduCu1TKPO6H\n        25ozMoxard5szREX0HL8TUwWu2j89MjOKwQBqE2hxcOW+5AecvKLxAV0+voDF9DmFTsPbz91dfOxy8u2\n        H5rZsn/Jxr0zW0gAdz+iC+itL3/z1N0XPLm5IICcBy4g9cjxAPdVCwADiA/cV6FfHWq3n0KFKUAckvaD\n        owxifdWDAC/3jxQygCmgBoEB8QB3kfwAeq1Pkn8c9AiRGEADNAiy6PFPZClR+nbAFtzrEYAeFqd/rUGp\n        lZMoTmRHeF7i7i5MDOXWj6YHKy3s/Bw2K+wgxB1adC4JCMOwaLAqjdl0AQGpG0z6hWb9pEXfa9W3WfUx\n        q77Hqutjewmlxa50ZmekspWERfNMhuYHlbbXFo/fPnF0z7Ydk0NDfbXRzrI8j2V2zKCpMmk8Vn2zTQnb\n        2DsoaNa7LfoCyQLyiZZnBBiGi7inSs1acEO1NJsDGcAsqDFpC4nL9K7UyD6RJZInmmfgJpFWbhXAYHi1\n        5GiCDquypP2nJAKxcCydBqorz2JFWDEMDjMwkbGEYiMwXQcLINegAMRBOQBcIDtUPAAXoh60QbEvwj9P\n        Ar+wHhg5IMTT/4PFTPYXm4MinUfgNSvFcJNCmz7PSmJjryEjwwx4LmAdZCNNsMkuhTal3KbkgxLAHHIJ\n        Ah/LcA4OyMN6M+wABS8mRgYWMKSMSawBskPpM1XUIKBPtxIpwSTy35BJAsA5ycaMq4rVLC6gwfGTV+8d\n        O3f5wqNPnH301s4Tlzccu3TqsadO33xh3urtsbrWare/wuUpr64uKa+scLmdgVhpeVWNB/o+UV7jclTW\n        LFy9Yc6iRcXlFcFYwhmIlNW4/PEGhy/oDgVC8ZQrUBtINdV39NtKyjbuO/E//vN//erPfvPBJ19cv+PI\n        xZv3fv/733/8re9sPf/Iky+/8dYHn/7l3/zN5cfvj82s+ud/+x9bDx3VGo3L1uz67V/+bvPOvYUVlbG6\n        xkh9U7ips76rs7l7oKmpp6GtI97UE4y3+BIN0frmeGNzrLk10diaqMNJd7ixtdzhGpq7ZNHKbZGGNmc4\n        WdvYsXDZztFF22sbexva5/cNLRlZunp8/dqeseUNXfPcwUh771hj12g41R2obcNXGjoHmlvneAOJRGPH\n        4lWbRhYsH5laOrJ4ydTizVdu3L1x+9mbT7955fZTI+NLN63d/9iNpy5cuv30K69tO3xs8YZ9mw6ePHvx\n        8rXrd/omV/UOT05Mr84pKIR4f+CwZglYdm4eJm05TGC3ZBcA0IF3Va5A/8iEy+M3W6D+2fvBQtCn6rfZ\n        8mABgDDADYByBgAsVqOReC0YTcjGeQZoAEAsql/IgPv9qugvG/aSEkAAJAM2gFOdQmn+wNeZBsqa3gfg\n        rqK8nJNLpNxXPWHUF5SgLlP9SIL5QP2HgE5TQEjpDzMPCeDBpDqENlS/kPrmLFTGc9VjFhtX4LYmrU6P\n        Fx4cn5kztcKWXWCy2lW3D2lSsF51AcEagLWFPzibZwhDpAlgz+nrC9ak00CX7zy89cSVjYcvLN1yYPGG\n        PYvW716yWSWATy889+pbX/3midvPubJzVAsgjfsPXP8gABlanBc+cAEVUv4T94n+4ACcyBAjAOjPkIBK\n        AzAFmAuUqfr9qf1hBDAkoDALqDpT65ZUH3BDjdoHVHwy7ARn4O6+mKxhsFcJG3RJ4Lj4/VkOZlQAfzAF\n        IgztUvJLlS8IgKZAiK3imHMJ4Y+Bq6wCszAfH9+CZeAz4J50AflM0lk6UwfaSBLrM2AidJp00yAAq77V\n        pvRb2fVzqVlXZ1IA4h1Wfa1dKc5WwtkZp/IyHrdp3rRqng2UHx6fc3jjhn179+3Ysm18dLTW73IaZ0UU\n        jcc4q9aqr7ew+Vq1VV9jpSOoQlAecF9oVkqkazR9ViAGNmjTGSH/Ddxn2MXEGG6DlZuldRh0TrpTSAPM\n        0ZTMmWoD/giKC3DPFCAAvWKjHcB9GaHQod+B4yWC46r0tkvmTxmIRAQ+RrlEgMEKqvuIa4CtovTVr+fj\n        BcSA4P5idB+JVBcLAAxhEpsD57AD6KUBslso0tM4btEVmMFzpD0AN9iFt2UHJH22RZdvgynAbFF68016\n        K9bI64EqCixM7uSkCVCut5kVtvfBHwdGjJVeHYuB6G82cMcxi1FrM2lBCYYsXWaGLjOTf0B85OPkW7lW\n        7exZGlcwsWbr4V0nL+06emTvseMXLt8/ce3egUtX7r70wWOvf27ustVVTm9hSUVpWTWYoNIVKK1wVta4\n        PaFYJNVQVeMsKi5bu+fQzMYtJaVlrkAgWFvnDafckZgrFPVHkv5oMhJvGpi/oLm335xTMrR43Tsff/F3\n        v/uXn/3qz0YWrjl58dH/9b//9ze++b1v//BHP/z1r24/+/ojl56odtUuXbv+X/7r346ce6S43OWJ1J+6\n        +uzY4tXVvmCsqdWfqgvEG8K19U1d/SPzlgwMjUQSddHGpnhLRziRqo2nEi090ebuuva+ZHMv9H6l2zu0\n        eMnMpu3RRGe1K+YJp5atOTBvenu4rmt4fOXKdacWrjnSPXesqWskluyKN/Wu3vxIa/d4KN6QauyvbRxs\n        6RuLx1vcrlg80dXe2dPY0z+6cPHKNbsWLz+y49zVc9fuXbr69J17rxw7dbm9c+L0iYs3bt07fu2px++/\n        uu/UpUXrdk8uXP34pdtTMxuaevrmTa5pbBsEWEkAIFe6F0ClstbXkg2VKsOeA+Az2/IaO/sb27tyC9ga\n        yGxmr3+VJCB4IWnBB9n5+YA2ILgRBCClW8IBzAsyWW2ix3FIV3UR2Q1mWAkGDKmqBZ4ajFbR1yQGSH58\n        V7BbtoanxcA4MBlF+INH4QBcIm2k14gHiQqdNyR8E8cJ62J88KNKADL5EO4fCH9x/oAt8Kb/BxngqiA+\n        h9AA+YbWgMlgsuKjdrYW7zAwvkQsgHxaAJL9yWiKmgsk1hLjwLb0jGwOnJ+dV6C5/8anu089uoC9gNQ6\n        gAObj17aeOj8kk37ptfvmlqzc/GmfU++9f7tDz++8Pyr73zt20dv3nfYbKYHdQDZDxNARfILDWhxAgLA\n        Amp/nQ5wz7xPIP6DjkBAf37MkPovMQXK2W5eVwRrgGxB4Q8OAPpjAPHx0ZnBbb8A9CAD2ASSI0QCCGWx\n        fw7sAJw7sxQoXMFxifqKEx8WACZx7ssioAcNqvefPqKwBH4h/Dvs+iYbS8Ownlk60tTBT4cJjQwfjmAC\n        OXHBBJE624hZ6YEFYNbNs+rHrXoc57J1hBAJrpr0UaveZVNK7Uq+XRnKzXitIPOpHGUqS9Ns0AwXGiaj\n        rq3DPbvXrNm4dcemefMHHOWFmRrQQEumptqsc1v1TnqEFLdZKQdWmlgpViwDPFRs0tI4kMTQMtkipkK6\n        hBaYdDkmUkJVFkuFYRAAcx1GwjpOgOZsESqO/mKDUkm4h32gNWdqAdCQ+fhdTPIx6WtMCswFLMNXYOUA\n        xzPEfV8lTnaAO6wEvInDRIsBgpq6Wxw7ucBQ8d5gGQAar42V3LBevaoOOoiY2lRkoSufmT9mxQYmsPBX\n        4CsgBnKAbHbPiDFuaNXlWxWrlbo+36wD6IMzrKw7E18/KMqiy7HyxAJSsfIrIIASmxT6SrUXhD9oAEer\n        WWc26bKEAGAEgDYYKsDjzEq2VZ9v15kyNRBNkaae9ccubN1/cN22nXfvPf3Ms2+dffypk4/d3nXq0ZnN\n        R0cWbUo09pQUlZeUVXlDKacvVO0NOTyhQCRaXVlTXFa1fNuhxeu3V1XX1Pg8wVgsEEq5vWF3MO6L1vvj\n        TXUNXQ0dfZ5osrjKk+oYvPvsy3//D/9w/MIjq3Yd+PgL33jt3Q/f+eBLf/k3f/uXf/sP73/4pYamLs1s\n        5dTN259++Wtb9p3qnzNZUFoebx3qmb/EF0uGYvXSCzqZbO2sbxvsHZgYGpnqHpk/snRpx5wpf7weZBOJ\n        NzrC4baBseG5K6J17eVO99jMhkWrdwVjrQ6n3xdJrNh0cnBsmS+amr943arNJyfGNnf0jLf1jNTWNc+b\n        2rJo+b5IqjGQbMb965uGcPPmjj6cdPUOheLJKpe/rX1wyaLN+/ef3rDz5MHD1y5cvbvv/PW7r7y649DJ\n        eE/XwSPH7z7z3KNPPvHYk/d3Hz+fahs8e/bS+m17GwcnmlqGhuYvdQWiRjb1ZFuC7NxCEIDatkwy1mEc\n        5Jgs2cA7hy/cPTjf4fSCMKT9J6A/B7hvy2X/OKb92CX9X3Xom2gKGBkPsMBKwIyKv8IKFhXBme0DTDfb\n        gKqqxBY0p91AIY+VJhgHAFxx7guX4ARkZGCpMJW+ePkhwB/SANcQmskTf9D7OKbd/eLbwQmHgP7/B+XV\n        GAAGqQIf01YCaIMjfSuVBnh/vrD8NOPs2TrwWd/8RcMLVALIJsTTLcad3830m+XKYDkFTAQJnBRY7ezC\n        xGZwu09fUwlgYs2WpTsObj52CRbA4k17p9ftWLBy2/TGPfdAAB99cp4E8N2Dl5+oNJssGg2wPof+n1ly\n        pPZX3T6YF+jnOQgA0E+9Lw2fcZ73kABE+BPuJcbLgHCmtlKwvkyhL4jaX2K/+KLToPVBgzOiq3MobBFB\n        myCDJcHAaLfsBwmkBsrHxU+iIj5DvhD45ABd3Ei9X5OJS7o6MzkgYWbDOCxutDIazOQfzJiUegubuEWF\n        AzxGBRZAQPaLZ1JQpi4IkqB9oNTb9F02JWblnsDzLczoB1bC8mgwK10WXcxMyHZZ9R57RsKmTNj1Z+wZ\n        8+0ZHdm6djv0uyaQqQnpNYNFxu19bZd27d6z6+DI4FBZRRnuHNZrSnHVok8wRq2EzfpSi77SQszNNit4\n        ihQNaMMmXamZrv9cqdsCGmbTUNDlStIkYLeAzYIyaswKUBJoDrBmjg3JgPXJLvH8wDjIgREgtbWAe7dJ\n        KTTR1OAABzCqzPIxYDEDBqK7YQHgKmR+vriGAO64j0R3SR55dM7QiV9IDxJX5kgrUzwa2t8Oi0HUPV32\n        EPIAaCvxHUgN+Ga6p4XxD7U8OO3zYQoQf1QeABrDTHcQeIJhBjEFuJJPZLA3T7I88RXcHOtzbCQAu5l5\n        pTb8lUCQFtKDGsc2ZMAUSJsUIAbyh0mrn61JtrTNW7Fp3c5j5649tuPE6d2nz1+5//wjd56eXL+mrXdy\n        09Yrhy7dH1+22ueP5haV5JeWOdmyP1JaUV3l9FQ6nEVFhaPTK8ZWbncFaz2BYCRWG4jEXYFITTDi9Ied\n        /oQnkqyo8ZdUVde1D4wv3fzO577413/9t5s377967d4nX/7m4cuXvvuLn//wp7+6++zr3/nhTw4dO1/b\n        Nbhp9/lVGw6MrVo3smBJJFnb3DnQN7bcEQx5/cn6loHaxvZEU3swmEo0tQ3MXTy6dOWcBdOp5t7ajv76\n        tqFobVONL9g3Z+H0mr3BeGNJZfX8JVvGVm7x1zZWOnyeSNPMhmNDE4vizT2dI4snptcPz1s4unznyNJ1\n        7Zhdfyze0OoKxhq6RxONvd5IXV1zW2vbYPvgRHf/nFRda8/AvOnpFd0dcy+cf2zn3hNjK7Ydv3bz2KWr\n        5y/fevGV9+cvWd/e3nv9+mOXbt184umnbz39fG1T24Y9h/eceqRn3oJ4ojkYbYk1dpfVeADOqi/IJj2i\n        gVC2nAJgN4wDIFeWyWTPK2ruGm5o6cSCbG4onw+lTw6gyM222rLNlhwDq1vF+UOMBiJbuV+kJdtotBI6\n        gdygBDOlPdbQqyOhWkFVAreI6/9D10u6DrNOHwIu3gSXxBpQJ7EYX+QRrAAU5jKhBInuqkr/ofbPAAfg\n        JM0BxHqygrhxVFuBQ+wA9eQP3+XKBzMqGYhHKx0M0Gr1esXQPjB/iARQQAKQJqCs9mKSq2yZIBwA0Ae/\n        ineI1QDZecWqC+jaAokBgACW7zy05filzUcfWbJ53+SaHePLt0yu33n3jffvfvTZ+Rdffefr391z7tGy\n        rAyrEIAaBFY5QDUCsoUAVPTPV3BM+/05MniOwWRQfNTT1VOSoSvJ5GYvKvpLGzg16qsrZg6oOqN1GbhV\n        enUWtX+1GAdO7g3JE/WjJ5PSPprFfWBiUOvM16S6Txgyag0KCABMAD7wiDWQsCopK7eLAV7Xs/KWeUEh\n        7iMv/X+4bxe/i/vgCPyNsDBYfEEwKSyAfqXJpjTY9TEby4NHLboFUuLby36fSpuZbeDKJZsTIrfOqo9b\n        6dbvNeO5OpgFddlKT44+ma3EcpSkRVOXqRkrt68f6T21ffuZ/Yc3rFhVH/DmZWmKdJpqw2zgbJWUCORY\n        FJeFyZ0VDBLoMK+GhfMsBMd86Q5UYORJCdFQWyU7SqZMituilJi51xgAGkhth36nWUDxrkpynHALMMC3\n        kV6ysEnJMdEjTwGORxDouSYghWOqwKfvhbdi9wXwAc4B7rA8GBIwkgMAqVgDSAX+MgkH2AqyEejnEfAt\n        why4X2zVF9n0FVYSD9C5wKYvsZKBbFl0N7GI16Kz08+jK7FnFEoiPzN2zIwPA+Wp/XEiSt8s+0Hi6YB+\n        hpFhl1g5T8cR3tyiL7DiEZIGauErZWWyfg0fQQYmcWdZpA6gbWT+rnO39h55/OrtV7ftP9o1tmTdkXNH\n        rtxZtG7z5MbNm/Zf3LDv7MSKNTNrtk0v2+SLJnJgClRVgwCqPaFqXyS/qLi+vXN0ZlWwtrG0yun1RbyR\n        RHU4Wu33e/xhd6DWGaytcHodNe5U95y9lx79wU9+/tYHny5cs2XTtkMvfvi5L33v+z/6+a/uPPvG/pPX\n        fvGb3/z13/3TF7/xvedfeWf1viOD0ys6Bxa4w/HWwXnPvPzesZPnXbQqUvVNvaFoyhcO17V3dffP7xmf\n        6Jue7B6a39DZD8THcPljLX1jE6v2giSyCwpWrNm1cvV2d7C2ssYfTnYvWX14cO6Mt7aloWd4YnL95IrN\n        c5evbe2d7wumeoYn69o76tu7OwbHahu7A/HGtoHhwdGF/QNjsdq2mmrfxKLVuw+f6R+a3L3vwtZ9x5Jt\n        A1v3HrrzzNPnLt556skXbjzxRENv7+I1O5955p07959/+sXXQ8nW4emVJ89fmjs2f3BkvKikptodjsTq\n        S8udwNDsXHoq6NMXtz5QzGSymS02QDzEbo0/2j93wuny0ieUnW3PUX0aFLmAde4EIKVh4ocBHFtgAZjN\n        7A3HcK6477GMloHAt2oKAIXxLYvdbskmVlK/q84cNSOI57KdC1hB6rDkznIkzajufgOsBAnz4hI/coaS\n        n9AseC3qnlj/f3r55fzBDI+4M7+ucoDMCD2kCUA9ig0hrYT4RD4Cd9DqdDp9RkvvXAgKQLzJDIuKoWCj\n        WvqbzU0i8RGUIK5/2S8+TQCSBrr71FWVAMZXbVq67eCWY5c2H7k4s2X/1Nqd48s3L1i3487r79798NNH\n        QADf+N6OExcg5M0aDd39DwhA9QXlCPqrRgCHAlOAEWCVAPAt4D6HnBQrJADI/FJuM0ulT7Evfn/Vw1Mq\n        wWFMVkPJZumrMvVgAsA9lLia6sN0fnqEYAeouwKI8BeI92bSAqilBaAA+hPi+QlLQFh1BNUaSRX1FuYF\n        1Yrfxg8+MOuB7NDgjA2IcZAy65gdhPVWzPMmCVtGsy2j1a40WfUpu743Wz9pF9e/RT8MLsGkhdYDUNtr\n        ZnmXj9t76dss+k1WfT/IwKJvsioxdpXQD+UotXmZ8RylzqjpztK0Vmav6W28sm713oOHpxYtrinMrZY9\n        KbMz6dZnZYBFjzcsMbOHaJlZyWNCpBYfK03MCCqTDNEicgCkt65GOkNUGpVKAq6uACxi1Fdxw0ilwoDB\n        j2aArLSJhjUAhc6aZ/p/CLvAaBgQ2UaCeAY76dM7Tx89+EAUOughR5hD0mxoGVjpUCL0A3zxUfzyhHuo\n        b7Zdw4w6yCsi86XSjc0ebDpAM34I5ktsSr5NsdJNTy7BZIFFB+EPqgCaF9p5lV0cxGWfZ6XnJ9fKGUA8\n        gwFZih1GCamF1b8gIbwG14MJyBOMEKh8AAKgHYCXtJLtMLhS6gC6RxY9/tLnDp29N7XqwPTK1et2Hly9\n        4/DYzPolmw7uPHd12abdrT1jLb0jO46eO3Lmiabe4aLKqrLqiopqpysUC9c1V7g8gUhkeGR+or6hqLS8\n        yuVz+YPgBqc36AnFfCEgdSoQrauq8lX4/Hdff+U//+u/V23e7Ymlzly59f0f/eLv/+F3N59/Zc2hs1/4\n        5vd/97t/+7383//+X//3Wx99snjVnvV7joUbWp3e+h/94E+/8JVvhOobKt3u2lRrtLE+1t6Rahusre9o\n        BTyvWTNv+ZbWzhFvKO6Lp1zB5JzxZZv2nQjWNpSUu7bsPrVy2RaHM+SLpFoHJ6c3HGponwd1D6Nh3ujS\n        JSu2N3X0pBo6amqY5NTY3dk7f87AvKlUS3uqqW3O2OKlq7b29I2EovUOhy/V0Lz14LG+6SV986dXrtvX\n        O3/pyOjSG9funb5898r9u8+//MaildtGl2594rl3bj/30hNPPtfRMeSKJPadudA/vGB84YaCooqc3EKf\n        P1lb31Xu8ADjGLcEstNrkS1ebOC71WSzG8wma05efVtPz8BoIJIoKi+3WKxs+sauDyQJaS4k3huTRZq+\n        Sd9/qx10Iqqf8A3IZlNoE4MEEvsFtmZa7dkFRSV5+YU2OysGqO5pCuCSIZ2zr6p+mgiU6mIiAP3TMQYV\n        oLFedcqr5oLAt0B2eojefyjz0yjPBXwQT1jnpbIL5jFJ6E/bAXKinmM9zAu13bSi3ooLQADSC2hu3/wZ\n        sy2PQWxWP9jMkPpl1UUVTltOoTR+yPsD+rM6jG02VBfQ1XQMYOWmma0ggMubjlxcsmnv1JqdEyu2Tq3b\n        def1d26DAJ5/7e2vfXfjwROF2lkgAED8AwLgSa5uluoFKpBQMK5KOlCaAMoE8fMVbYEQgOoXwgABqAmg\n        DpH/hHu2fEj3g2MMIBPor6vBYAEwQapKsv6B0VDoQGS3ZAF5srTcwz1L78oUiBcEZyaogZ1BYQTEWB6l\n        +LME3GEQSLsI+usNUhwgkj9i4r6M+OiVjdpDJkB5RtKckbIqSTud/kD2Djvz/RtAA3alOVvbZ9eP2ZQJ\n        i74dhgLUPTQ+CMCiBCyME7gsOr9FF8ElizJhVbos+pCFZNBh1jdb9BGbPmRXoraMYLYCs6DdrPEqmi7r\n        rJWtifP79547dGyivb1ar1E0msJZGvxkdvuRvhEQuRDjpexyQ7EM9AfHBCRWDLSVzFEGKvAroPqBvGCF\n        RhASwB1YzzRQAjcIgP53+RtW0xfEijAHo740F6rMbKEDDQ7tD40PrITwl7oqVmOVSgyA8d4sdnSQLH5y\n        BlEYdo+8BiOrss+MIYuwC8EOzoAqN4sRACYoYvWDUgx1b9Pl2fTsz2xSikEAkOryCJAEmKPEmgGbIJdK\n        n5GAguyMPHvafQRiyLOoHeJIPDAULNL/R3UB4YhzK16GWaSckapgqQ8QYqAXKJPtIszCByAJu5UEMLFw\n        3WOvfTy+cl2svm3Bsi1HLt6dN7mkqsbRPjy2dOv+4enVdW09AMbBiWVjSzYkW7q75s5r7Oopd7hKHDXe\n        2pTbFw3GEvMmF3b29NW43a5AwBMIudzgAF8Vt5MMONyBGlcot6Cyf+7Yt3/yg2/+5pfu2mSkoeMbP/rp\n        v/zDv/7uX/719O27aw+f+/f/+p//+Lvf/d0//vO//8f/BAf8+7/+29V7zy7fuT8QS0TjbR9/9rVf/Plf\n        9c1fkldUWtfWHm/vCNV3uCOpQLJhfNHq5at39c5bPLhgpnds2h+vd/pjJy5fuf/6K9HWtnC8e+vJK0OL\n        ljoqQ7FUd/fYzPjy9c3tg+FUa0PL8KKZTcMTy8qrg6HaplCw0RtM1Lf3Do5OD40ubuqY09Q7Mmdy2cIl\n        m/vHphau3TR3/jJPqHb9zgMDY4s9wVhzJ/42II+5uw+cvnjr/s7DJy9cvHP15tMTy7YvWLnz9I1bz9x/\n        atH85TmF1VMrdkST7fUd88urPFqtPhCpq/EFw3UthWXl0NqQ//Y8wBPz/WEQqALfbGU6UF5RWWNH//DY\n        wv45Y+FYKie/AOgMjKatwM28GBTFYmAfu7+ZbAYLDAN2hqD3hsqdMQCDkXECI0O+BGvcuaCwtKi4LK+g\n        EOYCwBeTki8kXYNMzAeluWBgKpEKxHyQxITVO0hQIe1BShMAhDn+n/iu4nVWZobq53nAAep4APGqeYGb\n        YKhwDxpIGwfpI1bKJgE0DnAub4JBAsjE31BRsqQZHAnAwCwmtnvLKSyrcAXKHF4QAD1szAhKa38MfszJ\n        19x/4zNaACoBwAIAAZwgASzeuGdy9fbx5Vsm1uy489o7dz789OILr735lW+t2nGgYLaGFoDgPtDfLkNN\n        BCIryFFlAlgAwHpAv5r6mZb/4gjCuRobKIAdILhP6JdRlqEtFuOANCApoW4AvUhUBnsh/w06Px0yD60B\n        FgcA94FuOKr76waN9GZEzcwKVTNBsSacRTjGZEKyKtUTIHtCRgiTkjAasUgQWDYJSFky4lb6/QHi9daM\n        9mx9Z7Ye6B+3K602/Ry7bgXkPzv709XTayGyx21K2EKMpr/erDMB/sz6IbESgP6dNiYROax6p0UfsOrL\n        bfqATd+Yo/TkZHTmZMSNGodWEy0y75iYe+HMmaO7d/fEo8ZZGp1GY5qtcZhmu4GJkvsI+ZxnVaqsCrAY\n        uFbJcjBGjMuAgLjKsi+648EWjQxmUI+DAqukFU+lbAYA9Af8Ab5BCdDsakKOS/4yPpOSa1KA4DAIqqQV\n        BFW/WAB2MQKKoeKJ46zydchVEA9+JhaX0L/PbEtqatUzA5aCHseMmhgqNwEllFmZ5p9t01fa9FWAaXaF\n        05db9A6LgkuFoAcYCraMQgC9eHtKbPoCu2K3K1ab3m7T5VrTXh16osQLhIdS7+Oc3KO1GLVsUwGDQAjD\n        ZtHZrKQKwD2YCfIf0G/CH4EnEh82MguoobdveNG6ts6567fv3rj/aFPvQCgci9e3NnT3N/cNpZp7auta\n        I6mGaCpV19LZNbpoxYaD/fNmIPy50W2FA0APIF4wvbxrZF5xVU2V21ft8fPoC9QEah3eiNMXLADcFBXd\n        fub+j/7sV6OrFxqz87YfuvTj3/zmZ3/6688+/cLmLcfO33zuv/73//rbf/qnH/7iT77/k1/+7d/9Ezjg\n        d//275eeeLLMDeHedvKRu5i59/zbBZXueGNrsrnXE0xVeGvb+uYcOXNl+6lrfdOLxzdsm9i43ukJlrsS\n        b3/2hXc/+cQTTtZ3je+6cLNzYsLjj7Z29A+OTI8uXF3fMVTlCPVNrFi2/3D74PxS7nkWi8Qaa+s6Ew3d\n        HV3zegbHWntGG3vmtA+Ndg/Nb+sbWbxz39jKja0DI0ceeWJsYmNRqcPtS3b2Lkh19ixdv+PKzScWLlg6\n        b/G6q88+39bXY8oundm057nnX9m++VRRiaeubY7Tn3RHEoFU0yyttszhdAdi+YWlkdomHAHowCmrnbuX\n        qGmLLP6SaDCAz2zLKa2oTta3jk7OdA7OLSopNTHkC5JgH3wgtcoWMAvo7ZE2D7gKnIdZwPiwQLmk/Mt5\n        FvOC7Nl5hUXFefnFBrP0g6PKNmWZ0rEEOoUE7h/CLigAoM/aMYF7QLwsA/qDPOj/IXyLAwjYTYYQblAx\n        nZJfhD+/mEZ2lRUM4nGCXSKT4gVSHT7qGq4HAaiNJR5ygJQRaLU6HNv6RwfGlgkXskOqJTsfBFBYXp2d\n        XwqDADMSWlej6yoBFNhJAK9/tvukuIDWbZ1YtXnp1gObj13ccOjCog27J1dvG1u2af6KrU+88vbtjz55\n        5MXXXv/SN5Zt2VMwS2MhAcxSU4BUDgAZCOKnCSDvQTKoSgAQ/hwC/fQFCQEQ/YUVKh7IfxzL6RGidwgW\n        wMMC4KosXWUW23/i3AeMFlcPLAOQgRQBQOwrgH7uGCwFvT4jCSBkVAImhVqenh/mEYE2gO8x5n0qtWb2\n        ewCsx6wZOIIYYCVECH8kA0aJpVk0jQMgtVGJmpRGq9LX5ElAAAD/9ElEQVQCAsghBwRtdBl1WPUbzSSA\n        iEkbM+u7LAo4oBEoD7FPCIMIVQBMhdwchv3gRqzcUz6OGwqjeKX5D9gCdBLLVgazlXq7UgMVnKUpVjRz\n        /I69G9dfO3dux+Yt9alkZYbWpNGYdZoCo7ZKgLLAolTb9dU2hVmSAGjJ2gRGQ8JT+EubaCB1RAQ1sBUn\n        xSriS0fPGiN7hULm04lvZA2ax5TBjnKC+BajAqCsZFRWwbe4cTF7P/A+jEwYSTa0FSRKwewd1iiQlmAE\n        qM4iArrYK+AecBL0OIS/XfLuAceghCKLDuBeAkqTMECekaFaWjCAfvHjg1GI8jaFTiRwgI0On2xLZo5d\n        KcrWZ1sUK/4Idgp8QDlYkBxAJ48WaG40McvTytRPZvvwubA27DqLGgPAenxXggpgQcyAGMBnIAB/bWLO\n        1Iqe4SWTy9bOXbi4vrWjbWDeyh1Hx2fWxho7Yw2tHl+wpbNvzviS3vGZxXt3Q5DW1nc4I6myal+FM1Dt\n        DxeVV8Xqm+vbekqrakoc1RVOt8MXqvFFnIFYtS/kDkXKa3xVNe7H7j716POvGbNzLSb76ev3v/LDn/79\n        v/zjmcvXF67Y8as//+2f/Povvvv9n/7sT379q9/8xa9/+1d/9fd/B8T/j//5v5p6hhJNPWu2nfu3f/+P\n        //iP/0y29eYVOxJtvbGmznBtS1Nj55q9h1eeOjl3/caJ1Tt7R+YVFleGUz3f//Gf3H/xlRJHqGt86Y7j\n        F1t7RsL1Tc29Az2DoxNLNoYbO0rLPGOLtyzauDvZ1OWPJYLJVLS+ua5jJJRsC9U2NLb3tvf0wxwIxxtD\n        DCrEQ6lOX7x1ambdU8+/vGjZ5tJyb6K+q65hKJrqmDe9/OTJK8uWbIwl2zfsPTU0vmS2LqtraMmtp97a\n        eex8lScSSXX7os3V3mCqY9CanQud7vREiosrLbacarcvt6DEbCHuA8etgC0wgc1uYq0vZ+iRl6BrVY1n\n        ZHxR7xB+YCmQlMIfuG+SnqA28AFVMCfVlNAHloHgPpU7MV1yPfERk8IWVoC+4DJxXCLA+AjsZt8FOvqJ\n        3XTOiCuGHEBuwMsYjaAKojNxmZKcMQDiOM6Yv69yg3pJDfnio8QPKOFJAwLouCWeInaG6jISGiAB8LkY\n        KpGkJ9NXQQAZKgG0D8wfXrBSgsA5OEL1Q+xbwAeMjTMRSNBfJYB8LMBIxwB2nbzK/QDWbQUNLN12YOOR\n        R9YdOLtw/a4Fq7bOnyEB3HrlrTtSB/D6l765bNu+/FkaBoF1s2y6WYB+1Qv0f5YCkABUPgDWA/fVns8U\n        /g/QH/If6J8nNFD5IOGnMlNbmil8IC6gCnH+kBtAABINdmRS2AYNJAC2cBCfPgZOgPL0/MiloOh6EIBf\n        hD9WMpUzQ+eRigFQAlNFWf+lp7RnQS/LgLlHI3eIJD0kbfp6OvRhQ2QELTJpwozSkZ3RbVdgB9TaM2oB\n        5Sb2+Byhd17rNenazPpRs67BpO+mO4h+7WpBugIzu/N3mrmJfLtZ3y0kAZugxaJrMevrgOZ0hTN+gPUl\n        dn2ZXam06RozNEmjpjceWL9qxbGjJ0/s3r2yv7ci25zFP76Gvn6LvsKmL7UrZdkZIBvWD1M1SyWBIG+1\n        9BMFTOP9YR8AiItNDFCX8pV0AHEH+YDZonhVn5kcUGJK78piwyUTNTjuA1C2wyaQFCAgewnuCdUvHSBw\n        DpkP0wH4yzbL7OQjwE1HEF+J0VqryHAR/nkWBq4B0NnM2KF/vzLt4cFTiP5qLiluIj4fon++jegPvM7B\n        R7sCxC/NzsCfCAtwz2KrUpSjz7ZzgQWWB9U9tDwrvExGLYbZwHMjTsw6rLFa9SYLaQDUwloBCQjDILBZ\n        YR9oZ83SOFy+qZVr5y1bBRCPNST7JqYbOkaaOoebBuaFEs2JxpZwItXWOzBnclnH6JL+hYvjzS1V7kBd\n        95zeiSW4lF9aWlzmiDS2N/X0BiPM/HH4gjXesDNQW+3zV3u8ZU5vpTvojIRX7z00vGhNQXFlfX3b3nOX\n        /+Qv/urP/vy3aw+ceOrlt4D1v/zTP//Rj3/257/9q7/5+7//j//8z7/623/453/999//9+8np5b7ks2r\n        th9asnzHP/xff/f0K2/ONuZEm1rnTM80t/bk5xcOTyx648NPXn37vaWbDzT1TJSUe5It3R9/8Vu3776e\n        bOrdtPvopv0X4m1z4g1t8ebmtsGx0an10bp2Z7B2aGxZ3+hiFg/XdzZ0Dqbahus7hyONXf5IXbKtG/I/\n        kmhxeuPuQMIfra+qDlutufPGlz//4pvTK9ZXOTx1TZ0uXzSCX94/d/3+E3vPXvIFkm2do/uOX6twhiqd\n        4cvX7588d8kTawomO/2p5ryC0nBdW35xmdFms1izKyo80pbHml9UqlYAgA/M3PM9Rz2nEWCFts3GJNB5\n        tlZfWFLWP2e8u3+0oLgEaMseQczzsRmI9bLli2wMwLow8fuTDET4U/tziBNf4FiFdQkgCwcAlgm4QhWq\n        wDcKiAuOE51F7NNEwHriskAzez9wHjYBB1E7Lf//8F0sEDTnMjlhhDldoSaT6suoEC9DUB7GhCHrwY4x\n        D2cyWIfMdtD49R1DY8OTq6w5hcwCSjt5uBMAbCYaBFJt9wcOYLA9nwRw748JYPWWmW0H1h08t3rPyal1\n        OxeIBTBvxRaVAB55/pXXv/iNma178sQCyJacH/H/wBSYRXfQA/RX/T84qtUAsh28TiUAHNUTlQBUJoDe\n        Bwc8lP8gAA7MqGVf0tANlFAJqsjSuQzs3uzN0kWy9EljBtS626B3qjFhydwHGSShqdVc/j9iBR8b67OS\n        ICh+HsF6LgNV1NJW0LvMuoiRFcJRM7P4ExhSDByz6BvoylfiNn1btr45O6OJoWDFD/vApGwSZK816waY\n        XaqPShYQFrulr0OFlHRZJIdnUqii26IbtugHrPoGMQUSwkAQ0QBKP7eLoZ4ts/BbSbs+YZ7lVjTVBk29\n        t2bZooWPHj9x9uDRge7uvKxZ3Jc/a3aVNbPSnuGwZ1TZ2DwOOroSmtrKjebdRl2GqHIgtRN/CmkR6hAH\n        DnS9GuylPIdxYNDXSBolVDBTibII/R6LUgbIlvT/akkNglVRKHFjcADsBu4TKereamRjONAMDAuaF9LO\n        CA/NNymFAuKFdPHDAuDGZ/h1eeKUzzMrzAUCb0mMN5v+HKalskBMejMUWJUKe0YRkN2KL1Ld59r1hXZ9\n        Qba+NDczz5phwzvbgNrQ9bwEZCeIyysJ+uvMFpUJtAYMA+u/wBB8FnmC8QmsZOTAqJgySGC5Np0xU1NQ\n        XtHY0j2yYFFz73C8pbmtb6Supb+yxl9Z4/X4Av5AIBSvD9amPLWR6kCkxhOJN7Q7/ZGWwTnT6zc3dHUV\n        AP+rfbGm7lRbq88fdHrDVT5feY232huDERCIN9QE4hXVrnCyac7C1ZH6VlcgMTix6tTF+//4d787c+n2\n        vOWbf/6bP/kzbh3zl7/97V/95Oe/+t4Pf/ZXf/V3//y7f/+P//yvf/sf/3Pe9CpzbtXhk1dbB6Zu3H/2\n        H/7lPwZGp8qqvb1z5q3YsbuxZ7iptf9Pf/3XoJAjlx5tH5mudnq9ybrn3/v0ypVngonmTXsPbdhzPNU1\n        nGzpidfXd/bObe+Z9IUb6hr6Oronw/WdwUQH+KCupbehbbitf157z1BzR29T/9ym/olEU3co0lDb2NU6\n        NB2H5ZFf0NzUfv7akyvW74nH65wevycYrcVfwxteuWP3mTtP13jjhWWu3RdutPXOM1uKzl+7du36I/7a\n        VCjR4Y4klazMMoe7sKxSnDyU/Dn5hRZ7PoO6NvZnht63gQlycmy5UvD1//L1FuBVXPsXaEhm5vjIOSfu\n        7k6CQwTibiQQgrs7BVpoSwvFW4q7uxRpaSml7u7eUqFCqff6vX1r7Um49/++971++567z8yeOXOSsNb6\n        6Wa3Hxw0h9uO365i8QaFFJXVlNU0RURGE7TNSCw9NqbeZ95nl7eHbhxWfolkUBFxJb4L5c4Ob4TpzqR+\n        0fgTNxP2AfEdBCDujJuAD7CYRgBh3RxAYTpncIX5VuA4oZ8YTSg3gV684iE7OYATGgSiXJnraUZQ/t9E\n        f/M+ggPMI7iq087AnLaLywCTibPOwsqmyuaRqu6PL94F8aJKrmuIg+wOLXxB+Hmyo4bIAlq2nu2gRSHY\n        sOkLxi1YNnrWEqB/6/jZg8fObBo3c+uxMzsuXl516PjJx5/pmDbf34cWgEkA/ycTtNP500kA5lxMiP6m\n        KcAhQB/QjxEiLADWA4vOz0z/F+gPvc/UFxvneAUHxIhAcQyxnhtDJrImS0oXe3uxpTNQ3qmwKEz4iIC/\n        mUL+Q/ubxJBOLU+ozaKWZ3Z/spMufsB9d6clT7VkqCIq4GTKZgYHvUC5Ttb99qXrn70f+hlyX3pp5Cyd\n        Yd4Ep1yoKks1udQl5TjlAhc78gOFM1QaE6KvJ5AOIChbQQya3KbJ/TVCf7lq5psyYpzftZKJQ4wS8zGS\n        VSlIlH1Fa3KaLiWr3dyKj6H4JEcFTh456v4NW2dPmNQvLsLbzcch+2RqcqahROqWZMOSoMsRqpKmWUJE\n        HCJXBCeA12ACqHIQAJiALX1gKDBsQNSG0g8TO0FCXwOyoanddr5NcbHHHDQ+NxETbIF5mI3FYpGqwuqq\n        m6KeWfb0FAH9g/DqYiAXj8HghCox/EsjgByAOZS+v66EGAoEuOmaV+malwxd8QDf8QwONqLACNIUvMUA\n        Nwigl3VDuP5hE3gsgW4MXmLoopjAkNwm+psZPkB/QDzLCxQYHy5BAE4HPf7AfTwJGAsGDQwX0KEX393K\n        bx3g9HNJPhFJKQMq6nr3L09Mz+/eY0DrsPFjFiytbm7PysrPyu+dmpWdmp6dmt0zMTs7ISkjLjGTu0Vm\n        5mT3LepXWlYwqCarV1FwRAyEbXR8XHxiUmJKZkJ6RmxaakxicnhMclpOr6xevVMys3v0Kk1Kz49PTc3o\n        M6Cosm3xHZu2HTlXM2HqbSvXv/X++w88/MRzL7z+1rsfvPjS66+8+s4Tz7362Rdf/+Of//zPn3+OnzZf\n        cQacufDoJ1982TBq3pnzTx05eSIgIimn58D5y1bdtm5jVcOIu5ZvfeWNj7YculDRPEz3eBNz8t96/9P1\n        928KiIofPnnRsElzuxdC0ddl9O5XUF7Zr6A6KSM3t9fAHn2qs3uX5hdW5BdU9OhTmdO774DSssLi6j4F\n        lb2Ky/NAGL1L8voO7N2/rF95fWFDG2iuoWHY4SNnFy1dnt+rMDg8Mjd/QEZ+P6fT2zFm4uqde+NTsmXZ\n        MXT8rBHjp6v2wNm33H7vzq1JWXm5vfrHpWYqVofhCQoOjQQcQ4oy80fzmPkqEPjc3l0VNV8ej8swzObP\n        7Pmjsn0/MA7WAKjCV7Lo3oDC0uqqhtaIqGh6ZqjZCe64LbODVE2EAdh/TbSIYJ4PbAUnrAFm7gOmhe7m\n        hPq6C8HpoBfHmVd68552EgD4AEAMzDW3ZOHleEtY57XiVfCKefy//npSisDurtaeN68Vl5suHe4EIA7y\n        Ekz4uaK02EwM5XGyFDkDz8NHteOfNzjDDrauah2juYNg5dwEfZfQ/uboIgBhHBjcJEB3ixjAXEEAgydM\n        bxozpX3KPBDAiBmLG0ZOaRo9HaNl/KxtsAAuPrby0AkQwMiZi7y+3UgAQvgD9035Dya4Kf+7IsCciM4Q\n        nXAPDqAvqAv9zSDwzYxP5vwwAZQWALAeHAALgN5/4fqPt1LmxzkUEoDpGrKxQAxMAIGfBYgHrJMAKHWh\n        7kUhGB36EP5Z3PWXWA+ZjyPggGzh6wfK41qGDQC7IjhMx5EwHdIdnIMzcqDrRfOfgR652KP0cyu9De4l\n        SZ6gnJdXqfIwkfqZ4qJnP0UFE8i9VCmdXn56aVQXGxrHanKlJlfpQH95oLgtKAEcAxOE2wAIuR2vkqhg\n        N4SoUrSLshpQBSQFDYAhgu3doiWfKLvPgPysibPnLbtr1byWpn7hAdkWn1yrT7yjW19DyYUdgEtAQoYF\n        c9gu4CSgeQSGaDWKV1BLsFDoUPcQ9QZ78UODMxcTII4jusj5AQQHuhSQB/uD2jsbObDOQFWg2fF1wlVh\n        FggOcAO1Abh2OmEAvoB1PDOr0kQzZ3+V6p5hWN5TDtAp5JnMw+Qcwr1XZ0oP1kDvgyHADXj1qGAFCRAP\n        AiBDwA7QZX+3gsVBbiXIq3jcwH2LW1fAATACPDAFQABQ/XgS0eDTRHyni8EAcAAOmrvEOOyKSouHHx2g\n        KqEiyIzhcUp+Pj4JGd3Lho3sNbAsI7NXXn5heeOQtonTobJz+hTk9ivKyO2RmpmVnJ6dnJKTkpqfkJoZ\n        Hh2RkJSWmpmXlJFNP3j/qriklIDgiOCoeFYCZ+WmZuczFSctIzgyJj4pOaN7fo9+pd17FQeFR0cmp/Qo\n        qW4eMbF98pQ+tW0Tblv++tvvvfvex48/9/I7H37yyedfvPPee19eu/bV999//MnnN278DF1/95r1PlbX\n        7oPHMF91386ps29bs2VX/9ra/L6FBQNrRk2bdeDEmV3Hjt+9YuOSJRtqW4cDH5Oz+3x69aut23Zl9amY\n        c/vGlo4p6d379BhQnt2zT7/i8l6FZfn9i3Pye+b0LoTG79WvqLC4bkBxXb/+xf37FuT3G9SjT2luXv+M\n        nr17DSzpXVSR13NAzz4FgyqaevetqKkbenj33kV3Lo9MzsrO61NQ1ZCQmuu0u+vq229bsT46MU3qZknJ\n        6lM7bILHG9o+cup9m4/27V9dUT8kpXtPi83l1NjRE9gEoDdYucp9CoXLHgRgqKrp+WFZACFb1c2eP5jY\n        2O6NDAEOkBUrDvbsP6ikqqF7z77xyamQxgBHMgT7bnKN6narhgFTAEIeuC8CwqwTpiq3dbWH4xA93XB5\n        VzsHHGQWEAMJnWhr8gFOiWv/F8dNC8D0//BWJkzTvSNUvCAAHhFzhhDEVQwD4FXQhuk14ucKrMdBp50x\n        bbFdJSmEBCDMFD4DmICR5s6tibklZOPI6QGhMYyC3CQATfTQ7nzL8mBmAfkH6f7BnfsB7KELCAQwAxZA\n        46jJbZPnjFtw14iZt9Z2TKwfNrG2fULDGOECuvjY6sMnTz/x7IhZC4H1qo+PQfQHB3QGAMw0UAyYBYD+\n        IBESMAkAiA+g70R/8dY0AjhYDkYCCBGvoaQBP8Z+baIgAMJfxADY/U24+5noafOLs/nFYkKHPveCT8Yp\n        UeibYleS7Uqm2GJF5PwoWXbGgYHsOYwGKyAJ0AO0P0yBTJgODtIDjgjJL3ZiYe4QCwUyYD2InSNBA5Dz\n        AHSI93ydsYEemtxLs/SB7hYR3a2qPFWV+6qM5eapRHYT3HN0JnoCaiGr01QlUVMadXmwKvd0Sd1dEpQ+\n        1heJpkPA5VSRIQoKCSdhMG8ywSXFuWgHADFBCXHcAAAHlUBbt9huPklBanNjw4qFt84fPrw4NzMp2J2o\n        SlmqX7TKut9QPIDKLQcSmWYDSsAPge2D4jSGjnFPyN4w0Ayz8tmnIVTYB4D7cNFlAcQAKHcKeQ6Id+FH\n        TSuBTdb8YZpwExvucwkCAD3AksDlbu5Xw8/VRDNnmA5M4wGH4bZ03JMDBKYTcIn7wi/krxPWgzVmf2JN\n        IF09kkdjZifrfrHekHW3BDMCJKqLeK9ZCuB1S14DuA8LQOFEFP16DEYamOoj/EVOpwKsdzolpzAIwAF2\n        lizQ8+PEF+zMCzIfSTAQCMkp+/j4JGX2aR03o6qpvl/xoNy+RWnd+yWmZ8ckpyekZSWlZ8QnZyampCYk\n        JMTHJsclZ8QnpiXBIsjpkZyZF5GQHpcGbd8bMj8hq0dwRGxIeHhscnJUXHxSek5Cal54dHJMYmpqVn5O\n        z/7JWd0Tc/LS8vvm9a1oHD2jR0llr5KqZ196C7D+1Tffff3dt6+/8f77H3zy7Q8/XLt+46eff7361bXv\n        vmcu0K7DB23eoAW3rcP87//828gZM0dOmzdz0TIQTGFVVVlV4+13rXrr4w/OXXy8snF4QUVNRHxK26gp\n        r7/19pwFy4rrhs1ZtrakbihIrnu/gqKqmr5FJTl5/Xv0rxhU3VhWV923oLBn76IBxWWDyspKS8orqurK\n        6uvqGltKSup7FZcUlVUXllUPKCsvLqsZOLCqpW14nz49p06ZNWPObTm9YUs0VNa3pKTmAnQGljUuWLo+\n        NiFNke3esOgefatDI5LaOkZv3LxvUPWIgsrBGT37ALkAoNDmVKYGd/dlDIAue9XFwi6qfjZ4MPv+66zz\n        UvmWexmKIRz9tAZUBVioGtk9B7SOGD+4Y0xccqok497MCKIvSDWcho674eaAb9AA0F/EABx2+nOAp5T/\n        YghwFyiPC03EtzIN1CXwWgxzjSgBEzAtLhd3oIonK3TekAgO9tB0UI44TvgG2wDlhQcf+C58O+QPsZgX\n        mmFnTEgAuDmeE1+QhNRJABzgAIsVBGBaDFZJViTF0q+kpmHEtMDwWMh81QBT3sR9MTrfMgzA+LDYEIYx\n        gE4CmGASwJS2SXPG33LX6Dm314+cUjtsfPWQcfWjpoEAzDqA048/N2zaAo8v6wAA/brI/zGNALMcDMN0\n        DQH62S600xoQPh8T/UEDXfKfLYBE63/gvmgKLWIAYAKrFGGjO6jTFyTawKWYBCDaAWGIHFAwAdNA2eGH\n        m2RRsxOvBRmYYWHQQBKT+tkKjcEATID40P4C/cEcsAmEp4heewA9OUBsEw8rAUYA5HlPnT6ffI07RNIa\n        YHaQ3FeX+htyvM6cn+OaPFFj2g9IoliV+mlyuggepOpyrCHHkQaUHOb7U/4PVNk+CItTNTO0QHAPNp0z\n        ggAAzf6qAjOCTnzQmCj7imFQgTXJwG5o+RiHFCH7hCs+iWHe4h7dWwf0ra+qKCsuSA5wwkqIZO9SZnNG\n        anIuHkYHDVgSGGhVwoTaDVIlCHYYHMB6TNggSNSOhQDQAYU4LtL8o0E2IqHTRq8RfrD0mKsi6psI0wR4\n        Kpq1gZbiRaFZhMsSqSvRugU3YYCX6UAM5wLouRcj+xSJGl0oemEQBELIi2BAkK6EAdOh4nX2e/AatAAA\n        ygGaAivBq9NrzxQdl4KVQW4eMWAcaBLmgR7ZQ0cQaAATWdO5/QsJQKPhRSNGPAxYAfLf7lDYKUiV8Y1c\n        +O78CBKAqBzGDRk9lrv5xCRnDCiv6zmgX17/fr2KBgGsI2KSgkOjIqJjohLi4lMzUzNyU1KzEzKy4jMz\n        krPyeg0YlNuzd2J2bnxqVnRCcloelHJVWm6P2Pi0nr2Ls7r3Co2MTExOT8nIi00CheQlZWZHxsbHwjbo\n        079734G5vYv6lNbFZPScc8fK6z/+8vnVa+988MlLb7x34fxjb7z17g8///rW2x+8+sY7X3z97U8///aP\n        //x7w8bNnqDQ+avW0B/055/b9x66ZemdGzbv7l1Uf+vKNas23lc9bPSFK09e/+HGtMV35RQUhcYkHj3z\n        yOdffj183PSC2mHVI6b0LWns3b+ssLS6tLYlt29B9z6FOf1KygYPKamuLhhU3quoJLd//+KKirLyupKK\n        6qahrU3D2guLqvoWlOBowcCKysbm8qrGkpr65iFDKssrli5fPXny3JLC8rqmoVU1dTCCbJqnYFDlbUvu\n        S0zMtFgc+OmBYOIz8usHd9y+fl1+WVV4TGpKep7u9ffzkyDnAUkCnujiB15C+7P6FxygsUEQQJ81AYz9\n        MhOUa2AogAao7kV0V9Vw1gpAtDnx62hsH9PQ1hEeGU0OAHoKADXZAis5KOep0DkYLWBiKDEXUr3L24Mr\n        cZDHqcfJB5T2hGah/Tt1euecur5TkhPKAfqmZ1/M+RF4MKp7QRgm9MMY6OQAhwg8iJvwLS4BuJtBYHAA\n        D9LO4A07c4H+SwMYnQQABrBYB5TVVreN9QSGqe4AzSN+pDdBX7QGwkQMHhFMwI31/5cApjeOntI2Zc6E\n        hctHzVpa2zGhpn1czdBxjWNnbjt5VsQATpx6/Lkhk+dq3TrrAMABIADhC+qsCaAvSOC+ARoQc1gDRH9F\n        ouoX6E8XkMxkUKC/2BKAzh/AfZhw/kD7M+1HFAObFcKxQv4DrKH3E+n9ZwUAcB9mQTwmdu7vCHBPcQg3\n        DlN66OJP4B6QwixwMLRrZgSRDCjwudEjJokAStHyE5czMuxi6UCucMtgkglrwKX0NeQCr5KnkVroVXfJ\n        vTUclHrobNlWoiknDHmZJjWrUosm1WtSuerXXZPyDanEI/dzS70NUIVvpEdJ1Ls1OnwqNam706+vw7eH\n        KvXRuA9MMKvPKP9jXXT+ADdD6EBnSIA9f1xSujAR4sXuwZDeANxgEXT12HwjZZ8Qq0+qrlRlJtX1yU8I\n        0SJd3dJwT9EcFHfGrcINGaAM1RyJj9MU6HewCPgG9g1+ArHQ7yJyazikBNgKqgIGYuKQEPjhAkMTcUNV\n        wQNA7Dvp5WdQwXDQSgDaAvrxSLgK/BFhKNFuS5jBxmpYZg7cIUQj97idIvbLVE6B/pjAMiDukyECIech\n        /GEWGBDjrN6CcU/TAa8MA0i6uBBK39CZzEOPkCH5u5UADwwCyn/QAAlAoL8YEj4C1II5UB6XAPpxB02T\n        HSJUgLc0cUAJojiARcWqZJN9QqPiANNR8cnxidD2eZnd8+KSU8Ji4oHa0P7pmVmp6Tkp6d0TM7vHpoAA\n        svP6FSdm5EUmJiZnZCWn52b3LSiub4qLSwH6z71zbcu4yd3ze6Vn9UzLzkvOyE1My42IT4JdkJTVIzoB\n        t+/Xb1B1do8+aT37r91z+M13P3nsiZcfvPzkwTMPv/Tqm7/+8us33/7wxlsfvPPRJ99dv/H3f/zzn//+\n        97xbVmn+0dsPHiT8//nn229/MHLqvHt27t17/PzkBSsOPnT56KnzR06e++SLL/YeOxvH7Wji3njrs5fe\n        +bCgvCm3V0XOgIHFjS0NHdMGlDb0LSnPyi/oU1heVNHQZ1BJ34GlhaWVvYqK84uKehaVFJdUFhcV1dQ1\n        lDc39C6t6FcwqGe/QtBd377F/YqLBpRUlpfWFRWWLVl6R/vwMYUltc3to4dPGFta06BYXb0LK+fdujI6\n        Ps1m06LjUzN69MzqU1jXMX7qrUvy+hcCWONTc1K79wZuAR91w20AsNxsXqZyA3fGeKnumc/Ojm/gAEC8\n        5vGKNCGdniJdd2iqQzWbvpE2nKoBQMQNY5Ozq1tHl9U2B4WE0ukicn6ED0e8djZ2dtpNmc/UIEYF/iv/\n        Cf1C+JuozVwgUoUJ92Ii3PGmd54HBUADwQHf3GFGB2+BcnCk02gQJgIhXsD3f135VPRWkdIqGEVYBmKN\n        ucCMMzNaQKrolP+CAP47OtOBJEnBa0FFfeXgkZonyGV4SQAiAADWxKvp+hfjf8LCMK3+1wXUJgrBhk6Z\n        O+GWu0fOvK122MTqdloADWOmbztxdvvFR9ccOQkCaJ4w0yQA4D70vpD/GH6AfnJAl/DHQZ4S8v9mHYBJ\n        ABhmcYBo/OkXLHaDAdzjFehv+nzABDcDwmz745DNns8YKSz7EnFgRgXYpg2Sn+16GAbAILhzlxix8S9d\n        +U45V2Txp4lN0rE4QdQuJYIksFIwB+0AsQkw1gBAcZ9M0R8CQh4WABA/12XJdSm5mtRLVwoNeYDOSY7b\n        kqdbal1KnUvpYzi6u+zdXY5MtzPN7YjWrd11ey+3PVt39va44jRreVTI6JS4Ppqth1cvDNAG6Ep/VQL0\n        F6pypZD8eM5YVYZUB+CyGIppqSSACLKCojuBoQwwwDKApeLPzWG4JUCEXQp0+MbafFI13yivEu+2xHss\n        AFzV5ucUG//magqEub+mpNJhpfRSLWCCOPa/Yx8kEECIiAADx4NVKZwfbYlwKglOUWgGxBQGCvjA38lt\n        WELpjyK1hLlY3qWLfg+U9qAlOlKUyABroscSzPosmgVkC8YklGDgu/A+4Z6mxybQLfu7GcIF1gPNQ1nN\n        ABRWgg0lVOR6ut2SR6ffn/4ZHZcoutD+AHTcQUC5pFK8WwxD8XhgLrBjKMS+xoEJ3ooFGntR4BJwCYPM\n        OCICM8wZFazgdNImYGM4l+S0dwsJjYpPSo9JTI2Miw+Lio2JT45LSoiIiY+ITUxIyUxITo1LSIxJSI6K\n        S4+ITYpPSk7OyopJzAiLio5LSU7IyAAx5A0oiY5LzczuMf3W5ePnLOzZZ0B8anZcSlZCZi5bh8anJGb0\n        TEzLiY5Nz8kv6NG3PDOvX2Fty/o9B5579a0nn3/z0pMvPP3ia99+T8T/7rsffrjx01/++rerX3x9/cZP\n        QPw7l693ekM37tiFs3/85W9///u/Rkya2TFm+rfXf5i2eNnIKXeeu/TMknVr1m7csXnP8fi0vKy+RVde\n        fGPxqs2af2RWj9KhY6YNbp9a1Tipb3F1flFJ3/K6/iXlDW1DB5SXlTU1l9Q29i4tHlBS0QsYX1E+qLKy\n        qqm2tr52YE1LVVN7TXNbUUVd4cCq4or6voU1JWUNJYMqlq5a0TZqZI9+RSWVFY2D2xrq2gMDwvoMahg1\n        dV5SWrrN5gqLTo6IS+1RMahu2tSRU27PyCmGtg2JiCmv6QgOi/bp5iOUPrM8dbfXpRp2pwuA3hkAAHiJ\n        UgAd9KAbgH6Gf1U6i0TAQLfTPYLBns84ApQHCgeFx/UZWN2rfxGoxQpRz5R/0x1EV76Ae3pa8NpZ5dtF\n        ADdRHnOcwnEQlBDvN5N8hDAHSNsdglRoOphoDgjGVWAyjz93OSboW3AJb0iSEAFeAeL/hW9x0HQBEdm5\n        Unj2eRbITrg3T2ElWEFMxMqbdzAJwE+SZYWFYIIAAp3c7Z0xXvAoN1LWQKLkALMyANzAIWwCFoLtPnV5\n        9h3rSAATZzaPm9Y+bcGkRSvGzbuzZcyM+hGTq4aMrR85dduJczsevrz2yKkTjz3dMGaK6iPSQOn2Icrf\n        HHQBEf0Z9cUr0F+4gPgWNADVz0mX/wcD6A/QNwdbv7HKl9u+A/cjRFOgEOEFYlcDlgGTG8wIMPcAIDHw\n        rekdyrTTdw9wx5zJ/lYeFGFeRoAxEcKfAj8Vspr98QH9pBBcwogx5D8WuOhySRLVALkOS19NGWDQBcQA\n        skoPTA9NKdSlUrfS198VY2hulx2/Yh+7o5vLJcSIhl+J0+nwqLQ6ZYeDc8MI1vUIzdUzOiovNs6ruyI8\n        nu7R0RWh7nyHT75oFRdHuKffKVmlzIdZkCosAFgD4SAtCHYgpkjtz9FYOwY7AOgf5vQTrd+YoxnHXkB+\n        MboS5bEGeZQAyHAdWl4KEtsYeJmbpPTWlSJV7qfJ2ZolXVOyAbVCmAPcgdFxonogAA+g0X0U7mTtFYQ/\n        IBvLQAYsyhXlzUB/fCgeD/Ifw83dyvicmoMZnwmB1jB/C9Q0vTSidXOUZoG6V3WJK4UGF6Av0WljSF5A\n        vErPT5CmBNLno0S6aUmEMNIL0OcpsFcQlL6hBGHohGyHUPT4CEA87hbgtQR4LFhvGIB+VofRAsCrC1jP\n        7KBQTU5mdqwsuySrCCfYHQxX4DnJGSJi7MLXUSWHvZsnIAhYnpqRk5SWERFtCv/05PTshHS2dUvOzotP\n        S4uNT4hNzEjKzE3NzIlKSIpPTk1MSI2GtI+LC4mMik1MS8rKCggPyereq7SsLjohPiQ8PDI2ISO3T2b3\n        /qk5PVNyekREworon9+/mE6lvKKWcTM3Hzz95AtvPPfi6+99dPXq118//uxzV5594cPPr35x7fvPv/zm\n        1dfffO2td4D4d65Z62O1zbj99m9v3Lj61feghIuPXcrPK3z00ad/+e2PdVt2PPTkU/uPnz1+7PTh46ey\n        ehWOmrH42JlHapraPEEx46bcefDUheFjpvbqWdpvUGP/qvrSlrai8oYBAyuKK2sGlJXXt42trR82oH/x\n        gP5l/QrLy6oaWocOrm9pLypp6jWgpLiotrisvk9RZVFx/cCK9j7FpWMmTly5dXdlY2t5bVOfgeUFRXWl\n        JTXZPXoNqmyuaBqWmt3b6VCB8oEhcYXVLaNn3DZ07C0xaTlMurSreX1LehVU+MkK4MvhVAH67LsgWvYD\n        rHXD3+sfAmIAAaia1ymqwAT60wUkEntY80VYF0VeOI63okTA6ePj4w2OGFjdmJSSAeg0kd1chn+YIkTM\n        PqDCb0ODgAQAniD685Sp97EMEC9MARPiAbVEftOVL2CdJgIW86wYWCzIjE/FG3bSgwnWNBpIADc5QHAG\n        JriJOCKMAMYkTOc+1/PyzmAAxs0P+u9NWC1ssfr6+WJeXNNS2SoIQDUA+g7RDI40AFNASH6Cvvu/zeBA\n        CSYBPDrrjrXCBTSzcdSUoVPmiTqAu1rGTq/rmFTVOqZ+5LTtJ87tfOQxEsDlp2tHTIT814QL6L+4z0k3\n        oD+GV7yCAID+QZz7ebtKwPyF/Afum/Lf9P9gAOWF2GfrN0zCxUZgsADAAZDq7MUvFH2ssACSbDIJQMzZ\n        olns2JUsOsGxX79oDQSNbyb757iYa5/tolOIgWInt3jEelyYKuwGXMUgMLiBoWBGiUXQmFlDRYbc3xD1\n        wC4FSJ2rKgM0qcBrSQtQA3SnxWEDxEvcOddp1w3MLapqBYRASTqdisvlh1MOh9XpUESWgdUBvck/P83t\n        7h8TXx2sxTm6RQLfKbolgD6IBxAfzybSNAKAvxpbH4MApBh2PWM6aQRQjHqc2xGHig2Bqa9FImmuk54i\n        lYEHS77bkgbExNCZXAQrIcwp5WtKP8YD5CxNwYBlALKBSQHEDyIN0DwKET592CJRTOukxwbEEw9eES16\n        YIL4q4rTwWVYAH4CaBoi9gtWUJ1SnCHHexS32wKU58buwv8eLvxOLoH+gUzXIegHYNAOkBgHFk1+hMwH\n        xBP3w+i2kk07IFijGwcTj1sKcNMUAKCDXiHePSzdknXIfzc+VAn0yIEeRobp0mHtBZN8PC5RTaaxDgNG\n        TxYTQ2UfiyTZROzXya3wWQlBWiIVWa0+gSFhcUmZsQlpELDM4ExKTcnKSM/Mj01Ij03mHump2b2iYhLi\n        k6H9cxISU8Oj4qPiE0ES8Wm58RnZUQnJ4VFxsWlpMAjCwsJhGMQlJ8enpGRk5ecPGJTWvXdYTFJKelZq\n        Tn5i957JGd3BLzm9iyuHT1py77YHzj368KPPPfXcG+cfeWz3kaOnHnzkuVffePrF1195850PPvv8w0+v\n        /vrH32YsWOpjdS67b+0///WvX375/bff2Slo/JRFPQY1ffn99c+vff3Rp5899ezLFx5+8u4Vm6Kz83Yd\n        OffQlWdj0lKikrLWbj360guv3rL41vyC8qKGESVNbXXt48rrh/cfWFPTOrq6rqOleWTD4I5+ffp1796z\n        e/cBpSXVdU3Nla3tA0prevUd2LPXwJ6Fg3oMKhtU1lBQVJo3oN+QUWMnTL2lafTomqEdJXXDyipbBhRX\n        DKodPLC6NafngOz8AQa70BiJcQljRt86bvK6Ee0zEpIyoFgBYYY7qF9ZU3RKJvBa+OUpxlmUa+btGG63\n        f6Dby06WDNvSfa87XEwTMt0+5qA1gFPmnLvD45SO23fzlVJyevcvqfR4/YGSQss7YS44dRoQBH2B7CYB\n        ALjpDhLEIAYOqjYT/TsJgIjciddCsJua3RydiaSEb/M+uNzJ8mARQhBA34XXdOZ0eni6JmKBSQ8muHcO\n        4RHiwf+5hHfoWkAu4VU44uvrC0OnvGlYRctI1fC3iR8LyVJ3q2Y1gNvfKbaCAROYEWAGgbt6AV2effsa\n        MwuofuSk1okzx99y99i5y5pGTa8bNokuoNHTt514YMfFRwUBPFPVMQEMCwIw0V/4f4TrH68C/U0XEHAf\n        NBDQRQCmBdDpCLop/8kBIuTblfsfzkpgEQcW2wKbEM94L9GfCT8m7osjAG4p2cFJZ1QAwl80CGJqEAO/\n        ADKm52c6mPEJMyLVwWb6qU7uFA8+ANaLXCAGjVNFcyGGhYW1keliv+giXemnKVDoeQL9+6p+eZo10uPG\n        36qMH7vDrjjsUIy+dls32AGy7Ie/FI9HYbKhAzDJbUeYcuiQ8fehqlpAoBUrZckVGloYF16hWSIdfpDS\n        2eAnVVSNqVKEyi4IQHPKfFWCAI/mcer3cGEoAILxFmdh1sS62EI5iBn63D04xaXAFAhzMvmnt9uS6VZi\n        3WwvkWtYYAbFgAYMOc5QEvBWZ6MFfEqii4UIGZqcBsNCU1LEFvnhLPtiWirwl53aRBSXyfjCHIlyKaHA\n        cQaN+TBuERamlSDsg0hdCfVYMIINEgaQ10vnD4U2sBXsBQIAlAcYLOgF1nOrL+C+KrxD9NezJwReww0a\n        AZGGJcywhPJpQQBKiMfiFRFgNgHVJbYDAtBDs0PRY27I/h4ZDOF1S7re6dsBA4FdGAemKcDtGcpUuUnl\n        tg2+VtmHrUAZTQHR0qpwynarJEs+ETGxSRm50UmpiRnZCSkZ0fHJscmJkdHxIWExCamZWb36QcUnpmTG\n        JCZGxcZHxsTFJqWFJyRFJCckpKWnZOSnpveOx9nk9FjYBHHxcUlJGd1zcnv2ycjvG5+ZEYPbJmfFJSVH\n        JaVFxacGBIQGh8eFJ2YaEfFjZsz66tq1L7698cQTLz7//EvvfPjRW+98fOnyMw8+dOX1t9/56PPPv/6G\n        en/JqjWKYezdfxDzb67fMP1CTzz7evaA8gV3Lsf8+vc3dp44NXji3IjEnqPn3P7TT38cO3XGHRAan5Td\n        2D7uwIEz+49frB86vbJ5Yl375GGjZzW1jS5raBg8fnpT8+SG5vayxuqmtqF9Bpbm9BrYf2BFwaCS0tqm\n        4tLawuLqfkVlheW1A0orCsoqSyvLSypKOkaPqa9tq2/pKK/BmsqSsrqBNU21HSMHlNYHhUX0LCrWDH+7\n        01VZ2TZ52l0jxs1vGjo2JaO7olh1r9dXkqPj0iqaxwZHxPhKvqLpGxDczWaWopeZSwyRtGNCPIiBOaDM\n        6GdTT/Z14FUa/T9OVoexd5Bwy9j9/CSX5p/brzSv7wC3xwOUFjn7Dl4LAnCoAv0p0inVBe5DvnfNwQSi\n        /ovQfxP06QgSR+gLgm7/LxBzggVkC/NysTEAhTwwWrRuFlKdUA4ExzGu5xAufvHWBHSbVUR6TToRWC+u\n        Mhd03YFz4YYSKx0kAD8/fBEQQElDO1Q/HsDpYg/trqhvJwcA/WlIdYYEhBfIrAOYffu6tvEzaQGMYRbQ\n        uAV3jZp1W33HFBBAzZAJjWNmbGcM4PLao6eOX36qfOgYh4+PLgjg/6C/8AgJ7W8OgD4jwGYdgPkKDoAp\n        APl/kwPM7E+ofsC9aQeYiUA0Apj8Qzg2MT2eGwKTADCJFeXBOCVAn54caH/u2WJjAICVX3Ylhd4eYDqO\n        A9Yh7SnqAYVJ4qpkp5QG0BTcwAiwiAHAmIAKTrZLmU4QgLUHkz6Vnrqlpyb3U6Vs3eYJ9FpVh2K3QtDa\n        VJfitPvZLL5Wi+xyWCH5rTY/ixVwD1bwox3g8LNZ8eprVfSg4KjULJz18ZOsQVF5YYGFzm4JIkgLNIeR\n        kUWslyKFCyhZ7JMOrQ3cj2dhF0ecJmeq7EqEh0l3sX9OpKbAgPBnMJamQALThJjVCqwPU5UkGAEGs496\n        uuUYQ4k2LJFuJUZECBJBAwwIQ/7j56AEuZQkTcHiVEOJhTXAnkJAWIZzI3U5xCWFcrNc5lYCT0NcCmhA\n        +HwYAIARAKCng4j+IhEK9rAxAyAe7BWIuxkU8owMawrre5n+TzkfSnBnjwfh1WHAIARWCN/KsDZCsIaO\n        IIvw/PDOYIJwVn6RM/xFDADY7QaRiKAx7B6N1WFKsFfxeGRVY5YnFkDXA/1hS8FWAMeI2gUy7ihdnqHJ\n        BTAFHBwsHGPITbbYJFn2CYmISUjPiU5KSUzPTcrIgl6PSUyNioG+z+pXWpXTuyA1Iyc1Ix3aPiwqIS07\n        Py0jCyQRHBkVGh0dgwPd+2Xm94tOBvonpWblZ+T1zsjNz+nRNy07LyIqOjktr6S+JbNX7+DwmIiYpNDo\n        +OCwmPC4lKDw2Ky+AzbvO/r5l9/8+tsf//rHPz/46LNnnn/jldfefvWNd199990PPv34m++u//mvP+/b\n        ty8gKfPUuUeB9de++f769R8+u/rFP//57zm33ZmSX/T9jV/+85//fHz169lLVkt6+IeiJLhv74KcXn2b\n        OqYX1rTUDR03etKikRMXVg6ZNLBhZGl5S0PbMGj2ysHDGoaNrmxoa+4YVlxRNWTc1IqGoT2KKuqa2qoq\n        G4vKG/uXN/QeUNyvf3FxRV1x3eBB1c2VVU0trR21dc0VJS11TcMHlVWUl9WVVw1uGTm+R2Gh6vFk9y0G\n        7qbm9miZNnfU5MVDm8aU1nckZuRKimz4c98SWbH2HVBdXjvM4nBBtgsOUEEYUK/M03dodrrpNZcqjABR\n        CkC9b+b2sIEP+MCDq7ihmNsAB+AsIBiwCBBUrHbdG5zZo6BX/4HBIWEwOgip3PpRpHUKdS+y/jHBW4C7\n        jQQAlBfAKjz+xHoTZ28OvhVgTQQX0EyqgI0vCEDQhuAV4c03KQGvJABAeJcB0XUt551vGTAQNQQiKYhw\n        L2wOQQC8sOsI035IKoIAmB1ktfv6SaC0soahRdUtIiLiIsrT0R8A9Kf/R9gBTvbSYEy4ixi4xmf3ycuz\n        bl87ZMKstokzm8ZMGTpl/sSFy0fNXlo3fFLtsAnVbePqR0/beuyB7bAAjp4+9uiTJa0jQQAGCaCzEKwz\n        /CvKwWABCNXfaQ0A928SACghwPQFiTBAmHAEYRDuBe5T+9/0AgmPUIzY8CtelASbTh7I/3gxgPWQ+SkA\n        PlElgAmAG6wAaZ8tRH2aCORmOOQkJ50bWazqYmc3oH+cQ4rnejPXk9mlKSISgNcksSFwH1GilaUzgtpT\n        U/I1qY9LijQMNSBAdgLfbRaX00oCENvLwgTUPbLd4WtR/Bz0P8IasKiqn90KAvDFL8zptAGf7E5fm83H\n        JkOL5YYExjm7xTHGy+qBnsKBw5Jg0QsoSrSCALBysxSNlJAHVmDPHIYHMkQXBwNfRFAFXTS0XaRQkSw0\n        wAV5y59GHjBdV2J1fAslzpCThfYPhVlgKPGi31wivpoODqANEa0qMAuYvQMYhbWhKuAMSOxwXcnUWDAF\n        gQwANQTEY/iLbQPAPbAAwjQLlH44owJM8CfmCl0PxPfHtaJ5AxR9GKt8WdhFQBcCP1TANw0CtxQmMkGZ\n        8CMIA8dxFagCj0QaMGC+SNHiLV1AOv3+wHQ69/nYDCqohhTpURICrP7+imaIugEdgzFkXMKUf5gp+MHi\n        S4k9G6aq8j0aK/gSXYIGrLJkla3cKb5bcFh4XFJ6XEpmUmZ+cmZeYmZmXHpGWk7vivqG8tqG+NSMxKys\n        QVWVeX17RyQmQewnJmfGxqdByPuHRYXDeOien5XXLz4lKyYxOT41Oz4tOyk9KzkzNyE1PT4hsWe/ASXN\n        bWlZPbNy+5Y0Dm2bOq9i8NDM3Lz0vN6hsUn+wVHFxfVrthx64c1P33zn/U8+++Ln33//7vpPmMEC+Ozr\n        r7/58Yelq9ZHJGdtO3D0g4+vPv7UC19+89W1b2kZvPjWe5kFtXPvuBNz/HfkgQfn3rXy46vX5i66C3+S\n        y7bct/f4+Yrmyen5ffuXV9+9csPUOcvLB0/sX9JQVNMyd8nKocMndcyY2zJu5pAxM8uqGyqbhhWXN/Xs\n        W1xb01RXXd+/pLZ7/4p+5VXFpVVlFS2l9YMLSquLSurLa0fVt4xoaB5cXFJd2zB02OhJgxs66uqH9Coq\n        DoyMikvKjIlP6VfR3DB+2uBRM3Lyi/sNbAHtSYri0rjblwLU1NSy6qE9+pR18/MD/DmYpUN/PRYIa0AT\n        fAAOcIv4MJN5CP0utgOyO3S701DZ/Q3Q5hZZoTddOnQZyYrFzvqAokFV9bDVGCuFeAY9CHeTQGeB1EBh\n        IriZt0No7sRlluzelP8mWANwWTpA2sAcqI2ZZmgeGDpql35nYMCMDeAgyAmvgGwwEO4mPo608d/RSScY\n        ptjH/1H+dxKAwlfxMCLka2WjaWEc3FzPXkBgneKaluLaVodKV4/uH6S5AwHxptvHqWN46AViMKAzEQhz\n        sR/AyUdnLl0zZOKcVhLAtGHTFky6deWYuXc2jJhSM2xiVdvY+hFTtx49wyDw0dMnLj9T3jbGJQgA6M/i\n        r/+xA0ztL0Bf1AHwCJ0/AbLklSXQAAiAtWBC/gP6zbwg2AFM+IEp0GkHMBoMPogWYd4EmxxL+c/9INMF\n        ByQKuE93kgBuOohSRZQY9MBWEALQs0RKKCYQxVws9hRLFV3yUx2gARkWBu8jeubEs6xMThWR2J4qd3jv\n        xTApd3bs7mJXuHRdcQd6NLdHcTgxZOHkYX2RHapfseluT2hkN1nylZWiupqM/GxfSQIxgADwRw12Bq6A\n        CXxtFlwSExpWFmSkOHwgTgtccrNL7isy6wHfzJnp6hUarknhmgJdnC5iwlFAWBCATg4AQ0SoEnQ3QV/Y\n        BLBswjodQXKsCwxHDw9YJEyjRygXV4HM3EqGB5hriTXkRAMmhQX0lgsmUOV0jUZAiC6DBlIMWAOWXrQV\n        lDQ32QJSOpj+H1GywFwaFgyzlZDYwTFQU0I1C5vQaWxGBOxmPqVI34RspxeIIl2KcCvhbmbr06FkyNT4\n        whck3EFyJMCdGUHcESzYTYcPYN1twBRgqztAfzA5gLSB9brB/E58LuwA5vbgQ81yAdgHXjkogGViusrk\n        Io8uqWwlpDAkLzgVNhZ+YiDdSuELatflWZpUiSd0SBYbbAVJt3ULCY9KychKzslOyu2emJaTnJmdkpuT\n        nJVXNKiuorYpPiU1r0eflvb2XoMGhsYkhccmRsXFR8Ykh8emR8YnxjG/PyM5u2diel5Sampsciq4JD27\n        e1oORn7PAQP7DixNycyLT07L7z+w/8D69onzpt56T2PryL6FZe0TFheWNgOsXQFhlSNm7Dx88p2PP/zm\n        +o/fff/jR59cffyZl97/6LNPr301dNyE+LSMrXv3v/LuBxsOH73y7Ev/+ue/f//tD4D+svX3pvcq+PX3\n        33/65ddpty+/9MxTi+9ehRtm9+z71POvvPn+e2OnzMvILGyfOOPendtW37tr1LRFVa1DKppap027dcaM\n        O9rGzWwfN2Ho0EmTZ9zaq6S2x4CK0ora0n6lBcUlPYoKc3r3LyqvGzCwurC4alB5Q9/CgYWl9TXNo4d3\n        jGkf3Fpa2TqwYmhZc0d964ja1vaKxpb0zLyU9LyEtNy+5Y21wyb3LKwJjU7sWVQTEBwG/HKxWhVQZfhK\n        fgFBoZXNIxJTc/CogFPAPRCTRgDtABgEwr8PkHV7GQZwMEjAgDBbQEPyE16Fv8jD1g4i6VNEd2lG4BTE\n        GEgmr29xeW1zZDQ4AIhKYU7EZ9amaBPk6FT3gGeiPGU4oLYzP0focYHsXRMSAD5LNGLDRDM8Xi9DHeIs\n        bUnwjsj+ZLses3VdJ6Cbkh93/h+3PhP8yQFd7h0Ofoq4j9j8S/j6/+fmoAT6jshAYr2fJOFsUU3zwNpW\n        YD3JlfsouB2Miov+GYIAutCf+T9mWYDbG0gLYMaS1UMnz22bNLtl7Izh02+ZdOsqEEB9x5Ta9kkkgFFT\n        YQHseFgEgR97uqxtBFSuLgrBhPD3dcuiBriTABj75RCnCPfkAwkcwBiAGJjQ+SNoAHaASQaMCYv9vwT6\n        Y8IiLwB6nM0vGhOrDJnPI2Z2v5Opn4kO7mRi7hOQZOWGwBgpdm6FSOcPm+BLiXYR3e3M/PHDKy7MdjIY\n        AF7BW9yExCCoAuZCb43JP701uZfYIx43yRZVvon46QV6nIbBclKb3c9qlR12un3sNvzVuoODepaW+sqy\n        T7duheUVSWmpPr6+sABgK9iESas4HH4OhyckyBEc0SsirMrfFWLvBoGfpyqFogg5TIAsQDyEuaEE/ShV\n        wgATZKoKawJEiDhBVSJ1E8WkMFACrBzAN0FcSWJyDnNDsTJF5U73bM0vUktzVVxIAyKR2TWWIB3WgALt\n        HEPct2TrBPoUiH23nGYo3XUlx2vJ9loHeSypXiXMY4nRFVBRsKYk61ggRemMQ/jTw05zwa1yy4EAzPFg\n        uow7A/HBJUBt0EykrkQS3wXou5UoQLluAV4LUW8BDQDQaTTQILBA+wPZRR0Az+IIEFyc4rJwgx1AcS1+\n        CcB94LsbGl+kEoFgAtwyhL/ulj1uC5hABfSLvm+wA4D+bArEh5TAdsnCgZagSuNVeYqmTNDkEbpcZ0gJ\n        blm2SxalW3hETEpGdkpGenJ6JvR+enaPXv2YF1PfOrZp5IS0nLy01Kw+AwqB9GFRCckZOVFxcVGxSYlp\n        mQnpmQD9xOSkhPTsxLSs7Jyeub0HcNP2vD5A/+z8PkVldbl5fYJDItPz+oRExXoDIkMjYnN6FdS1T+g/\n        qLK+fcK6/aeWbdk6btLs/sW1IXHJOX36jRk9c9mKjffcv23L8dPfXP/plz9+r2wdnN+/4sHHXvzy+o9L\n        t96/4O5VX3353a+//f6Pf/zruVde6pg6/4UX3jpz9qHcAQMPnT01bOxEGKS7jjz4l7///eXX3z734KMT\n        x88vqwLvzF6y/p5b7ljZ0DamfPDYho7JTa0zbrt1xZQJswYUVtc1tzdPmNQ4bkpzx7jG5nFFJbX5/QcU\n        l1WWlDb06Deo78CSgoFVAxuGFje0VNbXtwxvb+/oaGwaXFDRWlg7ombwmGFjJ9W3jSwsqolLSnEHBBU3\n        txXVtAUEx4RGxuT2GWR4AqDDIZuBmBBO4AAIc/BocdWQsIg4/AsSAp9hXkAzXUAYmIjecABTMAHzhRwu\n        M0ggTISbZoFuZ7cfGgEAd3IAiMSh+kkyJH8+OLa6KSomHvaH8KvYoc/xb9O8XHAGNTsGzlBxc0Kgp2Zn\n        8x/irzno7hfynyaCHU+i67RXdHKGcNTwWpKH8OeQKriDvHltp5y/aQQwAoyJ4AAx4Z3NT2cYQCxmuifP\n        4hRdSbQAzI9g7RuW+HJHGEv/8rp+pTXCOnExIQoDFGvm/xgsszCFv+kOMmMAnRvCzFhKAhgyaXbzuOkk\n        gNtWjpq7tG7YxJr2idVt4xpGT916/IFdJAC6gAa1dNi7gsDgAAH0wvsv/D+Q/6YLSBSIkQAA/R4SADcB\n        BvSbYYAgsxxMJAJFWEgAOBtqYQSYVWB89Yth3ie1PwiAe/+Kg2wLAejnhsAQ8gz2Qrmb3JBkY+kv4D7d\n        RH+7EitMgUxR9AT0N++GIwB9jBTREo5vYUawkFjK1eQ+urUPQFDjljLgCVybz6wYJdKjq27VphuKy2mB\n        /Lc7gOl0ATlBBjbZYXEYLslqg9gHH/h082Fyic2mOO1WlrVrNtXlBx0S7NWDQ8tCAos1JdIh9WLzBnp4\n        oiHVRSZPkkuBfofQhswH9PdTpX5Cd6cxO4g5LXEMtAoHkfDDxLsYHogGT2ikingm59BqAb0lYjHrsxQA\n        H9giGszBSDJ98UE0LyxQ06kG967JNZQk4SDq4Zaz6CyS6f33WuM9dBlFuS2JhgV2QJjbEuyhBwnPYPqj\n        QCG4Jz3yTnCA5IEAN2RAPK6CHQMCgK4Ppdg383kskYYFZ/3d3AQYR3AcBIC3MCnCYB8YlghhHGDADjD5\n        AAuwGEdwt2g37ACL6SYC9Kss9ZIZCgYH6KKYC9YGuwMpmtsKc9wMDmMle0KI5tKaYEH8bNPZJEPpp8l3\n        adJtulytcZeeOKx04DfpExAcHpeckZCSlpyWmZSRndu7YFBtw9RFt67auH/4hMVpWbmQ872KKoHvGTlZ\n        KRm5qTl5ydndU7PzMvP6Zvfsk57XPSklIzkpVbj++4AhIqLiIqLjEtKzUrOzElKTE1Kzo+LT3cHhJU0d\n        /UrrVa9/Vv/CzJ4DADTp+X3Gz7t97eZDd6y6t0/RQMg3yeqMiEtL71nQv2nIqs37dp44n9azT21Dxzsf\n        f3P9xq+bdhysGjXm4APnfvvtL598/vkXX31x5pFHb71jQ9PQiRWtHesPHsns27epbfKLL3zy2ZfXnn7h\n        1fMPPbJ9394Ro+bNvOX25evWzrpl5S233lVSO6SiY8ySO5dPmT1//JSFY2YtqWwauWj+LbPmLm0aPKpm\n        yNDSpsayusaiyvqiQYMr6lpLahvLyuqKy5sq6ofX1bQNHtrR0ja8tLK6rH5odd3wyorBJWX1FY1DB9W3\n        hSck9yqvrhw6KjY+zWFXQ6NiY5OyADrUxcJjQ5Bibx/D11cOjYrvM6jSExAMuIacxylAKhBcACJ+NjAC\n        sN7cIlgkgBLxRbdnVQc9AMdpEFD1a0RteuFF+j9z7zR6yZ1q994FZTUtcYkp9KQLAKWvRqR7YjGFuQnu\n        wjjAYKqoeSsH3USdkC3W2Ox8MAHEFOOCRVx4TBPHidrilLAh2GwIt6J4F/AtbtJ5N96hayWv7eQD3sEc\n        AHRBV7xEkIFNhhEj/EIkGyhR7gfg59PNr0f/gf1Ka7kdmM6eeponkIFf4fE3/EPcASF0CnWiP4cgBq/P\n        3jMggLW0ACbOaho7fdjUBZMW3zNqztL6jkk1Q0kAdSOmbjl2Ztcjj607evrY5acGtQyH6IUFYMp/vGKY\n        cH9zV0i8ujud/iwEE6zQmQmKt8L5I5nVAMwBtUhhisTSMOEFAtCbjT8J+twHRvj9cZDyn97/GLtIDxVd\n        P0XuP+MEwHos4F6PzPdnHJjRY4eUgbMORhGSaRn4AetBGNT+Vj/6gtj8hwYBi35VpYeh9NGVPJ1tD9Kc\n        co6TMYPuMAI0S6zXA5q3617FpcmQ8xarn5X+HDCBZLF1g/bHL0FRaBw4bH7MDrLJdrsfOMDB2IBss4It\n        /BxOI9C/OMS/nyg46K0qfTQm4eDj8CRRLjKBSAcixIeI7tDA/WiXJJpAsA4Lp6JELhDIIJK7w/MVDAFQ\n        jtIIzfEwAljVxS1igHQwGsLFbRMYD2CvUCAg7gA+wIjR5DhDjnMrYboFCJtJ548SJ2CXoQIGjekCwsh2\n        KwlYZiiwBpJ1bkOWqMnphgSNH6gxpyhUl4TrRoYG9xrM0gE9MLPTTWkP1R8tGjuTCbBShHnxFhyAlbBI\n        4g3aGV5YD26yAj4IbIHFpuSHWcDsIFEfwLfCR0T5D8gW4V8YAS5dcqmKKmwCf4/F321lPqioGXaJMC/o\n        waVJ+MnE4gel06sWqcn9dfkWXWnSlDz8WJx0VTktPsHhsam5PeNT0hOTM+JT0/J7FwweNnrSwtuWrr5/\n        9oI1HeNnTl68pGPc9ML+5eCGtO55BaWD8goGgAO69xqAf4E9CkoSUtKTM7LiU1KSkjOSUrKdTltYbFSv\n        QeXxSempqZlVraOKqhsmzJlz98798+7d3TZ1Xsf8WzrmLuw1sCo2KTc1fcDwKQsWb988ddFtFfVDA6Nj\n        dS+LeoLCouOSsxMzertDwltGT3nh5Q927jo8dtoto6bM2X30xPc3fv3siy//+c+/f/HdDwObhvcoqthx\n        +FzzqBkRSZmvvPba559/ffSBCy++/NrRs2cvPP74y6+8d/T0hdtWrJq35O4je4+s37Rp0tI7xs6YOue2\n        5YtWr160fElD05CW1mGDhw0vLKkubWouGFRWUllXUtfYr7B8UHlL/eBRZfVNg8paBwwcXFJaPaxteEv9\n        iMqaxvIqEENLUUljn7KGktr2krLG+qETBk+YGx2fBqTWDLd/YHBEbJLuCXQ4dW7ypXvtZl6/atgduq+v\n        b1BYFEwl1e2FahZo7nLhH525bYuzM4PTwfwWQ9VBACzrxbViuxhmjoocf4ZACdAC1s0BugE6S7DubI6M\n        7r3KapujYxNlWRaQKhS6ifWMD9NuIPp3evmZyM+3DtUisvUJ5Qzz0okEowF4TTQmiAOpWRssWKHTn0Pg\n        FsEDEJiJ5iZh4NVEeXNu4r4J7jwlBj/Lzk/hWUh+Lu48RQtAGAH4IAh/pi5IsiRb+g6qLm8ernuDWT3n\n        ZisIhoINr+4NcgeGeQLDdP9gkf7fFRvQPZrb67PvzJWZS9cNnTy/VRBA+9R5IIDRs26v75gMy7S6dVzd\n        8Cmbj5xiDODYyeOPPlnaOhwWAAjA7AJkEgDQH28xAP2BwgLwiNebWUCm8wccANAXQWCJ6K/4hZk7f4ky\n        4GCFsV9o/GjhC2LzZ1H8lSgcQdD4QH9gPRbQX2Tzo9feTtWfI+A+nohP4E5ziFQfzun3j2Vw2C/eQdcQ\n        Bm7CuDGYQNwwxcbsoL5Af83SE3DvIu7jJinU3cwaynX6gQACPAb+pFwer+xwdZMtMn43Lqb8d7MqTPek\n        9rfLVtMasGMwNmATuaGKVQ8Mcno9ssMmOXUlOKImwD3J2a2Xyv0AcnQ5X5fx6SUuuT89PFKypgDlKfBd\n        7GMM9M+mV0cKEB2BcBawRf+Pi/VfScI1FM7GloqbXhrKWxBACChBzDFSVFgV3K84WqTzA1tDRf1XhMq9\n        diMwF0o8RJyCKdBLZxvRPINh4RQwgduSYCjJbjnNTU9RoluJc9Olk2TI8W6AMvu1kRhEYBlQDmgOp/ef\n        mp0EgJt7WMAFyyOKFAK9L/kLTA8GmgPKGTGmn4fP4Kbbx+2WgjwsB8NVgjPIBAE8i+dnjAQcQDMCZ90s\n        AoAFADvAoZnVFwoDCR45kOlAIGtaBiYHMMtTtH9I1eUUTYlVpVgNc2WGrqzQpAEqb644/LopPgkZmRBT\n        2b37J2XmpWTllDXVjps2b+iYKaMnTVmx7r5Ve47evfvgqNlL+hRX9e5fXtXUXFJXAVOge5/CxjFT+wyq\n        yMrtV97QkZieDbwLi4wOj4gqqqodu+C2wR1jkhOyimqbNhw6smvfg7sPP3z3xp337t554qHLhx967OSD\n        D1168vndhy+u2nBw7+ELt6/bPnnu4s17Dtx21+bknL7eiEhu42cYkTEJaVk9ge8tHRN69StNyu9XXNNw\n        8uyFP//889dfGQb46ZdfehdXFZY0TZmxKCgudeue43/++893P/pk/8lTJ84/9NSrb3197bu33nhj0979\n        429Zunzd1gsPXlm+esvCpatLKuuHj5x86pEH56+4bcSEiaWNw8aMXTB0zNTeBVVl5S0DKyrqmobWNYzo\n        X9hYVT20pq6psqZ5wMDGQbWtHRMndIwdP2LctLqGUUVlTYMaWwpb2grLW2qbh925bmNm974wiUVvMiMo\n        OCwpNRcw7VA1QA9gSLhxRA84tujRZMXq9ni9gcF06ajc+4WJPWaWJ1He3OJRuP5FTwgSgCgawCATML+T\n        wp8q3uHAp4htHbucPA6Xrx8jAlk9+pZWNYaEhksS/r0CoJmvSaAX8QOuZBInucFMFjKdLSJsAJ4QnEEC\n        4CuAWJIV5hd1SnKeFVpeAL1wNGEijhPiaQGYIN5FAOQJQQCc/JcAcEp8imAFgD2A3gR93Me0FbDGXIyb\n        c0MYm2NgzeC69vEgANIq7SdQo4fufnegBoOgs/hL7BEmKoTx8zf8g2gBzLx9bfuUW1ongACmDZ06b+Ki\n        5aNm3FYL9B86vqp1TO0IEsD2hx9dc/TUiceeqhgy2iSALv8Ph0kANyPAYmISgNn8R+h90wukCIPAjAEA\n        /QUNMCQgioFDuxrA4TWGLT+J3WZ0lxO7MAVwVuwegwneptk69wNgPg97vSmQ/AB6QH+Sk2UEZA6nHMd4\n        gEB/cQrrU3k3kULjknqqCvQ4oDadchu4TyMgxSklY+L0y1StYW4PrUuvP+DEF0acw2URBCDSPe1M+LHa\n        /EMj7LqOOSS/1eVyh4b5Wiw+stSjrDI0Ls6nm4/iUp0hIeX+rmFO3wIXu0P3NShC+7JDHPV7tohPQuBz\n        MN9GSnRJCayokiKA/iKREcgOhsDZRA4msEeL/B8GkFXchJXD4IAYp8R9LskWSoaq5MLO0KHfLYnMz2Hl\n        V4TIEYLdEA9oFlobqh/IDoSFRgamA3PNNnapAG6obzCBV4n1WADoCW45g0xAJw/kfBh9RBZwACA7VEB/\n        LEwHN/W+6dMnWBuWMOA7YZ2sECDiBLgWaI4BQwEGBF1GlPMiDIAFGukhWGc8AB+Bm8M+YD2wcArhnoIY\n        ZM2QXbqs6orK6jAFcE+PEEwEr6J6GDE2RDNRh1NxuiSrLuEngB8Ivngyng0GjSHfq8uzdLq/rC4/2eaT\n        kpXRs3hg39La7r0Lew0o7Zg4dcSCRYuWb7lv/Z571t6/cuOONdsOL1q1qapjbGFF26hZi0ZPm1VQNhBA\n        3Ku0srSupbFtYk6PgtCoxMCwcCNAzx8waMPW08cefnZgWVWv/gNX7T+0/9yFw8cvrt1ydMnKrXsOHX3m\n        uWefe/6VF15644svvn7xpbeuPPPCy2+//9DDTz725HN//cffvvzyu9Wb9+89dmL8jBnJudyZq0e/QcGh\n        MXpwaG6/AVk9+wdExIydPsesBvjb3/8x99ZbM3L79iwoUz3hS+5ajYPfXf/h9bffffXNt4+cu3D60pV3\n        3/3woQcvrNm0bdqclR3TFmw/vHfp0s0jhy0cM37yhBnTl6xafff961avWTlxwozB9ZNHjZlRP3zK6IkL\n        Gwa31DQPr2wY3rNfYVV9e/HA0oKBRWWVbQUVbUU1DYNHjxw9ZXrz8KnlzeObh04paRxZ2zxyweI75i1Z\n        5g4Iwc9Uc/s7nM6I6ITU9DwQgOb2mC3+Xbq/md5DBNe4kxeADNIeB0kA7P2JUypOqVCsGrtE2LmvC31H\n        UP1M6ndp3ODXJUK+DBtQs0O5Y+Kk88cltnBhFIEr6QuSAfR9YLVVNgQEBskEVYH1oicEFTfBvbMIADcB\n        eQgQt5tEgrPEXxPoIcBZxswBYhFYLLBe2AomOvOgwGhcJWLIWGCidhcBYHSiOe5gzjthvWuBQ7HaTYIB\n        Q5AShJFhvjUvlyQJRwoqGstbhrsMr3CXEeLNwC+9QDpDvpjjIBiU6M880UBPQAgI4MqM29cMm7awbeKc\n        ZtMCAAHMWlLTPqFqyNhKEsDkTgvgyOnjl5+ubB/r6GwF0Qn9N4cJ+iYBCAuAnh+h9zsjvZwLI8C0CQj6\n        OG7aB4IPwlkAbJIBu8JB7wP32QOuU/7LcUK80+EjDAUQA5OCBAFksZsb5X+8lb5+BodFvwdYALQkwBa8\n        kJcwL8gBAlBSRFJQuuj500PjDsAmBGeL8K8ZTM5ySt1VR4Sm2jWrAwSgGZLDbnE6/SxWqn6HXaT6WLsp\n        kuYf4PR4fK0KOMCiqS6PP8MA+NP0eBW7HUaD5DFiogJaAuzVLr+eKreGz9YZb8hTpTyXkqrKTpU4TuUu\n        0nso511SFDnALxaAbvaD01glAGsgUpXiRDIolplxglgXdynIUfmNEp0gMwVSF2wRo/I1U5e5kwHLvuRM\n        Q04A5JkfoTM4DDSPMhheBj2E6ZYQDAYDlARdyXCzvhdKHAIfTBDqtuB4tAeIzIYTcbAb3HKyTs0e6QZY\n        U/6DDEAhWANSMW0LHPQS+pnuCeIBcOMIoN/DGAA+kWug973mVu/MRmXGkUckBQH9wQSMDbip69lHSOyg\n        CZLAehCAv0HVb3gkFwuA5QBNMtyy4VY0N9sEGbAD2B2aVWM+wv1VI/qk4lH9NcWlS+W6vEWTO1jK4Jto\n        9cnp3rusfWzHxJljpswdP2/JbSs2LVqzce3eY4cfuHzfoaOrt2zbuHvPpoNHV2zaNnvh6vnz71uzcfvU\n        O5b26l+UlZM1evq85hETRRyoW2J2XuWQkRt2HT917vlRE+dHJWRPnH/H5See2Xvo3P7jD5w4/8jBMw8d\n        v3DpyjPPP/PqG08998qZi5f2nDh59Oz5R5587t0PPvnbP/4B+L7x04/vf/Tpn//589e//nXv2Yv9q+pg\n        yyd07+0JiwyOiO7eqyAhJS8qNXPfiZN//ds/1m7dofqH+fsHR6Rnjpq+6D//+vPf//nX2++//8nnX17/\n        4af3Pvj04ccfv/jIU1eeeOWhhx7ftP3wvCWLJs9duOD2NfOXrrjtrhVtY8ZXNbaOnThr7fqNcxbOGd4x\n        ZtrMxYW1DU3NHSWltRWNHVVNwysqmyoHt9W1jq5r6Cirbiysaq9pmtzYPrZp2JD6tiHgg+KBg6vqh9eP\n        GD1p2ryWYRMjElMsDsh0N9AqISU9MS0L+K4BlTpd+V7m+9MRBDTXRMIPw7+m0hf4rppNIKDuKWlxyqwL\n        UzVcTg4Qu32J48Lh42AAAIKd4p0B3k6DgBwgggQ2h7Obn5/bG1ha3TxgUCXISLFa7E6RuQ/yMLdmJPqL\n        Yed9BKPQESQYgo2dBQrTnwPcF+ivQKELVqC5YA5CtmkWUM6b6h7wjfn/JQAT+sUCi3KTDMw1N5N/BBng\n        uLjJ/1kgkoVkGU/BdtClDe3Q9fhJ3gR6Jv6zz9JNAjC51sMgsCfQHRDss++Bx6cvWQsCGDJ5bvO4GcOm\n        z5+8+B62g+6YRCOgdWzd8Clbjp7acZG9gI49+lR52yizFYTp9xejc1cARgVEATA4QJAB839M1z+BHtpf\n        kYTe92UEGAaBIAYGBhQRJFBEUZjFL9gqhYrKAIh3jAhbp0co2kJKSKXAl2EBQP6TIazMARVudFZ1JdvY\n        CS7J7pcmCrsYQHbKsCQwB+5T/tvoODIzSjMdcp7L0kO15Ksy0J+sYFYMOJVYO7OP0p1ynlPKVm3Buuoy\n        VCMoxKI6JQervQD6khgmAeCffGhsVFpujo9vNz+H3ddq9TX9/uQGWbHTPSH5B2XFRU3wKGM1aaAul+pS\n        HybYsGU/QwIueaBLwSvm7KwpagJCTQJwSiF07ktgBYwEtuPncSygH0k0oAYlZIvthdNgBIi8TywLAKgJ\n        wIXpkKBJOJ4EytHlbLeUZDDSAKsiiR4egjiYwOui8QHIjhDBAIB+gthuLNhrxmkVr3DfRxmsNE7wUOkz\n        hEC3D8+KkK8S7iagJ+kW3CHAbYH2x328Gu0YIDsUfTAre0kAoAHo+nDm/OAShhO8eAY6iJhaCnmOEeXB\n        w3AlLgEZuEVcF9wQARPBYL/oALYMkt0wBdwwBdgHAmfBJbAJvG6LPzhAtAh1uWRFk300bsW8TpXHijZ8\n        4OAYGEm6Mk2XR6tKmyoXd/PpU1Y9e9naJWs33r3t4Lp9B+4/eGTr/rMrth68Z/PB7UdPr9174O5NO9fu\n        2rv7xOldB07v3nli36mTbcMmFhbUrdq1v2nkmG7dfPTAoJ5lpeNnzj54+pGHHn9h3JwlCWm9x09ZfOjC\n        w+cevfz006889/Irz7325oPPPr3j+Jn1m/bet3vfoRNn9x99YMfJsw8++cKb73zw9bXr17774Ytr335y\n        9ctPPv/8hx+5Fcy//vNnj8KygtrGIw8/NnziND0gmpUH0bGxycn1Q0aNmDw/OScnKi4+MC6xZtjEH39l\n        i4hffvkN13766Vdvv/vR1a+++eCTj99598PXXn//oYeeePTK4+cuPjz7zg23r9m+adeuLXv333f/htkL\n        Fi5ZsXL5qjVzF6yoHDyytLYur2f/usYRVfUjehQO7NW/rKRoaP+Cytb2ccMnzqgd3N7YNq6mdfiQtvHt\n        w6e2Dh1b19Ja0dBaP3j4oKFDi5qGNjZP6N27HHjk0FiempCWHR4dB1PA3PJXM0SYV+C+iex2u4n+9PAI\n        DhBzYRzQv49TWIyDYg8Apv+zg7TwCJk5o7QAOn04AvSZ5APEN99anQ67i3mfFrsDHBARHVfb0pGZ20Ox\n        yMRli+nrNxcLF7/w/5AMOHiQp+gRor/IJABFOGdks8sbwwDCPhAZPqbHRhw3sR5IbZ66SQmmhL/pz+mE\n        9f+ZmClA5uXmwf+eunkc95RkcJC1X2lNeVMHgF4QgPCVqcybAiX8lwCE6x8TtodjO+gAEMCVKYtXD5my\n        oG3ibFgAQ6fNm7Dw7tGzljZ2TBZhgIkNo6ZuOXrabAZ3/PKTZa0j7KIOAHBv7gdwE/05utBfEECXEQAC\n        EDJf5INyHmrGABgB7rQM8Boh9gMIA/TbZG4II2IAEOxRVjncKqp/rX7JooeP6cyJMQMDVpYCsO+bUxGV\n        YsKr4+AW7XGU/ByJDoltPukdEg2iOVg5nOtSemrWnjp7vfFyETCIp/A3PUXCAsC1mi3QTZ+j0+PlliJ2\n        G5DdFz93GwjAwnx/O4DebgT5RyXH+VplGgf4K9FUi6oy/R+/bwf7Q6gB/hGRASWa32RNbtCVWl0uABZD\n        YqsMXWSIzQbiiewM2warUoiLkjzU5RfO1m8SRH2Ki+6LRDZqloJcEmO/wHSxAyUuyREWQDLLeuUUYDHr\n        s5gU1FMEUWN0GUwQzYQf0ICcqTE2gDskGnKiW45hjRhLDVjZC/5gQx4lQLfgAcATQN5oD706eMu6XBgW\n        hiXF39LdqyR6lCSPJdmjZBhgGmb9gwDw6RgR7O3DXE9gN135wimEJwGCg2NCuJmXBL6JF1XKWBYgytBY\n        Q8BMf8YqQtxKhMcCzgABANNxHwh/Jv6LO4TqLBWGZcB9Y0S3CTM9FJYBLsHBYA8Dwrph9bplWZV9YOpp\n        8l26vAA/f00epSnTdWuLBjtJLtbkMbptnC6n+/iUt49YtmP/7BX3zV69ZeW2XRsOHNx94sKmXYdX3L9n\n        257jWw+cWrPr6Mrte1dv2b9z/+lDlx6ZdPudAwc2rVu3ZfzseZCEssVR1z55x97TBx44f/DsxUXLVuYW\n        lM5ZuvKV19+99NSzO09cPPjApRNnHjxy4cK+Iyc3bN+/fPWW1Rv3HXvgkaeeewHQ/O4Hn3382edXv/r6\n        vY8+feGVN9957+MbP/38x1//BjT/4J0Po9N7n73yFOaffvntxu3HSysaUvN69hxQnpDRPTm7R0BQWExK\n        +tbDp37+7S///Ne/fv319x9/+fXn337/8cefX3/r3TMPPXrqwYe/+ParL768dur8xfVbtt993+67t+xc\n        u2PXfTt23LZi1aH9h6ZOnb1s9br1G9ZsvG/T1AVL6pvbm9o6hk2d0zh0Qu+CstScHgPKmoAyZdUNZUNa\n        2kYNGzJ4TNuQMaNGTq9u6BgyfPTIcZOrm0fUD5nYNGpi7dhxQ4ZPGtw81j80QrIohn9QdGKW2NidAQAA\n        E4wA4d4xffcCr8VGvnZVtavMrXSI2IDL3CGA6pVOf27Pwtx6r+EO4D9JHfRADoAlIcLFqineAdYcIAAR\n        BhBZmGZjZ9CDE5AN0Mzu3ruirjUoJNTPDAYA9MVVAt/FW2EEiCPEfeCvibnEX6yhzAfK33T+CP+M0P4m\n        xIu35inhMuIlxOtOVui8io7+/0p7QQ9dKC8Wi8vFwAQH+XHmEEc4zG6gA8rqBAGI0Dq0PywAEgDEfqfr\n        3wz8mmSAZbAMWAm874HHJi9a2Tpxbuv4mU2jpw6ZMnfcLctGzVraMHwKjIC6YRMaxkzbcvTMzkeurDl8\n        6tilJ2EBmDEAgD4IQBPob2aCCgugE/3dggCYEgq9D9AXKG8SgKn9TeEfJgiAZoGoB44SlcCA/kiR8BMv\n        ID7G0untAfoDu1kaZuVbngLEW/2ShCmQYsZ+2c6BJBHPxqLM9KfvyC4IgL0f6PzJsLO5f7oDBEANmKEp\n        CXb6jrq7yAGRuLlDytDlPB1iXOQRqXbdpbo0TfUPsjjdQHMr9KTDDvmv2GyyxepjkXwUCbLCExHq9BrC\n        8+Pspkh+NovkdPj4+fkqCmSGGuIfGaz3d/qO0+RyXemhSaW6DCMgAWKfm/eyAadw6EtC+NPXjxEhwB2c\n        FIIngR1Av41C+U/4lsJVsZJUwe3gQQbp3H1M7q3LfUXKJr5LtFNO0SUgMgAaYAfJn6YryaqSpHFLgxTR\n        aSfWzRR+mBfBLoYHot2S8NuwAoC31aVIen6sCYB+8YSgijDgvtea6bVm+VvTAy3hItgLqBW5Q5YE4Q7C\n        nTUB2bGGEuOBcWCJhNgnEzC0C/0eonMryjDDAo4hVRDBJWB6kEgHwkGAPjtA4JWxZfYa6nQQCfQ3owVm\n        RzmDhWkS2AVGAGiACaaGJFpEWBS3xcfgZpwbNfleQ+rQpGGafItuWaIr83XLXE2ZpCnHdOtdql+Wj8+w\n        cfNXH3vkjs277t6yb8vhk/sfOLPnxMVtu47uO3Tk1KXH9x+7sGLDrnt27Ntx7Oz6rUdHzVnYv7z51uVb\n        Zsya4+vjI9ktw6bMvv/gmTXb9i/bcXjCbfc0DRu36J57j1y+eObRB9dt3XPnPZs27z6+7dCJNTv3rLx3\n        /8atRw+cvHT87COHzl44efHK40+9ePnx55546rl3P/z4m++++/zLq5+CC7797vsff/rHP/514Nj5iiFT\n        3vzgk//8+9+///HXP/742y8//nXLiVNFDUMzMvOS07I0I8ATEX32yrNgiPc//uzb725c/fqbV9567/qP\n        P33//Y2jxx5YvWXnq++/d+3r7y4/9vScRUsnzbnzyEMPbdm3c9eB/WOmzOiYMP+uO9fMmXnH8jUb1t23\n        9pYlt9UP6WgdOXHw2NltHeNam0f3LBiYP7CgsKqmf2ldSUPLkGHDW9pGjJoyva1jREPb0NYREyrqh9c0\n        j25kl6Gp7UCSadOGjZ8Zm5zt4+vjHxIaEZ1ic9Ch72R01626DfybogtIEAAltlPs1OhSzfY+ggB0FRBP\n        K4F2AFnBpeKt4fY3PEG40Oztw+PChyPAmsVZph1gJwcwI5gEQNdNpzMHsC7JCthowMDKwpJqt9sLBAUW\n        i43jRR4RlT4lPx1H9CwxLKzwP+CtQ2w6z2V400kAxG6bAsTvBHeiP1ea2H1zbuvkA4K7uMR8S7sBR8Rb\n        E9y7+ECc7bwDOYAfJwiGd+i8FesA8LTFNc0lDUOdqpsWFUujRemvyAgyCUCYAp3WgPlWhwWw94ErIIC2\n        CXMHT5jZNGYqu4EuYiuI+mGT64ZNqh06oX7UtM1HT+145DEQwInHnq4YMrqrFQShH/Kf4d9OL1A3j2wy\n        AcvBgPUYIAMT60EAeL1JBp1hAKH9zfAvtb+oAcYksjMAwCIAYL0Q8mwNxIpfO138GHF2vxgxx0HGfoV4\n        B0SmibxPs19Qgkj3BG3Q7SOyLTFh4hCgX7fkawomohcQ937JEpvCx4l9AnIYCZByNLmPCjKw6apm13Q9\n        IMSiemX8cTBjnKk+3WgBWBM8hma1++FPjcQA+8BpVTWbpvtYLN0sUvdBfYMiw318ZD04OMVf7SEIoFGT\n        S1l2wDIuCHa2WabPh88DUewRmJ6misR/F3efh2UAyY9vF8vSASlCtO3MY54oc35ABmCRUPa64QKYAjm4\n        FcAdCAueAO3BSnDLqQa+FBN4IkUyPuyARF2JA5STFSRAc4hGZ06MRndQHAgDlKDRGRVN8KUnJ5Q5RSxC\n        DlIlf1YGWBL9Lalea2yANchrCfUoKV45yd8S42FeKRhFJG4y+ygUj6crEUzlpCGCu2FA4Ad46MfHh4a6\n        LaznEk7/cI8c4uZZgLgoIwABiCJhQwli22fckyaCmSZEC0A4r4D7GIYuOUUkALYIs0I1yWbI3dyWWR7L\n        eUPeockrdOVe3bJDU9awCkxp1ZRmTanXpBG6ZaLTt8bHZ+Yty3ZeuHLv9sPb9hzac/LsnuMP3rfjyIrN\n        u3YePHLwzMV7tx69+74du48c23fikYlT78zpVdwwanxpbVNgYExVddvideuX7dqxdtvuuzftX3zvjjGL\n        bp2zfPnuw+fu23N86boNt6y8d/2WfZeeeuaxl1/Ye/LEuo371+85dvzilbMPX9p75Ojeo+fPXr588fEn\n        n3zqpadfeuult9756LNPfvjhx2+B3z///sPPN6bdcs+OQ+e+vX7jp59++fnnX//+z38D6Dfv2xeVkApI\n        iknJbB0+rrp+VHxan8LS6l1HT37/w69//P63jz67eu2773/99Y9Pr1597JkXDx678Mxzz3322dcnzz68\n        ZdeO/SeP7T54eO/BI4uWLbtj5X27Dx5fd+/WRbevWLh67b1bj4ybNrt62NjR028d2j6pvqq9rKG1oKq2\n        f2lFv7LqisZhVbVt7ePGj5o5YdT48SPGTGluHzlk6pSmMZMah45uGTOtpW3KqJHTps9YUFLbqjhU/8DQ\n        oLAogKbTpZu7P6rQ/pqbLh2XgG9RdSWCt5pwXED1M04AjQ8U5vaNTihaERamN58OfXxror8LFoMKJiDc\n        MwGUznpe4hLaX6RyAisJwSzxBQcIUQ+jXJEDQ8LLapsLBlZquhsyugu7O7095iXkFbExgABcan+nbuhA\n        WKdm3tkEazGh194MAvM+Fu4URnCHBWB14PFMu8FEc7PsoPMsLhH4LpCdMt+8rVjANYJOxAIc77Qw/nvQ\n        z1ey2JyD6ttKG9qdqgecB+inxmcRAIO9wghgXyBz3KwEpgsIBDDplnsGj58zeOKs5rHT2qeaMYClQP/6\n        YbAAJjaOmQkLYPvD7AV0/PLTZYOHOztbQZAATOj/L/qLGmC8hfYPE3mfIADQALA+oMvjD72PtyADMkFX\n        RhAzQa1SiFUKtvrBFDCLAGLtzO5PEY2AGBOGkBe9H9gQwiZFdap7+k+ynRZmAbE7tHkh0L/TX5TkYLu3\n        VFwF9HexFSjeZghwFwTA5s/ZYoI74G6JDqhmEUy2sRysQJcy3bbAwAAQgNNwW5hRaAfo4xWjG9u9ufp5\n        Q8I0lw/rAyyyzepnUayqagSHSXQNWaJTk11ew6G7Q4L8Q3S2aqhQ5WJ8om7ppcHOYPEBew05KedNl4sH\n        uM8MTilPlQDxQU4iewx7t4EM/CLZOo1VY6lAc/Gl4l0KcB+Gglk8nA9zh6n6UobI5AEHBINOYNAYllhh\n        JWS45UwPEx9hE4RrLA4IB1jrSqwhxWA9VL+upLqlaOEUAnaLU0z0BM0kMt2IVyW7lUjcBIjvtWTAFPAo\n        aR4l1iNHeyzZHsYVIsU945gRxDRQr8YEHoA4pH24oJNokVwUyi4RUogZ6cUX94A/uADLIPnxigFzgWd1\n        iZxBW4EEZtIVKIQhX7FrvK5LRHyVGUEesZekn4t+/2ke5dMAy+Me5agmH9UtmzTLfM0CIwzsm+uS7JpU\n        rVtqdYvb6VPi47P0ruXHH39+/eaja7fsBYweOf3gfTv3b9i7f+fRs/cfOL7jxNm9py/fff/+wcMm53Qv\n        ScvtGRwTbTf0aXOXHr/wyLELl7ecPLl0zf2L79y2aN22+3Ye23vo+Op1O1fdf2Djnv3bDh4/dOjBfUfO\n        7T91/vC5h85euvzkK69/8PGnb7/3wZMvvPrGO++8+uabMDJOXXrq2JnLZx59/NW333vrzfc+u/rVf/79\n        55Vnnqlsn/zWe58A9PHf7//815nTTzUNHq56PD4+fn2qGi89+/S//v2vD977sqx6iI+PT2puvxWbd7/7\n        xVVz/S+//Pa3v//zm2+v79x/9MSFi19d+/rTT744f/HyklXr9xw5dOaB80fPnN2+a//MmfPn33PHyh07\n        brln1dwld99y15rRsxbVtYwdOmpCa/vIgsqahvYRlW0dA5uH1bWNHD122rhZC5rGThg/beptCxdXNgxt\n        HTehpWN8dfvIxrGj2odPGT1+/sgJs+qGT3D7h7r9gwxPoOmeNuO3wsnjBphSyFNTM9lf+P11B0Dd4BZg\n        eItLgGiAeGEBaIBd5owyKsAsT4eqmsFeLOBExACA3eat8CqcP4BLCn8M4i/JgBxgsdv9JDkoLLKstqV3\n        /4F2h4MRXQG+9CMJd7+Y024wgRgDqlzVPW5vAHgIot4mMJ1SHaAMaGa6J0vDTPgW1zrBBHiMrgfotEV4\n        1oR4czCoQPSX/+vewaMKrBcPcJMA8HwkCd6c98Fn+fn64fKBtYMrmoYD1kGo9PKLOi/gvu4VBGAEmKD/\n        34Fv4R/ks+/M4+Pn3t0ydtZg0wU0ed6Ehcu5I9jQCRh17RNaxs7efvzs9kdAACePP/p0WUsHLID/qQOA\n        5O8KAgu4xxBZQAR3c/xvJMCU/EGKRMlvIfr7dxFAiEUKtkhBYoeAaIufmbFzc+MXQDPbPAjtb/p/TOMA\n        iJ/qYIMHwroo7qXnx7xEONYzbJ39PjOcYo1DynBKIs+HTiGQRyb7PXCnX6bZAGHtzBmF6AYTZLpoASS7\n        rZob/9Mdbq+F6l4lstvp5VdcqsXiqA+NiXW7fCwKKEFhDbBVsdv8rIoimkCwMlj2dYV44oPcDLq6pEEu\n        pUCVEnRuM1AgfFCQ+f6iBT9bK4s2cClAc5dfgEBb9vxxyhFOSWz8QpKAKk9h0if1fhbrh1k4li9GkigC\n        SOXO9exmGuZWYgzuOAYjINMtx7mZ5ZmIBQYeQIrQWQ8lysEkCHaAPhgCUj2Ksp0NnPEwMCxiDCb2MNnf\n        YBtRMA2bV+tyKB1HUp5byfHwFOBeZwUZ+IDgDqyP8sgpIAlCvAWSHMTmL+p1GVIG00D4A9zdlhiWAVsC\n        Rd4njkSBDJjpT0MEPwqh/ZldGo9lwstE9CeLMEzN1FIWBIiUfxoBilPsFuCvy7Im+ajScE15xK0867U8\n        4W9Z51GaDLmHqiSRgaRwTYL1M0CTVxm2kYY90umX4eMzZ9EdZ594ccuBw2v2Hdl7/vKlx54+cu78nWu3\n        LFpx7707Dy7fuXvm4lUDy1psGhv/Gf6epMyc2Xev23fu4Q1Hj9579NShU+c27Ng7d8XmJau3b924/8jB\n        h7bsPLRo+f33Hzqy/+TZhau2zFm2deP24ycvXnrprbc/+vjLDz774tU3337i2ec/uvr5Cy++uWLVARgf\n        D19++q33Pv7o06tXnnr2pdfe+PLr77bvPXbqwUsmmj/x8pvz7lwTFJKCB7A5tZpRY9/+7Asc/w+I4s//\n        fPzlt1Pn3O4JDMPZgsbGhx994t//oK3wn//8ef2Hn97+8L1XXn/91IOPXHn+2Tdef3/XkQu7T53du//Q\n        sVPnd+8+tmHNurvWrFx7/9Z7VmwYN2bG1MWL26Ytbh8xc/z0uYOHjyuuqClpbKloHdY0YUpd67jhHVOX\n        LFt/14YN4+bOmzxzTsfoGfVt4wcPG9fYNqWxaeyw4dObh08ZNW7W2MkLwqITbEBuoBJbFNACgMZnLFcD\n        rJuID/0uqr2YpoIjIv/HjOsKJwx9QYa70z4wQB4gBhoBOEuFzoZxeCuCBMIIoDPHzgYPwEcgsgm+1PWA\n        UUK8yPZxMqXHp5tvSGRsed3gzOweQFtZeO2JrcBf0dwNw3wrorhEfHyKS+z60nlW9JAQyr3zWvM45523\n        ouXBlZ3Z/QLNBYhjTddVWCCQnaMT3In+5sDdROcJLjYvFHxg0oyfRBfQoLrWyqbhQHn8HDqh32Nu/wIC\n        6FT9/+UA3etS3QHBET77H3h83NxlTaNntIyb0Th6ypDJc8fOv3PYlEVVrWMqB4+uGjy2cdT0bewGennN\n        4ZMnH3u2snWk3ceHRoCAftMIMFW/W3h+QAAiEQgyX2LKv4B+vIIGzEKwznRPKzkAb4H+OBIsWoHSAhCJ\n        QGGsASaOdw4h500+wBwDlgGshCSgPA5yPwBGd9McihkfhvBPYXsfKcepZJMYCO6sFbAC7pUsbu1rwUQ0\n        f+bZ7i6K8RwQABsHAfqVRLElJOghV/VL9Tphh9oMXfVC1Kus73W6he4QjeHwy7DzNyQ6CTAyzMoAG1u/\n        MT5stfniV2V3Ob2emGAdmtoQzX+KYXaoSrHYbCBK5S61UYB+UcQLTIcRECo2g4xyiv77UPdOIjuOMGAA\n        mawR8VNEtRdWhrvY4bKAvRm4vVc0npzhYjkTRKIz6TMP8C3SYxLcEps9iAuTRS4NkJduGUNOEyjvT587\n        jYNENn/mR5Me6I6Xg0RRWJIGW4Td6IJUJvAkutlSIolVYJYAw5LkVoD4wV6AsiWOHiElzcsKAFEEANS2\n        +LM7vwTUjnUztd9t+IEnwnRLmKr4q8wRijAk9pOgewd8QJQPFE09w3RrrGGFVSEKCDqjCKAB3ATfIgjo\n        T++/6BAnOkNYVNlHladpUP3KfE2e7FHG+luK/K0JbhaLYTGsHPwcknXLbN260LAN0K2gYYDmyClzjl54\n        bPmW3au37F6z9cjmPQ9s3XfsthX3TpizcPiMuSVNLQUD60rKG5Iy8oOjo5vaR2/ae3LfmQfX7z24fPPO\n        1Xv37D15+uDR88s37Fq4bPV9O/eeevDyxn37l2/avPP4mU0Hzq/YefjYgxdffvnVK088ffrK5RMXLx88\n        d+ng2Qv7jp8/c+mZcxevrL9v7/ELD3305dXHnnz+zLmLb3/w8bufffLESy++9sZ7P/78+wuvvD1h+iKb\n        NxzPabW78wsqth46+sffmTD68y+/fvXNdz/98ivmf/nHv+5avcGpu7EsLDxhzq0rnnn9vRs///zXv/7t\n        9z/+8sknn+Gr3b1pw2OPP3v0zOXth07u3rd/247d+44c2nv0zLLbV926dPHmHXvXb9gya+6iaYtuXXT/\n        6ulzlw4aWFs8qGLI2IllDYNLahsrm9sHlre0toyfNGvmXavvn7t4Vcf4iR2jpgwZPKaldVx96+TGYTMb\n        h04ZMWX6wqV3ZPcplBRF1Q3D7dV0j+kCMoHeSQ4A0LPLG7s7MHmRWC/0O7P7gbNAf14CnoAFwOoBA//0\n        xFCp/V301HeVcWkWineGbYngAliFc4kCXECz6UIhvII5cC0gtVs338jY5MqmoZk5+Sb+3tTvpBDhxsG8\n        81YOmhH4ODazY0MLBp9xRFwFDWjeXMB3l1oXEh7PY/qUOrmBx00CoMwnN4i3OIhBrO88a95BzDm6jnfd\n        BJ9g8/X1A7eVN7bftABYAOwJMPyDDX/2hCABmKOTALx4cpgFEXHJPgfOPTFu7p1A+ZZxjAG0T10AC6B9\n        6sLy1lEVLSMrWkbVj5iy5cip7Q89uvbwqZOPPVfVxhgAM0G7UoDMARrg265K4EAB93g15b85AdxHKFT6\n        IIAoIfmDRAQYb0NF6meYGKz1FVlAgH5zmzBT+2MizAK/JNHVB6DPrd4h+W101wDf2f5BpIRmig5oWcIg\n        SLcBytkSDuthB2Rizm3ClCyx5zuOpzlYM5WvWrKcbBcK6AQNYEKPkEPOcvgleV02t664XJ6gKLvh8cNf\n        hTBdIfYhIiSHzcfH18fCjV9EBwib4rBbXNxexJdGgGgQbbcFh4Sl+LvD1W4ggESnVOCSQDl9DXmQxv3W\n        gYmA9RhOCOKR7ATH7kAYOItTEOOQ3mkCtQH9QPN4TUoAoDMkICe76PHP0AH3IvHfBQvAQlePqoAAUgw5\n        361kQzWDUVQJ9w9XJZyN0IiAAHS2c9AhiuVYqmliN+R2nK54XUqEJqUI6A9jcieJJ1wj7qfreAbGbAG+\n        iYYcT58M4TjbsMACiBUGQQLsA68lxmMVr1T6kR42dMPzs5hL5JUCvkM0BTIcvOVhVwnRgsLDIAGwng2C\n        3KAH5vwEi0ZG4TpxP0wkBeHjcLazpADQr3KHAIC7ocqKU7Y45cmasl2zQODD6OluKEVepdjf1hO0JNre\n        sfpBt5QZ9lmGfYxh76tbQU74XY2aNP34Q4+v2Xngro2771i9ccXm3Rv2Hbz4yOPHTz+0ePn629dum7dq\n        y4hp82bdtmLd9sP7Tjx09Oyl3UfObtt/5N49++/ctHvl5p07d53Yv//shl37l2/dd9/BI7tOnzh66oF9\n        x07uOXbu9IVLTz35zKVLz+47+eDWo8fW7Ni5ZP39m4+ePHzx8q5DJ0+dfvDoAw+duvDw2+99+Pxrbz73\n        8lufX/vmgw8/f+jyY6t2bGkYOcHljcITBgSHtI4cfeTkhRs/Ee7//M+fv/3+F24e/PMvP/386+9ij7Bv\n        v/9h8d0b/MNTfS1OT2RMZFLmjHkLv7nxLU798vtvjzz2xPGzD15+7uWHLj3x8OVLW44d2bR7946du267\n        5/51G3c/+eJTW44cXrhw5eJb71m8/J5lGzaMGDepsKiooWNMw4hp5Q1DBlW2VDYMrakdUVM1ZHBbx/QZ\n        86ZMXjp7wbKJE2eOHjGzfcSYEdNnVgyZNGn+wnvuXb9o8ZKismYLC6mA7QxLdubtMN2TiO/S2UkNMMpM\n        UJfKBCGDRQA2+vqFwwfWgHilo1/09oH8MuEbcpzuIwp/SmyoftCAxaaajngTiAGOXejfBaYWSHJRK+Di\n        q5+f7OsnZfUurhncERIa4SdbZIV5nOIOzAe1CNcN7kAzQiQs4SEDgkK9gcEwX+jV4W0J9JwDmrsIQKQJ\n        wQwg/eAx2CUUjyESgUz5Lx6Gfp4u1Y8j4i3LCG4m/HSxBc8S93lncYm5wLebLwipsmVE7dDxBiuB8UNj\n        MzjdHfj/JgCxFQwIwKm53YGhCWnZIICnxs6+vaZjUvOYac1jprId9JJVI2cvqRoytqIVFsCYuuGTWQfQ\n        mQb6dHnLMDML6Cb6Q/UD92kKdDp/fAMVBn4h/03t7xG9oOkCYtoP0T9cpPqEWMzgsBn+NXP/GQQG0BPr\n        O4t+/aItUjLhm0fibX4plPzs5g8Jn2mH5JcjuTu8km5nk+ccB8EdBMC6MKC/Q8qAxheNQtNxEDIfHOBg\n        j4dsM+WflV9+3TVcwiTRdCHPsRKMgtvGOeQ8p1+cYZe9hgU2ptvrMDz+4ZHcO8pmZdsfO3ca6h0YFOx0\n        dpNYFSycP1bV399pGD6y5CdLMakpelxMuNuV7rVHaH5eVR7glOrFbly9dbkMytcpudnMWQoW+T9YEApl\n        KggAZkGEqiS6FChcr0ZFH03kpRcID5lOP4/cX7h9oOjDNSmTLRwswH0YBBhxKt3c3d1KjqGkiZz3WJcC\n        DkgUPYhgWwCLmUTEMIAFd451m2Lf7AEHMc4UIO7zxZitaXaw9Ne0GGg9iDwlUTJGd1AArtWYqwN1H49r\n        3Uqk1xLLNCFLmpf3BDHEeGAZsMrMAGoLEGdHCpFaGsq2EIwZYASKLtB4hmDBBEkMTtAciYS94rZwdzA2\n        EeKzgY1w51CdtoXXLetuNn0DAfi75EpdSRX9SuO5qYNS4JYGeCwFYvQSnS166NYRhm2W4Rhu2PobdjwJ\n        4HXsjDkXnnh6xdati+7fvGXn/gOHj2w9dmLz3mP3bd1/356j9+04tmHP4U0H9h85f+mxKy8dv/DIun0H\n        N+45tvXQgXXbdi5du2nxytWrNuzaffjMgdMXtuw9ctd92+7dc3zHwdPrtu1bvW3Xxp1HN+85tvvYmR0n\n        Hjx75vLR4ycX3r/mnu27H37y6WdefPHNd95/7LkXl67ZNOO2dau2HTp25uG9J08tWbWhaejI6IzUyKzM\n        ksahazft+/Tq1X//50+M//znT4j6H376GXDPbNG//PXnn3+98ePPv7E79L//+e8/dx+9FJneS7Y7Q4LC\n        vEFhlY0Nzz73xr///SdWf/DeJ48++eSjTz3x6ONPgeEeuHj5ysVnz55/5NCDp3ZsP3Dg8PFlq7fccvuq\n        zQcOTpu+oHv3rKETRg0eMn5QVUthZUlxaXVNbXvrkLENI4YPnzeztmV0RfWYlcu3zJt1++Tps8ZPnjJy\n        4qzqlva5ixYsuPvuTVsP3L18rS8ADxAo2nnS/yOS/U0mALhjYnb/J1gL4S8ogRBP6Fc1wj31Pl1DJuJz\n        AtwXnZxx1mZzWRTOcdbKZFCRAArg7lLuwiAgTOMtA7wYwiGDT8Srn5/k1Dw5fQb2HDAI/8T9JMA/vTqA\n        2q4ILUHcnIO0AoNDwyKi/IND7aoGIBagbIflAdLiMtBGl+mA4zZBNvhEEADgnkAvHkZwknltJ8QLeiDT\n        4C0rDMgBPCs+V/SeE5fgZ0lroysl1Ne3m82pVTaPbOiY4gkIYxaQyAFlGECEf+n86UJ/8y1I1x0QEp2Y\n        5nPw3FPjZt0O065h5OSm0VOGTV8wecnq0XPvqBk6tqJtdOXg0XUdJgFwS8hjl58ubW43YwB6l/D3Cu1v\n        en5MF1CQ4gv5D+gXnh/RC1q4ekItUqAgANH8h64ecyeAYBH+jewa4AAWcNn8zPafydz6kVHfGBEAEBv/\n        ykk2oL+cITo9xALcBaZnsLMb47c4ns7sICndzryXTDuvgvzPcZEYRMIoz8KwAB/kaawDwKkcSGZRh5Ut\n        8kHD7cy0gX0Qodu4IZbD4XD7K7AxoTs0DdDva7P6KIrNorUlxcQFunz8rKLhj93XatH9/YOiovysFp9u\n        3bIKByZmZaUbDiCX4vCLdUm9RRx4EIPP7OYPmyPMKcU7pUBzF3VVCoL0Fv39wWQZ4C2Qk3DIAI6Bv+Ei\n        gQcGAQMAom4ZVkKkS4pzcW9h8F8SeEKTAPGJQv5nuFnrC9SOFFfRkmDyj8JMHkhviG69c4uxKOFaAXDH\n        GcwKxStTg8QWAqZgj9aUSJW5oUB8s9YMBMC9yTQLRTooAYSBs4IkAOI0C2A9eFg1luhl0DiZBEA7IwpW\n        AoO9IADJH1DOJ6TPB9wQw8+lEQCLJNZQ8BXw/OAVsCA3shcBAOEsIjN5DAk2Qbhh9bBwjMlCYEpD4wYA\n        PqokiT4QAWJDGE1sZgDOwN1SxCMVapYxbttUr32o19bTsAUIF9DQidN2nr8EKF++bevuAw8cOHJh84ET\n        t63ZvHL91ns371++afdjTz3z5jtvbzlw+u77d+09d27HsfP7953edfDY6u377tq8665NO5dt23P77r0b\n        jx08dOjoxm27l6/fvmnH7o37D9+5efey+7ffvXnPxh37t+w7uuf4+UOnzq3ev2v5ll0nH7j42rtvvvrm\n        u+cvP7lq58E5t6/fyBLiS4fOPLDjxNHth49evPTUq+++/+2Pv/xJf/6f//jHP4H7X1z79tq3339348YP\n        P/34w08/ffPdD998/8OPP/3y6+9//PrbH/8BP/z558vvfDioqrGbr+QJCAkMjsxO73PHkvvf+/DLH3/4\n        5czZi0cOnXv68ssXL19+/Llnz1945PCxk5sO75p1y62nTp17+MkrTzz7Auye4qKKUSM6Js9f2tg2pby2\n        oapxcFldy6DKhsrG5qq2tqFTx3WMm93QPmHBwrlz5i8qr2sd3DFq6NgZI0aNmz57wYh5S+9ct+3ue++3\n        ayokrcY6AEZ9XSwDFnW8XVAO0MdbM/QKvKaJQBe/SO7EYIIQF2ClkP/c4NckDAI6BwDXJXwp1OkMKqjM\n        BCUum8DKCUCWZ4XpIOKx5AAnP8UOO8DP4XLn9RvUa0Cxput+rK4l2gpVDm0uOEMAMdDTPyDEGxgChOXB\n        TqAXzyAoh2zBcIWO78g8VHwirzVPidgvY8VMMRKintBvQrn5QRYbqIIEgNdOkuBFmGDBfxezlEwwBJ4c\n        P5bShvbyphGqEWB3aGY/ODPwK9L/WfbFI2KbMHGQ2UFBYdE+h84/NXbW0vK2MQ2jpjTBApi+YNKie4bP\n        uLWS6D+msnV03bDJW46c4p7Ah0UQeDD3AzC6XEBAfxEHJhkA+gPM3H8z9VNAfyC0v8j/AeJHWPyCheeH\n        Ph8R8jV3fhcVAIR+TPAK0CesE/25KVicSOkRvn5ivenxh/bPoPwnJUDR50BQc+OXzkRP6n2mDNGNkyl2\n        BgY3YFm2UwGgJ4gbMjFUlI+Z1kAvds5RUukgUnJdlmyVEYI0QSehLrvsclk0l+oNkezOblZZEjmgIhHI\n        0c1q81FkHxgENuC72CXGBvvAYsUlqoo5MEV1+/eNj4Gu76b4RjulEpc0UJUrXHI/YQT0A2Q7uUsljABw\n        QILosB/klEAVbnrh6R0CDaSKrNBsAa+i1JbWQAL9P2xdF87moFJPp8Rlol9QmiGnullqCymd5Fay3LiQ\n        WfNAfxgQsDMA1oBUf8I35TyuSsERnTtHRgOvcTmxmNVY7ABh0EQAA4WqbDUa4ZZgK8AEieAGlkqQy0Lj\n        gEW8TGYFB4AAYtxKDJgANoHKdtNJ/kT8dBEWZuDXw60iwS7B3CxeCfXQnxPpZpgXpgDoBI8d4pbD3bw2\n        3rCFGVYSkiaJ5B/yTZTbCk51G6wd84BvYBO4GS3wV1kWILJCFSd7goqtg1XZ6pAtDllSZYsmuzxWl6Ek\n        a5ZmjQQwJdBR6ME/Igm/rJaRE7ceeXjvkfOPP/3c5hNnlm0/uHPv2U37Tq7ZufOe+zZt33vq8edfPXL+\n        wszla27fsOvQuXPHz106eOjsmi2H79m0Z+X2A2t3Ht2wbdc9W3fcvXHrffdt27nj4KZte+7ff2T32fMb\n        Dx1fvW3/iu17V2zev3HH3vv3Hbz/0NEDp88eOX1h/8lzpy5eOXDsoYMQ4U+/cPnpF15/54OXX3/vwpVn\n        nn71ta+/+Y6o/+ef39+48ea7H772xrtXv/rqx19//eGnX7/FoRs//fGXv/zy229fC0Pgjz/++vPvv1//\n        8eevv/3hL39hBdnnX30xbcEtCak5sXEJ/gGhLiMUQn7viUcee+aVNcvvv3fltnffefeDjz/atHPH8pVr\n        9+89ceDYmRMPnHnm5ZcefPRK35K6W5cuf/apFxYsXjlpxqIRo8cNHFRfXjukqKq5sr6tvr6jvqlt4rzF\n        o2fMGzVtYsvIkR3j5raPmzlx1ryli5eMHDlpwi23zF92191rtub0KfTx6aZpbs0wVPYC8ojkH0I/Mztd\n        TKk0PfXEO/yPu4MR34GGIrmTGI3BXE9YAF2jE39N9zrg1SQAG8BXJcqDEm5q7U7dLaoEXKLtTyfa8kNB\n        Kph08/E1/IP7lVT17FuAO4ACzNuK7kBgGhKJuBxUBOODYl/cH7AOLCY0i8UM3mKB7nYbhoefZRYYMycV\n        K2kEiJWdzGF2iDNh3bQPiPWd7h3zEx30CHXJf9wBc5MezCH2BHaWNrQNqmmzO1l07dI8Av3p7eHeauwJ\n        wZJg0xTgQcOje4MYBAYBjJ6xpLxtbOPoqc3jpg+bfsvERSuGT19UNWRM1ZBxVa1ja2EBHDmz/eKjaw6f\n        PPHo0xWDR5oEQJ+PcPqbNV9Af3KASAAF6Av5TwLgpIsABAd0Qj8GJsz8Edu/xArVb3r8AfrEepgCovdn\n        rIV4jSOpAvrj2OVfgpBPt9H/k2SjqIfsZY2Yme/vuAn9skj4YTwgU7yFzM8Um0EmCqsilXsFc/9IEEB3\n        TQKSJjm4BugPVgD6422KzS/ccFkMw6qpTm+Q7FQVyHyR6gOUZ5Mfh91H8vWxWJkaxI3gecrPqnRuDozf\n        rt3mDg5JD/Skqn4Q2k7itV9fl18Pp98A0Y0glsVcLFcOdUlhKh8jUWOPz2AniwDo2xG+GmA6CCBZkzOE\n        yzsWdoCo6Q1zEYJzxK7ukOTRKiuE0yDz2bAT4t2SycGrsnQLQwJsBscPimF/CKb0RKiU8+apKPpzLLEe\n        S7rIuiGIG8zTD6ILnsmpoS4lFJ8iPh3aPEzEqAHiPCVKdqHBQRjMI6JCp5aPFZQD/otk3idd/Akeoe5F\n        M4lg3QKwxif2D7BneZg+BC3vBSHxJhavGOCJCBoElig+iS1Es0ZrtgjDGswu04wSG4bkZUSBgWh/lRaA\n        6gJZS06dnaKdGn9vTrGFvYvcoDgNi010GSpz28e4HRP91QKvy+LwAwEMGzv14cdePHb28pkHn1i5de/y\n        zYd2HTyx4/CZQxcvnX744omT53YcOX3P5h1rdx5++PEXH3jg0sZtB1fv2rFk47bl67av3LLvvt2HN+4+\n        eN+uvXev3zb7zjVYuf/oifX7DizbtHP97v0bjxy/e9v2dXsPnn/48tkHr8AIOPrA+XMPPXL0/CMnHnx4\n        z+Gzh09fuPTEU0+88OK7H3z65rsfX3rqxedeevWtt9957Y13XnzzrTfefe+dDz9+872P3vnwk8+++OrL\n        r7/jrsA//vgDx08//fzzr78S+r/65pvvv7v+3fUbH31+9YZoI4H/Hnr0if6FDcHhcRHx8UZgaEJK/tTF\n        i/ccPXzP+l23r964dv2OjXsPb923f+/2I+cefPSlN15bd/+m7B595ixZcvj0yT17ds6ff+vEqQsW3Lms\n        ZdTYfgMq+hVWlNcPHVhd33dgxahRk1auvX/k1HkllW0N7eMmz1p49x133rXkjrm33jVz2V1rN+145PLL\n        raNmUgm5IE512AFAR9GspjMYQKwXDXyAm9DjjJRyOy3MaRMAKEkAnaaASPM3e/5QVvMIYRcCHOOmACdP\n        iJKuTqe8aSIwY4eVAea1AoIFKAuUh+5WINe6eYPCi8rre/YrdGoqfUFWOv0FYZhwzDkXdwV7xQN0peiA\n        JASd4NWJL2sSABfQJiADUbkLr44J9J2YTljHKwFdxB5MZKf/p/P+ZgM4cxl5onOB2GnS15cxgNLGoSW1\n        Q2DE4INELN3NrcHYCY511+KtWQWGV4/hDfQPjggIifQ5eO7JsbPurBo6QRDAjA4QwOJ7Rs68raZ9XPXQ\n        8TVDxtePmLrZrAPgjmDPVDQzBqB26yQAE/fp9wcNiCOYAPS9IuprvnYm/yhSkOjiiQHcD7Uw358EgDlx\n        n8jexQGM8ULyM6NfkEGKDUDPAEAqj8uwCZJZEAC4V4D+AH2m/TjYBILgzpVyFvM7wQpSLjN5RLI/aYNO\n        oTQHPTysGea1DBJkueQs1SwiExfSC8TysUh2FvIL0R2KoVnwp+kNtmsGdIPMNFArs80dNovdXhkaGWoY\n        PlYnjACLE4aCv0V1Mg7scio28IGv7u/NCPDP1Pygl70uOcEllbukKpUJiBDIANAgl2Q4qfo9Lj+85guf\n        T7iT6J8IyQ8C0JiUGcNkGKZyxutM2Gc8ltkscoIuwTJIE3uHMSZMmS8BzVMNJcuQCw1lIHv9S5m6ghFO\n        B5EoGhAJo7gwSSOvJAm8hnIPEaHXGEh+Ol5wZxkLSDkaGSiREWaif4TIImUdGT1XbGENhgAc+xvcSCCM\n        jYNYohUqIr1BGvhMCXAx+zPZoyR7lVivEue1JHtkTCINOcdt6e6xxnuUcNoHTAECOke4rSLka9Z80QoJ\n        hMWgW0N1W6hmDdKtXp0uIHyQv2716NYAwxbstgUxY0vRNUVT8Wpx6xYSAH4bLtmFt6rFq1lduuJxW8O8\n        1pQAe5G/ozlAKwhwKxZfgNT4mQvPPvb82i0H7rx3z53rtq3fdnjFpu27jp1966Orjz730tL77r9n7a7j\n        Zx87ce6JE2cf2rnv2Mp79y7buHPlzp3rt+3dsPPo2h0H79p2YPmOffds2Hv31u0bDu7bd+zkvdt3L75r\n        7X3c0eXctv1Hjpw4+9hTLzz40FN7j5zad+jYgVNnD59/+OT5Cw9ceOTCxcfPPvjIhUcev/T0Sw8/8TyW\n        vfHGO2+8/d6TL7x4+dkX3v7gk+s3fv76+x8+/PjzDz/7/Jvvrn/73fdfXbv2+Zdff3L1i2uYf3v9/c++\n        /PzLaz/e+PnGjz+BFa5+/c0Hn37+2++/gwOeeuq1ktIad0hIVn7v6NhEV1Boy7RZi9bcP6C0qn+/8vUb\n        t1167vHzVx49cfrM1Hm3dC8oX7ny/udeePX0o5fuuXftqPGTx865Y+Ts2Q1DRwys57YwxTXNA+paK+qH\n        N9W2DB8+qqlpTE1jR8OoaSOmTx43deaYOUunzr975Oi596za/PiLb0yYOQ8/WycwVdWZ+sO0To/pCKKL\n        n8FVl4ORAG4DQP8MkJpYD8lPC8BuZnwKfKcGd8BiYJ4PND6xXihxEAOoBfcUp0wnksgEBcSbBGA3IwQE\n        9M6mEQL6b0IwxLgsKz7d/ALDowdVN+X3HmCDTS/UN5Q5gZg2ikgxIiib3idBD8JpYzKNeSvxVMJYoYML\n        8p84zo8QYh8TcS0GAd0kEtMUMEeXwAet8ELhsGLoGEtx0DwL6Dcn3H7QqVU0d5Q3tgP0OwlADLwVLiAP\n        J2IOAqBx4h8cEBYdEBzmc/Dsk5MXrADKN4+d0TZxzvCZi2ABjJh+WzUsgLZx3BFs5NQtR07vuHh5zaGT\n        IICSuhawpCYIwOz/A/SHEQAmAPQL9OcQe0N2EgAjvQwCCwugy9UTAWAVjT/DLVIA+YCunigSgOj7xt2A\n        if5xggAwZ8anCAIni7exAsEB/QwFOyj/YRZkUNcrII841gmLgAHjBHI67ACNHIA5eEL0BaLAzxCbwnND\n        GCI+rAEGANJccjLTgXjPWLsSjcdz2YEiikt1eQIdupuq3+m0OJw+FtkHNGBz9AkLDtKcmPtISjcZgt/g\n        ZmE2wRNWmx4Gsg3K8jcyVF9gbqoTnCQ1u+RhutJbZwo/DiYIOA5y+oU6/EKcfiGsB1Z4nD4WlkdFCd99\n        jOjbEyEyWFI09mPASGdBLyeJmpSgy7mG0huDQC8lGVIvQ8kzLOk6Oy1jDVgEOh1YDy4BdpMMhFMolRDM\n        1B0eF63Z2IqH+TmMFsQAhUXVGD4II1a0eTBjBrGin4+HtcFMMw0RrvkAnT3dRKcHZm0KGrDE6XQTgS3Y\n        FsLLZKFI0QUogX4hJcmLNfQaxXmUxABbuMcKAjDRP86wggDYDA5MQPS3ggOA7IGaNVizeAHlutUffKBZ\n        /XWL120LNGweFb8xq6bbNM0eYFhB37quaE7u5GaoFo8GlrKFGPZQFjPL0V5rVqArw19TlG4AqVvvXL7n\n        3ONL1+3deugBaPb1m/au3Xxw/6mLpx9+fPneg8t3bD9y7MGDpy9tO3j23o0Hl6/csvTeXYvuP7x2y8Gt\n        u45s3XPgzmU7Zt+58Y4tu+7bfWzb4SPbjp/Yc+zk9v3H19+/7/6dR7YdPbvj2ANHHrh47tGnjpy9dOKB\n        iw+cfXjXkTPHTp89e/7SAw9dOXfhyvmHHn3kiRePX3hs66HjD1y69MLzrz734uuvvP32My+++uJr737+\n        +RdXv/zis6tfff3d9R9+/vntd957650Pbvzyyw83APe/fH/jp2+/Yxj4xi+/Xr9x44+//PWXX//48JPP\n        Lz///EeiVuCjjz8fVNus2J3pPXql9uodl5ySnNu9b1nlmPGTRnRMmjB77u7jx6fesmBgecWunUcfeuDJ\n        +YuWgY2ee/6Vu1esq2kZM2Pe/LKKpv6DGpo7JtQ3tTU0j5m9YEVTe1t5dXVNfXvTkAmTZi2Zs2Tp1CXL\n        R86+dfbc5XPn33bL0hU7dp+ZPm+RRXXJ0N6sAyDuE/11gzRgQLQSpgnZmkHlLqBTAB+Leyn5RexX7IAI\n        0MfgeoKvgHUTlKG4vf6Bbm8AqALLgP4iioC7iZhwpwFBxxEmWI81YtBEEGhr4rIdqOrj4xsZm1TVMCQ9\n        Jx9vwQE4jufBk/Ba8UqrhY9k3oR3uOnCgsbvskj4bKQxuozIXkLI4250K5mPjfUizECfvtzp5/mvh4ck\n        JyIZmNN3RG4gMYiz/4cAqlpGlDePUHV//ABvEoBpB3RxAO0AHMSTa+4Ab1CYJyDI58C5J6cuXNk4ekbL\n        +Jltk+aMmL140q33dEy/rap1TMVgBoHrR04xCWD1oRPHHn2quKoRFoDRrXNHMNMIwAANCNc/0R+vgH6x\n        EyS3Ag4wm30KAggT+B4lcn4YGxBNIGAHhFmY4in6NrPns0j4IegD6wn3AtPNtymCA6DxIfaB5gmiPwQG\n        LAN6bBz0FGFZhA0WhqgftkmZIuEnhb2ASAlmZ1AzaJwpgqhZLinHZWGowEn0p/cfxoHYtwtPEqjZFRCA\n        yuoPqxMy0smUf6crxx0SqWq+DouPiAZ7NaOPf5jDKvvIMgwF6Cxf2dJNkXuXVybGxfZx+eFTUnlzqdQp\n        tbnkeqhvHHFIkPxmOg0kf4STeBrrouES4WK6DhQ9sDVA4+YtUazYYqc2MEG8KOKNNBRYA2ma3N3Nvs2p\n        htTDUHK4eS+bu6W65Ww3kF0CpkeLrYbBKGkgAE2C5AdbRIrPytBIAOluJd8Af0jxbAEkx7gk4HUkw85E\n        3hDh/wE9QMJHuAn0jCfrDMBGu3FQChcbxLOXAzNzJDAEAJ0XiiY/YAXYEzjiL8qS8UXCBd/gIL5CuNsS\n        DYOAW07SfRTjb2UTUA++rw2SHwI/gDsHWISHxxYBAtCsHmEBAPfNoWtWTQUBwCaA/LfiV+bBP0/N6gBD\n        aCAAqxtr2EnMgom41q7rVsNtGRTiTg1UQ7z2WI9DsdECWHjPmnPPv711/4mth49v33f8yImHth06vePA\n        mR1Hzm8/+sAjV55+8d0Pjj348Or1W+9YvuO21Tvv3LLj7t2HVm49sH7zvnt37Fm8aufkpauXb9684+ip\n        uzfuWbhm3a6Dpw6deOT+nYd3Hrlw9srzB85e2nbo2NGT50+dv/jgI489cP7RgycuPPjQlYcff/rik89d\n        efLZRx9/5vyjz567/MzFp5+58vwLz7342pvvfPjVV999+tnVF19/86VXXn/n3fff/ejjT69+8cVXX3/x\n        1bXrP/54Heh/4+e//f0fv/z62xdffP3VtW+v3/jxx59//fGnX/8Quf9fXPsWpgD4ABzwyusf5hdV28Ii\n        knJy8vP7xsanpXbvWT9kxKwFd82Yd1tlZcOUGQufuHJlw5Zt85evXbd190PnHn3w7LlVa9YV1bQPnzBt\n        1tzbC0rqBpa3lpU31rcMHjl2Wm378KKW1pq2sYPHTZl/1/L20dMWL11x74atq9dunn3HsqmL7tiy/dSq\n        lVtjk9N8fP0cbO9jaIB+9nn2sGkle4VCjAMHodCZ0U+/PxCWmaCm3CawQnQLIS+8LgB04VQhvptbugNn\n        YT4YblX3EFUFXjO8jJvglFkUxpt0Rg5w1gRWQQDkAHOIm5Mb/GQlMS2rom5wXFKqpABmu5Q4m1LQ/hCw\n        LrpBCDeOOcEaHDQNFFzCNWQdprTySYQXiFCO9cJuuHl5p9OfTECNb/KEudJ8NSd4kM7jfOWOYIoCAvB1\n        uPTq1lEVIADD39aVBWQSQKfrXxR/qYwHGFgMAnB7g3XDSxfQ1MUr60cyANA2cdbI2YunLF0zctaS6qFj\n        zVqwmo5JW46c2vnw5VUggEtPFlXWwwL4XwIwAwCmBQD0Z0ooyYAxAH9BAAB60oAsBYqMT2j8KFYAdJ0S\n        8t8U/iY3AO6B2hD+1P7iCHNDSQPs+5YCfLfDMmCmpkB8qvVUeoTYLIhnbUq8XY6xy1F2BUyQaJfS6OhX\n        cFW83S/eStMhXVWAxSk27soLyyBLbAlAPhAcAHqIx52dco5KX1OY7lTcBnDf7vGXrA4/m+JjtfrYLHvS\n        0psC/X38ukFY+sjdsnXva72yot2wA2QLpIeuMSbssLq8Rnho2CB/V5rDV/TwkRqc0hBVHsBqXjnaJQWp\n        JABgLtA5Xjhkemhs+BzK9FAm9Ue4ZLfKEC74ABAJfM8ANItyMFgGEbqUr8tFoqVzplvu6VYg0mN0Bmmh\n        tcEWvdwMNecY3BIgmfuhszA4VrSOSNOkRFYAKPEGKEHK0mWR9U9HjWg2JzxUQvvjc+NEiVmwykR+4HKk\n        6CMUa/IBtTm3B4h1M4QL2Q6ITyDiKx6Rqs8MIjf3BA4XbaiDHFKwJgoORMcIgDt4IkVsPAmmgSUR67Ym\n        em1JZAKL2C7Y5u+2hrttYW5bgNsSwCCwUPo6hgXoj+FVbcEQ9YYtQLcH6g7YB26Xxatagg0bDgapNizA\n        wTDDHuV2BGt4a+kR4r8uO2VwdCDslSi3Hfzh8vGpHjJk45mHdx1/YNWmPQdOPPzQUy/tfuDy0YcvnX7k\n        qS0Hji27b8eqvUd2nTi7YtPuRWt2rdt3/MDJC5vPnF99/Mz9e47uOHbqwMXLO08/tOfYqR3Hzi/ffnjZ\n        hl3bD5w5de7yyXMXTz30xOnLj+06emL33lO7joEVzp194LFDpy4cPnP5wsPPPvLk8088+9KFK5dPXnr0\n        0lPPvPTSqy++/vZzr7zxyttvfv7lV19e++6ra9+8+ua7r7753tUvr139Cuj/1Y3rP934+dcvv/76uVde\n        f/yFVz69+uXnn3/56ptvf/zp59evf//J51+++f57r7/z3nsff/rp1asffPjxW29/+MHHn/3y8y/vfXr1\n        ro07i8qa4pK7Z+T2TUrLjk/OaOsYveTe9XPmzB/cMHrypHl7jhzdc+b83v2n9u4+dOHygwfOnB4xZWFB\n        9bClazc3dIwsLmktrWkvqW6ub2gbVNU0oGZYXevEoaOmTrnl1tFT5k6cuXDavDtuu3vF6nt3LFy+Yc2G\n        XRs37ureoxD8CujXdF0VtWCAJ4dTF0AMCBawaLrpuS07g8AC34HgQF6Vjnv6WwCpTPZ3sm6AJcTkCYHs\n        hFfKauh9kXgDq0K8NbEesI5X8yYCdsEfZtIRPotYbKJ/1ylVUcgB6dk9Smuaw6OiJZCAtZM/iPt8xdCx\n        3gRoXijuQALgY3cKfN4TBObs3LgYn9iVxGnaAZ3oj2vNSZfBQarDGvGW5V44xLed6I+VJABzQbduIACj\n        qnUkC8F0fzzA/ycBkAMMr9NFv5B/cLjuCYBNQAKYuXRNw6hpTWOmtU6aNXLWrdPuWD92zh217eOrh4wr\n        Hzyqun3C5qOndj7yGCyA4488UVBRZxJAVxkw4R7ob8p/vOKt6QUS/h/KfLMKDHAfLDpAQO9HWiTMYRmA\n        EvCWlQG0ANjwOV74fDAg+RkwEDvFwz5gdpCFMQAgcozNL9rONeAJKPo0IerjmdkppzssCXTdEL5ZzMVo\n        gYgNgCfEBmFQ9MliN116jcTZTLucr1lyVZoUwi/E9TE2BZd017gmCALC44XkdwSFWzRDsVu62Z0+dtuS\n        1MjiII9s0apiI2ELFrjDt6ZGqTZLN4vTR/Lz8ekGzvDFYotvWEhEgb+Wa/eB/E9ySOVOqUWVS3W5zJB6\n        6czoB5gCfJOhoFkYTPc9RD3A118UScWK/Jx0wRAA90ycZds4KUcUAycy0ZNlXADQfLF9Y4KozAJkp+Ce\n        YgdHIC/oIQiqnNsOS6mwJ1TJX2WKTqJbjvPQpZME2hAZRJFugDUrhxPEvonC1WOJEXmf4Ax2rXBB7EP1\n        W8xd5oO527sVEC/6gCqwUUygB/1EQL+LbV4A95H0DnHjMCwDwUS6uKF8sIgWYD0GCCOTH8297ENc1hiP\n        NTXAmhRgi/faYjz2ILc10G2NdFsjPPZwL0DcFkKlb4P896qYWMM0W6Bq81dtQZjoViB+kGoPVh0Bmi0A\n        VoLLojtALdYkrzPGbfdqeBJXQVhgTZi3f7AeEuAIMmwhmi0aVoLucodHhkYnREQlxiSkZeb3GtYxbnD7\n        4MLy0uCQiPTu+TXtHYlZ+fn9B42ZsbBj0rS65o7SlmElLaMGt0+ctPCWRSvX3LVu+/L7dt66Zus9W4/u\n        PX5p9+GHj52+9OxLb7zy1vtPvfr6lVffevGdz55+5b3zjzz96BMvXHn+1fOXnz5z4dJDjz3+6NPPn3zo\n        4UMXHn70uRefeebFZ19+4+0PPn7x9bdefuudtz/88I13P3zymRdffO31H3765W9///v3P1x/9e33X371\n        TZgDL7/+7jMvv/n+x2CKb77+5js6gn64ARPh3Y8+euOdd199573X3nn37bff/+CjTz797PMPP7kKhvjs\n        6tfnrjw/dfGtuYOqE7P7JKWm5/ToXlhW2t4+cXDHuN79y8fPXPTyGx9eevjJDVs3X3jswdUbd65cdt/k\n        WYt6VzcWNbUMrB1aXjtsYHVzYUlNZe2wurbRNQ3DBuN11JQFi5YvXrmqYfjkZcvu3bLz8IoNO1fcee+h\n        I6d7FpaDAAyPG0KdcligocB3U4nTEyIIQCAyENzOIDAWsEuEAHFCPxBf0+yq6VunX4XNgkgP9M/whuag\n        nwd2gLjKXAnNLmgAZAMc52sn/grcBwPxrRPILoCbRoOfxCa+ub0HlFQ1BIWEAWrF04oMVMp5M4pAv7/A\n        dNAAIdu0UQT3uExAx0HwEB6PX5MbDzDjCAe7FovIsGARMz6Mq/AksAzMNWAeHjQJ4Ob2A+ZKMXx9Jdy8\n        ormjrLED4C4IoLMdNDeEof+HdWHCCPCANb2BYQEhEWY8wGf/2Sdm3XFv67gFLRNmt06aPWLm4im3rx4z\n        +/a69onVQ8eVN4+qAgEcPrH94cfWMA30yeLKem4KLwjANAIMwQGmHQDcx8R8dZu1YF17QAaz5otpoOAA\n        5v6DCczub8L/QyNAeHhAAHFMA2UCKAgA2j9cWAYAbpgC9O/bcUp0hmA2J709rAxgSqgiMB18wCwg+nCE\n        fWDSQ5w4lQyjwS5luBQcB77DFEhiCbHSXWz/myzQP5E1B6wJgIkAnsh2+oWoTqvuVlxOF7uB6orDLtvt\n        smrzsVtlp9Pm0oPdGgzWQLfTx2L1kR2+stUb5vWEBvoqVj/8yg01PjAwW7XFOH1jHX49HH6NLqlBkzvc\n        8hCP1MfN3Xch6vO4NRj3BkgQOT9A+Z4GXT3CY0N/Cx4pS2XHZgjzLOHAwcFk8gcDvDnC9Z9tsPQXJAEO\n        SDPoFEo094Ex2EsnXJTyJmh0GWVoSrQmQa2HuyVgLlAbEB/B4gBKe7BCOm5C84LyH2gOSwLwjVNghUiX\n        FMzcJGsom++THuJ09m+IZNwYUpo5oBGCA3AJjINg2AS0VyQzKSgJdOW1gE7CXKwCAwdEukEwMAIssR5r\n        mr81FuDusgSqlnCPLTrAFuO1hXmA+9ZgEIBBMgiho597zQPrifi0BuwezWo4rQEu4D7Q3x6sOYJhN6gW\n        vtVw3BrgtILLuYsAPlS1Bqs2Q1WsdjlUt0X42wNgOjhtIR6HYbOyHMDHhxwuhtPHx+Ljg4N4dUg+QQEB\n        iuQXZOiVAwb0z+8VFBiUlZ5J55GPj6+fn2SxGgEBRmBgUERkdEJmdl6/3n0HFpXWtA4bPm7K7PlLVt+z\n        cceKnXu27T+z7/SDpx658tQzrz//5tsvv/PeK2+8/8Ib77332ScffvIZkP/1t9///Muvr33//SdXv3zp\n        9bffeufd9z4Amr/59nsfXPv2BoT/p19/9fSrr739zoc3fvjphxs/Xfvu+6+//f77H3788cdfvv3hx2+u\n        //jHX//yl7/+/fc//vLb73/5/fe//vG3v/39n2wace3b648/+/ILb7x17fr317799t6DZ0qHDC8or2vo\n        GN2/pDQ9rXe/AaU1Da1FxRUF5VXrNm57/PknYKts3rx/6V2rq+rrB7e23nLL7SW1LYUD60vL6ktqm1qG\n        jh42amzrqJlVjcMHDR7ZPnLKjHmLFi5duXDhPdOW3Ln1+PF5S1fdt3N3/8oq/IgcTP/nHuv0yQjfCwSy\n        RTS6AZYROoVyF1Buym1SBdAcGCdcOgB0l13DhIUCwk2EAS0vbgjY5eWEYFoV1PJOscAkG3KDeWdgN3v7\n        mJ9InU7/Et8KPhBuGU58JQkP3G9gRXF5rTcgyI8NoennER2qGQMwc4pwoQn0UOi8A74Rvxp7xROyoehx\n        EPRAEGc9nEkGpj+HrCDAnXObSPuh79KFxbwnPf78yQi9/z8cgKuEvwjrZVnGI5U1tJc1DQPi4ydm+vo7\n        LQDuv2+Gf/0h/z0BoeExie6AEFX3ig1hzj42a8n6IRMWtk2e3zZp7oiZCycuXj5y1pK69kk1Q8dVto6p\n        6Zi06dCJHSCAQyePX3pyUG2zGQMQ8v9mK9BOAsCrSQAYIACRDMoB6GffN5kef8j/IAp/URPQRQAAelgA\n        QHOgv3AEkQCg+iNtihkAAAGYHGDaCsBxmgg27vaFidkpOoWBASnFwRqxBBu9QAD6eDaKYEwYBABKAB/g\n        rPDFkwDADdz7xc6Bs6l2JZZ3YMyAYQMmBflGqA5FNRSXQ/UEKU5dEht++dmt1UHRSbrbxyb5KFYfP1l1\n        6dVhMW63xcfXNyk3PiwxAgfxR+bw908MC8p1SckOv1Cn1Msh1Tqlak0u0eRBujJAl/pqBPREJuQwKzRX\n        48bl0PX93HKewe1cwA3A4h6a3Itbw1PFA5Qh1ek4UtmHJ0+X6foXgQHmieqs+80A7puynfwhMV+oM5jM\n        sth4nenzoApANnAZ+J7qZseIGJbX0h8FmsGHxgnHfZSo8IpjWZkoFmM8gG6rQJE1hEel20dXQFdmfBhv\n        I0SjNyH5LQE0ApgIhAWpbiVRxH4j3ArTn1hmIQcYliBBAGCCLI8t3d8WBdDXreGalRmfHlucxxbutoe6\n        HQL6rf6GxV8n7ocY9kDdHqTZgw27P4vR7CG6M8BpD3QB/R0EfVUJ03HWFqzZQzRHoO7wChMBF4I53E5L\n        gGoL9TjCPA6P0xpsOEI9Lq/T6XU4AnSHhwFkZ5ihB2uqv66q3FGKrQeAYooi20WFh183H01VNQ2sYbco\n        1m4+3Xy7dQOKkA3+f/7r5uun2LwhEREJydnZ+cWDqkaMn7ZkxdqNOw6fvPD4U2+988W313/9y99+++tf\n        b/z662dffPXqm+99fvXLn3/5+cbPP3/73Q+ffv716+988Owrr7/w8hvvvv/JF6CJH2588/334IBvv79+\n        7bvvrn13/Zvvf/jm++vfXf/hB5ELdP36DZz66tq1jz/Bna79/vtffvz5l8+++PKLL7765rsfnnz5pQkL\n        Flc2Dp16y4phY+fmdh/Qp39RdU1DWm5mSUn5bfOWHTj2wMUHL67bvn/1/RsnTp3Q2jKitm54/8qmqtrB\n        dQ2tda1DKmpaGjrG1LaNrBo8smrYmPaOCXMX3jn2lgVj5t4yY87yCWMm3r7yzqaOKbJkB0GKSi7Vwiwa\n        6lxCMLMzTdDsBHFTIwPnbHb83LkRmHC5AMrpezGhvzPZXwSQ6fAROA4oFFAOVCWykxX4QVhGSY6zVPHC\n        MjCX8aP56XQBEU+7xDjOmjlCvr4y4LKwrLawtCYgKARymyBOq0JsQSwsD34o0BlgDdgGvpNvoN/pvRF4\n        bUr4Tg7A1YIhhMA38d0MA4g1/MqC9oT1IEwEQQ+dZ02q6LIJ+EMDAeAWdmdpw9DKllGqhj9eQQBiAPd1\n        T6DBHeHp8MHbyNikqPhkt3+w5vZnEHj/2SszblvbMn7e0CkL2qcuGDFr8cRF94yadXtDx5S6YROrh4yr\n        GTbx/oPHdz7MLKCjjzxR0jjkJgEA+in/gf5dFQA30b+LD5gLFCgG7QDZL0T4fEyDAJOgroIAyH9gNNAc\n        EC+GXyQHiwMSRQIoDppVY4IqmCcKCwBno8SFCaIxXDIVvcJdARysCYgXtb5AeZKBFUfYPxmWQQaLyNgZ\n        FGQAiMdisojwIHGxGKwuFqUA2Xa/SN1m9fcqsDoD/G2aB+LFx2H3sTqf7JkxJtofqi9EZQ5olhrwclZC\n        rKH4yHJ4lD9+ET5+fk7DCEuJjzVc+QwASFFOqcAhDXRIgPICUQ/cnZ8ixTpZ/5WqKYk6JTyYAJNkt9LP\n        zV3Lgd2pdATR557iYg5PiJtJPjkuCVSR7ab8T3Mr6fT5SAD3XGh/YT3E6jAvyAGA7ESxA7A/ND67D0lR\n        ouAL5kWmQWQHrMNQSDHkZDftgyjuO0Yu6c48HDlQtHZI16QEN/sFwQ4IUdmlTqQMUfjHiHgD0J+DLnsr\n        BtR6FOZ08VsB8QFYqUP4W0PZyp8ZPv5gC90SrSoeFWukEBoi1iSPNc5ri/Baozy4g9XfqQRoljCvPcxw\n        RED7eyzhsAM8RPAwjzPS6wo0bP506NuCdWeg7vS4HPgXgEmAZve6bB6XDQwR5nYB+v0B6JrDo+ImWIlT\n        VpKH7vRX7aH+LsB9sG6PDtRCvapHdXqcdo/TBtuPBjf+JUuKJMvQ9926+UH+SbLi6+vnSx8BzXX8U6df\n        GxBjtQPbu/lAOEp+vhLWSH58BeJDO3brxiwj8z+//5nf/M/XVzHcISk5PQePnDhv2T2b9h957d0Pvvj+\n        xifXvvvxl98g3v/693+8+9FnZx589IVXXgOOv/fBpx9+/Pl3QPeffv7hp5/x+utvf/z08y/ggKtff/v+\n        R1ff++TT9z/55P2PP3rvo4/eeu+DV996+4knn3v9zXd/+fWPb6/feOOdd19+/Y1PP//y2+9/fPCxx6Yt\n        vLVtwqxla7et3LC1aejofO792NGvX3nPjD5zps8+evLo8bMXjp8+t2nP/sKqpr59S0oH1RRX101avGTC\n        LUvqmtuHDR81ePTkYWPmTF20bNi4GVPnzFuw7I5lKzc01E6ZN3Xe7j2bb797Db4dTCo7sZu1VALK8QpQ\n        dtjMjXlF5NbhpFMIAhnQBoAj9FPpE8EdTsYwmVVJFjFh3SEGHTKddNKF3QLWOyeidACvggZIAMBo5uQI\n        7zqvMnEcis3EXDEwYVVXNz8/3RvQr7i8pLoxLDIG7E2cF3FdEAAYCxSFu/FpWbqFj+NNBFILCd+J1yQb\n        HMSyTug3J/8Fd+Hc55x3J0mIW3UqfcI9X8UGxJjgI0gk+O6CtGxFlY01rWOg6x1ODZJfbLrp1Y0A3RPk\n        CWC8F18wICQiMjbZPzgM2l/3BuK4z4FzV2YsWds4etbQSfM7pi8cPf/2qXesHTPnzsbhUxuGT64ZMr6m\n        fcLGA8e5J/DhkycuP1PW0gGLWOwI9l/5HyA4wNPVCgIEYEYCzExQDA87gzIpSDiCOi0ACH9wgNkcgg4f\n        0eEZgB5t9YtjUyDu/B5nNoW2+cXYO6kimqYA68KA2lgfJiyABLsf4B7yPwlGgCAAkAHMAsj/DOHqga0A\n        GjDhPtlBd5AI+UpsAiGKyLAmXkA/XUYO7iiQwLCBnGWTIjWH7DEsquoMDlZEyaIvCMBinRQbUhzmtlic\n        rVGhLs2W7DbmpQGaXH5WaEjVrjl98ffgcnhiY7IDAwY4/TKEH7/EJTU4pN4Ov57gANEKItklhzi57Tvk\n        f19dyRVx4BhVyoRloNOrI3r1MDEUoxImgptu+lxd6acrg9xKkXCdx3ko5EEDuQb7/CSJGECW8OQA96NZ\n        T0BvfoSqAHCh7jM0BdAPdkl3k0XS8EEsLqNHPl5UIeAZItVOIc9+O8JNHyty/yH2zVAwqCXRbWH3Hjwk\n        KwOsMYYt2rBGu22Rms3fZQlgDFkJ95AJQDmhYmd5Zn8ypYe7vsS4rcFu0hKkejCIxMPyrjDDGoJXN0gC\n        62EEUMKHakwAjfDao7zOMLcz0mMP87cHuu1BhgNY79GdQV63v+40XHaP5vJXXf6U7YT1IDfW60B//E4M\n        J0S96q853C6bAW4wNI+Kud0LetAdYf6uiABXpL87LMCtOaywrAHcQGUB977Q9phgAKklSe6GU918ge+y\n        rPgB7mXJz88P/y7xrxEKH3P80yf0czHO06sEOrAoNkx0t9vjcavANRmr8Fei+IkPwKn/85+vEhgaObCq\n        du7tt+87eea19z+//ivTePDfH3/87a9/+euvv/0KXf/Nd99/f/0HiP1r3+Llx59//f2b6+wJce27GzAF\n        rn79zWeff3n1i6+ufn3ty2++/erbb979+NO3P/jsvU8+f+mNd5954c0rTz//9IsvPfni63uPn5u/ZM2s\n        OXcsWbXpvgMHy5qbMvN6llY21g8dXti/tGP4xFMXzj//4ssHjp2pHjZu1Pg5I0dOKiytXrB87ehp81tG\n        j5k8Y37TsPEVdcNaJ8yeNOuW0ZNmTJs19867Vs5bfPeSFWu2btu9be/+qPhEfC1uBgnod7qcLu4GLKS9\n        0yEGJsR6oaxFKQBTfYCGoAe6+3mVaQSYXh3mdwLcicJ0xdAUIOILe4KDJoVwDQnJT20ugsnmXFgA+I0B\n        bhlwdoJXzHY9ggMIuAKCzaZAPt26uXR336LSyoYh0bEJ+LXjnmxfQS8Q6QeGiIB1Ir5AZLIXwb0zn4fE\n        IL4XGQULxHH6iLBSMIG5jA+DT+dXFjveCErjI5m3woX4e+PWNebjiaRY/AHhT6vfwKrq1tGq4WWSj9kO\n        miNQtIQLxLcDN0TFpQSGRKqiLxAsA0EAsACWrq0bPn3wuDnDp98ybsGdM+5cP2b2nXXtk+qH0wtU3T6B\n        +2BcfHTdkZMnH3uueuhoVxcBiD4QnRYAXgUBAOuZDoRXtyyZbeBEEJgZQQz5MiNIpACxCICADlg3vUB4\n        C5kPWAfcx1vZ+Yeen66MIMwZGBBMYDYFEm/JAeISCfjOLCAR140TaA6xny76+3c2ERJxYzMgDBpIFz6f\n        bBc34cIloIoYcRXJwKlwoxXBCikkALvV67FqgBOvrDoVc0MYO5OF/SAYPBr+vVstNrcbE8UHv0+X20fs\n        FcxWoPjluD3dQ0P6a36phpSnK1NVZahL6uvwy3ZKvVW2oAABAJHxGH1UeaCghARmYbIyIF74c8LdCiwA\n        gHiySkAHXme42fcNI8EA4lsyRdwV+r2vYckyTQEWDCuginhDitakm2k/8cwpgvVgAR9Es2GnkurGDdkG\n        A88QRU+9AoMgGnwjKr9gfED1486gnBhdShItSNlUDssEK+AOieLT2bpHs8YbVm4H5rYFqBbDJbthcBhW\n        anYYBAzVWkAwCW5bjGEFEwDog93c4SsUJoLGIq9A3RoGE4FJQZZIjyPEzdhsmNse4v5/CPvv+KiuNFsY\n        liqciieHykk5ZyQBkhAoIgkQOUgiRyFyzhkDBkywsQ0mmJyzMcZg45xDt91tu91td87dc2em586de995\n        +13PPoLu+8f3+8rbxal9YpXOWWs9YT8bct4BjZ/Q5ZDq9UvumM4HGPoHZcGvin5DCuqyIXo10avIvC6J\n        fllURK9fEYHyhPsiD6zXBK8ui9DqAH1VEgDzOnokSH6PXxEMyR3UxahP1xXJDRPe6aLZttkDzVCePgEq\n        JFkGDeAjnlq7HVqfXoARPMawDwD6bOZA+g+YTlncghAK+f0BQ5aU/JJ+GQVFw1qb6+sHZeTmjBo3Phoj\n        R1BKahaQURREgffaycjwMAb451dyVmH5uOlzDx499d6nP/jud7/7j/+HSv2Yr//4n//5u9//EcL/17/9\n        /be/+NX3v/r1r379e7z//Jc0WgCWwV//+i///re//cd//Off/uM///iXv371k+/f/fiH7334+fsf/+DW\n        vYcnr944fuXWyct3jp+5sGzD5uk9q3c/f+LMxWuzZi3p3zS8ZfSo0ZOmDGwY1t295NDh4z0L1504denV\n        dz/effhU55R5HZNmj588e1TntPVP7Nu+7VDntKUTZy2eMmfJxLlLZi1fM2/pqpmLl6zYvHnnU8dPX7zZ\n        MGIovgnz6pBDnxeJCRgBMJQnoCdRT1UTyFdDfEAeHrfpqMEqwlmQgVdgJAFINd33JJ+xDOgkyY/G0Tvp\n        d4antEwfwRCsKgPZAWi0L+CV9qKPZjop7UhC29yFHY2OD4AGyHoFsW9N4+D28RGyA2xAZ+YFYkdw8xzN\n        zw50xl+f0Bwoze6DXkcNTmESGJEQGSsUaWAeITddFTEf++4mA8HWERRiKXbZ5sWAHIhXyIYgjmHfiy6V\n        ri3ZUtM4dOiEGSI5+kVGAFT1gdBf9QPucSiICRCA5gsxbvD1EsCpm68v2ri/vWvBqKkLO+etmL588/yN\n        T01dvGlY15xhnbOHTJg5ZOKcZ85cPvLy/T1naT6A9q6ZjwiAcJ+8QKbrnzggGQvmcDDgvsGSf9Ao/6c3\n        C4iKP4dZNNjHYgCQ/+QFYpFe5vYhcAcBkH+ffQQTwAIwI73Ad5MG8DHdQ5gO6KdGE4ERgqcCsj2E/iYB\n        AMHLmCmQwkIFpvzHqmxWOzqXxYqxFgwBoDedPzQIALDronzQYpEGhRW5rQnR7dZVWAC8pjsAaV6vxeWw\n        2LgxbaUl/YJOjq/Ij8gAIVUY0zfT8AlJNqfdY5aDRnNpsUjfoFEsWvzk2LF3iPaJgn0Mb6/22HK8NHl9\n        ASQ5Q9UaFgYIMfQP8VQ2Lk3gCHAVe4pExR7IhyOQxwbSvkDh+tMgKfLRZ0v2MpErkm1Fsr1S5WhSeNHW\n        R6Z6QVgFdQ/0DzP+yICopwmEWeIpSwDFZhUiCIbKRMNAAQ0kKPDLZYpU6icT/CHbU2iuGMpTKsIGZBlQ\n        ldBUlTI4QQMpCpeQHWGRSjVkq5S4CXxPUFINQ3PFFVSc0PUxycUalh34GJRcAdXlp7G+jgAN9SK9r1NQ\n        F/LfldC8IcUdVgHxIABPSPUEZC/590mqO0MqH9QEv8yHNAlA71PFkF/xqzKMADCBrPABvwGlr0jYTFV5\n        L+BeAfqL2F00iADcCu9VBS8WNFkUeZfodemyoPIeGWaez1DxUlRZhGoSZBq0KsiSLIi8w2oPBv3jOzog\n        ViHwWJq326/rhqYbuootcTBdVbDgM3y6qgZ8wbTUjMLCwrb6xhHDhrUNa504v3vBqrXLFy6aN79n2szp\n        W5958umjhzsmzuqaOn3JsmUZeQVFpUWTp01NZOX0q6nt27fK48HTZnULrKj4P730cLS+ffSa7U9cu333\n        F7+iIs94/evf/v0Xv/7dT7//xbc///7rb3/25Tc/+8FX33797fe/++Of/uVf/+0v//pvf/jLv/zuD3/6\n        1W9+9/Nf/earn37/2ZdfffrlF+9+8Mnt+289ePetDz/94Z17rx8+f3rZ6s1TJq7Yu3HPmfNX2qf3FJSV\n        1zU2Nze1Z+eXpeaXbV655/rll587evzarVvPnrqwfP2OrZv3rF28bvumPWtXPzV3xaadu/d3TFnQ0b1w\n        Ws+SeUtXrF+/88izpw4cOnP6zKWepYuTrQSRHlbmE1BFgO6hUC2L/QIWyfVhor/ZSOcSegqUcwnmAFsQ\n        5rppLXFGL8QDMbEZIT5rAG6G5ubQXDQAKNPgzAsEqGXiGtsQAZgoz/xItJb1oN/kEpMD6GjAUOA7eKtq\n        0ODGttGq7ku2WM1+ohayP2gQWa/wZ5DNANqEfpawRFXqegvY0Slw/YwYvCINiKNKeYJMe8FcwC7EEyar\n        sXc6BVkPpkFgLpgnxbLVYgMBDO+aDbj3QtgwAiALQCUCwPF5UYmmZAQiKbIGm4D6JZ0RwMkbry3ddGDk\n        pCVjZiwZ371syuL1Pev2TFuyCejfNmFmy7jpQ7vmPHP2MpsT+PKFe2+0jp8qJj2uBcQyQU13v+kOehQD\n        ANyjAf1Nzw+MAHL6k/ynBTRGADQS2GCmANP+QHAiAIh6KH1zjrAUhy3LSSO/TFYA0GMZOM7KwPXCd5o5\n        GoAyfHrRH8fJ9XDmWhgB+YwDMplLJ5eNBcPGsA+wFzgj3cXlkeTH9ixg4CHXP7mGIJy99gKcV+OdquIE\n        dRsaJ8A081o9eCA9T26tGzwk6nELT+wcosdkw82f2tqammPA6Kc5Ydwui9tpdbi0SKAsLGd4LYrAyYK9\n        Web2yFyPyJV5bZleWz5vK6TRWHadLQDB80QahRDxWPPYTC8hqvjPpYgUnoVsD0DFy/ZiUvdcukoVftDK\n        Ja5Y4mIizXNZCokNdJbssAPMKSELsC/z50DgmwlFUQFCnlI8c1h0IY8GBFAyEpZDoi1M48goBRbHiVG1\n        fRrGlU/RCHIfRWhaYIoSMxynxP8UxgRA9jTZkcn0fkR2pqvuqOKOKK4QIF5xsUEAEP7uOIVzXQFobQh8\n        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\n        AFwBhgeEQAlgAazYFByX6xuTHV9QlV4BFsAyGQH4R6dgMXB0qk9Mxtqu/kcfPp+8cad94LBnBLqAxApy\n        MtyXEl5+2IC/oWwbaACMAJnrX8YEYA2AoYDgLuvng2j+n3IBkOQE7mNUAA+hFwhd/0QA4HcMAPbDGDAC\n        YA3KHThDCxNA0VdjwcK8HdDyIOp/e/yp6OgHNEdjApiGkPlEMzgkAMB6YyIUDOiv+ddUwHrEPAF6WGeg\n        pE7DSQX0aVgSrI/RAkVVNpOObZmZXHVlChaVcBSoLKFEYu+gr6zC1tUVGxupKFHpCiDwmQDrWMFLZTHA\n        RKCx2XQOB7YpTOycQwWlw2KT4IUAFoG/HI/HFon5ymoCNXWOWCLR1hNp6avMtpjjEezoF+YeGu4SHOEU\n        k+IZleAYGOgcEeWRmOAUHugTGhCVm5SQHxWbkxKUkJ6UmJwaH5BUmBFTlJ6ak5CaHRKVGBqbkGDn7jrL\n        yUbPxAD0Fo3OJdM4ShSlzPJFs+Y5OLm7WVjMF6iomdnYgiwDw4UtEghV1eArxhEqbehPn5n5cvbR/85y\n        XSonL2BqKOraGKhZz5bqzRJraajoaKhqGOrbWRqmepo0u1lsdzfvcZzX7zRnq5XpNkvTLhvzHbYW3U6W\n        PV7Wu5yse5zn7XSbvc3VaqeHQ7+vw25Ph92+jrv8rQfcrXt8bbcGWG/3suxyt9rlb7MzwLbTx3afj+Mx\n        X/fTgU5HA237Auc0uZikWWnaGvM5xCwmJnrqZnoqhupSfS3l+fqqJqpsFl/Lxi14zQL/xQlaBlp8pkhN\n        U9/J3VfHwBi+KvA9UVDAFENUiJhVxeWKJGKRVIvP0hMyNDh0kpzcnraomU8rpy4t/Hm3afpO3fS9uumH\n        zb8erp14uGzsPmwv+/lgxcTdhp+3yqauLZy6VTV5t3jiTsGPC1lfTsd+HY74fjH567XMTzeLvlzNfn8u\n        5fPV7G9X0t4d9nx/JuLDrdK3N7M/3sx8eyr43fnEdxeyXh50e3k56cWF2Ofnol+cDXt/JfPD2YwXx7we\n        n/J7eNrnzaWkZ8MRry8nv7+S9+pq8pNh/0sddme3up3d4Xqjz+/W7rArnYE3d4dc7w64vN37eo/bvUGf\n        i53eF3b63Orzu9rjdW8w9M2R2BcHEh7tjrndF3q+y+9qr/+ZjV5HVrkfXOO1b6Xv8TXBJzaHHN7gd2Rd\n        4NCKoD3NfnuWBR1YGXFgW/LAhti+lsje5bE7l0RuqQrf3hS1sTl+W33SlqXRezYkda1M3bQ8bceK/K7G\n        7O0NGduXFWxryV7fkrW0PmvnutIz+9uW1xV2rKrtWFOxeU35xrUV21Yv2bph8fJ1VYuXVLfVFrW2FJQ2\n        5qVlRocFuM03ny0l+usBWgEByCQ/B1QRmWSobyAQCuTlsTcKFeCP4AAYIBQrG5iYeQaGq6hpKygqynJA\n        CTxFHAdYpxNOGyB42ICdhEZG8CURmTZ0OjpkiPG4BjMcQVmW+ikzGuB0glRAvKPfRubMwTk3EdBx5gaZ\n        h4eOHV0A5QGdMYEHzmFzceI4voDJ5eMEW+g4InhIllEKXEK4jxDoMaMU7oXgDuIdXkS4PoA7XJArBJgW\n        APTDWXhTDEQDATBI2BCDyFmis+A3oUShz7Vx9A6I4PIAeuXg58U2TsAcGD2Gc+lgMgF9ms23DYhJI7KA\n        iGafBMQTHPCftB+ZWQAfuXywAIhuoItXb43NWhicWJJQsCizsrmgvq148erU0tqguMyAuMzA2AwggJUd\n        fY8+fj198+6GgcNeRAxAooAWAIHjiPJgCgDQC0iK6jJ3P7EhMwgwLwgbQZP0CeAWIZorqsNCfARwB/n/\n        V/hXUY0q268I6E8sCPoy9Mf6AGIbM4hoSjpUkiEd5f98JoZ2DYlFVsMF8K1G9JDQBjlPUAJyAOEy0pVV\n        AxAGgQ72h0AmMMOm/+gjgtOBFYA/jKiwjdECNBpoihKgZy6PxWZyVZUpPC6FzpBToHBFYksfQ6mWgEeh\n        z5uvrm4CvxWM/ZLQO0THUAEbOJ/JAAJg4Dwt2OoHuYFD5PgzyQw2Uyhli1TYQhWxhh5XWY2jqibW09cy\n        n29q6WXjG2gf5ukUFG7nFWjt7uwQm+oVmuUcEevg7+8aFh5eUFC8oCSlKMM30T8iKymvJDM/LycpPTY6\n        zj0hwc0lyNHWy83Ow97KzUGkoTLXyVlTfza8NyQyXZ6kwBGDxsd/OrOMItPztLRmK1FIHA1NOTmem6fG\n        tdHtd/9vxjnpgJycFlVZydjFTN3WTGKkq6Gvo6qtqaKrr+djbZrrYd7mMq/HYXaPldnOeXM7red3OVns\n        cDbvdpm7y9V6p5tNt7fTHj+Hfi+rfnfLXV7ztvu47YuOvJjpuT/E91BU0FCMy55g16EQz/4I5/4I284g\n        255Qh10hzj1hrgMhbkOBboMhrruC3QYDXI+FuJ0Ic+rzm11hq2FnAhwl4IlU9dTUzbTVDXXU9LVVdFWF\n        Yrayvq5DVnpAXa6RlbGyRE2iosnkcuGrLi+noARWNJrehJUNX1GcC4OrK2JpC5jaHBpNTu5AR+rMrwPT\n        lyr/uFgwfaPg19XKX9drp+9X/bxfM3mnZvpBzd+eLJ28unDqSun07eJfd6qmb1ZNXMj8fj7v05n0r2eS\n        v97I/35/xbe7bZ+uFX69Ev3tYsrI9bJvV0q+Xs/+cjv/7fWFH+83f7qZ8+582MfreW8vF7+/XfvqWs6b\n        a4Xvb5W+upPx9m75x5uFb86nvLlQ+OFGyZsLCc9Pen64nf/uYeWHa+mPB31v9do9HPB6fSrm4UHPZwd8\n        Xh3zfXY04O5+58fH/N6fjn25P+jFUPDrU0lvT0a+OhT1+kT8i6ORT4ain+5Lu78n6uHu0Ie9wZe2elzZ\n        7nNpa/DldT53tgXe7A87s8NneL33ua6Q4d6Ya/2Jw9viBlqiBtsiu5uCB5aF7Vkbt7MhpmNp5L61SX2t\n        KTtXJva0pne05GxcmtjZktKzLGd3W8H+9XkDq/I31qfvXld743RPe2vxqraijg0lu1ct6Fxdvnlj/cb2\n        +nWtNVtW1m9Y0bByRdOKNbWNi8sXNxTHRoU5OznqaqsSaULyNJzRgKykIA+Wga4W5gkAAWCVGKaHgn2A\n        IQEOV6CuoW3v4TvfwV1eQZ6M+T8sDKQBjhN1W7ABmh05AMU1h0gBwp2yMgN0wsCXDvYQjnWQAgRSo1MI\n        C7uI5NHfTID4i6CMaXh4FoIyBe4EYI3XxxIwgHgMMMCzwXeJRfhheAIZysvEu+ys3xYAGBOEuYBJpUQy\n        EvAHQjxaBkgzYLtIVTRB1zM5mFoqcx/Jkv0xWoI9wvCHhUNABsA4jm4+AeHxHB5fTl4e3nAWl08DW4eo\n        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\n        A6hcNnaoZjLg+akClpwiAyyQvquL9/zfS8OwVXJy6mIdupGdgbqlsbKhtjKoNT0DA38bwzqH2VvdzXod\n        Zu+0nbPDzrLH02qnm22Hp3Wf7/wd/jZbve27fR13BbrvDQo8nhJxMifieHbIseSQU2lxtyuSbpcnXs3O\n        uFYfd6Ys7mxx9Lni4MO5wUdy4k/lx57I8T+Y7Lcrzqc/3rs32XswJfxIRtzhjMD9aV4Hk/wPx/vvifLa\n        HeF5INH7RLLvpUTnQ1GzK1ylNjpivkRNU0vPwlDVWBskooqBCl+ZLzUwdstLd071FYmEYoGqsqom/qXQ\n        YEcHMXxLBEy6iMOUsBkqfIYqi6YkJ3dwX/XMzIuJ8ZtT07d/Td3825cDPx+2Tl/MnTwZ88dw1p9X8qev\n        Fk0/Wjn9auevp+smHzRNPVv983X32Ns9Y58Hv7/c9P3piu9PV46+Xj/yat2X+63fH6/69qh15Mm67/eX\n        fb/XMPps+Zdny7893/D5ydrPD5d9fbnu69Mt3593f3vW+vVO0ed7tW/ulLx/uPzT03ZcP2z9+KDmw+Xk\n        r3cbvr3o+Px87efH6z+eL3h5MefN+dRP16o/31j+4fqStwD91xvfXaz4cLXsw4WC9+dK3g4XvT+V92E4\n        591w0dszpW9PZ704lPBif/qrk3nvzpS8OwoskvbmSMKLoZRXe5JeDcXcP1r+4PSSh8dr7+/JvLIz6vjG\n        mHPbQy9tC7m4Peb0zvTDW+MOtkYNrkzqXRvXtTZ6sC1+/+rUvZtSB9ak963M3bMmdfe6tN5NWQNrCgbX\n        5+7fVHnv4p6+7dU7mvO3razcsb68b31NT3td9/raTStr1rVVbm6r3bp+0aa15avXNLW31DbVpZZWZScm\n        pAYEezo5zqGSkQPguwMkoCAvz2GzdTR1wSRQUgIrgEbkC5EU5RVYLI5URcPJ2cN8no1M18viwIjLgLMg\n        r35n6BNJnzKvDgtwFn0vCOIEBKMkRyWOQQJYYCTAK6b9ILxiZJiAXcT93wSAGM0FhAW9Dzv/XSqMwC3z\n        7WAEgstg8+HWiO/4VL/tCTgBY9tEpJowPmTMgWNwm4HtKwi7AW/K4PB5QjFHAEjNx6Y9XD76dgiGgAvC\n        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\n        sWuwnn5/fOzOqvE7a8Zv1n87kfxkT/qFbt+uBrvypHn+oeamzsY+7rOT/cyyA2fX51ttqpq7t8p8uG3O\n        vS1G33ebTZ50/HE6+N1O10999mOHXMf3+vzoMJ86HvTrbPr77S5gCvzjWt73R1uay5yzk2cf31V073Dl\n        +YHcnmUxzQs9K0sty3Lm1hY7tFb4rl4a27Mh91h31f7OktXNHsvzLToWeR/cFNnb4pYTaexoq+bipOHs\n        YTh7rpa2Fl9fBxukGmgLLUzUTfXExvoie0vD2Oig2sry6FB/N3fzeRba5rM0HWz0Y2MdcnP9kpM902L8\n        UuN8E5IDohN8QiO9giO8w6I9k1N9M9MDImI9Q6K9I2KDEyICEqODY5MikxKiU+PiCnJTiorTCrIT0lMj\n        s3OTcsuTszLiYuOiIpJSclJTispyK0ryFhSklpVm11eX1y0ur6td0NBUumjJgrSE2LWt6538whfUNBw5\n        d3b/keN79x3o7N/X03Po8ND+nu6hrs59/YND3b27+wf27R4a6tjZu2XHrk1dPVu2De7Ze9yUmOtCKFZG\n        /wZRPUuobB7gI6Ae4QLi0VlcmU0A8hxAGeiBxWaLJMpgOgCkokEAZMAlIrfo/RdyRSK+WCoQKwuE2E4H\n        1boQsBtNB7gFepPgUijqxWweele4st4P2CLid8IPaHlQ4jwR2AqE8x2ujB/hmmpMOMricYTKQok6X6gM\n        w5BshGIW5ghhdpAsBkDEftlAJGQqNv3HqK9sDwaBGQTbwTZObymvoGBh7egfmQiXgp8dTBk4nXhIMFRU\n        TObM1dQ1RDrkEO3kZPXJ6LwSyzWv2ZZUUBuRWZVc2phe0ZS1qLkQCKCkPjA2yy863Sc8xScyo2Vr74vX\n        74Zv3Wvs3efo6ouTwpMU0J9DAD3h2wFk/63rZSlAMg6Qpf3AGvAX9vwuCYY9RCKmbBESKAzgC2vC84Oc\n        AdAMTAB78IJEUBfuAhwgy/WUEYAmBYAe48BwO/Q7ERcB+Abo/6vsi4B+AuiBY2AD7k5YD0T6P+FuAiqS\n        GRkwABa4I1COANCfoDdVIsygymcx+AIKiydUVacwaFQmUxG4ncUs01Mr1ZMyeCw5Cl1OjtysZXjSYxaH\n        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\n        6sUKNWoKAR/MBcwRYjBA8lMYzBA6g0Jn0JgMNnwNlSqsOeCyGBI2aH8WfKOUAn24OcqbGOlOLBs91pVE\n        JID++yPWyDKm1oZl5ShMKnOMQ+UMM0S5lDlW2SI1PY7JcDJDIigkEYmkw0RPShSVHEcNogYJSqT8yWKS\n        hATILqlXK6cbyROoqoUmUbmClE0STJSJ4hRUA42URpJv1wqcQhKTxBzDvuHh5Y7hBPfbnEPxM25tPjBy\n        fHjk/Jm/nnvtPx9+8td3tx/9+M/jf2AQup/wAmFG0Mivv9x+4eeXD9w/vuVu78zP1s1+Z9PElxYWnW4o\n        O9WS2p+VcrbQN1wY35VV9EXTSyPvjzwauTbyS/OfS79aoK09nqU9k5nRmxPfm5Y8nOvq9PIni8wbY/zD\n        hWmdWRknsnRPR77730+f+uc1Tp8+Zld6ypFC25aosF1R9u2R1q2OqA6PZY/duS/Zucdv3xPr6vF7diaq\n        Ygwyo15hM4rFCrlTXbx6XFx+EkcpMJp0Fq2GyeDYTLo/Pu54/NXgw+vHH37WcffFsT9cyLx7oerBhco7\n        zzXceWfDnXdW37q68sZT9d8Px//w3pYb1wduftZ799PDd+6/evujzrsn83/4bvD23Vfuf917+/ru+9cG\n        7l87efed3bfeXPr9tV03Pjt2/8tzd746f/etrTcvVX79wrzvX1tz9739C1qco4rUezekrZrjSY/m718U\n        fnZn/Oga69hRjpRojVLAVKsEERGa2AjV7JbcN84t/+jV+ddfXPz9S6uf6Z3gjldJVTyDTmozyZITjMWl\n        kWMq3VMrnWNHRY1u8Y2pS6iviC0ujMrMCGsdk75xanXPjKahVS2dq5s2TSxePqWoZ0Xjwqac8pKEuko4\n        0ze2KnHiqJSx1amVVQnllf6KrPiaDE9Zri8nPz4nLyYv01OdlzwqL6ksOyE7zZ2a7M7MiMvJ92XmJaXl\n        puRkJpVnpRQXp2bnpuXkpqUUpBQW51ZWVZRWFRcC+FeVFtdWjh1bN27SqNrJLVNaxtfkFo4ZPWrjuk2+\n        hOzShgnlTVM27d534uTJ3mPHu/oHuvqPHeoBrD/aNXD0QP9wV+fQsaOn+k8eH+o/0995rLt34OTJM/3H\n        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\n        YdJJlCAGg0pi80s0msURRhKDSsZiYDbmBWEQmE0KIYs0iujURF2Y3RgeqdCZeUQEBqwEOodHxTOZ1IAR\n        wKBTWSy+QCDTaRkSFlWIbUQ5MhlbKOJrRN70XPikfalZC7a160LtZCpdbbYl5BTEJKRbXBEpU0fr4qLN\n        qU59pjPM5VZH2zTzQo1bwkmGoGBdEFkaEsQPZvl5phUOWgorOCokRBYSTA7hjOKxS/nsyQL+KklIEpmT\n        I6A00BVTDfHrs0h6knalWT/RTkoKos9ikWxknZd1HSZzcvT9iYbxRtv66MLLjRO/WFT+/rhZtzcv/XHb\n        +gc7m+5M/+q/Nwgj4MkP0MGjR49Gimquvd63aqR31r2tUz5fUPvy+MbnJhSfGOUbznT2JaUcL4o7nJX0\n        YXXHyDlA88UjWzkvi33H8gwvV34+xjR3R4LqYnHMkZSIQ27HYb//WGn6sRLn/jjHYS/vqPHpX16/N/Kj\n        +rTduj3G150ZtjsmdEtkTLsvutcf258atS8u+oDP2Rlv2Gi1bImKPJhuORxrbbArFEqxSSk1KOGf1t9Y\n        VLJ+nixSJ1NK9TqNTqslkWid+8aO3Dv85YWJ189O+Ozljd+92vnt5Y7v3z548+ru25fX33thzo03l9z+\n        5ODdq+tvvL7g9ieHb37Rc+ejvTefGXvr5am3Lm+9fTz95vM1N767eP/Do7df2Xz77bY7X527c/P5298O\n        Pbj5zP27H9x7eP3Bhx0PX5v952ebDq1JS3AwLBqFx6WIi5FER0pKMi2Jcbo4lznZG+qL0Xidysl1CVtX\n        lS1bnrN0bvHcmQXV1f6+ra1XT8/s3VV//EDLUHtjz+byUzvKLrQ37F5cOrs1ubI0NiMltCgnPDs9NCsz\n        IishPCPelJpiKivybJhRtnVm+ZrxVbOacssq4xqqUiY35qalh0ZH61wRuki7IcJujHDqwyKN4XaDw6Fz\n        2A2RDmus0xofG5bgj/ImgJixp6Y68nM8RSXpuTnxyX5XWlZ8Zl5iXn5ycUlmRXFGbl56UlpyVmZScUFG\n        TkFmTnF2UWVhUVl5TW1ZVUNpcVV5TcuoSXNaZs9pzS3MzCkqmTp5fnJKTpw3LSurbMfu9v6+4b17Ovd3\n        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\n        MXlciDG1riRtzR98hHu5UA04pvH5eu4ifXAApoq3LiJ9X+YUchDqW7P+OAC+O30N/FJzFeMt+YtsRBw7\n        McdGqGcp1HMxNPAwMnAUca0oSsx1FgscxHw7Ec/TUKihkC+hP/6NPwSRWCSkxSRCuVisNjG2UCqsNGoH\n        K1Wgi0uIq0eEl29cQEh6aPCYnITN44pWTZmwfdbSLWOGr1s+c/mMSeuHT5hZPq60sOS7lWt3rNy6e/XO\n        w9u/766r6224deXU6Yt7j107fKLndt27gc6Pzx91Xq8/ue/AqoXzS4oL3Dy9jRRqHT5HZ4hQR99IRygR\n        WJoJnU2NnN3lXv5mIYHmgZGaoKHq8Cilb5iho5/AxlWsstTRpRoVQ/QFOkJDHSFHbWvr4hcWHpNSXlu9\n        ZsuWuvo7bz++7m3pvPfb5YHe3p6H3e33Wl48f/Pg8M8/ZUU35Se3xCc3x8U1x0c+yI/tqM26W5R9NzW8\n        KSO0NTuuPTe1KT3+YU5cR35KU1L0zejgi7GRx6Ii9oaHHPP33OjkMMVUM81COc7OfKyF6XCNqkItL1FL\n        85TSLKlhttIk1MJqwcRJ48ZUxgf5jcgunFA8fPXcBcumz1gza+nxPUc3rlxz5PCxnTv2nzpx6l5j44UL\n        V6/cqL9+7VZj/a2+nq6Gu/cedHT+tO8QQY6xiYWFuUpFfh4KAqvUcqWSFegFCSipjLRMYULwp2LpoWql\n        AnaBUilTaCD/1abmZCKozJSmZhpTPS5UtU64j9/F/UdfdHbv3PFdemZORIBLgIs6JcKmssi7iHaFDCzN\n        CczL8E3PDCrMCi3PCk5MCU1OC83PCcxN8cvMCiotji4pj66qGlpYFBOfFpZVEFdVm1BSFFNTkjJrZP6i\n        UfnLZlUvHFe2aFLBshlF02sys5Ii3Vw8DIQyV09vc0tTVzvNxHGVx04c3bvj+9gYyv4UGIhTUgoCAwIT\n        U9I2bN6eGBePk9DiMHOkQiMDXT1Tc6ucstE+/lE4D+uUhUahi/FKUV9tRj+gn+hQYcrwTmKsLaoMIGPK\n        V2xEgAi8o30ZTZRaAmCKnvl5yMnD1+Z6okH7Q8JrER9wTAfEHOQLokaVJChcLAJSk31AGaWGzBFPup4w\n        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\n        hAVw/srGE7+PHj5So6Njxx3iBP0L+Uz+fWhkyggCJlJGkAElyAP9genmXNo0Bk3rDiJvPvHBV0wHagM9\n        LVnsF+hpySVRT9DJvPksDEtEAtBHf/QEOgNbQTauPA7lfTLh7ySgboBawLQ37AYhx5GjEyIRji0uGlFS\n        7mJsZAwO0NclXxOXpL2bUC/UkBMi4niwy3Eh5D9MCqIHxjc4g7fWjIdY2g9xAMwRNCIYfEqTp7JuWsmP\n        S+xYyAHNkZWStqU0Vj0zMilokgB9YDpeYRmomIcHBOAv5joKuLAAGAdwaOMXPsecR4lAFCkx0FfzOcak\n        /QnfSf7r/0MAXHrl6esagAD09fn6HAGHI+Zw9XX1RHy+h1LmaiLiGEuDnN0vxvvUZweerMqKSRw2pnD0\n        zklzdm3+4a/m+o8PGl93tH8eGPiTcP/1+ycvPj5++vH5sz8+fPjXlz//BGq/efvp1ZtPg28+v3378SVl\n        iOIk4P5//utf3d199fX3+nof/eu//vWvv/7rz7/++vT+0+unTz6+ffPnn//rj8/A/78+f/7z07sP7169\n        +vj+7V9//vXHF/z/T9gEb1+/efGk/+XTgRc9j550dfd2POy+39LZ1NR5v/nmxQtNN6+9e/aq80FHW3Mz\n        zt+9Vl9/9Sr44N61uqYbdaCBB3ebG67Un9x3pO7GlfZbdR03bjRfvt50/vL5g0cunDx56/KFu3fudHV2\n        dfc87ezqb2vp6O7ofPJsoP8xuYKeDL569OhZ25bdD+dNaFkw/fqo4ovDcuozCppqCq+OzPg9M+psWuzP\n        2dE/JQSdiA06Ext0NjLgQGLU7Oz0xMyc9IyscSPGjB05ZfykWePGTxldM6OmfEJeaaV3QKC5qYWAxxXy\n        ucy/zXLLAf1Ux5n+6K2sHUytLC0srKHQy4ePn7Jg/bffH9++c9/q1bsPHT4TlZRkZufo5u3vHxgcHBji\n        7RHqFxDl7ePn7u8RER8bm5AcG5OUnJyfnpCfkpadVjSsrHxMVkFeVmlZfsHIjILa2PTs2PTMmKT0kKjo\n        oXHJ0bGZkfFZkdEZ0XEpUfFpsVmZcRlZySl5Sal5SekFCRn5GfmlmQVlQ1MKEnLL0sqGV9dOSMsojM2p\n        qJ0wc/qCWUvX7th18OThEyePHz9z+tRv+49igmcPHj+1dffe9Tv3bN918OCR4zt2H9y4Y/eWXd9v3PL9\n        wUNnv9v9w969hzdu2bV83Zo5S5bOW7t17IL5NbOX2XlRISBoViY2SW5rJfn/tQMMmf+H6W4CJgoGUMOX\n        B2RnXg5azAUOoO3RyV0DQMQ3qsYBuenJncL8M2IodMqkFLOEH20jmS8yBEoyssFHRgBQaGeCb/J6k8sI\n        YIr5kF+FZgVIxUzIWDEGtfyTFATkpQgwLapjYQbGXrgpYFpKGzZoZKwqEcAdBMA89bSgAfM0kanAGezR\n        aGKYHiaMbngicjERypMXiOiNpSGRR0uuMFFSfJvJfzImcCPy1eByFgFmtSXYegL6uujpeMQBQhYDoCRR\n        jgFfZ4ieX/jQjJLhQHb2aPRV4Hn/oQFiI/ZtU/v/sQCmzl83ftaaOev2zVr7XdHIKdFpueMXrh4+dWlC\n        TkVaYU1GyeiskrF7T/zy6n/IBbRoz9HKyloLHR0HgyE2LGnSkdkBwHfgsh0zBXDGFjJZQIpYRRWBCPRh\n        KDgA/pgf34b58e1piSwJbeA7OVtYOqm2jpA5dWAbvLDKmhgHbEFleUgpQ63jPKVgQv7jALiPjwDWuLUb\n        JdVw7Pl6Lro6MUrpmJKyiuw8N0OBlPYQJvT3FOr7ivWixZwwEdGGM48DgwAXAvoh9vFKBKP1YtH49IA+\n        5GWiFE8QAO03wFJd8bxW9HQ0NyA+zA5chSkRkQiJpSxZ/o8N5sk8QgB9vJqz1CAZbUjA8RdzQAAgBhCA\n        tmwcjs3pC6GAgRlzBAn1gexEAIYcfTTS/lpTQF+Pr6dH6K8HJqCTIg6XsoAMuDYmJrFm0iBrtbvaYlWI\n        /dwo5+4VoxsWTS6Mztk5fdG173e0/H7mQ8O1JzdufOjv//T0yWDL/Xc9PR9fDH548eLd0yfv+x59evH8\n        y6u3H16+/vz+3adXrwe7e1/3931+++7Pz1/+57//19u3rxtu1/d19//7f/4HYE8ung9fPkPvf/nj0/t3\n        f3z5448/yDD449OXVwNP3jx79vHt+z8+fv745u2bV6/ff/j45tWLV08GelpI+z/vfdrT2v6kt+t5b09b\n        8736axc76++11N2533C7s5k2fqm7dPHa+Qt3Lly9ff5Sw7XrD+81NV29duPn3y6ePNVwre7y6TPtVy+3\n        nf3t/vnfHtZdunHulwtnTl85fb699WF339OGhqa29taO9s6enp7WlnacevKgo2n+glvDR7SvXdgwZ8Kl\n        6uIL+UWXqgsvj8w7k5ZwPDHydHLMscS4g0lBR1JDT8bGHIuNWp6akJaWBf2dkJSemp7+zeJNG9d8P2v6\n        0uT80tScguKCQndXz5jE7LiEHBdnb0d7Dx+vUGdn59AAyOwi/5BID1//wNDIofFpBeWjl67fvXDV+smz\n        F+SPHj9m4Ypvt+4Lj4yxdvFy9Qpx9wn29fT38PD2Cw4KDQ33DwlMK85PzcqJCI1KTElPTspISstLyMyr\n        HTl2xeIVcxcuLqoakZxemFNanpxXklRQHZqYGpuUlpFenJ5bEp+ZMzQxIz6lICYtNTYvOzNnWEp6SWpG\n        QX5OeVZeQWxGbmbJyGFjJkxfvGTx0pULly5fun7bgR8PHT1+cMO2g9/9cPTy+QvHTp07eOKXfUdOHDj+\n        48mfL36/7/i+/Yd/2HMYWL/u213rd+zatW/frj2Htu4/snb5tpUrt2/Y+P38pctmLlk6e8masimTaxcs\n        CIz8GgMgwKJqNuT2ARAzqAUuE/ICswh2xbRKFp8ynpBQxVDK36fETTKkmKceelmLqhR3pVRLlglKJRMI\n        09FEhpRpSsEMQn+CSMYHWscOcQ9BP8sNpc7Mo4KeAEEIZz5l1MBcQE9KEtV2xgiwBmhLdzICtGYBaXCM\n        RiEUmdSEAr8qmUKp9QsZyeRiuimGxYUUskYHQlvgLGV5GguE4AYq+MOWvJFfnm5E4XZaNUYBCTCBQgXJ\n        D9TmUyEPBv3a0AUDbq39IRQzHw5sFLaeAJRpwNAfzYAv0Bmi6xs2NGvYKGOZigoEsezP/zSxEd5qR6Aq\n        EUZUKZr8TloCWD9+9ur56w8t33Fy9Ozlds5uqYXVwybOSS+tTSuqTSsemVU6bv+JX1/++9+Hz19deuCn\n        6uGjzHV03HhDHLToz8S+Fo4Bi0BVmAWOQqbcmcMHQGnBpbVX6KONBFgz4YwLWWSYfCNQ97AGHCivn8Q1\n        2IKUuICcPPgUDOHEI/QHvGpVP4jBRcTSe2gXMA4DX9ydXE9urPyOC8hARyfGymxs9YiC6GhnfR3ZEB0N\n        l7Zi9xfpBwg4wWIuUBtXQc47sqJAmDluB5jG3fEgmAlowJX/Ne8Twh/H1JMlfWoNF1gqUOvgHszHQ0jc\n        A/jGeZbOxKZKzEFRXwh/yumkzRKIAPB03iKuE5/LXD0gBg7mJufiIz25AaWQokm4+kB/qHtDDseIq2/E\n        JSYgAuDqCvT1DfQZ9IMA9GAEMMtAT5+D82JDO5VqnLNZsEoiNjGJdLJdXZTxacfi5eOnTi2qvbZkQfe5\n        E09v3Xp+t+ltb//b9odP6+petbRQAs/rN09u1T+ta3jT2fmuv/cLEP/Ln28fP3k/8PTNo8eDfb1fPn3+\n        69Pn//rrr9bWzt4H7f/+668Pz55+fPUG6h4y/+ObN2+fDrx79uzL5z++fP6TmODTpzdPnj3v7X/z7CUI\n        4LN2rcCbd8+6ex+1P3w98PxJb39vW1v73cbWG7c7bzV1NrW2Ntx92Nh459qVugtXm6/dbrlz715d/f3G\n        5osnTl795eyd63W/njxx48qFGz+fv/Hrpd8O/nj97LmLp09f/un048aH7Q31rc13Tx/44eC2TTev1PW/\n        fP7k+ZOGuoa79Y11dTdu1DWfW765ccLo+hGVrTNm3F88/dbcERdGVl6oKP25tPBw6tCDsRE/JCUcSUk6\n        kBq3Ny36h5y4HfGRM0P80mLiYxLzIlNzckvKK/KqKwpGZ+bmR2ZmFowYuXX7rtGT5udXTiyrnlM1cnZC\n        cn5J0fiy6knDRs3IKxodGh0XHB6ZmpY/NCkuPbswK68yNiE+Lb+spHralHlLK8ZO9QwIdvX29fIOcfEI\n        9PAN9PT19Az0CwiJCAwMD4uIi42KT4xPT0zPTMrMTk7PyijKL6moXrJgzbQ5SxPzSiLiUnLyh6UWlhdV\n        jy4ZNiIsuTAluyg3vyQ5ryAhvTR2aGF6albhsIqq8TNqJ83D6+hJC+fMXbRkzdq1O787cuz4qROnf/79\n        /NGTZ06ePfvD8R/37zt29tffjp49uf/oiau3bp8+88uSFVsOwBb47fJPJ8//eOqHA0cPrt2wfcuOPad/\n        v/L9gR937dmzfteeOYuXLVu5cdd3ByfOmDt6+tzlq1ZVj5o2fMqs0KEUAxBS5o9YIAbYkh+cchZBA+Sm\n        p/wfvrZCJ+CMEoFwTIgGtQvoJ5VN/nRK/QTqSVipU+AUEM3YhFaxogMGpNVeeIVk1gp/wlbKNaKEGVoe\n        peUDcraQEUCOIPKukIuJUiopE4msEFLT7IAW3JLGZ+4piRERDws2sLQiZkNIQDMSqrFN7hrC0P+Hq78A\n        aCtb24bhlCQ4LU69UHd3d6fu7u4t9ZYChVJa3N3dHRIIEoUQ3N09OHTmPO//zX/fazPnfb6vZ53Mzta1\n        M53rum5datoaOmgEwIvAOVhngO4jpBC4FidPVSyPGyU4N7AA8Lbo9YJ3x0ZNOH/4BKMES4IxRRVnTkwH\n        nC1uI6XBragLMWKhgpEPYM1xI0BRiZQFKMjQ6RgEvnJ/kgbJAqJc/zCACTABCcgPnUv4atgHdLwWjHIB\n        Wb80tPpmG2jiHPnSyFp78uR5i1ccvXDnxJVHgP6HL9w5cuG+Z0RC+3/+Jzg1y8w/5u69x1NptAVyNEAx\n        gFr4BFyDT8BQwEeghOWkczLAPaA/QXyEQtg/G+u5MJ9HG+wAUib2bxc5pBC4Fbp9sCkmojkiMjAE6bIA\n        hzBfnoh05ACC2iuVGWuU8Xy4Mwh/QGe4EL6uU2Kuwk4PzKXydD0abe/KVQ9uPTq8fMk8MAIm0OBxwD2r\n        lZgbldCtj2KfPAsuh/0U34DwB4iHT5jhciXGehXZVQDupJR33FghNckkBwmDGfD6sBNIAjgAztGWZcAL\n        gnEwk0wbJgymwBTiBYKBGT7wg5CVKeFnUWPStYAjicUAwh+2gQPUcGAQGAgAq72YGAmYiATAUJKlK8vR\n        wQiQpQgAPukMOeAA8qnEpKuqTVRSnQyyZP3sqYunTj29etGzPZtN7j/LtLDw+mAWa2HdzEntqy7vKS/t\n        qazulOS25Yi7iksB/Ye6utpE4nZxkbS+cbCrc3RoaGxotK+to720uru2XtrShHq/r/8/f/3V2NrRWts4\n        3NEB3AB7RkfHRoaGehqaBnv7AOiBJ0aGR9EXNDQEiN/X3iXt7h0aHumX9vf1SKXtXW31TU2VNe0tbc0N\n        dRViUYWQXyEpzOcKqwoKioS5FflFlSD0E5O4MXHFIklFcVldZWUBN0uYnp4UFp0UGxEZ4pPJSmGnJmXE\n        RAc7ekaExHpY2RRkZeYLRVWVFUU5/Gg3L1Y8qwNLwLrLS8rq6htKiguy03lJVu65b15J7t0tfvOs0Pyd\n        +Mc71r3LCZePR+ufCDm4x+/gLr9Th/zPHvE/c9T39B7/87ssD+24v3fXjp2HNm/et2nLtv379B9ev3fv\n        8o2te/cu3Lhp4+6999+8ffnd6cLtj7cefbn37OueQxevX39mYx/wysD8xPl7c5cuX7Bw+Zy5S8EU2Lv/\n        5M5dJw+fvqCvf+Xqubu37zw9ffn2qvXrlq9av3rNxlUrNyxfvW7lmrUr1q1fs2bzuvWbt+7au//wsaPH\n        zxzWv7BP/7z+2fN3Hr2+cuPpoYNXHrz4cv3520cGX+88eXnyxpXTN+58ePzt2vXHB46fP3nh8s1nT8/f\n        e3X95qunTx4/ffTys7Gl8S8XW3cv//BQ/7CIkKh4r/BQNj87kZ0ZlcqOZ7N8wwK8A4OjIpOjI1M9A4K9\n        Q4N9Q0P8wsLtPTw8Ar39ohMCIhK9/b0CwsJ9/GKdfUKDIqL8AkM8fEPtnPx/2dl9MrT4/s3h+0+n/Rfu\n        Pn/+9eNXm0dGhkvWrUULQBVdPaCyAcVAziM0g9KfOFEB+xKR3FPSA46AL9AAEADVIAET4dU1pyDeAZiq\n        aaBvRB0hHpUywBbqWeIFAukNQKyOsAiwS5xImCupgPlFVKUxAChiKEAt2CKItoDjWOeFfhWcA8I9Php7\n        LSghGxG8xl49OEgYYCLAOvqO0HkCfEPakRLVr6EBA0wTdNzDmfg4vJb4l7DPM2h2SqfjiyATwGuCGQQ3\n        GSchuBsYB6rEuAG2AzFOOYsopz8iPr4XkiLcYRKYRJrY0hlOw3dE+oTfdiKpBUMCAw6QoTPWbdujf/ku\n        1gFgR9VxJw8MwgRAIViiDPYBnED2wyeJARh8tX751fKLtd83h5Cvtj6b9xxUVVNfvmbTwVPXT117evjC\n        vUNnb7qFxXX8538CkjOM/aIfPHgCBKArSwP9TrruIMDBANCn3OgrlHCFRcDlmYB3TPT7wzmg99EmIDHh\n        6Zj5gxwAJwBigoKeQellJQB90O9MwPfF8tiUDfAXroUBz4I7AwHMh4eS1P7lxBEE0A/PWqEou5yKBMgz\n        1ilhcg56gYAqZHDtgZO79t69+fDk0oVLJ9Amy+AawqDfKX8O5q3KY84S3BwuB9W/gDxoAbE25snjar3r\n        VTDrHxgCLIPJpJBtBmEC4CEkAJLoCQSwkJQLjMM9Wf1YB5M+mcBtsAcuQe1P9D6MmVhVgH0jNJl0DVmk\n        hynyeGfYD6epyzEB7lWYdBWC/jDACFDGFCA6EAAMRaYMcABwAxAABf0wmHS6PJ2+Hv5qqatP0Z68aOrM\n        E/P0Vi+Y8/7yRScj0xALm6hvdm4G36sigodqivurKzrFOc0cTldJGeK4FB01nfnFdUnpXcXlY4PDo4PD\n        f0ZGe+qa2koq+1tbu+sax8ZGR4cG/xoZxY5vbe3DWFzbMtDVPTr6Z3R4ZKCrB8bwAIA+yv/RkbHe1nZp\n        a3tPc0t3a/vQCBYHdNY3d7W09HZ0ttc1Njc1dnV3ttXWNJaVlBcUl+QWVOQXVBThZ7GQl5OenpuWWpyb\n        k8PnFYhzROkcVmxcemwcn8XmsVKyUlJzMnlpcbFpcVHeTn5+jh7p8bElhcLGpoYqSXFWRGwOT9DU0t7Z\n        3VOYV1BWUFwqzstOTUoICROEhwhf3i98ck9k8J5v+Ibz4Cbr0c2Ey8dC9PXdDu32PrHf+/Qh//P7fU8d\n        DDx5xOz4vlP7965evWnNytWbN2/euXXnlVNnTx47c/j41dO3Hj98b2Ro7mBq5fra2OrlR1Mn1/A3n62P\n        Xbn129HR1sbn1j2jQ6dvHjtx8ezZO4/e/Xxr8vvNu+837j0/cebi+Yt37t97t2fnwYVLlqzdsm3txo2r\n        Vq1bv3bDynUb1qzfvH7N5i27dh44uH//Qf39+if2Hzu+//i54ycu3332+caTL/v3H798+aqh0XfDb6af\n        LUzeGX24+eiF/o2bH569/vDO6Nbnt2++vP9mZv3KyNTc+qeLvae7a5C3f1RgaHREXHwEixUYkhgREhka\n        Fgba3jMyOiwh1i84wsM7KDQkxsc/3icwNIGV6OTubese6B0W5eUT4BEUFxibHBgRHRAR5xYcZese4h4Y\n        YGJrY+bk9cXU8us3i++mv549e/vyy/frL74+vPfZwNjyjanFgmWrqSwg0u0N1TGAFAAWKnTAaFTc2JkH\n        /dEUK2D6JkAzOmcAczWoElki4dEvjyivpYT6nbRhAMzVQL8/6lmES8A1jNACwFHeEkR8siQG4jsBdMBQ\n        aoCsJo8Yd60AHMNMiFcECQmd7OiSwkpgzPxBfxTOB5CdurPqeFMg0P4aaurYTQlsAuAGQEs4H+4Adyac\n        AdiK2p88HbEerZB/A9fwVUNLR2vyNA2dGarqUwGRdabN0NSZgq+PJWw4GZwkXogmCDwXLoRH41cSIAFe\n        ATOF/HTAAaTbHSmolqEz12zdQ9JAJyPhwTQw/R8H6H0sNINByIb4f8YPEQIwtAEC+GzlZ+QYauoa8trE\n        atmajWBZzF+64vDZGyevPT128YFHRELH3//xSWB98wy7c+/RNBptnuwEQH9AQCoKOg8EPrp0EEYBW5cq\n        oSkA2Afyn6zzhRA5l2TT6xGnEOyfDgMLfdGdAnIbGGKJMsmbxO4OmBi6GP31SCpEaMNTsPHDEuwUJAty\n        e50yc5UyqHjZpcAExHQA/AUCWEHSgWAaYI7A3BYxaKuUZM8dOvr66fNzyxYtodGmydD+S0voLCK8ghYA\n        gX64Fj4XoxGDJVorSM3XamqhGOzvRgdYB8mvR0wEGBQZoPWgwIT9sLGQdIiDR2gwsYMpZkb96/0HcJ8s\n        x9TCJFGmnoIsDIB+IAAwGrTQ+YMRBeBCLcz8oSszEPcB/anMH4oAAPflyYaKHENBFjiATrxAdDky4D+8\n        Yzoa52Zpa0yevGfalKU6Ohv0lr67eTXd1tjP8HtZXFxBeHhdVpq0smS0o7mnphq0P+r9ju7h3p6R3v6B\n        1s6euoa+xsb+trah3oER9Av1gsYf7u0FE2F0cHBkaHBkYGC0f+jP4PDY2BiWicEeVPoDGAPo6R/u7x8Z\n        AUL4A3aAtLNroK9voLevt61zoLd3qL9f2tWFbRmaWzsbGqSdnZ2trW2Nja3VNeIMXj4vp7qovKaooliY\n        W1YkqSwEPBfVlWAkIDudk5WakhwZWZqXV5FfnMcTpsUnJkXFRIZF8TLTnWzsQwMjYkLjcoXcyqKS0oLi\n        ArG4rrKqoaGlpb0D2zDU1jXWtZUJi7LjktnJKZlxEWKzb0UfX+Z+MeC+usN9ez/t4VXf40d8j+4NOHnQ\n        U39voP7ekBP6YWePvj24a++6dWuWrFy6aNmK5UvnLlq0au3mnXuPHz1/89FL009Gzo5OAU6u7g5e/mbm\n        1uYmDpFxbO+AUDtnV4+gWP/QZM/ACDfPiMCARPegSEcX/5dPPl+8cPfasxeXH77et1d/7tyFa1dv3LRj\n        x8atOzZv37t738GtO2Fjx5btu3cf2H/w4N69ew8cOHDk4FH9w6fPnTl//tiFC1cfvHr29umNO3fMv9vY\n        WLu8tjC1sHc1/elw9vGLuy8++PgH/TK3+2loYvXTxtTU+ZedY2BoKCuVm8LOTkxh+4fFOroFhATGBfoE\n        RYSHJySkRiamRiexouKTXbz8goNCY1lprp6RvgExkTEpLl7+bn4BIUHx7t5R4dHJrAy+rYfPW+MfvmEJ\n        HqGh9p5e9s4BH77ZvHhlEhQQ9OLt14uPXz//ZHJA/8L1ey9evv8xbxEhABTjWICM8IRKXwWd6ZTvhUQC\n        CEROgm0sZVUFDkAEB2gGfEeJjXCpjgsuEmcL+pFQVo/vR2cI2gSIp5gqCiQx7t4Z34n+buQbTAfCYCxg\n        OoI7noB3IBVVgO/AT3gOkhB8/l8jgNAPSUsFmwVlOynXIjXAmLWJEyPBYWJnUA56QhvorCdeI9wmrnx8\n        ELrdSRNmmDM8XV0D5NlMrcmzNHVmwJ11pkzX0JqMPwh5oqIiLlsGF2LgmhSUodGDHiTCXljKgW+qiBaA\n        EkZTMBkUm0NMmDBhzeZdJ64+UNWcAq/8X4iHgTlUqP2xfzWxDIiHjdgBapratDffbF9/s/n42+ujla+B\n        mdM3O883xua6cxcy5eR05y3ac+yC/qXHnmFxPf/zf7xjUz67Bt68+1CPRlsoO2EWyn8AWZTkAIW6xLOx\n        hEJVJYRRCscB9IEA9IjGB0hF1zmBORT+8hgkmAscQC4B+Q8nAAgCklLEAEC8AvbLMxfLgyTHfHlcSF2R\n        uVKBuVmFuXUic6OS7EIFDAgvpgiACP9lCngCYDrQCYx5E2grFWXvnDrz7c27a1s2rGfSptBoGhNoWgwZ\n        mAacAEbDKuKhAtJaqYwlviDnEcqx2I0JtgUchfdCLU+MFZgehfvwCvAu8F7IUgpoH8DkgajgWtgPgA7n\n        wEDoB8qBo/JMgP4pcriWwAxcK0Z2qjxDHQvE0Dukjg4iTBiFDWUmQ0UWP4kFgOn/ZBsJAEEfoF8WVD9s\n        yxAvECEABl1mwgR1BcWnelPWTNZaOm3yxtlTn61a9mLvni/3Hzp/+JTi6jpcKZY2VPRUVPQ31Pe3tw9J\n        +4b7B0CkS1tbh3q7x4ZB9Y+NDgwNdnePYLcdTPAfGxoZGxwaGRhENxGcPzA4SiIBYyMjf0ZHx8b+kDhw\n        H5DBCLp+YIyMjpIYAG6O/fnrP/3dve31DdLuzn5pT19vV1ttbUt1ZQ/gf1NDZ3NjU0VFoUBcKBSUZPPK\n        +DmVxfnVlWVFBbnF+eISoaiYl1MsllRh01BxHl+UzxeKWBlZmRmBAV4xQcEhnv4pcYlxESG5WYLcbGEO\n        J7ugWNIp7W6qqqkqKa8or5QihQ22tnYVF1RVSAoyfH0iftskO1tw/X4nOfwSuf0UfHnFef0i7vJh/927\n        ffbsCz62L+z4cdZJ/ZgTe17s3LZxyXLdmbrTpszSnTln2nS9efNX7T568sabT1/Mf7//8OPd199vzcwM\n        3v0O8Y8zt3bxDQqLCIqPDGG5+4WZOdrn5ktCw2N/OXgnpbN/fre9d/3zzXvvTt1+sGL9+gVz5q1Zu2X7\n        zgNbd+3aum3X0WPn9hw6duDAwZ27927dd2T33v0Hjh7bf+DEoX0nThy/cOLMqSNnT2/auv/iraemzg6W\n        vx3Mja28vYO9fEOsXVwtbG1t7Ly+WHl4BYYkg86Pj4tNSAwIjHDx9nP08/cPiwyLTAiKiYmLj42OiA+K\n        iQuOjgsLiw8NiktJz/APiQwMDvYJDXL3CwoIC4+ISgqLSnHxC/YICHR38/T0CfIKC/EPCE+Oy/5t6WBu\n        ZesWEurtG+oVEOrk6PHh0w/jn/bOrt5fLN0u3Hhz597bs/df3r37+P71R7pz5tNkZABJAZ5QqyLCIsgC\n        H8AeVKyA+4QJAFsRhRH9MRoMup4S+ATl0YGDcpvK/CHJ9TBgG8Aa62yxMQO221Qbj2ciPhLljvFhREkA\n        X4w3YDYOevZxeWGSVYl5PoDXlBGgpoQiGq0TRSWSmIT6GglAGeO3mG9D3PFwMikdQCbAm6sTGwWL1wDu\n        4SgW2QHcoymA1gxwG1gSCNkYd4UH4bPwchg6qhoYydDQnKKhPRmbiapjzg9lfOBsCQ9h4qkGVqjBo8Em\n        gJlgi264ORVbJtSCthSJW8AJQAYyMozVm3Ydu3xvkuZkOAehn/r1MJ0UG8MpT8R+ecBz8BNhAqsWVoeR\n        GMA3WwNju9emzo8+/b5n8P25oWUYO9PeP1R3/mJgcp0ZuktWb3f1CRn55x+vmOSPbgE37zyYhXUAEwD9\n        dYkTH/B39r+QjT4QIvYXkQR5wHcQ74Dvc6ijuHgWgiOcDOhJYSig5zw5jPEuU0IagLvBHYAnwHQAtAVq\n        mYd5kyjJQXcvUAKRjqAM0LxFmblJWRYEPrpfiPEBBAC4vwHDA/CVOO6JW2YVnbZposI1ff1v7z8aXDi3\n        e84s4ICJNJoqjTYZV5NHDoBPMCDgEwZgOkwbrIE1Shj+xdgDynwwEdBfP1UOQHw8XRWmB3CPL4hiH1Ce\n        RESIvQI3AXIC3tKVZ4LdoMmka5ML4ZyppCAA7AMdkgZKlf6qwZClq8vRVWUxAKCGXiDGRFk6MIEicfdT\n        TCAvi9pfnsmQk4GdxCYYjwTQ6RMmzFRRWqGlum2K9pbZs+6vnL990Zxda7b/eGZk99kq1cmhjZfeW14m\n        ra7vLK0Y6mgHlB/o6G6va+ppBTKQjvQPwJ7BXulgt3RI2g8bw319sBMpobOnv70D5D/A/djQMFDF6NDw\n        n+Hhv0ZGx9DjPzg8PDSK1sAIgP7Q8OjoIBDA8OjYnyHpQEd9U3d71/DQ8GBfX1cHrgXWXtvYVFvb0dLU\n        29zaXFdXVVZSIc4ryxEWCLIri3MKRHwBJ72quFjM47MTEgtFORUVZVUlxfz0jPSkpKzk9Bw+NzUhMiY8\n        JDjIPykmjsfiCNjcyNDopLh4iUDQ1dXZVldfmJVVV1HR0d5TVVlfWVGdx+GLo2Oy7X4kfnmbYPvD78Vz\n        13fvIj0c4r2coizMsl/di31yy+XC5dDD+v4njkToHzDbs33L0mW603RBkWpo6ixesnTxvHlLF68+fuHu\n        g9fGrz68M7Oxum9gYmZt/9XC0TskKZ6THZnAiYxm+/lGBYfGPzJ4//rzB6FYHJ3K9vEPjAxLNP/p+uGz\n        5cZte6brzl2/ffeWvds37DqwafOuPfv2nbl4/fSpc4f0j+08sn/r7r37Dh06dOLkwcOn9+0/efzMtTPn\n        rh08AsfvXn1qYOPgFhoSaWfv6OTg7Oji88vDzcXd0xcgPDgs1Cc0KTUxICY6IjE5KiUhIiYhPjkzJjEx\n        ODIyNjElPik5EpghJdUzJDgkPCosIs47KDKelRIWHe0fHBMSkcJmZ0VGx/j4+YZGRgXFJfqExbh6BXl6\n        hkaksh3cgt1c/f1DfC3sHX799HT1iHL3DrJzc7b1dvn42+KFidmDe89vX3968+nbW4/fvHhrpqyuSQex\n        gmk/VL8HzPkB9Fck2IpMADSAi7aTDFFME0LQpJQ7dtYkPhbUsKpoDVBMgCoYBb6G6iQN0PvYXwGXvtfW\n        njIN/u0g9KMXiGhkNA7Q0a9KOUwoVAWljzvxPiQwoI5aWwVkPoprRH+kKDRK8FaYd49Qi5UK2FwPoBNt\n        F3QcYd0AYC7BZYwhE1OGNLEAAoBPwgrwOjhVuBDJg/AWGhyqaiRooa1G2kfD9NQ0NDW1MaaNDAHCHMsa\n        YEr4g8CZqmowSeRO+IooTyIcsEHYi/w4VMCAmDLwa8vQGas27tC/eGeShg4hANKACGU+qn6YOTwFqA4G\n        /KTYUQMejUXCaAHYvDNxeG3qeu+DxR0Dk9uvjW39Qzv+/p9fLt4KEwEhafKKEy0dPQf+n398YlM+uQbe\n        uPtoMo22WH7CPJL1T+XMAKBTahejvkwsp1qkzJyjiK4eQFKESBJZBZQExIdPgEgM8BLXEGp/ovGXgN2A\n        gVk8BzgA7omGBWkZpEd8TXA+7AGsX0KMgLVKzE0TmRtUmMAByzFJFLU/cMMGFfp6vBX63wGy1yvLAo6D\n        HbCUTjuydo2R0Q8PF2+D23c3z5unRqPJAgfQaID1wDELkD/oq4j5gnxGyANwHyYD9sFK0u50tiJ9KnZq\n        QwLQkxsPGADWw5zBLCD1wLjsO+A74STZBTgNJgp8JkODydCUBRoA6GcC+sN9JmPyD0Z9QfVryjHhKDCB\n        KhNTgNTkmDA0ZOkTAfEZwAEkBgBGAPIBXYEhI4esQPWHgK8YAIB/WQsmKW+dorlwss6eeXo7Fi+6uGbl\n        /j27v3/8HPbxV5y5fVtWVk9p2XBzS70kv7mk4q8hEPs9A23dw739Q30Dw9J+0PhDsKezEztD9EgHe3tH\n        +weGe/qAAAY6Oge6e0YB1ilwB8QHhB8aBQ74MzY2SlI/ifDH7qHDA8OwOTQw2NvaIW3r7IM7kNah0p7u\n        jrbWjsaWtoa69paW3s7ubqADXD2rsq6murykpKIgXyLi56XjEroSXnZaUqogI0PIy8gD7c/LzhVwRbxc\n        IZefm5mdlpwUEuWbmsbOyy3JSEoP8/WLDgnixKaIeIKmpvoKobC2traprqmgqKimsqYwLlkQ7FOUHMyx\n        tAp8+tT9zDH3M2c8r16yOXXC8Ogxz/M3wwyeWN++7rL78PX1G/esXr128ZKZ8+ZO0509dZrurNmzNq5b\n        tXfzlt27dl+4/PzmNYPf1i7m9k7uvoEmljY/PT2+WjvFRMRFxiVGxqRY2nuYWnoEhKY4ewf9dHIPiWf5\n        h0aHRsb9tHV29w398sXi/XvjOy/f6J88ffzstcPHL+w7fPTA4VMXLt88fObs7oMnDxw4tffg0f2HTx4+\n        fvHImbMnLl69cOP+g8ePf5hbvDIyMvj8LTwqNjg6xtPLz80z2NMv3NLOIygyMsDPixXPZmWyg6JCY1OS\n        MoWiwuLy4tLS5BRWajIL+NEvLD4iIQn+Z+PiGRUVlchKjY1J5aRxUzmc0Ni4VE6ml3ewra0TfCaxOQFh\n        iQ5eoS7+/r6B4X7xcT9cnQNCIm1dvUzM7X9aeTp6hHz47fjTxdnEwuqdsdWtl58evHp36dq9Qxcunbr9\n        6szNJypqanKyckgAEycqKCqRggDYBqwkWIZyldQukcafGBsgMQAQ9QCL6lgcO778Ou7R0iKp8YieiO+Y\n        IUoqsDS0UcnCPyZPI2XDGiTFBQZAMLZfhjuQRFJU1jCQBhA60REPOzEegKyDgI5Qjo4gAuL/mhHIHMSt\n        j24WRZg/3AH9ReiwQr8Wgin8EzkA3TVwLbqMAMoBteHFcRvQGTEdI9XYiQFogFgPMGd4L5iGKqaQamPO\n        qNZkdMtQPhmcEuFCEr4mb413himR35NEJmDCSJxqaupghcDLImEoTZrEYDBXb9px9OJt4BiYMJXqo0rW\n        fkHXP1YnYGMJ9ImhJwoPITmRZnBIAO9/eT01sn1i+PvJVwsDc9v2P38P//PP9UevaTQZgJWr9x91/PlP\n        YBLno0vg1dsPtAExFSbMJT2fQfYCOAKaE0DHPVOI338uusUBxzHrX1cOUzPRUEBpjPthwPkA7hhIIBFj\n        zMcnHUMBecFcADyF26JxoIjAiheihx3TTGEDv8qjPN8+CdAfYRrOhDuAWgf5v06JuV5RdrkSIu8SBeZG\n        ZdnVIOQVmYuYtNk02vr5816/eOfjERDkHWD/zejctm1TaTQloAEZGtwW5rmchBBwrRtsGEdfSjgJJrwS\n        E4cA6zF2DTIfT5anj5ME4TOYJ9gEMLSIrocXmS+PiaEz5JiwR4sEgdEOIBxA1RCAiTNVDjN/CAEgJQB/\n        ABMA9KvLoncIhhLx9Y+jP1NGkSEDcE8IgOxnyJAxQZ5BZ8hMACFwYJrm2mnae+bpXly54NSmLV73b3p8\n        N3L89CvMwr2Cze3MEw03NVZKCgp5gsHuTvTj9/Rh+09p33AfqP6+ERhSbAIxRFo6Yy+gvn74BP1OujCj\n        t2d0dAzQf3R4BDlgdOTPnzH0HQEHAPxjN7jB0T9/+jt6AP0H+/ulLe197Z393V0DcPnASGdbW1tzY1tD\n        fXtDs7RH2lLdXFlY0dLY0FBV3VBeU1lYWllUUi4uKuCLSnJFogx+VkqmhJ+TLxKKudk5vCxBVpaIy81M\n        zkiOjedxM8QSYQ4vIyMhNZfH47HZmUlpxXmFDQ2NZSXFja3Nba3dLW1tLa3tZaL8XG5GdmBg0tu3SS+e\n        +F085XTicKD+oS9LFu+bOf3ygnlWG1YZrV5+b87cDdOnL545Y/Ps2RsWL5izaNHseYvmL1y8dvW6fRu3\n        7N687fKte08/GH/98iM6JlGcl2/vEfTLyjEqJh4UMihrv7BwMxsvB/9IJ3c/VooomcUPikrhCvN9/Pwt\n        be28/INiojLiItJcnPy/fbP+/PnHnUfvnz5+f/Xqve3Hztx+/PrNa9OHD9+eunTj+NlLB/TPnj578sK1\n        88cvX3rzydDcyt7Dzc/e2cXNxyuVzUlMSoERFZNqA+ZHRHBiIhhEyVnZOQD74iIJnyvMEUgCIyJ9giLD\n        o6PDw+MCA8O4An40m21j55WcyI5PYcfEpkdGpEVGJ7lHhNh7+Hl6RTq6+nqHRnkEhQWGxIRFxrp4ODj7\n        +JlaOjk4uXoFBNu5+Zk7uBh+t3R29bN38YEJvTAwc3cKfv/R9OCJ8/uPn953/Ibhd4+jxy8y5HGtR8Qp\n        4udBgYz96AE6sWEDACvVvIxyB8FR1NcAx1hzC8iI/h+EP1zZUQsDrRpESoPIVYZrwSZARAPtr6aJjRlQ\n        WRNPEQhe2AYoB0MBgBjxl3RVIwMdOCilESsRTDFj519sJQ8FpAbARfcLYDrFN0gASrjYgPy/eaIwKPTH\n        nHr0wMBbUKUDGHYmeA3ASvAamAZXW5yMNWJohWgQtkP4BtBH1J6E629qIpMBTGtiZQPQA9oB6pM0sSco\n        +U1wDng3ipbIOvjIPehxolhBXQkmQNhIToHKAtoLFgDQCRIA4r6OKlnJACPA8CBVrDNQRA6Am4NpgmlC\n        qlQ3UANj+w+/PN+YOr80sn5tYvfmu3UQO+vvf/6RVDceOXMDOEBzymR7Xz/f+NQfgfFXb91Tp9EWKcgA\n        ak+VxV4OgOOAhpRkBqwEAvi34Au9Q+jwIcVfiNoYI8XQ8UxZrPuFC0FEo2sFOIC4X4ADYP9sskgAni/P\n        hEOLlND7D4i/hFQALCJ1trPk6QDHmyYylikjtcwh63ytUkZWoLr2b1SSxRAxKRRYpYgtPJcoyc6WnTCD\n        RluirHB4w6a3j56GW/zI9HKx+/Jx17zZwGqaMjLwdHgQcA9FbGBPwA2BAxZRyabEO4RxXXgp8jrwyshn\n        ZAJwCGwggPWpxK1PYsIYn4CdgOxAAJNR44MpQAddDwwBZ8K18An0MIm4fXSIg0gb0F+OrsaUmYR6H1Fe\n        kQyygXAP6C8Lkp+BZKBIJ3xAp8O2LH0CbYLM9EkqB6ZP2T195vtlC/ZsWvv20rV8G2d/K9sAp6CKVF53\n        aVFXWVkhX1xTWNDX3DTU09fb3DLY1TXcJR3Gxg+A9QMjfYMo/AcA6weHOnsHe9E7NDowhH1+pL1jw0N/\n        APzBeujrg39gHBj7Ag2PIQeMjQyPoRkATNHYDCcPdkulXe29He3tDQ1dHe19nd0dDY2tDY1tTY0dDU1d\n        LZ3NjY0tLY0dLc1ACc1VVVUFJcXCfD4nray4sCK/iJuekRoZxU1KSY6P5bMzksKi0xMS88X81NSUAI+A\n        9Hh2cmJyZGgAj8PKKSxIjk8SZmXXNdQXFxZWlJd3NncUcEUNLa0tzZ2FmdysqKC0nz95P41jn18NvaDv\n        efyA0YY1l+bN3j1/5oVFc1/Pnn9Pb/rF2ZPPz5x8YNrkg1N19HWnr10wb8GiJfMXLlu+cs2OjZt2bN13\n        5d6Db/buZ648srF39w6KNDayNP1s6R8QFRARZefqExGf6BYQ9sve09zS67OpbRI7MzIuJT6JkyMpYKWl\n        paVmczMkzm6BdnbeEdGsAJ/gr5+s7W287FxcHhh8/G5u7+gc/PW3zQ8bp3evvxw7eVH/9OlzN669+mho\n        /tvy0ev3dg6uwaERzk6e0bEJmZzM8PBod/+wmKQUXnZWSlJyWExsUjIrI1vIE+YnJ7ECg2OCoiJcggMD\n        o6IS4lOzMrJiWIlRSWnJiSle4SG/PPytPQJCohPDYhI9/UMdXLyd3IP8Y1Ot3X3gtSJjE92DfT3dPWxt\n        3O1sPdzcvM1+u7h6hdm6uX77YW5iZWnn7uERGPbV3O7da4uvX98fOnfy9PV79598MHhnfPLMZZoMHRAT\n        4AzhGCU/anzSngG98MAKCKnE4Y7xADgHkR1gDtAcsWwicc0DTAMsak2eoqoOewDTcbkYAFD0CGGnBFyP\n        BaQuAisFixPVsDcO3A6XRkM8hT3wDb6D5Cf4ju4gmBiyDqbkw364z2RN7Wmak6cCT8AkEeKxfQXcEI0G\n        ipxgD16FDdcwegE74Z6wATvBLCAnI0aD3gdMp94CttU1cBlhyvFCqIu4uSZpwhMRoMk7Yk4RLnCmiaCP\n        FoM6laCJNyddNOAngsuBCfC5OIhLCqGfPBRvDtOA33YSEJUMnblu2z4kgEnINyDtgQMIDaCrB60B4ANc\n        oUwDO0OgSQTWBgZRaAbfbDAO/N3ppbHDs6+Wr03t3v2wuf/OOIYn/vPPPzEp2eu3Hpw8Y9a8JUuOXrhi\n        G556985DTRptgbzMHAVcsnEqE6F/FkhXJtbxwgYBQcz3nzne9w2PAg6CUl6IiIn7Z8rigEMEu8ejtTAA\n        7meRYmDQ1NiBmaT9UJJ8njyunQt3QC1PdPdCBczlX6vCXEGaOQM6ryDWAIZh5RlrlWTBFIDLgTDwkzwd\n        SGs+TEmGpovFzDLr5WhP1y/NjIzKiIm9smMrGAGaMhMA3wHQ4RNeBK6Fp2NlA36ifwlwfwpBeWAgDBXA\n        61DBDAWwZsAOwDpeou6Zs+Qwpg2MiPEAEgrWkUNfEMA9cMAkpsxkIE5SRQF8QEq9MBSsRbQ/HFXBQfI+\n        ifaXZ9Jl6YD4dGWC+yj/ifYH9Fdi0OVk0AWkwJhAl5kgq6y0UEf7gt7MlTOn7Fi37vLRc9b37me4W8e4\n        hUhiYtrzi/rKqzua6nvaW4e7paDN2+vqhrp6h7uxG+iwVDrY1YONoIEApP1jg0MDne2Dvb1DUlw3Zrin\n        dxQzRAfHhobGQP0PDo4MDw+TptBoEIzAoALDfw/Bnbs7+zp7+tpah0aGBnqkfb3dPZ1tnc1NLVX1bcAB\n        1fUtNfW9A30DA0PS7p7mhrq21uZWIIPqusriwlxBdnFeTn1ZdUFeXmKCb2SgS06moDS/sFgiyWalZ2ew\n        4iND48Ij2QmJQoGQz+cJs/ncbJFILMkXi2vKKnJ5uXnigqqi8sLMzOrq2vb2zubyqqKYyORXH9gGLyKu\n        HnY5tsdw88ob82fvnzXzkJ7eiflzzsydfWTGtGO6Uy/oTrswe9rxGdNOTZ+yfbbukgWLl69dt23HoXWr\n        tm/Ztu/tOxPQ3Jcfvn5n+CM4NtHSyt3Y0Pa7pZtzQLiFnYe5lbt7UMhvRzd7/0g7b1+v4AhOVm5UAiue\n        xU5J4SSmZvIFYhY7KywmOSUlMzEmJT4uNSgoIiQsLCmJ4+Ub7ukbHhiS4OYT+POb1fNHn85ce7jn7OWH\n        Lz9+/Pbzp6WtpbWVb4B/SHBMYio7IZWVGMtKjE/jifMKC4pK8gvTMzhxKSmJqVlxMWnWTp5mds7xrLSk\n        DHaOMCeLzw+KCA+JiwkOjfXxDPrt7OqPhWBsmAlgvbe/X1BYlItfuJN3kIunv7uHv29AuLmLk5t3yC87\n        TzcvPxcXT2tbR2sH7+Dg+F8unr8cXYzMLD/9trH28r/+6NmXz0anLz+59tTw3deP1x/dWbN9N50uC/iF\n        eIqpn8AEKJxhoMMEI5YIwYDUlP+EMMEkbKFDMvrR14Fp+xjbJLFWHeAMIABVNW0N7alquBwYevYBuzW1\n        pyhP1ABjAu4GjELSSQEWNdQA6TD1BT0wBD2xHJfywBAxTsiG6F8ARzWtKVo609S0p6AqV0asRz8VFbbF\n        +eMr4OTx/soIxOiFx7xMypIAXqGCwHAmwP3kqTMBwYEDsI+FhpYq2ChYf4t3A/BFU4YsVInXEjMFZ4J3\n        0IT3UteegiSErw+DlDVggAG2kUSBZmAayCIwBzIr2CD7cSEErAYgaaDrt+/D9QDUKP8Yhn//HUTsa+Li\n        9ej9J1YU+SUJAbw1sn3x2ebR+1+PPlk++mTx4pv1RwvHq48/3XpmWNDWPvbPP64+YfuOX9CZM4dGox26\n        dPPoYf2ZNBquBUbyPkHLw5gsi4hPNW0mHvNx/z4GioleBkyfRfQ+cRNhbIDqAUf1fgBcXqaEBACACCeA\n        uYAynNAAgCyYBXAU1DScBiCOdgCF5gq4SO8mFRxrSBYQxTHIHwpYmovuJhJ7gAFkM4NMBuYMnzD/eUza\n        NBpNj0Z7duxIRFD4vfMXp02ggXEzRRZPAzMFl2kk5IQFxlhtADTAJAmdmO2jJ8/E5Fc0CEhlABXZJnVt\n        UzHPh4lfMd0TP+co0KmEH0B/zPSXBXUvowl8ib2PGBpyQAB0NawExm0SB6ZPxDoAujLJB4VPRTqdSbJ9\n        0AWEXYDAAkDoxwZBGAYA+Q/nyDBkaGCdamhp7tWdsmX29OWLlp7devjttWusyLBKXi4vJr6Bwx9s6hhs\n        aRro7kCnf5+0Xyrta+sY6OwZHhgYGegf7O4Hs2Cwp3cQQwLSkcF+MAuwwqu/f7C9s6ehaaR/8O+///7P\n        n7HRoaFh4AMQ/oj98OcP0MAwtghFL9Ag5he1DvT2AHkMDwwO9Pd3tbT2dHUB5ne3d1WXljdXVXe2tnX3\n        Sgd6+8ACaKypBUroaGlta25srm+qKCgpEeU2NTSK83gBLtbcVFZJYX6xJC8rk5MnEHGSYvNFXIlAwElN\n        4GdkpCWnp7HYfIGwNK+wNLcwi8MpyM3N44oK8/NxgbDq5tqqqtKk6LRPb3xv3HI+edxk04arixbumD19\n        56xpe2ZMP6o369g83R3Tp+nPnHF6ru7ZOTMuzJmxf8a0lXqzV6xas3HP/k079m7ZvG/Nmu137xu4+gaZ\n        2Nj+dnZLy+QBSsYksHxDYnzD431CE347ejh4ewdFxcF/MilsjoW9i19QQna2MDwm3sU3Ijg4JtwvPCOT\n        lybI5nF5WVm8mNTk+GQWi5WWnMLm83M4Aj4nQxQUFu3m5vXxneG9x5/ffDR9+OTp/edfHKw9/Xw8Q+Pj\n        EpLZ6ez0goL8QklBfm4BVyBKTEnN4mQXFBYmsTJ8g6JCwmJj45ODo2NdPHz8wyPj4mMB/eOSsoID4ty9\n        gpzcg5PZ3PCwsKCgEDsnX2f3oKTULFt7P4MvJj/MbcJDY8PjYt38/D2DIryD4+1dfZw8/SxdApzcfGyt\n        3Sx+u9p5+BlZObk4eL99Z/rT0dvE1cHg66/bdwz2nrn66N2rq08ezV++miGngCntKLdBnoOsxq6foFUB\n        uYhcBaTGNQAAuRRxGwQ1IimgGwIcLvdIwS6YC+pY7YUOcURwdfRjTMaU0EkasK2pg7kuTFl5BlNOHm5K\n        kjUBXkkMGf1IlHeFPBfurzVJFQgG4RugUEN7CoxJoL5VUXGTajIKWDEDB84HJgBegTkA4pPoqzLAMZH5\n        pE+nBi5YBo+AoaoxBR4HUwVg1dKZDlAO0wBwBzTHVs/AOqjrYRpoCoD8h/njfNAxpYlArzRJFU2W8QgB\n        +cVgJmoK5LnIheR3gLfD4i/8ZXCehF+RVxTB7iE2DfwCtAl0sABOXX+sqjkFND4BfcT9cQLA7E/c/tcU\n        GCcAdU0dQgBfrG48M7z+0vjp199vTB0+WTjeNfi+R//aJwuH6r6BlsExO7eADbsOAAFM1Jkyc5buVBoN\n        UVgZs31myGFlL+A+NaaTNX5nkwbLs5AbUObDzikMuhZDRoMhA1QBlwDIajFlYM8UMCAIyK7E1dipaCr6\n        jgC7YXseyRwF3IdnUSAOUno+1asHF21Hp/wOFeaWibKAznBoHmnbAPcBAqD4AC6HAYYIQDlAPwA3uubJ\n        nUGwz5FnzqbTNqrKP7t+/bT+Sa0JtEkkL2g2Wh74IHgKljWQEgGYJNwQ8BoGvKOuPFoDsIF7qNxQcnPY\n        D+gPD4Kv1JkzMOTLhG2wDFSJ/we0v7osHba1ScQY9qgwqcwfPKoFn3IysA2soDyeAMogbh8ccnSQ/xgB\n        BjIADsBaMBINlmfIgBHAgFeQl52qpa2jM2PLzFlbFy/csGzdlT0nPA1tqtOz6wXCJm5uRSa3USzqrqge\n        aGkf7OoY7O3ua2job24b7OrFhQG6cTWYob4BMA56m5uxOzRofKkUFwru7O5vbwW8x9xQbAUKBDAwjKuG\n        4cKQI7gTD/Z3dve1tA8N4NGh/j5pR1d3WztQSH+vFP4MDeKa8+2dbV3tLY3VlZ1dHT0dYCtIe9o7Whvq\n        6quq2tta21tbK4qKastLulraaiurMlPio0ODeZlZpWJxYY4gITYqMytLwM6MDAwKDfYv5ImFmZmZ7PSs\n        tKyy/LIcQU5WNruipKiisDxfIM7LZBcIuFXVFeXZydnf39kfPGC8e+eHjStvrlpydL7udr3p62ZM3zh9\n        6uapU7fOmrFvjq7+vNknZs85rTfr0Oxpq+bOW7lu17Y9R3YfPn3gzOWNO/Ydv3TD+LdLeGyMtYNTbDTL\n        xSPQLySKlZEVGB5l4+oTn8YBOR2dnOpo62Vi4uAREWf60zUkJC6vsDwmJTMhgRMSkhAYFuPtF5rKyigp\n        rUlK56ZwMnnZeZncnPz8grziYkl+SWlhcVpa1i8rD2NzO1fbQGcHt2/mVvaOwX5BsZFxKalsdkZmNp/H\n        zcnJBRbgCYWxCSlpnCwwBLL5/NjolMxsUVFpSTonMykhNSAk3DPIPz6d7RUe4+UTFhISHRWV7OkZ5uzm\n        Y+3i4hcWGRwW88vGzeDLD2cPb4/AQHdPL1tXd+cQP0cv928/ftg7uNr4+jqFxdm6Bni6I0kY/XS0dvKx\n        tPf6be35wdz6o53je5Pfrz9+3nfi9NlbL67cfac7ZyFTTgHgBoWzojI2hcboJSp9GJRZAIO4a0iKC7am\n        wS7HJC8IPR5oFpCcHMyCx4Y8mOWCaP5vfqcaWXARJDbAMZwGJwNDqJJDgMsAowD3qphtCfiOvnIs5YWd\n        JPkHrQF1LU2dKRpa04iJ8N80TbQ8FIkzCuZJdaoApAbNjt0XFLFMDKuUcXVisv6Xlo6G5lR1rankKZit\n        BCYAPALOwRivOjAETgDmD2eqaU0GDgC2gIlhsJoEeNGVj8EADVzumJSA4btTrPlvuAJnhQlI4y1OqZ8I\n        jipgCyCgB6QK/GGVVRQUlSbIMJev33ri8n2YISEACu7JoDbGyQD5gDwaM5Tgl0QCeP3N7vKDT6dvv3r2\n        1crY3ueng+uLLxZHzz86cPKWpXdQ05//FDe1f/n2c8W6TSpTpjOZcso0GvHIo+gGgNMmTn+U80TpA9TC\n        UQBH9AiReisAbpD8gPiaDBn4nEYWBdMEAmDKADcAQKPKVsIFF+eSbsxzSXbNEizoJXcjZADgi4EEso0u\n        HQR07AmxTpmxSgXPnIXEwNyqLLtZmTkX3UTMlRgcxvQhhHtCAHoKGCqAbZDhsHMxrv9Fn0WjHVyo9+L+\n        o51bd2jLyWnQaFMZNLgzQP9yZCbmYjKTuQrIIvCCAOUU9E+VQz6jsJ4acHQmUgITtuFxYBlMA4tBlqkp\n        i+4y+FmmyiHEA+6Dxldjjqt+dSbqfRD+muQoWAZAD2AlqIFlQErAAN+ZdER/QHwkANxGn48cnSFL2gEB\n        GcAeBSYQwAQ5WYa2mvpU9clzZ8w+v2nDgxP73pw9b3LkbvDLn00Jya0CXlk6u6OhsqehoZEnbM7JA/Qf\n        amsblvb2Nre0SgrbS4oHOrsAzQe6ewC7exqae+sa+9q6els6MKleKh2GT1xBvgtsgLGxseG+gf72jj5c\n        WLgHw8J//vR39khb2+FrX2dHb1f7oLS3r6t7CJsEDfe0tna3tIPdACcOSKUdTS31FTXlecUNFdV9vd1t\n        TY3tHW3dHd1VRSXVFRW1dTU1hcWlopy8PFE6Ky0jIbVIlAO4nxARxWGlcVNTJEIeJ4UVFxqZyc7IYKWL\n        srOL8yS5opyaqsqSnIJ8fj6fnSZMSyorLSnOFmV5O6Z9eJFw+6LviUMftq69uXbp+UWLVk+bsXjK5JXT\n        J++YPnmP3vT983T36uoenD3rzFzdawtmHV65bPWGfRt3HT5x/uq9px+3Hjh64ORJQ4tfZpaW1tbOgUFx\n        weFJn83sfOKjg+KTXLxDnbxCvEOCA6MCouISvv12N7VycXD0cQ+M8guK8fANj4hnJaRlpGfy2Kz09CxB\n        RoYoX1Kem1fAF+SIRLj2ZW5eXmlRWUNNo6SgID6VGxyX4u3j6ebj5xsQk5DACo9MYLFTxGIxjyvO5gn4\n        QkFuniSvID9HJObweGk8YX5hQU6OKDI6PSWTJxLlsNN5CcmpobGxIeHxIRFxkfEJAYER3l6h6ZmZXiGR\n        FrbuPqDzYxJ+/HJ0sHMPQZT3/f7991djezM7p69mpk8/m5jaeHn7B4TEJjkHRNl7ebp4uhv/tLF28TK3\n        83j3ydLI0NrI0v7h23f6Fy9evn3v+QfTc1fvaWpNk5cH1AJ5C5iF3daUsCQY155E/wkm/GBCi7yispy8\n        EiIdBmPHU92RM6hPTG8nLRA0EBkBgtU1cBEYEMsA9GgKgB1ACXA1QPOpVCIQfFUjfTTRdJiERgBQC0Aq\n        3AGOTsSecWAWUGuw6GB/fJJVSWCX6G7SuI1429VUsGiLku3oQVKZpK2mCZyBy36pqU+Goa6tg8uEgZRG\n        jY/3B3hFL7+6prqWFilmxjUjscsbGi7jG8BDQELEO4/sRR6EVgVuoGMKEZ9APAF6DC9jPwz8DXGGuIIC\n        /pKg9/HXU6TsJ2wNBBaDorKMDH3Vxp3HLt2Ht6MI4L9ifzwGgAMmjF8p+2ASrrJJCODdd8cbL0zO3jF4\n        +OGnkZ2XpYv7OxObC3feHT53R//8vVB2VuOfv4vrW9jZgpNXboIdMIFGU2FMmEXW1EVZjXIekzWnEpcO\n        wCsgHeyHEwC7UXoTaQxAOZ2cM5WcPEUWwwawR49UgVEefPic+W97tYWKeBXgJtwH8BcJgNx5sQJjLekA\n        ijKcNONcSUqIAdwXktSgVehNQtf/UlyWEq+C0+ATLIlFuGYvwrceWVgGuATwWk9WZiWDdnrV0puXruza\n        sV9v8lQNOuaGwn64yTIS+wVCQgIgeU1wOdwNtuGNAKyn/jtJAH2wA2AbJD/cFkyBWfLo9Nf51/MDO4ES\n        YADKqwG+k8AvVgAwGZOYiP5ApQD9oP3xKPELTSQxAJT2MsgB2AQUcR/EPup9sk2X/fcT7QAZGSaDrj5x\n        4nRtHe3pM/euXe/36L73p09eZlbxP53zw6I7q8r721oBx9tKSqozsrrrGnqqqoe7u4f7pSODQ50V9T21\n        jbi8V9/A2NifrrrGgc6OflDkxWVDvX2kMHhwuLtnoL29v6v7j8urRwAA//RJREFUz5+/KA4YAXTv7cM1\n        YeD//bhGGIA7yv9e6fDA0OjoH+wR+vffA93dYAr0dnVJe7ql/X0dzS0dTc1t9Q2d7W1NtVU9YF5I+7s6\n        O9tbO9rbuioKSooEOfkCYV1DbV11dVpcQkJ0ZJmkmJuWzs8CuE8szs+pq6zLz80HgyA+MT4zIy2bnRLh\n        6wsWQCFfLGRz83IlxZLc/HSeIDKaHxmZFx0isvwtMjOKuXjCeMuah6tXXVm2bOPMWUun6KyZNnnTjGkH\n        5sw6Oltv04wZS6fqHNWben2h3qktazbt2LVi054LN+9euvngzM1bb94Z2Tu5W9o7OXv5JaRysjNzolNS\n        7Pz9WWx+cETcFwt7CwfvgNBYP9/wqNjY39ZuFtbuLEFObDLbwz0iMpZVVFzCz8nhZGcVF5bxcgTpXC6P\n        Ly7ML+GLchNSUgoKC/r6BmqqawtLS8ur6rgCSXRCXGxSYjKLLckFdshNy+SwWNxCSYkwR8jLFWWIhNnZ\n        /IrC0uLiUmADOBqbnBARm5yUxMnK4IpyxAJhfiIrPSI2JYMnTMviufuFOHgHp2RnpXHYfoERDl7B/jEx\n        EYksB2dfM2t3Cyvnryamrl4hX75bmVjZffzl9snK2cnFy80zxM492Mbd0zs85ruNk6mFlbGpxUvD7x8M\n        HX58s35p8Hnr0bP7z18+c/3+tn1HAVMAoRDT0duDXQowDgxGAApVBFyCWZQRoKSItcIkgorqGFM/Afjg\n        KjAd4EyEPzyE2ArboGFB4KtrYqx1EqkLQ4+/hraWDspwomfVVbEwGLs6g8omuAzaXxNOAxMB8Q5buekA\n        AYD+JUwD8wEhDCdoopWAqUcYLlYDlNcChtDANkFEcU9SJwv2orMeEzrhVoCqoPRxehjXBahFNoLXhstx\n        OXhMsacy/afAhRPBJsCCBnTCYHkXLjCAbzQeQMYF7uE3IbFlEqbGr+QTbQVsb0ecUbiTMqRUZOUV5OQV\n        APQJB2BWj7yCEgDAhp0HT159qKqBFgBOAIMcVAcIpAEc460gSHooequwExHWAbw1cXhuaH//3c/7b02f\n        frV8a2b/8MOP83fenLn54sDJ288/myWJ8mJ4uQW1LYLcgvl6s4EDZGg0NXSVjGvhaUyZKaTDD2A6YDSM\n        WQQoAWERKwkZAOgD3M8k6TGAyLPIUgGwE+Aee+8AXisxliqjroc984noHicAAvpL4FaAwnIYBF6vzFyp\n        gjFhsAmAXYAMVpO1vcAyALBeRpT7YkUmNg4CwCW4PF8eAwZwDoXd8DlNDl3wAOsYgZCbsFSGtnOKxtnd\n        u44dP7Nx/dZpamrqYArQacBPYEPAWEqWbp9BUj/hK/XuQGNAACj/5Zmg7mF7Fq5Uw5xBGsBNIwSgRdrA\n        aRB1j78JdodGZFdh4vIvUwkfANZrMOlUXdhEpoyqrIyqHAODwBjyRaAH+Q8EMC7/ySeQAYA+bFMDowLw\n        VUaGISOjpqQ0RUd7ms4U3Wmz7h+9ZPP6q4+Lm9DVuygosKWutr+js7+jo7O6tlGY31pU2ltfN9LbM9DR\n        MTY82lFW1VlePTIw2NfROTwyMtDV2VVTC5TQ19Q+1Nvf39nV19rV09jU29QkbWxGd88YLvI1NjQ80NGJ\n        QD8w2N/WOTQ42C/tGxocGujqGurr/+vv/4NxArAVgBG6e3o6OylfUG9P54C0r6GytqG6urena6B/uLu1\n        q6msura8oqWhvrKgsCRPXJiXV1lcWlNUJuLz8sW5JQWFYoGAm56emhibksKSiAuLJYUZ7NT46KjggABv\n        T19fFw9eJiclIo6VmpyVxk6MSoITarMThPFRvIDwuI/f/G8+Cjh7wHr/2pdrlr9es+zOovn7ZsxaM3Xa\n        1hkzTsyZc37+vAOz9bbPnLpvus4+3RmH16/Yc+Dwzp1Hjpy+duDCjX36Jz9+sbX77e7iEGDr4hkQFpXJ\n        yUtJT/fyDwqLTPL2Cnd0CzS19bS0cbGxcnTzCebmSFIzuVEJaTFRcTGx7MjE9BxxSU11AyszJz4pq6Ag\n        Pz2dk5qRmcIGM4ZTXlEBqF9ZXV9TV1tUXF5aVt7a3lVcUMHj8PJzQPULQOCXl5cBY/BycjPTuGJxfm4B\n        kF8aPy27sLi4trGJlZbOSuaU5ErAShCI8iqqKvgiMTtbGBKX4OrjH8/ipGVlBYVHBAUnxsUlsrIyvEMj\n        PAK8/YPDf7m4f7O2t7SxNbW0dfWLsrZ2sLR1ePbF1PCn/Q8nZ0snLxfvQFfPYDMbVzMrO2MLh9fffrw3\n        N/vy+8eX7+Z3H759aGBw98WHUxefHzt9TYEsVwvwrQByVUEFcB90MYYrKfxCfAeBryKvoCwHW4BxpFwW\n        sHsSnKaC2SyAd1h1BedjCFddVQ1X1kWnOabZYOI8CHn4CrcF/KL0NQYJcMkwQHzSOYfqu4DojFdNxAx9\n        dTVNbUyIJKszEqzHQCug50QAaFVt4ABAdrghwU3M0IcNlUmYOC9PljBTA6zE1CNt4uSBQ1h3BndTx6Uf\n        0e9POgLhu5AHYYUtuSH2WphEDBeYIVozpKMRshf5WdCVjz4ogu8qqtgUj6xHBveBo7ATfgEC+uR3G6+h\n        U5JXUJSTw6VgyE60meSVVJiyiht3HThz64m69lSwXSiZD6yDcA8EQOAenkssHpiDNhADsLWG9mS0AF5+\n        sbn/zuLhh1+PP/18/MninsGPM9dfHDl/5/T1Z8cu3t+jf/Hk5XuvPv8IimMP/M8/CaHh8sAANJq8DE1H\n        VgbBmmS5oPKVY2AQGOQ2UcRoChAPPmwA9GOQgBQG/2sf0GdQMWFZ1NcrCfovVMJDcIf5xOE+TgBwKywk\n        RlcM6H3Yj3559PUjEM/BcgHmcmUEfSCSxUq40stybCqHzAGEgc8izaKBHuAquATuOZNof7gWq4hJZtFS\n        BcYiOm2NEl1/+aKrJ07vP3pq7pz5k2g0bRoNjJJZ/wYVgA/mUctAEtc/ID6xbODd6cAo0+XQLoFz4OaA\n        7JNJE1CwEnTkZAD0AeiBJODQFBD7cDKaCDg3uAmWgBFjAmgD48DECACzYCKDjs2fieqnoJ8M4vBBvz+d\n        QUdioLiBsgkmTJigqqQwW0NzurqW7sxZe3fu/P30fegv7ySvyIqMzPrcvLbSCmlH19jgSFdNfVtZWV9L\n        M/r9O9pGevtA7EvbWqWdbQM9vYNkVcjelraehubuumZpazsAvRQ7+TRib+e+/lFc9XcYDAVgjuH+gbHR\n        P3BJX1vX0OAw4P7wwPBg3wCaBaNYH4ClA3/+HhgYHISndEn7e3sHBwZaGpobKuramhq72trbGlpa6lub\n        ahrqqiubGmobaqorwUYpLS8SisuLC0tKi3hsPjs2ISUhhsNOk4gkqQkpWVlZIp6AnRAfGx7p4+EVFxHM\n        jk8B60CQxuFnsJOC4/0dfdMzWWWlRaUhfgLbn3GvnoReOu914pDl/r0Gm9Y+WjX/wkK9I3p666fP3D1r\n        xq0Fc1+tWHJ36cKz82dvnDFlhY725kULDh86dPTg0YOHTu3Sv7h2z4k3pvbeHhFBvrG+ATH2bj5R0ex0\n        Tm5saqa9Z5i9vY93QKSZves3c4vPJt+/Wlj6hoTFJLLCo1NyJMUJqemJKVmcTEliUkZOQUl6pkiQnSvO\n        kZSXVoENIBBJ8vNKS8qrysurykorKisry8oqGhua6+obi4pKykvKyKGymqrKwrJiYW5evqSoQFIIVoFA\n        kAOjrKy8pr6hqrZOnFuUlsaLT4gPiYqISEyIjkkIi40PiUlOSUqLisfmz1w+LyIsxj88ztLF67e1nbOD\n        q7NbgGdUmHtw8Fsji48mFubWLjaW7u+//bZ1cLW2cP30097TM8jV09fB0d3RKcDOxefCowc3nxl8MbE3\n        /mHx5bf5YwOzx5++PH726tljw+179BnyCgDigPqAWdiqDN362ERh3JGNJWDYv15WThHAC6AZkXQi2KvY\n        E4I6SoWICU5h1SuuAaA9WU0bnRXqWtNU1ZEAkDMAf4mcR3cKJnTCQLcGIr4q9uNEyU8NdN8D0E3WnozN\n        1wBe4QScEibVoJ0BMA13wKvQRaMK/ANPR1+/NoadlUn7aHUNHSw6gyeS/jxwW5iwuraWhs5kDAhTrYqI\n        xkdvjwb6ozDwoA6TBA7QVMMll4EAsMB4oirwCuh9TAEiFgbKf0R/qu4XKQGr0oi1hFW7wDQw4AQ8io4g\n        PA1+PTk5sAPwZyT0MInBlF2/fe/pm4/VdaYBbajgU/ASuAMl/GFuYPqQnfB0UgysBQQwhfb+u/3T979O\n        XH12+tarRx/MXpvZAwccPXdny94Te/Qv7D1+ceNu/cVrdp6+ejcoNjmvrGZEKvWxs8W4M42mOIE2Q5ZC\n        YQrlGTOY9JlMyvuPqE2ZAgCOMAB2p8kimsPOmSTRHnZOZWLaDMD3amU6JtUQWwEJgOAsYjfxFIGtAFSB\n        lbq4hC+q/oXoo0fUXqiIzUdB+GMXB4wcYPOGRSRUAGMB8BOhHGxEQQgDKAEegbEEYBpiVQCyryDRY9iY\n        xqDNp9F2qCtfP7Dv4b1H+3bv01VXU6PRpjAmIPSTgTchLwuCHQZygCxmecIGUAJg+nTMCwKDAFt7apNQ\n        hzbwH8Z70bOvLSsDNgFYPEBgsH+yrAxcBfcBApgG76vI0FViTldgauOSAPSJ/8YAyCDhX5T5CP1yMrCH\n        IQcMIEMH1U84AAsC6DITmPCjqanOnjxlyax5O3fu+nr3uffHXymBUXVCYW50dBlfNAwo3NLeWFDcVlsj\n        bW4aaG0b6sXsT0D8vu5uaWfnUE9fd0ubtK1rdGS0t6W1pawUhD+pDZb29/SODA2O/fmDqI6Lv2Al8J+x\n        P2AB4AKQfXB0ZHgQG4L++fP32NhfYAoACYwMjyEx9A8MDPQPDQz3tnf3gj3R09Pe2NTX3dPR3tLcUC+V\n        9tVXVBeJJe0d7bU11WX5BZ3Nze3dnQXiAkG2kJOWkZ2UnJWayEtJEwnEQnFuvkTMik6ODopMSkpMCo9I\n        iYzOTGazEpK4mdx8sSgthRXs6pPg4ZYTG56TFFnu6895+szv9DHfsyfsj+032rPt4rJF2+bM3DdPb4vu\n        rO2zdG8snndv2YJzC2dvnzltw/TpJ+fMPLJgwdaN6w+dPH3y1Jnjx47fffjB2TfBztknLDIxLJTj7hsZ\n        l8AWCvNzJKUxMWxvnxAP/6APdrbff9sbmljZubl7e4UFB6UkpmVwJfkcrjg9g8vn50THp8YnpFdW1ecV\n        VPCzxfnC/OqahsaGlsK8QoFAVF1VTQC/uqK6DjigoLi4sqauqaWlura6sbmptKIqT1Isyskrq6woLS3l\n        83OLCouKC4qqqmrYWVkcLj9LKEpJ5wt4gvCEmODo6MjIJN+YuMDoqBxRDjtT6B0RncHP5ot43gExHgHh\n        7gEBtq6+wbGpQWHJFtZeXyxd33/9bmr2w97Rw8U71NE/2PCnu5GxnYOtq72z9y8HV0fPMBNb/8evP754\n        8urRe/O7b79+NTEzNXO+ct/g+ctvz19/XbX1gAxDFvAIA6forwDJj3k1gNeAcfAVQENBkUhXRRWAQgAj\n        chRhEYYyill0ceAdAKbR4TNFHbQqlSipNRkzQQHI0IWC/mtVLUB/FODqJPeGWAkwQPyS+i+MzRKnPxlq\n        2lg6QJkLMNDtTuwDZRVKuYMeRwcUgiwaH5Ownz5SBeh9XJQGRD3VCxrAHW5L2hCRhVzgUx29QPBEQgNI\n        IWh8kHgDmZs2nECICtNS4VlKE1VBsGNLBpLpjx4e+LlIKEIRKBNLzzDjiPw+mCJFWApuqwE/C/xcwBA4\n        T1xTQUlBSYksOIPhgQkTZNZs2X3i6gM1ranEeMJ2GmhCUY4grAbAzB9SCwb/XlSxFzT+pFNo74ztn334\n        ff3p1xsvje69MXlm+OuFkf3p60+37D22Zd+JzftObNx1dPXmA2duPLTyDDT+7Wj9+sX/dHew+GIFZWwU\n        oSIzAfB6rjwaAZQ0nk2Sf6YzKdxHtKUSJXXHhT+gJIkWkPW/gAAAT1eQJB+KSMBWmCVLX4SN/jE8AOdj\n        P1EkAPS/A4gDxIOWhw3Q+wD9mKtD/DPLyQq9oOVh/yIQ++i1x8uBAxaQkgJCA/gJxIC1Aph0xESXDhZ8\n        MZYryS7EOi86Vi/TaKvlJlxYt+L17dtXLt+YN3OWOo2myZgAdgCYJnAHQHls4Yn5r+NeIEz/J0s5wjb1\n        ldqYjF2AZED7A/oTI0BGlYnt/tGOgZ+F5AJp4KoAWCcMV+nB/RWZsxWZkxUwHqAE6I/5neMEAAMXg/zX\n        +4+Iz0BHEBAAEAEYB8RQAAqgqatOnKGttWz69GN7d395+srno1GyrUu7pLitvLyztr6WK6jkClsqyltK\n        S3qb6qSN9UO9A0MdvV11DdKuzoE+6UBnb39L1xAm7eCC730dPd1NrdKmlv7O7jGQ/YP9YwMA8yN/Rsf+\n        IjXAuPTjyNggdpfrIwmhf+He0TGQ/YQG/u7rlg4Af/RJ+3p7wHLoau8a6Osf6O9ra27obm/v6+0f6Bvs\n        aG2tr6muqSqHUV9b39HZ1dnWXl9ZlS/Kk0jyy8srGmqrwUCQiHIL8kTFkkKJOC8pIjo2MCw5NjaTlRQX\n        EZcYH5/JyeBx+exUVmZWSmx8VJKPZ1loaHZESOpPs7hrt4POnfU4cez3ni2muzY/X7/i4Pw5W+bMWj9j\n        5lZd7J59du6cg3P1NsyYvnXGzMuLF+zR050/S+/Afv0bF+9ev3svJCg2J6vY2cU7MDQ6LpVn5xAUHZKU\n        mpLGYmdnZ4vjkljxSRzHoLDQ6AR331BLB5+Y6DROhig9nZcryZcUlmdkidmpXJG4jMsrEOcXi4tKissq\n        8vILc3ILcoRiTmoaWAPFxaV5eaX5+WW1jY3FpfDGJTWN9fmFJUJRrlCSX1JZVVpeXVJWAUZCXpFELC5o\n        amipq68DWBeIxFncXK4wD2iAnytO53GjExIDAkI9AqM8Q2JjUtjcnHw2OzMhNiUmLiUoKDYymmXn4fPd\n        3t4zJPjuw/dmFk6eQT5GZtYmlo62Pp5eQZHfrFzNLW0Njc0cvX18wv1/ONk9M/z89bulrb3H/ZcfDpy7\n        cfP5K4M3Jl8/md999O7W49f6l+8tWrlNVk4J1DciOwE7yu+PCT+UvwKGIgx0rMM5JGALOIW+DnRnwz9I\n        UFRJGSlBFR0ymrAf9mJeDTpnMPaLUIuZNtQ26neU+VSWC3qTAJrRw45+G/R9axE+wF7K5CbEPkD0V8fJ\n        oECm9DXKcGyTAIREggdAUUw5UNhK8FyycCM6c/BkgGNStKyqCQN1Peb5kN5wyEzYpxNj3aD6wT4A9Ecf\n        EZkh/CB4iOSbwk9BUnoonxi8N65rDzvhxXGZX6AEsoINDLgVchLpPkQ51oBZsWSBRIbxF1DVgvtgEJjO\n        XIsrgj1S05xK3gJ/E4B4da0pamDKUOVgxAj4/xKAAXEBPf9qZ2Du9srE/uF7k4fvTS/cfbvn6Pn9J68c\n        OHV9//Fr+05ce/Tum4N/2PUXXxYqyn/cteGff/4JTmSTWABNkw4cgAHVcce9PFkHmER6sU5YFtU3OnZQ\n        +BP0p3JGCT3AAPhehOFZbOYzl5SJgeoHgbycpN/AUZT2isAuwAqg+ukrlHApGJD/wBag9MlV6PFfrsBc\n        pyS7TIk5j0SAF5ESLZgJFior0AGykaJIMQEMuIQqLADDAgacvIqUEAMPASvAzeeSKoFtmipvzp2+deOu\n        3rQZ6A5iTAC1TmV5TkNAR+WOWE+CAUAAuJI7sgIT9yMxYGUvcfigox8AXUcW0R+OTmfKzMFCOQwOAwfA\n        oXEvEPxECugdwkXB5LEBHAX0lAuIwn1AfGrnuPef7AELAF1D/xIAaAkdTbVpUyfrb95i8fCx4xNTrw9W\n        BRx+c1l5f3ltdRwrLzmls7Wpr6Ojt7Gxr6N5qEs60NbR09BIUoDQw9NVVtdSWtbXhuUCA919g1190pZW\n        kOTY6QEbAY2A8P8LPkbGcFGwsb9GBwalra0DA4NgD/whiwRgYugoGgqw0Udiv8NgCIyN9ff093T2DPT0\n        dbS093R2ttU11JXX9HR2Sfuk0gEMEDQ3N/UAlwyPdWCyaGt9bVVjU11dQ31TbXNrfWtLQ2NhXg7YB6WS\n        AlZsTGxYEDc9TZDOzs5KE4slteX1wtT0cP+gbHZ2jiCXEx2baWsT9/qe771zrufOeZw6a7xry7OVC9+t\n        X/lo3dJjC+ds0tPdNHPG7jmzTi6YfWnhvJPz9fbMm7Vr9qzdM2dumDpl+ex5Jw+e+PDow70Xb0OikpOT\n        hQERsSlsVkxahodPqKdnGGBlUkpGahLHKywyNCwlKTU7iZ0VnpAemZwVHBWbmJSQKxQXFIOWryguqsot\n        KOeJCsTCvKL8YsDxgqKSHElBJkfEF0j8QqJCYhPKq+vyS0vzCoHtKgslBeUlpcXllaWlFeWlFUWFZTU1\n        9cAQuZLCwpLiguJ8cY5YwBUWFZdlZHG5mAVUAgwYGZcYFhOfmp5WVFQZE5vo7uGfKhBGpMSnpWfEJSUE\n        hMYieyXEB4UnuHuHh/jHmHz5ae3oZG7l+P2nk0NguKGd0y9nBzN7d2sXHxtbu1+2zt9+O/34+cvK0uHL\n        l+9GH42srF2Onr238+TFz1Y2r79+/Wxsfu3Rm3N3bjx8/GTF6i0yTDniu6C6WmIwE30+imTlQowJI5yR\n        Q6j91dS0AbIByOASchV6fgA8kQyAA0jnNYA2AE0AbgA7jKOqYpsHHCiKx78iIhMOIE5/IsbxTM2JFGfA\n        BgFTrM/C0DF6/wE8FZXAHIE5kkQgmBjMmXT1UQUcJyYC0gMaIujeIZ2FtFRUMLiNl6uDdYL4rooJP2gZ\n        UCYI1dtOWQVICx6lgw4itAC0MVEHdT22IQLoRwIgrwaiHn4rRQXcA7iMPxEWo8EjkB5gDjgmobeKKguA\n        +eA2rmAz7i/CZfEJMTCY8mu37D4FBIAWAFUV8W/UF0MaaCQhR6JHC24ybhmME8BrQ/vbL03vvDN9/8v9\n        +pM3uw8dPX/75dHzd45dvHv6xtPT11/oX3z49P13r4iEB++/T9XU0aHRDDYsbxJmf/hoNIHOkMUVdyeg\n        ckdPPQI9QOEUJmMaE0MC8KlHQrWA9YibJGdUB706CL6zQW6TRRyXkRZs6PonoV1Q2auVcAXHFSro9gEa\n        AINglRLodCSDhSRbFK5Cnw/aClhptViBvlYJV4YBCwAOATdgnJbgO+XqWUJiAwsJ08AJxF7Bci04DW0I\n        RcZqZeZqJVlq7UmYxjwFXFNssxLjyamTx46dnaqkCCaPJgNl/gw57PEJAh85gOh94sMBmwDz+oEkAPQR\n        0ElmJzEI6JMIylMVv9OYMjoMZAuqpaiWnMxEWZmJTLQGqEuwM6gc+n+UiFcHVD+F7P8lAOQA4heiOABr\n        xGTGd+IJYBBMmKCpqaYzbfrqBYsfHztp+8nK47tDiptnW0nBQF1jJYdfK5H0d3b1t/c0l1QCHg/3Soc6\n        uvtbW3tqG0ak/f2tHd31Db2tzQMdHf1tHegaausCEB8awLZx6NAfGf4L3UBAAJj8D4g/MjA0NDgwOjI2\n        3I9tQUdH/owMjpCkICCMEUwKGur/89ffo0OjXc1tbY3NPa0dXW3tXe2dbU3N3b2dnZ1ABt2DA8M93VKM\n        G/z1B+ihpQ64oKmtpbW7paOmpLJYXJCTJaosLhXzc3P5Aj6HmxyfmJKUkBARFhoYyklPKckrEKRwkyOi\n        2WkJQV4Bvl7BrIjwXGerhOsng/SPeJ88anxg+4dtK28tW3Bl0cILyxedXDZXf+G8/fP0ds3WPblg/rkF\n        cy/Pn3towZxt83S3TZ++aeqUfStX3D13xu6r4U8r9/Do1IRkAPeUzIwsFpvvGRRuae8RFBoXm5AeGhTj\n        5xcREc9KZGVw2PzUNH4yh5/JFUTFp8YmcFjp2UUl5ZKiskyhOJ0rEogkQoFEwM/NkxTm5hWB9ZCWllVQ\n        WJqWmeUdEppbVFBSUV5YWFRaXMYTANhXAg3kiuHcIp5AnJ9fVF1eUVFRUllRLimQ5BYUcrJFQp4kP784\n        vzCfnZ4ON2VnpKdlcnLyiqJiUrMyeYlsVmhMPCdLwMrMTEjPSOBwgyJiwmOTeXzJbxv7J+8+uYWGWzq6\n        G362/W7l6Bjg5xsW4uLl7+4T9sPO+91Hq1+mjj4BYcYWjudOP/j22fLmrVdbd+nff/HByNrli5Xrrecf\n        r91/cefei+evPi1YtpouK4uefRDCCHC4DCTm0hDPBuAdYB9yA6l0RbU+ERNgCDojriE4/iuN4TTAQdIZ\n        Hwup0O9PWiwAyAKEAaxj8RRGWTVAnoM2x0NYKIA2AbUBsIs7CfSD5MdFvvAcNBFQWePjgGMwxxQeB7NF\n        +gHWwVROtBgQQDXGsRtOw2x9Yp3gQIsElwvGyLAWTANLfzW1p6oCvmPhGw5EWCAJrO/VpAwLwm3q5AWV\n        YRusIgBx2CCqH38W4CK0BkhmKl5CYgPEWCERFDJJnDDaEGqwhyIPOErcR6pMptzKDduPXbqnqjFFCYPA\n        41FfsowMcCf1cwETkEGawQF7UQRg98rQ5uYLk6vPDV8YW780+r3v2MntB0/uPX55056jOw6fPnnl8alr\n        L15/tvCJSn72xWL+dF01Gm0qjXZz2kRhkP/V20+VFCaq0GjqdOSABcTbDhJ+BuhfQgCwAaYADCrnR4eJ\n        XhGwA+Dk2XL0ZYr0pUro1QFwB2kPGn8JynyEeOLTx4owIAOghJmy6L6nUvL1EH8x1gqcsZDIebA/lmNb\n        CAwMEJ8P3meZEsac4Ux0/oz7+sezieBaYAigB5gJHIXHAZEsgocqk4Y/sIe0poDngh2wdbLGw1v3T+qf\n        0lVWwoUEyJowYFIADQABwNBiojsItD+gP5DfDLwtbJMFfnHIAMSjQ1+WoYy/BkY1NJkMdRISgLvBabAN\n        BDCRKaMOPMFkYB8IWRkVBl2ZjuW+SqTIS5ZAvDxhAooGYCcM0P4MspMiCWr/BBoNdILutGlL9XSvHj1q\n        aWodYu2d4es9WFNXn1Ocl8Xtau0Y6uzprmtsr6oGmd/X1jPU1dvfAZTQiRHgvv6RocHBQWlfd9eQtG9Q\n        2ov7u3txYcghwPVREP4A+uPyn9QA97V3D0kHwD4YGhwC9MemECOjiP5AEqNjwA0YJxj7a7h/qLe9s725\n        sburbXAYuGRkEF1Kw0019c3NjYNDGGBua2pvbWnraO8CSmior22sr6soKSvOyxdkcPJEovLCkvq6WrAJ\n        CsTiUnFRZno2m5UUD9I3IkaQyY4JCEqKjOZmcTx83BwsbVLs7UW21uwX9+Mvnw25cMBZf/vrDWsvr1p0\n        e8Wie6uWn148f/9c3a16s9bNnH5owdwbS5ZcmTdbX3fWKV09fb2ph+bqXly33eT6Hbv37wN8sIl+ciov\n        gcVPjGGnJrPcwqOsHYPiY9PCo5ICIuL8QiNDoxNj49Ky0rmZaTx2VlaGQBgSmeLlG52UxskrKc0vKRfm\n        FiSlwEGBUFKSxZOIJWWSwhLAel4mLy42tbSsMig8LCAysqC8LIMnzOLnFJaUivMLCsvK+TkSfk5BQhJL\n        KMqtLquqKCorLq/IFAo4wtw0riA3p1CQnReXGJcLv0hhflJqala2iJUtiE5KAONAmJsfmQQWSVJGNi8m\n        Id3dO8LHM8LLOyI0OvWV6U8LV7fXH74Hh8Y4ung6OnrFJrOcgwK8fcLMfro9NbN6YmL109rOwd3t0XvD\n        fZfv3zH49uzNu9s37nu6+H01Nrl1+8O1ux8uPXh94dGbU3cfz1m4XFZWntTujgMWABnJZVQHOwD71xPR\n        CuCI7mwAdJKNAzCHZ+JQAWgE7YxOIYRRxEfE7klY4UUhL1DLJA0tbGmgjlntgOagzdXUdfA0NdhPeWkQ\n        /VXBvMBwMSAmAj0gPm4DvpNb4dMB5UmyEO6HaWCzUpwMPB3dTTiQThSVUInDQ+GrGkhpVNPo+RnnCaxF\n        wHgA1oipY+AX4BiMCZL0ialKcPN/tbwq0iGJ9MJTFLC2i+TwgJbH8DjWS+PJKqq4auYkEjknF8IGThLX\n        mCRNgUhsnBAD+tBU4LciBMBgyC5ft/XYpbsYuP5fBACTRBsCbCOKAKh80H+LA8YJ4NnHX3dfmd4zsHhi\n        aGnqFvDhu8Xabftnzl+uoq4DV67ZtEP/wsO3xnZ+8aznhr+X6M7WpNGmMGV0abTr86d9f/lmv/5l+DcM\n        HKDFlNGTw2XTATcB96czYSDQY3sf4hQCDtAmTDBDXmaanMxcOFmBDoC7Qpm5VomxRgkluZ48QjkofUr4\n        A+4DggMiU+EEIszH/fhwJnyCWifILrtOSXazCnOtMn2RErqJViszgFoApgH615CQABgNcDmcjBxDDA4w\n        Dmai/4exnISLYfJAGPAsXXm4CT4LoxeyE6YDB8yfe2X/vrWTNXVkaEBgANmg+qlUH+K6QU8O2gFoCqB3\n        Cw7NkMeKX5g2LgZAEj1B+8PjYMLwmsAHigwZapmXSaT/s+q/bX+ABoAMAPcp9CcN4LDtM4X1QACkOzRT\n        CbODkBgYdPiD3YH+JQP4xA0mGAEak1Yumn/x0LGn1175fLURp8RzfELyo1K7G5try6p6mpqHeqTSltbm\n        wpKOuvqh3v5B6cCAdGBYiqu3Exro6++TjgIqw3ZnD9gBQwPD2Bairw/7vg2N0wDJ9B/F7hHdvQM9/aNj\n        2B8a9gIF/Bn9a2R4ZAjpBKwAdB2NjGCseACbi/YP9g/BHcCE6O7o7mzvGBrBdWWGhka6O3sqysp6errB\n        lADbo7m5vRaX+GqRiIuqq2tqq2sb6mqbmuoqK8tL84slmcISSb6EzxdyMyT5ubk5vOCI0JCo8MSocJad\n        a9qX16lP77Cf3019fTX+8vHwk4eNt61/uWHJh62rnqxdfWXZkl1zZmzWnb5Vd+bRBfMfrl99Z8Wik3oz\n        bszTfbdm3p01K54fP29+96HnFyMfF5+A8OiQGE5MPD8yKikwKMTS1sPWLTA2Kd3PNzI4LNIrOC4oJDkz\n        SxAemZCcmJbJFyekCaKik+MS2YKcXJ4oX5RflJktSmVnJWak8YRYrgD/yMrkZmYL8iQlaWmZyWx2UWlZ\n        eGIKi5MFQJ7M5iQmp+cVFeUW5JaVlYdGpXKyhLmSgvQ0fr6kKIWTkcrJ4IsA3gu53NxsjqC4vCSnUMRO\n        T2NnC5KTOIJcSXwaKyQ6Ni6R88vaJSwugcVOC/KLcnYPDIqMD41MdnTzD05gfzKzffbsS0hUok9IuIu7\n        7y8bNwe3wF/WHl/NHL7+trLz8/z80/nWm88Xbj+78dzg5sOnr198+f7F6OO3D+++Gl07+fjxk4/Hrj14\n        9NXk1JWnWlNmyMrLU/k8qE8pbwmiFTrcid8fnS24NoCiCjAB4BrgLCKgwni9mCLWi2Gok/oEGQ4gqKiI\n        zm7gAALi6sSjjShMhRDU1LRUUdpj4HcSpn6iuxz9QqpaaDRgIBfTTJFLCAHAQ4FRUA6juQDIqIoFxqQX\n        G8CoAkFnwHG8IZYCYKktzARupYILioF9QN0NIB79ThMnYjMJNS3sYo3BALBF1DWVJqkqYxCCIg84E/kG\n        oB/VPbFyyFKOWNlLOACD3sT1Dy+NE1BARxC8Kf4IVAiETF4Vnj6eR4SxAfiqPolqS6cC91GWoTNWrN92\n        4soDNS1cEYzCdxgwPbQhKAJAPhi3A2ADhoYWpoHavfhsde+N+b23P5+Z2Js4+lg4uF+49+zszYenLt/Q\n        mQboR9Ods/iloUUYm//axGHh7HlaNBpoeYBy2DgyTcvk0/cdOw9NotE0CDiCBQCDFHkh/sKZYBDoETtg\n        KjaJkwHyAA4AbJ1D2v4AIC5XogNwgzUAWA97FhNMX4TRXWy4BkAMoAzoP5PkdIJaBzQHKwHoAb3/OOgg\n        /IED1ioxt0ykU7XBWFUgj6J+HlklBlcAJnFmmBuwCxgc8FwyVSSh1aR6YB7YB0gM2AJoLnE3wflUsHq2\n        DG25vMwqZTk4NB0T/DFsS1V1YSgYDAVczhd/Ex1ZBtDDNCrribIDSO9PFTCAsBsSsUiUcRFgbOVPVnRR\n        YDJgW4UBnwzYBsSHr4oE/anAL7UYAGyAukcOYICJgAtGEucP7gThD+iPXzEdCM+RZaARAH+7lizQO7Fn\n        1/ljlwyOXk10dRfEJ9bwcxpLytqraqQtzQOd0s665s6Ghs76+q76ZoDvxvzSRklpT0OrtKOzq6MN0L+v\n        vrmjvKKtvKajum5ISqB8cHB4CLv+jA6DBUA8QMOjvW0dA729Y3/+BtCnjAMQ83BssH8ABsh/gPsB6SCe\n        PPbXX3/+7pfC6X3Dg0Pd7Z09PYDz/Y3Vje0tHd3dPcOjI/2DA739sG+wq72joqy8sbGlvb2rur6poaWt\n        V9pbVlJWVlEmFuXkCPhirrBUKKksK6qqLYWd/MzMuISEpMCAitjEyvCAfKcfJc7fs40MYp9cS75xKejE\n        Ma/Du75vXPVk48r3G9e/2rDs1LJ566dPg7Fnru6JJfP1Fy04uWj+hdXLnq5Z+WLvrg8PHxg9e2z/0sDi\n        nbmLV5STU6i7Q1hgRHJAeJyNg6e5nVt4THxEZIxfcJCLV5izd0RYYmpQeHxMSno8m5fE4nGFEh5PlJme\n        yckWCnLzuVm8tPTMuGRWehqPw81N5vEkhYUioQTYIqeszD8qMjaJLcorTUvLKC0qKSwtjU9iiXLFeSX5\n        ucVFmUIRTyAQ5ReCvmen83LEOQVFEpE4DzghV1KUwRFkAZEUFcYns+NTM0HI83PE5TU1yWnpQWFxQBWR\n        sQkwjfjE9Pi0jDSBMD4V5pDlFRRkYGwREBZv5+7x87eThYOb2W9XT49Yf/8oI0tHo+9Wv+1+G3z+Zmzl\n        9OWH05HT15+9N3z72dI30PeV8ZvXX38eOX//wat31+5+uv/w09kLT1TUNOXkFVBNEzcIcgAJAxAfCOWz\n        RscFoBWgmjKJcyLEg2Sm6AE5AOPDBHMJ6E/SnIg8QQaxGED4Y949Judgy51xqQ4cgN0XALJR8gOMAs5i\n        kg+1+JcaqH7ivUGljxk1GF4mwQO4LTwd4BI2YL8Spi2hBwa2YW6AwkgGxArBr+SlCFWQ1qEYxNYialpT\n        HWOtOuoaYARgQBgYBY4qot8fW7mNWxLo0oGbk0NKSADkh5qI/jGMkSiiUwhLupTl5TFYAvQAZhOSJfwa\n        GBVHoiLWDHqE4Cv1mhQZwDwZTLAAthy/cl9NaxoSwL9wj4MURmAMYHz8LwKgLIDnny3vvPp+/8PPV98d\n        DG08f9i5PHpvYuUVmFlUYmBsKq8yETjgwJFjwXHsjxbui+cuAdzXJdpZmz5hGo328tgRVxf/9cvWKGFH\n        ZXQEgd4HCwDRXB4hD3AQEJ/kg2Ja5BRZGUBVAHTsF43xWwRfjAGQlJ4FZKlhOIGqKVsMOE4OAfSTLFI6\n        qPUVRMiDKQDEAPodGEIPyQC9SduVGTtVmCuVybLyJPUTzgR6wK/oHaKvwZRTxlzSrI3y/gPQr0H+wP0b\n        JuKqkNgjiBgKy5UxHoDLBcvT58vKUJYHqHt4I4z9kleDMV2OORVTQrEzBFgD2sTvD9AP2+pMGXXi/AGe\n        gJ8Fc4fk6LpANkqMaQoMZSrPB4CeLqNCx7XA4ExcC54QAOwnPZ/HaYDK/wF8p7o+UG3gFP9XZJjEA+jA\n        AZgRxMBIgCyDMXuazo6Nq0+fvv745M1YG9fOgjJubHy5WDTQ3tlcWwfSvq+9p7W0rLm2vLezs6+9u7W4\n        rC4nr6WsRtra3dpc39vS2t/c1l5T3VRZ0dXYMDIIMn4Ucz9HhgDchwfHhvuHRrHLw6i0u3NkeOivv/7n\n        D0Z9B0aGx3D1GAwBD6MzqW8AhD82DAXWGB7FxNHRP3290vb29s7uzr7+/o7mjprSqqb6BrA7qMWGpf39\n        0t6Blubmxsba+rqGtub2nu7e1rbO3m5pTU1dSVVlRWV9sbgojZ2eX1CE+THFZdXVZWXC7NrszGYerzkr\n        rVmQXc3hlEQ65nj+Epl8S7h4NlB/b8CJw077txpuXvd962rzrUuvLVu4ccaMLXrT9RfoHZyjt23unEOL\n        5h9eOOf69h1mN+4b3Xpm98EwzMw0zNXjt3OQraObo5OXu0+Yb1hMoH/4NyNLv6DIkISUmKRUv/AIR58A\n        v6DYdBY3lZ0RmwRGgAiAPo3LS8/kZ2Zhig4Ad3RKGmBveoognZObyhbxhIX5kpJMrjCFw01ks609PNKz\n        uOUVVTkg7EtqSssr0tPTRXklBSUVXAEWAOQVFOfk5Qv4OZVVNTX1daVlNTk5hcXltWBPZPEEWXxeXkFR\n        Oic7VyJOTElhp2aI8/IzcnMFEjEYSGlZvKCYhLCopPSsbBY708bV4+MPyy/frCxtXF18/Iy//3J28vEJ\n        jXT28/9h7vDa4Pvnb79/ujp8NTT88OKDqbHNR0ObU1efmFo7+4aHfTOzfvLK6PbXt+fvvDh89t65u09O\n        X3k0SU1HTg4kLAZ4AZIo3zdiHMC6ErpWUAUjjCJ+wX7U5gimiGWk/wHwAuLsvxCM6IbSG/348BWT6zUA\n        ZzW11dAg0AJ8V1UFLKM4gIh9oBOil4Eq4EJU6JjkQxEA8gfWnRGDAA+RSC8aJZiFSVqBkvR8PA3oQVUL\n        Z4JEgnofEJzaIJfDtSDqcT7qOjqYHgrCX01zEsxHTZMEBrDnM8h/+BHwDmQCKPmB51TwXeB3AHwnbw0E\n        gDIffjZCD5PkSJEXhk+oYmn0GsFppH81UBemM2HgBH9kZfx9YA8QA9AMEMCqjTtOIAEQC+D/rffHB/H7\n        U0Vh/y8CePTW/NrTr/c//Hr13cnQ2sPc3u32q69XHryKzuQJymsMjExlFZWY8oov3n248+zjqkUrwCgA\n        ZKcc6Jo02jw6zeL5CzsrZz0tHUV0BE0AHATcR38LEe+A+FqyqPqBEmYpoB2gzZABNFxMWq0BAQDULsL1\n        IDEJBywAuBZMhylMNB3+i/6A1/AV8Joq9AXxDhbGFDmsHgBkBxoAaIaTd6jQd6tg9HgdSHgi+eGey0ng\n        d6USmg7LFYEDxpd5gfnDlOCGYB+sUcJSYcIB6MUCWIeZwyVrlGWXIQegKwmGrjxKe8B3UP1UBHg69RUz\n        +qlET7oWYQUQ/hjUJZ4f4IDJJEhAtXibLs+cq8iYqYgrPqLbh3hvQPVryNHVsBKYoQLITmK8JAKMGwDx\n        VCKQnAyJ9ILFgEFjBpxAdQmFOxAjgI7FYfhngjKTQafRJmtrbV638szOXdcPnvI2synhZORnsHsbm9vz\n        iquFkva6dmlbd09jc1lWdk2BpLW0pKOwvKWsahAbwPX3tHW0lVV0VtX0d3eDph8cHOhubBzs7etpbgHl\n        /tdff48MkO4P3T09zW29bVg+hgQw+tfw4EB/by8uJoOYPwbQ398rHRwgKUDSXml3N3AAWBHDQ6MtDY0N\n        1TVtrR3VFdUFksKeHinYB60tbbVlNd3dvWA8dHX11lXXlBQUluTmV5ZVdHR3NdU2lJeWVFRWtja3tDY1\n        SvIkgI2lhSX1lRUt9fWdlRWtZQUNpSW1EnFXTWVrYU41O7iGH1/i4Z798Ery3ZOxV077H9rpum+d1Z41\n        Pzauebhs6YUFs68smX1y/uwjc/VOzJt9fOGso3o6t/btN7/3yuzJS98fPxLsnMM9PH2jo8MTUkOikn9b\n        uTu4hUXFpVlae9j89HL1DbZz9rNz83dy8YiNS05KSUtIy4iMY0fGpsTFpiVzMthZghSWIIMvzuDxkjhp\n        SZzs+KQMXnaumF+YnMRLE4pEkvyomGRBriQ5PdPe3a2quqa+tonHzQPBn5qamZLMF+QUAO4XlZWVlZYJ\n        QfsXFuUXlOQVFpZVVhVISsrL6wpLKoWA9dn8FA4rjQMSP4ebkxMVlxSfyGKBrZFX4uIT5B8WweZmJiVw\n        rJx9fji4PHll/MvKz+CLhZ2Ld2Jymou/7xdLa0//EBsX15fGJrfuvTT7Ye0ZHmv82+Hps1eP7r35Ymz5\n        6PHbF+8/GVra/v7m8t3U9qnR1/36146de3T61vPdh84pI5gi5AFsIUIhwBFTQBnXU4QNQEDcCdwA4IiK\n        mAAZxj9VScs2Uv4KKAj4i55r2EOpXeADgHL07GMplgbYAYBuoOIJphM7YJI6ceagrgdcg50E6CnvOd4H\n        UBt9PritRpkUSC3wdEWEXRIDAAIgcE/5fzDsDE8nX+EonEnRFd4TvUxISHAIeAgsEgxR4LXoblLV0NbQ\n        0QFQJtYMvKy6EhIAngyMSNkBlBMMGRHb5FHFcUAAsIdYA5g3pUQqfjFPiTKk4OYwDQL3yAT4lTivYGLo\n        LFJRY8rJb9x58MSVBwDuxAU07uX/XwP2jBMAxgCwnxIVA/hm8+zDr7uvTR9+sHj53fabtbuZg9uNV1+2\n        HTz74K0hr7iiVjpo6uSmt2ip3px5G3fsW6Q7d/oEGuIgaHyialVotMWKcnYmpl8/GWvIycvSaBqMCVOZ\n        AM305aC10X0vM1VORoeJwh8uBHAEMpgtJ7OEyP8FxNu+RAmXdkEtD7Id0Jn0GQVjAlAYBqA/VgOQ7CCA\n        fsBuwGI8geQdAdCvhsuV0BpYqcTYosJYr4yYDii/SQX3LJDHkDLQxhrl8ZUDYGJLFOlYFkCiwchDxKEE\n        d15BHETUg+BMLBJWxKXnwToBOwOwG+YPpsxkkucDsA7yfwoKfJD/KPNJIhB6/3WIl0xdDlEedsI5QADA\n        BMABQBhTxxd/p3o+U+v9EkwH2iCD8gIhAVC6nhAARoCBAGRgPxoKpEiYAUcpC+BfOwAZQIb4gmQnTFCU\n        l1u3aP7JrVuObtpv+/BVSQart7yiLDi+UpTbUFpRIypuLCzrqm8pTRPUCPOq+NyOxloA7OHhwZGhwaHe\n        ga7yynqBoLO+EfhgqL+/r629t6Wto7p2eJi0d0CdPwpsIW1ta62u7u3o/Ouv/1D+/6G+gf6OHvjEIoCe\n        PrAB/vrP/3S3AE+0g7zv6entbO8cGhhsrq+vr6xvqK6vAPjuaB0eGa6rbGioa6yrrGpubB0YGO7uknb0\n        dNfV1GSnJpQWF3Z299Y3NlZWVpSIC/K4opL8gsqiiuqqyq7u7oGBwY7Orq62rpbmpsaq6paGhr7+gaGh\n        oYHu7taCgobc7BYeu9jGPO3+5dgLZ4PO7/E4utNu2zajzWter1n8etXC1ysX3lg6//biuWcXzDo+b8bN\n        nTu+P7jr9PaNz/s3UXZWkYamztY+QdGcgKDYX1bOUeFJMbFse4/g3xbu1vY+5r9dnL38fX2i/MJioxOS\n        Ezjc6JSMmCR2dFJacip6/Fn8XK5IzMpkJ6aw4ll8Nl/ITs/MzgBdnsvhcvMkheK8kgQWr6qygZ2R7hMY\n        KhDkSQoKcyV5ohxJWrqIky3I4edxeUJ+jkgoyi8oLsvLL8jNEYvzJLBLmJtfVFrG5wkzMnjCXImkoITH\n        5UsK84EDPP0DI6PjcgvzWRlpKUlpwSFR3qEJoTFsJy+Pt29Mnzw0j0xOTuFk+AaG2Lh7fvOw/2VpE+QT\n        /d3S2crGwcnTz+yX7edvRg8NPv74aWNkZXHn8ScDQ9P7b9/cffz+7QfTz7+cD526eu7y4yOX7m7bcRhQ\n        DPQpYCv2slcB1QzbGAJVIKJ+PL0H2+6j/0cZrQEAdwBiAH0M/AKCg+ydiI0TQE2jzx3RDbuzYeo97AcE\n        V8M+DajrYQD8YSSAWAPAAejomETlCyHgjrt94Fb/zQUi84FtYBhcJp7YChiURksFDRSEdVUs1MKTibcd\n        n0iQFDkD8R2jvnAaTAmvRVZDboBb4W2BVGBKmuiewugCenjGXw2uIjqdco6Ne8NgoC+IID7sAaAn0I+I\n        D0xJKgOUgUqp3408BU0EpB/iC8K7Yacg/KlhGoAEG3YePI4EgIFbgPiJaijz//X5IPojAQBdYQX1+Fd1\n        rSnYC+j5x9+P3/9+Zmj98ru9ka3bL2f322+MNuw6vnzj3uefTRuHR//55x/f6PiJmjpMeeUZ2tpTZWgA\n        0+jOZiIog46eRKOtn6LtaeP84vEbDTpdiUbTYU6YJkuaemJPN/pUxEdqoAVAvEMIuAsUcTkwRH+i9IEM\n        5o/nAmH6JtwBroVBRWtnEBsCrQF5+mxFTBCisn0oOQ+fK0mu5xplRHDMLwJiIF+BA+bJo4No00Rc4R3k\n        /BIlNBoWymPKPwj/NcT7hAmj6ORBQ2ExkfyzsFcEGBboCEIeUhgv8aVW9NVmIgEAGcC2hhzJ5yHxYYB+\n        LaYMRQBqmAuE1g+QGRwFAoATZijQpysgAQDoTyLZnwD9lNsHNtRkZdRlcTUYQHyqCgykPfH1owVAgF4G\n        bAKgDSAAeUIA1FH4RNDHAfgvQ5sgI89kMGk0XU31Xes2Ht54xOHxh4KszL7KxkRDi3S/gNaikuaykqbq\n        utbausr0tMoUTmdx7Z8//09PfXNva1t3XWODUAQ2QXOuuK2isqmkDHC+v6kdM0QbGkeHhkdHMNN/FPR+\n        /0BfR3tXfQNYAH/++h+sAYZjsLOzq7+7F6sCxrAf3OjwaEdjc0NZZU9rR0d7S3dv1/Bgf0ttXam4sLao\n        or9voKert7KsvLaqpp2kALW3d0m7pb29fSN//aequEyUwalvqe/p6yvMKxFk8gvzCsrySgry8gslkibA\n        +oHBnl6ptA9oaoS0revpGejrHx4ZGP1L+udPz7C076+hxpKaalZidbhvkZsD1/hV2Il9Hvs2OO/aarZ+\n        7bd1K402rfi8aemHdcverV/6ZN2Kl7u3/bpx2uniVc+bN1nmxklv39oaWZn+dnV39A6PY7t4e/v4Rzr4\n        hv92dnP2DPLwifLwCwqOTAiOSohJYCckZ8SnZCSlZbOyeGkg/zkZmTm5XJ44SyCIi0uMjWPHsjPCo+PT\n        MwViSYEgO5fNyczk8XPERZLyUnExZnOGRMQERyeLJAUFxaWpXF5SJic5KVvEE0ZHxwlFhfXNbdW1dcUF\n        pax0HjBHU1NzeXl5aWmJOD+fm5EXHB0blZiSyRHFJrELiyQ5OaKQ2ERejjg8IvH3bzdH9zD/kMSw8Oik\n        2GRTcxe/4NCYxOTQ6DQrW3dHX2dnb29bez/Db5YfjX7aeHm//Why/8mbb9a/rr97+9nS5uG7T48NPplZ\n        uRmY/Dh/676B0e8nn7+evHTj+JmbmzbvYTBlAZJQjxOXtyKm1QPaUsFVzPDBdptkeSx0d2AYk/hhiAYH\n        aCNYhtkvOBCaMeMFbgWgTDbQa68KiK+B94evcBrxigAlYHY/4RLgDMwuxUNADOgdAuyDk0lAGAu40DWE\n        ThWC2uMzQQZC/CUgjpYELgCA6+4SCkFWwG5C6MonEx4/DY0GuHB82jg3xH1NwFyYA9gHxE1EUB5VP7Et\n        gAOoS3AgDcBQUJyI3f+BgZRV5BQU0TYiPTOAGyhDCg4hK2BbCJw50gDFBMQOgN8bzRfFSQADG3ceouoA\n        0DT5LwEgB1Bwj3YAKQ4gBAADewEBARjaPHv/69E7ixdGdgbmzib2nr+dPe6/Nd5+8NyGnUc37z5hYufx\n        n3/+Gfo//79bz9/QyB9tBraDBugHUAZY1JNjAjSr02j7Fy90dfC4dfWuloyMKo2mzpgwjYkAOkueiWUB\n        pAxqiqzMdFnsHIclArKYlgNwv5j0AZ0vzySVulifNR/Tb9ALBBYGEAAR+yQYS4AY4H4+NukE+Ea3D6j7\n        1SoYGADxDp9rlHBl4NUq9FXKmJYK91+mjNHg5UqM1cQOmIPQT56oiN2kt6lgJTDofdgP70WR0yKSPIqp\n        R2iRYLHxHFwAAEuap5Flv1DRY/s25LMpxPMD4E4yguiaTLLaAWzIkZ4/xJQBDgDon0R2ziPlDtPkQelT\n        6f8yExl0JSBOGKQ1NFgJwAco9okFoECgn0GGrAwJBlAEIEsRAKI/RQCg/f/NAgIrAKMFshNoaoqKa+fP\n        X7d4g9Hdl6IkdlmGsCw9vTAivj6D19FY11HfVJaZmxcSVZWUVsPLbSwqbykp72lqaS4qaSst72lpay+v\n        bKuqbC6p6Kiu625owPWBe3qxHGxwFDB9bOTP6OAIQL+0sxMbBA2D/v/rzwg2hgOLASMEY2PDI0MDvb09\n        bV29nV0t9XWNpdU9Lc3d3Z2tjY3FuWLs9iMpaKqvrygtKcsrbKqvq6+pq69r6eqW9vT0dXZ2d7T3VJdX\n        SvLExaXFXR2deVk5eXxBVXV9Q0MrWAO1dbVdHd1dnXAuTKK3t79vaPSvobHRurra5oaWhtJqSQa3oqqu\n        qbS1LDRKHB/c2VXfnp9ZnxRe5GqV+uxhytNHgWfO2+7ZbL5no+vhnT+2rr+9dsXppQs+7tpqd/WCzYWL\n        9mfO+l+5FXbrYeQv69dfbWzsHIwtbC/df+PvFebkgf01PTyibVwDnLwCg8Nj0lmcgPDIkJCYiNCkyISk\n        5DQ2m8OJTU1NZWekpmSw2Nw0FicuOTU6PjU2iZWaxs8VFvNzCzOFwoSUDKFAwEnPzubnVlZXikT5iazs\n        lLTsLL5EUCBO5nI52aK4+HRWRpYoLzcbxH4mNzdPzBflxcSzQPiLJUX8HDASJImpnJjE+OgEdlR0SkR8\n        ileQf1BYdEhMckhUXAaXm5yc7hsQ5ezjFxweZWvrbWRh/830Z0JCsqd/nL0DvECwT1SYsbnjhWsvXrz9\n        /MPS7oeV+4v35ve/fHhjaWaDTUPtv/4wf2784/bHryZGDgf0rx28ePnR209nbt5bsm4j2JwYysRGOjqA\n        dwB8oFXVsV+bNqCe8n9xkGRGgrAFFAaMYzLkZOXkMQ1GEX3f8gpKeDJ621GAEycP4iliPTZ1ABQGgY9h\n        VaQEoAfi60fnODZ9Qz7AOC3iL+zXQmMCOAM4YJK6qqq6uoY2ojCl/VHFI7wSMIVHYINoQGF4HOyH98AT\n        iOkAgAuKm5QFYGchAuXwODyfILgyvBfhG2QI2Ea3D9gThCcAi0GPEx8OXIU+KyVcxYXkgOJKCfALAA3g\n        r4EefyLnkTPAAlBQgnPgQvII/GVgP9yExFGQwIAMMOGVtJpQVlZlMOW27NM/c/OJmvZUZaArys8z7vyh\n        BvUVDQK0A+AEqhcQWAAvP1s9/vDrhbHd+19O3+09fzl53Dcw3n300sHTVw+dvrnv2DUr9wAwAv7655+v\n        P37DCwAH6DAm6JGgLtoBqMqZ05kycGD/8qWWv51PHz6hSKPJ02iqDBngiUWgoEkwYDITcBOtAU0QyKSB\n        qB62/kdARA87cdQsVmLOU5AFaIbzZ5AsUoBOGID+8CwAYmAUgGa44UpQ+oQDFgLiqyDug64HDlinxNhI\n        jAAggJUqQACYNgp6fznR9Ssx3YgxTw4tBkB/uHAV1YQObksCEhQhEaMBThtvbgqGBXydiQMBXQfL2Rha\n        SAAyk0m8F0wBgH6gAUB/qvcDDOLtQa8XvDWcBtA/SQ5jwkAqemDiyNM1GXQVUP0U9MNAWEcCALMAXUAA\n        3wxM7AFwJ+n/FMQDAdAVQPuPu4Aoz89/CYAaGAlgMhhMGQwX02m0pTOmbVq67szeE9Fermk+vtV5ku7a\n        6gZxXlt1Q3t5TUVaVo1AWC0S5sVGF2dmtFXVSFvb+qXSof7BnvauSpGwrljSXdcEZ/Z2dPR2dY4Mjw5J\n        B/q6eoeHhkDg//nzN3Z/Gxz6M/bX0MDgGHYHwi5Ao0O4Vhhs9PVIu5s7Wuubuzs7ANTbwMJoa29tbiyX\n        5Jfk5FaXllUWlRRLxGWgd3MkZfkFVdWVHZ24YExDc1tPj7S3R9rT3d3U1FBZXdXU3NLa2tLa0gQn9PYO\n        9HT39A0O9A0MSYeG+8b+7h380wFWSkNTXbYkJzCUHxfLd/VgGbzkfDVkP/sg/vwq5v2LZEeffA/3/AjP\n        upSEnI9f01/cZT24En/hePiZA95bN31csvje0rlPFs2237op9PIl70P7nPfser9hm82pU1GPX3x+Y3r+\n        4fNj+hcePTOxsvI2N7V1dwp0cQ/1CYmMY6cFR0UHBkWFRcRGJ8RERMb5+0f7BER4+/h5+PmHx8SmcXlp\n        GQjcQAmJCWkZ/JywqKTYGBb6cwqLU1jZcUmpGRwen58nyC3IlZRl80UcFlcokHCy+T5+EZmZGVHxqYnp\n        3ILS4ozMrNy8wsraxrKSMr5QwBNIeKI8oVCCpFBWwOOJXLyC/GLjswWiRFaaR0hEYFR0XBIrIDI2KCw+\n        JDwRHhSbmOgeGGjr4fXD1skvKCw8Ntk/JOanpZ23j+9vO5fP5jZmllZfTX+/+mhiYef22dzJ2s7jp4Pb\n        TwcnM0uXy7dePXn97dU3i0Pn7h89dvPq48fXP7yfs2wVGJ2ghbHDM/ZLAAjGNj4IvtiCXxswF5BOWRnU\n        CKasMJmy8NdzAvwtlVNWxGwcrBejy8rKyKFTE/4CAx8QKQ2wjoVXWPClRm6ohjtR/AKeYooL+mQwA0cD\n        1wlA6FcDOEaHDGzgTDAwQNEDZp3CV6AQ+DruokHnD4prslYXEgCR9piYBI+HbeL2IRYGoS50DZGnI7Kj\n        nMcqXAB0tDDQ46SFgRCK6tBkwS7QKhMB9PFWJPOVPJqYBYR+kAJJvBdbQeA5xEKCR2MAgDiC5GEmSlhG\n        h0mlJIqA9QFoBFBTgtfBX4App7DtwLFzt55iN9BxAsA6gHHQV8MIMOEA2EN2wlfKAjD4ZvPik9X9t+Yv\n        Tew/WbqbOXhaOLrffPF1r/7lI2dvnrn25PCZm1v2nv7606F7DCjgn7DQcGAryg4AUAZ8B3kOnyDzZzFp\n        U2i0c3v3/frtumPlKgUajUmjTWLIzJXHoCt6VEhNLKpjQHZyFSAjCHzA9AXEBbRMCcsCwBRAAlDASjEA\n        feQY8gmUAModPgGIlwDQqwDWMxei3YD4vpb4guAoYDeI+q3KjPUqpJ6AUMUy7AOKnpwVGATG7kNAFWvh\n        HFIuQHmfgAP0yJ3h/NXK6DsCi2EpWRkGOAO4B6gO0Hwqan/M7tcmgV9qACXAVyL/UfuryzFI4j+GOuaQ\n        ggCSIYrhAQ0mbk9FIsGlYMarvf4dKoQAYEOBjmQAHAD4jo4dEP4UB8hQ/h/kAAU6Q06GRIYJBwD0g+yn\n        HEG4RZeZgOYClmprKCtsWrPu8Po99u8eZQS4lwnFvXUNNVmi6kxxnaiwmptdlJ1WAhKbk12SwWutqO5q\n        au1uaetubuxsaa2XFNSLctvqG0C/97Z2DPZLcfHIwSGgh77O7qG+wbGxMdIVbngE/wyPkfT/0ZExODTQ\n        Kx2QDmCdb0trc219VxuuCtlc21BbXF5eWFiaIy4V5pYVFFYUlZblF5VKCvK43MKcvNqmxtauru6u9tb2\n        tpb2TrQuuvAGPcAGcM+hYVD6/YNYcDwA3POf/9M9ONbe1leZnisJj8zz9Mtz8y8O8hN8+cD98Kbsx1vB\n        dX3BxcPCc4d5d86lXToee3h/+OFtYcd3xJ08UvD4dM7lfZlHt/JO7s3W3x2/dlnQ6kXxW5cnbFiesHtD\n        lv6OzI3LUjcuC9632fPsKZ8LFx1evNp35d6RU9fefjJ+8/q7uYnzL3PnN68MLX+7xHMy7Tw9DK3svlu7\n        Wzq7hCfFR6WyAoMjvNz9A3yi4lM4mdixR5LCzoxNSElMTUvPEiSz2BGxUbl5kqKSCr4gBw6nZPBFAoDy\n        3Nyi0tKysjxxrihHCKdmZfIyszK5opxUNp8nEHN5mARa39KeJ8nPyc2pr2nIyS3Ky5UUFZSUV1VlZfFY\n        WVnZeXmc7OzUdF5UUoa9d4BTYEBUTIKDk6+3V0RYcLxveGxwVPy3b1ZRcakffjr+cPKKiIjxAmvGN9zG\n        zf/7T+d7r79+s7Ix+unm7B7o4uH57KPRgzcfDb+bff9ldffup2evv775bvjk1YeHz968+Gx06dHb+UvW\n        yshMACwDhKJULeAdeuQBpADBNTRBU4MsmTCBQWcqysoCnGnNmrvi4MmrNwzen7rxdNPuU5t3Hti79/j2\n        3ceXb9yhPUNPRVVLVkEZjAMlgDrSyl9dczJsYFoncc4QJMUNYgogrqF4Jw4lqmoX9TLKfOKJQnTGwABa\n        FdgSB1EY8JRYAHgJEf4YV4DTiJse3wKzLfGG2OkToBwMAkXU8nBDrK6iHEoEkTGYoQT3xEwhgsjIIhPh\n        K2zjIWJtqJAUIJwGBoSR8EhYGE0N6hcjhgjYBxPlqPAv8REhFWGcAIeiAqbJUnOGRxA2gm01RRU1WXnF\n        HYeOX7j7TF17CkUA8JsQOwm9QP/X80OxAvm5gAYwBmDwzfbJu5/XHn9+9NHiwy8PU0fPH3ZuVx9/3HHw\n        9P7jlw+fuXHozPWD524dvvzgh4tvS9/gaEer6fsPSkoqMjTaZCZtBsmKIQVfmEevJ0ObJUO7eenGd1Pb\n        rYuXyJFuQcqkUQQQwFwSuZ0si1Vg02Qx0ROlPcnuXwpATFrCLSDRVzgTQH8O6G5kDuzhDBtIAyQGACcs\n        xe4RaDGAYAeFPgfsDBIAALBeJM/coMTcO5GxE9Q9FpfBbem4qjDJSoLTQPhvUaEvV6YvJk2k4RxkDkXG\n        bEJRcHOsBlAEM4K+HU5QZi5WwuqtOQrM2Qokq5U4fwDlAfeBxqYQ7z8V+EW3j+y4/FdBpxAQEra7QIbA\n        3FAMgJPIAf5cOmQdGBUGJoACByiSRCAgABjy+N8KfsI2cADx52CjfzkGuoPAAlAcXyeAAecAB2DGJ4F+\n        OBG1P50Bn/BlApAHQ0YZFBWNtmDmTP3dx16cvBjr5FhbkC9taC7hcMvZvEZJSQGbI05NLRIJ87NyK3Mk\n        TYXFXbVt0tb2rpamrs52aXtbd11tc3VVa1V1f0dnf08P2AGjw8N/Rkf7cNmvbuz5Q9I6hwb6SY+gv8EI\n        GOzv7++VDvcPdmPdb1MHiPaqup7WdmlXRz0o/MKCiqKifHFugUBUIhDncAUVhWVVJaV5Al6uQNTe3int\n        Hejt6QPEr6lrbGlp7++XdoMhIO3tlnb39A4Mjv7dMzLS1jtQX91SnJQhDg3LsXXIfHSbe/985sUzuS/u\n        FZg84t++wL1yWnLjNP/k/oyzB7JPHxBc2i84fSjv4r6cI+tFR3dknNvNOrWPtXtz7Jal6Yc2CfR3pG9d\n        y961LmPb+tTVCxMOrmftX8/avSrj+HbxuUOiZ0/j330Mu3fv2pnTpx4+O3P5xoXb9759Mn/79OvJC/dv\n        3TWw9wo0NDc/d+3G1mPXT1x95xEQmiHkp3A40YkpKclZSYkZCSkZWVxRNjcvJoETnZAeE5taVFgoyhHn\n        iCVllTXYIkKSz8+XZGeIcgT5wpw8bhY3S8AT5edxBTnCHAlflM/OELLS+awMfm5+sThfwufx62qacnj5\n        OcK8qrqGjEx+Who3JTkDqKOoopovzhNJCsOiWSkZ3FhWKkeMMeTw8CgPd287W6+Q2DhHT18bO3dHj0Az\n        W+83H03N7RyCI2Ps3H1fGpsZ/3KzdvX6bGL+86ePh3ekiZnluQdPv5r+fGZgeOvF0wevjK8/eP/pvemb\n        p1+evf/8wMz09mvDJcs3y8jQ0XcBOAXQRtwXSgiI6oBfIEJA6k/U0p63avWOQwe3HDy09cTJJ29MQ4KS\n        vYJDLlx5sGzD7kOnz//4YW310+PZy8/Xnr/Xv/Bk1eb9U6cvlFOYKAtUoAS2BXpx0KTAMADiPqA2hmrR\n        RMCaXsB6AuWIsID+FF7DTOA0EplA8CWedKKg0QigklPRjY6HUFDjVYDC6G3H/bjqJHwlF8IJGoDv//r3\n        Uc4rYTQbww9KVGgB76w+EbFVE07AQ6jQsdyBXIt+IeAS6qFwZ3QEYfEB4UskG+AM4CTEfRT7xAqBHxN+\n        UnlFJcwQlVfASwgzoekAG/DWk7CXnJyCws7DJy7efaE1ZQYSAHH44MozCPfjSwJgayAM/1KWwf8lALun\n        739eum9w/bnhCxO7b9ZupnZuN1583nXk/B79c3uOXjhw4urZe6/ufvj+zcrp7qsPz07o8yND35v8VFRQ\n        BI0/XW4C6OJpTOzwM1MW8/qxgT6TfvvKrXcfTTcuWwkcAH+UsI2aDKp4YjHgYoqkHw6AKRoQ8vT5StiD\n        AdAfBlgAgOlIAFQkFhNAx60B0P5AAPPlGYvl0VYApAYEBxoAcF+gSJZ2IV3hVikxt6gwNylhJACMAOAV\n        APEVSpjfCeesAnVPQs3kKsw+gvvAU+BxMIAwqIg0nLBVBU0BPRIhWExICJ4+laQA4Qr48C6Y1IR5n4jv\n        VKkzafsDwA3yfwp5O6A6bewQh2eSamF865m4Bzv+K9Nl/iv/YaDnB0vDsPEDOnAI1suTJhBgF8syZHCJ\n        GJD8pCwA0B87QlNLQpJQMJwDJxIOQCaAHbBTnsmAfwUKsoxtG3bev3jf8eO3aAevmkxRa1FhJVfQUlIB\n        0jsnjVXA41QXFHU1dLSU1vQ2tg509bbXtfS0dQ5KpQMd3b2Nzd319YPdPf2d3cOD6OcBsY/lwAODg7g2\n        AGn9hhUAQ2Txl1G4ahBEem9/V0t7V3sHafpW11xd3VBaUV1SWlNRUllWVlpSkMMX5GbwCnP4TfVVzQ31\n        5SUl5WUlrW1NHVge0C3t6unp7IbR0drRNzg0MPoXTKSyrKYsr7aEzRH5+aS9fMc+cTT94tHc28dyHupn\n        Xz3JvXYy9/HxBP0dEacOpV7XTz++k3tkZ/qR3fH6e2KP7/PatTbl2C7hqQNZJw5yzx3JOnUgbffm4OWL\n        Ereu5u7fELNmScS6lclrl4cvnh24am7q3lXJ+zbEHtzGv3gs9u71kA8fox48C7h61c7S6tTNZw8ev3/8\n        0OD2g+cnb989d+3B22/fjUwtT5+/cun+8ycfvzt4BIRFJgdHp8SnZ7EyuHGpaQnp/Iys3CROJjsjKzIq\n        JTIukQeSPrcoky8Q5uQLhXlczBSScIXCnFwJny8W5eYkpbKzgQoKi7hicbpQHB2bmpXNlxSX5OYVpbLT\n        udncspIqSWFpflGxKFeSyMkKiYqNZXHySksyuDloasSnsFhcv5B47+CItIzMhKR0Dpvj5xNg/NPJzsvT\n        LzI0KCbe3MrDPzA+PDj6+29r35AQFycfG3d3c1dHY3t3Z/cgZzfv159NDM3sPxn/fvfxs527z+N3Hx8a\n        fH7w/KvZb9fbTz/eefT+qaHhzbefFqAFQMe1TUgxF0AqQBWdibgvKyc3ZYbetn3Hzl95+vK9kb2z6wtD\n        80vP3jz68u3lp2+nTt6cprdgorrakk1bH77+/OKN0QH9K+fvvv9kbvfZyPrivbcb9x9cMH/p5Om6Supa\n        soCCKipYC4bZOCDYSWgXkR3tDAphCRMAiKOvhnhjMIkI3fe4LBeiMDpk/htKRaxHf85EQHNU1sAoqOvR\n        lQQyH4Q8iUagtEd7AnMxkQPQ1MDYLEFwDCADglOYDtCviq3/8XLEehL1RUcQCeESoEfioZw5aDDBwDuo\n        oGMH/VFolBBYV8OFX3DxLwBadAGRamEEfTgBP+FHJolAsK2srAJHdx4+eeOJge68xQpKMA0dXAsMlyzW\n        BKAH3FfTmgyDEMD/HRQBYBbQrZdGD96ZvzKx//zbxcLB9dlns0Nnbu87fmnPkQuHTl0//+D1gy+mdv6h\n        t5590KTRHmxe7e0buHXPQSaNpjWBBqAP6El56jFUKyejQ6MBXl86cebpa8M1C5eA/AQ7QIUxQYuk/+ui\n        PwQrA4AD8CpgDnnMBVoJRgCB2lnymF1KwfEcxH3EUDAygAxAp4M1sFSRuQioQoGxBpv/IAEApq8Ata6E\n        DaLBDlitJLtOibkRfUHMjcTLj2k/GAGmb1BCt88KkP9gUhCxvxatATQjcCgg3IMpsJxklFJR5dnUTEjf\n        aXhZwHF4TV15zGoFUQ/gDpQAuA/afwpaANjdU4kkdJKAB+p9TTiBqP6p2CUUrsIlE+D1J/7r/wH5T32S\n        FE/MC1IGDiA+HwroiZ8HBwh/IAkgBnIUNpgKdAahAYL34wM4gPyRQdogX7Bv60K9Bfev3jR58sjj+4+y\n        NF6TWFzK4TSLC2skBfxkdmE2r6mmqq2xpa2upQWz6UtaC0obJUWNJaWt5RWDHd2j0oHBjp5B6QDo+lEQ\n        /WNjVI7/KMA9dnboI30dqEUCMOcHrASQ/J1NLX2g3bt7O5qbG+trW+vq6kGj5kvK8vNLc3JEWdm8LC4Y\n        BFWl+ZUVpejcb+vo6unq6OroARNACvcdaO/uqaxrqKiqq6ioLUrlFbv7xz56xD5/QXTtHOfi3vRzh3Ov\n        HCu8dlxy/xQfNP7V4+Jnl9hXD0Xo70g8fYB7+Vj8/k1xezYl6+8J3bst+si2lLN7E09szzq1J+7Qpuyz\n        O9n7N4SuXxK+ZVXMhuUhqxe6L1/gvWJR0JqlwWsWRm5ZHbR3S/jurUlXL/vev+Vx9ZLVidOWF06Hmxle\n        u/Py5sOv1+6/u/7krf7587sPHLt09fHpGw8Pnrz88sm7Vx+Nrz14/eWThcUvR++QkKDw6IxssUhYEBOR\n        EB0Tn5KVxcnmJqUkJ6ayONlCrqggkyeS5OVl8HkJqel5RaUSSUFGVnYyJ5OTwecKhMWllaXlNcLcvKQU\n        djZfWABwL5akZQhyxPmcrCxxSbEoT5LOyoplsXk5/OwcIYvH5wiESaz0mLi4spKSxGS2tbuLm5ebt3fA\n        DysHOycPSxcPZx+/5LTsyOjUr0ZWxnZ23oER4UEx9k6u7l6e3m6e5r/tTH47mvxy/Wnp/OsH2AluH4ys\n        3huYWDk7P39t8t3C8f27r58+Gz7/ZH7p9tPnBu9vPf8yZ+Ey+KsGeDSRaFgZBoNGlwGhOn3m7BVrdtx5\n        9tbDP8jRxs/EzObpB7Ntey/pzl41b8WGZet3TJm1UAnU8STVecvWbN97du3m/ZNnLZg2e/mBs9fO3Xp+\n        /fkH81/WxmbWt569Pn/xzuIV65nySnJyGKydiG59TWU1DQKCAOzYNBRxFjEUvTqA44jdKMA1sXsPemPQ\n        8wO4id4hRFtU+kRHo7QHICboTKwKRHC4M8I3gWlVFeI4gm2kAbgcI7cTAZEBeUGMEwNCjdgoWmoa2kgb\n        mDaKfEOVgCkoKxPExyxYJCfYL0/8PNjIAQuDsRUoZTYhJaigz0dBUVZOnikrCxtwJrX8C9yZ2BbodCLu\n        qUkTVXGPnILKrsOnbz57O3v+EtiehOme1EqW4yFf7P3578IAMNAp9L/SQC0fvbV4Y+r02cbL2NbdkhDA\n        wTM39x27iBbAqWvnHry6+dbQzi/MwtV/2dwFU2m0Ezu2XbpxZ/Ys3Yk02jw5GZDYumRJAMzaxIUY6ZNh\n        vwzt5skzj198Wjl/kTKNBioUpKs6aQUxEysDMHkGPjG6C0pfEb00wAEgyWcQKwFwH2gAVD/gL+hlOAcg\n        m0rfXEpygSi8Xggyn2D6KmVcv3etMmOzCmM9RoOZm1QY+1UY2ycylmNGECaGLlSkw8kblBnrlOnAAWAB\n        APTDaauUCLuQmgDYAHNkkwp9G7YVQuthJTyFlIYBYcBkdBVkpuO6lZg2qsnEJqBU1j98aqIXiCr9xUVg\n        gLcA7qloAfAEGATUnimyMkB7cBo2faPTJ/4r/wHE5Rj0SXS6BgOXjAeUB/0OQA8coMCQQVsBLQAkAPiE\n        /bIYAGAoMpkYEyZhAGIEoB0gg5mgE2QmwB0YQADECURjMhiX9uyzvP/Iz9qUn8Qqyc6pyeN1lhU3Soor\n        ikuqiysqS0samur6UfvXNhYUtJeWNBfnNxRKWstL26uqeptb+5EA+oelA6D3B3qxWGwMGz7/GR4cGhrq\n        x9SgIeCEsaHhwZGx0aHewf4OEO9t3W1dHXUNDdW17Y0tvR2tddVVpUWFZfl5RVncAhG/tLCgLC8/X5Bd\n        UiSuLC5qrmvq6xvo7uoG+O/s7G1oaK0sLMoJDmcbm6cbvEi5ekZ0ZA9rzxr2qd2S+yd59w6nXTzCPXWA\n        e2Jf8qn9yaf3JJ/YnHRiF+fUbuHpjdwzu1KP7fLZsc5hwxqnTatCd6zhH92ZcGR76um9mWf2pOzfHr99\n        XczqeeGbFjtvW+m+YXnCthWeaxc4rlqUdXRn1sl9ITs2+G1bFbJzvdvxXRYX9F0uX3q7Y8+1rdstL129\n        emj/Tv0T994avTWxuXDj4bkzt86fvblp+8Fjp69fvP7k0MnrJ0+fv379/pUHL288f/XDwiEwMCEqMi42\n        Ji46OjmZxU1NTYeN1LRsdnomh8stKCgQ5uZHJKWwMjiC3AJRbnEyOysjUyQQ5mXzcguKS0tKy/MLysqq\n        qorLKnLF4uKykrLqam6OOCE5LZWTVVhYVlNbm5GZycsVc9K5iQnpYGew0tPDI2NS2VyPQH+vkAAgh7j4\n        NAd3f3svz5DICFYaPzopzc8/xs7Rw9Dyu9mvX4GBce6egS9fGRh/++nkGGD0w97Y2tnU2u6Xtds3C5sP\n        xtbW9j4uTp6PHnz7aGT37rPhh48fH7wwPnHu1pPX7x+/NlqwdDWIDYBItPdB7alqzV+2Zs3m/UdOX7G2\n        87R3CPpi9uubmdnjF+827j89dc5iFYDASeqTp8zClpkknX/6ND29+UumztCdpKY2ffbcZZt2z168YfGa\n        vWALhEcmRkYl+rn5GP2wPnPlybQ5S+UA+ABklVUwAxIkEJMpJ8dUUFJWRiEPgI51W8SfA7iMrT0nYeUw\n        IDsIcBDOeIigP9WpDRGZQP94nj6VwINfiX7/11OPJxAQR4JRwqb82K0BBrDORMxHmoQBagw2YORDWRnN\n        BaABoBbkANLmCDU7ce/ArUjmD/rKiMAn3h60JNCkkAeSA+2PFoAioD98yimQ6jAMFMOjMWwAD8L7Y/CZ\n        8gJN2nn41M2nb/XmLZaDKWLTOgL0muPLAv9/LQASE/6XAN7/uvf6xytTZ0N7X3NHTwt7t/tvjfefuLJX\n        /8Ju/Qv7T1w+d//lrbeGVj5Bv9z81y9biYvl0mjrly3dt2//DC1NbcB67J6GHvm5ANxkiRXggJk02tqJ\n        8vcv37z36N2GNRuUZGgAQop0DAvPkqXPxyRLlP9wvi7BVkBeyvGygHT+odrJARlQ/SSAAODQInnSsp8E\n        HqhWQkAAaxDNxx07AO7rVfATxbsyA+T/jokkGkySf5aTQPEyJACEfmQFcibcGVuEkjnAzo3KSB7rVOAQ\n        Ey7BE3AhSVzBkRL7AOKg6wHx0bmPgV8kMx05UP3Y001NVkaH6n2EBQF0yuk/GeU/MQhIDFydgf1BJzEZ\n        E0kTCLADiMwnOaDYEBQHFQGGAYeI8EcCAPQnbiIkBsr1L4+94RjwCej/34FBA0ICwAdMBqEEGTQCVuvN\n        fX/lvr3Jz2gXTwmb01yU11FU1FXf1N7S2drc1tXd2dXS2l5VJ21vb8Nlq8Qt5YUtpaVtNbXdrfW9rU2d\n        tU2d5bXSjvbe9nZpe+dgP/Z/BjLAMTw6NDAw1DcwMjiCjR+kfYM9OHraO7tb29vq6hsqKtvr6ltByxeV\n        4MqHueJCHr8wT1yen1+Sl5+TnVWQnZmbzsrPz2lp7mhp625p76vMK82Jjivys8//8izz+PGUvZvZR7cJ\n        zh0QnD6ace6g4NZh1un90fvWR+/ZGL1nQ9ju1UHb1sTtX+u6aemnBfMtNi5z2rUSENxr02rHtUu+Ll74\n        Y9XixAMbs89sTz67NeH87qyTu0I3LPNZOt9h6Xy/NYsS1i1JWL0wasXCsG0r+Zd2l947ITy9P3CRns+y\n        OZEHtprt3Gp+6Pijzdvf7Tny6/T1Q5vX7d25687tl7effDpy9tb+Ayd37z28esP2nQdO7te/vP/Q+VNX\n        r5+5ee/kjYd3H39+eMfg8oP3n83sXb3C4pI4ceGpIWFxrCx+ZrogMiKOw8vOzc1NzxKFRsRkpGdy+aKE\n        lLSsrLw8YQGuFFlUDuifm5/P5vMqKqoLi8rF+Vj8kJUtzMstzBVKsvkidhY/QyhISU+JTkhJSeGICwqC\n        o6I8vXzdfYOcvQIj4+PDoxOCQpMjElOCI5NcfAKMLH57+oV6BES4eYXFxsUEBQfbOru9/frzl6Onq7P/\n        Twvrd4Y/ze39zWzdTax//rR1Mbb0MLRy+GFva/jd+uajN0/fvDez+vnkw4czV59evfv6zqsPD94YLVy5\n        noJ+RSXV/cdOvzYwvnfv+bkb99/+tvQJDnvzyuzM5Yf3n785debe/GUb1CZP1p4yRWfyNA0t7cnTZs2a\n        PU937sLpevOmzNDVwpUXJ0+erjd93iJt+D5/2Ys3X+LjWCEx8W8+mDw0+OYYFmTh4Hzw7K2Zi1dPnrlg\n        ydqNWw8dXrfl4Jwlq8AaIHJZRRld7VrYQROhGct6sUYMMZpy6QABkBweIADEYuJyIRVnBFJR4CNSE1Yg\n        lEAQn3LKYyrOuGcJrAFSqwX8ge4dMB0I3yDo41ElbCRHmIM4f7AzBHAWsoi8ItgNmPRJOACrvWDSuAdv\n        iwYBIr68Ai7+rghoP0leEcPCQADEOtGkailIDAMJAK0cvHDSrqOngQBmL1iqoATcSlI/ifZHMtDQpgIA\n        OGAnoD/ux7g61gG8wjRQ67c/PI0d/H84en+3dbn+5NPOw+d2HTm74/CZvccunb334ubbr1ZeQT8cfdYs\n        WQ7qfjqNpkmj7diwfuf2nWpyzMkyNCqXBkQxjPnyOKYDvtNooMoPrl1/6vztzdv2qasoy9NoChNoGkzM\n        jSG+o/FET1DWAOUw0Akjh52fZwEB/LtmAHwFQwFIYgHp/IMynHQTmkdYAUCcGAforwdpv5g09sFaMFw7\n        nr5LhbFPBf08q4AnSH4nEAYcBXCH0wDx4YlwQ6r5D/EvYabQfLL+zAoMLNPnEtc/sUsAxFHaa5E13IEA\n        ZsgTdY9JQQj9oOgB1uEogD5FEnCaJgMZAk6j2AIOwU5Vpgx8qv2bA0qhP2yrMwD6sSk0oDzshEGKgXEo\n        0SkjAOW/AhPDAMgBMLAzBHqBSJyAsgAI4pPgMdmGD4wPw3+fTBmZK/onHA2/+9vaZQZHdEokfRVlXbW1\n        0rbewa7eFhDpFdWdzS3d7Z29zS2tVRXVQn5zYXFLWTUYBPVFRc3FZe0Vtd2d7cPDg2Og9bHJ/xB2BgIa\n        GB4dxUyg4cE+6XBfn7S9Q9rR0dfVA9Df2dTc3dHe2lDX3dTcUlVbUwKGRVFToaRcKK7MkVQXivMzMkui\n        4sRR0eUigD1+ET+rKDGlIDxBaGzGfXBN8uRyxd0zxZf2C84dSb9wNPPCIf7J3Wn623jH93L2boG/kc6r\n        FnusWey2cr7L6oWuKxc5rFxis2jha705rxbN/rV2qdO6lW8W6Rkvnm23ZqH99hWxx7YH7F4VsXd90L71\n        IeuWha9fZLRAz3Th7LA1i2Lmzw1aNNd11aKEHWtyru0RnN4bs3qJ85r5VhtWP9m6+cqGTVc3bLqxfcel\n        Xbv2rt1wdO/Rk4eObd20Y/qsBaqa2jrTZkybOUdn6uzpurMXLFk3d8GqpavXrduyc8PGPVt3HX/60eTx\n        S6Nnnx1/mbtG+EclcbKT2WkJSem+wREZfB6bLwiPTWKx2BnczDQOiPq0bFwtoFhSWFpSUcYT5nJz8rOE\n        ovyiooKS0vwiMJlKuNmi3JwcPk8AVgMYATyBIIvLS2bxwmOSUtksdjI7IZGdyOJEJsRGJyZ6+kc/evnd\n        1svrh72zm6uHX3Cwm6dvSEicqY2Ts6ubl2eAW1jILycwAEJCA0MtftgeuXL/+ddfjs7+nz+bW1h7/PgN\n        HOB4/90ng88/Xn/6/tzA4M2nr3cNvl1/+PLRu/cvTH7efP5p5pyFWIu0YYflb1v30EgLG8cP7z8/eP/h\n        lZHZ68/fT128c+DE2QMnLq7ccEBr8nRVdfUpU6dPn6E7dYbedF3dWbPngG6dOWfRVPwBZ+pMnvX/Z+wv\n        oKNK27VhMJ2k4l7ucRcCEUKIEnd395AQVxIiBIIHd3dC8EDcXYhCCBACwWlaXznnfP8/a+ab+34q9Onz\n        rZk1w3pW9a5dT+29i+6+rut2vibygaoaXaCt5xUSm5JfHJicbekcomvpEJKS+KildWh4ftu+My4J+Zm1\n        NTfu371698mBs9eCwjKodCHYAujVUcZmn0pqJA+VuOOViZ8HxDIg5moAGYEeu7OtBnIJypMDdBABLqOQ\n        h7eI3YDgqNDJHvQaERWPjiD0OBE+AElO7AmsCcDLikre0IxQBgsAa4bhjhg8wNbJgO+A+JjrCfJfAf0/\n        gO94fZz8jhPzsTYCIR9uR7rpocGBhgjSG5YaYBAYXoEGcAoNeo0UwAKIzyrS0DGQllNazf8huZ6YLIvl\n        cgT9/6IBYgogARTXHM6t2JdaWF9cf3r7kSs1h84W1B3yDk+3tHO3dfG1cwtw9g4LSc1NKq0+ePHGjiPn\n        TPWNQfILpX4CO4CnIOvl6m5mYKQkJsal/MQhPm6AbH2AbBnMdkdPt5iYhpiYtVDo7xvm4RkkYLBlf3CA\n        tiyGbZEAyNgAbVmKnjwCMTqFpCXU0WmODiIAeg3RpEbiBQLIBvQH7S+aQwmojaofWzugeLckEG9G9Pta\n        Bco6BclNipJOihJ2ipIbiNhfp4iEAXRlIS8B+G5IHhWubICDISVA6WP8GQu+0Cm0ljQNhTNABmiUYBoP\n        uv5B72MtGKkBBlinS2FCJyxAeQGgPAp8IvxJXhAcq0oi4gM3oH2A+C4OlAAEoIgRYHFZ0t0BjACqhARN\n        Ajdjlucq7mPIF4+J3x82Ey+QuIgAYIHYlyJ1YWAByGLs978JAHEf/4hLYiQACQBYADhAX6C5KzX90sE9\n        7U23Pwz2/vvV7KeZ2a/PFn9fePl2eu7D82eg37+9fff59ZtPL199efnqw/Tcu+nJN0+nPiy++uP7t+/L\n        K99XPv756+///P2P337++c/ff/9f/9f//a8///Hbt2///hfgP3b0//P7r98+vv/z91+/vH3/bvH115X3\n        v3369PXDp28r7z69WPjw+s270fF3wz1LY4PT/T2LfR3Pm+8u3Lu30PZk4Ob9iSs3h+vzW8LcWiPcH4c6\n        tbus63Ky7rW3mw5y6/W1f+JscddxzS3HNZdsDBrMjS6uMTpprNNgoHXGSHe/ic4+I60GPf5WfX6Ovmai\n        pqDUQH2vifYxY/14Q60SA8HFNdpHLA1PWBtfWGd03FSvQl97v5HOxTVa2401cnTUi7TUL8B1DLTKNPiH\n        jPRu2Ky9bmFyyUz3mI1h3TpDZ0NdE3WN9boGa/X19LQ1LQ1MLAzNuEymrJQ4/H8L/8MDcIB2A9VGkZKS\n        B8kmrSghJaOgjHNF1ljY2W/ycg+OC07ML6movdN050lz572mh40PHzd39fYPj/X04eRIAPqJyYnh0ZGx\n        yadjo+NPJ6bHx6ZHJ2YnZ2cxyXNmsrm9f/rZ/OTU9Ojw05GRpw/bO/uGhrvaO+4+aH74uHVwaHR2brGj\n        o6/pzsP+npFnL551dg08uN/a1T94rrHx0Pnr9buPnr529dyFyydOXNq58+jJE1du3G8+dvzK4RNXrj5+\n        cPlW07kzVwuqqjLyKnbtO5q1deu26vpTh84XVx6JissB0V+141xMfHbSlorte45ml27N3VZfs/1wSWVd\n        cka5X1Su6Xpnd/fIUydOPW57uHPP4fTsksTC8pj0PBD+vpFpG5191lht0DezZgu0AVXVaGwqlUmjczkC\n        bS6fB9xJZ/NZXAFXXZ0rELJ56jx1fa66DpXBYbHV+dr6NC6fxhbytA2MjZ2i4/POXbh16fzDrUW7sgsq\n        6o6cPHv56oVr12413jt3vTlqcwlfS19GBgu6SNEAOpcQDbFsGCOrYBzAA6jiUEmARWIKwEkSGED3uiLZ\n        QBqUirQ5IqwSVU4OxD5Geon/B0iCcIYyBp/hW/AfAOYdkZgBXFxJmQ46XeSfQRtCEcO2ANbYEgNuhH4n\n        vBq8XUV2BH1FwgEKsnLyxO2Deh94Ba8ATIMeJ7gCxtWlfwxVhpti3BjNF+QA+KKtq29MZoFAU1dSSlYB\n        qx9A6RP/DyyC/mBaoReIOIJ+EAAT20FnFu6ITi/JrT68reFiZcPpzRX73QLjLTe62Dj72G7ytfcMCkre\n        klhSAwRQfeCEvpYeaQctzqH8BAcbjAwC/QMFDLoKDgnANnCAjzoyEnrot0HsBjClS+BOAzlpd3sXJ1d/\n        ppKStJiYvPhPdCmwA1B0gwbHSoIfeZ9wkuA+oj86grCtNPrrtUh2EPZlwyoBrADQJXNjLOQlreTRybOG\n        tACCV0tl9PyAzDeQR7EP9LCeOIhMFXBoDGwADoD9a+Up1pgDikYD8AdcCjgAQxEkZ1QLz1DAsDCUx1dt\n        OYoAfpEMUhG8cknxFyA+anbi3gHGEhJrRqT6qZKI/jQAfUkJJUkJZYq46EAJ0B/PU9RIwx8Ed3EM/6qI\n        0B/sACSA1YagIu2PC2U+cACJCRMCgNdVAvjxKdgQfzMCVuGfyH9yhP+Q/InY6d4WG8/WVg+23HvZ0/Vt\n        qPPz8MCH/oEPI2P/+uXX3z9/+TA9+2H+6W9fPr0Zmnj7dHZpePL7248fX394Mzf/4cXiyouFf/z2y69f\n        vv327TsI/j++//rHz7/++duvOPD9l9+AA/71DzAC/vz28RPs+bz0buXF6y/v3v728ePHtyvLi8/fzz9/\n        P/vidX/fq9bm2bZ7s+13nzZenm26NP2oaam/Z3BrXUtwYLu/a6+H9RNHw3t+654E2D10sb5kYXTaGMBa\n        +94a7UZrk2u25rdtjA9ZG+43N64zUC/V4OUL+Lt11C/qCA9rcer5jAo2w59Js2HTMjR5NdrCIh3BHl2t\n        Q6Y6h630D6/VvrZGr8FAu1JTUKLBT9UUJupww9TZwRxWJo+5V4tfq6NxxlDnjK56hRa/QJ1boiMoNNCw\n        0eTrczlaNKYGg8lXU6MqK9NVVZh0OofDASXL19Dl8LSEGsbaBqbG6zass3TQNlqrrWWgraHL5Wuh7AKT\n        m62ha2AWmpC+e8/xM0ev3G588uRxz6Ubd+8/7unvGeoBtB4fG5mYGxmfGewfm56annw6PT/3YvbZwujk\n        067uoW5s+Dz2dOrZwNBY9+DI4NjY4PjU8OTEzOx01+DIg7bOoYmJ4f7B8ZHJew/bbt+71zHYfut+84Pm\n        7rbW1rsdj0/fvHrp0vWz167eePCwvLa+fv+xU5dv1+05cOFCY9nuI1sqK48cPnfvXntaSWV0bFZ5+Z7c\n        isLk/PzKPUdiN1ds8o5Jii/cV3skI70gOj67rHrProOHt9fuLyup2lxSHZmV5xYQ7hmWuLVqx+mT53ft\n        P5Ecnu7hGekalujk6WPj6GZi5QiKns5kcjgg/3hUBpvN1+DwtZhsPpsr5ArV2Tw8z+QIOQJ1gbo2R10T\n        lCmLK+RpaXP4mqo0ppycApXOMjRbn5FUduH8/ZMXGqPic21svfMKag8dv76jtqF6977EvJyiur0nblxP\n        ychmMIRSUrIkkwdzhEhNlqiBKLrLAeuxMAoJALgBXShKyjQC6DiBAD7FbBxAZ1GaJvGuwFsC5YD1OM6e\n        XAe3AdzLY7IpkgEckzJjbBCETS/QU6SCGp/0igCsx0R+eRyRJroU8eOrghmB6C+nAAQAB8A60rJyMjKy\n        siDwwYAA1U86Q4jqhEUMJPIdwUfEi6UiDxSlqgYsYufmF7+5SKilT5GWxexPNQa6pFTADKID3AP0AwGI\n        1o9gAAP+bsVKag5tKdudWXpg64GrO07d2Hn8fEn9Yf+YzTZOvnbugWQFByRsTiquOnjhxo5j582MTJmY\n        /Ym5/DwJMQ1ZST9nZ1cXN7qCPF9STF1GnORroqzWI1IajoEtaMANYmKactJ2G1032HuwqQx5MTFVCTEW\n        RVwHBwCszngRxXU1QYCLJslIS2gRd5C+HAWwG8wFIAl94qVBbz7iOyK1rhwFYwDypPUQZvVIWipJuipS\n        HDD5B2vQrOUpGxQo6xUlrBD9KRuUiMWApcKSjgoUJxK9ELmAzOQlLAkxmMjjZDGMMWC/aNwARMWXxvA1\n        lkCv1nZJAqyDlhcQj7/I6U9aQAPoY4YPaHmU89jrH71AcF6RpPZTidFAlUKUJ74dRH+Q//AKdgAhADwJ\n        6y//j2hhSiiZCgCILzpARxAer3KA1H8bAfAHWQDOwD8IBYhekALYKtSc2KQ7Zy/OPel8Nzz42/LCrytL\n        byZGv795+fvnz9/fLH59t/z57YfJ23de9PasTC2sPHv9funt25nZd09nl5/O/PLpyx/ffvnjl1//8//6\n        r3/8QkbJf/mKLd6+fPk3Dof5z3//858/v/30fvb5pxfPv71e+OXd208v5p6N9SzNTL+bmH/7dOrt0NDr\n        3o75zuaX3Y9H71x909v2vPHS9IGG9tjoa1ZGZzda3nZc22m75r6t+X3Pje1eG+7Zm9bp8vfrC86b6J5f\n        a3BtneFpE/0zpjpXjLT2qHN3CZkFXFoGXWWLqnK4snyEsnyOEizZNCWFRGXFaDWlAiWFbKpKNpdZJmDX\n        a/H3aAlruZw8HmuvOi+Jz/Fn0WIYatF01RCqci6LmsdmJNPVNrMZ0WxGPJ+dwGYEsamWDLoxm2PM52kJ\n        hBYGRq7W1nY2jpvsXL3cPd0CAtx9Ql3dQt2DYiJTC9LL6zLLa0ordhzffbS29mB6SU1iRk5GaqG9c6Dx\n        egdLKzsXF7/w2Jys8try6j1nTly8euXBtWtNjx+0Lswv9g2PPWjuaG3r7+0eGZ3ATg8zz+aGxie72oc6\n        O4ZmZudfLi5PTDztGxoApH/+/PnY5Ozk1NzI0MTQ8PiTts6mxrudfX0PnzSfvHDhxu0Hza1dew6f3dvQ\n        cODIie17j544e+HkybO37t0/e+lyTknl3uMndu/bn5FdllpUs23H3mOnLp49e+vQ4VM5pVXh8blpeUXb\n        6nbEZpcFZOYW1tZW7zhQVFwXk5J1+MiJ/PKd6Xnbiou3FVVVZxQUpWQXeEfFecclZtdtzSqsSkwucXb2\n        MV67wWSNjYaOIYunzuTyAINUaSwuT53F5tNZHI5QnS/UZXD4dCabxRFw+AD9miyeBtAAmydk89VpdND+\n        fK6GFp3No9FZfG09YzuXyISc/QdO7Tt6tnrXnsSSkk1xqcXb9x09dCY3e0dZzd7w0mK/lNy6gye37Tlh\n        aOEOEAq4CcJcVBUMyK5CJZ0hSL4/hnkxtZ+G6I+5pGQ0GDqFAJGx0QKiuTJ2NAIkxiQcTLoHGiBeIAUM\n        EqAXnuj6vy9iRigTDz76cwCg4ZVwAI6BXMVrkmUEFgqpOsbAAyEAHA0PC2u+ZGV/3BFvB98VoT8YDeSp\n        0Kckujt8Hb4iijEAfzh4BiZkowtISkYef5EyuqTgW7ABrYG/ccBfBADHYkXVB4u3H6psuLLzbNOuczd2\n        n7xUufdoUFyOrWvgJr9wF78oV//YkJTcZOICqj95xcp0LRcJAJ0hANDCn8TWqCmG+gYYr7FiSYgZSosB\n        NBPtj8VTelg5BUtcFyO9mB6qRae7+ETZeQZz1GhqpJyYQcHcUFD9moQDAIg1ZbEBA4+CQhvO65NpvdaK\n        ODYS9gANAKaDnLdRRH+ODrYUlQDNDtofxLuFAqb9WCui5MeOQKS1J5gIcOwEi/QcxaZAROabyEnYwn6S\n        WaSBYQAcQ28DZoQCThUmfn8MVgP6w031pDE6rS0DHCDBlsFxviD/AfHhUdVJkzuEfiL5GRQJZUIAYAow\n        wD5Atz4SAFaHEWkPpgCVIqkoRcFmcPDpD+2/mhIqjkUAWBf2PwkAvghcIg/anwQMEPqxWRBQAs4GWDUC\n        ViMBP4kIgEIWID/GgwkBwHkxMeSAUIdNe8q33jl2Ymn25ffl5T9eL//85s2XF89/e//hzz/++Pnz1w/T\n        M3MPnyxPzb9o6fn0cvE//+u/Pr9aXpqc/jC7+Glp5ZfPX/4EAvjP//wPAP4/f//j+8+/ffv2B1oA//Hv\n        f/3nn99/Acn/ffn1h9mnv75f+m3p9dJw51zr7eWx8ZfdHSvjg2/6O1/1tr4Y6J1suj53+Upb/YGmgpIr\n        QSGHNq45YKKfzufmslkVLFYFj7GLzzwv5DzQ5p/SYB+lqx1RUztEVTnJoR9kU6tUFW6wVB9rsJvUOY/V\n        uUeZqrmqCkl05TC6chyTnsJiZrJpW9hqRQy1YjWVfGXFVGXFNEXFYjXlPFWleGWFGKpyMF3FhabiqaoY\n        paLorqIUSlNNoqsmUZViqWp2NDV3hmo4XTVdhx9tqJO41irDyWlvSNC24MjNYVHlMVGp/uFxUXHZSUkR\n        cUnefuFxcdn5ZdsScvMSigrySrc17D25q+FI6Y4DVcdOn7hy5/r9tis32s+eebhn78ltOxsKt1b7h8XZ\n        eYZGRcUHRyYm5hRV7Tt55MjVY8cv7jh05MzFG53tA32DQ939I504HuD1zPT0MGj76dl3K++mpmZm5+bf\n        vH0z/XR6anKmb3C4t7e3p6e/rbvrcVfPwXNXTt262HTvwa2bLe1dHZeuNh48capu64Hi/N0Hjp8+eujk\n        wVOX7j/oKsir8fWNunr9/u6jF3Jza7ILttXsPLRnT33t7l0BMRlZZRWZ5XsrqvdvLq3K3FZ/4tTJbbU1\n        MRmFUcmZldtq9uw6tbXqeEFteXb51rS08rSkMp+wNMeAMCffEGe/4A1u7toGBmy+AKCfweQxmTwGi6fK\n        YAHcM7l8nJxFY3CFmhyBBkugweZp0OlsJofHE2rz1bVhJ5XFYvEE+FagzeJq0JhMLW1j7/DYsoba2kMN\n        5dsOZ5Xv2nXyaPGug9rrNhitsams2FlZezA4KjutpKqwam9+1b6s+kPOYZksdX2gAEyYIZKfpMNj93yc\n        JUlmtihi+0/CDTTiBRJl/aPwJ5k/CipKynSAbBkysR24BEQ6sQMQ0+VxbiU6f2Ch1+iHrYD8gb3kAPQB\n        tUUuHfQjwRfBHAH4RrwWkQdJ5oHzcAUE+tUrYLKQlLQs8AfBffwudqbDVnok5EvC2qKvEzrBqAC2TVVQ\n        hTs6eAEBlKhrgwUAzyiKSCO34bjKH24fFfp/pwOpUJlqDLZYQVVDZf3xfedu7bt0d9eZm7uOX9y271h4\n        cqG9Z4iLP6K/d2hSeEZhUmnNwYs3649ftDQyFWKaP8510cJgrzhfTMzbfE1kdCqfxRaKi+nJiANcAuKL\n        0oFEkwPgLaA5m4IcoM8TuAfEbnTxo8nKqoqJgXGgKomOdVGAF3Q9FgSQyiweGSgPMh+kuoUCEoA2VvNK\n        WCtgWqclyfgE7Q/wDdAMsE6wXgKIYQPW+hKGgE/lJQzkJCzkEOjtsMEDGUJAaGOdHJoCwCXYHQgzStGS\n        gK/AlbFZtCxWJJDzknAFZAJ8QoB+cZD/HPwbQPQHC0ZICAAMAqAE+CFMAHoJRHZRChCgvxIsKcz7VJbE\n        Xv8iJw9WipH5+CD8lVH+iyuRUgAZEhIAlMdsHwL9olwgQgDIH/KrdgCWBZBMUAlRX6BVIwCdPv9NAMAH\n        RPuLCAAsAywTAwIwVdfYVVJypK6m7+btz3Nz/3r56uvk85Wp2V8//vxh8ePrpzMroyPLQ/1vZ+aXJ8Y+\n        Ly39+uH7ytjE8vjwp1evvq28/+P7r//844//ArT/8x///hfOe/zz99+x8cOvv//29effv/wMvPD7l88/\n        v1z8NP3sy9zst4XZlbnJ5eHBt0PtK9PDLwc7Z5pvLHa3vnp4/1Flqaf5OlMGJ47JSJGTDpYUdxAT8xcT\n        KxYTK5Ci7FRRPa6sdFhZ9jpP7TpD9bqA+8hA876ZZrevZU9xdHfFls5o3267DdeszDuDPUcTAx+6WN3a\n        ZH3YyqzMUKt+nd4BY+29BurHzA2PGuvU6fDKhZxSLmMHj1kpZOdxWO4MNXNVJWdVpSCqchSLFsaketEB\n        9xnRfI4rixauJSyxMM+2sa5wca728k523ZS5ya3UI6AgyPdg6ua98ZnRQcHJQWERofFuwYlAB+nZ5bHZ\n        hdFpGRkppWWl9RlVtfGbt+RUVxXV7Siuqjt09GJDw/kTZ5s6Wkemhqd62oerao67+kaZrN9A52uxdczY\n        fC0u33CTX0R2bunNxodtnf2Tk8/6egew18/Ms4VXr4bGJ0bHJ2fnX0xMzXd19vf0dI+Njj9q63jU/uT5\n        i0WwALqHRsemn1+43tjUdLe9u/da071TV64eOnv23OXGfYeO1dQ1pOWU5FXW7Dh1cvueffl5ZUn5NTWn\n        rySmbtno5rfrwKnNW/LCM7ILwTTZXrO5dre5Z3DN/lNnLj9MyChNzyrLKaqMjE0vzdq+a2fDriNnckt2\n        bt5SnbW5JKO4Niyl2HjdRr5QR6ChwxOqUxlMGsh80PUcIYerDnDP4ApoTBaNwaEyODQml8kVsnl8nkBL\n        oKHP4asz2QJYLBafyeazeEK+uqZAS4cj1KDR2aBS7TwDz126dfrKpdzq2oz8bTlbq3Kr966z94D/mmXk\n        aD5J6QcvncvNrdpSUp2bVxEaEpdTU33g2BUnryQ5FZqUjDRKb1T0KNsR7lWoqlQmmCPoICJDZpAMAFUB\n        90VeflT6ooXiGl0uiNSItmQzTnxE9z1BbZE/B5mDbCOqHLgEKQSYAwkAt8HXSfUWRoMR5XEPphjhdzHG\n        C+gvp0g64qHrX5QChEaAyGVEBhWIboGUAzcVWRJAM3I/nkFRDZS+vWdAfHYxcQHBXir81YkgXo3Bgt+7\n        SgD/cyEBFFY1lO04Wnf0xu7zd+rPXK87er72wPHEnIpNftGw3PxivUKTQtJyE4urwALYfeqypYExWABa\n        2MtBXCiD/hB1CbE1spLxfoGuPiE0GRkGQLwsllkB9INYBgtAk1ROYWIMRYIjib4gbTprk1uArYMHW0Ge\n        hv2CflKSxEuZEV2PQE9ygTDSi62h0RdvLC9hRtL2Ya2Xx6AubDOUxybP+rIo4eE8wDdgt5UCznVxUKLY\n        EaMBDAgtOQkTWUk7eSwLsFWQMCIn14L8l0eqsCJXNiJ1A+aK2AkO3pqR+TDGcph1CpvBlOHLiHOI8wdn\n        G5BUHwwJAEuRSDWQAeA70ICIGgHKQeaD9lehYGNn9OfAsRS2h8NWP8QaUIcvUtBfBJAN+6k/CAAsAOAA\n        QHN5Yi6IjABAeSwFIEbAD0cQEgAs0QgwWdhMaEAW8/5FXiB0BJGS4L9MAHhBaiB+oJ/iQiMbaqsfHjg0\n        f/n2Ytvjf7xa+vnl8srM4vLwyKvRobdTk696W95MjX1eWXn/ennl2eLXVy++vHj2fu7px9cLv3359gfW\n        +v75H1gI9s8/fv/9n3/8+Y8///jl48ffPrz/89u3P799/+X9+1+W3nwaGX03P/3l5cL7p+MfJ4feTk6+\n        Gh170dH+rLlpsvFqc/3+yuAgGysThzX6mc6WZ9NCho/WDhyu6t+V8fFgTp/LhjoBc6+R+kUznWZXm/EM\n        765o166YgP4DGU/vHuy+e3Hi3s2HWZlN2YmPy+LathU+f3z21eH63szk9iSv7giPrlCfS87rbmwyOe9k\n        es7G/LyV8VlLgwumuseNtHcZaidoqtuxmeuoKnZqKo6qyv5sui+L7sRiuXN5m1h0FxbdX1d9n+emQkfX\n        cnf3Hd7eJZs8i71DK/2Ckx3s4739MiPCwry9U8NiEmIy3PwjN3j62XsEJ2RUh8fmO7gHxSdlZ5ZU5IGI\n        rqot3LWtctue7fWn9xw+fu3C9aZ7j283idB67nH70PWb9ytrd7j7+Xl7Bdq7+peU1VfX7Dt66kp79xBI\n        /rGh0ZGRpzPPF6fmnjc9au8bGJufnr/9pLVzcGhycmL46URnX9+j5paBwdGRp1NtPd2jE2P9g2OXr18/\n        feHK5TuPTpw933D82N7TJ/Y0HD9+5EpORVV43JaKPQ3Hrl88fvZEdnXl1gMnQyLj3fwCkvO2lmw/uvfw\n        2aDo+OSc3JqGA9H5W+CBC4uqQmK3FGzblZZblF2ybc/B6/kF24u37a2oPVlUVhGdmBW9pSA+O01Tw0Be\n        UZVK59LpHDqTy+FrcvgCOoPJZPMwuZPNpTHZDCaXwRHQ2QJQ+mwuj8tX5wu1eQIdFldIZWJOOo3JZ/OA\n        FXTYAjyDMMbiJmRnX7nxMCt/R0Tq5pjkzR6B4Ws3uMJm+K9bSl7ZJTjs+u3btfsP+kWke0dmpm8pKi3c\n        cWjPhfyyes01G8UpFJDPGLNFbQ52ADp/MCNI1AtBFTt0Yg9RNcYPQY1+FZTnhDYI8qI7CBAWgwSK2FpO\n        XllVBmwCBGhU/YDFgOyi64uAHsgGPf6Y5IOefVGGD3b0xGoAVP3oAsJkU7y46AroBZKVkwK+kkazhWxW\n        gP1IIaQ6jLySuTrkIeEt0ANsILdDLpGSkQMWj8ss1NAxlFNUwWJpUR0AtlD9b8Qn+aBgBPyNAIqqDxZW\n        HyzZeb7uWGPt8WtVh85WYOSnfJNfpIt/tJt/jHtQXFDyloTibQ2Xru85c3WDkYkAR0KKg+zlS4uDugc7\n        QENMbCNDLSo01tTcRuUnMa6EmC5x1GgDBxBRzMXcGHEWEbxMSTEQ/pqqat4+4U6bvLnycvJiYlISP9Ek\n        xfVlMGYLkh/QXwh2gyym38ClgA90fnh+ANzBRNgIMp9wAGwAkjBRkLBSlCBuH4rI8wPwDSoeY8LIE9ho\n        aKOCpJci0oApIDtpGgoGgQ0xL4zlJOCtDZoLeC+wRUg5MQVuJyo6E8APAQtGlP8jhRmcXIqEOqE0/F2i\n        jE+S/yOQQmrEtB8S75UnM79Ebn1RhqgisRUMpCQ1sR0QuomUKeJUSXEVUuQFSw5dOoj+BM2RAGDBSQB9\n        YAJAf8wCIhFglP9wQDhACu6Fs4WBMyThDEA9IQCAe8T/VQIQLcIKwAAGHEF5aNyF+r0zjfemr91609X5\n        qm9osW/g1WDvbE/7m/GZ5dHRl4MDK0/n3s29eL/w4su7dx9evl55PvN+ce7ndyt//vY72AH//gdWAPzr\n        H/Dnz99/++VfQAXfvv7x89d/fv7y69vlr2+XPz8dfTfaD9r/VW/3+5npd3PTS0P9L1oevWxtet56c+rB\n        jf7LJ0YfX/m4NPHzh9f/+Pc//+N//+9//u///dv/8//++P/43+/77nZmeV302tBaENdbWjp8ctf07eMj\n        16/2t9x/Pjsy++jO0zu3Xlw523ehoe/0/taK8psllUNHjk8f3dNZnjm1f9tY/pYHYd53Izbd8LI+72x5\n        fpPVNTeLzk1Wp9bohmsJPAR8BzbTlEmzpNMd6dRALt2fywzisj3YNB82I4rPitHkpq0x2+7qVenqmmFj\n        2eAXdDgsoS4oqswnJMXDPy0gJDk4KiE2NjggJDgwwjM8cb2b/3rHgI0uYe5BSdGJecVbK3OrqosqDuw4\n        sH93w9Hd+y6cPnr1zMkbl2/dvXLv0b3HPS2tvS2P2nt6Jmbnltrau5tbAN6nJyZnxyfn+4cmRsdmJ8an\n        h3HCy8Lk02fjk9OdnX0dPT1v362098LnM2/efhydmmppbml70tXWNTD1fGZ6bnqgf2h4bKylq+XSrRun\n        Lt9qaW5t6+g6efnqoYbTl5oasyurSwt2Xjh2Lm1rXdGeYweOHIhLSq/adaJsX0NERsbO/ScuXr+XV1Id\n        EBZ38uyJqzdu+0dm5BVuLa3YHpNZlJhTXlJbl1JcvqWkvmr7kW27j1XVb0/KzfKJSggOS9XSNlFSBYnP\n        Z3P5LI6AyeUzWcAE8AK6HuU/ncWmc7gMHp/J4bJZXDabj3YAB0wBDRZfncEBhuBQmRwGTx3IA+wAGpsj\n        q6hgZG5Zv+/ovrOXotLSwiIynF2i+eqGSqoqcB06iw8Ceb2/96VHd/acPWfuEuISmFi1fXf+5vLY2IK9\n        R89mFtQoKLPBDFYkVV0A8aj0ifDHFB1lkkGP7UKx8QPWCpDEUNTaJIEH00YJrANbEHBHswAhGGO8P1BY\n        ARagMGjw1VQfQhvAJej6x+x+GRD1gNS4pMmxSPLDZtwJj4QXRM8P/BYpGVnkADjGjhpwfQWMH8gRHxQp\n        AZMDGwWDECqwH4cHEPIQ3Y5Ckdng4h23uVBT1wieFrEeA9049guZgHCAkhpj1TJYJQMRAdQcLKg6WFB3\n        qvbYzTpCAIU7DgbF5dq7BwMBuPrHuQfGBaXkYB3Apeu7Tl9eb2Ssg5VfGAAAzQ4LHUHS4npiYm4mRiGR\n        KfpG5lSKpIaEGKCziRwm8ABEMtDJA0CJXaCBBjiS4mAH6FPVgoJj3Vx9qRI/AQfISSAIAqOYkAgtyfvE\n        SLIGiQxr4QwAUPcS64jrHyDeQuTiB/QHwQ7ngQNIGijsMSduHwNZcWMZHAtjQmIA9gqSbhj1lbAgXaPh\n        8eAKcN6CoPw6OXwL1gawjh7QBikABp6Aj2CB8Mewh4w4SwbLfUH1axH0B7OG/DpM+yFz8JHqgAyAAJQl\n        sSIMVD+OfCHjIYkvCHP8daUktaWw0IFNkSTBYdIUiFgGZIljGihm9RD3DiEAZAJCALCAAOQo4jKkFkzU\n        IQ4WBY0A9BEpYHMIRH1YohgAtoX7mxuI/MGqMCUpaX8L++r04vazFyevXx24cPllX+f3l3OvRwdmOzsW\n        +kYXBvqedXcvj4//vPTq7czMy6ezb6dm3gx0fZiZ+P716x+//Pb791///B0HxP8b1f/v//zH7//+xz9/\n        +fDx55XlP3/59I9fv/35+eOnyeH3fd0rA4NvJoeWJodfjw8tTU+8Guyfvnfr9Ujfx5m5T7Nzv3x4hyOF\n        //iPb19/X1n59PXzL1+//fLhy2/Lv3x+/2Js8cH1/qazI5cujLa1Pnvx/P3i86cdXUOjkx9fPJu7f//p\n        k9svh/qe3W2cPnuse2tl28Hti4+f9NdvH7txZLg6tyMz6mGM54Mo/0cp/o99Nza62HaEuly2Nqw00s7W\n        0kzn8xOF3Eg+K0ODs0WdG8tlJ/OYmzn0VA4rU5ObriUM1dbPtVy/z33T0UCfHV5u2Q4bt/n71fiH5gcF\n        Z3r7FUdEJQUE+7v7pEQmeAZGrdvkZ+noGxSzOSUlNzguNSqlKDgmLXNLQWHVjtK9Bw+du3To0On9B86d\n        v3j3xu1Hd5qam5oe373f3tza/eRhd1vH0OP2gZaWnv7hodGn010DYyOj0zNYIfd8bHK+p29sePjp+MzU\n        8MTY2MTU88WXw2NT7b0jvYMTA/3Do5PTI09nu/v6h0bGHjS3XWy8dbHp7s3rt69cv3bsxs2DZ6/W1ew6\n        fuJUQe3OxM1lVXWHjp87nVBUHJJccOTI1eKS7ak5FWXb96UW5h44sb/h1PnYLTlxm4u2Vh2o2dPgHp4c\n        H5uRGJ+WVVBdsbMhe2ttcmZezpbKvB31xTsPVFbtyi0t8Y0vcPfbrK1lrKSmwuCwmVwek80HNCdeIAFf\n        XYPNFdJYoO55DI46Cz4FGmDzGfCWCTt5gPUsHuwBs4ALep8B/MEXMDkCNQYHEMopIHz/mas1u05FxGY6\n        ugZrG1sDioGoZ/CEPA1tKpWqZWrumZYYmlkSllAQl5oblZyRvCUjMaWgeNuB2n2n11i7gdCRUyRVXaIu\n        DgTWAV6REhDogQlQ6aOPCNNyqKCRldSYosgqpg/hMBnYqayoQvxI6FsHwkDvjSym6KCfB+wDuDJm5mA6\n        EOn7Dywir0wKvkjGDhAGiQavpnii9QBkgLCO6h6jBVj6i5Vf2O8BeAEYSw3IQ1ZWUX5V7JPxCfKY/Qlf\n        EVkGcljuAIylBgcUivSGTd7xWUVa+kZgAQDKk0SgVTsAmQDPYJMiLI3GOmFcJAhcAxZAA6kCa6w9crX6\n        0JnyvUcjUovt3AIcPENd/GK8QxLDMvKTS2sOXbm1/ehZY01dvpiYtoy4NqnRhQWyHYO9FDFtSTEvM7Og\n        wChdfVO6xE8aklgdBpCqJY0oCcIZpDG+Usg4eBlxqpiYCV+QnLTF09WPDr/9R52wQFrSlLhxANmxTT/2\n        /pQAFW8qL2kPEl4J6QFhGuhHFh36FgpYrwtq3VKk/TFggIreVFYSns1YBl06gPIg8IEDnBXQUIDNWBSG\n        fSBwGow+8flgKhEpFjMk+y2wMwQ6l0xkJXRkscsb9rDDZkcSRsQ9RSP9nEHF0wkZgEkEBAD0BpiuKilO\n        SgGwSgDHA5B20Kqk/kubIgHoz5GS1CBdRcECgJMo9iXQ4SOigR81wKtOHhETYB0AcAAJDyAfUCSkAd1B\n        6f8kSgYFSkC7QQGpAnOByMLEUBIWRhb4mwUArPDTT2Jia03WpvpGH9mcM3buzOSDh8sTQ38sL35bePFy\n        cHBhqO/lcN+bieHlqakvrxY+LS0uz82/HX/6aXLsl5WV759//vnL5+8fPoDe//2373/88sufv/75rz//\n        CQf//P2Pf/z2y2+//fzL159/+/Dhl9fP30+NvZ2cWJmfWnk68nZw+PXQ8Jv+oVedrS9GhxZGR+f6+6cG\n        BqeH+mdGBp6OD79cWvr+/bcvX798/fbp45dv775///rLr2+m5562d0339Y13d8/2D70DmGzrnhqfmL13\n        Y+Rh4/zU3LvnC2/nJ//jH9/evnzetmfv2MmTU+3dU/dPD+zIG9+W152V0BIf1hvvc9PT5p7vxmaXDXc3\n        rtthqLFFnZehJUjWFiRr8iOFHG8uO1TAjuEz4wWcLH3dTHPTcFPjNPM1eTbWVa6uDUH++wP99wYEHY2K\n        Lw8MCHN3KI4Irg2O3uwXnR4aFuLrZ+MW5BUQ7+wZEJWQFhad5hOdmbC5OKugNil3V1n1gT31J/YdPn/i\n        5MVzl2813mm5cfvhrVt3m+61Pn7S+7il/35z2/3mzvau4e6+4d7u4f7+0aGxiaH+sf7+4cGJUWwSNzI5\n        PjYxOjrbPzA+Ojk1MDzS3jPQ2ktOT0329Y+Nj810D4zefvDk1MVbJy/fbGxqvHH7xsHT5y/cgFvdvXGv\n        +fiJq0Wl5allhcX1uxJTs3cfPlRUfzA+vTCrqDy/pH7v3oayyrqYzPzE0uLMosqa2iNbttalZm4OjUx2\n        cgtKTMrJLN6enldRXlGXll4eHV9UUFubVbY1K39bcn6Jd2S8gK+jpAaCEnGfwebRmIDmHAznqmtyBEIA\n        eiZXwOZqgHEAVgKVwVWlsahMBpPFZbGBAAQcnoDF4tFZAjoLywKodDaAqbr+muziXbsOX07I2O7pmWhi\n        ZUNlsqnoYuKpqFDhlcERUOlceRU1Klc7Mas8sbzKNjSsoKLy4LFTOYXl+RU1PuGJUlLyUjIyIqxHoEds\n        BSRd9fMQsf9X3wjM6STd3JiglBVIghAmj5LeolhWhuVjOJoYa68wx58M/sXkH2I3oBNplTawdzReXOTh\n        wYVeIALfpKYXpb2UFMI98Q5hvFdKWoagP7ACWAMiv78akAeZkwMbMB0INpO7iCIQGFoANIdfJKeoJCkl\n        bSMiAD0kAAx0I8T/hf7o8iLJTtjXmtSI4aeqdCYQQENhzcGS3Re2H79Zfehy5YFTFfuOxW+pdPKOsPcI\n        dvaJ8ApNDEsvSC6tRQI4dFpPU4dDLABtGcBBRH9RpBcMAp64mLaYmIeJoYd3iFDbUEVSUoPyE+ApYChf\n        Cvu+CTB9HufA8HC8u4Qm5SfggLUa2mnJW1zcfJUA9ZADfgJYJICO/n1YFoDOJMMHCADeWhMfPYh0I1mw\n        PNAEwTIuLP3FhhCA6dbyFEfCBMA9IPMB6+EAeMKc1IvB14EA1pMwAKD8RkWEe9iAI+PRMsB4gL4suv51\n        5ShashSAfl1ZcXhajgwuMAL0pCX0cBoagDv6cNik+EtHGmPdHHiLuI/o/6MJhCQD7B5kDpwgbyQluUZG\n        0hAPKHwpkP/oLFKUJJKfpACRPB/044s8P7AA+rHcVxwbQRNwx+xPiij2S4AeOACAHj1CeEZEHoj0xAKA\n        tWoErKL/DwKABeKIpigf4uKxPTKr+/iF108nFkcnl4aHPs5MTff2Pu/HbnEfXz1//2zx7djT93Nz3968\n        fD8y9LKnZ2V66uPT8e8vF35++/qXT59++QKK/evX5aXvHz/8+edvf/722+9fv3//+OnDs8WVmanvCwtf\n        Fxfezk4sjQ4uj/S/GxtZ6u1d7Bv4tPB8ZXbmzdT04sjE85HxZ70DYy2d86OT796vfPn556/YleLbx88f\n        Pn359Onbt3fvP72aW3zW1T708OZkZ9dcT99M6+OBBzdnezsWn04MtLW8fvP225//Xv78+2JLe++Nw8sf\n        3k12DYz2tr17Oz976WrP1pyuirgncSGXA9xuBzpe9bY772G1a51hhq5moZ5mrAbXgcXcxGa58Zl+PKYP\n        m56ko5ltYpRpZhJrZhq5xiBq3ZqNutoJG613+fiWunmVeAVU+wTm+/sGbrQtCYw8kpK/NSo2PiAoxCPM\n        PzDeNzrROyzR3y89MHazd0RKeAwg0e6yqj312w/tP3x696Hz+w9dOnf++vWme5du3Lt48+Hdh533nvQ1\n        t3S3dvR09w31tg08ae7Etm9Dw4P9E919I33DPQNDw8NDI0P9A72D4x09Q0/aeps7urp6B7s6h1sftw70\n        9/UNjfX3TXR0DnX3j7Z19N152Hy3+f7j9ifXG2/ce/joSmNj+fZ9x05ePXPuol9cdExKUUX1vqT8fJ+o\n        xICo2LKa6pCY1OjkLXv3nyso255dtqv+6NmysvLctDy/wPiwzNyIpC0BAcnu4an+8ZG5Fdu2bN0XlbA5\n        v6AoN68qKj0nIb8wJDaNr6kB0AnaH5M7WUAAHDo6efhsEPig+llcJl/A5mlweBosrgBIQg3HUTGZLDYL\n        A78ClgC9RvAVoA0Gm0tn8wDgNrr7n7/QuvvwdZfQBFMbR4GOkYoancbg0Tl8ZTUqmBQcvhZHqIlOFSVl\n        v9jNYcm5bpExhfUHzt6+f/zohdLKXRlbyoQ6hmI//YQxXoBOUd6OgoqiAompok8f+8et9gJClCeTHUk1\n        gLJohCRmCiEHYAqpGihoklAE+E5SelavCZci0WDgGDgAOCYWA5IKYrQKTgQDHBdBNqEBDPlKSQMXrKYY\n        wRGqe9IZAkFfRh6sHPixcgoqsFMWP0Vrg/ANLng8vCm6m6gKiqrScnJwNVsXP3QB6SABqNJIv4e/yf//\n        c2FXODwQEcChkvqztUdvVB2+XNlwqmLvkdisbU7ekY7eoZt8IzyDE0KxFxBYADd3nry4Rt9IV0zMQlbC\n        SEbCkLR8EPlqtEXBXgkxjZ/EnIyNXbyCheo6yj+JCaR+go+AHoAAeKSMFr3n2PsBS4VZkmLAAdZCflxc\n        urWNo5z4T1JkhoyRLMp5fTkU+FYkZRNw2ZiMZlwjJ7mBADrwihmgM5byok2gJ4+pQfaKFGcldPSD9QCc\n        YSSPXGKCc2CQPOAMZv7ISVoTi2EDCRUAE4B5YUHSQ4FI4LKi+jV4PG057CEK9zWQReHPJmQD6K8FG7BX\n        nTiHgm3d1CkSGiTUIapfA3MHYJ0uJU5DGsAx8Qxp4AD8ork0xVha0kJa0liGApRA5D9KfkWSKYQBXlEi\n        EMF9GRD1xA7AqZA4AABHwZAaYBLaBdwnQx9hJ8aB8S3aCug7Qrz/6YcXSBQH/uECIgv+SJL2cHJiYnZr\n        LHJCki/X7Xs9N/rhxcLr4anFvpHFqcnX09OvJmdePZv7/mHl+9LSm9GJb4uvfu7vXnrc9HZ2/NPsxNfF\n        xV9//fmPX379/edff175+PnVi++fP337+OX3X379xy+/fgdEfj79fm7yA04VHn83Of5+Znp5ZOzt2NjL\n        vr7nY2Nv5hfezc0vL754M//s9dOhV/1dL/sGn48+XZqef/ns+aefv79/+/n9+69ffvl5aXlp8eXyly+f\n        v6wsvXs28XZk6PnQwNLT/pcD7c8nJxanRiaePH757OXC84Wx7vb5/ta+vtZ3v/7Hp7nJgdYHH/5f//vt\n        UN+tnPi5h6eelhWd3uR0xdd1m7PFVud1hy1MKwx0M830knQEYWx6II8XLORH8DihTGYsj5upr51hqBe/\n        xix6rWm4mXH02rUR5kbh5qYlfu5Fri4pthujbDbGWTrGbLTL9PXP9wuN8/CJCQiJjk4Kjkx38gzxCYoI\n        jEuy8Ytz8o7PKCkt2t+w58jZ/XuPlu7YX7f7+Mnj5y5dvHKz6eH1O61X7zU3Pmh50t7X0tHzqKOrs72v\n        s2u4pQ/nCfcOjvb0j/R1ghUwOjA41INnxnoHJ1t6hruGhnoHRno7h7q6B1sftz1+0vGwuae1tbPx4eOW\n        brhC19FjF+rqDzU+vH/i9PXSwtoLl64cOnO2bv/BuJSCkqo9hVX1niFJgUGpocnpARlJsZn5YSmbi8t3\n        bs7emlu8p3TXEc+I2JysbakF1ab2jm5ewbGJeeEJyWkFRc7uUWkltVl7d+aXl5eV7ArLKHcNjQoMidPQ\n        NlClUtk8dZD/CPdskOfo3mFg7j+AO48pIK4ejpAFDMHh0lhcOpPDACsBYwZCBpfP4HFpbC5cAigEPgX8\n        s3X3q204u6Vkq7GVFUOgrkJnq1JZRPgL2UJtJk8TCIetDneE72oC7waGRMVlZmSV1m/dffz67Tt19Ucz\n        i7faeriKi0sBegJiouoH+SxKCsICWowNgNgnjh1AcGUVUjIGwh/RH/OFsFgMtpH0ITQCwCzAkC8gLzaG\n        UxK1ZyCLxGmxPQMiNah1ci/CNwjWJGsT9yvAZhns7yYv80P+y8giAWDmKCzMREJXDwar4XZKKhhFQAJY\n        jTHA12UV8OLEaoGfANyjBBxBkZbFIPDmIvgXge2gRegPSl8UCRAtbAHEWv1IjYlmigoVCaCo9lD5ngvb\n        T9yuPHhx6/6TlfuPxWVtc/AIBwJw8Y3yCk2KyCxKLkMLYMfxi+v0jPSAAGTETQF5ZTEAIMDZXoj+gH0C\n        aXGwA3QpYq4GBlZammxJHBojkEHPviheyiMNPnVkJYEDSH98cabkTwwxMVst9fDweGNDU3kxMVlSaWyB\n        3T0RkUGng5wHHAdohgVgvV5O0pIU7hoQhgATATeQbZakHthMngIov5akkwKXmJKmDrDguyT/R9JGFmlA\n        RCpwfbAMgDww24fMmNSWxUn3QACGmAgkYSiHdEXCAFiVpkta14EFwCPzjYUE/TWJ9x8WcACLgv2CYFEp\n        APGI8mABaJIvwm/XpaAdoE7aSICJAAQA6A8LtT8sCUk5CZD/ROCvMsFq7Ff0Vh79RdgcQuTbIamfkhI/\n        oU+fmAKizhCiCPBfRgDSwA/8X/0HnPlJ7CcFSYq+QOhgbr49MWuqtf/N9MzbiaeLw6Mfl9+uzM9/fPli\n        ZWb2zcjY54XFxcGBpeHxzy9nP4MUn5xbfrqwPP3s199//V//6z/+8duvX9++/fb5489fP/+8/OHbm6Vf\n        3739/nb5j58//7K09Gp09GVvx+uuzrcz8+9HZ98MDL6aHlqYnP4w8/z9m5fvll69m5l+uzDz/uXC2+dz\n        C+NjL6cm3szOvX79bnn585sX7z58/fLh04eV5ZWPHz5/+fW3z59//vhq8dPrl/Ddb29erTx79mp29vnE\n        5NjIwOLz529evVh5tzw7NTUz/+zd8rvFp6P3HrW+6J1oydt851j9wPbas/aOdwNCjznYFK83umK/7oix\n        TrKh7g4z/QvG2ls1eYlcTpqQv0tLUK2tnqSlkW9mnGW+Js7EJM7IKM3YMMfGqtjdvnzT+gY/96OefuVO\n        TqlOG1OdHPLdvbK9AjJ9/KJ8/AM8fLxd/Zy9QlwCQrzDErxCUwOjEmLTsraV11ftOFlYfqC2tuHY4RMn\n        T58/f+7apWv3Lt95dP7u3Wu3mu8+aH/woL3lYUd7e29n10hH10Bb30jvyPjo8NPenoG27t7ZuWfDY2M9\n        fcN9A1O9wyPdvb3Dw0+b23sftff190/ce/Cka3Cwvb+nrWugc3Dk2o0b167fPnj6/M79Jy5fbs7bWrv7\n        8Kmtu/YWVW33Dkgqqqo+dupCae3+oPRs9/Bo77B4602utt4ea5097LxCfcKjg8NSXDzDHAKSYreUrrdz\n        Nnd0C4nJjIrNCk/NikpKD4tNTa2syqmsyiyuCcup2pSY7Bmcoq1trEpTY6K7n8Pkclk8dTpHAHqfJ9Dl\n        CjRA4zO56rBIZQCXzuAyWAImRwiSH/Q+g4OSn87CAzZfncnhgwZncASmlhttnbyMTMypdJaiqpoKlQG2\n        BZynwdc56kyeOpXBhivAW5ZQzz9uc1R0ckpmXnZxdXpuWen2nRX1BxJycxy8/VXUWFIysiK4RywmoV3E\n        fVg4oxHOY0BYGeU/gCa2jlBRY4AAB8QHFCbxYdgMaIuYC5guixofOADgWMQEJDwrYgISpEXPD+nrCaiN\n        oh5DuJjA81evNyQJ4gjCTCFZeTAGRO4gGYwG45gXJTJJWFZeHvAdnpmEmuGawC54caATWPhIGAEmAWRp\n        OVtXX1EvIBngKBHiA/r/nQBwiQwCQgD484EAqhuKag5WHLxaf+7e1n3nCnccKdt9OC5rq5MPtgJ19Y/2\n        CU+J2FwMBNBw6caOoxcsdA20xMT0iQsIYFEPe+WvcgAsDWlxdRlxXamf1kmJmcph/RfofToFy4YBFlmS\n        aAfANiFJgedK/yQko8HoEmIsMTEnszWBofG6GlqiZkEAweZy6KsBmDaUwyGRBjISgOaAzrCAGEzksHsP\n        oD+YCLYkyQcEvgFhAlNZPG+hKGmlKLFGTsIIQRwT/EH164v8SLKS5rJoJawVEQAxMrAFBYk5AxOAESCQ\n        oWiTDtLGsji4mCcDFgCqeKA67AonjTPr+ZK4BCKbBifeYGYnsCD2isC5wVgTgB2wpTBkgvRAERdIYtgA\n        jAOaJGYTYcAAI8CSWAImgTEALBZDDlglgL+WlKg4gCKugNYAmQVGwF0UBsBpe+Lo6RepfowPixxBwAok\n        RPw3AwAWeoGANuAi+iyuqa5Oun/E7fLDT282zj5oHrt5493k5HL/4Menfe8nxmba+oeb7s213X0x1Lf8\n        6g3g7/LwyIvununent9+/+0f//jXb798/7S09O3Ll1+//Pzbpw/fF+e/PHu6/HTi8+t33xbmXvR3vhke\n        fzs8vDw18v7pxPLk2OuFp4vTM8vzzz4tL63MLb6fffHu+YuVlXdvnr94/+rlm7dvlmafz0/OLUzOPZt8\n        9mb50/uVDyvvgCCev11+9+nr7x/A2vj86cuvv6+AkfH2zdev35aXXg/1tPd1d71deffp88cPn97j5IHl\n        5a8f37c07D6ckvS662b3yd13k+P2uTm11FfMJkTvWGuUv8640FDHW8BO1lSv0NMs1OKG8liJQkGavnq+\n        jnq6lkaqmXHuGuMUI710fY0qU6OaDet3bLIvsLYus92w18l5t9umvE12Fe4eDSFhJZs8Uzx8wryDw7x8\n        fT3d3NwCHANjXILjgsOyAqPS45ILKot21NSD0tpXvuPQ3r1HD568dOjMrbPnb9+60Xzr1v1rlxsvXX9w\n        s/HxvRsdDx8+bm5p63zS1QUc0D3c2zva09vf0zc0Mvq0rbOrpb27tW2gq7u/s7e/r3+ob2D8QUvLwMDo\n        k0e4o6Wjq2dgYHx85tSF22ev33j4pGPn3lN7D507cepK47W75ZXVaVsKc0u2p2ZtLinbFp9dut4nyNbb\n        19HF3c432CEs0sUvfN1GZzc/P/+QqPQt+R6hsRudg9ZudLdxDXAPDLXyCXKNT0+vKE1ISE6Iy8jN3Zqa\n        WRySsSUyu8w/MJGjoalCUwXsZnHUGVwhnSugwzFbIBBqCDQ04DydwQfxTmOhgwiEP5Nof0z85/CZHA6V\n        yYY9HHVNNl/I5PF5mrq6Jlba+muBB1SU1FRpDDUwF9gCGotHZWCsGKiGwRayeVpqdA4gKUfPMCW7JjO1\n        0N4vMG1LfsmOQ4W7j2Zv3eceHLve2Vdd3ww0MoFLrMJddeir4KBgQHbsA4HyX4UQAAOxnlQOo+uGuIzQ\n        kwOcQfI74Yt4ElsGYQwZq8DQF7Ta+BMnB6AdAFYCqSkjkwBQs5OmoWSnqK8DJgXhLAHi8yEGwWr/H2lZ\n        MBIwqRTuBc9D2nyiE2m1noBYAAT64VKiQmK8EdxFSlrWdpNP/OYiTV1DWSQAbAWBCzkAu2GTtz9OonHA\n        gMvCeeICqj5Uuvv8jtO3tx28ULTzaOHOg5HpJU4+4a4B0R4hCX6R6eHEAmi4eH3n8YvWBugCMiLaX58M\n        6QUagGPgAyHOSEEnD5xRB80rJa5HYgMMijgTYwA4CQCMAA6pIQA0BGsAyYCMEGBJiGlQxALsHVx9Qlhs\n        jpSYmDSZKmNOIBu1OUaD8crwqi2DyT8g5IEGUN2DoscE/1UVbwLILoOJ/6DrbYAAyBXWySPQr1OggH0A\n        zLGGWADOchQnUkpmBsKfJBrBw4M2x/IuYAJZSaGshKGsBFwNfi8LEFxmVcXDHrAG1CkSQkl0+vMoaABp\n        EQKAnwPHsJAASKkwnTQBhR/Lh20U3IzRYEksFlPCIDA2k1ChEMQXRwLA9cMRhKFdyb8FA7A+ALN94Bjf\n        EkcQ6fmMTh4KGSKGHn/EdwL6BO1Fx39Df/gGhoWRFH4S06Ix9XmanmssTsQm9OzbOXLp/Kuu7qnzp+ef\n        NL8a7H47MfOsc7T34pkPS3Of3i4/Gx5/OTryfmFhuq/j3Yu5pbGpN9PPVxbeLD2d+vzmzfeVL7//+u3X\n        dx8+v3z9/dXrF22t78cGlkf7X48NvJubXOjvWRgeWll4vjg59uX1yw+vFz8tvlyemZkYGlt5+er5yMT8\n        yMTbl4vvFhanBgZeP58fvN08gnWwS2+XPyzMzE0Pjy2/fL3yZmVh4eWX779++vxtfnpudmrmw8dP//qv\n        f473DIz3DP782zccGP/+08ryu3ew+ec/fnv1ojEz9tGjrl//13+9PHmowdv+6o7Sh8mx9/xd6izMIrSE\n        KbpCdyF/LZsZzedUa2mUagrCNPihQm6uoU6qsUGkgU6CoW7+GlNY29atrVhrVW3vWGRnn2tpVmBlkbXO\n        MtPGOtdhfebG9X52jj6ubuFe3oGum4Lcfd394l2CYzxCwt3C4yPTtuaU7yndsb1o646cLTuKy3ZX7N63\n        79iZU6cbL567c6PpYdPthxcuNZ27eufizYfYKe7Jk+bWrkfNPU/aOtt7Blu7hvv7x/sHxjraejo6+h/c\n        a+tsG7rf3Nvc2jsxNdfV09P8pLO1bWh27sWDB4/vPnw0Pfei8fbDc2cu7qpvOHPx6qlz10+cun3w2IUz\n        F85U1tTtqDl6cM8RN88gW88wW88QU+sNHoGBKcWVnoExnqD5fMKTU/ICIxOCIxJCo1Ot7X3cglL8fNOc\n        vUJ90xNTMtMDYmISkrNTYnKzsouyS0uj0wujEgu9/aPoPAEJAWiSpg7qLA4J/LIB3EGkYzwAgZuBpQCg\n        9AHHaWw4YJOiMAFsUKHS2VwhX11bjc5kcHmmlvYmFo58LX1VBgNog8XTVGNw4fp4BTafLdDASANcn6cF\n        QEmhSFm5eu7bd9XDO5muaxoWlXXk+JWDF85Hpmwxdw1a7xqgZ7oeBDVALYA7UfRUFSpofNGcAJqSEhUJ\n        AMGdpqCiQtr6Y2AA4JVgPTp85DBVH6Q96c9DHP2kEhj24GgX1OZkkhfiO8F9IAbEfVG3Z/wUJDyCPvIB\n        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\n        d/TM33zQf+HS6+fj//j69tPii1czz768fftl+fXXF/PvZ8d/+frl9eTUysKrT/PLK9PzX5Zf/vz67efF\n        udczwzPdfS+Hht8MjnxZev1hYe799Ni7ibGZjieTbS0TrW0vRobeTQ29mhwdausabWubaXs83Te0svJ5\n        +fWr0b7uga4uQP+F+ZdfPn16+Wx+cuzpy5mFmUkwDZ5/XPn07v37lU+ffv7ll3fvP7z7/GXl3efu+09G\n        J6f6rt/p7+hcar5xKiam+cLF8SN7b6cmX8hMeZgSu8tIP8lAI1FfO0nIj1TnhQmFsXxuCJcVq8HL0xQm\n        aQozDHXr15rsWbd2q5nZ9nVrKi3X7LS0OGBpsdvacsd620POG/fYrS82WxNjsjbGfF3eBttE+00uG2wd\n        N9hZ2zg42Ti6uUXY+SVt8ov0C4tLzyrPL92ds7WsKKc8q2xb6fYde/eeOnjs+vbjl3YePn3u0uUbV+5f\n        uXD/ytWrF240Xb/W3NTUfPdBx52HbffvPXn4oPneo9aO7tHHrZ33H3V29A83PXp8v7mlZ7DvwZPmG3cf\n        tnT13bx1r62lvae758qtpstNN5vu3b18/erWvQfyq3afOn2u6c69fUeupFbtDkhKLy2uTM7OC45LSojK\n        DItMScgtDk/MDElMdY9OtQuO8AiMdfGN9A6Ms3f2cQsMC0vMCYrNiElMSUwEIyDSMyY1OHXL5uLC5LzM\n        qOzczLyqhM35vnH59r7xoP5VqWAGCPl8DRZfqMZkq2CdEYcEe7k0Ojp5aAwOSRBCNIdFA5uAzlSj02kM\n        kPYsJoevxmCh95+rwRLoq1C5ANCqdLgOzrbFwgImyH+wG4SA+GpgSbCxR7QqDXiFb+fsHhWbrm9mLdAz\n        dA+OidxSEp6yxWaTu6n1RkNzG7ggXAFwEx0+KtgljaR+ohsHLAMVHC+sCktRVVVRDesAsDmEsqoccfGj\n        J4f4dkBx4wG6eogSR/wlQQVccAY/QqcQQWdRnr6oRxBIe8IBoloBkf8HqwewSkD0Vha7Bom2EXc/yQSF\n        r2DIAewJYAU4wFAEnAFxD9dHO4aKIWJ8HhKIlqRIrXfySs4t0zcxByL5P3D/fyykOhENYK9yYgFUNmSU\n        7E0t2Z1aVJdVubdox5HIDODPCMwEdQt2D4yN3FycXF574Py17YfOmekbC8XEQPgD+gNogsYHXBbl+aAb\n        hMh50ODGJPEGBDsQAGA9B8CRGAE89I8jEyDuk7ABfFHkOcHWb7ISWhJiRhQxP1v70Jg0XV1jCvEFMShi\n        sBPuAsBtSnz9a4i730Qe0/ZBvJsCxIsMAhmcAr9RieKiSLEjvn6wCeAj0P7wLdgMb+HZ9GCzvIS9IpaG\n        WWHeJzb5AV7RwVEzCP16JP8HrAFtWSlNWQqD+HyMMHuHNK0DUwBLeYEDMJotgn44AOOGQyhNl9g3ahIS\n        dEkMD+gjAWA6EDaFJv4fZdIRSJm0h5MjHACvxP+DwQAR9Is8PwD6sEjfNzxQpGCeD4A+wDpuwyDwXwTw\n        k4QYJv+IQP/vHCA6/kEAovPIAUAAVBkpEwbTQl3b1cwi1dnr8tbtk6evP795Z7mr90XTw2c3r764eXvm\n        1tXFvo63c1MvFxbeTE9/HRpd6O98Pv10eXbp7cDYx+XXnz98/Prhy7elV59ev/y49PHt9MznxVev+8be\n        jo9/mJt9Nzr2dmxkaaD3WVvH4vDo8vj4+6U3XwGwF+aXhgZnO1sWWjufPXw0Oz6wsrz04dn8s6mJN89f\n        LE5Oz4yPPhudWpyenxwY7nrY/HR6bmZ4dryrfX5++sXzpfHBofZ7d7tv353s7n02Nz/77OXnj18H2rrH\n        R6aezzx7ePnK09mXc62P2h41Ddy+2F9ZcNQn5ERoWEti1BlX92oTy5PrjEsNhPE6/GAhL1qbn60jTBJw\n        Nwt56XyuL58dpqux2cQwVVszRlN9q5V5ne36/RvWlVuurbRcW79+3e51lgfWW29fb7XT0qrA2jrTymqb\n        vf0WB2ePDeudrdb72TkHOLokufiGhyU5RqRHRsVHxWckpRfnldSWVO4sqqlJKyvO31azt+HC0ZO3th85\n        s7Ph2Lmz5y9fvH3l8v2TF28fv3zz3I2HF289uvno0d3m1qY7zddvPGh+2P3gYfudB0/ut7U/edwBdsCT\n        jv4HLe0PHz0a6hluuvf48ZOeR3c7L1+6c/ZK4+mrl45dOLXnxKnSmvqzV6919vacON2UU3s8Ib9y9+4D\n        IeFx9m4hBaW7YtPznLyDfENjPfwjPXyCnLwDzCztLW2dnVyCNtp5uvhFr9/gBdo/LCk3NiM9KCElLCU/\n        KrMoODE5Oi4xIWVLdnldRlFBWFqGg280k8VTpVOxlycGe3lqNJaqGoPJ5vF42O0ZW0EAE7B5oO5BxQOa\n        q6oycfYLlwcmAnHsCBhcoRodjAYeT9OQxdNBpwcgKxVH7IJuBQmvSmMqqWBLBgA+wC9s6UN82YCMfC0D\n        Y2snLUMzGpezwcWvaOfR3Oqda20c1PVMNfWN6Sy+EoplBZTn6KVBcQ0YCgQDuEw8QgxRnzXCEHCAkV7A\n        YjJ+Cx33xAlDXD1Y64uVwPIK6BQCRU/CAGQ/oQo4D0+OPhzYDNCMSn/1W0AhmPBDEkIB9wni41eAD9A7\n        hOYFBoFR1JO6X2w6TSIWhHuAs+DZCOX8SDkln4ooBxOBbJy9koAATNfiTOD/Afq0/3lMW/UOYTtohljZ\n        jiOZRTu8w9IC43OT8mpyaw4W7ToaHJ9taeduZe9usdHD3j0oNL0gpXz7gQs36k9cEjWD0yb+HFDuAPfw\n        yscUTyL2KeghATsAVLYB6HRZRHlAdlzEDsAAKabEiKOjhnSNVocltZpFClcDCa8pLqYvKRbs7JqcUWCz\n        cRMYVwo4cAb7jFrKY1gYXT0k/wc4BuAbLADAfeAkYnyga2gdpvyjWQBwD1QBwn8jZnnCVySAKjDrn3QN\n        EpWGbQQ6IQ0n4NbAJUADQAB8aewEh42AZCkCWQpTWlJfWtJEWtIQjQAJQ2ls5KBFCnrhAIU/IQA44JJM\n        UA0se5ZQk8S4tzb8OkIVeIZof2UKoj+2hiZRX1wkAVRkByAlgLQn9V9SP4YAi/w/sJAVsBcQEsAPgY9O\n        IUmU+D9J/PQTILzIRBAJ/7+2AejjZ2SJ9D+8iv30k6oMRZ+qpktnWavru5tZF3tFPSksH9lf9fTInldN\n        Nxd72t4NdK8MtL8eH16anl58OrU8M/VubuLbq1dvZ+ZnuwdWns3//PnD53fvviy/+fRqcXl84s3o8Kfl\n        lU/L70C6f3rz7v3owOfhnjedrS96ut6MdgNsf5idXRqb/Pz2/ZeXL14P9i/2dy8M9byfmljs65keHlxe\n        WHg1OPhyZnphcWHpxdyzvrbJ3u7JkYm5p9MvZl4MPGwZ7Xgy0dczNTg+MzE13dk6fv/eYGfbbP/weHPr\n        cNuD+/v3P2w40H38yEB/y1BnS3vD3t4Lxx7VltxPi2lPD7vk7dPg6HDY3bbUynT/OuNjhho1uvx9uhr1\n        Jjq1xjq7DTQP6WnWa/C3CLkJelpBuppuAq67Oi95rWGhlVmxiX6+iX7pGuNaG7NayzWFRiZ55qY7rNfU\n        WFtus3OstbcttLSINLcIslm/zdmz3Nmj0tPpfFRggn+kX3Jxcm7FloLtOXkHiqsPb63YF59ampxbVb1j\n        z/Hj544cP11TfXjf7qPnzl+809TaeLP1+JUbpy/funru9rWb90DsX7nefPPW40d3W24/6L5248H1xqYn\n        j1pbn3Tfa+u5/6Tv/p3ma1ev3mq6d/HKHaCK5ic9N++2nr159+SF87dvNR49fn7/kbPnGu/cuPXwxPGL\n        qTlbN1fW+MTG2Nh7bM4v2lJZGRiaFRGfb+kWuMHZc6Orh5mNrbmNg6NfeHj05rCYnMCIbFfvqLjUgvzS\n        iqSy4tSC6vyyqojczUHxKSkZuVvyK1NSi0MysjaFRTNwzheVgS0/BUwWR5XKUqVSWTgsQZMr1GLxBXQW\n        toEDDsBCMA5Pjc4CYmDxhABDYCvgfpKZztbWW2vvpmOwDiAMTnKF2sATgFNgQGAFFoIXfTV1hyRZKqrQ\n        ATGVVWk6RpYMrqaYmISF/cb6XYf9wjIYAk0mWxMtBgztqqLQJj2WEc0xBQiT+gHrRfmgcGUlFZqSEqny\n        Rf8PwLoapodihihuABCXV1ICeQ5Aj6ofQJn4eUTEgPvRKY+SnBADJu0gcGNMWBmfFjcgYaAfCSEeezxg\n        +hDx4K8aBLJysnieRIzxAeDX0YADSVkASQ0C5Q6khRmlYBkASSABKCmDOaIMqn/DJu+kHJEF8P/VBUQW\n        CX4QC4AQwM6j6QW1bsFJIcnFSfm1aaU7sqr2+0Wmr93gYu3oaePsa+caFJCUnVRafeDC9R3HLq7TN+SJ\n        oR5nkxGJ+sT9ghCMcE/atxE7ADAU3oK0FzVI0IKPZCS5JBRMXhHuEa9JJBlwHzgDhDMcwEn0L0mI6UqJ\n        ORsZhPiFuXuHa3P4bDExQ6mfAKnXkvIuQH84hgN4C/uBhIBvjGSxYSegv2gD1g+TuoG1pF80WA8Yk0CD\n        QAJAHwf/kvJgZ0VJR9JtFH6COon9CmQoHBLyBYtEW0aSJ0MxkpFcSzgAQxEkoRMsAER/Yr6I5L8GIQAB\n        ZjdhyyAmKRIWUiT0SG4okyxAf1UyGYYQALp0AN//ngYqJyFOPEIYE0Ynzw8CgLeiGmA4ubpIL2jKasYn\n        cgMsFP4E4eHgryUiAFiA+EgA5A8cw/pJXFyBQhEoKAoUlIwZXDsdI/c1NgdTYkfri2cbGmavXJ0bAoDu\n        e93ZutDbMd10/3nLw1eTEy+ezX199Wy5q+dF/+DK+5UvS8vvZ+beTY7MtT1+PTH45eXs66HB5fnZP/75\n        zw/T0+8WZ769W/w4MfRueuzlaN+roe6vc88+zcL5xS9Lr76+Wfzw+vXL4ZGZruYXnc3THc3z3QPzLS3P\n        B/tfPZ2b7up52ftkrrfr1euljysfproHJ/t7p2anno9NTj/uHH/wZOji5b7bt4bv3X7aeHvo2mVQ+mN7\n        D7TX7uw639DfdGPi7Mn7OYmX0iJuJYdeighoy01s9A086uS409Gixtqk0MQgUYsXocvZZqy510g7x1Rv\n        i5luopYwTUcjVUsQo8ML1RK6q3P9NYWh2hremvxATV6avmaavk6ogW6ikW6usX6OqVGJqcm2dcbb7Gzq\n        7Z2qbO0qnBz3uTudCfK8HRjRFBn5KCn0amjE1rjNZQcOF584kZxbmpZYmJBSmZpdlZm5u7ysZs+RIw1n\n        zu87enzn9pP1u04C7gOCX79x79SZi+cuNl26dvfCjes3Gh/fu9V6+17b487exsZHV+423Xx8/9H91luN\n        zfeaW5+Ozt69f+/G7aarD56cvnLjfktL0+OWmw8enTl38czxi/fvtZ07e6F274GdB3aVl1VmF1QcPXch\n        KXuLc0i4i194SGRKQFh6UeUuj5BonraBf3yii7efnZund3RSZGpedFRWbFqFQ2BsdPJmn4i08JT0un37\n        80tr3ONTvVNSopPy0tIqMrOyIzZneYbF0ahsZWUanckGWGfzhQwmQDyGfzk8IZenzST1AQwmB1CfxuBh\n        EJjFZnEFLLa6Co0FsA8Wg4oqHTQ4R0PbxMqOr24AGE1ls9V1DTg8DdjMBDTnaWLaKIsPPKOshtk4IK6V\n        VBkAl8ANWgaWagyBlJyyrZ1LuH+o0GgNU8dEQ99MhcqWVUDVT5GSBpkMAlxa5HCXEUEtiHcSy1UGeKVh\n        oawoZx+99givJBqMviDU6SjwEZqBDwhAk8kwOKgLczexyItkeaJPH+t+iT+HqHvkALgLmTQJFAI2AAn8\n        EiNg1YlPTAFRpyBsBgffUgJyAk4lXSXQg6SMJcrIB/I4EpJ4foCRlLHHtaKqKhKAsw8SgPH/LxcQMQLI\n        EhHADiQA74j0+Nzq7G37tlQfKNtzLC57q61LwHpnH3v3QK/QxPDMoqTSmn3nrhbW7hGwuWpYCYzRV4BL\n        kPAA2aB5AX9NFSQNSBsfA3lJDdJgWYPky4t8JgCdQlmMBwAHAAEASoL2B/SEBfANshrkNuwXEgc9iHR1\n        STGBmJiJvLSfs0dQaJIem6MkJsaREBPVc4kg3kgeIR4eQBdoA706WM9lRToFwTYgJyAhuNo68hYO4CHh\n        seHrzooUWyXKWkWKqH2QBV6NAtDPB/Qn2h+eGR8Ys0IpoPptZCSNSQQYfghIfg1s5yChC8RG/D/AcEJC\n        AHxkAsyLJcaQhDpFHE6ysTOEhBIGe3FagKqkuKK4hBJFXFmKdPcUR3wX2QFYxCuOWA/HJCaM3h4RScCr\n        rPgqK8DCwmCsCkbXkEjLg+rH80TaAwcQVsD1dwJY5YC/EYCYuDjclCcny5dT0FOjWgk0bPV04503dew4\n        8uzc9Ynj+2fv3n7Z2b400L00Ovaq9eFS+5M3M4vPJueej43++ur1x4nJicb7y1Pzv7x7/3Xh6dvxwdfT\n        E5/fvfz+5uXKi1fvZ+ff9na+WXz9/sXC+8nxT8+fvunvffHkwZvJ8W+vl153Plns6/3w9uPyq1cvJ0dH\n        r5+fvHVj7tK5qTOH51puPh/uXxoYnWt+NN/WvtjTDhzwrLdzvvnRxJOW4Sct4zcfjZ270Hv84MDZU32N\n        Z/uratoKCwbq9gye2Dt1cvv03uqumpw7qQmdORmNEQHHnJ1vRwfd8fc5Z+90wcn6iZfddTvrGlPdNF2t\n        SL5GkrZmtL56qqEgx1ir2EznjJHWPl3tSG1+sDonWMD34rC9uZxAIS9UyPHnc+O11eEjDyHXT0PoyGUH\n        62oVrjGutjAptjYvsbQ4bG931NH+trf3w+SwB1FBj+OjOwuzH+SmdBYlPqnZ2lBTn122IzaiNCclv6Ck\n        IjmrJjmvpLL+yOETN+oPH6msPVG94/ihk5cvNT24BPL/6r2zFx+eOnn7/JXrt27duXX93pXGx4237jfe\n        eXS9qenizVtXGh9dvnrj4rUbl6/eb27uvHT39pHLjafPX7t08+bluw/OX7x66uzZUxduNhw/mVtVsv/4\n        6RNX4PhMbe2h80eubK+qt9zkhbO+IxK9Q8KCY9JsHb2d3H2c3fzWb3TxCo2IycxJya7ITi+PSsiMz90a\n        GJ0ZEJnsExYdtSUzPC07MHpzVMrWkKDMhPistNycqNws98AoVTVU2aDxuTyQ/DosHvb2IcNe1FlcTAFi\n        YEYQD1N3WLCw1AsJgMejc3gMtgBdRnQmYByNJVDXN4dPgQwA7rnqWPCF9QECTRZfGwgGyYAjpDH5qgwu\n        OjGoLCUVKkuoZWrnIdQ2NTBcGxSRY+UYYu0ZGBKZscHVn61hANgqp6giKSUjtTqJF33uwAQo50l6D5oF\n        ispgBGApr8hjo6gCTKBIZgmQFCAFOdL7E4AY5LxI4JMIsLIM4rsSmRuM9oEorx9e5eVFTiFlQhJ4LK8I\n        1gDYBKDW0dsD0I8OHzgQBRjQmw/PQzxC6AjCWyipqKmpgS2FvxErkElVmiiWgPtB+atQVWh0eWUVSWkZ\n        G2ev5NxyfeO1/38TAA0JoLTuSHbZ7uCEwqjNFZu37anYf3Lv8TN5VftcAxI3ugRsdA30j05PKKhK2VrX\n        cOlmxe7D8K9UEWcCI7aC3gdtC9YAork0QrCOHEVPjgIIayByqpAwAAp8hHvEd3SvE9wH9IeP4Dx8F64A\n        EtuMNF7GhfmXmJBjICMuyjjycfUNCIrTE2qogvEhCayAEA+iHngC0H/VksAe1BLrSE9QGwWU/PAAcDUk\n        BjmKOTEF4FgLTuJQMApwwDoFKV15nPkOTwU2CizgAFFWErAXX4aiTtxBQADrSAKogTR2cdAF4U/B2C9I\n        ey0K+n+Qz4jMBwJASiOMCDaBJkWcT5I+Af0VJMSVSeK/ElH0cAYIAIPAxLOPMp90gwAQB5lPVD/CPaAz\n        0ADWgmHuPyK+DI79QlhHbvhBAKIFrIAlwX+D/tXzf1twctUMEFkAEj/JU8QFstJCBTktFVUTKtuaJ1yv\n        a1AdHDe6bdfg/v2T168+e/BwsWdwpm/s5ezcYkvnyK2HMx3dI3cfPpud/cfyylLLw2dtrT9/+/Xnnz+v\n        jI2uTE2+ffHi86ev77r7Zy+eezXUvzz17O3oyPtnU1+WX31feP5+eHh5Zv7Ts4V3g73PWp7Mt7e8mR1+\n        MTk8c+tO75FDfdUlkycqX7Q3zjU3zd6/snT/9rPHzTO3r85dPDJ0tmHq9Onps+dH9+8fqyif2LV1uKHy\n        6cG60ZrC9rTk1ui4/vTM5uSY5ki/tpiAtlDfNm/PZk/3WxZrrtutu7LReo+BbqGWoMZYc7++YI+W5h5N\n        9Rptfp2m4JyRTr0uv8FAY5e++hYDQbGO5hZ1XpYGJ1NDCIjvzmS6sukuTGYgl+PBYvkLOH4CdqS6IIzH\n        N6DRXATcQjPjHTaWpx0d6iwtDjpvOOGw4bCj84Uw74exIXeiQx4np15LSr2Umnw9KbEpJaM+MSMxMXdz\n        Tl52bnlBVf3mjIrK/L0Ne87UHDy4tX5vXd3RAweP7zt44uChc+fP3rp46daxk9dOn7x269rV81dunr7e\n        dOFC49nLTWfP3Lhw/Obx8zcunj13/fLNU+duXLzz4Pytm+fPXj9z9dbVG1evNd47f6nxytXLp65cvXj5\n        +pFTly7dvLfzyPG6gydSs7embi4Lj0wIjkwJjk0rKt4enZLt7B/h4ObvExxjYrFho7unW2hUTuW+0Li8\n        +MzC3MJtQeHJXpExmzfnRCRnuUVEhaZmZVdWRsXnegemJWekJqXmJW4uco2MVKUDFoM05/EE2jyBFtoB\n        GADQBP3O4ILGZ9KIlx82MPkCrN2FtxwOg8Vic9UZHIEKnU5jY6Y/R91Qf60tanxVGgfnxmhh2iiTBQaE\n        KAaARMKFawqBEhiYHcSiMdimVg5+kZnahms19c19QtO9E7NLavcUZBbaeQfqrlkP0MlgCwG7AcdBsMNF\n        4Az6f0DFK6EkBxNB5NVBKAcyUEFpjxUDxPVP4r2qpOMbSdFBhz4wBGb0o34XJQVhphDhABz4Loekgh4h\n        IAkV0OxwI/Tyy8vDGdDv8Cn6fwjQExzHADIsvLWICRSU4ItwoEJj0lkCIDjgIWJ8YHQBU4nQkbX6Q4CQ\n        4OKSFBlrRw8kABMgADAb/gfio/sIKORvJ5HtRARQVNNQvP1w8e5zhbtObalB+Q//oaSX1HmGprgFxNh7\n        hLoHxUZtKU0przt0pfHA+ca1RmY0MRzlCGAnkJLkUNDhA5guIEyASh+AEscoItqie2c1EQjzJmEPqGPA\n        VsB0HVkM+ZrIYoq9psiJT5LuMZBLfDWiXB0DWew1baCsEBwQl5BWtMbQBOhH8BOOHMCILqkQhrtg/ACW\n        rISxvMQGeYn18tgIGugBGYKUC8DVsGZNVlKXNH0zU6DYKFDWyVMA3/lY84X2ChAGHKBZQ5rQ8dAXBAQm\n        aSpDWUPkP6D/WmkJONaDn0nkv8gFBBYAKWtAU4CLXbLxrwI4ki+JE8HopByMLiWhJiWuLCGOsV/M/4ED\n        YAUkAAT6vy14+9dC0AcCIMW9slgBgE1AMTZAWEFkDWAW0F8Q/4MAAOhFBACvoo/+OoCTIvRHAiBppkwp\n        KT5wgKKCjrKaGYNloaG1yWjNhcDQ/rqa3hMXR06eHzl9rv/MpYn7txZuXRxpuj7Z1rfY2T91697Thy0f\n        Xz1fGe1/Pjz19uncq7bmNxODH5defny+8L6n7c147+eVzysDw4sdT95MT72eevb59dvl/p65nsfflpe+\n        zb96/rhlvvnmfFvri5aeqStnus7sGTpzZqSheLihuq+qsKMyd+rogeED2+dPH3q9e9tg2ebhutK5hgOv\n        Dx14VpYzWZQ+UJwykZ3QHe7dkxozl5IxkhU5lBDY6+H1wMX5mqvjTReHe04bHqw3aXNc/9DMpEjArDfU\n        2G+sVaavtVlLPVBTEKepEavJTdPjZ2rzsrUEddrqB/Q0C7U1UtR5CXx2jIATwmf68hieXMYmJt2JATRA\n        D+JxXdgsZzbbkUFz47Nj9bQ2GxpstTDdvsHyoJPzTqf1dXYWh92dzkX6nQiJuBwedtzPp8Er6EJY3PWE\n        rJsZW24lxlelJUblFGXk1uYX7a8q2FVaWrWt7lDd3kOlu+sqdh0u3350a9XBuu3HTh27cOnm7fPXHxw+\n        fvHIwVOHj148dOryySPX9x+90HDuxpnjN84cvnyw4Vzj7TsPmlvONTbefnD3yrlbdbuO32i+f63x/vHz\n        NxtOXThy4eqBhlPHT16vq2/YvfvA0XM3t+8/WlyzIyghvry8Oigq1c7d39bN2yU8wtLB2cLW2cLS0Tci\n        0i8qysM/0jcg0TciJSG7NDQ61cXDJyu7MDOv3DMg3tolKDAtKyGn1Ctis090XHxUypaU3ODkDKZAQ1WZ\n        ysEaLh2eUIuDBIAjX7hCbbYI8TkCBg/7QzB4OP6FyVIHZGeiESBUpbOoLLYKncFka1g6+ZhscFJRJTFk\n        noDO5WGeKIOjRmOqqFFVqWzYg+FiLBwTAAeQhp2MDZt8guJyNPXNGBo6tq5+tQd2Hzh0xsM7zsTCga+p\n        B7Ar1NSjMtjojcEESlUlzPgEYQ4qG4U2xmxFQQUi//EtIKYqxmBVqADBPDqLo0ylkrJb4iAirn+0A4hH\n        CKAfWWRVuaNnH5W+AnADGhZE6aNTSITsojsSQ4FYFRgzUMDNyAoiFsG7wB4U+GoY+sYLih6M3BeYSYTp\n        Ctg1mmxWUJKSlrd28MAgsMlaGfn/JgBFFRr+HFI79tdJstCeUMNmcFUNxbWHtp+4ufvSg/L9Z0p3HSnf\n        czQqs8zRM9TZK8zJK9w9ODY0oyCprHb/uWu7z1zfsMYCEBnEu6Y0jnTXJmkzIP9hiewATUzmISCOuCwJ\n        UEgW2gqAjLAApo1w3haSAVgA2ui+xxACgCm8AmSbi/o8AwFgDFZCV0ocB40pK/o5eSam5G60sWdKU9TF\n        4RnEgWOwwQNgNzro0b8PWG8N6I9dgPBS8BaQHZY+GekFCz4yVMDBkBaEP/Tl0c8DC54ZtmmSOcZCWYro\n        jLGMpLkMZZ0MxRyuj8k8koD+a0k3NyAADVyi5B8SBqdgMziwBvBnAh1SJLhkJgwQAJxkSuPAABD+6P0X\n        BXslxUXyf3USJFkiPgAjAHv9ixp/wiLojx0gRLPgVz3+P5AdjYC/vf2B+/AqQQrEROfJ29WPRGQgIgA4\n        pkpRGFJSDBkpgYKCPpW+hs0z4guirda3lJR2bK1vq6oeOX/q6ZVzk5fOzj+4Ov+g8Wlj4/Lw4Ot79ycf\n        3lqcn/r+fOH5k5b59nsLT66+Gu/77fdf//H1w5fXz96/WVoam1qZGHo72LHU0b7c373Y0wYWw9JIz5uJ\n        qZWR4TeDHbOP70413Z57/GT6zqX+q2d7dtR3ZkV0lib15KU2Jwa250S1xAf1VGQ+21swmRs5Xpo2UZwx\n        mRczUxYxFB/W5+XWH+TzxMO13dOlJ9R7PCV0KNJtPNhjMNirzd76iaPtfW+bi/ZmR4wMLhvqHNBjZ2nw\n        NusIDxnonTHWrNUV1hrq1BpobBXyQwQcdx4rXp2XrM6JE7JLNfiZAl4wj+HHAdBXc2bQfLlMHy7Di0V3\n        pdLdWAx7Dn0jVTVCQxCtr+Ovzo/WFmQaGVRYrttvv77B2eZikM8BP59qF/uDPq67AvxzNjoeCg45l5x0\n        NTX9WnzK3sSkrKKarNy61M01ufk1eXnlldvramsbCooqcsqqc7ft27r3TGXt0e27j+w7cv4E/B93+HRZ\n        9ZGavSf2Hz5/7MjN85funDh9cd/+Uwf3HDlx6eqhS1dr6s/cutF85fqNPXtPHj547dCZa2eu3jt+4cre\n        40dOHT6/58DZzIpt+aXlSRkF1YdP7Dp8avuOIymFRWGpm518w/RNLV1d/dyCIgzXb9DQ1rdd7+Tq5uUd\n        EesaGBUemhKWmh+Zkh8QmuDs7h8UFR+WmOwZlLzBJ9I1LCEmpzw4NN7DP9o3OiUmMysyr0Coq6esQmfx\n        hRyhkKeuzePrcPlafE1NgTbY7do8sAOwCzSXzuRTMQDApdI5VDoQgDqdzVNjYnooICmbr+fgE2JiZaek\n        wlRUoVKxdAAXHKgxWVQ6m8HkMzmaIIoBvFSpHPg6SHhlJcYGR89NwZFUjqajW/i+Ixcq6vaFxOaERKWu\n        WbdBDiW/Kl9oQKXzAIURwUnsFHGTpO6sAisSgxpxr//IrlHBWDGdzeXy1WlsHqYJkcwcAFdAZvJ1ouUR\n        8ZEJiJDHOAGGdoES0I+PfIA2gTRp+4ORWxLvxaAuhoKJMwqLAJBUwBYR8QTaDRhzhseAJ8QsI5HNQZ4K\n        2Ys0p4NnRjOCGA2KCqrSMgo2m7xJGuhfBIAhDXmSfgpWApzBIoDVWrDVpSaaCVyy/Uj53vNl+y8V7DxU\n        sOMgrNCkHGtHn/WO3jZOPs5+kWGZhYklNXvOXq46eMrSwBTrAOQlAOJFThhQ0DyC+4D+AuL90JAG9MQD\n        OM+lYIYPoLwG6RgBe4hHCJOFhD+cJ3BG5J2Ha4JgXydKyyERXQBu+Ag24BxKcTHXtZbJ8ekOjh4cFRW2\n        hJihDEn1wex+XMakLACeyoK4++GmotCCAYYlMDPVQAatCmPSIwhMB4wiEFeVBhH+GphFisccGUkGDgSW\n        tJQBuEcCsAbmkJY0pkiYSUkAGZhISeqS3B4wAgD9WdjcH5gAG8PxpLAIQIfUB4i8/wwi/1VJ9qcSSf4B\n        xFeiSIq6v8ExnPmLAGTFcWF+J6h7UgEgQ1xGsMgcGEz4AexGXxAR/hRyRtQBQgT0InwnC/FfEqdC4lsk\n        AOL8Id/6ET0GC0ASM1NpFEmaFIUjK6uhpKJPZa7lCM35Ols9nDty0zsqKibPXpi4cHbs1NnJy5embl1e\n        7Ot40fvkee+T5eczr6emFnv73s+MvxnreTs9/Nu3z5+wUuv9l89f38w///T61cr8zFJv64exro8zw8tD\n        vW8HR1719L4d7lsa71saaH/V37qyML3Q+uBp45WJa6d7tmbeTYh/Ul3QVZbRkxo9nBrWHh04UhY+czBj\n        ZF/u022Z4wnuo4meMwVRw7EBPQEu49H+wyHe4wl+vQleM/H+vf5Obb72LV6OTXZrG+3XNXtZNTtZPLQ0\n        GrQyHlhrcGGd3nlDjRN6WlW62nu0NUp1+fk6/HIut1DAPqYryNDgOPAY7jy2F48Vx2PGc1jOTLWNNFVb\n        quomJs2TSXVmUm1oVF8OE/jAm8vJMDV24HCtWEx3IS/bwsSXx80w0qt13HjQy2u/q3OBy4Z8F/tCb+8d\n        gYG7QwJ3JMZXR8bnewfW+gZVbC5L3lIdHJURH19YlltbW1VbVFCbkFUSl5RXVLRt24HDVfuPbi7em1PU\n        ULd9/4G9x/YdPVV/+sLW3QcPHrx4/tq9/YeO7dl76sDxM7tPHt198FRlzYnDh28eOn7h8IlrV5taTl+9\n        f+DclX0nj928fvPUwdP5eWW1exrK9+0r31bnG5WQUFiWkV+dlFW50dXHNzjWySPYMzDMxtFNU8dU12Ct\n        i5dvWGSsnVuIB8j+vLzw+GzfiM3O/lERiamOHl7ugWEuAVE+0ZvDo9M9/CP8otK9QxJ8guMCY7fEJ+Vp\n        G+gq07ESWCjURsQXaLG46nyBhqaWtrqWnkBDi8bmqtHZaiyOGoOjQmMAkIG4pjJA4PM46to0JldWQUHD\n        YI2dS5SOgZWiCsAcDXQ3g4emA+YOcQVMjgZcE+U/jYXOcYwrCAG4WTwNO2f/dbablBm8rLyqO0/6k3LL\n        7bxCQhLSDMzWSUnLwk4N7bU0hkBKGtAVcRzHA+DwXuyuA0hKhLmo7IsgrKqayAOjoKyKpWog/2lMkdYW\n        JV8SkkBEJq4hFZGQxyuI3PrIBMqyOEwY8V2U34nHIPkxcrvqO0JPEUah8RguKIo0AHQD8ymrMInjCB4P\n        8J3gPmlDJLqpMjaJQ7MDn18JU4zkFalgAdg4AwGU65uY/2UBYEwbGxlhvJek/WDmz98Wg1gANYdK6o7m\n        bDuUue1ATu2B0j3H8rcf9I3MtLTztHLyXO/svckvAgggqbR237krNQdPrdHR54uJoaYmKhvAF3CWRbAP\n        8B1sAliAoXzs/LyqhQH0NcgxvOoSDgCDAHAf4ZJwBgC9OQntmpJrwlvYCQtTRUkrNzQFZCR0JLHdtAWT\n        5uXitdHRk62iLBAXA24ANLcijaBNSTxAQxaTRM3AmACpDp8CGZCgNLALgL6pvMQ6bPGGb8GAQKbBqTUI\n        90LiJgKbhi8jSSMFX2tJ7r+ZtKQ1LBl8NSRZPUZSEgZYBiwJRgBwGBsJQBQExl+N43FIJTA2/MGRABSR\n        9lcCrAcclwDhj84fYg3ggUj4/4j0iiT/6mRgkve5mghELAAJ9P+QCDBsBnoQ+X9EdQCA8gTr4SR2e5YS\n        NYIWbfiB/iT+S6BfdJJwgzKJTsOjMmWk+PJymsqqwAEmLL6Hge7VhPjebfva9zR0Hz88dujw1JULk+3N\n        C6Ojr3vaXwy0PR8cXuobet7SvDw1/HFq/O2z6U9fv79/9Wr52dy7dyu//PLbr//656eVD8tPxxb6u5am\n        Rz/OTH+YGF0a6n3/6vmrrscrgwPv5uZf9Y8/vXV9tq9lsfPR+KnjAyeOdhzd3V1dcDfSvz06dKg4Y257\n        7uSe8tHa7Ons0PHUyKdb0vtiwqeLQsdSw4ZDfMYifabSg+fTI0dD/Ae9bJs91rS5Wj50s7rsYn1xvfll\n        a5PqtXq7zfW2GxvcsDK6u8b4gKnuMXOdw8ZaJUJ+oYCfpSVMVeeUafBK+ewMHiuRy4pg0cPZNG8WzZZG\n        taaqWlNVNqiqOKuq2tKpG+lqvgxGEJPlx+cG6mla0hm2bFakgV6W5RoHIceKyw4zM8uwsw+xsIyy3Riw\n        3sp/w/otPj7Jbs5ZHq7ZfgEB9m75jr6ZUenB6YVhCdnhyVmJ2aW5Bdsz07dGxxeERRcXpldtrdhVUrEn\n        u2Rb7tY9JVv21VTv33Pq+J7jJ6oqd9VX79t3+nTNfhDypxtOnSrf1VC9++CuPUfrGy7uPnbx3OV7Tfc7\n        jjc1Fu/bW1VZd3T/ifJt+wMDoo8fPVtYsy8psyQkIi46Kd3TJ9I9IMHG2cvC0s7e1WOTf5CByRotHX0X\n        r/Dw2C2x6cXewVH+AZFBCWlpOYVhSfmuQWk+ESke4fHOodEb3H3tXEO9w5MCEpPCE1PjIpL9g+I9ghJC\n        wpK09A1UQdILNNQ19AHu2QIhg8XjcNSFQi2hpjZXqMFg8VVJpFeNzlAhncgw/4fJpXN4fA09YAIAQw0D\n        k/WbgnlaRgBwVAaLhd2k1TEIzFbHBFMevKK/SFmFqkYFc0LI5AoAN4U6Rs6+sYaWzjxt47yi0qqqvWmp\n        ReFx2ZaO3uq6Jqo0ugqNrWO0nsYUUKSk0bOPPn10iaDuRnG9eoAEoKSsoIKdnJVIhIAwBNoBiLyr3iFc\n        8BWSiqqiAjCqigW6QCFEy4u6vJGeoGgEEPsA7QBM/IePVq2EH+FfeXT947GcEuzHWwDuK6ux0OlPuvwT\n        AgCDAOgQw9HIQGCCIBkQGoNnxsZBaoqqVIqUrJWDR1JOuYHpWhmgDjIQhizkAKQBbH1BmkCsMgEeiAgA\n        LICjebWHi3af3Lr/XM3hc8U7D3mFpq3b6L7e2dfJJ9QnMjkssyippKbh/PXdp6+tMzLjiYmBsgbJD9AP\n        TABQzqCIM0ifAx4F82SAG0BQwwHgKSIyQX+gBzAC4FtwgO2AyDhJdTiDbd3QIQPoDDQAB6D9BSCuCQfA\n        1wHEMcxLukpoS/2Ed1eWdzC3MGbSqeJiYEkAmluRrwMZwE7SBwIbPMDV0N1Ppjxy8KYSwDG2pB4Y7AOg\n        FrgvGBzwAAIZSTaJBAD6wwILBowAoB9bGQkLov0NpSTXSEmul8ZjoARDeDCSBQS4j3XOWAqAEQ4Affh1\n        BtLiQCEM0u4fgJVJxn5hrucPIY8dIJAMxEH7o94XXyUAeRIHFi2S5YlLRAAkAixOyr4Q4qWJBQALEJ94\n        84k1sOrtgdcf6C+OkwCAA9ACINqfbF6lCtFbeAUCgKdVpUhSpShsWWmhkoKWqooRi7WOy48xsboQFnu7\n        clvP4dN9u/YNHNw7cfvK1L3Gkbt3nre1Pnv0ePT6pWetzc9aW8cab398/+nTm7fP25rfPXs53Tc02Nw8\n        MzixNPN8qatrsX9wcXhwtuPx0lj3u7nJdxPTy71tMy0t8x1dc3fujlw+PTPU+fT2jbnbdyabLo01XZ5p\n        PNO7d0tXbWZfTmxPQcrItuz+zITR0ICJ5Oje6ICeBM+xjOD5+MieIN/Hbpu6N7n0BXqMRPtPxwZO+G8a\n        cF3f42370NWmxd6i2dr4sLXetY2m1Ua6qXoGuca6FRa6peZ6pbrquRr8BB67RJOfJ+QEC9jJQmYSmx7L\n        Y0Ty6G50qi1VbQNDzUpV2UpF2VpVxUZF2UFNbZOqSgQwBI/nQGc4s5nWdIYN8IGOeoiuljmDsZbHsdAW\n        hluv9zA2C7ew9F1vEWRjF+7skuDllu8XlOAbEOHiGbjRycszwD0iMTJmc0RsfkTyloiEnPTU4vg4UNz5\n        6RkVienVqXG5ecWFpXsOl207nFeys+7Asbr649XVh/K31pbUbdtz+OiB0xcqt9fuqNq7e//puvpTOw6e\n        2XH89P7j589cuH3pxo19Dafqao/v2bG3ZtfRrPzawm1bc0q2OzqF+gTF5G/dFhabYuPubWnnbL3RxcnV\n        39HVV8fI1MjSwsHDLzKmyNs3PiIyPjg8YZN/ZGTalqJtO2JTC3yiMnDirm+8u1/cRr8Ap+AIz9CY0IDI\n        8JBU75hkz6hYn4gkbX0z0KYsHo+vqccXamOHZw6Pjf3gEKaBDOhY98tQozFodCYVy4aZgMtUnBIs5HCx\n        pxuoaaGmnqm1E0uoqaLGYHIE2FaIowEyn0bnUelsbCZB6o3BkqCx+GAN0BgcAEF1HbOYpHzvgHgazyAo\n        PT0ls8jTLcnZM8LAfL1Ay5jG5iur0jX1LFSoHIoUBXCTqGksAVNSBWCFAxTUANmI2kpKcoqKosoAgrBw\n        EtH8xzF6/OE5wYAAzQ4oq7yKxUoYTAZkJ2lFAOi4WUmFMAF6igDlpXGCI9YEAM0QDsBkf7AbMCMILABS\n        3wtQDj9cSRm71MEtENyReAj3kAPCBIDm+MxoFsCt4TkxXq0sKSltbuMcv7kQg8DAJ4QAFEXBXhEBrNZ/\n        4ZwAXIQA4G8VCaB4++GyfWe2Hb5WuvtkbvWBzeV7AmIyHbxCNvlGOPuGuQXFhmUUJJfVHLhwY9/5Rhtz\n        S03MzEH4BoAGQAcIZpEubywEO3E+DnvBBUgKnwLU6mKcAP37gOm4HyPGWA1AisJAsGPCD3Z0wLROBGVN\n        YiLATtFSJzYEfFeUOAQQryUpZiQlhn1+ZMQR9AlPAAEA1oMdsBbtEjLOl5gUcBIeBq4A94LrW5JmcLrS\n        eFIfc34omAUkh4W+XGK7wOJhAx8JY2nM/rSQoZgAk0mKG0hKmJIYALyFBUYAWACk+AtpAH4Rm8wG0CFW\n        Dlcar0CXEsdeQIQAVvX+D38OIQB8Baz/ywKQl/o/vUCiBR8R9BeXlpCUQXBH4Q+voggwgDiAPKA8ebsK\n        7kT7ryK8yBoQIf5fCylBdEBKDagUSRVJSVVJ4C0pjrysUElJQ01Vm87kqtCD9NQvR8fcjEu4GR0+snfH\n        /I3T87cv9Z089HjPnr7D54dOHpu6cmX04PG+U0cWp198fjo5d+/m84HBqeabQw9uzE7MvhkYnWu88WFu\n        bqG9c7bl0UJv37OO9tcjw0sdHTMXzw5cvf52bPTN2OCryfH57rbprnvDF/dP37sz3Hjj6e1zYycO99VW\n        DO0rGi2Le7Y15Wli0ES076NNti0hjk8iXB95uQ/EhQ8mBI+GBXf4OrX72gzF+o1Eebd5WD5yWP/QwarP\n        fcOY8/oOu3UjzhsmNtlcszbbZ6y+1UyvVE8vQch3UWfbcpi2bLo3m5Eo4EQImS4sujud6saluTJpm6iq\n        JkqKpioqFmoq1mrK1moqNmoqrlTVaD7LS8Bbz2HbCjg6airGVBUvdX68ubkZk23IopnwOLYGBo6mJg4m\n        xh7mlv5W671sN0S6eiYEhSYGh/m5uDnYOjg5um9wDQwKTIlNrIhKyEtMzonLLQxNTY9MyAlJKwxKy06K\n        y09JrcrK31NcXL25pGZzXm351v31NYfr6/bX7z5YXLErt7KmtLK6JL+6vPzItvJT1XXH6w4dLd25u3JX\n        w7EjF3fsOVO5/+S28ppttTs2F2/zjUkOTS10cw2LiM1MLCtz8PDVNTJ28PL09I9ycg02s3IwMLV0dHXb\n        4Lxpk1eUk6dfeFy8f2RaQHxyYWVlQeGO2NgMD98YJ8/A6JicuIQc39AoOw+/jY4+nsGx7uGJboGRXsGR\n        QTGpekZrQTszOUK+ui4HE/a5OPmdIyA6nQ/ArUZngd5UozIZNDadxVFjclQIppOJ8BxVbPTGFajr6xit\n        YfEFNJL3yRFgDigdSwo4qmocFSqDijPEMDeUxddSpXMA50DLc3SMU5LyM9OLFJkMU0dP98QSU8cgw7Wb\n        dPTW0VhCJSAMGlNbHwiADf+rIG5iHwjs8AwyHzAUsFXUXwGDpbgQzfGAeIcUlMEgQCcM+QigHKU9mB1w\n        IErFUcBWoCDtsXYXwF0WO8FheihsA5LAdCBYmNyJdgDZibhPwsWYNookIUpAQicSsAtp+oZlBxg/QLqC\n        WwMfiGK/pBgYQBwAHfgATAFlKmh8KjAEEICptX1cRr6e0RopGbgk0f4E/RWQUQgBkBIwgH6gGUIGJAZQ\n        TAigfP+FrQ1XMsvqozNKIlKLfcKT3QKivUITHLxC7dxDgpNzksuxHfSuk9csjM1Bg4vqtmBhIFcGlS+L\n        gggrBPSURi8QoD8gIxvAkfTOBFQVZWRiSJZk2ZO1Gh7QlMWPAKzhUzAdNEmEAPQ4epNIeg+iP/qXMOsG\n        kzJlJddKi68h9VzW6LgntoIsFgGYyUuYyFKMiIeHuIBWS8aMSfo/doLDDB9yX5LiqSWLFoCWnKS6LDqC\n        4OEBuBkkhIveHpHDhyKxRgq9//qA7xQJDfIKx7qrfSCI54ciDv99cSTxSQToE5NQIVMhcWoYmAJSGAxQ\n        lhQXBYER60WgL8L9H28B/Unaz6r/5y8CkFudBgMcIAkLjkVoTrAemUD0RwToZKHqBwKA9QP9kTZE8l+0\n        R3QM6C9FmIkmKSpSk1SjUOhSFK6cDE9RgY+t0KnaNGbVmnWX3R1PBXg9LCpsrajq2H6gJTP9cVJ6V0Z2\n        T1l5R27BI+CGuozZx0/e9Q+87mx52fJoZXFubu7Zx6XlD6ODzztbP716+WZi5Fnrk6cPHi50979u7Zi5\n        ee1N54Oh61eePmp7NTo639W+ODn5fGRi8mHT1KOmweu3FvraFzvv9R0pHz1Q0lG6uSUzvj88YNDX7Wmo\n        20i4V3+Ue0eYU7ufx0xOxExuxERCyEig/USoa7ev433HdY+dLR44W7a42D52trxpZXLV3OSWjdkTe8s7\n        1iYnzLSv6asf0BZE85hJfLYnk76JQc/isYq5jBwmPZmm5sdUDWRSXdVUTFRV1qqobFBT8aSqedBpG6iq\n        LnQgBrV1asprqFRDBl2TqrKGybBXF0SuXWOrIdRmUNcKBIZCdVMDfXN9PRtjMyfzde7W1pEOztGubjF+\n        /o42juYGFrbWDo5+0UHhCWHh2UFh2Ukxm2MSiyISsn38Yl3DE33T02OjiwKjSnwSs7dkb83eUpdVsHXb\n        9u11ew/X1tRXbK3Pr9iell2Qn1+xbduevK2Hy7c31O3bV1S1p6C0fHf9gep9h0v27iuu3pWTU+HunRAQ\n        mbzr4P64zCxn99C4lPzIhMyNDi7rbe2CoxO9AxP09M119U0tbRxsNrlvcPHc5Bvm4R8UGZ8YlpbvG5mW\n        kJIbGJwUlVEQkpe3KTTQMzjUJzjCwzvELSDSwS3YwTfYKSzCwTfIxScgIDLTZM1GENRsnoDL1wD5j80+\n        mTwGAzhAHc/wuIDdanSQnEw6g4fNQZlcNRqbweYxuUKAJOAGoAqeujZHQ5PJV2fxNbCrBJaPadAY2AJa\n        jcZRUaWD5OcJtXlCHSZHA/AL0BAgmMYRurgHJaTmq+ubaRhZesYmJW0pd/dJMVhnwxFoqFIZNAbLyGy9\n        Go0L/92j/0RJDdtLqDFIoS9GX0WJlYDCGHElTh7U6XCG+NxFPiI4QKQm8E1ogCC7PEaPAcTRjUN6wMEx\n        JmsCnWBrIKAK4g7CGmAC+lgghqCPNEAWuT4GEkScQc6A9sf9wD1w/ON5lED1YyMjHE2D5gt+hEYM9q6Q\n        JyMhLexcE7KL9QzXUKThntjrX0QD6MJCiwGrneEvTbSUcNoBTYWkgR4srTtasf980e4zKcXbYzPLgAM8\n        gxLtXYM2+Ua6+Ea6BsQEJW9JQQK4vm3vCX0tfRrOBEbgBlDmksRHAUkABUwHuAcEBGIAmS9KjgRuAEjl\n        ULA8CowAXRLdFbXzFBXuGsthPBmwmFQMIBbDBgB64AC4goYUqn5YgPIGaG3gR9jOkzSEsFeQdFHChE5g\n        DrgCWA/mcpg/CnSii338sS0EOoLksa20iTz2goZ7ARuB3aBHuIcPSxatEFjwzKDcRQ8MEK8jKa4hKQ5K\n        34LEAMzBgJCSMITnkZQQSkqoS2JvZ0B/dcpqGzh1Mg+SjpXA2PWBCrJaEi+F3hUS/iUL0RYTgQjQA+KL\n        GkLAAYA+CH8gADQCfriAAP3x9UcWEKA/GgFoCpBALskEBWT/y9H/A/3hBRH+7wRAbAL8A3vgi6sxAUIA\n        KqRam0YRJ4PsJenSUhxpCkcO7ABFDRVVZSVlawbz+Ia154Kdb0UEN4ZFNEWFtMRHdUanPkmKuOzvcjM6\n        trskf+xw4ci1M/MPH7943PZ+fHZpfLLr2tXFrpG302Pv5kbfzc7P9/RNNz0cu3b9ZX8vsMKr0cGl8anZ\n        u5enr1x40dzyZqDrWfuT6dau2Z7hmQcPnzXffYHtozv7D9YM797al5bcGBB4P8Kry9ulxdXlsYfrcJjb\n        dKjHQJjPZEbEeHzgUFzIaEzg02i3Ln+7Jx42zY5rbljqX7AxfWRldsncoHGD8WUro0vrjG+YGx421Tmo\n        q17GZ5erc3dr8eP4LBcWNZXDTKLTshjURKaqA1XFlywHmqqtqpKlqqIrk+rHoNnT1QxUlPRUlPWVlQ1V\n        lNbR1IwYdAcNDUMWS4/DNRUItBhMPQ5Pm8vVFQjW6BmbG5uZGxu5Wq8PcXINdfMI9XKzW29vrGNutc7K\n        3c83KDLRyyfW3j3CxzsuOjo3Ii7b0yvSzS/GPSLRPyAhLCA+KrEwIbskLb24MLOmsLgmtWpXSl71lryt\n        ZdW7UvNrknIr08q355XuLM6ryCupy6/ZX7SjPi03e3NJSWXl/pKyXVsrduVl1/iFZRbV1Nk42m9wCoxI\n        2eIXGOHg4OEeEOLuF27j6G1ibmVqZr3GeoO1i4d7SKRLQKCrd1BAcOomj9A1lo6bvMK9/SJD4pIjtuR4\n        BEY4uQducglw94h0D4y28/C32eRv5xNqGxjiGhAWEZ9p4+CipsZgcTl0FvrugQMw5EtjM1l8DhgBHB4N\n        c3jYYA0weQIGB91B2BwUx8cLqDQOaHwaEzZqgrSnc4V0MlcSE4QY2FSOCp/iAhbh4TE2kuPTWAI6BztJ\n        KMgpqxuauscnmlu76pha5xTl7Tt6IqV4m2d8sp65JahdKpNltMaWxhD8JC6BohgbwKHvXlkFwBflPAZ4\n        UXcTTwui/GoyPjpniN+f+GHgI+IjUsASYoR4WLgH38JOdOujox9BHBAZczTxdTW5CE0BjBXjThEliChH\n        dBFEeWI9wH1Jnij2hyA7CYuQCDMxWfDhyTXBLABMByiHM2g0UKTlrB09E7aU6BqaIQGgiUMjKC/yAiEH\n        4FfQDsBcIEB/tAlwJGT1wfKdRyv2ncvbfjSlqDYpryq1oMYvIs3OLWCTT7hHYLxPWHJwak5mVf2hS9eL\n        avdoq2syxMRAvAOGAtADXLIxmUdUAEXcPoCnogOS+y+q8+JQUMUD4ALI4oEo50caVflaBeQDrhTmiRpg\n        MReqcqAT2AYcIHL+wNKTRW8S2ApwfS1Z7PgGct5MThLQ302RAqYAXIr0/UcXEGaREscOXM1SASwACeAb\n        IAA9eYqGHBIVXF9AlDs8GMaikZMoejKY/ckm1LWOLHNpyXXSEtbSEpZSkqZSEibSEqbScCCpQziATyYB\n        8Ej+j7YUMgoQHkhpUP1g+gD0g/ZnSEuoSaG6B5iGV5H/R0QAGA3GlFBJRcoqAaAF8IMM/tsCEJkIxAsk\n        CgDApQD3pbEiTIT7Io8QwjocANCLlkjlEzJA5P/xEdlMyAM+/om8gvYXgOmDXamxXyldmkKVlqbJSHPk\n        5YRKShwVFVUlRRcuvXCNwR5728semxqjgidKMzpTou/GhR32sjvo4XavIKutrqxrd3lzSfn9yrLB61dH\n        z+2bPrVroeXh66eji91dC003l/q6VwY6X3Y/+bjw/OPrlwsDwxMP7j67d/XFg1tLnd2vOztmL1+fvHt9\n        YbTzTW//Ulfr6I3rI9euDJ04MXLuzFhpcku0X0dswECE/4NQ73vhbp2eTsMBrt1R3h0hnuOxQUMhHt0+\n        7o+8bZ8E23W5W953sLzrtO62jdGNNQbXjAwa15vdtlt3yUJ3l57GDmPt45r8Qjojlc3YKWRVCNlhLEYM\n        kxpFp8Wy6OlMagxNzVlN2ZWm6qyqYq+i4qCqsolBc2OouTKoNmqqHEUFjrKSIY2moaJsyGbb6OuwaTS6\n        CtWAzwNdKmAxNfkcPU0Nc30jc0MDc2NjC9N1rhudfJw2+djZ2ltvMF+z3tba1tXOwcMrxD0wboNHsL1L\n        kH9gbEBwrJdPpLtPjGtwjLNXsK9veHhCVlBUZnBMcmxqeVJmRWpWSXpSVmpO3uackvLSvRHJJSGReWlZ\n        BVnJJbm5u0vq92WW70nOrcyvrswvqc3Mr0nYXJxTVJ6RX+0cEGm81jIgLtMnItl0ra31Rq8NLr4m62w1\n        dI3N1tkZm2+0tnNz9Q928Q9x8wlycguJjS8KCgi3sXVf7+xv6x7kERTp6B7k6hnuG57s4huyyS3C2z/K\n        IyzWwTfC1SfC1svPwSMkICh+o6ObKqh7HO/FYbH5gPuA/qo0JouN9cBUJmb74BQwLAfDKWCg+EluD2A9\n        zgVTo2GWJ1ddi6uug3qfzsJ+0Sw2eo2QG+DrgP4cVZzYxVRRY6nRuTT4ywbbgisADU6l8zZ4BG70DNIx\n        t00qKCnZdigkrSBsc7GRuYMSzpOha+qbG5jZIJKSPqCkMQPobgL6JL2HxGBVlERym7h3CKZjLj86cIjA\n        Jx9h8FYGXlc7fWIvTzmC6ZjwQ+oMcBYYwXSi7hHZicbHAi7ciRdHjU+24RdF2wDEkQCIoQAn8eLALfgp\n        0AlcSo2UJZOQgyI2IkV8VwIbiGT6K6pQpGWt7N0Tsor/PxAAiQEowAJuI1mkgPvkPHWVAEp3HC3bfSq3\n        9khGWX166Y60op1+Ean27gGO3mGewYnB8VvCM4tzavceu9ZYUFOvyRXQSS8gxGVZ9MsD0oF4ZEqJA9YD\n        MQDmwgKhDRAPJEFaAyH0kwQh9BEBvhsQyQ8f6WMTZgpsho/4ZFCiAanJgs3YVoi4gOBe6qTnqC7wCuEA\n        faLrjeUldeWx+tdSTsKBkAFcB25tjnk+EmY4zAsoAYMB60jG5xrCEDjml1xEQNxNWKAAd4Ez+AyS6lKS\n        VCkJI2lJe1lJOxlJJxlJaxmkAXQHSWJUwFhGUl9KUktSQgDoL4lJrsAiYAfoUDARCKAftD+APkca/Ug0\n        jAMjAcASNX8G3AcCIIAuMgXEwSzAVqB/MwJkJMRlxGGhHQALNv+gDXT+AO6DEYAEQBbm/2ADuJ8I+ovo\n        AfU++n8A/ckin6P2FxEAfIlswwAxGAFi4uIqkmDBAJfjiEpVHGIsSZOSoklLseSkWfJyXGVlhqoqGMAB\n        DHq+sd4ee8fDPr5NcfHdiRHXAjfdDvF6HOF/K8jjSpBPS2zc3ZjAxtSY+znZnZUlndtL+neVzzc0jJ+o\n        edp0/GVr58snd18Ot74aGXvxpGXx4Z1nzY1PH9yZ6+15MzG6eO/mfPO1Vx1tz7q6nve0PHv0YOLC2b79\n        O8buNz1rb+mtLmzNjm0N833o7zoQ5jka5DUR7jWe4N8V6tvh6zId7TUe4t7h49DisXEo0HPUzbbd1eKR\n        2/ou67XlxgZHjHXaLIzPmBlcMtXeaSAs0eaGcFjOdKotTTWKSa8TciOZ1E10FVcWzZZBdQftT1e1UlO2\n        VFOxVlayU1Z0pqk5UVXt6aqOVFVLNWWhipKGipKWmhpTSZHLpJloa/LZLBCT2nyBNlcoZDJ1hXxdbS0z\n        A4O1+rqmhvqGRmb2Vut9HR297W03Wq+zsrLbuM7O2cbB0TVgg2uwg0uIh3+8d3C4u0eIi3+os5+/o0eA\n        k0+oZ0xiYHScX2C8f3R+eFphXMaWmLiUsMC4yNjszKyCorzKuITyuIy8uKyc3MLtKen5cYnpGTnVaYml\n        sWlborM2J6Vke/hGR0SmBYXFm6+3iUvPCorLMF5jp6ljpGtmbWC2Yb2t01oLWyNTW3UdY2tbDzePMP01\n        Vrb2Xu7uge6ewQHhEUFx8b4RcU7+kRt9w9c5uDv4hETEF4YEJ3mFJrgFJXgEJXoHx/tFxLn7RgMB2HsE\n        Wzt5AsSrMtgsrgYd0JnJopOxX2wOFn/RAL5FiwEfsRlsbASETSB4ArZAi8kRwkfAnnwNHZ6mNp2NZV9q\n        NA6KfdwsoAFDMLkqVIYalQ5yngrcAB+xOAyugM1XV6Uy5OUUTS1sXUMT9KztHQOigsJynDyTIhLyrB18\n        qGw+6GUwMjZ6BOmYmktKUOAtMAEqemz6ht4VGYzKImQrrRYA4ytBZIB4EPiYsA/YjZuBEkgnCaL3sXmn\n        HC4S3RU5hQisi1xJxJgQuYzgPJoFCOj4EdIPKRcgWfz4Fj+FL8IdRTRALqiIaaZADxgDIKELZWzij32K\n        VNSUlXGeF6h4kTuIIi1jae+WuKVEzxhdQAoYHVETQT9aAKqiwTIYYwDoJwSAriFCADUHi2sO59ceK6g7\n        vqUKdER9WvHOgMgMO5cAO/dgN/+o4LgtMblbS/ccvnCvuaRuL5/FpoqJgTDXJ/k5CNwk41OIfZ5XnTaA\n        sCICIPVigP4YBwbdjZYBmc4I2K1PwB00vq4okV8BPwURCjBqCBofP1qNFgBMizxOOiSSDPvh6yYE63Xl\n        0JhYQ+qHRVYFUAswgYUcEgCcXKOA4WWQ/xakPsBcAY/1ZbHHA5gdQD8A/XAMTwtfhxuJklMx6VNW0kpG\n        coMsZn+uJaCvS6IC+qQlnBZIZsIBHND7YAqQ0WAMMusRrsAG9JfGxEo1KXFVijgwCloD0hKq2OkTaUCB\n        Iq5IwdwbZQrpBkGmAsiRxB4p1P7isNAd9DejQUQA6Dha5QBcgOOA7wjwq01A/zsFaJUAiPgXuXuIoYCW\n        AXEBEQIg8h8+BMphSuLMTg4FOADQH1OYGNJSTGkpNRlpqpycQFVZyGCY0tT8tfkFNmsbnDZc8nbvjgq6\n        4+/0ICiwNcznquemCx7ut91dLwd6PE4I701JuxEWeyMy9qqb4+MYn7EzlaN3zw7ta+jfu3vi5s1njU0v\n        HjQtdj6au3p28v7dFyNjc7eaFm40LnR3vGxvXejtWx4dxa5znQ9fPrrzbGjsZfvA6KHdrXVb2iODO4I9\n        WkOdH3g4t/p5tXg7D3k5TwW5jyZ6DQY6dnjbt3hvuO9u9djFqs3Z+p6Nae/GNY/W6l40VX+yVu+KoeY1\n        ffU7euqXtHmV2vwYPtOZquJIpzlxGC5MNT+aWiKTFkMD4a/iRlf1pVNNVFWMVZRsVZUcaeSC24MAAP/0\n        SURBVFQrqqqJirK+qgpPRUGfqqJNVWWoKvPVVOiqyhpcnj6PL2CwhByOlkCgzecbaGqYaGmv1TVaa2hs\n        bKhvami80XSt23o7V/uNdlZrrczXWa/b4GBjv97e1cxqk72tr7dfrJt/yCavcJfAUEcfX2t7b3vvMN+w\n        yJDg6MCoFL/onJDorNDITN+QdJ+QhPCY2IikjPj0gtQtpbG5+UGx2aERaYH+UYHhcfFZ+dExOZERGT4B\n        UZ6hcV5BiTYbvcw3eDn6Rjl5h1rbeesbmJuaWRqts9M3tTK3tLVx8NTQWaNtaGFus8l8vaOFraNnYKRH\n        QKiNo6dPRJx/VKSnV6Czi5+tayBwlZNbaHDwZkfnAGe/QO+QaK/AGO/AOLeAGNfAOAf3IFtXXwffMIFA\n        F3CNzsJuz1QmWAOg/vkcrgCHvGMQGFAbhDxHjclQYzCwLxALG0JwBNosjjqOiuTxuRoaXHXs/KNGY6iQ\n        /qBgAYDwx0VngUkBHIMXZ7DoDD6HrwXkQaVzAS4VVeimji72PkFrrVysNrobWdpabAzMqayPLSgW6poT\n        EFcyWb/JxtVXSgpAG9U9YK6SCshzOBaFZAFt1TBXEpCRDHQExISt0jisET37InwnfX5++Hxk5aXxysAN\n        cAUi/zH1E/Q7SnUAZbAYRH3ogDyAYwD9MQJBIBsOCCITVQ73QkcTcMBqeADOkMgwHKgqwPoRhUbPlRqd\n        XFYRKAqMIfTmw6WUVaVkZK0c3JO2lOobr5GUgidCrBf5/f9CfxIVQM8P0gYGh0UjIasaSmqP5NUAARzL\n        qdqfXrIzvbQuODbLziXQzjVwo2uAe1B8TE75tkMnb7Z01Dac1OULGWKYfIkpOkTC66HPB3AfYRrkMJuC\n        fhtAc8B3OCDp/+hyARoAzAXstpTHyS3wXVFuqDZ2g5A0lMUmQsAfbApeBwgAvgUHmKuDLnugB4wEgHEA\n        uh4uAkAPByInD5ABsAICOjmGBRtA8sMesiimZBgAMAF8BHs05DDlH4wAAH0tkccJo9MUsDkAu02kJCwo\n        IPYl0BYhC4PJpBIYOAAWEoCUpIB0+gT0FxEALDgAMwiuAEaAaMiXChCAFDpYqLDgJNgBUsQOoIjDgaIU\n        pv0oSknCgYgYkAwI6JMYgLgUmdm7agH86BaHrYEwBgAIjgQgWkgDqx1AV1GeAP3qgg/hz4+TuA39RYQc\n        RJEAKUlxqqQ4mHEMCtIANi8ipoCqlJSqtBRVToanIK+lpgrSbg2TnmiqtdPJ6py77b3ATc0B3vfd3G+5\n        bDzjsvGOr+vjFP/mxJDrwT4PkwKa4sKu+gU/DPW6FbLpcmJk78G6jtqCx8kpT3btHjt1dPhk/eTFg5OH\n        9o2cvDR28frCzTMvHt972dG/8Lh1trPnef/gbHvLRMuDud7mkZu3Ji/fXmi8Ontx/1BxWneMd2eaX3NS\n        4B1Pz2sbHe84b2wPcO8P9+6Lch0Ocunws3ngbXHLcc0jx7VnrUwuOlp22K27aKxzwlR/l5FWnaHWdnV+\n        rTrnuDbvmAYnl0MPZVOj2fTNTDUPqnI8TTWOpuZFVc2mqyUwqNqqSjwVRUM1VT0VZXXgPzUVrqoKW0mF\n        r6TMVVFiq1E1sfM9W4fLNdXQIB5rpgaLq8Pja6sLDTQ0zbS0DDV0dDW0DbW0bYzMHdbZ2FnZrDNZZ25q\n        br3WasM6awsLR3Nbzw0OHq5egd4BkS6ewS7uIRtdQ6zs/Rxcw3z9I/2DwgIiU/yjMkFle4bHRsZlx4dl\n        hMdHeoUnB4ZtjszMjEjZEhpV4O2XHhSXlVFRmZZfHpKUF5Na6BuaAGo3Jjbb3TvMJTjB1Nadr65nYeWk\n        a2AGuK9nss7Q2Mps7UZNE0tNfUt9ExsdE3MDSwv/0NigiBQrJ1cbJ093uHVMgl94gl9UoodfvJ2Tl42T\n        t5W9p72fn0dIWER4XFREqmdApJ2zr+2mAC+fGEePILegKANjC8A+Ko1JA7BmsMAaEE36ZXAEqkAAWNPL\n        VWNyVDE2gPYBEAAgOF9TB6wBwHfAfa5Qg83XoLN5YAQQqsDsIFHWCo3BwokCHL4qnauoTFNVY4KpgU2E\n        VNXUWEwTa/uo1FIrJ289UxuT9R7WDv4RKYVVx85s3XvC3NpZGrPzlTjqujbOgSyeJkVKCjAUMVdeWUpa\n        Bstxf7hx0CwgDhmRC0ik8WVk5RDf0TmDBsEqAcgqYFdRGfgn2YlOIZTzSgC1INjRCEACUFTBrFO4MnxK\n        iIG4cZSQaRCISZ+G/zdbf/0gx31njcLyTDMzMzMz93QPz2hG0ojBkixLliwZZJDZjjlmSmJObMcUczgb\n        2E2y4Wc3yT7Pwr33ee8P71/ynvOtGSd736t8U66uqq6qnu4653zwS5Q3moR3SBgQWjqFCNZSD2pWMgvg\n        FgXARmwUrUlhuEC/m1gTByg3KzU6FoLdcAcsABCA3myl/4etswn0zC/COXfQHwMbwQrgj1233vvMbV95\n        4cb7X7h077PX3/XEdVcePXPrg/jZkQAW9vbn9053Hz14/pb7nv36+z/86UPPv5oLhb3CAvAB3yHMRUZN\n        RMGXYAUAN50qYl0aOAYHJ4DmauDybEWkZgLTAf18i+gOBAGeEo4ggL6IHzAajBWRJkR5vp0dJPxIMCZS\n        wkeEATQHAQD6vyQAqeNbTCOXduG9ZAsdDuAEL2zyo5ED/cVV5BHR8gFnw/GwY1wixagrUjxjGKLtMz6C\n        j0s2AcWIg5/YAogTAgP06QKCNSCGi9n0lP+wh8ABdjFgBxjkouePjO0fiK1SAii1vEwlYB3oT4Ev5okE\n        VYA5APQM8zJGy3XsJQ0IQ4ElYH9HAIwHiGDAly6gLwlAwP32kn6fvxGAdLy0XdgBzAKascvoC5KmqzTI\n        WLdsUsgtSoVNpXSolR6dxms0ha22qdd2qZx6opF9blD75tLS56PFt9rdJwbVb28tf3B677sHD3x6ZPN7\n        V47/8Pbz31icf2Gx98nVK5/fcOLTu2/+9MKJL04f/+TGsz+6+/I/3nDDp5eu/fS2Gz8/d+iH9971xy8+\n        +c1n7//pnXf+5zvv/vuPv/vvv/jJ//qH7//LJ9/53Rsv//zp+3/95jN/euHlP7/wzF9fe/g39578/ZVr\n        /nrL9f9x44k/HF3+yfz4B3tWvrdv4ftbc/96cOnnK6Nf7h79ar37D5PmR/3SN+rZp4q5Z3Lpl4rJrxWS\n        z5VTt6aDx4K+i2H/w1HvpYh32e9ad9v3263H7DACzBt264LNtGwxjs2mgMnotcDGNlj0Wq9JHzab/Saj\n        32BwGHRWg95ntkc8vojPF3A4YhCjLqfXagu7PBGfPx4MJcLRZJjlsOFAOBpL1LP5XqnWKddqhXKlVKrm\n        841cvlHvFzvTymCx3lpoQ/Uv7ZmuHGgPN7pz68Px7vHaocnmkeni4YUVwOue+bW9Bw5cffTAuT0Hzq4f\n        Pb1x7JrNo+f3X3vTuXP3HD92676TN+09cfbw9TecuPrMgf1nJ3uObm2d2dpzqlAbVNpz2Vo/EMkk87Vg\n        NJXM1QKxZD5Xy2UaTk84U2oW6710oVyodSdL+zu9aa3V783v6S6sz+/ZWj54YrJxeHXfNZPVo/sPXrN3\n        68TWqfMHj9+wsXV67+ELo5Wj3cFad7Q+v7Y12X1gsrmv3BwYTTaj0Wa1skEbIBq4T0eNG1DutgLxaRl4\n        2drB7oVBwIyeaDKSSDt9QavD7XSzcbTXF7JyDmGfnb2DArAMYFOYmPvvMlvtJosNZABgxTCxN5wdQj6c\n        KVx7y61feezVUK7pjhTmFq+55Zannv/6W4888dy1N91d7E+MYjowlz/anOwpdRflMAJETZYk8BUqcICW\n        HnmtVq3Ws0jYQH8OoB3mgkKpBrjzeMp/en7IDYIVJCbAFsl64CzBjBOIUAHzRPVStJYBWOHAAQ0AtfV6\n        yQkjxDtoQFQSkHso/A0aho7pmGIxGgO2hH5yhsQBAHT2IsXJeRjOYxJBXZxfodZ2pmvsBSTaQXOeHItz\n        hwD4dskUkNAfY4cAHLAAnr2Z0P/UjQ+ABp65ePdXr73lkfUDZ3uTzdHygfnNE6v7r9k6e+M9z3zt/R/8\n        9J6vvgjJ4xNZQJDkSREKBsQD96n9FQTKgEjKBCsA94GeQO2gsAwgtCH8q1pGDqSOaQRW4Kx6NkV5Ls9o\n        2cqNwWEB3/QjCcQHsgPH8XaJA+LS3AMq1vdC5ovjeQwsjDS7DJEMsBGcge153WxFkv8aeVRLbw94CLif\n        wBDOJTYHpT0h94mag75KVhddP6Wm/1jB0quUOURKUlBU/EL4cykqACJydoMIiXwnm4KqHxwgmI8zw0g0\n        APhWCoc+IB5GgMgHldw7M1rR3A2Yjr2S2McZyAfbWE+pDskvEYAIGwhTQLwEiOMfCWDHHbQt7bnxb5k/\n        GJJHiEfTFvgbMYhdfNdVgP7ZGad81jg7Y6IXiGYcqMsqHEFWJewApU2rduq1LqslYTPvsZkeyIS+2s/f\n        06y82Ru93m++MK68sbbw5tLS1/rDT6/Z99sHb/zh9ac+XJl/bXHw3on17958/P3rj79zaPOdI1vfXl34\n        5OSB7197/MOTB79z8eyP7jjx3Ycv//irT/z0uSd//+7X/vDy1/782Xf+6x+++5fvf/LXD9//l3e++b9+\n        9Ol//Pzj37358i9efem3r77yq5ce+tU9t//6xLHfX7f/f123769X7/3z2X2/P7fxpzNrfzy6/tPdS7/Y\n        nPx2c/KTSfOH7fInlew71fhb7cwH7dz3y4mPavk3G7lnM5FHIr6HEr4n0+Hbo/5Tfseqy7bbaRs6LCO7\n        dclpK9rMHoPBb9YHLUaXUe82GNxGvd9k8BkMYIWw1eSzmL02W9DtjXoDYY8nHPKGfXRz+F3eoM+bCgbj\n        /lCaDRBCoYAvlkw1csVBsdKv1NqVQq2UqxdLvWK92ewVGqNab7lcn2DncLJvbnmjO1xpDVebw9XedH1u\n        YXNhfn9/YaOzuGcyf3i6enhh4/Da1qmt4yf3HD25sv/s5sHzR05fd+zkpaOHLu/dOL125Op9B46s7wZn\n        HJxbPNAcTNL5WixRTWTrkUTeF0p6A0lfMJnL1zK5cjSej8azqVK10h7lK91Ysphv9hvDaaU2HC9ujZe2\n        is3R/O5Th47eNr9xaN+JCwf3njiw5+r9x29e3n92uudce25ve7TSn2501/e2F9e6w1WwVLW/ANyHRBW+\n        e9Hl3+62Urkzwwe473AFmPbjgjXAYIDLG4qk8vF0gSVddjf4wOMPuUEGTg9TdxweO9tH4+/qsTicZquT\n        ytpoAbRBCEPhAs7UGqNab2w2Jw8+/vSB6y4ZvLFye3r7pQceufuFex9+7Yabbt5/6kBtfrc7mAKSesPJ\n        QmOxPd3ncPtlMjkwWmC36NaAFcmTIzL6NXr6YaD3BT0IAthxyuNgevxZNszMUbIIp2xk/uj2AVoxzxdO\n        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\n        nQc37hxt7tyaXrW+rpWoX7WxrnVTY1t3a2dPK+JZ3Q21pjVdDe1dLWu2tm/Y0baxp6VzS3PH1vaN2zq6\n        e5vXbKlt7KxDTjq6W9dCuRsxpBo743WruGMn1ZyoW1XbvKa2pSPd0lnXui7V0BGtaQon6kPxulA8HYzV\n        wc3TRmuaIjVNCBJPr5JvQ7ZEU03RJIXR2mZcQsgXm+tXc1tqsjFa01gdrqlwBWDeKtCCMFoeNKunws2n\n        RPLZMt5IDEaT9U3tbeu6B/YfOXXp9s37z5+6dLOmrrG4jPN9Tvkx8V9G+naIAbgCA/Bw556RNRt6Nm7d\n        NX3i9KG5hT1HZvfNnhiZpwH4lX/2g1//vT/5Nz/7h//17/7bH/zJj3//z/+XP/+Pf/PPf/Rn3/rN33n0\n        vV9765PvvPjuRy++8/433v3gpbff/8Y7H7707offePfDl995n5dvf/DKWxA++vrbj77+1qOX3v7g1Uff\n        fP39T+T349fe++br7330xqOP3/7os1/61uePvvX5ux9/9+0Pv/3ao49feuvd519+/cVX3njptbdeeevd\n        V9959No7H7z+3oevv/fBq28/evXdD19/9AkCvvn+x4jh5Tffe+n1d1545a3nX37rhVfefuGVN59/6Y2v\n        ff2151585ZkXXn743EvA11567cVX33rp9Xdfe/vRK2++99RzL926+/Ttuw/vPnjmiXtP3bx9/9rNe5ev\n        37l07fb5q0+cuXjtxJkLM8dOT86fIuYWJmZOTMwtTM2fnDp+5ujpi8fPXj116RYq5/Kdp89cvXvq0hPn\n        bt2//OSzF249PHPliZOXbpy6ePPkhRvHF68cP3v5zNUnzt24u3j17pmrd9BCxxevnrwIhVvQv/nwhWv3\n        vnbp9sNz159cvHp78cpt/l67c/HmfQgvPfHw0q0H52/cPX/9SSicv3FPOej7xMPLt5+6fAd4eOXO01fv\n        PnP9/nNX7z1z7vrdCzfunbl868yVW5du3seM4MaDr91++sW7z379zjMv3nnu6w9efPXpF1+7//wrd559\n        6clnX3rw/Mv3X3gZjttPvwCde8994y7lUH4BoSB88pkX7j7z4hMPX7j18PnbT33t5oNnrz351NU7D68J\n        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\n</value>\n  </data>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Properties/Settings.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code was generated by a tool.\n//     Runtime Version:4.0.30319.42000\n//\n//     Changes to this file may cause incorrect behavior and will be lost if\n//     the code is regenerated.\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace MobiusEditor.Properties {\n    \n    \n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator\", \"15.9.0.0\")]\n    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {\n        \n        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\n        \n        public static Settings Default {\n            get {\n                return defaultInstance;\n            }\n        }\n        \n        [global::System.Configuration.ApplicationScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"2\")]\n        public int Quality {\n            get {\n                return ((int)(this[\"Quality\"]));\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"0, 0\")]\n        public global::System.Drawing.Point ToolDialogPosition {\n            get {\n                return ((global::System.Drawing.Point)(this[\"ToolDialogPosition\"]));\n            }\n            set {\n                this[\"ToolDialogPosition\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool ShowInviteWarning {\n            get {\n                return ((bool)(this[\"ShowInviteWarning\"]));\n            }\n            set {\n                this[\"ShowInviteWarning\"] = value;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Properties/Settings.settings",
    "content": "﻿<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"http://schemas.microsoft.com/VisualStudio/2004/01/settings\" CurrentProfile=\"(Default)\" GeneratedClassNamespace=\"MobiusEditor.Properties\" GeneratedClassName=\"Settings\">\n  <Profiles />\n  <Settings>\n    <Setting Name=\"Quality\" Type=\"System.Int32\" Scope=\"Application\">\n      <Value Profile=\"(Default)\">2</Value>\n    </Setting>\n    <Setting Name=\"ToolDialogPosition\" Type=\"System.Drawing.Point\" Scope=\"User\">\n      <Value Profile=\"(Default)\">0, 0</Value>\n    </Setting>\n    <Setting Name=\"ShowInviteWarning\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n  </Settings>\n</SettingsFile>"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/ActionDataTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.RedAlert\n{\n    public static class ActionDataTypes\n    {\n        public enum ThemeType\n        {\n            THEME_QUIET = -3,\n            THEME_PICK_ANOTHER = -2,\n            THEME_NONE = -1,\n            THEME_BIGF,\n            THEME_CRUS,\n            THEME_FAC1,\n            THEME_FAC2,\n            THEME_HELL,\n            THEME_RUN1,\n            THEME_SMSH,\n            THEME_TREN,\n            THEME_WORK,\n            THEME_AWAIT,\n            THEME_DENSE_R,\n            THEME_FOGGER1A,\n            THEME_MUD1A,\n            THEME_RADIO2,\n            THEME_ROLLOUT,\n            THEME_SNAKE,\n            THEME_TERMINAT,\n            THEME_TWIN,\n            THEME_VECTOR1A,\n            THEME_MAP,\n            THEME_SCORE,\n            THEME_INTRO,\n            THEME_CREDITS,\n            THEME_2ND_HAND,\n            THEME_ARAZOID,\n            THEME_BACKSTAB,\n            THEME_CHAOS2,\n            THEME_SHUT_IT,\n            THEME_TWINMIX1,\n            THEME_UNDER3,\n            THEME_VR2,\n            THEME_BOG,\n            THEME_FLOAT_V2,\n            THEME_GLOOM,\n            THEME_GRNDWIRE,\n            THEME_RPT,\n            THEME_SEARCH,\n            THEME_TRACTION,\n            THEME_WASTELND,\n        };\n\n        public enum VocType\n        {\n            VOC_NONE = -1,\n            VOC_GIRL_OKAY,          // \"okay\"\n            VOC_GIRL_YEAH,          // \"yeah?\"\n            VOC_GUY_OKAY,           //\t\"okay\"\n            VOC_GUY_YEAH,           // \"yeah?\"\n            VOC_MINELAY1,           // mine layer sound\n            VOC_ACKNOWL,            //\t\"acknowledged\"\n            VOC_AFFIRM,             //\t\"affirmative\"\n            VOC_AWAIT,              //\t\"awaiting orders\"\n            VOC_ENG_AFFIRM,     // Engineer: \"affirmative\"\n            VOC_ENG_ENG,            // Engineer: \"engineering\"\n            VOC_NO_PROB,            //\t\"not a problem\"\n            VOC_READY,              //\t\"ready and waiting\"\n            VOC_REPORT,             //\t\"reporting\"\n            VOC_RIGHT_AWAY,     //\t\"right away sir\"\n            VOC_ROGER,              //\t\"roger\"\n            VOC_UGOTIT,             //\t\"you got it\"\n            VOC_VEHIC,              //\t\"vehicle reporting\"\n            VOC_YESSIR,             //\t\"yes sir\"\n            VOC_SCREAM1,            //\tshort infantry scream\n            VOC_SCREAM3,            //\tshort infantry scream\n            VOC_SCREAM4,            //\tshort infantry scream\n            VOC_SCREAM5,            //\tshort infantry scream\n            VOC_SCREAM6,            //\tshort infantry scream\n            VOC_SCREAM7,            //\tshort infantry scream\n            VOC_SCREAM10,           //\tshort infantry scream\n            VOC_SCREAM11,           //\tshort infantry scream\n            VOC_YELL1,              //\tlong infantry scream\n            VOC_CHRONO,             //\tChronosphere sound.\n            VOC_CANNON1,            // Cannon sound (medium).\n            VOC_CANNON2,            // Cannon sound (short).\n            VOC_IRON1,\n            VOC_ENG_MOVEOUT,        // Engineer: \"movin' out\"\n            VOC_SONAR,              // sonar pulse\n            VOC_SANDBAG,            // sand bag crunch\n            VOC_MINEBLOW,\n            VOC_CHUTE1,             // wind swoosh sound\n            VOC_DOG_BARK,           // dog bark\n            VOC_DOG_WHINE,          // dog whine\n            VOC_DOG_GROWL2,     // strong dog growl\n            VOC_FIRE_LAUNCH,        // fireball launch sound\n            VOC_FIRE_EXPLODE,       // fireball explode sound\n            VOC_GRENADE_TOSS,       // grenade toss\n            VOC_GUN_5,              // 5 round gun burst (slow).\n            VOC_GUN_7,              // 7 round gun burst (fast).\n            VOC_ENG_YES,            // Engineer: \"yes sir\"\n            VOC_GUN_RIFLE,          // Rifle shot.\n            VOC_HEAL,               // Healing effect.\n            VOC_DOOR,               // Hyrdrolic door.\n            VOC_INVULNERABLE,       // Invulnerability effect.\n            VOC_KABOOM1,            // Long explosion (muffled).\n            VOC_KABOOM12,           // Very long explosion (muffled).\n            VOC_KABOOM15,           // Very long explosion (muffled).\n            VOC_SPLASH,             // Water splash\n            VOC_KABOOM22,           // Long explosion (sharp).\n            VOC_AACANON3,           // AA-Cannon\n            VOC_TANYA_DIE,          // Tanya: scream\n            VOC_GUN_5F,             // 5 round gun burst (fast).\n            VOC_MISSILE_1,          // Missile with high tech effect.\n            VOC_MISSILE_2,          // Long missile launch.\n            VOC_MISSILE_3,          // Short missile launch.\n            VOC_x6,\n            VOC_GUN_5R,             // 5 round gun burst (rattles).\n            VOC_BEEP,               // Generic beep sound.\n            VOC_CLICK,              //\tGeneric click sound.\n            VOC_SILENCER,           // Silencer.\n            VOC_CANNON6,            // Long muffled cannon shot.\n            VOC_CANNON7,            // Sharp mechanical cannon fire.\n            VOC_TORPEDO,            // Torpedo launch.\n            VOC_CANNON8,            // Sharp cannon fire.\n            VOC_TESLA_POWER_UP, // Hum charge up.\n            VOC_TESLA_ZAP,          // Tesla zap effect.\n            VOC_SQUISH,             // Squish effect.\n            VOC_SCOLD,              // Scold bleep.\n            VOC_RADAR_ON,           // Powering up electronics.\n            VOC_RADAR_OFF,          // B movie power down effect.\n            VOC_PLACE_BUILDING_DOWN,    // Building slam down sound.\n            VOC_KABOOM30,           // Short explosion (HE).\n            VOC_KABOOM25,           // Short growling explosion.\n            VOC_x7,\n            VOC_DOG_HURT,           //\tDog whine.\n            VOC_DOG_YES,            // Dog 'yes sir'.\n            VOC_CRUMBLE,            // Building crumble.\n            VOC_MONEY_UP,           // Rising money tick.\n            VOC_MONEY_DOWN,     // Falling money tick.\n            VOC_CONSTRUCTION,       // Building construction sound.\n            VOC_GAME_CLOSED,        // Long bleep.\n            VOC_INCOMING_MESSAGE,   // Soft happy warble.\n            VOC_SYS_ERROR,          // Sharp soft warble.\n            VOC_OPTIONS_CHANGED,    // Mid range soft warble.\n            VOC_GAME_FORMING,       // Long warble.\n            VOC_PLAYER_LEFT,        // Chirp sequence.\n            VOC_PLAYER_JOINED,  // Reverse chirp sequence.\n            VOC_DEPTH_CHARGE,       // Distant explosion sound.\n            VOC_CASHTURN,           // Airbrake.\n            VOC_TANYA_CHEW,     // Tanya: \"Chew on this\"\n            VOC_TANYA_ROCK,     // Tanya: \"Let's rock\"\n            VOC_TANYA_LAUGH,        // Tanya: \"ha ha ha\"\n            VOC_TANYA_SHAKE,        // Tanya: \"Shake it baby\"\n            VOC_TANYA_CHING,        // Tanya: \"Cha Ching\"\n            VOC_TANYA_GOT,          // Tanya: \"That's all you got\"\n            VOC_TANYA_KISS,     // Tanya: \"Kiss it bye bye\"\n            VOC_TANYA_THERE,        // Tanya: \"I'm there\"\n            VOC_TANYA_GIVE,     // Tanya: \"Give it to me\"\n            VOC_TANYA_YEA,          // Tanya: \"Yea?\"\n            VOC_TANYA_YES,          // Tanya: \"Yes sir?\"\n            VOC_TANYA_WHATS,        // Tanya: \"What's up.\"\n            VOC_WALLKILL2,          // Crushing wall sound.\n            VOC_x8,\n            VOC_TRIPLE_SHOT,        // Three quick shots in succession.\n            VOC_SUBSHOW,            // Submarine surfacing.\n            VOC_E_AH,               // Einstein \"ah\"\n            VOC_E_OK,               // Einstein \"ok\"\n            VOC_E_YES,              // Einstein \"yes\"\n            VOC_TRIP_MINE,          // mine explosion sound\n            VOC_SPY_COMMANDER,  // Spy: \"commander?\"\n            VOC_SPY_YESSIR,     // Spy: \"yes sir\"\n            VOC_SPY_INDEED,     // Spy: \"indeed\"\n            VOC_SPY_ONWAY,          // Spy: \"on my way\"\n            VOC_SPY_KING,           // Spy: \"for king and country\"\n            VOC_MED_REPORTING,  // Medic: \"reporting\"\n            VOC_MED_YESSIR,     // Medic: \"yes sir\"\n            VOC_MED_AFFIRM,     // Medic: \"affirmative\"\n            VOC_MED_MOVEOUT,        // Medic: \"movin' out\"\n            VOC_BEEP_SELECT,        // map selection beep\n            VOC_THIEF_YEA,          // Thief: \"yea?\"\n            VOC_ANTDIE,\n            VOC_ANTBITE,\n            VOC_THIEF_MOVEOUT,  // Thief: \"movin' out\"\n            VOC_THIEF_OKAY,     // Thief: \"ok\"\n            VOC_x11,\n            VOC_THIEF_WHAT,     // Thief: \"what\"\n            VOC_THIEF_AFFIRM,       // Thief: \"affirmative\"\n            VOC_STAVCMDR,\n            VOC_STAVCRSE,\n            VOC_STAVYES,\n            VOC_STAVMOV,\n            VOC_BUZZY1,\n            VOC_RAMBO1,\n            VOC_RAMBO2,\n            VOC_RAMBO3,\n            VOC_MECHYES1,\n            VOC_MECHHOWDY1,\n            VOC_MECHRISE1,\n            VOC_MECHHUH1,\n            VOC_MECHHEAR1,\n            VOC_MECHLAFF1,\n            VOC_MECHBOSS1,\n            VOC_MECHYEEHAW1,\n            VOC_MECHHOTDIG1,\n            VOC_MECHWRENCH1,\n            VOC_STBURN1,\n            VOC_STCHRGE1,\n            VOC_STCRISP1,\n            VOC_STDANCE1,\n            VOC_STJUICE1,\n            VOC_STJUMP1,\n            VOC_STLIGHT1,\n            VOC_STPOWER1,\n            VOC_STSHOCK1,\n            VOC_STYES1,\n            VOC_CHRONOTANK1,\n            VOC_MECH_FIXIT1,\n            VOC_MAD_CHARGE,\n            VOC_MAD_EXPLODE,\n            VOC_SHOCK_TROOP1,\n        };\n\n        public enum VoxType\n        {\n            VOX_NONE = -1,\n            VOX_ACCOMPLISHED,                   //\tmission accomplished\n            VOX_FAIL,                           //\tyour mission has failed\n            VOX_NO_FACTORY,                 //\tunable to comply, building in progress\n            VOX_CONSTRUCTION,                   //\tconstruction complete\n            VOX_UNIT_READY,                 // unit ready\n            VOX_NEW_CONSTRUCT,              //\tnew construction options\n            VOX_DEPLOY,                         //\tcannot deploy here\n            VOX_STRUCTURE_DESTROYED,        // structure destroyed\n            VOX_INSUFFICIENT_POWER,         // insufficient power\n            VOX_NO_CASH,                        //\tinsufficient funds\n            VOX_CONTROL_EXIT,                   //\tbattle control terminated\n            VOX_REINFORCEMENTS,             //\treinforcements have arrived\n            VOX_CANCELED,                       //\tcanceled\n            VOX_BUILDING,                       //\tbuilding\n            VOX_LOW_POWER,                      //\tlow power\n            VOX_NEED_MO_MONEY,              //\tneed more funds\n            VOX_BASE_UNDER_ATTACK,          //\tour base is under attack\n            VOX_UNABLE_TO_BUILD,                //\tunable to build more\n            VOX_PRIMARY_SELECTED,           //\tprimary building selected\n            VOX_MADTANK_DEPLOYED,\t\t\t// M.A.D. Tank Deployed\n            VOX_none4,\n            VOX_UNIT_LOST,                      //\tunit lost\n            VOX_SELECT_TARGET,              // select target\n            VOX_PREPARE,                        //\tenemy approaching\n            VOX_NEED_MO_CAPACITY,           //\tsilos needed\n            VOX_SUSPENDED,                      //\ton hold\n            VOX_REPAIRING,                      //\trepairing\n            VOX_none5,\n            VOX_none6,\n            VOX_AIRCRAFT_LOST,\n            VOX_none7,\n            VOX_ALLIED_FORCES_APPROACHING,\n            VOX_ALLIED_APPROACHING,\n            VOX_none8,\n            VOX_none9,\n            VOX_BUILDING_INFILTRATED,\n            VOX_CHRONO_CHARGING,\n            VOX_CHRONO_READY,\n            VOX_CHRONO_TEST,\n            VOX_HQ_UNDER_ATTACK,\n            VOX_CENTER_DEACTIVATED,\n            VOX_CONVOY_APPROACHING,\n            VOX_CONVOY_UNIT_LOST,\n            VOX_EXPLOSIVE_PLACED,\n            VOX_MONEY_STOLEN,\n            VOX_SHIP_LOST,\n            VOX_SATALITE_LAUNCHED,\n            VOX_SONAR_AVAILABLE,\n            VOX_none10,\n            VOX_SOVIET_FORCES_APPROACHING,\n            VOX_SOVIET_REINFORCEMENTS,\n            VOX_TRAINING,\n            VOX_ABOMB_READY,\n            VOX_ABOMB_LAUNCH,\n            VOX_ALLIES_N,\n            VOX_ALLIES_S,\n            VOX_ALLIES_E,\n            VOX_ALLIES_W,\n            VOX_OBJECTIVE1,\n            VOX_OBJECTIVE2,\n            VOX_OBJECTIVE3,\n            VOX_IRON_CHARGING,\n            VOX_IRON_READY,\n            VOX_RESCUED,\n            VOX_OBJECTIVE_NOT,\n            VOX_SIGNAL_N,\n            VOX_SIGNAL_S,\n            VOX_SIGNAL_E,\n            VOX_SIGNAL_W,\n            VOX_SPY_PLANE,\n            VOX_FREED,\n            VOX_UPGRADE_ARMOR,\n            VOX_UPGRADE_FIREPOWER,\n            VOX_UPGRADE_SPEED,\n            VOX_MISSION_TIMER,\n            VOX_UNIT_FULL,\n            VOX_UNIT_REPAIRED,\n            VOX_TIME_40,\n            VOX_TIME_30,\n            VOX_TIME_20,\n            VOX_TIME_10,\n            VOX_TIME_5,\n            VOX_TIME_4,\n            VOX_TIME_3,\n            VOX_TIME_2,\n            VOX_TIME_1,\n            VOX_TIME_STOP,\n            VOX_UNIT_SOLD,\n            VOX_TIMER_STARTED,\n            VOX_TARGET_RESCUED,\n            VOX_TARGET_FREED,\n            VOX_TANYA_RESCUED,\n            VOX_STRUCTURE_SOLD,\n            VOX_SOVIET_FORCES_FALLEN,\n            VOX_SOVIET_SELECTED,\n            VOX_SOVIET_EMPIRE_FALLEN,\n            VOX_OPERATION_TERMINATED,\n            VOX_OBJECTIVE_REACHED,\n            VOX_OBJECTIVE_NOT_REACHED,\n            VOX_OBJECTIVE_MET,\n            VOX_MERCENARY_RESCUED,\n            VOX_MERCENARY_FREED,\n            VOX_KOSOYGEN_FREED,\n            VOX_FLARE_DETECTED,\n            VOX_COMMANDO_RESCUED,\n            VOX_COMMANDO_FREED,\n            VOX_BUILDING_IN_PROGRESS,\n            VOX_ATOM_PREPPING,\n            VOX_ALLIED_SELECTED,\n            VOX_ABOMB_PREPPING,\n            VOX_ATOM_LAUNCHED,\n            VOX_ALLIED_FORCES_FALLEN,\n            VOX_ABOMB_AVAILABLE,\n            VOX_ALLIED_REINFORCEMENTS,\n            VOX_SAVE1,\n            VOX_LOAD1,\n        };\n\n        public enum SpecialWeaponType\n        {\n            SPC_NONE = -1,\n            SPC_SONAR_PULSE,            // Momentarily reveals submarines.\n            SPC_NUCLEAR_BOMB,           //\tTactical nuclear weapon.\n            SPC_CHRONOSPHERE,           // Paradox device, for teleportation\n            SPC_PARA_BOMB,              // Parachute bomb delivery.\n            SPC_PARA_INFANTRY,      // Parachute reinforcement delivery.\n            SPC_SPY_MISSION,            // Spy plane to take photo recon mission.\n            SPC_IRON_CURTAIN,           // Bestow invulnerability on a unit/building\n            SPC_GPS,\t\t\t\t\t\t// give allies free unjammable radar.\n        };\n\n        public enum QuarryType\n        {\n            QUARRY_NONE,\n            QUARRY_ANYTHING,                    // Attack any enemy (same as \"hunt\").\n            QUARRY_BUILDINGS,                   // Attack buildings (in general).\n            QUARRY_HARVESTERS,              // Attack harvesters or refineries.\n            QUARRY_INFANTRY,                    // Attack infantry.\n            QUARRY_VEHICLES,                    // Attack combat vehicles.\n            QUARRY_VESSELS,                 // Attach ships.\n            QUARRY_FACTORIES,                   // Attack factories (all types).\n            QUARRY_DEFENSE,                 // Attack base defense buildings.\n            QUARRY_THREAT,                      // Attack enemies near friendly base.\n            QUARRY_POWER,                       // Attack power facilities.\n            QUARRY_FAKES,\t\t\t\t\t\t// Prefer to attack fake buildings.\n        };\n\n        public enum VQType\n        {\n            VQ_NONE = -1,\n            VQ_AAGUN,\n            VQ_MIG,\n            VQ_SFROZEN,\n            VQ_AIRFIELD,\n            VQ_BATTLE,\n            VQ_BMAP,\n            VQ_BOMBRUN,\n            VQ_DPTHCHRG,\n            VQ_GRVESTNE,\n            VQ_MONTPASS,\n            VQ_MTNKFACT,\n            VQ_CRONTEST,\n            VQ_OILDRUM,\n            VQ_ALLYEND,\n            VQ_RADRRAID,\n            VQ_SHIPYARD,\n            VQ_SHORBOMB,\n            VQ_SITDUCK,\n            VQ_SLNTSRVC,\n            VQ_SNOWBASE,\n            VQ_EXECUTE,\n            VQ_TITLE,               // Low res.\n            VQ_NUKESTOK,\n            VQ_V2ROCKET,\n            VQ_SEARCH,\n            VQ_BINOC,\n            VQ_ELEVATOR,\n            VQ_FROZEN,\n            VQ_MCV,\n            VQ_SHIPSINK,\n            VQ_SOVMCV,\n            VQ_TRINITY,\n            VQ_ALLYMORF,\n            VQ_APCESCPE,\n            VQ_BRDGTILT,\n            VQ_CRONFAIL,\n            VQ_STRAFE,\n            VQ_DESTROYR,\n            VQ_DOUBLE,\n            VQ_FLARE,\n            VQ_SNSTRAFE,\n            VQ_LANDING,\n            VQ_ONTHPRWL,\n            VQ_OVERRUN,\n            VQ_SNOWBOMB,\n            VQ_SOVCEMET,\n            VQ_TAKE_OFF,\n            VQ_TESLA,\n            VQ_SOVIET8,\n            VQ_SPOTTER,\n            VQ_SCENE1,\n            VQ_SCENE2,\n            VQ_SCENE4,\n            VQ_SOVFINAL,\n            VQ_ASSESS,\n            VQ_SOVIET10,\n            VQ_DUD,\n            VQ_MCV_LAND,\n            VQ_MCVBRDGE,\n            VQ_PERISCOP,\n            VQ_SHORBOM1,\n            VQ_SHORBOM2,\n            VQ_SOVBATL,\n            VQ_SOVTSTAR,\n            VQ_AFTRMATH,\n            VQ_SOVIET11,\n            VQ_MASASSLT,\n            VQ_REDINTRO,        // High res\n            VQ_SOVIET1,\n            VQ_SOVIET2,\n            VQ_SOVIET3,\n            VQ_SOVIET4,\n            VQ_SOVIET5,\n            VQ_SOVIET6,\n            VQ_SOVIET7,\n            VQ_INTRO_MOVIE,\n            VQ_AVERTED,\n            VQ_COUNTDWN,\n            VQ_MOVINGIN,\n            VQ_ALLIED10,\n            VQ_ALLIED12,\n            VQ_ALLIED5,\n            VQ_ALLIED6,\n            VQ_ALLIED8,\n            VQ_TANYA1,\n            VQ_TANYA2,\n            VQ_ALLY10B,\n            VQ_ALLY11,\n            VQ_ALLY14,\n            VQ_ALLY9,\n            VQ_SPY,\n            VQ_TOOFAR,\n            VQ_SOVIET12,\n            VQ_SOVIET13,\n            VQ_SOVIET9,\n            VQ_BEACHEAD,\n            VQ_SOVIET14,\n            VQ_SIZZLE,\n            VQ_SIZZLE2,\n            VQ_ANTEND,\n            VQ_ANTINTRO,\n            VQ_RETALIATION_ALLIED1,\n            VQ_RETALIATION_ALLIED2,\n            VQ_RETALIATION_ALLIED3,\n            VQ_RETALIATION_ALLIED4,\n            VQ_RETALIATION_ALLIED5,\n            VQ_RETALIATION_ALLIED6,\n            VQ_RETALIATION_ALLIED7,\n            VQ_RETALIATION_ALLIED8,\n            VQ_RETALIATION_ALLIED9,\n            VQ_RETALIATION_ALLIED10,\n            VQ_RETALIATION_SOVIET1,\n            VQ_RETALIATION_SOVIET2,\n            VQ_RETALIATION_SOVIET3,\n            VQ_RETALIATION_SOVIET4,\n            VQ_RETALIATION_SOVIET5,\n            VQ_RETALIATION_SOVIET6,\n            VQ_RETALIATION_SOVIET7,\n            VQ_RETALIATION_SOVIET8,\n            VQ_RETALIATION_SOVIET9,\n            VQ_RETALIATION_SOVIET10,\n            VQ_RETALIATION_WINA,\n            VQ_RETALIATION_WINS,\n            VQ_RETALIATION_ANTS,\n        };\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/ActionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class ActionTypes\n    {\n        public const string TACTION_NONE = \"None\";\n        public const string TACTION_WIN = \"Winner is...\";\n        public const string TACTION_LOSE = \"Loser is...\";\n        public const string TACTION_BEGIN_PRODUCTION = \"Production Begins\";\n        public const string TACTION_CREATE_TEAM = \"Create Team...\";\n        public const string TACTION_DESTROY_TEAM = \"Destroy All Teams\";\n        public const string TACTION_ALL_HUNT = \"All to Hunt...\";\n        public const string TACTION_REINFORCEMENTS = \"Reinforcement (team)...\";\n        public const string TACTION_DZ = \"Drop Zone Flare (waypoint)...\";\n        public const string TACTION_FIRE_SALE = \"Fire Sale...\";\n        public const string TACTION_PLAY_MOVIE = \"Play Movie...\";\n        public const string TACTION_TEXT_TRIGGER = \"Text Trigger (ID num)...\";\n        public const string TACTION_DESTROY_TRIGGER = \"Destroy Trigger...\";\n        public const string TACTION_AUTOCREATE = \"Autocreate Begins...\";\n        public const string TACTION_WINLOSE = \"\";\n        public const string TACTION_ALLOWWIN = \"Allow Win\";\n        public const string TACTION_REVEAL_ALL = \"Reveal all map\";\n        public const string TACTION_REVEAL_SOME = \"Reveal around waypoint...\";\n        public const string TACTION_REVEAL_ZONE = \"Reveal zone of waypoint...\";\n        public const string TACTION_PLAY_SOUND = \"Play sound effect...\";\n        public const string TACTION_PLAY_MUSIC = \"Play music theme...\";\n        public const string TACTION_PLAY_SPEECH = \"Play speech...\";\n        public const string TACTION_FORCE_TRIGGER = \"Force Trigger...\";\n        public const string TACTION_START_TIMER = \"Timer Start\";\n        public const string TACTION_STOP_TIMER = \"Timer Stop\";\n        public const string TACTION_ADD_TIMER = \"Timer Extend (1/10th min)...\";\n        public const string TACTION_SUB_TIMER = \"Timer Shorten (1/10th min)...\";\n        public const string TACTION_SET_TIMER = \"Timer Set (1/10th min)...\";\n        public const string TACTION_SET_GLOBAL = \"Global Set...\";\n        public const string TACTION_CLEAR_GLOBAL = \"Global Clear...\";\n        public const string TACTION_BASE_BUILDING = \"Auto Base Building...\";\n        public const string TACTION_CREEP_SHADOW = \"Grow shroud one 'step'\";\n        public const string TACTION_DESTROY_OBJECT = \"Destroy attached building\";\n        public const string TACTION_1_SPECIAL = \"Add 1-time special weapon...\";\n        public const string TACTION_FULL_SPECIAL = \"Add repeating special weapon...\";\n        public const string TACTION_PREFERRED_TARGET = \"Preferred target...\";\n        public const string TACTION_LAUNCH_NUKES = \"Launch Nukes\";\n\n        private static readonly string[] Types;\n\n        static ActionTypes()\n        {\n            Types =\n                (from field in typeof(ActionTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsLiteral && !field.IsInitOnly && typeof(string).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as string).ToArray();\n        }\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/BasicSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.ComponentModel;\n\nnamespace MobiusEditor.RedAlert\n{\n    public class BasicSection : Model.BasicSection\n    {\n        private string win2;\n        [DefaultValue(\"x\")]\n        public string Win2 { get => win2; set => SetField(ref win2, value); }\n\n        private string win3;\n        [DefaultValue(\"x\")]\n        public string Win3 { get => win3; set => SetField(ref win3, value); }\n\n        private string win4;\n        [DefaultValue(\"x\")]\n        public string Win4 { get => win4; set => SetField(ref win4, value); }\n\n        private bool toCarryOver;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool ToCarryOver { get => toCarryOver; set => SetField(ref toCarryOver, value); }\n\n        private bool toInherit;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool ToInherit { get => toInherit; set => SetField(ref toInherit, value); }\n\n        private bool timerInherit;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool TimerInherit { get => timerInherit; set => SetField(ref timerInherit, value); }\n\n        private bool endOfGame;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool EndOfGame { get => endOfGame; set => SetField(ref endOfGame, value); }\n\n        private bool civEvac;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool CivEvac { get => civEvac; set => SetField(ref civEvac, value); }\n\n        private bool noSpyPlane;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool NoSpyPlane { get => noSpyPlane; set => SetField(ref noSpyPlane, value); }\n\n        private bool skipScore;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool SkipScore { get => skipScore; set => SetField(ref skipScore, value); }\n\n        private bool oneTimeOnly;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool OneTimeOnly { get => oneTimeOnly; set => SetField(ref oneTimeOnly, value); }\n\n        private bool skipMapSelect;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool SkipMapSelect { get => skipMapSelect; set => SetField(ref skipMapSelect, value); }\n\n        private bool truckCrate;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool TruckCrate { get => truckCrate; set => SetField(ref truckCrate, value); }\n\n        private bool fillSilos;\n        [TypeConverter(typeof(BooleanTypeConverter))]\n        [DefaultValue(false)]\n        public bool FillSilos { get => fillSilos; set => SetField(ref fillSilos, value); }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/BuildingTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class BuildingTypes\n    {\n        public static readonly BuildingType AdvancedTech = new BuildingType(0, \"atek\", \"TEXT_STRUCTURE_RA_ATEK\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType IronCurtain = new BuildingType(1, \"iron\", \"TEXT_STRUCTURE_RA_IRON\", new bool[2, 2] { { false, false }, { true, true } }, false, \"USSR\");\n        public static readonly BuildingType Weapon = new BuildingType(2, \"weap\", \"TEXT_STRUCTURE_RA_WEAP\", new bool[2, 3] { { true, true, true }, { true, true, true } }, true, \"Greece\", false, false, \"weap2\");\n        public static readonly BuildingType Chronosphere = new BuildingType(3, \"pdox\", \"TEXT_STRUCTURE_RA_PDOX\", new bool[2, 2] { { true, true }, { true, true } }, false, \"Greece\");\n        public static readonly BuildingType Pillbox = new BuildingType(4, \"pbox\", \"TEXT_STRUCTURE_RA_PBOX\", new bool[1, 1] { { true } }, false, \"Greece\");\n        public static readonly BuildingType CamoPillbox = new BuildingType(5, \"hbox\", \"TEXT_STRUCTURE_RA_HBOX\", new bool[1, 1] { { true } }, false, \"Greece\");\n        public static readonly BuildingType Command = new BuildingType(6, \"dome\", \"TEXT_STRUCTURE_RA_DOME\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType GapGenerator = new BuildingType(7, \"gap\", \"TEXT_STRUCTURE_RA_GAP\", new bool[2, 1] { { false }, { true } }, false, \"Greece\");\n        public static readonly BuildingType Turret = new BuildingType(8, \"gun\", \"TEXT_STRUCTURE_RA_GUN\", new bool[1, 1] { { true } }, false, \"Greece\", false, true);\n        public static readonly BuildingType AAGun = new BuildingType(9, \"agun\", \"TEXT_STRUCTURE_RA_AGUN\", new bool[2, 1] { { false }, { true } }, false, \"Greece\", false, true);\n        public static readonly BuildingType FlameTurret = new BuildingType(10, \"ftur\", \"TEXT_STRUCTURE_RA_FTUR\", new bool[1, 1] { { true } }, false, \"USSR\");\n        public static readonly BuildingType Const = new BuildingType(11, \"fact\", \"TEXT_STRUCTURE_RA_FACT\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, true, \"Greece\");\n        public static readonly BuildingType Refinery = new BuildingType(12, \"proc\", \"TEXT_STRUCTURE_RA_PROC\", new bool[3, 3] { { false, true, false }, { true, true, true }, { true, false, false } }, true, \"Greece\");\n        public static readonly BuildingType Storage = new BuildingType(13, \"silo\", \"TEXT_STRUCTURE_RA_SILO\", new bool[1, 1] { { true } }, false, \"Greece\");\n        public static readonly BuildingType Helipad = new BuildingType(14, \"hpad\", \"TEXT_STRUCTURE_RA_HPAD\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType SAM = new BuildingType(15, \"sam\", \"TEXT_STRUCTURE_RA_SAM\", new bool[1, 2] { { true, true } }, false, \"USSR\");\n        public static readonly BuildingType AirStrip = new BuildingType(16, \"afld\", \"TEXT_STRUCTURE_RA_AFLD\", new bool[2, 3] { { true, true, true }, { true, true, true } }, false, \"USSR\");\n        public static readonly BuildingType Power = new BuildingType(17, \"powr\", \"TEXT_STRUCTURE_RA_POWR\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType AdvancedPower = new BuildingType(18, \"apwr\", \"TEXT_STRUCTURE_RA_APWR\", new bool[3, 3] { { false, false, false }, { true, true, true }, { true, true, true } }, true, \"Greece\");\n        public static readonly BuildingType SovietTech = new BuildingType(19, \"stek\", \"TEXT_STRUCTURE_RA_STEK\", new bool[3, 3] { { false, false, false }, { true, true, true }, { true, true, true } }, true, \"USSR\");\n        public static readonly BuildingType Hospital = new BuildingType(20, \"hosp\", \"TEXT_STRUCTURE_RA_HOSP\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType Barracks = new BuildingType(21, \"barr\", \"TEXT_STRUCTURE_RA_BARR\", new bool[2, 2] { { true, true }, { true, true } }, true, \"USSR\");\n        public static readonly BuildingType Tent = new BuildingType(22, \"tent\", \"TEXT_STRUCTURE_RA_TENT\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType Kennel = new BuildingType(23, \"kenn\", \"TEXT_STRUCTURE_RA_KENN\", new bool[1, 1] { { true } }, false, \"USSR\");\n        public static readonly BuildingType Repair = new BuildingType(24, \"fix\", \"TEXT_STRUCTURE_RA_FIX\", new bool[3, 3] { { false, true, false }, { true, true, true }, { false, true, false } }, false, \"Greece\");\n        public static readonly BuildingType BioLab = new BuildingType(25, \"bio\", \"TEXT_STRUCTURE_RA_BIO\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\");\n        public static readonly BuildingType Mission = new BuildingType(26, \"miss\", \"TEXT_STRUCTURE_RA_MISS\", new bool[2, 3] { { true, true, true }, { true, true, true } }, true, \"Greece\");\n        public static readonly BuildingType ShipYard = new BuildingType(27, \"syrd\", \"TEXT_STRUCTURE_RA_SYRD\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, false, \"Greece\");\n        public static readonly BuildingType SubPen = new BuildingType(28, \"spen\", \"TEXT_STRUCTURE_RA_SPEN\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, false, \"USSR\");\n        public static readonly BuildingType MissileSilo = new BuildingType(29, \"mslo\", \"TEXT_STRUCTURE_RA_MSLO\", new bool[1, 2] { { true, true } }, false, \"Greece\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType ForwardCom = new BuildingType(30, \"fcom\", \"TEXT_STRUCTURE_RA_FCOM\", new bool[2, 2] { { false, false }, { true, true } }, true, \"USSR\");\n        public static readonly BuildingType Tesla = new BuildingType(31, \"tsla\", \"TEXT_STRUCTURE_RA_TSLA\", new bool[2, 1] { { false }, { true } }, false, \"USSR\");\n        public static readonly BuildingType FakeWeapon = new BuildingType(32, \"weap\", \"TEXT_STRUCTURE_RA_WEAF\", new bool[2, 3] { { true, true, true }, { true, true, true } }, true, \"Greece\", true, false, \"weap2\");\n        public static readonly BuildingType FakeConst = new BuildingType(33, \"fact\", \"TEXT_STRUCTURE_RA_FACF\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, true, \"Greece\", true);\n        public static readonly BuildingType FakeShipYard = new BuildingType(34, \"syrd\", \"TEXT_STRUCTURE_RA_SYRF\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, false, \"Greece\", true);\n        public static readonly BuildingType FakeSubPen = new BuildingType(35, \"spen\", \"TEXT_STRUCTURE_RA_SPEF\", new bool[3, 3] { { true, true, true }, { true, true, true }, { true, true, true } }, false, \"USSR\", true);\n        public static readonly BuildingType FakeCommand = new BuildingType(36, \"dome\", \"TEXT_STRUCTURE_RA_DOMF\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Greece\", true);\n        public static readonly BuildingType AVMine = new BuildingType(43, \"minv\", \"TEXT_STRUCTURE_RA_MINV\", new bool[1, 1] { { true } }, false, \"Greece\");\n        public static readonly BuildingType APMine = new BuildingType(44, \"minp\", \"TEXT_STRUCTURE_RA_MINP\", new bool[1, 1] { { true } }, false, \"Greece\");\n        public static readonly BuildingType V01 = new BuildingType(45, \"v01\", \"TEXT_STRUCTURE_TITLE_CIV1\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V02 = new BuildingType(46, \"v02\", \"TEXT_STRUCTURE_TITLE_CIV2\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V03 = new BuildingType(47, \"v03\", \"TEXT_STRUCTURE_TITLE_CIV3\", new bool[2, 2] { { false, true }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V04 = new BuildingType(48, \"v04\", \"TEXT_STRUCTURE_TITLE_CIV4\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V05 = new BuildingType(49, \"v05\", \"TEXT_STRUCTURE_TITLE_CIV5\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V06 = new BuildingType(50, \"v06\", \"TEXT_STRUCTURE_TITLE_CIV6\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V07 = new BuildingType(51, \"v07\", \"TEXT_STRUCTURE_TITLE_CIV7\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V08 = new BuildingType(52, \"v08\", \"TEXT_STRUCTURE_TITLE_CIV8\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V09 = new BuildingType(53, \"v09\", \"TEXT_STRUCTURE_TITLE_CIV9\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V10 = new BuildingType(54, \"v10\", \"TEXT_STRUCTURE_TITLE_CIV10\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V11 = new BuildingType(55, \"v11\", \"TEXT_STRUCTURE_TITLE_CIV11\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V12 = new BuildingType(56, \"v12\", \"TEXT_STRUCTURE_RA_CIVILIAN\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V13 = new BuildingType(57, \"v13\", \"TEXT_STRUCTURE_RA_CIVILIAN\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V14 = new BuildingType(58, \"v14\", \"TEXT_STRUCTURE_TITLE_CIV13\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V15 = new BuildingType(59, \"v15\", \"TEXT_STRUCTURE_TITLE_CIV14\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V16 = new BuildingType(60, \"v16\", \"TEXT_STRUCTURE_TITLE_CIV15\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V17 = new BuildingType(61, \"v17\", \"TEXT_STRUCTURE_TITLE_CIV16\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V18 = new BuildingType(62, \"v18\", \"TEXT_STRUCTURE_TITLE_CIV17\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType V19 = new BuildingType(63, \"v19\", \"TEXT_STRUCTURE_RA_CIVILIAN\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly BuildingType Barrel = new BuildingType(82, \"barl\", \"TEXT_STRUCTURE_RA_BARL\", new bool[1, 1] { { true } }, false, \"Neutral\");\n        public static readonly BuildingType Barrel3 = new BuildingType(83, \"brl3\", \"TEXT_STRUCTURE_RA_BRL3\", new bool[1, 1] { { true } }, false, \"Neutral\");\n        public static readonly BuildingType Queen = new BuildingType(84, \"quee\", \"TEXT_STRUCTURE_RA_QUEE\", new bool[1, 2] { { true, true } }, false, \"Special\");\n        public static readonly BuildingType Larva1 = new BuildingType(85, \"lar1\", \"TEXT_STRUCTURE_RA_LAR1\", new bool[1, 1] { { true } }, false, \"Special\");\n        public static readonly BuildingType Larva2 = new BuildingType(86, \"lar2\", \"TEXT_STRUCTURE_RA_LAR2\", new bool[1, 1] { { true } }, false, \"Special\");\n\n        private static readonly BuildingType[] Types;\n\n        static BuildingTypes()\n        {\n            Types =\n                (from field in typeof(BuildingTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(BuildingType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as BuildingType).ToArray();\n        }\n\n        public static IEnumerable<BuildingType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/Constants.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Drawing;\nusing System.IO;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class Constants\n    {\n        public static readonly string SaveDirectory = Path.Combine(Globals.RootSaveDirectory, \"Red_Alert\");\n\n        public static readonly Size MaxSize = new Size(128, 128);\n\n        public const int MaxAircraft = 100;\n        public const int MaxVessels = 100;\n        public const int MaxBuildings = 500;\n        public const int MaxInfantry = 500;\n        public const int MaxTerrain = 500;\n        public const int MaxUnits = 500;\n        public const int MaxTeams = 60;\n        public const int MaxTriggers = 200;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/DirectionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class DirectionTypes\n    {\n        public static readonly DirectionType North = new DirectionType(0, \"North\", FacingType.North);\n        public static readonly DirectionType NorthNorthEast = new DirectionType(16, \"North-NorthEast\");\n        public static readonly DirectionType NorthEast = new DirectionType(32, \"NorthEast\", FacingType.NorthEast);\n        public static readonly DirectionType EastNorthEast = new DirectionType(48, \"East-NorthEast\");\n        public static readonly DirectionType East = new DirectionType(64, \"East\", FacingType.East);\n        public static readonly DirectionType EastSouthEast = new DirectionType(80, \"East-SouthEast\");\n        public static readonly DirectionType SouthEast = new DirectionType(96, \"SouthEast\", FacingType.SouthEast);\n        public static readonly DirectionType SouthSouthEast = new DirectionType(112, \"South-SouthEast\");\n        public static readonly DirectionType South = new DirectionType(128, \"South\", FacingType.South);\n        public static readonly DirectionType SouthSouthWest = new DirectionType(144, \"South-SouthWest\");\n        public static readonly DirectionType SouthWest = new DirectionType(160, \"SouthWest\", FacingType.SouthWest);\n        public static readonly DirectionType WestSouthWest = new DirectionType(176, \"West-SouthWest\");\n        public static readonly DirectionType West = new DirectionType(192, \"West\", FacingType.West);\n        public static readonly DirectionType WestNorthWest = new DirectionType(208, \"West-NorthWest\");\n        public static readonly DirectionType NorthWest = new DirectionType(224, \"NorthWest\", FacingType.NorthWest);\n        public static readonly DirectionType NorthNorthWest = new DirectionType(240, \"North-NorthWest\");\n\n        private static DirectionType[] Types;\n\n        static DirectionTypes()\n        {\n            Types =\n                (from field in typeof(DirectionTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(DirectionType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as DirectionType).ToArray();\n        }\n\n        public static IEnumerable<DirectionType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/EventTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class EventTypes\n    {\n        public const string TEVENT_NONE = \"None\";\n        public const string TEVENT_PLAYER_ENTERED = \"Entered by...\";\n        public const string TEVENT_SPIED = \"Spied by...\";\n        public const string TEVENT_THIEVED = \"Thieved by...\";\n        public const string TEVENT_DISCOVERED = \"Discovered by player\";\n        public const string TEVENT_HOUSE_DISCOVERED = \"House Discovered...\";\n        public const string TEVENT_ATTACKED = \"Attacked by anybody\";\n        public const string TEVENT_DESTROYED = \"Destroyed by anybody\";\n        public const string TEVENT_ANY = \"Any Event\";\n        public const string TEVENT_UNITS_DESTROYED = \"Destroyed, Units, All...\";\n        public const string TEVENT_BUILDINGS_DESTROYED = \"Destroyed, Buildings, All...\";\n        public const string TEVENT_ALL_DESTROYED = \"Destroyed, All...\";\n        public const string TEVENT_CREDITS = \"Credits exceed (x100)...\";\n        public const string TEVENT_TIME = \"Elapsed Time (1/10th min)...\";\n        public const string TEVENT_MISSION_TIMER_EXPIRED = \"Mission Timer Expired\";\n        public const string TEVENT_NBUILDINGS_DESTROYED = \"Destroyed, Buildings, #...\";\n        public const string TEVENT_NUNITS_DESTROYED = \"# Destroyed, Units, #...\";\n        public const string TEVENT_NOFACTORIES = \"No Factories left\";\n        public const string TEVENT_EVAC_CIVILIAN = \"Civilians Evacuated\";\n        public const string TEVENT_BUILD = \"Build Building Type...\";\n        public const string TEVENT_BUILD_UNIT = \"Build Unit Type...\";\n        public const string TEVENT_BUILD_INFANTRY = \"Build Infantry Type...\";\n        public const string TEVENT_BUILD_AIRCRAFT = \"Build Aircraft Type...\";\n        public const string TEVENT_LEAVES_MAP = \"Leaves map (team)...\";\n        public const string TEVENT_ENTERS_ZONE = \"Zone Entry by...\";\n        public const string TEVENT_CROSS_HORIZONTAL = \"Crosses Horizontal Line...\";\n        public const string TEVENT_CROSS_VERTICAL = \"Crosses Vertical Line...\";\n        public const string TEVENT_GLOBAL_SET = \"Global is set...\";\n        public const string TEVENT_GLOBAL_CLEAR = \"Global is clear...\";\n        public const string TEVENT_FAKES_DESTROYED = \"Destroyed, Fakes, All...\";\n        public const string TEVENT_LOW_POWER = \"Low Power...\";\n        public const string TEVENT_ALL_BRIDGES_DESTROYED = \"All bridges destroyed\";\n        public const string TEVENT_BUILDING_EXISTS = \"Building exists...\";\n\n        private static readonly string[] Types;\n\n        static EventTypes()\n        {\n            Types =\n                (from field in typeof(EventTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsLiteral && !field.IsInitOnly && typeof(string).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as string).ToArray();\n        }\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/GamePlugin.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing Newtonsoft.Json;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.RedAlert\n{\n    class GamePlugin : IGamePlugin\n    {\n        private static readonly IEnumerable<string> movieTypes = new string[]\n        {\n            \"x\",\n            \"AAGUN\",\n            \"AFTRMATH\",\n            \"AIRFIELD\",\n            \"ALLIEND\",\n            \"ALLY1\",\n            \"ALLY10\",\n            \"ALLY10B\",\n            \"ALLY11\",\n            \"ALLY12\",\n            \"ALLY14\",\n            \"ALLY2\",\n            \"ALLY4\",\n            \"ALLY5\",\n            \"ALLY6\",\n            \"ALLY8\",\n            \"ALLY9\",\n            \"ALLYMORF\",\n            \"ANTEND\",\n            \"ANTINTRO\",\n            \"APCESCPE\",\n            \"ASSESS\",\n            \"AVERTED\",\n            \"BATTLE\",\n            \"BEACHEAD\",\n            \"BINOC\",\n            \"BMAP\",\n            \"BOMBRUN\",\n            \"BRDGTILT\",\n            \"COUNTDWN\",\n            \"CRONFAIL\",\n            \"CRONTEST\",\n            \"DESTROYR\",\n            \"DOUBLE\",\n            \"DPTHCHRG\",\n            \"DUD\",\n            \"ELEVATOR\",\n            \"ENGLISH\",\n            \"EXECUTE\",\n            \"FLARE\",\n            \"FROZEN\",\n            \"GRVESTNE\",\n            \"LANDING\",\n            \"MASASSLT\",\n            \"MCV\",\n            \"MCVBRDGE\",\n            \"MCV_LAND\",\n            \"MIG\",\n            \"MONTPASS\",\n            \"MOVINGIN\",\n            \"MTNKFACT\",\n            \"NUKESTOK\",\n            \"OILDRUM\",\n            \"ONTHPRWL\",\n            \"OVERRUN\",\n            \"PERISCOP\",\n            \"PROLOG\",\n            \"RADRRAID\",\n            \"REDINTRO\",\n            \"RETALIATION_ALLIED1\",\n            \"RETALIATION_ALLIED10\",\n            \"RETALIATION_ALLIED2\",\n            \"RETALIATION_ALLIED3\",\n            \"RETALIATION_ALLIED4\",\n            \"RETALIATION_ALLIED5\",\n            \"RETALIATION_ALLIED6\",\n            \"RETALIATION_ALLIED7\",\n            \"RETALIATION_ALLIED8\",\n            \"RETALIATION_ALLIED9\",\n            \"RETALIATION_ANTS\",\n            \"RETALIATION_SOVIET1\",\n            \"RETALIATION_SOVIET10\",\n            \"RETALIATION_SOVIET2\",\n            \"RETALIATION_SOVIET3\",\n            \"RETALIATION_SOVIET4\",\n            \"RETALIATION_SOVIET5\",\n            \"RETALIATION_SOVIET6\",\n            \"RETALIATION_SOVIET7\",\n            \"RETALIATION_SOVIET8\",\n            \"RETALIATION_SOVIET9\",\n            \"RETALIATION_WINA\",\n            \"RETALIATION_WINS\",\n            \"SEARCH\",\n            \"SFROZEN\",\n            \"SHIPSINK\",\n            \"SHIPYARD\", // MISSING\n            \"SHORBOM1\",\n            \"SHORBOM2\",\n            \"SHORBOMB\",\n            \"SITDUCK\",\n            \"SIZZLE\",   //MISSING\n            \"SIZZLE2\",  //MISSING\n            \"SLNTSRVC\",\n            \"SNOWBASE\",\n            \"SNOWBOMB\",\n            \"SNSTRAFE\",\n            \"SOVBATL\",\n            \"SOVCEMET\",\n            \"SOVFINAL\",\n            \"SOVIET1\",\n            \"SOVIET10\",\n            \"SOVIET11\",\n            \"SOVIET12\",\n            \"SOVIET13\",\n            \"SOVIET14\",\n            \"SOVIET2\",\n            \"SOVIET3\",\n            \"SOVIET4\",\n            \"SOVIET5\",\n            \"SOVIET6\",\n            \"SOVIET7\",\n            \"SOVIET8\",\n            \"SOVIET9\",\n            \"SOVMCV\",\n            \"SOVTSTAR\",\n            \"SPOTTER\",\n            \"SPY\",\n            \"STRAFE\",\n            \"TAKE_OFF\",\n            \"TANYA1\",\n            \"TANYA2\",\n            \"TESLA\",\n            \"TOOFAR\",\n            \"TRINITY\",\n            \"V2ROCKET\",\n        };\n\n        private static readonly IEnumerable<ITechnoType> technoTypes;\n\n        public GameType GameType => GameType.RedAlert;\n\n        public Map Map { get; }\n\n        public Image MapImage { get; private set; }\n\n        public bool Dirty { get; set; }\n\n        private INISectionCollection extraSections;\n\n        static GamePlugin()\n        {\n            technoTypes = InfantryTypes.GetTypes().Cast<ITechnoType>().Concat(UnitTypes.GetTypes().Cast<ITechnoType>());\n        }\n\n        public GamePlugin(bool mapImage)\n        {\n            var playerWaypoints = Enumerable.Range(0, 8).Select(i => new Waypoint(string.Format(\"P{0}\", i), WaypointFlag.PlayerStart));\n            var generalWaypoints = Enumerable.Range(8, 90).Select(i => new Waypoint(i.ToString()));\n            var specialWaypoints = new Waypoint[] { new Waypoint(\"Home\"), new Waypoint(\"Reinf.\"), new Waypoint(\"Special\") };\n            var waypoints = playerWaypoints.Concat(generalWaypoints).Concat(specialWaypoints);\n\n            var basicSection = new BasicSection();\n            basicSection.SetDefault();\n\n            var houseTypes = HouseTypes.GetTypes();\n            basicSection.Player = houseTypes.First().Name;\n\n            Map = new Map(basicSection, null, Constants.MaxSize, typeof(House),\n                houseTypes, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(), TerrainTypes.GetTypes(),\n                OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(), EventTypes.GetTypes(), ActionTypes.GetTypes(),\n                MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(),\n                BuildingTypes.GetTypes(), TeamMissionTypes.GetTypes(), waypoints, movieTypes)\n            {\n                TiberiumOrGoldValue = 35,\n                GemValue = 110\n            };\n\n            Map.BasicSection.PropertyChanged += BasicSection_PropertyChanged;\n            Map.MapSection.PropertyChanged += MapSection_PropertyChanged;\n\n            if (mapImage)\n            {\n                MapImage = new Bitmap(Map.Metrics.Width * Globals.TileWidth, Map.Metrics.Height * Globals.TileHeight);\n            }\n        }\n\n        public GamePlugin()\n            : this(true)\n        {\n        }\n\n        public void New(string theater)\n        {\n            Map.Theater = Map.TheaterTypes.Where(t => t.Equals(theater)).FirstOrDefault() ?? TheaterTypes.Temperate;\n            Map.TopLeft = new Point(1, 1);\n            Map.Size = Map.Metrics.Size - new Size(2, 2);\n\n            UpdateBasePlayerHouse();\n\n            Dirty = true;\n        }\n\n        public IEnumerable<string> Load(string path, FileType fileType)\n        {\n            var errors = new List<string>();\n\n            switch (fileType)\n            {\n                case FileType.INI:\n                case FileType.BIN:\n                    {\n                        var ini = new INI();\n                        using (var reader = new StreamReader(path))\n                        {\n                            ini.Parse(reader);\n                        }\n                        errors.AddRange(LoadINI(ini));\n                    }\n                    break;\n                case FileType.MEG:\n                case FileType.PGM:\n                    {\n                        using (var megafile = new Megafile(path))\n                        {\n                            var mprFile = megafile.Where(p => Path.GetExtension(p).ToLower() == \".mpr\").FirstOrDefault();\n                            if (mprFile != null)\n                            {\n                                var ini = new INI();\n                                using (var reader = new StreamReader(megafile.Open(mprFile)))\n                                {\n                                    ini.Parse(reader);\n                                }\n                                errors.AddRange(LoadINI(ini));\n                            }\n                        }\n                    }\n                    break;\n                default:\n                    throw new NotSupportedException();\n            }\n\n            return errors;\n        }\n\n        private IEnumerable<string> LoadINI(INI ini)\n        {\n            var errors = new List<string>();\n\n            Map.BeginUpdate();\n\n            var basicSection = ini.Sections.Extract(\"Basic\");\n            if (basicSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, true), basicSection, Map.BasicSection);\n            }\n\n            Map.BasicSection.Player = Map.HouseTypes.Where(t => t.Equals(Map.BasicSection.Player)).FirstOrDefault()?.Name ?? Map.HouseTypes.First().Name;\n            Map.BasicSection.BasePlayer = HouseTypes.GetBasePlayer(Map.BasicSection.Player);\n\n            var mapSection = ini.Sections.Extract(\"Map\");\n            if (mapSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, true), mapSection, Map.MapSection);\n            }\n\n            var steamSection = ini.Sections.Extract(\"Steam\");\n            if (steamSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, true), steamSection, Map.SteamSection);\n            }\n\n            string indexToType(IList<string> list, string index)\n            {\n                return (int.TryParse(index, out int result) && (result >= 0) && (result < list.Count)) ? list[result] : list.First();\n            }\n\n            var teamTypesSection = ini.Sections.Extract(\"TeamTypes\");\n            if (teamTypesSection != null)\n            {\n                foreach (var (Key, Value) in teamTypesSection)\n                {\n                    try\n                    {\n                        var teamType = new TeamType { Name = Key };\n\n                        var tokens = Value.Split(',').ToList();\n                        teamType.House = Map.HouseTypes.Where(t => t.Equals(sbyte.Parse(tokens[0]))).FirstOrDefault(); tokens.RemoveAt(0);\n\n                        var flags = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.IsRoundAbout = (flags & 0x01) != 0;\n                        teamType.IsSuicide = (flags & 0x02) != 0;\n                        teamType.IsAutocreate = (flags & 0x04) != 0;\n                        teamType.IsPrebuilt = (flags & 0x08) != 0;\n                        teamType.IsReinforcable = (flags & 0x10) != 0;\n\n                        teamType.RecruitPriority = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.InitNum = byte.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.MaxAllowed = byte.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.Origin = int.Parse(tokens[0]) + 1; tokens.RemoveAt(0);\n                        teamType.Trigger = tokens[0]; tokens.RemoveAt(0);\n\n                        var numClasses = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        for (int i = 0; i < Math.Min(Globals.MaxTeamClasses, numClasses); ++i)\n                        {\n                            var classTokens = tokens[0].Split(':'); tokens.RemoveAt(0);\n                            if (classTokens.Length == 2)\n                            {\n                                var type = technoTypes.Where(t => t.Equals(classTokens[0])).FirstOrDefault();\n                                var count = byte.Parse(classTokens[1]);\n                                if (type != null)\n                                {\n                                    teamType.Classes.Add(new TeamTypeClass { Type = type, Count = count });\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Team '{0}' references unknown class '{1}'\", Key, classTokens[0]));\n                                }\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Team '{0}' has wrong number of tokens for class index {1} (expecting 2)\", Key, i));\n                            }\n                        }\n\n                        var numMissions = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        for (int i = 0; i < Math.Min(Globals.MaxTeamMissions, numMissions); ++i)\n                        {\n                            var missionTokens = tokens[0].Split(':'); tokens.RemoveAt(0);\n                            if (missionTokens.Length == 2)\n                            {\n                                teamType.Missions.Add(new TeamTypeMission { Mission = indexToType(Map.TeamMissionTypes, missionTokens[0]), Argument = int.Parse(missionTokens[1]) });\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Team '{0}' has wrong number of tokens for mission index {1} (expecting 2)\", Key, i));\n                            }\n                        }\n\n                        Map.TeamTypes.Add(teamType);\n                    }\n                    catch (ArgumentOutOfRangeException) { }\n                }\n            }\n\n            var triggersSection = ini.Sections.Extract(\"Trigs\");\n            if (triggersSection != null)\n            {\n                foreach (var (Key, Value) in triggersSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 18)\n                    {\n                        var trigger = new Trigger { Name = Key };\n\n                        trigger.PersistantType = (TriggerPersistantType)int.Parse(tokens[0]);\n                        trigger.House = Map.HouseTypes.Where(t => t.Equals(sbyte.Parse(tokens[1]))).FirstOrDefault()?.Name ?? \"None\";\n                        trigger.EventControl = (TriggerMultiStyleType)int.Parse(tokens[2]);\n\n                        trigger.Event1.EventType = indexToType(Map.EventTypes, tokens[4]);\n                        trigger.Event1.Team = tokens[5];\n                        trigger.Event1.Data = long.Parse(tokens[6]);\n\n                        trigger.Event2.EventType = indexToType(Map.EventTypes, tokens[7]);\n                        trigger.Event2.Team = tokens[8];\n                        trigger.Event2.Data = long.Parse(tokens[9]);\n\n                        trigger.Action1.ActionType = indexToType(Map.ActionTypes, tokens[10]);\n                        trigger.Action1.Team = tokens[11];\n                        trigger.Action1.Trigger = tokens[12];\n                        trigger.Action1.Data = long.Parse(tokens[13]);\n\n                        trigger.Action2.ActionType = indexToType(Map.ActionTypes, tokens[14]);\n                        trigger.Action2.Team = tokens[15];\n                        trigger.Action2.Trigger = tokens[16];\n                        trigger.Action2.Data = long.Parse(tokens[17]);\n\n                        // Fix up data caused by union usage in the legacy game\n                        Action<TriggerEvent> fixEvent = (TriggerEvent e) =>\n                        {\n                            switch (e.EventType)\n                            {\n                                case EventTypes.TEVENT_THIEVED:\n                                case EventTypes.TEVENT_PLAYER_ENTERED:\n                                case EventTypes.TEVENT_CROSS_HORIZONTAL:\n                                case EventTypes.TEVENT_CROSS_VERTICAL:\n                                case EventTypes.TEVENT_ENTERS_ZONE:\n                                case EventTypes.TEVENT_HOUSE_DISCOVERED:\n                                case EventTypes.TEVENT_BUILDINGS_DESTROYED:\n                                case EventTypes.TEVENT_UNITS_DESTROYED:\n                                case EventTypes.TEVENT_ALL_DESTROYED:\n                                case EventTypes.TEVENT_LOW_POWER:\n                                case EventTypes.TEVENT_BUILDING_EXISTS:\n                                case EventTypes.TEVENT_BUILD:\n                                case EventTypes.TEVENT_BUILD_UNIT:\n                                case EventTypes.TEVENT_BUILD_INFANTRY:\n                                case EventTypes.TEVENT_BUILD_AIRCRAFT:\n                                    e.Data &= 0xFF;\n                                    break;\n                                default:\n                                    break;\n                            }\n                        };\n\n                        Action<TriggerAction> fixAction = (TriggerAction a) =>\n                        {\n                            switch (a.ActionType)\n                            {\n                                case ActionTypes.TACTION_1_SPECIAL:\n                                case ActionTypes.TACTION_FULL_SPECIAL:\n                                case ActionTypes.TACTION_FIRE_SALE:\n                                case ActionTypes.TACTION_WIN:\n                                case ActionTypes.TACTION_LOSE:\n                                case ActionTypes.TACTION_ALL_HUNT:\n                                case ActionTypes.TACTION_BEGIN_PRODUCTION:\n                                case ActionTypes.TACTION_AUTOCREATE:\n                                case ActionTypes.TACTION_BASE_BUILDING:\n                                case ActionTypes.TACTION_CREATE_TEAM:\n                                case ActionTypes.TACTION_DESTROY_TEAM:\n                                case ActionTypes.TACTION_REINFORCEMENTS:\n                                case ActionTypes.TACTION_FORCE_TRIGGER:\n                                case ActionTypes.TACTION_DESTROY_TRIGGER:\n                                case ActionTypes.TACTION_DZ:\n                                case ActionTypes.TACTION_REVEAL_SOME:\n                                case ActionTypes.TACTION_REVEAL_ZONE:\n                                case ActionTypes.TACTION_PLAY_MUSIC:\n                                case ActionTypes.TACTION_PLAY_MOVIE:\n                                case ActionTypes.TACTION_PLAY_SOUND:\n                                case ActionTypes.TACTION_PLAY_SPEECH:\n                                case ActionTypes.TACTION_PREFERRED_TARGET:\n                                    a.Data &= 0xFF;\n                                    break;\n                                case ActionTypes.TACTION_TEXT_TRIGGER:\n                                    a.Data = Math.Max(1, Math.Min(209, a.Data));\n                                    break;\n                                default:\n                                    break;\n                            }\n                        };\n\n                        fixEvent(trigger.Event1);\n                        fixEvent(trigger.Event2);\n\n                        fixAction(trigger.Action1);\n                        fixAction(trigger.Action2);\n\n                        Map.Triggers.Add(trigger);\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Trigger '{0}' has too few tokens (expecting 18)\", Key));\n                    }\n                }\n            }\n\n            var mapPackSection = ini.Sections.Extract(\"MapPack\");\n            if (mapPackSection != null)\n            {\n                Map.Templates.Clear();\n\n                var data = DecompressLCWSection(mapPackSection, 3);\n                using (var reader = new BinaryReader(new MemoryStream(data)))\n                {\n                    for (var y = 0; y < Map.Metrics.Height; ++y)\n                    {\n                        for (var x = 0; x < Map.Metrics.Width; ++x)\n                        {\n                            var typeValue = reader.ReadUInt16();\n                            var templateType = Map.TemplateTypes.Where(t => t.Equals(typeValue)).FirstOrDefault();\n                            if ((templateType != null) && !templateType.Theaters.Contains(Map.Theater))\n                            {\n                                templateType = null;\n                            }\n                            Map.Templates[x, y] = (templateType != null) ? new Template { Type = templateType } : null;\n                        }\n                    }\n\n                    for (var y = 0; y < Map.Metrics.Height; ++y)\n                    {\n                        for (var x = 0; x < Map.Metrics.Width; ++x)\n                        {\n                            var iconValue = reader.ReadByte();\n                            var template = Map.Templates[x, y];\n                            if (template != null)\n                            {\n                                if ((template.Type != TemplateTypes.Clear) && (iconValue >= template.Type.NumIcons))\n                                {\n                                    Map.Templates[x, y] = null;\n                                }\n                                else\n                                {\n                                    template.Icon = iconValue;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            var terrainSection = ini.Sections.Extract(\"Terrain\");\n            if (terrainSection != null)\n            {\n                foreach (var (Key, Value) in terrainSection)\n                {\n                    var cell = int.Parse(Key);\n                    var name = Value.Split(',')[0];\n                    var terrainType = Map.TerrainTypes.Where(t => t.Equals(name)).FirstOrDefault();\n                    if (terrainType != null)\n                    {\n                        if (!Map.Technos.Add(cell, new Terrain\n                        {\n                            Type = terrainType,\n                            Icon = terrainType.IsTransformable ? 22 : 0,\n                            Trigger = Trigger.None\n                        }))\n                        {\n                            var techno = Map.Technos[cell];\n                            if (techno is Building building)\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps structure '{1}' in cell {2}, skipping\", name, building.Type.Name, cell));\n                            }\n                            else if (techno is Overlay overlay)\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps overlay '{1}' in cell {2}, skipping\", name, overlay.Type.Name, cell));\n                            }\n                            else if (techno is Terrain terrain)\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps terrain '{1}' in cell {2}, skipping\", name, terrain.Type.Name, cell));\n                            }\n                            else if (techno is InfantryGroup infantry)\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps infantry in cell {1}, skipping\", name, cell));\n                            }\n                            else if (techno is Unit unit)\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps unit '{1}' in cell {2}, skipping\", name, unit.Type.Name, cell));\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Terrain '{0}' overlaps unknown techno in cell {1}, skipping\", name, cell));\n                            }\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Terrain '{0}' references unknown terrain\", name));\n                    }\n                }\n            }\n\n            var overlayPackSection = ini.Sections.Extract(\"OverlayPack\");\n            if (overlayPackSection != null)\n            {\n                Map.Overlay.Clear();\n\n                var data = DecompressLCWSection(overlayPackSection, 1);\n                using (var reader = new BinaryReader(new MemoryStream(data)))\n                {\n                    for (var i = 0; i < Map.Metrics.Length; ++i)\n                    {\n                        var overlayId = reader.ReadSByte();\n                        if (overlayId >= 0)\n                        {\n                            var overlayType = Map.OverlayTypes.Where(t => t.Equals(overlayId)).FirstOrDefault();\n                            if (overlayType != null)\n                            {\n                                Map.Overlay[i] = new Overlay { Type = overlayType, Icon = 0 };\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Overlay ID {0} references unknown overlay\", overlayId));\n                            }\n                        }\n                    }\n                }\n            }\n\n            var smudgeSection = ini.Sections.Extract(\"Smudge\");\n            if (smudgeSection != null)\n            {\n                foreach (var (Key, Value) in smudgeSection)\n                {\n                    var cell = int.Parse(Key);\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 3)\n                    {\n                        var smudgeType = Map.SmudgeTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();\n                        if (smudgeType != null)\n                        {\n                            if ((smudgeType.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None)\n                            {\n                                Map.Smudge[cell] = new Smudge\n                                {\n                                    Type = smudgeType,\n                                    Icon = 0,\n                                    Data = int.Parse(tokens[2])\n                                };\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Smudge '{0}' is a bib, skipped\", tokens[0]));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Smudge '{0}' references unknown smudge\", tokens[0]));\n                        }\n                    }\n                }\n            }\n\n            var unitsSection = ini.Sections.Extract(\"Units\");\n            if (unitsSection != null)\n            {\n                foreach (var (_, Value) in unitsSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 7)\n                    {\n                        var unitType = Map.UnitTypes.Where(t => t.IsUnit && t.Equals(tokens[1])).FirstOrDefault();\n                        if (unitType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Technos.Add(cell, new Unit()\n                            {\n                                Type = unitType,\n                                House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                Strength = int.Parse(tokens[2]),\n                                Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                Mission = tokens[5],\n                                Trigger = tokens[6]\n                            }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Unit '{0}' references unknown unit\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Unit '{0}' has wrong number of tokens (expecting 7)\", tokens[1]));\n                    }\n                }\n            }\n\n            var aircraftSections = ini.Sections.Extract(\"Aircraft\");\n            if (aircraftSections != null)\n            {\n                foreach (var (_, Value) in aircraftSections)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 6)\n                    {\n                        var aircraftType = Map.UnitTypes.Where(t => t.IsAircraft && t.Equals(tokens[1])).FirstOrDefault();\n                        if (aircraftType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Technos.Add(cell, new Unit()\n                                {\n                                    Type = aircraftType,\n                                    House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                    Strength = int.Parse(tokens[2]),\n                                    Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                    Mission = tokens[5]\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Aircraft '{0}' references unknown aircraft\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Aircraft '{0}' has wrong number of tokens (expecting 6)\", tokens[1]));\n                    }\n                }\n            }\n\n            var shipsSection = ini.Sections.Extract(\"Ships\");\n            if (shipsSection != null)\n            {\n                foreach (var (_, Value) in shipsSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 7)\n                    {\n                        var vesselType = Map.UnitTypes.Where(t => t.IsVessel && t.Equals(tokens[1])).FirstOrDefault();\n                        if (vesselType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Technos.Add(cell, new Unit()\n                                {\n                                    Type = vesselType,\n                                    House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                    Strength = int.Parse(tokens[2]),\n                                    Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                    Mission = Map.MissionTypes.Where(t => t.Equals(tokens[5])).FirstOrDefault(),\n                                    Trigger = tokens[6]\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Ship '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Ship '{0}' references unknown ship\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Ship '{0}' has wrong number of tokens (expecting 7)\", tokens[1]));\n                    }\n                }\n            }\n\n            var infantrySections = ini.Sections.Extract(\"Infantry\");\n            if (infantrySections != null)\n            {\n                foreach (var (_, Value) in infantrySections)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 8)\n                    {\n                        var infantryType = Map.InfantryTypes.Where(t => t.Equals(tokens[1])).FirstOrDefault();\n                        if (infantryType != null)\n                        {\n                            var cell = int.Parse(tokens[3]);\n                            var infantryGroup = Map.Technos[cell] as InfantryGroup;\n                            if ((infantryGroup == null) && (Map.Technos[cell] == null))\n                            {\n                                infantryGroup = new InfantryGroup();\n                                Map.Technos.Add(cell, infantryGroup);\n                            }\n\n                            if (infantryGroup != null)\n                            {\n                                var stoppingPos = int.Parse(tokens[4]);\n                                if (stoppingPos < Globals.NumInfantryStops)\n                                {\n                                    var direction = (byte)((int.Parse(tokens[6]) + 0x08) & ~0x0F);\n\n                                    if (infantryGroup.Infantry[stoppingPos] == null)\n                                    {\n                                        infantryGroup.Infantry[stoppingPos] = new Infantry(infantryGroup)\n                                        {\n                                            Type = infantryType,\n                                            House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                            Strength = int.Parse(tokens[2]),\n                                            Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                            Mission = Map.MissionTypes.Where(t => t.Equals(tokens[5])).FirstOrDefault(),\n                                            Trigger = tokens[7]\n                                        };\n                                    }\n                                    else\n                                    {\n                                        errors.Add(string.Format(\"Infantry '{0}' overlaps another infantry at position {1} in cell {2}, skipping\", tokens[1], stoppingPos, cell));\n                                    }\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' has invalid position {1} in cell {2}, skipping\", tokens[1], stoppingPos, cell));\n                                }\n                            }\n                            else\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Infantry '{0}' references unknown infantry\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Infantry '{0}' has wrong number of tokens (expecting 8)\", tokens[1]));\n                    }\n                }\n            }\n\n            var structuresSection = ini.Sections.Extract(\"Structures\");\n            if (structuresSection != null)\n            {\n                foreach (var (_, Value) in structuresSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length >= 6)\n                    {\n                        var buildingType = Map.BuildingTypes.Where(t => t.Equals(tokens[1])).FirstOrDefault();\n                        if (buildingType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n                            bool sellable = (tokens.Length >= 7) ? (int.Parse(tokens[6]) != 0) : false;\n                            bool rebuild = (tokens.Length >= 8) ? (int.Parse(tokens[7]) != 0) : false;\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Buildings.Add(cell, new Building()\n                                {\n                                    Type = buildingType,\n                                    House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                    Strength = int.Parse(tokens[2]),\n                                    Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                    Trigger = tokens[5],\n                                    Sellable = sellable,\n                                    Rebuild = rebuild\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Structure '{0}' references unknown structure\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Structure '{0}' has wrong number of tokens (expecting 6)\", tokens[1]));\n                    }\n                }\n            }\n\n            var baseSection = ini.Sections.Extract(\"Base\");\n            if (baseSection != null)\n            {\n                foreach (var (Key, Value) in baseSection)\n                {\n                    if (Key.Equals(\"Player\", StringComparison.OrdinalIgnoreCase))\n                    {\n                        Map.BasicSection.BasePlayer = Map.HouseTypes.Where(t => t.Equals(Value)).FirstOrDefault()?.Name ?? Map.HouseTypes.First().Name;\n                    }\n                    else if (int.TryParse(Key, out int priority))\n                    {\n                        var tokens = Value.Split(',');\n                        if (tokens.Length == 2)\n                        {\n                            var buildingType = Map.BuildingTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();\n                            if (buildingType != null)\n                            {\n                                var cell = int.Parse(tokens[1]);\n                                Map.Metrics.GetLocation(cell, out Point location);\n                                if (Map.Buildings.OfType<Building>().Where(x => x.Location == location).FirstOrDefault().Occupier is Building building)\n                                {\n                                    building.BasePriority = priority;\n                                }\n                                else\n                                {\n                                    Map.Buildings.Add(cell, new Building()\n                                    {\n                                        Type = buildingType,\n                                        Strength = 256,\n                                        Direction = DirectionTypes.North,\n                                        BasePriority = priority,\n                                        IsPrebuilt = false\n                                    });\n                                }\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Base priority {0} references unknown structure '{1}'\", priority, tokens[0]));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Base priority {0} has wrong number of tokens (expecting 2)\", priority));\n                        }\n                    }\n                    else if (!Key.Equals(\"Count\", StringComparison.CurrentCultureIgnoreCase))\n                    {\n                        errors.Add(string.Format(\"Invalid base priority '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            var waypointsSection = ini.Sections.Extract(\"Waypoints\");\n            if (waypointsSection != null)\n            {\n                foreach (var (Key, Value) in waypointsSection)\n                {\n                    if (int.TryParse(Key, out int waypoint))\n                    {\n                        if (int.TryParse(Value, out int cell))\n                        {\n                            if ((waypoint >= 0) && (waypoint < Map.Waypoints.Length))\n                            {\n                                if (Map.Metrics.Contains(cell))\n                                {\n                                    Map.Waypoints[waypoint].Cell = cell;\n                                }\n                                else\n                                {\n                                    Map.Waypoints[waypoint].Cell = null;\n                                    if (cell != -1)\n                                    {\n                                        errors.Add(string.Format(\"Waypoint {0} cell value {1} out of range (expecting between {2} and {3})\", waypoint, cell, 0, Map.Metrics.Length - 1));\n                                    }\n                                }\n                            }\n                            else if (cell != -1)\n                            {\n                                errors.Add(string.Format(\"Waypoint {0} out of range (expecting between {1} and {2})\", waypoint, 0, Map.Waypoints.Length - 1));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Waypoint {0} has invalid cell '{1}' (expecting integer)\", waypoint, Value));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Invalid waypoint '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            var cellTriggersSection = ini.Sections.Extract(\"CellTriggers\");\n            if (cellTriggersSection != null)\n            {\n                foreach (var (Key, Value) in cellTriggersSection)\n                {\n                    if (int.TryParse(Key, out int cell))\n                    {\n                        if (Map.Metrics.Contains(cell))\n                        {\n                            Map.CellTriggers[cell] = new CellTrigger\n                            {\n                                Trigger = Value\n                            };\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Cell trigger {0} outside map bounds\", cell));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Invalid cell trigger '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            var briefingSection = ini.Sections.Extract(\"Briefing\");\n            if (briefingSection != null)\n            {\n                if (briefingSection.Keys.Contains(\"Text\"))\n                {\n                    Map.BriefingSection.Briefing = briefingSection[\"Text\"].Replace(\"@\", Environment.NewLine);\n                }\n                else\n                {\n                    Map.BriefingSection.Briefing = string.Join(\" \", briefingSection.Keys.Select(k => k.Value)).Replace(\"@\", Environment.NewLine);\n                }\n            }\n\n            foreach (var house in Map.Houses)\n            {\n                if (house.Type.ID < 0)\n                {\n                    continue;\n                }\n\n                var houseSection = ini.Sections.Extract(house.Type.Name);\n                if (houseSection != null)\n                {\n                    INI.ParseSection(new MapContext(Map, true), houseSection, house);\n                    house.Enabled = true;\n                }\n                else\n                {\n                    house.Enabled = false;\n                }\n            }\n\n            string indexToName<T>(IList<T> list, string index, string defaultValue) where T : INamedType\n            {\n                return (int.TryParse(index, out int result) && (result >= 0) && (result < list.Count)) ? list[result].Name : defaultValue;\n            }\n\n            foreach (var teamType in Map.TeamTypes)\n            {\n                teamType.Trigger = indexToName(Map.Triggers, teamType.Trigger, Trigger.None);\n            }\n\n            foreach (var trigger in Map.Triggers)\n            {\n                trigger.Event1.Team = indexToName(Map.TeamTypes, trigger.Event1.Team, TeamType.None);\n                trigger.Event2.Team = indexToName(Map.TeamTypes, trigger.Event2.Team, TeamType.None);\n                trigger.Action1.Team = indexToName(Map.TeamTypes, trigger.Action1.Team, TeamType.None);\n                trigger.Action1.Trigger = indexToName(Map.Triggers, trigger.Action1.Trigger, Trigger.None);\n                trigger.Action2.Team = indexToName(Map.TeamTypes, trigger.Action2.Team, TeamType.None);\n                trigger.Action2.Trigger = indexToName(Map.Triggers, trigger.Action2.Trigger, Trigger.None);\n            }\n\n            UpdateBasePlayerHouse();\n\n            extraSections = ini.Sections;\n\n            Map.EndUpdate();\n\n            return errors;\n        }\n\n        public bool Save(string path, FileType fileType)\n        {\n            if (!Validate())\n            {\n                return false;\n            }\n\n            switch (fileType)\n            {\n                case FileType.INI:\n                case FileType.BIN:\n                    {\n                        var mprPath = Path.ChangeExtension(path, \".mpr\");\n                        var tgaPath = Path.ChangeExtension(path, \".tga\");\n                        var jsonPath = Path.ChangeExtension(path, \".json\");\n\n                        var ini = new INI();\n                        using (var mprWriter = new StreamWriter(mprPath))\n                        using (var tgaStream = new FileStream(tgaPath, FileMode.Create))\n                        using (var jsonStream = new FileStream(jsonPath, FileMode.Create))\n                        using (var jsonWriter = new JsonTextWriter(new StreamWriter(jsonStream)))\n                        {\n                            SaveINI(ini, fileType);\n                            mprWriter.Write(ini.ToString());\n                            SaveMapPreview(tgaStream);\n                            SaveJSON(jsonWriter);\n                        }\n                    }\n                    break;\n                case FileType.MEG:\n                case FileType.PGM:\n                    {\n                        using (var iniStream = new MemoryStream())\n                        using (var tgaStream = new MemoryStream())\n                        using (var jsonStream = new MemoryStream())\n                        using (var jsonWriter = new JsonTextWriter(new StreamWriter(jsonStream)))\n                        using (var megafileBuilder = new MegafileBuilder(@\"\", path))\n                        {\n                            var ini = new INI();\n                            SaveINI(ini, fileType);\n                            var iniWriter = new StreamWriter(iniStream);\n                            iniWriter.Write(ini.ToString());\n                            iniWriter.Flush();\n                            iniStream.Position = 0;\n\n                            SaveMapPreview(tgaStream);\n                            tgaStream.Position = 0;\n\n                            SaveJSON(jsonWriter);\n                            jsonWriter.Flush();\n                            jsonStream.Position = 0;\n\n                            var mprFile = Path.ChangeExtension(Path.GetFileName(path), \".mpr\").ToUpper();\n                            var tgaFile = Path.ChangeExtension(Path.GetFileName(path), \".tga\").ToUpper();\n                            var jsonFile = Path.ChangeExtension(Path.GetFileName(path), \".json\").ToUpper();\n\n                            megafileBuilder.AddFile(mprFile, iniStream);\n                            megafileBuilder.AddFile(tgaFile, tgaStream);\n                            megafileBuilder.AddFile(jsonFile, jsonStream);\n                            megafileBuilder.Write();\n                        }\n                    }\n                    break;\n                default:\n                    throw new NotSupportedException();\n            }\n\n            return true;\n        }\n\n        private void SaveINI(INI ini, FileType fileType)\n        {\n            if (extraSections != null)\n            {\n                ini.Sections.AddRange(extraSections);\n            }\n\n            INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Basic\"), Map.BasicSection);\n            INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Map\"), Map.MapSection);\n\n            if (fileType != FileType.PGM)\n            {\n                INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Steam\"), Map.SteamSection);\n            }\n\n            ini[\"Basic\"][\"NewINIFormat\"] = \"3\";\n\n            var smudgeSection = ini.Sections.Add(\"SMUDGE\");\n            foreach (var (cell, smudge) in Map.Smudge.Where(item => (item.Value.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))\n            {\n                smudgeSection[cell.ToString()] = string.Format(\"{0},{1},{2}\", smudge.Type.Name.ToUpper(), cell, smudge.Data);\n            }\n\n            var terrainSection = ini.Sections.Add(\"TERRAIN\");\n            foreach (var (location, terrain) in Map.Technos.OfType<Terrain>())\n            {\n                Map.Metrics.GetCell(location, out int cell);\n                terrainSection[cell.ToString()] = terrain.Type.Name.ToUpper();\n            }\n\n            var cellTriggersSection = ini.Sections.Add(\"CellTriggers\");\n            foreach (var (cell, cellTrigger) in Map.CellTriggers)\n            {\n                cellTriggersSection[cell.ToString()] = cellTrigger.Trigger;\n            }\n\n            int nameToIndex<T>(IList<T> list, string name)\n            {\n                var index = list.TakeWhile(x => !x.Equals(name)).Count();\n                return (index < list.Count) ? index : -1;\n            }\n\n            string nameToIndexString<T>(IList<T> list, string name) => nameToIndex(list, name).ToString();\n\n            var teamTypesSection = ini.Sections.Add(\"TeamTypes\");\n            foreach (var teamType in Map.TeamTypes)\n            {\n                var classes = teamType.Classes\n                    .Select(c => string.Format(\"{0}:{1}\", c.Type.Name.ToUpper(), c.Count))\n                    .ToArray();\n                var missions = teamType.Missions\n                    .Select(m => string.Format(\"{0}:{1}\", nameToIndexString(Map.TeamMissionTypes, m.Mission), m.Argument))\n                    .ToArray();\n\n                int flags = 0;\n                if (teamType.IsRoundAbout) flags |= 0x01;\n                if (teamType.IsSuicide) flags |= 0x02;\n                if (teamType.IsAutocreate) flags |= 0x04;\n                if (teamType.IsPrebuilt) flags |= 0x08;\n                if (teamType.IsReinforcable) flags |= 0x10;\n\n                var tokens = new List<string>\n                {\n                    teamType.House.ID.ToString(),\n                    flags.ToString(),\n                    teamType.RecruitPriority.ToString(),\n                    teamType.InitNum.ToString(),\n                    teamType.MaxAllowed.ToString(),\n                    (teamType.Origin - 1).ToString(),\n                    nameToIndexString(Map.Triggers, teamType.Trigger),\n                    classes.Length.ToString(),\n                    string.Join(\",\", classes),\n                    missions.Length.ToString(),\n                    string.Join(\",\", missions)\n                };\n\n                teamTypesSection[teamType.Name] = string.Join(\",\", tokens.Where(t => !string.IsNullOrEmpty(t)));\n            }\n\n            var infantrySection = ini.Sections.Add(\"INFANTRY\");\n            var infantryIndex = 0;\n            foreach (var (location, infantryGroup) in Map.Technos.OfType<InfantryGroup>())\n            {\n                for (var i = 0; i < infantryGroup.Infantry.Length; ++i)\n                {\n                    var infantry = infantryGroup.Infantry[i];\n                    if (infantry == null)\n                    {\n                        continue;\n                    }\n\n                    var key = infantryIndex.ToString(\"D3\");\n                    infantryIndex++;\n\n                    Map.Metrics.GetCell(location, out int cell);\n                    infantrySection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6},{7}\",\n                        infantry.House.Name,\n                        infantry.Type.Name,\n                        infantry.Strength,\n                        cell,\n                        i,\n                        infantry.Mission,\n                        infantry.Direction.ID,\n                        infantry.Trigger\n                    );\n                }\n            }\n\n            var structuresSection = ini.Sections.Add(\"STRUCTURES\");\n            var structureIndex = 0;\n            foreach (var (location, building) in Map.Buildings.OfType<Building>().Where(x => x.Occupier.IsPrebuilt))\n            {\n                var key = structureIndex.ToString(\"D3\");\n                structureIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                structuresSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6},{7}\",\n                    building.House.Name,\n                    building.Type.Name,\n                    building.Strength,\n                    cell,\n                    building.Direction.ID,\n                    building.Trigger,\n                    building.Sellable ? 1 : 0,\n                    building.Rebuild ? 1 : 0\n                );\n            }\n\n            var baseSection = ini.Sections.Add(\"Base\");\n            var baseBuildings = Map.Buildings.OfType<Building>().Where(x => x.Occupier.BasePriority >= 0).OrderBy(x => x.Occupier.BasePriority).ToArray();\n            baseSection[\"Player\"] = Map.BasicSection.BasePlayer;\n            baseSection[\"Count\"] = baseBuildings.Length.ToString();\n            var baseIndex = 0;\n            foreach (var (location, building) in baseBuildings)\n            {\n                var key = baseIndex.ToString(\"D3\");\n                baseIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                baseSection[key] = string.Format(\"{0},{1}\",\n                    building.Type.Name.ToUpper(),\n                    cell\n                );\n            }\n\n            var unitsSection = ini.Sections.Add(\"UNITS\");\n            var unitIndex = 0;\n            foreach (var (location, unit) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsUnit))\n            {\n                var key = unitIndex.ToString(\"D3\");\n                unitIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                unitsSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6}\",\n                    unit.House.Name,\n                    unit.Type.Name,\n                    unit.Strength,\n                    cell,\n                    unit.Direction.ID,\n                    unit.Mission,\n                    unit.Trigger\n                );\n            }\n\n            var aircraftSection = ini.Sections.Add(\"AIRCRAFT\");\n            var aircraftIndex = 0;\n            foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))\n            {\n                var key = aircraftIndex.ToString(\"D3\");\n                aircraftIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                aircraftSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5}\",\n                    aircraft.House.Name,\n                    aircraft.Type.Name,\n                    aircraft.Strength,\n                    cell,\n                    aircraft.Direction.ID,\n                    aircraft.Mission\n                );\n            }\n\n            var shipsSection = ini.Sections.Add(\"SHIPS\");\n            var shipsIndex = 0;\n            foreach (var (location, ship) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsVessel))\n            {\n                var key = shipsIndex.ToString(\"D3\");\n                shipsIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                shipsSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6}\",\n                    ship.House.Name,\n                    ship.Type.Name,\n                    ship.Strength,\n                    cell,\n                    ship.Direction.ID,\n                    ship.Mission,\n                    ship.Trigger\n                );\n            }\n\n            var triggersSection = ini.Sections.Add(\"Trigs\");\n            foreach (var trigger in Map.Triggers)\n            {\n                if (string.IsNullOrEmpty(trigger.Name))\n                {\n                    continue;\n                }\n\n                var action2TypeIndex = nameToIndex(Map.ActionTypes, trigger.Action2.ActionType);\n                var actionControl = (action2TypeIndex > 0) ? TriggerMultiStyleType.And : TriggerMultiStyleType.Only;\n\n                var tokens = new List<string>\n                {\n                    ((int)trigger.PersistantType).ToString(),\n                    !string.IsNullOrEmpty(trigger.House) ? (Map.HouseTypes.Where(h => h.Equals(trigger.House)).FirstOrDefault()?.ID.ToString() ?? \"-1\") : \"-1\",\n                    ((int)trigger.EventControl).ToString(),\n                    ((int)actionControl).ToString(),\n                    nameToIndexString(Map.EventTypes, trigger.Event1.EventType),\n                    nameToIndexString(Map.TeamTypes, trigger.Event1.Team),\n                    trigger.Event1.Data.ToString(),\n                    nameToIndexString(Map.EventTypes, trigger.Event2.EventType),\n                    nameToIndexString(Map.TeamTypes, trigger.Event2.Team),\n                    trigger.Event2.Data.ToString(),\n                    nameToIndexString(Map.ActionTypes, trigger.Action1.ActionType),\n                    nameToIndexString(Map.TeamTypes, trigger.Action1.Team),\n                    nameToIndexString(Map.Triggers, trigger.Action1.Trigger),\n                    trigger.Action1.Data.ToString(),\n                    action2TypeIndex.ToString(),\n                    nameToIndexString(Map.TeamTypes, trigger.Action2.Team),\n                    nameToIndexString(Map.Triggers, trigger.Action2.Trigger),\n                    trigger.Action2.Data.ToString()\n                };\n\n                triggersSection[trigger.Name] = string.Join(\",\", tokens);\n            }\n\n            var waypointsSection = ini.Sections.Add(\"Waypoints\");\n            for (var i = 0; i < Map.Waypoints.Length; ++i)\n            {\n                var waypoint = Map.Waypoints[i];\n                if (waypoint.Cell.HasValue)\n                {\n                    waypointsSection[i.ToString()] = waypoint.Cell.Value.ToString();\n                }\n            }\n\n            foreach (var house in Map.Houses)\n            {\n                if ((house.Type.ID < 0) || !house.Enabled)\n                {\n                    continue;\n                }\n\n                INI.WriteSection(new MapContext(Map, true), ini.Sections.Add(house.Type.Name), house);\n            }\n\n            ini.Sections.Remove(\"Briefing\");\n            if (!string.IsNullOrEmpty(Map.BriefingSection.Briefing))\n            {\n                var briefingSection = ini.Sections.Add(\"Briefing\");\n                briefingSection[\"Text\"] = Map.BriefingSection.Briefing.Replace(Environment.NewLine, \"@\");\n            }\n\n            using (var stream = new MemoryStream())\n            {\n                using (var writer = new BinaryWriter(stream))\n                {\n                    for (var y = 0; y < Map.Metrics.Height; ++y)\n                    {\n                        for (var x = 0; x < Map.Metrics.Width; ++x)\n                        {\n                            var template = Map.Templates[x, y];\n                            if (template != null)\n                            {\n                                writer.Write(template.Type.ID);\n                            }\n                            else\n                            {\n                                writer.Write(ushort.MaxValue);\n                            }\n                        }\n                    }\n\n                    for (var y = 0; y < Map.Metrics.Height; ++y)\n                    {\n                        for (var x = 0; x < Map.Metrics.Width; ++x)\n                        {\n                            var template = Map.Templates[x, y];\n                            if (template != null)\n                            {\n                                writer.Write((byte)template.Icon);\n                            }\n                            else\n                            {\n                                writer.Write(byte.MaxValue);\n                            }\n                        }\n                    }\n                }\n\n                ini.Sections.Remove(\"MapPack\");\n                CompressLCWSection(ini.Sections.Add(\"MapPack\"), stream.ToArray());\n            }\n\n            using (var stream = new MemoryStream())\n            {\n                using (var writer = new BinaryWriter(stream))\n                {\n                    for (var i = 0; i < Map.Metrics.Length; ++i)\n                    {\n                        var overlay = Map.Overlay[i];\n                        if (overlay != null)\n                        {\n                            writer.Write(overlay.Type.ID);\n                        }\n                        else\n                        {\n                            writer.Write((sbyte)-1);\n                        }\n                    }\n                }\n\n                ini.Sections.Remove(\"OverlayPack\");\n                CompressLCWSection(ini.Sections.Add(\"OverlayPack\"), stream.ToArray());\n            }\n        }\n\n        private void SaveMapPreview(Stream stream)\n        {\n            Map.GenerateMapPreview().Save(stream);\n        }\n\n        private void SaveJSON(JsonTextWriter writer)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"MapTileX\");\n            writer.WriteValue(Map.MapSection.X);\n            writer.WritePropertyName(\"MapTileY\");\n            writer.WriteValue(Map.MapSection.Y);\n            writer.WritePropertyName(\"MapTileWidth\");\n            writer.WriteValue(Map.MapSection.Width);\n            writer.WritePropertyName(\"MapTileHeight\");\n            writer.WriteValue(Map.MapSection.Height);\n            writer.WritePropertyName(\"Theater\");\n            writer.WriteValue(Map.MapSection.Theater.Name.ToUpper());\n            writer.WritePropertyName(\"Waypoints\");\n            writer.WriteStartArray();\n            foreach (var waypoint in Map.Waypoints.Where(w => (w.Flag == WaypointFlag.PlayerStart) && w.Cell.HasValue))\n            {\n                writer.WriteValue(waypoint.Cell.Value);\n            }\n            writer.WriteEndArray();\n            writer.WriteEndObject();\n        }\n\n        private bool Validate()\n        {\n            StringBuilder sb = new StringBuilder(\"Error(s) during map validation:\");\n\n            bool ok = true;\n            int numAircraft = Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft).Count();\n            int numBuildings = Map.Buildings.OfType<Building>().Where(x => x.Occupier.IsPrebuilt).Count();\n            int numInfantry = Map.Technos.OfType<InfantryGroup>().Sum(item => item.Occupier.Infantry.Count(i => i != null));\n            int numTerrain = Map.Technos.OfType<Terrain>().Count();\n            int numUnits = Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsUnit).Count();\n            int numVessels = Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsVessel).Count();\n            int numWaypoints = Map.Waypoints.Count(w => w.Cell.HasValue);\n\n            if (numAircraft > Constants.MaxAircraft)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of aircraft exceeded ({0} > {1})\", numAircraft, Constants.MaxAircraft));\n                ok = false;\n            }\n\n            if (numBuildings > Constants.MaxBuildings)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of structures exceeded ({0} > {1})\", numBuildings, Constants.MaxBuildings));\n                ok = false;\n            }\n\n            if (numInfantry > Constants.MaxInfantry)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of infantry exceeded ({0} > {1})\", numInfantry, Constants.MaxInfantry));\n                ok = false;\n            }\n\n            if (numTerrain > Constants.MaxTerrain)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of terrain objects exceeded ({0} > {1})\", numTerrain, Constants.MaxTerrain));\n                ok = false;\n            }\n\n            if (numUnits > Constants.MaxUnits)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of units exceeded ({0} > {1})\", numUnits, Constants.MaxUnits));\n                ok = false;\n            }\n\n            if (numVessels > Constants.MaxVessels)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of ships exceeded ({0} > {1})\", numVessels, Constants.MaxVessels));\n                ok = false;\n            }\n\n            if (Map.TeamTypes.Count > Constants.MaxTeams)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of team types exceeded ({0} > {1})\", Map.TeamTypes.Count, Constants.MaxTeams));\n                ok = false;\n            }\n\n            if (Map.Triggers.Count > Constants.MaxTriggers)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of triggers exceeded ({0} > {1})\", Map.Triggers.Count, Constants.MaxTriggers));\n                ok = false;\n            }\n\n            if (!Map.BasicSection.SoloMission && (numWaypoints < 2))\n            {\n                sb.Append(Environment.NewLine + \"Skirmish/Multiplayer maps need at least 2 waypoints for player starting locations.\");\n                ok = false;\n            }\n\n            var homeWaypoint = Map.Waypoints.Where(w => w.Equals(\"Home\")).FirstOrDefault();\n            if (Map.BasicSection.SoloMission && !homeWaypoint.Cell.HasValue)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Single-player maps need the Home waypoint to be placed.\", Map.Triggers.Count, Constants.MaxTriggers));\n                ok = false;\n            }\n\n            if (!ok)\n            {\n                MessageBox.Show(sb.ToString(), \"Validation Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n\n            return ok;\n        }\n\n        private void BasicSection_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"BasePlayer\":\n                    {\n                        UpdateBasePlayerHouse();\n                    }\n                    break;\n            }\n        }\n\n        private void MapSection_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"Theater\":\n                    {\n                        Map.InitTheater(GameType);\n                    }\n                    break;\n            }\n        }\n\n        private void UpdateBasePlayerHouse()\n        {\n            var basePlayer = Map.HouseTypes.Where(h => h.Equals(Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Map.HouseTypes.First();\n            foreach (var (_, building) in Map.Buildings.OfType<Building>())\n            {\n                if (!building.IsPrebuilt)\n                {\n                    building.House = basePlayer;\n                }\n            }\n        }\n\n        private void CompressLCWSection(INISection section, byte[] decompressedBytes)\n        {\n            using (var stream = new MemoryStream())\n            using (var writer = new BinaryWriter(stream))\n            {\n                foreach (var decompressedChunk in decompressedBytes.Split(8192))\n                {\n                    var compressedChunk = WWCompression.LcwCompress(decompressedChunk);\n                    writer.Write((ushort)compressedChunk.Length);\n                    writer.Write((ushort)decompressedChunk.Length);\n                    writer.Write(compressedChunk);\n                }\n\n                writer.Flush();\n                stream.Position = 0;\n\n                var values = Convert.ToBase64String(stream.ToArray()).Split(70).ToArray();\n                for (var i = 0; i < values.Length; ++i)\n                {\n                    section[(i + 1).ToString()] = values[i];\n                }\n            }\n        }\n\n        private byte[] DecompressLCWSection(INISection section, int bytesPerCell)\n        {\n            var sb = new StringBuilder();\n            foreach (var (key, value) in section)\n            {\n                sb.Append(value);\n            }\n\n            var compressedBytes = Convert.FromBase64String(sb.ToString());\n            int readPtr = 0;\n            int writePtr = 0;\n            var decompressedBytes = new byte[Map.Metrics.Width * Map.Metrics.Height * bytesPerCell];\n\n            while ((readPtr + 4) <= compressedBytes.Length)\n            {\n                uint uLength;\n                using (var reader = new BinaryReader(new MemoryStream(compressedBytes, readPtr, 4)))\n                {\n                    uLength = reader.ReadUInt32();\n                }\n                var length = (int)(uLength & 0x0000FFFF);\n                readPtr += 4;\n                var dest = new byte[8192];\n                var readPtr2 = readPtr;\n                var decompressed = WWCompression.LcwDecompress(compressedBytes, ref readPtr2, dest, 0);\n                Array.Copy(dest, 0, decompressedBytes, writePtr, decompressed);\n                readPtr += length;\n                writePtr += decompressed;\n            }\n            return decompressedBytes;\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    MapImage?.Dispose();\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/House.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.ComponentModel;\n\nnamespace MobiusEditor.RedAlert\n{\n    public class House : Model.House\n    {\n        public House(Model.HouseType type)\n            : base(type)\n        {\n        }\n\n        [DefaultValue(150)]\n        public int MaxInfantry { get; set; }\n\n        [DefaultValue(150)]\n        public int MaxVessel { get; set; }\n\n        [DefaultValue(99)]\n        public int TechLevel { get; set; }\n\n        [DefaultValue(5)]\n        public int IQ { get; set; }\n\n        [DefaultValue(false)]\n        public bool PlayerControl { get; set; }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/HouseTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class HouseTypes\n    {\n        public static readonly HouseType Spain = new HouseType(0, \"Spain\", \"SPAIN\");\n        public static readonly HouseType Greece = new HouseType(1, \"Greece\", \"GREECE\");\n        public static readonly HouseType USSR = new HouseType(2, \"USSR\", \"USSR\");\n        public static readonly HouseType England = new HouseType(3, \"England\", \"ENGLAND\");\n        public static readonly HouseType Ukraine = new HouseType(4, \"Ukraine\", \"UKRAINE\");\n        public static readonly HouseType Germany = new HouseType(5, \"Germany\", \"GERMANY\");\n        public static readonly HouseType France = new HouseType(6, \"France\", \"FRANCE\");\n        public static readonly HouseType Turkey = new HouseType(7, \"Turkey\", \"TURKEY\");\n        public static readonly HouseType Good = new HouseType(8, \"GoodGuy\", \"GOOD\");\n        public static readonly HouseType Bad = new HouseType(9, \"BadGuy\", \"BAD\");\n        public static readonly HouseType Neutral = new HouseType(10, \"Neutral\");\n        public static readonly HouseType Special = new HouseType(11, \"Special\");\n        public static readonly HouseType Multi1 = new HouseType(12, \"Multi1\", \"MULTI1\");\n        public static readonly HouseType Multi2 = new HouseType(13, \"Multi2\", \"MULTI2\");\n        public static readonly HouseType Multi3 = new HouseType(14, \"Multi3\", \"MULTI3\");\n        public static readonly HouseType Multi4 = new HouseType(15, \"Multi4\", \"MULTI4\");\n        public static readonly HouseType Multi5 = new HouseType(16, \"Multi5\", \"MULTI5\");\n        public static readonly HouseType Multi6 = new HouseType(17, \"Multi6\", \"MULTI6\");\n        public static readonly HouseType Multi7 = new HouseType(18, \"Multi7\", \"MULTI7\");\n        public static readonly HouseType Multi8 = new HouseType(19, \"Multi8\", \"MULTI8\");\n\n        private static readonly HouseType[] Types;\n\n        static HouseTypes()\n        {\n            Types =\n                (from field in typeof(HouseTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(HouseType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as HouseType).ToArray();\n        }\n\n        public static IEnumerable<HouseType> GetTypes()\n        {\n            return Types;\n        }\n\n        public static string GetBasePlayer(string player)\n        {\n            return (USSR.Equals(player) || Ukraine.Equals(player) || Bad.Equals(player)) ? Good.Name : Bad.Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/InfantryTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class InfantryTypes\n    {\n        public static readonly InfantryType E1 = new InfantryType(0, \"e1\", \"TEXT_UNIT_RA_E1\", \"Greece\");\n        public static readonly InfantryType E2 = new InfantryType(1, \"e2\", \"TEXT_UNIT_RA_E2\", \"USSR\");\n        public static readonly InfantryType E3 = new InfantryType(2, \"e3\", \"TEXT_UNIT_RA_E3\", \"Greece\");\n        public static readonly InfantryType E4 = new InfantryType(3, \"e4\", \"TEXT_UNIT_RA_E4\", \"USSR\");\n        public static readonly InfantryType E6 = new InfantryType(4, \"e6\", \"TEXT_UNIT_RA_E6\", \"USSR\");\n        public static readonly InfantryType E7 = new InfantryType(5, \"e7\", \"TEXT_UNIT_RA_E7\", \"USSR\");\n        public static readonly InfantryType E8 = new InfantryType(6, \"spy\", \"TEXT_UNIT_RA_SPY\", \"Greece\");\n        public static readonly InfantryType E9 = new InfantryType(7, \"thf\", \"TEXT_UNIT_RA_THF\", \"Greece\");\n        public static readonly InfantryType Medic = new InfantryType(8, \"medi\", \"TEXT_UNIT_RA_MEDI\", \"Greece\");\n        public static readonly InfantryType General = new InfantryType(9, \"gnrl\", \"TEXT_UNIT_RA_GNRL\", \"Greece\");\n        public static readonly InfantryType Dog = new InfantryType(10, \"dog\", \"TEXT_UNIT_RA_DOG\", \"USSR\");\n        public static readonly InfantryType C1 = new InfantryType(11, \"c1\", \"TEXT_UNIT_TITLE_CIV1\", \"Neutral\");\n        public static readonly InfantryType C2 = new InfantryType(12, \"c2\", \"TEXT_UNIT_TITLE_CIV2\", \"Neutral\");\n        public static readonly InfantryType C3 = new InfantryType(13, \"c3\", \"TEXT_UNIT_TITLE_CIV3\", \"Neutral\");\n        public static readonly InfantryType C4 = new InfantryType(14, \"c4\", \"TEXT_UNIT_TITLE_CIV4\", \"Neutral\");\n        public static readonly InfantryType C5 = new InfantryType(15, \"c5\", \"TEXT_UNIT_TITLE_CIV5\", \"Neutral\");\n        public static readonly InfantryType C6 = new InfantryType(16, \"c6\", \"TEXT_UNIT_TITLE_CIV6\", \"Neutral\");\n        public static readonly InfantryType C7 = new InfantryType(17, \"c7\", \"TEXT_UNIT_TITLE_CIV7\", \"Neutral\");\n        public static readonly InfantryType C8 = new InfantryType(18, \"c8\", \"TEXT_UNIT_TITLE_CIV8\", \"Neutral\");\n        public static readonly InfantryType C9 = new InfantryType(19, \"c9\", \"TEXT_UNIT_TITLE_CIV9\", \"Neutral\");\n        public static readonly InfantryType C10 = new InfantryType(20, \"c10\", \"TEXT_UNIT_RA_SCIENTIST\", \"Neutral\");\n        public static readonly InfantryType Einstein = new InfantryType(21, \"einstein\", \"TEXT_UNIT_RA_EINSTEIN\", \"Neutral\");\n        public static readonly InfantryType Delphi = new InfantryType(22, \"delphi\", \"TEXT_UNIT_RA_DELPHI\", \"Neutral\");\n        public static readonly InfantryType DrChan = new InfantryType(23, \"chan\", \"TEXT_UNIT_TITLE_CHAN\", \"Neutral\");\n        public static readonly InfantryType ShockTrooper = new InfantryType(24, \"shok\", \"TEXT_UNIT_RA_SHOK\", \"USSR\");\n        public static readonly InfantryType Mechanic = new InfantryType(25, \"mech\", \"TEXT_UNIT_RA_MECH\", \"Greece\");\n\n        private static readonly InfantryType[] Types;\n\n        static InfantryTypes()\n        {\n            Types =\n                (from field in typeof(InfantryTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(InfantryType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as InfantryType).ToArray();\n        }\n\n        public static IEnumerable<InfantryType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/MissionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class MissionTypes\n    {\n        private static readonly string[] Types = new string[]\n        {\n            \"Sleep\",\n            \"Attack\",\n            \"Move\",\n            \"QMove\",\n            \"Retreat\",\n            \"Guard\",\n            \"Sticky\",\n            \"Enter\",\n            \"Capture\",\n            \"Harvest\",\n            \"Area Guard\",\n            \"Return\",\n            \"Stop\",\n            \"Ambush\",\n            \"Hunt\",\n            \"Unload\",\n            \"Sabotage\",\n            \"Construction\",\n            \"Selling\",\n            \"Repair\",\n            \"Rescue\",\n            \"Missile\",\n            \"Harmless\"\n        };\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/OverlayTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class OverlayTypes\n    {\n        public static readonly OverlayType Sandbag = new OverlayType(0, \"sbag\", \"TEXT_STRUCTURE_RA_SBAG\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Cyclone = new OverlayType(1, \"cycl\", \"TEXT_STRUCTURE_RA_CYCL\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Brick = new OverlayType(2, \"brik\", \"TEXT_STRUCTURE_RA_BRIK\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Barbwire = new OverlayType(3, \"barb\", \"TEXT_STRUCTURE_RA_BARB\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Wood = new OverlayType(4, \"wood\", \"TEXT_STRUCTURE_TD_WOOD\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Gold1 = new OverlayType(5, \"gold01\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Gold2 = new OverlayType(6, \"gold02\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Gold3 = new OverlayType(7, \"gold03\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Gold4 = new OverlayType(8, \"gold04\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Gems1 = new OverlayType(9, \"gem01\", OverlayTypeFlag.Gems);\n        public static readonly OverlayType Gems2 = new OverlayType(10, \"gem02\", OverlayTypeFlag.Gems);\n        public static readonly OverlayType Gems3 = new OverlayType(11, \"gem03\", OverlayTypeFlag.Gems);\n        public static readonly OverlayType Gems4 = new OverlayType(12, \"gem04\", OverlayTypeFlag.Gems);\n        public static readonly OverlayType V12 = new OverlayType(13, \"v12\", \"TEXT_STRUCTURE_RA_CIVILIAN\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V13 = new OverlayType(14, \"v13\", \"TEXT_STRUCTURE_RA_CIVILIAN\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V14 = new OverlayType(15, \"v14\", \"TEXT_STRUCTURE_TITLE_CIV13\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V15 = new OverlayType(16, \"v15\", \"TEXT_STRUCTURE_TITLE_CIV14\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V16 = new OverlayType(17, \"v16\", \"TEXT_STRUCTURE_TITLE_CIV15\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V17 = new OverlayType(18, \"v17\", \"TEXT_STRUCTURE_TITLE_CIV16\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType V18 = new OverlayType(19, \"v18\", \"TEXT_STRUCTURE_TITLE_CIV17\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly OverlayType FlagSpot = new OverlayType(20, \"fpls\", OverlayTypeFlag.Flag);\n        public static readonly OverlayType WoodCrate = new OverlayType(21, \"wcrate\", OverlayTypeFlag.Crate);\n        public static readonly OverlayType SteelCrate = new OverlayType(22, \"scrate\", OverlayTypeFlag.Crate);\n        public static readonly OverlayType Fence = new OverlayType(23, \"fenc\", \"TEXT_STRUCTURE_RA_FENC\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType WaterCrate = new OverlayType(24, \"wwcrate\", OverlayTypeFlag.Crate);\n\n        private static OverlayType[] Types;\n\n        static OverlayTypes()\n        {\n            Types =\n                (from field in typeof(OverlayTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(OverlayType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as OverlayType).ToArray();\n        }\n\n        public static IEnumerable<OverlayType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/SmudgeTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class SmudgeTypes\n    {\n        public static readonly SmudgeType Crater1 = new SmudgeType(0, \"cr1\");\n        public static readonly SmudgeType Crater2 = new SmudgeType(1, \"cr2\");\n        public static readonly SmudgeType Crater3 = new SmudgeType(2, \"cr3\");\n        public static readonly SmudgeType Crater4 = new SmudgeType(3, \"cr4\");\n        public static readonly SmudgeType Crater5 = new SmudgeType(4, \"cr5\");\n        public static readonly SmudgeType Crater6 = new SmudgeType(5, \"cr6\");\n        public static readonly SmudgeType Scorch1 = new SmudgeType(6, \"sc1\");\n        public static readonly SmudgeType Scorch2 = new SmudgeType(7, \"sc2\");\n        public static readonly SmudgeType Scorch3 = new SmudgeType(8, \"sc3\");\n        public static readonly SmudgeType Scorch4 = new SmudgeType(9, \"sc4\");\n        public static readonly SmudgeType Scorch5 = new SmudgeType(10, \"sc5\");\n        public static readonly SmudgeType Scorch6 = new SmudgeType(11, \"sc6\");\n        public static readonly SmudgeType Bib1 = new SmudgeType(12, \"bib1\", new Size(4, 2), SmudgeTypeFlag.Bib1);\n        public static readonly SmudgeType Bib2 = new SmudgeType(13, \"bib2\", new Size(3, 2), SmudgeTypeFlag.Bib2);\n        public static readonly SmudgeType Bib3 = new SmudgeType(14, \"bib3\", new Size(2, 2), SmudgeTypeFlag.Bib3);\n\n        private static SmudgeType[] Types;\n\n        static SmudgeTypes()\n        {\n            Types =\n                (from field in typeof(SmudgeTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(SmudgeType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as SmudgeType).ToArray();\n        }\n\n        public static IEnumerable<SmudgeType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/TeamMissionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class TeamMissionTypes\n    {\n        private static readonly string[] Types = new string[]\n        {\n            \"Attack...\",\n            \"Attack Waypoint...\",\n            \"Change Formation to...\",\n            \"Move to waypoint...\",\n            \"Move to Cell...\",\n            \"Guard area (1/10th min)...\",\n            \"Jump to line #...\",\n            \"Attack Tarcom\",\n            \"Unload\",\n            \"Deploy\",\n            \"Follow friendlies\",\n            \"Do this...\",\n            \"Set global...\",\n            \"Invulnerable\",\n            \"Load onto Transport\",\n            \"Spy on bldg @ waypt...\",\n            \"Patrol to waypoint...\"\n        };\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/TemplateTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class TemplateTypes\n    {\n        public static readonly TemplateType Clear = new TemplateType(0, \"clear1\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow, TheaterTypes.Interior }, TemplateTypeFlag.Clear);\n        public static readonly TemplateType Water = new TemplateType(1, \"w1\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, TemplateTypeFlag.Water);\n        public static readonly TemplateType Water2 = new TemplateType(2, \"w2\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, TemplateTypeFlag.Water);\n        public static readonly TemplateType Shore01 = new TemplateType(3, \"sh01\", 4, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore02 = new TemplateType(4, \"sh02\", 5, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore03 = new TemplateType(5, \"sh03\", 3, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore04 = new TemplateType(6, \"sh04\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore05 = new TemplateType(7, \"sh05\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore06 = new TemplateType(8, \"sh06\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore07 = new TemplateType(9, \"sh07\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore08 = new TemplateType(10, \"sh08\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore09 = new TemplateType(11, \"sh09\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore10 = new TemplateType(12, \"sh10\", 5, 6, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore11 = new TemplateType(13, \"sh11\", 4, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore12 = new TemplateType(14, \"sh12\", 3, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore13 = new TemplateType(15, \"sh13\", 6, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore14 = new TemplateType(16, \"sh14\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore15 = new TemplateType(17, \"sh15\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore16 = new TemplateType(18, \"sh16\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore17 = new TemplateType(19, \"sh17\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore18 = new TemplateType(20, \"sh18\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore19 = new TemplateType(21, \"sh19\", 4, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore20 = new TemplateType(22, \"sh20\", 5, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore21 = new TemplateType(23, \"sh21\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore22 = new TemplateType(24, \"sh22\", 6, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore23 = new TemplateType(25, \"sh23\", 5, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore24 = new TemplateType(26, \"sh24\", 3, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore25 = new TemplateType(27, \"sh25\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore26 = new TemplateType(28, \"sh26\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore27 = new TemplateType(29, \"sh27\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore28 = new TemplateType(30, \"sh28\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore29 = new TemplateType(31, \"sh29\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore30 = new TemplateType(32, \"sh30\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore31 = new TemplateType(33, \"sh31\", 6, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore32 = new TemplateType(34, \"sh32\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore33 = new TemplateType(35, \"sh33\", 3, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore34 = new TemplateType(36, \"sh34\", 6, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore35 = new TemplateType(37, \"sh35\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore36 = new TemplateType(38, \"sh36\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore37 = new TemplateType(39, \"sh37\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore38 = new TemplateType(40, \"sh38\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore39 = new TemplateType(41, \"sh39\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore40 = new TemplateType(42, \"sh40\", 5, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore41 = new TemplateType(43, \"sh41\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore42 = new TemplateType(44, \"sh42\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore43 = new TemplateType(45, \"sh43\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore44 = new TemplateType(46, \"sh44\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore45 = new TemplateType(47, \"sh45\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore46 = new TemplateType(48, \"sh46\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore47 = new TemplateType(49, \"sh47\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore48 = new TemplateType(50, \"sh48\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore49 = new TemplateType(51, \"sh49\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore50 = new TemplateType(52, \"sh50\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore51 = new TemplateType(53, \"sh51\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore52 = new TemplateType(54, \"sh52\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore53 = new TemplateType(55, \"sh53\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore54 = new TemplateType(56, \"sh54\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore55 = new TemplateType(57, \"sh55\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Shore56 = new TemplateType(58, \"sh56\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff01 = new TemplateType(59, \"wc01\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff02 = new TemplateType(60, \"wc02\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff03 = new TemplateType(61, \"wc03\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff04 = new TemplateType(62, \"wc04\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff05 = new TemplateType(63, \"wc05\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff06 = new TemplateType(64, \"wc06\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff07 = new TemplateType(65, \"wc07\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff08 = new TemplateType(66, \"wc08\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff09 = new TemplateType(67, \"wc09\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff10 = new TemplateType(68, \"wc10\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff11 = new TemplateType(69, \"wc11\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff12 = new TemplateType(70, \"wc12\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff13 = new TemplateType(71, \"wc13\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff14 = new TemplateType(72, \"wc14\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff15 = new TemplateType(73, \"wc15\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff16 = new TemplateType(74, \"wc16\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff17 = new TemplateType(75, \"wc17\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff18 = new TemplateType(76, \"wc18\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff19 = new TemplateType(77, \"wc19\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff20 = new TemplateType(78, \"wc20\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff21 = new TemplateType(79, \"wc21\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff22 = new TemplateType(80, \"wc22\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff23 = new TemplateType(81, \"wc23\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff24 = new TemplateType(82, \"wc24\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff25 = new TemplateType(83, \"wc25\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff26 = new TemplateType(84, \"wc26\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff27 = new TemplateType(85, \"wc27\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff28 = new TemplateType(86, \"wc28\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff29 = new TemplateType(87, \"wc29\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff30 = new TemplateType(88, \"wc30\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff31 = new TemplateType(89, \"wc31\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff32 = new TemplateType(90, \"wc32\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff33 = new TemplateType(91, \"wc33\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff34 = new TemplateType(92, \"wc34\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff35 = new TemplateType(93, \"wc35\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff36 = new TemplateType(94, \"wc36\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff37 = new TemplateType(95, \"wc37\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ShoreCliff38 = new TemplateType(96, \"wc38\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Boulder1 = new TemplateType(97, \"b1\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Boulder2 = new TemplateType(98, \"b2\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Boulder3 = new TemplateType(99, \"b3\", 3, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        //public static readonly TemplateType Boulder4 = new TemplateType(100, \"b4\", 0, 0, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        //public static readonly TemplateType Boulder5 = new TemplateType(101, \"b5\", 0, 0, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        //public static readonly TemplateType Boulder6 = new TemplateType(102, \"b6\", 0, 0, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch01 = new TemplateType(103, \"p01\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch02 = new TemplateType(104, \"p02\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch03 = new TemplateType(105, \"p03\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch04 = new TemplateType(106, \"p04\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch07 = new TemplateType(107, \"p07\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch08 = new TemplateType(108, \"p08\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch13 = new TemplateType(109, \"p13\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Patch14 = new TemplateType(110, \"p14\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        //public static readonly TemplateType Patch15 = new TemplateType(111, \"p15\", 0, 0, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River01 = new TemplateType(112, \"rv01\", 5, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River02 = new TemplateType(113, \"rv02\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River03 = new TemplateType(114, \"rv03\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River04 = new TemplateType(115, \"rv04\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River05 = new TemplateType(116, \"rv05\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River06 = new TemplateType(117, \"rv06\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River07 = new TemplateType(118, \"rv07\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River08 = new TemplateType(119, \"rv08\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River09 = new TemplateType(120, \"rv09\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River10 = new TemplateType(121, \"rv10\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River11 = new TemplateType(122, \"rv11\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River12 = new TemplateType(123, \"rv12\", 3, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River13 = new TemplateType(124, \"rv13\", 4, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Falls1 = new TemplateType(125, \"falls1\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Falls1a = new TemplateType(126, \"falls1a\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Falls2 = new TemplateType(127, \"falls2\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Falls2a = new TemplateType(128, \"falls2a\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Ford1 = new TemplateType(129, \"ford1\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Ford2 = new TemplateType(130, \"ford2\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1 = new TemplateType(131, \"bridge1\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1d = new TemplateType(132, \"bridge1d\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2 = new TemplateType(133, \"bridge2\", 5, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2d = new TemplateType(134, \"bridge2d\", 5, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope01 = new TemplateType(135, \"s01\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope02 = new TemplateType(136, \"s02\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope03 = new TemplateType(137, \"s03\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope04 = new TemplateType(138, \"s04\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope05 = new TemplateType(139, \"s05\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope06 = new TemplateType(140, \"s06\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope07 = new TemplateType(141, \"s07\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope08 = new TemplateType(142, \"s08\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope09 = new TemplateType(143, \"s09\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope10 = new TemplateType(144, \"s10\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope11 = new TemplateType(145, \"s11\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope12 = new TemplateType(146, \"s12\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope13 = new TemplateType(147, \"s13\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope14 = new TemplateType(148, \"s14\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope15 = new TemplateType(149, \"s15\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope16 = new TemplateType(150, \"s16\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope17 = new TemplateType(151, \"s17\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope18 = new TemplateType(152, \"s18\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope19 = new TemplateType(153, \"s19\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope20 = new TemplateType(154, \"s20\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope21 = new TemplateType(155, \"s21\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope22 = new TemplateType(156, \"s22\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope23 = new TemplateType(157, \"s23\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope24 = new TemplateType(158, \"s24\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope25 = new TemplateType(159, \"s25\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope26 = new TemplateType(160, \"s26\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope27 = new TemplateType(161, \"s27\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope28 = new TemplateType(162, \"s28\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope29 = new TemplateType(163, \"s29\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope30 = new TemplateType(164, \"s30\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope31 = new TemplateType(165, \"s31\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope32 = new TemplateType(166, \"s32\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope33 = new TemplateType(167, \"s33\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope34 = new TemplateType(168, \"s34\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope35 = new TemplateType(169, \"s35\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope36 = new TemplateType(170, \"s36\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope37 = new TemplateType(171, \"s37\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Slope38 = new TemplateType(172, \"s38\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road01 = new TemplateType(173, \"d01\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road02 = new TemplateType(174, \"d02\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road03 = new TemplateType(175, \"d03\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road04 = new TemplateType(176, \"d04\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road05 = new TemplateType(177, \"d05\", 3, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road06 = new TemplateType(178, \"d06\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road07 = new TemplateType(179, \"d07\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road08 = new TemplateType(180, \"d08\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road09 = new TemplateType(181, \"d09\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road10 = new TemplateType(182, \"d10\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road11 = new TemplateType(183, \"d11\", 2, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road12 = new TemplateType(184, \"d12\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road13 = new TemplateType(185, \"d13\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road14 = new TemplateType(186, \"d14\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road15 = new TemplateType(187, \"d15\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road16 = new TemplateType(188, \"d16\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road17 = new TemplateType(189, \"d17\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road18 = new TemplateType(190, \"d18\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road19 = new TemplateType(191, \"d19\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road20 = new TemplateType(192, \"d20\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road21 = new TemplateType(193, \"d21\", 3, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road22 = new TemplateType(194, \"d22\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road23 = new TemplateType(195, \"d23\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road24 = new TemplateType(196, \"d24\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road25 = new TemplateType(197, \"d25\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road26 = new TemplateType(198, \"d26\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road27 = new TemplateType(199, \"d27\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road28 = new TemplateType(200, \"d28\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road29 = new TemplateType(201, \"d29\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road30 = new TemplateType(202, \"d30\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road31 = new TemplateType(203, \"d31\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road32 = new TemplateType(204, \"d32\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road33 = new TemplateType(205, \"d33\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road34 = new TemplateType(206, \"d34\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road35 = new TemplateType(207, \"d35\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road36 = new TemplateType(208, \"d36\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road37 = new TemplateType(209, \"d37\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road38 = new TemplateType(210, \"d38\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road39 = new TemplateType(211, \"d39\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road40 = new TemplateType(212, \"d40\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road41 = new TemplateType(213, \"d41\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road42 = new TemplateType(214, \"d42\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road43 = new TemplateType(215, \"d43\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough01 = new TemplateType(216, \"rf01\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough02 = new TemplateType(217, \"rf02\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough03 = new TemplateType(218, \"rf03\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough04 = new TemplateType(219, \"rf04\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough05 = new TemplateType(220, \"rf05\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough06 = new TemplateType(221, \"rf06\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough07 = new TemplateType(222, \"rf07\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough08 = new TemplateType(223, \"rf08\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough09 = new TemplateType(224, \"rf09\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough10 = new TemplateType(225, \"rf10\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Rough11 = new TemplateType(226, \"rf11\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road44 = new TemplateType(227, \"d44\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Road45 = new TemplateType(228, \"d45\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River14 = new TemplateType(229, \"rv14\", 1, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType River15 = new TemplateType(230, \"rv15\", 2, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType RiverCliff01 = new TemplateType(231, \"rc01\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType RiverCliff02 = new TemplateType(232, \"rc02\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType RiverCliff03 = new TemplateType(233, \"rc03\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType RiverCliff04 = new TemplateType(234, \"rc04\", 2, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1a = new TemplateType(235, \"br1a\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1b = new TemplateType(236, \"br1b\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1c = new TemplateType(237, \"br1c\", 4, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2a = new TemplateType(238, \"br2a\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2b = new TemplateType(239, \"br2b\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2c = new TemplateType(240, \"br2c\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3a = new TemplateType(241, \"br3a\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3b = new TemplateType(242, \"br3b\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3c = new TemplateType(243, \"br3c\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3d = new TemplateType(244, \"br3d\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3e = new TemplateType(245, \"br3e\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge3f = new TemplateType(246, \"br3f\", 4, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F01 = new TemplateType(247, \"f01\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F02 = new TemplateType(248, \"f02\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F03 = new TemplateType(249, \"f03\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F04 = new TemplateType(250, \"f04\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F05 = new TemplateType(251, \"f05\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType F06 = new TemplateType(252, \"f06\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType ARRO0001 = new TemplateType(253, \"arro0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0002 = new TemplateType(254, \"arro0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0003 = new TemplateType(255, \"arro0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0004 = new TemplateType(256, \"arro0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0005 = new TemplateType(257, \"arro0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0006 = new TemplateType(258, \"arro0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0007 = new TemplateType(259, \"arro0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0008 = new TemplateType(260, \"arro0008\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0009 = new TemplateType(261, \"arro0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0010 = new TemplateType(262, \"arro0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0011 = new TemplateType(263, \"arro0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0012 = new TemplateType(264, \"arro0012\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0013 = new TemplateType(265, \"arro0013\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0014 = new TemplateType(266, \"arro0014\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType ARRO0015 = new TemplateType(267, \"arro0015\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0001 = new TemplateType(268, \"flor0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0002 = new TemplateType(269, \"flor0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0003 = new TemplateType(270, \"flor0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0004 = new TemplateType(271, \"flor0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0005 = new TemplateType(272, \"flor0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0006 = new TemplateType(273, \"flor0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType FLOR0007 = new TemplateType(274, \"flor0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GFLR0001 = new TemplateType(275, \"gflr0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GFLR0002 = new TemplateType(276, \"gflr0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GFLR0003 = new TemplateType(277, \"gflr0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GFLR0004 = new TemplateType(278, \"gflr0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GFLR0005 = new TemplateType(279, \"gflr0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0001 = new TemplateType(280, \"gstr0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0002 = new TemplateType(281, \"gstr0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0003 = new TemplateType(282, \"gstr0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0004 = new TemplateType(283, \"gstr0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0005 = new TemplateType(284, \"gstr0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0006 = new TemplateType(285, \"gstr0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0007 = new TemplateType(286, \"gstr0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0008 = new TemplateType(287, \"gstr0008\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0009 = new TemplateType(288, \"gstr0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0010 = new TemplateType(289, \"gstr0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType GSTR0011 = new TemplateType(290, \"gstr0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0001 = new TemplateType(291, \"lwal0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0002 = new TemplateType(292, \"lwal0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0003 = new TemplateType(293, \"lwal0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0004 = new TemplateType(294, \"lwal0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0005 = new TemplateType(295, \"lwal0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0006 = new TemplateType(296, \"lwal0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0007 = new TemplateType(297, \"lwal0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0008 = new TemplateType(298, \"lwal0008\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0009 = new TemplateType(299, \"lwal0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0010 = new TemplateType(300, \"lwal0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0011 = new TemplateType(301, \"lwal0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0012 = new TemplateType(302, \"lwal0012\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0013 = new TemplateType(303, \"lwal0013\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0014 = new TemplateType(304, \"lwal0014\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0015 = new TemplateType(305, \"lwal0015\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0016 = new TemplateType(306, \"lwal0016\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0017 = new TemplateType(307, \"lwal0017\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0018 = new TemplateType(308, \"lwal0018\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0019 = new TemplateType(309, \"lwal0019\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0020 = new TemplateType(310, \"lwal0020\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0021 = new TemplateType(311, \"lwal0021\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0022 = new TemplateType(312, \"lwal0022\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0023 = new TemplateType(313, \"lwal0023\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0024 = new TemplateType(314, \"lwal0024\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0025 = new TemplateType(315, \"lwal0025\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0026 = new TemplateType(316, \"lwal0026\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType LWAL0027 = new TemplateType(317, \"lwal0027\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0001 = new TemplateType(318, \"strp0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0002 = new TemplateType(319, \"strp0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0003 = new TemplateType(320, \"strp0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0004 = new TemplateType(321, \"strp0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0005 = new TemplateType(322, \"strp0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0006 = new TemplateType(323, \"strp0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0007 = new TemplateType(324, \"strp0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0008 = new TemplateType(325, \"strp0008\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0009 = new TemplateType(326, \"strp0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0010 = new TemplateType(327, \"strp0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType STRP0011 = new TemplateType(328, \"strp0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0001 = new TemplateType(329, \"wall0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0002 = new TemplateType(330, \"wall0002\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0003 = new TemplateType(331, \"wall0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0004 = new TemplateType(332, \"wall0004\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0005 = new TemplateType(333, \"wall0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0006 = new TemplateType(334, \"wall0006\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0007 = new TemplateType(335, \"wall0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0008 = new TemplateType(336, \"wall0008\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0009 = new TemplateType(337, \"wall0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0010 = new TemplateType(338, \"wall0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0011 = new TemplateType(339, \"wall0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0012 = new TemplateType(340, \"wall0012\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0013 = new TemplateType(341, \"wall0013\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0014 = new TemplateType(342, \"wall0014\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0015 = new TemplateType(343, \"wall0015\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0016 = new TemplateType(344, \"wall0016\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0017 = new TemplateType(345, \"wall0017\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0018 = new TemplateType(346, \"wall0018\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0019 = new TemplateType(347, \"wall0019\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0020 = new TemplateType(348, \"wall0020\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0021 = new TemplateType(349, \"wall0021\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0022 = new TemplateType(350, \"wall0022\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0023 = new TemplateType(351, \"wall0023\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0024 = new TemplateType(352, \"wall0024\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0025 = new TemplateType(353, \"wall0025\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0026 = new TemplateType(354, \"wall0026\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0027 = new TemplateType(355, \"wall0027\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0028 = new TemplateType(356, \"wall0028\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0029 = new TemplateType(357, \"wall0029\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0030 = new TemplateType(358, \"wall0030\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0031 = new TemplateType(359, \"wall0031\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0032 = new TemplateType(360, \"wall0032\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0033 = new TemplateType(361, \"wall0033\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0034 = new TemplateType(362, \"wall0034\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0035 = new TemplateType(363, \"wall0035\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0036 = new TemplateType(364, \"wall0036\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0037 = new TemplateType(365, \"wall0037\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0038 = new TemplateType(366, \"wall0038\", 2, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0039 = new TemplateType(367, \"wall0039\", 2, 3, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0040 = new TemplateType(368, \"wall0040\", 2, 3, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0041 = new TemplateType(369, \"wall0041\", 2, 3, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0042 = new TemplateType(370, \"wall0042\", 2, 3, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0043 = new TemplateType(371, \"wall0043\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0044 = new TemplateType(372, \"wall0044\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0045 = new TemplateType(373, \"wall0045\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0046 = new TemplateType(374, \"wall0046\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0047 = new TemplateType(375, \"wall0047\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0048 = new TemplateType(376, \"wall0048\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType WALL0049 = new TemplateType(377, \"wall0049\", 3, 3, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Bridge1h = new TemplateType(378, \"bridge1h\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2h = new TemplateType(379, \"bridge2h\", 5, 2, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1ax = new TemplateType(380, \"br1x\", 5, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2ax = new TemplateType(381, \"br2x\", 5, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge1x = new TemplateType(382, \"bridge1x\", 5, 4, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Bridge2x = new TemplateType(383, \"bridge2x\", 5, 5, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow });\n        public static readonly TemplateType Xtra0001 = new TemplateType(384, \"xtra0001\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0002 = new TemplateType(385, \"xtra0002\", 2, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0003 = new TemplateType(386, \"xtra0003\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0004 = new TemplateType(387, \"xtra0004\", 1, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0005 = new TemplateType(388, \"xtra0005\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0006 = new TemplateType(389, \"xtra0006\", 2, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0007 = new TemplateType(390, \"xtra0007\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0008 = new TemplateType(391, \"xtra0008\", 1, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0009 = new TemplateType(392, \"xtra0009\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0010 = new TemplateType(393, \"xtra0010\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0011 = new TemplateType(394, \"xtra0011\", 1, 1, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0012 = new TemplateType(395, \"xtra0012\", 1, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0013 = new TemplateType(396, \"xtra0013\", 1, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0014 = new TemplateType(397, \"xtra0014\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0015 = new TemplateType(398, \"xtra0015\", 3, 2, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType Xtra0016 = new TemplateType(399, \"xtra0016\", 2, 4, new TheaterType[] { TheaterTypes.Interior });\n        public static readonly TemplateType AntHill = new TemplateType(400, \"hill01\", 4, 3, new TheaterType[] { TheaterTypes.Temperate });\n\n        private static TemplateType[] Types;\n\n        static TemplateTypes()\n        {\n            Types =\n                (from field in typeof(TemplateTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TemplateType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TemplateType).ToArray();\n        }\n\n        public static IEnumerable<TemplateType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/TerrainTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public class TerrainTypes\n    {\n        public static readonly TerrainType Tree1Class = new TerrainType(0, \"t01\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree2Class = new TerrainType(1, \"t02\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree3Class = new TerrainType(2, \"t03\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree5Class = new TerrainType(3, \"t05\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree6Class = new TerrainType(4, \"t06\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree7Class = new TerrainType(5, \"t07\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree8Class = new TerrainType(6, \"t08\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Tree10Class = new TerrainType(7, \"t10\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree11Class = new TerrainType(8, \"t11\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree12Class = new TerrainType(9, \"t12\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree13Class = new TerrainType(10, \"t13\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree14Class = new TerrainType(11, \"t14\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree15Class = new TerrainType(12, \"t15\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree16Class = new TerrainType(13, \"t16\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree17Class = new TerrainType(14, \"t17\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Clump1Class = new TerrainType(15, \"tc01\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 3] { { false, false, false }, { true, true, false } });\n        public static readonly TerrainType Clump2Class = new TerrainType(16, \"tc02\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 3] { { false, true, false }, { true, true, false } });\n        public static readonly TerrainType Clump3Class = new TerrainType(17, \"tc03\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[2, 3] { { true, true, false }, { true, true, false } });\n        public static readonly TerrainType Clump4Class = new TerrainType(18, \"tc04\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[3, 4] { { false, false, false, false }, { true, true, true, false }, { true, false, false, false } });\n        public static readonly TerrainType Clump5Class = new TerrainType(19, \"tc05\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[3, 4] { { false, false, true, false }, { true, true, true, false }, { false, true, true, false } });\n        public static readonly TerrainType Ice01 = new TerrainType(20, \"ice01\", new TheaterType[] { TheaterTypes.Snow }, new bool[2, 2] { { true, true }, { true, true } }, TemplateTypeFlag.Water);\n        public static readonly TerrainType Ice02 = new TerrainType(21, \"ice02\", new TheaterType[] { TheaterTypes.Snow }, new bool[2, 2] { { true, false }, { true, false } }, TemplateTypeFlag.Water);\n        public static readonly TerrainType Ice03 = new TerrainType(22, \"ice03\", new TheaterType[] { TheaterTypes.Snow }, new bool[1, 2] { { true, true } }, TemplateTypeFlag.Water);\n        public static readonly TerrainType Ice04 = new TerrainType(23, \"ice04\", new TheaterType[] { TheaterTypes.Snow }, new bool[1, 2] { { true, false } }, TemplateTypeFlag.Water);\n        public static readonly TerrainType Ice05 = new TerrainType(24, \"ice05\", new TheaterType[] { TheaterTypes.Snow }, new bool[1, 2] { { true, false } }, TemplateTypeFlag.Water);\n        public static readonly TerrainType Boxes01 = new TerrainType(25, \"boxes01\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes02 = new TerrainType(26, \"boxes02\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes03 = new TerrainType(27, \"boxes03\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes04 = new TerrainType(28, \"boxes04\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes05 = new TerrainType(29, \"boxes05\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes06 = new TerrainType(30, \"boxes06\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes07 = new TerrainType(31, \"boxes07\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes08 = new TerrainType(32, \"boxes08\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Boxes09 = new TerrainType(33, \"boxes09\", new TheaterType[] { TheaterTypes.Interior }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Mine = new TerrainType(34, \"mine\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new bool[1, 2] { { true, false } }, TemplateTypeFlag.OreMine);\n\n\n        private static TerrainType[] Types;\n\n        static TerrainTypes()\n        {\n            Types =\n                (from field in typeof(TerrainTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TerrainType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TerrainType).ToArray();\n        }\n\n        public static IEnumerable<TerrainType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/TheaterTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class TheaterTypes\n    {\n        private static readonly IEnumerable<string> commonTilesets = new string[] { \"RA_Units\", \"RA_Structures\", \"RA_VFX\", \"Common_VFX\" };\n\n        public static readonly TheaterType Temperate = new TheaterType(0, \"temperate\", \"RA_Terrain_Temperate\".Yield().Concat(commonTilesets));\n        public static readonly TheaterType Snow = new TheaterType(1, \"snow\", \"RA_Terrain_Snow\".Yield().Concat(commonTilesets));\n        public static readonly TheaterType Interior = new TheaterType(2, \"interior\", \"RA_Terrain_Interior\".Yield().Concat(commonTilesets));\n\n        private static TheaterType[] Types;\n\n        static TheaterTypes()\n        {\n            Types =\n                (from field in typeof(TheaterTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TheaterType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TheaterType).ToArray();\n        }\n\n        public static IEnumerable<TheaterType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/RedAlert/UnitTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.RedAlert\n{\n    public static class UnitTypes\n    {\n        public static readonly UnitType HTank = new UnitType(0, \"4tnk\", \"TEXT_UNIT_RA_4TNK\", \"USSR\", true);\n        public static readonly UnitType MTank = new UnitType(1, \"3tnk\", \"TEXT_UNIT_RA_3TNK\", \"USSR\", true);\n        public static readonly UnitType MTank2 = new UnitType(2, \"2tnk\", \"TEXT_UNIT_RA_2TNK\", \"Greece\", true);\n        public static readonly UnitType LTank = new UnitType(3, \"1tnk\", \"TEXT_UNIT_RA_1TNK\", \"Greece\", true);\n        public static readonly UnitType APC = new UnitType(4, \"apc\", \"TEXT_UNIT_RA_APC\", \"Greece\");\n        public static readonly UnitType MineLayer = new UnitType(5, \"mnly\", \"TEXT_UNIT_RA_MNLY\", \"Greece\");\n        public static readonly UnitType Jeep = new UnitType(6, \"jeep\", \"TEXT_UNIT_RA_JEEP\", \"Greece\", true);\n        public static readonly UnitType Harvester = new UnitType(7, \"harv\", \"TEXT_UNIT_RA_HARV\", \"Greece\");\n        public static readonly UnitType Arty = new UnitType(8, \"arty\", \"TEXT_UNIT_RA_ARTY\", \"Greece\");\n        public static readonly UnitType MRJammer = new UnitType(9, \"mrj\", \"TEXT_UNIT_RA_MRJ\", \"Greece\");\n        public static readonly UnitType MGG = new UnitType(10, \"mgg\", \"TEXT_UNIT_RA_MGG\", \"Greece\");\n        public static readonly UnitType MCV = new UnitType(11, \"mcv\", \"TEXT_UNIT_RA_MCV\", \"Greece\");\n        public static readonly UnitType V2Launcher = new UnitType(12, \"v2rl\", \"TEXT_UNIT_RA_V2RL\", \"USSR\");\n        public static readonly UnitType ConvoyTruck = new UnitType(13, \"truk\", \"TEXT_UNIT_RA_TRUK\", \"Greece\");\n        public static readonly UnitType Ant1 = new UnitType(14, \"ant1\", \"TEXT_UNIT_RA_ANT1\", \"Special\");\n        public static readonly UnitType Ant2 = new UnitType(15, \"ant2\", \"TEXT_UNIT_RA_ANT2\", \"Special\");\n        public static readonly UnitType Ant3 = new UnitType(16, \"ant3\", \"TEXT_UNIT_RA_ANT3\", \"Special\");\n        public static readonly UnitType Chrono = new UnitType(17, \"ctnk\", \"TEXT_UNIT_RA_CTNK\", \"Greece\");\n        public static readonly UnitType Tesla = new UnitType(18, \"ttnk\", \"TEXT_UNIT_RA_TTNK\", \"USSR\");\n        public static readonly UnitType MAD = new UnitType(19, \"qtnk\", \"TEXT_UNIT_RA_QTNK\", \"Greece\");\n        public static readonly UnitType DemoTruck = new UnitType(20, \"dtrk\", \"TEXT_UNIT_RA_DTRK\", \"USSR\");\n        public static readonly UnitType Phase = new UnitType(21, \"stnk\", \"TEXT_UNIT_RA_STNK\", \"Greece\", true);\n\n        public static readonly UnitType Tran = new UnitType(0 | UnitTypeIDMask.Aircraft, \"tran\", \"TEXT_UNIT_RA_TRAN\", \"USSR\");\n        public static readonly UnitType Badr = new UnitType(1 | UnitTypeIDMask.Aircraft, \"badr\", \"TEXT_UNIT_RA_BADR\", \"USSR\", false, true);\n        public static readonly UnitType U2 = new UnitType(2 | UnitTypeIDMask.Aircraft, \"u2\", \"TEXT_UNIT_RA_U2\", \"USSR\", false, true);\n        public static readonly UnitType Mig = new UnitType(3 | UnitTypeIDMask.Aircraft, \"mig\", \"TEXT_UNIT_RA_MIG\", \"USSR\", false, true);\n        public static readonly UnitType Yak = new UnitType(4 | UnitTypeIDMask.Aircraft, \"yak\", \"TEXT_UNIT_RA_YAK\", \"USSR\", false, true);\n        public static readonly UnitType Heli = new UnitType(5 | UnitTypeIDMask.Aircraft, \"heli\", \"TEXT_UNIT_RA_HELI\", \"Greece\");\n        public static readonly UnitType Hind = new UnitType(6 | UnitTypeIDMask.Aircraft, \"hind\", \"TEXT_UNIT_RA_HIND\", \"USSR\");\n\n        public static readonly UnitType Submarine = new UnitType(0 | UnitTypeIDMask.Vessel, \"ss\", \"TEXT_UNIT_RA_SS\", \"USSR\");\n        public static readonly UnitType Destroyer = new UnitType(1 | UnitTypeIDMask.Vessel, \"dd\", \"TEXT_UNIT_RA_DD\", \"Greece\", true);\n        public static readonly UnitType Cruiser = new UnitType(2 | UnitTypeIDMask.Vessel, \"ca\", \"TEXT_UNIT_RA_CA\", \"Greece\", true);\n        public static readonly UnitType Transport = new UnitType(3 | UnitTypeIDMask.Vessel, \"lst\", \"TEXT_UNIT_RA_LST\", \"Greece\");\n        public static readonly UnitType PTBoat = new UnitType(4 | UnitTypeIDMask.Vessel, \"pt\", \"TEXT_UNIT_RA_PT\", \"Greece\", true);\n        public static readonly UnitType MissileSubmarine = new UnitType(5 | UnitTypeIDMask.Vessel, \"msub\", \"TEXT_UNIT_RA_MSUB\", \"USSR\");\n        public static readonly UnitType Carrier = new UnitType(6 | UnitTypeIDMask.Vessel, \"carr\", \"TEXT_UNIT_RA_CARR\", \"Greece\");\n\n        private static readonly UnitType[] Types;\n\n        static UnitTypes()\n        {\n            Types =\n                (from field in typeof(UnitTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(UnitType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as UnitType).ToArray();\n        }\n\n        public static IEnumerable<UnitType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Render/MapRenderer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.Linq;\n\nnamespace MobiusEditor.Render\n{\n    public static class MapRenderer\n    {\n        private static readonly int[] Facing16 = new int[256]\n        {\n            0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,\n            2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,\n            4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,\n            6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,\n            8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,\n            10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n            12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,\n            14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,0,0,0,0,0,0\n        };\n\n        private static readonly int[] Facing32 = new int[256]\n        {\n            0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,\n            3,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,\n            8,8,8,9,9,9,9,9,9,9,10,10,10,10,10,10,10,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n            13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,\n            16,16,16,16,16,17,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,\n            19,20,20,20,20,20,20,21,21,21,21,21,21,21,22,22,22,22,22,22,22,23,23,23,23,23,23,23,24,24,24,24,\n            24,24,24,25,25,25,25,25,25,25,26,26,26,26,26,26,26,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,\n            29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,0,0,0,0,0,0\n        };\n\n        private static readonly int[] HumanShape = new int[32]\n        {\n            0,0,7,7,7,7,6,6,6,6,5,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,1,1,1,1,1,0\n        };\n\n        private static readonly int[] BodyShape = new int[32]\n        {\n            0,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1\n        };\n\n        private static readonly Point[] TurretAdjust = new Point[]\n        {\n            new Point(1, 2),\t// N\n            new Point(-1, 1),\n            new Point(-2, 0),\n            new Point(-3, 0),\n            new Point(-3, 1),\t// NW\n            new Point(-4, -1),\n            new Point(-4, -1),\n            new Point(-5, -2),\n            new Point(-5, -3),\t// W\n            new Point(-5, -3),\n            new Point(-3, -3),\n            new Point(-3, -4),\n            new Point(-3, -4),\t// SW\n            new Point(-3, -5),\n            new Point(-2, -5),\n            new Point(-1, -5),\n            new Point(0, -5),\t// S\n            new Point(1, -6),\n            new Point(2, -5),\n            new Point(3, -5),\n            new Point(4, -5),\t// SE\n            new Point(6, -4),\n            new Point(6, -3),\n            new Point(6, -3),\n            new Point(6, -3),\t// E\n            new Point(5, -1),\n            new Point(5, -1),\n            new Point(4, 0),\n            new Point(3, 0),\t// NE\n            new Point(2, 0),\n            new Point(2, 1),\n            new Point(1, 2)\n        };\n\n        private static readonly int[] tiberiumCounts = new int[] { 0, 1, 3, 4, 6, 7, 8, 10, 11 };\n        private static readonly int randomSeed;\n\n        static MapRenderer()\n        {\n            randomSeed = Guid.NewGuid().GetHashCode();\n        }\n\n        public static void Render(GameType gameType, Map map, Graphics graphics, ISet<Point> locations, MapLayerFlag layers, int tileScale)\n        {\n            var tileSize = new Size(Globals.OriginalTileWidth / tileScale, Globals.OriginalTileHeight / tileScale);\n            var tiberiumOrGoldTypes = map.OverlayTypes.Where(t => t.IsTiberiumOrGold).Select(t => t).ToArray();\n            var gemTypes = map.OverlayTypes.Where(t => t.IsGem).ToArray();\n\n            var overlappingRenderList = new List<(Rectangle, Action<Graphics>)>();\n\n            Func<IEnumerable<Point>> renderLocations = null;\n            if (locations != null)\n            {\n                renderLocations = () => locations;\n            }\n            else\n            {\n                IEnumerable<Point> allCells()\n                {\n                    for (var y = 0; y < map.Metrics.Height; ++y)\n                    {\n                        for (var x = 0; x < map.Metrics.Width; ++x)\n                        {\n                            yield return new Point(x, y);\n                        }\n                    }\n                }\n\n                renderLocations = allCells;\n            }\n\n            if ((layers & MapLayerFlag.Template) != MapLayerFlag.None)\n            {\n                foreach (var topLeft in renderLocations())\n                {\n                    map.Metrics.GetCell(topLeft, out int cell);\n\n                    var template = map.Templates[topLeft];\n                    var name = template?.Type.Name ?? map.TemplateTypes.Where(t => t.Equals(\"clear1\")).FirstOrDefault().Name;\n                    var icon = template?.Icon ?? ((cell & 0x03) | ((cell >> 4) & 0x0C));\n\n                    if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, name, icon, out Tile tile))\n                    {\n                        var renderBounds = new Rectangle(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height, tileSize.Width, tileSize.Height);\n                        graphics.DrawImage(tile.Image, renderBounds);\n                    }\n                    else\n                    {\n                        Debug.Print(string.Format(\"Template {0} ({1}) not found\", name, icon));\n                    }\n                }\n            }\n\n            if ((layers & MapLayerFlag.Smudge) != MapLayerFlag.None)\n            {\n                foreach (var topLeft in renderLocations())\n                {\n                    var smudge = map.Smudge[topLeft];\n                    if (smudge != null)\n                    {\n                        Render(map.Theater, topLeft, tileSize, smudge).Item2(graphics);\n                    }\n                }\n            }\n\n            if ((layers & MapLayerFlag.OverlayAll) != MapLayerFlag.None)\n            {\n                foreach (var topLeft in renderLocations())\n                {\n                    var overlay = map.Overlay[topLeft];\n                    if (overlay == null)\n                    {\n                        continue;\n                    }\n\n                    if ((overlay.Type.IsResource && ((layers & MapLayerFlag.Resources) != MapLayerFlag.None)) ||\n                        (overlay.Type.IsWall && ((layers & MapLayerFlag.Walls) != MapLayerFlag.None)) ||\n                        ((layers & MapLayerFlag.Overlay) != MapLayerFlag.None))\n                    {\n                        Render(map.Theater, tiberiumOrGoldTypes, gemTypes, topLeft, tileSize, tileScale, overlay).Item2(graphics);\n                    }\n                }\n            }\n\n            if ((layers & MapLayerFlag.Terrain) != MapLayerFlag.None)\n            {\n                foreach (var (topLeft, terrain) in map.Technos.OfType<Terrain>())\n                {\n                    if ((locations != null) && !locations.Contains(topLeft))\n                    {\n                        continue;\n                    }\n\n                    string tileName = terrain.Type.Name;\n                    if ((terrain.Type.TemplateType & TemplateTypeFlag.OreMine) != TemplateTypeFlag.None)\n                    {\n                        tileName = \"OREMINE\";\n                    }\n\n                    if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, tileName, terrain.Icon, out Tile tile))\n                    {\n                        var tint = terrain.Tint;\n                        var imageAttributes = new ImageAttributes();\n                        if (tint != Color.White)\n                        {\n                            var colorMatrix = new ColorMatrix(new float[][]\n                            {\n                                new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                                new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                                new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                                new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                                new float[] {0, 0, 0, 0, 1},\n                            }\n                            );\n                            imageAttributes.SetColorMatrix(colorMatrix);\n                        }\n\n                        var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);\n                        var size = new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale);\n                        var terrainBounds = new Rectangle(location, size);\n                        overlappingRenderList.Add((terrainBounds, g => g.DrawImage(tile.Image, terrainBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes)));\n                    }\n                    else\n                    {\n                        Debug.Print(string.Format(\"Terrain {0} ({1}) not found\", tileName, terrain.Icon));\n                    }\n                }\n            }\n\n            if ((layers & MapLayerFlag.Buildings) != MapLayerFlag.None)\n            {\n                foreach (var (topLeft, building) in map.Buildings.OfType<Building>())\n                {\n                    if ((locations != null) && !locations.Contains(topLeft))\n                    {\n                        continue;\n                    }\n\n                    overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, tileScale, building));\n                }\n            }\n\n            if ((layers & MapLayerFlag.Infantry) != MapLayerFlag.None)\n            {\n                foreach (var (topLeft, infantryGroup) in map.Technos.OfType<InfantryGroup>())\n                {\n                    if ((locations != null) && !locations.Contains(topLeft))\n                    {\n                        continue;\n                    }\n\n                    for (int i = 0; i < infantryGroup.Infantry.Length; ++i)\n                    {\n                        var infantry = infantryGroup.Infantry[i];\n                        if (infantry == null)\n                        {\n                            continue;\n                        }\n\n                        overlappingRenderList.Add(Render(map.Theater, topLeft, tileSize, infantry, (InfantryStoppingType)i));\n                    }\n                }\n            }\n\n            if ((layers & MapLayerFlag.Units) != MapLayerFlag.None)\n            {\n                foreach (var (topLeft, unit) in map.Technos.OfType<Unit>())\n                {\n                    if ((locations != null) && !locations.Contains(topLeft))\n                    {\n                        continue;\n                    }\n\n                    overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, unit));\n                }\n            }\n\n            foreach (var (location, renderer) in overlappingRenderList.Where(x => !x.Item1.IsEmpty).OrderBy(x => x.Item1.Bottom))\n            {\n                renderer(graphics);\n            }\n        }\n\n        public static void Render(GameType gameType, Map map, Graphics graphics, ISet<Point> locations, MapLayerFlag layers)\n        {\n            Render(gameType, map, graphics, locations, layers, Globals.TileScale);\n        }\n\n        public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Smudge smudge)\n        {\n            var tint = smudge.Tint;\n            var imageAttributes = new ImageAttributes();\n            if (tint != Color.White)\n            {\n                var colorMatrix = new ColorMatrix(new float[][]\n                {\n                    new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                    new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                    new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                    new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                    new float[] {0, 0, 0, 0, 1},\n                }\n                );\n                imageAttributes.SetColorMatrix(colorMatrix);\n            }\n\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, smudge.Type.Name, smudge.Icon, out Tile tile))\n            {\n                var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);\n                var smudgeBounds = new Rectangle(location, smudge.Type.RenderSize);\n\n                void render(Graphics g)\n                {\n                    g.DrawImage(tile.Image, smudgeBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                }\n\n                return (smudgeBounds, render);\n            }\n            else\n            {\n                Debug.Print(string.Format(\"Smudge {0} ({1}) not found\", smudge.Type.Name, smudge.Icon));\n                return (Rectangle.Empty, (g) => { });\n            }\n        }\n\n        public static (Rectangle, Action<Graphics>) Render(TheaterType theater, OverlayType[] tiberiumOrGoldTypes, OverlayType[] gemTypes, Point topLeft, Size tileSize, int tileScale, Overlay overlay)\n        {\n            var name = overlay.Type.Name;\n            if (overlay.Type.IsGem)\n            {\n                name = gemTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;\n            }\n            else if (overlay.Type.IsTiberiumOrGold)\n            {\n                name = tiberiumOrGoldTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;\n            }\n\n            if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, name, overlay.Icon, out Tile tile))\n            {\n                var size = (overlay.Type.IsCrate || overlay.Type.IsFlag) ? new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale) : tileSize;\n                var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)\n                    + new Size(tileSize.Width / 2, tileSize.Height / 2)\n                    - new Size(size.Width / 2, size.Height / 2);\n                var overlayBounds = new Rectangle(location, size);\n\n                var tint = overlay.Tint;\n                void render(Graphics g)\n                {\n                    var imageAttributes = new ImageAttributes();\n                    if (tint != Color.White)\n                    {\n                        var colorMatrix = new ColorMatrix(new float[][]\n                        {\n                            new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                            new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                            new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                            new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                            new float[] {0, 0, 0, 0, 1},\n                        }\n                        );\n                        imageAttributes.SetColorMatrix(colorMatrix);\n                    }\n\n                    g.DrawImage(tile.Image, overlayBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                }\n\n                return (overlayBounds, render);\n            }\n            else\n            {\n                Debug.Print(string.Format(\"Overlay {0} ({1}) not found\", overlay.Type.Name, overlay.Icon));\n                return (Rectangle.Empty, (g) => { });\n            }\n        }\n\n        public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, int tileScale, Building building)\n        {\n            var tint = building.Tint;\n\n            var stringFormat = new StringFormat\n            {\n                Alignment = StringAlignment.Center,\n                LineAlignment = StringAlignment.Center\n            };\n            var fakeBackgroundBrush = new SolidBrush(Color.FromArgb(building.Tint.A / 2, Color.Black));\n            var fakeTextBrush = new SolidBrush(Color.FromArgb(building.Tint.A, Color.White));\n            var baseBackgroundBrush = new SolidBrush(Color.FromArgb(building.Tint.A / 2, Color.Black));\n            var baseTextBrush = new SolidBrush(Color.FromArgb(building.Tint.A, Color.Red));\n\n            var icon = 0;\n            if (building.Type.HasTurret)\n            {\n                icon = BodyShape[Facing32[building.Direction.ID]];\n                if (building.Strength < 128)\n                {\n                    switch (gameType)\n                    {\n                        case GameType.TiberianDawn:\n                            icon += 64;\n                            break;\n                        case GameType.RedAlert:\n                            icon += building.Type.Equals(\"sam\") ? 35 : 64;\n                            break;\n                    }\n                }\n            }\n            else\n            {\n                if (building.Strength <= 1)\n                {\n                    icon = -1;\n                }\n                else if (building.Strength < 128)\n                {\n                    icon = -2;\n                    if (building.Type.Equals(\"weap\") || building.Type.Equals(\"weaf\"))\n                    {\n                        icon = 1;\n                    }\n                    else if ((gameType == GameType.TiberianDawn) && building.Type.Equals(\"proc\"))\n                    {\n                        icon = 30;\n                    }\n                    else if (building.Type.Equals(\"eye\"))\n                    {\n                        icon = 16;\n                    }\n                    else if (building.Type.Equals(\"silo\"))\n                    {\n                        icon = 5;\n                    }\n                    else if (building.Type.Equals(\"fix\"))\n                    {\n                        icon = 7;\n                    }\n                    else if (building.Type.Equals(\"v19\"))\n                    {\n                        icon = 14;\n                    }\n                }\n            }\n\n            if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.Tilename, icon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out Tile tile))\n            {\n                var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);\n                var size = new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale);\n                var maxSize = new Size(building.Type.Size.Width * tileSize.Width, building.Type.Size.Height * tileSize.Height);\n                if ((size.Width >= size.Height) && (size.Width > maxSize.Width))\n                {\n                    size.Height = size.Height * maxSize.Width / size.Width;\n                    size.Width = maxSize.Width;\n                }\n                else if ((size.Height >= size.Width) && (size.Height > maxSize.Height))\n                {\n                    size.Width = size.Width * maxSize.Height / size.Height;\n                    size.Height = maxSize.Height;\n                }\n                var buildingBounds = new Rectangle(location, size);\n\n                Tile factoryOverlayTile = null;\n                if (building.Type.FactoryOverlay != null)\n                {\n                    int overlayIcon = 0;\n                    if (building.Strength < 128)\n                    {\n                        switch (gameType)\n                        {\n                            case GameType.TiberianDawn:\n                                overlayIcon = 10;\n                                break;\n                            case GameType.RedAlert:\n                                overlayIcon = 4;\n                                break;\n                        }\n                    }\n\n                    Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile);\n                }\n\n                void render(Graphics g)\n                {\n                    var imageAttributes = new ImageAttributes();\n                    if (tint != Color.White)\n                    {\n                        var colorMatrix = new ColorMatrix(new float[][]\n                        {\n                            new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                            new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                            new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                            new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                            new float[] {0, 0, 0, 0, 1},\n                        }\n                        );\n                        imageAttributes.SetColorMatrix(colorMatrix);\n                    }\n\n                    if (factoryOverlayTile != null)\n                    {\n                        g.DrawImage(tile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                        g.DrawImage(factoryOverlayTile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                    }\n                    else\n                    {\n                        g.DrawImage(tile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                    }\n\n                    if (building.Type.IsFake)\n                    {\n                        var text = Globals.TheGameTextManager[\"TEXT_UI_FAKE\"];\n                        var textSize = g.MeasureString(text, SystemFonts.CaptionFont) + new SizeF(6.0f, 6.0f);\n                        var textBounds = new RectangleF(buildingBounds.Location, textSize);\n                        g.FillRectangle(fakeBackgroundBrush, textBounds);\n                        g.DrawString(text, SystemFonts.CaptionFont, fakeTextBrush, textBounds, stringFormat);\n                    }\n\n                    if (building.BasePriority >= 0)\n                    {\n                        var text = building.BasePriority.ToString();\n                        var textSize = g.MeasureString(text, SystemFonts.CaptionFont) + new SizeF(6.0f, 6.0f);\n                        var textBounds = new RectangleF(buildingBounds.Location +\n                            new Size((int)((buildingBounds.Width - textSize.Width) / 2.0f), (int)(buildingBounds.Height - textSize.Height)),\n                            textSize\n                        );\n                        g.FillRectangle(baseBackgroundBrush, textBounds);\n                        g.DrawString(text, SystemFonts.CaptionFont, baseTextBrush, textBounds, stringFormat);\n                    }\n                }\n\n                return (buildingBounds, render);\n            }\n            else\n            {\n                Debug.Print(string.Format(\"Building {0} (0) not found\", building.Type.Name));\n                return (Rectangle.Empty, (g) => { });\n            }\n        }\n\n        public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Infantry infantry, InfantryStoppingType infantryStoppingType)\n        {\n            var icon = HumanShape[Facing32[infantry.Direction.ID]];\n\n            string teamColor = infantry.House?.UnitTeamColor;\n            if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, infantry.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))\n            {\n                var baseLocation = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)\n                    + new Size(tileSize.Width / 2, tileSize.Height / 2);\n\n                var offset = Point.Empty;\n                switch (infantryStoppingType)\n                {\n                    case InfantryStoppingType.UpperLeft:\n                        offset.X = -tileSize.Width / 4;\n                        offset.Y = -tileSize.Height / 4;\n                        break;\n                    case InfantryStoppingType.UpperRight:\n                        offset.X = tileSize.Width / 4;\n                        offset.Y = -tileSize.Height / 4;\n                        break;\n                    case InfantryStoppingType.LowerLeft:\n                        offset.X = -tileSize.Width / 4;\n                        offset.Y = tileSize.Height / 4;\n                        break;\n                    case InfantryStoppingType.LowerRight:\n                        offset.X = tileSize.Width / 4;\n                        offset.Y = tileSize.Height / 4;\n                        break;\n                }\n                baseLocation.Offset(offset);\n\n                var virtualBounds = new Rectangle(\n                    new Point(baseLocation.X - (tile.OpaqueBounds.Width / 2), baseLocation.Y - tile.OpaqueBounds.Height),\n                    tile.OpaqueBounds.Size\n                );\n                var renderBounds = new Rectangle(\n                    baseLocation - new Size(infantry.Type.RenderSize.Width / 2, infantry.Type.RenderSize.Height / 2),\n                    infantry.Type.RenderSize\n                );\n\n                var tint = infantry.Tint;\n                void render(Graphics g)\n                {\n                    var imageAttributes = new ImageAttributes();\n                    if (tint != Color.White)\n                    {\n                        var colorMatrix = new ColorMatrix(new float[][]\n                        {\n                            new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                            new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                            new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                            new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                            new float[] {0, 0, 0, 0, 1},\n                        }\n                        );\n                        imageAttributes.SetColorMatrix(colorMatrix);\n                    }\n                    g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                }\n\n                return (virtualBounds, render);\n            }\n            else\n            {\n                Debug.Print(string.Format(\"Infantry {0} ({1}) not found\", infantry.Type.Name, icon));\n                return (Rectangle.Empty, (g) => { });\n            }\n        }\n\n        public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, Unit unit)\n        {\n            int icon = 0;\n            if (gameType == GameType.TiberianDawn)\n            {\n                if (unit.Type == TiberianDawn.UnitTypes.GunBoat)\n                {\n                    switch (unit.Direction.Facing)\n                    {\n                        case FacingType.NorthEast:\n                        case FacingType.East:\n                        case FacingType.SouthEast:\n                            icon = 96;\n                            break;\n                        default:\n                            icon = 0;\n                            break;\n                    }\n                }\n                else if ((unit.Type == TiberianDawn.UnitTypes.Tric) ||\n                         (unit.Type == TiberianDawn.UnitTypes.Trex) ||\n                         (unit.Type == TiberianDawn.UnitTypes.Rapt) ||\n                         (unit.Type == TiberianDawn.UnitTypes.Steg))\n                {\n                    var facing = ((unit.Direction.ID + 0x10) & 0xFF) >> 5;\n                    icon = BodyShape[facing + ((facing > 0) ? 24 : 0)];\n                }\n                else if ((unit.Type == TiberianDawn.UnitTypes.Hover) ||\n                         (unit.Type == TiberianDawn.UnitTypes.Visceroid))\n                {\n                    icon = 0;\n                }\n                else\n                {\n                    icon = BodyShape[Facing32[unit.Direction.ID]];\n                }\n            }\n            else if (gameType == GameType.RedAlert)\n            {\n                if (unit.Type.IsAircraft)\n                {\n                    if ((unit.Type == RedAlert.UnitTypes.Tran) ||\n                        (unit.Type == RedAlert.UnitTypes.Heli) ||\n                        (unit.Type == RedAlert.UnitTypes.Hind))\n                    {\n                        icon = BodyShape[Facing32[unit.Direction.ID]];\n                    }\n                    else\n                    {\n                        icon = BodyShape[Facing16[unit.Direction.ID] * 2] / 2;\n                    }\n                }\n                else if (unit.Type.IsVessel)\n                {\n                    if ((unit.Type == RedAlert.UnitTypes.Transport) ||\n                        (unit.Type == RedAlert.UnitTypes.Carrier))\n                    {\n                        icon = 0;\n                    }\n                    else\n                    {\n                        icon = BodyShape[Facing16[unit.Direction.ID] * 2] >> 1;\n                    }\n                }\n                else\n                {\n                    if ((unit.Type == RedAlert.UnitTypes.Ant1) ||\n                        (unit.Type == RedAlert.UnitTypes.Ant2) ||\n                        (unit.Type == RedAlert.UnitTypes.Ant3))\n                    {\n                        icon = ((BodyShape[Facing32[unit.Direction.ID]] + 2) / 4) & 0x07;\n                    }\n                    else\n                    {\n                        icon = BodyShape[Facing32[unit.Direction.ID]];\n                    }\n                }\n            }\n\n            string teamColor = null;\n            if (unit.House != null)\n            {\n                if (!unit.House.OverrideTeamColors.TryGetValue(unit.Type.Name, out teamColor))\n                {\n                    teamColor = unit.House.UnitTeamColor;\n                }\n            }\n\n            if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))\n            {\n                var location =\n                    new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height) +\n                    new Size(tileSize.Width / 2, tileSize.Height / 2);\n                var renderBounds = new Rectangle(\n                    location - new Size(unit.Type.RenderSize.Width / 2, unit.Type.RenderSize.Height / 2),\n                    unit.Type.RenderSize\n                );\n\n                Tile radarTile = null;\n                if ((unit.Type == RedAlert.UnitTypes.MGG) ||\n                    (unit.Type == RedAlert.UnitTypes.MRJammer) ||\n                    (unit.Type == RedAlert.UnitTypes.Tesla))\n                {\n                    Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, 32, Globals.TheTeamColorManager[teamColor], out radarTile);\n                }\n\n                Tile turretTile = null;\n                if (unit.Type.HasTurret)\n                {\n                    var turretName = unit.Type.Name;\n                    var turretIcon = icon + 32;\n                    if (unit.Type == RedAlert.UnitTypes.Phase)\n                    {\n                        turretIcon += 6;\n                    }\n#if TODO\n                    else if (unit.Type == RedAlert.UnitTypes.Cruiser)\n                    {\n                        turretName = \"TURR\";\n                        turretIcon = BodyShape[Facing32[unit.Direction.ID]];\n                    }\n                    else if (unit.Type == RedAlert.UnitTypes.Destroyer)\n                    {\n                        turretName = \"SSAM\";\n                        turretIcon = BodyShape[Facing32[unit.Direction.ID]];\n                    }\n                    else if (unit.Type == RedAlert.UnitTypes.PTBoat)\n                    {\n                        turretName = \"MGUN\";\n                        turretIcon = BodyShape[Facing32[unit.Direction.ID]];\n                    }\n#endif\n\n                    Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, turretName, turretIcon, Globals.TheTeamColorManager[teamColor], out turretTile);\n                }\n\n                var tint = unit.Tint;\n                void render(Graphics g)\n                {\n                    var imageAttributes = new ImageAttributes();\n                    if (tint != Color.White)\n                    {\n                        var colorMatrix = new ColorMatrix(new float[][]\n                        {\n                            new float[] {tint.R / 255.0f, 0, 0, 0, 0},\n                            new float[] {0, tint.G / 255.0f, 0, 0, 0},\n                            new float[] {0, 0, tint.B / 255.0f, 0, 0},\n                            new float[] {0, 0, 0, tint.A / 255.0f, 0},\n                            new float[] {0, 0, 0, 0, 1},\n                        }\n                        );\n                        imageAttributes.SetColorMatrix(colorMatrix);\n                    }\n\n                    g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n\n                    if (radarTile != null)\n                    {\n                        Point turretAdjust = Point.Empty;\n                        if (unit.Type == RedAlert.UnitTypes.MGG)\n                        {\n                            turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]];\n                        }\n                        else if (unit.Type != RedAlert.UnitTypes.Tesla)\n                        {\n                            turretAdjust.Y = -5;\n                        }\n\n                        var radarBounds = renderBounds;\n                        radarBounds.Offset(\n                            turretAdjust.X * tileSize.Width / Globals.PixelWidth,\n                            turretAdjust.Y * tileSize.Height / Globals.PixelHeight\n                        );\n\n                        g.DrawImage(radarTile.Image, radarBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                    }\n                    if (turretTile != null)\n                    {\n                        Point turretAdjust = Point.Empty;\n                        if (gameType == GameType.RedAlert)\n                        {\n                            if (unit.Type.IsVessel)\n                            {\n\n                            }\n                            else if (unit.Type == RedAlert.UnitTypes.Jeep)\n                            {\n                                turretAdjust.Y = -4;\n                            }\n                        }\n                        else if (gameType == GameType.TiberianDawn)\n                        {\n                            if ((unit.Type == TiberianDawn.UnitTypes.Jeep) ||\n                                (unit.Type == TiberianDawn.UnitTypes.Buggy))\n                            {\n                                turretAdjust.Y = -4;\n                            }\n                            else if ((unit.Type == TiberianDawn.UnitTypes.SAM) ||\n                                     (unit.Type == TiberianDawn.UnitTypes.MLRS))\n                            {\n                                turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]];\n                            }\n                        }\n\n                        var turretBounds = renderBounds;\n                        turretBounds.Offset(\n                            turretAdjust.X * tileSize.Width / Globals.PixelWidth,\n                            turretAdjust.Y * tileSize.Height / Globals.PixelHeight\n                        );\n\n                        g.DrawImage(turretTile.Image, turretBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);\n                    }\n                }\n\n                return (renderBounds, render);\n            }\n            else\n            {\n                Debug.Print(string.Format(\"Unit {0} ({1}) not found\", unit.Type.Name, icon));\n                return (Rectangle.Empty, (g) => { });\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/CallbackDispatcher.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\n#if UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6\n\t#error Unsupported Unity platform. Steamworks.NET requires Unity 4.7 or higher.\n#elif UNITY_4_7 || UNITY_5 || UNITY_2017 || UNITY_2017_1_OR_NEWER\n\t#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)\n\t\t#define WINDOWS_BUILD\n\t#endif\n#elif STEAMWORKS_WIN\n\t#define WINDOWS_BUILD\n#elif STEAMWORKS_LIN_OSX\n\t// So that we don't enter the else block below.\n#else\n\t#error You need to define STEAMWORKS_WIN, or STEAMWORKS_LIN_OSX. Refer to the readme for more details.\n#endif\n\n// Unity 32bit Mono on Windows crashes with ThisCall/Cdecl for some reason, StdCall without the 'this' ptr is the only thing that works..?\n#if (UNITY_EDITOR_WIN && !UNITY_EDITOR_64) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN && !UNITY_64)\n\t#define STDCALL\n#elif STEAMWORKS_WIN\n\t#define THISCALL\n#endif\n\n// Calling Conventions:\n// Unity x86 Windows        - StdCall (No this pointer)\n// Unity x86 Linux          - Cdecl\n// Unity x86 OSX            - Cdecl\n// Unity x64 Windows        - Cdecl\n// Unity x64 Linux          - Cdecl\n// Unity x64 OSX            - Cdecl\n// Microsoft x86 Windows    - ThisCall\n// Microsoft x64 Windows    - ThisCall\n// Mono x86 Linux           - Cdecl\n// Mono x86 OSX             - Cdecl\n// Mono x64 Linux           - Cdecl\n// Mono x64 OSX             - Cdecl\n// Mono on Windows is probably not supported.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace Steamworks {\n\tpublic static class CallbackDispatcher {\n\t\t// We catch exceptions inside callbacks and reroute them here.\n\t\t// For some reason throwing an exception causes RunCallbacks() to break otherwise.\n\t\t// If you have a custom ExceptionHandler in your engine you can register it here manually until we get something more elegant hooked up.\n\t\tpublic static void ExceptionHandler(Exception e) {\n#if UNITY_STANDALONE\n\t\t\tUnityEngine.Debug.LogException(e);\n#elif STEAMWORKS_WIN || STEAMWORKS_LIN_OSX\n\t\t\tConsole.WriteLine(e.Message);\n#endif\n\t\t}\n\t}\n\n\tpublic sealed class Callback<T> : IDisposable {\n\t\tprivate CCallbackBaseVTable m_CallbackBaseVTable;\n\t\tprivate IntPtr m_pVTable = IntPtr.Zero;\n\t\tprivate CCallbackBase m_CCallbackBase;\n\t\tprivate GCHandle m_pCCallbackBase;\n\n\t\tpublic delegate void DispatchDelegate(T param);\n\t\tprivate event DispatchDelegate m_Func;\n\n\t\tprivate bool m_bGameServer;\n\t\tprivate readonly int m_size = Marshal.SizeOf(typeof(T));\n\n\t\tprivate bool m_bDisposed = false;\n\n\t\t/// <summary>\n\t\t/// Creates a new Callback. You must be calling SteamAPI.RunCallbacks() to retrieve the callbacks.\n\t\t/// <para>Returns a handle to the Callback.</para>\n\t\t/// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>\n\t\t/// </summary>\n\t\tpublic static Callback<T> Create(DispatchDelegate func) {\n\t\t\treturn new Callback<T>(func, bGameServer: false);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Creates a new GameServer Callback. You must be calling GameServer.RunCallbacks() to retrieve the callbacks.\n\t\t/// <para>Returns a handle to the Callback.</para>\n\t\t/// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>\n\t\t/// </summary>\n\t\tpublic static Callback<T> CreateGameServer(DispatchDelegate func) {\n\t\t\treturn new Callback<T>(func, bGameServer: true);\n\t\t}\n\n\t\tpublic Callback(DispatchDelegate func, bool bGameServer = false) {\n\t\t\tm_bGameServer = bGameServer;\n\t\t\tBuildCCallbackBase();\n\t\t\tRegister(func);\n\t\t}\n\n\t\t~Callback() {\n\t\t\tDispose();\n\t\t}\n\n\t\tpublic void Dispose() {\n\t\t\tif (m_bDisposed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tGC.SuppressFinalize(this);\n\n\t\t\tUnregister();\n\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pCCallbackBase.IsAllocated) {\n\t\t\t\tm_pCCallbackBase.Free();\n\t\t\t}\n\n\t\t\tm_bDisposed = true;\n\t\t}\n\n\t\t// Manual registration of the callback\n\t\tpublic void Register(DispatchDelegate func) {\n\t\t\tif (func == null) {\n\t\t\t\tthrow new Exception(\"Callback function must not be null.\");\n\t\t\t}\n\n\t\t\tif ((m_CCallbackBase.m_nCallbackFlags & CCallbackBase.k_ECallbackFlagsRegistered) == CCallbackBase.k_ECallbackFlagsRegistered) {\n\t\t\t\tUnregister();\n\t\t\t}\n\n\t\t\tif (m_bGameServer) {\n\t\t\t\tSetGameserverFlag();\n\t\t\t}\n\n\t\t\tm_Func = func;\n\n\t\t\t// k_ECallbackFlagsRegistered is set by SteamAPI_RegisterCallback.\n\t\t\tNativeMethods.SteamAPI_RegisterCallback(m_pCCallbackBase.AddrOfPinnedObject(), CallbackIdentities.GetCallbackIdentity(typeof(T)));\n\t\t}\n\n\t\tpublic void Unregister() {\n\t\t\t// k_ECallbackFlagsRegistered is removed by SteamAPI_UnregisterCallback.\n\t\t\tNativeMethods.SteamAPI_UnregisterCallback(m_pCCallbackBase.AddrOfPinnedObject());\n\t\t}\n\n\t\tpublic void SetGameserverFlag() {\n\t\t\tm_CCallbackBase.m_nCallbackFlags |= CCallbackBase.k_ECallbackFlagsGameServer;\n\t\t}\n\n\t\tprivate void OnRunCallback(\n#if !STDCALL\n\t\t\tIntPtr thisptr,\n#endif\n\t\t\tIntPtr pvParam) {\n\t\t\ttry {\n\t\t\t\tm_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)));\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tCallbackDispatcher.ExceptionHandler(e);\n\t\t\t}\n\t\t}\n\n\t\t// Shouldn't ever get called here, but this is what C++ Steamworks does!\n\t\tprivate void OnRunCallResult(\n#if !STDCALL\n\t\t\tIntPtr thisptr,\n#endif\n\t\t\tIntPtr pvParam, bool bFailed, ulong hSteamAPICall) {\n\t\t\ttry { \n\t\t\t\tm_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)));\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tCallbackDispatcher.ExceptionHandler(e);\n\t\t\t}\n\t\t}\n\n\t\tprivate int OnGetCallbackSizeBytes(\n#if !STDCALL\n\t\t\tIntPtr thisptr\n#endif\n\t\t\t) {\n\t\t\treturn m_size;\n\t\t}\n\n\t\t// Steamworks.NET Specific\n\t\tprivate void BuildCCallbackBase() {\n\t\t\tm_CallbackBaseVTable = new CCallbackBaseVTable() {\n\t\t\t\tm_RunCallResult = OnRunCallResult,\n\t\t\t\tm_RunCallback = OnRunCallback,\n\t\t\t\tm_GetCallbackSizeBytes = OnGetCallbackSizeBytes\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CCallbackBaseVTable)));\n\t\t\tMarshal.StructureToPtr(m_CallbackBaseVTable, m_pVTable, false);\n\n\t\t\tm_CCallbackBase = new CCallbackBase() {\n\t\t\t\tm_vfptr = m_pVTable,\n\t\t\t\tm_nCallbackFlags = 0,\n\t\t\t\tm_iCallback = CallbackIdentities.GetCallbackIdentity(typeof(T))\n\t\t\t};\n\t\t\tm_pCCallbackBase = GCHandle.Alloc(m_CCallbackBase, GCHandleType.Pinned);\n\t\t}\n\t}\n\n\tpublic sealed class CallResult<T> : IDisposable {\n\t\tprivate CCallbackBaseVTable m_CallbackBaseVTable;\n\t\tprivate IntPtr m_pVTable = IntPtr.Zero;\n\t\tprivate CCallbackBase m_CCallbackBase;\n\t\tprivate GCHandle m_pCCallbackBase;\n\n\t\tpublic delegate void APIDispatchDelegate(T param, bool bIOFailure);\n\t\tprivate event APIDispatchDelegate m_Func;\n\n\t\tprivate SteamAPICall_t m_hAPICall = SteamAPICall_t.Invalid;\n\t\tpublic SteamAPICall_t Handle { get { return m_hAPICall; } }\n\n\t\tprivate readonly int m_size = Marshal.SizeOf(typeof(T));\n\n\t\tprivate bool m_bDisposed = false;\n\n\t\t/// <summary>\n\t\t/// Creates a new async CallResult. You must be calling SteamAPI.RunCallbacks() to retrieve the callback.\n\t\t/// <para>Returns a handle to the CallResult.</para>\n\t\t/// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>\n\t\t/// </summary>\n\t\tpublic static CallResult<T> Create(APIDispatchDelegate func = null) {\n\t\t\treturn new CallResult<T>(func);\n\t\t}\n\n\t\tpublic CallResult(APIDispatchDelegate func = null) {\n\t\t\tm_Func = func;\n\t\t\tBuildCCallbackBase();\n\t\t}\n\n\t\t~CallResult() {\n\t\t\tDispose();\n\t\t}\n\n\t\tpublic void Dispose() {\n\t\t\tif (m_bDisposed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tGC.SuppressFinalize(this);\n\n\t\t\tCancel();\n\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pCCallbackBase.IsAllocated) {\n\t\t\t\tm_pCCallbackBase.Free();\n\t\t\t}\n\n\t\t\tm_bDisposed = true;\n\t\t}\n\n\t\tpublic void Set(SteamAPICall_t hAPICall, APIDispatchDelegate func = null) {\n\t\t\t// Unlike the official SDK we let the user assign a single function during creation,\n\t\t\t// and allow them to skip having to do so every time that they call .Set()\n\t\t\tif (func != null) {\n\t\t\t\tm_Func = func;\n\t\t\t}\n\n\t\t\tif (m_Func == null) {\n\t\t\t\tthrow new Exception(\"CallResult function was null, you must either set it in the CallResult Constructor or via Set()\");\n\t\t\t}\n\n\t\t\tif (m_hAPICall != SteamAPICall_t.Invalid) {\n\t\t\t\tNativeMethods.SteamAPI_UnregisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)m_hAPICall);\n\t\t\t}\n\n\t\t\tm_hAPICall = hAPICall;\n\n\t\t\tif (hAPICall != SteamAPICall_t.Invalid) {\n\t\t\t\tNativeMethods.SteamAPI_RegisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)hAPICall);\n\t\t\t}\n\t\t}\n\n\t\tpublic bool IsActive() {\n\t\t\treturn (m_hAPICall != SteamAPICall_t.Invalid);\n\t\t}\n\n\t\tpublic void Cancel() {\n\t\t\tif (m_hAPICall != SteamAPICall_t.Invalid) {\n\t\t\t\tNativeMethods.SteamAPI_UnregisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)m_hAPICall);\n\t\t\t\tm_hAPICall = SteamAPICall_t.Invalid;\n\t\t\t}\n\t\t}\n\n\t\tpublic void SetGameserverFlag() {\n\t\t\tm_CCallbackBase.m_nCallbackFlags |= CCallbackBase.k_ECallbackFlagsGameServer;\n\t\t}\n\n\t\t// Shouldn't ever get called here, but this is what C++ Steamworks does!\n\t\tprivate void OnRunCallback(\n#if !STDCALL\n\t\t\tIntPtr thisptr,\n#endif\n\t\t\tIntPtr pvParam) {\n\t\t\tm_hAPICall = SteamAPICall_t.Invalid; // Caller unregisters for us\n\n\t\t\ttry {\n\t\t\t\tm_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)), false);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tCallbackDispatcher.ExceptionHandler(e);\n\t\t\t}\n\t\t}\n\n\t\tprivate void OnRunCallResult(\n#if !STDCALL\n\t\t\tIntPtr thisptr,\n#endif\n\t\t\tIntPtr pvParam, bool bFailed, ulong hSteamAPICall_) {\n\t\t\tSteamAPICall_t hSteamAPICall = (SteamAPICall_t)hSteamAPICall_;\n\t\t\tif (hSteamAPICall == m_hAPICall) {\n\t\t\t\tm_hAPICall = SteamAPICall_t.Invalid; // Caller unregisters for us\n\n\t\t\t\ttry {\n\t\t\t\t\tm_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)), bFailed);\n\t\t\t\t}\n\t\t\t\tcatch (Exception e) {\n\t\t\t\t\tCallbackDispatcher.ExceptionHandler(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate int OnGetCallbackSizeBytes(\n#if !STDCALL\n\t\t\tIntPtr thisptr\n#endif\n\t\t\t) {\n\t\t\treturn m_size;\n\t\t}\n\n\t\t// Steamworks.NET Specific\n\t\tprivate void BuildCCallbackBase() {\n\t\t\tm_CallbackBaseVTable = new CCallbackBaseVTable() {\n\t\t\t\tm_RunCallback = OnRunCallback,\n\t\t\t\tm_RunCallResult = OnRunCallResult,\n\t\t\t\tm_GetCallbackSizeBytes = OnGetCallbackSizeBytes\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CCallbackBaseVTable)));\n\t\t\tMarshal.StructureToPtr(m_CallbackBaseVTable, m_pVTable, false);\n\n\t\t\tm_CCallbackBase = new CCallbackBase() {\n\t\t\t\tm_vfptr = m_pVTable,\n\t\t\t\tm_nCallbackFlags = 0,\n\t\t\t\tm_iCallback = CallbackIdentities.GetCallbackIdentity(typeof(T))\n\t\t\t};\n\t\t\tm_pCCallbackBase = GCHandle.Alloc(m_CCallbackBase, GCHandleType.Pinned);\n\t\t}\n\t}\n\n\t[StructLayout(LayoutKind.Sequential)]\n\tinternal class CCallbackBase {\n\t\tpublic const byte k_ECallbackFlagsRegistered = 0x01;\n\t\tpublic const byte k_ECallbackFlagsGameServer = 0x02;\n\n\t\tpublic IntPtr m_vfptr;\n\t\tpublic byte m_nCallbackFlags;\n\t\tpublic int m_iCallback;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential)]\n\tinternal class CCallbackBaseVTable {\n#if STDCALL\n\t\tprivate const CallingConvention cc = CallingConvention.StdCall;\n\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate void RunCBDel(IntPtr pvParam);\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate void RunCRDel(IntPtr pvParam, [MarshalAs(UnmanagedType.I1)] bool bIOFailure, ulong hSteamAPICall);\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate int GetCallbackSizeBytesDel();\n#else\n\t#if THISCALL\n\t\tprivate const CallingConvention cc = CallingConvention.ThisCall;\n\t#else\n\t\tprivate const CallingConvention cc = CallingConvention.Cdecl;\n\t#endif\n\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate void RunCBDel(IntPtr thisptr, IntPtr pvParam);\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate void RunCRDel(IntPtr thisptr, IntPtr pvParam, [MarshalAs(UnmanagedType.I1)] bool bIOFailure, ulong hSteamAPICall);\n\t\t[UnmanagedFunctionPointer(cc)]\n\t\tpublic delegate int GetCallbackSizeBytesDel(IntPtr thisptr);\n#endif\n\n\t\t// RunCallback and RunCallResult are swapped in MSVC ABI\n#if WINDOWS_BUILD\n\t\t[NonSerialized]\n\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\tpublic RunCRDel m_RunCallResult;\n#endif\n\t\t[NonSerialized]\n\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\tpublic RunCBDel m_RunCallback;\n#if !WINDOWS_BUILD\n\t\t[NonSerialized]\n\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\tpublic RunCRDel m_RunCallResult;\n#endif\n\t\t[NonSerialized]\n\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\tpublic GetCallbackSizeBytesDel m_GetCallbackSizeBytes;\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/CallbackIdentity.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nnamespace Steamworks {\n\tclass CallbackIdentities {\n\t\tpublic static int GetCallbackIdentity(System.Type callbackStruct) {\n#if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX\n\t\t\tforeach (CallbackIdentityAttribute attribute in callbackStruct.GetCustomAttributes(typeof(CallbackIdentityAttribute), false)) {\n\t\t\t\treturn attribute.Identity;\n\t\t\t}\n#endif\n\t\t\tthrow new System.Exception(\"Callback number not found for struct \" + callbackStruct);\n\t\t}\n\t}\n\n\t[System.AttributeUsage(System.AttributeTargets.Struct, AllowMultiple = false)]\n\tinternal class CallbackIdentityAttribute : System.Attribute {\n\t\tpublic int Identity { get; set; }\n\t\tpublic CallbackIdentityAttribute(int callbackNum) {\n\t\t\tIdentity = callbackNum;\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/ISteamMatchmakingResponses.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\n// Unity 32bit Mono on Windows crashes with ThisCall for some reason, StdCall without the 'this' ptr is the only thing that works..?\n#if (UNITY_EDITOR_WIN && !UNITY_EDITOR_64) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN && !UNITY_64)\n\t#define NOTHISPTR\n#endif\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace Steamworks {\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback interface for receiving responses after a server list refresh\n\t// or an individual server update.\n\t//\n\t// Since you get these callbacks after requesting full list refreshes you will\n\t// usually implement this interface inside an object like CServerBrowser.  If that\n\t// object is getting destructed you should use ISteamMatchMakingServers()->CancelQuery()\n\t// to cancel any in-progress queries so you don't get a callback into the destructed\n\t// object and crash.\n\t//-----------------------------------------------------------------------------\n\tpublic class ISteamMatchmakingServerListResponse {\n\t\t// Server has responded ok with updated data\n\t\tpublic delegate void ServerResponded(HServerListRequest hRequest, int iServer);\n\t\t// Server has failed to respond\n\t\tpublic delegate void ServerFailedToRespond(HServerListRequest hRequest, int iServer);\n\t\t// A list refresh you had initiated is now 100% completed\n\t\tpublic delegate void RefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response);\n\n\t\tprivate VTable m_VTable;\n\t\tprivate IntPtr m_pVTable;\n\t\tprivate GCHandle m_pGCHandle;\n\t\tprivate ServerResponded m_ServerResponded;\n\t\tprivate ServerFailedToRespond m_ServerFailedToRespond;\n\t\tprivate RefreshComplete m_RefreshComplete;\n\n\t\tpublic ISteamMatchmakingServerListResponse(ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond, RefreshComplete onRefreshComplete) {\n\t\t\tif (onServerResponded == null || onServerFailedToRespond == null || onRefreshComplete == null) {\n\t\t\t\tthrow new ArgumentNullException();\n\t\t\t}\n\t\t\tm_ServerResponded = onServerResponded;\n\t\t\tm_ServerFailedToRespond = onServerFailedToRespond;\n\t\t\tm_RefreshComplete = onRefreshComplete;\n\n\t\t\tm_VTable = new VTable() {\n\t\t\t\tm_VTServerResponded = InternalOnServerResponded,\n\t\t\t\tm_VTServerFailedToRespond = InternalOnServerFailedToRespond,\n\t\t\t\tm_VTRefreshComplete = InternalOnRefreshComplete\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));\n\t\t\tMarshal.StructureToPtr(m_VTable, m_pVTable, false);\n\n\t\t\tm_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);\n\t\t}\n\n\t\t~ISteamMatchmakingServerListResponse() {\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pGCHandle.IsAllocated) {\n\t\t\t\tm_pGCHandle.Free();\n\t\t\t}\n\t\t}\n\t\t\n#if NOTHISPTR\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tprivate delegate void InternalServerResponded(HServerListRequest hRequest, int iServer);\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tprivate delegate void InternalServerFailedToRespond(HServerListRequest hRequest, int iServer);\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tprivate delegate void InternalRefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response);\n\t\tprivate void InternalOnServerResponded(HServerListRequest hRequest, int iServer) {\n\t\t\tm_ServerResponded(hRequest, iServer);\n\t\t}\n\t\tprivate void InternalOnServerFailedToRespond(HServerListRequest hRequest, int iServer) {\n\t\t\tm_ServerFailedToRespond(hRequest, iServer);\n\t\t}\n\t\tprivate void InternalOnRefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response) {\n\t\t\tm_RefreshComplete(hRequest, response);\n\t\t}\n#else\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tprivate delegate void InternalServerResponded(IntPtr thisptr, HServerListRequest hRequest, int iServer);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tprivate delegate void InternalServerFailedToRespond(IntPtr thisptr, HServerListRequest hRequest, int iServer);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tprivate delegate void InternalRefreshComplete(IntPtr thisptr, HServerListRequest hRequest, EMatchMakingServerResponse response);\n\t\tprivate void InternalOnServerResponded(IntPtr thisptr, HServerListRequest hRequest, int iServer) {\n\t\t\tm_ServerResponded(hRequest, iServer);\n\t\t}\n\t\tprivate void InternalOnServerFailedToRespond(IntPtr thisptr, HServerListRequest hRequest, int iServer) {\n\t\t\tm_ServerFailedToRespond(hRequest, iServer);\n\t\t}\n\t\tprivate void InternalOnRefreshComplete(IntPtr thisptr, HServerListRequest hRequest, EMatchMakingServerResponse response) {\n\t\t\tm_RefreshComplete(hRequest, response);\n\t\t}\n#endif\n\n\t\t[StructLayout(LayoutKind.Sequential)]\n\t\tprivate class VTable {\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalServerResponded m_VTServerResponded;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalServerFailedToRespond m_VTServerFailedToRespond;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalRefreshComplete m_VTRefreshComplete;\n\t\t}\n\n\t\tpublic static explicit operator System.IntPtr(ISteamMatchmakingServerListResponse that) {\n\t\t\treturn that.m_pGCHandle.AddrOfPinnedObject();\n\t\t}\n\t};\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback interface for receiving responses after pinging an individual server \n\t//\n\t// These callbacks all occur in response to querying an individual server\n\t// via the ISteamMatchmakingServers()->PingServer() call below.  If you are \n\t// destructing an object that implements this interface then you should call \n\t// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query\n\t// which is in progress.  Failure to cancel in progress queries when destructing\n\t// a callback handler may result in a crash when a callback later occurs.\n\t//-----------------------------------------------------------------------------\n\tpublic class ISteamMatchmakingPingResponse {\n\t\t// Server has responded successfully and has updated data\n\t\tpublic delegate void ServerResponded(gameserveritem_t server);\n\n\t\t// Server failed to respond to the ping request\n\t\tpublic delegate void ServerFailedToRespond();\n\n\t\tprivate VTable m_VTable;\n\t\tprivate IntPtr m_pVTable;\n\t\tprivate GCHandle m_pGCHandle;\n\t\tprivate ServerResponded m_ServerResponded;\n\t\tprivate ServerFailedToRespond m_ServerFailedToRespond;\n\n\t\tpublic ISteamMatchmakingPingResponse(ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond) {\n\t\t\tif (onServerResponded == null || onServerFailedToRespond == null) {\n\t\t\t\tthrow new ArgumentNullException();\n\t\t\t}\n\t\t\tm_ServerResponded = onServerResponded;\n\t\t\tm_ServerFailedToRespond = onServerFailedToRespond;\n\n\t\t\tm_VTable = new VTable() {\n\t\t\t\tm_VTServerResponded = InternalOnServerResponded,\n\t\t\t\tm_VTServerFailedToRespond = InternalOnServerFailedToRespond,\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));\n\t\t\tMarshal.StructureToPtr(m_VTable, m_pVTable, false);\n\n\t\t\tm_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);\n\t\t}\n\n\t\t~ISteamMatchmakingPingResponse() {\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pGCHandle.IsAllocated) {\n\t\t\t\tm_pGCHandle.Free();\n\t\t\t}\n\t\t}\n\n#if NOTHISPTR\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tprivate delegate void InternalServerResponded(gameserveritem_t server);\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tprivate delegate void InternalServerFailedToRespond();\n\t\tprivate void InternalOnServerResponded(gameserveritem_t server) {\n\t\t\tm_ServerResponded(server);\n\t\t}\n\t\tprivate void InternalOnServerFailedToRespond() {\n\t\t\tm_ServerFailedToRespond();\n\t\t}\n#else\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tprivate delegate void InternalServerResponded(IntPtr thisptr, gameserveritem_t server);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tprivate delegate void InternalServerFailedToRespond(IntPtr thisptr);\n\t\tprivate void InternalOnServerResponded(IntPtr thisptr, gameserveritem_t server) {\n\t\t\tm_ServerResponded(server);\n\t\t}\n\t\tprivate void InternalOnServerFailedToRespond(IntPtr thisptr) {\n\t\t\tm_ServerFailedToRespond();\n\t\t}\n#endif\n\n\t\t[StructLayout(LayoutKind.Sequential)]\n\t\tprivate class VTable {\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalServerResponded m_VTServerResponded;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalServerFailedToRespond m_VTServerFailedToRespond;\n\t\t}\n\n\t\tpublic static explicit operator System.IntPtr(ISteamMatchmakingPingResponse that) {\n\t\t\treturn that.m_pGCHandle.AddrOfPinnedObject();\n\t\t}\n\t};\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback interface for receiving responses after requesting details on\n\t// who is playing on a particular server.\n\t//\n\t// These callbacks all occur in response to querying an individual server\n\t// via the ISteamMatchmakingServers()->PlayerDetails() call below.  If you are \n\t// destructing an object that implements this interface then you should call \n\t// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query\n\t// which is in progress.  Failure to cancel in progress queries when destructing\n\t// a callback handler may result in a crash when a callback later occurs.\n\t//-----------------------------------------------------------------------------\n\tpublic class ISteamMatchmakingPlayersResponse {\n\t\t// Got data on a new player on the server -- you'll get this callback once per player\n\t\t// on the server which you have requested player data on.\n\t\tpublic delegate void AddPlayerToList(string pchName, int nScore, float flTimePlayed);\n\n\t\t// The server failed to respond to the request for player details\n\t\tpublic delegate void PlayersFailedToRespond();\n\n\t\t// The server has finished responding to the player details request \n\t\t// (ie, you won't get anymore AddPlayerToList callbacks)\n\t\tpublic delegate void PlayersRefreshComplete();\n\n\t\tprivate VTable m_VTable;\n\t\tprivate IntPtr m_pVTable;\n\t\tprivate GCHandle m_pGCHandle;\n\t\tprivate AddPlayerToList m_AddPlayerToList;\n\t\tprivate PlayersFailedToRespond m_PlayersFailedToRespond;\n\t\tprivate PlayersRefreshComplete m_PlayersRefreshComplete;\n\n\t\tpublic ISteamMatchmakingPlayersResponse(AddPlayerToList onAddPlayerToList, PlayersFailedToRespond onPlayersFailedToRespond, PlayersRefreshComplete onPlayersRefreshComplete) {\n\t\t\tif (onAddPlayerToList == null || onPlayersFailedToRespond == null || onPlayersRefreshComplete == null) {\n\t\t\t\tthrow new ArgumentNullException();\n\t\t\t}\n\t\t\tm_AddPlayerToList = onAddPlayerToList;\n\t\t\tm_PlayersFailedToRespond = onPlayersFailedToRespond;\n\t\t\tm_PlayersRefreshComplete = onPlayersRefreshComplete;\n\t\t\t\n\t\t\tm_VTable = new VTable() {\n\t\t\t\tm_VTAddPlayerToList = InternalOnAddPlayerToList,\n\t\t\t\tm_VTPlayersFailedToRespond = InternalOnPlayersFailedToRespond,\n\t\t\t\tm_VTPlayersRefreshComplete = InternalOnPlayersRefreshComplete\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));\n\t\t\tMarshal.StructureToPtr(m_VTable, m_pVTable, false);\n\n\t\t\tm_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);\n\t\t}\n\n\t\t~ISteamMatchmakingPlayersResponse() {\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pGCHandle.IsAllocated) {\n\t\t\t\tm_pGCHandle.Free();\n\t\t\t}\n\t\t}\n\t\t\n#if NOTHISPTR\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalAddPlayerToList(IntPtr pchName, int nScore, float flTimePlayed);\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalPlayersFailedToRespond();\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalPlayersRefreshComplete();\n\t\tprivate void InternalOnAddPlayerToList(IntPtr pchName, int nScore, float flTimePlayed) {\n\t\t\tm_AddPlayerToList(InteropHelp.PtrToStringUTF8(pchName), nScore, flTimePlayed);\n\t\t}\n\t\tprivate void InternalOnPlayersFailedToRespond() {\n\t\t\tm_PlayersFailedToRespond();\n\t\t}\n\t\tprivate void InternalOnPlayersRefreshComplete() {\n\t\t\tm_PlayersRefreshComplete();\n\t\t}\n#else\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalPlayersFailedToRespond(IntPtr thisptr);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalPlayersRefreshComplete(IntPtr thisptr);\n\t\tprivate void InternalOnAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed) {\n\t\t\tm_AddPlayerToList(InteropHelp.PtrToStringUTF8(pchName), nScore, flTimePlayed);\n\t\t}\n\t\tprivate void InternalOnPlayersFailedToRespond(IntPtr thisptr) {\n\t\t\tm_PlayersFailedToRespond();\n\t\t}\n\t\tprivate void InternalOnPlayersRefreshComplete(IntPtr thisptr) {\n\t\t\tm_PlayersRefreshComplete();\n\t\t}\n#endif\n\n\t\t[StructLayout(LayoutKind.Sequential)]\n\t\tprivate class VTable {\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalAddPlayerToList m_VTAddPlayerToList;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalPlayersFailedToRespond m_VTPlayersFailedToRespond;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalPlayersRefreshComplete m_VTPlayersRefreshComplete;\n\t\t}\n\n\t\tpublic static explicit operator System.IntPtr(ISteamMatchmakingPlayersResponse that) {\n\t\t\treturn that.m_pGCHandle.AddrOfPinnedObject();\n\t\t}\n\t};\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback interface for receiving responses after requesting rules\n\t// details on a particular server.\n\t//\n\t// These callbacks all occur in response to querying an individual server\n\t// via the ISteamMatchmakingServers()->ServerRules() call below.  If you are \n\t// destructing an object that implements this interface then you should call \n\t// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query\n\t// which is in progress.  Failure to cancel in progress queries when destructing\n\t// a callback handler may result in a crash when a callback later occurs.\n\t//-----------------------------------------------------------------------------\n\tpublic class ISteamMatchmakingRulesResponse {\n\t\t// Got data on a rule on the server -- you'll get one of these per rule defined on\n\t\t// the server you are querying\n\t\tpublic delegate void RulesResponded(string pchRule, string pchValue);\n\n\t\t// The server failed to respond to the request for rule details\n\t\tpublic delegate void RulesFailedToRespond();\n\n\t\t// The server has finished responding to the rule details request \n\t\t// (ie, you won't get anymore RulesResponded callbacks)\n\t\tpublic delegate void RulesRefreshComplete();\n\n\t\tprivate VTable m_VTable;\n\t\tprivate IntPtr m_pVTable;\n\t\tprivate GCHandle m_pGCHandle;\n\t\tprivate RulesResponded m_RulesResponded;\n\t\tprivate RulesFailedToRespond m_RulesFailedToRespond;\n\t\tprivate RulesRefreshComplete m_RulesRefreshComplete;\n\n\t\tpublic ISteamMatchmakingRulesResponse(RulesResponded onRulesResponded, RulesFailedToRespond onRulesFailedToRespond, RulesRefreshComplete onRulesRefreshComplete) {\n\t\t\tif (onRulesResponded == null || onRulesFailedToRespond == null || onRulesRefreshComplete == null) {\n\t\t\t\tthrow new ArgumentNullException();\n\t\t\t}\n\t\t\tm_RulesResponded = onRulesResponded;\n\t\t\tm_RulesFailedToRespond = onRulesFailedToRespond;\n\t\t\tm_RulesRefreshComplete = onRulesRefreshComplete;\n\n\t\t\tm_VTable = new VTable() {\n\t\t\t\tm_VTRulesResponded = InternalOnRulesResponded,\n\t\t\t\tm_VTRulesFailedToRespond = InternalOnRulesFailedToRespond,\n\t\t\t\tm_VTRulesRefreshComplete = InternalOnRulesRefreshComplete\n\t\t\t};\n\t\t\tm_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));\n\t\t\tMarshal.StructureToPtr(m_VTable, m_pVTable, false);\n\n\t\t\tm_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);\n\t\t}\n\n\t\t~ISteamMatchmakingRulesResponse() {\n\t\t\tif (m_pVTable != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pVTable);\n\t\t\t}\n\n\t\t\tif (m_pGCHandle.IsAllocated) {\n\t\t\t\tm_pGCHandle.Free();\n\t\t\t}\n\t\t}\n\t\t\n#if NOTHISPTR\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalRulesResponded(IntPtr pchRule, IntPtr pchValue);\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalRulesFailedToRespond();\n\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]\n\t\tpublic delegate void InternalRulesRefreshComplete();\n\t\tprivate void InternalOnRulesResponded(IntPtr pchRule, IntPtr pchValue) {\n\t\t\tm_RulesResponded(InteropHelp.PtrToStringUTF8(pchRule), InteropHelp.PtrToStringUTF8(pchValue));\n\t\t}\n\t\tprivate void InternalOnRulesFailedToRespond() {\n\t\t\tm_RulesFailedToRespond();\n\t\t}\n\t\tprivate void InternalOnRulesRefreshComplete() {\n\t\t\tm_RulesRefreshComplete();\n\t\t}\n#else\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalRulesFailedToRespond(IntPtr thisptr);\n\t\t[UnmanagedFunctionPointer(CallingConvention.ThisCall)]\n\t\tpublic delegate void InternalRulesRefreshComplete(IntPtr thisptr);\n\t\tprivate void InternalOnRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue) {\n\t\t\tm_RulesResponded(InteropHelp.PtrToStringUTF8(pchRule), InteropHelp.PtrToStringUTF8(pchValue));\n\t\t}\n\t\tprivate void InternalOnRulesFailedToRespond(IntPtr thisptr) {\n\t\t\tm_RulesFailedToRespond();\n\t\t}\n\t\tprivate void InternalOnRulesRefreshComplete(IntPtr thisptr) {\n\t\t\tm_RulesRefreshComplete();\n\t\t}\n#endif\n\n\t\t[StructLayout(LayoutKind.Sequential)]\n\t\tprivate class VTable {\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalRulesResponded m_VTRulesResponded;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalRulesFailedToRespond m_VTRulesFailedToRespond;\n\n\t\t\t[NonSerialized]\n\t\t\t[MarshalAs(UnmanagedType.FunctionPtr)]\n\t\t\tpublic InternalRulesRefreshComplete m_VTRulesRefreshComplete;\n\t\t}\n\n\t\tpublic static explicit operator System.IntPtr(ISteamMatchmakingRulesResponse that) {\n\t\t\treturn that.m_pGCHandle.AddrOfPinnedObject();\n\t\t}\n\t};\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/InteropHelp.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nusing System.Text;\n\nnamespace Steamworks {\n\tpublic class InteropHelp {\n\t\tpublic static void TestIfPlatformSupported() {\n#if !UNITY_EDITOR && !UNITY_STANDALONE && !STEAMWORKS_WIN && !STEAMWORKS_LIN_OSX\n\t\t\tthrow new System.InvalidOperationException(\"Steamworks functions can only be called on platforms that Steam is available on.\");\n#endif\n\t\t}\n\n\t\tpublic static void TestIfAvailableClient() {\n\t\t\tTestIfPlatformSupported();\n\t\t\tif (CSteamAPIContext.GetSteamClient() == System.IntPtr.Zero) {\n\t\t\t\tif (!CSteamAPIContext.Init()) {\n\t\t\t\t\tthrow new System.InvalidOperationException(\"Steamworks is not initialized.\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic static void TestIfAvailableGameServer() {\n\t\t\tTestIfPlatformSupported();\n\t\t\tif (CSteamGameServerAPIContext.GetSteamClient() == System.IntPtr.Zero) {\n\t\t\t\tif (!CSteamGameServerAPIContext.Init()) {\n\t\t\t\t\tthrow new System.InvalidOperationException(\"Steamworks GameServer is not initialized.\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// This continues to exist for both 'out string' and strings returned by Steamworks functions.\n\t\tpublic static string PtrToStringUTF8(IntPtr nativeUtf8) {\n\t\t\tif (nativeUtf8 == IntPtr.Zero) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tint len = 0;\n\n\t\t\twhile (Marshal.ReadByte(nativeUtf8, len) != 0) {\n\t\t\t\t++len;\n\t\t\t}\n\n\t\t\tif (len == 0) {\n\t\t\t\treturn string.Empty;\n\t\t\t}\n\n\t\t\tbyte[] buffer = new byte[len];\n\t\t\tMarshal.Copy(nativeUtf8, buffer, 0, buffer.Length);\n\t\t\treturn Encoding.UTF8.GetString(buffer);\n\t\t}\n\n\t\t// This is for 'const char *' arguments which we need to ensure do not get GC'd while Steam is using them.\n\t\t// We can't use an ICustomMarshaler because Unity crashes when a string between 96 and 127 characters long is defined/initialized at the top of class scope...\n#if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX\n\t\tpublic class UTF8StringHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid {\n\t\t\tpublic UTF8StringHandle(string str)\n\t\t\t\t: base(true) {\n\t\t\t\tif (str == null) {\n\t\t\t\t\tSetHandle(IntPtr.Zero);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// +1 for '\\0'\n\t\t\t\tbyte[] strbuf = new byte[Encoding.UTF8.GetByteCount(str) + 1];\n\t\t\t\tEncoding.UTF8.GetBytes(str, 0, str.Length, strbuf, 0);\n\t\t\t\tIntPtr buffer = Marshal.AllocHGlobal(strbuf.Length);\n\t\t\t\tMarshal.Copy(strbuf, 0, buffer, strbuf.Length);\n\n\t\t\t\tSetHandle(buffer);\n\t\t\t}\n\n\t\t\tprotected override bool ReleaseHandle() {\n\t\t\t\tif (!IsInvalid) {\n\t\t\t\t\tMarshal.FreeHGlobal(handle);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n#else\n\t\tpublic class UTF8StringHandle : IDisposable {\n\t\t\tpublic UTF8StringHandle(string str) { }\n\t\t\tpublic void Dispose() {}\n\t\t}\n#endif\n\n\t\t// TODO - Should be IDisposable\n\t\t// We can't use an ICustomMarshaler because Unity dies when MarshalManagedToNative() gets called with a generic type.\n\t\tpublic class SteamParamStringArray {\n\t\t\t// The pointer to each AllocHGlobal() string\n\t\t\tIntPtr[] m_Strings;\n\t\t\t// The pointer to the condensed version of m_Strings\n\t\t\tIntPtr m_ptrStrings;\n\t\t\t// The pointer to the StructureToPtr version of SteamParamStringArray_t that will get marshaled\n\t\t\tIntPtr m_pSteamParamStringArray;\n\n\t\t\tpublic SteamParamStringArray(System.Collections.Generic.IList<string> strings) {\n\t\t\t\tif (strings == null) {\n\t\t\t\t\tm_pSteamParamStringArray = IntPtr.Zero;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tm_Strings = new IntPtr[strings.Count];\n\t\t\t\tfor (int i = 0; i < strings.Count; ++i) {\n\t\t\t\t\tbyte[] strbuf = new byte[Encoding.UTF8.GetByteCount(strings[i]) + 1];\n\t\t\t\t\tEncoding.UTF8.GetBytes(strings[i], 0, strings[i].Length, strbuf, 0);\n\t\t\t\t\tm_Strings[i] = Marshal.AllocHGlobal(strbuf.Length);\n\t\t\t\t\tMarshal.Copy(strbuf, 0, m_Strings[i], strbuf.Length);\n\t\t\t\t}\n\n\t\t\t\tm_ptrStrings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * m_Strings.Length);\n\t\t\t\tSteamParamStringArray_t stringArray = new SteamParamStringArray_t() {\n\t\t\t\t\tm_ppStrings = m_ptrStrings,\n\t\t\t\t\tm_nNumStrings = m_Strings.Length\n\t\t\t\t};\n\t\t\t\tMarshal.Copy(m_Strings, 0, stringArray.m_ppStrings, m_Strings.Length);\n\n\t\t\t\tm_pSteamParamStringArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SteamParamStringArray_t)));\n\t\t\t\tMarshal.StructureToPtr(stringArray, m_pSteamParamStringArray, false);\n\t\t\t}\n\n\t\t\t~SteamParamStringArray() {\n\t\t\t\tforeach (IntPtr ptr in m_Strings) {\n\t\t\t\t\tMarshal.FreeHGlobal(ptr);\n\t\t\t\t}\n\n\t\t\t\tif (m_ptrStrings != IntPtr.Zero) {\n\t\t\t\t\tMarshal.FreeHGlobal(m_ptrStrings);\n\t\t\t\t}\n\n\t\t\t\tif (m_pSteamParamStringArray != IntPtr.Zero) {\n\t\t\t\t\tMarshal.FreeHGlobal(m_pSteamParamStringArray);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic static implicit operator IntPtr(SteamParamStringArray that) {\n\t\t\t\treturn that.m_pSteamParamStringArray;\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO - Should be IDisposable\n\t// MatchMaking Key-Value Pair Marshaller\n\tpublic class MMKVPMarshaller {\n\t\tprivate IntPtr m_pNativeArray;\n\t\tprivate IntPtr m_pArrayEntries;\n\n\t\tpublic MMKVPMarshaller(MatchMakingKeyValuePair_t[] filters) {\n\t\t\tif (filters == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tint sizeOfMMKVP = Marshal.SizeOf(typeof(MatchMakingKeyValuePair_t));\n\n\t\t\tm_pNativeArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * filters.Length);\n\t\t\tm_pArrayEntries = Marshal.AllocHGlobal(sizeOfMMKVP * filters.Length);\n\t\t\tfor (int i = 0; i < filters.Length; ++i) {\n\t\t\t\tMarshal.StructureToPtr(filters[i], new IntPtr(m_pArrayEntries.ToInt64() + (i * sizeOfMMKVP)), false);\n\t\t\t}\n\n\t\t\tMarshal.WriteIntPtr(m_pNativeArray, m_pArrayEntries);\n\t\t}\n\n\t\t~MMKVPMarshaller() {\n\t\t\tif (m_pArrayEntries != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pArrayEntries);\n\t\t\t}\n\t\t\tif (m_pNativeArray != IntPtr.Zero) {\n\t\t\t\tMarshal.FreeHGlobal(m_pNativeArray);\n\t\t\t}\n\t\t}\n\n\t\tpublic static implicit operator IntPtr(MMKVPMarshaller that) {\n\t\t\treturn that.m_pNativeArray;\n\t\t}\n\t}\n\n\tpublic class DllCheck {\n#if DISABLED\n\t\t[DllImport(\"kernel32.dll\")]\n\t\tpublic static extern IntPtr GetModuleHandle(string lpModuleName);\n\n\t\t[DllImport(\"kernel32.dll\", CharSet = CharSet.Auto)]\n\t\textern static int GetModuleFileName(IntPtr hModule, StringBuilder strFullPath, int nSize);\n#endif\n\n\t\t/// <summary>\n\t\t/// This is an optional runtime check to ensure that the dlls are the correct version. Returns false only if the steam_api.dll is found and it's the wrong size or version number.\n\t\t/// </summary>\n\t\tpublic static bool Test() {\n#if DISABLED\n\t\t\tbool ret = CheckSteamAPIDLL();\n#endif\n\t\t\treturn true;\n\t\t}\n\n#if DISABLED\n\t\tprivate static bool CheckSteamAPIDLL() {\n\t\t\tstring fileName;\n\t\t\tint fileBytes;\n\t\t\tif (IntPtr.Size == 4) {\n\t\t\t\tfileName = \"steam_api.dll\";\n\t\t\t\tfileBytes = Version.SteamAPIDLLSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfileName = \"steam_api64.dll\";\n\t\t\t\tfileBytes = Version.SteamAPI64DLLSize;\n\t\t\t}\n\n\t\t\tIntPtr handle = GetModuleHandle(fileName);\n\t\t\tif (handle == IntPtr.Zero) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tStringBuilder filePath = new StringBuilder(256);\n\t\t\tGetModuleFileName(handle, filePath, filePath.Capacity);\n\t\t\tstring file = filePath.ToString();\n\n\t\t\t// If we can not find the file we'll just skip it and let the DllNotFoundException take care of it.\n\t\t\tif (System.IO.File.Exists(file)) {\n\t\t\t\tSystem.IO.FileInfo fInfo = new System.IO.FileInfo(file);\n\t\t\t\tif (fInfo.Length != fileBytes) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (System.Diagnostics.FileVersionInfo.GetVersionInfo(file).FileVersion != Version.SteamAPIDLLVersion) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n#endif\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/Packsize.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\n// If we're running in the Unity Editor we need the editors platform.\n#if UNITY_EDITOR_WIN\n\t#define VALVE_CALLBACK_PACK_LARGE\n#elif UNITY_EDITOR_OSX\n\t#define VALVE_CALLBACK_PACK_SMALL\n\n// Otherwise we want the target platform.\n#elif UNITY_STANDALONE_WIN || STEAMWORKS_WIN\n\t#define VALVE_CALLBACK_PACK_LARGE\n#elif UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_LIN_OSX\n\t#define VALVE_CALLBACK_PACK_SMALL\n\n// We do not want to throw a warning when we're building in Unity but for an unsupported platform. So we'll silently let this slip by.\n// It would be nice if Unity itself would define 'UNITY' or something like that...\n#elif UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_2017_1_OR_NEWER\n\t#define VALVE_CALLBACK_PACK_SMALL\n\n// But we do want to be explicit on the Standalone build for XNA/Monogame.\n#else\n\t#define VALVE_CALLBACK_PACK_LARGE\n\t#warning You need to define STEAMWORKS_WIN, or STEAMWORKS_LIN_OSX. Refer to the readme for more details.\n#endif\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class Packsize {\n#if VALVE_CALLBACK_PACK_LARGE\n\t\tpublic const int value = 8;\n#elif VALVE_CALLBACK_PACK_SMALL\n\t\tpublic const int value = 4;\n#endif\n\n\t\tpublic static bool Test() {\n\t\t\tint sentinelSize = Marshal.SizeOf(typeof(ValvePackingSentinel_t));\n\t\t\tint subscribedFilesSize = Marshal.SizeOf(typeof(RemoteStorageEnumerateUserSubscribedFilesResult_t));\n#if VALVE_CALLBACK_PACK_LARGE\n\t\t\tif (sentinelSize != 32 || subscribedFilesSize != (1 + 1 + 1 + 50 + 100) * 4 + 4)\n\t\t\t\treturn false;\n#elif VALVE_CALLBACK_PACK_SMALL\n\t\t\tif (sentinelSize != 24 || subscribedFilesSize != (1 + 1 + 1 + 50 + 100) * 4)\n\t\t\t\treturn false;\n#endif\n\t\t\treturn true;\n\t\t}\n\n\t\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t\tstruct ValvePackingSentinel_t {\n\t\t\tuint m_u32;\n\t\t\tulong m_u64;\n\t\t\tushort m_u16;\n\t\t\tdouble m_d;\n\t\t};\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/Steam.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class Version {\n\t\tpublic const string SteamworksNETVersion = \"13.0.0\";\n\t\tpublic const string SteamworksSDKVersion = \"1.46\";\n\t\tpublic const string SteamAPIDLLVersion = \"05.25.65.21\";\n\t\tpublic const int SteamAPIDLLSize = 259360;\n\t\tpublic const int SteamAPI64DLLSize = 289568;\n\t}\n\n\tpublic static class SteamAPI {\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\t\t//\tSteam API setup & shutdown\n\t\t//\n\t\t//\tThese functions manage loading, initializing and shutdown of the steamclient.dll\n\t\t//\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\n\t\t// SteamAPI_Init must be called before using any other API functions. If it fails, an\n\t\t// error message will be output to the debugger (or stderr) with further information.\n\t\tpublic static bool Init() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\n\t\t\tbool ret = NativeMethods.SteamAPI_Init();\n\n\t\t\t// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it\n\t\t\t// every time that Unity reloads binaries, so we also check if the pointers are available and initialized\n\t\t\t// before each call to any interface functions. That is in InteropHelp.cs\n\t\t\tif (ret)\n\t\t\t{\n\t\t\t\tret = CSteamAPIContext.Init();\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static void Shutdown() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamAPI_Shutdown();\n\t\t}\n\n\t\t// SteamAPI_RestartAppIfNecessary ensures that your executable was launched through Steam.\n\t\t//\n\t\t// Returns true if the current process should terminate. Steam is now re-launching your application.\n\t\t//\n\t\t// Returns false if no action needs to be taken. This means that your executable was started through\n\t\t// the Steam client, or a steam_appid.txt file is present in your game's directory (for development).\n\t\t// Your current process should continue if false is returned.\n\t\t//\n\t\t// NOTE: If you use the Steam DRM wrapper on your primary executable file, this check is unnecessary\n\t\t// since the DRM wrapper will ensure that your application was launched properly through Steam.\n\t\tpublic static bool RestartAppIfNecessary(AppId_t unOwnAppID) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamAPI_RestartAppIfNecessary(unOwnAppID);\n\t\t}\n\n\t\t// Many Steam API functions allocate a small amount of thread-local memory for parameter storage.\n\t\t// SteamAPI_ReleaseCurrentThreadMemory() will free API memory associated with the calling thread.\n\t\t// This function is also called automatically by SteamAPI_RunCallbacks(), so a single-threaded\n\t\t// program never needs to explicitly call this function.\n\t\tpublic static void ReleaseCurrentThreadMemory() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamAPI_ReleaseCurrentThreadMemory();\n\t\t}\n\n\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\t\t//\tsteam callback and call-result helpers\n\t\t//\n\t\t//\tThe following macros and classes are used to register your application for\n\t\t//\tcallbacks and call-results, which are delivered in a predictable manner.\n\t\t//\n\t\t//\tSTEAM_CALLBACK macros are meant for use inside of a C++ class definition.\n\t\t//\tThey map a Steam notification callback directly to a class member function\n\t\t//\twhich is automatically prototyped as \"void func( callback_type *pParam )\".\n\t\t//\n\t\t//\tCCallResult is used with specific Steam APIs that return \"result handles\".\n\t\t//\tThe handle can be passed to a CCallResult object's Set function, along with\n\t\t//\tan object pointer and member-function pointer. The member function will\n\t\t//\tbe executed once the results of the Steam API call are available.\n\t\t//\n\t\t//\tCCallback and CCallbackManual classes can be used instead of STEAM_CALLBACK\n\t\t//\tmacros if you require finer control over registration and unregistration.\n\t\t//\n\t\t//\tCallbacks and call-results are queued automatically and are only\n\t\t//\tdelivered/executed when your application calls SteamAPI_RunCallbacks().\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\n\t\t// SteamAPI_RunCallbacks is safe to call from multiple threads simultaneously,\n\t\t// but if you choose to do this, callback code could be executed on any thread.\n\t\t// One alternative is to call SteamAPI_RunCallbacks from the main thread only,\n\t\t// and call SteamAPI_ReleaseCurrentThreadMemory regularly on other threads.\n\t\tpublic static void RunCallbacks() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamAPI_RunCallbacks();\n\t\t}\n\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\t\t//\tsteamclient.dll private wrapper functions\n\t\t//\n\t\t//\tThe following functions are part of abstracting API access to the steamclient.dll, but should only be used in very specific cases\n\t\t//----------------------------------------------------------------------------------------------------------------------------------------------------------//\n\n\t\t// SteamAPI_IsSteamRunning() returns true if Steam is currently running\n\t\tpublic static bool IsSteamRunning() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamAPI_IsSteamRunning();\n\t\t}\n\n\t\t// returns the HSteamUser of the last user to dispatch a callback\n\t\tpublic static HSteamUser GetHSteamUserCurrent() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (HSteamUser)NativeMethods.Steam_GetHSteamUserCurrent();\n\t\t}\n\n\t\t// returns the pipe we are communicating to Steam with\n\t\tpublic static HSteamPipe GetHSteamPipe() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (HSteamPipe)NativeMethods.SteamAPI_GetHSteamPipe();\n\t\t}\n\n\t\tpublic static HSteamUser GetHSteamUser() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (HSteamUser)NativeMethods.SteamAPI_GetHSteamUser();\n\t\t}\n\t}\n\n\tpublic static class GameServer {\n\t\t// Initialize ISteamGameServer interface object, and set server properties which may not be changed.\n\t\t//\n\t\t// After calling this function, you should set any additional server parameters, and then\n\t\t// call ISteamGameServer::LogOnAnonymous() or ISteamGameServer::LogOn()\n\t\t//\n\t\t// - usSteamPort is the local port used to communicate with the steam servers.\n\t\t// - usGamePort is the port that clients will connect to for gameplay.\n\t\t// - usQueryPort is the port that will manage server browser related duties and info\n\t\t//\t\tpings from clients.  If you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE for usQueryPort, then it\n\t\t//\t\twill use \"GameSocketShare\" mode, which means that the game is responsible for sending and receiving\n\t\t//\t\tUDP packets for the master  server updater. See references to GameSocketShare in isteamgameserver.h.\n\t\t// - The version string is usually in the form x.x.x.x, and is used by the master server to detect when the\n\t\t//\t\tserver is out of date.  (Only servers with the latest version will be listed.)\n\t\tpublic static bool Init(uint unIP, ushort usSteamPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\n\t\t\tbool ret;\n\t\t\tusing (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString)) {\n\t\t\t\tret = NativeMethods.SteamGameServer_Init(unIP, usSteamPort, usGamePort, usQueryPort, eServerMode, pchVersionString2);\n\t\t\t}\n\n\t\t\t// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it\n\t\t\t// every time that Unity reloads binaries, so we also check if the pointers are available and initialized\n\t\t\t// before each call to any interface functions. That is in InteropHelp.cs\n\t\t\tif (ret) {\n\t\t\t\tret = CSteamGameServerAPIContext.Init();\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static void Shutdown() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamGameServer_Shutdown();\n\t\t\tCSteamGameServerAPIContext.Clear();\n\t\t}\n\n\t\tpublic static void RunCallbacks() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamGameServer_RunCallbacks();\n\t\t}\n\n\t\t// Most Steam API functions allocate some amount of thread-local memory for\n\t\t// parameter storage. Calling SteamGameServer_ReleaseCurrentThreadMemory()\n\t\t// will free all API-related memory associated with the calling thread.\n\t\t// This memory is released automatically by SteamGameServer_RunCallbacks(),\n\t\t// so single-threaded servers do not need to explicitly call this function.\n\t\tpublic static void ReleaseCurrentThreadMemory() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamGameServer_ReleaseCurrentThreadMemory();\n\t\t}\n\n\t\tpublic static bool BSecure() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamGameServer_BSecure();\n\t\t}\n\n\t\tpublic static CSteamID GetSteamID() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (CSteamID)NativeMethods.SteamGameServer_GetSteamID();\n\t\t}\n\n\t\tpublic static HSteamPipe GetHSteamPipe() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (HSteamPipe)NativeMethods.SteamGameServer_GetHSteamPipe();\n\t\t}\n\n\t\tpublic static HSteamUser GetHSteamUser() {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn (HSteamUser)NativeMethods.SteamGameServer_GetHSteamUser();\n\t\t}\n\t}\n\n\tpublic static class SteamEncryptedAppTicket {\n\t\tpublic static bool BDecryptTicket(byte[] rgubTicketEncrypted, uint cubTicketEncrypted, byte[] rgubTicketDecrypted, ref uint pcubTicketDecrypted, byte[] rgubKey, int cubKey) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_BDecryptTicket(rgubTicketEncrypted, cubTicketEncrypted, rgubTicketDecrypted, ref pcubTicketDecrypted, rgubKey, cubKey);\n\t\t}\n\n\t\tpublic static bool BIsTicketForApp(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_BIsTicketForApp(rgubTicketDecrypted, cubTicketDecrypted, nAppID);\n\t\t}\n\n\t\tpublic static uint GetTicketIssueTime(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_GetTicketIssueTime(rgubTicketDecrypted, cubTicketDecrypted);\n\t\t}\n\n\t\tpublic static void GetTicketSteamID(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out CSteamID psteamID) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tNativeMethods.SteamEncryptedAppTicket_GetTicketSteamID(rgubTicketDecrypted, cubTicketDecrypted, out psteamID);\n\t\t}\n\n\t\tpublic static uint GetTicketAppID(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_GetTicketAppID(rgubTicketDecrypted, cubTicketDecrypted);\n\t\t}\n\n\t\tpublic static bool BUserOwnsAppInTicket(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_BUserOwnsAppInTicket(rgubTicketDecrypted, cubTicketDecrypted, nAppID);\n\t\t}\n\n\t\tpublic static bool BUserIsVacBanned(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_BUserIsVacBanned(rgubTicketDecrypted, cubTicketDecrypted);\n\t\t}\n\n\t\tpublic static byte[] GetUserVariableData(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out uint pcubUserData) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\tIntPtr punSecretData = NativeMethods.SteamEncryptedAppTicket_GetUserVariableData(rgubTicketDecrypted, cubTicketDecrypted, out pcubUserData);\n\t\t\tbyte[] ret = new byte[pcubUserData];\n\t\t\tSystem.Runtime.InteropServices.Marshal.Copy(punSecretData, ret, 0, (int)pcubUserData);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool BIsTicketSigned(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, byte[] pubRSAKey, uint cubRSAKey) {\n\t\t\tInteropHelp.TestIfPlatformSupported();\n\t\t\treturn NativeMethods.SteamEncryptedAppTicket_BIsTicketSigned(rgubTicketDecrypted, cubTicketDecrypted, pubRSAKey, cubRSAKey);\n\t\t}\n\t}\n\n\tinternal static class CSteamAPIContext {\n\t\tinternal static void Clear() {\n\t\t\tm_pSteamClient = IntPtr.Zero;\n\t\t\tm_pSteamUser = IntPtr.Zero;\n\t\t\tm_pSteamFriends = IntPtr.Zero;\n\t\t\tm_pSteamUtils = IntPtr.Zero;\n\t\t\tm_pSteamMatchmaking = IntPtr.Zero;\n\t\t\tm_pSteamUserStats = IntPtr.Zero;\n\t\t\tm_pSteamApps = IntPtr.Zero;\n\t\t\tm_pSteamMatchmakingServers = IntPtr.Zero;\n\t\t\tm_pSteamNetworking = IntPtr.Zero;\n\t\t\tm_pSteamRemoteStorage = IntPtr.Zero;\n\t\t\tm_pSteamHTTP = IntPtr.Zero;\n\t\t\tm_pSteamScreenshots = IntPtr.Zero;\n\t\t\tm_pSteamGameSearch = IntPtr.Zero;\n\t\t\tm_pSteamMusic = IntPtr.Zero;\n\t\t\tm_pController = IntPtr.Zero;\n\t\t\tm_pSteamUGC = IntPtr.Zero;\n\t\t\tm_pSteamAppList = IntPtr.Zero;\n\t\t\tm_pSteamMusic = IntPtr.Zero;\n\t\t\tm_pSteamMusicRemote = IntPtr.Zero;\n\t\t\tm_pSteamHTMLSurface = IntPtr.Zero;\n\t\t\tm_pSteamInventory = IntPtr.Zero;\n\t\t\tm_pSteamVideo = IntPtr.Zero;\n\t\t\tm_pSteamParentalSettings = IntPtr.Zero;\n\t\t\tm_pSteamInput = IntPtr.Zero;\n\t\t\tm_pSteamParties = IntPtr.Zero;\n\t\t\tm_pSteamRemotePlay = IntPtr.Zero;\n\t\t}\n\n\t\tinternal static bool Init() {\n\t\t\tHSteamUser hSteamUser = SteamAPI.GetHSteamUser();\n\t\t\tHSteamPipe hSteamPipe = SteamAPI.GetHSteamPipe();\n\t\t\tif (hSteamPipe == (HSteamPipe)0) { return false; }\n\n\t\t\tusing (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMCLIENT_INTERFACE_VERSION)) {\n\t\t\t\tm_pSteamClient = NativeMethods.SteamInternal_CreateInterface(pchVersionString);\n\t\t\t}\n\n\t\t\tif (m_pSteamClient == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUser = SteamClient.GetISteamUser(hSteamUser, hSteamPipe, Constants.STEAMUSER_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUser == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamFriends = SteamClient.GetISteamFriends(hSteamUser, hSteamPipe, Constants.STEAMFRIENDS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamFriends == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUtils = SteamClient.GetISteamUtils(hSteamPipe, Constants.STEAMUTILS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUtils == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamMatchmaking = SteamClient.GetISteamMatchmaking(hSteamUser, hSteamPipe, Constants.STEAMMATCHMAKING_INTERFACE_VERSION);\n\t\t\tif (m_pSteamMatchmaking == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamMatchmakingServers = SteamClient.GetISteamMatchmakingServers(hSteamUser, hSteamPipe, Constants.STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamMatchmakingServers == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUserStats = SteamClient.GetISteamUserStats(hSteamUser, hSteamPipe, Constants.STEAMUSERSTATS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUserStats == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamApps = SteamClient.GetISteamApps(hSteamUser, hSteamPipe, Constants.STEAMAPPS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamApps == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamNetworking = SteamClient.GetISteamNetworking(hSteamUser, hSteamPipe, Constants.STEAMNETWORKING_INTERFACE_VERSION);\n\t\t\tif (m_pSteamNetworking == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamRemoteStorage = SteamClient.GetISteamRemoteStorage(hSteamUser, hSteamPipe, Constants.STEAMREMOTESTORAGE_INTERFACE_VERSION);\n\t\t\tif (m_pSteamRemoteStorage == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamScreenshots = SteamClient.GetISteamScreenshots(hSteamUser, hSteamPipe, Constants.STEAMSCREENSHOTS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamScreenshots == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamGameSearch = SteamClient.GetISteamGameSearch(hSteamUser, hSteamPipe, Constants.STEAMGAMESEARCH_INTERFACE_VERSION);\n\t\t\tif (m_pSteamGameSearch == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamHTTP = SteamClient.GetISteamHTTP(hSteamUser, hSteamPipe, Constants.STEAMHTTP_INTERFACE_VERSION);\n\t\t\tif (m_pSteamHTTP == IntPtr.Zero) { return false; }\n\n\t\t\tm_pController = SteamClient.GetISteamController(hSteamUser, hSteamPipe, Constants.STEAMCONTROLLER_INTERFACE_VERSION);\n\t\t\tif (m_pController == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUGC = SteamClient.GetISteamUGC(hSteamUser, hSteamPipe, Constants.STEAMUGC_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUGC == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamAppList = SteamClient.GetISteamAppList(hSteamUser, hSteamPipe, Constants.STEAMAPPLIST_INTERFACE_VERSION);\n\t\t\tif (m_pSteamAppList == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamMusic = SteamClient.GetISteamMusic(hSteamUser, hSteamPipe, Constants.STEAMMUSIC_INTERFACE_VERSION);\n\t\t\tif (m_pSteamMusic == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamMusicRemote = SteamClient.GetISteamMusicRemote(hSteamUser, hSteamPipe, Constants.STEAMMUSICREMOTE_INTERFACE_VERSION);\n\t\t\tif (m_pSteamMusicRemote == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamHTMLSurface = SteamClient.GetISteamHTMLSurface(hSteamUser, hSteamPipe, Constants.STEAMHTMLSURFACE_INTERFACE_VERSION);\n\t\t\tif (m_pSteamHTMLSurface == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamInventory = SteamClient.GetISteamInventory(hSteamUser, hSteamPipe, Constants.STEAMINVENTORY_INTERFACE_VERSION);\n\t\t\tif (m_pSteamInventory == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamVideo = SteamClient.GetISteamVideo(hSteamUser, hSteamPipe, Constants.STEAMVIDEO_INTERFACE_VERSION);\n\t\t\tif (m_pSteamVideo == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamParentalSettings = SteamClient.GetISteamParentalSettings(hSteamUser, hSteamPipe, Constants.STEAMPARENTALSETTINGS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamParentalSettings == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamInput = SteamClient.GetISteamInput(hSteamUser, hSteamPipe, Constants.STEAMINPUT_INTERFACE_VERSION);\n\t\t\tif (m_pSteamInput == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamParties = SteamClient.GetISteamParties(hSteamUser, hSteamPipe, Constants.STEAMPARTIES_INTERFACE_VERSION);\n\t\t\tif (m_pSteamParties == IntPtr.Zero) { return false; }\n\n            m_pSteamRemotePlay = SteamClient.GetISteamRemotePlay(hSteamUser, hSteamPipe, Constants.STEAMREMOTEPLAY_INTERFACE_VERSION);\n            if (m_pSteamRemotePlay == IntPtr.Zero) { return false; }\n\n            return true;\n\t\t}\n\n\t\tinternal static IntPtr GetSteamClient() { return m_pSteamClient; }\n\t\tinternal static IntPtr GetSteamUser() { return m_pSteamUser; }\n\t\tinternal static IntPtr GetSteamFriends() { return m_pSteamFriends; }\n\t\tinternal static IntPtr GetSteamUtils() { return m_pSteamUtils; }\n\t\tinternal static IntPtr GetSteamMatchmaking() { return m_pSteamMatchmaking; }\n\t\tinternal static IntPtr GetSteamUserStats() { return m_pSteamUserStats; }\n\t\tinternal static IntPtr GetSteamApps() { return m_pSteamApps; }\n\t\tinternal static IntPtr GetSteamMatchmakingServers() { return m_pSteamMatchmakingServers; }\n\t\tinternal static IntPtr GetSteamNetworking() { return m_pSteamNetworking; }\n\t\tinternal static IntPtr GetSteamRemoteStorage() { return m_pSteamRemoteStorage; }\n\t\tinternal static IntPtr GetSteamScreenshots() { return m_pSteamScreenshots; }\n\t\tinternal static IntPtr GetSteamGameSearch() { return m_pSteamGameSearch; }\n\t\tinternal static IntPtr GetSteamHTTP() { return m_pSteamHTTP; }\n\t\tinternal static IntPtr GetSteamController() { return m_pController; }\n\t\tinternal static IntPtr GetSteamUGC() { return m_pSteamUGC; }\n\t\tinternal static IntPtr GetSteamAppList() { return m_pSteamAppList; }\n\t\tinternal static IntPtr GetSteamMusic() { return m_pSteamMusic; }\n\t\tinternal static IntPtr GetSteamMusicRemote() { return m_pSteamMusicRemote; }\n\t\tinternal static IntPtr GetSteamHTMLSurface() { return m_pSteamHTMLSurface; }\n\t\tinternal static IntPtr GetSteamInventory() { return m_pSteamInventory; }\n\t\tinternal static IntPtr GetSteamVideo() { return m_pSteamVideo; }\n\t\tinternal static IntPtr GetSteamParentalSettings() { return m_pSteamParentalSettings; }\n\t\tinternal static IntPtr GetSteamInput() { return m_pSteamInput; }\n\t\tinternal static IntPtr GetSteamParties() { return m_pSteamParties; }\n\t\tinternal static IntPtr GetSteamRemotePlay() { return m_pSteamRemotePlay; }\n\n\t\tprivate static IntPtr m_pSteamClient;\n\t\tprivate static IntPtr m_pSteamUser;\n\t\tprivate static IntPtr m_pSteamFriends;\n\t\tprivate static IntPtr m_pSteamUtils;\n\t\tprivate static IntPtr m_pSteamMatchmaking;\n\t\tprivate static IntPtr m_pSteamUserStats;\n\t\tprivate static IntPtr m_pSteamApps;\n\t\tprivate static IntPtr m_pSteamMatchmakingServers;\n\t\tprivate static IntPtr m_pSteamNetworking;\n\t\tprivate static IntPtr m_pSteamRemoteStorage;\n\t\tprivate static IntPtr m_pSteamScreenshots;\n\t\tprivate static IntPtr m_pSteamGameSearch;\n\t\tprivate static IntPtr m_pSteamHTTP;\n\t\tprivate static IntPtr m_pController;\n\t\tprivate static IntPtr m_pSteamUGC;\n\t\tprivate static IntPtr m_pSteamAppList;\n\t\tprivate static IntPtr m_pSteamMusic;\n\t\tprivate static IntPtr m_pSteamMusicRemote;\n\t\tprivate static IntPtr m_pSteamHTMLSurface;\n\t\tprivate static IntPtr m_pSteamInventory;\n\t\tprivate static IntPtr m_pSteamVideo;\n\t\tprivate static IntPtr m_pSteamParentalSettings;\n\t\tprivate static IntPtr m_pSteamInput;\n\t\tprivate static IntPtr m_pSteamParties;\n\t\tprivate static IntPtr m_pSteamRemotePlay;\n\t}\n\n\tinternal static class CSteamGameServerAPIContext {\n\t\tinternal static void Clear() {\n\t\t\tm_pSteamClient = IntPtr.Zero;\n\t\t\tm_pSteamGameServer = IntPtr.Zero;\n\t\t\tm_pSteamUtils = IntPtr.Zero;\n\t\t\tm_pSteamNetworking = IntPtr.Zero;\n\t\t\tm_pSteamGameServerStats = IntPtr.Zero;\n\t\t\tm_pSteamHTTP = IntPtr.Zero;\n\t\t\tm_pSteamInventory = IntPtr.Zero;\n\t\t\tm_pSteamUGC = IntPtr.Zero;\n\t\t\tm_pSteamApps = IntPtr.Zero;\n\t\t}\n\n\t\tinternal static bool Init() {\n\t\t\tHSteamUser hSteamUser = GameServer.GetHSteamUser();\n\t\t\tHSteamPipe hSteamPipe = GameServer.GetHSteamPipe();\n\t\t\tif (hSteamPipe == (HSteamPipe)0) { return false; }\n\n\t\t\tusing (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMCLIENT_INTERFACE_VERSION)) {\n\t\t\t\tm_pSteamClient = NativeMethods.SteamInternal_CreateInterface(pchVersionString);\n\t\t\t}\n\t\t\tif (m_pSteamClient == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamGameServer = SteamGameServerClient.GetISteamGameServer(hSteamUser, hSteamPipe, Constants.STEAMGAMESERVER_INTERFACE_VERSION);\n\t\t\tif (m_pSteamGameServer == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUtils = SteamGameServerClient.GetISteamUtils(hSteamPipe, Constants.STEAMUTILS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUtils == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamNetworking = SteamGameServerClient.GetISteamNetworking(hSteamUser, hSteamPipe, Constants.STEAMNETWORKING_INTERFACE_VERSION);\n\t\t\tif (m_pSteamNetworking == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamGameServerStats = SteamGameServerClient.GetISteamGameServerStats(hSteamUser, hSteamPipe, Constants.STEAMGAMESERVERSTATS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamGameServerStats == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamHTTP = SteamGameServerClient.GetISteamHTTP(hSteamUser, hSteamPipe, Constants.STEAMHTTP_INTERFACE_VERSION);\n\t\t\tif (m_pSteamHTTP == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamInventory = SteamGameServerClient.GetISteamInventory(hSteamUser, hSteamPipe, Constants.STEAMINVENTORY_INTERFACE_VERSION);\n\t\t\tif (m_pSteamInventory == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamUGC = SteamGameServerClient.GetISteamUGC(hSteamUser, hSteamPipe, Constants.STEAMUGC_INTERFACE_VERSION);\n\t\t\tif (m_pSteamUGC == IntPtr.Zero) { return false; }\n\n\t\t\tm_pSteamApps = SteamGameServerClient.GetISteamApps(hSteamUser, hSteamPipe, Constants.STEAMAPPS_INTERFACE_VERSION);\n\t\t\tif (m_pSteamApps == IntPtr.Zero) { return false; }\n\n\t\t\treturn true;\n\t\t}\n\n\t\tinternal static IntPtr GetSteamClient() { return m_pSteamClient; }\n\t\tinternal static IntPtr GetSteamGameServer() { return m_pSteamGameServer; }\n\t\tinternal static IntPtr GetSteamUtils() { return m_pSteamUtils; }\n\t\tinternal static IntPtr GetSteamNetworking() { return m_pSteamNetworking; }\n\t\tinternal static IntPtr GetSteamGameServerStats() { return m_pSteamGameServerStats; }\n\t\tinternal static IntPtr GetSteamHTTP() { return m_pSteamHTTP; }\n\t\tinternal static IntPtr GetSteamInventory() { return m_pSteamInventory; }\n\t\tinternal static IntPtr GetSteamUGC() { return m_pSteamUGC; }\n\t\tinternal static IntPtr GetSteamApps() { return m_pSteamApps; }\n\n\t\tprivate static IntPtr m_pSteamClient;\n\t\tprivate static IntPtr m_pSteamGameServer;\n\t\tprivate static IntPtr m_pSteamUtils;\n\t\tprivate static IntPtr m_pSteamNetworking;\n\t\tprivate static IntPtr m_pSteamGameServerStats;\n\t\tprivate static IntPtr m_pSteamHTTP;\n\t\tprivate static IntPtr m_pSteamInventory;\n\t\tprivate static IntPtr m_pSteamUGC;\n\t\tprivate static IntPtr m_pSteamApps;\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/NativeMethods.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\n#if UNITY_EDITOR_64 || (UNITY_STANDALONE && !UNITY_EDITOR && UNITY_64)\n\t#define STEAMWORKS_X64\n#elif UNITY_EDITOR_32 || (UNITY_STANDALONE && !UNITY_EDITOR && !UNITY_64)\n\t#define STEAMWORKS_X86\n#endif\n\n#if UNITY_EDITOR_WIN\n\t#define STEAMWORKS_WIN\n#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX\n\t#define STEAMWORKS_LIN_OSX\n#elif UNITY_STANDALONE_WIN\n\t#define STEAMWORKS_WIN\n#elif UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX\n\t#define STEAMWORKS_LIN_OSX\n#endif\n\n#if !STEAMWORKS_WIN && !STEAMWORKS_LIN_OSX\n\t#error You must define STEAMWORKS_WIN or STEAMWORKS_LIN_OSX if you're not using Unity.\n#endif\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Security.SuppressUnmanagedCodeSecurity()]\n\tinternal static class NativeMethods {\n\t\t#if STEAMWORKS_WIN && STEAMWORKS_X64\n\t\t\tinternal const string NativeLibraryName = \"steam_api64\";\n\t\t\tinternal const string NativeLibrary_SDKEncryptedAppTicket = \"sdkencryptedappticket64\";\n\t\t#else\n\t\t\tinternal const string NativeLibraryName = \"steam_api\";\n\t\t\tinternal const string NativeLibrary_SDKEncryptedAppTicket = \"sdkencryptedappticket\";\n\t\t#endif\n\n#region steam_api.h\n\t\t// Steam API setup & shutdown\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_Init\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamAPI_Init();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_Shutdown\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_Shutdown();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_RestartAppIfNecessary\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ReleaseCurrentThreadMemory\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_ReleaseCurrentThreadMemory();\n\n\t\t// crash dump recording functions\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_WriteMiniDump\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_WriteMiniDump(uint uStructuredExceptionCode, IntPtr pvExceptionInfo, uint uBuildID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_SetMiniDumpComment\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_SetMiniDumpComment(InteropHelp.UTF8StringHandle pchMsg);\n\n\t\t// steam callback and call-result helpers\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_RunCallbacks\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_RunCallbacks();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_RegisterCallback\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_RegisterCallback(IntPtr pCallback, int iCallback);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_UnregisterCallback\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_UnregisterCallback(IntPtr pCallback);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_RegisterCallResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_RegisterCallResult(IntPtr pCallback, ulong hAPICall);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_UnregisterCallResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_UnregisterCallResult(IntPtr pCallback, ulong hAPICall);\n\n\t\t// steamclient.dll private wrapper functions\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_IsSteamRunning\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamAPI_IsSteamRunning();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"Steam_RunCallbacks\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void Steam_RunCallbacks(HSteamPipe hSteamPipe, [MarshalAs(UnmanagedType.I1)] bool bGameServerCallbacks);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"Steam_RegisterInterfaceFuncs\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void Steam_RegisterInterfaceFuncs(IntPtr hModule);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"Steam_GetHSteamUserCurrent\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int Steam_GetHSteamUserCurrent();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_GetSteamInstallPath\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int SteamAPI_GetSteamInstallPath();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_GetHSteamPipe\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int SteamAPI_GetHSteamPipe();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_SetTryCatchCallbacks\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_SetTryCatchCallbacks([MarshalAs(UnmanagedType.I1)] bool bTryCatchCallbacks);\n\n\t\t// steam_api_internal.h\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_GetHSteamUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int SteamAPI_GetHSteamUser();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamInternal_ContextInit\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr SteamInternal_ContextInit(IntPtr pContextInitData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamInternal_CreateInterface\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr SteamInternal_CreateInterface(InteropHelp.UTF8StringHandle ver);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_UseBreakpadCrashHandler\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_UseBreakpadCrashHandler(InteropHelp.UTF8StringHandle pchVersion, InteropHelp.UTF8StringHandle pchDate, InteropHelp.UTF8StringHandle pchTime, [MarshalAs(UnmanagedType.I1)] bool bFullMemoryDumps, IntPtr pvContext, IntPtr m_pfnPreMinidumpCallback);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_SetBreakpadAppID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamAPI_SetBreakpadAppID(uint unAppID);\n#endregion\n#region steam_gameserver.h\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_InitSafe\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamGameServer_Init(uint unIP, ushort usSteamPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_Shutdown\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamGameServer_Shutdown();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_RunCallbacks\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamGameServer_RunCallbacks();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_ReleaseCurrentThreadMemory\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamGameServer_ReleaseCurrentThreadMemory();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_BSecure\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamGameServer_BSecure();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_GetSteamID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong SteamGameServer_GetSteamID();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_GetHSteamPipe\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int SteamGameServer_GetHSteamPipe();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServer_GetHSteamUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int SteamGameServer_GetHSteamUser();\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamInternal_GameServer_Init\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamInternal_GameServer_Init(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString);\n#endregion\n#region SteamAPI Accessors\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamClient\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr SteamClient();\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamGameServerClient\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr SteamGameServerClient();\n#endregion\n#region steamencryptedappticket.h\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamEncryptedAppTicket_BDecryptTicket([In, Out] byte[] rgubTicketEncrypted, uint cubTicketEncrypted, [In, Out] byte[] rgubTicketDecrypted, ref uint pcubTicketDecrypted, [MarshalAs(UnmanagedType.LPArray, SizeConst=Constants.k_nSteamEncryptedAppTicketSymmetricKeyLen)] byte[] rgubKey, int cubKey);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamEncryptedAppTicket_BIsTicketForApp([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint SteamEncryptedAppTicket_GetTicketIssueTime([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void SteamEncryptedAppTicket_GetTicketSteamID([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out CSteamID psteamID);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint SteamEncryptedAppTicket_GetTicketAppID([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamEncryptedAppTicket_BUserOwnsAppInTicket([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamEncryptedAppTicket_BUserIsVacBanned([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr SteamEncryptedAppTicket_GetUserVariableData([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out uint pcubUserData);\n\n\t\t[DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool SteamEncryptedAppTicket_BIsTicketSigned([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, [In, Out] byte[] pubRSAKey, uint cubRSAKey);\n#endregion\n#region SteamAppList\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamAppList_GetNumInstalledApps\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamAppList_GetNumInstalledApps(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamAppList_GetInstalledApps\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamAppList_GetInstalledApps(IntPtr instancePtr, [In, Out] AppId_t[] pvecAppID, uint unMaxAppIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamAppList_GetAppName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamAppList_GetAppName(IntPtr instancePtr, AppId_t nAppID, IntPtr pchName, int cchNameMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamAppList_GetAppInstallDir\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamAppList_GetAppInstallDir(IntPtr instancePtr, AppId_t nAppID, IntPtr pchDirectory, int cchNameMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamAppList_GetAppBuildId\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamAppList_GetAppBuildId(IntPtr instancePtr, AppId_t nAppID);\n#endregion\n#region SteamApps\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsSubscribed\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsSubscribed(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsLowViolence\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsLowViolence(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsCybercafe\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsCybercafe(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsVACBanned\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsVACBanned(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetCurrentGameLanguage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamApps_GetCurrentGameLanguage(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetAvailableGameLanguages\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamApps_GetAvailableGameLanguages(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsSubscribedApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsSubscribedApp(IntPtr instancePtr, AppId_t appID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsDlcInstalled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsDlcInstalled(IntPtr instancePtr, AppId_t appID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetEarliestPurchaseUnixTime\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamApps_GetEarliestPurchaseUnixTime(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsSubscribedFromFreeWeekend\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsSubscribedFromFreeWeekend(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetDLCCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamApps_GetDLCCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BGetDLCDataByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BGetDLCDataByIndex(IntPtr instancePtr, int iDLC, out AppId_t pAppID, out bool pbAvailable, IntPtr pchName, int cchNameBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_InstallDLC\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamApps_InstallDLC(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_UninstallDLC\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamApps_UninstallDLC(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_RequestAppProofOfPurchaseKey\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamApps_RequestAppProofOfPurchaseKey(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetCurrentBetaName\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_GetCurrentBetaName(IntPtr instancePtr, IntPtr pchName, int cchNameBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_MarkContentCorrupt\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_MarkContentCorrupt(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bMissingFilesOnly);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetInstalledDepots\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamApps_GetInstalledDepots(IntPtr instancePtr, AppId_t appID, [In, Out] DepotId_t[] pvecDepots, uint cMaxDepots);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetAppInstallDir\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamApps_GetAppInstallDir(IntPtr instancePtr, AppId_t appID, IntPtr pchFolder, uint cchFolderBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsAppInstalled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsAppInstalled(IntPtr instancePtr, AppId_t appID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetAppOwner\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamApps_GetAppOwner(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetLaunchQueryParam\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamApps_GetLaunchQueryParam(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetDlcDownloadProgress\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_GetDlcDownloadProgress(IntPtr instancePtr, AppId_t nAppID, out ulong punBytesDownloaded, out ulong punBytesTotal);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetAppBuildId\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamApps_GetAppBuildId(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_RequestAllProofOfPurchaseKeys\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamApps_RequestAllProofOfPurchaseKeys(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetFileDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamApps_GetFileDetails(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszFileName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_GetLaunchCommandLine\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamApps_GetLaunchCommandLine(IntPtr instancePtr, IntPtr pszCommandLine, int cubCommandLine);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamApps_BIsSubscribedFromFamilySharing\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamApps_BIsSubscribedFromFamilySharing(IntPtr instancePtr);\n#endregion\n#region SteamClient\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_CreateSteamPipe\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamClient_CreateSteamPipe(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_BReleaseSteamPipe\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamClient_BReleaseSteamPipe(IntPtr instancePtr, HSteamPipe hSteamPipe);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_ConnectToGlobalUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamClient_ConnectToGlobalUser(IntPtr instancePtr, HSteamPipe hSteamPipe);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_CreateLocalUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamClient_CreateLocalUser(IntPtr instancePtr, out HSteamPipe phSteamPipe, EAccountType eAccountType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_ReleaseUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamClient_ReleaseUser(IntPtr instancePtr, HSteamPipe hSteamPipe, HSteamUser hUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamUser(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamGameServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamGameServer(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_SetLocalIPBinding\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamClient_SetLocalIPBinding(IntPtr instancePtr, uint unIP, ushort usPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamFriends\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamFriends(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamUtils\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamUtils(IntPtr instancePtr, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamMatchmaking\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamMatchmaking(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamMatchmakingServers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamMatchmakingServers(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamGenericInterface\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamGenericInterface(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamUserStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamUserStats(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamGameServerStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamGameServerStats(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamApps\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamApps(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamNetworking\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamNetworking(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamRemoteStorage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamRemoteStorage(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamScreenshots\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamScreenshots(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamGameSearch\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamGameSearch(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetIPCCallCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamClient_GetIPCCallCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_SetWarningMessageHook\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamClient_SetWarningMessageHook(IntPtr instancePtr, SteamAPIWarningMessageHook_t pFunction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_BShutdownIfAllPipesClosed\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamClient_BShutdownIfAllPipesClosed(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamHTTP\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamHTTP(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamController\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamController(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamUGC\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamUGC(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamAppList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamAppList(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamMusic\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamMusic(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamMusicRemote\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamMusicRemote(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamHTMLSurface\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamHTMLSurface(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamInventory\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamInventory(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamVideo\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamVideo(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamParentalSettings\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamParentalSettings(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamInput\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamInput(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamParties\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamParties(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamClient_GetISteamRemotePlay\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamClient_GetISteamRemotePlay(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion);\n#endregion\n#region SteamController\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_Init\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamController_Init(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_Shutdown\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamController_Shutdown(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_RunFrame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_RunFrame(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetConnectedControllers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamController_GetConnectedControllers(IntPtr instancePtr, [In, Out] ControllerHandle_t[] handlesOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetActionSetHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamController_GetActionSetHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionSetName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_ActivateActionSet\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_ActivateActionSet(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetCurrentActionSet\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamController_GetCurrentActionSet(IntPtr instancePtr, ControllerHandle_t controllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_ActivateActionSetLayer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_ActivateActionSetLayer(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_DeactivateActionSetLayer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_DeactivateActionSetLayer(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_DeactivateAllActionSetLayers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_DeactivateAllActionSetLayers(IntPtr instancePtr, ControllerHandle_t controllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetActiveActionSetLayers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamController_GetActiveActionSetLayers(IntPtr instancePtr, ControllerHandle_t controllerHandle, [In, Out] ControllerActionSetHandle_t[] handlesOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetDigitalActionHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamController_GetDigitalActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetDigitalActionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ControllerDigitalActionData_t ISteamController_GetDigitalActionData(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetDigitalActionOrigins\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamController_GetDigitalActionOrigins(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerDigitalActionHandle_t digitalActionHandle, [In, Out] EControllerActionOrigin[] originsOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetAnalogActionHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamController_GetAnalogActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetAnalogActionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ControllerAnalogActionData_t ISteamController_GetAnalogActionData(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetAnalogActionOrigins\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamController_GetAnalogActionOrigins(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerAnalogActionHandle_t analogActionHandle, [In, Out] EControllerActionOrigin[] originsOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetGlyphForActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamController_GetGlyphForActionOrigin(IntPtr instancePtr, EControllerActionOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetStringForActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamController_GetStringForActionOrigin(IntPtr instancePtr, EControllerActionOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_StopAnalogActionMomentum\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_StopAnalogActionMomentum(IntPtr instancePtr, ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t eAction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetMotionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ControllerMotionData_t ISteamController_GetMotionData(IntPtr instancePtr, ControllerHandle_t controllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_TriggerHapticPulse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_TriggerHapticPulse(IntPtr instancePtr, ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_TriggerRepeatedHapticPulse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_TriggerRepeatedHapticPulse(IntPtr instancePtr, ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_TriggerVibration\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_TriggerVibration(IntPtr instancePtr, ControllerHandle_t controllerHandle, ushort usLeftSpeed, ushort usRightSpeed);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_SetLEDColor\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamController_SetLEDColor(IntPtr instancePtr, ControllerHandle_t controllerHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_ShowBindingPanel\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamController_ShowBindingPanel(IntPtr instancePtr, ControllerHandle_t controllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetInputTypeForHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ESteamInputType ISteamController_GetInputTypeForHandle(IntPtr instancePtr, ControllerHandle_t controllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetControllerForGamepadIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamController_GetControllerForGamepadIndex(IntPtr instancePtr, int nIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetGamepadIndexForController\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamController_GetGamepadIndexForController(IntPtr instancePtr, ControllerHandle_t ulControllerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetStringForXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamController_GetStringForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetGlyphForXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamController_GetGlyphForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetActionOriginFromXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EControllerActionOrigin ISteamController_GetActionOriginFromXboxOrigin(IntPtr instancePtr, ControllerHandle_t controllerHandle, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_TranslateActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EControllerActionOrigin ISteamController_TranslateActionOrigin(IntPtr instancePtr, ESteamInputType eDestinationInputType, EControllerActionOrigin eSourceOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamController_GetControllerBindingRevision\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamController_GetControllerBindingRevision(IntPtr instancePtr, ControllerHandle_t controllerHandle, out int pMajor, out int pMinor);\n#endregion\n#region SteamFriends\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetPersonaName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetPersonaName(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SetPersonaName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_SetPersonaName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchPersonaName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetPersonaState\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EPersonaState ISteamFriends_GetPersonaState(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendCount(IntPtr instancePtr, EFriendFlags iFriendFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetFriendByIndex(IntPtr instancePtr, int iFriend, EFriendFlags iFriendFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendRelationship\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EFriendRelationship ISteamFriends_GetFriendRelationship(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendPersonaState\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EPersonaState ISteamFriends_GetFriendPersonaState(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendPersonaName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetFriendPersonaName(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendGamePlayed\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_GetFriendGamePlayed(IntPtr instancePtr, CSteamID steamIDFriend, out FriendGameInfo_t pFriendGameInfo);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendPersonaNameHistory\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetFriendPersonaNameHistory(IntPtr instancePtr, CSteamID steamIDFriend, int iPersonaName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendSteamLevel\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendSteamLevel(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetPlayerNickname\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetPlayerNickname(IntPtr instancePtr, CSteamID steamIDPlayer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendsGroupCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendsGroupCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendsGroupIDByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern short ISteamFriends_GetFriendsGroupIDByIndex(IntPtr instancePtr, int iFG);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendsGroupName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetFriendsGroupName(IntPtr instancePtr, FriendsGroupID_t friendsGroupID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendsGroupMembersCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendsGroupMembersCount(IntPtr instancePtr, FriendsGroupID_t friendsGroupID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendsGroupMembersList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_GetFriendsGroupMembersList(IntPtr instancePtr, FriendsGroupID_t friendsGroupID, [In, Out] CSteamID[] pOutSteamIDMembers, int nMembersCount);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_HasFriend\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_HasFriend(IntPtr instancePtr, CSteamID steamIDFriend, EFriendFlags iFriendFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetClanCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetClanByIndex(IntPtr instancePtr, int iClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetClanName(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetClanTag(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanActivityCounts\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_GetClanActivityCounts(IntPtr instancePtr, CSteamID steamIDClan, out int pnOnline, out int pnInGame, out int pnChatting);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_DownloadClanActivityCounts\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_DownloadClanActivityCounts(IntPtr instancePtr, [In, Out] CSteamID[] psteamIDClans, int cClansToRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendCountFromSource\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendCountFromSource(IntPtr instancePtr, CSteamID steamIDSource);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendFromSourceByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetFriendFromSourceByIndex(IntPtr instancePtr, CSteamID steamIDSource, int iFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsUserInSource\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_IsUserInSource(IntPtr instancePtr, CSteamID steamIDUser, CSteamID steamIDSource);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SetInGameVoiceSpeaking\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_SetInGameVoiceSpeaking(IntPtr instancePtr, CSteamID steamIDUser, [MarshalAs(UnmanagedType.I1)] bool bSpeaking);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ActivateGameOverlay\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ActivateGameOverlay(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDialog);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ActivateGameOverlayToUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ActivateGameOverlayToUser(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDialog, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ActivateGameOverlayToWebPage(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchURL, EActivateGameOverlayToWebPageMode eMode);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ActivateGameOverlayToStore\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ActivateGameOverlayToStore(IntPtr instancePtr, AppId_t nAppID, EOverlayToStoreFlag eFlag);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SetPlayedWith\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_SetPlayedWith(IntPtr instancePtr, CSteamID steamIDUserPlayedWith);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ActivateGameOverlayInviteDialog\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ActivateGameOverlayInviteDialog(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetSmallFriendAvatar\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetSmallFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetMediumFriendAvatar\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetMediumFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetLargeFriendAvatar\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetLargeFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_RequestUserInformation\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_RequestUserInformation(IntPtr instancePtr, CSteamID steamIDUser, [MarshalAs(UnmanagedType.I1)] bool bRequireNameOnly);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_RequestClanOfficerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_RequestClanOfficerList(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanOwner\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetClanOwner(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanOfficerCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetClanOfficerCount(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanOfficerByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetClanOfficerByIndex(IntPtr instancePtr, CSteamID steamIDClan, int iOfficer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetUserRestrictions\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamFriends_GetUserRestrictions(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SetRichPresence\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_SetRichPresence(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ClearRichPresence\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_ClearRichPresence(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendRichPresence\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetFriendRichPresence(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendRichPresenceKeyCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendRichPresenceKeyCount(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendRichPresenceKeyByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamFriends_GetFriendRichPresenceKeyByIndex(IntPtr instancePtr, CSteamID steamIDFriend, int iKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_RequestFriendRichPresence\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamFriends_RequestFriendRichPresence(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_InviteUserToGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_InviteUserToGame(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchConnectString);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetCoplayFriendCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetCoplayFriendCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetCoplayFriend\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetCoplayFriend(IntPtr instancePtr, int iCoplayFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendCoplayTime\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendCoplayTime(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendCoplayGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamFriends_GetFriendCoplayGame(IntPtr instancePtr, CSteamID steamIDFriend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_JoinClanChatRoom\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_JoinClanChatRoom(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_LeaveClanChatRoom\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_LeaveClanChatRoom(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanChatMemberCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetClanChatMemberCount(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetChatMemberByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetChatMemberByIndex(IntPtr instancePtr, CSteamID steamIDClan, int iUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SendClanChatMessage\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_SendClanChatMessage(IntPtr instancePtr, CSteamID steamIDClanChat, InteropHelp.UTF8StringHandle pchText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetClanChatMessage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetClanChatMessage(IntPtr instancePtr, CSteamID steamIDClanChat, int iMessage, IntPtr prgchText, int cchTextMax, out EChatEntryType peChatEntryType, out CSteamID psteamidChatter);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsClanChatAdmin\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_IsClanChatAdmin(IntPtr instancePtr, CSteamID steamIDClanChat, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsClanChatWindowOpenInSteam\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_IsClanChatWindowOpenInSteam(IntPtr instancePtr, CSteamID steamIDClanChat);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_OpenClanChatWindowInSteam\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_OpenClanChatWindowInSteam(IntPtr instancePtr, CSteamID steamIDClanChat);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_CloseClanChatWindowInSteam\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_CloseClanChatWindowInSteam(IntPtr instancePtr, CSteamID steamIDClanChat);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_SetListenForFriendsMessages\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_SetListenForFriendsMessages(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bInterceptEnabled);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_ReplyToFriendMessage\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_ReplyToFriendMessage(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchMsgToSend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFriendMessage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetFriendMessage(IntPtr instancePtr, CSteamID steamIDFriend, int iMessageID, IntPtr pvData, int cubData, out EChatEntryType peChatEntryType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetFollowerCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_GetFollowerCount(IntPtr instancePtr, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsFollowing\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_IsFollowing(IntPtr instancePtr, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_EnumerateFollowingList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamFriends_EnumerateFollowingList(IntPtr instancePtr, uint unStartIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsClanPublic\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_IsClanPublic(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_IsClanOfficialGameGroup\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamFriends_IsClanOfficialGameGroup(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamFriends_GetNumChatsWithUnreadPriorityMessages\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamFriends_GetNumChatsWithUnreadPriorityMessages(IntPtr instancePtr);\n#endregion\n#region SteamGameServer\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_InitGameServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_InitGameServer(IntPtr instancePtr, uint unIP, ushort usGamePort, ushort usQueryPort, uint unFlags, AppId_t nGameAppId, InteropHelp.UTF8StringHandle pchVersionString);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetProduct\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetProduct(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszProduct);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetGameDescription\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetGameDescription(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszGameDescription);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetModDir\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetModDir(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszModDir);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetDedicatedServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetDedicatedServer(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bDedicated);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_LogOn\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_LogOn(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszToken);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_LogOnAnonymous\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_LogOnAnonymous(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_LogOff\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_LogOff(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_BLoggedOn\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_BLoggedOn(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_BSecure\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_BSecure(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetSteamID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServer_GetSteamID(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_WasRestartRequested\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_WasRestartRequested(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetMaxPlayerCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetMaxPlayerCount(IntPtr instancePtr, int cPlayersMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetBotPlayerCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetBotPlayerCount(IntPtr instancePtr, int cBotplayers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetServerName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetServerName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszServerName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetMapName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetMapName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszMapName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetPasswordProtected\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetPasswordProtected(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bPasswordProtected);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetSpectatorPort\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetSpectatorPort(IntPtr instancePtr, ushort unSpectatorPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetSpectatorServerName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetSpectatorServerName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszSpectatorServerName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_ClearAllKeyValues\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_ClearAllKeyValues(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetKeyValue\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetKeyValue(IntPtr instancePtr, InteropHelp.UTF8StringHandle pKey, InteropHelp.UTF8StringHandle pValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetGameTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetGameTags(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchGameTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetGameData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetGameData(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchGameData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetRegion\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetRegion(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszRegion);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SendUserConnectAndAuthenticate\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_SendUserConnectAndAuthenticate(IntPtr instancePtr, uint unIPClient, byte[] pvAuthBlob, uint cubAuthBlobSize, out CSteamID pSteamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_CreateUnauthenticatedUserConnection\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServer_CreateUnauthenticatedUserConnection(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SendUserDisconnect\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SendUserDisconnect(IntPtr instancePtr, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_BUpdateUserData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_BUpdateUserData(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchPlayerName, uint uScore);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetAuthSessionTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamGameServer_GetAuthSessionTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_BeginAuthSession\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EBeginAuthSessionResult ISteamGameServer_BeginAuthSession(IntPtr instancePtr, byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_EndAuthSession\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_EndAuthSession(IntPtr instancePtr, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_CancelAuthTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_CancelAuthTicket(IntPtr instancePtr, HAuthTicket hAuthTicket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_UserHasLicenseForApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EUserHasLicenseForAppResult ISteamGameServer_UserHasLicenseForApp(IntPtr instancePtr, CSteamID steamID, AppId_t appID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_RequestUserGroupStatus\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_RequestUserGroupStatus(IntPtr instancePtr, CSteamID steamIDUser, CSteamID steamIDGroup);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetGameplayStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_GetGameplayStats(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetServerReputation\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServer_GetServerReputation(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetPublicIP\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamGameServer_GetPublicIP(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_HandleIncomingPacket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServer_HandleIncomingPacket(IntPtr instancePtr, byte[] pData, int cbData, uint srcIP, ushort srcPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_GetNextOutgoingPacket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamGameServer_GetNextOutgoingPacket(IntPtr instancePtr, byte[] pOut, int cbMaxOut, out uint pNetAdr, out ushort pPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_EnableHeartbeats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_EnableHeartbeats(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bActive);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_SetHeartbeatInterval\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_SetHeartbeatInterval(IntPtr instancePtr, int iHeartbeatInterval);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_ForceHeartbeat\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamGameServer_ForceHeartbeat(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_AssociateWithClan\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServer_AssociateWithClan(IntPtr instancePtr, CSteamID steamIDClan);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServer_ComputeNewPlayerCompatibility\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServer_ComputeNewPlayerCompatibility(IntPtr instancePtr, CSteamID steamIDNewPlayer);\n#endregion\n#region SteamGameServerStats\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_RequestUserStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServerStats_RequestUserStats(IntPtr instancePtr, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_GetUserStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_GetUserStat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out int pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_GetUserStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_GetUserStat0(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out float pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_GetUserAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_GetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_SetUserStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_SetUserStat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, int nData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_SetUserStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_SetUserStat0(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, float fData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_UpdateUserAvgRateStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_UpdateUserAvgRateStat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, float flCountThisSession, double dSessionLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_SetUserAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_SetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_ClearUserAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamGameServerStats_ClearUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameServerStats_StoreUserStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamGameServerStats_StoreUserStats(IntPtr instancePtr, CSteamID steamIDUser);\n#endregion\n#region SteamHTMLSurface\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_Init\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTMLSurface_Init(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_Shutdown\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTMLSurface_Shutdown(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_CreateBrowser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamHTMLSurface_CreateBrowser(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchUserAgent, InteropHelp.UTF8StringHandle pchUserCSS);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_RemoveBrowser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_RemoveBrowser(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_LoadURL\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_LoadURL(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchURL, InteropHelp.UTF8StringHandle pchPostData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetSize(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint unWidth, uint unHeight);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_StopLoad\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_StopLoad(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_Reload\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_Reload(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_GoBack\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_GoBack(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_GoForward\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_GoForward(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_AddHeader\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_AddHeader(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_ExecuteJavascript\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_ExecuteJavascript(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchScript);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_MouseUp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_MouseUp(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_MouseDown\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_MouseDown(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_MouseDoubleClick\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_MouseDoubleClick(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_MouseMove\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_MouseMove(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int x, int y);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_MouseWheel\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_MouseWheel(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int nDelta);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_KeyDown\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_KeyDown(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, [MarshalAs(UnmanagedType.I1)] bool bIsSystemKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_KeyUp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_KeyUp(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_KeyChar\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_KeyChar(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetHorizontalScroll\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetHorizontalScroll(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetVerticalScroll\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetVerticalScroll(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetKeyFocus\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetKeyFocus(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bHasKeyFocus);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_ViewSource\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_ViewSource(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_CopyToClipboard\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_CopyToClipboard(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_PasteFromClipboard\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_PasteFromClipboard(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_Find\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_Find(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchSearchStr, [MarshalAs(UnmanagedType.I1)] bool bCurrentlyInFind, [MarshalAs(UnmanagedType.I1)] bool bReverse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_StopFind\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_StopFind(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_GetLinkAtPosition\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_GetLinkAtPosition(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int x, int y);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetCookie\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetCookie(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchHostname, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue, InteropHelp.UTF8StringHandle pchPath, uint nExpires, [MarshalAs(UnmanagedType.I1)] bool bSecure, [MarshalAs(UnmanagedType.I1)] bool bHTTPOnly);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetPageScaleFactor\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetPageScaleFactor(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, float flZoom, int nPointX, int nPointY);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetBackgroundMode\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetBackgroundMode(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bBackgroundMode);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_SetDPIScalingFactor\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_SetDPIScalingFactor(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, float flDPIScaling);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_OpenDeveloperTools\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_OpenDeveloperTools(IntPtr instancePtr, HHTMLBrowser unBrowserHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_AllowStartRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_AllowStartRequest(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bAllowed);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_JSDialogResponse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_JSDialogResponse(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bResult);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTMLSurface_FileLoadDialogResponse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamHTMLSurface_FileLoadDialogResponse(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, IntPtr pchSelectedFiles);\n#endregion\n#region SteamHTTP\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_CreateHTTPRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamHTTP_CreateHTTPRequest(IntPtr instancePtr, EHTTPMethod eHTTPRequestMethod, InteropHelp.UTF8StringHandle pchAbsoluteURL);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestContextValue\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestContextValue(IntPtr instancePtr, HTTPRequestHandle hRequest, ulong ulContextValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestNetworkActivityTimeout\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(IntPtr instancePtr, HTTPRequestHandle hRequest, uint unTimeoutSeconds);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestHeaderValue\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestHeaderValue(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, InteropHelp.UTF8StringHandle pchHeaderValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestGetOrPostParameter\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestGetOrPostParameter(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchParamName, InteropHelp.UTF8StringHandle pchParamValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SendHTTPRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SendHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SendHTTPRequestAndStreamResponse\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SendHTTPRequestAndStreamResponse(IntPtr instancePtr, HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_DeferHTTPRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_DeferHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_PrioritizeHTTPRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_PrioritizeHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPResponseHeaderSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPResponseHeaderSize(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, out uint unResponseHeaderSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPResponseHeaderValue\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPResponseHeaderValue(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPResponseBodySize\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPResponseBodySize(IntPtr instancePtr, HTTPRequestHandle hRequest, out uint unBodySize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPResponseBodyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPResponseBodyData(IntPtr instancePtr, HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPStreamingResponseBodyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPStreamingResponseBodyData(IntPtr instancePtr, HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_ReleaseHTTPRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_ReleaseHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPDownloadProgressPct\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPDownloadProgressPct(IntPtr instancePtr, HTTPRequestHandle hRequest, out float pflPercentOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestRawPostBody\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestRawPostBody(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchContentType, byte[] pubBody, uint unBodyLen);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_CreateCookieContainer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamHTTP_CreateCookieContainer(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAllowResponsesToModify);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_ReleaseCookieContainer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_ReleaseCookieContainer(IntPtr instancePtr, HTTPCookieContainerHandle hCookieContainer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetCookie\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetCookie(IntPtr instancePtr, HTTPCookieContainerHandle hCookieContainer, InteropHelp.UTF8StringHandle pchHost, InteropHelp.UTF8StringHandle pchUrl, InteropHelp.UTF8StringHandle pchCookie);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestCookieContainer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestCookieContainer(IntPtr instancePtr, HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestUserAgentInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestUserAgentInfo(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchUserAgentInfo);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(IntPtr instancePtr, HTTPRequestHandle hRequest, [MarshalAs(UnmanagedType.I1)] bool bRequireVerifiedCertificate);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(IntPtr instancePtr, HTTPRequestHandle hRequest, uint unMilliseconds);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamHTTP_GetHTTPRequestWasTimedOut\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamHTTP_GetHTTPRequestWasTimedOut(IntPtr instancePtr, HTTPRequestHandle hRequest, out bool pbWasTimedOut);\n#endregion\n#region SteamInput\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_Init\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInput_Init(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_Shutdown\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInput_Shutdown(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_RunFrame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_RunFrame(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetConnectedControllers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamInput_GetConnectedControllers(IntPtr instancePtr, [In, Out] InputHandle_t[] handlesOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetActionSetHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInput_GetActionSetHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionSetName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_ActivateActionSet\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_ActivateActionSet(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetCurrentActionSet\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInput_GetCurrentActionSet(IntPtr instancePtr, InputHandle_t inputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_ActivateActionSetLayer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_ActivateActionSetLayer(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_DeactivateActionSetLayer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_DeactivateActionSetLayer(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_DeactivateAllActionSetLayers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_DeactivateAllActionSetLayers(IntPtr instancePtr, InputHandle_t inputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetActiveActionSetLayers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamInput_GetActiveActionSetLayers(IntPtr instancePtr, InputHandle_t inputHandle, [In, Out] InputActionSetHandle_t[] handlesOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetDigitalActionHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInput_GetDigitalActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetDigitalActionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern InputDigitalActionData_t ISteamInput_GetDigitalActionData(IntPtr instancePtr, InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetDigitalActionOrigins\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamInput_GetDigitalActionOrigins(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, [In, Out] EInputActionOrigin[] originsOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetAnalogActionHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInput_GetAnalogActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetAnalogActionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern InputAnalogActionData_t ISteamInput_GetAnalogActionData(IntPtr instancePtr, InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetAnalogActionOrigins\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamInput_GetAnalogActionOrigins(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, [In, Out] EInputActionOrigin[] originsOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetGlyphForActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamInput_GetGlyphForActionOrigin(IntPtr instancePtr, EInputActionOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetStringForActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamInput_GetStringForActionOrigin(IntPtr instancePtr, EInputActionOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_StopAnalogActionMomentum\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_StopAnalogActionMomentum(IntPtr instancePtr, InputHandle_t inputHandle, InputAnalogActionHandle_t eAction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetMotionData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern InputMotionData_t ISteamInput_GetMotionData(IntPtr instancePtr, InputHandle_t inputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_TriggerVibration\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_TriggerVibration(IntPtr instancePtr, InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_SetLEDColor\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_SetLEDColor(IntPtr instancePtr, InputHandle_t inputHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_TriggerHapticPulse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_TriggerHapticPulse(IntPtr instancePtr, InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_TriggerRepeatedHapticPulse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInput_TriggerRepeatedHapticPulse(IntPtr instancePtr, InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_ShowBindingPanel\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInput_ShowBindingPanel(IntPtr instancePtr, InputHandle_t inputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetInputTypeForHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ESteamInputType ISteamInput_GetInputTypeForHandle(IntPtr instancePtr, InputHandle_t inputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetControllerForGamepadIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInput_GetControllerForGamepadIndex(IntPtr instancePtr, int nIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetGamepadIndexForController\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamInput_GetGamepadIndexForController(IntPtr instancePtr, InputHandle_t ulinputHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetStringForXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamInput_GetStringForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetGlyphForXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamInput_GetGlyphForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetActionOriginFromXboxOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EInputActionOrigin ISteamInput_GetActionOriginFromXboxOrigin(IntPtr instancePtr, InputHandle_t inputHandle, EXboxOrigin eOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_TranslateActionOrigin\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EInputActionOrigin ISteamInput_TranslateActionOrigin(IntPtr instancePtr, ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetDeviceBindingRevision\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInput_GetDeviceBindingRevision(IntPtr instancePtr, InputHandle_t inputHandle, out int pMajor, out int pMinor);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInput_GetRemotePlaySessionID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamInput_GetRemotePlaySessionID(IntPtr instancePtr, InputHandle_t inputHandle);\n#endregion\n#region SteamInventory\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetResultStatus\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EResult ISteamInventory_GetResultStatus(IntPtr instancePtr, SteamInventoryResult_t resultHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetResultItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetResultItems(IntPtr instancePtr, SteamInventoryResult_t resultHandle, [In, Out] SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetResultItemProperty\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetResultItemProperty(IntPtr instancePtr, SteamInventoryResult_t resultHandle, uint unItemIndex, InteropHelp.UTF8StringHandle pchPropertyName, IntPtr pchValueBuffer, ref uint punValueBufferSizeOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetResultTimestamp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamInventory_GetResultTimestamp(IntPtr instancePtr, SteamInventoryResult_t resultHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_CheckResultSteamID\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_CheckResultSteamID(IntPtr instancePtr, SteamInventoryResult_t resultHandle, CSteamID steamIDExpected);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_DestroyResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInventory_DestroyResult(IntPtr instancePtr, SteamInventoryResult_t resultHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetAllItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetAllItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetItemsByID\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetItemsByID(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SerializeResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SerializeResult(IntPtr instancePtr, SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_DeserializeResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_DeserializeResult(IntPtr instancePtr, out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, [MarshalAs(UnmanagedType.I1)] bool bRESERVED_MUST_BE_FALSE);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GenerateItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GenerateItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] uint[] punArrayQuantity, uint unArrayLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GrantPromoItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GrantPromoItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_AddPromoItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_AddPromoItem(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_AddPromoItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_AddPromoItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayItemDefs, uint unArrayLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_ConsumeItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_ConsumeItem(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_ExchangeItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_ExchangeItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayGenerate, [In, Out] uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, [In, Out] SteamItemInstanceID_t[] pArrayDestroy, [In, Out] uint[] punArrayDestroyQuantity, uint unArrayDestroyLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_TransferItemQuantity\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_TransferItemQuantity(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SendItemDropHeartbeat\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamInventory_SendItemDropHeartbeat(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_TriggerItemDrop\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_TriggerItemDrop(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_TradeItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_TradeItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, [In, Out] SteamItemInstanceID_t[] pArrayGive, [In, Out] uint[] pArrayGiveQuantity, uint nArrayGiveLength, [In, Out] SteamItemInstanceID_t[] pArrayGet, [In, Out] uint[] pArrayGetQuantity, uint nArrayGetLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_LoadItemDefinitions\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_LoadItemDefinitions(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetItemDefinitionIDs\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetItemDefinitionIDs(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetItemDefinitionProperty\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetItemDefinitionProperty(IntPtr instancePtr, SteamItemDef_t iDefinition, InteropHelp.UTF8StringHandle pchPropertyName, IntPtr pchValueBuffer, ref uint punValueBufferSizeOut);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_RequestEligiblePromoItemDefinitionsIDs\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(IntPtr instancePtr, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetEligiblePromoItemDefinitionIDs\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetEligiblePromoItemDefinitionIDs(IntPtr instancePtr, CSteamID steamID, [In, Out] SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_StartPurchase\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInventory_StartPurchase(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] uint[] punArrayQuantity, uint unArrayLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_RequestPrices\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInventory_RequestPrices(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetNumItemsWithPrices\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamInventory_GetNumItemsWithPrices(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetItemsWithPrices\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetItemsWithPrices(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] ulong[] pCurrentPrices, [In, Out] ulong[] pBasePrices, uint unArrayLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_GetItemPrice\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_GetItemPrice(IntPtr instancePtr, SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_StartUpdateProperties\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamInventory_StartUpdateProperties(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_RemoveProperty\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_RemoveProperty(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SetProperty\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SetProperty(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, InteropHelp.UTF8StringHandle pchPropertyValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SetProperty0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SetProperty0(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SetProperty1\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SetProperty1(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, long nValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SetProperty2\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SetProperty2(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, float flValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamInventory_SubmitUpdateProperties\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamInventory_SubmitUpdateProperties(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle);\n#endregion\n#region SteamMatchmaking\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetFavoriteGameCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_GetFavoriteGameCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetFavoriteGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_GetFavoriteGame(IntPtr instancePtr, int iGame, out AppId_t pnAppID, out uint pnIP, out ushort pnConnPort, out ushort pnQueryPort, out uint punFlags, out uint pRTime32LastPlayedOnServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddFavoriteGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_AddFavoriteGame(IntPtr instancePtr, AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags, uint rTime32LastPlayedOnServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_RemoveFavoriteGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_RemoveFavoriteGame(IntPtr instancePtr, AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_RequestLobbyList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_RequestLobbyList(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListStringFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListStringFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, InteropHelp.UTF8StringHandle pchValueToMatch, ELobbyComparison eComparisonType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListNumericalFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListNumericalFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, int nValueToMatch, ELobbyComparison eComparisonType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListNearValueFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListNearValueFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, int nValueToBeCloseTo);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable(IntPtr instancePtr, int nSlotsAvailable);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListDistanceFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListDistanceFilter(IntPtr instancePtr, ELobbyDistanceFilter eLobbyDistanceFilter);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListResultCountFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListResultCountFilter(IntPtr instancePtr, int cMaxResults);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_GetLobbyByIndex(IntPtr instancePtr, int iLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_CreateLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_CreateLobby(IntPtr instancePtr, ELobbyType eLobbyType, int cMaxMembers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_JoinLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_JoinLobby(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_LeaveLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_LeaveLobby(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_InviteUserToLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_InviteUserToLobby(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDInvitee);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetNumLobbyMembers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_GetNumLobbyMembers(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyMemberByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_GetLobbyMemberByIndex(IntPtr instancePtr, CSteamID steamIDLobby, int iMember);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmaking_GetLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyDataCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_GetLobbyDataCount(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyDataByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_GetLobbyDataByIndex(IntPtr instancePtr, CSteamID steamIDLobby, int iLobbyData, IntPtr pchKey, int cchKeyBufferSize, IntPtr pchValue, int cchValueBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_DeleteLobbyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_DeleteLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyMemberData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmaking_GetLobbyMemberData(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyMemberData\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_SetLobbyMemberData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SendLobbyChatMsg\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SendLobbyChatMsg(IntPtr instancePtr, CSteamID steamIDLobby, byte[] pvMsgBody, int cubMsgBody);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyChatEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_GetLobbyChatEntry(IntPtr instancePtr, CSteamID steamIDLobby, int iChatID, out CSteamID pSteamIDUser, byte[] pvData, int cubData, out EChatEntryType peChatEntryType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_RequestLobbyData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_RequestLobbyData(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyGameServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_SetLobbyGameServer(IntPtr instancePtr, CSteamID steamIDLobby, uint unGameServerIP, ushort unGameServerPort, CSteamID steamIDGameServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyGameServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_GetLobbyGameServer(IntPtr instancePtr, CSteamID steamIDLobby, out uint punGameServerIP, out ushort punGameServerPort, out CSteamID psteamIDGameServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyMemberLimit\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLobbyMemberLimit(IntPtr instancePtr, CSteamID steamIDLobby, int cMaxMembers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyMemberLimit\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmaking_GetLobbyMemberLimit(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyType\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLobbyType(IntPtr instancePtr, CSteamID steamIDLobby, ELobbyType eLobbyType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyJoinable\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLobbyJoinable(IntPtr instancePtr, CSteamID steamIDLobby, [MarshalAs(UnmanagedType.I1)] bool bLobbyJoinable);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_GetLobbyOwner\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamMatchmaking_GetLobbyOwner(IntPtr instancePtr, CSteamID steamIDLobby);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLobbyOwner\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLobbyOwner(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDNewOwner);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_SetLinkedLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmaking_SetLinkedLobby(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDLobbyDependent);\n#if _PS3\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmaking_CheckForPSNGameBootInvite\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmaking_CheckForPSNGameBootInvite(IntPtr instancePtr, uint iGameBootAttributes);\n#endif\n#endregion\n#region SteamMatchmakingServers\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestInternetServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestInternetServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestLANServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestLANServerList(IntPtr instancePtr, AppId_t iApp, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestFriendsServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestFriendsServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestFavoritesServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestFavoritesServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestHistoryServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestHistoryServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RequestSpectatorServerList\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_RequestSpectatorServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_ReleaseRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmakingServers_ReleaseRequest(IntPtr instancePtr, HServerListRequest hServerListRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_GetServerDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamMatchmakingServers_GetServerDetails(IntPtr instancePtr, HServerListRequest hRequest, int iServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_CancelQuery\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmakingServers_CancelQuery(IntPtr instancePtr, HServerListRequest hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RefreshQuery\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmakingServers_RefreshQuery(IntPtr instancePtr, HServerListRequest hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_IsRefreshing\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMatchmakingServers_IsRefreshing(IntPtr instancePtr, HServerListRequest hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_GetServerCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmakingServers_GetServerCount(IntPtr instancePtr, HServerListRequest hRequest);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_RefreshServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmakingServers_RefreshServer(IntPtr instancePtr, HServerListRequest hRequest, int iServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_PingServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmakingServers_PingServer(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_PlayerDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmakingServers_PlayerDetails(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_ServerRules\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamMatchmakingServers_ServerRules(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMatchmakingServers_CancelServerQuery\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMatchmakingServers_CancelServerQuery(IntPtr instancePtr, HServerQuery hServerQuery);\n#endregion\n#region SteamGameSearch\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_AddGameSearchParams\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_AddGameSearchParams(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToFind, InteropHelp.UTF8StringHandle pchValuesToFind);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_SearchForGameWithLobby\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_SearchForGameWithLobby(IntPtr instancePtr, CSteamID steamIDLobby, int nPlayerMin, int nPlayerMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_SearchForGameSolo\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_SearchForGameSolo(IntPtr instancePtr, int nPlayerMin, int nPlayerMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_AcceptGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_AcceptGame(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_DeclineGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_DeclineGame(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_RetrieveConnectionDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_RetrieveConnectionDetails(IntPtr instancePtr, CSteamID steamIDHost, IntPtr pchConnectionDetails, int cubConnectionDetails);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_EndGameSearch\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_EndGameSearch(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_SetGameHostParams\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_SetGameHostParams(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_SetConnectionDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_SetConnectionDetails(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchConnectionDetails, int cubConnectionDetails);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_RequestPlayersForGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_RequestPlayersForGame(IntPtr instancePtr, int nPlayerMin, int nPlayerMax, int nMaxTeamSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_HostConfirmGameStart\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_HostConfirmGameStart(IntPtr instancePtr, ulong ullUniqueGameID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_CancelRequestPlayersForGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_CancelRequestPlayersForGame(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_SubmitPlayerResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_SubmitPlayerResult(IntPtr instancePtr, ulong ullUniqueGameID, CSteamID steamIDPlayer, EPlayerResult_t EPlayerResult);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamGameSearch_EndGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EGameSearchErrorCode_t ISteamGameSearch_EndGame(IntPtr instancePtr, ulong ullUniqueGameID);\n#endregion\n#region SteamParties\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetNumActiveBeacons\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamParties_GetNumActiveBeacons(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetBeaconByIndex\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamParties_GetBeaconByIndex(IntPtr instancePtr, uint unIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetBeaconDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParties_GetBeaconDetails(IntPtr instancePtr, PartyBeaconID_t ulBeaconID, out CSteamID pSteamIDBeaconOwner, out SteamPartyBeaconLocation_t pLocation, IntPtr pchMetadata, int cchMetadata);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_JoinParty\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamParties_JoinParty(IntPtr instancePtr, PartyBeaconID_t ulBeaconID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetNumAvailableBeaconLocations\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParties_GetNumAvailableBeaconLocations(IntPtr instancePtr, out uint puNumLocations);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetAvailableBeaconLocations\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParties_GetAvailableBeaconLocations(IntPtr instancePtr, [In, Out] SteamPartyBeaconLocation_t[] pLocationList, uint uMaxNumLocations);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_CreateBeacon\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamParties_CreateBeacon(IntPtr instancePtr, uint unOpenSlots, ref SteamPartyBeaconLocation_t pBeaconLocation, InteropHelp.UTF8StringHandle pchConnectString, InteropHelp.UTF8StringHandle pchMetadata);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_OnReservationCompleted\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamParties_OnReservationCompleted(IntPtr instancePtr, PartyBeaconID_t ulBeacon, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_CancelReservation\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamParties_CancelReservation(IntPtr instancePtr, PartyBeaconID_t ulBeacon, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_ChangeNumOpenSlots\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamParties_ChangeNumOpenSlots(IntPtr instancePtr, PartyBeaconID_t ulBeacon, uint unOpenSlots);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_DestroyBeacon\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParties_DestroyBeacon(IntPtr instancePtr, PartyBeaconID_t ulBeacon);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParties_GetBeaconLocationData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParties_GetBeaconLocationData(IntPtr instancePtr, SteamPartyBeaconLocation_t BeaconLocation, ESteamPartyBeaconLocationData eData, IntPtr pchDataStringOut, int cchDataStringOut);\n#endregion\n#region SteamMusic\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_BIsEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusic_BIsEnabled(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_BIsPlaying\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusic_BIsPlaying(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_GetPlaybackStatus\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern AudioPlayback_Status ISteamMusic_GetPlaybackStatus(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_Play\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMusic_Play(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_Pause\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMusic_Pause(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_PlayPrevious\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMusic_PlayPrevious(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_PlayNext\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMusic_PlayNext(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_SetVolume\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamMusic_SetVolume(IntPtr instancePtr, float flVolume);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusic_GetVolume\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern float ISteamMusic_GetVolume(IntPtr instancePtr);\n#endregion\n#region SteamMusicRemote\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_RegisterSteamMusicRemote\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_RegisterSteamMusicRemote(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_DeregisterSteamMusicRemote\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_DeregisterSteamMusicRemote(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_BIsCurrentMusicRemote\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_BIsCurrentMusicRemote(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_BActivationSuccess\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_BActivationSuccess(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetDisplayName\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetDisplayName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDisplayName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetPNGIcon_64x64\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetPNGIcon_64x64(IntPtr instancePtr, byte[] pvBuffer, uint cbBufferLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnablePlayPrevious\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnablePlayPrevious(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnablePlayNext\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnablePlayNext(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnableShuffled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnableShuffled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnableLooped\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnableLooped(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnableQueue\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnableQueue(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_EnablePlaylists\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_EnablePlaylists(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdatePlaybackStatus\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdatePlaybackStatus(IntPtr instancePtr, AudioPlayback_Status nStatus);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateShuffled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateShuffled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateLooped\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateLooped(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateVolume\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateVolume(IntPtr instancePtr, float flValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_CurrentEntryWillChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_CurrentEntryWillChange(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_CurrentEntryIsAvailable\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_CurrentEntryIsAvailable(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAvailable);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateCurrentEntryText\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateCurrentEntryText(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds(IntPtr instancePtr, int nValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_UpdateCurrentEntryCoverArt\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_UpdateCurrentEntryCoverArt(IntPtr instancePtr, byte[] pvBuffer, uint cbBufferLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_CurrentEntryDidChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_CurrentEntryDidChange(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_QueueWillChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_QueueWillChange(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_ResetQueueEntries\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_ResetQueueEntries(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetQueueEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetQueueEntry(IntPtr instancePtr, int nID, int nPosition, InteropHelp.UTF8StringHandle pchEntryText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetCurrentQueueEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetCurrentQueueEntry(IntPtr instancePtr, int nID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_QueueDidChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_QueueDidChange(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_PlaylistWillChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_PlaylistWillChange(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_ResetPlaylistEntries\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_ResetPlaylistEntries(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetPlaylistEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetPlaylistEntry(IntPtr instancePtr, int nID, int nPosition, InteropHelp.UTF8StringHandle pchEntryText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_SetCurrentPlaylistEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_SetCurrentPlaylistEntry(IntPtr instancePtr, int nID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamMusicRemote_PlaylistDidChange\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamMusicRemote_PlaylistDidChange(IntPtr instancePtr);\n#endregion\n#region SteamNetworking\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_SendP2PPacket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_SendP2PPacket(IntPtr instancePtr, CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_IsP2PPacketAvailable\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_IsP2PPacketAvailable(IntPtr instancePtr, out uint pcubMsgSize, int nChannel);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_ReadP2PPacket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_ReadP2PPacket(IntPtr instancePtr, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_AcceptP2PSessionWithUser(IntPtr instancePtr, CSteamID steamIDRemote);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_CloseP2PSessionWithUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_CloseP2PSessionWithUser(IntPtr instancePtr, CSteamID steamIDRemote);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_CloseP2PChannelWithUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_CloseP2PChannelWithUser(IntPtr instancePtr, CSteamID steamIDRemote, int nChannel);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_GetP2PSessionState\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_GetP2PSessionState(IntPtr instancePtr, CSteamID steamIDRemote, out P2PSessionState_t pConnectionState);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_AllowP2PPacketRelay\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_AllowP2PPacketRelay(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAllow);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_CreateListenSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamNetworking_CreateListenSocket(IntPtr instancePtr, int nVirtualP2PPort, uint nIP, ushort nPort, [MarshalAs(UnmanagedType.I1)] bool bAllowUseOfPacketRelay);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_CreateP2PConnectionSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamNetworking_CreateP2PConnectionSocket(IntPtr instancePtr, CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, [MarshalAs(UnmanagedType.I1)] bool bAllowUseOfPacketRelay);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_CreateConnectionSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamNetworking_CreateConnectionSocket(IntPtr instancePtr, uint nIP, ushort nPort, int nTimeoutSec);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_DestroySocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_DestroySocket(IntPtr instancePtr, SNetSocket_t hSocket, [MarshalAs(UnmanagedType.I1)] bool bNotifyRemoteEnd);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_DestroyListenSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_DestroyListenSocket(IntPtr instancePtr, SNetListenSocket_t hSocket, [MarshalAs(UnmanagedType.I1)] bool bNotifyRemoteEnd);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_SendDataOnSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_SendDataOnSocket(IntPtr instancePtr, SNetSocket_t hSocket, byte[] pubData, uint cubData, [MarshalAs(UnmanagedType.I1)] bool bReliable);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_IsDataAvailableOnSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_IsDataAvailableOnSocket(IntPtr instancePtr, SNetSocket_t hSocket, out uint pcubMsgSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_RetrieveDataFromSocket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_RetrieveDataFromSocket(IntPtr instancePtr, SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_IsDataAvailable\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_IsDataAvailable(IntPtr instancePtr, SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_RetrieveData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_RetrieveData(IntPtr instancePtr, SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_GetSocketInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_GetSocketInfo(IntPtr instancePtr, SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out uint punIPRemote, out ushort punPortRemote);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_GetListenSocketInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamNetworking_GetListenSocketInfo(IntPtr instancePtr, SNetListenSocket_t hListenSocket, out uint pnIP, out ushort pnPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_GetSocketConnectionType\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ESNetSocketConnectionType ISteamNetworking_GetSocketConnectionType(IntPtr instancePtr, SNetSocket_t hSocket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamNetworking_GetMaxPacketSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamNetworking_GetMaxPacketSize(IntPtr instancePtr, SNetSocket_t hSocket);\n#endregion\n#region SteamParentalSettings\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsParentalLockEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsParentalLockEnabled(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsParentalLockLocked\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsParentalLockLocked(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsAppBlocked\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsAppBlocked(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsAppInBlockList\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsAppInBlockList(IntPtr instancePtr, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsFeatureBlocked\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsFeatureBlocked(IntPtr instancePtr, EParentalFeature eFeature);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamParentalSettings_BIsFeatureInBlockList\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamParentalSettings_BIsFeatureInBlockList(IntPtr instancePtr, EParentalFeature eFeature);\n#endregion\n#region SteamRemotePlay\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_GetSessionCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamRemotePlay_GetSessionCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_GetSessionID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamRemotePlay_GetSessionID(IntPtr instancePtr, int iSessionIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_GetSessionSteamID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemotePlay_GetSessionSteamID(IntPtr instancePtr, uint unSessionID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_GetSessionClientName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamRemotePlay_GetSessionClientName(IntPtr instancePtr, uint unSessionID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_GetSessionClientFormFactor\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ESteamDeviceFormFactor ISteamRemotePlay_GetSessionClientFormFactor(IntPtr instancePtr, uint unSessionID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemotePlay_BGetSessionClientResolution\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemotePlay_BGetSessionClientResolution(IntPtr instancePtr, uint unSessionID, out int pnResolutionX, out int pnResolutionY);\n#endregion\n#region SteamRemoteStorage\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWrite\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileWrite(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, int cubData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileRead\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamRemoteStorage_FileRead(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, int cubDataToRead);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWriteAsync\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_FileWriteAsync(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, uint cubData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileReadAsync\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_FileReadAsync(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, uint nOffset, uint cubToRead);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileReadAsyncComplete\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileReadAsyncComplete(IntPtr instancePtr, SteamAPICall_t hReadCall, byte[] pvBuffer, uint cubToRead);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileForget\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileForget(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileDelete\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileDelete(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileShare\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_FileShare(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SetSyncPlatforms\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_SetSyncPlatforms(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, ERemoteStoragePlatform eRemoteStoragePlatform);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWriteStreamOpen\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_FileWriteStreamOpen(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWriteStreamWriteChunk\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileWriteStreamWriteChunk(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle, byte[] pvData, int cubData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWriteStreamClose\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileWriteStreamClose(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileWriteStreamCancel\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileWriteStreamCancel(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileExists\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileExists(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FilePersisted\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FilePersisted(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetFileSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamRemoteStorage_GetFileSize(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetFileTimestamp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern long ISteamRemoteStorage_GetFileTimestamp(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetSyncPlatforms\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ERemoteStoragePlatform ISteamRemoteStorage_GetSyncPlatforms(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetFileCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamRemoteStorage_GetFileCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetFileNameAndSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamRemoteStorage_GetFileNameAndSize(IntPtr instancePtr, int iFile, out int pnFileSizeInBytes);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetQuota\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_GetQuota(IntPtr instancePtr, out ulong pnTotalBytes, out ulong puAvailableBytes);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_IsCloudEnabledForAccount\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_IsCloudEnabledForAccount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_IsCloudEnabledForApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_IsCloudEnabledForApp(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SetCloudEnabledForApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamRemoteStorage_SetCloudEnabledForApp(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bEnabled);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UGCDownload\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_UGCDownload(IntPtr instancePtr, UGCHandle_t hContent, uint unPriority);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetUGCDownloadProgress\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_GetUGCDownloadProgress(IntPtr instancePtr, UGCHandle_t hContent, out int pnBytesDownloaded, out int pnBytesExpected);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetUGCDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_GetUGCDetails(IntPtr instancePtr, UGCHandle_t hContent, out AppId_t pnAppID, out IntPtr ppchName, out int pnFileSizeInBytes, out CSteamID pSteamIDOwner);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UGCRead\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamRemoteStorage_UGCRead(IntPtr instancePtr, UGCHandle_t hContent, byte[] pvData, int cubDataToRead, uint cOffset, EUGCReadAction eAction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetCachedUGCCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamRemoteStorage_GetCachedUGCCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetCachedUGCHandle\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_GetCachedUGCHandle(IntPtr instancePtr, int iCachedContent);\n#if _PS3 || _SERVER\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetFileListFromServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamRemoteStorage_GetFileListFromServer(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FileFetch\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FileFetch(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_FilePersist\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_FilePersist(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SynchronizeToClient\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_SynchronizeToClient(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SynchronizeToServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_SynchronizeToServer(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_ResetFileRequestState\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_ResetFileRequestState(IntPtr instancePtr);\n#endif\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_PublishWorkshopFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_PublishWorkshopFile(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, InteropHelp.UTF8StringHandle pchPreviewFile, AppId_t nConsumerAppId, InteropHelp.UTF8StringHandle pchTitle, InteropHelp.UTF8StringHandle pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, IntPtr pTags, EWorkshopFileType eWorkshopFileType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_CreatePublishedFileUpdateRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_CreatePublishedFileUpdateRequest(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileFile(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFilePreviewFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFilePreviewFile(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchPreviewFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileTitle\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileTitle(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchTitle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileDescription\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileDescription(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchDescription);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileVisibility\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileVisibility(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, ERemoteStoragePublishedFileVisibility eVisibility);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileTags(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, IntPtr pTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_CommitPublishedFileUpdate\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_CommitPublishedFileUpdate(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetPublishedFileDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_GetPublishedFileDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, uint unMaxSecondsOld);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_DeletePublishedFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_DeletePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_EnumerateUserPublishedFiles\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_EnumerateUserPublishedFiles(IntPtr instancePtr, uint unStartIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SubscribePublishedFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_SubscribePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_EnumerateUserSubscribedFiles\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_EnumerateUserSubscribedFiles(IntPtr instancePtr, uint unStartIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UnsubscribePublishedFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_UnsubscribePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchChangeDescription);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetPublishedItemVoteDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_GetPublishedItemVoteDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UpdateUserPublishedItemVote\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_UpdateUserPublishedItemVote(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, [MarshalAs(UnmanagedType.I1)] bool bVoteUp);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_GetUserPublishedItemVoteDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_GetUserPublishedItemVoteDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles(IntPtr instancePtr, CSteamID steamId, uint unStartIndex, IntPtr pRequiredTags, IntPtr pExcludedTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_PublishVideo\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_PublishVideo(IntPtr instancePtr, EWorkshopVideoProvider eVideoProvider, InteropHelp.UTF8StringHandle pchVideoAccount, InteropHelp.UTF8StringHandle pchVideoIdentifier, InteropHelp.UTF8StringHandle pchPreviewFile, AppId_t nConsumerAppId, InteropHelp.UTF8StringHandle pchTitle, InteropHelp.UTF8StringHandle pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, IntPtr pTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_SetUserPublishedFileAction\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_SetUserPublishedFileAction(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, EWorkshopFileAction eAction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_EnumeratePublishedFilesByUserAction\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_EnumeratePublishedFilesByUserAction(IntPtr instancePtr, EWorkshopFileAction eAction, uint unStartIndex);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_EnumeratePublishedWorkshopFiles\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_EnumeratePublishedWorkshopFiles(IntPtr instancePtr, EWorkshopEnumerationType eEnumerationType, uint unStartIndex, uint unCount, uint unDays, IntPtr pTags, IntPtr pUserTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamRemoteStorage_UGCDownloadToLocation\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamRemoteStorage_UGCDownloadToLocation(IntPtr instancePtr, UGCHandle_t hContent, InteropHelp.UTF8StringHandle pchLocation, uint unPriority);\n#endregion\n#region SteamScreenshots\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_WriteScreenshot\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamScreenshots_WriteScreenshot(IntPtr instancePtr, byte[] pubRGB, uint cubRGB, int nWidth, int nHeight);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_AddScreenshotToLibrary\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamScreenshots_AddScreenshotToLibrary(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFilename, InteropHelp.UTF8StringHandle pchThumbnailFilename, int nWidth, int nHeight);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_TriggerScreenshot\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamScreenshots_TriggerScreenshot(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_HookScreenshots\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamScreenshots_HookScreenshots(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bHook);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_SetLocation\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamScreenshots_SetLocation(IntPtr instancePtr, ScreenshotHandle hScreenshot, InteropHelp.UTF8StringHandle pchLocation);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_TagUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamScreenshots_TagUser(IntPtr instancePtr, ScreenshotHandle hScreenshot, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_TagPublishedFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamScreenshots_TagPublishedFile(IntPtr instancePtr, ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_IsScreenshotsHooked\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamScreenshots_IsScreenshotsHooked(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamScreenshots_AddVRScreenshotToLibrary\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamScreenshots_AddVRScreenshotToLibrary(IntPtr instancePtr, EVRScreenshotType eType, InteropHelp.UTF8StringHandle pchFilename, InteropHelp.UTF8StringHandle pchVRFilename);\n#endregion\n#region SteamUGC\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_CreateQueryUserUGCRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_CreateQueryUserUGCRequest(IntPtr instancePtr, AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_CreateQueryAllUGCRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_CreateQueryAllUGCRequest(IntPtr instancePtr, EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_CreateQueryAllUGCRequest0\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_CreateQueryAllUGCRequest0(IntPtr instancePtr, EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, InteropHelp.UTF8StringHandle pchCursor);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_CreateQueryUGCDetailsRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_CreateQueryUGCDetailsRequest(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SendQueryUGCRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_SendQueryUGCRequest(IntPtr instancePtr, UGCQueryHandle_t handle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCResult(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCPreviewURL\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCPreviewURL(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, IntPtr pchURL, uint cchURLSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCMetadata\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCMetadata(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, IntPtr pchMetadata, uint cchMetadatasize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCChildren\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCChildren(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCStatistic\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCStatistic(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCNumAdditionalPreviews\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUGC_GetQueryUGCNumAdditionalPreviews(IntPtr instancePtr, UGCQueryHandle_t handle, uint index);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCAdditionalPreview\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCAdditionalPreview(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint previewIndex, IntPtr pchURLOrVideoID, uint cchURLSize, IntPtr pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCNumKeyValueTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUGC_GetQueryUGCNumKeyValueTags(IntPtr instancePtr, UGCQueryHandle_t handle, uint index);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCKeyValueTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCKeyValueTag(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, IntPtr pchKey, uint cchKeySize, IntPtr pchValue, uint cchValueSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetQueryUGCKeyValueTag0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetQueryUGCKeyValueTag0(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, InteropHelp.UTF8StringHandle pchKey, IntPtr pchValue, uint cchValueSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_ReleaseQueryUGCRequest\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_ReleaseQueryUGCRequest(IntPtr instancePtr, UGCQueryHandle_t handle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddRequiredTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddRequiredTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pTagName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddExcludedTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddExcludedTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pTagName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnOnlyIDs\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnOnlyIDs(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnOnlyIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnKeyValueTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnKeyValueTags(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnKeyValueTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnLongDescription\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnLongDescription(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnLongDescription);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnMetadata\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnMetadata(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnMetadata);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnChildren\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnChildren(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnChildren);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnAdditionalPreviews\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnAdditionalPreviews(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnAdditionalPreviews);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnTotalOnly\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnTotalOnly(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnTotalOnly);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetReturnPlaytimeStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetReturnPlaytimeStats(IntPtr instancePtr, UGCQueryHandle_t handle, uint unDays);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetLanguage\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetLanguage(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pchLanguage);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetAllowCachedResponse\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetAllowCachedResponse(IntPtr instancePtr, UGCQueryHandle_t handle, uint unMaxAgeSeconds);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetCloudFileNameFilter\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetCloudFileNameFilter(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pMatchCloudFileName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetMatchAnyTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetMatchAnyTag(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bMatchAnyTag);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetSearchText\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetSearchText(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pSearchText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetRankedByTrendDays\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetRankedByTrendDays(IntPtr instancePtr, UGCQueryHandle_t handle, uint unDays);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddRequiredKeyValueTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddRequiredKeyValueTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pKey, InteropHelp.UTF8StringHandle pValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RequestUGCDetails\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_RequestUGCDetails(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_CreateItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_CreateItem(IntPtr instancePtr, AppId_t nConsumerAppId, EWorkshopFileType eFileType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_StartItemUpdate\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_StartItemUpdate(IntPtr instancePtr, AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemTitle\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemTitle(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchTitle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemDescription\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemDescription(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchDescription);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemUpdateLanguage\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemUpdateLanguage(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchLanguage);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemMetadata\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemMetadata(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchMetaData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemVisibility\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemVisibility(IntPtr instancePtr, UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemTags(IntPtr instancePtr, UGCUpdateHandle_t updateHandle, IntPtr pTags);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemContent\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemContent(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszContentFolder);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetItemPreview\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetItemPreview(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszPreviewFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetAllowLegacyUpload\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_SetAllowLegacyUpload(IntPtr instancePtr, UGCUpdateHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bAllowLegacyUpload);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveAllItemKeyValueTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_RemoveAllItemKeyValueTags(IntPtr instancePtr, UGCUpdateHandle_t handle);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveItemKeyValueTags\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_RemoveItemKeyValueTags(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddItemKeyValueTag\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddItemKeyValueTag(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddItemPreviewFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddItemPreviewFile(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszPreviewFile, EItemPreviewType type);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddItemPreviewVideo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_AddItemPreviewVideo(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszVideoID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_UpdateItemPreviewFile\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_UpdateItemPreviewFile(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index, InteropHelp.UTF8StringHandle pszPreviewFile);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_UpdateItemPreviewVideo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_UpdateItemPreviewVideo(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index, InteropHelp.UTF8StringHandle pszVideoID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveItemPreview\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_RemoveItemPreview(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SubmitItemUpdate\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_SubmitItemUpdate(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchChangeNote);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetItemUpdateProgress\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EItemUpdateStatus ISteamUGC_GetItemUpdateProgress(IntPtr instancePtr, UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SetUserItemVote\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_SetUserItemVote(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, [MarshalAs(UnmanagedType.I1)] bool bVoteUp);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetUserItemVote\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_GetUserItemVote(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddItemToFavorites\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_AddItemToFavorites(IntPtr instancePtr, AppId_t nAppId, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveItemFromFavorites\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_RemoveItemFromFavorites(IntPtr instancePtr, AppId_t nAppId, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SubscribeItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_SubscribeItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_UnsubscribeItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_UnsubscribeItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetNumSubscribedItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUGC_GetNumSubscribedItems(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetSubscribedItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUGC_GetSubscribedItems(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetItemState\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUGC_GetItemState(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetItemInstallInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetItemInstallInfo(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, IntPtr pchFolder, uint cchFolderSize, out uint punTimeStamp);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetItemDownloadInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_GetItemDownloadInfo(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_DownloadItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_DownloadItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, [MarshalAs(UnmanagedType.I1)] bool bHighPriority);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_BInitWorkshopForGameServer\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUGC_BInitWorkshopForGameServer(IntPtr instancePtr, DepotId_t unWorkshopDepotID, InteropHelp.UTF8StringHandle pszFolder);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_SuspendDownloads\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUGC_SuspendDownloads(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bSuspend);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_StartPlaytimeTracking\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_StartPlaytimeTracking(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_StopPlaytimeTracking\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_StopPlaytimeTracking(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_StopPlaytimeTrackingForAllItems\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_StopPlaytimeTrackingForAllItems(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddDependency\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_AddDependency(IntPtr instancePtr, PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveDependency\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_RemoveDependency(IntPtr instancePtr, PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_AddAppDependency\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_AddAppDependency(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_RemoveAppDependency\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_RemoveAppDependency(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, AppId_t nAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_GetAppDependencies\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_GetAppDependencies(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUGC_DeleteItem\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUGC_DeleteItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID);\n#endregion\n#region SteamUser\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetHSteamUser\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUser_GetHSteamUser(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BLoggedOn\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BLoggedOn(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetSteamID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUser_GetSteamID(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_InitiateGameConnection\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUser_InitiateGameConnection(IntPtr instancePtr, byte[] pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer, [MarshalAs(UnmanagedType.I1)] bool bSecure);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_TerminateGameConnection\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_TerminateGameConnection(IntPtr instancePtr, uint unIPServer, ushort usPortServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_TrackAppUsageEvent\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_TrackAppUsageEvent(IntPtr instancePtr, CGameID gameID, int eAppUsageEvent, InteropHelp.UTF8StringHandle pchExtraInfo);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetUserDataFolder\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_GetUserDataFolder(IntPtr instancePtr, IntPtr pchBuffer, int cubBuffer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_StartVoiceRecording\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_StartVoiceRecording(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_StopVoiceRecording\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_StopVoiceRecording(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetAvailableVoice\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EVoiceResult ISteamUser_GetAvailableVoice(IntPtr instancePtr, out uint pcbCompressed, IntPtr pcbUncompressed_Deprecated, uint nUncompressedVoiceDesiredSampleRate_Deprecated);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetVoice\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EVoiceResult ISteamUser_GetVoice(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bWantCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, [MarshalAs(UnmanagedType.I1)] bool bWantUncompressed_Deprecated, IntPtr pUncompressedDestBuffer_Deprecated, uint cbUncompressedDestBufferSize_Deprecated, IntPtr nUncompressBytesWritten_Deprecated, uint nUncompressedVoiceDesiredSampleRate_Deprecated);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_DecompressVoice\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EVoiceResult ISteamUser_DecompressVoice(IntPtr instancePtr, byte[] pCompressed, uint cbCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, uint nDesiredSampleRate);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetVoiceOptimalSampleRate\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUser_GetVoiceOptimalSampleRate(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetAuthSessionTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUser_GetAuthSessionTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BeginAuthSession\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EBeginAuthSessionResult ISteamUser_BeginAuthSession(IntPtr instancePtr, byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_EndAuthSession\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_EndAuthSession(IntPtr instancePtr, CSteamID steamID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_CancelAuthTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_CancelAuthTicket(IntPtr instancePtr, HAuthTicket hAuthTicket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_UserHasLicenseForApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EUserHasLicenseForAppResult ISteamUser_UserHasLicenseForApp(IntPtr instancePtr, CSteamID steamID, AppId_t appID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BIsBehindNAT\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BIsBehindNAT(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_AdvertiseGame\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUser_AdvertiseGame(IntPtr instancePtr, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_RequestEncryptedAppTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUser_RequestEncryptedAppTicket(IntPtr instancePtr, byte[] pDataToInclude, int cbDataToInclude);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetEncryptedAppTicket\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_GetEncryptedAppTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetGameBadgeLevel\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUser_GetGameBadgeLevel(IntPtr instancePtr, int nSeries, [MarshalAs(UnmanagedType.I1)] bool bFoil);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetPlayerSteamLevel\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUser_GetPlayerSteamLevel(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_RequestStoreAuthURL\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUser_RequestStoreAuthURL(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchRedirectURL);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BIsPhoneVerified\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BIsPhoneVerified(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BIsTwoFactorEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BIsTwoFactorEnabled(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BIsPhoneIdentifying\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BIsPhoneIdentifying(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_BIsPhoneRequiringVerification\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUser_BIsPhoneRequiringVerification(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetMarketEligibility\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUser_GetMarketEligibility(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUser_GetDurationControl\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUser_GetDurationControl(IntPtr instancePtr);\n#endregion\n#region SteamUserStats\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_RequestCurrentStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_RequestCurrentStats(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetStat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out int pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetStat0(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out float pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_SetStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_SetStat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, int nData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_SetStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_SetStat0(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, float fData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_UpdateAvgRateStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_UpdateAvgRateStat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, float flCountThisSession, double dSessionLength);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_SetAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_SetAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_ClearAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_ClearAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetAchievementAndUnlockTime(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved, out uint punUnlockTime);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_StoreStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_StoreStats(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievementIcon\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetAchievementIcon(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamUserStats_GetAchievementDisplayAttribute(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, InteropHelp.UTF8StringHandle pchKey);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_IndicateAchievementProgress\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_IndicateAchievementProgress(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, uint nCurProgress, uint nMaxProgress);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetNumAchievements\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUserStats_GetNumAchievements(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievementName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamUserStats_GetAchievementName(IntPtr instancePtr, uint iAchievement);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_RequestUserStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_RequestUserStats(IntPtr instancePtr, CSteamID steamIDUser);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetUserStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetUserStat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out int pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetUserStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetUserStat0(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out float pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetUserAchievement\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetUserAchievementAndUnlockTime\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetUserAchievementAndUnlockTime(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved, out uint punUnlockTime);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_ResetAllStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_ResetAllStats(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAchievementsToo);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_FindOrCreateLeaderboard\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_FindOrCreateLeaderboard(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_FindLeaderboard\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_FindLeaderboard(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchLeaderboardName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetLeaderboardName\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamUserStats_GetLeaderboardName(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetLeaderboardEntryCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetLeaderboardEntryCount(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetLeaderboardSortMethod\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ELeaderboardSortMethod ISteamUserStats_GetLeaderboardSortMethod(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetLeaderboardDisplayType\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ELeaderboardDisplayType ISteamUserStats_GetLeaderboardDisplayType(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_DownloadLeaderboardEntries\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_DownloadLeaderboardEntries(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_DownloadLeaderboardEntriesForUsers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_DownloadLeaderboardEntriesForUsers(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, [In, Out] CSteamID[] prgUsers, int cUsers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetDownloadedLeaderboardEntry(IntPtr instancePtr, SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, out LeaderboardEntry_t pLeaderboardEntry, [In, Out] int[] pDetails, int cDetailsMax);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_UploadLeaderboardScore\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_UploadLeaderboardScore(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, int nScore, [In, Out] int[] pScoreDetails, int cScoreDetailsCount);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_AttachLeaderboardUGC\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_AttachLeaderboardUGC(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetNumberOfCurrentPlayers\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_GetNumberOfCurrentPlayers(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_RequestGlobalAchievementPercentages\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_RequestGlobalAchievementPercentages(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetMostAchievedAchievementInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetMostAchievedAchievementInfo(IntPtr instancePtr, IntPtr pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetNextMostAchievedAchievementInfo\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetNextMostAchievedAchievementInfo(IntPtr instancePtr, int iIteratorPrevious, IntPtr pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetAchievementAchievedPercent\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetAchievementAchievedPercent(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out float pflPercent);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_RequestGlobalStats\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_RequestGlobalStats(IntPtr instancePtr, int nHistoryDays);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetGlobalStat\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetGlobalStat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, out long pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetGlobalStat0\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetGlobalStat0(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, out double pData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetGlobalStatHistory\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetGlobalStatHistory(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, [In, Out] long[] pData, uint cubData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetGlobalStatHistory0\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUserStats_GetGlobalStatHistory0(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, [In, Out] double[] pData, uint cubData);\n#if _PS3\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_InstallPS3Trophies\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_InstallPS3Trophies(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetTrophySpaceRequiredBeforeInstall\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUserStats_GetTrophySpaceRequiredBeforeInstall(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_SetUserStatsData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_SetUserStatsData(IntPtr instancePtr, IntPtr pvData, uint cubData);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUserStats_GetUserStatsData\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUserStats_GetUserStatsData(IntPtr instancePtr, IntPtr pvData, uint cubData, out uint pcubWritten);\n#endif\n#endregion\n#region SteamUtils\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetSecondsSinceAppActive\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetSecondsSinceAppActive(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetSecondsSinceComputerActive\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetSecondsSinceComputerActive(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetConnectedUniverse\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern EUniverse ISteamUtils_GetConnectedUniverse(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetServerRealTime\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetServerRealTime(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetIPCountry\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamUtils_GetIPCountry(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetImageSize\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_GetImageSize(IntPtr instancePtr, int iImage, out uint pnWidth, out uint pnHeight);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetImageRGBA\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_GetImageRGBA(IntPtr instancePtr, int iImage, byte[] pubDest, int nDestBufferSize);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetCSERIPPort\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_GetCSERIPPort(IntPtr instancePtr, out uint unIP, out ushort usPort);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetCurrentBatteryPower\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern byte ISteamUtils_GetCurrentBatteryPower(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetAppID\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetAppID(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_SetOverlayNotificationPosition\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUtils_SetOverlayNotificationPosition(IntPtr instancePtr, ENotificationPosition eNotificationPosition);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsAPICallCompleted\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsAPICallCompleted(IntPtr instancePtr, SteamAPICall_t hSteamAPICall, out bool pbFailed);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetAPICallFailureReason\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ESteamAPICallFailure ISteamUtils_GetAPICallFailureReason(IntPtr instancePtr, SteamAPICall_t hSteamAPICall);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetAPICallResult\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_GetAPICallResult(IntPtr instancePtr, SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetIPCCallCount\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetIPCCallCount(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_SetWarningMessageHook\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUtils_SetWarningMessageHook(IntPtr instancePtr, SteamAPIWarningMessageHook_t pFunction);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsOverlayEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsOverlayEnabled(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_BOverlayNeedsPresent\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_BOverlayNeedsPresent(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_CheckFileSignature\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern ulong ISteamUtils_CheckFileSignature(IntPtr instancePtr, InteropHelp.UTF8StringHandle szFileName);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_ShowGamepadTextInput\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_ShowGamepadTextInput(IntPtr instancePtr, EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, InteropHelp.UTF8StringHandle pchDescription, uint unCharMax, InteropHelp.UTF8StringHandle pchExistingText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetEnteredGamepadTextLength\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern uint ISteamUtils_GetEnteredGamepadTextLength(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetEnteredGamepadTextInput\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_GetEnteredGamepadTextInput(IntPtr instancePtr, IntPtr pchText, uint cchText);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_GetSteamUILanguage\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern IntPtr ISteamUtils_GetSteamUILanguage(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsSteamRunningInVR\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsSteamRunningInVR(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_SetOverlayNotificationInset\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUtils_SetOverlayNotificationInset(IntPtr instancePtr, int nHorizontalInset, int nVerticalInset);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsSteamInBigPictureMode\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsSteamInBigPictureMode(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_StartVRDashboard\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUtils_StartVRDashboard(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsVRHeadsetStreamingEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsVRHeadsetStreamingEnabled(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_SetVRHeadsetStreamingEnabled\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamUtils_SetVRHeadsetStreamingEnabled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bEnabled);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_IsSteamChinaLauncher\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_IsSteamChinaLauncher(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_InitFilterText\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamUtils_InitFilterText(IntPtr instancePtr);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamUtils_FilterText\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern int ISteamUtils_FilterText(IntPtr instancePtr, IntPtr pchOutFilteredText, uint nByteSizeOutFilteredText, InteropHelp.UTF8StringHandle pchInputMessage, [MarshalAs(UnmanagedType.I1)] bool bLegalOnly);\n#endregion\n#region SteamVideo\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamVideo_GetVideoURL\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamVideo_GetVideoURL(IntPtr instancePtr, AppId_t unVideoAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamVideo_IsBroadcasting\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamVideo_IsBroadcasting(IntPtr instancePtr, out int pnNumViewers);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamVideo_GetOPFSettings\", CallingConvention = CallingConvention.Cdecl)]\n\t\tpublic static extern void ISteamVideo_GetOPFSettings(IntPtr instancePtr, AppId_t unVideoAppID);\n\n\t\t[DllImport(NativeLibraryName, EntryPoint = \"SteamAPI_ISteamVideo_GetOPFStringForApp\", CallingConvention = CallingConvention.Cdecl)]\n\t\t[return: MarshalAs(UnmanagedType.I1)]\n\t\tpublic static extern bool ISteamVideo_GetOPFStringForApp(IntPtr instancePtr, AppId_t unVideoAppID, IntPtr pchBuffer, ref int pnBufferSize);\n#endregion\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/SteamCallbacks.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t// callbacks\n\t//---------------------------------------------------------------------------------\n\t// Purpose: Sent when a new app is installed\n\t//---------------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppListCallbacks + 1)]\n\tpublic struct SteamAppInstalled_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppListCallbacks + 1;\n\t\tpublic AppId_t m_nAppID;\t\t\t// ID of the app that installs\n\t}\n\n\t//---------------------------------------------------------------------------------\n\t// Purpose: Sent when an app is uninstalled\n\t//---------------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppListCallbacks + 2)]\n\tpublic struct SteamAppUninstalled_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppListCallbacks + 2;\n\t\tpublic AppId_t m_nAppID;\t\t\t// ID of the app that installs\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: posted after the user gains ownership of DLC & that DLC is installed\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppsCallbacks + 5)]\n\tpublic struct DlcInstalled_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppsCallbacks + 5;\n\t\tpublic AppId_t m_nAppID;\t\t// AppID of the DLC\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: response to RegisterActivationCode()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppsCallbacks + 8)]\n\tpublic struct RegisterActivationCodeResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppsCallbacks + 8;\n\t\tpublic ERegisterActivationCodeResult m_eResult;\n\t\tpublic uint m_unPackageRegistered;\t\t\t\t\t\t// package that was registered. Only set on success\n\t}\n\n\t//---------------------------------------------------------------------------------\n\t// Purpose: posted after the user gains executes a Steam URL with command line or query parameters\n\t// such as steam://run/<appid>//-commandline/?param1=value1&param2=value2&param3=value3 etc\n\t// while the game is already running.  The new params can be queried\n\t// with GetLaunchQueryParam and GetLaunchCommandLine\n\t//---------------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamAppsCallbacks + 14)]\n\tpublic struct NewUrlLaunchParameters_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppsCallbacks + 14;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: response to RequestAppProofOfPurchaseKey/RequestAllProofOfPurchaseKeys\n\t// for supporting third-party CD keys, or other proof-of-purchase systems.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppsCallbacks + 21)]\n\tpublic struct AppProofOfPurchaseKeyResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppsCallbacks + 21;\n\t\tpublic EResult m_eResult;\n\t\tpublic uint m_nAppID;\n\t\tpublic uint m_cchKeyLength;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cubAppProofOfPurchaseKeyMax)]\n\t\tpublic string m_rgchKey;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: response to GetFileDetails\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamAppsCallbacks + 23)]\n\tpublic struct FileDetailsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamAppsCallbacks + 23;\n\t\tpublic EResult m_eResult;\n\t\tpublic ulong m_ulFileSize;\t// original file size in bytes\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]\n\t\tpublic byte[] m_FileSHA;\t// original file SHA1 hash\n\t\tpublic uint m_unFlags;\t\t//\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when a friends' status changes\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 4)]\n\tpublic struct PersonaStateChange_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 4;\n\t\t\n\t\tpublic ulong m_ulSteamID;\t\t// steamID of the friend who changed\n\t\tpublic EPersonaChange m_nChangeFlags;\t\t// what's changed\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: posted when game overlay activates or deactivates\n\t//\t\t\tthe game can use this to be pause or resume single player games\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 31)]\n\tpublic struct GameOverlayActivated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 31;\n\t\tpublic byte m_bActive;\t// true if it's just been activated, false otherwise\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the user tries to join a different game server from their friends list\n\t//\t\t\tgame client should attempt to connect to specified server when this is received\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 32)]\n\tpublic struct GameServerChangeRequested_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 32;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]\n\t\tpublic string m_rgchServer;\t\t// server address (\"127.0.0.1:27015\", \"tf2.valvesoftware.com\")\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]\n\t\tpublic string m_rgchPassword;\t// server password, if any\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the user tries to join a lobby from their friends list\n\t//\t\t\tgame client should attempt to connect to specified lobby when this is received\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 33)]\n\tpublic struct GameLobbyJoinRequested_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 33;\n\t\tpublic CSteamID m_steamIDLobby;\n\t\t\n\t\t// The friend they did the join via (will be invalid if not directly via a friend)\n\t\t//\n\t\t// On PS3, the friend will be invalid if this was triggered by a PSN invite via the XMB, but\n\t\t// the account type will be console user so you can tell at least that this was from a PSN friend\n\t\t// rather than a Steam friend.\n\t\tpublic CSteamID m_steamIDFriend;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when an avatar is loaded in from a previous GetLargeFriendAvatar() call\n\t//\t\t\tif the image wasn't already available\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 34)]\n\tpublic struct AvatarImageLoaded_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 34;\n\t\tpublic CSteamID m_steamID; // steamid the avatar has been loaded for\n\t\tpublic int m_iImage; // the image index of the now loaded image\n\t\tpublic int m_iWide; // width of the loaded image\n\t\tpublic int m_iTall; // height of the loaded image\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: marks the return of a request officer list call\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 35)]\n\tpublic struct ClanOfficerListResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 35;\n\t\tpublic CSteamID m_steamIDClan;\n\t\tpublic int m_cOfficers;\n\t\tpublic byte m_bSuccess;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: callback indicating updated data about friends rich presence information\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 36)]\n\tpublic struct FriendRichPresenceUpdate_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 36;\n\t\tpublic CSteamID m_steamIDFriend;\t// friend who's rich presence has changed\n\t\tpublic AppId_t m_nAppID;\t\t\t// the appID of the game (should always be the current game)\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the user tries to join a game from their friends list\n\t//\t\t\trich presence will have been set with the \"connect\" key which is set here\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 37)]\n\tpublic struct GameRichPresenceJoinRequested_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 37;\n\t\tpublic CSteamID m_steamIDFriend;\t\t// the friend they did the join via (will be invalid if not directly via a friend)\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchMaxRichPresenceValueLength)]\n\t\tpublic string m_rgchConnect;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a chat message has been received for a clan chat the game has joined\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 38)]\n\tpublic struct GameConnectedClanChatMsg_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 38;\n\t\tpublic CSteamID m_steamIDClanChat;\n\t\tpublic CSteamID m_steamIDUser;\n\t\tpublic int m_iMessageID;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a user has joined a clan chat\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 39)]\n\tpublic struct GameConnectedChatJoin_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 39;\n\t\tpublic CSteamID m_steamIDClanChat;\n\t\tpublic CSteamID m_steamIDUser;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a user has left the chat we're in\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 40)]\n\tpublic struct GameConnectedChatLeave_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 40;\n\t\tpublic CSteamID m_steamIDClanChat;\n\t\tpublic CSteamID m_steamIDUser;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bKicked;\t\t// true if admin kicked\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bDropped;\t// true if Steam connection dropped\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a DownloadClanActivityCounts() call has finished\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 41)]\n\tpublic struct DownloadClanActivityCountsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 41;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bSuccess;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a JoinClanChatRoom() call has finished\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 42)]\n\tpublic struct JoinClanChatRoomCompletionResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 42;\n\t\tpublic CSteamID m_steamIDClanChat;\n\t\tpublic EChatRoomEnterResponse m_eChatRoomEnterResponse;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a chat message has been received from a user\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 43)]\n\tpublic struct GameConnectedFriendChatMsg_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 43;\n\t\tpublic CSteamID m_steamIDUser;\n\t\tpublic int m_iMessageID;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 44)]\n\tpublic struct FriendsGetFollowerCount_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 44;\n\t\tpublic EResult m_eResult;\n\t\tpublic CSteamID m_steamID;\n\t\tpublic int m_nCount;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 45)]\n\tpublic struct FriendsIsFollowing_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 45;\n\t\tpublic EResult m_eResult;\n\t\tpublic CSteamID m_steamID;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bIsFollowing;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 46)]\n\tpublic struct FriendsEnumerateFollowingList_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 46;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cEnumerateFollowersMax)]\n\t\tpublic CSteamID[] m_rgSteamID;\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: reports the result of an attempt to change the user's persona name\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 47)]\n\tpublic struct SetPersonaNameResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 47;\n\t\t\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bSuccess; // true if name change succeeded completely.\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bLocalSuccess; // true if name change was retained locally.  (We might not have been able to communicate with Steam)\n\t\tpublic EResult m_result; // detailed result code\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Invoked when the status of unread messages changes\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 48)]\n\tpublic struct UnreadChatMessagesChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 48;\n\t}\n\n\t// callbacks\n\t// callback notification - A new message is available for reading from the message queue\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameCoordinatorCallbacks + 1)]\n\tpublic struct GCMessageAvailable_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameCoordinatorCallbacks + 1;\n\t\tpublic uint m_nMessageSize;\n\t}\n\n\t// callback notification - A message failed to make it to the GC. It may be down temporarily\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamGameCoordinatorCallbacks + 2)]\n\tpublic struct GCMessageFailed_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameCoordinatorCallbacks + 2;\n\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// won't enforce authentication of users that connect to the server.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Useful when you run a server where the clients may not\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// be connected to the internet but you want them to play (i.e LANs)\n\t// callbacks\n\t// client has been approved to connect to this game server\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 1)]\n\tpublic struct GSClientApprove_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 1;\n\t\tpublic CSteamID m_SteamID;\t\t\t// SteamID of approved player\n\t\tpublic CSteamID m_OwnerSteamID;\t// SteamID of original owner for game license\n\t}\n\n\t// client has been denied to connection to this game server\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 2)]\n\tpublic struct GSClientDeny_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 2;\n\t\tpublic CSteamID m_SteamID;\n\t\tpublic EDenyReason m_eDenyReason;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]\n\t\tpublic string m_rgchOptionalText;\n\t}\n\n\t// request the game server should kick the user\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 3)]\n\tpublic struct GSClientKick_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 3;\n\t\tpublic CSteamID m_SteamID;\n\t\tpublic EDenyReason m_eDenyReason;\n\t}\n\n\t// NOTE: callback values 4 and 5 are skipped because they are used for old deprecated callbacks,\n\t// do not reuse them here.\n\t// client achievement info\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 6)]\n\tpublic struct GSClientAchievementStatus_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 6;\n\t\tpublic ulong m_SteamID;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]\n\t\tpublic string m_pchAchievement;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUnlocked;\n\t}\n\n\t// received when the game server requests to be displayed as secure (VAC protected)\n\t// m_bSecure is true if the game server should display itself as secure to users, false otherwise\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 15)]\n\tpublic struct GSPolicyResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 15;\n\t\tpublic byte m_bSecure;\n\t}\n\n\t// GS gameplay stats info\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 7)]\n\tpublic struct GSGameplayStats_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 7;\n\t\tpublic EResult m_eResult;\t\t\t\t\t// Result of the call\n\t\tpublic int m_nRank;\t\t\t\t\t// Overall rank of the server (0-based)\n\t\tpublic uint m_unTotalConnects;\t\t\t// Total number of clients who have ever connected to the server\n\t\tpublic uint m_unTotalMinutesPlayed;\t\t// Total number of minutes ever played on the server\n\t}\n\n\t// send as a reply to RequestUserGroupStatus()\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 8)]\n\tpublic struct GSClientGroupStatus_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 8;\n\t\tpublic CSteamID m_SteamIDUser;\n\t\tpublic CSteamID m_SteamIDGroup;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bMember;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bOfficer;\n\t}\n\n\t// Sent as a reply to GetServerReputation()\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 9)]\n\tpublic struct GSReputation_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 9;\n\t\tpublic EResult m_eResult;\t\t\t\t// Result of the call;\n\t\tpublic uint m_unReputationScore;\t// The reputation score for the game server\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bBanned;\t\t\t\t// True if the server is banned from the Steam\n\t\t\t\t\t\t\t\t\t\t// master servers\n\t\t\n\t\t// The following members are only filled out if m_bBanned is true. They will all\n\t\t// be set to zero otherwise. Master server bans are by IP so it is possible to be\n\t\t// banned even when the score is good high if there is a bad server on another port.\n\t\t// This information can be used to determine which server is bad.\n\t\t\n\t\tpublic uint m_unBannedIP;\t\t// The IP of the banned server\n\t\tpublic ushort m_usBannedPort;\t\t// The port of the banned server\n\t\tpublic ulong m_ulBannedGameID;\t// The game ID the banned server is serving\n\t\tpublic uint m_unBanExpires;\t\t// Time the ban expires, expressed in the Unix epoch (seconds since 1/1/1970)\n\t}\n\n\t// Sent as a reply to AssociateWithClan()\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 10)]\n\tpublic struct AssociateWithClanResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 10;\n\t\tpublic EResult m_eResult;\t\t\t\t// Result of the call;\n\t}\n\n\t// Sent as a reply to ComputeNewPlayerCompatibility()\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 11)]\n\tpublic struct ComputeNewPlayerCompatibilityResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 11;\n\t\tpublic EResult m_eResult;\t\t\t\t// Result of the call;\n\t\tpublic int m_cPlayersThatDontLikeCandidate;\n\t\tpublic int m_cPlayersThatCandidateDoesntLike;\n\t\tpublic int m_cClanPlayersThatDontLikeCandidate;\n\t\tpublic CSteamID m_SteamIDCandidate;\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the latests stats and achievements have been received\n\t//\t\t\tfrom the server\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerStatsCallbacks)]\n\tpublic struct GSStatsReceived_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerStatsCallbacks;\n\t\tpublic EResult m_eResult;\t\t// Success / error fetching the stats\n\t\tpublic CSteamID m_steamIDUser;\t// The user for whom the stats are retrieved for\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result of a request to store the user stats for a game\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamGameServerStatsCallbacks + 1)]\n\tpublic struct GSStatsStored_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameServerStatsCallbacks + 1;\n\t\tpublic EResult m_eResult;\t\t// success / error\n\t\tpublic CSteamID m_steamIDUser;\t// The user for whom the stats were stored\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback indicating that a user's stats have been unloaded.\n\t//  Call RequestUserStats again to access stats for this user\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 8)]\n\tpublic struct GSStatsUnloaded_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 8;\n\t\tpublic CSteamID m_steamIDUser;\t// User whose stats have been unloaded\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The browser is ready for use\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 1)]\n\tpublic struct HTML_BrowserReady_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 1;\n\t\tpublic HHTMLBrowser unBrowserHandle; // this browser is now fully created and ready to navigate to pages\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: the browser has a pending paint\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 2)]\n\tpublic struct HTML_NeedsPaint_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 2;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the browser that needs the paint\n\t\tpublic IntPtr pBGRA; // a pointer to the B8G8R8A8 data for this surface, valid until SteamAPI_RunCallbacks is next called\n\t\tpublic uint unWide; // the total width of the pBGRA texture\n\t\tpublic uint unTall; // the total height of the pBGRA texture\n\t\tpublic uint unUpdateX; // the offset in X for the damage rect for this update\n\t\tpublic uint unUpdateY; // the offset in Y for the damage rect for this update\n\t\tpublic uint unUpdateWide; // the width of the damage rect for this update\n\t\tpublic uint unUpdateTall; // the height of the damage rect for this update\n\t\tpublic uint unScrollX; // the page scroll the browser was at when this texture was rendered\n\t\tpublic uint unScrollY; // the page scroll the browser was at when this texture was rendered\n\t\tpublic float flPageScale; // the page scale factor on this page when rendered\n\t\tpublic uint unPageSerial; // incremented on each new page load, you can use this to reject draws while navigating to new pages\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The browser wanted to navigate to a new page\n\t//   NOTE - you MUST call AllowStartRequest in response to this callback\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 3)]\n\tpublic struct HTML_StartRequest_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 3;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface navigating\n\t\tpublic string pchURL; // the url they wish to navigate to\n\t\tpublic string pchTarget; // the html link target type  (i.e _blank, _self, _parent, _top )\n\t\tpublic string pchPostData; // any posted data for the request\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bIsRedirect; // true if this was a http/html redirect from the last load request\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The browser has been requested to close due to user interaction (usually from a javascript window.close() call)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 4)]\n\tpublic struct HTML_CloseBrowser_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 4;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: the browser is navigating to a new url\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 5)]\n\tpublic struct HTML_URLChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 5;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface navigating\n\t\tpublic string pchURL; // the url they wish to navigate to\n\t\tpublic string pchPostData; // any posted data for the request\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bIsRedirect; // true if this was a http/html redirect from the last load request\n\t\tpublic string pchPageTitle; // the title of the page\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bNewNavigation; // true if this was from a fresh tab and not a click on an existing page\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: A page is finished loading\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 6)]\n\tpublic struct HTML_FinishedRequest_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 6;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchURL; //\n\t\tpublic string pchPageTitle; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a request to load this url in a new tab\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 7)]\n\tpublic struct HTML_OpenLinkInNewTab_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 7;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchURL; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: the page has a new title now\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 8)]\n\tpublic struct HTML_ChangedTitle_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 8;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchTitle; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: results from a search\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 9)]\n\tpublic struct HTML_SearchResults_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 9;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic uint unResults; //\n\t\tpublic uint unCurrentMatch; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: page history status changed on the ability to go backwards and forward\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 10)]\n\tpublic struct HTML_CanGoBackAndForward_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 10;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bCanGoBack; //\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bCanGoForward; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: details on the visibility and size of the horizontal scrollbar\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 11)]\n\tpublic struct HTML_HorizontalScroll_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 11;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic uint unScrollMax; //\n\t\tpublic uint unScrollCurrent; //\n\t\tpublic float flPageScale; //\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bVisible; //\n\t\tpublic uint unPageSize; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: details on the visibility and size of the vertical scrollbar\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 12)]\n\tpublic struct HTML_VerticalScroll_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 12;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic uint unScrollMax; //\n\t\tpublic uint unScrollCurrent; //\n\t\tpublic float flPageScale; //\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bVisible; //\n\t\tpublic uint unPageSize; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: response to GetLinkAtPosition call\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 13)]\n\tpublic struct HTML_LinkAtPosition_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 13;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic uint x; // NOTE - Not currently set\n\t\tpublic uint y; // NOTE - Not currently set\n\t\tpublic string pchURL; //\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bInput; //\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool bLiveLink; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: show a Javascript alert dialog, call JSDialogResponse\n\t//   when the user dismisses this dialog (or right away to ignore it)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 14)]\n\tpublic struct HTML_JSAlert_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 14;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchMessage; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: show a Javascript confirmation dialog, call JSDialogResponse\n\t//   when the user dismisses this dialog (or right away to ignore it)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 15)]\n\tpublic struct HTML_JSConfirm_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 15;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchMessage; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: when received show a file open dialog\n\t//   then call FileLoadDialogResponse with the file(s) the user selected.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 16)]\n\tpublic struct HTML_FileOpenDialog_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 16;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchTitle; //\n\t\tpublic string pchInitialFile; //\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a new html window is being created.\n\t//\n\t// IMPORTANT NOTE: at this time, the API does not allow you to acknowledge or\n\t// render the contents of this new window, so the new window is always destroyed\n\t// immediately. The URL and other parameters of the new window are passed here\n\t// to give your application the opportunity to call CreateBrowser and set up\n\t// a new browser in response to the attempted popup, if you wish to do so.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 21)]\n\tpublic struct HTML_NewWindow_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 21;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the current surface\n\t\tpublic string pchURL; // the page to load\n\t\tpublic uint unX; // the x pos into the page to display the popup\n\t\tpublic uint unY; // the y pos into the page to display the popup\n\t\tpublic uint unWide; // the total width of the pBGRA texture\n\t\tpublic uint unTall; // the total height of the pBGRA texture\n\t\tpublic HHTMLBrowser unNewWindow_BrowserHandle_IGNORE;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: change the cursor to display\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 22)]\n\tpublic struct HTML_SetCursor_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 22;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic uint eMouseCursor; // the EMouseCursor to display\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: informational message from the browser\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 23)]\n\tpublic struct HTML_StatusText_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 23;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchMsg; // the EMouseCursor to display\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: show a tooltip\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 24)]\n\tpublic struct HTML_ShowToolTip_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 24;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchMsg; // the EMouseCursor to display\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: update the text of an existing tooltip\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 25)]\n\tpublic struct HTML_UpdateToolTip_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 25;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t\tpublic string pchMsg; // the EMouseCursor to display\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: hide the tooltip you are showing\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 26)]\n\tpublic struct HTML_HideToolTip_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 26;\n\t\tpublic HHTMLBrowser unBrowserHandle; // the handle of the surface\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The browser has restarted due to an internal failure, use this new handle value\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 27)]\n\tpublic struct HTML_BrowserRestarted_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 27;\n\t\tpublic HHTMLBrowser unBrowserHandle; // this is the new browser handle after the restart\n\t\tpublic HHTMLBrowser unOldBrowserHandle; // the handle for the browser before the restart, if your handle was this then switch to using unBrowserHandle for API calls\n\t}\n\n\t// callbacks\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientHTTPCallbacks + 1)]\n\tpublic struct HTTPRequestCompleted_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientHTTPCallbacks + 1;\n\t\t\n\t\t// Handle value for the request that has completed.\n\t\tpublic HTTPRequestHandle m_hRequest;\n\t\t\n\t\t// Context value that the user defined on the request that this callback is associated with, 0 if\n\t\t// no context value was set.\n\t\tpublic ulong m_ulContextValue;\n\t\t\n\t\t// This will be true if we actually got any sort of response from the server (even an error).\n\t\t// It will be false if we failed due to an internal error or client side network failure.\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bRequestSuccessful;\n\t\t\n\t\t// Will be the HTTP status code value returned by the server, k_EHTTPStatusCode200OK is the normal\n\t\t// OK response, if you get something else you probably need to treat it as a failure.\n\t\tpublic EHTTPStatusCode m_eStatusCode;\n\t\t\n\t\tpublic uint m_unBodySize; // Same as GetHTTPResponseBodySize()\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientHTTPCallbacks + 2)]\n\tpublic struct HTTPRequestHeadersReceived_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientHTTPCallbacks + 2;\n\t\t\n\t\t// Handle value for the request that has received headers.\n\t\tpublic HTTPRequestHandle m_hRequest;\n\t\t\n\t\t// Context value that the user defined on the request that this callback is associated with, 0 if\n\t\t// no context value was set.\n\t\tpublic ulong m_ulContextValue;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientHTTPCallbacks + 3)]\n\tpublic struct HTTPRequestDataReceived_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientHTTPCallbacks + 3;\n\t\t\n\t\t// Handle value for the request that has received data.\n\t\tpublic HTTPRequestHandle m_hRequest;\n\t\t\n\t\t// Context value that the user defined on the request that this callback is associated with, 0 if\n\t\t// no context value was set.\n\t\tpublic ulong m_ulContextValue;\n\t\t\n\t\t\n\t\t// Offset to provide to GetHTTPStreamingResponseBodyData to get this chunk of data\n\t\tpublic uint m_cOffset;\n\t\t\n\t\t// Size to provide to GetHTTPStreamingResponseBodyData to get this chunk of data\n\t\tpublic uint m_cBytesReceived;\n\t}\n\n\t// SteamInventoryResultReady_t callbacks are fired whenever asynchronous\n\t// results transition from \"Pending\" to \"OK\" or an error state. There will\n\t// always be exactly one callback per handle.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 0)]\n\tpublic struct SteamInventoryResultReady_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 0;\n\t\tpublic SteamInventoryResult_t m_handle;\n\t\tpublic EResult m_result;\n\t}\n\n\t// SteamInventoryFullUpdate_t callbacks are triggered when GetAllItems\n\t// successfully returns a result which is newer / fresher than the last\n\t// known result. (It will not trigger if the inventory hasn't changed,\n\t// or if results from two overlapping calls are reversed in flight and\n\t// the earlier result is already known to be stale/out-of-date.)\n\t// The normal ResultReady callback will still be triggered immediately\n\t// afterwards; this is an additional notification for your convenience.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 1)]\n\tpublic struct SteamInventoryFullUpdate_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 1;\n\t\tpublic SteamInventoryResult_t m_handle;\n\t}\n\n\t// A SteamInventoryDefinitionUpdate_t callback is triggered whenever\n\t// item definitions have been updated, which could be in response to\n\t// LoadItemDefinitions() or any other async request which required\n\t// a definition update in order to process results from the server.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 2)]\n\tpublic struct SteamInventoryDefinitionUpdate_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 2;\n\t}\n\n\t// Returned\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 3)]\n\tpublic struct SteamInventoryEligiblePromoItemDefIDs_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 3;\n\t\tpublic EResult m_result;\n\t\tpublic CSteamID m_steamID;\n\t\tpublic int m_numEligiblePromoItemDefs;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bCachedData;\t// indicates that the data was retrieved from the cache and not the server\n\t}\n\n\t// Triggered from StartPurchase call\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 4)]\n\tpublic struct SteamInventoryStartPurchaseResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 4;\n\t\tpublic EResult m_result;\n\t\tpublic ulong m_ulOrderID;\n\t\tpublic ulong m_ulTransID;\n\t}\n\n\t// Triggered from RequestPrices\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientInventoryCallbacks + 5)]\n\tpublic struct SteamInventoryRequestPricesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientInventoryCallbacks + 5;\n\t\tpublic EResult m_result;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]\n\t\tpublic string m_rgchCurrency;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Callbacks for ISteamMatchmaking (which go through the regular Steam callback registration system)\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a server was added/removed from the favorites list, you should refresh now\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 2)]\n\tpublic struct FavoritesListChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 2;\n\t\tpublic uint m_nIP; // an IP of 0 means reload the whole list, any other value means just one server\n\t\tpublic uint m_nQueryPort;\n\t\tpublic uint m_nConnPort;\n\t\tpublic uint m_nAppID;\n\t\tpublic uint m_nFlags;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bAdd; // true if this is adding the entry, otherwise it is a remove\n\t\tpublic AccountID_t m_unAccountId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Someone has invited you to join a Lobby\n\t//\t\t\tnormally you don't need to do anything with this, since\n\t//\t\t\tthe Steam UI will also display a '<user> has invited you to the lobby, join?' dialog\n\t//\n\t//\t\t\tif the user outside a game chooses to join, your game will be launched with the parameter \"+connect_lobby <64-bit lobby id>\",\n\t//\t\t\tor with the callback GameLobbyJoinRequested_t if they're already in-game\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 3)]\n\tpublic struct LobbyInvite_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 3;\n\t\t\n\t\tpublic ulong m_ulSteamIDUser;\t\t// Steam ID of the person making the invite\n\t\tpublic ulong m_ulSteamIDLobby;\t// Steam ID of the Lobby\n\t\tpublic ulong m_ulGameID;\t\t\t// GameID of the Lobby\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Sent on entering a lobby, or on failing to enter\n\t//\t\t\tm_EChatRoomEnterResponse will be set to k_EChatRoomEnterResponseSuccess on success,\n\t//\t\t\tor a higher value on failure (see enum EChatRoomEnterResponse)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 4)]\n\tpublic struct LobbyEnter_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 4;\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t\t\t\t\t\t// SteamID of the Lobby you have entered\n\t\tpublic uint m_rgfChatPermissions;\t\t\t\t\t\t// Permissions of the current user\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bLocked;\t\t\t\t\t\t\t\t\t\t// If true, then only invited users may join\n\t\tpublic uint m_EChatRoomEnterResponse;\t// EChatRoomEnterResponse\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The lobby metadata has changed\n\t//\t\t\tif m_ulSteamIDMember is the steamID of a lobby member, use GetLobbyMemberData() to access per-user details\n\t//\t\t\tif m_ulSteamIDMember == m_ulSteamIDLobby, use GetLobbyData() to access lobby metadata\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 5)]\n\tpublic struct LobbyDataUpdate_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 5;\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t// steamID of the Lobby\n\t\tpublic ulong m_ulSteamIDMember;\t\t// steamID of the member whose data changed, or the room itself\n\t\tpublic byte m_bSuccess;\t\t\t\t// true if we lobby data was successfully changed;\n\t\t\t\t\t\t\t\t\t\t// will only be false if RequestLobbyData() was called on a lobby that no longer exists\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The lobby chat room state has changed\n\t//\t\t\tthis is usually sent when a user has joined or left the lobby\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 6)]\n\tpublic struct LobbyChatUpdate_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 6;\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t\t// Lobby ID\n\t\tpublic ulong m_ulSteamIDUserChanged;\t\t// user who's status in the lobby just changed - can be recipient\n\t\tpublic ulong m_ulSteamIDMakingChange;\t\t// Chat member who made the change (different from SteamIDUserChange if kicking, muting, etc.)\n\t\t\t\t\t\t\t\t\t\t\t// for example, if one user kicks another from the lobby, this will be set to the id of the user who initiated the kick\n\t\tpublic uint m_rgfChatMemberStateChange;\t// bitfield of EChatMemberStateChange values\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: A chat message for this lobby has been sent\n\t//\t\t\tuse GetLobbyChatEntry( m_iChatID ) to retrieve the contents of this message\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 7)]\n\tpublic struct LobbyChatMsg_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 7;\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t\t// the lobby id this is in\n\t\tpublic ulong m_ulSteamIDUser;\t\t\t// steamID of the user who has sent this message\n\t\tpublic byte m_eChatEntryType;\t\t\t// type of message\n\t\tpublic uint m_iChatID;\t\t\t\t// index of the chat entry to lookup\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: A game created a game for all the members of the lobby to join,\n\t//\t\t\tas triggered by a SetLobbyGameServer()\n\t//\t\t\tit's up to the individual clients to take action on this; the usual\n\t//\t\t\tgame behavior is to leave the lobby and connect to the specified game server\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 9)]\n\tpublic struct LobbyGameCreated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 9;\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t// the lobby we were in\n\t\tpublic ulong m_ulSteamIDGameServer;\t// the new game server that has been created or found for the lobby members\n\t\tpublic uint m_unIP;\t\t\t\t\t// IP & Port of the game server (if any)\n\t\tpublic ushort m_usPort;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Number of matching lobbies found\n\t//\t\t\titerate the returned lobbies with GetLobbyByIndex(), from values 0 to m_nLobbiesMatching-1\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 10)]\n\tpublic struct LobbyMatchList_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 10;\n\t\tpublic uint m_nLobbiesMatching;\t\t// Number of lobbies that matched search criteria and we have SteamIDs for\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: posted if a user is forcefully removed from a lobby\n\t//\t\t\tcan occur if a user loses connection to Steam\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 12)]\n\tpublic struct LobbyKicked_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 12;\n\t\tpublic ulong m_ulSteamIDLobby;\t\t\t// Lobby\n\t\tpublic ulong m_ulSteamIDAdmin;\t\t\t// User who kicked you - possibly the ID of the lobby itself\n\t\tpublic byte m_bKickedDueToDisconnect;\t\t// true if you were kicked from the lobby due to the user losing connection to Steam (currently always true)\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Result of our request to create a Lobby\n\t//\t\t\tm_eResult == k_EResultOK on success\n\t//\t\t\tat this point, the lobby has been joined and is ready for use\n\t//\t\t\ta LobbyEnter_t callback will also be received (since the local user is joining their own lobby)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 13)]\n\tpublic struct LobbyCreated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 13;\n\t\t\n\t\tpublic EResult m_eResult;\t\t// k_EResultOK - the lobby was successfully created\n\t\t\t\t\t\t\t\t// k_EResultNoConnection - your Steam client doesn't have a connection to the back-end\n\t\t\t\t\t\t\t\t// k_EResultTimeout - you the message to the Steam servers, but it didn't respond\n\t\t\t\t\t\t\t\t// k_EResultFail - the server responded, but with an unknown internal error\n\t\t\t\t\t\t\t\t// k_EResultAccessDenied - your game isn't set to allow lobbies, or your client does haven't rights to play the game\n\t\t\t\t\t\t\t\t// k_EResultLimitExceeded - your game client has created too many lobbies\n\t\t\n\t\tpublic ulong m_ulSteamIDLobby;\t\t// chat room, zero if failed\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Result of our request to create a Lobby\n\t//\t\t\tm_eResult == k_EResultOK on success\n\t//\t\t\tat this point, the lobby has been joined and is ready for use\n\t//\t\t\ta LobbyEnter_t callback will also be received (since the local user is joining their own lobby)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 16)]\n\tpublic struct FavoritesListAccountsUpdated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 16;\n\t\t\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Callbacks for ISteamGameSearch (which go through the regular Steam callback registration system)\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 1)]\n\tpublic struct SearchForGameProgressCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 1;\n\t\t\n\t\tpublic ulong m_ullSearchID;\t// all future callbacks referencing this search will include this Search ID\n\t\t\n\t\tpublic EResult m_eResult; // if search has started this result will be k_EResultOK, any other value indicates search has failed to start or has terminated\n\t\tpublic CSteamID m_lobbyID; // lobby ID if lobby search, invalid steamID otherwise\n\t\tpublic CSteamID m_steamIDEndedSearch; // if search was terminated, steamID that terminated search\n\t\t\n\t\tpublic int m_nSecondsRemainingEstimate;\n\t\tpublic int m_cPlayersSearching;\n\t}\n\n\t// notification to all players searching that a game has been found\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 2)]\n\tpublic struct SearchForGameResultCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 2;\n\t\t\n\t\tpublic ulong m_ullSearchID;\n\t\t\n\t\tpublic EResult m_eResult; // if game/host was lost this will be an error value\n\t\t\n\t\t// if m_bGameFound is true the following are non-zero\n\t\tpublic int m_nCountPlayersInGame;\n\t\tpublic int m_nCountAcceptedGame;\n\t\t// if m_steamIDHost is valid the host has started the game\n\t\tpublic CSteamID m_steamIDHost;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bFinalCallback;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// ISteamGameSearch : Game Host API callbacks\n\t// callback from RequestPlayersForGame when the matchmaking service has started or ended search\n\t// callback will also follow a call from CancelRequestPlayersForGame - m_bSearchInProgress will be false\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 11)]\n\tpublic struct RequestPlayersForGameProgressCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 11;\n\t\t\n\t\tpublic EResult m_eResult;\t\t// m_ullSearchID will be non-zero if this is k_EResultOK\n\t\tpublic ulong m_ullSearchID; \t// all future callbacks referencing this search will include this Search ID\n\t}\n\n\t// callback from RequestPlayersForGame\n\t// one of these will be sent per player\n\t// followed by additional callbacks when players accept or decline the game\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 12)]\n\tpublic struct RequestPlayersForGameResultCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 12;\n\t\t\n\t\tpublic EResult m_eResult;\t\t// m_ullSearchID will be non-zero if this is k_EResultOK\n\t\tpublic ulong m_ullSearchID;\n\t\t\n\t\tpublic CSteamID m_SteamIDPlayerFound; // player steamID\n\t\tpublic CSteamID m_SteamIDLobby;\t// if the player is in a lobby, the lobby ID\n\t\tpublic PlayerAcceptState_t m_ePlayerAcceptState;\n\t\tpublic int m_nPlayerIndex;\n\t\tpublic int m_nTotalPlayersFound;\t\t// expect this many callbacks at minimum\n\t\tpublic int m_nTotalPlayersAcceptedGame;\n\t\tpublic int m_nSuggestedTeamIndex;\n\t\tpublic ulong m_ullUniqueGameID;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 13)]\n\tpublic struct RequestPlayersForGameFinalResultCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 13;\n\t\t\n\t\tpublic EResult m_eResult;\n\t\tpublic ulong m_ullSearchID;\n\t\tpublic ulong m_ullUniqueGameID;\n\t}\n\n\t// this callback confirms that results were received by the matchmaking service for this player\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 14)]\n\tpublic struct SubmitPlayerResultResultCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 14;\n\t\t\n\t\tpublic EResult m_eResult;\n\t\tpublic ulong ullUniqueGameID;\n\t\tpublic CSteamID steamIDPlayer;\n\t}\n\n\t// this callback confirms that the game is recorded as complete on the matchmaking service\n\t// the next call to RequestPlayersForGame will generate a new unique game ID\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 15)]\n\tpublic struct EndGameResultCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 15;\n\t\t\n\t\tpublic EResult m_eResult;\n\t\tpublic ulong ullUniqueGameID;\n\t}\n\n\t// Steam has responded to the user request to join a party via the given Beacon ID.\n\t// If successful, the connect string contains game-specific instructions to connect\n\t// to the game with that party.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 1)]\n\tpublic struct JoinPartyCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 1;\n\t\t\n\t\tpublic EResult m_eResult;\n\t\tpublic PartyBeaconID_t m_ulBeaconID;\n\t\tpublic CSteamID m_SteamIDBeaconOwner;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]\n\t\tpublic string m_rgchConnectString;\n\t}\n\n\t// Response to CreateBeacon request. If successful, the beacon ID is provided.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 2)]\n\tpublic struct CreateBeaconCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 2;\n\t\t\n\t\tpublic EResult m_eResult;\n\t\tpublic PartyBeaconID_t m_ulBeaconID;\n\t}\n\n\t// Someone has used the beacon to join your party - they are in-flight now\n\t// and we've reserved one of the open slots for them.\n\t// You should confirm when they join your party by calling OnReservationCompleted().\n\t// Otherwise, Steam may timeout their reservation eventually.\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 3)]\n\tpublic struct ReservationNotificationCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 3;\n\t\t\n\t\tpublic PartyBeaconID_t m_ulBeaconID;\n\t\tpublic CSteamID m_steamIDJoiner;\n\t}\n\n\t// Response to ChangeNumOpenSlots call\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 4)]\n\tpublic struct ChangeNumOpenSlotsCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 4;\n\t\t\n\t\tpublic EResult m_eResult;\n\t}\n\n\t// The list of possible Party beacon locations has changed\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 5)]\n\tpublic struct AvailableBeaconLocationsUpdated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 5;\n\t}\n\n\t// The list of active beacons may have changed\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 6)]\n\tpublic struct ActiveBeaconsUpdated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 6;\n\t}\n\n\t// callbacks\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicCallbacks + 1)]\n\tpublic struct PlaybackStatusHasChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicCallbacks + 1;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicCallbacks + 2)]\n\tpublic struct VolumeHasChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicCallbacks + 2;\n\t\tpublic float m_flNewVolume;\n\t}\n\n\t// callbacks\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 1)]\n\tpublic struct MusicPlayerRemoteWillActivate_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 1;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 2)]\n\tpublic struct MusicPlayerRemoteWillDeactivate_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 2;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 3)]\n\tpublic struct MusicPlayerRemoteToFront_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 3;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 4)]\n\tpublic struct MusicPlayerWillQuit_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 4;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 5)]\n\tpublic struct MusicPlayerWantsPlay_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 5;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 6)]\n\tpublic struct MusicPlayerWantsPause_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 6;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 7)]\n\tpublic struct MusicPlayerWantsPlayPrevious_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 7;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 8)]\n\tpublic struct MusicPlayerWantsPlayNext_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 8;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 9)]\n\tpublic struct MusicPlayerWantsShuffled_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 9;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bShuffled;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 10)]\n\tpublic struct MusicPlayerWantsLooped_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 10;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bLooped;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicCallbacks + 11)]\n\tpublic struct MusicPlayerWantsVolume_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicCallbacks + 11;\n\t\tpublic float m_flNewVolume;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicCallbacks + 12)]\n\tpublic struct MusicPlayerSelectsQueueEntry_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicCallbacks + 12;\n\t\tpublic int nID;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicCallbacks + 13)]\n\tpublic struct MusicPlayerSelectsPlaylistEntry_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicCallbacks + 13;\n\t\tpublic int nID;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 14)]\n\tpublic struct MusicPlayerWantsPlayingRepeatStatus_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 14;\n\t\tpublic int m_nPlayingRepeatStatus;\n\t}\n\n\t// callbacks\n\t// callback notification - a user wants to talk to us over the P2P channel via the SendP2PPacket() API\n\t// in response, a call to AcceptP2PPacketsFromUser() needs to be made, if you want to talk with them\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 2)]\n\tpublic struct P2PSessionRequest_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 2;\n\t\tpublic CSteamID m_steamIDRemote;\t\t\t// user who wants to talk to us\n\t}\n\n\t// callback notification - packets can't get through to the specified user via the SendP2PPacket() API\n\t// all packets queued packets unsent at this point will be dropped\n\t// further attempts to send will retry making the connection (but will be dropped if we fail again)\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\t[CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 3)]\n\tpublic struct P2PSessionConnectFail_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 3;\n\t\tpublic CSteamID m_steamIDRemote;\t\t\t// user we were sending packets to\n\t\tpublic byte m_eP2PSessionError;\t\t\t// EP2PSessionError indicating why we're having trouble\n\t}\n\n\t// callback notification - status of a socket has changed\n\t// used as part of the CreateListenSocket() / CreateP2PConnectionSocket()\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 1)]\n\tpublic struct SocketStatusCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 1;\n\t\tpublic SNetSocket_t m_hSocket;\t\t\t\t// the socket used to send/receive data to the remote host\n\t\tpublic SNetListenSocket_t m_hListenSocket;\t// this is the server socket that we were listening on; NULL if this was an outgoing connection\n\t\tpublic CSteamID m_steamIDRemote;\t\t\t// remote steamID we have connected to, if it has one\n\t\tpublic int m_eSNetSocketState;\t\t\t\t// socket state, ESNetSocketState\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback for querying UGC\n\t//-----------------------------------------------------------------------------\n\t[CallbackIdentity(Constants.k_ISteamParentalSettingsCallbacks + 1)]\n\tpublic struct SteamParentalSettingsChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_ISteamParentalSettingsCallbacks + 1;\n\t}\n\n\t// callbacks\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamRemotePlayCallbacks + 1)]\n\tpublic struct SteamRemotePlaySessionConnected_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamRemotePlayCallbacks + 1;\n\t\tpublic uint m_unSessionID;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamRemotePlayCallbacks + 2)]\n\tpublic struct SteamRemotePlaySessionDisconnected_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamRemotePlayCallbacks + 2;\n\t\tpublic uint m_unSessionID;\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent when the local file cache is fully synced with the server for an app\n\t//          That means that an application can be started and has all latest files\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 1)]\n\tpublic struct RemoteStorageAppSyncedClient_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 1;\n\t\tpublic AppId_t m_nAppID;\n\t\tpublic EResult m_eResult;\n\t\tpublic int m_unNumDownloads;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent when the server is fully synced with the local file cache for an app\n\t//          That means that we can shutdown Steam and our data is stored on the server\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 2)]\n\tpublic struct RemoteStorageAppSyncedServer_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 2;\n\t\tpublic AppId_t m_nAppID;\n\t\tpublic EResult m_eResult;\n\t\tpublic int m_unNumUploads;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Status of up and downloads during a sync session\n\t//\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 3)]\n\tpublic struct RemoteStorageAppSyncProgress_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 3;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]\n\t\tpublic string m_rgchCurrentFile;\t\t\t\t// Current file being transferred\n\t\tpublic AppId_t m_nAppID;\t\t\t\t\t\t\t// App this info relates to\n\t\tpublic uint m_uBytesTransferredThisChunk;\t\t// Bytes transferred this chunk\n\t\tpublic double m_dAppPercentComplete;\t\t\t\t// Percent complete that this app's transfers are\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUploading;\t\t\t\t\t\t\t// if false, downloading\n\t}\n\n\t//\n\t// IMPORTANT! k_iClientRemoteStorageCallbacks + 4 is used, see iclientremotestorage.h\n\t//\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Sent after we've determined the list of files that are out of sync\n\t//          with the server.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 5)]\n\tpublic struct RemoteStorageAppSyncStatusCheck_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 5;\n\t\tpublic AppId_t m_nAppID;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to FileShare()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 7)]\n\tpublic struct RemoteStorageFileShareResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 7;\n\t\tpublic EResult m_eResult;\t\t\t// The result of the operation\n\t\tpublic UGCHandle_t m_hFile;\t\t// The handle that can be shared with users and features\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]\n\t\tpublic string m_rgchFilename; // The name of the file that was shared\n\t}\n\n\t// k_iClientRemoteStorageCallbacks + 8 is deprecated! Do not reuse\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to PublishFile()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 9)]\n\tpublic struct RemoteStoragePublishFileResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 9;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUserNeedsToAcceptWorkshopLegalAgreement;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to DeletePublishedFile()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 11)]\n\tpublic struct RemoteStorageDeletePublishedFileResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 11;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to EnumerateUserPublishedFiles()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 12)]\n\tpublic struct RemoteStorageEnumerateUserPublishedFilesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 12;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic PublishedFileId_t[] m_rgPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to SubscribePublishedFile()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 13)]\n\tpublic struct RemoteStorageSubscribePublishedFileResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 13;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to EnumerateSubscribePublishedFiles()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 14)]\n\tpublic struct RemoteStorageEnumerateUserSubscribedFilesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 14;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic PublishedFileId_t[] m_rgPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic uint[] m_rgRTimeSubscribed;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to UnsubscribePublishedFile()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 15)]\n\tpublic struct RemoteStorageUnsubscribePublishedFileResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 15;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to CommitPublishedFileUpdate()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 16)]\n\tpublic struct RemoteStorageUpdatePublishedFileResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 16;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUserNeedsToAcceptWorkshopLegalAgreement;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to UGCDownload()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 17)]\n\tpublic struct RemoteStorageDownloadUGCResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 17;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic UGCHandle_t m_hFile;\t\t\t// The handle to the file that was attempted to be downloaded.\n\t\tpublic AppId_t m_nAppID;\t\t\t\t// ID of the app that created this file.\n\t\tpublic int m_nSizeInBytes;\t\t\t// The size of the file that was downloaded, in bytes.\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]\n\t\tpublic string m_pchFileName;\t\t// The name of the file that was downloaded.\n\t\tpublic ulong m_ulSteamIDOwner;\t\t// Steam ID of the user who created this content.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to GetPublishedFileDetails()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 18)]\n\tpublic struct RemoteStorageGetPublishedFileDetailsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 18;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic AppId_t m_nCreatorAppID;\t\t// ID of the app that created this file.\n\t\tpublic AppId_t m_nConsumerAppID;\t\t// ID of the app that will consume this file.\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentTitleMax)]\n\t\tpublic string m_rgchTitle;\t\t// title of document\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)]\n\t\tpublic string m_rgchDescription;\t// description of document\n\t\tpublic UGCHandle_t m_hFile;\t\t\t// The handle of the primary file\n\t\tpublic UGCHandle_t m_hPreviewFile;\t\t// The handle of the preview file\n\t\tpublic ulong m_ulSteamIDOwner;\t\t// Steam ID of the user who created this content.\n\t\tpublic uint m_rtimeCreated;\t\t\t// time when the published file was created\n\t\tpublic uint m_rtimeUpdated;\t\t\t// time when the published file was last updated\n\t\tpublic ERemoteStoragePublishedFileVisibility m_eVisibility;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bBanned;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchTagListMax)]\n\t\tpublic string m_rgchTags;\t// comma separated list of all tags associated with this file\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bTagsTruncated;\t\t\t// whether the list of tags was too long to be returned in the provided buffer\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]\n\t\tpublic string m_pchFileName;\t\t// The name of the primary file\n\t\tpublic int m_nFileSize;\t\t\t\t// Size of the primary file\n\t\tpublic int m_nPreviewFileSize;\t\t// Size of the preview file\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedFileURLMax)]\n\t\tpublic string m_rgchURL;\t// URL (for a video or a website)\n\t\tpublic EWorkshopFileType m_eFileType;\t// Type of the file\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bAcceptedForUse;\t\t\t// developer has specifically flagged this item as accepted in the Workshop\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 19)]\n\tpublic struct RemoteStorageEnumerateWorkshopFilesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 19;\n\t\tpublic EResult m_eResult;\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic PublishedFileId_t[] m_rgPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic float[] m_rgScore;\n\t\tpublic AppId_t m_nAppId;\n\t\tpublic uint m_unStartIndex;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of GetPublishedItemVoteDetails\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 20)]\n\tpublic struct RemoteStorageGetPublishedItemVoteDetailsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 20;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_unPublishedFileId;\n\t\tpublic int m_nVotesFor;\n\t\tpublic int m_nVotesAgainst;\n\t\tpublic int m_nReports;\n\t\tpublic float m_fScore;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: User subscribed to a file for the app (from within the app or on the web)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 21)]\n\tpublic struct RemoteStoragePublishedFileSubscribed_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 21;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic AppId_t m_nAppID;\t\t\t\t\t\t// ID of the app that will consume this file.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: User unsubscribed from a file for the app (from within the app or on the web)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 22)]\n\tpublic struct RemoteStoragePublishedFileUnsubscribed_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 22;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic AppId_t m_nAppID;\t\t\t\t\t\t// ID of the app that will consume this file.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Published file that a user owns was deleted (from within the app or the web)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 23)]\n\tpublic struct RemoteStoragePublishedFileDeleted_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 23;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic AppId_t m_nAppID;\t\t\t\t\t\t// ID of the app that will consume this file.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to UpdateUserPublishedItemVote()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 24)]\n\tpublic struct RemoteStorageUpdateUserPublishedItemVoteResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 24;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to GetUserPublishedItemVoteDetails()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 25)]\n\tpublic struct RemoteStorageUserVoteDetails_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 25;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic EWorkshopVote m_eVote;\t\t\t// what the user voted\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 26)]\n\tpublic struct RemoteStorageEnumerateUserSharedWorkshopFilesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 26;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic PublishedFileId_t[] m_rgPublishedFileId;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 27)]\n\tpublic struct RemoteStorageSetUserPublishedFileActionResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 27;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic EWorkshopFileAction m_eAction;\t// the action that was attempted\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 28)]\n\tpublic struct RemoteStorageEnumeratePublishedFilesByUserActionResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 28;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation.\n\t\tpublic EWorkshopFileAction m_eAction;\t// the action that was filtered on\n\t\tpublic int m_nResultsReturned;\n\t\tpublic int m_nTotalResultCount;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic PublishedFileId_t[] m_rgPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)]\n\t\tpublic uint[] m_rgRTimeUpdated;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Called periodically while a PublishWorkshopFile is in progress\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 29)]\n\tpublic struct RemoteStoragePublishFileProgress_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 29;\n\t\tpublic double m_dPercentFile;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bPreview;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Called when the content for a published file is updated\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 30)]\n\tpublic struct RemoteStoragePublishedFileUpdated_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 30;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\t// The published file id\n\t\tpublic AppId_t m_nAppID;\t\t\t\t\t\t// ID of the app that will consume this file.\n\t\tpublic ulong m_ulUnused;\t\t\t\t\t\t// not used anymore\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Called when a FileWriteAsync completes\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 31)]\n\tpublic struct RemoteStorageFileWriteAsyncComplete_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 31;\n\t\tpublic EResult m_eResult;\t\t\t\t\t\t// result\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Called when a FileReadAsync completes\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 32)]\n\tpublic struct RemoteStorageFileReadAsyncComplete_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 32;\n\t\tpublic SteamAPICall_t m_hFileReadAsync;\t\t// call handle of the async read which was made\n\t\tpublic EResult m_eResult;\t\t\t\t\t\t// result\n\t\tpublic uint m_nOffset;\t\t\t\t\t\t// offset in the file this read was at\n\t\tpublic uint m_cubRead;\t\t\t\t\t\t// amount read - will the <= the amount requested\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Screenshot successfully written or otherwise added to the library\n\t// and can now be tagged\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamScreenshotsCallbacks + 1)]\n\tpublic struct ScreenshotReady_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamScreenshotsCallbacks + 1;\n\t\tpublic ScreenshotHandle m_hLocal;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Screenshot has been requested by the user.  Only sent if\n\t// HookScreenshots() has been called, in which case Steam will not take\n\t// the screenshot itself.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamScreenshotsCallbacks + 2)]\n\tpublic struct ScreenshotRequested_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamScreenshotsCallbacks + 2;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback for querying UGC\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 1)]\n\tpublic struct SteamUGCQueryCompleted_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 1;\n\t\tpublic UGCQueryHandle_t m_handle;\n\t\tpublic EResult m_eResult;\n\t\tpublic uint m_unNumResultsReturned;\n\t\tpublic uint m_unTotalMatchingResults;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bCachedData;\t// indicates whether this data was retrieved from the local on-disk cache\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedFileURLMax)]\n\t\tpublic string m_rgchNextCursor; // If a paging cursor was used, then this will be the next cursor to get the next result set.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback for requesting details on one piece of UGC\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 2)]\n\tpublic struct SteamUGCRequestUGCDetailsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 2;\n\t\tpublic SteamUGCDetails_t m_details;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bCachedData; // indicates whether this data was retrieved from the local on-disk cache\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result for ISteamUGC::CreateItem()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 3)]\n\tpublic struct CreateItemResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 3;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId; // new item got this UGC PublishFileID\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUserNeedsToAcceptWorkshopLegalAgreement;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result for ISteamUGC::SubmitItemUpdate()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 4)]\n\tpublic struct SubmitItemUpdateResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 4;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bUserNeedsToAcceptWorkshopLegalAgreement;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: a Workshop item has been installed or updated\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 5)]\n\tpublic struct ItemInstalled_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 5;\n\t\tpublic AppId_t m_unAppID;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result of DownloadItem(), existing item files can be accessed again\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 6)]\n\tpublic struct DownloadItemResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 6;\n\t\tpublic AppId_t m_unAppID;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result of AddItemToFavorites() or RemoveItemFromFavorites()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 7)]\n\tpublic struct UserFavoriteItemsListChanged_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 7;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bWasAddRequest;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to SetUserItemVote()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 8)]\n\tpublic struct SetUserItemVoteResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 8;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bVoteUp;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to GetUserItemVote()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 9)]\n\tpublic struct GetUserItemVoteResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 9;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bVotedUp;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bVotedDown;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bVoteSkipped;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to StartPlaytimeTracking()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 10)]\n\tpublic struct StartPlaytimeTrackingResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 10;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to StopPlaytimeTracking()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 11)]\n\tpublic struct StopPlaytimeTrackingResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 11;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to AddDependency\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 12)]\n\tpublic struct AddUGCDependencyResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 12;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic PublishedFileId_t m_nChildPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to RemoveDependency\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 13)]\n\tpublic struct RemoveUGCDependencyResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 13;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic PublishedFileId_t m_nChildPublishedFileId;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to AddAppDependency\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 14)]\n\tpublic struct AddAppDependencyResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 14;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic AppId_t m_nAppID;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to RemoveAppDependency\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 15)]\n\tpublic struct RemoveAppDependencyResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 15;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic AppId_t m_nAppID;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to GetAppDependencies.  Callback may be called\n\t//\t\t\tmultiple times until all app dependencies have been returned.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 16)]\n\tpublic struct GetAppDependenciesResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 16;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]\n\t\tpublic AppId_t[] m_rgAppIDs;\n\t\tpublic uint m_nNumAppDependencies;\t\t// number returned in this struct\n\t\tpublic uint m_nTotalNumAppDependencies;\t// total found\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The result of a call to DeleteItem\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientUGCCallbacks + 17)]\n\tpublic struct DeleteItemResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientUGCCallbacks + 17;\n\t\tpublic EResult m_eResult;\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when a connections to the Steam back-end has been established\n\t//\t\t\tthis means the Steam client now has a working connection to the Steam servers\n\t//\t\t\tusually this will have occurred before the game has launched, and should\n\t//\t\t\tonly be seen if the user has dropped connection due to a networking issue\n\t//\t\t\tor a Steam server update\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 1)]\n\tpublic struct SteamServersConnected_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 1;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when a connection attempt has failed\n\t//\t\t\tthis will occur periodically if the Steam client is not connected,\n\t//\t\t\tand has failed in it's retry to establish a connection\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 2)]\n\tpublic struct SteamServerConnectFailure_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 2;\n\t\tpublic EResult m_eResult;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bStillRetrying;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called if the client has lost connection to the Steam servers\n\t//\t\t\treal-time services will be disabled until a matching SteamServersConnected_t has been posted\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 3)]\n\tpublic struct SteamServersDisconnected_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 3;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Sent by the Steam server to the client telling it to disconnect from the specified game server,\n\t//\t\t\twhich it may be in the process of or already connected to.\n\t//\t\t\tThe game client should immediately disconnect upon receiving this message.\n\t//\t\t\tThis can usually occur if the user doesn't have rights to play on the game server.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 13)]\n\tpublic struct ClientGameServerDeny_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 13;\n\t\t\n\t\tpublic uint m_uAppID;\n\t\tpublic uint m_unGameServerIP;\n\t\tpublic ushort m_usGameServerPort;\n\t\tpublic ushort m_bSecure;\n\t\tpublic uint m_uReason;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the callback system for this client is in an error state (and has flushed pending callbacks)\n\t//\t\t\tWhen getting this message the client should disconnect from Steam, reset any stored Steam state and reconnect.\n\t//\t\t\tThis usually occurs in the rare event the Steam client has some kind of fatal error.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 17)]\n\tpublic struct IPCFailure_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 17;\n\t\tpublic byte m_eFailureType;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Signaled whenever licenses change\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 25)]\n\tpublic struct LicensesUpdated_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 25;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// callback for BeginAuthSession\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = 4)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 43)]\n\tpublic struct ValidateAuthTicketResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 43;\n\t\tpublic CSteamID m_SteamID;\n\t\tpublic EAuthSessionResponse m_eAuthSessionResponse;\n\t\tpublic CSteamID m_OwnerSteamID; // different from m_SteamID if borrowed\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when a user has responded to a microtransaction authorization request\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 52)]\n\tpublic struct MicroTxnAuthorizationResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 52;\n\t\t\n\t\tpublic uint m_unAppID;\t\t\t// AppID for this microtransaction\n\t\tpublic ulong m_ulOrderID;\t\t\t// OrderID provided for the microtransaction\n\t\tpublic byte m_bAuthorized;\t\t// if user authorized transaction\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Result from RequestEncryptedAppTicket\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 54)]\n\tpublic struct EncryptedAppTicketResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 54;\n\t\t\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// callback for GetAuthSessionTicket\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 63)]\n\tpublic struct GetAuthSessionTicketResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 63;\n\t\tpublic HAuthTicket m_hAuthTicket;\n\t\tpublic EResult m_eResult;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent to your game in response to a steam://gamewebcallback/ command\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 64)]\n\tpublic struct GameWebCallback_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 64;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]\n\t\tpublic string m_szURL;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent to your game in response to ISteamUser::RequestStoreAuthURL\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 65)]\n\tpublic struct StoreAuthURLResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 65;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]\n\t\tpublic string m_szURL;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent in response to ISteamUser::GetMarketEligibility\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 66)]\n\tpublic struct MarketEligibilityResponse_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 66;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bAllowed;\n\t\tpublic EMarketNotAllowedReasonFlags m_eNotAllowedReason;\n\t\tpublic RTime32 m_rtAllowedAtTime;\n\t\t\n\t\tpublic int m_cdaySteamGuardRequiredDays; // The number of days any user is required to have had Steam Guard before they can use the market\n\t\tpublic int m_cdayNewDeviceCooldown; // The number of days after initial device authorization a user must wait before using the market on that device\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: sent for games with enabled anti indulgence / duration control, for\n\t// enabled users. Lets the game know whether persistent rewards or XP should be\n\t// granted at normal rate, half rate, or zero rate.\n\t//\n\t// This callback is fired asynchronously in response to timers triggering.\n\t// It is also fired in response to calls to GetDurationControl().\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserCallbacks + 67)]\n\tpublic struct DurationControl_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserCallbacks + 67;\n\t\t\n\t\tpublic EResult m_eResult;\t\t\t\t\t\t\t\t// result of call (always k_EResultOK for asynchronous timer-based notifications)\n\t\tpublic AppId_t m_appid;\t\t\t\t\t\t\t\t// appid generating playtime\n\t\t\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bApplicable;\t\t\t\t\t\t\t// is duration control applicable to user + game combination\n\t\tpublic int m_csecsLast5h;\t\t\t\t\t\t\t// playtime in trailing 5 hour window plus current session, in seconds\n\t\tpublic EDurationControlProgress m_progress;\t\t\t// recommended progress\n\t\tpublic EDurationControlNotification m_notification;\t// notification to show, if any (always k_EDurationControlNotification_None for API calls)\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when the latests stats and achievements have been received\n\t//\t\t\tfrom the server\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Explicit, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 1)]\n\tpublic struct UserStatsReceived_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 1;\n\t\t[FieldOffset(0)]\n\t\tpublic ulong m_nGameID;\t\t// Game these stats are for\n\t\t[FieldOffset(8)]\n\t\tpublic EResult m_eResult;\t\t// Success / error fetching the stats\n\t\t[FieldOffset(12)]\n\t\tpublic CSteamID m_steamIDUser;\t// The user for whom the stats are retrieved for\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result of a request to store the user stats for a game\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 2)]\n\tpublic struct UserStatsStored_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 2;\n\t\tpublic ulong m_nGameID;\t\t// Game these stats are for\n\t\tpublic EResult m_eResult;\t\t// success / error\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: result of a request to store the achievements for a game, or an\n\t//\t\t\t\"indicate progress\" call. If both m_nCurProgress and m_nMaxProgress\n\t//\t\t\tare zero, that means the achievement has been fully unlocked.\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 3)]\n\tpublic struct UserAchievementStored_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 3;\n\t\t\n\t\tpublic ulong m_nGameID;\t\t\t\t// Game this is for\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bGroupAchievement;\t// if this is a \"group\" achievement\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchStatNameMax)]\n\t\tpublic string m_rgchAchievementName;\t\t// name of the achievement\n\t\tpublic uint m_nCurProgress;\t\t\t// current progress towards the achievement\n\t\tpublic uint m_nMaxProgress;\t\t\t// \"out of\" this many\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: call result for finding a leaderboard, returned as a result of FindOrCreateLeaderboard() or FindLeaderboard()\n\t//\t\t\tuse CCallResult<> to map this async result to a member function\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 4)]\n\tpublic struct LeaderboardFindResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 4;\n\t\tpublic SteamLeaderboard_t m_hSteamLeaderboard;\t// handle to the leaderboard serarched for, 0 if no leaderboard found\n\t\tpublic byte m_bLeaderboardFound;\t\t\t\t// 0 if no leaderboard found\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: call result indicating scores for a leaderboard have been downloaded and are ready to be retrieved, returned as a result of DownloadLeaderboardEntries()\n\t//\t\t\tuse CCallResult<> to map this async result to a member function\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 5)]\n\tpublic struct LeaderboardScoresDownloaded_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 5;\n\t\tpublic SteamLeaderboard_t m_hSteamLeaderboard;\n\t\tpublic SteamLeaderboardEntries_t m_hSteamLeaderboardEntries;\t// the handle to pass into GetDownloadedLeaderboardEntries()\n\t\tpublic int m_cEntryCount; // the number of entries downloaded\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: call result indicating scores has been uploaded, returned as a result of UploadLeaderboardScore()\n\t//\t\t\tuse CCallResult<> to map this async result to a member function\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 6)]\n\tpublic struct LeaderboardScoreUploaded_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 6;\n\t\tpublic byte m_bSuccess;\t\t\t// 1 if the call was successful\n\t\tpublic SteamLeaderboard_t m_hSteamLeaderboard;\t// the leaderboard handle that was\n\t\tpublic int m_nScore;\t\t\t\t// the score that was attempted to set\n\t\tpublic byte m_bScoreChanged;\t\t// true if the score in the leaderboard change, false if the existing score was better\n\t\tpublic int m_nGlobalRankNew;\t\t// the new global rank of the user in this leaderboard\n\t\tpublic int m_nGlobalRankPrevious;\t// the previous global rank of the user in this leaderboard; 0 if the user had no existing entry in the leaderboard\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 7)]\n\tpublic struct NumberOfCurrentPlayers_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 7;\n\t\tpublic byte m_bSuccess;\t\t\t// 1 if the call was successful\n\t\tpublic int m_cPlayers;\t\t\t// Number of players currently playing\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback indicating that a user's stats have been unloaded.\n\t//  Call RequestUserStats again to access stats for this user\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 8)]\n\tpublic struct UserStatsUnloaded_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 8;\n\t\tpublic CSteamID m_steamIDUser;\t// User whose stats have been unloaded\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback indicating that an achievement icon has been fetched\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 9)]\n\tpublic struct UserAchievementIconFetched_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 9;\n\t\t\n\t\tpublic CGameID m_nGameID;\t\t\t\t// Game this is for\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchStatNameMax)]\n\t\tpublic string m_rgchAchievementName;\t\t// name of the achievement\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bAchieved;\t\t// Is the icon for the achieved or not achieved version?\n\t\tpublic int m_nIconHandle;\t\t// Handle to the image, which can be used in SteamUtils()->GetImageRGBA(), 0 means no image is set for the achievement\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Callback indicating that global achievement percentages are fetched\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 10)]\n\tpublic struct GlobalAchievementPercentagesReady_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 10;\n\t\t\n\t\tpublic ulong m_nGameID;\t\t\t\t// Game this is for\n\t\tpublic EResult m_eResult;\t\t\t\t// Result of the operation\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: call result indicating UGC has been uploaded, returned as a result of SetLeaderboardUGC()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 11)]\n\tpublic struct LeaderboardUGCSet_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 11;\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the operation\n\t\tpublic SteamLeaderboard_t m_hSteamLeaderboard;\t// the leaderboard handle that was\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: callback indicating global stats have been received.\n\t//\tReturned as a result of RequestGlobalStats()\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 12)]\n\tpublic struct GlobalStatsReceived_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 12;\n\t\tpublic ulong m_nGameID;\t\t\t\t// Game global stats were requested for\n\t\tpublic EResult m_eResult;\t\t\t\t// The result of the request\n\t}\n\n\t// callbacks\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The country of the user changed\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 1)]\n\tpublic struct IPCountry_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 1;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 2)]\n\tpublic struct LowBatteryPower_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 2;\n\t\tpublic byte m_nMinutesBatteryLeft;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: called when a SteamAsyncCall_t has completed (or failed)\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 3)]\n\tpublic struct SteamAPICallCompleted_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 3;\n\t\tpublic SteamAPICall_t m_hAsyncCall;\n\t\tpublic int m_iCallback;\n\t\tpublic uint m_cubParam;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// called when Steam wants to shutdown\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 4)]\n\tpublic struct SteamShutdown_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 4;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// callback for CheckFileSignature\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 5)]\n\tpublic struct CheckFileSignature_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 5;\n\t\tpublic ECheckFileSignature m_eCheckFileSignature;\n\t}\n\n\t// k_iSteamUtilsCallbacks + 13 is taken\n\t//-----------------------------------------------------------------------------\n\t// Big Picture gamepad text input has been closed\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 14)]\n\tpublic struct GamepadTextInputDismissed_t {\n\t\tpublic const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 14;\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bSubmitted;\t\t\t\t\t\t\t\t\t\t// true if user entered & accepted text (Call ISteamUtils::GetEnteredGamepadTextInput() for text), false if canceled input\n\t\tpublic uint m_unSubmittedText;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientVideoCallbacks + 11)]\n\tpublic struct GetVideoURLResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientVideoCallbacks + 11;\n\t\tpublic EResult m_eResult;\n\t\tpublic AppId_t m_unVideoAppID;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]\n\t\tpublic string m_rgchURL;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\t[CallbackIdentity(Constants.k_iClientVideoCallbacks + 24)]\n\tpublic struct GetOPFSettingsResult_t {\n\t\tpublic const int k_iCallback = Constants.k_iClientVideoCallbacks + 24;\n\t\tpublic EResult m_eResult;\n\t\tpublic AppId_t m_unVideoAppID;\n\t}\n\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/SteamConstants.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class Constants {\n\t\tpublic const string STEAMAPPLIST_INTERFACE_VERSION = \"STEAMAPPLIST_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMAPPS_INTERFACE_VERSION = \"STEAMAPPS_INTERFACE_VERSION008\";\n\t\tpublic const string STEAMAPPTICKET_INTERFACE_VERSION = \"STEAMAPPTICKET_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMCLIENT_INTERFACE_VERSION = \"SteamClient019\";\n\t\tpublic const string STEAMCONTROLLER_INTERFACE_VERSION = \"SteamController007\";\n\t\tpublic const string STEAMFRIENDS_INTERFACE_VERSION = \"SteamFriends017\";\n\t\tpublic const string STEAMGAMECOORDINATOR_INTERFACE_VERSION = \"SteamGameCoordinator001\";\n\t\tpublic const string STEAMGAMESERVER_INTERFACE_VERSION = \"SteamGameServer012\";\n\t\tpublic const string STEAMGAMESERVERSTATS_INTERFACE_VERSION = \"SteamGameServerStats001\";\n\t\tpublic const string STEAMHTMLSURFACE_INTERFACE_VERSION = \"STEAMHTMLSURFACE_INTERFACE_VERSION_005\";\n\t\tpublic const string STEAMHTTP_INTERFACE_VERSION = \"STEAMHTTP_INTERFACE_VERSION003\";\n\t\tpublic const string STEAMINPUT_INTERFACE_VERSION = \"SteamInput001\";\n\t\tpublic const string STEAMINVENTORY_INTERFACE_VERSION = \"STEAMINVENTORY_INTERFACE_V003\";\n\t\tpublic const string STEAMMATCHMAKING_INTERFACE_VERSION = \"SteamMatchMaking009\";\n\t\tpublic const string STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION = \"SteamMatchMakingServers002\";\n\t\tpublic const string STEAMGAMESEARCH_INTERFACE_VERSION = \"SteamMatchGameSearch001\";\n\t\tpublic const string STEAMPARTIES_INTERFACE_VERSION = \"SteamParties002\";\n\t\tpublic const string STEAMMUSIC_INTERFACE_VERSION = \"STEAMMUSIC_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMMUSICREMOTE_INTERFACE_VERSION = \"STEAMMUSICREMOTE_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMNETWORKING_INTERFACE_VERSION = \"SteamNetworking005\";\n\t\tpublic const string STEAMPARENTALSETTINGS_INTERFACE_VERSION = \"STEAMPARENTALSETTINGS_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMREMOTEPLAY_INTERFACE_VERSION = \"STEAMREMOTEPLAY_INTERFACE_VERSION001\";\n\t\tpublic const string STEAMREMOTESTORAGE_INTERFACE_VERSION = \"STEAMREMOTESTORAGE_INTERFACE_VERSION014\";\n\t\tpublic const string STEAMSCREENSHOTS_INTERFACE_VERSION = \"STEAMSCREENSHOTS_INTERFACE_VERSION003\";\n\t\tpublic const string STEAMUGC_INTERFACE_VERSION = \"STEAMUGC_INTERFACE_VERSION013\";\n\t\tpublic const string STEAMUSER_INTERFACE_VERSION = \"SteamUser020\";\n\t\tpublic const string STEAMUSERSTATS_INTERFACE_VERSION = \"STEAMUSERSTATS_INTERFACE_VERSION011\";\n\t\tpublic const string STEAMUTILS_INTERFACE_VERSION = \"SteamUtils009\";\n\t\tpublic const string STEAMVIDEO_INTERFACE_VERSION = \"STEAMVIDEO_INTERFACE_V002\";\n\t\tpublic const int k_cubAppProofOfPurchaseKeyMax = 240; // max supported length of a legacy cd key\n\t\t// maximum length of friend group name (not including terminating nul!)\n\t\tpublic const int k_cchMaxFriendsGroupName = 64;\n\t\t// maximum number of groups a single user is allowed\n\t\tpublic const int k_cFriendsGroupLimit = 100;\n\t\tpublic const int k_cEnumerateFollowersMax = 50;\n\t\t// maximum number of characters in a user's name. Two flavors; one for UTF-8 and one for UTF-16.\n\t\t// The UTF-8 version has to be very generous to accomodate characters that get large when encoded\n\t\t// in UTF-8.\n\t\tpublic const int k_cchPersonaNameMax = 128;\n\t\tpublic const int k_cwchPersonaNameMax = 32;\n\t\t// size limit on chat room or member metadata\n\t\tpublic const int k_cubChatMetadataMax = 8192;\n\t\t// size limits on Rich Presence data\n\t\tpublic const int k_cchMaxRichPresenceKeys = 30;\n\t\tpublic const int k_cchMaxRichPresenceKeyLength = 64;\n\t\tpublic const int k_cchMaxRichPresenceValueLength = 256;\n\t\t// game server flags\n\t\tpublic const int k_unServerFlagNone = 0x00;\n\t\tpublic const int k_unServerFlagActive = 0x01; // server has users playing\n\t\tpublic const int k_unServerFlagSecure = 0x02; // server wants to be secure\n\t\tpublic const int k_unServerFlagDedicated = 0x04; // server is dedicated\n\t\tpublic const int k_unServerFlagLinux = 0x08; // linux build\n\t\tpublic const int k_unServerFlagPassworded = 0x10; // password protected\n\t\tpublic const int k_unServerFlagPrivate = 0x20; // server shouldn't list on master server and\n\t\t// game server flags\n\t\tpublic const int k_unFavoriteFlagNone = 0x00;\n\t\tpublic const int k_unFavoriteFlagFavorite = 0x01; // this game favorite entry is for the favorites list\n\t\tpublic const int k_unFavoriteFlagHistory = 0x02; // this game favorite entry is for the history list\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Defines the largest allowed file size. Cloud files cannot be written\n\t\t// in a single chunk over 100MB (and cannot be over 200MB total.)\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic const int k_unMaxCloudFileChunkSize = 100 * 1024 * 1024;\n\t\tpublic const int k_cchPublishedDocumentTitleMax = 128 + 1;\n\t\tpublic const int k_cchPublishedDocumentDescriptionMax = 8000;\n\t\tpublic const int k_cchPublishedDocumentChangeDescriptionMax = 8000;\n\t\tpublic const int k_unEnumeratePublishedFilesMaxResults = 50;\n\t\tpublic const int k_cchTagListMax = 1024 + 1;\n\t\tpublic const int k_cchFilenameMax = 260;\n\t\tpublic const int k_cchPublishedFileURLMax = 256;\n\t\tpublic const int k_nScreenshotMaxTaggedUsers = 32;\n\t\tpublic const int k_nScreenshotMaxTaggedPublishedFiles = 32;\n\t\tpublic const int k_cubUFSTagTypeMax = 255;\n\t\tpublic const int k_cubUFSTagValueMax = 255;\n\t\t// Required with of a thumbnail provided to AddScreenshotToLibrary.  If you do not provide a thumbnail\n\t\t// one will be generated.\n\t\tpublic const int k_ScreenshotThumbWidth = 200;\n\t\tpublic const int kNumUGCResultsPerPage = 50;\n\t\tpublic const int k_cchDeveloperMetadataMax = 5000;\n\t\t// size limit on stat or achievement name (UTF-8 encoded)\n\t\tpublic const int k_cchStatNameMax = 128;\n\t\t// maximum number of bytes for a leaderboard name (UTF-8 encoded)\n\t\tpublic const int k_cchLeaderboardNameMax = 128;\n\t\t// maximum number of details int32's storable for a single leaderboard entry\n\t\tpublic const int k_cLeaderboardDetailsMax = 64;\n\t\t//\n\t\t// Max size (in bytes of UTF-8 data, not in characters) of server fields, including null terminator.\n\t\t// WARNING: These cannot be changed easily, without breaking clients using old interfaces.\n\t\t//\n\t\tpublic const int k_cbMaxGameServerGameDir = 32;\n\t\tpublic const int k_cbMaxGameServerMapName = 32;\n\t\tpublic const int k_cbMaxGameServerGameDescription = 64;\n\t\tpublic const int k_cbMaxGameServerName = 64;\n\t\tpublic const int k_cbMaxGameServerTags = 128;\n\t\tpublic const int k_cbMaxGameServerGameData = 2048;\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Base values for callback identifiers, each callback must\n\t\t//\t\t\thave a unique ID.\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic const int k_iSteamUserCallbacks = 100;\n\t\tpublic const int k_iSteamGameServerCallbacks = 200;\n\t\tpublic const int k_iSteamFriendsCallbacks = 300;\n\t\tpublic const int k_iSteamBillingCallbacks = 400;\n\t\tpublic const int k_iSteamMatchmakingCallbacks = 500;\n\t\tpublic const int k_iSteamContentServerCallbacks = 600;\n\t\tpublic const int k_iSteamUtilsCallbacks = 700;\n\t\tpublic const int k_iClientFriendsCallbacks = 800;\n\t\tpublic const int k_iClientUserCallbacks = 900;\n\t\tpublic const int k_iSteamAppsCallbacks = 1000;\n\t\tpublic const int k_iSteamUserStatsCallbacks = 1100;\n\t\tpublic const int k_iSteamNetworkingCallbacks = 1200;\n\t\tpublic const int k_iSteamNetworkingSocketsCallbacks = 1220;\n\t\tpublic const int k_iSteamNetworkingMessagesCallbacks = 1250;\n\t\tpublic const int k_iSteamNetworkingUtilsCallbacks = 1280;\n\t\tpublic const int k_iClientRemoteStorageCallbacks = 1300;\n\t\tpublic const int k_iClientDepotBuilderCallbacks = 1400;\n\t\tpublic const int k_iSteamGameServerItemsCallbacks = 1500;\n\t\tpublic const int k_iClientUtilsCallbacks = 1600;\n\t\tpublic const int k_iSteamGameCoordinatorCallbacks = 1700;\n\t\tpublic const int k_iSteamGameServerStatsCallbacks = 1800;\n\t\tpublic const int k_iSteam2AsyncCallbacks = 1900;\n\t\tpublic const int k_iSteamGameStatsCallbacks = 2000;\n\t\tpublic const int k_iClientHTTPCallbacks = 2100;\n\t\tpublic const int k_iClientScreenshotsCallbacks = 2200;\n\t\tpublic const int k_iSteamScreenshotsCallbacks = 2300;\n\t\tpublic const int k_iClientAudioCallbacks = 2400;\n\t\tpublic const int k_iClientUnifiedMessagesCallbacks = 2500;\n\t\tpublic const int k_iSteamStreamLauncherCallbacks = 2600;\n\t\tpublic const int k_iClientControllerCallbacks = 2700;\n\t\tpublic const int k_iSteamControllerCallbacks = 2800;\n\t\tpublic const int k_iClientParentalSettingsCallbacks = 2900;\n\t\tpublic const int k_iClientDeviceAuthCallbacks = 3000;\n\t\tpublic const int k_iClientNetworkDeviceManagerCallbacks = 3100;\n\t\tpublic const int k_iClientMusicCallbacks = 3200;\n\t\tpublic const int k_iClientRemoteClientManagerCallbacks = 3300;\n\t\tpublic const int k_iClientUGCCallbacks = 3400;\n\t\tpublic const int k_iSteamStreamClientCallbacks = 3500;\n\t\tpublic const int k_IClientProductBuilderCallbacks = 3600;\n\t\tpublic const int k_iClientShortcutsCallbacks = 3700;\n\t\tpublic const int k_iClientRemoteControlManagerCallbacks = 3800;\n\t\tpublic const int k_iSteamAppListCallbacks = 3900;\n\t\tpublic const int k_iSteamMusicCallbacks = 4000;\n\t\tpublic const int k_iSteamMusicRemoteCallbacks = 4100;\n\t\tpublic const int k_iClientVRCallbacks = 4200;\n\t\tpublic const int k_iClientGameNotificationCallbacks = 4300;\n\t\tpublic const int k_iSteamGameNotificationCallbacks = 4400;\n\t\tpublic const int k_iSteamHTMLSurfaceCallbacks = 4500;\n\t\tpublic const int k_iClientVideoCallbacks = 4600;\n\t\tpublic const int k_iClientInventoryCallbacks = 4700;\n\t\tpublic const int k_iClientBluetoothManagerCallbacks = 4800;\n\t\tpublic const int k_iClientSharedConnectionCallbacks = 4900;\n\t\tpublic const int k_ISteamParentalSettingsCallbacks = 5000;\n\t\tpublic const int k_iClientShaderCallbacks = 5100;\n\t\tpublic const int k_iSteamGameSearchCallbacks = 5200;\n\t\tpublic const int k_iSteamPartiesCallbacks = 5300;\n\t\tpublic const int k_iClientPartiesCallbacks = 5400;\n\t\tpublic const int k_iSteamSTARCallbacks = 5500;\n\t\tpublic const int k_iClientSTARCallbacks = 5600;\n\t\tpublic const int k_iSteamRemotePlayCallbacks = 5700;\n\t\tpublic const int k_unSteamAccountIDMask = -1;\n\t\tpublic const int k_unSteamAccountInstanceMask = 0x000FFFFF;\n\t\t// we allow 3 simultaneous user account instances right now, 1= desktop, 2 = console, 4 = web, 0 = all\n\t\tpublic const int k_unSteamUserDesktopInstance = 1;\n\t\tpublic const int k_unSteamUserConsoleInstance = 2;\n\t\tpublic const int k_unSteamUserWebInstance = 4;\n\t\tpublic const int k_cchGameExtraInfoMax = 64;\n\t\tpublic const int k_nSteamEncryptedAppTicketSymmetricKeyLen = 32;\n\t\tpublic const int k_cubSaltSize = 8;\n\t\tpublic const ulong k_GIDNil = 0xffffffffffffffff;\n\t\tpublic const ulong k_TxnIDNil = k_GIDNil;\n\t\tpublic const ulong k_TxnIDUnknown = 0;\n\t\tpublic const int k_uPackageIdInvalid = -1;\n\t\tpublic const ulong k_ulAssetClassIdInvalid = 0x0;\n\t\tpublic const int k_uPhysicalItemIdInvalid = 0x0;\n\t\tpublic const int k_uCellIDInvalid = -1;\n\t\tpublic const int k_uPartnerIdInvalid = 0;\n\t\tpublic const ulong k_ulPartyBeaconIdInvalid = 0;\n\t\tpublic const int STEAM_CONTROLLER_MAX_COUNT = 16;\n\t\tpublic const int STEAM_CONTROLLER_MAX_ANALOG_ACTIONS = 16;\n\t\tpublic const int STEAM_CONTROLLER_MAX_DIGITAL_ACTIONS = 128;\n\t\tpublic const int STEAM_CONTROLLER_MAX_ORIGINS = 8;\n\t\tpublic const int STEAM_CONTROLLER_MAX_ACTIVE_LAYERS = 16;\n\t\t// When sending an option to a specific controller handle, you can send to all controllers via this command\n\t\tpublic const ulong STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS = 0xFFFFFFFFFFFFFFFF;\n\t\tpublic const float STEAM_CONTROLLER_MIN_ANALOG_ACTION_DATA = -1.0f;\n\t\tpublic const float STEAM_CONTROLLER_MAX_ANALOG_ACTION_DATA = 1.0f;\n\t\tpublic const ushort MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE\t= 0xFFFF;\n\t\tpublic const int INVALID_HTTPREQUEST_HANDLE\t\t= 0;\n\t\tpublic const int STEAM_INPUT_MAX_COUNT = 16;\n\t\tpublic const int STEAM_INPUT_MAX_ANALOG_ACTIONS = 16;\n\t\tpublic const int STEAM_INPUT_MAX_DIGITAL_ACTIONS = 128;\n\t\tpublic const int STEAM_INPUT_MAX_ORIGINS = 8;\n\t\tpublic const int STEAM_INPUT_MAX_ACTIVE_LAYERS = 16;\n\t\t// When sending an option to a specific controller handle, you can send to all devices via this command\n\t\tpublic const ulong STEAM_INPUT_HANDLE_ALL_CONTROLLERS = 0xFFFFFFFFFFFFFFFF;\n\t\tpublic const float STEAM_INPUT_MIN_ANALOG_ACTION_DATA = -1.0f;\n\t\tpublic const float STEAM_INPUT_MAX_ANALOG_ACTION_DATA = 1.0f;\n\t\t// maximum number of characters a lobby metadata key can be\n\t\tpublic const byte k_nMaxLobbyKeyLength = 255;\n\t\tpublic const int k_SteamMusicNameMaxLength = 255;\n\t\tpublic const int k_SteamMusicPNGMaxLength = 65535;\n\t\t//-----------------------------------------------------------------------------\n\t\t// Constants used for query ports.\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic const int QUERY_PORT_NOT_INITIALIZED\t\t= 0xFFFF; // We haven't asked the GS for this query port's actual value yet.\n\t\tpublic const int QUERY_PORT_ERROR\t\t\t\t= 0xFFFE; // We were unable to get the query port for this server.\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/SteamEnums.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nusing Flags = System.FlagsAttribute;\n\nnamespace Steamworks {\n\t//-----------------------------------------------------------------------------\n\t// Purpose: possible results when registering an activation code\n\t//-----------------------------------------------------------------------------\n\tpublic enum ERegisterActivationCodeResult : int {\n\t\tk_ERegisterActivationCodeResultOK = 0,\n\t\tk_ERegisterActivationCodeResultFail = 1,\n\t\tk_ERegisterActivationCodeResultAlreadyRegistered = 2,\n\t\tk_ERegisterActivationCodeResultTimeout = 3,\n\t\tk_ERegisterActivationCodeAlreadyOwned = 4,\n\t}\n\n\tpublic enum EControllerSource : int {\n\t\tk_EControllerSource_None,\n\t\tk_EControllerSource_LeftTrackpad,\n\t\tk_EControllerSource_RightTrackpad,\n\t\tk_EControllerSource_Joystick,\n\t\tk_EControllerSource_ABXY,\n\t\tk_EControllerSource_Switch,\n\t\tk_EControllerSource_LeftTrigger,\n\t\tk_EControllerSource_RightTrigger,\n\t\tk_EControllerSource_LeftBumper,\n\t\tk_EControllerSource_RightBumper,\n\t\tk_EControllerSource_Gyro,\n\t\tk_EControllerSource_CenterTrackpad,\t\t// PS4\n\t\tk_EControllerSource_RightJoystick,\t\t// Traditional Controllers\n\t\tk_EControllerSource_DPad,\t\t\t\t// Traditional Controllers\n\t\tk_EControllerSource_Key,                // Keyboards with scan codes - Unused\n\t\tk_EControllerSource_Mouse,              // Traditional mouse - Unused\n\t\tk_EControllerSource_LeftGyro,\t\t\t// Secondary Gyro - Switch - Unused\n\t\tk_EControllerSource_Count\n\t}\n\n\tpublic enum EControllerSourceMode : int {\n\t\tk_EControllerSourceMode_None,\n\t\tk_EControllerSourceMode_Dpad,\n\t\tk_EControllerSourceMode_Buttons,\n\t\tk_EControllerSourceMode_FourButtons,\n\t\tk_EControllerSourceMode_AbsoluteMouse,\n\t\tk_EControllerSourceMode_RelativeMouse,\n\t\tk_EControllerSourceMode_JoystickMove,\n\t\tk_EControllerSourceMode_JoystickMouse,\n\t\tk_EControllerSourceMode_JoystickCamera,\n\t\tk_EControllerSourceMode_ScrollWheel,\n\t\tk_EControllerSourceMode_Trigger,\n\t\tk_EControllerSourceMode_TouchMenu,\n\t\tk_EControllerSourceMode_MouseJoystick,\n\t\tk_EControllerSourceMode_MouseRegion,\n\t\tk_EControllerSourceMode_RadialMenu,\n\t\tk_EControllerSourceMode_SingleButton,\n\t\tk_EControllerSourceMode_Switches\n\t}\n\n\t// Note: Please do not use action origins as a way to identify controller types. There is no\n\t// guarantee that they will be added in a contiguous manner - use GetInputTypeForHandle instead\n\t// Versions of Steam that add new controller types in the future will extend this enum if you're\n\t// using a lookup table please check the bounds of any origins returned by Steam.\n\tpublic enum EControllerActionOrigin : int {\n\t\t// Steam Controller\n\t\tk_EControllerActionOrigin_None,\n\t\tk_EControllerActionOrigin_A,\n\t\tk_EControllerActionOrigin_B,\n\t\tk_EControllerActionOrigin_X,\n\t\tk_EControllerActionOrigin_Y,\n\t\tk_EControllerActionOrigin_LeftBumper,\n\t\tk_EControllerActionOrigin_RightBumper,\n\t\tk_EControllerActionOrigin_LeftGrip,\n\t\tk_EControllerActionOrigin_RightGrip,\n\t\tk_EControllerActionOrigin_Start,\n\t\tk_EControllerActionOrigin_Back,\n\t\tk_EControllerActionOrigin_LeftPad_Touch,\n\t\tk_EControllerActionOrigin_LeftPad_Swipe,\n\t\tk_EControllerActionOrigin_LeftPad_Click,\n\t\tk_EControllerActionOrigin_LeftPad_DPadNorth,\n\t\tk_EControllerActionOrigin_LeftPad_DPadSouth,\n\t\tk_EControllerActionOrigin_LeftPad_DPadWest,\n\t\tk_EControllerActionOrigin_LeftPad_DPadEast,\n\t\tk_EControllerActionOrigin_RightPad_Touch,\n\t\tk_EControllerActionOrigin_RightPad_Swipe,\n\t\tk_EControllerActionOrigin_RightPad_Click,\n\t\tk_EControllerActionOrigin_RightPad_DPadNorth,\n\t\tk_EControllerActionOrigin_RightPad_DPadSouth,\n\t\tk_EControllerActionOrigin_RightPad_DPadWest,\n\t\tk_EControllerActionOrigin_RightPad_DPadEast,\n\t\tk_EControllerActionOrigin_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_LeftStick_Move,\n\t\tk_EControllerActionOrigin_LeftStick_Click,\n\t\tk_EControllerActionOrigin_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_Gyro_Move,\n\t\tk_EControllerActionOrigin_Gyro_Pitch,\n\t\tk_EControllerActionOrigin_Gyro_Yaw,\n\t\tk_EControllerActionOrigin_Gyro_Roll,\n\n\t\t// PS4 Dual Shock\n\t\tk_EControllerActionOrigin_PS4_X,\n\t\tk_EControllerActionOrigin_PS4_Circle,\n\t\tk_EControllerActionOrigin_PS4_Triangle,\n\t\tk_EControllerActionOrigin_PS4_Square,\n\t\tk_EControllerActionOrigin_PS4_LeftBumper,\n\t\tk_EControllerActionOrigin_PS4_RightBumper,\n\t\tk_EControllerActionOrigin_PS4_Options,  //Start\n\t\tk_EControllerActionOrigin_PS4_Share,\t//Back\n\t\tk_EControllerActionOrigin_PS4_LeftPad_Touch,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_Swipe,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_Click,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_DPadNorth,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_DPadSouth,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_DPadWest,\n\t\tk_EControllerActionOrigin_PS4_LeftPad_DPadEast,\n\t\tk_EControllerActionOrigin_PS4_RightPad_Touch,\n\t\tk_EControllerActionOrigin_PS4_RightPad_Swipe,\n\t\tk_EControllerActionOrigin_PS4_RightPad_Click,\n\t\tk_EControllerActionOrigin_PS4_RightPad_DPadNorth,\n\t\tk_EControllerActionOrigin_PS4_RightPad_DPadSouth,\n\t\tk_EControllerActionOrigin_PS4_RightPad_DPadWest,\n\t\tk_EControllerActionOrigin_PS4_RightPad_DPadEast,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_Touch,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_Swipe,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_Click,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_DPadNorth,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_DPadSouth,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_DPadWest,\n\t\tk_EControllerActionOrigin_PS4_CenterPad_DPadEast,\n\t\tk_EControllerActionOrigin_PS4_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_PS4_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_PS4_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_PS4_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_Move,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_Click,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_PS4_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_PS4_RightStick_Move,\n\t\tk_EControllerActionOrigin_PS4_RightStick_Click,\n\t\tk_EControllerActionOrigin_PS4_RightStick_DPadNorth,\n\t\tk_EControllerActionOrigin_PS4_RightStick_DPadSouth,\n\t\tk_EControllerActionOrigin_PS4_RightStick_DPadWest,\n\t\tk_EControllerActionOrigin_PS4_RightStick_DPadEast,\n\t\tk_EControllerActionOrigin_PS4_DPad_North,\n\t\tk_EControllerActionOrigin_PS4_DPad_South,\n\t\tk_EControllerActionOrigin_PS4_DPad_West,\n\t\tk_EControllerActionOrigin_PS4_DPad_East,\n\t\tk_EControllerActionOrigin_PS4_Gyro_Move,\n\t\tk_EControllerActionOrigin_PS4_Gyro_Pitch,\n\t\tk_EControllerActionOrigin_PS4_Gyro_Yaw,\n\t\tk_EControllerActionOrigin_PS4_Gyro_Roll,\n\n\t\t// XBox One\n\t\tk_EControllerActionOrigin_XBoxOne_A,\n\t\tk_EControllerActionOrigin_XBoxOne_B,\n\t\tk_EControllerActionOrigin_XBoxOne_X,\n\t\tk_EControllerActionOrigin_XBoxOne_Y,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftBumper,\n\t\tk_EControllerActionOrigin_XBoxOne_RightBumper,\n\t\tk_EControllerActionOrigin_XBoxOne_Menu,  //Start\n\t\tk_EControllerActionOrigin_XBoxOne_View,  //Back\n\t\tk_EControllerActionOrigin_XBoxOne_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_XBoxOne_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_XBoxOne_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_Move,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_Click,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_XBoxOne_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_Move,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_Click,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_DPadNorth,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_DPadSouth,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_DPadWest,\n\t\tk_EControllerActionOrigin_XBoxOne_RightStick_DPadEast,\n\t\tk_EControllerActionOrigin_XBoxOne_DPad_North,\n\t\tk_EControllerActionOrigin_XBoxOne_DPad_South,\n\t\tk_EControllerActionOrigin_XBoxOne_DPad_West,\n\t\tk_EControllerActionOrigin_XBoxOne_DPad_East,\n\n\t\t// XBox 360\n\t\tk_EControllerActionOrigin_XBox360_A,\n\t\tk_EControllerActionOrigin_XBox360_B,\n\t\tk_EControllerActionOrigin_XBox360_X,\n\t\tk_EControllerActionOrigin_XBox360_Y,\n\t\tk_EControllerActionOrigin_XBox360_LeftBumper,\n\t\tk_EControllerActionOrigin_XBox360_RightBumper,\n\t\tk_EControllerActionOrigin_XBox360_Start,  //Start\n\t\tk_EControllerActionOrigin_XBox360_Back,  //Back\n\t\tk_EControllerActionOrigin_XBox360_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_XBox360_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_XBox360_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_XBox360_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_Move,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_Click,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_XBox360_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_Move,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_Click,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_DPadNorth,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_DPadSouth,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_DPadWest,\n\t\tk_EControllerActionOrigin_XBox360_RightStick_DPadEast,\n\t\tk_EControllerActionOrigin_XBox360_DPad_North,\n\t\tk_EControllerActionOrigin_XBox360_DPad_South,\n\t\tk_EControllerActionOrigin_XBox360_DPad_West,\n\t\tk_EControllerActionOrigin_XBox360_DPad_East,\n\n\t\t// SteamController V2\n\t\tk_EControllerActionOrigin_SteamV2_A,\n\t\tk_EControllerActionOrigin_SteamV2_B,\n\t\tk_EControllerActionOrigin_SteamV2_X,\n\t\tk_EControllerActionOrigin_SteamV2_Y,\n\t\tk_EControllerActionOrigin_SteamV2_LeftBumper,\n\t\tk_EControllerActionOrigin_SteamV2_RightBumper,\n\t\tk_EControllerActionOrigin_SteamV2_LeftGrip_Lower,\n\t\tk_EControllerActionOrigin_SteamV2_LeftGrip_Upper,\n\t\tk_EControllerActionOrigin_SteamV2_RightGrip_Lower,\n\t\tk_EControllerActionOrigin_SteamV2_RightGrip_Upper,\n\t\tk_EControllerActionOrigin_SteamV2_LeftBumper_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_RightBumper_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_LeftGrip_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_RightGrip_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_LeftGrip_Upper_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_RightGrip_Upper_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_Start,\n\t\tk_EControllerActionOrigin_SteamV2_Back,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_Touch,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_Swipe,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_Click,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_DPadNorth,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_DPadSouth,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_DPadWest,\n\t\tk_EControllerActionOrigin_SteamV2_LeftPad_DPadEast,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_Touch,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_Swipe,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_Click,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_Pressure,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_DPadNorth,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_DPadSouth,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_DPadWest,\n\t\tk_EControllerActionOrigin_SteamV2_RightPad_DPadEast,\n\t\tk_EControllerActionOrigin_SteamV2_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_SteamV2_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_SteamV2_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_SteamV2_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_Move,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_Click,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_SteamV2_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_SteamV2_Gyro_Move,\n\t\tk_EControllerActionOrigin_SteamV2_Gyro_Pitch,\n\t\tk_EControllerActionOrigin_SteamV2_Gyro_Yaw,\n\t\tk_EControllerActionOrigin_SteamV2_Gyro_Roll,\n\n\t\t// Switch - Pro or Joycons used as a single input device.\n\t\t// This does not apply to a single joycon\n\t\tk_EControllerActionOrigin_Switch_A,\n\t\tk_EControllerActionOrigin_Switch_B,\n\t\tk_EControllerActionOrigin_Switch_X,\n\t\tk_EControllerActionOrigin_Switch_Y,\n\t\tk_EControllerActionOrigin_Switch_LeftBumper,\n\t\tk_EControllerActionOrigin_Switch_RightBumper,\n\t\tk_EControllerActionOrigin_Switch_Plus,  //Start\n\t\tk_EControllerActionOrigin_Switch_Minus,\t//Back\n\t\tk_EControllerActionOrigin_Switch_Capture,\n\t\tk_EControllerActionOrigin_Switch_LeftTrigger_Pull,\n\t\tk_EControllerActionOrigin_Switch_LeftTrigger_Click,\n\t\tk_EControllerActionOrigin_Switch_RightTrigger_Pull,\n\t\tk_EControllerActionOrigin_Switch_RightTrigger_Click,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_Move,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_Click,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_DPadNorth,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_DPadSouth,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_DPadWest,\n\t\tk_EControllerActionOrigin_Switch_LeftStick_DPadEast,\n\t\tk_EControllerActionOrigin_Switch_RightStick_Move,\n\t\tk_EControllerActionOrigin_Switch_RightStick_Click,\n\t\tk_EControllerActionOrigin_Switch_RightStick_DPadNorth,\n\t\tk_EControllerActionOrigin_Switch_RightStick_DPadSouth,\n\t\tk_EControllerActionOrigin_Switch_RightStick_DPadWest,\n\t\tk_EControllerActionOrigin_Switch_RightStick_DPadEast,\n\t\tk_EControllerActionOrigin_Switch_DPad_North,\n\t\tk_EControllerActionOrigin_Switch_DPad_South,\n\t\tk_EControllerActionOrigin_Switch_DPad_West,\n\t\tk_EControllerActionOrigin_Switch_DPad_East,\n\t\tk_EControllerActionOrigin_Switch_ProGyro_Move,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EControllerActionOrigin_Switch_ProGyro_Pitch,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EControllerActionOrigin_Switch_ProGyro_Yaw,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EControllerActionOrigin_Switch_ProGyro_Roll,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\t// Switch JoyCon Specific\n\t\tk_EControllerActionOrigin_Switch_RightGyro_Move,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EControllerActionOrigin_Switch_RightGyro_Pitch,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EControllerActionOrigin_Switch_RightGyro_Yaw,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EControllerActionOrigin_Switch_RightGyro_Roll,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EControllerActionOrigin_Switch_LeftGyro_Move,\n\t\tk_EControllerActionOrigin_Switch_LeftGyro_Pitch,\n\t\tk_EControllerActionOrigin_Switch_LeftGyro_Yaw,\n\t\tk_EControllerActionOrigin_Switch_LeftGyro_Roll,\n\t\tk_EControllerActionOrigin_Switch_LeftGrip_Lower, // Left JoyCon SR Button\n\t\tk_EControllerActionOrigin_Switch_LeftGrip_Upper, // Left JoyCon SL Button\n\t\tk_EControllerActionOrigin_Switch_RightGrip_Lower,  // Right JoyCon SL Button\n\t\tk_EControllerActionOrigin_Switch_RightGrip_Upper,  // Right JoyCon SR Button\n\n\t\t// Added in SDK 1.45\n\t\tk_EControllerActionOrigin_PS4_DPad_Move,\n\t\tk_EControllerActionOrigin_XBoxOne_DPad_Move,\n\t\tk_EControllerActionOrigin_XBox360_DPad_Move,\n\t\tk_EControllerActionOrigin_Switch_DPad_Move,\n\n\t\tk_EControllerActionOrigin_Count, // If Steam has added support for new controllers origins will go here.\n\t\tk_EControllerActionOrigin_MaximumPossibleValue = 32767, // Origins are currently a maximum of 16 bits.\n\t}\n\n\tpublic enum ESteamControllerLEDFlag : int {\n\t\tk_ESteamControllerLEDFlag_SetColor,\n\t\tk_ESteamControllerLEDFlag_RestoreUserDefault\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: set of relationships to other users\n\t//-----------------------------------------------------------------------------\n\tpublic enum EFriendRelationship : int {\n\t\tk_EFriendRelationshipNone = 0,\n\t\tk_EFriendRelationshipBlocked = 1,\t\t\t// this doesn't get stored; the user has just done an Ignore on an friendship invite\n\t\tk_EFriendRelationshipRequestRecipient = 2,\n\t\tk_EFriendRelationshipFriend = 3,\n\t\tk_EFriendRelationshipRequestInitiator = 4,\n\t\tk_EFriendRelationshipIgnored = 5,\t\t\t// this is stored; the user has explicit blocked this other user from comments/chat/etc\n\t\tk_EFriendRelationshipIgnoredFriend = 6,\n\t\tk_EFriendRelationshipSuggested_DEPRECATED = 7,\t\t// was used by the original implementation of the facebook linking feature, but now unused.\n\n\t\t// keep this updated\n\t\tk_EFriendRelationshipMax = 8,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: list of states a friend can be in\n\t//-----------------------------------------------------------------------------\n\tpublic enum EPersonaState : int {\n\t\tk_EPersonaStateOffline = 0,\t\t\t// friend is not currently logged on\n\t\tk_EPersonaStateOnline = 1,\t\t\t// friend is logged on\n\t\tk_EPersonaStateBusy = 2,\t\t\t// user is on, but busy\n\t\tk_EPersonaStateAway = 3,\t\t\t// auto-away feature\n\t\tk_EPersonaStateSnooze = 4,\t\t\t// auto-away for a long time\n\t\tk_EPersonaStateLookingToTrade = 5,\t// Online, trading\n\t\tk_EPersonaStateLookingToPlay = 6,\t// Online, wanting to play\n\t\tk_EPersonaStateInvisible = 7,\t\t// Online, but appears offline to friends.  This status is never published to clients.\n\t\tk_EPersonaStateMax,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: flags for enumerating friends list, or quickly checking a the relationship between users\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EFriendFlags : int {\n\t\tk_EFriendFlagNone\t\t\t= 0x00,\n\t\tk_EFriendFlagBlocked\t\t= 0x01,\n\t\tk_EFriendFlagFriendshipRequested\t= 0x02,\n\t\tk_EFriendFlagImmediate\t\t= 0x04,\t\t\t// \"regular\" friend\n\t\tk_EFriendFlagClanMember\t\t= 0x08,\n\t\tk_EFriendFlagOnGameServer\t= 0x10,\n\t\t// k_EFriendFlagHasPlayedWith\t= 0x20,\t// not currently used\n\t\t// k_EFriendFlagFriendOfFriend\t= 0x40, // not currently used\n\t\tk_EFriendFlagRequestingFriendship = 0x80,\n\t\tk_EFriendFlagRequestingInfo = 0x100,\n\t\tk_EFriendFlagIgnored\t\t= 0x200,\n\t\tk_EFriendFlagIgnoredFriend\t= 0x400,\n\t\t// k_EFriendFlagSuggested\t\t= 0x800,\t// not used\n\t\tk_EFriendFlagChatMember\t\t= 0x1000,\n\t\tk_EFriendFlagAll\t\t\t= 0xFFFF,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: user restriction flags\n\t//-----------------------------------------------------------------------------\n\tpublic enum EUserRestriction : int {\n\t\tk_nUserRestrictionNone\t\t= 0,\t// no known chat/content restriction\n\t\tk_nUserRestrictionUnknown\t= 1,\t// we don't know yet (user offline)\n\t\tk_nUserRestrictionAnyChat\t= 2,\t// user is not allowed to (or can't) send/recv any chat\n\t\tk_nUserRestrictionVoiceChat\t= 4,\t// user is not allowed to (or can't) send/recv voice chat\n\t\tk_nUserRestrictionGroupChat\t= 8,\t// user is not allowed to (or can't) send/recv group chat\n\t\tk_nUserRestrictionRating\t= 16,\t// user is too young according to rating in current region\n\t\tk_nUserRestrictionGameInvites\t= 32,\t// user cannot send or recv game invites (e.g. mobile)\n\t\tk_nUserRestrictionTrading\t= 64,\t// user cannot participate in trading (console, mobile)\n\t}\n\n\t// These values are passed as parameters to the store\n\tpublic enum EOverlayToStoreFlag : int {\n\t\tk_EOverlayToStoreFlag_None = 0,\n\t\tk_EOverlayToStoreFlag_AddToCart = 1,\n\t\tk_EOverlayToStoreFlag_AddToCartAndShow = 2,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Tells Steam where to place the browser window inside the overlay\n\t//-----------------------------------------------------------------------------\n\tpublic enum EActivateGameOverlayToWebPageMode : int {\n\t\tk_EActivateGameOverlayToWebPageMode_Default = 0,\t\t// Browser will open next to all other windows that the user has open in the overlay.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The window will remain open, even if the user closes then re-opens the overlay.\n\n\t\tk_EActivateGameOverlayToWebPageMode_Modal = 1\t\t\t// Browser will be opened in a special overlay configuration which hides all other windows\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// that the user has open in the overlay. When the user closes the overlay, the browser window\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// will also close. When the user closes the browser window, the overlay will automatically close.\n\t}\n\n\t// used in PersonaStateChange_t::m_nChangeFlags to describe what's changed about a user\n\t// these flags describe what the client has learned has changed recently, so on startup you'll see a name, avatar & relationship change for every friend\n\t[Flags]\n\tpublic enum EPersonaChange : int {\n\t\tk_EPersonaChangeName\t\t= 0x0001,\n\t\tk_EPersonaChangeStatus\t\t= 0x0002,\n\t\tk_EPersonaChangeComeOnline\t= 0x0004,\n\t\tk_EPersonaChangeGoneOffline\t= 0x0008,\n\t\tk_EPersonaChangeGamePlayed\t= 0x0010,\n\t\tk_EPersonaChangeGameServer\t= 0x0020,\n\t\tk_EPersonaChangeAvatar\t\t= 0x0040,\n\t\tk_EPersonaChangeJoinedSource= 0x0080,\n\t\tk_EPersonaChangeLeftSource\t= 0x0100,\n\t\tk_EPersonaChangeRelationshipChanged = 0x0200,\n\t\tk_EPersonaChangeNameFirstSet = 0x0400,\n\t\tk_EPersonaChangeBroadcast = 0x0800,\n\t\tk_EPersonaChangeNickname =\t0x1000,\n\t\tk_EPersonaChangeSteamLevel = 0x2000,\n\t\tk_EPersonaChangeRichPresence = 0x4000,\n\t}\n\n\t// list of possible return values from the ISteamGameCoordinator API\n\tpublic enum EGCResults : int {\n\t\tk_EGCResultOK = 0,\n\t\tk_EGCResultNoMessage = 1,\t\t\t// There is no message in the queue\n\t\tk_EGCResultBufferTooSmall = 2,\t\t// The buffer is too small for the requested message\n\t\tk_EGCResultNotLoggedOn = 3,\t\t\t// The client is not logged onto Steam\n\t\tk_EGCResultInvalidMessage = 4,\t\t// Something was wrong with the message being sent with SendMessage\n\t}\n\n\tpublic enum EHTMLMouseButton : int {\n\t\teHTMLMouseButton_Left = 0,\n\t\teHTMLMouseButton_Right = 1,\n\t\teHTMLMouseButton_Middle = 2,\n\t}\n\n\tpublic enum EMouseCursor : int {\n\t\tdc_user = 0,\n\t\tdc_none,\n\t\tdc_arrow,\n\t\tdc_ibeam,\n\t\tdc_hourglass,\n\t\tdc_waitarrow,\n\t\tdc_crosshair,\n\t\tdc_up,\n\t\tdc_sizenw,\n\t\tdc_sizese,\n\t\tdc_sizene,\n\t\tdc_sizesw,\n\t\tdc_sizew,\n\t\tdc_sizee,\n\t\tdc_sizen,\n\t\tdc_sizes,\n\t\tdc_sizewe,\n\t\tdc_sizens,\n\t\tdc_sizeall,\n\t\tdc_no,\n\t\tdc_hand,\n\t\tdc_blank, // don't show any custom cursor, just use your default\n\t\tdc_middle_pan,\n\t\tdc_north_pan,\n\t\tdc_north_east_pan,\n\t\tdc_east_pan,\n\t\tdc_south_east_pan,\n\t\tdc_south_pan,\n\t\tdc_south_west_pan,\n\t\tdc_west_pan,\n\t\tdc_north_west_pan,\n\t\tdc_alias,\n\t\tdc_cell,\n\t\tdc_colresize,\n\t\tdc_copycur,\n\t\tdc_verticaltext,\n\t\tdc_rowresize,\n\t\tdc_zoomin,\n\t\tdc_zoomout,\n\t\tdc_help,\n\t\tdc_custom,\n\n\t\tdc_last, // custom cursors start from this value and up\n\t}\n\n\t[Flags]\n\tpublic enum EHTMLKeyModifiers : int {\n\t\tk_eHTMLKeyModifier_None = 0,\n\t\tk_eHTMLKeyModifier_AltDown = 1 << 0,\n\t\tk_eHTMLKeyModifier_CtrlDown = 1 << 1,\n\t\tk_eHTMLKeyModifier_ShiftDown = 1 << 2,\n\t}\n\n\tpublic enum EInputSource : int {\n\t\tk_EInputSource_None,\n\t\tk_EInputSource_LeftTrackpad,\n\t\tk_EInputSource_RightTrackpad,\n\t\tk_EInputSource_Joystick,\n\t\tk_EInputSource_ABXY,\n\t\tk_EInputSource_Switch,\n\t\tk_EInputSource_LeftTrigger,\n\t\tk_EInputSource_RightTrigger,\n\t\tk_EInputSource_LeftBumper,\n\t\tk_EInputSource_RightBumper,\n\t\tk_EInputSource_Gyro,\n\t\tk_EInputSource_CenterTrackpad,\t\t// PS4\n\t\tk_EInputSource_RightJoystick,\t\t// Traditional Controllers\n\t\tk_EInputSource_DPad,\t\t\t\t// Traditional Controllers\n\t\tk_EInputSource_Key,                 // Keyboards with scan codes - Unused\n\t\tk_EInputSource_Mouse,               // Traditional mouse - Unused\n\t\tk_EInputSource_LeftGyro,\t\t\t// Secondary Gyro - Switch - Unused\n\t\tk_EInputSource_Count\n\t}\n\n\tpublic enum EInputSourceMode : int {\n\t\tk_EInputSourceMode_None,\n\t\tk_EInputSourceMode_Dpad,\n\t\tk_EInputSourceMode_Buttons,\n\t\tk_EInputSourceMode_FourButtons,\n\t\tk_EInputSourceMode_AbsoluteMouse,\n\t\tk_EInputSourceMode_RelativeMouse,\n\t\tk_EInputSourceMode_JoystickMove,\n\t\tk_EInputSourceMode_JoystickMouse,\n\t\tk_EInputSourceMode_JoystickCamera,\n\t\tk_EInputSourceMode_ScrollWheel,\n\t\tk_EInputSourceMode_Trigger,\n\t\tk_EInputSourceMode_TouchMenu,\n\t\tk_EInputSourceMode_MouseJoystick,\n\t\tk_EInputSourceMode_MouseRegion,\n\t\tk_EInputSourceMode_RadialMenu,\n\t\tk_EInputSourceMode_SingleButton,\n\t\tk_EInputSourceMode_Switches\n\t}\n\n\t// Note: Please do not use action origins as a way to identify controller types. There is no\n\t// guarantee that they will be added in a contiguous manner - use GetInputTypeForHandle instead.\n\t// Versions of Steam that add new controller types in the future will extend this enum so if you're\n\t// using a lookup table please check the bounds of any origins returned by Steam.\n\tpublic enum EInputActionOrigin : int {\n\t\t// Steam Controller\n\t\tk_EInputActionOrigin_None,\n\t\tk_EInputActionOrigin_SteamController_A,\n\t\tk_EInputActionOrigin_SteamController_B,\n\t\tk_EInputActionOrigin_SteamController_X,\n\t\tk_EInputActionOrigin_SteamController_Y,\n\t\tk_EInputActionOrigin_SteamController_LeftBumper,\n\t\tk_EInputActionOrigin_SteamController_RightBumper,\n\t\tk_EInputActionOrigin_SteamController_LeftGrip,\n\t\tk_EInputActionOrigin_SteamController_RightGrip,\n\t\tk_EInputActionOrigin_SteamController_Start,\n\t\tk_EInputActionOrigin_SteamController_Back,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_Touch,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_Swipe,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_Click,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_DPadNorth,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_DPadSouth,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_DPadWest,\n\t\tk_EInputActionOrigin_SteamController_LeftPad_DPadEast,\n\t\tk_EInputActionOrigin_SteamController_RightPad_Touch,\n\t\tk_EInputActionOrigin_SteamController_RightPad_Swipe,\n\t\tk_EInputActionOrigin_SteamController_RightPad_Click,\n\t\tk_EInputActionOrigin_SteamController_RightPad_DPadNorth,\n\t\tk_EInputActionOrigin_SteamController_RightPad_DPadSouth,\n\t\tk_EInputActionOrigin_SteamController_RightPad_DPadWest,\n\t\tk_EInputActionOrigin_SteamController_RightPad_DPadEast,\n\t\tk_EInputActionOrigin_SteamController_LeftTrigger_Pull,\n\t\tk_EInputActionOrigin_SteamController_LeftTrigger_Click,\n\t\tk_EInputActionOrigin_SteamController_RightTrigger_Pull,\n\t\tk_EInputActionOrigin_SteamController_RightTrigger_Click,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_Move,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_Click,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_DPadNorth,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_DPadSouth,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_DPadWest,\n\t\tk_EInputActionOrigin_SteamController_LeftStick_DPadEast,\n\t\tk_EInputActionOrigin_SteamController_Gyro_Move,\n\t\tk_EInputActionOrigin_SteamController_Gyro_Pitch,\n\t\tk_EInputActionOrigin_SteamController_Gyro_Yaw,\n\t\tk_EInputActionOrigin_SteamController_Gyro_Roll,\n\t\tk_EInputActionOrigin_SteamController_Reserved0,\n\t\tk_EInputActionOrigin_SteamController_Reserved1,\n\t\tk_EInputActionOrigin_SteamController_Reserved2,\n\t\tk_EInputActionOrigin_SteamController_Reserved3,\n\t\tk_EInputActionOrigin_SteamController_Reserved4,\n\t\tk_EInputActionOrigin_SteamController_Reserved5,\n\t\tk_EInputActionOrigin_SteamController_Reserved6,\n\t\tk_EInputActionOrigin_SteamController_Reserved7,\n\t\tk_EInputActionOrigin_SteamController_Reserved8,\n\t\tk_EInputActionOrigin_SteamController_Reserved9,\n\t\tk_EInputActionOrigin_SteamController_Reserved10,\n\n\t\t// PS4 Dual Shock\n\t\tk_EInputActionOrigin_PS4_X,\n\t\tk_EInputActionOrigin_PS4_Circle,\n\t\tk_EInputActionOrigin_PS4_Triangle,\n\t\tk_EInputActionOrigin_PS4_Square,\n\t\tk_EInputActionOrigin_PS4_LeftBumper,\n\t\tk_EInputActionOrigin_PS4_RightBumper,\n\t\tk_EInputActionOrigin_PS4_Options,\t//Start\n\t\tk_EInputActionOrigin_PS4_Share,\t\t//Back\n\t\tk_EInputActionOrigin_PS4_LeftPad_Touch,\n\t\tk_EInputActionOrigin_PS4_LeftPad_Swipe,\n\t\tk_EInputActionOrigin_PS4_LeftPad_Click,\n\t\tk_EInputActionOrigin_PS4_LeftPad_DPadNorth,\n\t\tk_EInputActionOrigin_PS4_LeftPad_DPadSouth,\n\t\tk_EInputActionOrigin_PS4_LeftPad_DPadWest,\n\t\tk_EInputActionOrigin_PS4_LeftPad_DPadEast,\n\t\tk_EInputActionOrigin_PS4_RightPad_Touch,\n\t\tk_EInputActionOrigin_PS4_RightPad_Swipe,\n\t\tk_EInputActionOrigin_PS4_RightPad_Click,\n\t\tk_EInputActionOrigin_PS4_RightPad_DPadNorth,\n\t\tk_EInputActionOrigin_PS4_RightPad_DPadSouth,\n\t\tk_EInputActionOrigin_PS4_RightPad_DPadWest,\n\t\tk_EInputActionOrigin_PS4_RightPad_DPadEast,\n\t\tk_EInputActionOrigin_PS4_CenterPad_Touch,\n\t\tk_EInputActionOrigin_PS4_CenterPad_Swipe,\n\t\tk_EInputActionOrigin_PS4_CenterPad_Click,\n\t\tk_EInputActionOrigin_PS4_CenterPad_DPadNorth,\n\t\tk_EInputActionOrigin_PS4_CenterPad_DPadSouth,\n\t\tk_EInputActionOrigin_PS4_CenterPad_DPadWest,\n\t\tk_EInputActionOrigin_PS4_CenterPad_DPadEast,\n\t\tk_EInputActionOrigin_PS4_LeftTrigger_Pull,\n\t\tk_EInputActionOrigin_PS4_LeftTrigger_Click,\n\t\tk_EInputActionOrigin_PS4_RightTrigger_Pull,\n\t\tk_EInputActionOrigin_PS4_RightTrigger_Click,\n\t\tk_EInputActionOrigin_PS4_LeftStick_Move,\n\t\tk_EInputActionOrigin_PS4_LeftStick_Click,\n\t\tk_EInputActionOrigin_PS4_LeftStick_DPadNorth,\n\t\tk_EInputActionOrigin_PS4_LeftStick_DPadSouth,\n\t\tk_EInputActionOrigin_PS4_LeftStick_DPadWest,\n\t\tk_EInputActionOrigin_PS4_LeftStick_DPadEast,\n\t\tk_EInputActionOrigin_PS4_RightStick_Move,\n\t\tk_EInputActionOrigin_PS4_RightStick_Click,\n\t\tk_EInputActionOrigin_PS4_RightStick_DPadNorth,\n\t\tk_EInputActionOrigin_PS4_RightStick_DPadSouth,\n\t\tk_EInputActionOrigin_PS4_RightStick_DPadWest,\n\t\tk_EInputActionOrigin_PS4_RightStick_DPadEast,\n\t\tk_EInputActionOrigin_PS4_DPad_North,\n\t\tk_EInputActionOrigin_PS4_DPad_South,\n\t\tk_EInputActionOrigin_PS4_DPad_West,\n\t\tk_EInputActionOrigin_PS4_DPad_East,\n\t\tk_EInputActionOrigin_PS4_Gyro_Move,\n\t\tk_EInputActionOrigin_PS4_Gyro_Pitch,\n\t\tk_EInputActionOrigin_PS4_Gyro_Yaw,\n\t\tk_EInputActionOrigin_PS4_Gyro_Roll,\n\t\tk_EInputActionOrigin_PS4_DPad_Move,\n\t\tk_EInputActionOrigin_PS4_Reserved1,\n\t\tk_EInputActionOrigin_PS4_Reserved2,\n\t\tk_EInputActionOrigin_PS4_Reserved3,\n\t\tk_EInputActionOrigin_PS4_Reserved4,\n\t\tk_EInputActionOrigin_PS4_Reserved5,\n\t\tk_EInputActionOrigin_PS4_Reserved6,\n\t\tk_EInputActionOrigin_PS4_Reserved7,\n\t\tk_EInputActionOrigin_PS4_Reserved8,\n\t\tk_EInputActionOrigin_PS4_Reserved9,\n\t\tk_EInputActionOrigin_PS4_Reserved10,\n\n\t\t// XBox One\n\t\tk_EInputActionOrigin_XBoxOne_A,\n\t\tk_EInputActionOrigin_XBoxOne_B,\n\t\tk_EInputActionOrigin_XBoxOne_X,\n\t\tk_EInputActionOrigin_XBoxOne_Y,\n\t\tk_EInputActionOrigin_XBoxOne_LeftBumper,\n\t\tk_EInputActionOrigin_XBoxOne_RightBumper,\n\t\tk_EInputActionOrigin_XBoxOne_Menu,  //Start\n\t\tk_EInputActionOrigin_XBoxOne_View,  //Back\n\t\tk_EInputActionOrigin_XBoxOne_LeftTrigger_Pull,\n\t\tk_EInputActionOrigin_XBoxOne_LeftTrigger_Click,\n\t\tk_EInputActionOrigin_XBoxOne_RightTrigger_Pull,\n\t\tk_EInputActionOrigin_XBoxOne_RightTrigger_Click,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_Move,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_Click,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_DPadNorth,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_DPadSouth,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_DPadWest,\n\t\tk_EInputActionOrigin_XBoxOne_LeftStick_DPadEast,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_Move,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_Click,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_DPadNorth,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_DPadSouth,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_DPadWest,\n\t\tk_EInputActionOrigin_XBoxOne_RightStick_DPadEast,\n\t\tk_EInputActionOrigin_XBoxOne_DPad_North,\n\t\tk_EInputActionOrigin_XBoxOne_DPad_South,\n\t\tk_EInputActionOrigin_XBoxOne_DPad_West,\n\t\tk_EInputActionOrigin_XBoxOne_DPad_East,\n\t\tk_EInputActionOrigin_XBoxOne_DPad_Move,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved1,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved2,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved3,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved4,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved5,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved6,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved7,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved8,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved9,\n\t\tk_EInputActionOrigin_XBoxOne_Reserved10,\n\n\t\t// XBox 360\n\t\tk_EInputActionOrigin_XBox360_A,\n\t\tk_EInputActionOrigin_XBox360_B,\n\t\tk_EInputActionOrigin_XBox360_X,\n\t\tk_EInputActionOrigin_XBox360_Y,\n\t\tk_EInputActionOrigin_XBox360_LeftBumper,\n\t\tk_EInputActionOrigin_XBox360_RightBumper,\n\t\tk_EInputActionOrigin_XBox360_Start,\t\t//Start\n\t\tk_EInputActionOrigin_XBox360_Back,\t\t//Back\n\t\tk_EInputActionOrigin_XBox360_LeftTrigger_Pull,\n\t\tk_EInputActionOrigin_XBox360_LeftTrigger_Click,\n\t\tk_EInputActionOrigin_XBox360_RightTrigger_Pull,\n\t\tk_EInputActionOrigin_XBox360_RightTrigger_Click,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_Move,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_Click,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_DPadNorth,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_DPadSouth,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_DPadWest,\n\t\tk_EInputActionOrigin_XBox360_LeftStick_DPadEast,\n\t\tk_EInputActionOrigin_XBox360_RightStick_Move,\n\t\tk_EInputActionOrigin_XBox360_RightStick_Click,\n\t\tk_EInputActionOrigin_XBox360_RightStick_DPadNorth,\n\t\tk_EInputActionOrigin_XBox360_RightStick_DPadSouth,\n\t\tk_EInputActionOrigin_XBox360_RightStick_DPadWest,\n\t\tk_EInputActionOrigin_XBox360_RightStick_DPadEast,\n\t\tk_EInputActionOrigin_XBox360_DPad_North,\n\t\tk_EInputActionOrigin_XBox360_DPad_South,\n\t\tk_EInputActionOrigin_XBox360_DPad_West,\n\t\tk_EInputActionOrigin_XBox360_DPad_East,\n\t\tk_EInputActionOrigin_XBox360_DPad_Move,\n\t\tk_EInputActionOrigin_XBox360_Reserved1,\n\t\tk_EInputActionOrigin_XBox360_Reserved2,\n\t\tk_EInputActionOrigin_XBox360_Reserved3,\n\t\tk_EInputActionOrigin_XBox360_Reserved4,\n\t\tk_EInputActionOrigin_XBox360_Reserved5,\n\t\tk_EInputActionOrigin_XBox360_Reserved6,\n\t\tk_EInputActionOrigin_XBox360_Reserved7,\n\t\tk_EInputActionOrigin_XBox360_Reserved8,\n\t\tk_EInputActionOrigin_XBox360_Reserved9,\n\t\tk_EInputActionOrigin_XBox360_Reserved10,\n\n\n\t\t// Switch - Pro or Joycons used as a single input device.\n\t\t// This does not apply to a single joycon\n\t\tk_EInputActionOrigin_Switch_A,\n\t\tk_EInputActionOrigin_Switch_B,\n\t\tk_EInputActionOrigin_Switch_X,\n\t\tk_EInputActionOrigin_Switch_Y,\n\t\tk_EInputActionOrigin_Switch_LeftBumper,\n\t\tk_EInputActionOrigin_Switch_RightBumper,\n\t\tk_EInputActionOrigin_Switch_Plus,\t//Start\n\t\tk_EInputActionOrigin_Switch_Minus,\t//Back\n\t\tk_EInputActionOrigin_Switch_Capture,\n\t\tk_EInputActionOrigin_Switch_LeftTrigger_Pull,\n\t\tk_EInputActionOrigin_Switch_LeftTrigger_Click,\n\t\tk_EInputActionOrigin_Switch_RightTrigger_Pull,\n\t\tk_EInputActionOrigin_Switch_RightTrigger_Click,\n\t\tk_EInputActionOrigin_Switch_LeftStick_Move,\n\t\tk_EInputActionOrigin_Switch_LeftStick_Click,\n\t\tk_EInputActionOrigin_Switch_LeftStick_DPadNorth,\n\t\tk_EInputActionOrigin_Switch_LeftStick_DPadSouth,\n\t\tk_EInputActionOrigin_Switch_LeftStick_DPadWest,\n\t\tk_EInputActionOrigin_Switch_LeftStick_DPadEast,\n\t\tk_EInputActionOrigin_Switch_RightStick_Move,\n\t\tk_EInputActionOrigin_Switch_RightStick_Click,\n\t\tk_EInputActionOrigin_Switch_RightStick_DPadNorth,\n\t\tk_EInputActionOrigin_Switch_RightStick_DPadSouth,\n\t\tk_EInputActionOrigin_Switch_RightStick_DPadWest,\n\t\tk_EInputActionOrigin_Switch_RightStick_DPadEast,\n\t\tk_EInputActionOrigin_Switch_DPad_North,\n\t\tk_EInputActionOrigin_Switch_DPad_South,\n\t\tk_EInputActionOrigin_Switch_DPad_West,\n\t\tk_EInputActionOrigin_Switch_DPad_East,\n\t\tk_EInputActionOrigin_Switch_ProGyro_Move,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EInputActionOrigin_Switch_ProGyro_Pitch,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EInputActionOrigin_Switch_ProGyro_Yaw,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EInputActionOrigin_Switch_ProGyro_Roll,  // Primary Gyro in Pro Controller, or Right JoyCon\n\t\tk_EInputActionOrigin_Switch_DPad_Move,\n\t\tk_EInputActionOrigin_Switch_Reserved1,\n\t\tk_EInputActionOrigin_Switch_Reserved2,\n\t\tk_EInputActionOrigin_Switch_Reserved3,\n\t\tk_EInputActionOrigin_Switch_Reserved4,\n\t\tk_EInputActionOrigin_Switch_Reserved5,\n\t\tk_EInputActionOrigin_Switch_Reserved6,\n\t\tk_EInputActionOrigin_Switch_Reserved7,\n\t\tk_EInputActionOrigin_Switch_Reserved8,\n\t\tk_EInputActionOrigin_Switch_Reserved9,\n\t\tk_EInputActionOrigin_Switch_Reserved10,\n\n\t\t// Switch JoyCon Specific\n\t\tk_EInputActionOrigin_Switch_RightGyro_Move,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EInputActionOrigin_Switch_RightGyro_Pitch,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EInputActionOrigin_Switch_RightGyro_Yaw,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EInputActionOrigin_Switch_RightGyro_Roll,  // Right JoyCon Gyro generally should correspond to Pro's single gyro\n\t\tk_EInputActionOrigin_Switch_LeftGyro_Move,\n\t\tk_EInputActionOrigin_Switch_LeftGyro_Pitch,\n\t\tk_EInputActionOrigin_Switch_LeftGyro_Yaw,\n\t\tk_EInputActionOrigin_Switch_LeftGyro_Roll,\n\t\tk_EInputActionOrigin_Switch_LeftGrip_Lower, // Left JoyCon SR Button\n\t\tk_EInputActionOrigin_Switch_LeftGrip_Upper, // Left JoyCon SL Button\n\t\tk_EInputActionOrigin_Switch_RightGrip_Lower,  // Right JoyCon SL Button\n\t\tk_EInputActionOrigin_Switch_RightGrip_Upper,  // Right JoyCon SR Button\n\t\tk_EInputActionOrigin_Switch_Reserved11,\n\t\tk_EInputActionOrigin_Switch_Reserved12,\n\t\tk_EInputActionOrigin_Switch_Reserved13,\n\t\tk_EInputActionOrigin_Switch_Reserved14,\n\t\tk_EInputActionOrigin_Switch_Reserved15,\n\t\tk_EInputActionOrigin_Switch_Reserved16,\n\t\tk_EInputActionOrigin_Switch_Reserved17,\n\t\tk_EInputActionOrigin_Switch_Reserved18,\n\t\tk_EInputActionOrigin_Switch_Reserved19,\n\t\tk_EInputActionOrigin_Switch_Reserved20,\n\n\t\tk_EInputActionOrigin_Count, // If Steam has added support for new controllers origins will go here.\n\t\tk_EInputActionOrigin_MaximumPossibleValue = 32767, // Origins are currently a maximum of 16 bits.\n\t}\n\n\tpublic enum EXboxOrigin : int {\n\t\tk_EXboxOrigin_A,\n\t\tk_EXboxOrigin_B,\n\t\tk_EXboxOrigin_X,\n\t\tk_EXboxOrigin_Y,\n\t\tk_EXboxOrigin_LeftBumper,\n\t\tk_EXboxOrigin_RightBumper,\n\t\tk_EXboxOrigin_Menu,  //Start\n\t\tk_EXboxOrigin_View,  //Back\n\t\tk_EXboxOrigin_LeftTrigger_Pull,\n\t\tk_EXboxOrigin_LeftTrigger_Click,\n\t\tk_EXboxOrigin_RightTrigger_Pull,\n\t\tk_EXboxOrigin_RightTrigger_Click,\n\t\tk_EXboxOrigin_LeftStick_Move,\n\t\tk_EXboxOrigin_LeftStick_Click,\n\t\tk_EXboxOrigin_LeftStick_DPadNorth,\n\t\tk_EXboxOrigin_LeftStick_DPadSouth,\n\t\tk_EXboxOrigin_LeftStick_DPadWest,\n\t\tk_EXboxOrigin_LeftStick_DPadEast,\n\t\tk_EXboxOrigin_RightStick_Move,\n\t\tk_EXboxOrigin_RightStick_Click,\n\t\tk_EXboxOrigin_RightStick_DPadNorth,\n\t\tk_EXboxOrigin_RightStick_DPadSouth,\n\t\tk_EXboxOrigin_RightStick_DPadWest,\n\t\tk_EXboxOrigin_RightStick_DPadEast,\n\t\tk_EXboxOrigin_DPad_North,\n\t\tk_EXboxOrigin_DPad_South,\n\t\tk_EXboxOrigin_DPad_West,\n\t\tk_EXboxOrigin_DPad_East,\n\t\tk_EXboxOrigin_Count,\n\t}\n\n\tpublic enum ESteamControllerPad : int {\n\t\tk_ESteamControllerPad_Left,\n\t\tk_ESteamControllerPad_Right\n\t}\n\n\tpublic enum ESteamInputType : int {\n\t\tk_ESteamInputType_Unknown,\n\t\tk_ESteamInputType_SteamController,\n\t\tk_ESteamInputType_XBox360Controller,\n\t\tk_ESteamInputType_XBoxOneController,\n\t\tk_ESteamInputType_GenericGamepad,\t\t// DirectInput controllers\n\t\tk_ESteamInputType_PS4Controller,\n\t\tk_ESteamInputType_AppleMFiController,\t// Unused\n\t\tk_ESteamInputType_AndroidController,\t// Unused\n\t\tk_ESteamInputType_SwitchJoyConPair,\t\t// Unused\n\t\tk_ESteamInputType_SwitchJoyConSingle,\t// Unused\n\t\tk_ESteamInputType_SwitchProController,\n\t\tk_ESteamInputType_MobileTouch,\t\t\t// Steam Link App On-screen Virtual Controller\n\t\tk_ESteamInputType_PS3Controller,\t\t// Currently uses PS4 Origins\n\t\tk_ESteamInputType_Count,\n\t\tk_ESteamInputType_MaximumPossibleValue = 255,\n\t}\n\n\t// These values are passed into SetLEDColor\n\tpublic enum ESteamInputLEDFlag : int {\n\t\tk_ESteamInputLEDFlag_SetColor,\n\t\t// Restore the LED color to the user's preference setting as set in the controller personalization menu.\n\t\t// This also happens automatically on exit of your game.\n\t\tk_ESteamInputLEDFlag_RestoreUserDefault\n\t}\n\n\t[Flags]\n\tpublic enum ESteamItemFlags : int {\n\t\t// Item status flags - these flags are permanently attached to specific item instances\n\t\tk_ESteamItemNoTrade = 1 << 0, // This item is account-locked and cannot be traded or given away.\n\n\t\t// Action confirmation flags - these flags are set one time only, as part of a result set\n\t\tk_ESteamItemRemoved = 1 << 8,\t// The item has been destroyed, traded away, expired, or otherwise invalidated\n\t\tk_ESteamItemConsumed = 1 << 9,\t// The item quantity has been decreased by 1 via ConsumeItem API.\n\n\t\t// All other flag bits are currently reserved for internal Steam use at this time.\n\t\t// Do not assume anything about the state of other flags which are not defined here.\n\t}\n\n\t// lobby type description\n\tpublic enum ELobbyType : int {\n\t\tk_ELobbyTypePrivate = 0,\t\t// only way to join the lobby is to invite to someone else\n\t\tk_ELobbyTypeFriendsOnly = 1,\t// shows for friends or invitees, but not in lobby list\n\t\tk_ELobbyTypePublic = 2,\t\t\t// visible for friends and in lobby list\n\t\tk_ELobbyTypeInvisible = 3,\t\t// returned by search, but not visible to other friends\n\t\t\t\t\t\t\t\t\t\t//    useful if you want a user in two lobbies, for example matching groups together\n\t\t\t\t\t\t\t\t\t\t//\t  a user can be in only one regular lobby, and up to two invisible lobbies\n\t\tk_ELobbyTypePrivateUnique = 4,\t// private, unique and does not delete when empty - only one of these may exist per unique keypair set\n\t\t\t\t\t\t\t\t\t\t// can only create from webapi\n\t}\n\n\t// lobby search filter tools\n\tpublic enum ELobbyComparison : int {\n\t\tk_ELobbyComparisonEqualToOrLessThan = -2,\n\t\tk_ELobbyComparisonLessThan = -1,\n\t\tk_ELobbyComparisonEqual = 0,\n\t\tk_ELobbyComparisonGreaterThan = 1,\n\t\tk_ELobbyComparisonEqualToOrGreaterThan = 2,\n\t\tk_ELobbyComparisonNotEqual = 3,\n\t}\n\n\t// lobby search distance. Lobby results are sorted from closest to farthest.\n\tpublic enum ELobbyDistanceFilter : int {\n\t\tk_ELobbyDistanceFilterClose,\t\t// only lobbies in the same immediate region will be returned\n\t\tk_ELobbyDistanceFilterDefault,\t\t// only lobbies in the same region or near by regions\n\t\tk_ELobbyDistanceFilterFar,\t\t\t// for games that don't have many latency requirements, will return lobbies about half-way around the globe\n\t\tk_ELobbyDistanceFilterWorldwide,\t// no filtering, will match lobbies as far as India to NY (not recommended, expect multiple seconds of latency between the clients)\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Used in ChatInfo messages - fields specific to a chat member - must fit in a uint32\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EChatMemberStateChange : int {\n\t\t// Specific to joining / leaving the chatroom\n\t\tk_EChatMemberStateChangeEntered\t\t\t= 0x0001,\t\t// This user has joined or is joining the chat room\n\t\tk_EChatMemberStateChangeLeft\t\t\t= 0x0002,\t\t// This user has left or is leaving the chat room\n\t\tk_EChatMemberStateChangeDisconnected\t= 0x0004,\t\t// User disconnected without leaving the chat first\n\t\tk_EChatMemberStateChangeKicked\t\t\t= 0x0008,\t\t// User kicked\n\t\tk_EChatMemberStateChangeBanned\t\t\t= 0x0010,\t\t// User kicked and banned\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Functions for quickly creating a Party with friends or acquaintances,\n\t//\t\t\tEG from chat rooms.\n\t//-----------------------------------------------------------------------------\n\tpublic enum ESteamPartyBeaconLocationType : int {\n\t\tk_ESteamPartyBeaconLocationType_Invalid = 0,\n\t\tk_ESteamPartyBeaconLocationType_ChatGroup = 1,\n\n\t\tk_ESteamPartyBeaconLocationType_Max,\n\t}\n\n\tpublic enum ESteamPartyBeaconLocationData : int {\n\t\tk_ESteamPartyBeaconLocationDataInvalid = 0,\n\t\tk_ESteamPartyBeaconLocationDataName = 1,\n\t\tk_ESteamPartyBeaconLocationDataIconURLSmall = 2,\n\t\tk_ESteamPartyBeaconLocationDataIconURLMedium = 3,\n\t\tk_ESteamPartyBeaconLocationDataIconURLLarge = 4,\n\t}\n\n\tpublic enum PlayerAcceptState_t : int {\n\t\tk_EStateUnknown = 0,\n\t\tk_EStatePlayerAccepted = 1,\n\t\tk_EStatePlayerDeclined = 2,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose:\n\t//-----------------------------------------------------------------------------\n\tpublic enum AudioPlayback_Status : int {\n\t\tAudioPlayback_Undefined = 0,\n\t\tAudioPlayback_Playing = 1,\n\t\tAudioPlayback_Paused = 2,\n\t\tAudioPlayback_Idle = 3\n\t}\n\n\t// list of possible errors returned by SendP2PPacket() API\n\t// these will be posted in the P2PSessionConnectFail_t callback\n\tpublic enum EP2PSessionError : int {\n\t\tk_EP2PSessionErrorNone = 0,\n\t\tk_EP2PSessionErrorNotRunningApp = 1,\t\t\t// target is not running the same game\n\t\tk_EP2PSessionErrorNoRightsToApp = 2,\t\t\t// local user doesn't own the app that is running\n\t\tk_EP2PSessionErrorDestinationNotLoggedIn = 3,\t// target user isn't connected to Steam\n\t\tk_EP2PSessionErrorTimeout = 4,\t\t\t\t\t// target isn't responding, perhaps not calling AcceptP2PSessionWithUser()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// corporate firewalls can also block this (NAT traversal is not firewall traversal)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// make sure that UDP ports 3478, 4379, and 4380 are open in an outbound direction\n\t\tk_EP2PSessionErrorMax = 5\n\t}\n\n\t// SendP2PPacket() send types\n\t// Typically k_EP2PSendUnreliable is what you want for UDP-like packets, k_EP2PSendReliable for TCP-like packets\n\tpublic enum EP2PSend : int {\n\t\t// Basic UDP send. Packets can't be bigger than 1200 bytes (your typical MTU size). Can be lost, or arrive out of order (rare).\n\t\t// The sending API does have some knowledge of the underlying connection, so if there is no NAT-traversal accomplished or\n\t\t// there is a recognized adjustment happening on the connection, the packet will be batched until the connection is open again.\n\t\tk_EP2PSendUnreliable = 0,\n\n\t\t// As above, but if the underlying p2p connection isn't yet established the packet will just be thrown away. Using this on the first\n\t\t// packet sent to a remote host almost guarantees the packet will be dropped.\n\t\t// This is only really useful for kinds of data that should never buffer up, i.e. voice payload packets\n\t\tk_EP2PSendUnreliableNoDelay = 1,\n\n\t\t// Reliable message send. Can send up to 1MB of data in a single message.\n\t\t// Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for efficient sends of large chunks of data.\n\t\tk_EP2PSendReliable = 2,\n\n\t\t// As above, but applies the Nagle algorithm to the send - sends will accumulate\n\t\t// until the current MTU size (typically ~1200 bytes, but can change) or ~200ms has passed (Nagle algorithm).\n\t\t// Useful if you want to send a set of smaller messages but have the coalesced into a single packet\n\t\t// Since the reliable stream is all ordered, you can do several small message sends with k_EP2PSendReliableWithBuffering and then\n\t\t// do a normal k_EP2PSendReliable to force all the buffered data to be sent.\n\t\tk_EP2PSendReliableWithBuffering = 3,\n\n\t}\n\n\t// connection progress indicators, used by CreateP2PConnectionSocket()\n\tpublic enum ESNetSocketState : int {\n\t\tk_ESNetSocketStateInvalid = 0,\n\n\t\t// communication is valid\n\t\tk_ESNetSocketStateConnected = 1,\n\n\t\t// states while establishing a connection\n\t\tk_ESNetSocketStateInitiated = 10,\t\t\t\t// the connection state machine has started\n\n\t\t// p2p connections\n\t\tk_ESNetSocketStateLocalCandidatesFound = 11,\t// we've found our local IP info\n\t\tk_ESNetSocketStateReceivedRemoteCandidates = 12,// we've received information from the remote machine, via the Steam back-end, about their IP info\n\n\t\t// direct connections\n\t\tk_ESNetSocketStateChallengeHandshake = 15,\t\t// we've received a challenge packet from the server\n\n\t\t// failure states\n\t\tk_ESNetSocketStateDisconnecting = 21,\t\t\t// the API shut it down, and we're in the process of telling the other end\n\t\tk_ESNetSocketStateLocalDisconnect = 22,\t\t\t// the API shut it down, and we've completed shutdown\n\t\tk_ESNetSocketStateTimeoutDuringConnect = 23,\t// we timed out while trying to creating the connection\n\t\tk_ESNetSocketStateRemoteEndDisconnected = 24,\t// the remote end has disconnected from us\n\t\tk_ESNetSocketStateConnectionBroken = 25,\t\t// connection has been broken; either the other end has disappeared or our local network connection has broke\n\n\t}\n\n\t// describes how the socket is currently connected\n\tpublic enum ESNetSocketConnectionType : int {\n\t\tk_ESNetSocketConnectionTypeNotConnected = 0,\n\t\tk_ESNetSocketConnectionTypeUDP = 1,\n\t\tk_ESNetSocketConnectionTypeUDPRelay = 2,\n\t}\n\n\t// Feature types for parental settings\n\tpublic enum EParentalFeature : int {\n\t\tk_EFeatureInvalid = 0,\n\t\tk_EFeatureStore = 1,\n\t\tk_EFeatureCommunity = 2,\n\t\tk_EFeatureProfile = 3,\n\t\tk_EFeatureFriends = 4,\n\t\tk_EFeatureNews = 5,\n\t\tk_EFeatureTrading = 6,\n\t\tk_EFeatureSettings = 7,\n\t\tk_EFeatureConsole = 8,\n\t\tk_EFeatureBrowser = 9,\n\t\tk_EFeatureParentalSetup = 10,\n\t\tk_EFeatureLibrary = 11,\n\t\tk_EFeatureTest = 12,\n\t\tk_EFeatureMax\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: The form factor of a device\n\t//-----------------------------------------------------------------------------\n\tpublic enum ESteamDeviceFormFactor : int {\n\t\tk_ESteamDeviceFormFactorUnknown,\n\t\tk_ESteamDeviceFormFactorPhone,\n\t\tk_ESteamDeviceFormFactorTablet,\n\t\tk_ESteamDeviceFormFactorComputer,\n\t\tk_ESteamDeviceFormFactorTV,\n\t}\n\n\t[Flags]\n\tpublic enum ERemoteStoragePlatform : int {\n\t\tk_ERemoteStoragePlatformNone\t\t= 0,\n\t\tk_ERemoteStoragePlatformWindows\t\t= (1 << 0),\n\t\tk_ERemoteStoragePlatformOSX\t\t\t= (1 << 1),\n\t\tk_ERemoteStoragePlatformPS3\t\t\t= (1 << 2),\n\t\tk_ERemoteStoragePlatformLinux\t\t= (1 << 3),\n\t\tk_ERemoteStoragePlatformReserved2\t= (1 << 4),\n\t\tk_ERemoteStoragePlatformAndroid\t\t= (1 << 5),\n\t\tk_ERemoteStoragePlatformIOS\t\t\t= (1 << 6),\n\n\t\tk_ERemoteStoragePlatformAll = -1\n\t}\n\n\tpublic enum ERemoteStoragePublishedFileVisibility : int {\n\t\tk_ERemoteStoragePublishedFileVisibilityPublic = 0,\n\t\tk_ERemoteStoragePublishedFileVisibilityFriendsOnly = 1,\n\t\tk_ERemoteStoragePublishedFileVisibilityPrivate = 2,\n\t}\n\n\tpublic enum EWorkshopFileType : int {\n\t\tk_EWorkshopFileTypeFirst = 0,\n\n\t\tk_EWorkshopFileTypeCommunity\t\t\t  = 0,\t\t// normal Workshop item that can be subscribed to\n\t\tk_EWorkshopFileTypeMicrotransaction\t\t  = 1,\t\t// Workshop item that is meant to be voted on for the purpose of selling in-game\n\t\tk_EWorkshopFileTypeCollection\t\t\t  = 2,\t\t// a collection of Workshop or Greenlight items\n\t\tk_EWorkshopFileTypeArt\t\t\t\t\t  = 3,\t\t// artwork\n\t\tk_EWorkshopFileTypeVideo\t\t\t\t  = 4,\t\t// external video\n\t\tk_EWorkshopFileTypeScreenshot\t\t\t  = 5,\t\t// screenshot\n\t\tk_EWorkshopFileTypeGame\t\t\t\t\t  = 6,\t\t// Greenlight game entry\n\t\tk_EWorkshopFileTypeSoftware\t\t\t\t  = 7,\t\t// Greenlight software entry\n\t\tk_EWorkshopFileTypeConcept\t\t\t\t  = 8,\t\t// Greenlight concept\n\t\tk_EWorkshopFileTypeWebGuide\t\t\t\t  = 9,\t\t// Steam web guide\n\t\tk_EWorkshopFileTypeIntegratedGuide\t\t  = 10,\t\t// application integrated guide\n\t\tk_EWorkshopFileTypeMerch\t\t\t\t  = 11,\t\t// Workshop merchandise meant to be voted on for the purpose of being sold\n\t\tk_EWorkshopFileTypeControllerBinding\t  = 12,\t\t// Steam Controller bindings\n\t\tk_EWorkshopFileTypeSteamworksAccessInvite = 13,\t\t// internal\n\t\tk_EWorkshopFileTypeSteamVideo\t\t\t  = 14,\t\t// Steam video\n\t\tk_EWorkshopFileTypeGameManagedItem\t\t  = 15,\t\t// managed completely by the game, not the user, and not shown on the web\n\n\t\t// Update k_EWorkshopFileTypeMax if you add values.\n\t\tk_EWorkshopFileTypeMax = 16\n\n\t}\n\n\tpublic enum EWorkshopVote : int {\n\t\tk_EWorkshopVoteUnvoted = 0,\n\t\tk_EWorkshopVoteFor = 1,\n\t\tk_EWorkshopVoteAgainst = 2,\n\t\tk_EWorkshopVoteLater = 3,\n\t}\n\n\tpublic enum EWorkshopFileAction : int {\n\t\tk_EWorkshopFileActionPlayed = 0,\n\t\tk_EWorkshopFileActionCompleted = 1,\n\t}\n\n\tpublic enum EWorkshopEnumerationType : int {\n\t\tk_EWorkshopEnumerationTypeRankedByVote = 0,\n\t\tk_EWorkshopEnumerationTypeRecent = 1,\n\t\tk_EWorkshopEnumerationTypeTrending = 2,\n\t\tk_EWorkshopEnumerationTypeFavoritesOfFriends = 3,\n\t\tk_EWorkshopEnumerationTypeVotedByFriends = 4,\n\t\tk_EWorkshopEnumerationTypeContentByFriends = 5,\n\t\tk_EWorkshopEnumerationTypeRecentFromFollowedUsers = 6,\n\t}\n\n\tpublic enum EWorkshopVideoProvider : int {\n\t\tk_EWorkshopVideoProviderNone = 0,\n\t\tk_EWorkshopVideoProviderYoutube = 1\n\t}\n\n\tpublic enum EUGCReadAction : int {\n\t\t// Keeps the file handle open unless the last byte is read.  You can use this when reading large files (over 100MB) in sequential chunks.\n\t\t// If the last byte is read, this will behave the same as k_EUGCRead_Close.  Otherwise, it behaves the same as k_EUGCRead_ContinueReading.\n\t\t// This value maintains the same behavior as before the EUGCReadAction parameter was introduced.\n\t\tk_EUGCRead_ContinueReadingUntilFinished = 0,\n\n\t\t// Keeps the file handle open.  Use this when using UGCRead to seek to different parts of the file.\n\t\t// When you are done seeking around the file, make a final call with k_EUGCRead_Close to close it.\n\t\tk_EUGCRead_ContinueReading = 1,\n\n\t\t// Frees the file handle.  Use this when you're done reading the content.\n\t\t// To read the file from Steam again you will need to call UGCDownload again.\n\t\tk_EUGCRead_Close = 2,\n\t}\n\n\tpublic enum EVRScreenshotType : int {\n\t\tk_EVRScreenshotType_None\t\t\t= 0,\n\t\tk_EVRScreenshotType_Mono\t\t\t= 1,\n\t\tk_EVRScreenshotType_Stereo\t\t\t= 2,\n\t\tk_EVRScreenshotType_MonoCubemap\t\t= 3,\n\t\tk_EVRScreenshotType_MonoPanorama\t= 4,\n\t\tk_EVRScreenshotType_StereoPanorama\t= 5\n\t}\n\n\t// Matching UGC types for queries\n\tpublic enum EUGCMatchingUGCType : int {\n\t\tk_EUGCMatchingUGCType_Items\t\t\t\t = 0,\t\t// both mtx items and ready-to-use items\n\t\tk_EUGCMatchingUGCType_Items_Mtx\t\t\t = 1,\n\t\tk_EUGCMatchingUGCType_Items_ReadyToUse\t = 2,\n\t\tk_EUGCMatchingUGCType_Collections\t\t = 3,\n\t\tk_EUGCMatchingUGCType_Artwork\t\t\t = 4,\n\t\tk_EUGCMatchingUGCType_Videos\t\t\t = 5,\n\t\tk_EUGCMatchingUGCType_Screenshots\t\t = 6,\n\t\tk_EUGCMatchingUGCType_AllGuides\t\t\t = 7,\t\t// both web guides and integrated guides\n\t\tk_EUGCMatchingUGCType_WebGuides\t\t\t = 8,\n\t\tk_EUGCMatchingUGCType_IntegratedGuides\t = 9,\n\t\tk_EUGCMatchingUGCType_UsableInGame\t\t = 10,\t\t// ready-to-use items and integrated guides\n\t\tk_EUGCMatchingUGCType_ControllerBindings = 11,\n\t\tk_EUGCMatchingUGCType_GameManagedItems\t = 12,\t\t// game managed items (not managed by users)\n\t\tk_EUGCMatchingUGCType_All\t\t\t\t = ~0,\t\t// return everything\n\t}\n\n\t// Different lists of published UGC for a user.\n\t// If the current logged in user is different than the specified user, then some options may not be allowed.\n\tpublic enum EUserUGCList : int {\n\t\tk_EUserUGCList_Published,\n\t\tk_EUserUGCList_VotedOn,\n\t\tk_EUserUGCList_VotedUp,\n\t\tk_EUserUGCList_VotedDown,\n\t\tk_EUserUGCList_WillVoteLater,\n\t\tk_EUserUGCList_Favorited,\n\t\tk_EUserUGCList_Subscribed,\n\t\tk_EUserUGCList_UsedOrPlayed,\n\t\tk_EUserUGCList_Followed,\n\t}\n\n\t// Sort order for user published UGC lists (defaults to creation order descending)\n\tpublic enum EUserUGCListSortOrder : int {\n\t\tk_EUserUGCListSortOrder_CreationOrderDesc,\n\t\tk_EUserUGCListSortOrder_CreationOrderAsc,\n\t\tk_EUserUGCListSortOrder_TitleAsc,\n\t\tk_EUserUGCListSortOrder_LastUpdatedDesc,\n\t\tk_EUserUGCListSortOrder_SubscriptionDateDesc,\n\t\tk_EUserUGCListSortOrder_VoteScoreDesc,\n\t\tk_EUserUGCListSortOrder_ForModeration,\n\t}\n\n\t// Combination of sorting and filtering for queries across all UGC\n\tpublic enum EUGCQuery : int {\n\t\tk_EUGCQuery_RankedByVote\t\t\t\t\t\t\t\t  = 0,\n\t\tk_EUGCQuery_RankedByPublicationDate\t\t\t\t\t\t  = 1,\n\t\tk_EUGCQuery_AcceptedForGameRankedByAcceptanceDate\t\t  = 2,\n\t\tk_EUGCQuery_RankedByTrend\t\t\t\t\t\t\t\t  = 3,\n\t\tk_EUGCQuery_FavoritedByFriendsRankedByPublicationDate\t  = 4,\n\t\tk_EUGCQuery_CreatedByFriendsRankedByPublicationDate\t\t  = 5,\n\t\tk_EUGCQuery_RankedByNumTimesReported\t\t\t\t\t  = 6,\n\t\tk_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate = 7,\n\t\tk_EUGCQuery_NotYetRated\t\t\t\t\t\t\t\t\t  = 8,\n\t\tk_EUGCQuery_RankedByTotalVotesAsc\t\t\t\t\t\t  = 9,\n\t\tk_EUGCQuery_RankedByVotesUp\t\t\t\t\t\t\t\t  = 10,\n\t\tk_EUGCQuery_RankedByTextSearch\t\t\t\t\t\t\t  = 11,\n\t\tk_EUGCQuery_RankedByTotalUniqueSubscriptions\t\t\t  = 12,\n\t\tk_EUGCQuery_RankedByPlaytimeTrend\t\t\t\t\t\t  = 13,\n\t\tk_EUGCQuery_RankedByTotalPlaytime\t\t\t\t\t\t  = 14,\n\t\tk_EUGCQuery_RankedByAveragePlaytimeTrend\t\t\t\t  = 15,\n\t\tk_EUGCQuery_RankedByLifetimeAveragePlaytime\t\t\t\t  = 16,\n\t\tk_EUGCQuery_RankedByPlaytimeSessionsTrend\t\t\t\t  = 17,\n\t\tk_EUGCQuery_RankedByLifetimePlaytimeSessions\t\t\t  = 18,\n\t}\n\n\tpublic enum EItemUpdateStatus : int {\n\t\tk_EItemUpdateStatusInvalid \t\t\t\t= 0, // The item update handle was invalid, job might be finished, listen too SubmitItemUpdateResult_t\n\t\tk_EItemUpdateStatusPreparingConfig \t\t= 1, // The item update is processing configuration data\n\t\tk_EItemUpdateStatusPreparingContent\t\t= 2, // The item update is reading and processing content files\n\t\tk_EItemUpdateStatusUploadingContent\t\t= 3, // The item update is uploading content changes to Steam\n\t\tk_EItemUpdateStatusUploadingPreviewFile\t= 4, // The item update is uploading new preview file image\n\t\tk_EItemUpdateStatusCommittingChanges\t= 5  // The item update is committing all changes\n\t}\n\n\t[Flags]\n\tpublic enum EItemState : int {\n\t\tk_EItemStateNone\t\t\t= 0,\t// item not tracked on client\n\t\tk_EItemStateSubscribed\t\t= 1,\t// current user is subscribed to this item. Not just cached.\n\t\tk_EItemStateLegacyItem\t\t= 2,\t// item was created with ISteamRemoteStorage\n\t\tk_EItemStateInstalled\t\t= 4,\t// item is installed and usable (but maybe out of date)\n\t\tk_EItemStateNeedsUpdate\t\t= 8,\t// items needs an update. Either because it's not installed yet or creator updated content\n\t\tk_EItemStateDownloading\t\t= 16,\t// item update is currently downloading\n\t\tk_EItemStateDownloadPending\t= 32,\t// DownloadItem() was called for this item, content isn't available until DownloadItemResult_t is fired\n\t}\n\n\tpublic enum EItemStatistic : int {\n\t\tk_EItemStatistic_NumSubscriptions\t\t\t\t\t = 0,\n\t\tk_EItemStatistic_NumFavorites\t\t\t\t\t\t = 1,\n\t\tk_EItemStatistic_NumFollowers\t\t\t\t\t\t = 2,\n\t\tk_EItemStatistic_NumUniqueSubscriptions\t\t\t\t = 3,\n\t\tk_EItemStatistic_NumUniqueFavorites\t\t\t\t\t = 4,\n\t\tk_EItemStatistic_NumUniqueFollowers\t\t\t\t\t = 5,\n\t\tk_EItemStatistic_NumUniqueWebsiteViews\t\t\t\t = 6,\n\t\tk_EItemStatistic_ReportScore\t\t\t\t\t\t = 7,\n\t\tk_EItemStatistic_NumSecondsPlayed\t\t\t\t\t = 8,\n\t\tk_EItemStatistic_NumPlaytimeSessions\t\t\t\t = 9,\n\t\tk_EItemStatistic_NumComments\t\t\t\t\t\t = 10,\n\t\tk_EItemStatistic_NumSecondsPlayedDuringTimePeriod\t = 11,\n\t\tk_EItemStatistic_NumPlaytimeSessionsDuringTimePeriod = 12,\n\t}\n\n\tpublic enum EItemPreviewType : int {\n\t\tk_EItemPreviewType_Image\t\t\t\t\t\t\t= 0,\t// standard image file expected (e.g. jpg, png, gif, etc.)\n\t\tk_EItemPreviewType_YouTubeVideo\t\t\t\t\t\t= 1,\t// video id is stored\n\t\tk_EItemPreviewType_Sketchfab\t\t\t\t\t\t= 2,\t// model id is stored\n\t\tk_EItemPreviewType_EnvironmentMap_HorizontalCross\t= 3,\t// standard image file expected - cube map in the layout\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// +---+---+-------+\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// |   |Up |       |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// +---+---+---+---+\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// | L | F | R | B |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// +---+---+---+---+\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// |   |Dn |       |\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// +---+---+---+---+\n\t\tk_EItemPreviewType_EnvironmentMap_LatLong\t\t\t= 4,\t// standard image file expected\n\t\tk_EItemPreviewType_ReservedMax\t\t\t\t\t\t= 255,\t// you can specify your own types above this value\n\t}\n\n\tpublic enum EFailureType : int {\n\t\tk_EFailureFlushedCallbackQueue,\n\t\tk_EFailurePipeFail,\n\t}\n\n\t// type of data request, when downloading leaderboard entries\n\tpublic enum ELeaderboardDataRequest : int {\n\t\tk_ELeaderboardDataRequestGlobal = 0,\n\t\tk_ELeaderboardDataRequestGlobalAroundUser = 1,\n\t\tk_ELeaderboardDataRequestFriends = 2,\n\t\tk_ELeaderboardDataRequestUsers = 3\n\t}\n\n\t// the sort order of a leaderboard\n\tpublic enum ELeaderboardSortMethod : int {\n\t\tk_ELeaderboardSortMethodNone = 0,\n\t\tk_ELeaderboardSortMethodAscending = 1,\t// top-score is lowest number\n\t\tk_ELeaderboardSortMethodDescending = 2,\t// top-score is highest number\n\t}\n\n\t// the display type (used by the Steam Community web site) for a leaderboard\n\tpublic enum ELeaderboardDisplayType : int {\n\t\tk_ELeaderboardDisplayTypeNone = 0,\n\t\tk_ELeaderboardDisplayTypeNumeric = 1,\t\t\t// simple numerical score\n\t\tk_ELeaderboardDisplayTypeTimeSeconds = 2,\t\t// the score represents a time, in seconds\n\t\tk_ELeaderboardDisplayTypeTimeMilliSeconds = 3,\t// the score represents a time, in milliseconds\n\t}\n\n\tpublic enum ELeaderboardUploadScoreMethod : int {\n\t\tk_ELeaderboardUploadScoreMethodNone = 0,\n\t\tk_ELeaderboardUploadScoreMethodKeepBest = 1,\t// Leaderboard will keep user's best score\n\t\tk_ELeaderboardUploadScoreMethodForceUpdate = 2,\t// Leaderboard will always replace score with specified\n\t}\n\n\t// Steam API call failure results\n\tpublic enum ESteamAPICallFailure : int {\n\t\tk_ESteamAPICallFailureNone = -1,\t\t\t// no failure\n\t\tk_ESteamAPICallFailureSteamGone = 0,\t\t// the local Steam process has gone away\n\t\tk_ESteamAPICallFailureNetworkFailure = 1,\t// the network connection to Steam has been broken, or was already broken\n\t\t// SteamServersDisconnected_t callback will be sent around the same time\n\t\t// SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again\n\t\tk_ESteamAPICallFailureInvalidHandle = 2,\t// the SteamAPICall_t handle passed in no longer exists\n\t\tk_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call\n\t}\n\n\t// Input modes for the Big Picture gamepad text entry\n\tpublic enum EGamepadTextInputMode : int {\n\t\tk_EGamepadTextInputModeNormal = 0,\n\t\tk_EGamepadTextInputModePassword = 1\n\t}\n\n\t// Controls number of allowed lines for the Big Picture gamepad text entry\n\tpublic enum EGamepadTextInputLineMode : int {\n\t\tk_EGamepadTextInputLineModeSingleLine = 0,\n\t\tk_EGamepadTextInputLineModeMultipleLines = 1\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// results for CheckFileSignature\n\t//-----------------------------------------------------------------------------\n\tpublic enum ECheckFileSignature : int {\n\t\tk_ECheckFileSignatureInvalidSignature = 0,\n\t\tk_ECheckFileSignatureValidSignature = 1,\n\t\tk_ECheckFileSignatureFileNotFound = 2,\n\t\tk_ECheckFileSignatureNoSignaturesFoundForThisApp = 3,\n\t\tk_ECheckFileSignatureNoSignaturesFoundForThisFile = 4,\n\t}\n\n\tpublic enum EMatchMakingServerResponse : int {\n\t\teServerResponded = 0,\n\t\teServerFailedToRespond,\n\t\teNoServersListedOnMasterServer // for the Internet query type, returned in response callback if no servers of this type match\n\t}\n\n\tpublic enum EServerMode : int {\n\t\teServerModeInvalid = 0, // DO NOT USE\n\t\teServerModeNoAuthentication = 1, // Don't authenticate user logins and don't list on the server list\n\t\teServerModeAuthentication = 2, // Authenticate users, list on the server list, don't run VAC on clients that connect\n\t\teServerModeAuthenticationAndSecure = 3, // Authenticate users, list on the server list and VAC protect clients\n\t}\n\n\t// General result codes\n\tpublic enum EResult : int {\n\t\tk_EResultOK\t= 1,\t\t\t\t\t\t\t// success\n\t\tk_EResultFail = 2,\t\t\t\t\t\t\t// generic failure\n\t\tk_EResultNoConnection = 3,\t\t\t\t\t// no/failed network connection\n\t//\tk_EResultNoConnectionRetry = 4,\t\t\t\t// OBSOLETE - removed\n\t\tk_EResultInvalidPassword = 5,\t\t\t\t// password/ticket is invalid\n\t\tk_EResultLoggedInElsewhere = 6,\t\t\t\t// same user logged in elsewhere\n\t\tk_EResultInvalidProtocolVer = 7,\t\t\t// protocol version is incorrect\n\t\tk_EResultInvalidParam = 8,\t\t\t\t\t// a parameter is incorrect\n\t\tk_EResultFileNotFound = 9,\t\t\t\t\t// file was not found\n\t\tk_EResultBusy = 10,\t\t\t\t\t\t\t// called method busy - action not taken\n\t\tk_EResultInvalidState = 11,\t\t\t\t\t// called object was in an invalid state\n\t\tk_EResultInvalidName = 12,\t\t\t\t\t// name is invalid\n\t\tk_EResultInvalidEmail = 13,\t\t\t\t\t// email is invalid\n\t\tk_EResultDuplicateName = 14,\t\t\t\t// name is not unique\n\t\tk_EResultAccessDenied = 15,\t\t\t\t\t// access is denied\n\t\tk_EResultTimeout = 16,\t\t\t\t\t\t// operation timed out\n\t\tk_EResultBanned = 17,\t\t\t\t\t\t// VAC2 banned\n\t\tk_EResultAccountNotFound = 18,\t\t\t\t// account not found\n\t\tk_EResultInvalidSteamID = 19,\t\t\t\t// steamID is invalid\n\t\tk_EResultServiceUnavailable = 20,\t\t\t// The requested service is currently unavailable\n\t\tk_EResultNotLoggedOn = 21,\t\t\t\t\t// The user is not logged on\n\t\tk_EResultPending = 22,\t\t\t\t\t\t// Request is pending (may be in process, or waiting on third party)\n\t\tk_EResultEncryptionFailure = 23,\t\t\t// Encryption or Decryption failed\n\t\tk_EResultInsufficientPrivilege = 24,\t\t// Insufficient privilege\n\t\tk_EResultLimitExceeded = 25,\t\t\t\t// Too much of a good thing\n\t\tk_EResultRevoked = 26,\t\t\t\t\t\t// Access has been revoked (used for revoked guest passes)\n\t\tk_EResultExpired = 27,\t\t\t\t\t\t// License/Guest pass the user is trying to access is expired\n\t\tk_EResultAlreadyRedeemed = 28,\t\t\t\t// Guest pass has already been redeemed by account, cannot be acked again\n\t\tk_EResultDuplicateRequest = 29,\t\t\t\t// The request is a duplicate and the action has already occurred in the past, ignored this time\n\t\tk_EResultAlreadyOwned = 30,\t\t\t\t\t// All the games in this guest pass redemption request are already owned by the user\n\t\tk_EResultIPNotFound = 31,\t\t\t\t\t// IP address not found\n\t\tk_EResultPersistFailed = 32,\t\t\t\t// failed to write change to the data store\n\t\tk_EResultLockingFailed = 33,\t\t\t\t// failed to acquire access lock for this operation\n\t\tk_EResultLogonSessionReplaced = 34,\n\t\tk_EResultConnectFailed = 35,\n\t\tk_EResultHandshakeFailed = 36,\n\t\tk_EResultIOFailure = 37,\n\t\tk_EResultRemoteDisconnect = 38,\n\t\tk_EResultShoppingCartNotFound = 39,\t\t\t// failed to find the shopping cart requested\n\t\tk_EResultBlocked = 40,\t\t\t\t\t\t// a user didn't allow it\n\t\tk_EResultIgnored = 41,\t\t\t\t\t\t// target is ignoring sender\n\t\tk_EResultNoMatch = 42,\t\t\t\t\t\t// nothing matching the request found\n\t\tk_EResultAccountDisabled = 43,\n\t\tk_EResultServiceReadOnly = 44,\t\t\t\t// this service is not accepting content changes right now\n\t\tk_EResultAccountNotFeatured = 45,\t\t\t// account doesn't have value, so this feature isn't available\n\t\tk_EResultAdministratorOK = 46,\t\t\t\t// allowed to take this action, but only because requester is admin\n\t\tk_EResultContentVersion = 47,\t\t\t\t// A Version mismatch in content transmitted within the Steam protocol.\n\t\tk_EResultTryAnotherCM = 48,\t\t\t\t\t// The current CM can't service the user making a request, user should try another.\n\t\tk_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.\n\t\tk_EResultAlreadyLoggedInElsewhere = 50,\t\t// You are already logged in elsewhere, you must wait\n\t\tk_EResultSuspended = 51,\t\t\t\t\t// Long running operation (content download) suspended/paused\n\t\tk_EResultCancelled = 52,\t\t\t\t\t// Operation canceled (typically by user: content download)\n\t\tk_EResultDataCorruption = 53,\t\t\t\t// Operation canceled because data is ill formed or unrecoverable\n\t\tk_EResultDiskFull = 54,\t\t\t\t\t\t// Operation canceled - not enough disk space.\n\t\tk_EResultRemoteCallFailed = 55,\t\t\t\t// an remote call or IPC call failed\n\t\tk_EResultPasswordUnset = 56,\t\t\t\t// Password could not be verified as it's unset server side\n\t\tk_EResultExternalAccountUnlinked = 57,\t\t// External account (PSN, Facebook...) is not linked to a Steam account\n\t\tk_EResultPSNTicketInvalid = 58,\t\t\t\t// PSN ticket was invalid\n\t\tk_EResultExternalAccountAlreadyLinked = 59,\t// External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first\n\t\tk_EResultRemoteFileConflict = 60,\t\t\t// The sync cannot resume due to a conflict between the local and remote files\n\t\tk_EResultIllegalPassword = 61,\t\t\t\t// The requested new password is not legal\n\t\tk_EResultSameAsPreviousValue = 62,\t\t\t// new value is the same as the old one ( secret question and answer )\n\t\tk_EResultAccountLogonDenied = 63,\t\t\t// account login denied due to 2nd factor authentication failure\n\t\tk_EResultCannotUseOldPassword = 64,\t\t\t// The requested new password is not legal\n\t\tk_EResultInvalidLoginAuthCode = 65,\t\t\t// account login denied due to auth code invalid\n\t\tk_EResultAccountLogonDeniedNoMail = 66,\t\t// account login denied due to 2nd factor auth failure - and no mail has been sent\n\t\tk_EResultHardwareNotCapableOfIPT = 67,\t\t//\n\t\tk_EResultIPTInitError = 68,\t\t\t\t\t//\n\t\tk_EResultParentalControlRestricted = 69,\t// operation failed due to parental control restrictions for current user\n\t\tk_EResultFacebookQueryError = 70,\t\t\t// Facebook query returned an error\n\t\tk_EResultExpiredLoginAuthCode = 71,\t\t\t// account login denied due to auth code expired\n\t\tk_EResultIPLoginRestrictionFailed = 72,\n\t\tk_EResultAccountLockedDown = 73,\n\t\tk_EResultAccountLogonDeniedVerifiedEmailRequired = 74,\n\t\tk_EResultNoMatchingURL = 75,\n\t\tk_EResultBadResponse = 76,\t\t\t\t\t// parse failure, missing field, etc.\n\t\tk_EResultRequirePasswordReEntry = 77,\t\t// The user cannot complete the action until they re-enter their password\n\t\tk_EResultValueOutOfRange = 78,\t\t\t\t// the value entered is outside the acceptable range\n\t\tk_EResultUnexpectedError = 79,\t\t\t\t// something happened that we didn't expect to ever happen\n\t\tk_EResultDisabled = 80,\t\t\t\t\t\t// The requested service has been configured to be unavailable\n\t\tk_EResultInvalidCEGSubmission = 81,\t\t\t// The set of files submitted to the CEG server are not valid !\n\t\tk_EResultRestrictedDevice = 82,\t\t\t\t// The device being used is not allowed to perform this action\n\t\tk_EResultRegionLocked = 83,\t\t\t\t\t// The action could not be complete because it is region restricted\n\t\tk_EResultRateLimitExceeded = 84,\t\t\t// Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent\n\t\tk_EResultAccountLoginDeniedNeedTwoFactor = 85,\t// Need two-factor code to login\n\t\tk_EResultItemDeleted = 86,\t\t\t\t\t// The thing we're trying to access has been deleted\n\t\tk_EResultAccountLoginDeniedThrottle = 87,\t// login attempt failed, try to throttle response to possible attacker\n\t\tk_EResultTwoFactorCodeMismatch = 88,\t\t// two factor code mismatch\n\t\tk_EResultTwoFactorActivationCodeMismatch = 89,\t// activation code for two-factor didn't match\n\t\tk_EResultAccountAssociatedToMultiplePartners = 90,\t// account has been associated with multiple partners\n\t\tk_EResultNotModified = 91,\t\t\t\t\t// data not modified\n\t\tk_EResultNoMobileDevice = 92,\t\t\t\t// the account does not have a mobile device associated with it\n\t\tk_EResultTimeNotSynced = 93,\t\t\t\t// the time presented is out of range or tolerance\n\t\tk_EResultSmsCodeFailed = 94,\t\t\t\t// SMS code failure (no match, none pending, etc.)\n\t\tk_EResultAccountLimitExceeded = 95,\t\t\t// Too many accounts access this resource\n\t\tk_EResultAccountActivityLimitExceeded = 96,\t// Too many changes to this account\n\t\tk_EResultPhoneActivityLimitExceeded = 97,\t// Too many changes to this phone\n\t\tk_EResultRefundToWallet = 98,\t\t\t\t// Cannot refund to payment method, must use wallet\n\t\tk_EResultEmailSendFailure = 99,\t\t\t\t// Cannot send an email\n\t\tk_EResultNotSettled = 100,\t\t\t\t\t// Can't perform operation till payment has settled\n\t\tk_EResultNeedCaptcha = 101,\t\t\t\t\t// Needs to provide a valid captcha\n\t\tk_EResultGSLTDenied = 102,\t\t\t\t\t// a game server login token owned by this token's owner has been banned\n\t\tk_EResultGSOwnerDenied = 103,\t\t\t\t// game server owner is denied for other reason (account lock, community ban, vac ban, missing phone)\n\t\tk_EResultInvalidItemType = 104,\t\t\t\t// the type of thing we were requested to act on is invalid\n\t\tk_EResultIPBanned = 105,\t\t\t\t\t// the ip address has been banned from taking this action\n\t\tk_EResultGSLTExpired = 106,\t\t\t\t\t// this token has expired from disuse; can be reset for use\n\t\tk_EResultInsufficientFunds = 107,\t\t\t// user doesn't have enough wallet funds to complete the action\n\t\tk_EResultTooManyPending = 108,\t\t\t\t// There are too many of this thing pending already\n\t\tk_EResultNoSiteLicensesFound = 109,\t\t\t// No site licenses found\n\t\tk_EResultWGNetworkSendExceeded = 110,\t\t// the WG couldn't send a response because we exceeded max network send size\n\t\tk_EResultAccountNotFriends = 111,\t\t\t// the user is not mutually friends\n\t\tk_EResultLimitedUserAccount = 112,\t\t\t// the user is limited\n\t\tk_EResultCantRemoveItem = 113,\t\t\t\t// item can't be removed\n\t}\n\n\t// Error codes for use with the voice functions\n\tpublic enum EVoiceResult : int {\n\t\tk_EVoiceResultOK = 0,\n\t\tk_EVoiceResultNotInitialized = 1,\n\t\tk_EVoiceResultNotRecording = 2,\n\t\tk_EVoiceResultNoData = 3,\n\t\tk_EVoiceResultBufferTooSmall = 4,\n\t\tk_EVoiceResultDataCorrupted = 5,\n\t\tk_EVoiceResultRestricted = 6,\n\t\tk_EVoiceResultUnsupportedCodec = 7,\n\t\tk_EVoiceResultReceiverOutOfDate = 8,\n\t\tk_EVoiceResultReceiverDidNotAnswer = 9,\n\n\t}\n\n\t// Result codes to GSHandleClientDeny/Kick\n\tpublic enum EDenyReason : int {\n\t\tk_EDenyInvalid = 0,\n\t\tk_EDenyInvalidVersion = 1,\n\t\tk_EDenyGeneric = 2,\n\t\tk_EDenyNotLoggedOn = 3,\n\t\tk_EDenyNoLicense = 4,\n\t\tk_EDenyCheater = 5,\n\t\tk_EDenyLoggedInElseWhere = 6,\n\t\tk_EDenyUnknownText = 7,\n\t\tk_EDenyIncompatibleAnticheat = 8,\n\t\tk_EDenyMemoryCorruption = 9,\n\t\tk_EDenyIncompatibleSoftware = 10,\n\t\tk_EDenySteamConnectionLost = 11,\n\t\tk_EDenySteamConnectionError = 12,\n\t\tk_EDenySteamResponseTimedOut = 13,\n\t\tk_EDenySteamValidationStalled = 14,\n\t\tk_EDenySteamOwnerLeftGuestUser = 15,\n\t}\n\n\t// results from BeginAuthSession\n\tpublic enum EBeginAuthSessionResult : int {\n\t\tk_EBeginAuthSessionResultOK = 0,\t\t\t\t\t\t// Ticket is valid for this game and this steamID.\n\t\tk_EBeginAuthSessionResultInvalidTicket = 1,\t\t\t\t// Ticket is not valid.\n\t\tk_EBeginAuthSessionResultDuplicateRequest = 2,\t\t\t// A ticket has already been submitted for this steamID\n\t\tk_EBeginAuthSessionResultInvalidVersion = 3,\t\t\t// Ticket is from an incompatible interface version\n\t\tk_EBeginAuthSessionResultGameMismatch = 4,\t\t\t\t// Ticket is not for this game\n\t\tk_EBeginAuthSessionResultExpiredTicket = 5,\t\t\t\t// Ticket has expired\n\t}\n\n\t// Callback values for callback ValidateAuthTicketResponse_t which is a response to BeginAuthSession\n\tpublic enum EAuthSessionResponse : int {\n\t\tk_EAuthSessionResponseOK = 0,\t\t\t\t\t\t\t// Steam has verified the user is online, the ticket is valid and ticket has not been reused.\n\t\tk_EAuthSessionResponseUserNotConnectedToSteam = 1,\t\t// The user in question is not connected to steam\n\t\tk_EAuthSessionResponseNoLicenseOrExpired = 2,\t\t\t// The license has expired.\n\t\tk_EAuthSessionResponseVACBanned = 3,\t\t\t\t\t// The user is VAC banned for this game.\n\t\tk_EAuthSessionResponseLoggedInElseWhere = 4,\t\t\t// The user account has logged in elsewhere and the session containing the game instance has been disconnected.\n\t\tk_EAuthSessionResponseVACCheckTimedOut = 5,\t\t\t\t// VAC has been unable to perform anti-cheat checks on this user\n\t\tk_EAuthSessionResponseAuthTicketCanceled = 6,\t\t\t// The ticket has been canceled by the issuer\n\t\tk_EAuthSessionResponseAuthTicketInvalidAlreadyUsed = 7,\t// This ticket has already been used, it is not valid.\n\t\tk_EAuthSessionResponseAuthTicketInvalid = 8,\t\t\t// This ticket is not from a user instance currently connected to steam.\n\t\tk_EAuthSessionResponsePublisherIssuedBan = 9,\t\t\t// The user is banned for this game. The ban came via the web api and not VAC\n\t}\n\n\t// results from UserHasLicenseForApp\n\tpublic enum EUserHasLicenseForAppResult : int {\n\t\tk_EUserHasLicenseResultHasLicense = 0,\t\t\t\t\t// User has a license for specified app\n\t\tk_EUserHasLicenseResultDoesNotHaveLicense = 1,\t\t\t// User does not have a license for the specified app\n\t\tk_EUserHasLicenseResultNoAuth = 2,\t\t\t\t\t\t// User has not been authenticated\n\t}\n\n\t// Steam account types\n\tpublic enum EAccountType : int {\n\t\tk_EAccountTypeInvalid = 0,\n\t\tk_EAccountTypeIndividual = 1,\t\t// single user account\n\t\tk_EAccountTypeMultiseat = 2,\t\t// multiseat (e.g. cybercafe) account\n\t\tk_EAccountTypeGameServer = 3,\t\t// game server account\n\t\tk_EAccountTypeAnonGameServer = 4,\t// anonymous game server account\n\t\tk_EAccountTypePending = 5,\t\t\t// pending\n\t\tk_EAccountTypeContentServer = 6,\t// content server\n\t\tk_EAccountTypeClan = 7,\n\t\tk_EAccountTypeChat = 8,\n\t\tk_EAccountTypeConsoleUser = 9,\t\t// Fake SteamID for local PSN account on PS3 or Live account on 360, etc.\n\t\tk_EAccountTypeAnonUser = 10,\n\n\t\t// Max of 16 items in this field\n\t\tk_EAccountTypeMax\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose:\n\t//-----------------------------------------------------------------------------\n\tpublic enum EAppReleaseState : int {\n\t\tk_EAppReleaseState_Unknown\t\t\t= 0,\t// unknown, required appinfo or license info is missing\n\t\tk_EAppReleaseState_Unavailable\t\t= 1,\t// even if user 'just' owns it, can see game at all\n\t\tk_EAppReleaseState_Prerelease\t\t= 2,\t// can be purchased and is visible in games list, nothing else. Common appInfo section released\n\t\tk_EAppReleaseState_PreloadOnly\t\t= 3,\t// owners can preload app, not play it. AppInfo fully released.\n\t\tk_EAppReleaseState_Released\t\t\t= 4,\t// owners can download and play app.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose:\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EAppOwnershipFlags : int {\n\t\tk_EAppOwnershipFlags_None\t\t\t\t= 0x0000,\t// unknown\n\t\tk_EAppOwnershipFlags_OwnsLicense\t\t= 0x0001,\t// owns license for this game\n\t\tk_EAppOwnershipFlags_FreeLicense\t\t= 0x0002,\t// not paid for game\n\t\tk_EAppOwnershipFlags_RegionRestricted\t= 0x0004,\t// owns app, but not allowed to play in current region\n\t\tk_EAppOwnershipFlags_LowViolence\t\t= 0x0008,\t// only low violence version\n\t\tk_EAppOwnershipFlags_InvalidPlatform\t= 0x0010,\t// app not supported on current platform\n\t\tk_EAppOwnershipFlags_SharedLicense\t\t= 0x0020,\t// license was granted by authorized local device\n\t\tk_EAppOwnershipFlags_FreeWeekend\t\t= 0x0040,\t// owned by a free weekend licenses\n\t\tk_EAppOwnershipFlags_RetailLicense\t\t= 0x0080,\t// has a retail license for game, (CD-Key etc)\n\t\tk_EAppOwnershipFlags_LicenseLocked\t\t= 0x0100,\t// shared license is locked (in use) by other user\n\t\tk_EAppOwnershipFlags_LicensePending\t\t= 0x0200,\t// owns app, but transaction is still pending. Can't install or play\n\t\tk_EAppOwnershipFlags_LicenseExpired\t\t= 0x0400,\t// doesn't own app anymore since license expired\n\t\tk_EAppOwnershipFlags_LicensePermanent\t= 0x0800,\t// permanent license, not borrowed, or guest or freeweekend etc\n\t\tk_EAppOwnershipFlags_LicenseRecurring\t= 0x1000,\t// Recurring license, user is charged periodically\n\t\tk_EAppOwnershipFlags_LicenseCanceled\t= 0x2000,\t// Mark as canceled, but might be still active if recurring\n\t\tk_EAppOwnershipFlags_AutoGrant\t\t\t= 0x4000,\t// Ownership is based on any kind of autogrant license\n\t\tk_EAppOwnershipFlags_PendingGift\t\t= 0x8000,\t// user has pending gift to redeem\n\t\tk_EAppOwnershipFlags_RentalNotActivated\t= 0x10000,\t// Rental hasn't been activated yet\n\t\tk_EAppOwnershipFlags_Rental\t\t\t\t= 0x20000,\t// Is a rental\n\t\tk_EAppOwnershipFlags_SiteLicense\t\t= 0x40000,\t// Is from a site license\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: designed as flags to allow filters masks\n\t// NOTE: If you add to this, please update PackageAppType (SteamConfig) as well as populatePackageAppType\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EAppType : int {\n\t\tk_EAppType_Invalid\t\t\t\t= 0x000,\t// unknown / invalid\n\t\tk_EAppType_Game\t\t\t\t\t= 0x001,\t// playable game, default type\n\t\tk_EAppType_Application\t\t\t= 0x002,\t// software application\n\t\tk_EAppType_Tool\t\t\t\t\t= 0x004,\t// SDKs, editors & dedicated servers\n\t\tk_EAppType_Demo\t\t\t\t\t= 0x008,\t// game demo\n\t\tk_EAppType_Media_DEPRECATED\t\t= 0x010,\t// legacy - was used for game trailers, which are now just videos on the web\n\t\tk_EAppType_DLC\t\t\t\t\t= 0x020,\t// down loadable content\n\t\tk_EAppType_Guide\t\t\t\t= 0x040,\t// game guide, PDF etc\n\t\tk_EAppType_Driver\t\t\t\t= 0x080,\t// hardware driver updater (ATI, Razor etc)\n\t\tk_EAppType_Config\t\t\t\t= 0x100,\t// hidden app used to config Steam features (backpack, sales, etc)\n\t\tk_EAppType_Hardware\t\t\t\t= 0x200,\t// a hardware device (Steam Machine, Steam Controller, Steam Link, etc.)\n\t\tk_EAppType_Franchise\t\t\t= 0x400,\t// A hub for collections of multiple apps, eg films, series, games\n\t\tk_EAppType_Video\t\t\t\t= 0x800,\t// A video component of either a Film or TVSeries (may be the feature, an episode, preview, making-of, etc)\n\t\tk_EAppType_Plugin\t\t\t\t= 0x1000,\t// Plug-in types for other Apps\n\t\tk_EAppType_Music\t\t\t\t= 0x2000,\t// Music files\n\t\tk_EAppType_Series\t\t\t\t= 0x4000,\t// Container app for video series\n\t\tk_EAppType_Comic\t\t\t\t= 0x8000,\t// Comic Book\n\t\tk_EAppType_Beta\t\t\t\t\t= 0x10000,\t// this is a beta version of a game\n\n\t\tk_EAppType_Shortcut\t\t\t\t= 0x40000000,\t// just a shortcut, client side only\n\t\tk_EAppType_DepotOnly\t\t\t= -2147483647,\t// placeholder since depots and apps share the same namespace\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// types of user game stats fields\n\t// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN DATABASE\n\t//-----------------------------------------------------------------------------\n\tpublic enum ESteamUserStatType : int {\n\t\tk_ESteamUserStatTypeINVALID = 0,\n\t\tk_ESteamUserStatTypeINT = 1,\n\t\tk_ESteamUserStatTypeFLOAT = 2,\n\t\t// Read as FLOAT, set with count / session length\n\t\tk_ESteamUserStatTypeAVGRATE = 3,\n\t\tk_ESteamUserStatTypeACHIEVEMENTS = 4,\n\t\tk_ESteamUserStatTypeGROUPACHIEVEMENTS = 5,\n\n\t\t// max, for sanity checks\n\t\tk_ESteamUserStatTypeMAX\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Chat Entry Types (previously was only friend-to-friend message types)\n\t//-----------------------------------------------------------------------------\n\tpublic enum EChatEntryType : int {\n\t\tk_EChatEntryTypeInvalid = 0,\n\t\tk_EChatEntryTypeChatMsg = 1,\t\t// Normal text message from another user\n\t\tk_EChatEntryTypeTyping = 2,\t\t\t// Another user is typing (not used in multi-user chat)\n\t\tk_EChatEntryTypeInviteGame = 3,\t\t// Invite from other user into that users current game\n\t\tk_EChatEntryTypeEmote = 4,\t\t\t// text emote message (deprecated, should be treated as ChatMsg)\n\t\t//k_EChatEntryTypeLobbyGameStart = 5,\t// lobby game is starting (dead - listen for LobbyGameCreated_t callback instead)\n\t\tk_EChatEntryTypeLeftConversation = 6, // user has left the conversation ( closed chat window )\n\t\t// Above are previous FriendMsgType entries, now merged into more generic chat entry types\n\t\tk_EChatEntryTypeEntered = 7,\t\t// user has entered the conversation (used in multi-user chat and group chat)\n\t\tk_EChatEntryTypeWasKicked = 8,\t\t// user was kicked (data: 64-bit steamid of actor performing the kick)\n\t\tk_EChatEntryTypeWasBanned = 9,\t\t// user was banned (data: 64-bit steamid of actor performing the ban)\n\t\tk_EChatEntryTypeDisconnected = 10,\t// user disconnected\n\t\tk_EChatEntryTypeHistoricalChat = 11,\t// a chat message from user's chat history or offilne message\n\t\t//k_EChatEntryTypeReserved1 = 12, // No longer used\n\t\t//k_EChatEntryTypeReserved2 = 13, // No longer used\n\t\tk_EChatEntryTypeLinkBlocked = 14, // a link was removed by the chat filter.\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Chat Room Enter Responses\n\t//-----------------------------------------------------------------------------\n\tpublic enum EChatRoomEnterResponse : int {\n\t\tk_EChatRoomEnterResponseSuccess = 1,\t\t// Success\n\t\tk_EChatRoomEnterResponseDoesntExist = 2,\t// Chat doesn't exist (probably closed)\n\t\tk_EChatRoomEnterResponseNotAllowed = 3,\t\t// General Denied - You don't have the permissions needed to join the chat\n\t\tk_EChatRoomEnterResponseFull = 4,\t\t\t// Chat room has reached its maximum size\n\t\tk_EChatRoomEnterResponseError = 5,\t\t\t// Unexpected Error\n\t\tk_EChatRoomEnterResponseBanned = 6,\t\t\t// You are banned from this chat room and may not join\n\t\tk_EChatRoomEnterResponseLimited = 7,\t\t// Joining this chat is not allowed because you are a limited user (no value on account)\n\t\tk_EChatRoomEnterResponseClanDisabled = 8,\t// Attempt to join a clan chat when the clan is locked or disabled\n\t\tk_EChatRoomEnterResponseCommunityBan = 9,\t// Attempt to join a chat when the user has a community lock on their account\n\t\tk_EChatRoomEnterResponseMemberBlockedYou = 10, // Join failed - some member in the chat has blocked you from joining\n\t\tk_EChatRoomEnterResponseYouBlockedMember = 11, // Join failed - you have blocked some member already in the chat\n\t\t// k_EChatRoomEnterResponseNoRankingDataLobby = 12,  // No longer used\n\t\t// k_EChatRoomEnterResponseNoRankingDataUser = 13,  //  No longer used\n\t\t// k_EChatRoomEnterResponseRankOutOfRange = 14, //  No longer used\n\t\tk_EChatRoomEnterResponseRatelimitExceeded = 15, // Join failed - to many join attempts in a very short period of time\n\t}\n\n\t// Special flags for Chat accounts - they go in the top 8 bits\n\t// of the steam ID's \"instance\", leaving 12 for the actual instances\n\t[Flags]\n\tpublic enum EChatSteamIDInstanceFlags : int {\n\t\tk_EChatAccountInstanceMask = 0x00000FFF, // top 8 bits are flags\n\n\t\tk_EChatInstanceFlagClan = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 1,\t// top bit\n\t\tk_EChatInstanceFlagLobby = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 2,\t// next one down, etc\n\t\tk_EChatInstanceFlagMMSLobby = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 3,\t// next one down, etc\n\n\t\t// Max of 8 flags\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Marketing message flags that change how a client should handle them\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EMarketingMessageFlags : int {\n\t\tk_EMarketingMessageFlagsNone = 0,\n\t\tk_EMarketingMessageFlagsHighPriority = 1 << 0,\n\t\tk_EMarketingMessageFlagsPlatformWindows = 1 << 1,\n\t\tk_EMarketingMessageFlagsPlatformMac = 1 << 2,\n\t\tk_EMarketingMessageFlagsPlatformLinux = 1 << 3,\n\n\t\t//aggregate flags\n\t\tk_EMarketingMessageFlagsPlatformRestrictions =\n\t\tk_EMarketingMessageFlagsPlatformWindows |\n\t\tk_EMarketingMessageFlagsPlatformMac |\n\t\tk_EMarketingMessageFlagsPlatformLinux,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Possible positions to tell the overlay to show notifications in\n\t//-----------------------------------------------------------------------------\n\tpublic enum ENotificationPosition : int {\n\t\tk_EPositionTopLeft = 0,\n\t\tk_EPositionTopRight = 1,\n\t\tk_EPositionBottomLeft = 2,\n\t\tk_EPositionBottomRight = 3,\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Broadcast upload result details\n\t//-----------------------------------------------------------------------------\n\tpublic enum EBroadcastUploadResult : int {\n\t\tk_EBroadcastUploadResultNone = 0,\t// broadcast state unknown\n\t\tk_EBroadcastUploadResultOK = 1,\t\t// broadcast was good, no problems\n\t\tk_EBroadcastUploadResultInitFailed = 2,\t// broadcast init failed\n\t\tk_EBroadcastUploadResultFrameFailed = 3,\t// broadcast frame upload failed\n\t\tk_EBroadcastUploadResultTimeout = 4,\t// broadcast upload timed out\n\t\tk_EBroadcastUploadResultBandwidthExceeded = 5,\t// broadcast send too much data\n\t\tk_EBroadcastUploadResultLowFPS = 6,\t// broadcast FPS too low\n\t\tk_EBroadcastUploadResultMissingKeyFrames = 7,\t// broadcast sending not enough key frames\n\t\tk_EBroadcastUploadResultNoConnection = 8,\t// broadcast client failed to connect to relay\n\t\tk_EBroadcastUploadResultRelayFailed = 9,\t// relay dropped the upload\n\t\tk_EBroadcastUploadResultSettingsChanged = 10,\t// the client changed broadcast settings\n\t\tk_EBroadcastUploadResultMissingAudio = 11,\t// client failed to send audio data\n\t\tk_EBroadcastUploadResultTooFarBehind = 12,\t// clients was too slow uploading\n\t\tk_EBroadcastUploadResultTranscodeBehind = 13,\t// server failed to keep up with transcode\n\t\tk_EBroadcastUploadResultNotAllowedToPlay = 14, // Broadcast does not have permissions to play game\n\t\tk_EBroadcastUploadResultBusy = 15, // RTMP host to busy to take new broadcast stream, choose another\n\t\tk_EBroadcastUploadResultBanned = 16, // Account banned from community broadcast\n\t\tk_EBroadcastUploadResultAlreadyActive = 17, // We already already have an stream running.\n\t\tk_EBroadcastUploadResultForcedOff = 18, // We explicitly shutting down a broadcast\n\t\tk_EBroadcastUploadResultAudioBehind = 19, // Audio stream was too far behind video\n\t\tk_EBroadcastUploadResultShutdown = 20,\t// Broadcast Server was shut down\n\t\tk_EBroadcastUploadResultDisconnect = 21,\t// broadcast uploader TCP disconnected\n\t\tk_EBroadcastUploadResultVideoInitFailed = 22,\t// invalid video settings\n\t\tk_EBroadcastUploadResultAudioInitFailed = 23,\t// invalid audio settings\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: codes for well defined launch options\n\t//-----------------------------------------------------------------------------\n\tpublic enum ELaunchOptionType : int {\n\t\tk_ELaunchOptionType_None\t\t= 0,\t// unknown what launch option does\n\t\tk_ELaunchOptionType_Default\t\t= 1,\t// runs the game, app, whatever in default mode\n\t\tk_ELaunchOptionType_SafeMode\t= 2,\t// runs the game in safe mode\n\t\tk_ELaunchOptionType_Multiplayer = 3,\t// runs the game in multiplayer mode\n\t\tk_ELaunchOptionType_Config\t\t= 4,\t// runs config tool for this game\n\t\tk_ELaunchOptionType_OpenVR\t\t= 5,\t// runs game in VR mode using OpenVR\n\t\tk_ELaunchOptionType_Server\t\t= 6,\t// runs dedicated server for this game\n\t\tk_ELaunchOptionType_Editor\t\t= 7,\t// runs game editor\n\t\tk_ELaunchOptionType_Manual\t\t= 8,\t// shows game manual\n\t\tk_ELaunchOptionType_Benchmark\t= 9,\t// runs game benchmark\n\t\tk_ELaunchOptionType_Option1\t\t= 10,\t// generic run option, uses description field for game name\n\t\tk_ELaunchOptionType_Option2\t\t= 11,\t// generic run option, uses description field for game name\n\t\tk_ELaunchOptionType_Option3     = 12,\t// generic run option, uses description field for game name\n\t\tk_ELaunchOptionType_OculusVR\t= 13,\t// runs game in VR mode using the Oculus SDK\n\t\tk_ELaunchOptionType_OpenVROverlay = 14,\t// runs an OpenVR dashboard overlay\n\t\tk_ELaunchOptionType_OSVR\t\t= 15,\t// runs game in VR mode using the OSVR SDK\n\n\n\t\tk_ELaunchOptionType_Dialog \t\t= 1000, // show launch options dialog\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: code points for VR HMD vendors and models\n\t// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN A DATABASE\n\t//-----------------------------------------------------------------------------\n\tpublic enum EVRHMDType : int {\n\t\tk_eEVRHMDType_None = -1, // unknown vendor and model\n\n\t\tk_eEVRHMDType_Unknown = 0, // unknown vendor and model\n\n\t\tk_eEVRHMDType_HTC_Dev = 1,\t// original HTC dev kits\n\t\tk_eEVRHMDType_HTC_VivePre = 2,\t// htc vive pre\n\t\tk_eEVRHMDType_HTC_Vive = 3,\t// htc vive consumer release\n\t\tk_eEVRHMDType_HTC_VivePro = 4,\t// htc vive pro release\n\t\tk_eEVRHMDType_HTC_ViveCosmos = 5,\t// HTC Vive Cosmos\n\n\t\tk_eEVRHMDType_HTC_Unknown = 20, // unknown htc hmd\n\n\t\tk_eEVRHMDType_Oculus_DK1 = 21, // Oculus DK1\n\t\tk_eEVRHMDType_Oculus_DK2 = 22, // Oculus DK2\n\t\tk_eEVRHMDType_Oculus_Rift = 23, // Oculus Rift\n\t\tk_eEVRHMDType_Oculus_RiftS = 24, // Oculus Rift S\n\n\t\tk_eEVRHMDType_Oculus_Unknown = 40, // // Oculus unknown HMD\n\n\t\tk_eEVRHMDType_Acer_Unknown = 50, // Acer unknown HMD\n\t\tk_eEVRHMDType_Acer_WindowsMR = 51, // Acer QHMD Windows MR headset\n\n\t\tk_eEVRHMDType_Dell_Unknown = 60, // Dell unknown HMD\n\t\tk_eEVRHMDType_Dell_Visor = 61, // Dell Visor Windows MR headset\n\n\t\tk_eEVRHMDType_Lenovo_Unknown = 70, // Lenovo unknown HMD\n\t\tk_eEVRHMDType_Lenovo_Explorer = 71, // Lenovo Explorer Windows MR headset\n\n\t\tk_eEVRHMDType_HP_Unknown = 80, // HP unknown HMD\n\t\tk_eEVRHMDType_HP_WindowsMR = 81, // HP Windows MR headset\n\n\t\tk_eEVRHMDType_Samsung_Unknown = 90, // Samsung unknown HMD\n\t\tk_eEVRHMDType_Samsung_Odyssey = 91, // Samsung Odyssey Windows MR headset\n\n\t\tk_eEVRHMDType_Unannounced_Unknown = 100, // Unannounced unknown HMD\n\t\tk_eEVRHMDType_Unannounced_WindowsMR = 101, // Unannounced Windows MR headset\n\n\t\tk_eEVRHMDType_vridge = 110, // VRIDGE tool\n\n\t\tk_eEVRHMDType_Huawei_Unknown = 120, // Huawei unknown HMD\n\t\tk_eEVRHMDType_Huawei_VR2 = 121, // Huawei VR2 3DOF headset\n\t\tk_eEVRHMDType_Huawei_EndOfRange = 129, // end of Huawei HMD range\n\n\t\tk_eEVRHmdType_Valve_Unknown = 130, // Valve Unknown HMD\n\t\tk_eEVRHmdType_Valve_Index = 131, // Valve Index HMD\n\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Reasons a user may not use the Community Market.\n\t//          Used in MarketEligibilityResponse_t.\n\t//-----------------------------------------------------------------------------\n\t[Flags]\n\tpublic enum EMarketNotAllowedReasonFlags : int {\n\t\tk_EMarketNotAllowedReason_None = 0,\n\n\t\t// A back-end call failed or something that might work again on retry\n\t\tk_EMarketNotAllowedReason_TemporaryFailure = (1 << 0),\n\n\t\t// Disabled account\n\t\tk_EMarketNotAllowedReason_AccountDisabled = (1 << 1),\n\n\t\t// Locked account\n\t\tk_EMarketNotAllowedReason_AccountLockedDown = (1 << 2),\n\n\t\t// Limited account (no purchases)\n\t\tk_EMarketNotAllowedReason_AccountLimited = (1 << 3),\n\n\t\t// The account is banned from trading items\n\t\tk_EMarketNotAllowedReason_TradeBanned = (1 << 4),\n\n\t\t// Wallet funds aren't tradable because the user has had no purchase\n\t\t// activity in the last year or has had no purchases prior to last month\n\t\tk_EMarketNotAllowedReason_AccountNotTrusted = (1 << 5),\n\n\t\t// The user doesn't have Steam Guard enabled\n\t\tk_EMarketNotAllowedReason_SteamGuardNotEnabled = (1 << 6),\n\n\t\t// The user has Steam Guard, but it hasn't been enabled for the required\n\t\t// number of days\n\t\tk_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled = (1 << 7),\n\n\t\t// The user has recently forgotten their password and reset it\n\t\tk_EMarketNotAllowedReason_RecentPasswordReset = (1 << 8),\n\n\t\t// The user has recently funded his or her wallet with a new payment method\n\t\tk_EMarketNotAllowedReason_NewPaymentMethod = (1 << 9),\n\n\t\t// An invalid cookie was sent by the user\n\t\tk_EMarketNotAllowedReason_InvalidCookie = (1 << 10),\n\n\t\t// The user has Steam Guard, but is using a new computer or web browser\n\t\tk_EMarketNotAllowedReason_UsingNewDevice = (1 << 11),\n\n\t\t// The user has recently refunded a store purchase by his or herself\n\t\tk_EMarketNotAllowedReason_RecentSelfRefund = (1 << 12),\n\n\t\t// The user has recently funded his or her wallet with a new payment method that cannot be verified\n\t\tk_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified = (1 << 13),\n\n\t\t// Not only is the account not trusted, but they have no recent purchases at all\n\t\tk_EMarketNotAllowedReason_NoRecentPurchases = (1 << 14),\n\n\t\t// User accepted a wallet gift that was recently purchased\n\t\tk_EMarketNotAllowedReason_AcceptedWalletGift = (1 << 15),\n\t}\n\n\t//\n\t// describes XP / progress restrictions to apply for games with duration control /\n\t// anti-indulgence enabled for minor Steam China users.\n\t//\n\tpublic enum EDurationControlProgress : int {\n\t\tk_EDurationControlProgress_Full,\t\t// Full progress\n\t\tk_EDurationControlProgress_Half,\t\t// XP or persistent rewards should be halved\n\t\tk_EDurationControlProgress_None,\t\t// XP or persistent rewards should be stopped\n\t}\n\n\t//\n\t// describes which notification timer has expired, for steam china duration control feature\n\t//\n\tpublic enum EDurationControlNotification : int {\n\t\tk_EDurationControlNotification_None,\t\t\t// just informing you about progress, no notification to show\n\t\tk_EDurationControlNotification_1Hour,\t\t\t// \"you've been playing for an hour\"\n\t\tk_EDurationControlNotification_3Hours,\t\t\t// \"you've been playing for 3 hours; take a break\"\n\t\tk_EDurationControlNotification_HalfProgress,\t// \"your XP / progress is half normal\"\n\t\tk_EDurationControlNotification_NoProgress,\t\t// \"your XP / progress is zero\"\n\t}\n\n\tpublic enum EGameSearchErrorCode_t : int {\n\t\tk_EGameSearchErrorCode_OK = 1,\n\t\tk_EGameSearchErrorCode_Failed_Search_Already_In_Progress = 2,\n\t\tk_EGameSearchErrorCode_Failed_No_Search_In_Progress = 3,\n\t\tk_EGameSearchErrorCode_Failed_Not_Lobby_Leader = 4, // if not the lobby leader can not call SearchForGameWithLobby\n\t\tk_EGameSearchErrorCode_Failed_No_Host_Available = 5, // no host is available that matches those search params\n\t\tk_EGameSearchErrorCode_Failed_Search_Params_Invalid = 6, // search params are invalid\n\t\tk_EGameSearchErrorCode_Failed_Offline = 7, // offline, could not communicate with server\n\t\tk_EGameSearchErrorCode_Failed_NotAuthorized = 8, // either the user or the application does not have priveledges to do this\n\t\tk_EGameSearchErrorCode_Failed_Unknown_Error = 9, // unknown error\n\t}\n\n\tpublic enum EPlayerResult_t : int {\n\t\tk_EPlayerResultFailedToConnect = 1, // failed to connect after confirming\n\t\tk_EPlayerResultAbandoned = 2,\t\t// quit game without completing it\n\t\tk_EPlayerResultKicked = 3,\t\t\t// kicked by other players/moderator/server rules\n\t\tk_EPlayerResultIncomplete = 4,\t\t// player stayed to end but game did not conclude successfully ( nofault to player )\n\t\tk_EPlayerResultCompleted = 5,\t\t// player completed game\n\t}\n\n\t// HTTP related types\n\t// This enum is used in client API methods, do not re-number existing values.\n\tpublic enum EHTTPMethod : int {\n\t\tk_EHTTPMethodInvalid = 0,\n\t\tk_EHTTPMethodGET,\n\t\tk_EHTTPMethodHEAD,\n\t\tk_EHTTPMethodPOST,\n\t\tk_EHTTPMethodPUT,\n\t\tk_EHTTPMethodDELETE,\n\t\tk_EHTTPMethodOPTIONS,\n\t\tk_EHTTPMethodPATCH,\n\n\t\t// The remaining HTTP methods are not yet supported, per rfc2616 section 5.1.1 only GET and HEAD are required for\n\t\t// a compliant general purpose server.  We'll likely add more as we find uses for them.\n\n\t\t// k_EHTTPMethodTRACE,\n\t\t// k_EHTTPMethodCONNECT\n\t}\n\n\t// HTTP Status codes that the server can send in response to a request, see rfc2616 section 10.3 for descriptions\n\t// of each of these.\n\tpublic enum EHTTPStatusCode : int {\n\t\t// Invalid status code (this isn't defined in HTTP, used to indicate unset in our code)\n\t\tk_EHTTPStatusCodeInvalid =\t\t\t\t\t0,\n\n\t\t// Informational codes\n\t\tk_EHTTPStatusCode100Continue =\t\t\t\t100,\n\t\tk_EHTTPStatusCode101SwitchingProtocols =\t101,\n\n\t\t// Success codes\n\t\tk_EHTTPStatusCode200OK =\t\t\t\t\t200,\n\t\tk_EHTTPStatusCode201Created =\t\t\t\t201,\n\t\tk_EHTTPStatusCode202Accepted =\t\t\t\t202,\n\t\tk_EHTTPStatusCode203NonAuthoritative =\t\t203,\n\t\tk_EHTTPStatusCode204NoContent =\t\t\t\t204,\n\t\tk_EHTTPStatusCode205ResetContent =\t\t\t205,\n\t\tk_EHTTPStatusCode206PartialContent =\t\t206,\n\n\t\t// Redirection codes\n\t\tk_EHTTPStatusCode300MultipleChoices =\t\t300,\n\t\tk_EHTTPStatusCode301MovedPermanently =\t\t301,\n\t\tk_EHTTPStatusCode302Found =\t\t\t\t\t302,\n\t\tk_EHTTPStatusCode303SeeOther =\t\t\t\t303,\n\t\tk_EHTTPStatusCode304NotModified =\t\t\t304,\n\t\tk_EHTTPStatusCode305UseProxy =\t\t\t\t305,\n\t\t//k_EHTTPStatusCode306Unused =\t\t\t\t306, (used in old HTTP spec, now unused in 1.1)\n\t\tk_EHTTPStatusCode307TemporaryRedirect =\t\t307,\n\n\t\t// Error codes\n\t\tk_EHTTPStatusCode400BadRequest =\t\t\t400,\n\t\tk_EHTTPStatusCode401Unauthorized =\t\t\t401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the client can sent an Authorization header in response.\n\t\tk_EHTTPStatusCode402PaymentRequired =\t\t402, // This is reserved for future HTTP specs, not really supported by clients\n\t\tk_EHTTPStatusCode403Forbidden =\t\t\t\t403,\n\t\tk_EHTTPStatusCode404NotFound =\t\t\t\t404,\n\t\tk_EHTTPStatusCode405MethodNotAllowed =\t\t405,\n\t\tk_EHTTPStatusCode406NotAcceptable =\t\t\t406,\n\t\tk_EHTTPStatusCode407ProxyAuthRequired =\t\t407,\n\t\tk_EHTTPStatusCode408RequestTimeout =\t\t408,\n\t\tk_EHTTPStatusCode409Conflict =\t\t\t\t409,\n\t\tk_EHTTPStatusCode410Gone =\t\t\t\t\t410,\n\t\tk_EHTTPStatusCode411LengthRequired =\t\t411,\n\t\tk_EHTTPStatusCode412PreconditionFailed =\t412,\n\t\tk_EHTTPStatusCode413RequestEntityTooLarge =\t413,\n\t\tk_EHTTPStatusCode414RequestURITooLong =\t\t414,\n\t\tk_EHTTPStatusCode415UnsupportedMediaType =\t415,\n\t\tk_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416,\n\t\tk_EHTTPStatusCode417ExpectationFailed =\t\t417,\n\t\tk_EHTTPStatusCode4xxUnknown = \t\t\t\t418, // 418 is reserved, so we'll use it to mean unknown\n\t\tk_EHTTPStatusCode429TooManyRequests\t=\t\t429,\n\n\t\t// Server error codes\n\t\tk_EHTTPStatusCode500InternalServerError =\t500,\n\t\tk_EHTTPStatusCode501NotImplemented =\t\t501,\n\t\tk_EHTTPStatusCode502BadGateway =\t\t\t502,\n\t\tk_EHTTPStatusCode503ServiceUnavailable =\t503,\n\t\tk_EHTTPStatusCode504GatewayTimeout =\t\t504,\n\t\tk_EHTTPStatusCode505HTTPVersionNotSupported = 505,\n\t\tk_EHTTPStatusCode5xxUnknown =\t\t\t\t599,\n\t}\n\n\t// Steam universes.  Each universe is a self-contained Steam instance.\n\tpublic enum EUniverse : int {\n\t\tk_EUniverseInvalid = 0,\n\t\tk_EUniversePublic = 1,\n\t\tk_EUniverseBeta = 2,\n\t\tk_EUniverseInternal = 3,\n\t\tk_EUniverseDev = 4,\n\t\t// k_EUniverseRC = 5,\t\t\t\t// no such universe anymore\n\t\tk_EUniverseMax\n\t}\n\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/SteamStructs.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\tpublic struct ControllerAnalogActionData_t {\n\t\t// Type of data coming from this action, this will match what got specified in the action set\n\t\tpublic EControllerSourceMode eMode;\n\t\t\n\t\t// The current state of this action; will be delta updates for mouse actions\n\t\tpublic float x, y;\n\t\t\n\t\t// Whether or not this action is currently available to be bound in the active action set\n\t\tpublic byte bActive;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\tpublic struct ControllerDigitalActionData_t {\n\t\t// The current state of this action; will be true if currently pressed\n\t\tpublic byte bState;\n\t\t\n\t\t// Whether or not this action is currently available to be bound in the active action set\n\t\tpublic byte bActive;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct ControllerMotionData_t {\n\t\t// Sensor-fused absolute rotation; will drift in heading\n\t\tpublic float rotQuatX;\n\t\tpublic float rotQuatY;\n\t\tpublic float rotQuatZ;\n\t\tpublic float rotQuatW;\n\t\t\n\t\t// Positional acceleration\n\t\tpublic float posAccelX;\n\t\tpublic float posAccelY;\n\t\tpublic float posAccelZ;\n\t\t\n\t\t// Angular velocity\n\t\tpublic float rotVelX;\n\t\tpublic float rotVelY;\n\t\tpublic float rotVelZ;\n\t}\n\n\t// friend game played information\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct FriendGameInfo_t {\n\t\tpublic CGameID m_gameID;\n\t\tpublic uint m_unGameIP;\n\t\tpublic ushort m_usGamePort;\n\t\tpublic ushort m_usQueryPort;\n\t\tpublic CSteamID m_steamIDLobby;\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: information about user sessions\n\t//-----------------------------------------------------------------------------\n\tpublic struct FriendSessionStateInfo_t {\n\t\tpublic uint m_uiOnlineSessionInstances;\n\t\tpublic byte m_uiPublishedToFriendsSessionInstance;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\tpublic struct InputAnalogActionData_t {\n\t\t// Type of data coming from this action, this will match what got specified in the action set\n\t\tpublic EInputSourceMode eMode;\n\t\t\n\t\t// The current state of this action; will be delta updates for mouse actions\n\t\tpublic float x, y;\n\t\t\n\t\t// Whether or not this action is currently available to be bound in the active action set\n\t\tpublic byte bActive;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = 1)]\n\tpublic struct InputDigitalActionData_t {\n\t\t// The current state of this action; will be true if currently pressed\n\t\tpublic byte bState;\n\t\t\n\t\t// Whether or not this action is currently available to be bound in the active action set\n\t\tpublic byte bActive;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct InputMotionData_t {\n\t\t// Sensor-fused absolute rotation; will drift in heading\n\t\tpublic float rotQuatX;\n\t\tpublic float rotQuatY;\n\t\tpublic float rotQuatZ;\n\t\tpublic float rotQuatW;\n\t\t\n\t\t// Positional acceleration\n\t\tpublic float posAccelX;\n\t\tpublic float posAccelY;\n\t\tpublic float posAccelZ;\n\t\t\n\t\t// Angular velocity\n\t\tpublic float rotVelX;\n\t\tpublic float rotVelY;\n\t\tpublic float rotVelZ;\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct SteamItemDetails_t {\n\t\tpublic SteamItemInstanceID_t m_itemId;\n\t\tpublic SteamItemDef_t m_iDefinition;\n\t\tpublic ushort m_unQuantity;\n\t\tpublic ushort m_unFlags; // see ESteamItemFlags\n\t}\n\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct SteamPartyBeaconLocation_t {\n\t\tpublic ESteamPartyBeaconLocationType m_eType;\n\t\tpublic ulong m_ulLocationID;\n\t}\n\n\t// connection state to a specified user, returned by GetP2PSessionState()\n\t// this is under-the-hood info about what's going on with a SendP2PPacket(), shouldn't be needed except for debuggin\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct P2PSessionState_t {\n\t\tpublic byte m_bConnectionActive;\t\t// true if we've got an active open connection\n\t\tpublic byte m_bConnecting;\t\t\t// true if we're currently trying to establish a connection\n\t\tpublic byte m_eP2PSessionError;\t\t// last error recorded (see enum above)\n\t\tpublic byte m_bUsingRelay;\t\t\t// true if it's going through a relay server (TURN)\n\t\tpublic int m_nBytesQueuedForSend;\n\t\tpublic int m_nPacketsQueuedForSend;\n\t\tpublic uint m_nRemoteIP;\t\t\t\t// potential IP:Port of remote host. Could be TURN server.\n\t\tpublic ushort m_nRemotePort;\t\t\t// Only exists for compatibility with older authentication api's\n\t}\n\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Structure that contains an array of const char * strings and the number of those strings\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct SteamParamStringArray_t {\n\t\tpublic IntPtr m_ppStrings;\n\t\tpublic int m_nNumStrings;\n\t}\n\n\t// Details for a single published file/UGC\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct SteamUGCDetails_t {\n\t\tpublic PublishedFileId_t m_nPublishedFileId;\n\t\tpublic EResult m_eResult;\t\t\t\t\t\t\t\t\t\t\t\t// The result of the operation.\n\t\tpublic EWorkshopFileType m_eFileType;\t\t\t\t\t\t\t\t\t// Type of the file\n\t\tpublic AppId_t m_nCreatorAppID;\t\t\t\t\t\t\t\t\t\t// ID of the app that created this file.\n\t\tpublic AppId_t m_nConsumerAppID;\t\t\t\t\t\t\t\t\t\t// ID of the app that will consume this file.\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentTitleMax)]\n\t\tpublic string m_rgchTitle;\t\t\t\t// title of document\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)]\n\t\tpublic string m_rgchDescription;\t// description of document\n\t\tpublic ulong m_ulSteamIDOwner;\t\t\t\t\t\t\t\t\t\t// Steam ID of the user who created this content.\n\t\tpublic uint m_rtimeCreated;\t\t\t\t\t\t\t\t\t\t\t// time when the published file was created\n\t\tpublic uint m_rtimeUpdated;\t\t\t\t\t\t\t\t\t\t\t// time when the published file was last updated\n\t\tpublic uint m_rtimeAddedToUserList;\t\t\t\t\t\t\t\t\t// time when the user added the published file to their list (not always applicable)\n\t\tpublic ERemoteStoragePublishedFileVisibility m_eVisibility;\t\t\t// visibility\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bBanned;\t\t\t\t\t\t\t\t\t\t\t\t\t// whether the file was banned\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bAcceptedForUse;\t\t\t\t\t\t\t\t\t\t\t// developer has specifically flagged this item as accepted in the Workshop\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bTagsTruncated;\t\t\t\t\t\t\t\t\t\t\t// whether the list of tags was too long to be returned in the provided buffer\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchTagListMax)]\n\t\tpublic string m_rgchTags;\t\t\t\t\t\t\t\t// comma separated list of all tags associated with this file\n\t\t// file/url information\n\t\tpublic UGCHandle_t m_hFile;\t\t\t\t\t\t\t\t\t\t\t// The handle of the primary file\n\t\tpublic UGCHandle_t m_hPreviewFile;\t\t\t\t\t\t\t\t\t\t// The handle of the preview file\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]\n\t\tpublic string m_pchFileName;\t\t\t\t\t\t\t// The cloud filename of the primary file\n\t\tpublic int m_nFileSize;\t\t\t\t\t\t\t\t\t\t\t\t// Size of the primary file\n\t\tpublic int m_nPreviewFileSize;\t\t\t\t\t\t\t\t\t\t// Size of the preview file\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedFileURLMax)]\n\t\tpublic string m_rgchURL;\t\t\t\t\t\t// URL (for a video or a website)\n\t\t// voting information\n\t\tpublic uint m_unVotesUp;\t\t\t\t\t\t\t\t\t\t\t\t// number of votes up\n\t\tpublic uint m_unVotesDown;\t\t\t\t\t\t\t\t\t\t\t// number of votes down\n\t\tpublic float m_flScore;\t\t\t\t\t\t\t\t\t\t\t\t// calculated score\n\t\t// collection details\n\t\tpublic uint m_unNumChildren;\n\t}\n\n\t// structure that contains client callback data\n\t// see callbacks documentation for more details\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct CallbackMsg_t {\n\t\tpublic int m_hSteamUser;\n\t\tpublic int m_iCallback;\n\t\tpublic IntPtr m_pubParam;\n\t\tpublic int m_cubParam;\n\t}\n\n\t// a single entry in a leaderboard, as returned by GetDownloadedLeaderboardEntry()\n\t[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]\n\tpublic struct LeaderboardEntry_t {\n\t\tpublic CSteamID m_steamIDUser; // user with the entry - use SteamFriends()->GetFriendPersonaName() & SteamFriends()->GetFriendAvatar() to get more info\n\t\tpublic int m_nGlobalRank;\t// [1..N], where N is the number of users with an entry in the leaderboard\n\t\tpublic int m_nScore;\t\t\t// score as set in the leaderboard\n\t\tpublic int m_cDetails;\t\t// number of int32 details available for this entry\n\t\tpublic UGCHandle_t m_hUGC;\t\t// handle for UGC attached to the entry\n\t}\n\n\t/// Store key/value pair used in matchmaking queries.\n\t///\n\t/// Actually, the name Key/Value is a bit misleading.  The \"key\" is better\n\t/// understood as \"filter operation code\" and the \"value\" is the operand to this\n\t/// filter operation.  The meaning of the operand depends upon the filter.\n\t[StructLayout(LayoutKind.Sequential)]\n\tpublic struct MatchMakingKeyValuePair_t {\n\t\tMatchMakingKeyValuePair_t(string strKey, string strValue) {\n\t\t\tm_szKey = strKey;\n\t\t\tm_szValue = strValue;\n\t\t}\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]\n\t\tpublic string m_szKey;\n\t\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]\n\t\tpublic string m_szValue;\n\t}\n\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamapplist.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamAppList {\n\t\tpublic static uint GetNumInstalledApps() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamAppList_GetNumInstalledApps(CSteamAPIContext.GetSteamAppList());\n\t\t}\n\n\t\tpublic static uint GetInstalledApps(AppId_t[] pvecAppID, uint unMaxAppIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamAppList_GetInstalledApps(CSteamAPIContext.GetSteamAppList(), pvecAppID, unMaxAppIDs);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns -1 if no name was found</para>\n\t\t/// </summary>\n\t\tpublic static int GetAppName(AppId_t nAppID, out string pchName, int cchNameMax) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal(cchNameMax);\n\t\t\tint ret = NativeMethods.ISteamAppList_GetAppName(CSteamAPIContext.GetSteamAppList(), nAppID, pchName2, cchNameMax);\n\t\t\tpchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns -1 if no dir was found</para>\n\t\t/// </summary>\n\t\tpublic static int GetAppInstallDir(AppId_t nAppID, out string pchDirectory, int cchNameMax) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchDirectory2 = Marshal.AllocHGlobal(cchNameMax);\n\t\t\tint ret = NativeMethods.ISteamAppList_GetAppInstallDir(CSteamAPIContext.GetSteamAppList(), nAppID, pchDirectory2, cchNameMax);\n\t\t\tpchDirectory = ret != -1 ? InteropHelp.PtrToStringUTF8(pchDirectory2) : null;\n\t\t\tMarshal.FreeHGlobal(pchDirectory2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return the buildid of this app, may change at any time based on backend updates to the game</para>\n\t\t/// </summary>\n\t\tpublic static int GetAppBuildId(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamAppList_GetAppBuildId(CSteamAPIContext.GetSteamAppList(), nAppID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamapps.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamApps {\n\t\tpublic static bool BIsSubscribed() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribed(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsLowViolence() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsLowViolence(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsCybercafe() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsCybercafe(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsVACBanned() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsVACBanned(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static string GetCurrentGameLanguage() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetCurrentGameLanguage(CSteamAPIContext.GetSteamApps()));\n\t\t}\n\n\t\tpublic static string GetAvailableGameLanguages() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetAvailableGameLanguages(CSteamAPIContext.GetSteamApps()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> only use this member if you need to check ownership of another game related to yours, a demo for example</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedApp(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedApp(CSteamAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Takes AppID of DLC and checks if the user owns the DLC &amp; if the DLC is installed</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsDlcInstalled(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsDlcInstalled(CSteamAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the Unix time of the purchase of the app</para>\n\t\t/// </summary>\n\t\tpublic static uint GetEarliestPurchaseUnixTime(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_GetEarliestPurchaseUnixTime(CSteamAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Checks if the user is subscribed to the current app through a free weekend</para>\n\t\t/// <para> This function will return false for users who have a retail or other type of license</para>\n\t\t/// <para> Before using, please ask your Valve technical contact how to package and secure your free weekened</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedFromFreeWeekend() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedFromFreeWeekend(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the number of DLC pieces for the running app</para>\n\t\t/// </summary>\n\t\tpublic static int GetDLCCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_GetDLCCount(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns metadata for DLC by index, of range [0, GetDLCCount()]</para>\n\t\t/// </summary>\n\t\tpublic static bool BGetDLCDataByIndex(int iDLC, out AppId_t pAppID, out bool pbAvailable, out string pchName, int cchNameBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamApps_BGetDLCDataByIndex(CSteamAPIContext.GetSteamApps(), iDLC, out pAppID, out pbAvailable, pchName2, cchNameBufferSize);\n\t\t\tpchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Install/Uninstall control for optional DLC</para>\n\t\t/// </summary>\n\t\tpublic static void InstallDLC(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamApps_InstallDLC(CSteamAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\tpublic static void UninstallDLC(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamApps_UninstallDLC(CSteamAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request legacy cd-key for yourself or owned DLC. If you are interested in this</para>\n\t\t/// <para> data then make sure you provide us with a list of valid keys to be distributed</para>\n\t\t/// <para> to users when they purchase the game, before the game ships.</para>\n\t\t/// <para> You'll receive an AppProofOfPurchaseKeyResponse_t callback when</para>\n\t\t/// <para> the key is available (which may be immediately).</para>\n\t\t/// </summary>\n\t\tpublic static void RequestAppProofOfPurchaseKey(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamApps_RequestAppProofOfPurchaseKey(CSteamAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns current beta branch name, 'public' is the default branch</para>\n\t\t/// </summary>\n\t\tpublic static bool GetCurrentBetaName(out string pchName, int cchNameBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamApps_GetCurrentBetaName(CSteamAPIContext.GetSteamApps(), pchName2, cchNameBufferSize);\n\t\t\tpchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> signal Steam that game files seems corrupt or missing</para>\n\t\t/// </summary>\n\t\tpublic static bool MarkContentCorrupt(bool bMissingFilesOnly) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_MarkContentCorrupt(CSteamAPIContext.GetSteamApps(), bMissingFilesOnly);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return installed depots in mount order</para>\n\t\t/// </summary>\n\t\tpublic static uint GetInstalledDepots(AppId_t appID, DepotId_t[] pvecDepots, uint cMaxDepots) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_GetInstalledDepots(CSteamAPIContext.GetSteamApps(), appID, pvecDepots, cMaxDepots);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns current app install folder for AppID, returns folder name length</para>\n\t\t/// </summary>\n\t\tpublic static uint GetAppInstallDir(AppId_t appID, out string pchFolder, uint cchFolderBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderBufferSize);\n\t\t\tuint ret = NativeMethods.ISteamApps_GetAppInstallDir(CSteamAPIContext.GetSteamApps(), appID, pchFolder2, cchFolderBufferSize);\n\t\t\tpchFolder = ret != 0 ? InteropHelp.PtrToStringUTF8(pchFolder2) : null;\n\t\t\tMarshal.FreeHGlobal(pchFolder2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if that app is installed (not necessarily owned)</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsAppInstalled(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsAppInstalled(CSteamAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the SteamID of the original owner. If this CSteamID is different from ISteamUser::GetSteamID(),</para>\n\t\t/// <para> the user has a temporary license borrowed via Family Sharing</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetAppOwner() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamApps_GetAppOwner(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated launch param if the game is run via steam://run/&lt;appid&gt;//?param1=value1&amp;param2=value2&amp;param3=value3 etc.</para>\n\t\t/// <para> Parameter names starting with the character '@' are reserved for internal use and will always return and empty string.</para>\n\t\t/// <para> Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried by the game,</para>\n\t\t/// <para> but it is advised that you not param names beginning with an underscore for your own features.</para>\n\t\t/// <para> Check for new launch parameters on callback NewUrlLaunchParameters_t</para>\n\t\t/// </summary>\n\t\tpublic static string GetLaunchQueryParam(string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetLaunchQueryParam(CSteamAPIContext.GetSteamApps(), pchKey2));\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get download progress for optional DLC</para>\n\t\t/// </summary>\n\t\tpublic static bool GetDlcDownloadProgress(AppId_t nAppID, out ulong punBytesDownloaded, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_GetDlcDownloadProgress(CSteamAPIContext.GetSteamApps(), nAppID, out punBytesDownloaded, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return the buildid of this app, may change at any time based on backend updates to the game</para>\n\t\t/// </summary>\n\t\tpublic static int GetAppBuildId() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_GetAppBuildId(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request all proof of purchase keys for the calling appid and asociated DLC.</para>\n\t\t/// <para> A series of AppProofOfPurchaseKeyResponse_t callbacks will be sent with</para>\n\t\t/// <para> appropriate appid values, ending with a final callback where the m_nAppId</para>\n\t\t/// <para> member is k_uAppIdInvalid (zero).</para>\n\t\t/// </summary>\n\t\tpublic static void RequestAllProofOfPurchaseKeys() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamApps_RequestAllProofOfPurchaseKeys(CSteamAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetFileDetails(string pszFileName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszFileName2 = new InteropHelp.UTF8StringHandle(pszFileName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamApps_GetFileDetails(CSteamAPIContext.GetSteamApps(), pszFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get command line if game was launched via Steam URL, e.g. steam://run/&lt;appid&gt;//&lt;command line&gt;/.</para>\n\t\t/// <para> This method of passing a connect string (used when joining via rich presence, accepting an</para>\n\t\t/// <para> invite, etc) is preferable to passing the connect string on the operating system command</para>\n\t\t/// <para> line, which is a security risk.  In order for rich presence joins to go through this</para>\n\t\t/// <para> path and not be placed on the OS command line, you must set a value in your app's</para>\n\t\t/// <para> configuration on Steam.  Ask Valve for help with this.</para>\n\t\t/// <para> If game was already running and launched again, the NewUrlLaunchParameters_t will be fired.</para>\n\t\t/// </summary>\n\t\tpublic static int GetLaunchCommandLine(out string pszCommandLine, int cubCommandLine) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pszCommandLine2 = Marshal.AllocHGlobal(cubCommandLine);\n\t\t\tint ret = NativeMethods.ISteamApps_GetLaunchCommandLine(CSteamAPIContext.GetSteamApps(), pszCommandLine2, cubCommandLine);\n\t\t\tpszCommandLine = ret != -1 ? InteropHelp.PtrToStringUTF8(pszCommandLine2) : null;\n\t\t\tMarshal.FreeHGlobal(pszCommandLine2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender SteamID</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedFromFamilySharing() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedFromFamilySharing(CSteamAPIContext.GetSteamApps());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamclient.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamClient {\n\t\t/// <summary>\n\t\t/// <para> Creates a communication pipe to the Steam client.</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamPipe CreateSteamPipe() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HSteamPipe)NativeMethods.ISteamClient_CreateSteamPipe(CSteamAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Releases a previously created communications pipe</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static bool BReleaseSteamPipe(HSteamPipe hSteamPipe) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamClient_BReleaseSteamPipe(CSteamAPIContext.GetSteamClient(), hSteamPipe);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> connects to an existing global user, failing if none exists</para>\n\t\t/// <para> used by the game to coordinate with the steamUI</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamUser ConnectToGlobalUser(HSteamPipe hSteamPipe) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HSteamUser)NativeMethods.ISteamClient_ConnectToGlobalUser(CSteamAPIContext.GetSteamClient(), hSteamPipe);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> used by game servers, create a steam user that won't be shared with anyone else</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamUser CreateLocalUser(out HSteamPipe phSteamPipe, EAccountType eAccountType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HSteamUser)NativeMethods.ISteamClient_CreateLocalUser(CSteamAPIContext.GetSteamClient(), out phSteamPipe, eAccountType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> removes an allocated user</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static void ReleaseUser(HSteamPipe hSteamPipe, HSteamUser hUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamClient_ReleaseUser(CSteamAPIContext.GetSteamClient(), hSteamPipe, hUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves the ISteamUser interface associated with the handle</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUser(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUser(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves the ISteamGameServer interface associated with the handle</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameServer(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameServer(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set the local IP and Port to bind to</para>\n\t\t/// <para> this must be set before CreateLocalUser()</para>\n\t\t/// </summary>\n\t\tpublic static void SetLocalIPBinding(uint unIP, ushort usPort) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamClient_SetLocalIPBinding(CSteamAPIContext.GetSteamClient(), unIP, usPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamFriends interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamFriends(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamFriends(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamUtils interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUtils(HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUtils(CSteamAPIContext.GetSteamClient(), hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamMatchmaking interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMatchmaking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMatchmaking(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamMatchmakingServers interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMatchmakingServers(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMatchmakingServers(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the a generic interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGenericInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGenericInterface(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamUserStats interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUserStats(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUserStats(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamGameServerStats interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameServerStats(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameServerStats(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns apps interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamApps(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamApps(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> networking</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamNetworking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamNetworking(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remote storage</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamRemoteStorage(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamRemoteStorage(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> user screenshots</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamScreenshots(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamScreenshots(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> game search</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameSearch(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameSearch(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of IPC calls made since the last time this function was called</para>\n\t\t/// <para> Used for perf debugging so you can understand how many IPC calls your game makes per frame</para>\n\t\t/// <para> Every IPC call is at minimum a thread context switch if not a process one so you want to rate</para>\n\t\t/// <para> control how often you do them.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetIPCCallCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamClient_GetIPCCallCount(CSteamAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API warning handling</para>\n\t\t/// <para> 'int' is the severity; 0 for msg, 1 for warning</para>\n\t\t/// <para> 'const char *' is the text of the message</para>\n\t\t/// <para> callbacks will occur directly after the API function is called that generated the warning or message.</para>\n\t\t/// </summary>\n\t\tpublic static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamClient_SetWarningMessageHook(CSteamAPIContext.GetSteamClient(), pFunction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger global shutdown for the DLL</para>\n\t\t/// </summary>\n\t\tpublic static bool BShutdownIfAllPipesClosed() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamClient_BShutdownIfAllPipesClosed(CSteamAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Expose HTTP interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamHTTP(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamHTTP(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the ISteamController interface - deprecated in favor of Steam Input</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamController(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamController(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the ISteamUGC interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUGC(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns app list interface, only available on specially registered apps</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamAppList(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamAppList(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Music Player</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMusic(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMusic(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Music Player Remote</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMusicRemote(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMusicRemote(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> html page display</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamHTMLSurface(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> inventory</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamInventory(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamInventory(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Video</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamVideo(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamVideo(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Parental controls</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamParentalSettings(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamParentalSettings(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the Steam Input interface for controller support</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamInput(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamInput(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Parties interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamParties(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamParties(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Remote Play interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamRemotePlay(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamRemotePlay(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamcontroller.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamController {\n\t\t/// <summary>\n\t\t/// <para> Init and Shutdown must be called when starting/ending use of this interface</para>\n\t\t/// </summary>\n\t\tpublic static bool Init() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_Init(CSteamAPIContext.GetSteamController());\n\t\t}\n\n\t\tpublic static bool Shutdown() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_Shutdown(CSteamAPIContext.GetSteamController());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Synchronize API state with the latest Steam Controller inputs available. This</para>\n\t\t/// <para> is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest</para>\n\t\t/// <para> possible latency, you call this directly before reading controller state. This must</para>\n\t\t/// <para> be called from somewhere before GetConnectedControllers will return any handles</para>\n\t\t/// </summary>\n\t\tpublic static void RunFrame() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_RunFrame(CSteamAPIContext.GetSteamController());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Enumerate currently connected controllers</para>\n\t\t/// <para> handlesOut should point to a STEAM_CONTROLLER_MAX_COUNT sized array of ControllerHandle_t handles</para>\n\t\t/// <para> Returns the number of handles written to handlesOut</para>\n\t\t/// </summary>\n\t\tpublic static int GetConnectedControllers(ControllerHandle_t[] handlesOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (handlesOut != null && handlesOut.Length != Constants.STEAM_CONTROLLER_MAX_COUNT) {\n\t\t\t\tthrow new System.ArgumentException(\"handlesOut must be the same size as Constants.STEAM_CONTROLLER_MAX_COUNT!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamController_GetConnectedControllers(CSteamAPIContext.GetSteamController(), handlesOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> ACTION SETS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static ControllerActionSetHandle_t GetActionSetHandle(string pszActionSetName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionSetName2 = new InteropHelp.UTF8StringHandle(pszActionSetName)) {\n\t\t\t\treturn (ControllerActionSetHandle_t)NativeMethods.ISteamController_GetActionSetHandle(CSteamAPIContext.GetSteamController(), pszActionSetName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')</para>\n\t\t/// <para> This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in</para>\n\t\t/// <para> your state loops, instead of trying to place it in all of your state transitions.</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateActionSet(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_ActivateActionSet(CSteamAPIContext.GetSteamController(), controllerHandle, actionSetHandle);\n\t\t}\n\n\t\tpublic static ControllerActionSetHandle_t GetCurrentActionSet(ControllerHandle_t controllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (ControllerActionSetHandle_t)NativeMethods.ISteamController_GetCurrentActionSet(CSteamAPIContext.GetSteamController(), controllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ACTION SET LAYERS</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateActionSetLayer(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_ActivateActionSetLayer(CSteamAPIContext.GetSteamController(), controllerHandle, actionSetLayerHandle);\n\t\t}\n\n\t\tpublic static void DeactivateActionSetLayer(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_DeactivateActionSetLayer(CSteamAPIContext.GetSteamController(), controllerHandle, actionSetLayerHandle);\n\t\t}\n\n\t\tpublic static void DeactivateAllActionSetLayers(ControllerHandle_t controllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_DeactivateAllActionSetLayers(CSteamAPIContext.GetSteamController(), controllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Enumerate currently active layers</para>\n\t\t/// <para> handlesOut should point to a STEAM_CONTROLLER_MAX_ACTIVE_LAYERS sized array of ControllerActionSetHandle_t handles.</para>\n\t\t/// <para> Returns the number of handles written to handlesOut</para>\n\t\t/// </summary>\n\t\tpublic static int GetActiveActionSetLayers(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t[] handlesOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (handlesOut != null && handlesOut.Length != Constants.STEAM_CONTROLLER_MAX_ACTIVE_LAYERS) {\n\t\t\t\tthrow new System.ArgumentException(\"handlesOut must be the same size as Constants.STEAM_CONTROLLER_MAX_ACTIVE_LAYERS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamController_GetActiveActionSetLayers(CSteamAPIContext.GetSteamController(), controllerHandle, handlesOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> ACTIONS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static ControllerDigitalActionHandle_t GetDigitalActionHandle(string pszActionName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) {\n\t\t\t\treturn (ControllerDigitalActionHandle_t)NativeMethods.ISteamController_GetDigitalActionHandle(CSteamAPIContext.GetSteamController(), pszActionName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the current state of the supplied digital game action</para>\n\t\t/// </summary>\n\t\tpublic static ControllerDigitalActionData_t GetDigitalActionData(ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetDigitalActionData(CSteamAPIContext.GetSteamController(), controllerHandle, digitalActionHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.</para>\n\t\t/// <para> originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles. The EControllerActionOrigin enum will get extended as support for new controller controllers gets added to</para>\n\t\t/// <para> the Steam client and will exceed the values from this header, please check bounds if you are using a look up table.</para>\n\t\t/// </summary>\n\t\tpublic static int GetDigitalActionOrigins(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerDigitalActionHandle_t digitalActionHandle, EControllerActionOrigin[] originsOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (originsOut != null && originsOut.Length != Constants.STEAM_CONTROLLER_MAX_ORIGINS) {\n\t\t\t\tthrow new System.ArgumentException(\"originsOut must be the same size as Constants.STEAM_CONTROLLER_MAX_ORIGINS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamController_GetDigitalActionOrigins(CSteamAPIContext.GetSteamController(), controllerHandle, actionSetHandle, digitalActionHandle, originsOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static ControllerAnalogActionHandle_t GetAnalogActionHandle(string pszActionName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) {\n\t\t\t\treturn (ControllerAnalogActionHandle_t)NativeMethods.ISteamController_GetAnalogActionHandle(CSteamAPIContext.GetSteamController(), pszActionName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the current state of these supplied analog game action</para>\n\t\t/// </summary>\n\t\tpublic static ControllerAnalogActionData_t GetAnalogActionData(ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetAnalogActionData(CSteamAPIContext.GetSteamController(), controllerHandle, analogActionHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.</para>\n\t\t/// <para> originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles. The EControllerActionOrigin enum will get extended as support for new controller controllers gets added to</para>\n\t\t/// <para> the Steam client and will exceed the values from this header, please check bounds if you are using a look up table.</para>\n\t\t/// </summary>\n\t\tpublic static int GetAnalogActionOrigins(ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerAnalogActionHandle_t analogActionHandle, EControllerActionOrigin[] originsOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (originsOut != null && originsOut.Length != Constants.STEAM_CONTROLLER_MAX_ORIGINS) {\n\t\t\t\tthrow new System.ArgumentException(\"originsOut must be the same size as Constants.STEAM_CONTROLLER_MAX_ORIGINS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamController_GetAnalogActionOrigins(CSteamAPIContext.GetSteamController(), controllerHandle, actionSetHandle, analogActionHandle, originsOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get a local path to art for on-screen glyph for a particular origin - this call is cheap</para>\n\t\t/// </summary>\n\t\tpublic static string GetGlyphForActionOrigin(EControllerActionOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamController_GetGlyphForActionOrigin(CSteamAPIContext.GetSteamController(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns a localized string (from Steam's language setting) for the specified origin - this call is serialized</para>\n\t\t/// </summary>\n\t\tpublic static string GetStringForActionOrigin(EControllerActionOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamController_GetStringForActionOrigin(CSteamAPIContext.GetSteamController(), eOrigin));\n\t\t}\n\n\t\tpublic static void StopAnalogActionMomentum(ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t eAction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_StopAnalogActionMomentum(CSteamAPIContext.GetSteamController(), controllerHandle, eAction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns raw motion data from the specified controller</para>\n\t\t/// </summary>\n\t\tpublic static ControllerMotionData_t GetMotionData(ControllerHandle_t controllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetMotionData(CSteamAPIContext.GetSteamController(), controllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> OUTPUTS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Trigger a haptic pulse on a controller</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerHapticPulse(ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_TriggerHapticPulse(CSteamAPIContext.GetSteamController(), controllerHandle, eTargetPad, usDurationMicroSec);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger a pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times.</para>\n\t\t/// <para> nFlags is currently unused and reserved for future use.</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerRepeatedHapticPulse(ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_TriggerRepeatedHapticPulse(CSteamAPIContext.GetSteamController(), controllerHandle, eTargetPad, usDurationMicroSec, usOffMicroSec, unRepeat, nFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger a vibration event on supported controllers.</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerVibration(ControllerHandle_t controllerHandle, ushort usLeftSpeed, ushort usRightSpeed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_TriggerVibration(CSteamAPIContext.GetSteamController(), controllerHandle, usLeftSpeed, usRightSpeed);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the controller LED color on supported controllers.</para>\n\t\t/// </summary>\n\t\tpublic static void SetLEDColor(ControllerHandle_t controllerHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamController_SetLEDColor(CSteamAPIContext.GetSteamController(), controllerHandle, nColorR, nColorG, nColorB, nFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Utility functions availible without using the rest of Steam Input API</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Invokes the Steam overlay and brings up the binding screen if the user is using Big Picture Mode</para>\n\t\t/// <para> If the user is not in Big Picture Mode it will open up the binding in a new window</para>\n\t\t/// </summary>\n\t\tpublic static bool ShowBindingPanel(ControllerHandle_t controllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_ShowBindingPanel(CSteamAPIContext.GetSteamController(), controllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the input type for a particular handle</para>\n\t\t/// </summary>\n\t\tpublic static ESteamInputType GetInputTypeForHandle(ControllerHandle_t controllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetInputTypeForHandle(CSteamAPIContext.GetSteamController(), controllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated controller handle for the specified emulated gamepad - can be used with the above 2 functions</para>\n\t\t/// <para> to identify controllers presented to your game over Xinput. Returns 0 if the Xinput index isn't associated with Steam Input</para>\n\t\t/// </summary>\n\t\tpublic static ControllerHandle_t GetControllerForGamepadIndex(int nIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (ControllerHandle_t)NativeMethods.ISteamController_GetControllerForGamepadIndex(CSteamAPIContext.GetSteamController(), nIndex);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated gamepad index for the specified controller, if emulating a gamepad or -1 if not associated with an Xinput index</para>\n\t\t/// </summary>\n\t\tpublic static int GetGamepadIndexForController(ControllerHandle_t ulControllerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetGamepadIndexForController(CSteamAPIContext.GetSteamController(), ulControllerHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns a localized string (from Steam's language setting) for the specified Xbox controller origin.</para>\n\t\t/// </summary>\n\t\tpublic static string GetStringForXboxOrigin(EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamController_GetStringForXboxOrigin(CSteamAPIContext.GetSteamController(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get a local path to art for on-screen glyph for a particular Xbox controller origin.</para>\n\t\t/// </summary>\n\t\tpublic static string GetGlyphForXboxOrigin(EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamController_GetGlyphForXboxOrigin(CSteamAPIContext.GetSteamController(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the equivalent ActionOrigin for a given Xbox controller origin this can be chained with GetGlyphForActionOrigin to provide future proof glyphs for</para>\n\t\t/// <para> non-Steam Input API action games. Note - this only translates the buttons directly and doesn't take into account any remapping a user has made in their configuration</para>\n\t\t/// </summary>\n\t\tpublic static EControllerActionOrigin GetActionOriginFromXboxOrigin(ControllerHandle_t controllerHandle, EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetActionOriginFromXboxOrigin(CSteamAPIContext.GetSteamController(), controllerHandle, eOrigin);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Convert an origin to another controller type - for inputs not present on the other controller type this will return k_EControllerActionOrigin_None</para>\n\t\t/// </summary>\n\t\tpublic static EControllerActionOrigin TranslateActionOrigin(ESteamInputType eDestinationInputType, EControllerActionOrigin eSourceOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_TranslateActionOrigin(CSteamAPIContext.GetSteamController(), eDestinationInputType, eSourceOrigin);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the binding revision for a given device. Returns false if the handle was not valid or if a mapping is not yet loaded for the device</para>\n\t\t/// </summary>\n\t\tpublic static bool GetControllerBindingRevision(ControllerHandle_t controllerHandle, out int pMajor, out int pMinor) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamController_GetControllerBindingRevision(CSteamAPIContext.GetSteamController(), controllerHandle, out pMajor, out pMinor);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamfriends.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamFriends {\n\t\t/// <summary>\n\t\t/// <para> returns the local players name - guaranteed to not be NULL.</para>\n\t\t/// <para> this is the same name as on the users community profile page</para>\n\t\t/// <para> this is stored in UTF-8 format</para>\n\t\t/// <para> like all the other interface functions that return a char *, it's important that this pointer is not saved</para>\n\t\t/// <para> off; it will eventually be free'd or re-allocated</para>\n\t\t/// </summary>\n\t\tpublic static string GetPersonaName() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetPersonaName(CSteamAPIContext.GetSteamFriends()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the player name, stores it on the server and publishes the changes to all friends who are online.</para>\n\t\t/// <para> Changes take place locally immediately, and a PersonaStateChange_t is posted, presuming success.</para>\n\t\t/// <para> The final results are available through the return value SteamAPICall_t, using SetPersonaNameResponse_t.</para>\n\t\t/// <para> If the name change fails to happen on the server, then an additional global PersonaStateChange_t will be posted</para>\n\t\t/// <para> to change the name back, in addition to the SetPersonaNameResponse_t callback.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SetPersonaName(string pchPersonaName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPersonaName2 = new InteropHelp.UTF8StringHandle(pchPersonaName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_SetPersonaName(CSteamAPIContext.GetSteamFriends(), pchPersonaName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets the status of the current user</para>\n\t\t/// </summary>\n\t\tpublic static EPersonaState GetPersonaState() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetPersonaState(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> friend iteration</para>\n\t\t/// <para> takes a set of k_EFriendFlags, and returns the number of users the client knows about who meet that criteria</para>\n\t\t/// <para> then GetFriendByIndex() can then be used to return the id's of each of those users</para>\n\t\t/// </summary>\n\t\tpublic static int GetFriendCount(EFriendFlags iFriendFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendCount(CSteamAPIContext.GetSteamFriends(), iFriendFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the steamID of a user</para>\n\t\t/// <para> iFriend is a index of range [0, GetFriendCount())</para>\n\t\t/// <para> iFriendsFlags must be the same value as used in GetFriendCount()</para>\n\t\t/// <para> the returned CSteamID can then be used by all the functions below to access details about the user</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetFriendByIndex(int iFriend, EFriendFlags iFriendFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetFriendByIndex(CSteamAPIContext.GetSteamFriends(), iFriend, iFriendFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns a relationship to a user</para>\n\t\t/// </summary>\n\t\tpublic static EFriendRelationship GetFriendRelationship(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendRelationship(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the current status of the specified user</para>\n\t\t/// <para> this will only be known by the local user if steamIDFriend is in their friends list; on the same game server; in a chat room or lobby; or in a small group with the local user</para>\n\t\t/// </summary>\n\t\tpublic static EPersonaState GetFriendPersonaState(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendPersonaState(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the name another user - guaranteed to not be NULL.</para>\n\t\t/// <para> same rules as GetFriendPersonaState() apply as to whether or not the user knowns the name of the other user</para>\n\t\t/// <para> note that on first joining a lobby, chat room or game server the local user will not known the name of the other users automatically; that information will arrive asyncronously</para>\n\t\t/// </summary>\n\t\tpublic static string GetFriendPersonaName(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendPersonaName(CSteamAPIContext.GetSteamFriends(), steamIDFriend));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the friend is actually in a game, and fills in pFriendGameInfo with an extra details</para>\n\t\t/// </summary>\n\t\tpublic static bool GetFriendGamePlayed(CSteamID steamIDFriend, out FriendGameInfo_t pFriendGameInfo) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendGamePlayed(CSteamAPIContext.GetSteamFriends(), steamIDFriend, out pFriendGameInfo);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> accesses old friends names - returns an empty string when their are no more items in the history</para>\n\t\t/// </summary>\n\t\tpublic static string GetFriendPersonaNameHistory(CSteamID steamIDFriend, int iPersonaName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendPersonaNameHistory(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iPersonaName));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> friends steam level</para>\n\t\t/// </summary>\n\t\tpublic static int GetFriendSteamLevel(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendSteamLevel(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns nickname the current user has set for the specified player. Returns NULL if the no nickname has been set for that player.</para>\n\t\t/// <para> DEPRECATED: GetPersonaName follows the Steam nickname preferences, so apps shouldn't need to care about nicknames explicitly.</para>\n\t\t/// </summary>\n\t\tpublic static string GetPlayerNickname(CSteamID steamIDPlayer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetPlayerNickname(CSteamAPIContext.GetSteamFriends(), steamIDPlayer));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> friend grouping (tag) apis</para>\n\t\t/// <para> returns the number of friends groups</para>\n\t\t/// </summary>\n\t\tpublic static int GetFriendsGroupCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendsGroupCount(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the friends group ID for the given index (invalid indices return k_FriendsGroupID_Invalid)</para>\n\t\t/// </summary>\n\t\tpublic static FriendsGroupID_t GetFriendsGroupIDByIndex(int iFG) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (FriendsGroupID_t)NativeMethods.ISteamFriends_GetFriendsGroupIDByIndex(CSteamAPIContext.GetSteamFriends(), iFG);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the name for the given friends group (NULL in the case of invalid friends group IDs)</para>\n\t\t/// </summary>\n\t\tpublic static string GetFriendsGroupName(FriendsGroupID_t friendsGroupID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendsGroupName(CSteamAPIContext.GetSteamFriends(), friendsGroupID));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of members in a given friends group</para>\n\t\t/// </summary>\n\t\tpublic static int GetFriendsGroupMembersCount(FriendsGroupID_t friendsGroupID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendsGroupMembersCount(CSteamAPIContext.GetSteamFriends(), friendsGroupID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets up to nMembersCount members of the given friends group, if fewer exist than requested those positions' SteamIDs will be invalid</para>\n\t\t/// </summary>\n\t\tpublic static void GetFriendsGroupMembersList(FriendsGroupID_t friendsGroupID, CSteamID[] pOutSteamIDMembers, int nMembersCount) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_GetFriendsGroupMembersList(CSteamAPIContext.GetSteamFriends(), friendsGroupID, pOutSteamIDMembers, nMembersCount);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the specified user meets any of the criteria specified in iFriendFlags</para>\n\t\t/// <para> iFriendFlags can be the union (binary or, |) of one or more k_EFriendFlags values</para>\n\t\t/// </summary>\n\t\tpublic static bool HasFriend(CSteamID steamIDFriend, EFriendFlags iFriendFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_HasFriend(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iFriendFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> clan (group) iteration and access functions</para>\n\t\t/// </summary>\n\t\tpublic static int GetClanCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetClanCount(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\tpublic static CSteamID GetClanByIndex(int iClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetClanByIndex(CSteamAPIContext.GetSteamFriends(), iClan);\n\t\t}\n\n\t\tpublic static string GetClanName(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetClanName(CSteamAPIContext.GetSteamFriends(), steamIDClan));\n\t\t}\n\n\t\tpublic static string GetClanTag(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetClanTag(CSteamAPIContext.GetSteamFriends(), steamIDClan));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the most recent information we have about what's happening in a clan</para>\n\t\t/// </summary>\n\t\tpublic static bool GetClanActivityCounts(CSteamID steamIDClan, out int pnOnline, out int pnInGame, out int pnChatting) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetClanActivityCounts(CSteamAPIContext.GetSteamFriends(), steamIDClan, out pnOnline, out pnInGame, out pnChatting);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> for clans a user is a member of, they will have reasonably up-to-date information, but for others you'll have to download the info to have the latest</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t DownloadClanActivityCounts(CSteamID[] psteamIDClans, int cClansToRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_DownloadClanActivityCounts(CSteamAPIContext.GetSteamFriends(), psteamIDClans, cClansToRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> iterators for getting users in a chat room, lobby, game server or clan</para>\n\t\t/// <para> note that large clans that cannot be iterated by the local user</para>\n\t\t/// <para> note that the current user must be in a lobby to retrieve CSteamIDs of other users in that lobby</para>\n\t\t/// <para> steamIDSource can be the steamID of a group, game server, lobby or chat room</para>\n\t\t/// </summary>\n\t\tpublic static int GetFriendCountFromSource(CSteamID steamIDSource) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendCountFromSource(CSteamAPIContext.GetSteamFriends(), steamIDSource);\n\t\t}\n\n\t\tpublic static CSteamID GetFriendFromSourceByIndex(CSteamID steamIDSource, int iFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetFriendFromSourceByIndex(CSteamAPIContext.GetSteamFriends(), steamIDSource, iFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the local user can see that steamIDUser is a member or in steamIDSource</para>\n\t\t/// </summary>\n\t\tpublic static bool IsUserInSource(CSteamID steamIDUser, CSteamID steamIDSource) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_IsUserInSource(CSteamAPIContext.GetSteamFriends(), steamIDUser, steamIDSource);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> User is in a game pressing the talk button (will suppress the microphone for all voice comms from the Steam friends UI)</para>\n\t\t/// </summary>\n\t\tpublic static void SetInGameVoiceSpeaking(CSteamID steamIDUser, bool bSpeaking) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_SetInGameVoiceSpeaking(CSteamAPIContext.GetSteamFriends(), steamIDUser, bSpeaking);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> activates the game overlay, with an optional dialog to open</para>\n\t\t/// <para> valid options include \"Friends\", \"Community\", \"Players\", \"Settings\", \"OfficialGameGroup\", \"Stats\", \"Achievements\",</para>\n\t\t/// <para> \"chatroomgroup/nnnn\"</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateGameOverlay(string pchDialog) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDialog2 = new InteropHelp.UTF8StringHandle(pchDialog)) {\n\t\t\t\tNativeMethods.ISteamFriends_ActivateGameOverlay(CSteamAPIContext.GetSteamFriends(), pchDialog2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> activates game overlay to a specific place</para>\n\t\t/// <para> valid options are</para>\n\t\t/// <para>\t\t\"steamid\" - opens the overlay web browser to the specified user or groups profile</para>\n\t\t/// <para>\t\t\"chat\" - opens a chat window to the specified user, or joins the group chat</para>\n\t\t/// <para>\t\t\"jointrade\" - opens a window to a Steam Trading session that was started with the ISteamEconomy/StartTrade Web API</para>\n\t\t/// <para>\t\t\"stats\" - opens the overlay web browser to the specified user's stats</para>\n\t\t/// <para>\t\t\"achievements\" - opens the overlay web browser to the specified user's achievements</para>\n\t\t/// <para>\t\t\"friendadd\" - opens the overlay in minimal mode prompting the user to add the target user as a friend</para>\n\t\t/// <para>\t\t\"friendremove\" - opens the overlay in minimal mode prompting the user to remove the target friend</para>\n\t\t/// <para>\t\t\"friendrequestaccept\" - opens the overlay in minimal mode prompting the user to accept an incoming friend invite</para>\n\t\t/// <para>\t\t\"friendrequestignore\" - opens the overlay in minimal mode prompting the user to ignore an incoming friend invite</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateGameOverlayToUser(string pchDialog, CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDialog2 = new InteropHelp.UTF8StringHandle(pchDialog)) {\n\t\t\t\tNativeMethods.ISteamFriends_ActivateGameOverlayToUser(CSteamAPIContext.GetSteamFriends(), pchDialog2, steamID);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> activates game overlay web browser directly to the specified URL</para>\n\t\t/// <para> full address with protocol type is required, e.g. http://www.steamgames.com/</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateGameOverlayToWebPage(string pchURL, EActivateGameOverlayToWebPageMode eMode = EActivateGameOverlayToWebPageMode.k_EActivateGameOverlayToWebPageMode_Default) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchURL2 = new InteropHelp.UTF8StringHandle(pchURL)) {\n\t\t\t\tNativeMethods.ISteamFriends_ActivateGameOverlayToWebPage(CSteamAPIContext.GetSteamFriends(), pchURL2, eMode);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> activates game overlay to store page for app</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateGameOverlayToStore(AppId_t nAppID, EOverlayToStoreFlag eFlag) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_ActivateGameOverlayToStore(CSteamAPIContext.GetSteamFriends(), nAppID, eFlag);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Mark a target user as 'played with'. This is a client-side only feature that requires that the calling user is</para>\n\t\t/// <para> in game</para>\n\t\t/// </summary>\n\t\tpublic static void SetPlayedWith(CSteamID steamIDUserPlayedWith) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_SetPlayedWith(CSteamAPIContext.GetSteamFriends(), steamIDUserPlayedWith);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> activates game overlay to open the invite dialog. Invitations will be sent for the provided lobby.</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateGameOverlayInviteDialog(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_ActivateGameOverlayInviteDialog(CSteamAPIContext.GetSteamFriends(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets the small (32x32) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set</para>\n\t\t/// </summary>\n\t\tpublic static int GetSmallFriendAvatar(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetSmallFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets the medium (64x64) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set</para>\n\t\t/// </summary>\n\t\tpublic static int GetMediumFriendAvatar(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetMediumFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets the large (184x184) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set</para>\n\t\t/// <para> returns -1 if this image has yet to be loaded, in this case wait for a AvatarImageLoaded_t callback and then call this again</para>\n\t\t/// </summary>\n\t\tpublic static int GetLargeFriendAvatar(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetLargeFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> requests information about a user - persona name &amp; avatar</para>\n\t\t/// <para> if bRequireNameOnly is set, then the avatar of a user isn't downloaded</para>\n\t\t/// <para> - it's a lot slower to download avatars and churns the local cache, so if you don't need avatars, don't request them</para>\n\t\t/// <para> if returns true, it means that data is being requested, and a PersonaStateChanged_t callback will be posted when it's retrieved</para>\n\t\t/// <para> if returns false, it means that we already have all the details about that user, and functions can be called immediately</para>\n\t\t/// </summary>\n\t\tpublic static bool RequestUserInformation(CSteamID steamIDUser, bool bRequireNameOnly) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_RequestUserInformation(CSteamAPIContext.GetSteamFriends(), steamIDUser, bRequireNameOnly);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> requests information about a clan officer list</para>\n\t\t/// <para> when complete, data is returned in ClanOfficerListResponse_t call result</para>\n\t\t/// <para> this makes available the calls below</para>\n\t\t/// <para> you can only ask about clans that a user is a member of</para>\n\t\t/// <para> note that this won't download avatars automatically; if you get an officer,</para>\n\t\t/// <para> and no avatar image is available, call RequestUserInformation( steamID, false ) to download the avatar</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestClanOfficerList(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_RequestClanOfficerList(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> iteration of clan officers - can only be done when a RequestClanOfficerList() call has completed</para>\n\t\t/// <para> returns the steamID of the clan owner</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetClanOwner(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetClanOwner(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of officers in a clan (including the owner)</para>\n\t\t/// </summary>\n\t\tpublic static int GetClanOfficerCount(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetClanOfficerCount(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the steamID of a clan officer, by index, of range [0,GetClanOfficerCount)</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetClanOfficerByIndex(CSteamID steamIDClan, int iOfficer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetClanOfficerByIndex(CSteamAPIContext.GetSteamFriends(), steamIDClan, iOfficer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> if current user is chat restricted, he can't send or receive any text/voice chat messages.</para>\n\t\t/// <para> the user can't see custom avatars. But the user can be online and send/recv game invites.</para>\n\t\t/// <para> a chat restricted user can't add friends or join any groups.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetUserRestrictions() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetUserRestrictions(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Rich Presence data is automatically shared between friends who are in the same game</para>\n\t\t/// <para> Each user has a set of Key/Value pairs</para>\n\t\t/// <para> Note the following limits: k_cchMaxRichPresenceKeys, k_cchMaxRichPresenceKeyLength, k_cchMaxRichPresenceValueLength</para>\n\t\t/// <para> There are two magic keys:</para>\n\t\t/// <para>\t\t\"status\"  - a UTF-8 string that will show up in the 'view game info' dialog in the Steam friends list</para>\n\t\t/// <para>\t\t\"connect\" - a UTF-8 string that contains the command-line for how a friend can connect to a game</para>\n\t\t/// <para> GetFriendRichPresence() returns an empty string \"\" if no value is set</para>\n\t\t/// <para> SetRichPresence() to a NULL or an empty string deletes the key</para>\n\t\t/// <para> You can iterate the current set of keys for a friend with GetFriendRichPresenceKeyCount()</para>\n\t\t/// <para> and GetFriendRichPresenceKeyByIndex() (typically only used for debugging)</para>\n\t\t/// </summary>\n\t\tpublic static bool SetRichPresence(string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\treturn NativeMethods.ISteamFriends_SetRichPresence(CSteamAPIContext.GetSteamFriends(), pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static void ClearRichPresence() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_ClearRichPresence(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\tpublic static string GetFriendRichPresence(CSteamID steamIDFriend, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendRichPresence(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchKey2));\n\t\t\t}\n\t\t}\n\n\t\tpublic static int GetFriendRichPresenceKeyCount(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendRichPresenceKeyCount(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\tpublic static string GetFriendRichPresenceKeyByIndex(CSteamID steamIDFriend, int iKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendRichPresenceKeyByIndex(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iKey));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Requests rich presence for a specific user.</para>\n\t\t/// </summary>\n\t\tpublic static void RequestFriendRichPresence(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamFriends_RequestFriendRichPresence(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Rich invite support.</para>\n\t\t/// <para> If the target accepts the invite, a GameRichPresenceJoinRequested_t callback is posted containing the connect string.</para>\n\t\t/// <para> (Or you can configure yout game so that it is passed on the command line instead.  This is a deprecated path; ask us if you really need this.)</para>\n\t\t/// <para> Invites can only be sent to friends.</para>\n\t\t/// </summary>\n\t\tpublic static bool InviteUserToGame(CSteamID steamIDFriend, string pchConnectString) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString)) {\n\t\t\t\treturn NativeMethods.ISteamFriends_InviteUserToGame(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchConnectString2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> recently-played-with friends iteration</para>\n\t\t/// <para> this iterates the entire list of users recently played with, across games</para>\n\t\t/// <para> GetFriendCoplayTime() returns as a unix time</para>\n\t\t/// </summary>\n\t\tpublic static int GetCoplayFriendCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetCoplayFriendCount(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\n\t\tpublic static CSteamID GetCoplayFriend(int iCoplayFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetCoplayFriend(CSteamAPIContext.GetSteamFriends(), iCoplayFriend);\n\t\t}\n\n\t\tpublic static int GetFriendCoplayTime(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetFriendCoplayTime(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\tpublic static AppId_t GetFriendCoplayGame(CSteamID steamIDFriend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (AppId_t)NativeMethods.ISteamFriends_GetFriendCoplayGame(CSteamAPIContext.GetSteamFriends(), steamIDFriend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> chat interface for games</para>\n\t\t/// <para> this allows in-game access to group (clan) chats from in the game</para>\n\t\t/// <para> the behavior is somewhat sophisticated, because the user may or may not be already in the group chat from outside the game or in the overlay</para>\n\t\t/// <para> use ActivateGameOverlayToUser( \"chat\", steamIDClan ) to open the in-game overlay version of the chat</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t JoinClanChatRoom(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_JoinClanChatRoom(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\tpublic static bool LeaveClanChatRoom(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_LeaveClanChatRoom(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\tpublic static int GetClanChatMemberCount(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetClanChatMemberCount(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\tpublic static CSteamID GetChatMemberByIndex(CSteamID steamIDClan, int iUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamFriends_GetChatMemberByIndex(CSteamAPIContext.GetSteamFriends(), steamIDClan, iUser);\n\t\t}\n\n\t\tpublic static bool SendClanChatMessage(CSteamID steamIDClanChat, string pchText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchText2 = new InteropHelp.UTF8StringHandle(pchText)) {\n\t\t\t\treturn NativeMethods.ISteamFriends_SendClanChatMessage(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, pchText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static int GetClanChatMessage(CSteamID steamIDClanChat, int iMessage, out string prgchText, int cchTextMax, out EChatEntryType peChatEntryType, out CSteamID psteamidChatter) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr prgchText2 = Marshal.AllocHGlobal(cchTextMax);\n\t\t\tint ret = NativeMethods.ISteamFriends_GetClanChatMessage(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, iMessage, prgchText2, cchTextMax, out peChatEntryType, out psteamidChatter);\n\t\t\tprgchText = ret != 0 ? InteropHelp.PtrToStringUTF8(prgchText2) : null;\n\t\t\tMarshal.FreeHGlobal(prgchText2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool IsClanChatAdmin(CSteamID steamIDClanChat, CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_IsClanChatAdmin(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> interact with the Steam (game overlay / desktop)</para>\n\t\t/// </summary>\n\t\tpublic static bool IsClanChatWindowOpenInSteam(CSteamID steamIDClanChat) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_IsClanChatWindowOpenInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat);\n\t\t}\n\n\t\tpublic static bool OpenClanChatWindowInSteam(CSteamID steamIDClanChat) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_OpenClanChatWindowInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat);\n\t\t}\n\n\t\tpublic static bool CloseClanChatWindowInSteam(CSteamID steamIDClanChat) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_CloseClanChatWindowInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> peer-to-peer chat interception</para>\n\t\t/// <para> this is so you can show P2P chats inline in the game</para>\n\t\t/// </summary>\n\t\tpublic static bool SetListenForFriendsMessages(bool bInterceptEnabled) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_SetListenForFriendsMessages(CSteamAPIContext.GetSteamFriends(), bInterceptEnabled);\n\t\t}\n\n\t\tpublic static bool ReplyToFriendMessage(CSteamID steamIDFriend, string pchMsgToSend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchMsgToSend2 = new InteropHelp.UTF8StringHandle(pchMsgToSend)) {\n\t\t\t\treturn NativeMethods.ISteamFriends_ReplyToFriendMessage(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchMsgToSend2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static int GetFriendMessage(CSteamID steamIDFriend, int iMessageID, out string pvData, int cubData, out EChatEntryType peChatEntryType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pvData2 = Marshal.AllocHGlobal(cubData);\n\t\t\tint ret = NativeMethods.ISteamFriends_GetFriendMessage(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iMessageID, pvData2, cubData, out peChatEntryType);\n\t\t\tpvData = ret != 0 ? InteropHelp.PtrToStringUTF8(pvData2) : null;\n\t\t\tMarshal.FreeHGlobal(pvData2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> following apis</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetFollowerCount(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_GetFollowerCount(CSteamAPIContext.GetSteamFriends(), steamID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t IsFollowing(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_IsFollowing(CSteamAPIContext.GetSteamFriends(), steamID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t EnumerateFollowingList(uint unStartIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamFriends_EnumerateFollowingList(CSteamAPIContext.GetSteamFriends(), unStartIndex);\n\t\t}\n\n\t\tpublic static bool IsClanPublic(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_IsClanPublic(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\tpublic static bool IsClanOfficialGameGroup(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_IsClanOfficialGameGroup(CSteamAPIContext.GetSteamFriends(), steamIDClan);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Return the number of chats (friends or chat rooms) with unread messages.</para>\n\t\t/// <para>/ A \"priority\" message is one that would generate some sort of toast or</para>\n\t\t/// <para>/ notification, and depends on user settings.</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ You can register for UnreadChatMessagesChanged_t callbacks to know when this</para>\n\t\t/// <para>/ has potentially changed.</para>\n\t\t/// </summary>\n\t\tpublic static int GetNumChatsWithUnreadPriorityMessages() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamFriends_GetNumChatsWithUnreadPriorityMessages(CSteamAPIContext.GetSteamFriends());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserver.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServer {\n\t\t/// <summary>\n\t\t/// <para> Basic server data.  These properties, if set, must be set before before calling LogOn.  They</para>\n\t\t/// <para> may not be changed after logged in.</para>\n\t\t/// <para>/ This is called by SteamGameServer_Init, and you will usually not need to call it directly</para>\n\t\t/// </summary>\n\t\tpublic static bool InitGameServer(uint unIP, ushort usGamePort, ushort usQueryPort, uint unFlags, AppId_t nGameAppId, string pchVersionString) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString)) {\n\t\t\t\treturn NativeMethods.ISteamGameServer_InitGameServer(CSteamGameServerAPIContext.GetSteamGameServer(), unIP, usGamePort, usQueryPort, unFlags, nGameAppId, pchVersionString2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Game product identifier.  This is currently used by the master server for version checking purposes.</para>\n\t\t/// <para>/ It's a required field, but will eventually will go away, and the AppID will be used for this purpose.</para>\n\t\t/// </summary>\n\t\tpublic static void SetProduct(string pszProduct) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszProduct2 = new InteropHelp.UTF8StringHandle(pszProduct)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetProduct(CSteamGameServerAPIContext.GetSteamGameServer(), pszProduct2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Description of the game.  This is a required field and is displayed in the steam server browser....for now.</para>\n\t\t/// <para>/ This is a required field, but it will go away eventually, as the data should be determined from the AppID.</para>\n\t\t/// </summary>\n\t\tpublic static void SetGameDescription(string pszGameDescription) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszGameDescription2 = new InteropHelp.UTF8StringHandle(pszGameDescription)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetGameDescription(CSteamGameServerAPIContext.GetSteamGameServer(), pszGameDescription2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ If your game is a \"mod,\" pass the string that identifies it.  The default is an empty string, meaning</para>\n\t\t/// <para>/ this application is the original game, not a mod.</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerGameDir</para>\n\t\t/// </summary>\n\t\tpublic static void SetModDir(string pszModDir) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszModDir2 = new InteropHelp.UTF8StringHandle(pszModDir)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetModDir(CSteamGameServerAPIContext.GetSteamGameServer(), pszModDir2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Is this is a dedicated server?  The default value is false.</para>\n\t\t/// </summary>\n\t\tpublic static void SetDedicatedServer(bool bDedicated) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetDedicatedServer(CSteamGameServerAPIContext.GetSteamGameServer(), bDedicated);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Login</para>\n\t\t/// <para>/ Begin process to login to a persistent game server account</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ You need to register for callbacks to determine the result of this operation.</para>\n\t\t/// <para>/ @see SteamServersConnected_t</para>\n\t\t/// <para>/ @see SteamServerConnectFailure_t</para>\n\t\t/// <para>/ @see SteamServersDisconnected_t</para>\n\t\t/// </summary>\n\t\tpublic static void LogOn(string pszToken) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszToken2 = new InteropHelp.UTF8StringHandle(pszToken)) {\n\t\t\t\tNativeMethods.ISteamGameServer_LogOn(CSteamGameServerAPIContext.GetSteamGameServer(), pszToken2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Login to a generic, anonymous account.</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ Note: in previous versions of the SDK, this was automatically called within SteamGameServer_Init,</para>\n\t\t/// <para>/ but this is no longer the case.</para>\n\t\t/// </summary>\n\t\tpublic static void LogOnAnonymous() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_LogOnAnonymous(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Begin process of logging game server out of steam</para>\n\t\t/// </summary>\n\t\tpublic static void LogOff() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_LogOff(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> status functions</para>\n\t\t/// </summary>\n\t\tpublic static bool BLoggedOn() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_BLoggedOn(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\tpublic static bool BSecure() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_BSecure(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\tpublic static CSteamID GetSteamID() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (CSteamID)NativeMethods.ISteamGameServer_GetSteamID(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Returns true if the master server has requested a restart.</para>\n\t\t/// <para>/ Only returns true once per request.</para>\n\t\t/// </summary>\n\t\tpublic static bool WasRestartRequested() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_WasRestartRequested(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Server state.  These properties may be changed at any time.</para>\n\t\t/// <para>/ Max player count that will be reported to server browser and client queries</para>\n\t\t/// </summary>\n\t\tpublic static void SetMaxPlayerCount(int cPlayersMax) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetMaxPlayerCount(CSteamGameServerAPIContext.GetSteamGameServer(), cPlayersMax);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Number of bots.  Default value is zero</para>\n\t\t/// </summary>\n\t\tpublic static void SetBotPlayerCount(int cBotplayers) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetBotPlayerCount(CSteamGameServerAPIContext.GetSteamGameServer(), cBotplayers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Set the name of server as it will appear in the server browser</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerName</para>\n\t\t/// </summary>\n\t\tpublic static void SetServerName(string pszServerName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszServerName2 = new InteropHelp.UTF8StringHandle(pszServerName)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetServerName(CSteamGameServerAPIContext.GetSteamGameServer(), pszServerName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Set name of map to report in the server browser</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerName</para>\n\t\t/// </summary>\n\t\tpublic static void SetMapName(string pszMapName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszMapName2 = new InteropHelp.UTF8StringHandle(pszMapName)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetMapName(CSteamGameServerAPIContext.GetSteamGameServer(), pszMapName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Let people know if your server will require a password</para>\n\t\t/// </summary>\n\t\tpublic static void SetPasswordProtected(bool bPasswordProtected) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetPasswordProtected(CSteamGameServerAPIContext.GetSteamGameServer(), bPasswordProtected);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Spectator server.  The default value is zero, meaning the service</para>\n\t\t/// <para>/ is not used.</para>\n\t\t/// </summary>\n\t\tpublic static void SetSpectatorPort(ushort unSpectatorPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetSpectatorPort(CSteamGameServerAPIContext.GetSteamGameServer(), unSpectatorPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Name of the spectator server.  (Only used if spectator port is nonzero.)</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerMapName</para>\n\t\t/// </summary>\n\t\tpublic static void SetSpectatorServerName(string pszSpectatorServerName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszSpectatorServerName2 = new InteropHelp.UTF8StringHandle(pszSpectatorServerName)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetSpectatorServerName(CSteamGameServerAPIContext.GetSteamGameServer(), pszSpectatorServerName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Call this to clear the whole list of key/values that are sent in rules queries.</para>\n\t\t/// </summary>\n\t\tpublic static void ClearAllKeyValues() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_ClearAllKeyValues(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Call this to add/update a key/value pair.</para>\n\t\t/// </summary>\n\t\tpublic static void SetKeyValue(string pKey, string pValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pKey2 = new InteropHelp.UTF8StringHandle(pKey))\n\t\t\tusing (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetKeyValue(CSteamGameServerAPIContext.GetSteamGameServer(), pKey2, pValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Sets a string defining the \"gametags\" for this server, this is optional, but if it is set</para>\n\t\t/// <para>/ it allows users to filter in the matchmaking/server-browser interfaces based on the value</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerTags</para>\n\t\t/// </summary>\n\t\tpublic static void SetGameTags(string pchGameTags) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchGameTags2 = new InteropHelp.UTF8StringHandle(pchGameTags)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetGameTags(CSteamGameServerAPIContext.GetSteamGameServer(), pchGameTags2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Sets a string defining the \"gamedata\" for this server, this is optional, but if it is set</para>\n\t\t/// <para>/ it allows users to filter in the matchmaking/server-browser interfaces based on the value</para>\n\t\t/// <para>/ don't set this unless it actually changes, its only uploaded to the master once (when</para>\n\t\t/// <para>/ acknowledged)</para>\n\t\t/// <para>/</para>\n\t\t/// <para>/ @see k_cbMaxGameServerGameData</para>\n\t\t/// </summary>\n\t\tpublic static void SetGameData(string pchGameData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchGameData2 = new InteropHelp.UTF8StringHandle(pchGameData)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetGameData(CSteamGameServerAPIContext.GetSteamGameServer(), pchGameData2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/ Region identifier.  This is an optional field, the default value is empty, meaning the \"world\" region</para>\n\t\t/// </summary>\n\t\tpublic static void SetRegion(string pszRegion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszRegion2 = new InteropHelp.UTF8StringHandle(pszRegion)) {\n\t\t\t\tNativeMethods.ISteamGameServer_SetRegion(CSteamGameServerAPIContext.GetSteamGameServer(), pszRegion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Player list management / authentication</para>\n\t\t/// <para> Handles receiving a new connection from a Steam user.  This call will ask the Steam</para>\n\t\t/// <para> servers to validate the users identity, app ownership, and VAC status.  If the Steam servers</para>\n\t\t/// <para> are off-line, then it will validate the cached ticket itself which will validate app ownership</para>\n\t\t/// <para> and identity.  The AuthBlob here should be acquired on the game client using SteamUser()-&gt;InitiateGameConnection()</para>\n\t\t/// <para> and must then be sent up to the game server for authentication.</para>\n\t\t/// <para> Return Value: returns true if the users ticket passes basic checks. pSteamIDUser will contain the Steam ID of this user. pSteamIDUser must NOT be NULL</para>\n\t\t/// <para> If the call succeeds then you should expect a GSClientApprove_t or GSClientDeny_t callback which will tell you whether authentication</para>\n\t\t/// <para> for the user has succeeded or failed (the steamid in the callback will match the one returned by this call)</para>\n\t\t/// </summary>\n\t\tpublic static bool SendUserConnectAndAuthenticate(uint unIPClient, byte[] pvAuthBlob, uint cubAuthBlobSize, out CSteamID pSteamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_SendUserConnectAndAuthenticate(CSteamGameServerAPIContext.GetSteamGameServer(), unIPClient, pvAuthBlob, cubAuthBlobSize, out pSteamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Creates a fake user (ie, a bot) which will be listed as playing on the server, but skips validation.</para>\n\t\t/// <para> Return Value: Returns a SteamID for the user to be tracked with, you should call HandleUserDisconnect()</para>\n\t\t/// <para> when this user leaves the server just like you would for a real user.</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID CreateUnauthenticatedUserConnection() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (CSteamID)NativeMethods.ISteamGameServer_CreateUnauthenticatedUserConnection(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Should be called whenever a user leaves our game server, this lets Steam internally</para>\n\t\t/// <para> track which users are currently on which servers for the purposes of preventing a single</para>\n\t\t/// <para> account being logged into multiple servers, showing who is currently on a server, etc.</para>\n\t\t/// </summary>\n\t\tpublic static void SendUserDisconnect(CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SendUserDisconnect(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Update the data to be displayed in the server browser and matchmaking interfaces for a user</para>\n\t\t/// <para> currently connected to the server.  For regular users you must call this after you receive a</para>\n\t\t/// <para> GSUserValidationSuccess callback.</para>\n\t\t/// <para> Return Value: true if successful, false if failure (ie, steamIDUser wasn't for an active player)</para>\n\t\t/// </summary>\n\t\tpublic static bool BUpdateUserData(CSteamID steamIDUser, string pchPlayerName, uint uScore) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPlayerName2 = new InteropHelp.UTF8StringHandle(pchPlayerName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServer_BUpdateUserData(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser, pchPlayerName2, uScore);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> New auth system APIs - do not mix with the old auth system APIs.</para>\n\t\t/// <para> ----------------------------------------------------------------</para>\n\t\t/// <para> Retrieve ticket to be sent to the entity who wishes to authenticate you ( using BeginAuthSession API ).</para>\n\t\t/// <para> pcbTicket retrieves the length of the actual ticket.</para>\n\t\t/// </summary>\n\t\tpublic static HAuthTicket GetAuthSessionTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (HAuthTicket)NativeMethods.ISteamGameServer_GetAuthSessionTicket(CSteamGameServerAPIContext.GetSteamGameServer(), pTicket, cbMaxTicket, out pcbTicket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Authenticate ticket ( from GetAuthSessionTicket ) from entity steamID to be sure it is valid and isnt reused</para>\n\t\t/// <para> Registers for callbacks if the entity goes offline or cancels the ticket ( see ValidateAuthTicketResponse_t callback and EAuthSessionResponse )</para>\n\t\t/// </summary>\n\t\tpublic static EBeginAuthSessionResult BeginAuthSession(byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_BeginAuthSession(CSteamGameServerAPIContext.GetSteamGameServer(), pAuthTicket, cbAuthTicket, steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Stop tracking started by BeginAuthSession - called when no longer playing game with this entity</para>\n\t\t/// </summary>\n\t\tpublic static void EndAuthSession(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_EndAuthSession(CSteamGameServerAPIContext.GetSteamGameServer(), steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Cancel auth ticket from GetAuthSessionTicket, called when no longer playing game with the entity you gave the ticket to</para>\n\t\t/// </summary>\n\t\tpublic static void CancelAuthTicket(HAuthTicket hAuthTicket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_CancelAuthTicket(CSteamGameServerAPIContext.GetSteamGameServer(), hAuthTicket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> After receiving a user's authentication data, and passing it to SendUserConnectAndAuthenticate, use this function</para>\n\t\t/// <para> to determine if the user owns downloadable content specified by the provided AppID.</para>\n\t\t/// </summary>\n\t\tpublic static EUserHasLicenseForAppResult UserHasLicenseForApp(CSteamID steamID, AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_UserHasLicenseForApp(CSteamGameServerAPIContext.GetSteamGameServer(), steamID, appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Ask if a user in in the specified group, results returns async by GSUserGroupStatus_t</para>\n\t\t/// <para> returns false if we're not connected to the steam servers and thus cannot ask</para>\n\t\t/// </summary>\n\t\tpublic static bool RequestUserGroupStatus(CSteamID steamIDUser, CSteamID steamIDGroup) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_RequestUserGroupStatus(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser, steamIDGroup);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> these two functions s are deprecated, and will not return results</para>\n\t\t/// <para> they will be removed in a future version of the SDK</para>\n\t\t/// </summary>\n\t\tpublic static void GetGameplayStats() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_GetGameplayStats(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetServerReputation() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamGameServer_GetServerReputation(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the public IP of the server according to Steam, useful when the server is</para>\n\t\t/// <para> behind NAT and you want to advertise its IP in a lobby for other clients to directly</para>\n\t\t/// <para> connect to</para>\n\t\t/// </summary>\n\t\tpublic static uint GetPublicIP() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_GetPublicIP(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> These are in GameSocketShare mode, where instead of ISteamGameServer creating its own</para>\n\t\t/// <para> socket to talk to the master server on, it lets the game use its socket to forward messages</para>\n\t\t/// <para> back and forth. This prevents us from requiring server ops to open up yet another port</para>\n\t\t/// <para> in their firewalls.</para>\n\t\t/// <para> the IP address and port should be in host order, i.e 127.0.0.1 == 0x7f000001</para>\n\t\t/// <para> These are used when you've elected to multiplex the game server's UDP socket</para>\n\t\t/// <para> rather than having the master server updater use its own sockets.</para>\n\t\t/// <para> Source games use this to simplify the job of the server admins, so they</para>\n\t\t/// <para> don't have to open up more ports on their firewalls.</para>\n\t\t/// <para> Call this when a packet that starts with 0xFFFFFFFF comes in. That means</para>\n\t\t/// <para> it's for us.</para>\n\t\t/// </summary>\n\t\tpublic static bool HandleIncomingPacket(byte[] pData, int cbData, uint srcIP, ushort srcPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_HandleIncomingPacket(CSteamGameServerAPIContext.GetSteamGameServer(), pData, cbData, srcIP, srcPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> AFTER calling HandleIncomingPacket for any packets that came in that frame, call this.</para>\n\t\t/// <para> This gets a packet that the master server updater needs to send out on UDP.</para>\n\t\t/// <para> It returns the length of the packet it wants to send, or 0 if there are no more packets to send.</para>\n\t\t/// <para> Call this each frame until it returns 0.</para>\n\t\t/// </summary>\n\t\tpublic static int GetNextOutgoingPacket(byte[] pOut, int cbMaxOut, out uint pNetAdr, out ushort pPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamGameServer_GetNextOutgoingPacket(CSteamGameServerAPIContext.GetSteamGameServer(), pOut, cbMaxOut, out pNetAdr, out pPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Control heartbeats / advertisement with master server</para>\n\t\t/// <para> Call this as often as you like to tell the master server updater whether or not</para>\n\t\t/// <para> you want it to be active (default: off).</para>\n\t\t/// </summary>\n\t\tpublic static void EnableHeartbeats(bool bActive) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_EnableHeartbeats(CSteamGameServerAPIContext.GetSteamGameServer(), bActive);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> You usually don't need to modify this.</para>\n\t\t/// <para> Pass -1 to use the default value for iHeartbeatInterval.</para>\n\t\t/// <para> Some mods change this.</para>\n\t\t/// </summary>\n\t\tpublic static void SetHeartbeatInterval(int iHeartbeatInterval) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_SetHeartbeatInterval(CSteamGameServerAPIContext.GetSteamGameServer(), iHeartbeatInterval);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Force a heartbeat to steam at the next opportunity</para>\n\t\t/// </summary>\n\t\tpublic static void ForceHeartbeat() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamGameServer_ForceHeartbeat(CSteamGameServerAPIContext.GetSteamGameServer());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> associate this game server with this clan for the purposes of computing player compat</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AssociateWithClan(CSteamID steamIDClan) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamGameServer_AssociateWithClan(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDClan);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ask if any of the current players dont want to play with this new player - or vice versa</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t ComputeNewPlayerCompatibility(CSteamID steamIDNewPlayer) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamGameServer_ComputeNewPlayerCompatibility(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDNewPlayer);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverapps.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerApps {\n\t\tpublic static bool BIsSubscribed() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribed(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsLowViolence() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsLowViolence(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsCybercafe() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsCybercafe(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static bool BIsVACBanned() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsVACBanned(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static string GetCurrentGameLanguage() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetCurrentGameLanguage(CSteamGameServerAPIContext.GetSteamApps()));\n\t\t}\n\n\t\tpublic static string GetAvailableGameLanguages() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetAvailableGameLanguages(CSteamGameServerAPIContext.GetSteamApps()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> only use this member if you need to check ownership of another game related to yours, a demo for example</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedApp(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedApp(CSteamGameServerAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Takes AppID of DLC and checks if the user owns the DLC &amp; if the DLC is installed</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsDlcInstalled(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsDlcInstalled(CSteamGameServerAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the Unix time of the purchase of the app</para>\n\t\t/// </summary>\n\t\tpublic static uint GetEarliestPurchaseUnixTime(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_GetEarliestPurchaseUnixTime(CSteamGameServerAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Checks if the user is subscribed to the current app through a free weekend</para>\n\t\t/// <para> This function will return false for users who have a retail or other type of license</para>\n\t\t/// <para> Before using, please ask your Valve technical contact how to package and secure your free weekened</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedFromFreeWeekend() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedFromFreeWeekend(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the number of DLC pieces for the running app</para>\n\t\t/// </summary>\n\t\tpublic static int GetDLCCount() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_GetDLCCount(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns metadata for DLC by index, of range [0, GetDLCCount()]</para>\n\t\t/// </summary>\n\t\tpublic static bool BGetDLCDataByIndex(int iDLC, out AppId_t pAppID, out bool pbAvailable, out string pchName, int cchNameBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamApps_BGetDLCDataByIndex(CSteamGameServerAPIContext.GetSteamApps(), iDLC, out pAppID, out pbAvailable, pchName2, cchNameBufferSize);\n\t\t\tpchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Install/Uninstall control for optional DLC</para>\n\t\t/// </summary>\n\t\tpublic static void InstallDLC(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamApps_InstallDLC(CSteamGameServerAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\tpublic static void UninstallDLC(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamApps_UninstallDLC(CSteamGameServerAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request legacy cd-key for yourself or owned DLC. If you are interested in this</para>\n\t\t/// <para> data then make sure you provide us with a list of valid keys to be distributed</para>\n\t\t/// <para> to users when they purchase the game, before the game ships.</para>\n\t\t/// <para> You'll receive an AppProofOfPurchaseKeyResponse_t callback when</para>\n\t\t/// <para> the key is available (which may be immediately).</para>\n\t\t/// </summary>\n\t\tpublic static void RequestAppProofOfPurchaseKey(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamApps_RequestAppProofOfPurchaseKey(CSteamGameServerAPIContext.GetSteamApps(), nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns current beta branch name, 'public' is the default branch</para>\n\t\t/// </summary>\n\t\tpublic static bool GetCurrentBetaName(out string pchName, int cchNameBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamApps_GetCurrentBetaName(CSteamGameServerAPIContext.GetSteamApps(), pchName2, cchNameBufferSize);\n\t\t\tpchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> signal Steam that game files seems corrupt or missing</para>\n\t\t/// </summary>\n\t\tpublic static bool MarkContentCorrupt(bool bMissingFilesOnly) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_MarkContentCorrupt(CSteamGameServerAPIContext.GetSteamApps(), bMissingFilesOnly);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return installed depots in mount order</para>\n\t\t/// </summary>\n\t\tpublic static uint GetInstalledDepots(AppId_t appID, DepotId_t[] pvecDepots, uint cMaxDepots) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_GetInstalledDepots(CSteamGameServerAPIContext.GetSteamApps(), appID, pvecDepots, cMaxDepots);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns current app install folder for AppID, returns folder name length</para>\n\t\t/// </summary>\n\t\tpublic static uint GetAppInstallDir(AppId_t appID, out string pchFolder, uint cchFolderBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderBufferSize);\n\t\t\tuint ret = NativeMethods.ISteamApps_GetAppInstallDir(CSteamGameServerAPIContext.GetSteamApps(), appID, pchFolder2, cchFolderBufferSize);\n\t\t\tpchFolder = ret != 0 ? InteropHelp.PtrToStringUTF8(pchFolder2) : null;\n\t\t\tMarshal.FreeHGlobal(pchFolder2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if that app is installed (not necessarily owned)</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsAppInstalled(AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsAppInstalled(CSteamGameServerAPIContext.GetSteamApps(), appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the SteamID of the original owner. If this CSteamID is different from ISteamUser::GetSteamID(),</para>\n\t\t/// <para> the user has a temporary license borrowed via Family Sharing</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetAppOwner() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (CSteamID)NativeMethods.ISteamApps_GetAppOwner(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated launch param if the game is run via steam://run/&lt;appid&gt;//?param1=value1&amp;param2=value2&amp;param3=value3 etc.</para>\n\t\t/// <para> Parameter names starting with the character '@' are reserved for internal use and will always return and empty string.</para>\n\t\t/// <para> Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried by the game,</para>\n\t\t/// <para> but it is advised that you not param names beginning with an underscore for your own features.</para>\n\t\t/// <para> Check for new launch parameters on callback NewUrlLaunchParameters_t</para>\n\t\t/// </summary>\n\t\tpublic static string GetLaunchQueryParam(string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetLaunchQueryParam(CSteamGameServerAPIContext.GetSteamApps(), pchKey2));\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get download progress for optional DLC</para>\n\t\t/// </summary>\n\t\tpublic static bool GetDlcDownloadProgress(AppId_t nAppID, out ulong punBytesDownloaded, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_GetDlcDownloadProgress(CSteamGameServerAPIContext.GetSteamApps(), nAppID, out punBytesDownloaded, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return the buildid of this app, may change at any time based on backend updates to the game</para>\n\t\t/// </summary>\n\t\tpublic static int GetAppBuildId() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_GetAppBuildId(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request all proof of purchase keys for the calling appid and asociated DLC.</para>\n\t\t/// <para> A series of AppProofOfPurchaseKeyResponse_t callbacks will be sent with</para>\n\t\t/// <para> appropriate appid values, ending with a final callback where the m_nAppId</para>\n\t\t/// <para> member is k_uAppIdInvalid (zero).</para>\n\t\t/// </summary>\n\t\tpublic static void RequestAllProofOfPurchaseKeys() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamApps_RequestAllProofOfPurchaseKeys(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetFileDetails(string pszFileName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszFileName2 = new InteropHelp.UTF8StringHandle(pszFileName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamApps_GetFileDetails(CSteamGameServerAPIContext.GetSteamApps(), pszFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get command line if game was launched via Steam URL, e.g. steam://run/&lt;appid&gt;//&lt;command line&gt;/.</para>\n\t\t/// <para> This method of passing a connect string (used when joining via rich presence, accepting an</para>\n\t\t/// <para> invite, etc) is preferable to passing the connect string on the operating system command</para>\n\t\t/// <para> line, which is a security risk.  In order for rich presence joins to go through this</para>\n\t\t/// <para> path and not be placed on the OS command line, you must set a value in your app's</para>\n\t\t/// <para> configuration on Steam.  Ask Valve for help with this.</para>\n\t\t/// <para> If game was already running and launched again, the NewUrlLaunchParameters_t will be fired.</para>\n\t\t/// </summary>\n\t\tpublic static int GetLaunchCommandLine(out string pszCommandLine, int cubCommandLine) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pszCommandLine2 = Marshal.AllocHGlobal(cubCommandLine);\n\t\t\tint ret = NativeMethods.ISteamApps_GetLaunchCommandLine(CSteamGameServerAPIContext.GetSteamApps(), pszCommandLine2, cubCommandLine);\n\t\t\tpszCommandLine = ret != -1 ? InteropHelp.PtrToStringUTF8(pszCommandLine2) : null;\n\t\t\tMarshal.FreeHGlobal(pszCommandLine2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender SteamID</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsSubscribedFromFamilySharing() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamApps_BIsSubscribedFromFamilySharing(CSteamGameServerAPIContext.GetSteamApps());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverclient.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerClient {\n\t\t/// <summary>\n\t\t/// <para> Creates a communication pipe to the Steam client.</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamPipe CreateSteamPipe() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (HSteamPipe)NativeMethods.ISteamClient_CreateSteamPipe(CSteamGameServerAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Releases a previously created communications pipe</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static bool BReleaseSteamPipe(HSteamPipe hSteamPipe) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamClient_BReleaseSteamPipe(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> connects to an existing global user, failing if none exists</para>\n\t\t/// <para> used by the game to coordinate with the steamUI</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamUser ConnectToGlobalUser(HSteamPipe hSteamPipe) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (HSteamUser)NativeMethods.ISteamClient_ConnectToGlobalUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> used by game servers, create a steam user that won't be shared with anyone else</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static HSteamUser CreateLocalUser(out HSteamPipe phSteamPipe, EAccountType eAccountType) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (HSteamUser)NativeMethods.ISteamClient_CreateLocalUser(CSteamGameServerAPIContext.GetSteamClient(), out phSteamPipe, eAccountType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> removes an allocated user</para>\n\t\t/// <para> NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling</para>\n\t\t/// </summary>\n\t\tpublic static void ReleaseUser(HSteamPipe hSteamPipe, HSteamUser hUser) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamClient_ReleaseUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe, hUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves the ISteamUser interface associated with the handle</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUser(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves the ISteamGameServer interface associated with the handle</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameServer(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameServer(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set the local IP and Port to bind to</para>\n\t\t/// <para> this must be set before CreateLocalUser()</para>\n\t\t/// </summary>\n\t\tpublic static void SetLocalIPBinding(uint unIP, ushort usPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamClient_SetLocalIPBinding(CSteamGameServerAPIContext.GetSteamClient(), unIP, usPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamFriends interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamFriends(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamFriends(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamUtils interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUtils(HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUtils(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamMatchmaking interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMatchmaking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMatchmaking(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamMatchmakingServers interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMatchmakingServers(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMatchmakingServers(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the a generic interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGenericInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGenericInterface(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamUserStats interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUserStats(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUserStats(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the ISteamGameServerStats interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameServerStats(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameServerStats(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns apps interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamApps(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamApps(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> networking</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamNetworking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamNetworking(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remote storage</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamRemoteStorage(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamRemoteStorage(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> user screenshots</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamScreenshots(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamScreenshots(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> game search</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamGameSearch(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamGameSearch(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of IPC calls made since the last time this function was called</para>\n\t\t/// <para> Used for perf debugging so you can understand how many IPC calls your game makes per frame</para>\n\t\t/// <para> Every IPC call is at minimum a thread context switch if not a process one so you want to rate</para>\n\t\t/// <para> control how often you do them.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetIPCCallCount() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamClient_GetIPCCallCount(CSteamGameServerAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API warning handling</para>\n\t\t/// <para> 'int' is the severity; 0 for msg, 1 for warning</para>\n\t\t/// <para> 'const char *' is the text of the message</para>\n\t\t/// <para> callbacks will occur directly after the API function is called that generated the warning or message.</para>\n\t\t/// </summary>\n\t\tpublic static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamClient_SetWarningMessageHook(CSteamGameServerAPIContext.GetSteamClient(), pFunction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger global shutdown for the DLL</para>\n\t\t/// </summary>\n\t\tpublic static bool BShutdownIfAllPipesClosed() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamClient_BShutdownIfAllPipesClosed(CSteamGameServerAPIContext.GetSteamClient());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Expose HTTP interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamHTTP(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamHTTP(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the ISteamController interface - deprecated in favor of Steam Input</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamController(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamController(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the ISteamUGC interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamUGC(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns app list interface, only available on specially registered apps</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamAppList(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamAppList(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Music Player</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMusic(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMusic(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Music Player Remote</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamMusicRemote(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamMusicRemote(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> html page display</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamHTMLSurface(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> inventory</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamInventory(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamInventory(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Video</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamVideo(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamVideo(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Parental controls</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamParentalSettings(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamParentalSettings(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Exposes the Steam Input interface for controller support</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamInput(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamInput(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Parties interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamParties(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamParties(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Remote Play interface</para>\n\t\t/// </summary>\n\t\tpublic static IntPtr GetISteamRemotePlay(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) {\n\t\t\t\treturn NativeMethods.ISteamClient_GetISteamRemotePlay(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2);\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverhttp.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerHTTP {\n\t\t/// <summary>\n\t\t/// <para> Initializes a new HTTP request, returning a handle to use in further operations on it.  Requires</para>\n\t\t/// <para> the method (GET or POST) and the absolute URL for the request.  Both http and https are supported,</para>\n\t\t/// <para> so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/</para>\n\t\t/// <para> or such.</para>\n\t\t/// </summary>\n\t\tpublic static HTTPRequestHandle CreateHTTPRequest(EHTTPMethod eHTTPRequestMethod, string pchAbsoluteURL) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchAbsoluteURL2 = new InteropHelp.UTF8StringHandle(pchAbsoluteURL)) {\n\t\t\t\treturn (HTTPRequestHandle)NativeMethods.ISteamHTTP_CreateHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), eHTTPRequestMethod, pchAbsoluteURL2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after</para>\n\t\t/// <para> sending the request.  This is just so the caller can easily keep track of which callbacks go with which request data.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestContextValue(HTTPRequestHandle hRequest, ulong ulContextValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestContextValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, ulContextValue);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a timeout in seconds for the HTTP request, must be called prior to sending the request.  Default</para>\n\t\t/// <para> timeout is 60 seconds if you don't call this.  Returns false if the handle is invalid, or the request</para>\n\t\t/// <para> has already been sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestNetworkActivityTimeout(HTTPRequestHandle hRequest, uint unTimeoutSeconds) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, unTimeoutSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a request header value for the request, must be called prior to sending the request.  Will</para>\n\t\t/// <para> return false if the handle is invalid or the request is already sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, string pchHeaderValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName))\n\t\t\tusing (var pchHeaderValue2 = new InteropHelp.UTF8StringHandle(pchHeaderValue)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestHeaderValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pchHeaderValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified</para>\n\t\t/// <para> when creating the request.  Must be called prior to sending the request.  Will return false if the</para>\n\t\t/// <para> handle is invalid or the request is already sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestGetOrPostParameter(HTTPRequestHandle hRequest, string pchParamName, string pchParamValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchParamName2 = new InteropHelp.UTF8StringHandle(pchParamName))\n\t\t\tusing (var pchParamValue2 = new InteropHelp.UTF8StringHandle(pchParamValue)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestGetOrPostParameter(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchParamName2, pchParamValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on</para>\n\t\t/// <para> asynchronous response via callback.</para>\n\t\t/// <para> Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control</para>\n\t\t/// <para> header and only do a local cache lookup rather than sending any actual remote request.</para>\n\t\t/// </summary>\n\t\tpublic static bool SendHTTPRequest(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SendHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pCallHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on</para>\n\t\t/// <para> asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and</para>\n\t\t/// <para> HTTPRequestDataReceived_t callbacks while streaming.</para>\n\t\t/// </summary>\n\t\tpublic static bool SendHTTPRequestAndStreamResponse(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SendHTTPRequestAndStreamResponse(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pCallHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move</para>\n\t\t/// <para> the specified request to the tail of the queue.  Returns false on invalid handle, or if the request is not yet sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool DeferHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_DeferHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move</para>\n\t\t/// <para> the specified request to the head of the queue.  Returns false on invalid handle, or if the request is not yet sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool PrioritizeHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_PrioritizeHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also</para>\n\t\t/// <para> returns the size of the header value if present so the caller and allocate a correctly sized buffer for</para>\n\t\t/// <para> GetHTTPResponseHeaderValue.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseHeaderSize(HTTPRequestHandle hRequest, string pchHeaderName, out uint unResponseHeaderSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseHeaderSize(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, out unResponseHeaderSize);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> header is not present or if your buffer is too small to contain it's value.  You should first call</para>\n\t\t/// <para> BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseHeaderValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pHeaderValueBuffer, unBufferSize);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> handle is invalid.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseBodySize(HTTPRequestHandle hRequest, out uint unBodySize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseBodySize(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out unBodySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> handle is invalid or is to a streaming response, or if the provided buffer is not the correct size.  Use BGetHTTPResponseBodySize first to find out</para>\n\t\t/// <para> the correct buffer size to use.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseBodyData(HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseBodyData(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pBodyDataBuffer, unBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the</para>\n\t\t/// <para> handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset</para>\n\t\t/// <para> do not match the size and offset sent in HTTPRequestDataReceived_t.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPStreamingResponseBodyData(HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPStreamingResponseBodyData(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, cOffset, pBodyDataBuffer, unBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t</para>\n\t\t/// <para> callback and finishing using the response.</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_ReleaseHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets progress on downloading the body for the request.  This will be zero unless a response header has already been</para>\n\t\t/// <para> received which included a content-length field.  For responses that contain no content-length it will report</para>\n\t\t/// <para> zero for the duration of the request as the size is unknown until the connection closes.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPDownloadProgressPct(HTTPRequestHandle hRequest, out float pflPercentOut) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPDownloadProgressPct(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pflPercentOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the body for an HTTP Post request.  Will fail and return false on a GET request, and will fail if POST params</para>\n\t\t/// <para> have already been set for the request.  Setting this raw body makes it the only contents for the post, the pchContentType</para>\n\t\t/// <para> parameter will set the content-type header for the request so the server may know how to interpret the body.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestRawPostBody(HTTPRequestHandle hRequest, string pchContentType, byte[] pubBody, uint unBodyLen) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchContentType2 = new InteropHelp.UTF8StringHandle(pchContentType)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestRawPostBody(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchContentType2, pubBody, unBodyLen);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Creates a cookie container handle which you must later free with ReleaseCookieContainer().  If bAllowResponsesToModify=true</para>\n\t\t/// <para> than any response to your requests using this cookie container may add new cookies which may be transmitted with</para>\n\t\t/// <para> future requests.  If bAllowResponsesToModify=false than only cookies you explicitly set will be sent.  This API is just for</para>\n\t\t/// <para> during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across</para>\n\t\t/// <para> repeat executions of your process.</para>\n\t\t/// </summary>\n\t\tpublic static HTTPCookieContainerHandle CreateCookieContainer(bool bAllowResponsesToModify) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (HTTPCookieContainerHandle)NativeMethods.ISteamHTTP_CreateCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), bAllowResponsesToModify);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Release a cookie container you are finished using, freeing it's memory</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseCookieContainer(HTTPCookieContainerHandle hCookieContainer) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_ReleaseCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), hCookieContainer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Adds a cookie to the specified cookie container that will be used with future requests.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetCookie(HTTPCookieContainerHandle hCookieContainer, string pchHost, string pchUrl, string pchCookie) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchHost2 = new InteropHelp.UTF8StringHandle(pchHost))\n\t\t\tusing (var pchUrl2 = new InteropHelp.UTF8StringHandle(pchUrl))\n\t\t\tusing (var pchCookie2 = new InteropHelp.UTF8StringHandle(pchCookie)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetCookie(CSteamGameServerAPIContext.GetSteamHTTP(), hCookieContainer, pchHost2, pchUrl2, pchCookie2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the cookie container to use for a HTTP request</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestCookieContainer(HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, hCookieContainer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestUserAgentInfo(HTTPRequestHandle hRequest, string pchUserAgentInfo) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchUserAgentInfo2 = new InteropHelp.UTF8StringHandle(pchUserAgentInfo)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestUserAgentInfo(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchUserAgentInfo2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Disable or re-enable verification of SSL/TLS certificates.</para>\n\t\t/// <para> By default, certificates are checked for all HTTPS requests.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestRequiresVerifiedCertificate(HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, bRequireVerifiedCertificate);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout</para>\n\t\t/// <para> which can bump everytime we get more data</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestAbsoluteTimeoutMS(HTTPRequestHandle hRequest, uint unMilliseconds) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, unMilliseconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Check if the reason the request failed was because we timed it out (rather than some harder failure)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPRequestWasTimedOut(HTTPRequestHandle hRequest, out bool pbWasTimedOut) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPRequestWasTimedOut(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pbWasTimedOut);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverinventory.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerInventory {\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC RESULT MANAGEMENT</para>\n\t\t/// <para> Asynchronous inventory queries always output a result handle which can be used with</para>\n\t\t/// <para> GetResultStatus, GetResultItems, etc. A SteamInventoryResultReady_t callback will</para>\n\t\t/// <para> be triggered when the asynchronous result becomes ready (or fails).</para>\n\t\t/// <para> Find out the status of an asynchronous inventory result handle. Possible values:</para>\n\t\t/// <para>  k_EResultPending - still in progress</para>\n\t\t/// <para>  k_EResultOK - done, result ready</para>\n\t\t/// <para>  k_EResultExpired - done, result ready, maybe out of date (see DeserializeResult)</para>\n\t\t/// <para>  k_EResultInvalidParam - ERROR: invalid API call parameters</para>\n\t\t/// <para>  k_EResultServiceUnavailable - ERROR: service temporarily down, you may retry later</para>\n\t\t/// <para>  k_EResultLimitExceeded - ERROR: operation would exceed per-user inventory limits</para>\n\t\t/// <para>  k_EResultFail - ERROR: unknown / generic error</para>\n\t\t/// </summary>\n\t\tpublic static EResult GetResultStatus(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetResultStatus(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Copies the contents of a result set into a flat array. The specific</para>\n\t\t/// <para> contents of the result set depend on which query which was used.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetResultItems(SteamInventoryResult_t resultHandle, SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tif (pOutItemsArray != null && pOutItemsArray.Length != punOutItemsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pOutItemsArray must be the same size as punOutItemsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetResultItems(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, pOutItemsArray, ref punOutItemsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> In combination with GetResultItems, you can use GetResultItemProperty to retrieve</para>\n\t\t/// <para> dynamic string properties for a given item returned in the result set.</para>\n\t\t/// <para> Property names are always composed of ASCII letters, numbers, and/or underscores.</para>\n\t\t/// <para> Pass a NULL pointer for pchPropertyName to get a comma - separated list of available</para>\n\t\t/// <para> property names.</para>\n\t\t/// <para> If pchValueBuffer is NULL, *punValueBufferSize will contain the</para>\n\t\t/// <para> suggested buffer size. Otherwise it will be the number of bytes actually copied</para>\n\t\t/// <para> to pchValueBuffer. If the results do not fit in the given buffer, partial</para>\n\t\t/// <para> results may be copied.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetResultItemProperty(SteamInventoryResult_t resultHandle, uint unItemIndex, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut);\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\tbool ret = NativeMethods.ISteamInventory_GetResultItemProperty(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, unItemIndex, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut);\n\t\t\t\tpchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValueBuffer2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the server time at which the result was generated. Compare against</para>\n\t\t/// <para> the value of IClientUtils::GetServerRealTime() to determine age.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetResultTimestamp(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetResultTimestamp(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the result belongs to the target steam ID, false if the</para>\n\t\t/// <para> result does not. This is important when using DeserializeResult, to verify</para>\n\t\t/// <para> that a remote player is not pretending to have a different user's inventory.</para>\n\t\t/// </summary>\n\t\tpublic static bool CheckResultSteamID(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_CheckResultSteamID(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, steamIDExpected);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Destroys a result handle and frees all associated memory.</para>\n\t\t/// </summary>\n\t\tpublic static void DestroyResult(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamInventory_DestroyResult(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC QUERY</para>\n\t\t/// <para> Captures the entire state of the current user's Steam inventory.</para>\n\t\t/// <para> You must call DestroyResult on this handle when you are done with it.</para>\n\t\t/// <para> Returns false and sets *pResultHandle to zero if inventory is unavailable.</para>\n\t\t/// <para> Note: calls to this function are subject to rate limits and may return</para>\n\t\t/// <para> cached results if called too frequently. It is suggested that you call</para>\n\t\t/// <para> this function only when you are about to display the user's full inventory,</para>\n\t\t/// <para> or if you expect that the inventory may have changed.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetAllItems(out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetAllItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Captures the state of a subset of the current user's Steam inventory,</para>\n\t\t/// <para> identified by an array of item instance IDs. The results from this call</para>\n\t\t/// <para> can be serialized and passed to other players to \"prove\" that the current</para>\n\t\t/// <para> user owns specific items, without exposing the user's entire inventory.</para>\n\t\t/// <para> For example, you could call GetItemsByID with the IDs of the user's</para>\n\t\t/// <para> currently equipped cosmetic items and serialize this to a buffer, and</para>\n\t\t/// <para> then transmit this buffer to other players upon joining a game.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemsByID(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetItemsByID(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pInstanceIDs, unCountInstanceIDs);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> RESULT SERIALIZATION AND AUTHENTICATION</para>\n\t\t/// <para> Serialized result sets contain a short signature which can't be forged</para>\n\t\t/// <para> or replayed across different game sessions. A result set can be serialized</para>\n\t\t/// <para> on the local client, transmitted to other players via your game networking,</para>\n\t\t/// <para> and deserialized by the remote players. This is a secure way of preventing</para>\n\t\t/// <para> hackers from lying about posessing rare/high-value items.</para>\n\t\t/// <para> Serializes a result set with signature bytes to an output buffer. Pass</para>\n\t\t/// <para> NULL as an output buffer to get the required size via punOutBufferSize.</para>\n\t\t/// <para> The size of a serialized result depends on the number items which are being</para>\n\t\t/// <para> serialized. When securely transmitting items to other players, it is</para>\n\t\t/// <para> recommended to use \"GetItemsByID\" first to create a minimal result set.</para>\n\t\t/// <para> Results have a built-in timestamp which will be considered \"expired\" after</para>\n\t\t/// <para> an hour has elapsed. See DeserializeResult for expiration handling.</para>\n\t\t/// </summary>\n\t\tpublic static bool SerializeResult(SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_SerializeResult(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, pOutBuffer, out punOutBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Deserializes a result set and verifies the signature bytes. Returns false</para>\n\t\t/// <para> if bRequireFullOnlineVerify is set but Steam is running in Offline mode.</para>\n\t\t/// <para> Otherwise returns true and then delivers error codes via GetResultStatus.</para>\n\t\t/// <para> The bRESERVED_MUST_BE_FALSE flag is reserved for future use and should not</para>\n\t\t/// <para> be set to true by your game at this time.</para>\n\t\t/// <para> DeserializeResult has a potential soft-failure mode where the handle status</para>\n\t\t/// <para> is set to k_EResultExpired. GetResultItems() still succeeds in this mode.</para>\n\t\t/// <para> The \"expired\" result could indicate that the data may be out of date - not</para>\n\t\t/// <para> just due to timed expiration (one hour), but also because one of the items</para>\n\t\t/// <para> in the result set may have been traded or consumed since the result set was</para>\n\t\t/// <para> generated. You could compare the timestamp from GetResultTimestamp() to</para>\n\t\t/// <para> ISteamUtils::GetServerRealTime() to determine how old the data is. You could</para>\n\t\t/// <para> simply ignore the \"expired\" result code and continue as normal, or you</para>\n\t\t/// <para> could challenge the player with expired data to send an updated result set.</para>\n\t\t/// </summary>\n\t\tpublic static bool DeserializeResult(out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, bool bRESERVED_MUST_BE_FALSE = false) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_DeserializeResult(CSteamGameServerAPIContext.GetSteamInventory(), out pOutResultHandle, pBuffer, unBufferSize, bRESERVED_MUST_BE_FALSE);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC MODIFICATION</para>\n\t\t/// <para> GenerateItems() creates one or more items and then generates a SteamInventoryCallback_t</para>\n\t\t/// <para> notification with a matching nCallbackContext parameter. This API is only intended</para>\n\t\t/// <para> for prototyping - it is only usable by Steam accounts that belong to the publisher group</para>\n\t\t/// <para> for your game.</para>\n\t\t/// <para> If punArrayQuantity is not NULL, it should be the same length as pArrayItems and should</para>\n\t\t/// <para> describe the quantity of each item to generate.</para>\n\t\t/// </summary>\n\t\tpublic static bool GenerateItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GenerateItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, punArrayQuantity, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GrantPromoItems() checks the list of promotional items for which the user may be eligible</para>\n\t\t/// <para> and grants the items (one time only).  On success, the result set will include items which</para>\n\t\t/// <para> were granted, if any. If no items were granted because the user isn't eligible for any</para>\n\t\t/// <para> promotions, this is still considered a success.</para>\n\t\t/// </summary>\n\t\tpublic static bool GrantPromoItems(out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GrantPromoItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> AddPromoItem() / AddPromoItems() are restricted versions of GrantPromoItems(). Instead of</para>\n\t\t/// <para> scanning for all eligible promotional items, the check is restricted to a single item</para>\n\t\t/// <para> definition or set of item definitions. This can be useful if your game has custom UI for</para>\n\t\t/// <para> showing a specific promo item to the user.</para>\n\t\t/// </summary>\n\t\tpublic static bool AddPromoItem(out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_AddPromoItem(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemDef);\n\t\t}\n\n\t\tpublic static bool AddPromoItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_AddPromoItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ConsumeItem() removes items from the inventory, permanently. They cannot be recovered.</para>\n\t\t/// <para> Not for the faint of heart - if your game implements item removal at all, a high-friction</para>\n\t\t/// <para> UI confirmation process is highly recommended.</para>\n\t\t/// </summary>\n\t\tpublic static bool ConsumeItem(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_ConsumeItem(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemConsume, unQuantity);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ExchangeItems() is an atomic combination of item generation and consumption.</para>\n\t\t/// <para> It can be used to implement crafting recipes or transmutations, or items which unpack</para>\n\t\t/// <para> themselves into other items (e.g., a chest).</para>\n\t\t/// <para> Exchange recipes are defined in the ItemDef, and explicitly list the required item</para>\n\t\t/// <para> types and resulting generated type.</para>\n\t\t/// <para> Exchange recipes are evaluated atomically by the Inventory Service; if the supplied</para>\n\t\t/// <para> components do not match the recipe, or do not contain sufficient quantity, the</para>\n\t\t/// <para> exchange will fail.</para>\n\t\t/// </summary>\n\t\tpublic static bool ExchangeItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayGenerate, uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, SteamItemInstanceID_t[] pArrayDestroy, uint[] punArrayDestroyQuantity, uint unArrayDestroyLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_ExchangeItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayGenerate, punArrayGenerateQuantity, unArrayGenerateLength, pArrayDestroy, punArrayDestroyQuantity, unArrayDestroyLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> TransferItemQuantity() is intended for use with items which are \"stackable\" (can have</para>\n\t\t/// <para> quantity greater than one). It can be used to split a stack into two, or to transfer</para>\n\t\t/// <para> quantity from one stack into another stack of identical items. To split one stack into</para>\n\t\t/// <para> two, pass k_SteamItemInstanceIDInvalid for itemIdDest and a new item will be generated.</para>\n\t\t/// </summary>\n\t\tpublic static bool TransferItemQuantity(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_TransferItemQuantity(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemIdSource, unQuantity, itemIdDest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> TIMED DROPS AND PLAYTIME CREDIT</para>\n\t\t/// <para> Deprecated. Calling this method is not required for proper playtime accounting.</para>\n\t\t/// </summary>\n\t\tpublic static void SendItemDropHeartbeat() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamInventory_SendItemDropHeartbeat(CSteamGameServerAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Playtime credit must be consumed and turned into item drops by your game. Only item</para>\n\t\t/// <para> definitions which are marked as \"playtime item generators\" can be spawned. The call</para>\n\t\t/// <para> will return an empty result set if there is not enough playtime credit for a drop.</para>\n\t\t/// <para> Your game should call TriggerItemDrop at an appropriate time for the user to receive</para>\n\t\t/// <para> new items, such as between rounds or while the player is dead. Note that players who</para>\n\t\t/// <para> hack their clients could modify the value of \"dropListDefinition\", so do not use it</para>\n\t\t/// <para> to directly control rarity.</para>\n\t\t/// <para> See your Steamworks configuration to set playtime drop rates for individual itemdefs.</para>\n\t\t/// <para> The client library will suppress too-frequent calls to this method.</para>\n\t\t/// </summary>\n\t\tpublic static bool TriggerItemDrop(out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_TriggerItemDrop(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, dropListDefinition);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Deprecated. This method is not supported.</para>\n\t\t/// </summary>\n\t\tpublic static bool TradeItems(out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, SteamItemInstanceID_t[] pArrayGive, uint[] pArrayGiveQuantity, uint nArrayGiveLength, SteamItemInstanceID_t[] pArrayGet, uint[] pArrayGetQuantity, uint nArrayGetLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_TradeItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, steamIDTradePartner, pArrayGive, pArrayGiveQuantity, nArrayGiveLength, pArrayGet, pArrayGetQuantity, nArrayGetLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ITEM DEFINITIONS</para>\n\t\t/// <para> Item definitions are a mapping of \"definition IDs\" (integers between 1 and 1000000)</para>\n\t\t/// <para> to a set of string properties. Some of these properties are required to display items</para>\n\t\t/// <para> on the Steam community web site. Other properties can be defined by applications.</para>\n\t\t/// <para> Use of these functions is optional; there is no reason to call LoadItemDefinitions</para>\n\t\t/// <para> if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue</para>\n\t\t/// <para> weapon mod = 55) and does not allow for adding new item types without a client patch.</para>\n\t\t/// <para> LoadItemDefinitions triggers the automatic load and refresh of item definitions.</para>\n\t\t/// <para> Every time new item definitions are available (eg, from the dynamic addition of new</para>\n\t\t/// <para> item types while players are still in-game), a SteamInventoryDefinitionUpdate_t</para>\n\t\t/// <para> callback will be fired.</para>\n\t\t/// </summary>\n\t\tpublic static bool LoadItemDefinitions() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_LoadItemDefinitions(CSteamGameServerAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GetItemDefinitionIDs returns the set of all defined item definition IDs (which are</para>\n\t\t/// <para> defined via Steamworks configuration, and not necessarily contiguous integers).</para>\n\t\t/// <para> If pItemDefIDs is null, the call will return true and *punItemDefIDsArraySize will</para>\n\t\t/// <para> contain the total size necessary for a subsequent call. Otherwise, the call will</para>\n\t\t/// <para> return false if and only if there is not enough space in the output array.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDefinitionIDs(SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tif (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pItemDefIDs must be the same size as punItemDefIDsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetItemDefinitionIDs(CSteamGameServerAPIContext.GetSteamInventory(), pItemDefIDs, ref punItemDefIDsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GetItemDefinitionProperty returns a string property from a given item definition.</para>\n\t\t/// <para> Note that some properties (for example, \"name\") may be localized and will depend</para>\n\t\t/// <para> on the current Steam language settings (see ISteamApps::GetCurrentGameLanguage).</para>\n\t\t/// <para> Property names are always composed of ASCII letters, numbers, and/or underscores.</para>\n\t\t/// <para> Pass a NULL pointer for pchPropertyName to get a comma - separated list of available</para>\n\t\t/// <para> property names. If pchValueBuffer is NULL, *punValueBufferSize will contain the</para>\n\t\t/// <para> suggested buffer size. Otherwise it will be the number of bytes actually copied</para>\n\t\t/// <para> to pchValueBuffer. If the results do not fit in the given buffer, partial</para>\n\t\t/// <para> results may be copied.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDefinitionProperty(SteamItemDef_t iDefinition, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut);\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\tbool ret = NativeMethods.ISteamInventory_GetItemDefinitionProperty(CSteamGameServerAPIContext.GetSteamInventory(), iDefinition, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut);\n\t\t\t\tpchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValueBuffer2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request the list of \"eligible\" promo items that can be manually granted to the given</para>\n\t\t/// <para> user.  These are promo items of type \"manual\" that won't be granted automatically.</para>\n\t\t/// <para> An example usage of this is an item that becomes available every week.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestEligiblePromoItemDefinitionsIDs(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(CSteamGameServerAPIContext.GetSteamInventory(), steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> After handling a SteamInventoryEligiblePromoItemDefIDs_t call result, use this</para>\n\t\t/// <para> function to pull out the list of item definition ids that the user can be</para>\n\t\t/// <para> manually granted via the AddPromoItems() call.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetEligiblePromoItemDefinitionIDs(CSteamID steamID, SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tif (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pItemDefIDs must be the same size as punItemDefIDsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetEligiblePromoItemDefinitionIDs(CSteamGameServerAPIContext.GetSteamInventory(), steamID, pItemDefIDs, ref punItemDefIDsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Starts the purchase process for the given item definitions.  The callback SteamInventoryStartPurchaseResult_t</para>\n\t\t/// <para> will be posted if Steam was able to initialize the transaction.</para>\n\t\t/// <para> Once the purchase has been authorized and completed by the user, the callback SteamInventoryResultReady_t</para>\n\t\t/// <para> will be posted.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t StartPurchase(SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_StartPurchase(CSteamGameServerAPIContext.GetSteamInventory(), pArrayItemDefs, punArrayQuantity, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request current prices for all applicable item definitions</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestPrices() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_RequestPrices(CSteamGameServerAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the number of items with prices.  Need to call RequestPrices() first.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumItemsWithPrices() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetNumItemsWithPrices(CSteamGameServerAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns item definition ids and their prices in the user's local currency.</para>\n\t\t/// <para> Need to call RequestPrices() first.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemsWithPrices(SteamItemDef_t[] pArrayItemDefs, ulong[] pCurrentPrices, ulong[] pBasePrices, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tif (pArrayItemDefs != null && pArrayItemDefs.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pArrayItemDefs must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\tif (pCurrentPrices != null && pCurrentPrices.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pCurrentPrices must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\tif (pBasePrices != null && pBasePrices.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pBasePrices must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetItemsWithPrices(CSteamGameServerAPIContext.GetSteamInventory(), pArrayItemDefs, pCurrentPrices, pBasePrices, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieves the price for the item definition id</para>\n\t\t/// <para> Returns false if there is no price stored for the item definition.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemPrice(SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_GetItemPrice(CSteamGameServerAPIContext.GetSteamInventory(), iDefinition, out pCurrentPrice, out pBasePrice);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Create a request to update properties on items</para>\n\t\t/// </summary>\n\t\tpublic static SteamInventoryUpdateHandle_t StartUpdateProperties() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamInventoryUpdateHandle_t)NativeMethods.ISteamInventory_StartUpdateProperties(CSteamGameServerAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Remove the property on the item</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_RemoveProperty(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Accessor methods to set properties on items</para>\n\t\t/// </summary>\n\t\tpublic static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, string pchPropertyValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName))\n\t\t\tusing (var pchPropertyValue2 = new InteropHelp.UTF8StringHandle(pchPropertyValue)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, pchPropertyValue2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty0(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, bValue);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty1(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, long nValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty1(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, nValue);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty2(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, float flValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty2(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, flValue);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Submit the update request by handle</para>\n\t\t/// </summary>\n\t\tpublic static bool SubmitUpdateProperties(SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamInventory_SubmitUpdateProperties(CSteamGameServerAPIContext.GetSteamInventory(), handle, out pResultHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameservernetworking.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerNetworking {\n\t\t/// <summary>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> UDP-style (connectionless) networking interface.  These functions send messages using</para>\n\t\t/// <para> an API organized around the destination.  Reliable and unreliable messages are supported.</para>\n\t\t/// <para> For a more TCP-style interface (meaning you have a connection handle), see the functions below.</para>\n\t\t/// <para> Both interface styles can send both reliable and unreliable messages.</para>\n\t\t/// <para> Automatically establishes NAT-traversing or Relay server connections</para>\n\t\t/// <para> Sends a P2P packet to the specified user</para>\n\t\t/// <para> UDP-like, unreliable and a max packet size of 1200 bytes</para>\n\t\t/// <para> the first packet send may be delayed as the NAT-traversal code runs</para>\n\t\t/// <para> if we can't get through to the user, an error will be posted via the callback P2PSessionConnectFail_t</para>\n\t\t/// <para> see EP2PSend enum above for the descriptions of the different ways of sending packets</para>\n\t\t/// <para> nChannel is a routing number you can use to help route message to different systems \t- you'll have to call ReadP2PPacket()</para>\n\t\t/// <para> with the same channel number in order to retrieve the data on the other end</para>\n\t\t/// <para> using different channels to talk to the same user will still use the same underlying p2p connection, saving on resources</para>\n\t\t/// </summary>\n\t\tpublic static bool SendP2PPacket(CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_SendP2PPacket(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, pubData, cubData, eP2PSendType, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if any data is available for read, and the amount of data that will need to be read</para>\n\t\t/// </summary>\n\t\tpublic static bool IsP2PPacketAvailable(out uint pcubMsgSize, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_IsP2PPacketAvailable(CSteamGameServerAPIContext.GetSteamNetworking(), out pcubMsgSize, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> reads in a packet that has been sent from another user via SendP2PPacket()</para>\n\t\t/// <para> returns the size of the message and the steamID of the user who sent it in the last two parameters</para>\n\t\t/// <para> if the buffer passed in is too small, the message will be truncated</para>\n\t\t/// <para> this call is not blocking, and will return false if no data is available</para>\n\t\t/// </summary>\n\t\tpublic static bool ReadP2PPacket(byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_ReadP2PPacket(CSteamGameServerAPIContext.GetSteamNetworking(), pubDest, cubDest, out pcubMsgSize, out psteamIDRemote, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> AcceptP2PSessionWithUser() should only be called in response to a P2PSessionRequest_t callback</para>\n\t\t/// <para> P2PSessionRequest_t will be posted if another user tries to send you a packet that you haven't talked to yet</para>\n\t\t/// <para> if you don't want to talk to the user, just ignore the request</para>\n\t\t/// <para> if the user continues to send you packets, another P2PSessionRequest_t will be posted periodically</para>\n\t\t/// <para> this may be called multiple times for a single user</para>\n\t\t/// <para> (if you've called SendP2PPacket() on the other user, this implicitly accepts the session request)</para>\n\t\t/// </summary>\n\t\tpublic static bool AcceptP2PSessionWithUser(CSteamID steamIDRemote) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_AcceptP2PSessionWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> call CloseP2PSessionWithUser() when you're done talking to a user, will free up resources under-the-hood</para>\n\t\t/// <para> if the remote user tries to send data to you again, another P2PSessionRequest_t callback will be posted</para>\n\t\t/// </summary>\n\t\tpublic static bool CloseP2PSessionWithUser(CSteamID steamIDRemote) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_CloseP2PSessionWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> call CloseP2PChannelWithUser() when you're done talking to a user on a specific channel. Once all channels</para>\n\t\t/// <para> open channels to a user have been closed, the open session to the user will be closed and new data from this</para>\n\t\t/// <para> user will trigger a P2PSessionRequest_t callback</para>\n\t\t/// </summary>\n\t\tpublic static bool CloseP2PChannelWithUser(CSteamID steamIDRemote, int nChannel) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_CloseP2PChannelWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> fills out P2PSessionState_t structure with details about the underlying connection to the user</para>\n\t\t/// <para> should only needed for debugging purposes</para>\n\t\t/// <para> returns false if no connection exists to the specified user</para>\n\t\t/// </summary>\n\t\tpublic static bool GetP2PSessionState(CSteamID steamIDRemote, out P2PSessionState_t pConnectionState) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_GetP2PSessionState(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, out pConnectionState);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Allow P2P connections to fall back to being relayed through the Steam servers if a direct connection</para>\n\t\t/// <para> or NAT-traversal cannot be established. Only applies to connections created after setting this value,</para>\n\t\t/// <para> or to existing connections that need to automatically reconnect after this value is set.</para>\n\t\t/// <para> P2P packet relay is allowed by default</para>\n\t\t/// </summary>\n\t\tpublic static bool AllowP2PPacketRelay(bool bAllow) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_AllowP2PPacketRelay(CSteamGameServerAPIContext.GetSteamNetworking(), bAllow);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> LISTEN / CONNECT connection-oriented interface functions</para>\n\t\t/// <para> These functions are more like a client-server TCP API.  One side is the \"server\"</para>\n\t\t/// <para> and \"listens\" for incoming connections, which then must be \"accepted.\"  The \"client\"</para>\n\t\t/// <para> initiates a connection by \"connecting.\"  Sending and receiving is done through a</para>\n\t\t/// <para> connection handle.</para>\n\t\t/// <para> For a more UDP-style interface, where you do not track connection handles but</para>\n\t\t/// <para> simply send messages to a SteamID, use the UDP-style functions above.</para>\n\t\t/// <para> Both methods can send both reliable and unreliable methods.</para>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> creates a socket and listens others to connect</para>\n\t\t/// <para> will trigger a SocketStatusCallback_t callback on another client connecting</para>\n\t\t/// <para> nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports</para>\n\t\t/// <para>\t\tthis can usually just be 0 unless you want multiple sets of connections</para>\n\t\t/// <para> unIP is the local IP address to bind to</para>\n\t\t/// <para>\t\tpass in 0 if you just want the default local IP</para>\n\t\t/// <para> unPort is the port to use</para>\n\t\t/// <para>\t\tpass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only</para>\n\t\t/// </summary>\n\t\tpublic static SNetListenSocket_t CreateListenSocket(int nVirtualP2PPort, uint nIP, ushort nPort, bool bAllowUseOfPacketRelay) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SNetListenSocket_t)NativeMethods.ISteamNetworking_CreateListenSocket(CSteamGameServerAPIContext.GetSteamNetworking(), nVirtualP2PPort, nIP, nPort, bAllowUseOfPacketRelay);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> creates a socket and begin connection to a remote destination</para>\n\t\t/// <para> can connect via a known steamID (client or game server), or directly to an IP</para>\n\t\t/// <para> on success will trigger a SocketStatusCallback_t callback</para>\n\t\t/// <para> on failure or timeout will trigger a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState</para>\n\t\t/// </summary>\n\t\tpublic static SNetSocket_t CreateP2PConnectionSocket(CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SNetSocket_t)NativeMethods.ISteamNetworking_CreateP2PConnectionSocket(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDTarget, nVirtualPort, nTimeoutSec, bAllowUseOfPacketRelay);\n\t\t}\n\n\t\tpublic static SNetSocket_t CreateConnectionSocket(uint nIP, ushort nPort, int nTimeoutSec) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SNetSocket_t)NativeMethods.ISteamNetworking_CreateConnectionSocket(CSteamGameServerAPIContext.GetSteamNetworking(), nIP, nPort, nTimeoutSec);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> disconnects the connection to the socket, if any, and invalidates the handle</para>\n\t\t/// <para> any unread data on the socket will be thrown away</para>\n\t\t/// <para> if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect</para>\n\t\t/// </summary>\n\t\tpublic static bool DestroySocket(SNetSocket_t hSocket, bool bNotifyRemoteEnd) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_DestroySocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> destroying a listen socket will automatically kill all the regular sockets generated from it</para>\n\t\t/// </summary>\n\t\tpublic static bool DestroyListenSocket(SNetListenSocket_t hSocket, bool bNotifyRemoteEnd) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_DestroyListenSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sending data</para>\n\t\t/// <para> must be a handle to a connected socket</para>\n\t\t/// <para> data is all sent via UDP, and thus send sizes are limited to 1200 bytes; after this, many routers will start dropping packets</para>\n\t\t/// <para> use the reliable flag with caution; although the resend rate is pretty aggressive,</para>\n\t\t/// <para> it can still cause stalls in receiving data (like TCP)</para>\n\t\t/// </summary>\n\t\tpublic static bool SendDataOnSocket(SNetSocket_t hSocket, byte[] pubData, uint cubData, bool bReliable) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_SendDataOnSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, pubData, cubData, bReliable);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> receiving data</para>\n\t\t/// <para> returns false if there is no data remaining</para>\n\t\t/// <para> fills out *pcubMsgSize with the size of the next message, in bytes</para>\n\t\t/// </summary>\n\t\tpublic static bool IsDataAvailableOnSocket(SNetSocket_t hSocket, out uint pcubMsgSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_IsDataAvailableOnSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, out pcubMsgSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> fills in pubDest with the contents of the message</para>\n\t\t/// <para> messages are always complete, of the same size as was sent (i.e. packetized, not streaming)</para>\n\t\t/// <para> if *pcubMsgSize &lt; cubDest, only partial data is written</para>\n\t\t/// <para> returns false if no data is available</para>\n\t\t/// </summary>\n\t\tpublic static bool RetrieveDataFromSocket(SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_RetrieveDataFromSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, pubDest, cubDest, out pcubMsgSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> checks for data from any socket that has been connected off this listen socket</para>\n\t\t/// <para> returns false if there is no data remaining</para>\n\t\t/// <para> fills out *pcubMsgSize with the size of the next message, in bytes</para>\n\t\t/// <para> fills out *phSocket with the socket that data is available on</para>\n\t\t/// </summary>\n\t\tpublic static bool IsDataAvailable(SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_IsDataAvailable(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, out pcubMsgSize, out phSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves data from any socket that has been connected off this listen socket</para>\n\t\t/// <para> fills in pubDest with the contents of the message</para>\n\t\t/// <para> messages are always complete, of the same size as was sent (i.e. packetized, not streaming)</para>\n\t\t/// <para> if *pcubMsgSize &lt; cubDest, only partial data is written</para>\n\t\t/// <para> returns false if no data is available</para>\n\t\t/// <para> fills out *phSocket with the socket that data is available on</para>\n\t\t/// </summary>\n\t\tpublic static bool RetrieveData(SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_RetrieveData(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, pubDest, cubDest, out pcubMsgSize, out phSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns information about the specified socket, filling out the contents of the pointers</para>\n\t\t/// </summary>\n\t\tpublic static bool GetSocketInfo(SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out uint punIPRemote, out ushort punPortRemote) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_GetSocketInfo(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, out pSteamIDRemote, out peSocketStatus, out punIPRemote, out punPortRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns which local port the listen socket is bound to</para>\n\t\t/// <para> *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only</para>\n\t\t/// </summary>\n\t\tpublic static bool GetListenSocketInfo(SNetListenSocket_t hListenSocket, out uint pnIP, out ushort pnPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_GetListenSocketInfo(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, out pnIP, out pnPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true to describe how the socket ended up connecting</para>\n\t\t/// </summary>\n\t\tpublic static ESNetSocketConnectionType GetSocketConnectionType(SNetSocket_t hSocket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_GetSocketConnectionType(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> max packet size, in bytes</para>\n\t\t/// </summary>\n\t\tpublic static int GetMaxPacketSize(SNetSocket_t hSocket) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamNetworking_GetMaxPacketSize(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverstats.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerStats {\n\t\t/// <summary>\n\t\t/// <para> downloads stats for the user</para>\n\t\t/// <para> returns a GSStatsReceived_t callback when completed</para>\n\t\t/// <para> if the user has no stats, GSStatsReceived_t.m_eResult will be set to k_EResultFail</para>\n\t\t/// <para> these stats will only be auto-updated for clients playing on the server. For other</para>\n\t\t/// <para> users you'll need to call RequestUserStats() again to refresh any data</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestUserStats(CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamGameServerStats_RequestUserStats(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> requests stat information for a user, usable after a successful call to RequestUserStats()</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUserStat(CSteamID steamIDUser, string pchName, out int pData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_GetUserStat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetUserStat(CSteamID steamIDUser, string pchName, out float pData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_GetUserStat0(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetUserAchievement(CSteamID steamIDUser, string pchName, out bool pbAchieved) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_GetUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pbAchieved);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set / update stats and achievements.</para>\n\t\t/// <para> Note: These updates will work only on stats game servers are allowed to edit and only for</para>\n\t\t/// <para> game servers that have been declared as officially controlled by the game creators.</para>\n\t\t/// <para> Set the IP range of your official servers on the Steamworks page</para>\n\t\t/// </summary>\n\t\tpublic static bool SetUserStat(CSteamID steamIDUser, string pchName, int nData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_SetUserStat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, nData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetUserStat(CSteamID steamIDUser, string pchName, float fData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_SetUserStat0(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, fData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdateUserAvgRateStat(CSteamID steamIDUser, string pchName, float flCountThisSession, double dSessionLength) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_UpdateUserAvgRateStat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, flCountThisSession, dSessionLength);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetUserAchievement(CSteamID steamIDUser, string pchName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_SetUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool ClearUserAchievement(CSteamID steamIDUser, string pchName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamGameServerStats_ClearUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Store the current data on the server, will get a GSStatsStored_t callback when set.</para>\n\t\t/// <para> If the callback has a result of k_EResultInvalidParam, one or more stats</para>\n\t\t/// <para> uploaded has been rejected, either because they broke constraints</para>\n\t\t/// <para> or were out of date. In this case the server sends back updated values.</para>\n\t\t/// <para> The stats should be re-iterated to keep in sync.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t StoreUserStats(CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamGameServerStats_StoreUserStats(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverugc.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerUGC {\n\t\t/// <summary>\n\t\t/// <para> Query UGC associated with a user. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryUserUGCRequest(AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUserUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for all matching UGC. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, unPage);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for all matching UGC using the new deep paging interface. Creator app id or consumer app id must be valid and be set to the current running app. pchCursor should be set to NULL or \"*\" to get the first result set.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, string pchCursor = null) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchCursor2 = new InteropHelp.UTF8StringHandle(pchCursor)) {\n\t\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequest0(CSteamGameServerAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, pchCursor2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this)</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryUGCDetailsRequest(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUGCDetailsRequest(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Send the query to Steam</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SendQueryUGCRequest(UGCQueryHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SendQueryUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieve an individual result after receiving the callback for querying UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool GetQueryUGCResult(UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCResult(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, out pDetails);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCPreviewURL(UGCQueryHandle_t handle, uint index, out string pchURL, uint cchURLSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchURL2 = Marshal.AllocHGlobal((int)cchURLSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCPreviewURL(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchURL2, cchURLSize);\n\t\t\tpchURL = ret ? InteropHelp.PtrToStringUTF8(pchURL2) : null;\n\t\t\tMarshal.FreeHGlobal(pchURL2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool GetQueryUGCMetadata(UGCQueryHandle_t handle, uint index, out string pchMetadata, uint cchMetadatasize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchMetadata2 = Marshal.AllocHGlobal((int)cchMetadatasize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchMetadata2, cchMetadatasize);\n\t\t\tpchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null;\n\t\t\tMarshal.FreeHGlobal(pchMetadata2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool GetQueryUGCChildren(UGCQueryHandle_t handle, uint index, PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCChildren(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pvecPublishedFileID, cMaxEntries);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCStatistic(UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCStatistic(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, eStatType, out pStatValue);\n\t\t}\n\n\t\tpublic static uint GetQueryUGCNumAdditionalPreviews(UGCQueryHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCNumAdditionalPreviews(CSteamGameServerAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCAdditionalPreview(UGCQueryHandle_t handle, uint index, uint previewIndex, out string pchURLOrVideoID, uint cchURLSize, out string pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchURLOrVideoID2 = Marshal.AllocHGlobal((int)cchURLSize);\n\t\t\tIntPtr pchOriginalFileName2 = Marshal.AllocHGlobal((int)cchOriginalFileNameSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCAdditionalPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, previewIndex, pchURLOrVideoID2, cchURLSize, pchOriginalFileName2, cchOriginalFileNameSize, out pPreviewType);\n\t\t\tpchURLOrVideoID = ret ? InteropHelp.PtrToStringUTF8(pchURLOrVideoID2) : null;\n\t\t\tMarshal.FreeHGlobal(pchURLOrVideoID2);\n\t\t\tpchOriginalFileName = ret ? InteropHelp.PtrToStringUTF8(pchOriginalFileName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchOriginalFileName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static uint GetQueryUGCNumKeyValueTags(UGCQueryHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCNumKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, out string pchKey, uint cchKeySize, out string pchValue, uint cchValueSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchKey2 = Marshal.AllocHGlobal((int)cchKeySize);\n\t\t\tIntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, keyValueTagIndex, pchKey2, cchKeySize, pchValue2, cchValueSize);\n\t\t\tpchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null;\n\t\t\tMarshal.FreeHGlobal(pchKey2);\n\t\t\tpchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;\n\t\t\tMarshal.FreeHGlobal(pchValue2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Return the first value matching the pchKey. Note that a key may map to multiple values.  Returns false if there was an error or no matching value was found.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, string pchKey, out string pchValue, uint cchValueSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize);\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag0(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchKey2, pchValue2, cchValueSize);\n\t\t\t\tpchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValue2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Release the request to free up memory, after retrieving results</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseQueryUGCRequest(UGCQueryHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_ReleaseQueryUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options to set for querying UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool AddRequiredTag(UGCQueryHandle_t handle, string pTagName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddRequiredTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pTagName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool AddExcludedTag(UGCQueryHandle_t handle, string pTagName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddExcludedTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pTagName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetReturnOnlyIDs(UGCQueryHandle_t handle, bool bReturnOnlyIDs) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnOnlyIDs(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnOnlyIDs);\n\t\t}\n\n\t\tpublic static bool SetReturnKeyValueTags(UGCQueryHandle_t handle, bool bReturnKeyValueTags) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnKeyValueTags);\n\t\t}\n\n\t\tpublic static bool SetReturnLongDescription(UGCQueryHandle_t handle, bool bReturnLongDescription) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnLongDescription(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnLongDescription);\n\t\t}\n\n\t\tpublic static bool SetReturnMetadata(UGCQueryHandle_t handle, bool bReturnMetadata) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnMetadata);\n\t\t}\n\n\t\tpublic static bool SetReturnChildren(UGCQueryHandle_t handle, bool bReturnChildren) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnChildren(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnChildren);\n\t\t}\n\n\t\tpublic static bool SetReturnAdditionalPreviews(UGCQueryHandle_t handle, bool bReturnAdditionalPreviews) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnAdditionalPreviews(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnAdditionalPreviews);\n\t\t}\n\n\t\tpublic static bool SetReturnTotalOnly(UGCQueryHandle_t handle, bool bReturnTotalOnly) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnTotalOnly(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnTotalOnly);\n\t\t}\n\n\t\tpublic static bool SetReturnPlaytimeStats(UGCQueryHandle_t handle, uint unDays) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnPlaytimeStats(CSteamGameServerAPIContext.GetSteamUGC(), handle, unDays);\n\t\t}\n\n\t\tpublic static bool SetLanguage(UGCQueryHandle_t handle, string pchLanguage) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetLanguage(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchLanguage2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetAllowCachedResponse(UGCQueryHandle_t handle, uint unMaxAgeSeconds) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetAllowCachedResponse(CSteamGameServerAPIContext.GetSteamUGC(), handle, unMaxAgeSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options only for querying user UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool SetCloudFileNameFilter(UGCQueryHandle_t handle, string pMatchCloudFileName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pMatchCloudFileName2 = new InteropHelp.UTF8StringHandle(pMatchCloudFileName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetCloudFileNameFilter(CSteamGameServerAPIContext.GetSteamUGC(), handle, pMatchCloudFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options only for querying all UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool SetMatchAnyTag(UGCQueryHandle_t handle, bool bMatchAnyTag) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetMatchAnyTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, bMatchAnyTag);\n\t\t}\n\n\t\tpublic static bool SetSearchText(UGCQueryHandle_t handle, string pSearchText) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pSearchText2 = new InteropHelp.UTF8StringHandle(pSearchText)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetSearchText(CSteamGameServerAPIContext.GetSteamUGC(), handle, pSearchText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetRankedByTrendDays(UGCQueryHandle_t handle, uint unDays) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetRankedByTrendDays(CSteamGameServerAPIContext.GetSteamUGC(), handle, unDays);\n\t\t}\n\n\t\tpublic static bool AddRequiredKeyValueTag(UGCQueryHandle_t handle, string pKey, string pValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pKey2 = new InteropHelp.UTF8StringHandle(pKey))\n\t\t\tusing (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddRequiredKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pKey2, pValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead!</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestUGCDetails(PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RequestUGCDetails(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, unMaxAgeSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Workshop Creator API</para>\n\t\t/// <para> create new item for this app with no content attached yet</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CreateItem(AppId_t nConsumerAppId, EWorkshopFileType eFileType) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_CreateItem(CSteamGameServerAPIContext.GetSteamUGC(), nConsumerAppId, eFileType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> start an UGC item update. Set changed properties before commiting update with CommitItemUpdate()</para>\n\t\t/// </summary>\n\t\tpublic static UGCUpdateHandle_t StartItemUpdate(AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (UGCUpdateHandle_t)NativeMethods.ISteamUGC_StartItemUpdate(CSteamGameServerAPIContext.GetSteamUGC(), nConsumerAppId, nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the title of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemTitle(UGCUpdateHandle_t handle, string pchTitle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemTitle(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchTitle2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the description of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemDescription(UGCUpdateHandle_t handle, string pchDescription) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemDescription(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchDescription2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> specify the language of the title or description that will be set</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemUpdateLanguage(UGCUpdateHandle_t handle, string pchLanguage) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemUpdateLanguage(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchLanguage2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the metadata of an UGC item (max = k_cchDeveloperMetadataMax)</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemMetadata(UGCUpdateHandle_t handle, string pchMetaData) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchMetaData2 = new InteropHelp.UTF8StringHandle(pchMetaData)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchMetaData2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the visibility of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemVisibility(UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetItemVisibility(CSteamGameServerAPIContext.GetSteamUGC(), handle, eVisibility);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the tags of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemTags(UGCUpdateHandle_t updateHandle, System.Collections.Generic.IList<string> pTags) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetItemTags(CSteamGameServerAPIContext.GetSteamUGC(), updateHandle, new InteropHelp.SteamParamStringArray(pTags));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> update item content from this local folder</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemContent(UGCUpdateHandle_t handle, string pszContentFolder) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszContentFolder2 = new InteropHelp.UTF8StringHandle(pszContentFolder)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemContent(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszContentFolder2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemPreview(UGCUpdateHandle_t handle, string pszPreviewFile) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszPreviewFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  use legacy upload for a single small file. The parameter to SetItemContent() should either be a directory with one file or the full path to the file.  The file must also be less than 10MB in size.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetAllowLegacyUpload(UGCUpdateHandle_t handle, bool bAllowLegacyUpload) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_SetAllowLegacyUpload(CSteamGameServerAPIContext.GetSteamUGC(), handle, bAllowLegacyUpload);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove all existing key-value tags (you can add new ones via the AddItemKeyValueTag function)</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveAllItemKeyValueTags(UGCUpdateHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_RemoveAllItemKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove any existing key-value tags with the specified key</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveItemKeyValueTags(UGCUpdateHandle_t handle, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_RemoveItemKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchKey2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> add new key-value tags for the item. Note that there can be multiple values for a tag.</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemKeyValueTag(UGCUpdateHandle_t handle, string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemPreviewFile(UGCUpdateHandle_t handle, string pszPreviewFile, EItemPreviewType type) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemPreviewFile(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszPreviewFile2, type);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  add preview video for this item</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemPreviewVideo(UGCUpdateHandle_t handle, string pszVideoID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemPreviewVideo(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszVideoID2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdateItemPreviewFile(UGCUpdateHandle_t handle, uint index, string pszPreviewFile) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_UpdateItemPreviewFile(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pszPreviewFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  updates an existing preview video for this item</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdateItemPreviewVideo(UGCUpdateHandle_t handle, uint index, string pszVideoID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_UpdateItemPreviewVideo(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pszVideoID2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove a preview by index starting at 0 (previews are sorted)</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveItemPreview(UGCUpdateHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_RemoveItemPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> commit update process started with StartItemUpdate()</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SubmitItemUpdate(UGCUpdateHandle_t handle, string pchChangeNote) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchChangeNote2 = new InteropHelp.UTF8StringHandle(pchChangeNote)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SubmitItemUpdate(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchChangeNote2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static EItemUpdateStatus GetItemUpdateProgress(UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemUpdateProgress(CSteamGameServerAPIContext.GetSteamUGC(), handle, out punBytesProcessed, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Workshop Consumer API</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SetUserItemVote(PublishedFileId_t nPublishedFileID, bool bVoteUp) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SetUserItemVote(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, bVoteUp);\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetUserItemVote(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_GetUserItemVote(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t AddItemToFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddItemToFavorites(CSteamGameServerAPIContext.GetSteamUGC(), nAppId, nPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveItemFromFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveItemFromFavorites(CSteamGameServerAPIContext.GetSteamUGC(), nAppId, nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> subscribe to this item, will be installed ASAP</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SubscribeItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SubscribeItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> unsubscribe from this item, will be uninstalled after game quits</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t UnsubscribeItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_UnsubscribeItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> number of subscribed items</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumSubscribedItems() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetNumSubscribedItems(CSteamGameServerAPIContext.GetSteamUGC());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> all subscribed item PublishFileIDs</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSubscribedItems(PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetSubscribedItems(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, cMaxEntries);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get EItemState flags about item on this client</para>\n\t\t/// </summary>\n\t\tpublic static uint GetItemState(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemState(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get info about currently installed content on disc for items that have k_EItemStateInstalled set</para>\n\t\t/// <para> if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemInstallInfo(PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, out string pchFolder, uint cchFolderSize, out uint punTimeStamp) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetItemInstallInfo(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, out punSizeOnDisk, pchFolder2, cchFolderSize, out punTimeStamp);\n\t\t\tpchFolder = ret ? InteropHelp.PtrToStringUTF8(pchFolder2) : null;\n\t\t\tMarshal.FreeHGlobal(pchFolder2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDownloadInfo(PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemDownloadInfo(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, out punBytesDownloaded, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed,</para>\n\t\t/// <para> then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time.</para>\n\t\t/// <para> If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP.</para>\n\t\t/// </summary>\n\t\tpublic static bool DownloadItem(PublishedFileId_t nPublishedFileID, bool bHighPriority) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUGC_DownloadItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, bHighPriority);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> game servers can set a specific workshop folder before issuing any UGC commands.</para>\n\t\t/// <para> This is helpful if you want to support multiple game servers running out of the same install folder</para>\n\t\t/// </summary>\n\t\tpublic static bool BInitWorkshopForGameServer(DepotId_t unWorkshopDepotID, string pszFolder) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pszFolder2 = new InteropHelp.UTF8StringHandle(pszFolder)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_BInitWorkshopForGameServer(CSteamGameServerAPIContext.GetSteamUGC(), unWorkshopDepotID, pszFolder2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> SuspendDownloads( true ) will suspend all workshop downloads until SuspendDownloads( false ) is called or the game ends</para>\n\t\t/// </summary>\n\t\tpublic static void SuspendDownloads(bool bSuspend) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUGC_SuspendDownloads(CSteamGameServerAPIContext.GetSteamUGC(), bSuspend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> usage tracking</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t StartPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StartPlaytimeTracking(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\tpublic static SteamAPICall_t StopPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTracking(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\tpublic static SteamAPICall_t StopPlaytimeTrackingForAllItems() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTrackingForAllItems(CSteamGameServerAPIContext.GetSteamUGC());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> parent-child relationship or dependency management</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AddDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddDependency(CSteamGameServerAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveDependency(CSteamGameServerAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> add/remove app dependence/requirements (usually DLC)</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AddAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddAppDependency(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, nAppID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveAppDependency(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times</para>\n\t\t/// <para> until all app dependencies have been returned</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetAppDependencies(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_GetAppDependencies(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> delete the item without prompting the user</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t DeleteItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_DeleteItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamgameserverutils.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamGameServerUtils {\n\t\t/// <summary>\n\t\t/// <para> return the number of seconds since the user</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSecondsSinceAppActive() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetSecondsSinceAppActive(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\tpublic static uint GetSecondsSinceComputerActive() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetSecondsSinceComputerActive(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> the universe this client is connecting to</para>\n\t\t/// </summary>\n\t\tpublic static EUniverse GetConnectedUniverse() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetConnectedUniverse(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam server time.  Number of seconds since January 1, 1970, GMT (i.e unix time)</para>\n\t\t/// </summary>\n\t\tpublic static uint GetServerRealTime() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetServerRealTime(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database)</para>\n\t\t/// <para> e.g \"US\" or \"UK\".</para>\n\t\t/// </summary>\n\t\tpublic static string GetIPCountry() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetIPCountry(CSteamGameServerAPIContext.GetSteamUtils()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the image exists, and valid sizes were filled out</para>\n\t\t/// </summary>\n\t\tpublic static bool GetImageSize(int iImage, out uint pnWidth, out uint pnHeight) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetImageSize(CSteamGameServerAPIContext.GetSteamUtils(), iImage, out pnWidth, out pnHeight);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the image exists, and the buffer was successfully filled out</para>\n\t\t/// <para> results are returned in RGBA format</para>\n\t\t/// <para> the destination buffer size should be 4 * height * width * sizeof(char)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetImageRGBA(int iImage, byte[] pubDest, int nDestBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetImageRGBA(CSteamGameServerAPIContext.GetSteamUtils(), iImage, pubDest, nDestBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the IP of the reporting server for valve - currently only used in Source engine games</para>\n\t\t/// </summary>\n\t\tpublic static bool GetCSERIPPort(out uint unIP, out ushort usPort) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetCSERIPPort(CSteamGameServerAPIContext.GetSteamUtils(), out unIP, out usPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return the amount of battery power left in the current system in % [0..100], 255 for being on AC power</para>\n\t\t/// </summary>\n\t\tpublic static byte GetCurrentBatteryPower() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetCurrentBatteryPower(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the appID of the current process</para>\n\t\t/// </summary>\n\t\tpublic static AppId_t GetAppID() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn (AppId_t)NativeMethods.ISteamUtils_GetAppID(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the position where the overlay instance for the currently calling game should show notifications.</para>\n\t\t/// <para> This position is per-game and if this function is called from outside of a game context it will do nothing.</para>\n\t\t/// </summary>\n\t\tpublic static void SetOverlayNotificationPosition(ENotificationPosition eNotificationPosition) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUtils_SetOverlayNotificationPosition(CSteamGameServerAPIContext.GetSteamUtils(), eNotificationPosition);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API asynchronous call results</para>\n\t\t/// <para> can be used directly, but more commonly used via the callback dispatch API (see steam_api.h)</para>\n\t\t/// </summary>\n\t\tpublic static bool IsAPICallCompleted(SteamAPICall_t hSteamAPICall, out bool pbFailed) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsAPICallCompleted(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall, out pbFailed);\n\t\t}\n\n\t\tpublic static ESteamAPICallFailure GetAPICallFailureReason(SteamAPICall_t hSteamAPICall) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetAPICallFailureReason(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall);\n\t\t}\n\n\t\tpublic static bool GetAPICallResult(SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetAPICallResult(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall, pCallback, cubCallback, iCallbackExpected, out pbFailed);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of IPC calls made since the last time this function was called</para>\n\t\t/// <para> Used for perf debugging so you can understand how many IPC calls your game makes per frame</para>\n\t\t/// <para> Every IPC call is at minimum a thread context switch if not a process one so you want to rate</para>\n\t\t/// <para> control how often you do them.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetIPCCallCount() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetIPCCallCount(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API warning handling</para>\n\t\t/// <para> 'int' is the severity; 0 for msg, 1 for warning</para>\n\t\t/// <para> 'const char *' is the text of the message</para>\n\t\t/// <para> callbacks will occur directly after the API function is called that generated the warning or message</para>\n\t\t/// </summary>\n\t\tpublic static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUtils_SetWarningMessageHook(CSteamGameServerAPIContext.GetSteamUtils(), pFunction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the overlay is running &amp; the user can access it. The overlay process could take a few seconds to</para>\n\t\t/// <para> start &amp; hook the game process, so this function will initially return false while the overlay is loading.</para>\n\t\t/// </summary>\n\t\tpublic static bool IsOverlayEnabled() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsOverlayEnabled(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Normally this call is unneeded if your game has a constantly running frame loop that calls the</para>\n\t\t/// <para> D3D Present API, or OGL SwapBuffers API every frame.</para>\n\t\t/// <para> However, if you have a game that only refreshes the screen on an event driven basis then that can break</para>\n\t\t/// <para> the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also</para>\n\t\t/// <para> need to Present() to the screen any time an even needing a notification happens or when the overlay is</para>\n\t\t/// <para> brought up over the game by a user.  You can use this API to ask the overlay if it currently need a present</para>\n\t\t/// <para> in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you</para>\n\t\t/// <para> refresh the screen with Present or SwapBuffers to allow the overlay to do it's work.</para>\n\t\t/// </summary>\n\t\tpublic static bool BOverlayNeedsPresent() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_BOverlayNeedsPresent(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Asynchronous call to check if an executable file has been signed using the public key set on the signing tab</para>\n\t\t/// <para> of the partner site, for example to refuse to load modified executable files.</para>\n\t\t/// <para> The result is returned in CheckFileSignature_t.</para>\n\t\t/// <para>   k_ECheckFileSignatureNoSignaturesFoundForThisApp - This app has not been configured on the signing tab of the partner site to enable this function.</para>\n\t\t/// <para>   k_ECheckFileSignatureNoSignaturesFoundForThisFile - This file is not listed on the signing tab for the partner site.</para>\n\t\t/// <para>   k_ECheckFileSignatureFileNotFound - The file does not exist on disk.</para>\n\t\t/// <para>   k_ECheckFileSignatureInvalidSignature - The file exists, and the signing tab has been set for this file, but the file is either not signed or the signature does not match.</para>\n\t\t/// <para>   k_ECheckFileSignatureValidSignature - The file is signed and the signature is valid.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CheckFileSignature(string szFileName) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var szFileName2 = new InteropHelp.UTF8StringHandle(szFileName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUtils_CheckFileSignature(CSteamGameServerAPIContext.GetSteamUtils(), szFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Activates the Big Picture text input dialog which only supports gamepad input</para>\n\t\t/// </summary>\n\t\tpublic static bool ShowGamepadTextInput(EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription))\n\t\t\tusing (var pchExistingText2 = new InteropHelp.UTF8StringHandle(pchExistingText)) {\n\t\t\t\treturn NativeMethods.ISteamUtils_ShowGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils(), eInputMode, eLineInputMode, pchDescription2, unCharMax, pchExistingText2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns previously entered text &amp; length</para>\n\t\t/// </summary>\n\t\tpublic static uint GetEnteredGamepadTextLength() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_GetEnteredGamepadTextLength(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\tpublic static bool GetEnteredGamepadTextInput(out string pchText, uint cchText) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchText2 = Marshal.AllocHGlobal((int)cchText);\n\t\t\tbool ret = NativeMethods.ISteamUtils_GetEnteredGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils(), pchText2, cchText);\n\t\t\tpchText = ret ? InteropHelp.PtrToStringUTF8(pchText2) : null;\n\t\t\tMarshal.FreeHGlobal(pchText2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the language the steam client is running in, you probably want ISteamApps::GetCurrentGameLanguage instead, this is for very special usage cases</para>\n\t\t/// </summary>\n\t\tpublic static string GetSteamUILanguage() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetSteamUILanguage(CSteamGameServerAPIContext.GetSteamUtils()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if Steam itself is running in VR mode</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamRunningInVR() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamRunningInVR(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition.</para>\n\t\t/// </summary>\n\t\tpublic static void SetOverlayNotificationInset(int nHorizontalInset, int nVerticalInset) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUtils_SetOverlayNotificationInset(CSteamGameServerAPIContext.GetSteamUtils(), nHorizontalInset, nVerticalInset);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if Steam &amp; the Steam Overlay are running in Big Picture mode</para>\n\t\t/// <para> Games much be launched through the Steam client to enable the Big Picture overlay. During development,</para>\n\t\t/// <para> a game can be added as a non-steam game to the developers library to test this feature</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamInBigPictureMode() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamInBigPictureMode(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ask SteamUI to create and render its OpenVR dashboard</para>\n\t\t/// </summary>\n\t\tpublic static void StartVRDashboard() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUtils_StartVRDashboard(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the HMD content will be streamed via Steam In-Home Streaming</para>\n\t\t/// </summary>\n\t\tpublic static bool IsVRHeadsetStreamingEnabled() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsVRHeadsetStreamingEnabled(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set whether the HMD content will be streamed via Steam In-Home Streaming</para>\n\t\t/// <para> If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be allowed.</para>\n\t\t/// <para> If this is set to false, then the application window will be streamed instead, and remote input will be allowed.</para>\n\t\t/// <para> The default is true unless \"VRHeadsetStreaming\" \"0\" is in the extended appinfo for a game.</para>\n\t\t/// <para> (this is useful for games that have asymmetric multiplayer gameplay)</para>\n\t\t/// </summary>\n\t\tpublic static void SetVRHeadsetStreamingEnabled(bool bEnabled) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tNativeMethods.ISteamUtils_SetVRHeadsetStreamingEnabled(CSteamGameServerAPIContext.GetSteamUtils(), bEnabled);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns whether this steam client is a Steam China specific client, vs the global client.</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamChinaLauncher() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamChinaLauncher(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Initializes text filtering.</para>\n\t\t/// <para>   Returns false if filtering is unavailable for the language the user is currently running in.</para>\n\t\t/// </summary>\n\t\tpublic static bool InitFilterText() {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\treturn NativeMethods.ISteamUtils_InitFilterText(CSteamGameServerAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Filters the provided input message and places the filtered result into pchOutFilteredText.</para>\n\t\t/// <para>   pchOutFilteredText is where the output will be placed, even if no filtering or censoring is performed</para>\n\t\t/// <para>   nByteSizeOutFilteredText is the size (in bytes) of pchOutFilteredText</para>\n\t\t/// <para>   pchInputText is the input string that should be filtered, which can be ASCII or UTF-8</para>\n\t\t/// <para>   bLegalOnly should be false if you want profanity and legally required filtering (where required) and true if you want legally required filtering only</para>\n\t\t/// <para>   Returns the number of characters (not bytes) filtered.</para>\n\t\t/// </summary>\n\t\tpublic static int FilterText(out string pchOutFilteredText, uint nByteSizeOutFilteredText, string pchInputMessage, bool bLegalOnly) {\n\t\t\tInteropHelp.TestIfAvailableGameServer();\n\t\t\tIntPtr pchOutFilteredText2 = Marshal.AllocHGlobal((int)nByteSizeOutFilteredText);\n\t\t\tusing (var pchInputMessage2 = new InteropHelp.UTF8StringHandle(pchInputMessage)) {\n\t\t\t\tint ret = NativeMethods.ISteamUtils_FilterText(CSteamGameServerAPIContext.GetSteamUtils(), pchOutFilteredText2, nByteSizeOutFilteredText, pchInputMessage2, bLegalOnly);\n\t\t\t\tpchOutFilteredText = ret != -1 ? InteropHelp.PtrToStringUTF8(pchOutFilteredText2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchOutFilteredText2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamhtmlsurface.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamHTMLSurface {\n\t\t/// <summary>\n\t\t/// <para> Must call init and shutdown when starting/ending use of the interface</para>\n\t\t/// </summary>\n\t\tpublic static bool Init() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTMLSurface_Init(CSteamAPIContext.GetSteamHTMLSurface());\n\t\t}\n\n\t\tpublic static bool Shutdown() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTMLSurface_Shutdown(CSteamAPIContext.GetSteamHTMLSurface());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Create a browser object for display of a html page, when creation is complete the call handle</para>\n\t\t/// <para> will return a HTML_BrowserReady_t callback for the HHTMLBrowser of your new browser.</para>\n\t\t/// <para>   The user agent string is a substring to be added to the general user agent string so you can</para>\n\t\t/// <para> identify your client on web servers.</para>\n\t\t/// <para>   The userCSS string lets you apply a CSS style sheet to every displayed page, leave null if</para>\n\t\t/// <para> you do not require this functionality.</para>\n\t\t/// <para> YOU MUST HAVE IMPLEMENTED HANDLERS FOR HTML_BrowserReady_t, HTML_StartRequest_t,</para>\n\t\t/// <para> HTML_JSAlert_t, HTML_JSConfirm_t, and HTML_FileOpenDialog_t! See the CALLBACKS</para>\n\t\t/// <para> section of this interface (AllowStartRequest, etc) for more details. If you do</para>\n\t\t/// <para> not implement these callback handlers, the browser may appear to hang instead of</para>\n\t\t/// <para> navigating to new pages or triggering javascript popups.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CreateBrowser(string pchUserAgent, string pchUserCSS) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchUserAgent2 = new InteropHelp.UTF8StringHandle(pchUserAgent))\n\t\t\tusing (var pchUserCSS2 = new InteropHelp.UTF8StringHandle(pchUserCSS)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamHTMLSurface_CreateBrowser(CSteamAPIContext.GetSteamHTMLSurface(), pchUserAgent2, pchUserCSS2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Call this when you are done with a html surface, this lets us free the resources being used by it</para>\n\t\t/// </summary>\n\t\tpublic static void RemoveBrowser(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_RemoveBrowser(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Navigate to this URL, results in a HTML_StartRequest_t as the request commences</para>\n\t\t/// </summary>\n\t\tpublic static void LoadURL(HHTMLBrowser unBrowserHandle, string pchURL, string pchPostData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchURL2 = new InteropHelp.UTF8StringHandle(pchURL))\n\t\t\tusing (var pchPostData2 = new InteropHelp.UTF8StringHandle(pchPostData)) {\n\t\t\t\tNativeMethods.ISteamHTMLSurface_LoadURL(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchURL2, pchPostData2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Tells the surface the size in pixels to display the surface</para>\n\t\t/// </summary>\n\t\tpublic static void SetSize(HHTMLBrowser unBrowserHandle, uint unWidth, uint unHeight) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetSize(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, unWidth, unHeight);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Stop the load of the current html page</para>\n\t\t/// </summary>\n\t\tpublic static void StopLoad(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_StopLoad(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Reload (most likely from local cache) the current page</para>\n\t\t/// </summary>\n\t\tpublic static void Reload(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_Reload(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> navigate back in the page history</para>\n\t\t/// </summary>\n\t\tpublic static void GoBack(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_GoBack(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> navigate forward in the page history</para>\n\t\t/// </summary>\n\t\tpublic static void GoForward(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_GoForward(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> add this header to any url requests from this browser</para>\n\t\t/// </summary>\n\t\tpublic static void AddHeader(HHTMLBrowser unBrowserHandle, string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\tNativeMethods.ISteamHTMLSurface_AddHeader(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> run this javascript script in the currently loaded page</para>\n\t\t/// </summary>\n\t\tpublic static void ExecuteJavascript(HHTMLBrowser unBrowserHandle, string pchScript) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchScript2 = new InteropHelp.UTF8StringHandle(pchScript)) {\n\t\t\t\tNativeMethods.ISteamHTMLSurface_ExecuteJavascript(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchScript2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Mouse click and mouse movement commands</para>\n\t\t/// </summary>\n\t\tpublic static void MouseUp(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_MouseUp(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton);\n\t\t}\n\n\t\tpublic static void MouseDown(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_MouseDown(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton);\n\t\t}\n\n\t\tpublic static void MouseDoubleClick(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_MouseDoubleClick(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> x and y are relative to the HTML bounds</para>\n\t\t/// </summary>\n\t\tpublic static void MouseMove(HHTMLBrowser unBrowserHandle, int x, int y) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_MouseMove(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, x, y);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> nDelta is pixels of scroll</para>\n\t\t/// </summary>\n\t\tpublic static void MouseWheel(HHTMLBrowser unBrowserHandle, int nDelta) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_MouseWheel(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nDelta);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> keyboard interactions, native keycode is the virtual key code value from your OS, system key flags the key to not</para>\n\t\t/// <para> be sent as a typed character as well as a key down</para>\n\t\t/// </summary>\n\t\tpublic static void KeyDown(HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, bool bIsSystemKey = false) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_KeyDown(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nNativeKeyCode, eHTMLKeyModifiers, bIsSystemKey);\n\t\t}\n\n\t\tpublic static void KeyUp(HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_KeyUp(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nNativeKeyCode, eHTMLKeyModifiers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> cUnicodeChar is the unicode character point for this keypress (and potentially multiple chars per press)</para>\n\t\t/// </summary>\n\t\tpublic static void KeyChar(HHTMLBrowser unBrowserHandle, uint cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_KeyChar(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, cUnicodeChar, eHTMLKeyModifiers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> programmatically scroll this many pixels on the page</para>\n\t\t/// </summary>\n\t\tpublic static void SetHorizontalScroll(HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetHorizontalScroll(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nAbsolutePixelScroll);\n\t\t}\n\n\t\tpublic static void SetVerticalScroll(HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetVerticalScroll(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nAbsolutePixelScroll);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> tell the html control if it has key focus currently, controls showing the I-beam cursor in text controls amongst other things</para>\n\t\t/// </summary>\n\t\tpublic static void SetKeyFocus(HHTMLBrowser unBrowserHandle, bool bHasKeyFocus) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetKeyFocus(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bHasKeyFocus);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> open the current pages html code in the local editor of choice, used for debugging</para>\n\t\t/// </summary>\n\t\tpublic static void ViewSource(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_ViewSource(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> copy the currently selected text on the html page to the local clipboard</para>\n\t\t/// </summary>\n\t\tpublic static void CopyToClipboard(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_CopyToClipboard(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> paste from the local clipboard to the current html page</para>\n\t\t/// </summary>\n\t\tpublic static void PasteFromClipboard(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_PasteFromClipboard(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> find this string in the browser, if bCurrentlyInFind is true then instead cycle to the next matching element</para>\n\t\t/// </summary>\n\t\tpublic static void Find(HHTMLBrowser unBrowserHandle, string pchSearchStr, bool bCurrentlyInFind, bool bReverse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchSearchStr2 = new InteropHelp.UTF8StringHandle(pchSearchStr)) {\n\t\t\t\tNativeMethods.ISteamHTMLSurface_Find(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchSearchStr2, bCurrentlyInFind, bReverse);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> cancel a currently running find</para>\n\t\t/// </summary>\n\t\tpublic static void StopFind(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_StopFind(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return details about the link at position x,y on the current page</para>\n\t\t/// </summary>\n\t\tpublic static void GetLinkAtPosition(HHTMLBrowser unBrowserHandle, int x, int y) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_GetLinkAtPosition(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, x, y);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set a webcookie for the hostname in question</para>\n\t\t/// </summary>\n\t\tpublic static void SetCookie(string pchHostname, string pchKey, string pchValue, string pchPath = \"/\", uint nExpires = 0, bool bSecure = false, bool bHTTPOnly = false) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchHostname2 = new InteropHelp.UTF8StringHandle(pchHostname))\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue))\n\t\t\tusing (var pchPath2 = new InteropHelp.UTF8StringHandle(pchPath)) {\n\t\t\t\tNativeMethods.ISteamHTMLSurface_SetCookie(CSteamAPIContext.GetSteamHTMLSurface(), pchHostname2, pchKey2, pchValue2, pchPath2, nExpires, bSecure, bHTTPOnly);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Zoom the current page by flZoom ( from 0.0 to 2.0, so to zoom to 120% use 1.2 ), zooming around point X,Y in the page (use 0,0 if you don't care)</para>\n\t\t/// </summary>\n\t\tpublic static void SetPageScaleFactor(HHTMLBrowser unBrowserHandle, float flZoom, int nPointX, int nPointY) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetPageScaleFactor(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, flZoom, nPointX, nPointY);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Enable/disable low-resource background mode, where javascript and repaint timers are throttled, resources are</para>\n\t\t/// <para> more aggressively purged from memory, and audio/video elements are paused. When background mode is enabled,</para>\n\t\t/// <para> all HTML5 video and audio objects will execute \".pause()\" and gain the property \"._steam_background_paused = 1\".</para>\n\t\t/// <para> When background mode is disabled, any video or audio objects with that property will resume with \".play()\".</para>\n\t\t/// </summary>\n\t\tpublic static void SetBackgroundMode(HHTMLBrowser unBrowserHandle, bool bBackgroundMode) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetBackgroundMode(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bBackgroundMode);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Scale the output display space by this factor, this is useful when displaying content on high dpi devices.</para>\n\t\t/// <para> Specifies the ratio between physical and logical pixels.</para>\n\t\t/// </summary>\n\t\tpublic static void SetDPIScalingFactor(HHTMLBrowser unBrowserHandle, float flDPIScaling) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_SetDPIScalingFactor(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, flDPIScaling);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Open HTML/JS developer tools</para>\n\t\t/// </summary>\n\t\tpublic static void OpenDeveloperTools(HHTMLBrowser unBrowserHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_OpenDeveloperTools(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> CALLBACKS</para>\n\t\t/// <para>  These set of functions are used as responses to callback requests</para>\n\t\t/// <para> You MUST call this in response to a HTML_StartRequest_t callback</para>\n\t\t/// <para>  Set bAllowed to true to allow this navigation, false to cancel it and stay</para>\n\t\t/// <para> on the current page. You can use this feature to limit the valid pages</para>\n\t\t/// <para> allowed in your HTML surface.</para>\n\t\t/// </summary>\n\t\tpublic static void AllowStartRequest(HHTMLBrowser unBrowserHandle, bool bAllowed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_AllowStartRequest(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bAllowed);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> You MUST call this in response to a HTML_JSAlert_t or HTML_JSConfirm_t callback</para>\n\t\t/// <para>  Set bResult to true for the OK option of a confirm, use false otherwise</para>\n\t\t/// </summary>\n\t\tpublic static void JSDialogResponse(HHTMLBrowser unBrowserHandle, bool bResult) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_JSDialogResponse(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bResult);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> You MUST call this in response to a HTML_FileOpenDialog_t callback</para>\n\t\t/// </summary>\n\t\tpublic static void FileLoadDialogResponse(HHTMLBrowser unBrowserHandle, IntPtr pchSelectedFiles) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamHTMLSurface_FileLoadDialogResponse(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchSelectedFiles);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamhttp.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamHTTP {\n\t\t/// <summary>\n\t\t/// <para> Initializes a new HTTP request, returning a handle to use in further operations on it.  Requires</para>\n\t\t/// <para> the method (GET or POST) and the absolute URL for the request.  Both http and https are supported,</para>\n\t\t/// <para> so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/</para>\n\t\t/// <para> or such.</para>\n\t\t/// </summary>\n\t\tpublic static HTTPRequestHandle CreateHTTPRequest(EHTTPMethod eHTTPRequestMethod, string pchAbsoluteURL) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchAbsoluteURL2 = new InteropHelp.UTF8StringHandle(pchAbsoluteURL)) {\n\t\t\t\treturn (HTTPRequestHandle)NativeMethods.ISteamHTTP_CreateHTTPRequest(CSteamAPIContext.GetSteamHTTP(), eHTTPRequestMethod, pchAbsoluteURL2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after</para>\n\t\t/// <para> sending the request.  This is just so the caller can easily keep track of which callbacks go with which request data.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestContextValue(HTTPRequestHandle hRequest, ulong ulContextValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestContextValue(CSteamAPIContext.GetSteamHTTP(), hRequest, ulContextValue);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a timeout in seconds for the HTTP request, must be called prior to sending the request.  Default</para>\n\t\t/// <para> timeout is 60 seconds if you don't call this.  Returns false if the handle is invalid, or the request</para>\n\t\t/// <para> has already been sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestNetworkActivityTimeout(HTTPRequestHandle hRequest, uint unTimeoutSeconds) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(CSteamAPIContext.GetSteamHTTP(), hRequest, unTimeoutSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a request header value for the request, must be called prior to sending the request.  Will</para>\n\t\t/// <para> return false if the handle is invalid or the request is already sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, string pchHeaderValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName))\n\t\t\tusing (var pchHeaderValue2 = new InteropHelp.UTF8StringHandle(pchHeaderValue)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestHeaderValue(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pchHeaderValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified</para>\n\t\t/// <para> when creating the request.  Must be called prior to sending the request.  Will return false if the</para>\n\t\t/// <para> handle is invalid or the request is already sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestGetOrPostParameter(HTTPRequestHandle hRequest, string pchParamName, string pchParamValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchParamName2 = new InteropHelp.UTF8StringHandle(pchParamName))\n\t\t\tusing (var pchParamValue2 = new InteropHelp.UTF8StringHandle(pchParamValue)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestGetOrPostParameter(CSteamAPIContext.GetSteamHTTP(), hRequest, pchParamName2, pchParamValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on</para>\n\t\t/// <para> asynchronous response via callback.</para>\n\t\t/// <para> Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control</para>\n\t\t/// <para> header and only do a local cache lookup rather than sending any actual remote request.</para>\n\t\t/// </summary>\n\t\tpublic static bool SendHTTPRequest(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SendHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest, out pCallHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on</para>\n\t\t/// <para> asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and</para>\n\t\t/// <para> HTTPRequestDataReceived_t callbacks while streaming.</para>\n\t\t/// </summary>\n\t\tpublic static bool SendHTTPRequestAndStreamResponse(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SendHTTPRequestAndStreamResponse(CSteamAPIContext.GetSteamHTTP(), hRequest, out pCallHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move</para>\n\t\t/// <para> the specified request to the tail of the queue.  Returns false on invalid handle, or if the request is not yet sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool DeferHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_DeferHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move</para>\n\t\t/// <para> the specified request to the head of the queue.  Returns false on invalid handle, or if the request is not yet sent.</para>\n\t\t/// </summary>\n\t\tpublic static bool PrioritizeHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_PrioritizeHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also</para>\n\t\t/// <para> returns the size of the header value if present so the caller and allocate a correctly sized buffer for</para>\n\t\t/// <para> GetHTTPResponseHeaderValue.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseHeaderSize(HTTPRequestHandle hRequest, string pchHeaderName, out uint unResponseHeaderSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseHeaderSize(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, out unResponseHeaderSize);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> header is not present or if your buffer is too small to contain it's value.  You should first call</para>\n\t\t/// <para> BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseHeaderValue(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pHeaderValueBuffer, unBufferSize);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> handle is invalid.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseBodySize(HTTPRequestHandle hRequest, out uint unBodySize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseBodySize(CSteamAPIContext.GetSteamHTTP(), hRequest, out unBodySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the</para>\n\t\t/// <para> handle is invalid or is to a streaming response, or if the provided buffer is not the correct size.  Use BGetHTTPResponseBodySize first to find out</para>\n\t\t/// <para> the correct buffer size to use.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPResponseBodyData(HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPResponseBodyData(CSteamAPIContext.GetSteamHTTP(), hRequest, pBodyDataBuffer, unBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the</para>\n\t\t/// <para> handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset</para>\n\t\t/// <para> do not match the size and offset sent in HTTPRequestDataReceived_t.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPStreamingResponseBodyData(HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPStreamingResponseBodyData(CSteamAPIContext.GetSteamHTTP(), hRequest, cOffset, pBodyDataBuffer, unBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t</para>\n\t\t/// <para> callback and finishing using the response.</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseHTTPRequest(HTTPRequestHandle hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_ReleaseHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets progress on downloading the body for the request.  This will be zero unless a response header has already been</para>\n\t\t/// <para> received which included a content-length field.  For responses that contain no content-length it will report</para>\n\t\t/// <para> zero for the duration of the request as the size is unknown until the connection closes.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPDownloadProgressPct(HTTPRequestHandle hRequest, out float pflPercentOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPDownloadProgressPct(CSteamAPIContext.GetSteamHTTP(), hRequest, out pflPercentOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the body for an HTTP Post request.  Will fail and return false on a GET request, and will fail if POST params</para>\n\t\t/// <para> have already been set for the request.  Setting this raw body makes it the only contents for the post, the pchContentType</para>\n\t\t/// <para> parameter will set the content-type header for the request so the server may know how to interpret the body.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestRawPostBody(HTTPRequestHandle hRequest, string pchContentType, byte[] pubBody, uint unBodyLen) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchContentType2 = new InteropHelp.UTF8StringHandle(pchContentType)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestRawPostBody(CSteamAPIContext.GetSteamHTTP(), hRequest, pchContentType2, pubBody, unBodyLen);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Creates a cookie container handle which you must later free with ReleaseCookieContainer().  If bAllowResponsesToModify=true</para>\n\t\t/// <para> than any response to your requests using this cookie container may add new cookies which may be transmitted with</para>\n\t\t/// <para> future requests.  If bAllowResponsesToModify=false than only cookies you explicitly set will be sent.  This API is just for</para>\n\t\t/// <para> during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across</para>\n\t\t/// <para> repeat executions of your process.</para>\n\t\t/// </summary>\n\t\tpublic static HTTPCookieContainerHandle CreateCookieContainer(bool bAllowResponsesToModify) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HTTPCookieContainerHandle)NativeMethods.ISteamHTTP_CreateCookieContainer(CSteamAPIContext.GetSteamHTTP(), bAllowResponsesToModify);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Release a cookie container you are finished using, freeing it's memory</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseCookieContainer(HTTPCookieContainerHandle hCookieContainer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_ReleaseCookieContainer(CSteamAPIContext.GetSteamHTTP(), hCookieContainer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Adds a cookie to the specified cookie container that will be used with future requests.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetCookie(HTTPCookieContainerHandle hCookieContainer, string pchHost, string pchUrl, string pchCookie) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchHost2 = new InteropHelp.UTF8StringHandle(pchHost))\n\t\t\tusing (var pchUrl2 = new InteropHelp.UTF8StringHandle(pchUrl))\n\t\t\tusing (var pchCookie2 = new InteropHelp.UTF8StringHandle(pchCookie)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetCookie(CSteamAPIContext.GetSteamHTTP(), hCookieContainer, pchHost2, pchUrl2, pchCookie2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the cookie container to use for a HTTP request</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestCookieContainer(HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestCookieContainer(CSteamAPIContext.GetSteamHTTP(), hRequest, hCookieContainer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestUserAgentInfo(HTTPRequestHandle hRequest, string pchUserAgentInfo) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchUserAgentInfo2 = new InteropHelp.UTF8StringHandle(pchUserAgentInfo)) {\n\t\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestUserAgentInfo(CSteamAPIContext.GetSteamHTTP(), hRequest, pchUserAgentInfo2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Disable or re-enable verification of SSL/TLS certificates.</para>\n\t\t/// <para> By default, certificates are checked for all HTTPS requests.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestRequiresVerifiedCertificate(HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(CSteamAPIContext.GetSteamHTTP(), hRequest, bRequireVerifiedCertificate);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout</para>\n\t\t/// <para> which can bump everytime we get more data</para>\n\t\t/// </summary>\n\t\tpublic static bool SetHTTPRequestAbsoluteTimeoutMS(HTTPRequestHandle hRequest, uint unMilliseconds) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(CSteamAPIContext.GetSteamHTTP(), hRequest, unMilliseconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Check if the reason the request failed was because we timed it out (rather than some harder failure)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetHTTPRequestWasTimedOut(HTTPRequestHandle hRequest, out bool pbWasTimedOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamHTTP_GetHTTPRequestWasTimedOut(CSteamAPIContext.GetSteamHTTP(), hRequest, out pbWasTimedOut);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteaminput.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamInput {\n\t\t/// <summary>\n\t\t/// <para> Init and Shutdown must be called when starting/ending use of this interface</para>\n\t\t/// </summary>\n\t\tpublic static bool Init() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_Init(CSteamAPIContext.GetSteamInput());\n\t\t}\n\n\t\tpublic static bool Shutdown() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_Shutdown(CSteamAPIContext.GetSteamInput());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Synchronize API state with the latest Steam Controller inputs available. This</para>\n\t\t/// <para> is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest</para>\n\t\t/// <para> possible latency, you call this directly before reading controller state. This must</para>\n\t\t/// <para> be called from somewhere before GetConnectedControllers will return any handles</para>\n\t\t/// </summary>\n\t\tpublic static void RunFrame() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_RunFrame(CSteamAPIContext.GetSteamInput());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Enumerate currently connected Steam Input enabled devices - developers can opt in controller by type (ex: Xbox/Playstation/etc) via</para>\n\t\t/// <para> the Steam Input settings in the Steamworks site or users can opt-in in their controller settings in Steam.</para>\n\t\t/// <para> handlesOut should point to a STEAM_INPUT_MAX_COUNT sized array of InputHandle_t handles</para>\n\t\t/// <para> Returns the number of handles written to handlesOut</para>\n\t\t/// </summary>\n\t\tpublic static int GetConnectedControllers(InputHandle_t[] handlesOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (handlesOut != null && handlesOut.Length != Constants.STEAM_INPUT_MAX_COUNT) {\n\t\t\t\tthrow new System.ArgumentException(\"handlesOut must be the same size as Constants.STEAM_INPUT_MAX_COUNT!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInput_GetConnectedControllers(CSteamAPIContext.GetSteamInput(), handlesOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> ACTION SETS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static InputActionSetHandle_t GetActionSetHandle(string pszActionSetName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionSetName2 = new InteropHelp.UTF8StringHandle(pszActionSetName)) {\n\t\t\t\treturn (InputActionSetHandle_t)NativeMethods.ISteamInput_GetActionSetHandle(CSteamAPIContext.GetSteamInput(), pszActionSetName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')</para>\n\t\t/// <para> This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in</para>\n\t\t/// <para> your state loops, instead of trying to place it in all of your state transitions.</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateActionSet(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_ActivateActionSet(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle);\n\t\t}\n\n\t\tpublic static InputActionSetHandle_t GetCurrentActionSet(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (InputActionSetHandle_t)NativeMethods.ISteamInput_GetCurrentActionSet(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ACTION SET LAYERS</para>\n\t\t/// </summary>\n\t\tpublic static void ActivateActionSetLayer(InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_ActivateActionSetLayer(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetLayerHandle);\n\t\t}\n\n\t\tpublic static void DeactivateActionSetLayer(InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_DeactivateActionSetLayer(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetLayerHandle);\n\t\t}\n\n\t\tpublic static void DeactivateAllActionSetLayers(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_DeactivateAllActionSetLayers(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Enumerate currently active layers.</para>\n\t\t/// <para> handlesOut should point to a STEAM_INPUT_MAX_ACTIVE_LAYERS sized array of ControllerActionSetHandle_t handles</para>\n\t\t/// <para> Returns the number of handles written to handlesOut</para>\n\t\t/// </summary>\n\t\tpublic static int GetActiveActionSetLayers(InputHandle_t inputHandle, InputActionSetHandle_t[] handlesOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (handlesOut != null && handlesOut.Length != Constants.STEAM_INPUT_MAX_ACTIVE_LAYERS) {\n\t\t\t\tthrow new System.ArgumentException(\"handlesOut must be the same size as Constants.STEAM_INPUT_MAX_ACTIVE_LAYERS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInput_GetActiveActionSetLayers(CSteamAPIContext.GetSteamInput(), inputHandle, handlesOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> ACTIONS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static InputDigitalActionHandle_t GetDigitalActionHandle(string pszActionName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) {\n\t\t\t\treturn (InputDigitalActionHandle_t)NativeMethods.ISteamInput_GetDigitalActionHandle(CSteamAPIContext.GetSteamInput(), pszActionName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the current state of the supplied digital game action</para>\n\t\t/// </summary>\n\t\tpublic static InputDigitalActionData_t GetDigitalActionData(InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetDigitalActionData(CSteamAPIContext.GetSteamInput(), inputHandle, digitalActionHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.</para>\n\t\t/// <para> originsOut should point to a STEAM_INPUT_MAX_ORIGINS sized array of EInputActionOrigin handles. The EInputActionOrigin enum will get extended as support for new controller controllers gets added to</para>\n\t\t/// <para> the Steam client and will exceed the values from this header, please check bounds if you are using a look up table.</para>\n\t\t/// </summary>\n\t\tpublic static int GetDigitalActionOrigins(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, EInputActionOrigin[] originsOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (originsOut != null && originsOut.Length != Constants.STEAM_INPUT_MAX_ORIGINS) {\n\t\t\t\tthrow new System.ArgumentException(\"originsOut must be the same size as Constants.STEAM_INPUT_MAX_ORIGINS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInput_GetDigitalActionOrigins(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle, digitalActionHandle, originsOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.</para>\n\t\t/// </summary>\n\t\tpublic static InputAnalogActionHandle_t GetAnalogActionHandle(string pszActionName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) {\n\t\t\t\treturn (InputAnalogActionHandle_t)NativeMethods.ISteamInput_GetAnalogActionHandle(CSteamAPIContext.GetSteamInput(), pszActionName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the current state of these supplied analog game action</para>\n\t\t/// </summary>\n\t\tpublic static InputAnalogActionData_t GetAnalogActionData(InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetAnalogActionData(CSteamAPIContext.GetSteamInput(), inputHandle, analogActionHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.</para>\n\t\t/// <para> originsOut should point to a STEAM_INPUT_MAX_ORIGINS sized array of EInputActionOrigin handles. The EInputActionOrigin enum will get extended as support for new controller controllers gets added to</para>\n\t\t/// <para> the Steam client and will exceed the values from this header, please check bounds if you are using a look up table.</para>\n\t\t/// </summary>\n\t\tpublic static int GetAnalogActionOrigins(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, EInputActionOrigin[] originsOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (originsOut != null && originsOut.Length != Constants.STEAM_INPUT_MAX_ORIGINS) {\n\t\t\t\tthrow new System.ArgumentException(\"originsOut must be the same size as Constants.STEAM_INPUT_MAX_ORIGINS!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInput_GetAnalogActionOrigins(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle, analogActionHandle, originsOut);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get a local path to art for on-screen glyph for a particular origin</para>\n\t\t/// </summary>\n\t\tpublic static string GetGlyphForActionOrigin(EInputActionOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphForActionOrigin(CSteamAPIContext.GetSteamInput(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns a localized string (from Steam's language setting) for the specified origin.</para>\n\t\t/// </summary>\n\t\tpublic static string GetStringForActionOrigin(EInputActionOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForActionOrigin(CSteamAPIContext.GetSteamInput(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Stop analog momentum for the action if it is a mouse action in trackball mode</para>\n\t\t/// </summary>\n\t\tpublic static void StopAnalogActionMomentum(InputHandle_t inputHandle, InputAnalogActionHandle_t eAction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_StopAnalogActionMomentum(CSteamAPIContext.GetSteamInput(), inputHandle, eAction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns raw motion data from the specified device</para>\n\t\t/// </summary>\n\t\tpublic static InputMotionData_t GetMotionData(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetMotionData(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> OUTPUTS</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Trigger a vibration event on supported controllers - Steam will translate these commands into haptic pulses for Steam Controllers</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerVibration(InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_TriggerVibration(CSteamAPIContext.GetSteamInput(), inputHandle, usLeftSpeed, usRightSpeed);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set the controller LED color on supported controllers. nFlags is a bitmask of values from ESteamInputLEDFlag - 0 will default to setting a color. Steam will handle</para>\n\t\t/// <para> the behavior on exit of your program so you don't need to try restore the default as you are shutting down</para>\n\t\t/// </summary>\n\t\tpublic static void SetLEDColor(InputHandle_t inputHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_SetLEDColor(CSteamAPIContext.GetSteamInput(), inputHandle, nColorR, nColorG, nColorB, nFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger a haptic pulse on a Steam Controller - if you are approximating rumble you may want to use TriggerVibration instead.</para>\n\t\t/// <para> Good uses for Haptic pulses include chimes, noises, or directional gameplay feedback (taking damage, footstep locations, etc).</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerHapticPulse(InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_TriggerHapticPulse(CSteamAPIContext.GetSteamInput(), inputHandle, eTargetPad, usDurationMicroSec);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trigger a haptic pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times. If you are approximating rumble you may want to use TriggerVibration instead.</para>\n\t\t/// <para> nFlags is currently unused and reserved for future use.</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerRepeatedHapticPulse(InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInput_TriggerRepeatedHapticPulse(CSteamAPIContext.GetSteamInput(), inputHandle, eTargetPad, usDurationMicroSec, usOffMicroSec, unRepeat, nFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Utility functions availible without using the rest of Steam Input API</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Invokes the Steam overlay and brings up the binding screen if the user is using Big Picture Mode</para>\n\t\t/// <para> If the user is not in Big Picture Mode it will open up the binding in a new window</para>\n\t\t/// </summary>\n\t\tpublic static bool ShowBindingPanel(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_ShowBindingPanel(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the input type for a particular handle</para>\n\t\t/// </summary>\n\t\tpublic static ESteamInputType GetInputTypeForHandle(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetInputTypeForHandle(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated controller handle for the specified emulated gamepad - can be used with the above 2 functions</para>\n\t\t/// <para> to identify controllers presented to your game over Xinput. Returns 0 if the Xinput index isn't associated with Steam Input</para>\n\t\t/// </summary>\n\t\tpublic static InputHandle_t GetControllerForGamepadIndex(int nIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (InputHandle_t)NativeMethods.ISteamInput_GetControllerForGamepadIndex(CSteamAPIContext.GetSteamInput(), nIndex);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the associated gamepad index for the specified controller, if emulating a gamepad or -1 if not associated with an Xinput index</para>\n\t\t/// </summary>\n\t\tpublic static int GetGamepadIndexForController(InputHandle_t ulinputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetGamepadIndexForController(CSteamAPIContext.GetSteamInput(), ulinputHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns a localized string (from Steam's language setting) for the specified Xbox controller origin.</para>\n\t\t/// </summary>\n\t\tpublic static string GetStringForXboxOrigin(EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForXboxOrigin(CSteamAPIContext.GetSteamInput(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get a local path to art for on-screen glyph for a particular Xbox controller origin</para>\n\t\t/// </summary>\n\t\tpublic static string GetGlyphForXboxOrigin(EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphForXboxOrigin(CSteamAPIContext.GetSteamInput(), eOrigin));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the equivalent ActionOrigin for a given Xbox controller origin this can be chained with GetGlyphForActionOrigin to provide future proof glyphs for</para>\n\t\t/// <para> non-Steam Input API action games. Note - this only translates the buttons directly and doesn't take into account any remapping a user has made in their configuration</para>\n\t\t/// </summary>\n\t\tpublic static EInputActionOrigin GetActionOriginFromXboxOrigin(InputHandle_t inputHandle, EXboxOrigin eOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetActionOriginFromXboxOrigin(CSteamAPIContext.GetSteamInput(), inputHandle, eOrigin);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Convert an origin to another controller type - for inputs not present on the other controller type this will return k_EInputActionOrigin_None</para>\n\t\t/// <para> When a new input type is added you will be able to pass in k_ESteamInputType_Unknown and the closest origin that your version of the SDK recognized will be returned</para>\n\t\t/// <para> ex: if a Playstation 5 controller was released this function would return Playstation 4 origins.</para>\n\t\t/// </summary>\n\t\tpublic static EInputActionOrigin TranslateActionOrigin(ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_TranslateActionOrigin(CSteamAPIContext.GetSteamInput(), eDestinationInputType, eSourceOrigin);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the binding revision for a given device. Returns false if the handle was not valid or if a mapping is not yet loaded for the device</para>\n\t\t/// </summary>\n\t\tpublic static bool GetDeviceBindingRevision(InputHandle_t inputHandle, out int pMajor, out int pMinor) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetDeviceBindingRevision(CSteamAPIContext.GetSteamInput(), inputHandle, out pMajor, out pMinor);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the Steam Remote Play session ID associated with a device, or 0 if there is no session associated with it</para>\n\t\t/// <para> See isteamremoteplay.h for more information on Steam Remote Play sessions</para>\n\t\t/// </summary>\n\t\tpublic static uint GetRemotePlaySessionID(InputHandle_t inputHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInput_GetRemotePlaySessionID(CSteamAPIContext.GetSteamInput(), inputHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteaminventory.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamInventory {\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC RESULT MANAGEMENT</para>\n\t\t/// <para> Asynchronous inventory queries always output a result handle which can be used with</para>\n\t\t/// <para> GetResultStatus, GetResultItems, etc. A SteamInventoryResultReady_t callback will</para>\n\t\t/// <para> be triggered when the asynchronous result becomes ready (or fails).</para>\n\t\t/// <para> Find out the status of an asynchronous inventory result handle. Possible values:</para>\n\t\t/// <para>  k_EResultPending - still in progress</para>\n\t\t/// <para>  k_EResultOK - done, result ready</para>\n\t\t/// <para>  k_EResultExpired - done, result ready, maybe out of date (see DeserializeResult)</para>\n\t\t/// <para>  k_EResultInvalidParam - ERROR: invalid API call parameters</para>\n\t\t/// <para>  k_EResultServiceUnavailable - ERROR: service temporarily down, you may retry later</para>\n\t\t/// <para>  k_EResultLimitExceeded - ERROR: operation would exceed per-user inventory limits</para>\n\t\t/// <para>  k_EResultFail - ERROR: unknown / generic error</para>\n\t\t/// </summary>\n\t\tpublic static EResult GetResultStatus(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetResultStatus(CSteamAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Copies the contents of a result set into a flat array. The specific</para>\n\t\t/// <para> contents of the result set depend on which query which was used.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetResultItems(SteamInventoryResult_t resultHandle, SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (pOutItemsArray != null && pOutItemsArray.Length != punOutItemsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pOutItemsArray must be the same size as punOutItemsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetResultItems(CSteamAPIContext.GetSteamInventory(), resultHandle, pOutItemsArray, ref punOutItemsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> In combination with GetResultItems, you can use GetResultItemProperty to retrieve</para>\n\t\t/// <para> dynamic string properties for a given item returned in the result set.</para>\n\t\t/// <para> Property names are always composed of ASCII letters, numbers, and/or underscores.</para>\n\t\t/// <para> Pass a NULL pointer for pchPropertyName to get a comma - separated list of available</para>\n\t\t/// <para> property names.</para>\n\t\t/// <para> If pchValueBuffer is NULL, *punValueBufferSize will contain the</para>\n\t\t/// <para> suggested buffer size. Otherwise it will be the number of bytes actually copied</para>\n\t\t/// <para> to pchValueBuffer. If the results do not fit in the given buffer, partial</para>\n\t\t/// <para> results may be copied.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetResultItemProperty(SteamInventoryResult_t resultHandle, uint unItemIndex, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut);\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\tbool ret = NativeMethods.ISteamInventory_GetResultItemProperty(CSteamAPIContext.GetSteamInventory(), resultHandle, unItemIndex, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut);\n\t\t\t\tpchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValueBuffer2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the server time at which the result was generated. Compare against</para>\n\t\t/// <para> the value of IClientUtils::GetServerRealTime() to determine age.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetResultTimestamp(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetResultTimestamp(CSteamAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the result belongs to the target steam ID, false if the</para>\n\t\t/// <para> result does not. This is important when using DeserializeResult, to verify</para>\n\t\t/// <para> that a remote player is not pretending to have a different user's inventory.</para>\n\t\t/// </summary>\n\t\tpublic static bool CheckResultSteamID(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_CheckResultSteamID(CSteamAPIContext.GetSteamInventory(), resultHandle, steamIDExpected);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Destroys a result handle and frees all associated memory.</para>\n\t\t/// </summary>\n\t\tpublic static void DestroyResult(SteamInventoryResult_t resultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInventory_DestroyResult(CSteamAPIContext.GetSteamInventory(), resultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC QUERY</para>\n\t\t/// <para> Captures the entire state of the current user's Steam inventory.</para>\n\t\t/// <para> You must call DestroyResult on this handle when you are done with it.</para>\n\t\t/// <para> Returns false and sets *pResultHandle to zero if inventory is unavailable.</para>\n\t\t/// <para> Note: calls to this function are subject to rate limits and may return</para>\n\t\t/// <para> cached results if called too frequently. It is suggested that you call</para>\n\t\t/// <para> this function only when you are about to display the user's full inventory,</para>\n\t\t/// <para> or if you expect that the inventory may have changed.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetAllItems(out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetAllItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Captures the state of a subset of the current user's Steam inventory,</para>\n\t\t/// <para> identified by an array of item instance IDs. The results from this call</para>\n\t\t/// <para> can be serialized and passed to other players to \"prove\" that the current</para>\n\t\t/// <para> user owns specific items, without exposing the user's entire inventory.</para>\n\t\t/// <para> For example, you could call GetItemsByID with the IDs of the user's</para>\n\t\t/// <para> currently equipped cosmetic items and serialize this to a buffer, and</para>\n\t\t/// <para> then transmit this buffer to other players upon joining a game.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemsByID(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetItemsByID(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pInstanceIDs, unCountInstanceIDs);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> RESULT SERIALIZATION AND AUTHENTICATION</para>\n\t\t/// <para> Serialized result sets contain a short signature which can't be forged</para>\n\t\t/// <para> or replayed across different game sessions. A result set can be serialized</para>\n\t\t/// <para> on the local client, transmitted to other players via your game networking,</para>\n\t\t/// <para> and deserialized by the remote players. This is a secure way of preventing</para>\n\t\t/// <para> hackers from lying about posessing rare/high-value items.</para>\n\t\t/// <para> Serializes a result set with signature bytes to an output buffer. Pass</para>\n\t\t/// <para> NULL as an output buffer to get the required size via punOutBufferSize.</para>\n\t\t/// <para> The size of a serialized result depends on the number items which are being</para>\n\t\t/// <para> serialized. When securely transmitting items to other players, it is</para>\n\t\t/// <para> recommended to use \"GetItemsByID\" first to create a minimal result set.</para>\n\t\t/// <para> Results have a built-in timestamp which will be considered \"expired\" after</para>\n\t\t/// <para> an hour has elapsed. See DeserializeResult for expiration handling.</para>\n\t\t/// </summary>\n\t\tpublic static bool SerializeResult(SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_SerializeResult(CSteamAPIContext.GetSteamInventory(), resultHandle, pOutBuffer, out punOutBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Deserializes a result set and verifies the signature bytes. Returns false</para>\n\t\t/// <para> if bRequireFullOnlineVerify is set but Steam is running in Offline mode.</para>\n\t\t/// <para> Otherwise returns true and then delivers error codes via GetResultStatus.</para>\n\t\t/// <para> The bRESERVED_MUST_BE_FALSE flag is reserved for future use and should not</para>\n\t\t/// <para> be set to true by your game at this time.</para>\n\t\t/// <para> DeserializeResult has a potential soft-failure mode where the handle status</para>\n\t\t/// <para> is set to k_EResultExpired. GetResultItems() still succeeds in this mode.</para>\n\t\t/// <para> The \"expired\" result could indicate that the data may be out of date - not</para>\n\t\t/// <para> just due to timed expiration (one hour), but also because one of the items</para>\n\t\t/// <para> in the result set may have been traded or consumed since the result set was</para>\n\t\t/// <para> generated. You could compare the timestamp from GetResultTimestamp() to</para>\n\t\t/// <para> ISteamUtils::GetServerRealTime() to determine how old the data is. You could</para>\n\t\t/// <para> simply ignore the \"expired\" result code and continue as normal, or you</para>\n\t\t/// <para> could challenge the player with expired data to send an updated result set.</para>\n\t\t/// </summary>\n\t\tpublic static bool DeserializeResult(out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, bool bRESERVED_MUST_BE_FALSE = false) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_DeserializeResult(CSteamAPIContext.GetSteamInventory(), out pOutResultHandle, pBuffer, unBufferSize, bRESERVED_MUST_BE_FALSE);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> INVENTORY ASYNC MODIFICATION</para>\n\t\t/// <para> GenerateItems() creates one or more items and then generates a SteamInventoryCallback_t</para>\n\t\t/// <para> notification with a matching nCallbackContext parameter. This API is only intended</para>\n\t\t/// <para> for prototyping - it is only usable by Steam accounts that belong to the publisher group</para>\n\t\t/// <para> for your game.</para>\n\t\t/// <para> If punArrayQuantity is not NULL, it should be the same length as pArrayItems and should</para>\n\t\t/// <para> describe the quantity of each item to generate.</para>\n\t\t/// </summary>\n\t\tpublic static bool GenerateItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GenerateItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, punArrayQuantity, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GrantPromoItems() checks the list of promotional items for which the user may be eligible</para>\n\t\t/// <para> and grants the items (one time only).  On success, the result set will include items which</para>\n\t\t/// <para> were granted, if any. If no items were granted because the user isn't eligible for any</para>\n\t\t/// <para> promotions, this is still considered a success.</para>\n\t\t/// </summary>\n\t\tpublic static bool GrantPromoItems(out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GrantPromoItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> AddPromoItem() / AddPromoItems() are restricted versions of GrantPromoItems(). Instead of</para>\n\t\t/// <para> scanning for all eligible promotional items, the check is restricted to a single item</para>\n\t\t/// <para> definition or set of item definitions. This can be useful if your game has custom UI for</para>\n\t\t/// <para> showing a specific promo item to the user.</para>\n\t\t/// </summary>\n\t\tpublic static bool AddPromoItem(out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_AddPromoItem(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemDef);\n\t\t}\n\n\t\tpublic static bool AddPromoItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_AddPromoItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ConsumeItem() removes items from the inventory, permanently. They cannot be recovered.</para>\n\t\t/// <para> Not for the faint of heart - if your game implements item removal at all, a high-friction</para>\n\t\t/// <para> UI confirmation process is highly recommended.</para>\n\t\t/// </summary>\n\t\tpublic static bool ConsumeItem(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_ConsumeItem(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemConsume, unQuantity);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ExchangeItems() is an atomic combination of item generation and consumption.</para>\n\t\t/// <para> It can be used to implement crafting recipes or transmutations, or items which unpack</para>\n\t\t/// <para> themselves into other items (e.g., a chest).</para>\n\t\t/// <para> Exchange recipes are defined in the ItemDef, and explicitly list the required item</para>\n\t\t/// <para> types and resulting generated type.</para>\n\t\t/// <para> Exchange recipes are evaluated atomically by the Inventory Service; if the supplied</para>\n\t\t/// <para> components do not match the recipe, or do not contain sufficient quantity, the</para>\n\t\t/// <para> exchange will fail.</para>\n\t\t/// </summary>\n\t\tpublic static bool ExchangeItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayGenerate, uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, SteamItemInstanceID_t[] pArrayDestroy, uint[] punArrayDestroyQuantity, uint unArrayDestroyLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_ExchangeItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayGenerate, punArrayGenerateQuantity, unArrayGenerateLength, pArrayDestroy, punArrayDestroyQuantity, unArrayDestroyLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> TransferItemQuantity() is intended for use with items which are \"stackable\" (can have</para>\n\t\t/// <para> quantity greater than one). It can be used to split a stack into two, or to transfer</para>\n\t\t/// <para> quantity from one stack into another stack of identical items. To split one stack into</para>\n\t\t/// <para> two, pass k_SteamItemInstanceIDInvalid for itemIdDest and a new item will be generated.</para>\n\t\t/// </summary>\n\t\tpublic static bool TransferItemQuantity(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_TransferItemQuantity(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemIdSource, unQuantity, itemIdDest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> TIMED DROPS AND PLAYTIME CREDIT</para>\n\t\t/// <para> Deprecated. Calling this method is not required for proper playtime accounting.</para>\n\t\t/// </summary>\n\t\tpublic static void SendItemDropHeartbeat() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamInventory_SendItemDropHeartbeat(CSteamAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Playtime credit must be consumed and turned into item drops by your game. Only item</para>\n\t\t/// <para> definitions which are marked as \"playtime item generators\" can be spawned. The call</para>\n\t\t/// <para> will return an empty result set if there is not enough playtime credit for a drop.</para>\n\t\t/// <para> Your game should call TriggerItemDrop at an appropriate time for the user to receive</para>\n\t\t/// <para> new items, such as between rounds or while the player is dead. Note that players who</para>\n\t\t/// <para> hack their clients could modify the value of \"dropListDefinition\", so do not use it</para>\n\t\t/// <para> to directly control rarity.</para>\n\t\t/// <para> See your Steamworks configuration to set playtime drop rates for individual itemdefs.</para>\n\t\t/// <para> The client library will suppress too-frequent calls to this method.</para>\n\t\t/// </summary>\n\t\tpublic static bool TriggerItemDrop(out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_TriggerItemDrop(CSteamAPIContext.GetSteamInventory(), out pResultHandle, dropListDefinition);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Deprecated. This method is not supported.</para>\n\t\t/// </summary>\n\t\tpublic static bool TradeItems(out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, SteamItemInstanceID_t[] pArrayGive, uint[] pArrayGiveQuantity, uint nArrayGiveLength, SteamItemInstanceID_t[] pArrayGet, uint[] pArrayGetQuantity, uint nArrayGetLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_TradeItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, steamIDTradePartner, pArrayGive, pArrayGiveQuantity, nArrayGiveLength, pArrayGet, pArrayGetQuantity, nArrayGetLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ITEM DEFINITIONS</para>\n\t\t/// <para> Item definitions are a mapping of \"definition IDs\" (integers between 1 and 1000000)</para>\n\t\t/// <para> to a set of string properties. Some of these properties are required to display items</para>\n\t\t/// <para> on the Steam community web site. Other properties can be defined by applications.</para>\n\t\t/// <para> Use of these functions is optional; there is no reason to call LoadItemDefinitions</para>\n\t\t/// <para> if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue</para>\n\t\t/// <para> weapon mod = 55) and does not allow for adding new item types without a client patch.</para>\n\t\t/// <para> LoadItemDefinitions triggers the automatic load and refresh of item definitions.</para>\n\t\t/// <para> Every time new item definitions are available (eg, from the dynamic addition of new</para>\n\t\t/// <para> item types while players are still in-game), a SteamInventoryDefinitionUpdate_t</para>\n\t\t/// <para> callback will be fired.</para>\n\t\t/// </summary>\n\t\tpublic static bool LoadItemDefinitions() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_LoadItemDefinitions(CSteamAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GetItemDefinitionIDs returns the set of all defined item definition IDs (which are</para>\n\t\t/// <para> defined via Steamworks configuration, and not necessarily contiguous integers).</para>\n\t\t/// <para> If pItemDefIDs is null, the call will return true and *punItemDefIDsArraySize will</para>\n\t\t/// <para> contain the total size necessary for a subsequent call. Otherwise, the call will</para>\n\t\t/// <para> return false if and only if there is not enough space in the output array.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDefinitionIDs(SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pItemDefIDs must be the same size as punItemDefIDsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetItemDefinitionIDs(CSteamAPIContext.GetSteamInventory(), pItemDefIDs, ref punItemDefIDsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> GetItemDefinitionProperty returns a string property from a given item definition.</para>\n\t\t/// <para> Note that some properties (for example, \"name\") may be localized and will depend</para>\n\t\t/// <para> on the current Steam language settings (see ISteamApps::GetCurrentGameLanguage).</para>\n\t\t/// <para> Property names are always composed of ASCII letters, numbers, and/or underscores.</para>\n\t\t/// <para> Pass a NULL pointer for pchPropertyName to get a comma - separated list of available</para>\n\t\t/// <para> property names. If pchValueBuffer is NULL, *punValueBufferSize will contain the</para>\n\t\t/// <para> suggested buffer size. Otherwise it will be the number of bytes actually copied</para>\n\t\t/// <para> to pchValueBuffer. If the results do not fit in the given buffer, partial</para>\n\t\t/// <para> results may be copied.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDefinitionProperty(SteamItemDef_t iDefinition, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut);\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\tbool ret = NativeMethods.ISteamInventory_GetItemDefinitionProperty(CSteamAPIContext.GetSteamInventory(), iDefinition, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut);\n\t\t\t\tpchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValueBuffer2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request the list of \"eligible\" promo items that can be manually granted to the given</para>\n\t\t/// <para> user.  These are promo items of type \"manual\" that won't be granted automatically.</para>\n\t\t/// <para> An example usage of this is an item that becomes available every week.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestEligiblePromoItemDefinitionsIDs(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(CSteamAPIContext.GetSteamInventory(), steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> After handling a SteamInventoryEligiblePromoItemDefIDs_t call result, use this</para>\n\t\t/// <para> function to pull out the list of item definition ids that the user can be</para>\n\t\t/// <para> manually granted via the AddPromoItems() call.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetEligiblePromoItemDefinitionIDs(CSteamID steamID, SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) {\n\t\t\t\tthrow new System.ArgumentException(\"pItemDefIDs must be the same size as punItemDefIDsArraySize!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetEligiblePromoItemDefinitionIDs(CSteamAPIContext.GetSteamInventory(), steamID, pItemDefIDs, ref punItemDefIDsArraySize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Starts the purchase process for the given item definitions.  The callback SteamInventoryStartPurchaseResult_t</para>\n\t\t/// <para> will be posted if Steam was able to initialize the transaction.</para>\n\t\t/// <para> Once the purchase has been authorized and completed by the user, the callback SteamInventoryResultReady_t</para>\n\t\t/// <para> will be posted.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t StartPurchase(SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_StartPurchase(CSteamAPIContext.GetSteamInventory(), pArrayItemDefs, punArrayQuantity, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request current prices for all applicable item definitions</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestPrices() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamInventory_RequestPrices(CSteamAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the number of items with prices.  Need to call RequestPrices() first.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumItemsWithPrices() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetNumItemsWithPrices(CSteamAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns item definition ids and their prices in the user's local currency.</para>\n\t\t/// <para> Need to call RequestPrices() first.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemsWithPrices(SteamItemDef_t[] pArrayItemDefs, ulong[] pCurrentPrices, ulong[] pBasePrices, uint unArrayLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tif (pArrayItemDefs != null && pArrayItemDefs.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pArrayItemDefs must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\tif (pCurrentPrices != null && pCurrentPrices.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pCurrentPrices must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\tif (pBasePrices != null && pBasePrices.Length != unArrayLength) {\n\t\t\t\tthrow new System.ArgumentException(\"pBasePrices must be the same size as unArrayLength!\");\n\t\t\t}\n\t\t\treturn NativeMethods.ISteamInventory_GetItemsWithPrices(CSteamAPIContext.GetSteamInventory(), pArrayItemDefs, pCurrentPrices, pBasePrices, unArrayLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieves the price for the item definition id</para>\n\t\t/// <para> Returns false if there is no price stored for the item definition.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemPrice(SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_GetItemPrice(CSteamAPIContext.GetSteamInventory(), iDefinition, out pCurrentPrice, out pBasePrice);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Create a request to update properties on items</para>\n\t\t/// </summary>\n\t\tpublic static SteamInventoryUpdateHandle_t StartUpdateProperties() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamInventoryUpdateHandle_t)NativeMethods.ISteamInventory_StartUpdateProperties(CSteamAPIContext.GetSteamInventory());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Remove the property on the item</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_RemoveProperty(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Accessor methods to set properties on items</para>\n\t\t/// </summary>\n\t\tpublic static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, string pchPropertyValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName))\n\t\t\tusing (var pchPropertyValue2 = new InteropHelp.UTF8StringHandle(pchPropertyValue)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, pchPropertyValue2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty0(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, bValue);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty1(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, long nValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty1(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, nValue);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetProperty2(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, float flValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) {\n\t\t\t\treturn NativeMethods.ISteamInventory_SetProperty2(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, flValue);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Submit the update request by handle</para>\n\t\t/// </summary>\n\t\tpublic static bool SubmitUpdateProperties(SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamInventory_SubmitUpdateProperties(CSteamAPIContext.GetSteamInventory(), handle, out pResultHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteammatchmaking.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamMatchmaking {\n\t\t/// <summary>\n\t\t/// <para> game server favorites storage</para>\n\t\t/// <para> saves basic details about a multiplayer game server locally</para>\n\t\t/// <para> returns the number of favorites servers the user has stored</para>\n\t\t/// </summary>\n\t\tpublic static int GetFavoriteGameCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetFavoriteGameCount(CSteamAPIContext.GetSteamMatchmaking());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the details of the game server</para>\n\t\t/// <para> iGame is of range [0,GetFavoriteGameCount())</para>\n\t\t/// <para> *pnIP, *pnConnPort are filled in the with IP:port of the game server</para>\n\t\t/// <para> *punFlags specify whether the game server was stored as an explicit favorite or in the history of connections</para>\n\t\t/// <para> *pRTime32LastPlayedOnServer is filled in the with the Unix time the favorite was added</para>\n\t\t/// </summary>\n\t\tpublic static bool GetFavoriteGame(int iGame, out AppId_t pnAppID, out uint pnIP, out ushort pnConnPort, out ushort pnQueryPort, out uint punFlags, out uint pRTime32LastPlayedOnServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), iGame, out pnAppID, out pnIP, out pnConnPort, out pnQueryPort, out punFlags, out pRTime32LastPlayedOnServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> adds the game server to the local list; updates the time played of the server if it already exists in the list</para>\n\t\t/// </summary>\n\t\tpublic static int AddFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags, uint rTime32LastPlayedOnServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_AddFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags, rTime32LastPlayedOnServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> removes the game server from the local storage; returns true if one was removed</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_RemoveFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>/////</para>\n\t\t/// <para> Game lobby functions</para>\n\t\t/// <para> Get a list of relevant lobbies</para>\n\t\t/// <para> this is an asynchronous request</para>\n\t\t/// <para> results will be returned by LobbyMatchList_t callback &amp; call result, with the number of lobbies found</para>\n\t\t/// <para> this will never return lobbies that are full</para>\n\t\t/// <para> to add more filter, the filter calls below need to be call before each and every RequestLobbyList() call</para>\n\t\t/// <para> use the CCallResult&lt;&gt; object in steam_api.h to match the SteamAPICall_t call result to a function in an object, e.g.</para>\n\t\t/// <para>\t\tclass CMyLobbyListManager</para>\n\t\t/// <para>\t\t{</para>\n\t\t/// <para>\t\t\tCCallResult&lt;CMyLobbyListManager, LobbyMatchList_t&gt; m_CallResultLobbyMatchList;</para>\n\t\t/// <para>\t\t\tvoid FindLobbies()</para>\n\t\t/// <para>\t\t\t{</para>\n\t\t/// <para>\t\t\t\t// SteamMatchmaking()-&gt;AddRequestLobbyListFilter*() functions would be called here, before RequestLobbyList()</para>\n\t\t/// <para>\t\t\t\tSteamAPICall_t hSteamAPICall = SteamMatchmaking()-&gt;RequestLobbyList();</para>\n\t\t/// <para>\t\t\t\tm_CallResultLobbyMatchList.Set( hSteamAPICall, this, &amp;CMyLobbyListManager::OnLobbyMatchList );</para>\n\t\t/// <para>\t\t\t}</para>\n\t\t/// <para>\t\t\tvoid OnLobbyMatchList( LobbyMatchList_t *pLobbyMatchList, bool bIOFailure )</para>\n\t\t/// <para>\t\t\t{</para>\n\t\t/// <para>\t\t\t\t// lobby list has be retrieved from Steam back-end, use results</para>\n\t\t/// <para>\t\t\t}</para>\n\t\t/// <para>\t\t}</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestLobbyList() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamMatchmaking_RequestLobbyList(CSteamAPIContext.GetSteamMatchmaking());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> filters for lobbies</para>\n\t\t/// <para> this needs to be called before RequestLobbyList() to take effect</para>\n\t\t/// <para> these are cleared on each call to RequestLobbyList()</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListStringFilter(string pchKeyToMatch, string pchValueToMatch, ELobbyComparison eComparisonType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch))\n\t\t\tusing (var pchValueToMatch2 = new InteropHelp.UTF8StringHandle(pchValueToMatch)) {\n\t\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListStringFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, pchValueToMatch2, eComparisonType);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> numerical comparison</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListNumericalFilter(string pchKeyToMatch, int nValueToMatch, ELobbyComparison eComparisonType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) {\n\t\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListNumericalFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToMatch, eComparisonType);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns results closest to the specified value. Multiple near filters can be added, with early filters taking precedence</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListNearValueFilter(string pchKeyToMatch, int nValueToBeCloseTo) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) {\n\t\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListNearValueFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToBeCloseTo);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns only lobbies with the specified number of slots available</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable(CSteamAPIContext.GetSteamMatchmaking(), nSlotsAvailable);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sets the distance for which we should search for lobbies (based on users IP address to location map on the Steam backed)</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter eLobbyDistanceFilter) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListDistanceFilter(CSteamAPIContext.GetSteamMatchmaking(), eLobbyDistanceFilter);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sets how many results to return, the lower the count the faster it is to download the lobby results &amp; details to the client</para>\n\t\t/// </summary>\n\t\tpublic static void AddRequestLobbyListResultCountFilter(int cMaxResults) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListResultCountFilter(CSteamAPIContext.GetSteamMatchmaking(), cMaxResults);\n\t\t}\n\n\t\tpublic static void AddRequestLobbyListCompatibleMembersFilter(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the CSteamID of a lobby, as retrieved by a RequestLobbyList call</para>\n\t\t/// <para> should only be called after a LobbyMatchList_t callback is received</para>\n\t\t/// <para> iLobby is of the range [0, LobbyMatchList_t::m_nLobbiesMatching)</para>\n\t\t/// <para> the returned CSteamID::IsValid() will be false if iLobby is out of range</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetLobbyByIndex(int iLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyByIndex(CSteamAPIContext.GetSteamMatchmaking(), iLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Create a lobby on the Steam servers.</para>\n\t\t/// <para> If private, then the lobby will not be returned by any RequestLobbyList() call; the CSteamID</para>\n\t\t/// <para> of the lobby will need to be communicated via game channels or via InviteUserToLobby()</para>\n\t\t/// <para> this is an asynchronous request</para>\n\t\t/// <para> results will be returned by LobbyCreated_t callback and call result; lobby is joined &amp; ready to use at this point</para>\n\t\t/// <para> a LobbyEnter_t callback will also be received (since the local user is joining their own lobby)</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CreateLobby(ELobbyType eLobbyType, int cMaxMembers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamMatchmaking_CreateLobby(CSteamAPIContext.GetSteamMatchmaking(), eLobbyType, cMaxMembers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Joins an existing lobby</para>\n\t\t/// <para> this is an asynchronous request</para>\n\t\t/// <para> results will be returned by LobbyEnter_t callback &amp; call result, check m_EChatRoomEnterResponse to see if was successful</para>\n\t\t/// <para> lobby metadata is available to use immediately on this call completing</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t JoinLobby(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamMatchmaking_JoinLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Leave a lobby; this will take effect immediately on the client side</para>\n\t\t/// <para> other users in the lobby will be notified by a LobbyChatUpdate_t callback</para>\n\t\t/// </summary>\n\t\tpublic static void LeaveLobby(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_LeaveLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Invite another user to the lobby</para>\n\t\t/// <para> the target user will receive a LobbyInvite_t callback</para>\n\t\t/// <para> will return true if the invite is successfully sent, whether or not the target responds</para>\n\t\t/// <para> returns false if the local user is not connected to the Steam servers</para>\n\t\t/// <para> if the other user clicks the join link, a GameLobbyJoinRequested_t will be posted if the user is in-game,</para>\n\t\t/// <para> or if the game isn't running yet the game will be launched with the parameter +connect_lobby &lt;64-bit lobby id&gt;</para>\n\t\t/// </summary>\n\t\tpublic static bool InviteUserToLobby(CSteamID steamIDLobby, CSteamID steamIDInvitee) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_InviteUserToLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDInvitee);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Lobby iteration, for viewing details of users in a lobby</para>\n\t\t/// <para> only accessible if the lobby user is a member of the specified lobby</para>\n\t\t/// <para> persona information for other lobby members (name, avatar, etc.) will be asynchronously received</para>\n\t\t/// <para> and accessible via ISteamFriends interface</para>\n\t\t/// <para> returns the number of users in the specified lobby</para>\n\t\t/// </summary>\n\t\tpublic static int GetNumLobbyMembers(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetNumLobbyMembers(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the CSteamID of a user in the lobby</para>\n\t\t/// <para> iMember is of range [0,GetNumLobbyMembers())</para>\n\t\t/// <para> note that the current user must be in a lobby to retrieve CSteamIDs of other users in that lobby</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetLobbyMemberByIndex(CSteamID steamIDLobby, int iMember) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyMemberByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iMember);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get data associated with this lobby</para>\n\t\t/// <para> takes a simple key, and returns the string associated with it</para>\n\t\t/// <para> \"\" will be returned if no value is set, or if steamIDLobby is invalid</para>\n\t\t/// </summary>\n\t\tpublic static string GetLobbyData(CSteamID steamIDLobby, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2));\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets a key/value pair in the lobby metadata</para>\n\t\t/// <para> each user in the lobby will be broadcast this new value, and any new users joining will receive any existing data</para>\n\t\t/// <para> this can be used to set lobby names, map, etc.</para>\n\t\t/// <para> to reset a key, just set it to \"\"</para>\n\t\t/// <para> other users in the lobby will receive notification of the lobby data change via a LobbyDataUpdate_t callback</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLobbyData(CSteamID steamIDLobby, string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\treturn NativeMethods.ISteamMatchmaking_SetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of metadata keys set on the specified lobby</para>\n\t\t/// </summary>\n\t\tpublic static int GetLobbyDataCount(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetLobbyDataCount(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns a lobby metadata key/values pair by index, of range [0, GetLobbyDataCount())</para>\n\t\t/// </summary>\n\t\tpublic static bool GetLobbyDataByIndex(CSteamID steamIDLobby, int iLobbyData, out string pchKey, int cchKeyBufferSize, out string pchValue, int cchValueBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchKey2 = Marshal.AllocHGlobal(cchKeyBufferSize);\n\t\t\tIntPtr pchValue2 = Marshal.AllocHGlobal(cchValueBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamMatchmaking_GetLobbyDataByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iLobbyData, pchKey2, cchKeyBufferSize, pchValue2, cchValueBufferSize);\n\t\t\tpchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null;\n\t\t\tMarshal.FreeHGlobal(pchKey2);\n\t\t\tpchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;\n\t\t\tMarshal.FreeHGlobal(pchValue2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> removes a metadata key from the lobby</para>\n\t\t/// </summary>\n\t\tpublic static bool DeleteLobbyData(CSteamID steamIDLobby, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn NativeMethods.ISteamMatchmaking_DeleteLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets per-user metadata for someone in this lobby</para>\n\t\t/// </summary>\n\t\tpublic static string GetLobbyMemberData(CSteamID steamIDLobby, CSteamID steamIDUser, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDUser, pchKey2));\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets per-user metadata (for the local user implicitly)</para>\n\t\t/// </summary>\n\t\tpublic static void SetLobbyMemberData(CSteamID steamIDLobby, string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\tNativeMethods.ISteamMatchmaking_SetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Broadcasts a chat message to the all the users in the lobby</para>\n\t\t/// <para> users in the lobby (including the local user) will receive a LobbyChatMsg_t callback</para>\n\t\t/// <para> returns true if the message is successfully sent</para>\n\t\t/// <para> pvMsgBody can be binary or text data, up to 4k</para>\n\t\t/// <para> if pvMsgBody is text, cubMsgBody should be strlen( text ) + 1, to include the null terminator</para>\n\t\t/// </summary>\n\t\tpublic static bool SendLobbyChatMsg(CSteamID steamIDLobby, byte[] pvMsgBody, int cubMsgBody) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SendLobbyChatMsg(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pvMsgBody, cubMsgBody);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get a chat message as specified in a LobbyChatMsg_t callback</para>\n\t\t/// <para> iChatID is the LobbyChatMsg_t::m_iChatID value in the callback</para>\n\t\t/// <para> *pSteamIDUser is filled in with the CSteamID of the member</para>\n\t\t/// <para> *pvData is filled in with the message itself</para>\n\t\t/// <para> return value is the number of bytes written into the buffer</para>\n\t\t/// </summary>\n\t\tpublic static int GetLobbyChatEntry(CSteamID steamIDLobby, int iChatID, out CSteamID pSteamIDUser, byte[] pvData, int cubData, out EChatEntryType peChatEntryType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetLobbyChatEntry(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iChatID, out pSteamIDUser, pvData, cubData, out peChatEntryType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Refreshes metadata for a lobby you're not necessarily in right now</para>\n\t\t/// <para> you never do this for lobbies you're a member of, only if your</para>\n\t\t/// <para> this will send down all the metadata associated with a lobby</para>\n\t\t/// <para> this is an asynchronous call</para>\n\t\t/// <para> returns false if the local user is not connected to the Steam servers</para>\n\t\t/// <para> results will be returned by a LobbyDataUpdate_t callback</para>\n\t\t/// <para> if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false</para>\n\t\t/// </summary>\n\t\tpublic static bool RequestLobbyData(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_RequestLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sets the game server associated with the lobby</para>\n\t\t/// <para> usually at this point, the users will join the specified game server</para>\n\t\t/// <para> either the IP/Port or the steamID of the game server has to be valid, depending on how you want the clients to be able to connect</para>\n\t\t/// </summary>\n\t\tpublic static void SetLobbyGameServer(CSteamID steamIDLobby, uint unGameServerIP, ushort unGameServerPort, CSteamID steamIDGameServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_SetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, unGameServerIP, unGameServerPort, steamIDGameServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the details of a game server set in a lobby - returns false if there is no game server set, or that lobby doesn't exist</para>\n\t\t/// </summary>\n\t\tpublic static bool GetLobbyGameServer(CSteamID steamIDLobby, out uint punGameServerIP, out ushort punGameServerPort, out CSteamID psteamIDGameServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, out punGameServerIP, out punGameServerPort, out psteamIDGameServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set the limit on the # of users who can join the lobby</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLobbyMemberLimit(CSteamID steamIDLobby, int cMaxMembers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, cMaxMembers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the current limit on the # of users who can join the lobby; returns 0 if no limit is defined</para>\n\t\t/// </summary>\n\t\tpublic static int GetLobbyMemberLimit(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_GetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> updates which type of lobby it is</para>\n\t\t/// <para> only lobbies that are k_ELobbyTypePublic or k_ELobbyTypeInvisible, and are set to joinable, will be returned by RequestLobbyList() calls</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLobbyType(CSteamID steamIDLobby, ELobbyType eLobbyType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SetLobbyType(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, eLobbyType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sets whether or not a lobby is joinable - defaults to true for a new lobby</para>\n\t\t/// <para> if set to false, no user can join, even if they are a friend or have been invited</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLobbyJoinable(CSteamID steamIDLobby, bool bLobbyJoinable) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SetLobbyJoinable(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, bLobbyJoinable);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the current lobby owner</para>\n\t\t/// <para> you must be a member of the lobby to access this</para>\n\t\t/// <para> there always one lobby owner - if the current owner leaves, another user will become the owner</para>\n\t\t/// <para> it is possible (bur rare) to join a lobby just as the owner is leaving, thus entering a lobby with self as the owner</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetLobbyOwner(CSteamID steamIDLobby) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> changes who the lobby owner is</para>\n\t\t/// <para> you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby</para>\n\t\t/// <para> after completion, the local user will no longer be the owner</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLobbyOwner(CSteamID steamIDLobby, CSteamID steamIDNewOwner) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDNewOwner);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> link two lobbies for the purposes of checking player compatibility</para>\n\t\t/// <para> you must be the lobby owner of both lobbies</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLinkedLobby(CSteamID steamIDLobby, CSteamID steamIDLobbyDependent) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmaking_SetLinkedLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDLobbyDependent);\n\t\t}\n#if _PS3\n\t\t/// <summary>\n\t\t/// <para> changes who the lobby owner is</para>\n\t\t/// <para> you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby</para>\n\t\t/// <para> after completion, the local user will no longer be the owner</para>\n\t\t/// </summary>\n\t\tpublic static void CheckForPSNGameBootInvite(uint iGameBootAttributes) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmaking_CheckForPSNGameBootInvite(CSteamAPIContext.GetSteamMatchmaking(), iGameBootAttributes);\n\t\t}\n#endif\n\t}\n\tpublic static class SteamMatchmakingServers {\n\t\t/// <summary>\n\t\t/// <para> Request a new list of servers of a particular type.  These calls each correspond to one of the EMatchMakingType values.</para>\n\t\t/// <para> Each call allocates a new asynchronous request object.</para>\n\t\t/// <para> Request object must be released by calling ReleaseRequest( hServerListRequest )</para>\n\t\t/// </summary>\n\t\tpublic static HServerListRequest RequestInternetServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestInternetServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\tpublic static HServerListRequest RequestLANServerList(AppId_t iApp, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestLANServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\tpublic static HServerListRequest RequestFriendsServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFriendsServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\tpublic static HServerListRequest RequestFavoritesServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFavoritesServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\tpublic static HServerListRequest RequestHistoryServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestHistoryServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\tpublic static HServerListRequest RequestSpectatorServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestSpectatorServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Releases the asynchronous request object and cancels any pending query on it if there's a pending query in progress.</para>\n\t\t/// <para> RefreshComplete callback is not posted when request is released.</para>\n\t\t/// </summary>\n\t\tpublic static void ReleaseRequest(HServerListRequest hServerListRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmakingServers_ReleaseRequest(CSteamAPIContext.GetSteamMatchmakingServers(), hServerListRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> the filter operation codes that go in the key part of MatchMakingKeyValuePair_t should be one of these:</para>\n\t\t/// <para>\t\t\"map\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server is playing the specified map.</para>\n\t\t/// <para>\t\t\"gamedataand\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains all of the</para>\n\t\t/// <para>\t\t\tspecified strings.  The value field is a comma-delimited list of strings to match.</para>\n\t\t/// <para>\t\t\"gamedataor\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains at least one of the</para>\n\t\t/// <para>\t\t\tspecified strings.  The value field is a comma-delimited list of strings to match.</para>\n\t\t/// <para>\t\t\"gamedatanor\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game data (ISteamGameServer::SetGameData) does not contain any</para>\n\t\t/// <para>\t\t\tof the specified strings.  The value field is a comma-delimited list of strings to check.</para>\n\t\t/// <para>\t\t\"gametagsand\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) contains all</para>\n\t\t/// <para>\t\t\tof the specified strings.  The value field is a comma-delimited list of strings to check.</para>\n\t\t/// <para>\t\t\"gametagsnor\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) does not contain any</para>\n\t\t/// <para>\t\t\tof the specified strings.  The value field is a comma-delimited list of strings to check.</para>\n\t\t/// <para>\t\t\"and\" (x1 &amp;&amp; x2 &amp;&amp; ... &amp;&amp; xn)</para>\n\t\t/// <para>\t\t\"or\" (x1 || x2 || ... || xn)</para>\n\t\t/// <para>\t\t\"nand\" !(x1 &amp;&amp; x2 &amp;&amp; ... &amp;&amp; xn)</para>\n\t\t/// <para>\t\t\"nor\" !(x1 || x2 || ... || xn)</para>\n\t\t/// <para>\t\t\t- Performs Boolean operation on the following filters.  The operand to this filter specifies</para>\n\t\t/// <para>\t\t\tthe \"size\" of the Boolean inputs to the operation, in Key/value pairs.  (The keyvalue</para>\n\t\t/// <para>\t\t\tpairs must immediately follow, i.e. this is a prefix logical operator notation.)</para>\n\t\t/// <para>\t\t\tIn the simplest case where Boolean expressions are not nested, this is simply</para>\n\t\t/// <para>\t\t\tthe number of operands.</para>\n\t\t/// <para>\t\t\tFor example, to match servers on a particular map or with a particular tag, would would</para>\n\t\t/// <para>\t\t\tuse these filters.</para>\n\t\t/// <para>\t\t\t\t( server.map == \"cp_dustbowl\" || server.gametags.contains(\"payload\") )</para>\n\t\t/// <para>\t\t\t\t\"or\", \"2\"</para>\n\t\t/// <para>\t\t\t\t\"map\", \"cp_dustbowl\"</para>\n\t\t/// <para>\t\t\t\t\"gametagsand\", \"payload\"</para>\n\t\t/// <para>\t\t\tIf logical inputs are nested, then the operand specifies the size of the entire</para>\n\t\t/// <para>\t\t\t\"length\" of its operands, not the number of immediate children.</para>\n\t\t/// <para>\t\t\t\t( server.map == \"cp_dustbowl\" || ( server.gametags.contains(\"payload\") &amp;&amp; !server.gametags.contains(\"payloadrace\") ) )</para>\n\t\t/// <para>\t\t\t\t\"or\", \"4\"</para>\n\t\t/// <para>\t\t\t\t\"map\", \"cp_dustbowl\"</para>\n\t\t/// <para>\t\t\t\t\"and\", \"2\"</para>\n\t\t/// <para>\t\t\t\t\"gametagsand\", \"payload\"</para>\n\t\t/// <para>\t\t\t\t\"gametagsnor\", \"payloadrace\"</para>\n\t\t/// <para>\t\t\tUnary NOT can be achieved using either \"nand\" or \"nor\" with a single operand.</para>\n\t\t/// <para>\t\t\"addr\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's query address matches the specified IP or IP:port.</para>\n\t\t/// <para>\t\t\"gameaddr\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server's game address matches the specified IP or IP:port.</para>\n\t\t/// <para>\t\tThe following filter operations ignore the \"value\" part of MatchMakingKeyValuePair_t</para>\n\t\t/// <para>\t\t\"dedicated\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if it passed true to SetDedicatedServer.</para>\n\t\t/// <para>\t\t\"secure\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the server is VAC-enabled.</para>\n\t\t/// <para>\t\t\"notfull\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the player count is less than the reported max player count.</para>\n\t\t/// <para>\t\t\"hasplayers\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if the player count is greater than zero.</para>\n\t\t/// <para>\t\t\"noplayers\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if it doesn't have any players.</para>\n\t\t/// <para>\t\t\"linux\"</para>\n\t\t/// <para>\t\t\t- Server passes the filter if it's a linux server</para>\n\t\t/// <para> Get details on a given server in the list, you can get the valid range of index</para>\n\t\t/// <para> values by calling GetServerCount().  You will also receive index values in</para>\n\t\t/// <para> ISteamMatchmakingServerListResponse::ServerResponded() callbacks</para>\n\t\t/// </summary>\n\t\tpublic static gameserveritem_t GetServerDetails(HServerListRequest hRequest, int iServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (gameserveritem_t)Marshal.PtrToStructure(NativeMethods.ISteamMatchmakingServers_GetServerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer), typeof(gameserveritem_t));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Cancel an request which is operation on the given list type.  You should call this to cancel</para>\n\t\t/// <para> any in-progress requests before destructing a callback object that may have been passed</para>\n\t\t/// <para> to one of the above list request calls.  Not doing so may result in a crash when a callback</para>\n\t\t/// <para> occurs on the destructed object.</para>\n\t\t/// <para> Canceling a query does not release the allocated request handle.</para>\n\t\t/// <para> The request handle must be released using ReleaseRequest( hRequest )</para>\n\t\t/// </summary>\n\t\tpublic static void CancelQuery(HServerListRequest hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmakingServers_CancelQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Ping every server in your list again but don't update the list of servers</para>\n\t\t/// <para> Query callback installed when the server list was requested will be used</para>\n\t\t/// <para> again to post notifications and RefreshComplete, so the callback must remain</para>\n\t\t/// <para> valid until another RefreshComplete is called on it or the request</para>\n\t\t/// <para> is released with ReleaseRequest( hRequest )</para>\n\t\t/// </summary>\n\t\tpublic static void RefreshQuery(HServerListRequest hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmakingServers_RefreshQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the list is currently refreshing its server list</para>\n\t\t/// </summary>\n\t\tpublic static bool IsRefreshing(HServerListRequest hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmakingServers_IsRefreshing(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> How many servers in the given list, GetServerDetails above takes 0... GetServerCount() - 1</para>\n\t\t/// </summary>\n\t\tpublic static int GetServerCount(HServerListRequest hRequest) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMatchmakingServers_GetServerCount(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Refresh a single server inside of a query (rather than all the servers )</para>\n\t\t/// </summary>\n\t\tpublic static void RefreshServer(HServerListRequest hRequest, int iServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmakingServers_RefreshServer(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Queries to individual servers directly via IP/Port</para>\n\t\t/// <para>-----------------------------------------------------------------------------</para>\n\t\t/// <para> Request updated ping time and other details from a single server</para>\n\t\t/// </summary>\n\t\tpublic static HServerQuery PingServer(uint unIP, ushort usPort, ISteamMatchmakingPingResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerQuery)NativeMethods.ISteamMatchmakingServers_PingServer(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request the list of players currently playing on a server</para>\n\t\t/// </summary>\n\t\tpublic static HServerQuery PlayerDetails(uint unIP, ushort usPort, ISteamMatchmakingPlayersResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerQuery)NativeMethods.ISteamMatchmakingServers_PlayerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Request the list of rules that the server is running (See ISteamGameServer::SetKeyValue() to set the rules server side)</para>\n\t\t/// </summary>\n\t\tpublic static HServerQuery ServerRules(uint unIP, ushort usPort, ISteamMatchmakingRulesResponse pRequestServersResponse) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HServerQuery)NativeMethods.ISteamMatchmakingServers_ServerRules(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Cancel an outstanding Ping/Players/Rules query from above.  You should call this to cancel</para>\n\t\t/// <para> any in-progress requests before destructing a callback object that may have been passed</para>\n\t\t/// <para> to one of the above calls to avoid crashing when callbacks occur.</para>\n\t\t/// </summary>\n\t\tpublic static void CancelServerQuery(HServerQuery hServerQuery) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMatchmakingServers_CancelServerQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hServerQuery);\n\t\t}\n\t}\n\tpublic static class SteamGameSearch {\n\t\t/// <summary>\n\t\t/// <para> =============================================================================================</para>\n\t\t/// <para> Game Player APIs</para>\n\t\t/// <para> a keyname and a list of comma separated values: one of which is must be found in order for the match to qualify</para>\n\t\t/// <para> fails if a search is currently in progress</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t AddGameSearchParams(string pchKeyToFind, string pchValuesToFind) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKeyToFind2 = new InteropHelp.UTF8StringHandle(pchKeyToFind))\n\t\t\tusing (var pchValuesToFind2 = new InteropHelp.UTF8StringHandle(pchValuesToFind)) {\n\t\t\t\treturn NativeMethods.ISteamGameSearch_AddGameSearchParams(CSteamAPIContext.GetSteamGameSearch(), pchKeyToFind2, pchValuesToFind2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> all players in lobby enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress</para>\n\t\t/// <para> if not the owner of the lobby or search already in progress this call fails</para>\n\t\t/// <para> periodic callbacks will be sent as queue time estimates change</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t SearchForGameWithLobby(CSteamID steamIDLobby, int nPlayerMin, int nPlayerMax) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_SearchForGameWithLobby(CSteamAPIContext.GetSteamGameSearch(), steamIDLobby, nPlayerMin, nPlayerMax);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> user enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress</para>\n\t\t/// <para> periodic callbacks will be sent as queue time estimates change</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t SearchForGameSolo(int nPlayerMin, int nPlayerMax) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_SearchForGameSolo(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> after receiving SearchForGameResultCallback_t, accept or decline the game</para>\n\t\t/// <para> multiple SearchForGameResultCallback_t will follow as players accept game until the host starts or cancels the game</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t AcceptGame() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_AcceptGame(CSteamAPIContext.GetSteamGameSearch());\n\t\t}\n\n\t\tpublic static EGameSearchErrorCode_t DeclineGame() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_DeclineGame(CSteamAPIContext.GetSteamGameSearch());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> after receiving GameStartedByHostCallback_t get connection details to server</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t RetrieveConnectionDetails(CSteamID steamIDHost, out string pchConnectionDetails, int cubConnectionDetails) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchConnectionDetails2 = Marshal.AllocHGlobal(cubConnectionDetails);\n\t\t\tEGameSearchErrorCode_t ret = NativeMethods.ISteamGameSearch_RetrieveConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), steamIDHost, pchConnectionDetails2, cubConnectionDetails);\n\t\t\tpchConnectionDetails = ret != 0 ? InteropHelp.PtrToStringUTF8(pchConnectionDetails2) : null;\n\t\t\tMarshal.FreeHGlobal(pchConnectionDetails2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> leaves queue if still waiting</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t EndGameSearch() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_EndGameSearch(CSteamAPIContext.GetSteamGameSearch());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> =============================================================================================</para>\n\t\t/// <para> Game Host APIs</para>\n\t\t/// <para> a keyname and a list of comma separated values: all the values you allow</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t SetGameHostParams(string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\treturn NativeMethods.ISteamGameSearch_SetGameHostParams(CSteamAPIContext.GetSteamGameSearch(), pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set connection details for players once game is found so they can connect to this server</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t SetConnectionDetails(string pchConnectionDetails, int cubConnectionDetails) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchConnectionDetails2 = new InteropHelp.UTF8StringHandle(pchConnectionDetails)) {\n\t\t\t\treturn NativeMethods.ISteamGameSearch_SetConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), pchConnectionDetails2, cubConnectionDetails);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> mark server as available for more players with nPlayerMin,nPlayerMax desired</para>\n\t\t/// <para> accept no lobbies with playercount greater than nMaxTeamSize</para>\n\t\t/// <para> the set of lobbies returned must be partitionable into teams of no more than nMaxTeamSize</para>\n\t\t/// <para> RequestPlayersForGameNotificationCallback_t callback will be sent when the search has started</para>\n\t\t/// <para> multple RequestPlayersForGameResultCallback_t callbacks will follow when players are found</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t RequestPlayersForGame(int nPlayerMin, int nPlayerMax, int nMaxTeamSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_RequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax, nMaxTeamSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> accept the player list and release connection details to players</para>\n\t\t/// <para> players will only be given connection details and host steamid when this is called</para>\n\t\t/// <para> ( allows host to accept after all players confirm, some confirm, or none confirm. decision is entirely up to the host )</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t HostConfirmGameStart(ulong ullUniqueGameID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_HostConfirmGameStart(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> cancel request and leave the pool of game hosts looking for players</para>\n\t\t/// <para> if a set of players has already been sent to host, all players will receive SearchForGameHostFailedToConfirm_t</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t CancelRequestPlayersForGame() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_CancelRequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> submit a result for one player. does not end the game. ullUniqueGameID continues to describe this game</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t SubmitPlayerResult(ulong ullUniqueGameID, CSteamID steamIDPlayer, EPlayerResult_t EPlayerResult) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_SubmitPlayerResult(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID, steamIDPlayer, EPlayerResult);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ends the game. no further SubmitPlayerResults for ullUniqueGameID will be accepted</para>\n\t\t/// <para> any future requests will provide a new ullUniqueGameID</para>\n\t\t/// </summary>\n\t\tpublic static EGameSearchErrorCode_t EndGame(ulong ullUniqueGameID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamGameSearch_EndGame(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID);\n\t\t}\n\t}\n\tpublic static class SteamParties {\n\t\t/// <summary>\n\t\t/// <para> =============================================================================================</para>\n\t\t/// <para> Party Client APIs</para>\n\t\t/// <para> Enumerate any active beacons for parties you may wish to join</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumActiveBeacons() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParties_GetNumActiveBeacons(CSteamAPIContext.GetSteamParties());\n\t\t}\n\n\t\tpublic static PartyBeaconID_t GetBeaconByIndex(uint unIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (PartyBeaconID_t)NativeMethods.ISteamParties_GetBeaconByIndex(CSteamAPIContext.GetSteamParties(), unIndex);\n\t\t}\n\n\t\tpublic static bool GetBeaconDetails(PartyBeaconID_t ulBeaconID, out CSteamID pSteamIDBeaconOwner, out SteamPartyBeaconLocation_t pLocation, out string pchMetadata, int cchMetadata) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchMetadata2 = Marshal.AllocHGlobal(cchMetadata);\n\t\t\tbool ret = NativeMethods.ISteamParties_GetBeaconDetails(CSteamAPIContext.GetSteamParties(), ulBeaconID, out pSteamIDBeaconOwner, out pLocation, pchMetadata2, cchMetadata);\n\t\t\tpchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null;\n\t\t\tMarshal.FreeHGlobal(pchMetadata2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Join an open party. Steam will reserve one beacon slot for your SteamID,</para>\n\t\t/// <para> and return the necessary JoinGame string for you to use to connect</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t JoinParty(PartyBeaconID_t ulBeaconID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamParties_JoinParty(CSteamAPIContext.GetSteamParties(), ulBeaconID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> =============================================================================================</para>\n\t\t/// <para> Party Host APIs</para>\n\t\t/// <para> Get a list of possible beacon locations</para>\n\t\t/// </summary>\n\t\tpublic static bool GetNumAvailableBeaconLocations(out uint puNumLocations) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParties_GetNumAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), out puNumLocations);\n\t\t}\n\n\t\tpublic static bool GetAvailableBeaconLocations(SteamPartyBeaconLocation_t[] pLocationList, uint uMaxNumLocations) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParties_GetAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), pLocationList, uMaxNumLocations);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Create a new party beacon and activate it in the selected location.</para>\n\t\t/// <para> unOpenSlots is the maximum number of users that Steam will send to you.</para>\n\t\t/// <para> When people begin responding to your beacon, Steam will send you</para>\n\t\t/// <para> PartyReservationCallback_t callbacks to let you know who is on the way.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CreateBeacon(uint unOpenSlots, ref SteamPartyBeaconLocation_t pBeaconLocation, string pchConnectString, string pchMetadata) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString))\n\t\t\tusing (var pchMetadata2 = new InteropHelp.UTF8StringHandle(pchMetadata)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamParties_CreateBeacon(CSteamAPIContext.GetSteamParties(), unOpenSlots, ref pBeaconLocation, pchConnectString2, pchMetadata2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Call this function when a user that had a reservation (see callback below)</para>\n\t\t/// <para> has successfully joined your party.</para>\n\t\t/// <para> Steam will manage the remaining open slots automatically.</para>\n\t\t/// </summary>\n\t\tpublic static void OnReservationCompleted(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamParties_OnReservationCompleted(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> To cancel a reservation (due to timeout or user input), call this.</para>\n\t\t/// <para> Steam will open a new reservation slot.</para>\n\t\t/// <para> Note: The user may already be in-flight to your game, so it's possible they will still connect and try to join your party.</para>\n\t\t/// </summary>\n\t\tpublic static void CancelReservation(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamParties_CancelReservation(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Change the number of open beacon reservation slots.</para>\n\t\t/// <para> Call this if, for example, someone without a reservation joins your party (eg a friend, or via your own matchmaking system).</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t ChangeNumOpenSlots(PartyBeaconID_t ulBeacon, uint unOpenSlots) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamParties_ChangeNumOpenSlots(CSteamAPIContext.GetSteamParties(), ulBeacon, unOpenSlots);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Turn off the beacon.</para>\n\t\t/// </summary>\n\t\tpublic static bool DestroyBeacon(PartyBeaconID_t ulBeacon) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParties_DestroyBeacon(CSteamAPIContext.GetSteamParties(), ulBeacon);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Utils</para>\n\t\t/// </summary>\n\t\tpublic static bool GetBeaconLocationData(SteamPartyBeaconLocation_t BeaconLocation, ESteamPartyBeaconLocationData eData, out string pchDataStringOut, int cchDataStringOut) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchDataStringOut2 = Marshal.AllocHGlobal(cchDataStringOut);\n\t\t\tbool ret = NativeMethods.ISteamParties_GetBeaconLocationData(CSteamAPIContext.GetSteamParties(), BeaconLocation, eData, pchDataStringOut2, cchDataStringOut);\n\t\t\tpchDataStringOut = ret ? InteropHelp.PtrToStringUTF8(pchDataStringOut2) : null;\n\t\t\tMarshal.FreeHGlobal(pchDataStringOut2);\n\t\t\treturn ret;\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteammusic.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamMusic {\n\t\tpublic static bool BIsEnabled() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusic_BIsEnabled(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static bool BIsPlaying() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusic_BIsPlaying(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static AudioPlayback_Status GetPlaybackStatus() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusic_GetPlaybackStatus(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static void Play() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMusic_Play(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static void Pause() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMusic_Pause(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static void PlayPrevious() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMusic_PlayPrevious(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\tpublic static void PlayNext() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMusic_PlayNext(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> volume is between 0.0 and 1.0</para>\n\t\t/// </summary>\n\t\tpublic static void SetVolume(float flVolume) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamMusic_SetVolume(CSteamAPIContext.GetSteamMusic(), flVolume);\n\t\t}\n\n\t\tpublic static float GetVolume() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusic_GetVolume(CSteamAPIContext.GetSteamMusic());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteammusicremote.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamMusicRemote {\n\t\t/// <summary>\n\t\t/// <para> Service Definition</para>\n\t\t/// </summary>\n\t\tpublic static bool RegisterSteamMusicRemote(string pchName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamMusicRemote_RegisterSteamMusicRemote(CSteamAPIContext.GetSteamMusicRemote(), pchName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool DeregisterSteamMusicRemote() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_DeregisterSteamMusicRemote(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool BIsCurrentMusicRemote() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_BIsCurrentMusicRemote(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool BActivationSuccess(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_BActivationSuccess(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool SetDisplayName(string pchDisplayName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDisplayName2 = new InteropHelp.UTF8StringHandle(pchDisplayName)) {\n\t\t\t\treturn NativeMethods.ISteamMusicRemote_SetDisplayName(CSteamAPIContext.GetSteamMusicRemote(), pchDisplayName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetPNGIcon_64x64(byte[] pvBuffer, uint cbBufferLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_SetPNGIcon_64x64(CSteamAPIContext.GetSteamMusicRemote(), pvBuffer, cbBufferLength);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Abilities for the user interface</para>\n\t\t/// </summary>\n\t\tpublic static bool EnablePlayPrevious(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnablePlayPrevious(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool EnablePlayNext(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnablePlayNext(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool EnableShuffled(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnableShuffled(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool EnableLooped(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnableLooped(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool EnableQueue(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnableQueue(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool EnablePlaylists(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_EnablePlaylists(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Status</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdatePlaybackStatus(AudioPlayback_Status nStatus) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdatePlaybackStatus(CSteamAPIContext.GetSteamMusicRemote(), nStatus);\n\t\t}\n\n\t\tpublic static bool UpdateShuffled(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateShuffled(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\tpublic static bool UpdateLooped(bool bValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateLooped(CSteamAPIContext.GetSteamMusicRemote(), bValue);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> volume is between 0.0 and 1.0</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdateVolume(float flValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateVolume(CSteamAPIContext.GetSteamMusicRemote(), flValue);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Current Entry</para>\n\t\t/// </summary>\n\t\tpublic static bool CurrentEntryWillChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_CurrentEntryWillChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool CurrentEntryIsAvailable(bool bAvailable) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_CurrentEntryIsAvailable(CSteamAPIContext.GetSteamMusicRemote(), bAvailable);\n\t\t}\n\n\t\tpublic static bool UpdateCurrentEntryText(string pchText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchText2 = new InteropHelp.UTF8StringHandle(pchText)) {\n\t\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateCurrentEntryText(CSteamAPIContext.GetSteamMusicRemote(), pchText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdateCurrentEntryElapsedSeconds(int nValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds(CSteamAPIContext.GetSteamMusicRemote(), nValue);\n\t\t}\n\n\t\tpublic static bool UpdateCurrentEntryCoverArt(byte[] pvBuffer, uint cbBufferLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_UpdateCurrentEntryCoverArt(CSteamAPIContext.GetSteamMusicRemote(), pvBuffer, cbBufferLength);\n\t\t}\n\n\t\tpublic static bool CurrentEntryDidChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_CurrentEntryDidChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Queue</para>\n\t\t/// </summary>\n\t\tpublic static bool QueueWillChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_QueueWillChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool ResetQueueEntries() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_ResetQueueEntries(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool SetQueueEntry(int nID, int nPosition, string pchEntryText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchEntryText2 = new InteropHelp.UTF8StringHandle(pchEntryText)) {\n\t\t\t\treturn NativeMethods.ISteamMusicRemote_SetQueueEntry(CSteamAPIContext.GetSteamMusicRemote(), nID, nPosition, pchEntryText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetCurrentQueueEntry(int nID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_SetCurrentQueueEntry(CSteamAPIContext.GetSteamMusicRemote(), nID);\n\t\t}\n\n\t\tpublic static bool QueueDidChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_QueueDidChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Playlist</para>\n\t\t/// </summary>\n\t\tpublic static bool PlaylistWillChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_PlaylistWillChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool ResetPlaylistEntries() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_ResetPlaylistEntries(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\n\t\tpublic static bool SetPlaylistEntry(int nID, int nPosition, string pchEntryText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchEntryText2 = new InteropHelp.UTF8StringHandle(pchEntryText)) {\n\t\t\t\treturn NativeMethods.ISteamMusicRemote_SetPlaylistEntry(CSteamAPIContext.GetSteamMusicRemote(), nID, nPosition, pchEntryText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetCurrentPlaylistEntry(int nID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_SetCurrentPlaylistEntry(CSteamAPIContext.GetSteamMusicRemote(), nID);\n\t\t}\n\n\t\tpublic static bool PlaylistDidChange() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamMusicRemote_PlaylistDidChange(CSteamAPIContext.GetSteamMusicRemote());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamnetworking.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamNetworking {\n\t\t/// <summary>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> UDP-style (connectionless) networking interface.  These functions send messages using</para>\n\t\t/// <para> an API organized around the destination.  Reliable and unreliable messages are supported.</para>\n\t\t/// <para> For a more TCP-style interface (meaning you have a connection handle), see the functions below.</para>\n\t\t/// <para> Both interface styles can send both reliable and unreliable messages.</para>\n\t\t/// <para> Automatically establishes NAT-traversing or Relay server connections</para>\n\t\t/// <para> Sends a P2P packet to the specified user</para>\n\t\t/// <para> UDP-like, unreliable and a max packet size of 1200 bytes</para>\n\t\t/// <para> the first packet send may be delayed as the NAT-traversal code runs</para>\n\t\t/// <para> if we can't get through to the user, an error will be posted via the callback P2PSessionConnectFail_t</para>\n\t\t/// <para> see EP2PSend enum above for the descriptions of the different ways of sending packets</para>\n\t\t/// <para> nChannel is a routing number you can use to help route message to different systems \t- you'll have to call ReadP2PPacket()</para>\n\t\t/// <para> with the same channel number in order to retrieve the data on the other end</para>\n\t\t/// <para> using different channels to talk to the same user will still use the same underlying p2p connection, saving on resources</para>\n\t\t/// </summary>\n\t\tpublic static bool SendP2PPacket(CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_SendP2PPacket(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, pubData, cubData, eP2PSendType, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if any data is available for read, and the amount of data that will need to be read</para>\n\t\t/// </summary>\n\t\tpublic static bool IsP2PPacketAvailable(out uint pcubMsgSize, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_IsP2PPacketAvailable(CSteamAPIContext.GetSteamNetworking(), out pcubMsgSize, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> reads in a packet that has been sent from another user via SendP2PPacket()</para>\n\t\t/// <para> returns the size of the message and the steamID of the user who sent it in the last two parameters</para>\n\t\t/// <para> if the buffer passed in is too small, the message will be truncated</para>\n\t\t/// <para> this call is not blocking, and will return false if no data is available</para>\n\t\t/// </summary>\n\t\tpublic static bool ReadP2PPacket(byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel = 0) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_ReadP2PPacket(CSteamAPIContext.GetSteamNetworking(), pubDest, cubDest, out pcubMsgSize, out psteamIDRemote, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> AcceptP2PSessionWithUser() should only be called in response to a P2PSessionRequest_t callback</para>\n\t\t/// <para> P2PSessionRequest_t will be posted if another user tries to send you a packet that you haven't talked to yet</para>\n\t\t/// <para> if you don't want to talk to the user, just ignore the request</para>\n\t\t/// <para> if the user continues to send you packets, another P2PSessionRequest_t will be posted periodically</para>\n\t\t/// <para> this may be called multiple times for a single user</para>\n\t\t/// <para> (if you've called SendP2PPacket() on the other user, this implicitly accepts the session request)</para>\n\t\t/// </summary>\n\t\tpublic static bool AcceptP2PSessionWithUser(CSteamID steamIDRemote) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_AcceptP2PSessionWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> call CloseP2PSessionWithUser() when you're done talking to a user, will free up resources under-the-hood</para>\n\t\t/// <para> if the remote user tries to send data to you again, another P2PSessionRequest_t callback will be posted</para>\n\t\t/// </summary>\n\t\tpublic static bool CloseP2PSessionWithUser(CSteamID steamIDRemote) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_CloseP2PSessionWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> call CloseP2PChannelWithUser() when you're done talking to a user on a specific channel. Once all channels</para>\n\t\t/// <para> open channels to a user have been closed, the open session to the user will be closed and new data from this</para>\n\t\t/// <para> user will trigger a P2PSessionRequest_t callback</para>\n\t\t/// </summary>\n\t\tpublic static bool CloseP2PChannelWithUser(CSteamID steamIDRemote, int nChannel) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_CloseP2PChannelWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, nChannel);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> fills out P2PSessionState_t structure with details about the underlying connection to the user</para>\n\t\t/// <para> should only needed for debugging purposes</para>\n\t\t/// <para> returns false if no connection exists to the specified user</para>\n\t\t/// </summary>\n\t\tpublic static bool GetP2PSessionState(CSteamID steamIDRemote, out P2PSessionState_t pConnectionState) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_GetP2PSessionState(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, out pConnectionState);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Allow P2P connections to fall back to being relayed through the Steam servers if a direct connection</para>\n\t\t/// <para> or NAT-traversal cannot be established. Only applies to connections created after setting this value,</para>\n\t\t/// <para> or to existing connections that need to automatically reconnect after this value is set.</para>\n\t\t/// <para> P2P packet relay is allowed by default</para>\n\t\t/// </summary>\n\t\tpublic static bool AllowP2PPacketRelay(bool bAllow) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_AllowP2PPacketRelay(CSteamAPIContext.GetSteamNetworking(), bAllow);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> LISTEN / CONNECT connection-oriented interface functions</para>\n\t\t/// <para> These functions are more like a client-server TCP API.  One side is the \"server\"</para>\n\t\t/// <para> and \"listens\" for incoming connections, which then must be \"accepted.\"  The \"client\"</para>\n\t\t/// <para> initiates a connection by \"connecting.\"  Sending and receiving is done through a</para>\n\t\t/// <para> connection handle.</para>\n\t\t/// <para> For a more UDP-style interface, where you do not track connection handles but</para>\n\t\t/// <para> simply send messages to a SteamID, use the UDP-style functions above.</para>\n\t\t/// <para> Both methods can send both reliable and unreliable methods.</para>\n\t\t/// <para>//////////////////////////////////////////////////////////////////////////////////////////</para>\n\t\t/// <para> creates a socket and listens others to connect</para>\n\t\t/// <para> will trigger a SocketStatusCallback_t callback on another client connecting</para>\n\t\t/// <para> nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports</para>\n\t\t/// <para>\t\tthis can usually just be 0 unless you want multiple sets of connections</para>\n\t\t/// <para> unIP is the local IP address to bind to</para>\n\t\t/// <para>\t\tpass in 0 if you just want the default local IP</para>\n\t\t/// <para> unPort is the port to use</para>\n\t\t/// <para>\t\tpass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only</para>\n\t\t/// </summary>\n\t\tpublic static SNetListenSocket_t CreateListenSocket(int nVirtualP2PPort, uint nIP, ushort nPort, bool bAllowUseOfPacketRelay) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SNetListenSocket_t)NativeMethods.ISteamNetworking_CreateListenSocket(CSteamAPIContext.GetSteamNetworking(), nVirtualP2PPort, nIP, nPort, bAllowUseOfPacketRelay);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> creates a socket and begin connection to a remote destination</para>\n\t\t/// <para> can connect via a known steamID (client or game server), or directly to an IP</para>\n\t\t/// <para> on success will trigger a SocketStatusCallback_t callback</para>\n\t\t/// <para> on failure or timeout will trigger a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState</para>\n\t\t/// </summary>\n\t\tpublic static SNetSocket_t CreateP2PConnectionSocket(CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SNetSocket_t)NativeMethods.ISteamNetworking_CreateP2PConnectionSocket(CSteamAPIContext.GetSteamNetworking(), steamIDTarget, nVirtualPort, nTimeoutSec, bAllowUseOfPacketRelay);\n\t\t}\n\n\t\tpublic static SNetSocket_t CreateConnectionSocket(uint nIP, ushort nPort, int nTimeoutSec) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SNetSocket_t)NativeMethods.ISteamNetworking_CreateConnectionSocket(CSteamAPIContext.GetSteamNetworking(), nIP, nPort, nTimeoutSec);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> disconnects the connection to the socket, if any, and invalidates the handle</para>\n\t\t/// <para> any unread data on the socket will be thrown away</para>\n\t\t/// <para> if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect</para>\n\t\t/// </summary>\n\t\tpublic static bool DestroySocket(SNetSocket_t hSocket, bool bNotifyRemoteEnd) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_DestroySocket(CSteamAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> destroying a listen socket will automatically kill all the regular sockets generated from it</para>\n\t\t/// </summary>\n\t\tpublic static bool DestroyListenSocket(SNetListenSocket_t hSocket, bool bNotifyRemoteEnd) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_DestroyListenSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> sending data</para>\n\t\t/// <para> must be a handle to a connected socket</para>\n\t\t/// <para> data is all sent via UDP, and thus send sizes are limited to 1200 bytes; after this, many routers will start dropping packets</para>\n\t\t/// <para> use the reliable flag with caution; although the resend rate is pretty aggressive,</para>\n\t\t/// <para> it can still cause stalls in receiving data (like TCP)</para>\n\t\t/// </summary>\n\t\tpublic static bool SendDataOnSocket(SNetSocket_t hSocket, byte[] pubData, uint cubData, bool bReliable) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_SendDataOnSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, pubData, cubData, bReliable);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> receiving data</para>\n\t\t/// <para> returns false if there is no data remaining</para>\n\t\t/// <para> fills out *pcubMsgSize with the size of the next message, in bytes</para>\n\t\t/// </summary>\n\t\tpublic static bool IsDataAvailableOnSocket(SNetSocket_t hSocket, out uint pcubMsgSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_IsDataAvailableOnSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, out pcubMsgSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> fills in pubDest with the contents of the message</para>\n\t\t/// <para> messages are always complete, of the same size as was sent (i.e. packetized, not streaming)</para>\n\t\t/// <para> if *pcubMsgSize &lt; cubDest, only partial data is written</para>\n\t\t/// <para> returns false if no data is available</para>\n\t\t/// </summary>\n\t\tpublic static bool RetrieveDataFromSocket(SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_RetrieveDataFromSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, pubDest, cubDest, out pcubMsgSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> checks for data from any socket that has been connected off this listen socket</para>\n\t\t/// <para> returns false if there is no data remaining</para>\n\t\t/// <para> fills out *pcubMsgSize with the size of the next message, in bytes</para>\n\t\t/// <para> fills out *phSocket with the socket that data is available on</para>\n\t\t/// </summary>\n\t\tpublic static bool IsDataAvailable(SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_IsDataAvailable(CSteamAPIContext.GetSteamNetworking(), hListenSocket, out pcubMsgSize, out phSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieves data from any socket that has been connected off this listen socket</para>\n\t\t/// <para> fills in pubDest with the contents of the message</para>\n\t\t/// <para> messages are always complete, of the same size as was sent (i.e. packetized, not streaming)</para>\n\t\t/// <para> if *pcubMsgSize &lt; cubDest, only partial data is written</para>\n\t\t/// <para> returns false if no data is available</para>\n\t\t/// <para> fills out *phSocket with the socket that data is available on</para>\n\t\t/// </summary>\n\t\tpublic static bool RetrieveData(SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_RetrieveData(CSteamAPIContext.GetSteamNetworking(), hListenSocket, pubDest, cubDest, out pcubMsgSize, out phSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns information about the specified socket, filling out the contents of the pointers</para>\n\t\t/// </summary>\n\t\tpublic static bool GetSocketInfo(SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out uint punIPRemote, out ushort punPortRemote) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_GetSocketInfo(CSteamAPIContext.GetSteamNetworking(), hSocket, out pSteamIDRemote, out peSocketStatus, out punIPRemote, out punPortRemote);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns which local port the listen socket is bound to</para>\n\t\t/// <para> *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only</para>\n\t\t/// </summary>\n\t\tpublic static bool GetListenSocketInfo(SNetListenSocket_t hListenSocket, out uint pnIP, out ushort pnPort) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_GetListenSocketInfo(CSteamAPIContext.GetSteamNetworking(), hListenSocket, out pnIP, out pnPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true to describe how the socket ended up connecting</para>\n\t\t/// </summary>\n\t\tpublic static ESNetSocketConnectionType GetSocketConnectionType(SNetSocket_t hSocket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_GetSocketConnectionType(CSteamAPIContext.GetSteamNetworking(), hSocket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> max packet size, in bytes</para>\n\t\t/// </summary>\n\t\tpublic static int GetMaxPacketSize(SNetSocket_t hSocket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamNetworking_GetMaxPacketSize(CSteamAPIContext.GetSteamNetworking(), hSocket);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamparentalsettings.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamParentalSettings {\n\t\tpublic static bool BIsParentalLockEnabled() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsParentalLockEnabled(CSteamAPIContext.GetSteamParentalSettings());\n\t\t}\n\n\t\tpublic static bool BIsParentalLockLocked() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsParentalLockLocked(CSteamAPIContext.GetSteamParentalSettings());\n\t\t}\n\n\t\tpublic static bool BIsAppBlocked(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsAppBlocked(CSteamAPIContext.GetSteamParentalSettings(), nAppID);\n\t\t}\n\n\t\tpublic static bool BIsAppInBlockList(AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsAppInBlockList(CSteamAPIContext.GetSteamParentalSettings(), nAppID);\n\t\t}\n\n\t\tpublic static bool BIsFeatureBlocked(EParentalFeature eFeature) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsFeatureBlocked(CSteamAPIContext.GetSteamParentalSettings(), eFeature);\n\t\t}\n\n\t\tpublic static bool BIsFeatureInBlockList(EParentalFeature eFeature) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamParentalSettings_BIsFeatureInBlockList(CSteamAPIContext.GetSteamParentalSettings(), eFeature);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamremoteplay.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamRemotePlay {\n\t\t/// <summary>\n\t\t/// <para> Get the number of currently connected Steam Remote Play sessions</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSessionCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemotePlay_GetSessionCount(CSteamAPIContext.GetSteamRemotePlay());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the currently connected Steam Remote Play session ID at the specified index. Returns zero if index is out of bounds.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSessionID(int iSessionIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemotePlay_GetSessionID(CSteamAPIContext.GetSteamRemotePlay(), iSessionIndex);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the SteamID of the connected user</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetSessionSteamID(uint unSessionID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamRemotePlay_GetSessionSteamID(CSteamAPIContext.GetSteamRemotePlay(), unSessionID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the name of the session client device</para>\n\t\t/// <para> This returns NULL if the sessionID is not valid</para>\n\t\t/// </summary>\n\t\tpublic static string GetSessionClientName(uint unSessionID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamRemotePlay_GetSessionClientName(CSteamAPIContext.GetSteamRemotePlay(), unSessionID));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the form factor of the session client device</para>\n\t\t/// </summary>\n\t\tpublic static ESteamDeviceFormFactor GetSessionClientFormFactor(uint unSessionID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemotePlay_GetSessionClientFormFactor(CSteamAPIContext.GetSteamRemotePlay(), unSessionID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the resolution, in pixels, of the session client device</para>\n\t\t/// <para> This is set to 0x0 if the resolution is not available</para>\n\t\t/// </summary>\n\t\tpublic static bool BGetSessionClientResolution(uint unSessionID, out int pnResolutionX, out int pnResolutionY) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemotePlay_BGetSessionClientResolution(CSteamAPIContext.GetSteamRemotePlay(), unSessionID, out pnResolutionX, out pnResolutionY);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamremotestorage.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamRemoteStorage {\n\t\t/// <summary>\n\t\t/// <para> NOTE</para>\n\t\t/// <para> Filenames are case-insensitive, and will be converted to lowercase automatically.</para>\n\t\t/// <para> So \"foo.bar\" and \"Foo.bar\" are the same file, and if you write \"Foo.bar\" then</para>\n\t\t/// <para> iterate the files, the filename returned will be \"foo.bar\".</para>\n\t\t/// <para> file operations</para>\n\t\t/// </summary>\n\t\tpublic static bool FileWrite(string pchFile, byte[] pvData, int cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileWrite(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static int FileRead(string pchFile, byte[] pvData, int cubDataToRead) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileRead(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubDataToRead);\n\t\t\t}\n\t\t}\n\n\t\tpublic static SteamAPICall_t FileWriteAsync(string pchFile, byte[] pvData, uint cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileWriteAsync(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static SteamAPICall_t FileReadAsync(string pchFile, uint nOffset, uint cubToRead) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileReadAsync(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, nOffset, cubToRead);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool FileReadAsyncComplete(SteamAPICall_t hReadCall, byte[] pvBuffer, uint cubToRead) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_FileReadAsyncComplete(CSteamAPIContext.GetSteamRemoteStorage(), hReadCall, pvBuffer, cubToRead);\n\t\t}\n\n\t\tpublic static bool FileForget(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileForget(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool FileDelete(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileDelete(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static SteamAPICall_t FileShare(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileShare(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetSyncPlatforms(string pchFile, ERemoteStoragePlatform eRemoteStoragePlatform) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_SetSyncPlatforms(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, eRemoteStoragePlatform);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> file operations that cause network IO</para>\n\t\t/// </summary>\n\t\tpublic static UGCFileWriteStreamHandle_t FileWriteStreamOpen(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn (UGCFileWriteStreamHandle_t)NativeMethods.ISteamRemoteStorage_FileWriteStreamOpen(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool FileWriteStreamWriteChunk(UGCFileWriteStreamHandle_t writeHandle, byte[] pvData, int cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_FileWriteStreamWriteChunk(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle, pvData, cubData);\n\t\t}\n\n\t\tpublic static bool FileWriteStreamClose(UGCFileWriteStreamHandle_t writeHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_FileWriteStreamClose(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle);\n\t\t}\n\n\t\tpublic static bool FileWriteStreamCancel(UGCFileWriteStreamHandle_t writeHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_FileWriteStreamCancel(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> file information</para>\n\t\t/// </summary>\n\t\tpublic static bool FileExists(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileExists(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool FilePersisted(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FilePersisted(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static int GetFileSize(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_GetFileSize(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static long GetFileTimestamp(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_GetFileTimestamp(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static ERemoteStoragePlatform GetSyncPlatforms(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_GetSyncPlatforms(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> iteration</para>\n\t\t/// </summary>\n\t\tpublic static int GetFileCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_GetFileCount(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\tpublic static string GetFileNameAndSize(int iFile, out int pnFileSizeInBytes) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamRemoteStorage_GetFileNameAndSize(CSteamAPIContext.GetSteamRemoteStorage(), iFile, out pnFileSizeInBytes));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> configuration management</para>\n\t\t/// </summary>\n\t\tpublic static bool GetQuota(out ulong pnTotalBytes, out ulong puAvailableBytes) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_GetQuota(CSteamAPIContext.GetSteamRemoteStorage(), out pnTotalBytes, out puAvailableBytes);\n\t\t}\n\n\t\tpublic static bool IsCloudEnabledForAccount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_IsCloudEnabledForAccount(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\tpublic static bool IsCloudEnabledForApp() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_IsCloudEnabledForApp(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\tpublic static void SetCloudEnabledForApp(bool bEnabled) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamRemoteStorage_SetCloudEnabledForApp(CSteamAPIContext.GetSteamRemoteStorage(), bEnabled);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> user generated content</para>\n\t\t/// <para> Downloads a UGC file.  A priority value of 0 will download the file immediately,</para>\n\t\t/// <para> otherwise it will wait to download the file until all downloads with a lower priority</para>\n\t\t/// <para> value are completed.  Downloads with equal priority will occur simultaneously.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t UGCDownload(UGCHandle_t hContent, uint unPriority) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UGCDownload(CSteamAPIContext.GetSteamRemoteStorage(), hContent, unPriority);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the amount of data downloaded so far for a piece of content. pnBytesExpected can be 0 if function returns false</para>\n\t\t/// <para> or if the transfer hasn't started yet, so be careful to check for that before dividing to get a percentage</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUGCDownloadProgress(UGCHandle_t hContent, out int pnBytesDownloaded, out int pnBytesExpected) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_GetUGCDownloadProgress(CSteamAPIContext.GetSteamRemoteStorage(), hContent, out pnBytesDownloaded, out pnBytesExpected);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets metadata for a file after it has been downloaded. This is the same metadata given in the RemoteStorageDownloadUGCResult_t call result</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUGCDetails(UGCHandle_t hContent, out AppId_t pnAppID, out string ppchName, out int pnFileSizeInBytes, out CSteamID pSteamIDOwner) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr ppchName2;\n\t\t\tbool ret = NativeMethods.ISteamRemoteStorage_GetUGCDetails(CSteamAPIContext.GetSteamRemoteStorage(), hContent, out pnAppID, out ppchName2, out pnFileSizeInBytes, out pSteamIDOwner);\n\t\t\tppchName = ret ? InteropHelp.PtrToStringUTF8(ppchName2) : null;\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> After download, gets the content of the file.</para>\n\t\t/// <para> Small files can be read all at once by calling this function with an offset of 0 and cubDataToRead equal to the size of the file.</para>\n\t\t/// <para> Larger files can be read in chunks to reduce memory usage (since both sides of the IPC client and the game itself must allocate</para>\n\t\t/// <para> enough memory for each chunk).  Once the last byte is read, the file is implicitly closed and further calls to UGCRead will fail</para>\n\t\t/// <para> unless UGCDownload is called again.</para>\n\t\t/// <para> For especially large files (anything over 100MB) it is a requirement that the file is read in chunks.</para>\n\t\t/// </summary>\n\t\tpublic static int UGCRead(UGCHandle_t hContent, byte[] pvData, int cubDataToRead, uint cOffset, EUGCReadAction eAction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_UGCRead(CSteamAPIContext.GetSteamRemoteStorage(), hContent, pvData, cubDataToRead, cOffset, eAction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Functions to iterate through UGC that has finished downloading but has not yet been read via UGCRead()</para>\n\t\t/// </summary>\n\t\tpublic static int GetCachedUGCCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_GetCachedUGCCount(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\tpublic static UGCHandle_t GetCachedUGCHandle(int iCachedContent) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (UGCHandle_t)NativeMethods.ISteamRemoteStorage_GetCachedUGCHandle(CSteamAPIContext.GetSteamRemoteStorage(), iCachedContent);\n\t\t}\n#if _PS3 || _SERVER\n\t\t/// <summary>\n\t\t/// <para> The following functions are only necessary on the Playstation 3. On PC &amp; Mac, the Steam client will handle these operations for you</para>\n\t\t/// <para> On Playstation 3, the game controls which files are stored in the cloud, via FilePersist, FileFetch, and FileForget.</para>\n\t\t/// <para> Connect to Steam and get a list of files in the Cloud - results in a RemoteStorageAppSyncStatusCheck_t callback</para>\n\t\t/// </summary>\n\t\tpublic static void GetFileListFromServer() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamRemoteStorage_GetFileListFromServer(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Indicate this file should be downloaded in the next sync</para>\n\t\t/// </summary>\n\t\tpublic static bool FileFetch(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FileFetch(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Indicate this file should be persisted in the next sync</para>\n\t\t/// </summary>\n\t\tpublic static bool FilePersist(string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_FilePersist(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Pull any requested files down from the Cloud - results in a RemoteStorageAppSyncedClient_t callback</para>\n\t\t/// </summary>\n\t\tpublic static bool SynchronizeToClient() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_SynchronizeToClient(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Upload any requested files to the Cloud - results in a RemoteStorageAppSyncedServer_t callback</para>\n\t\t/// </summary>\n\t\tpublic static bool SynchronizeToServer() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_SynchronizeToServer(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Reset any fetch/persist/etc requests</para>\n\t\t/// </summary>\n\t\tpublic static bool ResetFileRequestState() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_ResetFileRequestState(CSteamAPIContext.GetSteamRemoteStorage());\n\t\t}\n#endif\n\t\t/// <summary>\n\t\t/// <para> publishing UGC</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t PublishWorkshopFile(string pchFile, string pchPreviewFile, AppId_t nConsumerAppId, string pchTitle, string pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, System.Collections.Generic.IList<string> pTags, EWorkshopFileType eWorkshopFileType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile))\n\t\t\tusing (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile))\n\t\t\tusing (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle))\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_PublishWorkshopFile(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pchPreviewFile2, nConsumerAppId, pchTitle2, pchDescription2, eVisibility, new InteropHelp.SteamParamStringArray(pTags), eWorkshopFileType);\n\t\t\t}\n\t\t}\n\n\t\tpublic static PublishedFileUpdateHandle_t CreatePublishedFileUpdateRequest(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (PublishedFileUpdateHandle_t)NativeMethods.ISteamRemoteStorage_CreatePublishedFileUpdateRequest(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileFile(PublishedFileUpdateHandle_t updateHandle, string pchFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileFile(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFilePreviewFile(PublishedFileUpdateHandle_t updateHandle, string pchPreviewFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFilePreviewFile(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchPreviewFile2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileTitle(PublishedFileUpdateHandle_t updateHandle, string pchTitle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileTitle(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchTitle2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileDescription(PublishedFileUpdateHandle_t updateHandle, string pchDescription) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileDescription(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchDescription2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileVisibility(PublishedFileUpdateHandle_t updateHandle, ERemoteStoragePublishedFileVisibility eVisibility) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileVisibility(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, eVisibility);\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileTags(PublishedFileUpdateHandle_t updateHandle, System.Collections.Generic.IList<string> pTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileTags(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, new InteropHelp.SteamParamStringArray(pTags));\n\t\t}\n\n\t\tpublic static SteamAPICall_t CommitPublishedFileUpdate(PublishedFileUpdateHandle_t updateHandle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_CommitPublishedFileUpdate(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets published file details for the given publishedfileid.  If unMaxSecondsOld is greater than 0,</para>\n\t\t/// <para> cached data may be returned, depending on how long ago it was cached.  A value of 0 will force a refresh.</para>\n\t\t/// <para> A value of k_WorkshopForceLoadPublishedFileDetailsFromCache will use cached data if it exists, no matter how old it is.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetPublishedFileDetails(PublishedFileId_t unPublishedFileId, uint unMaxSecondsOld) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetPublishedFileDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, unMaxSecondsOld);\n\t\t}\n\n\t\tpublic static SteamAPICall_t DeletePublishedFile(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_DeletePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> enumerate the files that the current user published with this app</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t EnumerateUserPublishedFiles(uint unStartIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserPublishedFiles(CSteamAPIContext.GetSteamRemoteStorage(), unStartIndex);\n\t\t}\n\n\t\tpublic static SteamAPICall_t SubscribePublishedFile(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_SubscribePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\tpublic static SteamAPICall_t EnumerateUserSubscribedFiles(uint unStartIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserSubscribedFiles(CSteamAPIContext.GetSteamRemoteStorage(), unStartIndex);\n\t\t}\n\n\t\tpublic static SteamAPICall_t UnsubscribePublishedFile(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UnsubscribePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\tpublic static bool UpdatePublishedFileSetChangeDescription(PublishedFileUpdateHandle_t updateHandle, string pchChangeDescription) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchChangeDescription2 = new InteropHelp.UTF8StringHandle(pchChangeDescription)) {\n\t\t\t\treturn NativeMethods.ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchChangeDescription2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetPublishedItemVoteDetails(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetPublishedItemVoteDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\tpublic static SteamAPICall_t UpdateUserPublishedItemVote(PublishedFileId_t unPublishedFileId, bool bVoteUp) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UpdateUserPublishedItemVote(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, bVoteUp);\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetUserPublishedItemVoteDetails(PublishedFileId_t unPublishedFileId) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetUserPublishedItemVoteDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId);\n\t\t}\n\n\t\tpublic static SteamAPICall_t EnumerateUserSharedWorkshopFiles(CSteamID steamId, uint unStartIndex, System.Collections.Generic.IList<string> pRequiredTags, System.Collections.Generic.IList<string> pExcludedTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles(CSteamAPIContext.GetSteamRemoteStorage(), steamId, unStartIndex, new InteropHelp.SteamParamStringArray(pRequiredTags), new InteropHelp.SteamParamStringArray(pExcludedTags));\n\t\t}\n\n\t\tpublic static SteamAPICall_t PublishVideo(EWorkshopVideoProvider eVideoProvider, string pchVideoAccount, string pchVideoIdentifier, string pchPreviewFile, AppId_t nConsumerAppId, string pchTitle, string pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, System.Collections.Generic.IList<string> pTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchVideoAccount2 = new InteropHelp.UTF8StringHandle(pchVideoAccount))\n\t\t\tusing (var pchVideoIdentifier2 = new InteropHelp.UTF8StringHandle(pchVideoIdentifier))\n\t\t\tusing (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile))\n\t\t\tusing (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle))\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_PublishVideo(CSteamAPIContext.GetSteamRemoteStorage(), eVideoProvider, pchVideoAccount2, pchVideoIdentifier2, pchPreviewFile2, nConsumerAppId, pchTitle2, pchDescription2, eVisibility, new InteropHelp.SteamParamStringArray(pTags));\n\t\t\t}\n\t\t}\n\n\t\tpublic static SteamAPICall_t SetUserPublishedFileAction(PublishedFileId_t unPublishedFileId, EWorkshopFileAction eAction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_SetUserPublishedFileAction(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, eAction);\n\t\t}\n\n\t\tpublic static SteamAPICall_t EnumeratePublishedFilesByUserAction(EWorkshopFileAction eAction, uint unStartIndex) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumeratePublishedFilesByUserAction(CSteamAPIContext.GetSteamRemoteStorage(), eAction, unStartIndex);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> this method enumerates the public view of workshop files</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t EnumeratePublishedWorkshopFiles(EWorkshopEnumerationType eEnumerationType, uint unStartIndex, uint unCount, uint unDays, System.Collections.Generic.IList<string> pTags, System.Collections.Generic.IList<string> pUserTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumeratePublishedWorkshopFiles(CSteamAPIContext.GetSteamRemoteStorage(), eEnumerationType, unStartIndex, unCount, unDays, new InteropHelp.SteamParamStringArray(pTags), new InteropHelp.SteamParamStringArray(pUserTags));\n\t\t}\n\n\t\tpublic static SteamAPICall_t UGCDownloadToLocation(UGCHandle_t hContent, string pchLocation, uint unPriority) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLocation2 = new InteropHelp.UTF8StringHandle(pchLocation)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UGCDownloadToLocation(CSteamAPIContext.GetSteamRemoteStorage(), hContent, pchLocation2, unPriority);\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamscreenshots.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamScreenshots {\n\t\t/// <summary>\n\t\t/// <para> Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB format.</para>\n\t\t/// <para> The return value is a handle that is valid for the duration of the game process and can be used to apply tags.</para>\n\t\t/// </summary>\n\t\tpublic static ScreenshotHandle WriteScreenshot(byte[] pubRGB, uint cubRGB, int nWidth, int nHeight) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (ScreenshotHandle)NativeMethods.ISteamScreenshots_WriteScreenshot(CSteamAPIContext.GetSteamScreenshots(), pubRGB, cubRGB, nWidth, nHeight);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Adds a screenshot to the user's screenshot library from disk.  If a thumbnail is provided, it must be 200 pixels wide and the same aspect ratio</para>\n\t\t/// <para> as the screenshot, otherwise a thumbnail will be generated if the user uploads the screenshot.  The screenshots must be in either JPEG or TGA format.</para>\n\t\t/// <para> The return value is a handle that is valid for the duration of the game process and can be used to apply tags.</para>\n\t\t/// <para> JPEG, TGA, and PNG formats are supported.</para>\n\t\t/// </summary>\n\t\tpublic static ScreenshotHandle AddScreenshotToLibrary(string pchFilename, string pchThumbnailFilename, int nWidth, int nHeight) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFilename2 = new InteropHelp.UTF8StringHandle(pchFilename))\n\t\t\tusing (var pchThumbnailFilename2 = new InteropHelp.UTF8StringHandle(pchThumbnailFilename)) {\n\t\t\t\treturn (ScreenshotHandle)NativeMethods.ISteamScreenshots_AddScreenshotToLibrary(CSteamAPIContext.GetSteamScreenshots(), pchFilename2, pchThumbnailFilename2, nWidth, nHeight);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Causes the Steam overlay to take a screenshot.  If screenshots are being hooked by the game then a ScreenshotRequested_t callback is sent back to the game instead.</para>\n\t\t/// </summary>\n\t\tpublic static void TriggerScreenshot() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamScreenshots_TriggerScreenshot(CSteamAPIContext.GetSteamScreenshots());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or the game handles them.  If the game is hooking screenshots,</para>\n\t\t/// <para> then the ScreenshotRequested_t callback will be sent if the user presses the hotkey, and the game is expected to call WriteScreenshot or AddScreenshotToLibrary</para>\n\t\t/// <para> in response.</para>\n\t\t/// </summary>\n\t\tpublic static void HookScreenshots(bool bHook) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamScreenshots_HookScreenshots(CSteamAPIContext.GetSteamScreenshots(), bHook);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets metadata about a screenshot's location (for example, the name of the map)</para>\n\t\t/// </summary>\n\t\tpublic static bool SetLocation(ScreenshotHandle hScreenshot, string pchLocation) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLocation2 = new InteropHelp.UTF8StringHandle(pchLocation)) {\n\t\t\t\treturn NativeMethods.ISteamScreenshots_SetLocation(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, pchLocation2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Tags a user as being visible in the screenshot</para>\n\t\t/// </summary>\n\t\tpublic static bool TagUser(ScreenshotHandle hScreenshot, CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamScreenshots_TagUser(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Tags a published file as being visible in the screenshot</para>\n\t\t/// </summary>\n\t\tpublic static bool TagPublishedFile(ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamScreenshots_TagPublishedFile(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, unPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the app has hooked the screenshot</para>\n\t\t/// </summary>\n\t\tpublic static bool IsScreenshotsHooked() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamScreenshots_IsScreenshotsHooked(CSteamAPIContext.GetSteamScreenshots());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Adds a VR screenshot to the user's screenshot library from disk in the supported type.</para>\n\t\t/// <para> pchFilename should be the normal 2D image used in the library view</para>\n\t\t/// <para> pchVRFilename should contain the image that matches the correct type</para>\n\t\t/// <para> The return value is a handle that is valid for the duration of the game process and can be used to apply tags.</para>\n\t\t/// <para> JPEG, TGA, and PNG formats are supported.</para>\n\t\t/// </summary>\n\t\tpublic static ScreenshotHandle AddVRScreenshotToLibrary(EVRScreenshotType eType, string pchFilename, string pchVRFilename) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchFilename2 = new InteropHelp.UTF8StringHandle(pchFilename))\n\t\t\tusing (var pchVRFilename2 = new InteropHelp.UTF8StringHandle(pchVRFilename)) {\n\t\t\t\treturn (ScreenshotHandle)NativeMethods.ISteamScreenshots_AddVRScreenshotToLibrary(CSteamAPIContext.GetSteamScreenshots(), eType, pchFilename2, pchVRFilename2);\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamugc.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamUGC {\n\t\t/// <summary>\n\t\t/// <para> Query UGC associated with a user. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryUserUGCRequest(AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUserUGCRequest(CSteamAPIContext.GetSteamUGC(), unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for all matching UGC. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequest(CSteamAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, unPage);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for all matching UGC using the new deep paging interface. Creator app id or consumer app id must be valid and be set to the current running app. pchCursor should be set to NULL or \"*\" to get the first result set.</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, string pchCursor = null) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchCursor2 = new InteropHelp.UTF8StringHandle(pchCursor)) {\n\t\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequest0(CSteamAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, pchCursor2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this)</para>\n\t\t/// </summary>\n\t\tpublic static UGCQueryHandle_t CreateQueryUGCDetailsRequest(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUGCDetailsRequest(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Send the query to Steam</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SendQueryUGCRequest(UGCQueryHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SendQueryUGCRequest(CSteamAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieve an individual result after receiving the callback for querying UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool GetQueryUGCResult(UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCResult(CSteamAPIContext.GetSteamUGC(), handle, index, out pDetails);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCPreviewURL(UGCQueryHandle_t handle, uint index, out string pchURL, uint cchURLSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchURL2 = Marshal.AllocHGlobal((int)cchURLSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCPreviewURL(CSteamAPIContext.GetSteamUGC(), handle, index, pchURL2, cchURLSize);\n\t\t\tpchURL = ret ? InteropHelp.PtrToStringUTF8(pchURL2) : null;\n\t\t\tMarshal.FreeHGlobal(pchURL2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool GetQueryUGCMetadata(UGCQueryHandle_t handle, uint index, out string pchMetadata, uint cchMetadatasize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchMetadata2 = Marshal.AllocHGlobal((int)cchMetadatasize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCMetadata(CSteamAPIContext.GetSteamUGC(), handle, index, pchMetadata2, cchMetadatasize);\n\t\t\tpchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null;\n\t\t\tMarshal.FreeHGlobal(pchMetadata2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static bool GetQueryUGCChildren(UGCQueryHandle_t handle, uint index, PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCChildren(CSteamAPIContext.GetSteamUGC(), handle, index, pvecPublishedFileID, cMaxEntries);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCStatistic(UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCStatistic(CSteamAPIContext.GetSteamUGC(), handle, index, eStatType, out pStatValue);\n\t\t}\n\n\t\tpublic static uint GetQueryUGCNumAdditionalPreviews(UGCQueryHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCNumAdditionalPreviews(CSteamAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCAdditionalPreview(UGCQueryHandle_t handle, uint index, uint previewIndex, out string pchURLOrVideoID, uint cchURLSize, out string pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchURLOrVideoID2 = Marshal.AllocHGlobal((int)cchURLSize);\n\t\t\tIntPtr pchOriginalFileName2 = Marshal.AllocHGlobal((int)cchOriginalFileNameSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCAdditionalPreview(CSteamAPIContext.GetSteamUGC(), handle, index, previewIndex, pchURLOrVideoID2, cchURLSize, pchOriginalFileName2, cchOriginalFileNameSize, out pPreviewType);\n\t\t\tpchURLOrVideoID = ret ? InteropHelp.PtrToStringUTF8(pchURLOrVideoID2) : null;\n\t\t\tMarshal.FreeHGlobal(pchURLOrVideoID2);\n\t\t\tpchOriginalFileName = ret ? InteropHelp.PtrToStringUTF8(pchOriginalFileName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchOriginalFileName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\tpublic static uint GetQueryUGCNumKeyValueTags(UGCQueryHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetQueryUGCNumKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\tpublic static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, out string pchKey, uint cchKeySize, out string pchValue, uint cchValueSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchKey2 = Marshal.AllocHGlobal((int)cchKeySize);\n\t\t\tIntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, index, keyValueTagIndex, pchKey2, cchKeySize, pchValue2, cchValueSize);\n\t\t\tpchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null;\n\t\t\tMarshal.FreeHGlobal(pchKey2);\n\t\t\tpchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;\n\t\t\tMarshal.FreeHGlobal(pchValue2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Return the first value matching the pchKey. Note that a key may map to multiple values.  Returns false if there was an error or no matching value was found.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, string pchKey, out string pchValue, uint cchValueSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize);\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\tbool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag0(CSteamAPIContext.GetSteamUGC(), handle, index, pchKey2, pchValue2, cchValueSize);\n\t\t\t\tpchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchValue2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Release the request to free up memory, after retrieving results</para>\n\t\t/// </summary>\n\t\tpublic static bool ReleaseQueryUGCRequest(UGCQueryHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_ReleaseQueryUGCRequest(CSteamAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options to set for querying UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool AddRequiredTag(UGCQueryHandle_t handle, string pTagName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddRequiredTag(CSteamAPIContext.GetSteamUGC(), handle, pTagName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool AddExcludedTag(UGCQueryHandle_t handle, string pTagName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddExcludedTag(CSteamAPIContext.GetSteamUGC(), handle, pTagName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetReturnOnlyIDs(UGCQueryHandle_t handle, bool bReturnOnlyIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnOnlyIDs(CSteamAPIContext.GetSteamUGC(), handle, bReturnOnlyIDs);\n\t\t}\n\n\t\tpublic static bool SetReturnKeyValueTags(UGCQueryHandle_t handle, bool bReturnKeyValueTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, bReturnKeyValueTags);\n\t\t}\n\n\t\tpublic static bool SetReturnLongDescription(UGCQueryHandle_t handle, bool bReturnLongDescription) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnLongDescription(CSteamAPIContext.GetSteamUGC(), handle, bReturnLongDescription);\n\t\t}\n\n\t\tpublic static bool SetReturnMetadata(UGCQueryHandle_t handle, bool bReturnMetadata) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnMetadata(CSteamAPIContext.GetSteamUGC(), handle, bReturnMetadata);\n\t\t}\n\n\t\tpublic static bool SetReturnChildren(UGCQueryHandle_t handle, bool bReturnChildren) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnChildren(CSteamAPIContext.GetSteamUGC(), handle, bReturnChildren);\n\t\t}\n\n\t\tpublic static bool SetReturnAdditionalPreviews(UGCQueryHandle_t handle, bool bReturnAdditionalPreviews) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnAdditionalPreviews(CSteamAPIContext.GetSteamUGC(), handle, bReturnAdditionalPreviews);\n\t\t}\n\n\t\tpublic static bool SetReturnTotalOnly(UGCQueryHandle_t handle, bool bReturnTotalOnly) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnTotalOnly(CSteamAPIContext.GetSteamUGC(), handle, bReturnTotalOnly);\n\t\t}\n\n\t\tpublic static bool SetReturnPlaytimeStats(UGCQueryHandle_t handle, uint unDays) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetReturnPlaytimeStats(CSteamAPIContext.GetSteamUGC(), handle, unDays);\n\t\t}\n\n\t\tpublic static bool SetLanguage(UGCQueryHandle_t handle, string pchLanguage) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetLanguage(CSteamAPIContext.GetSteamUGC(), handle, pchLanguage2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetAllowCachedResponse(UGCQueryHandle_t handle, uint unMaxAgeSeconds) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetAllowCachedResponse(CSteamAPIContext.GetSteamUGC(), handle, unMaxAgeSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options only for querying user UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool SetCloudFileNameFilter(UGCQueryHandle_t handle, string pMatchCloudFileName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pMatchCloudFileName2 = new InteropHelp.UTF8StringHandle(pMatchCloudFileName)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetCloudFileNameFilter(CSteamAPIContext.GetSteamUGC(), handle, pMatchCloudFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Options only for querying all UGC</para>\n\t\t/// </summary>\n\t\tpublic static bool SetMatchAnyTag(UGCQueryHandle_t handle, bool bMatchAnyTag) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetMatchAnyTag(CSteamAPIContext.GetSteamUGC(), handle, bMatchAnyTag);\n\t\t}\n\n\t\tpublic static bool SetSearchText(UGCQueryHandle_t handle, string pSearchText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pSearchText2 = new InteropHelp.UTF8StringHandle(pSearchText)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetSearchText(CSteamAPIContext.GetSteamUGC(), handle, pSearchText2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetRankedByTrendDays(UGCQueryHandle_t handle, uint unDays) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetRankedByTrendDays(CSteamAPIContext.GetSteamUGC(), handle, unDays);\n\t\t}\n\n\t\tpublic static bool AddRequiredKeyValueTag(UGCQueryHandle_t handle, string pKey, string pValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pKey2 = new InteropHelp.UTF8StringHandle(pKey))\n\t\t\tusing (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddRequiredKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, pKey2, pValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead!</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestUGCDetails(PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RequestUGCDetails(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, unMaxAgeSeconds);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Workshop Creator API</para>\n\t\t/// <para> create new item for this app with no content attached yet</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CreateItem(AppId_t nConsumerAppId, EWorkshopFileType eFileType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_CreateItem(CSteamAPIContext.GetSteamUGC(), nConsumerAppId, eFileType);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> start an UGC item update. Set changed properties before commiting update with CommitItemUpdate()</para>\n\t\t/// </summary>\n\t\tpublic static UGCUpdateHandle_t StartItemUpdate(AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (UGCUpdateHandle_t)NativeMethods.ISteamUGC_StartItemUpdate(CSteamAPIContext.GetSteamUGC(), nConsumerAppId, nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the title of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemTitle(UGCUpdateHandle_t handle, string pchTitle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemTitle(CSteamAPIContext.GetSteamUGC(), handle, pchTitle2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the description of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemDescription(UGCUpdateHandle_t handle, string pchDescription) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemDescription(CSteamAPIContext.GetSteamUGC(), handle, pchDescription2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> specify the language of the title or description that will be set</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemUpdateLanguage(UGCUpdateHandle_t handle, string pchLanguage) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemUpdateLanguage(CSteamAPIContext.GetSteamUGC(), handle, pchLanguage2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the metadata of an UGC item (max = k_cchDeveloperMetadataMax)</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemMetadata(UGCUpdateHandle_t handle, string pchMetaData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchMetaData2 = new InteropHelp.UTF8StringHandle(pchMetaData)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemMetadata(CSteamAPIContext.GetSteamUGC(), handle, pchMetaData2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the visibility of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemVisibility(UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetItemVisibility(CSteamAPIContext.GetSteamUGC(), handle, eVisibility);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> change the tags of an UGC item</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemTags(UGCUpdateHandle_t updateHandle, System.Collections.Generic.IList<string> pTags) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetItemTags(CSteamAPIContext.GetSteamUGC(), updateHandle, new InteropHelp.SteamParamStringArray(pTags));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> update item content from this local folder</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemContent(UGCUpdateHandle_t handle, string pszContentFolder) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszContentFolder2 = new InteropHelp.UTF8StringHandle(pszContentFolder)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemContent(CSteamAPIContext.GetSteamUGC(), handle, pszContentFolder2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool SetItemPreview(UGCUpdateHandle_t handle, string pszPreviewFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_SetItemPreview(CSteamAPIContext.GetSteamUGC(), handle, pszPreviewFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  use legacy upload for a single small file. The parameter to SetItemContent() should either be a directory with one file or the full path to the file.  The file must also be less than 10MB in size.</para>\n\t\t/// </summary>\n\t\tpublic static bool SetAllowLegacyUpload(UGCUpdateHandle_t handle, bool bAllowLegacyUpload) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_SetAllowLegacyUpload(CSteamAPIContext.GetSteamUGC(), handle, bAllowLegacyUpload);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove all existing key-value tags (you can add new ones via the AddItemKeyValueTag function)</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveAllItemKeyValueTags(UGCUpdateHandle_t handle) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_RemoveAllItemKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove any existing key-value tags with the specified key</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveItemKeyValueTags(UGCUpdateHandle_t handle, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_RemoveItemKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, pchKey2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> add new key-value tags for the item. Note that there can be multiple values for a tag.</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemKeyValueTag(UGCUpdateHandle_t handle, string pchKey, string pchValue) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey))\n\t\t\tusing (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, pchKey2, pchValue2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemPreviewFile(UGCUpdateHandle_t handle, string pszPreviewFile, EItemPreviewType type) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemPreviewFile(CSteamAPIContext.GetSteamUGC(), handle, pszPreviewFile2, type);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  add preview video for this item</para>\n\t\t/// </summary>\n\t\tpublic static bool AddItemPreviewVideo(UGCUpdateHandle_t handle, string pszVideoID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_AddItemPreviewVideo(CSteamAPIContext.GetSteamUGC(), handle, pszVideoID2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdateItemPreviewFile(UGCUpdateHandle_t handle, uint index, string pszPreviewFile) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_UpdateItemPreviewFile(CSteamAPIContext.GetSteamUGC(), handle, index, pszPreviewFile2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para>  updates an existing preview video for this item</para>\n\t\t/// </summary>\n\t\tpublic static bool UpdateItemPreviewVideo(UGCUpdateHandle_t handle, uint index, string pszVideoID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_UpdateItemPreviewVideo(CSteamAPIContext.GetSteamUGC(), handle, index, pszVideoID2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> remove a preview by index starting at 0 (previews are sorted)</para>\n\t\t/// </summary>\n\t\tpublic static bool RemoveItemPreview(UGCUpdateHandle_t handle, uint index) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_RemoveItemPreview(CSteamAPIContext.GetSteamUGC(), handle, index);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> commit update process started with StartItemUpdate()</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SubmitItemUpdate(UGCUpdateHandle_t handle, string pchChangeNote) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchChangeNote2 = new InteropHelp.UTF8StringHandle(pchChangeNote)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SubmitItemUpdate(CSteamAPIContext.GetSteamUGC(), handle, pchChangeNote2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static EItemUpdateStatus GetItemUpdateProgress(UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemUpdateProgress(CSteamAPIContext.GetSteamUGC(), handle, out punBytesProcessed, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam Workshop Consumer API</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SetUserItemVote(PublishedFileId_t nPublishedFileID, bool bVoteUp) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SetUserItemVote(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, bVoteUp);\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetUserItemVote(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_GetUserItemVote(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t AddItemToFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddItemToFavorites(CSteamAPIContext.GetSteamUGC(), nAppId, nPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveItemFromFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveItemFromFavorites(CSteamAPIContext.GetSteamUGC(), nAppId, nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> subscribe to this item, will be installed ASAP</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t SubscribeItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_SubscribeItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> unsubscribe from this item, will be uninstalled after game quits</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t UnsubscribeItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_UnsubscribeItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> number of subscribed items</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumSubscribedItems() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetNumSubscribedItems(CSteamAPIContext.GetSteamUGC());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> all subscribed item PublishFileIDs</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSubscribedItems(PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetSubscribedItems(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, cMaxEntries);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get EItemState flags about item on this client</para>\n\t\t/// </summary>\n\t\tpublic static uint GetItemState(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemState(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get info about currently installed content on disc for items that have k_EItemStateInstalled set</para>\n\t\t/// <para> if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemInstallInfo(PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, out string pchFolder, uint cchFolderSize, out uint punTimeStamp) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderSize);\n\t\t\tbool ret = NativeMethods.ISteamUGC_GetItemInstallInfo(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, out punSizeOnDisk, pchFolder2, cchFolderSize, out punTimeStamp);\n\t\t\tpchFolder = ret ? InteropHelp.PtrToStringUTF8(pchFolder2) : null;\n\t\t\tMarshal.FreeHGlobal(pchFolder2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once</para>\n\t\t/// </summary>\n\t\tpublic static bool GetItemDownloadInfo(PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_GetItemDownloadInfo(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, out punBytesDownloaded, out punBytesTotal);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed,</para>\n\t\t/// <para> then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time.</para>\n\t\t/// <para> If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP.</para>\n\t\t/// </summary>\n\t\tpublic static bool DownloadItem(PublishedFileId_t nPublishedFileID, bool bHighPriority) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUGC_DownloadItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, bHighPriority);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> game servers can set a specific workshop folder before issuing any UGC commands.</para>\n\t\t/// <para> This is helpful if you want to support multiple game servers running out of the same install folder</para>\n\t\t/// </summary>\n\t\tpublic static bool BInitWorkshopForGameServer(DepotId_t unWorkshopDepotID, string pszFolder) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pszFolder2 = new InteropHelp.UTF8StringHandle(pszFolder)) {\n\t\t\t\treturn NativeMethods.ISteamUGC_BInitWorkshopForGameServer(CSteamAPIContext.GetSteamUGC(), unWorkshopDepotID, pszFolder2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> SuspendDownloads( true ) will suspend all workshop downloads until SuspendDownloads( false ) is called or the game ends</para>\n\t\t/// </summary>\n\t\tpublic static void SuspendDownloads(bool bSuspend) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUGC_SuspendDownloads(CSteamAPIContext.GetSteamUGC(), bSuspend);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> usage tracking</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t StartPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StartPlaytimeTracking(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\tpublic static SteamAPICall_t StopPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTracking(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs);\n\t\t}\n\n\t\tpublic static SteamAPICall_t StopPlaytimeTrackingForAllItems() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTrackingForAllItems(CSteamAPIContext.GetSteamUGC());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> parent-child relationship or dependency management</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AddDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddDependency(CSteamAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveDependency(CSteamAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> add/remove app dependence/requirements (usually DLC)</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AddAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_AddAppDependency(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, nAppID);\n\t\t}\n\n\t\tpublic static SteamAPICall_t RemoveAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveAppDependency(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, nAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times</para>\n\t\t/// <para> until all app dependencies have been returned</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetAppDependencies(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_GetAppDependencies(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> delete the item without prompting the user</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t DeleteItem(PublishedFileId_t nPublishedFileID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUGC_DeleteItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamunifiedmessages.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\n#endif // !DISABLESTEAMWORKS\n\n// This file is no longer needed. Valve has removed the functionality.\n// We continue to generate this file to provide a small amount of backwards compatability.\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamuser.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamUser {\n\t\t/// <summary>\n\t\t/// <para> returns the HSteamUser this interface represents</para>\n\t\t/// <para> this is only used internally by the API, and by a few select interfaces that support multi-user</para>\n\t\t/// </summary>\n\t\tpublic static HSteamUser GetHSteamUser() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HSteamUser)NativeMethods.ISteamUser_GetHSteamUser(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the Steam client current has a live connection to the Steam servers.</para>\n\t\t/// <para> If false, it means there is no active connection due to either a networking issue on the local machine, or the Steam server is down/busy.</para>\n\t\t/// <para> The Steam client will automatically be trying to recreate the connection as often as possible.</para>\n\t\t/// </summary>\n\t\tpublic static bool BLoggedOn() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BLoggedOn(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the CSteamID of the account currently logged into the Steam client</para>\n\t\t/// <para> a CSteamID is a unique identifier for an account, and used to differentiate users in all parts of the Steamworks API</para>\n\t\t/// </summary>\n\t\tpublic static CSteamID GetSteamID() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (CSteamID)NativeMethods.ISteamUser_GetSteamID(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Multiplayer Authentication functions</para>\n\t\t/// <para> InitiateGameConnection() starts the state machine for authenticating the game client with the game server</para>\n\t\t/// <para> It is the client portion of a three-way handshake between the client, the game server, and the steam servers</para>\n\t\t/// <para> Parameters:</para>\n\t\t/// <para> void *pAuthBlob - a pointer to empty memory that will be filled in with the authentication token.</para>\n\t\t/// <para> int cbMaxAuthBlob - the number of bytes of allocated memory in pBlob. Should be at least 2048 bytes.</para>\n\t\t/// <para> CSteamID steamIDGameServer - the steamID of the game server, received from the game server by the client</para>\n\t\t/// <para> CGameID gameID - the ID of the current game. For games without mods, this is just CGameID( &lt;appID&gt; )</para>\n\t\t/// <para> uint32 unIPServer, uint16 usPortServer - the IP address of the game server</para>\n\t\t/// <para> bool bSecure - whether or not the client thinks that the game server is reporting itself as secure (i.e. VAC is running)</para>\n\t\t/// <para> return value - returns the number of bytes written to pBlob. If the return is 0, then the buffer passed in was too small, and the call has failed</para>\n\t\t/// <para> The contents of pBlob should then be sent to the game server, for it to use to complete the authentication process.</para>\n\t\t/// </summary>\n\t\tpublic static int InitiateGameConnection(byte[] pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer, bool bSecure) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_InitiateGameConnection(CSteamAPIContext.GetSteamUser(), pAuthBlob, cbMaxAuthBlob, steamIDGameServer, unIPServer, usPortServer, bSecure);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> notify of disconnect</para>\n\t\t/// <para> needs to occur when the game client leaves the specified game server, needs to match with the InitiateGameConnection() call</para>\n\t\t/// </summary>\n\t\tpublic static void TerminateGameConnection(uint unIPServer, ushort usPortServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_TerminateGameConnection(CSteamAPIContext.GetSteamUser(), unIPServer, usPortServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Legacy functions</para>\n\t\t/// <para> used by only a few games to track usage events</para>\n\t\t/// </summary>\n\t\tpublic static void TrackAppUsageEvent(CGameID gameID, int eAppUsageEvent, string pchExtraInfo = \"\") {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchExtraInfo2 = new InteropHelp.UTF8StringHandle(pchExtraInfo)) {\n\t\t\t\tNativeMethods.ISteamUser_TrackAppUsageEvent(CSteamAPIContext.GetSteamUser(), gameID, eAppUsageEvent, pchExtraInfo2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> get the local storage folder for current Steam account to write application data, e.g. save games, configs etc.</para>\n\t\t/// <para> this will usually be something like \"C:\\Progam Files\\Steam\\userdata\\&lt;SteamID&gt;\\&lt;AppID&gt;\\local\"</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUserDataFolder(out string pchBuffer, int cubBuffer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchBuffer2 = Marshal.AllocHGlobal(cubBuffer);\n\t\t\tbool ret = NativeMethods.ISteamUser_GetUserDataFolder(CSteamAPIContext.GetSteamUser(), pchBuffer2, cubBuffer);\n\t\t\tpchBuffer = ret ? InteropHelp.PtrToStringUTF8(pchBuffer2) : null;\n\t\t\tMarshal.FreeHGlobal(pchBuffer2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Starts voice recording. Once started, use GetVoice() to get the data</para>\n\t\t/// </summary>\n\t\tpublic static void StartVoiceRecording() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_StartVoiceRecording(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Stops voice recording. Because people often release push-to-talk keys early, the system will keep recording for</para>\n\t\t/// <para> a little bit after this function is called. GetVoice() should continue to be called until it returns</para>\n\t\t/// <para> k_eVoiceResultNotRecording</para>\n\t\t/// </summary>\n\t\tpublic static void StopVoiceRecording() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_StopVoiceRecording(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Determine the size of captured audio data that is available from GetVoice.</para>\n\t\t/// <para> Most applications will only use compressed data and should ignore the other</para>\n\t\t/// <para> parameters, which exist primarily for backwards compatibility. See comments</para>\n\t\t/// <para> below for further explanation of \"uncompressed\" data.</para>\n\t\t/// </summary>\n\t\tpublic static EVoiceResult GetAvailableVoice(out uint pcbCompressed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetAvailableVoice(CSteamAPIContext.GetSteamUser(), out pcbCompressed, IntPtr.Zero, 0);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ---------------------------------------------------------------------------</para>\n\t\t/// <para> NOTE: \"uncompressed\" audio is a deprecated feature and should not be used</para>\n\t\t/// <para> by most applications. It is raw single-channel 16-bit PCM wave data which</para>\n\t\t/// <para> may have been run through preprocessing filters and/or had silence removed,</para>\n\t\t/// <para> so the uncompressed audio could have a shorter duration than you expect.</para>\n\t\t/// <para> There may be no data at all during long periods of silence. Also, fetching</para>\n\t\t/// <para> uncompressed audio will cause GetVoice to discard any leftover compressed</para>\n\t\t/// <para> audio, so you must fetch both types at once. Finally, GetAvailableVoice is</para>\n\t\t/// <para> not precisely accurate when the uncompressed size is requested. So if you</para>\n\t\t/// <para> really need to use uncompressed audio, you should call GetVoice frequently</para>\n\t\t/// <para> with two very large (20kb+) output buffers instead of trying to allocate</para>\n\t\t/// <para> perfectly-sized buffers. But most applications should ignore all of these</para>\n\t\t/// <para> details and simply leave the \"uncompressed\" parameters as NULL/zero.</para>\n\t\t/// <para> ---------------------------------------------------------------------------</para>\n\t\t/// <para> Read captured audio data from the microphone buffer. This should be called</para>\n\t\t/// <para> at least once per frame, and preferably every few milliseconds, to keep the</para>\n\t\t/// <para> microphone input delay as low as possible. Most applications will only use</para>\n\t\t/// <para> compressed data and should pass NULL/zero for the \"uncompressed\" parameters.</para>\n\t\t/// <para> Compressed data can be transmitted by your application and decoded into raw</para>\n\t\t/// <para> using the DecompressVoice function below.</para>\n\t\t/// </summary>\n\t\tpublic static EVoiceResult GetVoice(bool bWantCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetVoice(CSteamAPIContext.GetSteamUser(), bWantCompressed, pDestBuffer, cbDestBufferSize, out nBytesWritten, false, IntPtr.Zero, 0, IntPtr.Zero, 0);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Decodes the compressed voice data returned by GetVoice. The output data is</para>\n\t\t/// <para> raw single-channel 16-bit PCM audio. The decoder supports any sample rate</para>\n\t\t/// <para> from 11025 to 48000; see GetVoiceOptimalSampleRate() below for details.</para>\n\t\t/// <para> If the output buffer is not large enough, then *nBytesWritten will be set</para>\n\t\t/// <para> to the required buffer size, and k_EVoiceResultBufferTooSmall is returned.</para>\n\t\t/// <para> It is suggested to start with a 20kb buffer and reallocate as necessary.</para>\n\t\t/// </summary>\n\t\tpublic static EVoiceResult DecompressVoice(byte[] pCompressed, uint cbCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, uint nDesiredSampleRate) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_DecompressVoice(CSteamAPIContext.GetSteamUser(), pCompressed, cbCompressed, pDestBuffer, cbDestBufferSize, out nBytesWritten, nDesiredSampleRate);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> This returns the native sample rate of the Steam voice decompressor; using</para>\n\t\t/// <para> this sample rate for DecompressVoice will perform the least CPU processing.</para>\n\t\t/// <para> However, the final audio quality will depend on how well the audio device</para>\n\t\t/// <para> (and/or your application's audio output SDK) deals with lower sample rates.</para>\n\t\t/// <para> You may find that you get the best audio output quality when you ignore</para>\n\t\t/// <para> this function and use the native sample rate of your audio output device,</para>\n\t\t/// <para> which is usually 48000 or 44100.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetVoiceOptimalSampleRate() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetVoiceOptimalSampleRate(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieve ticket to be sent to the entity who wishes to authenticate you.</para>\n\t\t/// <para> pcbTicket retrieves the length of the actual ticket.</para>\n\t\t/// </summary>\n\t\tpublic static HAuthTicket GetAuthSessionTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (HAuthTicket)NativeMethods.ISteamUser_GetAuthSessionTicket(CSteamAPIContext.GetSteamUser(), pTicket, cbMaxTicket, out pcbTicket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Authenticate ticket from entity steamID to be sure it is valid and isnt reused</para>\n\t\t/// <para> Registers for callbacks if the entity goes offline or cancels the ticket ( see ValidateAuthTicketResponse_t callback and EAuthSessionResponse )</para>\n\t\t/// </summary>\n\t\tpublic static EBeginAuthSessionResult BeginAuthSession(byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BeginAuthSession(CSteamAPIContext.GetSteamUser(), pAuthTicket, cbAuthTicket, steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Stop tracking started by BeginAuthSession - called when no longer playing game with this entity</para>\n\t\t/// </summary>\n\t\tpublic static void EndAuthSession(CSteamID steamID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_EndAuthSession(CSteamAPIContext.GetSteamUser(), steamID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Cancel auth ticket from GetAuthSessionTicket, called when no longer playing game with the entity you gave the ticket to</para>\n\t\t/// </summary>\n\t\tpublic static void CancelAuthTicket(HAuthTicket hAuthTicket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_CancelAuthTicket(CSteamAPIContext.GetSteamUser(), hAuthTicket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> After receiving a user's authentication data, and passing it to BeginAuthSession, use this function</para>\n\t\t/// <para> to determine if the user owns downloadable content specified by the provided AppID.</para>\n\t\t/// </summary>\n\t\tpublic static EUserHasLicenseForAppResult UserHasLicenseForApp(CSteamID steamID, AppId_t appID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_UserHasLicenseForApp(CSteamAPIContext.GetSteamUser(), steamID, appID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if this users looks like they are behind a NAT device. Only valid once the user has connected to steam</para>\n\t\t/// <para> (i.e a SteamServersConnected_t has been issued) and may not catch all forms of NAT.</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsBehindNAT() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BIsBehindNAT(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> set data to be replicated to friends so that they can join your game</para>\n\t\t/// <para> CSteamID steamIDGameServer - the steamID of the game server, received from the game server by the client</para>\n\t\t/// <para> uint32 unIPServer, uint16 usPortServer - the IP address of the game server</para>\n\t\t/// </summary>\n\t\tpublic static void AdvertiseGame(CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUser_AdvertiseGame(CSteamAPIContext.GetSteamUser(), steamIDGameServer, unIPServer, usPortServer);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Requests a ticket encrypted with an app specific shared key</para>\n\t\t/// <para> pDataToInclude, cbDataToInclude will be encrypted into the ticket</para>\n\t\t/// <para> ( This is asynchronous, you must wait for the ticket to be completed by the server )</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestEncryptedAppTicket(byte[] pDataToInclude, int cbDataToInclude) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUser_RequestEncryptedAppTicket(CSteamAPIContext.GetSteamUser(), pDataToInclude, cbDataToInclude);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> retrieve a finished ticket</para>\n\t\t/// </summary>\n\t\tpublic static bool GetEncryptedAppTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetEncryptedAppTicket(CSteamAPIContext.GetSteamUser(), pTicket, cbMaxTicket, out pcbTicket);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Trading Card badges data access</para>\n\t\t/// <para> if you only have one set of cards, the series will be 1</para>\n\t\t/// <para> the user has can have two different badges for a series; the regular (max level 5) and the foil (max level 1)</para>\n\t\t/// </summary>\n\t\tpublic static int GetGameBadgeLevel(int nSeries, bool bFoil) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetGameBadgeLevel(CSteamAPIContext.GetSteamUser(), nSeries, bFoil);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets the Steam Level of the user, as shown on their profile</para>\n\t\t/// </summary>\n\t\tpublic static int GetPlayerSteamLevel() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_GetPlayerSteamLevel(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Requests a URL which authenticates an in-game browser for store check-out,</para>\n\t\t/// <para> and then redirects to the specified URL. As long as the in-game browser</para>\n\t\t/// <para> accepts and handles session cookies, Steam microtransaction checkout pages</para>\n\t\t/// <para> will automatically recognize the user instead of presenting a login page.</para>\n\t\t/// <para> The result of this API call will be a StoreAuthURLResponse_t callback.</para>\n\t\t/// <para> NOTE: The URL has a very short lifetime to prevent history-snooping attacks,</para>\n\t\t/// <para> so you should only call this API when you are about to launch the browser,</para>\n\t\t/// <para> or else immediately navigate to the result URL using a hidden browser window.</para>\n\t\t/// <para> NOTE 2: The resulting authorization cookie has an expiration time of one day,</para>\n\t\t/// <para> so it would be a good idea to request and visit a new auth URL every 12 hours.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestStoreAuthURL(string pchRedirectURL) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchRedirectURL2 = new InteropHelp.UTF8StringHandle(pchRedirectURL)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUser_RequestStoreAuthURL(CSteamAPIContext.GetSteamUser(), pchRedirectURL2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets whether the users phone number is verified</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsPhoneVerified() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BIsPhoneVerified(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets whether the user has two factor enabled on their account</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsTwoFactorEnabled() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BIsTwoFactorEnabled(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets whether the users phone number is identifying</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsPhoneIdentifying() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BIsPhoneIdentifying(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> gets whether the users phone number is awaiting (re)verification</para>\n\t\t/// </summary>\n\t\tpublic static bool BIsPhoneRequiringVerification() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUser_BIsPhoneRequiringVerification(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\tpublic static SteamAPICall_t GetMarketEligibility() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUser_GetMarketEligibility(CSteamAPIContext.GetSteamUser());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieves anti indulgence / duration control for current user</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetDurationControl() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUser_GetDurationControl(CSteamAPIContext.GetSteamUser());\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamuserstats.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamUserStats {\n\t\t/// <summary>\n\t\t/// <para> Ask the server to send down this user's data and achievements for this game</para>\n\t\t/// </summary>\n\t\tpublic static bool RequestCurrentStats() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_RequestCurrentStats(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Data accessors</para>\n\t\t/// </summary>\n\t\tpublic static bool GetStat(string pchName, out int pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetStat(CSteamAPIContext.GetSteamUserStats(), pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetStat(string pchName, out float pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetStat0(CSteamAPIContext.GetSteamUserStats(), pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set / update data</para>\n\t\t/// </summary>\n\t\tpublic static bool SetStat(string pchName, int nData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_SetStat(CSteamAPIContext.GetSteamUserStats(), pchName2, nData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetStat(string pchName, float fData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_SetStat0(CSteamAPIContext.GetSteamUserStats(), pchName2, fData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool UpdateAvgRateStat(string pchName, float flCountThisSession, double dSessionLength) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_UpdateAvgRateStat(CSteamAPIContext.GetSteamUserStats(), pchName2, flCountThisSession, dSessionLength);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Achievement flag accessors</para>\n\t\t/// </summary>\n\t\tpublic static bool GetAchievement(string pchName, out bool pbAchieved) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2, out pbAchieved);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool SetAchievement(string pchName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_SetAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool ClearAchievement(string pchName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_ClearAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the achievement status, and the time it was unlocked if unlocked.</para>\n\t\t/// <para> If the return value is true, but the unlock time is zero, that means it was unlocked before Steam</para>\n\t\t/// <para> began tracking achievement unlock times (December 2009). Time is seconds since January 1, 1970.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetAchievementAndUnlockTime(string pchName, out bool pbAchieved, out uint punUnlockTime) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetAchievementAndUnlockTime(CSteamAPIContext.GetSteamUserStats(), pchName2, out pbAchieved, out punUnlockTime);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Store the current data on the server, will get a callback when set</para>\n\t\t/// <para> And one callback for every new achievement</para>\n\t\t/// <para> If the callback has a result of k_EResultInvalidParam, one or more stats</para>\n\t\t/// <para> uploaded has been rejected, either because they broke constraints</para>\n\t\t/// <para> or were out of date. In this case the server sends back updated values.</para>\n\t\t/// <para> The stats should be re-iterated to keep in sync.</para>\n\t\t/// </summary>\n\t\tpublic static bool StoreStats() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_StoreStats(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Achievement / GroupAchievement metadata</para>\n\t\t/// <para> Gets the icon of the achievement, which is a handle to be used in ISteamUtils::GetImageRGBA(), or 0 if none set.</para>\n\t\t/// <para> A return value of 0 may indicate we are still fetching data, and you can wait for the UserAchievementIconFetched_t callback</para>\n\t\t/// <para> which will notify you when the bits are ready. If the callback still returns zero, then there is no image set for the</para>\n\t\t/// <para> specified achievement.</para>\n\t\t/// </summary>\n\t\tpublic static int GetAchievementIcon(string pchName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetAchievementIcon(CSteamAPIContext.GetSteamUserStats(), pchName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get general attributes for an achievement. Accepts the following keys:</para>\n\t\t/// <para> - \"name\" and \"desc\" for retrieving the localized achievement name and description (returned in UTF8)</para>\n\t\t/// <para> - \"hidden\" for retrieving if an achievement is hidden (returns \"0\" when not hidden, \"1\" when hidden)</para>\n\t\t/// </summary>\n\t\tpublic static string GetAchievementDisplayAttribute(string pchName, string pchKey) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName))\n\t\t\tusing (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) {\n\t\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetAchievementDisplayAttribute(CSteamAPIContext.GetSteamUserStats(), pchName2, pchKey2));\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Achievement progress - triggers an AchievementProgress callback, that is all.</para>\n\t\t/// <para> Calling this w/ N out of N progress will NOT set the achievement, the game must still do that.</para>\n\t\t/// </summary>\n\t\tpublic static bool IndicateAchievementProgress(string pchName, uint nCurProgress, uint nMaxProgress) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_IndicateAchievementProgress(CSteamAPIContext.GetSteamUserStats(), pchName2, nCurProgress, nMaxProgress);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Used for iterating achievements. In general games should not need these functions because they should have a</para>\n\t\t/// <para> list of existing achievements compiled into them</para>\n\t\t/// </summary>\n\t\tpublic static uint GetNumAchievements() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetNumAchievements(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get achievement name iAchievement in [0,GetNumAchievements)</para>\n\t\t/// </summary>\n\t\tpublic static string GetAchievementName(uint iAchievement) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetAchievementName(CSteamAPIContext.GetSteamUserStats(), iAchievement));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Friends stats &amp; achievements</para>\n\t\t/// <para> downloads stats for the user</para>\n\t\t/// <para> returns a UserStatsReceived_t received when completed</para>\n\t\t/// <para> if the other user has no stats, UserStatsReceived_t.m_eResult will be set to k_EResultFail</para>\n\t\t/// <para> these stats won't be auto-updated; you'll need to call RequestUserStats() again to refresh any data</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestUserStats(CSteamID steamIDUser) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestUserStats(CSteamAPIContext.GetSteamUserStats(), steamIDUser);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> requests stat information for a user, usable after a successful call to RequestUserStats()</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUserStat(CSteamID steamIDUser, string pchName, out int pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetUserStat(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetUserStat(CSteamID steamIDUser, string pchName, out float pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetUserStat0(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetUserAchievement(CSteamID steamIDUser, string pchName, out bool pbAchieved) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetUserAchievement(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pbAchieved);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> See notes for GetAchievementAndUnlockTime above</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUserAchievementAndUnlockTime(CSteamID steamIDUser, string pchName, out bool pbAchieved, out uint punUnlockTime) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetUserAchievementAndUnlockTime(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pbAchieved, out punUnlockTime);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Reset stats</para>\n\t\t/// </summary>\n\t\tpublic static bool ResetAllStats(bool bAchievementsToo) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_ResetAllStats(CSteamAPIContext.GetSteamUserStats(), bAchievementsToo);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Leaderboard functions</para>\n\t\t/// <para> asks the Steam back-end for a leaderboard by name, and will create it if it's not yet</para>\n\t\t/// <para> This call is asynchronous, with the result returned in LeaderboardFindResult_t</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t FindOrCreateLeaderboard(string pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLeaderboardName2 = new InteropHelp.UTF8StringHandle(pchLeaderboardName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_FindOrCreateLeaderboard(CSteamAPIContext.GetSteamUserStats(), pchLeaderboardName2, eLeaderboardSortMethod, eLeaderboardDisplayType);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> as above, but won't create the leaderboard if it's not found</para>\n\t\t/// <para> This call is asynchronous, with the result returned in LeaderboardFindResult_t</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t FindLeaderboard(string pchLeaderboardName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchLeaderboardName2 = new InteropHelp.UTF8StringHandle(pchLeaderboardName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_FindLeaderboard(CSteamAPIContext.GetSteamUserStats(), pchLeaderboardName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the name of a leaderboard</para>\n\t\t/// </summary>\n\t\tpublic static string GetLeaderboardName(SteamLeaderboard_t hSteamLeaderboard) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetLeaderboardName(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the total number of entries in a leaderboard, as of the last request</para>\n\t\t/// </summary>\n\t\tpublic static int GetLeaderboardEntryCount(SteamLeaderboard_t hSteamLeaderboard) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetLeaderboardEntryCount(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the sort method of the leaderboard</para>\n\t\t/// </summary>\n\t\tpublic static ELeaderboardSortMethod GetLeaderboardSortMethod(SteamLeaderboard_t hSteamLeaderboard) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetLeaderboardSortMethod(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the display type of the leaderboard</para>\n\t\t/// </summary>\n\t\tpublic static ELeaderboardDisplayType GetLeaderboardDisplayType(SteamLeaderboard_t hSteamLeaderboard) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetLeaderboardDisplayType(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Asks the Steam back-end for a set of rows in the leaderboard.</para>\n\t\t/// <para> This call is asynchronous, with the result returned in LeaderboardScoresDownloaded_t</para>\n\t\t/// <para> LeaderboardScoresDownloaded_t will contain a handle to pull the results from GetDownloadedLeaderboardEntries() (below)</para>\n\t\t/// <para> You can ask for more entries than exist, and it will return as many as do exist.</para>\n\t\t/// <para> k_ELeaderboardDataRequestGlobal requests rows in the leaderboard from the full table, with nRangeStart &amp; nRangeEnd in the range [1, TotalEntries]</para>\n\t\t/// <para> k_ELeaderboardDataRequestGlobalAroundUser requests rows around the current user, nRangeStart being negate</para>\n\t\t/// <para>   e.g. DownloadLeaderboardEntries( hLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -3, 3 ) will return 7 rows, 3 before the user, 3 after</para>\n\t\t/// <para> k_ELeaderboardDataRequestFriends requests all the rows for friends of the current user</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t DownloadLeaderboardEntries(SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_DownloadLeaderboardEntries(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, eLeaderboardDataRequest, nRangeStart, nRangeEnd);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers</para>\n\t\t/// <para> if a user doesn't have a leaderboard entry, they won't be included in the result</para>\n\t\t/// <para> a max of 100 users can be downloaded at a time, with only one outstanding call at a time</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t DownloadLeaderboardEntriesForUsers(SteamLeaderboard_t hSteamLeaderboard, CSteamID[] prgUsers, int cUsers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_DownloadLeaderboardEntriesForUsers(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, prgUsers, cUsers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns data about a single leaderboard entry</para>\n\t\t/// <para> use a for loop from 0 to LeaderboardScoresDownloaded_t::m_cEntryCount to get all the downloaded entries</para>\n\t\t/// <para> e.g.</para>\n\t\t/// <para>\t\tvoid OnLeaderboardScoresDownloaded( LeaderboardScoresDownloaded_t *pLeaderboardScoresDownloaded )</para>\n\t\t/// <para>\t\t{</para>\n\t\t/// <para>\t\t\tfor ( int index = 0; index &lt; pLeaderboardScoresDownloaded-&gt;m_cEntryCount; index++ )</para>\n\t\t/// <para>\t\t\t{</para>\n\t\t/// <para>\t\t\t\tLeaderboardEntry_t leaderboardEntry;</para>\n\t\t/// <para>\t\t\t\tint32 details[3];\t\t// we know this is how many we've stored previously</para>\n\t\t/// <para>\t\t\t\tGetDownloadedLeaderboardEntry( pLeaderboardScoresDownloaded-&gt;m_hSteamLeaderboardEntries, index, &amp;leaderboardEntry, details, 3 );</para>\n\t\t/// <para>\t\t\t\tassert( leaderboardEntry.m_cDetails == 3 );</para>\n\t\t/// <para>\t\t\t\t...</para>\n\t\t/// <para>\t\t\t}</para>\n\t\t/// <para> once you've accessed all the entries, the data will be free'd, and the SteamLeaderboardEntries_t handle will become invalid</para>\n\t\t/// </summary>\n\t\tpublic static bool GetDownloadedLeaderboardEntry(SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, out LeaderboardEntry_t pLeaderboardEntry, int[] pDetails, int cDetailsMax) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetDownloadedLeaderboardEntry(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboardEntries, index, out pLeaderboardEntry, pDetails, cDetailsMax);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Uploads a user score to the Steam back-end.</para>\n\t\t/// <para> This call is asynchronous, with the result returned in LeaderboardScoreUploaded_t</para>\n\t\t/// <para> Details are extra game-defined information regarding how the user got that score</para>\n\t\t/// <para> pScoreDetails points to an array of int32's, cScoreDetailsCount is the number of int32's in the list</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t UploadLeaderboardScore(SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, int nScore, int[] pScoreDetails, int cScoreDetailsCount) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_UploadLeaderboardScore(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, eLeaderboardUploadScoreMethod, nScore, pScoreDetails, cScoreDetailsCount);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Attaches a piece of user generated content the user's entry on a leaderboard.</para>\n\t\t/// <para> hContent is a handle to a piece of user generated content that was shared using ISteamUserRemoteStorage::FileShare().</para>\n\t\t/// <para> This call is asynchronous, with the result returned in LeaderboardUGCSet_t.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t AttachLeaderboardUGC(SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_AttachLeaderboardUGC(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, hUGC);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Retrieves the number of players currently playing your game (online + offline)</para>\n\t\t/// <para> This call is asynchronous, with the result returned in NumberOfCurrentPlayers_t</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t GetNumberOfCurrentPlayers() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_GetNumberOfCurrentPlayers(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Requests that Steam fetch data on the percentage of players who have received each achievement</para>\n\t\t/// <para> for the game globally.</para>\n\t\t/// <para> This call is asynchronous, with the result returned in GlobalAchievementPercentagesReady_t.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestGlobalAchievementPercentages() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestGlobalAchievementPercentages(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the info on the most achieved achievement for the game, returns an iterator index you can use to fetch</para>\n\t\t/// <para> the next most achieved afterwards.  Will return -1 if there is no data on achievement</para>\n\t\t/// <para> percentages (ie, you haven't called RequestGlobalAchievementPercentages and waited on the callback).</para>\n\t\t/// </summary>\n\t\tpublic static int GetMostAchievedAchievementInfo(out string pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal((int)unNameBufLen);\n\t\t\tint ret = NativeMethods.ISteamUserStats_GetMostAchievedAchievementInfo(CSteamAPIContext.GetSteamUserStats(), pchName2, unNameBufLen, out pflPercent, out pbAchieved);\n\t\t\tpchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the info on the next most achieved achievement for the game. Call this after GetMostAchievedAchievementInfo or another</para>\n\t\t/// <para> GetNextMostAchievedAchievementInfo call passing the iterator from the previous call. Returns -1 after the last</para>\n\t\t/// <para> achievement has been iterated.</para>\n\t\t/// </summary>\n\t\tpublic static int GetNextMostAchievedAchievementInfo(int iIteratorPrevious, out string pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchName2 = Marshal.AllocHGlobal((int)unNameBufLen);\n\t\t\tint ret = NativeMethods.ISteamUserStats_GetNextMostAchievedAchievementInfo(CSteamAPIContext.GetSteamUserStats(), iIteratorPrevious, pchName2, unNameBufLen, out pflPercent, out pbAchieved);\n\t\t\tpchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null;\n\t\t\tMarshal.FreeHGlobal(pchName2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the percentage of users who have achieved the specified achievement.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetAchievementAchievedPercent(string pchName, out float pflPercent) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetAchievementAchievedPercent(CSteamAPIContext.GetSteamUserStats(), pchName2, out pflPercent);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Requests global stats data, which is available for stats marked as \"aggregated\".</para>\n\t\t/// <para> This call is asynchronous, with the results returned in GlobalStatsReceived_t.</para>\n\t\t/// <para> nHistoryDays specifies how many days of day-by-day history to retrieve in addition</para>\n\t\t/// <para> to the overall totals. The limit is 60.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t RequestGlobalStats(int nHistoryDays) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestGlobalStats(CSteamAPIContext.GetSteamUserStats(), nHistoryDays);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets the lifetime totals for an aggregated stat</para>\n\t\t/// </summary>\n\t\tpublic static bool GetGlobalStat(string pchStatName, out long pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetGlobalStat(CSteamAPIContext.GetSteamUserStats(), pchStatName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool GetGlobalStat(string pchStatName, out double pData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetGlobalStat0(CSteamAPIContext.GetSteamUserStats(), pchStatName2, out pData);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Gets history for an aggregated stat. pData will be filled with daily values, starting with today.</para>\n\t\t/// <para> So when called, pData[0] will be today, pData[1] will be yesterday, and pData[2] will be two days ago,</para>\n\t\t/// <para> etc. cubData is the size in bytes of the pubData buffer. Returns the number of</para>\n\t\t/// <para> elements actually set.</para>\n\t\t/// </summary>\n\t\tpublic static int GetGlobalStatHistory(string pchStatName, long[] pData, uint cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetGlobalStatHistory(CSteamAPIContext.GetSteamUserStats(), pchStatName2, pData, cubData);\n\t\t\t}\n\t\t}\n\n\t\tpublic static int GetGlobalStatHistory(string pchStatName, double[] pData, uint cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) {\n\t\t\t\treturn NativeMethods.ISteamUserStats_GetGlobalStatHistory0(CSteamAPIContext.GetSteamUserStats(), pchStatName2, pData, cubData);\n\t\t\t}\n\t\t}\n#if _PS3\n\t\t/// <summary>\n\t\t/// <para> Call to kick off installation of the PS3 trophies. This call is asynchronous, and the results will be returned in a PS3TrophiesInstalled_t</para>\n\t\t/// <para> callback.</para>\n\t\t/// </summary>\n\t\tpublic static bool InstallPS3Trophies() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_InstallPS3Trophies(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns the amount of space required at boot to install trophies. This value can be used when comparing the amount of space needed</para>\n\t\t/// <para> by the game to the available space value passed to the game at boot. The value is set during InstallPS3Trophies().</para>\n\t\t/// </summary>\n\t\tpublic static ulong GetTrophySpaceRequiredBeforeInstall() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetTrophySpaceRequiredBeforeInstall(CSteamAPIContext.GetSteamUserStats());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> On PS3, user stats &amp; achievement progress through Steam must be stored with the user's saved game data.</para>\n\t\t/// <para> At startup, before calling RequestCurrentStats(), you must pass the user's stats data to Steam via this method.</para>\n\t\t/// <para> If you do not have any user data, call this function with pvData = NULL and cubData = 0</para>\n\t\t/// </summary>\n\t\tpublic static bool SetUserStatsData(IntPtr pvData, uint cubData) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_SetUserStatsData(CSteamAPIContext.GetSteamUserStats(), pvData, cubData);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Call to get the user's current stats data. You should retrieve this data after receiving successful UserStatsReceived_t &amp; UserStatsStored_t</para>\n\t\t/// <para> callbacks, and store the data with the user's save game data. You can call this method with pvData = NULL and cubData = 0 to get the required</para>\n\t\t/// <para> buffer size.</para>\n\t\t/// </summary>\n\t\tpublic static bool GetUserStatsData(IntPtr pvData, uint cubData, out uint pcubWritten) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUserStats_GetUserStatsData(CSteamAPIContext.GetSteamUserStats(), pvData, cubData, out pcubWritten);\n\t\t}\n#endif\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamutils.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamUtils {\n\t\t/// <summary>\n\t\t/// <para> return the number of seconds since the user</para>\n\t\t/// </summary>\n\t\tpublic static uint GetSecondsSinceAppActive() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetSecondsSinceAppActive(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\tpublic static uint GetSecondsSinceComputerActive() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetSecondsSinceComputerActive(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> the universe this client is connecting to</para>\n\t\t/// </summary>\n\t\tpublic static EUniverse GetConnectedUniverse() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetConnectedUniverse(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Steam server time.  Number of seconds since January 1, 1970, GMT (i.e unix time)</para>\n\t\t/// </summary>\n\t\tpublic static uint GetServerRealTime() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetServerRealTime(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database)</para>\n\t\t/// <para> e.g \"US\" or \"UK\".</para>\n\t\t/// </summary>\n\t\tpublic static string GetIPCountry() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetIPCountry(CSteamAPIContext.GetSteamUtils()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the image exists, and valid sizes were filled out</para>\n\t\t/// </summary>\n\t\tpublic static bool GetImageSize(int iImage, out uint pnWidth, out uint pnHeight) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetImageSize(CSteamAPIContext.GetSteamUtils(), iImage, out pnWidth, out pnHeight);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if the image exists, and the buffer was successfully filled out</para>\n\t\t/// <para> results are returned in RGBA format</para>\n\t\t/// <para> the destination buffer size should be 4 * height * width * sizeof(char)</para>\n\t\t/// </summary>\n\t\tpublic static bool GetImageRGBA(int iImage, byte[] pubDest, int nDestBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetImageRGBA(CSteamAPIContext.GetSteamUtils(), iImage, pubDest, nDestBufferSize);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the IP of the reporting server for valve - currently only used in Source engine games</para>\n\t\t/// </summary>\n\t\tpublic static bool GetCSERIPPort(out uint unIP, out ushort usPort) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetCSERIPPort(CSteamAPIContext.GetSteamUtils(), out unIP, out usPort);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> return the amount of battery power left in the current system in % [0..100], 255 for being on AC power</para>\n\t\t/// </summary>\n\t\tpublic static byte GetCurrentBatteryPower() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetCurrentBatteryPower(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the appID of the current process</para>\n\t\t/// </summary>\n\t\tpublic static AppId_t GetAppID() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn (AppId_t)NativeMethods.ISteamUtils_GetAppID(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the position where the overlay instance for the currently calling game should show notifications.</para>\n\t\t/// <para> This position is per-game and if this function is called from outside of a game context it will do nothing.</para>\n\t\t/// </summary>\n\t\tpublic static void SetOverlayNotificationPosition(ENotificationPosition eNotificationPosition) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUtils_SetOverlayNotificationPosition(CSteamAPIContext.GetSteamUtils(), eNotificationPosition);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API asynchronous call results</para>\n\t\t/// <para> can be used directly, but more commonly used via the callback dispatch API (see steam_api.h)</para>\n\t\t/// </summary>\n\t\tpublic static bool IsAPICallCompleted(SteamAPICall_t hSteamAPICall, out bool pbFailed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsAPICallCompleted(CSteamAPIContext.GetSteamUtils(), hSteamAPICall, out pbFailed);\n\t\t}\n\n\t\tpublic static ESteamAPICallFailure GetAPICallFailureReason(SteamAPICall_t hSteamAPICall) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetAPICallFailureReason(CSteamAPIContext.GetSteamUtils(), hSteamAPICall);\n\t\t}\n\n\t\tpublic static bool GetAPICallResult(SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetAPICallResult(CSteamAPIContext.GetSteamUtils(), hSteamAPICall, pCallback, cubCallback, iCallbackExpected, out pbFailed);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the number of IPC calls made since the last time this function was called</para>\n\t\t/// <para> Used for perf debugging so you can understand how many IPC calls your game makes per frame</para>\n\t\t/// <para> Every IPC call is at minimum a thread context switch if not a process one so you want to rate</para>\n\t\t/// <para> control how often you do them.</para>\n\t\t/// </summary>\n\t\tpublic static uint GetIPCCallCount() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetIPCCallCount(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> API warning handling</para>\n\t\t/// <para> 'int' is the severity; 0 for msg, 1 for warning</para>\n\t\t/// <para> 'const char *' is the text of the message</para>\n\t\t/// <para> callbacks will occur directly after the API function is called that generated the warning or message</para>\n\t\t/// </summary>\n\t\tpublic static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUtils_SetWarningMessageHook(CSteamAPIContext.GetSteamUtils(), pFunction);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the overlay is running &amp; the user can access it. The overlay process could take a few seconds to</para>\n\t\t/// <para> start &amp; hook the game process, so this function will initially return false while the overlay is loading.</para>\n\t\t/// </summary>\n\t\tpublic static bool IsOverlayEnabled() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsOverlayEnabled(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Normally this call is unneeded if your game has a constantly running frame loop that calls the</para>\n\t\t/// <para> D3D Present API, or OGL SwapBuffers API every frame.</para>\n\t\t/// <para> However, if you have a game that only refreshes the screen on an event driven basis then that can break</para>\n\t\t/// <para> the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also</para>\n\t\t/// <para> need to Present() to the screen any time an even needing a notification happens or when the overlay is</para>\n\t\t/// <para> brought up over the game by a user.  You can use this API to ask the overlay if it currently need a present</para>\n\t\t/// <para> in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you</para>\n\t\t/// <para> refresh the screen with Present or SwapBuffers to allow the overlay to do it's work.</para>\n\t\t/// </summary>\n\t\tpublic static bool BOverlayNeedsPresent() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_BOverlayNeedsPresent(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Asynchronous call to check if an executable file has been signed using the public key set on the signing tab</para>\n\t\t/// <para> of the partner site, for example to refuse to load modified executable files.</para>\n\t\t/// <para> The result is returned in CheckFileSignature_t.</para>\n\t\t/// <para>   k_ECheckFileSignatureNoSignaturesFoundForThisApp - This app has not been configured on the signing tab of the partner site to enable this function.</para>\n\t\t/// <para>   k_ECheckFileSignatureNoSignaturesFoundForThisFile - This file is not listed on the signing tab for the partner site.</para>\n\t\t/// <para>   k_ECheckFileSignatureFileNotFound - The file does not exist on disk.</para>\n\t\t/// <para>   k_ECheckFileSignatureInvalidSignature - The file exists, and the signing tab has been set for this file, but the file is either not signed or the signature does not match.</para>\n\t\t/// <para>   k_ECheckFileSignatureValidSignature - The file is signed and the signature is valid.</para>\n\t\t/// </summary>\n\t\tpublic static SteamAPICall_t CheckFileSignature(string szFileName) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var szFileName2 = new InteropHelp.UTF8StringHandle(szFileName)) {\n\t\t\t\treturn (SteamAPICall_t)NativeMethods.ISteamUtils_CheckFileSignature(CSteamAPIContext.GetSteamUtils(), szFileName2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Activates the Big Picture text input dialog which only supports gamepad input</para>\n\t\t/// </summary>\n\t\tpublic static bool ShowGamepadTextInput(EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tusing (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription))\n\t\t\tusing (var pchExistingText2 = new InteropHelp.UTF8StringHandle(pchExistingText)) {\n\t\t\t\treturn NativeMethods.ISteamUtils_ShowGamepadTextInput(CSteamAPIContext.GetSteamUtils(), eInputMode, eLineInputMode, pchDescription2, unCharMax, pchExistingText2);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns previously entered text &amp; length</para>\n\t\t/// </summary>\n\t\tpublic static uint GetEnteredGamepadTextLength() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_GetEnteredGamepadTextLength(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\tpublic static bool GetEnteredGamepadTextInput(out string pchText, uint cchText) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchText2 = Marshal.AllocHGlobal((int)cchText);\n\t\t\tbool ret = NativeMethods.ISteamUtils_GetEnteredGamepadTextInput(CSteamAPIContext.GetSteamUtils(), pchText2, cchText);\n\t\t\tpchText = ret ? InteropHelp.PtrToStringUTF8(pchText2) : null;\n\t\t\tMarshal.FreeHGlobal(pchText2);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns the language the steam client is running in, you probably want ISteamApps::GetCurrentGameLanguage instead, this is for very special usage cases</para>\n\t\t/// </summary>\n\t\tpublic static string GetSteamUILanguage() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetSteamUILanguage(CSteamAPIContext.GetSteamUtils()));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if Steam itself is running in VR mode</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamRunningInVR() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamRunningInVR(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition.</para>\n\t\t/// </summary>\n\t\tpublic static void SetOverlayNotificationInset(int nHorizontalInset, int nVerticalInset) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUtils_SetOverlayNotificationInset(CSteamAPIContext.GetSteamUtils(), nHorizontalInset, nVerticalInset);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if Steam &amp; the Steam Overlay are running in Big Picture mode</para>\n\t\t/// <para> Games much be launched through the Steam client to enable the Big Picture overlay. During development,</para>\n\t\t/// <para> a game can be added as a non-steam game to the developers library to test this feature</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamInBigPictureMode() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamInBigPictureMode(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> ask SteamUI to create and render its OpenVR dashboard</para>\n\t\t/// </summary>\n\t\tpublic static void StartVRDashboard() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUtils_StartVRDashboard(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns true if the HMD content will be streamed via Steam In-Home Streaming</para>\n\t\t/// </summary>\n\t\tpublic static bool IsVRHeadsetStreamingEnabled() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsVRHeadsetStreamingEnabled(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Set whether the HMD content will be streamed via Steam In-Home Streaming</para>\n\t\t/// <para> If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be allowed.</para>\n\t\t/// <para> If this is set to false, then the application window will be streamed instead, and remote input will be allowed.</para>\n\t\t/// <para> The default is true unless \"VRHeadsetStreaming\" \"0\" is in the extended appinfo for a game.</para>\n\t\t/// <para> (this is useful for games that have asymmetric multiplayer gameplay)</para>\n\t\t/// </summary>\n\t\tpublic static void SetVRHeadsetStreamingEnabled(bool bEnabled) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamUtils_SetVRHeadsetStreamingEnabled(CSteamAPIContext.GetSteamUtils(), bEnabled);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Returns whether this steam client is a Steam China specific client, vs the global client.</para>\n\t\t/// </summary>\n\t\tpublic static bool IsSteamChinaLauncher() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_IsSteamChinaLauncher(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Initializes text filtering.</para>\n\t\t/// <para>   Returns false if filtering is unavailable for the language the user is currently running in.</para>\n\t\t/// </summary>\n\t\tpublic static bool InitFilterText() {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamUtils_InitFilterText(CSteamAPIContext.GetSteamUtils());\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Filters the provided input message and places the filtered result into pchOutFilteredText.</para>\n\t\t/// <para>   pchOutFilteredText is where the output will be placed, even if no filtering or censoring is performed</para>\n\t\t/// <para>   nByteSizeOutFilteredText is the size (in bytes) of pchOutFilteredText</para>\n\t\t/// <para>   pchInputText is the input string that should be filtered, which can be ASCII or UTF-8</para>\n\t\t/// <para>   bLegalOnly should be false if you want profanity and legally required filtering (where required) and true if you want legally required filtering only</para>\n\t\t/// <para>   Returns the number of characters (not bytes) filtered.</para>\n\t\t/// </summary>\n\t\tpublic static int FilterText(out string pchOutFilteredText, uint nByteSizeOutFilteredText, string pchInputMessage, bool bLegalOnly) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchOutFilteredText2 = Marshal.AllocHGlobal((int)nByteSizeOutFilteredText);\n\t\t\tusing (var pchInputMessage2 = new InteropHelp.UTF8StringHandle(pchInputMessage)) {\n\t\t\t\tint ret = NativeMethods.ISteamUtils_FilterText(CSteamAPIContext.GetSteamUtils(), pchOutFilteredText2, nByteSizeOutFilteredText, pchInputMessage2, bLegalOnly);\n\t\t\t\tpchOutFilteredText = ret != -1 ? InteropHelp.PtrToStringUTF8(pchOutFilteredText2) : null;\n\t\t\t\tMarshal.FreeHGlobal(pchOutFilteredText2);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/autogen/isteamvideo.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\tpublic static class SteamVideo {\n\t\t/// <summary>\n\t\t/// <para> Get a URL suitable for streaming the given Video app ID's video</para>\n\t\t/// </summary>\n\t\tpublic static void GetVideoURL(AppId_t unVideoAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamVideo_GetVideoURL(CSteamAPIContext.GetSteamVideo(), unVideoAppID);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> returns true if user is uploading a live broadcast</para>\n\t\t/// </summary>\n\t\tpublic static bool IsBroadcasting(out int pnNumViewers) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\treturn NativeMethods.ISteamVideo_IsBroadcasting(CSteamAPIContext.GetSteamVideo(), out pnNumViewers);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// <para> Get the OPF Details for 360 Video Playback</para>\n\t\t/// </summary>\n\t\tpublic static void GetOPFSettings(AppId_t unVideoAppID) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tNativeMethods.ISteamVideo_GetOPFSettings(CSteamAPIContext.GetSteamVideo(), unVideoAppID);\n\t\t}\n\n\t\tpublic static bool GetOPFStringForApp(AppId_t unVideoAppID, out string pchBuffer, ref int pnBufferSize) {\n\t\t\tInteropHelp.TestIfAvailableClient();\n\t\t\tIntPtr pchBuffer2 = Marshal.AllocHGlobal((int)pnBufferSize);\n\t\t\tbool ret = NativeMethods.ISteamVideo_GetOPFStringForApp(CSteamAPIContext.GetSteamVideo(), unVideoAppID, pchBuffer2, ref pnBufferSize);\n\t\t\tpchBuffer = ret ? InteropHelp.PtrToStringUTF8(pchBuffer2) : null;\n\t\t\tMarshal.FreeHGlobal(pchBuffer2);\n\t\t\treturn ret;\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/MatchmakingTypes/gameserveritem_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nusing System.Text;\n\nnamespace Steamworks {\n\t//-----------------------------------------------------------------------------\n\t// Purpose: Data describing a single server\n\t//-----------------------------------------------------------------------------\n\t[StructLayout(LayoutKind.Sequential, Size = 372, Pack = 4)]\n\t[System.Serializable]\n\tpublic class gameserveritem_t {\n\t\tpublic string GetGameDir() {\n\t\t\treturn Encoding.UTF8.GetString(m_szGameDir, 0, System.Array.IndexOf<byte>(m_szGameDir, 0));\n\t\t}\n\n\t\tpublic void SetGameDir(string dir) {\n\t\t\tm_szGameDir = Encoding.UTF8.GetBytes(dir + '\\0');\n\t\t}\n\n\t\tpublic string GetMap() {\n\t\t\treturn Encoding.UTF8.GetString(m_szMap, 0, System.Array.IndexOf<byte>(m_szMap, 0));\n\t\t}\n\n\t\tpublic void SetMap(string map) {\n\t\t\tm_szMap = Encoding.UTF8.GetBytes(map + '\\0');\n\t\t}\n\n\t\tpublic string GetGameDescription() {\n\t\t\treturn Encoding.UTF8.GetString(m_szGameDescription, 0, System.Array.IndexOf<byte>(m_szGameDescription, 0));\n\t\t}\n\n\t\tpublic void SetGameDescription(string desc) {\n\t\t\tm_szGameDescription = Encoding.UTF8.GetBytes(desc + '\\0');\n\t\t}\n\n\t\tpublic string GetServerName() {\n\t\t\t// Use the IP address as the name if nothing is set yet.\n\t\t\tif (m_szServerName[0] == 0)\n\t\t\t\treturn m_NetAdr.GetConnectionAddressString();\n\t\t\telse\n\t\t\t\treturn Encoding.UTF8.GetString(m_szServerName, 0, System.Array.IndexOf<byte>(m_szServerName, 0));\n\t\t}\n\n\t\tpublic void SetServerName(string name) {\n\t\t\tm_szServerName = Encoding.UTF8.GetBytes(name + '\\0');\n\t\t}\n\n\t\tpublic string GetGameTags() {\n\t\t\treturn Encoding.UTF8.GetString(m_szGameTags, 0, System.Array.IndexOf<byte>(m_szGameTags, 0));\n\t\t}\n\n\t\tpublic void SetGameTags(string tags) {\n\t\t\tm_szGameTags = Encoding.UTF8.GetBytes(tags + '\\0');\n\t\t}\n\n\t\tpublic servernetadr_t m_NetAdr;\t\t\t\t\t\t\t\t\t\t///< IP/Query Port/Connection Port for this server\n\t\tpublic int m_nPing;\t\t\t\t\t\t\t\t\t\t\t\t\t///< current ping time in milliseconds\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bHadSuccessfulResponse;\t\t\t\t\t\t\t\t///< server has responded successfully in the past\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bDoNotRefresh;\t\t\t\t\t\t\t\t\t\t///< server is marked as not responding and should no longer be refreshed\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerGameDir)]\n\t\tprivate byte[] m_szGameDir;\t\t\t\t\t\t\t\t\t\t\t///< current game directory\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerMapName)]\n\t\tprivate byte[] m_szMap;\t\t\t\t\t\t\t\t\t\t\t\t///< current map\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerGameDescription)]\n\t\tprivate byte[] m_szGameDescription;\t\t\t\t\t\t\t\t\t///< game description\n\t\tpublic uint m_nAppID;\t\t\t\t\t\t\t\t\t\t\t\t///< Steam App ID of this server\n\t\tpublic int m_nPlayers;\t\t\t\t\t\t\t\t\t\t\t\t///< total number of players currently on the server.  INCLUDES BOTS!!\n\t\tpublic int m_nMaxPlayers;\t\t\t\t\t\t\t\t\t\t\t///< Maximum players that can join this server\n\t\tpublic int m_nBotPlayers;\t\t\t\t\t\t\t\t\t\t\t///< Number of bots (i.e simulated players) on this server\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bPassword;\t\t\t\t\t\t\t\t\t\t\t///< true if this server needs a password to join\n\t\t[MarshalAs(UnmanagedType.I1)]\n\t\tpublic bool m_bSecure;\t\t\t\t\t\t\t\t\t\t\t\t///< Is this server protected by VAC\n\t\tpublic uint m_ulTimeLastPlayed;\t\t\t\t\t\t\t\t\t\t///< time (in unix time) when this server was last played on (for favorite/history servers)\n\t\tpublic int\tm_nServerVersion;\t\t\t\t\t\t\t\t\t\t///< server version as reported to Steam\n\n\t\t// Game server name\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerName)]\n\t\tprivate byte[] m_szServerName;\n\n\t\t// the tags this server exposes\n\t\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerTags)]\n\t\tprivate byte[] m_szGameTags;\n\n\t\t// steamID of the game server - invalid if it's doesn't have one (old server, or not connected to Steam)\n\t\tpublic CSteamID m_steamID;\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/MatchmakingTypes/servernetadr_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t// servernetadr_t is all the addressing info the serverbrowser needs to know about a game server,\n\t// namely: its IP, its connection port, and its query port.\n\t[System.Serializable]\n\tpublic struct servernetadr_t {\n\t\tprivate ushort m_usConnectionPort;\t// (in HOST byte order)\n\t\tprivate ushort m_usQueryPort;\n\t\tprivate uint m_unIP;\n\n\t\tpublic void Init(uint ip, ushort usQueryPort, ushort usConnectionPort) {\n\t\t\tm_unIP = ip;\n\t\t\tm_usQueryPort = usQueryPort;\n\t\t\tm_usConnectionPort = usConnectionPort;\n\t\t}\n\n#if NETADR_H\n\t\tpublic netadr_t GetIPAndQueryPort() {\n\t\t\treturn netadr_t( m_unIP, m_usQueryPort );\n\t\t}\n#endif\n\n\t\t// Access the query port.\n\t\tpublic ushort GetQueryPort() {\n\t\t\treturn m_usQueryPort;\n\t\t}\n\n\t\tpublic void SetQueryPort(ushort usPort) {\n\t\t\tm_usQueryPort = usPort;\n\t\t}\n\n\t\t// Access the connection port.\n\t\tpublic ushort GetConnectionPort() {\n\t\t\treturn m_usConnectionPort;\n\t\t}\n\n\t\tpublic void SetConnectionPort(ushort usPort) {\n\t\t\tm_usConnectionPort = usPort;\n\t\t}\n\n\t\t// Access the IP\n\t\tpublic uint GetIP() {\n\t\t\treturn m_unIP;\n\t\t}\n\n\t\tpublic void SetIP(uint unIP) {\n\t\t\tm_unIP = unIP;\n\t\t}\n\n\t\t// This gets the 'a.b.c.d:port' string with the connection port (instead of the query port).\n\t\tpublic string GetConnectionAddressString() {\n\t\t\treturn ToString(m_unIP, m_usConnectionPort);\n\t\t}\n\n\t\tpublic string GetQueryAddressString() {\n\t\t\treturn ToString(m_unIP, m_usQueryPort);\n\t\t}\n\n\t\tpublic static string ToString(uint unIP, ushort usPort) {\n#if VALVE_BIG_ENDIAN\n\t\treturn string.Format(\"{0}.{1}.{2}.{3}:{4}\", unIP & 0xFFul, (unIP >> 8) & 0xFFul, (unIP >> 16) & 0xFFul, (unIP >> 24) & 0xFFul, usPort);\n#else\n\t\treturn string.Format(\"{0}.{1}.{2}.{3}:{4}\", (unIP >> 24) & 0xFFul, (unIP >> 16) & 0xFFul, (unIP >> 8) & 0xFFul, unIP & 0xFFul, usPort);\n#endif\n\t\t}\n\n\t\tpublic static bool operator <(servernetadr_t x, servernetadr_t y) {\n\t\t\treturn (x.m_unIP < y.m_unIP) || (x.m_unIP == y.m_unIP && x.m_usQueryPort < y.m_usQueryPort);\n\t\t}\n\n\t\tpublic static bool operator >(servernetadr_t x, servernetadr_t y) {\n\t\t\treturn (x.m_unIP > y.m_unIP) || (x.m_unIP == y.m_unIP && x.m_usQueryPort > y.m_usQueryPort);\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is servernetadr_t && this == (servernetadr_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_unIP.GetHashCode() + m_usQueryPort.GetHashCode() + m_usConnectionPort.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(servernetadr_t x, servernetadr_t y) {\n\t\t\treturn (x.m_unIP == y.m_unIP) && (x.m_usQueryPort == y.m_usQueryPort) && (x.m_usConnectionPort == y.m_usConnectionPort);\n\t\t}\n\n\t\tpublic static bool operator !=(servernetadr_t x, servernetadr_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic bool Equals(servernetadr_t other) {\n\t\t\treturn (m_unIP == other.m_unIP) && (m_usQueryPort == other.m_usQueryPort) && (m_usConnectionPort == other.m_usConnectionPort);\n\t\t}\n\n\t\tpublic int CompareTo(servernetadr_t other) {\n\t\t\treturn m_unIP.CompareTo(other.m_unIP) + m_usQueryPort.CompareTo(other.m_usQueryPort) + m_usConnectionPort.CompareTo(other.m_usConnectionPort);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClient/SteamAPIWarningMessageHook_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]\n\tpublic delegate void SteamAPIWarningMessageHook_t(int nSeverity, System.Text.StringBuilder pchDebugText);\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.StdCall)] // TODO: This is probably wrong, will likely crash on some platform.\n\tpublic delegate void SteamAPI_CheckCallbackRegistered_t(int iCallbackNum);\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClient/SteamAPI_PostAPIResultInProcess_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\n#endif // !DISABLESTEAMWORKS\n\n// This file is no longer needed. Valve has removed the functionality.\n// We continue to generate this file to provide a small amount of backwards compatability.\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClientPublic/CGameID.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct CGameID : System.IEquatable<CGameID>, System.IComparable<CGameID> {\n\t\tpublic ulong m_GameID;\n\n\t\tpublic enum EGameIDType {\n\t\t\tk_EGameIDTypeApp = 0,\n\t\t\tk_EGameIDTypeGameMod = 1,\n\t\t\tk_EGameIDTypeShortcut = 2,\n\t\t\tk_EGameIDTypeP2P = 3,\n\t\t};\n\n\t\tpublic CGameID(ulong GameID) {\n\t\t\tm_GameID = GameID;\n\t\t}\n\n\t\tpublic CGameID(AppId_t nAppID) {\n\t\t\tm_GameID = 0;\n\t\t\tSetAppID(nAppID);\n\t\t}\n\n\t\tpublic CGameID(AppId_t nAppID, uint nModID) {\n\t\t\tm_GameID = 0;\n\t\t\tSetAppID(nAppID);\n\t\t\tSetType(EGameIDType.k_EGameIDTypeGameMod);\n\t\t\tSetModID(nModID);\n\t\t}\n\n\t\tpublic bool IsSteamApp() {\n\t\t\treturn Type() == EGameIDType.k_EGameIDTypeApp;\n\t\t}\n\n\t\tpublic bool IsMod() {\n\t\t\treturn Type() == EGameIDType.k_EGameIDTypeGameMod;\n\t\t}\n\n\t\tpublic bool IsShortcut() {\n\t\t\treturn Type() == EGameIDType.k_EGameIDTypeShortcut;\n\t\t}\n\n\t\tpublic bool IsP2PFile() {\n\t\t\treturn Type() == EGameIDType.k_EGameIDTypeP2P;\n\t\t}\n\n\t\tpublic AppId_t AppID() {\n\t\t\treturn new AppId_t((uint)(m_GameID & 0xFFFFFFul));\n\t\t}\n\n\t\tpublic EGameIDType Type() {\n\t\t\treturn (EGameIDType)((m_GameID >> 24) & 0xFFul);\n\t\t}\n\n\t\tpublic uint ModID() {\n\t\t\treturn (uint)((m_GameID >> 32) & 0xFFFFFFFFul);\n\t\t}\n\n\t\tpublic bool IsValid() {\n\t\t\t// Each type has it's own invalid fixed point:\n\t\t\tswitch (Type()) {\n\t\t\t\tcase EGameIDType.k_EGameIDTypeApp:\n\t\t\t\t\treturn AppID() != AppId_t.Invalid;\n\n\t\t\t\tcase EGameIDType.k_EGameIDTypeGameMod:\n\t\t\t\t\treturn AppID() != AppId_t.Invalid && (ModID() & 0x80000000) != 0;\n\n\t\t\t\tcase EGameIDType.k_EGameIDTypeShortcut:\n\t\t\t\t\treturn (ModID() & 0x80000000) != 0;\n\n\t\t\t\tcase EGameIDType.k_EGameIDTypeP2P:\n\t\t\t\t\treturn AppID() == AppId_t.Invalid && (ModID() & 0x80000000) != 0;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tpublic void Reset() {\n\t\t\tm_GameID = 0;\n\t\t}\n\n\t\tpublic void Set(ulong GameID) {\n\t\t\tm_GameID = GameID;\n\t\t}\n\n\t\t#region Private Setters for internal use\n\t\tprivate void SetAppID(AppId_t other) {\n\t\t\tm_GameID = (m_GameID & ~(0xFFFFFFul << (ushort)0)) | (((ulong)(other) & 0xFFFFFFul) << (ushort)0);\n\t\t}\n\n\t\tprivate void SetType(EGameIDType other) {\n\t\t\tm_GameID = (m_GameID & ~(0xFFul << (ushort)24)) | (((ulong)(other) & 0xFFul) << (ushort)24);\n\t\t}\n\n\t\tprivate void SetModID(uint other) {\n\t\t\tm_GameID = (m_GameID & ~(0xFFFFFFFFul << (ushort)32)) | (((ulong)(other) & 0xFFFFFFFFul) << (ushort)32);\n\t\t}\n\t\t#endregion\n\n\t\t#region Overrides\n\t\tpublic override string ToString() {\n\t\t\treturn m_GameID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is CGameID && this == (CGameID)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_GameID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(CGameID x, CGameID y) {\n\t\t\treturn x.m_GameID == y.m_GameID;\n\t\t}\n\n\t\tpublic static bool operator !=(CGameID x, CGameID y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator CGameID(ulong value) {\n\t\t\treturn new CGameID(value);\n\t\t}\n\t\tpublic static explicit operator ulong(CGameID that) {\n\t\t\treturn that.m_GameID;\n\t\t}\n\n\t\tpublic bool Equals(CGameID other) {\n\t\t\treturn m_GameID == other.m_GameID;\n\t\t}\n\n\t\tpublic int CompareTo(CGameID other) {\n\t\t\treturn m_GameID.CompareTo(other.m_GameID);\n\t\t}\n\t\t#endregion\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClientPublic/CSteamID.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\t[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 4)]\n\tpublic struct CSteamID : System.IEquatable<CSteamID>, System.IComparable<CSteamID> {\n\t\tpublic static readonly CSteamID Nil = new CSteamID();\n\t\tpublic static readonly CSteamID OutofDateGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);\n\t\tpublic static readonly CSteamID LanModeGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniversePublic, EAccountType.k_EAccountTypeInvalid);\n\t\tpublic static readonly CSteamID NotInitYetGS = new CSteamID(new AccountID_t(1), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);\n\t\tpublic static readonly CSteamID NonSteamGS = new CSteamID(new AccountID_t(2), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);\n\t\tpublic ulong m_SteamID;\n\n\t\tpublic CSteamID(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType) {\n\t\t\tm_SteamID = 0;\n\t\t\tSet(unAccountID, eUniverse, eAccountType);\n\t\t}\n\n\t\tpublic CSteamID(AccountID_t unAccountID, uint unAccountInstance, EUniverse eUniverse, EAccountType eAccountType) {\n\t\t\tm_SteamID = 0;\n#if _SERVER && Assert\n\t\tAssert( ! ( ( EAccountType.k_EAccountTypeIndividual == eAccountType ) && ( unAccountInstance > k_unSteamUserWebInstance ) ) );\t// enforce that for individual accounts, instance is always 1\n#endif // _SERVER\n\t\t\tInstancedSet(unAccountID, unAccountInstance, eUniverse, eAccountType);\n\t\t}\n\n\t\tpublic CSteamID(ulong ulSteamID) {\n\t\t\tm_SteamID = ulSteamID;\n\t\t}\n\n\t\tpublic void Set(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType) {\n\t\t\tSetAccountID(unAccountID);\n\t\t\tSetEUniverse(eUniverse);\n\t\t\tSetEAccountType(eAccountType);\n\n\t\t\tif (eAccountType == EAccountType.k_EAccountTypeClan || eAccountType == EAccountType.k_EAccountTypeGameServer) {\n\t\t\t\tSetAccountInstance(0);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// by default we pick the desktop instance\n\t\t\t\tSetAccountInstance(Constants.k_unSteamUserDesktopInstance);\n\t\t\t}\n\t\t}\n\n\t\tpublic void InstancedSet(AccountID_t unAccountID, uint unInstance, EUniverse eUniverse, EAccountType eAccountType) {\n\t\t\tSetAccountID(unAccountID);\n\t\t\tSetEUniverse(eUniverse);\n\t\t\tSetEAccountType(eAccountType);\n\t\t\tSetAccountInstance(unInstance);\n\t\t}\n\n\t\tpublic void Clear() {\n\t\t\tm_SteamID = 0;\n\t\t}\n\n\t\tpublic void CreateBlankAnonLogon(EUniverse eUniverse) {\n\t\t\tSetAccountID(new AccountID_t(0));\n\t\t\tSetEUniverse(eUniverse);\n\t\t\tSetEAccountType(EAccountType.k_EAccountTypeAnonGameServer);\n\t\t\tSetAccountInstance(0);\n\t\t}\n\n\t\tpublic void CreateBlankAnonUserLogon(EUniverse eUniverse) {\n\t\t\tSetAccountID(new AccountID_t(0));\n\t\t\tSetEUniverse(eUniverse);\n\t\t\tSetEAccountType(EAccountType.k_EAccountTypeAnonUser);\n\t\t\tSetAccountInstance(0);\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this an anonymous game server login that will be filled in?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BBlankAnonAccount() {\n\t\t\treturn GetAccountID() == new AccountID_t(0) && BAnonAccount() && GetUnAccountInstance() == 0;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a game server account id?  (Either persistent or anonymous)\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BGameServerAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeGameServer || GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a persistent (not anonymous) game server account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BPersistentGameServerAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeGameServer;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this an anonymous game server account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BAnonGameServerAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a content server account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BContentServerAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeContentServer;\n\t\t}\n\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a clan account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BClanAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeClan;\n\t\t}\n\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a chat account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BChatAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeChat;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a chat account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool IsLobby() {\n\t\t\treturn (GetEAccountType() == EAccountType.k_EAccountTypeChat)\n\t\t\t\t&& (GetUnAccountInstance() & (int)EChatSteamIDInstanceFlags.k_EChatInstanceFlagLobby) != 0;\n\t\t}\n\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this an individual user account id?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BIndividualAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeIndividual || GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser;\n\t\t}\n\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this an anonymous account?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BAnonAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeAnonUser || GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this an anonymous user account? ( used to create an account or reset a password )\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BAnonUserAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeAnonUser;\n\t\t}\n\n\t\t//-----------------------------------------------------------------------------\n\t\t// Purpose: Is this a faked up Steam ID for a PSN friend account?\n\t\t//-----------------------------------------------------------------------------\n\t\tpublic bool BConsoleUserAccount() {\n\t\t\treturn GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser;\n\t\t}\n\n\t\tpublic void SetAccountID(AccountID_t other) {\n\t\t\tm_SteamID = (m_SteamID & ~(0xFFFFFFFFul << (ushort)0)) | (((ulong)(other) & 0xFFFFFFFFul) << (ushort)0);\n\t\t}\n\n\t\tpublic void SetAccountInstance(uint other) {\n\t\t\tm_SteamID = (m_SteamID & ~(0xFFFFFul << (ushort)32)) | (((ulong)(other) & 0xFFFFFul) << (ushort)32);\n\t\t}\n\n\t\t// This is a non standard/custom function not found in C++ Steamworks\n\t\tpublic void SetEAccountType(EAccountType other) {\n\t\t\tm_SteamID = (m_SteamID & ~(0xFul << (ushort)52)) | (((ulong)(other) & 0xFul) << (ushort)52);\n\t\t}\n\n\t\tpublic void SetEUniverse(EUniverse other) {\n\t\t\tm_SteamID = (m_SteamID & ~(0xFFul << (ushort)56)) | (((ulong)(other) & 0xFFul) << (ushort)56);\n\t\t}\n\n\t\tpublic void ClearIndividualInstance() {\n\t\t\tif (BIndividualAccount())\n\t\t\t\tSetAccountInstance(0);\n\t\t}\n\n\t\tpublic bool HasNoIndividualInstance() {\n\t\t\treturn BIndividualAccount() && (GetUnAccountInstance() == 0);\n\t\t}\n\n\t\tpublic AccountID_t GetAccountID() {\n\t\t\treturn new AccountID_t((uint)(m_SteamID & 0xFFFFFFFFul));\n\t\t}\n\n\t\tpublic uint GetUnAccountInstance() {\n\t\t\treturn (uint)((m_SteamID >> 32) & 0xFFFFFul);\n\t\t}\n\n\t\tpublic EAccountType GetEAccountType() {\n\t\t\treturn (EAccountType)((m_SteamID >> 52) & 0xFul);\n\t\t}\n\n\t\tpublic EUniverse GetEUniverse() {\n\t\t\treturn (EUniverse)((m_SteamID >> 56) & 0xFFul);\n\t\t}\n\n\t\tpublic bool IsValid() {\n\t\t\tif (GetEAccountType() <= EAccountType.k_EAccountTypeInvalid || GetEAccountType() >= EAccountType.k_EAccountTypeMax)\n\t\t\t\treturn false;\n\n\t\t\tif (GetEUniverse() <= EUniverse.k_EUniverseInvalid || GetEUniverse() >= EUniverse.k_EUniverseMax)\n\t\t\t\treturn false;\n\n\t\t\tif (GetEAccountType() == EAccountType.k_EAccountTypeIndividual) {\n\t\t\t\tif (GetAccountID() == new AccountID_t(0) || GetUnAccountInstance() > Constants.k_unSteamUserWebInstance)\n\t\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (GetEAccountType() == EAccountType.k_EAccountTypeClan) {\n\t\t\t\tif (GetAccountID() == new AccountID_t(0) || GetUnAccountInstance() != 0)\n\t\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (GetEAccountType() == EAccountType.k_EAccountTypeGameServer) {\n\t\t\t\tif (GetAccountID() == new AccountID_t(0))\n\t\t\t\t\treturn false;\n\t\t\t\t// Any limit on instances?  We use them for local users and bots\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t#region Overrides\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is CSteamID && this == (CSteamID)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(CSteamID x, CSteamID y) {\n\t\t\treturn x.m_SteamID == y.m_SteamID;\n\t\t}\n\n\t\tpublic static bool operator !=(CSteamID x, CSteamID y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator CSteamID(ulong value) {\n\t\t\treturn new CSteamID(value);\n\t\t}\n\t\tpublic static explicit operator ulong(CSteamID that) {\n\t\t\treturn that.m_SteamID;\n\t\t}\n\n\t\tpublic bool Equals(CSteamID other) {\n\t\t\treturn m_SteamID == other.m_SteamID;\n\t\t}\n\n\t\tpublic int CompareTo(CSteamID other) {\n\t\t\treturn m_SteamID.CompareTo(other.m_SteamID);\n\t\t}\n\t\t#endregion\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamClientPublic/HAuthTicket.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HAuthTicket : System.IEquatable<HAuthTicket>, System.IComparable<HAuthTicket> {\n\t\tpublic static readonly HAuthTicket Invalid = new HAuthTicket(0);\n\t\tpublic uint m_HAuthTicket;\n\n\t\tpublic HAuthTicket(uint value) {\n\t\t\tm_HAuthTicket = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HAuthTicket.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HAuthTicket && this == (HAuthTicket)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HAuthTicket.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HAuthTicket x, HAuthTicket y) {\n\t\t\treturn x.m_HAuthTicket == y.m_HAuthTicket;\n\t\t}\n\n\t\tpublic static bool operator !=(HAuthTicket x, HAuthTicket y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HAuthTicket(uint value) {\n\t\t\treturn new HAuthTicket(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(HAuthTicket that) {\n\t\t\treturn that.m_HAuthTicket;\n\t\t}\n\n\t\tpublic bool Equals(HAuthTicket other) {\n\t\t\treturn m_HAuthTicket == other.m_HAuthTicket;\n\t\t}\n\n\t\tpublic int CompareTo(HAuthTicket other) {\n\t\t\treturn m_HAuthTicket.CompareTo(other.m_HAuthTicket);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamController/ControllerActionSetHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ControllerActionSetHandle_t : System.IEquatable<ControllerActionSetHandle_t>, System.IComparable<ControllerActionSetHandle_t> {\n\t\tpublic ulong m_ControllerActionSetHandle;\n\n\t\tpublic ControllerActionSetHandle_t(ulong value) {\n\t\t\tm_ControllerActionSetHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ControllerActionSetHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ControllerActionSetHandle_t && this == (ControllerActionSetHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ControllerActionSetHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ControllerActionSetHandle_t x, ControllerActionSetHandle_t y) {\n\t\t\treturn x.m_ControllerActionSetHandle == y.m_ControllerActionSetHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(ControllerActionSetHandle_t x, ControllerActionSetHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ControllerActionSetHandle_t(ulong value) {\n\t\t\treturn new ControllerActionSetHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(ControllerActionSetHandle_t that) {\n\t\t\treturn that.m_ControllerActionSetHandle;\n\t\t}\n\n\t\tpublic bool Equals(ControllerActionSetHandle_t other) {\n\t\t\treturn m_ControllerActionSetHandle == other.m_ControllerActionSetHandle;\n\t\t}\n\n\t\tpublic int CompareTo(ControllerActionSetHandle_t other) {\n\t\t\treturn m_ControllerActionSetHandle.CompareTo(other.m_ControllerActionSetHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamController/ControllerAnalogActionHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ControllerAnalogActionHandle_t : System.IEquatable<ControllerAnalogActionHandle_t>, System.IComparable<ControllerAnalogActionHandle_t> {\n\t\tpublic ulong m_ControllerAnalogActionHandle;\n\n\t\tpublic ControllerAnalogActionHandle_t(ulong value) {\n\t\t\tm_ControllerAnalogActionHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ControllerAnalogActionHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ControllerAnalogActionHandle_t && this == (ControllerAnalogActionHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ControllerAnalogActionHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ControllerAnalogActionHandle_t x, ControllerAnalogActionHandle_t y) {\n\t\t\treturn x.m_ControllerAnalogActionHandle == y.m_ControllerAnalogActionHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(ControllerAnalogActionHandle_t x, ControllerAnalogActionHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ControllerAnalogActionHandle_t(ulong value) {\n\t\t\treturn new ControllerAnalogActionHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(ControllerAnalogActionHandle_t that) {\n\t\t\treturn that.m_ControllerAnalogActionHandle;\n\t\t}\n\n\t\tpublic bool Equals(ControllerAnalogActionHandle_t other) {\n\t\t\treturn m_ControllerAnalogActionHandle == other.m_ControllerAnalogActionHandle;\n\t\t}\n\n\t\tpublic int CompareTo(ControllerAnalogActionHandle_t other) {\n\t\t\treturn m_ControllerAnalogActionHandle.CompareTo(other.m_ControllerAnalogActionHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamController/ControllerDigitalActionHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ControllerDigitalActionHandle_t : System.IEquatable<ControllerDigitalActionHandle_t>, System.IComparable<ControllerDigitalActionHandle_t> {\n\t\tpublic ulong m_ControllerDigitalActionHandle;\n\n\t\tpublic ControllerDigitalActionHandle_t(ulong value) {\n\t\t\tm_ControllerDigitalActionHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ControllerDigitalActionHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ControllerDigitalActionHandle_t && this == (ControllerDigitalActionHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ControllerDigitalActionHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ControllerDigitalActionHandle_t x, ControllerDigitalActionHandle_t y) {\n\t\t\treturn x.m_ControllerDigitalActionHandle == y.m_ControllerDigitalActionHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(ControllerDigitalActionHandle_t x, ControllerDigitalActionHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ControllerDigitalActionHandle_t(ulong value) {\n\t\t\treturn new ControllerDigitalActionHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(ControllerDigitalActionHandle_t that) {\n\t\t\treturn that.m_ControllerDigitalActionHandle;\n\t\t}\n\n\t\tpublic bool Equals(ControllerDigitalActionHandle_t other) {\n\t\t\treturn m_ControllerDigitalActionHandle == other.m_ControllerDigitalActionHandle;\n\t\t}\n\n\t\tpublic int CompareTo(ControllerDigitalActionHandle_t other) {\n\t\t\treturn m_ControllerDigitalActionHandle.CompareTo(other.m_ControllerDigitalActionHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamController/ControllerHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ControllerHandle_t : System.IEquatable<ControllerHandle_t>, System.IComparable<ControllerHandle_t> {\n\t\tpublic ulong m_ControllerHandle;\n\n\t\tpublic ControllerHandle_t(ulong value) {\n\t\t\tm_ControllerHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ControllerHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ControllerHandle_t && this == (ControllerHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ControllerHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ControllerHandle_t x, ControllerHandle_t y) {\n\t\t\treturn x.m_ControllerHandle == y.m_ControllerHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(ControllerHandle_t x, ControllerHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ControllerHandle_t(ulong value) {\n\t\t\treturn new ControllerHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(ControllerHandle_t that) {\n\t\t\treturn that.m_ControllerHandle;\n\t\t}\n\n\t\tpublic bool Equals(ControllerHandle_t other) {\n\t\t\treturn m_ControllerHandle == other.m_ControllerHandle;\n\t\t}\n\n\t\tpublic int CompareTo(ControllerHandle_t other) {\n\t\t\treturn m_ControllerHandle.CompareTo(other.m_ControllerHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamFriends/FriendsGroupID_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct FriendsGroupID_t : System.IEquatable<FriendsGroupID_t>, System.IComparable<FriendsGroupID_t> {\n\t\tpublic static readonly FriendsGroupID_t Invalid = new FriendsGroupID_t(-1);\n\t\tpublic short m_FriendsGroupID;\n\n\t\tpublic FriendsGroupID_t(short value) {\n\t\t\tm_FriendsGroupID = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_FriendsGroupID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is FriendsGroupID_t && this == (FriendsGroupID_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_FriendsGroupID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(FriendsGroupID_t x, FriendsGroupID_t y) {\n\t\t\treturn x.m_FriendsGroupID == y.m_FriendsGroupID;\n\t\t}\n\n\t\tpublic static bool operator !=(FriendsGroupID_t x, FriendsGroupID_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator FriendsGroupID_t(short value) {\n\t\t\treturn new FriendsGroupID_t(value);\n\t\t}\n\n\t\tpublic static explicit operator short(FriendsGroupID_t that) {\n\t\t\treturn that.m_FriendsGroupID;\n\t\t}\n\n\t\tpublic bool Equals(FriendsGroupID_t other) {\n\t\t\treturn m_FriendsGroupID == other.m_FriendsGroupID;\n\t\t}\n\n\t\tpublic int CompareTo(FriendsGroupID_t other) {\n\t\t\treturn m_FriendsGroupID.CompareTo(other.m_FriendsGroupID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamHTMLSurface/HHTMLBrowser.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HHTMLBrowser : System.IEquatable<HHTMLBrowser>, System.IComparable<HHTMLBrowser> {\n\t\tpublic static readonly HHTMLBrowser Invalid = new HHTMLBrowser(0);\n\t\tpublic uint m_HHTMLBrowser;\n\n\t\tpublic HHTMLBrowser(uint value) {\n\t\t\tm_HHTMLBrowser = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HHTMLBrowser.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HHTMLBrowser && this == (HHTMLBrowser)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HHTMLBrowser.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HHTMLBrowser x, HHTMLBrowser y) {\n\t\t\treturn x.m_HHTMLBrowser == y.m_HHTMLBrowser;\n\t\t}\n\n\t\tpublic static bool operator !=(HHTMLBrowser x, HHTMLBrowser y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HHTMLBrowser(uint value) {\n\t\t\treturn new HHTMLBrowser(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(HHTMLBrowser that) {\n\t\t\treturn that.m_HHTMLBrowser;\n\t\t}\n\n\t\tpublic bool Equals(HHTMLBrowser other) {\n\t\t\treturn m_HHTMLBrowser == other.m_HHTMLBrowser;\n\t\t}\n\n\t\tpublic int CompareTo(HHTMLBrowser other) {\n\t\t\treturn m_HHTMLBrowser.CompareTo(other.m_HHTMLBrowser);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamHTTP/HTTPCookieContainerHandle.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HTTPCookieContainerHandle : System.IEquatable<HTTPCookieContainerHandle>, System.IComparable<HTTPCookieContainerHandle> {\n\t\tpublic static readonly HTTPCookieContainerHandle Invalid = new HTTPCookieContainerHandle(0);\n\t\tpublic uint m_HTTPCookieContainerHandle;\n\n\t\tpublic HTTPCookieContainerHandle(uint value) {\n\t\t\tm_HTTPCookieContainerHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HTTPCookieContainerHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HTTPCookieContainerHandle && this == (HTTPCookieContainerHandle)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HTTPCookieContainerHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HTTPCookieContainerHandle x, HTTPCookieContainerHandle y) {\n\t\t\treturn x.m_HTTPCookieContainerHandle == y.m_HTTPCookieContainerHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(HTTPCookieContainerHandle x, HTTPCookieContainerHandle y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HTTPCookieContainerHandle(uint value) {\n\t\t\treturn new HTTPCookieContainerHandle(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(HTTPCookieContainerHandle that) {\n\t\t\treturn that.m_HTTPCookieContainerHandle;\n\t\t}\n\n\t\tpublic bool Equals(HTTPCookieContainerHandle other) {\n\t\t\treturn m_HTTPCookieContainerHandle == other.m_HTTPCookieContainerHandle;\n\t\t}\n\n\t\tpublic int CompareTo(HTTPCookieContainerHandle other) {\n\t\t\treturn m_HTTPCookieContainerHandle.CompareTo(other.m_HTTPCookieContainerHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamHTTP/HTTPRequestHandle.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HTTPRequestHandle : System.IEquatable<HTTPRequestHandle>, System.IComparable<HTTPRequestHandle> {\n\t\tpublic static readonly HTTPRequestHandle Invalid = new HTTPRequestHandle(0);\n\t\tpublic uint m_HTTPRequestHandle;\n\n\t\tpublic HTTPRequestHandle(uint value) {\n\t\t\tm_HTTPRequestHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HTTPRequestHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HTTPRequestHandle && this == (HTTPRequestHandle)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HTTPRequestHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HTTPRequestHandle x, HTTPRequestHandle y) {\n\t\t\treturn x.m_HTTPRequestHandle == y.m_HTTPRequestHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(HTTPRequestHandle x, HTTPRequestHandle y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HTTPRequestHandle(uint value) {\n\t\t\treturn new HTTPRequestHandle(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(HTTPRequestHandle that) {\n\t\t\treturn that.m_HTTPRequestHandle;\n\t\t}\n\n\t\tpublic bool Equals(HTTPRequestHandle other) {\n\t\t\treturn m_HTTPRequestHandle == other.m_HTTPRequestHandle;\n\t\t}\n\n\t\tpublic int CompareTo(HTTPRequestHandle other) {\n\t\t\treturn m_HTTPRequestHandle.CompareTo(other.m_HTTPRequestHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInput/InputActionSetHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct InputActionSetHandle_t : System.IEquatable<InputActionSetHandle_t>, System.IComparable<InputActionSetHandle_t> {\n\t\tpublic ulong m_InputActionSetHandle;\n\n\t\tpublic InputActionSetHandle_t(ulong value) {\n\t\t\tm_InputActionSetHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_InputActionSetHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is InputActionSetHandle_t && this == (InputActionSetHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_InputActionSetHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(InputActionSetHandle_t x, InputActionSetHandle_t y) {\n\t\t\treturn x.m_InputActionSetHandle == y.m_InputActionSetHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(InputActionSetHandle_t x, InputActionSetHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator InputActionSetHandle_t(ulong value) {\n\t\t\treturn new InputActionSetHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(InputActionSetHandle_t that) {\n\t\t\treturn that.m_InputActionSetHandle;\n\t\t}\n\n\t\tpublic bool Equals(InputActionSetHandle_t other) {\n\t\t\treturn m_InputActionSetHandle == other.m_InputActionSetHandle;\n\t\t}\n\n\t\tpublic int CompareTo(InputActionSetHandle_t other) {\n\t\t\treturn m_InputActionSetHandle.CompareTo(other.m_InputActionSetHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInput/InputAnalogActionHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct InputAnalogActionHandle_t : System.IEquatable<InputAnalogActionHandle_t>, System.IComparable<InputAnalogActionHandle_t> {\n\t\tpublic ulong m_InputAnalogActionHandle;\n\n\t\tpublic InputAnalogActionHandle_t(ulong value) {\n\t\t\tm_InputAnalogActionHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_InputAnalogActionHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is InputAnalogActionHandle_t && this == (InputAnalogActionHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_InputAnalogActionHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(InputAnalogActionHandle_t x, InputAnalogActionHandle_t y) {\n\t\t\treturn x.m_InputAnalogActionHandle == y.m_InputAnalogActionHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(InputAnalogActionHandle_t x, InputAnalogActionHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator InputAnalogActionHandle_t(ulong value) {\n\t\t\treturn new InputAnalogActionHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(InputAnalogActionHandle_t that) {\n\t\t\treturn that.m_InputAnalogActionHandle;\n\t\t}\n\n\t\tpublic bool Equals(InputAnalogActionHandle_t other) {\n\t\t\treturn m_InputAnalogActionHandle == other.m_InputAnalogActionHandle;\n\t\t}\n\n\t\tpublic int CompareTo(InputAnalogActionHandle_t other) {\n\t\t\treturn m_InputAnalogActionHandle.CompareTo(other.m_InputAnalogActionHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInput/InputDigitalActionHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct InputDigitalActionHandle_t : System.IEquatable<InputDigitalActionHandle_t>, System.IComparable<InputDigitalActionHandle_t> {\n\t\tpublic ulong m_InputDigitalActionHandle;\n\n\t\tpublic InputDigitalActionHandle_t(ulong value) {\n\t\t\tm_InputDigitalActionHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_InputDigitalActionHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is InputDigitalActionHandle_t && this == (InputDigitalActionHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_InputDigitalActionHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(InputDigitalActionHandle_t x, InputDigitalActionHandle_t y) {\n\t\t\treturn x.m_InputDigitalActionHandle == y.m_InputDigitalActionHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(InputDigitalActionHandle_t x, InputDigitalActionHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator InputDigitalActionHandle_t(ulong value) {\n\t\t\treturn new InputDigitalActionHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(InputDigitalActionHandle_t that) {\n\t\t\treturn that.m_InputDigitalActionHandle;\n\t\t}\n\n\t\tpublic bool Equals(InputDigitalActionHandle_t other) {\n\t\t\treturn m_InputDigitalActionHandle == other.m_InputDigitalActionHandle;\n\t\t}\n\n\t\tpublic int CompareTo(InputDigitalActionHandle_t other) {\n\t\t\treturn m_InputDigitalActionHandle.CompareTo(other.m_InputDigitalActionHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInput/InputHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct InputHandle_t : System.IEquatable<InputHandle_t>, System.IComparable<InputHandle_t> {\n\t\tpublic ulong m_InputHandle;\n\n\t\tpublic InputHandle_t(ulong value) {\n\t\t\tm_InputHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_InputHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is InputHandle_t && this == (InputHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_InputHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(InputHandle_t x, InputHandle_t y) {\n\t\t\treturn x.m_InputHandle == y.m_InputHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(InputHandle_t x, InputHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator InputHandle_t(ulong value) {\n\t\t\treturn new InputHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(InputHandle_t that) {\n\t\t\treturn that.m_InputHandle;\n\t\t}\n\n\t\tpublic bool Equals(InputHandle_t other) {\n\t\t\treturn m_InputHandle == other.m_InputHandle;\n\t\t}\n\n\t\tpublic int CompareTo(InputHandle_t other) {\n\t\t\treturn m_InputHandle.CompareTo(other.m_InputHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInventory/SteamInventoryResult_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamInventoryResult_t : System.IEquatable<SteamInventoryResult_t>, System.IComparable<SteamInventoryResult_t> {\n\t\tpublic static readonly SteamInventoryResult_t Invalid = new SteamInventoryResult_t(-1);\n\t\tpublic int m_SteamInventoryResult;\n\n\t\tpublic SteamInventoryResult_t(int value) {\n\t\t\tm_SteamInventoryResult = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamInventoryResult.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamInventoryResult_t && this == (SteamInventoryResult_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamInventoryResult.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamInventoryResult_t x, SteamInventoryResult_t y) {\n\t\t\treturn x.m_SteamInventoryResult == y.m_SteamInventoryResult;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamInventoryResult_t x, SteamInventoryResult_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamInventoryResult_t(int value) {\n\t\t\treturn new SteamInventoryResult_t(value);\n\t\t}\n\n\t\tpublic static explicit operator int(SteamInventoryResult_t that) {\n\t\t\treturn that.m_SteamInventoryResult;\n\t\t}\n\n\t\tpublic bool Equals(SteamInventoryResult_t other) {\n\t\t\treturn m_SteamInventoryResult == other.m_SteamInventoryResult;\n\t\t}\n\n\t\tpublic int CompareTo(SteamInventoryResult_t other) {\n\t\t\treturn m_SteamInventoryResult.CompareTo(other.m_SteamInventoryResult);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInventory/SteamInventoryUpdateHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamInventoryUpdateHandle_t : System.IEquatable<SteamInventoryUpdateHandle_t>, System.IComparable<SteamInventoryUpdateHandle_t> {\n\t\tpublic static readonly SteamInventoryUpdateHandle_t Invalid = new SteamInventoryUpdateHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_SteamInventoryUpdateHandle;\n\n\t\tpublic SteamInventoryUpdateHandle_t(ulong value) {\n\t\t\tm_SteamInventoryUpdateHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamInventoryUpdateHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamInventoryUpdateHandle_t && this == (SteamInventoryUpdateHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamInventoryUpdateHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamInventoryUpdateHandle_t x, SteamInventoryUpdateHandle_t y) {\n\t\t\treturn x.m_SteamInventoryUpdateHandle == y.m_SteamInventoryUpdateHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamInventoryUpdateHandle_t x, SteamInventoryUpdateHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamInventoryUpdateHandle_t(ulong value) {\n\t\t\treturn new SteamInventoryUpdateHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SteamInventoryUpdateHandle_t that) {\n\t\t\treturn that.m_SteamInventoryUpdateHandle;\n\t\t}\n\n\t\tpublic bool Equals(SteamInventoryUpdateHandle_t other) {\n\t\t\treturn m_SteamInventoryUpdateHandle == other.m_SteamInventoryUpdateHandle;\n\t\t}\n\n\t\tpublic int CompareTo(SteamInventoryUpdateHandle_t other) {\n\t\t\treturn m_SteamInventoryUpdateHandle.CompareTo(other.m_SteamInventoryUpdateHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInventory/SteamItemDef_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamItemDef_t : System.IEquatable<SteamItemDef_t>, System.IComparable<SteamItemDef_t> {\n\t\tpublic int m_SteamItemDef;\n\n\t\tpublic SteamItemDef_t(int value) {\n\t\t\tm_SteamItemDef = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamItemDef.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamItemDef_t && this == (SteamItemDef_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamItemDef.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamItemDef_t x, SteamItemDef_t y) {\n\t\t\treturn x.m_SteamItemDef == y.m_SteamItemDef;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamItemDef_t x, SteamItemDef_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamItemDef_t(int value) {\n\t\t\treturn new SteamItemDef_t(value);\n\t\t}\n\n\t\tpublic static explicit operator int(SteamItemDef_t that) {\n\t\t\treturn that.m_SteamItemDef;\n\t\t}\n\n\t\tpublic bool Equals(SteamItemDef_t other) {\n\t\t\treturn m_SteamItemDef == other.m_SteamItemDef;\n\t\t}\n\n\t\tpublic int CompareTo(SteamItemDef_t other) {\n\t\t\treturn m_SteamItemDef.CompareTo(other.m_SteamItemDef);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamInventory/SteamItemInstanceID_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamItemInstanceID_t : System.IEquatable<SteamItemInstanceID_t>, System.IComparable<SteamItemInstanceID_t> {\n\t\tpublic static readonly SteamItemInstanceID_t Invalid = new SteamItemInstanceID_t(0xFFFFFFFFFFFFFFFF);\n\t\tpublic ulong m_SteamItemInstanceID;\n\n\t\tpublic SteamItemInstanceID_t(ulong value) {\n\t\t\tm_SteamItemInstanceID = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamItemInstanceID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamItemInstanceID_t && this == (SteamItemInstanceID_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamItemInstanceID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamItemInstanceID_t x, SteamItemInstanceID_t y) {\n\t\t\treturn x.m_SteamItemInstanceID == y.m_SteamItemInstanceID;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamItemInstanceID_t x, SteamItemInstanceID_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamItemInstanceID_t(ulong value) {\n\t\t\treturn new SteamItemInstanceID_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SteamItemInstanceID_t that) {\n\t\t\treturn that.m_SteamItemInstanceID;\n\t\t}\n\n\t\tpublic bool Equals(SteamItemInstanceID_t other) {\n\t\t\treturn m_SteamItemInstanceID == other.m_SteamItemInstanceID;\n\t\t}\n\n\t\tpublic int CompareTo(SteamItemInstanceID_t other) {\n\t\t\treturn m_SteamItemInstanceID.CompareTo(other.m_SteamItemInstanceID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamMatchmaking/HServerListRequest.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HServerListRequest : System.IEquatable<HServerListRequest> {\n\t\tpublic static readonly HServerListRequest Invalid = new HServerListRequest(System.IntPtr.Zero);\n\t\tpublic System.IntPtr m_HServerListRequest;\n\n\t\tpublic HServerListRequest(System.IntPtr value) {\n\t\t\tm_HServerListRequest = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HServerListRequest.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HServerListRequest && this == (HServerListRequest)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HServerListRequest.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HServerListRequest x, HServerListRequest y) {\n\t\t\treturn x.m_HServerListRequest == y.m_HServerListRequest;\n\t\t}\n\n\t\tpublic static bool operator !=(HServerListRequest x, HServerListRequest y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HServerListRequest(System.IntPtr value) {\n\t\t\treturn new HServerListRequest(value);\n\t\t}\n\n\t\tpublic static explicit operator System.IntPtr(HServerListRequest that) {\n\t\t\treturn that.m_HServerListRequest;\n\t\t}\n\n\t\tpublic bool Equals(HServerListRequest other) {\n\t\t\treturn m_HServerListRequest == other.m_HServerListRequest;\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamMatchmaking/HServerQuery.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HServerQuery : System.IEquatable<HServerQuery>, System.IComparable<HServerQuery> {\n\t\tpublic static readonly HServerQuery Invalid = new HServerQuery(-1);\n\t\tpublic int m_HServerQuery;\n\n\t\tpublic HServerQuery(int value) {\n\t\t\tm_HServerQuery = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HServerQuery.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HServerQuery && this == (HServerQuery)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HServerQuery.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HServerQuery x, HServerQuery y) {\n\t\t\treturn x.m_HServerQuery == y.m_HServerQuery;\n\t\t}\n\n\t\tpublic static bool operator !=(HServerQuery x, HServerQuery y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HServerQuery(int value) {\n\t\t\treturn new HServerQuery(value);\n\t\t}\n\n\t\tpublic static explicit operator int(HServerQuery that) {\n\t\t\treturn that.m_HServerQuery;\n\t\t}\n\n\t\tpublic bool Equals(HServerQuery other) {\n\t\t\treturn m_HServerQuery == other.m_HServerQuery;\n\t\t}\n\n\t\tpublic int CompareTo(HServerQuery other) {\n\t\t\treturn m_HServerQuery.CompareTo(other.m_HServerQuery);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamNetworking/SNetListenSocket_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SNetListenSocket_t : System.IEquatable<SNetListenSocket_t>, System.IComparable<SNetListenSocket_t> {\n\t\tpublic uint m_SNetListenSocket;\n\n\t\tpublic SNetListenSocket_t(uint value) {\n\t\t\tm_SNetListenSocket = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SNetListenSocket.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SNetListenSocket_t && this == (SNetListenSocket_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SNetListenSocket.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SNetListenSocket_t x, SNetListenSocket_t y) {\n\t\t\treturn x.m_SNetListenSocket == y.m_SNetListenSocket;\n\t\t}\n\n\t\tpublic static bool operator !=(SNetListenSocket_t x, SNetListenSocket_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SNetListenSocket_t(uint value) {\n\t\t\treturn new SNetListenSocket_t(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(SNetListenSocket_t that) {\n\t\t\treturn that.m_SNetListenSocket;\n\t\t}\n\n\t\tpublic bool Equals(SNetListenSocket_t other) {\n\t\t\treturn m_SNetListenSocket == other.m_SNetListenSocket;\n\t\t}\n\n\t\tpublic int CompareTo(SNetListenSocket_t other) {\n\t\t\treturn m_SNetListenSocket.CompareTo(other.m_SNetListenSocket);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamNetworking/SNetSocket_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SNetSocket_t : System.IEquatable<SNetSocket_t>, System.IComparable<SNetSocket_t> {\n\t\tpublic uint m_SNetSocket;\n\n\t\tpublic SNetSocket_t(uint value) {\n\t\t\tm_SNetSocket = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SNetSocket.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SNetSocket_t && this == (SNetSocket_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SNetSocket.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SNetSocket_t x, SNetSocket_t y) {\n\t\t\treturn x.m_SNetSocket == y.m_SNetSocket;\n\t\t}\n\n\t\tpublic static bool operator !=(SNetSocket_t x, SNetSocket_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SNetSocket_t(uint value) {\n\t\t\treturn new SNetSocket_t(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(SNetSocket_t that) {\n\t\t\treturn that.m_SNetSocket;\n\t\t}\n\n\t\tpublic bool Equals(SNetSocket_t other) {\n\t\t\treturn m_SNetSocket == other.m_SNetSocket;\n\t\t}\n\n\t\tpublic int CompareTo(SNetSocket_t other) {\n\t\t\treturn m_SNetSocket.CompareTo(other.m_SNetSocket);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamRemoteStorage/PublishedFileId_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct PublishedFileId_t : System.IEquatable<PublishedFileId_t>, System.IComparable<PublishedFileId_t> {\n\t\tpublic static readonly PublishedFileId_t Invalid = new PublishedFileId_t(0);\n\t\tpublic ulong m_PublishedFileId;\n\n\t\tpublic PublishedFileId_t(ulong value) {\n\t\t\tm_PublishedFileId = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_PublishedFileId.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is PublishedFileId_t && this == (PublishedFileId_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_PublishedFileId.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(PublishedFileId_t x, PublishedFileId_t y) {\n\t\t\treturn x.m_PublishedFileId == y.m_PublishedFileId;\n\t\t}\n\n\t\tpublic static bool operator !=(PublishedFileId_t x, PublishedFileId_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator PublishedFileId_t(ulong value) {\n\t\t\treturn new PublishedFileId_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(PublishedFileId_t that) {\n\t\t\treturn that.m_PublishedFileId;\n\t\t}\n\n\t\tpublic bool Equals(PublishedFileId_t other) {\n\t\t\treturn m_PublishedFileId == other.m_PublishedFileId;\n\t\t}\n\n\t\tpublic int CompareTo(PublishedFileId_t other) {\n\t\t\treturn m_PublishedFileId.CompareTo(other.m_PublishedFileId);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct PublishedFileUpdateHandle_t : System.IEquatable<PublishedFileUpdateHandle_t>, System.IComparable<PublishedFileUpdateHandle_t> {\n\t\tpublic static readonly PublishedFileUpdateHandle_t Invalid = new PublishedFileUpdateHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_PublishedFileUpdateHandle;\n\n\t\tpublic PublishedFileUpdateHandle_t(ulong value) {\n\t\t\tm_PublishedFileUpdateHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_PublishedFileUpdateHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is PublishedFileUpdateHandle_t && this == (PublishedFileUpdateHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_PublishedFileUpdateHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(PublishedFileUpdateHandle_t x, PublishedFileUpdateHandle_t y) {\n\t\t\treturn x.m_PublishedFileUpdateHandle == y.m_PublishedFileUpdateHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(PublishedFileUpdateHandle_t x, PublishedFileUpdateHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator PublishedFileUpdateHandle_t(ulong value) {\n\t\t\treturn new PublishedFileUpdateHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(PublishedFileUpdateHandle_t that) {\n\t\t\treturn that.m_PublishedFileUpdateHandle;\n\t\t}\n\n\t\tpublic bool Equals(PublishedFileUpdateHandle_t other) {\n\t\t\treturn m_PublishedFileUpdateHandle == other.m_PublishedFileUpdateHandle;\n\t\t}\n\n\t\tpublic int CompareTo(PublishedFileUpdateHandle_t other) {\n\t\t\treturn m_PublishedFileUpdateHandle.CompareTo(other.m_PublishedFileUpdateHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct UGCFileWriteStreamHandle_t : System.IEquatable<UGCFileWriteStreamHandle_t>, System.IComparable<UGCFileWriteStreamHandle_t> {\n\t\tpublic static readonly UGCFileWriteStreamHandle_t Invalid = new UGCFileWriteStreamHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_UGCFileWriteStreamHandle;\n\n\t\tpublic UGCFileWriteStreamHandle_t(ulong value) {\n\t\t\tm_UGCFileWriteStreamHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_UGCFileWriteStreamHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is UGCFileWriteStreamHandle_t && this == (UGCFileWriteStreamHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_UGCFileWriteStreamHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(UGCFileWriteStreamHandle_t x, UGCFileWriteStreamHandle_t y) {\n\t\t\treturn x.m_UGCFileWriteStreamHandle == y.m_UGCFileWriteStreamHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(UGCFileWriteStreamHandle_t x, UGCFileWriteStreamHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator UGCFileWriteStreamHandle_t(ulong value) {\n\t\t\treturn new UGCFileWriteStreamHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(UGCFileWriteStreamHandle_t that) {\n\t\t\treturn that.m_UGCFileWriteStreamHandle;\n\t\t}\n\n\t\tpublic bool Equals(UGCFileWriteStreamHandle_t other) {\n\t\t\treturn m_UGCFileWriteStreamHandle == other.m_UGCFileWriteStreamHandle;\n\t\t}\n\n\t\tpublic int CompareTo(UGCFileWriteStreamHandle_t other) {\n\t\t\treturn m_UGCFileWriteStreamHandle.CompareTo(other.m_UGCFileWriteStreamHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamRemoteStorage/UGCHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct UGCHandle_t : System.IEquatable<UGCHandle_t>, System.IComparable<UGCHandle_t> {\n\t\tpublic static readonly UGCHandle_t Invalid = new UGCHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_UGCHandle;\n\n\t\tpublic UGCHandle_t(ulong value) {\n\t\t\tm_UGCHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_UGCHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is UGCHandle_t && this == (UGCHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_UGCHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(UGCHandle_t x, UGCHandle_t y) {\n\t\t\treturn x.m_UGCHandle == y.m_UGCHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(UGCHandle_t x, UGCHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator UGCHandle_t(ulong value) {\n\t\t\treturn new UGCHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(UGCHandle_t that) {\n\t\t\treturn that.m_UGCHandle;\n\t\t}\n\n\t\tpublic bool Equals(UGCHandle_t other) {\n\t\t\treturn m_UGCHandle == other.m_UGCHandle;\n\t\t}\n\n\t\tpublic int CompareTo(UGCHandle_t other) {\n\t\t\treturn m_UGCHandle.CompareTo(other.m_UGCHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamScreenshots/ScreenshotHandle.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ScreenshotHandle : System.IEquatable<ScreenshotHandle>, System.IComparable<ScreenshotHandle> {\n\t\tpublic static readonly ScreenshotHandle Invalid = new ScreenshotHandle(0);\n\t\tpublic uint m_ScreenshotHandle;\n\n\t\tpublic ScreenshotHandle(uint value) {\n\t\t\tm_ScreenshotHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ScreenshotHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ScreenshotHandle && this == (ScreenshotHandle)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ScreenshotHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ScreenshotHandle x, ScreenshotHandle y) {\n\t\t\treturn x.m_ScreenshotHandle == y.m_ScreenshotHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(ScreenshotHandle x, ScreenshotHandle y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ScreenshotHandle(uint value) {\n\t\t\treturn new ScreenshotHandle(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(ScreenshotHandle that) {\n\t\t\treturn that.m_ScreenshotHandle;\n\t\t}\n\n\t\tpublic bool Equals(ScreenshotHandle other) {\n\t\t\treturn m_ScreenshotHandle == other.m_ScreenshotHandle;\n\t\t}\n\n\t\tpublic int CompareTo(ScreenshotHandle other) {\n\t\t\treturn m_ScreenshotHandle.CompareTo(other.m_ScreenshotHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/AccountID_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct AccountID_t : System.IEquatable<AccountID_t>, System.IComparable<AccountID_t> {\n\t\tpublic uint m_AccountID;\n\n\t\tpublic AccountID_t(uint value) {\n\t\t\tm_AccountID = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_AccountID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is AccountID_t && this == (AccountID_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_AccountID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(AccountID_t x, AccountID_t y) {\n\t\t\treturn x.m_AccountID == y.m_AccountID;\n\t\t}\n\n\t\tpublic static bool operator !=(AccountID_t x, AccountID_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator AccountID_t(uint value) {\n\t\t\treturn new AccountID_t(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(AccountID_t that) {\n\t\t\treturn that.m_AccountID;\n\t\t}\n\n\t\tpublic bool Equals(AccountID_t other) {\n\t\t\treturn m_AccountID == other.m_AccountID;\n\t\t}\n\n\t\tpublic int CompareTo(AccountID_t other) {\n\t\t\treturn m_AccountID.CompareTo(other.m_AccountID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/AppId_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct AppId_t : System.IEquatable<AppId_t>, System.IComparable<AppId_t> {\n\t\tpublic static readonly AppId_t Invalid = new AppId_t(0x0);\n\t\tpublic uint m_AppId;\n\n\t\tpublic AppId_t(uint value) {\n\t\t\tm_AppId = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_AppId.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is AppId_t && this == (AppId_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_AppId.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(AppId_t x, AppId_t y) {\n\t\t\treturn x.m_AppId == y.m_AppId;\n\t\t}\n\n\t\tpublic static bool operator !=(AppId_t x, AppId_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator AppId_t(uint value) {\n\t\t\treturn new AppId_t(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(AppId_t that) {\n\t\t\treturn that.m_AppId;\n\t\t}\n\n\t\tpublic bool Equals(AppId_t other) {\n\t\t\treturn m_AppId == other.m_AppId;\n\t\t}\n\n\t\tpublic int CompareTo(AppId_t other) {\n\t\t\treturn m_AppId.CompareTo(other.m_AppId);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/DepotId_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct DepotId_t : System.IEquatable<DepotId_t>, System.IComparable<DepotId_t> {\n\t\tpublic static readonly DepotId_t Invalid = new DepotId_t(0x0);\n\t\tpublic uint m_DepotId;\n\n\t\tpublic DepotId_t(uint value) {\n\t\t\tm_DepotId = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_DepotId.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is DepotId_t && this == (DepotId_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_DepotId.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(DepotId_t x, DepotId_t y) {\n\t\t\treturn x.m_DepotId == y.m_DepotId;\n\t\t}\n\n\t\tpublic static bool operator !=(DepotId_t x, DepotId_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator DepotId_t(uint value) {\n\t\t\treturn new DepotId_t(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(DepotId_t that) {\n\t\t\treturn that.m_DepotId;\n\t\t}\n\n\t\tpublic bool Equals(DepotId_t other) {\n\t\t\treturn m_DepotId == other.m_DepotId;\n\t\t}\n\n\t\tpublic int CompareTo(DepotId_t other) {\n\t\t\treturn m_DepotId.CompareTo(other.m_DepotId);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/ManifestId_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct ManifestId_t : System.IEquatable<ManifestId_t>, System.IComparable<ManifestId_t> {\n\t\tpublic static readonly ManifestId_t Invalid = new ManifestId_t(0x0);\n\t\tpublic ulong m_ManifestId;\n\n\t\tpublic ManifestId_t(ulong value) {\n\t\t\tm_ManifestId = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_ManifestId.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is ManifestId_t && this == (ManifestId_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_ManifestId.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(ManifestId_t x, ManifestId_t y) {\n\t\t\treturn x.m_ManifestId == y.m_ManifestId;\n\t\t}\n\n\t\tpublic static bool operator !=(ManifestId_t x, ManifestId_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator ManifestId_t(ulong value) {\n\t\t\treturn new ManifestId_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(ManifestId_t that) {\n\t\t\treturn that.m_ManifestId;\n\t\t}\n\n\t\tpublic bool Equals(ManifestId_t other) {\n\t\t\treturn m_ManifestId == other.m_ManifestId;\n\t\t}\n\n\t\tpublic int CompareTo(ManifestId_t other) {\n\t\t\treturn m_ManifestId.CompareTo(other.m_ManifestId);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/PartyBeaconID_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct PartyBeaconID_t : System.IEquatable<PartyBeaconID_t>, System.IComparable<PartyBeaconID_t> {\n\t\tpublic static readonly PartyBeaconID_t Invalid = new PartyBeaconID_t(0);\n\t\tpublic ulong m_PartyBeaconID;\n\n\t\tpublic PartyBeaconID_t(ulong value) {\n\t\t\tm_PartyBeaconID = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_PartyBeaconID.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is PartyBeaconID_t && this == (PartyBeaconID_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_PartyBeaconID.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(PartyBeaconID_t x, PartyBeaconID_t y) {\n\t\t\treturn x.m_PartyBeaconID == y.m_PartyBeaconID;\n\t\t}\n\n\t\tpublic static bool operator !=(PartyBeaconID_t x, PartyBeaconID_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator PartyBeaconID_t(ulong value) {\n\t\t\treturn new PartyBeaconID_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(PartyBeaconID_t that) {\n\t\t\treturn that.m_PartyBeaconID;\n\t\t}\n\n\t\tpublic bool Equals(PartyBeaconID_t other) {\n\t\t\treturn m_PartyBeaconID == other.m_PartyBeaconID;\n\t\t}\n\n\t\tpublic int CompareTo(PartyBeaconID_t other) {\n\t\t\treturn m_PartyBeaconID.CompareTo(other.m_PartyBeaconID);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/RTime32.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct RTime32 : System.IEquatable<RTime32>, System.IComparable<RTime32> {\n\t\tpublic uint m_RTime32;\n\n\t\tpublic RTime32(uint value) {\n\t\t\tm_RTime32 = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_RTime32.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is RTime32 && this == (RTime32)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_RTime32.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(RTime32 x, RTime32 y) {\n\t\t\treturn x.m_RTime32 == y.m_RTime32;\n\t\t}\n\n\t\tpublic static bool operator !=(RTime32 x, RTime32 y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator RTime32(uint value) {\n\t\t\treturn new RTime32(value);\n\t\t}\n\n\t\tpublic static explicit operator uint(RTime32 that) {\n\t\t\treturn that.m_RTime32;\n\t\t}\n\n\t\tpublic bool Equals(RTime32 other) {\n\t\t\treturn m_RTime32 == other.m_RTime32;\n\t\t}\n\n\t\tpublic int CompareTo(RTime32 other) {\n\t\t\treturn m_RTime32.CompareTo(other.m_RTime32);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/SiteId_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SiteId_t : System.IEquatable<SiteId_t>, System.IComparable<SiteId_t> {\n\t\tpublic static readonly SiteId_t Invalid = new SiteId_t(0);\n\t\tpublic ulong m_SiteId;\n\n\t\tpublic SiteId_t(ulong value) {\n\t\t\tm_SiteId = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SiteId.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SiteId_t && this == (SiteId_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SiteId.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SiteId_t x, SiteId_t y) {\n\t\t\treturn x.m_SiteId == y.m_SiteId;\n\t\t}\n\n\t\tpublic static bool operator !=(SiteId_t x, SiteId_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SiteId_t(ulong value) {\n\t\t\treturn new SiteId_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SiteId_t that) {\n\t\t\treturn that.m_SiteId;\n\t\t}\n\n\t\tpublic bool Equals(SiteId_t other) {\n\t\t\treturn m_SiteId == other.m_SiteId;\n\t\t}\n\n\t\tpublic int CompareTo(SiteId_t other) {\n\t\t\treturn m_SiteId.CompareTo(other.m_SiteId);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamTypes/SteamAPICall_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamAPICall_t : System.IEquatable<SteamAPICall_t>, System.IComparable<SteamAPICall_t> {\n\t\tpublic static readonly SteamAPICall_t Invalid = new SteamAPICall_t(0x0);\n\t\tpublic ulong m_SteamAPICall;\n\n\t\tpublic SteamAPICall_t(ulong value) {\n\t\t\tm_SteamAPICall = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamAPICall.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamAPICall_t && this == (SteamAPICall_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamAPICall.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamAPICall_t x, SteamAPICall_t y) {\n\t\t\treturn x.m_SteamAPICall == y.m_SteamAPICall;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamAPICall_t x, SteamAPICall_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamAPICall_t(ulong value) {\n\t\t\treturn new SteamAPICall_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SteamAPICall_t that) {\n\t\t\treturn that.m_SteamAPICall;\n\t\t}\n\n\t\tpublic bool Equals(SteamAPICall_t other) {\n\t\t\treturn m_SteamAPICall == other.m_SteamAPICall;\n\t\t}\n\n\t\tpublic int CompareTo(SteamAPICall_t other) {\n\t\t\treturn m_SteamAPICall.CompareTo(other.m_SteamAPICall);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamUGC/UGCQueryHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct UGCQueryHandle_t : System.IEquatable<UGCQueryHandle_t>, System.IComparable<UGCQueryHandle_t> {\n\t\tpublic static readonly UGCQueryHandle_t Invalid = new UGCQueryHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_UGCQueryHandle;\n\n\t\tpublic UGCQueryHandle_t(ulong value) {\n\t\t\tm_UGCQueryHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_UGCQueryHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is UGCQueryHandle_t && this == (UGCQueryHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_UGCQueryHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(UGCQueryHandle_t x, UGCQueryHandle_t y) {\n\t\t\treturn x.m_UGCQueryHandle == y.m_UGCQueryHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(UGCQueryHandle_t x, UGCQueryHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator UGCQueryHandle_t(ulong value) {\n\t\t\treturn new UGCQueryHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(UGCQueryHandle_t that) {\n\t\t\treturn that.m_UGCQueryHandle;\n\t\t}\n\n\t\tpublic bool Equals(UGCQueryHandle_t other) {\n\t\t\treturn m_UGCQueryHandle == other.m_UGCQueryHandle;\n\t\t}\n\n\t\tpublic int CompareTo(UGCQueryHandle_t other) {\n\t\t\treturn m_UGCQueryHandle.CompareTo(other.m_UGCQueryHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamUGC/UGCUpdateHandle_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct UGCUpdateHandle_t : System.IEquatable<UGCUpdateHandle_t>, System.IComparable<UGCUpdateHandle_t> {\n\t\tpublic static readonly UGCUpdateHandle_t Invalid = new UGCUpdateHandle_t(0xffffffffffffffff);\n\t\tpublic ulong m_UGCUpdateHandle;\n\n\t\tpublic UGCUpdateHandle_t(ulong value) {\n\t\t\tm_UGCUpdateHandle = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_UGCUpdateHandle.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is UGCUpdateHandle_t && this == (UGCUpdateHandle_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_UGCUpdateHandle.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(UGCUpdateHandle_t x, UGCUpdateHandle_t y) {\n\t\t\treturn x.m_UGCUpdateHandle == y.m_UGCUpdateHandle;\n\t\t}\n\n\t\tpublic static bool operator !=(UGCUpdateHandle_t x, UGCUpdateHandle_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator UGCUpdateHandle_t(ulong value) {\n\t\t\treturn new UGCUpdateHandle_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(UGCUpdateHandle_t that) {\n\t\t\treturn that.m_UGCUpdateHandle;\n\t\t}\n\n\t\tpublic bool Equals(UGCUpdateHandle_t other) {\n\t\t\treturn m_UGCUpdateHandle == other.m_UGCUpdateHandle;\n\t\t}\n\n\t\tpublic int CompareTo(UGCUpdateHandle_t other) {\n\t\t\treturn m_UGCUpdateHandle.CompareTo(other.m_UGCUpdateHandle);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamUnifiedMessages/ClientUnifiedMessageHandle.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\n#endif // !DISABLESTEAMWORKS\n\n// This file is no longer needed. Valve has removed the functionality.\n// We continue to generate this file to provide a small amount of backwards compatability.\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamUserStats/SteamLeaderboardEntries_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamLeaderboardEntries_t : System.IEquatable<SteamLeaderboardEntries_t>, System.IComparable<SteamLeaderboardEntries_t> {\n\t\tpublic ulong m_SteamLeaderboardEntries;\n\n\t\tpublic SteamLeaderboardEntries_t(ulong value) {\n\t\t\tm_SteamLeaderboardEntries = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamLeaderboardEntries.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamLeaderboardEntries_t && this == (SteamLeaderboardEntries_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamLeaderboardEntries.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamLeaderboardEntries_t x, SteamLeaderboardEntries_t y) {\n\t\t\treturn x.m_SteamLeaderboardEntries == y.m_SteamLeaderboardEntries;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamLeaderboardEntries_t x, SteamLeaderboardEntries_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamLeaderboardEntries_t(ulong value) {\n\t\t\treturn new SteamLeaderboardEntries_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SteamLeaderboardEntries_t that) {\n\t\t\treturn that.m_SteamLeaderboardEntries;\n\t\t}\n\n\t\tpublic bool Equals(SteamLeaderboardEntries_t other) {\n\t\t\treturn m_SteamLeaderboardEntries == other.m_SteamLeaderboardEntries;\n\t\t}\n\n\t\tpublic int CompareTo(SteamLeaderboardEntries_t other) {\n\t\t\treturn m_SteamLeaderboardEntries.CompareTo(other.m_SteamLeaderboardEntries);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/SteamUserStats/SteamLeaderboard_t.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct SteamLeaderboard_t : System.IEquatable<SteamLeaderboard_t>, System.IComparable<SteamLeaderboard_t> {\n\t\tpublic ulong m_SteamLeaderboard;\n\n\t\tpublic SteamLeaderboard_t(ulong value) {\n\t\t\tm_SteamLeaderboard = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_SteamLeaderboard.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is SteamLeaderboard_t && this == (SteamLeaderboard_t)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_SteamLeaderboard.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(SteamLeaderboard_t x, SteamLeaderboard_t y) {\n\t\t\treturn x.m_SteamLeaderboard == y.m_SteamLeaderboard;\n\t\t}\n\n\t\tpublic static bool operator !=(SteamLeaderboard_t x, SteamLeaderboard_t y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator SteamLeaderboard_t(ulong value) {\n\t\t\treturn new SteamLeaderboard_t(value);\n\t\t}\n\n\t\tpublic static explicit operator ulong(SteamLeaderboard_t that) {\n\t\t\treturn that.m_SteamLeaderboard;\n\t\t}\n\n\t\tpublic bool Equals(SteamLeaderboard_t other) {\n\t\t\treturn m_SteamLeaderboard == other.m_SteamLeaderboard;\n\t\t}\n\n\t\tpublic int CompareTo(SteamLeaderboard_t other) {\n\t\t\treturn m_SteamLeaderboard.CompareTo(other.m_SteamLeaderboard);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/Steam_api_common/HSteamPipe.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HSteamPipe : System.IEquatable<HSteamPipe>, System.IComparable<HSteamPipe> {\n\t\tpublic int m_HSteamPipe;\n\n\t\tpublic HSteamPipe(int value) {\n\t\t\tm_HSteamPipe = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HSteamPipe.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HSteamPipe && this == (HSteamPipe)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HSteamPipe.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HSteamPipe x, HSteamPipe y) {\n\t\t\treturn x.m_HSteamPipe == y.m_HSteamPipe;\n\t\t}\n\n\t\tpublic static bool operator !=(HSteamPipe x, HSteamPipe y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HSteamPipe(int value) {\n\t\t\treturn new HSteamPipe(value);\n\t\t}\n\n\t\tpublic static explicit operator int(HSteamPipe that) {\n\t\t\treturn that.m_HSteamPipe;\n\t\t}\n\n\t\tpublic bool Equals(HSteamPipe other) {\n\t\t\treturn m_HSteamPipe == other.m_HSteamPipe;\n\t\t}\n\n\t\tpublic int CompareTo(HSteamPipe other) {\n\t\t\treturn m_HSteamPipe.CompareTo(other.m_HSteamPipe);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/Steamworks.NET/types/Steam_api_common/HSteamUser.cs",
    "content": "// This file is provided under The MIT License as part of Steamworks.NET.\n// Copyright (c) 2013-2019 Riley Labrecque\n// Please see the included LICENSE.txt for additional information.\n\n// This file is automatically generated.\n// Changes to this file will be reverted when you update Steamworks.NET\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH\n\t#define DISABLESTEAMWORKS\n#endif\n\n#if !DISABLESTEAMWORKS\n\nusing System.Runtime.InteropServices;\nusing IntPtr = System.IntPtr;\n\nnamespace Steamworks {\n\t[System.Serializable]\n\tpublic struct HSteamUser : System.IEquatable<HSteamUser>, System.IComparable<HSteamUser> {\n\t\tpublic int m_HSteamUser;\n\n\t\tpublic HSteamUser(int value) {\n\t\t\tm_HSteamUser = value;\n\t\t}\n\n\t\tpublic override string ToString() {\n\t\t\treturn m_HSteamUser.ToString();\n\t\t}\n\n\t\tpublic override bool Equals(object other) {\n\t\t\treturn other is HSteamUser && this == (HSteamUser)other;\n\t\t}\n\n\t\tpublic override int GetHashCode() {\n\t\t\treturn m_HSteamUser.GetHashCode();\n\t\t}\n\n\t\tpublic static bool operator ==(HSteamUser x, HSteamUser y) {\n\t\t\treturn x.m_HSteamUser == y.m_HSteamUser;\n\t\t}\n\n\t\tpublic static bool operator !=(HSteamUser x, HSteamUser y) {\n\t\t\treturn !(x == y);\n\t\t}\n\n\t\tpublic static explicit operator HSteamUser(int value) {\n\t\t\treturn new HSteamUser(value);\n\t\t}\n\n\t\tpublic static explicit operator int(HSteamUser that) {\n\t\t\treturn that.m_HSteamUser;\n\t\t}\n\n\t\tpublic bool Equals(HSteamUser other) {\n\t\t\treturn m_HSteamUser == other.m_HSteamUser;\n\t\t}\n\n\t\tpublic int CompareTo(HSteamUser other) {\n\t\t\treturn m_HSteamUser.CompareTo(other.m_HSteamUser);\n\t\t}\n\t}\n}\n\n#endif // !DISABLESTEAMWORKS\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/ActionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class ActionTypes\n    {\n        public const string ACTION_NONE = \"None\";\n        public const string ACTION_WIN = \"Win\";\n        public const string ACTION_LOSE = \"Lose\";\n        public const string ACTION_BEGIN_PRODUCTION = \"Production\";\n        public const string ACTION_CREATE_TEAM = \"Create Team\";\n        public const string ACTION_DESTROY_TEAM = \"Dstry Teams\";\n        public const string ACTION_ALL_HUNT = \"All to Hunt\";\n        public const string ACTION_REINFORCEMENTS = \"Reinforce.\";\n        public const string ACTION_DZ = \"DZ at 'Z'\";\n        public const string ACTION_AIRSTRIKE = \"Airstrike\";\n        public const string ACTION_NUKE = \"Nuclear Missile\";\n        public const string ACTION_ION = \"Ion Cannon\";\n        public const string ACTION_DESTROY_XXXX = \"Dstry Trig 'XXXX'\";\n        public const string ACTION_DESTROY_YYYY = \"Dstry Trig 'YYYY'\";\n        public const string ACTION_DESTROY_ZZZZ = \"Dstry Trig 'ZZZZ'\";\n        public const string ACTION_AUTOCREATE = \"Autocreate\";\n        public const string ACTION_WINLOSE = \"Cap=Win/Des=Lose\";\n        public const string ACTION_ALLOWWIN = \"Allow Win\";\n\n        private static readonly string[] Types;\n\n        static ActionTypes()\n        {\n            Types =\n                (from field in typeof(ActionTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsLiteral && !field.IsInitOnly && typeof(string).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as string).ToArray();\n        }\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/BasicSection.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.ComponentModel;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public class BasicSection : Model.BasicSection\n    {\n        private int buildLevel;\n        [DefaultValue(99)]\n        public int BuildLevel { get => buildLevel; set => SetField(ref buildLevel, value); }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/BuildingTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class BuildingTypes\n    {\n        public static readonly BuildingType Weapon = new BuildingType(0, \"weap\", \"TEXT_STRUCTURE_TITLE_GDI_WEAPONS_FACTORY\", new bool[3, 3] { { false, false, false }, { true, true, true }, { true, true, true } }, true, \"Goodguy\", false, false, \"weap2\");\n        public static readonly BuildingType GTower = new BuildingType(1, \"gtwr\", \"TEXT_STRUCTURE_TITLE_GDI_GUARD_TOWER\", new bool[1, 1] { { true } }, false, \"Goodguy\");\n        public static readonly BuildingType ATower = new BuildingType(2, \"atwr\", \"TEXT_STRUCTURE_TITLE_GDI_ADV_GUARD_TOWER\", new bool[2, 1] { { false }, { true } }, false, \"Goodguy\");\n        public static readonly BuildingType Obelisk = new BuildingType(3, \"obli\", \"TEXT_STRUCTURE_TITLE_NOD_OBELISK\", new bool[2, 1] { { false }, { true } }, false, \"Badguy\");\n        public static readonly BuildingType Command = new BuildingType(4, \"hq\", \"TEXT_STRUCTURE_TITLE_GDI_COMM_CENTER\", new bool[2, 2] { { true, false }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Turret = new BuildingType(5, \"gun\", \"TEXT_STRUCTURE_TITLE_NOD_TURRET\", new bool[1, 1] { { true } }, false, \"Badguy\", false, true);\n        public static readonly BuildingType Const = new BuildingType(6, \"fact\", \"TEXT_STRUCTURE_RA_FACT\", new bool[2, 3] { { true, true, true }, { true, true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Refinery = new BuildingType(7, \"proc\", \"TEXT_STRUCTURE_TITLE_GDI_REFINERY\", new bool[3, 3] { { false, true, false }, { true, true, true }, { false, false, false } }, true, \"Goodguy\");\n        public static readonly BuildingType Storage = new BuildingType(8, \"silo\", \"TEXT_STRUCTURE_TITLE_GDI_SILO\", new bool[1, 2] { { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Helipad = new BuildingType(9, \"hpad\", \"TEXT_STRUCTURE_TITLE_GDI_HELIPAD\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType SAM = new BuildingType(10, \"sam\", \"TEXT_STRUCTURE_TITLE_NOD_SAM_SITE\", new bool[1, 2] { { true, true } }, false, \"Badguy\");\n        public static readonly BuildingType AirStrip = new BuildingType(11, \"afld\", \"TEXT_STRUCTURE_TITLE_NOD_AIRFIELD\", new bool[2, 4] { { true, true, true, true }, { true, true, true, true } }, true, \"Badguy\");\n        public static readonly BuildingType Power = new BuildingType(12, \"nuke\", \"TEXT_STRUCTURE_TITLE_GDI_POWER_PLANT\", new bool[2, 2] { { true, false }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType AdvancedPower = new BuildingType(13, \"nuk2\", \"TEXT_STRUCTURE_TITLE_GDI_ADV_POWER_PLANT\", new bool[2, 2] { { true, false }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Hospital = new BuildingType(14, \"hosp\", \"TEXT_UNIT_TITLE_HOSP\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Barracks = new BuildingType(15, \"pyle\", \"TEXT_STRUCTURE_TITLE_GDI_BARRACKS\", new bool[2, 2] { { true, true }, { false, false } }, true, \"Goodguy\");\n        public static readonly BuildingType Tanker = new BuildingType(16, \"arco\", \"TEXT_UNIT_TITLE_ARCO\", new bool[1, 2] { { true, true } }, false, \"Goodguy\");\n        public static readonly BuildingType Repair = new BuildingType(17, \"fix\", \"TEXT_STRUCTURE_TITLE_GDI_REPAIR_FACILITY\", new bool[3, 3] { { false, true, false }, { true, true, true }, { false, true, false} }, true, \"Goodguy\");\n        public static readonly BuildingType BioLab = new BuildingType(18, \"bio\", \"TEXT_UNIT_TITLE_BIO\", new bool[2, 2] { { true, true }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Hand = new BuildingType(19, \"hand\", \"TEXT_STRUCTURE_TITLE_NOD_HAND_OF_NOD\", new bool[3, 2] { { false, false }, { true, true }, { false, true } }, true, \"Badguy\");\n        public static readonly BuildingType Temple = new BuildingType(20, \"tmpl\", \"TEXT_STRUCTURE_TITLE_NOD_TEMPLE_OF_NOD\", new bool[3, 3] { { false, false, false }, { true, true, true }, { true, true, true } }, true, \"Badguy\");\n        public static readonly BuildingType Eye = new BuildingType(21, \"eye\", \"TEXT_STRUCTURE_TITLE_GDI_ADV_COMM_CENTER\", new bool[2, 2] { { true, false }, { true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType Mission = new BuildingType(22, \"miss\", \"TEXT_STRUCTURE_TITLE_CIV35\", new bool[2, 3] { { true, true, true }, { true, true, true } }, true, \"Goodguy\");\n        public static readonly BuildingType V01 = new BuildingType(23, \"v01\", \"TEXT_STRUCTURE_TITLE_CIV1\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V02 = new BuildingType(24, \"v02\", \"TEXT_STRUCTURE_TITLE_CIV2\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V03 = new BuildingType(25, \"v03\", \"TEXT_STRUCTURE_TITLE_CIV3\", new bool[2, 2] { { false, true }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V04 = new BuildingType(26, \"v04\", \"TEXT_STRUCTURE_TITLE_CIV4\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V05 = new BuildingType(27, \"v05\", \"TEXT_STRUCTURE_TITLE_CIV5\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V06 = new BuildingType(28, \"v06\", \"TEXT_STRUCTURE_TITLE_CIV6\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V07 = new BuildingType(29, \"v07\", \"TEXT_STRUCTURE_TITLE_CIV7\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V08 = new BuildingType(30, \"v08\", \"TEXT_STRUCTURE_TITLE_CIV8\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V09 = new BuildingType(31, \"v09\", \"TEXT_STRUCTURE_TITLE_CIV9\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V10 = new BuildingType(32, \"v10\", \"TEXT_STRUCTURE_TITLE_CIV10\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V11 = new BuildingType(33, \"v11\", \"TEXT_STRUCTURE_TITLE_CIV11\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V12 = new BuildingType(34, \"v12\", \"TEXT_STRUCTURE_TITLE_CIV12\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly BuildingType V13 = new BuildingType(35, \"v13\", \"TEXT_STRUCTURE_TITLE_CIV12\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly BuildingType V14 = new BuildingType(36, \"v14\", \"TEXT_STRUCTURE_TITLE_CIV13\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V15 = new BuildingType(37, \"v15\", \"TEXT_STRUCTURE_TITLE_CIV14\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V16 = new BuildingType(38, \"v16\", \"TEXT_STRUCTURE_TITLE_CIV15\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V17 = new BuildingType(39, \"v17\", \"TEXT_STRUCTURE_TITLE_CIV16\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V18 = new BuildingType(40, \"v18\", \"TEXT_STRUCTURE_TITLE_CIV17\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly BuildingType V19 = new BuildingType(41, \"v19\", \"TEXT_STRUCTURE_CIVILIAN_TITLE\", new bool[1, 1] { { true } }, false, \"Neutral\");\n        public static readonly BuildingType V20 = new BuildingType(42, \"v20\", \"TEXT_STRUCTURE_TITLE_CIV18\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V21 = new BuildingType(43, \"v21\", \"TEXT_STRUCTURE_TITLE_CIV19\", new bool[2, 2] { { true, true }, { false, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V22 = new BuildingType(44, \"v22\", \"TEXT_STRUCTURE_TITLE_CIV20\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V23 = new BuildingType(45, \"v23\", \"TEXT_STRUCTURE_TITLE_CIV21\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V24 = new BuildingType(46, \"v24\", \"TEXT_STRUCTURE_TITLE_CIV22\", new bool[2, 2] { { false, false }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V25 = new BuildingType(47, \"v25\", \"TEXT_STRUCTURE_TITLE_CIV1\", new bool[2, 2] { { false, true }, { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V26 = new BuildingType(48, \"v26\", \"TEXT_STRUCTURE_TITLE_CIV23\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V27 = new BuildingType(49, \"v27\", \"TEXT_STRUCTURE_TITLE_CIV24\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V28 = new BuildingType(50, \"v28\", \"TEXT_STRUCTURE_TITLE_CIV25\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V29 = new BuildingType(51, \"v29\", \"TEXT_STRUCTURE_TITLE_CIV26\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V30 = new BuildingType(52, \"v30\", \"TEXT_STRUCTURE_TITLE_CIV27\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V31 = new BuildingType(53, \"v31\", \"TEXT_STRUCTURE_TITLE_CIV28\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V32 = new BuildingType(54, \"v32\", \"TEXT_STRUCTURE_TITLE_CIV29\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V33 = new BuildingType(55, \"v33\", \"TEXT_STRUCTURE_TITLE_CIV30\", new bool[1, 2] { { true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V34 = new BuildingType(56, \"v34\", \"TEXT_STRUCTURE_TITLE_CIV31\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V35 = new BuildingType(57, \"v35\", \"TEXT_STRUCTURE_TITLE_CIV32\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V36 = new BuildingType(58, \"v36\", \"TEXT_STRUCTURE_TITLE_CIV33\", new bool[1, 1] { { true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n        public static readonly BuildingType V37 = new BuildingType(59, \"v37\", \"TEXT_STRUCTURE_TITLE_CIV34\", new bool[2, 4] { { false, true, true, true }, { false, true, true, true } }, false, \"Neutral\", new TheaterType[] { TheaterTypes.Desert });\n\n        private static readonly BuildingType[] Types;\n\n        static BuildingTypes()\n        {\n            Types =\n                (from field in typeof(BuildingTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(BuildingType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as BuildingType).ToArray();\n        }\n\n        public static IEnumerable<BuildingType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/Constants.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Drawing;\nusing System.IO;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class Constants\n    {\n        public static readonly string SaveDirectory = Path.Combine(Globals.RootSaveDirectory, \"Tiberian_Dawn\");\n\n        public static readonly Size MaxSize = new Size(64, 64);\n\n        public const int MaxAircraft = 100;\n        public const int MaxBuildings = 500;\n        public const int MaxInfantry = 500;\n        public const int MaxTerrain = 500;\n        public const int MaxUnits = 500;\n        public const int MaxTeams = 60;\n        public const int MaxTriggers = 80;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/DirectionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class DirectionTypes\n    {\n        public static readonly DirectionType North = new DirectionType(0, \"North\", FacingType.North);\n        public static readonly DirectionType NorthNorthEast = new DirectionType(16, \"North-NorthEast\");\n        public static readonly DirectionType NorthEast = new DirectionType(32, \"NorthEast\", FacingType.NorthEast);\n        public static readonly DirectionType EastNorthEast = new DirectionType(48, \"East-NorthEast\");\n        public static readonly DirectionType East = new DirectionType(64, \"East\", FacingType.East);\n        public static readonly DirectionType EastSouthEast = new DirectionType(80, \"East-SouthEast\");\n        public static readonly DirectionType SouthEast = new DirectionType(96, \"SouthEast\", FacingType.SouthEast);\n        public static readonly DirectionType SouthSouthEast = new DirectionType(112, \"South-SouthEast\");\n        public static readonly DirectionType South = new DirectionType(128, \"South\", FacingType.South);\n        public static readonly DirectionType SouthSouthWest = new DirectionType(144, \"South-SouthWest\");\n        public static readonly DirectionType SouthWest = new DirectionType(160, \"SouthWest\", FacingType.SouthWest);\n        public static readonly DirectionType WestSouthWest = new DirectionType(176, \"West-SouthWest\");\n        public static readonly DirectionType West = new DirectionType(192, \"West\", FacingType.West);\n        public static readonly DirectionType WestNorthWest = new DirectionType(208, \"West-NorthWest\");\n        public static readonly DirectionType NorthWest = new DirectionType(224, \"NorthWest\", FacingType.NorthWest);\n        public static readonly DirectionType NorthNorthWest = new DirectionType(240, \"North-NorthWest\");\n\n        private static DirectionType[] Types;\n\n        static DirectionTypes()\n        {\n            Types =\n                (from field in typeof(DirectionTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(DirectionType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as DirectionType).ToArray();\n        }\n\n        public static IEnumerable<DirectionType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/EventTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class EventTypes\n    {\n        public const string EVENT_NONE = \"None\";\n        public const string EVENT_PLAYER_ENTERED = \"Player Enters\";\n        public const string EVENT_DISCOVERED = \"Discovered\";\n        public const string EVENT_ATTACKED = \"Attacked\";\n        public const string EVENT_DESTROYED = \"Destroyed\";\n        public const string EVENT_ANY = \"Any\";\n        public const string EVENT_HOUSE_DISCOVERED = \"House Discov.\";\n        public const string EVENT_UNITS_DESTROYED = \"Units Destr.\";\n        public const string EVENT_BUILDINGS_DESTROYED = \"Bldgs Destr.\";\n        public const string EVENT_ALL_DESTROYED = \"All Destr.\";\n        public const string EVENT_CREDITS = \"Credits\";\n        public const string EVENT_TIME = \"Time\";\n        public const string EVENT_NBUILDINGS_DESTROYED = \"# Bldgs Dstr.\";\n        public const string EVENT_NUNITS_DESTROYED = \"# Units Dstr.\";\n        public const string EVENT_NOFACTORIES = \"No Factories\";\n        public const string EVENT_EVAC_CIVILIAN = \"Civ. Evac.\";\n        public const string EVENT_BUILD = \"Built It\";\n\n        private static readonly string[] Types;\n\n        static EventTypes()\n        {\n            Types =\n                (from field in typeof(EventTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsLiteral && !field.IsInitOnly && typeof(string).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as string).ToArray();\n        }\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/GamePlugin.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing Newtonsoft.Json;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public class GamePlugin : IGamePlugin\n    {\n        private static readonly Regex MovieRegex = new Regex(@\"^(.*?\\\\)*(.*?)\\.BK2$\", RegexOptions.IgnoreCase | RegexOptions.Compiled);\n\n        private static readonly IEnumerable<ITechnoType> technoTypes;\n\n        private readonly IEnumerable<string> movieTypes;\n\n        public GameType GameType => GameType.TiberianDawn;\n\n        public Map Map { get; }\n\n        public Image MapImage { get; private set; }\n\n        public bool Dirty { get; set; }\n\n        private INISectionCollection extraSections;\n\n        static GamePlugin()\n        {\n            technoTypes = InfantryTypes.GetTypes().Cast<ITechnoType>().Concat(UnitTypes.GetTypes().Cast<ITechnoType>());\n        }\n\n        public GamePlugin(bool mapImage)\n        {\n            var playerWaypoints = Enumerable.Range(0, 8).Select(i => new Waypoint(string.Format(\"P{0}\", i), WaypointFlag.PlayerStart));\n            var generalWaypoints = Enumerable.Range(8, 17).Select(i => new Waypoint(i.ToString()));\n            var specialWaypoints = new Waypoint[] { new Waypoint(\"Flare\"), new Waypoint(\"Home\"), new Waypoint(\"Reinf.\") };\n            var waypoints = playerWaypoints.Concat(generalWaypoints).Concat(specialWaypoints);\n\n            var movies = new List<string>(new string[] { \"x\" });\n            using (var megafile = new Megafile(Path.Combine(Globals.MegafilePath, \"MOVIES_TD.MEG\")))\n            {\n                foreach (var filename in megafile)\n                {\n                    var m = MovieRegex.Match(filename);\n                    if (m.Success)\n                    {\n                        movies.Add(m.Groups[m.Groups.Count - 1].ToString());\n                    }\n                }\n            }\n            movieTypes = movies.ToArray();\n\n            var basicSection = new BasicSection();\n            basicSection.SetDefault();\n\n            var houseTypes = HouseTypes.GetTypes();\n            basicSection.Player = houseTypes.First().Name;\n\n            Map = new Map(basicSection, null, Constants.MaxSize, typeof(House),\n                houseTypes, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(), TerrainTypes.GetTypes(),\n                OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(), EventTypes.GetTypes(), ActionTypes.GetTypes(),\n                MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(),\n                BuildingTypes.GetTypes(), TeamMissionTypes.GetTypes(), waypoints, movieTypes)\n            {\n                TiberiumOrGoldValue = 25\n            };\n\n            Map.BasicSection.PropertyChanged += BasicSection_PropertyChanged;\n            Map.MapSection.PropertyChanged += MapSection_PropertyChanged;\n\n            if (mapImage)\n            {\n                MapImage = new Bitmap(Map.Metrics.Width * Globals.TileWidth, Map.Metrics.Height * Globals.TileHeight);\n            }\n        }\n\n        public GamePlugin()\n            : this(true)\n        {\n        }\n\n        public void New(string theater)\n        {\n            Map.Theater = Map.TheaterTypes.Where(t => t.Equals(theater)).FirstOrDefault() ?? TheaterTypes.Temperate;\n            Map.TopLeft = new Point(1, 1);\n            Map.Size = Map.Metrics.Size - new Size(2, 2);\n\n            UpdateBasePlayerHouse();\n\n            Dirty = true;\n        }\n\n        public IEnumerable<string> Load(string path, FileType fileType)\n        {\n            var errors = new List<string>();\n            switch (fileType)\n            {\n                case FileType.INI:\n                case FileType.BIN:\n                    {\n                        var iniPath = Path.ChangeExtension(path, \".ini\");\n                        var binPath = Path.ChangeExtension(path, \".bin\");\n                        var ini = new INI();\n                        using (var iniReader = new StreamReader(iniPath))\n                        using (var binReader = new BinaryReader(new FileStream(binPath, FileMode.Open, FileAccess.Read)))\n                        {\n                            ini.Parse(iniReader);\n                            errors.AddRange(LoadINI(ini));\n                            LoadBinary(binReader);\n                        }\n                    }\n                    break;\n                case FileType.MEG:\n                case FileType.PGM:\n                    {\n                        using (var megafile = new Megafile(path))\n                        {\n                            var iniFile = megafile.Where(p => Path.GetExtension(p).ToLower() == \".ini\").FirstOrDefault();\n                            var binFile = megafile.Where(p => Path.GetExtension(p).ToLower() == \".bin\").FirstOrDefault();\n                            if ((iniFile != null) && (binFile != null))\n                            {\n                                var ini = new INI();\n                                using (var iniReader = new StreamReader(megafile.Open(iniFile)))\n                                using (var binReader = new BinaryReader(megafile.Open(binFile)))\n                                {\n                                    ini.Parse(iniReader);\n                                    errors.AddRange(LoadINI(ini));\n                                    LoadBinary(binReader);\n                                }\n                            }\n                        }\n                    }\n                    break;\n                default:\n                    throw new NotSupportedException();\n            }\n            return errors;\n        }\n\n        private IEnumerable<string> LoadINI(INI ini)\n        {\n            var errors = new List<string>();\n\n            Map.BeginUpdate();\n\n            var basicSection = ini.Sections.Extract(\"Basic\");\n            if (basicSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, false), basicSection, Map.BasicSection);\n            }\n\n            Map.BasicSection.Player = Map.HouseTypes.Where(t => t.Equals(Map.BasicSection.Player)).FirstOrDefault()?.Name ?? Map.HouseTypes.First().Name;\n\n            var mapSection = ini.Sections.Extract(\"Map\");\n            if (mapSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, false), mapSection, Map.MapSection);\n            }\n\n            var briefingSection = ini.Sections.Extract(\"Briefing\");\n            if (briefingSection != null)\n            {\n                if (briefingSection.Keys.Contains(\"Text\"))\n                {\n                    Map.BriefingSection.Briefing = briefingSection[\"Text\"].Replace(\"@\", Environment.NewLine);\n                }\n                else\n                {\n                    Map.BriefingSection.Briefing = string.Join(\" \", briefingSection.Keys.Select(k => k.Value)).Replace(\"@\", Environment.NewLine);\n                }\n            }\n\n            var steamSection = ini.Sections.Extract(\"Steam\");\n            if (steamSection != null)\n            {\n                INI.ParseSection(new MapContext(Map, false), steamSection, Map.SteamSection);\n            }\n\n            var teamTypesSection = ini.Sections.Extract(\"TeamTypes\");\n            if (teamTypesSection != null)\n            {\n                foreach (var (Key, Value) in teamTypesSection)\n                {\n                    try\n                    {\n                        var teamType = new TeamType { Name = Key };\n\n                        var tokens = Value.Split(',').ToList();\n                        teamType.House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(); tokens.RemoveAt(0);\n                        teamType.IsRoundAbout = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        teamType.IsLearning = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        teamType.IsSuicide = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        teamType.IsAutocreate = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        teamType.IsMercenary = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        teamType.RecruitPriority = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.MaxAllowed = byte.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.InitNum = byte.Parse(tokens[0]); tokens.RemoveAt(0);\n                        teamType.Fear = byte.Parse(tokens[0]); tokens.RemoveAt(0);\n\n                        var numClasses = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        for (int i = 0; i < Math.Min(Globals.MaxTeamClasses, numClasses); ++i)\n                        {\n                            var classTokens = tokens[0].Split(':'); tokens.RemoveAt(0);\n                            if (classTokens.Length == 2)\n                            {\n                                var type = technoTypes.Where(t => t.Equals(classTokens[0])).FirstOrDefault();\n                                var count = byte.Parse(classTokens[1]);\n                                if (type != null)\n                                {\n                                    teamType.Classes.Add(new TeamTypeClass { Type = type, Count = count });\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Team '{0}' references unknown class '{1}'\", Key, classTokens[0]));\n                                }\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Team '{0}' has wrong number of tokens for class index {1} (expecting 2)\", Key, i));\n                            }\n                        }\n\n                        var numMissions = int.Parse(tokens[0]); tokens.RemoveAt(0);\n                        for (int i = 0; i < Math.Min(Globals.MaxTeamMissions, numMissions); ++i)\n                        {\n                            var missionTokens = tokens[0].Split(':'); tokens.RemoveAt(0);\n                            if (missionTokens.Length == 2)\n                            {\n                                teamType.Missions.Add(new TeamTypeMission { Mission = missionTokens[0], Argument = int.Parse(missionTokens[1]) });\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Team '{0}' has wrong number of tokens for mission index {1} (expecting 2)\", Key, i));\n                            }\n                        }\n\n                        if (tokens.Count > 0)\n                        {\n                            teamType.IsReinforcable = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        }\n\n                        if (tokens.Count > 0)\n                        {\n                            teamType.IsPrebuilt = int.Parse(tokens[0]) != 0; tokens.RemoveAt(0);\n                        }\n\n                        Map.TeamTypes.Add(teamType);\n                    }\n                    catch (ArgumentOutOfRangeException) { }\n                }\n            }\n\n            var triggersSection = ini.Sections.Extract(\"Triggers\");\n            if (triggersSection != null)\n            {\n                foreach (var (Key, Value) in triggersSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length >= 5)\n                    {\n                        var trigger = new Trigger { Name = Key };\n\n                        trigger.Event1.EventType = tokens[0];\n                        trigger.Event1.Data = long.Parse(tokens[2]);\n                        trigger.Action1.ActionType = tokens[1];\n                        trigger.House = Map.HouseTypes.Where(t => t.Equals(tokens[3])).FirstOrDefault()?.Name ?? \"None\";\n                        trigger.Action1.Team = tokens[4];\n                        trigger.PersistantType = TriggerPersistantType.Volatile;\n\n                        if (tokens.Length >= 6)\n                        {\n                            trigger.PersistantType = (TriggerPersistantType)int.Parse(tokens[5]);\n                        }\n\n                        Map.Triggers.Add(trigger);\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Trigger '{0}' has too few tokens (expecting at least 5)\", Key));\n                    }\n                }\n            }\n\n            var terrainSection = ini.Sections.Extract(\"Terrain\");\n            if (terrainSection != null)\n            {\n                foreach (var (Key, Value) in terrainSection)\n                {\n                    var cell = int.Parse(Key);\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 2)\n                    {\n                        var terrainType = Map.TerrainTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();\n                        if (terrainType != null)\n                        {\n                            if (!Map.Technos.Add(cell, new Terrain\n                                {\n                                    Type = terrainType,\n                                    Icon = terrainType.IsTransformable ? 22 : 0,\n                                    Trigger = tokens[1]\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[0], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[0], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[0], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps infantry in cell {1}, skipping\", tokens[0], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[0], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Terrain '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[0], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Terrain '{0}' references unknown terrain\", tokens[0]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Terrain '{0}' has wrong number of tokens (expecting 2)\", Key));\n                    }\n                }\n            }\n\n            var overlaySection = ini.Sections.Extract(\"Overlay\");\n            if (overlaySection != null)\n            {\n                foreach (var (Key, Value) in overlaySection)\n                {\n                    var cell = int.Parse(Key);\n                    var overlayType = Map.OverlayTypes.Where(t => t.Equals(Value)).FirstOrDefault();\n                    if (overlayType != null)\n                    {\n                        Map.Overlay[cell] = new Overlay { Type = overlayType, Icon = 0 };\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Overlay '{0}' references unknown overlay\", Value));\n                    }\n                }\n            }\n\n            var smudgeSection = ini.Sections.Extract(\"Smudge\");\n            if (smudgeSection != null)\n            {\n                foreach (var (Key, Value) in smudgeSection)\n                {\n                    var cell = int.Parse(Key);\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 3)\n                    {\n                        var smudgeType = Map.SmudgeTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();\n                        if (smudgeType != null)\n                        {\n                            if (((smudgeType.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))\n                            {\n                                Map.Smudge[cell] = new Smudge\n                                {\n                                    Type = smudgeType,\n                                    Icon = 0,\n                                    Data = int.Parse(tokens[2])\n                                };\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Smudge '{0}' is a bib, skipped\", tokens[0]));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Smudge '{0}' references unknown smudge\", tokens[0]));\n                        }\n                    }\n                }\n            }\n\n            var infantrySections = ini.Sections.Extract(\"Infantry\");\n            if (infantrySections != null)\n            {\n                foreach (var (_, Value) in infantrySections)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 8)\n                    {\n                        var infantryType = Map.InfantryTypes.Where(t => t.Equals(tokens[1])).FirstOrDefault();\n                        if (infantryType != null)\n                        {\n                            var cell = int.Parse(tokens[3]);\n                            var infantryGroup = Map.Technos[cell] as InfantryGroup;\n                            if ((infantryGroup == null) && (Map.Technos[cell] == null))\n                            {\n                                infantryGroup = new InfantryGroup();\n                                Map.Technos.Add(cell, infantryGroup);\n                            }\n\n                            if (infantryGroup != null)\n                            {\n                                var stoppingPos = int.Parse(tokens[4]);\n                                if (stoppingPos < Globals.NumInfantryStops)\n                                {\n                                    var direction = (byte)((int.Parse(tokens[6]) + 0x08) & ~0x0F);\n\n                                    if (infantryGroup.Infantry[stoppingPos] == null)\n                                    {\n                                        infantryGroup.Infantry[stoppingPos] = new Infantry(infantryGroup)\n                                        {\n                                            Type = infantryType,\n                                            House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                            Strength = int.Parse(tokens[2]),\n                                            Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                            Mission = Map.MissionTypes.Where(t => t.Equals(tokens[5])).FirstOrDefault(),\n                                            Trigger = tokens[7]\n                                        };\n                                    }\n                                    else\n                                    {\n                                        errors.Add(string.Format(\"Infantry '{0}' overlaps another infantry at position {1} in cell {2}, skipping\", tokens[1], stoppingPos, cell));\n                                    }\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' has invalid position {1} in cell {2}, skipping\", tokens[1], stoppingPos, cell));\n                                }\n                            }\n                            else\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Infantry '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Infantry '{0}' references unknown infantry\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Infantry '{0}' has wrong number of tokens (expecting 8)\", tokens[1]));\n                    }\n                }\n            }\n\n            var unitsSections = ini.Sections.Extract(\"Units\");\n            if (unitsSections != null)\n            {\n                foreach (var (_, Value) in unitsSections)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 7)\n                    {\n                        var unitType = Map.UnitTypes.Where(t => t.IsUnit && t.Equals(tokens[1])).FirstOrDefault();\n                        if (unitType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Technos.Add(cell, new Unit()\n                                {\n                                    Type = unitType,\n                                    House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                    Strength = int.Parse(tokens[2]),\n                                    Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                    Mission = Map.MissionTypes.Where(t => t.Equals(tokens[5])).FirstOrDefault(),\n                                    Trigger = tokens[6]\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Unit '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Unit '{0}' references unknown unit\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Unit '{0}' has wrong number of tokens (expecting 7)\", tokens[1]));\n                    }\n                }\n            }\n\n            var aircraftSections = ini.Sections.Extract(\"Aircraft\");\n            if (aircraftSections != null)\n            {\n                foreach (var (_, Value) in aircraftSections)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 6)\n                    {\n                        var aircraftType = Map.UnitTypes.Where(t => t.IsAircraft && t.Equals(tokens[1])).FirstOrDefault();\n                        if (aircraftType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Technos.Add(cell, new Unit()\n                                {\n                                    Type = aircraftType,\n                                    House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                    Strength = int.Parse(tokens[2]),\n                                    Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                    Mission = Map.MissionTypes.Where(t => t.Equals(tokens[5])).FirstOrDefault()\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Aircraft '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Aircraft '{0}' references unknown aircraft\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Aircraft '{0}' has wrong number of tokens (expecting 6)\", tokens[1]));\n                    }\n                }\n            }\n\n            var structuresSection = ini.Sections.Extract(\"Structures\");\n            if (structuresSection != null)\n            {\n                foreach (var (_, Value) in structuresSection)\n                {\n                    var tokens = Value.Split(',');\n                    if (tokens.Length == 6)\n                    {\n                        var buildingType = Map.BuildingTypes.Where(t => t.Equals(tokens[1])).FirstOrDefault();\n                        if (buildingType != null)\n                        {\n                            var direction = (byte)((int.Parse(tokens[4]) + 0x08) & ~0x0F);\n\n                            var cell = int.Parse(tokens[3]);\n                            if (!Map.Buildings.Add(cell, new Building()\n                            {\n                                Type = buildingType,\n                                House = Map.HouseTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault(),\n                                Strength = int.Parse(tokens[2]),\n                                Direction = Map.DirectionTypes.Where(d => d.Equals(direction)).FirstOrDefault(),\n                                Trigger = tokens[5]\n                                }))\n                            {\n                                var techno = Map.Technos[cell];\n                                if (techno is Building building)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps structure '{1}' in cell {2}, skipping\", tokens[1], building.Type.Name, cell));\n                                }\n                                else if (techno is Overlay overlay)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps overlay '{1}' in cell {2}, skipping\", tokens[1], overlay.Type.Name, cell));\n                                }\n                                else if (techno is Terrain terrain)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps terrain '{1}' in cell {2}, skipping\", tokens[1], terrain.Type.Name, cell));\n                                }\n                                else if (techno is InfantryGroup infantry)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps infantry in cell {1}, skipping\", tokens[1], cell));\n                                }\n                                else if (techno is Unit unit)\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps unit '{1}' in cell {2}, skipping\", tokens[1], unit.Type.Name, cell));\n                                }\n                                else\n                                {\n                                    errors.Add(string.Format(\"Structure '{0}' overlaps unknown techno in cell {1}, skipping\", tokens[1], cell));\n                                }\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Structure '{0}' references unknown structure\", tokens[1]));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Structure '{0}' has wrong number of tokens (expecting 6)\", tokens[1]));\n                    }\n                }\n            }\n\n            var baseSection = ini.Sections.Extract(\"Base\");\n            if (baseSection != null)\n            {\n                foreach (var (Key, Value) in baseSection)\n                {\n                    if (int.TryParse(Key, out int priority))\n                    {\n                        var tokens = Value.Split(',');\n                        if (tokens.Length == 2)\n                        {\n                            var buildingType = Map.BuildingTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();\n                            if (buildingType != null)\n                            {\n                                var coord = int.Parse(tokens[1]);\n                                var location = new Point((coord >> 8) & 0x3F, (coord >> 24) & 0x3F);\n                                if (Map.Buildings.OfType<Building>().Where(x => x.Location == location).FirstOrDefault().Occupier is Building building)\n                                {\n                                    building.BasePriority = priority;\n                                }\n                                else\n                                {\n                                    Map.Buildings.Add(location, new Building()\n                                    {\n                                        Type = buildingType,\n                                        Strength = 256,\n                                        Direction = DirectionTypes.North,\n                                        BasePriority = priority,\n                                        IsPrebuilt = false\n                                    });\n                                }\n                            }\n                            else\n                            {\n                                errors.Add(string.Format(\"Base priority {0} references unknown structure '{1}'\", priority, tokens[0]));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Base priority {0} has wrong number of tokens (expecting 2)\", priority));\n                        }\n                    }\n                    else if (!Key.Equals(\"Count\", StringComparison.CurrentCultureIgnoreCase))\n                    {\n                        errors.Add(string.Format(\"Invalid base priority '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            var waypointsSection = ini.Sections.Extract(\"Waypoints\");\n            if (waypointsSection != null)\n            {\n                foreach (var (Key, Value) in waypointsSection)\n                {\n                    if (int.TryParse(Key, out int waypoint))\n                    {\n                        if (int.TryParse(Value, out int cell))\n                        {\n                            if ((waypoint >= 0) && (waypoint < Map.Waypoints.Length))\n                            {\n                                if (Map.Metrics.Contains(cell))\n                                {\n                                    Map.Waypoints[waypoint].Cell = cell;\n                                }\n                                else\n                                {\n                                    Map.Waypoints[waypoint].Cell = null;\n                                    if (cell != -1)\n                                    {\n                                        errors.Add(string.Format(\"Waypoint {0} cell value {1} out of range (expecting between {2} and {3})\", waypoint, cell, 0, Map.Metrics.Length - 1));\n                                    }\n                                }\n                            }\n                            else if (cell != -1)\n                            {\n                                errors.Add(string.Format(\"Waypoint {0} out of range (expecting between {1} and {2})\", waypoint, 0, Map.Waypoints.Length - 1));\n                            }\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Waypoint {0} has invalid cell '{1}' (expecting integer)\", waypoint, Value));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Invalid waypoint '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            var cellTriggersSection = ini.Sections.Extract(\"CellTriggers\");\n            if (cellTriggersSection != null)\n            {\n                foreach (var (Key, Value) in cellTriggersSection)\n                {\n                    if (int.TryParse(Key, out int cell))\n                    {\n                        if (Map.Metrics.Contains(cell))\n                        {\n                            Map.CellTriggers[cell] = new CellTrigger\n                            {\n                                Trigger = Value\n                            };\n                        }\n                        else\n                        {\n                            errors.Add(string.Format(\"Cell trigger {0} outside map bounds\", cell));\n                        }\n                    }\n                    else\n                    {\n                        errors.Add(string.Format(\"Invalid cell trigger '{0}' (expecting integer)\", Key));\n                    }\n                }\n            }\n\n            foreach (var house in Map.Houses)\n            {\n                if (house.Type.ID < 0)\n                {\n                    continue;\n                }\n\n                var houseSection = ini.Sections.Extract(house.Type.Name);\n                if (houseSection != null)\n                {\n                    INI.ParseSection(new MapContext(Map, false), houseSection, house);\n                    house.Enabled = true;\n                }\n                else\n                {\n                    house.Enabled = false;\n                }\n            }\n\n            UpdateBasePlayerHouse();\n\n            extraSections = ini.Sections;\n\n            Map.EndUpdate();\n\n            return errors;\n        }\n\n        private void LoadBinary(BinaryReader reader)\n        {\n            Map.Templates.Clear();\n\n            for (var y = 0; y < Map.Metrics.Height; ++y)\n            {\n                for (var x = 0; x < Map.Metrics.Width; ++x)\n                {\n                    var typeValue = reader.ReadByte();\n                    var iconValue = reader.ReadByte();\n                    var templateType = Map.TemplateTypes.Where(t => t.Equals(typeValue)).FirstOrDefault();\n                    if ((templateType != null) && !templateType.Theaters.Contains(Map.Theater))\n                    {\n                        templateType = null;\n                    }\n                    if ((templateType ?? TemplateTypes.Clear) != TemplateTypes.Clear)\n                    {\n                        if (iconValue >= templateType.NumIcons)\n                        {\n                            templateType = null;\n                        }\n                    }\n                    Map.Templates[x, y] = (templateType != null) ? new Template { Type = templateType, Icon = iconValue } : null;\n                }\n            }\n        }\n\n        public bool Save(string path, FileType fileType)\n        {\n            if (!Validate())\n            {\n                return false;\n            }\n\n            switch (fileType)\n            {\n                case FileType.INI:\n                case FileType.BIN:\n                    {\n                        var iniPath = Path.ChangeExtension(path, \".ini\");\n                        var binPath = Path.ChangeExtension(path, \".bin\");\n                        var tgaPath = Path.ChangeExtension(path, \".tga\");\n                        var jsonPath = Path.ChangeExtension(path, \".json\");\n\n                        var ini = new INI();\n                        using (var iniWriter = new StreamWriter(iniPath))\n                        using (var binStream = new FileStream(binPath, FileMode.Create))\n                        using (var binWriter = new BinaryWriter(binStream))\n                        using (var tgaStream = new FileStream(tgaPath, FileMode.Create))\n                        using (var jsonStream = new FileStream(jsonPath, FileMode.Create))\n                        using (var jsonWriter = new JsonTextWriter(new StreamWriter(jsonStream)))\n                        {\n                            SaveINI(ini, fileType);\n                            iniWriter.Write(ini.ToString());\n                            SaveBinary(binWriter);\n                            SaveMapPreview(tgaStream);\n                            SaveJSON(jsonWriter);\n                        }\n                    }\n                    break;\n                case FileType.MEG:\n                case FileType.PGM:\n                    {\n                        using (var iniStream = new MemoryStream())\n                        using (var binStream = new MemoryStream())\n                        using (var tgaStream = new MemoryStream())\n                        using (var jsonStream = new MemoryStream())\n                        using (var binWriter = new BinaryWriter(binStream))\n                        using (var jsonWriter = new JsonTextWriter(new StreamWriter(jsonStream)))\n                        using (var megafileBuilder = new MegafileBuilder(@\"\", path))\n                        {\n                            var ini = new INI();\n                            SaveINI(ini, fileType);\n                            var iniWriter = new StreamWriter(iniStream);\n                            iniWriter.Write(ini.ToString());\n                            iniWriter.Flush();\n                            iniStream.Position = 0;\n\n                            SaveBinary(binWriter);\n                            binWriter.Flush();\n                            binStream.Position = 0;\n\n                            SaveMapPreview(tgaStream);\n                            tgaStream.Position = 0;\n\n                            SaveJSON(jsonWriter);\n                            jsonWriter.Flush();\n                            jsonStream.Position = 0;\n\n                            var iniFile = Path.ChangeExtension(Path.GetFileName(path), \".ini\").ToUpper();\n                            var binFile = Path.ChangeExtension(Path.GetFileName(path), \".bin\").ToUpper();\n                            var tgaFile = Path.ChangeExtension(Path.GetFileName(path), \".tga\").ToUpper();\n                            var jsonFile = Path.ChangeExtension(Path.GetFileName(path), \".json\").ToUpper();\n\n                            megafileBuilder.AddFile(iniFile, iniStream);\n                            megafileBuilder.AddFile(binFile, binStream);\n                            megafileBuilder.AddFile(tgaFile, tgaStream);\n                            megafileBuilder.AddFile(jsonFile, jsonStream);\n                            megafileBuilder.Write();\n                        }\n                    }\n                    break;\n                default:\n                    throw new NotSupportedException();\n            }\n\n            return true;\n        }\n\n        private void SaveINI(INI ini, FileType fileType)\n        {\n            if (extraSections != null)\n            {\n                ini.Sections.AddRange(extraSections);\n            }\n\n            INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Basic\"), Map.BasicSection);\n            INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Map\"), Map.MapSection);\n\n            if (fileType != FileType.PGM)\n            {\n                INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(\"Steam\"), Map.SteamSection);\n            }\n\n            ini.Sections.Remove(\"Briefing\");\n            if (!string.IsNullOrEmpty(Map.BriefingSection.Briefing))\n            {\n                var briefingSection = ini.Sections.Add(\"Briefing\");\n                briefingSection[\"Text\"] = Map.BriefingSection.Briefing.Replace(Environment.NewLine, \"@\");\n            }\n\n            var cellTriggersSection = ini.Sections.Add(\"CellTriggers\");\n            foreach (var (cell, cellTrigger) in Map.CellTriggers)\n            {\n                cellTriggersSection[cell.ToString()] = cellTrigger.Trigger;\n            }\n\n            var teamTypesSection = ini.Sections.Add(\"TeamTypes\");\n            foreach(var teamType in Map.TeamTypes)\n            {\n                var classes = teamType.Classes\n                    .Select(c => string.Format(\"{0}:{1}\", c.Type.Name.ToLower(), c.Count))\n                    .ToArray();\n                var missions = teamType.Missions\n                    .Select(m => string.Format(\"{0}:{1}\", m.Mission, m.Argument))\n                    .ToArray();\n\n                var tokens = new List<string>\n                {\n                    teamType.House.Name,\n                    teamType.IsRoundAbout ? \"1\" : \"0\",\n                    teamType.IsLearning ? \"1\" : \"0\",\n                    teamType.IsSuicide ? \"1\" : \"0\",\n                    teamType.IsAutocreate ? \"1\" : \"0\",\n                    teamType.IsMercenary ? \"1\" : \"0\",\n                    teamType.RecruitPriority.ToString(),\n                    teamType.MaxAllowed.ToString(),\n                    teamType.InitNum.ToString(),\n                    teamType.Fear.ToString(),\n                    classes.Length.ToString(),\n                    string.Join(\",\", classes),\n                    missions.Length.ToString(),\n                    string.Join(\",\", missions),\n                    teamType.IsReinforcable ? \"1\" : \"0\",\n                    teamType.IsPrebuilt ? \"1\" : \"0\"\n                };\n\n                teamTypesSection[teamType.Name] = string.Join(\",\", tokens.Where(t => !string.IsNullOrEmpty(t)));\n            }\n\n            var triggersSection = ini.Sections.Add(\"Triggers\");\n            foreach (var trigger in Map.Triggers)\n            {\n                if (string.IsNullOrEmpty(trigger.Name))\n                {\n                    continue;\n                }\n\n                var tokens = new List<string>\n                {\n                    trigger.Event1.EventType,\n                    trigger.Action1.ActionType,\n                    trigger.Event1.Data.ToString(),\n                    trigger.House,\n                    trigger.Action1.Team,\n                    ((int)trigger.PersistantType).ToString()\n                };\n\n                triggersSection[trigger.Name] = string.Join(\",\", tokens);\n            }\n\n            var waypointsSection = ini.Sections.Add(\"Waypoints\");\n            for (var i = 0; i < Map.Waypoints.Length; ++i)\n            {\n                var waypoint = Map.Waypoints[i];\n                if (waypoint.Cell.HasValue)\n                {\n                    waypointsSection[i.ToString()] = waypoint.Cell.Value.ToString();\n                }\n            }\n\n            var baseSection = ini.Sections.Add(\"Base\");\n            var baseBuildings = Map.Buildings.OfType<Building>().Where(x => x.Occupier.BasePriority >= 0).OrderByDescending(x => x.Occupier.BasePriority).ToArray();\n            var baseIndex = baseBuildings.Length - 1;\n            foreach (var (location, building) in baseBuildings)\n            {\n                var key = baseIndex.ToString(\"D3\");\n                baseIndex--;\n\n                baseSection[key] = string.Format(\"{0},{1}\",\n                    building.Type.Name.ToUpper(),\n                    ((location.Y & 0x3F) << 24) | ((location.X & 0x3F) << 8)\n                );\n            }\n            baseSection[\"Count\"] = baseBuildings.Length.ToString();\n\n            var infantrySection = ini.Sections.Add(\"Infantry\");\n            var infantryIndex = 0;\n            foreach (var (location, infantryGroup) in Map.Technos.OfType<InfantryGroup>())\n            {\n                for (var i = 0; i < infantryGroup.Infantry.Length; ++i)\n                {\n                    var infantry = infantryGroup.Infantry[i];\n                    if (infantry == null)\n                    {\n                        continue;\n                    }\n\n                    var key = infantryIndex.ToString(\"D3\");\n                    infantryIndex++;\n\n                    Map.Metrics.GetCell(location, out int cell);\n                    infantrySection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6},{7}\",\n                        infantry.House.Name,\n                        infantry.Type.Name,\n                        infantry.Strength,\n                        cell,\n                        i,\n                        infantry.Mission,\n                        infantry.Direction.ID,\n                        infantry.Trigger\n                    );\n                }\n            }\n\n            var structuresSection = ini.Sections.Add(\"Structures\");\n            var structureIndex = 0;\n            foreach (var (location, building) in Map.Buildings.OfType<Building>().Where(x => x.Occupier.IsPrebuilt))\n            {\n                var key = structureIndex.ToString(\"D3\");\n                structureIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                structuresSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5}\",\n                    building.House.Name,\n                    building.Type.Name,\n                    building.Strength,\n                    cell,\n                    building.Direction.ID,\n                    building.Trigger\n                );\n            }\n\n            var unitsSection = ini.Sections.Add(\"Units\");\n            var unitIndex = 0;\n            foreach (var (location, unit) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsUnit))\n            {\n                var key = unitIndex.ToString(\"D3\");\n                unitIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                unitsSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5},{6}\",\n                    unit.House.Name,\n                    unit.Type.Name,\n                    unit.Strength,\n                    cell,\n                    unit.Direction.ID,\n                    unit.Mission,\n                    unit.Trigger\n                );\n            }\n\n            var aircraftSection = ini.Sections.Add(\"Aircraft\");\n            var aircraftIndex = 0;\n            foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))\n            {\n                var key = aircraftIndex.ToString(\"D3\");\n                aircraftIndex++;\n\n                Map.Metrics.GetCell(location, out int cell);\n                aircraftSection[key] = string.Format(\"{0},{1},{2},{3},{4},{5}\",\n                    aircraft.House.Name,\n                    aircraft.Type.Name,\n                    aircraft.Strength,\n                    cell,\n                    aircraft.Direction.ID,\n                    aircraft.Mission\n                );\n            }\n\n            foreach (var house in Map.Houses)\n            {\n                if ((house.Type.ID < 0) || !house.Enabled)\n                {\n                    continue;\n                }\n\n                INI.WriteSection(new MapContext(Map, false), ini.Sections.Add(house.Type.Name), house);\n            }\n\n            var overlaySection = ini.Sections.Add(\"Overlay\");\n            foreach (var (cell, overlay) in Map.Overlay)\n            {\n                overlaySection[cell.ToString()] = overlay.Type.Name;\n            }\n\n            var smudgeSection = ini.Sections.Add(\"Smudge\");\n            foreach (var (cell, smudge) in Map.Smudge.Where(item => (item.Value.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))\n            {\n                smudgeSection[cell.ToString()] = string.Format(\"{0},{1},{2}\", smudge.Type.Name, cell, smudge.Data);\n            }\n\n            var terrainSection = ini.Sections.Add(\"Terrain\");\n            foreach (var (location, terrain) in Map.Technos.OfType<Terrain>())\n            {\n                Map.Metrics.GetCell(location, out int cell);\n                terrainSection[cell.ToString()] = string.Format(\"{0},None\", terrain.Type.Name);\n            }\n        }\n\n        private void SaveBinary(BinaryWriter writer)\n        {\n            for (var y = 0; y < Map.Metrics.Height; ++y)\n            {\n                for (var x = 0; x < Map.Metrics.Width; ++x)\n                {\n                    var template = Map.Templates[x, y];\n                    if (template != null)\n                    {\n                        writer.Write((byte)template.Type.ID);\n                        writer.Write((byte)template.Icon);\n                    }\n                    else\n                    {\n                        writer.Write(byte.MaxValue);\n                        writer.Write(byte.MaxValue);\n                    }\n                }\n            }\n        }\n\n        private void SaveMapPreview(Stream stream)\n        {\n            Map.GenerateMapPreview().Save(stream);\n        }\n\n        private void SaveJSON(JsonTextWriter writer)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"MapTileX\");\n            writer.WriteValue(Map.MapSection.X);\n            writer.WritePropertyName(\"MapTileY\");\n            writer.WriteValue(Map.MapSection.Y);\n            writer.WritePropertyName(\"MapTileWidth\");\n            writer.WriteValue(Map.MapSection.Width);\n            writer.WritePropertyName(\"MapTileHeight\");\n            writer.WriteValue(Map.MapSection.Height);\n            writer.WritePropertyName(\"Theater\");\n            writer.WriteValue(Map.MapSection.Theater.Name.ToUpper());\n            writer.WritePropertyName(\"Waypoints\");\n            writer.WriteStartArray();\n            foreach (var waypoint in Map.Waypoints.Where(w => (w.Flag == WaypointFlag.PlayerStart) && w.Cell.HasValue))\n            {\n                writer.WriteValue(waypoint.Cell.Value);\n            }\n            writer.WriteEndArray();\n            writer.WriteEndObject();\n        }\n\n        private bool Validate()\n        {\n            StringBuilder sb = new StringBuilder(\"Error(s) during map validation:\");\n\n            bool ok = true;\n            int numAircraft = Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft).Count();\n            int numBuildings = Map.Buildings.OfType<Building>().Where(x => x.Occupier.IsPrebuilt).Count();\n            int numInfantry = Map.Technos.OfType<InfantryGroup>().Sum(item => item.Occupier.Infantry.Count(i => i != null));\n            int numTerrain = Map.Technos.OfType<Terrain>().Count();\n            int numUnits = Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsUnit).Count();\n            int numWaypoints = Map.Waypoints.Count(w => w.Cell.HasValue);\n\n            if (numAircraft > Constants.MaxAircraft)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of aircraft exceeded ({0} > {1})\", numAircraft, Constants.MaxAircraft));\n                ok = false;\n            }\n\n            if (numBuildings > Constants.MaxBuildings)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of structures exceeded ({0} > {1})\", numBuildings, Constants.MaxBuildings));\n                ok = false;\n            }\n\n            if (numInfantry > Constants.MaxInfantry)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of infantry exceeded ({0} > {1})\", numInfantry, Constants.MaxInfantry));\n                ok = false;\n            }\n\n            if (numTerrain > Constants.MaxTerrain)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of terrain objects exceeded ({0} > {1})\", numTerrain, Constants.MaxTerrain));\n                ok = false;\n            }\n\n            if (numUnits > Constants.MaxUnits)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of units exceeded ({0} > {1})\", numUnits, Constants.MaxUnits));\n                ok = false;\n            }\n\n            if (Map.TeamTypes.Count > Constants.MaxTeams)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of team types exceeded ({0} > {1})\", Map.TeamTypes.Count, Constants.MaxTeams));\n                ok = false;\n            }\n\n            if (Map.Triggers.Count > Constants.MaxTriggers)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Maximum number of triggers exceeded ({0} > {1})\", Map.Triggers.Count, Constants.MaxTriggers));\n                ok = false;\n            }\n\n            if (!Map.BasicSection.SoloMission && (numWaypoints < 2))\n            {\n                sb.Append(Environment.NewLine + \"Skirmish/Multiplayer maps need at least 2 waypoints for player starting locations.\");\n                ok = false;\n            }\n\n            var homeWaypoint = Map.Waypoints.Where(w => w.Equals(\"Home\")).FirstOrDefault();\n            if (Map.BasicSection.SoloMission && !homeWaypoint.Cell.HasValue)\n            {\n                sb.Append(Environment.NewLine + string.Format(\"Single-player maps need the Home waypoint to be placed.\", Map.Triggers.Count, Constants.MaxTriggers));\n                ok = false;\n            }\n\n            if (!ok)\n            {\n                MessageBox.Show(sb.ToString(), \"Validation Error\", MessageBoxButtons.OK, MessageBoxIcon.Error);\n            }\n\n            return ok;\n        }\n\n        private void BasicSection_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"Player\":\n                    {\n                        UpdateBasePlayerHouse();\n                    }\n                    break;\n            }\n        }\n\n        private void MapSection_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"Theater\":\n                    {\n                        Map.InitTheater(GameType);\n                    }\n                    break;\n            }\n        }\n\n        private void UpdateBasePlayerHouse()\n        {\n            Map.BasicSection.BasePlayer = HouseTypes.GetBasePlayer(Map.BasicSection.Player);\n\n            var basePlayer = Map.HouseTypes.Where(h => h.Equals(Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Map.HouseTypes.First();\n            foreach (var (_, building) in Map.Buildings.OfType<Building>())\n            {\n                if (!building.IsPrebuilt)\n                {\n                    building.House = basePlayer;\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    MapImage?.Dispose();\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/House.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.TiberianDawn\n{\n    public class House : Model.House\n    {\n        public House(Model.HouseType type)\n            : base(type)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/HouseTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class HouseTypes\n    {\n        public static readonly HouseType Good = new HouseType(0, \"GoodGuy\", \"GOOD\");\n        public static readonly HouseType Bad = new HouseType(1, \"BadGuy\", \"BAD_UNIT\", \"BAD_STRUCTURE\", (\"harv\", \"BAD_STRUCTURE\"), (\"mcv\", \"BAD_STRUCTURE\"));\n        public static readonly HouseType Neutral = new HouseType(2, \"Neutral\");\n        public static readonly HouseType Special = new HouseType(3, \"Special\");\n        public static readonly HouseType Multi1 = new HouseType(4, \"Multi1\", \"MULTI1\");\n        public static readonly HouseType Multi2 = new HouseType(5, \"Multi2\", \"MULTI2\");\n        public static readonly HouseType Multi3 = new HouseType(6, \"Multi3\", \"MULTI3\");\n        public static readonly HouseType Multi4 = new HouseType(7, \"Multi4\", \"MULTI4\");\n        public static readonly HouseType Multi5 = new HouseType(8, \"Multi5\", \"MULTI5\");\n        public static readonly HouseType Multi6 = new HouseType(9, \"Multi6\", \"MULTI6\");\n\n        private static readonly HouseType[] Types;\n\n        static HouseTypes()\n        {\n            Types =\n                (from field in typeof(HouseTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(HouseType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as HouseType).ToArray();\n        }\n\n        public static IEnumerable<HouseType> GetTypes()\n        {\n            return Types;\n        }\n\n        public static string GetBasePlayer(string player)\n        {\n            return Bad.Equals(player) ? Good.Name : Bad.Name;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/InfantryTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class InfantryTypes\n    {\n        public static readonly InfantryType E1 = new InfantryType(0, \"e1\", \"TEXT_UNIT_TITLE_GDI_MINIGUNNER\", \"Goodguy\");\n        public static readonly InfantryType E2 = new InfantryType(1, \"e2\", \"TEXT_UNIT_TITLE_GDI_GRENADIER\", \"Goodguy\");\n        public static readonly InfantryType E3 = new InfantryType(2, \"e3\", \"TEXT_UNIT_TITLE_GDI_ROCKET_SOLDIER\", \"Badguy\");\n        public static readonly InfantryType E4 = new InfantryType(3, \"e4\", \"TEXT_UNIT_TITLE_NOD_FLAMETHROWER\", \"Badguy\");\n        public static readonly InfantryType E5 = new InfantryType(4, \"e5\", \"TEXT_UNIT_TITLE_NOD_CHEM_WARRIOR\", \"Badguy\");\n        public static readonly InfantryType E7 = new InfantryType(5, \"e6\", \"TEXT_UNIT_TITLE_GDI_ENGINEER\", \"Goodguy\");\n        public static readonly InfantryType Commando = new InfantryType(6, \"rmbo\", \"TEXT_UNIT_TITLE_GDI_COMMANDO\", \"Goodguy\");\n        public static readonly InfantryType C1 = new InfantryType(7, \"c1\", \"TEXT_UNIT_TITLE_CIV1\", \"Neutral\");\n        public static readonly InfantryType C2 = new InfantryType(8, \"c2\", \"TEXT_UNIT_TITLE_CIV2\", \"Neutral\");\n        public static readonly InfantryType C3 = new InfantryType(9, \"c3\", \"TEXT_UNIT_TITLE_CIV3\", \"Neutral\");\n        public static readonly InfantryType C4 = new InfantryType(10, \"c4\", \"TEXT_UNIT_TITLE_CIV4\", \"Neutral\");\n        public static readonly InfantryType C5 = new InfantryType(11, \"c5\", \"TEXT_UNIT_TITLE_CIV5\", \"Neutral\");\n        public static readonly InfantryType C6 = new InfantryType(12, \"c6\", \"TEXT_UNIT_TITLE_CIV6\", \"Neutral\");\n        public static readonly InfantryType C7 = new InfantryType(13, \"c7\", \"TEXT_UNIT_TITLE_CIV7\", \"Neutral\");\n        public static readonly InfantryType C8 = new InfantryType(14, \"c8\", \"TEXT_UNIT_TITLE_CIV8\", \"Neutral\");\n        public static readonly InfantryType C9 = new InfantryType(15, \"c9\", \"TEXT_UNIT_TITLE_CIV9\", \"Neutral\");\n        public static readonly InfantryType C10 = new InfantryType(16, \"c10\", \"TEXT_UNIT_TITLE_C10\", \"Neutral\");\n        public static readonly InfantryType Moebius = new InfantryType(17, \"moebius\", \"TEXT_UNIT_TITLE_MOEBIUS\", \"Neutral\");\n        public static readonly InfantryType Delphi = new InfantryType(18, \"delphi\", \"TEXT_UNIT_TITLE_DELPHI\", \"Neutral\");\n        public static readonly InfantryType DrChan = new InfantryType(19, \"chan\", \"TEXT_UNIT_TITLE_CHAN\", \"Neutral\");\n\n        private static readonly InfantryType[] Types;\n\n        static InfantryTypes()\n        {\n            Types =\n                (from field in typeof(InfantryTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(InfantryType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as InfantryType).ToArray();\n        }\n\n        public static IEnumerable<InfantryType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/MissionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class MissionTypes\n    {\n        private static readonly string[] Types = new string[]\n        {\n            \"Sleep\",\n            \"Attack\",\n            \"Move\",\n            \"Retreat\",\n            \"Guard\",\n            \"Sticky\",\n            \"Enter\",\n            \"Capture\",\n            \"Harvest\",\n            \"Area Guard\",\n            \"Return\",\n            \"Stop\",\n            \"Ambush\",\n            \"Hunt\",\n            \"Timed Hunt\",\n            \"Unload\",\n            \"Sabotage\",\n            \"Construction\",\n            \"Selling\",\n            \"Repair\",\n            \"Rescue\",\n            \"Missile\"\n        };\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/OverlayTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class OverlayTypes\n    {\n        public static readonly OverlayType Sandbag = new OverlayType(1, \"sbag\", \"TEXT_STRUCTURE_TITLE_GDI_SANDBAGS\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Cyclone = new OverlayType(2, \"cycl\", \"TEXT_STRUCTURE_TITLE_GDI_CHAIN_LINK\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Brick = new OverlayType(3, \"brik\", \"TEXT_STRUCTURE_TITLE_GDI_CONCRETE\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Barbwire = new OverlayType(4, \"barb\", \"TEXT_STRUCTURE_RA_BARB\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Wood = new OverlayType(5, \"wood\", \"TEXT_STRUCTURE_TD_WOOD\", OverlayTypeFlag.Wall);\n        public static readonly OverlayType Tiberium1 = new OverlayType(6, \"ti1\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium2 = new OverlayType(7, \"ti2\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium3 = new OverlayType(8, \"ti3\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium4 = new OverlayType(9, \"ti4\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium5 = new OverlayType(10, \"ti5\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium6 = new OverlayType(11, \"ti6\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium7 = new OverlayType(12, \"ti7\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium8 = new OverlayType(13, \"ti8\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium9 = new OverlayType(14, \"ti9\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium10 = new OverlayType(15, \"ti10\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium11 = new OverlayType(16, \"ti11\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType Tiberium12 = new OverlayType(17, \"ti12\", OverlayTypeFlag.TiberiumOrGold);\n        public static readonly OverlayType V12 = new OverlayType(20, \"v12\", \"TEXT_STRUCTURE_TITLE_CIV12\", new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly OverlayType V13 = new OverlayType(21, \"v13\", \"TEXT_STRUCTURE_TITLE_CIV12\", new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly OverlayType V14 = new OverlayType(22, \"v14\", \"TEXT_STRUCTURE_TITLE_CIV13\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly OverlayType V15 = new OverlayType(23, \"v15\", \"TEXT_STRUCTURE_TITLE_CIV14\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly OverlayType V16 = new OverlayType(24, \"v16\", \"TEXT_STRUCTURE_TITLE_CIV15\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly OverlayType V17 = new OverlayType(25, \"v17\", \"TEXT_STRUCTURE_TITLE_CIV16\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly OverlayType V18 = new OverlayType(26, \"v18\", \"TEXT_STRUCTURE_TITLE_CIV17\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly OverlayType FlagSpot = new OverlayType(27, \"fpls\", OverlayTypeFlag.Flag);\n        public static readonly OverlayType WoodCrate = new OverlayType(28, \"wcrate\", OverlayTypeFlag.Crate);\n        public static readonly OverlayType SteelCrate = new OverlayType(29, \"scrate\", OverlayTypeFlag.Crate);\n\n        private static OverlayType[] Types;\n\n        static OverlayTypes()\n        {\n            Types =\n                (from field in typeof(OverlayTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(OverlayType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as OverlayType).ToArray();\n        }\n\n        public static IEnumerable<OverlayType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/SmudgeTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class SmudgeTypes\n    {\n        public static readonly SmudgeType Crater1 = new SmudgeType(0, \"cr1\");\n        public static readonly SmudgeType Crater2 = new SmudgeType(1, \"cr2\");\n        public static readonly SmudgeType Crater3 = new SmudgeType(2, \"cr3\");\n        public static readonly SmudgeType Crater4 = new SmudgeType(3, \"cr4\");\n        public static readonly SmudgeType Crater5 = new SmudgeType(4, \"cr5\");\n        public static readonly SmudgeType Crater6 = new SmudgeType(5, \"cr6\");\n        public static readonly SmudgeType Scorch1 = new SmudgeType(6, \"sc1\");\n        public static readonly SmudgeType Scorch2 = new SmudgeType(7, \"sc2\");\n        public static readonly SmudgeType Scorch3 = new SmudgeType(8, \"sc3\");\n        public static readonly SmudgeType Scorch4 = new SmudgeType(9, \"sc4\");\n        public static readonly SmudgeType Scorch5 = new SmudgeType(10, \"sc5\");\n        public static readonly SmudgeType Scorch6 = new SmudgeType(11, \"sc6\");\n        public static readonly SmudgeType Bib1 = new SmudgeType(12, \"bib1\", new Size(4, 2), SmudgeTypeFlag.Bib1);\n        public static readonly SmudgeType Bib2 = new SmudgeType(13, \"bib2\", new Size(3, 2), SmudgeTypeFlag.Bib2);\n        public static readonly SmudgeType Bib3 = new SmudgeType(14, \"bib3\", new Size(2, 2), SmudgeTypeFlag.Bib3);\n\n        private static SmudgeType[] Types;\n\n        static SmudgeTypes()\n        {\n            Types =\n                (from field in typeof(SmudgeTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(SmudgeType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as SmudgeType).ToArray();\n        }\n\n        public static IEnumerable<SmudgeType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/TeamMissionTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class TeamMissionTypes\n    {\n        private static readonly string[] Types = new string[]\n        {\n            \"Attack Base\",\n            \"Attack Units\",\n            \"Attack Civil.\",\n            \"Rampage\",\n            \"Defend Base\",\n            \"Move\",\n            \"Move to Cell\",\n            \"Retreat\",\n            \"Guard\",\n            \"Loop\",\n            \"Attack Tarcom\",\n            \"Unload\"\n        };\n\n        public static IEnumerable<string> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/TemplateTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class TemplateTypes\n    {\n        public static readonly TemplateType Clear = new TemplateType(0, \"clear1\", 1, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate }, TemplateTypeFlag.Clear);\n        public static readonly TemplateType Water = new TemplateType(1, \"w1\", 1, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Water2 = new TemplateType(2, \"w2\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore1 = new TemplateType(3, \"sh1\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore2 = new TemplateType(4, \"sh2\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore3 = new TemplateType(5, \"sh3\", 1, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore4 = new TemplateType(6, \"sh4\", 2, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore5 = new TemplateType(7, \"sh5\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore11 = new TemplateType(8, \"sh11\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore12 = new TemplateType(9, \"sh12\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore13 = new TemplateType(10, \"sh13\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore14 = new TemplateType(11, \"sh14\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore15 = new TemplateType(12, \"sh15\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope1 = new TemplateType(13, \"s01\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope2 = new TemplateType(14, \"s02\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope3 = new TemplateType(15, \"s03\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope4 = new TemplateType(16, \"s04\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope5 = new TemplateType(17, \"s05\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope6 = new TemplateType(18, \"s06\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope7 = new TemplateType(19, \"s07\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope8 = new TemplateType(20, \"s08\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope9 = new TemplateType(21, \"s09\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope10 = new TemplateType(22, \"s10\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope11 = new TemplateType(23, \"s11\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope12 = new TemplateType(24, \"s12\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope13 = new TemplateType(25, \"s13\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope14 = new TemplateType(26, \"s14\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope15 = new TemplateType(27, \"s15\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope16 = new TemplateType(28, \"s16\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope17 = new TemplateType(29, \"s17\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope18 = new TemplateType(30, \"s18\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope19 = new TemplateType(31, \"s19\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope20 = new TemplateType(32, \"s20\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope21 = new TemplateType(33, \"s21\", 1, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope22 = new TemplateType(34, \"s22\", 2, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope23 = new TemplateType(35, \"s23\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope24 = new TemplateType(36, \"s24\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope25 = new TemplateType(37, \"s25\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope26 = new TemplateType(38, \"s26\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope27 = new TemplateType(39, \"s27\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope28 = new TemplateType(40, \"s28\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope29 = new TemplateType(41, \"s29\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope30 = new TemplateType(42, \"s30\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope31 = new TemplateType(43, \"s31\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope32 = new TemplateType(44, \"s32\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope33 = new TemplateType(45, \"s33\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope34 = new TemplateType(46, \"s34\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope35 = new TemplateType(47, \"s35\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope36 = new TemplateType(48, \"s36\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope37 = new TemplateType(49, \"s37\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Slope38 = new TemplateType(50, \"s38\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore32 = new TemplateType(51, \"sh32\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly TemplateType Shore33 = new TemplateType(52, \"sh33\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly TemplateType Shore20 = new TemplateType(53, \"sh20\", 4, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore21 = new TemplateType(54, \"sh21\", 3, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore22 = new TemplateType(55, \"sh22\", 6, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore23 = new TemplateType(56, \"sh23\", 2, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush1 = new TemplateType(57, \"br1\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush2 = new TemplateType(58, \"br2\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush3 = new TemplateType(59, \"br3\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush4 = new TemplateType(60, \"br4\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush5 = new TemplateType(61, \"br5\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush6 = new TemplateType(62, \"br6\", 2, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush7 = new TemplateType(63, \"br7\", 2, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush8 = new TemplateType(64, \"br8\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush9 = new TemplateType(65, \"br9\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Brush10 = new TemplateType(66, \"br10\", 2, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Patch1 = new TemplateType(67, \"p01\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Patch2 = new TemplateType(68, \"p02\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Patch3 = new TemplateType(69, \"p03\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Patch4 = new TemplateType(70, \"p04\", 1, 1, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Patch5 = new TemplateType(71, \"p05\", 2, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Patch6 = new TemplateType(72, \"p06\", 6, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Patch7 = new TemplateType(73, \"p07\", 4, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Patch8 = new TemplateType(74, \"p08\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Shore16 = new TemplateType(75, \"sh16\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore17 = new TemplateType(76, \"sh17\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Shore18 = new TemplateType(77, \"sh18\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Shore19 = new TemplateType(78, \"sh19\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Patch13 = new TemplateType(79, \"p13\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Patch14 = new TemplateType(80, \"p14\", 2, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Patch15 = new TemplateType(81, \"p15\", 4, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Boulder1 = new TemplateType(82, \"b1\", 1, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Boulder2 = new TemplateType(83, \"b2\", 2, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert });\n        public static readonly TemplateType Boulder3 = new TemplateType(84, \"b3\", 3, 1, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Boulder4 = new TemplateType(85, \"b4\", 1, 1, new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly TemplateType Boulder5 = new TemplateType(86, \"b5\", 1, 1, new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly TemplateType Boulder6 = new TemplateType(87, \"b6\", 1, 1, new TheaterType[] { TheaterTypes.Temperate });\n        public static readonly TemplateType Shore6 = new TemplateType(88, \"sh6\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore7 = new TemplateType(89, \"sh7\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore8 = new TemplateType(90, \"sh8\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore9 = new TemplateType(91, \"sh9\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Shore10 = new TemplateType(92, \"sh10\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Road1 = new TemplateType(93, \"d01\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road2 = new TemplateType(94, \"d02\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road3 = new TemplateType(95, \"d03\", 1, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road4 = new TemplateType(96, \"d04\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road5 = new TemplateType(97, \"d05\", 3, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road6 = new TemplateType(98, \"d06\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road7 = new TemplateType(99, \"d07\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road8 = new TemplateType(100, \"d08\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road9 = new TemplateType(101, \"d09\", 4, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road10 = new TemplateType(102, \"d10\", 4, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road11 = new TemplateType(103, \"d11\", 2, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road12 = new TemplateType(104, \"d12\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road13 = new TemplateType(105, \"d13\", 4, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road14 = new TemplateType(106, \"d14\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road15 = new TemplateType(107, \"d15\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road16 = new TemplateType(108, \"d16\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road17 = new TemplateType(109, \"d17\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road18 = new TemplateType(110, \"d18\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road19 = new TemplateType(111, \"d19\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road20 = new TemplateType(112, \"d20\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road21 = new TemplateType(113, \"d21\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road22 = new TemplateType(114, \"d22\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road23 = new TemplateType(115, \"d23\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road24 = new TemplateType(116, \"d24\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road25 = new TemplateType(117, \"d25\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road26 = new TemplateType(118, \"d26\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road27 = new TemplateType(119, \"d27\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road28 = new TemplateType(120, \"d28\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road29 = new TemplateType(121, \"d29\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road30 = new TemplateType(122, \"d30\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road31 = new TemplateType(123, \"d31\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road32 = new TemplateType(124, \"d32\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road33 = new TemplateType(125, \"d33\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road34 = new TemplateType(126, \"d34\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road35 = new TemplateType(127, \"d35\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road36 = new TemplateType(128, \"d36\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road37 = new TemplateType(129, \"d37\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road38 = new TemplateType(130, \"d38\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road39 = new TemplateType(131, \"d39\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road40 = new TemplateType(132, \"d40\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road41 = new TemplateType(133, \"d41\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road42 = new TemplateType(134, \"d42\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Road43 = new TemplateType(135, \"d43\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType River1 = new TemplateType(136, \"rv01\", 5, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River2 = new TemplateType(137, \"rv02\", 5, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River3 = new TemplateType(138, \"rv03\", 4, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River4 = new TemplateType(139, \"rv04\", 4, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River5 = new TemplateType(140, \"rv05\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River6 = new TemplateType(141, \"rv06\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River7 = new TemplateType(142, \"rv07\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River8 = new TemplateType(143, \"rv08\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River9 = new TemplateType(144, \"rv09\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River10 = new TemplateType(145, \"rv10\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River11 = new TemplateType(146, \"rv11\", 2, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River12 = new TemplateType(147, \"rv12\", 3, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River13 = new TemplateType(148, \"rv13\", 4, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType River14 = new TemplateType(149, \"rv14\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River15 = new TemplateType(150, \"rv15\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River16 = new TemplateType(151, \"rv16\", 6, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River17 = new TemplateType(152, \"rv17\", 6, 5, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River18 = new TemplateType(153, \"rv18\", 4, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River19 = new TemplateType(154, \"rv19\", 4, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River20 = new TemplateType(155, \"rv20\", 6, 8, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River21 = new TemplateType(156, \"rv21\", 5, 8, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River22 = new TemplateType(157, \"rv22\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River23 = new TemplateType(158, \"rv23\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River24 = new TemplateType(159, \"rv24\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType River25 = new TemplateType(160, \"rv25\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Ford1 = new TemplateType(161, \"ford1\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Ford2 = new TemplateType(162, \"ford2\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Falls1 = new TemplateType(163, \"falls1\", 3, 3, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Falls2 = new TemplateType(164, \"falls2\", 3, 2, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Desert, TheaterTypes.Temperate });\n        public static readonly TemplateType Bridge1 = new TemplateType(165, \"bridge1\", 4, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Bridge1d = new TemplateType(166, \"bridge1d\", 4, 4, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Bridge2 = new TemplateType(167, \"bridge2\", 5, 5, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Bridge2d = new TemplateType(168, \"bridge2d\", 5, 5, new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate });\n        public static readonly TemplateType Bridge3 = new TemplateType(169, \"bridge3\", 6, 5, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Bridge3d = new TemplateType(170, \"bridge3d\", 6, 5, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Bridge4 = new TemplateType(171, \"bridge4\", 6, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Bridge4d = new TemplateType(172, \"bridge4d\", 6, 4, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore24 = new TemplateType(173, \"sh24\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore25 = new TemplateType(174, \"sh25\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore26 = new TemplateType(175, \"sh26\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore27 = new TemplateType(176, \"sh27\", 4, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore28 = new TemplateType(177, \"sh28\", 3, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore29 = new TemplateType(178, \"sh29\", 6, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore30 = new TemplateType(179, \"sh30\", 2, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore31 = new TemplateType(180, \"sh31\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Patch16 = new TemplateType(181, \"p16\", 2, 2, new TheaterType[] { TheaterTypes.Winter });\n        public static readonly TemplateType Patch17 = new TemplateType(182, \"p17\", 4, 2, new TheaterType[] { TheaterTypes.Winter });\n        public static readonly TemplateType Patch18 = new TemplateType(183, \"p18\", 4, 3, new TheaterType[] { TheaterTypes.Winter });\n        public static readonly TemplateType Patch19 = new TemplateType(184, \"p19\", 4, 3, new TheaterType[] { TheaterTypes.Winter });\n        public static readonly TemplateType Patch20 = new TemplateType(185, \"p20\", 4, 3, new TheaterType[] { TheaterTypes.Winter });\n        public static readonly TemplateType Shore34 = new TemplateType(186, \"sh34\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly TemplateType Shore35 = new TemplateType(187, \"sh35\", 3, 3, new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter });\n        public static readonly TemplateType Shore36 = new TemplateType(188, \"sh36\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore37 = new TemplateType(189, \"sh37\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore38 = new TemplateType(190, \"sh38\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore39 = new TemplateType(191, \"sh39\", 1, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore40 = new TemplateType(192, \"sh40\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore41 = new TemplateType(193, \"sh41\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore42 = new TemplateType(194, \"sh42\", 1, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore43 = new TemplateType(195, \"sh43\", 1, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore44 = new TemplateType(196, \"sh44\", 1, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore45 = new TemplateType(197, \"sh45\", 1, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore46 = new TemplateType(198, \"sh46\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore47 = new TemplateType(199, \"sh47\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore48 = new TemplateType(200, \"sh48\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore49 = new TemplateType(201, \"sh49\", 3, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore50 = new TemplateType(202, \"sh50\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore51 = new TemplateType(203, \"sh51\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore52 = new TemplateType(204, \"sh52\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore53 = new TemplateType(205, \"sh53\", 4, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore54 = new TemplateType(206, \"sh54\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore55 = new TemplateType(207, \"sh55\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore56 = new TemplateType(208, \"sh56\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore57 = new TemplateType(209, \"sh57\", 3, 2, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore58 = new TemplateType(210, \"sh58\", 2, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore59 = new TemplateType(211, \"sh59\", 2, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore60 = new TemplateType(212, \"sh60\", 2, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore61 = new TemplateType(213, \"sh61\", 2, 3, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore62 = new TemplateType(214, \"sh62\", 6, 1, new TheaterType[] { TheaterTypes.Desert });\n        public static readonly TemplateType Shore63 = new TemplateType(215, \"sh63\", 4, 1, new TheaterType[] { TheaterTypes.Desert });\n\n        private static TemplateType[] Types;\n\n        static TemplateTypes()\n        {\n            Types =\n                (from field in typeof(TemplateTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TemplateType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TemplateType).ToArray();\n        }\n\n        public static IEnumerable<TemplateType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/TerrainTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class TerrainTypes\n    {\n        public static readonly TerrainType Tree1 = new TerrainType(0, \"t01\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree2 = new TerrainType(1, \"t02\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree3 = new TerrainType(2, \"t03\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree4 = new TerrainType(3, \"t04\", new TheaterType[] { TheaterTypes.Desert }, new bool[1, 1] { { true } });\n        public static readonly TerrainType Tree5 = new TerrainType(4, \"t05\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree6 = new TerrainType(5, \"t06\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree7 = new TerrainType(6, \"t07\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree8 = new TerrainType(7, \"t08\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate, TheaterTypes.Desert }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Tree9 = new TerrainType(8, \"t09\", new TheaterType[] { TheaterTypes.Desert }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Tree10 = new TerrainType(9, \"t10\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree11 = new TerrainType(10, \"t11\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree12 = new TerrainType(11, \"t12\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree13 = new TerrainType(12, \"t13\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree14 = new TerrainType(13, \"t14\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree15 = new TerrainType(14, \"t15\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Tree16 = new TerrainType(15, \"t16\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree17 = new TerrainType(16, \"t17\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 2] { { false, false }, { true, false } });\n        public static readonly TerrainType Tree18 = new TerrainType(17, \"t18\", new TheaterType[] { TheaterTypes.Desert }, new bool[2, 3] { { false, false, false }, { false, true, false } });\n        public static readonly TerrainType Split1 = new TerrainType(18, \"split2\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter }, new bool[2, 2] { { false, false }, { true, false } }, true);\n        public static readonly TerrainType Split2 = new TerrainType(19, \"split3\", new TheaterType[] { TheaterTypes.Temperate, TheaterTypes.Winter, TheaterTypes.Desert }, new bool[2, 2] { { false, false }, { true, false } }, true);\n        public static readonly TerrainType Clump1 = new TerrainType(20, \"tc01\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 3] { { false, false, false }, { true, true, false } });\n        public static readonly TerrainType Clump2 = new TerrainType(21, \"tc02\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 3] { { false, true, false }, { true, true, false } });\n        public static readonly TerrainType Clump3 = new TerrainType(22, \"tc03\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[2, 3] { { true, true, false }, { true, true, false } });\n        public static readonly TerrainType Clump4 = new TerrainType(23, \"tc04\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[3, 4] { { false, false, false, false }, { true, true, true, false }, { true, false, false, false } });\n        public static readonly TerrainType Clump5 = new TerrainType(24, \"tc05\", new TheaterType[] { TheaterTypes.Winter, TheaterTypes.Temperate }, new bool[3, 4] { { false, false, true, false }, { true, true, true, false }, { false, true, true, false } });\n        public static readonly TerrainType Rock1 = new TerrainType(25, \"rock1\", new TheaterType[] { TheaterTypes.Desert }, new bool[2, 2] { { false, false }, { true, true } });\n        public static readonly TerrainType Rock2 = new TerrainType(26, \"rock2\", new TheaterType[] { TheaterTypes.Desert }, new bool[2, 2] { { true, true }, { false, false } });\n        public static readonly TerrainType Rock3 = new TerrainType(27, \"rock3\", new TheaterType[] { TheaterTypes.Desert }, new bool[2, 3] { { false, false, false }, { true, true, false } });\n        public static readonly TerrainType Rock4 = new TerrainType(28, \"rock4\", new TheaterType[] { TheaterTypes.Desert }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Rock5 = new TerrainType(29, \"rock5\", new TheaterType[] { TheaterTypes.Desert }, new bool[1, 2] { { true, false } });\n        public static readonly TerrainType Rock6 = new TerrainType(30, \"rock6\", new TheaterType[] { TheaterTypes.Desert }, new bool[2, 3] { { false, false, false }, { true, true, true } });\n        public static readonly TerrainType Rock7 = new TerrainType(31, \"rock7\", new TheaterType[] { TheaterTypes.Desert }, new bool[1, 5] { { true, true, true, true, false } });\n\n        private static TerrainType[] Types;\n\n        static TerrainTypes()\n        {\n            Types =\n                (from field in typeof(TerrainTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TerrainType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TerrainType).ToArray();\n        }\n\n        public static IEnumerable<TerrainType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/TheaterTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class TheaterTypes\n    {\n        private static readonly IEnumerable<string> commonTilesets = new string[] { \"TD_Units\", \"TD_Structures\", \"TD_VFX\", \"Common_VFX\" };\n\n        public static readonly TheaterType Desert = new TheaterType(0, \"desert\", \"TD_Terrain_Desert\".Yield().Concat(commonTilesets));\n        public static readonly TheaterType Temperate = new TheaterType(2, \"temperate\", \"TD_Terrain_Temperate\".Yield().Concat(commonTilesets));\n        public static readonly TheaterType Winter = new TheaterType(2, \"winter\", \"TD_Terrain_Winter\".Yield().Concat(commonTilesets));\n\n        private static TheaterType[] Types;\n\n        static TheaterTypes()\n        {\n            Types =\n                (from field in typeof(TheaterTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(TheaterType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as TheaterType).ToArray();\n        }\n\n        public static IEnumerable<TheaterType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/TiberianDawn/UnitTypes.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.TiberianDawn\n{\n    public static class UnitTypes\n    {\n        public static readonly UnitType HTank = new UnitType(0, \"htnk\", \"TEXT_UNIT_TITLE_GDI_MAMMOTH_TANK\", \"Goodguy\", true);\n        public static readonly UnitType MTank = new UnitType(1, \"mtnk\", \"TEXT_UNIT_TITLE_GDI_MED_TANK\", \"Goodguy\", true);\n        public static readonly UnitType LTank = new UnitType(2, \"ltnk\", \"TEXT_UNIT_TITLE_NOD_LIGHT_TANK\", \"Badguy\", true);\n        public static readonly UnitType STank = new UnitType(3, \"stnk\", \"TEXT_UNIT_TITLE_NOD_STEALTH_TANK\", \"Badguy\");\n        public static readonly UnitType FTank = new UnitType(4, \"ftnk\", \"TEXT_UNIT_TITLE_NOD_FLAME_TANK\", \"Badguy\");\n        public static readonly UnitType Visceroid = new UnitType(5, \"vice\", \"TEXT_UNIT_TITLE_VICE\", \"Special\");\n        public static readonly UnitType APC = new UnitType(6, \"apc\", \"TEXT_UNIT_TITLE_GDI_APC\", \"Goodguy\");\n        public static readonly UnitType MLRS = new UnitType(7, \"msam\", \"TEXT_UNIT_TITLE_GDI_MRLS\", \"Goodguy\", true);\n        public static readonly UnitType Jeep = new UnitType(8, \"jeep\", \"TEXT_UNIT_TITLE_GDI_HUMVEE\", \"Goodguy\", true);\n        public static readonly UnitType Buggy = new UnitType(9, \"bggy\", \"TEXT_UNIT_TITLE_NOD_NOD_BUGGY\", \"Badguy\", true);\n        public static readonly UnitType Harvester = new UnitType(10, \"harv\", \"TEXT_UNIT_TITLE_GDI_HARVESTER\", \"Goodguy\");\n        public static readonly UnitType Arty = new UnitType(11, \"arty\", \"TEXT_UNIT_TITLE_NOD_ARTILLERY\", \"Badguy\");\n        public static readonly UnitType SAM = new UnitType(12, \"mlrs\", \"TEXT_UNIT_TITLE_GDI_MLRS\", \"Goodguy\", true);\n        public static readonly UnitType Hover = new UnitType(13, \"lst\", \"TEXT_UNIT_TITLE_LST\", \"Goodguy\");\n        public static readonly UnitType MHQ = new UnitType(14, \"mhq\", \"TEXT_UNIT_TITLE_MHQ\", \"Goodguy\");\n        public static readonly UnitType GunBoat = new UnitType(15, \"boat\", \"TEXT_UNIT_TITLE_WAKE\", \"Goodguy\", true);\n        public static readonly UnitType MCV = new UnitType(16, \"mcv\", \"TEXT_UNIT_TITLE_GDI_MCV\", \"Goodguy\");\n        public static readonly UnitType Bike = new UnitType(17, \"bike\", \"TEXT_UNIT_TITLE_NOD_RECON_BIKE\", \"Badguy\");\n        public static readonly UnitType Tric = new UnitType(18, \"tric\", \"TEXT_UNIT_TITLE_TRIC\", \"Special\");\n        public static readonly UnitType Trex = new UnitType(19, \"trex\", \"TEXT_UNIT_TITLE_TREX\", \"Special\");\n        public static readonly UnitType Rapt = new UnitType(20, \"rapt\", \"TEXT_UNIT_TITLE_RAPT\", \"Special\");\n        public static readonly UnitType Steg = new UnitType(21, \"steg\", \"TEXT_UNIT_TITLE_STEG\", \"Special\");\n\n        public static readonly UnitType Tran = new UnitType(0 | UnitTypeIDMask.Aircraft, \"tran\", \"TEXT_UNIT_TITLE_GDI_TRANSPORT\", \"Goodguy\");\n        public static readonly UnitType A10 = new UnitType(1 | UnitTypeIDMask.Aircraft, \"a10\", \"TEXT_UNIT_TITLE_A10\", \"Goodguy\", false, true);\n        public static readonly UnitType Heli = new UnitType(2 | UnitTypeIDMask.Aircraft, \"heli\", \"TEXT_UNIT_TITLE_NOD_HELICOPTER\", \"Badguy\");\n        public static readonly UnitType C17 = new UnitType(3 | UnitTypeIDMask.Aircraft, \"c17\", \"TEXT_UNIT_TITLE_C17\", \"Badguy\", false, true);\n        public static readonly UnitType Orca = new UnitType(4 | UnitTypeIDMask.Aircraft, \"orca\", \"TEXT_UNIT_TITLE_GDI_ORCA\", \"Goodguy\");\n\n        private static readonly UnitType[] Types;\n\n        static UnitTypes()\n        {\n            Types =\n                (from field in typeof(UnitTypes).GetFields(BindingFlags.Static | BindingFlags.Public)\n                 where field.IsInitOnly && typeof(UnitType).IsAssignableFrom(field.FieldType)\n                 select field.GetValue(null) as UnitType).ToArray();\n        }\n\n        public static IEnumerable<UnitType> GetTypes()\n        {\n            return Types;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/BuildingTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class BuildingTool : ViewTool\n    {\n        private readonly TypeComboBox buildingTypeComboBox;\n        private readonly MapPanel buildingTypeMapPanel;\n        private readonly ObjectProperties objectProperties;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private readonly Building mockBuilding;\n\n        private Building selectedBuilding;\n        private ObjectPropertiesPopup selectedObjectProperties;\n        private Point selectedBuildingPivot;\n\n        private BuildingType selectedBuildingType;\n        private BuildingType SelectedBuildingType\n        {\n            get => selectedBuildingType;\n            set\n            {\n                if (selectedBuildingType != value)\n                {\n                    if (placementMode && (selectedBuildingType != null))\n                    {\n                        mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedBuildingType.OverlapBounds.Size));\n                    }\n\n                    selectedBuildingType = value;\n                    buildingTypeComboBox.SelectedValue = selectedBuildingType;\n\n                    if (placementMode && (selectedBuildingType != null))\n                    {\n                        mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedBuildingType.OverlapBounds.Size));\n                    }\n\n                    mockBuilding.Type = selectedBuildingType;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public BuildingTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox buildingTypeComboBox, MapPanel buildingTypeMapPanel, ObjectProperties objectProperties, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            mockBuilding = new Building()\n            {\n                Type = buildingTypeComboBox.Types.First() as BuildingType,\n                House = map.Houses.First().Type,\n                Strength = 256,\n                Direction = map.DirectionTypes.Where(d => d.Equals(FacingType.North)).First()\n            };\n            mockBuilding.PropertyChanged += MockBuilding_PropertyChanged;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseDoubleClick += MapPanel_MouseDoubleClick;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += UnitTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += UnitTool_KeyUp;\n\n            this.buildingTypeComboBox = buildingTypeComboBox;\n            this.buildingTypeComboBox.SelectedIndexChanged += UnitTypeComboBox_SelectedIndexChanged;\n\n            this.buildingTypeMapPanel = buildingTypeMapPanel;\n            this.buildingTypeMapPanel.BackColor = Color.White;\n            this.buildingTypeMapPanel.MaxZoom = 1;\n\n            this.objectProperties = objectProperties;\n            this.objectProperties.Object = mockBuilding;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedBuildingType = mockBuilding.Type;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDoubleClick(object sender, MouseEventArgs e)\n        {\n            if (Control.ModifierKeys != Keys.None)\n            {\n                return;\n            }\n\n            if (map.Metrics.GetCell(navigationWidget.MouseCell, out int cell))\n            {\n                if (map.Technos[cell] is Building building)\n                {\n                    selectedBuilding = null;\n                    selectedBuildingPivot = Point.Empty;\n\n                    selectedObjectProperties?.Close();\n                    selectedObjectProperties = new ObjectPropertiesPopup(objectProperties.Plugin, building);\n                    selectedObjectProperties.Closed += (cs, ce) =>\n                    {\n                        navigationWidget.Refresh();\n                    };\n\n                    building.PropertyChanged += SelectedBuilding_PropertyChanged;\n\n                    selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));\n\n                    UpdateStatus();\n                }\n            }\n        }\n\n        private void MockBuilding_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            if ((mockBuilding.Type == null) || !mockBuilding.Type.HasTurret)\n            {\n                mockBuilding.Direction = map.DirectionTypes.Where(d => d.Equals(FacingType.North)).First();\n            }\n\n            RefreshMapPanel();\n        }\n\n        private void SelectedBuilding_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            mapPanel.Invalidate(map, sender as Building);\n        }\n\n        private void UnitTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedBuildingType = buildingTypeComboBox.SelectedValue as BuildingType;\n        }\n\n        private void UnitTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void UnitTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddBuilding(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveBuilding(navigationWidget.MouseCell);\n                }\n            }\n            else if (e.Button == MouseButtons.Left)\n            {\n                SelectBuilding(navigationWidget.MouseCell);\n            }\n            else if (e.Button == MouseButtons.Right)\n            {\n                PickBuilding(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (selectedBuilding != null)\n            {\n                selectedBuilding = null;\n                selectedBuildingPivot = Point.Empty;\n\n                UpdateStatus();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedBuildingType != null)\n                {\n                    mapPanel.Invalidate(map, new Rectangle(e.OldCell, SelectedBuildingType.OverlapBounds.Size));\n                    mapPanel.Invalidate(map, new Rectangle(e.NewCell, SelectedBuildingType.OverlapBounds.Size));\n                }\n            }\n            else if (selectedBuilding != null)\n            {\n                var oldLocation = map.Technos[selectedBuilding].Value;\n                var newLocation = new Point(Math.Max(0, e.NewCell.X - selectedBuildingPivot.X), Math.Max(0, e.NewCell.Y - selectedBuildingPivot.Y));\n                mapPanel.Invalidate(map, selectedBuilding);\n                map.Buildings.Remove(selectedBuilding);\n                if (map.Technos.CanAdd(newLocation, selectedBuilding, selectedBuilding.Type.BaseOccupyMask) &&\n                    map.Buildings.Add(newLocation, selectedBuilding))\n                {\n                    mapPanel.Invalidate(map, selectedBuilding);\n                    plugin.Dirty = true;\n                }\n                else\n                {\n                    map.Buildings.Add(oldLocation, selectedBuilding);\n                }\n            }\n        }\n\n        private void AddBuilding(Point location)\n        {\n            if (SelectedBuildingType != null)\n            {\n                var building = mockBuilding.Clone();\n                if (map.Technos.CanAdd(location, building, building.Type.BaseOccupyMask) && map.Buildings.Add(location, building))\n                {\n                    if (building.BasePriority >= 0)\n                    {\n                        foreach (var baseBuilding in map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0))\n                        {\n                            if ((building != baseBuilding) && (baseBuilding.BasePriority >= building.BasePriority))\n                            {\n                                baseBuilding.BasePriority++;\n                            }\n                        }\n\n                        var baseBuildings = map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0).OrderBy(x => x.BasePriority).ToArray();\n                        for (var i = 0; i < baseBuildings.Length; ++i)\n                        {\n                            baseBuildings[i].BasePriority = i;\n                        }\n\n                        foreach (var baseBuilding in map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0))\n                        {\n                            mapPanel.Invalidate(map, baseBuilding);\n                        }\n                    }\n\n                    mapPanel.Invalidate(map, building);\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveBuilding(Point location)\n        {\n            if (map.Technos[location] is Building building)\n            {\n                mapPanel.Invalidate(map, building);\n                map.Buildings.Remove(building);\n\n                if (building.BasePriority >= 0)\n                {\n                    var baseBuildings = map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0).OrderBy(x => x.BasePriority).ToArray();\n                    for (var i = 0; i < baseBuildings.Length; ++i)\n                    {\n                        baseBuildings[i].BasePriority = i;\n                    }\n\n                    foreach (var baseBuilding in map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0))\n                    {\n                        mapPanel.Invalidate(map, baseBuilding);\n                    }\n                }\n\n                plugin.Dirty = true;\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedBuildingType != null)\n            {\n                mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, SelectedBuildingType.OverlapBounds.Size));\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedBuildingType != null)\n            {\n                mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, SelectedBuildingType.OverlapBounds.Size));\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickBuilding(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.Technos[cell] is Building building)\n                {\n                    SelectedBuildingType = building.Type;\n                    mockBuilding.House = building.House;\n                    mockBuilding.Strength = building.Strength;\n                    mockBuilding.Direction = building.Direction;\n                    mockBuilding.Trigger = building.Trigger;\n                    mockBuilding.BasePriority = building.BasePriority;\n                    mockBuilding.IsPrebuilt = building.IsPrebuilt;\n                    mockBuilding.Sellable = building.Sellable;\n                    mockBuilding.Rebuild = building.Rebuild;\n                }\n            }\n        }\n\n        private void SelectBuilding(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                selectedBuilding = map.Technos[cell] as Building;\n                selectedBuildingPivot = (selectedBuilding != null) ? (location - (Size)map.Technos[selectedBuilding].Value) : Point.Empty;\n            }\n\n            UpdateStatus();\n        }\n\n        private void RefreshMapPanel()\n        {\n            if (mockBuilding.Type != null)\n            {\n                var render = MapRenderer.Render(plugin.GameType, map.Theater, new Point(0, 0), Globals.TileSize, Globals.TileScale, mockBuilding);\n                if (!render.Item1.IsEmpty)\n                {\n                    var buildingPreview = new Bitmap(render.Item1.Width, render.Item1.Height);\n                    using (var g = Graphics.FromImage(buildingPreview))\n                    {\n                        render.Item2(g);\n                    }\n                    buildingTypeMapPanel.MapImage = buildingPreview;\n                }\n                else\n                {\n                    buildingTypeMapPanel.MapImage = null;\n                }\n            }\n            else\n            {\n                buildingTypeMapPanel.MapImage = null;\n            }\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place building, Right-Click to remove building\";\n            }\n            else if (selectedBuilding != null)\n            {\n                statusLbl.Text = \"Drag mouse to move building\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click drag to move building, Double-Click update building properties, Right-Click to pick building\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedBuildingType != null)\n                {\n                    var building = mockBuilding.Clone();\n                    building.Tint = Color.FromArgb(128, Color.White);\n                    if (previewMap.Technos.CanAdd(location, building, building.Type.BaseOccupyMask) && previewMap.Buildings.Add(location, building))\n                    {\n                        mapPanel.Invalidate(previewMap, building);\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var buildingPen = new Pen(Color.Green, 4.0f);\n            var occupyPen = new Pen(Color.Red, 2.0f);\n            foreach (var (topLeft, building) in map.Buildings.OfType<Building>())\n            {\n                var bounds = new Rectangle(\n                    new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight),\n                    new Size(building.Type.Size.Width * Globals.TileWidth, building.Type.Size.Height * Globals.TileHeight)\n                );\n                graphics.DrawRectangle(buildingPen, bounds);\n\n                for (var y = 0; y < building.Type.BaseOccupyMask.GetLength(0); ++y)\n                {\n                    for (var x = 0; x < building.Type.BaseOccupyMask.GetLength(1); ++x)\n                    {\n                        if (building.Type.BaseOccupyMask[y, x])\n                        {\n                            var occupyBounds = new Rectangle(\n                                new Point((topLeft.X + x) * Globals.TileWidth, (topLeft.Y + y) * Globals.TileHeight),\n                                Globals.TileSize\n                            );\n                            graphics.DrawRectangle(occupyPen, occupyBounds);\n                        }\n                    }\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseDoubleClick -= MapPanel_MouseDoubleClick;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= UnitTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= UnitTool_KeyUp;\n\n                    buildingTypeComboBox.SelectedIndexChanged -= UnitTypeComboBox_SelectedIndexChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/CellTriggersTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class CellTriggersTool : ViewTool\n    {\n        private readonly ComboBox triggerCombo;\n\n        private readonly Dictionary<int, CellTrigger> undoCellTriggers = new Dictionary<int, CellTrigger>();\n        private readonly Dictionary<int, CellTrigger> redoCellTriggers = new Dictionary<int, CellTrigger>();\n\n        private bool placementMode;\n\n        public CellTriggersTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, ComboBox triggerCombo, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += WaypointsTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += WaypointsTool_KeyUp;\n\n            this.triggerCombo = triggerCombo;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    SetCellTrigger(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveCellTrigger(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickCellTrigger(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if ((undoCellTriggers.Count > 0) || (redoCellTriggers.Count > 0))\n            {\n                CommitChange();\n            }\n        }\n\n        private void WaypointsTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void WaypointsTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n\n            \n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (Control.MouseButtons == MouseButtons.Left)\n                {\n                    SetCellTrigger(e.NewCell);\n                }\n                else if (Control.MouseButtons == MouseButtons.Right)\n                {\n                    RemoveCellTrigger(e.NewCell);\n                }\n            }\n        }\n\n        private void SetCellTrigger(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.CellTriggers[cell] == null)\n                {\n                    if (!undoCellTriggers.ContainsKey(cell))\n                    {\n                        undoCellTriggers[cell] = map.CellTriggers[cell];\n                    }\n\n                    var cellTrigger = new CellTrigger { Trigger = triggerCombo.SelectedItem as string };\n                    map.CellTriggers[cell] = cellTrigger;\n                    redoCellTriggers[cell] = cellTrigger;\n\n                    mapPanel.Invalidate();\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveCellTrigger(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var cellTrigger = map.CellTriggers[cell];\n                if (cellTrigger != null)\n                {\n                    if (!undoCellTriggers.ContainsKey(cell))\n                    {\n                        undoCellTriggers[cell] = map.CellTriggers[cell];\n                    }\n\n                    map.CellTriggers[cell] = null;\n                    redoCellTriggers[cell] = null;\n\n                    mapPanel.Invalidate();\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            UpdateStatus();\n        }\n\n        private void PickCellTrigger(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var cellTrigger = map.CellTriggers[cell];\n                if (cellTrigger != null)\n                {\n                    triggerCombo.SelectedItem = cellTrigger.Trigger;\n                }\n            }\n        }\n\n        private void CommitChange()\n        {\n            var undoCellTriggers2 = new Dictionary<int, CellTrigger>(undoCellTriggers);\n            void undoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in undoCellTriggers2)\n                {\n                    e.Map.CellTriggers[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate();\n            }\n\n            var redoCellTriggers2 = new Dictionary<int, CellTrigger>(redoCellTriggers);\n            void redoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in redoCellTriggers2)\n                {\n                    e.Map.CellTriggers[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate();\n            }\n\n            undoCellTriggers.Clear();\n            redoCellTriggers.Clear();\n\n            url.Track(undoAction, redoAction);\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to set cell trigger, Right-Click to clear cell trigger\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click or Right-Click to pick cell trigger\";\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= WaypointsTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= WaypointsTool_KeyUp;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/CellTriggersToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class CellTriggersToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.triggerCombo = new System.Windows.Forms.ComboBox();\n            this.tableLayoutPanel4.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel4\n            // \n            this.tableLayoutPanel4.AutoSize = true;\n            this.tableLayoutPanel4.ColumnCount = 2;\n            this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel4.Controls.Add(this.triggerCombo, 1, 0);\n            this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.tableLayoutPanel4.Name = \"tableLayoutPanel4\";\n            this.tableLayoutPanel4.RowCount = 2;\n            this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel4.Size = new System.Drawing.Size(218, 118);\n            this.tableLayoutPanel4.TabIndex = 3;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(4, 0);\n            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(58, 38);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"Trigger\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // triggerCombo\n            // \n            this.triggerCombo.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.triggerCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.triggerCombo.FormattingEnabled = true;\n            this.triggerCombo.Location = new System.Drawing.Point(70, 5);\n            this.triggerCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.triggerCombo.Name = \"triggerCombo\";\n            this.triggerCombo.Size = new System.Drawing.Size(144, 28);\n            this.triggerCombo.TabIndex = 1;\n            // \n            // CellTriggersToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.AutoSize = true;\n            this.ClientSize = new System.Drawing.Size(218, 118);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel4);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;\n            this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(210, 91);\n            this.Name = \"CellTriggersToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Cell Triggers\";\n            this.tableLayoutPanel4.ResumeLayout(false);\n            this.tableLayoutPanel4.PerformLayout();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.ComboBox triggerCombo;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/CellTriggersToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class CellTriggersToolDialog : Form\n    {\n        public ComboBox TriggerCombo => triggerCombo;\n\n        public CellTriggersToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/CellTriggersToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/GenericToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class GenericToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TemplateToolDialog));\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.genericTypeMapPanel = new MobiusEditor.Controls.MapPanel();\n            this.genericTypeComboBox = new MobiusEditor.Controls.TypeComboBox();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.genericTypeMapPanel, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.genericTypeComboBox, 0, 0);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 2;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(274, 254);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // templateTypeMapPanel\n            // \n            this.genericTypeMapPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.genericTypeMapPanel.Location = new System.Drawing.Point(3, 30);\n            this.genericTypeMapPanel.MaxZoom = 8;\n            this.genericTypeMapPanel.MinZoom = 1;\n            this.genericTypeMapPanel.Name = \"templateTypeMapPanel\";\n            this.genericTypeMapPanel.Quality = 1;\n            this.genericTypeMapPanel.Size = new System.Drawing.Size(268, 221);\n            this.genericTypeMapPanel.TabIndex = 3;\n            this.genericTypeMapPanel.Zoom = 1;\n            // \n            // templateTypeComboBox\n            // \n            this.genericTypeComboBox.DisplayMember = \"Name\";\n            this.genericTypeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.genericTypeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;\n            this.genericTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.genericTypeComboBox.FormattingEnabled = true;\n            this.genericTypeComboBox.Location = new System.Drawing.Point(3, 3);\n            this.genericTypeComboBox.MissingThumbnail = ((System.Drawing.Image)(resources.GetObject(\"templateTypeComboBox.MissingThumbnail\")));\n            this.genericTypeComboBox.Name = \"templateTypeComboBox\";\n            this.genericTypeComboBox.Size = new System.Drawing.Size(268, 21);\n            this.genericTypeComboBox.TabIndex = 2;\n            this.genericTypeComboBox.ValueMember = \"Type\";\n            // \n            // TemplateToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(274, 254);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(290, 293);\n            this.Name = \"TemplateToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Map\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private Controls.TypeComboBox genericTypeComboBox;\n        private Controls.MapPanel genericTypeMapPanel;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/GenericToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class GenericToolDialog : Form\n    {\n        public TypeComboBox GenericTypeComboBox => genericTypeComboBox;\n\n        public MapPanel GenericTypeMapPanel => genericTypeMapPanel;\n\n        public GenericToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/GenericToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"templateTypeComboBox.MissingThumbnail\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        fwDWYGmBKz70PQAAAABJRU5ErkJggg==\n</value>\n  </data>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ObjectToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class ObjectToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ObjectToolDialog));\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.objectTypeMapPanel = new MobiusEditor.Controls.MapPanel();\n            this.objectTypeComboBox = new MobiusEditor.Controls.TypeComboBox();\n            this.objectProperties = new MobiusEditor.Controls.ObjectProperties();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Controls.Add(this.objectTypeMapPanel, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.objectTypeComboBox, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.objectProperties, 0, 2);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 3;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(365, 582);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // objectTypeMapPanel\n            // \n            this.objectTypeMapPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Left) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.objectTypeMapPanel.Location = new System.Drawing.Point(4, 35);\n            this.objectTypeMapPanel.MapImage = null;\n            this.objectTypeMapPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.objectTypeMapPanel.MaxZoom = 8;\n            this.objectTypeMapPanel.MinZoom = 1;\n            this.objectTypeMapPanel.Name = \"objectTypeMapPanel\";\n            this.objectTypeMapPanel.Quality = 1;\n            this.objectTypeMapPanel.Size = new System.Drawing.Size(357, 272);\n            this.objectTypeMapPanel.TabIndex = 3;\n            this.objectTypeMapPanel.Zoom = 1;\n            this.objectTypeMapPanel.ZoomStep = 1;\n            // \n            // objectTypeComboBox\n            // \n            this.objectTypeComboBox.DisplayMember = \"Name\";\n            this.objectTypeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.objectTypeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;\n            this.objectTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.objectTypeComboBox.FormattingEnabled = true;\n            this.objectTypeComboBox.Location = new System.Drawing.Point(4, 4);\n            this.objectTypeComboBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.objectTypeComboBox.MissingThumbnail = ((System.Drawing.Image)(resources.GetObject(\"objectTypeComboBox.MissingThumbnail\")));\n            this.objectTypeComboBox.Name = \"objectTypeComboBox\";\n            this.objectTypeComboBox.Size = new System.Drawing.Size(357, 23);\n            this.objectTypeComboBox.TabIndex = 2;\n            this.objectTypeComboBox.ValueMember = \"Type\";\n            // \n            // objectProperties\n            // \n            this.objectProperties.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) \n            | System.Windows.Forms.AnchorStyles.Left) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.objectProperties.Location = new System.Drawing.Point(5, 316);\n            this.objectProperties.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5);\n            this.objectProperties.Name = \"objectProperties\";\n            this.objectProperties.Object = null;\n            this.objectProperties.Size = new System.Drawing.Size(355, 261);\n            this.objectProperties.TabIndex = 4;\n            // \n            // ObjectToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(365, 582);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;\n            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(381, 528);\n            this.Name = \"ObjectToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Map\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private Controls.TypeComboBox objectTypeComboBox;\n        private Controls.MapPanel objectTypeMapPanel;\n        private Controls.ObjectProperties objectProperties;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ObjectToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class ObjectToolDialog : Form\n    {\n        public TypeComboBox ObjectTypeComboBox => objectTypeComboBox;\n\n        public MapPanel ObjectTypeMapPanel => objectTypeMapPanel;\n\n        public ObjectProperties ObjectProperties => objectProperties;\n\n        public ObjectToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        public ObjectToolDialog(IGamePlugin plugin)\n            : this()\n        {\n            objectProperties.Initialize(plugin, true);\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ObjectToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"objectTypeComboBox.MissingThumbnail\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        fwDWYGmBKz70PQAAAABJRU5ErkJggg==\n</value>\n  </data>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ResourcesToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class ResourcesToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();\n            this.label10 = new System.Windows.Forms.Label();\n            this.totalResourcesLbl = new System.Windows.Forms.Label();\n            this.gemsCheckBox = new System.Windows.Forms.CheckBox();\n            this.resourceBrushSizeNud = new System.Windows.Forms.NumericUpDown();\n            this.label1 = new System.Windows.Forms.Label();\n            this.tableLayoutPanel6.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.resourceBrushSizeNud)).BeginInit();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel6\n            // \n            this.tableLayoutPanel6.ColumnCount = 2;\n            this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel6.Controls.Add(this.label10, 0, 0);\n            this.tableLayoutPanel6.Controls.Add(this.totalResourcesLbl, 1, 0);\n            this.tableLayoutPanel6.Controls.Add(this.gemsCheckBox, 0, 3);\n            this.tableLayoutPanel6.Controls.Add(this.resourceBrushSizeNud, 1, 2);\n            this.tableLayoutPanel6.Controls.Add(this.label1, 0, 2);\n            this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel6.Name = \"tableLayoutPanel6\";\n            this.tableLayoutPanel6.RowCount = 4;\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));\n            this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));\n            this.tableLayoutPanel6.Size = new System.Drawing.Size(196, 67);\n            this.tableLayoutPanel6.TabIndex = 1;\n            // \n            // label10\n            // \n            this.label10.AutoSize = true;\n            this.label10.Location = new System.Drawing.Point(3, 0);\n            this.label10.Name = \"label10\";\n            this.label10.Size = new System.Drawing.Size(88, 13);\n            this.label10.TabIndex = 0;\n            this.label10.Text = \"Total Resources:\";\n            // \n            // totalResourcesLbl\n            // \n            this.totalResourcesLbl.AutoSize = true;\n            this.totalResourcesLbl.Location = new System.Drawing.Point(97, 0);\n            this.totalResourcesLbl.Name = \"totalResourcesLbl\";\n            this.totalResourcesLbl.Size = new System.Drawing.Size(13, 13);\n            this.totalResourcesLbl.TabIndex = 1;\n            this.totalResourcesLbl.Text = \"0\";\n            // \n            // gemsCheckBox\n            // \n            this.gemsCheckBox.AutoSize = true;\n            this.tableLayoutPanel6.SetColumnSpan(this.gemsCheckBox, 2);\n            this.gemsCheckBox.Location = new System.Drawing.Point(3, 42);\n            this.gemsCheckBox.Name = \"gemsCheckBox\";\n            this.gemsCheckBox.Size = new System.Drawing.Size(53, 17);\n            this.gemsCheckBox.TabIndex = 2;\n            this.gemsCheckBox.Text = \"Gems\";\n            this.gemsCheckBox.UseVisualStyleBackColor = true;\n            // \n            // resourceBrushSizeNud\n            // \n            this.resourceBrushSizeNud.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) \n            | System.Windows.Forms.AnchorStyles.Right)));\n            this.resourceBrushSizeNud.Increment = new decimal(new int[] {\n            2,\n            0,\n            0,\n            0});\n            this.resourceBrushSizeNud.Location = new System.Drawing.Point(97, 16);\n            this.resourceBrushSizeNud.Maximum = new decimal(new int[] {\n            9,\n            0,\n            0,\n            0});\n            this.resourceBrushSizeNud.Minimum = new decimal(new int[] {\n            1,\n            0,\n            0,\n            0});\n            this.resourceBrushSizeNud.Name = \"resourceBrushSizeNud\";\n            this.resourceBrushSizeNud.Size = new System.Drawing.Size(99, 20);\n            this.resourceBrushSizeNud.TabIndex = 3;\n            this.resourceBrushSizeNud.Value = new decimal(new int[] {\n            1,\n            0,\n            0,\n            0});\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(3, 13);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(88, 26);\n            this.label1.TabIndex = 4;\n            this.label1.Text = \"Brush Size\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // ResourcesToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(196, 67);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel6);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(212, 106);\n            this.Name = \"ResourcesToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Resources\";\n            this.tableLayoutPanel6.ResumeLayout(false);\n            this.tableLayoutPanel6.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.resourceBrushSizeNud)).EndInit();\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;\n        private System.Windows.Forms.Label label10;\n        private System.Windows.Forms.Label totalResourcesLbl;\n        private System.Windows.Forms.CheckBox gemsCheckBox;\n        private System.Windows.Forms.NumericUpDown resourceBrushSizeNud;\n        private System.Windows.Forms.Label label1;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ResourcesToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class ResourcesToolDialog : Form\n    {\n        public Label TotalResourcesLbl => totalResourcesLbl;\n\n        public NumericUpDown ResourceBrushSizeNud => resourceBrushSizeNud;\n\n        public CheckBox GemsCheckBox => gemsCheckBox;\n\n        public ResourcesToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/ResourcesToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TemplateToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class TemplateToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.splitContainer1 = new System.Windows.Forms.SplitContainer();\n            this.templateTypeListView = new System.Windows.Forms.ListView();\n            this.templateTypeMapPanel = new MobiusEditor.Controls.MapPanel();\n            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();\n            this.splitContainer1.Panel1.SuspendLayout();\n            this.splitContainer1.Panel2.SuspendLayout();\n            this.splitContainer1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // splitContainer1\n            // \n            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.splitContainer1.Location = new System.Drawing.Point(2, 2);\n            this.splitContainer1.Name = \"splitContainer1\";\n            this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;\n            // \n            // splitContainer1.Panel1\n            // \n            this.splitContainer1.Panel1.Controls.Add(this.templateTypeListView);\n            // \n            // splitContainer1.Panel2\n            // \n            this.splitContainer1.Panel2.Controls.Add(this.templateTypeMapPanel);\n            this.splitContainer1.Size = new System.Drawing.Size(270, 545);\n            this.splitContainer1.SplitterDistance = 275;\n            this.splitContainer1.TabIndex = 7;\n            // \n            // templateTypeListView\n            // \n            this.templateTypeListView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.templateTypeListView.HideSelection = false;\n            this.templateTypeListView.Location = new System.Drawing.Point(0, 0);\n            this.templateTypeListView.Margin = new System.Windows.Forms.Padding(0);\n            this.templateTypeListView.MultiSelect = false;\n            this.templateTypeListView.Name = \"templateTypeListView\";\n            this.templateTypeListView.Size = new System.Drawing.Size(270, 275);\n            this.templateTypeListView.TabIndex = 7;\n            this.templateTypeListView.UseCompatibleStateImageBehavior = false;\n            // \n            // templateTypeMapPanel\n            // \n            this.templateTypeMapPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.templateTypeMapPanel.Location = new System.Drawing.Point(0, 0);\n            this.templateTypeMapPanel.MapImage = null;\n            this.templateTypeMapPanel.Margin = new System.Windows.Forms.Padding(0);\n            this.templateTypeMapPanel.MaxZoom = 8;\n            this.templateTypeMapPanel.MinZoom = 1;\n            this.templateTypeMapPanel.Name = \"templateTypeMapPanel\";\n            this.templateTypeMapPanel.Quality = 1;\n            this.templateTypeMapPanel.Size = new System.Drawing.Size(270, 266);\n            this.templateTypeMapPanel.TabIndex = 6;\n            this.templateTypeMapPanel.Zoom = 1;\n            this.templateTypeMapPanel.ZoomStep = 1;\n            // \n            // TemplateToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(274, 549);\n            this.ControlBox = false;\n            this.Controls.Add(this.splitContainer1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(288, 287);\n            this.Name = \"TemplateToolDialog\";\n            this.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Map\";\n            this.splitContainer1.Panel1.ResumeLayout(false);\n            this.splitContainer1.Panel2.ResumeLayout(false);\n            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();\n            this.splitContainer1.ResumeLayout(false);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.SplitContainer splitContainer1;\n        private System.Windows.Forms.ListView templateTypeListView;\n        private Controls.MapPanel templateTypeMapPanel;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TemplateToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class TemplateToolDialog : Form\n    {\n        public ListView TemplateTypeListView => templateTypeListView;\n\n        public MapPanel TemplateTypeMapPanel => templateTypeMapPanel;\n\n        public TemplateToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TemplateToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TerrainToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class TerrainToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TerrainToolDialog));\n            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();\n            this.terrainTypeMapPanel = new MobiusEditor.Controls.MapPanel();\n            this.terrainTypeComboBox = new MobiusEditor.Controls.TypeComboBox();\n            this.terrainProperties = new MobiusEditor.Controls.TerrainProperties();\n            this.tableLayoutPanel1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel1\n            // \n            this.tableLayoutPanel1.AutoSize = true;\n            this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.tableLayoutPanel1.ColumnCount = 1;\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));\n            this.tableLayoutPanel1.Controls.Add(this.terrainTypeMapPanel, 0, 1);\n            this.tableLayoutPanel1.Controls.Add(this.terrainTypeComboBox, 0, 0);\n            this.tableLayoutPanel1.Controls.Add(this.terrainProperties, 0, 3);\n            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            this.tableLayoutPanel1.RowCount = 4;\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));\n            this.tableLayoutPanel1.Size = new System.Drawing.Size(411, 466);\n            this.tableLayoutPanel1.TabIndex = 0;\n            // \n            // terrainTypeMapPanel\n            // \n            this.terrainTypeMapPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.terrainTypeMapPanel.Location = new System.Drawing.Point(4, 42);\n            this.terrainTypeMapPanel.MapImage = null;\n            this.terrainTypeMapPanel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.terrainTypeMapPanel.MaxZoom = 8;\n            this.terrainTypeMapPanel.MinZoom = 1;\n            this.terrainTypeMapPanel.Name = \"terrainTypeMapPanel\";\n            this.terrainTypeMapPanel.Quality = 1;\n            this.terrainTypeMapPanel.Size = new System.Drawing.Size(403, 370);\n            this.terrainTypeMapPanel.TabIndex = 3;\n            this.terrainTypeMapPanel.Zoom = 1;\n            this.terrainTypeMapPanel.ZoomStep = 1;\n            // \n            // terrainTypeComboBox\n            // \n            this.terrainTypeComboBox.DisplayMember = \"Name\";\n            this.terrainTypeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.terrainTypeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;\n            this.terrainTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.terrainTypeComboBox.FormattingEnabled = true;\n            this.terrainTypeComboBox.Location = new System.Drawing.Point(4, 5);\n            this.terrainTypeComboBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.terrainTypeComboBox.MissingThumbnail = ((System.Drawing.Image)(resources.GetObject(\"terrainTypeComboBox.MissingThumbnail\")));\n            this.terrainTypeComboBox.Name = \"terrainTypeComboBox\";\n            this.terrainTypeComboBox.Size = new System.Drawing.Size(403, 27);\n            this.terrainTypeComboBox.TabIndex = 2;\n            this.terrainTypeComboBox.ValueMember = \"Type\";\n            // \n            // terrainProperties\n            // \n            this.terrainProperties.Dock = System.Windows.Forms.DockStyle.Top;\n            this.terrainProperties.Location = new System.Drawing.Point(4, 422);\n            this.terrainProperties.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.terrainProperties.Name = \"terrainProperties\";\n            this.terrainProperties.Size = new System.Drawing.Size(403, 38);\n            this.terrainProperties.TabIndex = 4;\n            this.terrainProperties.Terrain = null;\n            // \n            // TerrainToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.AutoSize = true;\n            this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;\n            this.ClientSize = new System.Drawing.Size(411, 466);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel1);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;\n            this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(424, 421);\n            this.Name = \"TerrainToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Terrain\";\n            this.tableLayoutPanel1.ResumeLayout(false);\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;\n        private Controls.TypeComboBox terrainTypeComboBox;\n        private Controls.MapPanel terrainTypeMapPanel;\n        private Controls.TerrainProperties terrainProperties;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TerrainToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Interface;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class TerrainToolDialog : Form\n    {\n        public TypeComboBox TerrainTypeComboBox => terrainTypeComboBox;\n\n        public MapPanel TerrainTypeMapPanel => terrainTypeMapPanel;\n\n        public TerrainProperties TerrainProperties => terrainProperties;\n\n        public TerrainToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        public TerrainToolDialog(IGamePlugin plugin)\n            : this()\n        {\n            terrainProperties.Initialize(plugin, true);\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/TerrainToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"terrainTypeComboBox.MissingThumbnail\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        fwDWYGmBKz70PQAAAABJRU5ErkJggg==\n</value>\n  </data>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/WaypointsToolDialog.Designer.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nnamespace MobiusEditor.Tools.Dialogs\n{\n    partial class WaypointsToolDialog\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();\n            this.label1 = new System.Windows.Forms.Label();\n            this.waypointCombo = new System.Windows.Forms.ComboBox();\n            this.tableLayoutPanel4.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // tableLayoutPanel4\n            // \n            this.tableLayoutPanel4.AutoSize = true;\n            this.tableLayoutPanel4.ColumnCount = 2;\n            this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());\n            this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0);\n            this.tableLayoutPanel4.Controls.Add(this.waypointCombo, 1, 0);\n            this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 0);\n            this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.tableLayoutPanel4.Name = \"tableLayoutPanel4\";\n            this.tableLayoutPanel4.RowCount = 2;\n            this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());\n            this.tableLayoutPanel4.Size = new System.Drawing.Size(218, 118);\n            this.tableLayoutPanel4.TabIndex = 3;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.label1.Location = new System.Drawing.Point(4, 0);\n            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(75, 38);\n            this.label1.TabIndex = 0;\n            this.label1.Text = \"Waypoint\";\n            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // waypointCombo\n            // \n            this.waypointCombo.DisplayMember = \"Name\";\n            this.waypointCombo.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.waypointCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.waypointCombo.FormattingEnabled = true;\n            this.waypointCombo.Location = new System.Drawing.Point(87, 5);\n            this.waypointCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.waypointCombo.Name = \"waypointCombo\";\n            this.waypointCombo.Size = new System.Drawing.Size(127, 28);\n            this.waypointCombo.TabIndex = 1;\n            this.waypointCombo.ValueMember = \"Type\";\n            // \n            // WaypointsToolDialog\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.AutoSize = true;\n            this.ClientSize = new System.Drawing.Size(218, 118);\n            this.ControlBox = false;\n            this.Controls.Add(this.tableLayoutPanel4);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;\n            this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.MinimumSize = new System.Drawing.Size(210, 91);\n            this.Name = \"WaypointsToolDialog\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;\n            this.Text = \"Waypoints\";\n            this.tableLayoutPanel4.ResumeLayout(false);\n            this.tableLayoutPanel4.PerformLayout();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.ComboBox waypointCombo;\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/WaypointsToolDialog.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools.Dialogs\n{\n    public partial class WaypointsToolDialog : Form\n    {\n        public ComboBox WaypointCombo => waypointCombo;\n\n        public WaypointsToolDialog()\n        {\n            InitializeComponent();\n\n            Location = Properties.Settings.Default.ToolDialogPosition;\n        }\n\n        protected override void OnMove(EventArgs e)\n        {\n            base.OnMove(e);\n\n            Properties.Settings.Default.ToolDialogPosition = Location;\n            Properties.Settings.Default.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/Dialogs/WaypointsToolDialog.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/InfantryTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class InfantryTool : ViewTool\n    {\n        private readonly TypeComboBox infantryTypeComboBox;\n        private readonly MapPanel infantryTypeMapPanel;\n        private readonly ObjectProperties objectProperties;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private readonly Infantry mockInfantry;\n\n        private Infantry selectedInfantry;\n        private ObjectPropertiesPopup selectedObjectProperties;\n\n        private InfantryType selectedInfantryType;\n        private InfantryType SelectedInfantryType\n        {\n            get => selectedInfantryType;\n            set\n            {\n                if (selectedInfantryType != value)\n                {\n                    if (placementMode && (selectedInfantryType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    selectedInfantryType = value;\n                    infantryTypeComboBox.SelectedValue = selectedInfantryType;\n\n                    if (placementMode && (selectedInfantryType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    mockInfantry.Type = selectedInfantryType;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public InfantryTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox infantryTypeComboBox, MapPanel infantryTypeMapPanel, ObjectProperties objectProperties, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            mockInfantry = new Infantry(null)\n            {\n                Type = infantryTypeComboBox.Types.First() as InfantryType,\n                House = map.Houses.First().Type,\n                Strength = 256,\n                Direction = map.DirectionTypes.Where(d => d.Equals(FacingType.South)).First(),\n                Mission = map.MissionTypes.Where(m => m.Equals(\"Guard\")).FirstOrDefault() ?? map.MissionTypes.First()\n            };\n            mockInfantry.PropertyChanged += MockInfantry_PropertyChanged;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseDoubleClick += MapPanel_MouseDoubleClick;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += InfantryTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += InfantryTool_KeyUp;\n\n            this.infantryTypeComboBox = infantryTypeComboBox;\n            this.infantryTypeComboBox.SelectedIndexChanged += InfantryTypeComboBox_SelectedIndexChanged;\n\n            this.infantryTypeMapPanel = infantryTypeMapPanel;\n            this.infantryTypeMapPanel.BackColor = Color.White;\n            this.infantryTypeMapPanel.MaxZoom = 1;\n\n            this.objectProperties = objectProperties;\n            this.objectProperties.Object = mockInfantry;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedInfantryType = this.infantryTypeComboBox.Types.First() as InfantryType;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDoubleClick(object sender, MouseEventArgs e)\n        {\n            if (Control.ModifierKeys != Keys.None)\n            {\n                return;\n            }\n\n            if (map.Metrics.GetCell(navigationWidget.MouseCell, out int cell))\n            {\n                if (map.Technos[cell] is InfantryGroup infantryGroup)\n                {\n                    var i = InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>().First();\n                    if (infantryGroup.Infantry[i] is Infantry infantry)\n                    {\n                        selectedInfantry = null;\n\n                        selectedObjectProperties?.Close();\n                        selectedObjectProperties = new ObjectPropertiesPopup(objectProperties.Plugin, infantry);\n                        selectedObjectProperties.Closed += (cs, ce) =>\n                        {\n                            navigationWidget.Refresh();\n                        };\n\n                        infantry.PropertyChanged += SelectedInfantry_PropertyChanged;\n\n                        selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));\n\n                        UpdateStatus();\n                    }\n                }\n            }\n        }\n\n        private void MockInfantry_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            RefreshMapPanel();\n        }\n\n        private void SelectedInfantry_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            mapPanel.Invalidate(map, (sender as Infantry).InfantryGroup);\n        }\n\n        private void InfantryTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedInfantryType = infantryTypeComboBox.SelectedValue as InfantryType;\n        }\n\n        private void InfantryTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void InfantryTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n\n            if (placementMode)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n            else if (selectedInfantry != null)\n            {\n                var oldLocation = map.Technos[selectedInfantry.InfantryGroup].Value;\n                var oldStop = Array.IndexOf(selectedInfantry.InfantryGroup.Infantry, selectedInfantry);\n\n                InfantryGroup infantryGroup = null;\n                var techno = map.Technos[navigationWidget.MouseCell];\n                if (techno == null)\n                {\n                    infantryGroup = new InfantryGroup();\n                    map.Technos.Add(navigationWidget.MouseCell, infantryGroup);\n                }\n                else if (techno is InfantryGroup)\n                {\n                    infantryGroup = techno as InfantryGroup;\n                }\n\n                if (infantryGroup != null)\n                {\n                    foreach (var i in InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>())\n                    {\n                        if (infantryGroup.Infantry[i] == null)\n                        {\n                            selectedInfantry.InfantryGroup.Infantry[oldStop] = null;\n                            infantryGroup.Infantry[i] = selectedInfantry;\n                            \n                            if (infantryGroup != selectedInfantry.InfantryGroup)\n                            {\n                                mapPanel.Invalidate(map, selectedInfantry.InfantryGroup);\n                                if (selectedInfantry.InfantryGroup.Infantry.All(x => x == null))\n                                {\n                                    map.Technos.Remove(selectedInfantry.InfantryGroup);\n                                }\n                            }\n                            selectedInfantry.InfantryGroup = infantryGroup;\n\n                            mapPanel.Invalidate(map, infantryGroup);\n\n                            plugin.Dirty = true;\n                        }\n\n                        if (infantryGroup == selectedInfantry.InfantryGroup)\n                        {\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddInfantry(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveInfantry(navigationWidget.MouseCell);\n                }\n            }\n            else if (e.Button == MouseButtons.Left)\n            {\n                SelectInfantry(navigationWidget.MouseCell);\n            }\n            else if (e.Button == MouseButtons.Right)\n            {\n                PickInfantry(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (selectedInfantry != null)\n            {\n                selectedInfantry = null;\n                UpdateStatus();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedInfantryType != null)\n                {\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.OldCell, new Size(1, 1)), 1, 1));\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.NewCell, new Size(1, 1)), 1, 1));\n                }\n            }\n        }\n\n        private void AddInfantry(Point location)\n        {\n            if (SelectedInfantryType != null)\n            {\n                if (map.Metrics.GetCell(location, out int cell))\n                {\n                    InfantryGroup infantryGroup = null;\n\n                    var techno = map.Technos[cell];\n                    if (techno == null)\n                    {\n                        infantryGroup = new InfantryGroup();\n                        map.Technos.Add(cell, infantryGroup);\n                    }\n                    else if (techno is InfantryGroup)\n                    {\n                        infantryGroup = techno as InfantryGroup;\n                    }\n\n                    if (infantryGroup != null)\n                    {\n                        foreach (var i in InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>())\n                        {\n                            if (infantryGroup.Infantry[i] == null)\n                            {\n                                var infantry = mockInfantry.Clone();\n                                infantryGroup.Infantry[i] = infantry;\n                                infantry.InfantryGroup = infantryGroup;\n                                mapPanel.Invalidate(map, infantryGroup);\n                                plugin.Dirty = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private void RemoveInfantry(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.Technos[cell] is InfantryGroup infantryGroup)\n                {\n                    foreach (var i in InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>())\n                    {\n                        if (infantryGroup.Infantry[i] != null)\n                        {\n                            infantryGroup.Infantry[i] = null;\n                            mapPanel.Invalidate(map, infantryGroup);\n                            plugin.Dirty = true;\n                            break;\n                        }\n                    }\n                    if (infantryGroup.Infantry.All(i => i == null))\n                    {\n                        map.Technos.Remove(infantryGroup);\n                    }\n                }\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedInfantryType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedInfantryType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickInfantry(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.Technos[cell] is InfantryGroup infantryGroup)\n                {\n                    var i = InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>().First();\n                    if (infantryGroup.Infantry[i] is Infantry infantry)\n                    {\n                        SelectedInfantryType = infantry.Type;\n                        mockInfantry.House = infantry.House;\n                        mockInfantry.Strength = infantry.Strength;\n                        mockInfantry.Direction = infantry.Direction;\n                        mockInfantry.Mission = infantry.Mission;\n                        mockInfantry.Trigger = infantry.Trigger;\n                    }\n                }\n            }\n        }\n\n        private void SelectInfantry(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                selectedInfantry = null;\n                if (map.Technos[cell] is InfantryGroup infantryGroup)\n                {\n                    var i = InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>().First();\n                    if (infantryGroup.Infantry[i] is Infantry infantry)\n                    {\n                        selectedInfantry = infantry;\n                    }\n                }\n            }\n\n            UpdateStatus();\n        }\n\n        private void RefreshMapPanel()\n        {\n            if (mockInfantry.Type != null)\n            {\n                var infantryPreview = new Bitmap(Globals.TileWidth, Globals.TileHeight);\n                using (var g = Graphics.FromImage(infantryPreview))\n                {\n                    MapRenderer.Render(map.Theater, Point.Empty, Globals.TileSize, mockInfantry, InfantryStoppingType.Center).Item2(g);\n                }\n                infantryTypeMapPanel.MapImage = infantryPreview;\n            }\n            else\n            {\n                infantryTypeMapPanel.MapImage = null;\n            }\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place infantry, Right-Click to remove infantry\";\n            }\n            else if (selectedInfantry != null)\n            {\n                statusLbl.Text = \"Drag mouse to move infantry\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click drag to move infantry, Double-Click update infantry properties, Right-Click to pick infantry\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedInfantryType != null)\n                {\n                    if (previewMap.Metrics.GetCell(location, out int cell))\n                    {\n                        InfantryGroup infantryGroup = null;\n\n                        var techno = previewMap.Technos[cell];\n                        if (techno == null)\n                        {\n                            infantryGroup = new InfantryGroup();\n                            previewMap.Technos.Add(cell, infantryGroup);\n                        }\n                        else if (techno is InfantryGroup)\n                        {\n                            infantryGroup = techno as InfantryGroup;\n                        }\n\n                        if (infantryGroup != null)\n                        {\n                            foreach (var i in InfantryGroup.ClosestStoppingTypes(navigationWidget.MouseSubPixel).Cast<int>())\n                            {\n                                if (infantryGroup.Infantry[i] == null)\n                                {\n                                    var infantry = mockInfantry.Clone();\n                                    infantry.Tint = Color.FromArgb(128, Color.White);\n                                    infantryGroup.Infantry[i] = infantry;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var infantryPen = new Pen(Color.Green, 4.0f);\n            foreach (var (topLeft, _) in map.Technos.OfType<InfantryGroup>())\n            {\n                var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                graphics.DrawRectangle(infantryPen, bounds);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseDoubleClick -= MapPanel_MouseDoubleClick;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= InfantryTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= InfantryTool_KeyUp;\n\n                    infantryTypeComboBox.SelectedIndexChanged -= InfantryTypeComboBox_SelectedIndexChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/OverlaysTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class OverlaysTool : ViewTool\n    {\n        private readonly TypeComboBox overlayTypeComboBox;\n        private readonly MapPanel overlayTypeMapPanel;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private OverlayType selectedOverlayType;\n        private OverlayType SelectedOverlayType\n        {\n            get => selectedOverlayType;\n            set\n            {\n                if (selectedOverlayType != value)\n                {\n                    if (placementMode && (selectedOverlayType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    selectedOverlayType = value;\n                    overlayTypeComboBox.SelectedValue = selectedOverlayType;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public OverlaysTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox overlayTypeComboBox, MapPanel overlayTypeMapPanel, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += OverlaysTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += OverlaysTool_KeyUp;\n\n            this.overlayTypeComboBox = overlayTypeComboBox;\n            this.overlayTypeComboBox.SelectedIndexChanged += OverlayTypeComboBox_SelectedIndexChanged;\n\n            this.overlayTypeMapPanel = overlayTypeMapPanel;\n            this.overlayTypeMapPanel.BackColor = Color.White;\n            this.overlayTypeMapPanel.MaxZoom = 1;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedOverlayType = this.overlayTypeComboBox.Types.First() as OverlayType;\n\n            UpdateStatus();\n        }\n\n        private void OverlayTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedOverlayType = overlayTypeComboBox.SelectedValue as OverlayType;\n        }\n\n        private void OverlaysTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void OverlaysTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddOverlay(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveOverlay(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickOverlay(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedOverlayType != null)\n                {\n                    mapPanel.Invalidate(map, new Rectangle(e.OldCell, new Size(1, 1)));\n                    mapPanel.Invalidate(map, new Rectangle(e.NewCell, new Size(1, 1)));\n                }\n            }\n        }\n\n        private void AddOverlay(Point location)\n        {\n            if ((location.Y == 0) || (location.Y == (map.Metrics.Height - 1)))\n            {\n                return;\n            }\n\n            if (map.Overlay[location] == null)\n            {\n                if (SelectedOverlayType != null)\n                {\n                    var overlay = new Overlay\n                    {\n                        Type = SelectedOverlayType,\n                        Icon = 0\n                    };\n                    map.Overlay[location] = overlay;\n                    mapPanel.Invalidate(map, location);\n\n                    void undoAction(UndoRedoEventArgs e)\n                    {\n                        e.MapPanel.Invalidate(e.Map, location);\n                        e.Map.Overlay[location] = null;\n                    }\n\n                    void redoAction(UndoRedoEventArgs e)\n                    {\n                        e.Map.Overlay[location] = overlay;\n                        e.MapPanel.Invalidate(e.Map, location);\n                    }\n\n                    url.Track(undoAction, redoAction);\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveOverlay(Point location)\n        {\n            if ((map.Overlay[location] is Overlay overlay) && overlay.Type.IsPlaceable)\n            {\n                map.Overlay[location] = null;\n                mapPanel.Invalidate(map, location);\n\n                void undoAction(UndoRedoEventArgs e)\n                {\n                    e.Map.Overlay[location] = overlay;\n                    e.MapPanel.Invalidate(e.Map, location);\n                }\n\n                void redoAction(UndoRedoEventArgs e)\n                {\n                    e.MapPanel.Invalidate(e.Map, location);\n                    e.Map.Overlay[location] = null;\n                }\n\n                url.Track(undoAction, redoAction);\n\n                plugin.Dirty = true;\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedOverlayType != null)\n            {\n                mapPanel.Invalidate(map, navigationWidget.MouseCell);\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedOverlayType != null)\n            {\n                mapPanel.Invalidate(map, navigationWidget.MouseCell);\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickOverlay(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var overlay = map.Overlay[cell];\n                if ((overlay != null) && !overlay.Type.IsWall)\n                {\n                    SelectedOverlayType = overlay.Type;\n                }\n            }\n        }\n\n        private void RefreshMapPanel()\n        {\n            overlayTypeMapPanel.MapImage = SelectedOverlayType?.Thumbnail;\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place overlay, Right-Click to remove overlay\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click or Right-Click to pick overlay\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedOverlayType != null)\n                {\n                    if (previewMap.Metrics.GetCell(location, out int cell))\n                    {\n                        if (previewMap.Overlay[cell] == null)\n                        {\n                            previewMap.Overlay[cell] = new Overlay\n                            {\n                                Type = SelectedOverlayType,\n                                Icon = 0,\n                                Tint = Color.FromArgb(128, Color.White)\n                            };\n                        }\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var overlayPen = new Pen(Color.Green, 4.0f);\n            foreach (var (cell, overlay) in previewMap.Overlay.Where(x => x.Value.Type.IsPlaceable))\n            {\n                previewMap.Metrics.GetLocation(cell, out Point topLeft);\n                var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                graphics.DrawRectangle(overlayPen, bounds);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    overlayTypeComboBox.SelectedIndexChanged -= OverlayTypeComboBox_SelectedIndexChanged;\n\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= OverlaysTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= OverlaysTool_KeyUp;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/ResourcesTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class ResourcesTool : ViewTool\n    {\n        private readonly Label totalResourcesLbl;\n        private readonly NumericUpDown brushSizeNud;\n        private readonly CheckBox gemsCheckBox;\n\n        private bool placementMode;\n        private bool additivePlacement;\n\n        private readonly Dictionary<int, Overlay> undoOverlays = new Dictionary<int, Overlay>();\n        private readonly Dictionary<int, Overlay> redoOverlays = new Dictionary<int, Overlay>();\n\n        public ResourcesTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, Label totalResourcesLbl, NumericUpDown brushSizeNud, CheckBox gemsCheckBox, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            (this.mapPanel as Control).KeyDown += ResourceTool_KeyDown;\n\n            this.totalResourcesLbl = totalResourcesLbl;\n            this.brushSizeNud = brushSizeNud;\n            this.gemsCheckBox = gemsCheckBox;\n\n            this.brushSizeNud.ValueChanged += BrushSizeNud_ValueChanged;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n            navigationWidget.MouseoverSize = new Size((int)brushSizeNud.Value, (int)brushSizeNud.Value);\n\n            url.Undone += Url_UndoRedo;\n            url.Redone += Url_UndoRedo;\n\n            Update();\n\n            UpdateStatus();\n        }\n\n        private void Url_UndoRedo(object sender, EventArgs e)\n        {\n            Update();\n        }\n\n        private void BrushSizeNud_ValueChanged(object sender, EventArgs e)\n        {\n            navigationWidget.MouseoverSize = new Size((int)brushSizeNud.Value, (int)brushSizeNud.Value);\n        }\n\n        private void ResourceTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.OemOpenBrackets)\n            {\n                brushSizeNud.DownButton();\n                mapPanel.Invalidate();\n            }\n            else if (e.KeyCode == Keys.OemCloseBrackets)\n            {\n                brushSizeNud.UpButton();\n                mapPanel.Invalidate();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (e.Button == MouseButtons.Left)\n            {\n                if (!placementMode)\n                {\n                    EnterPlacementMode(true);\n                    AddResource(navigationWidget.MouseCell);\n                }\n            }\n            else if (e.Button == MouseButtons.Right)\n            {\n                if (!placementMode)\n                {\n                    EnterPlacementMode(false);\n                    RemoveResource(navigationWidget.MouseCell);\n                }\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (((e.Button == MouseButtons.Left) && additivePlacement) ||\n                    ((e.Button == MouseButtons.Right) && !additivePlacement))\n                {\n                    ExitPlacementMode();\n                }\n            }\n\n            if ((undoOverlays.Count > 0) || (redoOverlays.Count > 0))\n            {\n                CommitChange();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (additivePlacement)\n                {\n                    AddResource(e.NewCell);\n                }\n                else\n                {\n                    RemoveResource(e.NewCell);\n                }\n            }\n\n            if (brushSizeNud.Value > 1)\n            {\n                foreach (var cell in new Point[] { e.OldCell, e.NewCell })\n                {\n                    mapPanel.Invalidate(mapPanel.MapToClient(new Rectangle(\n                        new Point(cell.X - ((int)brushSizeNud.Value / 2), cell.Y - ((int)brushSizeNud.Value / 2)),\n                        new Size((int)brushSizeNud.Value, (int)brushSizeNud.Value)\n                    )));\n                }\n            }\n        }\n\n        private void AddResource(Point location)\n        {\n            Rectangle rectangle = new Rectangle(location, new Size(1, 1));\n            rectangle.Inflate(navigationWidget.MouseoverSize.Width / 2, navigationWidget.MouseoverSize.Height / 2);\n            foreach (var subLocation in rectangle.Points())\n            {\n                if ((subLocation.Y == 0) || (subLocation.Y == (map.Metrics.Height - 1)))\n                {\n                    continue;\n                }\n\n                if (map.Metrics.GetCell(subLocation, out int cell))\n                {\n                    if (map.Overlay[cell] == null)\n                    {\n                        var resourceType = gemsCheckBox.Checked ?\n                            map.OverlayTypes.Where(t => t.IsGem).FirstOrDefault() :\n                            map.OverlayTypes.Where(t => t.IsTiberiumOrGold).FirstOrDefault();\n                        if (resourceType != null)\n                        {\n                            if (!undoOverlays.ContainsKey(cell))\n                            {\n                                undoOverlays[cell] = map.Overlay[cell];\n                            }\n\n                            var overlay = new Overlay { Type = resourceType, Icon = 0 };\n                            map.Overlay[cell] = overlay;\n                            redoOverlays[cell] = overlay;\n\n                            plugin.Dirty = true;\n                        }\n                    }\n                }\n            }\n\n            rectangle.Inflate(1, 1);\n            mapPanel.Invalidate(map, rectangle);\n\n            Update();\n        }\n\n        private void RemoveResource(Point location)\n        {\n            Rectangle rectangle = new Rectangle(location, new Size(1, 1));\n            rectangle.Inflate(navigationWidget.MouseoverSize.Width / 2, navigationWidget.MouseoverSize.Height / 2);\n            foreach (var subLocation in rectangle.Points())\n            {\n                if (map.Metrics.GetCell(subLocation, out int cell))\n                {\n                    if (map.Overlay[cell]?.Type.IsResource ?? false)\n                    {\n                        if (!undoOverlays.ContainsKey(cell))\n                        {\n                            undoOverlays[cell] = map.Overlay[cell];\n                        }\n\n                        map.Overlay[cell] = null;\n                        redoOverlays[cell] = null;\n\n                        plugin.Dirty = true;\n                    }\n                }\n            }\n\n            rectangle.Inflate(1, 1);\n            mapPanel.Invalidate(map, rectangle);\n\n            Update();\n        }\n\n        private void EnterPlacementMode(bool additive)\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n            additivePlacement = additive;\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            UpdateStatus();\n        }\n\n        private void CommitChange()\n        {\n            var undoOverlays2 = new Dictionary<int, Overlay>(undoOverlays);\n            void undoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in undoOverlays2)\n                {\n                    e.Map.Overlay[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, undoOverlays2.Keys.Select(k =>\n                {\n                    e.Map.Metrics.GetLocation(k, out Point location);\n                    var rectangle = new Rectangle(location, new Size(1, 1));\n                    rectangle.Inflate(1, 1);\n                    return rectangle;\n                }));\n            }\n\n            var redoOverlays2 = new Dictionary<int, Overlay>(redoOverlays);\n            void redoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in redoOverlays2)\n                {\n                    e.Map.Overlay[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, redoOverlays2.Keys.Select(k =>\n                {\n                    e.Map.Metrics.GetLocation(k, out Point location);\n                    var rectangle = new Rectangle(location, new Size(1, 1));\n                    rectangle.Inflate(1, 1);\n                    return rectangle;\n                }));\n            }\n\n            undoOverlays.Clear();\n            redoOverlays.Clear();\n\n            url.Track(undoAction, redoAction);\n        }\n\n        private void Update()\n        {\n            totalResourcesLbl.Text = map.TotalResources.ToString();\n\n            if (map.OverlayTypes.Any(t => t.IsGem))\n            {\n                gemsCheckBox.Visible = true;\n            }\n            else\n            {\n                gemsCheckBox.Visible = false;\n                gemsCheckBox.Checked = false;\n            }\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                if (additivePlacement)\n                {\n                    statusLbl.Text = \"Drag mouse to add resources\";\n                }\n                else\n                {\n                    statusLbl.Text = \"Drag mouse to remove resources\";\n                }\n            }\n            else\n            {\n                statusLbl.Text = \"Left-Click drag to add resources, Right-Click drag to remove resources\";\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var resourcePen = new Pen(Color.Green, 4.0f);\n            foreach (var (cell, overlay) in map.Overlay)\n            {\n                if (overlay.Type.IsResource)\n                {\n                    map.Metrics.GetLocation(cell, out Point topLeft);\n                    var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                    graphics.DrawRectangle(resourcePen, bounds);\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    (mapPanel as Control).KeyDown -= ResourceTool_KeyDown;\n\n                    brushSizeNud.ValueChanged -= BrushSizeNud_ValueChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n\n                    url.Undone -= Url_UndoRedo;\n                    url.Redone -= Url_UndoRedo;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/SmudgeTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class SmudgeTool : ViewTool\n    {\n        private readonly TypeComboBox smudgeTypeComboBox;\n        private readonly MapPanel smudgeTypeMapPanel;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private SmudgeType selectedSmudgeType;\n        private SmudgeType SelectedSmudgeType\n        {\n            get => selectedSmudgeType;\n            set\n            {\n                if (selectedSmudgeType != value)\n                {\n                    if (placementMode && (selectedSmudgeType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    selectedSmudgeType = value;\n                    smudgeTypeComboBox.SelectedValue = selectedSmudgeType;\n\n                    if (placementMode && (selectedSmudgeType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public SmudgeTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox smudgeTypeComboBox, MapPanel smudgeTypeMapPanel, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += SmudgeTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += SmudgeTool_KeyUp;\n\n            this.smudgeTypeComboBox = smudgeTypeComboBox;\n            this.smudgeTypeComboBox.SelectedIndexChanged += SmudgeTypeComboBox_SelectedIndexChanged;\n\n            this.smudgeTypeMapPanel = smudgeTypeMapPanel;\n            this.smudgeTypeMapPanel.BackColor = Color.White;\n            this.smudgeTypeMapPanel.MaxZoom = 1;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedSmudgeType = smudgeTypeComboBox.Types.First() as SmudgeType;\n\n            UpdateStatus();\n        }\n\n        private void SmudgeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedSmudgeType = smudgeTypeComboBox.SelectedValue as SmudgeType;\n        }\n\n        private void SmudgeTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void SmudgeTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddSmudge(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveSmudge(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickSmudge(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedSmudgeType != null)\n                {\n                    mapPanel.Invalidate(map, e.OldCell);\n                    mapPanel.Invalidate(map, e.NewCell);\n                }\n            }\n        }\n\n        private void AddSmudge(Point location)\n        {\n            if (map.Smudge[location] == null)\n            {\n                if (SelectedSmudgeType != null)\n                {\n                    var smudge = new Smudge\n                    {\n                        Type = SelectedSmudgeType,\n                        Icon = 0,\n                        Data = 0\n                    };\n                    map.Smudge[location] = smudge;\n                    mapPanel.Invalidate(map, location);\n\n                    void undoAction(UndoRedoEventArgs e)\n                    {\n                        e.MapPanel.Invalidate(e.Map, location);\n                        e.Map.Smudge[location] = null;\n                    }\n\n                    void redoAction(UndoRedoEventArgs e)\n                    {\n                        e.Map.Smudge[location] = smudge;\n                        e.MapPanel.Invalidate(e.Map, location);\n                    }\n\n                    url.Track(undoAction, redoAction);\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveSmudge(Point location)\n        {\n            if ((map.Smudge[location] is Smudge smudge) && ((smudge.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))\n            {\n                map.Smudge[location] = null;\n                mapPanel.Invalidate(map, location);\n\n                void undoAction(UndoRedoEventArgs e)\n                {\n                    e.Map.Smudge[location] = smudge;\n                    e.MapPanel.Invalidate(e.Map, location);\n                }\n\n                void redoAction(UndoRedoEventArgs e)\n                {\n                    e.MapPanel.Invalidate(e.Map, location);\n                    e.Map.Smudge[location] = null;\n                }\n\n                url.Track(undoAction, redoAction);\n\n                plugin.Dirty = true;\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedSmudgeType != null)\n            {\n                mapPanel.Invalidate(map, navigationWidget.MouseCell);\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedSmudgeType != null)\n            {\n                mapPanel.Invalidate(map, navigationWidget.MouseCell);\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickSmudge(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var smudge = map.Smudge[cell];\n                if (smudge != null)\n                {\n                    SelectedSmudgeType = smudge.Type;\n                }\n            }\n        }\n\n        private void RefreshMapPanel()\n        {\n            smudgeTypeMapPanel.MapImage = SelectedSmudgeType?.Thumbnail;\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place smudge, Right-Click to remove smudge\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click or Right-Click to pick smudge\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedSmudgeType != null)\n                {\n                    if (previewMap.Metrics.GetCell(location, out int cell))\n                    {\n                        if (previewMap.Smudge[cell] == null)\n                        {\n                            previewMap.Smudge[cell] = new Smudge { Type = SelectedSmudgeType, Data = 0, Tint = Color.FromArgb(128, Color.White) };\n                        }\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var smudgePen = new Pen(Color.Green, 4.0f);\n            foreach (var (cell, smudge) in previewMap.Smudge.Where(x => (x.Value.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))\n            {\n                previewMap.Metrics.GetLocation(cell, out Point topLeft);\n                var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                graphics.DrawRectangle(smudgePen, bounds);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    smudgeTypeComboBox.SelectedIndexChanged -= SmudgeTypeComboBox_SelectedIndexChanged;\n\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= SmudgeTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= SmudgeTool_KeyUp;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/TemplateTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class TemplateTool : ViewTool\n    {\n        private static readonly Regex CategoryRegex = new Regex(@\"^([a-z]*)\", RegexOptions.Compiled);\n\n        private readonly ListView templateTypeListView;\n        private readonly MapPanel templateTypeMapPanel;\n        private readonly ToolTip mouseTooltip;\n\n        private readonly Dictionary<int, Template> undoTemplates = new Dictionary<int, Template>();\n        private readonly Dictionary<int, Template> redoTemplates = new Dictionary<int, Template>();\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private bool boundsMode;\n        private Rectangle dragBounds;\n        private int dragEdge = -1;\n\n        private TemplateType selectedTemplateType;\n        private TemplateType SelectedTemplateType\n        {\n            get => selectedTemplateType;\n            set\n            {\n                if (selectedTemplateType != value)\n                {\n                    if (placementMode && (selectedTemplateType != null))\n                    {\n                        for (var y = 0; y < selectedTemplateType.IconHeight; ++y)\n                        {\n                            for (var x = 0; x < selectedTemplateType.IconWidth; ++x)\n                            {\n                                mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                            }\n                        }\n                    }\n\n                    selectedTemplateType = value;\n\n                    templateTypeListView.BeginUpdate();\n                    templateTypeListView.SelectedIndexChanged -= TemplateTypeListView_SelectedIndexChanged;\n                    foreach (ListViewItem item in templateTypeListView.Items)\n                    {\n                        item.Selected = item.Tag == selectedTemplateType;\n                    }\n                    if (templateTypeListView.SelectedIndices.Count > 0)\n                    {\n                        templateTypeListView.EnsureVisible(templateTypeListView.SelectedIndices[0]);\n                    }\n                    templateTypeListView.SelectedIndexChanged += TemplateTypeListView_SelectedIndexChanged;\n                    templateTypeListView.EndUpdate();\n\n                    if (placementMode && (selectedTemplateType != null))\n                    {\n                        for (var y = 0; y < selectedTemplateType.IconHeight; ++y)\n                        {\n                            for (var x = 0; x < selectedTemplateType.IconWidth; ++x)\n                            {\n                                mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                            }\n                        }\n                    }\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        private Point? selectedIcon;\n        private Point? SelectedIcon\n        {\n            get => selectedIcon;\n            set\n            {\n                if (selectedIcon != value)\n                {\n                    selectedIcon = value;\n                    templateTypeMapPanel.Invalidate();\n\n                    if (placementMode && (SelectedTemplateType != null))\n                    {\n                        for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                        {\n                            for (var x = 0; x < SelectedTemplateType.IconWidth; ++x)\n                            {\n                                mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private NavigationWidget templateTypeNavigationWidget;\n\n        public TemplateTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, ListView templateTypeListView, MapPanel templateTypeMapPanel, ToolTip mouseTooltip, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += TemplateTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += TemplateTool_KeyUp;\n\n            this.templateTypeListView = templateTypeListView;\n            this.templateTypeListView.SelectedIndexChanged += TemplateTypeListView_SelectedIndexChanged;\n\n            string templateCategory(TemplateType template)\n            {\n                var m = CategoryRegex.Match(template.Name);\n                return m.Success ? m.Groups[1].Value : string.Empty;\n            }\n\n            var templateTypes = plugin.Map.TemplateTypes\n                .Where(t =>\n                    (t.Thumbnail != null) &&\n                    t.Theaters.Contains(plugin.Map.Theater) &&\n                    ((t.Flag & TemplateTypeFlag.Clear) == TemplateTypeFlag.None))\n                .GroupBy(t => templateCategory(t)).OrderBy(g => g.Key);\n            var templateTypeImages = templateTypes.SelectMany(g => g).Select(t => t.Thumbnail);\n\n            var maxWidth = templateTypeImages.Max(t => t.Width);\n            var maxHeight = templateTypeImages.Max(t => t.Height);\n\n            var imageList = new ImageList();\n            imageList.Images.AddRange(templateTypeImages.ToArray());\n            imageList.ImageSize = new Size(maxWidth, maxHeight);\n            imageList.ColorDepth = ColorDepth.Depth24Bit;\n\n            this.templateTypeListView.BeginUpdate();\n            this.templateTypeListView.LargeImageList = imageList;\n\n            var imageIndex = 0;\n            foreach (var templateTypeGroup in templateTypes)\n            {\n                var group = new ListViewGroup(templateTypeGroup.Key);\n                this.templateTypeListView.Groups.Add(group);\n                foreach (var templateType in templateTypeGroup)\n                {\n                    var item = new ListViewItem(templateType.DisplayName, imageIndex++)\n                    {\n                        Group = group,\n                        Tag = templateType\n                    };\n                    this.templateTypeListView.Items.Add(item);\n                }\n            }\n            this.templateTypeListView.EndUpdate();\n\n            this.templateTypeMapPanel = templateTypeMapPanel;\n            this.templateTypeMapPanel.MouseDown += TemplateTypeMapPanel_MouseDown;\n            this.templateTypeMapPanel.PostRender += TemplateTypeMapPanel_PostRender;\n            this.templateTypeMapPanel.BackColor = Color.Black;\n            this.templateTypeMapPanel.MaxZoom = 1;\n\n            this.mouseTooltip = mouseTooltip;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            url.Undone += Url_Undone;\n            url.Redone += Url_Redone;\n\n            SelectedTemplateType = templateTypes.First().First();\n\n            UpdateStatus();\n        }\n\n        private void Url_Redone(object sender, EventArgs e)\n        {\n            if (boundsMode && (map.Bounds != dragBounds))\n            {\n                dragBounds = map.Bounds;\n                dragEdge = -1;\n\n                UpdateTooltip();\n                mapPanel.Invalidate();\n            }\n        }\n\n        private void Url_Undone(object sender, EventArgs e)\n        {\n            if (boundsMode && (map.Bounds != dragBounds))\n            {\n                dragBounds = map.Bounds;\n                dragEdge = -1;\n\n                UpdateTooltip();\n                mapPanel.Invalidate();\n            }\n        }\n\n        private void TemplateTypeMapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if ((SelectedTemplateType == null) || ((SelectedTemplateType.IconWidth * SelectedTemplateType.IconHeight) == 1))\n            {\n                SelectedIcon = null;\n            }\n            else\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    var templateTypeMouseCell = templateTypeNavigationWidget.MouseCell;\n                    if ((templateTypeMouseCell.X >= 0) && (templateTypeMouseCell.X < SelectedTemplateType.IconWidth))\n                    {\n                        if ((templateTypeMouseCell.Y >= 0) && (templateTypeMouseCell.Y < SelectedTemplateType.IconHeight))\n                        {\n                            if (SelectedTemplateType.IconMask[templateTypeMouseCell.X, templateTypeMouseCell.Y])\n                            {\n                                SelectedIcon = templateTypeMouseCell;\n                            }\n                        }\n                    }\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    SelectedIcon = null;\n                }\n            }\n        }\n\n        private void TemplateTypeMapPanel_PostRender(object sender, RenderEventArgs e)\n        {\n            if (SelectedIcon.HasValue)\n            {\n                var selectedIconPen = new Pen(Color.Yellow, 2);\n                var cellSize = new Size(Globals.OriginalTileWidth / 4, Globals.OriginalTileHeight / 4);\n                var rect = new Rectangle(new Point(SelectedIcon.Value.X * cellSize.Width, SelectedIcon.Value.Y * cellSize.Height), cellSize);\n                e.Graphics.DrawRectangle(selectedIconPen, rect);\n            }\n\n            if (SelectedTemplateType != null)\n            {\n                var sizeStringFormat = new StringFormat\n                {\n                    Alignment = StringAlignment.Center,\n                    LineAlignment = StringAlignment.Center\n                };\n                var sizeBackgroundBrush = new SolidBrush(Color.FromArgb(128, Color.Black));\n                var sizeTextBrush = new SolidBrush(Color.White);\n\n                var text = string.Format(\"{0} ({1}x{2})\", SelectedTemplateType.DisplayName, SelectedTemplateType.IconWidth, SelectedTemplateType.IconHeight);\n                var textSize = e.Graphics.MeasureString(text, SystemFonts.CaptionFont) + new SizeF(6.0f, 6.0f);\n                var textBounds = new RectangleF(new PointF(0, 0), textSize);\n                e.Graphics.Transform = new Matrix();\n                e.Graphics.FillRectangle(sizeBackgroundBrush, textBounds);\n                e.Graphics.DrawString(text, SystemFonts.CaptionFont, sizeTextBrush, textBounds, sizeStringFormat);\n            }\n        }\n\n        private void TemplateTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n            else if (e.KeyCode == Keys.ControlKey)\n            {\n                EnterBoundsMode();\n            }\n        }\n\n        private void TemplateTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if ((e.KeyCode == Keys.ShiftKey) || (e.KeyCode == Keys.ControlKey))\n            {\n                ExitAllModes();\n            }\n        }\n\n        private void TemplateTypeListView_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedTemplateType = (templateTypeListView.SelectedItems.Count > 0) ? (templateTypeListView.SelectedItems[0].Tag as TemplateType) : null;\n            SelectedIcon = null;\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (boundsMode)\n            {\n                dragEdge = DetectDragEdge();\n\n                UpdateStatus();\n            }\n            else if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    SetTemplate(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveTemplate(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickTemplate(navigationWidget.MouseCell, e.Button == MouseButtons.Left);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (boundsMode)\n            {\n                if (dragBounds != map.Bounds)\n                {\n                    var oldBounds = map.Bounds;\n                    void undoAction(UndoRedoEventArgs ure)\n                    {\n                        ure.Map.Bounds = oldBounds;\n                        ure.MapPanel.Invalidate();\n                    }\n\n                    void redoAction(UndoRedoEventArgs ure)\n                    {\n                        ure.Map.Bounds = dragBounds;\n                        ure.MapPanel.Invalidate();\n                    }\n\n                    map.Bounds = dragBounds;\n\n                    url.Track(undoAction, redoAction);\n                    mapPanel.Invalidate();\n                }\n\n                dragEdge = -1;\n\n                UpdateStatus();\n            }\n            else\n            {\n                if ((undoTemplates.Count > 0) || (redoTemplates.Count > 0))\n                {\n                    CommitChange();\n                }\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (!boundsMode && (Control.ModifierKeys == Keys.Control))\n            {\n                EnterBoundsMode();\n            }\n            else if ((placementMode || boundsMode) && (Control.ModifierKeys == Keys.None))\n            {\n                ExitAllModes();\n            }\n\n            var cursor = Cursors.Default;\n            if (boundsMode)\n            {\n                switch ((dragEdge >= 0) ? dragEdge : DetectDragEdge())\n                {\n                    case 0:\n                    case 4:\n                        cursor = Cursors.SizeNS;\n                        break;\n                    case 2:\n                    case 6:\n                        cursor = Cursors.SizeWE;\n                        break;\n                    case 1:\n                    case 5:\n                        cursor = Cursors.SizeNESW;\n                        break;\n                    case 3:\n                    case 7:\n                        cursor = Cursors.SizeNWSE;\n                        break;\n                }\n            }\n            Cursor.Current = cursor;\n\n            UpdateTooltip();\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (dragEdge >= 0)\n            {\n                var endDrag = navigationWidget.MouseCell;\n                map.Metrics.Clip(ref endDrag, new Size(1, 1), Size.Empty);\n\n                switch (dragEdge)\n                {\n                    case 0:\n                    case 1:\n                    case 7:\n                        if (endDrag.Y < dragBounds.Bottom)\n                        {\n                            dragBounds.Height = dragBounds.Bottom - endDrag.Y;\n                            dragBounds.Y = endDrag.Y;\n                        }\n                        break;\n                }\n\n                switch (dragEdge)\n                {\n                    case 5:\n                    case 6:\n                    case 7:\n                        if (endDrag.X < dragBounds.Right)\n                        {\n                            dragBounds.Width = dragBounds.Right - endDrag.X;\n                            dragBounds.X = endDrag.X;\n                        }\n                        break;\n                }\n\n                switch (dragEdge)\n                {\n                    case 3:\n                    case 4:\n                    case 5:\n                        if (endDrag.Y > dragBounds.Top)\n                        {\n                            dragBounds.Height = endDrag.Y - dragBounds.Top;\n                        }\n                        break;\n                }\n\n                switch (dragEdge)\n                {\n                    case 1:\n                    case 2:\n                    case 3:\n                        if (endDrag.X > dragBounds.Left)\n                        {\n                            dragBounds.Width = endDrag.X - dragBounds.Left;\n                        }\n                        break;\n                }\n\n                mapPanel.Invalidate();\n            }\n            else if (placementMode)\n            {\n                if (Control.MouseButtons == MouseButtons.Right)\n                {\n                    RemoveTemplate(navigationWidget.MouseCell);\n                }\n\n                if (SelectedTemplateType != null)\n                {\n                    foreach (var location in new Point[] { e.OldCell, e.NewCell })\n                    {\n                        for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                        {\n                            for (var x = 0; x < SelectedTemplateType.IconWidth; ++x)\n                            {\n                                mapPanel.Invalidate(map, new Point(location.X + x, location.Y + y));\n                            }\n                        }\n                    }\n                }\n            }\n            else if((Control.MouseButtons == MouseButtons.Left) || (Control.MouseButtons == MouseButtons.Right))\n            {\n                PickTemplate(navigationWidget.MouseCell, Control.MouseButtons == MouseButtons.Left);\n            }\n        }\n\n        private void RefreshMapPanel()\n        {\n            if (templateTypeNavigationWidget != null)\n            {\n                templateTypeNavigationWidget.Dispose();\n                templateTypeNavigationWidget = null;\n            }\n\n            if (SelectedTemplateType != null)\n            {\n                templateTypeMapPanel.MapImage = SelectedTemplateType.Thumbnail;\n\n                var templateTypeMetrics = new CellMetrics(SelectedTemplateType.IconWidth, SelectedTemplateType.IconHeight);\n                templateTypeNavigationWidget = new NavigationWidget(templateTypeMapPanel, templateTypeMetrics,\n                    new Size(Globals.OriginalTileWidth / 4, Globals.OriginalTileHeight / 4));\n                templateTypeNavigationWidget.MouseoverSize = Size.Empty;\n            }\n            else\n            {\n                templateTypeMapPanel.MapImage = null;\n            }\n        }\n\n        private void SetTemplate(Point location)\n        {\n            if (SelectedTemplateType != null)\n            {\n                if (SelectedIcon.HasValue)\n                {\n                    if (map.Metrics.GetCell(location, out int cell))\n                    {\n                        if (!undoTemplates.ContainsKey(cell))\n                        {\n                            undoTemplates[cell] = map.Templates[location];\n                        }\n\n                        var icon = (SelectedIcon.Value.Y * SelectedTemplateType.IconWidth) + SelectedIcon.Value.X;\n                        var template = new Template { Type = SelectedTemplateType, Icon = icon };\n                        map.Templates[cell] = template;\n                        redoTemplates[cell] = template;\n                        mapPanel.Invalidate(map, cell);\n                        plugin.Dirty = true;\n                    }\n                }\n                else\n                {\n                    for (int y = 0, icon = 0; y < SelectedTemplateType.IconHeight; ++y)\n                    {\n                        for (var x = 0; x < SelectedTemplateType.IconWidth; ++x, ++icon)\n                        {\n                            var subLocation = new Point(location.X + x, location.Y + y);\n                            if (map.Metrics.GetCell(subLocation, out int cell))\n                            {\n                                if (!undoTemplates.ContainsKey(cell))\n                                {\n                                    undoTemplates[cell] = map.Templates[subLocation];\n                                }\n                            }\n                        }\n                    }\n\n                    for (int y = 0, icon = 0; y < SelectedTemplateType.IconHeight; ++y)\n                    {\n                        for (var x = 0; x < SelectedTemplateType.IconWidth; ++x, ++icon)\n                        {\n                            if (!SelectedTemplateType.IconMask[x, y])\n                            {\n                                continue;\n                            }\n\n                            var subLocation = new Point(location.X + x, location.Y + y);\n                            if (map.Metrics.GetCell(subLocation, out int cell))\n                            {\n                                var template = new Template { Type = SelectedTemplateType, Icon = icon };\n                                map.Templates[cell] = template;\n                                redoTemplates[cell] = template;\n                                mapPanel.Invalidate(map, cell);\n                                plugin.Dirty = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private void RemoveTemplate(Point location)\n        {\n            if (SelectedTemplateType != null)\n            {\n                if (SelectedIcon.HasValue)\n                {\n                    if (map.Metrics.GetCell(location, out int cell))\n                    {\n                        if (!undoTemplates.ContainsKey(cell))\n                        {\n                            undoTemplates[cell] = map.Templates[location];\n                        }\n\n                        map.Templates[cell] = null;\n                        redoTemplates[cell] = null;\n                        mapPanel.Invalidate(map, cell);\n                        plugin.Dirty = true;\n                    }\n                }\n                else\n                {\n                    for (int y = 0, icon = 0; y < SelectedTemplateType.IconHeight; ++y)\n                    {\n                        for (var x = 0; x < SelectedTemplateType.IconWidth; ++x, ++icon)\n                        {\n                            var subLocation = new Point(location.X + x, location.Y + y);\n                            if (map.Metrics.GetCell(subLocation, out int cell))\n                            {\n                                if (!undoTemplates.ContainsKey(cell))\n                                {\n                                    undoTemplates[cell] = map.Templates[subLocation];\n                                }\n                            }\n                        }\n                    }\n\n                    for (int y = 0, icon = 0; y < SelectedTemplateType.IconHeight; ++y)\n                    {\n                        for (var x = 0; x < SelectedTemplateType.IconWidth; ++x, ++icon)\n                        {\n                            var subLocation = new Point(location.X + x, location.Y + y);\n                            if (map.Metrics.GetCell(subLocation, out int cell))\n                            {\n                                map.Templates[cell] = null;\n                                redoTemplates[cell] = null;\n                                mapPanel.Invalidate(map, cell);\n                                plugin.Dirty = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode || boundsMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedTemplateType != null)\n            {\n                for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                {\n                    for (var x = 0; x < SelectedTemplateType.IconWidth; ++x)\n                    {\n                        mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                    }\n                }\n            }\n\n            UpdateStatus();\n        }\n\n        private void EnterBoundsMode()\n        {\n            if (boundsMode || placementMode)\n            {\n                return;\n            }\n\n            boundsMode = true;\n            dragBounds = map.Bounds;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedTemplateType != null)\n            {\n                for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                {\n                    for (var x = 0; x < SelectedTemplateType.IconWidth; ++x)\n                    {\n                        mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                    }\n                }\n            }\n\n            UpdateTooltip();\n            UpdateStatus();\n        }\n\n        private void ExitAllModes()\n        {\n            if (!placementMode && !boundsMode)\n            {\n                return;\n            }\n\n            boundsMode = false;\n            dragEdge = -1;\n            dragBounds = Rectangle.Empty;\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedTemplateType != null)\n            {\n                for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                {\n                    for (var x = 0; x < SelectedTemplateType.IconWidth; ++x)\n                    {\n                        mapPanel.Invalidate(map, new Point(navigationWidget.MouseCell.X + x, navigationWidget.MouseCell.Y + y));\n                    }\n                }\n            }\n\n            UpdateTooltip();\n            UpdateStatus();\n        }\n\n        private void UpdateTooltip()\n        {\n            if (boundsMode)\n            {\n                var tooltip = string.Format(\"X = {0}\\nY = {1}\\nWidth = {2}\\nHeight = {3}\", dragBounds.Left, dragBounds.Top, dragBounds.Width, dragBounds.Height);\n                var textSize = TextRenderer.MeasureText(tooltip, SystemFonts.CaptionFont);\n                var tooltipSize = new Size(textSize.Width + 6, textSize.Height + 6);\n\n                var tooltipPosition = mapPanel.PointToClient(Control.MousePosition);\n                switch (dragEdge)\n                {\n                    case -1:\n                    case 0:\n                    case 1:\n                    case 7:\n                        tooltipPosition.Y -= tooltipSize.Height;\n                        break;\n                }\n                switch (dragEdge)\n                {\n                    case -1:\n                    case 5:\n                    case 6:\n                    case 7:\n                        tooltipPosition.X -= tooltipSize.Width;\n                        break;\n                }\n\n                var screenPosition = mapPanel.PointToScreen(tooltipPosition);\n                var screen = Screen.FromControl(mapPanel);\n                screenPosition.X = Math.Max(0, Math.Min(screen.WorkingArea.Width - tooltipSize.Width, screenPosition.X));\n                screenPosition.Y = Math.Max(0, Math.Min(screen.WorkingArea.Height - tooltipSize.Height, screenPosition.Y));\n                tooltipPosition = mapPanel.PointToClient(screenPosition);\n\n                mouseTooltip.Show(tooltip, mapPanel, tooltipPosition.X, tooltipPosition.Y);\n            }\n            else\n            {\n                mouseTooltip.Hide(mapPanel);\n            }\n        }\n\n        private void PickTemplate(Point location, bool wholeTemplate)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var template = map.Templates[cell];\n                if (template != null)\n                {\n                    SelectedTemplateType = template.Type;\n                }\n                else\n                {\n                    SelectedTemplateType = map.TemplateTypes.Where(t => t.Equals(\"clear1\")).FirstOrDefault();\n                }\n\n                if (!wholeTemplate && ((SelectedTemplateType.IconWidth * SelectedTemplateType.IconHeight) > 1))\n                {\n                    var icon = template?.Icon ?? 0;\n                    SelectedIcon = new Point(icon % SelectedTemplateType.IconWidth, icon / SelectedTemplateType.IconWidth);\n                }\n                else\n                {\n                    SelectedIcon = null;\n                }\n            }\n        }\n\n        private int DetectDragEdge()\n        {\n            var mouseCell = navigationWidget.MouseCell;\n            var mousePixel = navigationWidget.MouseSubPixel;\n            var topEdge =\n                ((mouseCell.Y == dragBounds.Top) && (mousePixel.Y <= (Globals.PixelHeight / 4))) ||\n                ((mouseCell.Y == dragBounds.Top - 1) && (mousePixel.Y >= (3 * Globals.PixelHeight / 4)));\n            var bottomEdge =\n                ((mouseCell.Y == dragBounds.Bottom) && (mousePixel.Y <= (Globals.PixelHeight / 4))) ||\n                ((mouseCell.Y == dragBounds.Bottom - 1) && (mousePixel.Y >= (3 * Globals.PixelHeight / 4)));\n            var leftEdge =\n                 ((mouseCell.X == dragBounds.Left) && (mousePixel.X <= (Globals.PixelWidth / 4))) ||\n                 ((mouseCell.X == dragBounds.Left - 1) && (mousePixel.X >= (3 * Globals.PixelWidth / 4)));\n            var rightEdge =\n                ((mouseCell.X == dragBounds.Right) && (mousePixel.X <= (Globals.PixelHeight / 4))) ||\n                ((mouseCell.X == dragBounds.Right - 1) && (mousePixel.X >= (3 * Globals.PixelHeight / 4)));\n            if (topEdge)\n            {\n                if (rightEdge)\n                {\n                    return 1;\n                }\n                else if (leftEdge)\n                {\n                    return 7;\n                }\n                else\n                {\n                    return 0;\n                }\n            }\n            else if (bottomEdge)\n            {\n                if (rightEdge)\n                {\n                    return 3;\n                }\n                else if (leftEdge)\n                {\n                    return 5;\n                }\n                else\n                {\n                    return 4;\n                }\n            }\n            else if (rightEdge)\n            {\n                return 2;\n            }\n            else if (leftEdge)\n            {\n                return 6;\n            }\n            else\n            {\n                return -1;\n            }\n        }\n\n        private void CommitChange()\n        {\n            var undoTemplates2 = new Dictionary<int, Template>(undoTemplates);\n            void undoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in undoTemplates2)\n                {\n                    e.Map.Templates[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, undoTemplates2.Keys);\n            }\n\n            var redoTemplates2 = new Dictionary<int, Template>(redoTemplates);\n            void redoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in redoTemplates2)\n                {\n                    e.Map.Templates[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, redoTemplates2.Keys);\n            }\n\n            undoTemplates.Clear();\n            redoTemplates.Clear();\n\n            url.Track(undoAction, redoAction);\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place template, Right-Click to clear template\";\n            }\n            else if (boundsMode)\n            {\n                if (dragEdge >= 0)\n                {\n                    statusLbl.Text = \"Release left button to end dragging map bounds edge\";\n                }\n                else\n                {\n                    statusLbl.Text = \"Left-Click a map bounds edge to start dragging\";\n                }\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Ctrl to enter map bounds mode, Left-Click to pick whole template, Right-Click to pick individual template tile\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedTemplateType != null)\n                {\n                    if (SelectedIcon.HasValue)\n                    {\n                        if (previewMap.Metrics.GetCell(location, out int cell))\n                        {\n                            var icon = (SelectedIcon.Value.Y * SelectedTemplateType.IconWidth) + SelectedIcon.Value.X;\n                            previewMap.Templates[cell] = new Template { Type = SelectedTemplateType, Icon = icon };\n                        }\n                    }\n                    else\n                    {\n                        int icon = 0;\n                        for (var y = 0; y < SelectedTemplateType.IconHeight; ++y)\n                        {\n                            for (var x = 0; x < SelectedTemplateType.IconWidth; ++x, ++icon)\n                            {\n                                if (!SelectedTemplateType.IconMask[x, y])\n                                {\n                                    continue;\n                                }\n\n                                var subLocation = new Point(location.X + x, location.Y + y);\n                                if (previewMap.Metrics.GetCell(subLocation, out int cell))\n                                {\n                                    previewMap.Templates[cell] = new Template { Type = SelectedTemplateType, Icon = icon };\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            if (boundsMode)\n            {\n                var bounds = Rectangle.FromLTRB(\n                    dragBounds.Left * Globals.TileWidth,\n                    dragBounds.Top * Globals.TileHeight,\n                    dragBounds.Right * Globals.TileWidth,\n                    dragBounds.Bottom * Globals.TileHeight\n                );\n\n                var boundsPen = new Pen(Color.Red, 8.0f);\n                graphics.DrawRectangle(boundsPen, bounds);\n            }\n            else if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedTemplateType != null)\n                {\n                    var previewPen = new Pen(Color.Green, 4.0f);\n                    var previewBounds = new Rectangle(\n                        location.X * Globals.TileWidth,\n                        location.Y * Globals.TileHeight,\n                        (SelectedIcon.HasValue ? 1 : SelectedTemplateType.IconWidth) * Globals.TileWidth,\n                        (SelectedIcon.HasValue ? 1 : SelectedTemplateType.IconHeight) * Globals.TileHeight\n                    );\n                    graphics.DrawRectangle(previewPen, previewBounds);\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= TemplateTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= TemplateTool_KeyUp;\n\n                    templateTypeListView.SelectedIndexChanged -= TemplateTypeListView_SelectedIndexChanged;\n\n                    templateTypeMapPanel.MouseDown -= TemplateTypeMapPanel_MouseDown;\n                    templateTypeMapPanel.PostRender -= TemplateTypeMapPanel_PostRender;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n\n                    url.Undone -= Url_Undone;\n                    url.Redone -= Url_Redone;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/TerrainTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class TerrainTool : ViewTool\n    {\n        private readonly TypeComboBox terrainTypeComboBox;\n        private readonly MapPanel terrainTypeMapPanel;\n        private readonly TerrainProperties terrainProperties;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private readonly Terrain mockTerrain;\n\n        private Terrain selectedTerrain;\n        private Point selectedTerrainPivot;\n\n        private TerrainType selectedTerrainType;\n        private TerrainPropertiesPopup selectedTerrainProperties;\n        private TerrainType SelectedTerrainType\n        {\n            get => selectedTerrainType;\n            set\n            {\n                if (selectedTerrainType != value)\n                {\n                    if (placementMode && (selectedTerrainType != null))\n                    {\n                        mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedTerrainType.OverlapBounds.Size));\n                    }\n\n                    selectedTerrainType = value;\n                    terrainTypeComboBox.SelectedValue = selectedTerrainType;\n\n                    if (placementMode && (selectedTerrainType != null))\n                    {\n                        mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedTerrainType.OverlapBounds.Size));\n                    }\n\n                    mockTerrain.Type = selectedTerrainType;\n                    mockTerrain.Icon = selectedTerrainType.IsTransformable ? 22 : 0;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public TerrainTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox terrainTypeComboBox, MapPanel terrainTypeMapPanel, TerrainProperties terrainProperties, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            mockTerrain = new Terrain();\n            mockTerrain.PropertyChanged += MockTerrain_PropertyChanged;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseDoubleClick += MapPanel_MouseDoubleClick;\n            (this.mapPanel as Control).KeyDown += TerrainTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += TerrainTool_KeyUp;\n\n            this.terrainTypeComboBox = terrainTypeComboBox;\n            this.terrainTypeComboBox.SelectedIndexChanged += TerrainTypeCombo_SelectedIndexChanged;\n\n            this.terrainTypeMapPanel = terrainTypeMapPanel;\n            this.terrainTypeMapPanel.BackColor = Color.White;\n            this.terrainTypeMapPanel.MaxZoom = 1;\n\n            this.terrainProperties = terrainProperties;\n            this.terrainProperties.Terrain = mockTerrain;\n            this.terrainProperties.Visible = plugin.GameType == GameType.TiberianDawn;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedTerrainType = terrainTypeComboBox.Types.First() as TerrainType;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDoubleClick(object sender, MouseEventArgs e)\n        {\n            if (Control.ModifierKeys != Keys.None)\n            {\n                return;\n            }\n\n            if (map.Metrics.GetCell(navigationWidget.MouseCell, out int cell))\n            {\n                if (map.Technos[cell] is Terrain terrain)\n                {\n                    selectedTerrain = null;\n\n                    selectedTerrainProperties?.Close();\n                    selectedTerrainProperties = new TerrainPropertiesPopup(terrainProperties.Plugin, terrain);\n                    selectedTerrainProperties.Closed += (cs, ce) =>\n                    {\n                        navigationWidget.Refresh();\n                    };\n\n                    selectedTerrainProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));\n\n                    UpdateStatus();\n                }\n            }\n        }\n\n        private void MockTerrain_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            RefreshMapPanel();\n        }\n\n        private void TerrainTypeCombo_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedTerrainType = terrainTypeComboBox.SelectedValue as TerrainType;\n        }\n\n        private void TerrainTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void TerrainTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddTerrain(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveTerrain(navigationWidget.MouseCell);\n                }\n            }\n            else if (e.Button == MouseButtons.Left)\n            {\n                SelectTerrain(navigationWidget.MouseCell);\n            }\n            else if (e.Button == MouseButtons.Right)\n            {\n                PickTerrain(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (selectedTerrain != null)\n            {\n                selectedTerrain = null;\n                selectedTerrainPivot = Point.Empty;\n\n                UpdateStatus();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedTerrainType != null)\n                {\n                    mapPanel.Invalidate(map, new Rectangle(e.OldCell, SelectedTerrainType.OverlapBounds.Size));\n                    mapPanel.Invalidate(map, new Rectangle(e.NewCell, SelectedTerrainType.OverlapBounds.Size));\n                }\n            }\n            else if (selectedTerrain != null)\n            {\n                var oldLocation = map.Technos[selectedTerrain].Value;\n                var newLocation = new Point(Math.Max(0, e.NewCell.X - selectedTerrainPivot.X), Math.Max(0, e.NewCell.Y - selectedTerrainPivot.Y));\n                mapPanel.Invalidate(map, selectedTerrain);\n                map.Technos.Remove(selectedTerrain);\n                if (map.Technos.Add(newLocation, selectedTerrain))\n                {\n                    mapPanel.Invalidate(map, selectedTerrain);\n                }\n                else\n                {\n                    map.Technos.Add(oldLocation, selectedTerrain);\n                }\n            }\n        }\n\n        private void AddTerrain(Point location)\n        {\n            if (!map.Metrics.Contains(location))\n            {\n                return;\n            }\n\n            if (SelectedTerrainType != null)\n            {\n                var terrain = mockTerrain.Clone();\n                if (map.Technos.Add(location, terrain))\n                {\n                    mapPanel.Invalidate(map, terrain);\n\n                    void undoAction(UndoRedoEventArgs e)\n                    {\n                        e.MapPanel.Invalidate(e.Map, location);\n                        e.Map.Technos.Remove(terrain);\n                    }\n\n                    void redoAction(UndoRedoEventArgs e)\n                    {\n                        e.Map.Technos.Add(location, terrain);\n                        e.MapPanel.Invalidate(e.Map, location);\n                    }\n\n                    url.Track(undoAction, redoAction);\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveTerrain(Point location)\n        {\n            if (map.Technos[location] is Terrain terrain)\n            {\n                mapPanel.Invalidate(map, terrain);\n                map.Technos.Remove(location);\n\n                void undoAction(UndoRedoEventArgs e)\n                {\n                    e.Map.Technos.Add(location, terrain);\n                    e.MapPanel.Invalidate(e.Map, location);\n                }\n\n                void redoAction(UndoRedoEventArgs e)\n                {\n                    e.MapPanel.Invalidate(e.Map, location);\n                    e.Map.Technos.Remove(terrain);\n                }\n\n                url.Track(undoAction, redoAction);\n\n                plugin.Dirty = true;\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedTerrainType != null)\n            {\n                mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedTerrainType.OverlapBounds.Size));\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedTerrainType != null)\n            {\n                mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedTerrainType.OverlapBounds.Size));\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickTerrain(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.Technos[cell] is Terrain terrain)\n                {\n                    SelectedTerrainType = terrain.Type;\n                    mockTerrain.Trigger = terrain.Trigger;\n                }\n            }\n        }\n\n        private void SelectTerrain(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                selectedTerrain = map.Technos[cell] as Terrain;\n                selectedTerrainPivot = (selectedTerrain != null) ? (location - (Size)map.Technos[selectedTerrain].Value) : Point.Empty;\n            }\n\n            UpdateStatus();\n        }\n\n        private void RefreshMapPanel()\n        {\n            terrainTypeMapPanel.MapImage = mockTerrain.Type.Thumbnail;\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place terrain, Right-Click to remove terrain\";\n            }\n            else if (selectedTerrain != null)\n            {\n                statusLbl.Text = \"Drag mouse to move terrain\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click drag to move terrain, Double-Click update terrain properties, Right-Click to pick terrain\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedTerrainType != null)\n                {\n                    if (previewMap.Metrics.Contains(location))\n                    {\n                        var terrain = new Terrain\n                        {\n                            Type = SelectedTerrainType,\n                            Icon = SelectedTerrainType.IsTransformable ? 22 : 0,\n                            Tint = Color.FromArgb(128, Color.White)\n                        };\n                        previewMap.Technos.Add(location, terrain);\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var terrainPen = new Pen(Color.Green, 4.0f);\n            var occupyPen = new Pen(Color.Red, 2.0f);\n            foreach (var (topLeft, terrain) in previewMap.Technos.OfType<Terrain>())\n            {\n                var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), terrain.Type.RenderSize);\n                graphics.DrawRectangle(terrainPen, bounds);\n\n                for (var y = 0; y < terrain.Type.OccupyMask.GetLength(0); ++y)\n                {\n                    for (var x = 0; x < terrain.Type.OccupyMask.GetLength(1); ++x)\n                    {\n                        if (terrain.Type.OccupyMask[y, x])\n                        {\n                            var occupyBounds = new Rectangle(\n                                new Point((topLeft.X + x) * Globals.TileWidth, (topLeft.Y + y) * Globals.TileHeight),\n                                Globals.TileSize\n                            );\n                            graphics.DrawRectangle(occupyPen, occupyBounds);\n                        }\n                    }\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    selectedTerrainProperties?.Close();\n\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseDoubleClick -= MapPanel_MouseDoubleClick;\n                    (mapPanel as Control).KeyDown -= TerrainTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= TerrainTool_KeyUp;\n\n                    terrainTypeComboBox.SelectedIndexChanged -= TerrainTypeCombo_SelectedIndexChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/UnitTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class UnitTool : ViewTool\n    {\n        private readonly TypeComboBox unitTypeComboBox;\n        private readonly MapPanel unitTypeMapPanel;\n        private readonly ObjectProperties objectProperties;\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private readonly Unit mockUnit;\n\n        private Unit selectedUnit;\n        private ObjectPropertiesPopup selectedObjectProperties;\n\n        private UnitType selectedUnitType;\n        private UnitType SelectedUnitType\n        {\n            get => selectedUnitType;\n            set\n            {\n                if (selectedUnitType != value)\n                {\n                    if (placementMode && (selectedUnitType != null))\n                    {\n                        mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n                    }\n\n                    selectedUnitType = value;\n                    unitTypeComboBox.SelectedValue = selectedUnitType;\n\n                    if (placementMode && (selectedUnitType != null))\n                    {\n                        mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n                    }\n\n                    mockUnit.Type = selectedUnitType;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public UnitTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox unitTypeComboBox, MapPanel unitTypeMapPanel, ObjectProperties objectProperties, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            mockUnit = new Unit()\n            {\n                Type = unitTypeComboBox.Types.First() as UnitType,\n                House = map.Houses.First().Type,\n                Strength = 256,\n                Direction = map.DirectionTypes.Where(d => d.Equals(FacingType.North)).First(),\n                Mission = map.MissionTypes.Where(m => m.Equals(\"Guard\")).FirstOrDefault() ?? map.MissionTypes.First()\n            };\n            mockUnit.PropertyChanged += MockUnit_PropertyChanged;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseDoubleClick += MapPanel_MouseDoubleClick;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += UnitTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += UnitTool_KeyUp;\n\n            this.unitTypeComboBox = unitTypeComboBox;\n            this.unitTypeComboBox.SelectedIndexChanged += UnitTypeComboBox_SelectedIndexChanged;\n\n            this.unitTypeMapPanel = unitTypeMapPanel;\n            this.unitTypeMapPanel.BackColor = Color.White;\n            this.unitTypeMapPanel.MaxZoom = 1;\n\n            this.objectProperties = objectProperties;\n            this.objectProperties.Object = mockUnit;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedUnitType = mockUnit.Type;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDoubleClick(object sender, MouseEventArgs e)\n        {\n            if (Control.ModifierKeys != Keys.None)\n            {\n                return;\n            }\n\n            if (map.Metrics.GetCell(navigationWidget.MouseCell, out int cell))\n            {\n                if (map.Technos[cell] is Unit unit)\n                {\n                    selectedUnit = null;\n\n                    selectedObjectProperties?.Close();\n                    selectedObjectProperties = new ObjectPropertiesPopup(objectProperties.Plugin, unit);\n                    selectedObjectProperties.Closed += (cs, ce) =>\n                    {\n                        navigationWidget.Refresh();\n                    };\n\n                    unit.PropertyChanged += SelectedUnit_PropertyChanged;\n\n                    selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));\n\n                    UpdateStatus();\n                }\n            }\n        }\n\n        private void MockUnit_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            RefreshMapPanel();\n        }\n\n        private void SelectedUnit_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            mapPanel.Invalidate(map, sender as Unit);\n        }\n\n        private void UnitTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedUnitType = unitTypeComboBox.SelectedValue as UnitType;\n        }\n\n        private void UnitTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void UnitTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddUnit(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveUnit(navigationWidget.MouseCell);\n                }\n            }\n            else if (e.Button == MouseButtons.Left)\n            {\n                SelectUnit(navigationWidget.MouseCell);\n            }\n            else if (e.Button == MouseButtons.Right)\n            {\n                PickUnit(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (selectedUnit != null)\n            {\n                selectedUnit = null;\n\n                UpdateStatus();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (SelectedUnitType != null)\n                {\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.OldCell, new Size(1, 1)), 1, 1));\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.NewCell, new Size(1, 1)), 1, 1));\n                }\n            }\n            else if (selectedUnit != null)\n            {\n                var oldLocation = map.Technos[selectedUnit].Value;\n                mapPanel.Invalidate(map, selectedUnit);\n                map.Technos.Remove(selectedUnit);\n                if (map.Technos.Add(e.NewCell, selectedUnit))\n                {\n                    mapPanel.Invalidate(map, selectedUnit);\n                    plugin.Dirty = true;\n                }\n                else\n                {\n                    map.Technos.Add(oldLocation, selectedUnit);\n                }\n            }\n        }\n\n        private void AddUnit(Point location)\n        {\n            if (SelectedUnitType != null)\n            {\n                var unit = mockUnit.Clone();\n                if (map.Technos.Add(location, unit))\n                {\n                    mapPanel.Invalidate(map, unit);\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveUnit(Point location)\n        {\n            if (map.Technos[location] is Unit unit)\n            {\n                mapPanel.Invalidate(map, unit);\n                map.Technos.Remove(unit);\n                plugin.Dirty = true;\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedUnitType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedUnitType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickUnit(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (map.Technos[cell] is Unit unit)\n                {\n                    SelectedUnitType = unit.Type;\n                    mockUnit.House = unit.House;\n                    mockUnit.Strength = unit.Strength;\n                    mockUnit.Direction = unit.Direction;\n                    mockUnit.Mission = unit.Mission;\n                    mockUnit.Trigger = unit.Trigger;\n                }\n            }\n        }\n\n        private void SelectUnit(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                selectedUnit = map.Technos[cell] as Unit;\n            }\n\n            UpdateStatus();\n        }\n\n        private void RefreshMapPanel()\n        {\n            if (mockUnit.Type != null)\n            {\n                var unitPreview = new Bitmap(Globals.TileWidth * 3, Globals.TileHeight * 3);\n                using (var g = Graphics.FromImage(unitPreview))\n                {\n                    MapRenderer.Render(plugin.GameType, map.Theater, new Point(1, 1), Globals.TileSize, mockUnit).Item2(g);\n                }\n                unitTypeMapPanel.MapImage = unitPreview;\n            }\n            else\n            {\n                unitTypeMapPanel.MapImage = null;\n            }\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to place unit, Right-Click to remove unit\";\n            }\n            else if (selectedUnit != null)\n            {\n                statusLbl.Text = \"Drag mouse to move unit\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click drag to move unit, Double-Click update unit properties, Right-Click to pick unit\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedUnitType != null)\n                {\n                    var unit = mockUnit.Clone();\n                    unit.Tint = Color.FromArgb(128, Color.White);\n                    if (previewMap.Technos.Add(location, unit))\n                    {\n                        mapPanel.Invalidate(previewMap, unit);\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var unitPen = new Pen(Color.Green, 4.0f);\n            foreach (var (topLeft, _) in map.Technos.OfType<Unit>())\n            {\n                var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                graphics.DrawRectangle(unitPen, bounds);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    selectedObjectProperties?.Close();\n\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseDoubleClick -= MapPanel_MouseDoubleClick;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= UnitTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= UnitTool_KeyUp;\n\n                    unitTypeComboBox.SelectedIndexChanged -= UnitTypeComboBox_SelectedIndexChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/ViewTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Render;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public abstract class ViewTool : ITool\n    {\n        protected readonly IGamePlugin plugin;\n        protected readonly Map map;\n\n        protected readonly MapPanel mapPanel;\n        protected readonly ToolStripStatusLabel statusLbl;\n        protected readonly UndoRedoList<UndoRedoEventArgs> url;\n        protected readonly NavigationWidget navigationWidget;\n\n        protected virtual Map RenderMap => map;\n\n        private MapLayerFlag layers;\n        public MapLayerFlag Layers\n        {\n            get => layers;\n            set\n            {\n                if (layers != value)\n                {\n                    layers = value;\n                    Invalidate();\n                }\n            }\n        }\n\n        public ViewTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n        {\n            this.layers = layers;\n            this.plugin = plugin;\n            this.url = url;\n\n            this.mapPanel = mapPanel;\n            this.mapPanel.PreRender += MapPanel_PreRender;\n            this.mapPanel.PostRender += MapPanel_PostRender;\n\n            this.statusLbl = statusLbl;\n\n            map = plugin.Map;\n            map.BasicSection.PropertyChanged += BasicSection_PropertyChanged;\n\n            navigationWidget = new NavigationWidget(mapPanel, map.Metrics, Globals.TileSize);\n        }\n\n        protected void Invalidate()\n        {\n            mapPanel.Invalidate(RenderMap);\n        }\n\n        private void BasicSection_PropertyChanged(object sender, PropertyChangedEventArgs e)\n        {\n            switch (e.PropertyName)\n            {\n                case \"BasePlayer\":\n                    {\n                        foreach (var baseBuilding in map.Buildings.OfType<Building>().Select(x => x.Occupier).Where(x => x.BasePriority >= 0))\n                        {\n                            mapPanel.Invalidate(map, baseBuilding);\n                        }\n                    }\n                    break;\n            }\n        }\n\n        private void MapPanel_PreRender(object sender, RenderEventArgs e)\n        {\n            if ((e.Cells != null) && (e.Cells.Count == 0))\n            {\n                return;\n            }\n\n            PreRenderMap();\n\n            using (var g = Graphics.FromImage(mapPanel.MapImage))\n            {\n                if (Properties.Settings.Default.Quality > 1)\n                {\n                    g.InterpolationMode = InterpolationMode.NearestNeighbor;\n                    g.PixelOffsetMode = PixelOffsetMode.HighSpeed;\n                }\n\n                MapRenderer.Render(plugin.GameType, RenderMap, g, e.Cells?.Where(p => map.Metrics.Contains(p)).ToHashSet(), Layers);\n            }\n        }\n\n        private void MapPanel_PostRender(object sender, RenderEventArgs e)\n        {\n            PostRenderMap(e.Graphics);\n            navigationWidget.Render(e.Graphics);\n        }\n\n        protected virtual void PreRenderMap() { }\n\n        protected virtual void PostRenderMap(Graphics graphics)\n        {\n            if ((Layers & MapLayerFlag.Waypoints) != MapLayerFlag.None)\n            {\n                var waypointBackgroundBrush = new SolidBrush(Color.FromArgb(96, Color.Black));\n                var waypointBrush = new SolidBrush(Color.FromArgb(128, Color.DarkOrange));\n                var waypointPen = new Pen(Color.DarkOrange);\n\n                foreach (var waypoint in map.Waypoints)\n                {\n                    if (waypoint.Cell.HasValue)\n                    {\n                        var x = waypoint.Cell.Value % map.Metrics.Width;\n                        var y = waypoint.Cell.Value / map.Metrics.Width;\n\n                        var location = new Point(x * Globals.TileWidth, y * Globals.TileHeight);\n                        var textBounds = new Rectangle(location, Globals.TileSize);\n\n                        graphics.FillRectangle(waypointBackgroundBrush, textBounds);\n                        graphics.DrawRectangle(waypointPen, textBounds);\n\n                        StringFormat stringFormat = new StringFormat\n                        {\n                            Alignment = StringAlignment.Center,\n                            LineAlignment = StringAlignment.Center\n                        };\n\n                        var text = waypoint.Name.ToString();\n                        var font = graphics.GetAdjustedFont(text, SystemFonts.DefaultFont, textBounds.Width, 24 / Globals.TileScale, 48 / Globals.TileScale, true);\n                        graphics.DrawString(text.ToString(), font, waypointBrush, textBounds, stringFormat);\n                    }\n                }\n            }\n\n            if ((Layers & MapLayerFlag.TechnoTriggers) != MapLayerFlag.None)\n            {\n                var technoTriggerBackgroundBrush = new SolidBrush(Color.FromArgb(96, Color.Black));\n                var technoTriggerBrush = new SolidBrush(Color.LimeGreen);\n                var technoTriggerPen = new Pen(Color.LimeGreen);\n\n                foreach (var (cell, techno) in map.Technos)\n                {\n                    var location = new Point(cell.X * Globals.TileWidth, cell.Y * Globals.TileHeight);\n\n                    (string trigger, Rectangle bounds)[] triggers = null;\n                    if (techno is Terrain terrain)\n                    {\n                        triggers = new (string, Rectangle)[] { (terrain.Trigger, new Rectangle(location, terrain.Type.RenderSize)) };\n                    }\n                    else if (techno is Building building)\n                    {\n                        var size = new Size(building.Type.Size.Width * Globals.TileWidth, building.Type.Size.Height * Globals.TileHeight);\n                        triggers = new (string, Rectangle)[] { (building.Trigger, new Rectangle(location, size)) };\n                    }\n                    else if (techno is Unit unit)\n                    {\n                        triggers = new (string, Rectangle)[] { (unit.Trigger, new Rectangle(location, Globals.TileSize)) };\n                    }\n                    else if (techno is InfantryGroup infantryGroup)\n                    {\n                        List<(string, Rectangle)> infantryTriggers = new List<(string, Rectangle)>();\n                        for (var i = 0; i < infantryGroup.Infantry.Length; ++i)\n                        {\n                            var infantry = infantryGroup.Infantry[i];\n                            if (infantry == null)\n                            {\n                                continue;\n                            }\n\n                            var size = Globals.TileSize;\n                            var offset = Size.Empty;\n                            switch ((InfantryStoppingType)i)\n                            {\n                                case InfantryStoppingType.UpperLeft:\n                                    offset.Width = -size.Width / 4;\n                                    offset.Height = -size.Height / 4;\n                                    break;\n                                case InfantryStoppingType.UpperRight:\n                                    offset.Width = size.Width / 4;\n                                    offset.Height = -size.Height / 4;\n                                    break;\n                                case InfantryStoppingType.LowerLeft:\n                                    offset.Width = -size.Width / 4;\n                                    offset.Height = size.Height / 4;\n                                    break;\n                                case InfantryStoppingType.LowerRight:\n                                    offset.Width = size.Width / 4;\n                                    offset.Height = size.Height / 4;\n                                    break;\n                            }\n\n                            var bounds = new Rectangle(location + offset, size);\n                            infantryTriggers.Add((infantry.Trigger, bounds));\n                        }\n\n                        triggers = infantryTriggers.ToArray();\n                    }\n\n                    if (triggers != null)\n                    {\n                        StringFormat stringFormat = new StringFormat\n                        {\n                            Alignment = StringAlignment.Center,\n                            LineAlignment = StringAlignment.Center\n                        };\n\n                        foreach (var (trigger, bounds) in triggers.Where(x => !x.trigger.Equals(\"None\", StringComparison.OrdinalIgnoreCase)))\n                        {\n                            var font = graphics.GetAdjustedFont(trigger, SystemFonts.DefaultFont, bounds.Width, 12 / Globals.TileScale, 24 / Globals.TileScale, true);\n                            var textBounds = graphics.MeasureString(trigger, font, bounds.Width, stringFormat);\n\n                            var backgroundBounds = new RectangleF(bounds.Location, textBounds);\n                            backgroundBounds.Offset((bounds.Width - textBounds.Width) / 2.0f, (bounds.Height - textBounds.Height) / 2.0f);\n                            graphics.FillRectangle(technoTriggerBackgroundBrush, backgroundBounds);\n                            graphics.DrawRectangle(technoTriggerPen, Rectangle.Round(backgroundBounds));\n\n                            graphics.DrawString(trigger, font, technoTriggerBrush, bounds, stringFormat);\n                        }\n                    }\n                }\n            }\n\n            if ((Layers & MapLayerFlag.CellTriggers) != MapLayerFlag.None)\n            {\n                var cellTriggersBackgroundBrush = new SolidBrush(Color.FromArgb(96, Color.Black));\n                var cellTriggersBrush = new SolidBrush(Color.FromArgb(128, Color.White));\n                var cellTriggerPen = new Pen(Color.White);\n\n                foreach (var (cell, cellTrigger) in map.CellTriggers)\n                {\n                    var x = cell % map.Metrics.Width;\n                    var y = cell / map.Metrics.Width;\n\n                    var location = new Point(x * Globals.TileWidth, y * Globals.TileHeight);\n                    var textBounds = new Rectangle(location, Globals.TileSize);\n\n                    graphics.FillRectangle(cellTriggersBackgroundBrush, textBounds);\n                    graphics.DrawRectangle(cellTriggerPen, textBounds);\n\n                    StringFormat stringFormat = new StringFormat\n                    {\n                        Alignment = StringAlignment.Center,\n                        LineAlignment = StringAlignment.Center\n                    };\n\n                    var text = cellTrigger.Trigger;\n                    var font = graphics.GetAdjustedFont(text, SystemFonts.DefaultFont, textBounds.Width, 24 / Globals.TileScale, 48 / Globals.TileScale, true);\n                    graphics.DrawString(text.ToString(), font, cellTriggersBrush, textBounds, stringFormat);\n                }\n            }\n\n            if ((Layers & MapLayerFlag.Boundaries) != MapLayerFlag.None)\n            {\n                var boundsPen = new Pen(Color.Cyan, 8.0f);\n                var bounds = Rectangle.FromLTRB(\n                    map.Bounds.Left * Globals.TileWidth,\n                    map.Bounds.Top * Globals.TileHeight,\n                    map.Bounds.Right * Globals.TileWidth,\n                    map.Bounds.Bottom * Globals.TileHeight\n                );\n                graphics.DrawRectangle(boundsPen, bounds);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    navigationWidget.Dispose();\n\n                    mapPanel.PreRender -= MapPanel_PreRender;\n                    mapPanel.PostRender -= MapPanel_PostRender;\n\n                    map.BasicSection.PropertyChanged -= BasicSection_PropertyChanged;\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/WallsTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class WallsTool : ViewTool\n    {\n        private readonly TypeComboBox wallTypeComboBox;\n        private readonly MapPanel wallTypeMapPanel;\n\n        private readonly Dictionary<int, Overlay> undoOverlays = new Dictionary<int, Overlay>();\n        private readonly Dictionary<int, Overlay> redoOverlays = new Dictionary<int, Overlay>();\n\n        private Map previewMap;\n        protected override Map RenderMap => previewMap;\n\n        private bool placementMode;\n\n        private OverlayType selectedWallType;\n        private OverlayType SelectedWallType\n        {\n            get => selectedWallType;\n            set\n            {\n                if (selectedWallType != value)\n                {\n                    if (placementMode && (selectedWallType != null))\n                    {\n                        mapPanel.Invalidate(map, navigationWidget.MouseCell);\n                    }\n\n                    selectedWallType = value;\n                    wallTypeComboBox.SelectedValue = selectedWallType;\n\n                    RefreshMapPanel();\n                }\n            }\n        }\n\n        public WallsTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox wallTypeComboBox, MapPanel wallTypeMapPanel, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            previewMap = map;\n\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseUp += MapPanel_MouseUp;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += WallTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += WallTool_KeyUp;\n\n            this.wallTypeComboBox = wallTypeComboBox;\n            this.wallTypeComboBox.SelectedIndexChanged += WallTypeComboBox_SelectedIndexChanged;\n\n            this.wallTypeMapPanel = wallTypeMapPanel;\n            this.wallTypeMapPanel.BackColor = Color.White;\n            this.wallTypeMapPanel.MaxZoom = 1;\n\n            navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;\n\n            SelectedWallType = this.wallTypeComboBox.Types.First() as OverlayType;\n\n            UpdateStatus();\n        }\n\n        private void WallTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            SelectedWallType = wallTypeComboBox.SelectedValue as OverlayType;\n        }\n\n        private void WallTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void WallTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    AddWall(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveWall(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickWall(navigationWidget.MouseCell);\n            }\n        }\n\n        private void MapPanel_MouseUp(object sender, MouseEventArgs e)\n        {\n            if ((undoOverlays.Count > 0) || (redoOverlays.Count > 0))\n            {\n                CommitChange();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (Control.MouseButtons == MouseButtons.Left)\n                {\n                    AddWall(e.NewCell);\n                }\n                else if (Control.MouseButtons == MouseButtons.Right)\n                {\n                    RemoveWall(e.NewCell);\n                }\n\n                if (SelectedWallType != null)\n                {\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.OldCell, new Size(1, 1)), 1, 1));\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(e.NewCell, new Size(1, 1)), 1, 1));\n                }\n            }\n        }\n\n        private void AddWall(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                if (SelectedWallType != null)\n                {\n                    var overlay = new Overlay { Type = SelectedWallType, Icon = 0 };\n                    if (map.Technos.CanAdd(cell, overlay) && map.Buildings.CanAdd(cell, overlay))\n                    {\n                        if (!undoOverlays.ContainsKey(cell))\n                        {\n                            undoOverlays[cell] = map.Overlay[cell];\n                        }\n\n                        map.Overlay[cell] = overlay;\n                        redoOverlays[cell] = overlay;\n\n                        mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));\n\n                        plugin.Dirty = true;\n                    }\n                }\n            }\n        }\n\n        private void RemoveWall(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var overlay = map.Overlay[cell];\n                if (overlay?.Type.IsWall ?? false)\n                {\n                    if (!undoOverlays.ContainsKey(cell))\n                    {\n                        undoOverlays[cell] = map.Overlay[cell];\n                    }\n\n                    map.Overlay[cell] = null;\n                    redoOverlays[cell] = null;\n\n                    mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void CommitChange()\n        {\n            var undoOverlays2 = new Dictionary<int, Overlay>(undoOverlays);\n            void undoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in undoOverlays2)\n                {\n                    e.Map.Overlay[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, undoOverlays2.Keys.Select(k =>\n                {\n                    e.Map.Metrics.GetLocation(k, out Point location);\n                    return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);\n                }));\n            }\n\n            var redoOverlays2 = new Dictionary<int, Overlay>(redoOverlays);\n            void redoAction(UndoRedoEventArgs e)\n            {\n                foreach (var kv in redoOverlays2)\n                {\n                    e.Map.Overlay[kv.Key] = kv.Value;\n                }\n                e.MapPanel.Invalidate(e.Map, redoOverlays2.Keys.Select(k =>\n                {\n                    e.Map.Metrics.GetLocation(k, out Point location);\n                    return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);\n                }));\n            }\n\n            undoOverlays.Clear();\n            redoOverlays.Clear();\n\n            url.Track(undoAction, redoAction);\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            navigationWidget.MouseoverSize = Size.Empty;\n\n            if (SelectedWallType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            navigationWidget.MouseoverSize = new Size(1, 1);\n\n            if (SelectedWallType != null)\n            {\n                mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));\n            }\n\n            UpdateStatus();\n        }\n\n        private void PickWall(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var overlay = map.Overlay[cell];\n                if ((overlay != null) && overlay.Type.IsWall)\n                {\n                    SelectedWallType = overlay.Type;\n                }\n            }\n        }\n\n        private void RefreshMapPanel()\n        {\n            wallTypeMapPanel.MapImage = SelectedWallType?.Thumbnail;\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click drag to add walls, Right-Click drag to remove walls\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click or Right-Click to pick wall\";\n            }\n        }\n\n        protected override void PreRenderMap()\n        {\n            base.PreRenderMap();\n\n            previewMap = map.Clone();\n            if (placementMode)\n            {\n                var location = navigationWidget.MouseCell;\n                if (SelectedWallType != null)\n                {\n                    if (previewMap.Metrics.GetCell(location, out int cell))\n                    {\n                        var overlay = new Overlay { Type = SelectedWallType, Icon = 0, Tint = Color.FromArgb(128, Color.White) };\n                        if (previewMap.Technos.CanAdd(cell, overlay) && previewMap.Buildings.CanAdd(cell, overlay))\n                        {\n                            previewMap.Overlay[cell] = overlay;\n                            mapPanel.Invalidate(previewMap, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));\n                        }\n                    }\n                }\n            }\n        }\n\n        protected override void PostRenderMap(Graphics graphics)\n        {\n            base.PostRenderMap(graphics);\n\n            var wallPen = new Pen(Color.Green, 4.0f);\n            foreach (var (cell, overlay) in previewMap.Overlay)\n            {\n                if (overlay.Type.IsWall)\n                {\n                    previewMap.Metrics.GetLocation(cell, out Point topLeft);\n                    var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);\n                    graphics.DrawRectangle(wallPen, bounds);\n                }\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseUp -= MapPanel_MouseUp;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= WallTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= WallTool_KeyUp;\n\n                    wallTypeComboBox.SelectedIndexChanged -= WallTypeComboBox_SelectedIndexChanged;\n\n                    navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Tools/WaypointsTool.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Event;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing MobiusEditor.Utility;\nusing MobiusEditor.Widgets;\nusing System;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Tools\n{\n    public class WaypointsTool : ViewTool\n    {\n        private readonly ComboBox waypointCombo;\n\n        private (Waypoint waypoint, int? cell)? undoWaypoint;\n        private (Waypoint waypoint, int? cell)? redoWaypoint;\n\n        private bool placementMode;\n\n        public WaypointsTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, ComboBox waypointCombo, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)\n            : base(mapPanel, layers, statusLbl, plugin, url)\n        {\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            (this.mapPanel as Control).KeyDown += WaypointsTool_KeyDown;\n            (this.mapPanel as Control).KeyUp += WaypointsTool_KeyUp;\n\n            this.waypointCombo = waypointCombo;\n\n            UpdateStatus();\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if (placementMode)\n            {\n                if (e.Button == MouseButtons.Left)\n                {\n                    SetWaypoint(navigationWidget.MouseCell);\n                }\n                else if (e.Button == MouseButtons.Right)\n                {\n                    RemoveWaypoint(navigationWidget.MouseCell);\n                }\n            }\n            else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))\n            {\n                PickWaypoint(navigationWidget.MouseCell);\n            }\n        }\n\n        private void WaypointsTool_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                EnterPlacementMode();\n            }\n        }\n\n        private void WaypointsTool_KeyUp(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.ShiftKey)\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (!placementMode && (Control.ModifierKeys == Keys.Shift))\n            {\n                EnterPlacementMode();\n            }\n            else if (placementMode && (Control.ModifierKeys == Keys.None))\n            {\n                ExitPlacementMode();\n            }\n        }\n\n        private void SetWaypoint(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var waypoint = map.Waypoints[waypointCombo.SelectedIndex];\n                if (waypoint.Cell != cell)\n                {\n                    if (undoWaypoint == null)\n                    {\n                        undoWaypoint = (waypoint, waypoint.Cell);\n                    }\n                    else if (undoWaypoint.Value.cell == cell)\n                    {\n                        undoWaypoint = null;\n                    }\n\n                    waypoint.Cell = cell;\n                    redoWaypoint = (waypoint, waypoint.Cell);\n\n                    CommitChange();\n\n                    mapPanel.Invalidate();\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void RemoveWaypoint(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                var waypoint = map.Waypoints.Where(w => w.Cell == cell).FirstOrDefault();\n                if (waypoint != null)\n                {\n                    if (undoWaypoint == null)\n                    {\n                        undoWaypoint = (waypoint, waypoint.Cell);\n                    }\n\n                    waypoint.Cell = null;\n                    redoWaypoint = (waypoint, null);\n\n                    CommitChange();\n\n                    mapPanel.Invalidate();\n\n                    plugin.Dirty = true;\n                }\n            }\n        }\n\n        private void EnterPlacementMode()\n        {\n            if (placementMode)\n            {\n                return;\n            }\n\n            placementMode = true;\n\n            UpdateStatus();\n        }\n\n        private void ExitPlacementMode()\n        {\n            if (!placementMode)\n            {\n                return;\n            }\n\n            placementMode = false;\n\n            UpdateStatus();\n        }\n\n        private void PickWaypoint(Point location)\n        {\n            if (map.Metrics.GetCell(location, out int cell))\n            {\n                for (var i = 0; i < map.Waypoints.Length; ++i)\n                {\n                    if (map.Waypoints[i].Cell == cell)\n                    {\n                        waypointCombo.SelectedIndex = i;\n                        break;\n                    }\n                }\n            }\n        }\n\n        private void CommitChange()\n        {\n            var undoWaypoint2 = undoWaypoint;\n            void undoAction(UndoRedoEventArgs e)\n            {\n                undoWaypoint2.Value.waypoint.Cell = undoWaypoint2.Value.cell;\n                mapPanel.Invalidate();\n            }\n\n            var redoWaypoint2 = redoWaypoint;\n            void redoAction(UndoRedoEventArgs e)\n            {\n                redoWaypoint2.Value.waypoint.Cell = redoWaypoint2.Value.cell;\n                mapPanel.Invalidate();\n            }\n\n            undoWaypoint = null;\n            redoWaypoint = null;\n\n            url.Track(undoAction, redoAction);\n        }\n\n        private void UpdateStatus()\n        {\n            if (placementMode)\n            {\n                statusLbl.Text = \"Left-Click to set cell waypoint, Right-Click to clear cell waypoint\";\n            }\n            else\n            {\n                statusLbl.Text = \"Shift to enter placement mode, Left-Click or Right-Click to pick cell waypoint\";\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                    (mapPanel as Control).KeyDown -= WaypointsTool_KeyDown;\n                    (mapPanel as Control).KeyUp -= WaypointsTool_KeyUp;\n                }\n                disposedValue = true;\n            }\n\n            base.Dispose(disposing);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/CRC.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\n\nnamespace MobiusEditor.Utility\n{\n    public class CRC\n    {\n        static CRC()\n        {\n            for (var i = 0U; i < 256U; ++i)\n            {\n                uint crc = i;\n                for (var j = 0U; j < 8U; ++j)\n                {\n                    if ((crc & 1U) != 0U)\n                    {\n                        crc = (crc >> 1) ^ polynomial;\n                    }\n                    else\n                    {\n                        crc >>= 1;\n                    }\n                }\n                crcTable[i] = crc;\n            }\n        }\n\n        public static uint Calculate(byte[] bytes)\n        {\n            if (bytes == null)\n            {\n                throw new ArgumentNullException(\"bytes\");\n            }\n\n            uint remainder = 0xFFFFFFFFU;\n            for (var i = 0; i < bytes.Length; ++i)\n            {\n                uint index = (remainder & 0xFF) ^ bytes[i];\n                remainder = (remainder >> 8) ^ crcTable[index];\n            }\n            return ~remainder;\n        }\n\n        private static readonly uint[] crcTable = new uint[256];\n        private const uint polynomial = 0xEDB88320;\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/ExtensionMethods.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\n\nnamespace MobiusEditor.Utility\n{\n    public static class ExtensionMethods\n    {\n        public static float ToLinear(this float v)\n        {\n            return (v < 0.04045f) ? (v * 25.0f / 323.0f) : (float)Math.Pow(((200.0f * v) + 11.0f) / 211.0f, 12.0f / 5.0f);\n        }\n\n        public static float ToLinear(this byte v)\n        {\n            return (v / 255.0f).ToLinear();\n        }\n\n        public static float ToSRGB(this float v)\n        {\n            return (v < 0.0031308) ? (v * 323.0f / 25.0f) : ((((float)Math.Pow(v, 5.0f / 12.0f) * 211.0f) - 11.0f) / 200.0f);\n        }\n\n        public static void SetDefault<T>(this T data)\n        {\n            var properties = data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetSetMethod() != null);\n            foreach (var property in properties)\n            {\n                if (property.GetCustomAttribute(typeof(DefaultValueAttribute)) is DefaultValueAttribute defaultValueAttr)\n                {\n                    property.SetValue(data, defaultValueAttr.Value);\n                }\n            }\n        }\n\n        public static void CopyTo<T>(this T data, T other)\n        {\n            var properties = data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => (p.GetSetMethod() != null) && (p.GetGetMethod() != null));\n            foreach (var property in properties)\n            {\n                var defaultValueAttr = property.GetCustomAttribute(typeof(DefaultValueAttribute)) as DefaultValueAttribute;\n                property.SetValue(other, property.GetValue(data));\n            }\n        }\n\n        public static IEnumerable<Point> Points(this Rectangle rectangle)\n        {\n            for (var y = rectangle.Top; y < rectangle.Bottom; ++y)\n            {\n                for (var x = rectangle.Left; x < rectangle.Right; ++x)\n                {\n                    yield return new Point(x, y);\n                }\n            }\n        }\n\n        public static IEnumerable<T> Yield<T>(this T item)\n        {\n            yield return item;\n        }\n\n        public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null)\n        {\n            return new HashSet<T>(source, comparer);\n        }\n\n        public static IEnumerable<byte[]> Split(this byte[] bytes, int length)\n        {\n            for (int i = 0; i < bytes.Length; i += length)\n            {\n                yield return bytes.Skip(i).Take(Math.Min(length, bytes.Length - i)).ToArray();\n            }\n        }\n\n        public static IEnumerable<string> Split(this string str, int length)\n        {\n            for (int i = 0; i < str.Length; i += length)\n            {\n                yield return str.Substring(i, Math.Min(length, str.Length - i));\n            }\n        }\n\n        public static Font GetAdjustedFont(this Graphics graphics, string text, Font originalFont, int width, int minSize, int maxSize, bool smallestOnFail)\n        {\n            if (minSize > maxSize)\n            {\n                throw new ArgumentOutOfRangeException(\"minSize\");\n            }\n\n            for (var size = maxSize; size >= minSize; --size)\n            {\n                var font = new Font(originalFont.Name, size, originalFont.Style);\n                var textSize = graphics.MeasureString(text, font);\n\n                if (width > Convert.ToInt32(textSize.Width))\n                {\n                    return font;\n                }\n            }\n\n            return smallestOnFail ? new Font(originalFont.Name, minSize, originalFont.Style) : originalFont;\n        }\n\n        public static Bitmap Sharpen(this Bitmap bitmap, double strength)\n        {\n            var sharpenImage = bitmap.Clone() as Bitmap;\n\n            int width = bitmap.Width;\n            int height = bitmap.Height;\n\n            // Create sharpening filter.\n            const int filterSize = 5;\n\n            var filter = new double[,]\n            {\n                {-1, -1, -1, -1, -1},\n                {-1,  2,  2,  2, -1},\n                {-1,  2, 16,  2, -1},\n                {-1,  2,  2,  2, -1},\n                {-1, -1, -1, -1, -1}\n            };\n\n            double bias = 1.0 - strength;\n            double factor = strength / 16.0;\n\n            const int s = filterSize / 2;\n\n            var result = new Color[bitmap.Width, bitmap.Height];\n\n            // Lock image bits for read/write.\n            if (sharpenImage != null)\n            {\n                BitmapData pbits = sharpenImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);\n\n                // Declare an array to hold the bytes of the bitmap.\n                int bytes = pbits.Stride * height;\n                var rgbValues = new byte[bytes];\n\n                // Copy the RGB values into the array.\n                Marshal.Copy(pbits.Scan0, rgbValues, 0, bytes);\n\n                int rgb;\n                // Fill the color array with the new sharpened color values.\n                for (int x = s; x < width - s; x++)\n                {\n                    for (int y = s; y < height - s; y++)\n                    {\n                        double red = 0.0, green = 0.0, blue = 0.0;\n\n                        for (int filterX = 0; filterX < filterSize; filterX++)\n                        {\n                            for (int filterY = 0; filterY < filterSize; filterY++)\n                            {\n                                int imageX = (x - s + filterX + width) % width;\n                                int imageY = (y - s + filterY + height) % height;\n\n                                rgb = imageY * pbits.Stride + 3 * imageX;\n\n                                red += rgbValues[rgb + 2] * filter[filterX, filterY];\n                                green += rgbValues[rgb + 1] * filter[filterX, filterY];\n                                blue += rgbValues[rgb + 0] * filter[filterX, filterY];\n                            }\n\n                            rgb = y * pbits.Stride + 3 * x;\n\n                            int r = Math.Min(Math.Max((int)(factor * red + (bias * rgbValues[rgb + 2])), 0), 255);\n                            int g = Math.Min(Math.Max((int)(factor * green + (bias * rgbValues[rgb + 1])), 0), 255);\n                            int b = Math.Min(Math.Max((int)(factor * blue + (bias * rgbValues[rgb + 0])), 0), 255);\n\n                            result[x, y] = Color.FromArgb(r, g, b);\n                        }\n                    }\n                }\n\n                // Update the image with the sharpened pixels.\n                for (int x = s; x < width - s; x++)\n                {\n                    for (int y = s; y < height - s; y++)\n                    {\n                        rgb = y * pbits.Stride + 3 * x;\n\n                        rgbValues[rgb + 2] = result[x, y].R;\n                        rgbValues[rgb + 1] = result[x, y].G;\n                        rgbValues[rgb + 0] = result[x, y].B;\n                    }\n                }\n\n                // Copy the RGB values back to the bitmap.\n                Marshal.Copy(rgbValues, 0, pbits.Scan0, bytes);\n                // Release image bits.\n                sharpenImage.UnlockBits(pbits);\n            }\n\n            return sharpenImage;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/GameTextManager.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace MobiusEditor.Utility\n{\n    public class GameTextManager\n    {\n        private readonly Dictionary<string, string> gameText = new Dictionary<string, string>();\n\n        public string this[string textId] => gameText.TryGetValue(textId, out string text) ? text : textId;\n\n        public GameTextManager(MegafileManager megafileManager, string gameTextFile)\n        {\n            using (var stream = megafileManager.Open(gameTextFile))\n            using (var reader = new BinaryReader(stream))\n            using (var unicodeReader = new BinaryReader(stream, Encoding.Unicode))\n            using (var asciiReader = new BinaryReader(stream, Encoding.ASCII))\n            {\n                var numStrings = reader.ReadUInt32();\n                var stringSizes = new (uint textSize, uint idSize)[numStrings];\n                var strings = new string[numStrings];\n\n                for (var i = 0; i < numStrings; ++i)\n                {\n                    reader.ReadUInt32();\n                    stringSizes[i] = (reader.ReadUInt32(), reader.ReadUInt32());\n                }\n\n                for (var i = 0; i < numStrings; ++i)\n                {\n                    strings[i] = new string(unicodeReader.ReadChars((int)stringSizes[i].textSize));\n                }\n\n                for (var i = 0; i < numStrings; ++i)\n                {\n                    var textId = new string(asciiReader.ReadChars((int)stringSizes[i].idSize));\n                    gameText[textId] = strings[i];\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/INI.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\nnamespace MobiusEditor.Utility\n{\n    static class INIHelpers\n    {\n        public static readonly Regex SectionRegex = new Regex(@\"^\\s*\\[([^\\]]*)\\]\", RegexOptions.Compiled);\n        public static readonly Regex KeyValueRegex = new Regex(@\"^\\s*(.*?)\\s*=([^;]*)\", RegexOptions.Compiled);\n        public static readonly Regex CommentRegex = new Regex(@\"^\\s*(#|;)\", RegexOptions.Compiled);\n\n        public static readonly Func<INIDiffType, string> DiffPrefix = t =>\n        {\n            switch (t)\n            {\n                case INIDiffType.Added:\n                    return \"+\";\n                case INIDiffType.Removed:\n                    return \"-\";\n                case INIDiffType.Updated:\n                    return \"@\";\n            }\n            return string.Empty;\n        };\n    }\n\n    public class INIKeyValueCollection : IEnumerable<(string Key, string Value)>, IEnumerable\n    {\n        private readonly OrderedDictionary KeyValues;\n\n        public string this[string key]\n        {\n            get\n            {\n                if (!KeyValues.Contains(key))\n                {\n                    throw new KeyNotFoundException(key);\n                }\n                return KeyValues[key] as string;\n            }\n            set\n            {\n                if (key == null)\n                {\n                    throw new ArgumentNullException(\"key\");\n                }\n                KeyValues[key] = value;\n            }\n        }\n\n        public INIKeyValueCollection()\n        {\n            KeyValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);\n        }\n\n        public int Count => KeyValues.Count;\n\n        public bool Contains(string key) => KeyValues.Contains(key);\n\n        public T Get<T>(string key) where T : struct\n        {\n            var converter = TypeDescriptor.GetConverter(typeof(T));\n            return (T)converter.ConvertFromString(this[key]);\n        }\n\n        public void Set<T>(string key, T value) where T : struct\n        {\n            var converter = TypeDescriptor.GetConverter(typeof(T));\n            this[key] = converter.ConvertToString(value);\n        }\n\n        public bool Remove(string key)\n        {\n            if (!KeyValues.Contains(key))\n            {\n                return false;\n            }\n            KeyValues.Remove(key);\n            return true;\n        }\n\n        public IEnumerator<(string Key, string Value)> GetEnumerator()\n        {\n            foreach (DictionaryEntry entry in KeyValues)\n            {\n                yield return (entry.Key as string, entry.Value as string);\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    public class INISection : IEnumerable<(string Key, string Value)>, IEnumerable\n    {\n        public readonly INIKeyValueCollection Keys;\n\n        public string Name { get; private set; }\n\n        public string this[string key] { get => Keys[key]; set => Keys[key] = value; }\n\n        public bool Empty => Keys.Count == 0;\n\n        public INISection(string name)\n        {\n            Keys = new INIKeyValueCollection();\n            Name = name;\n        }\n\n        public void Parse(TextReader reader)\n        {\n            while (true)\n            {\n                var line = reader.ReadLine();\n                if (line == null)\n                {\n                    break;\n                }\n\n                var m = INIHelpers.KeyValueRegex.Match(line);\n                if (m.Success)\n                {\n                    Keys[m.Groups[1].Value] = m.Groups[2].Value;\n                }\n            }\n        }\n\n        public void Parse(string iniText)\n        {\n            using (var reader = new StringReader(iniText))\n            {\n                Parse(reader);\n            }\n        }\n\n        public IEnumerator<(string Key, string Value)> GetEnumerator()\n        {\n            return Keys.GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        public override string ToString()\n        {\n            var lines = new List<string>(Keys.Count);\n            foreach (var item in Keys)\n            {\n                lines.Add(string.Format(\"{0}={1}\", item.Key, item.Value));\n            }\n            return string.Join(Environment.NewLine, lines);\n        }\n    }\n\n    public class INISectionCollection : IEnumerable<INISection>, IEnumerable\n    {\n        private readonly OrderedDictionary Sections;\n\n        public INISection this[string name] => Sections.Contains(name) ? (Sections[name] as INISection) : null;\n\n        public INISectionCollection()\n        {\n            Sections = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);\n        }\n\n        public int Count => Sections.Count;\n\n        public bool Contains(string section) => Sections.Contains(section);\n\n        public INISection Add(string name)\n        {\n            if (!Sections.Contains(name))\n            {\n                var section = new INISection(name);\n                Sections[name] = section;\n            }\n            return this[name];\n        }\n\n        public bool Add(INISection section)\n        {\n            if ((section == null) || Sections.Contains(section.Name))\n            {\n                return false;\n            }\n            Sections[section.Name] = section;\n            return true;\n        }\n\n        public void AddRange(IEnumerable<INISection> sections)\n        {\n            foreach (var section in sections)\n            {\n                Add(section);\n            }\n        }\n\n        public bool Remove(string name)\n        {\n            if (!Sections.Contains(name))\n            {\n                return false;\n            }\n            Sections.Remove(name);\n            return true;\n        }\n\n        public INISection Extract(string name)\n        {\n            if (!Sections.Contains(name))\n            {\n                return null;\n            }\n            var section = this[name];\n            Sections.Remove(name);\n            return section;\n        }\n\n        public IEnumerator<INISection> GetEnumerator()\n        {\n            foreach (DictionaryEntry entry in Sections)\n            {\n                yield return entry.Value as INISection;\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    public partial class INI : IEnumerable<INISection>, IEnumerable\n    {\n        public readonly INISectionCollection Sections;\n\n        public INISection this[string name] { get => Sections[name]; }\n\n        public INI()\n        {\n            Sections = new INISectionCollection();\n        }\n\n        public void Parse(TextReader reader)\n        {\n            INISection currentSection = null;\n\n            while (true)\n            {\n                var line = reader.ReadLine();\n                if (line == null)\n                {\n                    break;\n                }\n\n                var m = INIHelpers.SectionRegex.Match(line);\n                if (m.Success)\n                {\n                    currentSection = Sections.Add(m.Groups[1].Value);\n                }\n\n                if (currentSection != null)\n                {\n                    if (INIHelpers.CommentRegex.Match(line).Success)\n                    {\n                        continue;\n                    }\n\n                    currentSection.Parse(line);\n                }\n            }\n        }\n\n        public void Parse(string iniText)\n        {\n            using (var reader = new StringReader(iniText))\n            {\n                Parse(reader);\n            }\n        }\n\n        public IEnumerator<INISection> GetEnumerator()\n        {\n            foreach (var section in Sections)\n            {\n                yield return section;\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        public override string ToString()\n        {\n            var sections = new List<string>(Sections.Count);\n            foreach (var item in Sections)\n            {\n                var lines = new List<string>\n                {\n                    string.Format(\"[{0}]\", item.Name)\n                };\n                if (!item.Empty)\n                {\n                    lines.Add(item.ToString());\n                }\n                sections.Add(string.Join(Environment.NewLine, lines));\n            }\n            return string.Join(Environment.NewLine + Environment.NewLine, sections) + Environment.NewLine;\n        }\n    }\n\n    [Flags]\n    public enum INIDiffType\n    {\n        None = 0,\n        Added = 1,\n        Removed = 2,\n        Updated = 4,\n        AddedOrUpdated = 5\n    }\n\n    public class INISectionDiff : IEnumerable<string>, IEnumerable\n    {\n        public readonly INIDiffType Type;\n\n        private readonly Dictionary<string, INIDiffType> keyDiff;\n\n        public INIDiffType this[string key]\n        {\n            get\n            {\n                INIDiffType diffType;\n                if (!keyDiff.TryGetValue(key, out diffType))\n                {\n                    return INIDiffType.None;\n                }\n                return diffType;\n            }\n        }\n\n        private INISectionDiff()\n        {\n            keyDiff = new Dictionary<string, INIDiffType>();\n            Type = INIDiffType.None;\n        }\n\n        internal INISectionDiff(INIDiffType type, INISection section)\n            : this()\n        {\n            foreach (var keyValue in section.Keys)\n            {\n                keyDiff[keyValue.Key] = type;\n            }\n\n            Type = type;\n        }\n\n        internal INISectionDiff(INISection leftSection, INISection rightSection)\n            : this(INIDiffType.Removed, leftSection)\n        {\n            foreach (var keyValue in rightSection.Keys)\n            {\n                var key = keyValue.Key;\n                if (keyDiff.ContainsKey(key))\n                {\n                    if (leftSection[key] == rightSection[key])\n                    {\n                        keyDiff.Remove(key);\n                    }\n                    else\n                    {\n                        keyDiff[key] = INIDiffType.Updated;\n                        Type = INIDiffType.Updated;\n                    }\n                }\n                else\n                {\n                    keyDiff[key] = INIDiffType.Added;\n                    Type = INIDiffType.Updated;\n                }\n            }\n\n            Type = (keyDiff.Count > 0) ? INIDiffType.Updated : INIDiffType.None;\n        }\n\n        public IEnumerator<string> GetEnumerator()\n        {\n            return keyDiff.Keys.GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        public override string ToString()\n        {\n            var sb = new StringBuilder();\n            foreach (var item in keyDiff)\n            {\n                sb.AppendLine(string.Format(\"{0} {1}\", INIHelpers.DiffPrefix(item.Value), item.Key));\n            }\n            return sb.ToString();\n        }\n    }\n\n    public class INIDiff : IEnumerable<string>, IEnumerable\n    {\n        private readonly Dictionary<string, INISectionDiff> sectionDiffs;\n\n        public INISectionDiff this[string key]\n        {\n            get\n            {\n                if (!sectionDiffs.TryGetValue(key, out INISectionDiff sectionDiff))\n                {\n                    return null;\n                }\n                return sectionDiff;\n            }\n        }\n\n        private INIDiff()\n        {\n            sectionDiffs = new Dictionary<string, INISectionDiff>(StringComparer.OrdinalIgnoreCase);\n        }\n\n        public INIDiff(INI leftIni, INI rightIni)\n            : this()\n        {\n            foreach (var leftSection in leftIni)\n            {\n                sectionDiffs[leftSection.Name] = rightIni.Sections.Contains(leftSection.Name) ?\n                    new INISectionDiff(leftSection, rightIni[leftSection.Name]) :\n                    new INISectionDiff(INIDiffType.Removed, leftSection);\n            }\n\n            foreach (var rightSection in rightIni)\n            {\n                if (!leftIni.Sections.Contains(rightSection.Name))\n                {\n                    sectionDiffs[rightSection.Name] = new INISectionDiff(INIDiffType.Added, rightSection);\n                }\n            }\n\n            sectionDiffs = sectionDiffs.Where(x => x.Value.Type != INIDiffType.None).ToDictionary(x => x.Key, x => x.Value);\n        }\n\n        public bool Contains(string key) => sectionDiffs.ContainsKey(key);\n\n        public IEnumerator<string> GetEnumerator()\n        {\n            return sectionDiffs.Keys.GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        public override string ToString()\n        {\n            var sb = new StringBuilder();\n            foreach (var item in sectionDiffs)\n            {\n                sb.AppendLine(string.Format(\"{0} {1}\", INIHelpers.DiffPrefix(item.Value.Type), item.Key));\n                using (var reader = new StringReader(item.Value.ToString()))\n                {\n                    while (true)\n                    {\n                        var line = reader.ReadLine();\n                        if (line == null)\n                        {\n                            break;\n                        }\n\n                        sb.AppendLine(string.Format(\"\\t{0}\", line));\n                    }\n                }\n            }\n            return sb.ToString();\n        }\n    }\n\n    [AttributeUsage(AttributeTargets.Property)]\n    public class NonSerializedINIKeyAttribute : Attribute\n    {\n    }\n\n    public partial class INI\n    {\n        public static void ParseSection<T>(ITypeDescriptorContext context, INISection section, T data)\n        {\n            var propertyDescriptors = TypeDescriptor.GetProperties(data);\n            var properties = data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetSetMethod() != null);\n            foreach (var property in properties)\n            {\n                if (property.GetCustomAttribute<NonSerializedINIKeyAttribute>() != null)\n                {\n                    continue;\n                }\n\n                if (section.Keys.Contains(property.Name))\n                {\n                    var converter = propertyDescriptors.Find(property.Name, false)?.Converter ?? TypeDescriptor.GetConverter(property.PropertyType);\n                    if (converter.CanConvertFrom(context, typeof(string)))\n                    {\n                        try\n                        {\n                            property.SetValue(data, converter.ConvertFromString(context, section[property.Name]));\n                        }\n                        catch (FormatException)\n                        {\n                            if (property.PropertyType == typeof(bool))\n                            {\n                                var value = section[property.Name].ToLower();\n                                if (value == \"no\")\n                                {\n                                    property.SetValue(data, false);\n                                }\n                                else if (value == \"yes\")\n                                {\n                                    property.SetValue(data, true);\n                                }\n                                else\n                                {\n                                    throw;\n                                }\n                            }\n                            else\n                            {\n                                throw;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        public static void WriteSection<T>(ITypeDescriptorContext context, INISection section, T data)\n        {\n            var propertyDescriptors = TypeDescriptor.GetProperties(data);\n            var properties = data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetGetMethod() != null);\n            foreach (var property in properties)\n            {\n                if (property.GetCustomAttribute<NonSerializedINIKeyAttribute>() != null)\n                {\n                    continue;\n                }\n\n                var value = property.GetValue(data);\n                if (property.PropertyType.IsValueType || (value != null))\n                {\n                    var converter = propertyDescriptors.Find(property.Name, false)?.Converter ?? TypeDescriptor.GetConverter(property.PropertyType);\n                    if (converter.CanConvertTo(context, typeof(string)))\n                    {\n                        section[property.Name] = converter.ConvertToString(context, value);\n                    }\n                }\n            }\n        }\n\n        public static void ParseSection<T>(INISection section, T data) => ParseSection(null, section, data);\n\n        public static void WriteSection<T>(INISection section, T data) => WriteSection(null, section, data);\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/MRU.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing Microsoft.Win32;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Utility\n{\n    public class MRU\n    {\n        private readonly RegistryKey registryKey;\n        private readonly int maxFiles;\n\n        private readonly List<FileInfo> files = new List<FileInfo>();\n\n        private readonly ToolStripMenuItem menu;\n        private readonly ToolStripMenuItem[] fileItems;\n\n        public event EventHandler<FileInfo> FileSelected;\n\n        public MRU(string registryPath, int maxFiles, ToolStripMenuItem menu)\n        {\n            var subKey = Registry.CurrentUser;\n            foreach (var key in registryPath.Split('\\\\'))\n            {\n                subKey = subKey.CreateSubKey(key, true);\n            }\n            registryKey = subKey.CreateSubKey(\"MRU\");\n\n            this.maxFiles = maxFiles;\n            this.menu = menu;\n            this.menu.DropDownItems.Clear();\n\n            fileItems = new ToolStripMenuItem[maxFiles];\n            for (var i = 0; i < fileItems.Length; ++i)\n            {\n                var fileItem = fileItems[i] = new ToolStripMenuItem();\n                fileItem.Visible = false;\n                menu.DropDownItems.Add(fileItem);\n            }\n\n            LoadMRU();\n            ShowMRU();\n        }\n\n        public void Add(FileInfo file)\n        {\n            files.RemoveAll(f => f.FullName == file.FullName);\n            files.Insert(0, file);\n\n            if (files.Count > maxFiles)\n            {\n                files.RemoveAt(files.Count - 1);\n            }\n\n            SaveMRU();\n            ShowMRU();\n        }\n\n        public void Remove(FileInfo file)\n        {\n            files.RemoveAll(f => f.FullName == file.FullName);\n\n            SaveMRU();\n            ShowMRU();\n        }\n\n        private void LoadMRU()\n        {\n            files.Clear();\n            for (var i = 0; i < maxFiles; ++i)\n            {\n                string fileName = registryKey.GetValue(i.ToString()) as string;\n                if (!string.IsNullOrEmpty(fileName))\n                {\n                    files.Add(new FileInfo(fileName));\n                }\n            }\n        }\n\n        private void SaveMRU()\n        {\n            for (var i = 0; i < files.Count; ++i)\n            {\n                registryKey.SetValue(i.ToString(), files[i].FullName);\n            }\n            for (var i = files.Count; i < maxFiles; ++i)\n            {\n                registryKey.DeleteValue(i.ToString(), false);\n            }\n        }\n\n        private void ShowMRU()\n        {\n            for (var i = 0; i < files.Count; ++i)\n            {\n                var file = files[i];\n                var fileItem = fileItems[i];\n\n                fileItem.Text = string.Format(\"&{0} {1}\", i + 1, file.FullName);\n                fileItem.Tag = file;\n                fileItem.Click -= FileItem_Click;\n                fileItem.Click += FileItem_Click;\n                fileItem.Visible = true;\n            }\n            for (var i = files.Count; i < maxFiles; ++i)\n            {\n                var fileItem = fileItems[i];\n\n                fileItem.Visible = false;\n                fileItem.Click -= FileItem_Click;\n            }\n            menu.Enabled = files.Count > 0;\n        }\n\n        private void FileItem_Click(object sender, EventArgs e)\n        {\n            FileSelected?.Invoke(this, (sender as ToolStripMenuItem).Tag as FileInfo);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/Megafile.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.MemoryMappedFiles;\nusing System.Runtime.InteropServices;\n\nnamespace MobiusEditor.Utility\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 2)]\n    struct SubFileData\n    {\n        public ushort Flags;\n        public uint CRCValue;\n        public int SubfileIndex;\n        public uint SubfileSize;\n        public uint SubfileImageDataOffset;\n        public ushort SubfileNameIndex;\n\n        public static readonly uint Size = (uint)Marshal.SizeOf(typeof(SubFileData));\n    }\n\n    public class Megafile : IEnumerable<string>, IEnumerable, IDisposable\n    {\n        private readonly MemoryMappedFile megafileMap;\n\n        private readonly string[] stringTable;\n\n        private readonly Dictionary<string, SubFileData> fileTable = new Dictionary<string, SubFileData>();\n\n        public Megafile(string megafilePath)\n        {\n            megafileMap = MemoryMappedFile.CreateFromFile(\n                new FileStream(megafilePath, FileMode.Open, FileAccess.Read, FileShare.Read) , null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, false\n            );\n\n            var numFiles = 0U;\n            var numStrings = 0U;\n            var stringTableSize = 0U;\n            var fileTableSize = 0U;\n\n            var readOffset = 0U;\n            using (var magicNumberReader = new BinaryReader(megafileMap.CreateViewStream(readOffset, 4, MemoryMappedFileAccess.Read)))\n            {\n                var magicNumber = magicNumberReader.ReadUInt32();\n                if ((magicNumber == 0xFFFFFFFF) || (magicNumber == 0x8FFFFFFF))\n                {\n                    // Skip header size and version\n                    readOffset += 8;\n                }\n            }\n\n            readOffset += 4U;\n            using (var headerReader = new BinaryReader(megafileMap.CreateViewStream(readOffset, 12, MemoryMappedFileAccess.Read)))\n            {\n                numFiles = headerReader.ReadUInt32();\n                numStrings = headerReader.ReadUInt32();\n                stringTableSize = headerReader.ReadUInt32();\n                fileTableSize = numFiles * SubFileData.Size;\n            }\n\n            readOffset += 12U;\n            using (var stringReader = new BinaryReader(megafileMap.CreateViewStream(readOffset, stringTableSize, MemoryMappedFileAccess.Read)))\n            {\n                stringTable = new string[numStrings];\n\n                for (var i = 0U; i < numStrings; ++i)\n                {\n                    var stringSize = stringReader.ReadUInt16();\n                    stringTable[i] = new string(stringReader.ReadChars(stringSize));\n                }\n            }\n\n            readOffset += stringTableSize;\n            using (var subFileAccessor = megafileMap.CreateViewAccessor(readOffset, fileTableSize, MemoryMappedFileAccess.Read))\n            {\n                for (var i = 0U; i < numFiles; ++i)\n                {\n                    subFileAccessor.Read(i * SubFileData.Size, out SubFileData subFile);\n                    var fullName = stringTable[subFile.SubfileNameIndex];\n                    fileTable[fullName] = subFile;\n                }\n            }\n        }\n\n        public Stream Open(string path)\n        {\n            if (!fileTable.TryGetValue(path, out SubFileData subFile))\n            {\n                return null;\n            }\n\n            return megafileMap.CreateViewStream(subFile.SubfileImageDataOffset, subFile.SubfileSize, MemoryMappedFileAccess.Read);\n        }\n\n        public IEnumerator<string> GetEnumerator()\n        {\n            foreach (var file in stringTable)\n            {\n                yield return file;\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    megafileMap.Dispose();\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/MegafileBuilder.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace MobiusEditor.Utility\n{\n    public class MegafileBuilder : IDisposable\n    {\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    Out.Dispose();\n                }\n\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n\n        private const float Version = 0.99f;\n\n        public string RootPath { get; private set; }\n\n        private Stream Out { get; set; }\n\n        private List<(string, object)> Files = new List<(string, object)>();\n\n        public MegafileBuilder(string rootPath, string outFile)\n        {\n            RootPath = rootPath.ToUpper();\n            Out = new FileStream(outFile, FileMode.Create);\n        }\n\n        public void AddFile(string path)\n        {\n            if (File.Exists(path))\n            {\n                Files.Add((Path.GetFileName(path), path));\n            }\n        }\n\n        public void AddFile(string path, Stream stream)\n        {\n            Files.Add((Path.GetFileName(path), stream));\n        }\n\n        public void AddDirectory(string path)\n        {\n            AddDirectory(path, \"*.*\");\n        }\n\n        public void AddDirectory(string path, string searchPattern)\n        {\n            var uriPath = new Uri(path);\n            foreach (var file in Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories))\n            {\n                var relativePath = Uri.UnescapeDataString(uriPath.MakeRelativeUri(new Uri(file)).ToString()).Replace('/', Path.DirectorySeparatorChar);\n                Files.Add((relativePath, file));\n            }\n        }\n\n        public void Write()\n        {\n            var headerSize = sizeof(uint) * 6U;\n            headerSize += SubFileData.Size * (uint)Files.Count;\n\n            var strings = new List<string>();\n            Func<string, ushort> stringIndex = (string value) =>\n            {\n                var index = strings.IndexOf(value);\n                if (index < 0)\n                {\n                    index = strings.Count;\n                    if (index > ushort.MaxValue)\n                    {\n                        throw new IndexOutOfRangeException();\n                    }\n                    strings.Add(value);\n                }\n                return (ushort)index;\n            };\n\n            var files = new List<(ushort index, uint crc, Stream stream, bool dispose)>();\n            foreach (var (filename, source) in Files)\n            {\n                var name = Encoding.ASCII.GetBytes(filename);\n                var crc = CRC.Calculate(name);\n\n                if (source is string)\n                {\n                    var file = source as string;\n                    if (File.Exists(file))\n                    {\n                        files.Add((stringIndex(Path.Combine(RootPath, filename).ToUpper()), crc, new FileStream(file, FileMode.Open, FileAccess.Read), true));\n                    }\n                }\n                else if (source is Stream)\n                {\n                    files.Add((stringIndex(Path.Combine(RootPath, filename).ToUpper()), crc, source as Stream, false));\n                }\n            }\n            files = files.OrderBy(x => x.crc).ToList();\n\n            var stringsSize = sizeof(ushort) * (uint)strings.Count;\n            stringsSize += (uint)strings.Sum(x => x.Length);\n            headerSize += stringsSize;\n\n            var subfileImageOffset = headerSize;\n            using (var writer = new BinaryWriter(Out))\n            {\n                writer.Write(0xFFFFFFFF);\n                writer.Write(Version);\n                writer.Write(headerSize);\n\n                writer.Write((uint)Files.Count);\n                writer.Write((uint)strings.Count);\n                writer.Write(stringsSize);\n\n                foreach (var item in strings)\n                {\n                    writer.Write((ushort)item.Length);\n                    writer.Write(item.ToCharArray());\n                }\n\n                using (var fileStream = new MemoryStream())\n                {\n                    for (var i = 0; i < files.Count; ++i)\n                    {\n                        var (index, crc, stream, dispose) = files[i];\n\n                        var fileSize = (uint)(stream.Length - stream.Position);\n                        var fileBytes = new byte[fileSize];\n                        stream.Read(fileBytes, 0, fileBytes.Length);\n                        fileStream.Write(fileBytes, 0, fileBytes.Length);\n\n                        if (dispose)\n                        {\n                            stream.Dispose();\n                        }\n\n                        SubFileData data = new SubFileData\n                        {\n                            Flags = 0,\n                            CRCValue = crc,\n                            SubfileIndex = i,\n                            SubfileSize = fileSize,\n                            SubfileImageDataOffset = subfileImageOffset,\n                            SubfileNameIndex = index\n                        };\n\n                        var ptr = Marshal.AllocHGlobal((int)SubFileData.Size);\n                        Marshal.StructureToPtr(data, ptr, false);\n                        var bytes = new byte[SubFileData.Size];\n                        Marshal.Copy(ptr, bytes, 0, bytes.Length);\n                        Marshal.FreeHGlobal(ptr);\n\n                        writer.Write(bytes);\n\n                        subfileImageOffset += data.SubfileSize;\n                    }\n\n                    fileStream.Seek(0, SeekOrigin.Begin);\n                    fileStream.CopyTo(writer.BaseStream);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/MegafileManager.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace MobiusEditor.Utility\n{\n    public class MegafileManager : IEnumerable<string>, IEnumerable, IDisposable\n    {\n        private readonly string looseFilePath;\n\n        private readonly List<Megafile> megafiles = new List<Megafile>();\n\n        private readonly HashSet<string> filenames = new HashSet<string>();\n\n        public MegafileManager(string looseFilePath)\n        {\n            this.looseFilePath = looseFilePath;\n        }\n\n        public bool Load(string megafilePath)\n        {\n            if (!File.Exists(megafilePath))\n            {\n                return false;\n            }\n\n            var megafile = new Megafile(megafilePath);\n            filenames.UnionWith(megafile);\n            megafiles.Add(megafile);\n            return true;\n        }\n\n        public bool Exists(string path)\n        {\n            return File.Exists(Path.Combine(looseFilePath, path)) || filenames.Contains(path.ToUpper());\n        }\n\n        public Stream Open(string path)\n        {\n            string loosePath = Path.Combine(looseFilePath, path);\n            if (File.Exists(loosePath))\n            {\n                return File.Open(loosePath, FileMode.Open, FileAccess.Read);\n            }\n\n            foreach (var megafile in megafiles)\n            {\n                var stream = megafile.Open(path.ToUpper());\n                if (stream != null)\n                {\n                    return stream;\n                }\n            }\n\n            return null;\n        }\n\n        public IEnumerator<string> GetEnumerator()\n        {\n            return filenames.GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    megafiles.ForEach(m => m.Dispose());\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/PropertyTracker.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Dynamic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MobiusEditor.Utility\n{\n    public class TrackablePropertyDescriptor<T> : PropertyDescriptor\n    {\n        private readonly T obj;\n        private readonly PropertyInfo propertyInfo;\n        private readonly Dictionary<string, object> propertyValues;\n\n        public override Type ComponentType => obj.GetType();\n\n        public override bool IsReadOnly => false;\n\n        public override Type PropertyType => propertyInfo.PropertyType;\n\n        public TrackablePropertyDescriptor(string name, T obj, PropertyInfo propertyInfo, Dictionary<string, object> propertyValues)\n            : base(name, null)\n        {\n            this.obj = obj;\n            this.propertyInfo = propertyInfo;\n            this.propertyValues = propertyValues;\n        }\n\n        public override bool CanResetValue(object component)\n        {\n            return propertyValues.ContainsKey(Name);\n        }\n\n        public override object GetValue(object component)\n        {\n            if (propertyValues.TryGetValue(Name, out object result))\n            {\n                return result;\n            }\n            return propertyInfo.GetValue(obj);\n        }\n\n        public override void ResetValue(object component)\n        {\n            propertyValues.Remove(Name);\n        }\n\n        public override void SetValue(object component, object value)\n        {\n            if (Equals(propertyInfo.GetValue(obj), value))\n            {\n                propertyValues.Remove(Name);\n            }\n            else\n            {\n                propertyValues[Name] = value;\n            }\n        }\n\n        public override bool ShouldSerializeValue(object component)\n        {\n            return false;\n        }\n    }\n\n    public class PropertyTracker<T> : DynamicObject, ICustomTypeDescriptor\n    {\n        private readonly Dictionary<string, PropertyInfo> trackableProperties;\n        private readonly Dictionary<string, object> propertyValues = new Dictionary<string, object>();\n\n        public T Object { get; private set; }\n        \n        public PropertyTracker(T obj)\n        {\n            Object = obj;\n\n            trackableProperties = Object.GetType()\n                .GetProperties(BindingFlags.Public | BindingFlags.Instance)\n                .Where(p => (p.GetGetMethod() != null) && (p.GetSetMethod() != null))\n                .ToDictionary(k => k.Name, v => v);\n        }\n\n        public void Revert() => propertyValues.Clear();\n\n        public void Commit()\n        {\n            foreach (var propertyValue in propertyValues)\n            {\n                trackableProperties[propertyValue.Key].SetValue(Object, propertyValue.Value);\n            }\n            propertyValues.Clear();\n        }\n\n        public IDictionary<string, object> GetUndoValues() => propertyValues.ToDictionary(kv => kv.Key, kv => trackableProperties[kv.Key].GetValue(Object));\n\n        public IDictionary<string, object> GetRedoValues() => new Dictionary<string, object>(propertyValues);\n\n        public override bool TryGetMember(GetMemberBinder binder, out object result)\n        {\n            if (!trackableProperties.TryGetValue(binder.Name, out PropertyInfo property))\n            {\n                result = null;\n                return false;\n            }\n\n            if (!propertyValues.TryGetValue(binder.Name, out result))\n            {\n                result = property.GetValue(Object);\n            }\n            return true;\n        }\n\n        public override bool TrySetMember(SetMemberBinder binder, object value)\n        {\n            if (!trackableProperties.TryGetValue(binder.Name, out PropertyInfo property))\n            {\n                return false;\n            }\n\n            if (Equals(property.GetValue(Object), value))\n            {\n                propertyValues.Remove(binder.Name);\n            }\n            else\n            {\n                propertyValues[binder.Name] = value;\n            }\n            return true;\n        }\n\n        public AttributeCollection GetAttributes()\n        {\n            return TypeDescriptor.GetAttributes(Object.GetType());\n        }\n\n        public string GetClassName()\n        {\n            return TypeDescriptor.GetClassName(Object.GetType());\n        }\n\n        public string GetComponentName()\n        {\n            return TypeDescriptor.GetComponentName(Object.GetType());\n        }\n\n        public TypeConverter GetConverter()\n        {\n            return TypeDescriptor.GetConverter(Object.GetType());\n        }\n\n        public EventDescriptor GetDefaultEvent()\n        {\n            return TypeDescriptor.GetDefaultEvent(Object.GetType());\n        }\n\n        public PropertyDescriptor GetDefaultProperty()\n        {\n            return TypeDescriptor.GetDefaultProperty(Object.GetType());\n        }\n\n        public object GetEditor(Type editorBaseType)\n        {\n            return TypeDescriptor.GetEditor(Object.GetType(), editorBaseType);\n        }\n\n        public EventDescriptorCollection GetEvents()\n        {\n            return TypeDescriptor.GetEvents(Object.GetType());\n        }\n\n        public EventDescriptorCollection GetEvents(Attribute[] attributes)\n        {\n            return TypeDescriptor.GetEvents(Object.GetType(), attributes);\n        }\n\n        public PropertyDescriptorCollection GetProperties()\n        {\n            var propertyDescriptors = trackableProperties.Select(kv =>\n            {\n                return new TrackablePropertyDescriptor<T>(kv.Key, Object, kv.Value, propertyValues);\n            }).ToArray();\n            return new PropertyDescriptorCollection(propertyDescriptors);\n        }\n\n        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)\n        {\n            return GetProperties();\n        }\n\n        public object GetPropertyOwner(PropertyDescriptor pd)\n        {\n            return Object;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/SteamworksUGC.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Model;\nusing Steamworks;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Text;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Utility\n{\n    public interface ISteamworksOperation : IDisposable\n    {\n        bool Done { get; }\n\n        bool Failed { get; }\n\n        string Status { get; }\n\n        void OnSuccess();\n\n        void OnFailed();\n    }\n\n    public class SteamworksUGCPublishOperation : ISteamworksOperation\n    {\n        private readonly string ugcPath;\n        private readonly IList<string> tags;\n        private readonly Action onSuccess;\n        private readonly Action<string> onFailed;\n\n        private CallResult<CreateItemResult_t> createItemResult;\n        private CallResult<SubmitItemUpdateResult_t> submitItemUpdateResult;\n        private SteamSection steamSection = new SteamSection();\n\n        public bool Done => !(createItemResult?.IsActive() ?? false) && !(submitItemUpdateResult?.IsActive() ?? false);\n\n        public bool Failed { get; private set; }\n\n        public string Status { get; private set; }\n\n        public SteamworksUGCPublishOperation(string ugcPath, SteamSection steamSection, IList<string> tags, Action onSuccess, Action<string> onFailed)\n        {\n            this.ugcPath = ugcPath;\n            this.steamSection = steamSection;\n            this.tags = tags;\n            this.onSuccess = onSuccess;\n            this.onFailed = onFailed;\n\n            if (steamSection.PublishedFileId == PublishedFileId_t.Invalid.m_PublishedFileId)\n            {\n                CreateUGCItem();\n            }\n            else\n            {\n                UpdateUGCItem();\n            }\n\n            Status = \"Publishing UGC...\";\n        }\n\n        public void OnSuccess() => onSuccess();\n\n        public void OnFailed() => onFailed(Status);\n\n        private void CreateUGCItem()\n        {\n            var steamAPICall = SteamUGC.CreateItem(SteamUtils.GetAppID(), EWorkshopFileType.k_EWorkshopFileTypeCommunity);\n            if (steamAPICall == SteamAPICall_t.Invalid)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            createItemResult = CallResult<CreateItemResult_t>.Create(OnCreateItemResult);\n            createItemResult.Set(steamAPICall);\n        }\n\n        private void UpdateUGCItem()\n        {\n            var updateHandle = SteamUGC.StartItemUpdate(SteamUtils.GetAppID(), new PublishedFileId_t(steamSection.PublishedFileId));\n            if (updateHandle == UGCUpdateHandle_t.Invalid)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            bool success = true;\n            success = success && SteamUGC.SetItemContent(updateHandle, ugcPath);\n            success = success && SteamUGC.SetItemPreview(updateHandle, steamSection.PreviewFile);\n            success = success && SteamUGC.SetItemUpdateLanguage(updateHandle, \"English\");\n            success = success && SteamUGC.SetItemTitle(updateHandle, steamSection.Title);\n            success = success && SteamUGC.SetItemDescription(updateHandle, steamSection.Description);\n            success = success && SteamUGC.SetItemVisibility(updateHandle, steamSection.Visibility);\n            success = success && SteamUGC.SetItemTags(updateHandle, tags);\n            if (!success)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            var steamAPICall = SteamUGC.SubmitItemUpdate(updateHandle, \"\");\n            if (steamAPICall == SteamAPICall_t.Invalid)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            submitItemUpdateResult = CallResult<SubmitItemUpdateResult_t>.Create(OnSubmitItemUpdateResult);\n            submitItemUpdateResult.Set(steamAPICall);\n        }\n\n        private void OnCreateItemResult(CreateItemResult_t callback, bool ioFailure)\n        {\n            if (ioFailure)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            switch (callback.m_eResult)\n            {\n                case EResult.k_EResultOK:\n                    steamSection.PublishedFileId = callback.m_nPublishedFileId.m_PublishedFileId;\n                    UpdateUGCItem();\n                    break;\n                case EResult.k_EResultFileNotFound:\n                    Failed = true;\n                    Status = \"UGC not found.\";\n                    break;\n                case EResult.k_EResultNotLoggedOn:\n                    Failed = true;\n                    Status = \"Not logged on.\";\n                    break;\n                default:\n                    Failed = true;\n                    Status = \"Publishing failed.\";\n                    break;\n            }\n        }\n\n        private void OnSubmitItemUpdateResult(SubmitItemUpdateResult_t callback, bool ioFailure)\n        {\n            if (ioFailure)\n            {\n                Failed = true;\n                Status = \"Publishing failed.\";\n                return;\n            }\n\n            switch (callback.m_eResult)\n            {\n                case EResult.k_EResultOK:\n                    Status = \"Done.\";\n                    steamSection.PublishedFileId = callback.m_nPublishedFileId.m_PublishedFileId;\n                    break;\n                case EResult.k_EResultFileNotFound:\n                    Failed = true;\n                    Status = \"UGC not found.\";\n                    break;\n                case EResult.k_EResultLimitExceeded:\n                    Failed = true;\n                    Status = \"Size limit exceeded.\";\n                    break;\n                default:\n                    Failed = true;\n                    Status = string.Format(\"Publishing failed. ({0})\", callback.m_eResult);\n                    break;\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    createItemResult?.Dispose();\n                    submitItemUpdateResult?.Dispose();\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n\n    public static class SteamworksUGC\n    {\n        public static bool IsInit { get; private set; }\n\n        public static ISteamworksOperation CurrentOperation { get; private set; }\n\n        public static string WorkshopURL\n        {\n            get\n            {\n                var app_id = IsInit ? SteamUtils.GetAppID() : AppId_t.Invalid;\n                if (app_id == AppId_t.Invalid)\n                {\n                    return string.Empty;\n                }\n                return string.Format(\"http://steamcommunity.com/app/{0}/workshop/\", app_id.ToString());\n            }\n        }\n\n        public static bool IsSteamBuild => File.Exists(\"steam_appid.txt\");\n\n        private static Callback<GameLobbyJoinRequested_t> GameLobbyJoinRequested;\n\n        public static bool Init()\n        {\n            if (IsInit)\n            {\n                return true;\n            }\n\n            if (!IsSteamBuild)\n            {\n                return false;\n            }\n\n            if (!Packsize.Test())\n            {\n                return false;\n            }\n\n            if (!DllCheck.Test())\n            {\n                return false;\n            }\n\n            if (!SteamAPI.Init())\n            {\n                return false;\n            }\n\n            SteamClient.SetWarningMessageHook(new SteamAPIWarningMessageHook_t(SteamAPIDebugTextHook));\n\n            GameLobbyJoinRequested = Callback<GameLobbyJoinRequested_t>.Create(OnGameLobbyJoinRequested);\n\n            IsInit = true;\n            return IsInit;\n        }\n\n        public static void Shutdown()\n        {\n            if (IsInit)\n            {\n                GameLobbyJoinRequested?.Dispose();\n                GameLobbyJoinRequested = null;\n\n                CurrentOperation?.Dispose();\n                CurrentOperation = null;\n\n                SteamAPI.Shutdown();\n                IsInit = false;\n            }\n        }\n\n        public static void Service()\n        {\n            SteamAPI.RunCallbacks();\n\n            if (CurrentOperation?.Done ?? false)\n            {\n                if (CurrentOperation.Failed)\n                {\n                    CurrentOperation.OnFailed();\n                }\n                else\n                {\n                    CurrentOperation.OnSuccess();\n                }\n                CurrentOperation.Dispose();\n                CurrentOperation = null;\n            }\n        }\n\n        public static bool PublishUGC(string ugcPath, SteamSection steamSection, IList<string> tags, Action onSuccess, Action<string> onFailed)\n        {\n            if (CurrentOperation != null)\n            {\n                return false;\n            }\n\n            CurrentOperation = new SteamworksUGCPublishOperation(ugcPath, steamSection, tags, onSuccess, onFailed);\n\n            return true;\n        }\n\n        private static void SteamAPIDebugTextHook(int nSeverity, StringBuilder pchDebugText)\n        {\n            Debug.WriteLine(pchDebugText);\n        }\n\n        private static void OnGameLobbyJoinRequested(GameLobbyJoinRequested_t data)\n        {\n            MessageBox.Show(\"You cannot accept an invitation to a multiplayer game while using the map editor.\", \"Steam\", MessageBoxButtons.OK, MessageBoxIcon.Information);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/TGASharpLib.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n/*                         MIT License\n                 Copyright (c) 2017 TGASharpLib\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.IO;\nusing System.Runtime.InteropServices;\n\nnamespace TGASharpLib\n{\n    #region Enums\n    /// <summary>\n    /// <para>The first 128 Color Map Type codes are reserved for use by Truevision,\n    /// while the second set of 128 Color Map Type codes(128 to 255) may be used for\n    /// developer applications.</para>\n    /// True-Color images do not normally make use of the color map field, but some current\n    /// applications store palette information or developer-defined information in this field.\n    /// It is best to check Field 3, Image Type, to make sure you have a file which can use the\n    /// data stored in the Color Map Field.\n    /// Otherwise ignore the information. When saving or creating files for True-Color\n    /// images do not use this field and set it to Zero to ensure compatibility. Please refer\n    /// to the Developer Area specification for methods of storing developer defined information.\n    /// </summary>\n    public enum TgaColorMapType : byte\n    {\n        NoColorMap = 0,\n        ColorMap = 1,\n        Truevision_2,\n        Truevision_3,\n        Truevision_4,\n        Truevision_5,\n        Truevision_6,\n        Truevision_7,\n        Truevision_8,\n        Truevision_9,\n        Truevision_10,\n        Truevision_11,\n        Truevision_12,\n        Truevision_13,\n        Truevision_14,\n        Truevision_15,\n        Truevision_16,\n        Truevision_17,\n        Truevision_18,\n        Truevision_19,\n        Truevision_20,\n        Truevision_21,\n        Truevision_22,\n        Truevision_23,\n        Truevision_24,\n        Truevision_25,\n        Truevision_26,\n        Truevision_27,\n        Truevision_28,\n        Truevision_29,\n        Truevision_30,\n        Truevision_31,\n        Truevision_32,\n        Truevision_33,\n        Truevision_34,\n        Truevision_35,\n        Truevision_36,\n        Truevision_37,\n        Truevision_38,\n        Truevision_39,\n        Truevision_40,\n        Truevision_41,\n        Truevision_42,\n        Truevision_43,\n        Truevision_44,\n        Truevision_45,\n        Truevision_46,\n        Truevision_47,\n        Truevision_48,\n        Truevision_49,\n        Truevision_50,\n        Truevision_51,\n        Truevision_52,\n        Truevision_53,\n        Truevision_54,\n        Truevision_55,\n        Truevision_56,\n        Truevision_57,\n        Truevision_58,\n        Truevision_59,\n        Truevision_60,\n        Truevision_61,\n        Truevision_62,\n        Truevision_63,\n        Truevision_64,\n        Truevision_65,\n        Truevision_66,\n        Truevision_67,\n        Truevision_68,\n        Truevision_69,\n        Truevision_70,\n        Truevision_71,\n        Truevision_72,\n        Truevision_73,\n        Truevision_74,\n        Truevision_75,\n        Truevision_76,\n        Truevision_77,\n        Truevision_78,\n        Truevision_79,\n        Truevision_80,\n        Truevision_81,\n        Truevision_82,\n        Truevision_83,\n        Truevision_84,\n        Truevision_85,\n        Truevision_86,\n        Truevision_87,\n        Truevision_88,\n        Truevision_89,\n        Truevision_90,\n        Truevision_91,\n        Truevision_92,\n        Truevision_93,\n        Truevision_94,\n        Truevision_95,\n        Truevision_96,\n        Truevision_97,\n        Truevision_98,\n        Truevision_99,\n        Truevision_100,\n        Truevision_101,\n        Truevision_102,\n        Truevision_103,\n        Truevision_104,\n        Truevision_105,\n        Truevision_106,\n        Truevision_107,\n        Truevision_108,\n        Truevision_109,\n        Truevision_110,\n        Truevision_111,\n        Truevision_112,\n        Truevision_113,\n        Truevision_114,\n        Truevision_115,\n        Truevision_116,\n        Truevision_117,\n        Truevision_118,\n        Truevision_119,\n        Truevision_120,\n        Truevision_121,\n        Truevision_122,\n        Truevision_123,\n        Truevision_124,\n        Truevision_125,\n        Truevision_126,\n        Truevision_127,\n        Other_128,\n        Other_129,\n        Other_130,\n        Other_131,\n        Other_132,\n        Other_133,\n        Other_134,\n        Other_135,\n        Other_136,\n        Other_137,\n        Other_138,\n        Other_139,\n        Other_140,\n        Other_141,\n        Other_142,\n        Other_143,\n        Other_144,\n        Other_145,\n        Other_146,\n        Other_147,\n        Other_148,\n        Other_149,\n        Other_150,\n        Other_151,\n        Other_152,\n        Other_153,\n        Other_154,\n        Other_155,\n        Other_156,\n        Other_157,\n        Other_158,\n        Other_159,\n        Other_160,\n        Other_161,\n        Other_162,\n        Other_163,\n        Other_164,\n        Other_165,\n        Other_166,\n        Other_167,\n        Other_168,\n        Other_169,\n        Other_170,\n        Other_171,\n        Other_172,\n        Other_173,\n        Other_174,\n        Other_175,\n        Other_176,\n        Other_177,\n        Other_178,\n        Other_179,\n        Other_180,\n        Other_181,\n        Other_182,\n        Other_183,\n        Other_184,\n        Other_185,\n        Other_186,\n        Other_187,\n        Other_188,\n        Other_189,\n        Other_190,\n        Other_191,\n        Other_192,\n        Other_193,\n        Other_194,\n        Other_195,\n        Other_196,\n        Other_197,\n        Other_198,\n        Other_199,\n        Other_200,\n        Other_201,\n        Other_202,\n        Other_203,\n        Other_204,\n        Other_205,\n        Other_206,\n        Other_207,\n        Other_208,\n        Other_209,\n        Other_210,\n        Other_211,\n        Other_212,\n        Other_213,\n        Other_214,\n        Other_215,\n        Other_216,\n        Other_217,\n        Other_218,\n        Other_219,\n        Other_220,\n        Other_221,\n        Other_222,\n        Other_223,\n        Other_224,\n        Other_225,\n        Other_226,\n        Other_227,\n        Other_228,\n        Other_229,\n        Other_230,\n        Other_231,\n        Other_232,\n        Other_233,\n        Other_234,\n        Other_235,\n        Other_236,\n        Other_237,\n        Other_238,\n        Other_239,\n        Other_240,\n        Other_241,\n        Other_242,\n        Other_243,\n        Other_244,\n        Other_245,\n        Other_246,\n        Other_247,\n        Other_248,\n        Other_249,\n        Other_250,\n        Other_251,\n        Other_252,\n        Other_253,\n        Other_254,\n        Other_255\n    }\n\n    /// <summary>\n    /// Establishes the number of bits per entry. Typically 15, 16, 24 or 32-bit values are used.\n    /// <para>When working with VDA or VDA/D cards it is preferred that you select 16 bits(5 bits\n    /// per primary with 1 bit to select interrupt control) and set the 16th bit to 0 so that the\n    /// interrupt bit is disabled. Even if this field is set to 15 bits(5 bits per primary) you\n    /// must still parse the color map data 16 bits at a time and ignore the 16th bit.</para>\n    /// <para>When working with a TARGA M8 card you would select 24 bits (8 bits per primary)\n    /// since the color map is defined as 256 entries of 24 bit color values.</para>\n    /// When working with a TrueVista card(ATVista or NuVista) you would select 24-bit(8 bits per\n    /// primary) or 32-bit(8 bits per primary including Alpha channel) depending on your\n    /// application’s use of look-up tables. It is suggested that when working with 16-bit and\n    /// 32-bit color images, you store them as True-Color images and do not use the color map \n    /// field to store look-up tables. Please refer to the TGA Extensions for fields better suited\n    /// to storing look-up table information.\n    /// </summary>\n    public enum TgaColorMapEntrySize : byte\n    {\n        Other = 0,\n        X1R5G5B5 = 15,\n        A1R5G5B5 = 16,\n        R8G8B8 = 24,\n        A8R8G8B8 = 32\n    }\n\n    /// <summary>\n    /// Truevision has currently defined seven image types:\n    /// <para>0 - No Image Data Included;</para>\n    /// <para>1 - Uncompressed, Color-mapped Image;</para>\n    /// <para>2 - Uncompressed, True-color Image;</para>\n    /// <para>3 - Uncompressed, Black-and-white Image;</para>\n    /// <para>9 - Run-length encoded, Color-mapped Image;</para>\n    /// <para>10 - Run-length encoded, True-color Image;</para>\n    /// <para>11 - Run-length encoded, Black-and-white Image.</para>\n    /// Image Data Type codes 0 to 127 are reserved for use by Truevision for general applications.\n    /// Image Data Type codes 128 to 255 may be used for developer applications.\n    /// </summary>\n    public enum TgaImageType : byte\n    {\n        NoImageData = 0,\n        Uncompressed_ColorMapped = 1,\n        Uncompressed_TrueColor,\n        Uncompressed_BlackWhite,\n        _Truevision_4,\n        _Truevision_5,\n        _Truevision_6,\n        _Truevision_7,\n        _Truevision_8,\n        RLE_ColorMapped = 9,\n        RLE_TrueColor,\n        RLE_BlackWhite,\n        _Truevision_12,\n        _Truevision_13,\n        _Truevision_14,\n        _Truevision_15,\n        _Truevision_16,\n        _Truevision_17,\n        _Truevision_18,\n        _Truevision_19,\n        _Truevision_20,\n        _Truevision_21,\n        _Truevision_22,\n        _Truevision_23,\n        _Truevision_24,\n        _Truevision_25,\n        _Truevision_26,\n        _Truevision_27,\n        _Truevision_28,\n        _Truevision_29,\n        _Truevision_30,\n        _Truevision_31,\n        _Truevision_32,\n        _Truevision_33,\n        _Truevision_34,\n        _Truevision_35,\n        _Truevision_36,\n        _Truevision_37,\n        _Truevision_38,\n        _Truevision_39,\n        _Truevision_40,\n        _Truevision_41,\n        _Truevision_42,\n        _Truevision_43,\n        _Truevision_44,\n        _Truevision_45,\n        _Truevision_46,\n        _Truevision_47,\n        _Truevision_48,\n        _Truevision_49,\n        _Truevision_50,\n        _Truevision_51,\n        _Truevision_52,\n        _Truevision_53,\n        _Truevision_54,\n        _Truevision_55,\n        _Truevision_56,\n        _Truevision_57,\n        _Truevision_58,\n        _Truevision_59,\n        _Truevision_60,\n        _Truevision_61,\n        _Truevision_62,\n        _Truevision_63,\n        _Truevision_64,\n        _Truevision_65,\n        _Truevision_66,\n        _Truevision_67,\n        _Truevision_68,\n        _Truevision_69,\n        _Truevision_70,\n        _Truevision_71,\n        _Truevision_72,\n        _Truevision_73,\n        _Truevision_74,\n        _Truevision_75,\n        _Truevision_76,\n        _Truevision_77,\n        _Truevision_78,\n        _Truevision_79,\n        _Truevision_80,\n        _Truevision_81,\n        _Truevision_82,\n        _Truevision_83,\n        _Truevision_84,\n        _Truevision_85,\n        _Truevision_86,\n        _Truevision_87,\n        _Truevision_88,\n        _Truevision_89,\n        _Truevision_90,\n        _Truevision_91,\n        _Truevision_92,\n        _Truevision_93,\n        _Truevision_94,\n        _Truevision_95,\n        _Truevision_96,\n        _Truevision_97,\n        _Truevision_98,\n        _Truevision_99,\n        _Truevision_100,\n        _Truevision_101,\n        _Truevision_102,\n        _Truevision_103,\n        _Truevision_104,\n        _Truevision_105,\n        _Truevision_106,\n        _Truevision_107,\n        _Truevision_108,\n        _Truevision_109,\n        _Truevision_110,\n        _Truevision_111,\n        _Truevision_112,\n        _Truevision_113,\n        _Truevision_114,\n        _Truevision_115,\n        _Truevision_116,\n        _Truevision_117,\n        _Truevision_118,\n        _Truevision_119,\n        _Truevision_120,\n        _Truevision_121,\n        _Truevision_122,\n        _Truevision_123,\n        _Truevision_124,\n        _Truevision_125,\n        _Truevision_126,\n        _Truevision_127,\n        _Other_128,\n        _Other_129,\n        _Other_130,\n        _Other_131,\n        _Other_132,\n        _Other_133,\n        _Other_134,\n        _Other_135,\n        _Other_136,\n        _Other_137,\n        _Other_138,\n        _Other_139,\n        _Other_140,\n        _Other_141,\n        _Other_142,\n        _Other_143,\n        _Other_144,\n        _Other_145,\n        _Other_146,\n        _Other_147,\n        _Other_148,\n        _Other_149,\n        _Other_150,\n        _Other_151,\n        _Other_152,\n        _Other_153,\n        _Other_154,\n        _Other_155,\n        _Other_156,\n        _Other_157,\n        _Other_158,\n        _Other_159,\n        _Other_160,\n        _Other_161,\n        _Other_162,\n        _Other_163,\n        _Other_164,\n        _Other_165,\n        _Other_166,\n        _Other_167,\n        _Other_168,\n        _Other_169,\n        _Other_170,\n        _Other_171,\n        _Other_172,\n        _Other_173,\n        _Other_174,\n        _Other_175,\n        _Other_176,\n        _Other_177,\n        _Other_178,\n        _Other_179,\n        _Other_180,\n        _Other_181,\n        _Other_182,\n        _Other_183,\n        _Other_184,\n        _Other_185,\n        _Other_186,\n        _Other_187,\n        _Other_188,\n        _Other_189,\n        _Other_190,\n        _Other_191,\n        _Other_192,\n        _Other_193,\n        _Other_194,\n        _Other_195,\n        _Other_196,\n        _Other_197,\n        _Other_198,\n        _Other_199,\n        _Other_200,\n        _Other_201,\n        _Other_202,\n        _Other_203,\n        _Other_204,\n        _Other_205,\n        _Other_206,\n        _Other_207,\n        _Other_208,\n        _Other_209,\n        _Other_210,\n        _Other_211,\n        _Other_212,\n        _Other_213,\n        _Other_214,\n        _Other_215,\n        _Other_216,\n        _Other_217,\n        _Other_218,\n        _Other_219,\n        _Other_220,\n        _Other_221,\n        _Other_222,\n        _Other_223,\n        _Other_224,\n        _Other_225,\n        _Other_226,\n        _Other_227,\n        _Other_228,\n        _Other_229,\n        _Other_230,\n        _Other_231,\n        _Other_232,\n        _Other_233,\n        _Other_234,\n        _Other_235,\n        _Other_236,\n        _Other_237,\n        _Other_238,\n        _Other_239,\n        _Other_240,\n        _Other_241,\n        _Other_242,\n        _Other_243,\n        _Other_244,\n        _Other_245,\n        _Other_246,\n        _Other_247,\n        _Other_248,\n        _Other_249,\n        _Other_250,\n        _Other_251,\n        _Other_252,\n        _Other_253,\n        _Other_254,\n        _Other_255\n    }\n\n    /// <summary>\n    /// Number of bits per pixel. This number includes the Attribute or Alpha channel bits.\n    /// Common values are 8, 16, 24 and 32 but other pixel depths could be used.\n    /// </summary>\n    public enum TgaPixelDepth : byte\n    {\n        Other = 0,\n        Bpp8 = 8,\n        Bpp16 = 16,\n        Bpp24 = 24,\n        Bpp32 = 32\n    }\n\n    /// <summary>\n    /// Used to indicate the order in which pixel data is transferred from the file to the screen.\n    /// (Bit 4 (bit 0 in enum) is for left-to-right ordering and bit 5 (bit 1 in enum) is for\n    /// topto-bottom ordering as shown below.)\n    /// </summary>\n    public enum TgaImgOrigin : byte\n    {\n        BottomLeft = 0,\n        BottomRight,\n        TopLeft,\n        TopRight\n    }\n\n    /// <summary>\n    /// Contains a value which specifies the type of Alpha channel\n    /// data contained in the file. Value Meaning:\n    /// <para>0: no Alpha data included (bits 3-0 of field 5.6 should also be set to zero)</para>\n    /// <para>1: undefined data in the Alpha field, can be ignored</para>\n    /// <para>2: undefined data in the Alpha field, but should be retained</para>\n    /// <para>3: useful Alpha channel data is present</para>\n    /// <para>4: pre-multiplied Alpha(see description below)</para>\n    /// <para>5 -127: RESERVED</para>\n    /// <para>128-255: Un-assigned</para>\n    /// <para>Pre-multiplied Alpha Example: Suppose the Alpha channel data is being used to specify the\n    /// opacity of each pixel(for use when the image is overlayed on another image), where 0 indicates\n    /// that the pixel is completely transparent and a value of 1 indicates that the pixel is\n    /// completely opaque(assume all component values have been normalized).</para>\n    /// <para>A quadruple(a, r, g, b) of( 0.5, 1, 0, 0) would indicate that the pixel is pure red with a\n    /// transparency of one-half. For numerous reasons(including image compositing) is is better to\n    /// pre-multiply the individual color components with the value in the Alpha channel.</para>\n    /// A pre-multiplication of the above would produce a quadruple(0.5, 0.5, 0, 0).\n    /// A value of 3 in the Attributes Type Field(field 23) would indicate that the color components\n    /// of the pixel have already been scaled by the value in the Alpha channel.\n    /// </summary>\n    public enum TgaAttrType : byte\n    {\n        NoAlpha = 0,\n        UndefinedAlphaCanBeIgnored,\n        UndefinedAlphaButShouldBeRetained,\n        UsefulAlpha,\n        PreMultipliedAlpha,\n        _Reserved_5,\n        _Reserved_6,\n        _Reserved_7,\n        _Reserved_8,\n        _Reserved_9,\n        _Reserved_10,\n        _Reserved_11,\n        _Reserved_12,\n        _Reserved_13,\n        _Reserved_14,\n        _Reserved_15,\n        _Reserved_16,\n        _Reserved_17,\n        _Reserved_18,\n        _Reserved_19,\n        _Reserved_20,\n        _Reserved_21,\n        _Reserved_22,\n        _Reserved_23,\n        _Reserved_24,\n        _Reserved_25,\n        _Reserved_26,\n        _Reserved_27,\n        _Reserved_28,\n        _Reserved_29,\n        _Reserved_30,\n        _Reserved_31,\n        _Reserved_32,\n        _Reserved_33,\n        _Reserved_34,\n        _Reserved_35,\n        _Reserved_36,\n        _Reserved_37,\n        _Reserved_38,\n        _Reserved_39,\n        _Reserved_40,\n        _Reserved_41,\n        _Reserved_42,\n        _Reserved_43,\n        _Reserved_44,\n        _Reserved_45,\n        _Reserved_46,\n        _Reserved_47,\n        _Reserved_48,\n        _Reserved_49,\n        _Reserved_50,\n        _Reserved_51,\n        _Reserved_52,\n        _Reserved_53,\n        _Reserved_54,\n        _Reserved_55,\n        _Reserved_56,\n        _Reserved_57,\n        _Reserved_58,\n        _Reserved_59,\n        _Reserved_60,\n        _Reserved_61,\n        _Reserved_62,\n        _Reserved_63,\n        _Reserved_64,\n        _Reserved_65,\n        _Reserved_66,\n        _Reserved_67,\n        _Reserved_68,\n        _Reserved_69,\n        _Reserved_70,\n        _Reserved_71,\n        _Reserved_72,\n        _Reserved_73,\n        _Reserved_74,\n        _Reserved_75,\n        _Reserved_76,\n        _Reserved_77,\n        _Reserved_78,\n        _Reserved_79,\n        _Reserved_80,\n        _Reserved_81,\n        _Reserved_82,\n        _Reserved_83,\n        _Reserved_84,\n        _Reserved_85,\n        _Reserved_86,\n        _Reserved_87,\n        _Reserved_88,\n        _Reserved_89,\n        _Reserved_90,\n        _Reserved_91,\n        _Reserved_92,\n        _Reserved_93,\n        _Reserved_94,\n        _Reserved_95,\n        _Reserved_96,\n        _Reserved_97,\n        _Reserved_98,\n        _Reserved_99,\n        _Reserved_100,\n        _Reserved_101,\n        _Reserved_102,\n        _Reserved_103,\n        _Reserved_104,\n        _Reserved_105,\n        _Reserved_106,\n        _Reserved_107,\n        _Reserved_108,\n        _Reserved_109,\n        _Reserved_110,\n        _Reserved_111,\n        _Reserved_112,\n        _Reserved_113,\n        _Reserved_114,\n        _Reserved_115,\n        _Reserved_116,\n        _Reserved_117,\n        _Reserved_118,\n        _Reserved_119,\n        _Reserved_120,\n        _Reserved_121,\n        _Reserved_122,\n        _Reserved_123,\n        _Reserved_124,\n        _Reserved_125,\n        _Reserved_126,\n        _Reserved_127,\n        _UnAssigned_128,\n        _UnAssigned_129,\n        _UnAssigned_130,\n        _UnAssigned_131,\n        _UnAssigned_132,\n        _UnAssigned_133,\n        _UnAssigned_134,\n        _UnAssigned_135,\n        _UnAssigned_136,\n        _UnAssigned_137,\n        _UnAssigned_138,\n        _UnAssigned_139,\n        _UnAssigned_140,\n        _UnAssigned_141,\n        _UnAssigned_142,\n        _UnAssigned_143,\n        _UnAssigned_144,\n        _UnAssigned_145,\n        _UnAssigned_146,\n        _UnAssigned_147,\n        _UnAssigned_148,\n        _UnAssigned_149,\n        _UnAssigned_150,\n        _UnAssigned_151,\n        _UnAssigned_152,\n        _UnAssigned_153,\n        _UnAssigned_154,\n        _UnAssigned_155,\n        _UnAssigned_156,\n        _UnAssigned_157,\n        _UnAssigned_158,\n        _UnAssigned_159,\n        _UnAssigned_160,\n        _UnAssigned_161,\n        _UnAssigned_162,\n        _UnAssigned_163,\n        _UnAssigned_164,\n        _UnAssigned_165,\n        _UnAssigned_166,\n        _UnAssigned_167,\n        _UnAssigned_168,\n        _UnAssigned_169,\n        _UnAssigned_170,\n        _UnAssigned_171,\n        _UnAssigned_172,\n        _UnAssigned_173,\n        _UnAssigned_174,\n        _UnAssigned_175,\n        _UnAssigned_176,\n        _UnAssigned_177,\n        _UnAssigned_178,\n        _UnAssigned_179,\n        _UnAssigned_180,\n        _UnAssigned_181,\n        _UnAssigned_182,\n        _UnAssigned_183,\n        _UnAssigned_184,\n        _UnAssigned_185,\n        _UnAssigned_186,\n        _UnAssigned_187,\n        _UnAssigned_188,\n        _UnAssigned_189,\n        _UnAssigned_190,\n        _UnAssigned_191,\n        _UnAssigned_192,\n        _UnAssigned_193,\n        _UnAssigned_194,\n        _UnAssigned_195,\n        _UnAssigned_196,\n        _UnAssigned_197,\n        _UnAssigned_198,\n        _UnAssigned_199,\n        _UnAssigned_200,\n        _UnAssigned_201,\n        _UnAssigned_202,\n        _UnAssigned_203,\n        _UnAssigned_204,\n        _UnAssigned_205,\n        _UnAssigned_206,\n        _UnAssigned_207,\n        _UnAssigned_208,\n        _UnAssigned_209,\n        _UnAssigned_210,\n        _UnAssigned_211,\n        _UnAssigned_212,\n        _UnAssigned_213,\n        _UnAssigned_214,\n        _UnAssigned_215,\n        _UnAssigned_216,\n        _UnAssigned_217,\n        _UnAssigned_218,\n        _UnAssigned_219,\n        _UnAssigned_220,\n        _UnAssigned_221,\n        _UnAssigned_222,\n        _UnAssigned_223,\n        _UnAssigned_224,\n        _UnAssigned_225,\n        _UnAssigned_226,\n        _UnAssigned_227,\n        _UnAssigned_228,\n        _UnAssigned_229,\n        _UnAssigned_230,\n        _UnAssigned_231,\n        _UnAssigned_232,\n        _UnAssigned_233,\n        _UnAssigned_234,\n        _UnAssigned_235,\n        _UnAssigned_236,\n        _UnAssigned_237,\n        _UnAssigned_238,\n        _UnAssigned_239,\n        _UnAssigned_240,\n        _UnAssigned_241,\n        _UnAssigned_242,\n        _UnAssigned_243,\n        _UnAssigned_244,\n        _UnAssigned_245,\n        _UnAssigned_246,\n        _UnAssigned_247,\n        _UnAssigned_248,\n        _UnAssigned_249,\n        _UnAssigned_250,\n        _UnAssigned_251,\n        _UnAssigned_252,\n        _UnAssigned_253,\n        _UnAssigned_254,\n        _UnAssigned_255\n    }\n    #endregion\n\n    #region Classes\n    public class TgaColorKey : ICloneable\n    {\n        byte a = 0;\n        byte r = 0;\n        byte g = 0;\n        byte b = 0;\n\n        public TgaColorKey()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaColorKey\"/> from ARGB bytes.\n        /// </summary>\n        /// <param name=\"A\">Alpha value.</param>\n        /// <param name=\"R\">Red value.</param>\n        /// <param name=\"G\">Green value.</param>\n        /// <param name=\"B\">Blue value.</param>\n        public TgaColorKey(byte A, byte R, byte G, byte B)\n        {\n            a = A;\n            r = R;\n            g = G;\n            b = B;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaColorKey\"/> from ARGB bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[4]).</param>\n        public TgaColorKey(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            Color color = Color.FromArgb(BitConverter.ToInt32(Bytes, 0));\n            a = color.A;\n            r = color.R;\n            g = color.G;\n            b = color.B;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaColorKey\"/> from <see cref=\"int\"/>.\n        /// </summary>\n        /// <param name=\"ARGB\">32bit ARGB integer color value.</param>\n        public TgaColorKey(int ARGB)\n        {\n            Color ColorARGB = Color.FromArgb(ARGB);\n            a = ColorARGB.A;\n            r = ColorARGB.R;\n            g = ColorARGB.G;\n            b = ColorARGB.B;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaColorKey\"/> from <see cref=\"Color\"/>.\n        /// </summary>\n        /// <param name=\"color\">GDI+ <see cref=\"Color\"/> value.</param>\n        public TgaColorKey(Color color)\n        {\n            a = color.A;\n            r = color.R;\n            g = color.G;\n            b = color.B;\n        }\n\n        /// <summary>\n        /// Gets or sets alpha color value.\n        /// </summary>\n        public byte A\n        {\n            get { return a; }\n            set { a = value; }\n        }\n\n        /// <summary>\n        /// Gets or sets red color value.\n        /// </summary>\n        public byte R\n        {\n            get { return r; }\n            set { r = value; }\n        }\n\n        /// <summary>\n        /// Gets or sets green color value.\n        /// </summary>\n        public byte G\n        {\n            get { return g; }\n            set { g = value; }\n        }\n\n        /// <summary>\n        /// Gets or sets blue color value.\n        /// </summary>\n        public byte B\n        {\n            get { return b; }\n            set { b = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 4;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaColorKey\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaColorKey\"/></returns>\n        public TgaColorKey Clone()\n        {\n            return new TgaColorKey(a, r, g, b);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaColorKey\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaColorKey\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaColorKey) ? Equals((TgaColorKey)obj) : false);\n        }\n\n        public bool Equals(TgaColorKey item)\n        {\n            return (a == item.a && r == item.r && g == item.g && b == item.b);\n        }\n\n        public static bool operator ==(TgaColorKey item1, TgaColorKey item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaColorKey item1, TgaColorKey item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            return ToInt().GetHashCode();\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaColorKey\"/> like string.\n        /// </summary>\n        /// <returns>String in ARGB format.</returns>\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, {4}={5}, {6}={7}\",\n                nameof(A), a, nameof(R), r, nameof(G), g, nameof(B), b);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaColorKey\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 4.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverter.GetBytes(ToInt());\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaColorKey\"/> like GDI+ <see cref=\"Color\"/>.\n        /// </summary>\n        /// <returns><see cref=\"Color\"/> value of <see cref=\"TgaColorKey\"/>.</returns>\n        public Color ToColor()\n        {\n            return Color.FromArgb(a, r, g, b);\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaColorKey\"/> like ARGB <see cref=\"int\"/>.\n        /// </summary>\n        /// <returns>ARGB <see cref=\"int\"/> value of <see cref=\"TgaColorKey\"/>.</returns>\n        public int ToInt()\n        {\n            return ToColor().ToArgb();\n        }\n    }\n\n    /// <summary>\n    /// This field (5 bytes) and its sub-fields describe the color map (if any) used for the image.\n    /// If the Color Map Type field is set to zero, indicating that no color map exists, then\n    /// these 5 bytes should be set to zero. These bytes always must be written to the file.\n    /// </summary>\n    public class TgaColorMapSpec : ICloneable\n    {\n        ushort firstEntryIndex = 0;\n        ushort colorMapLength = 0;\n        TgaColorMapEntrySize colorMapEntrySize = TgaColorMapEntrySize.Other;\n\n        /// <summary>\n        /// Make new <see cref=\"TgaColorMapSpec\"/>.\n        /// </summary>\n        public TgaColorMapSpec()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaColorMapSpec\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[5]).</param>\n        public TgaColorMapSpec(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            firstEntryIndex = BitConverter.ToUInt16(Bytes, 0);\n            colorMapLength = BitConverter.ToUInt16(Bytes, 2);\n            colorMapEntrySize = (TgaColorMapEntrySize)Bytes[4];\n        }\n\n        /// <summary>\n        /// Field 4.1 (2 bytes):\n        /// Index of the first color map entry. Index refers to the starting entry in loading\n        /// the color map.\n        /// <para>Example: If you would have 1024 entries in the entire color map but you only\n        /// need to store 72 of those entries, this field allows you to start in the middle of\n        /// the color-map (e.g., position 342).</para>\n        /// </summary>\n        public ushort FirstEntryIndex\n        {\n            get { return firstEntryIndex; }\n            set { firstEntryIndex = value; }\n        }\n\n        /// <summary>\n        /// Field 4.2 (2 bytes):\n        /// Total number of color map entries included.\n        /// </summary>\n        public ushort ColorMapLength\n        {\n            get { return colorMapLength; }\n            set { colorMapLength = value; }\n        }\n\n        /// <summary>\n        /// Field 4.3 (1 byte):\n        /// Establishes the number of bits per entry. Typically 15, 16, 24 or 32-bit values are used.\n        /// <para>When working with VDA or VDA/D cards it is preferred that you select 16 bits(5 bits\n        /// per primary with 1 bit to select interrupt control) and set the 16th bit to 0 so that the\n        /// interrupt bit is disabled. Even if this field is set to 15 bits(5 bits per primary) you\n        /// must still parse the color map data 16 bits at a time and ignore the 16th bit.</para>\n        /// <para>When working with a TARGA M8 card you would select 24 bits (8 bits per primary)\n        /// since the color map is defined as 256 entries of 24 bit color values.</para>\n        /// When working with a TrueVista card(ATVista or NuVista) you would select 24-bit(8 bits per\n        /// primary) or 32-bit(8 bits per primary including Alpha channel) depending on your\n        /// application’s use of look-up tables. It is suggested that when working with 16-bit and\n        /// 32-bit color images, you store them as True-Color images and do not use the color map \n        /// field to store look-up tables. Please refer to the TGA Extensions for fields better suited\n        /// to storing look-up table information.\n        /// </summary>\n        public TgaColorMapEntrySize ColorMapEntrySize\n        {\n            get { return colorMapEntrySize; }\n            set { colorMapEntrySize = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 5;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaColorMapSpec\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaColorMapSpec\"/></returns>\n        public TgaColorMapSpec Clone()\n        {\n            return new TgaColorMapSpec(ToBytes());\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaColorMapSpec\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaColorMapSpec\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaColorMapSpec) ? Equals((TgaColorMapSpec)obj) : false);\n        }\n\n        public bool Equals(TgaColorMapSpec item)\n        {\n            return (firstEntryIndex == item.firstEntryIndex &&\n                colorMapLength == item.colorMapLength &&\n                colorMapEntrySize == item.colorMapEntrySize);\n        }\n\n        public static bool operator ==(TgaColorMapSpec item1, TgaColorMapSpec item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaColorMapSpec item1, TgaColorMapSpec item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (firstEntryIndex << 16 | colorMapLength).GetHashCode() ^ colorMapEntrySize.GetHashCode();\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, {4}={5}\", nameof(FirstEntryIndex), FirstEntryIndex,\n                nameof(ColorMapLength), ColorMapLength, nameof(ColorMapEntrySize), ColorMapEntrySize);\n        }\n\n        /// <summary>\n        /// Convert ColorMapSpec to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 5.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(firstEntryIndex, colorMapLength, (byte)colorMapEntrySize);\n        }\n    }\n\n    public class TgaComment : ICloneable\n    {\n        const int StrNLen = 80; //80 ASCII chars + 1 '\\0' = 81 per SrtN!\n        string origString = String.Empty;\n        char blankSpaceChar = TgaString.DefaultBlankSpaceChar;\n\n        public TgaComment()\n        {\n        }\n\n        public TgaComment(string Str, char BlankSpaceChar = '\\0')\n        {\n            if (Str == null)\n                throw new ArgumentNullException(nameof(Str) + \" = null!\");\n\n            origString = Str;\n            blankSpaceChar = BlankSpaceChar;\n        }\n\n        public TgaComment(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            string s = Encoding.ASCII.GetString(Bytes, 0, StrNLen);\n            s += Encoding.ASCII.GetString(Bytes, 81, StrNLen);\n            s += Encoding.ASCII.GetString(Bytes, 162, StrNLen);\n            s += Encoding.ASCII.GetString(Bytes, 243, StrNLen);\n\n            switch (s[s.Length - 1])\n            {\n                case '\\0':\n                case ' ':\n                    blankSpaceChar = s[s.Length - 1];\n                    origString = s.TrimEnd(new char[] { s[s.Length - 1] });\n                    break;\n                default:\n                    origString = s;\n                    break;\n            }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 81 * 4;\n\n        public string OriginalString\n        {\n            get { return origString; }\n            set { origString = value; }\n        }\n\n        public char BlankSpaceChar\n        {\n            get { return blankSpaceChar; }\n            set { blankSpaceChar = value; }\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaComment\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaComment\"/></returns>\n        public TgaComment Clone()\n        {\n            return new TgaComment(origString, blankSpaceChar);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaComment\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaComment\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaComment) ? Equals((TgaComment)obj) : false);\n        }\n\n        public bool Equals(TgaComment item)\n        {\n            return (origString == item.origString && blankSpaceChar == item.blankSpaceChar);\n        }\n\n        public static bool operator ==(TgaComment item1, TgaComment item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaComment item1, TgaComment item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            return origString.GetHashCode() ^ blankSpaceChar.GetHashCode();\n        }\n\n        /// <summary>\n        /// Get ASCII-Like string with string-terminators, example: \"Line1 \\0\\0 Line2 \\0\\0\\0\".\n        /// </summary>\n        /// <returns>String with replaced string-terminators to \"\\0\".</returns>\n        public override string ToString()\n        {\n            return Encoding.ASCII.GetString(ToBytes()).Replace(\"\\0\", @\"\\0\");\n        }\n\n        /// <summary>\n        /// Get ASCII-Like string to first string-terminator, example:\n        /// \"Some string \\0 Some Data \\0\" - > \"Some string\".\n        /// </summary>\n        /// <returns>String to first string-terminator.</returns>\n        public string GetString()\n        {\n            String Str = Encoding.ASCII.GetString(ToBytes());\n            for (int i = 1; i < 4; i++)\n                Str = Str.Insert((StrNLen + 1) * i + i - 1, \"\\n\");\n            return Str.Replace(\"\\0\", String.Empty).TrimEnd(new char[] { '\\n' });\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaComment\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array, every byte is ASCII symbol.</returns>\n        public byte[] ToBytes()\n        {\n            return ToBytes(origString, blankSpaceChar);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaComment\"/> to byte array.\n        /// </summary>\n        /// <param name=\"Str\">Input string.</param>\n        /// <param name=\"BlankSpaceChar\">Char for filling blank space in string.</param>\n        /// <returns>Byte array, every byte is ASCII symbol.</returns>\n        public static byte[] ToBytes(string Str, char BlankSpaceChar = '\\0')\n        {\n            char[] C = new char[81 * 4];\n\n            for (int i = 0; i < C.Length; i++)\n            {\n                if ((i + 82) % 81 == 0)\n                    C[i] = TgaString.DefaultEndingChar;\n                else\n                {\n                    int Index = i - i / 81;\n                    C[i] = (Index < Str.Length ? Str[Index] : BlankSpaceChar);\n                }\n            }\n            return Encoding.ASCII.GetBytes(C);\n        }\n    }\n\n    public class TgaDateTime : ICloneable\n    {\n        ushort month = 0;\n        ushort day = 0;\n        ushort year = 0;\n        ushort hour = 0;\n        ushort minute = 0;\n        ushort second = 0;\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaDateTime\"/>.\n        /// </summary>\n        public TgaDateTime()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDateTime\"/> from <see cref=\"DateTime\"/>.\n        /// </summary>\n        /// <param name=\"DateAndTime\">Some <see cref=\"DateTime\"/> variable.</param>\n        public TgaDateTime(DateTime DateAndTime)\n        {\n            month = (ushort)DateAndTime.Month;\n            day = (ushort)DateAndTime.Day;\n            year = (ushort)DateAndTime.Year;\n            hour = (ushort)DateAndTime.Hour;\n            minute = (ushort)DateAndTime.Minute;\n            second = (ushort)DateAndTime.Second;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDateTime\"/> from ushort values.\n        /// </summary>\n        /// <param name=\"Month\">Month (1 - 12).</param>\n        /// <param name=\"Day\">Day (1 - 31).</param>\n        /// <param name=\"Year\">Year (4 digit, ie. 1989).</param>\n        /// <param name=\"Hour\">Hour (0 - 23).</param>\n        /// <param name=\"Minute\">Minute (0 - 59).</param>\n        /// <param name=\"Second\">Second (0 - 59).</param>\n        public TgaDateTime(ushort Month, ushort Day, ushort Year, ushort Hour, ushort Minute, ushort Second)\n        {\n            month = Month;\n            day = Day;\n            year = Year;\n            hour = Hour;\n            minute = Minute;\n            second = Second;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDateTime\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[12]).</param>\n        public TgaDateTime(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            else if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes) + \" must be equal \" + Size + \"!\");\n\n            month = BitConverter.ToUInt16(Bytes, 0);\n            day = BitConverter.ToUInt16(Bytes, 2);\n            year = BitConverter.ToUInt16(Bytes, 4);\n            hour = BitConverter.ToUInt16(Bytes, 6);\n            minute = BitConverter.ToUInt16(Bytes, 8);\n            second = BitConverter.ToUInt16(Bytes, 10);\n        }\n\n        /// <summary>\n        /// Gets or Sets month (1 - 12).\n        /// </summary>\n        public ushort Month\n        {\n            get { return month; }\n            set { month = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets day (1 - 31).\n        /// </summary>\n        public ushort Day\n        {\n            get { return day; }\n            set { day = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets year (4 digit, ie. 1989).\n        /// </summary>\n        public ushort Year\n        {\n            get { return year; }\n            set { year = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets hour (0 - 23).\n        /// </summary>\n        public ushort Hour\n        {\n            get { return hour; }\n            set { hour = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets minute (0 - 59).\n        /// </summary>\n        public ushort Minute\n        {\n            get { return minute; }\n            set { minute = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets second (0 - 59).\n        /// </summary>\n        public ushort Second\n        {\n            get { return second; }\n            set { second = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 12;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaDateTime\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaDateTime\"/></returns>\n        public TgaDateTime Clone()\n        {\n            return new TgaDateTime(month, day, year, hour, minute, second);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaDateTime\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaDateTime\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaDateTime) ? Equals((TgaDateTime)obj) : false);\n        }\n\n        public bool Equals(TgaDateTime item)\n        {\n            return (\n                month == item.month &&\n                day == item.day &&\n                year == item.year &&\n                hour == item.hour &&\n                minute == item.minute &&\n                second == item.second);\n        }\n\n        public static bool operator ==(TgaDateTime item1, TgaDateTime item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaDateTime item1, TgaDateTime item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + (month << 16 | hour).GetHashCode();\n                hash = hash * 23 + (day << 16 | minute).GetHashCode();\n                hash = hash * 23 + (year << 16 | second).GetHashCode();\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaDateTime\"/> like string.\n        /// </summary>\n        /// <returns>String in \"1990.01.23 1:02:03\" format.</returns>\n        public override string ToString()\n        {\n            return String.Format(\"{0:D4}.{1:D2}.{2:D2} {3}:{4:D2}:{5:D2}\", year, month, day, hour, minute, second);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaDateTime\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 12.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(month, day, year, hour, minute, second);\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaDateTime\"/> like <see cref=\"DateTime\"/>.\n        /// </summary>\n        /// <returns><see cref=\"DateTime\"/> value of <see cref=\"TgaDateTime\"/>.</returns>\n        public DateTime ToDateTime()\n        {\n            return new DateTime(year, month, day, hour, minute, second);\n        }\n    }\n\n    public class TgaDevEntry : ICloneable\n    {\n        // Directory\n        ushort fieldTag = 0;\n        uint fieldFileOffset = 0;\n        // Field\n        byte[] data = null;\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaDevEntry\"/>.\n        /// </summary>\n        public TgaDevEntry()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDevEntry\"/> from other <see cref=\"TgaDevEntry\"/>.\n        /// </summary>\n        /// <param name=\"Entry\">Some <see cref=\"TgaDevEntry\"/> variable.</param>\n        public TgaDevEntry(TgaDevEntry Entry)\n        {\n            if (Entry == null)\n                throw new ArgumentNullException();\n\n            fieldTag = Entry.fieldTag;\n            fieldFileOffset = Entry.fieldFileOffset;\n            data = BitConverterExt.ToBytes(Entry.data);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDevEntry\"/> from <see cref=\"Tag\"/>, <see cref=\"Offset\"/> and <see cref=\"FieldSize\"/>.\n        /// </summary>\n        /// <param name=\"Tag\">TAG ID (0 - 65535). See <see cref=\"Tag\"/>.</param>\n        /// <param name=\"Offset\">TAG file offset in bytes. See <see cref=\"Offset\"/>.</param>\n        /// <param name=\"Data\">This is DevEntry Field Data. See <see cref=\"Data\"/>.</param>\n        public TgaDevEntry(ushort Tag, uint Offset, byte[] Data = null)\n        {\n            fieldTag = Tag;\n            fieldFileOffset = Offset;\n            data = Data;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaDevEntry\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[6] or bigger, if <see cref=\"Data\"/> exist).</param>\n        public TgaDevEntry(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            else if (Bytes.Length < 6)\n                throw new ArgumentOutOfRangeException(nameof(Bytes) + \" must be >= 6!\");\n\n            fieldTag = BitConverter.ToUInt16(Bytes, 0);\n            fieldFileOffset = BitConverter.ToUInt32(Bytes, 2);\n\n            if (Bytes.Length > 6)\n                data = BitConverterExt.GetElements(Bytes, 6, Bytes.Length - 6);\n        }\n\n        /// <summary>\n        /// Each TAG is a value in the range of 0 to 65535. Values from 0 - 32767 are available for developer use,\n        /// while values from 32768 - 65535 are reserved for Truevision.\n        /// </summary>\n        public ushort Tag\n        {\n            get { return fieldTag; }\n            set { fieldTag = value; }\n        }\n\n        /// <summary>\n        /// This OFFSET is a number of bytes from the beginning of the file to the start of the field\n        /// referenced by the tag.\n        /// </summary>\n        public uint Offset\n        {\n            get { return fieldFileOffset; }\n            set { fieldFileOffset = value; }\n        }\n\n        /// <summary>\n        /// Field DATA.\n        /// Although the size and format of the actual Developer Area fields are totally up to the developer,\n        /// please define your formats to address future considerations you might have concerning your fields.\n        /// This means that if you anticipate changing a field, build flexibility into the format to make these\n        /// changes easy on other developers.Major changes to an existing TAG’s definition should never happen.\n        /// </summary>\n        public byte[] Data\n        {\n            get { return data; }\n            set { data = value; }\n        }\n\n        /// <summary>\n        /// The FIELD SIZE is a number of bytes in the field. Same like: <see cref=\"Data.Length\"/>,\n        /// if <see cref=\"Data\"/> is null, return -1.\n        /// </summary>\n        public int FieldSize\n        {\n            get\n            {\n                if (Data == null)\n                    return -1;\n\n                return Data.Length;\n            }\n        }\n\n        /// <summary>\n        /// Gets TGA <see cref=\"TgaDevEntry\"/> size in bytes (Always constant and equal 10!).\n        /// It is not <see cref=\"FieldSize\"/>! It is just size of entry sizeof(ushort + uint + uint).\n        /// </summary>\n        public const int Size = 10;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaDevEntry\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaDevEntry\"/></returns>\n        public TgaDevEntry Clone()\n        {\n            return new TgaDevEntry(this);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaDevEntry\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaDevEntry\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaDevEntry) ? Equals((TgaDevEntry)obj) : false);\n        }\n\n        public bool Equals(TgaDevEntry item)\n        {\n            return (fieldTag == item.fieldTag &&\n                fieldFileOffset == item.fieldFileOffset &&\n                BitConverterExt.IsArraysEqual(data, item.data));\n        }\n\n        public static bool operator ==(TgaDevEntry item1, TgaDevEntry item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaDevEntry item1, TgaDevEntry item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + fieldTag.GetHashCode();\n                hash = hash * 23 + fieldFileOffset.GetHashCode();\n\n                if (data != null)\n                    for (int i = 0; i < data.Length; i++)\n                        hash = hash * 23 + data[i].GetHashCode();\n\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaDevEntry\"/> like string.\n        /// </summary>\n        /// <returns>String in \"Tag={0}, Offset={1}, FieldSize={2}\" format.</returns>\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {1}={2}, {3}={4}\", nameof(Tag), fieldTag,\n                nameof(Offset), fieldFileOffset, nameof(FieldSize), FieldSize);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaDevEntry\"/> to byte array. (Not include <see cref=\"Data\"/>!).\n        /// </summary>\n        /// <returns>Byte array with length = 10.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(fieldTag, fieldFileOffset, (data == null ? 0 : data.Length));\n        }\n    } //Not full ToBytes()\n\n    public class TgaFraction : ICloneable\n    {\n        ushort numerator = 0;\n        ushort denominator = 0;\n\n        /// <summary>\n        /// Make <see cref=\"TgaFraction\"/> from <see cref=\"Numerator\"/> and <see cref=\"Denominator\"/>.\n        /// </summary>\n        /// <param name=\"Numerator\">Numerator value.</param>\n        /// <param name=\"Denominator\">Denominator value.</param>\n        public TgaFraction(ushort Numerator = 0, ushort Denominator = 0)\n        {\n            numerator = Numerator;\n            denominator = Denominator;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaFraction\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[4]).</param>\n        public TgaFraction(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            numerator = BitConverter.ToUInt16(Bytes, 0);\n            denominator = BitConverter.ToUInt16(Bytes, 2);\n        }\n\n        /// <summary>\n        /// Gets or sets numerator value.\n        /// </summary>\n        public ushort Numerator\n        {\n            get { return numerator; }\n            set { numerator = value; }\n        }\n\n        /// <summary>\n        /// Gets or sets denominator value.\n        /// </summary>\n        public ushort Denominator\n        {\n            get { return denominator; }\n            set { denominator = value; }\n        }\n\n        /// <summary>\n        /// Get aspect ratio = <see cref=\"Numerator\"/> / <see cref=\"Denominator\"/>.\n        /// </summary>\n        public float AspectRatio\n        {\n            get\n            {\n                if (numerator == denominator)\n                    return 1f;\n\n                return numerator / (float)denominator;\n            }\n        }\n\n        /// <summary>\n        /// Gets Empty <see cref=\"TgaFraction\"/>, all values are 0.\n        /// </summary>\n        public static readonly TgaFraction Empty = new TgaFraction();\n\n        /// <summary>\n        /// Gets One <see cref=\"TgaFraction\"/>, all values are 1 (ones, 1 / 1 = 1).\n        /// </summary>\n        public static readonly TgaFraction One = new TgaFraction(1, 1);\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 4;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaFraction\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaFraction\"/></returns>\n        public TgaFraction Clone()\n        {\n            return new TgaFraction(numerator, denominator);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaFraction\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaFraction\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaFraction) ? Equals((TgaFraction)obj) : false);\n        }\n\n        public bool Equals(TgaFraction item)\n        {\n            return (numerator == item.numerator && denominator == item.denominator);\n        }\n\n        public static bool operator ==(TgaFraction item1, TgaFraction item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaFraction item1, TgaFraction item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            return (numerator << 16 | denominator).GetHashCode();\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaFraction\"/> like string.\n        /// </summary>\n        /// <returns>String in \"Numerator=1, Denominator=2\" format.</returns>\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}\", nameof(Numerator), numerator,\n                nameof(Denominator), denominator);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaFraction\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 4.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(numerator, denominator);\n        }\n    }\n\n    /// <summary>\n    /// Contains image origin bits and alpha channel bits(or number of overlay bits)\n    /// </summary>\n    public class TgaImageDescriptor : ICloneable\n    {\n        TgaImgOrigin imageOrigin = 0; //bits 5-4\n        byte alphaChannelBits = 0; //bits 3-0\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaImageDescriptor\"/>.\n        /// </summary>\n        public TgaImageDescriptor()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaImageDescriptor\"/> from bytes.\n        /// </summary>\n        /// <param name=\"b\">ImageDescriptor byte with reserved 7-6 bits, bits 5-4 used for\n        /// <see cref=\"ImageOrigin\"/>, 3-0 used as alpha channel bits or number of overlay bits.</param>\n        public TgaImageDescriptor(byte b)\n        {\n            imageOrigin = (TgaImgOrigin)((b & 0x30) >> 4);\n            alphaChannelBits = (byte)(b & 0x0F);\n        }\n\n        /// <summary>\n        /// Gets or Sets Image Origin bits (select from enum only, don'n use 5-4 bits!).\n        /// </summary>\n        public TgaImgOrigin ImageOrigin\n        {\n            get { return imageOrigin; }\n            set { imageOrigin = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets alpha channel bits or number of overlay bits.\n        /// </summary>\n        public byte AlphaChannelBits\n        {\n            get { return alphaChannelBits; }\n            set { alphaChannelBits = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 1;\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImageDescriptor\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaImageDescriptor\"/>.</returns>\n        public TgaImageDescriptor Clone()\n        {\n            return new TgaImageDescriptor(ToByte());\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImageDescriptor\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaImageDescriptor\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaImageDescriptor) ? Equals((TgaImageDescriptor)obj) : false);\n        }\n\n        public bool Equals(TgaImageDescriptor item)\n        {\n            return (imageOrigin == item.imageOrigin && alphaChannelBits == item.alphaChannelBits);\n        }\n\n        public static bool operator ==(TgaImageDescriptor item1, TgaImageDescriptor item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaImageDescriptor item1, TgaImageDescriptor item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return ((int)ImageOrigin << 4 | alphaChannelBits).GetHashCode();\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, ImageDescriptor_AsByte={4}\", nameof(ImageOrigin),\n                imageOrigin, nameof(AlphaChannelBits), alphaChannelBits, ToByte());\n        }\n\n        /// <summary>\n        /// Gets ImageDescriptor byte.\n        /// </summary>\n        /// <returns>ImageDescriptor byte with reserved 7-6 bits, bits 5-4 used for imageOrigin,\n        /// 3-0 used as alpha channel bits or number of overlay bits.</returns>\n        public byte ToByte()\n        {\n            return (byte)(((int)imageOrigin << 4) | alphaChannelBits);\n        }\n    }\n\n    /// <summary>\n    /// Image Specification - Field 5 (10 bytes):\n    /// <para>This field and its sub-fields describe the image screen location, size and pixel depth.\n    /// These information is always written to the file.</para>\n    /// </summary>\n    public class TgaImageSpec : ICloneable\n    {\n        ushort x_Origin = 0;\n        ushort y_Origin = 0;\n        ushort imageWidth = 0;\n        ushort imageHeight = 0;\n        TgaPixelDepth pixelDepth = TgaPixelDepth.Other;\n        TgaImageDescriptor imageDescriptor = new TgaImageDescriptor();\n\n        public TgaImageSpec()\n        {\n        }\n\n        /// <summary>\n        /// Make ImageSpec from values.\n        /// </summary>\n        /// <param name=\"X_Origin\">These specify the absolute horizontal coordinate for the lower\n        /// left corner of the image as it is positioned on a display device having an origin at\n        /// the lower left of the screen(e.g., the TARGA series).</param>\n        /// <param name=\"Y_Origin\">These specify the absolute vertical coordinate for the lower\n        /// left corner of the image as it is positioned on a display device having an origin at\n        /// the lower left of the screen(e.g., the TARGA series).</param>\n        /// <param name=\"ImageWidth\">This field specifies the width of the image in pixels.</param>\n        /// <param name=\"ImageHeight\">This field specifies the height of the image in pixels.</param>\n        /// <param name=\"PixelDepth\">This field indicates the number of bits per pixel. This number\n        /// includes the Attribute or Alpha channel bits. Common values are 8, 16, 24 and 32 but\n        /// other pixel depths could be used.</param>\n        /// <param name=\"ImageDescriptor\">Contains image origin bits and alpha channel bits\n        /// (or number of overlay bits).</param>\n        public TgaImageSpec(ushort X_Origin, ushort Y_Origin, ushort ImageWidth, ushort ImageHeight,\n            TgaPixelDepth PixelDepth, TgaImageDescriptor ImageDescriptor)\n        {\n            x_Origin = X_Origin;\n            y_Origin = Y_Origin;\n            imageWidth = ImageWidth;\n            imageHeight = ImageHeight;\n            pixelDepth = PixelDepth;\n            imageDescriptor = ImageDescriptor;\n        }\n\n        /// <summary>\n        /// Make ImageSpec from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[10]).</param>\n        public TgaImageSpec(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            x_Origin = BitConverter.ToUInt16(Bytes, 0);\n            y_Origin = BitConverter.ToUInt16(Bytes, 2);\n            imageWidth = BitConverter.ToUInt16(Bytes, 4);\n            imageHeight = BitConverter.ToUInt16(Bytes, 6);\n            pixelDepth = (TgaPixelDepth)Bytes[8];\n            imageDescriptor = new TgaImageDescriptor(Bytes[9]);\n        }\n\n        /// <summary>\n        /// These specify the absolute horizontal coordinate for the lower left corner of the image\n        /// as it is positioned on a display device having an origin at the lower left of the\n        /// screen(e.g., the TARGA series).\n        /// </summary>\n        public ushort X_Origin\n        {\n            get { return x_Origin; }\n            set { x_Origin = value; }\n        }\n\n        /// <summary>\n        /// These specify the absolute vertical coordinate for the lower left corner of the image\n        /// as it is positioned on a display device having an origin at the lower left of the\n        /// screen(e.g., the TARGA series).\n        /// </summary>\n        public ushort Y_Origin\n        {\n            get { return y_Origin; }\n            set { y_Origin = value; }\n        }\n\n        /// <summary>\n        /// This field specifies the width of the image in pixels.\n        /// </summary>\n        public ushort ImageWidth\n        {\n            get { return imageWidth; }\n            set { imageWidth = value; }\n        }\n\n        /// <summary>\n        /// This field specifies the height of the image in pixels.\n        /// </summary>\n        public ushort ImageHeight\n        {\n            get { return imageHeight; }\n            set { imageHeight = value; }\n        }\n\n        /// <summary>\n        /// This field indicates the number of bits per pixel. This number includes the Attribute or\n        /// Alpha channel bits. Common values are 8, 16, 24 and 32 but other pixel depths could be used.\n        /// </summary>\n        public TgaPixelDepth PixelDepth\n        {\n            get { return pixelDepth; }\n            set { pixelDepth = value; }\n        }\n\n        /// <summary>\n        /// Contains image origin bits and alpha channel bits(or number of overlay bits).\n        /// </summary>\n        public TgaImageDescriptor ImageDescriptor\n        {\n            get { return imageDescriptor; }\n            set { imageDescriptor = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 10;\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImageDescriptor\"/>.\n        /// </summary>\n        /// <returns></returns>\n        public TgaImageSpec Clone()\n        {\n            return new TgaImageSpec(ToBytes());\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImageDescriptor\"/>.\n        /// </summary>\n        /// <returns></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaImageSpec) ? Equals((TgaImageSpec)obj) : false);\n        }\n\n        public bool Equals(TgaImageSpec item)\n        {\n            return (\n                x_Origin == item.x_Origin &&\n                y_Origin == item.y_Origin &&\n                imageWidth == item.imageWidth &&\n                imageHeight == item.imageHeight &&\n                pixelDepth == item.pixelDepth &&\n                imageDescriptor == item.imageDescriptor);\n        }\n\n        public static bool operator ==(TgaImageSpec item1, TgaImageSpec item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaImageSpec item1, TgaImageSpec item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + x_Origin.GetHashCode();\n                hash = hash * 23 + y_Origin.GetHashCode();\n                hash = hash * 23 + imageWidth.GetHashCode();\n                hash = hash * 23 + imageHeight.GetHashCode();\n                hash = hash * 23 + pixelDepth.GetHashCode();\n\n                if (imageDescriptor != null)\n                    hash = hash * 23 + imageDescriptor.GetHashCode();\n\n                return hash;\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, {4}={5}, {6}={7}, {8}={9}, {10}={11}\",\n                nameof(X_Origin), x_Origin,\n                nameof(Y_Origin), y_Origin,\n                nameof(ImageWidth), imageWidth,\n                nameof(ImageHeight), imageHeight,\n                nameof(PixelDepth), pixelDepth,\n                nameof(ImageDescriptor), imageDescriptor);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaImageSpec\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 10.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(x_Origin, y_Origin, imageWidth, imageHeight,\n                (byte)pixelDepth, (imageDescriptor == null ? byte.MinValue : imageDescriptor.ToByte()));\n        }\n    }\n\n    /// <summary>\n    /// Postage Stamp Image (MaxSize 64x64, uncompressed, PixelDepth like in full image).\n    /// </summary>\n    public class TgaPostageStampImage : ICloneable\n    {\n        byte width = 0;\n        byte height = 0;\n        byte[] data = null;\n\n        public TgaPostageStampImage()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaPostageStampImage\"/> from bytes array.\n        /// </summary>\n        /// <param name=\"Bytes\">Bytes array, first 2 bytes are <see cref=\"Width\"/> and <see cref=\"Height\"/>,\n        /// next bytes - image data.</param>\n        public TgaPostageStampImage(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length < 2)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be >= \" + 2 + \"!\");\n\n            width = Bytes[0];\n            height = Bytes[1];\n\n            if (Bytes.Length > 2)\n                data = BitConverterExt.GetElements(Bytes, 2, Bytes.Length - 2);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaPostageStampImage\"/> from bytes and size.\n        /// </summary>\n        /// <param name=\"Width\">Image Width.</param>\n        /// <param name=\"Height\">Image Height.</param>\n        /// <param name=\"Bytes\">Postage Stamp Image Data.</param>\n        public TgaPostageStampImage(byte Width, byte Height, byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n\n            width = Width;\n            height = Height;\n            data = Bytes;\n        }\n\n        /// <summary>\n        /// Postage Stamp Image Data\n        /// </summary>\n        public byte[] Data\n        {\n            get { return data; }\n            set { data = value; }\n        }\n\n        /// <summary>\n        /// Postage Stamp Image Width (maximum = 64).\n        /// </summary>\n        public byte Width\n        {\n            get { return width; }\n            set { width = value; }\n        }\n\n        /// <summary>\n        /// Postage Stamp Image Height (maximum = 64).\n        /// </summary>\n        public byte Height\n        {\n            get { return height; }\n            set { height = value; }\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaPostageStampImage\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaPostageStampImage\"/>.</returns>\n        public TgaPostageStampImage Clone()\n        {\n            return new TgaPostageStampImage(width, height, BitConverterExt.ToBytes(data));\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaPostageStampImage\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaPostageStampImage\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaPostageStampImage) ? Equals((TgaPostageStampImage)obj) : false);\n        }\n\n        public bool Equals(TgaPostageStampImage item)\n        {\n            return width == item.width && height == item.height && BitConverterExt.IsArraysEqual(data, item.data);\n        }\n\n        public static bool operator ==(TgaPostageStampImage item1, TgaPostageStampImage item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaPostageStampImage item1, TgaPostageStampImage item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 27;\n                hash = (13 * hash) + width.GetHashCode();\n                hash = (13 * hash) + height.GetHashCode();\n                if (data != null)\n                    for (int i = 0; i < data.Length; i++)\n                        hash = (13 * hash) + data[i].GetHashCode();\n                return hash;\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, DataLength={4}\",\n                nameof(Width), width, nameof(Height), height, (data == null ? -1 : data.Length));\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaPostageStampImage\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(width, height, data);\n        }\n    }\n\n    public class TgaSoftVersion : ICloneable\n    {\n        ushort versionNumber = 0;\n        char versionLetter = ' ';\n\n        /// <summary>\n        /// Gets Empty <see cref=\"TgaSoftVersion\"/>, <see cref=\"VersionLetter\"/> = ' ' (space).\n        /// </summary>\n        public TgaSoftVersion()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaSoftVersion\"/> from string.\n        /// </summary>\n        /// <param name=\"Str\">Input string, example: \"123d\".</param>\n        public TgaSoftVersion(string Str)\n        {\n            if (Str == null)\n                throw new ArgumentNullException();\n            if (Str.Length < 3 || Str.Length > 4)\n                throw new ArgumentOutOfRangeException(nameof(Str.Length) + \" must be equal 3 or 4!\");\n\n            bool Res = ushort.TryParse(Str.Substring(0, 3), out versionNumber);\n            if (Res && Str.Length == 4)\n                versionLetter = Str[3];\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaSoftVersion\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Bytes array (byte[3]).</param>\n        public TgaSoftVersion(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            versionNumber = BitConverter.ToUInt16(Bytes, 0);\n            versionLetter = Encoding.ASCII.GetString(Bytes, 2, 1)[0];\n        }\n\n        public TgaSoftVersion(ushort VersionNumber, char VersionLetter = ' ')\n        {\n            versionNumber = VersionNumber;\n            versionLetter = VersionLetter;\n        }\n\n        public ushort VersionNumber\n        {\n            get { return versionNumber; }\n            set { versionNumber = value; }\n        }\n\n        public char VersionLetter\n        {\n            get { return versionLetter; }\n            set { versionLetter = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 3;\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaSoftVersion\"/>.\n        /// </summary>\n        /// <returns></returns>\n        public TgaSoftVersion Clone()\n        {\n            return new TgaSoftVersion(versionNumber, versionLetter);\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaSoftVersion\"/>.\n        /// </summary>\n        /// <returns></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaSoftVersion) ? Equals((TgaSoftVersion)obj) : false);\n        }\n\n        public bool Equals(TgaSoftVersion item)\n        {\n            return (versionNumber == item.versionNumber && versionLetter == item.versionLetter);\n        }\n\n        public static bool operator ==(TgaSoftVersion item1, TgaSoftVersion item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaSoftVersion item1, TgaSoftVersion item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            return versionNumber.GetHashCode() ^ versionLetter.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return (versionNumber.ToString(\"000\") + versionLetter).TrimEnd(new char[] { ' ', '\\0' });\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaSoftVersion\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array, <see cref=\"VersionNumber\"/> (2 bytes) and\n        /// <see cref=\"VersionLetter\"/> (ASCII symbol).</returns>\n        public byte[] ToBytes()\n        {\n            return ToBytes(versionNumber, versionLetter);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaSoftVersion\"/> to byte array.\n        /// </summary>\n        /// <param name=\"VersionNumber\">Set 123 for 1.23 version.</param>\n        /// <param name=\"VersionLetter\">Version letter, example: for 'a' - \"1.23a\".</param>\n        /// <returns>Byte array, <see cref=\"VersionNumber\"/> (2 bytes) and <see cref=\"VersionLetter\"/> (ASCII symbol).</returns>\n        public static byte[] ToBytes(ushort VersionNumber, char VersionLetter = ' ')\n        {\n            return BitConverterExt.ToBytes(VersionNumber, Encoding.ASCII.GetBytes(VersionLetter.ToString()));\n        }\n    }\n\n    /// <summary>\n    /// Use it for working with ASCII strings in TGA files.\n    /// </summary>\n    public class TgaString : ICloneable\n    {\n        public const string XFileSignatuteConst = \"TRUEVISION-XFILE\";\n        public const string DotSymbolConst = \".\";\n\n        string origString = String.Empty;\n        int length = 0;\n        char blankSpaceChar = DefaultBlankSpaceChar;\n        bool useEnding = false;\n\n        public TgaString(bool UseEnding = false)\n        {\n            useEnding = UseEnding;\n        }\n\n        public TgaString(byte[] Bytes, bool UseEnding = false)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n\n            length = Bytes.Length;\n            useEnding = UseEnding;\n            string s = Encoding.ASCII.GetString(Bytes, 0, Bytes.Length - (useEnding ? 1 : 0));\n\n            if (s.Length > 0)\n                switch (s[s.Length - 1])\n                {\n                    case '\\0':\n                    case ' ':\n                        blankSpaceChar = s[s.Length - 1];\n                        origString = s.TrimEnd(new char[] { s[s.Length - 1] });\n                        break;\n                    default:\n                        origString = s;\n                        break;\n                }\n        }\n\n        public TgaString(int Length, bool UseEnding = false)\n        {\n            length = Length;\n            useEnding = UseEnding;\n        }\n\n        public TgaString(string Str, int Length, bool UseEnding = false, char BlankSpaceChar = '\\0')\n        {\n            if (Str == null)\n                throw new ArgumentNullException(nameof(Str) + \" = null!\");\n\n            origString = Str;\n            length = Length;\n            blankSpaceChar = BlankSpaceChar;\n            useEnding = UseEnding;\n        }\n\n        public string OriginalString\n        {\n            get { return origString; }\n            set { origString = value; }\n        }\n\n        public int Length\n        {\n            get { return length; }\n            set { length = value; }\n        }\n\n        public char BlankSpaceChar\n        {\n            get { return blankSpaceChar; }\n            set { blankSpaceChar = value; }\n        }\n\n        public bool UseEndingChar\n        {\n            get { return useEnding; }\n            set { useEnding = value; }\n        }\n\n        /// <summary>\n        /// Gets ending char, default '\\0'.\n        /// </summary>\n        public static readonly char DefaultEndingChar = '\\0';\n\n        /// <summary>\n        /// Gets blank space char, value = '\\0'.\n        /// </summary>\n        public static readonly char DefaultBlankSpaceChar = '\\0';\n\n        /// <summary>\n        /// Gets Empty <see cref=\"TgaString\"/>.\n        /// </summary>\n        public static readonly TgaString Empty = new TgaString();\n\n        /// <summary>\n        /// Gets <see cref=\"TgaString\"/> with <see cref=\"DefaultEndingChar\"/> = '\\0' and <see cref=\"UseEndingChar\"/> = true.\n        /// </summary>\n        public static readonly TgaString ZeroTerminator = new TgaString(true);\n\n        /// <summary>\n        /// Gets \".\" <see cref=\"TgaString\"/> with dot (period) symbol.\n        /// </summary>\n        public static readonly TgaString DotSymbol = new TgaString(DotSymbolConst, DotSymbolConst.Length);\n\n        /// <summary>\n        /// Gets \"TRUEVISION-XFILE\" <see cref=\"TgaString\"/> (TGA File Format Version 2.0 signatute).\n        /// </summary>\n        public static readonly TgaString XFileSignatute = new TgaString(XFileSignatuteConst, XFileSignatuteConst.Length);\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaString\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaString\"/></returns>\n        public TgaString Clone()\n        {\n            return new TgaString(origString, length, useEnding, blankSpaceChar);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaString\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaString\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaString) ? Equals((TgaString)obj) : false);\n        }\n\n        public bool Equals(TgaString item)\n        {\n            return (\n                origString == item.origString &&\n                length == item.length &&\n                blankSpaceChar == item.blankSpaceChar &&\n                useEnding == item.useEnding);\n        }\n\n        public static bool operator ==(TgaString item1, TgaString item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaString item1, TgaString item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public static TgaString operator +(TgaString item1, TgaString item2)\n        {\n            if (ReferenceEquals(item1, null) || ReferenceEquals(item2, null))\n                throw new ArgumentNullException();\n\n            return new TgaString(BitConverterExt.ToBytes(item1.ToBytes(), item2.ToBytes()));\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + origString.GetHashCode();\n                hash = hash * 23 + length.GetHashCode();\n                hash = hash * 23 + blankSpaceChar.GetHashCode();\n                hash = hash * 23 + useEnding.GetHashCode();\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Get ASCII-Like string with string-terminators, example: \"Some string\\0\\0\\0\\0\\0\".\n        /// </summary>\n        /// <returns>String with replaced string-terminators to \"\\0\".</returns>\n        public override string ToString()\n        {\n            return Encoding.ASCII.GetString(ToBytes()).Replace(\"\\0\", @\"\\0\");\n        }\n\n        /// <summary>\n        /// Get ASCII-Like string to first string-terminator, example:\n        /// \"Some string \\0 Some Data \\0\" - > \"Some string\".\n        /// </summary>\n        /// <returns>String to first string-terminator.</returns>\n        public string GetString()\n        {\n            String Str = Encoding.ASCII.GetString(ToBytes());\n            int EndIndex = Str.IndexOf('\\0');\n            if (EndIndex != -1)\n                Str = Str.Substring(0, EndIndex);\n            return Str;\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaString\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array, every byte is ASCII symbol.</returns>\n        public byte[] ToBytes()\n        {\n            return ToBytes(origString, length, useEnding, blankSpaceChar);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaString\"/> to byte array.\n        /// </summary>\n        /// <param name=\"str\">Input string.</param>\n        /// <param name=\"Length\">Length of output ASCII string with Ending char (if used).</param>\n        /// <param name=\"UseEnding\">Add <see cref=\"EndingChr\"/> to string or not?</param>\n        /// <param name=\"BlankSpaceChar\">Char for filling blank space in string. If this char is '-' (only for example!),\n        /// for string \"ABC\" with <see cref=\"Length\"/> = 7, with <see cref=\"UseEnding\"/> = true,\n        /// <see cref=\"DefaultEndingChar\"/> is '\\0', result string is \"ABC---\\0\".</param>\n        /// <returns>Byte array, every byte is ASCII symbol.</returns>\n        public static byte[] ToBytes(string str, int Length, bool UseEnding = true, char BlankSpaceChar = '\\0')\n        {\n            char[] C = new char[Math.Max(Length, (UseEnding ? 1 : 0))];\n\n            for (int i = 0; i < C.Length; i++)\n                C[i] = (i < str.Length ? str[i] : BlankSpaceChar);\n\n            if (UseEnding)\n                C[C.Length - 1] = DefaultEndingChar;\n\n            return Encoding.ASCII.GetBytes(C);\n        }\n    }\n\n    public class TgaTime : ICloneable\n    {\n        ushort hours = 0;\n        ushort minutes = 0;\n        ushort seconds = 0;\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaTime\"/>.\n        /// </summary>\n        public TgaTime()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaTime\"/> from <see cref=\"TimeSpan\"/>.\n        /// </summary>\n        /// <param name=\"Time\">Some <see cref=\"TimeSpan\"/> variable.</param>\n        public TgaTime(TimeSpan Time)\n        {\n            hours = (ushort)Time.TotalHours;\n            minutes = (ushort)Time.Minutes;\n            seconds = (ushort)Time.Seconds;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaTime\"/> from ushort values.\n        /// </summary>\n        /// <param name=\"Hours\">Hour (0 - 65535).</param>\n        /// <param name=\"Minutes\">Minute (0 - 59).</param>\n        /// <param name=\"Seconds\">Second (0 - 59).</param>\n        public TgaTime(ushort Hours, ushort Minutes, ushort Seconds)\n        {\n            hours = Hours;\n            minutes = Minutes;\n            seconds = Seconds;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaTime\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Array of bytes(byte[6]).</param>\n        public TgaTime(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            else if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes) + \" must be equal \" + Size + \"!\");\n\n            hours = BitConverter.ToUInt16(Bytes, 0);\n            minutes = BitConverter.ToUInt16(Bytes, 2);\n            seconds = BitConverter.ToUInt16(Bytes, 4);\n        }\n\n        /// <summary>\n        /// Gets or Sets hour (0 - 65535).\n        /// </summary>\n        public ushort Hours\n        {\n            get { return hours; }\n            set { hours = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets minute (0 - 59).\n        /// </summary>\n        public ushort Minutes\n        {\n            get { return minutes; }\n            set { minutes = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets second (0 - 59).\n        /// </summary>\n        public ushort Seconds\n        {\n            get { return seconds; }\n            set { seconds = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Field size in bytes.\n        /// </summary>\n        public const int Size = 6;\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaTime\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaTime\"/></returns>\n        public TgaTime Clone()\n        {\n            return new TgaTime(hours, minutes, seconds);\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TgaTime\"/>.\n        /// </summary>\n        /// <returns>Copy of <see cref=\"TgaTime\"/></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaTime) ? Equals((TgaTime)obj) : false);\n        }\n\n        public bool Equals(TgaTime item)\n        {\n            return (hours == item.hours && minutes == item.minutes && seconds == item.seconds);\n        }\n\n        public static bool operator ==(TgaTime item1, TgaTime item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaTime item1, TgaTime item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + hours.GetHashCode();\n                hash = hash * 23 + (minutes << 16 | seconds).GetHashCode();\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaTime\"/> like string.\n        /// </summary>\n        /// <returns>String in \"H:M:S\" format.</returns>\n        public override string ToString()\n        {\n            return String.Format(\"{0}:{1}:{2}\", hours, minutes, seconds);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaTime\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with length = 6.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(hours, minutes, seconds);\n        }\n\n        /// <summary>\n        /// Gets <see cref=\"TgaTime\"/> like <see cref=\"TimeSpan\"/>.\n        /// </summary>\n        /// <returns><see cref=\"TimeSpan\"/> value of <see cref=\"TgaTime\"/>.</returns>\n        public TimeSpan ToTimeSpan()\n        {\n            return new TimeSpan(hours, minutes, seconds);\n        }\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////////////////////\n\n    /// <summary>\n    /// File Header Area (18 bytes)\n    /// </summary>\n    public class TgaHeader : ICloneable\n    {\n        byte idLength = 0;\n        TgaColorMapType colorMapType = TgaColorMapType.NoColorMap;\n        TgaImageType imageType = TgaImageType.NoImageData;\n        TgaColorMapSpec colorMapSpec = new TgaColorMapSpec();\n        TgaImageSpec imageSpec = new TgaImageSpec();\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaHeader\"/>.\n        /// </summary>\n        public TgaHeader()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaHeader\"/> from bytes.\n        /// </summary>\n        /// <param name=\"Bytes\">Bytes array (byte[18]).</param>\n        public TgaHeader(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            idLength = Bytes[0];\n            colorMapType = (TgaColorMapType)Bytes[1];\n            imageType = (TgaImageType)Bytes[2];\n            colorMapSpec = new TgaColorMapSpec(BitConverterExt.GetElements(Bytes, 3, TgaColorMapSpec.Size));\n            imageSpec = new TgaImageSpec(BitConverterExt.GetElements(Bytes, 8, TgaImageSpec.Size));\n        }\n\n        /// <summary>\n        /// ID Length - Field 1 (1 byte):\n        /// This field identifies the number of bytes contained in the <see cref=\"ImageID\"/> Field.\n        /// The maximum number of characters is 255. A value of zero indicates that no Image ID\n        /// field is included with the image.\n        /// </summary>\n        public byte IDLength\n        {\n            get { return idLength; }\n            set { idLength = value; }\n        }\n\n        /// <summary>\n        /// Color Map Type - Field 2 (1 byte):\n        /// This field indicates the type of color map (if any) included with the image.\n        /// There are currently 2 defined values for this field:\n        /// <para>0 - indicates that no color-map data is included with this image;</para>\n        /// <para>1 - indicates that a color-map is included with this image.</para>\n        /// </summary>\n        public TgaColorMapType ColorMapType\n        {\n            get { return colorMapType; }\n            set { colorMapType = value; }\n        }\n\n        /// <summary>\n        /// Image Type - Field 3 (1 byte):\n        /// <para>The TGA File Format can be used to store Pseudo-Color, True-Color and Direct-Color images\n        /// of various pixel depths.</para>\n        /// </summary>\n        public TgaImageType ImageType\n        {\n            get { return imageType; }\n            set { imageType = value; }\n        }\n\n        /// <summary>\n        /// Color Map Specification - Field 4 (5 bytes):\n        /// <para>This field and its sub-fields describe the color map (if any) used for the image.\n        /// If the Color Map Type field is set to zero, indicating that no color map exists, then\n        /// these 5 bytes should be set to zero. These bytes always must be written to the file.</para>\n        /// </summary>\n        public TgaColorMapSpec ColorMapSpec\n        {\n            get { return colorMapSpec; }\n            set { colorMapSpec = value; }\n        }\n\n        /// <summary>\n        /// Image Specification - Field 5 (10 bytes):\n        /// <para>This field and its sub-fields describe the image screen location, size and pixel depth.\n        /// These information is always written to the file.</para>\n        /// </summary>\n        public TgaImageSpec ImageSpec\n        {\n            get { return imageSpec; }\n            set { imageSpec = value; }\n        }\n\n        /// <summary>\n        /// Gets TGA Header Section size in bytes.\n        /// </summary>\n        public const int Size = 18;\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaHeader\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaHeader\"/>.</returns>\n        public TgaHeader Clone()\n        {\n            return new TgaHeader(ToBytes());\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaHeader\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaHeader\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaHeader) ? Equals((TgaHeader)obj) : false);\n        }\n\n        public bool Equals(TgaHeader item)\n        {\n            return (idLength == item.idLength &&\n                colorMapType == item.colorMapType &&\n                imageType == item.imageType &&\n                colorMapSpec == item.colorMapSpec &&\n                imageSpec == item.imageSpec);\n        }\n\n        public static bool operator ==(TgaHeader item1, TgaHeader item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaHeader item1, TgaHeader item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + (idLength << 24 | (byte)colorMapType << 8 | (byte)imageType).GetHashCode();\n\n                if (colorMapSpec != null)\n                    hash = hash * 23 + colorMapSpec.GetHashCode();\n\n                if (imageSpec != null)\n                    hash = hash * 23 + imageSpec.GetHashCode();\n\n                return hash;\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, {4}={5}, {6}={7}, {8}={9}\",\n                nameof(IDLength), idLength,\n                nameof(ColorMapType), colorMapType,\n                nameof(ImageType), imageType,\n                nameof(ColorMapSpec), colorMapSpec,\n                nameof(ImageSpec), imageSpec);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaHeader\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with size equal <see cref=\"Size\"/>.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(idLength, (byte)colorMapType, (byte)imageType,\n                (colorMapSpec == null ? new byte[TgaColorMapSpec.Size] : colorMapSpec.ToBytes()),\n                (imageSpec == null ? new byte[TgaImageSpec.Size] : imageSpec.ToBytes()));\n        }\n    }\n\n    /// <summary>\n    /// Image Or ColorMap Area\n    /// </summary>\n    public class TgaImgOrColMap : ICloneable\n    {\n        TgaString imageID = null;\n        byte[] colorMapData = null;\n        byte[] imageData = null;\n\n        /// <summary>\n        /// Make empty <see cref=\"TgaImgOrColMap\"/>.\n        /// </summary>\n        public TgaImgOrColMap()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaImgOrColMap\"/> from arrays.\n        /// </summary>\n        /// <param name=\"ImageID\">This optional field contains identifying information about the image.\n        /// The maximum length for this field is 255 bytes. Refer to <see cref=\"TgaHeader.IDLength\"/>\n        /// for the length of this field. If field 1 is set to Zero indicating that no Image ID exists\n        /// then these bytes are not written to the file.</param>\n        /// <param name=\"ColorMapData\">Color Map Data, see <see cref=\"ColorMapData\"/> description.</param>\n        /// <param name=\"ImageData\">Image Data, see <see cref=\"ImageData\"/> description.</param>\n        public TgaImgOrColMap(TgaString ImageID, byte[] ColorMapData, byte[] ImageData)\n        {\n            imageID = ImageID;\n            colorMapData = ColorMapData;\n            imageData = ImageData;\n        }\n\n        /// <summary>\n        /// Image ID - Field 6 (variable):\n        /// <para>This optional field contains identifying information about the image. The maximum length\n        /// for this field is 255 bytes. Refer to <see cref=\"TgaHeader.IDLength\"/> for the length of this\n        /// field. If field 1 is set to Zero indicating that no Image ID exists then these bytes are not\n        /// written to the file. Can have text inside (ASCII).</para>\n        /// </summary>\n        public TgaString ImageID\n        {\n            get { return imageID; }\n            set { imageID = value; }\n        }\n\n        /// <summary>\n        /// Color Map Data - Field 7 (variable):\n        /// <para>If the Color Map Type(field 2) field is set to zero indicating that no Color-Map\n        /// exists then this field will not be present (i.e., no bytes written to the file).</para>\n        /// <para>This variable-length field contains the actual color map information (LUT data).\n        /// Field 4.3 specifies the width in bits of each color map entry while Field 4.2 specifies\n        /// the number of color map entries in this field. These two fields together are used to\n        /// determine the number of bytes contained in field 7.</para>\n        /// <para>Each color map entry is stored using an integral number of bytes.The RGB specification\n        /// for each color map entry is stored in successive bit-fields in the multi-byte entries.\n        /// Each color bit-field is assumed to be MIN(Field4.3/3, 8) bits in length. If Field 4.3\n        /// contains 24, then each color specification is 8 bits in length; if Field 4.3 contains 32,\n        /// then each color specification is also 8 bits (32/3 gives 10, but 8 is smaller).\n        /// Unused bit(s) in the multi-byte entries are assumed to specify attribute bits. The\n        /// attribute bit field is often called the Alpha Channel, Overlay Bit(s) or Interrupt Bit(s).</para>\n        /// For the TARGA M-8, ATVista and NuVista, the number of bits in a color map specification is\n        /// 24 (or 32). The red, green, and blue components are each represented by one byte.\n        /// </summary>\n        public byte[] ColorMapData\n        {\n            get { return colorMapData; }\n            set { colorMapData = value; }\n        }\n\n        /// <summary>\n        /// Image Data - Field 8 (variable):\n        /// <para>This field contains (Width)x(Height) pixels. Each pixel specifies image data in one\n        /// of the following formats:</para>\n        /// <para>a single color-map index for Pseudo-Color;\n        /// Attribute, Red, Green and Blue ordered data for True-Color;\n        /// and independent color-map indices for Direct-Color.</para>\n        /// <para>The values for Width and Height are specified in Fields 5.3 and 5.4 respectively.\n        /// The number of attribute and color-definition bits for each pixel are defined in Fields 5.6\n        /// and 5.5, respectively.Each pixel is stored as an integral number of bytes.</para>\n        /// </summary>\n        public byte[] ImageData\n        {\n            get { return imageData; }\n            set { imageData = value; }\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImgOrColMap\"/>.\n        /// </summary>\n        /// <returns>Full independed copy of <see cref=\"TgaImgOrColMap\"/>.</returns>\n        public TgaImgOrColMap Clone()\n        {\n            return new TgaImgOrColMap(\n                (imageID == null ? null : imageID.Clone()),\n                (colorMapData == null ? null : (byte[])colorMapData.Clone()),\n                (imageData == null ? null : (byte[])imageData.Clone()));\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaImgOrColMap\"/>.\n        /// </summary>\n        /// <returns>Full independed copy of <see cref=\"TgaImgOrColMap\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaImgOrColMap) ? Equals((TgaImgOrColMap)obj) : false);\n        }\n\n        public bool Equals(TgaImgOrColMap item)\n        {\n            return imageID == item.imageID &&\n                BitConverterExt.IsArraysEqual(colorMapData, item.colorMapData) &&\n                BitConverterExt.IsArraysEqual(imageData, item.imageData);\n        }\n\n        public static bool operator ==(TgaImgOrColMap item1, TgaImgOrColMap item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaImgOrColMap item1, TgaImgOrColMap item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 27;\n\n                if (imageID != null)\n                    hash = (13 * hash) + imageID.GetHashCode();\n                if (colorMapData != null)\n                    for (int i = 0; i < colorMapData.Length; i++)\n                        hash = (13 * hash) + colorMapData[i].GetHashCode();\n                if (imageData != null)\n                    for (int i = 0; i < imageData.Length; i++)\n                        hash = (13 * hash) + imageData[i].GetHashCode();\n\n                return hash;\n            }\n        }\n    } //No ToBytes()\n\n    /// <summary>\n    /// Developer Area\n    /// </summary> //?\n    public class TgaDevArea : ICloneable\n    {\n        List<TgaDevEntry> entries = new List<TgaDevEntry>();\n\n        public TgaDevArea()\n        {\n        }\n\n        public TgaDevArea(List<TgaDevEntry> Entries)\n        {\n            if (Entries == null)\n                throw new ArgumentNullException(nameof(Entries) + \" = null!\");\n\n            entries = Entries;\n        }\n\n        /// <summary>\n        /// Developer Data - Field 9 (variable):\n        /// </summary>\n        public List<TgaDevEntry> Entries\n        {\n            get { return entries; }\n            set { entries = value; }\n        }\n\n        public int Count\n        {\n            get { return entries.Count; }\n        }\n\n        public TgaDevEntry this[int index]\n        {\n            get { return entries[index]; }\n            set { entries[index] = value; }\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaDevArea\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaDevArea\"/>.</returns>\n        public TgaDevArea Clone()\n        {\n            if (entries == null)\n                return new TgaDevArea(null);\n\n            List<TgaDevEntry> L = new List<TgaDevEntry>();\n            for (int i = 0; i < entries.Count; i++)\n                L.Add(entries[i].Clone());\n\n            return new TgaDevArea(L);\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaDevArea\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaDevArea\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaDevArea) ? Equals((TgaDevArea)obj) : false);\n        }\n\n        public bool Equals(TgaDevArea item)\n        {\n            return BitConverterExt.IsListsEqual(entries, item.entries);\n        }\n\n        public static bool operator ==(TgaDevArea item1, TgaDevArea item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaDevArea item1, TgaDevArea item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 27;\n                if (entries != null)\n                    for (int i = 0; i < entries.Count; i++)\n                        hash = (13 * hash) + entries[i].GetHashCode();\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaDevArea\"/> (without Fields Data, only Directory!) to byte array.\n        /// </summary>\n        /// <returns>Byte array, Len = (NUMBER_OF_TAGS_IN_THE_DIRECTORY * 10) + 2 bytes in size.\n        /// The \"+ 2\" includes the 2 bytes for the number of tags in the directory.</returns>\n        public byte[] ToBytes()\n        {\n            if (entries == null)\n                throw new Exception(nameof(Entries) + \" = null!\");\n\n            ushort NumberOfEntries = (ushort)Math.Min(ushort.MaxValue, entries.Count);\n            List<byte> DevDir = new List<byte>(BitConverter.GetBytes(NumberOfEntries));\n\n            for (int i = 0; i < entries.Count; i++)\n            {\n                DevDir.AddRange(BitConverter.GetBytes(entries[i].Tag));\n                DevDir.AddRange(BitConverter.GetBytes(entries[i].Offset));\n                DevDir.AddRange(BitConverter.GetBytes(entries[i].FieldSize));\n            }\n\n            return DevDir.ToArray();\n        }\n    } //Not full ToBytes()\n\n    /// <summary>\n    /// Extension Area\n    /// </summary>\n    public class TgaExtArea : ICloneable\n    {\n        public const int MinSize = 495; //bytes\n\n        ushort extensionSize = MinSize;\n        TgaString authorName = new TgaString(41, true);\n        TgaComment authorComments = new TgaComment();\n        TgaDateTime dateTimeStamp = new TgaDateTime();\n        TgaString jobNameOrID = new TgaString(41, true);\n        TgaTime jobTime = new TgaTime();\n        TgaString softwareID = new TgaString(41, true);\n        TgaSoftVersion softVersion = new TgaSoftVersion();\n        TgaColorKey keyColor = new TgaColorKey();\n        TgaFraction pixelAspectRatio = TgaFraction.Empty;\n        TgaFraction gammaValue = TgaFraction.Empty;\n        uint colorCorrectionOffset = 0;\n        uint postageStampOffset = 0;\n        uint scanLineOffset = 0;\n        TgaAttrType attributesType = TgaAttrType.NoAlpha;\n        uint[] scanLineTable = null;\n        TgaPostageStampImage postageStampImage = null;\n        ushort[] colorCorrectionTable = null;\n        byte[] otherDataInExtensionArea = null;\n\n        public TgaExtArea()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaExtArea\"/> from bytes. Warning: <see cref=\"ScanLineTable\"/>,\n        /// <see cref=\"PostageStampImage\"/>, <see cref=\"ColorCorrectionTable\"/> not included,\n        /// because thea are can be not in the Extension Area of TGA file!\n        /// </summary>\n        /// <param name=\"Bytes\">Bytes of <see cref=\"TgaExtArea\"/>.</param>\n        /// <param name=\"SLT\">Scan Line Table.</param>\n        /// <param name=\"PostImg\">Postage Stamp Image.</param>\n        /// <param name=\"CCT\">Color Correction Table.</param>\n        public TgaExtArea(byte[] Bytes, uint[] SLT = null, TgaPostageStampImage PostImg = null, ushort[] CCT = null)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length < MinSize)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be >= \" + MinSize + \"!\");\n\n            extensionSize = BitConverter.ToUInt16(Bytes, 0);\n            authorName = new TgaString(BitConverterExt.GetElements(Bytes, 2, 41), true);\n            authorComments = new TgaComment(BitConverterExt.GetElements(Bytes, 43, TgaComment.Size));\n            dateTimeStamp = new TgaDateTime(BitConverterExt.GetElements(Bytes, 367, TgaDateTime.Size));\n            jobNameOrID = new TgaString(BitConverterExt.GetElements(Bytes, 379, 41), true);\n            jobTime = new TgaTime(BitConverterExt.GetElements(Bytes, 420, TgaTime.Size));\n            softwareID = new TgaString(BitConverterExt.GetElements(Bytes, 426, 41), true);\n            softVersion = new TgaSoftVersion(BitConverterExt.GetElements(Bytes, 467, TgaSoftVersion.Size));\n            keyColor = new TgaColorKey(BitConverterExt.GetElements(Bytes, 470, TgaColorKey.Size));\n            pixelAspectRatio = new TgaFraction(BitConverterExt.GetElements(Bytes, 474, TgaFraction.Size));\n            gammaValue = new TgaFraction(BitConverterExt.GetElements(Bytes, 478, TgaFraction.Size));\n            colorCorrectionOffset = BitConverter.ToUInt32(Bytes, 482);\n            postageStampOffset = BitConverter.ToUInt32(Bytes, 486);\n            scanLineOffset = BitConverter.ToUInt32(Bytes, 490);\n            attributesType = (TgaAttrType)Bytes[494];\n\n            if (extensionSize > MinSize)\n                otherDataInExtensionArea = BitConverterExt.GetElements(Bytes, 495, Bytes.Length - MinSize);\n\n            scanLineTable = SLT;\n            postageStampImage = PostImg;\n            colorCorrectionTable = CCT;\n        }\n\n        #region Properties\n        /// <summary>\n        /// Extension Size - Field 10 (2 Bytes):\n        /// This field is a SHORT field which specifies the number of BYTES in the fixedlength portion of\n        /// the Extension Area. For Version 2.0 of the TGA File Format, this number should be set to 495.\n        /// If the number found in this field is not 495, then the file will be assumed to be of a\n        /// version other than 2.0. If it ever becomes necessary to alter this number, the change\n        /// will be controlled by Truevision, and will be accompanied by a revision to the TGA File\n        /// Format with an accompanying change in the version number.\n        /// </summary>\n        public ushort ExtensionSize\n        {\n            get { return extensionSize; }\n            set { extensionSize = value; }\n        }\n\n        /// <summary>\n        /// Author Name - Field 11 (41 Bytes):\n        /// Bytes 2-42 - This field is an ASCII field of 41 bytes where the last byte must be a null\n        /// (binary zero). This gives a total of 40 ASCII characters for the name. If the field is used,\n        /// it should contain the name of the person who created the image (author). If the field is not\n        /// used, you may fill it with nulls or a series of blanks(spaces) terminated by a null.\n        /// The 41st byte must always be a null.\n        /// </summary>\n        public TgaString AuthorName\n        {\n            get { return authorName; }\n            set { authorName = value; }\n        }\n\n        /// <summary>\n        /// Author Comments - Field 12 (324 Bytes):\n        /// Bytes 43-366 - This is an ASCII field consisting of 324 bytes which are organized as four lines\n        /// of 80 characters, each followed by a null terminator.This field is provided, in addition to the\n        /// original IMAGE ID field(in the original TGA format), because it was determined that a few\n        /// developers had used the IMAGE ID field for their own purposes.This field gives the developer\n        /// four lines of 80 characters each, to use as an Author Comment area. Each line is fixed to 81\n        /// bytes which makes access to the four lines easy.Each line must be terminated by a null.\n        /// If you do not use all 80 available characters in the line, place the null after the last\n        /// character and blank or null fill the rest of the line. The 81st byte of each of the four\n        /// lines must be null.\n        /// </summary>\n        public TgaComment AuthorComments\n        {\n            get { return authorComments; }\n            set { authorComments = value; }\n        }\n\n        /// <summary>\n        /// Date/Time Stamp - Field 13 (12 Bytes):\n        /// Bytes 367-378 - This field contains a series of 6 SHORT values which define the integer\n        /// value for the date and time that the image was saved. This data is formatted as follows:\n        /// <para>SHORT 0: Month(1 - 12)</para>\n        /// <para>SHORT 1: Day(1 - 31)</para>\n        /// <para>SHORT 2: Year(4 digit, ie. 1989)</para>\n        /// <para>SHORT 3: Hour(0 - 23)</para>\n        /// <para>SHORT 4: Minute(0 - 59)</para>\n        /// <para>SHORT 5: Second(0 - 59)</para>\n        /// Even though operating systems typically time- and date-stamp files, this feature is\n        /// provided because the operating system may change the time and date stamp if the file is\n        /// copied. By using this area, you are guaranteed an unmodified region for date and time\n        /// recording. If the fields are not used, you should fill them with binary zeros (0).\n        /// </summary>\n        public TgaDateTime DateTimeStamp\n        {\n            get { return dateTimeStamp; }\n            set { dateTimeStamp = value; }\n        }\n\n        /// <summary>\n        /// Job Name/ID - Field 14 (41 Bytes):\n        /// Bytes 379-419 - This field is an ASCII field of 41 bytes where the last byte must be \n        /// a binary zero. This gives a total of 40 ASCII characters for the job name or the ID.\n        /// If the field is used, it should contain a name or id tag which refers to the job with\n        /// which the image was associated.This allows production companies (and others) to tie\n        /// images with jobs by using this field as a job name (i.e., CITY BANK) or job id number\n        /// (i.e., CITY023). If the field is not used, you may fill it with a null terminated series\n        /// of blanks (spaces) or nulls. In any case, the 41st byte must be a null.\n        /// </summary>\n        public TgaString JobNameOrID\n        {\n            get { return jobNameOrID; }\n            set { jobNameOrID = value; }\n        }\n\n        /// <summary>\n        /// Job Time - Field 15 (6 Bytes):\n        /// Bytes 420-425 - This field contains a series of 3 SHORT values which define the integer\n        /// value for the job elapsed time when the image was saved.This data is formatted as follows:\n        /// <para>SHORT 0: Hours(0 - 65535)</para>\n        /// <para>SHORT 1: Minutes(0 - 59)</para>\n        /// <para>SHORT 2: Seconds(0 - 59)</para>\n        /// The purpose of this field is to allow production houses (and others) to keep a running total\n        /// of the amount of time invested in a particular image. This may be useful for billing, costing,\n        /// and time estimating. If the fields are not used, you should fill them with binary zeros (0).\n        /// </summary>\n        public TgaTime JobTime\n        {\n            get { return jobTime; }\n            set { jobTime = value; }\n        }\n\n        /// <summary>\n        /// Software ID - Field 16 (41 Bytes):\n        /// Bytes 426-466 - This field is an ASCII field of 41 bytes where the last byte must be\n        /// a binary zero (null). This gives a total of 40 ASCII characters for the Software ID.\n        /// The purpose of this field is to allow software to determine and record with what program\n        /// a particular image was created.If the field is not used, you may fill it with a\n        /// null terminated series of blanks (spaces) or nulls. The 41st byte must always be a null.\n        /// </summary>\n        public TgaString SoftwareID\n        {\n            get { return softwareID; }\n            set { softwareID = value; }\n        }\n\n        /// <summary>\n        /// Software Version - Field 17 (3 Bytes):\n        /// Bytes 467-469 - This field consists of two sub-fields, a SHORT and an ASCII BYTE.\n        /// The purpose of this field is to define the version of software defined by the\n        /// “Software ID” field above. The SHORT contains the version number as a binary\n        /// integer times 100.\n        /// <para>Therefore, software version 4.17 would be the integer value 417.This allows for\n        /// two decimal positions of sub-version.The ASCII BYTE supports developers who also\n        /// tag a release letter to the end. For example, if the version number is 1.17b, then\n        /// the SHORT would contain 117. and the ASCII BYTE would contain “b”.\n        /// The organization is as follows:</para>\n        /// <para>SHORT (Bytes 0 - 1): Version Number * 100</para>\n        /// <para>BYTE(Byte 2): Version Letter</para>\n        /// If you do not use this field, set the SHORT to binary zero, and the BYTE to a space(“ “)\n        /// </summary>\n        public TgaSoftVersion SoftVersion\n        {\n            get { return softVersion; }\n            set { softVersion = value; }\n        }\n\n        /// <summary>\n        /// Key Color - Field 18 (4 Bytes):\n        /// Bytes 470-473 - This field contains a long value which is the key color in effect at\n        /// the time the image is saved. The format is in A:R:G:B where ‘A’ (most significant byte)\n        /// is the alpha channel key color(if you don’t have an alpha channel in your application,\n        /// keep this byte zero [0]).\n        /// <para>The Key Color can be thought of as the ‘background color’ or ‘transparent color’.\n        /// This is the color of the ‘non image’ area of the screen, and the same color that the\n        /// screen would be cleared to if erased in the application. If you don’t use this field,\n        /// set it to all zeros (0). Setting the field to all zeros is the same as selecting a key\n        /// color of black.</para>\n        /// A good example of a key color is the ‘transparent color’ used in TIPS™ for WINDOW loading/saving.\n        /// </summary>\n        public TgaColorKey KeyColor\n        {\n            get { return keyColor; }\n            set { keyColor = value; }\n        }\n\n        /// <summary>\n        /// Pixel Aspect Ratio - Field 19 (4 Bytes):\n        /// Bytes 474-477 - This field contains two SHORT sub-fields, which when taken together\n        /// specify a pixel size ratio.The format is as follows:\n        /// <para>SHORT 0: Pixel Ratio Numerator(pixel width)</para>\n        /// <para>SHORT 1: Pixel Ratio Denominator(pixel height)</para>\n        /// These sub-fields may be used to determine the aspect ratio of a pixel. This is useful when\n        /// it is important to preserve the proper aspect ratio of the saved image. If the two values\n        /// are set to the same non-zero value, then the image is composed of square pixels. A zero\n        /// in the second sub-field (denominator) indicates that no pixel aspect ratio is specified.\n        /// </summary>\n        public TgaFraction PixelAspectRatio\n        {\n            get { return pixelAspectRatio; }\n            set { pixelAspectRatio = value; }\n        }\n\n        /// <summary>\n        /// Gamma Value - Field 20 (4 Bytes):\n        /// Bytes 478-481 - This field contains two SHORT sub-fields, which when taken together in a ratio,\n        /// provide a fractional gamma value.The format is as follows:\n        /// <para>SHORT 0: Gamma Numerator</para>\n        /// <para>SHORT 1: Gamma Denominator</para>\n        /// The resulting value should be in the range of 0.0 to 10.0, with only one decimal place of\n        /// precision necessary. An uncorrected image (an image with no gamma) should have the value 1.0 as\n        /// the result.This may be accomplished by placing thesame, non-zero values in both positions\n        /// (i.e., 1/1). If you decide to totally ignore this field, please set the denominator (the second\n        /// SHORT) to the value zero. This will indicate that the Gamma Value field is not being used.\n        /// </summary>\n        public TgaFraction GammaValue\n        {\n            get { return gammaValue; }\n            set { gammaValue = value; }\n        }\n\n        /// <summary>\n        /// Color Correction Offset - Field 21 (4 Bytes):\n        /// Bytes 482-485 - This field is a 4-byte field containing a single offset value. This is an offset\n        /// from the beginning of the file to the start of the Color Correction table. This table may be\n        /// written anywhere between the end of the Image Data field (field 8) and the start of the TGA\n        /// File Footer. If the image has no Color Correction Table or if the Gamma Value setting is\n        /// sufficient, set this value to zero and do not write a Correction Table anywhere.\n        /// </summary>\n        public uint ColorCorrectionTableOffset\n        {\n            get { return colorCorrectionOffset; }\n            set { colorCorrectionOffset = value; }\n        }\n\n        /// <summary>\n        /// Postage Stamp Offset - Field 22 (4 Bytes):\n        /// Bytes 486-489 - This field is a 4-byte field containing a single offset value. This is an offset\n        /// from the beginning of the file to the start of the Postage Stamp Image. The Postage Stamp Image\n        /// must be written after Field 25 (Scan Line Table) but before the start of the TGA File Footer.\n        /// If no postage stamp is stored, set this field to the value zero (0).\n        /// </summary>\n        public uint PostageStampOffset\n        {\n            get { return postageStampOffset; }\n            set { postageStampOffset = value; }\n        }\n\n        /// <summary>\n        /// Scan Line Offset - Field 23 (4 Bytes):\n        /// Bytes 490-493 - This field is a 4-byte field containing a single offset value. This is an\n        /// offset from the beginning of the file to the start of the Scan Line Table.\n        /// </summary>\n        public uint ScanLineOffset\n        {\n            get { return scanLineOffset; }\n            set { scanLineOffset = value; }\n        }\n\n        /// <summary>\n        /// Attributes Type - Field 24 (1 Byte):\n        /// Byte 494 - This single byte field contains a value which specifies the type of Alpha channel\n        /// data contained in the file. Value Meaning:\n        /// <para>0: no Alpha data included (bits 3-0 of field 5.6 should also be set to zero)</para>\n        /// <para>1: undefined data in the Alpha field, can be ignored</para>\n        /// <para>2: undefined data in the Alpha field, but should be retained</para>\n        /// <para>3: useful Alpha channel data is present</para>\n        /// <para>4: pre-multiplied Alpha(see description below)</para>\n        /// <para>5 -127: RESERVED</para>\n        /// <para>128-255: Un-assigned</para>\n        /// <para>Pre-multiplied Alpha Example: Suppose the Alpha channel data is being used to specify the\n        /// opacity of each pixel(for use when the image is overlayed on another image), where 0 indicates\n        /// that the pixel is completely transparent and a value of 1 indicates that the pixel is\n        /// completely opaque(assume all component values have been normalized).</para>\n        /// <para>A quadruple(a, r, g, b) of( 0.5, 1, 0, 0) would indicate that the pixel is pure red with a\n        /// transparency of one-half. For numerous reasons(including image compositing) is is better to\n        /// pre-multiply the individual color components with the value in the Alpha channel.</para>\n        /// A pre-multiplication of the above would produce a quadruple(0.5, 0.5, 0, 0).\n        /// A value of 3 in the Attributes Type Field(field 23) would indicate that the color components\n        /// of the pixel have already been scaled by the value in the Alpha channel.\n        /// </summary>\n        public TgaAttrType AttributesType\n        {\n            get { return attributesType; }\n            set { attributesType = value; }\n        }\n\n        /// <summary>\n        /// Scan Line Table - Field 25 (Variable):\n        /// This information is provided, at the developers’ request, for two purposes:\n        /// <para>1) To make random access of compressed images easy.</para>\n        /// <para>2) To allow “giant picture” access in smaller “chunks”.</para>\n        /// This table should contain a series of 4-byte offsets.Each offset you write should point to the\n        /// start of the next scan line, in the order that the image was saved (i.e., top down or bottom up).\n        /// The offset should be from the start of the file.Therefore, you will have a four byte value for\n        /// each scan line in your image. This means that if your image is 768 pixels tall, you will have 768,\n        /// 4-byte offset pointers (for a total of 3072 bytes). This size is not extreme, and thus this table\n        /// can be built and maintained in memory, and then written out at the proper time.\n        /// </summary>\n        public uint[] ScanLineTable\n        {\n            get { return scanLineTable; }\n            set { scanLineTable = value; }\n        }\n\n        /// <summary>\n        /// Postage Stamp Image - Field 26 (Variable):\n        /// The Postage Stamp area is a smaller representation of the original image. This is useful for\n        /// “browsing” a collection of image files. If your application can deal with a postage stamp image,\n        /// it is recommended that you create one using sub-sampling techniques to create the best\n        /// representation possible. The postage stamp image must be stored in the same format as the normal\n        /// image specified in the file, but without any compression. The first byte of the postage stamp\n        /// image specifies the X size of the stamp in pixels, the second byte of the stamp image specifies the\n        /// Y size of the stamp in pixels. Truevision does not recommend stamps larger than 64x64 pixels, and\n        /// suggests that any stamps stored larger be clipped. Obviously, the storage of the postage stamp\n        /// relies heavily on the storage of the image. The two images are stored using the same format under\n        /// the assumption that if you can read the image, then you can read the postage stamp. If the original\n        /// image is color mapped, DO NOT average the postage stamp, as you will create new colors not in your map.\n        /// </summary>\n        public TgaPostageStampImage PostageStampImage\n        {\n            get { return postageStampImage; }\n            set { postageStampImage = value; }\n        }\n\n        /// <summary>\n        /// Color Correction Table - Field 27 (2K Bytes):\n        /// The Color Correction Table is a block of 256 x 4 SHORT values, where each set of\n        /// four contiguous values are the desired A:R:G:B correction for that entry. This\n        /// allows the user to store a correction table for image remapping or LUT driving.\n        /// Since each color in the block is a SHORT, the maximum value for a color gun (i.e.,\n        /// A, R, G, B) is 65535, and the minimum value is zero.Therefore, BLACK maps to\n        /// 0, 0, 0, 0 and WHITE maps to 65535, 65535, 65535, 65535.\n        /// </summary>\n        public ushort[] ColorCorrectionTable\n        {\n            get { return colorCorrectionTable; }\n            set { colorCorrectionTable = value; }\n        }\n\n        /// <summary>\n        /// Other Data In Extension Area (if <see cref=\"ExtensionSize\"/> > 495).\n        /// </summary>\n        public byte[] OtherDataInExtensionArea\n        {\n            get { return otherDataInExtensionArea; }\n            set { otherDataInExtensionArea = value; }\n        }\n        #endregion\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaExtArea\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaExtArea\"/>.</returns>\n        public TgaExtArea Clone()\n        {\n            TgaExtArea NewExtArea = new TgaExtArea();\n            NewExtArea.extensionSize = extensionSize;\n            NewExtArea.authorName = authorName.Clone();\n            NewExtArea.authorComments = authorComments.Clone();\n            NewExtArea.dateTimeStamp = dateTimeStamp.Clone();\n            NewExtArea.jobNameOrID = jobNameOrID.Clone();\n            NewExtArea.jobTime = jobTime.Clone();\n            NewExtArea.softwareID = softwareID.Clone();\n            NewExtArea.softVersion = softVersion.Clone();\n            NewExtArea.keyColor = keyColor.Clone();\n            NewExtArea.pixelAspectRatio = pixelAspectRatio.Clone();\n            NewExtArea.gammaValue = gammaValue.Clone();\n            NewExtArea.colorCorrectionOffset = colorCorrectionOffset;\n            NewExtArea.postageStampOffset = postageStampOffset;\n            NewExtArea.scanLineOffset = scanLineOffset;\n            NewExtArea.attributesType = attributesType;\n\n            if (scanLineTable != null)\n                NewExtArea.scanLineTable = (uint[])scanLineTable.Clone();\n            if (postageStampImage != null)\n                NewExtArea.postageStampImage = new TgaPostageStampImage(postageStampImage.ToBytes());\n            if (colorCorrectionTable != null)\n                NewExtArea.colorCorrectionTable = (ushort[])colorCorrectionTable.Clone();\n\n            if (otherDataInExtensionArea != null)\n                NewExtArea.otherDataInExtensionArea = (byte[])otherDataInExtensionArea.Clone();\n\n            return NewExtArea;\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaExtArea\"/>.\n        /// </summary>\n        /// <returns>Full independent copy of <see cref=\"TgaExtArea\"/>.</returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaExtArea) ? Equals((TgaExtArea)obj) : false);\n        }\n\n        public bool Equals(TgaExtArea item)\n        {\n            return (extensionSize == item.extensionSize &&\n                authorName == item.authorName &&\n                authorComments == item.authorComments &&\n                dateTimeStamp == item.dateTimeStamp &&\n                jobNameOrID == item.jobNameOrID &&\n                jobTime == item.jobTime &&\n                softwareID == item.softwareID &&\n                softVersion == item.softVersion &&\n                keyColor == item.keyColor &&\n                pixelAspectRatio == item.pixelAspectRatio &&\n                gammaValue == item.gammaValue &&\n                colorCorrectionOffset == item.colorCorrectionOffset &&\n                postageStampOffset == item.postageStampOffset &&\n                scanLineOffset == item.scanLineOffset &&\n                attributesType == item.attributesType &&\n\n                BitConverterExt.IsArraysEqual(scanLineTable, item.scanLineTable) &&\n                postageStampImage == item.postageStampImage &&\n                BitConverterExt.IsArraysEqual(colorCorrectionTable, item.colorCorrectionTable) &&\n\n                BitConverterExt.IsArraysEqual(otherDataInExtensionArea, item.otherDataInExtensionArea));\n        }\n\n        public static bool operator ==(TgaExtArea item1, TgaExtArea item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaExtArea item1, TgaExtArea item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 27;\n                hash = (13 * hash) + extensionSize.GetHashCode();\n                hash = (13 * hash) + authorName.GetHashCode();\n                hash = (13 * hash) + authorComments.GetHashCode();\n                hash = (13 * hash) + dateTimeStamp.GetHashCode();\n                hash = (13 * hash) + jobNameOrID.GetHashCode();\n                hash = (13 * hash) + jobTime.GetHashCode();\n                hash = (13 * hash) + softwareID.GetHashCode();\n                hash = (13 * hash) + softVersion.GetHashCode();\n                hash = (13 * hash) + keyColor.GetHashCode();\n                hash = (13 * hash) + pixelAspectRatio.GetHashCode();\n                hash = (13 * hash) + gammaValue.GetHashCode();\n                hash = (13 * hash) + colorCorrectionOffset.GetHashCode();\n                hash = (13 * hash) + postageStampOffset.GetHashCode();\n                hash = (13 * hash) + scanLineOffset.GetHashCode();\n                hash = (13 * hash) + attributesType.GetHashCode();\n\n                if (scanLineTable != null)\n                    for (int i = 0; i < scanLineTable.Length; i++)\n                        hash = (13 * hash) + scanLineTable[i].GetHashCode();\n\n                if (postageStampImage != null)\n                    hash = (13 * hash) + postageStampImage.GetHashCode();\n\n                if (colorCorrectionTable != null)\n                    for (int i = 0; i < colorCorrectionTable.Length; i++)\n                        hash = (13 * hash) + colorCorrectionTable[i].GetHashCode();\n\n                if (otherDataInExtensionArea != null)\n                    for (int i = 0; i < otherDataInExtensionArea.Length; i++)\n                        hash = (13 * hash) + otherDataInExtensionArea[i].GetHashCode();\n\n                return hash;\n            }\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaExtArea\"/> to byte array. Warning: <see cref=\"ScanLineTable\"/>,\n        /// <see cref=\"PostageStampImage\"/>, <see cref=\"ColorCorrectionTable\"/> not included,\n        /// because thea are can be not in the Extension Area of TGA file!\n        /// </summary>\n        /// <returns>Byte array.</returns>\n        public byte[] ToBytes()\n        {\n            #region Exceptions check\n            if (authorName == null)\n                authorName = new TgaString(41, true);\n\n            if (authorComments == null)\n                authorComments = new TgaComment();\n\n            if (dateTimeStamp == null)\n                dateTimeStamp = new TgaDateTime(DateTime.UtcNow);\n\n            if (jobNameOrID == null)\n                jobNameOrID = new TgaString(41, true);\n\n            if (jobTime == null)\n                jobTime = new TgaTime();\n\n            if (softwareID == null)\n                softwareID = new TgaString(41, true);\n\n            if (softVersion == null)\n                softVersion = new TgaSoftVersion();\n\n            if (keyColor == null)\n                keyColor = new TgaColorKey();\n\n            if (pixelAspectRatio == null)\n                pixelAspectRatio = new TgaFraction();\n\n            if (gammaValue == null)\n                gammaValue = new TgaFraction();\n            #endregion\n\n            return BitConverterExt.ToBytes(\n                extensionSize,\n                authorName.ToBytes(),\n                authorComments.ToBytes(),\n                dateTimeStamp.ToBytes(),\n                jobNameOrID.ToBytes(),\n                jobTime.ToBytes(),\n                softwareID.ToBytes(),\n                softVersion.ToBytes(),\n                keyColor.ToBytes(),\n                pixelAspectRatio.ToBytes(),\n                gammaValue.ToBytes(),\n                colorCorrectionOffset,\n                postageStampOffset,\n                scanLineOffset,\n                (byte)attributesType,\n                otherDataInExtensionArea);\n        }\n    } //Not full ToBytes()\n\n    /// <summary>\n    /// File Footer Area\n    /// </summary>\n    public class TgaFooter : ICloneable\n    {\n        uint extAreaOffset = 0;\n        uint devDirOffset = 0;\n        TgaString signature = TgaString.XFileSignatute;\n        TgaString reservedChar = TgaString.DotSymbol;\n        TgaString zeroStrTerminator = TgaString.ZeroTerminator;\n\n        /// <summary>\n        /// Make NewXFile format TGA Footer with <see cref=\"ExtensionAreaOffset\"/> = 0 and\n        /// <see cref=\"DeveloperDirectoryOffset\"/> = 0.\n        /// </summary>\n        public TgaFooter()\n        {\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaFooter\"/> from values.\n        /// </summary>\n        /// <param name=\"ExtOff\">Extension Area Offset, offset from the beginning of the file.</param>\n        /// <param name=\"DevDirOff\">Developer Directory Offset, offset from the beginning of the file.</param>\n        /// <param name=\"Sign\">New TGA format signature.</param>\n        /// <param name=\"ReservChr\">Reserved Character - ASCII character “.” (period).</param>\n        /// <param name=\"Termin\">Binary Zero Terminator, a binary zero which acts as a final terminator.</param>\n        public TgaFooter(uint ExtOff, uint DevDirOff, TgaString Sign, TgaString ReservChr, TgaString Termin)\n        {\n            extAreaOffset = ExtOff;\n            devDirOffset = DevDirOff;\n            signature = Sign;\n            reservedChar = ReservChr;\n            zeroStrTerminator = Termin;\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TgaFooter\"/> from bytes (if signature is right).\n        /// </summary>\n        /// <param name=\"Bytes\">Bytes array (byte[26]).</param>\n        public TgaFooter(byte[] Bytes)\n        {\n            if (Bytes == null)\n                throw new ArgumentNullException(nameof(Bytes) + \" = null!\");\n            if (Bytes.Length != Size)\n                throw new ArgumentOutOfRangeException(nameof(Bytes.Length) + \" must be equal \" + Size + \"!\");\n\n            extAreaOffset = BitConverter.ToUInt32(Bytes, 0);\n            devDirOffset = BitConverter.ToUInt32(Bytes, 4);\n            signature = new TgaString(BitConverterExt.GetElements(Bytes, 8, TgaString.XFileSignatuteConst.Length));\n            reservedChar = new TgaString(new byte[] { Bytes[24] });\n            zeroStrTerminator = new TgaString(new byte[] { Bytes[25] });\n        }\n\n        /// <summary>\n        /// Byte 0-3 - Extension Area Offset - Field 28\n        /// The first four bytes (bytes 0-3, the first LONG) of the TGA File Footer contain an\n        /// offset from the beginning of the file to the start of the Extension Area. Simply\n        /// SEEK to this location to position to the start of the Extension Area. If the\n        /// Extension Area Offset is zero, no Extension Area exists in the file.\n        /// </summary>\n        public uint ExtensionAreaOffset\n        {\n            get { return extAreaOffset; }\n            set { extAreaOffset = value; }\n        }\n\n        /// <summary>\n        /// Byte 4-7 - Developer Directory Offset - Field 29\n        /// The next four bytes(bytes 4-7, the second LONG) contain an offset from the\n        /// beginning of the file to the start of the Developer Directory. If the Developer\n        /// Directory Offset is zero, then the Developer Area does not exist.\n        /// </summary>\n        public uint DeveloperDirectoryOffset\n        {\n            get { return devDirOffset; }\n            set { devDirOffset = value; }\n        }\n\n        /// <summary>\n        /// Byte 8-23 - Signature - Field 30\n        /// This string is exactly 16 bytes long and is formatted exactly as shown below\n        /// capital letters), with a hyphen between “TRUEVISION” and “XFILE.” If the\n        /// signature is detected, the file is assumed to be of the New TGA format and MAY,\n        /// therefore, contain the Developer Area and/or the Extension Area fields.If the\n        /// signature is not found, then the file is assumed to be in the Original TGA format.\n        /// </summary>\n        public TgaString Signature\n        {\n            get { return signature; }\n            set { signature = value; }\n        }\n\n        /// <summary>\n        /// Byte 24 - Reserved Character - Field 31\n        /// Byte 24 is an ASCII character “.” (period). This character MUST BE a period or\n        /// the file is not considered a proper TGA file.\n        /// </summary>\n        public TgaString ReservedCharacter\n        {\n            get { return reservedChar; }\n            set { reservedChar = value; }\n        }\n\n        /// <summary>\n        /// Byte 25 - Binary Zero String Terminator - Field 32\n        /// Byte 25 is a binary zero which acts as a final terminator and allows the entire TGA\n        /// File Footer to be read and utilized as a “C” string.\n        /// </summary>\n        public TgaString BinaryZeroStringTerminator\n        {\n            get { return zeroStrTerminator; }\n            set { zeroStrTerminator = value; }\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaFooter\"/>.\n        /// </summary>\n        /// <returns></returns>\n        public TgaFooter Clone()\n        {\n            return new TgaFooter(extAreaOffset, devDirOffset, signature.Clone(),\n                reservedChar.Clone(), zeroStrTerminator.Clone());\n        }\n\n        /// <summary>\n        /// Make full copy of <see cref=\"TgaFooter\"/>.\n        /// </summary>\n        /// <returns></returns>\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        /// <summary>\n        /// Gets TGA Footer Section size in bytes.\n        /// </summary>\n        public const int Size = 26;\n\n        public override bool Equals(object obj)\n        {\n            return ((obj is TgaFooter) ? Equals((TgaFooter)obj) : false);\n        }\n\n        public bool Equals(TgaFooter item)\n        {\n            return (extAreaOffset == item.extAreaOffset &&\n                devDirOffset == item.devDirOffset &&\n                signature == item.signature &&\n                reservedChar == item.reservedChar &&\n                zeroStrTerminator == item.zeroStrTerminator);\n        }\n\n        public static bool operator ==(TgaFooter item1, TgaFooter item2)\n        {\n            if (ReferenceEquals(item1, null))\n                return ReferenceEquals(item2, null);\n\n            if (ReferenceEquals(item2, null))\n                return ReferenceEquals(item1, null);\n\n            return item1.Equals(item2);\n        }\n\n        public static bool operator !=(TgaFooter item1, TgaFooter item2)\n        {\n            return !(item1 == item2);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hash = 17;\n                hash = hash * 23 + extAreaOffset.GetHashCode();\n                hash = hash * 23 + devDirOffset.GetHashCode();\n\n                if (signature != null)\n                    hash = hash * 23 + signature.GetHashCode();\n\n                if (reservedChar != null)\n                    hash = hash * 23 + reservedChar.GetHashCode();\n\n                if (zeroStrTerminator != null)\n                    hash = hash * 23 + zeroStrTerminator.GetHashCode();\n\n                return hash;\n            }\n        }\n\n        public override string ToString()\n        {\n            return String.Format(\"{0}={1}, {2}={3}, FullSignature={4}\",\n                nameof(ExtensionAreaOffset), extAreaOffset, nameof(DeveloperDirectoryOffset), devDirOffset,\n                (signature + reservedChar + zeroStrTerminator).ToString());\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TgaFooter\"/> to byte array.\n        /// </summary>\n        /// <returns>Byte array with size equal <see cref=\"Size\"/>.</returns>\n        public byte[] ToBytes()\n        {\n            return BitConverterExt.ToBytes(extAreaOffset, devDirOffset,\n                signature.ToBytes(), reservedChar.ToBytes(), zeroStrTerminator.ToBytes());\n        }\n\n        /// <summary>\n        /// Is footer is real footer of TGA File Format Version 2.0?\n        /// Checking by <see cref=\"TgaString.XFileSignatute\"/>.\n        /// </summary>\n        public bool IsFooterCorrect\n        {\n            get { return signature == TgaString.XFileSignatute; }\n        }\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////////////////////\n\n    /// <summary>\n    /// Simplify ByteConversion operations, like concatination of byte arrays, comparing and other.\n    /// </summary>\n    public static class BitConverterExt\n    {\n        /// <summary>\n        /// Combine byte, byte[], (u)short, (u)int, (u)long values to byte[] array.\n        /// </summary>\n        /// <param name=\"obj\">Array of byte, byte[], (u)short, (u)int, (u)long values.</param>\n        /// <returns>Array of bytes, null when some object is null.</returns>\n        public static byte[] ToBytes(params object[] obj)\n        {\n            if (obj == null)\n                return null;\n\n            List<byte> BytesList = new List<byte>();\n\n            for (int i = 0; i < obj.Length; i++)\n            {\n                if (obj[i] == null)\n                    continue;\n                else if (obj[i] is byte)\n                    BytesList.Add((byte)obj[i]);\n                else if (obj[i] is byte[])\n                    BytesList.AddRange((byte[])obj[i]);\n                else if (obj[i] is short)\n                    BytesList.AddRange(BitConverter.GetBytes((short)obj[i]));\n                else if (obj[i] is ushort)\n                    BytesList.AddRange(BitConverter.GetBytes((ushort)obj[i]));\n                else if (obj[i] is int)\n                    BytesList.AddRange(BitConverter.GetBytes((int)obj[i]));\n                else if (obj[i] is uint)\n                    BytesList.AddRange(BitConverter.GetBytes((uint)obj[i]));\n                else if (obj[i] is long)\n                    BytesList.AddRange(BitConverter.GetBytes((long)obj[i]));\n                else if (obj[i] is ulong)\n                    BytesList.AddRange(BitConverter.GetBytes((ulong)obj[i]));\n            }\n            return BytesList.ToArray();\n        }\n\n        /// <summary>\n        /// Copies a range of elements from an Array starting at the specified source index.\n        /// The length and the index are specified as 32-bit integers.\n        /// </summary>\n        /// <param name=\"SrcArray\">The <see cref=\"Array\"/> that contains the data to copy.</param>\n        /// <param name=\"Offset\">A 32-bit integer that represents the index in the\n        /// <see cref=\"SrcArray\"/> at which copying begins.</param>\n        /// <param name=\"Count\">A 32-bit integer that represents the number of elements to copy.</param>\n        /// <returns></returns>\n        public static T[] GetElements<T>(T[] SrcArray, int Offset, int Count)\n        {\n            if (SrcArray == null)\n                throw new ArgumentNullException(nameof(SrcArray) + \" is null!\");\n\n            if (Offset >= SrcArray.Length || Offset < 0)\n                throw new ArgumentOutOfRangeException(nameof(Offset) + \" has wrong value!\");\n\n            if (Count <= 0 || Offset + Count > SrcArray.Length)\n                throw new ArgumentOutOfRangeException(nameof(Count) + \" has wrong value!\");\n\n            T[] Buff = new T[Count];\n            Array.Copy(SrcArray, Offset, Buff, 0, Buff.Length);\n            return Buff;\n        }\n\n        /// <summary>\n        /// Compare N-dimensional Arrays.\n        /// </summary>\n        /// <typeparam name=\"T\">Arrays Type.</typeparam>\n        /// <param name=\"item1\">First Array.</param>\n        /// <param name=\"item2\">Second Array.</param>\n        /// <returns>True, if Arrays are equal.</returns>\n        public static bool IsArraysEqual<T>(T[] item1, T[] item2)\n        {\n            if (ReferenceEquals(item1, item2))\n                return true;\n\n            if (item1 == null || item2 == null)\n                return false;\n\n            if (item1.Length != item2.Length)\n                return false;\n\n            EqualityComparer<T> comparer = EqualityComparer<T>.Default;\n            for (int i = 0; i < item1.Length; i++)\n                if (!comparer.Equals(item1[i], item2[i]))\n                    return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Compare Lists.\n        /// </summary>\n        /// <typeparam name=\"T\">List Type.</typeparam>\n        /// <param name=\"item1\">First List.</param>\n        /// <param name=\"item2\">Second List.</param>\n        /// <returns>True, if Lists are equal.</returns>\n        public static bool IsListsEqual<T>(List<T> item1, List<T> item2)\n        {\n            if (ReferenceEquals(item1, item2))\n                return true;\n\n            if (item1 == null || item2 == null)\n                return false;\n\n            if (item1.Count != item2.Count)\n                return false;\n\n            for (int i = 0; i < item1.Count; i++)\n                if (!item1[i].Equals(item2[i]))\n                    return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Compare elements in one Array with different offsets.\n        /// </summary>\n        /// <typeparam name=\"T\">Array type.</typeparam>\n        /// <param name=\"Arr\">Some Array.</param>\n        /// <param name=\"Offset1\">First offset.</param>\n        /// <param name=\"Offset2\">Second offset.</param>\n        /// <param name=\"Count\">Elements count which must be compared.</param>\n        /// <returns></returns>\n        public static bool IsElementsEqual<T>(T[] Arr, int Offset1, int Offset2, int Count)\n        {\n            if (Arr == null)\n                throw new ArgumentNullException(nameof(Arr) + \" is null!\");\n\n            if (Offset1 >= Arr.Length || Offset1 < 0)\n                throw new ArgumentOutOfRangeException(nameof(Offset1) + \" has wrong value!\");\n\n            if (Offset2 >= Arr.Length || Offset2 < 0)\n                throw new ArgumentOutOfRangeException(nameof(Offset2) + \" has wrong value!\");\n\n            if (Count <= 0 || Offset1 + Count > Arr.Length || Offset2 + Count > Arr.Length)\n                throw new ArgumentOutOfRangeException(nameof(Count) + \" has wrong value!\");\n\n            if (Offset1 == Offset2)\n                return true;\n\n            for (int i = 0; i < Count; i++)\n                if (!Arr[Offset1 + i].Equals(Arr[Offset2 + i]))\n                    return false;\n\n            return true;\n        }\n    }\n    #endregion\n\n    public class TGA : ICloneable\n    {\n        public TgaHeader Header = new TgaHeader();\n        public TgaImgOrColMap ImageOrColorMapArea = new TgaImgOrColMap();\n        public TgaDevArea DevArea = null;\n        public TgaExtArea ExtArea = null;\n        public TgaFooter Footer = null;\n\n        #region TGA Creation, Loading, Saving (all are public, have reference to private metods).\n        /// <summary>\n        /// Create new empty <see cref=\"TGA\"/> istance.\n        /// </summary>\n        public TGA()\n        {\n        }\n\n        /// <summary>\n        /// Create <see cref=\"TGA\"/> instance with some params. If it must have ColorMap,\n        /// check all ColorMap fields and settings after.\n        /// </summary>\n        /// <param name=\"Width\">Image Width.</param>\n        /// <param name=\"Height\">Image Height.</param>\n        /// <param name=\"PixDepth\">Image Pixel Depth (bits / pixel), set ColorMap bpp after, if needed!</param>\n        /// <param name=\"ImgType\">Image Type (is RLE compressed, ColorMapped or GrayScaled).</param>\n        /// <param name=\"AttrBits\">Set numder of Attrbute bits (Alpha channel bits), default: 0, 1, 8.</param>\n        /// <param name=\"NewFormat\">Use new 2.0 TGA XFile format?</param>\n        public TGA(ushort Width, ushort Height, TgaPixelDepth PixDepth = TgaPixelDepth.Bpp24,\n            TgaImageType ImgType = TgaImageType.Uncompressed_TrueColor, byte AttrBits = 0, bool NewFormat = true)\n        {\n            if (Width <= 0 || Height <= 0 || PixDepth == TgaPixelDepth.Other)\n            {\n                Width = Height = 0;\n                PixDepth = TgaPixelDepth.Other;\n                ImgType = TgaImageType.NoImageData;\n                AttrBits = 0;\n            }\n            else\n            {\n                int BytesPerPixel = (int)Math.Ceiling((double)PixDepth / 8.0);\n                ImageOrColorMapArea.ImageData = new byte[Width * Height * BytesPerPixel];\n\n                if (ImgType == TgaImageType.Uncompressed_ColorMapped || ImgType == TgaImageType.RLE_ColorMapped)\n                {\n                    Header.ColorMapType = TgaColorMapType.ColorMap;\n                    Header.ColorMapSpec.FirstEntryIndex = 0;\n                    Header.ColorMapSpec.ColorMapEntrySize = (TgaColorMapEntrySize)Math.Ceiling((double)PixDepth / 8);\n                }\n            }\n\n            Header.ImageType = ImgType;\n            Header.ImageSpec.ImageWidth = Width;\n            Header.ImageSpec.ImageHeight = Height;\n            Header.ImageSpec.PixelDepth = PixDepth;\n            Header.ImageSpec.ImageDescriptor.AlphaChannelBits = AttrBits;\n\n            if (NewFormat)\n            {\n                Footer = new TgaFooter();\n                ExtArea = new TgaExtArea();\n                ExtArea.DateTimeStamp = new TgaDateTime(DateTime.UtcNow);\n                ExtArea.AttributesType = (AttrBits > 0 ? TgaAttrType.UsefulAlpha : TgaAttrType.NoAlpha);\n            }\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from some <see cref=\"TGA\"/> instance.\n        /// Equal to <see cref=\"TGA.Clone()\"/> function.\n        /// </summary>\n        /// <param name=\"tga\">Original <see cref=\"TGA\"/> instance.</param>\n        public TGA(TGA tga)\n        {\n            Header = tga.Header.Clone();\n            ImageOrColorMapArea = tga.ImageOrColorMapArea.Clone();\n            DevArea = tga.DevArea.Clone();\n            ExtArea = tga.ExtArea.Clone();\n            Footer = tga.Footer.Clone();\n        }\n\n        /// <summary>\n        /// Load <see cref=\"TGA\"/> from file.\n        /// </summary>\n        /// <param name=\"filename\">Full path to TGA file.</param>\n        /// <returns>Loaded <see cref=\"TGA\"/> file.</returns>\n        public TGA(string filename)\n        {\n            LoadFunc(filename);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from bytes array.\n        /// </summary>\n        /// <param name=\"bytes\">Bytes array (same like TGA File).</param>\n        public TGA(byte[] bytes)\n        {\n            LoadFunc(bytes);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from <see cref=\"Stream\"/>.\n        /// For file opening better use <see cref=\"FromFile(string)\"/>.\n        /// </summary>\n        /// <param name=\"stream\">Some stream. You can use a lot of Stream types, but Stream must support:\n        /// <see cref=\"Stream.CanSeek\"/> and <see cref=\"Stream.CanRead\"/>.</param>\n        public TGA(Stream stream)\n        {\n            LoadFunc(stream);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from <see cref=\"Bitmap\"/>.\n        /// </summary>\n        /// <param name=\"bmp\">Input Bitmap, supported a lot of bitmaps types: 8/15/16/24/32 Bpp's.</param>\n        /// <param name=\"UseRLE\">Use RLE Compression?</param>\n        /// <param name=\"NewFormat\">Use new 2.0 TGA XFile format?</param>\n        /// <param name=\"ColorMap2BytesEntry\">Is Color Map Entry size equal 15 or 16 Bpp, else - 24 or 32.</param>\n        public TGA(Bitmap bmp, bool UseRLE = false, bool NewFormat = true, bool ColorMap2BytesEntry = false)\n        {\n            LoadFunc(bmp, UseRLE, NewFormat, ColorMap2BytesEntry);\n        }\n\n        /// <summary>\n        /// Load <see cref=\"TGA\"/> from file.\n        /// </summary>\n        /// <param name=\"filename\">Full path to TGA file.</param>\n        /// <returns>Loaded <see cref=\"TGA\"/> file.</returns>\n        public static TGA FromFile(string filename)\n        {\n            return new TGA(filename);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from bytes array.\n        /// </summary>\n        /// <param name=\"bytes\">Bytes array (same like TGA File).</param>\n        public static TGA FromBytes(byte[] bytes)\n        {\n            return new TGA(bytes);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from <see cref=\"Stream\"/>.\n        /// For file opening better use <see cref=\"FromFile(string)\"/>.\n        /// </summary>\n        /// <param name=\"stream\">Some stream. You can use a lot of Stream types, but Stream must support:\n        /// <see cref=\"Stream.CanSeek\"/> and <see cref=\"Stream.CanRead\"/>.</param>\n        public static TGA FromStream(Stream stream)\n        {\n            return new TGA(stream);\n        }\n\n        /// <summary>\n        /// Make <see cref=\"TGA\"/> from <see cref=\"Bitmap\"/>.\n        /// </summary>\n        /// <param name=\"bmp\">Input Bitmap, supported a lot of bitmaps types: 8/15/16/24/32 Bpp's.</param>\n        /// <param name=\"UseRLE\">Use RLE Compression?</param>\n        /// <param name=\"NewFormat\">Use new 2.0 TGA XFile format?</param>\n        /// <param name=\"ColorMap2BytesEntry\">Is Color Map Entry size equal 15 or 16 Bpp, else - 24 or 32.</param>\n        public static TGA FromBitmap(Bitmap bmp, bool UseRLE = false,\n            bool NewFormat = true, bool ColorMap2BytesEntry = false)\n        {\n            return new TGA(bmp, UseRLE, NewFormat, ColorMap2BytesEntry);\n        }\n\n        /// <summary>\n        /// Save <see cref=\"TGA\"/> to file.\n        /// </summary>\n        /// <param name=\"filename\">Full path to file.</param>\n        /// <returns>Return \"true\", if all done or \"false\", if failed.</returns>\n        public bool Save(string filename)\n        {\n            try\n            {\n                bool Result = false;\n                using (FileStream Fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))\n                {\n                    using (MemoryStream Ms = new MemoryStream())\n                    {\n                        Result = SaveFunc(Ms);\n                        Ms.WriteTo(Fs);\n                        Fs.Flush();\n                    }\n                }\n                return Result;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Save <see cref=\"TGA\"/> to <see cref=\"Stream\"/>.\n        /// </summary>\n        /// <param name=\"stream\">Some stream, it must support: <see cref=\"Stream.CanWrite\"/>.</param>\n        /// <returns>Return \"true\", if all done or \"false\", if failed.</returns>\n        public bool Save(Stream stream)\n        {\n            return SaveFunc(stream);\n        }\n        #endregion\n\n        /// <summary>\n        /// Gets or Sets Image Width (see <see cref=\"Header.ImageSpec.ImageWidth\"/>).\n        /// </summary>\n        public ushort Width\n        {\n            get { return Header.ImageSpec.ImageWidth; }\n            set { Header.ImageSpec.ImageWidth = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets Image Height (see <see cref=\"Header.ImageSpec.ImageHeight\"/>).\n        /// </summary>\n        public ushort Height\n        {\n            get { return Header.ImageSpec.ImageHeight; }\n            set { Header.ImageSpec.ImageHeight = value; }\n        }\n\n        /// <summary>\n        /// Gets or Sets <see cref=\"TGA\"/> image Size.\n        /// </summary>\n        public Size Size\n        {\n            get { return new Size(Header.ImageSpec.ImageWidth, Header.ImageSpec.ImageHeight); }\n            set\n            {\n                Header.ImageSpec.ImageWidth = (ushort)value.Width;\n                Header.ImageSpec.ImageHeight = (ushort)value.Height;\n            }\n        }\n\n        /// <summary>\n        /// Make full independed copy of <see cref=\"TGA\"/>.\n        /// </summary>\n        /// <returns>Full independed copy of <see cref=\"TGA\"/>.</returns>\n        public TGA Clone()\n        {\n            return new TGA(this);\n        }\n\n        object ICloneable.Clone()\n        {\n            return Clone();\n        }\n\n        /// <summary>\n        /// Flip <see cref=\"TGA\"/> directions, for more info see <see cref=\"TgaImgOrigin\"/>.\n        /// </summary>\n        /// <param name=\"Horizontal\">Flip horizontal.</param>\n        /// <param name=\"Vertical\">Flip vertical.</param>\n        public void Flip(bool Horizontal = false, bool Vertical = false)\n        {\n            int NewOrigin = (int)Header.ImageSpec.ImageDescriptor.ImageOrigin;\n            NewOrigin = NewOrigin ^ ((Vertical ? 0x20 : 0) | (Horizontal ? 0x10 : 0));\n            Header.ImageSpec.ImageDescriptor.ImageOrigin = (TgaImgOrigin)NewOrigin;\n        }\n\n        /// <summary>\n        /// Get information from TGA image.\n        /// </summary>\n        /// <returns>MultiLine string with info fields (one per line).</returns>\n        public string GetInfo()\n        {\n            StringBuilder SB = new StringBuilder();\n\n            SB.AppendLine(\"Header:\");\n            SB.AppendLine(\"\\tID Length = \" + Header.IDLength);\n            SB.AppendLine(\"\\tImage Type = \" + Header.ImageType);\n            SB.AppendLine(\"\\tHeader -> ImageSpec:\");\n            SB.AppendLine(\"\\t\\tImage Width = \" + Header.ImageSpec.ImageWidth);\n            SB.AppendLine(\"\\t\\tImage Height = \" + Header.ImageSpec.ImageHeight);\n            SB.AppendLine(\"\\t\\tPixel Depth = \" + Header.ImageSpec.PixelDepth);\n            SB.AppendLine(\"\\t\\tImage Descriptor (AsByte) = \" + Header.ImageSpec.ImageDescriptor.ToByte());\n            SB.AppendLine(\"\\t\\tImage Descriptor -> AttributeBits = \" + Header.ImageSpec.ImageDescriptor.AlphaChannelBits);\n            SB.AppendLine(\"\\t\\tImage Descriptor -> ImageOrigin = \" + Header.ImageSpec.ImageDescriptor.ImageOrigin);\n            SB.AppendLine(\"\\t\\tX_Origin = \" + Header.ImageSpec.X_Origin);\n            SB.AppendLine(\"\\t\\tY_Origin = \" + Header.ImageSpec.Y_Origin);\n            SB.AppendLine(\"\\tColorMap Type = \" + Header.ColorMapType);\n            SB.AppendLine(\"\\tHeader -> ColorMapSpec:\");\n            SB.AppendLine(\"\\t\\tColorMap Entry Size = \" + Header.ColorMapSpec.ColorMapEntrySize);\n            SB.AppendLine(\"\\t\\tColorMap Length = \" + Header.ColorMapSpec.ColorMapLength);\n            SB.AppendLine(\"\\t\\tFirstEntry Index = \" + Header.ColorMapSpec.FirstEntryIndex);\n\n            SB.AppendLine(\"\\nImage / Color Map Area:\");\n            if (Header.IDLength > 0 && ImageOrColorMapArea.ImageID != null)\n                SB.AppendLine(\"\\tImage ID = \\\"\" + ImageOrColorMapArea.ImageID.GetString() + \"\\\"\");\n            else\n                SB.AppendLine(\"\\tImage ID = null\");\n\n            if (ImageOrColorMapArea.ImageData != null)\n                SB.AppendLine(\"\\tImage Data Length = \" + ImageOrColorMapArea.ImageData.Length);\n            else\n                SB.AppendLine(\"\\tImage Data = null\");\n\n            if (ImageOrColorMapArea.ColorMapData != null)\n                SB.AppendLine(\"\\tColorMap Data Length = \" + ImageOrColorMapArea.ColorMapData.Length);\n            else\n                SB.AppendLine(\"\\tColorMap Data = null\");\n\n            SB.AppendLine(\"\\nDevelopers Area:\");\n            if (DevArea != null)\n                SB.AppendLine(\"\\tCount = \" + DevArea.Count);\n            else\n                SB.AppendLine(\"\\tDevArea = null\");\n\n            SB.AppendLine(\"\\nExtension Area:\");\n            if (ExtArea != null)\n            {\n                SB.AppendLine(\"\\tExtension Size = \" + ExtArea.ExtensionSize);\n                SB.AppendLine(\"\\tAuthor Name = \\\"\" + ExtArea.AuthorName.GetString() + \"\\\"\");\n                SB.AppendLine(\"\\tAuthor Comments = \\\"\" + ExtArea.AuthorComments.GetString() + \"\\\"\");\n                SB.AppendLine(\"\\tDate / Time Stamp = \" + ExtArea.DateTimeStamp);\n                SB.AppendLine(\"\\tJob Name / ID = \\\"\" + ExtArea.JobNameOrID.GetString() + \"\\\"\");\n                SB.AppendLine(\"\\tJob Time = \" + ExtArea.JobTime);\n                SB.AppendLine(\"\\tSoftware ID = \\\"\" + ExtArea.SoftwareID.GetString() + \"\\\"\");\n                SB.AppendLine(\"\\tSoftware Version = \\\"\" + ExtArea.SoftVersion + \"\\\"\");\n                SB.AppendLine(\"\\tKey Color = \" + ExtArea.KeyColor);\n                SB.AppendLine(\"\\tPixel Aspect Ratio = \" + ExtArea.PixelAspectRatio);\n                SB.AppendLine(\"\\tGamma Value = \" + ExtArea.GammaValue);\n                SB.AppendLine(\"\\tColor Correction Table Offset = \" + ExtArea.ColorCorrectionTableOffset);\n                SB.AppendLine(\"\\tPostage Stamp Offset = \" + ExtArea.PostageStampOffset);\n                SB.AppendLine(\"\\tScan Line Offset = \" + ExtArea.ScanLineOffset);\n                SB.AppendLine(\"\\tAttributes Type = \" + ExtArea.AttributesType);\n\n                if (ExtArea.ScanLineTable != null)\n                    SB.AppendLine(\"\\tScan Line Table = \" + ExtArea.ScanLineTable.Length);\n                else\n                    SB.AppendLine(\"\\tScan Line Table = null\");\n\n                if (ExtArea.PostageStampImage != null)\n                    SB.AppendLine(\"\\tPostage Stamp Image: \" + ExtArea.PostageStampImage.ToString());\n                else\n                    SB.AppendLine(\"\\tPostage Stamp Image = null\");\n\n                SB.AppendLine(\"\\tColor Correction Table = \" + (ExtArea.ColorCorrectionTable != null));\n            }\n            else\n                SB.AppendLine(\"\\tExtArea = null\");\n\n            SB.AppendLine(\"\\nFooter:\");\n            if (Footer != null)\n            {\n                SB.AppendLine(\"\\tExtension Area Offset = \" + Footer.ExtensionAreaOffset);\n                SB.AppendLine(\"\\tDeveloper Directory Offset = \" + Footer.DeveloperDirectoryOffset);\n                SB.AppendLine(\"\\tSignature (Full) = \\\"\" + Footer.Signature.ToString() +\n                    Footer.ReservedCharacter.ToString() + Footer.BinaryZeroStringTerminator.ToString() + \"\\\"\");\n            }\n            else\n                SB.AppendLine(\"\\tFooter = null\");\n\n            return SB.ToString();\n        }\n\n        /// <summary>\n        /// Check and update all fields with data length and offsets.\n        /// </summary>\n        /// <returns>Return \"true\", if all OK or \"false\", if checking failed.</returns>\n        public bool CheckAndUpdateOffsets(out string ErrorStr)\n        {\n            ErrorStr = String.Empty;\n\n            if (Header == null)\n            {\n                ErrorStr = \"Header = null\";\n                return false;\n            }\n\n            if (ImageOrColorMapArea == null)\n            {\n                ErrorStr = \"ImageOrColorMapArea = null\";\n                return false;\n            }\n\n            uint Offset = TgaHeader.Size; // Virtual Offset\n\n            #region Header\n            if (ImageOrColorMapArea.ImageID != null)\n            {\n                int StrMaxLen = 255;\n                if (ImageOrColorMapArea.ImageID.UseEndingChar)\n                    StrMaxLen--;\n\n                Header.IDLength = (byte)Math.Min(ImageOrColorMapArea.ImageID.OriginalString.Length, StrMaxLen);\n                ImageOrColorMapArea.ImageID.Length = Header.IDLength;\n                Offset += Header.IDLength;\n            }\n            else\n                Header.IDLength = 0;\n            #endregion\n\n            #region ColorMap\n            if (Header.ColorMapType != TgaColorMapType.NoColorMap)\n            {\n                if (Header.ColorMapSpec == null)\n                {\n                    ErrorStr = \"Header.ColorMapSpec = null\";\n                    return false;\n                }\n\n                if (Header.ColorMapSpec.ColorMapLength == 0)\n                {\n                    ErrorStr = \"Header.ColorMapSpec.ColorMapLength = 0\";\n                    return false;\n                }\n\n                if (ImageOrColorMapArea.ColorMapData == null)\n                {\n                    ErrorStr = \"ImageOrColorMapArea.ColorMapData = null\";\n                    return false;\n                }\n\n                int CmBytesPerPixel = (int)Math.Ceiling((double)Header.ColorMapSpec.ColorMapEntrySize / 8.0);\n                int LenBytes = Header.ColorMapSpec.ColorMapLength * CmBytesPerPixel;\n\n                if (LenBytes != ImageOrColorMapArea.ColorMapData.Length)\n                {\n                    ErrorStr = \"ImageOrColorMapArea.ColorMapData.Length has wrong size!\";\n                    return false;\n                }\n\n                Offset += (uint)ImageOrColorMapArea.ColorMapData.Length;\n            }\n            #endregion\n\n            #region Image Data\n            int BytesPerPixel = 0;\n            if (Header.ImageType != TgaImageType.NoImageData)\n            {\n                if (Header.ImageSpec == null)\n                {\n                    ErrorStr = \"Header.ImageSpec = null\";\n                    return false;\n                }\n\n                if (Header.ImageSpec.ImageWidth == 0 || Header.ImageSpec.ImageHeight == 0)\n                {\n                    ErrorStr = \"Header.ImageSpec.ImageWidth = 0 or Header.ImageSpec.ImageHeight = 0\";\n                    return false;\n                }\n\n                if (ImageOrColorMapArea.ImageData == null)\n                {\n                    ErrorStr = \"ImageOrColorMapArea.ImageData = null\";\n                    return false;\n                }\n\n                BytesPerPixel = (int)Math.Ceiling((double)Header.ImageSpec.PixelDepth / 8.0);\n                if (Width * Height * BytesPerPixel != ImageOrColorMapArea.ImageData.Length)\n                {\n                    ErrorStr = \"ImageOrColorMapArea.ImageData.Length has wrong size!\";\n                    return false;\n                }\n\n                if (Header.ImageType >= TgaImageType.RLE_ColorMapped &&\n                    Header.ImageType <= TgaImageType.RLE_BlackWhite)\n                {\n                    byte[] RLE = RLE_Encode(ImageOrColorMapArea.ImageData, Width, Height);\n                    if (RLE == null)\n                    {\n                        ErrorStr = \"RLE Compressing error! Check Image Data size.\";\n                        return false;\n                    }\n\n                    Offset += (uint)RLE.Length;\n                    RLE = null;\n                }\n                else\n                    Offset += (uint)ImageOrColorMapArea.ImageData.Length;\n            }\n            #endregion\n\n            #region Footer, DevArea, ExtArea\n            if (Footer != null)\n            {\n                #region DevArea\n                if (DevArea != null)\n                {\n                    int DevAreaCount = DevArea.Count;\n                    for (int i = 0; i < DevAreaCount; i++)\n                        if (DevArea[i] == null || DevArea[i].FieldSize <= 0) //Del Empty Entries\n                        {\n                            DevArea.Entries.RemoveAt(i);\n                            DevAreaCount--;\n                            i--;\n                        }\n\n                    if (DevArea.Count <= 0)\n                        Footer.DeveloperDirectoryOffset = 0;\n\n                    if (DevArea.Count > 2)\n                    {\n                        DevArea.Entries.Sort((a, b) => { return a.Tag.CompareTo(b.Tag); });\n                        for (int i = 0; i < DevArea.Count - 1; i++)\n                            if (DevArea[i].Tag == DevArea[i + 1].Tag)\n                            {\n                                ErrorStr = \"DevArea Enties has same Tags!\";\n                                return false;\n                            }\n                    }\n\n                    for (int i = 0; i < DevArea.Count; i++)\n                    {\n                        DevArea[i].Offset = Offset;\n                        Offset += (uint)DevArea[i].FieldSize;\n                    }\n\n                    Footer.DeveloperDirectoryOffset = Offset;\n                    Offset += (uint)(DevArea.Count * 10 + 2);\n                }\n                else\n                    Footer.DeveloperDirectoryOffset = 0;\n                #endregion\n\n                #region ExtArea\n                if (ExtArea != null)\n                {\n                    ExtArea.ExtensionSize = TgaExtArea.MinSize;\n                    if (ExtArea.OtherDataInExtensionArea != null)\n                        ExtArea.ExtensionSize += (ushort)ExtArea.OtherDataInExtensionArea.Length;\n\n                    ExtArea.DateTimeStamp = new TgaDateTime(DateTime.UtcNow);\n\n                    Footer.ExtensionAreaOffset = Offset;\n                    Offset += ExtArea.ExtensionSize;\n\n                    #region ScanLineTable\n                    if (ExtArea.ScanLineTable == null)\n                        ExtArea.ScanLineOffset = 0;\n                    else\n                    {\n                        if (ExtArea.ScanLineTable.Length != Height)\n                        {\n                            ErrorStr = \"ExtArea.ScanLineTable.Length != Height\";\n                            return false;\n                        }\n\n                        ExtArea.ScanLineOffset = Offset;\n                        Offset += (uint)(ExtArea.ScanLineTable.Length * 4);\n                    }\n                    #endregion\n\n                    #region PostageStampImage\n                    if (ExtArea.PostageStampImage == null)\n                        ExtArea.PostageStampOffset = 0;\n                    else\n                    {\n                        if (ExtArea.PostageStampImage.Width == 0 || ExtArea.PostageStampImage.Height == 0)\n                        {\n                            ErrorStr = \"ExtArea.PostageStampImage Width or Height is equal 0!\";\n                            return false;\n                        }\n\n                        if (ExtArea.PostageStampImage.Data == null)\n                        {\n                            ErrorStr = \"ExtArea.PostageStampImage.Data == null\";\n                            return false;\n                        }\n\n                        int PImgSB = ExtArea.PostageStampImage.Width * ExtArea.PostageStampImage.Height * BytesPerPixel;\n                        if (Header.ImageType != TgaImageType.NoImageData &&\n                            ExtArea.PostageStampImage.Data.Length != PImgSB)\n                        {\n                            ErrorStr = \"ExtArea.PostageStampImage.Data.Length is wrong!\";\n                            return false;\n                        }\n\n\n                        ExtArea.PostageStampOffset = Offset;\n                        Offset += (uint)(ExtArea.PostageStampImage.Data.Length);\n                    }\n                    #endregion\n\n                    #region ColorCorrectionTable\n                    if (ExtArea.ColorCorrectionTable == null)\n                        ExtArea.ColorCorrectionTableOffset = 0;\n                    else\n                    {\n                        if (ExtArea.ColorCorrectionTable.Length != 1024)\n                        {\n                            ErrorStr = \"ExtArea.ColorCorrectionTable.Length != 256 * 4\";\n                            return false;\n                        }\n\n                        ExtArea.ColorCorrectionTableOffset = Offset;\n                        Offset += (uint)(ExtArea.ColorCorrectionTable.Length * 2);\n                    }\n                    #endregion\n                }\n                else\n                    Footer.ExtensionAreaOffset = 0;\n                #endregion\n\n                #region Footer\n                if (Footer.ToBytes().Length != TgaFooter.Size)\n                {\n                    ErrorStr = \"Footer.Length is wrong!\";\n                    return false;\n                }\n\n                Offset += TgaFooter.Size;\n                #endregion\n            }\n            #endregion\n\n            return true;\n        }\n\n        #region Convert\n        /// <summary>\n        /// Convert <see cref=\"TGA\"/> to <see cref=\"Bitmap\"/>.\n        /// </summary>\n        /// <param name=\"ForceUseAlpha\">Force use alpha channel.</param>\n        /// <returns>Bitmap or null, on error.</returns>\n        public Bitmap ToBitmap(bool ForceUseAlpha = false)\n        {\n            return ToBitmapFunc(ForceUseAlpha, false);\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TGA\"/> to bytes array.\n        /// </summary>\n        /// <returns>Bytes array, (equal to saved file, but in memory) or null (on error).</returns>\n        public byte[] ToBytes()\n        {\n            try\n            {\n                byte[] Bytes;\n                using (MemoryStream ms = new MemoryStream())\n                {\n                    Save(ms);\n                    Bytes = ms.ToArray();\n                    ms.Flush();\n                }\n                return Bytes;\n            }\n            catch\n            {\n                return null;\n            }\n        }\n\n        /// <summary>\n        /// Convert TGA Image to new XFile format (v2.0).\n        /// </summary>\n        public void ToNewFormat()\n        {\n            if (Footer == null)\n                Footer = new TgaFooter();\n\n            if (ExtArea == null)\n            {\n                ExtArea = new TgaExtArea();\n\n                ExtArea.DateTimeStamp = new TgaDateTime(DateTime.UtcNow);\n\n                if (Header.ImageSpec.ImageDescriptor.AlphaChannelBits > 0)\n                    ExtArea.AttributesType = TgaAttrType.UsefulAlpha;\n                else\n                    ExtArea.AttributesType = TgaAttrType.NoAlpha;\n            }\n        }\n        #endregion\n\n        #region Private functions\n        bool LoadFunc(string filename)\n        {\n            if (!File.Exists(filename))\n                throw new FileNotFoundException(\"File: \\\"\" + filename + \"\\\" not found!\");\n\n            try\n            {\n                using (FileStream FS = new FileStream(filename, FileMode.Open, FileAccess.Read))\n                    return LoadFunc(FS);\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        bool LoadFunc(byte[] bytes)\n        {\n            if (bytes == null)\n                throw new ArgumentNullException();\n\n            try\n            {\n                using (MemoryStream FS = new MemoryStream(bytes, false))\n                    return LoadFunc(FS);\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        bool LoadFunc(Stream stream)\n        {\n            if (stream == null)\n                throw new ArgumentNullException();\n            if (!(stream.CanRead && stream.CanSeek))\n                throw new FileLoadException(\"Stream reading or seeking is not avaiable!\");\n\n            try\n            {\n                stream.Seek(0, SeekOrigin.Begin);\n                BinaryReader Br = new BinaryReader(stream);\n\n                Header = new TgaHeader(Br.ReadBytes(TgaHeader.Size));\n\n                if (Header.IDLength > 0)\n                    ImageOrColorMapArea.ImageID = new TgaString(Br.ReadBytes(Header.IDLength));\n\n                if (Header.ColorMapSpec.ColorMapLength > 0)\n                {\n                    int CmBytesPerPixel = (int)Math.Ceiling((double)Header.ColorMapSpec.ColorMapEntrySize / 8.0);\n                    int LenBytes = Header.ColorMapSpec.ColorMapLength * CmBytesPerPixel;\n                    ImageOrColorMapArea.ColorMapData = Br.ReadBytes(LenBytes);\n                }\n\n                #region Read Image Data\n                int BytesPerPixel = (int)Math.Ceiling((double)Header.ImageSpec.PixelDepth / 8.0);\n                if (Header.ImageType != TgaImageType.NoImageData)\n                {\n                    int ImageDataSize = Width * Height * BytesPerPixel;\n                    switch (Header.ImageType)\n                    {\n                        case TgaImageType.RLE_ColorMapped:\n                        case TgaImageType.RLE_TrueColor:\n                        case TgaImageType.RLE_BlackWhite:\n\n                            int DataOffset = 0;\n                            byte PacketInfo;\n                            int PacketCount;\n                            byte[] RLE_Bytes, RLE_Part;\n                            ImageOrColorMapArea.ImageData = new byte[ImageDataSize];\n\n                            do\n                            {\n                                PacketInfo = Br.ReadByte(); //1 type bit and 7 count bits. Len = Count + 1.\n                                PacketCount = (PacketInfo & 127) + 1;\n\n                                if (PacketInfo >= 128) // bit7 = 1, RLE\n                                {\n                                    RLE_Bytes = new byte[PacketCount * BytesPerPixel];\n                                    RLE_Part = Br.ReadBytes(BytesPerPixel);\n                                    for (int i = 0; i < RLE_Bytes.Length; i++)\n                                        RLE_Bytes[i] = RLE_Part[i % BytesPerPixel];\n                                }\n                                else // RAW format\n                                    RLE_Bytes = Br.ReadBytes(PacketCount * BytesPerPixel);\n\n                                Buffer.BlockCopy(RLE_Bytes, 0, ImageOrColorMapArea.ImageData, DataOffset, RLE_Bytes.Length);\n                                DataOffset += RLE_Bytes.Length;\n                            }\n                            while (DataOffset < ImageDataSize);\n                            RLE_Bytes = null;\n                            break;\n\n                        case TgaImageType.Uncompressed_ColorMapped:\n                        case TgaImageType.Uncompressed_TrueColor:\n                        case TgaImageType.Uncompressed_BlackWhite:\n                            ImageOrColorMapArea.ImageData = Br.ReadBytes(ImageDataSize);\n                            break;\n                    }\n                }\n                #endregion\n\n                #region Try parse Footer\n                stream.Seek(-TgaFooter.Size, SeekOrigin.End);\n                uint FooterOffset = (uint)stream.Position;\n                TgaFooter MbFooter = new TgaFooter(Br.ReadBytes(TgaFooter.Size));\n                if (MbFooter.IsFooterCorrect)\n                {\n                    Footer = MbFooter;\n                    uint DevDirOffset = Footer.DeveloperDirectoryOffset;\n                    uint ExtAreaOffset = Footer.ExtensionAreaOffset;\n\n                    #region If Dev Area exist, read it.\n                    if (DevDirOffset != 0)\n                    {\n                        stream.Seek(DevDirOffset, SeekOrigin.Begin);\n                        DevArea = new TgaDevArea();\n                        uint NumberOfTags = Br.ReadUInt16();\n\n                        ushort[] Tags = new ushort[NumberOfTags];\n                        uint[] TagOffsets = new uint[NumberOfTags];\n                        uint[] TagSizes = new uint[NumberOfTags];\n\n                        for (int i = 0; i < NumberOfTags; i++)\n                        {\n                            Tags[i] = Br.ReadUInt16();\n                            TagOffsets[i] = Br.ReadUInt32();\n                            TagSizes[i] = Br.ReadUInt32();\n                        }\n\n                        for (int i = 0; i < NumberOfTags; i++)\n                        {\n                            stream.Seek(TagOffsets[i], SeekOrigin.Begin);\n                            var Ent = new TgaDevEntry(Tags[i], TagOffsets[i], Br.ReadBytes((int)TagSizes[i]));\n                            DevArea.Entries.Add(Ent);\n                        }\n\n                        Tags = null;\n                        TagOffsets = null;\n                        TagSizes = null;\n                    }\n                    #endregion\n\n                    #region If Ext Area exist, read it.\n                    if (ExtAreaOffset != 0)\n                    {\n                        stream.Seek(ExtAreaOffset, SeekOrigin.Begin);\n                        ushort ExtAreaSize = Math.Max((ushort)TgaExtArea.MinSize, Br.ReadUInt16());\n                        stream.Seek(ExtAreaOffset, SeekOrigin.Begin);\n                        ExtArea = new TgaExtArea(Br.ReadBytes(ExtAreaSize));\n\n                        if (ExtArea.ScanLineOffset > 0)\n                        {\n                            stream.Seek(ExtArea.ScanLineOffset, SeekOrigin.Begin);\n                            ExtArea.ScanLineTable = new uint[Height];\n                            for (int i = 0; i < ExtArea.ScanLineTable.Length; i++)\n                                ExtArea.ScanLineTable[i] = Br.ReadUInt32();\n                        }\n\n                        if (ExtArea.PostageStampOffset > 0)\n                        {\n                            stream.Seek(ExtArea.PostageStampOffset, SeekOrigin.Begin);\n                            byte W = Br.ReadByte();\n                            byte H = Br.ReadByte();\n                            int ImgDataSize = W * H * BytesPerPixel;\n                            if (ImgDataSize > 0)\n                                ExtArea.PostageStampImage = new TgaPostageStampImage(W, H, Br.ReadBytes(ImgDataSize));\n                        }\n\n                        if (ExtArea.ColorCorrectionTableOffset > 0)\n                        {\n                            stream.Seek(ExtArea.ColorCorrectionTableOffset, SeekOrigin.Begin);\n                            ExtArea.ColorCorrectionTable = new ushort[256 * 4];\n                            for (int i = 0; i < ExtArea.ColorCorrectionTable.Length; i++)\n                                ExtArea.ColorCorrectionTable[i] = Br.ReadUInt16();\n                        }\n                    }\n                    #endregion\n                }\n                #endregion\n\n                Br.Close();\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        bool LoadFunc(Bitmap bmp, bool UseRLE = false, bool NewFormat = true, bool ColorMap2BytesEntry = false)\n        {\n            if (bmp == null)\n                throw new ArgumentNullException();\n\n            try\n            {\n                Header.ImageSpec.ImageWidth = (ushort)bmp.Width;\n                Header.ImageSpec.ImageHeight = (ushort)bmp.Height;\n                Header.ImageSpec.ImageDescriptor.ImageOrigin = TgaImgOrigin.TopLeft;\n\n                switch (bmp.PixelFormat)\n                {\n                    case PixelFormat.Indexed:\n                    case PixelFormat.Gdi:\n                    case PixelFormat.Alpha:\n                    case PixelFormat.Undefined:\n                    case PixelFormat.PAlpha:\n                    case PixelFormat.Extended:\n                    case PixelFormat.Max:\n                    case PixelFormat.Canonical:\n                    case PixelFormat.Format16bppRgb565:\n                    default:\n                        throw new FormatException(nameof(PixelFormat) + \" is not supported!\");\n\n                    case PixelFormat.Format1bppIndexed:\n                    case PixelFormat.Format4bppIndexed:\n                    case PixelFormat.Format8bppIndexed:\n                    case PixelFormat.Format16bppGrayScale:\n                    case PixelFormat.Format16bppRgb555:\n                    case PixelFormat.Format16bppArgb1555:\n                    case PixelFormat.Format24bppRgb:\n                    case PixelFormat.Format32bppRgb:\n                    case PixelFormat.Format32bppArgb:\n                    case PixelFormat.Format32bppPArgb:\n                    case PixelFormat.Format48bppRgb:\n                    case PixelFormat.Format64bppArgb:\n                    case PixelFormat.Format64bppPArgb:\n\n                        int bpp = Math.Max(8, Image.GetPixelFormatSize(bmp.PixelFormat));\n                        int BytesPP = bpp / 8;\n\n                        if (bmp.PixelFormat == PixelFormat.Format16bppRgb555)\n                            bpp = 15;\n\n                        bool IsAlpha = Image.IsAlphaPixelFormat(bmp.PixelFormat);\n                        bool IsPreAlpha = IsAlpha && bmp.PixelFormat.ToString().EndsWith(\"PArgb\");\n                        bool IsColorMapped = bmp.PixelFormat.ToString().EndsWith(\"Indexed\");\n\n                        Header.ImageSpec.PixelDepth = (TgaPixelDepth)(BytesPP * 8);\n\n                        if (IsAlpha)\n                        {\n                            Header.ImageSpec.ImageDescriptor.AlphaChannelBits = (byte)(BytesPP * 2);\n\n                            if (bmp.PixelFormat == PixelFormat.Format16bppArgb1555)\n                                Header.ImageSpec.ImageDescriptor.AlphaChannelBits = 1;\n                        }\n\n                        #region ColorMap\n                        bool IsGrayImage = (bmp.PixelFormat == PixelFormat.Format16bppGrayScale | IsColorMapped);\n\n                        if (IsColorMapped && bmp.Palette != null)\n                        {\n                            Color[] Colors = bmp.Palette.Entries;\n\n                            #region Analyze ColorMapType\n                            int AlphaSum = 0;\n                            bool ColorMapUseAlpha = false;\n\n                            for (int i = 0; i < Colors.Length; i++)\n                            {\n                                IsGrayImage &= (Colors[i].R == Colors[i].G && Colors[i].G == Colors[i].B);\n                                ColorMapUseAlpha |= (Colors[i].A < 248);\n                                AlphaSum |= Colors[i].A;\n                            }\n                            ColorMapUseAlpha &= (AlphaSum > 0);\n\n                            int CMapBpp = (ColorMap2BytesEntry ? 15 : 24) + (ColorMapUseAlpha ? (ColorMap2BytesEntry ? 1 : 8) : 0);\n                            int CMBytesPP = (int)Math.Ceiling(CMapBpp / 8.0);\n                            #endregion\n\n                            Header.ColorMapSpec.ColorMapLength = Math.Min((ushort)Colors.Length, ushort.MaxValue);\n                            Header.ColorMapSpec.ColorMapEntrySize = (TgaColorMapEntrySize)CMapBpp;\n                            ImageOrColorMapArea.ColorMapData = new byte[Header.ColorMapSpec.ColorMapLength * CMBytesPP];\n\n                            byte[] CMapEntry = new byte[CMBytesPP];\n\n                            const float To5Bit = 32f / 256f; // Scale value from 8 to 5 bits.\n                            for (int i = 0; i < Colors.Length; i++)\n                            {\n                                switch (Header.ColorMapSpec.ColorMapEntrySize)\n                                {\n                                    case TgaColorMapEntrySize.A1R5G5B5:\n                                    case TgaColorMapEntrySize.X1R5G5B5:\n                                        int R = (int)(Colors[i].R * To5Bit);\n                                        int G = (int)(Colors[i].G * To5Bit) << 5;\n                                        int B = (int)(Colors[i].B * To5Bit) << 10;\n                                        int A = 0;\n\n                                        if (Header.ColorMapSpec.ColorMapEntrySize == TgaColorMapEntrySize.A1R5G5B5)\n                                            A = ((Colors[i].A & 0x80) << 15);\n\n                                        CMapEntry = BitConverter.GetBytes(A | R | G | B);\n                                        break;\n\n                                    case TgaColorMapEntrySize.R8G8B8:\n                                        CMapEntry[0] = Colors[i].B;\n                                        CMapEntry[1] = Colors[i].G;\n                                        CMapEntry[2] = Colors[i].R;\n                                        break;\n\n                                    case TgaColorMapEntrySize.A8R8G8B8:\n                                        CMapEntry[0] = Colors[i].B;\n                                        CMapEntry[1] = Colors[i].G;\n                                        CMapEntry[2] = Colors[i].R;\n                                        CMapEntry[3] = Colors[i].A;\n                                        break;\n\n                                    case TgaColorMapEntrySize.Other:\n                                    default:\n                                        break;\n                                }\n\n                                Buffer.BlockCopy(CMapEntry, 0, ImageOrColorMapArea.ColorMapData, i * CMBytesPP, CMBytesPP);\n                            }\n                        }\n                        #endregion\n\n                        #region ImageType\n                        if (UseRLE)\n                        {\n                            if (IsGrayImage)\n                                Header.ImageType = TgaImageType.RLE_BlackWhite;\n                            else if (IsColorMapped)\n                                Header.ImageType = TgaImageType.RLE_ColorMapped;\n                            else\n                                Header.ImageType = TgaImageType.RLE_TrueColor;\n                        }\n                        else\n                        {\n                            if (IsGrayImage)\n                                Header.ImageType = TgaImageType.Uncompressed_BlackWhite;\n                            else if (IsColorMapped)\n                                Header.ImageType = TgaImageType.Uncompressed_ColorMapped;\n                            else\n                                Header.ImageType = TgaImageType.Uncompressed_TrueColor;\n                        }\n\n                        Header.ColorMapType = (IsColorMapped ? TgaColorMapType.ColorMap : TgaColorMapType.NoColorMap);\n                        #endregion\n\n                        #region NewFormat\n                        if (NewFormat)\n                        {\n                            Footer = new TgaFooter();\n                            ExtArea = new TgaExtArea();\n                            ExtArea.DateTimeStamp = new TgaDateTime(DateTime.UtcNow);\n\n                            if (IsAlpha)\n                            {\n                                ExtArea.AttributesType = TgaAttrType.UsefulAlpha;\n\n                                if (IsPreAlpha)\n                                    ExtArea.AttributesType = TgaAttrType.PreMultipliedAlpha;\n                            }\n                            else\n                            {\n                                ExtArea.AttributesType = TgaAttrType.NoAlpha;\n\n                                if (Header.ImageSpec.ImageDescriptor.AlphaChannelBits > 0)\n                                    ExtArea.AttributesType = TgaAttrType.UndefinedAlphaButShouldBeRetained;\n                            }\n                        }\n                        #endregion\n\n                        #region Bitmap width is aligned by 32 bits = 4 bytes! Delete it.\n                        int StrideBytes = bmp.Width * BytesPP;\n                        int PaddingBytes = (int)Math.Ceiling(StrideBytes / 4.0) * 4 - StrideBytes;\n\n                        byte[] ImageData = new byte[(StrideBytes + PaddingBytes) * bmp.Height];\n\n                        Rectangle Re = new Rectangle(0, 0, bmp.Width, bmp.Height);\n                        BitmapData BmpData = bmp.LockBits(Re, ImageLockMode.ReadOnly, bmp.PixelFormat);\n                        Marshal.Copy(BmpData.Scan0, ImageData, 0, ImageData.Length);\n                        bmp.UnlockBits(BmpData);\n                        BmpData = null;\n\n                        if (PaddingBytes > 0) //Need delete bytes align\n                        {\n                            ImageOrColorMapArea.ImageData = new byte[StrideBytes * bmp.Height];\n                            for (int i = 0; i < bmp.Height; i++)\n                                Buffer.BlockCopy(ImageData, i * (StrideBytes + PaddingBytes),\n                                    ImageOrColorMapArea.ImageData, i * StrideBytes, StrideBytes);\n                        }\n                        else\n                            ImageOrColorMapArea.ImageData = ImageData;\n\n                        ImageData = null;\n\n                        // Not official supported, but works (tested on 16bpp GrayScale test images)!\n                        if (bmp.PixelFormat == PixelFormat.Format16bppGrayScale)\n                        {\n                            for (long i = 0; i < ImageOrColorMapArea.ImageData.Length; i++)\n                                ImageOrColorMapArea.ImageData[i] ^= byte.MaxValue;\n                        }\n                        #endregion\n\n                        break;\n                }\n\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        bool SaveFunc(Stream stream)\n        {\n            try\n            {\n                if (stream == null)\n                    throw new ArgumentNullException();\n                if (!(stream.CanWrite && stream.CanSeek))\n                    throw new FileLoadException(\"Stream writing or seeking is not avaiable!\");\n\n                string CheckResult;\n                if (!CheckAndUpdateOffsets(out CheckResult))\n                    return false;\n\n                BinaryWriter Bw = new BinaryWriter(stream);\n                Bw.Write(Header.ToBytes());\n\n                if (ImageOrColorMapArea.ImageID != null)\n                    Bw.Write(ImageOrColorMapArea.ImageID.ToBytes());\n\n                if (Header.ColorMapType != TgaColorMapType.NoColorMap)\n                    Bw.Write(ImageOrColorMapArea.ColorMapData);\n\n                #region ImageData\n                if (Header.ImageType != TgaImageType.NoImageData)\n                {\n                    if (Header.ImageType >= TgaImageType.RLE_ColorMapped &&\n                        Header.ImageType <= TgaImageType.RLE_BlackWhite)\n                        Bw.Write(RLE_Encode(ImageOrColorMapArea.ImageData, Width, Height));\n                    else\n                        Bw.Write(ImageOrColorMapArea.ImageData);\n                }\n                #endregion\n\n                #region Footer\n                if (Footer != null)\n                {\n                    #region DevArea\n                    if (DevArea != null)\n                    {\n                        for (int i = 0; i < DevArea.Count; i++)\n                            Bw.Write(DevArea[i].Data);\n\n                        Bw.Write((ushort)DevArea.Count);\n\n                        for (int i = 0; i < DevArea.Count; i++)\n                        {\n                            Bw.Write(DevArea[i].Tag);\n                            Bw.Write(DevArea[i].Offset);\n                            Bw.Write(DevArea[i].FieldSize);\n                        }\n                    }\n                    #endregion\n\n                    #region ExtArea\n                    if (ExtArea != null)\n                    {\n                        Bw.Write(ExtArea.ToBytes());\n\n                        if (ExtArea.ScanLineTable != null)\n                            for (int i = 0; i < ExtArea.ScanLineTable.Length; i++)\n                                Bw.Write(ExtArea.ScanLineTable[i]);\n\n                        if (ExtArea.PostageStampImage != null)\n                            Bw.Write(ExtArea.PostageStampImage.ToBytes());\n\n                        if (ExtArea.ColorCorrectionTable != null)\n                            for (int i = 0; i < ExtArea.ColorCorrectionTable.Length; i++)\n                                Bw.Write(ExtArea.ColorCorrectionTable[i]);\n                    }\n                    #endregion\n\n                    Bw.Write(Footer.ToBytes());\n                }\n                #endregion\n\n                Bw.Flush();\n                stream.Flush();\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Encode image with RLE compression (used RLE per line)!\n        /// </summary>\n        /// <param name=\"ImageData\">Image data, bytes array with size = Width * Height * BytesPerPixel.</param>\n        /// <param name=\"Width\">Image Width, must be > 0.</param>\n        /// <param name=\"Height\">Image Height, must be > 0.</param>\n        /// <returns>Bytes array with RLE compressed image data.</returns>\n        byte[] RLE_Encode(byte[] ImageData, int Width, int Height)\n        {\n            if (ImageData == null)\n                throw new ArgumentNullException(nameof(ImageData) + \"in null!\");\n\n            if (Width <= 0 || Height <= 0)\n                throw new ArgumentOutOfRangeException(nameof(Width) + \" and \" + nameof(Height) + \" must be > 0!\");\n\n            int Bpp = ImageData.Length / Width / Height; // Bytes per pixel\n            int ScanLineSize = Width * Bpp;\n\n            if (ScanLineSize * Height != ImageData.Length)\n                throw new ArgumentOutOfRangeException(\"ImageData has wrong Length!\");\n\n            try\n            {\n                int Count = 0;\n                int Pos = 0;\n                bool IsRLE = false;\n                List<byte> Encoded = new List<byte>();\n                byte[] RowData = new byte[ScanLineSize];\n\n                for (int y = 0; y < Height; y++)\n                {\n                    Pos = 0;\n                    Buffer.BlockCopy(ImageData, y * ScanLineSize, RowData, 0, ScanLineSize);\n\n                    while (Pos < ScanLineSize)\n                    {\n                        if (Pos >= ScanLineSize - Bpp)\n                        {\n                            Encoded.Add(0);\n                            Encoded.AddRange(BitConverterExt.GetElements(RowData, Pos, Bpp));\n                            Pos += Bpp;\n                            break;\n                        }\n\n                        Count = 0; //1\n                        IsRLE = BitConverterExt.IsElementsEqual(RowData, Pos, Pos + Bpp, Bpp);\n\n                        for (int i = Pos + Bpp; i < Math.Min(Pos + 128 * Bpp, ScanLineSize) - Bpp; i += Bpp)\n                        {\n                            if (IsRLE ^ BitConverterExt.IsElementsEqual(RowData, (IsRLE ? Pos : i), i + Bpp, Bpp))\n                            {\n                                //Count--;\n                                break;\n                            }\n                            else\n                                Count++;\n                        }\n\n                        int CountBpp = (Count + 1) * Bpp;\n                        Encoded.Add((byte)(IsRLE ? Count | 128 : Count));\n                        Encoded.AddRange(BitConverterExt.GetElements(RowData, Pos, (IsRLE ? Bpp : CountBpp)));\n                        Pos += CountBpp;\n                    }\n                }\n\n                return Encoded.ToArray();\n            }\n            catch\n            {\n                return null;\n            }\n        }\n\n        /// <summary>\n        /// Convert <see cref=\"TGA\"/> to <see cref=\"Bitmap\"/>.\n        /// </summary>\n        /// <param name=\"ForceUseAlpha\">Force use alpha channel.</param>\n        /// <param name=\"PostageStampImage\">Get Postage Stamp Image (Thumb) or get main image?</param>\n        /// <returns>Bitmap or null, on error.</returns>\n        Bitmap ToBitmapFunc(bool ForceUseAlpha = false, bool PostageStampImage = false)\n        {\n            try\n            {\n                #region UseAlpha?\n                bool UseAlpha = true;\n                if (ExtArea != null)\n                {\n                    switch (ExtArea.AttributesType)\n                    {\n                        case TgaAttrType.NoAlpha:\n                        case TgaAttrType.UndefinedAlphaCanBeIgnored:\n                        case TgaAttrType.UndefinedAlphaButShouldBeRetained:\n                            UseAlpha = false;\n                            break;\n                        case TgaAttrType.UsefulAlpha:\n                        case TgaAttrType.PreMultipliedAlpha:\n                        default:\n                            break;\n                    }\n                }\n                UseAlpha = (Header.ImageSpec.ImageDescriptor.AlphaChannelBits > 0 && UseAlpha) | ForceUseAlpha;\n                #endregion\n\n                #region IsGrayImage\n                bool IsGrayImage = Header.ImageType == TgaImageType.RLE_BlackWhite ||\n                    Header.ImageType == TgaImageType.Uncompressed_BlackWhite;\n                #endregion\n\n                #region Get PixelFormat\n                PixelFormat PixFormat = PixelFormat.Format24bppRgb;\n\n                switch (Header.ImageSpec.PixelDepth)\n                {\n                    case TgaPixelDepth.Bpp8:\n                        PixFormat = PixelFormat.Format8bppIndexed;\n                        break;\n\n                    case TgaPixelDepth.Bpp16:\n                        if (IsGrayImage)\n                            PixFormat = PixelFormat.Format16bppGrayScale;\n                        else\n                            PixFormat = (UseAlpha ? PixelFormat.Format16bppArgb1555 : PixelFormat.Format16bppRgb555);\n                        break;\n\n                    case TgaPixelDepth.Bpp24:\n                        PixFormat = PixelFormat.Format24bppRgb;\n                        break;\n\n                    case TgaPixelDepth.Bpp32:\n                        if (UseAlpha)\n                        {\n                            var f = Footer;\n                            if (ExtArea?.AttributesType == TgaAttrType.PreMultipliedAlpha)\n                                PixFormat = PixelFormat.Format32bppPArgb;\n                            else\n                                PixFormat = PixelFormat.Format32bppArgb;\n                        }\n                        else\n                            PixFormat = PixelFormat.Format32bppRgb;\n                        break;\n\n                    default:\n                        PixFormat = PixelFormat.Undefined;\n                        break;\n                }\n                #endregion\n\n                ushort BMP_Width = (PostageStampImage ? ExtArea.PostageStampImage.Width : Width);\n                ushort BMP_Height = (PostageStampImage ? ExtArea.PostageStampImage.Height : Height);\n                Bitmap BMP = new Bitmap(BMP_Width, BMP_Height, PixFormat);\n\n                #region ColorMap and GrayPalette\n                if (Header.ColorMapType == TgaColorMapType.ColorMap &&\n                   (Header.ImageType == TgaImageType.RLE_ColorMapped ||\n                    Header.ImageType == TgaImageType.Uncompressed_ColorMapped))\n                {\n\n                    ColorPalette ColorMap = BMP.Palette;\n                    Color[] CMapColors = ColorMap.Entries;\n\n                    switch (Header.ColorMapSpec.ColorMapEntrySize)\n                    {\n                        case TgaColorMapEntrySize.X1R5G5B5:\n                        case TgaColorMapEntrySize.A1R5G5B5:\n                            const float To8Bit = 255f / 31f; // Scale value from 5 to 8 bits.\n                            for (int i = 0; i < Math.Min(CMapColors.Length, Header.ColorMapSpec.ColorMapLength); i++)\n                            {\n                                ushort A1R5G5B5 = BitConverter.ToUInt16(ImageOrColorMapArea.ColorMapData, i * 2);\n                                int A = (UseAlpha ? (A1R5G5B5 & 0x8000) >> 15 : 1) * 255; // (0 or 1) * 255\n                                int R = (int)(((A1R5G5B5 & 0x7C00) >> 10) * To8Bit);\n                                int G = (int)(((A1R5G5B5 & 0x3E0) >> 5) * To8Bit);\n                                int B = (int)((A1R5G5B5 & 0x1F) * To8Bit);\n                                CMapColors[i] = Color.FromArgb(A, R, G, B);\n                            }\n                            break;\n\n                        case TgaColorMapEntrySize.R8G8B8:\n                            for (int i = 0; i < Math.Min(CMapColors.Length, Header.ColorMapSpec.ColorMapLength); i++)\n                            {\n                                int Index = i * 3; //RGB = 3 bytes\n                                int R = ImageOrColorMapArea.ColorMapData[Index + 2];\n                                int G = ImageOrColorMapArea.ColorMapData[Index + 1];\n                                int B = ImageOrColorMapArea.ColorMapData[Index];\n                                CMapColors[i] = Color.FromArgb(R, G, B);\n                            }\n                            break;\n\n                        case TgaColorMapEntrySize.A8R8G8B8:\n                            for (int i = 0; i < Math.Min(CMapColors.Length, Header.ColorMapSpec.ColorMapLength); i++)\n                            {\n                                int ARGB = BitConverter.ToInt32(ImageOrColorMapArea.ColorMapData, i * 4);\n                                CMapColors[i] = Color.FromArgb(UseAlpha ? ARGB | (0xFF << 24) : ARGB);\n                            }\n                            break;\n\n                        default:\n                            ColorMap = null;\n                            break;\n                    }\n\n                    if (ColorMap != null)\n                        BMP.Palette = ColorMap;\n                }\n\n                if (PixFormat == PixelFormat.Format8bppIndexed && IsGrayImage)\n                {\n                    ColorPalette GrayPalette = BMP.Palette;\n                    Color[] GrayColors = GrayPalette.Entries;\n                    for (int i = 0; i < GrayColors.Length; i++)\n                        GrayColors[i] = Color.FromArgb(i, i, i);\n                    BMP.Palette = GrayPalette;\n                }\n                #endregion\n\n                #region Bitmap width must by aligned (align value = 32 bits = 4 bytes)!\n                byte[] ImageData;\n                int BytesPerPixel = (int)Math.Ceiling((double)Header.ImageSpec.PixelDepth / 8.0);\n                int StrideBytes = BMP.Width * BytesPerPixel;\n                int PaddingBytes = (int)Math.Ceiling(StrideBytes / 4.0) * 4 - StrideBytes;\n\n                if (PaddingBytes > 0) //Need bytes align\n                {\n                    ImageData = new byte[(StrideBytes + PaddingBytes) * BMP.Height];\n                    for (int i = 0; i < BMP.Height; i++)\n                        Buffer.BlockCopy(PostageStampImage ? ExtArea.PostageStampImage.Data :\n                            ImageOrColorMapArea.ImageData, i * StrideBytes, ImageData,\n                            i * (StrideBytes + PaddingBytes), StrideBytes);\n                }\n                else\n                    ImageData = BitConverterExt.ToBytes(PostageStampImage ? ExtArea.PostageStampImage.Data :\n                        ImageOrColorMapArea.ImageData);\n\n                // Not official supported, but works (tested on 2 test images)!\n                if (PixFormat == PixelFormat.Format16bppGrayScale)\n                {\n                    for (long i = 0; i < ImageData.Length; i++)\n                        ImageData[i] ^= byte.MaxValue;\n                }\n                #endregion\n\n                Rectangle Re = new Rectangle(0, 0, BMP.Width, BMP.Height);\n                BitmapData BmpData = BMP.LockBits(Re, ImageLockMode.WriteOnly, BMP.PixelFormat);\n                Marshal.Copy(ImageData, 0, BmpData.Scan0, ImageData.Length);\n                BMP.UnlockBits(BmpData);\n                ImageData = null;\n                BmpData = null;\n\n                if (ExtArea != null && ExtArea.KeyColor.ToInt() != 0)\n                    BMP.MakeTransparent(ExtArea.KeyColor.ToColor());\n\n                #region Flip Image\n                switch (Header.ImageSpec.ImageDescriptor.ImageOrigin)\n                {\n                    case TgaImgOrigin.BottomLeft:\n                        BMP.RotateFlip(RotateFlipType.RotateNoneFlipY);\n                        break;\n                    case TgaImgOrigin.BottomRight:\n                        BMP.RotateFlip(RotateFlipType.RotateNoneFlipXY);\n                        break;\n                    case TgaImgOrigin.TopLeft:\n                    default:\n                        break;\n                    case TgaImgOrigin.TopRight:\n                        BMP.RotateFlip(RotateFlipType.RotateNoneFlipX);\n                        break;\n                }\n                #endregion\n\n                return BMP;\n            }\n            catch\n            {\n                return null;\n            }\n        }\n        #endregion\n\n        #region Explicit\n        public static explicit operator Bitmap(TGA tga)\n        {\n            return tga.ToBitmap();\n        }\n\n        public static explicit operator TGA(Bitmap bmp)\n        {\n            return FromBitmap(bmp);\n        }\n        #endregion\n\n        #region PostageStamp Image\n        /// <summary>\n        /// Convert <see cref=\"TgaPostageStampImage\"/> to <see cref=\"Bitmap\"/>.\n        /// </summary>\n        /// <param name=\"ForceUseAlpha\">Force use alpha channel.</param>\n        /// <returns>Bitmap or null.</returns>\n        public Bitmap GetPostageStampImage(bool ForceUseAlpha = false)\n        {\n            if (ExtArea == null || ExtArea.PostageStampImage == null || ExtArea.PostageStampImage.Data == null ||\n                ExtArea.PostageStampImage.Width <= 0 || ExtArea.PostageStampImage.Height <= 0)\n                return null;\n\n            return ToBitmapFunc(ForceUseAlpha, true);\n        }\n\n        /// <summary>\n        /// Update Postage Stamp Image or set it.\n        /// </summary>\n        public void UpdatePostageStampImage()\n        {\n            if (Header.ImageType == TgaImageType.NoImageData)\n            {\n                if (ExtArea != null)\n                    ExtArea.PostageStampImage = null;\n                return;\n            }\n\n            ToNewFormat();\n            if (ExtArea.PostageStampImage == null)\n                ExtArea.PostageStampImage = new TgaPostageStampImage();\n\n            int PS_Width = Header.ImageSpec.ImageWidth;\n            int PS_Height = Header.ImageSpec.ImageHeight;\n\n            if (Width > 64 || Height > 64)\n            {\n                float AspectRatio = Width / (float)Height;\n                PS_Width = (byte)(64f * (AspectRatio < 1f ? AspectRatio : 1f));\n                PS_Height = (byte)(64f / (AspectRatio > 1f ? AspectRatio : 1f));\n            }\n            PS_Width = Math.Max(PS_Width, 4);\n            PS_Height = Math.Max(PS_Height, 4);\n\n            ExtArea.PostageStampImage.Width = (byte)PS_Width;\n            ExtArea.PostageStampImage.Height = (byte)PS_Height;\n\n            int BytesPerPixel = (int)Math.Ceiling((double)Header.ImageSpec.PixelDepth / 8.0);\n            ExtArea.PostageStampImage.Data = new byte[PS_Width * PS_Height * BytesPerPixel];\n\n            float WidthCoef = Width / (float)PS_Width;\n            float HeightCoef = Height / (float)PS_Height;\n\n            for (int y = 0; y < PS_Height; y++)\n            {\n                int Y_Offset = (int)(y * HeightCoef) * Width * BytesPerPixel;\n                int y_Offset = y * PS_Width * BytesPerPixel;\n\n                for (int x = 0; x < PS_Width; x++)\n                {\n                    Buffer.BlockCopy(ImageOrColorMapArea.ImageData, Y_Offset + (int)(x * WidthCoef) * BytesPerPixel,\n                        ExtArea.PostageStampImage.Data, y_Offset + x * BytesPerPixel, BytesPerPixel);\n                }\n            }\n        }\n\n        public void DeletePostageStampImage()\n        {\n            if (ExtArea != null)\n                ExtArea.PostageStampImage = null;\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/TeamColor.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Drawing;\nusing System.Numerics;\nusing System.Xml;\n\nnamespace MobiusEditor.Utility\n{\n    public class TeamColor\n    {\n        private readonly TeamColorManager teamColorManager;\n        private readonly MegafileManager megafileManager;\n\n        public string Variant { get; private set; }\n\n        public string Name { get; private set; }\n\n        private Color? lowerBounds;\n        public Color LowerBounds => lowerBounds.HasValue ? lowerBounds.Value : ((Variant != null) ? teamColorManager[Variant].LowerBounds : default);\n\n        private Color? upperBounds;\n        public Color UpperBounds => upperBounds.HasValue ? upperBounds.Value : ((Variant != null) ? teamColorManager[Variant].UpperBounds : default);\n\n        private float? fudge;\n        public float Fudge => fudge.HasValue ? fudge.Value : ((Variant != null) ? teamColorManager[Variant].Fudge : default);\n\n        private Vector3? hsvShift;\n        public Vector3 HSVShift => hsvShift.HasValue ? hsvShift.Value : ((Variant != null) ? teamColorManager[Variant].HSVShift : default);\n\n        private Vector3? inputLevels;\n        public Vector3 InputLevels => inputLevels.HasValue ? inputLevels.Value : ((Variant != null) ? teamColorManager[Variant].InputLevels : default);\n\n        private Vector2? outputLevels;\n        public Vector2 OutputLevels => outputLevels.HasValue ? outputLevels.Value : ((Variant != null) ? teamColorManager[Variant].OutputLevels : default);\n\n        private Vector3? overallInputLevels;\n        public Vector3 OverallInputLevels => overallInputLevels.HasValue ? overallInputLevels.Value : ((Variant != null) ? teamColorManager[Variant].OverallInputLevels : default);\n\n        private Vector2? overallOutputLevels;\n        public Vector2 OverallOutputLevels => overallOutputLevels.HasValue ? overallOutputLevels.Value : ((Variant != null) ? teamColorManager[Variant].OverallOutputLevels : default);\n\n        private Color? radarMapColor;\n        public Color RadarMapColor => radarMapColor.HasValue ? radarMapColor.Value : ((Variant != null) ? teamColorManager[Variant].RadarMapColor : default);\n\n        public TeamColor(TeamColorManager teamColorManager, MegafileManager megafileManager)\n        {\n            this.teamColorManager = teamColorManager;\n            this.megafileManager = megafileManager;\n        }\n\n        public void Load(string xml)\n        {\n            XmlDocument xmlDoc = new XmlDocument();\n            xmlDoc.LoadXml(xml);\n\n            var node = xmlDoc.FirstChild;\n            Name = node.Attributes[\"Name\"].Value;\n            Variant = node.Attributes[\"Variant\"]?.Value;\n\n            var lowerBoundsNode = node.SelectSingleNode(\"LowerBounds\");\n            if (lowerBoundsNode != null)\n            {\n                lowerBounds = Color.FromArgb(\n                    (int)(float.Parse(lowerBoundsNode.SelectSingleNode(\"R\").InnerText) * 255),\n                    (int)(float.Parse(lowerBoundsNode.SelectSingleNode(\"G\").InnerText) * 255),\n                    (int)(float.Parse(lowerBoundsNode.SelectSingleNode(\"B\").InnerText) * 255)\n                );\n            }\n\n            var upperBoundsNode = node.SelectSingleNode(\"UpperBounds\");\n            if (upperBoundsNode != null)\n            {\n                upperBounds = Color.FromArgb(\n                    (int)(float.Parse(upperBoundsNode.SelectSingleNode(\"R\").InnerText) * 255),\n                    (int)(float.Parse(upperBoundsNode.SelectSingleNode(\"G\").InnerText) * 255),\n                    (int)(float.Parse(upperBoundsNode.SelectSingleNode(\"B\").InnerText) * 255)\n                );\n            }\n\n            var fudgeNode = node.SelectSingleNode(\"Fudge\");\n            if (fudgeNode != null)\n            {\n                fudge = float.Parse(fudgeNode.InnerText);\n            }\n\n            var hsvShiftNode = node.SelectSingleNode(\"HSVShift\");\n            if (hsvShiftNode != null)\n            {\n                hsvShift = new Vector3(\n                    float.Parse(hsvShiftNode.SelectSingleNode(\"X\").InnerText),\n                    float.Parse(hsvShiftNode.SelectSingleNode(\"Y\").InnerText),\n                    float.Parse(hsvShiftNode.SelectSingleNode(\"Z\").InnerText)\n                );\n            }\n\n            var inputLevelsNode = node.SelectSingleNode(\"InputLevels\");\n            if (inputLevelsNode != null)\n            {\n                inputLevels = new Vector3(\n                    float.Parse(inputLevelsNode.SelectSingleNode(\"X\").InnerText),\n                    float.Parse(inputLevelsNode.SelectSingleNode(\"Y\").InnerText),\n                    float.Parse(inputLevelsNode.SelectSingleNode(\"Z\").InnerText)\n                );\n            }\n\n            var outputLevelsNode = node.SelectSingleNode(\"OutputLevels\");\n            if (outputLevelsNode != null)\n            {\n                outputLevels = new Vector2(\n                    float.Parse(outputLevelsNode.SelectSingleNode(\"X\").InnerText),\n                    float.Parse(outputLevelsNode.SelectSingleNode(\"Y\").InnerText)\n                );\n            }\n\n            var overallInputLevelsNode = node.SelectSingleNode(\"OverallInputLevels\");\n            if (overallInputLevelsNode != null)\n            {\n                overallInputLevels = new Vector3(\n                    float.Parse(overallInputLevelsNode.SelectSingleNode(\"X\").InnerText),\n                    float.Parse(overallInputLevelsNode.SelectSingleNode(\"Y\").InnerText),\n                    float.Parse(overallInputLevelsNode.SelectSingleNode(\"Z\").InnerText)\n                );\n            }\n\n            var overallOutputLevelsNode = node.SelectSingleNode(\"OverallOutputLevels\");\n            if (outputLevelsNode != null)\n            {\n                overallOutputLevels = new Vector2(\n                    float.Parse(overallOutputLevelsNode.SelectSingleNode(\"X\").InnerText),\n                    float.Parse(overallOutputLevelsNode.SelectSingleNode(\"Y\").InnerText)\n                );\n            }\n\n            var radarMapColorNode = node.SelectSingleNode(\"RadarMapColor\");\n            if (radarMapColorNode != null)\n            {\n                radarMapColor = Color.FromArgb(\n                    (int)(float.Parse(radarMapColorNode.SelectSingleNode(\"R\").InnerText) * 255),\n                    (int)(float.Parse(radarMapColorNode.SelectSingleNode(\"G\").InnerText) * 255),\n                    (int)(float.Parse(radarMapColorNode.SelectSingleNode(\"B\").InnerText) * 255)\n                );\n            }\n        }\n\n        public void Flatten()\n        {\n            lowerBounds = LowerBounds;\n            upperBounds = UpperBounds;\n            fudge = Fudge;\n            hsvShift = HSVShift;\n            inputLevels = InputLevels;\n            outputLevels = OutputLevels;\n            overallInputLevels = OverallInputLevels;\n            overallOutputLevels = OverallOutputLevels;\n            radarMapColor = RadarMapColor;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/TeamColorManager.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Xml;\n\nnamespace MobiusEditor.Utility\n{\n    public class TeamColorManager\n    {\n        private readonly Dictionary<string, TeamColor> teamColors = new Dictionary<string, TeamColor>();\n\n        private readonly MegafileManager megafileManager;\n\n        public TeamColor this[string key] => !string.IsNullOrEmpty(key) ? teamColors[key] : null;\n\n        public TeamColorManager(MegafileManager megafileManager)\n        {\n            this.megafileManager = megafileManager;\n        }\n\n        public void Reset()\n        {\n            teamColors.Clear();\n        }\n\n        public void Load(string xmlPath)\n        {\n            XmlDocument xmlDoc = new XmlDocument();\n            xmlDoc.Load(megafileManager.Open(xmlPath));\n\n            foreach (XmlNode teamColorNode in xmlDoc.SelectNodes(\"/*/TeamColorTypeClass\"))\n            {\n                var teamColor = new TeamColor(this, megafileManager);\n                teamColor.Load(teamColorNode.OuterXml);\n\n                teamColors[teamColorNode.Attributes[\"Name\"].Value] = teamColor;\n            }\n\n            foreach (var teamColor in TopologicalSortTeamColors())\n            {\n                teamColor.Flatten();\n            }\n        }\n\n        private IEnumerable<TeamColor> TopologicalSortTeamColors()\n        {\n            var nodes = teamColors.Values.ToList();\n            HashSet<(TeamColor, TeamColor)> edges = new HashSet<(TeamColor, TeamColor)>();\n            foreach (var node in nodes)\n            {\n                if (!string.IsNullOrEmpty(node.Variant))\n                {\n                    edges.Add((this[node.Variant], node));\n                }\n            }\n\n            var sorted = new List<TeamColor>();\n            var openSet = new HashSet<TeamColor>(nodes.Where(n => edges.All(e => !e.Item2.Equals(n))));\n            while (openSet.Count > 0)\n            {\n                var node = openSet.First();\n                openSet.Remove(node);\n                sorted.Add(node);\n\n                foreach (var edge in edges.Where(e => e.Item1.Equals(node)).ToArray())\n                {\n                    var node2 = edge.Item2;\n                    edges.Remove(edge);\n\n                    if (edges.All(edge2 => !edge2.Item2.Equals(node2)))\n                    {\n                        openSet.Add(node2);\n                    }\n                }\n            }\n\n            return (edges.Count == 0) ? sorted : null;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/TextureManager.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing Newtonsoft.Json.Linq;\nusing Pfim;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing TGASharpLib;\n\nnamespace MobiusEditor.Utility\n{\n    public class TextureManager\n    {\n#if false\n        private class ImageData\n        {\n            public TGA TGA;\n            public JObject Metadata;\n        }\n#endif\n\n        private readonly MegafileManager megafileManager;\n\n        private Dictionary<string, Bitmap> cachedTextures = new Dictionary<string, Bitmap>();\n        private Dictionary<(string, TeamColor), (Bitmap, Rectangle)> teamColorTextures = new Dictionary<(string, TeamColor), (Bitmap, Rectangle)>();\n\n        public TextureManager(MegafileManager megafileManager)\n        {\n            this.megafileManager = megafileManager;\n        }\n\n        public void Reset()\n        {\n            cachedTextures.Clear();\n            teamColorTextures.Clear();\n        }\n\n        public (Bitmap, Rectangle) GetTexture(string filename, TeamColor teamColor)\n        {\n            if (teamColorTextures.TryGetValue((filename, teamColor), out (Bitmap bitmap, Rectangle opaqueBounds) result))\n            {\n                return result;\n            }\n\n            if (!cachedTextures.TryGetValue(filename, out result.bitmap))\n            {\n                if (Path.GetExtension(filename).ToLower() == \".tga\")\n                {\n                    TGA tga = null;\n                    JObject metadata = null;\n\n                    // First attempt to find the texture in an archive\n                    var name = Path.GetFileNameWithoutExtension(filename);\n                    var archiveDir = Path.GetDirectoryName(filename);\n                    var archivePath = archiveDir + \".ZIP\";\n                    using (var fileStream = megafileManager.Open(archivePath))\n                    {\n                        if (fileStream != null)\n                        {\n                            using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Read))\n                            {\n                                foreach (var entry in archive.Entries)\n                                {\n                                    if (name == Path.GetFileNameWithoutExtension(entry.Name))\n                                    {\n                                        if ((tga == null) && (Path.GetExtension(entry.Name).ToLower() == \".tga\"))\n                                        {\n                                            using (var stream = entry.Open())\n                                            using (var memStream = new MemoryStream())\n                                            {\n                                                stream.CopyTo(memStream);\n                                                tga = new TGA(memStream);\n                                            }\n                                        }\n                                        else if ((metadata == null) && (Path.GetExtension(entry.Name).ToLower() == \".meta\"))\n                                        {\n                                            using (var stream = entry.Open())\n                                            using (var reader = new StreamReader(stream))\n                                            {\n                                                metadata = JObject.Parse(reader.ReadToEnd());\n                                            }\n                                        }\n\n                                        if ((tga != null) && (metadata != null))\n                                        {\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    // Next attempt to load a standalone file\n                    if (tga == null)\n                    {\n                        using (var fileStream = megafileManager.Open(filename))\n                        {\n                            if (fileStream != null)\n                            {\n                                tga = new TGA(fileStream);\n                            }\n                        }\n                    }\n\n                    if (tga != null)\n                    {\n                        var bitmap = tga.ToBitmap(true);\n                        if (metadata != null)\n                        {\n                            var size = new Size(metadata[\"size\"][0].ToObject<int>(), metadata[\"size\"][1].ToObject<int>());\n                            var crop = Rectangle.FromLTRB(\n                                metadata[\"crop\"][0].ToObject<int>(),\n                                metadata[\"crop\"][1].ToObject<int>(),\n                                metadata[\"crop\"][2].ToObject<int>(),\n                                metadata[\"crop\"][3].ToObject<int>()\n                            );\n\n                            var uncroppedBitmap = new Bitmap(size.Width, size.Height, bitmap.PixelFormat);\n                            using (var g = Graphics.FromImage(uncroppedBitmap))\n                            {\n                                g.DrawImage(bitmap, crop, new Rectangle(Point.Empty, bitmap.Size), GraphicsUnit.Pixel);\n                            }\n                            cachedTextures[filename] = uncroppedBitmap;\n                        }\n                        else\n                        {\n                            cachedTextures[filename] = bitmap;\n                        }\n                    }\n\n#if false\n                    // Attempt to load parent directory as archive\n                    var archiveDir = Path.GetDirectoryName(filename);\n                    var archivePath = archiveDir + \".ZIP\";\n                    using (var fileStream = megafileManager.Open(archivePath))\n                    {\n                        if (fileStream != null)\n                        {\n                            using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Read))\n                            {\n                                var images = new Dictionary<string, ImageData>();\n\n                                foreach (var entry in archive.Entries)\n                                {\n                                    var name = Path.GetFileNameWithoutExtension(entry.Name);\n                                    if (!images.TryGetValue(name, out ImageData imageData))\n                                    {\n                                        imageData = images[name] = new ImageData { TGA = null, Metadata = null };\n                                    }\n\n                                    if ((imageData.TGA == null) && (Path.GetExtension(entry.Name).ToLower() == \".tga\"))\n                                    {\n                                        using (var stream = entry.Open())\n                                        using (var memStream = new MemoryStream())\n                                        {\n                                            stream.CopyTo(memStream);\n                                            imageData.TGA = new TGA(memStream);\n                                        }\n                                    }\n                                    else if ((imageData.Metadata == null) && (Path.GetExtension(entry.Name).ToLower() == \".meta\"))\n                                    {\n                                        using (var stream = entry.Open())\n                                        using (var reader = new StreamReader(stream))\n                                        {\n                                            imageData.Metadata = JObject.Parse(reader.ReadToEnd());\n                                        }\n                                    }\n\n                                    if ((imageData.TGA != null) && (imageData.Metadata != null))\n                                    {\n                                        var bitmap = imageData.TGA.ToBitmap(true);\n                                        var size = new Size(imageData.Metadata[\"size\"][0].ToObject<int>(), imageData.Metadata[\"size\"][1].ToObject<int>());\n                                        var crop = Rectangle.FromLTRB(\n                                            imageData.Metadata[\"crop\"][0].ToObject<int>(),\n                                            imageData.Metadata[\"crop\"][1].ToObject<int>(),\n                                            imageData.Metadata[\"crop\"][2].ToObject<int>(),\n                                            imageData.Metadata[\"crop\"][3].ToObject<int>()\n                                        );\n\n                                        var uncroppedBitmap = new Bitmap(size.Width, size.Height, bitmap.PixelFormat);\n                                        using (var g = Graphics.FromImage(uncroppedBitmap))\n                                        {\n                                            g.DrawImage(bitmap, crop, new Rectangle(Point.Empty, bitmap.Size), GraphicsUnit.Pixel);\n                                        }\n                                        cachedTextures[Path.Combine(archiveDir, name) + \".tga\"] = uncroppedBitmap;\n\n                                        images.Remove(name);\n                                    }\n                                }\n\n                                foreach (var item in images.Where(x => x.Value.TGA != null))\n                                {\n                                    cachedTextures[Path.Combine(archiveDir, item.Key) + \".tga\"] = item.Value.TGA.ToBitmap(true);\n                                }\n                            }\n                        }\n                    }\n#endif\n                }\n\n                if (!cachedTextures.TryGetValue(filename, out result.bitmap))\n                {\n                    // Try loading as a DDS\n                    var ddsFilename = Path.ChangeExtension(filename, \".DDS\");\n                    using (var fileStream = megafileManager.Open(ddsFilename))\n                    {\n                        if (fileStream != null)\n                        {\n                            var bytes = new byte[fileStream.Length];\n                            fileStream.Read(bytes, 0, bytes.Length);\n\n                            using (var image = Dds.Create(bytes, new PfimConfig()))\n                            {\n                                PixelFormat format;\n                                switch (image.Format)\n                                {\n                                    case Pfim.ImageFormat.Rgb24:\n                                        format = PixelFormat.Format24bppRgb;\n                                        break;\n\n                                    case Pfim.ImageFormat.Rgba32:\n                                        format = PixelFormat.Format32bppArgb;\n                                        break;\n\n                                    case Pfim.ImageFormat.R5g5b5:\n                                        format = PixelFormat.Format16bppRgb555;\n                                        break;\n\n                                    case Pfim.ImageFormat.R5g6b5:\n                                        format = PixelFormat.Format16bppRgb565;\n                                        break;\n\n                                    case Pfim.ImageFormat.R5g5b5a1:\n                                        format = PixelFormat.Format16bppArgb1555;\n                                        break;\n\n                                    case Pfim.ImageFormat.Rgb8:\n                                        format = PixelFormat.Format8bppIndexed;\n                                        break;\n\n                                    default:\n                                        format = PixelFormat.DontCare;\n                                        break;\n                                }\n\n                                var bitmap = new Bitmap(image.Width, image.Height, format);\n                                var bitmapData = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);\n                                Marshal.Copy(image.Data, 0, bitmapData.Scan0, image.Stride * image.Height);\n                                bitmap.UnlockBits(bitmapData);\n                                cachedTextures[filename] = bitmap;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (!cachedTextures.TryGetValue(filename, out result.bitmap))\n            {\n                return result;\n            }\n\n            result.bitmap = new Bitmap(result.bitmap);\n            result.opaqueBounds = new Rectangle(0, 0, result.bitmap.Width, result.bitmap.Height);\n            if (teamColor != null)\n            {\n                float frac(float x) => x - (int)x;\n                float lerp(float x, float y, float t) => (x * (1.0f - t)) + (y * t);\n                float saturate(float x) => Math.Max(0.0f, Math.Min(1.0f, x));\n\n                BitmapData data = null;\n                try\n                {\n                    data = result.bitmap.LockBits(new Rectangle(0, 0, result.bitmap.Width, result.bitmap.Height), ImageLockMode.ReadWrite, result.bitmap.PixelFormat);\n                    var bpp = Image.GetPixelFormatSize(data.PixelFormat) / 8;\n                    var bytes = new byte[data.Stride * data.Height];\n                    Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);\n\n                    result.opaqueBounds = CalculateOpaqueBounds(bytes, data.Width, data.Height, bpp, data.Stride);\n\n                    for (int j = 0; j < bytes.Length; j += bpp)\n                    {\n                        var pixel = Color.FromArgb(bytes[j + 2], bytes[j + 1], bytes[j + 0]);\n                        (float r, float g, float b) = (pixel.R.ToLinear(), pixel.G.ToLinear(), pixel.B.ToLinear());\n\n                        (float x, float y, float z, float w) K = (0.0f, -1.0f / 3.0f, 2.0f / 3.0f, -1.0f);\n                        (float x, float y, float z, float w) p = (g >= b) ? (g, b, K.x, K.y) : (b, g, K.w, K.z);\n                        (float x, float y, float z, float w) q = (r >= p.x) ? (r, p.y, p.z, p.x) : (p.x, p.y, p.w, r);\n                        (float d, float e) = (q.x - Math.Min(q.w, q.y), 1e-10f);\n                        (float hue, float saturation, float value) = (Math.Abs(q.z + (q.w - q.y) / (6.0f * d + e)), d / (q.x + e), q.x);\n\n                        var lowerHue = teamColor.LowerBounds.GetHue() / 360.0f;\n                        var upperHue = teamColor.UpperBounds.GetHue() / 360.0f;\n                        if ((hue >= lowerHue) && (upperHue >= hue))\n                        {\n                            hue = (hue / (upperHue - lowerHue)) * ((upperHue + teamColor.Fudge) - (lowerHue - teamColor.Fudge));\n                            hue += teamColor.HSVShift.X;\n                            saturation += teamColor.HSVShift.Y;\n                            value += teamColor.HSVShift.Z;\n\n                            (float x, float y, float z, float w) L = (1.0f, 2.0f / 3.0f, 1.0f / 3.0f, 3.0f);\n                            (float x, float y, float z) m = (\n                                Math.Abs(frac(hue + L.x) * 6.0f - L.w),\n                                Math.Abs(frac(hue + L.y) * 6.0f - L.w),\n                                Math.Abs(frac(hue + L.z) * 6.0f - L.w)\n                            );\n\n                            r = value * lerp(L.x, saturate(m.x - L.x), saturation);\n                            g = value * lerp(L.x, saturate(m.y - L.x), saturation);\n                            b = value * lerp(L.x, saturate(m.z - L.x), saturation);\n\n                            (float x, float y, float z) n = (\n                                Math.Min(1.0f, Math.Max(0.0f, r - teamColor.InputLevels.X) / (teamColor.InputLevels.Z - teamColor.InputLevels.X)),\n                                Math.Min(1.0f, Math.Max(0.0f, g - teamColor.InputLevels.X) / (teamColor.InputLevels.Z - teamColor.InputLevels.X)),\n                                Math.Min(1.0f, Math.Max(0.0f, b - teamColor.InputLevels.X) / (teamColor.InputLevels.Z - teamColor.InputLevels.X))\n                            );\n                            n.x = (float)Math.Pow(n.x, teamColor.InputLevels.Y);\n                            n.y = (float)Math.Pow(n.y, teamColor.InputLevels.Y);\n                            n.z = (float)Math.Pow(n.z, teamColor.InputLevels.Y);\n\n                            r = lerp(teamColor.OutputLevels.X, teamColor.OutputLevels.Y, n.x);\n                            g = lerp(teamColor.OutputLevels.X, teamColor.OutputLevels.Y, n.y);\n                            b = lerp(teamColor.OutputLevels.X, teamColor.OutputLevels.Y, n.z);\n                        }\n\n                        (float x, float y, float z) n2 = (\n                            Math.Min(1.0f, Math.Max(0.0f, r - teamColor.OverallInputLevels.X) / (teamColor.OverallInputLevels.Z - teamColor.OverallInputLevels.X)),\n                            Math.Min(1.0f, Math.Max(0.0f, g - teamColor.OverallInputLevels.X) / (teamColor.OverallInputLevels.Z - teamColor.OverallInputLevels.X)),\n                            Math.Min(1.0f, Math.Max(0.0f, b - teamColor.OverallInputLevels.X) / (teamColor.OverallInputLevels.Z - teamColor.OverallInputLevels.X))\n                        );\n                        n2.x = (float)Math.Pow(n2.x, teamColor.OverallInputLevels.Y);\n                        n2.y = (float)Math.Pow(n2.y, teamColor.OverallInputLevels.Y);\n                        n2.z = (float)Math.Pow(n2.z, teamColor.OverallInputLevels.Y);\n\n                        r = lerp(teamColor.OverallOutputLevels.X, teamColor.OverallOutputLevels.Y, n2.x);\n                        g = lerp(teamColor.OverallOutputLevels.X, teamColor.OverallOutputLevels.Y, n2.y);\n                        b = lerp(teamColor.OverallOutputLevels.X, teamColor.OverallOutputLevels.Y, n2.z);\n\n                        bytes[j + 2] = (byte)(r.ToSRGB() * 255.0f);\n                        bytes[j + 1] = (byte)(g.ToSRGB() * 255.0f);\n                        bytes[j + 0] = (byte)(b.ToSRGB() * 255.0f);\n                    }\n\n                    Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);\n                }\n                finally\n                {\n                    if (data != null)\n                    {\n                        result.bitmap.UnlockBits(data);\n                    }\n                }\n            }\n            else\n            {\n                result.opaqueBounds = CalculateOpaqueBounds(result.bitmap);\n            }\n\n            teamColorTextures[(filename, teamColor)] = result;\n            return result;\n        }\n\n        private static Rectangle CalculateOpaqueBounds(byte[] data, int width, int height, int bpp, int stride)\n        {\n            bool isTransparentRow(int y)\n            {\n                var start = y * stride;\n                for (var i = bpp - 1; i < stride; i += bpp)\n                {\n                    if (data[start + i] != 0)\n                    {\n                        return false;\n                    }\n                }\n                return true;\n            }\n\n            var opaqueBounds = new Rectangle(0, 0, width, height);\n            for (int y = 0; y < height; ++y)\n            {\n                if (!isTransparentRow(y))\n                {\n                    opaqueBounds.Offset(0, y);\n                    break;\n                }\n            }\n            for (int y = height; y > 0; --y)\n            {\n                if (!isTransparentRow(y - 1))\n                {\n                    opaqueBounds.Height = y - opaqueBounds.Top;\n                    break;\n                }\n            }\n\n            bool isTransparentColumn(int x)\n            {\n                var start = (x * bpp) + (bpp - 1);\n                for (var y = opaqueBounds.Top; y < opaqueBounds.Bottom; ++y)\n                {\n                    if (data[start + (y * stride)] != 0)\n                    {\n                        return false;\n                    }\n                }\n                return true;\n            }\n\n            for (int x = 0; x < width; ++x)\n            {\n                if (!isTransparentColumn(x))\n                {\n                    opaqueBounds.Offset(x, 0);\n                    break;\n                }\n            }\n            for (int x = width; x > 0; --x)\n            {\n                if (!isTransparentColumn(x - 1))\n                {\n                    opaqueBounds.Width = x - opaqueBounds.Left;\n                    break;\n                }\n            }\n\n            return opaqueBounds;\n        }\n\n        private static Rectangle CalculateOpaqueBounds(Bitmap bitmap)\n        {\n            BitmapData data = null;\n            try\n            {\n                data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);\n                var bpp = Image.GetPixelFormatSize(data.PixelFormat) / 8;\n                var bytes = new byte[data.Stride * data.Height];\n                Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);\n                return CalculateOpaqueBounds(bytes, data.Width, data.Height, bpp, data.Stride);\n            }\n            finally\n            {\n                if (data != null)\n                {\n                    bitmap.UnlockBits(data);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/Tileset.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System.Xml;\n\nnamespace MobiusEditor.Utility\n{\n    public class Tile\n    {\n        public Image Image { get; private set; }\n\n        public Rectangle OpaqueBounds { get; private set; }\n\n        public Tile(Image image, Rectangle opaqueBounds)\n        {\n            Image = image;\n            OpaqueBounds = opaqueBounds;\n        }\n\n        public Tile(Image image)\n            : this(image, new Rectangle(0, 0, image.Width, image.Height))\n        {\n        }\n    }\n\n    public class Tileset\n    {\n        private class TileData\n        {\n            public int FPS { get; set; }\n            public string[] Frames { get; set; }\n\n            public Dictionary<string, Tile[]> TeamColorTiles { get; } = new Dictionary<string, Tile[]>();\n        }\n\n        private readonly Dictionary<string, Dictionary<int, TileData>> tiles = new Dictionary<string, Dictionary<int, TileData>>(StringComparer.OrdinalIgnoreCase);\n\n        private readonly TextureManager textureManager;\n\n        private static readonly Bitmap transparentTileImage;\n\n        static Tileset()\n        {\n            transparentTileImage = new Bitmap(Globals.TileWidth, Globals.TileHeight);\n            transparentTileImage.MakeTransparent();\n        }\n\n        public Tileset(TextureManager textureManager)\n        {\n            this.textureManager = textureManager;\n        }\n\n        public void Reset()\n        {\n            foreach (var item in tiles)\n            {\n                foreach (var tileItem in item.Value)\n                {\n                    tileItem.Value.TeamColorTiles.Clear();\n                }\n            }\n        }\n\n        public void Load(string xml, string texturesPath)\n        {\n            XmlDocument xmlDoc = new XmlDocument();\n            xmlDoc.LoadXml(xml);\n\n            var rootPath = Path.Combine(texturesPath, xmlDoc.SelectSingleNode(\"TilesetTypeClass/RootTexturePath\").InnerText);\n            foreach (XmlNode tileNode in xmlDoc.SelectNodes(\"TilesetTypeClass/Tiles/Tile\"))\n            {\n                TileData tileData = new TileData();\n\n                var name = tileNode.SelectSingleNode(\"Key/Name\").InnerText;\n                var shape = int.Parse(tileNode.SelectSingleNode(\"Key/Shape\").InnerText);\n                var fpsNode = tileNode.SelectSingleNode(\"Value/AnimationData/FPS\");\n                tileData.FPS = (fpsNode != null) ? int.Parse(fpsNode.InnerText) : 0;\n\n                var frameNodes = tileNode.SelectNodes(\"Value/Frames/Frame\");\n#if false\n                tileData.Frames = new string[frameNodes.Count];\n#else\n                tileData.Frames = new string[Math.Min(1, frameNodes.Count)];\n#endif\n\n                for (var i = 0; i < tileData.Frames.Length; ++i)\n                {\n                    string filename = null;\n                    if (!string.IsNullOrEmpty(frameNodes[i].InnerText))\n                    {\n                        filename = Path.Combine(rootPath, frameNodes[i].InnerText);\n                    }\n\n                    tileData.Frames[i] = filename;\n                }\n\n                if (!tiles.TryGetValue(name, out Dictionary<int, TileData> shapes))\n                {\n                    shapes = new Dictionary<int, TileData>();\n                    tiles[name] = shapes;\n                }\n\n                shapes[shape] = tileData;\n            }\n        }\n\n        public bool GetTileData(string name, int shape, TeamColor teamColor, out int fps, out Tile[] tiles)\n        {\n            fps = 0;\n            tiles = null;\n\n            if (!this.tiles.TryGetValue(name, out Dictionary<int, TileData> shapes))\n            {\n                return false;\n            }\n\n            if (shape < 0)\n            {\n                shape = Math.Max(0, shapes.Max(kv => kv.Key) + shape + 1);\n            }\n            if (!shapes.TryGetValue(shape, out TileData tileData))\n            {\n                return false;\n            }\n\n            var key = teamColor?.Name ?? string.Empty;\n            if (!tileData.TeamColorTiles.TryGetValue(key, out Tile[] tileDataTiles))\n            {\n                tileDataTiles = new Tile[tileData.Frames.Length];\n                tileData.TeamColorTiles[key] = tileDataTiles;\n\n                for (int i = 0; i < tileDataTiles.Length; ++i)\n                {\n                    var filename = tileData.Frames[i];\n                    if (!string.IsNullOrEmpty(filename))\n                    {\n                        (Bitmap bitmap, Rectangle opaqueBounds) = textureManager.GetTexture(filename, teamColor);\n                        tileDataTiles[i] = new Tile(bitmap, opaqueBounds);\n                    }\n                    else\n                    {\n                        tileDataTiles[i] = new Tile(transparentTileImage);\n                    }\n                }\n            }\n\n            fps = tileData.FPS;\n            tiles = tileDataTiles;\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/TilesetManager.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Xml;\n\nnamespace MobiusEditor.Utility\n{\n    public class TilesetManager\n    {\n        private readonly Dictionary<string, Tileset> tilesets = new Dictionary<string, Tileset>();\n\n        private readonly MegafileManager megafileManager;\n\n        public TilesetManager(MegafileManager megafileManager, TextureManager textureManager, string xmlPath, string texturesPath)\n        {\n            this.megafileManager = megafileManager;\n\n            XmlDocument xmlDoc = new XmlDocument();\n            xmlDoc.Load(megafileManager.Open(xmlPath));\n\n            foreach (XmlNode fileNode in xmlDoc.SelectNodes(\"TilesetFiles/File\"))\n            {\n                var xmlFile = Path.Combine(Path.GetDirectoryName(xmlPath), fileNode.InnerText);\n                XmlDocument fileXmlDoc = new XmlDocument();\n                fileXmlDoc.Load(megafileManager.Open(xmlFile));\n\n                foreach (XmlNode tilesetNode in fileXmlDoc.SelectNodes(\"Tilesets/TilesetTypeClass\"))\n                {\n                    var tileset = new Tileset(textureManager);\n                    tileset.Load(tilesetNode.OuterXml, texturesPath);\n\n                    tilesets[tilesetNode.Attributes[\"name\"].Value] = tileset;\n                }\n            }\n        }\n\n        public void Reset()\n        {\n            foreach (var item in tilesets)\n            {\n                item.Value.Reset();\n            }\n        }\n\n        public bool GetTeamColorTileData(IEnumerable<string> searchTilesets, string name, int shape, TeamColor teamColor, out int fps, out Tile[] tiles)\n        {\n            fps = 0;\n            tiles = null;\n\n            foreach (var tileset in tilesets.Join(searchTilesets, x => x.Key, y => y, (x, y) => x.Value))\n            {\n                if (tileset.GetTileData(name, shape, teamColor, out fps, out tiles))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public bool GetTeamColorTileData(IEnumerable<string> searchTilesets, string name, int shape, TeamColor teamColor, out int fps, out Tile tile)\n        {\n            tile = null;\n            if (!GetTeamColorTileData(searchTilesets, name, shape, teamColor, out fps, out Tile[] tiles))\n            {\n                return false;\n            }\n            tile = tiles[0];\n            return true;\n        }\n\n        public bool GetTeamColorTileData(IEnumerable<string> searchTilesets, string name, int shape, TeamColor teamColor, out Tile[] tiles)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, teamColor, out int fps, out tiles);\n        }\n\n        public bool GetTeamColorTileData(IEnumerable<string> searchTilesets, string name, int shape, TeamColor teamColor, out Tile tile)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, teamColor, out int fps, out tile);\n        }\n\n        public bool GetTileData(IEnumerable<string> searchTilesets, string name, int shape, out int fps, out Tile[] tiles)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, null, out fps, out tiles);\n        }\n\n        public bool GetTileData(IEnumerable<string> searchTilesets, string name, int shape, out int fps, out Tile tile)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, null, out fps, out tile);\n        }\n\n        public bool GetTileData(IEnumerable<string> searchTilesets, string name, int shape, out Tile[] tiles)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, null, out tiles);\n        }\n\n        public bool GetTileData(IEnumerable<string> searchTilesets, string name, int shape, out Tile tile)\n        {\n            return GetTeamColorTileData(searchTilesets, name, shape, null, out tile);\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/UndoRedoList.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MobiusEditor.Utility\n{\n    public class UndoRedoList<T>\n    {\n        private const int DefaultMaxUndoRedo = 50;\n\n        private readonly List<(Action<T> Undo, Action<T> Redo)> undoRedoActions = new List<(Action<T> Undo, Action<T> Redo)>();\n        private readonly int maxUndoRedo;\n        private int undoRedoPosition = 0;\n\n        public event EventHandler<EventArgs> Tracked;\n        public event EventHandler<EventArgs> Undone;\n        public event EventHandler<EventArgs> Redone;\n\n        public bool CanUndo => undoRedoPosition > 0;\n\n        public bool CanRedo => undoRedoActions.Count > undoRedoPosition;\n\n        public UndoRedoList(int maxUndoRedo)\n        {\n            this.maxUndoRedo = maxUndoRedo;\n        }\n\n        public UndoRedoList()\n            : this(DefaultMaxUndoRedo)\n        {\n        }\n\n        public void Clear()\n        {\n            undoRedoActions.Clear();\n            undoRedoPosition = 0;\n            OnTracked();\n        }\n\n        public void Track(Action<T> undo, Action<T> redo)\n        {\n            if (undoRedoActions.Count > undoRedoPosition)\n            {\n                undoRedoActions.RemoveRange(undoRedoPosition, undoRedoActions.Count - undoRedoPosition);\n            }\n\n            undoRedoActions.Add((undo, redo));\n\n            if (undoRedoActions.Count > maxUndoRedo)\n            {\n                undoRedoActions.RemoveRange(0, undoRedoActions.Count - maxUndoRedo);\n            }\n\n            undoRedoPosition = undoRedoActions.Count;\n            OnTracked();\n        }\n\n        public void Undo(T context)\n        {\n            if (!CanUndo)\n            {\n                throw new InvalidOperationException();\n            }\n\n            undoRedoPosition--;\n            undoRedoActions[undoRedoPosition].Undo(context);\n            OnUndone();\n        }\n\n        public void Redo(T context)\n        {\n            if (!CanRedo)\n            {\n                throw new InvalidOperationException();\n            }\n\n            undoRedoActions[undoRedoPosition].Redo(context);\n            undoRedoPosition++;\n            OnRedone();\n        }\n\n        protected virtual void OnTracked()\n        {\n            Tracked?.Invoke(this, new EventArgs());\n        }\n\n        protected virtual void OnUndone()\n        {\n            Undone?.Invoke(this, new EventArgs());\n        }\n\n        protected virtual void OnRedone()\n        {\n            Redone?.Invoke(this, new EventArgs());\n        }\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor/Utility/WWCompression.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing System;\n\nnamespace MobiusEditor.Utility\n{\n    /// <summary>\n    /// This class contains encoders and decoders for the Westwood XOR Delta and LCW compression schemes.\n    /// </summary>\n    public static class WWCompression\n    {\n        ////////////////////////////////////////////////////////////////////////////////\n        //  Notes\n        ////////////////////////////////////////////////////////////////////////////////\n        //\n        // LCW streams should always start and end with the fill command (& 0x80) though\n        // the decompressor doesn't strictly require that it start with one the ability\n        // to use the offset commands in place of the RLE command early in the stream\n        // relies on it. Streams larger than 64k that need the relative versions of the\n        // 3 and 5 byte commands should start with a null byte before the first 0x80\n        // command to flag that they are relative compressed.\n        //\n        // LCW uses the following rules to decide which command to use:\n        // 1. Runs of the same colour should only use 4 byte RLE command if longer than\n        //    64 bytes. 2 and 3 byte offset commands are more efficient otherwise.\n        // 2. Runs of less than 3 should just be stored as is with the one byte fill\n        //    command.\n        // 3. Runs greater than 10 or if the relative offset is greater than\n        //    4095 use an absolute copy. Less than 64 bytes uses 3 byte command, else it\n        //    uses the 5 byte command.\n        // 4. If Absolute rule isn't met then copy from a relative offset with 2 byte\n        //    command.\n        //\n        // Absolute LCW can efficiently compress data that is 64k in size, much greater\n        // and relative offsets for the 3 and 5 byte commands are needed.\n        //\n        // The XOR delta generator code works to the following assumptions\n        //\n        // 1. Any skip command is preferable if source and base are same\n        // 2. Fill is preferable to XOR if 4 or larger, XOR takes same data plus at\n        //    least 1 byte\n        //\n        ////////////////////////////////////////////////////////////////////////////////\n\n        ////////////////////////////////////////////////////////////////////////////////\n        //  Some defines used by the encoders\n        ////////////////////////////////////////////////////////////////////////////////\n        public const Byte XOR_SMALL = 0x7F;\n        public const Byte XOR_MED = 0xFF;\n        public const Int32 XOR_LARGE = 0x3FFF;\n        public const Int32 XOR_MAX = 0x7FFF;\n\n        ////////////////////////////////////////////////////////////////////////////////\n        //  Some utility functions to get worst case sizes for buffer allocation\n        ////////////////////////////////////////////////////////////////////////////////\n\n        public static Int32 LCWWorstCase(Int32 datasize)\n        {\n            return datasize + (datasize / 63) + 1;\n        }\n\n        public static Int32 XORWorstCase(Int32 datasize)\n        {\n            return datasize + ((datasize / 63) * 3) + 4;\n        }\n        \n        /// <summary>\n        ///    Compresses data to the proprietary LCW format used in\n        ///    many games developed by Westwood Studios. Compression is better\n        ///    than that achieved by popular community tools. This is a new\n        ///    implementation based on understanding of the compression gained from\n        ///    the reference code.\n        /// </summary>\n        /// <param name=\"input\">Array of the data to compress.</param>\n        /// <returns>The compressed data.</returns>\n        /// <remarks>Commonly known in the community as \"format80\".</remarks>\n        public static Byte[] LcwCompress(Byte[] input)\n        {\n            if (input == null || input.Length == 0)\n                return new Byte[0];\n\n            //Decide if we are going to do relative offsets for 3 and 5 byte commands\n            Boolean relative = input.Length > UInt16.MaxValue;\n\n            // Nyer's C# conversion: replacements for write and read for pointers.\n            Int32 getp = 0;\n            Int32 putp = 0;\n            // Input length. Used commonly enough to warrant getting it out in advance I guess.\n            Int32 getend = input.Length;\n            // \"Worst case length\" code by OmniBlade. We'll just use a buffer of\n            // that max length and cut it down to the actual used size at the end.\n            // Not using it- it's not big enough in case of some small images.\n            //LCWWorstCase(getend)\n            Int32 worstcase = Math.Max(10000, getend * 2);\n            Byte[] output = new Byte[worstcase];\n            // relative LCW starts with 0 as flag to decoder.\n            // this is only used by later games for decoding hi-color vqa files.\n            if (relative)\n                output[putp++] = 0;\n\n            //Implementations that properly conform to the WestWood encoder should\n            //write a starting cmd1. It's important for using the offset copy commands\n            //to do more efficient RLE in some cases than the cmd4.\n\n            //we also set bool to flag that we have an on going cmd1.\n            Int32 cmd_onep = putp;\n            output[putp++] = 0x81;\n            output[putp++] = input[getp++];\n            Boolean cmd_one = true;\n\n            //Compress data until we reach end of input buffer.\n            while (getp < getend)\n            {\n                //Is RLE encode (4bytes) worth evaluating?\n                if (getend - getp > 64 && input[getp] == input[getp + 64])\n                {\n                    //RLE run length is encoded as a short so max is UINT16_MAX\n                    Int32 rlemax = (getend - getp) < UInt16.MaxValue ? getend : getp + UInt16.MaxValue;\n                    Int32 rlep = getp + 1;\n                    while (rlep < rlemax && input[rlep] == input[getp])\n                        rlep++;\n\n                    UInt16 run_length = (UInt16)(rlep - getp);\n\n                    //If run length is long enough, write the command and start loop again\n                    if (run_length >= 0x41)\n                    {\n                        //write 4byte command 0b11111110\n                        cmd_one = false;\n                        output[putp++] = 0xFE;\n                        output[putp++] = (Byte)(run_length & 0xFF);\n                        output[putp++] = (Byte)((run_length >> 8) & 0xFF);\n                        output[putp++] = input[getp];\n                        getp = rlep;\n                        continue;\n                    }\n                }\n\n                //current block size for an offset copy\n                UInt16 block_size = 0;\n                //Set where we start looking for matching runs.\n                Int32 offstart = relative ? getp < UInt16.MaxValue ? 0 : getp - UInt16.MaxValue : 0;\n\n                //Look for matching runs\n                Int32 offchk = offstart;\n                Int32 offsetp = getp;\n                while (offchk < getp)\n                {\n                    //Move offchk to next matching position\n                    while (offchk < getp && input[offchk] != input[getp])\n                        offchk++;\n\n                    //If the checking pointer has reached current pos, break\n                    if (offchk >= getp)\n                        break;\n\n                    //find out how long the run of matches goes for\n                    Int32 i;\n                    for (i = 1; getp + i < getend; ++i)\n                        if (input[offchk + i] != input[getp + i])\n                            break;\n                    if (i >= block_size)\n                    {\n                        block_size = (UInt16)i;\n                        offsetp = offchk;\n                    }\n                    offchk++;\n                }\n\n                //decide what encoding to use for current run\n                //If it's less than 2 bytes long, we store as is with cmd1\n                if (block_size <= 2)\n                {\n                    //short copy 0b10??????\n                    //check we have an existing 1 byte command and if its value is still\n                    //small enough to handle additional bytes\n                    //start a new command if current one doesn't have space or we don't\n                    //have one to continue\n                    if (cmd_one && output[cmd_onep] < 0xBF)\n                    {\n                        //increment command value\n                        output[cmd_onep]++;\n                        output[putp++] = input[getp++];\n                    }\n                    else\n                    {\n                        cmd_onep = putp;\n                        output[putp++] = 0x81;\n                        output[putp++] = input[getp++];\n                        cmd_one = true;\n                    }\n                    //Otherwise we need to decide what relative copy command is most efficient\n                }\n                else\n                {\n                    Int32 offset;\n                    Int32 rel_offset = getp - offsetp;\n                    if (block_size > 0xA || ((rel_offset) > 0xFFF))\n                    {\n                        //write 5 byte command 0b11111111\n                        if (block_size > 0x40)\n                        {\n                            output[putp++] = 0xFF;\n                            output[putp++] = (Byte)(block_size & 0xFF);\n                            output[putp++] = (Byte)((block_size >> 8) & 0xFF);\n                            //write 3 byte command 0b11??????\n                        }\n                        else\n                        {\n                            output[putp++] = (Byte)((block_size - 3) | 0xC0);\n                        }\n\n                        offset = relative ? rel_offset : offsetp;\n                        //write 2 byte command? 0b0???????\n                    }\n                    else\n                    {\n                        offset = rel_offset << 8 | (16 * (block_size - 3) + (rel_offset >> 8));\n                    }\n                    output[putp++] = (Byte)(offset & 0xFF);\n                    output[putp++] = (Byte)((offset >> 8) & 0xFF);\n                    getp += block_size;\n                    cmd_one = false;\n                }\n            }\n\n            //write final 0x80, basically an empty cmd1 to signal the end of the stream.\n            output[putp++] = 0x80;\n\n            Byte[] finalOutput = new Byte[putp];\n            Array.Copy(output, 0, finalOutput, 0, putp);\n            // Return the final compressed data.\n            return finalOutput;\n        }\n\n        /// <summary>\n        ///     Decompresses data in the proprietary LCW format used in many games\n        ///     developed by Westwood Studios.\n        /// </summary>\n        /// <param name=\"input\">The data to decompress.</param>\n        /// <param name=\"readOffset\">Location to start at in the input array.</param>\n        /// <param name=\"output\">The buffer to store the decompressed data. This is assumed to be initialized to the correct size.</param>\n        /// <param name=\"readEnd\">End offset for reading. Use 0 to take the end of the given data array.</param>\n        /// <returns>Length of the decompressed data in bytes.</returns>\n        public static Int32 LcwDecompress(Byte[] input, ref Int32 readOffset, Byte[] output, Int32 readEnd)\n        {\n            if (input == null || input.Length == 0 || output == null || output.Length == 0)\n                return 0;\n\t        Boolean relative = false;\n            // Nyer's C# conversion: replacements for write and read for pointers.\n\t        Int32 writeOffset = 0;\n            // Output length should be part of the information given in the file format using LCW.\n            // Techncically it can just be cropped at the end, though this value is used to\n            // automatically cut off repeat-commands that go too far.\n            Int32 writeEnd = output.Length;\n            if (readEnd <= 0)\n                readEnd = input.Length;\n\n            //Decide if the stream uses relative 3 and 5 byte commands\n\t        //Extension allows effective compression of data > 64k\n\t        //https://github.com/madmoose/scummvm/blob/bladerunner/engines/bladerunner/decompress_lcw.cpp\n            // this is only used by later games for decoding hi-color vqa files.\n            // For other stuff (like shp), just check in advance to decide if the data is too big.\n            if (readOffset >= readEnd)\n                return writeOffset;\n\t        if (input[readOffset] == 0)\n\t        {\n\t\t        relative = true;\n\t\t        readOffset++;\n\t        }\n\t        //DEBUG_SAY(\"LCW Decompression... \\n\");\n\t        while (writeOffset < writeEnd)\n\t        {\n                if (readOffset >= readEnd)\n\t                return writeOffset;\n\t\t        Byte flag = input[readOffset++];\n\t\t        UInt16 cpysize;\n                UInt16 offset;\n\n\t\t        if ((flag & 0x80) != 0)\n\t\t        {\n\t\t\t        if ((flag & 0x40) != 0)\n\t\t\t        {\n                        cpysize = (UInt16)((flag & 0x3F) + 3);\n\t\t\t\t        //long set 0b11111110\n\t\t\t\t        if (flag == 0xFE)\n\t\t\t\t        {\n                            if (readOffset >= readEnd)\n                                return writeOffset;\n                            cpysize = input[readOffset++];\n                            if (readOffset >= readEnd)\n                                return writeOffset;\n                            cpysize += (UInt16)((input[readOffset++]) << 8);\n\t\t\t\t\t        if (cpysize > writeEnd - writeOffset)\n                                cpysize = (UInt16)(writeEnd - writeOffset);\n                            if (readOffset >= readEnd)\n                                return writeOffset;\n\t\t\t\t\t        //DEBUG_SAY(\"0b11111110 Source Pos %ld, Dest Pos %ld, Count %d\\n\", source - sstart - 3, dest - start, cpysize);\n                            for (; cpysize > 0; --cpysize)\n                            {\n                                if (writeOffset >= writeEnd)\n                                    return writeOffset;\n                                output[writeOffset++] = input[readOffset];\n                            }\n\t\t\t\t            readOffset++;\n\t\t\t\t        }\n\t\t\t\t        else\n\t\t\t\t        {\n\t\t\t\t\t        Int32 s;\n\t\t\t\t\t        //long move, abs 0b11111111\n\t\t\t\t\t        if (flag == 0xFF)\n\t\t\t\t\t        {\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n                                cpysize = input[readOffset++];\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n\t\t\t\t\t\t        cpysize += (UInt16)((input[readOffset++]) << 8);\n\t\t\t\t\t\t        if (cpysize > writeEnd - writeOffset)\n\t\t\t\t\t\t\t        cpysize = (UInt16)(writeEnd - writeOffset);\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n                                offset = input[readOffset++];\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n                                offset += (UInt16)((input[readOffset++]) << 8);\n                                //extended format for VQA32\n\t\t\t\t\t\t        if (relative)\n\t\t\t\t\t\t\t        s = writeOffset - offset;\n\t\t\t\t\t\t        else\n\t\t\t\t\t\t\t        s = offset;\n\t\t\t\t\t\t        //DEBUG_SAY(\"0b11111111 Source Pos %ld, Dest Pos %ld, Count %d, Offset %d\\n\", source - sstart - 5, dest - start, cpysize, offset);\n\t\t\t\t\t            for (; cpysize > 0; --cpysize)\n\t\t\t\t\t            {\n                                    if (writeOffset >= writeEnd)\n                                        return writeOffset;\n\t\t\t\t\t                output[writeOffset++] = output[s++];\n\t\t\t\t\t            }\n\t\t\t\t\t            //short move abs 0b11??????\n\t\t\t\t\t        }\n\t\t\t\t\t        else\n\t\t\t\t\t        {\n\t\t\t\t\t\t        if (cpysize > writeEnd - writeOffset)\n\t\t\t\t\t\t\t        cpysize = (UInt16)(writeEnd - writeOffset);\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n                                offset = input[readOffset++];\n                                if (readOffset >= readEnd)\n                                    return writeOffset;\n                                offset += (UInt16)((input[readOffset++]) << 8);\n\t\t\t\t\t\t        //extended format for VQA32\n\t\t\t\t\t\t        if (relative)\n\t\t\t\t\t\t\t        s = writeOffset - offset;\n\t\t\t\t\t\t        else\n\t\t\t\t\t\t\t        s = offset;\n\t\t\t\t\t\t        //DEBUG_SAY(\"0b11?????? Source Pos %ld, Dest Pos %ld, Count %d, Offset %d\\n\", source - sstart - 3, dest - start, cpysize, offset);\n\t\t\t\t\t            for (; cpysize > 0; --cpysize)\n                                {\n                                    if (writeOffset >= writeEnd)\n                                        return writeOffset;\n                                    output[writeOffset++] = output[s++];\n\t\t\t\t\t            }\n\t\t\t\t\t        }\n\t\t\t\t        }\n\t\t\t        //short copy 0b10??????\n\t\t\t        }\n\t\t\t        else\n\t\t\t        {\n\t\t\t\t        if (flag == 0x80)\n\t\t\t\t        {\n\t\t\t\t\t        //DEBUG_SAY(\"0b10?????? Source Pos %ld, Dest Pos %ld, Count %d\\n\", source - sstart - 1, dest - start, 0);\n\t\t\t\t\t        return writeOffset;\n\t\t\t\t        }\n\t\t\t\t        cpysize = (UInt16)(flag & 0x3F);\n\t\t\t\t        if (cpysize > writeEnd - writeOffset)\n\t\t\t\t\t        cpysize = (UInt16)(writeEnd - writeOffset);\n\t\t\t\t        //DEBUG_SAY(\"0b10?????? Source Pos %ld, Dest Pos %ld, Count %d\\n\", source - sstart - 1, dest - start, cpysize);\n\t\t\t            for (; cpysize > 0; --cpysize)\n\t\t\t            {\n                            if (readOffset >= readEnd || writeOffset >= writeEnd)\n                                return writeOffset;\n\t\t\t                output[writeOffset++] = input[readOffset++];\n\t\t\t            }\n\t\t\t        }\n\t\t        //short move rel 0b0???????\n\t\t        }\n\t\t        else\n\t\t        {\n\t\t\t        cpysize = (UInt16)((flag >> 4) + 3);\n\t\t\t        if (cpysize > writeEnd - writeOffset)\n\t\t\t\t        cpysize = (UInt16)(writeEnd - writeOffset);\n                    if (readOffset >= readEnd)\n                        return writeOffset;\n\t\t\t        offset = (UInt16)(((flag & 0xF) << 8) + input[readOffset++]);\n\t\t\t        //DEBUG_SAY(\"0b0??????? Source Pos %ld, Dest Pos %ld, Count %d, Offset %d\\n\", source - sstart - 2, dest - start, cpysize, offset);\n\t\t\t        for (; cpysize > 0; --cpysize)\n                    {\n                        if (writeOffset >= writeEnd || writeOffset < offset)\n                            return writeOffset;\n\t\t\t\t        output[writeOffset] = output[writeOffset - offset];\n\t\t\t\t        writeOffset++;\n\t\t\t        }\n\t\t        }\n\t        }\n            // If buffer is full, make sure to skip end command!\n            if (writeOffset == writeEnd && readOffset < input.Length && input[readOffset] == 0x80)\n                readOffset++;\n\t        return writeOffset;\n        }\n\n        /// <summary>\n        /// Generates a binary delta between two buffers. Mainly used for image data.\n        /// </summary>\n        /// <param name=\"source\">Buffer containing data to generate the delta for.</param>\n        /// <param name=\"base\">Buffer containing data that is the base for the delta.</param>\n        /// <returns>The generated delta as bytes array.</returns>\n        /// <remarks>Commonly known in the community as \"format40\".</remarks>\n        public static Byte[] GenerateXorDelta(Byte[] source, Byte[] @base)\n        {\n            // Nyer's C# conversion: replacements for write and read for pointers.\n            // -for our delta (output)\n            Int32 putp = 0;\n            // -for the image we go to\n            Int32 getsp = 0;\n            // -for the image we come from\n            Int32 getbp = 0;\n            //Length to process\n            Int32 getsendp = Math.Min(source.Length, @base.Length);\n            Byte[] dest = new Byte[XORWorstCase(getsendp)];\n\n            //Only check getsp to save a redundant check.\n            //Both source and base should be same size and both pointers should be\n            //incremented at the same time.\n            while (getsp < getsendp)\n            {\n                UInt32 fillcount = 0;\n                UInt32 xorcount = 0;\n                UInt32 skipcount = 0;\n                Byte lastxor = (Byte)(source[getsp] ^ @base[getbp]);\n                Int32 testsp = getsp;\n                Int32 testbp = getbp;\n\n                //Only evaluate other options if we don't have a matched pair\n                while (testsp < getsendp && source[testsp] != @base[testbp])\n                {\n                    if ((source[testsp] ^  @base[testbp]) == lastxor)\n                    {\n                        ++fillcount;\n                        ++xorcount;\n                    }\n                    else\n                    {\n                        if (fillcount > 3)\n                            break;\n                        lastxor = (Byte)(source[testsp] ^ @base[testbp]);\n                        fillcount = 1;\n                        ++xorcount;\n                    }\n                    testsp++;\n                    testbp++;\n                }\n\n                //fillcount should always be lower than xorcount and should be greater\n                //than 3 to warrant using the fill commands.\n                fillcount = fillcount > 3 ? fillcount : 0;\n\n                //Okay, lets see if we have any xor bytes we need to handle\n                xorcount -= fillcount;\n                while (xorcount != 0)\n                {\n                    UInt16 count;\n                    //It's cheaper to do the small cmd twice than do the large cmd once\n                    //for data that can be handled by two small cmds.\n                    //cmd 0???????\n                    if (xorcount < XOR_MED)\n                    {\n                        count = (UInt16)(xorcount <= XOR_SMALL ? xorcount : XOR_SMALL);\n                        dest[putp++] = (Byte)count;\n                        //cmd 10000000 10?????? ??????\n                    }\n                    else\n                    {\n                        count = (UInt16)(xorcount <= XOR_LARGE ? xorcount : XOR_LARGE);\n                        dest[putp++] = 0x80;\n                        dest[putp++] = (Byte)(count & 0xFF);\n                        dest[putp++] = (Byte)(((count >> 8) & 0xFF) | 0x80);\n                    }\n\n                    while (count != 0)\n                    {\n                        dest[putp++] = (Byte)(source[getsp++] ^ @base[getbp++]);\n                        count--;\n                        xorcount--;\n                    }\n                }\n\n                //lets handle the bytes that are best done as xorfill\n                while (fillcount != 0)\n                {\n                    UInt16 count;\n                    //cmd 00000000 ????????\n                    if (fillcount <= XOR_MED)\n                    {\n                        count = (UInt16)fillcount;\n                        dest[putp++] = 0;\n                        dest[putp++] = (Byte)(count & 0xFF);\n                        //cmd 10000000 11?????? ??????\n                    }\n                    else\n                    {\n                        count = (UInt16)(fillcount <= XOR_LARGE ? fillcount : XOR_LARGE);\n                        dest[putp++] = 0x80;\n                        dest[putp++] = (Byte)(count & 0xFF);\n                        dest[putp++] = (Byte)(((count >> 8) & 0xFF) | 0xC0);\n                    }\n                    dest[putp++] = (Byte)(source[getsp] ^ @base[getbp]);\n                    fillcount -= count;\n                    getsp += count;\n                    getbp += count;\n                }\n\n                //Handle regions that match exactly\n                while (testsp < getsendp && source[testsp] == @base[testbp])\n                {\n                    skipcount++;\n                    testsp++;\n                    testbp++;\n                }\n\n                while (skipcount != 0)\n                {\n                    UInt16 count;\n                    //Again it's cheaper to do the small cmd twice than do the large cmd\n                    //once for data that can be handled by two small cmds.\n                    //cmd 1???????\n                    if (skipcount < XOR_MED)\n                    {\n                        count = (Byte)(skipcount <= XOR_SMALL ? skipcount : XOR_SMALL);\n                        dest[putp++] = (Byte)(count | 0x80);\n                        //cmd 10000000 0??????? ????????\n                    }\n                    else\n                    {\n                        count = (UInt16)(skipcount <= XOR_MAX ? skipcount : XOR_MAX);\n                        dest[putp++] = 0x80;\n                        dest[putp++] = (Byte)(count & 0xFF);\n                        dest[putp++] = (Byte)((count >> 8) & 0xFF);\n                    }\n                    skipcount -= count;\n                    getsp += count;\n                    getbp += count;\n                }\n            }\n\n            //final skip command of 0 to signal end of stream.\n            dest[putp++] = 0x80;\n            dest[putp++] = 0;\n            dest[putp++] = 0;\n\n            Byte[] finalOutput = new Byte[putp];\n            Array.Copy(dest, 0, finalOutput, 0, putp);\n            // Return the final data\n            return finalOutput;\n        }\n\n        /// <summary>\n        /// Applies a binary delta to a buffer.\n        /// </summary>\n        /// <param name=\"data\">The data to apply the xor to.</param>\n        /// <param name=\"xorSource\">The the delta data to apply.</param>\n        /// <param name=\"xorStart\">Start offset in the data.</param>\n        /// <param name=\"xorEnd\">End offset in the data. Use 0 to take the end of the whole array.</param>\n        public static void ApplyXorDelta(Byte[] data, Byte[] xorSource, ref Int32 xorStart, Int32 xorEnd)\n        {\n            // Nyer's C# conversion: replacements for write and read for pointers.\n            Int32 putp = 0;\n            Byte value = 0;\n            Int32 dataEnd = data.Length;\n            if (xorEnd <= 0)\n                xorEnd = xorSource.Length;\n            while (putp < dataEnd && xorStart < xorEnd)\n            {\n                //DEBUG_SAY(\"XOR_Delta Put pos: %u, Get pos: %u.... \", putp - scast<sint8*>(dest), getp - scast<sint8*>(source));\n                Byte cmd = xorSource[xorStart++];\n                UInt16 count = cmd;\n                Boolean xorval = false;\n\n                if ((cmd & 0x80) == 0)\n                {\n                    //0b00000000\n                    if (cmd == 0)\n                    {\n                        if (xorStart >= xorEnd)\n                            return;\n                        count = (UInt16)(xorSource[xorStart++] & 0xFF);\n                        if (xorStart >= xorEnd)\n                            return;\n                        value = xorSource[xorStart++];\n                        xorval = true;\n                        //DEBUG_SAY(\"0b00000000 Val Count %d \", count);\n                        //0b0???????\n                    }\n                }\n                else\n                {\n                    //0b1??????? remove most significant bit\n                    count &= 0x7F;\n                    if (count != 0)\n                    {\n                        putp += count;\n                        //DEBUG_SAY(\"0b1??????? Skip Count %d\\n\", count);\n                        continue;\n                    }\n                    if (xorStart >= xorEnd)\n                        return;\n                    count = (UInt16) (xorSource[xorStart++] & 0xFF);\n                    if (xorStart >= xorEnd)\n                        return;\n                    count += (UInt16) (xorSource[xorStart++] << 8);\n\n                    //0b10000000 0 0\n                    if (count == 0)\n                    {\n                        //DEBUG_SAY(\"0b10000000 Count %d to end delta\\n\", count);\n                        return;\n                    }\n\n                    //0b100000000 0?\n                    if ((count & 0x8000) == 0)\n                    {\n                        putp += count;\n                        //DEBUG_SAY(\"0b100000000 0? Skip Count %d\\n\", count);\n                        continue;\n                    }\n                    //0b10000000 11\n                    if ((count & 0x4000) != 0)\n                    {\n                        count &= 0x3FFF;\n                        if (xorStart >= xorEnd)\n                            return;\n                        value = xorSource[xorStart++];\n                        //DEBUG_SAY(\"0b10000000 11 Val Count %d \", count);\n                        xorval = true;\n                        //0b10000000 10\n                    }\n                    else\n                    {\n                        count &= 0x3FFF;\n                        //DEBUG_SAY(\"0b10000000 10 XOR Count %d \", count);\n                    }\n                }\n\n                if (xorval)\n                {\n                    //DEBUG_SAY(\"XOR Val %d\\n\", value);\n                    for (; count > 0; --count)\n                    {\n                        if (putp >= dataEnd)\n                            return; \n                        data[putp++] ^= value;\n                    }\n                }\n                else\n                {\n                    //DEBUG_SAY(\"XOR Source to Dest\\n\");\n                    for (; count > 0; --count)\n                    {\n                        if (putp >= dataEnd || xorStart >= xorEnd)\n                            return;\n                        data[putp++] ^= xorSource[xorStart++];\n                    }\n                }\n            }\n        }\n\n    }\n}"
  },
  {
    "path": "CnCTDRAMapEditor/Widgets/NavigationWidget.cs",
    "content": "﻿//\n// Copyright 2020 Electronic Arts Inc.\n//\n// The Command & Conquer Map Editor and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// The Command & Conquer Map Editor and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\nusing MobiusEditor.Controls;\nusing MobiusEditor.Interface;\nusing MobiusEditor.Model;\nusing System;\nusing System.Drawing;\nusing System.Windows.Forms;\n\nnamespace MobiusEditor.Widgets\n{\n    public class MouseCellChangedEventArgs : EventArgs\n    {\n        public Point OldCell { get; private set; }\n\n        public Point NewCell { get; private set; }\n\n        public MouseCellChangedEventArgs(Point oldCell, Point newCell)\n        {\n            OldCell = oldCell;\n            NewCell = newCell;\n        }\n    }\n\n    public class NavigationWidget : IWidget\n    {\n        private static readonly Pen defaultMouseoverPen = new Pen(Color.Yellow, 4);\n\n        private readonly MapPanel mapPanel;\n        private readonly Size cellSize;\n\n        private bool dragging = false;\n        private Point lastMouseLocation;\n\n        public CellMetrics Metrics { get; private set; }\n\n        public Point MouseCell { get; private set; }\n        public Point MouseSubPixel { get; private set; }\n\n        private Size mouseoverSize = new Size(1, 1);\n        public Size MouseoverSize\n        {\n            get => mouseoverSize;\n            set => mouseoverSize = !value.IsEmpty ? new Size(value.Width | 1, value.Height | 1) : Size.Empty;\n        }\n\n        public event EventHandler<MouseCellChangedEventArgs> MouseCellChanged;\n\n        public NavigationWidget(MapPanel mapPanel, CellMetrics metrics, Size cellSize)\n        {\n            this.mapPanel = mapPanel;\n            this.mapPanel.MouseDown += MapPanel_MouseDown;\n            this.mapPanel.MouseMove += MapPanel_MouseMove;\n            Metrics = metrics;\n            this.cellSize = cellSize;\n        }\n\n        public void Refresh()\n        {\n            OnMouseMove(mapPanel.PointToClient(Control.MousePosition));\n        }\n\n        private void MapPanel_MouseDown(object sender, MouseEventArgs e)\n        {\n            if ((e.Button & MouseButtons.Middle) != MouseButtons.None)\n            {\n                lastMouseLocation = e.Location;\n                dragging = true;\n            }\n        }\n\n        private void MapPanel_MouseMove(object sender, MouseEventArgs e)\n        {\n            OnMouseMove(e.Location);\n        }\n\n        private void OnMouseMove(Point location)\n        {\n            if (dragging)\n            {\n                if ((Control.MouseButtons & MouseButtons.Middle) == MouseButtons.None)\n                {\n                    dragging = false;\n                }\n                else\n                {\n                    var delta = location - (Size)lastMouseLocation;\n                    if (!delta.IsEmpty)\n                    {\n                        mapPanel.AutoScrollPosition = new Point(-mapPanel.AutoScrollPosition.X - delta.X, -mapPanel.AutoScrollPosition.Y - delta.Y);\n                    }\n                }\n            }\n\n            lastMouseLocation = location;\n\n            var newMousePosition = mapPanel.ClientToMap(location);\n            MouseSubPixel = new Point(\n                (newMousePosition.X * Globals.PixelWidth / cellSize.Width) % Globals.PixelWidth,\n                (newMousePosition.Y * Globals.PixelHeight / cellSize.Height) % Globals.PixelHeight\n            );\n\n            var newMouseCell = new Point(newMousePosition.X / cellSize.Width, newMousePosition.Y / cellSize.Height);\n            if (MouseCell == newMouseCell)\n            {\n                return;\n            }\n\n            if (!Metrics.Contains(newMouseCell))\n            {\n                return;\n            }\n\n            var oldCell = MouseCell;\n            MouseCell = newMouseCell;\n\n            MouseCellChanged?.Invoke(this, new MouseCellChangedEventArgs(oldCell, MouseCell));\n\n            mapPanel.Invalidate();\n        }\n\n        public void Render(Graphics graphics)\n        {\n            if (!MouseoverSize.IsEmpty)\n            {\n                var rect = new Rectangle(new Point(MouseCell.X * cellSize.Width, MouseCell.Y * cellSize.Height), cellSize);\n                rect.Inflate(cellSize.Width * (MouseoverSize.Width / 2), cellSize.Height * (MouseoverSize.Height / 2));\n                graphics.DrawRectangle(defaultMouseoverPen, rect);\n            }\n        }\n\n        #region IDisposable Support\n        private bool disposedValue = false;\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {\n                if (disposing)\n                {\n                    mapPanel.MouseDown -= MapPanel_MouseDown;\n                    mapPanel.MouseMove -= MapPanel_MouseMove;\n                }\n                disposedValue = true;\n            }\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "CnCTDRAMapEditor.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.1022\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"CnCTDRAMapEditor\", \"CnCTDRAMapEditor\\CnCTDRAMapEditor.csproj\", \"{397CEF00-8930-4EC8-B15F-F7CF7193FB22}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tGold|Any CPU = Gold|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Gold|Any CPU.ActiveCfg = Gold|Any CPU\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Gold|Any CPU.Build.0 = Gold|Any CPU\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{397CEF00-8930-4EC8-B15F-F7CF7193FB22}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {3A313796-A0F0-4740-98D6-037699DBC902}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Electronic Arts Inc. released only TiberianDawn.dll, RedAlert.dll and \nthe Command & Conquer Map Editor and their corresponding source code \nunder the GPL V3 below, with additional terms at the bottom.\n\nGNU General Public License\n==========================\n\n_Version 3, 29 June 2007_  \n_Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_\n\nEveryone is permitted to copy and distribute verbatim copies of this license\ndocument, but changing it is not allowed.\n\n## Preamble\n\nThe GNU General Public License is a free, copyleft license for software and other\nkinds of works.\n\nThe licenses for most software and other practical works are designed to take away\nyour freedom to share and change the works. By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change all versions of a\nprogram--to make sure it remains free software for all its users. We, the Free\nSoftware Foundation, use the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors. You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General\nPublic Licenses are designed to make sure that you have the freedom to distribute\ncopies of free software (and charge for them if you wish), that you receive source\ncode or can get it if you want it, that you can change the software or use pieces of\nit in new free programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you these rights or\nasking you to surrender the rights. Therefore, you have certain responsibilities if\nyou distribute copies of the software, or if you modify it: responsibilities to\nrespect the freedom of others.\n\nFor example, if you distribute copies of such a program, whether gratis or for a fee,\nyou must pass on to the recipients the same freedoms that you received. You must make\nsure that they, too, receive or can get the source code. And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps: **(1)** assert\ncopyright on the software, and **(2)** offer you this License giving you legal permission\nto copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains that there is\nno warranty for this free software. For both users' and authors' sake, the GPL\nrequires that modified versions be marked as changed, so that their problems will not\nbe attributed erroneously to authors of previous versions.\n\nSome devices are designed to deny users access to install or run modified versions of\nthe software inside them, although the manufacturer can do so. This is fundamentally\nincompatible with the aim of protecting users' freedom to change the software. The\nsystematic pattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable. Therefore, we have designed\nthis version of the GPL to prohibit the practice for those products. If such problems\narise substantially in other domains, we stand ready to extend this provision to\nthose domains in future versions of the GPL, as needed to protect the freedom of\nusers.\n\nFinally, every program is threatened constantly by software patents. States should\nnot allow patents to restrict development and use of software on general-purpose\ncomputers, but in those that do, we wish to avoid the special danger that patents\napplied to a free program could make it effectively proprietary. To prevent this, the\nGPL assures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\n## TERMS AND CONDITIONS\n\n### 0. Definitions\n\n“This License” refers to version 3 of the GNU General Public License.\n\n“Copyright” also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n“The Program” refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as “you”. “Licensees” and\n“recipients” may be individuals or organizations.\n\nTo “modify” a work means to copy from or adapt all or part of the work in\na fashion requiring copyright permission, other than the making of an exact copy. The\nresulting work is called a “modified version” of the earlier work or a\nwork “based on” the earlier work.\n\nA “covered work” means either the unmodified Program or a work based on\nthe Program.\n\nTo “propagate” a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for infringement under\napplicable copyright law, except executing it on a computer or modifying a private\ncopy. Propagation includes copying, distribution (with or without modification),\nmaking available to the public, and in some countries other activities as well.\n\nTo “convey” a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through a computer\nnetwork, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays “Appropriate Legal Notices” to the\nextent that it includes a convenient and prominently visible feature that **(1)**\ndisplays an appropriate copyright notice, and **(2)** tells the user that there is no\nwarranty for the work (except to the extent that warranties are provided), that\nlicensees may convey the work under this License, and how to view a copy of this\nLicense. If the interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n### 1. Source Code\n\nThe “source code” for a work means the preferred form of the work for\nmaking modifications to it. “Object code” means any non-source form of a\nwork.\n\nA “Standard Interface” means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of interfaces\nspecified for a particular programming language, one that is widely used among\ndevelopers working in that language.\n\nThe “System Libraries” of an executable work include anything, other than\nthe work as a whole, that **(a)** is included in the normal form of packaging a Major\nComponent, but which is not part of that Major Component, and **(b)** serves only to\nenable use of the work with that Major Component, or to implement a Standard\nInterface for which an implementation is available to the public in source code form.\nA “Major Component”, in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system (if any) on which\nthe executable work runs, or a compiler used to produce the work, or an object code\ninterpreter used to run it.\n\nThe “Corresponding Source” for a work in object code form means all the\nsource code needed to generate, install, and (for an executable work) run the object\ncode and to modify the work, including scripts to control those activities. However,\nit does not include the work's System Libraries, or general-purpose tools or\ngenerally available free programs which are used unmodified in performing those\nactivities but which are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for the work, and\nthe source code for shared libraries and dynamically linked subprograms that the work\nis specifically designed to require, such as by intimate data communication or\ncontrol flow between those subprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can regenerate\nautomatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same work.\n\n### 2. Basic Permissions\n\nAll rights granted under this License are granted for the term of copyright on the\nProgram, and are irrevocable provided the stated conditions are met. This License\nexplicitly affirms your unlimited permission to run the unmodified Program. The\noutput from running a covered work is covered by this License only if the output,\ngiven its content, constitutes a covered work. This License acknowledges your rights\nof fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey, without\nconditions so long as your license otherwise remains in force. You may convey covered\nworks to others for the sole purpose of having them make modifications exclusively\nfor you, or provide you with facilities for running those works, provided that you\ncomply with the terms of this License in conveying all material for which you do not\ncontrol copyright. Those thus making or running the covered works for you must do so\nexclusively on your behalf, under your direction and control, on terms that prohibit\nthem from making any copies of your copyrighted material outside their relationship\nwith you.\n\nConveying under any other circumstances is permitted solely under the conditions\nstated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n### 3. Protecting Users' Legal Rights From Anti-Circumvention Law\n\nNo covered work shall be deemed part of an effective technological measure under any\napplicable law fulfilling obligations under article 11 of the WIPO copyright treaty\nadopted on 20 December 1996, or similar laws prohibiting or restricting circumvention\nof such measures.\n\nWhen you convey a covered work, you waive any legal power to forbid circumvention of\ntechnological measures to the extent such circumvention is effected by exercising\nrights under this License with respect to the covered work, and you disclaim any\nintention to limit operation or modification of the work as a means of enforcing,\nagainst the work's users, your or third parties' legal rights to forbid circumvention\nof technological measures.\n\n### 4. Conveying Verbatim Copies\n\nYou may convey verbatim copies of the Program's source code as you receive it, in any\nmedium, provided that you conspicuously and appropriately publish on each copy an\nappropriate copyright notice; keep intact all notices stating that this License and\nany non-permissive terms added in accord with section 7 apply to the code; keep\nintact all notices of the absence of any warranty; and give all recipients a copy of\nthis License along with the Program.\n\nYou may charge any price or no price for each copy that you convey, and you may offer\nsupport or warranty protection for a fee.\n\n### 5. Conveying Modified Source Versions\n\nYou may convey a work based on the Program, or the modifications to produce it from\nthe Program, in the form of source code under the terms of section 4, provided that\nyou also meet all of these conditions:\n\n* **a)** The work must carry prominent notices stating that you modified it, and giving a\nrelevant date.\n* **b)** The work must carry prominent notices stating that it is released under this\nLicense and any conditions added under section 7. This requirement modifies the\nrequirement in section 4 to “keep intact all notices”.\n* **c)** You must license the entire work, as a whole, under this License to anyone who\ncomes into possession of a copy. This License will therefore apply, along with any\napplicable section 7 additional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged. This License gives no permission to license the\nwork in any other way, but it does not invalidate such permission if you have\nseparately received it.\n* **d)** If the work has interactive user interfaces, each must display Appropriate Legal\nNotices; however, if the Program has interactive interfaces that do not display\nAppropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are\nnot by their nature extensions of the covered work, and which are not combined with\nit such as to form a larger program, in or on a volume of a storage or distribution\nmedium, is called an “aggregate” if the compilation and its resulting\ncopyright are not used to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work in an aggregate\ndoes not cause this License to apply to the other parts of the aggregate.\n\n### 6. Conveying Non-Source Forms\n\nYou may convey a covered work in object code form under the terms of sections 4 and\n5, provided that you also convey the machine-readable Corresponding Source under the\nterms of this License, in one of these ways:\n\n* **a)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by the Corresponding Source fixed on a\ndurable physical medium customarily used for software interchange.\n* **b)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by a written offer, valid for at least\nthree years and valid for as long as you offer spare parts or customer support for\nthat product model, to give anyone who possesses the object code either **(1)** a copy of\nthe Corresponding Source for all the software in the product that is covered by this\nLicense, on a durable physical medium customarily used for software interchange, for\na price no more than your reasonable cost of physically performing this conveying of\nsource, or **(2)** access to copy the Corresponding Source from a network server at no\ncharge.\n* **c)** Convey individual copies of the object code with a copy of the written offer to\nprovide the Corresponding Source. This alternative is allowed only occasionally and\nnoncommercially, and only if you received the object code with such an offer, in\naccord with subsection 6b.\n* **d)** Convey the object code by offering access from a designated place (gratis or for\na charge), and offer equivalent access to the Corresponding Source in the same way\nthrough the same place at no further charge. You need not require recipients to copy\nthe Corresponding Source along with the object code. If the place to copy the object\ncode is a network server, the Corresponding Source may be on a different server\n(operated by you or a third party) that supports equivalent copying facilities,\nprovided you maintain clear directions next to the object code saying where to find\nthe Corresponding Source. Regardless of what server hosts the Corresponding Source,\nyou remain obligated to ensure that it is available for as long as needed to satisfy\nthese requirements.\n* **e)** Convey the object code using peer-to-peer transmission, provided you inform\nother peers where the object code and Corresponding Source of the work are being\noffered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the\nCorresponding Source as a System Library, need not be included in conveying the\nobject code work.\n\nA “User Product” is either **(1)** a “consumer product”, which\nmeans any tangible personal property which is normally used for personal, family, or\nhousehold purposes, or **(2)** anything designed or sold for incorporation into a\ndwelling. In determining whether a product is a consumer product, doubtful cases\nshall be resolved in favor of coverage. For a particular product received by a\nparticular user, “normally used” refers to a typical or common use of\nthat class of product, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected to use, the\nproduct. A product is a consumer product regardless of whether the product has\nsubstantial commercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n“Installation Information” for a User Product means any methods,\nprocedures, authorization keys, or other information required to install and execute\nmodified versions of a covered work in that User Product from a modified version of\nits Corresponding Source. The information must suffice to ensure that the continued\nfunctioning of the modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or specifically for\nuse in, a User Product, and the conveying occurs as part of a transaction in which\nthe right of possession and use of the User Product is transferred to the recipient\nin perpetuity or for a fixed term (regardless of how the transaction is\ncharacterized), the Corresponding Source conveyed under this section must be\naccompanied by the Installation Information. But this requirement does not apply if\nneither you nor any third party retains the ability to install modified object code\non the User Product (for example, the work has been installed in ROM).\n\nThe requirement to provide Installation Information does not include a requirement to\ncontinue to provide support service, warranty, or updates for a work that has been\nmodified or installed by the recipient, or for the User Product in which it has been\nmodified or installed. Access to a network may be denied when the modification itself\nmaterially and adversely affects the operation of the network or violates the rules\nand protocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided, in accord with\nthis section must be in a format that is publicly documented (and with an\nimplementation available to the public in source code form), and must require no\nspecial password or key for unpacking, reading or copying.\n\n### 7. Additional Terms\n\n“Additional permissions” are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions. Additional\npermissions that are applicable to the entire Program shall be treated as though they\nwere included in this License, to the extent that they are valid under applicable\nlaw. If additional permissions apply only to part of the Program, that part may be\nused separately under those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option remove any\nadditional permissions from that copy, or from any part of it. (Additional\npermissions may be written to require their own removal in certain cases when you\nmodify the work.) You may place additional permissions on material, added by you to a\ncovered work, for which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you add to a\ncovered work, you may (if authorized by the copyright holders of that material)\nsupplement the terms of this License with terms:\n\n* **a)** Disclaiming warranty or limiting liability differently from the terms of\nsections 15 and 16 of this License; or\n* **b)** Requiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices displayed by works\ncontaining it; or\n* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that\nmodified versions of such material be marked in reasonable ways as different from the\noriginal version; or\n* **d)** Limiting the use for publicity purposes of names of licensors or authors of the\nmaterial; or\n* **e)** Declining to grant rights under trademark law for use of some trade names,\ntrademarks, or service marks; or\n* **f)** Requiring indemnification of licensors and authors of that material by anyone\nwho conveys the material (or modified versions of it) with contractual assumptions of\nliability to the recipient, for any liability that these contractual assumptions\ndirectly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered “further\nrestrictions” within the meaning of section 10. If the Program as you received\nit, or any part of it, contains a notice stating that it is governed by this License\nalong with a term that is a further restriction, you may remove that term. If a\nlicense document contains a further restriction but permits relicensing or conveying\nunder this License, you may add to a covered work material governed by the terms of\nthat license document, provided that the further restriction does not survive such\nrelicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you must place, in\nthe relevant source files, a statement of the additional terms that apply to those\nfiles, or a notice indicating where to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the form of a\nseparately written license, or stated as exceptions; the above requirements apply\neither way.\n\n### 8. Termination\n\nYou may not propagate or modify a covered work except as expressly provided under\nthis License. Any attempt otherwise to propagate or modify it is void, and will\nautomatically terminate your rights under this License (including any patent licenses\ngranted under the third paragraph of section 11).\n\nHowever, if you cease all violation of this License, then your license from a\nparticular copyright holder is reinstated **(a)** provisionally, unless and until the\ncopyright holder explicitly and finally terminates your license, and **(b)** permanently,\nif the copyright holder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is reinstated permanently\nif the copyright holder notifies you of the violation by some reasonable means, this\nis the first time you have received notice of violation of this License (for any\nwork) from that copyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the licenses of\nparties who have received copies or rights from you under this License. If your\nrights have been terminated and not permanently reinstated, you do not qualify to\nreceive new licenses for the same material under section 10.\n\n### 9. Acceptance Not Required for Having Copies\n\nYou are not required to accept this License in order to receive or run a copy of the\nProgram. Ancillary propagation of a covered work occurring solely as a consequence of\nusing peer-to-peer transmission to receive a copy likewise does not require\nacceptance. However, nothing other than this License grants you permission to\npropagate or modify any covered work. These actions infringe copyright if you do not\naccept this License. Therefore, by modifying or propagating a covered work, you\nindicate your acceptance of this License to do so.\n\n### 10. Automatic Licensing of Downstream Recipients\n\nEach time you convey a covered work, the recipient automatically receives a license\nfrom the original licensors, to run, modify and propagate that work, subject to this\nLicense. You are not responsible for enforcing compliance by third parties with this\nLicense.\n\nAn “entity transaction” is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an organization, or\nmerging organizations. If propagation of a covered work results from an entity\ntransaction, each party to that transaction who receives a copy of the work also\nreceives whatever licenses to the work the party's predecessor in interest had or\ncould give under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if the predecessor\nhas it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the rights granted or\naffirmed under this License. For example, you may not impose a license fee, royalty,\nor other charge for exercise of rights granted under this License, and you may not\ninitiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging\nthat any patent claim is infringed by making, using, selling, offering for sale, or\nimporting the Program or any portion of it.\n\n### 11. Patents\n\nA “contributor” is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The work thus\nlicensed is called the contributor's “contributor version”.\n\nA contributor's “essential patent claims” are all patent claims owned or\ncontrolled by the contributor, whether already acquired or hereafter acquired, that\nwould be infringed by some manner, permitted by this License, of making, using, or\nselling its contributor version, but do not include claims that would be infringed\nonly as a consequence of further modification of the contributor version. For\npurposes of this definition, “control” includes the right to grant patent\nsublicenses in a manner consistent with the requirements of this License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license\nunder the contributor's essential patent claims, to make, use, sell, offer for sale,\nimport and otherwise run, modify and propagate the contents of its contributor\nversion.\n\nIn the following three paragraphs, a “patent license” is any express\nagreement or commitment, however denominated, not to enforce a patent (such as an\nexpress permission to practice a patent or covenant not to sue for patent\ninfringement). To “grant” such a patent license to a party means to make\nsuch an agreement or commitment not to enforce a patent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license, and the\nCorresponding Source of the work is not available for anyone to copy, free of charge\nand under the terms of this License, through a publicly available network server or\nother readily accessible means, then you must either **(1)** cause the Corresponding\nSource to be so available, or **(2)** arrange to deprive yourself of the benefit of the\npatent license for this particular work, or **(3)** arrange, in a manner consistent with\nthe requirements of this License, to extend the patent license to downstream\nrecipients. “Knowingly relying” means you have actual knowledge that, but\nfor the patent license, your conveying the covered work in a country, or your\nrecipient's use of the covered work in a country, would infringe one or more\nidentifiable patents in that country that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or arrangement, you\nconvey, or propagate by procuring conveyance of, a covered work, and grant a patent\nlicense to some of the parties receiving the covered work authorizing them to use,\npropagate, modify or convey a specific copy of the covered work, then the patent\nlicense you grant is automatically extended to all recipients of the covered work and\nworks based on it.\n\nA patent license is “discriminatory” if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on the\nnon-exercise of one or more of the rights that are specifically granted under this\nLicense. You may not convey a covered work if you are a party to an arrangement with\na third party that is in the business of distributing software, under which you make\npayment to the third party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties who would receive\nthe covered work from you, a discriminatory patent license **(a)** in connection with\ncopies of the covered work conveyed by you (or copies made from those copies), or **(b)**\nprimarily for and in connection with specific products or compilations that contain\nthe covered work, unless you entered into that arrangement, or that patent license\nwas granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting any implied\nlicense or other defenses to infringement that may otherwise be available to you\nunder applicable patent law.\n\n### 12. No Surrender of Others' Freedom\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise)\nthat contradict the conditions of this License, they do not excuse you from the\nconditions of this License. If you cannot convey a covered work so as to satisfy\nsimultaneously your obligations under this License and any other pertinent\nobligations, then as a consequence you may not convey it at all. For example, if you\nagree to terms that obligate you to collect a royalty for further conveying from\nthose to whom you convey the Program, the only way you could satisfy both those terms\nand this License would be to refrain entirely from conveying the Program.\n\n### 13. Use with the GNU Affero General Public License\n\nNotwithstanding any other provision of this License, you have permission to link or\ncombine any covered work with a work licensed under version 3 of the GNU Affero\nGeneral Public License into a single combined work, and to convey the resulting work.\nThe terms of this License will continue to apply to the part which is the covered\nwork, but the special requirements of the GNU Affero General Public License, section\n13, concerning interaction through a network will apply to the combination as such.\n\n### 14. Revised Versions of this License\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU\nGeneral Public License from time to time. Such new versions will be similar in spirit\nto the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies that\na certain numbered version of the GNU General Public License “or any later\nversion” applies to it, you have the option of following the terms and\nconditions either of that numbered version or of any later version published by the\nFree Software Foundation. If the Program does not specify a version number of the GNU\nGeneral Public License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions of the GNU\nGeneral Public License can be used, that proxy's public statement of acceptance of a\nversion permanently authorizes you to choose that version for the Program.\n\nLater license versions may give you additional or different permissions. However, no\nadditional obligations are imposed on any author or copyright holder as a result of\nyour choosing to follow a later version.\n\n### 15. Disclaimer of Warranty\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER\nEXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE\nQUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n### 16. Limitation of Liability\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY\nCOPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS\nPERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,\nINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nPROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE\nOR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE\nWITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n### 17. Interpretation of Sections 15 and 16\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be\ngiven local legal effect according to their terms, reviewing courts shall apply local\nlaw that most closely approximates an absolute waiver of all civil liability in\nconnection with the Program, unless a warranty or assumption of liability accompanies\na copy of the Program in return for a fee.\n\n_END OF TERMS AND CONDITIONS_\n\n## How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest possible use to\nthe public, the best way to achieve this is to make it free software which everyone\ncan redistribute and change under these terms.\n\nTo do so, attach the following notices to the program. It is safest to attach them\nto the start of each source file to most effectively state the exclusion of warranty;\nand each file should have at least the “copyright” line and a pointer to\nwhere the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type 'show c' for details.\n\nThe hypothetical commands `show w` and `show c` should show the appropriate parts of\nthe General Public License. Of course, your program's commands might be different;\nfor a GUI interface, you would use an “about box”.\n\nYou should also get your employer (if you work as a programmer) or school, if any, to\nsign a “copyright disclaimer” for the program, if necessary. For more\ninformation on this, and how to apply and follow the GNU GPL, see\n&lt;<http://www.gnu.org/licenses/>&gt;.\n\nThe GNU General Public License does not permit incorporating your program into\nproprietary programs. If your program is a subroutine library, you may consider it\nmore useful to permit linking proprietary applications with the library. If this is\nwhat you want to do, use the GNU Lesser General Public License instead of this\nLicense. But first, please read\n&lt;<http://www.gnu.org/philosophy/why-not-lgpl.html>&gt;.\n\n## ADDITIONAL TERMS per GNU GPL Section 7\n\nNo trademark or publicity rights are granted. This license does NOT give you\nany right, title or interest in \"Command & Conquer\" or any other Electronic Arts\ntrademark. You may not distribute any modification of this program using any\nElectronic Arts trademark or claim any affiliation or association with\nElectronic Arts Inc. or its affiliates or their employees.\n\nAny propagation or conveyance of this program must include this copyright\nnotice and these terms.\n\nIf you convey this program (or any modifications of it) and assume\ncontractual liability for the program to recipients of it, you agree to\nindemnify Electronic Arts for any liability that those contractual\nassumptions impose on Electronic Arts.\n\nYou may not misrepresent the origins of this program; modified versions of\nthe program must be marked as such and not identified as the original program.\n\nThis disclaimer supplements the one included in the General Public License.\nTO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS PROGRAM IS\nPROVIDED TO YOU \"AS IS,\" WITH ALL FAULTS, WITHOUT WARRANTY OF ANY KIND, AND\nYOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF SATISFACTORY QUALITY AND\nPERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS DISCLAIMS ANY AND ALL EXPRESS,\nIMPLIED OR STATUTORY WARRANTIES, INCLUDING IMPLIED WARRANTIES OF\nMERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE,\nNONINFRINGEMENT OF THIRD PARTY RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A\nCOURSE OF DEALING, USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT\nAGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL\nMEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR\nERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE WITH THIRD PARTY SOFTWARE\nOR THAT ANY ERRORS IN THE PROGRAM WILL BE CORRECTED. NO ORAL OR WRITTEN ADVICE\nPROVIDED BY ELECTRONIC ARTS OR ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A\nWARRANTY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON\nIMPLIED WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A\nCONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY NOT APPLY\nTO YOU.\n"
  },
  {
    "path": "README.md",
    "content": "# Command & Conquer Remastered Collection\n\nThis repository includes source code for TiberianDawn.dll, RedAlert.dll and the Map Editor for the Command & Conquer Remastered Collection. This release provides support to the [Steam Workshop](https://steamcommunity.com/workshop/browse/?appid=1213210) for the C&C Remaster Collection.\n\n\n## Dependencies\n\nThe following dependencies must be installed to successfully build the solution;\n\n- Windows 8.1 SDK\n- MFC for Visual Studio C++ \n\n\n## Compiling (Win32 Only)\n\nTo use the compiled binaries, you must own the game. The C&C Remastered Collection is available for purchase on [EA App](https://www.ea.com/games/command-and-conquer/command-and-conquer-remastered/buy/pc) or [Steam](https://store.steampowered.com/app/1213210/Command__Conquer_Remastered_Collection/).\n\nThe quickest way to build all configurations in the project is open [CnCRemastered.sln](CnCRemastered.sln) in Microsoft Visual Studio (we recommend using 2017 as later versions report an error due to a packing mismatch with the Windows SDK headers) and select “Build” from the toolbar, then select “Batch Build”. Click the \"Select All\" button, then click the \"Rebuild\" button.\n\nWhen the solution has finished building, the compiled binaries can be found in the newly created `bin` folder in the root of the repository.\n\n\n## Contributing\n\nThis repository will not be accepting any contributions (pull requests, issues, etc). If you wish to create changes to the source code and encourage collaboration, please create a fork of the repository under your GitHub user/organization space.\n\n\n## Support\n\nThis repository is for preservation purposes only and is archived without support. \n\n\n## License\n\nThis repository and its contents are licensed under the GPL v3 license, with additional terms applied. Please see [LICENSE.md](LICENSE.md) for details. \n"
  },
  {
    "path": "REDALERT/2KEYFRAM.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/2KEYFRAM.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : KEYFRAME.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/25/95                                                     *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_Build_Frame_Count -- Fetches the number of frames in data block.                      *\n *   Get_Build_Frame_Width -- Fetches the width of the shape image.                            *\n *   Get_Build_Frame_Height -- Fetches the height of the shape image.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n#define SUBFRAMEOFFS\t\t\t7\t// 3 1/2 frame offsets loaded (2 offsets/frame)\n\n\n#define\tApply_Delta(buffer, delta)\t\tApply_XOR_Delta((char*)(buffer), (char*)(delta))\n\ntypedef struct {\n\tunsigned short frames;\n\tunsigned short x;\n\tunsigned short y;\n\tunsigned short width;\n\tunsigned short height;\n\tunsigned short largest_frame_size;\n\tshort\t\t\t\tflags;\n} KeyFrameHeaderType;\n\n#define\tINITIAL_BIG_SHAPE_BUFFER_SIZE\t8000000\n#define\tTHEATER_BIG_SHAPE_BUFFER_SIZE 4000000\n#define\tUNCOMPRESS_MAGIC_NUMBER\t\t\t56789\n\nunsigned\tBigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;\nunsigned\tTheaterShapeBufferLength = THEATER_BIG_SHAPE_BUFFER_SIZE;\nextern \"C\"{\n\tchar\t\t*BigShapeBufferStart = NULL;\n\tchar\t\t*TheaterShapeBufferStart = NULL;\n\tBOOL\t\tUseBigShapeBuffer = FALSE;\n\tbool\t\tIsTheaterShape = false;\n}\n#ifdef FIXIT_SCORE_CRASH\n/*\n** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.\n*/\nbool\t\tOriginalUseBigShapeBuffer = false;\n#endif\t//FIXIT\nchar\t\t*BigShapeBufferPtr = NULL;\nint\t\t\tTotalBigShapes=0;\nBOOL\t\tReallocShapeBufferFlag = FALSE;\n\nchar\t\t*TheaterShapeBufferPtr = NULL;\nint\t\t\tTotalTheaterShapes = 0;\n\n\n#define MAX_SLOTS 1500\n#define THEATER_SLOT_START 1000\n\nchar\t**KeyFrameSlots [MAX_SLOTS];\nint \tTotalSlotsUsed=0;\nint\t\tTheaterSlotsUsed = THEATER_SLOT_START;\n\n\n\ntypedef struct tShapeHeaderType{\n\tunsigned draw_flags;\n\tchar\t\t*shape_data;\n\tint\t\tshape_buffer;\t\t//1 if shape is in theater buffer\n} ShapeHeaderType;\n\nstatic int Length;\n\nvoid *Get_Shape_Header_Data(void *ptr)\n{\n\tif (UseBigShapeBuffer) {\n\n\t\tShapeHeaderType *header = (ShapeHeaderType*) ptr;\n\t\treturn ((void*)  (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );\n\n\t} else {\n\t\treturn (ptr);\n\t}\n}\n\nint Get_Last_Frame_Length(void)\n{\n\treturn(Length);\n}\n\n\nvoid Reset_Theater_Shapes (void)\n{\n\t/*\n\t** Delete any previously allocated slots\n\t*/\n\tfor (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++) {\n\t\tdelete [] KeyFrameSlots [i];\n\t}\n\n\tTheaterShapeBufferPtr = TheaterShapeBufferStart;\n\tTotalTheaterShapes = 0;\n\tTheaterSlotsUsed = THEATER_SLOT_START;\n}\n\n\nvoid Reallocate_Big_Shape_Buffer(void)\n{\n\tif (ReallocShapeBufferFlag) {\n\t\tBigShapeBufferLength += 2000000;\t\t\t\t\t\t\t//Extra 2 Mb of uncompressed shape space\n\t\tBigShapeBufferPtr -= (unsigned)BigShapeBufferStart;\n\t\tMemory_Error = NULL;\n\t\tBigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);\n\t\tMemory_Error = &Memory_Error_Handler;\n\t\t/*\n\t\t** If we have run out of memory then disable the uncompressed shapes\n\t\t** It may still be possible to continue with compressed shapes\n\t\t*/\n\t\tif (!BigShapeBufferStart) {\n\t\t\tUseBigShapeBuffer = false;\n\t\t\treturn;\n\t\t}\n\t\tBigShapeBufferPtr += (unsigned)BigShapeBufferStart;\n\t\tReallocShapeBufferFlag = FALSE;\n\t}\n}\n\n\n//#ifdef FIXIT_SCORE_CRASH\n/***********************************************************************************************\n * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/19/96 2:37PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Disable_Uncompressed_Shapes (void)\n{\n\tUseBigShapeBuffer = false;\n}\n\n\n\n/***********************************************************************************************\n * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    11/19/96 2:37PM ST : Created                                                             *\n *=============================================================================================*/\nvoid Enable_Uncompressed_Shapes (void)\n{\n\tUseBigShapeBuffer = OriginalUseBigShapeBuffer;\n}\n//#endif\t//FIXIT\n\nvoid Check_Use_Compressed_Shapes (void)\n{\n#if (1)\t// Uncompressed shapes enabled for performance reasons. We don't need to worry about memory. \n\t\t\t// Uncompressed shapes don't seem to work in RA for rotated/scaled objects so wherever scale/rotate is used, \n\t\t\t// we will need to disable it (like in Techno_Draw_Object). ST - 11/6/2019 2:09PM\n\tUseBigShapeBuffer = true;\n\tOriginalUseBigShapeBuffer = true;\n\n#else\n\tMEMORYSTATUS\tmem_info;\n\n\tmem_info.dwLength=sizeof(mem_info);\n\tGlobalMemoryStatus(&mem_info);\n\n\tUseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Keep track of our original decision about whether to use cached shapes.\n\t** This is needed for the score screen crash fix.\n\t*/\n\tOriginalUseBigShapeBuffer = UseBigShapeBuffer;\n#endif\t//FIXIT\n#endif\n}\n\n\n\n\n\nunsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)\n{\n#ifdef FIXIT_SCORE_CRASH\n\tchar *ptr;\n\tunsigned long offcurr, offdiff;\n#else\n\tchar *ptr, *lockptr;//, *uncomp_ptr;\n\tunsigned long offcurr, off16, offdiff;\n#endif\n\tunsigned long offset[SUBFRAMEOFFS];\n\tKeyFrameHeaderType *keyfr;\n\tunsigned short buffsize, currframe, subframe;\n\tunsigned long length = 0;\n\tchar frameflags;\n\tunsigned long return_value;\n\tchar *temp_shape_ptr;\n\n\t//\n\t// valid pointer??\n\t//\n\tLength = 0;\n\tif ( !dataptr || !buffptr ) {\n\t\treturn(0);\n\t}\n\n\t//\n\t// look at header then check that frame to build is not greater\n\t// than total frames\n\t//\n\tkeyfr = (KeyFrameHeaderType *) dataptr;\n\n\tif ( framenumber >= keyfr->frames ) {\n\t\treturn(0);\n\t}\n\n\n\tif (UseBigShapeBuffer) {\n\t\t/*\n\t\t** If we havnt yet allocated memory for uncompressed shapes then do so now.\n\t\t**\n\t\t*/\n\t\tif (!BigShapeBufferStart) {\n\t\t\tBigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);\n\t\t\tBigShapeBufferPtr = BigShapeBufferStart;\n\n\t\t\t/*\n\t\t\t** Allocate memory for theater specific uncompressed shapes\n\t\t\t*/\n\t\t\tTheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);\n\t\t\tTheaterShapeBufferPtr = TheaterShapeBufferStart;\n\t\t}\n\n\t\t/*\n\t\t** If we are running out of memory (<10k left) for uncompressed shapes\n\t\t** then allocate some more.\n\t\t*/\n\t\tif (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128000) {\n\t\t\tReallocShapeBufferFlag = TRUE;\n\t\t}\n\n\t\t/*\n\t\t** If this animation was not previously uncompressed then\n\t\t** allocate memory to keep the pointers to the uncompressed data\n\t\t** for these animation frames\n\t\t*/\n\t\tif (keyfr->x != UNCOMPRESS_MAGIC_NUMBER) {\n\t\t\tkeyfr->x = UNCOMPRESS_MAGIC_NUMBER;\n\t\t\tif (IsTheaterShape) {\n\t\t\t\tkeyfr->y = TheaterSlotsUsed;\n\t\t\t\tTheaterSlotsUsed++;\n\t\t\t} else {\n\t\t\t\tkeyfr->y = TotalSlotsUsed;\n\t\t\t\tTotalSlotsUsed++;\n\t\t\t}\n\t\t\t/*\n\t\t\t** Allocate and clear the memory for the shape info\n\t\t\t*/\n\t\t\tKeyFrameSlots[keyfr->y]= new char *[keyfr->frames];\n\t\t\tmemset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);\n\t\t}\n\n\t\t/*\n\t\t** If this frame was previously uncompressed then just return\n\t\t** a pointer to the raw data\n\t\t*/\n\t\tif (*(KeyFrameSlots[keyfr->y]+framenumber)) {\n\t\t\tif (IsTheaterShape) {\n\t\t\t\treturn ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));\n\t\t\t} else {\n\t\t\t\treturn ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));\n\t\t\t}\n\t\t}\n\t}\n\n\t// calc buff size\n\tbuffsize = keyfr->width * keyfr->height;\n\n\t// get offset into data\n\tptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );\n\tMem_Copy( ptr, &offset[0], 12L );\n\tframeflags = (char)(offset[0] >> 24);\n\n\n\tif ( (frameflags & KF_KEYFRAME) ) {\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\t} else {\t// key delta or delta\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\tcurrframe = (unsigned short)offset[1];\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );\n\t\t\tMem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t}\n\n\t\t// key frame\n\t\toffcurr = offset[1] & 0x00FFFFFFL;\n\n\t\t// key delta\n\t\toffdiff = (offset[0] & 0x00FFFFFFL) - offcurr;\n\n\t\tptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );\n\n\t\tif (keyfr->flags & 1 ) {\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, 768L );\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n#endif\n\n\t\tlength = LCW_Uncompress( ptr, buffptr, buffsize );\n\n\t\tif (length > buffsize) {\n\t\t\treturn(0);\n\t\t}\n\n#ifndef FIXIT_SCORE_CRASH\n\t\tif ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\toff16 = (unsigned long)ptr & 0x00003FFFL;\n\n\t\t\toffcurr += offdiff;\n\t\t\toffdiff = 0;\n\t\t}\n#endif\n\n\t\tlength = buffsize;\n\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n\n\t\tif ( (frameflags & KF_DELTA) ) {\n\t\t\t// adjust to delta after the keydelta\n\n\t\t\tcurrframe++;\n\t\t\tsubframe = 2;\n\n\t\t\twhile (currframe <= framenumber) {\n\t\t\t\toffdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;\n\n#ifndef FIXIT_SCORE_CRASH\n\t\t\t\tif ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {\n\n\t\t\t\t\tptr = (char *)Add_Long_To_Pointer( ptr, offdiff );\n\t\t\t\t\toff16 = (unsigned long)lockptr & 0x00003FFFL;\n\n\t\t\t\t\toffcurr += offdiff;\n\t\t\t\t\toffdiff = 0;\n\t\t\t\t}\n#endif\n\n\t\t\t\tlength = buffsize;\n\t\t\t\tApply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));\n\n\t\t\t\tcurrframe++;\n\t\t\t\tsubframe += 2;\n\n\t\t\t\tif ( subframe >= (SUBFRAMEOFFS - 1) &&\n\t\t\t\t\tcurrframe <= framenumber ) {\n\t\t\t\t\tMem_Copy( Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t\t\t(((unsigned long)currframe << 3) +\n\t\t\t\t\t\t\t\t\tsizeof(KeyFrameHeaderType)) ),\n\t\t\t\t\t\t&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );\n\t\t\t\t\tsubframe = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (UseBigShapeBuffer) {\n\t\t/*\n\t\t** Save the uncompressed shape data so we dont have to uncompress it\n\t\t** again next time its drawn.\n\t\t** We keep a space free before the raw shape data so we can add line\n\t\t** header info before the shape is drawn for the first time\n\t\t*/\n\n\t\tif (IsTheaterShape) {\n\t\t\t/*\n\t\t\t** Shape is a theater specific shape\n\t\t\t*/\n\t\t\treturn_value = (unsigned long) TheaterShapeBufferPtr;\n\t\t\ttemp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);\n\t\t\t/*\n\t\t\t** align the actual shape data\n\t\t\t*/\n\t\t\tif (3 & (unsigned)temp_shape_ptr) {\n\t\t\t\ttemp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);\n\t\t\t}\n\n\t\t\tmemcpy (temp_shape_ptr , buffptr , length);\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1;\t\t\t\t\t\t//Flag that headers need to be generated\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart;\t\t//pointer to old raw shape data\n\t\t\t((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1;\t//Theater buffer\n\t\t\t*(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;\n\t\t\tTheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);\n\t\t\t/*\n\t\t\t** Align the next shape\n\t\t\t*/\n\t\t\tif (3 & (unsigned)TheaterShapeBufferPtr) {\n\t\t\t\tTheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tLength = length;\n\t\t\treturn (return_value);\n\n\t\t} else {\n\n\n\t\t\treturn_value=(unsigned long)BigShapeBufferPtr;\n\t\t\ttemp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);\n\t\t\t/*\n\t\t\t** align the actual shape data\n\t\t\t*/\n\t\t\tif (3 & (unsigned)temp_shape_ptr) {\n\t\t\t\ttemp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tmemcpy (temp_shape_ptr , buffptr , length);\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1;\t\t\t\t\t\t//Flag that headers need to be generated\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart;\t\t//pointer to old raw shape data\n\t\t\t((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0;\t//Normal Big Shape Buffer\n\t\t\t*(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;\n\t\t\tBigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);\n\t\t\t// Align the next shape\n\t\t\tif (3 & (unsigned)BigShapeBufferPtr) {\n\t\t\t\tBigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);\n\t\t\t}\n\t\t\tLength = length;\n\t\t\treturn (return_value);\n\t\t}\n\n\t} else {\n\t\treturn ((unsigned long)buffptr);\n\t}\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Count -- Fetches the number of frames in data block.                        *\n *                                                                                             *\n *    Use this routine to determine the number of shapes within the data block.                *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of shapes in the data block.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Count(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->frames);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_X(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->x);\n\t}\n\treturn(0);\n}\n\n\nunsigned short Get_Build_Frame_Y(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->y);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Width -- Fetches the width of the shape image.                              *\n *                                                                                             *\n *    Use this routine to fetch the width of the shapes within the keyframe shape data block.  *\n *    All shapes within the block have the same width.                                         *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the width of the shapes in the block -- expressed in pixels.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Width(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->width);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Get_Build_Frame_Height -- Fetches the height of the shape image.                            *\n *                                                                                             *\n *    Use this routine to fetch the height of the shapes within the keyframe shape data block. *\n *    All shapes within the block have the same height.                                        *\n *                                                                                             *\n * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the height of the shapes in the block -- expressed in pixels.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Commented                                                                *\n *=============================================================================================*/\nunsigned short Get_Build_Frame_Height(void const *dataptr)\n{\n\tif (dataptr) {\n\t\treturn(((KeyFrameHeaderType const *)dataptr)->height);\n\t}\n\treturn(0);\n}\n\n\nbool Get_Build_Frame_Palette(void const * dataptr, void * palette)\n{\n\tif (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {\n\t\tchar const * ptr = (char const *)Add_Long_To_Pointer( dataptr,\n\t\t\t\t\t\t\t( (( (long)sizeof(unsigned long) << 1) *\n\t\t\t\t\t\t\t\t((KeyFrameHeaderType *) dataptr)->frames ) +\n\t\t\t\t\t\t\t16 + sizeof(KeyFrameHeaderType) ) );\n\n\t\tmemcpy(palette, ptr, 768L);\n\t\treturn(true);\n\t}\n\treturn(false);\n}"
  },
  {
    "path": "REDALERT/2SUPPORT.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\2support.asv   5.0   11 Nov 1996 09:40:36   JOE_BOSTIC  $\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : SUPPORT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : September 23, 1993                       *\n;*                                                                         *\n;*                  Last Update : May 10, 1994   [JLB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   strtrim -- Remove the trailing white space from a string.             *\n;*   Fat_Put_Pixel -- Draws a fat pixel.                                   *\n;*   Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*\n;*   Remove_From_List -- Removes a pointer from a list of pointers.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"gbuffer.inc\"\n\tDISPLAY\t\"Command & Conquer assembly support routines.\"\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Fat_Put_Pixel -- Draws a fat pixel.                                     *\n;*                                                                         *\n;*    Use this routine to draw a \"pixel\" that is bigger than 1 pixel       *\n;*    across.  This routine is faster than drawing a similar small shape   *\n;*    and faster than calling Fill_Rect.                                   *\n;*                                                                         *\n;* INPUT:   x,y       -- Screen coordinates to draw the pixel's upper      *\n;*                       left corner.                                      *\n;*                                                                         *\n;*          color     -- The color to render the pixel in.                 *\n;*                                                                         *\n;*          size      -- The number of pixels width of the big \"pixel\".    *\n;*                                                                         *\n;*          page      -- The pointer to a GraphicBuffer class or something *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/17/1994 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)\n\tGLOBAL\tC Fat_Put_Pixel:NEAR\n\tPROC\tFat_Put_Pixel C near\n\tUSES\teax, ebx, ecx, edx, edi, esi\n\n\tARG\tx:DWORD\t\t; X coordinate of upper left pixel corner.\n\tARG\ty:DWORD\t\t; Y coordinate of upper left pixel corner.\n\tARG\tcolor:DWORD\t; Color to use for the \"pixel\".\n\tARG\tsiz:DWORD\t; Size of \"pixel\" to plot (square).\n\tARG\tgpage:DWORD\t; graphic page address to plot onto\n\n\tcmp\t[siz],0\n\tje\tshort ??exit\n\n\t; Set EDI to point to start of logical page memory.\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[gpage]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\n\t; Verify the the Y pixel offset is legal.\n\tmov\teax,[y]\n\tcmp\teax,[(GraphicViewPort ebx).GVPHeight]\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\tmov\tecx,[(GraphicViewPort ebx).GVPWidth]\n\tadd\tecx,[(GraphicViewPort ebx).GVPXAdd]\n\tadd\tecx,[(GraphicViewPort ebx).GVPPitch]\n\tmul\tecx\n\tadd\tedi,eax\n\n\t; Verify the the X pixel offset is legal.\n\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\n\tcmp\tedx,[x]\n\tmov\tedx,ecx\n\tjbe\tshort ??exit\n\tadd\tedi,[x]\n\n\t; Write the pixel to the screen.\n\tmov\tebx,[siz]\t\t; Copy of pixel size.\n\tsub\tedx,ebx\t\t\t; Modulo to reach start of next row.\n\tmov\teax,[color]\n??again:\n\tmov\tecx,ebx\n\trep stosb\n\tadd\tedi,edx\t\t\t; EDI points to start of next row.\n\tdec\t[siz]\n\tjnz\tshort ??again\n\n??exit:\n\tret\n\n\tENDP\tFat_Put_Pixel\n\n\nif 0\n\n;***************************************************************************\n;* strtrim -- Remove the trailing white space from a string.               *\n;*                                                                         *\n;*    Use this routine to remove white space characters from the beginning *\n;*    and end of the string.        The string is modified in place by     *\n;*    this routine.                                                        *\n;*                                                                         *\n;* INPUT:   buffer   -- Pointer to the string to modify.                   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl strtrim(BYTE *buffer);\n\tGLOBAL\tC strtrim :NEAR\n\tPROC\tstrtrim C near\n\tUSES\tax, edi, esi\n\n\tARG\tbuffer:DWORD\t\t; Pointer to string to modify.\n\n\tcmp\t[buffer],0\n\tje\tshort ??fini\n\n\t; Prepare for string scanning by loading pointers.\n\tcld\n\tmov\tesi,[buffer]\n\tmov\tedi,esi\n\n\t; Strip white space from the start of the string.\n??looper:\n\tlodsb\n\tcmp\tal,20h\t\t\t; Space\n\tje\tshort ??looper\n\tcmp\tal,9\t\t\t; TAB\n\tje\tshort ??looper\n\tstosb\n\n\t; Copy the rest of the string.\n??gruntloop:\n\tlodsb\n\tstosb\n\tor\tal,al\n\tjnz\tshort ??gruntloop\n\tdec\tedi\n\t; Strip the white space from the end of the string.\n??looper2:\n\tmov\t[edi],al\n\tdec\tedi\n\tmov\tah,[edi]\n\tcmp\tah,20h\n\tje\tshort ??looper2\n\tcmp\tah,9\n\tje\tshort ??looper2\n\n??fini:\n\tret\n\n\tENDP\tstrtrim\n\n\n;***************************************************************************\n;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.  *\n;*                                                                         *\n;*    This routine is used to build a special fading table for C&C.  There *\n;*    are certain colors that get faded to and cannot be faded again.      *\n;*    With this rule, it is possible to draw a shadow multiple times and   *\n;*    not have it get any lighter or darker.                               *\n;*                                                                         *\n;* INPUT:   palette  -- Pointer to the 768 byte IBM palette to build from. *\n;*                                                                         *\n;*          dest     -- Pointer to the 256 byte remap table.               *\n;*                                                                         *\n;*          color    -- Color index of the color to \"fade to\".             *\n;*                                                                         *\n;*          frac     -- The fraction to fade to the specified color        *\n;*                                                                         *\n;* OUTPUT:  Returns with pointer to the remap table.                       *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*/\n;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);\n\tGLOBAL\tC Conquer_Build_Fading_Table : NEAR\n\tPROC\tConquer_Build_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\nALLOWED_COUNT\tEQU\t16\nALLOWED_START\tEQU\t256-ALLOWED_COUNT\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini1\n\tcmp\t[dest],0\n\tje\t??fini1\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through a limited set of existing colors to find the closest\n\t; matching color.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,ALLOWED_COUNT\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,(ALLOWED_START)*3\n\n\t; BH = color index.\n\tmov\tbh,ALLOWED_START\n??innerloop:\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tjae\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,ALLOWED_START-1\n\tjne\t??mainloop\n\n\t; Fill the remainder of the remap table with values\n\t; that will remap the color to itself.\n\tmov\tecx,ALLOWED_COUNT\n??fillerloop:\n\tinc\tbl\n\tmov\tal,bl\n\tstosb\n\tloop\t??fillerloop\n\n??fini1:\n\tmov\tesi,[dest]\n\tmov\teax,esi\n\tret\n\n\tENDP\tConquer_Build_Fading_Table\n\n\n;***************************************************************************\n;* Remove_From_List -- Removes a pointer from a list of pointers.          *\n;*                                                                         *\n;*    This low level routine is used to remove a pointer from a list of    *\n;*    pointers.  The trailing pointers are moved downward to fill the      *\n;*    hole.                                                                *\n;*                                                                         *\n;* INPUT:   list     -- Pointer to list of pointer.                        *\n;*                                                                         *\n;*          index    -- Pointer to length of pointer list.                 *\n;*                                                                         *\n;*          ptr      -- The pointer value to search for and remove.        *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/11/1994 JLB : Created.                                             *\n;*   04/22/1994 JLB : Convert to assembly language.                        *\n;*   05/10/1994 JLB : Short pointers now.                                  *\n;*=========================================================================*/\n;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);\n\tGLOBAL\tC Remove_From_List:NEAR\n\tPROC\tRemove_From_List C near\n\tUSES\tedi, esi, ecx, eax\n\tARG\tlist:DWORD\t\t; Pointer to list.\n\tARG\tindex:DWORD\t\t; Pointer to count.\n\tARG\telement:DWORD\t\t; Element to remove.\n\n\t; Fetch the number of elements in the list.  If there are no\n\t; elements, then just exit quickly.\n\tmov\tedi,[index]\n\tmov\tecx,[edi]\n\tjcxz\tshort ??fini2\n\n\t; Fetch pointer to list.\n\tcmp\t[list],0\n\tje\tshort ??fini2\n\tmov\tedi,[list]\n\n\t; Loop through all elements searching for a match.\n\tmov\teax,[element]\n\trepne scasd\n\tjne\tshort ??fini2\t\t; No match found.\n\n\t; Copy all remaining elements down.  If this is the\n\t; last element in the list then nothing needs to be\n\t; copied -- just decrement the list size.\n\tjcxz\tshort ??nocopy\t\t; No copy necessary.\n\tmov\tesi,edi\n\tsub\tedi,4\n\trep movsd\n\n\t; Reduce the list count by one.\n??nocopy:\n\tmov\tedi,[index]\n\tdec\t[DWORD PTR edi]\n\n??fini2:\n\tret\n\n\tENDP\tRemove_From_List\n\n\n; long cdecl Get_EAX();\n\tGLOBAL\tC Get_EAX :NEAR\n\tPROC\tGet_EAX C near\n\tret\n\n\tENDP\tGet_EAX\nendif\n\n\n\tDATASEG\n\nTabA\tDD 6949350\n\tDD 4913933\n\tDD 3474675\n\tDD 2456966\n\tDD 1737338\n\tDD 1228483\n\tDD 868669\n\tDD 614242\n\tDD 434334\n\tDD 307121\n\tDD 217167\n\tDD 153560\n\tDD 108584\n\tDD 76780\n\tDD 54292\n\tDD 38390\n\tDD 27146\n\tDD 19195\n\tDD 13573\n\tDD 9598\n\tDD 6786\n\tDD 4799\n\tDD 3393\n\tDD 2399\n\tDD 1697\n\tDD 1200\n\tDD 848\n\tDD 600\n\tDD 424\n\tDD 300\n\tDD 212\n\tDD 150\n\tDD 106\n\nTabB\tDD 154\n\tDD 218\n\tDD 309\n\tDD 437\n\tDD 618\n\tDD 874\n\tDD 1236\n\tDD 1748\n\tDD 2472\n\tDD 3496\n\tDD 4944\n\tDD 6992\n\tDD 9888\n\tDD 13983\n\tDD 19775\n\tDD 27967\n\tDD 39551\n\tDD 55933\n\tDD 79101\n\tDD 111866\n\tDD 158203\n\tDD 223732\n\tDD 316405\n\tDD 447465\n\tDD 632811\n\tDD 894929\n\tDD 1265621\n\tDD 1789859\n\tDD 2531243\n\tDD 3579718\n\tDD 5062486\n\tDD 7159436\n\tDD 10124971\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Square_Root -- Finds the square root of the fixed pointer parameter.                        *\n;*                                                                                             *\n;* INPUT:   val   -- The fixed point (16:16) value to find the square root of.                 *\n;*                                                                                             *\n;* OUTPUT:  Returns with the square root of the fixed pointer parameter.                       *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   10/04/1995 JLB : Adapted.                                                                 *\n;*=============================================================================================*/\n;unsigned Square_Root(unsigned val);\n\tGLOBAL\tC Square_Root :NEAR\n\tPROC\tSquare_Root C near\n\tUSES\tebx,edx\n\n\tbsr ebx,eax\n\tjz ??zero\n\n\tmul [DWORD 4*ebx + OFFSET TabA]\n\tshrd eax,edx,10h\n\tadd eax, [4*ebx + OFFSET TabB]\n??zero:\n\tret\n\n\tENDP\tSquare_Root\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n"
  },
  {
    "path": "REDALERT/2TXTPRNT.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n;***************************************************************************\n;**      C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S      **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood 32 bit Library                  *\n;*                                                                         *\n;*                    File Name : TXTPRNT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : January 17, 1995                         *\n;*                                                                         *\n;*                  Last Update : January 17, 1995   [PWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   MCGA_Print -- Assembly MCGA text print routine                        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\n;INCLUDE \"mcgaprim.inc\"\n;INCLUDE \".\\gbuffer.inc\"\n\nGLOBAL C Buffer_Print : NEAR\n\nSTRUC GraphicViewPort\nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPPitch\t\tdd\t\t?\t\t; modulo of graphic view port\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nENDS\n\n\n\n;*=========================================================================*\n;* Extern the font pointer which is defined by the font class\t\t   *\n;*=========================================================================*\nGLOBAL\tC FontPtr:DWORD\nGLOBAL\tC FontXSpacing:DWORD\nGLOBAL\tC FontYSpacing:DWORD\nGLOBAL\tC ColorXlat:BYTE\n\n;*=========================================================================*\n;* Define the necessary equates for structures and bounds checking\t   *\n;*=========================================================================*\n; The header of the font file looks like this:\n; \tUWORD\tFontLength;\t\t0\n; \tBYTE\tFontCompress;\t\t2\n;\tBYTE\tFontDataBlocks;\t\t3\n;\tUWORD\tInfoBlockOffset;\t4\n;\tUWORD\tOffsetBlockOffset;\t6\n;\tUWORD\tWidthBlockOffset;\t8\n;\tUWORD\tDataBlockOffset;\t10\n;\tUWORD\tHeightOffset;\t\t12\n; For this reason the following equates have these values:\nFONTINFOBLOCK\t\tEQU\t4\nFONTOFFSETBLOCK\t\tEQU\t6\nFONTWIDTHBLOCK\t\tEQU\t8\nFONTDATABLOCK\t\tEQU\t10\nFONTHEIGHTBLOCK\t\tEQU\t12\n\nFONTINFOMAXHEIGHT\tEQU\t4\nFONTINFOMAXWIDTH\tEQU\t5\n\n\nLOCALS ??\n;*=========================================================================*\n;* Define the color xlate table in the data segment\t\t\t   *\n;*=========================================================================*\n\tDATASEG\nColorXlat\tDB\t000H,001H,002H,003H,004H,005H,006H,007H\n\t\tDB\t008H,009H,00AH,00BH,00CH,00DH,00EH,00FH\n\n\t\tDB\t001H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t002H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t003H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t004H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t005H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t006H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t007H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t008H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t009H,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00AH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00BH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00CH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00DH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00EH,000H,000H,000H,000H,000H,000H,000H\n\t\tDB\t000H,000H,000H,000H,000H,000H,000H,000H\n\n\t\tDB\t00FH\n\tCODESEG\n\n\n;***************************************************************************\n;* MCGA_PRINT -- Assembly MCGA text print routine                          *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* PROTO:                                                                  *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   01/17/1995 PWG : Created.                                             *\n;*=========================================================================*\n\tPROC\tBuffer_Print C near\n\tUSES\tebx,ecx,edx,esi,edi\n\n\tARG\tthis:DWORD\n\tARG\tstring:DWORD\n\tARG\tx_pixel:DWORD\n\tARG\ty_pixel:DWORD\n\tARG\tfcolor:DWORD\n\tARG\tbcolor:DWORD\n\n\tLOCAL\tinfoblock:DWORD\t\t; pointer to info block\n\tLOCAL\toffsetblock:DWORD\t; pointer to offset block  (UWORD *)\n\tLOCAL\twidthblock:DWORD\t; pointer to width block   (BYTE  *)\n\tLOCAL\theightblock:DWORD\t; pointer to height block  (UWORD *)\n\n\tLOCAL\tcurline:DWORD\t\t; pointer to first column of current row.\n\tLOCAL\tbufferwidth:DWORD    \t; width of buffer (vpwidth + Xadd)\n\tLOCAL\tnextdraw:DWORD\t\t; bufferwidth - width of cur character.\n\tLOCAL\tstartdraw:DWORD\t\t; where next character will start being drawn.\n\n\tLOCAL\tchar:DWORD\t\t; current character value.\n\n\tLOCAL\tmaxheight:BYTE\t\t; max height of characters in font.\n\tLOCAL\tbottomblank:BYTE\t; amount of empty space below current character.\n\tLOCAL\tcharheight:BYTE\t\t; true height of current character.\n\tLOCAL\tvpwidth:DWORD\n\tLOCAL\tvpheight:DWORD\n\tLOCAL\toriginal_x:DWORD\t; Starting X position.\n\n\n;-------------------------------- Where to draw -----------------------------------------------\n\t; Set up memory location to start drawing.\n\tmov  \tebx,[this]\t\t\t\t; get a pointer to dest\n\tmov\teax,[(GraphicViewPort ebx).GVPHeight]\t; get height of viewport\n\tmov\t[vpheight],eax\t\t\t\t; save off height of viewport\n\tmov\teax,[(GraphicViewPort ebx).GVPWidth]\t; get width of viewport\n\tmov\t[vpwidth],eax\t\t\t\t; save it off for later\n\tadd\teax,[(GraphicViewPort ebx).GVPXAdd]\t; add in xadd for bytes_per_line\n\tadd\teax,[(GraphicViewPort ebx).GVPPitch]\t; add in pitch of direct draw surface\n\tmov\t[bufferwidth],eax     \t\t\t; save it off for later use.\n\n\tmul\t[y_pixel]\t\t\t\t; multiply rowsize * y_pixel start.\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get start of the viewport\n\tadd\tedi,eax\t\t\t\t\t; add y position to start of vp\n\tmov\t[curline],edi\t\t\t\t; save 0,y address for line feed stuff.\n\tadd\tedi,[x_pixel]\t\t\t\t; add to get starting column in starting row.\n\tmov\t[startdraw],edi\t\t\t\t; save it off.\n\n\tmov\teax,[x_pixel]\n\tmov\t[original_x],eax\n\n;-------------------------------- Create block pointers ----------------------------------------\n\t; Get the pointer to the font.\n\t; We could check for NULL but why waste the time.\n\t; It is up to programmer to make sure it is set.\n\tmov\tesi,[FontPtr]\t\t; Get the font pointer\n\tor\tesi,esi\n\tjz\t??overflow\n\n\t; Set up some pointers to the different memory blocks.\n\t; esi (FontPtr) is added to each to get the true address of each block.\n\t; Many registers are used for P5 optimizations.\n\t; ebx is used for InfoBlock which is then used in the next section.\n\tmovzx\teax,[WORD PTR esi+FONTOFFSETBLOCK]\t; get offset to offset block\n\tmovzx\tebx,[WORD PTR esi+FONTINFOBLOCK]      \t; get offset to info block (must be ebx for height test)\n\tmovzx\tecx,[WORD PTR esi+FONTWIDTHBLOCK] \t; get offset to width block\n\tmovzx\tedx,[WORD PTR esi+FONTHEIGHTBLOCK]\t; get offset to height block\n\n\tadd\teax,esi\t\t\t\t; add offset of FontPtr to offset block\n\tadd\tebx,esi\t\t\t\t; add offset of FontPtr to info block\n\tadd\tecx,esi\t\t\t\t; add offset of FontPtr to width block\n\tadd\tedx,esi\t\t\t\t; add offset of FontPtr to height block\n\n\tmov\t[offsetblock],eax\t\t; save offset to offset block\n\tmov\t[infoblock],ebx\t\t\t; save offset to info block\n\tmov\t[widthblock],ecx   \t\t; save offset to width block\n\tmov\t[heightblock],edx\t\t; save offset to height block\n\n;------------------------------------------ Test for fit ----------------------------------------------\n\t; Test to make sure the height of the max character will fit on this line\n\t; and and not fall out of the viewport.\n\t; remember we set ebx to FONTINFOBLOCK above.\n\tmovzx\teax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.\n\tmov\t[maxheight],al\t\t\t; save it for later use.\n\tadd\teax,[y_pixel]\t\t\t; add current y_value.\n\tcmp\teax,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we're outa here.\n\n\tmov\t[y_pixel],eax\t\t\t; save for next line feed. y value for next line.\n\n\tcld\t\t\t\t\t; Make sure we are always forward copying.\n\n;------------------------ Set palette foreground and background ----------------------------------\n\tmov\teax,[fcolor]\t\t; foreground color\n\tmov\t[ColorXlat+1],al\n\tmov\t[ColorXlat+16],al\n\n\tmov\teax,[bcolor]\t\t; background color\n\tmov\t[ColorXlat],al\n\n;-------------------------------------------------------------------------------------------------\n;----------------------------------------- Main loop ----------------------------------------------\n\t; Now we go into the main loop of reading each character in the string and doing\n\t; something with it.\n??next_char:\n\t; while (*string++)\n\txor\teax,eax\t\t\t\t; zero out since we will just load al.\n\tmov\tesi,[string]\t\t\t; get address on next character.\n\tlodsb\t\t\t\t\t; load the character into al.\n\ttest\teax,0FFH\t\t\t; test to see if character is a NULL\n\tjz\t??done\t\t\t\t; character is NULL, get outa here.\n\n\tmov\tedi,[startdraw]\t\t\t; Load the starting address.\n\n\tmov\t[string],esi\t\t\t; save index into string. (incremented by lodsb)\n\n\tcmp\tal,10\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tcmp\tal,13\t\t\t\t; is the character a line feed?\n\tje\t??line_feed\t\t\t; if so, go to special case.\n\n\tmov\t[char],eax\t\t\t; save the character off for later reference.\n\tmov\tebx,eax\t\t\t\t; save it in ebx for later use also.\n\n\tadd\teax,[widthblock]\t\t; figure address of width of character.\n\tmov\tecx,[x_pixel]\t\t\t; get current x_pixel.\n\tmovzx\tedx,[BYTE PTR eax]\t \t; get the width of the character in dl.\n\tadd\tecx,edx\t\t\t\t; add width of char to current x_pixel.\n\tmov\teax,[FontXSpacing]\n\tadd\tecx,eax\n\tadd\t[startdraw],edx\t\t\t; save start draw for next character.\n\tadd\t[startdraw],eax\t\t\t; adjust for the font spacing value\n\n\tcmp\tecx,[vpwidth]\t\t\t; is the pixel greater then the vp width?\n\tjg\t??force_line_feed\t\t; if so, force a line feed.\n\n\tmov\t[x_pixel],ecx\t\t\t; save value of start of next character.\n\tmov\tecx,[bufferwidth]\t\t; get amount to next y same x (one row down)\n\tsub\tecx,edx\t\t\t\t; take the current width off.\n\tmov\t[nextdraw],ecx\t\t\t; save it to add to edi when done with a row.\n\n\t; At this point we got the character. It is now time to find out specifics\n\t; about drawing the darn thing.\n\t; ebx = char so they can be used as an indexes.\n\t; edx = width of character for loop later.\n\n\t; get offset of data for character into esi.\n\tshl\tebx,1\t\t\t\t; mult by 2 to later use as a WORD index.\n\tmov\tesi,[offsetblock]\t\t; get pointer to begining of offset block.\n\tadd\tesi,ebx\t\t\t\t; index into offset block.\n\tmovzx\tesi,[WORD PTR esi]\t\t; get true offset into data block from FontPtr.\n\tadd\tesi,[FontPtr]\t\t\t; Now add FontPtr address to get true address.\n\n\t; Get top and bottom blank sizes and the true height of the character.\n\tadd\tebx,[heightblock]\t\t; point ebx to element in height array.\n\tmov\tal,[ebx+1]\t\t\t; load the data height into dl.\n\tmov\tcl,[ebx]\t\t\t; load the first data row into cl.\n\tmov\tbl,[maxheight]\t\t\t; get the max height of characters.\n\tmov\t[charheight],al\t\t\t; get number of rows with data.\n\tadd\tal,cl\t\t\t\t; add the two heights.\n\tsub\tbl,al\t\t\t\t; subract topblank + char height from maxheight.\n\tmov\t[bottomblank],bl\t\t; save off the number of blank rows on the bottom.\n\t; leaving this section:\n\t; dl is still the width of the character.\n\t; cl is the height of the top blank area.\n\n\tmov\tebx,OFFSET ColorXlat\t\t; setup ebx for xlat commands.\n\tmov\tdh,dl\t\t\t\t; save the width of the character to restore each loop.\n\n\tcmp\tcl,0\t\t\t\t; is there any blank rows on top?\n\tjz\t??draw_char\t\t\t; if not go and draw the real character.\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjnz\t??loop_top\t\t\t; if not go and write the color\n\n;----------------------------------------- skip Top blank area ----------------------------------------\n\t; this case, the top is transparrent, but we need to increase our dest pointer to correct row.\n\tmovzx\teax,cl\t\t\t\t; get number of rows into eax;\n\tmov\tecx,edx\t\t\t\t; save width since edx will be destroyed by mul.\n\tmul\t[bufferwidth]\t\t\t; multiply that by the width of the buffer.\n\tmov\tedx,ecx\t\t\t\t; restore the width\n\tadd\tedi,eax\t\t\t\t; update the pointer.\n\tjmp\tshort ??draw_char\t\t; now go draw the character.\n\n;----------------------------------------- fill Top blank area ----------------------------------------\n\t; edi was set a long time ago.\n\t; al is the translated color\n??loop_top:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_top\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tdec\tcl\t\t\t\t; decrement or row count\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tjz\t??draw_char\t\t\t; we are done here, go draw the character.\n\tjmp\tshort ??loop_top\t\t; go back to top of loop.\n\n\n;----------------------------------------- Draw character ----------------------------------------------\n??draw_char:\n\tmovzx\tecx,[charheight]\t\t; get the height of character to count down rows.\n\ttest\tecx,ecx\t\t\t\t; is there any data? (blank would not have any)\n\tjz\t??next_char\t\t\t; if no data, go on to next character.\n\n??while_data:\n\tlodsb\t\t\t\t\t; get byte value from font data\n\tmov\tah,al\t\t\t\t; save hinibble\n\tand\teax,0F00FH\t       \t\t; mask of low nibble in al hi nibble in ah.\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiplo\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiplo:\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjz\tshort ??nextrow\t\t\t; check if done with width of char\n\n\tmov\tal,ah\t\t\t\t; restore to get\n\t; test the time difference between looking up in a large table when shr al,4 is not done as\n\t; compared to using only a 16 byte table when using the shr al,4\n\t;shr\tal,4\t\t\t\t; shift the hi nibble down to low nibble\n\txlat\t[ebx]\t\t\t\t; get new color\n\n\ttest\tal,al\t\t\t\t; is it a transparent?\n\tjz\tshort ??skiphi\t\t\t; skip over write\n\tmov\t[es:edi],al\t\t\t; write it out\n??skiphi:\n\n\tinc\tedi\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\tshort ??while_data\t\t; check if done with width of char\n\n??nextrow:\n\tadd\tedi,[nextdraw]\t\t\t; go to next line.\n\tdec\tecx\t\t\t\t; decrement the number of rows to go\n\tmov\tdh,dl\t\t\t\t; restore our column count for row.\n\tjnz\t??while_data\t\t\t; more data for character.\n\n\t; Now it is time to setup for clearing out the bottom of the character.\n\tmovzx\tecx,[bottomblank]\t\t; get amount on bottom that is blank\n\tcmp\tecx,0\t\t\t\t; if there is no blank bottom...\n\tjz\t??next_char\t\t\t; then skip to go to next character\n\n\txor\teax,eax\t\t\t\t; get color 0 for background.\n\txlat\t[ebx]\t\t\t\t; get translated color into al\n\ttest\tal,al\t\t\t\t; is it transparent black\n\tjz\t??next_char\t\t\t; skip the top black section to let the background through\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\n;----------------------------------------- Blank below character -----------------------------------\n??loop_bottom:\n\tstosb\t\t\t\t\t; store the value\n\tdec\tdh\t\t\t\t; decrement our width.\n\tjnz\t??loop_bottom\t\t\t; if more width, continue on.\n\n\tadd\tedi,[nextdraw]\t\t\t; add amount for entire row.\n\n\tmov\tdh,dl\t\t\t\t; restore width in dh for loop.\n\tdec\tcl\t\t\t\t; decrement or row count\n\tjz\t??next_char\t\t\t; we are done here, go to the next character.\n\tjmp\tshort ??loop_bottom\t\t; go back to top of loop.\n\n;----------------------------------- end of next_char (main) loop ------------------------------------\n;-------------------------------------------------------------------------------------------------\n\n\n;----------------------------------- special case line feeds ----------------------------------------\n\n??force_line_feed:\n\t; decrement pointer *string so that it will be back at same character\n\t; when it goes through the loop.\n\tmov\teax,[string]\t\t\t; get string pointer.\n\tdec\teax\t\t\t\t; decrement it to point to previos char\n\tmov\t[string],eax\t\t\t; save it back off.\n\txor\teax,eax\n\t; Now go into the line feed code.....\n\n??line_feed:\n\tmov\tbl,al\n\tmov\tedx,[y_pixel]\t\t\t; get the current y pixel value.\n\tmovzx\tecx,[maxheight]\t\t\t; get max height for later use.\n\tadd\tecx,[FontYSpacing]\n\tadd\tedx,ecx\t\t\t\t; add max height to y_pixel\n\tcmp\tedx,[vpheight]\t\t\t; are we over the edge?\n\tjg\t??overflow\t\t\t; if so, we are outa here.\n\n\tmov\teax,[bufferwidth]      \t\t; get bytes to next line.\n\tmov\tedi,[curline]\t\t\t; get start of current line.\n\tmul\tecx\t\t\t\t; mult max height * next line.\n\n\tadd\tedi,eax\t\t\t\t; add adjustment to current line.\n\tadd\t[y_pixel],ecx\t\t\t; increment to our next y position.\n;;; DRD\n\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\n\t; Move the cursor to either the left edge of the screen\n\t; or the left margin of the print position depending\n\t; on whether <CR> or <LF> was specified. <CR> = left margin\n\t; <LF> = left edge of screen\n\txor\teax,eax\n\tcmp\tbl,10\n\tje\t??lfeed\n\tmov\teax,[original_x]\n??lfeed:\n\tmov\t[x_pixel],eax\t\t\t; zero out x_pixel\n\n\tadd\tedi,eax\n;;; DRD\tmov\t[curline],edi\t\t\t; save it off for next line_feed.\n\tmov\t[startdraw],edi\t\t\t; save it off so we know where to draw next char.w\n\n\tjmp\t??next_char\n\n??overflow:\n\tmov\t[startdraw],0\t\t\t; Indicate that there is no valid next pos.\n??done:\n\tmov\teax,[startdraw]\t\t\t; return this so calling routine\n\tret\t\t\t\t\t; can figure out where to draw next.\n\n\tENDP\tBuffer_Print\n;***************************************************************************\n;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *\n;*                                                                         *\n;* INPUT:\tnone                                                       *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* PROTO:\tvoid *Get_Font_Palette_Ptr(void);                          *\n;*                                                                         *\n;* HISTORY:\t\t\t\t\t\t\t\t   *\n;*   08/18/1995 PWG : Created.                                             *\n;*=========================================================================*\n\n\tGLOBAL\tC Get_Font_Palette_Ptr:NEAR\n\tPROC\tGet_Font_Palette_Ptr C near\n\tmov\teax, OFFSET ColorXlat\n\tret\n\tENDP\tGet_Font_Palette_Ptr\n\n\nEND\n"
  },
  {
    "path": "REDALERT/AADATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/AADATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AADATA.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects.                 *\n *   AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object. *\n *   AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game syste*\n *   AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type.   *\n *   AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type.     *\n *   AircraftTypeClass::Display -- Displays a generic version of the aircraft type.            *\n *   AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number.      *\n *   AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap.                  *\n *   AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed.                *\n *   AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft.       *\n *   AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class*\n *   AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft.     *\n *   AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft obj*\n *   AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool.       *\n *   AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool.   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nvoid const * AircraftTypeClass::LRotorData = NULL;\nvoid const * AircraftTypeClass::RRotorData = NULL;\n\n// Badger bomber\nstatic AircraftTypeClass const BadgerPlane(\n\tAIRCRAFT_BADGER,\t\t// What kind of aircraft is this.\n\tTXT_BADGER,\t\t\t\t// Translated text number for aircraft.\n\t\"BADR\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\tfalse,\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Photo recon plane.\nstatic AircraftTypeClass const U2Plane(\n\tAIRCRAFT_U2,\t\t\t// What kind of aircraft is this.\n\tTXT_U2,\t\t\t\t\t// Translated text number for aircraft.\n\t\"U2\",\t\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\tfalse,\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Mig attack aircraft.\nstatic AircraftTypeClass const MigPlane(\n\tAIRCRAFT_MIG,\t\t\t// What kind of aircraft is this.\n\tTXT_MIG,\t\t\t\t\t// Translated text number for aircraft.\n\t\"MIG\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0020,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0020,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_AIRSTRIP,\t\t// Preferred landing building.\n\t0xC0,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Yak attack aircraft.\nstatic AircraftTypeClass const YakPlane(\n\tAIRCRAFT_YAK,\t\t\t// What kind of aircraft is this.\n\tTXT_YAK,\t\t\t\t\t// Translated text number for aircraft.\n\t\"YAK\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0020,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0020,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t// Fixed wing aircraft?\n\t\tfalse,\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_AIRSTRIP,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t16,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Transport helicopter.\nstatic AircraftTypeClass const TransportHeli(\n\tAIRCRAFT_TRANSPORT,\t// What kind of aircraft is this.\n\tTXT_TRANS,\t\t\t\t// Translated text number for aircraft.\n\t\"TRAN\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\ttrue,\t\t\t\t\t// Custom rotor sets for each facing?\n\t\ttrue,\t\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_NONE,\t\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n// Longbow attack helicopter\nstatic AircraftTypeClass const AttackHeli(\n\tAIRCRAFT_LONGBOW,\t\t// What kind of aircraft is this.\n\tTXT_HELI,\t\t\t\t// Translated text number for aircraft.\n\t\"HELI\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_HELIPAD,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n\n// Hind\nstatic AircraftTypeClass const OrcaHeli(\n\tAIRCRAFT_HIND,\t\t\t// What kind of aircraft is this.\n\tTXT_ORCA,\t\t\t\t// Translated text number for aircraft.\n\t\"HIND\",\t\t\t\t\t// INI name of aircraft.\n\t0x0000,\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t// Fixed wing aircraft?\n\t\ttrue,\t\t\t\t\t// Equipped with a rotor?\n\t\tfalse,\t\t\t\t// Custom rotor sets for each facing?\n\t\tfalse,\t\t\t\t// Can this aircraft land on clear terrain?\n\t\ttrue,\t\t\t\t\t// Is it invisible on radar?\n\t\ttrue,\t\t\t\t\t// Can the player select it so as to give it orders?\n\t\ttrue,\t\t\t\t\t// Can it be assigned as a target for attack.\n\t\tfalse,\t\t\t\t// Is it insignificant (won't be announced)?\n\t\tfalse,\t\t\t\t// Is it immune to normal combat damage?\n\tSTRUCT_HELIPAD,\t\t// Preferred landing building.\n\t0xFF,\t\t\t\t\t\t// Landing speed\n\t32,\t\t\t\t\t\t// Number of rotation stages.\n\tMISSION_HUNT\t\t\t// Default mission for aircraft.\n);\n\n\n/***********************************************************************************************\n * AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects.                   *\n *                                                                                             *\n *    This is the constructor for the aircraft object.                                         *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftTypeClass::AircraftTypeClass(\n\t\t\t\tAircraftType airtype,\n\t\t\t\tint name,\n\t\t\t\tchar const * ininame,\n\t\t\t\tint verticaloffset,\n\t\t\t\tint primaryoffset,\n\t\t\t\tint primarylateral,\n\t\t\t\tbool is_fixedwing,\n\t\t\t\tbool is_rotorequipped,\n\t\t\t\tbool is_rotorcustom,\n\t\t\t\tbool is_landable,\n\t\t\t\tbool is_stealthy,\n\t\t\t\tbool is_selectable,\n\t\t\t\tbool is_legal_target,\n\t\t\t\tbool is_insignificant,\n\t\t\t\tbool is_immune,\n\t\t\t\tStructType building,\n\t\t\t\tint landingspeed,\n\t\t\t\tint rotation,\n\t\t\t\tMissionType deforder\n\t\t\t\t) :\n\t\t\t\t\tTechnoTypeClass(RTTI_AIRCRAFTTYPE,\n\t\t\t\t\t\t\t\t\t\tint(airtype),\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\tREMAP_NORMAL,\n\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\t\t\t\tis_selectable,\n\t\t\t\t\t\t\t\t\t\tis_legal_target,\n\t\t\t\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\t\t\t\tis_immune,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\trotation,\n\t\t\t\t\t\t\t\t\t\tSPEED_WINGED),\n\tIsFixedWing(is_fixedwing),\n\tIsLandable(is_landable),\n\tIsRotorEquipped(is_rotorequipped),\n\tIsRotorCustom(is_rotorcustom),\n\tType(airtype),\n\tMission(deforder),\n\tBuilding(building),\n\tLandingSpeed(landingspeed)\n{\n\t/*\n\t**\tForced aircraft overrides from the default.\n\t*/\n\tSpeed = SPEED_WINGED;\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool.     *\n *                                                                                             *\n *    This will allocate an aircraft type class object from the memory pool of that purpose.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated aircraft type class object. If there *\n *          was insufficient memory to fulfill the request, then NULL is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AircraftTypeClass::operator new(size_t)\n{\n\treturn(AircraftTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool.         *\n *                                                                                             *\n *    This will return the aircraft type class object back to the special memory pool that     *\n *    it was allocated from.                                                                   *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the aircraft type class object to delete.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::operator delete(void * pointer)\n{\n\tAircraftTypes.Free((AircraftTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap.                    *\n *                                                                                             *\n *    This will initialize the aircraft type class heap by pre-allocating all known aircraft   *\n *    types. It should be called once and before the rules.ini file is processed.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese aircraft type class objects must be allocated in the exact order that they\n\t**\tare specified in the AircraftSmen enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew AircraftTypeClass(TransportHeli);\n\tnew AircraftTypeClass(BadgerPlane);\n\tnew AircraftTypeClass(U2Plane);\n\tnew AircraftTypeClass(MigPlane);\n\tnew AircraftTypeClass(YakPlane);\n\tnew AircraftTypeClass(AttackHeli);\n\tnew AircraftTypeClass(OrcaHeli);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number.        *\n *                                                                                             *\n *    This routine is used to convert an ASCII representation of an aircraft into the          *\n *    matching aircraft type number. This is used by the scenario INI reader code.             *\n *                                                                                             *\n * INPUT:   name  -- Pointer to ASCII name to translate.                                       *\n *                                                                                             *\n * OUTPUT:  Returns the aircraft type number that matches the ASCII name provided. If no       *\n *          match could be found, then AIRCRAFT_NONE is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftType AircraftTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (int classid = AIRCRAFT_FIRST; classid < AIRCRAFT_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference((AircraftType)classid).IniName, name) == 0) {\n\t\t\t\treturn(AircraftType)classid;\n\t\t\t}\n\t\t}\n\t}\n\treturn(AIRCRAFT_NONE);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class. *\n *                                                                                             *\n *    This routine is used to perform the onetime initialization of the aircraft type. This    *\n *    includes primarily the shape and other graphic data loading.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This goes to disk and also must only be called ONCE.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::One_Time(void)\n{\n\tfor (int index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\tAircraftTypeClass\tconst & uclass = As_Reference((AircraftType)index);\n\n\t\t/*\n\t\t**\tFetch the supporting data files for the unit.\n\t\t*/\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%sICON\", uclass.Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);\n\n\t\t/*\n\t\t**\tGeneric shape for all houses load method.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass.Graphic_Name(), \".SHP\");\n\t\t((void const *&)uclass.ImageData) = MFCD::Retrieve(fullname);\n\t}\n\n\tLRotorData = MFCD::Retrieve(\"LROTOR.SHP\");\n\tRRotorData = MFCD::Retrieve(\"RROTOR.SHP\");\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type.     *\n *                                                                                             *\n *    This routine is used to create an aircraft object that matches the aircraft type. It     *\n *    serves as a shortcut to creating an object using the \"new\" operator and \"if\" checks.     *\n *                                                                                             *\n * INPUT:   house -- The house owner of the aircraft that is to be created.                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the aircraft created. If the aircraft could not be       *\n *          created, then a NULL is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * AircraftTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new AircraftClass(Type, house->Class->House));\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft objec*\n *                                                                                             *\n *    This routine is used by the scenario editor to prepare for the adding operation. It      *\n *    builds a list of pointers to object types that can be added.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Prep_For_Add(void)\n{\n\tfor (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Display -- Displays a generic version of the aircraft type.              *\n *                                                                                             *\n *    This routine is used by the scenario editor to display a generic version of the object   *\n *    type. This is displayed in the object selection dialog box.                              *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates to draw the aircraft at (centered).                    *\n *                                                                                             *\n *          window   -- The window to base the coordinates upon.                               *\n *                                                                                             *\n *          house    -- The owner of this generic aircraft.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint shape = 0;\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tptr = Get_Image_Data();\n\t\tshape = 5;\n\t}\n\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n}\n#endif\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft.         *\n *                                                                                             *\n *    This determines the occupation list for the aircraft (if it was landed).                 *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset occupation list for the aircraft.          *\n *                                                                                             *\n * WARNINGS:   This occupation list is only valid if the aircraft is landed.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft.       *\n *                                                                                             *\n *    This routine figures out the overlap list for the aircraft as if it were landed.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell offset overlap list for the aircraft.                        *\n *                                                                                             *\n * WARNINGS:   This overlap list is only valid when the aircraft is landed.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftTypeClass::Overlap_List(void) const\n{\n\tstatic short const _list[] = {-(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1), -1, 1, (MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1), REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed.                  *\n *                                                                                             *\n *    Use this routine to retrieve the maximum pip count allowed for this aircraft. This is    *\n *    the maximum number of passengers.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the maximum number of pips for this aircraft.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/26/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftTypeClass::Max_Pips(void) const\n{\n\tif (PrimaryWeapon != NULL) {\n\t\t// Camera weapon (ex. on the Spy plane) doesn't display any pips\n\t\tif (!PrimaryWeapon->IsCamera) {\n\t\t\treturn(5);\n\t\t}\n\t}\n\treturn(Max_Passengers());\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game system *\n *                                                                                             *\n *    This routine is used to create and place an aircraft through the normal game system.     *\n *    Since creation of aircraft in this fashion is prohibited, this routine does nothing.     *\n *                                                                                             *\n * INPUT:   na                                                                                 *\n *                                                                                             *\n * OUTPUT:  Always returns a failure code (false).                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftTypeClass::Create_And_Place(CELL, HousesType) const\n{\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type.       *\n *                                                                                             *\n *    This routine will fetch the pixel dimensions of this aircraft type. These dimensions     *\n *    are used to control map refresh and select box rendering.                                *\n *                                                                                             *\n * INPUT:   width    -- Reference to variable that will be filled in with aircraft width.      *\n *                                                                                             *\n *          height   -- Reference to variable that will be filled in with aircraft height.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftTypeClass::Dimensions(int &width, int &height) const\n{\n\tif (Type == AIRCRAFT_BADGER) {\n\t\twidth = 56;\n\t\theight = 56;\n\t} else {\n\t\twidth = 21;\n\t\theight = 20;\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object.   *\n *                                                                                             *\n *    This routine is used to fetch a reference to the aircraft type class object that matches *\n *    the aircraft type specified.                                                             *\n *                                                                                             *\n * INPUT:   aircraft -- The aircraft type to fetch a reference to the type class object of.    *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the type class object of this aircraft type.           *\n *                                                                                             *\n * WARNINGS:   Be sure that the aircraft type specified is legal. Illegal values will result   *\n *             in undefined behavior.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftTypeClass & AircraftTypeClass::As_Reference(AircraftType aircraft)\n{\n\treturn(*AircraftTypes.Ptr(aircraft));\n}\n"
  },
  {
    "path": "REDALERT/ABSTRACT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ABSTRACT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ABSTRACT.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/26/95                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AbstractClass::Debug_Dump -- Display debug information to mono screen.                    *\n *   AbstractClass::Distance -- Determines distance to target.                                 *\n *   AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects.            *\n *   AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate.     *\n *   AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type.       *\n *   AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * AbstractClass::Debug_Dump -- Display debug information to mono screen.                      *\n *                                                                                             *\n *    This debug only routine will display various information about this abstract class       *\n *    object to the monochrome screen specified.                                               *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen to display the debug information to.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef CHEAT_KEYS\nvoid AbstractClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(11, 5);mono->Printf(\"%08X\", As_Target());\n\tmono->Set_Cursor(20, 1);mono->Printf(\"%08X\", Coord);\n\tmono->Set_Cursor(29, 1);mono->Printf(\"%3d\", Height);\n\tif (Owner() != HOUSE_NONE) {\n\t\tmono->Set_Cursor(1, 3);\n\t\tmono->Printf(\"%-18s\", Text_String(HouseTypeClass::As_Reference(Owner()).FullName));\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * AbstractClass::Distance -- Determines distance to target.                                   *\n *                                                                                             *\n *    This will determine the distance (direct line) to the target. The distance is in         *\n *    'leptons'. This routine is typically used for weapon range checks.                       *\n *                                                                                             *\n * INPUT:   target   -- The target to determine range to.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the range to the specified target (in leptons).                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractClass::Distance(TARGET target) const\n{\n\t/*\n\t**\tShould subtract a fudge-factor distance for building targets.\n\t*/\n\tBuildingClass * obj = As_Building(target);\n\tint dist = Distance(As_Coord(target));\n\n\t/*\n\t** If the object is a building the adjust it by the average radius\n\t** of the object.\n\t*/\n\tif (obj && obj->IsActive) {\n\t\tdist -= ((obj->Class->Width() + obj->Class->Height()) * (0x100 / 4));\n\t\tif (dist < 0) dist = 0;\n\t}\n\n\t/*\n\t** Return the distance to the target\n\t*/\n\treturn(dist);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects.              *\n *                                                                                             *\n *    This is the constructor for AbstractTypeClass objects. It initializes the INI name and   *\n *    the text name for this object type.                                                      *\n *                                                                                             *\n * INPUT:   name  -- Text number for the full name of the object.                              *\n *                                                                                             *\n *          ini   -- The ini name for this object type.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAbstractTypeClass::AbstractTypeClass(RTTIType rtti, int id, int name, char const * ini) :\n\tRTTI(rtti),\n\tID(id),\n\tFullName(name)\n{\n\tstrncpy((char *)IniName, ini, sizeof(IniName));\n\t((char &)IniName[sizeof(IniName)-1]) = '\\0';\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate.       *\n *                                                                                             *\n *    This routine is called when the placement coordinate should be fixed up according        *\n *    to any special rules specific to this object type. At this level, no transformation      *\n *    occurs. Derived classes will transform the coordinate as necessary.                      *\n *                                                                                             *\n * INPUT:   coord -- The proposed coordinate that this object type will be placed down at.     *\n *                                                                                             *\n * OUTPUT:  Returns with the adjusted coordinate that the object should be placed down at.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE AbstractTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type.         *\n *                                                                                             *\n *    This routine is used to fetch the full name of this object type. The name value          *\n *    returned is actually the index number into the text array.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the full name index number for this object type.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractTypeClass::Full_Name(void) const\n{\n#ifdef FIXIT_NAME_OVERRIDE\n\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\tif (NameIDOverride[index] == ((RTTI+1) * 100) + ID)  {\n\t\t\treturn(-(index+1));\n\t\t}\n\t}\n#endif\n\treturn(FullName);\n}\n\n\n/***********************************************************************************************\n * AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object.                   *\n *                                                                                             *\n *    This returns a bit flag that indicates which houses are allowed to own this object       *\n *    type. At this level, all houses have ownership rights. This routine will be overridden   *\n *    by object types that restrict ownership.                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a bit flag indicating which houses have ownership rights.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AbstractTypeClass::Get_Ownable(void) const\n{\n\treturn(HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS);\n}\n\n\n\n"
  },
  {
    "path": "REDALERT/ABSTRACT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ABSTRACT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ABSTRACT.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/26/95                                                     *\n *                                                                                             *\n *                  Last Update : January 26, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ABSTRACT_H\n#define ABSTRACT_H\n\nDirType Direction(CELL cell1, CELL cell2);\nDirType Direction(COORDINATE coord1, COORDINATE coord2);\nint Distance(COORDINATE coord1, COORDINATE coord2);\nCOORDINATE As_Coord(TARGET target);\n\nclass AbstractTypeClass;\n\n/*\n**\tThis class is the base class for all game objects that have an existence on the\n**\tbattlefield.\n*/\nclass AbstractClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis specifies the type of object and the unique ID number\n\t\t**\tassociated with it. The ID number happens to match the index into\n\t\t**\tthe object heap appropriate for this object type.\n\t\t*/\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\t/*\n\t\t**\tThe coordinate location of the unit. For vehicles, this is the center\n\t\t**\tpoint. For buildings, it is the upper left corner.\n\t\t*/\n\t\tCOORDINATE Coord;\n\n\t\t/*\n\t\t**\tThis is the height of the object above ground (expressed in leptons).\n\t\t*/\n\t\tint Height;\n\n\t\t/*\n\t\t**\tThe actual object ram-space is located in arrays in the data segment. This flag\n\t\t**\tis used to indicate which objects are free to be reused and which are currently\n\t\t**\tin use by the game.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t** A flag to indicate that this object was recently created. Since an object's allocation is just a matter of whether\n\t\t** the IsActive flag is set, during a logic frame an object with a given ID could be 'deleted' then reallocated \n\t\t** as a different type of object in a different location. This flag lets us know that this happened. ST - 8/19/2019 5:33PM\n\t\t*/\n\t\tunsigned IsRecentlyCreated:1;\n\n\t\t/*-----------------------------------------------------------------------------------\n\t\t**\tConstructor & destructors.\n\t\t*/\n\t\tAbstractClass(RTTIType rtti, int id) : RTTI(rtti), ID(id), Coord(0xFFFFFFFFL), Height(0) {};\n\t\tAbstractClass(NoInitClass const & x) {x();};\n\t\tvirtual ~AbstractClass(void) {};\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual char const * Name(void) const {return(\"\");}\n\t\tvirtual HousesType Owner(void) const {return HOUSE_NONE;};\n\t\tTARGET As_Target(void) const {return(Build_Target(RTTI, ID));};\n\t\tRTTIType What_Am_I(void) const {return(RTTI);};\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass * mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tCoordinate query support functions.\n\t\t*/\n\t\tvirtual COORDINATE Center_Coord(void) const {return Coord;};\n\t\tvirtual COORDINATE Target_Coord(void) const {return Coord;};\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tDirType Direction(AbstractClass const * object) const {return ::Direction(Center_Coord(), object->Target_Coord());};\n\t\tDirType Direction(COORDINATE coord) const {return ::Direction(Center_Coord(), coord);};\n\t\tDirType Direction(TARGET target) const {return ::Direction(Center_Coord(), As_Coord(target));};\n\t\tDirType Direction(CELL cell) const {return ::Direction(Coord_Cell(Center_Coord()), cell);};\n\t\tint Distance(TARGET target) const;\n\t\tint Distance(COORDINATE coord) const {return ::Distance(Center_Coord(), coord);};\n\t\tint Distance(AbstractClass const * object) const {return ::Distance(Center_Coord(), object->Target_Coord());};\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual MoveType Can_Enter_Cell(CELL , FacingType = FACING_NONE) const {return MOVE_OK;};\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void) {};\n\n\t\t/*\n\t\t** Set the new recently created flag every time the active flag is set. ST - 8/19/2019 5:41PM\n\t\t*/\n\t\tvoid Set_Active(void) {IsActive = true; IsRecentlyCreated = true;}\n\n};\n\n\n#endif"
  },
  {
    "path": "REDALERT/ADATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ADATA.CPP 3     3/07/97 4:27p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ADATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 30, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AnimTypeClass::AnimTypeClass -- Constructor for animation types.                          *\n *   AnimTypeClass::One_Time -- Performs one time action for animation types.                  *\n *   AnimTypeClass::Init -- Load any animation artwork that is theater specific.               *\n *   Anim_Name -- Fetches the ASCII name of the animation type specified.                      *\n *   AnimTypeClass::As_Reference -- Fetch a reference to the animation type specified.         *\n *   AnimTypeClass::Init_Heap -- Initialize the animation type system.                         *\n *   AnimTypeClass::operator new -- Allocate an animation type object from private pool.       *\n *   AnimTypeClass::operator delete -- Returns an anim type class object back to the pool.     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nstatic AnimTypeClass const AtomBomb(\n\tANIM_ATOM_BLAST,\t\t\t\t\t\t// Animation number.\n\t\"ATOMSFX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t72,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t19,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t75,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x300\t\t\t\t\t\t\t\t\t// Virtual scale\n);\n\nstatic AnimTypeClass const SputDoor(\n\tANIM_SPUTDOOR,\t\t\t\t\t\t\t// Animation number.\n\t\"SPUTDOOR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t42,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n// Electrocution death anim from Tesla coil\nstatic AnimTypeClass const ElectricDie(\n\tANIM_ELECT_DIE,\t\t\t\t\t\t// Animation number.\n\t\"ELECTRO\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t16,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_FIRE_MED\n);\n\n// Electrocution death anim from Tesla coil for dog\nstatic AnimTypeClass const DogElectricDie(\n\tANIM_DOG_ELECT_DIE,\t\t\t\t\t// Animation number.\n\t\"ELECTDOG\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t17,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_FIRE_MED\n);\n\nstatic AnimTypeClass const SAMN(\n\tANIM_SAM_N,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*0,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMNW(\n\tANIM_SAM_NW,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t22,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*1,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMW(\n\tANIM_SAM_W,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t40,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*2,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMSW(\n\tANIM_SAM_SW,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t58,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*3,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMS(\n\tANIM_SAM_S,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t76,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*4,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMSE(\n\tANIM_SAM_SE,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t94,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*5,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAME(\n\tANIM_SAM_E,\t\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t112,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*6,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const SAMNE(\n\tANIM_SAM_NE,\t\t\t\t\t\t\t// Animation number.\n\t\"SAMFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t55,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t130,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18*7,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t18,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const LZSmoke(\n\tANIM_LZ_SMOKE,\t\t\t\t\t\t// Animation number.\n\t\"SMOKLAND\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t72,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t72,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t91,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t127,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n/*\n**\tFlammable object burning animations. Primarily used on trees and buildings.\n*/\nstatic AnimTypeClass const BurnSmall(\n\tANIM_BURN_SMALL,\t\t\t\t\t\t// Animation number.\n\t\"BURN-S\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t11,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const BurnMed(\n\tANIM_BURN_MED,\t\t\t\t\t\t\t// Animation number.\n\t\"BURN-M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t14,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const BurnBig(\n\tANIM_BURN_BIG,\t\t\t\t\t\t\t// Animation number.\n\t\"BURN-L\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 10),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n/*\n**\tFlammable object burning animations that trail into smoke. Used for\n**\tbuildings and the gunboat.\n*/\nstatic AnimTypeClass const OnFireSmall(\n\tANIM_ON_FIRE_SMALL,\t\t\t\t\t// Animation number.\n\t\"BURN-S\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t11,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_SMOKE_M\n);\nstatic AnimTypeClass const OnFireMed(\n\tANIM_ON_FIRE_MED,\t\t\t\t\t\t// Animation number.\n\t\"BURN-M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t14,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_ON_FIRE_SMALL\n);\nstatic AnimTypeClass const OnFireBig(\n\tANIM_ON_FIRE_BIG,\t\t\t\t\t\t// Animation number.\n\t\"BURN-L\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 10),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t30,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t62,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_ON_FIRE_MED\n);\nstatic AnimTypeClass const Parachute(\n\tANIM_PARACHUTE,\t\t\t\t\t\t// Animation number.\n\t\"PARACH\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t15,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t15,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const ParaBomb(\n\tANIM_PARA_BOMB,\t\t\t\t\t\t// Animation number.\n\t\"PARABOMB\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t15,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const FBall1(\n\tANIM_FBALL1,\t\t\t\t\t\t\t// Animation number.\n\t\"FBALL1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t67,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM25,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Frag1(\n\tANIM_FRAG1,\t\t\t\t\t\t\t\t// Animation number.\n\t\"FRAG1\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t45,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM30,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t29\t\t\t\t\t\t\t\t\t\t// Virtual stages\n);\n\nstatic AnimTypeClass const VehHit1(\n\tANIM_VEH_HIT1,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t30,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM25,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const VehHit2(\n\tANIM_VEH_HIT2,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM12,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const VehHit3(\n\tANIM_VEH_HIT3,\t\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t19,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM12,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const ArtExp1(\n\tANIM_ART_EXP1,\t\t\t\t\t\t\t// Animation number.\n\t\"ART-EXP1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t41,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_KABOOM22,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm1(\n\tANIM_NAPALM1,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_EXPLODE,\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm2(\n\tANIM_NAPALM2,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t41,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_EXPLODE,\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Napalm3(\n\tANIM_NAPALM3,\t\t\t\t\t\t\t// Animation number.\n\t\"NAPALM3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t78,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t5,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_FIRE_LAUNCH,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const SmokePuff(\n\tANIM_SMOKE_PUFF,\t\t\t\t\t\t// Animation number.\n\t\"SMOKEY\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const FireBallFade(\n\tANIM_FBALL_FADE,\t\t\t\t\t\t// Animation number.\n\t\"FB2\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Piff(\n\tANIM_PIFF,\t\t\t\t\t\t\t\t// Animation number.\n\t\"PIFF\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t13,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const PiffPiff(\n\tANIM_PIFFPIFF,\t\t\t\t\t\t\t// Animation number.\n\t\"PIFFPIFF\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t20,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire3(\n\tANIM_FIRE_SMALL,\t\t\t\t\t\t// Animation number.\n\t\"FIRE3\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x100,\t\t\t\t\t\t\t\t\t// Virtual scale\n\tNULL,\t\t\t\t\t\t\t\t\t// Virtual name\n\tANIM_FIRE_SMALL_VIRTUAL\t\t\t\t\t// Virtual anim\n);\n\nstatic AnimTypeClass const Fire3Virtual(\n\tANIM_FIRE_SMALL_VIRTUAL,\t\t\t\t// Animation number.\n\t\"FIRE3\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t10,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t21,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t29,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire1(\n\tANIM_FIRE_MED2,\t\t \t\t\t\t// Animation number.\n\t\"FIRE1\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x100,\t\t\t\t\t\t\t\t\t// Virtual scale\n\tNULL,\t\t\t\t\t\t\t\t\t// Virtual name\n\tANIM_FIRE_MED2_VIRTUAL\t\t\t\t\t// Virtual anim\n);\n\nstatic AnimTypeClass const Fire1Virtual(\n\tANIM_FIRE_MED2_VIRTUAL,\t\t \t\t\t// Animation number.\n\t\"FIRE1\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t10,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t21,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t29,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire4(\n\tANIM_FIRE_TINY,\t\t \t\t\t\t// Animation number.\n\t\"FIRE4\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 32),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x100,\t\t\t\t\t\t\t\t\t// Virtual scale\n\tNULL,\t\t\t\t\t\t\t\t\t// Virtual name\n\tANIM_FIRE_TINY_VIRTUAL\t\t\t\t\t// Virtual anim\n);\n\nstatic AnimTypeClass const Fire4Virtual(\n\tANIM_FIRE_TINY_VIRTUAL,\t\t \t\t\t// Animation number.\n\t\"FIRE4\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t10,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t21,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t29,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Fire2(\n\tANIM_FIRE_MED,\t\t\t\t\t\t\t// Animation number.\n\t\"FIRE2\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\tfixed(1, 16),\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x100,\t\t\t\t\t\t\t\t\t// Virtual scale\n\tNULL,\t\t\t\t\t\t\t\t\t// Virtual name\n\tANIM_FIRE_MED_VIRTUAL\t\t\t\t\t// Virtual anim\n);\n\nstatic AnimTypeClass const Fire2Virtual(\n\tANIM_FIRE_MED_VIRTUAL,\t\t\t\t\t// Animation number.\n\t\"FIRE2\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t23,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t10,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t21,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t29,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const OilFieldBurn(\n\tANIM_OILFIELD_BURN,\t\t\t\t\t// Animation number.\n\t\"FLMSPT\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t42,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t58,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t33,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t99,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t66,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t127,\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Gunfire(\n\tANIM_MUZZLE_FLASH,\t\t\t\t\t// Animation number.\n\t\"GUNFIRE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t16,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t10\t\t\t\t\t\t\t\t\t\t// Virtual stages\n);\n\nstatic AnimTypeClass const SmokeM(\n\tANIM_SMOKE_M,\t\t\t\t\t\t\t// Animation number.\n\t\"SMOKE_M\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t30,\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t67,\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Loopback frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t105\t\t\t\t\t\t\t\t\t\t// Virtual stages\n);\n\n/*\n**\tMini-gun fire effect -- used by guard towers.\n*/\nstatic AnimTypeClass const GUNN(\n\tANIM_GUN_N,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNNW(\n\tANIM_GUN_NW,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNW(\n\tANIM_GUN_W,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t12,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNSW(\n\tANIM_GUN_SW,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t18,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNS(\n\tANIM_GUN_S,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t24,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNSE(\n\tANIM_GUN_SE,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t30,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNE(\n\tANIM_GUN_E,\t\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t36,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const GUNNE(\n\tANIM_GUN_NE,\t\t\t\t\t\t\t// Animation number.\n\t\"MINIGUN\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t18,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t42,\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\t6,\t\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const CDeviator(\n\tANIM_CRATE_DEVIATOR,\t\t\t\t\t// Animation number.\n\t\"DEVIATOR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CrateArmor(\n\tANIM_CRATE_ARMOR,\t\t\t\t\t\t// Animation number.\n\t\"ARMOR\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CrateSpeed(\n\tANIM_CRATE_SPEED,\t\t\t\t\t\t// Animation number.\n\t\"SPEED\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CrateFPower(\n\tANIM_CRATE_FPOWER,\t\t\t\t\t// Animation number.\n\t\"FPOWER\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CrateTQuake(\n\tANIM_CRATE_TQUAKE,\t\t\t\t\t// Animation number.\n\t\"TQUAKE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CDollar(\n\tANIM_CRATE_DOLLAR,\t\t\t\t\t// Animation number.\n\t\"DOLLAR\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CEarth(\n\tANIM_CRATE_EARTH,\t\t\t\t\t\t// Animation number.\n\t\"EARTH\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CEmpulse(\n\tANIM_CRATE_EMPULSE,\t\t\t\t\t// Animation number.\n\t\"EMPULSE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CInvun(\n\tANIM_CRATE_INVUN,\t\t\t\t\t\t// Animation number.\n\t\"INVUN\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CMine(\n\tANIM_CRATE_MINE,\t\t\t\t\t\t// Animation number.\n\t\"MINE\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CRapid(\n\tANIM_CRATE_RAPID,\t\t\t\t\t\t// Animation number.\n\t\"RAPID\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const CStealth(\n\tANIM_CRATE_STEALTH,\t\t\t\t\t// Animation number.\n\t\"STEALTH2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const ChronoBox(\n\tANIM_CHRONO_BOX,\t\t\t\t\t\t// Animation number.\n\t\"CHRONBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const GPSBox(\n\tANIM_GPS_BOX,\t\t\t\t\t\t\t// Animation number.\n\t\"GPSBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const InvulBox(\n\tANIM_INVUL_BOX,\t\t\t\t\t\t// Animation number.\n\t\"INVULBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const ParaBox(\n\tANIM_PARA_BOX,\t\t\t\t\t\t\t// Animation number.\n\t\"PARABOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\nstatic AnimTypeClass const SonarBox(\n\tANIM_SONAR_BOX,\t\t\t\t\t\t// Animation number.\n\t\"SONARBOX\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const CMissile(\n\tANIM_CRATE_MISSILE,\t\t\t\t\t// Animation number.\n\t\"MISSILE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t48,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t2,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const MoveFlash(\n\tANIM_MOVE_FLASH,\t\t\t\t\t\t\t// Animation number.\n\t\"MOVEFLSH\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\t\t\t\t\t\t\t\t// Follow up animation.\n);\n\nstatic AnimTypeClass const Corpse1(\n\tANIM_CORPSE1,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Corpse2(\n\tANIM_CORPSE2,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Corpse3(\n\tANIM_CORPSE3,\t\t\t\t\t\t\t// Animation number.\n\t\"CORPSE3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t24,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t15,\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Twinkle1(\n\tANIM_TWINKLE1,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Twinkle2(\n\tANIM_TWINKLE2,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Twinkle3(\n\tANIM_TWINKLE3,\t\t\t\t\t\t\t// Animation number.\n\t\"TWINKLE3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const Flak(\n\tANIM_FLAK,\t\t\t\t\t\t\t\t// Animation number.\n\t\"FLAK\",\t\t\t\t\t\t\t\t\t// Data name of animation.\n\t8,\t\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t7,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t17\t\t\t\t\t\t\t\t\t\t// Virtual stages\n);\nstatic AnimTypeClass const WaterExp1(\n\tANIM_WATER_EXP1,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP1\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t64,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const WaterExp2(\n\tANIM_WATER_EXP2,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t40,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\nstatic AnimTypeClass const WaterExp3(\n\tANIM_WATER_EXP3,\t\t\t\t\t\t// Animation number.\n\t\"H2O_EXP3\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t32,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t3,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_SPLASH,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n\nstatic AnimTypeClass const MineExp1(\n\tANIM_MINE_EXP1,\t\t\t\t\t\t// Animation number.\n\t\"VEH-HIT2\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_MINEBLOW,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Flag(\n\tANIM_FLAG,\t\t\t\t\t\t// Animation number.\n\t\"FLAGFLY\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\nstatic AnimTypeClass const Beacon(\n\tANIM_BEACON,\t\t\t\t\t\t\t// Animation number.\n\t\"MOVEFLSH\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\ttrue,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\t\t\t\t\t\t\t\t\t\t// Virtual stages\n\t0x100,\t\t\t\t\t\t\t\t\t// Virtual scale\n\tNULL,\t\t\t\t\t\t\t\t\t// Virtual name\n\tANIM_BEACON_VIRTUAL\t\t\t// Virtual anim\n);\n\nstatic AnimTypeClass const BeaconVirtual(\n\tANIM_BEACON_VIRTUAL,\t\t\t\t\t// Animation number.\n\t\"BEACON\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t21,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\tfalse,\t\t\t\t\t\t\t\t\t// Ground level animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_NONE,\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE\n);\n\n#ifdef FIXIT_ANTS\nstatic AnimTypeClass const Ant1Death(\n\tANIM_ANT1_DEATH,\t\t\t\t\t\t// Animation number.\n\t\"ANTDIE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_ANTDIE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\n\t0x100,\n\t\"ANTDIE1\"\n);\n\nstatic AnimTypeClass const Ant2Death(\n\tANIM_ANT2_DEATH,\t\t\t\t\t\t// Animation number.\n\t\"ANTDIE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_ANTDIE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\n\t0x100,\n\t\"ANTDIE2\"\n);\n\nstatic AnimTypeClass const Ant3Death(\n\tANIM_ANT3_DEATH,\t\t\t\t\t\t// Animation number.\n\t\"ANTDIE\",\t\t\t\t\t\t\t\t// Data name of animation.\n\t28,\t\t\t\t\t\t\t\t\t\t// Maximum dimension of animation.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Biggest animation stage.\n\tfalse,\t\t\t\t\t\t\t\t\t// Theater specific art imagery?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Normalized animation rate?\n\tfalse,\t\t\t\t\t\t\t\t\t// Uses white translucent table?\n\tfalse,\t\t\t\t\t\t\t\t\t// Scorches the ground?\n\tfalse,\t\t\t\t\t\t\t\t\t// Forms a crater?\n\tfalse,\t\t\t\t\t\t\t\t\t// Sticks to unit in square?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Ground level animation?\n\ttrue,\t\t\t\t\t\t\t\t\t\t// Translucent colors in this animation?\n\tfalse,\t\t\t\t\t\t\t\t\t// Is this a flame thrower animation?\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Damage to apply per tick (fixed point).\n\t4,\t\t\t\t\t\t\t\t\t\t\t// Delay between frames.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Starting frame number.\n\t0,\t\t\t\t\t\t\t\t\t\t\t// Loop start frame number.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Ending frame of loop back.\n\t-1,\t\t\t\t\t\t\t\t\t\t// Number of animation stages.\n\t1,\t\t\t\t\t\t\t\t\t\t\t// Number of times the animation loops.\n\tVOC_ANTDIE,\t\t\t\t\t\t\t\t// Sound effect to play.\n\tANIM_NONE,\n\t-1,\n\t0x100,\n\t\"ANTDIE3\"\n);\n#endif\n\n/***********************************************************************************************\n * AnimTypeClass::AnimTypeClass -- Constructor for animation types.                            *\n *                                                                                             *\n *    This is the constructor for static objects that elaborate the various animation types    *\n *    allowed in the game. Each animation in the game is of one of these types.                *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimTypeClass::AnimTypeClass(\n\t\tAnimType anim,\n\t\tchar const * name,\n\t\tint size,\n\t\tint biggest,\n\t\tbool istheater,\n\t\tbool isnormal,\n\t\tbool iswhitetrans,\n\t\tbool isscorcher,\n\t\tbool iscrater,\n\t\tbool issticky,\n\t\tbool ground,\n\t\tbool istrans,\n\t\tbool isflame,\n\t\tfixed damage,\n\t\tint delaytime,\n\t\tint start,\n\t\tint loopstart,\n\t\tint loopend,\n\t\tint stages,\n\t\tint loops,\n\t\tVocType soundid,\n\t\tAnimType chainto,\n\t\tint virtualstages,\n\t\tint virtualscale,\n\t\tchar const * virtualname,\n\t\tAnimType virtualanim) :\n\tObjectTypeClass(RTTI_ANIMTYPE,\n\t\t\tint(anim),\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tTXT_NONE,\n\t\t\tname\n\t\t\t),\n\tIsNormalized(isnormal),\n\tIsGroundLayer(ground),\n\tIsTranslucent(istrans),\n\tIsWhiteTrans(iswhitetrans),\n\tIsFlameThrower(isflame),\n\tIsScorcher(isscorcher),\n\tIsCraterForming(iscrater),\n\tIsSticky(issticky),\n\tIsTheater(istheater),\n\tType(anim),\n\tSize(size),\n\tBiggest(biggest),\n\tDamage(damage),\n\tDelay(delaytime),\n\tStart(start),\n\tLoopStart(loopstart),\n\tLoopEnd(loopend),\n\tStages(stages),\n\tLoops(loops),\n\tSound(soundid),\n\tChainTo(chainto),\n\tVirtualStages(virtualstages),\n\tVirtualScale(virtualscale),\n\tVirtualName(virtualname),\n\tVirtualAnim(virtualanim)\n{\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::operator new -- Allocate an animation type object from private pool.         *\n *                                                                                             *\n *    This routine will allocate an animation type class object.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated anim type object. If no anim type    *\n *          could be allocated, then NULL is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AnimTypeClass::operator new(size_t)\n{\n\treturn(AnimTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::operator delete -- Returns an anim type class object back to the pool.       *\n *                                                                                             *\n *    This will return the anim type class object back to the memory pool from whence it was   *\n *    previously allocated.                                                                    *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the anim type class object to return to the memory pool.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::operator delete(void * pointer)\n{\n\tAnimTypes.Free((AnimTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::Init_Heap -- Initialize the animation type system.                           *\n *                                                                                             *\n *    This routine is called to initialize the animation type class heap. It allocates all     *\n *    known animation types.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese anim type class objects must be allocated in the exact order that they\n\t**\tare specified in the AnimType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew AnimTypeClass(FBall1);\n\tnew AnimTypeClass(FireBallFade);\n\tnew AnimTypeClass(Frag1);\n\tnew AnimTypeClass(VehHit1);\n\tnew AnimTypeClass(VehHit2);\n\tnew AnimTypeClass(VehHit3);\n\tnew AnimTypeClass(ArtExp1);\n\tnew AnimTypeClass(Napalm1);\n\tnew AnimTypeClass(Napalm2);\n\tnew AnimTypeClass(Napalm3);\n\tnew AnimTypeClass(SmokePuff);\n\tnew AnimTypeClass(Piff);\n\tnew AnimTypeClass(PiffPiff);\n\tnew AnimTypeClass(Fire3);\n\tnew AnimTypeClass(Fire2);\n\tnew AnimTypeClass(Fire1);\n\tnew AnimTypeClass(Fire4);\n\tnew AnimTypeClass(Gunfire);\n\tnew AnimTypeClass(SmokeM);\n\tnew AnimTypeClass(BurnSmall);\n\tnew AnimTypeClass(BurnMed);\n\tnew AnimTypeClass(BurnBig);\n\tnew AnimTypeClass(OnFireSmall);\n\tnew AnimTypeClass(OnFireMed);\n\tnew AnimTypeClass(OnFireBig);\n\tnew AnimTypeClass(SAMN);\n\tnew AnimTypeClass(SAMNE);\n\tnew AnimTypeClass(SAME);\n\tnew AnimTypeClass(SAMSE);\n\tnew AnimTypeClass(SAMS);\n\tnew AnimTypeClass(SAMSW);\n\tnew AnimTypeClass(SAMW);\n\tnew AnimTypeClass(SAMNW);\n\tnew AnimTypeClass(GUNN);\n\tnew AnimTypeClass(GUNNE);\n\tnew AnimTypeClass(GUNE);\n\tnew AnimTypeClass(GUNSE);\n\tnew AnimTypeClass(GUNS);\n\tnew AnimTypeClass(GUNSW);\n\tnew AnimTypeClass(GUNW);\n\tnew AnimTypeClass(GUNNW);\n\tnew AnimTypeClass(LZSmoke);\n\tnew AnimTypeClass(CDeviator);\n\tnew AnimTypeClass(CDollar);\n\tnew AnimTypeClass(CEarth);\n\tnew AnimTypeClass(CEmpulse);\n\tnew AnimTypeClass(CInvun);\n\tnew AnimTypeClass(CMine);\n\tnew AnimTypeClass(CRapid);\n\tnew AnimTypeClass(CStealth);\n\tnew AnimTypeClass(CMissile);\n\tnew AnimTypeClass(MoveFlash);\n\tnew AnimTypeClass(OilFieldBurn);\n\tnew AnimTypeClass(ElectricDie);\n\tnew AnimTypeClass(Parachute);\n\tnew AnimTypeClass(DogElectricDie);\n\tnew AnimTypeClass(Corpse1);\n\tnew AnimTypeClass(Corpse2);\n\tnew AnimTypeClass(Corpse3);\n\tnew AnimTypeClass(SputDoor);\n\tnew AnimTypeClass(AtomBomb);\n\tnew AnimTypeClass(ChronoBox);\n\tnew AnimTypeClass(GPSBox);\n\tnew AnimTypeClass(InvulBox);\n\tnew AnimTypeClass(ParaBox);\n\tnew AnimTypeClass(SonarBox);\n\tnew AnimTypeClass(Twinkle1);\n\tnew AnimTypeClass(Twinkle2);\n\tnew AnimTypeClass(Twinkle3);\n\tnew AnimTypeClass(Flak);\n\tnew AnimTypeClass(WaterExp1);\n\tnew AnimTypeClass(WaterExp2);\n\tnew AnimTypeClass(WaterExp3);\n\tnew AnimTypeClass(CrateArmor);\n\tnew AnimTypeClass(CrateSpeed);\n\tnew AnimTypeClass(CrateFPower);\n\tnew AnimTypeClass(CrateTQuake);\n\tnew AnimTypeClass(ParaBomb);\n\tnew AnimTypeClass(MineExp1);\n\tnew AnimTypeClass(Flag);\n\tnew AnimTypeClass(Beacon);\n#ifdef FIXIT_ANTS\n\tnew AnimTypeClass(Ant1Death);\n\tnew AnimTypeClass(Ant2Death);\n\tnew AnimTypeClass(Ant3Death);\n#endif\n\tnew AnimTypeClass(Fire3Virtual);\n\tnew AnimTypeClass(Fire2Virtual);\n\tnew AnimTypeClass(Fire1Virtual);\n\tnew AnimTypeClass(Fire4Virtual);\n\tnew AnimTypeClass(BeaconVirtual);\n}\n\n/***********************************************************************************************\n * AnimTypeClass::One_Time -- Performs one time action for animation types.                    *\n *                                                                                             *\n *    This will load the animation shape data. It is called by the game initialization         *\n *    process.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should be called ONLY once.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::One_Time(void)\n{\n\tfor (int index = ANIM_FIRST; index < ANIM_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tAnimTypeClass const & anim = As_Reference((AnimType)index);\n\n\t\tif (!anim.IsTheater) {\n\n\t\t\t_makepath(fullname, NULL, NULL, As_Reference((AnimType)index).IniName, \".SHP\");\n\n\t\t\t#ifndef NDEBUG\n\t\t\t\tRawFileClass file(fullname);\n\t\t\t\tif (file.Is_Available()) {\n\t\t\t\t\t((void const *&)As_Reference((AnimType)index).ImageData) = Load_Alloc_Data(file);\n\t\t\t\t} else {\n\t\t\t\t\t((void const *&)As_Reference((AnimType)index).ImageData) = MFCD::Retrieve(fullname);\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\t((void const *&)As_Reference((AnimType)index).ImageData) = MFCD::Retrieve(fullname);\n\t\t\t#endif\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::Init -- Load any animation artwork that is theater specific.                 *\n *                                                                                             *\n *    This routine will examine all the animation types and for any that are theater           *\n *    specific, it will fetch a pointer to the artwork appropriate for the theater specified.  *\n *                                                                                             *\n * INPUT:   theater  -- The theater to align the animation artwork with.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine when the theater changes.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tfor (int index = ANIM_FIRST; index < ANIM_COUNT; index++) {\n\t\t\tAnimTypeClass const & anim = As_Reference((AnimType)index);\n\n\t\t\tif (anim.IsTheater) {\n\t\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\t\t\t\t_makepath(fullname, NULL, NULL, anim.IniName, Theaters[theater].Suffix);\n\t\t\t\t((void const *&)anim.ImageData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t}\n\n\t\t// Set up beacon image data manually since they're new animations only available in the virtual renderer\n\t\t((void const *&)As_Reference(ANIM_BEACON_VIRTUAL).ImageData) = As_Reference(ANIM_BEACON).ImageData;\n\t}\n}\n\n\n/***********************************************************************************************\n * Anim_Name -- Fetches the ASCII name of the animation type specified.                        *\n *                                                                                             *\n *    This will convert the animation type specified into a text name. This name can be used   *\n *    for uniquely identifying the animation.                                                  *\n *                                                                                             *\n * INPUT:   anim  -- The anim type to convert to a text string.                                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII string that identifies this animation.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Anim_Name(AnimType anim)\n{\n\tif (anim == ANIM_NONE) return(\"\");\n\n\treturn(AnimTypeClass::As_Reference(anim).IniName);\n}\n\n\n/***********************************************************************************************\n * AnimTypeClass::As_Reference -- Fetch a reference to the animation type specified.           *\n *                                                                                             *\n *    This routine will convert the animation type specified into a reference to the           *\n *    animation type class object.                                                             *\n *                                                                                             *\n * INPUT:   type  -- The animation type to convert into a reference.                           *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the animation type class object.                       *\n *                                                                                             *\n * WARNINGS:   Be sure that the animation type specified is legal. If it isn't then the        *\n *             results of this routine are undefined.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimTypeClass & AnimTypeClass::As_Reference(AnimType type)\n{\n\treturn(* AnimTypes.Ptr(type));\n}\n\n"
  },
  {
    "path": "REDALERT/ADPCM.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#include \"function.h\"\n\nextern \"C\" {\n#include \"soscomp.h\"\n#include \"itable.cpp\"\n#include \"dtable.cpp\"\n\n\nvoid sosCODECInitStream(_SOS_COMPRESS_INFO* info)\n{\n\tinfo->dwSampleIndex = 0;\n\tinfo->dwPredicted = 0;\n}\n\n\nunsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO* info, unsigned long numbytes)\n{\n\tunsigned long token;\n\tlong sample;\n\tunsigned int fastindex;\n\tunsigned char *inbuff;\n\tunsigned short *outbuff;\n\n\tinbuff = (unsigned char *)info->lpSource;\n\toutbuff = (unsigned short *)info->lpDest;\n\n\t// Preload variables before the big loop\n\tfastindex = (unsigned int)info->dwSampleIndex;\n\tsample = info->dwPredicted;\n\n\tif (!numbytes)\n\t\tgoto SkipLoop;\n\n\tdo {\n\t\t// First nibble\n\t\ttoken = *inbuff++;\n\t\tfastindex += token & 0x0f;\n\t\tsample += DiffTable[fastindex];\n\t\tfastindex = IndexTable[fastindex];\n\t\tif (sample > 32767L)\n\t\t\tsample = 32767L;\n\t\tif (sample < -32768L)\n\t\t\tsample = -32768L;\n\t\t*outbuff++ = (unsigned short)sample;\n\n\t\t// Second nibble\n\t\tfastindex += token >> 4;\n\t\tsample += DiffTable[fastindex];\n\t\tfastindex = IndexTable[fastindex];\n\t\tif (sample > 32767L)\n\t\t\tsample = 32767L;\n\t\tif (sample < -32768L)\n\t\t\tsample = -32768L;\n\t\t*outbuff++ = (unsigned short)sample;\n\t} while(--numbytes);\n\nSkipLoop:\n\n\t// Put local vars back\n\tinfo->dwSampleIndex = (unsigned long)fastindex;\n\tinfo->dwPredicted = sample;\n\treturn(numbytes << 2);\n}\n\n}\n"
  },
  {
    "path": "REDALERT/AIRCRAFT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/AIRCRAFT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AIRCRAFT.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AircraftClass::AI -- Processes the normal non-graphic AI for the aircraft.                *\n *   AircraftClass::Active_Click_With -- Handles clicking over specified cell.                 *\n *   AircraftClass::Active_Click_With -- Handles clicking over specified object.               *\n *   AircraftClass::AircraftClass -- The constructor for aircraft objects.                     *\n *   AircraftClass::Can_Enter_Cell -- Determines if the aircraft can land at this location.    *\n *   AircraftClass::Can_Fire -- Checks to see if the aircraft can fire.                        *\n *   AircraftClass::Cell_Seems_Ok -- Checks to see if a cell is good to enter.                 *\n *   AircraftClass::Desired_Load_Dir -- Determines where passengers should line up.            *\n *   AircraftClass::Draw_It -- Renders an aircraft object at the location specified.           *\n *   AircraftClass::Draw_Rotors -- Draw rotor blades on the aircraft.                          *\n *   AircraftClass::Edge_Of_World_AI -- Detect if aircraft has exited the map.                 *\n *   AircraftClass::Enter_Idle_Mode -- Gives the aircraft an appropriate mission.              *\n *   AircraftClass::Exit_Object -- Unloads passenger from aircraft.                            *\n *   AircraftClass::Fire_At -- Handles firing a projectile from an aircraft.                   *\n *   AircraftClass::Fire_Direction -- Determines the direction of fire.                        *\n *   AircraftClass::Good_Fire_Location -- Searches for and finds a good spot to fire from.     *\n *   AircraftClass::Good_LZ -- Locates a good spot ot land.                                    *\n *   AircraftClass::In_Which_Layer -- Calculates the display layer of the aircraft.            *\n *   AircraftClass::Init -- Initialize the aircraft system to an empty state.                  *\n *   AircraftClass::Is_LZ_Clear -- Determines if landing zone is free for landing.             *\n *   AircraftClass::Landing_Takeoff_AI -- Handle aircraft take off and landing processing.     *\n *   AircraftClass::Look -- Aircraft will look if they are on the ground always.               *\n *   AircraftClass::Mission_Attack -- Handles the attack mission for aircraft.                 *\n *   AircraftClass::Mission_Enter -- Control aircraft to fly to the helipad or repair center.  *\n *   AircraftClass::Mission_Guard -- Handles aircraft in guard mode.                           *\n *   AircraftClass::Mission_Guard_Area -- Handles the aircraft guard area logic.               *\n *   AircraftClass::Mission_Hunt -- Maintains hunt AI for the aircraft.                        *\n *   AircraftClass::Mission_Move -- Handles movement mission.                                  *\n *   AircraftClass::Mission_Retreat -- Handles the aircraft logic for leaving the battlefield. *\n *   AircraftClass::Mission_Unload -- Handles unloading cargo.                                 *\n *   AircraftClass::Movement_AI -- Handles aircraft physical movement logic.                   *\n *   AircraftClass::New_LZ -- Find a good landing zone.                                        *\n *   AircraftClass::Overlap_List -- Returns with list of cells the aircraft overlaps.          *\n *   AircraftClass::Paradrop_Cargo -- Drop a passenger by parachute.                           *\n *   AircraftClass::Per_Cell_Process -- Handle the aircraft per cell process.                  *\n *   AircraftClass::Pip_Count -- Returns the number of \"objects\" in aircraft.                  *\n *   AircraftClass::Player_Assign_Mission -- Handles player input to assign a mission.         *\n *   AircraftClass::Pose_Dir -- Fetches the natural landing facing.                            *\n *   AircraftClass::Process_Fly_To -- Handles state machine for flying to destination.         *\n *   AircraftClass::Process_Landing -- Landing process state machine handler.                  *\n *   AircraftClass::Process_Take_Off -- State machine support for taking off.                  *\n *   AircraftClass::Read_INI -- Reads aircraft object data from an INI file.                   *\n *   AircraftClass::Receive_Message -- Handles receipt of radio messages.                      *\n *   AircraftClass::Response_Attack -- Gives audio response to attack order.                   *\n *   AircraftClass::Response_Move -- Gives audio response to move request.                     *\n *   AircraftClass::Response_Select -- Gives audio response when selected.                     *\n *   AircraftClass::Rotation_AI -- Handle aircraft body and flight rotation.                   *\n *   AircraftClass::Scatter -- Causes the aircraft to move away a bit.                         *\n *   AircraftClass::Set_Speed -- Sets the speed for the aircraft.                              *\n *   AircraftClass::Shape_Number -- Fetch the shape number to use for the aircraft.            *\n *   AircraftClass::Sort_Y -- Figures the sorting coordinate.                                  *\n *   AircraftClass::Take_Damage -- Applies damage to the aircraft.                             *\n *   AircraftClass::Unlimbo -- Removes an aircraft from the limbo state.                       *\n *   AircraftClass::What_Action -- Determines what action to perform.                          *\n *   AircraftClass::What_Action -- Determines what action to perform.                          *\n *   AircraftClass::operator delete -- Deletes the aircraft object.                            *\n *   AircraftClass::operator new -- Allocates a new aircraft object from the pool              *\n *   AircraftClass::~AircraftClass -- Destructor for aircraft object.                          *\n *   _Counts_As_Civ_Evac -- Is the specified object a candidate for civilian evac logic?       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * _Counts_As_Civ_Evac -- Is the specified object a candidate for civilian evac logic?         *\n *                                                                                             *\n *    Examines the specified object to see if it qualifies to be a civilian evacuation. This   *\n *    can only occur if it is a civilian (or Tanya) and the special evacuation flag has been   *\n *    set in the scenario control structure.                                                   *\n *                                                                                             *\n * INPUT:   candidate   -- Candidate object to examine for civilian evacuation legality.       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified object considered a civilian that must be auto-evacuated?   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Counts_As_Civ_Evac(ObjectClass const * candidate)\n{\n\t/*\n\t**\tIf the candidate pointer is missing, then return with failure code.\n\t*/\n\tif (candidate == NULL) return(false);\n\n\t/*\n\t**\tOnly infantry objects can be considered for civilian evacuation action.\n\t*/\n\tif (candidate->What_Am_I() != RTTI_INFANTRY) return(false);\n\n\t/*\n\t**\tWorking infantry object pointer.\n\t*/\n\tInfantryClass const * inf = (InfantryClass const *)candidate;\n\n\t/*\n\t**\tCertain infantry types will always be considered a civilian evacuation candidate. These\n\t**\tinclude the special one-time infantry that appear in some missions.\n\t*/\n\tif (*inf == INFANTRY_EINSTEIN || *inf == INFANTRY_GENERAL || *inf == INFANTRY_DELPHI || *inf == INFANTRY_CHAN) return(true);\n\n\t/*\n\t**\tConsider Tanya to be part of the civilian evacuation logic if the scenario is\n\t**\tspecially flagged for this.\n\t*/\n\tif (Scen.IsTanyaEvac && *inf == INFANTRY_TANYA) return(true);\n\n\t/*\n\t**\tIf the infantry is not a civilian, then it isn't allowed to be a civilian evacuation.\n\t*/\n\tif (!inf->Class->IsCivilian) return(false);\n\n\t/*\n\t**\tTechnicians look like civilians, but are not considered a legal evacuation candidate.\n\t*/\n\tif (inf->IsTechnician) return(false);\n\n\t/*\n\t**\tAll tests pass, so return the success of the infantry as a civilian evacuation candidate.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::operator new -- Allocates a new aircraft object from the pool                *\n *                                                                                             *\n *    This routine will allocate an aircraft object from the free aircraft object pool. If     *\n *    there are no free object available, then this routine will fail (return NULL).           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocate aircraft object or NULL if none were        *\n *          available.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AircraftClass::operator new(size_t)\n{\n\tvoid * ptr = Aircraft.Allocate();\n\tif (ptr) {\n\t\t((AircraftClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::operator delete -- Deletes the aircraft object.                              *\n *                                                                                             *\n *    This routine will return the aircraft object back to the free aircraft object pool.      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the aircraft object to delete.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((AircraftClass *)ptr)->IsActive = false;\n\t}\n\tAircraft.Free((AircraftClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::AircraftClass -- The constructor for aircraft objects.                       *\n *                                                                                             *\n *    This routine is the constructor for aircraft objects. An aircraft object can be          *\n *    created and possibly placed into the game system by this routine.                        *\n *                                                                                             *\n * INPUT:   classid  -- The type of aircraft to create.                                        *\n *                                                                                             *\n *          house    -- The owner of this aircraft.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass::AircraftClass(AircraftType classid, HousesType house) :\n\tFootClass(RTTI_AIRCRAFT, Aircraft.ID(this), house),\n\tClass(AircraftTypes.Ptr((int)classid)),\n\tSecondaryFacing(PrimaryFacing),\n\tPassenger(false),\n\tIsLanding(false),\n\tIsTakingOff(false),\n\tIsHovering(false),\n\tJitter(0),\n\tSightTimer(0),\n\tAttacksRemaining(1)\n{\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tHouse->Tracking_Add(this);\n\tAmmo = Class->MaxAmmo;\n\tHeight = FLIGHT_LEVEL;\n\tStrength = Class->MaxStrength;\n\tNavCom = TARGET_NONE;\n\n\t/*\n\t** Keep count of the number of units created. Dont track cargo planes as they are created\n\t** automatically, not bought.\n\t*/\n//\tif (/*classid != AIRCRAFT_CARGO && */ Session.Type == GAME_INTERNET) {\n//\t\tHouse->AircraftTotals->Increment_Unit_Total((int)classid);\n//\t}\n\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Unlimbo -- Removes an aircraft from the limbo state.                         *\n *                                                                                             *\n *    This routine is used to transition the aircraft from the limbo to the non limbo state.   *\n *    It occurs when the aircraft is placed on the map for whatever reason. When it is         *\n *    unlimboed, only then will normal game processing recognize it.                           *\n *                                                                                             *\n * INPUT:   coord -- The coordinate that the aircraft should appear at.                        *\n *                                                                                             *\n *          dir   -- The direction it should start facing.                                     *\n *                                                                                             *\n *\t\t\t\tstrength (optional) -- sets initial strength\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *\t\t\t\tmission (optional) -- sets initial mission\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft unlimboed successfully?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (FootClass::Unlimbo(coord, dir)) {\n\n\t\tif (*this == AIRCRAFT_BADGER || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera)) {\n\t\t\tIsALoaner = true;\n\t\t}\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->AScan |= (1L << Class->Type);\n\t\tHouse->ActiveAScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tHack it so that aircraft that are both passenger and cargo carrying\n\t\t**\twill carry passengers at the expense of ammo.\n\t\t*/\n\t\tif (Is_Something_Attached()) {\n\t\t\tAmmo = 0;\n\t\t\tPassenger = true;\n\t\t}\n\n\t\t/*\n\t\t**\tForces the body of the helicopter to face the correct direction.\n\t\t*/\n\t\tSecondaryFacing = dir;\n\n\t\t/*\n\t\t**\tStart rotor animation.\n\t\t*/\n\t\tif (!Class->IsFixedWing) {\n\t\t\tSet_Rate(1);\n\t\t\tSet_Stage(0);\n\t\t}\n\n\t\t/*\n\t\t**\tWhen starting at flight level, then give it speed. When landed\n\t\t**\tthen it must be stationary.\n\t\t*/\n\t\tif (Height == FLIGHT_LEVEL) {\n\t\t\tSet_Speed(0xFF);\n\t\t} else {\n\t\t\tSet_Speed(0);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Shape_Number -- Fetch the shape number to use for the aircraft.              *\n *                                                                                             *\n *    This will determine what shape number to use for the aircraft in its current state.      *\n *    The shape number can be used for drawing or determine shape rectangle size.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use for the aircraft body.                        *\n *                                                                                             *\n * WARNINGS:   Some aircraft, particularly helicopters, require other shapes attached to it.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Shape_Number(void) const\n{\n\tint shapenum = 0;\n\n\tswitch (Class->Rotation) {\n\t\tcase 32:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_32(SecondaryFacing)];\n\t\t\tbreak;\n\n\t\tcase 16:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_16(SecondaryFacing)*2]/2;\n\t\t\tbreak;\n\n\t\tcase 8:\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_8(SecondaryFacing)*4]/4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tIf there is a door on this aircraft (Chinook), then adjust the\n\t**\tshape number to match the door open state.\n\t*/\n\tif (!Is_Door_Closed()) {\n\t\tshapenum = Class->Rotation + Door_Stage();\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Draw_It -- Renders an aircraft object at the location specified.             *\n *                                                                                             *\n *    This routine is used to display the aircraft object at the coordinates specified.        *\n *    The tactical map display uses this routine for all aircraft rendering.                   *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates to render the aircraft at.                             *\n *                                                                                             *\n *          window   -- The window that the coordinates are based upon.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tVerify the legality of the unit class.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\tif (!shapefile) return;\n\n\tint shapenum = Shape_Number();\n\n\t/*\n\t**\tCertain aircraft use algorithmic rotation for some stages. Set the\n\t**\trotation value accordingly. A rotation of DIR_N means no rotation at all.\n\t*/\n\tDirType rotation = DIR_N;\n\tif (Class->Rotation == 16) {\n\t\trotation = DirType(Rotation16[SecondaryFacing]);\n\t}\n\n#ifdef TOFIX\n\t/*\n\t**\tThe orca attack helicopter uses a special shape set when it is travelling\n\t**\tforward above a certain speed.\n\t*/\n\tif (*this == AIRCRAFT_HIND && Get_Speed() >= MPH_MEDIUM_FAST) {\n\t\tshapenum += Class->Rotation;\n\t}\n#endif\n\n\t/*\n\t**\tHelicopters that are flying have a \"bobbing\" effect.\n\t*/\n\tint jitter = 0;\n\tif (Height == FLIGHT_LEVEL && Get_Speed() < 3) {\n\t\tstatic int _jitter[] = {0,0,0,0,1,1,1,0,0,0,0,0,-1,-1,-1,0};\n\t\tjitter = _jitter[::Frame % 16];\n\t}\n\n\t// Virtual window needs to draw the body first so it's considered the primary object and the shadow is a sub-object\n\tif (window == WINDOW_VIRTUAL) {\n\t\t/*\n\t\t**\tDraw the root body of the unit.\n\t\t*/\n\t\tTechno_Draw_Object(shapefile, shapenum, x, y+jitter, window, rotation);\n\n\t\t/*\n\t\t**\tSpecial manual shadow draw code.\n\t\t*/\n\t\tif (Visual_Character() <= VISUAL_DARKEN) {\n\t\t\tCC_Draw_Shape(this, shapefile, shapenum, x+1, y+2, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, DisplayClass::FadingShade, NULL);\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tSpecial manual shadow draw code.\n\t\t*/\n\t\tif (Visual_Character() <= VISUAL_DARKEN) {\n\t\t\tCC_Draw_Shape(this, shapefile, shapenum, x+1, y+2, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, DisplayClass::FadingShade, NULL);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the root body of the unit.\n\t\t*/\n\t\tTechno_Draw_Object(shapefile, shapenum, x, y+jitter, window, rotation);\n\t}\n\n\t/*\n\t**\tIf this aircraft is equipped with rotor blades, then draw them at this time.\n\t*/\n\tif (Class->IsRotorEquipped) {\n\t\tDraw_Rotors(x, y+jitter, window);\n\t}\n\n\t/*\n\t**\tThis draws any overlay graphics on the aircraft.\n\t*/\n\tFootClass::Draw_It(x, y-Lepton_To_Pixel(Height), window);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Draw_Rotors -- Draw rotor blades on the aircraft.                            *\n *                                                                                             *\n *    This routine will draw rotor blades on the aircraft. It is presumed that the aircraft    *\n *    has already been drawn at the X and Y pixel coordinates specified.                       *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel coordinates to draw the rotor blades.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Draw_Rotors(int x, int y, WindowNumberType window) const\n{\n\tShapeFlags_Type flags = SHAPE_CENTER|SHAPE_WIN_REL;\n\tint shapenum;\n\n\t/*\n\t**\tThe rotor shape number depends on whether the helicopter is idling\n\t**\tor not. A landed helicopter uses slow moving \"idling\" blades.\n\t*/\n\tif (Height == 0) {\n\t\tshapenum = (Fetch_Stage()%8)+4;\n\t\tflags = flags | SHAPE_GHOST;\n\t} else {\n\t\tshapenum = Fetch_Stage()%4;\n\t\tflags = flags | SHAPE_FADING|SHAPE_PREDATOR;\n\t}\n\n\tif (*this == AIRCRAFT_TRANSPORT) {\n\t\tint _stretch[FACING_COUNT] = {8, 9, 10, 9, 8, 9, 10, 9};\n\n\t\t/*\n\t\t**\tDual rotors offset along flight axis.\n\t\t*/\n\t\tshort xx = x;\n\t\tshort yy = y-Lepton_To_Pixel(Height);\n\t\tFacingType face = Dir_Facing(SecondaryFacing);\n\t\tMove_Point(xx, yy, SecondaryFacing.Current(), _stretch[face]);\n\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\tCC_Draw_Shape(this, \"RROTOR\", AircraftTypeClass::RRotorData, shapenum, xx, yy-2, window, flags, NULL, DisplayClass::UnitShadow);\n\n\t\tMove_Point(xx, yy, SecondaryFacing.Current()+DIR_S, _stretch[face]*2);\n\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\tCC_Draw_Shape(this, \"LROTOR\", AircraftTypeClass::LRotorData, shapenum, xx, yy-2, window, flags, NULL, DisplayClass::UnitShadow);\n\n\t} else {\n\n\t\t/*\n\t\t**\tSingle rotor centered about shape.\n\t\t*/\n\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\tCC_Draw_Shape(this, \"RROTOR\", AircraftTypeClass::RRotorData, shapenum, x, ((y-Lepton_To_Pixel(Height))-2), window, flags, NULL, DisplayClass::UnitShadow);\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Read_INI -- Reads aircraft object data from an INI file.                     *\n *                                                                                             *\n *    This routine is used to read the aircraft object data from the INI file buffer           *\n *    specified. This is used by the scenario loader code to interpret the INI file and        *\n *    create the specified objects therein.                                                    *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI buffer.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Read_INI(CCINIClass & ini)\n{\n\tAircraftClass\t* air;\t\t\t// Working unit pointer.\n\tHousesType\t\tinhouse;\t\t\t// Unit house.\n\tAircraftType\tclassid;\t\t\t// Unit class.\n\tchar\t\t\t\tbuf[128];\n\n\tint counter = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < counter; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf)-1);\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\t\t\tclassid = AircraftTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\t\tif (classid != AIRCRAFT_NONE) {\n\n\t\t\t\tif (HouseClass::As_Pointer(inhouse) != NULL) {\n\t\t\t\t\tair = new AircraftClass(classid, inhouse);\n\t\t\t\t\tif (air) {\n\t\t\t\t\t\tCOORDINATE\tcoord;\n\t\t\t\t\t\tint\tstrength;\n\t\t\t\t\t\tDirType dir;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tRead the raw data.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tchar * token = strtok(NULL, \",\");\n\t\t\t\t\t\tif (token) {\n\t\t\t\t\t\t\tstrength = atoi(token);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstrength = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\t\t\tif (token) {\n\t\t\t\t\t\t\tcoord = Cell_Coord((CELL)atoi(token));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcoord = 0xFFFFFFFFL;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\t\t\tif (token) {\n\t\t\t\t\t\t\tdir = (DirType)atoi(token);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdir = DIR_N;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!Map.In_Radar(Coord_Cell(coord))) {\n\t\t\t\t\t\t\tdelete air;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tair->Strength = (int)air->Class->MaxStrength * fixed(strength, 256);\t\t// Cast this to (int). ST - 5/8/19\n\t\t\t\t\t\t\tif (air->Unlimbo(coord, dir)) {\n\t\t\t\t\t\t\t\tair->Assign_Mission(AircraftClass::Mission_From_Name(strtok(NULL, \",\\n\\r\")));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdelete air;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Hunt -- Maintains hunt AI for the aircraft.                          *\n *                                                                                             *\n *    Hunt AI consists of finding a target and attacking it. If there is no target assigned    *\n *    and this unit doesn't automatically hunt for more targets, then it will change           *\n *    mission to a more passive (land and await further orders) type.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of ticks before calling this routine again.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Hunt(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tif (TarCom != NavCom) {\n\t\t\tAssign_Destination(TarCom);\n\t\t}\n\n\t\tenum {\n\t\t\tLOOK_FOR_TARGET,\n\t\t\tTAKE_OFF,\n\t\t\tFLY_TO_TARGET,\n\t\t\tDROP_BOMBS,\n\t\t\tREGROUP\n\t\t};\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tAcquiring target stage.\n\t\t\t*/\n\t\t\tcase LOOK_FOR_TARGET:\n\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t\treturn(1);\n\t\t\t\t} else {\n\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_TIBERIUM));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_NORMAL));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf there is no target, then this aircraft should just do its normal thing.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!Target_Legal(TarCom) && !Team.Is_Valid()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tMake the aircraft take off from the airstrip.\n\t\t\t*/\n\t\t\tcase TAKE_OFF:\n\t\t\t\t/*\n\t\t\t\t**\tIf the aircraft is high enough to begin its mission, then do so.\n\t\t\t\t*/\n\t\t\t\tif (Process_Take_Off())  {\n\t\t\t\t\tIsTakingOff = false;\n\t\t\t\t\tSet_Speed(0xFF);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact()/*KO && Map[Coord].Cell_Building() == Contact_With_Whom()*/) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TO_TARGET;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tHoming in on target stage.\n\t\t\t*/\n\t\t\tcase FLY_TO_TARGET:\n\t\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCatch the case where it is tightly circling the target. In that\n\t\t\t\t\t\t**\tcase, increase the delay so that it has a chance to fly away and\n\t\t\t\t\t\t**\tbreak the circle cycle.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (In_Range(TarCom, 0) || Passenger) {\n\t\t\t\t\t\t\treturn(TICKS_PER_SECOND * 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!PrimaryFacing.Is_Rotating() && Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_AMMO:\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_CANT:\n\t\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\t\tif (Mission == MISSION_ATTACK) {\n\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t\tStatus = DROP_BOMBS;\n\t\t\t\t\t\treturn(1);\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (!PrimaryFacing.Is_Rotating() && Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn(TICKS_PER_SECOND/2);\n\n\t\t\t/*\n\t\t\t**\tDropping a stream of bombs phase.\n\t\t\t*/\n\t\t\tcase DROP_BOMBS:\n\t\t\t\tTARGET targ;\n\t\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t\ttarg = ::As_Target(Coord_Move(Center_Coord(), SecondaryFacing, Weapon_Range(0)-0x0200));\n\t\t\t\t\t\tif (Class->PrimaryWeapon != NULL) {\n\t\t\t\t\t\t\tif (Class->PrimaryWeapon->IsCamera) {\n\t\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tForce the target to be the actual target if this aircraft is\n\t\t\t\t\t\t\t**\tequipped with homing projectile.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Class->PrimaryWeapon->Bullet != NULL && Class->PrimaryWeapon->Bullet->ROT > 0) {\n\t\t\t\t\t\t\t\ttarg = TarCom;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tFire_At(targ, 0);\n\t\t\t\t\t\tif (Class->Is_Two_Shooter()) {\n\t\t\t\t\t\t\tFire_At(targ, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(Arm);\n\n\t\t\t\t\tcase FIRE_RANGE:\n\t\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\t\tStatus = FLY_TO_TARGET;\n\t\t\t\t\t\treturn(TICKS_PER_SECOND*4);\n\n\t\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\t\tif (Mission == MISSION_ATTACK) {\n\t\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_CANT:\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase FIRE_AMMO:\n\t\t\t\t\t\tAttacksRemaining--;\n\t\t\t\t\t\tStatus = REGROUP;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tPull away to regroup for possibly another attack or a retreat.\n\t\t\t*/\n\t\t\tcase REGROUP:\n\t\t\t\tif (Ammo == 0) {\n\t\t\t\t\tAttacksRemaining = 0;\n\t\t\t\t\tif (Team.Is_Valid()) Team->Remove(this);\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\n\t\t\t\tif (Mission == MISSION_ATTACK || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera) || (!AttacksRemaining && !Is_Something_Attached())) {\n\n\t\t\t\t\tif (IsALoaner)  {\n\t\t\t\t\t\tif (Team) Team->Remove(this);\n\t\t\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t\t\t\tCommence();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t\tCommence();\n\t\t\t\t} else {\n\t\t\t\t\tStatus = LOOK_FOR_TARGET;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tif (!Ammo) {\n\t\t\tif (Team) Team->Remove(this);\n\t\t\tEnter_Idle_Mode();\n\t\t} else {\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_TIBERIUM));\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\tAssign_Target(Greatest_Threat(THREAT_NORMAL));\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t\treturn(1);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::AI -- Processes the normal non-graphic AI for the aircraft.                  *\n *                                                                                             *\n *    This handles the non-graphic AI processing for the aircraft. This usually entails        *\n *    maintenance and other AI functions.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::AI(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tA Mission change can always occur if the aircraft is landed or flying.\n\t*/\n\tif (!IsLanding && !IsTakingOff) {\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tPerform any base class AI processing. If during this process, the aircraft was\n\t**\tdestroyed, then detect this and bail from this AI routine early.\n\t*/\n\tFootClass::AI();\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tA Mission change can always occur if the aircraft is landed or flying.\n\t*/\n\tif (!IsLanding && !IsTakingOff) {\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tHandle any body rotation at this time. Body rotation can occur even if the\n\t**\tflying object is not actually moving.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t**\tHandle any aircraft movement at this time.\n\t*/\n\tMovement_AI();\n\n\t/*\n\t**\tAny aircraft that is not in the ground layer must be redrawn. This is a\n\t**\tperformance hit, but there is no other choice. The cells under an aircraft\n\t**\tdo not know if there is an aircraft above it. Thus, it cannot flag the\n\t**\taircraft to redraw. As a consequence, all aircraft must redraw.\n\t*/\n\tif (In_Which_Layer() != LAYER_GROUND) {\n\t\tMark();\n\t}\n\n\t/*\n\t**\tPerform sighting every so often as controlled by the sight timer.\n\t*/\n\t//if (IsOwnedByPlayer && Class->SightRange && SightTimer == 0) {  // Changed to facilitate client/server multiplayer. ST - 8/2/2019 2:29PM\t\n\tif (House->IsHuman && Class->SightRange && SightTimer == 0) {\n\t\tLook();\n\t\tSightTimer = TICKS_PER_SECOND;\n\t}\n\n\t/*\n\t**\tHandle landing and taking off logic. Helicopters are prime users of this technique. The\n\t**\taircraft will either gain or lose altitude as appropriate. As the aircraft transitions\n\t**\tbetween flying level and ground level, it will be moved into the appropriate render\n\t**\tlayer.\n\t*/\n\tif (Landing_Takeoff_AI()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tAlways flag the map draw process to occur if there is an aircraft in the view.\n\t**\tThis ensures that it will be rendered even if there is nothing else that flagged\n\t**\tthe map to be redrawn.\n\t*/\n\tif (Map.In_View(Coord_Cell(Coord))) {\n\t\tMap.Flag_To_Redraw(false);\n\t\tMap.DisplayClass::IsToRedraw = true;\n\t}\n\n\t/*\n\t**\tWhen aircraft leave the edge of the map, they might get destroyed. This occurs if the\n\t**\taircraft is a non-player produced unit and it has completed its mission. A transport\n\t**\thelicopter that has already delivered reinforcements is a good example of this.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Overlap_List -- Returns with list of cells the aircraft overlaps.            *\n *                                                                                             *\n *    When aircraft are flying, they can overlap quite a number of cells. These cells can      *\n *    be determined from the coordinate where the aircraft is centered and the size of the     *\n *    aircraft's shape. Landed aircraft are a special case and are usually much smaller        *\n *    than when flying.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset list that specifies all cells that         *\n *          the aircraft overlaps given the aircraft's current state.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AircraftClass::Overlap_List(bool redraw) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic short const _list[] = {\n\t\t-(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1),\n\t\t-1, 0, 1,\n\t\t(MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1),\n\t\t-((MAP_CELL_W*2)-1), -(MAP_CELL_W*2), -((MAP_CELL_W*2)+1),\n\t\t-((MAP_CELL_W*3)-1), -(MAP_CELL_W*3), -((MAP_CELL_W*3)+1),\n\t\tREFRESH_EOL\n\t};\n\n\tstatic short const _listbadger[] = {\n\t\t-(MAP_CELL_W-2), -(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1), -(MAP_CELL_W+2),\n\t\t-2, -1, 0, 1, 2,\n\t\t(MAP_CELL_W-2), (MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1), (MAP_CELL_W+2),\n\t\t-((MAP_CELL_W*2)-2), -((MAP_CELL_W*2)-1), -(MAP_CELL_W*2), -((MAP_CELL_W*2)+1), -((MAP_CELL_W*2)+2),\n\t\t-((MAP_CELL_W*3)-2), -((MAP_CELL_W*3)-1), -(MAP_CELL_W*3), -((MAP_CELL_W*3)+1), -((MAP_CELL_W*3)+2),\n\t\tREFRESH_EOL\n\t};\n\n\tif (redraw || Height != 0) {\n#ifdef PARTIAL\n\t\tRect rect;\n\t\tif (!IsSelected && Class->DimensionData != NULL && Class->IsFixedWing) {\n\t\t\tint shapenum = min(Shape_Number(), Get_Build_Frame_Count(Class->Get_Image_Data())-1);\n\t\t\tif (!Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Class->Get_Image_Data(), shapenum);\n\t\t\t}\n\t\t\trect = Class->DimensionData[shapenum];\n\n\t\t\t/*\n\t\t\t**\tIncrease the rectangle for the aircraft since the aircraft could\n\t\t\t**\thave its shape algorithmically rotated.\n\t\t\t*/\n\t\t\trect.X -= 5;\n\t\t\trect.Y -= 5;\n\t\t\trect.Width += 10;\n\t\t\trect.Height += 10;\n\n\t\t\tRect hrect = rect;\n\n\t\t\threct.Y -= Lepton_To_Pixel(Height);\n\n\t\t\treturn(Coord_Spillage_List(Coord, Union(rect, hrect), true));\n\t\t}\n#endif\n\n\t\tif (*this == AIRCRAFT_BADGER) {\n\t\t\treturn(_listbadger);\n\t\t} else {\n\t\t\treturn(_list);\n\t\t}\n\t}\n\treturn(Class->Overlap_List());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Init -- Initialize the aircraft system to an empty state.                    *\n *                                                                                             *\n *    This routine is used to clear out the aircraft allocation system. It is called in        *\n *    preparation for a scenario load or save game load.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Init(void)\n{\n\tAircraft.Free_All();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Unload -- Handles unloading cargo.                                   *\n *                                                                                             *\n *    This function is used to handle finding, heading toward, landing, and unloading the      *\n *    cargo from the aircraft. Once unloading of cargo has occurred, then the aircraft follows *\n *    a different mission.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game ticks to delay before calling this function again.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/31/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Unload(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tAssign_Target(NavCom);\n\t\treturn(Mission_Hunt());\n\n\t} else {\n\t\tenum {\n\t\t\tSEARCH_FOR_LZ,\n\t\t\tFLY_TO_LZ,\n\t\t\tLAND_ON_LZ,\n\t\t\tUNLOAD_PASSENGERS,\n\t\t\tTAKE_OFF\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tSearch for an appropriate destination spot if one isn't already assigned.\n\t\t\t*/\n\t\t\tcase SEARCH_FOR_LZ:\n\t\t\t\tif (Height == 0 && (Target_Legal(NavCom) || Coord == As_Coord(NavCom))) {\n\t\t\t\t\tStatus = UNLOAD_PASSENGERS;\n\t\t\t\t} else {\n\t\t\t\t\tif (!Is_LZ_Clear(NavCom)) {\n\n\t\t\t\t\t\tFootClass * foot = Attached_Object();\n\t\t\t\t\t\tif (foot != NULL && foot->Team && foot->Team->Class->Origin != -1) {\n\t\t\t\t\t\t\tAssign_Destination(::As_Target(Scen.Waypoint[foot->Team->Class->Origin]));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(New_LZ(::As_Target(Scen.Waypoint[WAYPT_REINF])));\n\t\t\t\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Height == FLIGHT_LEVEL) {\n\t\t\t\t\t\t\tStatus = FLY_TO_LZ;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tFly to destination.\n\t\t\t*/\n\t\t\tcase FLY_TO_LZ:\n\t\t\t\tif (Is_LZ_Clear(NavCom)) {\n\t\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\t\tif (distance < 0x0100) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\n\t\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\t\tStatus = LAND_ON_LZ;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\t\t\treturn(5);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = SEARCH_FOR_LZ;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLanding phase. Just delay until landing is complete. At that time,\n\t\t\t**\ttransition to the unloading phase.\n\t\t\t*/\n\t\t\tcase LAND_ON_LZ:\n\t\t\t\tif (IsTakingOff) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t} else {\n\t\t\t\t\tif (Process_Landing()) {\n\t\t\t\t\t\tStatus = UNLOAD_PASSENGERS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tHold while unloading passengers. When passengers are unloaded the order for this\n\t\t\t**\ttransport gets changed to MISSION_RETREAT.\n\t\t\t*/\n\t\t\tcase UNLOAD_PASSENGERS:\n\t\t\t\tif (!IsTethered) {\n\t\t\t\t\tif (Is_Something_Attached()) {\n\t\t\t\t\t\tFootClass * unit = (FootClass *)Detach_Object();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFirst thing is to lift the transport off of the map so that the unlimbo\n\t\t\t\t\t\t**\tprocess for the passengers is more likely to succeed.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMap.Pick_Up(Coord_Cell(Coord), this);\n\n\t\t\t\t\t\tif (!Exit_Object(unit)) {\n\t\t\t\t\t\t\tdelete unit;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tRestore the transport back down on the map.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMap.Place_Down(Coord_Cell(Coord), this);\n\n\t\t\t\t\t\tif (!Is_Something_Attached()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else  {\n\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAircraft is now taking off. Once the aircraft reaches flying altitude then it\n\t\t\t**\twill either take off or look for another landing spot to try again.\n\t\t\t*/\n\t\t\tcase TAKE_OFF:  {\n\t\t\t\tif (Process_Take_Off()) {\n\t\t\t\t\tif (Is_Something_Attached()) {\n\t\t\t\t\t\tStatus = SEARCH_FOR_LZ;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tBreak off radio contact with the helipad it is taking off from.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else  {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Is_LZ_Clear -- Determines if landing zone is free for landing.               *\n *                                                                                             *\n *    This routine examines the landing zone (as specified by the target parameter) in order   *\n *    to determine if it is free to be landed upon. Call this routine when it is necessary     *\n *    to double check this. Typically this occurs right before a helicopter lands and also     *\n *    when determining the landing zone in the first place.                                    *\n *                                                                                             *\n * INPUT:   target   -- The target that is the \"landing zone\".                                 *\n *                                                                                             *\n * OUTPUT:  bool; Is the landing zone clear for landing?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/31/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Is_LZ_Clear(TARGET target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Target_Legal(target)) return(false);\n\tCELL cell = ::As_Cell(target);\n\tif (!Map.In_Radar(cell)) return(false);\n\n\t/*\n\t**\tIf the requested landing location is occupied, then only consider that location\n\t**\tlegal if the occupying object is in radio contact with the aircraft. This presumes that\n\t**\tthe two objects know what they are doing.\n\t*/\n\tObjectClass * object = Map[cell].Cell_Object();\n\tif (object) {\n\t\tif (object == this) return(true);\n\n\t\tif (In_Radio_Contact() && Contact_With_Whom() == object) {\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\tif (!Map[cell].Is_Clear_To_Move(SPEED_TRACK, false, false)) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Sort_Y -- Figures the sorting coordinate.                                    *\n *                                                                                             *\n *    This routine is used to determine the coordinate to use for sorting the aircraft. This   *\n *    sorting value is used when the aircraft is on the ground. At that time the aircraft      *\n *    must be rendered in proper relationship to the other ground objects.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when sorting the aircraft with other ground     *\n *          objects.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE AircraftClass::Sort_Y(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, 0x00800000L));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Retreat -- Handles the aircraft logic for leaving the battlefield.   *\n *                                                                                             *\n *    This mission will be followed when the aircraft decides that it is time to leave the     *\n *    battle. Typically, this occurs when a loaner transport has dropped off its load or when  *\n *    an attack air vehicle has expended its ordinance.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to delay before calling this routine again.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *   08/13/1995 JLB : Handles aircraft altitude gain after takeoff logic.                      *\n *=============================================================================================*/\nint AircraftClass::Mission_Retreat(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\t\tif (Class->IsFixedWing && Height < FLIGHT_LEVEL) {\n\t\t\tHeight += 1;\n\t\t\treturn(3);\n\t\t}\n\t\treturn(TICKS_PER_SECOND*10);\n\t}\n\n\tenum {\n\t\tTAKE_OFF,\n\t\tFACE_MAP_EDGE,\n\t\tKEEP_FLYING\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tTake off if landed.\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (Process_Take_Off()) {\n\t\t\t\tStatus = FACE_MAP_EDGE;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tSet facing and speed toward the friendly map edge.\n\t\t*/\n\t\tcase FACE_MAP_EDGE:\n\t\t\tSet_Speed(0xFF);\n\n\t\t\t/*\n\t\t\t**\tTake advantage of the fact that the source map edge enumerations happen to\n\t\t\t**\toccur in a clockwise order and are the first four enumerations of the map\n\t\t\t**\tedge default for the house. If this value is masked and then shifted, a\n\t\t\t**\tnormalized direction value results. Use this value to head the aircraft\n\t\t\t**\ttoward the \"friendly\" map edge.\n\t\t\t*/\n\t\t\tPrimaryFacing.Set_Desired((DirType)((House->Control.Edge & 0x03) << 6));\n\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\tStatus = KEEP_FLYING;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tJust do nothing since we are headed toward the map edge. When the edge is\n\t\t**\treached, the aircraft should be automatically eliminated.\n\t\t*/\n\t\tcase KEEP_FLYING:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Exit_Object -- Unloads passenger from aircraft.                              *\n *                                                                                             *\n *    This routine is called when the aircraft is to unload a passenger. The passenger must    *\n *    be able to move under its own power. Typical situation is when a transport helicopter    *\n *    is to unload an infantry unit.                                                           *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit that is to be unloaded from this aircraft.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit unloaded successfully?                                          *\n *                                                                                             *\n * WARNINGS:   The unload process is merely started by this routine. Radio contact is          *\n *             established with the unloading unit and when the unit is clear of the aircraft  *\n *             the radio contact will be broken and then the aircraft is free to pursue        *\n *             other.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Exit_Object(TechnoClass * unit)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic FacingType _toface[FACING_COUNT] = {FACING_S, FACING_SW, FACING_SE, FACING_NW, FACING_NE, FACING_N, FACING_W, FACING_E};\n\tCELL\tcell;\n\n\t/*\n\t**\tFind a free cell to drop the unit off at.\n\t*/\n\tFacingType face;\n\tfor (face = FACING_N; face < FACING_COUNT; face++) {\n\t\tcell = Adjacent_Cell(Coord_Cell(Coord), _toface[face]);\n\t\tif (unit->Can_Enter_Cell(cell) == MOVE_OK) break;\n\t}\n\n\t// Should perform a check here to see if no cell could be found.\n\n\t/*\n\t**\tIf the passenger can be placed on the map, then start it moving toward the\n\t**\tdestination cell and establish radio contact with the transport. This is used\n\t**\tto make sure that the transport waits until the passenger is clear before\n\t**\tunloading the next passenger or taking off.\n\t*/\n\tif (unit->Unlimbo(Coord, Facing_Dir(_toface[face]))) {\n\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\tunit->Assign_Destination(::As_Target(cell));\n\t\tif (Transmit_Message(RADIO_HELLO, unit) == RADIO_ROGER) {\n\t\t\tTransmit_Message(RADIO_UNLOAD);\n\t\t}\n\t\tunit->Look(false);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Paradrop_Cargo -- Drop a passenger by parachute.                             *\n *                                                                                             *\n *    Call this routine when a passenger needs to be dropped off by parachute. One passenger   *\n *    is offloaded by a call to this routine.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay time that it is safe to wait before processing any further  *\n *          paradrop actions.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Paradrop_Cargo(void)\n{\n\tFootClass * passenger = Detach_Object();\n\tif (passenger) {\n\t\tif (!passenger->Paradrop(Center_Coord())) {\n\t\t\tAttach(passenger);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tPlay a sound effect of the parachute opening.\n\t\t\t*/\n\t\t\tSound_Effect(VOC_CHUTE1, Coord);\n\n\t\t\tif (Team.Is_Valid()) {\n\t\t\t\tTeam->Remove(passenger);\n\t\t\t\tif (passenger->House->IsHuman) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t}\n\t\t\t}\n//\t\t\tArm = Rearm_Delay(IsSecondShot);\n\t\t\tArm = 0;\n\t\t}\n\t}\n\treturn(Arm);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Fire_At -- Handles firing a projectile from an aircraft.                     *\n *                                                                                             *\n *    Sometimes, aircraft firing needs special handling. Example: for napalm bombs, the        *\n *    bomb travels forward at nearly the speed of the delivery aircraft, not necessarily the   *\n *    default speed defined in the BulletTypeClass structure.                                  *\n *                                                                                             *\n * INPUT:   target   -- The target that the projectile is heading for.                         *\n *                                                                                             *\n *          which    -- Which weapon to use in the attack. 0=primary, 1=secondary.             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the bullet that was created as a result of this attack.  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * AircraftClass::Fire_At(TARGET target, int which)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tPassenger aircraft will actually paradrop their cargo instead of\n\t**\tfiring their weapon.\n\t*/\n\tif (Is_Something_Attached()) {\n\t\tParadrop_Cargo();\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the weapon is actually a camera, then perform the \"snapshot\" of the\n\t**\tground instead of normal weapon fire.\n\t*/\n\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera) {\n\t\t\n\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\n\t\t\tif (House->Is_Ally(PlayerPtr)) {\n\t\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 9, House, false);\n\t\t\t}\n\t\t\t\n\t\t} else {\n\t\t\n\t\t\tfor (int i = 0; i < Session.Players.Count(); i++) {\n\t\t\t\tHousesType house_type = Session.Players[i]->Player.ID;\n\t\t\t\tHouseClass *house = HouseClass::As_Pointer(house_type);\n\n\t\t\t\tif (house == House || House->Is_Ally(house)) {\n\t\t\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 9, house, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tAmmo = 0;\n\t\tArm = Rearm_Delay(IsSecondShot);\n\t\treturn(0);\n\t}\n\n\n\tBulletClass * bullet = FootClass::Fire_At(target, which);\n\n\tif (bullet) {\n\n\t\t/*\n\t\t**\tAircraft reveal when firing\n\t\t*/\n\t\tHouseClass *player = HouseClass::As_Pointer(Owner());\n\t\tif (player != nullptr && player->IsHuman) {\n\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), 1, player, false);\n\t\t}\n\n\t\t/*\n\t\t**\tFalling bullets move at a speed proportionate to the delivery craft.\n\t\t*/\n\t\tif (bullet->Class->IsDropping) {\n\t\t\tbullet->Fly_Speed(40, MPH_MEDIUM_SLOW);\t\t// TCTC To fix.\n\t\t}\n\t}\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Take_Damage -- Applies damage to the aircraft.                               *\n *                                                                                             *\n *    This routine is used to apply damage to the specified aircraft. This is where any        *\n *    special crash animation will be initiated.                                               *\n *                                                                                             *\n * INPUT:   damage   -- Reference to the damage that will be applied to the aircraft.          *\n *                      This value will be filled in with the actual damage that was           *\n *                      applied.                                                               *\n *                                                                                             *\n *          distance -- Distance from the source of the explosion to this aircraft.            *\n *                                                                                             *\n *          warhead  -- The warhead type that the damage occurs from.                          *\n *                                                                                             *\n *          source   -- Pointer to the originator of the damage. This can be used so that      *\n *                      proper \"thank you\" can be delivered.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the result of the damage as it affects this aircraft.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/26/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType AircraftClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tFlying aircraft take half damage.\n\t*/\n\tif (Height) {\n\t\tdamage /= 2;\n\t}\n\n\t/*\n\t**\tApply the damage to the aircraft.\n\t*/\n\tres = FootClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\t/*\n\t**\tSpecial action is performed if the aircraft is killed -- the cargo is destroyed\n\t**\tas well.\n\t*/\n\tswitch (res) {\n\t\tcase RESULT_DESTROYED:\n\t\t\t{\n\t\t\t\tKill_Cargo(source);\n\t\t\t\tDeath_Announcement();\n\t\t\t\tCOORDINATE coord = Target_Coord();\n\t\t\t\tif (!(coord & HIGH_COORD_MASK)) {\n\t\t\t\t\tnew AnimClass(ANIM_FBALL1, coord);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tParachute a survivor if possible.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsCrew && Percent_Chance(90) && Map[Center_Coord()].Is_Clear_To_Move(SPEED_FOOT, true, false)) {\n\t\t\t\t\tInfantryClass * infantry = new InfantryClass(INFANTRY_E1, House->Class->House);\n\t\t\t\t\tif (infantry != NULL) {\n\t\t\t\t\t\tif (!infantry->Paradrop(Center_Coord())) {\n\t\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdelete this;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase RESULT_HALF:\n\t\t\tbreak;\n\t}\n\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Move -- Handles movement mission.                                    *\n *                                                                                             *\n *    This state machine routine is used when an aircraft (usually helicopter) is to move      *\n *    from one location to another. It will handle any necessary take off and landing this     *\n *    may require.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames that should elapse before this routine      *\n *          is called again.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Move(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\n\t\tenum  {\n\t\t\tTAKE_OFF,\n\t\t\tFLY_TOWARD_TARGET\n\t\t};\n\n\t\tswitch (Status) {\n\t\t\tint distance;\n\n\t\t\tcase TAKE_OFF:\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the aircraft is high enough to begin its mission, then do so.\n\t\t\t\t*/\n\t\t\t\tif (Process_Take_Off())  {\n\t\t\t\t\tIsTakingOff = false;\n\t\t\t\t\tSet_Speed(0xFF);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TOWARD_TARGET;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tcase FLY_TOWARD_TARGET:\n\t\t\t\tPrimaryFacing.Set_Desired(Direction(NavCom));\n\t\t\t\tdistance = Distance(NavCom);\n\n\t\t\t\tif (distance < 0x00C0) {\n\t\t\t\t\tMissionType mission = MISSION_GUARD;\n\n\t\t\t\t\tif (!IsALoaner) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(Class->Building, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers() ) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (building && (Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER || building->What_Am_I() == RTTI_VESSEL) ) {\n#else\n\t\t\t\t\t\tif (building && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n#endif\n\t\t\t\t\t\t\tmission = MISSION_ENTER;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (building->What_Am_I() == RTTI_VESSEL) {\n\t\tAssign_Destination(building->As_Target());\n\t}\n#endif\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If this aircraft has nowhere else to go, meaning that\n\t\t\t\t\t\t\t** there is no airfield available, then it has to crash.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Is_Target_Cell(NavCom)) {\n\n\t\t\t\t\t\t\t\tif (Process_Landing()) {\n\t\t\t\t\t\t\t\t\tStrength = 1;\n\t\t\t\t\t\t\t\t\tint damage = Strength;\n\t\t\t\t\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn(500);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAssign_Mission(mission);\n\t\t\t\t\t\tCommence();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn(5);\n\t}\n\n\tenum {\n\t\tVALIDATE_LZ,\n\t\tTAKE_OFF,\n\t\tFLY_TO_LZ,\n\t\tLAND\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tDouble check and change LZ if necessary.\n\t\t*/\n\t\tcase VALIDATE_LZ:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t} else {\n\t\t\t\tif (!Is_LZ_Clear(NavCom) || !Cell_Seems_Ok(As_Cell(NavCom))) {\n\t\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTake off if necessary.\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tStatus = VALIDATE_LZ;\n\t\t\t} else {\n\t\t\t\tif (Process_Take_Off()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAfter takeoff is complete, break radio contact with any helipad that this\n\t\t\t\t\t**\thelicopter is taking off from.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\tStatus = FLY_TO_LZ;\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly toward target.\n\t\t*/\n\t\tcase FLY_TO_LZ:\n\t\t\tif (Is_LZ_Clear(NavCom)) {\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (distance < 0x0080) {\n\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\tStatus = LAND;\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n//\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\tSecondaryFacing.Set_Desired(Direction(NavCom));\n\n\t\t\t} else {\n\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = LAND;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tLand on target.\n\t\t*/\n\t\tcase LAND:\n\t\t\tif (IsTakingOff) {\n\t\t\t\tAssign_Destination(New_LZ(NavCom));\n\t\t\t\tif (Team.Is_Valid()) {\n\t\t\t\t\tTeam->Assign_Mission_Target(NavCom);\n\t\t\t\t}\n\t\t\t\tStatus = TAKE_OFF;\n\t\t\t}\n\t\t\tif (Process_Landing()) {\n\t\t\t\tif (MissionQueue == MISSION_NONE) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Enter_Idle_Mode -- Gives the aircraft an appropriate mission.                *\n *                                                                                             *\n *    Use this routine when the mission for the aircraft is in doubt. This routine will find   *\n *    an appropriate mission for the aircraft and dispatch it.                                 *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Enter_Idle_Mode(bool )\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType mission = (Class->IsFixedWing && IsALoaner && Class->PrimaryWeapon != NULL) ? MISSION_HUNT : MISSION_GUARD;\n\tif (Class->IsFixedWing) {\n\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\tif (IsALoaner) {\n\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t} else {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tmission = MISSION_GUARD;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf this transport is a loaner and part of a team, then remove it from\n\t\t\t**\tthe team it is attached to.\n\t\t\t*/\n\t\t\tif ((IsALoaner && House->IsHuman) || (!House->IsHuman && !Ammo)) {\n\t\t\t\tif (Team.Is_Valid() && Team->Has_Entered_Map()) {\n\t\t\t\t\tTeam->Remove(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Team.Is_Valid()) return;\n\n\t\t\t/*\n\t\t\t**\tWeapon equipped helicopters that run out of ammo and were\n\t\t\t**\tbrought in as reinforcements will leave the map.\n\t\t\t*/\n\t\t\tif (Mission != MISSION_ATTACK && IsALoaner && Ammo == 0 && Class->PrimaryWeapon != NULL) {\n\t\t\t\tmission = MISSION_HUNT;\n\t\t\t} else {\n\n\t\t\t\tif (!IsALoaner) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t*/\n\t\t\t\t\tBuildingClass * building = NULL;\n\t\t\t\t\tif (In_Radio_Contact() && Contact_With_Whom()->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\tbuilding = (BuildingClass *)Contact_With_Whom();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilding = Find_Docking_Bay(Class->Building, false);\n\t\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, building) != RADIO_ROGER) {\n\t\t\t\t\t\t\tbuilding = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tif (building != NULL) {\n\t\t\t\t\t\tif (Class->IsFixedWing) {\n\t\t\t\t\t\t\tStatus = 0;\t//BG - reset the mission status to avoid landing on the ground next to the airstrip\n\t\t\t\t\t\t\tif (IsLanding) {\n\t\t\t\t\t\t\t\tProcess_Take_Off();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmission = MISSION_ENTER;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\tif (IsALoaner) {\n\t\t\t\tif (Is_Something_Attached()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIn the case of a computer controlled helicopter that hold passengers,\n\t\t\t\t\t**\tdon't unload when landing. Wait for specific instructions from the\n\t\t\t\t\t**\tcontrolling team.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Team.Is_Valid()) {\n//\t\t\t\t\tif (Team.Is_Valid() && !House->IsHuman) {\n\t\t\t\t\t\tmission = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_UNLOAD;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tmission = MISSION_GUARD;\n\t\t\t}\n\t\t} else {\n\t\t\tif (Is_Something_Attached()) {\n\t\t\t\tif (IsALoaner) {\n\t\t\t\t\tif (Team) {\n\t\t\t\t\t\tmission = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmission = MISSION_UNLOAD;\n\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this transport is a loaner and part of a team, then remove it from\n\t\t\t\t**\tthe team it is attached to.\n\t\t\t\t*/\n\t\t\t\tif ((IsALoaner && House->IsHuman) || (!House->IsHuman && !Ammo)) {\n\t\t\t\t\tif (Team.Is_Valid() && Team->Has_Entered_Map()) {\n\t\t\t\t\t\tTeam->Remove(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (Class->PrimaryWeapon != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tWeapon equipped helicopters that run out of ammo and were\n\t\t\t\t\t**\tbrought in as reinforcements will leave the map.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsALoaner) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf it has no ammo, then break off of the team and leave the map.\n\t\t\t\t\t\t**\tIf it can fight, then give it fighting orders.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Ammo == 0) {\n\t\t\t\t\t\t\tif (Team.Is_Valid()) Team->Remove(this);\n\t\t\t\t\t\t\tmission = MISSION_RETREAT;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!Team.Is_Valid()) {\n\t\t\t\t\t\t\t\tmission = MISSION_HUNT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNormal aircraft try to find a good landing spot to rest.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tBuildingClass * building = Find_Docking_Bay(Class->Building, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers()/* && !ship->In_Radio_Contact()*/) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (building && (Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER || building->What_Am_I() == RTTI_VESSEL) ) {\n#else\n\t\t\t\t\t\tif (building && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) {\n#endif\n\t\t\t\t\t\t\tmission = MISSION_ENTER;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (building->What_Am_I() == RTTI_VESSEL) {\n\t\t\t\t\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Team) return;\n\n\t\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\t\tmission = MISSION_MOVE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(mission);\n\tCommence();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Fly_To -- Handles state machine for flying to destination.           *\n *                                                                                             *\n *    This support routine is used when the helicopter is to fly to the destination. It can    *\n *    optionally slow the helicopter down as it approaches the destination.                    *\n *                                                                                             *\n * INPUT:   slowdown -- Should the aircraft be slowed down when it approaches the dest?        *\n *                                                                                             *\n * OUTPUT:  Returns with the distance remaining between the aircraft and the destination.      *\n *                                                                                             *\n * WARNINGS:   Because the aircraft can move at a fast speed, the distance to target value     *\n *             will probably never be zero. The likely case will be that the aircraft          *\n *             overshoots the target.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *   03/05/1996 JLB : Specifies destination target value.                                      *\n *=============================================================================================*/\nint AircraftClass::Process_Fly_To(bool slowdown, TARGET dest)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) slowdown = false;\n\n\tCOORDINATE coord;\n\tif (Is_Target_Building(dest)) {\n\t\tcoord = As_Building(dest)->Docking_Coord();\n\t} else {\n\t\tcoord = As_Coord(dest);\n\t}\n\tint distance = Distance(coord);\n\n\tPrimaryFacing.Set_Desired(Direction(coord));\n\n\tif (slowdown) {\n\t\tint speed = min(distance, 0x0300);\n\t\tspeed = Bound(speed/3, 0x0020, 0x00FF);\n\t\tif (Speed != speed) {\n\t\t\tSet_Speed(speed);\n\t\t}\n\t}\n\n\tif (distance < 0x0010) {\n\t\tif (slowdown) {\n\t\t\tSet_Speed(0);\n\t\t}\n\t\tdistance = 0;\n\t}\n\treturn(distance);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * AircraftClass::Debug_Dump -- Displays the status of the aircraft to the mono monitor.       *\n *                                                                                             *\n *    This displays the current status of the aircraft class to the mono monitor. By this      *\n *    display bugs may be tracked down or prevented.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_AIRCRAFT));\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", AttacksRemaining);\n\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * AircraftClass::Active_Click_With -- Handles clicking over specified object.                 *\n *                                                                                             *\n *    This routine is used when the player clicks over the speicifed object. It will assign    *\n *    the appropriate mission to the aircraft.                                                 *\n *                                                                                             *\n * INPUT:   action   -- The action that was nominally determined by the What_Action function.  *\n *                                                                                             *\n *          object   -- The object over which the mouse was clicked.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will alter the game sequence and causes an event packet to be      *\n *             propagated to all connected machines.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\taction = What_Action(object);\n\n\tswitch (action) {\n\t\tcase ACTION_NOMOVE:\n\t\t\treturn;\n\n\t\tcase ACTION_ENTER:\n\t\t\tPlayer_Assign_Mission(MISSION_ENTER, TARGET_NONE, object->As_Target());\n\t\t\tbreak;\n\n\t\tcase ACTION_SELF:\n\t\t\tPlayer_Assign_Mission(MISSION_UNLOAD, TARGET_NONE, TARGET_NONE);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tFootClass::Active_Click_With(action, object);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Active_Click_With -- Handles clicking over specified cell.                   *\n *                                                                                             *\n *    This routine is used when the player clicks the mouse of the specified cell. It will     *\n *    assign the appropriate mission to the aircraft.                                          *\n *                                                                                             *\n * INPUT:   action   -- The action nominally determined by What_Action().                      *\n *                                                                                             *\n *          cell     -- The cell over which the mouse was clicked.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will affect the game sequence and causes an event object to be     *\n *             propagated to all connected machines.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::Active_Click_With(action, cell);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Player_Assign_Mission -- Handles player input to assign a mission.           *\n *                                                                                             *\n *    This routine is called as a result of player input with the intent to change the         *\n *    mission of the aircraft.                                                                 *\n *                                                                                             *\n * INPUT:   mission  -- The mission requested of the aircraft.                                 *\n *                                                                                             *\n *          target   -- The value to assign to the aircraft's targeting computer.              *\n *                                                                                             *\n *          dest.    -- The value to assign to the aircraft's navigation computer.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The mission specified will be executed at an indeterminate future game frame.   *\n *             This is controlled by net/modem propagation delay.                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Player_Assign_Mission(MissionType mission, TARGET target, TARGET destination)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (AllowVoice) {\n\t\tif (mission == MISSION_ATTACK) {\n\t\t\tResponse_Attack();\n\t\t} else {\n\t\t\tResponse_Move();\n\t\t}\n\t}\n\tQueue_Mission(TargetClass(this), mission, target, destination);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::What_Action -- Determines what action to perform.                            *\n *                                                                                             *\n *    This routine is used to determine what action will likely be performed if the mouse      *\n *    were clicked over the object specified. The display system calls this routine to         *\n *    control the mouse shape.                                                                 *\n *                                                                                             *\n * INPUT:   target   -- Pointer to the object that the mouse is currently over.                *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will occur if the mouse were clicked over the         *\n *          object specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType AircraftClass::What_Action(ObjectClass const * target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(target);\n\n\tif (action == ACTION_SELF && (!How_Many() || (Height > 0) || IsTethered)) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon == NULL) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (House->IsPlayerControl && House->Is_Ally(target) && target->What_Am_I() == RTTI_BUILDING && ((AircraftClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)target) == RADIO_ROGER) {\n\t\taction = ACTION_ENTER;\n\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing && House->IsPlayerControl && House->Is_Ally(target) && target->What_Am_I() == RTTI_VESSEL && *(VesselClass *)target == VESSEL_CARRIER && ((AircraftClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)target) == RADIO_ROGER) {\n\t\taction = ACTION_ENTER;\n\t}\n#endif\n\n\tif (Class->IsFixedWing && action == ACTION_MOVE) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\tif (action == ACTION_NONE) {\n\t\taction = What_Action(Coord_Cell(target->Center_Coord()));\n\t}\n\n\t/*\n\t**\tSpecial return to friendly repair factory action.\n\t*/\n\tif (House->IsPlayerControl && action == ACTION_SELECT && target->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass * building = (BuildingClass *)target;\n\t\tif (building->Class->Type == STRUCT_REPAIR && !building->In_Radio_Contact() && !building->Is_Something_Attached()) {\n\t\t\taction = ACTION_ENTER;\n\t\t}\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::What_Action -- Determines what action to perform.                            *\n *                                                                                             *\n *    This routine will determine what action would occur if the mouse were clicked over the   *\n *    cell specified. The display system calls this routine to determine what mouse shape      *\n *    to use.                                                                                  *\n *                                                                                             *\n * INPUT:   cell  -- The cell over which the mouse is currently positioned.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the action that will be performed if the mouse were clicked at the    *\n *          specified cell location.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType AircraftClass::What_Action(CELL cell) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(cell);\n\n\t//using function for IsVisible so we have different results for different players - JAS 2019/09/30\n\tif ((action == ACTION_MOVE || action == ACTION_ATTACK) && !Map[cell].Is_Visible(PlayerPtr)) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon == NULL) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (Class->IsFixedWing && action == ACTION_MOVE) {\n\t\taction = ACTION_NOMOVE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Pose_Dir -- Fetches the natural landing facing.                              *\n *                                                                                             *\n *    Use this routine to get the desired facing the aircraft should assume when landing.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the normal default facing the aircraft should have when landed.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *   03/04/1996 JLB : Fixed wing aircraft always face down the runway.                         *\n *=============================================================================================*/\nDirType AircraftClass::Pose_Dir(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == AIRCRAFT_TRANSPORT) {\n\t\treturn(DIR_N);\n\t}\n\tif (Class->IsFixedWing)  {\n\t\treturn(DIR_E);\n\t}\n\treturn(DIR_NE);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Attack -- Handles the attack mission for aircraft.                   *\n *                                                                                             *\n *    This routine is the state machine that handles the attack mission for aircraft. It will  *\n *    handling homing in on and firing on the target in the aircraft's targeting computer.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to pass before this routine must be called   *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *   09/22/1995 JLB : Fixes brain dead helicopter for Nod scen #7.                             *\n *=============================================================================================*/\nint AircraftClass::Mission_Attack(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsFixedWing) {\n\t\treturn(Mission_Hunt());\n\t}\n\n\tenum {\n\t\tVALIDATE_AZ,\n\t\tPICK_ATTACK_LOCATION,\n\t\tTAKE_OFF,\n\t\tFLY_TO_POSITION,\n\t\tFIRE_AT_TARGET,\n\t\tFIRE_AT_TARGET2,\n\t\tRETURN_TO_BASE\n\t};\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tDouble check target and validate the attack zone.\n\t\t*/\n\t\tcase VALIDATE_AZ:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPick a good location to attack from.\n\t\t*/\n\t\tcase PICK_ATTACK_LOCATION:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tAssign_Destination(Good_Fire_Location(TarCom));\n\t\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = TAKE_OFF;\n\t\t\t\t} else {\n\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTake off (if necessary).\n\t\t*/\n\t\tcase TAKE_OFF:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t} else {\n\t\t\t\tif (Process_Take_Off()) {\n\t\t\t\t\tStatus = FLY_TO_POSITION;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tBreak off radio contact with the helipad it is taking off from.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tStart flying toward the destination by skewing at first.\n\t\t\t\t\t**\tAs the flight progresses, the body will rotate to face\n\t\t\t\t\t**\tthe direction of travel.\n\t\t\t\t\t*/\n\t\t\t\t\tint diff = SecondaryFacing.Difference(Direction(NavCom));\n\t\t\t\t\tdiff = Bound(diff, -128, 128);\n\t\t\t\t\tPrimaryFacing = DirType((int)SecondaryFacing.Current()+diff);\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly to attack location.\n\t\t*/\n\t\tcase FLY_TO_POSITION:\n\t\t\tif (Target_Legal(TarCom)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the navcom was cleared mysteriously, then try to pick\n\t\t\t\t**\ta new attack location. This is a likely event if the player\n\t\t\t\t**\tclicks on a new target while in flight to an existing target.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (distance < 0x0200) {\n\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\n\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\tStatus = FIRE_AT_TARGET;\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tFire at the target.\n\t\t*/\n\t\tcase FIRE_AT_TARGET:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t\t\tStatus = FIRE_AT_TARGET2;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_REARM:\n\t\t\t\tcase FIRE_FACING:\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (!Ammo) {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = FIRE_AT_TARGET2;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn(1);\n\n\t\t/*\n\t\t**\tFire at the target.\n\t\t*/\n\t\tcase FIRE_AT_TARGET2:\n\t\t\tif (!Target_Legal(TarCom)) {\n\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\tswitch (Can_Fire(TarCom, 0)) {\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_REARM:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\n\t\t\t\t\tif (Ammo) {\n\t\t\t\t\t\tStatus = Rule.IsCurleyShuffle ? PICK_ATTACK_LOCATION : FIRE_AT_TARGET;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif (!Ammo) {\n\t\t\t\t\t\tStatus = RETURN_TO_BASE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!In_Range(TarCom)) {\n\t\t\t\t\t\t\tStatus = PICK_ATTACK_LOCATION;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = Rule.IsCurleyShuffle ? PICK_ATTACK_LOCATION : FIRE_AT_TARGET;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tFly back to landing spot.\n\t\t*/\n\t\tcase RETURN_TO_BASE:\n\t\t\t/*\n\t\t\t**\tBreak off of firing at the target if there is no more\n\t\t\t**\tpoint in attacking it this mission. The player will\n\t\t\t**\treassign a target for the next mission.\n\t\t\t*/\n\t\t\tif (!Ammo && (IsALoaner || House->IsHuman)) {\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t}\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\tEnter_Idle_Mode();\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::New_LZ -- Find a good landing zone.                                          *\n *                                                                                             *\n *    Use this routine to locate a good landing zone that is nearby the location specified.    *\n *    By using this routine it is possible to assign the same landing zone to several          *\n *    aircraft and they will land nearby without conflict.                                     *\n *                                                                                             *\n * INPUT:   oldlz -- Target value of desired landing zone (usually a cell target value).       *\n *                                                                                             *\n * OUTPUT:  Returns with the new good landing zone. It might be the same value passed in.      *\n *                                                                                             *\n * WARNINGS:   The landing zone might be a goodly distance away from the ideal if there is     *\n *             extensive blocking terrain in the vicinity.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET AircraftClass::New_LZ(TARGET oldlz) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Target_Legal(oldlz) && (!Is_LZ_Clear(oldlz) || !Cell_Seems_Ok(As_Cell(oldlz)))) {\n\t\tCOORDINATE coord = As_Coord(oldlz);\n\n\t\t/*\n\t\t**\tScan outward in a series of concentric rings up to certain distance\n\t\t**\tin cells.\n\t\t*/\n\t\tfor (int radius = 0; radius < Rule.LZScanRadius / CELL_LEPTON_W; radius++) {\n\t\t\tFacingType modifier = Random_Pick(FACING_N, FACING_NW);\n\t\t\tCELL lastcell = -1;\n\n\t\t\t/*\n\t\t\t**\tPerform a radius scan out from the original center location. Try to\n\t\t\t**\tfind a cell that is allowed to be a legal LZ.\n\t\t\t*/\n\t\t\tfor (FacingType facing = FACING_N; facing < FACING_COUNT; facing++) {\n\t\t\t\tCELL newcell = Coord_Cell(Coord_Move(coord, Facing_Dir(facing+modifier), radius * ICON_LEPTON_W));\n\t\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\t\tTARGET newtarget = ::As_Target(newcell);\n\n\t\t\t\t\tif (newcell != lastcell && Is_LZ_Clear(newtarget) && Cell_Seems_Ok(newcell)) {\n\t\t\t\t\t\treturn(newtarget);\n\t\t\t\t\t}\n\t\t\t\t\tlastcell = newcell;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(oldlz);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Receive_Message -- Handles receipt of radio messages.                        *\n *                                                                                             *\n *    This routine receives all radio messages directed at this aircraft. It is used to handle *\n *    all inter-object coordination. Typically, this would be for transport helicopters and    *\n *    other complex landing operations required of helicopters.                                *\n *                                                                                             *\n * INPUT:   from     -- The source of this radio message.                                      *\n *                                                                                             *\n *          message  -- The message itself.                                                    *\n *                                                                                             *\n *          param    -- An optional parameter that may be used to transfer additional          *\n *                      data.                                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response from the aircraft.                                 *\n *                                                                                             *\n * WARNINGS:   Some radio messages are handled by the base classes.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType AircraftClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\tcase RADIO_PREPARED:\n\t\t\tif (Target_Legal(TarCom)) return(RADIO_NEGATIVE);\n\t\t\tif ((Height == 0 && Ammo == Class->MaxAmmo) || (Height > 0 && Ammo > 0)) return(RADIO_ROGER);\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tSomething disastrous has happened to the object in contact with. Fall back\n\t\t**\tand regroup. This means that any landing process is immediately aborted.\n\t\t*/\n\t\tcase RADIO_RUN_AWAY:\n\t\t\tif (IsLanding) {\n\t\t\t\tIsLanding = false;\n\t\t\t\tIsTakingOff = true;\n\t\t\t}\n\t\t\tif (Class->IsFixedWing) {\n\t\t\t\tAssign_Destination(Good_LZ());\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tScatter(0, true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe ground control requests that this specified landing spot be used.\n\t\t*/\n\t\tcase RADIO_MOVE_HERE:\n\t\t\tFootClass::Receive_Message(from, message, param);\n\t\t\tif (Is_Target_Building(param)) {\n\t\t\t\tif (Transmit_Message(RADIO_CAN_LOAD, As_Techno(param)) != RADIO_ROGER) {\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t\t}\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t} else {\n\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t}\n\t\t\tCommence();\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tGround control is requesting if the aircraft requires navigation direction.\n\t\t*/\n\t\tcase RADIO_NEED_TO_MOVE:\n\t\t\tFootClass::Receive_Message(from, message, param);\n\t\t\tif (!Target_Legal(NavCom) && !IsTakingOff && !IsLanding) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tThis message is sent by the passenger when it determines that it has\n\t\t**\tentered the transport.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n\t\t\tif (How_Many() == Class->Max_Passengers()) {\n\t\t\t\tClose_Door(5, 4);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a civilian has entered the transport, then the transport will immediately\n\t\t\t**\tfly off the map.\n\t\t\t*/\n\t\t\tif (_Counts_As_Civ_Evac(from)) {\n\t\t\t\tAssign_Mission(MISSION_RETREAT);\n\t\t\t}\n\t\t\treturn(RADIO_ATTACH);\n\n\t\t/*\n\t\t**\tDocking maintenance message received. Check to see if new orders should be given\n\t\t**\tto the impatient unit.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\t\t\tif (Class->Max_Passengers() > 0 && How_Many() < Class->Max_Passengers()) {\n\t\t\t\tFootClass::Receive_Message(from, message, param);\n\n\t\t\t\tif (!IsTethered && !IsLanding && !IsTakingOff && Height == 0) {\n\n\t\t\t\t\tOpen_Door(5, 4);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the potential passenger needs someplace to go, then figure out a good\n\t\t\t\t\t**\tspot and tell it to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE, from) == RADIO_ROGER) {\n\t\t\t\t\t\tCELL cell;\n\t\t\t\t\t\t/*DirType dir =*/ Desired_Load_Dir(from, cell);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf no adjacent free cells are detected, then passenger loading\n\t\t\t\t\t\t**\tcannot occur. Break radio contact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell == 0) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tparam = (long)::As_Target(cell);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the potential passenger where it should go. If the passenger is\n\t\t\t\t\t\t\t**\talready at the staging location, then tell it to move onto the transport\n\t\t\t\t\t\t\t**\tdirectly.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) == RADIO_YEA_NOW_WHAT) {\n\t\t\t\t\t\t\t\tparam = (long)As_Target();\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT, from);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tContact_With_Whom()->Unselect();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAsks if the passenger can load on this transport.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tif (Class->Max_Passengers() == 0 || from == NULL || !House->Is_Ally(from->Owner()) || Height > 0) return(RADIO_STATIC);\n\t\t\tif (/*!In_Radio_Contact() &&*/ How_Many() < Class->Max_Passengers()) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tLet the base class take over processing this message.\n\t*/\n\treturn(FootClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Desired_Load_Dir -- Determines where passengers should line up.              *\n *                                                                                             *\n *    This routine is used by the transport helicopter to determine the location where the     *\n *    infantry passengers should line up before loading.                                       *\n *                                                                                             *\n * INPUT:   object   -- The object that is trying to load up on this transport.                *\n *                                                                                             *\n *                   -- Reference to the cell that the passengers should move to before the    *\n *                      actual load process may begin.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the direction that the helicopter should face for the load operation. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   07/30/1995 JLB : Revamped to scan all adjacent cells.                                     *\n *=============================================================================================*/\nDirType AircraftClass::Desired_Load_Dir(ObjectClass * object, CELL & moveto) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL center = Coord_Cell(Center_Coord());\n\tfor (int sweep = FACING_N; sweep < FACING_S; sweep++) {\n\t\tmoveto = Adjacent_Cell(center, FacingType(FACING_S+sweep));\n\t\tif (Map.In_Radar(moveto) && (Coord_Cell(object->Center_Coord()) == moveto || Map[moveto].Is_Clear_To_Move(SPEED_FOOT, false, false))) return(DIR_N);\n\n\t\tmoveto = Adjacent_Cell(center, FacingType(FACING_S-sweep));\n\t\tif (Map.In_Radar(moveto) && (Coord_Cell(object->Center_Coord()) == moveto || Map[moveto].Is_Clear_To_Move(SPEED_FOOT, false, false))) return(DIR_N);\n\t}\n\treturn(DIR_N);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Take_Off -- State machine support for taking off.                    *\n *                                                                                             *\n *    This routine is used by the main game state machine processor. This utility routine      *\n *    handles a helicopter as it transitions from landed to flying state.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the helicopter reached flight level now?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Process_Take_Off(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tIsLanding = false;\n\tIsTakingOff = true;\n\n\tif (Class->IsFixedWing)  {\n\t\tSet_Speed(0xFF);\n\t\tif (Height == FLIGHT_LEVEL)  {\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tClose_Door(5, 4);\n\t\t\t\tPrimaryFacing = SecondaryFacing;\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL/2:\n\t\t\t\tPrimaryFacing.Set_Desired(Direction(NavCom));\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL-(FLIGHT_LEVEL/3):\n\t\t\t\tSecondaryFacing.Set_Desired(PrimaryFacing.Desired());\n\t\t\t\tSet_Speed(0x20);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL-(FLIGHT_LEVEL/5):\n\t\t\t\tSet_Speed(0x40);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL:\n\t\t\t\tSet_Speed(0xFF);\n\t\t\t\tIsTakingOff = false;\n\t\t\t\treturn(true);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Process_Landing -- Landing process state machine handler.                    *\n *                                                                                             *\n *    This is a support routine that is called by the main state machine routines. This        *\n *    routine is responsible for handling the helicopter as it transitions from flight to      *\n *    landing.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the helicopter completely landed now?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   03/04/1996 JLB : Handles fixed wing aircraft.                                             *\n *=============================================================================================*/\nbool AircraftClass::Process_Landing(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tIsTakingOff = false;\n\tIsLanding = true;\n\n\tif (Class->IsFixedWing)  {\n\t\tint distance = Distance(NavCom);\n\n\t\tif (distance > 0x0100)  {\n\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t}\n\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tSet_Speed(0);\n\t\t\t\tIsLanding = false;\n\t\t\t\treturn(true);\n\n\t\t\tdefault:\n//\t\t\t\tif (distance*2 > Class->LandingSpeed) {\n//\t\t\t\t\tSet_Speed(Class->LandingSpeed);\n//\t\t\t\t} else {\n//\t\t\t\t\tSet_Speed(distance/2);\n//\t\t\t\t}\n\n\t\t\t\tSet_Speed(Class->LandingSpeed / House->AirspeedBias);\n\t\t\t\tbreak;\n\t\t}\n\n\t} else {\n\t\tswitch (Height) {\n\t\t\tcase 0:\n\t\t\t\tIsLanding = false;\n\t\t\t\treturn(true);\n\n\t\t\tcase FLIGHT_LEVEL/2:\n\t\t\t\tSet_Speed(0);\n\t\t\t\tbreak;\n\n\t\t\tcase FLIGHT_LEVEL:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Can_Enter_Cell -- Determines if the aircraft can land at this location.      *\n *                                                                                             *\n *    This routine is used when the passability of a cell needs to be determined. This is      *\n *    necessary when scanning for a location that the aircraft can land.                       *\n *                                                                                             *\n * INPUT:   cell  -- The cell location to check for landing.                                   *\n *                                                                                             *\n * OUTPUT:  Returns a value indicating if the cell is a legal landing spot or not.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType AircraftClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!Map.In_Radar(cell)) return(MOVE_NO);\n\n\tCellClass * cellptr = &Map[cell];\n\n\tObjectClass const * occupier = cellptr->Cell_Occupier();\n\n\tif (occupier == NULL ||\n\t\t!occupier->Is_Techno() ||\n\t\t((TechnoClass *)occupier)->House->Is_Ally(House) ||\n\t\t(!((TechnoClass *)occupier)->Is_Cloaked(this) &&\n\t\t\t(ScenarioInit == 0 && (occupier->What_Am_I() != RTTI_BUILDING || !((BuildingClass*)occupier)->Class->IsInvisible)) )\n\t\t) {\n\n\t\tif (!cellptr->Is_Clear_To_Move(SPEED_TRACK, false, false)) return(MOVE_NO);\n\t}\n\n\tif (Session.Type == GAME_NORMAL && IsOwnedByPlayer && !cellptr->IsMapped) {\n\t\treturn(MOVE_NO);\n\t}\n\n\treturn(MOVE_OK);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Good_Fire_Location -- Searches for and finds a good spot to fire from.       *\n *                                                                                             *\n *    Given the specified target, this routine will locate a good spot for the aircraft to     *\n *    fire at the target.                                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target that is desired to be attacked.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the target location of the place that firing should be made from.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   06/14/1995 JLB : Finer resolution on ring scan.                                           *\n *   11/02/1996 JLB : Bias fire position to get closer to moving objects.                      *\n *=============================================================================================*/\nTARGET AircraftClass::Good_Fire_Location(TARGET target) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Target_Legal(target)) {\n\t\tint range = Weapon_Range(0);\n\t\tCOORDINATE tcoord = As_Coord(target);\n\t\tCELL bestcell = 0;\n\t\tCELL best2cell = 0;\n\t\tint bestval = -1;\n\t\tint best2val = -1;\n\n\t\t/*\n\t\t**\tTry to get closer to a target that is moving.\n\t\t*/\n\t\tCOORDINATE altcoord = 0;\n\t\tif (Is_Target_Object(target) && As_Object(target)->Is_Foot()) {\n\t\t\tTARGET alttarg = ((FootClass *)As_Object(target))->NavCom;\n\t\t\tif (Target_Legal(alttarg)) {\n\t\t\t\taltcoord = As_Coord(alttarg);\n\t\t\t}\n\t\t}\n\n\t\tfor (int r = range-0x0100; r > 0x0100; r -= 0x0100) {\n\t\t\tfor (int face = 0; face < 255; face += 16) {\n\t\t\t\tCOORDINATE newcoord = Coord_Move(tcoord, (DirType)face, r);\n\t\t\t\tCELL newcell = Coord_Cell(newcoord);\n\t\t\t\tCELL actualcell = Coord_Cell(Coord_Sub(newcoord, XY_Coord(0, FLIGHT_LEVEL)));\n\n\t\t\t\t//using function for IsVisible so we have different results for different players - JAS 2019/09/30\n\t\t\t\tif (Map.In_Radar(actualcell) && (Session.Type != GAME_NORMAL || Map[newcell].Is_Visible(PlayerPtr)) && Cell_Seems_Ok(newcell, true)) {\n\t\t\t\t\tint dist;\n\t\t\t\t\tif (altcoord != 0) {\n\t\t\t\t\t\tdist = ::Distance(newcoord, altcoord);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdist = Distance(newcoord);\n\t\t\t\t\t}\n\t\t\t\t\tif (bestval == -1 || dist < bestval) {\n\t\t\t\t\t\tbest2val = bestval;\n\t\t\t\t\t\tbest2cell = bestcell;\n\t\t\t\t\t\tbestval = dist;\n\t\t\t\t\t\tbestcell = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bestval != -1) break;\n\t\t}\n\n\t\tif (best2val == -1) {\n\t\t\tbest2cell = bestcell;\n\t\t}\n\n\t\t/*\n\t\t**\tIf it found a good firing location, then return this location as\n\t\t**\ta target value.\n\t\t*/\n\t\tif (bestval != -1) {\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(::As_Target(bestcell));\n\t\t\t} else {\n\t\t\t\treturn(::As_Target(best2cell));\n\t\t\t}\n\t\t}\n\t}\n\treturn(TARGET_NONE);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Cell_Seems_Ok -- Checks to see if a cell is good to enter.                   *\n *                                                                                             *\n *    This routine examines the navigation computers of other aircraft in order to see if the  *\n *    specified cell is safe to fly to. The intent of this routine is to avoid unnecessary     *\n *    mid-air collisions.                                                                      *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine for clear airspace.                                *\n *                                                                                             *\n *          strict   -- Should the scan consider the aircraft, that is making this check, a    *\n *                      blocking aircraft. Typically, the aircraft itself is not considered    *\n *                      a blockage -- an aircraft can always exist where it is currently       *\n *                      located. A strict check is useful for helicopters that need to move    *\n *                      around at the slightest provocation.                                   *\n *                                                                                             *\n * OUTPUT:  Is the specified cell free from airspace conflicts?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Cell_Seems_Ok(CELL cell, bool strict) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tMake sure that no other aircraft are heading to the selected location. If they\n\t**\tare, then don't consider the location as valid.\n\t*/\n\tTARGET astarget = ::As_Target(cell);\n\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * air = Aircraft.Ptr(index);\n\t\tif (air && (strict || air != this) && !air->IsInLimbo) {\n\t\t\tif (Coord_Cell(air->Coord) == cell || air->NavCom == astarget) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Pip_Count -- Returns the number of \"objects\" in aircraft.                    *\n *                                                                                             *\n *    This routine is used by the render logic to draw the little container \"pips\". This       *\n *    corresponds to the number of passengers for a transport helicopter or the number of      *\n *    shots remaining for an attack helicopter.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of \"pips\" to render on the aircraft.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/11/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Pip_Count(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tint retval = 0;\n\n\tbool carrying_passengers = (Class->Max_Passengers() > 0) && ((*this != AIRCRAFT_BADGER) || (Mission != MISSION_HUNT));\n\tif (carrying_passengers) {\n\t\tretval = How_Many();\n\t} else {\n\t\tif (Ammo) {\n\t\t\tretval = Class->Max_Pips() * fixed(Ammo, Class->MaxAmmo);\n\t\t\tif (!retval) retval = 1;\n\t\t}\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Enter -- Control aircraft to fly to the helipad or repair center.    *\n *                                                                                             *\n *    This routine is used when the aircraft needs to fly for either rearming or repairing.    *\n *    It tries to establish contact with the support building. Once contact is established     *\n *    the ground controller takes care of commanding the aircraft.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before this routine should be called again.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Ground controller gives orders.                                          *\n *=============================================================================================*/\nint AircraftClass::Mission_Enter(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\n\t\tTAKEOFF,\n\t\tALTITUDE,\n\t\tSTACK,\n\t\tDOWNWIND,\n\t\tCROSSWIND,\n\t\tTRAVEL,\n\t\tLANDING\n\t};\n\n\t/*\n\t**\tVerify that it has a valid NavCom. If it doesn't then request one from the\n\t**\tbuilding this building is trying to land upon. If that fails, then enter\n\t**\tidle mode.\n\t*/\n\tif (!Target_Legal(NavCom) && In_Which_Layer() != LAYER_GROUND) {\n\t\tif (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {\n\t\t\tEnter_Idle_Mode();\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tif (Height < FLIGHT_LEVEL || IsLanding) {\n\t\t\t\tStatus = TAKEOFF;\n\t\t\t} else {\n\t\t\t\tStatus = ALTITUDE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TAKEOFF:\n\t\t\tif (Process_Take_Off()) {\n\t\t\t\t/*\n\t\t\t\t**\tAfter takeoff is complete, break radio contact with any helipad that this\n\t\t\t\t**\thelicopter is taking off from.\n\t\t\t\t*/\n\t\t\t\tif (In_Radio_Contact() && Map[Coord].Cell_Building() == Contact_With_Whom()) {\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\tStatus = ALTITUDE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ALTITUDE:\n\t\t\t/*\n\t\t\t**\tEstablish radio contact with the building this helicopter is trying\n\t\t\t**\tto land at.\n\t\t\t*/\n\t\t\tif (In_Radio_Contact()) {\n\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\tTransmit_Message(RADIO_DOCKING);\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tStatus = STACK;\n\t\t\t} else {\n\t\t\t\tTechnoClass * tech = As_Techno(NavCom);\n\t\t\t\tif (tech && Transmit_Message(RADIO_CAN_LOAD, tech) == RADIO_ROGER) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, tech);\n\t\t\t\t\tTransmit_Message(RADIO_DOCKING);\n\t\t\t\t\tStatus = STACK;\n\t\t\t\t} else {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (tech->What_Am_I() != RTTI_VESSEL) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n#else\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tEnter_Idle_Mode();\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase STACK:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_STACK));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = DOWNWIND;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = DOWNWIND;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase DOWNWIND:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tSet_Speed(200);\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_DOWNWIND));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = CROSSWIND;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = CROSSWIND;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CROSSWIND:\n\t\t\tif (Class->IsFixedWing)  {\n\t\t\t\tint distance;\n\t\t\t\tTARGET togo;\n\n\t\t\t\tSet_Speed(140);\n\t\t\t\tBuildingClass const * building = As_Building(NavCom);\n\t\t\t\tif (building)  {\n\t\t\t\t\ttogo = ::As_Target(building->Check_Point(CHECK_CROSSWIND));\n\t\t\t\t} else {\n\t\t\t\t\ttogo = NavCom;\n\t\t\t\t}\n\n\t\t\t\tdistance = Process_Fly_To(true, togo);\n\t\t\t\tif (distance < 0x0080)  {\n\t\t\t\t\tStatus = TRAVEL;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tStatus = TRAVEL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TRAVEL:\n\t\t\tTransmit_Message(RADIO_DOCKING);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\tif (!In_Radio_Contact() && !Is_Target_Vessel(NavCom)) {\n#else\n\t\t\tif (!In_Radio_Contact()) {\n#endif\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t} else {\n\t\t\t\tint distance = Process_Fly_To(true, NavCom);\n\n\t\t\t\tif (Class->IsFixedWing)  {\n\n\t\t\t\t\tif (distance < 0x0400)  {\n\t\t\t\t\t\tStatus = LANDING;\n\t\t\t\t\t}\n\t\t\t\t\treturn(1);\n\n\t\t\t\t} else {\n\t\t\t\t\tif (distance < 0x0080) {\n\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(TarCom));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSecondaryFacing.Set_Desired(Pose_Dir());\n\t\t\t\t\t\t}\n\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n if (Is_Target_Vessel(NavCom) && !In_Radio_Contact()) {\n \tEnter_Idle_Mode();\n \tbreak;\n }\n#endif\n\t\t\t\t\t\tif (distance < 0x0010) {\n\t\t\t\t\t\t\tStatus = LANDING;\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif(Is_Target_Vessel(NavCom) && As_Vessel(NavCom)->NavCom) {\n\t\tStatus = TRAVEL;\n\t}\n#endif\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSecondaryFacing.Set_Desired(Direction(NavCom));\n//\t\t\t\t\t\tSecondaryFacing.Set_Desired(::Direction(Fire_Coord(0), As_Coord(NavCom)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(3);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase LANDING:\n\t\t\tif (IsTakingOff && !Class->IsFixedWing) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n// If we were trying to land on a carrier and it moved, take off again\n\tif ( As_Vessel(NavCom) && !In_Radio_Contact()) {\n\t\tStatus = INITIAL;\n\t\tbreak;\n\t}\n#endif\n\t\t\tif (Process_Landing()) {\n\t\t\t\tswitch (Transmit_Message(RADIO_IM_IN)) {\n\t\t\t\t\tcase RADIO_ROGER:\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RADIO_ATTACH:\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif(Contact_With_Whom()->What_Am_I() != RTTI_VESSEL) Limbo();\n#else\n\t\t\t\t\t\tLimbo();\n#endif\n\t\t\t\t\t\tContact_With_Whom()->Attach(this);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Good_LZ -- Locates a good spot to land.                                      *\n *                                                                                             *\n *    This routine is used when helicopters need a place to land, but there are no obvious     *\n *    spots (i.e., helipad) available. It will try to land near a friendly helipad or friendly *\n *    building if there are no helipads anywhere. In the event that there are no friendly      *\n *    buildings anywhere on the map, then just land right where it is flying.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the target location where this aircraft should land. This value may   *\n *          not be a clear cell, but the normal landing logic will resolve that problem.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET AircraftClass::Good_LZ(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tScan through all of the buildings and try to land near\n\t**\tthe helipad (if there is one) or the nearest friendly building.\n\t*/\n\tCELL bestcell = 0;\n\tint bestdist = -1;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\tif (building && !building->IsInLimbo && building->House == House) {\n\t\t\tint dist = Distance(building);\n\t\t\tif (*building == Class->Building) {\n\t\t\t\tdist /= 4;\n\t\t\t}\n\t\t\tif (bestdist == -1 || dist < bestdist) {\n\t\t\t\tbestdist = dist;\n\t\t\t\tbestcell = Coord_Cell(building->Center_Coord());\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the suitable location if one was found.\n\t*/\n\tif (bestdist != -1) {\n\t\treturn(::As_Target(bestcell));\n\t}\n\n\t/*\n\t**\tNo good location was found. Just try to land here.\n\t*/\n\treturn(::As_Target(Coord_Cell(Coord)));\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Set_Speed -- Sets the speed for the aircraft.                                *\n *                                                                                             *\n *    This routine will set the speed for the aircraft. The speed is specified as a fraction   *\n *    of full speed.                                                                           *\n *                                                                                             *\n * INPUT:   speed -- The fixed point fractional speed setting. 0x00 is stopped, 0xFF is full   *\n *                   speed.                                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Set_Speed(int speed)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::Set_Speed(speed);\n\n\tMPHType sp = MPHType(min(Class->MaxSpeed * SpeedBias * House->AirspeedBias, MPH_LIGHT_SPEED));\n\tFly_Speed(speed, sp);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Fire_Direction -- Determines the direction of fire.                          *\n *                                                                                             *\n *    This routine will determine what direction a projectile would take if it were fired      *\n *    from the aircraft. This is the direction that the aircraft's body is facing.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the direction of projectile fire.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType AircraftClass::Fire_Direction(void) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(SecondaryFacing.Current());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::~AircraftClass -- Destructor for aircraft object.                            *\n *                                                                                             *\n *    This is the destructor for aircraft. It will limbo the aircraft if it isn't already      *\n *    and also removes the aircraft from any team it may be attached to.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass::~AircraftClass(void)\n{\n\tif (GameActive && Class) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\n\t\t/*\n\t\t**\tIf there are any cargo members, delete them.\n\t\t*/\n\t\twhile (Is_Something_Attached()) {\n\t\t\tdelete Detach_Object();\n\t\t}\n\n\t\tAircraftClass::Limbo();\n\t\tClass = 0;\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Scatter -- Causes the aircraft to move away a bit.                           *\n *                                                                                             *\n *    This routine will cause the aircraft to move away from its current location and then     *\n *    enter some idle mode. Typically this is called when the aircraft is attacked while on    *\n *    the ground.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Scatter(COORDINATE , bool, bool )\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (!MissionControl[Mission].IsScatter) return;\n\n\t/*\n\t**\tFixed wing aircraft never scatter.\n\t*/\n\tif (Class->IsFixedWing) return;\n\n\tif (IsLanding || Height == 0) {\n\t\tIsLanding = false;\n\t\tIsTakingOff = true;\n\t}\n\tEnter_Idle_Mode();\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Guard -- Handles aircraft in guard mode.                             *\n *                                                                                             *\n *    Aircraft don't like to be in guard mode if in flight. If this situation is detected,     *\n *    then figure out what the aircraft should be doing and go do it.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   This routine typically calls the normal guard logic for ground units.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *   10/10/1995 JLB : Hunts for harvesters that are unescorted.                                *\n *=============================================================================================*/\nint AircraftClass::Mission_Guard(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Height == FLIGHT_LEVEL) {\n\n\t\t/*\n\t\t**\tIf part of a team, then do nothing, since the team\n\t\t**\thandler will take care of giving this aircraft a\n\t\t**\tmission.\n\t\t*/\n\t\tif (Team) {\n\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t}\n\t\t\treturn(MissionControl[Mission].Normal_Delay());\n\t\t}\n\n\t\tif (Class->PrimaryWeapon == NULL) {\n\t\t\tAssign_Destination(::As_Target(Coord_Cell(Coord)));\n\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t} else {\n\t\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\t}\n\t\treturn(1);\n\t}\n\tif (House->IsHuman) return(MissionControl[Mission].Normal_Delay());\n\n\t/*\n\t**\tIf the aircraft is very badly damaged, then it will search for a\n\t**\trepair bay first.\n\t*/\n\tif (House->Available_Money() >= 100 && Health_Ratio() <= Rule.ConditionYellow) {\n\t\tif (!In_Radio_Contact() ||\n\t\t\t(Height == 0 &&\n\t\t\t\t(Contact_With_Whom()->What_Am_I() != RTTI_BUILDING || *((BuildingClass *)Contact_With_Whom()) != STRUCT_REPAIR))) {\n\n\n\t\t\tBuildingClass * building = Find_Docking_Bay(STRUCT_REPAIR, true);\n\t\t\tif (building != NULL) {\n\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the aircraft cannot attack anything because of lack of ammo,\n\t**\tabort any normal guard logic in order to look for a helipad\n\t**\tto rearm.\n\t*/\n\tif (Ammo == 0 && Is_Weapon_Equipped()) {\n\t\tif (!In_Radio_Contact()) {\n\t\t\tBuildingClass * building = Find_Docking_Bay(STRUCT_HELIPAD, false);\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tif (!Class->IsFixedWing) {\n\t\tint dist = 0x7FFFFFFF;\n\t\tif (building) dist=Distance(building);\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass *ship = Vessels.Ptr(index);\n\t\t\tif (ship != NULL && *ship == VESSEL_CARRIER && !ship->IsInLimbo && ship->IsActive && ship->House == House && ship->How_Many() < ship->Class->Max_Passengers()) {\n\t\t\t\tif (Distance(ship) < dist || !building) {\n\t\t\t\t\tbuilding = (BuildingClass *)ship;\n\t\t\t\t\tdist = Distance(ship);\n\t\t\t\t}\n//\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\t\tif (building != NULL) {\n\t\t\t\tAssign_Destination(building->As_Target());\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the aircraft already has a target, then attack it if possible.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tAssign_Mission(MISSION_ATTACK);\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tTransport helicopters don't really do anything but just sit there.\n\t*/\n\tif (!Is_Weapon_Equipped()) {\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\t/*\n\t**\tComputer controlled helicopters will defend themselves by bouncing around\n\t**\tand looking for a free helipad.\n\t*/\n\tif (Height == 0 && !In_Radio_Contact()) {\n\t\tScatter(0, true);\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\t/*\n\t**\tPerform a special check to hunt for harvesters that are outside of the protective\n\t**\tshield of their base.\n\t*/\n\tif (House->State != STATE_ATTACKED) {\n\t\tTARGET target = House->Find_Juicy_Target(Coord);\n\n\t\tif (Target_Legal(target)) {\n\t\t\tAssign_Target(target);\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t}\n\t}\n\n\treturn(FootClass::Mission_Guard());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Mission_Guard_Area -- Handles the aircraft guard area logic.                 *\n *                                                                                             *\n *    This routine handles area guard logic for aircraft. Aircraft require special handling    *\n *    for this mode since they are to guard area only if they are in a position to do so.      *\n *    Otherwise they just defend themselves.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint AircraftClass::Mission_Guard_Area(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Height == FLIGHT_LEVEL) {\n\t\tif (!Team.Is_Valid()) Enter_Idle_Mode();\n\t\treturn(1);\n\t}\n\tif (House->IsHuman) return(TICKS_PER_SECOND);\n\n\tif (Height == 0 && !In_Radio_Contact()) {\n\t\tScatter(0, true);\n\t\treturn(TICKS_PER_SECOND*3);\n\t}\n\n\tif (Target_Legal(TarCom)) {\n\t\tAssign_Mission(MISSION_ATTACK);\n\t\treturn(1);\n\t}\n\treturn(FootClass::Mission_Guard_Area());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Attack -- Gives audio response to attack order.                     *\n *                                                                                             *\n *    This routine is used to give an audio response to an attack order.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Attack(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_AFFIRM,\n\t\tVOC_ACKNOWL\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Move -- Gives audio response to move request.                       *\n *                                                                                             *\n *    This routine is used to give an audio response to movement orders.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Move(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_ACKNOWL,\n\t\tVOC_AFFIRM\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Response_Select -- Gives audio response when selected.                       *\n *                                                                                             *\n *    This routine is called when an audio response for selection is desired.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Response_Select(void)\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_VEHIC,\n\t\tVOC_REPORT,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_AWAIT\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Can_Fire -- Checks to see if the aircraft can fire.                          *\n *                                                                                             *\n *    This routine is used to determine if the aircraft can fire its weapon at the target      *\n *    specified. If it cannot, then the reason why is returned.                                *\n *                                                                                             *\n * INPUT:   target   -- The target that the aircraft might fire upon.                          *\n *                                                                                             *\n *          which    -- The weapon that will be used to fire.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the reason why it can't fire or with FIRE_OK.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *   07/11/1996 JLB : Fixed for camera carrying aircraft.                                      *\n *=============================================================================================*/\nFireErrorType AircraftClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Aircraft.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Passenger && !Is_Something_Attached()) {\n\t\treturn(FIRE_AMMO);\n\t}\n\n\tbool camera = (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsCamera);\n\tbool fudge = (Passenger || (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->Bullet != NULL && Class->PrimaryWeapon->Bullet->IsParachuted));\n\n\tif (fudge && !camera && !Ammo && !Passenger) {\n\t\treturn(FIRE_AMMO);\n\t}\n\n\t/*\n\t**\tPassenger aircraft that wish to 'fire' actually are requesting to\n\t**\tparadrop or 'throw out' the cargo. This is always allowed if the terrain under the\n\t**\taircraft is generally clear.\n\t*/\n\tif (camera || (fudge && Passenger && Is_Something_Attached()))  {\n\t\tif (Arm != 0) return(FIRE_REARM);\n\n\t\tif (Distance(target) < (camera ? 0x0380 : 0x0200) && Map.In_Radar(Coord_Cell(Center_Coord()))) {\n//\t\tif (Distance(target) < (camera ? 0x0380 : 0x0280) && Map.In_Radar(Coord_Cell(Center_Coord()))) {\n\t\t\treturn(FIRE_OK);\n\t\t}\n\t\treturn(FIRE_RANGE);\n\t}\n\n\tFireErrorType canfire = FootClass::Can_Fire(target, which);\n\n\tif (canfire == FIRE_OK) {\n\n\t\t/*\n\t\t**\tDouble check to make sure that the facing is roughly toward\n\t\t**\tthe target. If the difference is too great, then firing is\n\t\t**\ttemporarily postponed.\n\t\t*/\n\t\tif (Class->IsFixedWing) {\n\n\t\t\tint diff = PrimaryFacing.Difference(Direction(TarCom));\n\t\t\tif (ABS(diff) > (fudge ? 16 : 8)) {\n\t\t\t\treturn(FIRE_FACING);\n\t\t\t}\n\t\t}\n\t}\n\treturn(canfire);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Landing_Takeoff_AI -- Handle aircraft take off and landing processing.       *\n *                                                                                             *\n *    This routine handles the tricky maneuver of taking off and landing. The process of       *\n *    landing is not entirely safe and thus the aircraft may be destroyed as a consequence.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft destroyed by this process?                                  *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop. Be sure to        *\n *             examine the return value and if true, abort all further processing of this      *\n *             aircraft since it is now dead.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Landing_Takeoff_AI(void)\n{\n\t/*\n\t**\tHandle landing and taking off logic. Helicopters are prime users of this technique. The\n\t**\taircraft will either gain or lose altitude as appropriate. As the aircraft transitions\n\t**\tbetween flying level and ground level, it will be moved into the appropriate render\n\t**\tlayer.\n\t*/\n\tif (Is_Door_Closed() && (IsLanding || IsTakingOff)) {\n\t\tLayerType layer = In_Which_Layer();\n\n\t\tif (IsLanding) {\n\t\t\tMark(MARK_UP);\n\t\t\tif (Height) Height -= Pixel_To_Lepton(1);\n\t\t\tif (Height <= 0) {\n\t\t\t\tHeight = 0;\n\t\t\t\tIsLanding = false;\n\t\t\t\tSet_Speed(0);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the NavCom now equals the destination, then clear out the NavCom.\n\t\t\t\t*/\n\t\t\t\tif (Coord_Cell(Center_Coord()) == As_Cell(NavCom)) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If a fixed-wing aircraft just landed on the ground, blow him up\n\t\t\t\t*/\n\t\t\t\tif (Class->IsFixedWing && Mission != MISSION_ENTER) {\n\t\t\t\t\tStrength = 1;\n\n\t\t\t\t\tint damage = Strength;\n\t\t\t\t\tMap.Remove(this, layer);\n\t\t\t\t\tTake_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\n\t\t\t\tif (Target_Legal(NavCom) && As_Techno(NavCom) == Contact_With_Whom()) {\n\t\t\t\t\tif (In_Radio_Contact() && Transmit_Message(RADIO_IM_IN) != RADIO_ROGER) {\n\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t\tif (IsTakingOff) {\n\t\t\tMark(MARK_UP);\n//\t\t\tMap.Remove(this, layer);\n\t\t\tHeight += Pixel_To_Lepton(1);\n\t\t\tif (Height >= FLIGHT_LEVEL) {\n\t\t\t\tHeight = FLIGHT_LEVEL;\n\t\t\t\tIsTakingOff = false;\n\t\t\t}\n//\t\t\tMap.Submit(this, In_Which_Layer());\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\n\t\t/*\n\t\t**\tMake adjustments for altitude by moving from one layer to another as\n\t\t**\tnecessary.\n\t\t*/\n\t\tif (layer != In_Which_Layer()) {\n\n\t\t\t/*\n\t\t\t**\tWhen the aircraft is about to enter the ground layer, perform on last\n\t\t\t**\tcheck to see if it is legal to enter that location. If not, then\n\t\t\t**\tstart the take off process. Let the normal logic handle this\n\t\t\t**\tchange of plans.\n\t\t\t*/\n\t\t\tbool ok = true;\n\t\t\tif (In_Which_Layer() == LAYER_GROUND && !IsTakingOff && !Class->IsFixedWing) {\n\t\t\t\tif (!Is_LZ_Clear(::As_Target(Coord_Cell(Coord)))) {\n\t\t\t\t\tIsTakingOff = true;\n\t\t\t\t\tMark(MARK_UP);\n\t\t\t\t\tHeight += Pixel_To_Lepton(1);\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t\tok = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (ok) {\n\n\t\t\t\tMap.Remove(this, layer);\n\t\t\t\tMap.Submit(this, In_Which_Layer());\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen the aircraft is close to the ground, it should exist as a ground object.\n\t\t\t\t**\tThis aspect is controlled by the Place_Down and Pick_Up functions.\n\t\t\t\t*/\n\t\t\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\t\t// Clear the navcom.\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tLook();\n//\t\t\t\t\tMap.Sight_From(Coord_Cell(Coord), 1, House, false);\n\t\t\t\t} else  {\n\t\t\t\t\tTransmit_Message(RADIO_UNTETHER);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the navigation computer is not attached to the object this\n\t\t\t\t\t**\taircraft is in radio contact with, then assume that radio\n\t\t\t\t\t**\tcontact is now superfluous. Break radio contact.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Radio_Contact() && Target_Legal(NavCom) && NavCom != Contact_With_Whom()->As_Target()) {\n\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Edge_Of_World_AI -- Detect if aircraft has exited the map.                   *\n *                                                                                             *\n *    Certain aircraft will be eliminated when they leave the edge of the world presumably     *\n *    after completing their mission. An exception is for aircraft that have been newly        *\n *    created as reinforcements and have not yet completed their mission.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the aircraft deleted by this routine?                                    *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine only once per aircraft per game logic loop. If     *\n *             the return value is true, then abort any further processing of this aircraft    *\n *             since it has been eliminated.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AircraftClass::Edge_Of_World_AI(void)\n{\n\tif (!Map.In_Radar(Coord_Cell(Coord))) {\n\t\tif (Mission == MISSION_RETREAT /*|| (*this == AIRCRAFT_CARGO && !Is_Something_Attached())*/) {\n\n\t\t\t/*\n\t\t\t**\tCheck to see if there are any civilians aboard. If so, then flag the house\n\t\t\t**\tthat the civilian evacuation trigger event has been fulfilled.\n\t\t\t*/\n\t\t\twhile (Is_Something_Attached()) {\n\t\t\t\tFootClass * obj = Detach_Object();\n\n\t\t\t\t/*\n\t\t\t\t**\tFlag the owning house that civ evacuation has occurred.\n\t\t\t\t*/\n\t\t\t\tif (_Counts_As_Civ_Evac(obj)) {\n\t\t\t\t\tobj->House->IsCivEvacuated = true;\n\t\t\t\t}\n\n\t\t\t\tif (obj->Team.Is_Valid()) obj->Team->IsLeaveMap = true;\n\n#ifdef OLD\n\t\t\t\t/*\n\t\t\t\t**\tTransport planes that leave can only be because they carry purchased\n\t\t\t\t**\tequipment and must be have their cost refunded.\n\t\t\t\t*/\n\t\t\t\tif (*this == AIRCRAFT_CARGO) {\n\t\t\t\t\tHouse->Refund_Money(obj->Class_Of().Cost_Of());\n\t\t\t\t}\n#endif\n\t\t\t\tdelete obj;\n\t\t\t}\n\t\t\tif (Team.Is_Valid()) {\n\t\t\t\tTeam->IsLeaveMap = true;\n\t\t\t}\n\t\t\tStun();\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t} else {\n\t\tIsLocked = true;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Movement_AI -- Handles aircraft physical movement logic.                     *\n *                                                                                             *\n *    This routine manages the aircraft movement across the map. If any movement occurred, the *\n *    aircraft will be flagged to be redrawn.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Movement_AI(void)\n{\n\t/*\n\t**\tIf for some strange reason, there is a valid NavCom, but this aircraft is not\n\t**\tin a movement order, then give it a movement order.\n\t*/\n\tif (Target_Legal(NavCom) && Mission == MISSION_GUARD && MissionQueue == MISSION_NONE) {\n\t\tAssign_Mission(MISSION_MOVE);\n\t}\n\n\tif (Speed != 0) {\n\t\tif (In_Which_Layer() == LAYER_GROUND)  {\n\t\t\tMark(MARK_UP);\n\t\t\tPhysics(Coord, PrimaryFacing);\n\t\t\tMark(MARK_DOWN);\n\t\t} else {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\tif (Physics(Coord, PrimaryFacing) != RESULT_NONE) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Rotation_AI -- Handle aircraft body and flight rotation.                     *\n *                                                                                             *\n *    This will process the aircraft visible body and flight model rotation operations. If     *\n *    any rotation occurred, the aircraft will be flagged to be redrawn.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per aircraft per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Rotation_AI(void)\n{\n\tif (PrimaryFacing.Is_Rotating()) {\n\t\tMark(MARK_CHANGE_REDRAW);\n\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t}\n\tif (Class->IsFixedWing) {\n\t\tSecondaryFacing = PrimaryFacing;\n\t}\n\tif (SecondaryFacing.Is_Rotating()) {\n\t\tMark(MARK_CHANGE_REDRAW);\n\t\tif (SecondaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Per_Cell_Process -- Handle the aircraft per cell process.                    *\n *                                                                                             *\n *    This is a seldom used function since its only purpose is to be called when an aircraft   *\n *    lands on the ground.                                                                     *\n *                                                                                             *\n * INPUT:   why   -- Why was this per cell process function called.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/15/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Per_Cell_Process(PCPType why)\n{\n\tBStart(BENCH_PCP);\n\tFootClass::Per_Cell_Process(why);\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Assign_Destination -- Assigns movement destination to the object.            *\n *                                                                                             *\n *    This routine is called when the object needs to have a new movement destination          *\n *    assigned.  Aircraft have their own version of this routine because a fixed-wing plane\t  *\n *    trying to land will behave poorly if given a new destinatio while it's landing.\t\t\t  *                                                                                         *\n *                                                                                             *\n * INPUT:   destination -- The destination to assign to this object.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Assign_Destination(TARGET dest)\n{\n\tassert(IsActive);\n\tif (dest == NavCom) return;\n\n\tif (Target_Legal(dest) && Class->IsFixedWing && (IsLanding || (Target_Legal(NavCom) && dest != NavCom))) {\n//\tif (Target_Legal(dest) /*&& Class->IsFixedWing*/ && (IsLanding || (Target_Legal(NavCom) && dest != NavCom))) {\n\n//\t\tif (Class->IsFixedWing || As_Cell(dest) != Coord_Cell(Center_Coord())) {\n\t\t\tProcess_Take_Off();\n\t\t\tStatus = 0;\n//\t\t}\n\t}\n\tFootClass::Assign_Destination(dest);\n}\n\n\n/***********************************************************************************************\n * AircraftClass::In_Which_Layer -- Calculates the display layer of the aircraft.              *\n *                                                                                             *\n *    This examines the aircraft to determine what display layer it should be located          *\n *    in. Fixed wing aircraft must always be in the top layer if they are flying even though   *\n *    they may be low to the ground.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that this aircraft resides in.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType AircraftClass::In_Which_Layer(void) const\n{\n\tif (Class->IsFixedWing && Height > 0) {\n\t\treturn(LAYER_TOP);\n\t}\n\treturn(FootClass::In_Which_Layer());\n}\n\n\n/***********************************************************************************************\n * AircraftClass::Look -- Aircraft will look if they are on the ground always.                 *\n *                                                                                             *\n *    Aircraft perform a look operation according to their sight range. If the aircraft is     *\n *    on the ground, then it will look a distance of one cell regardless of what its           *\n *    specified sight range is.                                                                *\n *                                                                                             *\n * INPUT:   incremental -- Is this an incremental look?                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AircraftClass::Look(bool incremental)\n{\n\tassert(IsActive);\n\tassert(!IsInLimbo);\n\n\tint sight_range = Techno_Type_Class()->SightRange;\n\tif (Height == 0) {\n\t\tsight_range = 1;\n\t}\n\n\tif (sight_range) {\n\t\tMap.Sight_From(Coord_Cell(Coord), sight_range, House, incremental);\n\t}\n}\n\nunsigned AircraftClass::Spied_By() const\n{\n\tunsigned spiedby = FootClass::Spied_By();\n\n\t/*\n\t** Aircraft inherit the spied by flags of the helipad they've landed on\n\t*/\n\tBuildingClass* building = Map[Coord].Cell_Building();\n\tif ((Height == 0) && In_Radio_Contact() && (building == Contact_With_Whom())) {\n\t\tspiedby |= building->Spied_By();\n\t}\n\n\treturn spiedby;\n}"
  },
  {
    "path": "REDALERT/AIRCRAFT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/AIRCRAFT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AIRCRAFT.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 22, 1994                                                *\n *                                                                                             *\n *                  Last Update : November 28, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef AIRCRAFT_H\n#define AIRCRAFT_H\n\n#include\t\"radio.h\"\n#include\t\"fly.h\"\n#include\t\"target.h\"\n\n\n/*\n**\tThis aircraft class is used for all flying sentient objects. This includes fixed wing\n**\taircraft as well as helicopters. It excludes bullets even though some bullets might\n**\tbe considered to be \"flying\" in a loose interpretatin of the word.\n*/\nclass AircraftClass : public FootClass, public FlyClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the class control structure for the aircraft.\n\t\t*/\n\t\tCCPtr<AircraftTypeClass> Class;\n\n\t\t//-----------------------------------------------------------------------------\n\t\tstatic void * operator new(size_t);\n\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *);\n\t\toperator AircraftType(void) const {return Class->Type;};\n\t\tAircraftClass(AircraftType classid, HousesType house);\n\t\tAircraftClass(NoInitClass const & x) : FootClass(x), FlyClass(x), Class(x), SecondaryFacing(x), SightTimer(x) {};\n\t\tvirtual ~AircraftClass(void);\n\n\t\tstatic void Init(void);\n\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Hunt(void);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\t/*\n\t\t**\tState machine support routines.\n\t\t*/\n\t\tbool Process_Take_Off(void);\n\t\tbool Process_Landing(void);\n\t\tint Process_Fly_To(bool slowdown, TARGET dest);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual DirType Turret_Facing(void) const {return(SecondaryFacing.Current());}\n\t\tint Shape_Number(void) const;\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType facing=FACING_NONE) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual ActionType What_Action(ObjectClass const * target) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual DirType Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tTARGET Good_Fire_Location(TARGET target) const;\n\t\tbool Cell_Seems_Ok(CELL cell, bool landing=false) const;\n\t\tDirType Pose_Dir(void) const;\n\t\tTARGET Good_LZ(void) const;\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\n\t\t/*\n\t\t**\tLanding zone support functionality.\n\t\t*/\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tbool Is_LZ_Clear(TARGET target) const;\n\t\tTARGET New_LZ(TARGET oldlz) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Look(bool incremental=false);\n\t\tvoid Draw_Rotors(int x, int y, WindowNumberType window) const;\n\t\tvirtual int Exit_Object(TechnoClass *);\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual void Set_Speed(int speed);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\t\tvirtual void Player_Assign_Mission(MissionType mission, TARGET target=TARGET_NONE, TARGET destination=TARGET_NONE);\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced=false);\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tbool Landing_Takeoff_AI(void);\n\t\tbool Edge_Of_World_AI(void);\n\t\tvoid Movement_AI(void);\n\t\tvoid Rotation_AI(void);\n\t\tint Paradrop_Cargo(void);\n\t\tvirtual void AI(void);\n\t\tvirtual void Enter_Idle_Mode(bool initial = false);\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic char * INI_Name(void) {return \"AIRCRAFT\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\tvirtual unsigned Spied_By() const;\n\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is the facing used for the body of the aircraft. Typically, this is the same\n\t\t**\tas the PrimaryFacing, but in the case of helicopters, it can be different.\n\t\t*/\n\t\tFacingClass SecondaryFacing;\n\n\t\t/*\n\t\t**\tIf this is a passenger carrying aircraft then this flag will be set. This is\n\t\t**\tnecessary because once the passengers are unloaded, the fact that it was a\n\t\t**\tpassenger carrier must still be known.\n\t\t*/\n\t\tbool Passenger;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tAircraft can be in either state of landing, taking off, or in steady altitude.\n\t\t**\tThese flags are used to control transition between flying and landing. It is\n\t\t**\tnecessary to handle the transition in this manner so that it occurs smoothly\n\t\t**\tduring the graphic processing section.\n\t\t*/\n\t\tunsigned IsLanding:1;\n\t\tunsigned IsTakingOff:1;\n\n\t\t/*\n\t\t**\tIt is very common for aircraft to be homing in on a target. When this flag is\n\t\t**\ttrue, the aircraft will constantly adjust its facing toward the TarCom. When the\n\t\t**\ttarget is very close (one cell away or less), then this flag is automatically cleared.\n\t\t**\tThis is because the homing algorithm is designed to get the aircraft to the destination\n\t\t**\tbut no more. Checking when this flag is cleared is a way of flagging transition into\n\t\t**\ta new mode. Example: Transport helicopters go into a hovering into correct position\n\t\t**\tmode when the target is reached.\n\t\t*/\n\t\tunsigned IsHoming:1;\n\n\t\t/*\n\t\t**\tHelicopters that are about to land must hover into a position exactly above the landing\n\t\t**\tzone. When this flag is true, the aircraft will be adjusted so that it is exactly over\n\t\t**\tthe TarCom. The facing of the aircraft is not altered by this movement. The affect\n\t\t**\tlike the helicopter is hovering and shifting sideways to position over the landing\n\t\t**\tzone. When the position is over the landing zone, then this flag is set to false.\n\t\t*/\n\t\tunsigned IsHovering:1;\n\n\t\t/*\n\t\t**\tThis is the jitter tracker to be used when the aircraft is a helicopter and\n\t\t**\tis flying. It is most noticeable when the helicopter is hovering.\n\t\t*/\n\t\tunsigned char Jitter;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis timer controls when the aircraft will reveal the terrain around itself.\n\t\t**\tWhen this timer expires and this aircraft has a sight range, then the\n\t\t**\tlook around process will occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> SightTimer;\n\n\t\t/*\n\t\t**\tMost attack aircraft can make several attack runs. This value contains the\n\t\t**\tnumber of attack runs the aircraft has left. When this value reaches\n\t\t**\tzero then the aircraft is technically out of ammo.\n\t\t*/\n\t\tchar AttacksRemaining;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[32];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/ANIM.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ANIM.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Dune                                                         *\n *                                                                                             *\n *                    File Name : ANIM.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 3, 1991                                                 *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   AnimClass::AI -- This is the low level anim processor.                                    *\n *   AnimClass::AnimClass -- The constructor for animation objects.                            *\n *   AnimClass::Attach_To -- Attaches animation to object specified.                           *\n *   AnimClass::Sort_Above -- Sorts the animation above the target specified.                  *\n *   AnimClass::Center_Coord -- Determine center of animation.                                 *\n *   AnimClass::Detach -- Remove animation if attached to target.                              *\n *   AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.      *\n *   AnimClass::Draw_It -- Draws the animation at the location specified.                      *\n *   AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.          *\n *   AnimClass::Init -- Performs pre-scenario initialization.                                  *\n *   AnimClass::Mark -- Signals to map that redrawing is necessary.                            *\n *   AnimClass::Middle -- Processes any middle events.                                         *\n *   AnimClass::Occupy_List -- Determines the occupy list for the animation.                   *\n *   AnimClass::Overlap_List -- Determines the overlap list for the animation.                 *\n *   AnimClass::Render -- Draws an animation object.                                           *\n *   AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.               *\n *   AnimClass::Start -- Processes initial animation side effects.                             *\n *   AnimClass::delete -- Returns an anim object back to the free pool.                        *\n *   AnimClass::new -- Allocates an anim object from the pool.                                 *\n *   AnimClass::~AnimClass -- Destructor for anim objects.                                     *\n *   Anim_From_Name -- Given a name, this finds the corresponding anim type.                   *\n *   Shorten_Attached_Anims -- Reduces attached animation durations.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#define   VIC   1\n\n/***********************************************************************************************\n * Anim_From_Name -- Given a name, this finds the corresponding anim type.                     *\n *                                                                                             *\n *    This routine will convert the supplied ASCII name into the animation type that it        *\n *    represents.                                                                              *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name to convert.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the animation type that matches the name specified. If no match could *\n *          be found, then ANIM_NONE is returned.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType Anim_From_Name(char const * name)\n{\n  #ifdef VIC\n\tif (name == NULL) return(ANIM_NONE);\n\n\tfor (int anim = ANIM_FIRST; anim < ANIM_COUNT; anim++) {\n\t\tif (stricmp(AnimTypeClass::As_Reference((AnimType)anim).IniName, name) == 0) {\n\t\t\treturn((AnimType)anim);\n\t\t}\n\t}\n#endif\n\treturn(ANIM_NONE);\n}\n\n\n/***********************************************************************************************\n * Shorten_Attached_Anims -- Reduces attached animation durations.                             *\n *                                                                                             *\n *    This routine is used to reduce the amount of time any attached animations will process.  *\n *    Typical use of this is when an object is on fire and the object should now be destroyed  *\n *    but the attached animations are to run until completion before destruction can follow.   *\n *    This routine will make the animation appear to run its course, but in as short of time   *\n *    as possible. The shortening effect is achieved by reducing the number of times the       *\n *    animation will loop.                                                                     *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object that all attached animations will be processed.     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Shorten_Attached_Anims(ObjectClass * obj)\n{\n\tif (obj != NULL) {\n\t\tfor (int index = 0; index < Anims.Count(); index++) {\n\t\t\tAnimClass & anim = * Anims.Ptr(index);\n\n\t\t\tif (As_Object(anim.xObject) == obj) {\n\t\t\t\tanim.Loops = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Sort_Y -- Returns with the sorting coordinate for the animation.                 *\n *                                                                                             *\n *    This routine is used by the sorting system. Animations that are located in the ground    *\n *    layer will be sorted by this the value returned from this function.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the sort coordinate to use for this animation.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/15/1994 JLB : Handles flat anims (infantry decay anims).                               *\n *=============================================================================================*/\nCOORDINATE AnimClass::Sort_Y(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(As_Object(xObject)->Sort_Y(), 0x00010000L));\n\t}\n\tif (Target_Legal(SortTarget)) {\n\t\tObjectClass * obj = As_Object(SortTarget);\n\t\tif (obj && obj->IsActive) {\n\t\t\treturn(Coord_Add(obj->Sort_Y(), 0x00010000L));\n\t\t}\n\t}\n\tif (*this == ANIM_MOVE_FLASH) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, -24)));\n\t}\n\tif (Class->IsGroundLayer || *this == ANIM_LZ_SMOKE) {\n\t\treturn(Coord_Add(Center_Coord(), XYP_COORD(0, 14)));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Center_Coord -- Determine center of animation.                                   *\n *                                                                                             *\n *    This support function will return the \"center\" of the animation. The actual coordinate   *\n *    of the animation may be dependant on if the the animation is attached to an object.      *\n *    In such a case, it must factor in the object's location.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate of the center of the animation. The coordinate is in real   *\n *          game coordinates -- taking into consideration if the animation is attached.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/02/1996 JLB : Coordinate based on visual center of object.                             *\n *=============================================================================================*/\nCOORDINATE AnimClass::Center_Coord(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (xObject != TARGET_NONE) {\n\t\treturn(Coord_Add(Coord, As_Object(xObject)->Target_Coord()));\n\t}\n#endif\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Render -- Draws an animation object.                                             *\n *                                                                                             *\n *    This is the working routine that renders the animation shape. It gets called once        *\n *    per animation per frame. It needs to be fast.                                            *\n *                                                                                             *\n * INPUT:   bool; Should the animation be rendered in spite of render flag?                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation rendered?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Render(bool forced) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Delay) return(false);\n\tif (Map[Center_Coord()].IsVisible) {\n\t\tconst_cast<AnimClass*>(this)->IsToDisplay = true;\t// const_cast. ST - 5/8/2019\n\t}\n#endif\n\treturn(ObjectClass::Render(forced));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Draw_It -- Draws the animation at the location specified.                        *\n *                                                                                             *\n *    This routine is used to render the animation object at the location specified. This is   *\n *    how the map imagery gets updated.                                                        *\n *                                                                                             *\n * INPUT:   x,y      -- The pixel coordinates to draw the animation at.                        *\n *                                                                                             *\n *          window   -- The to base the draw coordinates upon.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   05/19/1995 JLB : Added white translucent effect.                                          *\n *=============================================================================================*/\nvoid AnimClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tbool render_legacy = !IsInvisible && (Class->VirtualAnim == ANIM_NONE || window != WINDOW_VIRTUAL);\n\tbool render_virtual = Target_Legal(VirtualAnimTarget) && window == WINDOW_VIRTUAL;\n\n\tif (render_legacy) {\n\t\tBStart(BENCH_ANIMS);\n\n\t\tIsTheaterShape = Class->IsTheater;\n\n\t\tvoid const * shapefile = Get_Image_Data();\n\t\tif (shapefile != NULL) {\n\t\t\tvoid const * transtable = NULL;\n\t\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\t\tvoid const * remap = NULL;\n\t\t\tShapeFlags_Type flags = SHAPE_CENTER|SHAPE_WIN_REL;\n\t\t\tbool alt = false;\n\t\t\tint width = 0;\n\t\t\tint height = 0;\n\n\t\t\t/*\n\t\t\t**\tSome animations require special fixups.\n\t\t\t*/\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase ANIM_ATOM_BLAST:\n\t\t\t\t\ttranstable = Map.UnitShadow;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ANIM_FLAG:\n\t\t\t\t\tx += (ICON_PIXEL_W / 2) - 2;\n\t\t\t\t\ty += (3 * ICON_PIXEL_H / 4) - Get_Build_Frame_Height(shapefile);\n\t\t\t\t\ttranstable = Map.UnitShadow;\n\t\t\t\t\talt = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ANIM_BEACON_VIRTUAL:\n\t\t\t\t\twidth = 29;\n\t\t\t\t\theight = 39;\n\t\t\t\t\tflags = flags | SHAPE_BOTTOM | SHAPE_COMPACT;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the translucent table hasn't been determined yet, then check to see if it\n\t\t\t**\tshould use the white or normal translucent tables.\n\t\t\t*/\n\t\t\tif (transtable == NULL && Class->IsWhiteTrans) transtable = DisplayClass::WhiteTranslucentTable;\n\t\t\tif (transtable == NULL && Class->IsTranslucent) transtable = DisplayClass::TranslucentTable;\n\n\t\t\t/*\n\t\t\t**\tSet the shape flags to properly take into account any fading or ghosting\n\t\t\t**\ttable necessary.\n\t\t\t*/\n\t\t\tif (alt) {\n\t\t\t\tflags = flags | SHAPE_FADING;\n\t\t\t\tif (OwnerHouse != HOUSE_NONE) {\n\t\t\t\t\tremap = HouseClass::As_Pointer(OwnerHouse)->Remap_Table(false);\n\t\t\t\t} else {\n\t\t\t\t\tremap = ColorRemaps[PCOLOR_GOLD].RemapTable;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (transtable != NULL) flags = flags | SHAPE_GHOST;\n\n\t\t\t/*\n\t\t\t**\tDraw the animation shape, but ignore legacy if beyond normal stage count.\n\t\t\t*/\n\t\t\tif ((window == WINDOW_VIRTUAL) || (Fetch_Stage() < Class->Stages)) {\n\t\t\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\t\t\tCC_Draw_Shape(this, shapefile, shapenum, x, y, window, flags, remap, transtable, DIR_N, Class->VirtualScale, width, height);\n\t\t\t}\n\t\t}\n\t\tIsTheaterShape = false;\n\t\tBEnd(BENCH_ANIMS);\n\t}\n\tif (render_virtual) {\n\t\tAnimClass* virtual_anim = As_Animation(VirtualAnimTarget);\n\t\tvirtual_anim->Make_Visible();\n\t\tvirtual_anim->Draw_It(x, y, window);\n\t\tvirtual_anim->Make_Invisible();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Mark -- Signals to map that redrawing is necessary.                              *\n *                                                                                             *\n *    This routine is used by the animation logic system to inform the map that the cells      *\n *    under the animation must be rerendered.                                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool AnimClass::Mark(MarkType mark)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n//\t\tObjectClass::Mark(mark);\n\t\treturn(true);\n\t}\n#endif\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Overlap_List -- Determines the overlap list for the animation.                   *\n *                                                                                             *\n *    Use this routine to fetch the overlap list for the animation. This overlap list is the   *\n *    cells that this animation spills over.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the overlap list for this particular instance of the          *\n *          animation.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Overlap_List(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tstatic short const OverlapAtom[] = {\n\t\t(-MAP_CELL_W * 2) - 1, (-MAP_CELL_W * 2), (-MAP_CELL_W * 2) + 1,\n\t\t(-MAP_CELL_W * 1) - 1, (-MAP_CELL_W * 1), (-MAP_CELL_W * 1) + 1,\n\t\t(-MAP_CELL_W * 0) - 1, (-MAP_CELL_W * 0), (-MAP_CELL_W * 0) + 1,\n\t\t( MAP_CELL_W * 1) - 1, ( MAP_CELL_W * 1), ( MAP_CELL_W * 1) + 1,\n\t\t( MAP_CELL_W * 2) - 1, ( MAP_CELL_W * 2), ( MAP_CELL_W * 2) + 1,\n \t\tREFRESH_EOL\n\t};\n\tstatic short const OverlapFlag[] = { 0, 1, -MAP_CELL_W, -(MAP_CELL_W-1), MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL };\n\n\tif (IsToDelete) {\n\t\tstatic short const _list[] = {REFRESH_EOL};\n\t\treturn(_list);\n\t}\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\treturn(OverlapAtom);\n\t}\n\n\tif (Class->Type == ANIM_FLAG) {\n\t\treturn(OverlapFlag);\n\t}\n\n#ifdef PARTIAL\nIsTheaterShape = Class->IsTheater;\n\tif (Class->Get_Image_Data() != NULL) {\n\t\tint shapenum = Class->Start + Fetch_Stage();\n\t\tint count = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\tshapenum = min(shapenum, count-1);\n\n\t\tif (Class->DimensionData == NULL) {\n\t\t\tClass->DimensionData = new Rect [count];\n\t\t}\n\t\tif (Class->DimensionData != NULL && !Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Class->Get_Image_Data(), shapenum);\nIsTheaterShape = false;\n\t\t\treturn(Coord_Spillage_List(Center_Coord(), Class->DimensionData[shapenum]));\n\t\t}\n\t}\nIsTheaterShape = false;\n#endif\n#endif\n\treturn(Coord_Spillage_List(Center_Coord(), Class->Size));\n}\n\n\n/***********************************************************************************************\n * AnimClass::Occupy_List -- Determines the occupy list for the animation.                     *\n *                                                                                             *\n *    Animations always occupy only the cell that their center is located over. As such, this  *\n *    routine always returns a simple (center cell) occupation list.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the occupation list for the animation.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * AnimClass::Occupy_List(bool) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tstatic short _simple[] = {REFRESH_EOL};\n\n#endif\n\treturn(_simple);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Init -- Performs pre-scenario initialization.                                    *\n *                                                                                             *\n *    This routine is used to initialize the animation system prior to a scenario being loaded *\n *    or reloaded. It effectively removes all animations from the system.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Init(void)\n{\n\tAnims.Free_All();\n}\n\n\n/***********************************************************************************************\n * AnimClass::new -- Allocates an anim object from the pool.                                   *\n *                                                                                             *\n *    This routine is used to allocate a free anim class object from the preallocated pool     *\n *    in the near heap. If there are no free animation objects, then null is returned.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a free anim object.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * AnimClass::operator new(size_t)\n{\n\tvoid * ptr = Anims.Allocate();\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->Set_Active();\n\t} else {\n\t\tGlyphX_Debug_Print(\"AnimClass::operator new FAILED\");\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::delete -- Returns an anim object back to the free pool.                          *\n *                                                                                             *\n *    This routine is used to return an anim object back to the pool of free anim objects.     *\n *    Anim objects so returned are available to be reallocated for the next animation.         *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the anim object to return to the pool.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((AnimClass *)ptr)->IsActive = false;\n\t}\n\tAnims.Free((AnimClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * AnimClass::AnimClass -- The constructor for animation objects.                              *\n *                                                                                             *\n *    This routine is used as the constructor of animation objects. It initializes and adds    *\n *    the animation object to the display and logic systems.                                   *\n *                                                                                             *\n * INPUT:   animnum  -- The animation number to start.                                         *\n *                                                                                             *\n *          coord    -- The location of the animation.                                         *\n *                                                                                             *\n *          timedelay-- The delay before the animation starts.                                 *\n *                                                                                             *\n *          loop     -- The number of times to loop this animation.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   08/03/1994 JLB : Added a delayed affect parameter.                                        *\n *=============================================================================================*/\nAnimClass::AnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay, char loop) :\n\tObjectClass(RTTI_ANIM, Anims.ID(this)),\n\tClass(AnimTypes.Ptr((int)animnum)),\n\txObject(TARGET_NONE),\n\tSortTarget(TARGET_NONE),\n\tOwnerHouse(HOUSE_NONE),\n\tLoops(1),\n\tIsToDelete(false),\n\tIsBrandNew(true),\n\tIsInvisible(false),\n\tDelay(timedelay),\n\tAccum(0),\n\tAttachLayer(LAYER_NONE),\n\tKillTime(0ULL)\n{\n#ifdef VIC\n\tif (Class->Stages == -1) {\nIsTheaterShape = Class->IsTheater;\n\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\nIsTheaterShape = false;\n\n\t}\n\tif (Class->LoopEnd == -1) {\n\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t}\n\tif (Class->IsNormalized) {\n\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t} else {\n\t\tSet_Rate(Class->Delay);\n\t}\n\tSet_Stage(0);\n\n\tif (Class->IsGroundLayer) {\n\t\tHeight = FLIGHT_LEVEL;\n\t}\n\n\tAnimClass::Unlimbo(coord);\n\n\tVisibleFlags = static_cast<unsigned int>(-1);\n\n\t/*\n\t**\tDrop zone smoke always reveals the map around itself.\n\t*/\n\tif (*this == ANIM_LZ_SMOKE) {\n\t\t// Added PlayerPtr here as Sight_From now needs to know who to perform the action for. This should be OK as long as it's not used in MP. ST - 8/2/2019 2:34PM\n\t\tMap.Sight_From(Coord_Cell(coord), Rule.DropZoneRadius / CELL_LEPTON_W, PlayerPtr, false);\n\t}\n\n\tif (Class->Loops >= 0) {\n\t\tLoops = (char)(max(loop, 1) * Class->Loops);\n\t\tLoops = (char)max(Loops, 1);\n\t} else {\n\t\tLoops = Class->Loops;\n\t}\n\n\t/*\n\t**\tIf the animation starts immediately, then play the associated sound effect now.\n\t*/\n\tif (!Delay) {\n\t\tStart();\n\t}\n\n\t/*\n\t**\tCheck for a virtual animation\n\t*/\n\tif (Class->VirtualAnim != ANIM_NONE) {\n\t\tAnimClass* virtual_anim = new AnimClass(Class->VirtualAnim, Coord, timedelay, loop);\n\t\tif (virtual_anim != NULL) {\n\t\t\tvirtual_anim->Make_Invisible();\n\t\t\tVirtualAnimTarget = virtual_anim->As_Target();\n\t\t} else {\n\t\t\tVirtualAnimTarget = TARGET_NONE;\n\t\t}\n\t} else {\n\t\tVirtualAnimTarget = TARGET_NONE;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::~AnimClass -- Destructor for anim objects.                                       *\n *                                                                                             *\n *    This destructor handles removing the animation object from the system. It might require  *\n *    informing any object this animation is attached to that it is no longer attached.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimClass::~AnimClass(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\tif (GameActive) {\n\n\t\t/*\n\t\t**\tIf this anim is attached to another object\n\t\t**\tthen check to see if this is the last anim attached to it. If this\n\t\t**\tis the case, then inform the object that it is no longer attached to\n\t\t**\tan animation.\n\t\t*/\n\t\tif (Target_Legal(xObject) && As_Object(xObject) != NULL) {\n\t\t\tObjectClass * to = As_Object(xObject);\n\n\t\t\t/*\n\t\t\t**\tRemove the object from the appropriate display list.\n\t\t\t*/\n\t\t\tMap.Remove(this, In_Which_Layer());\n\n\t\t\t/*\n\t\t\t**\tScan for any other animations that are attached to the object that\n\t\t\t**\tthis animation is attached to. If there are no others, then inform the\n\t\t\t**\tattached object of this fact.\n\t\t\t*/\n\t\t\tint index;\n\t\t\tfor (index = 0; index < Anims.Count(); index++) {\n\t\t\t\tif (Anims.Ptr(index) != this && Anims.Ptr(index)->xObject == xObject) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTell the object that it is no longer being damaged.\n\t\t\t*/\n\t\t\tif (index == Anims.Count()) {\n\t\t\t\tto->Fire_Out();\n\t\t\t\tif (to->In_Which_Layer() == LAYER_GROUND) to->Mark(MARK_OVERLAP_UP);\n\t\t\t\tto->IsAnimAttached = false;\n\t\t\t\tif (to->In_Which_Layer() == LAYER_GROUND) to->Mark(MARK_OVERLAP_DOWN);\n\t\t\t}\n\t\t\tCoord = Coord_Add(to->Center_Coord(), Coord);\n\t\t\txObject = TARGET_NONE;\n\t\t}\n\n\t\tLimbo();\n\t}\n\n\txObject = TARGET_NONE;\n\tClass = 0;\n\tID = -1;\n\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::AI -- This is the low level anim processor.                                      *\n *                                                                                             *\n *    This routine is called once per frame per animation. It handles transition between       *\n *    animation frames and marks the map for redraw as necessary.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Speed is of upmost importance.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::AI(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tFor ground level based animations (ones that can run slowly as well as\n\t**\toccur behind other ground objects) always cause the cell to be redrawn.\n\t*/\n#ifdef PARTIAL\n\tif (!Delay && Class->IsGroundLayer) {\n\t\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n\t}\n#else\n\tMap.Refresh_Cells(Coord_Cell(Center_Coord()), Overlap_List());\n#endif\n\n\t/*\n\t**\tSpecial case check to make sure that building on top of a smoke marker\n\t**\tcauses the smoke marker to vanish.\n\t*/\n\tif (Class->Type == ANIM_LZ_SMOKE && Map[Center_Coord()].Cell_Building()) {\n\t\tIsToDelete = true;\n\t}\n\n\t/*\n\t**\tDon't allow corpses on rocks, rivers, and water (looks really weird).\n\t*/\n\tif (Class->Type >= ANIM_CORPSE1 && Class->Type <= ANIM_CORPSE3) {\n\t\tLandType land = Map[Center_Coord()].Land_Type();\n\t\tif (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER) {\n\t\t\tIsToDelete = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck the kill time.\n\t*/\n\tif (KillTime > 0ULL) {\n\t\tFILETIME ft;\n\t\tGetSystemTimeAsFileTime(&ft);\n\n\t\tunsigned long long now = (unsigned long long)ft.dwLowDateTime + ((unsigned long long)ft.dwHighDateTime << 32ULL);\n\t\tif (now >= KillTime) {\n\t\t\tIsToDelete = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tDelete this animation and bail early if the animation is flagged to be deleted\n\t**\timmediately.\n\t*/\n\tif (IsToDelete) {\n\t\tdelete this;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf this is a brand new animation, then don't process it the first logic pass\n\t**\tsince it might end up skipping the first animation frame before it has had a\n\t**\tchance to draw it.\n\t*/\n\tif (IsBrandNew) {\n\t\tIsBrandNew = false;\n\t\treturn;\n\t}\n\n#ifdef FIXIT_MULTI_SAVE\n\tif (Class->Stages == -1) {\n\t\tIsTheaterShape = Class->IsTheater;\n\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\tIsTheaterShape = false;\n\t}\n\tif (Class->LoopEnd == -1) {\n\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t}\n#endif\n\n\tif (Delay) {\n\t\tDelay--;\n\t\tif (!Delay) {\n\t\t\tStart();\n\t\t}\n\t} else {\n\n#ifdef FIXIT_MULTI_SAVE\n\t\tif (Class->Stages == -1) {\n\t\t\tIsTheaterShape = Class->IsTheater;\n\t\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\t\tIsTheaterShape = false;\n\t\t}\n\t\tif (Class->LoopEnd == -1) {\n\t\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tThis is necessary because there is no recording of animations on the map\n\t\t**\tand thus the animation cannot be intelligently flagged for redraw. Most\n\t\t**\tanimations move fast enough that they would need to be redrawn every\n\t\t**\tgame frame anyway so this isn't TOO bad.\n\t\t*/\n\t\tMark(MARK_CHANGE);\n\n\t\tif (StageClass::Graphic_Logic()) {\n\t\t\tint stage = Fetch_Stage();\n\n\t\t\t/*\n\t\t\t**\tIf this animation is attached to another object and it is a\n\t\t\t**\tdamaging kind of animation, then do the damage to the other\n\t\t\t**\tobject.\n\t\t\t*/\n\t\t\tif (xObject != TARGET_NONE && Class->Damage > 0 && stage < Class->Stages) {\n\t\t\t\tAccum += Class->Damage;\n\n\t\t\t\tif (Accum >= 1) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdminister the damage. If the object was destroyed by this anim,\n\t\t\t\t\t**\tthen the attached damaging anim is also destroyed.\n\t\t\t\t\t*/\n\t\t\t\t\tint damage = Accum;\n\t\t\t\t\tAccum -= damage;\n\t\t\t\t\tif (As_Object(xObject)->Take_Damage(damage, 0, WARHEAD_FIRE) == RESULT_DESTROYED) {\n\t\t\t\t\t\tif (Target_Legal(VirtualAnimTarget)) {\n\t\t\t\t\t\t\tdelete As_Animation(VirtualAnimTarget);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDuring the biggest stage (covers the most ground), perform any ground altering\n\t\t\t**\taction required. This masks craters and scorch marks, so that they appear\n\t\t\t**\tnaturally rather than \"popping\" into existence while in plain sight.\n\t\t\t*/\n\t\t\tif (Class->Biggest && Class->Start+stage == Class->Biggest) {\n\t\t\t\tMiddle();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck to see if the last frame has been displayed. If so, then the\n\t\t\t**\tanimation either ends or loops.\n\t\t\t*/\n\t\t\tif ((Loops <= 1 && stage >= Class->Stages) || (Loops > 1 && stage >= Class->LoopEnd-Class->Start)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if this animation should loop another time. If so, then start the loop\n\t\t\t\t**\tbut if not, then proceed into the animation termination handler.\n\t\t\t\t*/\n\t\t\t\tif (Loops > 0) Loops--;\n\t\t\t\tif (Loops != 0) {\n\t\t\t\t\tSet_Stage(Class->LoopStart);\n\t\t\t\t} else {\n\n\t\t\t\t\tif (Class->VirtualAnim != ANIM_NONE) {\n\t\t\t\t\t\tMake_Invisible();\n\t\t\t\t\t\tif (!Target_Legal(VirtualAnimTarget)) {\n\t\t\t\t\t\t\tif (Class->ChainTo != ANIM_NONE) {\n\t\t\t\t\t\t\t\tChain();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif ((Class->VirtualStages < 0) || (stage >= Class->VirtualStages)) {\n\t\t\t\t\t\t\tif (Class->ChainTo != ANIM_NONE) {\n\t\t\t\t\t\t\t\tChain();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Attach_To -- Attaches animation to object specified.                             *\n *                                                                                             *\n *    An animation can be \"attached\" to an object. In such cases, the animation is rendered    *\n *    as an offset from the center of the object it is attached to. This allows affects such   *\n *    as fire or smoke to be consistently placed on the vehicle it is associated with.         *\n *                                                                                             *\n * INPUT:   obj   -- Pointer to the object to attach the animation to.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Attach_To(ObjectClass * obj)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (obj == NULL) return;\n\tassert(obj->IsActive);\n\n\tif (obj->In_Which_Layer() == LAYER_GROUND) obj->Mark(MARK_OVERLAP_UP);\n\tobj->IsAnimAttached = true;\n\tif (obj->In_Which_Layer() == LAYER_GROUND) obj->Mark(MARK_OVERLAP_DOWN);\n\tLimbo();\n\txObject = obj->As_Target();\n\tUnlimbo(Coord);\n\tAttachLayer = In_Which_Layer();\n\tHeight = (AttachLayer == LAYER_GROUND) ? FLIGHT_LEVEL : 0;\n\tCoord = Coord_Sub(Coord, obj->Target_Coord());\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Sort_Above -- Sorts the animation right above the specified target.              *\n *                                                                                             *\n *    Allows an animation to always be sorted above a particular target. Typically used        *\n *    for explosions and other effects that look weird beneath those objects.                  *\n *                                                                                             *\n * INPUT:   target   -- Target to sort above.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/2019 SKY : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Sort_Above(TARGET target)\n{\n#ifdef VIC\n\tSortTarget = target;\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::In_Which_Layer -- Determines what render layer the anim should be in.            *\n *                                                                                             *\n *    Use this routine to find out which display layer (ground or air) that the animation      *\n *    should be in. This information is used to place the animation into the correct display   *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that the animation should exist in.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/25/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType AnimClass::In_Which_Layer(void) const\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (AttachLayer != LAYER_NONE) {\n\t\treturn AttachLayer;\n\t}\n\n\tif (Class->Type >= ANIM_CORPSE1 && Class->Type <= ANIM_CORPSE3) {\n\t\treturn(LAYER_SURFACE);\n\t}\n\n\tif (Target_Legal(xObject)) {\n\t\treturn As_Object(xObject)->In_Which_Layer();\n\t}\n\n\tif (Class->IsGroundLayer) {\n\t\treturn(LAYER_GROUND);\n\t}\n#endif\n\treturn(LAYER_AIR);\n}\n\n\n/***********************************************************************************************\n * AnimClass::Start -- Processes initial animation side effects.                               *\n *                                                                                             *\n *    This routine is called when the animation first starts. Sometimes there are side effects *\n *    associated with this animation that must occur immediately. Typically, this is the       *\n *    sound effect assigned to this animation. If this animation is supposed to attach itself  *\n *    to any object at its location, then do so at this time as well.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Start(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark();\n\n\t/*\n\t**\tPlay the sound effect for this animation.\n\t*/\n\tSound_Effect(Class->Sound, Coord);\n\n\t/*\n\t**\tIf the stage where collateral effects occur is the first stage of the animation, then\n\t**\tperform this action now. Subsequent checks against this stage value starts with the\n\t**\tsecond frame of the animation.\n\t*/\n\tif (!Class->Biggest) {\n\t\tMiddle();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Middle -- Processes any middle events.                                           *\n *                                                                                             *\n *    This routine is called when the animation as reached its largest stage. Typically, this  *\n *    routine is used to cause scorches or craters to appear at a cosmetically pleasing        *\n *    moment.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   10/17/1995 JLB : Ion camera added.                                                        *\n *=============================================================================================*/\nvoid AnimClass::Middle(void)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL cell = Coord_Cell(Center_Coord());\n\tCellClass * cellptr = &Map[cell];\n\n\tif (Class->Type == ANIM_ATOM_BLAST) {\n\t\tDo_Atom_Damage(OwnerHouse, cell);\n\t}\n\n\t/*\n\t**\tIf this animation leaves scorch marks (e.g., napalm), then do so at this time.\n\t*/\n\tif (Class->IsScorcher) {\n\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Center_Coord());\n\t}\n\n\t/*\n\t**\tSome animations leave a crater when they occur. Artillery is a good example.\n\t**\tCraters always remove the Tiberium where they occur.\n\t*/\n\tif (Class->IsCraterForming) {\n\n\t\t/*\n\t\t**\tCraters reduce the level of Tiberium in the cell.\n\t\t*/\n\t\tcellptr->Reduce_Tiberium(6);\n\n\t\t/*\n\t\t**\tIf there already is a crater in the cell, then just expand the\n\t\t**\tcrater.\n\t\t*/\n\t\tnew SmudgeClass(SMUDGE_CRATER1, Center_Coord());\n\t}\n\n\tAnimClass * newanim;\n\n\t/*\n\t**\tIf this animation spawns side effects during its lifetime, then\n\t**\tdo so now. Usually, these side effects are in the form of other\n\t**\tanimations.\n\t*/\n\tswitch (Class->Type) {\n\t\tcase ANIM_NAPALM1:\n\t\tcase ANIM_NAPALM2:\n\t\tcase ANIM_NAPALM3:\n\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0040), true), 0, Random_Pick(1, 2));\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x00A0), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\tnew AnimClass(ANIM_FIRE_MED, Map.Closest_Free_Spot(Coord_Scatter(Center_Coord(), 0x0070), true), 0, Random_Pick(1, 2));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ANIM_FIRE_MED:\n\t\tcase ANIM_FIRE_MED2:\n\t\t\tnewanim = new AnimClass(ANIM_FIRE_SMALL, Center_Coord(), 0, Random_Pick(1, 2));\n\t\t\tif (newanim != NULL && xObject != TARGET_NONE) {\n\t\t\t\tnewanim->Attach_To(As_Object(xObject));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n#endif\n}\n\n\nvoid AnimClass::Chain(void)\n{\n\t/*\n\t**\tThe animation should end now, but first check to see if\n\t**\tit needs to chain into another animation. If so, then the\n\t**\tanimation isn't technically over. It metamorphoses into the\n\t**\tnew form.\n\t*/\n\tif (Class->ChainTo != ANIM_NONE) {\n\n\t\tClass = (AnimTypeClass *)&AnimTypeClass::As_Reference(Class->ChainTo);\n\n\t\tif (Class->Stages == -1) {\n\t\t\tIsTheaterShape = Class->IsTheater;\n\t\t\t((int&)Class->Stages) = Get_Build_Frame_Count(Class->Get_Image_Data());\n\t\t\tIsTheaterShape = false;\n\t\t}\n\t\tif (Class->LoopEnd == -1) {\n\t\t\t((int&)Class->LoopEnd) = Class->Stages;\n\t\t}\n\n\t\tIsToDelete = false;\n\t\tLoops = Class->Loops;\n\t\tAccum = 0;\n\t\tif (Class->IsNormalized) {\n\t\t\tSet_Rate(Options.Normalize_Delay(Class->Delay));\n\t\t} else {\n\t\t\tSet_Rate(Class->Delay);\n\t\t}\n\t\tSet_Stage(Class->Start);\n\t\tStart();\n\t}\n}\n\n\n/***********************************************************************************************\n * AnimClass::Detach -- Remove animation if attached to target.                                *\n *                                                                                             *\n *    This routine is called when the specified target is being removed from the game. If this *\n *    animation happens to be attached to this object, then the animation must be remove as    *\n *    well.                                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target that is about to be destroyed.                              *\n *                                                                                             *\n *          all      -- Is the target being destroyed RIGHT NOW? If not, then it will be       *\n *                      destroyed soon. In that case, the animation should continue to remain  *\n *                      attached for cosmetic reasons.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   07/02/1995 JLB : Detach is a precursor to animation destruction.                          *\n *=============================================================================================*/\nvoid AnimClass::Detach(TARGET target, bool all)\n{\n#ifdef VIC\n\tassert(Anims.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (all) {\n\t\tif (Target_Legal(VirtualAnimTarget) && VirtualAnimTarget == target) {\n\t\t\tVirtualAnimTarget = TARGET_NONE;\n\t\t\tif (IsInvisible) {\n\t\t\t\tIsToDelete = true;\n\t\t\t\tMark(MARK_UP);\n\t\t\t}\n\t\t}\n\t\tif (xObject == target) {\n\t\t\tMap.Remove(this, In_Which_Layer());\n\t\t\txObject = TARGET_NONE;\n\t\t\tAttachLayer = LAYER_NONE;\n\t\t\tIsToDelete = true;\n\t\t\tMark(MARK_UP);\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * AnimClass::Do_Atom_Damage -- Do atom bomb damage centered around the cell specified.        *\n *                                                                                             *\n *    This routine will apply damage around the ground-zero cell specified.                    *\n *                                                                                             *\n * INPUT:   ownerhouse  -- The owner of this atom bomb.                                        *\n *                                                                                             *\n *          cell        -- The ground zero location to apply the atom bomb damage.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid AnimClass::Do_Atom_Damage(HousesType ownerhouse, CELL cell)\n{\n#ifdef VIC\n\t/*\n\t**\tFind someone to blame the explosion on. This is necessary in\n\t**\torder to properly enact retribution and record the kill for\n\t**\tscore purposes.\n\t*/\n\tBuildingClass * building = NULL;\n\tTechnoClass * backup = NULL;\n\tif (ownerhouse != HOUSE_NONE) {\n\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\tObjectClass * obj = Logic[index];\n\n\t\t\tif (obj != NULL && obj->Is_Techno() && obj->Owner() == ownerhouse) {\n\t\t\t\tbackup = (TechnoClass *)obj;\n\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING && *((BuildingClass *)obj) == STRUCT_MSLO) {\n\t\t\t\t\tbuilding = (BuildingClass *)obj;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (building == NULL) building = (BuildingClass *)backup;\n\t}\n\n\tint radius;\n\tint rawdamage;\n\tif (Session.Type == GAME_NORMAL) {\n\t\tradius = 4;\n\t\trawdamage = Rule.AtomDamage;\n\t\t//WhitePalette.Set(FADE_PALETTE_SLOW, Call_Back);\t\t//TO_FIX. ST 5/8/2019\n\t} else {\n\t\tradius = 3;\n\t\trawdamage = Rule.AtomDamage/5;\n\t}\n\n\tWide_Area_Damage(Cell_Coord(cell), radius * CELL_LEPTON_W, rawdamage, building, WARHEAD_FIRE);\n\tShake_The_Screen(3);\n\tif (Session.Type == GAME_NORMAL) {\n\t\t//GamePalette.Set(FADE_PALETTE_SLOW, Call_Back);\t//TO_FIX. ST 5/8/2019\n\t}\n#endif\n}\n\nvoid AnimClass::Set_Owner(HousesType owner)\n{\n\tOwnerHouse = owner;\n\tif (Target_Legal(VirtualAnimTarget)) {\n\t\tAs_Animation(VirtualAnimTarget)->Set_Owner(owner);\n\t}\n}\n\nvoid AnimClass::Set_Visible_Flags(unsigned flags)\n{\n\tVisibleFlags = flags;\n\tif (Target_Legal(VirtualAnimTarget)) {\n\t\tAs_Animation(VirtualAnimTarget)->Set_Visible_Flags(flags);\n\t}\n}\n"
  },
  {
    "path": "REDALERT/ANIM.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ANIM.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ANIM.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 30, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 30, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ANIM_H\n#define ANIM_H\n\n#include\t\"type.h\"\n\n\n/**********************************************************************************************\n**\tThis is the class that controls the shape animation objects. Shape animation objects are\n**\tdisplayed over the top of the game map. Typically, they are used for explosion and fire\n**\teffects.\n*/\nclass AnimClass : public ObjectClass, public StageClass {\n\t\t/*\n\t\t**\tThis points to the type of animation object this is.\n\t\t*/\n\t\tCCPtr<AnimTypeClass> Class;\n\n\tpublic:\n\n\t\tAnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay=0, char loop=1);\n\t\tAnimClass(NoInitClass const & x) : ObjectClass(x), Class(x), StageClass(x) {};\n\t\tvirtual ~AnimClass(void);\n\n\t\toperator AnimType(void) const {return Class->Type;};\n\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tvoid Attach_To(ObjectClass *obj);\n\t\tvoid Sort_Above(TARGET target);\n\t\tvoid Make_Invisible(void) {IsInvisible = true;};\n\t\tvoid Make_Visible(void) {IsInvisible = false;};\n\t\tvoid Kill_At(unsigned long long kill_time) {KillTime = kill_time;}\n\t\tstatic void Do_Atom_Damage(HousesType ownerhouse, CELL cell);\n\n\t\t/*\n\t\t** 2019/09/19 JAS\n\t\t** Added functions for accessing which players can see this anim\n\t\t*/\n\t\tvoid Set_Visible_Flags(unsigned flags);\n\t\tunsigned Get_Visible_Flags() const { return (Delay == 0) ? VisibleFlags : 0; }\n\n\t\tvirtual void Set_Owner(HousesType owner);\n\t\tvirtual HousesType Owner(void) const {return OwnerHouse;};\n\t\tvirtual bool Can_Place_Here(COORDINATE ) const {return true;}\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual bool Render(bool forced) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual short const * Occupy_List(bool = false) const;\n\t\tvirtual short const * Overlap_List(void) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual void AI(void);\n\t\tvirtual void Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(FileClass & file);\n\n\t\t/*\n\t\t**\tIf this animation is attached to an object, then this points to that object. An\n\t\t**\tanimation that is attached will follow that object as it moves. This is important\n\t\t**\tfor animations such as flames and smoke.\n\t\t*/\n\t\tTARGET xObject;\n\n\t\t/*\n\t\t**\tIf specified, this animation uses the sort target for Y sorting\n\t\t*/\n\t\tTARGET SortTarget;\n\n\t\t/*\n\t\t**\tIf this animation has an owner, then it will be recorded here. An owner\n\t\t**\tis used when damage is caused by this animation during the middle of its\n\t\t**\tanimation.\n\t\t*/\n\t\tHousesType OwnerHouse;\n\n\t\t/*\n\t\t**\tThis counter tells how many more times the animation should loop before it\n\t\t**\tterminates.\n\t\t*/\n\t\tchar Loops;\n\n\tprotected:\n\t\tvoid Middle(void);\n\t\tvoid Start(void);\n\t\tvoid Chain(void);\n\n\tprivate:\n\t\t/*\n\t\t**\tDelete this animation at the next opportunity. This is flagged when the\n\t\t**\tanimation is to be prematurely ended as a result of some outside event.\n\t\t*/\n\t\tunsigned IsToDelete:1;\n\n\t\t/*\n\t\t**\tIf the animation has just been created, then don't do any animation\n\t\t**\tprocessing until it has been through the render loop at least once.\n\t\t*/\n\t\tunsigned IsBrandNew:1;\n\n\t\t/*\n\t\t**\tIf this animation is invisible, then this flag will be true. An invisible\n\t\t**\tanimation is one that is created for the sole purpose of keeping all\n\t\t**\tmachines synchronized. It will not be displayed.\n\t\t*/\n\t\tunsigned IsInvisible:1;\n\n\t\t/*\n\t\t** 2019/09/19 JAS\n\t\t** Flags storing which players can see this anim.\n\t\t*/\n\t\tunsigned VisibleFlags;\n\n\t\t/*\n\t\t**\tIs this animation in a temporary suspended state?  If so, then it won't\n\t\t**\tbe rendered until this value is zero. The flag will be set to false\n\t\t**\tafter the first countdown timer reaches 0.\n\t\t*/\n\t\tint Delay;\n\n\t\t/*\n\t\t**\tIf this is an animation that damages whatever it is attached to, then this\n\t\t**\tvalue holds the accumulation of fractional damage points. When the accumulated\n\t\t**\tfractions reach 256, then one damage point is applied to the attached object.\n\t\t*/\n\t\tfixed Accum;\n\n\t\t/*\n\t\t**\tThe map layer this animation is in when attached to an object.\n\t\t*/\n\t\tLayerType AttachLayer;\n\n\t\t/*\n\t\t**\tThis references the virtual animation.\n\t\t*/\n\t\tTARGET VirtualAnimTarget;\n\n\t\t/*\n\t\t**\tReal-time point to kill this animation.\n\t\t*/\n\t\tunsigned long long KillTime;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[24];\n};\n\n\n\n#endif"
  },
  {
    "path": "REDALERT/AUDIO.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/AUDIO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : November 1, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Is_Speaking -- Checks to see if the eva voice is still playing.                           *\n *   Sound_Effect -- General purpose sound player.                                             *\n *   Sound_Effect -- Plays a sound effect in the tactical map.                                 *\n *   Speak -- Computer speaks to the player.                                                   *\n *   Speak_AI -- Handles starting the EVA voices.                                              *\n *   Speech_Name -- Fetches the name for the voice specified.                                  *\n *   Stop_Speaking -- Forces the EVA voice to stop talking.                                    *\n *   Voc_From_Name -- Fetch VocType from ASCII name specified.                                 *\n *   Voc_Name -- Fetches the name for the sound effect.                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n /*\n **\n **\n ** Win32lib stubs\n **\n **\n **\n */\n\n\nSFX_Type\t\t\t\t\tSoundType;\nSample_Type\t\t\t\tSampleType;\n\nint File_Stream_Sample(char const *filename, BOOL real_time_start) { return 1; };\nint File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start) { return 1; };\nvoid __cdecl Sound_Callback(void) {};\nvoid __cdecl far maintenance_callback(void) {};\nvoid *Load_Sample(char const *filename) { return NULL; };\nlong Load_Sample_Into_Buffer(char const *filename, void *buffer, long size) { return 0; }\nlong Sample_Read(int fh, void *buffer, long size) { return 0; };\nvoid Free_Sample(void const *sample) {};\nBOOL Audio_Init(HWND window, int bits_per_sample, BOOL stereo, int rate, int reverse_channels) { return 0; };\nvoid Sound_End(void) {};\nvoid Stop_Sample(int handle) {};\nBOOL Sample_Status(int handle) { return 0; };\nBOOL Is_Sample_Playing(void const * sample) { return 0; };\nvoid Stop_Sample_Playing(void const * sample) {};\nint Play_Sample(void const *sample, int priority, int volume, signed short panloc) { return 1; };\nint Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id) { return 1; };\nint Set_Sound_Vol(int volume) { return 0; };\nint Set_Score_Vol(int volume) { return 0; };\nvoid Fade_Sample(int handle, int ticks) {};\nint Get_Free_Sample_Handle(int priority) { return 1; };\nint Get_Digi_Handle(void) { return 1; }\nlong Sample_Length(void const *sample) { return 0; };\nvoid Restore_Sound_Buffers(void) {};\nBOOL Set_Primary_Buffer_Format(void) { return 0; };\nBOOL Start_Primary_Sound_Buffer(BOOL forced) { return 0; };\nvoid Stop_Primary_Sound_Buffer(void) {};\n\n\n/***************************************************************************\n**\tControls what special effects may occur on the sound effect.\n*/\ntypedef enum {\n\tIN_NOVAR,\t\t\t// No variation or alterations allowed.\n\tIN_VAR\t\t\t\t// Infantry variance response modification.\n} ContextType;\n\n// static struct { // MBL 02.21.2019\n// Had to name the struct for VS 2017 distributed build. ST - 4/10/2019 3:59PM\nstruct SoundEffectNameStruct {\n\tchar const *\tName;\t\t// Digitized voice file name.\n\tint\t\t\t\tPriority;\t// Playback priority of this sample.\n\tContextType\t\tWhere;\t\t// In what game context does this sample exist.\n} SoundEffectName[VOC_COUNT] = {\n\n\t/*\n\t**\tCivilian voices (technicians too).\n\t*/\n\t{\"GIRLOKAY\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_OKAY\n\t{\"GIRLYEAH\",\t20,\tIN_NOVAR},\t\t//\tVOC_GIRL_YEAH\n\t{\"GUYOKAY1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_OKAY\n\t{\"GUYYEAH1\",\t20,\tIN_NOVAR},\t\t//\tVOC_GUY_YEAH\n\n\t{\"MINELAY1\",\t5,\t\tIN_VAR},\t\t\t// VOC_MINELAY1\n\n\t/*\n\t**\tInfantry and vehicle responses.\n\t*/\n\t{\"ACKNO\",\t\t20,\tIN_VAR},\t//\tVOC_ACKNOWL\t\t\t\"acknowledged\"\n\t{\"AFFIRM1\",\t\t20,\tIN_VAR},\t//\tVOC_AFFIRM\t\t\t\"affirmative\"\n\t{\"AWAIT1\",\t\t20,\tIN_VAR},\t//\tVOC_AWAIT1\t\t\t\"awaiting orders\"\n\t{\"EAFFIRM1\",\t20,\tIN_NOVAR},\t// VOC_ENG_AFFIRM\tEngineer: \"affirmative\"\n\t{\"EENGIN1\",\t\t20,\tIN_NOVAR},\t//\tVOC_ENG_ENG\t\t\tEngineer: \"engineering\"\n\t{\"NOPROB\",\t\t20,\tIN_VAR},\t// VOC_NO_PROB\t\t\t\"not a problem\"\n\t{\"READY\",\t\t20,\tIN_VAR},\t// VOC_READY\t\t\t\"ready and waiting\"\n\t{\"REPORT1\",\t\t20,\tIN_VAR},\t//\tVOC_REPORT\t\t\t\"reporting\"\n\t{\"RITAWAY\",\t\t20,\tIN_VAR},\t// VOC_RIGHT_AWAY\t\t\"right away sir\"\n\t{\"ROGER\",\t\t20,\tIN_VAR},\t// VOC_ROGER\t\t\t\"roger\"\n\t{\"UGOTIT\",\t\t20,\tIN_VAR},\t// VOC_UGOTIT\t\t\t\"you got it\"\n\t{\"VEHIC1\",\t\t20,\tIN_VAR},\t//\tVOC_VEHIC1\t\t\t\"vehicle reporting\"\n\t{\"YESSIR1\",\t\t20,\tIN_VAR},\t//\tVOC_YESSIR\t\t\t\"yes sir\"\n\n\t{\"DEDMAN1\", \t10,\tIN_NOVAR},\t// VOC_SCREAM1\t\t\tshort infantry scream\n\t{\"DEDMAN2\", \t10,\tIN_NOVAR},\t// VOC_SCREAM3\t\t\tshort infantry scream\n\t{\"DEDMAN3\", \t10,\tIN_NOVAR},\t// VOC_SCREAM4\t\t\tshort infantry scream\n\t{\"DEDMAN4\", \t10,\tIN_NOVAR},\t// VOC_SCREAM5\t\t\tshort infantry scream\n\t{\"DEDMAN5\", \t10,\tIN_NOVAR},\t// VOC_SCREAM6\t\t\tshort infantry scream\n\t{\"DEDMAN6\", \t10,\tIN_NOVAR},\t// VOC_SCREAM7\t\t\tshort infantry scream\n\t{\"DEDMAN7\", \t10,\tIN_NOVAR},\t// VOC_SCREAM10\t\tshort infantry scream\n\t{\"DEDMAN8\", \t10,\tIN_NOVAR},\t// VOC_SCREAM11\t\tshort infantry scream\n\t{\"DEDMAN10\", \t10,\tIN_NOVAR},\t// VOC_YELL1\t\t\tlong infantry scream\n\n\t{\"CHRONO2\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_CHRONO\t\t\tChronosphere sound\n\t{\"CANNON1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON1\t\t\tCannon sound (medium).\n\t{\"CANNON2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON2\t\t\tCannon sound (short).\n\t{\"IRONCUR9\",\t10,\tIN_NOVAR},\t// VOC_IRON1\n\t{\"EMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_MOVEOUT\tEngineer: \"movin' out\"\n\t{\"SONPULSE\",\t10,\tIN_NOVAR},\t//\tVOC_SONAR\n\t{\"SANDBAG2\",\t5,\t\tIN_NOVAR},\t// VOC_SANDBAG\t\t\tsand bag crunch\n\t{\"MINEBLO1\",\t5,\t\tIN_NOVAR},\t// VOC_MINEBLOW\t\tweird mine explosion\n\t{\"CHUTE1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CHUTE1\t\t\tWind swoosh sound.\n\t{\"DOGY1\",\t\t5,\t\tIN_NOVAR},\t//\tVOC_DOG_BARK\t\tDog bark.\n\t{\"DOGW5\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_WHINE\t\tDog whine.\n\t{\"DOGG5P\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_GROWL2\t\tStrong dog growl.\n\t{\"FIREBL3\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_LAUNCH\tFireball launch sound.\n\t{\"FIRETRT1\",\t1,\t\tIN_NOVAR},\t//\tVOC_FIRE_EXPLODE\tFireball explode sound.\n\t{\"GRENADE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GRENADE_TOSS\tGrenade toss.\n\t{\"GUN11\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5\t\t\t5 round gun burst (slow).\n\t{\"GUN13\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_7\t\t\t7 round gun burst (fast).\n\t{\"EYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_ENG_YES,\t\tEngineer: \"yes sir\"\n\t{\"GUN27\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_RIFLE\t\tRifle shot.\n\t{\"HEAL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_HEAL\t\t\t\tHealing effect.\n\t{\"HYDROD1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_DOOR\t\t\t\tHyrdrolic door.\n\t{\"INVUL2\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_INVULNERABLE\tInvulnerability effect.\n\t{\"KABOOM1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM1\t\t\tLong explosion (muffled).\n\t{\"KABOOM12\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM12\t\tVery long explosion (muffled).\n\t{\"KABOOM15\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM15\t\tVery long explosion (muffled).\n\t{\"SPLASH9\",\t\t5,\t\tIN_NOVAR},\t// VOC_SPLASH\t\t\twater splash\n\t{\"KABOOM22\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM22\t\tLong explosion (sharp).\n\t{\"AACANON3\",\t1,\t\tIN_NOVAR},\n\t{\"TANDETH1\",\t10,\tIN_NOVAR},\n\t{\"MGUNINF1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5F\t\t\t5 round gun burst (fast).\n\t{\"MISSILE1\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_1\t\tMissile with high tech effect.\n\t{\"MISSILE6\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_2\t\tLong missile launch.\n\t{\"MISSILE7\",\t1,\t\tIN_NOVAR},\t//\tVOC_MISSILE_3\t\tShort missile launch.\n\t{\"x\",\t\t\t\t1,\t\tIN_NOVAR},\n\t{\"PILLBOX1\",\t1,\t\tIN_NOVAR},\t//\tVOC_GUN_5R\t\t\t5 round gun burst (rattles).\n\t{\"RABEEP1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_BEEP\t\t\t\tGeneric beep sound.\n\t{\"RAMENU1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CLICK\t\t\tGeneric click sound.\n\t{\"SILENCER\",\t1,\t\tIN_NOVAR},\t//\tVOC_SILENCER\t\tSilencer.\n\t{\"TANK5\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON6\t\t\tLong muffled cannon shot.\n\t{\"TANK6\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON7\t\t\tSharp mechanical cannon fire.\n\t{\"TORPEDO1\",\t1,\t\tIN_NOVAR},\t//\tVOC_TORPEDO\t\t\tTorpedo launch.\n\t{\"TURRET1\",\t\t1,\t\tIN_NOVAR},\t//\tVOC_CANNON8\t\t\tSharp cannon fire.\n\t{\"TSLACHG2\",\t10,\tIN_NOVAR},\t//\tVOC_TESLA_POWER_UP\tHum charge up.\n\t{\"TESLA1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TESLA_ZAP\t\tTesla zap effect.\n\t{\"SQUISHY2\",\t10,\tIN_NOVAR},\t//\tVOC_SQUISH\t\t\tSquish effect.\n\t{\"SCOLDY1\",\t\t10,\tIN_NOVAR},\t//\tVOC_SCOLD\t\t\tScold bleep.\n\t{\"RADARON2\",\t20,\tIN_NOVAR},\t//\tVOC_RADAR_ON\t\tPowering up electronics.\n\t{\"RADARDN1\",\t10,\tIN_NOVAR},\t//\tVOC_RADAR_OFF\t\tB movie power down effect.\n\t{\"PLACBLDG\",\t10,\tIN_NOVAR},\t//\tVOC_PLACE_BUILDING_DOWN\tBuilding slam down sound.\n\t{\"KABOOM30\",\t1,\t\tIN_NOVAR},\t//\tVOC_KABOOM30\t\tShort explosion (HE).\n\t{\"KABOOM25\",\t10,\tIN_NOVAR},\t//\tVOC_KABOOM25\t\tShort growling explosion.\n\t{\"x\",\t\t\t\t10,\tIN_NOVAR},\n\t{\"DOGW7\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_HURT\t\tDog whine (loud).\n\t{\"DOGW3PX\",\t\t10,\tIN_NOVAR},\t//\tVOC_DOG_YES\t\t\tDog 'yes sir'.\n\t{\"CRMBLE2\",\t\t10,\tIN_NOVAR},\t//\tVOC_CRUMBLE\t\t\tBuilding crumble.\n\t{\"CASHUP1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_UP\t\tRising money tick.\n\t{\"CASHDN1\",\t\t10,\tIN_NOVAR},\t//\tVOC_MONEY_DOWN\t\tFalling money tick.\n\t{\"BUILD5\",\t\t10,\tIN_NOVAR},\t//\tVOC_CONSTRUCTION\tBuilding construction sound.\n\t{\"BLEEP9\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_CLOSED\tLong bleep.\n\t{\"BLEEP6\",\t\t10,\tIN_NOVAR},\t//\tVOC_INCOMING_MESSAGE\tSoft happy warble.\n\t{\"BLEEP5\",\t\t10,\tIN_NOVAR},\t//\tVOC_SYS_ERROR\t\tSharp soft warble.\n\t{\"BLEEP17\",\t\t10,\tIN_NOVAR},\t//\tVOC_OPTIONS_CHANGED\tMid range soft warble.\n\t{\"BLEEP13\",\t\t10,\tIN_NOVAR},\t//\tVOC_GAME_FORMING\tLong warble.\n\t{\"BLEEP12\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_LEFT\tChirp sequence.\n\t{\"BLEEP11\",\t\t10,\tIN_NOVAR},\t//\tVOC_PLAYER_JOINED\tReverse chirp sequence.\n\t{\"H2OBOMB2\",\t10,\tIN_NOVAR},\t//\tVOC_DEPTH_CHARGE\tDistant explosion sound.\n\t{\"CASHTURN\",\t10,\tIN_NOVAR},\t//\tVOC_CASHTURN\t\tAirbrake.\n\t{\"TUFFGUY1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHEW\t\t\tTanya: \"Chew on this\"\n\t{\"ROKROLL1\",\t20,\tIN_NOVAR},\t//\tVOC_TANYA_ROCK\t\t\tTanya: \"Let's rock\"\n\t{\"LAUGH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_LAUGH\t\tTanya: \"ha ha ha\"\n\t{\"CMON1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_SHAKE\t\tTanya: \"Shake it baby\"\n\t{\"BOMBIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_CHING\t\tTanya: \"Cha Ching\"\n\t{\"GOTIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GOT\t\t\tTanya: \"That's all you got\"\n\t{\"KEEPEM1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_KISS\t\t\tTanya: \"Kiss it bye bye\"\n\t{\"ONIT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_THERE\t\tTanya: \"I'm there\"\n\t{\"LEFTY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_GIVE\t\t\tTanya: \"Give it to me\"\n\t{\"YEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YEA\t\t\tTanya: \"Yea?\"\n\t{\"YES1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_YES\t\t\tTanya: \"Yes sir?\"\n\t{\"YO1\",\t\t\t20,\tIN_NOVAR},\t//\tVOC_TANYA_WHATS\t\tTanya: \"What's up.\"\n\t{\"WALLKIL2\",\t5,\t\tIN_NOVAR},\t//\tVOC_WALLKILL2\t\t\tCrushing wall sound.\n\t{\"x\",\t\t\t\t10,\tIN_NOVAR},\n\t{\"GUN5\",\t\t\t5,\t\tIN_NOVAR},\t//\tVOC_TRIPLE_SHOT\t\tThree quick shots in succession.\n\t{\"SUBSHOW1\",\t5,\t\tIN_NOVAR},\t//\tVOC_SUBSHOW\t\t\t\tSubmarine surface sound.\n\t{\"EINAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_AH,\t\t\t\tEinstien \"ah\"\n\t{\"EINOK1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_OK,\t\t\t\tEinstien \"ok\"\n\t{\"EINYES1\",\t\t20,\tIN_NOVAR},\t//\tVOC_E_YES,\t\t\t\tEinstien \"yes\"\n\t{\"MINE1\",\t\t10,\tIN_NOVAR},\t//\tVOC_TRIP_MINE\t\t\tmine explosion sound\n\n\t{\"SCOMND1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_COMMANDER\t\tSpy: \"commander?\"\n\t{\"SYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_YESSIR\t\t\tSpy: \"yes sir\"\n\t{\"SINDEED1\",\t20,\tIN_NOVAR},\t//\tVOC_SPY_INDEED\t\t\tSpy: \"indeed\"\n\t{\"SONWAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_ONWAY\t\t\tSpy: \"on my way\"\n\t{\"SKING1\",\t\t20,\tIN_NOVAR},\t//\tVOC_SPY_KING\t\t\tSpy: \"for king and country\"\n\t{\"MRESPON1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_REPORTING\t\tMedic: \"reporting\"\n\t{\"MYESSIR1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_YESSIR\t\t\tMedic: \"yes sir\"\n\t{\"MAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_AFFIRM\t\t\tMedic: \"affirmative\"\n\t{\"MMOVOUT1\",\t20,\tIN_NOVAR},\t//\tVOC_MED_MOVEOUT\t\tMedic: \"movin' out\"\n\t{\"BEEPSLCT\",\t10,\tIN_NOVAR},\t//\tVOC_BEEP_SELECT\t\tmap selection beep\n\n\t{\"SYEAH1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_YEA\t\t\tThief: \"yea?\"\n\t{\"ANTDIE\",\t\t20,\tIN_NOVAR},\t//\tVOC_ANTDIE\n\t{\"ANTBITE\",\t\t20,\tIN_NOVAR},\t//\tVOC_ANTBITE\n\t{\"SMOUT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_MOVEOUT\t\tThief: \"movin' out\"\n\t{\"SOKAY1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_OKAY\t\t\tThief: \"ok\"\n\t{\"x\",\t\t\t\t20,\tIN_NOVAR},\n\t{\"SWHAT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_THIEF_WHAT\t\t\tThief: \"what\"\n\t{\"SAFFIRM1\",\t20,\tIN_NOVAR},\t//\tVOC_THIEF_AFFIRM\t\tThief: \"affirmative\"\n//ADDED VG 2/24/97\n\t{\"STAVCMDR\",\t20,\tIN_NOVAR},\t\n\t{\"STAVCRSE\",\t20,\tIN_NOVAR},\t\n\t{\"STAVYES\",\t\t20,\tIN_NOVAR},\t\n\t{\"STAVMOV\",\t\t20,\tIN_NOVAR},\t\n\t{\"BUZZY1\",\t\t20,\tIN_NOVAR},\t\n\t{\"RAMBO1\",     20,   IN_NOVAR},\t\t\t\n\t{\"RAMBO2\", \t\t20,   IN_NOVAR}, \n\t{\"RAMBO3\",     20,   IN_NOVAR},\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t{\"MYES1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHYES1\t\t\tMechanic: \"Yes sir!\"\n\t{\"MHOWDY1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHOWDY1\t\t\tMechanic: \"Howdy!\"\n\t{\"MRISE1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHRISE1\t\t\tMechanic: \"Rise 'n shine!\"\n\t{\"MHUH1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHUH1\t\t\tMechanic: \"Huh?\"\n\t{\"MHEAR1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHHEAR1\t\t\tMechanic: \"I Hear Ya!\"\n\t{\"MLAFF1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHLAFF1\t\t\tMechanic: guffaw\n\t{\"MBOSS1\",\t\t20,\tIN_NOVAR},\t// VOC_MECHBOSS1\t\t\tMechanic: \"Sure Thing, Boss!\"\n\t{\"MYEEHAW1\",\t20,\tIN_NOVAR},\t// VOC_MECHYEEHAW1\t\tMechanic: \"Yee Haw!\"\n\t{\"MHOTDIG1\",\t20,\tIN_NOVAR},\t// VOC_MECHHOTDIG1\t\tMechanic: \"Hot Diggity Dog!\"\n\t{\"MWRENCH1\",\t20,\tIN_NOVAR},\t// VOC_MECHWRENCH1\t\tMechanic: \"I'll get my wrench.\"\n\n\t{\"JBURN1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STBURN1\t\t\t\tShock Trooper: \"Burn baby burn!\"\n\t{\"JCHRGE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STCHRGE1\t\t\tShock Trooper: \"Fully charged!\"\n\t{\"JCRISP1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STCRISP1\t\t\tShock Trooper: \"Extra Crispy!\"\n\t{\"JDANCE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STDANCE1\t\t\tShock Trooper: \"Let's Dance!\"\n\t{\"JJUICE1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STJUICE1\t\t\tShock Trooper: \"Got juice?\"\n\t{\"JJUMP1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STJUMP1\t\t\t\tShock Trooper: \"Need a jump?\"\n\t{\"JLIGHT1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STLIGHT1\t\t\tShock Trooper: \"Lights out!\"\n\t{\"JPOWER1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STPOWER1\t\t\tShock Trooper: \"Power on!\"\n\t{\"JSHOCK1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STSHOCK1\t\t\tShock Trooper: \"Shocking!\"\n\t{\"JYES1\",\t\t20,\tIN_NOVAR},\t//\tVOC_STYES1\t\t\t\tShock Trooper: \"Yesssss!\"\n\n\t{\"CHROTNK1\",\t20,\tIN_NOVAR},\t// VOC_CHRONOTANK1\t\tChrono tank teleport\n\t{\"FIXIT1\",\t\t20,\tIN_NOVAR},\t// VOC_MECH_FIXIT1\t\tMechanic fixes something\n\t{\"MADCHRG2\",\t20,\tIN_NOVAR},\t// VOC_MAD_CHARGE\t\t\tMAD tank charges up\n\t{\"MADEXPLO\",\t20,\tIN_NOVAR},\t// VOC_MAD_EXPLODE\t\tMAD tank explodes\n\t{\"SHKTROP1\",\t20,\tIN_NOVAR},\t// VOC_SHOCK_TROOP1\t\tShock Trooper fires\n\n\t{\"BEACON\", \t\t10,\tIN_NOVAR},\t// VOC_BEACON\t\t\tBeacon sound.\n\n#endif\n};\n\n\n//\n// External handlers. MBL 06.17.2019\n//\nextern void On_Sound_Effect(int sound_index, int variation, COORDINATE coord, int house);\n// extern void On_Speech(int speech_index); MBL 02.06.2020\nextern void On_Speech(int speech_index, HouseClass *house);\nextern void On_Ping(const HouseClass* player_ptr, COORDINATE coord);\n\n\n\n/***********************************************************************************************\n * Voc_From_Name -- Fetch VocType from ASCII name specified.                                   *\n *                                                                                             *\n *    This will find the corresponding VocType from the ASCII string specified. It does this   *\n *    by finding a root filename that matches the string.                                      *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII string that will be converted into a VocType.        *\n *                                                                                             *\n * OUTPUT:  Returns with the VocType that matches the string specified. If no match could be   *\n *          found, then VOC_NONE is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVocType Voc_From_Name(char const * name)\n{\n\tif (name == NULL) return(VOC_NONE);\n\n\tfor (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) {\n\t\tif (stricmp(name, SoundEffectName[voc].Name) == 0) {\n\t\t\treturn(voc);\n\t\t}\n\t}\n\n\treturn(VOC_NONE);\n}\n\n\n/***********************************************************************************************\n * Voc_Name -- Fetches the name for the sound effect.                                          *\n *                                                                                             *\n *    This routine returns the descriptive name of the sound effect. Currently, this is just   *\n *    the root of the file name.                                                               *\n *                                                                                             *\n * INPUT:   voc   -- The VocType that the corresponding name is requested.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text string the represents the sound effect.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Voc_Name(VocType voc)\n{\n\tif (voc == VOC_NONE) return(\"none\");\n\treturn(SoundEffectName[voc].Name);\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- Plays a sound effect in the tactical map.                                   *\n *                                                                                             *\n *    This routine is used when a sound effect occurs in the game world. It handles fading     *\n *    the sound according to distance.                                                         *\n *                                                                                             *\n * INPUT:   voc   -- The sound effect number to play.                                          *\n *                                                                                             *\n *          coord -- The world location that the sound originates from.                        *\n *                                                                                             *\n *          variation   -- This is the optional variation number to use when playing special   *\n *                         sound effects that have variations. For normal sound effects, this  *\n *                         parameter is ignored.                                               *\n *                                                                                             *\n *          house -- This specifies the optional house override value to use when playing      *\n *                   sound effects that have a variation. If not specified, then the current   *\n *                   player is examined for the house variation to use.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   01/05/1995 JLB : Reduces sound more dramatically when off screen.                         *\n *   09/15/1996 JLB : Revamped volume logic.                                                   *\n *   11/01/1996 JLB : House override control.                                                  *\n *=============================================================================================*/\nvoid Sound_Effect(VocType voc, COORDINATE coord, int variation, HousesType house)\n{\n\t//\n\t// Intercept sound effect calls. MBL 06.17.2019\n\t//\n\tOn_Sound_Effect((int)voc, variation, coord, (int)house);\n\n#if 0\n\tCELL cell_pos = 0;\n\tint pan_value;\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn;\n\t}\n\tif (coord) {\n\t\tcell_pos = Coord_Cell(coord);\n\t}\n\n\tfixed volume = 1;\n\tpan_value = 0;\n\tif (coord && !Map.In_View(cell_pos)) {\n\t\tint distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W;\n\t\tfixed dfixed = fixed(distance, 128+64);\n\t\tdfixed.Sub_Saturate(1);\n\t\tvolume = fixed(1) - dfixed;\n\n\t\tpan_value  = Cell_X(cell_pos);\n\t\tpan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2);\n\t\tif (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) {\n\t\t\tpan_value *= 0x8000;\n\t\t\tpan_value /= (MAP_CELL_W >> 2);\n\t\t\tpan_value = Bound(pan_value, -0x7FFF, 0x7FFF);\n\t\t} else {\n\t\t\tpan_value  = 0;\n\t\t}\n\t}\n\n\tSound_Effect(voc, volume, variation, pan_value, house);\n#endif\n}\n\n\n/***********************************************************************************************\n * Sound_Effect -- General purpose sound player.                                               *\n *                                                                                             *\n *    This is used for general purpose sound effects. These are sounds that occur outside      *\n *    of the game world. They do not have a corresponding game world location as their source. *\n *                                                                                             *\n * INPUT:   voc      -- The sound effect number to play.                                       *\n *                                                                                             *\n *          volume   -- The volume to assign to this sound effect.                             *\n *                                                                                             *\n *          variation   -- This is the optional variation number to use when playing special   *\n *                         sound effects that have variations. For normal sound effects, this  *\n *                         parameter is ignored.                                               *\n *                                                                                             *\n *          house -- This specifies the optional house override value to use when playing      *\n *                   sound effects that have a variation. If not specified, then the current   *\n *                   player is examined for the house variation to use.                        *\n *                                                                                             *\n * OUTPUT:  Returns with the sound handle (-1 if no sound was played).                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *   11/12/1994 JLB : Handles cache logic.                                                     *\n *   05/04/1995 JLB : Variation adjustments.                                                   *\n *   11/01/1996 JLB : House override control.                                                  *\n *=============================================================================================*/\nint Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value, HousesType house)\n{\n\t//\n\t// Intercept sound effect calls. MBL 06.17.2019\n\t//\n\tpan_value;\n\tCOORDINATE coord = 0;\n\tOn_Sound_Effect((int)voc, variation, coord, (int)house);\n\n#if 0\n\tchar name[_MAX_FNAME+_MAX_EXT];\t\t\t\t// Working filename of sound effect.\n\n\tif (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tAlter the volume according to the game volume setting.\n\t*/\n\tvolume = volume * Options.Volume;\n\n\t/*\n\t**\tFetch a pointer to the sound effect data. Modify the sound as appropriate and desired.\n\t*/\n\tchar const * ext = \".AUD\";\n\tif (SoundEffectName[voc].Where == IN_VAR) {\n\n\t\t/*\n\t\t**\tIf there is no forced house, then use the current player\n\t\t**\tact like house.\n\t\t*/\n\t\tif (house == HOUSE_NONE) {\n\t\t\thouse = PlayerPtr->ActLike;\n\t\t}\n\n\t\t/*\n\t\t**\tChange the extension based on the variation and house accent requested.\n\t\t*/\n\t\tif (((1 << house) & HOUSEF_ALLIES) != 0) {\n\n\t\t\t/*\n\t\t\t**\tFor infantry, use a variation on the response. For vehicles, always\n\t\t\t**\tuse the vehicle response table.\n\t\t\t*/\n\t\t\tif (variation < 0) {\n\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\text = \".V00\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V02\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation % 2) {\n\t\t\t\t\text = \".V01\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V03\";\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (variation < 0) {\n\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\text = \".R00\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".R02\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation % 2) {\n\t\t\t\t\text = \".R01\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".R03\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);\n\tvoid const * ptr = MFCD::Retrieve(name);\n\n\t/*\n\t**\tIf the sound data pointer is not null, then presume that it is valid.\n\t*/\n\tif (ptr != NULL) {\n\t\tvolume.Sub_Saturate(1);\n\t\treturn(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value));\n\t}\n#endif \n\n\treturn(-1);\n}\n\n\n/*\n**\tThis elaborates all the EVA speech voices.\n*/\n/*static PG*/ char const * Speech[VOX_COUNT] =  {\n\t\"MISNWON1\",\t\t//\tVOX_ACCOMPLISHED\t\t\t\t\tmission accomplished\n\t\"MISNLST1\",\t\t//\tVOX_FAIL\t\t\t\t\t\t\t\tyour mission has failed\n\t\"PROGRES1\",\t\t//\tVOX_NO_FACTORY\t\t\t\t\t\tunable to comply, building in progress\n\t\"CONSCMP1\",\t\t//\tVOX_CONSTRUCTION\t\t\t\t\tconstruction complete\n\t\"UNITRDY1\",\t\t//\tVOX_UNIT_READY\t\t\t\t\t\tunit ready\n\t\"NEWOPT1\",\t\t//\tVOX_NEW_CONSTRUCT\t\t\t\t\tnew construction options\n\t\"NODEPLY1\",\t\t//\tVOX_DEPLOY\t\t\t\t\t\t\tcannot deploy here\n\t\"STRCKIL1\",\t\t//\tVOX_STRUCTURE_DESTROYED,\t\tstructure destroyed\n\t\"NOPOWR1\",\t\t//\tVOX_INSUFFICIENT_POWER,\t\t\tinsufficient power\n\t\"NOFUNDS1\",\t\t//\tVOX_NO_CASH\t\t\t\t\t\t\tinsufficient funds\n\t\"BCT1\",\t\t\t//\tVOX_CONTROL_EXIT\t\t\t\t\tbattle control terminated\n\t\"REINFOR1\",\t\t//\tVOX_REINFORCEMENTS\t\t\t\treinforcements have arrived\n\t\"CANCLD1\",\t\t//\tVOX_CANCELED\t\t\t\t\t\tcanceled\n\t\"ABLDGIN1\",\t\t//\tVOX_BUILDING\t\t\t\t\t\tbuilding\n\t\"LOPOWER1\",\t\t//\tVOX_LOW_POWER\t\t\t\t\t\tlow power\n\t\"NOFUNDS1\",\t\t//\tVOX_NEED_MO_MONEY\t\t\t\t\tinsufficent funds\n\t\"BASEATK1\",\t\t//\tVOX_BASE_UNDER_ATTACK\t\t\tour base is under attack\n\t\"NOBUILD1\",\t\t//\tVOX_UNABLE_TO_BUILD\t\t\t\tunable to build more\n\t\"PRIBLDG1\",\t\t//\tVOX_PRIMARY_SELECTED\t\t\t\tprimary building selected\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef ENGLISH\n\t\"TANK01\",\t\t// VOX_MADTANK_DEPLOYED\t\t\t\tM.A.D. Tank Deployed\n#else\n\t\"none\",\n#endif\n#else\n\t\"none\",\n#endif\n\t\"none\",\t\t\t//\tVOX_SOVIET_CAPTURED\t\t\t\tAllied building captured\n\t\"UNITLST1\",\t\t// VOX_UNIT_LOST\t\t\t\t\t\tunit lost\n\t\"SLCTTGT1\",\t\t// VOX_SELECT_TARGET\t\t\t\t\tselect target\n\t\"ENMYAPP1\",\t\t//\tVOX_PREPARE\t\t\t\t\t\t\tenemy approaching\n\t\"SILOND1\",\t\t//\tVOX_NEED_MO_CAPACITY\t\t\t\tsilos needed\n\t\"ONHOLD1\",\t\t//\tVOX_SUSPENDED\t\t\t\t\t\ton hold\n\t\"REPAIR1\",\t\t//\tVOX_REPAIRING\t\t\t\t\t\trepairing\n\t\"none\",\n\t\"none\",\n\t\"AUNITL1\",\t\t//\tVOX_AIRCRAFT_LOST\t\t\t\t\tairborne unit lost\n\t\"none\",\n\t\"AAPPRO1\",\t\t//\tVOX_ALLIED_FORCES_APPROACHING\tallied forces approaching\n\t\"AARRIVE1\",\t\t// VOX_ALLIED_APPROACHING\t\t\tallied reinforcements have arrived\n\t\"none\",\n\t\"none\",\n\t\"BLDGINF1\",\t\t// VOX_BUILDING_INFILTRATED\t\tbuilding infiltrated\n\t\"CHROCHR1\",\t\t// VOX_CHRONO_CHARGING\t\t\t\tchronosphere charging\n\t\"CHRORDY1\",\t\t// VOX_CHRONO_READY\t\t\t\t\tchronosphere ready\n\t\"CHROYES1\",\t\t// VOX_CHRONO_TEST\t\t\t\t\tchronosphere test successful\n\t\"CMDCNTR1\",\t\t//\tVOX_HQ_UNDER_ATTACK\t\t\t\tcommand center under attack\n\t\"CNTLDED1\",\t\t//\tVOX_CENTER_DEACTIVATED\t\t\tcontrol center deactivated\n\t\"CONVYAP1\",\t\t//\tVOX_CONVOY_APPROACHING\t\t\tconvoy approaching\n\t\"CONVLST1\",\t\t// VOX_CONVOY_UNIT_LOST\t\t\t\tconvoy unit lost\n\t\"XPLOPLC1\",\t\t//\tVOX_EXPLOSIVE_PLACED\t\t\t\texplosive charge placed\n\t\"CREDIT1\",\t\t// VOX_MONEY_STOLEN\t\t\t\t\tcredits stolen\n\t\"NAVYLST1\",\t\t// VOX_SHIP_LOST\t\t\t\t\t\tnaval unit lost\n\t\"SATLNCH1\",\t\t//\tVOX_SATALITE_LAUNCHED\t\t\tsatalite launched\n\t\"PULSE1\",\t\t//\tVOX_SONAR_AVAILABLE\t\t\t\tsonar pulse available\n\t\"none\",\n\t\"SOVFAPP1\",\t\t//\tVOX_SOVIET_FORCES_APPROACHING\tsoviet forces approaching\n\t\"SOVREIN1\",\t\t// VOX_SOVIET_REINFROCEMENTS\t\tsoviet reinforcements have arrived\n\t\"TRAIN1\",\t\t//\tVOX_TRAINING\t\t\t\t\t\ttraining\n\t\"AREADY1\",\t\t//\tVOX_ABOMB_READY\n\t\"ALAUNCH1\",\t\t//\tVOX_ABOMB_LAUNCH\n\t\"AARRIVN1\",\t\t//\tVOX_ALLIES_N\n\t\"AARRIVS1\",\t\t//\tVOX_ALLIES_S\n\t\"AARIVE1\",\t\t//\tVOX_ALLIES_E\n\t\"AARRIVW1\",\t\t//\tVOX_ALLIES_W\n\t\"1OBJMET1\",\t\t//\tVOX_OBJECTIVE1\n\t\"2OBJMET1\",\t\t//\tVOX_OBJECTIVE2\n\t\"3OBJMET1\",\t\t//\tVOX_OBJECTIVE3\n\t\"IRONCHG1\",\t\t//\tVOX_IRON_CHARGING\n\t\"IRONRDY1\",\t\t//\tVOX_IRON_READY\n\t\"KOSYRES1\",\t\t//\tVOX_RESCUED\n\t\"OBJNMET1\",\t\t//\tVOX_OBJECTIVE_NOT\n\t\"FLAREN1\",\t\t//\tVOX_SIGNAL_N\n\t\"FLARES1\",\t\t//\tVOX_SIGNAL_S\n\t\"FLAREE1\",\t\t//\tVOX_SIGNAL_E\n\t\"FLAREW1\",\t\t//\tVOX_SIGNAL_W\n\t\"SPYPLN1\",\t\t//\tVOX_SPY_PLANE\n\t\"TANYAF1\",\t\t//\tVOX_FREED\n\t\"ARMORUP1\",\t\t//\tVOX_UPGRADE_ARMOR\n\t\"FIREPO1\",\t\t//\tVOX_UPGRADE_FIREPOWER\n\t\"UNITSPD1\",\t\t//\tVOX_UPGRADE_SPEED\n\t\"MTIMEIN1\",\t\t//\tVOX_MISSION_TIMER\n\t\"UNITFUL1\",\t\t//\tVOX_UNIT_FULL\n\t\"UNITREP1\",\t\t//\tVOX_UNIT_REPAIRED\n\t\"40MINR\",\t\t//\tVOX_TIME_40\n\t\"30MINR\",\t\t//\tVOX_TIME_30\n\t\"20MINR\",\t\t//\tVOX_TIME_20\n\t\"10MINR\",\t\t//\tVOX_TIME_10\n\t\"5MINR\",\t\t\t//\tVOX_TIME_5\n\t\"4MINR\",\t\t\t//\tVOX_TIME_4\n\t\"3MINR\",\t\t\t//\tVOX_TIME_3\n\t\"2MINR\",\t\t\t//\tVOX_TIME_2\n\t\"1MINR\",\t\t\t//\tVOX_TIME_1\n\t\"TIMERNO1\",\t\t//\tVOX_TIME_STOP\n\t\"UNITSLD1\",\t\t//\tVOX_UNIT_SOLD\n\t\"TIMERGO1\",\t\t//\tVOX_TIMER_STARTED\n\t\"TARGRES1\",\t\t//\tVOX_TARGET_RESCUED\n\t\"TARGFRE1\",\t\t//\tVOX_TARGET_FREED\n\t\"TANYAR1\",\t\t//\tVOX_TANYA_RESCUED\n\t\"STRUSLD1\",\t\t//\tVOX_STRUCTURE_SOLD\n\t\"SOVFORC1\",\t\t//\tVOX_SOVIET_FORCES_FALLEN\n\t\"SOVEMP1\",\t\t//\tVOX_SOVIET_SELECTED\n\t\"SOVEFAL1\",\t\t//\tVOX_SOVIET_EMPIRE_FALLEN\n\t\"OPTERM1\",\t\t//\tVOX_OPERATION_TERMINATED\n\t\"OBJRCH1\",\t\t//\tVOX_OBJECTIVE_REACHED\n\t\"OBJNRCH1\",\t\t//\tVOX_OBJECTIVE_NOT_REACHED\n\t\"OBJMET1\",\t\t//\tVOX_OBJECTIVE_MET\n\t\"MERCR1\",\t\t//\tVOX_MERCENARY_RESCUED\n\t\"MERCF1\",\t\t//\tVOX_MERCENARY_FREED\n\t\"KOSYFRE1\",\t\t//\tVOX_KOSOYGEN_FREED\n\t\"FLARE1\",\t\t//\tVOX_FLARE_DETECTED\n\t\"COMNDOR1\",\t\t//\tVOX_COMMANDO_RESCUED\n\t\"COMNDOF1\",\t\t//\tVOX_COMMANDO_FREED\n\t\"BLDGPRG1\",\t\t//\tVOX_BUILDING_IN_PROGRESS\n\t\"ATPREP1\",\t\t//\tVOX_ATOM_PREPPING\n\t\"ASELECT1\",\t\t//\tVOX_ALLIED_SELECTED\n\t\"APREP1\",\t\t//\tVOX_ABOMB_PREPPING\n\t\"ATLNCH1\",\t\t//\tVOX_ATOM_LAUNCHED\n\t\"AFALLEN1\",\t\t//\tVOX_ALLIED_FORCES_FALLEN\n\t\"AAVAIL1\",\t\t//\tVOX_ABOMB_AVAILABLE\n\t\"AARRIVE1\",\t\t//\tVOX_ALLIED_REINFORCEMENTS\n\t\"SAVE1\",\t\t\t//\tVOX_MISSION_SAVED\n\t\"LOAD1\"\t\t\t//\tVOX_MISSION_LOADED\n};\n\n\nstatic VoxType CurrentVoice = VOX_NONE;\n\n\n/***********************************************************************************************\n * Speech_Name -- Fetches the name for the voice specified.                                    *\n *                                                                                             *\n *    Use this routine to fetch the ASCII name of the speech id specified. Typical use of this *\n *    would be to build a displayable list of the speech types. The trigger system uses this   *\n *    so that a speech type can be selected.                                                   *\n *                                                                                             *\n * INPUT:   speech   -- The speech type id to convert to ASCII string.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the speech ASCII representation of the speech id type.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Speech_Name(VoxType speech)\n{\n\tif (speech == VOX_NONE) return(\"none\");\n\treturn(Speech[speech]);\n}\n\n\n/***********************************************************************************************\n * Speak -- Computer speaks to the player.                                                     *\n *                                                                                             *\n *    This routine is used to have the game computer (EVA) speak to the player.                *\n *                                                                                             *\n * INPUT:   voice -- The voice number to speak (see defines.h).                                *\n *                                                                                             *\n * OUTPUT:  Returns with the handle of the playing speech (-1 if no voice started).            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n// void Speak(VoxType voice) // MBL 02.06.2020\nvoid Speak(VoxType voice, HouseClass *house, COORDINATE coord)\n{\n\t// MBL 06.17.2019\n\tif (voice == VOX_NONE)\n\t{\n\t\treturn;\n\t}\n\n\t//\n\t// Intercept speech calls. MBL 06.17.2019\n\t//\n\n\t// On_Speech((int)voice); // MBL 02.06.2020\n\tOn_Speech((int)voice, house);\n\tif (coord) {\n\t\tOn_Ping(house, coord);\n\t}\n\n#if 0\n\tif (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {\n\t\tSpeakQueue = voice;\n\t\tSpeak_AI();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Speak_AI -- Handles starting the EVA voices.                                                *\n *                                                                                             *\n *    This starts the EVA voice talking as well. If there is any speech request in the queue,  *\n *    it will be started when the current voice is finished. Call this routine as often as     *\n *    possible (once per game tick is sufficient).                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *   10/11/1996 JLB : Handles multiple speech buffers.                                         *\n *=============================================================================================*/\nvoid Speak_AI(void)\n{\n// MBL 06.17.2019 KO\n#if 0\n\tstatic int _index = 0;\n\tif (Debug_Quiet || SampleType == 0) return;\n\n\tif (!Is_Sample_Playing(SpeechBuffer[_index])) {\n\t\tCurrentVoice = VOX_NONE;\n\t\tif (SpeakQueue != VOX_NONE) {\n\n\t\t\t/*\n\t\t\t**\tTry to find a previously loaded copy of the EVA speech in one of the\n\t\t\t**\tspeech buffers.\n\t\t\t*/\n\t\t\tvoid const * speech = NULL;\n\t\t\tfor (int index = 0; index < ARRAY_SIZE(SpeechRecord); index++) {\n\t\t\t\tif (SpeechRecord[index] == SpeakQueue) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a previous copy could not be located, then load the requested\n\t\t\t**\tvoice into the oldest buffer available.\n\t\t\t*/\n\t\t\tif (speech == NULL) {\n\t\t\t\t_index = (_index + 1) % ARRAY_SIZE(SpeechRecord);\n\n\t\t\t\tchar name[_MAX_FNAME+_MAX_EXT];\n\n\t\t\t\t_makepath(name, NULL, NULL, Speech[SpeakQueue], \".AUD\");\n\t\t\t\tCCFileClass file(name);\n\t\t\t\tif (file.Is_Available() && file.Read(SpeechBuffer[_index], SPEECH_BUFFER_SIZE)) {\n\t\t\t\t\tspeech = SpeechBuffer[_index];\n\t\t\t\t\tSpeechRecord[_index] = SpeakQueue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince the speech file was loaded, play it.\n\t\t\t*/\n\t\t\tif (speech != NULL) {\n\t\t\t\tPlay_Sample(speech, 254, Options.Volume * 256);\n\t\t\t\tCurrentVoice = SpeakQueue;\n\t\t\t}\n\n\t\t\tSpeakQueue = VOX_NONE;\n\t\t}\n\t}\n#endif\n\n\t// MBL 06.18.2019\n\tif (SpeakQueue != VOX_NONE) \n\t{\n\t\t// On_Speech((int)SpeakQueue); // MBL 02.06.2020\n\t\tOn_Speech((int)SpeakQueue, NULL);\n\t\tSpeakQueue = VOX_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * Stop_Speaking -- Forces the EVA voice to stop talking.                                      *\n *                                                                                             *\n *    Use this routine to immediately stop the EVA voice from speaking. It also clears out     *\n *    the pending voice queue.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Stop_Speaking(void)\n{\n\tSpeakQueue = VOX_NONE;\n\tStop_Sample_Playing(SpeechBuffer);\n}\n\n\n/***********************************************************************************************\n * Is_Speaking -- Checks to see if the eva voice is still playing.                             *\n *                                                                                             *\n *    Call this routine when the EVA voice being played needs to be checked. A typical use     *\n *    of this would be when some action needs to be delayed until the voice has finished --    *\n *    say the end of the game.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the EVA voice still playing?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Is_Speaking(void)\n{\n\tSpeak_AI();\n\tif (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/AUDIO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\audio.h_v   4.43   05 Jul 1996 17:58:10   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : AUDIO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 21, 1994                                                *\n *                                                                                             *\n *                  Last Update : June 21, 1994   [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef AUDIO_H\n#define AUDIO_H\n\n#include\t\"memory.h\"\n\nclass AudioClass {\n\t\tchar const * Name;\t// Name of audio asset.\n\t\tvoid const * Data;\t// Loaded audio data.\n\t\tint Handle;\t\t\t\t// Handle of asset (as it is playing).\n\t\tMemoryClass *Mem;\t\t// Pointer to memory handler class.\n\t\tunsigned IsMIDI:1;\t// Is this a midi file?\n\n\tpublic:\n\t\tAudioClass(void);\n\t\tAudioClass(char const *name, MemoryClass &mem);\n\t\tvirtual ~AudioClass(void);\n\n\t\tbool Load(char const *name = 0);\n\t\tbool Free(void);\n\t\tbool Play(int volume = 0xFF);\n\t\tbool Stop(void);\n\t\tbool Pause(void);\n\t\tbool Resume(void);\n\t\tbool Set_Name(char const *name);\n\t\tbool Is_Playing(void) const;\n\t\tbool Is_Loaded(void) const;\n\t\tbool Is_MIDI(void) const;\n};\n\ninline AudioClass::AudioClass(void)\n{\n\tName = 0; \n\tData = 0; \n\tMem = 0;\n\tHandle = -1;\n};\n\ninline AudioClass::AudioClass(char const *name, MemoryClass &mem) \n{\n\tif (mem) {\n\t\tMem = &mem;\n\t} else {\n\t\tMem = &::Mem;\t\t// Uses global default memory handler.\n\t}\n\tName = strdup(name);\n\tData = 0;\n\tHandle = -1;\n};\n\ninline AudioClass::~AudioClass(void)\n{\n\tif (GameActive) {\n\t\tif (Name) free(Name);\n\t\tif (Data) Mem->Free(Data);\n\t\tName = 0;\n\t\tData = 0;\n\t\tHandle = -1;\n\t}\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/B64PIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/B64PIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64PIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64Pipe::Put -- Processes a block of data through the pipe.                            *\n *   Base64Pipe::Flush -- Flushes the final pending data through the pipe.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"b64pipe.h\"\n#include\t\"base64.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Base64Pipe::Put -- Processes a block of data through the pipe.                              *\n *                                                                                             *\n *    This will take the data submitted and either Base64 encode or decode it (as specified    *\n *    in the pipe's constructor). The nature of Base64 encoding means that the data will       *\n *    grow 30% in size when encoding and decrease by a like amount when decoding.              *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be translated.                                  *\n *                                                                                             *\n *          length   -- The number of bytes to translate.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final end of     *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Pipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tint total = 0;\n\n\tchar * from;\n\tint fromsize;\n\tchar * to;\n\tint tosize;\n\n\tif (Control == ENCODE) {\n\t\tfrom = PBuffer;\n\t\tfromsize = sizeof(PBuffer);\n\t\tto = CBuffer;\n\t\ttosize = sizeof(CBuffer);\n\t} else {\n\t\tfrom = CBuffer;\n\t\tfromsize = sizeof(CBuffer);\n\t\tto = PBuffer;\n\t\ttosize = sizeof(PBuffer);\n\t}\n\n\tif (Counter > 0) {\n\t\tint len = (slen < (fromsize-Counter)) ? slen : (fromsize-Counter);\n\t\tmemmove(&from[Counter], source, len);\n\t\tCounter += len;\n\t\tslen -= len;\n\t\tsource = ((char *)source) + len;\n\n\t\tif (Counter == fromsize) {\n\t\t\tint outcount;\n\t\t\tif (Control == ENCODE) {\n\t\t\t\toutcount = Base64_Encode(from, fromsize, to, tosize);\n\t\t\t} else {\n\t\t\t\toutcount = Base64_Decode(from, fromsize, to, tosize);\n\t\t\t}\n\t\t\ttotal += Pipe::Put(to, outcount);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\twhile (slen >= fromsize) {\n\t\tint outcount;\n\t\tif (Control == ENCODE) {\n\t\t\toutcount = Base64_Encode(source, fromsize, to, tosize);\n\t\t} else {\n\t\t\toutcount = Base64_Decode(source, fromsize, to, tosize);\n\t\t}\n\t\tsource = ((char *)source) + fromsize;\n\t\ttotal += Pipe::Put(to, outcount);\n\t\tslen -= fromsize;\n\t}\n\n\tif (slen > 0) {\n\t\tmemmove(from, source, slen);\n\t\tCounter = slen;\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * Base64Pipe::Flush -- Flushes the final pending data through the pipe.                       *\n *                                                                                             *\n *    If there is any non-processed data accumulated in the holding buffer (quite likely when  *\n *    encoding), then it will be processed and flushed out the end of the pipe.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output at the far distant final end of the pipe   *\n *          chain.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Pipe::Flush(void)\n{\n\tint len = 0;\n\n\tif (Counter) {\n\t\tif (Control == ENCODE) {\n\t\t\tint chars = Base64_Encode(PBuffer, Counter, CBuffer, sizeof(CBuffer));\n\t\t\tlen += Pipe::Put(CBuffer, chars);\n\t\t} else {\n\t\t\tint chars = Base64_Decode(CBuffer, Counter, PBuffer, sizeof(PBuffer));\n\t\t\tlen += Pipe::Put(PBuffer, chars);\n\t\t}\n\t\tCounter = 0;\n\t}\n\tlen += Pipe::Flush();\n\treturn(len);\n}\n\n\n\n"
  },
  {
    "path": "REDALERT/B64PIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/B64PIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64PIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef B64PIPE_H\n#define B64PIPE_H\n\n#include\t\"pipe.h\"\n\n/*\n**\tThis class performs Base64 encoding/decoding to the data that is piped through. Note that\n**\tencoded data will grow in size by about 30%. The reverse occurs when decoding.\n*/\nclass Base64Pipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CodeControl {\n\t\t\tENCODE,\n\t\t\tDECODE\n\t\t} CodeControl;\n\n\t\tBase64Pipe(CodeControl control) : Control(control), Counter(0) {}\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIndicates if this is for encoding or decoding of Base64 data.\n\t\t*/\n\t\tCodeControl Control;\n\n\t\t/*\n\t\t**\tThe counter of the number of accumulated bytes pending for processing.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tBuffer that holds the Base64 coded bytes. This will be the staging buffer if\n\t\t**\tthis is for a decoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar CBuffer[4];\n\n\t\t/*\n\t\t**\tBuffer that holds the plain bytes. This will be the staging buffer if this\n\t\t**\tis for an encoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar PBuffer[3];\n\n\t\t/*\n\t\t**\tExplicitly disable the copy constructor and the assignment operator.\n\t\t*/\n\t\tBase64Pipe(Base64Pipe & rvalue);\n\t\tBase64Pipe & operator = (Base64Pipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/B64STRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/B64STRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64STRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"b64straw.h\"\n#include\t\"base64.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding.                     *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested and perform any conversion as      *\n *    necessary upon the data. The nature of Base 64 encoding means that the data will         *\n *    increase in size by 30% when encoding and decrease in like manner when decoding.         *\n *                                                                                             *\n * INPUT:   source   -- The buffer to hold the processed data.                                 *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the buffer. If the number is less     *\n *          than requested, then this indicates that the data stream has been exhausted.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64Straw::Get(void * source, int slen)\n{\n\tint total = 0;\n\n\tchar * from;\n\tint fromsize;\n\tchar * to;\n\tint tosize;\n\n\tif (Control == ENCODE) {\n\t\tfrom = PBuffer;\n\t\tfromsize = sizeof(PBuffer);\n\t\tto = CBuffer;\n\t\ttosize = sizeof(CBuffer);\n\t} else {\n\t\tfrom = CBuffer;\n\t\tfromsize = sizeof(CBuffer);\n\t\tto = PBuffer;\n\t\ttosize = sizeof(PBuffer);\n\t}\n\n\t/*\n\t**\tProcess the byte request in code blocks until there are either\n\t**\tno more source bytes available or the request has been fulfilled.\n\t*/\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tTransfer any processed bytes available to the request buffer.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tmemmove(source, &to[tosize-Counter], len);\n\t\t\tCounter -= len;\n\t\t\tslen -= len;\n\t\t\tsource = ((char *)source) + len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\t/*\n\t\t**\tMore bytes are needed, so fetch and process another base 64 block.\n\t\t*/\n\t\tint incount = Straw::Get(from, fromsize);\n\t\tif (Control == ENCODE) {\n\t\t\tCounter = Base64_Encode(from, incount, to, tosize);\n\t\t} else {\n\t\t\tCounter = Base64_Decode(from, incount, to, tosize);\n\t\t}\n\t\tif (Counter == 0) break;\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/B64STRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/B64STRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : B64STRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef B64STRAW_H\n#define B64STRAW_H\n\n#include\t\"straw.h\"\n\n/*\n**\tPerforms Base 64 encoding/decoding on the data that is drawn through the straw. Note that\n**\tencoding increases the data size by about 30%. The reverse occurs when decoding.\n*/\nclass Base64Straw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CodeControl {\n\t\t\tENCODE,\n\t\t\tDECODE\n\t\t} CodeControl;\n\n\t\tBase64Straw(CodeControl control) : Control(control), Counter(0) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIndicates if this is for encoding or decoding of Base64 data.\n\t\t*/\n\t\tCodeControl Control;\n\n\t\t/*\n\t\t**\tThe counter of the number of accumulated bytes pending for processing.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tBuffer that holds the Base64 coded bytes. This will be the staging buffer if\n\t\t**\tthis is for a decoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar CBuffer[4];\n\n\t\t/*\n\t\t**\tBuffer that holds the plain bytes. This will be the staging buffer if this\n\t\t**\tis for an encoding process. Otherwise, it will be used as a scratch buffer.\n\t\t*/\n\t\tchar PBuffer[3];\n\n\t\t/*\n\t\t**\tExplicitly disable the copy constructor and the assignment operator.\n\t\t*/\n\t\tBase64Straw(Base64Straw & rvalue);\n\t\tBase64Straw & operator = (Base64Straw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/BAR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BAR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BAR.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/16/96                                                     *\n *                                                                                             *\n *                  Last Update : August 16, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not.       *\n *   ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to.          *\n *   ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object.                *\n *   ProgressBarClass::Redraw -- Redraw the bargraph.                                          *\n *   ProgressBarClass::Set_Limit -- Set the logic tracking value.                              *\n *   ProgressBarClass::Update -- Update the value and redraw as necessary.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"bar.h\"\n#include\t\"fixed.h\"\n\n\n/***********************************************************************************************\n * ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object.                  *\n *                                                                                             *\n *    This is the constructor for the bargraph object. It establishes the dimensions and       *\n *    coordinate of the bargraph as well as the colors it will use when drawn.                 *\n *                                                                                             *\n * INPUT:   w,y      -- Pixel coordinate of the upper left corner of the bargraph.             *\n *                                                                                             *\n *          width,height   -- Dimensions of the bargraph.                                      *\n *                                                                                             *\n *          forecolor   -- The color to use for the filled portion of the bargraph.            *\n *                                                                                             *\n *          backcolor   -- The color to use for the non-filled portion of the bargraph.        *\n *                                                                                             *\n *          bordercolor -- Optional border color. If not zero, then the bargraph will be       *\n *                         outlined with this color.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nProgressBarClass::ProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor) :\n\tX(x),\n\tY(y),\n\tWidth(width),\n\tHeight(height),\n\tBarColor(forecolor),\n\tBackColor(backcolor),\n\tBorderColor(bordercolor),\n\tCurrentValue(0),\n\tLastDisplayCurrent(0),\n\tIsDrawn(false)\n{\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not.         *\n *                                                                                             *\n *    If the bargraph is oriented horizontally, then this function will return TRUE.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this bargraph horizontal?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ProgressBarClass::Is_Horizontal(void) const\n{\n\tif (Width > Height) return(true);\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Update -- Update the value and redraw as necessary.                       *\n *                                                                                             *\n *    This will update the value of the bargraph to the fill ratio specified and then          *\n *    redraw it if required. Very small changes to the bargraph value might not result in a    *\n *    visual change.                                                                           *\n *                                                                                             *\n * INPUT:   value -- The new value to assign to this bargraph.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   bool; Did this update result in a redraw?                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ProgressBarClass::Update(fixed value)\n{\n\tCurrentValue = value;\n\n\tif (!IsDrawn || value - LastDisplayCurrent >= fixed(1, 10)) {\n\t\tRedraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to.            *\n *                                                                                             *\n *    This routine will draw a border around the bargraph if this bargraph has a color         *\n *    specified for the border.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ProgressBarClass::Outline(void) const\n{\n\tif (Is_Outlined()) {\n\t\tLogicPage->Draw_Line(X, Y, X+Width, Y, BorderColor);\n\t\tLogicPage->Draw_Line(X, Y, X, Y+Height, BorderColor);\n\t\tLogicPage->Draw_Line(X, Y+Height, X, Y+Height, BorderColor);\n\t\tLogicPage->Draw_Line(X+Width, Y, X+Width, Y+Height, BorderColor);\n\t}\n}\n\n\n/***********************************************************************************************\n * ProgressBarClass::Redraw -- Redraw the bargraph.                                            *\n *                                                                                             *\n *    This will redraw the entire bargraph.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ProgressBarClass::Redraw(void) const\n{\n\tHide_Mouse();\n\n\tOutline();\n\n\t/*\n\t**\tDetermine the inner dimensions of the bargraph. This will be\n\t**\tsomewhat smaller than indicated if it has a border.\n\t*/\n\tint x = X;\n\tint y = Y;\n\tint w = Width;\n\tint h = Height;\n\tif (Is_Outlined()) {\n\t\tx += 1;\n\t\ty += 1;\n\t\tw -= 2;\n\t\th -= 2;\n\t}\n\n\t/*\n\t**\tThe working \"length\" of the bargraph is dependant on whether the\n\t**\tbargraph is horizontal or vertical.\n\t*/\n\tint size = Is_Horizontal() ? w : h;\n\n\t/*\n\t**\tDetermine the number of pixels to fill in the bargraph depending on the\n\t**\tsize of the internal value. The larger the internal value the more\n\t**\tfilled the bargraph becomes.\n\t*/\n\tint fill = CurrentValue * size;\n\n\t/*\n\t**\tDraw the filled portion of the bargraph if there is any pixels to draw.\n\t*/\n\tif (fill > 0) {\n\t\tif (Is_Horizontal()) {\n\t\t\tLogicPage->Fill_Rect(x, y, x+fill, y+h, BarColor);\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y+fill, x+w, y+h, BarColor);\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the unfilled portion of the bargraph if there are any pixels to\n\t**\tdraw of it.\n\t*/\n\tif (w-fill > 0) {\n\t\tif (Is_Horizontal()) {\n\t\t\tLogicPage->Fill_Rect(x+fill, y, x+w, y+h, BackColor);\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y, x+w, y+fill-1, BackColor);\n\t\t}\n\t}\n\n\tShow_Mouse();\n\n\tProgressBarClass * me = (ProgressBarClass *)this;\n\tme->LastDisplayCurrent = CurrentValue;\n\tme->IsDrawn = true;\n}\n"
  },
  {
    "path": "REDALERT/BAR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BAR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BAR.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/16/96                                                     *\n *                                                                                             *\n *                  Last Update : August 16, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BAR_H\n#define BAR_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include \"fixed.h\"\n\n\n/*\n**\tThis is a manager for a progress (or other) bargraph. Such a graph consists of a fill\n**\tand a background region. The fill percentage of the bargraph is controlled by an\n**\tupdate value. The bargraph can be optionally outlined.\n*/\nclass ProgressBarClass\n{\n\tpublic:\n\t\tProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor=0);\n\n\t\tbool Update(fixed value);\n\t\tvoid Redraw(void) const;\n\n\tprivate:\n\n\t\tvoid Outline(void) const;\n\t\tbool Is_Horizontal(void) const;\n\t\tbool Is_Outlined(void) const {return(BorderColor != 0);}\n\n\t\t/*\n\t\t**\tThis is the upper left coordinates of the bargraph.\n\t\t*/\n\t\tint X,Y;\n\n\t\t/*\n\t\t**\tThis is the dimensions of the bargraph.\n\t\t*/\n\t\tint Width, Height;\n\n\t\t/*\n\t\t**\tThese are the colors to use when drawing the progress bar.\n\t\t*/\n\t\tint BarColor;\n\t\tint BackColor;\n\t\tint BorderColor;\n\n\t\t/*\n\t\t**\tThis is the current value of the bargraph.\n\t\t*/\n\t\tfixed CurrentValue;\n\n\t\t/*\n\t\t**\tThis is the current value as of the last time the bargraph was rendered.\n\t\t*/\n\t\tfixed LastDisplayCurrent;\n\n\t\t/*\n\t\t**\tIf the bargraph has been drawn at least once, then this flag will\n\t\t**\tbe true.\n\t\t*/\n\t\tunsigned IsDrawn:1;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/BASE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BASE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : 03/27/95                                                     *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BaseClass::Get_Building -- Returns ptr to the built building for the given node           *\n *   BaseClass::Get_Node -- Finds the node that matches the cell specified.                    *\n *   BaseClass::Get_Node -- Returns ptr to the node corresponding to given object              *\n *   BaseClass::Is_Built -- Tells if given item in the list has been built yet                 *\n *   BaseClass::Is_Node -- Tells if the given building is part of our base list                *\n *   BaseClass::Load -- loads from a saved game file                                           *\n *   BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built          *\n *   BaseClass::Read_INI -- INI reading routine                                                *\n *   BaseClass::Save -- saves to a saved game file                                             *\n *   BaseClass::Write_INI -- Writes all the base information to the INI database.              *\n *   BaseNodeClass::operator != -- inequality operator                                         *\n *   BaseNodeClass::operator == -- equality operator                                           *\n *   BaseNodeClass::operator > -- greater-than operator                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator == -- equality operator                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = equal, false = not equal                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator == (BaseNodeClass const & node)\n{\n\treturn(Type == node.Type && Cell == node.Cell);\n}\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator != -- inequality operator                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      comparison result                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator !=(BaseNodeClass const & node)\n{\n\treturn(!(*this == node));\n}\n\n\n/***********************************************************************************************\n * BaseNodeClass::operator > -- greater-than operator                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      node      node to test against                                                         *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      comparison result                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint BaseNodeClass::operator > (BaseNodeClass const & )\n{\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Load -- loads from a saved game file                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      file      open file                                                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/04/1996 JLB : Converted to demand driven data source.                                  *\n *=============================================================================================*/\nbool BaseClass::Load(Straw & file)\n{\n\tint num_struct;\n\tint i;\n\tBaseNodeClass node;\n\n\t/*\n\t** Read in & check the size of this class\n\t*/\n\tif (file.Get(&i, sizeof(i)) != sizeof(i)) {\n\t\treturn(false);\n\t}\n\n\tif (i != sizeof(*this)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read in the House & the number of structures in the base\n\t*/\n\tif (file.Get(&House, sizeof(House)) != sizeof(House)) {\n\t\treturn(false);\n\t}\n\n\tif (file.Get(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read each node entry & add it to the list\n\t*/\n\tfor (i = 0; i < num_struct; i++) {\n\t\tif (file.Get(&node, sizeof(node)) != sizeof(node)) {\n\t\t\treturn(false);\n\t\t}\n\t\tNodes.Add(node);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Save -- saves to a saved game file                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      file      open file                                                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/04/1996 JLB : Converted to supply driven data output.                                  *\n *=============================================================================================*/\nbool BaseClass::Save(Pipe & file) const\n{\n\tint num_struct;\n\tint i;\n\tBaseNodeClass node;\n\n\t/*\n\t** Write the size of this class\n\t*/\n\ti = sizeof(*this);\n\tfile.Put(&i, sizeof(i));\n\n\t/*\n\t** Write the House & the number of structures in the base\n\t*/\n\tfile.Put(&House, sizeof(House));\n\n\tnum_struct = Nodes.Count();\n\tfile.Put(&num_struct, sizeof(num_struct));\n\n\t/*\n\t** Write each node entry\n\t*/\n\tfor (i = 0; i < num_struct; i++) {\n\t\tnode = Nodes[i];\n\t\tfile.Put(&node, sizeof(node));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Is_Built -- Tells if given item in the list has been built yet                   *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      index      index into base list                                                        *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = yes, false = no                                                                 *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool BaseClass::Is_Built(int index) const\n{\n\tif (Get_Building(index) != NULL) {\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Building -- Returns ptr to the built building for the given node             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to already-built building, NULL if none                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   07/30/1996 JLB : Handle arbitrary overlapper list length.                                 *\n *=============================================================================================*/\nBuildingClass * BaseClass::Get_Building(int index) const\n{\n\tObjectClass * obj[1 + ARRAY_SIZE(Map[(CELL)0].Overlapper)];\n\n\t/*\n\t** Check the location on the map where this building should be; if it's\n\t** there, return a pointer to it.\n\t*/\n\tCELL cell = Nodes[index].Cell;\n\n\tobj[0] = Map[cell].Cell_Building();\n\tint count = 1;\n\tfor (int xindex = 0; xindex < ARRAY_SIZE(Map[cell].Overlapper); xindex++) {\n\t\tif (Map[cell].Overlapper[xindex] != NULL) {\n\t\t\tobj[count++] = Map[cell].Overlapper[xindex];\n\t\t}\n\t}\n\n\tBuildingClass * bldg = NULL;\n\tfor (int i = 0; i < count; i++) {\n\t\tif (obj[i] &&\n\t\t\tCoord_Cell(obj[i]->Coord) == Nodes[index].Cell &&\n\t\t\tobj[i]->What_Am_I() == RTTI_BUILDING &&\n\t\t\t((BuildingClass *)obj[i])->Class->Type == Nodes[index].Type) {\n\n\t\t\t\tbldg = (BuildingClass *)obj[i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(bldg);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Is_Node -- Tells if the given building is part of our base list                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = building is a node in the list, false = isn't                                   *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool BaseClass::Is_Node(BuildingClass const * obj)\n{\n\tif (Get_Node(obj) != NULL) {\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Node -- Returns ptr to the node corresponding to given object                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      pointer to building to test                                                   *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to node                                                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Get_Node(BuildingClass const * obj)\n{\n\tfor (int i = 0; i < Nodes.Count(); i++) {\n\t\tif (obj->Class->Type == Nodes[i].Type && Coord_Cell(obj->Coord) == Nodes[i].Cell) {\n\t\t\treturn(&Nodes[i]);\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Get_Node -- Finds the node that matches the cell specified.                      *\n *                                                                                             *\n *    This routine is used to find a matching node the corresponds to the cell specified.      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to use in finding a match.                                       *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the matching node if found. If not found, then NULL is        *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Get_Node(CELL cell)\n{\n\tfor (int index = 0; index < Nodes.Count(); index++) {\n\t\tif (cell == Nodes[index].Cell) {\n\t\t\treturn(&Nodes[index]);\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built            *\n *                                                                                             *\n * If 'type' is not NONE, returns ptr to the next \"hole\" in the list of the given type.        *\n * Otherwise, returns ptr to the next hole in the list of any type.                            *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      type      type of building to check for                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to a BaseNodeClass, NULL if none                                                   *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nBaseNodeClass * BaseClass::Next_Buildable(StructType type)\n{\n\t/*\n\t** Loop through all node entries, returning a pointer to the first\n\t** un-built one that matches the requested type.\n\t*/\n\tfor (int i = 0; i < Nodes.Count(); i++) {\n\n\t\t/*\n\t\t** For STRUCT_NONE, return the first hole found\n\t\t*/\n\t\tif (type == STRUCT_NONE) {\n\t\t\tif (!Is_Built(i)) {\n\t\t\t\treturn(&Nodes[i]);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t** For a \"real\" building type, return the first hold for that type\n\t\t\t*/\n\t\t\tif (Nodes[i].Type==type && !Is_Built(i)) {\n\t\t\t\treturn(&Nodes[i]);\n\t\t\t}\n\t\t}\n\t}\n\n\n// If no entry could be found, then create a fake one that will allow\n// placement of the building. Make it static and reuse the next time this\n// routine is called.\n\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * BaseClass::Read_INI -- INI reading routine                                                  *\n *                                                                                             *\n * INI entry format:                                                                           *\n *      BLDG=COORDINATE                                                                        *\n *      BLDG=COORDINATE                                                                        *\n *        ...                                                                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      buffer      pointer to loaded INI file                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      This routines assumes there is only one base defined for the scenario.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/24/1995 BRR : Created.                                                                 *\n *   02/20/1996 JLB : Fixed to know what house to build base from.                             *\n *=============================================================================================*/\nvoid BaseClass::Read_INI(CCINIClass & ini)\n{\n\tchar buf[128];\n\tchar uname[10];\n\tBaseNodeClass node;\t\t\t\t\t\t// node to add to list\n\t\n\tMono_Clear_Screen();\n\t/*\n\t**\tFirst, determine the house of the human player, and set the Base's house\n\t**\taccordingly.\n\t*/\n\tHouse = ini.Get_HousesType(INI_Name(), \"Player\", PlayerPtr->Class->House);\n\n\t/*\n\t**\tRead the number of buildings that will go into the base node list\n\t*/\n\tint count = ini.Get_Int(INI_Name(), \"Count\", 0);\n\n\t/*\n\t**\tRead each entry in turn, in the same order they were written out.\n\t*/\n\tfor (int i = 0; i < count; i++) {\n\n\t\t/*\n\t\t** Get an INI entry\n\t\t*/\n\t\tsprintf(uname,\"%03d\",i);\n\t\tini.Get_String(INI_Name(), uname, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t** Set the node's building type\n\t\t*/\n\t\tnode.Type = BuildingTypeClass::From_Name(strtok(buf,\",\"));\n\n\t\t/*\n\t\t** Read & set the node's coordinate\n\t\t*/\n\t\tnode.Cell = atoi(strtok(NULL,\",\"));\n\n\t\t/*\n\t\t** Add this node to the Base's list\n\t\t*/\n\t\tNodes.Add(node);\n\t}\n}\n\n\n/***********************************************************************************************\n * BaseClass::Write_INI -- Writes all the base information to the INI database.                *\n *                                                                                             *\n *    Use this routine to write all prebuild base information to the INI database specified.   *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to store the data to.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If there was any preexisting prebuild base data in the database, it will be     *\n *             be erased by this routine.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BaseClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tClear out all existing base data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\tif (House != HOUSE_NONE) {\n\n\t\t/*\n\t\t**\tWrite out the owner of this buildable list.\n\t\t*/\n\t\tini.Put_HousesType(INI_Name(), \"Player\", House);\n\n\t\t/*\n\t\t**\tSave the # of buildings in the Nodes list.  This is essential because\n\t\t**\tthey must be read in the same order they were created, so \"000\" must be\n\t\t**\tread first, etc.\n\t\t*/\n\t\tini.Put_Int(INI_Name(), \"Count\", Nodes.Count());\n\n\t\t/*\n\t\t**\tWrite each entry into the INI\n\t\t*/\n\t\tfor (int i = 0; i < Nodes.Count(); i++) {\n\t\t\tchar buf[128];\n\t\t\tchar uname[10];\n\n\t\t\tsprintf(uname,\"%03d\",i);\n\t\t\tsprintf(buf,\"%s,%d\",\n\t\t\t\tBuildingTypeClass::As_Reference(Nodes[i].Type).IniName,\n\t\t\t\tNodes[i].Cell);\n\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/BASE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BASE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE.H                                                       *\n *                                                                                             *\n *                   Programmer : Bill Randolph\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *                   Start Date : 03/27/95                                                     *\n *                                                                                             *\n *                  Last Update : March 27, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BASE_H\n#define BASE_H\n\n\n/****************************************************************************\n** This class defines one \"node\" in the pre-built base list.  Each node\n** contains a type of building to build, and the COORDINATE to build it at.\n*/\nclass BaseNodeClass\n{\n\tpublic:\n\t\tBaseNodeClass(void) {};\n\t\tBaseNodeClass(StructType building, CELL cell) : Type(building), Cell(cell) {};\n\t\tint operator == (BaseNodeClass const & node);\n\t\tint operator != (BaseNodeClass const & node);\n\t\tint operator > (BaseNodeClass const & node);\n\n\t\tStructType Type;\n\t\tCELL Cell;\n};\n\n\n/****************************************************************************\n** This is the class that defines a pre-built base for the computer AI.\n** (Despite its name, this is NOT the \"base\" class for C&C's class hierarchy!)\n*/\nclass BaseClass\n{\n\tpublic:\n\n\t\t/*\n\t\t** Constructor/Destructor\n\t\t*/\n\t\tBaseClass(void) {};\n\t\tvirtual ~BaseClass() {Nodes.Clear();}\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvoid Init(void) {House = HOUSE_NONE; Nodes.Clear();}\n\n\t\t/*\n\t\t** The standard suite of load/save support routines\n\t\t*/\n\t\tvoid Read_INI(CCINIClass & ini);\n\t\tvoid Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"Base\";}\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void) {};\n\t\tvirtual void Decode_Pointers(void) {};\n\n\t\t/*\n\t\t** Tells if the given node has been built or not\n\t\t*/\n\t\tbool Is_Built(int index) const;\n\n\t\t/*\n\t\t** Returns a pointer to the object for the given node\n\t\t*/\n\t\tBuildingClass * Get_Building(int index) const;\n\n\t\t/*\n\t\t** Tells if the given building ptr is a node in this base's list.\n\t\t*/\n\t\tbool Is_Node(BuildingClass const * obj);\n\n\t\t/*\n\t\t** Returns a pointer to the requested node.\n\t\t*/\n\t\tBaseNodeClass * Get_Node(BuildingClass const * obj);\n\t\tBaseNodeClass * Get_Node(int index) { return (&Nodes[index]); }\n\t\tBaseNodeClass * Get_Node(CELL cell);\n\n\t\t/*\n\t\t** Returns a pointer to the next \"hole\" in the Nodes list.\n\t\t*/\n\t\tBaseNodeClass * Next_Buildable(StructType type = STRUCT_NONE);\n\n\t\t/*\n\t\t** This is the list of \"nodes\" that define the base.  Portions of this\n\t\t** list can be pre-built by simply saving those buildings in the INI\n\t\t** along with non-base buildings, so Is_Built will return true for them.\n\t\t*/\n\t\tDynamicVectorClass<BaseNodeClass> Nodes;\n\n\t\t/*\n\t\t** This is the house this base belongs to.\n\t\t*/\n\t\tHousesType House;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/BASE64.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BASE64.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE64.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Base64_Decode -- Decodes Base 64 data into its original data form.                        *\n *   Base64_Encode -- Encode data into Base 64 format.                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"base64.h\"\n#include\t<stddef.h>\n\n/*\n**\tThis is the magic padding character used to fill out the encoded data to a multiple of\n**\t4 characters even though the source data is less than necessary to accomplish this.\n**\tThe pad character lets the decoder know of this condition and it will compensate\n**\taccordingly.\n*/\nstatic char const * const _pad = \"=\";\n\n/*\n**\tThis encoder translation table will convert a 6 bit number into an ASCII character.\n*/\nstatic char const * const _encoder = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n/*\n**\tThe decoder translation table takes an ASCII character and converts it into a\n**\t6 bit number.\n*/\n#define\tBAD\t0xFE\t\t\t// Ignore this character in source data.\n#define\tEND\t0xFF\t\t\t// Signifies premature end of input data.\nstatic unsigned char const _decoder[256] = {\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,62,BAD,BAD,BAD,63,\n\t52,53,54,55,56,57,58,59,60,61,BAD,BAD,BAD,END,BAD,BAD,\n\tBAD,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t15,16,17,18,19,20,21,22,23,24,25,BAD,BAD,BAD,BAD,BAD,\n\tBAD,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,\n\t41,42,43,44,45,46,47,48,49,50,51,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,\n\tBAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD\n};\n\nint const PacketChars = 4;\n\n\n/*\n**\tThe packet type is used to construct and disect the Base64 data blocks. The data\n**\tconsists of three source data bytes mapped onto four 6 bit Base64 code elements.\n*/\ntypedef union {\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned char C1;\n\t\tunsigned char C2;\n\t\tunsigned char C3;\n#else\n\t\tunsigned char C3;\n\t\tunsigned char C2;\n\t\tunsigned char C1;\n#endif\n\t\tunsigned char pad;\n\t} Char;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned O1:6;\n\t\tunsigned O2:6;\n\t\tunsigned O3:6;\n\t\tunsigned O4:6;\n#else\n\t\tunsigned O4:6;\n\t\tunsigned O3:6;\n\t\tunsigned O2:6;\n\t\tunsigned O1:6;\n#endif\n\t\tunsigned pad:8;\n\t} SubCode;\n\tunsigned int Raw;\n}\tPacketType;\n\n\n/***********************************************************************************************\n * Base64_Encode -- Encode data into Base 64 format.                                           *\n *                                                                                             *\n *    This will take an arbitrary length of source data and transform it into base 64 format   *\n *    data. Base 64 format has the property of being very portable across text editors and     *\n *    country character encoding schemes. As such it is ideal for e-mail. Note that the output *\n *    data will be about 33% larger than the source.                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data to convert.                                 *\n *                                                                                             *\n *          slen     -- The number of bytes to encode.                                         *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer that will hold the encoded data.     *\n *                                                                                             *\n *          dlen     -- The size of the destination buffer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the destination buffer.               *\n *                                                                                             *\n * WARNINGS:   Be sure that the destination buffer is big enough to hold the encoded output.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64_Encode(void const * source, int slen, void * dest, int dlen)\n{\n\t/*\n\t**\tCheck the parameters for legality.\n\t*/\n\tif (source == NULL || slen == 0 || dest == NULL || dlen == 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tProcess the source data in blocks of three bytes. Fewer than three bytes\n\t**\tresults in special padding output characters (automatically discarded\n\t**\tduring the decode process).\n\t*/\n\tint total = 0;\n\tunsigned char const * sptr = (unsigned char const *)source;\n\tunsigned char * dptr = (unsigned char *)dest;\n\twhile (slen > 0 && dlen >= PacketChars) {\n\n\t\t/*\n\t\t**\tFetch 24 bits of source data.\n\t\t*/\n\t\tPacketType packet;\n\n\t\tint pad = 0;\n\t\tpacket.Raw = 0;\n\t\tpacket.Char.C1 = *sptr++;\n\t\tslen--;\n\t\tif (slen) {\n\t\t\tpacket.Char.C2 = *sptr++;\n\t\t\tslen--;\n\t\t} else {\n\t\t\tpad++;\n\t\t}\n\t\tif (slen) {\n\t\t\tpacket.Char.C3 = *sptr++;\n\t\t\tslen--;\n\t\t} else {\n\t\t\tpad++;\n\t\t}\n\n\t\t/*\n\t\t**\tTranslate and write 4 characters of Base64 data. Pad with pad\n\t\t**\tcharacters if there is insufficient source data for a full packet.\n\t\t*/\n\t\t*dptr++ = _encoder[packet.SubCode.O1];\n\t\t*dptr++ = _encoder[packet.SubCode.O2];\n\t\tif (pad < 2) {\n\t\t\t*dptr++ = _encoder[packet.SubCode.O3];\n\t\t} else {\n\t\t\t*dptr++ = _pad[0];\n\t\t}\n\t\tif (pad < 1) {\n\t\t\t*dptr++ = _encoder[packet.SubCode.O4];\n\t\t} else {\n\t\t\t*dptr++ = _pad[0];\n\t\t}\n\n\t\tdlen -= PacketChars;\n\t\ttotal += PacketChars;\n\t}\n\n\t/*\n\t**\tAdd a trailing null as a courtesy measure.\n\t*/\n\tif (dlen > 0) {\n\t\t*dptr = '\\0';\n\t}\n\n\t/*\n\t**\tReturn with the total number of characters in the output buffer.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * Base64_Decode -- Decodes Base 64 data into its original data form.                          *\n *                                                                                             *\n *    Use this routine to decode base 64 data back into the original data. A property of this  *\n *    decode process is that unrecognized input characters are ignored. This allows mangled    *\n *    source (filled with line breaks or spaces) to be correctly decoded. The decode process   *\n *    terminates when the end of the source data has been reached or the special end of data   *\n *    marker is encountered.                                                                   *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source data to decode.                                  *\n *                                                                                             *\n *          slen     -- The number of bytes in the source data buffer.                         *\n *                                                                                             *\n *          dest     -- Pointer to the destination buffer to be filled with the decoded data.  *\n *                                                                                             *\n *          dlen     -- The maximum size of the destination buffer.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the destination buffer. This will     *\n *          always be less than the number of source bytes (usually by about 33%).             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Base64_Decode(void const * source, int slen, void * dest, int dlen)\n{\n\t/*\n\t**\tCheck the parameters for legality.\n\t*/\n\tif (source == NULL || slen == 0 || dest == NULL || dlen == 0) {\n\t\treturn(0);\n\t}\n\n\tint total = 0;\n\tunsigned char const * sptr = (unsigned char const *)source;\n\tunsigned char * dptr = (unsigned char *)dest;\n\twhile (slen > 0 && dlen > 0) {\n\n\t\tPacketType packet;\n\t\tpacket.Raw = 0;\n\n\t\t/*\n\t\t**\tProcess input until a full packet has been accumulated or the\n\t\t**\tsource is exhausted.\n\t\t*/\n\t\tint pcount = 0;\n\t\twhile (pcount < PacketChars && slen > 0) {\n\t\t\tunsigned char c = *sptr++;\n\t\t\tslen--;\n\n\t\t\tunsigned char code = _decoder[c];\n\n\t\t\t/*\n\t\t\t**\tAn unrecognized character is skipped.\n\t\t\t*/\n\t\t\tif (code == BAD) continue;\n\n\t\t\t/*\n\t\t\t**\tThe \"=\" character signifies the end of data regardless of what\n\t\t\t**\tthe source buffer length value may be.\n\t\t\t*/\n\t\t\tif (code == END) {\n\t\t\t\tslen = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA valid Base64 character was found so add it to the packet\n\t\t\t**\tdata.\n\t\t\t*/\n\t\t\tswitch (pcount) {\n\t\t\t\tcase 0:\n\t\t\t\t\tpacket.SubCode.O1 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpacket.SubCode.O2 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpacket.SubCode.O3 = code;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpacket.SubCode.O4 = code;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpcount++;\n\t\t}\n\n\t\t/*\n\t\t**\tA packet block is ready for output into the destination buffer.\n\t\t*/\n\t\t*dptr++ = packet.Char.C1;\n\t\tdlen--;\n\t\ttotal++;\n\t\tif (dlen > 0 && pcount > 2) {\n\t\t\t*dptr++ = packet.Char.C2;\n\t\t\tdlen--;\n\t\t\ttotal++;\n\t\t}\n\t\tif (dlen > 0 && pcount > 3) {\n\t\t\t*dptr++ = packet.Char.C3;\n\t\t\tdlen--;\n\t\t\ttotal++;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the total number of characters decoded into the\n\t**\toutput buffer.\n\t*/\n\treturn(total);\n}\n\n\n/*\nBase64 Content-Transfer-Encoding\n\nThe Base64 Content-Transfer-Encoding is designed to represent arbitrary\nsequences of octets in a form that need not be humanly readable. The encoding\nand decoding algorithms are simple, but the encoded data are consistently\nonly about 33 percent larger than the unencoded data. This encoding is\nvirtually identical to the one used in Privacy Enhanced Mail (PEM)\napplications, as defined in RFC 1421. The base64 encoding is adapted from\nRFC 1421, with one change: base64 eliminates the \"*\" mechanism for embedded\nclear text.\n\nA 65-character subset of US-ASCII is used, enabling 6 bits to be represented\nper printable character. (The extra 65th character, \"=\", is used to signify a\nspecial processing function.)\n\nNOTE:\n    This subset has the important property that it is represented identically\n    in all versions of ISO 646, including US ASCII, and all characters in the\n    subset are also represented identically in all versions of EBCDIC. Other\n    popular encodings, such as the encoding used by the uuencode utility and\n    the base85 encoding specified as part of Level 2 PostScript, do not share\n    these properties, and thus do not fulfill the portability requirements a\n    binary transport encoding for mail must meet.\n\nThe encoding process represents 24-bit groups of input bits as output strings\nof 4 encoded characters. Proceeding from left to right, a 24-bit input group is\nformed by concatenating 3 8-bit input groups. These 24 bits are then treated as\n4 concatenated 6-bit groups, each of which is translated into a single digit in\nthe base64 alphabet. When encoding a bit stream via the base64 encoding, the\nbit stream must be presumed to be ordered with the most-significant-bit first.\nThat is, the first bit in the stream will be the high-order bit in the first\nbyte, and the eighth bit will be the low-order bit in the first byte, and so on.\n\nEach 6-bit group is used as an index into an array of 64 printable characters.\nThe character referenced by the index is placed in the output string. These\ncharacters, identified in Table 1, below, are selected so as to be universally\nrepresentable, and the set excludes characters with particular significance to\nSMTP (e.g., \".\", CR, LF) and to the encapsulation boundaries defined in this\ndocument (e.g., \"-\").\n\nTable 1: The Base64 Alphabet\n\n  Value Encoding  Value Encoding  Value Encoding  Value Encoding\n       0 A            17 R            34 i            51 z\n       1 B            18 S            35 j            52 0\n       2 C            19 T            36 k            53 1\n       3 D            20 U            37 l            54 2\n       4 E            21 V            38 m            55 3\n       5 F            22 W            39 n            56 4\n       6 G            23 X            40 o            57 5\n       7 H            24 Y            41 p            58 6\n       8 I            25 Z            42 q            59 7\n       9 J            26 a            43 r            60 8\n      10 K            27 b            44 s            61 9\n      11 L            28 c            45 t            62 +\n      12 M            29 d            46 u            63 /\n      13 N            30 e            47 v\n      14 O            31 f            48 w         (pad) =\n      15 P            32 g            49 x\n      16 Q            33 h            50 y\n\nThe output stream (encoded bytes) must be represented in lines of no more than\n76 characters each. All line breaks or other characters not found in Table 1\nmust be ignored by decoding software. In base64 data, characters other than\nthose in Table 1, line breaks, and other white space probably indicate a\ntransmission error, about which a warning message or even a message rejection\nmight be appropriate under some circumstances.\n\nSpecial processing is performed if fewer than 24 bits are available at the end\nof the data being encoded. A full encoding quantum is always completed at the\nend of a body. When fewer than 24 input bits are available in an input group,\nzero bits are added (on the right) to form an integral number of 6-bit groups.\nPadding at the end of the data is performed using the '=' character. Since all\nbase64 input is an integral number of octets, only the following cases can\narise: (1) the final quantum of encoding input is an integral multiple of 24\nbits; here, the final unit of encoded output will be an integral multiple of 4\ncharacters with no \"=\" padding, (2) the final quantum of encoding input is\nexactly 8 bits; here, the final unit of encoded output will be two characters\nfollowed by two \"=\" padding characters, or (3) the final quantum of encoding\ninput is exactly 16 bits; here, the final unit of encoded output will be three\ncharacters followed by one \"=\" padding character.\n\nBecause it is used only for padding at the end of the data, the occurrence of\nany '=' characters may be taken as evidence that the end of the data has been\nreached (without truncation in transit). No such assurance is possible,\nhowever, when the number of octets transmitted was a multiple of three.\n\nAny characters outside of the base64 alphabet are to be ignored in\nbase64-encoded data. The same applies to any illegal sequence of characters in\nthe base64 encoding, such as \"=====\"\n\nCare must be taken to use the proper octets for line breaks if base64 encoding\nis applied directly to text material that has not been converted to canonical\nform. In particular, text line breaks must be converted into CRLF sequences\nprior to base64 encoding. The important thing to note is that this may be done\ndirectly by the encoder rather than in a prior canonicalization step in some\nimplementations.\n\nNOTE:\n    There is no need to worry about quoting apparent encapsulation boundaries\n    within base64-encoded parts of multipart entities because no hyphen\n    characters are used in the base64 encoding.\n\n*/"
  },
  {
    "path": "REDALERT/BASE64.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BASE64.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BASE64.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : June 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\nint Base64_Encode(void const * source, int slen, void * dest, int dlen);\nint Base64_Decode(void const * source, int slen, void * dest, int dlen);\n"
  },
  {
    "path": "REDALERT/BBDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BBDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BBDATA.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 23, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specif*\n *   BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects.                  *\n *   BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type.            *\n *   BulletTypeClass::Load_Shapes -- Load shape data for bullet types.                         *\n *   BulletTypeClass::One_Time -- Performs the one time processing for bullets.                *\n *   BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database.            *\n *   BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap.   *\n *   BulletTypeClass::operator new -- Allocates a bullet type object from the special heap.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n\n/***********************************************************************************************\n * BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects.                    *\n *                                                                                             *\n *    This is basically a constructor for static type objects used by bullets. All bullets     *\n *    are of a type constructed by this routine at game initialization time.                   *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   07/17/1996 JLB : Uses correct default values.                                             *\n *=============================================================================================*/\nBulletTypeClass::BulletTypeClass(char const * name) :\n\t\tObjectTypeClass(\tRTTI_BULLETTYPE,\n\t\t\t\t\t\t\t\tBulletTypes.ID(this),\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\tTXT_NONE,\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t),\n\tIsHigh(false),\n\tIsShadow(true),\n\tIsArcing(false),\n\tIsDropping(false),\n\tIsInvisible(false),\n\tIsProximityArmed(false),\n\tIsFlameEquipped(false),\n\tIsFueled(false),\n\tIsFaceless(true),\n\tIsInaccurate(false),\n\tIsTranslucent(false),\n\tIsAntiAircraft(false),\n\tIsAntiGround(true),\n\tIsAntiSub(false),\n\tIsDegenerate(false),\n\tIsSubSurface(false),\n\tIsParachuted(false),\n\tIsGigundo(false),\n\tType(BulletType(ID)),\n\tROT(0),\n\tArming(0),\n\tTumble(0)\n{\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::operator new -- Allocates a bullet type object from the special heap.      *\n *                                                                                             *\n *    This allocates a bullet type object from a special heap that is used just for            *\n *    objects of this type.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an allocated block or NULL if the allocation could not   *\n *          occur.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BulletTypeClass::operator new(size_t)\n{\n\treturn(BulletTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap.     *\n *                                                                                             *\n *    This is the counterpart to the operator new function for bullet type objects. It will    *\n *    return the bullet type object back to the special heap used for bullet type object       *\n *    allocation.                                                                              *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the bullet type object to free.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::operator delete(void * ptr)\n{\n\tBulletTypes.Free((BulletTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type.              *\n *                                                                                             *\n *    This performs any necessary initialization for the bullet types.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese bullet type class objects must be allocated in the exact order that they\n\t**\tare specified in the BulletType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew BulletTypeClass(\"Invisible\");\t//\tBULLET_INVISIBLE\n\tnew BulletTypeClass(\"Cannon\");\t\t//\tBULLET_CANNON\n\tnew BulletTypeClass(\"Ack\");\t\t\t//\tBULLET_ACK\n\tnew BulletTypeClass(\"Torpedo\");\t\t//\tBULLET_TORPEDO\n\tnew BulletTypeClass(\"FROG\");\t\t\t//\tBULLET_FROG\n\tnew BulletTypeClass(\"HeatSeeker\");\t//\tBULLET_HEAT_SEEKER\n\tnew BulletTypeClass(\"LaserGuided\");\t//\tBULLET_LASER_GUIDED\n\tnew BulletTypeClass(\"Lobbed\");\t\t//\tBULLET_LOBBED\n\tnew BulletTypeClass(\"Bomblet\");\t\t//\tBULLET_BOMBLET\n\tnew BulletTypeClass(\"Ballistic\");\t//\tBULLET_BALLISTIC\n\tnew BulletTypeClass(\"Parachute\");\t//\tBULLET_PARACHUTE\n\tnew BulletTypeClass(\"Fireball\");\t\t//\tBULLET_FIREBALL\n\tnew BulletTypeClass(\"LeapDog\");\t\t//\tBULLET_DOG\n\tnew BulletTypeClass(\"Catapult\");\t\t//\tBULLET_CATAPULT\n\tnew BulletTypeClass(\"AAMissile\");\t//\tBULLET_AAMISSILE\n\tnew BulletTypeClass(\"GPSSatellite\");//\tBULLET_GPS_SATELLITE\n\tnew BulletTypeClass(\"NukeUp\");\t\t//\tBULLET_NUKE_UP\n\tnew BulletTypeClass(\"NukeDown\");\t\t//\tBULLET_NUKE_DOWN\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::One_Time -- Performs the one time processing for bullets.                  *\n *                                                                                             *\n *    This routine is used to perform any one time processing for the bullet type class. It    *\n *    handles loading of the shape files.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called before any rendering of bullets occurs and should   *\n *             only be called once.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletTypeClass::One_Time(void)\n{\n\t/*\n\t**\tLoad the bullet shapes.\n\t*/\n\tfor (int index = BULLET_FIRST; index < BULLET_COUNT; index++) {\n\t\tBulletTypeClass const & bullet = As_Reference((BulletType)index);\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tif (!bullet.IsInvisible) {\n\t\t\t_makepath(fullname, NULL, NULL, bullet.GraphicName, \".SHP\");\n\n\t\t\t#ifdef NDEBUG\n\t\t\t\t((void const *&)bullet.ImageData) =\tMFCD::Retrieve(fullname);\n\t\t\t#else\n\t\t\t\tRawFileClass file(fullname);\n\n\t\t\t\tif (file.Is_Available()) {\n\t\t\t\t\t((void const *&)bullet.ImageData) = Load_Alloc_Data(file);\n\t\t\t\t} else {\n\t\t\t\t\t((void const *&)bullet.ImageData) =\tMFCD::Retrieve(fullname);\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specifi *\n *                                                                                             *\n *    Given a bullet type identifier, this routine will return a reference to the bullet type  *\n *    object it refers to.                                                                     *\n *                                                                                             *\n * INPUT:   type  -- The bullet type identifier to convert to a reference.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the bullet type object.                                *\n *                                                                                             *\n * WARNINGS:   Make sure that the type parameter specified is a valid bullet type. If not,     *\n *             then the results are undefined.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletTypeClass & BulletTypeClass::As_Reference(BulletType type)\n{\n\treturn(*BulletTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database.              *\n *                                                                                             *\n *    Use this routine to fetch override information about this bullet type class object       *\n *    from the INI database specified.                                                         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to examine.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the section for this bullet found and the data extracted?                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tArming = ini.Get_Int(Name(), \"Arm\", Arming);\n\t\tROT = ini.Get_Int(Name(), \"ROT\", ROT);\n\t\tTumble = ini.Get_Int(Name(), \"Frames\", Tumble);\n\t\tIsHigh = ini.Get_Bool(Name(), \"High\", IsHigh);\n\t\tIsShadow = ini.Get_Bool(Name(), \"Shadow\", IsShadow);\n\t\tIsArcing = ini.Get_Bool(Name(), \"Arcing\", IsArcing);\n\t\tIsDropping = ini.Get_Bool(Name(), \"Dropping\", IsDropping);\n\t\tIsInvisible = ini.Get_Bool(Name(), \"Inviso\", IsInvisible);\n\t\tIsProximityArmed = ini.Get_Bool(Name(), \"Proximity\", IsProximityArmed);\n\t\tIsFlameEquipped = ini.Get_Bool(Name(), \"Animates\", IsFlameEquipped);\n\t\tIsFueled = ini.Get_Bool(Name(), \"Ranged\", IsFueled);\n\t\tIsInaccurate = ini.Get_Bool(Name(), \"Inaccuate\", IsInaccurate);\n\t\tIsAntiAircraft = ini.Get_Bool(Name(), \"AA\", IsAntiAircraft);\n\t\tIsAntiGround = ini.Get_Bool(Name(), \"AG\", IsAntiGround);\n\t\tIsAntiSub = ini.Get_Bool(Name(), \"ASW\", IsAntiSub);\n\t\tIsDegenerate = ini.Get_Bool(Name(), \"Degenerates\", IsDegenerate);\n\t\tIsSubSurface = ini.Get_Bool(Name(), \"UnderWater\", IsSubSurface);\n\t\tIsParachuted = ini.Get_Bool(Name(), \"Parachuted\", IsParachuted);\n\t\tIsFaceless = !ini.Get_Bool(Name(), \"Rotates\", !IsFaceless);\n\t\tIsTranslucent = ini.Get_Bool(Name(), \"Translucent\", IsTranslucent);\n\t\tIsGigundo = ini.Get_Bool(Name(), \"Gigundo\", IsGigundo);\n\t\tini.Get_String(Name(), \"Image\", GraphicName, GraphicName, sizeof(GraphicName));\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/BDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BDATA.CPP 2     3/03/97 10:37p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 2, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BuildingTypeClass::As_Reference -- Fetches reference to the building type specified.      *\n *   BuildingTypeClass::Bib_And_Offset -- Determines the bib and appropriate cell offset.      *\n *   BuildingTypeClass::BuildingTypeClass -- This is the constructor for the building types.   *\n *   BuildingTypeClass::Coord_Fixup -- Adjusts coordinate to be legal for assignment.          *\n *   BuildingTypeClass::Cost_Of -- Fetches the cost of this building.                          *\n *   BuildingTypeClass::Create_And_Place -- Creates and places a building object onto the map. *\n *   BuildingTypeClass::Create_One_Of -- Creates a building of this type.                      *\n *   BuildingTypeClass::Dimensions -- Fetches the pixel dimensions of the building.            *\n *   BuildingTypeClass::Display -- Renders a generic view of building.                         *\n *   BuildingTypeClass::Flush_For_Placement -- Tries to clear placement area for this building *\n *   BuildingTypeClass::Full_Name -- Fetches the name to give this building.                   *\n *   BuildingTypeClass::Height -- Determines the height of the building in icons.              *\n *   BuildingTypeClass::Init -- Performs theater specific initialization.                      *\n *   BuildingTypeClass::Init_Anim -- Initialize an animation control for a building.           *\n *   BuildingTypeClass::Init_Heap -- Initialize the heap as necessary for the building type obj*\n *   BuildingTypeClass::Max_Pips -- Determines the maximum pips to display.                    *\n *   BuildingTypeClass::Occupy_List -- Fetches the occupy list for the building.               *\n *   BuildingTypeClass::One_Time -- Performs special one time action for buildings.            *\n *   BuildingTypeClass::Overlap_List -- Fetches the overlap list for the building.             *\n *   BuildingTypeClass::Prep_For_Add -- Prepares scenario editor for adding an object.         *\n *   BuildingTypeClass::Raw_Cost -- Fetches the raw (base) cost of this building type.         *\n *   BuildingTypeClass::Read_INI -- Fetch building type data from the INI database.            *\n *   BuildingTypeClass::Width -- Determines width of building in icons.                        *\n *   BuildingTypeClass::operator delete -- Deletes a building type object from the special heap*\n *   BuildingTypeClass::operator new -- Allocates a building type object from the special heap.*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#define FATSHIP\n\n#define\tMCW\tMAP_CELL_W\n\n#define XYCELL(x,y)\t(y*MAP_CELL_W+x)\nstatic short const ExitPyle[] = {\n\tXYCELL(1,2),\n\tXYCELL(2,2),\n\tXYCELL(0,2),\n\tXYCELL(-1,2),\n\tXYCELL(-1,-1),\n\tXYCELL(0,-1),\n\tXYCELL(1,-1),\n\tXYCELL(2,-1),\n\tXYCELL(2,-1),\n\tXYCELL(-1,0),\n\tXYCELL(2,0),\n\tXYCELL(2,1),\n\tXYCELL(-1,1),\n\tREFRESH_EOL\n};\n\nstatic short const ExitSub[] = {\n\tXYCELL( 0, 2),\n\tXYCELL( 2, 2),\n\tXYCELL(-1, 2),\n\tXYCELL( 1, 2),\n\tXYCELL( 3, 2)\n};\n\nstatic short const ExitWeap[] = {\n\tXYCELL(1,2),\n\tXYCELL(-1,3),\n\tXYCELL(0,3),\n\tXYCELL(1,3),\n\tXYCELL(-2,3),\n\tXYCELL(2,3),\n\tREFRESH_EOL\n};\n\nstatic short const ComList[] = {0, 1, MCW, MCW+1, REFRESH_EOL};\nstatic short const List000111111[] = {(MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\nstatic short const List0010[] = {MCW, REFRESH_EOL};\nstatic short const List0011[] = {(MCW*1), (MCW*1)+1, REFRESH_EOL};\nstatic short const List010111100[] = {1, (MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), REFRESH_EOL};\nstatic short const List0111[] = {1, (MCW*1), (MCW*1)+1, REFRESH_EOL};\nstatic short const List1000[] = {0, REFRESH_EOL};\nstatic short const List101000011[] = {0, 2, (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\nstatic short const List1100[] = {0, 1, REFRESH_EOL};\nstatic short const List1101[] = {0, 1, (MCW*1)+1, REFRESH_EOL};\nstatic short const List11[] = {0, 1, REFRESH_EOL};\nstatic short const List12[] = {MCW, REFRESH_EOL};\nstatic short const List1[] = {0, REFRESH_EOL};\nstatic short const List21[] = {0, 1, REFRESH_EOL};\nstatic short const List22[] = {0, 1, MCW, MCW+1, REFRESH_EOL};\nstatic short const List22_0011[] = {MCW, MCW+1, REFRESH_EOL};\nstatic short const List22_1100[] = {0, 1, REFRESH_EOL};\nstatic short const List2[] = {0, 1, MCW+1, MCW, REFRESH_EOL};\nstatic short const List32[] = {0, 1, 2, MCW, MCW+1, MCW+2, REFRESH_EOL};\n//static short const List42[] = {0, 1, 2, 3, MCW, MCW+1, MCW+2, MCW+3, REFRESH_EOL};\nstatic short const ListFix[] = {1, MCW, MCW+1, MCW+2, MCW+MCW+1, REFRESH_EOL};\nstatic short const ListWeap[] = {0, 1, 2, (MCW*1), (MCW*1)+1, (MCW*1)+2, REFRESH_EOL};\nstatic short const ListWestwood[] = {1, 2, 3, MCW+1, MCW+2, MCW+3, REFRESH_EOL};\nstatic short const OListSAM[] = {-MCW, -(MCW-1), REFRESH_EOL};\n#ifdef FATSHIP\nstatic short const ListSPen[] = {0, 1, 2, MCW, MCW+1, MCW+2, MCW+MCW, MCW+MCW+1, MCW+MCW+2, REFRESH_EOL};\nstatic short const OListSPen[] = {REFRESH_EOL};\n#else\nstatic short const ListSPen[] = {1, MCW, MCW+1, MCW+2, MCW+MCW+1, REFRESH_EOL};\nstatic short const OListSPen[] = {0, 2, MCW+MCW, MCW+MCW+2, REFRESH_EOL};\n#endif\nstatic short const OListWestwood[] = {0, MCW, REFRESH_EOL};\nstatic short const StoreList[] = {0, REFRESH_EOL};\n\nstatic short const ListFactory[] = {0, 1, 2, (MCW*1), (MCW*1)+1, (MCW*1)+2, (MCW*2), (MCW*2)+1, (MCW*2)+2, REFRESH_EOL};\n\nstatic short const OListFix[] = {0, 2, MCW+MCW, MCW+MCW+2, REFRESH_EOL};\nstatic short const OListWeap[] = {REFRESH_EOL};\nstatic short const OComList[] = {1, REFRESH_EOL};\nstatic short const OList12[] = {0, REFRESH_EOL};\nstatic short const OListTmpl[] = {0, 1, 2, REFRESH_EOL};\n\n\n/***************************************************************************\n*/\nstatic BuildingTypeClass const ClassBarrel(\n\tSTRUCT_BARREL,\n\tTXT_BARREL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARL\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBarrel3(\n\tSTRUCT_BARREL3,\n\tTXT_BARREL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BRL3\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAVMine(\n\tSTRUCT_AVMINE,\n\tTXT_AVMINE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MINV\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NORMAL,\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\tfalse,\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAPMine(\n\tSTRUCT_APMINE,\n\tTXT_APMINE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MINP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NORMAL,\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\tfalse,\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassIronCurtain(\n\tSTRUCT_IRON_CURTAIN,\n\tTXT_IRON_CURTAIN,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"IRON\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22_0011,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassForwardCom(\n\tSTRUCT_FORWARD_COM,\n\tTXT_FORWARD_COM,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FCOM\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22_0011,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAdvancedTech(\n\tSTRUCT_ADVANCED_TECH,\n\tTXT_ADVANCED_TECH,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"ATEK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassChronosphere(\n\tSTRUCT_CHRONOSPHERE,\n\tTXT_CHRONOSPHERE,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PDOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassWeapon(\n\tSTRUCT_WEAP,\n\tTXT_WEAPON_FACTORY,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WEAP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXY_Coord(CELL_LEPTON_W+(CELL_LEPTON_W/2), CELL_LEPTON_H),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_UNITTYPE,\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListWeap,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWeap\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassShipYard(\n\tSTRUCT_SHIP_YARD,\n\tTXT_SHIP_YARD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SYRD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_VESSELTYPE,\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSubPen(\n\tSTRUCT_SUB_PEN,\n\tTXT_SUB_PEN,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SPEN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_VESSELTYPE,\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitSub,\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassPillbox(\n\tSTRUCT_PILLBOX,\n\tTXT_PILLBOX,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PBOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0010,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassCamoPillbox(\n\tSTRUCT_CAMOPILLBOX,\n\tTXT_CAMOPILLBOX,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HBOX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0010,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0040,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTesla(\n\tSTRUCT_TESLA,\n\tTXT_TESLA,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"TSLA\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x00C8,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List12,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OList12\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTurret(\n\tSTRUCT_TURRET,\n\tTXT_TURRET,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"GUN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0080,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\t(DirType)208,\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAAGun(\n\tSTRUCT_AAGUN,\n\tTXT_AAGUN,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"AGUN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_NE,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List12,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OList12\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFlameTurret(\n\tSTRUCT_FLAME_TURRET,\n\tTXT_FLAME_TURRET,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FTUR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassConst(\n\tSTRUCT_CONST,\n\tTXT_CONST_YARD,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FACT\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_BUILDINGTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFactory,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeConst(\n\tSTRUCT_FAKECONST,\n\tTXT_FAKE_CONST,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FACF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFactory,// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeWeapon(\n\tSTRUCT_FAKEWEAP,\n\tTXT_FAKE_WEAP,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WEAF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(10+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*3)-(CELL_PIXEL_H/2))-21),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListWeap,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWeap\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassRefinery(\n\tSTRUCT_REFINERY,\n\tTXT_REFINERY,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"PROC\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List010111100,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List101000011\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassStorage(\n\tSTRUCT_STORAGE,\n\tTXT_STORAGE,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SILO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)StoreList,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassHelipad(\n\tSTRUCT_HELIPAD,\n\tTXT_HELIPAD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HPAD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_AIRCRAFTTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassCommand(\n\tSTRUCT_RADAR,\n\tTXT_COMMAND,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"DOME\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ComList,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassGapGenerator(\n\tSTRUCT_GAP,\n\tTXT_GAP_GENERATOR,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"GAP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_12, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0010,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSAM(\n\tSTRUCT_SAM,\n\tTXT_SAM,\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SAM\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0030,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0080,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\ttrue,\t\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List21,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSAM\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassMissileSilo(\n\tSTRUCT_MSLO,\n\tTXT_MSLO,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MSLO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List21,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSAM\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAirStrip(\n\tSTRUCT_AIRSTRIP,\n\tTXT_AIRSTRIP,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"AFLD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_AIRCRAFTTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List32,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassPower(\n\tSTRUCT_POWER,\n\tTXT_POWER,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"POWR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List22_1100\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassAdvancedPower(\n\tSTRUCT_ADVANCED_POWER,\n\tTXT_ADVANCED_POWER,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"APWR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List000111111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListTmpl\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassSovietTech(\n\tSTRUCT_SOVIET_TECH,\n\tTXT_SOVIET_TECH,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"STEK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List000111111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListTmpl\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassHospital(\n\tSTRUCT_HOSPITAL,\n\tTXT_HOSPITAL,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"HOSP\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBioLab(\n\tSTRUCT_BIO_LAB,\n\tTXT_BIO_LAB,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BIO\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List2,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassBarracks(\n\tSTRUCT_BARRACKS,\n\tTXT_BARRACKS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARR\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n//\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tXYP_COORD(18,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassTent(\n\tSTRUCT_TENT,\n\tTXT_BARRACKS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"TENT\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List22,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassKennel(\n\tSTRUCT_KENNEL,\n\tTXT_KENNEL,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"KENN\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(8,16),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_INFANTRYTYPE,\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n//\t(short const *)ExitPyle,\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeShipYard(\n\tSTRUCT_FAKE_YARD,\n\tTXT_FAKE_YARD,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SYRF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitWeap,\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeSubPen(\n\tSTRUCT_FAKE_PEN,\n\tTXT_FAKE_PEN,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SPEF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(22+(CELL_PIXEL_W/2), ((CELL_PIXEL_H*2)-(CELL_PIXEL_H/2))),\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\t(short const *)ExitSub,\t\t// Preferred exit cell list.\n\t(short const *)ListSPen,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListSPen\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassFakeCommand(\n\tSTRUCT_FAKE_RADAR,\n\tTXT_FAKE_RADAR,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"DOMF\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\ttrue,\t\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ComList,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OComList\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassRepair(\n\tSTRUCT_REPAIR,\n\tTXT_FIX_IT,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FIX\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\tfalse,\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_33, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListFix,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListFix\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV01(\n\tSTRUCT_V01,\n\tTXT_CIV1,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V01\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE: Building size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV02(\n\tSTRUCT_V02,\n\tTXT_CIV2,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V02\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV03(\n\tSTRUCT_V03,\n\tTXT_CIV3,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V03\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1000\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV04(\n\tSTRUCT_V04,\n\tTXT_CIV4,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V04\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV05(\n\tSTRUCT_V05,\n\tTXT_CIV5,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V05\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV06(\n\tSTRUCT_V06,\n\tTXT_CIV6,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V06\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV07(\n\tSTRUCT_V07,\n\tTXT_CIV7,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V07\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV08(\n\tSTRUCT_V08,\n\tTXT_CIV8,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V08\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV09(\n\tSTRUCT_V09,\n\tTXT_CIV9,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V09\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV10(\n\tSTRUCT_V10,\n\tTXT_CIV10,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V10\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV11(\n\tSTRUCT_V11,\n\tTXT_CIV11,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V11\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV12(\n\tSTRUCT_V12,\n\tTXT_CIV12,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V12\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV13(\n\tSTRUCT_V13,\n\tTXT_CIV13,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V13\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV14(\n\tSTRUCT_V14,\n\tTXT_CIV14,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V14\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV15(\n\tSTRUCT_V15,\n\tTXT_CIV15,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V15\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV16(\n\tSTRUCT_V16,\n\tTXT_CIV16,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V16\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV17(\n\tSTRUCT_V17,\n\tTXT_CIV17,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V17\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV18(\n\tSTRUCT_V18,\n\tTXT_CIV18,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V18\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV19(\n\tSTRUCT_PUMP,\n\tTXT_PUMP,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V19\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV20(\n\tSTRUCT_V20,\n\tTXT_CIV20,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V20\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV21(\n\tSTRUCT_V21,\n\tTXT_CIV21,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V21\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1101,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List0010\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV22(\n\tSTRUCT_V22,\n\tTXT_CIV22,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V22\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV23(\n\tSTRUCT_V23,\n\tTXT_CIV23,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V23\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV24(\n\tSTRUCT_V24,\n\tTXT_CIV24,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V24\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0011,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1100\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV25(\n\tSTRUCT_V25,\n\tTXT_CIV25,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V25\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_S,\t\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_22, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List0111,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)List1000\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV26(\n\tSTRUCT_V26,\n\tTXT_CIV26,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V26\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV27(\n\tSTRUCT_V27,\n\tTXT_CIV27,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V27\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV28(\n\tSTRUCT_V28,\n\tTXT_CIV28,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V28\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV29(\n\tSTRUCT_V29,\n\tTXT_CIV29,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V29\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV30(\n\tSTRUCT_V30,\n\tTXT_CIV30,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V30\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV31(\n\tSTRUCT_V31,\n\tTXT_CIV31,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V31\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV32(\n\tSTRUCT_V32,\n\tTXT_CIV32,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V32\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV33(\n\tSTRUCT_V33,\n\tTXT_CIV33,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V33\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV34(\n\tSTRUCT_V34,\n\tTXT_CIV34,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V34\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV35(\n\tSTRUCT_V35,\n\tTXT_CIV35,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V35\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\nstatic BuildingTypeClass const ClassV36(\n\tSTRUCT_V36,\n\tTXT_CIV36,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V36\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassV37(\n\tSTRUCT_V37,\n\tTXT_CIV37,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"V37\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\ttrue,\t\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_42, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)ListWestwood,\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)OListWestwood\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassMission(\n\tSTRUCT_MISSION,\n\tTXT_CIVMISS,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"MISS\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_32, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List32,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\n// Sandbag wall\nstatic BuildingTypeClass const Sandbag(\n\tSTRUCT_SANDBAG_WALL,\n\tTXT_SANDBAG_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"SBAG\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Cyclone fence\nstatic BuildingTypeClass const Cyclone(\n\tSTRUCT_CYCLONE_WALL,\n\tTXT_CYCLONE_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"CYCL\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Brick wall\nstatic BuildingTypeClass const Brick(\n\tSTRUCT_BRICK_WALL,\n\tTXT_BRICK_WALL,\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BRIK\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Barbwire wall\nstatic BuildingTypeClass const Barbwire(\n\tSTRUCT_BARBWIRE_WALL,\n\tTXT_BARBWIRE_WALL,\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"BARB\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n// Wood wall\nstatic BuildingTypeClass const Wood(\n\tSTRUCT_WOOD_WALL,\n\tTXT_WOOD_WALL,\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"WOOD\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const Fence(\n\tSTRUCT_FENCE,\n\tTXT_FENCE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"FENC\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_NONE,\t\t\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\tfalse,\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n\n\n#ifdef FIXIT_ANTS\nstatic BuildingTypeClass const ClassQueen(\n\tSTRUCT_QUEEN,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"QUEE\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(24,47),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\ttrue,\t\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\tfalse,\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\tfalse,\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\tfalse,\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\ttrue,\t\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_21, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List11,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\tNULL\t\t\t\t\t\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassLarva1(\n\tSTRUCT_LARVA1,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"LAR1\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\nstatic BuildingTypeClass const ClassLarva2(\n\tSTRUCT_LARVA2,\n\tTXT_NONE,\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\t\"LAR2\",\t\t\t\t\t\t\t// NAME:\t\t\tShort name of the structure.\n\tFACING_NONE,\t\t\t\t\t// Foundation direction from center of building.\n\tXYP_COORD(0,0),\t\t\t\t// Exit point for produced units.\n\tREMAP_ALTERNATE,\t\t\t\t// Sidebar remap logic.\n\t0x0000,\t\t\t\t\t\t\t//\tVertical offset.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\t0x0000,\t\t\t\t\t\t\t// Primary weapon lateral offset along turret centerline.\n\t\tfalse,\t\t\t\t\t\t// Is this building a fake (decoy?)\n\t\tfalse,\t\t\t\t\t\t// Animation rate is regulated for constant speed?\n\t\ttrue,\t\t\t\t\t\t\t// Always use the given name for the building?\n\t\tfalse,\t\t\t\t\t\t// Is this a wall type structure?\n\t\ttrue,\t\t\t\t\t\t\t// Simple (one frame) damage imagery?\n\t\ttrue,\t\t\t\t\t\t\t// Is it invisible to radar?\n\t\ttrue,\t\t\t\t\t\t\t// Can the player select this?\n\t\ttrue,\t\t\t\t\t\t\t// Is this a legal target for attack or move?\n\t\ttrue,\t\t\t\t\t\t\t// Is this an insignificant building?\n\t\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\t\tfalse,\t\t\t\t\t\t// Does it have a rotating turret?\n\t\tfalse,\t\t\t\t\t\t// Can the building be color remapped to indicate owner?\n\tRTTI_NONE,\t\t\t\t\t\t// The object type produced at this factory.\n\tDIR_N,\t\t\t\t\t\t\t// Starting idle frame to match construction.\n\tBSIZE_11, \t\t\t\t\t\t// SIZE:\t\t\tBuilding size.\n\tNULL,\t\t\t\t\t\t\t\t// Preferred exit cell list.\n\t(short const *)List1,\t\t// OCCUPYLIST:\tList of active foundation squares.\n\t(short const *)NULL\t\t\t// OVERLAPLIST:List of overlap cell offset.\n);\n#endif\nvoid const * BuildingTypeClass::WarFactoryOverlay;\nvoid const * LightningShapes;\n\n\n/***********************************************************************************************\n * BuildingTypeClass::BuildingTypeClass -- This is the constructor for the building types.     *\n *                                                                                             *\n *    This is the constructor used to create the building types.                               *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass::BuildingTypeClass(\n\t\t\t\t\t\tStructType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tFacingType foundation,\n\t\t\t\t\t\tCOORDINATE exitpoint,\n\t\t\t\t\t\tRemapType remap,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tint primarylateral,\n\t\t\t\t\t\tbool is_fake,\n\t\t\t\t\t\tbool is_regulated,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_wall,\n\t\t\t\t\t\tbool is_simpledamage,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tbool is_turret_equipped,\n\t\t\t\t\t\tbool is_remappable,\n\t\t\t\t\t\tRTTIType tobuild,\n\t\t\t\t\t\tDirType sframe,\n\t\t\t\t\t\tBSizeType size,\n\t\t\t\t\t\tshort const * exitlist,\n\t\t\t\t\t\tshort const * sizelist,\n\t\t\t\t\t\tshort const * overlap) :\n\t\t\t\t\t\t\t\tTechnoTypeClass(RTTI_BUILDINGTYPE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\t\t\t\t\t\t\tremap,\n\t\t\t\t\t\t\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprimarylateral,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_stealthy,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_selectable,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_legal_target,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_insignificant,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_theater,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_turret_equipped,\n\t\t\t\t\t\t\t\t\t\t\t\t\tis_remappable,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(is_turret_equipped ? 32 : 1),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSPEED_NONE),\n\tIsBase(true),\n\tIsFake(is_fake),\n\tIsBibbed(false),\n\tIsWall(is_wall),\n\tIsSimpleDamage(is_simpledamage),\n\tIsCaptureable(false),\n\tIsRegulated(is_regulated),\n\tIsPowered(false),\n\tIsUnsellable(false),\n\tFoundationFace(foundation),\n\tAdjacent(1),\n\tToBuild(tobuild),\n\tExitCoordinate(exitpoint),\n\tExitList(exitlist),\n\tType(type),\n\tStartFace(sframe),\n\tCapacity(0),\n\tPower(0),\n\tDrain(0),\n\tSize(size),\n\tOccupyList(sizelist),\n\tOverlapList(overlap),\n\tBuildupData(0)\n{\n\n\tAnims[BSTATE_CONSTRUCTION].Start = 0;\n\tAnims[BSTATE_CONSTRUCTION].Count = 1;\n\tAnims[BSTATE_CONSTRUCTION].Rate = 0;\n\n\tAnims[BSTATE_IDLE].Start = 0;\n\tAnims[BSTATE_IDLE].Count = 1;\n\tAnims[BSTATE_IDLE].Rate = 0;\n\n\tAnims[BSTATE_ACTIVE].Start = 0;\n\tAnims[BSTATE_ACTIVE].Count = 1;\n\tAnims[BSTATE_ACTIVE].Rate = 0;\n\n\tAnims[BSTATE_AUX1].Start = 0;\n\tAnims[BSTATE_AUX1].Count = 1;\n\tAnims[BSTATE_AUX1].Rate = 0;\n\n\tAnims[BSTATE_AUX2].Start = 0;\n\tAnims[BSTATE_AUX2].Count = 1;\n\tAnims[BSTATE_AUX2].Rate = 0;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::operator new -- Allocates a building type object from the special heap.  *\n *                                                                                             *\n *    This routine will allocate a building type object from the special heap used just for    *\n *    allocation of object of this type.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated object. If the allocation could not  *\n *          succeed, then NULL will be returned.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BuildingTypeClass::operator new(size_t)\n{\n\treturn(BuildingTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::operator delete -- Deletes a building type object from the special heap. *\n *                                                                                             *\n *    This will delete a previously allocated building type object. The memory is returned     *\n *    to the special heap that is used for that purpose.                                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the building type object to return to the special heap.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::operator delete(void * ptr)\n{\n\tBuildingTypes.Free((BuildingTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init_Heap -- Initialize the heap as necessary for the building type obje *\n *                                                                                             *\n *    This routine performs the necessary heap initializations. Since we know exactly what     *\n *    building type objects will be needed, they are pre-allocated at this time.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese building type class objects must be allocated in the exact order that they\n\t**\tare specified in the StructType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew BuildingTypeClass(ClassAdvancedTech);\t// STRUCT_ADVANCED_TECH\n\tnew BuildingTypeClass(ClassIronCurtain);\t// STRUCT_IRON_CURTAIN\n\tnew BuildingTypeClass(ClassWeapon);\t\t\t//\tSTRUCT_WEAP\n\tnew BuildingTypeClass(ClassChronosphere);\t// STRUCT_CHRONOSPHERE\n\tnew BuildingTypeClass(ClassPillbox);\t\t//\tSTRUCT_PILLBOX\n\tnew BuildingTypeClass(ClassCamoPillbox);\t//\tSTRUCT_CAMOPILLBOX\n\tnew BuildingTypeClass(ClassCommand);\t\t//\tSTRUCT_RADAR\n\tnew BuildingTypeClass(ClassGapGenerator);\t// STRUCT_GAP\n\tnew BuildingTypeClass(ClassTurret);\t\t\t//\tSTRUCT_TURRET\n\tnew BuildingTypeClass(ClassAAGun);\t\t\t// STRUCT_AAGUN\n\tnew BuildingTypeClass(ClassFlameTurret);\t//\tSTRUCT_FLAME_TURRET\n\tnew BuildingTypeClass(ClassConst);\t\t\t//\tSTRUCT_CONST\n\tnew BuildingTypeClass(ClassRefinery);\t\t//\tSTRUCT_REFINERY\n\tnew BuildingTypeClass(ClassStorage);\t\t//\tSTRUCT_STORAGE\n\tnew BuildingTypeClass(ClassHelipad);\t\t//\tSTRUCT_HELIPAD\n\tnew BuildingTypeClass(ClassSAM);\t\t\t\t//\tSTRUCT_SAM\n\tnew BuildingTypeClass(ClassAirStrip);\t\t//\tSTRUCT_AIRSTRIP\n\tnew BuildingTypeClass(ClassPower);\t\t\t//\tSTRUCT_POWER\n\tnew BuildingTypeClass(ClassAdvancedPower);//\tSTRUCT_ADVANCED_POWER\n\tnew BuildingTypeClass(ClassSovietTech);\t// STRUCT_SOVIET_TECH\n\tnew BuildingTypeClass(ClassHospital);\t\t//\tSTRUCT_HOSPITAL\n\tnew BuildingTypeClass(ClassBarracks);\t\t//\tSTRUCT_BARRACKS\n\tnew BuildingTypeClass(ClassTent);\t\t\t//\tSTRUCT_TENT\n\tnew BuildingTypeClass(ClassKennel);\t\t\t// STRUCT_KENNEL\n\tnew BuildingTypeClass(ClassRepair);\t\t\t//\tSTRUCT_REPAIR\n\tnew BuildingTypeClass(ClassBioLab);\t\t\t//\tSTRUCT_BIO_LAB\n\tnew BuildingTypeClass(ClassMission);\t\t//\tSTRUCT_MISSION\n\tnew BuildingTypeClass(ClassShipYard);\t\t//\tSTRUCT_SHIP_YARD\n\tnew BuildingTypeClass(ClassSubPen);\t\t\t//\tSTRUCT_SUB_PEN\n\tnew BuildingTypeClass(ClassMissileSilo);\t// STRUCT_MSLO\n\tnew BuildingTypeClass(ClassForwardCom);\t// STRUCT_FORWARD_COM\n\tnew BuildingTypeClass(ClassTesla);\t\t\t//\tSTRUCT_TESLA\n\tnew BuildingTypeClass(ClassFakeWeapon);\t// STRUCT_FAKEWEAP\n\tnew BuildingTypeClass(ClassFakeConst);\t\t// STRUCT_FAKECONST\n\tnew BuildingTypeClass(ClassFakeShipYard);\t// STRUCT_FAKE_YARD\n\tnew BuildingTypeClass(ClassFakeSubPen);\t// STRUCT_FAKE_PEN\n\tnew BuildingTypeClass(ClassFakeCommand);\t// STRUCT_FAKE_RADAR\n\tnew BuildingTypeClass(Sandbag);\t\t\t\t// STRUCT_SANDBAG_WALL\n\tnew BuildingTypeClass(Cyclone);\t\t\t\t//\tSTRUCT_CYCLONE_WALL\n\tnew BuildingTypeClass(Brick);\t\t\t\t\t// STRUCT_BRICK_WALL\n\tnew BuildingTypeClass(Barbwire);\t\t\t\t// STRUCT_BARBWIRE_WALL\n\tnew BuildingTypeClass(Wood);\t\t\t\t\t//\tSTRUCT_WOOD_WALL\n\tnew BuildingTypeClass(Fence);\t\t\t\t\t// STRUCT_FENCE\n\tnew BuildingTypeClass(ClassAVMine);\t\t\t// STRUCT_AVMINE\n\tnew BuildingTypeClass(ClassAPMine);\t\t\t// STRUCT_APMINE\n\tnew BuildingTypeClass(ClassV01);\t\t\t\t//\tSTRUCT_V1\n\tnew BuildingTypeClass(ClassV02);\t\t\t\t//\tSTRUCT_V2\n\tnew BuildingTypeClass(ClassV03);\t\t\t\t//\tSTRUCT_V3\n\tnew BuildingTypeClass(ClassV04);\t\t\t\t//\tSTRUCT_V4\n\tnew BuildingTypeClass(ClassV05);\t\t\t\t//\tSTRUCT_V5\n\tnew BuildingTypeClass(ClassV06);\t\t\t\t//\tSTRUCT_V6\n\tnew BuildingTypeClass(ClassV07);\t\t\t\t//\tSTRUCT_V7\n\tnew BuildingTypeClass(ClassV08);\t\t\t\t//\tSTRUCT_V8\n\tnew BuildingTypeClass(ClassV09);\t\t\t\t//\tSTRUCT_V9\n\tnew BuildingTypeClass(ClassV10);\t\t\t\t//\tSTRUCT_V10\n\tnew BuildingTypeClass(ClassV11);\t\t\t\t//\tSTRUCT_V11\n\tnew BuildingTypeClass(ClassV12);\t\t\t\t//\tSTRUCT_V12\n\tnew BuildingTypeClass(ClassV13);\t\t\t\t//\tSTRUCT_V13\n\tnew BuildingTypeClass(ClassV14);\t\t\t\t//\tSTRUCT_V14\n\tnew BuildingTypeClass(ClassV15);\t\t\t\t//\tSTRUCT_V15\n\tnew BuildingTypeClass(ClassV16);\t\t\t\t//\tSTRUCT_V16\n\tnew BuildingTypeClass(ClassV17);\t\t\t\t//\tSTRUCT_V17\n\tnew BuildingTypeClass(ClassV18);\t\t\t\t//\tSTRUCT_V18\n\tnew BuildingTypeClass(ClassV19);\t\t\t\t//\tSTRUCT_PUMP\n\tnew BuildingTypeClass(ClassV20);\t\t\t\t//\tSTRUCT_V20\n\tnew BuildingTypeClass(ClassV21);\t\t\t\t//\tSTRUCT_V21\n\tnew BuildingTypeClass(ClassV22);\t\t\t\t//\tSTRUCT_V22\n\tnew BuildingTypeClass(ClassV23);\t\t\t\t//\tSTRUCT_V23\n\tnew BuildingTypeClass(ClassV24);\t\t\t\t//\tSTRUCT_V24\n\tnew BuildingTypeClass(ClassV25);\t\t\t\t//\tSTRUCT_V25\n\tnew BuildingTypeClass(ClassV26);\t\t\t\t//\tSTRUCT_V26\n\tnew BuildingTypeClass(ClassV27);\t\t\t\t//\tSTRUCT_V27\n\tnew BuildingTypeClass(ClassV28);\t\t\t\t//\tSTRUCT_V28\n\tnew BuildingTypeClass(ClassV29);\t\t\t\t//\tSTRUCT_V29\n\tnew BuildingTypeClass(ClassV30);\t\t\t\t//\tSTRUCT_V30\n\tnew BuildingTypeClass(ClassV31);\t\t\t\t//\tSTRUCT_V31\n\tnew BuildingTypeClass(ClassV32);\t\t\t\t//\tSTRUCT_V32\n\tnew BuildingTypeClass(ClassV33);\t\t\t\t//\tSTRUCT_V33\n\tnew BuildingTypeClass(ClassV34);\t\t\t\t//\tSTRUCT_V34\n\tnew BuildingTypeClass(ClassV35);\t\t\t\t//\tSTRUCT_V35\n\tnew BuildingTypeClass(ClassV36);\t\t\t\t//\tSTRUCT_V36\n\tnew BuildingTypeClass(ClassV37);\t\t\t\t//\tSTRUCT_V37\n\tnew BuildingTypeClass(ClassBarrel);\t\t\t// STRUCT_BARREL\n\tnew BuildingTypeClass(ClassBarrel3);\t\t// STRUCT_BARREL3\n\n#ifdef FIXIT_ANTS\n\tnew BuildingTypeClass(ClassQueen);\t\t\t// STRUCT_QUEEN\n\tnew BuildingTypeClass(ClassLarva1);\t\t\t// STRUCT_LARVA1\n\tnew BuildingTypeClass(ClassLarva2);\t\t\t// STRUCT_LARVA2\n#endif\n\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::One_Time -- Performs special one time action for buildings.              *\n *                                                                                             *\n *    This routine is used to do the one time action necessary to handle building type class   *\n *    objects. This entails loading of the building shapes and the brain file used by          *\n *    buildings.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should only be called ONCE.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   06/11/1994 JLB : Updated construction time and frame count logic.                         *\n *=============================================================================================*/\nvoid BuildingTypeClass::One_Time(void)\n{\n\tstatic const struct {\n\t\tStructType\tClass;\t\t\t// Building class number.\n\t\tBStateType\tStage;\t\t\t// Animation sequence to assign animation range to.\n\t\tint\t\t\tStart;\t\t\t// Starting frame number.\n\t\tint\t\t\tLength;\t\t\t// Number of frames (-1 means use all frames).\n\t\tint\t\t\tRate;\t\t\t\t// Rate of animation.\n\t} _anims[] = {\n\t\t{STRUCT_CHRONOSPHERE,\tBSTATE_IDLE,\t0, 4, 3},\t// idling\n\t\t{STRUCT_CHRONOSPHERE,\tBSTATE_ACTIVE,\t4, 16,3},\t// charging up and activating\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_IDLE,\t0, 0, 0},\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_ACTIVE,\t0, 5, 2},\t// door opening\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_AUX1,\t4, 1, 0},\t// door held open\n\t\t{STRUCT_MSLO,\t\t\t\tBSTATE_AUX2,\t5, 3, 2},\t// door closing\n\t\t{STRUCT_CAMOPILLBOX,\t\tBSTATE_ACTIVE,\t0,\t2, 1},\n\t\t{STRUCT_GAP,\t\t\t\tBSTATE_IDLE,\t0,\t32,3},\n\t\t{STRUCT_AIRSTRIP,\t\t\tBSTATE_IDLE,\t0,\t0,\t0},\n\t\t{STRUCT_AIRSTRIP,\t\t\tBSTATE_AUX1,\t0,\t8,\t3},\n\t\t{STRUCT_BARRACKS,\t\t\tBSTATE_ACTIVE,\t0,\t10,3},\n\t\t{STRUCT_BARRACKS,\t\t\tBSTATE_IDLE,\t0,\t10,3},\n\t\t{STRUCT_TENT,\t\t\t\tBSTATE_ACTIVE,\t0,\t10,3},\n\t\t{STRUCT_TENT,\t\t\t\tBSTATE_IDLE,\t0,\t10,3},\n#ifdef FIXIT_ANTS\n\t\t{STRUCT_QUEEN,\t\t\t\tBSTATE_IDLE,\t0,\t10,3},\n#endif\n\t\t{STRUCT_CONST,\t\t\t\tBSTATE_ACTIVE,\t0,\t26,3},\n\t\t{STRUCT_FAKECONST,\t\tBSTATE_ACTIVE,\t0,\t26,3},\n\t\t{STRUCT_HELIPAD,\t\t\tBSTATE_ACTIVE,\t0,\t7,\t4},\n\t\t{STRUCT_HELIPAD,\t\t\tBSTATE_IDLE,\t0,\t0,\t0},\n\t\t{STRUCT_HOSPITAL,\t\t\tBSTATE_IDLE,\t0,\t4,\t3},\n\t\t{STRUCT_PUMP,\t\t\t\tBSTATE_IDLE,\t0,\t14,4},\n\t\t{STRUCT_REPAIR,\t\t\tBSTATE_ACTIVE,\t0,\t7,\t2},\n\t\t{STRUCT_REPAIR,\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_V20,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V21,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V22,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_V23,\t\t\t\tBSTATE_IDLE,\t0,\t3,\t3},\n\t\t{STRUCT_WEAP,\t\t\t\tBSTATE_ACTIVE,\t0,\t1,\t0},\n\t\t{STRUCT_WEAP,\t\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_FAKEWEAP,\t\t\tBSTATE_ACTIVE,\t0,\t1,\t0},\n\t\t{STRUCT_FAKEWEAP,\t\t\tBSTATE_IDLE,\t0,\t1,\t0},\n\t\t{STRUCT_IRON_CURTAIN,\tBSTATE_ACTIVE,\t0,\t11,3},\n\t\t{STRUCT_TESLA,\t\t\t\tBSTATE_ACTIVE,\t0,\t10,2},\n\t\t{STRUCT_AIRSTRIP,\t\t\tBSTATE_IDLE,\t0,\t8,\t3}\n\t};\n\n\tfor (int sindex = STRUCT_FIRST; sindex < STRUCT_COUNT; sindex++) {\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\tchar\tbuffer[_MAX_FNAME];\n\t\tBuildingTypeClass const & building = As_Reference((StructType)sindex);\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (building.Level != -1) {\n//\t\tif (building.IsBuildable) {\n\t\t\tsprintf(buffer, \"%sICON\", building.Graphic_Name());\n\n\t\t\tif (building.IsFake) {\n\t\t\t\tbuffer[3] = 'F';\n\t\t\t}\n\n\t\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\t\t((void const *&)building.CameoData) = MFCD::Retrieve(fullname);\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the construction animation for this building.\n\t\t*/\n\t\tsprintf(buffer, \"%sMAKE\", building.Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\tvoid const * dataptr;\n\t\tdataptr = MFCD::Retrieve(fullname);\n\t\t((void const *&)building.BuildupData) = dataptr;\n\t\tif (dataptr != NULL) {\n\t\t\tint timedelay = 1;\n\t\t\tint count = Get_Build_Frame_Count(dataptr);\n\t\t\tif (count > 0) {\n\t\t\t\ttimedelay = (Rule.BuildupTime * TICKS_PER_MINUTE) / count;\n\t\t\t}\n\t\t\tbuilding.Init_Anim(BSTATE_CONSTRUCTION, 0, count, timedelay);\n\t\t}\n\n\t\t/*\n\t\t**\tFetch the normal game shape for this building.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, building.Graphic_Name(), \".SHP\");\n\t\t((void const *&)building.ImageData) = MFCD::Retrieve(fullname);\n\t}\n\n\t// Try to load weap2.shp and tesla coil's lightning shapes\n\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t_makepath(fullname, NULL, NULL, (char const *)\"WEAP2\",\".SHP\");\n\tWarFactoryOverlay = MFCD::Retrieve(fullname);\n\t_makepath(fullname, NULL, NULL, (char const *)\"LITNING\",\".SHP\");\n\tLightningShapes = MFCD::Retrieve(fullname);\n\n\t/*\n\t**\tInstall all the special animation sequences for the different building types.\n\t*/\n\tfor (unsigned index = 0; index < (sizeof(_anims) / sizeof(_anims[0])); index++) {\n\t\tAs_Reference(_anims[index].Class).Init_Anim(_anims[index].Stage, _anims[index].Start, _anims[index].Length, _anims[index].Rate);\n\t}\n\n}\n\n\n/***********************************************************************************************\n * Struct_From_Name -- Find BData structure from its name.                                     *\n *                                                                                             *\n *    This routine will convert an ASCII name for a building class into                        *\n *    the actual building class it represents.                                                 *\n *                                                                                             *\n * INPUT:   name  -- ASCII representation of a building class.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the actual building class number that the string                      *\n *          represents.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/02/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nStructType BuildingTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (int classid = STRUCT_FIRST; classid < STRUCT_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference((StructType)classid).IniName, name) == 0) {\n\t\t\t\treturn((StructType)classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(STRUCT_NONE);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * BuildingTypeClass::Display -- Renders a generic view of building.                           *\n *                                                                                             *\n *    This routine is used to display a generic representation of the                          *\n *    building. Typical use of this occurs with the scenario editor.                           *\n *                                                                                             *\n * INPUT:   x,y      -- Coordinate to display the building (centered).                         *\n *                                                                                             *\n *          window   -- The window the building should be rendered                             *\n *                      relative to.                                                           *\n *                                                                                             *\n *          house    -- The house color to use for the building.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tvoid const * ptr = Get_Cameo_Data();\n\tif (ptr == NULL) {\n\t\tIsTheaterShape = IsTheater;\n\t\tptr = Get_Image_Data();\n\t}\n\tCC_Draw_Shape(ptr, 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Prep_For_Add -- Prepares scenario editor for adding a                    *\n *                                                                                             *\n *    This routine is used to prepare the scenario editor for the addition                     *\n *    of a building object to the game.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   06/04/1994 JLB : Uses map editing interface routines.                                     *\n *=============================================================================================*/\nvoid BuildingTypeClass::Prep_For_Add(void)\n{\n\tfor (StructType index = STRUCT_FIRST; index < STRUCT_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Create_And_Place -- Creates and places a building object onto the map.   *\n *                                                                                             *\n *    This routine is used by the scenario editor to create and place buildings on the map.    *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the building is to be placed upon.                       *\n *                                                                                             *\n *          house    -- The owner of the building.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the building successfully created and placed on the map?                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tBuildingClass * ptr;\n\n\tptr = new BuildingClass(Type, house);\n\tif (ptr != NULL) {\n\t\treturn(ptr->Unlimbo(Cell_Coord(cell), DIR_N));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Create_One_Of -- Creates a building of this type.                        *\n *                                                                                             *\n *    This routine will create a building object of this type. The building object is in a     *\n *    limbo state. It is presumed that the building object will be unlimboed at the correct    *\n *    place and time. Typical use is when the building is created in a factory situation       *\n *    and will be placed on the map when construction completes.                               *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that is to be the owner of the building.             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building. If the building could not be created       *\n *          then a NULL is returned.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * BuildingTypeClass::Create_One_Of(HouseClass * house) const\n{\n\tHousesType htype = HOUSE_NEUTRAL;\n\tif (house != NULL) {\n\t\thtype = house->Class->House;\n\t}\n\treturn(new BuildingClass(Type, htype));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init_Anim -- Initialize an animation control for a building.             *\n *                                                                                             *\n *    This routine will initialize one animation control element for a                         *\n *    specified building. This modifies a \"const\" class and thus must                          *\n *    perform some strategic casting to get away with this.                                    *\n *                                                                                             *\n * INPUT:   state -- The animation state to apply these data values to.                        *\n *                                                                                             *\n *          start -- Starting frame for the building's animation.                              *\n *                                                                                             *\n *          count -- The number of frames in this animation.                                   *\n *                                                                                             *\n *          rate  -- The countdown timer between animation frames.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init_Anim(BStateType state, int start, int count, int rate) const\n{\n\t((int &)Anims[state].Start) = start;\n\t((int &)Anims[state].Count) = count;\n\t((int &)Anims[state].Rate) = rate;\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Init -- Performs theater specific initialization.                        *\n *                                                                                             *\n *    This routine is used to perform any initialization that is custom per theater.           *\n *    Typically, this is fetching the building shape data for those building types that have   *\n *    theater specific art.                                                                    *\n *                                                                                             *\n * INPUT:   theater  -- The theater to base this initialization on.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\n\t\tfor (int sindex = STRUCT_FIRST; sindex < STRUCT_COUNT; sindex++) {\n\t\t\tBuildingTypeClass const * classptr = &As_Reference((StructType)sindex);\n\n\t\t\tif (classptr->IsTheater) {\n\t\t\t\t_makepath(fullname, NULL, NULL, classptr->Graphic_Name(), Theaters[theater].Suffix);\n\t\t\t\t((void const *&)classptr->ImageData) = MFCD::Retrieve(fullname);\n\n\t\t\t\t/*\n\t\t\t\t**\tBuildup data is probably theater specific as well. Fetch a pointer to the\n\t\t\t\t**\tdata at this time as well.\n\t\t\t\t*/\n\t\t\t\tsprintf(fullname, \"%sMAKE.%s\", classptr->Graphic_Name(), Theaters[theater].Suffix);\n\t\t\t\t((void const *&)classptr->BuildupData) = MFCD::Retrieve(fullname);\n\t\t\t\tif (classptr->BuildupData) {\n\t\t\t\t\tint timedelay = 1;\n\t\t\t\t\tint count = Get_Build_Frame_Count(classptr->BuildupData);\n\t\t\t\t\tif (count != 0) {\n\t\t\t\t\t\ttimedelay = (5 * TICKS_PER_SECOND) / count;\n\t\t\t\t\t}\n\t\t\t\t\tclassptr->Init_Anim(BSTATE_CONSTRUCTION, 0, count, timedelay);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Dimensions -- Fetches the pixel dimensions of the building.              *\n *                                                                                             *\n *    This routine will fetch the dimensions of the building (in pixels). These dimensions are *\n *    used to render the selection rectangle and the health bar.                               *\n *                                                                                             *\n * INPUT:   width    -- Reference to the pixel width (to be filled in).                        *\n *                                                                                             *\n *          height   -- Reference to the pixel height (to be filled in).                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingTypeClass::Dimensions(int &width, int &height) const\n{\n\twidth = Width() * ICON_PIXEL_W;\n\twidth -= (width/5);\n\theight = Height() * ICON_PIXEL_H;\n\theight -= (height/5);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::As_Reference -- Fetches reference to the building type specified.        *\n *                                                                                             *\n *    This routine will fetch a reference to the BuildingTypeClass as indicated by the         *\n *    building type number specified.                                                          *\n *                                                                                             *\n * INPUT:   type  -- The building type number to convert into a BuildingTypeClass reference.   *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the building type class as indicated by the            *\n *          parameter.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass & BuildingTypeClass::As_Reference(StructType type)\n{\n\treturn(*BuildingTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Occupy_List -- Fetches the occupy list for the building.                 *\n *                                                                                             *\n *    Use this routine to fetch the occupy list pointer for the building. The occupy list is   *\n *    used to determine what cells the building occupies and thus precludes other buildings    *\n *    or objects from using.                                                                   *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a cell offset list to be used to determine what cells    *\n *          this building occupies.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * BuildingTypeClass::Occupy_List(bool placement) const\n{\n\tSmudgeType bib = SMUDGE_NONE;\n\tCELL cell=0;\n\n\tif (placement && Bib_And_Offset(bib, cell)) {\n\n\t\tSmudgeTypeClass const & smudge = SmudgeTypeClass::As_Reference(bib);\n\t\tstatic short _list[25];\n\t\tshort * dest = &_list[0];\n\n\t\t/*\n\t\t**\tCopy the bib overlap list into the working buffer.\n\t\t*/\n\t\tshort const * src = smudge.Occupy_List();\n\t\twhile (*src != REFRESH_EOL) {\n\t\t\t*dest++ = (*src++) + cell;\n\t\t}\n\n\t\t/*\n\t\t**\tAppend the building occupy list to this working buffer.\n\t\t*/\n\t\tsrc = OccupyList;\n\t\twhile (src && *src != REFRESH_EOL) {\n\t\t\t*dest++ = *src++;\n\t\t}\n\t\t*dest = REFRESH_EOL;\n\n\t\treturn(&_list[0]);\n\t}\n\n\tif (OccupyList != NULL) {\n\t\treturn(OccupyList);\n\t}\n\n\tstatic short const _templap[] = {REFRESH_EOL};\n\treturn(&_templap[0]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Overlap_List -- Fetches the overlap list for the building.               *\n *                                                                                             *\n *    This routine will fetch the overlap list for the building. The overlap list is used      *\n *    to determine what cells the building's graphics cover, but is not considered to occupy   *\n *    for movement purposes.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cell offset list that is used to determine the       *\n *          cells that this building overlaps.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * BuildingTypeClass::Overlap_List(void) const\n{\n\tif (OverlapList != NULL) {\n\t\treturn(OverlapList);\n\t}\n\n\tstatic short const _templap[] = {REFRESH_EOL};\n\treturn(&_templap[0]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Width -- Determines width of building in icons.                          *\n *                                                                                             *\n *    Use this routine to determine the width of the building type in icons.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building width in icons.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Width(void) const\n{\n\tstatic int width[BSIZE_COUNT] = {\n\t\t1,\n\t\t2,\n\t\t1,\n\t\t2,\n\t\t2,\n\t\t3,\n\t\t3,\n\t\t4,\n\t\t5\n\t};\n\treturn(width[Size]);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Height -- Determines the height of the building in icons.                *\n *                                                                                             *\n *    Use this routine to find the height of the building in icons.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building height in icons.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Height(bool bib) const\n{\n\tstatic int height[BSIZE_COUNT] = {\n\t\t1,\n\t\t1,\n\t\t2,\n\t\t2,\n\t\t3,\n\t\t2,\n\t\t3,\n\t\t2,\n\t\t5\n\t};\n\treturn(height[Size] + ((bib && IsBibbed) ? 1 : 0));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Bib_And_Offset -- Determines the bib and appropriate cell offset.        *\n *                                                                                             *\n *    This routine is used to determine what (if any) bib should be used for this building     *\n *    and also the cell offset for the upper left corner of the bib smudge type.               *\n *                                                                                             *\n * INPUT:   bib   -- Reference to the bib that should be used for this building.               *\n *                                                                                             *\n *          cell  -- The cell offset for the upper left corner of the bib. This offset is      *\n *                   relative to the upper left corner of the building.                        *\n *                                                                                             *\n * OUTPUT:  Is a bib required for this building? If the result is true, then the correct       *\n *          bib and cell offset will be filled in.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Bib_And_Offset(SmudgeType & bib, CELL & cell) const\n{\n\tbib = SMUDGE_NONE;\n\n\tif (IsBibbed) {\n\t\tswitch (Width()) {\n\t\t\tcase 2:\n\t\t\t\tbib = SMUDGE_BIB3;\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tbib = SMUDGE_BIB2;\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tbib = SMUDGE_BIB1;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbib = SMUDGE_NONE;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAdjust the bib position for special buildings that have the bib as part\n\t\t**\tof the building art itself.\n\t\t*/\n\t\tif (bib != SMUDGE_NONE) {\n\t\t\tcell += ((Height()-1)*MAP_CELL_W);\n\t\t}\n\t}\n\treturn(bib != SMUDGE_NONE);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Max_Pips -- Determines the maximum pips to display.                      *\n *                                                                                             *\n *    Use this routine to determine the maximum number of pips to display on this building     *\n *    when it is rendered. Typically, this is the tiberium capacity divided by 100.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pips to display on this building when selected.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Max_Pips(void) const\n{\n\tint maxpips = (Width() * ICON_PIXEL_W) / 4;\n\treturn(Bound((int)(Capacity/100), 0, maxpips));\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Raw_Cost -- Fetches the raw (base) cost of this building type.           *\n *                                                                                             *\n *    This routine is used to fetch the real raw base cost of the building. The raw cost       *\n *    is the cost of the building less any free unit that would come with the building         *\n *    if it were built in the normal fashion. Specifically, the helicopter cost is subtracted  *\n *    from the helipad and the harvester cost is subtracted from the refinery. This cost       *\n *    is used for refunding.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the raw (base) cost to build the building of this type.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Raw_Cost(void) const\n{\n\tint cost = TechnoTypeClass::Raw_Cost();\n\n\tif (Type == STRUCT_HELIPAD && !Rule.IsSeparate) {\n\t\tcost -= (AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Cost + AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Cost)/2;\n\t}\n\tif (Type == STRUCT_REFINERY) {\n\t\tcost -= UnitTypeClass::As_Reference(UNIT_HARVESTER).Cost;\n\t}\n\treturn(cost);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Cost_Of -- Fetches the cost of this building.                            *\n *                                                                                             *\n *    This routine will fetch the cost to build the building of this type.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cost to produce this building.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Cost_Of(void) const\n{\n\tif (Rule.IsSeparate && Type == STRUCT_HELIPAD) {\n\t\treturn(Raw_Cost());\n\t}\n\treturn(TechnoTypeClass::Cost_Of());\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Flush_For_Placement -- Tries to clear placement area for this building t *\n *                                                                                             *\n *    This routine is called when a clear space for placement is desired at the cell location  *\n *    specified. Typical use of this routine is by the computer when it wants to build up      *\n *    its base.                                                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the building of this type would like to be placed down at.  *\n *                                                                                             *\n *          house -- Pointer to the house that want to clear the foundation zone.              *\n *                                                                                             *\n * OUTPUT:  Placement is temporarily blocked, please try again later?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Flush_For_Placement(CELL cell, HouseClass * house)  const\n{\n\tbool again = false;\n\tif (cell > 0) {\n\t\tshort const * list = Occupy_List(true);\n\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\n\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\tTechnoClass * occupier = Map[newcell].Cell_Techno();\n\t\t\t\tif (occupier != NULL) {\n\t\t\t\t\tagain = true;\n\t\t\t\t\tif (occupier->House->Is_Ally(house) && occupier->Is_Foot() && !Target_Legal(((FootClass *)occupier)->NavCom)) {\n\t\t\t\t\t\tMap[newcell].Incoming(0, true);\n\t\t\t\t\t} else {\n//\t\t\t\t\t\tBase_Is_Attacked(occupier);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(again);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Read_INI -- Fetch building type data from the INI database.              *\n *                                                                                             *\n *    This routine will fetch the building type class data from the INI database file.         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that will be examined.                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the building entry found and the data extracted?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (TechnoTypeClass::Read_INI(ini)) {\n\t\tSpeed = ini.Get_Bool(Name(), \"WaterBound\", (Speed == SPEED_FLOAT)) ? SPEED_FLOAT : SPEED_NONE;\n\t\tCapacity = ini.Get_Int(Name(), \"Storage\", Capacity);\n\t\tAdjacent = ini.Get_Int(Name(), \"Adjacent\", Adjacent);\n\t\tIsCaptureable = ini.Get_Bool(Name(), \"Capturable\", IsCaptureable);\n\t\tIsPowered = ini.Get_Bool(Name(), \"Powered\", IsPowered);\n\t\tIsBibbed = ini.Get_Bool(Name(), \"Bib\", IsBibbed);\n\t\tIsUnsellable = ini.Get_Bool(Name(), \"Unsellable\", IsUnsellable);\n\t\tIsBase = ini.Get_Bool(Name(), \"BaseNormal\", IsBase);\n\t\tPower = ini.Get_Int(Name(), \"Power\", (Power > 0) ? Power : -Drain);\n\t\tif (Power < 0) {\n\t\t\tDrain = -Power;\n\t\t\tPower = 0;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Coord_Fixup -- Adjusts coordinate to be legal for assignment.            *\n *                                                                                             *\n *    This routine will adjust the specified coordinate so that it will be legal for assignment*\n *    to this building. All buildings are given a coordinate that is in the upper left corner  *\n *    of a cell. This routine will drop the fractional component of the coordinate.            *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to fixup into a legal to assign value.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate that can be assigned to the building.                    *\n *                                                                                             *\n * WARNINGS:   The coordinate is not examined to see if the cell is legal for placing the      *\n *             building. It merely adjusts the coordinate so that is legal at first glance.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n\n\n/***********************************************************************************************\n * BuildingTypeClass::Full_Name -- Fetches the name to give this building.                     *\n *                                                                                             *\n *    This routine will return the displayable given name for this building type. Normally,    *\n *    this is the official name as well, however in the case of civilian buildings, the        *\n *    name will just be \"Civilian Building\" unless special options are in place.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the text number of the building type.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingTypeClass::Full_Name(void) const\n{\n\tif (Debug_Map || Rule.IsNamed || *this < STRUCT_V01 || *this > STRUCT_V37) {\n\t\treturn(TechnoTypeClass::Full_Name());\n\t}\n\treturn(TXT_CIVILIAN_BUILDING);\n}\n"
  },
  {
    "path": "REDALERT/BENCH.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BENCH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BENCH.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 18, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Benchmark::Begin -- Start the benchmark operation.                                        *\n *   Benchmark::Benchmark -- Constructor for the benchmark object.                             *\n *   Benchmark::End -- Mark the end of a benchmarked operation                                 *\n *   Benchmark::Reset -- Clear out the benchmark statistics.                                   *\n *   Benchmark::Value -- Fetch the current average benchmark time.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#if (0)\n#include\t\"bench.h\"\n#include\t\"mpu.h\"\n\n\n/***********************************************************************************************\n * Benchmark::Benchmark -- Constructor for the benchmark object.                               *\n *                                                                                             *\n *    This will construct the benchmark object.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBenchmark::Benchmark(void) :\n\tAverage(0),\n\tCounter(0),\n\tTotalCount(0)\n{\n}\n\n\n/***********************************************************************************************\n * Benchmark::Reset -- Clear out the benchmark statistics.                                     *\n *                                                                                             *\n *    Use this routine to clear out all the accumulated statistics within this benchmark       *\n *    object. The object is set just as if it was freshly constructed.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::Reset(void)\n{\n\tAverage = 0;\n\tCounter = 0;\n\tTotalCount = 0;\n}\n\n\n/***********************************************************************************************\n * Benchmark::Begin -- Start the benchmark operation.                                          *\n *                                                                                             *\n *    Call this routine before the operation to be benchmarked is begun. The corresponding     *\n *    End() function must be called after the operation has completed.                         *\n *                                                                                             *\n * INPUT:   reset -- Should the entire benchmark object be reset at this time as well?         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The Begin() and End() functions are NOT nestable.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::Begin(bool reset)\n{\n\tif (reset) Reset();\n\tClock = 0;\n}\n\n\n/***********************************************************************************************\n * Benchmark::End -- Mark the end of a benchmarked operation                                   *\n *                                                                                             *\n *    This routine is called at the end of the operation that is being benchmarked. It is      *\n *    important to call this routine as soon as possible after the event being benchmarked     *\n *    has completed.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The Being() and End() functions are NOT nestable.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Benchmark::End(void)\n{\n\tunsigned long value = Clock;\n\n\tif (Counter == MAXIMUM_EVENT_COUNT) {\n\t\tAverage -= Average / MAXIMUM_EVENT_COUNT;\n\t\tAverage += value;\n\t} else {\n\t\tAverage += value;\n\t\tCounter++;\n\t}\n\tTotalCount++;\n}\n\n\n/***********************************************************************************************\n * Benchmark::Value -- Fetch the current average benchmark time.                               *\n *                                                                                             *\n *    This routine will take the statistics already accumulated and determine the average      *\n *    time recorded. This value will be returned.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the average time that all events tracked by this object.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned long Benchmark::Value(void) const\n{\n\tif (Counter) {\n\t\treturn(Average / Counter);\n\t}\n\treturn(0);\n}\n#endif"
  },
  {
    "path": "REDALERT/BENCH.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BENCH.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BENCH.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BENCH_H\n#define BENCH_H\n#if (0)\n\n#include\t\"mpu.h\"\n#include\t\"ftimer.h\"\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tThis is a timer access object that will fetch the internal Pentium\n**\tclock value.\n*/\nclass PentiumTimerClass\n{\n\tpublic:\n\t\tunsigned long operator () (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}\n\t\toperator unsigned long (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}\n};\n\n\n/*\n**\tA performance tracking tool object. It is used to track elapsed time. Unlike a simple clock, this\n**\tclass will keep a running average of the duration. Typical use of this would be to benchmark some\n**\tprocess that occurs multiple times. By benchmarking an average time, inconsistencies in a particular\n**\trun can be overcome.\n*/\nclass Benchmark\n{\n\tpublic:\n\t\tBenchmark(void);\n\n\t\tvoid Begin(bool reset=false);\n\t\tvoid End(void);\n\n\t\tvoid Reset(void);\n\t\tunsigned long Value(void) const;\n\t\tunsigned long Count(void) const {return(TotalCount);}\n\n\tprivate:\n\t\t/*\n\t\t**\tThe maximum number of events to keep running average of. If\n\t\t**\tevents exceed this number, then older events drop off the\n\t\t**\taccumulated time. This number needs to be as small as\n\t\t**\tis reasonable. The larger this number gets, the less magnitude\n\t\t**\tthat the benchmark timer can handle. Example; At a value of\n\t\t**\t256, the magnitude of the timer can only be 24 bits.\n\t\t*/\n\t\tenum {MAXIMUM_EVENT_COUNT=256};\n\n\t\t/*\n\t\t**\tThis is the timer the is used to clock the events.\n\t\t*/\n\t\tBasicTimerClass<PentiumTimerClass> Clock;\n\n\t\t/*\n\t\t**\tThe total time off all events tracked so far.\n\t\t*/\n\t\tunsigned long Average;\n\n\t\t/*\n\t\t**\tThe total number of events tracked so far.\n\t\t*/\n\t\tunsigned long Counter;\n\n\t\t/*\n\t\t**\tAbsolute total number of events (possibly greater than the\n\t\t**\tnumber of events tracked in the average).\n\t\t*/\n\t\tunsigned long TotalCount;\n};\n\n\n#endif\n#endif"
  },
  {
    "path": "REDALERT/BFIOFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BFIOFILE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAMFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : November 10, 1995                                            *\n *                                                                                             *\n *                  Last Update : November 10, 1995  [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object.     *\n *   BufferIOFileClass::BufferIOFileClass -- default constructor for a file object.            *\n *   BufferIOFileClass::Cache -- Load part or all of a file data into RAM.                     *\n *   BufferIOFileClass::Close -- Perform a closure of the file.                                *\n *   BufferIOFileClass::Commit -- Writes the cache to the file if it has changed.              *\n *   BufferIOFileClass::Free -- Frees the allocated buffer.                                    *\n *   BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk.        *\n *   BufferIOFileClass::Is_Open -- Determines if the file is open.                             *\n *   BufferIOFileClass::Open -- Assigns name and opens file in one operation.                  *\n *   BufferIOFileClass::Open -- Opens the file object with the rights specified.               *\n *   BufferIOFileClass::Read -- Reads data from the file cache.                                *\n *   BufferIOFileClass::Seek -- Moves the current file pointer in the file.                    *\n *   BufferIOFileClass::Set_Name -- Checks for name changed for a cached file.                 *\n *   BufferIOFileClass::Size -- Determines size of file (in bytes).                            *\n *   BufferIOFileClass::Write -- Writes data to the file cache.                                *\n *   BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"bfiofile.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object.       *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::BufferIOFileClass(char const * filename) :\n\tIsAllocated(false),\n\tIsOpen(false),\n\tIsDiskOpen(false),\n\tIsCached(false),\n\tIsChanged(false),\n\tUseBuffer(false),\n\tBufferRights(0),\n\tBuffer(0),\n\tBufferSize(0),\n\tBufferPos(0),\n\tBufferFilePos(0),\n\tBufferChangeBeg(-1),\n\tBufferChangeEnd(-1),\n\tFileSize(0),\n\tFilePos(0),\n\tTrueFileStart(0)\n{\n\tBufferIOFileClass::Set_Name(filename);\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::BufferIOFileClass -- default constructor for a file object.              *\n *                                                                                             *\n *    This is the default constructor for a file object.                                       *\n *                                                                                             *\n * INPUT:  none                                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::BufferIOFileClass(void) :\n\tIsAllocated(false),\n\tIsOpen(false),\n\tIsDiskOpen(false),\n\tIsCached(false),\n\tIsChanged(false),\n\tUseBuffer(false),\n\tBufferRights(0),\n\tBuffer(0),\n\tBufferSize(0),\n\tBufferPos(0),\n\tBufferFilePos(0),\n\tBufferChangeBeg(-1),\n\tBufferChangeEnd(-1),\n\tFileSize(0),\n\tFilePos(0),\n\tTrueFileStart(0)\n{\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object.                    *\n *                                                                                             *\n *    This destructor will free all memory allocated thru using Cache routines.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nBufferIOFileClass::~BufferIOFileClass(void)\n{\n\tFree();\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Cache -- Load part or all of a file data into RAM.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file load successful?  It could fail if there wasn't enough room     *\n *                to allocate the raw data block.                                              *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk for a potentially very long time.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool BufferIOFileClass::Cache( long size, void * ptr )\n{\n\tif (Buffer) {\n\t\t//\n\t\t// if trying to cache again with size or ptr fail\n\t\t//\n\t\tif (size || ptr) {\n\t\t\treturn( false );\n\t\t} else {\n\t\t\treturn( true );\n\t\t}\n\t}\n\n\tif ( Is_Available() ) {\n\t\tFileSize = Size();\n\t} else {\n\t\tFileSize = 0;\n\t}\n\n\tif (size) {\n\t\t//\n\t\t// minimum buffer size for performance\n\t\t//\n\t\tif (size < MINIMUM_BUFFER_SIZE) {\n\t\t\tsize = MINIMUM_BUFFER_SIZE;\n\n\t\t\t/*\n\t\t\t**\tSpecifying a size smaller than the minimum is an error\n\t\t\t**\tIF a buffer pointer was also specified. In such a case the\n\t\t\t**\tsystem cannot use the buffer.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\tError(EINVAL);\n\t\t\t}\n\t\t}\n\n\t\tBufferSize = size;\n\t} else {\n\t\tBufferSize = FileSize;\n\t}\n\n\t//\n\t// if size == 0 and a ptr to a buffer is specified then that is invalid.\n\t// if the BufferSize is 0 then this must be a new file and no size was\n\t// specified so exit.\n\t//\n\tif ( (size == 0 && ptr) || !BufferSize) {\n\t\treturn( false );\n\t}\n\n\tif (ptr) {\n\t\tBuffer = ptr;\n\t} else {\n\t\tBuffer = new char [BufferSize];\n\t}\n\n\tif (Buffer) {\n\t\tIsAllocated\t\t\t= true;\n\t\tIsDiskOpen\t\t\t= false;\n\t\tBufferPos\t\t\t= 0;\n\t\tBufferFilePos\t\t= 0;\n\t\tBufferChangeBeg\t= -1;\n\t\tBufferChangeEnd\t= -1;\n\t\tFilePos\t\t\t\t= 0;\n\t\tTrueFileStart\t\t= 0;\n\n\t\t//\n\t\t// the file was checked for availability then set the FileSize\n\t\t//\n\t\tif (FileSize) {\n\t\t\tlong readsize;\n\t\t\tint opened = false;\n\t\t\tlong prevpos = 0;\n\n\n\t\t\tif (FileSize <= BufferSize) {\n\t\t\t\treadsize = FileSize;\n\t\t\t} else {\n\t\t\t\treadsize = BufferSize;\n\t\t\t}\n\n\t\t\tif ( Is_Open() ) {\n\t\t\t\t//\n\t\t\t\t// get previous file position\n\t\t\t\t//\n\t\t\t\tprevpos = Seek(0);\n\n\t\t\t\t//\n\t\t\t\t// get true file position\n\t\t\t\t//\n\t\t\t\tif ( RawFileClass::Is_Open() ) {\n\t\t\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\t\t} else {\n\t\t\t\t\tTrueFileStart = prevpos;\n\t\t\t\t}\n\n\t\t\t\tif (FileSize <= BufferSize) {\n\t\t\t\t\t//\n\t\t\t\t\t// if previous position is non-zero seek to the beginning\n\t\t\t\t\t//\n\t\t\t\t\tif (prevpos) {\n\t\t\t\t\t\tSeek(0, SEEK_SET);\n\t\t\t\t\t}\n\n\t\t\t\t\t//\n\t\t\t\t\t// set the buffer position for future reads/writes\n\t\t\t\t\t//\n\t\t\t\t\tBufferPos = prevpos;\n\t\t\t\t} else {\n\t\t\t\t\tBufferFilePos = prevpos;\n\t\t\t\t}\n\n\t\t\t\tFilePos = prevpos;\n\t\t\t} else {\n\t\t\t\tif ( Open() ) {\n\t\t\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\t\t\topened = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlong actual = Read(Buffer, readsize);\n\n\t\t\tif (actual != readsize) {\n\t\t\t\tError(EIO);\n\t\t\t}\n\n\t\t\tif (opened) {\n\t\t\t\tClose();\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// seek to the previous position in the file\n\t\t\t\t//\n\t\t\t\tSeek(prevpos, SEEK_SET);\n\t\t\t}\n\n\t\t\tIsCached = true;\n\t\t}\n\n\t\tUseBuffer = true;\n\t\treturn(true);\n\t}\n\n\tError(ENOMEM);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Free -- Frees the allocated buffer.                                      *\n *                                                                                             *\n *    This routine will free the buffer. By using this in conjunction with the                 *\n *    Cache() function, one can maintain tight control of memory usage.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nvoid BufferIOFileClass::Free(void)\n{\n\tif (Buffer) {\n\t\tif (IsAllocated) {\n\t\t\tdelete [] Buffer;\n\t\t\tIsAllocated = false;\n\t\t}\n\n\t\tBuffer = 0;\n\t}\n\n\tBufferSize\t\t= 0;\n\tIsOpen\t\t\t= false;\n\tIsCached\t\t\t= false;\n\tIsChanged\t\t= false;\n\tUseBuffer\t\t= false;\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Commit -- Writes the cache to the file if it has changed.                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  false, did not need to write the buffer.                                           *\n *          true, wrote the buffer.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool BufferIOFileClass::Commit( void )\n{\n\tlong size;\n\n\n\tif (UseBuffer) {\n\t\tif (IsChanged) {\n\t\t\tsize = BufferChangeEnd - BufferChangeBeg;\n\n\t\t\tif (IsDiskOpen) {\n\t\t\t\tRawFileClass::Seek( TrueFileStart + BufferFilePos +\n\t\t\t\t\t\t\t\t\t\t  BufferChangeBeg, SEEK_SET );\n\t\t\t\tRawFileClass::Write( Buffer, size );\n\t\t\t\tRawFileClass::Seek( TrueFileStart + FilePos, SEEK_SET );\n\t\t\t} else {\n\t\t\t\tRawFileClass::Open();\n\t\t\t\tRawFileClass::Seek( TrueFileStart + BufferFilePos +\n\t\t\t\t\t\t\t\t\t\t  BufferChangeBeg, SEEK_SET );\n\t\t\t\tRawFileClass::Write( Buffer, size );\n\t\t\t\tRawFileClass::Close();\n\t\t\t}\n\n\t\t\tIsChanged = false;\n\t\t\treturn( true );\n\t\t} else {\n\t\t\treturn( false );\n\t\t}\n\t} else {\n\t\treturn( false );\n\t}\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Set_Name -- Checks for name changed for a cached file.                   *\n *                                                                                             *\n *    Checks for a previous filename and that it is cached.  If so, then check the             *\n *    new filename against the old. If they are the same then return that filename.            *\n *    Otherwise, the file object's name is set with just the raw filename as passed            *\n *    to this routine.                                                                         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to set as the name of this file object.        *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the final and complete filename of this file object. This     *\n *          may have a path attached to the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nchar const * BufferIOFileClass::Set_Name(char const * filename)\n{\n\tif ( File_Name() && UseBuffer) {\n\t\tif ( strcmp(filename, File_Name() ) == 0) {\n\t\t\treturn( File_Name() );\n\t\t} else {\n\t\t\tCommit();\n\t\t\tIsCached = false;\n\t\t}\n\t}\n\n\tRawFileClass::Set_Name(filename);\n\treturn( File_Name() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk.          *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/16/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Is_Available(int )\n{\n\tif (UseBuffer) {\n\t\treturn(true);\n\t}\n\n\treturn( RawFileClass::Is_Available() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Is_Open -- Determines if the file is open.                               *\n *                                                                                             *\n *    If part or all of the file is cached, then return that it is opened. A closed file       *\n *    doesn't have a valid pointer.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Is_Open(void) const\n{\n\tif (IsOpen && UseBuffer) {\n\t\treturn( true );\n\t}\n\n\treturn( RawFileClass::Is_Open() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Open -- Assigns name and opens file in one operation.                    *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Open(char const * filename, int rights)\n{\n\tSet_Name(filename);\n\treturn( BufferIOFileClass::Open( rights ) );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Open -- Opens the file object with the rights specified.                 *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nint BufferIOFileClass::Open(int rights)\n{\n\tBufferIOFileClass::Close();\n\n\tif (UseBuffer) {\n\n\t\tBufferRights = rights;\t\t// save rights requested for checks later\n\n\t\tif (rights != READ ||\n\t\t\t (rights == READ && FileSize > BufferSize) ) {\n\n\t\t\tif (rights == WRITE) {\n\t\t\t\tRawFileClass::Open( rights );\n\t\t\t\tRawFileClass::Close();\n\t\t\t\trights = READ | WRITE;\n\t\t\t\tTrueFileStart = 0;\t\t// now writing to single file\n\t\t\t}\n\n\t\t\tif (TrueFileStart) {\n\t\t\t\tUseBuffer = false;\n\t\t\t\tOpen( rights );\n\t\t\t\tUseBuffer = true;\n\t\t\t} else {\n\t\t\t\tRawFileClass::Open( rights );\n\t\t\t}\n\n\t\t\tIsDiskOpen = true;\n\n\t\t\tif (BufferRights == WRITE) {\n\t\t\t\tFileSize = 0;\n\t\t\t}\n\n\t\t} else {\n\t\t\tIsDiskOpen = false;\n\t\t}\n\n\t\tBufferPos\t\t\t= 0;\n\t\tBufferFilePos\t\t= 0;\n\t\tBufferChangeBeg\t= -1;\n\t\tBufferChangeEnd\t= -1;\n\t\tFilePos\t\t\t\t= 0;\n\t\tIsOpen\t\t\t\t= true;\n\t} else {\n\t\tRawFileClass::Open( rights );\n\t}\n\n\treturn( true );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Write -- Writes data to the file cache.                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Write(void const * buffer, long size)\n{\n\tint opened = false;\n\n\tif ( !Is_Open() ) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\topened = true;\n\t}\n\n\tif (UseBuffer) {\n\t\tlong sizewritten = 0;\n\n\t\tif (BufferRights != READ) {\n\t\t\twhile (size) {\n\t\t\t\tlong sizetowrite;\n\n\t\t\t\tif (size >= (BufferSize - BufferPos) ) {\n\t\t\t\t\tsizetowrite = (BufferSize - BufferPos);\n\t\t\t\t} else {\n\t\t\t\t\tsizetowrite = size;\n\t\t\t\t}\n\n\t\t\t\tif (sizetowrite != BufferSize) {\n\n\t\t\t\t\tif ( !IsCached ) {\n\t\t\t\t\t\tlong readsize;\n\n\t\t\t\t\t\tif (FileSize < BufferSize) {\n\t\t\t\t\t\t\treadsize = FileSize;\n\t\t\t\t\t\t\tBufferFilePos = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treadsize = BufferSize;\n\t\t\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( BufferFilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, readsize );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBufferPos\t\t\t= 0;\n\t\t\t\t\t\tBufferChangeBeg\t= -1;\n\t\t\t\t\t\tBufferChangeEnd\t= -1;\n\n\t\t\t\t\t\tIsCached = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmemmove((char *)Buffer + BufferPos, (char *)buffer + sizewritten, sizetowrite);\n\n\t\t\t\tIsChanged = true;\n\t\t\t\tsizewritten += sizetowrite;\n\t\t\t\tsize -= sizetowrite;\n\n\t\t\t\tif (BufferChangeBeg == -1) {\n\t\t\t\t\tBufferChangeBeg = BufferPos;\n\t\t\t\t\tBufferChangeEnd = BufferPos;\n\t\t\t\t} else {\n\t\t\t\t\tif (BufferChangeBeg > BufferPos) {\n\t\t\t\t\t\tBufferChangeBeg = BufferPos;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tBufferPos += sizetowrite;\n\n\t\t\t\tif (BufferChangeEnd < BufferPos) {\n\t\t\t\t\tBufferChangeEnd = BufferPos;\n\t\t\t\t}\n\n\t\t\t\tFilePos = BufferFilePos + BufferPos;\n\n\t\t\t\tif (FileSize < FilePos) {\n\t\t\t\t\tFileSize = FilePos;\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// end of buffer reached?\n\t\t\t\t//\n\t\t\t\tif (BufferPos == BufferSize) {\n\t\t\t\t\tCommit();\n\n\t\t\t\t\tBufferPos = 0;\n\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\tBufferChangeBeg = -1;\n\t\t\t\t\tBufferChangeEnd = -1;\n\n\t\t\t\t\tif (size && FileSize > FilePos) {\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, BufferSize );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tIsCached = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tError(EACCES);\n\t\t}\n\n\t\tsize = sizewritten;\n\t} else {\n\t\tsize = RawFileClass::Write(buffer, size);\n\t}\n\n\tif (opened) {\n\t\tClose();\n\t}\n\n\treturn( size );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Read -- Reads data from the file cache.                                  *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Read(void * buffer, long size)\n{\n\tint opened = false;\n\n\tif ( !Is_Open() ) {\n\t\tif ( Open() ) {\n\t\t\tTrueFileStart = RawFileClass::Seek(0);\n\t\t\topened = true;\n\t\t}\n\t}\n\n\tif (UseBuffer) {\n\t\tlong sizeread = 0;\n\n\t\tif (BufferRights != WRITE) {\n\t\t\twhile (size) {\n\t\t\t\tlong sizetoread;\n\n\t\t\t\tif (size >= (BufferSize - BufferPos) ) {\n\t\t\t\t\tsizetoread = (BufferSize - BufferPos);\n\t\t\t\t} else {\n\t\t\t\t\tsizetoread = size;\n\t\t\t\t}\n\n\t\t\t\tif ( !IsCached ) {\n\t\t\t\t\tlong readsize;\n\n\t\t\t\t\tif (FileSize < BufferSize) {\n\t\t\t\t\t\treadsize = FileSize;\n\t\t\t\t\t\tBufferFilePos = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treadsize = BufferSize;\n\t\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRawFileClass::Seek( BufferFilePos, SEEK_SET );\n\t\t\t\t\t\tRawFileClass::Read( Buffer, readsize );\n\t\t\t\t\t}\n\n\t\t\t\t\tBufferPos\t\t\t= 0;\n\t\t\t\t\tBufferChangeBeg\t= -1;\n\t\t\t\t\tBufferChangeEnd\t= -1;\n\n\t\t\t\t\tIsCached = true;\n\t\t\t\t}\n\n\t\t\t\tmemmove((char *)buffer + sizeread, (char *)Buffer + BufferPos, sizetoread);\n\n\t\t\t\tsizeread += sizetoread;\n\t\t\t\tsize -= sizetoread;\n\t\t\t\tBufferPos += sizetoread;\n\t\t\t\tFilePos = BufferFilePos + BufferPos;\n\n\t\t\t\t//\n\t\t\t\t// end of buffer reached?\n\t\t\t\t//\n\t\t\t\tif (BufferPos == BufferSize) {\n\t\t\t\t\tCommit();\n\n\t\t\t\t\tBufferPos = 0;\n\t\t\t\t\tBufferFilePos = FilePos;\n\t\t\t\t\tBufferChangeBeg = -1;\n\t\t\t\t\tBufferChangeEnd = -1;\n\n\t\t\t\t\tif (size && FileSize > FilePos) {\n\t\t\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRead( Buffer, BufferSize );\n\t\t\t\t\t\t\tSeek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tUseBuffer = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRawFileClass::Seek( FilePos, SEEK_SET );\n\t\t\t\t\t\t\tRawFileClass::Read( Buffer, BufferSize );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tIsCached = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tError(EACCES);\n\t\t}\n\n\t\tsize = sizeread;\n\t} else {\n\t\tsize = RawFileClass::Read(buffer, size);\n\t}\n\n\tif (opened) {\n\t\tClose();\n\t}\n\n\treturn( size );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Seek -- Moves the current file pointer in the file.                      *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/15/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Seek(long pos, int dir)\n{\n\tif (UseBuffer) {\n\t\tbool adjusted = false;\n\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tFilePos = FileSize;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tFilePos = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (TrueFileStart) {\n\t\t\tif (pos >= TrueFileStart) {\n\t\t\t\tpos -= TrueFileStart;\n\t\t\t\tadjusted = true;\n\t\t\t}\n\t\t}\n\n\t\tFilePos += pos;\n\n\t\tif (FilePos < 0) {\n\t\t\tFilePos = 0;\n\t\t}\n\n\t\tif (FilePos > FileSize ) {\n\t\t\tFilePos = FileSize;\n\t\t}\n\n\t\tif (FileSize <= BufferSize) {\n\t\t\tBufferPos = FilePos;\n\t\t} else {\n\t\t\tif (FilePos >= BufferFilePos &&\n\t\t\t\t FilePos < (BufferFilePos + BufferSize) ) {\n\t\t\t\tBufferPos = FilePos - BufferFilePos;\n\t\t\t} else {\n\t\t\t\tCommit();\n// check!!\n\t\t\t\tif (TrueFileStart) {\n\t\t\t\t\tUseBuffer = false;\n\t\t\t\t\tSeek(FilePos, SEEK_SET);\n\t\t\t\t\tUseBuffer = true;\n\t\t\t\t} else {\n\t\t\t\t\tRawFileClass::Seek(FilePos, SEEK_SET);\n\t\t\t\t}\n\n\t\t\t\tIsCached = false;\n\t\t\t}\n\t\t}\n\n\t\tif (TrueFileStart && adjusted) {\n\t\t\treturn( FilePos + TrueFileStart );\n\t\t}\n\n\t\treturn( FilePos );\n\t}\n\n\treturn( RawFileClass::Seek(pos, dir) );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Size -- Determines size of file (in bytes).                              *\n *                                                                                             *\n *    If part or all of the file is cached, then the size of the file is already               *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nlong BufferIOFileClass::Size(void)\n{\n\tif (IsOpen && UseBuffer) {\n\t\treturn( FileSize );\n\t}\n\n\treturn( RawFileClass::Size() );\n}\n\n\n/***********************************************************************************************\n * BufferIOFileClass::Close -- Perform a closure of the file.                                  *\n *                                                                                             *\n *    Call Commit() to write the buffer if the file is cached and the buffer has changed,      *\n *    then call lower level Close().                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nvoid BufferIOFileClass::Close(void)\n{\n\tif (UseBuffer) {\n\t\tCommit();\n\n\t\tif (IsDiskOpen) {\n\n\t\t\tif (TrueFileStart) {\n\t\t\t\tUseBuffer = false;\n\t\t\t\tClose();\n\t\t\t\tUseBuffer = true;\n\t\t\t} else {\n\t\t\t\tRawFileClass::Close();\n\t\t\t}\n\n\t\t\tIsDiskOpen = false;\n\t\t}\n\n\t\tIsOpen = false;\n\t} else {\n\t\tRawFileClass::Close();\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/BFIOFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BFIOFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : BFIOFILE.H                                                   *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : November 10, 1995                                            *\n *                                                                                             *\n *                  Last Update : November 10, 1995  [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BFIOFILE_H\n#define BFIOFILE_H\n\n#include\t\"rawfile.h\"\n\n/*\n**\tThis derivation of the raw file class handles buffering the input/output in order to\n**\tachieve greater speed. The buffering is not active by default. It must be activated\n**\tby setting the appropriate buffer through the Cache() function.\n*/\nclass BufferIOFileClass : public RawFileClass\n{\n\tpublic:\n\n\t\tBufferIOFileClass(char const *filename);\n\t\tBufferIOFileClass(void);\n\t\tvirtual ~BufferIOFileClass(void);\n\n\t\tbool Cache( long size=0, void *ptr=NULL );\n\t\tvoid Free( void );\n\t\tbool Commit( void );\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\n\t\tenum {MINIMUM_BUFFER_SIZE=1024};\n\n\tprivate:\n\n\t\tunsigned IsAllocated:1;\n\t\tunsigned IsOpen:1;\n\t\tunsigned IsDiskOpen:1;\n\t\tunsigned IsCached:1;\n\t\tunsigned IsChanged:1;\n\t\tunsigned UseBuffer:1;\n\n\t\tint BufferRights;\n\n\t\tvoid *Buffer;\n\n\t\tlong BufferSize;\n\t\tlong BufferPos;\n\t\tlong BufferFilePos;\n\t\tlong BufferChangeBeg;\n\t\tlong BufferChangeEnd;\n\t\tlong FileSize;\n\t\tlong FilePos;\n\t\tlong TrueFileStart;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/BIGCHECK.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//\tBigCheck.cpp\n//\tajw 9/14/98\n\n#ifdef WOLAPI_INTEGRATION\n\n#include\t\"function.h\"\n#include\t\"bigcheck.h\"\n\n//***********************************************************************************************\nint BigCheckBoxClass::Draw_Me( int forced )\n{\n\tif (ToggleClass::Draw_Me(forced))\n\t{\n\t\tHide_Mouse();\n\n\t\tif( !IsOn )\n\t\t{\n\t\t\tif( !IsDisabled )\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 0, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\telse\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 2, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( !IsDisabled )\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 1, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\telse\n\t\t\t\tCC_Draw_Shape( MFCD::Retrieve( \"bigcheck.shp\" ), 3, X, Y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t}\n\n\t\tTextPrintType flags = TextFlags;\n\t\t\n\t\tRemapControlType* pScheme;\n\t\t\n//\t\tif( !IsDisabled )\n\t\t\tpScheme = GadgetClass::Get_Color_Scheme();\n//\t\telse\n//\t\t{\n//\t\t\tpScheme = &GreyScheme;\n//\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n//\t\t}\n\n\t\tConquer_Clip_Text_Print( szCaption, X + BIGCHECK_OFFSETX, Y + BIGCHECK_OFFSETY, pScheme, TBLACK, flags, Width, 0 );\n\n\t\tShow_Mouse();\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n//***********************************************************************************************\nint BigCheckBoxClass::Action(unsigned flags, KeyNumType & key)\n{\n/*\tif( flags & LEFTPRESS )\n\t{\n\t\tif (IsOn) {\n\t\t\tTurn_Off();\n\t\t} else {\n\t\t\tTurn_On();\n\t\t}\n\t}\n*/\n\treturn(ToggleClass::Action(flags, key));\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/BIGCHECK.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//\tBigcheck.h\n//\tajw 9/14/98\n\n#ifdef WOLAPI_INTEGRATION\n\n#ifndef BIGCHECKBOX_H\n#define BIGCHECKBOX_H\n\n#include\t\"toggle.h\"\n\n#define BIGCHECK_OFFSETX\t20\n#define BIGCHECK_OFFSETY\t0\n\n//***********************************************************************************************\nclass BigCheckBoxClass : public ToggleClass\n{\npublic:\n\tBigCheckBoxClass( unsigned id, int x, int y, int w, int h, const char* szCaptionIn, TextPrintType TextFlags, \n\t\t\t\t\t\t\tbool bInitiallyChecked = false ) :\n\t\tToggleClass( id, x, y, w, h ),\n\t\tTextFlags( TextFlags )\n\t{\n\t\tszCaption = new char[ strlen( szCaptionIn ) + 1 ];\n\t\tstrcpy( szCaption, szCaptionIn );\n\t\tif( bInitiallyChecked )\n\t\t\tTurn_On();\n\t\tIsToggleType = 1;\n\t}\n\tvirtual ~BigCheckBoxClass()\n\t{\n\t\tdelete [] szCaption;\n\t}\n\n\tvirtual int Draw_Me(int forced=false);\n\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\tbool\tToggle()\n\t{\n\t\tif( IsOn )\n\t\t{\n\t\t\tTurn_Off();\n\t\t\treturn false;\n\t\t}\n\t\tTurn_On();\n\t\treturn true;\n\t}\n\nprotected:\n\tTextPrintType\tTextFlags;\n\tchar*\t\t\tszCaption;\n\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/BLOWFISH.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLOWFISH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWFISH.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/14/96                                                     *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowfishEngine::Decrypt -- Decrypts data using blowfish algorithm.                        *\n *   BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data.                            *\n *   BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm.        *\n *   BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing.          *\n *   BlowfishEngine::Submit_Key -- Submit a key that will allow data processing.               *\n *   BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"blowfish.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/*\n**\tByte order controlled long integer. This integer is constructed\n**\tso that character 0 (C0) is the most significant byte of the\n**\tinteger. This is biased toward big endian architecture, but that\n**\tjust happens to be how the Blowfish algorithm was designed.\n*/\ntypedef union {\n\tunsigned long Long;\n\tstruct {\n\t\tunsigned char C3;\n\t\tunsigned char C2;\n\t\tunsigned char C1;\n\t\tunsigned char C0;\n\t} Char;\n} Int;\n\n\n/***********************************************************************************************\n * BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine.                      *\n *                                                                                             *\n *    This destructor will clear out the s-box tables so that even if the memory for the       *\n *    class remains, it will contain no compromising data.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBlowfishEngine::~BlowfishEngine(void)\n{\n\tif (IsKeyed) {\n\t\tSubmit_Key(NULL, 0);\n\t}\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Submit_Key -- Submit a key that will allow data processing.                 *\n *                                                                                             *\n *    This routine must be called before any data can be encrypted or decrypted. This routine  *\n *    need only be called when the key is to be changed or set for the first time. Once the    *\n *    key has been set, the engine may be used to encrypt, decrypt, or both operations         *\n *    indefinitely. The key must be 56 bytes or less in length. This is necessary because      *\n *    any keys longer than that will not correctly affect the encryption process.              *\n *                                                                                             *\n *    If the key pointer is NULL, then the S-Box tables are reset to identity. This will       *\n *    mask the previous key setting. Use this method to clear the engine after processing in   *\n *    order to gain a measure of security.                                                     *\n *                                                                                             *\n * INPUT:   key      -- Pointer to the key data block.                                         *\n *                                                                                             *\n *          length   -- The length of the submitted key.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is a time consuming process.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Submit_Key(void const * key, int length)\n{\n\tassert(length <= MAX_KEY_LENGTH);\n\n\t/*\n\t**\tInitialize the permutation and S-Box tables to a known\n\t**\tconstant value.\n\t*/\n\tmemcpy(P_Encrypt, P_Init, sizeof(P_Init));\n\tmemcpy(P_Decrypt, P_Init, sizeof(P_Init));\n\tmemcpy(bf_S, S_Init, sizeof(S_Init));\n\n\t/*\n\t**\tValidate parameters.\n\t*/\n\tif (key == 0 || length == 0) {\n\t\tIsKeyed = false;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tCombine the key with the permutation table. Wrap the key\n\t**\tas many times as necessary to ensure that the entire\n\t**\tpermutation table has been modified. The key is lifted\n\t**\tinto a long by using endian independent means.\n\t*/\n\tint j = 0;\n\tunsigned char const * key_ptr = (unsigned char const *)key;\n\tunsigned long * p_ptr = &P_Encrypt[0];\n\tfor (int index = 0; index < ROUNDS+2; index++) {\n\t\tunsigned long data = 0;\n\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\t\tdata = (data << CHAR_BIT) | key_ptr[j++ % length];\n\n\t\t*p_ptr++ ^= data;\n\t}\n\n\t/*\n\t**\tThe permutation table must be scrambled by means of the key. This\n\t**\tis how the key is factored into the encryption -- by merely altering\n\t**\tthe permutation (and S-Box) tables. Because this transformation alters\n\t**\tthe table data WHILE it is using the table data, the tables are\n\t**\tthoroughly obfuscated by this process.\n\t*/\n\tunsigned long left = 0x00000000L;\n\tunsigned long right = 0x00000000L;\n\tunsigned long * p_en = &P_Encrypt[0];\t\t\t// Encryption table.\n\tunsigned long * p_de = &P_Decrypt[ROUNDS+1];\t// Decryption table.\n\tfor (int p_index = 0; p_index < ROUNDS+2; p_index += 2) {\n\t\tSub_Key_Encrypt(left, right);\n\n\t\t*p_en++ = left;\n\t\t*p_en++ = right;\n\n\t\t*p_de-- = left;\n\t\t*p_de-- = right;\n\t}\n\n\t/*\n\t**\tPerform a similar transmutation to the S-Box tables. Also notice that the\n\t**\tworking 64 bit number is carried into this process from the previous\n\t**\toperation.\n\t*/\n\tfor (int sbox_index = 0; sbox_index < 4; sbox_index++) {\n\t\tfor (int ss_index = 0; ss_index < UCHAR_MAX+1; ss_index += 2) {\n\t\t\tSub_Key_Encrypt(left, right);\n\t\t\tbf_S[sbox_index][ss_index] = left;\n\t\t\tbf_S[sbox_index][ss_index + 1] = right;\n\t\t}\n\t}\n\n\tIsKeyed = true;\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data.                              *\n *                                                                                             *\n *    Use this routine to encrypt an arbitrary block of data. The block must be an even        *\n *    multiple of 8 bytes. Any bytes left over will not be encrypted. The 8 byte requirement   *\n *    is necessary because the underlying algorithm processes blocks in 8 byte chunks.         *\n *    Partial blocks are unrecoverable and useless.                                            *\n *                                                                                             *\n * INPUT:   plaintext-- Pointer to the data block to be encrypted.                             *\n *                                                                                             *\n *          length   -- The length of the data block.                                          *\n *                                                                                             *\n *          cyphertext- Pointer to the output buffer that will hold the encrypted data.        *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes encrypted.                                 *\n *                                                                                             *\n * WARNINGS:   You must submit the key before calling this routine. This will only encrypt     *\n *             the plaintext in 8 byte increments. Modulo bytes left over are not processed.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowfishEngine::Encrypt(void const * plaintext, int length, void * cyphertext)\n{\n\tif (plaintext == 0 || length == 0) {\n\t\treturn(0);\n\t}\n\tif (cyphertext == 0) cyphertext = (void *)plaintext;\n\n\tif (IsKeyed) {\n\n\t\t/*\n\t\t**\tValidate parameters.\n\t\t*/\n\t\tint blocks = length / BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tProcess the buffer in 64 bit chunks.\n\t\t*/\n\t\tfor (int index = 0; index < blocks; index++) {\n\t\t\tProcess_Block(plaintext, cyphertext, P_Encrypt);\n\t\t\tplaintext = ((char *)plaintext) + BYTES_PER_BLOCK;\n\t\t\tcyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;\n\t\t}\n\t\tint encrypted = blocks * BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tCopy over any trailing left over appendix bytes.\n\t\t*/\n\t\tif (encrypted < length) {\n\t\t\tmemmove(cyphertext, plaintext, length - encrypted);\n\t\t}\n\n\t\treturn(encrypted);\n\t}\n\n\t/*\n\t**\tNon-keyed processing merely copies the data.\n\t*/\n\tif (plaintext != cyphertext) {\n\t\tmemmove(cyphertext, plaintext, length);\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Decrypt -- Decrypt an arbitrary block of data.                              *\n *                                                                                             *\n *    Use this routine to decrypt an arbitrary block of data. The block must be an even        *\n *    multiple of 8 bytes. Any bytes left over will not be decrypted. The 8 byte requirement   *\n *    is necessary because the underlying algorithm processes blocks in 8 byte chunks.         *\n *    Partial blocks are unrecoverable and useless.                                            *\n *                                                                                             *\n * INPUT:   cyphertext- Pointer to the data block to be decrypted.                             *\n *                                                                                             *\n *          length   -- The length of the data block.                                          *\n *                                                                                             *\n *          plaintext-- Pointer to the output buffer that will hold the decrypted data.        *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes decrypted.                                 *\n *                                                                                             *\n * WARNINGS:   You must submit the key before calling this routine. This will only decrypt     *\n *             the cyphertext in 8 byte increments. Modulo bytes left over are not processed.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowfishEngine::Decrypt(void const * cyphertext, int length, void * plaintext)\n{\n\tif (cyphertext == 0 || length == 0) {\n\t\treturn(0);\n\t}\n\tif (plaintext == 0) plaintext = (void *)cyphertext;\n\n\tif (IsKeyed) {\n\n\t\t/*\n\t\t**\tValidate parameters.\n\t\t*/\n\t\tint blocks = length / BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tProcess the buffer in 64 bit chunks.\n\t\t*/\n\t\tfor (int index = 0; index < blocks; index++) {\n\t\t\tProcess_Block(cyphertext, plaintext, P_Decrypt);\n\t\t\tcyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;\n\t\t\tplaintext = ((char *)plaintext) + BYTES_PER_BLOCK;\n\t\t}\n\t\tint encrypted = blocks * BYTES_PER_BLOCK;\n\n\t\t/*\n\t\t**\tCopy over any trailing left over appendix bytes.\n\t\t*/\n\t\tif (encrypted < length) {\n\t\t\tmemmove(plaintext, cyphertext, length - encrypted);\n\t\t}\n\n\t\treturn(encrypted);\n\t}\n\n\t/*\n\t**\tNon-keyed processing merely copies the data.\n\t*/\n\tif (plaintext != cyphertext) {\n\t\tmemmove(plaintext, cyphertext, length);\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm.          *\n *                                                                                             *\n *    This is the main processing routine for encryption and decryption. The algorithm         *\n *    consists of a 16 round Feistal network and uses mathematics from different algebraic     *\n *    groups (strengthens against differential cryptanalysis). The large S-Boxes and the       *\n *    rounds strengthen it against linear cryptanalysis.                                       *\n *                                                                                             *\n * INPUT:   plaintext   -- Pointer to the source text (it actually might be a pointer to       *\n *                         the cyphertext if this is called as a decryption process).          *\n *                                                                                             *\n *          cyphertext  -- Pointer to the output buffer that will hold the processed block.    *\n *                                                                                             *\n *          ptable      -- Pointer to the permutation table. This algorithm will encrypt       *\n *                         and decrypt using the same S-Box tables. The encryption control     *\n *                         is handled by the permutation table.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The source and destination buffers must be 8 bytes long.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable)\n{\n\t/*\n\t**\tInput the left and right halves of the source block such that\n\t**\tthe byte order is constant regardless of the endian\n\t**\tpersuasion of the current processor. The blowfish algorithm is\n\t**\tbiased toward \"big endian\" architecture and some optimizations\n\t**\tcould be done for big endian processors in that case.\n\t*/\n\tunsigned char const * source = (unsigned char const *)plaintext;\n\tInt left;\n\tleft.Char.C0 = *source++;\n\tleft.Char.C1 = *source++;\n\tleft.Char.C2 = *source++;\n\tleft.Char.C3 = *source++;\n\n\tInt right;\n\tright.Char.C0 = *source++;\n\tright.Char.C1 = *source++;\n\tright.Char.C2 = *source++;\n\tright.Char.C3 = *source;\n\n\t/*\n\t**\tPerform all Feistal rounds on the block. This is the encryption/decryption\n\t**\tprocess. Since there is an exchange that occurs after each round, two\n\t**\trounds are combined in this loop to avoid unnecessary exchanging.\n\t*/\n\tfor (int index = 0; index < ROUNDS/2; index++) {\n\t\tleft.Long ^= *ptable++;\n\t\tright.Long ^= ((( bf_S[0][left.Char.C0] + bf_S[1][left.Char.C1]) ^ bf_S[2][left.Char.C2]) + bf_S[3][left.Char.C3]);\n\t\tright.Long ^= *ptable++;\n\t\tleft.Long ^= ((( bf_S[0][right.Char.C0] + bf_S[1][right.Char.C1]) ^ bf_S[2][right.Char.C2]) + bf_S[3][right.Char.C3]);\n\t}\n\n\t/*\n\t**\tThe final two longs in the permutation table are processed into the block.\n\t**\tThe left and right halves are still reversed as a side effect of the last\n\t**\tround.\n\t*/\n\tleft.Long ^= *ptable++;\n\tright.Long ^= *ptable;\n\n\t/*\n\t**\tThe final block data is output in endian architecture\n\t**\tindependent format. Notice that the blocks are output as\n\t**\tright first and left second. This is to counteract the final\n\t**\tsuperfluous exchange that occurs as a side effect of the\n\t**\tencryption rounds.\n\t*/\n\tunsigned char * out = (unsigned char *)cyphertext;\n\t*out++ = right.Char.C0;\n\t*out++ = right.Char.C1;\n\t*out++ = right.Char.C2;\n\t*out++ = right.Char.C3;\n\n\t*out++ = left.Char.C0;\n\t*out++ = left.Char.C1;\n\t*out++ = left.Char.C2;\n\t*out = left.Char.C3;\n}\n\n\n/***********************************************************************************************\n * BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing.            *\n *                                                                                             *\n *    This is the same as the normal process block function but it doesn't have the endian     *\n *    fixup logic. Since this routine is only called for S-Box table generation and it is      *\n *    known that the S-Box initial data is already in local machine endian format, the         *\n *    byte order fixups are not needed. This also has a tendency to speed up S-Box generation  *\n *    as well.                                                                                 *\n *                                                                                             *\n * INPUT:   left  -- The left half of the data block.                                          *\n *                                                                                             *\n *          right -- The right half of the data block.                                         *\n *                                                                                             *\n * OUTPUT:  none, but the processed block is stored back into the left and right half          *\n *          integers.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowfishEngine::Sub_Key_Encrypt(unsigned long & left, unsigned long & right)\n{\n\tInt l;\n\tl.Long = left;\n\n\tInt r;\n\tr.Long = right;\n\n\tfor (int index = 0; index < ROUNDS; index += 2) {\n\t\tl.Long ^= P_Encrypt[index];\n\t\tr.Long ^= ((( bf_S[0][l.Char.C0] + bf_S[1][l.Char.C1]) ^ bf_S[2][l.Char.C2]) + bf_S[3][l.Char.C3]);\n\t\tr.Long ^= P_Encrypt[index+1];\n\t\tl.Long ^= ((( bf_S[0][r.Char.C0] + bf_S[1][r.Char.C1]) ^ bf_S[2][r.Char.C2]) + bf_S[3][r.Char.C3]);\n\t}\n\tleft = r.Long ^ P_Encrypt[ROUNDS+1];\n\tright = l.Long ^ P_Encrypt[ROUNDS];\n}\n\n\n/*\n**\tThese tables have the bytes stored in machine endian format. Because of this,\n**\ta special block cypher routine is needed when the sub-keys are generated.\n**\tThis is kludgier than it otherwise should be. However, storing these\n**\tintegers in machine independent format would be even more painful.\n*/\n\nunsigned long const BlowfishEngine::P_Init[BlowfishEngine::ROUNDS+2] = {\n\t0x243F6A88U,0x85A308D3U,0x13198A2EU,0x03707344U,0xA4093822U,0x299F31D0U,0x082EFA98U,0xEC4E6C89U,\n\t0x452821E6U,0x38D01377U,0xBE5466CFU,0x34E90C6CU,0xC0AC29B7U,0xC97C50DDU,0x3F84D5B5U,0xB5470917U,\n\t0x9216D5D9U,0x8979FB1BU\n} ;\n\nunsigned long const BlowfishEngine::S_Init[4][UCHAR_MAX+1] = {\n\t{\n\t\t0xD1310BA6U,0x98DFB5ACU,0x2FFD72DBU,0xD01ADFB7U,0xB8E1AFEDU,0x6A267E96U,0xBA7C9045U,0xF12C7F99U,\n\t\t0x24A19947U,0xB3916CF7U,0x0801F2E2U,0x858EFC16U,0x636920D8U,0x71574E69U,0xA458FEA3U,0xF4933D7EU,\n\t\t0x0D95748FU,0x728EB658U,0x718BCD58U,0x82154AEEU,0x7B54A41DU,0xC25A59B5U,0x9C30D539U,0x2AF26013U,\n\t\t0xC5D1B023U,0x286085F0U,0xCA417918U,0xB8DB38EFU,0x8E79DCB0U,0x603A180EU,0x6C9E0E8BU,0xB01E8A3EU,\n\t\t0xD71577C1U,0xBD314B27U,0x78AF2FDAU,0x55605C60U,0xE65525F3U,0xAA55AB94U,0x57489862U,0x63E81440U,\n\t\t0x55CA396AU,0x2AAB10B6U,0xB4CC5C34U,0x1141E8CEU,0xA15486AFU,0x7C72E993U,0xB3EE1411U,0x636FBC2AU,\n\t\t0x2BA9C55DU,0x741831F6U,0xCE5C3E16U,0x9B87931EU,0xAFD6BA33U,0x6C24CF5CU,0x7A325381U,0x28958677U,\n\t\t0x3B8F4898U,0x6B4BB9AFU,0xC4BFE81BU,0x66282193U,0x61D809CCU,0xFB21A991U,0x487CAC60U,0x5DEC8032U,\n\t\t0xEF845D5DU,0xE98575B1U,0xDC262302U,0xEB651B88U,0x23893E81U,0xD396ACC5U,0x0F6D6FF3U,0x83F44239U,\n\t\t0x2E0B4482U,0xA4842004U,0x69C8F04AU,0x9E1F9B5EU,0x21C66842U,0xF6E96C9AU,0x670C9C61U,0xABD388F0U,\n\t\t0x6A51A0D2U,0xD8542F68U,0x960FA728U,0xAB5133A3U,0x6EEF0B6CU,0x137A3BE4U,0xBA3BF050U,0x7EFB2A98U,\n\t\t0xA1F1651DU,0x39AF0176U,0x66CA593EU,0x82430E88U,0x8CEE8619U,0x456F9FB4U,0x7D84A5C3U,0x3B8B5EBEU,\n\t\t0xE06F75D8U,0x85C12073U,0x401A449FU,0x56C16AA6U,0x4ED3AA62U,0x363F7706U,0x1BFEDF72U,0x429B023DU,\n\t\t0x37D0D724U,0xD00A1248U,0xDB0FEAD3U,0x49F1C09BU,0x075372C9U,0x80991B7BU,0x25D479D8U,0xF6E8DEF7U,\n\t\t0xE3FE501AU,0xB6794C3BU,0x976CE0BDU,0x04C006BAU,0xC1A94FB6U,0x409F60C4U,0x5E5C9EC2U,0x196A2463U,\n\t\t0x68FB6FAFU,0x3E6C53B5U,0x1339B2EBU,0x3B52EC6FU,0x6DFC511FU,0x9B30952CU,0xCC814544U,0xAF5EBD09U,\n\t\t0xBEE3D004U,0xDE334AFDU,0x660F2807U,0x192E4BB3U,0xC0CBA857U,0x45C8740FU,0xD20B5F39U,0xB9D3FBDBU,\n\t\t0x5579C0BDU,0x1A60320AU,0xD6A100C6U,0x402C7279U,0x679F25FEU,0xFB1FA3CCU,0x8EA5E9F8U,0xDB3222F8U,\n\t\t0x3C7516DFU,0xFD616B15U,0x2F501EC8U,0xAD0552ABU,0x323DB5FAU,0xFD238760U,0x53317B48U,0x3E00DF82U,\n\t\t0x9E5C57BBU,0xCA6F8CA0U,0x1A87562EU,0xDF1769DBU,0xD542A8F6U,0x287EFFC3U,0xAC6732C6U,0x8C4F5573U,\n\t\t0x695B27B0U,0xBBCA58C8U,0xE1FFA35DU,0xB8F011A0U,0x10FA3D98U,0xFD2183B8U,0x4AFCB56CU,0x2DD1D35BU,\n\t\t0x9A53E479U,0xB6F84565U,0xD28E49BCU,0x4BFB9790U,0xE1DDF2DAU,0xA4CB7E33U,0x62FB1341U,0xCEE4C6E8U,\n\t\t0xEF20CADAU,0x36774C01U,0xD07E9EFEU,0x2BF11FB4U,0x95DBDA4DU,0xAE909198U,0xEAAD8E71U,0x6B93D5A0U,\n\t\t0xD08ED1D0U,0xAFC725E0U,0x8E3C5B2FU,0x8E7594B7U,0x8FF6E2FBU,0xF2122B64U,0x8888B812U,0x900DF01CU,\n\t\t0x4FAD5EA0U,0x688FC31CU,0xD1CFF191U,0xB3A8C1ADU,0x2F2F2218U,0xBE0E1777U,0xEA752DFEU,0x8B021FA1U,\n\t\t0xE5A0CC0FU,0xB56F74E8U,0x18ACF3D6U,0xCE89E299U,0xB4A84FE0U,0xFD13E0B7U,0x7CC43B81U,0xD2ADA8D9U,\n\t\t0x165FA266U,0x80957705U,0x93CC7314U,0x211A1477U,0xE6AD2065U,0x77B5FA86U,0xC75442F5U,0xFB9D35CFU,\n\t\t0xEBCDAF0CU,0x7B3E89A0U,0xD6411BD3U,0xAE1E7E49U,0x00250E2DU,0x2071B35EU,0x226800BBU,0x57B8E0AFU,\n\t\t0x2464369BU,0xF009B91EU,0x5563911DU,0x59DFA6AAU,0x78C14389U,0xD95A537FU,0x207D5BA2U,0x02E5B9C5U,\n\t\t0x83260376U,0x6295CFA9U,0x11C81968U,0x4E734A41U,0xB3472DCAU,0x7B14A94AU,0x1B510052U,0x9A532915U,\n\t\t0xD60F573FU,0xBC9BC6E4U,0x2B60A476U,0x81E67400U,0x08BA6FB5U,0x571BE91FU,0xF296EC6BU,0x2A0DD915U,\n\t\t0xB6636521U,0xE7B9F9B6U,0xFF34052EU,0xC5855664U,0x53B02D5DU,0xA99F8FA1U,0x08BA4799U,0x6E85076AU,\n\t},{\n\t\t0x4B7A70E9U,0xB5B32944U,0xDB75092EU,0xC4192623U,0xAD6EA6B0U,0x49A7DF7DU,0x9CEE60B8U,0x8FEDB266U,\n\t\t0xECAA8C71U,0x699A17FFU,0x5664526CU,0xC2B19EE1U,0x193602A5U,0x75094C29U,0xA0591340U,0xE4183A3EU,\n\t\t0x3F54989AU,0x5B429D65U,0x6B8FE4D6U,0x99F73FD6U,0xA1D29C07U,0xEFE830F5U,0x4D2D38E6U,0xF0255DC1U,\n\t\t0x4CDD2086U,0x8470EB26U,0x6382E9C6U,0x021ECC5EU,0x09686B3FU,0x3EBAEFC9U,0x3C971814U,0x6B6A70A1U,\n\t\t0x687F3584U,0x52A0E286U,0xB79C5305U,0xAA500737U,0x3E07841CU,0x7FDEAE5CU,0x8E7D44ECU,0x5716F2B8U,\n\t\t0xB03ADA37U,0xF0500C0DU,0xF01C1F04U,0x0200B3FFU,0xAE0CF51AU,0x3CB574B2U,0x25837A58U,0xDC0921BDU,\n\t\t0xD19113F9U,0x7CA92FF6U,0x94324773U,0x22F54701U,0x3AE5E581U,0x37C2DADCU,0xC8B57634U,0x9AF3DDA7U,\n\t\t0xA9446146U,0x0FD0030EU,0xECC8C73EU,0xA4751E41U,0xE238CD99U,0x3BEA0E2FU,0x3280BBA1U,0x183EB331U,\n\t\t0x4E548B38U,0x4F6DB908U,0x6F420D03U,0xF60A04BFU,0x2CB81290U,0x24977C79U,0x5679B072U,0xBCAF89AFU,\n\t\t0xDE9A771FU,0xD9930810U,0xB38BAE12U,0xDCCF3F2EU,0x5512721FU,0x2E6B7124U,0x501ADDE6U,0x9F84CD87U,\n\t\t0x7A584718U,0x7408DA17U,0xBC9F9ABCU,0xE94B7D8CU,0xEC7AEC3AU,0xDB851DFAU,0x63094366U,0xC464C3D2U,\n\t\t0xEF1C1847U,0x3215D908U,0xDD433B37U,0x24C2BA16U,0x12A14D43U,0x2A65C451U,0x50940002U,0x133AE4DDU,\n\t\t0x71DFF89EU,0x10314E55U,0x81AC77D6U,0x5F11199BU,0x043556F1U,0xD7A3C76BU,0x3C11183BU,0x5924A509U,\n\t\t0xF28FE6EDU,0x97F1FBFAU,0x9EBABF2CU,0x1E153C6EU,0x86E34570U,0xEAE96FB1U,0x860E5E0AU,0x5A3E2AB3U,\n\t\t0x771FE71CU,0x4E3D06FAU,0x2965DCB9U,0x99E71D0FU,0x803E89D6U,0x5266C825U,0x2E4CC978U,0x9C10B36AU,\n\t\t0xC6150EBAU,0x94E2EA78U,0xA5FC3C53U,0x1E0A2DF4U,0xF2F74EA7U,0x361D2B3DU,0x1939260FU,0x19C27960U,\n\t\t0x5223A708U,0xF71312B6U,0xEBADFE6EU,0xEAC31F66U,0xE3BC4595U,0xA67BC883U,0xB17F37D1U,0x018CFF28U,\n\t\t0xC332DDEFU,0xBE6C5AA5U,0x65582185U,0x68AB9802U,0xEECEA50FU,0xDB2F953BU,0x2AEF7DADU,0x5B6E2F84U,\n\t\t0x1521B628U,0x29076170U,0xECDD4775U,0x619F1510U,0x13CCA830U,0xEB61BD96U,0x0334FE1EU,0xAA0363CFU,\n\t\t0xB5735C90U,0x4C70A239U,0xD59E9E0BU,0xCBAADE14U,0xEECC86BCU,0x60622CA7U,0x9CAB5CABU,0xB2F3846EU,\n\t\t0x648B1EAFU,0x19BDF0CAU,0xA02369B9U,0x655ABB50U,0x40685A32U,0x3C2AB4B3U,0x319EE9D5U,0xC021B8F7U,\n\t\t0x9B540B19U,0x875FA099U,0x95F7997EU,0x623D7DA8U,0xF837889AU,0x97E32D77U,0x11ED935FU,0x16681281U,\n\t\t0x0E358829U,0xC7E61FD6U,0x96DEDFA1U,0x7858BA99U,0x57F584A5U,0x1B227263U,0x9B83C3FFU,0x1AC24696U,\n\t\t0xCDB30AEBU,0x532E3054U,0x8FD948E4U,0x6DBC3128U,0x58EBF2EFU,0x34C6FFEAU,0xFE28ED61U,0xEE7C3C73U,\n\t\t0x5D4A14D9U,0xE864B7E3U,0x42105D14U,0x203E13E0U,0x45EEE2B6U,0xA3AAABEAU,0xDB6C4F15U,0xFACB4FD0U,\n\t\t0xC742F442U,0xEF6ABBB5U,0x654F3B1DU,0x41CD2105U,0xD81E799EU,0x86854DC7U,0xE44B476AU,0x3D816250U,\n\t\t0xCF62A1F2U,0x5B8D2646U,0xFC8883A0U,0xC1C7B6A3U,0x7F1524C3U,0x69CB7492U,0x47848A0BU,0x5692B285U,\n\t\t0x095BBF00U,0xAD19489DU,0x1462B174U,0x23820E00U,0x58428D2AU,0x0C55F5EAU,0x1DADF43EU,0x233F7061U,\n\t\t0x3372F092U,0x8D937E41U,0xD65FECF1U,0x6C223BDBU,0x7CDE3759U,0xCBEE7460U,0x4085F2A7U,0xCE77326EU,\n\t\t0xA6078084U,0x19F8509EU,0xE8EFD855U,0x61D99735U,0xA969A7AAU,0xC50C06C2U,0x5A04ABFCU,0x800BCADCU,\n\t\t0x9E447A2EU,0xC3453484U,0xFDD56705U,0x0E1E9EC9U,0xDB73DBD3U,0x105588CDU,0x675FDA79U,0xE3674340U,\n\t\t0xC5C43465U,0x713E38D8U,0x3D28F89EU,0xF16DFF20U,0x153E21E7U,0x8FB03D4AU,0xE6E39F2BU,0xDB83ADF7U,\n\t},{\n\t\t0xE93D5A68U,0x948140F7U,0xF64C261CU,0x94692934U,0x411520F7U,0x7602D4F7U,0xBCF46B2EU,0xD4A20068U,\n\t\t0xD4082471U,0x3320F46AU,0x43B7D4B7U,0x500061AFU,0x1E39F62EU,0x97244546U,0x14214F74U,0xBF8B8840U,\n\t\t0x4D95FC1DU,0x96B591AFU,0x70F4DDD3U,0x66A02F45U,0xBFBC09ECU,0x03BD9785U,0x7FAC6DD0U,0x31CB8504U,\n\t\t0x96EB27B3U,0x55FD3941U,0xDA2547E6U,0xABCA0A9AU,0x28507825U,0x530429F4U,0x0A2C86DAU,0xE9B66DFBU,\n\t\t0x68DC1462U,0xD7486900U,0x680EC0A4U,0x27A18DEEU,0x4F3FFEA2U,0xE887AD8CU,0xB58CE006U,0x7AF4D6B6U,\n\t\t0xAACE1E7CU,0xD3375FECU,0xCE78A399U,0x406B2A42U,0x20FE9E35U,0xD9F385B9U,0xEE39D7ABU,0x3B124E8BU,\n\t\t0x1DC9FAF7U,0x4B6D1856U,0x26A36631U,0xEAE397B2U,0x3A6EFA74U,0xDD5B4332U,0x6841E7F7U,0xCA7820FBU,\n\t\t0xFB0AF54EU,0xD8FEB397U,0x454056ACU,0xBA489527U,0x55533A3AU,0x20838D87U,0xFE6BA9B7U,0xD096954BU,\n\t\t0x55A867BCU,0xA1159A58U,0xCCA92963U,0x99E1DB33U,0xA62A4A56U,0x3F3125F9U,0x5EF47E1CU,0x9029317CU,\n\t\t0xFDF8E802U,0x04272F70U,0x80BB155CU,0x05282CE3U,0x95C11548U,0xE4C66D22U,0x48C1133FU,0xC70F86DCU,\n\t\t0x07F9C9EEU,0x41041F0FU,0x404779A4U,0x5D886E17U,0x325F51EBU,0xD59BC0D1U,0xF2BCC18FU,0x41113564U,\n\t\t0x257B7834U,0x602A9C60U,0xDFF8E8A3U,0x1F636C1BU,0x0E12B4C2U,0x02E1329EU,0xAF664FD1U,0xCAD18115U,\n\t\t0x6B2395E0U,0x333E92E1U,0x3B240B62U,0xEEBEB922U,0x85B2A20EU,0xE6BA0D99U,0xDE720C8CU,0x2DA2F728U,\n\t\t0xD0127845U,0x95B794FDU,0x647D0862U,0xE7CCF5F0U,0x5449A36FU,0x877D48FAU,0xC39DFD27U,0xF33E8D1EU,\n\t\t0x0A476341U,0x992EFF74U,0x3A6F6EABU,0xF4F8FD37U,0xA812DC60U,0xA1EBDDF8U,0x991BE14CU,0xDB6E6B0DU,\n\t\t0xC67B5510U,0x6D672C37U,0x2765D43BU,0xDCD0E804U,0xF1290DC7U,0xCC00FFA3U,0xB5390F92U,0x690FED0BU,\n\t\t0x667B9FFBU,0xCEDB7D9CU,0xA091CF0BU,0xD9155EA3U,0xBB132F88U,0x515BAD24U,0x7B9479BFU,0x763BD6EBU,\n\t\t0x37392EB3U,0xCC115979U,0x8026E297U,0xF42E312DU,0x6842ADA7U,0xC66A2B3BU,0x12754CCCU,0x782EF11CU,\n\t\t0x6A124237U,0xB79251E7U,0x06A1BBE6U,0x4BFB6350U,0x1A6B1018U,0x11CAEDFAU,0x3D25BDD8U,0xE2E1C3C9U,\n\t\t0x44421659U,0x0A121386U,0xD90CEC6EU,0xD5ABEA2AU,0x64AF674EU,0xDA86A85FU,0xBEBFE988U,0x64E4C3FEU,\n\t\t0x9DBC8057U,0xF0F7C086U,0x60787BF8U,0x6003604DU,0xD1FD8346U,0xF6381FB0U,0x7745AE04U,0xD736FCCCU,\n\t\t0x83426B33U,0xF01EAB71U,0xB0804187U,0x3C005E5FU,0x77A057BEU,0xBDE8AE24U,0x55464299U,0xBF582E61U,\n\t\t0x4E58F48FU,0xF2DDFDA2U,0xF474EF38U,0x8789BDC2U,0x5366F9C3U,0xC8B38E74U,0xB475F255U,0x46FCD9B9U,\n\t\t0x7AEB2661U,0x8B1DDF84U,0x846A0E79U,0x915F95E2U,0x466E598EU,0x20B45770U,0x8CD55591U,0xC902DE4CU,\n\t\t0xB90BACE1U,0xBB8205D0U,0x11A86248U,0x7574A99EU,0xB77F19B6U,0xE0A9DC09U,0x662D09A1U,0xC4324633U,\n\t\t0xE85A1F02U,0x09F0BE8CU,0x4A99A025U,0x1D6EFE10U,0x1AB93D1DU,0x0BA5A4DFU,0xA186F20FU,0x2868F169U,\n\t\t0xDCB7DA83U,0x573906FEU,0xA1E2CE9BU,0x4FCD7F52U,0x50115E01U,0xA70683FAU,0xA002B5C4U,0x0DE6D027U,\n\t\t0x9AF88C27U,0x773F8641U,0xC3604C06U,0x61A806B5U,0xF0177A28U,0xC0F586E0U,0x006058AAU,0x30DC7D62U,\n\t\t0x11E69ED7U,0x2338EA63U,0x53C2DD94U,0xC2C21634U,0xBBCBEE56U,0x90BCB6DEU,0xEBFC7DA1U,0xCE591D76U,\n\t\t0x6F05E409U,0x4B7C0188U,0x39720A3DU,0x7C927C24U,0x86E3725FU,0x724D9DB9U,0x1AC15BB4U,0xD39EB8FCU,\n\t\t0xED545578U,0x08FCA5B5U,0xD83D7CD3U,0x4DAD0FC4U,0x1E50EF5EU,0xB161E6F8U,0xA28514D9U,0x6C51133CU,\n\t\t0x6FD5C7E7U,0x56E14EC4U,0x362ABFCEU,0xDDC6C837U,0xD79A3234U,0x92638212U,0x670EFA8EU,0x406000E0U,\n\t},{\n\t\t0x3A39CE37U,0xD3FAF5CFU,0xABC27737U,0x5AC52D1BU,0x5CB0679EU,0x4FA33742U,0xD3822740U,0x99BC9BBEU,\n\t\t0xD5118E9DU,0xBF0F7315U,0xD62D1C7EU,0xC700C47BU,0xB78C1B6BU,0x21A19045U,0xB26EB1BEU,0x6A366EB4U,\n\t\t0x5748AB2FU,0xBC946E79U,0xC6A376D2U,0x6549C2C8U,0x530FF8EEU,0x468DDE7DU,0xD5730A1DU,0x4CD04DC6U,\n\t\t0x2939BBDBU,0xA9BA4650U,0xAC9526E8U,0xBE5EE304U,0xA1FAD5F0U,0x6A2D519AU,0x63EF8CE2U,0x9A86EE22U,\n\t\t0xC089C2B8U,0x43242EF6U,0xA51E03AAU,0x9CF2D0A4U,0x83C061BAU,0x9BE96A4DU,0x8FE51550U,0xBA645BD6U,\n\t\t0x2826A2F9U,0xA73A3AE1U,0x4BA99586U,0xEF5562E9U,0xC72FEFD3U,0xF752F7DAU,0x3F046F69U,0x77FA0A59U,\n\t\t0x80E4A915U,0x87B08601U,0x9B09E6ADU,0x3B3EE593U,0xE990FD5AU,0x9E34D797U,0x2CF0B7D9U,0x022B8B51U,\n\t\t0x96D5AC3AU,0x017DA67DU,0xD1CF3ED6U,0x7C7D2D28U,0x1F9F25CFU,0xADF2B89BU,0x5AD6B472U,0x5A88F54CU,\n\t\t0xE029AC71U,0xE019A5E6U,0x47B0ACFDU,0xED93FA9BU,0xE8D3C48DU,0x283B57CCU,0xF8D56629U,0x79132E28U,\n\t\t0x785F0191U,0xED756055U,0xF7960E44U,0xE3D35E8CU,0x15056DD4U,0x88F46DBAU,0x03A16125U,0x0564F0BDU,\n\t\t0xC3EB9E15U,0x3C9057A2U,0x97271AECU,0xA93A072AU,0x1B3F6D9BU,0x1E6321F5U,0xF59C66FBU,0x26DCF319U,\n\t\t0x7533D928U,0xB155FDF5U,0x03563482U,0x8ABA3CBBU,0x28517711U,0xC20AD9F8U,0xABCC5167U,0xCCAD925FU,\n\t\t0x4DE81751U,0x3830DC8EU,0x379D5862U,0x9320F991U,0xEA7A90C2U,0xFB3E7BCEU,0x5121CE64U,0x774FBE32U,\n\t\t0xA8B6E37EU,0xC3293D46U,0x48DE5369U,0x6413E680U,0xA2AE0810U,0xDD6DB224U,0x69852DFDU,0x09072166U,\n\t\t0xB39A460AU,0x6445C0DDU,0x586CDECFU,0x1C20C8AEU,0x5BBEF7DDU,0x1B588D40U,0xCCD2017FU,0x6BB4E3BBU,\n\t\t0xDDA26A7EU,0x3A59FF45U,0x3E350A44U,0xBCB4CDD5U,0x72EACEA8U,0xFA6484BBU,0x8D6612AEU,0xBF3C6F47U,\n\t\t0xD29BE463U,0x542F5D9EU,0xAEC2771BU,0xF64E6370U,0x740E0D8DU,0xE75B1357U,0xF8721671U,0xAF537D5DU,\n\t\t0x4040CB08U,0x4EB4E2CCU,0x34D2466AU,0x0115AF84U,0xE1B00428U,0x95983A1DU,0x06B89FB4U,0xCE6EA048U,\n\t\t0x6F3F3B82U,0x3520AB82U,0x011A1D4BU,0x277227F8U,0x611560B1U,0xE7933FDCU,0xBB3A792BU,0x344525BDU,\n\t\t0xA08839E1U,0x51CE794BU,0x2F32C9B7U,0xA01FBAC9U,0xE01CC87EU,0xBCC7D1F6U,0xCF0111C3U,0xA1E8AAC7U,\n\t\t0x1A908749U,0xD44FBD9AU,0xD0DADECBU,0xD50ADA38U,0x0339C32AU,0xC6913667U,0x8DF9317CU,0xE0B12B4FU,\n\t\t0xF79E59B7U,0x43F5BB3AU,0xF2D519FFU,0x27D9459CU,0xBF97222CU,0x15E6FC2AU,0x0F91FC71U,0x9B941525U,\n\t\t0xFAE59361U,0xCEB69CEBU,0xC2A86459U,0x12BAA8D1U,0xB6C1075EU,0xE3056A0CU,0x10D25065U,0xCB03A442U,\n\t\t0xE0EC6E0EU,0x1698DB3BU,0x4C98A0BEU,0x3278E964U,0x9F1F9532U,0xE0D392DFU,0xD3A0342BU,0x8971F21EU,\n\t\t0x1B0A7441U,0x4BA3348CU,0xC5BE7120U,0xC37632D8U,0xDF359F8DU,0x9B992F2EU,0xE60B6F47U,0x0FE3F11DU,\n\t\t0xE54CDA54U,0x1EDAD891U,0xCE6279CFU,0xCD3E7E6FU,0x1618B166U,0xFD2C1D05U,0x848FD2C5U,0xF6FB2299U,\n\t\t0xF523F357U,0xA6327623U,0x93A83531U,0x56CCCD02U,0xACF08162U,0x5A75EBB5U,0x6E163697U,0x88D273CCU,\n\t\t0xDE966292U,0x81B949D0U,0x4C50901BU,0x71C65614U,0xE6C6C7BDU,0x327A140AU,0x45E1D006U,0xC3F27B9AU,\n\t\t0xC9AA53FDU,0x62A80F00U,0xBB25BFE2U,0x35BDD2F6U,0x71126905U,0xB2040222U,0xB6CBCF7CU,0xCD769C2BU,\n\t\t0x53113EC0U,0x1640E3D3U,0x38ABBD60U,0x2547ADF0U,0xBA38209CU,0xF746CE76U,0x77AFA1C5U,0x20756060U,\n\t\t0x85CBFE4EU,0x8AE88DD8U,0x7AAAF9B0U,0x4CF9AA7EU,0x1948C25CU,0x02FB8A8CU,0x01C36AE4U,0xD6EBE1F9U,\n\t\t0x90D4F869U,0xA65CDEA0U,0x3F09252DU,0xC208E69FU,0xB74E6132U,0xCE77E25BU,0x578FDFE3U,0x3AC372E6U\n\t}\n};\n\n"
  },
  {
    "path": "REDALERT/BLOWFISH.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLOWFISH.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWFISH.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/14/96                                                     *\n *                                                                                             *\n *                  Last Update : April 14, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BLOWFISH_H\n#define BLOWFISH_H\n\n#include\t<limits.h>\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/*\n**\tThis engine will process data blocks by encryption and decryption.\n**\tThe \"Blowfish\" algorithm is in the public domain. It uses\n**\ta Feistal network (similar to IDEA). It has no known\n**\tweaknesses, but is still relatively new. Blowfish is particularly strong\n**\tagainst brute force attacks. It is also quite strong against linear and\n**\tdifferential cryptanalysis. Its weakness is that it takes a relatively\n**\tlong time to set up with a new key (1/100th of a second on a P6-200).\n**\tThe time to set up a key is equivalent to encrypting 4240 bytes.\n*/\nclass BlowfishEngine {\n\tpublic:\n\t\tBlowfishEngine(void) : IsKeyed(false) {}\n\t\t~BlowfishEngine(void);\n\n\t\tvoid Submit_Key(void const * key, int length);\n\n\t\tint Encrypt(void const * plaintext, int length, void * cyphertext);\n\t\tint Decrypt(void const * cyphertext, int length, void * plaintext);\n\n\t\t/*\n\t\t**\tThis is the maximum key length supported.\n\t\t*/\n\t\tenum {MAX_KEY_LENGTH=56};\n\n\tprivate:\n\t\tbool IsKeyed;\n\n\t\tvoid Sub_Key_Encrypt(unsigned long & left, unsigned long & right);\n\n\t\tvoid Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable);\n\t\tvoid Initialize_Tables(void);\n\n\t\tenum {\n\t\t\tROUNDS = 16,\t\t// Feistal round count (16 is standard).\n\t\t\tBYTES_PER_BLOCK=8\t// The number of bytes in each cypher block (don't change).\n\t\t};\n\n\t\t/*\n\t\t**\tInitialization data for sub keys. The initial values are constant and\n\t\t**\tfilled with a number generated from pi. Thus they are not random but\n\t\t**\tthey don't hold a weak pattern either.\n\t\t*/\n\t\tstatic unsigned long const P_Init[(int)ROUNDS+2];\n\t\tstatic unsigned long const S_Init[4][UCHAR_MAX+1];\n\n\t\t/*\n\t\t**\tPermutation tables for encryption and decryption.\n\t\t*/\n \t\tunsigned long P_Encrypt[(int)ROUNDS+2];\n \t\tunsigned long P_Decrypt[(int)ROUNDS+2];\n\n\t\t/*\n\t\t**\tS-Box tables (four).\n\t\t*/\n\t\tunsigned long bf_S[4][UCHAR_MAX+1];\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/BLOWPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLOWPIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWPIPE.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowPipe::Flush -- Flushes any pending data out the pipe.                                 *\n *   BlowPipe::Key -- Submit a key to the blowfish pipe handler.                               *\n *   BlowPipe::Put -- Submit a block of data for encrypt/decrypt.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"blowpipe.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * BlowPipe::Flush -- Flushes any pending data out the pipe.                                   *\n *                                                                                             *\n *    If there is any pending data in the holding buffer, then this routine will force it to   *\n *    be flushed out the end of the pipe.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the end final distant pipe       *\n *          segment in the chain.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowPipe::Flush(void)\n{\n\tint total = 0;\n\tif (Counter > 0 && BF != NULL) {\n\t\ttotal += Pipe::Put(Buffer, Counter);\n\t}\n\tCounter = 0;\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowPipe::Put -- Submit a block of data for encrypt/decrypt.                                *\n *                                                                                             *\n *    This will take the data block specified and process it before passing it on to the next  *\n *    link in the pipe chain. A key must be submitted before this routine will actually perform*\n *    any processing. Prior to key submission, the data is passed through unchanged.           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that contains the data to pass through.          *\n *                                                                                             *\n *          length   -- The length of the data in the buffer.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with then actual number of bytes output at the final distant end link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\t/*\n\t**\tIf there is no blowfish engine present, then merely pass the data through\n\t**\tunchanged in any way.\n\t*/\n\tif (BF == NULL) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is a partial block accumulated, then tag on the new data to\n\t**\tthis block and process it if the block is full. Proceed with the bulk\n\t**\tprocessing if there are any left over bytes from this step. This step\n\t**\tcan be skipped if there are no pending bytes in the buffer.\n\t*/\n\tif (Counter) {\n\t\tint sublen = ((int)sizeof(Buffer)-Counter < slen) ? (sizeof(Buffer)-Counter) : slen;\n\t\tmemmove(&Buffer[Counter], source, sublen);\n\t\tCounter += sublen;\n\t\tsource = ((char *)source) + sublen;\n\t\tslen -= sublen;\n\n\t\tif (Counter == sizeof(Buffer)) {\n\t\t\tif (Control == DECRYPT) {\n\t\t\t\tBF->Decrypt(Buffer, sizeof(Buffer), Buffer);\n\t\t\t} else {\n\t\t\t\tBF->Encrypt(Buffer, sizeof(Buffer), Buffer);\n\t\t\t}\n\t\t\ttotal += Pipe::Put(Buffer, sizeof(Buffer));\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tProcess the input data in blocks until there is not enough\n\t**\tsource data to fill a full block of data.\n\t*/\n\twhile (slen >= sizeof(Buffer)) {\n\t\tif (Control == DECRYPT) {\n\t\t\tBF->Decrypt(source, sizeof(Buffer), Buffer);\n\t\t} else {\n\t\t\tBF->Encrypt(source, sizeof(Buffer), Buffer);\n\t\t}\n\t\ttotal += Pipe::Put(Buffer, sizeof(Buffer));\n\t\tsource = ((char *)source) + sizeof(Buffer);\n\t\tslen -= sizeof(Buffer);\n\t}\n\n\t/*\n\t**\tIf there are any left over bytes, then they must be less than the size of\n\t**\tthe staging buffer. Store the bytes in the staging buffer for later\n\t**\tprocessing.\n\t*/\n\tif (slen > 0) {\n\t\tmemmove(Buffer, source, slen);\n\t\tCounter = slen;\n\t}\n\n\t/*\n\t**\tReturn with the total number of bytes flushed out to the final end of the\n\t**\tpipe chain.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowPipe::Key -- Submit a key to the blowfish pipe handler.                                 *\n *                                                                                             *\n *    This routine will take the key provided and use it to process the data that passes       *\n *    through this pipe. Prior to a key being submitted, the data passes through the pipe      *\n *    unchanged.                                                                               *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key data to use.                                           *\n *                                                                                             *\n *          length-- The length of the key. The key length must not be greater than 56 bytes.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowPipe::Key(void const * key, int length)\n{\n\t/*\n\t**\tCreate the blowfish engine if one isn't already present.\n\t*/\n\tif (BF == NULL) {\n\t\tBF = new BlowfishEngine;\n\t}\n\n\tassert(BF != NULL);\n\n\tif (BF != NULL) {\n\t\tBF->Submit_Key(key, length);\n\t}\n}\n\n\n\n"
  },
  {
    "path": "REDALERT/BLOWPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLOWPIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLOWPIPE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BLOWPIPE_H\n#define BLOWPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"blowfish.h\"\n\n/*\n**\tPerforms Blowfish encryption/decryption on the data stream that is piped\n**\tthrough this class.\n*/\nclass BlowPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tBlowPipe(CryptControl control) : BF(NULL), Counter(0), Control(control) {}\n\t\tvirtual ~BlowPipe(void) {delete BF;BF = NULL;}\n\t\tvirtual int Flush(void);\n\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Submit key for blowfish engine.\n\t\tvoid Key(void const * key, int length);\n\n\tprotected:\n\t\t/*\n\t\t**\tThe Blowfish engine used for encryption/decryption. If this pointer is\n\t\t**\tNULL, then this indicates that the blowfish engine is not active and no\n\t\t**\tkey has been submitted. All data would pass through this pipe unchanged\n\t\t**\tin that case.\n\t\t*/\n\t\tBlowfishEngine * BF;\n\n\tprivate:\n\t\tchar Buffer[8];\n\t\tint Counter;\n\t\tCryptControl Control;\n\n\t\tBlowPipe(BlowPipe & rvalue);\n\t\tBlowPipe & operator = (BlowPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/BLWSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLWSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BlowStraw::Get -- Fetch a block of data from the straw.                                   *\n *   BlowStraw::Key -- Submit a key to the Blowfish straw.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"blwstraw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * BlowStraw::Get -- Fetch a block of data from the straw.                                     *\n *                                                                                             *\n *    This routine will take a block of data from the straw and process it according to the    *\n *    encrypt/decrypt flag and the key supplied. Prior to a key be supplied, the data passes   *\n *    through this straw unchanged.                                                            *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data being requested.                *\n *                                                                                             *\n *          length   -- The length of the data being requested.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If the number      *\n *          returned is less than the number requested, then this indicates that the data      *\n *          source has been exhausted.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BlowStraw::Get(void * source, int slen)\n{\n\t/*\n\t**\tVerify the parameter for legality.\n\t*/\n\tif (source == NULL || slen <= 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf there is no blowfish engine present, then merely pass the data through\n\t**\tunchanged.\n\t*/\n\tif (BF == NULL) {\n\t\treturn(Straw::Get(source, slen));\n\t}\n\n\tint total = 0;\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tIf there are any left over bytes in the buffer, pass them\n\t\t**\tthrough first.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint sublen = (slen < Counter) ? slen : Counter;\n\t\t\tmemmove(source, &Buffer[sizeof(Buffer)-Counter], sublen);\n\t\t\tCounter -= sublen;\n\t\t\tsource = ((char *)source) + sublen;\n\t\t\tslen -= sublen;\n\t\t\ttotal += sublen;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\t/*\n\t\t**\tFetch and encrypt/decrypt the next block.\n\t\t*/\n\t\tint incount = Straw::Get(Buffer, sizeof(Buffer));\n\t\tif (incount == 0) break;\n\n\t\t/*\n\t\t**\tOnly full blocks are processed. Partial blocks are\n\t\t**\tmerely passed through unchanged.\n\t\t*/\n\t\tif (incount == sizeof(Buffer)) {\n\t\t\tif (Control == DECRYPT) {\n\t\t\t\tBF->Decrypt(Buffer, incount, Buffer);\n\t\t\t} else {\n\t\t\t\tBF->Encrypt(Buffer, incount, Buffer);\n\t\t\t}\n\t\t} else {\n\t\t\tmemmove(&Buffer[sizeof(Buffer)-incount], Buffer, incount);\n\t\t}\n\t\tCounter = incount;\n\t}\n\n\t/*\n\t**\tReturn with the total number of bytes placed into the buffer.\n\t*/\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * BlowStraw::Key -- Submit a key to the Blowfish straw.                                       *\n *                                                                                             *\n *    This will take the key specified and use it to process the data that flows through this  *\n *    straw segment. Prior to a key being submitted, the data will flow through unchanged.     *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to submit.                                             *\n *                                                                                             *\n *          length-- The length of the key. The length must not exceed 56 bytes.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BlowStraw::Key(void const * key, int length)\n{\n\t/*\n\t**\tCreate the blowfish engine if one isn't already present.\n\t*/\n\tif (BF == NULL) {\n\t\tBF = new BlowfishEngine;\n\t}\n\n\tassert(BF != NULL);\n\n\tif (BF != NULL) {\n\t\tBF->Submit_Key(key, length);\n\t}\n}\n"
  },
  {
    "path": "REDALERT/BLWSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BLWSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BLWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BLWSTRAW_H\n#define BLWSTRAW_H\n\n#include\t\"straw.h\"\n#include\t\"blowfish.h\"\n\n\n/*\n**\tPerforms Blowfish encryption/decryption to the data that is drawn through this straw. The\n**\tprocess is controlled by the key which must be submitted to the class before any data\n**\tmanipulation will occur. The Blowfish algorithm is symmetric, thus the same key is used\n**\tfor encryption as is for decryption.\n*/\nclass BlowStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tBlowStraw(CryptControl control) : BF(NULL), Counter(0), Control(control) {}\n\t\tvirtual ~BlowStraw(void) {delete BF;BF = NULL;}\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Submit key for blowfish engine.\n\t\tvoid Key(void const * key, int length);\n\n\tprotected:\n\t\t/*\n\t\t**\tThe Blowfish engine used for encryption/decryption. If this pointer is\n\t\t**\tNULL, then this indicates that the blowfish engine is not active and no\n\t\t**\tkey has been submitted. All data would pass through this straw unchanged\n\t\t**\tin that case.\n\t\t*/\n\t\tBlowfishEngine * BF;\n\n\tprivate:\n\t\tchar Buffer[8];\n\t\tint Counter;\n\t\tCryptControl Control;\n\n\t\tBlowStraw(BlowStraw & rvalue);\n\t\tBlowStraw & operator = (BlowStraw const & straw);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/BMP8.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#include \"bmp8.h\"\n\n//***********************************************************************************************\nBMP8::~BMP8()\n{\n\t// free resources\n\tif( hBitmap )\n\t\t::DeleteObject( hBitmap );\n\tif( hPal )\n\t\t::DeleteObject( hPal );\n}\n\n//***********************************************************************************************\nbool BMP8::Init( const char* szFile, HWND hWnd )\n{\n  int                  i;\n  char                 string[128];\n  DWORD                dwRead;\n  BITMAPFILEHEADER     bitmapHeader;\n  BITMAPINFOHEADER     bitmapInfoHeader;\n  LPLOGPALETTE         lpLogPalette;\n  char                *palData;\n  HGLOBAL              hmem2;\n  LPVOID               lpvBits;\n  PAINTSTRUCT          ps;\n  HDC                  hdc;\n  HPALETTE             select;\n  UINT                 realize;\n  RECT                 rect;\n\n\n\t//\tRemember window handle for use later.\n\tthis->hWnd = hWnd;\n\n\t//\tRetrieve a handle identifying the file. \n\tHANDLE hFile = ::CreateFile(\n\t\tszFile,\n\t\tGENERIC_READ,\n\t\tFILE_SHARE_READ,\n\t\t(LPSECURITY_ATTRIBUTES)NULL,\n\t\tOPEN_EXISTING,\n\t\tFILE_ATTRIBUTE_READONLY,\n\t\t(HANDLE)NULL );\n\n\tif(\t!hFile )\n\t\treturn false;\n\n\t// Retrieve the BITMAPFILEHEADER structure. \n\t::ReadFile( hFile, &bitmapHeader, sizeof(BITMAPFILEHEADER), &dwRead, (LPOVERLAPPED)NULL );\n\n\t// Retrieve the BITMAPFILEHEADER structure. \n\t::ReadFile( hFile, &bitmapInfoHeader, sizeof(BITMAPINFOHEADER), &dwRead, (LPOVERLAPPED)NULL );\n \n\t// Allocate memory for the BITMAPINFO structure. \n\tHGLOBAL infoHeaderMem = ::GlobalAlloc( GHND, sizeof(BITMAPINFOHEADER) + ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)) );\n \n\tLPBITMAPINFO lpHeaderMem = (LPBITMAPINFO)::GlobalLock( infoHeaderMem ); \n \n\t// Load BITMAPINFOHEADER into the BITMAPINFO structure. \n\tlpHeaderMem->bmiHeader.biSize          = bitmapInfoHeader.biSize; \n\tlpHeaderMem->bmiHeader.biWidth         = bitmapInfoHeader.biWidth; \n\tlpHeaderMem->bmiHeader.biHeight        = bitmapInfoHeader.biHeight; \n\tlpHeaderMem->bmiHeader.biPlanes        = bitmapInfoHeader.biPlanes; \n\tlpHeaderMem->bmiHeader.biBitCount      = bitmapInfoHeader.biBitCount; \n\tlpHeaderMem->bmiHeader.biCompression   = bitmapInfoHeader.biCompression; \n\tlpHeaderMem->bmiHeader.biSizeImage     = bitmapInfoHeader.biSizeImage; \n\tlpHeaderMem->bmiHeader.biXPelsPerMeter = bitmapInfoHeader.biXPelsPerMeter; \n\tlpHeaderMem->bmiHeader.biYPelsPerMeter = bitmapInfoHeader.biYPelsPerMeter; \n\tlpHeaderMem->bmiHeader.biClrUsed       = bitmapInfoHeader.biClrUsed; \n\tlpHeaderMem->bmiHeader.biClrImportant  = bitmapInfoHeader.biClrImportant; \n\n\t// Retrieve the color table. \n\t// 1 << bitmapInfoHeader.biBitCount == 2 ^ bitmapInfoHeader.biBitCount \n\t::ReadFile( hFile, lpHeaderMem->bmiColors, ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)),\n\t\t\t\t&dwRead, (LPOVERLAPPED)NULL );\n\n\n\tlpLogPalette = (LPLOGPALETTE)new char[ (sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*256) ];\n\tlpLogPalette->palVersion=0x300;\n\tlpLogPalette->palNumEntries=256;\n\n\tpalData = (char*)lpHeaderMem->bmiColors;\n\n\tfor( i = 0; i < 256; i++ )\n\t{\n\t\tlpLogPalette->palPalEntry[i].peRed = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peGreen = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peBlue = *palData++;\n\t\tlpLogPalette->palPalEntry[i].peFlags = *palData++;\n\t}\n\thPal = ::CreatePalette( lpLogPalette );\n\tdelete [] lpLogPalette;\n\n\t// Allocate memory for the required number of bytes. \n\thmem2 = ::GlobalAlloc( GHND, (bitmapHeader.bfSize - bitmapHeader.bfOffBits) );\n \n\tlpvBits = ::GlobalLock( hmem2 );\n \n\t// Retrieve the bitmap data. \n\t::ReadFile( hFile, lpvBits, (bitmapHeader.bfSize - bitmapHeader.bfOffBits), &dwRead, (LPOVERLAPPED)NULL );\n \n\t// Create a bitmap from the data stored in the .BMP file. \n\thdc = ::GetDC( hWnd );\n\tselect = ::SelectPalette( hdc, hPal, 0 );\n\tif( !select )\n\t\treturn false;\n\trealize = ::RealizePalette( hdc );\n\tif( realize == GDI_ERROR )\n\t\treturn false;\n\n\thBMP = ::CreateDIBitmap( hdc, &bitmapInfoHeader, CBM_INIT, lpvBits, lpHeaderMem, DIB_RGB_COLORS );\n\t::ReleaseDC( hWnd, hdc );\n\n\t// Unlock the global memory objects and close the .BMP file.  \n\t::GlobalUnlock( infoHeaderMem );\n\t::GlobalUnlock( hmem2 );\n\t::CloseHandle( hFile );\n \n\tif( !hBMP )\n\t\treturn false;\n \n\treturn true;\n}\n\n\nbit8 BMP8::drawBmp(void)\n{\n  // Paint the window (and draw the bitmap). \n \n  PAINTSTRUCT ps;\n  HDC         hdc;\n  char        string[128];\n\n  InvalidateRect(WindowHandle_,NULL,FALSE); // keep windows from screwing up the\n                                           //  redrawing (as much).\n  hdc=BeginPaint(WindowHandle_,&ps);\n\n  //Do palette stuff\n  HPALETTE select=SelectPalette(ps.hdc,PalHandle_,0);\n  if (select==NULL)\n  {\n    sprintf(string,\"Select Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n  UINT realize=RealizePalette(ps.hdc);\n  if (realize==GDI_ERROR)\n  {\n    sprintf(string,\"Realize Pal Fail: %d\",GetLastError());\n    MessageBox(NULL,string,\"OK\",MB_OK);\n  }\n\n  HDC hdcMem = CreateCompatibleDC(ps.hdc); \n  SelectObject(hdcMem, BitmapHandle_); \n  BITMAP bm;\n  GetObject(BitmapHandle_, sizeof(BITMAP), (LPSTR) &bm);\n  \n  /// for non-stretching version\n  ///////BitBlt(ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); \n\n  RECT clientRect;\n  GetClientRect(WindowHandle_,&clientRect);\n  SetStretchBltMode(ps.hdc,COLORONCOLOR);\n  StretchBlt(ps.hdc,0,0,clientRect.right,clientRect.bottom,hdcMem,0,0,bm.bmWidth,\n    bm.bmHeight,SRCCOPY);\n\n\n  DeleteDC(hdcMem); \n  EndPaint(WindowHandle_,&ps);\n  return(TRUE);\n}\n"
  },
  {
    "path": "REDALERT/BMP8.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef BMP8_H\n#define BMP8_H\n\n//#include<stdlib.h>\n//#include<stdio.h>\n//#include \"wstypes.h\"\n//#include \"winblows.h\"\n\nclass BMP8\n{\npublic:\n\tBMP8() : hBMP( NULL ), hPal( NULL ), hWnd( NULL )\t{}\n\t~BMP8();\n\n\tbool\tInit( const char* szFile, HWND hWnd );\n\tbool\tDraw(void);  // call this from your WM_PAINT message\n\nprivate:\n\tHBITMAP\t\thBMP;\n\tHPALETTE\thPal;\n\tHWND\t\thWnd;\n};\n\n\n#endif"
  },
  {
    "path": "REDALERT/BUFF.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BUFF.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFF.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/29/96                                                     *\n *                                                                                             *\n *                  Last Update : September 7, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Buffer::Buffer -- Constructor for buffer object.                                          *\n *   Buffer::Buffer -- Copy constructor for buffer object.                                     *\n *   Buffer::Buffer -- Self-allocating constructor for buffer object.                          *\n *   Buffer::Reset -- Clears the buffer object to null state.                                  *\n *   Buffer::operator = -- Assignment operator for the buffer object.                          *\n *   Buffer::~Buffer -- Destructor for buffer object.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"buff.h\"\n#include\t<stddef.h>\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Constructor for buffer object.                                            *\n *                                                                                             *\n *    This is the normal constructor for a buffer object. The buffer pointer and size are      *\n *    specified as parameters.                                                                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer.                                                 *\n *                                                                                             *\n *          size     -- The size of the buffer.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It is possible to construct a Buffer object that has a pointer but a size       *\n *             value of zero. The Buffer object can still be used for its pointer, but it      *\n *             any function that requires a size will fail.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(void * buffer, long size) :\n\tBufferPtr(buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n// Alternate constructor for char * pointer.\nBuffer::Buffer(char * buffer, long size) :\n\tBufferPtr(buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n// Alternate constructor for void const * pointer.\nBuffer::Buffer(void const * buffer, long size) :\n\tBufferPtr((void*)buffer),\n\tSize(size),\n\tIsAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Self-allocating constructor for buffer object.                            *\n *                                                                                             *\n *    This construtor for a buffer object will automatically allocate the bytes necessary      *\n *    to fulfill the size requested. This object is also responsible for deleting the buffer   *\n *    it allocated.                                                                            *\n *                                                                                             *\n * INPUT:   size  -- The size of the buffer to allocated.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   There is no way to tell if the allocation failed. To verify, call Get_Buffer    *\n *             and compare with NULL.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(long size) :\n\tBufferPtr(NULL),\n\tSize(size),\n\tIsAllocated(false)\n{\n\tif (size > 0) {\n\t\tBufferPtr = new char[size];\n\t\tIsAllocated = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * Buffer::Buffer -- Copy constructor for buffer object.                                       *\n *                                                                                             *\n *    This will make a duplicate of the specified buffer object. The ownership of the pointer  *\n *    remains with the original object. This prevents multiple deletion of the same pointer.   *\n *                                                                                             *\n * INPUT:   buffer   -- Reference to the buffer object to be dupilcated.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::Buffer(Buffer const & buffer) :\n\tIsAllocated(false)\n{\n\tBufferPtr = buffer.BufferPtr;\n\tSize = buffer.Size;\n}\n\n\n/***********************************************************************************************\n * Buffer::operator = -- Assignment operator for the buffer object.                            *\n *                                                                                             *\n *    This will make a duplicate of the buffer object specified. Any buffer pointed to by the  *\n *    left hand buffer will be lost (possibley freed as a result).                             *\n *                                                                                             *\n * INPUT:   buffer   -- Reference to the right hand buffer object.                             *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the copied buffer object.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer & Buffer::operator = (Buffer const & buffer)\n{\n\tif (buffer != this) {\n\t\tif (IsAllocated) {\n\t\t\tdelete [] BufferPtr;\n\t\t}\n\t\tIsAllocated = false;\n\t\tBufferPtr = buffer.BufferPtr;\n\t\tSize = buffer.Size;\n\t}\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * Buffer::~Buffer -- Destructor for buffer object.                                            *\n *                                                                                             *\n *    This destructor will free any buffer it is responsible for.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuffer::~Buffer(void)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * Buffer::Reset -- Clears the buffer object to null state.                                    *\n *                                                                                             *\n *    This routine will bring the buffer object into a null (newly constructed) state. If      *\n *    there was any buffer allocated or referred to by this object, it will be freed or        *\n *    dereferenced as necessary.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will free the buffer if it is responsible for doing so when        *\n *             it is no longer referenced.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Buffer::Reset(void)\n{\n\tif (IsAllocated) {\n\t\tdelete [] BufferPtr;\n\t}\n\tBufferPtr = NULL;\n\tSize = 0;\n\tIsAllocated = false;\n}\n"
  },
  {
    "path": "REDALERT/BUFF.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BUFF.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFF.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CCBUFF_H\n#define CCBUFF_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tA general purpose buffer pointer handler object. It holds not only the pointer to the\n**\tbuffer, but its size as well. By using this class instead of separate pointer and size\n**\tvalues, function interfaces and algorithms become simpler to manage and understand.\n*/\nclass Buffer {\n\tpublic:\n\t\tBuffer(char * ptr, long size=0);\n\t\tBuffer(void * ptr=0, long size=0);\n\t\tBuffer(void const * ptr, long size=0);\n\t\tBuffer(long size);\n\t\tBuffer(Buffer const & buffer);\n\t\t~Buffer(void);\n\n\t\tBuffer & operator = (Buffer const & buffer);\n\t\toperator void * (void) const {return(BufferPtr);}\n\t\toperator char * (void) const {return((char *)BufferPtr);}\n\n\t\tvoid Reset(void);\n\t\tvoid * Get_Buffer(void) const {return(BufferPtr);}\n\t\tlong Get_Size(void) const {return(Size);}\n\t\tbool Is_Valid(void) const {return(BufferPtr != 0);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tPointer to the buffer memory.\n\t\t*/\n\t\tvoid * BufferPtr;\n\n\t\t/*\n\t\t**\tThe size of the buffer memory.\n\t\t*/\n\t\tlong Size;\n\n\t\t/*\n\t\t**\tWas the buffer allocated by this class? If so, then this class\n\t\t**\twill be responsible for freeing the buffer.\n\t\t*/\n\t\tbool IsAllocated;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/BUFFERX.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BUFFERX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUFFER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/04/96                                                     *\n *                                                                                             *\n *                  Last Update : May 4, 1996 [JLB]                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef BUFFERx_H\n#define BUFFERx_H\n\n#include\t\"wwfile.h\"\n\n/*\n**\tThis is a transmuter interface designed to aid implementation of compression, encryption, or\n**\tdata analysis classes. The Transmuter should be derived into a class that performs the necessary\n**\tprocessing.\n*/\nclass Transmuter {\n\tpublic:\n\t\tTransmuter(void) : Output(0) {}\n\t\tvirtual ~Transmuter(void) {}\n\n\t\t/*\n\t\t**\tThese are the interface function that are used to pass data to the transmuter. The\n\t\t**\tdefault implementation of these functions do nothing other than pass the data onto\n\t\t**\tthe subsequent transmuter. For practical use, these functions should be overloaded to\n\t\t**\tdo something more useful.\n\t\t*/\n\t\tvirtual void Attach(Transmuter * transmuter) {Output = transmuter;}\n\t\tvirtual void Flush(void) {if (Output) Output->Flush();}\n\t\tvirtual void Put(const void * input, unsigned length) {if (Output) Output->Put(input, length);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tPointer to the output transmuter.\n\t\t*/\n\t\tTransmuter * Output;\n};\n\n\nclass FileTransmuter {\n\tpublic:\n\t\tFileTransmuter(FileClass * file = NULL) : OutputFile(file) {}\n\n\t\tvirtual void Attach(FileClass * file) {OutputFile = file;}\n\t\tvirtual void Flush(void) {}\n\t\tvirtual void Put(const void * input, unsigned length) {if (OutputFile) OutputFile->Write(input, length);}\n\n\tprotected:\n\t\tFileClass * OutputFile;\n};\n\n\nclass BufferTransmuter {\n\tpublic:\n\t\tBufferTransmuter(void * buffer = NULL) : BufferPtr(buffer) {}\n\n\t\tvirtual void Attach(void * buffer) {BufferPtr = buffer;}\n\t\tvirtual void Flush(void) {}\n\t\tvirtual void Put(const void * input, unsigned length) {if (BufferPtr) {memcpy(BufferPtr, input, length);((char *&)BufferPtr) += length;}}\n\n\tprotected:\n\t\tvoid * BufferPtr;\n};\n\n\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/BUILDING.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BUILDING.CPP 5     3/13/97 5:18p Joe_b $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUILDING.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 27, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BuildingClass::AI -- Handles non-graphic AI processing for buildings.                     *\n *   BuildingClass::Active_Click_With -- Handles cell selection for buildings.                 *\n *   BuildingClass::Animation_AI -- Handles normal building animation processing.              *\n *   BuildingClass::Assign_Target -- Assigns a target to the building.                         *\n *   BuildingClass::Begin_Mode -- Begins an animation mode for the building.                   *\n *   BuildingClass::BuildingClass -- Constructor for buildings.                                *\n *   BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?          *\n *   BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.               *\n *   BuildingClass::Can_Fire -- Determines if this building can fire.                          *\n *   BuildingClass::Can_Player_Move -- Can this building be moved?                             *\n *   BuildingClass::Captured -- Captures the building.                                         *\n *   BuildingClass::Center_Coord -- Fetches the center coordinate for the building.            *\n *   BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.         *\n *   BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.*\n *   BuildingClass::Click_With -- Handles clicking on the map while the building is selected.  *\n *   BuildingClass::Crew_Type -- This determines the crew that this object generates.          *\n *   BuildingClass::Death_Announcement -- Announce the death of this building.                 *\n *   BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.           *\n *   BuildingClass::Detach -- Handles target removal from the game system.                     *\n *   BuildingClass::Detach_All -- Possibly abandons production according to factory type.      *\n *   BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                *\n *   BuildingClass::Draw_It -- Displays the building at the location specified.                *\n *   BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                    *\n *   BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                  *\n *   BuildingClass::Exit_Coord -- Determines location where object will leave it.              *\n *   BuildingClass::Exit_Object -- Initiates an object to leave the building.                  *\n *   BuildingClass::Factory_AI -- Handle factory production and initiation.                    *\n *   BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this buildin*\n *   BuildingClass::Fire_Direction -- Fetches the direction of firing.                         *\n *   BuildingClass::Fire_Out -- Handles when attached animation expires.                       *\n *   BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.       *\n *   BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                *\n *   BuildingClass::Grand_Opening -- Handles construction completed special operations.        *\n *   BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.        *\n *   BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.      *\n *   BuildingClass::Init -- Initialize the building system to an empty null state.             *\n *   BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.             *\n *   BuildingClass::Mark -- Building interface to map rendering system.                        *\n *   BuildingClass::Mission_Attack -- Handles attack mission for building.                     *\n *   BuildingClass::Mission_Construction -- Handles mission construction.                      *\n *   BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                 *\n *   BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.               *\n *   BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                  *\n *   BuildingClass::Mission_Missile -- State machine for nuclear missile launch.               *\n *   BuildingClass::Mission_Repair -- Handles the repair (active) state for building.          *\n *   BuildingClass::Mission_Unload -- Handles the unload mission for a building.               *\n *   BuildingClass::Pip_Count -- Determines \"full\" pips to display for building.               *\n *   BuildingClass::Power_Output -- Fetches the current power output from this building.       *\n *   BuildingClass::Read_INI -- Reads buildings from INI file.                                 *\n *   BuildingClass::Receive_Message -- Handle an incoming message to the building.             *\n *   BuildingClass::Remap_Table -- Fetches the remap table to use for this building.           *\n *   BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells               *\n *   BuildingClass::Repair -- Initiates or terminates the repair process.                      *\n *   BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.          *\n *   BuildingClass::Revealed -- Reveals the building to the specified house.                   *\n *   BuildingClass::Rotation_AI -- Process any turret rotation required of this building.      *\n *   BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                  *\n *   BuildingClass::Shape_Number -- Fetch the shape number for this building.                  *\n *   BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                *\n *   BuildingClass::Take_Damage -- Inflicts damage points upon a building.                     *\n *   BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building. *\n *   BuildingClass::Toggle_Primary -- Toggles the primary factory state.                       *\n *   BuildingClass::Turret_Facing -- Fetches the turret facing for this building.              *\n *   BuildingClass::Unlimbo -- Removes a building from limbo state.                            *\n *   BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.   *\n *   BuildingClass::Value -- Determine the value of this building.                             *\n *   BuildingClass::What_Action -- Determines action to perform if click on specified object.  *\n *   BuildingClass::What_Action -- Determines what action will occur.                          *\n *   BuildingClass::Write_INI -- Write out the building data to the INI file specified.        *\n *   BuildingClass::delete -- Deallocates building object.                                     *\n *   BuildingClass::new -- Allocates a building object from building pool.                     *\n *   BuildingClass::~BuildingClass -- Destructor for building type objects.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n** New sidebar for GlyphX multiplayer. ST - 8/2/2019 2:35PM\n*/\n#include \"SidebarGlyphx.h\"\n\nenum SAMState {\n\tSAM_READY,\t\t\t\t\t// Launcher can be facing any direction tracking targets.\n\tSAM_FIRING\t\t\t\t\t// Stationary while missile is being fired.\n};\n\n\n/***************************************************************************\n**\tCenter of building offset table.\n*/\nCOORDINATE const BuildingClass::CenterOffset[BSIZE_COUNT] = {\n\t0x00800080L,\n\t0x008000FFL,\n\t0x00FF0080L,\n\t0x00FF00FFL,\n\t0x018000FFL,\n\t0x00FF0180L,\n\t0x01800180L,\n\n\t0x00FF0200L,\n\n\t0x02800280L,\n};\n\n\n/***********************************************************************************************\n * BuildingClass::Receive_Message -- Handle an incoming message to the building.               *\n *                                                                                             *\n *    This routine handles an incoming message to the building. Messages regulate the          *\n *    various cooperative ventures between buildings and units. This might include such        *\n *    actions as coordinating the construction yard animation with the actual building's       *\n *    construction animation.                                                                  *\n *                                                                                             *\n * INPUT:   from     -- The originator of the message received.                                *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to an optional parameter that might be used to return        *\n *                      extra information to the message originator.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the response to the message (typically, this is just RADIO_OK).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1994 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Forces refinery load anim to start immediately.                          *\n *   08/13/1995 JLB : Uses ScenarioInit for special loose \"CAN_LOAD\" check.                    *\n *=============================================================================================*/\nRadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tThis message is received as a request to attach/load/dock with this building.\n\t\t**\tVerify that this is allowed and return the appropriate response.\n\t\t*/\n\t\tcase RADIO_CAN_LOAD:\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\tif (!House->Is_Ally(from)) return(RADIO_STATIC);\n\t\t\tif (Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION || BState == BSTATE_CONSTRUCTION || (!ScenarioInit && Class->Type != STRUCT_REFINERY && In_Radio_Contact())) return(RADIO_NEGATIVE);\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass const *)from)->Class->IsFixedWing) {\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass const *)from)->Class->IsFixedWing) {\n\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_UNIT || (from->What_Am_I() == RTTI_AIRCRAFT)) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_ON_DEPOT, from) != RADIO_ROGER) {\n\t\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tif (from->What_Am_I() == RTTI_UNIT &&\n\t\t\t\t\t\t*((UnitClass *)from) == UNIT_HARVESTER &&\n\t\t\t\t\t\t(ScenarioInit || !Is_Something_Attached())) {\n\n\t\t\t\t\t\treturn((Contact_With_Whom() != from) ? RADIO_ROGER : RADIO_NEGATIVE);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn(RADIO_STATIC);\n\n\t\t/*\n\t\t**\tThis message is received when the object has attached itself to this\n\t\t**\tbuilding.\n\t\t*/\n\t\tcase RADIO_IM_IN:\n\t\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\tIsReadyToCommence = true;\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\tfrom->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\treturn(RADIO_ROGER);\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDocking maneuver maintenance message. See if new order should be given to the\n\t\t**\tunit trying to dock.\n\t\t*/\n\t\tcase RADIO_DOCKING:\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\n\t\t\t/*\n\t\t\t**\tWhen in radio contact for loading, the refinery starts\n\t\t\t**\tflashing the lights.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_REFINERY && BState != BSTATE_FULL) {\n\t\t\t\tBegin_Mode(BSTATE_FULL);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this building is already in radio contact, then it might\n\t\t\t**\tbe able to satisfy the request to load by bumping off any\n\t\t\t**\tpreoccupying task.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_REPAIR) {\n\t\t\t\tif (Contact_With_Whom() != from) {\n\t\t\t\t\tif (Transmit_Message(RADIO_ON_DEPOT) == RADIO_ROGER) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_NEED_REPAIR) == RADIO_NEGATIVE) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tEstablish contact with the object if this building isn't already in contact\n\t\t\t**\twith another.\n\t\t\t*/\n\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\tTransmit_Message(RADIO_HELLO, from);\n\t\t\t}\n\n\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\tswitch (Class->Type) {\n\t\t\t\t\tcase STRUCT_AIRSTRIP:\n\t\t\t\t\t\tparam = As_Target();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_HELIPAD:\n\t\t\t\t\t\tparam = As_Target();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_REPAIR:\n\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\tparam = ::As_Target(Coord_Cell(Center_Coord()));\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\t\tparam = ::As_Target(Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S)));\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the harvester to move to the docking pad of the building.\n\t\t\t\t*/\n\t\t\t\tif (Transmit_Message(RADIO_MOVE_HERE, param) == RADIO_YEA_NOW_WHAT) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSince the harvester is already there, tell it to begin the backup\n\t\t\t\t\t**\tprocedure now. If it can't, then tell it to get outta here.\n\t\t\t\t\t*/\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tif (*this == STRUCT_REFINERY && Transmit_Message(RADIO_BACKUP_NOW, from) != RADIO_ROGER) {\n\t\t\t\t\t\tfrom->Scatter(NULL, true, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tIf a transport or harvester is requesting permission to head toward, dock\n\t\t**\tand load/unload, check to make sure that this is allowed given the current\n\t\t**\tstate of the building.\n\t\t*/\n\t\tcase RADIO_ARE_REFINERY:\n\t\t\tif (Is_Something_Attached() || In_Radio_Contact() || IsInLimbo || House->Class->House != from->Owner() || (*this != STRUCT_REFINERY/* && *this != STRUCT_REPAIR*/)) {\n\t\t\t\treturn(RADIO_NEGATIVE);\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tSomeone is telling us that it is starting construction. This should only\n\t\t**\toccur if this is a construction yard and a building was just placed on\n\t\t**\tthe map.\n\t\t*/\n\t\tcase RADIO_BUILDING:\n\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tSomeone is telling us that they have finished construction. This should\n\t\t**\tonly occur if this is a construction yard and the building that was being\n\t\t**\tconstructed has finished. In this case, stop the construction yard\n\t\t**\tanimation.\n\t\t*/\n\t\tcase RADIO_COMPLETE:\n\t\t\tif (Mission != MISSION_DECONSTRUCTION) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tThis message may occur unexpectedly if the unit in contact with this\n\t\t**\tbuilding is suddenly destroyed. Handle any cleanup necessary. For example,\n\t\t**\ta construction yard should stop its construction animation in this case.\n\t\t*/\n\t\tcase RADIO_OVER_OUT:\n\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\tif (*this == STRUCT_REPAIR) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t**\tThis message is received when an object has completely left\n\t\t** building. Sometimes special cleanup action is required when\n\t\t**\tthis event occurs.\n\t\t*/\n\t\tcase RADIO_UNLOADED:\n\t\t\tif (*this == STRUCT_REPAIR) {\n\t\t\t\tif (Distance(from) < 0x0180) {\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\tif (*this == STRUCT_WEAP || *this == STRUCT_AIRSTRIP || *this == STRUCT_REPAIR) return(RADIO_RUN_AWAY);\n\t\t\treturn(RADIO_ROGER);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tPass along the message to the default message handler in the radio itself.\n\t*/\n\treturn(TechnoClass::Receive_Message(from, message, param));\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.             *\n *                                                                                             *\n *    This utility function will output the current status of the building class to the        *\n *    monochrome screen. It is through this data that bugs may be fixed or detected.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_BUILDING));\n\tmono->Fill_Attrib(66, 13, 12, 1, IsRepairing ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 14, 12, 1, IsToRebuild ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 15, 12, 1, IsAllowedToSell ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 16, 12, 1, IsCharging ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 17, 12, 1, IsCharged ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 18, 12, 1, IsJamming ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 19, 12, 1, IsJammed ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Set_Cursor(1, 11);\n\tif (Factory) {\n\t\tmono->Printf(\"%s %d%%\", Factory->Get_Object()->Class_Of().IniName, (100*Factory->Completion())/FactoryClass::STEP_COUNT);\n\t}\n\n\tTechnoClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * BuildingClass::Draw_It -- Displays the building at the location specified.                  *\n *                                                                                             *\n *    This is the low level graphic routine that displays the building at the location         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to draw the building at.                                   *\n *                                                                                             *\n *          window   -- The clipping window to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a clipping window parameter.                                       *\n *   07/06/1995 JLB : Handles damaged silos correctly.                                         *\n *=============================================================================================*/\nvoid BuildingClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tThe shape file to use for rendering depends on whether the building\n\t**\tis undergoing construction or not.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\tif (shapefile == NULL) return;\n\n\t/*\n\t**\tActually draw the building shape.\n\t*/\n\tIsTheaterShape = Class->IsTheater;\t//Let Build_Frame know if this is a theater specific shape\n\tTechno_Draw_Object(shapefile, Shape_Number(), x, y, window);\n\tIsTheaterShape = false;\n\n\t/*\n\t** Patch for adding overlay onto weapon factory.  Only add the overlay if\n\t** the building has more than 1 hp.  Also, if the building's in radio\n\t** contact, he must be unloading a constructed vehicle, so draw that\n\t** vehicle before drawing the overlay.\n\t*/\n\tif (BState != BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tA Tethered object is always rendered AFTER the building.\n\t\t*/\n\t\tif (*this == STRUCT_WEAP && IsTethered && In_Radio_Contact() && !Contact_With_Whom()->IsInLimbo && Contact_With_Whom()->What_Am_I() != RTTI_BUILDING) {\n\t\t\tTechnoClass * contact = Contact_With_Whom();\n\n\t\t\tassert(contact->IsActive);\n\t\t\tint xxx = x + ((int)Lepton_To_Pixel((int)Coord_X(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_X(Render_Coord())));\n\t\t\tint yyy = y + ((int)Lepton_To_Pixel((int)Coord_Y(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_Y(Render_Coord())));\n\t\t\tcontact->Draw_It(xxx, yyy, window);\n\t\t\tcontact->IsToDisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the weapon factory custom overlay graphic.\n\t\t*/\n\t\tif ( (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP)) {\n\t\t\tint shapenum = Door_Stage();\n\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) shapenum += 4;\n\t\t\t// Added override shape file name. ST - 8/1/2019 5:24PM\n\t\t\t//Techno_Draw_Object(Class->WarFactoryOverlay, shapenum, x, y, window);\n\t\t\tTechno_Draw_Object_Virtual(Class->WarFactoryOverlay, shapenum, x, y, window, DIR_N, 0x0100, \"WEAP2\");\n\t\t}\n\n\t\t/*\n\t\t**\tDraw any repair feedback graphic required.\n\t\t*/\n\t\tif (IsRepairing && IsWrenchVisible) {\n\t\t\tCC_Draw_Shape(ObjectTypeClass::SelectShapes, SELECT_WRENCH, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t}\n\t}\n\n\tTechnoClass::Draw_It(x, y, window);\n\n\t/*\n\t** If this is a factory that we're spying on, show what it's producing\n\t*/\n\tif ((Spied_By() & (1<<(PlayerPtr->Class->House)) && Is_Selected_By_Player()) || ((window == WINDOW_VIRTUAL) && (Session.Type != GAME_NORMAL))) {\n\n\t\t/*\n\t\t**\tFetch the factory that is associate with this building. For computer controlled buildings, the\n\t\t**\tfactory pointer is integral to the building itself. For human controlled buildings, the factory\n\t\t**\tpointer is part of the house structure and must be retrieved from there.\n\t\t*/\n\t\tFactoryClass * factory = NULL;\n\t\tif (House->IsHuman) {\n\t\t\tfactory = House->Fetch_Factory(Class->ToBuild);\n\t\t} else {\n\t\t\tfactory = Factory;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a factory associated with this building, then fetch any attached\n\t\t**\tobject under production and display its cameo image over the top of this building.\n\t\t*/\n\t\tif (factory != NULL) {\n\t\t\tTechnoClass * obj = factory->Get_Object();\n\t\t\tif (obj != NULL) {\n#ifdef FIXIT_CSII\n\t\t\t\tCC_Draw_Shape(obj, obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_NORMAL, NULL);\n#else\n\t\t\t\tvoid const * remapper = obj->House->Remap_Table(false, obj->Techno_Type_Class()->Remap);\n\t\t\t\tCC_Draw_Shape(obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL | ((remapper != NULL) ? SHAPE_FADING : SHAPE_NORMAL), remapper);\n#endif\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Shape_Number -- Fetch the shape number for this building.                    *\n *                                                                                             *\n *    This routine will examine the current state of the building and return with the shape    *\n *    number to use. The shape number is subordinate to the building graphic image data.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use when rendering this building.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Shape_Number(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tint shapenum = Fetch_Stage();\n\n\t/*\n\t**\tThe shape file to use for rendering depends on whether the building\n\t**\tis undergoing construction or not.\n\t*/\n\tif (BState == BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tIf the building is deconstructing, then the display frame progresses\n\t\t**\tfrom the end to the beginning. Reverse the shape number accordingly.\n\t\t*/\n\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\tshapenum = (Class->Anims[BState].Start+Class->Anims[BState].Count-1)-shapenum;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf this is a camouflaged pill box and it is not owned by the player, then\n\t\t**\tit is displayed with the MEGA-camouflaged imagery.\n\t\t*/\n\t\tif ((!IsOwnedByPlayer) && (*this == STRUCT_CAMOPILLBOX)) {\n\t\t\tshapenum += 1;\n\t\t}\n\n\t\t/*\n\t\t**\tThe Tesla Coil has a stage value that can be overridden by\n\t\t**\tits current state.\n\t\t*/\n\t\tif (*this == STRUCT_TESLA) {\n\t\t\tif (IsCharged) {\n\t\t\t\tshapenum = 3;\n\t\t\t} else {\n\t\t\t\tif (IsCharging) {\n\t\t\t\t\tshapenum = Fetch_Stage();\n\t\t\t\t} else {\n\t\t\t\t\tshapenum = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuildings that contain a turret handle their shape determination\n\t\t**\tdifferently than normal buildings. They need to take into consideration\n\t\t**\tthe direction the turret is facing.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tshapenum = UnitClass::BodyShape[Dir_To_32(PrimaryFacing.Current())];\n\n\t\t\tif (*this == STRUCT_SAM) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSAM sites that are free to rotate fetch their animation frame\n\t\t\t\t**\tfrom the building's turret facing. All other animation stages\n\t\t\t\t**\tfetch their frame from the embedded animation sequencer.\n\t\t\t\t*/\n//\t\t\t\tif (Status == SAM_READY || Status == SAM_FIRING || Status == SAM_LOCKING) {\n//\t\t\t\t\tshapenum = Fetch_Stage();\n//\t\t\t\t}\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum += 35;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsInRecoilState) {\n\t\t\t\t\tshapenum += 32;\n\t\t\t\t}\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum += 64;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf it is a significantly damaged weapons factory, it is shown in\n\t\t\t**\tthe worst state possible.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP) {\n\t\t\t\tshapenum = 0;\n\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\tshapenum = 1;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial render stage for silos. The stage is dependent on the current\n\t\t\t\t**\tTiberium collected as it relates to Tiberium capacity.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_STORAGE) {\n\n\t\t\t\t\tint level = 0;\n\t\t\t\t\tif (House->Capacity) {\n\t\t\t\t\t\tlevel = (House->Tiberium * 5) / House->Capacity;\n\t\t\t\t\t}\n\n\t\t\t\t\tshapenum += Bound(level, 0, 4);\n\t\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\t\tshapenum += 5;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf below half strenth, then show the damage frames of the\n\t\t\t\t\t**\tbuilding.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Health_Ratio() <= Rule.ConditionYellow) {\n\t\t\t\t\t\tif (*this == STRUCT_CHRONOSPHERE) {\n\t\t\t\t\t\t\tshapenum += 29;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tint last1 = Class->Anims[BSTATE_IDLE].Start + Class->Anims[BSTATE_IDLE].Count;\n\t\t\t\t\t\t\tint last2 = Class->Anims[BSTATE_ACTIVE].Start + Class->Anims[BSTATE_ACTIVE].Count;\n\t\t\t\t\t\t\tint largest = max(last1, last2);\n\t\t\t\t\t\t\tlast2 = Class->Anims[BSTATE_AUX1].Start + Class->Anims[BSTATE_AUX1].Count;\n\t\t\t\t\t\t\tlargest = max(largest, last2);\n\t\t\t\t\t\t\tlast2 = Class->Anims[BSTATE_AUX2].Start + Class->Anims[BSTATE_AUX2].Count;\n\t\t\t\t\t\t\tlargest = max(largest, last2);\n\t\t\t\t\t\t\tshapenum += largest;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mark -- Building interface to map rendering system.                          *\n *                                                                                             *\n *    This routine is used to mark the map cells so that when it renders                       *\n *    the underlying icons will also be updated as necessary.                                  *\n *                                                                                             *\n * INPUT:   mark  -- Type of image change (MARK_UP, _DOWN, _CHANGE)                            *\n *             MARK_UP  -- Building is removed.                                                *\n *             MARK_CHANGE -- Building changes shape.                                          *\n *             MARK_DOWN -- Building is added.                                                 *\n *                                                                                             *\n * OUTPUT:  bool; Did the mark operation succeed? Failure could be the result of marking down  *\n *                when the building is already marked down, or visa versa.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/31/1994 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   04/16/1994 JLB : Added health bar tracking.                                               *\n *   12/23/1994 JLB : Calls low level check before proceeding.                                 *\n *   01/27/1995 JLB : Special road spacer template added.                                      *\n *=============================================================================================*/\nbool BuildingClass::Mark(MarkType mark)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TechnoClass::Mark(mark)) {\n\t\tshort const * offset = Overlap_List();\n\t\tshort const * occupy = Occupy_List();\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tSmudgeType bib;\n\n\t\tswitch (mark) {\n\t\t\tcase MARK_UP:\n\t\t\t\tMap.Pick_Up(cell, this);\n\t\t\t\tif (Class->Bib_And_Offset(bib, cell)) {\n\t\t\t\t\tSmudgeClass * smudge = new SmudgeClass(bib);\n\t\t\t\t\tif (smudge != NULL) {\n\t\t\t\t\t\tsmudge->Disown(cell);\n\t\t\t\t\t\tdelete smudge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_DOWN:\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial wall logic is handled here. A building that is really a wall\n\t\t\t\t**\tgets converted into an overlay wall type when it is placed down. The\n\t\t\t\t**\tactual building object itself is destroyed.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsWall) {\n\t\t\t\t\tswitch (Class->Type) {\n\t\t\t\t\t\tcase STRUCT_BRICK_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_BRICK_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_BARBWIRE_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_BARBWIRE_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_SANDBAG_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_SANDBAG_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_WOOD_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_WOOD_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_CYCLONE_WALL:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_CYCLONE_WALL, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase STRUCT_FENCE:\n\t\t\t\t\t\t\tnew OverlayClass(OVERLAY_FENCE, cell, House->Class->House);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\tdelete this;\n\n\t\t\t\t} else {\n\t\t\t\t\tif (Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetermine if a bib is required for this building. If one is, then\n\t\t\t\t\t\t**\tcreate and place it.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL newcell = cell;\n\t\t\t\t\t\tif (Class->Bib_And_Offset(bib, newcell)) {\n\t\t\t\t\t\t\tnew SmudgeClass(bib, Cell_Coord(newcell), Class->IsBase ? House->Class->House : HOUSE_NONE);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tMap.Place_Down(cell, this);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_CHANGE_REDRAW:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(true));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(false));\n\t\t\t\tMap.Refresh_Cells(cell, occupy);\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::AI -- Handles non-graphic AI processing for buildings.                       *\n *                                                                                             *\n *    This function is to handle the AI logic for the building. The graphic logic (facing,     *\n *    firing, and animation) is handled elsewhere.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/26/1994 JLB : Handles production.                                                      *\n *   06/11/1995 JLB : Revamped.                                                                *\n *=============================================================================================*/\nvoid BuildingClass::AI(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tProcess building animation state changes. Transition to a following state\n\t**\tif there is one specified and the current animation sequence has expired.\n\t**\tThis process must occur before mission AI since the mission AI relies on\n\t**\tthe bstate change to occur immediately before the MissionClass::AI.\n\t*/\n\tAnimation_AI();\n\n\t/*\n\t**\tIf now is a good time to act on a new mission, then do so. This process occurs\n\t**\there because some outside event may have requested a mission change for the building.\n\t**\tSuch outside requests (player input) must be initiated BEFORE the normal AI process.\n\t*/\n\tif (IsReadyToCommence && BState != BSTATE_CONSTRUCTION) {\n\n\t\t/*\n\t\t**\tClear the commencement flag ONLY if something actually occurred. By acting\n\t\t**\tthis way, a building can set the IsReadyToCommence flag before it goes\n\t\t**\tto \"sleep\" knowing that it will wake up as soon as a new mission comes\n\t\t**\talong.\n\t\t*/\n\t\tif (Commence()) {\n\t\t\tIsReadyToCommence = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tProceed with normal logic processing. This is where the mission processing\n\t**\toccurs. This call must be located after the animation sequence makes the\n\t**\ttransition to the next frame (see above) in order for the mission logic to\n\t**\tact at the exact moment of graphic transition BEFORE it has a chance to\n\t**\tbe displayed.\n\t*/\n\tTechnoClass::AI();\n\n\t/*\n\t**\tBail if the object died in the AI routine.\n\t*/\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tBuilding ammo is instantly reloaded.\n\t*/\n\tif (!Ammo) {\n\t\tAmmo = Class->MaxAmmo;\n\t}\n\n\t/*\n\t**\tIf now is a good time to act on a new mission, then do so. This occurs here because\n\t**\tsome AI event may have requested a mission change (usually from another mission\n\t**\tstate machine). This must occur here before it has a chance to render.\n\t*/\n\tif (IsReadyToCommence) {\n\n\t\t/*\n\t\t**\tClear the commencement flag ONLY if something actually occurred. By acting\n\t\t**\tthis way, a building can set the IsReadyToCommence flag before it goes\n\t\t**\tto \"sleep\" knowing that it will wake up as soon as a new mission comes\n\t\t**\talong.\n\t\t*/\n\t\tif (Commence()) {\n\t\t\tIsReadyToCommence = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a change of animation was requested, then make the change\n\t**\tnow. The building animation system acts independently but subordinate\n\t**\tto the mission state machine system. By performing the animation change-up\n\t**\there, the mission AI system is ensured of immediate visual affect when it\n\t**\tdecides to change the animation state of the building.\n\t*/\n\tif (QueueBState != BSTATE_NONE) {\n\t\tif (BState != QueueBState) {\n\t\t\tBState = QueueBState;\n\t\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\t\t\tif (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {\n\t\t\t\tSet_Rate(Options.Normalize_Delay(ctrl->Rate));\n\t\t\t} else {\n\t\t\t\tSet_Rate(ctrl->Rate);\n\t\t\t}\n\t\t\tSet_Stage(ctrl->Start);\n\t\t}\n\t\tQueueBState = BSTATE_NONE;\n\t}\n\n\t/*\n\t**\tIf the building's strength has changed, then update the power\n\t**\taccordingly.\n\t*/\n\tif (Strength != LastStrength) {\n\t\tint oldpower = Power_Output();\n\t\tLastStrength = Strength;\n\t\tint newpower = Power_Output();\n\t\tHouse->Adjust_Power(newpower - oldpower);\n\t}\n\n\t/*\n\t**\tCheck to see if the destruction countdown timer is active. If so, then decrement it.\n\t**\tWhen this timer reaches zero, the building is removed from the map. All the explosions\n\t**\tare presumed to be in progress at this time.\n\t*/\n\tif (Strength == 0) {\n\t\tif (CountDown == 0) {\n\t\t\tLimbo();\n\t\t\tDrop_Debris(WhomToRepay);\n\t\t\tdelete this;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tCharging logic.\n\t*/\n\tCharging_AI();\n\n\t/*\n\t**\tHandle any repair process that may be going on.\n\t*/\n\tRepair_AI();\n\n\t/*\n\t**\tFor computer controlled buildings, determine what should be produced and start\n\t**\tproduction accordingly.\n\t*/\n\tFactory_AI();\n\n\t/*\n\t**\tCheck for demolition timeout. When timeout has expired, the building explodes.\n\t*/\n\tif (IsGoingToBlow && CountDown == 0) {\n\n\t\t/*\n\t\t** Maybe trigger an achivement. ST - 11/14/2019 1:53PM\n\t\t*/\n\t\tTechnoTypeClass const *object_type = Techno_Type_Class();\n\t\tif (object_type) {\n\t\t\tTechnoClass *saboteur = As_Techno(WhomToRepay);\n\t\t\tif (saboteur && saboteur->IsActive && saboteur->House && saboteur->House->IsHuman) {\n\t\t\t\tOn_Achievement_Event(saboteur->House, \"BUILDING_DESTROYED_C4\", object_type->IniName);\n\t\t\t}\n\t\t}\t\t\t\n\t\t\n\t\tint damage = Strength;\n\t\tTake_Damage(damage, 0, WARHEAD_FIRE, As_Techno(WhomToRepay), true);\n\t\tif (!IsActive) {\n\t\t\treturn;\n\t\t}\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tTurret equiped buildings must handle turret rotation logic here. This entails\n\t**\trotating the turret to the desired facing as well as figuring out what that\n\t**\tdesired facing should be.\n\t*/\n\tRotation_AI();\n\n\t/*\n\t** Gap Generators need to scan if they've just become activated, or if\n\t** the power has just come on enough so they can scan.  Also, they need\n\t** to un-jam if the power has just dropped off.\n\t*/\n\tif (*this == STRUCT_GAP) {\n\t\tif (Arm == 0) {\n\t\t\tIsJamming = false;\n\t\t\tArm = TICKS_PER_MINUTE * Rule.GapRegenInterval + Random_Pick(1, TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (!IsJamming) {\n\t\t\tif (House->Power_Fraction() >= 1) {\n\t\t\t\tMap.Jam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\t\t\t\tIsJamming = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (House->Power_Fraction() < 1) {\n\t\t\t\tIsJamming = false;\n\t\t\t\tMap.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Radar facilities and SAMs need to check for the proximity of a mobile\n\t** radar jammer.\n\t*/\n\tif ((*this == STRUCT_RADAR || *this == STRUCT_SAM) && (Frame % TICKS_PER_SECOND) == 0) {\n\t\tIsJammed = false;\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj != NULL &&\n\t\t\t\t\t!obj->IsInLimbo &&\n\t\t\t\t\t!obj->House->Is_Ally(House) &&\n\t\t\t\t\tobj->Class->IsJammer &&\n\t\t\t\t\tDistance(obj) <= Rule.RadarJamRadius) {\n\n\t\t\t\tIsJammed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Chronosphere active animation control.\n\t*/\n\tif (*this == STRUCT_CHRONOSPHERE && BState == BSTATE_ACTIVE && QueueBState == BSTATE_NONE && Scen.FadeTimer == 0) {\n\t\tBegin_Mode(BSTATE_IDLE);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Unlimbo -- Removes a building from limbo state.                              *\n *                                                                                             *\n *    Use this routine to transform a building that has been held in limbo                     *\n *    state, into one that really exists on the map. Once a building as                        *\n *    been unlimboed, then it becomes a normal object in the game world.                       *\n *                                                                                             *\n * INPUT:   pos   -- The position to place the building on the map.                            *\n *                                                                                             *\n *          dir (optional) -- not used for this class                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the unlimbo successful?                                                  *\n *                                                                                             *\n * WARNINGS:   The unlimbo operation might not be successful if the                            *\n *             building could not be placed at the location specified.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Matches virtual function format for base class.                          *\n *   05/09/1995 JLB : Handles wall placement.                                                  *\n *   06/18/1995 JLB : Checks for wall legality before placing down.                            *\n *=============================================================================================*/\nbool BuildingClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this is a wall type building, then it never gets unlimboed. Instead, it gets\n\t**\tconverted to an overlay type.\n\t*/\n\tif (Class->IsWall) {\n\t\tif (Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {\n\t\t\tOverlayType otype = OVERLAY_NONE;\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_SANDBAG_WALL:\n\t\t\t\t\totype\t= OVERLAY_SANDBAG_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_CYCLONE_WALL:\n\t\t\t\t\totype = OVERLAY_CYCLONE_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BRICK_WALL:\n\t\t\t\t\totype = OVERLAY_BRICK_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BARBWIRE_WALL:\n\t\t\t\t\totype = OVERLAY_BARBWIRE_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_WOOD_WALL:\n\t\t\t\t\totype = OVERLAY_WOOD_WALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_FENCE:\n\t\t\t\t\totype = OVERLAY_FENCE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\totype = OVERLAY_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\t\t\tif (otype != OVERLAY_NONE) {\n\t\t\t\tObjectClass * o = OverlayTypeClass::As_Reference(otype).Create_One_Of(House);\n\t\t\t\tif (o && o->Unlimbo(coord)) {\n\t\t\t\t\tMap[coord].Owner = House->Class->House;\n\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\tMap.Sight_From(Coord_Cell(coord), Class->SightRange, House);\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tNormal building unlimbo process.\n\t*/\n\tif (TechnoClass::Unlimbo(coord, dir)) {\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->BScan |= (1L << Class->Type);\n\t\tHouse->ActiveBScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tRecalculate the center point of the house's base.\n\t\t*/\n\t\tHouse->Recalc_Center();\n\n\t\t/*\n\t\t**\tUpdate the total factory type, assuming this building has a factory.\n\t\t*/\n\t\tHouse->Active_Add(this);\n\n\t\t/*\n\t\t**\tPossibly the sidebar will be affected by this addition.\n\t\t*/\n\t\tHouse->IsRecalcNeeded = true;\n\t\tLastStrength = 0;\n\n\t\t// Changes to support client/server multiplayer. ST - 8/2/2019 2:36PM\n\t\t//if ((!IsDiscoveredByPlayer && Map[coord].IsVisible) || Session.Type != GAME_NORMAL) {\n\t\tif ((!Is_Discovered_By_Player(House) && Map[coord].Is_Visible(House)) || Session.Type != GAME_NORMAL) {\n\t\t\tif (House->IsHuman) {\n\t\t\t\t//Revealed(PlayerPtr);\n\t\t\t\tRevealed(House);\n\t\t\t}\n\t\t}\n\t\tif (!House->IsHuman) {\n\t\t\tRevealed(House);\n\t\t}\n\n\t\t// Changes to support client/server multiplayer. ST - 8/2/2019 2:36PM\n\t\t//if (IsOwnedByPlayer) {\n\t\tif (Is_Owned_By_Player()) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\tif ((Class->Ownable & (HOUSEF_GOOD | HOUSEF_BAD)) != (HOUSEF_GOOD | HOUSEF_BAD)) {\n\t\t\tif (Class->Ownable & HOUSEF_GOOD) {\n\t\t\t\tActLike = HOUSE_GREECE;\n\t\t\t} else {\n\t\t\t\tActLike = HOUSE_USSR;\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Take_Damage -- Inflicts damage points upon a building.                       *\n *                                                                                             *\n *    This routine will inflict damage points upon the specified building.                     *\n *    It will handle the damage animation and building destruction. Use                        *\n *    this routine whenever a building is attacked.                                            *\n *                                                                                             *\n * INPUT:   damage   -- Amount of damage to inflict.                                           *\n *                                                                                             *\n *          distance -- The distance from the damage center point to the object's center point.*\n *                                                                                             *\n *          warhead  -- The kind of damage to inflict.                                         *\n *                                                                                             *\n *          source   -- The source of the damage. This is used to change targeting.            *\n *                                                                                             *\n *          forced   -- Is the damage forced upon the object regardless of whether it          *\n *                      is normally immune?                                                    *\n *                                                                                             *\n * OUTPUT:  true/false; Was the building destroyed?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1991     : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   04/16/1994 JLB : Added warhead modifier to damage.                                        *\n *   06/03/1994 JLB : Added source of damage as target value.                                  *\n *   06/20/1994 JLB : Source is a base class pointer.                                          *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   07/15/1995 JLB : Power ratio gets adjusted.                                               *\n *=============================================================================================*/\nResultType BuildingClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\tint shakes;\n\n\tif (this != source /*&& !Class->IsInsignificant*/) {\n\n\t\tif (source) {\n\t\t\tHouse->LATime = Frame;\n\t\t\tHouse->LAType = source->What_Am_I();\n\t\t\tHouse->LAZone = House->Which_Zone(this);\n\t\t\tHouse->LAEnemy = source->Owner();\n\n\t\t\tif (!House->Is_Ally(source)) {\n\t\t\t\tHouse->Enemy = source->Owner();\n\t\t\t}\n\n\t\t\tBase_Is_Attacked(source);\n\t\t}\n\n\t\tshort const * offset = Occupy_List();\n\n\t\t/*\n\t\t** Memorize who they used to be in radio contact with.\n\t\t*/\n\t\tTechnoClass *tech = Contact_With_Whom();\n\t\t/*\n\t\t**\tPerform the low level damage assessment.\n\t\t*/\n\t\tres = TechnoClass::Take_Damage(damage, distance, warhead, source, forced);\n\t\tswitch (res) {\n\t\t\tcase RESULT_DESTROYED:\n\n\t\t\t\t/*\n\t\t\t\t**\tAdd the building to the base prebuild list if allowed. This will force\n\t\t\t\t**\tthe computer to rebuild this structure if it can.\n\t\t\t\t*/\n\t\t\t\tif (IsToRebuild && Class->Level != -1 && Base.House == House->Class->House && Base.Get_Node(this) == 0) {\n//\t\t\t\tif (IsToRebuild && Class->IsBuildable && Base.House == House->Class->House && Base.Get_Node(this) == 0) {\n\t\t\t\t\tBase.Nodes.Add(BaseNodeClass(Class->Type, Coord_Cell(Coord)));\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDestroy all attached objects.\n\t\t\t\t*/\n\t\t\t\twhile (Attached_Object()) {\n\t\t\t\t\tFootClass * obj = Detach_Object();\n\n\t\t\t\t\tDetach_All(true);\n\t\t\t\t\tdelete obj;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we were in contact with a landed plane, blow the plane up too.\n\t\t\t\t*/\n\t\t\t\tif (tech && tech->IsActive && tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tint damage = 500;\n\t\t\t\t\ttech->Take_Damage(damage, 0, WARHEAD_AP, source, forced);\n\t\t\t\t}\n\n\t\t\t\tSound_Effect(VOC_KABOOM22, Coord);\n\t\t\t\twhile (*offset != REFRESH_EOL) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the building is destroyed, then lots of\n\t\t\t\t\t**\texplosions occur.\n\t\t\t\t\t*/\n\t\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Cell_Coord(cell));\n\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\tnew AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0080), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\t\tnew AnimClass(ANIM_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnew AnimClass(ANIM_FBALL1, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 3));\n\t\t\t\t}\n\n\t\t\t\tshakes = Class->Cost_Of() / 400;\n\t\t\t\tif (shakes) {\n\t\t\t\t\tShake_The_Screen(shakes, Owner());\n\t\t\t\t\tif (source && Owner() != source->Owner()) {\n\t\t\t\t\t\tShake_The_Screen(shakes, source->Owner());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSound_Effect(VOC_CRUMBLE, Coord);\n\t\t\t\tif (Mission == MISSION_DECONSTRUCTION) {\n\t\t\t\t\tCountDown = 0;\n\t\t\t\t\tSet_Rate(0);\n\t\t\t\t} else {\n\t\t\t\t\tCountDown = 8;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf it is in radio contact and the object seems to be attached, then tell\n\t\t\t\t**\tit to run away.\n\t\t\t\t*/\n\t\t\t\tif (In_Radio_Contact() && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA force destruction will not generate survivors.\n\t\t\t\t*/\n\t\t\t\tif (forced || *this == STRUCT_KENNEL) {\n\t\t\t\t\tIsSurvivorless = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a radar facility or advanced communications\n\t\t\t\t** center will cause the spiedby field to change...\n\t\t\t\t*/\n\t\t\t\tif (SpiedBy) {\n\t\t\t\t\tSpiedBy = 0;\n\t\t\t\t\tStructType struc = *this;\n\t\t\t\t\tif (struc == STRUCT_RADAR /* || struc == STRUCT_EYE */) {\n\t\t\t\t\t\tUpdate_Radar_Spied();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a gap generator will cause the cells it affects\n\t\t\t\t** to stop being jammed.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_GAP) {\n\t\t\t\t\tRemove_Gap_Effect();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a shipyard or sub pen may cause attached ships\n\t\t\t\t** who are repairing themselves to discontinue repairs.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {\n\t\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\t\tVesselClass *obj = Vessels.Ptr(index);\n\t\t\t\t\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\t\t\t\t\tif (obj->IsSelfRepairing) {\n\t\t\t\t\t\t\t\tif (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {\n\t\t\t\t\t\t\t\t\tobj->IsSelfRepairing = false;\n\t\t\t\t\t\t\t\t\tobj->IsToSelfRepair = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Destruction of a barrel will cause the surrounding squares to\n\t\t\t\t** be hit with damage.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_BARREL || *this == STRUCT_BARREL3) {\n\t\t\t\t\tCOORDINATE center = Center_Coord();\n\t\t\t\t\tCELL cellcenter = Coord_Cell(center);\n\n\t\t\t\t\tBulletClass * bullet;\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_N)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_N);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_E)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_E);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_S)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_S);\n\t\t\t\t\t}\n\n\t\t\t\t\tbullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_W)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tbullet->Unlimbo(center, DIR_W);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (House) {\n\t\t\t\t\tHouse->Check_Pertinent_Structures();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_HALF:\n\t\t\t\tif (*this == STRUCT_PUMP) {\n\t\t\t\t\tAnimClass * anim = new AnimClass(ANIM_OILFIELD_BURN, Coord_Add(Coord, 0x00400130L), 1);\n\t\t\t\t\tif (anim) {\n\t\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fall into next case.\n\n\t\t\tcase RESULT_MAJOR:\n\t\t\t\tSound_Effect(VOC_KABOOM1, Coord);\n\t\t\t\twhile (*offset != REFRESH_EOL) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\t\t\t\t\tAnimClass * anim = NULL;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tShow pieces of fire to indicate that a significant change in\n\t\t\t\t\t**\tdamage level has occurred.\n\t\t\t\t\t*/\n\t\t\t\t\tif (warhead == WARHEAD_FIRE) {\n\t\t\t\t\t\tswitch (Random_Pick(0, 5+Class->Width()+Class->Height())) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\tcase 8:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_ON_FIRE_BIG, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Building may catch on fire, but only if it wasn't a\n\t\t\t\t\t\t\t** renovator that caused the damage.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (source == NULL || source->What_Am_I() != RTTI_INFANTRY || *(InfantryClass *)source != INFANTRY_RENOVATOR) {\n\t\t\t\t\t\t\t\tanim = new AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), Random_Pick(0, 7), Random_Pick(1, 3));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the animation was created, then attach it to the building.\n\t\t\t\t\t*/\n\t\t\t\t\tif (anim) {\n\t\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_NONE:\n\t\t\t\tbreak;\n\n\t\t\tcase RESULT_LIGHT:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (source && res != RESULT_NONE) {\n\n\t\t\t/*\n\t\t\t**\tIf any damage occurred, then inform the house of this fact. If it is the player's\n\t\t\t**\thouse, it might announce this fact.\n\t\t\t*/\n\t\t\tif (!Class->IsInsignificant) {\n\t\t\t\tHouse->Attacked(this);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Save the type of the house that's doing the damage, so if the building burns\n\t\t\t** to death credit can still be given for the kill\n\t\t\t*/\n\t\t\tWhoLastHurtMe = source->Owner();\n\n\t\t\t/*\n\t\t\t**\tWhen certain buildings are hit, they \"snap out of it\" and\n\t\t\t**\treturn fire if they are able and allowed.\n\t\t\t*/\n\t\t\tif (*this != STRUCT_SAM && *this != STRUCT_AAGUN &&\n\t\t\t\t!House->Is_Ally(source) &&\n\t\t\t\tClass->PrimaryWeapon != NULL &&\n\t\t\t\t(!Target_Legal(TarCom) || !In_Range(TarCom))) {\n\n\t\t\t\tif (source->What_Am_I() != RTTI_AIRCRAFT && (!House->IsHuman || Rule.IsSmartDefense)) {\n\t\t\t\t\tAssign_Target(source->As_Target());\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGenerate a random rotation effect since there is nothing else that this\n\t\t\t\t\t**\tbuilding can do.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!PrimaryFacing.Is_Rotating()) {\n\t\t\t\t\t\tPrimaryFacing.Set_Desired(Random_Pick(DIR_N, DIR_MAX));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::new -- Allocates a building object from building pool.                       *\n *                                                                                             *\n *    This routine will allocate a building slot from the building alloc                       *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated building. If NULL is                       *\n *          returned, then this indicates a failure to allocate.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/11/1994 JLB : Created.                                                                 *\n *   04/21/1994 JLB : Converted to operator new.                                               *\n *   05/17/1994 JLB : Revamped allocation scheme                                               *\n *   07/29/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid * BuildingClass::operator new(size_t )\n{\n\tvoid * ptr = Buildings.Allocate();\n\tif (ptr) {\n\t\t((BuildingClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::delete -- Deallocates building object.                                       *\n *                                                                                             *\n *    This is the memory deallocation operation for a building object.                         *\n *    Since buildings are allocated out of a fixed memory block, all that                      *\n *    is needed is to flag the unit as inactive.                                               *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to building to deallocate.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::operator delete(void *ptr)\n{\n\tif (ptr) {\n\t\t((BuildingClass *)ptr)->IsActive = false;\n\t}\n\tBuildings.Free((BuildingClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::BuildingClass -- Constructor for buildings.                                  *\n *                                                                                             *\n *    This routine inserts a building into the object tracking system.                         *\n *    It is placed into a limbo state unless a location is provided for                        *\n *    it to unlimbo at.                                                                        *\n *                                                                                             *\n * INPUT:   type  -- The structure type to make this object.                                   *\n *                                                                                             *\n *          house -- The owner of this building.                                               *\n *                                                                                             *\n *          pos   -- The position to unlimbo the building. If -1 is                            *\n *                   specified, then the building remains in a limbo                           *\n *                   state.                                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/21/1994 JLB : Created.                                                                 *\n *   08/07/1995 JLB : Fixed act like value to match expected value.                            *\n *=============================================================================================*/\nBuildingClass::BuildingClass(StructType type, HousesType house) :\n\tTechnoClass(RTTI_BUILDING, Buildings.ID(this), house),\n\tClass(BuildingTypes.Ptr((int)type)),\n\tFactory(0),\n\tActLike(House->ActLike),\n\tIsToRebuild(false),\n\tIsToRepair(false),\n\tIsAllowedToSell(true),\n\tIsReadyToCommence(false),\n\tIsRepairing(false),\n\tIsWrenchVisible(false),\n\tIsGoingToBlow(false),\n\tIsSurvivorless(false),\n\tIsCharging(false),\n\tIsCharged(false),\n\tIsCaptured(false),\n\tIsJamming(false),\n\tIsJammed(false),\n\tHasFired(false),\n\tHasOpened(false),\n\tCountDown(0),\n\tBState(BSTATE_NONE),\n\tQueueBState(BSTATE_NONE),\n\tWhoLastHurtMe(house),\n\tWhomToRepay(TARGET_NONE),\n\tAnimToTrack(TARGET_NONE),\n\tLastStrength(0),\n\tPlacementDelay(0)\n{\n\tHouse->Tracking_Add(this);\n\tIsSecondShot = !Class->Is_Two_Shooter();\n\tStrength = Class->MaxStrength;\n\tAmmo = Class->MaxAmmo;\n\n\t/*\n\t**\tIf the building could never be built, then it can never be sold either. This\n\t**\tis due to the lack of buildup animation.\n\t*/\n\tif (Class->Get_Buildup_Data() != NULL) {\n//\tif (!Class->IsBuildable) {\n\t\tIsAllowedToSell = false;\n\t}\n\n//\tif (Session.Type == GAME_INTERNET) {\n//\t\tHouse->BuildingTotals->Increment_Unit_Total( (int) type);\n//\t}\n\n}\n\n\n/***********************************************************************************************\n * BuildingClass::~BuildingClass -- Destructor for building type objects.                      *\n *                                                                                             *\n *    This destructor for building objects will put the building in limbo if possible.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass::~BuildingClass(void)\n{\n\tif (GameActive && Class) {\n\t\tif (House) {\n\t\t\tHouse->Tracking_Remove(this);\n\t\t}\n\t\tBuildingClass::Limbo();\n\t}\n\tClass = 0;\n\n\tdelete (FactoryClass *)Factory;\n\tFactory = 0;\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                      *\n *                                                                                             *\n *    This routine is called when a building is destroyed. It handles                          *\n *    placing the rubble down.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   06/13/1995 JLB : Added smoke and normal infantry survivor possibility.                    *\n *   07/16/1995 JLB : Survival rate depends on if captured or sabotaged.                       *\n *=============================================================================================*/\nvoid BuildingClass::Drop_Debris(TARGET source)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL const * offset;\n\tCELL cell;\n\n\t/*\n\t**\tGenerate random survivors from the destroyed building.\n\t*/\n\tcell = Coord_Cell(Coord);\n\toffset = Occupy_List();\n\tint odds = 2;\n\tif (Target_Legal(WhomToRepay)) odds -= 1;\n\tif (IsCaptured) odds += 6;\n\tint count = How_Many_Survivors();\n\twhile (*offset != REFRESH_EOL) {\n\t\tCELL\tnewcell;\n\n\t\tnewcell = cell + *offset++;\n\t\tCellClass const * cellptr = &Map[newcell];\n\n\t\t/*\n\t\t**\tInfantry could run out of a destroyed building.\n\t\t*/\n\t\tif (!House->IsToDie && count > 0) {\n\t\t\tInfantryClass * i = NULL;\n\n\t\t\tif (Random_Pick(0, odds) == 1) {\n\t\t\t\ti = NULL;\n\t\t\t\tInfantryType typ = Crew_Type();\n\t\t\t\tif (typ != INFANTRY_NONE) i = new InfantryClass(typ, House->Class->House);\n\t\t\t\tif (i != NULL) {\n\t\t\t\t\tif (Class->Get_Buildup_Data() != NULL && i->Class->IsNominal) i->IsTechnician = true;\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (i->Unlimbo(Cell_Coord(newcell), DIR_N)) {\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t\ti->Strength = Random_Pick(5, (int)i->Class->MaxStrength);\n\t\t\t\t\t\ti->Scatter(0, true);\n\t\t\t\t\t\tif (source != TARGET_NONE && !House->Is_Ally(As_Object(source))) {\n\t\t\t\t\t\t\ti->Assign_Mission(MISSION_ATTACK);\n\t\t\t\t\t\t\ti->Assign_Target(source);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (House->IsHuman) {\n\t\t\t\t\t\t\t\ti->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ti->Assign_Mission(MISSION_HUNT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete i;\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tSmoke and fire only appear on terrestrail cells. They should not appear on\n\t\t**\trivers, clifs, or water cells.\n\t\t*/\n\t\tif (cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true)) {\n\n\t\t\t/*\n\t\t\t**\tPossibly add some smoke rising from the ashes of the building.\n\t\t\t*/\n\t\t\tswitch (Random_Pick(0, 5)) {\n\t\t\t\tcase 0:\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\t\tnew AnimClass(ANIM_SMOKE_M, Coord_Scatter(Cell_Coord(newcell), 0x0050, false), Random_Pick(0, 5), Random_Pick(1, 2));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThe building always scars the ground in some fashion.\n\t\t\t*/\n\t\t\tif (Percent_Chance(25)) {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(newcell));\n\t\t\t} else {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Coord_Scatter(Cell_Coord(newcell), 0x0080, false));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Active_Click_With -- Handles clicking on the map while the building is selected.*\n *                                                                                             *\n *    This interface routine handles when the player clicks on the map while this building     *\n *    is currently selected. This is used to assign an override target to a turret or          *\n *    guard tower.                                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that was clicked upon.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (action == ACTION_ATTACK && object != NULL) {\n\t\tPlayer_Assign_Mission(MISSION_ATTACK, object->As_Target());\n\t}\n\n\tif (action == ACTION_TOGGLE_PRIMARY && Class->Is_Factory()) {\n\t\tOutList.Add(EventClass(EventClass::PRIMARY, TargetClass(this)));\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Active_Click_With -- Handles cell selection for buildings.                   *\n *                                                                                             *\n *    This routine really only serves one purpose -- to allow targeting of the ground for      *\n *    buildings that are equipped with weapons.                                                *\n *                                                                                             *\n * INPUT:   action   -- The requested action to perform.                                       *\n *                                                                                             *\n *          cell     -- The cell location to perform the action upon.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *   10/04/1995 JLB : Handles construction yard undeploy to move logic.                        *\n *=============================================================================================*/\nvoid BuildingClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (action == ACTION_ATTACK) {\n\t\tPlayer_Assign_Mission(MISSION_ATTACK, ::As_Target(cell));\n\t}\n\n\tif (action == ACTION_MOVE && *this == STRUCT_CONST) {\n\t\tOutList.Add(EventClass(EventClass::ARCHIVE, TargetClass(this), TargetClass(::As_Target(cell))));\n\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(this)));\n\n\t\tCOORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());\n\t\tOutList.Add(EventClass(ANIM_MOVE_FLASH, PlayerPtr->Class->House, coord, 1 << PlayerPtr->Class->House));\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Assign_Target -- Assigns a target to the building.                           *\n *                                                                                             *\n *    Assigning of a target to a building makes sense if the building is one that can attack.  *\n *    This routine would be used to assign the attack target to a turret or guard tower.       *\n *                                                                                             *\n * INPUT:   target   -- The target that was clicked on while this building was selected.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   11/02/1994 JLB : Checks for range before assigning target.                                *\n *=============================================================================================*/\nvoid BuildingClass::Assign_Target(TARGET target)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this != STRUCT_SAM && *this != STRUCT_AAGUN && !In_Range(target, 0)) {\n\t\ttarget = TARGET_NONE;\n\t}\n\n\tTechnoClass::Assign_Target(target);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Init -- Initialize the building system to an empty null state.               *\n *                                                                                             *\n *    This routine initializes the building system in preparation for a scenario load.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Init(void)\n{\n\tBuildings.Free_All();\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Exit_Object -- Initiates an object to leave the building.                    *\n *                                                                                             *\n *    This function is used to cause an object to exit the building. It is called when a       *\n *    factory produces a vehicle or other mobile object and that object needs to exit the      *\n *    building to join the ranks of a regular unit. Typically, the object is placed down on    *\n *    the map such that it overlaps the building and then it is given a movement order so that *\n *    it will move to an adjacent free cell.                                                   *\n *                                                                                             *\n * INPUT:   base  -- Pointer to the object that is to exit the building.                       *\n *                                                                                             *\n * OUTPUT:  Returns the success rating for the exit attempt;                                   *\n *             0  = complete failure (refund money please)                                     *\n *             1  = temporarily prevented (try again later please)                             *\n *             2  = successful                                                                 *\n *                                                                                             *\n * WARNINGS:   The building is placed in radio contact with the object. The object is in a     *\n *             tethered condition. This condition will be automatically broken when the        *\n *             object reaches the adjacent square.                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/28/1994 JLB : Created.                                                                 *\n *   04/10/1995 JLB : Handles building production by computer.                                 *\n *   06/17/1995 JLB : Handles refinery exit.                                                   *\n *=============================================================================================*/\nint BuildingClass::Exit_Object(TechnoClass * base)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!base) return(0);\n\n\tTechnoTypeClass const * ttype = (TechnoTypeClass const *)&base->Class_Of();\n\n\t/*\n\t**\tA unit exiting a building is always considered to be \"locked\". That means, it\n\t**\twill be considered as to have legally entered the visible map domain.\n\t*/\n\tbase->IsLocked = true;\n\n\t/*\n\t**\tFind a good cell to unload the object to. The object, probably a vehicle\n\t**\twill drive/walk to the adjacent free cell.\n\t*/\n\tCELL cell = 0;\n\n\tswitch (base->What_Am_I()) {\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\tAircraftClass * air = (AircraftClass *)base;\n\n\t\t\t\tair->Height = 0;\n\t\t\t\tScenarioInit++;\n\t\t\t\tif (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {\n\t\t\t\t\tTransmit_Message(RADIO_HELLO, air);\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\treturn(2);\n\t\t\t\t}\n\t\t\t\tScenarioInit--;\n\t\t\t} else {\n\t\t\t\tAircraftClass * air = (AircraftClass *)base;\n\n\t\t\t\tif (Cell_X(Coord_Cell(Center_Coord())) - Map.MapCellX < Map.MapCellWidth/2) {\n\t\t\t\t\tcell = XY_Cell(Map.MapCellX-1, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);\n\t\t\t\t} else {\n\t\t\t\t\tcell = XY_Cell(Map.MapCellX+Map.MapCellWidth, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);\n\t\t\t\t}\n\t\t\t\tScenarioInit++;\n\t\t\t\tif (air->Unlimbo(Cell_Coord(cell), DIR_N)) {\n//BG\t\t\t\tair->Assign_Destination(::As_Target(Nearby_Location(air)));\n/*BG*/\t\t\tair->Assign_Destination(::As_Target(air->Nearby_Location(this)));\n\t\t\t\t\tair->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\treturn(2);\n\t\t\t\t}\n\t\t\t\tScenarioInit--;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_SUB_PEN:\n\t\t\t\tcase STRUCT_SHIP_YARD:\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0 && base->Unlimbo(Cell_Coord(cell), Direction(Cell_Coord(cell)))) {\n\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_UNIT:\n\t\t\tswitch (Class->Type) {\n\t\t\t\tcase STRUCT_REFINERY:\n\t\t\t\t\tif (base->What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\tcell = Coord_Cell(Center_Coord());\n\t\t\t\t\t\tUnitClass * unit = (UnitClass *)base;\n\n\t\t\t\t\t\tcell = Adjacent_Cell(cell, FACING_SW);\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (unit->Unlimbo(Cell_Coord(Adjacent_Cell(cell, DIR_S)), DIR_SW_X2)) {\n\t\t\t\t\t\t\tunit->PrimaryFacing = DIR_S;\n\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_HARVEST);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbase->Scatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_WEAP:\n\t\t\t\t\tif (Mission == MISSION_UNLOAD) {\n\t\t\t\t\t\tfor(int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg->Owner() == Owner() && *bldg == STRUCT_WEAP && bldg != this && bldg->Mission == MISSION_GUARD && !bldg->Factory) {\n\t\t\t\t\t\t\t\tFactoryClass * temp = Factory;\n\t\t\t\t\t\t\t\tbldg->Factory = Factory;\n\t\t\t\t\t\t\t\tFactory = 0;\n\t\t\t\t\t\t\t\tint retval = (bldg->Exit_Object(base));\n\t\t\t\t\t\t\t\tbldg->Factory = 0;\n\t\t\t\t\t\t\t\tFactory = temp;\n\t\t\t\t\t\t\t\treturn(retval);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(1);\t// fail while we're still unloading previous\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (base->Unlimbo(Exit_Coord(), DIR_S)) {\n\t\t\t\t\t\tbase->Mark(MARK_UP);\n\t\t\t\t\t\tbase->Coord = Exit_Coord();\n\t\t\t\t\t\tbase->Mark(MARK_DOWN);\n\t\t\t\t\t\tTransmit_Message(RADIO_HELLO, base);\n\t\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t\t\tAssign_Mission(MISSION_UNLOAD);\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STRUCT_BARRACKS:\n\t\t\t\tcase STRUCT_TENT:\n\t\t\t\tcase STRUCT_KENNEL:\n\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0) {\n\t\t\t\t\t\tDirType\tdir = Direction(cell);\n\t\t\t\t\t\tCOORDINATE\t\tstart = Exit_Coord();\n\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (base->Unlimbo(start, dir)) {\n\n\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tWhen disembarking from a transport then guard an area around the\n\t\t\t\t\t\t\t**\tcenter of the base.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbase->Assign_Destination(::As_Target(cell));\n\t\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t\tbase->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tEstablish radio contact so unload coordination can occur. This\n\t\t\t\t\t\t\t**\tradio contact should always succeed.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, base) == RADIO_ROGER) {\n\t\t\t\t\t\t\t\tTransmit_Message(RADIO_UNLOAD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\treturn(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tcell = Find_Exit_Cell(base);\n\t\t\t\t\tif (cell != 0) {\n\t\t\t\t\t\tDirType\tdir = Direction(cell);\n\t\t\t\t\t\tCOORDINATE\t\tstart = Exit_Coord();\n\n\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\tif (base->Unlimbo(start, dir)) {\n\n\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tWhen disembarking from a transport then guard an area around the\n\t\t\t\t\t\t\t**\tcenter of the base.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbase->Assign_Destination(::As_Target(cell));\n\t\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\t\tbase->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t\tbase->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\treturn(2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\n\t\t\tif (!House->IsHuman) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the next available spot to place this newly created building. If the\n\t\t\t\t**\tbuilding could be placed at the desired location, fine. If not, then this\n\t\t\t\t**\troutine will return failure. The calling routine will probably abandon this\n\t\t\t\t**\tbuilding in preference to building another.\n\t\t\t\t*/\n\t\t\t\tBaseNodeClass * node = Base.Next_Buildable(((BuildingClass *)base)->Class->Type);\n\t\t\t\tCOORDINATE coord = 0;\n\t\t\t\tif (node) {\n\t\t\t\t\tcoord = Cell_Coord(node->Cell);\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFind a suitable new spot to place.\n\t\t\t\t\t*/\n\t\t\t\t\tcoord = House->Find_Build_Location((BuildingClass *)base);\n\t\t\t\t}\n\n\t\t\t\tif (coord) {\n\t\t\t\t\tif (Flush_For_Placement(base, Coord_Cell(coord))) {\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t\tif (base->Unlimbo(coord)) {\n\t\t\t\t\t\tif (node && ((BuildingClass *)base)->Class->Type == House->BuildStructure) {\n\t\t\t\t\t\t\tHouse->BuildStructure = STRUCT_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tFailure to exit the object results in a false return value.\n\t*/\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.     *\n *                                                                                             *\n *    This routine will tell the sidebar of objects that can be built. The function is called  *\n *    whenever a building matures.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/11/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Only updates for PLAYER buildings.                                       *\n *=============================================================================================*/\nvoid BuildingClass::Update_Buildables(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** Only do this for real human players. ST - 3/22/2019 1:38PM\n\t*/\n\tif (PlayerPtr != House) {\n\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER || House->IsHuman == false) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tbool buildable_via_capture = (IsCaptured && ActLike != House->ActLike) ? true : false;\n\n\tif (!IsInLimbo && Is_Discovered_By_Player()) {\n\t\tswitch (Class->ToBuild) {\n\t\t\tint i;\n\t\t\tint u;\n\t\t\tint f;\n\t\t\tint a;\n\t\t\tint v;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tfor (v = VESSEL_FIRST; v < VESSEL_COUNT; v++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&VesselTypeClass::As_Reference((VesselType)v), ActLike)) {\n\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_VESSELTYPE, v, House, buildable_via_capture);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.Add(RTTI_VESSELTYPE, v, buildable_via_capture);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\tfor (i = STRUCT_FIRST; i < STRUCT_COUNT; i++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&BuildingTypeClass::As_Reference((StructType)i), ActLike)) {\n\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_BUILDINGTYPE, i, House, buildable_via_capture);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.Add(RTTI_BUILDINGTYPE, i, buildable_via_capture);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tfor (u = UNIT_FIRST; u < UNIT_COUNT; u++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&UnitTypeClass::As_Reference((UnitType)u), ActLike)) {\n\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_UNITTYPE, u, House, buildable_via_capture);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.Add(RTTI_UNITTYPE, u, buildable_via_capture);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tfor (f = INFANTRY_FIRST; f < INFANTRY_COUNT; f++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&InfantryTypeClass::As_Reference((InfantryType)f), ActLike)) {\n\t\t\t\t\t\tif (InfantryTypeClass::As_Reference((InfantryType)f).IsDog) {\n\t\t\t\t\t\t\tif (*this == STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_INFANTRYTYPE, f, House, buildable_via_capture);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f, buildable_via_capture);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (*this != STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_INFANTRYTYPE, f, House, buildable_via_capture);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f, buildable_via_capture);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tfor (a = AIRCRAFT_FIRST; a < AIRCRAFT_COUNT; a++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&AircraftTypeClass::As_Reference((AircraftType)a), ActLike)) {\n\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_AIRCRAFTTYPE, a, House, buildable_via_capture);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.Add(RTTI_AIRCRAFTTYPE, a, buildable_via_capture);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n\n#if (0) //Old code for reference. ST - 8/2/2019 2:41PM\n/***********************************************************************************************\n * BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.     *\n *                                                                                             *\n *    This routine will tell the sidebar of objects that can be built. The function is called  *\n *    whenever a building matures.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/11/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Only updates for PLAYER buildings.                                       *\n *=============================================================================================*/\nvoid BuildingClass::Update_Buildables(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (House == PlayerPtr && !IsInLimbo && IsDiscoveredByPlayer) {\n\t\tswitch (Class->ToBuild) {\n\t\t\tint i;\n\t\t\tint u;\n\t\t\tint f;\n\t\t\tint a;\n\t\t\tint v;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tfor (v = VESSEL_FIRST; v < VESSEL_COUNT; v++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&VesselTypeClass::As_Reference((VesselType)v), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_VESSELTYPE, v);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\tfor (i = STRUCT_FIRST; i < STRUCT_COUNT; i++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&BuildingTypeClass::As_Reference((StructType)i), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_BUILDINGTYPE, i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tfor (u = UNIT_FIRST; u < UNIT_COUNT; u++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&UnitTypeClass::As_Reference((UnitType)u), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_UNITTYPE, u);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tfor (f = INFANTRY_FIRST; f < INFANTRY_COUNT; f++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&InfantryTypeClass::As_Reference((InfantryType)f), ActLike)) {\n\t\t\t\t\t\tif (InfantryTypeClass::As_Reference((InfantryType)f).IsDog) {\n\t\t\t\t\t\t\tif (*this == STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (*this != STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\tMap.Add(RTTI_INFANTRYTYPE, f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tfor (a = AIRCRAFT_FIRST; a < AIRCRAFT_COUNT; a++) {\n\t\t\t\t\tif (PlayerPtr->Can_Build(&AircraftTypeClass::As_Reference((AircraftType)a), ActLike)) {\n\t\t\t\t\t\tMap.Add(RTTI_AIRCRAFTTYPE, a);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * BuildingClass::Fire_Out -- Handles when attached animation expires.                         *\n *                                                                                             *\n *    This routine is used to perform any fixups necessary when the attached animation has     *\n *    terminated. This occurs when the fire & smoke animation that a SAM site produces stops.  *\n *    At that point, normal reload procedures can commence.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Fire_Out(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.               *\n *                                                                                             *\n *    This routine will handle the power adjustments for the associated house when the         *\n *    building goes into limbo. This means that its power drain or production is subtracted    *\n *    from the house accumulated totals.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the building limboed?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Limbo(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\n\t\t/*\n\t\t**\tUpdate the total factory type, assuming this building has a factory.\n\t\t*/\n\t\tHouse->Active_Remove(this);\n\t\tHouse->IsRecalcNeeded = true;\n\t\tHouse->Recalc_Center();\n\n\t\t/*\n\t\t**\tUpdate the power status of the owner's house.\n\t\t*/\n\t\tHouse->Adjust_Power(-Power_Output());\n\t\tHouse->Adjust_Drain(-Class->Drain);\n\t\tHouse->Adjust_Capacity(-Class->Capacity, true);\n\t\tif (House == PlayerPtr) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t**\tThis could be a building that builds. If so, then the sidebar may need adjustment.\n\t\t** Set IsInLimbo to true to \"fool\" the sidebar into knowing that this building\n\t\t** isn't available.  Set it back to false so the rest of the Limbo code works.\n\t\t** Otherwise, the sidebar won't properly remove non-available buildables.\n\t\t*/\n//\t\tif (IsOwnedByPlayer && !ScenarioInit) {\n//\t\t\tIsInLimbo = true;\n//\t\t\tMap.Recalc();\n//\t\t\tIsInLimbo = false;\n//\t\t}\n\t}\n\treturn(TechnoClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Turret_Facing -- Fetches the turret facing for this building.                *\n *                                                                                             *\n *    This will return the turret facing for this building. Some buildings don't have a        *\n *    visual turret (e.g., pillbox) so they return a turret facing that always faces their     *\n *    current target.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current facing of the turret.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType BuildingClass::Turret_Facing(void) const\n{\n\tif (!Class->IsTurretEquipped && Target_Legal(TarCom)) {\n\t\treturn(::Direction(Center_Coord(), As_Coord(TarCom)));\n\t}\n\treturn(PrimaryFacing.Current());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.          *\n *                                                                                             *\n *    This routine intercepts the Greatest_Threat function so that it can add the ability      *\n *    to search for ground targets, if this isn't a SAM site.                                  *\n *                                                                                             *\n * INPUT:   threat   -- The base threat control value. Typically, it might be THREAT_RANGE     *\n *                      or THREAT_NORMAL.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a suitable target. If none could be found, then TARGET_NONE is        *\n *          returned instead.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET BuildingClass::Greatest_Threat(ThreatType threat) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->PrimaryWeapon != NULL) {\n\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t}\n\tif (Class->SecondaryWeapon != NULL) {\n\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t}\n\tif (House->IsHuman) {\n\t\tthreat = threat & ~THREAT_BUILDINGS;\n\t}\n\tthreat = threat | THREAT_RANGE;\n\n//\tif (Class->PrimaryWeapon != NULL) {\n//\t\tif (Class->PrimaryWeapon->Bullet->IsAntiAircraft) {\n//\t\t\tthreat = threat | THREAT_AIR;\n//\t\t}\n//\t\tif (Class->PrimaryWeapon->Bullet->IsAntiGround) {\n//\t\t\tthreat = threat | THREAT_BUILDINGS|THREAT_INFANTRY|THREAT_BOATS|THREAT_VEHICLES;\n//\t\t}\n//\t\tthreat = threat | THREAT_RANGE;\n//\t}\n\treturn(TechnoClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Grand_Opening -- Handles construction completed special operations.          *\n *                                                                                             *\n *    This routine is called when construction has finished. Typically, this enables           *\n *    new production options for factories.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/08/1995 JLB : Created.                                                                 *\n *   06/13/1995 JLB : Added helipad.                                                           *\n *=============================================================================================*/\nvoid BuildingClass::Grand_Opening(bool captured)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!HasOpened || captured) {\n\t\tHasOpened = true;\n\n\t\t/*\n\t\t**\tAdjust the owning house according to the power, drain, and Tiberium capacity that\n\t\t**\tthis building has.\n\t\t*/\n\t\tHouse->Adjust_Drain(Class->Drain);\n\t\tHouse->Adjust_Capacity(Class->Capacity);\n\t\tHouse->IsRecalcNeeded = true;\n\n\t\t/*\tSPECIAL CASE:\n\t\t**\tTiberium Refineries get a free harvester. Add a harvester to the\n\t\t**\treinforcement list at this time.\n\t\t*/\n\t\tif (*this == STRUCT_REFINERY && !ScenarioInit && !captured && !Debug_Map && (!House->IsHuman || PurchasePrice == 0 || PurchasePrice > Class->Raw_Cost())) {\n\t\t\tCELL cell = Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S));\n\n\t\t\tUnitClass * unit = new UnitClass(UNIT_HARVESTER, House->Class->House);\n\t\t\tif (unit != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to place down the harvesters. If it could not be placed, then try\n\t\t\t\t**\tto place it in a nearby location.\n\t\t\t\t*/\n\t\t\t\tif (!unit->Unlimbo(Cell_Coord(cell), DIR_W)) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCheck multiple times for clear locations.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (int i = 0; i < 10; i++) {\n\t\t\t\t\t\tcell = unit->Nearby_Location(this, i);\n\t\t\t\t\t\tif (unit->Unlimbo(Cell_Coord(cell), DIR_SW)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the harvester could still not be placed, then refund the money\n\t\t\t\t\t**\tto the owner and then bail.\n\t\t\t\t\t*/\n\t\t\t\t\tif (unit->IsInLimbo) {\n\t\t\t\t\t\tHouse->Refund_Money(unit->Class->Cost_Of());\n\t\t\t\t\t\tdelete unit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the harvester could not be created in the first place, then give\n\t\t\t\t**\tthe full refund price to the owning player.\n\t\t\t\t*/\n\t\t\t\tHouse->Refund_Money(UnitTypeClass::As_Reference(UNIT_HARVESTER).Cost_Of());\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tHelicopter pads get a free attack helicopter.\n\t\t*/\n\t\tif (!Rule.IsSeparate && *this == STRUCT_HELIPAD && !captured) {\n\t\t\tScenarioInit++;\n\t\t\tAircraftClass * air = 0;\n\t\t\tif (House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_BAD || House->ActLike == HOUSE_UKRAINE) {\n\t\t\t\tair = new AircraftClass(AIRCRAFT_HIND, House->Class->House);\n\t\t\t} else {\n\t\t\t\tair = new AircraftClass(AIRCRAFT_LONGBOW, House->Class->House);\n\t\t\t}\n\t\t\tif (air) {\n\t\t\t\tair->Height = 0;\n\t\t\t\tif (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {\n\t\t\t\t\tair->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tair->Transmit_Message(RADIO_HELLO, this);\n\t\t\t\t\tTransmit_Message(RADIO_TETHER);\n\t\t\t\t}\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Repair -- Initiates or terminates the repair process.                        *\n *                                                                                             *\n *    This routine will start, stop, or toggle the repair process. When a building repairs, it *\n *    occurs incrementally over time.                                                          *\n *                                                                                             *\n * INPUT:   control  -- Determines how to control the repair process.                          *\n *                      0: Turns repair process off (if it was on).                            *\n *                      1: Turns repair process on (if it was off).                            *\n *                      -1:Toggles repair process to other state.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Repair(int control)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsRepairing = (IsRepairing == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tif (IsRepairing) return;\n\t\t\tIsRepairing = true;\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tif (!IsRepairing) return;\n\t\t\tIsRepairing = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tAt this point, we know that the repair state has changed. Perform\n\t**\tappropriate action.\n\t*/\n\tVocType soundid = VOC_NONE;\n\tif (IsRepairing) {\n\t\tif (Strength == Class->MaxStrength) {\n\t\t\tsoundid = VOC_SCOLD;\n\t\t} else {\n\t\t\tsoundid = VOC_CLICK;\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tClicked_As_Target(PlayerPtr->Class->House); // 2019/09/20 JAS - Added record of who clicked on the object\n\t\t\t}\n\t\t\tIsWrenchVisible = true;\n\t\t}\n\t} else {\n\t\tsoundid = VOC_CLICK;\n\t}\n\t\n\tif (House->IsPlayerControl) {\n\t\tSound_Effect(soundid, Coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                    *\n *                                                                                             *\n *    This routine will initiate or stop the sell back process for a building. It is called    *\n *    when the player clicks on a building when the sell mode is active.                       *\n *                                                                                             *\n * INPUT:   control  -- The action to perform. 0 = turn deconstruction off, 1 = deconstruct,   *\n *                      -1 = toggle deconstruction state.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Sell_Back(int control)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Get_Buildup_Data()) {\n\t\tbool decon = false;\n\t\tswitch (control) {\n\t\t\tcase -1:\n\t\t\t\tdecon = (Mission != MISSION_DECONSTRUCTION);\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tif (Mission == MISSION_DECONSTRUCTION) return;\n\t\t\t\tif (IsGoingToBlow) return;\n\t\t\t\tdecon = true;\n\t\t\t\tbreak;\n\n\t\t\tcase 0:\n\t\t\t\tif (Mission != MISSION_DECONSTRUCTION) return;\n\t\t\t\tdecon = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point, we know that the repair state has changed. Perform\n\t\t**\tappropriate action.\n\t\t*/\n\t\tif (decon) {\n\t\t\tAssign_Mission(MISSION_DECONSTRUCTION);\n\t\t\tCommence();\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tClicked_As_Target(PlayerPtr->Class->House);\n\t\t\t}\n\t\t}\n\t\tif (House->IsPlayerControl) {\n\t\t\tSound_Effect(VOC_CLICK);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::What_Action -- Determines action to perform if click on specified object.    *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse was clicked on the       *\n *    object specified. This determination is used to control the mouse imagery and the        *\n *    function process when the mouse button is pressed.                                       *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that, if clicked on, will control what action    *\n *                      is to be performed.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the ActionType that will occur if the mouse is clicked over the       *\n *          object specified while the building is currently selected.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType BuildingClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = TechnoClass::What_Action(object);\n\n\tif (action == ACTION_SELF) {\n\t\tint index;\n\t\tif (Class->Is_Factory() && PlayerPtr == House && *House->Factory_Counter(Class->ToBuild) > 1) {\n\t\t\tswitch (Class->ToBuild) {\n\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\tif (*this == STRUCT_KENNEL) {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && *bldg == STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\taction = ACTION_TOGGLE_PRIMARY;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && bldg->Class->ToBuild == RTTI_INFANTRYTYPE && *bldg != STRUCT_KENNEL) {\n\t\t\t\t\t\t\t\taction = ACTION_TOGGLE_PRIMARY;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\tif (*this == STRUCT_AIRSTRIP) {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && *bldg == STRUCT_AIRSTRIP) {\n\t\t\t\t\t\t\t\taction = ACTION_TOGGLE_PRIMARY;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass *bldg = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (bldg != this && bldg->Owner() == Owner() && bldg->Class->ToBuild == RTTI_AIRCRAFTTYPE && *bldg != STRUCT_AIRSTRIP) {\n\t\t\t\t\t\t\t\taction = ACTION_TOGGLE_PRIMARY;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tcase RTTI_UNIT:\n\t\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\taction = ACTION_TOGGLE_PRIMARY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_NONE:\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t} else {\n\t\t\taction = ACTION_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't allow targeting of SAM sites, even if the CTRL key\n\t**\tis held down. Also don't allow targeting if the object is too\n\t**\tfar away.\n\t*/\n\tif (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN || !In_Range(object, 0))) {\n\t\taction = ACTION_NONE;\n\t}\n\n\tif (action == ACTION_MOVE) {\n\t\taction = ACTION_NONE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::What_Action -- Determines what action will occur.                            *\n *                                                                                             *\n *    This routine examines the cell specified and returns with the action that will be        *\n *    performed if that cell were clicked upon while the building is selected.                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the ActionType that indicates what should occur if the mouse is clicked    *\n *          on this cell.                                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType BuildingClass::What_Action(CELL cell) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = TechnoClass::What_Action(cell);\n\n\tif (action == ACTION_MOVE && (*this != STRUCT_CONST || !Is_MCV_Deploy())) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tDon't allow targeting of SAM sites, even if the CTRL key\n\t**\tis held down.\n\t*/\n\tif (action == ACTION_ATTACK && Class->PrimaryWeapon != NULL && !Class->PrimaryWeapon->Bullet->IsAntiGround) {\n//\tif (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN)) {\n\t\taction = ACTION_NONE;\n\t}\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Begin_Mode -- Begins an animation mode for the building.                     *\n *                                                                                             *\n *    This routine will start the building animating. This animation will loop indefinitely    *\n *    until explicitly stopped.                                                                *\n *                                                                                             *\n * INPUT:   bstate   -- The animation state to initiate.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The building graphic state will reflect the first stage of this animation the   *\n *             very next time it is rendered.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   07/02/1995 JLB : Uses normalize animation rate where applicable.                          *\n *=============================================================================================*/\nvoid BuildingClass::Begin_Mode(BStateType bstate)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tQueueBState = bstate;\n\tif (BState == BSTATE_NONE || bstate == BSTATE_CONSTRUCTION || ScenarioInit) {\n\t\tBState = bstate;\n\t\tQueueBState = BSTATE_NONE;\n\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\n\t\tint rate = ctrl->Rate;\n\t\tif (Class->IsRegulated && bstate != BSTATE_CONSTRUCTION) {\n\t\t\trate = Options.Normalize_Delay(rate);\n\t\t}\n\t\tSet_Rate(rate);\n\t\tSet_Stage(ctrl->Start);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Center_Coord -- Fetches the center coordinate for the building.              *\n *                                                                                             *\n *    This routine is used to set the center coordinate for this building.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate for the center location for the building.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Center_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(Coord, CenterOffset[Class->Size]));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                  *\n *                                                                                             *\n *    This routine will return the coordinate to use when an object wishes to dock with this   *\n *    building. Normally the docking coordinate would be the center of the building.           *\n *    Exceptions to this would be the airfield and helipad. Their docking coordinates are      *\n *    offset to match the building artwork.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to head to when trying to dock with this building.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Docking_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_HELIPAD) {\n\t\treturn(Coord_Add(Coord, XYP_COORD(24, 18)));\n\t}\n\tif (*this == STRUCT_AIRSTRIP) {\n\t\treturn(Coord_Add(Coord, XYP_COORD(ICON_PIXEL_W + ICON_PIXEL_W/2, 28)));\n\t}\n\treturn(TechnoClass::Docking_Coord());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Fire -- Determines if this building can fire.                            *\n *                                                                                             *\n *    Use this routine to see if the building can fire its weapon.                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that firing upon is desired.                                *\n *                                                                                             *\n *          which    -- Which weapon to use when firing. 0=primary, 1=secondary.               *\n *                                                                                             *\n * OUTPUT:  Returns with the fire possibility code. If firing is allowed, then FIRE_OK is      *\n *          returned. Other cases will result in appropriate fire code value that indicates    *\n *          why firing is not allowed.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFireErrorType BuildingClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tFireErrorType canfire = TechnoClass::Can_Fire(target, which);\n\n\tif (canfire == FIRE_OK) {\n\n\t\t/*\n\t\t**\tDouble check to make sure that the facing is roughly toward\n\t\t**\tthe target. If the difference is too great, then firing is\n\t\t**\ttemporarily postponed.\n\t\t*/\n\t\tif (Class->IsTurretEquipped) {\n\t\t\tint diff = PrimaryFacing.Difference(Direction(TarCom));\n\t\t\tdiff = abs(diff);\n\t\t\tif (ABS(diff) > (*this == STRUCT_SAM ? 64 : 8)) {\n//\t\t\tif (ABS(diff) > 8) {\n\t\t\t\treturn(FIRE_FACING);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the turret is rotating then firing must be delayed.\n\t\t\t*/\n//\t\t\tif (PrimaryFacing.Is_Rotating()) {\n//\t\t\t\treturn(FIRE_ROTATING);\n//\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCertain buildings cannot fire if there is insufficient power.\n\t\t*/\n\t\tif (Class->IsPowered && House->Power_Fraction() < 1) {\n\t\t\treturn(FIRE_BUSY);\n\t\t}\n\n\t\t/*\n\t\t** If an obelisk can fire, check the state of charge.\n\t\t*/\n\t\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && !IsCharged) {\n\t\t\treturn(FIRE_BUSY);\n\t\t}\n\t}\n\treturn(canfire);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Toggle_Primary -- Toggles the primary factory state.                         *\n *                                                                                             *\n *    This routine will change the primary factory state of this building. The primary         *\n *    factory is the one that units will be produced from (by default).                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Is this building NOW the primary factory?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Toggle_Primary(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (IsLeader) {\n\t\tIsLeader = false;\n\t} else {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\tif (!building->IsInLimbo && building->Owner() == Owner() && building->Class->ToBuild == Class->ToBuild) {\n\t\t\t\tif (Class->ToBuild == RTTI_INFANTRYTYPE) {\n\t\t\t\t\tif (*building == STRUCT_KENNEL && *this == STRUCT_KENNEL) {\n\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (*building != STRUCT_KENNEL && *this != STRUCT_KENNEL) {\n\t\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (Class->ToBuild == RTTI_AIRCRAFTTYPE) {\n\t\t\t\t\tif (*building == STRUCT_AIRSTRIP && *this == STRUCT_AIRSTRIP) {\n\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (*building != STRUCT_AIRSTRIP && *this != STRUCT_AIRSTRIP) {\n\t\t\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbuilding->IsLeader = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tIsLeader = true;\n\t\t//\n\t\t// MBL 04.20.2020 - Update so that each player in multiplayer will properly hear this when it applies to them\n\t\t//\n\t\t// if ((HouseClass *)House == PlayerPtr) {\n\t\t// \tSpeak(VOX_PRIMARY_SELECTED);\n\t\t// }\n\t\tif ((HouseClass *)House->IsHuman) {\n\t\t\tSpeak(VOX_PRIMARY_SELECTED, House);\n\t\t}\n\t}\n\tMark(MARK_CHANGE);\n\treturn(IsLeader);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Captured -- Captures the building.                                           *\n *                                                                                             *\n *    This routine will change the owner of the building. It handles updating any related      *\n *    game systems as a result. Factories are the most prone to have great game related        *\n *    consequences when captured. This could also affect the sidebar and building ownership.   *\n *                                                                                             *\n * INPUT:   newowner -- Pointer to the house that is now the new owner.                        *\n *                                                                                             *\n * OUTPUT:  Was the capture attempt successful?                                                *\n *                                                                                             *\n * WARNINGS:   Capturing could fail if the house is already owned by the one specified or      *\n *             the building isn't allowed to be captured.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *   07/05/1995 JLB : Fixed production problem with capturing enemy buildings.                 *\n *=============================================================================================*/\nbool BuildingClass::Captured(HouseClass * newowner)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Can_Capture() && newowner != House) {\n#ifdef TOFIX\n\t\tswitch (Owner()) {\n\t\t\tcase HOUSE_GOOD:\n\t\t\t\tSpeak(VOX_GDI_CAPTURED);\n\t\t\t\tbreak;\n\n\t\t\tcase HOUSE_BAD:\n\t\t\t\tSpeak(VOX_NOD_CAPTURED);\n\t\t\t\tbreak;\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Maybe trigger an achivement. ST - 11/14/2019 1:53PM\n\t\t*/\n\t\tif (newowner->IsHuman) {\n\t\t\tTechnoTypeClass const *object_type = Techno_Type_Class();\n\t\t\tif (object_type) {\n\t\t\t\tif (newowner->ActLike != House->ActLike) {\n\t\t\t\t\tOn_Achievement_Event(newowner, \"OPPOSING_BUILDING_CAPTURED\", object_type->IniName);\n\t\t\t\t} else {\n\t\t\t\t\tOn_Achievement_Event(newowner, \"BUILDING_CAPTURED\", object_type->IniName);\n\t\t\t\t}\t\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Make sure the capturer isn't spying on his own building, and if\n\t\t** it was a radar facility, update the target house's RadarSpied field.\n\t\t*/\n\t\tif (SpiedBy & (1<<(newowner->Class->House)) ) {\n\t\t\tSpiedBy -= (1<<(newowner->Class->House));\n\t\t\tif (*this == STRUCT_RADAR) {\n\t\t\t\tUpdate_Radar_Spied();\n\t\t\t}\n\t\t}\n\n\t\tif (House == PlayerPtr) {\n\t\t\tMap.PowerClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\n\t\tif (*this == STRUCT_GAP) {\n\t\t\tRemove_Gap_Effect();\n\t\t\tIsJamming = false;\n\t\t\tArm = 0;\n\t\t}\n\n\t\t/*\n\t\t** Add this building to the list of buildings captured this game. For internet stats purposes.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tnewowner->CapturedBuildings->Increment_Unit_Total (Class->Type);\n\t\t}\n\n\t\tHouse->Adjust_Power(-Power_Output());\n\t\tLastStrength = 0;\n\t\tHouse->Adjust_Drain(-Class->Drain);\n\t\tint booty = House->Adjust_Capacity(-Class->Capacity, true);\n\n\t\t/*\n\t\t**\tIf there is something loaded, then it gets captured as well.\n\t\t*/\n\t\tTechnoClass * tech = Attached_Object();\n\t\tif (tech) tech->Captured(newowner);\n\n\t\t/*\n\t\t**\tIf something isn't technically attached, but is sitting on this\n\t\t**\tbuilding for another reason (e.g., helicopter on helipad), then it\n\t\t**\tgets captured as well.\n\t\t*/\n\t\ttech = Contact_With_Whom();\n\t\tif (tech) {\n\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && (::Distance(tech->Center_Coord(), Docking_Coord()) < 0x0040 ||\n\t\t\t\t(tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND)) ) {\n\t\t\t\ttech->Captured(newowner);\n\t\t\t} else {\n\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAbort any computer production in progress.\n\t\t*/\n\t\tif (Factory) {\n\t\t\tdelete (FactoryClass *)Factory;\n\t\t\tFactory = 0;\n\t\t}\n\n\t\t/*\n\t\t**\tDecrement the factory counter for the original owner.\n\t\t*/\n\t\tHouse->Active_Remove(this);\n\n\t\t/*\n\t\t**\tFlag that both owners now need to update their buildable lists.\n\t\t*/\n\t\tHouse->IsRecalcNeeded = true;\n\t\tnewowner->IsRecalcNeeded = true;\n\t\tHouseClass * oldowner = House;\n\t\tTARGET tocap = As_Target();\n\n\t\tIsCaptured = true;\n\t\tTechnoClass::Captured(newowner);\n\n\t\toldowner->ToCapture = tocap;\n\t\toldowner->Recalc_Center();\n\t\tHouse->Recalc_Center();\n\t\tif (House->ToCapture == As_Target()) {\n\t\t\tHouse->ToCapture = TARGET_NONE;\n\t\t}\n\n\t\tSmudgeType bib;\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tif (Class->Bib_And_Offset(bib, cell)) {\n\t\t\tSmudgeClass * smudge = new SmudgeClass(bib);\n\t\t\tif (smudge) {\n\t\t\t\tsmudge->Disown(cell);\n\t\t\t\tdelete smudge;\n\t\t\t}\n#ifdef FIXIT_CAPTURE_BIB\n\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), Class->IsBase ? House->Class->House : HOUSE_NONE);\n\t\t\t} else {\n\t\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), House->Class->House);\n\t\t\t}\n#else\n\t\t\tnew SmudgeClass(bib, Cell_Coord(cell), House->Class->House);\n#endif\n\t\t}\n\n\t\tHouse->Stole(Refund_Amount());\n\n\t\t/*\n\t\t**\tIncrement the factory count for the new owner.\n\t\t*/\n\t\tHouse->Active_Add(this);\n\n\t\tIsRepairing = false;\n\t\tGrand_Opening(true);\n\t\tHouse->Harvested(booty);\n\n\t\tMark(MARK_CHANGE);\n\n\t\t/*\n\t\t**\tPerform a look operation when captured if it was the player\n\t\t**\tthat performed the capture.\n\t\t*/\n\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER && House->IsHuman) {\n\t\t\tLook(false);\n\t\t} else {\n\t\t\tif (House == PlayerPtr) {\n\t\t\t\tLook(false);\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** If it was spied upon by the player who just captured it, clear the\n\t\t** spiedby flag for that house.\n\t\t*/\n\t\tif (SpiedBy & (1 << (newowner->Class->House))) {\n\t\t\tSpiedBy &= ~(1 << (newowner->Class->House));\n\t\t}\n\n\t\t/*\n\t\t** Update the new building's colors on the radar map.\n\t\t*/\n\t\tshort const * offset = Occupy_List();\n\t\twhile (*offset != REFRESH_EOL) {\n\t\t\tCELL cell = Coord_Cell(Coord) + *offset++;\n\t\t\tMap.Radar_Pixel(cell);\n\t\t}\n\n\t\tif (oldowner) {\n\t\t\toldowner->Check_Pertinent_Structures();\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                  *\n *                                                                                             *\n *    The coordinate value returned from this function should be used for sorting purposes.    *\n *    It has special offset adjustment applied so that vehicles don't overlap (as much).       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate value suitable to be used for sorting.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *   06/19/1995 JLB : Handles buildings that come with bibs built-in.                          *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Sort_Y(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_REPAIR) {\n\t\treturn(Coord);\n\t}\n\tif (*this == STRUCT_HELIPAD) {\n\t\treturn(Center_Coord());\n\t}\n\tif (*this == STRUCT_AIRSTRIP) {\n\t\treturn(Center_Coord());\n\t}\n\tif (*this == STRUCT_BARRACKS /*|| *this == STRUCT_POWER*/) {\n\t\treturn(Center_Coord());\n\t}\n\tif (*this == STRUCT_REFINERY) {\n\t\treturn(Center_Coord());\n\t}\n\n\t/*\n\t**\tMines need to bias their sort location such that they are typically drawn\n\t**\tbefore any objects that might overlap them.\n\t*/\n\tif (*this == STRUCT_AVMINE || *this == STRUCT_APMINE) {\n\t\treturn(Coord_Move(Center_Coord(), DIR_N, CELL_LEPTON_H));\n\t}\n\n\treturn(Coord_Add(Center_Coord(), XY_Coord(0, (Class->Height()*256)/3)));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.                 *\n *                                                                                             *\n *    This routine will determine if the building can be placed down at the location           *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine. This is usually the cell of the upper left corner    *\n *                   of the building if it were to be placed down.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the move legality value for placement at the location specified. This *\n *          will either be MOVE_OK or MOVE_NO.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType BuildingClass::Can_Enter_Cell(CELL cell, FacingType) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_CONST && IsDown) {\n\t\treturn(Map[cell].Is_Clear_To_Build(Class->Speed) ? MOVE_OK : MOVE_NO);\n\t}\n\n\tif (!Debug_Map && ScenarioInit == 0 && Session.Type == GAME_NORMAL && House->IsPlayerControl && !Map[cell].IsMapped) {\n\t\treturn(MOVE_NO);\n\t}\n\n\treturn(Class->Legal_Placement(cell) ? MOVE_OK : MOVE_NO);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?            *\n *                                                                                             *\n *    Determines if the player can sell this building. Selling is possible if the building     *\n *    is not currently in construction or deconstruction animation.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can the building be demolished at this time?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   07/01/1995 JLB : If there is no buildup data, then the building can't be sold.            *\n *   07/17/1995 JLB : Cannot sell a refinery that has a harvester attached.                    *\n *=============================================================================================*/\nbool BuildingClass::Can_Demolish(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsUnsellable) return(false);\n\n\tif (Class->Get_Buildup_Data() && BState != BSTATE_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION && Mission != MISSION_CONSTRUCTION) {\n\t\tif (*this == STRUCT_REFINERY && Is_Something_Attached()) return(false);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nbool BuildingClass::Can_Demolish_Unit(void) const\n{\n\treturn((*this == STRUCT_REPAIR || *this == STRUCT_AIRSTRIP) && In_Radio_Contact() && Distance(Contact_With_Whom()) < 0x0080);\n}\n\n\nbool BuildingClass::Can_Capture(void) const\n{\n\tbool can_capture = Class->IsCaptureable && Mission != MISSION_DECONSTRUCTION;\n\n\t// Only allow capturing of multiplayer-owned structures\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif (*this == STRUCT_V01) {\t\t// Check to fix exploit in specific map 'Tournament Ore Rift'\n\t\t\tcan_capture = false;\n\t\t}\n\t}\n\n\treturn(can_capture);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.                 *\n *                                                                                             *\n *    Buildings that can attack are given this mission. They will wait until a suitable target *\n *    comes within range and then launch into the attack mission. Buildings that have no       *\n *    weaponry will just sit in this routine forever.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before this routine will be called *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Guard(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this building has a weapon, then search for a target to attack. When\n\t**\ta target is found, switch into attack mode to deal with the threat.\n\t*/\n\tif (Is_Weapon_Equipped()) {\n\n\t\t/*\n\t\t**\tWeapon equipped buildings are ALWAYS ready to launch into another mission if\n\t\t**\tthey are sitting around in guard mode.\n\t\t*/\n\t\tIsReadyToCommence = true;\n\n\t\t/*\n\t\t**\tIf there is no target available, then search for one.\n\t\t*/\n\t\tif (!Target_Legal(TarCom)) {\n\t\t\tThreatType threat = THREAT_NORMAL;\n\t\t\tAssign_Target(Greatest_Threat(threat));\n\t\t}\n\n\t\t/*\n\t\t**\tThere is a valid target. Switch into attack mode right away.\n\t\t*/\n\t\tif (Target_Legal(TarCom)) {\n\t\t\tAssign_Mission(MISSION_ATTACK);\n\t\t\tCommence();\n\t\t\treturn(1);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tThis is the very simple state machine that basically does\n\t\t**\tnothing. This is the mode that non weapon equipped buildings\n\t\t**\tare normally in.\n\t\t*/\n\t\tenum {\n\t\t\tINITIAL_ENTRY,\n\t\t\tIDLE\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL_ENTRY:\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\tStatus = IDLE;\n\t\t\t\tbreak;\n\n\t\t\tcase IDLE:\n\t\t\t\t/*\n\t\t\t\t**\tSpecial case to break out of guard mode if this is a repair\n\t\t\t\t**\tfacility and there is a customer waiting at the grease pit.\n\t\t\t\t*/\n\t\t\t\tif (*this == STRUCT_REPAIR &&\n\t\t\t\t\tIn_Radio_Contact() &&\n\t\t\t\t\tContact_With_Whom()->Is_Techno() &&\n\t\t\t\t\t((TechnoClass *)Contact_With_Whom())->Mission == MISSION_ENTER &&\n\t\t\t\t\tDistance(Contact_With_Whom()) < 0x0040 &&\n\t\t\t\t\tTransmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\n\t\t\t\t\tAssign_Mission(MISSION_REPAIR);\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (*this == STRUCT_REPAIR) {\n\t\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t\t} else {\n\t\t\treturn(MissionControl[Mission].Normal_Delay() * 3 + Random_Pick(0, 2));\n\t\t}\n\t}\n\treturn(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Construction -- Handles mission construction.                        *\n *                                                                                             *\n *    This routine will handle mission construction. When this mission is complete, the        *\n *    building will begin normal operation.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Construction(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\n\t\tDURING\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\t\tTransmit_Message(RADIO_BUILDING);\n\t\t\tif (House->IsPlayerControl) {\n\t\t\t\tSound_Effect(VOC_CONSTRUCTION, Coord);\n\t\t\t}\n\t\t\tStatus = DURING;\n\t\t\tbreak;\n\n\t\tcase DURING:\n\t\t\tif (IsReadyToCommence) {\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen construction is complete, then transmit this\n\t\t\t\t**\tto the construction yard so that it can stop its\n\t\t\t\t**\tconstruction animation.\n\t\t\t\t*/\n\t\t\t\tTransmit_Message(RADIO_COMPLETE);\t\t// \"I'm finished.\"\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\t\t// \"You're free.\"\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\tGrand_Opening();\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tPrimaryFacing = Class->StartFace;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                   *\n *                                                                                             *\n *    This state machine is only used when the building is deconstructing as a result of       *\n *    selling.  When this mission is finished, the building will no longer exist.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   08/13/1995 JLB : Enable selling of units on a repair bay.                                 *\n *   08/20/1995 JLB : Scatters infantry from scattered starting points.                        *\n *=============================================================================================*/\nint BuildingClass::Mission_Deconstruction(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tAlways force repair off.\n\t*/\n\tRepair(0);\n\n\tenum {\n\t\tINITIAL,\n\t\tHOLDING,\n\t\tDURING\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\n\t\t\t/*\n\t\t\t**\tSpecial check for the repair bay which has the ability to sell\n\t\t\t**\twhatever is on it. If there is something on the repair bay, then\n\t\t\t**\tit will be sold. If there is nothing on the repair bay, then\n\t\t\t**\tthe repair bay itself will be sold.\n\t\t\t*/\n\t\t\tif (Can_Demolish_Unit() && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\tTechnoClass * tech = Contact_With_Whom();\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_UNIT_SOLD);\n\t\t\t\ttech->Sell_Back(1);\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\treturn(1);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Selling off a shipyard or sub pen may cause attached ships\n\t\t\t** who are repairing themselves to discontinue repairs.\n\t\t\t*/\n\t\t\tif (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {\n\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\t\t\t\tif (obj->IsSelfRepairing) {\n\t\t\t\t\t\t\tif (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {\n\t\t\t\t\t\t\t\tobj->IsSelfRepairing = false;\n\t\t\t\t\t\t\t\tobj->IsToSelfRepair = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tIsReadyToCommence = false;\n\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\tStatus = HOLDING;\n\t\t\tbreak;\n\n\t\tcase HOLDING:\n\t\t\tif (!IsTethered) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe crew will evacuate from the building. The number of crew\n\t\t\t\t**\tmembers leaving is equal to the unrecovered cost of the building\n\t\t\t\t**\tdivided by 100 (the typical cost of a minigunner infantryman).\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(ArchiveTarget) || !Is_MCV_Deploy() || *this != STRUCT_CONST) {\n\t\t\t\t\tint count = How_Many_Survivors();\n\t\t\t\t\tbool engine = false;\n\n\t\t\t\t\twhile (count) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tEnsure that the player only gets ONE engineer and not from a captured\n\t\t\t\t\t\t**\tconstruction yard.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tInfantryType typ = Crew_Type();\n\t\t\t\t\t\twhile (typ == INFANTRY_RENOVATOR && engine) {\n\t\t\t\t\t\t\ttyp = Crew_Type();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typ == INFANTRY_RENOVATOR) engine = true;\n\n\t\t\t\t\t\tInfantryClass * infantry = 0;\n\t\t\t\t\t\tif (typ != INFANTRY_NONE) infantry = new InfantryClass(typ, House->Class->House);\n\t\t\t\t\t\tif (infantry != NULL) {\n\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\tCOORDINATE coord = Coord_Add(Center_Coord(), XYP_COORD(0, -12));\n\t\t\t\t\t\t\tcoord = Map[coord].Closest_Free_Spot(coord, false);\n\n\t\t\t\t\t\t\tif (infantry->Unlimbo(coord, DIR_N)) {\n\t\t\t\t\t\t\t\tinfantry->IsZoneCheat = infantry->Can_Enter_Cell(Coord_Cell(infantry->Center_Coord())) != MOVE_OK;\n\t\t\t\t\t\t\t\tif (infantry->Class->IsNominal) infantry->IsTechnician = true;\n\t\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t\t\tinfantry->Scatter(0, true);\n\t\t\t\t\t\t\t\tScenarioInit++;\n\t\t\t\t\t\t\t\tinfantry->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tScenarioInit--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// MBL 07.10.2020 - In 1v1, sometimes both players will hear this SFX, or neither player will hear it\n\t\t\t\t// Making it so all players hear it positionally in the map; Per thread discussion in https://jaas.ea.com/browse/TDRA-7245\n\t\t\t\t//\n\t\t\t\t#if 0\n\t\t\t\t\tif (House->IsPlayerControl) {\n\t\t\t\t\t\tSound_Effect(VOC_CASHTURN, Coord);\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tSound_Effect(VOC_CASHTURN, Coord);\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\t/*\n\t\t\t\t**\tDestroy all attached objects. ST - 4/24/2020 9:38PM\n\t\t\t\t*/\n\t\t\t\twhile (Attached_Object()) {\n\t\t\t\t\tFootClass * obj = Detach_Object();\n\n\t\t\t\t\tDetach_All(true);\n\t\t\t\t\tdelete obj;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\tStatus = DURING;\n\t\t\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tIsSurvivorless = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\tbreak;\n\n\t\tcase DURING:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tHouse->IsRecalcNeeded = true;\n\n  \t\t\t\t// MBL 05.06.2020 - \"Structure Sold\" is being heard when selecting/moving a redepolyable Con Yard to turn back into an MCV (RA only), so moving below\n\t\t\t\t#if 0\n\t\t\t\t// MBL 04.06.2020: Fix being heard by wrong player\n\t\t\t\t// if (IsOwnedByPlayer) Speak(VOX_STRUCTURE_SOLD);\n\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\tif ((HouseClass *)House == PlayerPtr) {\n\t\t\t\t\t\tSpeak(VOX_STRUCTURE_SOLD);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t\tbool mcv_redeployed = false;\n\n\t\t\t\t/*\n\t\t\t\t**\tConstruction yards that deconstruct, really just revert back\n\t\t\t\t**\tto an MCV.\n\t\t\t\t*/\n\t\t\t\tif (Target_Legal(ArchiveTarget) && *this == STRUCT_CONST && House->IsHuman && Strength > 0) {\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tUnitClass * unit = new UnitClass(UNIT_MCV, House->Class->House);\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\tif (unit != NULL) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUnlimbo the MCV onto the map. The MCV should start in the same\n\t\t\t\t\t\t**\thealth condition that the construction yard was in.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfixed ratio = Health_Ratio();\n\t\t\t\t\t\tint money = Refund_Amount();\n\t\t\t\t\t\tTARGET arch = ArchiveTarget;\n\t\t\t\t\t\tCOORDINATE place = Coord_Snap(Adjacent_Cell(Coord, DIR_SE));\n\n\t\t\t\t\t\tdelete this;\n\n\t\t\t\t\t\tif (unit->Unlimbo(place, DIR_SW)) {\n\t\t\t\t\t\t\tunit->Strength = (int)unit->Class_Of().MaxStrength * ratio;\t\t\t// Cast to (int). ST - 5/8/2019\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tLift the move destination from the building and assign\n\t\t\t\t\t\t\t**\tit to the unit.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Target_Legal(arch)) {\n\t\t\t\t\t\t\t\tunit->Assign_Destination(arch);\n\t\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmcv_redeployed = true;\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf, for some strange reason, the MCV could not be placed on the\n\t\t\t\t\t\t\t**\tmap, then give the player some money to compensate.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tHouse->Refund_Money(money);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tHouse->Refund_Money(Refund_Amount());\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Selling off a gap generator will cause the cells it affects\n\t\t\t\t\t** to stop being jammed.\n\t\t\t\t\t*/\n\t\t\t\t\tif (*this == STRUCT_GAP) {\n\t\t\t\t\t\tRemove_Gap_Effect();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tA sold building still counts as a kill, but it just isn't directly\n\t\t\t\t\t**\tattributed to the enemy.\n\t\t\t\t\t*/\n\t\t\t\t\tWhoLastHurtMe = HOUSE_NONE;\n\t\t\t\t\tRecord_The_Kill(NULL);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe player gets part of the money back for the sell.\n\t\t\t\t\t*/\n\t\t\t\t\tHouse->Refund_Money(Refund_Amount());\n\t\t\t\t\tHouse->Stole(-Refund_Amount());\n\t\t\t\t\tLimbo();\n\n\t\t\t\t\tif (House) {\n\t\t\t\t\t\tHouse->Check_Pertinent_Structures();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFinally, delete the building from the game.\n\t\t\t\t\t*/\n\t\t\t\t\tdelete this;\n\t\t\t\t}\n\n\t\t\t\t// MBL 05.06.2020 - \"Structure Sold\" was being heard when selecting/moving a redepolyable Con Yard to turn back into an MCV (RA only) above, so moved here\n\t\t\t\t#if 1\n\t\t\t\tif (!mcv_redeployed) \n\t\t\t\t{\n\t\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\t\tif ((HouseClass *)House == PlayerPtr) {\n\t\t\t\t\t\t\tSpeak(VOX_STRUCTURE_SOLD);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Attack -- Handles attack mission for building.                       *\n *                                                                                             *\n *    Buildings that can attack are processed by this attack mission state machine.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   02/22/1996 JLB : SAM doesn't lower back into ground.                                      *\n *=============================================================================================*/\nint BuildingClass::Mission_Attack(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_SAM) {\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t**\tThis is the target tracking state of the launcher. It will rotate\n\t\t\t**\tto face the current TarCom of the launcher.\n\t\t\t*/\n\t\t\tcase SAM_READY:\n\t\t\t\tif ((Class->IsPowered && House->Power_Fraction() < 1) || IsJammed) {\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tif (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\tCommence();\n\t\t\t\t\treturn(1);\n\t\t\t\t} else {\n\t\t\t\t\tif (!PrimaryFacing.Is_Rotating()) {\n\t\t\t\t\t\tDirType facing = Direction(TarCom);\n\t\t\t\t\t\tif (PrimaryFacing.Difference(facing)) {\n\t\t\t\t\t\t\tPrimaryFacing.Set_Desired(facing);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tStatus = SAM_FIRING;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t**\tThe launcher is in the process of firing.\n\t\t\t*/\n\t\t\tcase SAM_FIRING:\n\t\t\t\tif (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {\n\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t} else {\n\t\t\t\t\tFireErrorType error = Can_Fire(TarCom, 0);\n\t\t\t\t\tif (error == FIRE_ILLEGAL || error == FIRE_CANT || error == FIRE_RANGE) {\n\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (error == FIRE_FACING) {\n\t\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (error == FIRE_OK) {\n\t\t\t\t\t\t\t\tFire_At(TarCom, 0);\n\t\t\t\t\t\t\t\tFire_At(TarCom, 1);\n\t\t\t\t\t\t\t\tStatus = SAM_READY;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));\n\n\t}\n\n\tif (!Target_Legal(TarCom)) {\n\t\tAssign_Target(TARGET_NONE);\n\t\tAssign_Mission(MISSION_GUARD);\n\t\tCommence();\n\t\treturn(1);\n\t}\n\n\tint primary = What_Weapon_Should_I_Use(TarCom);\n\tIsReadyToCommence = true;\n\tswitch (Can_Fire(TarCom, primary)) {\n\t\tcase FIRE_ILLEGAL:\n\t\tcase FIRE_CANT:\n\t\tcase FIRE_RANGE:\n\t\tcase FIRE_AMMO:\n\t\t\tAssign_Target(TARGET_NONE);\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\tCommence();\n\t\t\tbreak;\n\n\t\tcase FIRE_FACING:\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\treturn(2);\n\n\t\tcase FIRE_REARM:\n\t\t\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\t\t\treturn(Arm);\n\n\t\tcase FIRE_BUSY:\n\t\t\treturn(1);\n\n\t\tcase FIRE_CLOAKED:\n\t\t\tDo_Uncloak();\n\t\t\tbreak;\n\n\t\tcase FIRE_OK:\n\t\t\tFire_At(TarCom, primary);\n\t\t\treturn(1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tPrimaryFacing.Set_Desired(Direction(TarCom));\n\treturn(1);\n//\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                    *\n *                                                                                             *\n *    This state machine handles the refinery when it unloads the harvester.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Harvest(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tenum {\n\t\tINITIAL,\t\t\t\t\t// Dock the Tiberium cannister.\n\t\tWAIT_FOR_DOCK,\t\t\t// Waiting for docking to complete.\n\t\tMIDDLE,\t\t\t\t\t// Offload \"bails\" of tiberium.\n\t\tWAIT_FOR_UNDOCK\t\t// Waiting for undocking to complete.\n\t};\n\tswitch (Status) {\n\t\tcase INITIAL:\n\t\t\tStatus = WAIT_FOR_DOCK;\n\t\t\tbreak;\n\n\t\tcase WAIT_FOR_DOCK:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tStatus = MIDDLE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MIDDLE:\n\t\t\tif (IsReadyToCommence) {\n\t\t\t\tIsReadyToCommence = false;\n\n\t\t\t\t/*\n\t\t\t\t**\tForce any bib squatters to scatter.\n\t\t\t\t*/\n\t\t\t\tMap[Adjacent_Cell(Coord_Cell(Center_Coord()), DIR_S)].Incoming(0, true, true);\n\n\t\t\t\tFootClass * techno = Attached_Object();\n\t\t\t\tif (techno) {\n\t\t\t\t\tint bail = techno->Offload_Tiberium_Bail();\n\n\t\t\t\t\tif (bail) {\n\t\t\t\t\t\tHouse->Harvested(bail);\n\t\t\t\t\t\tif (techno->Tiberium_Load() > 0) {\n\t\t\t\t\t\t\treturn(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tStatus = WAIT_FOR_UNDOCK;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAIT_FOR_UNDOCK:\n\t\t\tif (IsReadyToCommence) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetach harvester and go back into idle state.\n\t\t\t\t*/\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Repair -- Handles the repair (active) state for building.            *\n *                                                                                             *\n *    This state machine is used when the building is active in some sort of repair or         *\n *    construction mode. The construction yard will animate. The repair facility will repair   *\n *    anything that it docked on it.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   06/25/1995 JLB : Handles repair facility                                                  *\n *   07/29/1995 JLB : Repair rate is controlled by power rating.                               *\n *=============================================================================================*/\nint BuildingClass::Mission_Repair(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_CONST) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\tStatus = DURING;\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(1);\n\t}\n\n\tif (*this == STRUCT_REPAIR) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tIDLE,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\t{\n\t\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\tint distance = 0x10;\n\t\t\t\t\tTechnoClass *tech = Contact_With_Whom();\n\n\t\t\t\t\t/*\n\t\t\t\t\t** BG: If the unit to repair is an aircraft, and the aircraft is\n\t\t\t\t\t** fixed-wing, and it's landed, be much more liberal with the\n\t\t\t\t\t** distance check.  Fixed-wing aircraft are very inaccurate with\n\t\t\t\t\t** their landings.\n\t\t\t\t\t*/\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\t\t\tif ( ((AircraftClass *)tech)->Class->IsFixedWing &&\n\t\t\t\t\t\t\t((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\t\t\tdistance = 0x80;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Distance(Contact_With_Whom()) < distance) {\n\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\treturn(TICKS_PER_SECOND/4);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase IDLE:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tTechnoClass * radio = Contact_With_Whom();\n\n\t\t\t\t\tif ( ((radio->Health_Ratio() < Rule.ConditionGreen) ||\n\t\t\t\t\t\t   (radio->What_Am_I() == RTTI_UNIT && *(UnitClass *)radio == UNIT_MINELAYER))\n\t\t\t\t\t\t\t&& Transmit_Message(RADIO_REPAIR) == RADIO_ROGER) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the object over the repair bay is marked as useless, then\n\t\t\t\t\t\t**\tsell it back to get some money.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (radio->IsUseless) {\n\t\t\t\t\t\t\tif (!radio->House->IsHuman) {\n\t\t\t\t\t\t\t\tradio->Sell_Back(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tStatus = INITIAL;\n\t\t\t\t\t\t\tIsReadyToCommence = true;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// MBL 04.27.2020: Legacy VOX_REPAIRING seems to be never called in TD, but only in RA.\n\t\t\t\t\t\t\t// It is currently supported as a client GUI event when standard repairing begins, with \"REPAIR1\" on both TD and RA\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// This repairing is in reference to the repair bay\n\t\t\t\t\t\t\t// There is a newer bug (https://jaas.ea.com/browse/TDRA-6224) reporting that it is heard in multiplayer by \n\t\t\t\t\t\t\t// other players, from this call, so modifiying the original call here:\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// if (IsOwnedByPlayer) Speak(VOX_REPAIRING);\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_REPAIRING, House);\n\n\t\t\t\t\t\t\tStatus = DURING;\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n//\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n///*BG*/\t\t\t\t\tif(radio->Health_Ratio() >= Rule.ConditionGreen) {\n//\t\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n//\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (!In_Radio_Contact()) {\n\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck to see if the repair light blink has completed and the attached\n\t\t\t\t**\tunit is not doing something else. If these conditions are favorable,\n\t\t\t\t**\tthe repair can proceed another step.\n\t\t\t\t*/\n\t\t\t\tif (IsReadyToCommence && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {\n\t\t\t\t\tIsReadyToCommence = false;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tTell the attached unit to repair one step. It will respond with how\n\t\t\t\t\t**\tit fared.\n\t\t\t\t\t*/\n\t\t\t\t\tswitch (Transmit_Message(RADIO_REPAIR)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step proceeded smoothly. Proceed normally with the\n\t\t\t\t\t\t**\trepair process.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_ROGER:\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair operation was aborted because of some reason. Presume\n\t\t\t\t\t\t**\tthat the reason is because of low cash.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_CANT:\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_NO_CASH);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step resulted in a completely repaired unit.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_ALL_DONE:\n\n\t\t\t\t\t\t\t// MBL 04.27.2020: Make only audible to the correct player\n\t\t\t\t\t\t\t// if (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED);\n\t\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED, House);\n\n//\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThe repair step could not be completed because this unit is already\n\t\t\t\t\t\t**\tat full strength.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RADIO_NEGATIVE:\n\t\t\t\t\t\tdefault:\n//\t\t\t\t\t\t\tTransmit_Message(RADIO_RUN_AWAY);\n\t\t\t\t\t\t\tBegin_Mode(BSTATE_IDLE);\n\t\t\t\t\t\t\tStatus = IDLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].Normal_Delay());\n\t}\n\n\tif (*this == STRUCT_HELIPAD || *this == STRUCT_AIRSTRIP) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDURING\n\t\t};\n\t\tswitch (Status) {\n\t\t\tcase INITIAL:\n\t\t\t\tif (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Transmit_Message(RADIO_PREPARED) == RADIO_NEGATIVE) {\n\t\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\n\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_SLEEP);\n\t\t\t\t\tStatus = DURING;\n\t\t\t\t\treturn(1);\n\t\t\t\t}\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tbreak;\n\n\t\t\tcase DURING:\n\t\t\t\tif (IsReadyToCommence) {\n\t\t\t\t\tif (!In_Radio_Contact() || Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_NEGATIVE) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Transmit_Message(RADIO_PREPARED) == RADIO_ROGER) {\n\t\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Transmit_Message(RADIO_RELOAD) != RADIO_ROGER) {\n\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tContact_With_Whom()->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\treturn(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfixed pfrac = Saturate(House->Power_Fraction(), 1);\n\t\t\t\t\t\tif (pfrac < fixed::_1_2) pfrac = fixed::_1_2;\n\t\t\t\t\t\tint time = Inverse(pfrac) * Rule.ReloadRate * TICKS_PER_MINUTE;\n//\t\t\t\t\t\tint time = Bound((int)(TICKS_PER_SECOND * Saturate(House->Power_Fraction(), 1)), 0, TICKS_PER_SECOND);\n//\t\t\t\t\t\ttime = (TICKS_PER_SECOND*3) - time;\n\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\treturn(time);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(3);\n\t}\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Missile -- State machine for nuclear missile launch.                 *\n *                                                                                             *\n *    This handles the Temple of Nod launching its nuclear missile.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of frames to delay before calling this routine again.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nint BuildingClass::Mission_Missile(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_ADVANCED_TECH) {\n\t\tenum {\n\t\t\tDOOR_OPENING,\n\t\t\tLAUNCH_UP,\n\t\t\tSATELLITE_DEPLOY,\n\t\t\tDONE_LAUNCH\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t** The initial case is responsible for starting the door\n\t\t\t** opening on the building, the missile rising, and smoke broiling.\n\t\t\t*/\n\t\t\tcase DOOR_OPENING:\n\t\t\t\t{\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tCOORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\tAnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);\n\t\t\t\t\tif (sput) {\n\t\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\t\tAnimToTrack = sput->As_Target();\n\t\t\t\t\t}\n#else\n\t\t\t\t\tIsReadyToCommence = false;\n\t\t\t\t\tCOORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\tAnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);\n\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\tAnimToTrack = sput->As_Target();\n\t\t\t\t\treturn(1);\n#endif\n\t\t\t\t}\n\n\t\t\t/*\n\t\t\t** Once the smoke has been going for a little while this\n\t\t\t** actually handles launching the missile into the air.\n\t\t\t*/\n\t\t\tcase LAUNCH_UP:\n\t\t\t\t{\n\t\t\t\t\tAnimClass * sput = As_Animation(AnimToTrack);\n\t\t\t\t\tif (sput) {\n\t\t\t\t\t\tif (sput->Fetch_Stage() >= 19) {\n\t\t\t\t\t\t\tCELL center = Coord_Cell(Center_Coord());\n\t\t\t\t\t\t\tCELL cell = XY_Cell( Cell_X(center), 1);\n\t\t\t\t\t\t\tTARGET targ = ::As_Target(cell);\n\n\t\t\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_GPS_SATELLITE, targ, this, 200, WARHEAD_FIRE, MPH_ROCKET);\n\t\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\t\tCOORDINATE launch = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);\n\t\t\t\t\t\t\t\tif (!bullet->Unlimbo(launch, DIR_N)) {\n\t\t\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\t\t\tbullet = NULL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\t\t}\n\t}\n\n\tif (*this == STRUCT_MSLO) {\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tDOOR_OPENING,\n\t\t\tLAUNCH_UP,\n\t\t\tLAUNCH_DOWN,\n\t\t\tDONE_LAUNCH\n\t\t};\n\n\t\tswitch (Status) {\n\n\t\t\t/*\n\t\t\t** The initial case is responsible for starting the door\n\t\t\t** opening on the building.\n\t\t\t*/\n\t\t\tcase INITIAL:\n\t\t\t\tIsReadyToCommence = false;\n\t\t\t\tBegin_Mode(BSTATE_ACTIVE);\t// open the door\n\t\t\t\tStatus = DOOR_OPENING;\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** This polls for the case when the door is actually open and\n\t\t\t** then kicks off the missile smoke.\n\t\t\t*/\n\t\t\tcase DOOR_OPENING:\n\t\t\t\tif (IsReadyToCommence) {\n\t\t\t\t\tBegin_Mode(BSTATE_AUX1);\t// hold the door open\n\t\t\t\t\tStatus = LAUNCH_UP;\n\t\t\t\t\treturn(14);\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** Once the smoke has been going for a little while this\n\t\t\t** actually handles launching the missile into the air.\n\t\t\t*/\n\t\t\tcase LAUNCH_UP:\n\t\t\t\t{\n\t\t\t\t\tCELL center = Coord_Cell(Center_Coord());\n\t\t\t\t\tCELL cell = XY_Cell( Cell_X(center), 1);\n\t\t\t\t\tTARGET targ = ::As_Target(cell);\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_UP, targ, this, 200, WARHEAD_HE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tCOORDINATE launch = Coord_Move(Center_Coord(), (DirType)28, 0xA0);\n\t\t\t\t\t\tif (!bullet->Unlimbo(launch, DIR_N)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\tbullet = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tSpeak(VOX_ABOMB_LAUNCH);\n\t\t\t\t\t\tStatus = LAUNCH_DOWN;\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t\t\t\t** tech level 15 or so.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (House->Control.TechLevel <= 10) {\n\t\t\t\t\t\t\treturn(6);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\t\tint celly = Cell_Y(House->NukeDest);\n\t\t\t\t\t\t\tcelly -= 64;\n\t\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));\n\t\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(8 * TICKS_PER_SECOND);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(1);\n\n\t\t\t/*\n\t\t\t** Once the missile is in the air, this handles waiting for\n\t\t\t** the missile to be off the screen and then launching one down\n\t\t\t** over the target.\n\t\t\t*/\n\t\t\tcase LAUNCH_DOWN:\n\t\t\t\t{\n\t\t\t\t\tBegin_Mode(BSTATE_AUX2);\t// start the door closing\n\n#ifdef OBSOLETE\n\t\t\t\t\t/*\n\t\t\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t\t\t** tech level 15 or so.\n\t\t\t\t\t*/\n\t\t\t\t\tif (House->Control.TechLevel <= 10) {\n\t\t\t\t\t\tStatus = DONE_LAUNCH;\n\t\t\t\t\t\treturn(6);\n\t\t\t\t\t}\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tint celly = Cell_Y(House->NukeDest);\n\t\t\t\t\t\tcelly -= 15;\n\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));\n\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (bullet) {\n#endif\n\t\t\t\t\t\tStatus = DONE_LAUNCH;\n\t\t\t\t\t\treturn(6);\n\t\t\t\t\t}\n#ifdef OBSOLETE\n\t\t\t\t}\n\t\t\t\treturn(1);\n#endif\n\n\t\t\t/*\n\t\t\t** Once the missile is done launching this handles allowing\n\t\t\t** the building to sit there with its door closed.\n\t\t\t*/\n\t\t\tcase DONE_LAUNCH:\n\t\t\t\tBegin_Mode(BSTATE_IDLE);\t// keep the door closed.\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\treturn(60);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Revealed -- Reveals the building to the specified house.                     *\n *                                                                                             *\n *    This routine will reveal the building to the specified house. It will handle updating    *\n *    the sidebar for player owned buildings. A player owned building that hasn't been         *\n *    revealed, is in a state of pseudo-limbo. It cannot be used for any of its special        *\n *    abilities even though it exists on the map for all other purposes.                       *\n *                                                                                             *\n * INPUT:   house -- The house that this building is being revealed to.                        *\n *                                                                                             *\n * OUTPUT:  Was this building revealed by this procedure?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Revealed(HouseClass * house)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TechnoClass::Revealed(house)) {\n\n\t\tif (!ScenarioInit) {\n\t\t\tHouse->JustBuiltStructure = Class->Type;\n\t\t\tHouse->IsBuiltSomething = true;\n\t\t}\n\t\tHouse->IsRecalcNeeded = true;\n\n\t\t/*\n\t\t**\tPerform any grand opening here so that in the scenarios where a player\n\t\t**\towned house is not yet revealed, it won't be reflected in the sidebar\n\t\t**\tselection icons.\n\t\t*/\n\t\tif (!In_Radio_Contact() && House->IsHuman && Mission != MISSION_CONSTRUCTION) {\n\t\t\tGrand_Opening();\n\t\t} else {\n\t\t\tif (!In_Radio_Contact() && !House->IsHuman && house == House && Mission != MISSION_CONSTRUCTION) {\n\t\t\t\tGrand_Opening();\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                    *\n *                                                                                             *\n *    This routine is called when the exact mode of the building isn't known. By examining     *\n *    the building's condition, this routine will assign an appropriate mission.               *\n *                                                                                             *\n * INPUT:   initial  -- This this being called during scenario init?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Enter_Idle_Mode(bool initial)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tAssign an appropriate mission for the building. If the ScenarioInit flag is true, then\n\t**\tthis must be an initial building. Start such buildings in idle state. For other buildings\n\t**\tit indicates that it is being placed during game play and thus it must start in\n\t**\tthe \"construction\" mission.\n\t*/\n\tMissionType mission = MISSION_GUARD;\n\n\n\tif (!initial || ScenarioInit || Debug_Map) {\n\t\tBegin_Mode(BSTATE_IDLE);\n\t\tmission = MISSION_GUARD;\n\t} else {\n\t\tBegin_Mode(BSTATE_CONSTRUCTION);\n\t\tmission = MISSION_CONSTRUCTION;\n\t}\n\tAssign_Mission(mission);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Pip_Count -- Determines \"full\" pips to display for building.                 *\n *                                                                                             *\n *    This routine will determine the number of pips that should be filled in when rendering   *\n *    the building.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of pips to display as filled in.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Pip_Count(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Class->Max_Pips() * House->Tiberium_Fraction());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Death_Announcement -- Announce the death of this building.                   *\n *                                                                                             *\n *    This routine is called when the building is destroyed by \"unnatural\" means. Typically    *\n *    as a result of combat. If the building is known to the player, then it should be         *\n *    announced.                                                                               *\n *                                                                                             *\n * INPUT:   source   -- The object most directly responsible for the building's death.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Death_Announcement(TechnoClass const * source) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (source != NULL && House->IsPlayerControl) {\n\t\tSpeak(VOX_STRUCTURE_DESTROYED);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Fire_Direction -- Fetches the direction of firing.                           *\n *                                                                                             *\n *    This routine will return with the default direction to use when firing from this         *\n *    building. This is the facing of the turret except for the case of non-turret equipped    *\n *    buildings that have a weapon (e.g., guard tower).                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the default firing direction for this building.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType BuildingClass::Fire_Direction(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsTurretEquipped) {\n\t\treturn(PrimaryFacing.Current());\n\t}\n\treturn(Direction(TarCom));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Remap_Table -- Fetches the remap table to use for this building.             *\n *                                                                                             *\n *    Use this routine to fetch the remap table to use.  This override function is needed      *\n *    because the default remap table for techno objects presumes the object is a unit.        *\n *    Buildings aren't units.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the proper remap table to use for this building.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * BuildingClass::Remap_Table(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(House->Remap_Table(IsBlushing, Class->Remap));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Mission_Unload -- Handles the unload mission for a building.                 *\n *                                                                                             *\n *    This is the unload mission for a building. This really only applies to the weapon's      *\n *    factory, since it needs the sophistication of an unload mission due to the door          *\n *    animation.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Mission_Unload(void)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (*this == STRUCT_WEAP) {\n\t\tCELL cell = Coord_Cell(Coord) + Class->ExitList[0];\n\t\tCOORDINATE coord = Cell_Coord(cell);\n\t\tCellClass * cellptr = &Map[cell];\n\t\tenum {\n\t\t\tINITIAL,\n\t\t\tCLEAR_BIB,\n\t\t\tOPEN,\n\t\t\tLEAVE,\n\t\t\tCLOSE\n\t\t};\n\t\tenum {\n\t\t\tDOOR_STAGES = 5,\n\t\t\tDOOR_RATE = 8\n\t\t};\n\t\tUnitClass * unit;\n\t\tswitch (Status) {\n\t\t\t/*\n\t\t\t**\tStart the door opening.\n\t\t\t*/\n\t\t\tcase INITIAL:\n//\t\t\t\tif (cellptr->Cell_Techno()) {\n//\t\t\t\t\tcellptr->Incoming(0, true);\n//\t\t\t\t}\n\t\t\t\tunit = (UnitClass *)Contact_With_Whom();\n\t\t\t\tif (unit) {\n\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\tunit->Commence();\n\t\t\t\t}\n\t\t\t\tOpen_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\tStatus = CLEAR_BIB;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNow that the occupants can peek out the door, they will tell\n\t\t\t**\teveryone that could be blocking the way, that they should\n\t\t\t**\tscatter away.\n\t\t\t*/\n\t\t\tcase CLEAR_BIB:\n\t\t\t\tif (cellptr->Cell_Techno()) {\n\t\t\t\t\tcellptr->Incoming(0, true, true);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tScatter everything around the weapon's factory door.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (FacingType f = FACING_FIRST; f < FACING_COUNT; f++) {\n\t\t\t\t\t\tCellClass * cptr = cellptr->Adjacent_Cell(f);\n\t\t\t\t\t\tif (cptr && cptr->Cell_Building() == NULL) {\n\t\t\t\t\t\t\tcptr->Incoming(coord, true, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStatus = OPEN;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWhen the door is finally open and the way is clear, tell the\n\t\t\t**\tunit to drive out.\n\t\t\t*/\n\t\t\tcase OPEN:\n\t\t\t\tif (Is_Door_Open()) {\n\t\t\t\t\tunit = (UnitClass *)Contact_With_Whom();\n\t\t\t\t\tif (unit) {\n\t\t\t\t\t\tunit->Assign_Mission(MISSION_MOVE);\n\n\t\t\t\t\t\tif (House->IQ >= Rule.IQGuardArea) {\n\t\t\t\t\t\t\tunit->Assign_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\tunit->ArchiveTarget = ::As_Target(House->Where_To_Go(unit));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tunit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, coord);\n//\t\t\t\t\t\tunit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, Adjacent_Cell(Adjacent_Cell(Center_Coord(), FACING_S), FACING_S));\n\t\t\t\t\t\tunit->Set_Speed(128);\n\t\t\t\t\t\tStatus = LEAVE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tClose_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\t\t\tStatus = CLOSE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWait until the unit has completely left the building.\n\t\t\t*/\n\t\t\tcase LEAVE:\n\t\t\t\tif (!IsTethered) {\n\t\t\t\t\tClose_Door(DOOR_RATE, DOOR_STAGES);\n\t\t\t\t\tStatus = CLOSE;\n\t\t\t\t} else {\n\n//\t\t\t\t\tif (In_Radio_Contact() && !((FootClass *)Contact_With_Whom())->IsDriving) {\n//\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n//\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tWait while the door closes.\n\t\t\t*/\n\t\t\tcase CLOSE:\n\t\t\t\tif (Is_Door_Closed()) {\n\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n\t}\n\n\tAssign_Mission(MISSION_GUARD);\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Power_Output -- Fetches the current power output from this building.         *\n *                                                                                             *\n *    This routine will return the current power output for this building. The power output    *\n *    is adjusted according to the damage level of the building.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current power output for this building.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Power_Output(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->Power) {\n\t\treturn(Class->Power * fixed(LastStrength, Class->MaxStrength));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Detach -- Handles target removal from the game system.                       *\n *                                                                                             *\n *    This routine is called when the specified target is about to be removed from the game    *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target to be removed from this building's targeting computer.      *\n *                                                                                             *\n *          all      -- Is the target about to be completely eliminated?                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Detach(TARGET target, bool all)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tTechnoClass::Detach(target, all);\n\tif (target == WhomToRepay) {\n\t\tWhomToRepay = TARGET_NONE;\n\t}\n\tif (target == AnimToTrack) {\n\t\tAnimToTrack = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Crew_Type -- This determines the crew that this object generates.            *\n *                                                                                             *\n *    When selling very cheap buildings (such as the silo), a technician will pop out since    *\n *    generating minigunners would be overkill -- the player could use this loophole to        *\n *    gain an advantage.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the infantry type that this building will generate as a survivor.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType BuildingClass::Crew_Type(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tswitch (Class->Type) {\n\t\tcase STRUCT_STORAGE:\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(INFANTRY_C1);\n\t\t\t} else {\n\t\t\t\treturn(INFANTRY_C7);\n\t\t\t}\n\n\t\tcase STRUCT_CONST:\n\t\t\tif (!IsCaptured && House->IsHuman && Percent_Chance(25)) {\n\t\t\t\treturn(INFANTRY_RENOVATOR);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase STRUCT_KENNEL:\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\treturn(INFANTRY_DOG);\n\t\t\t} else {\n\t\t\t\treturn(INFANTRY_NONE);\n\t\t\t}\n\n\t\tcase STRUCT_TENT:\n\t\tcase STRUCT_BARRACKS:\n\t\t\treturn(INFANTRY_E1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(TechnoClass::Crew_Type());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Detach_All -- Possibly abandons production according to factory type.        *\n *                                                                                             *\n *    When this routine is called, it indicates that the building is about to be destroyed     *\n *    or captured. In such a case any production it may be doing, must be abandoned.           *\n *                                                                                             *\n * INPUT:   all   -- Is the object about the be completely destroyed?                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Detach_All(bool all)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tIf it is producing something, then it must be abandoned.\n\t*/\n\tif (Factory) {\n\t\tFactory->Abandon();\n\t\tdelete (FactoryClass *)Factory;\n\t\tFactory = 0;\n\t}\n\n\t/*\n\t** If the owner HouseClass is building something, and this building can\n\t** build that thing, we may be the last building for that house that can\n\t** build that thing; if so, abandon production of it.\n\t*/\n\tif (House) {\n\t\tFactoryClass * factory = House->Fetch_Factory(Class->ToBuild);\n\n\t\t/*\n\t\t**\tIf a factory was found, then temporarily disable this building and then\n\t\t**\tdetermine if any object that is being produced can still be produced. If\n\t\t**\tnot, then the object being produced must be abandoned.\n\t\t*/\n\t\tif (factory) {\n\t\t\tTechnoClass * object = factory->Get_Object();\n\t\t\tIsInLimbo = true;\n\t\t\tif (object && !object->Techno_Type_Class()->Who_Can_Build_Me(true, false, House->Class->House)) {\n\t\t\t\tHouse->Abandon_Production(Class->ToBuild);\n\t\t\t}\n\t\t\tIsInLimbo = false;\n\t\t}\n\t}\n\n\tTechnoClass::Detach_All(all);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.         *\n *                                                                                             *\n *    This routine is used to clear the way for placement of the specified object (usually     *\n *    a building). If there are friendly units blocking the placement area, they are told      *\n *    to scatter. Enemy blocking units are attacked.                                           *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is desired to be placed.                    *\n *                                                                                             *\n *          cell     -- The cell that placement wants to occur at.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1995 JLB : Created.                                                                 *\n *   09/27/1995 JLB : Revised to use type class function.                                      *\n *=============================================================================================*/\nbool BuildingClass::Flush_For_Placement(TechnoClass * techno, CELL cell)\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (techno) {\n\t\treturn (((BuildingTypeClass const &)techno->Class_Of()).Flush_For_Placement(cell, House));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this building *\n *                                                                                             *\n *    This routine is called when the building needs to discharge a unit. It will find a       *\n *    nearby (adjacent) cell that is clear enough for the specified object to enter. Typical   *\n *    use of this routine is when the airfield disgorges its cargo.                            *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that wishes to exit this building.               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number to use for object placement. If no free location      *\n *          could be found, then zero (0) is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Added default case for exit cell calculation.                            *\n *=============================================================================================*/\nCELL BuildingClass::Find_Exit_Cell(TechnoClass const * techno) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tCELL const * ptr;\n\tCELL origin = Coord_Cell(Coord);\n\n\tptr = Class->ExitList;\n\tif (ptr != NULL) {\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\tCELL cell = origin + *ptr++;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tint x1, x2;\n\t\tint y1, y2;\n\t\tCELL cell;\n\n\t\ty1 = -1;\n\t\ty2 = Class->Height();\n\t\tfor (x1 = -1; x1 <= Class->Width(); x1++) {\n\t\t\tcell = origin + x1 + (y1 * MAP_CELL_W);\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t\tcell = origin + x1 + (y2 * MAP_CELL_W);\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\n\t\tx1 = -1;\n\t\tx2 = Class->Width();\n\t\tfor (y1 = -1; y1 <= Class->Height(); y1++) {\n\t\t\tcell = origin + (y1 * MAP_CELL_W) + x1;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t\tcell = origin + (y1 * MAP_CELL_W) + x2;\n\t\t\tif (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {\n\t\t\t\treturn(cell);\n\t\t\t}\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Can_Player_Move -- Can this building be moved?                               *\n *                                                                                             *\n *    This routine answers the question 'can this building be moved?' Typically, only the      *\n *    construction yard can be moved and it does this by undeploying back into a MCV.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can the building move to a new location under player control?                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BuildingClass::Can_Player_Move(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(*this == STRUCT_CONST && (Mission == MISSION_GUARD) && Special.IsMCVDeploy);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Exit_Coord -- Determines location where object will leave it.                *\n *                                                                                             *\n *    This routine will return the coordinate where an object that wishes to leave the         *\n *    building will exit at.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that the object should be created at.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Exit_Coord(void) const\n{\n\tassert(Buildings.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->ExitCoordinate) {\n\t\treturn(Coord_Add(Coord, Class->ExitCoordinate));\n\t}\n\treturn(TechnoClass::Exit_Coord());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.  *\n *                                                                                             *\n *    Use this routine to coordinate a landing operation. The specified checkpoint is          *\n *    converted into a cell number. The landing aircraft should fly over that cell and then    *\n *    request the next check point.                                                            *\n *                                                                                             *\n * INPUT:   cp    -- The check point to convert to a cell number.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the aircraft should fly over in order to complete       *\n *          that portion of the landing pattern.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL BuildingClass::Check_Point(CheckPointType cp) const\n{\n\tCELL xoffset = 6;\t\t// Downwind offset.\n\tCELL yoffset = 5;\t\t// Crosswind offset.\n\tCELL cell = Coord_Cell(Center_Coord());\n\n\tswitch (cp) {\n\t\tcase CHECK_STACK:\n\t\t\txoffset = 0;\n\t\t\tbreak;\n\n\t\tcase CHECK_CROSSWIND:\n\t\t\tyoffset = 0;\n\t\t\tbreak;\n\n\t\tcase CHECK_DOWNWIND:\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif ((Cell_X(cell) - Map.MapCellX) > Map.MapCellWidth/2)  {\n\t\txoffset = -xoffset;\n\t}\n\n\tif ((Cell_Y(cell) - Map.MapCellY) > Map.MapCellHeight/2)  {\n\t\tyoffset = -yoffset;\n\t}\n\n\treturn(XY_Cell(Cell_X(cell)+xoffset, Cell_Y(cell)+yoffset));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Update_Radar_Spied - set house's RadarSpied field appropriately.\t\t\t\t  *\n *                                                                                             *\n *    This routine is called when a radar facility is captured or destroyed.  It fills in the  *\n *    RadarSpied field of the house based on whether there's a spied-upon radar facility or not*\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  House->RadarSpied field gets set appropriately.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/22/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Update_Radar_Spied(void)\n{\n\tHouse->RadarSpied = 0;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == House) {\n\t\t\tif (*obj == STRUCT_RADAR /* || *obj == STRUCT_EYE */) {\n\t\t\t\tHouse->RadarSpied |= obj->Spied_By();\n\t\t\t}\n\t\t}\n\t}\n\tMap.RadarClass::Flag_To_Redraw(true);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Read_INI -- Reads buildings from INI file.                                   *\n *                                                                                             *\n *    This is the basic scenario initialization of building function. It                       *\n *    is called when reading the scenario startup INI file and it handles                      *\n *    creation of all specified buildings.                                                     *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Housename, Typename, Strength, Cell, Facing, Triggername                               *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded INI file data.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Read_INI(CCINIClass & ini)\n{\n\tBuildingClass\t\t\t* b;\t\t\t// Working unit pointer.\n\tHousesType\t\t\t\tbhouse;\t\t// Building house.\n\tStructType\t\t\t\tclassid;\t\t// Building type.\n\tCELL\t\t\t\t\t\tcell;\t\t\t// Cell of building.\n\tchar\t\t\t\t\t\tbuf[128];\n\tchar\t\t\t\t\t\t* trigname;\t// building's trigger's name\n\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\t/*\n\t\t**\tGet a building entry.\n\t\t*/\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t**\t1st token: house name.\n\t\t*/\n\t\tbhouse = HouseTypeClass::From_Name(strtok(buf, \",\"));\n\n\t\t/*\n\t\t**\t2nd token: building name.\n\t\t*/\n\t\tclassid = BuildingTypeClass::From_Name(strtok(NULL, \",\"));\n\n\t\tif (bhouse != HOUSE_NONE && classid != STRUCT_NONE) {\n\t\t\tint\tstrength;\n\t\t\tDirType facing;\n\n\t\t\t/*\n\t\t\t**\t3rd token: strength.\n\t\t\t*/\n\t\t\tstrength = atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t4th token: cell #.\n\t\t\t*/\n\t\t\tcell = atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t5th token: facing.\n\t\t\t*/\n\t\t\tfacing = (DirType)atoi(strtok(NULL, \",\"));\n\n\t\t\t/*\n\t\t\t**\t6th token: triggername (can be NULL).\n\t\t\t*/\n\t\t\ttrigname = strtok(NULL, \",\");\n\n\t\t\tbool sellable = false;\n\t\t\tchar * token_pointer = strtok(NULL, \",\");\n\t\t\tif (token_pointer) {\n\t\t\t\tsellable = atoi(token_pointer);\n\t\t\t}\n\n\t\t\tbool rebuild = false;\n\t\t\ttoken_pointer = strtok(NULL, \",\");\n\t\t\tif (token_pointer) {\n\t\t\t\trebuild = atoi(token_pointer);\n\t\t\t}\n\n\t\t\tif (HouseClass::As_Pointer(bhouse) != NULL) {\n\t\t\t\tb = new BuildingClass(classid, bhouse);\n\t\t\t\tif (b) {\n\n\t\t\t\t\tTriggerTypeClass * tp = TriggerTypeClass::From_Name(trigname);\n\t\t\t\t\tif (tp) {\n\t\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\t\tif (tt) {\n\t\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\t\tb->Trigger = tt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tb->IsAllowedToSell = sellable;\n\t\t\t\t\tb->IsToRebuild = rebuild;\n\t\t\t\t\tb->IsToRepair = rebuild || *b == STRUCT_CONST;\n\n\t\t\t\t\tif (b->Unlimbo(Cell_Coord(cell), facing)) {\n\t\t\t\t\t\tstrength = min(strength, 0x100);\n\t\t\t\t\t\tstrength = (int)b->Class->MaxStrength * fixed(strength, 256);\t\t// Cast to (int). ST - 5/8/2019\n\t\t\t\t\t\tb->Strength = strength;\n\t\t\t\t\t\tif (b->Strength > b->Class->MaxStrength-3) b->Strength = b->Class->MaxStrength;\n\t\t\t\t\t\tb->IsALemon = false;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the building could not be unlimboed on the map, then this indicates\n\t\t\t\t\t\t**\ta serious error. Delete the building.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdelete b;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Write_INI -- Write out the building data to the INI file specified.          *\n *                                                                                             *\n *    This will store the building data (as it relates to scenario initialization) to the      *\n *    INI database specified.                                                                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that the building data will be stored to.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing building data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the data out.\n\t*/\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\tif (!building->IsInLimbo) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[127];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%d,%d\",\n\t\t\t\tbuilding->House->Class->IniName,\n\t\t\t\tbuilding->Class->IniName,\n\t\t\t\tbuilding->Health_Ratio()*256,\n\t\t\t\tCoord_Cell(building->Coord),\n\t\t\t\tbuilding->PrimaryFacing.Current(),\n\t\t\t\tbuilding->Trigger.Is_Valid() ? building->Trigger->Class->IniName : \"None\",\n\t\t\t\tbuilding->IsAllowedToSell,\n\t\t\t\tbuilding->IsToRebuild\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building.   *\n *                                                                                             *\n *    This routine will determine the \"center\" location of this building for purposes of       *\n *    targeting. Usually, this location is somewhere near the foundation of the building.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when firing upon this building (or trying to    *\n *          walk onto it).                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BuildingClass::Target_Coord(void) const\n{\n\tCOORDINATE coord = Center_Coord();\n\n\tif (Class->FoundationFace != FACING_NONE) {\n\t\treturn(Adjacent_Cell(coord, Class->FoundationFace));\n\t}\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Factory_AI -- Handle factory production and initiation.                      *\n *                                                                                             *\n *    Some building (notably the computer controlled ones) can have a factory object attached. *\n *    This routine handles processing of that factory and also detecting when production       *\n *    should begin in order to initiate production.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Factory_AI(void)\n{\n\t/*\n\t**\tHandle any production tied to this building. Only computer controlled buildings have\n\t**\tproduction attached to the building itself. The player uses the sidebar interface for\n\t**\tall production control.\n\t*/\n\tif (Factory.Is_Valid() && Factory->Has_Completed() && PlacementDelay == 0) {\n\t\tTechnoClass * product = Factory->Get_Object();\n//\t\tFactoryClass * fact = Factory;\n\n\t\tswitch (Exit_Object(product)) {\n\n\t\t\t/*\n\t\t\t**\tIf the object could not leave the factory, then either request\n\t\t\t**\ta transport, place the (what must be a) building using another method, or\n\t\t\t**\tabort the production and refund money.\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tFactory->Abandon();\n\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\tFactory = 0;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tExiting this building is prevented by some temporary blockage. Wait\n\t\t\t**\ta bit before trying again.\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tPlacementDelay = TICKS_PER_SECOND*3;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe object was successfully sent from this factory. Inform the house\n\t\t\t**\ttracking logic that the requested object has been produced.\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tswitch (product->What_Am_I()) {\n\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\tHouse->JustBuiltVessel = ((VesselClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\tHouse->JustBuiltUnit = ((UnitClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\tHouse->JustBuiltInfantry = ((InfantryClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\tHouse->JustBuiltStructure = ((BuildingClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tHouse->JustBuiltAircraft = ((AircraftClass*)product)->Class->Type;\n\t\t\t\t\t\tHouse->IsBuiltSomething = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n//\t\t\t\tfact->Completed();\n\t\t\t\tFactory->Completed();\n//\t\t\t\tdelete fact;\n\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\tFactory = 0;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPick something to create for this factory.\n\t*/\n\tif (House->IsStarted && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {\n\n\t\t/*\n\t\t**\tBuildings that produce other objects have special factory logic handled here.\n\t\t*/\n\t\tif (Class->ToBuild != RTTI_NONE) {\n\t\t\tif (Factory.Is_Valid()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf production has halted, then just abort production and make the\n\t\t\t\t**\tfunds available for something else.\n\t\t\t\t*/\n\t\t\t\tif (PlacementDelay == 0 && !Factory->Is_Building()) {\n\t\t\t\t\tFactory->Abandon();\n\t\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\t\tFactory = 0;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly look to start production if there is at least a small amount of\n\t\t\t\t**\tmoney available. In cases where there is no practical money left, then\n\t\t\t\t**\tproduction can never complete -- don't bother starting it.\n\t\t\t\t*/\n\t\t\t\tif (House->IsStarted && House->Available_Money() > 10) {\n\t\t\t\t\tTechnoTypeClass const * techno = House->Suggest_New_Object(Class->ToBuild, *this == STRUCT_KENNEL);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf a suitable object type was selected for production, then start\n\t\t\t\t\t**\tproducing it now.\n\t\t\t\t\t*/\n\t\t\t\t\tif (techno != NULL) {\n\t\t\t\t\t\tFactory = new FactoryClass;\n\t\t\t\t\t\tif (Factory.Is_Valid()) {\n\t\t\t\t\t\t\tif (!Factory->Set(*techno, *House)) {\n\t\t\t\t\t\t\t\tdelete (FactoryClass *)Factory;\n\t\t\t\t\t\t\t\tFactory = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tHouse->Production_Begun(Factory->Get_Object());\n\t\t\t\t\t\t\t\tFactory->Start();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Rotation_AI -- Process any turret rotation required of this building.        *\n *                                                                                             *\n *    Some buildings have a turret and this routine handles processing the turret rotation.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *   10/27/1996 JLB : Rotation does not occur if power and no power avail.                     *\n *=============================================================================================*/\nvoid BuildingClass::Rotation_AI(void)\n{\n\tif (Class->IsTurretEquipped &&\n\t\t\tMission != MISSION_CONSTRUCTION &&\n\t\t\tMission != MISSION_DECONSTRUCTION &&\n\t\t\t(!Class->IsPowered || House->Power_Fraction() >= 1)) {\n\n\t\t/*\n\t\t**\tRotate turret to match desired facing.\n\t\t*/\n\t\tif (PrimaryFacing.Is_Rotating()) {\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.           *\n *                                                                                             *\n *    This handles the special logic required of the charging tesla coil. It requires special  *\n *    processing since its charge up is dependant upon the target and power surplus of the     *\n *    owning house.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Charging_AI(void)\n{\n\tif (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && BState != BSTATE_CONSTRUCTION) {\n\t\tif (Target_Legal(TarCom) && House->Power_Fraction() >= 1) {\n\t\t\tif (!IsCharged) {\n\t\t\t\tif (IsCharging) {\n//\t\t\t\t\tif (stagechange) {\n\t\t\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\t\t\tif (Fetch_Stage() >= 9) {\n\t\t\t\t\t\t\tIsCharged = true;\n\t\t\t\t\t\t\tIsCharging = false;\n\t\t\t\t\t\t\tSet_Rate(0);\n\t\t\t\t\t\t}\n//\t\t\t\t\t}\n\t\t\t\t} else if (!Arm) {\n\t\t\t\t\tIsCharged = false;\n\t\t\t\t\tIsCharging = true;\n\t\t\t\t\tSet_Stage(0);\n\t\t\t\t\tSet_Rate(3);\n\t\t\t\t\tSound_Effect(VOC_TESLA_POWER_UP, Coord);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (IsCharging || IsCharged) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t\tIsCharging = false;\n\t\t\t\tIsCharged = false;\n\t\t\t\tSet_Stage(0);\n\t\t\t\tSet_Rate(0);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.            *\n *                                                                                             *\n *    This routine handle the repair animation and healing logic. It also detects when the     *\n *    (computer controlled) building should begin repair or sell itself.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Repair_AI(void)\n{\n\tif (House->IQ >= Rule.IQRepairSell && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {\n\t\t/*\n\t\t**\tPossibly start repair process if the building is below half strength.\n\t\t*/\n//\t\tunsigned ratio = MIN(House->Smartness, 0x00F0);\n\t\tif (Can_Repair()) {\n\t\t\tif (House->Available_Money() >= Rule.RepairThreshhold) {\n\t\t\t\tif (!House->DidRepair) {\n\t\t\t\t\tif (!IsRepairing && (IsCaptured || IsToRepair || House->IsHuman || Session.Type != GAME_NORMAL)) {\n\t\t\t\t\t\tHouse->DidRepair = true;\t// flag that this house did its repair allocation for this frame\n\t\t\t\t\t\tRepair(1);\n\n\t\t\t\t\t\tif (!House->IsHuman) {\n\t\t\t\t\t\t\tHouse->RepairTimer = Random_Pick((int)(House->RepairDelay * (TICKS_PER_MINUTE/4)), (int)(House->RepairDelay * TICKS_PER_MINUTE * 2));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ((Session.Type != GAME_NORMAL || IsAllowedToSell) && IsTickedOff && House->Control.TechLevel >= Rule.IQSellBack && Random_Pick(0, 50) < House->Control.TechLevel && !Trigger.Is_Valid() && *this != STRUCT_CONST && Health_Ratio() < Rule.ConditionRed) {\n\t\t\t\t\tSell_Back(1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it is repairing, then apply any repair effects as necessary.\n\t*/\n\tif (IsRepairing && (Frame % (Rule.RepairRate * TICKS_PER_MINUTE)) == 0) {\n\t\tIsWrenchVisible = (IsWrenchVisible == false);\n\t\tMark(MARK_CHANGE);\n\t\tint cost = Class->Repair_Cost();\n\t\tint step = Class->Repair_Step();\n\n\t\t/*\n\t\t**\tCheck for and expend any necessary monies to continue the repair.\n\t\t*/\n\t\tif (House->Available_Money() >= cost) {\n\t\t\tHouse->Spend_Money(cost);\n\t\t\tStrength += step;\n\n\t\t\tif (Strength >= Class->MaxStrength) {\n\t\t\t\tStrength = Class->MaxStrength;\n\t\t\t\tIsRepairing = false;\n\t\t\t}\n\t\t} else {\n\t\t\tIsRepairing = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Animation_AI -- Handles normal building animation processing.                *\n *                                                                                             *\n *    This will process the general building animation mechanism. It detects when the          *\n *    building animation sequence has completed and flags the building to perform mission      *\n *    changes as a result.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once per building per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Animation_AI(void)\n{\n\tbool stagechange = Graphic_Logic();\n\tbool toloop = false;\n\n\t/*\n\t**\tAlways refresh the SAM site if it has an animation change.\n\t*/\n\tif (*this == STRUCT_SAM && stagechange) Mark(MARK_CHANGE);\n\n\tif ((!Class->IsTurretEquipped && *this != STRUCT_TESLA) || Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION) {\n\t\tif (stagechange) {\n\n\t\t\t/*\n\t\t\t**\tCheck for animation end or if special case of MCV deconstructing when it is allowed\n\t\t\t**\tto convert back into an MCV.\n\t\t\t*/\n\t\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\n\t\t\t/*\n\t\t\t**\tWhen the last frame of the current animation sequence is reached, flag that\n\t\t\t**\ta new mission may be started. This must occur before the animation actually\n\t\t\t**\tloops so that if a mission change does occur, it will have a chance to change\n\t\t\t**\tthe building graphic before the last frame is replaced by the first frame of\n\t\t\t**\tthe loop.\n\t\t\t*/\n\t\t\tif (Fetch_Stage() == ctrl->Start+ctrl->Count-1  || (!Target_Legal(ArchiveTarget) /*Is_MCV_Deploy()*/ && *this == STRUCT_CONST && Mission == MISSION_DECONSTRUCTION && Fetch_Stage() == (42-19))) {\n\t\t\t\tIsReadyToCommence = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the animation advances beyond the last frame, then start the animation\n\t\t\t**\tsequence over from the beginning.\n\t\t\t*/\n\t\t\tif (Fetch_Stage() >= ctrl->Start+ctrl->Count) {\n\t\t\t\ttoloop = true;\n\t\t\t}\n\t\t\tMark(MARK_CHANGE);\n\t\t} else {\n\t\t\tif (BState == BSTATE_NONE || Fetch_Rate() == 0) {\n\t\t\t\tIsReadyToCommence = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a door that is animating, then it might cause this building\n\t**\tto be redrawn. Check for and flag to redraw as necessary.\n\t*/\n\tif (Time_To_Redraw()) {\n\t\tClear_Redraw_Flag();\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tThe animation sequence has looped. Restart it and flag this loop condition.\n\t**\tThis is used to tell the mission system that the animation has completed. It\n\t**\talso signals that now is a good time to act on any pending mission.\n\t*/\n\tif (toloop) {\n\t\tBuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();\n\t\tif (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {\n\t\t\tSet_Rate(Options.Normalize_Delay(ctrl->Rate));\n\t\t} else {\n\t\t\tSet_Rate(ctrl->Rate);\n\t\t}\n\t\tSet_Stage(ctrl->Start);\n\t\tMark(MARK_CHANGE);\n\t}\n}\n\n\n/***********************************************************************************************\n * BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.        *\n *                                                                                             *\n *    This routine is called to determine how many survivors should run from this building     *\n *    when it is either sold or destroyed. Buildings that are captured have fewer survivors.   *\n *    The number of survivors is a portion of the cost of the building divided by the cost     *\n *    of a minigunner.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of soldiers that should run from this building.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::How_Many_Survivors(void) const\n{\n\tif (IsSurvivorless || !Class->IsCrew) return(0);\n\n\tint divisor = InfantryTypeClass::As_Reference(INFANTRY_E1).Raw_Cost();\n\tif (divisor == 0) return(0);\n\tif (IsCaptured) divisor *= 2;\n\tint count = (Class->Raw_Cost() * Rule.SurvivorFraction) / divisor;\n\treturn(Bound(count, 1, 5));\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                  *\n *                                                                                             *\n *    This routine will return with a pointer to the shape data for the building. The shape    *\n *    data is different than normal when the building is undergoing construction and           *\n *    disassembly.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the shape data for this building.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * BuildingClass::Get_Image_Data(void) const\n{\n\tif (BState == BSTATE_CONSTRUCTION) {\n\t\treturn(Class->Get_Buildup_Data());\n\t}\n\treturn(TechnoClass::Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Value -- Determine the value of this building.                               *\n *                                                                                             *\n *    The value of the building is normally just its ordinary assigned value. However, in the  *\n *    case of fakes, the value is artificially enhanced to match the structure that is         *\n *    being faked.                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the point value of the building type.                                 *\n *                                                                                             *\n * WARNINGS:   The point value returned should not be used for scoring, only for target        *\n *             scanning.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BuildingClass::Value(void) const\n{\n\tif (Class->IsFake) {\n\t\tswitch (Class->Type) {\n\t\t\tcase STRUCT_FAKEWEAP:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_WEAP).Reward + BuildingTypeClass::As_Reference(STRUCT_WEAP).Risk);\n\n\t\t\tcase STRUCT_FAKECONST:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_CONST).Reward + BuildingTypeClass::As_Reference(STRUCT_CONST).Risk);\n\n\t\t\tcase STRUCT_FAKE_YARD:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Reward + BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Risk);\n\n\t\t\tcase STRUCT_FAKE_PEN:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Reward + BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Risk);\n\n\t\t\tcase STRUCT_FAKE_RADAR:\n\t\t\t\treturn(BuildingTypeClass::As_Reference(STRUCT_RADAR).Reward + BuildingTypeClass::As_Reference(STRUCT_RADAR).Risk);\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(TechnoClass::Value());\n}\n\n\n/***********************************************************************************************\n * BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells.\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid BuildingClass::Remove_Gap_Effect(void)\n{\n\t// unjam this one's field...\n\tMap.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);\n\t\n\t\n\t/*\n\t** Updated for client/server multiplayer. ST - 8/12/2019 11:14AM\n\t*/\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (!House->IsPlayerControl && PlayerPtr->IsGPSActive) {\n\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, PlayerPtr);\n\t\t}\n\t\n\t} else {\n\t\t\n\t\tfor (int i = 0; i < Session.Players.Count(); i++) {\n\t\t\tHouseClass *player_house = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tif (player_house->IsGPSActive && player_house != House) {\n\t\t\t\tMap.Sight_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, player_house);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// and rejam any overlapping buildings' fields\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass *obj = Buildings.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == House && *obj == STRUCT_GAP && obj!=this) {\n\t\t\tobj->IsJamming = false;\n\t\t\tobj->Arm = 0;\n//\t\t\tMap.Jam_From(Coord_Cell(obj->Center_Coord()), Rule.GapShroudRadius, PlayerPtr);\n\t\t}\n\t}\n}\n\n\nshort const * BuildingClass::Overlap_List(bool redraw) const\n{\n\tif ((Spied_By() & (1 << PlayerPtr->Class->House)) != 0 && Is_Selected_By_Player()) {\n\t\tif (*this == STRUCT_BARRACKS || *this == STRUCT_TENT) {\n\t\t\tstatic short const _list[] = {\n\t\t\t\t-1, 2, (MAP_CELL_W*1)-1, (MAP_CELL_W*1)+2, REFRESH_EOL\n\t\t\t};\n\t\t\treturn(_list);\n\t\t} else if (*this == STRUCT_REFINERY) {\n\t\t\tstatic short const _list[] = {\n\t\t\t\t0, 2, (MAP_CELL_W*2)+0, (MAP_CELL_W*2)+1, (MAP_CELL_W*2)+2, REFRESH_EOL\n\t\t\t};\n\t\t\treturn(_list);\n\t\t}\n\t}\n\treturn(TechnoClass::Overlap_List(redraw));\n}\n\n\nunsigned BuildingClass::Spied_By() const\n{\n\tunsigned spiedby = TechnoClass::Spied_By();\n\n\t/*\n\t** If it's an ore refinery or other such storage-capable building,\n\t** loop thru all of their buildings to see if ANY of them are spied\n\t** upon, 'cause once you spy any money, you've spied all of it.\n\t*/\n\tif (Class->Capacity) {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\tif (building->House == House && building->Class->Capacity) {\n\t\t\t\tspiedby |= building->SpiedBy;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn spiedby;\n}"
  },
  {
    "path": "REDALERT/BUILDING.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BUILDING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BUILDING.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BUILDING_H\n#define BUILDING_H\n\n#include\t\"radio.h\"\n#include\t\"cargo.h\"\n#include\t\"mission.h\"\n#include\t\"bullet.h\"\n#include\t\"target.h\"\n#include\t\"factory.h\"\n#include\t\"techno.h\"\n\n#define\tMAX_DOOR_STAGE\t18\t// # of frames of door opening on weapons factory\n#define\tDOOR_OPEN_STAGE 9\t// frame on which the door is entirely open\n#define\tMAX_REPAIR_ANIM_STAGE\t5\t// # of stages of anim for repair center cycling\n\n/****************************************************************************\n**\tFor each instance of a building in the game, there is one of\n**\tthese structures. This structure holds information that is specific\n**\tand dynamic for a particular building.\n*/\nclass BuildingClass : public TechnoClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis points to the control data that gives this building its characteristics.\n\t\t*/\n\t\tCCPtr<BuildingTypeClass> Class;\n\n\t\t/*\n\t\t**\tIf this building is in the process of producing something, then this\n\t\t**\twill point to the factory manager.\n\t\t*/\n\t\tCCPtr<FactoryClass> Factory;\n\n\t\t/*\n\t\t**\tThis is the house that originally owned this factory. Objects buildable\n\t\t**\tby this house type will be produced from this factory regardless of who\n\t\t**\tthe current owner is.\n\t\t*/\n\t\tHousesType ActLike;\n\n\t\t/*\n\t\t**\tThis building should be rebuilt if it is destroyed. This is in spite\n\t\t**\tof the condition of the prebuilt base list.\n\t\t*/\n\t\tunsigned IsToRebuild:1;\n\n\t\t/*\n\t\t**\tIs the building allowed to repair itself?\n\t\t*/\n\t\tunsigned IsToRepair:1;\n\n\t\t/*\n\t\t**\tIf the computer owns this building, then it is allowed to sell it if\n\t\t**\tthe situation warrants it. In the other case, it cannot sell the\n\t\t**\tbuilding regardless of conditions.\n\t\t*/\n\t\tunsigned IsAllowedToSell:1;\n\n\t\t/*\n\t\t**\tIf the building is at a good point to change orders, then this\n\t\t**\tflag will be set to true.\n\t\t*/\n\t\tunsigned IsReadyToCommence:1;\n\n\t\t/*\n\t\t**\tIf this building is currently spending money to repair itself, then\n\t\t**\tthis flag is true. It will automatically be set to false when the building\n\t\t**\thas reached full strength, when money is exhausted, or if the player\n\t\t**\tspecifically stops the repair process.\n\t\t*/\n\t\tunsigned IsRepairing:1;\n\n\t\t/*\n\t\t**\tIf repair is currently in progress and this flag is true, then a wrench graphic\n\t\t**\twill be overlaid on the building to give visual feedback for the repair process.\n\t\t*/\n\t\tunsigned IsWrenchVisible:1;\n\n\t\t/*\n\t\t** This flag is set when a commando has raided the building and planted\n\t\t** plastic explosives.  When the CommandoCountDown timer expires, the\n\t\t** building takes massive damage.\n\t\t*/\n\t\tunsigned IsGoingToBlow:1;\n\n\t\t/*\n\t\t**\tIf this building was destroyed by some method that would prevent\n\t\t**\tsurvivors, then this flag will be true.\n\t\t*/\n\t\tunsigned IsSurvivorless:1;\n\n\t\t/*\n\t\t**\tThese state control variables are used by the obelisk for the charging\n\t\t**\tanimation.\n\t\t*/\n\t\tunsigned IsCharging:1;\n\t\tunsigned IsCharged:1;\n\n\t\t/*\n\t\t**\tA building that has been captured will not contain the full compliment\n\t\t**\tof crew. This is true even if it subsequently gets captured back.\n\t\t*/\n\t\tunsigned IsCaptured:1;\n\n\t\t/*\n\t\t** Used by the gap generator to decide if it should jam or unjam\n\t\t*/\n\t\tunsigned IsJamming:1;\n\n\t\t/*\n\t\t** Used by radar facilities to know if they're being jammed by a mobile\n\t\t** radar jammer\n\t\t*/\n\t\tunsigned IsJammed:1;\n\n\t\t/*\n\t\t** Used only by advanced tech center, this keeps track of whether the\n\t\t** GPS satellite has been fired or not.\n\t\t*/\n\t\tunsigned HasFired:1;\n\n\t\t/*\n\t\t**\tIf Grand_Opening was already called for this building, then this\n\t\t**\tflag will be true. By utilizing this flag, multiple inadvertant\n\t\t**\tcalls to Grand_Opening won't cause problems.\n\t\t*/\n\t\tunsigned HasOpened:1;\n\n\t\t/*\n\t\t**\tSpecial countdown to destruction value. If the building is destroyed,\n\t\t**\tit won't actually be removed from the map until this value reaches\n\t\t**\tzero. This delay is for cosmetic reasons.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> CountDown;\n\n\t\t/*\n\t\t**\tThis is the current animation processing state that the building is\n\t\t**\tin.\n\t\t*/\n\t\tBStateType BState;\n\t\tBStateType QueueBState;\n\n\t\t/*\n\t\t** For multiplayer games, this keeps track of the last house to damage\n\t\t** this building, so if it burns to death or otherwise gradually dies,\n\t\t** proper credit can be given for the kill.\n\t\t*/\n\t\tHousesType WhoLastHurtMe;\n\n\t\t/*\n\t\t**\tThis is the saboteur responsible for this building's destruction.\n\t\t*/\n\t\tTARGET WhomToRepay;\n\n\t\t/*\n\t\t**\tThis is a record of the last strength of the building. Every so often,\n\t\t**\tit will compare this strength to the current strength. If there is a\n\t\t**\tdiscrepancy, then the owner power is adjusted accordingly.\n\t\t*/\n\t\tint LastStrength;\n\n\t\t/*\n\t\t** This is a target id of an animation we're keeping track of.  Examples\n\t\t** of this usage are the advanced tech center, which needs to know\n\t\t** when the sputdoor animation has reached a certain stage.\n\t\t*/\n\t\tTARGET AnimToTrack;\n\n\t\t/*\n\t\t**\tThis is the countdown timer that regulates placement retry logic\n\t\t**\tfor factory type buildings.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> PlacementDelay;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tBuildingClass(StructType type, HousesType house);\n#ifdef FIXIT_MULTI_SAVE\n\t\tBuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), Factory(x), CountDown(x), PlacementDelay(x) {};\n#else\n\t\tBuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), CountDown(x), PlacementDelay(x) {};\n#endif\n\t\tvirtual ~BuildingClass(void);\n\t\toperator StructType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tTARGET Target_Scan(void);\n\t\tBuildingTypeClass::AnimControlType const * Fetch_Anim_Control(void) {return (&Class->Anims[BState]);};\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual int Value(void) const;\n\t\tvirtual void const * Get_Image_Data(void) const;\n\t\tvirtual int How_Many_Survivors(void) const;\n\t\tvirtual DirType Turret_Facing(void) const;\n\t\tvirtual CELL Find_Exit_Cell(TechnoClass const * techno) const;\n\t\tvirtual InfantryType Crew_Type(void) const;\n\t\tvirtual int Pip_Count(void) const;\n\t\tvirtual bool Can_Player_Move(void) const;\n\t\tvirtual ActionType What_Action(ObjectClass const * target) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tvirtual bool Can_Demolish_Unit(void) const;\n\t\tvirtual bool Can_Capture(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual DirType Fire_Direction(void) const;\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tint Shape_Number(void) const;\n\t\tint Power_Output(void) const;\n\t\tCELL Check_Point(CheckPointType cp) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\t\tvirtual COORDINATE Docking_Coord(void) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual COORDINATE Exit_Coord(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual void Grand_Opening(bool captured = false);\n\t\tvirtual void Update_Buildables(void);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType = FACING_NONE) const;\n\t\tvirtual bool Unlimbo(COORDINATE , DirType dir = DIR_N);\n\t\tvirtual bool Limbo(void);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void const * Remap_Table(void);\n\t\tvirtual int Exit_Object(TechnoClass * base);\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual void Fire_Out(void);\n\t\tvoid Begin_Mode(BStateType bstate);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual void Death_Announcement(TechnoClass const * source=0) const;\n\t\tvirtual FireErrorType Can_Fire(TARGET, int which) const;\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual bool Captured(HouseClass * newowner);\n\t\tvoid Update_Radar_Spied(void);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvoid Charging_AI(void);\n\t\tvoid Rotation_AI(void);\n\t\tvoid Factory_AI(void);\n\t\tvoid Repair_AI(void);\n\t\tvoid Animation_AI(void);\n\t\tvirtual bool Revealed(HouseClass * house);\n\t\tvirtual void Repair(int control);\n\t\tvirtual void Sell_Back(int control);\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual void AI(void);\n\t\tvirtual void Assign_Target(TARGET target);\n\t\tvirtual bool Toggle_Primary(void);\n\t\tbool Flush_For_Placement(TechnoClass * techno, CELL cell);\n\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Repair(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Harvest(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Construction(void);\n\t\tvirtual int Mission_Deconstruction(void);\n\t\tvirtual int Mission_Missile(void);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvoid Remove_Gap_Effect(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"STRUCTURES\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\tvirtual unsigned Spied_By() const;\n\n\tprivate:\n\t\tvoid Drop_Debris(TARGET source = TARGET_NONE);\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[32];\n\n\t\tstatic COORDINATE const CenterOffset[BSIZE_COUNT];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/BULLET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BULLET.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BULLET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 10, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletClass::AI -- Logic processing for bullet.                                           *\n *   BulletClass::BulletClass -- Bullet constructor.                                           *\n *   BulletClass::Bullet_Explodes -- Performs bullet explosion logic.                          *\n *   BulletClass::Detach -- Removes specified target from this bullet's targeting system.      *\n *   BulletClass::Draw_It -- Displays the bullet at location specified.                        *\n *   BulletClass::In_Which_Layer -- Fetches the layer that the bullet resides in.              *\n *   BulletClass::Init -- Clears the bullets array for scenario preparation.                   *\n *   BulletClass::Is_Forced_To_Explode -- Checks if bullet should explode NOW.                 *\n *   BulletClass::Mark -- Performs related map refreshing under bullet.                        *\n *   BulletClass::Occupy_List -- Determines the bullet occupation list.                        *\n *   BulletClass::Shape_Number -- Fetches the shape number for the bullet object.              *\n *   BulletClass::Sort_Y -- Sort coordinate for bullet rendering.                              *\n *   BulletClass::Target_Coord -- Fetches coordinate to use when firing on this object.        *\n *   BulletClass::Unlimbo -- Transitions a bullet object into the game render/logic system.    *\n *   BulletClass::delete -- Bullet memory delete.                                              *\n *   BulletClass::new -- Allocates memory for bullet object.                                   *\n *   BulletClass::~BulletClass -- Destructor for bullet objects.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * BulletClass::BulletClass -- Bullet constructor.                                             *\n *                                                                                             *\n *    This is the constructor for the bullet class. It handles all                             *\n *    initialization of the bullet and starting it in motion toward its                        *\n *    target.                                                                                  *\n *                                                                                             *\n * INPUT:   id       -- The type of bullet this is (could be missile).                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Firer is a base class pointer.                                           *\n *   12/10/1994 JLB : Auto calculate range optional.                                           *\n *   12/12/1994 JLB : Handles small arms as an instantaneous effect.                           *\n *   12/23/1994 JLB : Fixed scatter algorithm for non-homing projectiles.                      *\n *   12/31/1994 JLB : Removed range parameter (not needed).                                    *\n *=============================================================================================*/\nBulletClass::BulletClass(BulletType id, TARGET target, TechnoClass * payback, int strength, WarheadType warhead, int speed) :\n\tObjectClass(RTTI_BULLET, Bullets.ID(this)),\n\tClass(BulletTypes.Ptr((int)id)),\n\tPayback(payback),\n\tPrimaryFacing(DIR_N),\n\tIsInaccurate(false),\n\tIsToAnimate(false),\n\tIsLocked(true),\n\tTarCom(target),\n\tMaxSpeed(speed),\n\tWarhead(warhead)\n{\n\tStrength = strength;\n\tHeight = FLIGHT_LEVEL;\n}\n\n\n/***********************************************************************************************\n * BulletClass::~BulletClass -- Destructor for bullet objects.                                 *\n *                                                                                             *\n *    The bullet destructor must detect if a dog has been attached to this bullet. If so,      *\n *    then the attached dog must be unlimboed back onto the map. This operation is necessary   *\n *    because, unlike other objects, the dog flies with the bullet it fires.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass::~BulletClass(void)\n{\n\tif (GameActive) {\n\n\t\t/*\n\t\t**\tSPECIAL CASE:\n\t\t**\tThe dog is attached to the dog bullet in a limbo state. When the bullet is\n\t\t**\tdestroyed, the dog must come back out of limbo at the closest location possible to\n\t\t**\tthe bullet.\n\t\t*/\n\t\tif (Payback != NULL && Payback->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)Payback)->Class->IsDog) {\n\n\t\t\tInfantryClass * dog = (InfantryClass *)Payback;\n\t\t\tif (dog) {\n\t\t\t\tbool unlimbo = false;\n\t\t\t\tDirType dogface = dog->PrimaryFacing;\n\t\t\t\tCOORDINATE newcoord = Coord;\n\n\t\t\t\t/*\n\t\t\t\t**\tEnsure that the coordinate, that the dog is to appear at, is legal. If not,\n\t\t\t\t**\tthen find a nearby legal location.\n\t\t\t\t*/\n\t\t\t\tif (Can_Enter_Cell(newcoord) != MOVE_OK) {\n\t\t\t\t\tnewcoord = Map.Nearby_Location(Coord_Cell(newcoord), dog->Class->Speed);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Try to put the dog down where the target impacted.  If we can't\n\t\t\t\t** put it in that cell, then scan through the adjacent cells,\n\t\t\t\t** starting with our current heading, until we find a place where\n\t\t\t\t** we can put him down.  If all 8 adjacent cell checks fail, then\n\t\t\t\t** just delete the dog.\n\t\t\t\t*/\n\t\t\t\tfor (int i = -1; i < 8; i++) {\n\t\t\t\t\tif (i != -1) {\n\t\t\t\t\t\tnewcoord = Adjacent_Cell(Coord, FacingType(i));\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tif (dog->Unlimbo(newcoord, dog->PrimaryFacing)) {\n\t\t\t\t\t\tdog->Mark(MARK_DOWN);\n\t\t\t\t\t\tdog->Do_Action(DO_DOG_MAUL, true);\n\t\t\t\t\t\tif (dog->WasSelected) {\n\t\t\t\t\t\t\tdog->Select();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tScenarioInit--;\n\n\t\t\t\t\t\tunlimbo = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t}\n\n\t\t\t\tPayback = 0;\n\n\t\t\t\tif (!unlimbo) {\n\t\t\t\t\tdelete dog;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tBulletClass::Limbo();\n\t}\n\n\tClass=0;\n\tPayback=0;\n}\n\n\n/***********************************************************************************************\n * BulletClass::new -- Allocates memory for bullet object.                                     *\n *                                                                                             *\n *    This function will \"allocate\" a block of memory for a bullet object.                     *\n *    This memory block is merely lifted from a fixed pool of blocks.                          *\n *                                                                                             *\n * INPUT:   size  -- The size of the memory block needed.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an available bullet object block.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * BulletClass::operator new(size_t )\n{\n\tvoid * ptr = Bullets.Allocate();\n\tif (ptr) {\n\t\t((BulletClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * BulletClass::delete -- Bullet memory delete.                                                *\n *                                                                                             *\n *    Since bullets memory is merely \"allocated\" out of a pool, it never                       *\n *    actually gets deleted.                                                                   *\n *                                                                                             *\n * INPUT:   ptr   -- Generic pointer to bullet object.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((BulletClass *)ptr)->IsActive = false;\n\t}\n\tBullets.Free((BulletClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Occupy_List -- Determines the bullet occupation list.                          *\n *                                                                                             *\n *    This function will determine the cell occupation list and return a pointer to it. Most   *\n *    bullets are small and the list is usually short, but on occasion, it can be a list that  *\n *    rivals the size of regular vehicles.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cell offset list that covers all the cells a bullet  *\n *          is over.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   01/05/1995 JLB : Handles projectiles with altitude.                                       *\n *=============================================================================================*/\nshort const * BulletClass::Occupy_List(bool) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tSuper-gigundo units use the >= 64 coord spillage list logic.\n\t*/\n\tif (Class->IsGigundo) {\n\t\tstatic short _list[] = {\n\t\t\t-1, 0, 1,\n\t\t\tMAP_CELL_W*1-1, MAP_CELL_W*1, MAP_CELL_W*1+1,\n\t\t\t-MAP_CELL_W*1-1, -MAP_CELL_W*1, -MAP_CELL_W*1+1,\n\t\t\tMAP_CELL_W*2-1, MAP_CELL_W*2, MAP_CELL_W*2+1,\n\t\t\t-MAP_CELL_W*2-1, -MAP_CELL_W*2, -MAP_CELL_W*2+1,\n\t\t\t-MAP_CELL_W*3-1, -MAP_CELL_W*3, -MAP_CELL_W*3+1,\n\t\t\tREFRESH_EOL\n\t\t};\n\t\treturn(_list);\n//\t\treturn(Coord_Spillage_List(Coord, 64));\n\t}\n\n\t/*\n\t**\tFlying units need a special adjustment to the spillage list to take into account\n\t**\tthat the bullet imagery and the shadow are widely separated.\n\t*/\n\tif (Height > 0) {\n\t\tstatic short _list[25];\n\t\tconst short * ptr = Coord_Spillage_List(Coord, 5);\n\t\tint index = 0;\n\t\tCELL cell1 = Coord_Cell(Coord);\n\n\t\twhile (ptr[index] != REFRESH_EOL) {\n\t\t\t_list[index] = ptr[index];\n\t\t\tindex++;\n\t\t}\n\n\t\tCOORDINATE coord = Coord_Move(Coord, DIR_N, Height);\n\t\tCELL cell2 = Coord_Cell(coord);\n\t\tptr = Coord_Spillage_List(coord, 5);\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\t_list[index++] = *ptr + (cell2 - cell1);\n\t\t\tptr++;\n\t\t}\n\t\t_list[index] = REFRESH_EOL;\n\t\treturn(_list);\n\t}\n\n\treturn(Coord_Spillage_List(Coord, 10));\n}\n\n\n/***********************************************************************************************\n * BulletClass::Mark -- Performs related map refreshing under bullet.                          *\n *                                                                                             *\n *    This routine marks the objects under the bullet so that they will                        *\n *    be redrawn. This is necessary as the bullet moves -- objects under                       *\n *    its path need to be restored.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Mark(MarkType mark)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (!Class->IsInvisible) {\n\t\t\tMap.Refresh_Cells(Coord_Cell(Coord), Occupy_List());\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::AI -- Logic processing for bullet.                                             *\n *                                                                                             *\n *    This routine will perform all logic (flight) logic on the bullet.                        *\n *    Primarily this is motion, fuse tracking, and detonation logic. Call                      *\n *    this routine no more than once per bullet per game tick.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::AI(void)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tCOORDINATE\tcoord;\n\n\tObjectClass::AI();\n\n\tif (!IsActive) return;\n\n\t/*\n\t**\tBallistic objects are handled here.\n\t*/\n\tbool forced = false;\t\t\t// Forced explosion.\n\tif ((Class->IsArcing || Class->IsDropping) && !IsFalling) {\n\t\tforced = true;\n\t}\n\n\t/*\n\t**\tHoming projectiles constantly change facing to face toward the target but\n\t**\tthey only do so every other game frame (improves game speed and makes\n\t**\tmissiles not so deadly).\n\t*/\n\tif ((Frame & 0x01) && Class->ROT != 0 && Target_Legal(TarCom)) {\n\t\tPrimaryFacing.Set_Desired(Direction256(Coord, ::As_Coord(TarCom)));\n\t}\n\n\t/*\n\t**\tMove the projectile forward according to its speed\n\t**\tand direction.\n\t*/\n\tcoord = Coord;\n\tif (Class->IsFlameEquipped) {\n\t\tif (IsToAnimate) {\n\t\t\tif (stricmp(Class->GraphicName, \"FB1\") == 0) {\n\t\t\t\tnew AnimClass(ANIM_FBALL_FADE, coord, 1);\n\t\t\t} else {\n\t\t\t\tnew AnimClass(ANIM_SMOKE_PUFF, coord, 1);\n\t\t\t}\n\t\t}\n\t\tIsToAnimate = !IsToAnimate;\n\t}\n\n\t/*\n\t**\tHandle any body rotation at this time. This process must\n\t**\toccur every game fame in order to achieve smooth rotation.\n\t*/\n\tif (PrimaryFacing.Is_Rotating()) {\n\t\tPrimaryFacing.Rotation_Adjust(Class->ROT);\n\t}\n\tswitch (Physics(coord, PrimaryFacing)) {\n\t\t/*\n\t\t**\tWhen a projectile reaches the edge of the world, it\n\t\t**\tvanishes from existence -- presumed to explode off\n\t\t**\tmap.\n\t\t*/\n\t\tcase IMPACT_EDGE:\n\t\t\tMark();\n\t\t\tif (Payback != NULL && Class->Type == BULLET_GPS_SATELLITE) {\n\t\t\t\t\n\t\t\t\tbool reveal = false;\n\t\t\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\tif (Payback->House == PlayerPtr) {\n\t\t\t\t\t\treveal = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Payback->House->IsHuman) {\n\t\t\t\t\t\treveal = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (reveal) {\n\t\t\t\t\tif (!Map.Is_Radar_Active()) {\n\t\t\t\t\t\tMap.Radar_Activate(1);\n\t\t\t\t\t}\n\t\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\tMap.Map_Cell(cell, Payback->House);\n\t\t\t\t\t}\n\t\t\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t\tPayback->House->IsGPSActive = true;\n\t\t\t\tPayback->House->IsVisionary = true;\n\t\t\t}\n#ifdef OBSOLETE\n\t\t\t/*\n\t\t\t** Hack: If it's the artificial nukes, don't let the bullets come down (as\n\t\t\t** they're the only ones that blow up).  We know it's artificial if you're\n\t\t\t** at tech level 10 or below, because you can't build the nuclear silo until\n\t\t\t** tech level 15 or so.\n\t\t\t*/\n\t\t\tif (Payback != NULL && Class->Type == BULLET_NUKE_UP && Payback->House->Control.TechLevel <= 10) {\n\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(Payback->House->NukeDest), Payback, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\tif (bullet) {\n\t\t\t\t\tint celly = Cell_Y(Payback->House->NukeDest);\n\t\t\t\t\tcelly -= 15;\n\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(Payback->House->NukeDest), celly));\n\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tdelete this;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase IMPACT_NONE:\n\n\t\t/*\n\t\t**\tThe projectile has moved. Check its fuse. If detonation\n\t\t**\tis signaled, then do so. Otherwise, just move.\n\t\t*/\n\t\tcase IMPACT_NORMAL:\n\t\t\tMark();\n//\t\t\tif(Class->Type == BULLET_NUKE_DOWN) {\n//\t\t\t\tRender(true);\n//\t\t\t}\n\t\t\tif (Class->Type == BULLET_NUKE_UP) {\n\t\t\t\tif (Payback != NULL) {\n\t\t\t\t\tif (Distance(Payback->As_Target()) > 0x0C00) {\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tCoord = coord;\n\n\t\t\t/*\n\t\t\t**\tSee if the bullet should be forced to explode now in spite of what\n\t\t\t**\tthe fuse would otherwise indicate. Maybe the bullet hit a wall?\n\t\t\t*/\n\t\t\tif (!forced) {\n\t\t\t\tforced = Is_Forced_To_Explode(Coord);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the bullet is not to explode, then perform normal flight\n\t\t\t**\tmaintenance (usually nothing). Otherwise, explode and then\n\t\t\t**\tdelete the bullet.\n\t\t\t*/\n\t\t\tif (!forced && (Class->IsDropping || !Fuse_Checkup(Coord))) {\n\t\t\t\t/*\n\t\t\t\t**\tCertain projectiles lose strength when they travel.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsDegenerate && Strength > 5) {\n\t\t\t\t\tStrength--;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tBullet_Explodes(forced);\n\t\t\t\tdelete this;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n}\n\n\n/***********************************************************************************************\n * BulletClass::Shape_Number -- Fetches the shape number for the bullet object.                *\n *                                                                                             *\n *    Use this routine to fetch a shape number to use for this bullet object.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number to use when drawing this bullet.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint BulletClass::Shape_Number(void) const\n{\n\tint shapenum = 0;\n\n\tif (!Class->IsFaceless) {\n\t\tshapenum = UnitClass::BodyShape[Dir_To_32(PrimaryFacing)];\n\t}\n\n\t/*\n\t**\tFor tumbling projectiles, fetch offset stage.\n\t*/\n\tif (Class->Tumble > 0) {\n\t\tshapenum += (long)Frame % Class->Tumble;\n\t}\n\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Draw_It -- Displays the bullet at location specified.                          *\n *                                                                                             *\n *    This routine displays the bullet visual at the location specified.                       *\n *                                                                                             *\n * INPUT:   x,y   -- The center coordinate to render the bullet at.                            *\n *                                                                                             *\n *          window   -- The window to clip to.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a window clipping parameter.                                       *\n *   01/08/1995 JLB : Handles translucent colors if necessary.                                 *\n *=============================================================================================*/\nvoid BulletClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain projectiles aren't visible. This includes small bullets (which are actually\n\t**\tinvisible) and flame thrower flames (which are rendered as an animation instead of a projectile).\n\t*/\n\tif (Class->IsInvisible) return;\n\n\t/*\n\t**\tIf there is no shape loaded for this object, then\n\t**\tit obviously can't be rendered -- just bail.\n\t*/\n\tvoid const * shapeptr = Get_Image_Data();\n\tif (shapeptr == NULL) return;\n\n\t/*\n\t**\tGet the basic shape number for this projectile.\n\t*/\n\tint shapenum = Shape_Number();\n\n\t/*\n\t**\tFor flying projectiles, draw the shadow and adjust the actual projectile body\n\t**\trender position.\n\t*/\n\tif (Height > 0 && Class->IsShadow) {\n\n\t\tif (Class->IsParachuted) {\n\t\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\t\tCC_Draw_Shape(this, AnimTypeClass::As_Reference(ANIM_PARA_BOMB).Get_Image_Data(), 1, x+Lepton_To_Pixel(Height/2), y+10, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::UnitShadow);\n\t\t} else {\n\t\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\t\tCC_Draw_Shape(this, shapeptr, shapenum, x, y, window, SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::UnitShadow);\n\t\t}\n\t\ty -= Lepton_To_Pixel(Height);\n\t}\n\n\t/*\n\t**\tDraw the main body of the projectile.\n\t*/\n\tShapeFlags_Type flags = SHAPE_NORMAL;\n\tif (Class->IsTranslucent) {\n\t\tflags = SHAPE_GHOST;\n\t}\n\tif (Class->IsSubSurface) \n\t{\n\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\tCC_Draw_Shape(this, shapeptr, shapenum, x, y, window, flags|SHAPE_PREDATOR|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_FADING, NULL, DisplayClass::FadingShade);\n\t} else {\n\t\t// Add 'this' parameter to call new shape draw intercept. ST - 5/22/2019\n\t\tCC_Draw_Shape(this, shapeptr, shapenum, x, y, window, flags|SHAPE_CENTER|SHAPE_WIN_REL, NULL, DisplayClass::UnitShadow);\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletClass::Init -- Clears the bullets array for scenario preparation.                     *\n *                                                                                             *\n *    This routine will zero out the bullet tracking list and object array in preparation for  *\n *    the start of a new scenario. All bullets cease to exists after this function is          *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Init(void)\n{\n\tBullets.Free_All();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Detach -- Removes specified target from this bullet's targeting system.        *\n *                                                                                             *\n *    When an object is removed from the game system, it must be removed all targeting and     *\n *    tracking systems as well. This routine is used to remove the specified object from the   *\n *    bullet. If the object isn't part of this bullet's tracking system, then no action is     *\n *    performed.                                                                               *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from this tracking system.                        *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Detach(TARGET target, bool all)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\tObjectClass * obj = As_Object(target);\n\tif (Payback != NULL && obj == Payback) {\n\n\t\t/*\n\t\t** If we're being called as a result of the dog that fired us being put\n\t\t** in limbo, then don't detach.  If for any other reason, detach.\n\t\t*/\n\t\tif (Payback->What_Am_I() != RTTI_INFANTRY || !((InfantryClass *)Payback)->Class->IsDog) {\n\t\t\tPayback = 0;\n\t\t}\n\t}\n\n\tif (all && target == TarCom) {\n\t\tTarCom = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * BulletClass::Unlimbo -- Transitions a bullet object into the game render/logic system.      *\n *                                                                                             *\n *    This routine is used to take a bullet object that is in limbo and transition it to the   *\n *    game system. A bullet object so transitioned, will be drawn and logic processing         *\n *    performed. In effect, it comes into existence.                                           *\n *                                                                                             *\n * INPUT:   coord -- The location where the bullet object is to appear.                        *\n *                                                                                             *\n *          dir   -- The initial facing for the bullet object.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the unlimbo successful?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tTry to unlimbo the bullet as far as the base class is concerned. Use the already\n\t**\tset direction and strength if the \"punt\" values were passed in. This allows a bullet\n\t**\tto be setup prior to being launched.\n\t*/\n\tif (!Class->IsHigh) {\n\t\tHeight = 0;\n\t}\n\tif (ObjectClass::Unlimbo(coord)) {\n\t\tMap.Remove(this, In_Which_Layer());\n\n\t\tCOORDINATE tcoord = As_Coord(TarCom);\n\n\t\t/*\n\t\t**\tHoming projectiles (missiles) do NOT override facing. They just fire in the\n\t\t**\tdirection specified and let the chips fall where they may.\n\t\t*/\n\t\tif (Class->ROT == 0 && !Class->IsDropping) {\n\t\t\tdir = Direction(tcoord);\n\t\t}\n\n\t\t/*\n\t\t**\tPossibly adjust the target if this projectile is inaccurate. This occurs whenever\n\t\t**\tcertain weapons are trained upon targets they were never designed to attack. Example: when\n\t\t**\tturrets or anti-tank missiles are fired at infantry. Indirect\n\t\t**\tfire is inherently inaccurate.\n\t\t*/\n\t\tif (IsInaccurate || Class->IsInaccurate ||\n\t\t\t((Is_Target_Cell(TarCom) || Is_Target_Infantry(TarCom)) && (Warhead == WARHEAD_AP || Class->IsFueled))) {\n\n\t\t\t/*\n\t\t\t**\tInaccuracy for low velocity or homing projectiles manifests itself as a standard\n\t\t\t**\tCircular Error of Probability (CEP) algorithm. High speed projectiles usually\n\t\t\t**\tjust overshoot the target by extending the straight line flight.\n\t\t\t*/\n\t\t\tif (/*Class->ROT != 0 ||*/ Class->IsArcing) {\n\t\t\t\tint scatterdist = (::Distance(coord, tcoord)/16)-0x0040;\n\t\t\t\tscatterdist = min(scatterdist, Rule.HomingScatter);\n\t\t\t\tscatterdist = max(scatterdist, 0);\n\n\t\t\t\tdir = (DirType)((dir + (Random_Pick(0, 10)-5)) & 0x00FF);\n\t\t\t\ttcoord = Coord_Scatter(tcoord, Random_Pick(0, scatterdist));\n\t\t\t} else {\n\t\t\t\tint scatterdist = (::Distance(coord, tcoord)/16)-0x0040;\n\t\t\t\tscatterdist = min(scatterdist, Rule.BallisticScatter);\n\t\t\t\tscatterdist = max(scatterdist, 0);\n\t\t\t\ttcoord = Coord_Move(tcoord, dir, Random_Pick(0, scatterdist));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFor very fast and invisible projectiles, just make the projectile exist at the target\n\t\t**\tlocation and dispense with the actual flight.\n\t\t*/\n\t\tif (MaxSpeed == MPH_LIGHT_SPEED && Class->IsInvisible) {\n\t\t\tCoord = tcoord;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the range equal to either the class defined range or the calculated\n\t\t**\tnumber of game frames it would take for the projectile to reach the target.\n\t\t*/\n\t\tint range = 0xFF;\n\t\tif (!Class->IsDropping) {\n\t\t\trange = (::Distance(tcoord, Coord) / MaxSpeed) + 4;\n\t\t}\n\n\t\t/*\n\t\t**\tProjectile speed is usually the default value for that projectile, but\n\t\t**\tcertain projectiles alter speed according to the distance to the\n\t\t**\ttarget.\n\t\t*/\n\t\tint speed = MaxSpeed;\n\t\tif (speed == MPH_LIGHT_SPEED) speed = MPH_IMMOBILE;\n\t\tif (Class->IsArcing) {\n\t\t\tspeed = MaxSpeed + (Distance(tcoord) / 32);\n\n\t\t\t/*\n\t\t\t**\tSet minimum speed (i.e., distance) for arcing projectiles.\n\t\t\t*/\n\t\t\tspeed = max(speed, 25);\n\t\t}\n\t\tif (!Class->IsDropping) {\n\t\t\tFly_Speed(255, (MPHType)speed);\n\t\t}\n\n\t\t/*\n\t\t**\tArm the fuse.\n\t\t*/\n\t\tArm_Fuse(Coord, tcoord, range, ((As_Aircraft(TarCom)!=0) ? 0 : Class->Arming));\n\n\t\t/*\n\t\t**\tProjectiles that make a ballistic flight to impact point must determine a\n\t\t**\tvertical component for the projectile launch. This is crudely simulated\n\t\t**\tby biasing ground speed according to target distance and then giving\n\t\t**\tenough vertical velocity to keep the projectile airborne for the\n\t\t**\tdesired amount of time. The mathematically correct solution would be to\n\t\t**\tcalculate launch angle (given fixed projectile velocity) and then derive\n\t\t**\tthe vertical and horizontal components. That solution would require a\n\t\t**\tsquare root and an arcsine lookup table. OUCH!\n\t\t*/\n\t\tRiser = 0;\n\t\tif (Class->IsArcing) {\n\t\t\tIsFalling = true;\n\t\t\tHeight = 1;\n\t\t\tRiser = ((Distance(tcoord)/2) / (speed+1)) * Rule.Gravity;\n\t\t\tRiser = max(Riser, 10);\n\t\t}\n\t\tif (Class->IsDropping) {\n\t\t\tIsFalling = true;\n\t\t\tHeight = FLIGHT_LEVEL;\n//\t\t\tHeight = Pixel_To_Lepton(24);\n\t\t\tRiser = 0;\n\t\t\tif (Class->IsParachuted) {\n\t\t\t\tAnimClass * anim = new AnimClass(ANIM_PARA_BOMB, Target_Coord());\n//\t\t\t\tAnimClass * anim = new AnimClass(ANIM_PARACHUTE, Target_Coord());\n\t\t\t\tif (anim) {\n\t\t\t\t\tanim->Attach_To(this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMap.Submit(this, In_Which_Layer());\n\n\t\tPrimaryFacing = dir;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Target_Coord -- Fetches coordinate to use when firing on this object.          *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that should be used when firing at the object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BulletClass::Target_Coord(void) const\n{\n\tassert(Bullets.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(Coord_Add(XY_Coord(0, -Height), Coord));\n}\n\n\n/***********************************************************************************************\n * BulletClass::Sort_Y -- Sort coordinate for bullet rendering.                                *\n *                                                                                             *\n *    This will return the coordinate to use when sorting this bullet in the display list.     *\n *    Typically, this only occurs for bullets in the ground layer. Since bullets are to be     *\n *    seen a bit more than the normal sorting order would otherwise imply, bias the sort       *\n *    value such that bullets will tend to be drawn on top of the objects.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use when sorting this bullet in the display list.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE BulletClass::Sort_Y(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord_Move(Coord, DIR_S, CELL_LEPTON_H/2));\n}\n\n\n/***********************************************************************************************\n * BulletClass::In_Which_Layer -- Fetches the layer that the bullet resides in.                *\n *                                                                                             *\n *    This examines the bullet to determine what rendering layer it should be in. The          *\n *    normal logic applies unless this is a torpedo. A torpedo is always in the surface        *\n *    layer.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the render layer that this bullet should reside in.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType BulletClass::In_Which_Layer(void) const\n{\n\tif (Class->IsSubSurface) {\n\t\treturn(LAYER_SURFACE);\n\t}\n\treturn(ObjectClass::In_Which_Layer());\n}\n\n\n/***********************************************************************************************\n * BulletClass::Is_Forced_To_Explode -- Checks if bullet should explode NOW.                   *\n *                                                                                             *\n *    This routine will examine the bullet and where it is travelling in order to determine    *\n *    if it should prematurely explode. Typical of this would be when a bullet hits a wall     *\n *    or a torpedo hits a ship -- regardless of where the projectile was originally aimed.     *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to place the bullet at presuming it is forced to       *\n *                   explode and a modification of the bullet's coordinate is needed.          *\n *                   Otherwise, the coordinate is not modified.                                *\n *                                                                                             *\n * OUTPUT:  bool; Should the bullet explode now?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool BulletClass::Is_Forced_To_Explode(COORDINATE & coord) const\n{\n\tcoord = Coord;\n\tCellClass const * cellptr = &Map[coord];\n\n\t/*\n\t**\tCheck for impact on a wall or other high obstacle.\n\t*/\n\tif (!Class->IsHigh && cellptr->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(cellptr->Overlay).IsHigh) {\n\t\tcoord = Cell_Coord(Coord_Cell(coord));\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tCheck to make sure that underwater projectiles (torpedoes) will not\n\t**\ttravel in anything but water.\n\t*/\n\tif (Class->IsSubSurface) {\n\t\tint d = ::Distance(Coord_Fraction(coord), XY_Coord(CELL_LEPTON_W/2, CELL_LEPTON_W/2));\n\t\tif (cellptr->Land_Type() != LAND_WATER || (d < CELL_LEPTON_W/3 && cellptr->Cell_Techno() != NULL && cellptr->Cell_Techno() != Payback)) {\n\n\t\t\t/*\n\t\t\t**\tForce explosion to be at center of techno object if one is present.\n\t\t\t*/\n\t\t\tif (cellptr->Cell_Techno() != NULL) {\n\t\t\t\tcoord = cellptr->Cell_Techno()->Target_Coord();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tHowever, if the torpedo was blocked by a bridge, then force the\n\t\t\t**\ttorpedo to explode on top of that bridge cell.\n\t\t\t*/\n\t\t\tif (cellptr->Is_Bridge_Here()) {\n\t\t\t\tcoord = Coord_Snap(coord);\n\t\t\t}\n\n\t\t\treturn(true);\n\t\t}\n\t}\n\n\t/*\n\t**\tBullets are generally more effective when they are fired at aircraft.\n\t*/\n\tif (Class->IsAntiAircraft && As_Aircraft(TarCom) && Distance(TarCom) < 0x0080) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tNo reason for forced explosion was detected, so return 'false' to\n\t**\tindicate that no forced explosion is required.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * BulletClass::Bullet_Explodes -- Performs bullet explosion logic.                            *\n *                                                                                             *\n *    This handles the exploding bullet action. It will generate the animation and the         *\n *    damage as necessary.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The bullet should be deleted after this routine is called.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid BulletClass::Bullet_Explodes(bool forced)\n{\n\t/*\n\t**\tWhen the target is reached, explode and do the damage\n\t**\trequired of it. For homing objects, don't force the explosion to\n\t**\tmatch the target position. Non-homing projectiles adjust position so\n\t**\tthat they hit the target. This compensates for the error in line of\n\t**\tflight logic.\n\t*/\n\tif ( (Payback != NULL && Payback->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)Payback)->Class->IsDog) ||\n\t\t(!forced && !Class->IsArcing && Class->ROT == 0 && Fuse_Target())) {\n\t\tCoord = Fuse_Target();\n\t}\n\n\t/*\n\t**\tNon-aircraft targets apply damage to the ground.\n\t*/\n\tif (!Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->In_Which_Layer() == LAYER_GROUND) {\n\t\tExplosion_Damage(Coord, Strength, Payback, Warhead);\n\t\tif (!IsActive) return;\n\n\t} else {\n\n\t\t/*\n\t\t**\tSpecial damage apply for SAM missiles. This is the only way that missile\n\t\t**\tdamage affects the aircraft target.\n\t\t*/\n\t\tif (Distance(TarCom) < 0x0080) {\n\t\t\tAircraftClass * object = As_Aircraft(TarCom);\n\n\t\t\tint str = Strength;\n\t\t\tif (object) object->Take_Damage(str, 0, Warhead, Payback);\n\t\t}\n\t}\n\n\t/*\n\t**\tFor projectiles that are invisible while travelling toward the target,\n\t**\tallow scatter effect for the impact animation.\n\t*/\n\tif (Class->IsInvisible) {\n\t\tCoord = Coord_Scatter(Coord, 0x0020);\n\t}\n\n\t/*\n\t**\tFetch the land type that the explosion will be upon. Special case for\n\t**\tflying aircraft targets, their land type will be LAND_NONE.\n\t*/\n\tCellClass const * cellptr = &Map[Coord];\n\tLandType land = cellptr->Land_Type();\n\tif (Is_Target_Aircraft(TarCom) && As_Aircraft(TarCom)->In_Which_Layer() == LAYER_TOP) {\n\t\tland = LAND_NONE;\n\t}\n\n\tAnimType anim = Combat_Anim(Strength, Warhead, land);\n\n\t/*\n\t** If it's a water explosion that's going to play, don't play it\n\t** if its cell is the same as the center cell of the target ship.\n\t*/\n\tif (anim >= ANIM_WATER_EXP1 && anim <= ANIM_WATER_EXP3 && Is_Target_Vessel(TarCom)) {\n\t\tif (Coord_Cell(Coord) == Coord_Cell(As_Vessel(TarCom)->Center_Coord())) {\n\t\t\tanim = (AnimType) (ANIM_VEH_HIT1 + (anim - ANIM_WATER_EXP1));\n\t\t}\n\t}\n\n\tif (anim != ANIM_NONE) {\n\t\tAnimClass * aptr = new AnimClass(anim, Coord);\n\t\tif (aptr) {\n\t\t\taptr->Sort_Above(TarCom);\n\t\t}\n\t\t/*\n\t\t** Special case trap: if they're making the nuclear explosion,\n\t\t** and no anim is available, force the nuclear damage anyway\n\t\t** because nuke damage is done in the middle of the animation\n\t\t** and if there's no animation, there won't be any damage.\n\t\t*/\n\t\tif (!aptr && anim == ANIM_ATOM_BLAST) {\n\t\t\tGlyphX_Debug_Print(\"FAILED to create ANIM_ATOM_BLAST\");\n\t\t\tHousesType house = HOUSE_NONE;\n\t\t\tif (Payback) {\n\t\t\t\thouse = Payback->House->Class->House;\n\t\t\t}\n\t\t\tAnimClass::Do_Atom_Damage(house, Coord_Cell(Coord));\n\t\t}\n\n\t\t// MBL 05.20.2020\n\t\t// Fix for Nuke or Atom Bomb killing structures and units during animation sequence and not getting kills tracked\n\t\t// Per https://jaas.ea.com/browse/TDRA-6610\n\t\t//\n\t\telse if (aptr && anim == ANIM_ATOM_BLAST && aptr->OwnerHouse == HOUSE_NONE) {\n\t\t\tif (Payback && Payback->House && Payback->House->Class) {\n\t\t\t\taptr->Set_Owner(Payback->House->Class->House);\n\t\t\t}\n\t\t}\n\t}\n\n//\t\t\t\tif (Payback && Payback->House == PlayerPtr && stricmp(Class->Name(), \"GPSSATELLITE\") == 0) {\n\tif (Payback && Class->Type == BULLET_GPS_SATELLITE) {\n\t\t\n\t\tbool reveal = false;\n\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tif (Payback->House == PlayerPtr) {\n\t\t\t\treveal = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (Payback->House->IsHuman) {\n\t\t\t\treveal = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (reveal) {\n\t\t\tif (!Map.Is_Radar_Active()) {\n\t\t\t\tMap.Radar_Activate(1);\n\t\t\t}\n\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tMap.Map_Cell(cell, Payback->House);\n\t\t\t}\n\t\t\tMap.RadarClass::Flag_To_Redraw(true);\n\t\t}\n//\t\t\t\t\tSound_Effect(VOC_SATTACT2);\n\t\tPayback->House->IsGPSActive = true;\n\t\tPayback->House->IsVisionary = true;\n\t}\n}"
  },
  {
    "path": "REDALERT/BULLET.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/BULLET.H 2     3/06/97 1:46p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : BULLET.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef BULLET_H\n#define BULLET_H\n\n#include \"object.h\"\n#include\t\"fly.h\"\n#include\t\"fuse.h\"\n\n\nclass BulletClass :\tpublic ObjectClass,\n\t\t\t\t\t\t\tpublic FlyClass,\n\t\t\t\t\t\t\tpublic FuseClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis specifies exactly what kind of bullet this is. All of the static attributes\n\t\t**\tfor this bullet is located in the BulletTypeClass pointed to by this variable.\n\t\t*/\n\t\tCCPtr<BulletTypeClass> Class;\n\n\tprivate:\n\t\t/*\n\t\t**\tRecords who sent this \"present\" so that an appropriate \"thank you\" can\n\t\t**\tbe returned.\n\t\t*/\n\t\tTechnoClass * Payback;\n\n\t\t/*\n\t\t**\tThis is the facing that the projectile is travelling.\n\t\t*/\n\t\tFacingClass PrimaryFacing;\n\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tBulletClass(BulletType id, TARGET target, TechnoClass * Payback, int strength, WarheadType warhead, int speed);\n#ifdef FIXIT_MULTI_SAVE\n\t\tBulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x), PrimaryFacing(x) {};\n#else\n\t\tBulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x) {};\n#endif\n\t\tvirtual ~BulletClass(void);\n\t\toperator BulletType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tbool Is_Forced_To_Explode(COORDINATE & coord) const;\n\t\tvoid Bullet_Explodes(bool forced);\n\t\tint Shape_Number(void) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual void Assign_Target(TARGET target) {TarCom = target;};\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\t\tvirtual void AI(void);\n\t\tvirtual short const * Occupy_List(bool = false) const;\n\t\tvirtual short const * Overlap_List(void) const {return Occupy_List(false);};\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tIf this bullet is forced to be inaccurate because of some outside means. A tank\n\t\t**\tfiring while moving is a good example.\n\t\t*/\n\t\tunsigned IsInaccurate:1;\n\n\tprivate:\n\t\t// Crude animation flag.\n\t\tunsigned IsToAnimate:1;\n\n\t\t/*\n\t\t** Is this missile allowed to come in from out of bounds?\n\t\t*/\n\t\tunsigned IsLocked:1;\n\n\t\t/*\n\t\t**\tThis is the target of the projectile. It is especially significant for those projectiles\n\t\t**\tthat home in on a target.\n\t\t*/\n\t\tTARGET TarCom;\n\n\t\t/*\n\t\t**\tThe speed of this projectile.\n\t\t*/\n\t\tint MaxSpeed;\n\n\t\t/*\n\t\t**\tThe warhead of this projectile.\n\t\t*/\n\t\tWarheadType Warhead;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[32];\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CARGO.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CARGO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARGO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : 10/31/94 [JLB]                                               *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CargoClass::Attach -- Add unit to cargo hold.                                             *\n *   CargoClass::Attached_Object -- Determine attached unit pointer.                           *\n *   CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen.              *\n *   CargoClass::Detach_Object -- Removes a unit from the cargo hold.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen.                *\n *                                                                                             *\n *    This routine is used to dump the current cargo value to the monochrome monitor.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CargoClass::Debug_Dump(MonoClass * mono) const\n{\n\tif (How_Many()) {\n\t\tmono->Set_Cursor(63, 3);\n\t\tmono->Printf(\"(%d)%04X\", How_Many(), Attached_Object());\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * CargoClass::Attach -- Add unit to cargo hold.                                               *\n *                                                                                             *\n *    This routine will add the specified unit to the cargo hold. The                          *\n *    unit will chain to any existing units in the hold. The chaining is                       *\n *    in a LIFO order.                                                                         *\n *                                                                                             *\n * INPUT:   object-- Pointer to the object to attach to the cargo hold.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   10/31/94   JLB : Handles chained objects.                                                 *\n *=============================================================================================*/\nvoid CargoClass::Attach(FootClass * object)\n{\n\t/*\n\t**\tIf there is no object, then no action is necessary.\n\t*/\n\tif (object == NULL) return;\n\n\tobject->Limbo();\n\n\t/*\n\t**\tAttach any existing cargo hold object to the end of the list as indicated by the\n\t**\tobject pointer passed into this routine. This is necessary because several objects may\n\t**\tbe attached at one time or several objects may be attached as a result of several calls\n\t**\tto this routine. Either case must be handled properly.\n\t*/\n\tObjectClass * o = object->Next;\n\twhile (o != NULL) {\n\t\tif (o->Next == (void*)NULL) break;\n\t\to = o->Next;\n\t}\n\tif (o != NULL) {\n\t\to->Next = CargoHold;\n\t} else {\n\t\tobject->Next = CargoHold;\n\t}\n\n\t/*\n\t**\tFinally, assign the object pointer as the first object attached to this cargo hold.\n\t*/\n\tCargoHold = object;\n\tQuantity = 0;\n\tobject = CargoHold;\n\twhile (object != NULL) {\n\t\tQuantity++;\n\t\tobject = (FootClass *)(ObjectClass *)object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CargoClass::Detach_Object -- Removes a unit from the cargo hold.                            *\n *                                                                                             *\n *    This routine will take a unit from the cargo hold and extract it.                        *\n *    The unit extracted is the last unit added to the hold. If there                          *\n *    is no unit in the hold or the occupant is not a unit, then NULL is                       *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the unit that has been extracted.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles generic object types.                                            *\n *=============================================================================================*/\nFootClass * CargoClass::Detach_Object(void)\n{\n\tTechnoClass * unit = Attached_Object();\n\n\tif (unit != NULL) {\n\t\tCargoHold = (FootClass *)(ObjectClass *)unit->Next;\n\t\tunit->Next = 0;\n\t\tQuantity--;\n\t}\n\treturn((FootClass *)unit);\n}\n\n\n/***********************************************************************************************\n * CargoClass::Attached_Object -- Determine attached unit pointer.                             *\n *                                                                                             *\n *    This routine will return with a pointer to the attached unit if one                      *\n *    is present. One would need to know this if this is a transport                           *\n *    unit and it needs to unload.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the attached unit. If there is no                             *\n *          attached unit, then return NULL.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles generic object types.                                            *\n *=============================================================================================*/\nFootClass * CargoClass::Attached_Object(void) const\n{\n\tif (Is_Something_Attached()) {\n\t\treturn(CargoHold);\n\t}\n\treturn(NULL);\n}\n\n\n"
  },
  {
    "path": "REDALERT/CARGO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CARGO.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARGO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CARGO_H\n#define CARGO_H\n\nclass FootClass;\n\n/****************************************************************************\n**\tThis class handles the basic cargo logic.\n*/\nclass CargoClass {\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCargoClass(void) : Quantity(0), CargoHold(0) {};\n\t\tCargoClass(NoInitClass const & ) {};\n\t\t~CargoClass(void) {CargoHold=0;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid AI(void) {};\n\n\t\tint How_Many(void) const {return Quantity;};\n\t\tbool Is_Something_Attached(void) const {return (CargoHold != 0);};\n\t\tFootClass * Attached_Object(void) const;\n\t\tFootClass * Detach_Object(void);\n\t\tvoid Attach(FootClass * object);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the number of objects attached to this cargo hold. For transporter\n\t\t**\tobjects, they might contain more than one object.\n\t\t*/\n\t\tunsigned char Quantity;\n\n\t\t/*\n\t\t**\tThis is the target value of any attached object. A value of zero indicates\n\t\t**\tthat no object is attached.\n\t\t*/\n\t\tFootClass * CargoHold;\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/CARRY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CARRY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARRY.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : May 10, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CarryoverClass::CarryoverClass -- Constructor for carry over objects.                     *\n *   CarryoverClass::Create -- Creates a carried over object.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CarryoverClass::CarryoverClass -- Constructor for carry over objects.                       *\n *                                                                                             *\n *    This is the constructor for a carry over object. Such an object is used to record the    *\n *    object that will be \"carried over\" into a new scenario at some future time.              *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that will be carried over.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCarryoverClass::CarryoverClass(TechnoClass * techno) :\n\tRTTI(RTTI_NONE),\n\tCell(0),\n\tStrength(0),\n\tHouse(HOUSE_NONE)\n{\n\tif (techno) {\n\t\tRTTI = techno->What_Am_I();\n\n\t\tswitch (RTTI) {\n\t\t\tcase RTTI_UNIT:\n\t\t\t\tType.Unit = ((UnitClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tType.Building = ((BuildingClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRY:\n\t\t\t\tType.Infantry = ((InfantryClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\tType.Vessel = ((VesselClass *)techno)->Class->Type;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tHouse = techno->Owner();\n\t\tStrength = techno->Strength;\n\t\tCell = Coord_Cell(techno->Coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * CarryoverClass::Create -- Creates a carried over object.                                    *\n *                                                                                             *\n *    Use this routine to convert a carried over object into an actual object that will be     *\n *    placed on the map.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully created and placed on the map?                   *\n *                                                                                             *\n * WARNINGS:   This routine might not place the object if the old map location was invalid     *\n *             or there are other barriers to the object's creation and placement.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CarryoverClass::Create(void) const\n{\n\tTechnoClass * techno = 0;\n\tTechnoTypeClass const * ttype = 0;\n\n\tswitch (RTTI) {\n\t\tcase RTTI_UNIT:\n\t\t\tttype = &UnitTypeClass::As_Reference(Type.Unit);\n\t\t\ttechno = new UnitClass(Type.Unit, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tttype = &InfantryTypeClass::As_Reference(Type.Infantry);\n\t\t\ttechno = new InfantryClass(Type.Infantry, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tttype = &BuildingTypeClass::As_Reference(Type.Building);\n\t\t\ttechno = new BuildingClass(Type.Building, House);\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tttype = &VesselTypeClass::As_Reference(Type.Vessel);\n\t\t\ttechno = new VesselClass(Type.Vessel, House);\n\t\t\tbreak;\n\t}\n\n\tif (techno) {\n\t\tbool oldscen = ScenarioInit;\n\t\ttechno->Strength = Strength;\n\t\tif (RTTI == RTTI_INFANTRY) {\n\t\t\tScenarioInit = 0;\n\t\t}\n\t\ttechno->Unlimbo(Cell_Coord(Cell));\n\t\tif (RTTI == RTTI_INFANTRY) {\n\t\t\tScenarioInit = oldscen;\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n"
  },
  {
    "path": "REDALERT/CARRY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CARRY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CARRY.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : February 26, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CARRY_H\n#define CARRY_H\n\nclass CarryoverClass : public LinkClass {\n\tpublic:\n\t\tCarryoverClass(TechnoClass * techno = 0);\n\t\tCarryoverClass(NoInitClass const & x) : LinkClass(x) {}\n\n\t\tbool Create(void) const;\n\n\t//protected:\n\t\t/*\n\t\t**\tWhat type of object this is.\n\t\t*/\n\t\tRTTIType RTTI;\n\n\t\t/*\n\t\t**\tThis is the object type that is to be carried over. The exact nature of\n\t\t**\tthis type depends on the RTTI value. Only certain object types are\n\t\t**\trecorded.\n\t\t*/\n\t\tunion {\n\t\t\tStructType Building;\n\t\t\tUnitType Unit;\n\t\t\tInfantryType Infantry;\n\t\t\tVesselType Vessel;\n\t\t} Type;\n\n\t\t/*\n\t\t**\tThe location of the object.\n\t\t*/\n\t\tCELL Cell;\n\n\t\t/*\n\t\t**\tThe strength of the object at the time is was recorded.\n\t\t*/\n\t\tint Strength;\n\n\t\t/*\n\t\t**\tThis is the owner of the object.\n\t\t*/\n\t\tHousesType House;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/CBN_.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/****************************************************************************\n*  Error Constants, in case of values above 10 hexadecimal please call\n*  Marx International, Inc.\n****************************************************************************/\n\n#define PARAM_ERR       0x01\n#define BOX_NOT_FOUND   0x02\n\n#define BOX_CRYPT_ERR   0x03\n#define UNI_CRYPT_ERR   0x04\n#define READ_RAM_ERR    0x05\n#define WRITE_RAM_ERR   0x06\n#define RAM_COUNT_ERR   0x07\n#define BOX_READY_ERR   0x08\n\n\n/****************************************************************************\n*  Constants\n****************************************************************************/\n\n#define CRYPTLENG       32\n#define RAM1LENG        50\n#define RAM2LENG       433\n#define IDEALENG        32\n\n/****************************************************************************\n*  User Functions\n****************************************************************************/\nextern \"C\" {\n\nextern short CbN_BoxReady(unsigned short iPortNr, unsigned char *pcBoxName);\n\nextern short CbN_ReadID1(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID2(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID3(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID4(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID5(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID6(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID7(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadID8(unsigned short iPortNr, unsigned char *pcSCodeId,\n                     unsigned long *plIdReturn);\n\nextern short CbN_ReadSER(unsigned short iPortNr, unsigned char *pcSCodeSer,\n                     unsigned  long *plSerNum);\n\nextern short CbN_ReadRAM1(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned char *pcPasswRam1,unsigned short\n                      iStartAdr,unsigned short iLength, unsigned char *pcOutData);\n\nextern short CbN_ReadRAM2(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned char *pcPasswRam2,unsigned short\n                      iStartAdr,unsigned short iLength, unsigned char *pcOutData);\n\nextern short CbN_WriteRAM1(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned char *pcPasswRam1,unsigned short\n                      iStartAdr,unsigned short iLength,unsigned char *pcOutData);\n\nextern short CbN_WriteRAM2(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned char *pcPasswRam2,unsigned short\n                      iStartAdr,unsigned short iLength,unsigned char *pcOutData);\n\nextern short CbN_IncRAM1(unsigned short iPortNr, unsigned short iIdNr, unsigned char\n                      *pcSCodeId, unsigned char *pcPasswRam1, unsigned short\n                      iCounterAdr, unsigned short *piNewCount);\n\nextern short CbN_DecRAM1(unsigned short iPortNr, unsigned short iIdNr, unsigned char\n                      *pcSCodeId, unsigned char *pcPasswRam1, unsigned short\n                      iCounterAdr, unsigned short *piNewCount);\n\nextern short CbN_IncRAM2(unsigned short iPortNr, unsigned short iIdNr, unsigned char\n                      *pcSCodeId, unsigned char *pcPasswRam2, unsigned short\n                      iCounterAdr, unsigned short *piNewCount);\n\nextern short CbN_DecRAM2(unsigned short iPortNr, unsigned short iIdNr, unsigned char\n                      *pcSCodeId, unsigned char *pcPasswRam2, unsigned short\n                      iCounterAdr, unsigned short *piNewCount);\n\n\nextern short CbN_Decrypt(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned short iSeed, unsigned short iLength,\n                      unsigned char *pcOutData);\n\nextern short CbN_Encrypt(unsigned short iPortNr,unsigned short iIdNr,unsigned char\n                      *pcSCodeId,unsigned short iSeed,unsigned short iLength,\n                      unsigned char *pcOutData);\n\nextern short CbN_IDEA_Encrypt(unsigned short iPortNr, unsigned short iIdNr,\n                           unsigned char *pcSCodeId, unsigned char *pcBuff,\n                           unsigned long lLength);\n\nextern short CbN_IDEA_Decrypt(unsigned short iPortNr, unsigned short iIdNr,\n                           unsigned char *pcSCodeId, unsigned char *pcBuff,\n                           unsigned long lLength);\n\nextern short CbN_IDEA_EncryptP(unsigned short iPortNr, unsigned short iIdNr,\n                           unsigned char *pcSCodeId, unsigned char *pcBuff,\n                           unsigned long lLength, unsigned long lIdeaKey);\n\nextern short CbN_IDEA_DecryptP(unsigned short iPortNr, unsigned short iIdNr,\n                           unsigned char *pcSCodeId, unsigned char *pcBuff,\n                           unsigned long lLength, unsigned long lIdeaKey);\n\nextern short CbN_SetCounterRAM1(unsigned short iPortNr, unsigned short iIdNr,\n                              unsigned char *pcSCodeId, unsigned char\n                              *pcPassRam, unsigned short iAdrCount, unsigned short\n                              iNewCount);\n\nextern short CbN_ReadCounterRAM1(unsigned short iPortNr, unsigned short iIdNr,\n                               unsigned char *pcSCodeId, unsigned char\n                               *pcPassRam, unsigned short iAdrCount, unsigned short\n                               *piCurrentCount);\n\nextern short CbN_SetCounterRAM2(unsigned short iPortNr, unsigned short iIdNr,\n                              unsigned char *pcSCodeId, unsigned char\n                              *pcPassRam, unsigned short iAdrCount, unsigned short\n                              iNewCount);\n\nextern short CbN_ReadCounterRAM2(unsigned short iPortNr, unsigned short iIdNr,\n                               unsigned char *pcSCodeId, unsigned char\n                               *pcPassRam, unsigned short iAdrCount, unsigned short\n                               *piCurrentCount);\n\n}\n\u001a"
  },
  {
    "path": "REDALERT/CCDDE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer - Red Alert                                *\n *                                                                                             *\n *                    File Name : CCDDE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/04/95                                                     *\n *                                                                                             *\n *                  Last Update : August 5th, 1996 [ST]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   C&C's interface to the DDE class                                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * DDE_Callback -- DDE server callback function                                                *\n * DDEServerClass::DDEServerClass -- class constructor                                         *\n * DDEServerClass::Enable -- Enables the DDE callback                                          *\n * DDEServerClass::Disable -- Disables the DDE callback                                        *\n * DDEServerClass::~DDEServerClass -- class destructor                                         *\n * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *\n * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *\n * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *\n * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*\n *                                                                                             *\n * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include <WINDOWS.H>\n#include \"ccdde.h\"\n#include <stdio.h>\n#include <timer.h>\n\nDDEServerClass\tDDEServer;\t\t\t\t//Instance of the DDE Server class\n\nInstance_Class\t*DDE_Class = NULL;\t// pointer for client callback\n\t\t\t\t\t\t\t\t\t\t\t\t// this *must* be called DDE_Class\n\nBOOL RA95AlreadyRunning = FALSE;\t\t//Was there an instance of Red Alert 95 already running when we started?\n\n/*\n** Misc externs so we dont have to include FUNCTION.H\n*/\nextern HWND \t\t\tMainWindow;\nextern TimerClass\tGameTimer;\nextern bool\t\t\tGameTimerInUse;\nextern void \t\t\tWWDebugString (char *string);\n\n\n/***********************************************************************************************\n * DDE_Callback -- DDE server callback function                                                *\n *                                                                                             *\n *   Just acts as a wrapper for the DDEServerClass callback function                           *\n *                                                                                             *\n * INPUT:    ptr to data from client                                                           *\n *           length of data                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:19PM ST : Created                                                               *\n *=============================================================================================*/\nBOOL CALLBACK DDE_Callback (unsigned char *data, long length)\n{\n\treturn (DDEServer.Callback(data, length));\n}\n\n\n\n\n/***********************************************************************************************\n * DDEServerClass::DDEServerClass -- class constructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:20PM ST : Created                                                               *\n *=============================================================================================*/\nDDEServerClass::DDEServerClass(void)\n{\n\tMPlayerGameInfo = NULL;\t\t//Flag that we havnt received a start game info packet yet\n\n\t//DDE_Class = new Instance_Class (\"CONQUER\", \"WCHAT\");\n\tDDE_Class = new Instance_Class (\"REDALERT\", \"WCHAT\");\n\n\tDDE_Class->Enable_Callback( TRUE );\n\tIsEnabled = TRUE;\n\n\tif (DDE_Class->Test_Server_Running(DDE_Class->local_name)){\n\t\tRA95AlreadyRunning = TRUE;\n\t}else{\n\t\t//DDE_Class->Register_Server( DDE_Callback );\t\t\t\t// ST - 5/8/2019\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDEServerClass::Enable -- Enables the DDE callback                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/96 9:44PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Enable(void)\n{\n\tif (!IsEnabled){\n\t\tDDE_Class->Enable_Callback( TRUE );\n\t\tIsEnabled = TRUE;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDEServerClass::Disable -- Disables the DDE callback                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/5/96 9:44PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Disable(void)\n{\n\tif (IsEnabled){\n\t\tDDE_Class->Enable_Callback( FALSE );\n\t\tIsEnabled = FALSE;\n\t}\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * DDEServerClass::~DDEServerClass -- class destructor                                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:20PM ST : Created                                                               *\n *=============================================================================================*/\nDDEServerClass::~DDEServerClass(void)\n{\n\tDelete_MPlayer_Game_Info();\n\tdelete( DDE_Class );\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    data from DDE client                                                              *\n *           length of data                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: Data has length and type as first 2 ints                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:21PM ST : Created                                                               *\n *=============================================================================================*/\nBOOL DDEServerClass::Callback(unsigned char *data, long length)\n{\n\n\t/*\n\t** If the packet length < 0 then this is a special advisory packet\n\t*/\n\tif ( length<0 ) {\n\n\t\tswitch( length ) {\n\n\t\t\tcase\tDDE_ADVISE_CONNECT:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: client connect detected.\");\n\t\t\t\treturn TRUE;\n\n\t\t\tcase\tDDE_ADVISE_DISCONNECT:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: client disconnect detected.\");\n\t\t\t\treturn TRUE;\n\n\t\t\tdefault:\n\t\t\t\tWWDebugString(\"RA95 - DDE advisory: Unknown DDE advise type.\");\n\t\t\t\treturn FALSE;\n\t\t}\n\n\t}else{\n\n\t\t/*\n\t\t** Packet must be at least the length of the packet type & size fields to be valid\n\t\t*/\n\t\tif (length < 2*sizeof(int)) {\n\t\t\tWWDebugString (\"RA95 - Received invalid packet.\");\n\t\t\treturn (FALSE);\n\t\t}\n\n\t\t/*\n\t\t** Find out what kind of packet this is and its length.\n\t\t*/\n\t\tint *packet_pointer = (int *)data;\n\t\tint  actual_length = ntohl(*packet_pointer++);\n\t\tint  packet_type =  ntohl(*packet_pointer++);\n\n\t\t/*\n\t\t** Strip the ID int from the start of the packet\n\t\t*/\n\t\tdata   += 2*sizeof (int);\n\t\tlength -= 2*sizeof (int);\n\t\tactual_length -= 2*sizeof (int);\n\n\t\t/*\n\t\t** Take the appropriate action for the packet type\n\t\t*/\n\t\tswitch ( packet_type ){\n\n\t\t\t/*\n\t\t\t** This is a packet with the info required for starting a new internet game. This is really\n\t\t \t* just C&CSPAWN.INI sent from WChat instead of read from disk.\n\t\t\t*/\n\t\t\tcase DDE_PACKET_START_MPLAYER_GAME:\n\t\t\t\tWWDebugString(\"RA95 - Received start game packet.\");\n\t\t\t\tDelete_MPlayer_Game_Info();\n\t\t\t\tMPlayerGameInfo = new char [actual_length + 1];\n\t\t\t\tmemcpy (MPlayerGameInfo, data, actual_length);\n\t\t\t\t*(MPlayerGameInfo + actual_length) = 0;\t\t//Terminator in case we treat it as a string\n\t\t\t\tMPlayerGameInfoLength = actual_length;\n\t\t\t\tLastHeartbeat = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase DDE_TICKLE:\n\t\t\t\tWWDebugString(\"RA95 - Received 'tickle' packet.\");\n\t\t\t\t//SetForegroundWindow ( MainWindow );\n\t\t\t\t//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tbreak;\n\n\t\t\tcase DDE_PACKET_HEART_BEAT:\n\t\t\t\tWWDebugString(\"RA95 - Received heart beat packet.\");\n\t\t\t\tif (GameTimerInUse){\n\t\t\t\t\tLastHeartbeat = GameTimer.Time();\n\t\t\t\t}else{\n\t\t\t\t\tLastHeartbeat = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWDebugString(\"RA95 - Received unrecognised packet.\");\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\treturn (TRUE);\n\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ptr to data in .INI file format                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:23PM ST : Created                                                               *\n *=============================================================================================*/\nchar *DDEServerClass::Get_MPlayer_Game_Info (void)\n{\n\treturn (MPlayerGameInfo);\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 3:24PM ST : Created                                                               *\n *=============================================================================================*/\nvoid DDEServerClass::Delete_MPlayer_Game_Info(void)\n{\n\tif (MPlayerGameInfo){\n\t\tdelete [] MPlayerGameInfo;\n\t\tMPlayerGameInfo = NULL;\n\t}\n}\n\n\n\n/***********************************************************************************************\n * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   time since heartbeat                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 11:05PM ST : Created                                                              *\n *=============================================================================================*/\nint DDEServerClass::Time_Since_Heartbeat(void)\n{\n\treturn (GameTimer.Time() - LastHeartbeat);\n}\n\n\n\n\n/***********************************************************************************************\n * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to the data to send                                                           *\n *           length of data                                                                    *\n *           packet type identifier                                                            *\n *                                                                                             *\n * OUTPUT:   true if packet successfully sent                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 11:07PM ST : Created                                                              *\n *=============================================================================================*/\nBOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type)\n{\n\tif( DDE_Class->Open_Poke_Connection(DDE_Class->remote_name) == FALSE) {\n\t\tWWDebugString(\"RA95 - Failed to connect for POKE!\");\n\t\treturn (FALSE);\n\t}\n\n\tchar *poke_data = new char [length + 2*sizeof(int)];\n\n\tint *poke_data_int = (int*)poke_data;\n\n\t*poke_data_int \t= htonl (length + 2*sizeof(int));\n\t*(poke_data_int+1)= htonl (packet_type);\n\n\tmemcpy (poke_data + 8, data, length);\n\n\n\tif(DDE_Class->Poke_Server( (LPBYTE) poke_data, ntohl(*poke_data_int) ) == FALSE) {\n\t\tWWDebugString(\"RA95 - POKE failed!\\n\");\n\t\tDDE_Class->Close_Poke_Connection();\t\t// close down the link\n\t\tdelete poke_data;\n\t\treturn (FALSE);\n\t}\n\n\tDDE_Class->Close_Poke_Connection();\t\t// close down the link\n\n\tdelete poke_data;\n\n\treturn (TRUE);\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/CCDDE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer - Red Alert                                *\n *                                                                                             *\n *                    File Name : CCDDE.H                                                      *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 10/04/95                                                     *\n *                                                                                             *\n *                  Last Update : August 5th, 1996 [ST]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   C&C's interface to the DDE class                                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include \"dde.h\"\n\nclass DDEServerClass {\n\n\tpublic:\n\n\t\tDDEServerClass (void);\n\t\t~DDEServerClass (void);\n\n\n\t\tchar \t*Get_MPlayer_Game_Info (void);\t\t\t\t\t//Returns pointer to game info\n\t\tint    Get_MPlayer_Game_Info_Length(){return(MPlayerGameInfoLength);};\t//Len of game info\n\t\tBOOL\t Callback(unsigned char *data, long length);\t//DDE callback function\n\t\tvoid\t Delete_MPlayer_Game_Info(void);\t\t\t\t\t//release the game info memory\n\t\tvoid\t Enable(void);\t\t\t\t\t\t\t\t\t\t\t//Enable the DDE callback\n\t\tvoid\t Disable(void);\t\t\t\t\t\t\t\t\t\t//Disable the DDE callback\n\t\tint\t Time_Since_Heartbeat(void);\t\t\t\t\t\t//Returns the time since the last hearbeat from WChat\n\n\t\t/*\n\t\t** Enumeration for DDE packet types from WChat\n\t\t*/\n\t\tenum {\n\t\t\tDDE_PACKET_START_MPLAYER_GAME,\t\t//Start game packet. This includes game options\n\t\t\tDDE_PACKET_GAME_RESULTS,\t\t\t\t//Game results packet. The game statistics.\n\t\t\tDDE_PACKET_HEART_BEAT,\t\t\t\t\t//Heart beat packet so we know WChat is still there.\n\t\t\tDDE_TICKLE,\t\t\t\t\t\t\t\t\t//Message to prompt other app to take focus.\n\t\t\tDDE_CONNECTION_FAILED\n\t\t};\n\n\n\tprivate:\n\n\t\tchar \t\t\t\t*MPlayerGameInfo;\t\t\t//Pointer to game start packet\n\t\tint\t\t\t\tMPlayerGameInfoLength;\t//Length of game start packet.\n\t\tBOOL\t\t\t\tIsEnabled;\t\t\t\t\t//Flag for DDE callback enable\n\t\tint\t\t\t\tLastHeartbeat;\t\t// Time since last heartbeat packet was received from WChat\n\n};\n\n\nextern DDEServerClass DDEServer;\nextern BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type);\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/CCFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCFILE.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 5, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCFileClass::CCFileClass -- Default constructor for file object.                          *\n *   CCFileClass::CCFileClass -- Filename based constructor for C&C file.                      *\n *   CCFileClass::Close -- Closes the file.                                                    *\n *   CCFileClass::Error -- Handles displaying a file error message.                            *\n *   CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.          *\n *   CCFileClass::Is_Open -- Determines if the file is open.                                   *\n *   CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.   *\n *   CCFileClass::Read -- Reads data from the file.                                            *\n *   CCFileClass::Seek -- Moves the current file pointer in the file.                          *\n *   CCFileClass::Size -- Determines the size of the file.                                     *\n *   CCFileClass::Write -- Writes data to the file (non mixfile files only).                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t<errno.h>\n#include\t\"ccfile.h\"\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Filename based constructor for C&C file.                        *\n *                                                                                             *\n *    Use this constructor for a file when the filename is known at construction time.         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to use for this file object.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The filename pointer is presumed to be inviolate throughout the duration of     *\n *             the file object. If this is not guaranteed, then use the default constructor    *\n *             and then set the name manually.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(char const * filename) :\n\tPosition(0)\n{\n\tCCFileClass::Set_Name(filename);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::CCFileClass -- Default constructor for file object.                            *\n *                                                                                             *\n *    This is the default constructor for a C&C file object.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCCFileClass::CCFileClass(void) :\n\tPosition(0)\n{\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Error -- Handles displaying a file error message.                              *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Error(int , int , char const * )\n{\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\tProg_End(\"CCFileClass::Error CD not found\", true);\n\t\tif (!RunningAsDLL) {\t//PG\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Write -- Writes data to the file (non mixfile files only).                     *\n *                                                                                             *\n *    This routine will write data to the file, but NOT to a file that is part of a mixfile.   *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the data to be written.               *\n *                                                                                             *\n *          size     -- The number of bytes to write.                                          *\n *                                                                                             *\n * OUTPUT:  Returns the number of bytes actually written.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Write(void const * buffer, long size)\n{\n\t/*\n\t**\tIf this is part of a mixfile, then writing is not allowed. Error out with a fatal\n\t**\tmessage.\n\t*/\n\tif (Is_Resident()) {\n\t\tError(EACCES, false, File_Name());\n\t}\n\n\treturn(CDFileClass::Write(buffer, size));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Read -- Reads data from the file.                                              *\n *                                                                                             *\n *    This routine determines if the file is part of the mixfile system. If it is, then        *\n *    the file is copied from RAM if it is located there. Otherwise it is read from disk       *\n *    according to the correct position of the file within the parent mixfile.                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to place the read data.                          *\n *                                                                                             *\n *          size     -- The number of bytes to read.                                           *\n *                                                                                             *\n * OUTPUT:  Returns the actual number of bytes read (this could be less than requested).       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Read(void * buffer, long size)\n{\n\tbool opened = false;\n\n\t/*\n\t**\tIf the file isn't currently open, then open it.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (Open()) {\n\t\t\topened = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the file is part of a loaded mixfile, then a mere copy is\n\t**\tall that is required for the read.\n\t*/\n\tif (Is_Resident()) {\n\t\tlong\tmaximum = Data.Get_Size() - Position;\n\n\t\tsize = maximum < size ? maximum : size;\n//\t\tsize = MIN(maximum, size);\n\t\tif (size) {\n\t\t\tmemmove(buffer, (char *)Data + Position, size);\n//\t\t\tMem_Copy((char *)Pointer + Position, buffer, size);\n\t\t\tPosition += size;\n\t\t}\n\t\tif (opened) Close();\n\t\treturn(size);\n\t}\n\n\tlong s = CDFileClass::Read(buffer, size);\n\n\t/*\n\t**\tIf the file was opened by this routine, then close it at this time.\n\t*/\n\tif (opened) Close();\n\n\t/*\n\t**\tReturn with the number of bytes read.\n\t*/\n\treturn(s);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Seek -- Moves the current file pointer in the file.                            *\n *                                                                                             *\n *    This routine will change the current file pointer to the position specified. It follows  *\n *    the same rules the a normal Seek() does, but if the file is part of the mixfile system,  *\n *    then only the position value needs to be updated.                                        *\n *                                                                                             *\n * INPUT:   pos      -- The position to move the file to relative to the position indicated    *\n *                      by the \"dir\" parameter.                                                *\n *                                                                                             *\n *          dir      -- The direction to affect the position change against. This can be       *\n *                      either SEEK_CUR, SEEK_END, or SEEK_SET.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the position of the new location.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCFileClass::Seek(long pos, int dir)\n{\n\t/*\n\t**\tWhen the file is resident, a mere adjustment of the virtual file position is\n\t**\tall that is required of a seek.\n\t*/\n\tif (Is_Resident()) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_END:\n\t\t\t\tPosition = Data.Get_Size();\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_SET:\n\t\t\t\tPosition = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tPosition += pos;\n\t\tPosition = Position < 0 ? 0 : Position;\n\t\tPosition = Position > Data.Get_Size() ? Data.Get_Size() : Position;\n//\t\tPosition = Bound(Position+pos, 0L, Length);\n\t\treturn(Position);\n\t}\n\treturn(CDFileClass::Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Size -- Determines the size of the file.                                       *\n *                                                                                             *\n *    If the file is part of the mixfile system, then the size of the file is already          *\n *    determined and available. Otherwise, go to the low level system to find the file         *\n *    size.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the file in bytes.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   08/05/1996 JLB : Handles returning size of embedded file.                                 *\n *=============================================================================================*/\nlong CCFileClass::Size(void)\n{\n\t/*\n\t**\tIf the file is resident, the the size is already known. Just return the size in this\n\t**\tcase.\n\t*/\n\tif (Is_Resident()) return(Data.Get_Size());\n\n\t/*\n\t**\tIf the file is not available as a stand alone file, then search for it in the\n\t**\tmixfiles in order to get its size.\n\t*/\n\tif (!CDFileClass::Is_Available()) {\n\t\tlong length = 0;\n\t\tMFCD::Offset(File_Name(), NULL, NULL, NULL, &length);\n\t\treturn(length);\n\t}\n\n\treturn(CDFileClass::Size());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile.            *\n *                                                                                             *\n *    This routine will examine the mixfile system looking for the file. If the file could     *\n *    not be found there, then the disk is examined directly.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available for opening?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Available(int )\n{\n\t/*\n\t**\tA file that is open is presumed available.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tA file that is part of a mixfile is also presumed available.\n\t*/\n\tif (MFCD::Offset(File_Name())) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tOtherwise a manual check of the file system is required to\n\t**\tdetermine if the file is actually available.\n\t*/\n\treturn(CDFileClass::Is_Available());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Is_Open -- Determines if the file is open.                                     *\n *                                                                                             *\n *    A mixfile is open if there is a pointer to the mixfile data. In absence of this,         *\n *    the the file is open if the file handle is valid.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Is_Open(void) const\n{\n\t/*\n\t**\tIf the file is part of a cached file, then return that it is opened. A closed file\n\t**\tdoesn't have a valid pointer.\n\t*/\n\tif (Is_Resident()) return(true);\n\n\t/*\n\t**\tOtherwise, go to a lower level to determine if the file is open.\n\t*/\n\treturn(CDFileClass::Is_Open());\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Close -- Closes the file.                                                      *\n *                                                                                             *\n *    If this is a mixfile file, then only the pointers need to be adjusted.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCFileClass::Close(void)\n{\n\tnew(&Data) ::Buffer;\n\tPosition = 0;\t\t\t\t// Starts at beginning offset.\n\tCDFileClass::Close();\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system.     *\n *                                                                                             *\n *    This routine will open the specified file. It examines the mixfile system to find a      *\n *    match. If one is found then the file is \"opened\" in a special cached way. Otherwise      *\n *    it is opened as a standard DOS file.                                                     *\n *                                                                                             *\n * INPUT:   rights   -- The access rights desired.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCFileClass::Open(int rights)\n{\n\t/*\n\t**\tAlways close the file if it was open.\n\t*/\n\tClose();\n\n\t/*\n\t**\tPerform a preliminary check to see if the specified file\n\t**\texists on the disk. If it does, then open this file regardless\n\t**\tof whether it also exists in RAM. This is slower, but allows\n\t**\tupgrade files to work.\n\t*/\n\tif ((rights & WRITE) || CDFileClass::Is_Available()) {\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\n\t/*\n\t**\tCheck to see if file is part of a mixfile and that mixfile is currently loaded\n\t**\tinto RAM.\n\t*/\n\tMFCD * mixfile = NULL;\n\tvoid * pointer = NULL;\n\tlong length = 0;\n\tlong start = 0;\n\tif (MFCD::Offset(File_Name(), &pointer, &mixfile, &start, &length)) {\n\n\t\tassert(mixfile != NULL);\n\n\t\t/*\n\t\t**\tIf the mixfile is located on disk, then fake out the file system to read from\n\t\t**\tthe mixfile, but think it is reading from a solitary file.\n\t\t*/\n\t\tif (pointer == NULL && mixfile != NULL) {\n\n\t\t\t/*\n\t\t\t**\tThis is a legitimate open to the file. All access to the file through this\n\t\t\t**\tfile object will be appropriately adjusted for mixfile support however. Also\n\t\t\t**\tnote that the filename attached to this object is NOT the same as the file\n\t\t\t**\tattached to the file handle.\n\t\t\t*/\n\t\t\tchar * dupfile = strdup(File_Name());\n\t\t\tOpen(mixfile->Filename, READ);\n\t\t\tSearching(false);\t\t\t\t// Disable multi-drive search.\n\t\t\tSet_Name(dupfile);\n\t\t\tSearching(true);\n\t\t\tfree(dupfile);\n\t\t\tBias(0);\n\t\t\tBias(start, length);\n\t\t\tSeek(0, SEEK_SET);\n\t\t} else {\n\t\t\tnew (&Data) ::Buffer(pointer, length);\n\t\t\tPosition = 0;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tThe file cannot be found in any mixfile, so it must reside as\n\t\t** an individual file on the disk. Or else it is just plain missing.\n\t\t*/\n\t\treturn(CDFileClass::Open(rights));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Get_Date_Time -- Gets the date and time the file was last modified.            *\n *                                                                                             *\n *    Use this routine to get the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the file date and time as a long.                                     *\n *          Use the YEAR(long), MONTH(),....                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nunsigned long CCFileClass::Get_Date_Time(void)\n{\n\tunsigned long datetime;\n\tMFCD * mixfile;\n\n\tdatetime = CDFileClass::Get_Date_Time();\n\n\tif ( !datetime ) {\n\t\tif (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {\n\t\t\t//\n\t\t\t// check for nested MIX files\n\t\t\t//\n\t\t\treturn( CCFileClass(mixfile->Filename).Get_Date_Time() );\n\t\t}\n\t\t// else return 0 indicating no file\n\t}\n\n\treturn( datetime );\n}\n\n\n/***********************************************************************************************\n * CCFileClass::Set_Date_Time -- Sets the date and time the file was last modified.            *\n *                                                                                             *\n *    Use this routine to set the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   the file date and time as a long                                                   *\n *                                                                                             *\n * OUTPUT:  successful or not if the file date and time was changed.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *=============================================================================================*/\nbool CCFileClass::Set_Date_Time( unsigned long datetime )\n{\n\tbool status;\n\tMFCD * mixfile;\n\n\tstatus = CDFileClass::Set_Date_Time( datetime );\n\n\tif ( !status ) {\n\t\tif (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {\n\t\t\t//\n\t\t\t// check for nested MIX files\n\t\t\t//\n\t\t\treturn( CCFileClass(mixfile->Filename).Set_Date_Time( datetime ) );\n\t\t}\n\t\t// else return 0 indicating no file\n\t}\n\n\treturn( status );\n}\n\n\n/***********************************************************************************\n** Backward compatibility section.\n*/\n//extern \"C\" {\n\n\nstatic CCFileClass Handles[10];\n\nint __cdecl Open_File(char const * file_name, int mode)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(Handles); index++) {\n\t\tif (!Handles[index].Is_Open()) {\n\t\t\tif (Handles[index].Open(file_name, mode)) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(WWERROR);\n}\n\nvoid __cdecl Close_File(int handle)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\tHandles[handle].Close();\n\t}\n}\n\nlong __cdecl Read_File(int handle, void * buf, unsigned long bytes)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Read(buf, bytes));\n\t}\n\treturn(0);\n}\n\nlong __cdecl Write_File(int handle, void const * buf, unsigned long bytes)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Write(buf, bytes));\n\t}\n\treturn(0);\n}\n\nint __cdecl Find_File(char const * file_name)\n{\n\tCCFileClass file(file_name);\n\treturn(file.Is_Available());\n}\n\n#ifdef NEVER\nint __cdecl Delete_File(char const * file_name)\n{\n\treturn(CCFileClass(file_name).Delete());\n}\n\nint __cdecl Create_File(char const * file_name)\n{\n\treturn(CCFileClass(file_name).Create());\n}\n\nunsigned long __cdecl Load_Data(char const * name, void * ptr, unsigned long size)\n{\n\treturn(CCFileClass(name).Read(ptr, size));\n}\n#endif\n\nvoid * __cdecl Load_Alloc_Data(char const * name, int )\n{\n\tCCFileClass file(name);\n\n\treturn(Load_Alloc_Data(file));\n}\n\nunsigned long __cdecl File_Size(int handle)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Size());\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nunsigned long __cdecl Write_Data(char const * name, void const * ptr, unsigned long size)\n{\n\treturn(CCFileClass(name).Write(ptr, size));\n}\n#endif\n\nunsigned long __cdecl Seek_File(int handle, long offset, int starting)\n{\n\tif (handle != WWERROR && Handles[handle].Is_Open()) {\n\t\treturn(Handles[handle].Seek(offset, starting));\n\t}\n\treturn(0);\n}\n\n#ifdef NEVER\nbool __cdecl Multi_Drive_Search(bool on)\n{\n//\treturn(CCFileClass::Multi_Drive_Search(on));\n\treturn(on);\n}\n\nvoid __cdecl WWDOS_Init(void)\n{\n}\n\nvoid __cdecl WWDOS_Shutdown(void)\n{\n}\n\nint __cdecl Find_Disk_Number(char const *)\n{\n\treturn(0);\n}\n#endif\n\n//unsigned long __cdecl Load_Uncompress(char const * file, BuffType uncomp_buff, BuffType dest_buff, void * reserved_data)\n//{\n//\treturn(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));\n//\treturn(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));\n//}\n\n#ifdef WIN32\nextern \"C\" {\nint MaxDevice;\nint DefaultDrive;\nchar CallingDOSInt;\n\n}\n#endif\n\n\nvoid Unfragment_File_Cache(void)\n{\n}\n\n\n"
  },
  {
    "path": "REDALERT/CCFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 17, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CCFILE_H\n#define CCFILE_H\n\n//#include\t<wwlib32.h>\n#include\t<limits.h>\n#include\t\"mixfile.h\"\n#include\t\"cdfile.h\"\n#include\t\"buff.h\"\n\n\n/*\n**\tThis derived class for file access knows about mixfiles (packed files). It can handle opening\n**\ta file that is embedded within a mixfile. This is true if the mixfile is cached or resides on\n**\tdisk. It is functionally similar to pakfiles, except much faster and less RAM intensive.\n*/\nclass CCFileClass : public CDFileClass\n{\n\tpublic:\n\t\tCCFileClass(char const * filename);\n\t\tCCFileClass(void);\n\t\tvirtual ~CCFileClass(void) {Position = 0;};\n\n\t\t// Delete should be overloaded here as well. Don't allow deletes of mixfiles.\n\n\t\tbool Is_Resident(void) const {return(Data.Get_Buffer() != NULL);}\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const * filename, int rights=READ) {Set_Name(filename);return Open(rights);};\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void * buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const * buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void);\n\t\tvirtual bool Set_Date_Time(unsigned long datetime);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis indicates the file is actually part of a resident image of the mixfile\n\t\t**\titself. In this case, the embedded file handle is invalid. All file access actually\n\t\t**\tgets routed through the cached version of the file. This is a pointer to the start\n\t\t**\tof the RAM image of the file.\n\t\t*/\n\t\t::Buffer Data;\n//\t\tvoid * Pointer;\n\n\t\t/*\n\t\t**\tThis is the size of the file if it was embedded in a mixfile. The size must be manually\n\t\t**\tkept track of because the DOS file size is invalid.\n\t\t*/\n//\t\tlong Length;\n\n\t\t/*\n\t\t**\tThis is the current seek position of the file. It is duplicated here if the file is\n\t\t**\tpart of a mixfile since the DOS seek position is not accurate. This value will\n\t\t**\trange from zero to the size of the file in bytes.\n\t\t*/\n\t\tlong Position;\n\n\t\t// Force these to never be invoked.\n\t\tCCFileClass const & operator = (CCFileClass const & c);\n\t\tCCFileClass (CCFileClass const & );\n};\n\ntemplate <> class MixFileClass<CDFileClass>;\n\n#endif\n"
  },
  {
    "path": "REDALERT/CCINI.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCINI.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCINI.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/24/96                                                     *\n *                                                                                             *\n *                  Last Update : November 1, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCINIClass::Calculate_Message_Digest -- Calculate a message digest for the current databas*\n *   CCINIClass::Get_AnimType -- Fetch an animation type number from the INI database.         *\n *   CCINIClass::Get_ArmorType -- Fetches the armor type from the INI database.                *\n *   CCINIClass::Get_Buildings -- Fetch a building bitfield from the INI database.             *\n *   CCINIClass::Get_BulletType -- Fetch the bullet identifier from the INI database.          *\n *   CCINIClass::Get_CrateType -- Fetches a crate type value from the INI database.            *\n *   CCINIClass::Get_HousesType -- Fetch a house identifier from the INI database.             *\n *   CCINIClass::Get_Lepton -- Fetches a lepton value from the INI database.                   *\n *   CCINIClass::Get_MPHType -- Fetches the speed value as a number from 0 to 100.             *\n *   CCINIClass::Get_OverlayType -- Fetch the overlay identifier from the INI database.        *\n *   CCINIClass::Get_Owners -- Fetch the owners (list of house bits).                          *\n *   CCINIClass::Get_SourceType -- Fetch the source (edge) type from the INI database.         *\n *   CCINIClass::Get_TerrainType -- Fetch the terrain type identifier from the INI database.   *\n *   CCINIClass::Get_TheaterType -- Fetch the theater type from the INI database.              *\n *   CCINIClass::Get_ThemeType -- Fetch the theme identifier.                                  *\n *   CCINIClass::Get_TriggerType -- Fetch the trigger type identifier from the INI database.   *\n *   CCINIClass::Get_Unique_ID -- Fetch a unique identifier number for the INI file.           *\n *   CCINIClass::Get_VQType -- Fetch the VQ movie identifier from the INI database.            *\n *   CCINIClass::Get_VocType -- Fetch a voc (sound effect) from the INI database.              *\n *   CCINIClass::Get_WarheadType -- Fetch the warhead type from the INI database.              *\n *   CCINIClass::Get_WeaponType -- Fetches the weapon type from the INI database.              *\n *   CCINIClass::Invalidate_Message_Digest -- Flag message digest as being invalid.            *\n *   CCINIClass::Load -- Load the INI database from the data stream specified.                 *\n *   CCINIClass::Load -- Load the INI database from the file specified.                        *\n *   CCINIClass::Put_AnimType -- Stores the animation identifier to the INI database.          *\n *   CCINIClass::Put_ArmorType -- Store the armor type to the INI database.                    *\n *   CCINIClass::Put_Buildings -- Store a building list to the INI database.                   *\n *   CCINIClass::Put_BulletType -- Store the projectile identifier into the INI database.      *\n *   CCINIClass::Put_CrateType -- Stores the crate value in the section and entry specified.   *\n *   CCINIClass::Put_HousesType -- Store a house identifier to the INI database.               *\n *   CCINIClass::Put_Lepton -- Stores a lepton value to the INI database.                      *\n *   CCINIClass::Put_MPHType -- Stores the speed value to the section & entry specified.       *\n *   CCINIClass::Put_OverlayType -- Store the overlay identifier into the INI database.        *\n *   CCINIClass::Put_Owners -- Store the house bitfield to the INI database.                   *\n *   CCINIClass::Put_SourceType -- Store the source (edge) identifier to the INI database.     *\n *   CCINIClass::Put_TerrainType -- Store the terrain type number to the INI database.         *\n *   CCINIClass::Put_TheaterType -- Store the theater identifier to the INI database.          *\n *   CCINIClass::Put_ThemeType -- Store the theme identifier to the INI database.              *\n *   CCINIClass::Put_TriggerType -- Store the trigger identifier to the INI database.          *\n *   CCINIClass::Put_VQType -- Store the VQ movie identifier into the INI database.            *\n *   CCINIClass::Put_VocType -- Store a sound effect identifier into the INI database.         *\n *   CCINIClass::Put_WarheadType -- Stores the warhead identifier to the INI database.         *\n *   CCINIClass::Put_WeaponType -- Store the weapon identifier to the INI database.            *\n *   CCINIClass::Save -- Pipes the INI database to the pipe specified.                         *\n *   CCINIClass::Save -- Save the INI data to the file specified.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CCINIClass::Load -- Load the INI database from the file specified.                          *\n *                                                                                             *\n *    This routine will load the database from the file specified in much the same manner      *\n *    that the INIClass load function works. However, this class will examine the message      *\n *    digest (if present) and compare it to the actual digest. If they differ, a special       *\n *    return value is used. This will allow verification of the integrity of the ini data.     *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file that will be read from.                             *\n *                                                                                             *\n *          withdigest  -- Should a message digest be examined when loaded. If there is a      *\n *                         mismatch detected, then an error will be returned.                  *\n *                                                                                             *\n * OUTPUT:  If the file was not read, returns 0. If the file was read ok, returns 1. If the    *\n *          file was read ok, but the digest doesn't verify, returns 2.                        *\n *                                                                                             *\n * WARNINGS:   If no message digest was present in the INI file, then no verification can      *\n *             be performed.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles digest control.                                                  *\n *=============================================================================================*/\nbool CCINIClass::Load(FileClass & file, bool withdigest)\n{\n\treturn(Load(FileStraw(file), withdigest));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Load -- Load the INI database from the data stream specified.                   *\n *                                                                                             *\n *    This will load the INI database and in the process, it will fetch and verify any         *\n *    message digest present.                                                                  *\n *                                                                                             *\n * INPUT:   straw -- The data stream to fetch the INI data from.                               *\n *                                                                                             *\n *          withdigest  -- Should a message digest be examined when loaded. If there is a      *\n *                         mismatch detected, then an error will be returned.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the database loaded ok? (hack: returns \"2\" if digest doesn't match).     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nint CCINIClass::Load(Straw & file, bool withdigest)\n{\n\tbool ok = INIClass::Load(file);\n\n\tInvalidate_Message_Digest();\n\tif (ok && withdigest) {\n\n\t\t/*\n\t\t**\tIf a digest is present, fetch it.\n\t\t*/\n\t\tunsigned char digest[20];\n\t\tint len = Get_UUBlock(\"Digest\", digest, sizeof(digest));\n\t\tif (len > 0) {\n\t\t\tClear(\"Digest\");\n\n\t\t\t/*\n\t\t\t**\tCalculate the message digest for the INI data that was read.\n\t\t\t*/\n\t\t\tCalculate_Message_Digest();\n\n\t\t\t/*\n\t\t\t**\tIf the message digests don't match, then return with the special error code.\n\t\t\t*/\n\t\t\tif (memcmp(digest, Digest, sizeof(digest)) != 0) {\n\t\t\t\treturn(2);\n\t\t\t}\n\t\t}\n\t}\n\treturn(ok);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Save -- Save the INI data to the file specified.                                *\n *                                                                                             *\n *    This routine will save the INI data to the file. It will add a message digest so that    *\n *    validity check can be performed when the INI data is subsequently read.                  *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file to write the INI data to.                           *\n *                                                                                             *\n *          withdigest  -- Should a message digest be generated and saved with the INI         *\n *                         data file?                                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the INI data saved?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nint CCINIClass::Save(FileClass & file, bool withdigest) const\n{\n\treturn(Save(FilePipe(file), withdigest));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Save -- Pipes the INI database to the pipe specified.                           *\n *                                                                                             *\n *    This routine will pipe the INI data to the pipe segment specified. It is functionally    *\n *    the same as the save operation. A message digest is added to the output data so that     *\n *    validity check can occur during a subsequent read.                                       *\n *                                                                                             *\n * INPUT:   straw -- Reference to the pipe that will receive the output ini data stream.       *\n *                                                                                             *\n *          withdigest  -- Should a message digest be generated and saved with the INI         *\n *                         data file?                                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output to the pipe.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Handles message digest control.                                          *\n *=============================================================================================*/\nint CCINIClass::Save(Pipe & pipe, bool withdigest) const\n{\n\tif (!withdigest) {\n\t\treturn(INIClass::Save(pipe));\n\t}\n\n\t/*\n\t**\tJust in case these entries are present, clear them out.\n\t*/\n\t((CCINIClass *)this)->Clear(\"Digest\");\n\n\t/*\n\t**\tCalculate what the new digest should be.\n\t*/\n\t((CCINIClass *)this)->Calculate_Message_Digest();\n\n\t/*\n\t**\tStore the actual digest into the INI database.\n\t*/\n\t((CCINIClass *)this)->Put_UUBlock(\"Digest\", Digest, sizeof(Digest));\n\n\t/*\n\t**\tOutput the database to the pipe specified.\n\t*/\n\tint length = INIClass::Save(pipe);\n\n\t/*\n\t**\tRemove the digest from the database. It shouldn't stick around as if it were real data\n\t**\tsince it isn't really part of the INI database proper.\n\t*/\n\t((CCINIClass *)this)->Clear(\"Digest\");\n\n\t/*\n\t**\tFinally, return with the total number of bytes send out the pipe.\n\t*/\n\treturn(length);\n}\n\n\nstatic inline int _Scale_To_256(int val)\n{\n\tval = min(val, 100);\n\tval = max(val, 0);\n\tval = ((val * 256) / 100);\n\tval = min(val, 255);\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Lepton -- Fetches a lepton value from the INI database.                     *\n *                                                                                             *\n *    This routine will fetch the lepton value as if it were expressed as cells. Example;      *\n *    a value of 1 would mean 256 in leptons.                                                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to look under.                                  *\n *                                                                                             *\n *          entry    -- The entry identifier to find.                                          *\n *                                                                                             *\n *          defvalue -- The default value to use if the specified section and entry could      *\n *                      not be located.                                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton value of the section & entry specified. If not found, then *\n *          the default value is returned.                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLEPTON CCINIClass::Get_Lepton(char const * section, char const * entry, LEPTON defvalue) const\n{\n\tfixed result = Get_Fixed(section, entry, fixed(defvalue, CELL_LEPTON_W));\n\treturn(result * CELL_LEPTON_W);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Lepton -- Stores a lepton value to the INI database.                        *\n *                                                                                             *\n *    This routine will store the lepton value as if it were expressed in cells. Example;      *\n *    A lepton of 128 will be stored as \".5\".                                                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the value under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the lepton value at.                                *\n *                                                                                             *\n *          value    -- The lepton value to store.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the lepton value stored?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Lepton(char const * section, char const * entry, LEPTON value)\n{\n\treturn(Put_Fixed(section, entry, fixed(value, CELL_LEPTON_W)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_MPHType -- Fetches the speed value as a number from 0 to 100.               *\n *                                                                                             *\n *    This routine will fetch the speed value as if it were expressed as a number from 0       *\n *    to 100. The value of 100 would translate into a speed of 256 leptons per game frame.     *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to find.                                          *\n *                                                                                             *\n *          defvalue -- The default speed value to use if the entry could not be located.      *\n *                                                                                             *\n * OUTPUT:  Returns with the speed value. If no entry could be found, then the default value   *\n *          will be returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nMPHType CCINIClass::Get_MPHType(char const * section, char const * entry, MPHType defvalue) const\n{\n\tint val = Get_Int(section, entry, ((int)defvalue * 100) / 256);\n\treturn (MPHType(_Scale_To_256(val)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_MPHType -- Stores the speed value to the section & entry specified.         *\n *                                                                                             *\n *    Use this routine to store a speed value into the INI database. The number stored will    *\n *    be in a 0..100 format. A speed of 256 leptons per tick would be stored as 100.           *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to store the speed value to.                      *\n *                                                                                             *\n *          value    -- The speed value to store.                                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the speed value stored?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_MPHType(char const * section, char const * entry, MPHType value)\n{\n\treturn(Put_Int(section, entry, ((int)value * 100) / 256));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Owners -- Fetch the owners (list of house bits).                            *\n *                                                                                             *\n *    Use this to fetch a house bit array value from the INI database. This value will be      *\n *    various bit positions set (1 << house#) for each house specified in the database.        *\n *    Houses can be specified in series by the house name separated by commas or by the        *\n *    special group names of \"soviet\", and \"allies\" to cover the houses that are members of    *\n *    these groups.                                                                            *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default house bitfield to use if the entry could not be found.     *\n *                                                                                             *\n * OUTPUT:  Returns with the house bitfield value. If the entry could not be found, then the   *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCINIClass::Get_Owners(char const * section, char const * entry, long defvalue) const\n{\n\tchar buffer[128];\n\tlong ownable = defvalue;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\n\t\townable = 0;\n\t\tchar * name = strtok(buffer, \",\");\n\n\t\twhile (name) {\n\t\t\townable |= Owner_From_Name(name);\n\t\t\tname = strtok(NULL, \",\");\n\t\t}\n\t}\n\treturn(ownable);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Owners -- Store the house bitfield to the INI database.                     *\n *                                                                                             *\n *    Use this routine to store the house bitfield data into the database. The bitfield format *\n *    matches the format used by the Get_Owners function. Example; if both England and         *\n *    Spain were specified in the bitfield, the entry would be stored as \"England,Spain\".      *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier that is assigned the value.                       *\n *                                                                                             *\n *          value    -- The value to assign to the entry.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry stored in the INI database?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Owners(char const * section, char const * entry, long value)\n{\n\tchar buffer[128];\n\n\tbuffer[0] = '\\0';\n\n\tif ((value & HOUSEF_ALLIES) == HOUSEF_ALLIES) {\n\t\tstrcat(buffer, \"allies\");\n\t\tvalue &= ~HOUSEF_ALLIES;\n\t}\n\tif ((value & HOUSEF_SOVIET) == HOUSEF_SOVIET) {\n\t\tif (buffer[0] != '\\0') {\n\t\t\tstrcat(buffer, \",\");\n\t\t}\n\t\tstrcat(buffer, \"soviet\");\n\t\tvalue &= ~HOUSEF_SOVIET;\n\t}\n\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tif ((value & (1 << house)) != 0) {\n\t\t\tif (buffer[0] != '\\0') {\n\t\t\t\tstrcat(buffer, \",\");\n\t\t\t}\n\t\t\tstrcat(buffer, HouseTypeClass::As_Reference(house).Name());\n\t\t}\n\t}\n\n\tif (buffer[0] != '\\0') {\n\t\treturn(Put_String(section, entry, buffer));\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_ArmorType -- Fetches the armor type from the INI database.                  *\n *                                                                                             *\n *    This routine will fetch the armor type from the database.                                *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Th identifier for the entry to search for.                             *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the armor type specified in the INI database. If it could not be      *\n *          found, then the default value is returned instead.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nArmorType CCINIClass::Get_ArmorType(char const * section, char const * entry, ArmorType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, ArmorName[defvalue], buffer, sizeof(buffer));\n\treturn(Armor_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_ArmorType -- Store the armor type to the INI database.                      *\n *                                                                                             *\n *    Use this routine to store the specified armor type to the INI database.                  *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the value at.                                       *\n *                                                                                             *\n *          value    -- The value to store in the database.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry stored in the database?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_ArmorType(char const * section, char const * entry, ArmorType value)\n{\n\treturn(Put_String(section, entry, ArmorName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_VocType -- Fetch a voc (sound effect) from the INI database.                *\n *                                                                                             *\n *    This routine will fetch a voc number from the database. The voc number will either       *\n *    be a valid sound effect or VOC_NONE if no match could be found.                          *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to return if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the sound effect (VocType) from the INI database. If the entry could  *\n *          not be located, then the default value is returned.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVocType CCINIClass::Get_VocType(char const * section, char const * entry, VocType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, Voc_Name(defvalue), buffer, sizeof(buffer));\n\treturn(Voc_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_VocType -- Store a sound effect identifier into the INI database.           *\n *                                                                                             *\n *    Use this routine to store a voc identifier (stored a the text name of the sound) into    *\n *    the INI database.                                                                        *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- The entry to assign the value to.                                      *\n *                                                                                             *\n *          value    -- The sound effect to store to the entry.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the sound effect entry stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_VocType(char const * section, char const * entry, VocType value)\n{\n\tif (value == VOC_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, Voc_Name(value)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_AnimType -- Fetch an animation type number from the INI database.           *\n *                                                                                             *\n *    This will fetch an AnimType number from the INI database. The anim is stored as a text   *\n *    name of the art file used for that anim.                                                 *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default AnimType to use if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the anim type specified in the database. If it could not be found,    *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType CCINIClass::Get_AnimType(char const * section, char const * entry, AnimType defvalue) const\n{\n\tchar buffer[128];\n\n\tGet_String(section, entry, Anim_Name(defvalue), buffer, sizeof(buffer));\n\treturn(Anim_From_Name(buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_AnimType -- Stores the animation identifier to the INI database.            *\n *                                                                                             *\n *    This routine will store the animation identifier (stored as the text name of the art     *\n *    file it uses) to the INI database.                                                       *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to assign the animation number to.                *\n *                                                                                             *\n *          value    -- The animation identifier to store with the entry.                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation identifier stored?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_AnimType(char const * section, char const * entry, AnimType value)\n{\n\tif (value == ANIM_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, Anim_Name(value)));\n}\n\n\nUnitType CCINIClass::Get_UnitType(char const * section, char const * entry, UnitType defvalue) const\n{\n\tchar buffer[128];\n\n\tchar const * def = \"<none>\";\n\tif (defvalue != UNIT_NONE) {\n\t\tdef = UnitTypeClass::As_Reference(defvalue).Name();\n\t}\n\tGet_String(section, entry, def, buffer, sizeof(buffer));\n\treturn(UnitTypeClass::From_Name(buffer));\n}\n\n\nbool CCINIClass::Put_UnitType(char const * section, char const * entry, UnitType value)\n{\n\tif (value == UNIT_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, UnitTypeClass::As_Reference(value).Name()));\n}\n\n\n\n/***********************************************************************************************\n * CCINIClass::Get_WeaponType -- Fetches the weapon type from the INI database.                *\n *                                                                                             *\n *    This routine will fetch the weapon type from the INI database. The weapon type is        *\n *    stored as a custom identifier string.                                                    *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default weapon value to return if the entry could not be located.  *\n *                                                                                             *\n * OUTPUT:  Returns with the weapon type specified by the entry. If the entry could not be     *\n *          found then the default value is returned.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWeaponType CCINIClass::Get_WeaponType(char const * section, char const * entry, WeaponType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Weapon_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_WeaponType -- Store the weapon identifier to the INI database.              *\n *                                                                                             *\n *    Store the weapon identifier (as custom string name) to the INI database.                 *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- Identifier to store the weapon identifier with.                        *\n *                                                                                             *\n *          value    -- The weapon identifier to store.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the weapon identifier stored?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_WeaponType(char const * section, char const * entry, WeaponType value)\n{\n\tif (value == WEAPON_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, WeaponTypeClass::As_Pointer(value)->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_WarheadType -- Fetch the warhead type from the INI database.                *\n *                                                                                             *\n *    Will fetch the warhead identifier from the INI database.                                 *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section to search for the entry under.          *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default return value to use if the entry could not be located.     *\n *                                                                                             *\n * OUTPUT:  Returns with the found warhead type. If the entry could not be found then the      *\n *          default warhead value is returned.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nWarheadType CCINIClass::Get_WarheadType(char const * section, char const * entry, WarheadType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (WarheadType wh = WARHEAD_FIRST; wh < WARHEAD_COUNT; wh++) {\n\t\t\tif (stricmp(WarheadTypeClass::As_Pointer(wh)->Name(), buffer) == 0) {\n\t\t\t\treturn(wh);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_WarheadType -- Stores the warhead identifier to the INI database.           *\n *                                                                                             *\n *    This will store the weapon identifier specified to the INI database.                     *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry to store the warhead identifier.                             *\n *                                                                                             *\n *          value    -- The warhead identifier to store.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the warhead identifier stored to the database?                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_WarheadType(char const * section, char const * entry, WarheadType value)\n{\n\tif (value == WARHEAD_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, WarheadTypeClass::As_Pointer(value)->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_OverlayType -- Fetch the overlay identifier from the INI database.          *\n *                                                                                             *\n *    This routine will fetch the overlay identifier from the database.                        *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the overlay identifier found. If it could not be found, then the      *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayType CCINIClass::Get_OverlayType(char const * section, char const * entry, OverlayType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(OverlayTypeClass::From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_OverlayType -- Store the overlay identifier into the INI database.          *\n *                                                                                             *\n *    Use this routine to store the overlay identifier into the INI database.                  *\n *                                                                                             *\n * INPUT:   section  -- Identifier for to search for the entry under.                          *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          value    -- The overlay type value to store with the entry.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay value stored?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_OverlayType(char const * section, char const * entry, OverlayType value)\n{\n\tassert(value != OVERLAY_NONE);\n\treturn(Put_String(section, entry, OverlayTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_BulletType -- Fetch the bullet identifier from the INI database.            *\n *                                                                                             *\n *    Use this routine to fetch the bullet type identifier from the INI database.              *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search for the entry under.                  *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default bullet type value to return if the entry could not be      *\n *                      located.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the bullet type identifier found. If the entry could not be found     *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletType CCINIClass::Get_BulletType(char const * section, char const * entry, BulletType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (BulletType proj = BULLET_FIRST; proj < BULLET_COUNT; proj++) {\n\t\t\tif (stricmp(BulletTypeClass::As_Reference(proj).Name(), buffer) == 0) {\n//\t\t\tif (stricmp(ProjectileNames[proj], buffer) == 0) {\n\t\t\t\treturn(proj);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_BulletType -- Store the projectile identifier into the INI database.        *\n *                                                                                             *\n *    This routine will store the projectile name (as the identifier) to the INI database.     *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- The entry identifier to store the projectile value with.               *\n *                                                                                             *\n *          value    -- The projectile identifier to store.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the projectile identifier stored?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_BulletType(char const * section, char const * entry, BulletType value)\n{\n\tif (value == BULLET_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, BulletTypeClass::As_Reference(value).Name()));\n//\treturn(Put_String(section, entry, ProjectileNames[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_HousesType -- Fetch a house identifier from the INI database.               *\n *                                                                                             *\n *    Use this routine to fetch an individual house identifier from the INI database. This is  *\n *    somewhat similar to the Get_Owners function but is limited to a single house.            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the house identifier if it was found. If not found, then the default  *\n *          value is returned.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHousesType CCINIClass::Get_HousesType(char const * section, char const * entry, HousesType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(HouseTypeClass::From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_HousesType -- Store a house identifier to the INI database.                 *\n *                                                                                             *\n *    Use this routine to store the specified house identifier to the INI database.            *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          value    -- The house identifier to store in the database.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the house identifier stored?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_HousesType(char const * section, char const * entry, HousesType value)\n{\n\treturn(Put_String(section, entry, HouseTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_VQType -- Fetch the VQ movie identifier from the INI database.              *\n *                                                                                             *\n *    Fetches the VQ movie name (identifier) from the INI database.                            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the VQ movie identifier found. If the entry could not be located,     *\n *          then the default value is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVQType CCINIClass::Get_VQType(char const * section, char const * entry, VQType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tfor (VQType vq = VQ_FIRST; vq < VQ_COUNT; vq++) {\n\t\t\tif (stricmp(buffer, VQName[vq]) == 0) {\n\t\t\t\treturn(vq);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_VQType -- Store the VQ movie identifier into the INI database.              *\n *                                                                                             *\n *    Use this routine to store the VQ movie identifier into the INI database.                 *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store.                                     *\n *                                                                                             *\n *          value    -- The VQ movie identifier to store to the INI database.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the VQ identifier stored?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_VQType(char const * section, char const * entry, VQType value)\n{\n\tif (value == VQ_NONE) {\n\t\treturn(Put_String(section, entry, \"<none>\"));\n\t}\n\treturn(Put_String(section, entry, VQName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TheaterType -- Fetch the theater type from the INI database.                *\n *                                                                                             *\n *    This will fetch the theater identifier from the INI database.                            *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search for the entry under.              *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the theater type found. If the entry could not be found, then the     *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTheaterType CCINIClass::Get_TheaterType(char const * section, char const * entry, TheaterType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Theater_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TheaterType -- Store the theater identifier to the INI database.            *\n *                                                                                             *\n *    Use this routine to store the theater name to the INI database.                          *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store.                                     *\n *                                                                                             *\n *          value    -- The theater identifier to store.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the theater identifier stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TheaterType(char const * section, char const * entry, TheaterType value)\n{\n\treturn(Put_String(section, entry, Theaters[value].Name));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TriggerType -- Fetch the trigger type identifier from the INI database.     *\n *                                                                                             *\n *    This routine will fetch the trigger type identifier from the INI database.               *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier of the entry to search for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the trigger type pointer if a match was found. No match found will    *\n *          return a NULL.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass * CCINIClass::Get_TriggerType(char const * section, char const * entry) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(TriggerTypeClass::From_Name(buffer));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TriggerType -- Store the trigger identifier to the INI database.            *\n *                                                                                             *\n *    This routine will store the trigger (as its name) to the INI database.                   *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- The entry name to store the trigger identifier to.                     *\n *                                                                                             *\n *          value    -- The trigger type to store. The trigger name will be stored.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the trigger name stored?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TriggerType(char const * section, char const * entry, TriggerTypeClass * value)\n{\n\treturn(Put_String(section, entry, value->Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_ThemeType -- Fetch the theme identifier.                                    *\n *                                                                                             *\n *    This routine will fetch the theme identifier from the INI database.                      *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier of the entry to search for.                                 *\n *                                                                                             *\n *          defvalue -- The default theme identifier to return if the entry could not be found.*\n *                                                                                             *\n * OUTPUT:  Returns with the theme identifier if it was found. If not found, then the default  *\n *          value is returned instead.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nThemeType CCINIClass::Get_ThemeType(char const * section, char const * entry, ThemeType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Theme.From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_ThemeType -- Store the theme identifier to the INI database.                *\n *                                                                                             *\n *    This routine will store the specified theme identifier to the INI database.              *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to store the entry under.                   *\n *                                                                                             *\n *          entry    -- Identifier for the entry to store the value to.                        *\n *                                                                                             *\n *          value    -- The theme identifier to store.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the theme identifier stored.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_ThemeType(char const * section, char const * entry, ThemeType value)\n{\n\treturn(Put_String(section, entry, Theme.Base_Name(value)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_SourceType -- Fetch the source (edge) type from the INI database.           *\n *                                                                                             *\n *    This routine will fetch the source (reinforcement edge) identifier from the INI          *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section that the entry will be searched under.      *\n *                                                                                             *\n *          entry    -- Identifier for the entry that will be searched for.                    *\n *                                                                                             *\n *          defvalue -- The default value to return if the entry could not be located.         *\n *                                                                                             *\n * OUTPUT:  Returns with the source type of the entry if found. If not found, then the         *\n *          default value is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSourceType CCINIClass::Get_SourceType(char const * section, char const * entry, SourceType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Source_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_SourceType -- Store the source (edge) identifier to the INI database.       *\n *                                                                                             *\n *    This will store the source type (reinforcement edge) to the INI database.                *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier of the entry to store the source identifier to.             *\n *                                                                                             *\n *          value    -- The source (edge) value to store.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the source identifier stored?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_SourceType(char const * section, char const * entry, SourceType value)\n{\n\treturn(Put_String(section, entry, SourceName[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_CrateType -- Fetches a crate type value from the INI database.              *\n *                                                                                             *\n *    This will return with the crate type specified in the INI database.                      *\n *                                                                                             *\n * INPUT:   section  -- Identifier for the section to search under.                            *\n *                                                                                             *\n *          entry    -- The entry to find the matching crate value for.                        *\n *                                                                                             *\n *          defvalue -- The default crate value to return if the entry could not be found.     *\n *                                                                                             *\n * OUTPUT:  Returns with the crate type identified with the specified entry. If the entry      *\n *          could not be located, then the default value is returned.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCrateType CCINIClass::Get_CrateType(char const * section, char const * entry, CrateType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(Crate_From_Name(buffer));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_CrateType -- Stores the crate value in the section and entry specified.     *\n *                                                                                             *\n *    This will store the specified crate value to the section and entry specified.            *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to store the entry under.                       *\n *                                                                                             *\n *          entry    -- The entry identifier to store the crate value with.                    *\n *                                                                                             *\n *          value    -- The crate value to store.                                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate value stored to the INI database?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_CrateType(char const * section, char const * entry, CrateType value)\n{\n\treturn(Put_String(section, entry, CrateNames[value]));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_TerrainType -- Fetch the terrain type identifier from the INI database.     *\n *                                                                                             *\n *    Fetches the terrain type number from the INI database.                                   *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- Identifier for the entry to search for.                                *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the terrain type if found. If the entry wasn't found, then the        *\n *          default value will be returned.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainType CCINIClass::Get_TerrainType(char const * section, char const * entry, TerrainType defvalue) const\n{\n\tchar buffer[128];\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\treturn(TerrainTypeClass::From_Name(strtok(buffer, \",\")));\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_TerrainType -- Store the terrain type number to the INI database.           *\n *                                                                                             *\n *    This will store the terrain type identifier to the INI database.                         *\n *                                                                                             *\n * INPUT:   section  -- The section to store the entry under.                                  *\n *                                                                                             *\n *          entry    -- Identifier that the terrain number will be stored to.                  *\n *                                                                                             *\n *          value    -- The terrain type identifier to store.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the terrain identifier stored?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_TerrainType(char const * section, char const * entry, TerrainType value)\n{\n\treturn(Put_String(section, entry, TerrainTypeClass::As_Reference(value).Name()));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Buildings -- Fetch a building bitfield from the INI database.               *\n *                                                                                             *\n *    This routing will fetch the a list of buildings from the INI database. The buildings     *\n *    are expressed as a comma separated list of building identifiers. The return value is     *\n *    a composite of bits that represent these buildings -- one bit per building type.         *\n *                                                                                             *\n * INPUT:   section  -- The section to search for the entry under.                             *\n *                                                                                             *\n *          entry    -- The entry to fetch the building list from.                             *\n *                                                                                             *\n *          defvalue -- The default value to return if the section and entry could not be      *\n *                      located.                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the building list (as a bitfield). If the entry could not be          *\n *          found, the the default value is returned instead.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CCINIClass::Get_Buildings(char const * section, char const * entry, long defvalue) const\n{\n\tchar buffer[128];\n\tlong pre;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\n\t\tpre = 0;\n\t\tchar * token = strtok(buffer, \",\");\n\t\twhile (token != NULL && *token != '\\0') {\n\t\t\tStructType building = BuildingTypeClass::From_Name(token);\n\t\t\tif (building != STRUCT_NONE) {\n\t\t\t\tpre |= (1L << building);\n\t\t\t}\n\t\t\ttoken = strtok(NULL, \",\");\n\t\t}\n\t} else {\n\t\tpre = defvalue;\n\t}\n\n\treturn(pre);\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Put_Buildings -- Store a building list to the INI database.                     *\n *                                                                                             *\n *    This will store a list of buildings to the INI database. The buildings are listed by     *\n *    their identifier names separated by commas.                                              *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section to store the entry under.               *\n *                                                                                             *\n *          entry    -- The entry to store the building list to.                               *\n *                                                                                             *\n *          value    -- A list of buildings (in the form of a bit field -- one bit per         *\n *                      building type).                                                        *\n *                                                                                             *\n * OUTPUT:  Was the building list stored to the INI file?                                      *\n *                                                                                             *\n * WARNINGS:   This is limited to the buildings that can be expressed in a bitfield long.      *\n *             Which means, there can be only a maximum of 32 building types listed and        *\n *             even then, the total line length generated must not exceed 128 bytes.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CCINIClass::Put_Buildings(char const * section, char const * entry, long value)\n{\n\tchar buffer[128] = \"\";\n\tint maxi = (32 < STRUCT_COUNT) ? 32 : STRUCT_COUNT;\n\n\tfor (StructType index = STRUCT_FIRST; index < maxi; index++) {\n\t\tif ((value & (1L << index)) != 0) {\n\n\t\t\tif (buffer[0] != '\\0') {\n\t\t\t\tstrcat(buffer, \",\");\n\t\t\t}\n\t\t\tstrcat(buffer, BuildingTypeClass::As_Reference(index).IniName);\n\t\t}\n\t}\n\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Get_Unique_ID -- Fetch a unique identifier number for the INI file.             *\n *                                                                                             *\n *    This is a shorthand version of the message digest. It calculates the ID number from the  *\n *    message digest itself.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a 32 bit unique identifier number for the INI database.               *\n *                                                                                             *\n * WARNINGS:   Since the return value is only 32 bits, it is much less secure than the         *\n *             complete message digest.                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CCINIClass::Get_Unique_ID(void) const\n{\n\tif (!IsDigestPresent) {\n\t\t((CCINIClass *)this)->Calculate_Message_Digest();\n\t}\n\n\treturn(CRCEngine()(&Digest[0], sizeof(Digest)));\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Calculate_Message_Digest -- Calculate a message digest for the current database *\n *                                                                                             *\n *    This will calculate a new message digest according to the current state of the INI       *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the database is changed in any fashion, this message digest will be rendered *\n *             obsolete.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCINIClass::Calculate_Message_Digest(void)\n{\n\t/*\n\t**\tCalculate the message digest for the INI data that was read.\n\t*/\n\tSHAPipe sha;\n\tINIClass::Save(sha);\n\tsha.Result(Digest);\n\tIsDigestPresent = true;\n}\n\n\n/***********************************************************************************************\n * CCINIClass::Invalidate_Message_Digest -- Flag message digest as being invalid.              *\n *                                                                                             *\n *    This flags the message digest as being invalid so that it will be recalculated when      *\n *    needed.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CCINIClass::Invalidate_Message_Digest(void)\n{\n\tIsDigestPresent = false;\n}\n"
  },
  {
    "path": "REDALERT/CCINI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCINI.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCINI.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/24/96                                                     *\n *                                                                                             *\n *                  Last Update : May 24, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CCINI_H\n#define CCINI_H\n\n#include\t\"ini.h\"\n#include\t\"fixed.h\"\n#include\t\"pk.h\"\n\nclass TriggerTypeClass;\n\n/*\n**\tThe advanced version of the INI database manager. It handles the C&C expansion types and\n**\tidentifiers. In addition, it automatically stores a message digest with the INI data\n**\tso that verification can occur.\n*/\nclass CCINIClass : public INIClass\n{\n\tpublic:\n\t\tCCINIClass(void) : IsDigestPresent(false) {}\n\n\t\tbool Load(FileClass & file, bool withdigest);\n\t\tint Load(Straw & file, bool withdigest);\n\t\tint Save(FileClass & file, bool withdigest) const;\n\t\tint Save(Pipe & pipe, bool withdigest) const;\n\n\t\tlong Get_Buildings(char const * section, char const * entry, long defvalue) const;\n\t\tUnitType Get_UnitType(char const * section, char const * entry, UnitType defvalue) const;\n\t\tAnimType Get_AnimType(char const * section, char const * entry, AnimType defvalue) const;\n\t\tArmorType Get_ArmorType(char const * section, char const * entry, ArmorType defvalue) const;\n\t\tBulletType Get_BulletType(char const * section, char const * entry, BulletType defvalue) const;\n\t\tHousesType Get_HousesType(char const * section, char const * entry, HousesType defvalue) const;\n\t\tLEPTON Get_Lepton(char const * section, char const * entry, LEPTON defvalue) const;\n\t\tMPHType Get_MPHType(char const * section, char const * entry, MPHType defvalue) const;\n\t\tOverlayType Get_OverlayType(char const * section, char const * entry, OverlayType defvalue) const;\n\t\tSourceType Get_SourceType(char const * section, char const * entry, SourceType defvalue) const;\n\t\tTerrainType Get_TerrainType(char const * section, char const * entry, TerrainType defvalue) const;\n\t\tTheaterType Get_TheaterType(char const * section, char const * entry, TheaterType defvalue) const;\n\t\tThemeType Get_ThemeType(char const * section, char const * entry, ThemeType defvalue) const;\n\t\tTriggerTypeClass * Get_TriggerType(char const * section, char const * entry) const;\n\t\tVQType Get_VQType(char const * section, char const * entry, VQType defvalue) const;\n\t\tVocType Get_VocType(char const * section, char const * entry, VocType defvalue) const;\n\t\tWarheadType Get_WarheadType(char const * section, char const * entry, WarheadType defvalue) const;\n\t\tWeaponType Get_WeaponType(char const * section, char const * entry, WeaponType defvalue) const;\n\t\tlong Get_Owners(char const * section, char const * entry, long defvalue) const;\n\t\tCrateType Get_CrateType(char const * section, char const * entry, CrateType defvalue) const;\n\n\n\t\tbool Put_Buildings(char const * section, char const * entry, long value);\n\t\tbool Put_AnimType(char const * section, char const * entry, AnimType value);\n\t\tbool Put_UnitType(char const * section, char const * entry, UnitType value);\n\t\tbool Put_ArmorType(char const * section, char const * entry, ArmorType value);\n\t\tbool Put_BulletType(char const * section, char const * entry, BulletType value);\n\t\tbool Put_HousesType(char const * section, char const * entry, HousesType value);\n\t\tbool Put_Lepton(char const * section, char const * entry, LEPTON value);\n\t\tbool Put_MPHType(char const * section, char const * entry, MPHType value);\n\t\tbool Put_VQType(char const * section, char const * entry, VQType value);\n\t\tbool Put_OverlayType(char const * section, char const * entry, OverlayType value);\n\t\tbool Put_Owners(char const * section, char const * entry, long value);\n\t\tbool Put_SourceType(char const * section, char const * entry, SourceType value);\n\t\tbool Put_TerrainType(char const * section, char const * entry, TerrainType value);\n\t\tbool Put_TheaterType(char const * section, char const * entry, TheaterType value);\n\t\tbool Put_ThemeType(char const * section, char const * entry, ThemeType value);\n\t\tbool Put_TriggerType(char const * section, char const * entry, TriggerTypeClass * value);\n\t\tbool Put_VocType(char const * section, char const * entry, VocType value);\n\t\tbool Put_WarheadType(char const * section, char const * entry, WarheadType value);\n\t\tbool Put_WeaponType(char const * section, char const * entry, WeaponType value);\n\t\tbool Put_CrateType(char const * section, char const * entry, CrateType value);\n\n\t\tint Get_Unique_ID(void) const;\n\n\tprivate:\n\t\tvoid Calculate_Message_Digest(void);\n\t\tvoid Invalidate_Message_Digest(void);\n\n\t\tbool IsDigestPresent:1;\n\n\t\t/*\n\t\t**\tThis is the message digest (SHA) of the INI database that was embedded as part of\n\t\t**\tthe INI file.\n\t\t*/\n\t\tunsigned char Digest[20];\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CCMPATH.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CCMPATH.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 01/09/96                                 *\n *                                                                         *\n *                  Last Update : January 11, 1996 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_MPATH -- Performs MPATH-specific initialization                  *\n *   Shutdown_MPATH -- Shuts down MPATH connections                        *\n *   Connect_MPATH -- Waits for connections to other players               *\n *   Destroy_MPATH_Connection -- Destroys the given connection             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n\n/***************************************************************************\n * Init_MPATH -- Performs MPATH-specific initialization                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Init_MPATH(void)\n{\n#if(MPATH)\n\t//------------------------------------------------------------------------\n\t// Allocate a packet buffer for MPATH's use\n\t//------------------------------------------------------------------------\n\tSession.MPathPacket = new char[Session.MPathSize];\n\n\t//------------------------------------------------------------------------\n\t// Read the multiplayer settings from the CONQUER.INI file, and the game\n\t// options from the options file.\n\t//------------------------------------------------------------------------\n\tSession.Read_MultiPlayer_Settings();\n\n\tif (!Read_MPATH_Game_Options()) {\n\t\tWWMessageBox().Process(\"Unable to load game settings!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Flush all incoming packets\n\t//------------------------------------------------------------------------\n\tMPath->Flush_All();\n\n\t//------------------------------------------------------------------------\n\t// Form connections to all other players\n\t//------------------------------------------------------------------------\n\tConnect_MPATH();\n\n\t//------------------------------------------------------------------------\n\t// Set multiplayer values for the local system, and timing values.\n\t//------------------------------------------------------------------------\n\tSession.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;\n\n\treturn (1);\n#else\n\treturn (1);\n#endif\n\n}\t// end of Init_MPATH\n\n\n/***************************************************************************\n * Shutdown_MPATH -- Shuts down MPATH connections                          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_MPATH(void)\n{\n#if(MPATH)\n\tCDTimerClass<SystemTimerClass> timer;\n\n\t//------------------------------------------------------------------------\n\t// Wait a full second before exiting, to ensure all packets get sent.\n\t//------------------------------------------------------------------------\n\ttimer = 60;\n\twhile (timer) ;\n\n\t//------------------------------------------------------------------------\n\t// Free memory\n\t//------------------------------------------------------------------------\n\tif (Session.MPathPacket) {\n\t\tdelete [] Session.MPathPacket;\n\t\tSession.MPathPacket = NULL;\n\t}\n\n\tif (MPath) {\n\t\tdelete MPath;\n\t\tMPath = NULL;\n\t}\n\n\treturn;\n\n#endif\n}\t// end of Shutdown_MPATH\n\n\n/***************************************************************************\n * Connect_MPATH -- Waits for connections to other players                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/10/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Connect_MPATH(void)\n{\n#if(MPATH)\n\ttypedef struct ConnectPacketTag {\n\t\tNetCommandType Dummy;\t\t\t\t// packet type; set to PING\n\t\tchar Name[MPLAYER_NAME_MAX];\t\t// player's name\n\t\tHousesType House;\t\t\t\t\t\t// player's ActLike\n\t\tunsigned char Color;\t\t\t\t\t// player's Color\n\t} ConnectPacketType;\n\tint num_players;\n\tint num_found;\n\tConnectPacketType send_packet;\n\tConnectPacketType receive_packet;\n\tint address;\n\tint found;\n\tint size;\n\tint i;\n\tCDTimerClass<SystemTimerClass> send_timer;\n\tNodeNameType *who;\n\n\tenum {\n\t\tD_TXT6_H = 7,\n\t\tD_MARGIN = 5,\n\t};\n\tstatic int x,y,w,h;\n\tchar const *buf1;\n\tchar const *buf2;\n\n\tint display = 0;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//\n\t// Clear the Players list\n\t//\n\twhile (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\t//\n\t// Add myself to the list first thing\n\t//\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\t//\n\t// Find out how many players to wait for\n\t//\n\tnum_players = MPath->Find_Num_Connections();\n\tnum_found = 0;\n\tSession.NumPlayers = num_players + 1;\n\n\t//\n\t// Send out a packet announcing my presence\n\t//\n\tsend_packet.Dummy = NET_PING;\n\tstrcpy(send_packet.Name, Session.Handle);\n\tsend_packet.House = Session.House;\n\tsend_packet.Color = Session.ColorIdx;\n\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);\n\n\t//\n\t// Start our packet-sending timer\n\t//\n\tsend_timer = 240;\n\n\t//\n\t// Wait for all players to enter the game\n\t//\n\tdisplay = 1;\n\twhile (num_found < num_players) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = 1;\n\t\t}\n\t\t#endif\n\n\t\tif (display) {\n\t\t\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\t\t\tbuf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);\n\t\t\tbuf2 = Text_String(TXT_PRESS_ESC);\n\t\t\tw = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\t\t\tw += (D_MARGIN * 2);\n\t\t\th = (D_TXT6_H * 2) + (D_MARGIN * 7);\n\t\t\tx = 160 - (w / 2);\n\t\t\ty = 100 - (h / 2);\n\t\t\tHide_Mouse();\n\t\t\t//Set_Logic_Page(SeenBuff);\n\t\t\tDialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);\n\n\t\t\tFancy_Text_Print(buf1,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2)) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tFancy_Text_Print(buf2,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = 0;\n\t\t}\n\n\t\tMPath->Service();\n\n\t\t//\n\t\t// Check for an incoming packet; if a PING comes in, see if we already\n\t\t// have this player in our Players list.  If not, add him.\n\t\t//\n\t\tif (MPath->Get_Global_Message (&receive_packet, &size, &address) &&\n\t\t\treceive_packet.Dummy == NET_PING) {\n\t\t\tfound = 0;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tif (Session.Players[i]->MPathAddress == address) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Create a new connection and a new node in the list.\n\t\t\t//\n\t\t\tif (!found) {\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, receive_packet.Name);\n\t\t\t\twho->MPathAddress = address;\n\t\t\t\twho->Player.House = receive_packet.House;\n\t\t\t\twho->Player.Color = (PlayerColorType)receive_packet.Color;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tnum_found++;\n\n\t\t\t\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 1,\n\t\t\t\t\taddress);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// If the user hits ESC, bail out.\n\t\t//\n\t\tif (Keyboard->Check()) {\n\t\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\t\t//Prog_End();\n\t\t\t\tEmergency_Exit(0);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// When our timer expires, re-send the packet.\n\t\t//\n\t\tif (!send_timer) {\n\t\t\tsend_packet.Dummy = NET_PING;\n\t\t\tMPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);\n\t\t\tsend_timer = 240;\n\t\t}\n\t}\n\n#else\n\treturn;\n#endif\n}\n\n\n/***************************************************************************\n * Destroy_MPATH_Connection -- Destroys the given connection               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tconnection ID to destroy\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, \t\t*\n *\t\t\t\t\tno error is shown.\t\t  \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Destroy_MPATH_Connection(int id, int error)\n{\n#if(MPATH)\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*------------------------------------------------------------------------\n\tCreate a message to display to the user\n\t------------------------------------------------------------------------*/\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST),MPath->Connection_Name(id));\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME),MPath->Connection_Name(id));\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tDelete the MPATH connection\n\t------------------------------------------------------------------------*/\n\tMPath->Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*------------------------------------------------------------------------\n\tIf we're the last player left, tell the user.\n\t------------------------------------------------------------------------*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n#else\n\tid = id;\n\terror = error;\n\n#endif\n}\t// end of Destroy_MPATH_Connection\n\n\n/***************************** end of ccmpath.cpp **************************/\n"
  },
  {
    "path": "REDALERT/CCPTR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCPTR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCPTR.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/07/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CCPtr<T>::operator > -- Greater than comparison operator.                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n \ntemplate class CCPtr<AircraftClass>;\ntemplate class CCPtr<AircraftTypeClass>;\ntemplate class CCPtr<AnimClass>;\ntemplate class CCPtr<AnimTypeClass>;\ntemplate class CCPtr<BuildingClass>;\ntemplate class CCPtr<BuildingTypeClass>;\ntemplate class CCPtr<BulletClass>;\ntemplate class CCPtr<BulletTypeClass>;\ntemplate class CCPtr<FactoryClass>;\ntemplate class CCPtr<HouseClass>;\ntemplate class CCPtr<HouseTypeClass>;\ntemplate class CCPtr<InfantryClass>;\ntemplate class CCPtr<InfantryTypeClass>;\ntemplate class CCPtr<OverlayClass>;\ntemplate class CCPtr<OverlayTypeClass>;\ntemplate class CCPtr<SmudgeClass>;\ntemplate class CCPtr<SmudgeTypeClass>;\ntemplate class CCPtr<TeamClass>;\ntemplate class CCPtr<TeamTypeClass>;\ntemplate class CCPtr<TemplateClass>;\ntemplate class CCPtr<TemplateTypeClass>;\ntemplate class CCPtr<TerrainClass>;\ntemplate class CCPtr<TerrainTypeClass>;\ntemplate class CCPtr<TriggerClass>;\ntemplate class CCPtr<TriggerTypeClass>;\ntemplate class CCPtr<UnitClass>;\ntemplate class CCPtr<UnitTypeClass>;\ntemplate class CCPtr<VesselClass>;\ntemplate class CCPtr<VesselTypeClass>;\ntemplate class CCPtr<WarheadTypeClass>;\ntemplate class CCPtr<WeaponTypeClass>;\n\n\ntemplate<class T> FixedIHeapClass* CCPtr<T>::Heap = NULL;\n\n\n/*\n**\tThese member functions for the CCPtr class cannot be declared inside the\n**\tclass definition since they could refer to other objects that themselves\n**\tcontain CCPtr objects. The recursive nature of this type of declaration\n**\tis not handled by Watcom, hence the body declaration is dislocated here.\n*/\ntemplate<class T>\nCCPtr<T>::CCPtr(T * ptr) : ID(-1)\n{\n\tif (ptr != NULL) {\n\t\tID = ptr->ID;\n\t}\n}\n\n\n/***********************************************************************************************\n * CCPtr<T>::operator > -- Greater than comparison operator.                                   *\n *                                                                                             *\n *    This will compare two pointer value to see if the left hand value is greater than the    *\n *    right hand. The values are compared by comparing based on their Name() functions.        *\n *                                                                                             *\n * INPUT:   rvalue   -- The right handle CCPtr value.                                          *\n *                                                                                             *\n * OUTPUT:  Is the left hand value greater than the right hand value?                          *\n *                                                                                             *\n * WARNINGS:   The values pointed to by CCPtr must have a Name() function defined.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool CCPtr<T>::operator > (CCPtr<T> const & rvalue) const\n{\n\treturn (stricmp((*this)->Name(), rvalue->Name()) > 0);\n}"
  },
  {
    "path": "REDALERT/CCPTR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CCPTR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CCPTR.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/07/96                                                     *\n *                                                                                             *\n *                  Last Update : June 7, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CCPTR_H\n#define CCPTR_H\n\n/*\n**\tThe CCPtr class is designed for a specific purpose. It functions like a pointer except that\n**\tit requires no fixups for saving and loading. If pointer fixups are not an issue, than using\n**\tregular pointers would be more efficient.\n*/\ntemplate<class T>\nclass CCPtr\n{\n\tpublic:\n\t\tCCPtr(void) : ID(-1) {};\n\t\tCCPtr(NoInitClass const & ) {};\n\t\tCCPtr(T * ptr);\n\n\t\toperator T * (void) const {\n\t\t\tif (ID == -1) return(NULL);\n\t\t\tassert(Heap != NULL && ID < Heap->Length());\n\t\t\treturn((T*) (*Heap)[ID]);\n\t\t}\n\t\tT & operator * (void) const {\n\t\t\tassert(Heap != NULL && ID < Heap->Length());\n\t\t\treturn(*(T*)(*Heap)[ID]);\n\t\t}\n\t\tT * operator -> (void) const {\n\t\t\tif (ID == -1) return(NULL);\n\t\t\tassert(Heap != NULL && ID < Heap->Length());\n\t\t\treturn((T*) (*Heap)[ID]);\n\t\t}\n\n\t\tbool Is_Valid(void) const {return(ID != -1);}\n\n\t\tbool operator == (CCPtr<T> const & rvalue) const {return(ID == rvalue.ID);}\n\t\tbool operator != (CCPtr<T> const & rvalue) const {return(ID != rvalue.ID);}\n\t\tbool operator > (CCPtr<T> const & rvalue) const;\n\t\tbool operator <= (CCPtr<T> const & rvalue) const {return (rvalue > *this);}\n\t\tbool operator < (CCPtr<T> const & rvalue) const {return (*this != rvalue && rvalue > *this);}\n\t\tbool operator >= (CCPtr<T> const & rvalue) const {return (*this == rvalue || rvalue > *this);}\n\n\t\tlong Raw(void) const {return(ID);}\n\t\tvoid Set_Raw(long value) {ID = value;}\n\n\t\tstatic void Set_Heap(FixedIHeapClass *heap) {Heap = heap;}\n\n\tprivate:\n\n\t\tstatic FixedIHeapClass * Heap;\n\n\t\t/*\n\t\t**\tThis is the ID number of the object it refers to. By using an ID number, this class can\n\t\t**\tbe saved and loaded without pointer fixups.\n\t\t*/\n\t\tint ID;\n};\n\n/*\n**\tThese template helper functions tell the compiler what to do in the\n**\tambiguous case of a CCPtr on one side and a regular type pointer on the\n**\tother side. In such a case the compiler could create a temp CCPtr object\n**\tOR call the conversion operator on the existing CCPtr object. Either way\n**\tis technically valid, but the compiler doesn't know which is better so it\n**\tgenerates an error. These routines force the conversion operator rather than\n**\tcreating a temporary object. This presumes that the conversion operator is\n**\tcheaper than constructing a temporary and that cheaper solutions are desirable.\n*/\ntemplate<class T>\nint operator == (CCPtr<T> & lvalue, T * rvalue)\n{\n\treturn((T*)lvalue == rvalue);\n}\n\ntemplate<class T>\nint operator == (T * lvalue, CCPtr<T> & rvalue)\n{\n\treturn(lvalue == (T*)rvalue);\n}\n\n#endif"
  },
  {
    "path": "REDALERT/CCTEN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CCTEN.CPP                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 01/09/96                                 *\n *                                                                         *\n *                  Last Update : November 27, 1996 [BRR]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Init_TEN -- Performs TEN-specific initialization                      *\n *   Shutdown_TEN -- Shuts down TEN connections                            *\n *   Connect_TEN -- Waits for connections to other players                 *\n *   Destroy_TEN_Connection -- Destroys the given connection               *\n *   Debug_Mono -- Custom mono prints                                      *\n *   Send_TEN_Win_Packet -- Sends a win packet to server                   *\n *   Send_TEN_Alliance -- Sends an ally/enemy packet to server             *\n *   Send_TEN_Out_Of_Sync -- Announces this game out of sync               *\n *   Send_TEN_Packet_Too_Late -- Announces packet-received-too-late        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include \"function.h\"\n\n#if(TEN)\n#ifdef WIN32\n#define WINDOWS\n#endif\n#include \"ten.h\"\n#endif\n\nvoid Connect_TEN(void);\nvoid Debug_Mono(void);\n\n/***************************************************************************\n * Init_TEN -- Performs TEN-specific initialization                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Init_TEN(void)\n{\n#if(TEN)\n\t//------------------------------------------------------------------------\n\t// Allocate a packet buffer for TEN's use\n\t//------------------------------------------------------------------------\n\tSession.TenPacket = new char[Session.TenSize];\n\n\t//------------------------------------------------------------------------\n\t// Read the multiplayer settings from the CONQUER.INI file, and the game\n\t// options from the options file.\n\t//------------------------------------------------------------------------\n\tSession.Read_MultiPlayer_Settings();\n\n\tif (!Read_TEN_Game_Options()) {\n\t\tWWMessageBox().Process(\"Unable to load game settings!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Flush all incoming packets\n\t//------------------------------------------------------------------------\n\tTen->Flush_All();\n\n\t//------------------------------------------------------------------------\n\t// Form connections to all other players\n\t//------------------------------------------------------------------------\n\tConnect_TEN();\n\n\t//------------------------------------------------------------------------\n\t// Set multiplayer values for the local system, and timing values.\n\t//------------------------------------------------------------------------\n\tSession.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;\n\n\treturn (1);\n#else\n\treturn (1);\n#endif\n\n}\t// end of Init_TEN\n\n\n/***************************************************************************\n * Shutdown_TEN -- Shuts down TEN connections                              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/09/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_TEN(void)\n{\n#if(TEN)\n\tCDTimerClass<SystemTimerClass> timer;\n\n\t//------------------------------------------------------------------------\n\t// Wait a full second before exiting, to ensure all packets get sent.\n\t//------------------------------------------------------------------------\n\ttimer = 60;\n\twhile (timer) ;\n\n\t//------------------------------------------------------------------------\n\t// Free memory\n\t//------------------------------------------------------------------------\n\tif (Session.TenPacket) {\n\t\tdelete [] Session.TenPacket;\n\t\tSession.TenPacket = NULL;\n\t}\n\n\tif (Ten) {\n\t\tdelete Ten;\n\t\tTen = NULL;\n\t}\n\n\treturn;\n\n#endif\n}\t// end of Shutdown_TEN\n\n\n/***************************************************************************\n * Connect_TEN -- Waits for connections to other players                 \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tMPlayerCount must have been initialized at this point.\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/10/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Connect_TEN(void)\n{\n#if(TEN)\n\ttypedef struct ConnectPacketTag {\n\t\tNetCommandType Dummy;\t\t\t\t// packet type; set to PING\n\t\tchar Name[MPLAYER_NAME_MAX];\t\t// player's name\n\t\tHousesType House;\t\t\t\t\t\t// player's ActLike\n\t\tunsigned char Color;\t\t\t\t\t// player's Color\n\t} ConnectPacketType;\n\tint num_players;\n\tint num_found;\n\tConnectPacketType send_packet;\n\tConnectPacketType receive_packet;\n\tint address;\n\tint found;\n\tint size;\n\tint i;\n\tCDTimerClass<SystemTimerClass> send_timer;\n\tNodeNameType *who;\n\n\tenum {\n\t\tD_TXT6_H = 7,\n\t\tD_MARGIN = 5,\n\t};\n\tstatic int x,y,w,h;\n\tchar const *buf1;\n\tchar const *buf2;\n\n\tint display = 0;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//\n\t// Clear the Players list\n\t//\n\twhile (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\t//\n\t// Add myself to the list first thing\n\t//\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\t//\n\t// Find out how many players to wait for\n\t//\n\tnum_players = Session.NumPlayers - 1;\n\tnum_found = 0;\n\n\t//\n\t// Send out a packet announcing my presence\n\t//\n\tsend_packet.Dummy = NET_PING;\n\tstrcpy(send_packet.Name, Session.Handle);\n\tsend_packet.House = Session.House;\n\tsend_packet.Color = Session.ColorIdx;\n\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);\n\n\t//\n\t// Start our packet-sending timer\n\t//\n\tsend_timer = 240;\n\n\t//\n\t// Wait for all players to enter the game\n\t//\n\tdisplay = 1;\n\twhile (num_found < num_players) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = 1;\n\t\t}\n\t\t#endif\n\n\t\tif (display) {\n\t\t\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\t\t\tbuf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);\n\t\t\tbuf2 = Text_String(TXT_PRESS_ESC);\n\t\t\tw = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\t\t\tw += (D_MARGIN * 2);\n\t\t\th = (D_TXT6_H * 2) + (D_MARGIN * 7);\n\t\t\tx = 160 - (w / 2);\n\t\t\ty = 100 - (h / 2);\n\t\t\tHide_Mouse();\n\t\t\t//Set_Logic_Page(SeenBuff);\n\t\t\tDialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);\n\n\t\t\tFancy_Text_Print(buf1,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2)) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tFancy_Text_Print(buf2,\n\t\t\t\t160 * RESFACTOR,\n\t\t\t\t(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,\n\t\t\t\tscheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = 0;\n\t\t}\n\n\t\tTen->Service();\n\n\t\t//\n\t\t// Check for an incoming packet; if a PING comes in, see if we already\n\t\t// have this player in our Players list.  If not, add him.\n\t\t//\n\t\tif (Ten->Get_Global_Message (&receive_packet, &size, &address) &&\n\t\t\treceive_packet.Dummy == NET_PING) {\n\t\t\tfound = 0;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tif (Session.Players[i]->TenAddress == address) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\n\t\t\t// Create a new connection and a new node in the list.\n\t\t\t//\n\t\t\tif (!found) {\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, receive_packet.Name);\n\t\t\t\twho->TenAddress = address;\n\t\t\t\twho->Player.House = receive_packet.House;\n\t\t\t\twho->Player.Color = (PlayerColorType)receive_packet.Color;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tnum_found++;\n\n\t\t\t\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 1,\n\t\t\t\t\taddress);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// If the user hits ESC, bail out.\n\t\t//\n\t\tif (Keyboard->Check()) {\n\t\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\t\t//Prog_End();\n\t\t\t\tEmergency_Exit(0);\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// When our timer expires, re-send the packet.\n\t\t//\n\t\tif (!send_timer) {\n\t\t\tsend_packet.Dummy = NET_PING;\n\t\t\tTen->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);\n\t\t\tsend_timer = 240;\n\t\t}\n\t}\n\n#else\n\treturn;\n#endif\n}\n\n\n/***************************************************************************\n * Destroy_TEN_Connection -- Destroys the given connection                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tconnection ID to destroy (must be a HousesType)\t\t\t\t\t*\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, \t\t*\n *\t\t\t\t\tno error is shown.\t\t  \t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Destroy_TEN_Connection(int id, int error)\n{\n#if(TEN)\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*------------------------------------------------------------------------\n\tCreate a message to display to the user\n\t------------------------------------------------------------------------*/\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST),Ten->Connection_Name(id));\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME),Ten->Connection_Name(id));\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tDelete the TEN connection\n\t------------------------------------------------------------------------*/\n\tTen->Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*------------------------------------------------------------------------\n\tIf we're the last player left, tell the user.\n\t------------------------------------------------------------------------*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n#else\n\tid = id;\n\terror = error;\n\n#endif\n}\t// end of Destroy_TEN_Connection\n\n\n/***************************************************************************\n * Debug_Mono -- Custom mono prints                                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Debug_Mono(void)\n{\n#if(TEN)\n\tint i;\n\tint id;\n\n\tMono_Printf(\"STATE: # Connections:%d\\n\",Ten->Num_Connections());\n\tfor (i=0;i<Ten->Num_Connections();i++) {\n\t\tid = Ten->Connection_ID(i);\n\t\tMono_Printf(\"Connection %d: Name:%s, ID:%d, Address:%d\\n\",\n\t\t\ti,\n\t\t\tTen->Connection_Name(id),\n\t\t\tTen->Connection_ID(i),\n\t\t\tTen->Connection_Address(id));\n\t}\n\n#endif\n}\n\n\n/***************************************************************************\n * Send_TEN_Win_Packet -- Sends a win packet to server                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Win_Packet(void)\n{\n#if(TEN)\n\tchar winbuf[80];\n\tchar idbuf[20];\n\tint first = 1;\n\tHouseClass *hptr;\n\tint i;\n\n\t//\n\t// Build a special text buffer to send to the TEN server.  Format:\n\t// \"winner 'id id'\", where 'id' is the Ten Player ID of each player\n\t// on the winning team.  (For TEN, the color index is the player ID.)\n\t//\n\tsprintf(winbuf,\"winner '\");\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\thptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tif (!hptr->IsDefeated) {\n\t\t\tif (!first) {\n\t\t\t\tstrcat(winbuf,\" \");\n\t\t\t} else {\n\t\t\t\tfirst = 0;\n\t\t\t}\n\t\t\tsprintf(idbuf,\"%d\", Session.Players[i]->Player.Color);\n\t\t\tstrcat (winbuf, idbuf);\n\t\t}\n\t}\n\tstrcat (winbuf,\"' \");\n\ttenArSetPlayerState(winbuf);\n#endif\t// TEN\n\n}\t// end of Send_TEN_Win_Packet\n\n\n/***************************************************************************\n * Send_TEN_Alliance -- Sends an ally/enemy packet to server               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\twhom\t\tname of player we're allying / enemying with\t\t\t\t\t\t*\n *\t\tally\t\t1 = we're allying; 0 = we're breaking the alliance\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Alliance(char *whom, int ally)\n{\n#if(TEN)\n\tchar buf[80];\n\n\tif (ally) {\n\t\tsprintf(buf,\"ally '%s' \",whom);\n\t} else {\n\t\tsprintf(buf,\"enemy '%s' \",whom);\n\t}\n\n\ttenArSetPlayerState(buf);\n\n#else\n\twhom = whom;\n\tally = ally;\n#endif\t// TEN\n\n}\t// end of Send_TEN_Alliance\n\n\n/***************************************************************************\n * Send_TEN_Out_Of_Sync -- Announces this game out of sync                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Out_Of_Sync(void)\n{\n#if(TEN)\n\ttenArSetPlayerState(\"sync '1' \");\n#endif\t// TEN\n\n}\t// end of Send_TEN_Out_Of_Sync\n\n\n/***************************************************************************\n * Send_TEN_Packet_Too_Late -- Announces packet-received-too-late          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/27/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Send_TEN_Packet_Too_Late(void)\n{\n#if(TEN)\n\ttenArSetPlayerState(\"toolate '1' \");\n#endif\t// TEN\n\n}\t// end of Send_TEN_Packet_Too_Late\n\n\n/***************************** end of ccten.cpp *****************************/\n"
  },
  {
    "path": "REDALERT/CDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 16, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   TemplateTypeClass::As_Reference -- Fetches a reference to the template specified.         *\n *   TemplateTypeClass::Create_And_Place -- Creates and places a template object on the map.   *\n *   TemplateTypeClass::Create_One_Of -- Creates an object of this template type.              *\n *   TemplateTypeClass::Display -- Displays a generic representation of template.              *\n *   TemplateTypeClass::From_Name -- Determine template from ASCII name.                       *\n *   TemplateTypeClass::Init -- Loads graphic data for templates.                              *\n *   TemplateTypeClass::Land_Type -- Determines land type from template and icon number.       *\n *   TemplateTypeClass::Occupy_List -- Determines occupation list.                             *\n *   TemplateTypeClass::One_Time -- Performs one-time initialization                           *\n *   TemplateTypeClass::Prep_For_Add -- Prepares to add template to scenario.                  *\n *   TemplateTypeClass::TemplateTypeClass -- Constructor for template type objects.            *\n *   TemplateTypeClass::operator delete -- Deletes a template type object.                     *\n *   TemplateTypeClass::operator new -- Allocates a template type from special heap.           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nstatic TemplateTypeClass const Empty(\n\tTEMPLATE_CLEAR1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW|THEATERF_INTERIOR,\n\t\"CLEAR1\",\n\tTXT_CLEAR\n);\nstatic TemplateTypeClass const Clear(\n\tTEMPLATE_CLEAR1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW|THEATERF_INTERIOR,\n\t\"CLEAR1\",\n\tTXT_CLEAR\n);\nstatic TemplateTypeClass const Road01(\n\tTEMPLATE_ROAD01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D01\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road02(\n\tTEMPLATE_ROAD02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D02\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road03(\n\tTEMPLATE_ROAD03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D03\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road04(\n\tTEMPLATE_ROAD04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D04\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road05(\n\tTEMPLATE_ROAD05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D05\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road06(\n\tTEMPLATE_ROAD06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D06\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road07(\n\tTEMPLATE_ROAD07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D07\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road08(\n\tTEMPLATE_ROAD08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D08\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road09(\n\tTEMPLATE_ROAD09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D09\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road10(\n\tTEMPLATE_ROAD10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D10\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road11(\n\tTEMPLATE_ROAD11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D11\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road12(\n\tTEMPLATE_ROAD12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D12\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road13(\n\tTEMPLATE_ROAD13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D13\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road14(\n\tTEMPLATE_ROAD14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D14\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road15(\n\tTEMPLATE_ROAD15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D15\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road16(\n\tTEMPLATE_ROAD16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D16\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road17(\n\tTEMPLATE_ROAD17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D17\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road18(\n\tTEMPLATE_ROAD18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D18\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road19(\n\tTEMPLATE_ROAD19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D19\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road20(\n\tTEMPLATE_ROAD20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D20\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road21(\n\tTEMPLATE_ROAD21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D21\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road22(\n\tTEMPLATE_ROAD22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D22\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road23(\n\tTEMPLATE_ROAD23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D23\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road24(\n\tTEMPLATE_ROAD24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D24\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road25(\n\tTEMPLATE_ROAD25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D25\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road26(\n\tTEMPLATE_ROAD26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D26\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road27(\n\tTEMPLATE_ROAD27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D27\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road28(\n\tTEMPLATE_ROAD28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D28\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road29(\n\tTEMPLATE_ROAD29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D29\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road30(\n\tTEMPLATE_ROAD30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D30\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road31(\n\tTEMPLATE_ROAD31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D31\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road32(\n\tTEMPLATE_ROAD32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D32\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road33(\n\tTEMPLATE_ROAD33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D33\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road34(\n\tTEMPLATE_ROAD34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D34\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road35(\n\tTEMPLATE_ROAD35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D35\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road36(\n\tTEMPLATE_ROAD36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D36\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road37(\n\tTEMPLATE_ROAD37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D37\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road38(\n\tTEMPLATE_ROAD38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D38\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road39(\n\tTEMPLATE_ROAD39,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D39\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road40(\n\tTEMPLATE_ROAD40,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D40\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road41(\n\tTEMPLATE_ROAD41,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D41\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road42(\n\tTEMPLATE_ROAD42,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D42\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road43(\n\tTEMPLATE_ROAD43,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D43\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road44(\n\tTEMPLATE_ROAD44,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D44\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Road45(\n\tTEMPLATE_ROAD45,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"D45\",\n\tTXT_ROAD\n);\nstatic TemplateTypeClass const Water(\n\tTEMPLATE_WATER,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"W1\",\n\tTXT_WATER\n);\nstatic TemplateTypeClass const Water2(\n\tTEMPLATE_WATER2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"W2\",\n\tTXT_WATER\n);\nstatic TemplateTypeClass const Shore01(\n\tTEMPLATE_SHORE01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH01\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore02(\n\tTEMPLATE_SHORE02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH02\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore03(\n\tTEMPLATE_SHORE03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH03\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore04(\n\tTEMPLATE_SHORE04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH04\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore05(\n\tTEMPLATE_SHORE05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH05\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore06(\n\tTEMPLATE_SHORE06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH06\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore07(\n\tTEMPLATE_SHORE07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH07\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore08(\n\tTEMPLATE_SHORE08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH08\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore09(\n\tTEMPLATE_SHORE09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH09\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore10(\n\tTEMPLATE_SHORE10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH10\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore11(\n\tTEMPLATE_SHORE11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH11\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore12(\n\tTEMPLATE_SHORE12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH12\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore13(\n\tTEMPLATE_SHORE13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH13\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore14(\n\tTEMPLATE_SHORE14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH14\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore15(\n\tTEMPLATE_SHORE15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH15\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore16(\n\tTEMPLATE_SHORE16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH16\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore17(\n\tTEMPLATE_SHORE17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH17\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore18(\n\tTEMPLATE_SHORE18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH18\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore19(\n\tTEMPLATE_SHORE19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH19\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore20(\n\tTEMPLATE_SHORE20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH20\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore21(\n\tTEMPLATE_SHORE21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH21\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore22(\n\tTEMPLATE_SHORE22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH22\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore23(\n\tTEMPLATE_SHORE23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH23\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore24(\n\tTEMPLATE_SHORE24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH24\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore25(\n\tTEMPLATE_SHORE25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH25\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore26(\n\tTEMPLATE_SHORE26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH26\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore27(\n\tTEMPLATE_SHORE27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH27\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore28(\n\tTEMPLATE_SHORE28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH28\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore29(\n\tTEMPLATE_SHORE29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH29\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore30(\n\tTEMPLATE_SHORE30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH30\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore31(\n\tTEMPLATE_SHORE31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH31\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore32(\n\tTEMPLATE_SHORE32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH32\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore33(\n\tTEMPLATE_SHORE33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH33\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore34(\n\tTEMPLATE_SHORE34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH34\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore35(\n\tTEMPLATE_SHORE35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH35\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore36(\n\tTEMPLATE_SHORE36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH36\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore37(\n\tTEMPLATE_SHORE37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH37\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore38(\n\tTEMPLATE_SHORE38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH38\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore39(\n\tTEMPLATE_SHORE39,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH39\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore40(\n\tTEMPLATE_SHORE40,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH40\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore41(\n\tTEMPLATE_SHORE41,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH41\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore42(\n\tTEMPLATE_SHORE42,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH42\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore43(\n\tTEMPLATE_SHORE43,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH43\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore44(\n\tTEMPLATE_SHORE44,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH44\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore45(\n\tTEMPLATE_SHORE45,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH45\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore46(\n\tTEMPLATE_SHORE46,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH46\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore47(\n\tTEMPLATE_SHORE47,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH47\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore48(\n\tTEMPLATE_SHORE48,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH48\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore49(\n\tTEMPLATE_SHORE49,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH49\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore50(\n\tTEMPLATE_SHORE50,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH50\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore51(\n\tTEMPLATE_SHORE51,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH51\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore52(\n\tTEMPLATE_SHORE52,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH52\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore53(\n\tTEMPLATE_SHORE53,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH53\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore54(\n\tTEMPLATE_SHORE54,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH54\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore55(\n\tTEMPLATE_SHORE55,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH55\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Shore56(\n\tTEMPLATE_SHORE56,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"SH56\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Boulder1(\n\tTEMPLATE_BOULDER1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B1\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder2(\n\tTEMPLATE_BOULDER2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B2\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder3(\n\tTEMPLATE_BOULDER3,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B3\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder4(\n\tTEMPLATE_BOULDER4,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B4\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder5(\n\tTEMPLATE_BOULDER5,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B5\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Boulder6(\n\tTEMPLATE_BOULDER6,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"B6\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope01(\n\tTEMPLATE_SLOPE01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S01\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope02(\n\tTEMPLATE_SLOPE02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S02\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope03(\n\tTEMPLATE_SLOPE03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S03\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope04(\n\tTEMPLATE_SLOPE04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S04\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope05(\n\tTEMPLATE_SLOPE05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S05\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope06(\n\tTEMPLATE_SLOPE06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S06\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope07(\n\tTEMPLATE_SLOPE07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S07\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope08(\n\tTEMPLATE_SLOPE08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S08\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope09(\n\tTEMPLATE_SLOPE09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S09\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope10(\n\tTEMPLATE_SLOPE10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S10\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope11(\n\tTEMPLATE_SLOPE11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S11\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope12(\n\tTEMPLATE_SLOPE12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S12\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope13(\n\tTEMPLATE_SLOPE13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S13\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope14(\n\tTEMPLATE_SLOPE14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S14\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope15(\n\tTEMPLATE_SLOPE15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S15\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope16(\n\tTEMPLATE_SLOPE16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S16\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope17(\n\tTEMPLATE_SLOPE17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S17\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope18(\n\tTEMPLATE_SLOPE18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S18\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope19(\n\tTEMPLATE_SLOPE19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S19\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope20(\n\tTEMPLATE_SLOPE20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S20\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope21(\n\tTEMPLATE_SLOPE21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S21\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope22(\n\tTEMPLATE_SLOPE22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S22\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope23(\n\tTEMPLATE_SLOPE23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S23\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope24(\n\tTEMPLATE_SLOPE24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S24\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope25(\n\tTEMPLATE_SLOPE25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S25\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope26(\n\tTEMPLATE_SLOPE26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S26\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope27(\n\tTEMPLATE_SLOPE27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S27\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope28(\n\tTEMPLATE_SLOPE28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S28\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope29(\n\tTEMPLATE_SLOPE29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S29\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope30(\n\tTEMPLATE_SLOPE30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S30\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope31(\n\tTEMPLATE_SLOPE31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S31\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope32(\n\tTEMPLATE_SLOPE32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S32\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope33(\n\tTEMPLATE_SLOPE33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S33\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope34(\n\tTEMPLATE_SLOPE34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S34\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope35(\n\tTEMPLATE_SLOPE35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S35\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope36(\n\tTEMPLATE_SLOPE36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S36\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope37(\n\tTEMPLATE_SLOPE37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S37\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Slope38(\n\tTEMPLATE_SLOPE38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"S38\",\n\tTXT_SLOPE\n);\nstatic TemplateTypeClass const Patch01(\n\tTEMPLATE_PATCH01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P01\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch02(\n\tTEMPLATE_PATCH02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P02\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch03(\n\tTEMPLATE_PATCH03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P03\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch04(\n\tTEMPLATE_PATCH04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P04\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch07(\n\tTEMPLATE_PATCH07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P07\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch08(\n\tTEMPLATE_PATCH08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P08\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch13(\n\tTEMPLATE_PATCH13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P13\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch14(\n\tTEMPLATE_PATCH14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P14\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const Patch15(\n\tTEMPLATE_PATCH15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"P15\",\n\tTXT_PATCH\n);\nstatic TemplateTypeClass const River01(\n\tTEMPLATE_RIVER01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River02(\n\tTEMPLATE_RIVER02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River03(\n\tTEMPLATE_RIVER03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River04(\n\tTEMPLATE_RIVER04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV04\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River05(\n\tTEMPLATE_RIVER05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV05\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River06(\n\tTEMPLATE_RIVER06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV06\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River07(\n\tTEMPLATE_RIVER07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV07\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River08(\n\tTEMPLATE_RIVER08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV08\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River09(\n\tTEMPLATE_RIVER09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV09\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River10(\n\tTEMPLATE_RIVER10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV10\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River11(\n\tTEMPLATE_RIVER11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV11\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River12(\n\tTEMPLATE_RIVER12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV12\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River13(\n\tTEMPLATE_RIVER13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV13\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River14(\n\tTEMPLATE_RIVER14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV14\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const River15(\n\tTEMPLATE_RIVER15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RV15\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Ford1(\n\tTEMPLATE_FORD1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FORD1\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Ford2(\n\tTEMPLATE_FORD2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FORD2\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls1(\n\tTEMPLATE_FALLS1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS1\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls1a(\n\tTEMPLATE_FALLS1A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS1A\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls2(\n\tTEMPLATE_FALLS2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS2\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Falls2a(\n\tTEMPLATE_FALLS2A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"FALLS2A\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const Bridge1x(\n\tTEMPLATE_BRIDGE1X,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1(\n\tTEMPLATE_BRIDGE1,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1h(\n\tTEMPLATE_BRIDGE1H,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1H\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1d(\n\tTEMPLATE_BRIDGE1D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE1D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2x(\n\tTEMPLATE_BRIDGE2X,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2(\n\tTEMPLATE_BRIDGE2,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2h(\n\tTEMPLATE_BRIDGE2H,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2H\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2d(\n\tTEMPLATE_BRIDGE2D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BRIDGE2D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1ax(\n\tTEMPLATE_BRIDGE_1AX,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1a(\n\tTEMPLATE_BRIDGE_1A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1b(\n\tTEMPLATE_BRIDGE_1B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge1c(\n\tTEMPLATE_BRIDGE_1C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR1C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2ax(\n\tTEMPLATE_BRIDGE_2AX,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2X\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2a(\n\tTEMPLATE_BRIDGE_2A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2b(\n\tTEMPLATE_BRIDGE_2B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge2c(\n\tTEMPLATE_BRIDGE_2C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR2C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3a(\n\tTEMPLATE_BRIDGE_3A,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3A\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3b(\n\tTEMPLATE_BRIDGE_3B,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3B\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3c(\n\tTEMPLATE_BRIDGE_3C,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3C\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3d(\n\tTEMPLATE_BRIDGE_3D,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3D\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3e(\n\tTEMPLATE_BRIDGE_3E,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3E\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const Bridge3f(\n\tTEMPLATE_BRIDGE_3F,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"BR3F\",\n\tTXT_BRIDGE\n);\nstatic TemplateTypeClass const ShoreCliff01(\n\tTEMPLATE_SHORECLIFF01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC01\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff02(\n\tTEMPLATE_SHORECLIFF02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC02\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff03(\n\tTEMPLATE_SHORECLIFF03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC03\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff04(\n\tTEMPLATE_SHORECLIFF04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC04\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff05(\n\tTEMPLATE_SHORECLIFF05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC05\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff06(\n\tTEMPLATE_SHORECLIFF06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC06\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff07(\n\tTEMPLATE_SHORECLIFF07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC07\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff08(\n\tTEMPLATE_SHORECLIFF08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC08\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff09(\n\tTEMPLATE_SHORECLIFF09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC09\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff10(\n\tTEMPLATE_SHORECLIFF10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC10\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff11(\n\tTEMPLATE_SHORECLIFF11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC11\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff12(\n\tTEMPLATE_SHORECLIFF12,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC12\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff13(\n\tTEMPLATE_SHORECLIFF13,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC13\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff14(\n\tTEMPLATE_SHORECLIFF14,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC14\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff15(\n\tTEMPLATE_SHORECLIFF15,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC15\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff16(\n\tTEMPLATE_SHORECLIFF16,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC16\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff17(\n\tTEMPLATE_SHORECLIFF17,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC17\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff18(\n\tTEMPLATE_SHORECLIFF18,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC18\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff19(\n\tTEMPLATE_SHORECLIFF19,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC19\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff20(\n\tTEMPLATE_SHORECLIFF20,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC20\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff21(\n\tTEMPLATE_SHORECLIFF21,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC21\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff22(\n\tTEMPLATE_SHORECLIFF22,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC22\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff23(\n\tTEMPLATE_SHORECLIFF23,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC23\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff24(\n\tTEMPLATE_SHORECLIFF24,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC24\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff25(\n\tTEMPLATE_SHORECLIFF25,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC25\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff26(\n\tTEMPLATE_SHORECLIFF26,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC26\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff27(\n\tTEMPLATE_SHORECLIFF27,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC27\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff28(\n\tTEMPLATE_SHORECLIFF28,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC28\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff29(\n\tTEMPLATE_SHORECLIFF29,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC29\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff30(\n\tTEMPLATE_SHORECLIFF30,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC30\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff31(\n\tTEMPLATE_SHORECLIFF31,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC31\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff32(\n\tTEMPLATE_SHORECLIFF32,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC32\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff33(\n\tTEMPLATE_SHORECLIFF33,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC33\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff34(\n\tTEMPLATE_SHORECLIFF34,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC34\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff35(\n\tTEMPLATE_SHORECLIFF35,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC35\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff36(\n\tTEMPLATE_SHORECLIFF36,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC36\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff37(\n\tTEMPLATE_SHORECLIFF37,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC37\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const ShoreCliff38(\n\tTEMPLATE_SHORECLIFF38,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"WC38\",\n\tTXT_SHORE\n);\nstatic TemplateTypeClass const Rough01(\n\tTEMPLATE_ROUGH01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF01\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough02(\n\tTEMPLATE_ROUGH02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF02\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough03(\n\tTEMPLATE_ROUGH03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF03\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough04(\n\tTEMPLATE_ROUGH04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF04\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough05(\n\tTEMPLATE_ROUGH05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF05\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough06(\n\tTEMPLATE_ROUGH06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF06\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough07(\n\tTEMPLATE_ROUGH07,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF07\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough08(\n\tTEMPLATE_ROUGH08,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF08\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough09(\n\tTEMPLATE_ROUGH09,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF09\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough10(\n\tTEMPLATE_ROUGH10,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF10\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const Rough11(\n\tTEMPLATE_ROUGH11,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RF11\",\n\tTXT_ROCK\n);\nstatic TemplateTypeClass const RiverCliff01(\n\tTEMPLATE_RIVERCLIFF01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff02(\n\tTEMPLATE_RIVERCLIFF02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff03(\n\tTEMPLATE_RIVERCLIFF03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const RiverCliff04(\n\tTEMPLATE_RIVERCLIFF04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"RC04\",\n\tTXT_RIVER\n);\n\nstatic TemplateTypeClass const F01(\n\tTEMPLATE_F01,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F01\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F02(\n\tTEMPLATE_F02,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F02\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F03(\n\tTEMPLATE_F03,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F03\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F04(\n\tTEMPLATE_F04,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F04\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F05(\n\tTEMPLATE_F05,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F05\",\n\tTXT_RIVER\n);\nstatic TemplateTypeClass const F06(\n\tTEMPLATE_F06,\n\tTHEATERF_TEMPERATE|THEATERF_SNOW,\n\t\"F06\",\n\tTXT_RIVER\n);\n\nstatic TemplateTypeClass const ARRO0001(\n\tTEMPLATE_ARRO0001,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0002(\n\tTEMPLATE_ARRO0002,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0003(\n\tTEMPLATE_ARRO0003,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0004(\n\tTEMPLATE_ARRO0004,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0005(\n\tTEMPLATE_ARRO0005,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0006(\n\tTEMPLATE_ARRO0006,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0007(\n\tTEMPLATE_ARRO0007,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0008(\n\tTEMPLATE_ARRO0008,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0009(\n\tTEMPLATE_ARRO0009,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0010(\n\tTEMPLATE_ARRO0010,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0011(\n\tTEMPLATE_ARRO0011,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0012(\n\tTEMPLATE_ARRO0012,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0013(\n\tTEMPLATE_ARRO0013,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0014(\n\tTEMPLATE_ARRO0014,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const ARRO0015(\n\tTEMPLATE_ARRO0015,\n\tTHEATERF_INTERIOR,\n\t\"ARRO0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0001(\n\tTEMPLATE_FLOR0001,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0002(\n\tTEMPLATE_FLOR0002,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0003(\n\tTEMPLATE_FLOR0003,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0004(\n\tTEMPLATE_FLOR0004,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0005(\n\tTEMPLATE_FLOR0005,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0006(\n\tTEMPLATE_FLOR0006,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const FLOR0007(\n\tTEMPLATE_FLOR0007,\n\tTHEATERF_INTERIOR,\n\t\"FLOR0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0001(\n\tTEMPLATE_GFLR0001,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0002(\n\tTEMPLATE_GFLR0002,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0003(\n\tTEMPLATE_GFLR0003,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0004(\n\tTEMPLATE_GFLR0004,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GFLR0005(\n\tTEMPLATE_GFLR0005,\n\tTHEATERF_INTERIOR,\n\t\"GFLR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0001(\n\tTEMPLATE_GSTR0001,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0002(\n\tTEMPLATE_GSTR0002,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0003(\n\tTEMPLATE_GSTR0003,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0004(\n\tTEMPLATE_GSTR0004,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0005(\n\tTEMPLATE_GSTR0005,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0006(\n\tTEMPLATE_GSTR0006,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0007(\n\tTEMPLATE_GSTR0007,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0008(\n\tTEMPLATE_GSTR0008,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0009(\n\tTEMPLATE_GSTR0009,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0010(\n\tTEMPLATE_GSTR0010,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const GSTR0011(\n\tTEMPLATE_GSTR0011,\n\tTHEATERF_INTERIOR,\n\t\"GSTR0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0001(\n\tTEMPLATE_LWAL0001,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0002(\n\tTEMPLATE_LWAL0002,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0003(\n\tTEMPLATE_LWAL0003,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0004(\n\tTEMPLATE_LWAL0004,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0005(\n\tTEMPLATE_LWAL0005,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0006(\n\tTEMPLATE_LWAL0006,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0007(\n\tTEMPLATE_LWAL0007,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0008(\n\tTEMPLATE_LWAL0008,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0009(\n\tTEMPLATE_LWAL0009,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0010(\n\tTEMPLATE_LWAL0010,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0011(\n\tTEMPLATE_LWAL0011,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0012(\n\tTEMPLATE_LWAL0012,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0013(\n\tTEMPLATE_LWAL0013,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0014(\n\tTEMPLATE_LWAL0014,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0015(\n\tTEMPLATE_LWAL0015,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0016(\n\tTEMPLATE_LWAL0016,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0016\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0017(\n\tTEMPLATE_LWAL0017,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0017\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0018(\n\tTEMPLATE_LWAL0018,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0018\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0019(\n\tTEMPLATE_LWAL0019,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0019\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0020(\n\tTEMPLATE_LWAL0020,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0020\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0021(\n\tTEMPLATE_LWAL0021,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0021\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0022(\n\tTEMPLATE_LWAL0022,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0022\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0023(\n\tTEMPLATE_LWAL0023,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0023\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0024(\n\tTEMPLATE_LWAL0024,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0024\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0025(\n\tTEMPLATE_LWAL0025,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0025\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0026(\n\tTEMPLATE_LWAL0026,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0026\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const LWAL0027(\n\tTEMPLATE_LWAL0027,\n\tTHEATERF_INTERIOR,\n\t\"LWAL0027\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0001(\n\tTEMPLATE_STRP0001,\n\tTHEATERF_INTERIOR,\n\t\"STRP0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0002(\n\tTEMPLATE_STRP0002,\n\tTHEATERF_INTERIOR,\n\t\"STRP0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0003(\n\tTEMPLATE_STRP0003,\n\tTHEATERF_INTERIOR,\n\t\"STRP0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0004(\n\tTEMPLATE_STRP0004,\n\tTHEATERF_INTERIOR,\n\t\"STRP0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0005(\n\tTEMPLATE_STRP0005,\n\tTHEATERF_INTERIOR,\n\t\"STRP0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0006(\n\tTEMPLATE_STRP0006,\n\tTHEATERF_INTERIOR,\n\t\"STRP0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0007(\n\tTEMPLATE_STRP0007,\n\tTHEATERF_INTERIOR,\n\t\"STRP0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0008(\n\tTEMPLATE_STRP0008,\n\tTHEATERF_INTERIOR,\n\t\"STRP0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0009(\n\tTEMPLATE_STRP0009,\n\tTHEATERF_INTERIOR,\n\t\"STRP0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0010(\n\tTEMPLATE_STRP0010,\n\tTHEATERF_INTERIOR,\n\t\"STRP0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const STRP0011(\n\tTEMPLATE_STRP0011,\n\tTHEATERF_INTERIOR,\n\t\"STRP0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0001(\n\tTEMPLATE_WALL0001,\n\tTHEATERF_INTERIOR,\n\t\"WALL0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0002(\n\tTEMPLATE_WALL0002,\n\tTHEATERF_INTERIOR,\n\t\"WALL0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0003(\n\tTEMPLATE_WALL0003,\n\tTHEATERF_INTERIOR,\n\t\"WALL0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0004(\n\tTEMPLATE_WALL0004,\n\tTHEATERF_INTERIOR,\n\t\"WALL0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0005(\n\tTEMPLATE_WALL0005,\n\tTHEATERF_INTERIOR,\n\t\"WALL0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0006(\n\tTEMPLATE_WALL0006,\n\tTHEATERF_INTERIOR,\n\t\"WALL0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0007(\n\tTEMPLATE_WALL0007,\n\tTHEATERF_INTERIOR,\n\t\"WALL0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0008(\n\tTEMPLATE_WALL0008,\n\tTHEATERF_INTERIOR,\n\t\"WALL0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0009(\n\tTEMPLATE_WALL0009,\n\tTHEATERF_INTERIOR,\n\t\"WALL0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0010(\n\tTEMPLATE_WALL0010,\n\tTHEATERF_INTERIOR,\n\t\"WALL0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0011(\n\tTEMPLATE_WALL0011,\n\tTHEATERF_INTERIOR,\n\t\"WALL0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0012(\n\tTEMPLATE_WALL0012,\n\tTHEATERF_INTERIOR,\n\t\"WALL0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0013(\n\tTEMPLATE_WALL0013,\n\tTHEATERF_INTERIOR,\n\t\"WALL0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0014(\n\tTEMPLATE_WALL0014,\n\tTHEATERF_INTERIOR,\n\t\"WALL0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0015(\n\tTEMPLATE_WALL0015,\n\tTHEATERF_INTERIOR,\n\t\"WALL0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0016(\n\tTEMPLATE_WALL0016,\n\tTHEATERF_INTERIOR,\n\t\"WALL0016\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0017(\n\tTEMPLATE_WALL0017,\n\tTHEATERF_INTERIOR,\n\t\"WALL0017\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0018(\n\tTEMPLATE_WALL0018,\n\tTHEATERF_INTERIOR,\n\t\"WALL0018\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0019(\n\tTEMPLATE_WALL0019,\n\tTHEATERF_INTERIOR,\n\t\"WALL0019\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0020(\n\tTEMPLATE_WALL0020,\n\tTHEATERF_INTERIOR,\n\t\"WALL0020\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0021(\n\tTEMPLATE_WALL0021,\n\tTHEATERF_INTERIOR,\n\t\"WALL0021\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0022(\n\tTEMPLATE_WALL0022,\n\tTHEATERF_INTERIOR,\n\t\"WALL0022\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0023(\n\tTEMPLATE_WALL0023,\n\tTHEATERF_INTERIOR,\n\t\"WALL0023\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0024(\n\tTEMPLATE_WALL0024,\n\tTHEATERF_INTERIOR,\n\t\"WALL0024\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0025(\n\tTEMPLATE_WALL0025,\n\tTHEATERF_INTERIOR,\n\t\"WALL0025\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0026(\n\tTEMPLATE_WALL0026,\n\tTHEATERF_INTERIOR,\n\t\"WALL0026\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0027(\n\tTEMPLATE_WALL0027,\n\tTHEATERF_INTERIOR,\n\t\"WALL0027\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0028(\n\tTEMPLATE_WALL0028,\n\tTHEATERF_INTERIOR,\n\t\"WALL0028\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0029(\n\tTEMPLATE_WALL0029,\n\tTHEATERF_INTERIOR,\n\t\"WALL0029\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0030(\n\tTEMPLATE_WALL0030,\n\tTHEATERF_INTERIOR,\n\t\"WALL0030\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0031(\n\tTEMPLATE_WALL0031,\n\tTHEATERF_INTERIOR,\n\t\"WALL0031\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0032(\n\tTEMPLATE_WALL0032,\n\tTHEATERF_INTERIOR,\n\t\"WALL0032\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0033(\n\tTEMPLATE_WALL0033,\n\tTHEATERF_INTERIOR,\n\t\"WALL0033\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0034(\n\tTEMPLATE_WALL0034,\n\tTHEATERF_INTERIOR,\n\t\"WALL0034\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0035(\n\tTEMPLATE_WALL0035,\n\tTHEATERF_INTERIOR,\n\t\"WALL0035\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0036(\n\tTEMPLATE_WALL0036,\n\tTHEATERF_INTERIOR,\n\t\"WALL0036\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0037(\n\tTEMPLATE_WALL0037,\n\tTHEATERF_INTERIOR,\n\t\"WALL0037\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0038(\n\tTEMPLATE_WALL0038,\n\tTHEATERF_INTERIOR,\n\t\"WALL0038\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0039(\n\tTEMPLATE_WALL0039,\n\tTHEATERF_INTERIOR,\n\t\"WALL0039\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0040(\n\tTEMPLATE_WALL0040,\n\tTHEATERF_INTERIOR,\n\t\"WALL0040\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0041(\n\tTEMPLATE_WALL0041,\n\tTHEATERF_INTERIOR,\n\t\"WALL0041\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0042(\n\tTEMPLATE_WALL0042,\n\tTHEATERF_INTERIOR,\n\t\"WALL0042\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0043(\n\tTEMPLATE_WALL0043,\n\tTHEATERF_INTERIOR,\n\t\"WALL0043\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0044(\n\tTEMPLATE_WALL0044,\n\tTHEATERF_INTERIOR,\n\t\"WALL0044\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0045(\n\tTEMPLATE_WALL0045,\n\tTHEATERF_INTERIOR,\n\t\"WALL0045\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0046(\n\tTEMPLATE_WALL0046,\n\tTHEATERF_INTERIOR,\n\t\"WALL0046\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0047(\n\tTEMPLATE_WALL0047,\n\tTHEATERF_INTERIOR,\n\t\"WALL0047\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0048(\n\tTEMPLATE_WALL0048,\n\tTHEATERF_INTERIOR,\n\t\"WALL0048\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const WALL0049(\n\tTEMPLATE_WALL0049,\n\tTHEATERF_INTERIOR,\n\t\"WALL0049\",\n\tTXT_INTERIOR\n);\n\nstatic TemplateTypeClass const Xtra0001(\n\tTEMPLATE_XTRA0001,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0001\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0002(\n\tTEMPLATE_XTRA0002,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0002\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0003(\n\tTEMPLATE_XTRA0003,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0003\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0004(\n\tTEMPLATE_XTRA0004,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0004\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0005(\n\tTEMPLATE_XTRA0005,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0005\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0006(\n\tTEMPLATE_XTRA0006,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0006\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0007(\n\tTEMPLATE_XTRA0007,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0007\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0008(\n\tTEMPLATE_XTRA0008,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0008\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0009(\n\tTEMPLATE_XTRA0009,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0009\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0010(\n\tTEMPLATE_XTRA0010,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0010\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0011(\n\tTEMPLATE_XTRA0011,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0011\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0012(\n\tTEMPLATE_XTRA0012,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0012\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0013(\n\tTEMPLATE_XTRA0013,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0013\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0014(\n\tTEMPLATE_XTRA0014,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0014\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0015(\n\tTEMPLATE_XTRA0015,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0015\",\n\tTXT_INTERIOR\n);\nstatic TemplateTypeClass const Xtra0016(\n\tTEMPLATE_XTRA0016,\n\tTHEATERF_INTERIOR,\n\t\"XTRA0016\",\n\tTXT_INTERIOR\n);\n\n#ifdef FIXIT_ANTS\nstatic TemplateTypeClass const AntHill(\n\tTEMPLATE_HILL01,\n\tTHEATERF_TEMPERATE,\n\t\"HILL01\",\n\tTXT_ROCK\n);\n#endif\n\n/***********************************************************************************************\n * TemplateTypeClass::TemplateTypeClass -- Constructor for template type objects.              *\n *                                                                                             *\n *    This is the constructor for the template types.                                          *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateTypeClass::TemplateTypeClass(\n\tTemplateType iconset,\n\tint theater,\n\tchar const * ininame,\n\tint fullname) :\n\t\tObjectTypeClass(\n\t\t\tRTTI_TEMPLATETYPE,\n\t\t\tint(iconset),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfullname,\n\t\t\tininame),\n\tType(iconset),\n\tTheater(theater),\n\tWidth(0),\n\tHeight(0)\n{\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::operator new -- Allocates a template type from special heap.             *\n *                                                                                             *\n *    This allocates a template type object from the special heap used for that purpose.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated template type object. If no object   *\n *          could be allocated, then NULL is returned.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * TemplateTypeClass::operator new(size_t)\n{\n\treturn(TemplateTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::operator delete -- Deletes a template type object.                       *\n *                                                                                             *\n *    This routine will return a template type object back to the special heap it was          *\n *    allocated from.                                                                          *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the template type object to free.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::operator delete(void * ptr)\n{\n\tTemplateTypes.Free((TemplateTypeClass *)ptr);\n}\n\n\nstatic void _Watcom_Ugh_Hack(void)\n{\n\t(void)new TemplateTypeClass(Road37);\t\t\t//\tTEMPLATE_ROAD37\n\t(void)new TemplateTypeClass(Road38);\t\t\t//\tTEMPLATE_ROAD38\n\t(void)new TemplateTypeClass(Road39);\t\t\t//\tTEMPLATE_ROAD39\n\t(void)new TemplateTypeClass(Road40);\t\t\t//\tTEMPLATE_ROAD40\n\t(void)new TemplateTypeClass(Road41);\t\t\t//\tTEMPLATE_ROAD41\n\t(void)new TemplateTypeClass(Road42);\t\t\t//\tTEMPLATE_ROAD42\n\t(void)new TemplateTypeClass(Road43);\t\t\t//\tTEMPLATE_ROAD43\n\t(void)new TemplateTypeClass(Rough01);\t\t\t// TEMPLATE_ROUGH01\n\t(void)new TemplateTypeClass(Rough02);\t\t\t// TEMPLATE_ROUGH02\n\t(void)new TemplateTypeClass(Rough03);\t\t\t// TEMPLATE_ROUGH03\n\t(void)new TemplateTypeClass(Rough04);\t\t\t// TEMPLATE_ROUGH04\n\t(void)new TemplateTypeClass(Rough05);\t\t\t// TEMPLATE_ROUGH05\n\t(void)new TemplateTypeClass(Rough06);\t\t\t// TEMPLATE_ROUGH06\n\t(void)new TemplateTypeClass(Rough07);\t\t\t// TEMPLATE_ROUGH07\n\t(void)new TemplateTypeClass(Rough08);\t\t\t// TEMPLATE_ROUGH08\n\t(void)new TemplateTypeClass(Rough09);\t\t\t// TEMPLATE_ROUGH09\n\t(void)new TemplateTypeClass(Rough10);\t\t\t// TEMPLATE_ROUGH10\n\t(void)new TemplateTypeClass(Rough11);\t\t\t// TEMPLATE_ROUGH11\n\t(void)new TemplateTypeClass(Road44);\t\t\t//\tTEMPLATE_ROAD44\n\t(void)new TemplateTypeClass(Road45);\t\t\t//\tTEMPLATE_ROAD45\n\t(void)new TemplateTypeClass(River14);\t\t\t//\tTEMPLATE_RIVER14\n\t(void)new TemplateTypeClass(River15);\t\t\t//\tTEMPLATE_RIVER15\n\t(void)new TemplateTypeClass(RiverCliff01);\t//\tTEMPLATE_RIVERCLIFF01\n\t(void)new TemplateTypeClass(RiverCliff02);\t//\tTEMPLATE_RIVERCLIFF02\n\t(void)new TemplateTypeClass(RiverCliff03);\t//\tTEMPLATE_RIVERCLIFF03\n\t(void)new TemplateTypeClass(RiverCliff04);\t//\tTEMPLATE_RIVERCLIFF04\n\t(void)new TemplateTypeClass(Bridge1a);\t\t\t//\tTEMPLATE_BRIDGE_1A\n\t(void)new TemplateTypeClass(Bridge1b);\t\t\t//\tTEMPLATE_BRIDGE_1B\n\t(void)new TemplateTypeClass(Bridge1c);\t\t\t//\tTEMPLATE_BRIDGE_1C\n\t(void)new TemplateTypeClass(Bridge2a);\t\t\t//\tTEMPLATE_BRIDGE_2A\n\t(void)new TemplateTypeClass(Bridge2b);\t\t\t//\tTEMPLATE_BRIDGE_2B\n\t(void)new TemplateTypeClass(Bridge2c);\t\t\t//\tTEMPLATE_BRIDGE_2C\n\t(void)new TemplateTypeClass(Bridge3a);\t\t\t//\tTEMPLATE_BRIDGE_3A\n\t(void)new TemplateTypeClass(Bridge3b);\t\t\t//\tTEMPLATE_BRIDGE_3B\n\t(void)new TemplateTypeClass(Bridge3c);\t\t\t//\tTEMPLATE_BRIDGE_3C\n\t(void)new TemplateTypeClass(Bridge3d);\t\t\t//\tTEMPLATE_BRIDGE_3D\n\t(void)new TemplateTypeClass(Bridge3e);\t\t\t//\tTEMPLATE_BRIDGE_3E\n\t(void)new TemplateTypeClass(Bridge3f);\t\t\t//\tTEMPLATE_BRIDGE_3F\n\t(void)new TemplateTypeClass(F01);\t\t\t\t//\tTEMPLATE_F01\n\t(void)new TemplateTypeClass(F02);\t\t\t\t//\tTEMPLATE_F02\n\t(void)new TemplateTypeClass(F03);\t\t\t\t//\tTEMPLATE_F03\n\t(void)new TemplateTypeClass(F04);\t\t\t\t//\tTEMPLATE_F04\n\t(void)new TemplateTypeClass(F05);\t\t\t\t//\tTEMPLATE_F05\n\t(void)new TemplateTypeClass(F06);\t\t\t\t//\tTEMPLATE_F06\n\t(void)new TemplateTypeClass(ARRO0001);\t\t\t//\tTEMPLATE_ARRO0001\n\t(void)new TemplateTypeClass(ARRO0002);\t\t\t//\tTEMPLATE_ARRO0002\n\t(void)new TemplateTypeClass(ARRO0003);\t\t\t//\tTEMPLATE_ARRO0003\n\t(void)new TemplateTypeClass(ARRO0004);\t\t\t//\tTEMPLATE_ARRO0004\n\t(void)new TemplateTypeClass(ARRO0005);\t\t\t//\tTEMPLATE_ARRO0005\n\t(void)new TemplateTypeClass(ARRO0006);\t\t\t//\tTEMPLATE_ARRO0006\n\t(void)new TemplateTypeClass(ARRO0007);\t\t\t//\tTEMPLATE_ARRO0007\n\t(void)new TemplateTypeClass(ARRO0008);\t\t\t//\tTEMPLATE_ARRO0008\n\t(void)new TemplateTypeClass(ARRO0009);\t\t\t//\tTEMPLATE_ARRO0009\n\t(void)new TemplateTypeClass(ARRO0010);\t\t\t//\tTEMPLATE_ARRO0010\n\t(void)new TemplateTypeClass(ARRO0011);\t\t\t//\tTEMPLATE_ARRO0011\n\t(void)new TemplateTypeClass(ARRO0012);\t\t\t//\tTEMPLATE_ARRO0012\n\t(void)new TemplateTypeClass(ARRO0013);\t\t\t//\tTEMPLATE_ARRO0013\n\t(void)new TemplateTypeClass(ARRO0014);\t\t\t//\tTEMPLATE_ARRO0014\n\t(void)new TemplateTypeClass(ARRO0015);\t\t\t//\tTEMPLATE_ARRO0015\n\t(void)new TemplateTypeClass(FLOR0001);\t\t\t//\tTEMPLATE_FLOR0001\n\t(void)new TemplateTypeClass(FLOR0002);\t\t\t//\tTEMPLATE_FLOR0002\n\t(void)new TemplateTypeClass(FLOR0003);\t\t\t//\tTEMPLATE_FLOR0003\n\t(void)new TemplateTypeClass(FLOR0004);\t\t\t//\tTEMPLATE_FLOR0004\n\t(void)new TemplateTypeClass(FLOR0005);\t\t\t//\tTEMPLATE_FLOR0005\n\t(void)new TemplateTypeClass(FLOR0006);\t\t\t//\tTEMPLATE_FLOR0006\n\t(void)new TemplateTypeClass(FLOR0007);\t\t\t//\tTEMPLATE_FLOR0007\n\t(void)new TemplateTypeClass(GFLR0001);\t\t\t//\tTEMPLATE_GFLR0001\n\t(void)new TemplateTypeClass(GFLR0002);\t\t\t//\tTEMPLATE_GFLR0002\n\t(void)new TemplateTypeClass(GFLR0003);\t\t\t//\tTEMPLATE_GFLR0003\n\t(void)new TemplateTypeClass(GFLR0004);\t\t\t//\tTEMPLATE_GFLR0004\n\t(void)new TemplateTypeClass(GFLR0005);\t\t\t//\tTEMPLATE_GFLR0005\n\t(void)new TemplateTypeClass(GSTR0001);\t\t\t//\tTEMPLATE_GSTR0001\n\t(void)new TemplateTypeClass(GSTR0002);\t\t\t//\tTEMPLATE_GSTR0002\n\t(void)new TemplateTypeClass(GSTR0003);\t\t\t//\tTEMPLATE_GSTR0003\n\t(void)new TemplateTypeClass(GSTR0004);\t\t\t//\tTEMPLATE_GSTR0004\n\t(void)new TemplateTypeClass(GSTR0005);\t\t\t//\tTEMPLATE_GSTR0005\n\t(void)new TemplateTypeClass(GSTR0006);\t\t\t//\tTEMPLATE_GSTR0006\n\t(void)new TemplateTypeClass(GSTR0007);\t\t\t//\tTEMPLATE_GSTR0007\n\t(void)new TemplateTypeClass(GSTR0008);\t\t\t//\tTEMPLATE_GSTR0008\n\t(void)new TemplateTypeClass(GSTR0009);\t\t\t//\tTEMPLATE_GSTR0009\n\t(void)new TemplateTypeClass(GSTR0010);\t\t\t//\tTEMPLATE_GSTR0010\n\t(void)new TemplateTypeClass(GSTR0011);\t\t\t//\tTEMPLATE_GSTR0011\n\t(void)new TemplateTypeClass(LWAL0001);\t\t\t//\tTEMPLATE_LWAL0001\n\t(void)new TemplateTypeClass(LWAL0002);\t\t\t//\tTEMPLATE_LWAL0002\n\t(void)new TemplateTypeClass(LWAL0003);\t\t\t//\tTEMPLATE_LWAL0003\n\t(void)new TemplateTypeClass(LWAL0004);\t\t\t//\tTEMPLATE_LWAL0004\n\t(void)new TemplateTypeClass(LWAL0005);\t\t\t//\tTEMPLATE_LWAL0005\n\t(void)new TemplateTypeClass(LWAL0006);\t\t\t//\tTEMPLATE_LWAL0006\n\t(void)new TemplateTypeClass(LWAL0007);\t\t\t//\tTEMPLATE_LWAL0007\n\t(void)new TemplateTypeClass(LWAL0008);\t\t\t//\tTEMPLATE_LWAL0008\n\t(void)new TemplateTypeClass(LWAL0009);\t\t\t//\tTEMPLATE_LWAL0009\n\t(void)new TemplateTypeClass(LWAL0010);\t\t\t//\tTEMPLATE_LWAL0010\n\t(void)new TemplateTypeClass(LWAL0011);\t\t\t//\tTEMPLATE_LWAL0011\n\t(void)new TemplateTypeClass(LWAL0012);\t\t\t//\tTEMPLATE_LWAL0012\n\t(void)new TemplateTypeClass(LWAL0013);\t\t\t//\tTEMPLATE_LWAL0013\n\t(void)new TemplateTypeClass(LWAL0014);\t\t\t//\tTEMPLATE_LWAL0014\n\t(void)new TemplateTypeClass(LWAL0015);\t\t\t//\tTEMPLATE_LWAL0015\n\t(void)new TemplateTypeClass(LWAL0016);\t\t\t//\tTEMPLATE_LWAL0016\n\t(void)new TemplateTypeClass(LWAL0017);\t\t\t//\tTEMPLATE_LWAL0017\n\t(void)new TemplateTypeClass(LWAL0018);\t\t\t//\tTEMPLATE_LWAL0018\n\t(void)new TemplateTypeClass(LWAL0019);\t\t\t//\tTEMPLATE_LWAL0019\n\t(void)new TemplateTypeClass(LWAL0020);\t\t\t//\tTEMPLATE_LWAL0020\n\t(void)new TemplateTypeClass(LWAL0021);\t\t\t//\tTEMPLATE_LWAL0021\n\t(void)new TemplateTypeClass(LWAL0022);\t\t\t//\tTEMPLATE_LWAL0022\n\t(void)new TemplateTypeClass(LWAL0023);\t\t\t//\tTEMPLATE_LWAL0023\n\t(void)new TemplateTypeClass(LWAL0024);\t\t\t//\tTEMPLATE_LWAL0024\n\t(void)new TemplateTypeClass(LWAL0025);\t\t\t//\tTEMPLATE_LWAL0025\n\t(void)new TemplateTypeClass(LWAL0026);\t\t\t//\tTEMPLATE_LWAL0026\n\t(void)new TemplateTypeClass(LWAL0027);\t\t\t//\tTEMPLATE_LWAL0027\n\t(void)new TemplateTypeClass(STRP0001);\t\t\t//\tTEMPLATE_STRP0001\n\t(void)new TemplateTypeClass(STRP0002);\t\t\t//\tTEMPLATE_STRP0002\n\t(void)new TemplateTypeClass(STRP0003);\t\t\t//\tTEMPLATE_STRP0003\n\t(void)new TemplateTypeClass(STRP0004);\t\t\t//\tTEMPLATE_STRP0004\n\t(void)new TemplateTypeClass(STRP0005);\t\t\t//\tTEMPLATE_STRP0005\n\t(void)new TemplateTypeClass(STRP0006);\t\t\t//\tTEMPLATE_STRP0006\n\t(void)new TemplateTypeClass(STRP0007);\t\t\t//\tTEMPLATE_STRP0007\n\t(void)new TemplateTypeClass(STRP0008);\t\t\t//\tTEMPLATE_STRP0008\n\t(void)new TemplateTypeClass(STRP0009);\t\t\t//\tTEMPLATE_STRP0009\n\t(void)new TemplateTypeClass(STRP0010);\t\t\t//\tTEMPLATE_STRP0010\n\t(void)new TemplateTypeClass(STRP0011);\t\t\t//\tTEMPLATE_STRP0011\n\t(void)new TemplateTypeClass(WALL0001);\t\t\t//\tTEMPLATE_WALL0001\n\t(void)new TemplateTypeClass(WALL0002);\t\t\t//\tTEMPLATE_WALL0002\n\t(void)new TemplateTypeClass(WALL0003);\t\t\t//\tTEMPLATE_WALL0003\n\t(void)new TemplateTypeClass(WALL0004);\t\t\t//\tTEMPLATE_WALL0004\n\t(void)new TemplateTypeClass(WALL0005);\t\t\t//\tTEMPLATE_WALL0005\n\t(void)new TemplateTypeClass(WALL0006);\t\t\t//\tTEMPLATE_WALL0006\n\t(void)new TemplateTypeClass(WALL0007);\t\t\t//\tTEMPLATE_WALL0007\n\t(void)new TemplateTypeClass(WALL0008);\t\t\t//\tTEMPLATE_WALL0008\n\t(void)new TemplateTypeClass(WALL0009);\t\t\t//\tTEMPLATE_WALL0009\n\t(void)new TemplateTypeClass(WALL0010);\t\t\t//\tTEMPLATE_WALL0010\n\t(void)new TemplateTypeClass(WALL0011);\t\t\t//\tTEMPLATE_WALL0011\n\t(void)new TemplateTypeClass(WALL0012);\t\t\t//\tTEMPLATE_WALL0012\n\t(void)new TemplateTypeClass(WALL0013);\t\t\t//\tTEMPLATE_WALL0013\n\t(void)new TemplateTypeClass(WALL0014);\t\t\t//\tTEMPLATE_WALL0014\n\t(void)new TemplateTypeClass(WALL0015);\t\t\t//\tTEMPLATE_WALL0015\n\t(void)new TemplateTypeClass(WALL0016);\t\t\t//\tTEMPLATE_WALL0016\n\t(void)new TemplateTypeClass(WALL0017);\t\t\t//\tTEMPLATE_WALL0017\n\t(void)new TemplateTypeClass(WALL0018);\t\t\t//\tTEMPLATE_WALL0018\n\t(void)new TemplateTypeClass(WALL0019);\t\t\t//\tTEMPLATE_WALL0019\n\t(void)new TemplateTypeClass(WALL0020);\t\t\t//\tTEMPLATE_WALL0020\n\t(void)new TemplateTypeClass(WALL0021);\t\t\t//\tTEMPLATE_WALL0021\n\t(void)new TemplateTypeClass(WALL0022);\t\t\t//\tTEMPLATE_WALL0022\n\t(void)new TemplateTypeClass(WALL0023);\t\t\t//\tTEMPLATE_WALL0023\n\t(void)new TemplateTypeClass(WALL0024);\t\t\t//\tTEMPLATE_WALL0024\n\t(void)new TemplateTypeClass(WALL0025);\t\t\t//\tTEMPLATE_WALL0025\n\t(void)new TemplateTypeClass(WALL0026);\t\t\t//\tTEMPLATE_WALL0026\n\t(void)new TemplateTypeClass(WALL0027);\t\t\t//\tTEMPLATE_WALL0027\n\t(void)new TemplateTypeClass(WALL0028);\t\t\t//\tTEMPLATE_WALL0028\n\t(void)new TemplateTypeClass(WALL0029);\t\t\t//\tTEMPLATE_WALL0029\n\t(void)new TemplateTypeClass(WALL0030);\t\t\t//\tTEMPLATE_WALL0030\n\t(void)new TemplateTypeClass(WALL0031);\t\t\t//\tTEMPLATE_WALL0031\n\t(void)new TemplateTypeClass(WALL0032);\t\t\t//\tTEMPLATE_WALL0032\n\t(void)new TemplateTypeClass(WALL0033);\t\t\t//\tTEMPLATE_WALL0033\n\t(void)new TemplateTypeClass(WALL0034);\t\t\t//\tTEMPLATE_WALL0034\n\t(void)new TemplateTypeClass(WALL0035);\t\t\t//\tTEMPLATE_WALL0035\n\t(void)new TemplateTypeClass(WALL0036);\t\t\t//\tTEMPLATE_WALL0036\n\t(void)new TemplateTypeClass(WALL0037);\t\t\t//\tTEMPLATE_WALL0037\n\t(void)new TemplateTypeClass(WALL0038);\t\t\t//\tTEMPLATE_WALL0038\n\t(void)new TemplateTypeClass(WALL0039);\t\t\t//\tTEMPLATE_WALL0039\n\t(void)new TemplateTypeClass(WALL0040);\t\t\t//\tTEMPLATE_WALL0040\n\t(void)new TemplateTypeClass(WALL0041);\t\t\t//\tTEMPLATE_WALL0041\n\t(void)new TemplateTypeClass(WALL0042);\t\t\t//\tTEMPLATE_WALL0042\n\t(void)new TemplateTypeClass(WALL0043);\t\t\t//\tTEMPLATE_WALL0043\n\t(void)new TemplateTypeClass(WALL0044);\t\t\t//\tTEMPLATE_WALL0044\n\t(void)new TemplateTypeClass(WALL0045);\t\t\t//\tTEMPLATE_WALL0045\n\t(void)new TemplateTypeClass(WALL0046);\t\t\t//\tTEMPLATE_WALL0046\n\t(void)new TemplateTypeClass(WALL0047);\t\t\t//\tTEMPLATE_WALL0047\n\t(void)new TemplateTypeClass(WALL0048);\t\t\t//\tTEMPLATE_WALL0048\n\t(void)new TemplateTypeClass(WALL0049);\t\t\t//\tTEMPLATE_WALL0049\n\t(void)new TemplateTypeClass(Bridge1h);\t\t\t//\tTEMPLATE_BRIDGE1H\n\t(void)new TemplateTypeClass(Bridge2h);\t\t\t//\tTEMPLATE_BRIDGE2H\n\n\t(void)new TemplateTypeClass(Bridge1ax);\t\t//\tTEMPLATE_BRIDGE_1AX\n\t(void)new TemplateTypeClass(Bridge2ax);\t\t//\tTEMPLATE_BRIDGE_2AX\n\t(void)new TemplateTypeClass(Bridge1x);\t\t\t//\tTEMPLATE_BRIDGE1X\n\t(void)new TemplateTypeClass(Bridge2x);\t\t\t//\tTEMPLATE_BRIDGE2X\n\n\t(void)new TemplateTypeClass(Xtra0001);\t\t\t//\tTEMPLATE_XTRA0001\n\t(void)new TemplateTypeClass(Xtra0002);\t\t\t//\tTEMPLATE_XTRA0002\n\t(void)new TemplateTypeClass(Xtra0003);\t\t\t//\tTEMPLATE_XTRA0003\n\t(void)new TemplateTypeClass(Xtra0004);\t\t\t//\tTEMPLATE_XTRA0004\n\t(void)new TemplateTypeClass(Xtra0005);\t\t\t//\tTEMPLATE_XTRA0005\n\t(void)new TemplateTypeClass(Xtra0006);\t\t\t//\tTEMPLATE_XTRA0006\n\t(void)new TemplateTypeClass(Xtra0007);\t\t\t//\tTEMPLATE_XTRA0007\n\t(void)new TemplateTypeClass(Xtra0008);\t\t\t//\tTEMPLATE_XTRA0008\n\t(void)new TemplateTypeClass(Xtra0009);\t\t\t//\tTEMPLATE_XTRA0009\n\t(void)new TemplateTypeClass(Xtra0010);\t\t\t//\tTEMPLATE_XTRA0010\n\t(void)new TemplateTypeClass(Xtra0011);\t\t\t//\tTEMPLATE_XTRA0011\n\t(void)new TemplateTypeClass(Xtra0012);\t\t\t//\tTEMPLATE_XTRA0012\n\t(void)new TemplateTypeClass(Xtra0013);\t\t\t//\tTEMPLATE_XTRA0013\n\t(void)new TemplateTypeClass(Xtra0014);\t\t\t//\tTEMPLATE_XTRA0014\n\t(void)new TemplateTypeClass(Xtra0015);\t\t\t//\tTEMPLATE_XTRA0015\n\t(void)new TemplateTypeClass(Xtra0016);\t\t\t//\tTEMPLATE_XTRA0016\n\n#ifdef FIXIT_ANTS\n\t(void)new TemplateTypeClass(AntHill);\t\t\t//\tTEMPLATE_ROAD36\n#endif\n}\n\n\n\nvoid TemplateTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese template type class objects must be allocated in the exact order that they\n\t**\tare specified in the TemplateType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\t(void)new TemplateTypeClass(Clear);\t\t\t\t// TEMPLATE_CLEAR1\n\t(void)new TemplateTypeClass(Water);\t\t\t\t// TEMPLATE_WATER\n\t(void)new TemplateTypeClass(Water2);\t\t\t// TEMPLATE_WATER2\n\t(void)new TemplateTypeClass(Shore01);\t\t\t// TEMPLATE_SHORE1\n\t(void)new TemplateTypeClass(Shore02);\t\t\t// TEMPLATE_SHORE2\n\t(void)new TemplateTypeClass(Shore03);\t\t\t// TEMPLATE_SHORE3\n\t(void)new TemplateTypeClass(Shore04);\t\t\t// TEMPLATE_SHORE4\n\t(void)new TemplateTypeClass(Shore05);\t\t\t// TEMPLATE_SHORE5\n\t(void)new TemplateTypeClass(Shore06);\t\t\t// TEMPLATE_SHORE6\n\t(void)new TemplateTypeClass(Shore07);\t\t\t// TEMPLATE_SHORE7\n\t(void)new TemplateTypeClass(Shore08);\t\t\t// TEMPLATE_SHORE8\n\t(void)new TemplateTypeClass(Shore09);\t\t\t// TEMPLATE_SHORE9\n\t(void)new TemplateTypeClass(Shore10);\t\t\t// TEMPLATE_SHORE10\n\t(void)new TemplateTypeClass(Shore11);\t\t\t//\tTEMPLATE_SHORE11\n\t(void)new TemplateTypeClass(Shore12);\t\t\t// TEMPLATE_SHORE12\n\t(void)new TemplateTypeClass(Shore13);\t\t\t// TEMPLATE_SHORE13\n\t(void)new TemplateTypeClass(Shore14);\t\t\t// TEMPLATE_SHORE14\n\t(void)new TemplateTypeClass(Shore15);\t\t\t// TEMPLATE_SHORE15\n\t(void)new TemplateTypeClass(Shore16);\t\t\t//\tTEMPLATE_SHORE16\n\t(void)new TemplateTypeClass(Shore17);\t\t\t//\tTEMPLATE_SHORE17\n\t(void)new TemplateTypeClass(Shore18);\t\t\t//\tTEMPLATE_SHORE18\n\t(void)new TemplateTypeClass(Shore19);\t\t\t// TEMPLATE_SHORE19\n\t(void)new TemplateTypeClass(Shore20);\t\t\t// TEMPLATE_SHORE20\n\t(void)new TemplateTypeClass(Shore21);\t\t\t// TEMPLATE_SHORE21\n\t(void)new TemplateTypeClass(Shore22);\t\t\t//\tTEMPLATE_SHORE22\n\t(void)new TemplateTypeClass(Shore23);\t\t\t// TEMPLATE_SHORE23\n\t(void)new TemplateTypeClass(Shore24);\t\t\t//\tTEMPLATE_SHORE24\n\t(void)new TemplateTypeClass(Shore25);\t\t\t//\tTEMPLATE_SHORE25\n\t(void)new TemplateTypeClass(Shore26);\t\t\t//\tTEMPLATE_SHORE26\n\t(void)new TemplateTypeClass(Shore27);\t\t\t//\tTEMPLATE_SHORE27\n\t(void)new TemplateTypeClass(Shore28);\t\t\t//\tTEMPLATE_SHORE28\n\t(void)new TemplateTypeClass(Shore29);\t\t\t//\tTEMPLATE_SHORE29\n\t(void)new TemplateTypeClass(Shore30);\t\t\t//\tTEMPLATE_SHORE30\n\t(void)new TemplateTypeClass(Shore31);\t\t\t//\tTEMPLATE_SHORE31\n\t(void)new TemplateTypeClass(Shore32);\t\t\t// TEMPLATE_SHORE32\n\t(void)new TemplateTypeClass(Shore33);\t\t\t// TEMPLATE_SHORE33\n\t(void)new TemplateTypeClass(Shore34);\t\t\t//\tTEMPLATE_SHORE34\n\t(void)new TemplateTypeClass(Shore35);\t\t\t//\tTEMPLATE_SHORE35\n\t(void)new TemplateTypeClass(Shore36);\t\t\t//\tTEMPLATE_SHORE36\n\t(void)new TemplateTypeClass(Shore37);\t\t\t//\tTEMPLATE_SHORE37\n\t(void)new TemplateTypeClass(Shore38);\t\t\t//\tTEMPLATE_SHORE38\n\t(void)new TemplateTypeClass(Shore39);\t\t\t//\tTEMPLATE_SHORE39\n\t(void)new TemplateTypeClass(Shore40);\t\t\t//\tTEMPLATE_SHORE40\n\t(void)new TemplateTypeClass(Shore41);\t\t\t//\tTEMPLATE_SHORE41\n\t(void)new TemplateTypeClass(Shore42);\t\t\t//\tTEMPLATE_SHORE42\n\t(void)new TemplateTypeClass(Shore43);\t\t\t//\tTEMPLATE_SHORE43\n\t(void)new TemplateTypeClass(Shore44);\t\t\t//\tTEMPLATE_SHORE44\n\t(void)new TemplateTypeClass(Shore45);\t\t\t//\tTEMPLATE_SHORE45\n\t(void)new TemplateTypeClass(Shore46);\t\t\t//\tTEMPLATE_SHORE46\n\t(void)new TemplateTypeClass(Shore47);\t\t\t//\tTEMPLATE_SHORE47\n\t(void)new TemplateTypeClass(Shore48);\t\t\t//\tTEMPLATE_SHORE48\n\t(void)new TemplateTypeClass(Shore49);\t\t\t//\tTEMPLATE_SHORE49\n\t(void)new TemplateTypeClass(Shore50);\t\t\t//\tTEMPLATE_SHORE50\n\t(void)new TemplateTypeClass(Shore51);\t\t\t//\tTEMPLATE_SHORE51\n\t(void)new TemplateTypeClass(Shore52);\t\t\t//\tTEMPLATE_SHORE52\n\t(void)new TemplateTypeClass(Shore53);\t\t\t//\tTEMPLATE_SHORE53\n\t(void)new TemplateTypeClass(Shore54);\t\t\t//\tTEMPLATE_SHORE54\n\t(void)new TemplateTypeClass(Shore55);\t\t\t//\tTEMPLATE_SHORE55\n\t(void)new TemplateTypeClass(Shore56);\t\t\t//\tTEMPLATE_SHORE56\n\t(void)new TemplateTypeClass(ShoreCliff01);\t//\tTEMPLATE_SHORECLIFF01\n\t(void)new TemplateTypeClass(ShoreCliff02);\t//\tTEMPLATE_SHORECLIFF02\n\t(void)new TemplateTypeClass(ShoreCliff03);\t//\tTEMPLATE_SHORECLIFF03\n\t(void)new TemplateTypeClass(ShoreCliff04);\t//\tTEMPLATE_SHORECLIFF04\n\t(void)new TemplateTypeClass(ShoreCliff05);\t//\tTEMPLATE_SHORECLIFF05\n\t(void)new TemplateTypeClass(ShoreCliff06);\t//\tTEMPLATE_SHORECLIFF06\n\t(void)new TemplateTypeClass(ShoreCliff07);\t//\tTEMPLATE_SHORECLIFF07\n\t(void)new TemplateTypeClass(ShoreCliff08);\t//\tTEMPLATE_SHORECLIFF08\n\t(void)new TemplateTypeClass(ShoreCliff09);\t//\tTEMPLATE_SHORECLIFF09\n\t(void)new TemplateTypeClass(ShoreCliff10);\t//\tTEMPLATE_SHORECLIFF10\n\t(void)new TemplateTypeClass(ShoreCliff11);\t//\tTEMPLATE_SHORECLIFF11\n\t(void)new TemplateTypeClass(ShoreCliff12);\t//\tTEMPLATE_SHORECLIFF12\n\t(void)new TemplateTypeClass(ShoreCliff13);\t//\tTEMPLATE_SHORECLIFF13\n\t(void)new TemplateTypeClass(ShoreCliff14);\t//\tTEMPLATE_SHORECLIFF14\n\t(void)new TemplateTypeClass(ShoreCliff15);\t//\tTEMPLATE_SHORECLIFF15\n\t(void)new TemplateTypeClass(ShoreCliff16);\t//\tTEMPLATE_SHORECLIFF16\n\t(void)new TemplateTypeClass(ShoreCliff17);\t//\tTEMPLATE_SHORECLIFF17\n\t(void)new TemplateTypeClass(ShoreCliff18);\t//\tTEMPLATE_SHORECLIFF18\n\t(void)new TemplateTypeClass(ShoreCliff19);\t//\tTEMPLATE_SHORECLIFF19\n\t(void)new TemplateTypeClass(ShoreCliff20);\t//\tTEMPLATE_SHORECLIFF20\n\t(void)new TemplateTypeClass(ShoreCliff21);\t//\tTEMPLATE_SHORECLIFF21\n\t(void)new TemplateTypeClass(ShoreCliff22);\t//\tTEMPLATE_SHORECLIFF22\n\t(void)new TemplateTypeClass(ShoreCliff23);\t//\tTEMPLATE_SHORECLIFF23\n\t(void)new TemplateTypeClass(ShoreCliff24);\t//\tTEMPLATE_SHORECLIFF24\n\t(void)new TemplateTypeClass(ShoreCliff25);\t//\tTEMPLATE_SHORECLIFF25\n\t(void)new TemplateTypeClass(ShoreCliff26);\t//\tTEMPLATE_SHORECLIFF26\n\t(void)new TemplateTypeClass(ShoreCliff27);\t//\tTEMPLATE_SHORECLIFF27\n\t(void)new TemplateTypeClass(ShoreCliff28);\t//\tTEMPLATE_SHORECLIFF28\n\t(void)new TemplateTypeClass(ShoreCliff29);\t//\tTEMPLATE_SHORECLIFF29\n\t(void)new TemplateTypeClass(ShoreCliff30);\t//\tTEMPLATE_SHORECLIFF30\n\t(void)new TemplateTypeClass(ShoreCliff31);\t//\tTEMPLATE_SHORECLIFF31\n\t(void)new TemplateTypeClass(ShoreCliff32);\t//\tTEMPLATE_SHORECLIFF32\n\t(void)new TemplateTypeClass(ShoreCliff33);\t//\tTEMPLATE_SHORECLIFF33\n\t(void)new TemplateTypeClass(ShoreCliff34);\t//\tTEMPLATE_SHORECLIFF34\n\t(void)new TemplateTypeClass(ShoreCliff35);\t//\tTEMPLATE_SHORECLIFF35\n\t(void)new TemplateTypeClass(ShoreCliff36);\t//\tTEMPLATE_SHORECLIFF36\n\t(void)new TemplateTypeClass(ShoreCliff37);\t//\tTEMPLATE_SHORECLIFF37\n\t(void)new TemplateTypeClass(ShoreCliff38);\t//\tTEMPLATE_SHORECLIFF38\n\t(void)new TemplateTypeClass(Boulder1);\t\t\t//\tTEMPLATE_BOULDER1\n\t(void)new TemplateTypeClass(Boulder2);\t\t\t//\tTEMPLATE_BOULDER2\n\t(void)new TemplateTypeClass(Boulder3);\t\t\t//\tTEMPLATE_BOULDER3\n\t(void)new TemplateTypeClass(Boulder4);\t\t\t// TEMPLATE_BOULDER4\n\t(void)new TemplateTypeClass(Boulder5);\t\t\t//\tTEMPLATE_BOULDER5\n\t(void)new TemplateTypeClass(Boulder6);\t\t\t//\tTEMPLATE_BOULDER6\n\t(void)new TemplateTypeClass(Patch01);\t\t\t//\tTEMPLATE_PATCH1\n\t(void)new TemplateTypeClass(Patch02);\t\t\t//\tTEMPLATE_PATCH2\n\t(void)new TemplateTypeClass(Patch03);\t\t\t//\tTEMPLATE_PATCH3\n\t(void)new TemplateTypeClass(Patch04);\t\t\t//\tTEMPLATE_PATCH4\n\t(void)new TemplateTypeClass(Patch07);\t\t\t//\tTEMPLATE_PATCH7\n\t(void)new TemplateTypeClass(Patch08);\t\t\t//\tTEMPLATE_PATCH8\n\t(void)new TemplateTypeClass(Patch13);\t\t\t//\tTEMPLATE_PATCH13\n\t(void)new TemplateTypeClass(Patch14);\t\t\t//\tTEMPLATE_PATCH14\n\t(void)new TemplateTypeClass(Patch15);\t\t\t//\tTEMPLATE_PATCH15\n\t(void)new TemplateTypeClass(River01);\t\t\t//\tTEMPLATE_RIVER1\n\t(void)new TemplateTypeClass(River02);\t\t\t//\tTEMPLATE_RIVER2\n\t(void)new TemplateTypeClass(River03);\t\t\t//\tTEMPLATE_RIVER3\n\t(void)new TemplateTypeClass(River04);\t\t\t//\tTEMPLATE_RIVER4\n\t(void)new TemplateTypeClass(River05);\t\t\t//\tTEMPLATE_RIVER5\n\t(void)new TemplateTypeClass(River06);\t\t\t//\tTEMPLATE_RIVER6\n\t(void)new TemplateTypeClass(River07);\t\t\t//\tTEMPLATE_RIVER7\n\t(void)new TemplateTypeClass(River08);\t\t\t//\tTEMPLATE_RIVER8\n\t(void)new TemplateTypeClass(River09);\t\t\t//\tTEMPLATE_RIVER9\n\t(void)new TemplateTypeClass(River10);\t\t\t//\tTEMPLATE_RIVER10\n\t(void)new TemplateTypeClass(River11);\t\t\t//\tTEMPLATE_RIVER11\n\t(void)new TemplateTypeClass(River12);\t\t\t//\tTEMPLATE_RIVER12\n\t(void)new TemplateTypeClass(River13);\t\t\t//\tTEMPLATE_RIVER13\n\t(void)new TemplateTypeClass(Falls1);\t\t\t//\tTEMPLATE_FALLS1\n\t(void)new TemplateTypeClass(Falls1a);\t\t\t//\tTEMPLATE_FALLS1A\n\t(void)new TemplateTypeClass(Falls2);\t\t\t//\tTEMPLATE_FALLS2\n\t(void)new TemplateTypeClass(Falls2a);\t\t\t//\tTEMPLATE_FALLS2A\n\t(void)new TemplateTypeClass(Ford1);\t\t\t\t//\tTEMPLATE_FORD1\n\t(void)new TemplateTypeClass(Ford2);\t\t\t\t//\tTEMPLATE_FORD2\n\t(void)new TemplateTypeClass(Bridge1);\t\t\t//\tTEMPLATE_BRIDGE1\n\t(void)new TemplateTypeClass(Bridge1d);\t\t\t//\tTEMPLATE_BRIDGE1D\n\t(void)new TemplateTypeClass(Bridge2);\t\t\t//\tTEMPLATE_BRIDGE2\n\t(void)new TemplateTypeClass(Bridge2d);\t\t\t//\tTEMPLATE_BRIDGE2D\n\t(void)new TemplateTypeClass(Slope01);\t\t\t//\tTEMPLATE_SLOPE1\n\t(void)new TemplateTypeClass(Slope02);\t\t\t//\tTEMPLATE_SLOPE2\n\t(void)new TemplateTypeClass(Slope03);\t\t\t//\tTEMPLATE_SLOPE3\n\t(void)new TemplateTypeClass(Slope04);\t\t\t//\tTEMPLATE_SLOPE4\n\t(void)new TemplateTypeClass(Slope05);\t\t\t//\tTEMPLATE_SLOPE5\n\t(void)new TemplateTypeClass(Slope06);\t\t\t//\tTEMPLATE_SLOPE6\n\t(void)new TemplateTypeClass(Slope07);\t\t\t//\tTEMPLATE_SLOPE7\n\t(void)new TemplateTypeClass(Slope08);\t\t\t//\tTEMPLATE_SLOPE8\n\t(void)new TemplateTypeClass(Slope09);\t\t\t//\tTEMPLATE_SLOPE9\n\t(void)new TemplateTypeClass(Slope10);\t\t\t//\tTEMPLATE_SLOPE10\n\t(void)new TemplateTypeClass(Slope11);\t\t\t//\tTEMPLATE_SLOPE11\n\t(void)new TemplateTypeClass(Slope12);\t\t\t//\tTEMPLATE_SLOPE12\n\t(void)new TemplateTypeClass(Slope13);\t\t\t//\tTEMPLATE_SLOPE13\n\t(void)new TemplateTypeClass(Slope14);\t\t\t//\tTEMPLATE_SLOPE14\n\t(void)new TemplateTypeClass(Slope15);\t\t\t//\tTEMPLATE_SLOPE15\n\t(void)new TemplateTypeClass(Slope16);\t\t\t//\tTEMPLATE_SLOPE16\n\t(void)new TemplateTypeClass(Slope17);\t\t\t//\tTEMPLATE_SLOPE17\n\t(void)new TemplateTypeClass(Slope18);\t\t\t//\tTEMPLATE_SLOPE18\n\t(void)new TemplateTypeClass(Slope19);\t\t\t//\tTEMPLATE_SLOPE19\n\t(void)new TemplateTypeClass(Slope20);\t\t\t//\tTEMPLATE_SLOPE20\n\t(void)new TemplateTypeClass(Slope21);\t\t\t//\tTEMPLATE_SLOPE21\n\t(void)new TemplateTypeClass(Slope22);\t\t\t//\tTEMPLATE_SLOPE22\n\t(void)new TemplateTypeClass(Slope23);\t\t\t//\tTEMPLATE_SLOPE23\n\t(void)new TemplateTypeClass(Slope24);\t\t\t//\tTEMPLATE_SLOPE24\n\t(void)new TemplateTypeClass(Slope25);\t\t\t//\tTEMPLATE_SLOPE25\n\t(void)new TemplateTypeClass(Slope26);\t\t\t//\tTEMPLATE_SLOPE26\n\t(void)new TemplateTypeClass(Slope27);\t\t\t//\tTEMPLATE_SLOPE27\n\t(void)new TemplateTypeClass(Slope28);\t\t\t//\tTEMPLATE_SLOPE28\n\t(void)new TemplateTypeClass(Slope29);\t\t\t//\tTEMPLATE_SLOPE29\n\t(void)new TemplateTypeClass(Slope30);\t\t\t//\tTEMPLATE_SLOPE30\n\t(void)new TemplateTypeClass(Slope31);\t\t\t//\tTEMPLATE_SLOPE31\n\t(void)new TemplateTypeClass(Slope32);\t\t\t//\tTEMPLATE_SLOPE32\n\t(void)new TemplateTypeClass(Slope33);\t\t\t//\tTEMPLATE_SLOPE33\n\t(void)new TemplateTypeClass(Slope34);\t\t\t//\tTEMPLATE_SLOPE34\n\t(void)new TemplateTypeClass(Slope35);\t\t\t//\tTEMPLATE_SLOPE35\n\t(void)new TemplateTypeClass(Slope36);\t\t\t//\tTEMPLATE_SLOPE36\n\t(void)new TemplateTypeClass(Slope37);\t\t\t//\tTEMPLATE_SLOPE37\n\t(void)new TemplateTypeClass(Slope38);\t\t\t//\tTEMPLATE_SLOPE38\n\t(void)new TemplateTypeClass(Road01);\t\t\t//\tTEMPLATE_ROAD1\n\t(void)new TemplateTypeClass(Road02);\t\t\t//\tTEMPLATE_ROAD2\n\t(void)new TemplateTypeClass(Road03);\t\t\t//\tTEMPLATE_ROAD3\n\t(void)new TemplateTypeClass(Road04);\t\t\t//\tTEMPLATE_ROAD4\n\t(void)new TemplateTypeClass(Road05);\t\t\t//\tTEMPLATE_ROAD5\n\t(void)new TemplateTypeClass(Road06);\t\t\t//\tTEMPLATE_ROAD6\n\t(void)new TemplateTypeClass(Road07);\t\t\t//\tTEMPLATE_ROAD7\n\t(void)new TemplateTypeClass(Road08);\t\t\t//\tTEMPLATE_ROAD8\n\t(void)new TemplateTypeClass(Road09);\t\t\t//\tTEMPLATE_ROAD9\n\t(void)new TemplateTypeClass(Road10);\t\t\t//\tTEMPLATE_ROAD10\n\t(void)new TemplateTypeClass(Road11);\t\t\t//\tTEMPLATE_ROAD11\n\t(void)new TemplateTypeClass(Road12);\t\t\t//\tTEMPLATE_ROAD12\n\t(void)new TemplateTypeClass(Road13);\t\t\t//\tTEMPLATE_ROAD13\n\t(void)new TemplateTypeClass(Road14);\t\t\t//\tTEMPLATE_ROAD14\n\t(void)new TemplateTypeClass(Road15);\t\t\t//\tTEMPLATE_ROAD15\n\t(void)new TemplateTypeClass(Road16);\t\t\t//\tTEMPLATE_ROAD16\n\t(void)new TemplateTypeClass(Road17);\t\t\t//\tTEMPLATE_ROAD17\n\t(void)new TemplateTypeClass(Road18);\t\t\t//\tTEMPLATE_ROAD18\n\t(void)new TemplateTypeClass(Road19);\t\t\t//\tTEMPLATE_ROAD19\n\t(void)new TemplateTypeClass(Road20);\t\t\t//\tTEMPLATE_ROAD20\n\t(void)new TemplateTypeClass(Road21);\t\t\t//\tTEMPLATE_ROAD21\n\t(void)new TemplateTypeClass(Road22);\t\t\t//\tTEMPLATE_ROAD22\n\t(void)new TemplateTypeClass(Road23);\t\t\t//\tTEMPLATE_ROAD23\n\t(void)new TemplateTypeClass(Road24);\t\t\t//\tTEMPLATE_ROAD24\n\t(void)new TemplateTypeClass(Road25);\t\t\t//\tTEMPLATE_ROAD25\n\t(void)new TemplateTypeClass(Road26);\t\t\t//\tTEMPLATE_ROAD26\n\t(void)new TemplateTypeClass(Road27);\t\t\t//\tTEMPLATE_ROAD27\n\t(void)new TemplateTypeClass(Road28);\t\t\t//\tTEMPLATE_ROAD28\n\t(void)new TemplateTypeClass(Road29);\t\t\t//\tTEMPLATE_ROAD29\n\t(void)new TemplateTypeClass(Road30);\t\t\t//\tTEMPLATE_ROAD30\n\t(void)new TemplateTypeClass(Road31);\t\t\t//\tTEMPLATE_ROAD31\n\t(void)new TemplateTypeClass(Road32);\t\t\t//\tTEMPLATE_ROAD32\n\t(void)new TemplateTypeClass(Road33);\t\t\t//\tTEMPLATE_ROAD33\n\t(void)new TemplateTypeClass(Road34);\t\t\t//\tTEMPLATE_ROAD34\n\t(void)new TemplateTypeClass(Road35);\t\t\t//\tTEMPLATE_ROAD35\n\t(void)new TemplateTypeClass(Road36);\t\t\t//\tTEMPLATE_ROAD36\n\n\t/*\n\t**\tSeparate out the list of new operator calls. Watcom bombs\n\t**\tif they are kept together.\n\t*/\n\t_Watcom_Ugh_Hack();\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Land_Type -- Determines land type from template and icon number.         *\n *                                                                                             *\n *    This routine will convert the specified icon number into the appropriate land type. The  *\n *    land type can be determined from the embedded colors in the \"control template\" section   *\n *    of the original art file. This control information is encoded into the icon data file    *\n *    to be retrieved and interpreted as the program sees fit. The engine only recognizes      *\n *    the first 16 colors as control colors, so the control map color value serves as an       *\n *    index into a simple lookup table.                                                        *\n *                                                                                             *\n * INPUT:   icon  -- The icon number within this template that is to be examined and used      *\n *                   to determine the land type.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the land type that corresponds to the icon number specified.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLandType TemplateTypeClass::Land_Type(int icon) const\n{\n\tIconsetClass const * icontrol = (IconsetClass const *)Get_Image_Data();\n\n\tif (icontrol != NULL) {\n\t\tunsigned char const * map = icontrol->Control_Map();\n\t\tif (map != NULL) {\n\t\t\tstatic LandType _land[16] = {\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\t\t\t// Clear\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_BEACH,\t\t\t// Beach\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_ROCK,\t\t\t// Rock\n\t\t\t\tLAND_ROAD,\t\t\t// Road\n\t\t\t\tLAND_WATER,\t\t\t// Water\n\t\t\t\tLAND_RIVER,\t\t\t//\tRiver\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_CLEAR,\n\t\t\t\tLAND_ROUGH,\t\t\t// Rough\n\t\t\t\tLAND_CLEAR,\n\t\t\t};\n\n\t\t\treturn(_land[map[icon % (icontrol->Map_Width() * icontrol->Map_Height())]]);\n\t\t}\n\t}\n\treturn(LAND_CLEAR);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::From_Name -- Determine template from ASCII name.                         *\n *                                                                                             *\n *    This routine is used to determine the template number given only                         *\n *    an ASCII representation. The scenario loader uses this routine                           *\n *    to construct the map from the INI control file.                                          *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the template.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the template number. If the name had no match,                        *\n *          then returns with TEMPLATE_NONE.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateType TemplateTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (TemplateType index = TEMPLATE_FIRST; index < TEMPLATE_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(TEMPLATE_NONE);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Occupy_List -- Determines occupation list.                               *\n *                                                                                             *\n *    This routine is used to examine the template map and build an                            *\n *    occupation list. This list is used to render a template cursor as                        *\n *    well as placement of icon numbers.                                                       *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the template occupation list.                            *\n *                                                                                             *\n * WARNINGS:   The return pointer is valid only until the next time that                       *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   12/12/1995 JLB : Optimized for direct access to iconset data.                             *\n *=============================================================================================*/\nshort const * TemplateTypeClass::Occupy_List(bool) const\n{\n\tstatic short _occupy[13*8+5];\n\tshort\t* ptr;\n\n\tIconsetClass const * iconset = (IconsetClass const *)Get_Image_Data();\n\tunsigned char const * map = iconset->Map_Data();\n\n\tptr = &_occupy[0];\n\tfor (int index = 0; index < Width * Height; index++) {\n\t\tif (*map++ != 0xFF) {\n\t\t\t*ptr++ = (index % Width) + ((index / Width)*MAP_CELL_W);\n\t\t}\n\t}\n\t*ptr = REFRESH_EOL;\n\n\treturn((short const *)&_occupy[0]);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Init -- Loads graphic data for templates.                                *\n *                                                                                             *\n *    This routine loads the template graphic data for all the template                        *\n *    type supported for the specified theater. This routine is called                         *\n *    whenever the theater for the scenario is first determined.                               *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the template data is to be                            *\n *                      loaded for.                                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk!                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Only handles iconset loading now (as it should).                         *\n *=============================================================================================*/\nvoid TemplateTypeClass::Init(TheaterType theater)\n{\n\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\tvoid const * ptr;\t\t// Working loaded iconset pointer.\n\n\tfor (TemplateType index = TEMPLATE_FIRST; index < TEMPLATE_COUNT; index++) {\n\t\tTemplateTypeClass\tconst & tplate = As_Reference(index);\n\n\t\t((void const *&)tplate.ImageData) = NULL;\n\t\tif (tplate.Theater & (1<<theater)) {\n\t\t\t_makepath(fullname, NULL, NULL, tplate.IniName, Theaters[theater].Suffix);\n\t\t\tptr = MFCD::Retrieve(fullname);\n\t\t\t((void const *&)tplate.ImageData) = ptr;\n\n#ifdef WIN32\n\t\t\tRegister_Icon_Set((void*)ptr, TRUE);\t\t//Register icon set for video memory caching\n#endif\n\n\t\t\t((unsigned char &)tplate.Width) = Get_IconSet_MapWidth(ptr);\n\t\t\t((unsigned char &)tplate.Height) = Get_IconSet_MapHeight(ptr);\n\t\t}\n\t}\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * TemplateTypeClass::Display -- Displays a generic representation of template.                *\n *                                                                                             *\n *    This routine is used to display a generic view of the template                           *\n *    object. This is necessary for selection in the scenario editor.                          *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinates to center the display about.                              *\n *                                                                                             *\n *          window-- The window to base the coordinates upon.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tint\tw,h;\n\tint\tindex;\n\tbool\tscale;\t\t// Should the template be half sized?\n\n\tw = Bound(Width, 1, 13);\n\th = Bound(Height, 1, 8);\n\tscale = (w > 3 || h > 3);\n\tif (scale) {\n\t\tx -= (w * ICON_PIXEL_W) / 4;\n\t\ty -= (h * ICON_PIXEL_H) / 4;\n\t} else {\n\t\tx -= (w * ICON_PIXEL_W) / 2;\n\t\ty -= (h * ICON_PIXEL_H) / 2;\n\t}\n\tx += WindowList[window][WINDOWX];\n\ty += WindowList[window][WINDOWY];\n\n\tIconsetClass const * iconset = (IconsetClass const *)Get_Image_Data();\n\tunsigned char const * map = iconset->Map_Data();\n\n\tfor (index = 0; index < w*h; index++) {\n\t\tif (map[index] != 0xFF) {\n\t\t\tHidPage.Draw_Stamp(iconset, index, 0, 0, NULL, WINDOW_MAIN);\n\t\t\tif (scale) {\n\n\t\t\t\tHidPage.Scale((*LogicPage), 0, 0,\n\t\t\t\t\tx + ((index % w)*(ICON_PIXEL_W/2)),\n\t\t\t\t\ty + ((index / w)*(ICON_PIXEL_H/2)),\n\t\t\t\t\tICON_PIXEL_W, ICON_PIXEL_H,\n\t\t\t\t\tICON_PIXEL_W/2, ICON_PIXEL_H/2, (char *)NULL);\n\n\t\t\t} else {\n\t\t\t\tHidPage.Blit((*LogicPage), 0, 0, x + ((index % w)*(ICON_PIXEL_W)),\n\t\t\t\t\ty + ((index / w)*(ICON_PIXEL_H)), ICON_PIXEL_W, ICON_PIXEL_H);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Prep_For_Add -- Prepares to add template to scenario.                    *\n *                                                                                             *\n *    This routine prepares a list of template objects so that the                             *\n *    scenario editor can use this list to display a dialog box. The                           *\n *    selection of a template object will allow its placement upon the                         *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *   05/28/1994 JLB : Only handles real templates now.                                         *\n *   06/04/1994 JLB : Uses map editing interface functions.                                    *\n *=============================================================================================*/\nvoid TemplateTypeClass::Prep_For_Add(void)\n{\n\tfor (TemplateType index = TEMPLATE_CLEAR1; index < TEMPLATE_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Create_And_Place -- Creates and places a template object on the map.     *\n *                                                                                             *\n *    This support routine is used by the scenario editor to add a template object to the map  *\n *    and to the game.                                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the template object.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the template object placed successfully?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool TemplateTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new TemplateClass(Type, cell)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::Create_One_Of -- Creates an object of this template type.                *\n *                                                                                             *\n *    This routine will create an object of this type. For certain template objects, such      *\n *    as walls, it is actually created as a building. The \"building\" wall is converted into    *\n *    a template at the moment of placing down on the map.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the appropriate object for this template type.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * TemplateTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new TemplateClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::One_Time -- Performs one-time initialization                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid TemplateTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * TemplateTypeClass::As_Reference -- Fetches a reference to the template specified.           *\n *                                                                                             *\n *    This will return a reference to the TemplateTypeClass requested.                         *\n *                                                                                             *\n * INPUT:   type  -- The template type to fetch a reference to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the template type class specified.                     *\n *                                                                                             *\n * WARNINGS:   Be sure to pass a valid type parameter. This routine doesn't check it for       *\n *             legality.                                                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTemplateTypeClass & TemplateTypeClass::As_Reference(TemplateType type)\n{\n\treturn(*TemplateTypes.Ptr(type));\n}\n\n\nCOORDINATE TemplateTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n"
  },
  {
    "path": "REDALERT/CDFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CDFILE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : CDFILE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 18, 1994                                             *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                  *\n *   CDFileClass::Open -- Opens the file object -- with path search.                           *\n *   CDFileClass::Open -- Opens the file wherever it can be found.                             *\n *   CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.          *\n *   CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.            *\n *   Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive.               *\n *   harderr_handler -- Handles hard DOS errors.                                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"cdfile.h\"\n#include\t<stdio.h>\n#include\t<string.h>\n\n#ifndef WIN32\n#include\t<wwstd.h>\n#include\t<playcd.h>\n#endif\n\n/*\n**\tPointer to the first search path record.\n*/\nCDFileClass::SearchDriveType * CDFileClass::First = 0;\n\nint  CDFileClass::CurrentCDDrive = 0;\nint  CDFileClass::LastCDDrive = 0;\nchar CDFileClass::RawPath[512] = {0};\n\nCDFileClass::CDFileClass(char const *filename) :\n\tIsDisabled(false)\n{\n\tCDFileClass::Set_Name(filename);\n//\tmemset (RawPath, 0, sizeof(RawPath));\n}\n\n\nCDFileClass::CDFileClass(void) :\n\tIsDisabled(false)\n{\n}\nextern int Get_CD_Index (int cd_drive, int timeout);\n\n/***********************************************************************************************\n * harderr_handler -- Handles hard DOS errors.                                                 *\n *                                                                                             *\n *    This routine will handle the low level DOS error trapper. Instead of displaying the      *\n *    typical \"Abort, Retry, Ignore\" message, it simply returns with the failure code. The     *\n *    cause of the error will fail. The likely case would be with disk I/O.                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  Return the failure code.                                                           *\n *                                                                                             *\n * WARNINGS:   Do no processing in this routine that could possibly generate another           *\n *             hard error condition.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nint harderr_handler(unsigned int , unsigned int , unsigned int *)\n#else\nint harderr_handler(unsigned int , unsigned int , unsigned int __far *)\n#endif\n{\n\treturn(0);\t// _HARDERR_FAIL);\n}\n\n\n/***********************************************************************************************\n * Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive.                 *\n *                                                                                             *\n *    This routine will examine the drive specified to see if there is a disk inserted. It     *\n *    can be used for floppy drives as well as for the CD-ROM.                                 *\n *                                                                                             *\n * INPUT:   disk  -- The drive number to examine. 0=A, 1=B, etc.                               *\n *                                                                                             *\n * OUTPUT:  bool; Is a disk inserted into the specified drive?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint cdecl Is_Disk_Inserted(int disk)\n{\n#ifndef OBSOLETE\n\tdisk;\n\treturn true;\n#if (0)\n\tstruct find_t fb;\n\tchar\tscan[] = \"?:\\\\*.*\";\n\n\t#ifndef WIN32\n\t\t_harderr(harderr_handler);\t\t// BG: Install hard error handler\n\t#endif\n\n\tscan[0] = (char)('A' + disk);\n\treturn(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);\n#endif\n#else\n\tstruct {\n\t\tstruct {\n\t\t\tchar\tLength;\n\t\t\tchar\tUnit;\n\t\t\tchar\tFunction;\n\t\t\tchar\tStatus;\n\t\t\tchar\tReserved[8];\n\t\t} ReqHdr;\n\t\tchar\tMediaDescriptor;\t\t// Media descriptor byte from BPB.\n\t\tvoid\t*Transfer;\t\t\t\t// Pointer to transfer address block.\n\t\tshort\tLength;\t\t\t\t\t// Number of bytes to transfer.\n\t\tshort Sector;\t\t\t\t\t// Starting sector number.\n\t\tvoid\t*Volume;\t\t\t\t\t// Pointer to requested volume.\n\t} IOCTLI;\n\tchar status[5];\n\n\tmemset(IOCTLI, 0, sizeof(IOCTLI));\n\tIOCTLI.ReqHdr.Length = 26;\n\tIOCTLI.ReqHdr.Unit = 0;\t\t\t// First CD-ROM controlled by this driver.\n\t//IOCTLI.ReqHdr.Unit = 11;\t\t// Hard coded for K:\n\tIOCTLI.ReqHdr.Function = 3;\t// IOCTL read\n\tIOCTLI.Transfer = &status[0];\n\tIOCTLI.Length = sizeof(status);\n\tstatus[0] = 6;\t\t\t\t\t// Fetch device status code.\n\t_AX = 0x440D;\n\t_CX = 0x0003;\n\tgeninterrupt(0x21);\n\treturn(!(_AX & (1<<11)));\n#endif\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Open -- Opens the file object -- with path search.                             *\n *                                                                                             *\n *    This will open the file object, but since the file object could have been constructed    *\n *    with a pathname, this routine will try to find the file first. For files opened for      *\n *    writing, then use the existing filename without performing a path search.                *\n *                                                                                             *\n * INPUT:   rights   -- The access rights to use when opening the file                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the open successful?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Open(int rights)\n{\n\treturn(BufferIOFileClass::Open(rights));\n}\n/***********************************************************************************************\n * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 9:01AM ST : Created                                                              *\n *=============================================================================================*/\nvoid CDFileClass::Refresh_Search_Drives (void)\n{\n\tClear_Search_Drives();\n\tSet_Search_Drives(RawPath);\n}\n\n#if 0\n/***********************************************************************************************\n * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.              *\n *                                                                                             *\n *    This routine sets up a list of search paths to use when accessing files. The path list   *\n *    is scanned if the file could not be found in the current directory. This is the primary  *\n *    method of supporting CD-ROM drives, but is also useful for scanning network and other    *\n *    directories. The pathlist as passed to this routine is of the same format as the path    *\n *    list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*\n *                                                                                             *\n *    If a path entry begins with \"?:\" then the question mark will be replaced with the first  *\n *    CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path     *\n *    entry will be ignored. By using this feature, you can always pass the CD-ROM path        *\n *    specification to this routine and it will not break if the CD-ROM is not loaded (as in   *\n *    the case during development).                                                            *\n *                                                                                             *\n *    Here is an example path specification:                                                   *\n *                                                                                             *\n *       Set_Search_Drives(\"DATA;?:\\DATA;F:\\PROJECT\\DATA\");                                    *\n *                                                                                             *\n *    In this example, the current directory will be searched first, followed by a the         *\n *    subdirectory \"DATA\" located off of the current directory. If not found, then the CD-ROM  *\n *    will be searched in a directory called \"\\DATA\". If not found or the CD-ROM is not        *\n *    present, then it will look to the hard coded path of \"F:\\PROJECTS\\DATA\" (maybe a         *\n *    network?). If all of these searches fail, the file system will default to the current    *\n *    directory and let the normal file error system take over.                                *\n *                                                                                             *\n * INPUT:   pathlist -- Pointer to string of path specifications (separated by semicolons)     *\n *                      that will be used to search for files.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Set_Search_Drives(char * pathlist)\n{\n\tint found = false;\n\tint empty = false;\n\n\t/*\n\t**\tIf there is no pathlist to add, then just return.\n\t*/\n\tif (!pathlist) return(0);\n\n\tchar const * ptr = strtok(pathlist, \";\");\n\twhile (ptr) {\n\t\tchar path[PATH_MAX];\t\t\t\t\t\t// Working path buffer.\n\t\tSearchDriveType *srch;\t\t\t\t\t// Working pointer to path object.\n\n\t\t/*\n\t\t**\tFixup the path to be legal. Legal is defined as all that is necessary to\n\t\t**\tcreate a pathname is to append the actual filename submitted to the\n\t\t**\tfile system. This means that it must have either a trailing ':' or '\\'\n\t\t**\tcharacter.\n\t\t*/\n\t\tstrcpy(path, ptr);\n\t\tswitch (path[strlen(path)-1]) {\n\t\t\tcase ':':\n\t\t\tcase '\\\\':\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstrcat(path, \"\\\\\");\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a drive letter specified, and this drive letter is '?', then it should\n\t\t**\tbe substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then\n\t\t**\tmerely ignore this path entry.\n\t\t*/\n\t\tif (strncmp(path, \"?:\", 2) == 0) {\n\t\t\t#ifndef WIN32\n\t\t\t\tGetCDClass temp;\n\t\t\t\tint cd = temp.GetCDDrive();\n\t\t\t#else\n\t\t\t\tint cd = 10;\n\t\t\t#endif\n\t\t\tfound = cd;\n\t\t\tempty = !Is_Disk_Inserted(cd);\n\t\t\tif (!found || empty) goto nextpath;\n\t\t\tpath[0] = (char)('A' + cd);\n\t\t}\n\n\t\t/*\n\t\t**\tAllocate a record structure.\n\t\t*/\n\t\tsrch\t= new SearchDriveType;\n\t\tif (srch) {\n\t\t\tfound\t= true;\n\n\t\t\t/*\n\t\t\t**\tAttach the path to this structure.\n\t\t\t*/\n\t\t\tsrch->Path = strdup(path);\n\t\t\tsrch->Next = NULL;\n\n\t\t\t/*\n\t\t\t**\tAttach this path record to the end of the path chain.\n\t\t\t*/\n\t\t\tif (!First) {\n\t\t\t\tFirst = srch;\n\t\t\t} else {\n\t\t\t\tSearchDriveType * chain = First;\n\n\t\t\t\twhile (chain->Next) {\n\t\t\t\t\tchain = (SearchDriveType *)chain->Next;\n\t\t\t\t}\n\t\t\t\tchain->Next = srch;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tFind the next path string and resubmit.\n\t\t*/\nnextpath:\n\t\tptr = strtok(NULL, \";\");\n\t}\n\tif (!found) return(1);\n\tif (empty) return(2);\n\treturn(0);\n}\n#endif\n\n\n/***********************************************************************************************\n * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.              *\n *                                                                                             *\n *    This routine sets up a list of search paths to use when accessing files. The path list   *\n *    is scanned if the file could not be found in the current directory. This is the primary  *\n *    method of supporting CD-ROM drives, but is also useful for scanning network and other    *\n *    directories. The pathlist as passed to this routine is of the same format as the path    *\n *    list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*\n *                                                                                             *\n *    If a path entry begins with \"?:\" then the question mark will be replaced with the first  *\n *    CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path     *\n *    entry will be ignored. By using this feature, you can always pass the CD-ROM path        *\n *    specification to this routine and it will not break if the CD-ROM is not loaded (as in   *\n *    the case during development).                                                            *\n *                                                                                             *\n *    Here is an example path specification:                                                   *\n *                                                                                             *\n *       Set_Search_Drives(\"DATA;?:\\DATA;F:\\PROJECT\\DATA\");                                    *\n *                                                                                             *\n *    In this example, the current directory will be searched first, followed by a the         *\n *    subdirectory \"DATA\" located off of the current directory. If not found, then the CD-ROM  *\n *    will be searched in a directory called \"\\DATA\". If not found or the CD-ROM is not        *\n *    present, then it will look to the hard coded path of \"F:\\PROJECTS\\DATA\" (maybe a         *\n *    network?). If all of these searches fail, the file system will default to the current    *\n *    directory and let the normal file error system take over.                                *\n *                                                                                             *\n * INPUT:   pathlist -- Pointer to string of path specifications (separated by semicolons)     *\n *                      that will be used to search for files.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *   05/21/1996 ST  : Modified to recognise multiple CD drives                                 *\n *=============================================================================================*/\nint CDFileClass::Set_Search_Drives(char * pathlist)\n{\n\tint found = FALSE;\n\tint empty = FALSE;\n\n\t/*\n\t**\tIf there is no pathlist to add, then just return.\n\t*/\n\tif (!pathlist) return(0);\n\n\t/*\n\t** Save the path as it was passed in so we can parse it again later.\n\t** Check for the case where RawPath was passed in.\n\t*/\n\tif (pathlist != RawPath) {\n\t\tstrcat (RawPath, \";\");\n\t\tstrcat (RawPath, pathlist);\n\t}\n\n\tchar const * ptr = strtok(pathlist, \";\");\n\twhile (ptr != NULL) {\n\t\tif (strlen(ptr) > 0) {\n\n\t\t\tchar path[MAX_PATH];\t\t\t\t\t\t// Working path buffer.\n\n\t\t\t/*\n\t\t\t**\tFixup the path to be legal. Legal is defined as all that is necessary to\n\t\t\t**\tcreate a pathname is to append the actual filename submitted to the\n\t\t\t**\tfile system. This means that it must have either a trailing ':' or '\\'\n\t\t\t**\tcharacter.\n\t\t\t*/\n\t\t\tstrcpy(path, ptr);\n\t\t\tswitch (path[strlen(path)-1]) {\n\t\t\t\tcase ':':\n\t\t\t\tcase '\\\\':\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tstrcat(path, \"\\\\\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is a drive letter specified, and this drive letter is '?', then it should\n\t\t\t**\tbe substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then\n\t\t\t**\tmerely ignore this path entry.\n\t\t\t** Adds an extra entry for each CD drive in the system that has a C&C disc inserted.\n\t\t\t** \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tST - 5/21/96 4:40PM\n\t\t\t*/\n\t\t\tif (strncmp(path, \"?:\", 2) == 0) {\n\t\t\t\tif (CurrentCDDrive) {\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the drive has a C&C CD in it then add it to the path\n\t\t\t\t\t*/\n\t\t\t\t\tif (Get_CD_Index(CurrentCDDrive, 2*60) >= 0) {\n\t\t\t\t\t\tpath[0] = (char)(CurrentCDDrive + 'A');\n\t\t\t\t\t\tAdd_Search_Drive(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the next path string and resubmit.\n\t\t\t\t*/\n\t\t\t\tptr = strtok(NULL, \";\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfound\t= true;\n\t\t\tAdd_Search_Drive(path);\n\t\t}\n\n\t\t/*\n\t\t**\tFind the next path string and resubmit.\n\t\t*/\n\t\tptr = strtok(NULL, \";\");\n\t}\n\tif (!found) return(1);\n\tif (empty) return(2);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CDFC::Add_Search_Drive -- Add a new path to the search path list                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    path                                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 10:12AM ST : Created                                                             *\n *=============================================================================================*/\nvoid CDFileClass::Add_Search_Drive(char *path)\n{\n\tSearchDriveType *srch;\t\t\t\t\t// Working pointer to path object.\n\t/*\n\t**\tAllocate a record structure.\n\t*/\n\tsrch\t= new SearchDriveType;\n\n\t/*\n\t**\tAttach the path to this structure.\n\t*/\n\tsrch->Path = strdup(path);\n\tsrch->Next = NULL;\n\n\t/*\n\t**\tAttach this path record to the end of the path chain.\n\t*/\n\tif (!First) {\n\t\tFirst = srch;\n\t} else {\n\t\tSearchDriveType * chain = First;\n\n\t\twhile (chain->Next) {\n\t\t\tchain = (SearchDriveType *)chain->Next;\n\t\t}\n\t\tchain->Next = srch;\n\t}\n}\n\n\n/***********************************************************************************************\n * CDFC::Set_CD_Drive -- sets the current CD drive letter                                      *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/22/96 9:39AM ST : Created                                                              *\n *=============================================================================================*/\nvoid CDFileClass::Set_CD_Drive (int drive)\n{\n\tLastCDDrive = CurrentCDDrive;\n\tCurrentCDDrive = drive;\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                    *\n *                                                                                             *\n *    Use this routine to clear out any previous path(s) set with Set_Search_Drives()          *\n *    function.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CDFileClass::Clear_Search_Drives(void)\n{\n\tSearchDriveType\t* chain;\t\t\t// Working pointer to path chain.\n\n\tchain = First;\n\twhile (chain) {\n\t\tSearchDriveType\t*next;\n\n\t\tnext = (SearchDriveType *)chain->Next;\n\t\tif (chain->Path) {\n\t\t\tfree((char *)chain->Path);\n\t\t}\n\t\tdelete chain;\n\n\t\tchain = next;\n\t}\n\tFirst = 0;\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.            *\n *                                                                                             *\n *    This routine will scan all the directories specified in the path list and if the file    *\n *    was found in one of the directories, it will set the filename to a composite of the      *\n *    correct directory and the filename. It is used to allow path searching when searching    *\n *    for files. Typical use is to support CD-ROM drives. This routine examines the current    *\n *    directory first before scanning through the path list. If after scanning the entire      *\n *    path list, the file still could not be found, then the file object's name is set with    *\n *    just the raw filename as passed to this routine.                                         *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to set as the name of this file object.        *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the final and complete filename of this file object. This     *\n *          may have a path attached to the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * CDFileClass::Set_Name(char const *filename)\n{\n\t/*\n\t**\tTry to find the file in the current directory first. If it can be found, then\n\t**\tjust return with the normal file name setting process. Do the same if there is\n\t**\tno multi-drive search path.\n\t*/\n\tBufferIOFileClass::Set_Name(filename);\n\tif (IsDisabled || !First || BufferIOFileClass::Is_Available()) return(File_Name());\n\n\t/*\n\t**\tAttempt to find the file first. Check the current directory. If not found there, then\n\t**\tsearch all the path specifications available. If it still can't be found, then just\n\t**\tfall into the normal raw file filename setting system.\n\t*/\n\tSearchDriveType * srch = First;\n\n\twhile (srch) {\n\t\tchar path[_MAX_PATH];\n\n\t\t/*\n\t\t**\tBuild a pathname to search for.\n\t\t*/\n\t\tstrcpy(path, srch->Path);\n\t\tstrcat(path, filename);\n\n\t\t/*\n\t\t**\tCheck to see if the file could be found. The low level Is_Available logic will\n\t\t**\tprompt if necessary when the CD-ROM drive has been removed. In all other cases,\n\t\t**\tit will return false and the search process will continue.\n\t\t*/\n\t\tBufferIOFileClass::Set_Name(path);\n\t\tif (BufferIOFileClass::Is_Available()) {\n\t\t\treturn(File_Name());\n\t\t}\n\n\t\t/*\n\t\t**\tIt wasn't found, so try the next path entry.\n\t\t*/\n\t\tsrch = (SearchDriveType *)srch->Next;\n\t}\n\n\t/*\n\t**\tAt this point, all path searching has failed. Just set the file name to the\n\t**\tplain text passed to this routine and be done with it.\n\t*/\n\tBufferIOFileClass::Set_Name(filename);\n\treturn(File_Name());\n}\n\n\n/***********************************************************************************************\n * CDFileClass::Open -- Opens the file wherever it can be found.                               *\n *                                                                                             *\n *    This routine is similar to the RawFileClass open except that if the file is being        *\n *    opened only for READ access, it will search all specified directories looking for the    *\n *    file. If after a complete search the file still couldn't be found, then it is opened     *\n *    using the normal BufferIOFileClass system -- resulting in normal error procedures.       *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the override filename to supply for this file object. It    *\n *                      would be the base filename (sans any directory specification).         *\n *                                                                                             *\n *          rights   -- The access rights to use when opening the file.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? If so then the filename may be different   *\n *                than requested. The location of the file can be determined by examining the  *\n *                filename of this file object. The filename will contain the complete         *\n *                pathname used to open the file.                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CDFileClass::Open(char const *filename, int rights)\n{\n\tCDFileClass::Close();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (!filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tIf writing is requested, then multiple drive searching is not performed.\n\t*/\n\tif (IsDisabled || rights == WRITE) {\n\n\t\tBufferIOFileClass::Set_Name( filename );\n\t\treturn( BufferIOFileClass::Open( rights ) );\n\t}\n\n\t/*\n\t**\tPerform normal multiple drive searching for the filename and open\n\t**\tusing the normal procedure.\n\t*/\n\tSet_Name(filename);\n\treturn(BufferIOFileClass::Open(rights));\n}\n\n\nconst char *CDFileClass::Get_Search_Path(int index)\n{\n\tif (First == NULL) {\n\t\treturn NULL;\n\t}\n\n\tSearchDriveType *sd = First;\n\n\tfor (int i = 0; i <= index; i++) {\t\t// We want to loop once, even if index==0\n\n\t\tif (i == index) {\n\t\t\treturn sd->Path;\n\t\t}\n\n\t\tsd = (SearchDriveType *)sd->Next;\n\t\tif (sd == NULL) {\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\n\n\n#ifdef NEVER\n/*\n** Get the drive letters if the CD's online */\n*/\nWORD cdecl GetCDDrive(VOID)\n{\n\t_ES = FP_SEG(&cdDrive[0]);\n\t_BX = FP_OFF(&cdDrive[0]);\n\t_AX = 0x150d;\n\tgeninterrupt(0x2F);\n\treturn((WORD)(*cdDrive));\n}\n#endif\n\n#if 0\nint Get_CD_Drive(void)\n{\n#ifdef WIN32\n\treturn(10);\n#else\n\n#ifdef NEVER\n\tfor (int index = 0; index < 26; index++) {\n\t\tunion REGS regs;\n\n\t\tregs.w.ax = 0x150B;\n\t\tregs.w.bx = 0;\n\t\tregs.w.cx = index;\n\t\tint386(0x2F, &regs, &regs);\n\t\tif (regs.w.bx == 0xADAD) {\n\t\t\treturn(index);\n\t\t}\n\t}\n\treturn(0);\n#else\n\tGetCDClass temp;\n\treturn(temp.GetCDDrive());\n#endif\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/CDFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CDFILE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood LIbrary                                             *\n *                                                                                             *\n *                    File Name : CDFILE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 18, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CDFILE_H\n#define CDFILE_H\n\n#include\t<dos.h>\n#include\t\"bfiofile.h\"\n\n/*\n**\tThis class is derived from the BufferIOFileClass. This class adds the functionality of searching\n**\tacross multiple directories or drives. It is designed for the typical case of a CD-ROM game\n**\twere some data exists in the current directory (hard drive) and the rest exists on the CD-ROM.\n**\tSearching for the file occurs by first examining the current directory. If the file does not\n**\texist there, then all the paths available are examined in turn until the file can be found.\n**\tFor opening files to write, only the current directory is examined. The directory search order\n**\tis controlled by the path list as submitted to Set_Search_Drives(). The format of the path\n**\tstring is the same as the DOS path string.\n*/\nclass CDFileClass : public BufferIOFileClass\n{\n\tpublic:\n\t\tCDFileClass(char const *filename);\n\t\tCDFileClass(void);\n\t\tvirtual ~CDFileClass(void) {};\n\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\n\t\tvoid Searching(int on) {IsDisabled = !on;};\n\n\t\tstatic bool Is_There_Search_Drives(void) {return(First != NULL);};\n\t\tstatic int Set_Search_Drives(char * pathlist);\n\t\tstatic void Add_Search_Drive(char *path);\n\t\tstatic void Clear_Search_Drives(void);\n\t\tstatic void Refresh_Search_Drives(void);\n\t\tstatic void Set_CD_Drive(int drive);\n\t\tstatic int  Get_CD_Drive(void) {return(CurrentCDDrive);};\n\t\tstatic int  Get_Last_CD_Drive(void) {return(LastCDDrive);};\n\n\t\t// RawPath will overflow if we keep setting the path. ST - 1/23/2019 11:12AM\n\t\tstatic void Reset_Raw_Path(void) { RawPath[0] = 0; }\n\n\t\t// Need to access the paths. ST - 3/15/2019 2:14PM\n\t\tstatic const char *Get_Search_Path(int index);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIs multi-drive searching disabled for this file object?\n\t\t*/\n\t\tunsigned IsDisabled:1;\n\n\t\t/*\n\t\t**\tThis is the control record for each of the drives specified in the search\n\t\t**\tpath. There can be many such search paths available.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tvoid * Next;\t\t// Pointer to next search record.\n\t\t\tchar const * Path;\t\t\t// Pointer to path string.\n\t\t} SearchDriveType;\n\n\t\t/*\n\t\t**\tThis points to the first path record.\n\t\t*/\n\t\tstatic SearchDriveType * First;\n\t\t/*\n\t\t** This is a copy of the unparsed search path list\n\t\t*/\n\t\tstatic char RawPath[512];\n\n\t\t/*\n\t\t** The drive letter of the current cd drive\n\t\t*/\n\t\tstatic int CurrentCDDrive;\n\n\t\t/*\n\t\t** The drive letter of the last used CD drive\n\t\t*/\n\t\tstatic int LastCDDrive;\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/CELL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CELL.CPP 4     3/14/97 1:15p Joe_b $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CELL.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 6, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.             *\n *   CellClass::Adjust_Threat -- Allows adjustment of threat at cell level                     *\n *   CellClass::Can_Tiberium_Germinate -- Determines if Tiberium can begin growth in the cell. *\n *   CellClass::Can_Tiberium_Grow -- Determines if Tiberium can grow in this cell.             *\n *   CellClass::Can_Tiberium_Spread -- Determines if Tiberium can spread from this cell.       *\n *   CellClass::CellClass -- Constructor for cell objects.                                     *\n *   CellClass::Cell_Building -- Return with building at specified cell.                       *\n *   CellClass::Cell_Color   -- Determine what radar color to use for this cell.               *\n *   CellClass::Cell_Coord -- Returns the coordinate of this cell.                             *\n *   CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell                    *\n *   CellClass::Cell_Infantry -- Returns with pointer of first infantry unit.                  *\n *   CellClass::Cell_Object -- Returns with clickable object in cell.                          *\n *   CellClass::Cell_Techno -- Return with the unit/building at specified cell.                *\n *   CellClass::Cell_Terrain -- Determines terrain object in cell.                             *\n *   CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                      *\n *   CellClass::Cell_Vessel -- Returns with pointer to a vessel located in the cell.           *\n *   CellClass::Clear_Icon -- Calculates what the clear icon number should be.                 *\n *   CellClass::Closest_Free_Spot -- returns free spot closest to given coord                  *\n *   CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.             *\n *   CellClass::Draw_It -- Draws the cell imagery at the location specified.                   *\n *   CellClass::Flag_Place -- Places a house flag down on the cell.                            *\n *   CellClass::Flag_Remove -- Removes the house flag from the cell.                           *\n *   CellClass::Goodie_Check -- Performs crate discovery logic.                                *\n *   CellClass::Grow_Tiberium -- Grows the tiberium in the cell.                               *\n *   CellClass::Incoming -- Causes objects in cell to \"run for cover\".                         *\n *   CellClass::Is_Bridge_Here -- Checks to see if this is a bridge occupied cell.             *\n *   CellClass::Is_Clear_To_Build -- Determines if cell can be built upon.                     *\n *   CellClass::Is_Clear_To_Move -- Determines if the cell is generally clear for travel       *\n *   CellClass::Occupy_Down -- Flag occupation of specified cell.                              *\n *   CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                  *\n *   CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (over*\n *   CellClass::Overlap_Unit -- Marks cell as being overlapped by unit.                        *\n *   CellClass::Overlap_Up -- Removes overlap flag for the cell.                               *\n *   CellClass::Read -- Reads a particular cell value from a save game file.                   *\n *   CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.     *\n *   CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                   *\n *   CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.   *\n *   CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                       *\n *   CellClass::Reserve_Cell -- Marks a cell as being occupied by the specified unit ID.       *\n *   CellClass::Shimmer -- Causes all objects in the cell to shimmer.                          *\n *   CellClass::Spot_Index -- returns cell sub-coord index for given COORDINATE                *\n *   CellClass::Spread_Tiberium -- Spread Tiberium from this cell to an adjacent cell.         *\n *   CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smooth.                 *\n *   CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n/*\n** New sidebar for GlyphX multiplayer. ST - 8/2/2019 2:50PM\n*/\n#include \"SidebarGlyphx.h\"\n\n\n/***********************************************************************************************\n * CellClass::CellClass -- Constructor for cell objects.                                       *\n *                                                                                             *\n *    A cell object is constructed into an empty state. It contains no specific objects,       *\n *    templates, or overlays.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/09/1994 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Uses initializer list.                                                   *\n *=============================================================================================*/\nCellClass::CellClass(void) :\n\tID(Map.ID(this)),\n\tIsPlot(false),\n\tIsCursorHere(false),\n\tIsMapped(false),\n\tIsVisible(false),\n\tIsWaypoint(false),\n\tIsRadarCursor(false),\n\tIsFlagged(false),\n\tIsToShroud(false),\n\tJammed(0),\n\tTrigger(NULL),\n\tTType(TEMPLATE_NONE),\n\tTIcon(0),\n\tOverlay(OVERLAY_NONE),\n\tOverlayData(0),\n\tSmudge(SMUDGE_NONE),\n\tSmudgeData(0),\n\tOwner(HOUSE_NONE),\n\tInfType(HOUSE_NONE),\n\tOccupierPtr(0),\n\tLand(LAND_CLEAR),\n\tOverrideLand(LAND_NONE),\n\tIsMappedByPlayerMask(0),\n\tIsVisibleByPlayerMask(0),\n\tCTFFlag(NULL)\n{\n\tfor (int zone = MZONE_FIRST; zone < MZONE_COUNT; zone++) {\n\t\tZones[zone] = 0;\n\t}\n\tFlag.Composite = 0;\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tOverlapper[index] = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Color   -- Determine what radar color to use for this cell.                 *\n *                                                                                             *\n *    Use this routine to determine what radar color to render a radar                         *\n *    pixel with. This routine is called many many times to render the                         *\n *    radar map, so it must be fast.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the color to display the radar pixel with.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1994 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/31/1994 JLB : Takes into account any stealth characteristics of object.                *\n *=============================================================================================*/\nint CellClass::Cell_Color(bool override) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tBuildingClass * object = Cell_Building();\n\tif (object && !object->Class->IsInvisible) {\n\t\treturn(ColorRemaps[object->House->RemapColor].Bar);\n\t}\n\n\tif (override) {\n\t\treturn(TBLACK);\n\t}\n\tif (LastTheater == THEATER_SNOW) {\n\t\treturn(::SnowColor[Land_Type()]);\n\t} else {\n\t\treturn(::GroundColor[Land_Type()]);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Techno -- Return with the unit/building at specified cell.                  *\n *                                                                                             *\n *    Returns an object located in the cell. If there is a                                     *\n *    building present, it returns a pointer to that, otherwise it returns                     *\n *    a pointer to one of the units there. If nothing is present in the                        *\n *    specified cell, then it returns NULL.                                                    *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate offset (from upper left corner) to use as an aid in selecting  *\n *                   the desired object within the cell.                                       *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to a building or unit located in cell. If                        *\n *          nothing present, just returns NULL.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nTechnoClass * CellClass::Cell_Techno(int x, int y) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object;\n\tCOORDINATE\t\tclick;\t\t\t// Coordinate of click relative to cell corner.\n\tTechnoClass * close = NULL;\n\tlong\t\tdistance = 0;\t// Recorded closest distance.\n\n\t/*\n\t**\tCreate a coordinate value that represent the pixel location within the cell. This is\n\t**\tactually the lower significant bits (leptons) of a regular coordinate value.\n\t*/\n\tclick = XY_Coord(Pixel_To_Lepton(x), Pixel_To_Lepton(y));\n\n\tif (Cell_Occupier()) {\n\t\tobject = Cell_Occupier();\n\t\twhile (object && object->IsActive) {\n\t\t\tif (object->Is_Techno()) {\n\t\t\t\tCOORDINATE coord = Coord_Fraction(object->Center_Coord());\n\t\t\t\tlong dist = Distance(coord, click);\n\t\t\t\tif (!close || dist < distance) {\n\t\t\t\t\tclose = (TechnoClass *)object;\n\t\t\t\t\tdistance = dist;\n\t\t\t\t}\n\t\t\t}\n\t\t\tobject = object->Next;\n\t\t}\n\t}\n\treturn(close);\n}\n\n\n/***************************************************************************\n * CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell  *\n *                                                                         *\n * INPUT:\t\tRTTIType the RTTI type we are searching for                 *\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   03/17/1995 PWG : Created.                                             *\n *   06/12/1995 JLB : Returns object class pointer.                        *\n *=========================================================================*/\nObjectClass * CellClass::Cell_Find_Object(RTTIType rtti) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(rtti != RTTI_NONE);\n\n\tObjectClass * object = Cell_Occupier();\n\n\twhile (object != NULL && object->IsActive) {\n\t\tif (object->What_Am_I() == rtti) {\n\t\t\treturn(object);\n\t\t}\n\t\tobject = object->Next;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Building -- Return with building at specified cell.                         *\n *                                                                                             *\n *    Given a cell, determine if there is a building associated                                *\n *    and return with a pointer to this building.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building associated with the                         *\n *          cell. If there is no building associated, then NULL is                             *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nBuildingClass * CellClass::Cell_Building(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((BuildingClass *)Cell_Find_Object(RTTI_BUILDING));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Terrain -- Determines terrain object in cell.                               *\n *                                                                                             *\n *    This routine is used to determine the terrain object (if any) that                       *\n *    overlaps this cell.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the terrain object that overlaps                         *\n *          this cell. If there is no terrain object present, then NULL                        *\n *          is returned.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTerrainClass * CellClass::Cell_Terrain(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((TerrainClass *)Cell_Find_Object(RTTI_TERRAIN));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Object -- Returns with clickable object in cell.                            *\n *                                                                                             *\n *    This routine is used to determine which object is to be selected                         *\n *    by a player click upon the cell. Not all objects that overlap the                        *\n *    cell are selectable by the player. This routine sorts out which                          *\n *    is which and returns with the appropriate object pointer.                                *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate (from upper left corner of cell) to use as a guide when        *\n *                   selecting the object within the cell. This plays a role in those cases    *\n *                   where several objects (such as infantry) exist within the same cell.      *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the object clickable within the                            *\n *          cell. NULL is returned if there is no clickable object                             *\n *          present.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/13/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * CellClass::Cell_Object(int x, int y) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * ptr;\n\n\t/*\n\t**\tHack so that aircraft landed on helipads can still be selected if directly\n\t**\tclicked on.\n\t*/\n\tptr = (ObjectClass *)Cell_Find_Object(RTTI_AIRCRAFT);\n\tif (ptr) {\n\t\treturn(ptr);\n\t}\n\n\tptr = Cell_Techno(x, y);\n\tif (ptr) {\n\t\treturn(ptr);\n\t}\n\tptr = Cell_Terrain();\n\tif (ptr) return(ptr);\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                     *\n *                                                                                             *\n *    This is a low level routine that marks all objects that overlap this                     *\n *    cell to be redrawn. It is necessary to call this routine whenever                        *\n *    the underlying icon has to be redrawn.                                                   *\n *                                                                                             *\n * INPUT:   forced   -- Should this redraw be forced even if flags                             *\n *                      indicate that it would be redundant?                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Simplified to use object pointers.                                       *\n *   12/24/1994 JLB : Only checks if cell is in view and not flagged already.                  *\n *=============================================================================================*/\nvoid CellClass::Redraw_Objects(bool forced)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tCELL\tcell = Cell_Number();\n\n\tif (Map.In_View(cell) && (forced || !Map.Is_Cell_Flagged(cell))) {\n\n\t\t/*\n\t\t**\tFlag the icon to be redrawn.\n\t\t*/\n\t\tMap.Flag_Cell(cell);\n\n\t\t/*\n\t\t**\tFlag the main object in the cell to be redrawn.\n\t\t*/\n\t\tif (Cell_Occupier() != NULL) {\n\t\t\tObjectClass * optr = Cell_Occupier();\n\t\t\twhile (optr != NULL && optr->IsActive) {\n\n#ifdef SORTDRAW\n\t\t\t\tif (optr->Is_Techno() && ((TechnoClass *)optr)->Visual_Character() != VISUAL_NORMAL) {\n\t\t\t\t\toptr->Mark(MARK_CHANGE);\n\t\t\t\t}\n#else\n\t\t\t\toptr->Mark(MARK_CHANGE);\n#endif\n\t\t\t\tif (optr->Next != NULL && !optr->Next->IsActive) {\n\t\t\t\t\toptr->Next = NULL;\n\t\t\t\t}\n\t\t\t\toptr = optr->Next;\n\t\t\t}\n\t\t}\n\n#ifdef SORTDRAW\n\t\t/*\n\t\t**\tFlag any overlapping object in this cell to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tif (Overlapper[index]) {\n\t\t\t\tassert(Overlapper[index]->IsActive);\n\t\t\t\tif (Overlapper[index]->Is_Techno() && ((TechnoClass *)Overlapper[index])->Visual_Character() != VISUAL_NORMAL) {\n\t\t\t\t\tOverlapper[index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t/*\n\t\t**\tFlag any overlapping object in this cell to be redrawn.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tif (Overlapper[index] != NULL) {\n\t\t\t\tif (!Overlapper[index]->IsActive) {\n\t\t\t\t\tOverlapper[index] = NULL;\n\t\t\t\t} else {\n\t\t\t\t\tOverlapper[index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Clear_To_Build -- Determines if cell can be built upon.                       *\n *                                                                                             *\n *    This determines if the cell can become a proper foundation for                           *\n *    building placement.                                                                      *\n *                                                                                             *\n * INPUT:   loco     -- The locomotion of the object trying to consider if this cell is        *\n *                      generally clear. Buildings use the value of SPEED_NONE.                *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell generally clear (usually for building purposes)?                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1994 JLB : Created.                                                                 *\n *   06/25/1996 JLB : Handles different locomotion types.                                      *\n *   10/05/1996 JLB : Checks for crushable walls and crushable object.                         *\n *=============================================================================================*/\nbool CellClass::Is_Clear_To_Build(SpeedType loco) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tDuring scenario initialization, passability is always guaranteed.\n\t*/\n\tif (ScenarioInit) return(true);\n\n\t/*\n\t**\tIf there is an object there, then don't allow building.\n\t*/\n\tif (Cell_Object() != NULL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tPrevents a building from being placed over a flag object.\n\t*/\n#ifdef FIXIT_FLAG_CHECK\n\tif (IsFlagged)  {\n\t\treturn(false);\n\t}\n#endif\n\n\t/*\n\t**\tWalls are always considered to block the terrain for general passability\n\t**\tpurposes. In normal game mode, all overlays are not buildable.\n\t*/\n\tif (Overlay != OVERLAY_NONE && (Overlay == OVERLAY_FLAG_SPOT || !Debug_Map || OverlayTypeClass::As_Reference(Overlay).IsWall)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tBuilding over a bib is not allowed.\n\t*/\n\tif (Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(Smudge).IsBib /* && Owner != HOUSE_NONE*/) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tBuilding on certain kinds of terrain is prohibited -- bridges in particular.\n\t**\tIf the locomotion type is SPEED_NONE, then this check is presumed to be\n\t**\tfor the purposes of building.\n\t*/\n\tif (loco == SPEED_NONE) {\n\t\tif (Is_Bridge_Here()) {\n\t\t\treturn(false);\n\t\t}\n\n\t\treturn(::Ground[Land_Type()].Build);\n\n\t} else {\n\n\t\tif (::Ground[Land_Type()].Cost[loco] == fixed(0)) {\n//\t\tif (::Ground[Land_Type()].Cost[SPEED_TRACK] == fixed(0)) {\n\t\t\treturn(false);\n\t\t}\n\t\treturn(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.       *\n *                                                                                             *\n *    This routine recalculates the ground type in the cell. The speeds the find path          *\n *    algorithm and other determinations of the cell type.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Knows about template pointer in cell object.                             *\n *=============================================================================================*/\nvoid CellClass::Recalc_Attributes(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tSpecial override for interior terrain set so that a non-template or a clear template\n\t**\tis equivalent to impassable rock.\n\t*/\n\tif (LastTheater == THEATER_INTERIOR) {\n\t\tif (TType == TEMPLATE_NONE || TType == TEMPLATE_CLEAR1) {\n\t\t\tLand = LAND_ROCK;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck for wall effects.\n\t*/\n\tif (Overlay != OVERLAY_NONE) {\n\t\tLand = OverlayTypeClass::As_Reference(Overlay).Land;\n\t\tif (Land != LAND_CLEAR) return;\n\t}\n\n\t/*\n\t**\tIf there is a template associated with this cell, then fetch the\n\t**\tland type given the template type and icon number.\n\t*/\n\tif (TType != TEMPLATE_NONE && TType != 255) {\n\t\tTemplateTypeClass const * ttype = &TemplateTypeClass::As_Reference(TType);\n\t\tLand = ttype->Land_Type(TIcon);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tNo template is the same as clear terrain.\n\t*/\n\tLand = LAND_CLEAR;\n}\n\n\n/***********************************************************************************************\n * CellClass::Occupy_Down -- Flag occupation of specified cell.                                *\n *                                                                                             *\n *    This routine is used to mark the cell as being occupied by the specified object.         *\n *                                                                                             *\n * INPUT:   object   -- The object that is to occupy the cell                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   11/29/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid CellClass::Occupy_Down(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tObjectClass * optr;\n\n\tif (object == NULL) return;\n\n\t/*\n\t**\tAlways add buildings to the end of the occupation chain. This is necessary because\n\t**\tthe occupation chain is a single list even though buildings occupy more than one\n\t**\tcell. If more than one building is allowed to occupy the same cell, then this chain\n\t**\tlogic will fail.\n\t*/\n\tif (object->What_Am_I() == RTTI_BUILDING && Cell_Occupier()) {\n\t\toptr = Cell_Occupier();\n\t\twhile (optr->Next != NULL) {\n\t\t\tassert(optr != object);\n\t\t\tassert(optr->What_Am_I() != RTTI_BUILDING);\n\t\t\toptr = optr->Next;\n\t\t}\n\t\toptr->Next = object;\n\t\tobject->Next = 0;\n\t} else {\n\t\tobject->Next = Cell_Occupier();\n\t\tOccupierPtr = object;\n\t}\n\tMap.Radar_Pixel(Cell_Number());\n\n\t/*\n\t**\tIf being placed down on a visible square, then flag this\n\t**\ttechno object as being revealed to the player.\n\t*/\n\t// Changes for client/server multiplayer. ST - 8/2/2019 2:51PM\n\t//if (IsMapped || Session.Type != GAME_NORMAL) {\n\t//\tobject->Revealed(PlayerPtr);\n\t//}\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (IsMapped || Session.Type != GAME_NORMAL) {\n\t\t\tobject->Revealed(PlayerPtr);\n\t\t}\n\t} else {\n\t\t\n\t\tfor (int i = 0; i < Session.Players.Count(); i++) {\n\t\t\tHousesType house_type = Session.Players[i]->Player.ID;\n\t\t\tif (Is_Visible(house_type)) {\n\t\t\t\tHouseClass *house = HouseClass::As_Pointer(house_type);\n\t\t\t\tobject->Revealed(house);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/*\n\t**\tSpecial occupy bit set.\n\t*/\n\tswitch (object->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tFlag.Occupy.Building = true;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_UNIT:\n\t\t\tFlag.Occupy.Vehicle = true;\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tFlag.Occupy.Monolith = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                    *\n *                                                                                             *\n *    This routine will lift the object from the cell and free the cell to be occupied by      *\n *    another object. Only if the cell was previously marked with the object specified, will   *\n *    the object be lifted off. This routine is the counterpart to Occupy_Down().              *\n *                                                                                             *\n * INPUT:   object   -- The object that is being lifted off.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   11/29/1994 JLB : Fixed to handle next pointer in previous object.                         *\n *=============================================================================================*/\nvoid CellClass::Occupy_Up(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tif (object == NULL) return;\n\n\tObjectClass * optr = Cell_Occupier();\t\t// Working pointer to the objects in the chain.\n\n\tif (optr == object) {\n\t\tOccupierPtr = object->Next;\n\t\tobject->Next = 0;\n\t} else {\n\t\tbool found = false;\n\t\twhile (optr != NULL) {\n\t\t\tif (optr->Next == object) {\n\t\t\t\toptr->Next = object->Next;\n\t\t\t\tobject->Next = 0;\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\toptr = optr->Next;\n\t\t}\n//\t\tassert(found);\n\t}\n\tMap.Radar_Pixel(Cell_Number());\n\n\t/*\n\t**\tSpecial occupy bit clear.\n\t*/\n\tswitch (object->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tFlag.Occupy.Building = false;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_UNIT:\n\t\t\tFlag.Occupy.Vehicle = false;\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tFlag.Occupy.Monolith = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (overla*\n *                                                                                             *\n *    Most game objects can often have their graphic imagery spill into more than one cell     *\n *    even though they are considered to \"occupy\" only one cell. All cells overlapped are      *\n *    flagged by this routine. Using this information it is possible to keep the tactical map  *\n *    display correct.                                                                         *\n *                                                                                             *\n * INPUT:   object   -- The object to mark as overlapping this cell.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Ensures that buildings are always marked down.                           *\n *=============================================================================================*/\nvoid CellClass::Overlap_Down(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tObjectClass ** ptr = 0;\n\n\tif (!object) return;\n\n\tint index;\n\tfor (index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] == object) return;\n\t\tif (!Overlapper[index]) ptr = &Overlapper[index];\n\t}\n\n\t/*\n\t**\tBuildings must ALWAYS succeed in marking the cell as overlapped. Bump somebody\n\t**\telse out in this case.\n\t*/\n\tif (!ptr && object->What_Am_I() == RTTI_BUILDING) {\n\t\tfor (index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tswitch (Overlapper[index]->What_Am_I()) {\n\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\tcase RTTI_TERRAIN:\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tOverlapper[index] = object;\n\t\t\t\t\tindex = ARRAY_SIZE(Overlapper);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (ptr) *ptr = object;\n\n\t/*\n\t**\tIf being placed down on a visible square, then flag this\n\t**\ttechno object as being revealed to the player.\n\t*/\n\tif (IsMapped) {\n\t\tobject->Revealed(PlayerPtr);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Overlap_Up -- Removes overlap flag for the cell.                                 *\n *                                                                                             *\n *    This is the counterpart to Overlap_Down and is used to remove the overlap flag for the   *\n *    specified unit on the cell.                                                              *\n *                                                                                             *\n * INPUT:   object   -- The object to remove the overlap flag for.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Overlap_Up(ObjectClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tassert(object != NULL && object->IsActive);\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] == object) {\n\t\t\tOverlapper[index] = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                        *\n *                                                                                             *\n *    This routine will determine if a unit is occupying the cell and if so, return a pointer  *\n *    to it. If there is no unit occupying the cell, then NULL is returned.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to unit occupying cell, else NULL.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass * CellClass::Cell_Unit(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((UnitClass*)Cell_Find_Object(RTTI_UNIT));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Vessel -- Returns with pointer to a vessel located in the cell.             *\n *                                                                                             *\n *    Call this routine to query and return a pointer to a vessel located in the cell. If      *\n *    there is no vessel present, then this routine will return NULL.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the vessel class object if one is present.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass * CellClass::Cell_Vessel(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((VesselClass*)Cell_Find_Object(RTTI_VESSEL));\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Infantry -- Returns with pointer of first infantry unit occupying the cell. *\n *                                                                                             *\n *    This routine examines the cell and returns a pointer to the first infantry unit          *\n *    that occupies it. If there is no infantry unit in the cell, then NULL is returned.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to infantry unit occupying the cell or NULL if none are       *\n *          present.                                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass * CellClass::Cell_Infantry(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn((InfantryClass*)Cell_Find_Object(RTTI_INFANTRY));\n}\n\n\n#ifdef SORTDRAW\nstatic bool _Calc_Partial_Window(int cellx, int celly, int & drawx, int & drawy)\n{\n\tint & px = WindowList[WINDOW_PARTIAL][WINDOWX];\n\tint & py = WindowList[WINDOW_PARTIAL][WINDOWY];\n\tint & pw = WindowList[WINDOW_PARTIAL][WINDOWWIDTH];\n\tint & ph = WindowList[WINDOW_PARTIAL][WINDOWHEIGHT];\n\tint & tx = WindowList[WINDOW_TACTICAL][WINDOWX];\n\tint & ty = WindowList[WINDOW_TACTICAL][WINDOWY];\n\tint & tw = WindowList[WINDOW_TACTICAL][WINDOWWIDTH];\n\tint & th = WindowList[WINDOW_TACTICAL][WINDOWHEIGHT];\n\n\tpx = cellx + tx;\n\tpy = celly + ty;\n\tpw = CELL_PIXEL_W;\n\tph = CELL_PIXEL_H;\n\n\tif (px < tx) {\n\t\tpw -= tx - px;\n\t\tpx = tx;\n\t}\n\tif (pw < 1) return(false);\n\n\tif (py < ty) {\n\t\tph -= ty - py;\n\t\tpy = ty;\n\t}\n\tif (ph < 1) return(false);\n\n\tif (px + pw > tx + tw) {\n\t\tpw -= (px + pw) - (tx + tw);\n\t}\n\tif (pw < 1) return(false);\n\n\tif (py + ph > ty + th) {\n\t\tph -= (py + ph) - (ty + th);\n\t}\n\tif (ph < 1) return(false);\n\n\tdrawx = drawx - (px-tx);\n\tdrawy = drawy - (py-ty);\n\treturn(true);\n}\n\n\nstatic int _ocompare(const void * left, const void * right)\n{\n\tCOORDINATE lcoord = (*((ObjectClass **)left))->Sort_Y();\n\tCOORDINATE rcoord = (*((ObjectClass **)right))->Sort_Y();\n\tif (lcoord < rcoord) return(-1);\n\tif (lcoord > rcoord) return(1);\n\treturn(0);\n}\n#endif\n\n\n/***********************************************************************************************\n * CellClass::Get_Template_Info -- Get some info about a template for external use             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   Ref to info required                                                               *\n *                                                                                             *\n * OUTPUT:  True if image info available                                                       *\n *                                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   1/10/2019 5:57PM ST : Created.                                                            *\n *=============================================================================================*/\nbool CellClass::Get_Template_Info(char *template_name, int &icon, void *&image_data)\n{\n\tTemplateTypeClass const *ttype = NULL;\n\n\tif (TType != TEMPLATE_NONE && TType != TEMPLATE_CLEAR1 && TType != 255) {\t\t// Not sure why it's checking for 255 here since that's a valid tile type. ST - 6/4/2019\n\t\tttype = &TemplateTypeClass::As_Reference(TType);\n\t\ticon = TIcon;\n\t}\n\telse {\n\t\tttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);\n\t\ticon = Clear_Icon();\n\t}\n\n\tif (ttype) {\n\n\t\tstrcpy(template_name, ttype->IniName);\n\t\timage_data = (void*)ttype->ImageData;\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n\n\n/***********************************************************************************************\n * CellClass::Draw_It -- Draws the cell imagery at the location specified.                     *\n *                                                                                             *\n *    This is the gruntwork cell rendering code. It draws the cell at the screen location      *\n *    specified. This routine doesn't draw any overlapping or occupying units. It only         *\n *    deals with the ground (cell) layer -- icon level.                                        *\n *                                                                                             *\n * INPUT:   x,y   -- The screen coordinates to render the cell imagery at.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   08/21/1994 JLB : Revised for simple template objects.                                     *\n *   11/01/1994 BRR : Updated placement cursor; draws actual object                            *\n *   11/14/1994 BRR : Added remapping code to show passable areas                              *\n *   12/02/1994 BRR : Added trigger display                                                    *\n *   12/11/1994 JLB : Mixes up clear terrain through pseudo-random table.                      *\n *   04/25/1995 JLB : Smudges drawn BELOW overlays.                                            *\n *   07/22/1996 JLB : Objects added to draw process.                                           *\n *=============================================================================================*/\nvoid CellClass::Draw_It(int x, int y, bool objects) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (!objects) {\n\t\tBStart(BENCH_CELL);\n\n\t\tTemplateTypeClass const * ttype = 0;\n\t\tint\ticon;\t\t// The icon number to use from the template set.\n\t\tCELL\tcell = Cell_Number();\n\t\tvoid * remap = NULL;\n\t#ifdef SCENARIO_EDITOR\n\t\tTemplateTypeClass * tptr;\n//\t\tTriggerClass * trig;\n\t\tint i;\n\t\tchar waypt[3];\n\t#endif\n\n\t\tCellCount++;\n\n\t\t/*\n\t\t**\tFetch a pointer to the template type associated with this cell.\n\t\t*/\n\t\tif (TType != TEMPLATE_NONE && TType != TEMPLATE_CLEAR1 && TType != 255) {\n\t\t\tttype = &TemplateTypeClass::As_Reference(TType);\n\t\t\ticon = TIcon;\n\t\t} else {\n\t\t\tttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);\n\t\t\ticon = Clear_Icon();\n\t\t}\n\n\t#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tDraw the stamp of the template.\n\t\t*/\n\t\tif (Debug_Icon) {\n\t\t\tLogicPage->Fill_Rect(Map.TacPixelX+x, Map.TacPixelY+y, Map.TacPixelX+x+ICON_PIXEL_W-1, Map.TacPixelY+y+ICON_PIXEL_H-1, Sim_Random_Pick(1, 254));\n\t\t\tFontXSpacing -= 2;\n\t\t\tFancy_Text_Print(\"%02X%02X\\r%d%d%d\\r%d %d\", Map.TacPixelX+x+(ICON_PIXEL_W>>1), Map.TacPixelY+y, &GreyScheme, TBLACK, TPF_EFNT|TPF_CENTER|TPF_BRIGHT_COLOR|TPF_FULLSHADOW,\n\t\t\t\tCell_Y(cell), Cell_X(cell),\n\t\t\t\t//(CurrentObject.Count() && CurrentObject[0]->Is_Techno()) ? ((TechnoClass *)CurrentObject[0])->House->Which_Zone(cell) : -1,\n\t\t\t\tZones[MZONE_NORMAL],Zones[MZONE_CRUSHER],Zones[MZONE_DESTROYER],\n\t\t\t\tOverlay, OverlayData\n\t\t\t\t);\n\t\t\tFontXSpacing += 2;\n\t\t} else {\n\t#endif\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tSet up the remap table for this icon.\n\t\t\t*/\n\t\t\tif (Debug_Map && Debug_Passable) {\n\t\t\t\tif (::Ground[Land].Cost[0] == 0 || (Cell_Occupier() != NULL &&\n\t\t\t\t\tCell_Occupier()->What_Am_I() != RTTI_INFANTRY)) {\t// impassable\n\t\t\t\t\tremap = DisplayClass::FadingRed;\n\t\t\t\t} else {\n\t\t\t\t\tif (::Ground[Land].Cost[0] > fixed(1, 3)) {\t// pretty passable\n\t\t\t\t\t\tremap = DisplayClass::FadingGreen;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tremap = DisplayClass::FadingYellow;\t\t\t\t// moderately passable\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tThis is the underlying terrain icon.\n\t\t\t*/\n\t\t\tif (ttype->Get_Image_Data()) {\n\t\t\t\tLogicPage->Draw_Stamp(ttype->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\tif (remap) {\n\t\t\t\t\tLogicPage->Remap(x+Map.TacPixelX, y+Map.TacPixelY, ICON_PIXEL_W, ICON_PIXEL_H, remap);\n\t\t\t\t}\n\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tDraw the map editor's \"current\" cell. This is the cell that can be\n\t\t\t**\tassigned attributes such as tag labels.\n\t\t\t**\tThis must be draw before the placement cursor, but after drawing the\n\t\t\t**\tobjects in the cell.\n\t\t\t*/\n\t\t\tif (Debug_Map && CurrentCell == Cell_Number()) {\n\t\t\t\tLogicPage->Draw_Rect(x+Map.TacPixelX, y+Map.TacPixelY, Map.TacPixelX + x + CELL_PIXEL_W - 1, Map.TacPixelY + y + CELL_PIXEL_H - 1, YELLOW);\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tRedraw any smudge.\n\t\t\t*/\n\t\t\tif (Smudge != SMUDGE_NONE) {\n\t\t\t\tSmudgeTypeClass::As_Reference(Smudge).Draw_It(x, y, SmudgeData);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the overlay object.\n\t\t\t*/\n\t\t\tif (Overlay != OVERLAY_NONE) {\n\t\t\t\tOverlayTypeClass const & otype = OverlayTypeClass::As_Reference(Overlay);\n\t\t\t\tIsTheaterShape = (bool)otype.IsTheater;\t//Tell Build_Frame if this overlay is theater specific\n\t\t\t\tCC_Draw_Shape(otype.Get_Image_Data(), OverlayData, (x+(CELL_PIXEL_W>>1)), (y+(CELL_PIXEL_H>>1)), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, DisplayClass::UnitShadow);\n\t\t\t\tIsTheaterShape = false;\n\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\tif (Debug_Map) {\n\t\t\t\t/*\n\t\t\t\t**\tDraw the cell's Trigger mnemonic, if it has a trigger\n\t\t\t\t*/\n\t\t\t\tif (Trigger.Is_Valid()) {\n\t\t\t\t\tFancy_Text_Print(Trigger->Class->IniName, x+Map.TacPixelX, y+Map.TacPixelY, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the cell's Waypoint designation if there is one.\n\t\t\t\t*/\n\t\t\t\tif (IsWaypoint) {\n\t\t\t\t\tfor (i = 0; i < WAYPT_HOME; i++) {\n\t\t\t\t\t\tif (Scen.Waypoint[i] == Cell_Number()) {\n\t\t\t\t\t\t\tif (i < 26) {\n\t\t\t\t\t\t\t\twaypt[0] = 'A' + i;\n\t\t\t\t\t\t\t\twaypt[1] = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twaypt[0] = 'A' + (i/26)-1;\n\t\t\t\t\t\t\t\twaypt[1] = 'A' + (i % 26);\n\t\t\t\t\t\t\t\twaypt[2] = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tFancy_Text_Print(waypt, Map.TacPixelX + x + CELL_PIXEL_W / 2,\n\t\t\t\t\t\t\t\tMap.TacPixelY + y + (CELL_PIXEL_H / 2) - 3,\n\t\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_RED], TBLACK,\n\t\t\t\t\t\t\t\tTPF_EFNT | TPF_CENTER|TPF_FULLSHADOW);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Scen.Waypoint[WAYPT_HOME] == Cell_Number()) {\n\t\t\t\t\t\t\tFancy_Text_Print(\"Home\", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,\n\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t\t}\n\t\t\t\t\tif (Scen.Waypoint[WAYPT_REINF] == Cell_Number()) {\n\t\t\t\t\t\t\tFancy_Text_Print(\"Reinf\", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,\n\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK, TPF_EFNT|TPF_FULLSHADOW);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t#endif\n\n\t\t\t/*\n\t\t\t**\tDraw the placement cursor:\n\t\t\t**\t- First, draw the hash-mark cursor, so it will appear underneath\n\t\t\t**\t  any cursor being drawn\n\t\t\t**\t- If the PendingObject is a template, overlay, or smudge, draw it\n\t\t\t**\t- Otherwise, it's up to the Display.Refresh_Map() routine to draw it\n\t\t\t*/\n\t\t\tif (IsCursorHere) {\n\t\t\t\tSpeedType loco = SPEED_NONE;\n\t\t\t\tif (Map.PendingObjectPtr) {\n\t\t\t\t\tif (Map.PendingObjectPtr->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\tBuildingClass * obj = (BuildingClass *)(Map.PendingObjectPtr);\n\t\t\t\t\t\tloco = obj->Class->Speed;\n\t//\t\t\t\t\tif (*obj == STRUCT_SUB_PEN || *obj == STRUCT_SHIP_YARD ||\n\t//\t\t\t\t\t    *obj == STRUCT_FAKE_PEN || *obj == STRUCT_FAKE_YARD) loco = SPEED_FLOAT;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the hash-mark cursor:\n\t\t\t\t*/\n\t\t\t\tif (Map.ProximityCheck && Is_Clear_To_Build(loco)) {\n\t\t\t\t\tLogicPage->Draw_Stamp(DisplayClass::TransIconset, 0, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t} else {\n\t\t\t\t\tLogicPage->Draw_Stamp(DisplayClass::TransIconset, 2, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t}\n\n\t#ifdef SCENARIO_EDITOR\n\t\t\t\tif (Debug_Map && Map.PendingObject) {\n\n\t\t\t\t\tswitch (Map.PendingObject->What_Am_I()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw a template:\n\t\t\t\t\t\t**\t- Compute the icon offset of this cell for this template, using\n\t\t\t\t\t\t**\t  ZoneCell+ZoneOffset to get the upper-left corner of the placement\n\t\t\t\t\t\t**\t  cursor\n\t\t\t\t\t\t**\t- Draw the icon\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_TEMPLATETYPE:\n\t\t\t\t\t\t\ttptr = (TemplateTypeClass *)Map.PendingObject;\n\t\t\t\t\t\t\tif (tptr->Get_Image_Data()) {\n\t\t\t\t\t\t\t\ticon = (Cell_X(cell) - Cell_X(Map.ZoneCell + Map.ZoneOffset)) +\n\t\t\t\t\t\t\t\t\t(Cell_Y(cell) - Cell_Y(Map.ZoneCell + Map.ZoneOffset)) *\n\t\t\t\t\t\t\t\t\ttptr->Width;\n\t\t\t\t\t\t\t\tLogicPage->Draw_Stamp(tptr->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw an overlay; just use the existing 'OverlayData' even though\n\t\t\t\t\t\t**\tit means nothing.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_OVERLAYTYPE:\n\t\t\t\t\t\t\tOverlayTypeClass::As_Reference(((OverlayTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, OverlayData);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDraw a smudge\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_SMUDGETYPE:\n\t\t\t\t\t\t\tSmudgeTypeClass::As_Reference(((SmudgeTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, 0);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t#endif\n\t\t\t}\n\n\t#ifdef CHEAT_KEYS\n\t\t}\n\t#endif\n\t\tBEnd(BENCH_CELL);\n\t}\n\n#ifdef SORTDRAW\n\tif (objects) {\n\t\tBStart(BENCH_OBJECTS);\n\n\t\t/*\n\t\t**\tBuild a list of objects to draw into a working buffer. There is a\n\t\t**\tbig presumption here -- it is presumed that if the cell is to be\n\t\t**\tredrawn, then all objects in the cell should properly be flagged to\n\t\t**\tbe redrawn as well. Normally, this isn't a problem, but for subs\n\t\t**\tthe IsToDisplay flag MUST REMAIN SET. This is because there is a\n\t\t**\thack overpass after the cells are redrawn so that subs can be\n\t\t**\tredrawn separately.\n\t\t*/\n\t\tstatic DynamicVectorClass<ObjectClass*> optr(20 + ARRAY_SIZE(Overlapper));\n\t\toptr.Delete_All();\n\t\tObjectClass * object = Cell_Occupier();\n\t\twhile (object != NULL) {\n\t\t\tif (!object->IsActive) break;\n\t\t\toptr.Add(object);\n\t\t\tobject->IsToDisplay = true;\n\t\t\tobject = object->Next;\n\t\t}\n\t\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\t\tobject = Overlapper[index];\n\t\t\tif (object != NULL && object->IsActive) {\n\t\t\t\tobject->IsToDisplay = true;\n\t\t\t\toptr.Add(object);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tSort the object list so that objects will be drawn from\n\t\t**\tback to front.\n\t\t*/\n\t\tswitch (optr.Count()) {\n\n\t\t\t/*\n\t\t\t**\tIf there are zero or one object, then sorting is\n\t\t\t**\tunnecessary.\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTwo objects can be sorted with a single compare and swap.\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tif (optr[0]->Sort_Y() > optr[1]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[1]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThree objects can be sorted with three compares and swaps.\n\t\t\t*/\n\t\t\tcase 3:\n\t\t\t\tif (optr[0]->Sort_Y() > optr[2]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[2]);\n\t\t\t\t}\n\t\t\t\tif (optr[0]->Sort_Y() > optr[1]->Sort_Y()) {\n\t\t\t\t\tswap(optr[0], optr[1]);\n\t\t\t\t}\n\t\t\t\tif (optr[1]->Sort_Y() > optr[2]->Sort_Y()) {\n\t\t\t\t\tswap(optr[1], optr[2]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLarge number of objects can be effeciently sorted by using\n\t\t\t**\ta quicksort.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tqsort(&optr[0], optr.Count(), sizeof(ObjectClass*), _ocompare);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tDraw any objects that happen to be in or overlapping this cell.\n\t\t*/\n\t\tfor (int index = 0; index < optr.Count(); index++) {\n\t\t\tobject = optr[index];\n\t\t\tint xx,yy;\n\t\t\tif (object->IsToDisplay && (!object->Is_Techno() || ((TechnoClass *)object)->Visual_Character() == VISUAL_NORMAL) && Map.Coord_To_Pixel(object->Render_Coord(), xx, yy)) {\n\t\t\t\tif (_Calc_Partial_Window(x, y, xx, yy)) {\n\t\t\t\t\tobject->Draw_It(xx, yy, WINDOW_PARTIAL);\n\t\t\t\t\tif (Debug_Map) {\n\t\t\t\t\t\tobject->IsToDisplay = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobject->IsToDisplay = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tobject->IsToDisplay = false;\n\t\t\t}\n\t\t}\n\t\tBEnd(BENCH_OBJECTS);\n\t}\n#endif\n\n}\n\n\n/***********************************************************************************************\n * CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.               *\n *                                                                                             *\n *    This routine examines the cells around the current one and from this, determines what    *\n *    concrete icon shape to use (if any). The cell data is adjusted and the cell is marked    *\n *    for redraw if the icon changed.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Concrete_Calc(void)\n{\n#ifdef OBSOLETE\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tstatic FacingType _even[5] = {FACING_N, FACING_S, FACING_SW, FACING_W, FACING_NW};\n\tstatic FacingType _odd[5] = {FACING_N, FACING_NE, FACING_E, FACING_SE, FACING_S};\n\tFacingType * ptr;\t\t// Working pointer into adjacent cell list.\n\tint\tindex;\t// Constructed bit index.\n\tint\ticon;\t\t// Icon number.\n\tbool\tisodd;\t// Is this for the odd column?\n\n#define\tOF_N\t0x01\n#define\tOF_NE\t0x02\n#define\tOF_E\t0x04\n#define\tOF_SE\t0x08\n#define\tOF_S\t0x10\n\n#define\tEF_N\t0x01\n#define\tEF_NW\t0x10\n#define\tEF_W\t0x08\n#define\tEF_SW\t0x04\n#define\tEF_S\t0x02\n\n\t/*\n\t**\tDetermine if the even or odd row logic is necessary.\n\t*/\n\tisodd = ((Cell_Number() & 0x01) != 0);\n\n\t/*\n\t**\tFetch correct pointer depending on whether this is for an\n\t**\todd or even row.\n\t*/\n\tptr = (isodd) ? _odd : _even;\n\n\t/*\n\t**\tBuild an index according to the presence of concrete in the special\n\t**\tadjacent cells. This is a short list of adjacent cell flags since\n\t**\tonly 5 adjacent cells need to be examined. The choice of which 5\n\t**\tdepends on whether this is for an even or odd column.\n\t*/\n\tindex = 0;\n\tfor (int i = 0; i < (sizeof(_even)/sizeof(_even[0])); i++) {\n\t\tCellClass & cellptr = Adjacent_Cell(*ptr++);\n\n\t\tif (cellptr.Overlay == OVERLAY_CONCRETE) {\n\t\t\tindex |= (1<<i);\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial logic occurs for cells that are concrete filled.\n\t*/\n\tif (Overlay == OVERLAY_CONCRETE) {\n\n\t\t/*\n\t\t**\tProcess the index value and place the appropriate concrete icon\n\t\t**\tin the cell.\n\t\t*/\n\t\tif (isodd) {\n\t\t\tswitch (index) {\n\t\t\t\tcase OF_NE:\n\t\t\t\tcase OF_N|OF_NE:\n\t\t\t\tcase OF_E|OF_N:\n\t\t\t\tcase OF_E|OF_NE:\n\t\t\t\tcase OF_N|OF_NE|OF_E:\n\t\t\t\tcase OF_S|OF_N|OF_NE:\n\t\t\t\t\ticon = C_RIGHT_UP;\t\t// right - up\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_SE:\n\t\t\t\tcase OF_E|OF_SE:\n\t\t\t\tcase OF_S|OF_SE:\n\t\t\t\tcase OF_S|OF_E:\n\t\t\t\tcase OF_S|OF_SE|OF_E:\n\t\t\t\tcase OF_S|OF_SE|OF_N:\n\t\t\t\t\ticon = C_RIGHT_DOWN;\t\t// right - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_SE|OF_NE:\n\t\t\t\tcase OF_SE|OF_NE|OF_N:\n\t\t\t\tcase OF_SE|OF_NE|OF_S:\n\t\t\t\tcase OF_SE|OF_NE|OF_S|OF_N:\n\t\t\t\tcase OF_SE|OF_E|OF_N:\n\t\t\t\tcase OF_SE|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_E|OF_N:\n\t\t\t\tcase OF_S|OF_E|OF_NE:\n\t\t\t\tcase OF_S|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_NE|OF_N:\n\t\t\t\tcase OF_S|OF_SE|OF_E|OF_NE:\n\t\t\t\t\ticon = C_RIGHT_UPDOWN;\t\t// right - up - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\ticon = C_RIGHT;\t\t// right\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (index) {\n\t\t\t\tcase EF_NW:\n\t\t\t\tcase EF_NW|EF_N:\n\t\t\t\tcase EF_W|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_N:\n\t\t\t\tcase EF_NW|EF_W:\n\t\t\t\tcase EF_NW|EF_S|EF_N:\n\t\t\t\t\ticon = C_LEFT_UP;\t\t// left - up\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_SW:\n\t\t\t\tcase EF_SW|EF_S:\n\t\t\t\tcase EF_W|EF_S:\n\t\t\t\tcase EF_W|EF_SW|EF_S:\n\t\t\t\tcase EF_W|EF_SW:\n\t\t\t\tcase EF_SW|EF_S|EF_N:\n\t\t\t\t\ticon = C_LEFT_DOWN;\t\t// left - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_NW|EF_SW:\n\t\t\t\tcase EF_NW|EF_SW|EF_N:\n\t\t\t\tcase EF_NW|EF_SW|EF_S:\n\t\t\t\tcase EF_NW|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_W|EF_S|EF_N:\n\t\t\t\tcase EF_W|EF_SW|EF_N:\n\t\t\t\tcase EF_W|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_S:\n\t\t\t\tcase EF_NW|EF_W|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_S|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_N:\n\t\t\t\tcase EF_NW|EF_W|EF_SW|EF_S:\n\t\t\t\t\ticon = C_LEFT_UPDOWN;\t\t// left - up - down\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\ticon = C_LEFT;\t\t// left\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t// Presume that no concrete piece is needed.\n\t\ticon = C_NONE;\n\t\tif (isodd) {\n\t\t\tindex &= ~(OF_NE|OF_SE);\t\t// Ignore diagonals.\n\t\t\tswitch (index) {\n\t\t\t\tcase OF_N|OF_E:\n\t\t\t\t\ticon = C_UP_RIGHT;\t\t// up right\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_E|OF_S:\n\t\t\t\t\ticon = C_DOWN_RIGHT;\t\t// down right\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OF_N|OF_E|OF_S:\n\t\t\t\t\ticon = C_UPDOWN_RIGHT;\t// up/down right\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tindex &= ~(EF_NW|EF_SW);\t\t// Ignore diagonals.\n\t\t\tswitch (index) {\n\t\t\t\tcase EF_N|EF_W:\n\t\t\t\t\ticon = C_UP_LEFT;\t\t// up left\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_W|EF_S:\n\t\t\t\t\ticon = C_DOWN_LEFT;\t\t// down left\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase EF_N|EF_W|EF_S:\n\t\t\t\t\ticon = C_UPDOWN_LEFT;\t\t// up/down left\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf any kind of fixup piece is needed, then add concrete\n\t\t**\tto this location RECURSIVELY!\n\t\t*/\n\t\tif (icon != C_NONE) {\n\t\t\tOverlayTypeClass::As_Reference(OVERLAY_CONCRETE).Create_And_Place(Cell_Number());\n\t\t\ticon = C_NONE;\n\t\t}\n\n\t}\n\n\t/*\n\t**\tUpdate the icon on the map.\n\t*/\n\tif (icon != C_NONE && OverlayData != icon) {\n\t\tOverlayData = icon;\n\t\t//Array[cell].Base = 0;\n\t\tRedraw_Objects();\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                     *\n *                                                                                             *\n *    This routine will examine the cell and the adjacent cells to determine what the wall     *\n *    should look like with the cell. It will then update the wall's imagery value and flag    *\n *    the cell to be redrawn if necessary. This routine should be called whenever the wall     *\n *    or an adjacent wall is created or destroyed.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   09/19/1994 BWG : Updated to handle partially-damaged walls.                               *\n *=============================================================================================*/\nvoid CellClass::Wall_Update(void)\n{\n\tif (Overlay == OVERLAY_NONE) {\n\t\treturn;\n\t}\n\n\tOverlayTypeClass const & wall = OverlayTypeClass::As_Reference(Overlay);\n\tif (!wall.IsWall) {\n\t\treturn;\n\t}\n\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tstatic FacingType _offsets[5] = {FACING_N, FACING_E, FACING_S, FACING_W, FACING_NONE};\n\n\tfor (unsigned index = 0; index < (sizeof(_offsets)/sizeof(_offsets[0])); index++) {\n\t\tCellClass * newcell = Adjacent_Cell(_offsets[index]);\n\n\t\tif (newcell && newcell->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(newcell->Overlay).IsWall) {\n\t\t\tint\ticon = 0;\n\n\t\t\t/*\n\t\t\t**\tBuild the icon number according to walls located in the adjacent\n\t\t\t**\tcells.\n\t\t\t*/\n\t\t\tfor (unsigned i = 0; i < 4; i++) {\n\t\t\t\tCellClass * adjcell = newcell->Adjacent_Cell(_offsets[i]);\n\t\t\t\tif (adjcell && adjcell->Overlay == newcell->Overlay) {\n\t\t\t\t\ticon |= 1 << i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnewcell->OverlayData = (newcell->OverlayData & 0xFFF0) | icon;\n\n\t\t\t/*\n\t\t\t**\tHandle special cases for the incomplete damaged wall sets. If a damage stage\n\t\t\t**\tis calculated, but there is no artwork for it, then consider the wall to be\n\t\t\t**\tcompletely destroyed.\n\t\t\t*/\n\t\t\tif (newcell->Overlay == OVERLAY_BRICK_WALL && newcell->OverlayData == 48) {\n\t\t\t\tnewcell->Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell->Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell->Overlay == OVERLAY_SANDBAG_WALL && newcell->OverlayData == 16) {\n\t\t\t\tnewcell->Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell->Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell->Overlay == OVERLAY_CYCLONE_WALL && newcell->OverlayData == 32) {\n\t\t\t\tnewcell->Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell->Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell->Overlay == OVERLAY_FENCE && (newcell->OverlayData == 16 || newcell->OverlayData == 32)) {\n\t\t\t\tnewcell->Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell->Cell_Number()), true);\n\t\t\t}\n\t\t\tif (newcell->Overlay == OVERLAY_BARBWIRE_WALL && newcell->OverlayData == 16) {\n\t\t\t\tnewcell->Overlay = OVERLAY_NONE;\n\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\tDetach_This_From_All(::As_Target(newcell->Cell_Number()), true);\n\t\t\t}\n\n\t\t\tnewcell->Recalc_Attributes();\n\t\t\tnewcell->Redraw_Objects();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Cell_Coord -- Returns the coordinate of this cell.                               *\n *                                                                                             *\n *    This support function will determine the coordinate of this cell and return it.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with coordinate value of cell.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE CellClass::Cell_Coord(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\treturn(::Cell_Coord(Cell_Number()));\n}\n\n\n/***********************************************************************************************\n * CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.     *\n *                                                                                             *\n *    This routine will lower the tiberium level in the cell. It is used by the harvesting     *\n *    process as well as by combat damage to the tiberium fields.                              *\n *                                                                                             *\n * INPUT:   levels   -- The number of levels to reduce the tiberium.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the tiberium level reduced by at least one level?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CellClass::Reduce_Tiberium(int levels)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint reducer = 0;\n\n\tif (levels > 0 && Land == LAND_TIBERIUM) {\n\t\tif (OverlayData+1 > levels) {\n\t\t\tOverlayData -= levels;\n\t\t\treducer = levels;\n\t\t} else {\n\t\t\tOverlay = OVERLAY_NONE;\n\t\t\treducer = OverlayData;\n\t\t\tOverlayData = 0;\n\t\t\tRecalc_Attributes();\n\t\t}\n\t}\n\treturn(reducer);\n}\n\n\n/***********************************************************************************************\n * CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                         *\n *                                                                                             *\n *    This routine will change the wall shape used for a wall if it's damaged.                 *\n *                                                                                             *\n * INPUT:   damage   -- The number of damage points the wall was hit with. If this value is    *\n *                      -1, then the entire wall at this cell will be destroyed.               *\n *                                                                                             *\n * OUTPUT:  bool; Was the wall destroyed?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BWG : Created.                                                                 *\n *   03/19/1995 JLB : Updates cell information if wall was destroyed.                          *\n *   10/06/1996 JLB : Updates zone as necessary.                                               *\n *=============================================================================================*/\nint CellClass::Reduce_Wall(int damage)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (Overlay != OVERLAY_NONE) {\n\t\tbool destroyed = false;\n\t\tOverlayTypeClass const & wall = OverlayTypeClass::As_Reference(Overlay);\n\n\t\tif (wall.IsWall) {\n\n\t\t\t/*\n\t\t\t**\tIf the damage was great enough to ensure wall destruction, reduce the wall by one\n\t\t\t**\tlevel (no more). Otherwise determine wall reduction based on a percentage chance\n\t\t\t**\tproportional to the damage received and the wall's strength.\n\t\t\t*/\n\t\t\tif (damage == -1 || damage >= wall.DamagePoints) {\n\t\t\t\tdestroyed = true;\n\t\t\t} else {\n\t\t\t\tdestroyed = Random_Pick(0, wall.DamagePoints) < damage;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the wall is destroyed, destroy it and check for any adjustments to\n\t\t\t**\tadjacent walls.\n\t\t\t*/\n\t\t\tif (destroyed) {\n\t\t\t\tOverlayData+=16;\n\t\t\t\tif (damage == -1 ||\n\t\t\t\t\t(OverlayData>>4) >= wall.DamageLevels ||\n\t\t\t\t\t((OverlayData>>4) == wall.DamageLevels-1 && (OverlayData & 0xF)==0)\t) {\n\n\t\t\t\t\tOwner = HOUSE_NONE;\n\t\t\t\t\tOverlay = OVERLAY_NONE;\n\t\t\t\t\tOverlayData = 0;\n\t\t\t\t\tRecalc_Attributes();\n\t\t\t\t\tRedraw_Objects();\n\t\t\t\t\tCellClass * ncell = Adjacent_Cell(FACING_N);\n\t\t\t\t\tif (ncell) ncell->Wall_Update();\n\t\t\t\t\tCellClass * wcell = Adjacent_Cell(FACING_W);\n\t\t\t\t\tif (wcell) wcell->Wall_Update();\n\t\t\t\t\tCellClass * scell = Adjacent_Cell(FACING_S);\n\t\t\t\t\tif (scell) scell->Wall_Update();\n\t\t\t\t\tCellClass * ecell = Adjacent_Cell(FACING_E);\n\t\t\t\t\tif (ecell) ecell->Wall_Update();\n\t\t\t\t\tDetach_This_From_All(As_Target());\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe zone calculation changes now for non-crushable zone sensitive\n\t\t\t\t\t**\ttravellers.\n\t\t\t\t\t*/\n\t\t\t\t\tif (wall.IsCrushable) {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_NORMAL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_CRUSHER|MZONEF_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Spot_Index -- returns cell sub-coord index for given COORDINATE                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      coord      COORDINATE to compute index for                                             *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      index into StoppingCoord that's closest to this coord                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/21/1994 BR : Created.                                                                  *\n *   12/10/1994 JLB : Uses alternate sub-position algorithm.                                   *\n *=============================================================================================*/\nint CellClass::Spot_Index(COORDINATE coord)\n{\n\tCOORDINATE rel = Coord_Fraction(coord);\t\t// Sub coordinate value within cell.\n\n\t/*\n\t**\tIf the coordinate is close enough to the center of the cell, then return\n\t**\tthe center position index.\n\t*/\n\tif (Distance(rel, (COORDINATE)0x00800080L) < 60) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tSince the center cell position has been eliminated, a simple comparison\n\t**\tas related to the center of the cell can be used to determine the sub\n\t**\tposition. Take advantage of the fact that the sub positions are organized\n\t**\tfrom left to right, top to bottom.\n\t*/\n\tint index = 0;\n\tif (Coord_X(rel) > 0x80) index |= 0x01;\n\tif (Coord_Y(rel) > 0x80) index |= 0x02;\n\treturn(index+1);\n}\n\n\n/***********************************************************************************************\n * CellClass::Closest_Free_Spot -- returns free spot closest to given coord                    *\n *                                                                                             *\n * Similar to the CellClass::Free_Spot; this routine finds the spot in                         *\n * the cell closest to the given coordinate, and returns the COORDINATE of                     *\n * that spot if it's available, NULL if it's not.                                              *\n *                                                                                             *\n * INPUT:                                                                                      *\n *  coord   coordinate to check (only sub cell position examined)                              *\n *                                                                                             *\n *          any   -- If only the closest spot is desired regardless of whether it is free or   *\n *                   not, then this parameter will be true.                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *  COORDINATE of free spot, NULL if none. The coordinate return value does not alter the cell *\n *             coordinate data portions of the coordinate passed in. Only the lower sub-cell   *\n *             data is altered.                                                                *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *  none.                                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/08/1994 BR : Created.                                                                  *\n *   12/10/1994 JLB : Picks best of closest stopping positions.                                *\n *   12/21/1994 JLB : Adds a mix-up factor if center location is occupied.                     *\n *=============================================================================================*/\nCOORDINATE CellClass::Closest_Free_Spot(COORDINATE coord, bool any) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint spot_index = Spot_Index(coord);\n\n\t/*\n\t**\tThis precalculated sequence table records the closest spots to any given spot. Sequential\n\t**\texamination of these spots for availability ensures that the closest available one is\n\t**\tdiscovered first.\n\t*/\n\tstatic unsigned char _sequence[5][4] = {\n\t\t{1,2,3,4},\n\t\t{0,2,3,4},\n\t\t{0,1,4,3},\n\t\t{0,1,4,2},\n\t\t{0,2,3,1}\n\t};\n\n\t/*\n\t**\tIn the case of the center coordinate being requested, but is occupied, then all other\n\t**\tsublocations are equidistant. Instead of picking a static sequence of examination, the\n\t**\torder is mixed up by way of this table.\n\t*/\n\tstatic unsigned char _alternate[4][4] = {\n\t\t{1,2,3,4},\n\t\t{2,3,4,1},\n\t\t{3,4,1,2},\n\t\t{4,1,2,3},\n\t};\n\tcoord = Coord_Whole(coord);\n\n\t/*\n\t**\tCells occupied by buildings or vehicles don't have any free spots.\n\t*/\n\tif (!any && (Flag.Occupy.Vehicle || Flag.Occupy.Monolith)) {\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tIf just the nearest position is desired regardless of whether occupied or not,\n\t**\tthen just return with the stopping coordinate value.\n\t*/\n\tif (any || Is_Spot_Free(spot_index)) {\n\t\treturn(Coord_Add(coord, StoppingCoordAbs[spot_index]));\n\t}\n\n\t/*\n\t**\tScan through all available sub-locations in the cell in order to determine\n\t**\tthe closest one to the coordinate requested. Use precalculated table so that\n\t**\twhen the first free position is found, bail.\n\t*/\n\tunsigned char * sequence;\n\tif (spot_index == 0) {\n\t\tsequence = &_alternate[Random_Pick(0, 3)][0];\n\t} else {\n\t\tsequence = &_sequence[spot_index][0];\n\t}\n\tfor (int index = 0; index < 4; index++) {\n\t\tint pos = *sequence++;\n\n\t\tif (Is_Spot_Free(pos)) {\n\t\t\treturn(Coord_Add(coord, StoppingCoordAbs[pos]));\n\t\t}\n\t}\n\n\t/*\n\t**\tNo free spot could be found so return a NULL coordinate.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * CellClass::Clear_Icon -- Calculates what the clear icon number should be.                   *\n *                                                                                             *\n *    This support routine will determine what the clear icon number would be for the cell.    *\n *    The icon number is determined by converting the cell number into an index into a         *\n *    lookup table. This yields what appears to be a randomized map without the necessity of   *\n *    generating and recording randomized map numbers.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the icon number for clear terrain if it were displayed at the         *\n *          cell.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *   06/09/1995 JLB : Uses 16 entry scramble algorithm.                                        *\n *=============================================================================================*/\nint CellClass::Clear_Icon(void) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tCELL cell = Cell_Number();\n\treturn((Cell_X(cell) & 0x03) | ((Cell_Y(cell) & 0x03) << 2));\n//\treturn((cell & 0x03) | ((unsigned(cell)>>5) & 0x0C));\n}\n\n\n/***********************************************************************************************\n * CellClass::Incoming -- Causes objects in cell to \"run for cover\".                           *\n *                                                                                             *\n *    This routine is called whenever a great, but slow moving, threat is presented to the     *\n *    occupants of a cell. The occupants will, in most cases, stop what they are doing and     *\n *    try to get out of the way.                                                               *\n *                                                                                             *\n * INPUT:   threat      -- The coordinate source of the threat.                                *\n *                                                                                             *\n *          forced      -- If this threat is so major that the occupants should stop what      *\n *                         they are doing, then this parameter should be set to true.          *\n *                                                                                             *\n *          nokidding   -- Override the scatter to also affect human controlled objects.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *   08/02/1996 JLB : Added the \"nokidding\" parameter.                                         *\n *=============================================================================================*/\nvoid CellClass::Incoming(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object = NULL;\n\n\tobject = Cell_Occupier();\n\twhile (object != NULL) {\n\n\t\t/*\n\t\t**\tSpecial check to make sure that friendly units never scatter.\n\t\t*/\n\t\tif (nokidding || Rule.IsScatter || (object->Is_Techno() && ((TechnoClass *)object)->House->IQ >= Rule.IQScatter)) {\n\t\t\tobject->Scatter(threat, forced, nokidding);\n\t\t}\n\t\tobject = object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.               *\n *                                                                                             *\n *    Use this routine to return a reference to the adjacent cell in the direction specified.  *\n *                                                                                             *\n * INPUT:   face  -- The direction to use when determining the adjacent cell.                  *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the adjacent cell.                                     *\n *                                                                                             *\n * WARNINGS:   If the facing value is invalid, then a reference to the same cell is returned.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCellClass const * CellClass::Adjacent_Cell(FacingType face) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (face == FACING_NONE) {\n\t\treturn(this);\n\t}\n\n\tif ((unsigned)face >= FACING_COUNT) {\n\t\treturn(NULL);\n\t}\n\n\tCELL newcell = ::Adjacent_Cell(Cell_Number(), face);\n\tif ((unsigned)newcell >= MAP_CELL_TOTAL) {\n\t\treturn(NULL);\n\t}\n\n\treturn &Map[newcell];\n}\n\n\n/***************************************************************************\n * CellClass::Adjust_Threat -- Allows adjustment of threat at cell level   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/24/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid CellClass::Adjust_Threat(HousesType house, int threat_value)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tint region = Map.Cell_Region(Cell_Number());\n\n\tfor (HousesType lp = HOUSE_FIRST; lp < HOUSE_COUNT; lp ++) {\n\t\tif (lp == house) continue;\n\n\t\tHouseClass * house_ptr = HouseClass::As_Pointer(lp);\n\t\tif (house_ptr && (!house_ptr->IsHuman || !house_ptr->Is_Ally(house))) {\n\t\t\thouse_ptr->Adjust_Threat(region, threat_value);\n\t\t}\n\t}\n\tif (Debug_Threat) {\n\t\tMap.Flag_To_Redraw(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smoothing purposes.       *\n *                                                                                             *\n *    This routine will adjust the level of the Tiberium in the cell so that it will           *\n *    smoothly blend with the adjacent Tiberium. This routine should only be called for        *\n *    new Tiberium cells. Existing cells that contain Tiberium follow a different growth       *\n *    pattern.                                                                                 *\n *                                                                                             *\n * INPUT:   pregame  -- Is this a pregame call? Such a call will mixup the Tiberium overlay    *\n *                      used.                                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the added Tiberium value that is now available for harvesting.        *\n *                                                                                             *\n * WARNINGS:   The return value is only valid for the initial placement. Tiberium growth will  *\n *             increase the net worth of the existing Tiberium.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/16/1995 JLB : Created.                                                                 *\n *   02/20/1996 JLB : Takes into account the ore type.                                         *\n *=============================================================================================*/\nlong CellClass::Tiberium_Adjust(bool pregame)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\tif (Overlay != OVERLAY_NONE) {\n\t\tif (OverlayTypeClass::As_Reference(Overlay).Land == LAND_TIBERIUM) {\n\t\t\tstatic int _adj[9] = {0,1,3,4,6,7,8,10,11};\n\t\t\tstatic int _adjgem[9] = {0,0,0,1,1,1,2,2,2};\n\t\t\tint\tcount = 0;\n\n\t\t\t/*\n\t\t\t**\tMixup the Tiberium overlays so that they don't look the same.\n\t\t\t**\tSince the type of ore is known, also record the nominal\n\t\t\t**\tvalue per step of that ore type.\n\t\t\t*/\n\t\t\tbool gems = false;\n\t\t\tint value = 0;\n\t\t\tif (pregame) {\n\t\t\t\tswitch (Overlay) {\n\t\t\t\t\tcase OVERLAY_GOLD1:\n\t\t\t\t\tcase OVERLAY_GOLD2:\n\t\t\t\t\tcase OVERLAY_GOLD3:\n\t\t\t\t\tcase OVERLAY_GOLD4:\n\t\t\t\t\t\tvalue = Rule.GoldValue;\n\t\t\t\t\t\tOverlay = Random_Pick(OVERLAY_GOLD1, OVERLAY_GOLD4);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_GEMS1:\n\t\t\t\t\tcase OVERLAY_GEMS2:\n\t\t\t\t\tcase OVERLAY_GEMS3:\n\t\t\t\t\tcase OVERLAY_GEMS4:\n\t\t\t\t\t\tgems = true;\n\t\t\t\t\t\tvalue = Rule.GemValue*4;\n\t\t\t\t\t\tOverlay = Random_Pick(OVERLAY_GEMS1, OVERLAY_GEMS4);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAdd up all adjacent cells that contain tiberium.\n\t\t\t** (Skip those cells which aren't on the map)\n\t\t\t*/\n\t\t\tfor (FacingType face = FACING_FIRST; face < FACING_COUNT; face++) {\n\t\t\t\tif ((unsigned)::Adjacent_Cell(Cell_Number(), face) >= MAP_CELL_TOTAL) continue;\n\t\t\t\tCellClass * adj = Adjacent_Cell(face);\n\n\t\t\t\tif (adj && adj->Overlay != OVERLAY_NONE &&\n\t\t\t\t\tOverlayTypeClass::As_Reference(adj->Overlay).Land == LAND_TIBERIUM) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (gems) {\n\t\t\t\tOverlayData = _adjgem[count];\n\t\t\t\tOverlayData = min(OverlayData, 2);\n\t\t\t} else {\n\t\t\t\tOverlayData = _adj[count];\n\t\t\t}\n\t\t\treturn((OverlayData+1) * value);\n\t\t}\n\t}\n\treturn(0);\n}\n\nextern bool MPSuperWeaponDisable;\n\n/***********************************************************************************************\n * CellClass::Goodie_Check -- Performs crate discovery logic.                                  *\n *                                                                                             *\n *    Call this routine whenever an object enters a cell. It will check for the existence      *\n *    of a crate and generate any \"goodie\" it might contain.                                   *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is triggering this crate.                   *\n *                                                                                             *\n * OUTPUT:  Can the object continue to enter this cell? A false return value means that the    *\n *          cell is now occupied and must not be entered.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *   07/08/1995 JLB : Added a bunch of goodies to the crates.                                  *\n *   06/17/1996 JLB : Revamped for Red Alert                                                   *\n *=============================================================================================*/\nbool CellClass::Goodie_Check(FootClass * object)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (object != NULL && Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Overlay).IsCrate) {\n\t\tbool force_mcv = false;\n\t\tint force_money = 0;\n\t\tint damage;\n\t\tCOORDINATE coord;\n\n\t\t/*\n\t\t**\tDetermine the total number of shares for all the crate powerups. This is used as\n\t\t**\tthe base pool to determine the odds from.\n\t\t*/\n\t\tint total_shares = 0;\n\t\tfor (int index = CRATE_FIRST; index < CRATE_COUNT; index++) {\n\t\t\ttotal_shares += CrateShares[index];\n\t\t}\n\n\t\t/*\n\t\t**\tPick a random crate powerup according to the shares allotted to each powerup.\n\t\t**\tIn solo play, the bonus item is dependant upon the rules control.\n\t\t*/\n\t\tCrateType powerup;\n\t\tif (Session.Type == GAME_NORMAL) {\n\n\t\t\t/*\n\t\t\t**\tSolo play has money amount determined by rules.ini file.\n\t\t\t*/\n\t\t\tforce_money = Rule.SoloCrateMoney;\n\n\t\t\tif (Overlay == OVERLAY_STEEL_CRATE) {\n\t\t\t\tpowerup = Rule.SilverCrate;\n\t\t\t}\n\n\t\t\tif (Overlay == OVERLAY_WOOD_CRATE) {\n\t\t\t\tpowerup = Rule.WoodCrate;\n\t\t\t}\n\n\t\t\tif (Overlay == OVERLAY_WATER_CRATE) {\n//Mono_Printf(\"%d-%s.\\n\", __LINE__, __FILE__);\n\t\t\t\tpowerup = Rule.WaterCrate;\n\t\t\t}\n\n\t\t} else {\n\t\t\tint pick = Random_Pick(1, total_shares);\n\n\t\t\tint share_count = 0;\n\t\t\tfor (powerup = CRATE_FIRST; powerup < CRATE_COUNT; powerup++) {\n\t\t\t\tshare_count += CrateShares[powerup];\n\t\t\t\tif (pick <= share_count) break;\n\t\t\t}\n\t\t\tassert(powerup != CRATE_COUNT);\n\n\t\t\t/*\n\t\t\t**\tDepending on what was picked, there might be an alternate goodie if the selected\n\t\t\t**\tgoodie would have no effect.\n\t\t\t*/\n\t\t\tswitch (powerup) {\n\t\t\t\tcase CRATE_UNIT:\n\t\t\t\t\tif (object->House->CurUnits > 50) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_SQUAD:\n\t\t\t\t\tif (object->House->CurInfantry > 100) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_DARKNESS:\n\t\t\t\t\tif (object->House->IsGPSActive) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_ARMOR:\n\t\t\t\t\tif (object->ArmorBias != 1) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_SPEED:\n\t\t\t\t\tif (object->SpeedBias != 1 || object->What_Am_I() == RTTI_AIRCRAFT) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_FIREPOWER:\n\t\t\t\t\tif (object->FirepowerBias != 1 || !object->Is_Weapon_Equipped()) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_REVEAL:\n\t\t\t\t\tif (object->House->IsVisionary) {\n\t\t\t\t\t\tif (object->House->IsGPSActive) {\n\t\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpowerup = CRATE_DARKNESS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_CLOAK:\n\t\t\t\t\tif (object->IsCloakable) powerup = CRATE_MONEY;\n\t\t\t\t\tbreak;\n\n//\t\t\t\tcase CRATE_HEAL_BASE:\n//\t\t\t\t\tif (object->House->BScan == 0) powerup = CRATE_UNIT;\n\n\t\t\t\tcase CRATE_MONEY:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_ICBM:\n\t\t\t\tcase CRATE_PARA_BOMB:\n\t\t\t\tcase CRATE_SONAR:\n\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\tif (MPSuperWeaponDisable) {\n\t\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRATE_TIMEQUAKE:\n\t\t\t\t\t/*\n\t\t\t\t\t** For the time quake crate, scan through and count up all the\n\t\t\t\t\t** units (and infantry and ships and aircraft) and if either\n\t\t\t\t\t** side has very few, allow the time quake.  Otherwise,\n\t\t\t\t\t** change the crate to money or something.  Only do this for\n\t\t\t\t\t** multiplay - for solo play, they get what they get.  First,\n\t\t\t\t\t** check for time - the chance for getting a time quake crate\n\t\t\t\t\t** should be very very low when they first start the mission,\n\t\t\t\t\t** but as time goes on the chance goes up.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\tint i,ucount;\n\t\t\t\t\t\tint minunits = 1000;\n\t\t\t\t\t\tbool found = false;\n\t\t\t\t\t\tunsigned long minutes = (Score.ElapsedTime / TIMER_MINUTE);\n\t\t\t\t\t\tif (minutes > 100) minutes = 100;\n\t\t\t\t\t\tif (Random_Pick(0,100-(int)minutes) == 0) {\n\t\t\t\t\t\t\tfor (i=0; i < (Session.Players.Count() + Session.Options.AIPlayers); i++) {\n\t\t\t\t\t\t\t\tucount = 0;\n\t\t\t\t\t\t\t\tHouseClass * hptr = Houses.Ptr(i + HOUSE_MULTI1);\n\t\t\t\t\t\t\t\tif (hptr != NULL && !hptr->IsDefeated) {\n\t\t\t\t\t\t\t\t\tint j;\n\t\t\t\t\t\t\t\t\tfor( j=0; j < UNIT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityU(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < INFANTRY_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityI(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < AIRCRAFT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityA(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor( j=0; j < VESSEL_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tucount += hptr->QuantityV(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tint bcount = 0;\n\t\t\t\t\t\t\t\t\tfor( j=0; j < STRUCT_COUNT; j++) {\n\t\t\t\t\t\t\t\t\t\tbcount += hptr->QuantityB(j);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tucount += bcount/2;\t// weight buildings less\n\t\t\t\t\t\t\t\t\tminunits = min(minunits, ucount);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Random_Pick(0, minunits) == minunits) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*\n\t\t\t**\tPossibly force it to be an MCV if there is\n\t\t\t**\tsufficient money and no buildings left.\n\t\t\t*/\n\t\t\tif (\tobject->House->BScan == 0 &&\n\t\t\t\t\tobject->House->Available_Money() > ( (BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost + BuildingTypeClass::As_Reference(STRUCT_POWER).Cost) * object->House->CostBias) &&\n\t\t\t\t\tSession.Options.Bases &&\n\t\t\t\t\t!(object->House->UScan & UNITF_MCV)) {\n\t\t\t\tpowerup = CRATE_UNIT;\n\t\t\t\tforce_mcv = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the powerup is money but there is insufficient money to build a refinery but there is a construction\n\t\t\t**\tyard available, then force the money to be enough to rebuild the refinery.\n\t\t\t*/\n\t\t\tif (powerup == CRATE_MONEY && (object->House->BScan & (STRUCTF_CONST|STRUCTF_REFINERY)) == STRUCTF_CONST &&\n\t\t\t\t\t\tobject->House->Available_Money() < BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost * object->House->CostBias) {\n\n\t\t\t\tforce_money = BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost * object->House->CostBias;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial override for water crates so that illegal goodies items\n\t\t\t**\twon't appear.\n\t\t\t*/\n\t\t\tif (Overlay == OVERLAY_WATER_CRATE) {\n\t\t\t\tswitch (powerup) {\n\t\t\t\t\tcase CRATE_UNIT:\n\t\t\t\t\tcase CRATE_SQUAD:\n\t\t\t\t\t\tpowerup = CRATE_MONEY;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Keep track of the number of each type of crate found\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tobject->House->TotalCrates->Increment_Unit_Total(powerup);\n\t\t}\n\n\t\t/*\n\t\t**\tRemove the crate from the map.\n\t\t*/\n\t\tMap.Remove_Crate(Cell_Number());\n//\t\tMap[Cell_Number()].Overlay = OVERLAY_NONE;\n\n\t\tif (Session.Type != GAME_NORMAL && Rule.IsMPCrates) {\n\t\t\tMap.Place_Random_Crate();\n\t\t}\n\n\t\t/*\n\t\t**\tGenerate any corresponding animation associated with this crate powerup.\n\t\t*/\n\t\tif (CrateAnims[powerup] != ANIM_NONE) {\n\t\t\tnew AnimClass(CrateAnims[powerup], Cell_Coord());\n\t\t}\n\n\t\t/*\n\t\t**\tCreate the effect requested.\n\t\t*/\n\t\tbool tospeak = false;\n\t\tswitch (powerup) {\n\t\t\tcase CRATE_TIMEQUAKE:\n\t\t\t\tTimeQuake = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tGive the player money.\n\t\t\t*/\n\t\t\tcase CRATE_MONEY:\ncrate_money:\n\t\t\t\tif (force_money > 0) {\n\t\t\t\t\tobject->House->Refund_Money(force_money);\n\t\t\t\t} else {\n\t\t\t\t\tobject->House->Refund_Money(Random_Pick(CrateData[powerup], CrateData[powerup]+900));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tShroud the world in blackness.\n\t\t\t*/\n\t\t\tcase CRATE_DARKNESS:\n\t\t\t\t/*\n\t\t\t\t** Updated for client/server multiplayer. ST - 8/12/2019 11:38AM\n\t\t\t\t*/\n\t\t\t\tif (object->House->IsHuman) {\n\t\t\t\t\tMap.Shroud_The_Map(object->House);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tReveal the entire map.\n\t\t\t*/\n\t\t\tcase CRATE_REVEAL:\n\t\t\t\t/*\n\t\t\t\t** Updated for client/server multiplayer. ST - 8/12/2019 11:38AM\n\t\t\t\t*/\n\t\t\t\tobject->House->IsVisionary = true;\n\t\t\t\tif (object->House->IsHuman) {\n\t\t\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\tMap.Map_Cell(cell, object->House);\n\t\t\t\t\t}\n\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTry to create a unit where the crate was.\n\t\t\t*/\n\t\t\tcase CRATE_UNIT: {\n\t\t\t\tUnitTypeClass const * utp = NULL;\n\n\t\t\t\t/*\n\t\t\t\t**\tGive the player an MCV if he has no base left but does have more than enough\n\t\t\t\t**\tmoney to rebuild a new base. Of course, if he already has an MCV, then don't\n\t\t\t\t**\tgive him another one.\n\t\t\t\t*/\n\t\t\t\tif (force_mcv) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(UNIT_MCV);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the player has a base and a refinery, but no harvester, then give him\n\t\t\t\t**\ta free one.\n\t\t\t\t*/\n\t\t\t\tif (utp == NULL && (object->House->BScan & STRUCTF_REFINERY) && !(object->House->UScan & UNITF_HARVESTER)) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(UNIT_HARVESTER);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck for special unit type override value.\n\t\t\t\t*/\n\t\t\t\tif (Rule.UnitCrateType != UNIT_NONE) {\n\t\t\t\t\tutp = &UnitTypeClass::As_Reference(Rule.UnitCrateType);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no unit type has been determined, then pick one at random.\n\t\t\t\t*/\n\t\t\t\twhile (utp == NULL) {\n#ifdef FIXIT_ANTS\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_RA_COUNT-1 -3));\n#else\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_COUNT-1 -3));\n#endif\n#else\n\t\t\t\t\tUnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_COUNT-1));\n#endif\n\t\t\t\t\tif (utype != UNIT_MCV || Session.Options.Bases) {\n\t\t\t\t\t\tutp = &UnitTypeClass::As_Reference(utype);\n\t\t\t\t\t\tif (utp->IsCrateGoodie && (utp->Ownable & (1 << HouseClass::As_Pointer(object->Owner())->ActLike))) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tutp = NULL;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (utp != NULL) {\n\t\t\t\t\tUnitClass * goodie_unit = (UnitClass *)utp->Create_One_Of(object->House);\n\t\t\t\t\tif (goodie_unit != NULL) {\n\t\t\t\t\t\tif (goodie_unit->Unlimbo(Cell_Coord())) {\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tTry to place the object into a nearby cell if something is preventing\n\t\t\t\t\t\t**\tplacement at the crate location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL cell = Map.Nearby_Location(Cell_Number(), goodie_unit->Class->Speed);\n\t\t\t\t\t\tif (goodie_unit->Unlimbo(::Cell_Coord(cell))) {\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete goodie_unit;\n\t\t\t\t\t\tgoto crate_money;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCreate a squad of miscellaneous composition.\n\t\t\t*/\n\t\t\tcase CRATE_SQUAD:\n\t\t\t\tfor (int index = 0; index < 5; index++) {\n\t\t\t\t\tstatic InfantryType _inf[] = {\n\t\t\t\t\t\tINFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,\n\t\t\t\t\t\tINFANTRY_E2,\n\t\t\t\t\t\tINFANTRY_E3,\n\t\t\t\t\t\tINFANTRY_RENOVATOR\n\t\t\t\t\t};\n\t\t\t\t\tif (!InfantryTypeClass::As_Reference(_inf[Random_Pick(0, ARRAY_SIZE(_inf)-1)]).Create_And_Place(Cell_Number(), object->Owner())) {\n\t\t\t\t\t\tif (index == 0) {\n\t\t\t\t\t\t\tgoto crate_money;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(false);\n\n\t\t\t/*\n\t\t\t**\tA one para-bomb mission.\n\t\t\t*/\n\t\t\tcase CRATE_PARA_BOMB:\n\t\t\t\tif (object->House->SuperWeapon[SPC_PARA_BOMB].Enable(true)) {\n\t\t\t\t\t// Changes for client/server multiplayer. ST - 8/2/2019 2:56PM\n\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\tif (object->House->IsHuman) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_BOMB, object->House);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_BOMB);\n\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA one time sonar pulse\n\t\t\t*/\n\t\t\tcase CRATE_SONAR:\n\t\t\t\tif (object->House->SuperWeapon[SPC_SONAR_PULSE].Enable(true)) {\n\t\t\t\t\t// Changes for client/server multiplayer. ST - 8/2/2019 2:56PM\n\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\tif (object->House->IsHuman) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_SONAR_PULSE, object->House);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SONAR_PULSE);\n\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA group of explosions are triggered around the crate.\n\t\t\t*/\n\t\t\tcase CRATE_EXPLOSION:\n\t\t\t\tif (object != NULL) {\n\t\t\t\t\tint d = CrateData[powerup];\n\t\t\t\t\tobject->Take_Damage(d, 0, WARHEAD_HE, 0, true);\n\t\t\t\t}\n\t\t\t\tfor (int index = 0; index < 5; index++) {\n\t\t\t\t\tCOORDINATE frag_coord = Coord_Scatter(Cell_Coord(), Random_Pick(0, 0x0200));\n\t\t\t\t\tnew AnimClass(ANIM_FBALL1, frag_coord);\n\t\t\t\t\tdamage = CrateData[powerup];\n\t\t\t\t\tExplosion_Damage(frag_coord, damage, NULL, WARHEAD_HE);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tA napalm blast is triggered.\n\t\t\t*/\n\t\t\tcase CRATE_NAPALM:\n\t\t\t\tcoord = Coord_Mid(Cell_Coord(), object->Center_Coord());\n\t\t\t\tnew AnimClass(ANIM_NAPALM3, coord);\n\t\t\t\tif (object != NULL) {\n\t\t\t\t\tint d = CrateData[powerup];\n\t\t\t\t\tobject->Take_Damage(d, 0, WARHEAD_FIRE, 0, true);\n\t\t\t\t}\n\t\t\t\tdamage = CrateData[powerup];\n\t\t\t\tExplosion_Damage(coord, damage, NULL, WARHEAD_FIRE);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll objects within a certain range will gain the ability to cloak.\n\t\t\t*/\n\t\t\tcase CRATE_CLOAK:\n\t\t\t\tfor (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius) {\n\t\t\t\t\t\t((TechnoClass *)obj)->IsCloakable = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAll of the player's objects heal up.\n\t\t\t*/\n\t\t\tcase CRATE_HEAL_BASE:\n\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\tSound_Effect(VOC_HEAL, object->Center_Coord());\n\t\t\t\t}\n\t\t\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\t\t\tObjectClass * obj = Logic[index];\n\n\t\t\t\t\tif (obj && object->Is_Techno() && object->House->Class->House == obj->Owner()) {\n\t\t\t\t\t\tobj->Strength = obj->Class_Of().MaxStrength;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\tcase CRATE_ICBM:\n\t\t\t\tif (object->House->SuperWeapon[SPC_NUCLEAR_BOMB].Enable(true)) {\n\t\t\t\t\t// Changes for client/server multiplayer. ST - 8/2/2019 2:56PM\n\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\tif (object->House->IsHuman) {\n\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB, object->House);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (object->IsOwnedByPlayer) {\n\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);\n\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_ARMOR:\n\t\t\t\tfor (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj != NULL && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((TechnoClass *)obj)->ArmorBias == 1) {\n\t\t\t\t\t\tfixed val = ((TechnoClass *)obj)->ArmorBias * Inverse(fixed(CrateData[powerup], 256));\n\t\t\t\t\t\t((TechnoClass *)obj)->ArmorBias = val;\n\t\t\t\t\t\tif (obj->Owner() == PlayerPtr->Class->House) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_ARMOR);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_SPEED:\n\t\t\t\tfor (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Foot() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((FootClass *)obj)->SpeedBias == 1 && obj->What_Am_I() != RTTI_AIRCRAFT) {\n\t\t\t\t\t\tFootClass * foot = (FootClass *)obj;\n\n\t\t\t\t\t\tfixed val = foot->SpeedBias * fixed(CrateData[powerup], 256);\n\t\t\t\t\t\tfoot->SpeedBias = val;\n\t\t\t\t\t\tif (foot->IsOwnedByPlayer) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_SPEED);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_FIREPOWER:\n\t\t\t\tfor (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius && ((TechnoClass *)obj)->FirepowerBias == 1) {\n\n\t\t\t\t\t\tfixed val = ((TechnoClass *)obj)->FirepowerBias * fixed(CrateData[powerup], 256);\n\t\t\t\t\t\t((TechnoClass *)obj)->FirepowerBias = val;\n\t\t\t\t\t\tif (obj->Owner() == PlayerPtr->Class->House) tospeak = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tospeak) Speak(VOX_UPGRADE_FIREPOWER);\n\t\t\t\tbreak;\n\n\t\t\tcase CRATE_INVULN:\n\t\t\t\tfor (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {\n\t\t\t\t\tObjectClass * obj = DisplayClass::Layer[LAYER_GROUND][index];\n\n\t\t\t\t\tif (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < Rule.CrateRadius) {\n\t\t\t\t\t\t((TechnoClass *)obj)->IronCurtainCountDown = (TICKS_PER_MINUTE * fixed(CrateData[powerup], 256));\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** A chronal vortex appears targetted at the triggering object.\n\t\t\t*/\n\t\t\tcase CRATE_VORTEX:\n\t\t\t\tif ( !ChronalVortex.Is_Active()) {\n\t\t\t\t\tChronalVortex.Appear ( Cell_Coord() );\n\t\t\t\t\tChronalVortex.Set_Target ( (ObjectClass*) object );\n\t\t\t\t\tSound_Effect(VOC_TESLA_ZAP, object->Center_Coord());\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Flag_Place -- Places a house flag down on the cell.                              *\n *                                                                                             *\n *    This routine will place the house flag at this cell location.                            *\n *                                                                                             *\n * INPUT:   house -- The house that is having its flag placed here.                            *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully placed here?                                             *\n *                                                                                             *\n * WARNINGS:   Failure to place means that the cell is impassable for some reason.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Flag_Place(HousesType house)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (!IsFlagged && Is_Clear_To_Move(SPEED_TRACK, false, false)) {\n\t\tIsFlagged = true;\n\t\tOwner = house;\n\t\tFlag_Update();\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Flag_Remove -- Removes the house flag from the cell.                             *\n *                                                                                             *\n *    This routine will free the cell of any house flag that may be located there.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was there a flag here that was removed?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Flag_Remove(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tif (IsFlagged) {\n\t\tIsFlagged = false;\n\t\tOwner = HOUSE_NONE;\n\t\tFlag_Update();\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid CellClass::Flag_Update(void)\n{\n\tif (IsFlagged && !CTFFlag) {\n\t\tFlag_Create();\n\t} else if (!IsFlagged && CTFFlag) {\n\t\tFlag_Destroy();\n\t}\n}\n\n\nvoid CellClass::Flag_Create(void)\n{\n\tif (!CTFFlag) {\n\t\tCTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord());\n\t\tif (CTFFlag == NULL) {\n\t\t\tfor (int i = 0; i < Anims.Count(); ++i) {\n\t\t\t\tAnimClass* anim = Anims.Ptr(i);\n\t\t\t\tif (*anim != ANIM_FLAG) {\n\t\t\t\t\tdelete anim;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord());\n\t\t}\n\t\tassert(CTFFlag != NULL);\n\t\tCTFFlag->Set_Owner(Owner);\n\t}\n}\n\n\nvoid CellClass::Flag_Destroy(void)\n{\n\tdelete CTFFlag;\n\tCTFFlag = NULL;\n}\n\n\n/***********************************************************************************************\n * CellClass::Shimmer -- Causes all objects in the cell to shimmer.                            *\n *                                                                                             *\n *    This routine is called when some event would cause a momentary disruption in the         *\n *    cloaking device. All objects that are cloaked in the cell will have their cloaking       *\n *    device shimmer.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CellClass::Shimmer(void)\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\tObjectClass * object = Cell_Occupier();\n\n\twhile (object) {\n\t\tobject->Do_Shimmer();\n\t\tobject = object->Next;\n\t}\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Clear_To_Move -- Determines if the cell is generally clear for travel         *\n *                                                                                             *\n *    This routine is called when determining general passability for purposes of zone         *\n *    calculation. Only blockages that cannot be circumvented are considered to make a cell    *\n *    impassable. All other obstructions can either be destroyed or are temporary.             *\n *                                                                                             *\n * INPUT:   loco     -- The locomotion type to use when determining passablility.              *\n *                                                                                             *\n *          ignoreinfantry -- Should infantry in the cell be ignored for movement purposes?    *\n *                                                                                             *\n *          ignorevehicles -- If vehicles should be ignored, then this flag will be true.      *\n *                                                                                             *\n *          zone     -- If specified, the zone must match this value or else movement is       *\n *                      presumed disallowed.                                                   *\n *                                                                                             *\n *          check    -- This specifies the zone type that this check applies to.               *\n *                                                                                             *\n * OUTPUT:  Is the cell generally passable to ground targeting?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1995 JLB : Created.                                                                 *\n *   06/25/1996 JLB : Uses tracked vehicles as a basis for zone check.                         *\n *   10/05/1996 JLB : Allows checking for crushable blockages.                                 *\n *=============================================================================================*/\nbool CellClass::Is_Clear_To_Move(SpeedType loco, bool ignoreinfantry, bool ignorevehicles, int zone, MZoneType check) const\n{\n\tassert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);\n\n\t/*\n\t**\tFlying objects always consider every cell passable since they can fly over everything.\n\t*/\n\tif (loco == SPEED_WINGED) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tIf a zone was specified, then see if the cell is in a legal\n\t**\tzone to allow movement.\n\t*/\n\tif (zone != -1) {\n\t\tif (zone != Zones[check]) {\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck the occupy bits for passable legality. If ignore infantry is true, then\n\t**\tdon't consider infnatry.\n\t*/\n\tint composite = Flag.Composite;\n\tif (ignoreinfantry) {\n\t\tcomposite &= 0xE0;\t\t\t// Drop the infantry occupation bits.\n\t}\n\tif (ignorevehicles) {\n\t\tcomposite &= 0x5F;\t\t\t// Drop the vehicle/building bit.\n\t}\n\tif (composite != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tFetch the land type of the cell -- to be modified and used later.\n\t*/\n\tLandType land = Land_Type();\n\n\t/*\n\t**\tWalls are always considered to block the terrain for general passability\n\t**\tpurposes unless this is a wall crushing check or if the checking object\n\t**\tcan destroy walls.\n\t*/\n\tOverlayTypeClass const * overlay = NULL;\n\tif (Overlay != OVERLAY_NONE) {\n\t \toverlay = &OverlayTypeClass::As_Reference(Overlay);\n\t}\n\tif (overlay != NULL && overlay->IsWall) {\n\t\tif (check != MZONE_DESTROYER && (check != MZONE_CRUSHER || !overlay->IsCrushable)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tCrushing objects consider crushable walls as clear rather than the\n\t\t**\ttypical LAND_WALL setting.\n\t\t*/\n\t\tland = LAND_CLEAR;\n\t}\n\n\t/*\n\t**\tSee if the ground type is impassable to this locomotion type and if\n\t**\tso, return the error condition.\n\t*/\n\tif (::Ground[land].Cost[loco] == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tAll checks passed, so this cell must be passable.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Is_Bridge_Here -- Checks to see if this is a bridge occupied cell.               *\n *                                                                                             *\n *    This routine will examine this cell and if there is a bridge here, it will return        *\n *    true.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is there a bridge located in this cell?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Is_Bridge_Here(void) const\n{\n\tswitch (TType) {\n\t\tcase TEMPLATE_BRIDGE1:\n\t\tcase TEMPLATE_BRIDGE1H:\n\t\tcase TEMPLATE_BRIDGE1D:\n\t\tcase TEMPLATE_BRIDGE2:\n\t\tcase TEMPLATE_BRIDGE2H:\n\t\tcase TEMPLATE_BRIDGE2D:\n\t\tcase TEMPLATE_BRIDGE_1A:\n\t\tcase TEMPLATE_BRIDGE_1B:\n\t\tcase TEMPLATE_BRIDGE_2A:\n\t\tcase TEMPLATE_BRIDGE_2B:\n\t\tcase TEMPLATE_BRIDGE_3A:\n\t\tcase TEMPLATE_BRIDGE_3B:\n\t\tcase TEMPLATE_BRIDGE_3C:\n\t\tcase TEMPLATE_BRIDGE_3D:\n\t\tcase TEMPLATE_BRIDGE_3E:\n\t\tcase TEMPLATE_BRIDGE_3F:\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Grow -- Determines if Tiberium can grow in this cell.               *\n *                                                                                             *\n *    This checks the cell to see if Tiberium can grow at least one level in it. Tiberium can  *\n *    grow only if there is Tiberium already present. It can only grow to a certain level      *\n *    and then all further growth is suspended.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium grow in this cell?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Grow(void) const\n{\n\tif (!Rule.IsTGrowth) return(false);\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif(!Session.Options.Tiberium) return(false);\n\t}\n\n\tif (Land_Type() != LAND_TIBERIUM) return(false);\n\n\tif (OverlayData >= 11) return(false);\n\n\tif (Overlay != OVERLAY_GOLD1 && Overlay != OVERLAY_GOLD2 && Overlay != OVERLAY_GOLD3 && Overlay != OVERLAY_GOLD4) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Spread -- Determines if Tiberium can spread from this cell.         *\n *                                                                                             *\n *    This routine will examine the cell and determine if there is sufficient Tiberium         *\n *    present that Tiberium spores will spread to adjacent cells. If the Tiberium level is     *\n *    too low, spreading will not occur.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium spread from this cell into adjacent cells?                      *\n *                                                                                             *\n * WARNINGS:   This routine does not check to see if, in fact, there are any adjacent cells    *\n *             available to spread to.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Spread(void) const\n{\n\tif (!Rule.IsTSpread) return(false);\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif(!Session.Options.Tiberium) return(false);\n\t}\n\n\tif (Land_Type() != LAND_TIBERIUM) return(false);\n\n\tif (OverlayData <= 6) return(false);\n\n\tif (Overlay != OVERLAY_GOLD1 && Overlay != OVERLAY_GOLD2 && Overlay != OVERLAY_GOLD3 && Overlay != OVERLAY_GOLD4) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Grow_Tiberium -- Grows the tiberium in the cell.                                 *\n *                                                                                             *\n *    This routine will cause the tiberium to grow in the cell.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did Tiberium grow in the cell?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Grow_Tiberium(void)\n{\n\tif (Can_Tiberium_Grow()) {\n\t\tOverlayData++;\n\t\tRedraw_Objects();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Spread_Tiberium -- Spread Tiberium from this cell to an adjacent cell.           *\n *                                                                                             *\n *    This routine will cause the Tiberium to spread from this cell into an adjacent (random)  *\n *    cell.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did the Tiberium spread?                                                     *\n *                                                                                             *\n * WARNINGS:   If there are no adjacent cells that the tiberium can spread to, then this       *\n *             routine will fail.                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Spread_Tiberium(bool forced)\n{\n\tif (!forced) {\n\t\tif (!Can_Tiberium_Spread()) return(false);\n\t}\n\tFacingType offset = Random_Pick(FACING_N, FACING_NW);\n\tfor (FacingType index = FACING_N; index < FACING_COUNT; index++) {\n\t\tCellClass * newcell = Adjacent_Cell(index+offset);\n\n\t\tif (newcell != NULL && newcell->Can_Tiberium_Germinate()) {\n\t\t\tnew OverlayClass(Random_Pick(OVERLAY_GOLD1, OVERLAY_GOLD4), newcell->Cell_Number());\n\t\t\tnewcell->OverlayData = 0;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CellClass::Can_Tiberium_Germinate -- Determines if Tiberium can begin growth in the cell.   *\n *                                                                                             *\n *    This routine will examine the cell and determine if Tiberium can start growth in it.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can Tiberium grow in this cell?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Can_Tiberium_Germinate(void) const\n{\n\tif (!Map.In_Radar(Cell_Number())) return(false);\n\n\tif (Is_Bridge_Here()) return(false);\n\n\t/*\n\t**\tDon't allow Tiberium to grow on a cell with a building unless that building is\n\t**\tinvisible. In such a case, the Tiberium must grow or else the location of the\n\t**\tbuilding will be revealed.\n\t*/\n\tBuildingClass const * building = Cell_Building();\n\tif (building != NULL && !building->Class->IsInvisible) return(false);\n\n\tif (!Ground[Land_Type()].Build) return(false);\n\n\tif (Overlay != OVERLAY_NONE) return(false);\n\n\treturn(true);\n}\n\n\n\n\n\n\n\n\n\n\n/*\n**  Additions to CellClass to track visibility per-player. ST - 8/2/2019 2:59PM\n** \n** \n** \n** \n** \n*/\n\n/***********************************************************************************************\n * CellClass::Set_Mapped -- Set the cell mapped for the given player                           *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:09PM - ST                                                                      *\n *=============================================================================================*/\nvoid CellClass::Set_Mapped(HousesType house, bool set)\n{\n\tint shift = (int) house;\n\tif (set) {\n\t\tIsMappedByPlayerMask |= (1 << shift);\n\t} else {\n\t\tIsMappedByPlayerMask &= ~(1 << shift);\n\t}\t\n}\t\t\t  \n\n\n/***********************************************************************************************\n * CellClass::Set_Mapped -- Set the cell mapped for the given player                           *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:09PM - ST                                                                      *\n *=============================================================================================*/\nvoid CellClass::Set_Mapped(HouseClass *player, bool set)\n{\n\tif (player && player->Class) {\n\t\tSet_Mapped(player->Class->House, set);\n\t\tif (Session.Type == GAME_NORMAL && player->IsHuman) {\n\t\t\tIsMapped = set;\t\t\t// Also set the regular flag in single player\n\t\t}\n\t}\n}\t\t\t  \n\n/***********************************************************************************************\n * CellClass::Is_Mapped -- Is the cell mapped for the given player                             *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:13PM - ST                                                                      *\n *=============================================================================================*/\nbool CellClass::Is_Mapped(HousesType house) const\n{\n\tint shift = (int) house;\n\treturn (IsMappedByPlayerMask & (1 << shift)) ? true : false;\n}\t\t\t  \n\n/***********************************************************************************************\n * CellClass::Is_Mapped -- Is the cell mapped for the given player                             *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:13PM - ST                                                                      *\n *=============================================================================================*/\nbool CellClass::Is_Mapped(HouseClass *player) const\n{\n\tif (player && player->Class) {\n\t\treturn Is_Mapped(player->Class->House);\n\t}\n\treturn false;\n}\t\t\t  \n\n/***********************************************************************************************\n * CellClass::Set_Visible -- Set the cell visible for the given player                         *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:16PM - ST                                                                      *\n *=============================================================================================*/\nvoid CellClass::Set_Visible(HousesType house, bool set)\n{\n\tint shift = (int) house;\n\tif (set) {\n\t\tIsVisibleByPlayerMask |= (1 << shift);\n\t} else {\n\t\tIsVisibleByPlayerMask &= ~(1 << shift);\n\t}\t\n}\t\t\t  \n\n\n/***********************************************************************************************\n * CellClass::Set_Visible -- Set the cell visible for the given player                         *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:16PM - ST                                                                      *\n *=============================================================================================*/\nvoid CellClass::Set_Visible(HouseClass *player, bool set)\n{\n\tif (player && player->Class) {\n\t\tSet_Visible(player->Class->House, set);\n\t\tif (Session.Type == GAME_NORMAL && player->IsHuman) {\n\t\t\tIsVisible = set;\t\t\t// Also set the regular flag in single player. This is needed for rendering\n\t\t}\n\t}\n}\t\t\t  \n\n/***********************************************************************************************\n * CellClass::Is_Visible -- Is the cell visible for the given player                           *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:16PM - ST                                                                      *\n *=============================================================================================*/\nbool CellClass::Is_Visible(HousesType house) const\n{\n\tint shift = (int) house;\n\treturn (IsVisibleByPlayerMask & (1 << shift)) ? true : false;\n}\t\t\t  \n\n/***********************************************************************************************\n * CellClass::Is_Visible -- Is the cell visible for the given player                           *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   3/5/2019 3:16PM - ST                                                                      *\n *=============================================================================================*/\nbool CellClass::Is_Visible(HouseClass *player) const\n{\n\tif (player && player->Class) {\n\t\treturn Is_Visible(player->Class->House);\n\t}\n\treturn false;\n}\n\nbool CellClass::Is_Jamming(HousesType house) const\n{\n\tint shift = (int)house;\n\treturn (Jammed & (1 << shift)) ? true : false;\n}\n\nbool CellClass::Is_Jamming(HouseClass *player) const\n{\n\tif (player && player->Class) {\n\t\treturn Is_Jamming(player->Class->House);\n\t}\n\treturn false;\n}\n\nvoid CellClass::Override_Land_Type(LandType type)\n{\n\tOverrideLand = type;\n}"
  },
  {
    "path": "REDALERT/CELL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CELL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CELL.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CELL_H\n#define CELL_H\n\n#include\t\"building.h\"\n#include\t\"unit.h\"\n#include\t\"template.h\"\n\n\n/****************************************************************************\n**\tEach cell on the map is controlled by the following structure.\n*/\nclass CellClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the ID number of this cell. By placing the ID number here, it doesn't have\n\t\t**\tbe calculated. Calculating this number requires a divide and would occur about\n\t\t**\t5.72031 bijillion times per second.\n\t\t*/\n\t\tshort ID;\n\n\t\t/*\n\t\t**\tDoes this cell need to be updated on the radar map?  If something changes in the cell\n\t\t**\tthat might change the radar map imagery, then this flag will be set. It gets cleared\n\t\t**\twhen the cell graphic is updated to the radar map.\n\t\t*/\n\t\tunsigned IsPlot:1;\n\n\t\t/*\n\t\t**\tDoes this cell contain the special placement cursor graphic?  This graphic is\n\t\t**\tpresent when selecting a site for building placement.\n\t\t*/\n\t\tunsigned IsCursorHere:1;\n\n\t\t/*\n\t\t**\tA mapped cell has some portion of it visible. Maybe it has a shroud piece\n\t\t**\tover it and maybe not.\n\t\t*/\n\t\tunsigned IsMapped:1;\n\n\t\t/*\n\t\t**\tA visible cell means that it is completely visible with no shroud over\n\t\t**\tit at all.\n\t\t*/\n\t\tunsigned IsVisible:1;\n\n\t\t/*\n\t\t** Every cell can be assigned a waypoint.  A waypoint can only be assigned\n\t\t** to one cell, and vice-versa.  This bit simply indicates whether this\n\t\t** cell is assigned a waypoint or not.\n\t\t*/\n\t\tunsigned IsWaypoint:1;\n\n\t\t/*\n\t\t** Is this cell currently under the radar map cursor?  If so then it\n\t\t**   needs to be updated whenever the map is updated.\n\t\t*/\n\t\tunsigned IsRadarCursor:1;\n\n\t\t/*\n\t\t**\tIf this cell contains a house flag, then this will be true. The actual house\n\t\t**\tflag it contains is specified by the Owner field.\n\t\t*/\n\t\tunsigned IsFlagged:1;\n\n\t\t/*\n\t\t**\tThis is a working flag used to help keep track of what cells should be\n\t\t**\tshrouded. By using this flag it allows a single pass through the map\n\t\t**\tcells for determining shadow regrowth logic.\n\t\t*/\n\t\tunsigned IsToShroud:1;\n\n\t\t/*\n\t\t**\tThis records the movement zone for this map. Movement zones share the\n\t\t**\tsame number if they are contiguous (terrain consideration only). There\n\t\t**\tare basically two kinds of zones. The difference being determined by\n\t\t**\twalls that can be crushed by movement. A vehicle that can crush walls\n\t\t**\twill only consider the CrushZone. All other terrestrial travellers will\n\t\t**\tuse the normal Zone.\n\t\t*/\n\t\tunsigned char Zones[MZONE_COUNT];\n\n\t\t/*\n\t\t** This field controls whether an area is being jammed by a gap\n\t\t** generator.\n\t\t*/\n\t\tunsigned short Jammed;\n\n\t\t/*\n\t\t**\tThis is the trigger ID for any trigger that might be attached to\n\t\t**\tthis cell.\n\t\t*/\n\t\tCCPtr<TriggerClass> Trigger;\n\n\t\t/*\n\t\t**\tThis contains the icon number and set to use for the base\n\t\t**\tof the terrain. All rendering on an icon occurs AFTER the icon\n\t\t**\tspecified by this element is rendered. It is the lowest of the low.\n\t\t*/\n\t\tTemplateType TType;\n\t\tunsigned char TIcon;\n\n\t\t/*\n\t\t**\tThe second layer of 'terrain' icons is represented by a simple\n\t\t**\ttype number and a value byte. This is sufficient for handling\n\t\t**\tconcrete and walls.\n\t\t*/\n\t\tOverlayType Overlay;\n\t\tunsigned char OverlayData;\n\n\t\t/*\n\t\t**\tThis is used to specify any special 'stain' overlay icon. This\n\t\t**\ttypically includes infantry bodies or other temporary marks.\n\t\t*/\n\t\tSmudgeType Smudge;\n\t\tunsigned char SmudgeData;\n\n\t\t/*\n\t\t**\tSmudges and walls need to record ownership values. For walls, this\n\t\t**\tallows adjacent building placement logic to work. For smudges, it\n\t\t**\tallows building over smudges that are no longer attached to buildings\n\t\t**\tin addition to fixing the adjacent placement logic.\n\t\t*/\n\t\tHousesType Owner;\n\n\t\t/*\n\t\t** This flag tells you what type of infantry currently occupy the\n\t\t** cell or are moving into it.\n\t\t*/\n\t\tHousesType InfType;\n\n\t\t/*\n\t\t**\tThese point to the object(s) that are located in this cell or overlap\n\t\t**\tthis cell.\n\t\t*/\n\tprivate:\n\t\tObjectClass * OccupierPtr;\n\n\tpublic:\n#ifdef SORTDRAW\n\t\tObjectClass * Overlapper[10];\n#else\n\t\tObjectClass * Overlapper[6];\n#endif\n\n\n\t\t/*\n\t\t**\tPer-player view of whether a cell is mapped. One bit for each house type. ST - 8/2/2019 3:00PM\n\t\t*/\n\t\tunsigned int IsMappedByPlayerMask;\n\n\t\t/*\n\t\t**\tPer-player view of whether a cell is visible. One bit for each house type. ST - 8/2/2019 3:00PM\n\t\t*/\n\t\tunsigned int IsVisibleByPlayerMask;\n\n\n\t\t/*\n\t\t**\tThis array of bit flags is used to indicate which sub positions\n\t\t**\twithin the cell are either occupied or are soon going to be\n\t\t**\toccupied. For vehicles, the cells that the vehicle is passing over\n\t\t**\twill be flagged with the vehicle bit. For infantry, the the sub\n\t\t**\tposition the infantry is stopped at or headed toward will be marked.\n\t\t**\tThe sub positions it passes over will NOT be marked.\n\t\t*/\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tunsigned Center:1;\n\t\t\t\tunsigned NW:1;\n\t\t\t\tunsigned NE:1;\n\t\t\t\tunsigned SW:1;\n\t\t\t\tunsigned SE:1;\n\t\t\t\tunsigned Vehicle:1;\t\t// Reserved for vehicle occupation.\n\t\t\t\tunsigned Monolith:1;\t\t// Some immovable blockage is in cell.\n\t\t\t\tunsigned Building:1;\t\t// A building of some time (usually blocks movement).\n\t\t\t} Occupy;\n\t\t\tunsigned char Composite;\n\t\t} Flag;\n\n\t\t//----------------------------------------------------------------\n\t\tCellClass(void);\n\t\tCellClass(NoInitClass const & x) : Trigger(x) {}\n\t\t~CellClass(void) {OccupierPtr=0;}\n\n\t\tint operator == (CellClass const & cell) const {return &cell == this;}\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tbool Can_Tiberium_Germinate(void) const;\n\t\tbool Can_Tiberium_Grow(void) const;\n\t\tbool Can_Tiberium_Spread(void) const;\n\t\tbool Is_Bridge_Here(void) const;\n\t\tRTTIType What_Am_I(void) const {return(RTTI_CELL);}\n\t\tBuildingClass * Cell_Building(void) const;\n\t\tCELL Cell_Number(void) const {return(ID);}\n\t\tCOORDINATE Cell_Coord(void) const;\n\t\tCOORDINATE Closest_Free_Spot(COORDINATE coord, bool any=false) const;\n\t\tCOORDINATE Free_Spot(void) const {return Closest_Free_Spot(Cell_Coord());}\n\t\tCellClass * Adjacent_Cell(FacingType face) {return (CellClass *)((*((CellClass const *)this)).Adjacent_Cell(face));}\n\t\tCellClass const * Adjacent_Cell(FacingType face) const;\n\t\tInfantryClass * Cell_Infantry(void) const;\n\t\tLandType Land_Type(void) const {return((OverrideLand != LAND_NONE) ? OverrideLand : Land);}\n\t\tObjectClass * Cell_Find_Object(RTTIType rtti) const;\n\t\tObjectClass * Cell_Object(int x=0, int y=0) const;\n\t\tObjectClass * Cell_Occupier(void) const {return(OccupierPtr);}\n\t\tObjectClass * Fetch_Occupier(void) const;\n\t\tTARGET As_Target(void) const {return ::As_Target(Cell_Number());}\n\t\tTechnoClass * Cell_Techno(int x=0, int y=0) const;\n\t\tTerrainClass * Cell_Terrain(void) const;\n\t\tUnitClass * Cell_Unit(void) const;\n\t\tVesselClass * Cell_Vessel(void) const;\n\t\tbool Goodie_Check(FootClass * object);\n\t\tbool Is_Clear_To_Build(SpeedType loco = SPEED_TRACK) const;\n\t\tbool Is_Clear_To_Move(SpeedType loco, bool ignoreinfantry, bool ignorevehicles, int zone=-1, MZoneType check=MZONE_NORMAL) const;\n\t\tbool Is_Spot_Free(int spot_index) const {return (! (Flag.Composite & (1 << spot_index)) ); }\n\t\tint Cell_Color(bool override=false) const;\n\t\tint Clear_Icon(void) const;\n\t\tstatic int Spot_Index(COORDINATE coord);\n\t\tbool Get_Template_Info(char *template_name, int &icon, void *&image_data);\n\n\n\t\t/*\n\t\t**\tObject placement and removal flag operations.\n\t\t*/\n\t\tvoid Occupy_Down(ObjectClass * object);\n\t\tvoid Occupy_Up(ObjectClass * object);\n\t\tvoid Overlap_Down(ObjectClass * object);\n\t\tvoid Overlap_Up(ObjectClass * object);\n\t\tbool Flag_Place(HousesType house);\n\t\tbool Flag_Remove(void);\n\t\tvoid Flag_Update(void);\n\t\tvoid Flag_Create(void);\n\t\tvoid Flag_Destroy(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Should_Save(void) const;\n\t\tbool Save(Pipe & file) const;\n\t\tbool Load(Straw & file);\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tDisplay and rendering controls.\n\t\t*/\n\t\tvoid Draw_It(int x, int y, bool objects=false) const;\n\t\tvoid Redraw_Objects(bool forced=false);\n\t\tvoid Shimmer(void);\n\n\t\t/*\n\t\t**\tMaintenance calculation support.\n\t\t*/\n\t\tbool Grow_Tiberium(void);\n\t\tbool Spread_Tiberium(bool forced=false);\n\t\tlong Tiberium_Adjust(bool pregame=false);\n\t\tvoid Wall_Update(void);\n\t\tvoid Concrete_Calc(void);\n\t\tvoid Recalc_Attributes(void);\n\t\tint  Reduce_Tiberium(int levels);\n\t\tint  Reduce_Wall(int damage);\n\t\tvoid Incoming(COORDINATE threat=0, bool forced=false, bool nokidding=false);\n\t\tvoid Adjust_Threat(HousesType house, int threat_value);\n\n\t\tint operator != (CellClass const &) const {return 0;}\n\n\t\t\n\t\t/*\n\t\t**\tAdditional per-player functionality is needed for multiplayer. ST - 8/2/2019 3:01PM \n\t\t*/\n\t\tvoid Set_Mapped(HousesType house, bool set = true);\n\t\tvoid Set_Mapped(HouseClass *player, bool set = true);\n\t\tbool Is_Mapped(HousesType house) const;\n\t\tbool Is_Mapped(HouseClass *player) const;\n\t\tvoid Set_Visible(HousesType house, bool set = true);\n\t\tvoid Set_Visible(HouseClass *player, bool set = true);\n\t\tbool Is_Visible(HousesType house) const;\n\t\tbool Is_Visible(HouseClass *player) const;\n\t\tbool Is_Jamming(HousesType house) const;\n\t\tbool Is_Jamming(HouseClass *player) const;\n\n\t\t/*\n\t\t**\tOverride land type to fix passability issues on some maps\n\t\t*/\n\t\tvoid Override_Land_Type(LandType type);\n\n\tprivate:\n\t\tCellClass (CellClass const &) ;\n\n\t\tLandType Land;\t\t\t// The land type of this cell.\n\n\t\tLandType OverrideLand;\t// The overriden land type of this cell.\n\n\t\t/*\n\t\t**\tPoints to the flag animation on this cell in CTF games.\n\t\t*/\n\t\tAnimClass* CTFFlag;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[28];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/CHECKBOX.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CHECKBOX.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHECKBOX.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/26/95                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CheckBoxClass::Action -- Handles a button action on a checkbox object.                    *\n *   CheckBoxClass::Draw_Me -- Draws the checkbox imagery.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"checkbox.h\"\n\n\n/***********************************************************************************************\n * CheckBoxClass::Draw_Me -- Draws the checkbox imagery.                                       *\n *                                                                                             *\n *    This routine will draw the checkbox either filled or empty as necessary.                 *\n *                                                                                             *\n * INPUT:   forced   -- Should the check box be drawn even if it doesn't think it needs to?    *\n *                                                                                             *\n * OUTPUT:  Was the check box rendered?                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckBoxClass::Draw_Me(int forced)\n{\n\tif (ToggleClass::Draw_Me(forced)) {\n\n\t\tHide_Mouse();\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_DOWN, false);\n\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, DKGREY);\n\t\tif (IsOn) {\n\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, LTGREEN);\n\t\t}\n\t\tShow_Mouse();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CheckBoxClass::Action -- Handles a button action on a checkbox object.                      *\n *                                                                                             *\n *    This routine will detect if the mouse has been clicked on the checkbox object. If so,    *\n *    the check box state will be toggled.                                                     *\n *                                                                                             *\n * INPUT:   flags -- The event flags that resulted in this routine being called.               *\n *                                                                                             *\n *          key   -- The key that resulted in this routine being called.                       *\n *                                                                                             *\n * OUTPUT:  bool; Should normal processing occur?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckBoxClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (IsOn) {\n\t\t\tTurn_Off();\n\t\t} else {\n\t\t\tTurn_On();\n\t\t}\n\t}\n\treturn(ToggleClass::Action(flags, key));\n}\n"
  },
  {
    "path": "REDALERT/CHECKBOX.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CHECKBOX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHECKBOX.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/26/95                                                     *\n *                                                                                             *\n *                  Last Update : May 26, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CHECKBOX_H\n#define CHECKBOX_H\n\n#include\t\"toggle.h\"\n\nclass CheckBoxClass : public ToggleClass\n{\n\tpublic:\n\t\tCheckBoxClass(unsigned id, int x, int y) :\n\t\t\tToggleClass(id, x, y, 7, 7)\n\t\t{};\n\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\tprotected:\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CHEKLIST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CHEKLIST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CHEKLIST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CheckListClass::Action -- action function for this class                                  *\n *   CheckListClass::Add_Item -- Adds specifies text to check list box.                        *\n *   CheckListClass::CheckListClass -- constructor                                             *\n *   CheckListClass::Check_Item -- [un]checks an items                                         *\n *   CheckListClass::Draw_Entry -- draws a list box entry                                      *\n *   CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index.      *\n *   CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified.   *\n *   CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spe*\n *   CheckListClass::~CheckListClass -- Destructor for check list object.                      *\n *   CheckListClass::~CheckListClass -- destructor                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * CheckListClass::CheckListClass -- constructor                           *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         control ID for this list box                            *\n *      x         x-coord                                                  *\n *      y         y-coord                                                  *\n *      w         width                                                    *\n *      h         height                                                   *\n *      flags      mouse event flags                                       *\n *      up         ptr to Up-arrow shape                                   *\n *      down      ptr to Down-arrow shape                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *=========================================================================*/\nCheckListClass::CheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,\n\tvoid const * up, void const * down) :\n\tListClass (id, x, y, w, h, flags, up, down),\n\tIsReadOnly(false)\n{\n}\n\n\n/***********************************************************************************************\n * CheckListClass::~CheckListClass -- Destructor for check list object.                        *\n *                                                                                             *\n *    This destructor will delete all entries attached to it.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCheckListClass::~CheckListClass(void)\n{\n\twhile (CheckListClass::Count()) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(0);\n\n\t\tListClass::Remove_Item(0);\n\t\tdelete obj;\n\t}\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Add_Item -- Adds specifies text to check list box.                          *\n *                                                                                             *\n *    This routine will add the specified text string to the check list.                       *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to add to the list box.                        *\n *                                                                                             *\n * OUTPUT:  Returns the index number where the text object was added.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CheckListClass::Add_Item(char const * text)\n{\n\tCheckObject * obj = new CheckObject(text, false);\n\treturn(ListClass::Add_Item((char const *)obj));\n}\n\n\nchar const * CheckListClass::Current_Item(void) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Current_Item();\n\tif (obj) {\n\t\treturn(obj->Text);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index.        *\n *                                                                                             *\n *    This routine will find the text associated with the entry specified and return a pointer *\n *    to that text.                                                                            *\n *                                                                                             *\n * INPUT:   index -- The entry (index) to fetch a pointer to.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the text pointer associated with the index specified.                 *\n *                                                                                             *\n * WARNINGS:   If the index is out of range, then NULL is returned.                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * CheckListClass::Get_Item(int index) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj) {\n\t\treturn(obj->Text);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified.     *\n *                                                                                             *\n *    This routine will find the entry that matches the text pointer specified and then        *\n *    delete that entry.                                                                       *\n *                                                                                             *\n * INPUT:   text  -- The text pointer to use to find the exact match in the list.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CheckListClass::Remove_Item(char const * text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\t\tif (obj && stricmp(obj->Text, text) == 0) {\n\t\t\tListClass::Remove_Item(index);\n\t\t\tdelete obj;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spec *\n *                                                                                             *\n *    This routine will find the entry that exactly matches the text pointer specified. If     *\n *    found, then that entry will be set as the currently selected index.                      *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to find the match for.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If an exact match to the specified text string could not be found, then the     *\n *             currently selected index is not changed.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CheckListClass::Set_Selected_Index(char const * text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\t\tif (obj && stricmp(obj->Text, text) == 0) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * CheckListClass::Check_Item -- [un]checks an items                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      index         index of item to check or uncheck                    *\n *      checked      0 = uncheck, non-zero = check                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *   02/14/1996 JLB : Revamped.                                            *\n *=========================================================================*/\nvoid CheckListClass::Check_Item(int index, bool checked)\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj && obj->IsChecked != checked) {\n\t\tobj->IsChecked = checked;\n\t\tFlag_To_Redraw();\n\t}\n}\n\n\n/***************************************************************************\n * CheckListClass::Is_Checked -- returns checked state of an item          *\n *                                                                         *\n * INPUT:                                                                  *\n *      index         index of item to query                               *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = item is unchecked, 1 = item is checked                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *   02/14/1996 JLB : Revamped.                                            *\n *=========================================================================*/\nbool CheckListClass::Is_Checked(int index) const\n{\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\tif (obj) {\n\t\treturn(obj->IsChecked);\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * CheckListClass::Action -- action function for this class                *\n *                                                                         *\n * INPUT:                                                                  *\n *      flags      the reason we're being called                           *\n *      key      the KN_number that was pressed                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = event was processed, false = event not processed            *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/16/1995 BR : Created.                                              *\n *=========================================================================*/\nint CheckListClass::Action(unsigned flags, KeyNumType &key)\n{\n\tint rc;\n\n\t/*\n\t** If this is a read-only list, it's a display-only device\n\t*/\n\tif (IsReadOnly) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tInvoke parents Action first, so it can set the SelectedIndex if needed.\n\t*/\n\trc =  ListClass::Action(flags, key);\n\n\t/*\n\t**\tNow, if this event was a left-press, toggle the checked state of the\n\t**\tcurrent item.\n\t*/\n\tif (flags & LEFTPRESS) {\n\t\tCheck_Item(SelectedIndex, !Is_Checked(SelectedIndex));\n\t}\n\n\treturn(rc);\n}\n\n\n/***************************************************************************\n * CheckListClass::Draw_Entry -- draws a list box entry                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex into List of item to draw                      \t\t*\n *\t\tx,y\t\t\tx,y coords to draw at                                  \t*\n *\t\twidth\t\t\tmaximum width allowed for text                       \t\t*\n *\t\tselected\t\ttrue = this item is selected                         \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/14/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CheckListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tif (index >= Count()) return;\n\n\tCheckObject * obj = (CheckObject *)ListClass::Get_Item(index);\n\n\tif (obj) {\n\t\tchar buffer[100] = \"\";\n\n\t\tif (obj->IsChecked) {\n\t\t\tbuffer[0] = CHECK_CHAR;\n\t\t} else {\n\t\t\tbuffer[0] = UNCHECK_CHAR;\n\t\t}\n\t\tbuffer[1] = ' ';\n\t\tsprintf(&buffer[2], obj->Text);\n\n\t\tTextPrintType flags = TextFlags;\n\t\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(buffer, x, y, scheme, TBLACK, flags, width, Tabs);\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/CHEKLIST.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CHEKLIST.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CHEKLIST.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : February 16, 1995                        *\n *                                                                         *\n *                  Last Update : February 16, 1995   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *\tThis class behaves just like the standard list box, except that if the\t*\n * first character of a list entry is a space, clicking on it toggles the\t*\n * space with a check-mark ('\\3').  This makes each entry in the list box\t*\n * \"toggle-able\".\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CHEKLIST_H\n#define CHEKLIST_H\n\n#include \"list.h\"\n\nclass CheckObject\n{\n\tpublic:\n\t\tCheckObject(char const * text = 0, bool checked=false) :\n\t\t\tText(text),\n\t\t\tIsChecked(checked)\n\t\t{};\n\n\t\tchar const * Text;\n\t\tbool IsChecked;\n};\n\n\nclass CheckListClass : public ListClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tConstructor/Destructor\n\t\t*/\n\t\tCheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,\n\t\t\tvoid const * up, void const * down);\n\t\t~CheckListClass(void);\n\n\t\tvirtual int Add_Item(int text) {return ListClass::Add_Item(text);}\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual char const * Current_Item(void) const;\n\t\tvirtual char const * Get_Item(int index) const;\n\t\tvirtual void Remove_Item(char const * text);\n\t\tvirtual void Remove_Item(int text) {ListClass::Remove_Item(text);}\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Set_Selected_Index(int index) {ListClass::Set_Selected_Index(index);};\n\n\t\t/*\n\t\t**\tCheckmark utility functions\n\t\t*/\n\t\tvoid Check_Item(int index, bool checked);\t// sets checked state of item\n\t\tbool Is_Checked(int index) const;\t\t\t\t// gets checked state of item\n\n\t\tvoid Set_Read_Only(int rdonly) {IsReadOnly = rdonly;}\n\n\t\t/*\n\t\t**\tThis defines the ASCII value of the checkmark character & non-checkmark\n\t\t**\tcharacter.\n\t\t*/\n\t\ttypedef enum CheckListClassEnum {\n\t\t\tCHECK_CHAR = '\\3',\n\t\t\tUNCHECK_CHAR = ' '\n\t\t} CheckListClassEnum;\n\n\tprotected:\n\t\tvirtual int Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\tprivate:\n\t\tbool IsReadOnly;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/CLASS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\t\t\t\n"
  },
  {
    "path": "REDALERT/COLRLIST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COLRLIST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COLRLIST.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : April 19, 1995 [BRR]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ColorListClass::Add_Item -- Adds an item to the list                                      *\n *   ColorListClass::ColorListClass -- Class constructor                                       *\n *   ColorListClass::Draw_Entry -- Draws one text line                                         *\n *   ColorListClass::Remove_Item -- Removes an item from the list                              *\n *   ColorListClass::Set_Selected_Style -- tells how to draw selected item                     *\n *   ColorListClass::~ColorListClass -- Class destructor                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * ColorListClass::ColorListClass -- class constructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      id               button ID                                         *\n *      x,y            upper-left corner, in pixels                        *\n *      w,h            width, height, in pixels                            *\n *      list            ptr to array of char strings to list               *\n *    flags          flags for mouse, style of listbox                     *\n *      up,down         pointers to shapes for up/down buttons             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nColorListClass::ColorListClass (int id, int x, int y, int w, int h,\n\tTextPrintType flags, void const * up, void const * down) :\n\tListClass (id, x, y, w, h, flags, up, down),\n\tStyle(SELECT_HIGHLIGHT),\n\tSelectColor(NULL)\n{\n}\n\n\n/***************************************************************************\n * ColorListClass::~ColorListClass -- Class destructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nColorListClass::~ColorListClass(void)\n{\n\tColors.Clear();\n\tSelectColor = 0;\n}\n\n\n/***************************************************************************\n * ColorListClass::Add_Item -- Adds an item to the list                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to add to list                                      \t*\n *\t\tcolor\t\tcolor for item                                          \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tposition of item in the list                                       \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nint ColorListClass::Add_Item(char const * text, RemapControlType * color)\n{\n\tColors.Add(color);\n\treturn(ListClass::Add_Item(text));\n}\n\n\n/***************************************************************************\n * ColorListClass::Add_Item -- Adds an item to the list                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to add to list                                      \t*\n *\t\tcolor\t\tcolor for item                                          \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tposition of item in the list                                       \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nint ColorListClass::Add_Item(int text, RemapControlType * color)\n{\n\tColors.Add(color);\n\treturn(ListClass::Add_Item(text));\n}\n\n\n/***************************************************************************\n * ColorListClass::Remove_Item -- Removes an item from the list            *\n *                                                                         *\n * INPUT:                                                                  *\n *      text      ptr to item to remove                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Remove_Item(char const * text)\n{\n\tint index = List.ID(text);\n\tif (index != -1) {\n\t\tColors.Delete(index);\n\t\tListClass::Remove_Item(text);\n\t}\n}\n\n\n/***************************************************************************\n * ColorListClass::Set_Selected_Style -- tells how to draw selected item   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tstyle\t\tstyle to draw                                           \t\t*\n *\t\tcolor\t\tcolor to draw the special style in; -1 = use item's color\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Set_Selected_Style(SelectStyleType style, RemapControlType * color)\n{\n\tStyle = style;\n\tSelectColor = color;\n}\n\n\n/***************************************************************************\n * ColorListClass::Draw_Entry -- Draws one text line                       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex into List of item to draw                      \t\t*\n *\t\tx,y\t\t\tx,y coords to draw at                                  \t*\n *\t\twidth\t\t\tmaximum width allowed for text                       \t\t*\n *\t\tselected\t\ttrue = this item is selected                         \t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid ColorListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tRemapControlType * color;\n\n\t/*\n\t** Draw a non-selected item in its color\n\t*/\n\tif (!selected) {\n\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\treturn;\n\t}\n\n\t/*\n\t** For selected items, choose the right color & style:\n\t*/\n\tif (SelectColor == NULL) {\n\t\tcolor = Colors[index];\n\t} else {\n\t\tcolor = SelectColor;\n\t}\n\n\tswitch (Style) {\n\t\t/*\n\t\t**\tNONE: Just print the string in its native color\n\t\t*/\n\t\tcase SELECT_NORMAL:\n\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK,\n\t\t\t\tTextFlags, width, Tabs);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHIGHLIGHT: Draw the string in the highlight color (SelectColor must\n\t\t**\tbe set)\n\t\t*/\n\t\tcase SELECT_HIGHLIGHT:\n\t\t\tif (TextFlags & TPF_6PT_GRAD) {\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);\n\t\t\t} else {\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags, width, Tabs);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBOX: Draw a box around the item in the current select color\n\t\t*/\n\t\tcase SELECT_BOX:\n\t\t\tLogicPage->Draw_Rect (x, y, x + width - 2, y + LineHeight - 2, color->Color);\n\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tBAR: draw a color bar under the text\n\t\t*/\n\t\tcase SELECT_BAR:\n\t\t\tif (TextFlags & TPF_6PT_GRAD) {\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, color->Color);\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + width - 2, y + LineHeight - 2, color->Color);\n\t\t\t\tConquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tINVERT: Draw text as the background color on foreground color\n\t\t*/\n\t\tcase SELECT_INVERT:\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, Colors[index]->Color);\n\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "REDALERT/COLRLIST.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COLRLIST.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COLRLIST.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COLORLIST_H\n#define COLORLIST_H\n\n#include \"list.h\"\n\n\n/***************************************************************************\n** This class adds the ability for every list item to have a different color.\n*/\nclass ColorListClass : public ListClass\n{\n\tpublic:\n\t\t/*********************************************************************\n\t\t** These enums are the ways a selected item can be drawn\n\t\t*/\n\t\t//lint -esym(578,SELECT_NONE)\n\t\ttypedef enum SelectEnum {\n\t\t\tSELECT_NORMAL,\t\t\t\t// selected items aren't drawn differently\n\t\t\tSELECT_HIGHLIGHT,\t\t\t// item is highlighted\n\t\t\tSELECT_BOX,\t\t\t\t\t// draw a box around the item\n\t\t\tSELECT_BAR,\t\t\t\t\t// draw a bar behind the item\n\t\t\tSELECT_INVERT\t\t\t\t// draw the string inverted\n\t\t} SelectStyleType;\n\n\t\tColorListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tvirtual ~ColorListClass(void);\n\n\t\tvirtual int  Add_Item(char const * text, RemapControlType * color = NULL);\n\t\tvirtual int  Add_Item(int text, RemapControlType * color = NULL);\n\t\tvirtual void Remove_Item(char const * text);\n\n\t\tvirtual void Set_Selected_Style(SelectStyleType style, RemapControlType * color = NULL);\n\n\t\t/*\n\t\t**\tThis is the list of colors for each item.\n\t\t*/\n\t\tDynamicVectorClass<RemapControlType *> Colors;\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\t\t/*\n\t\t**\tThis tells how to draw the selected item.\n\t\t*/\n\t\tSelectStyleType Style;\n\t\tRemapControlType * SelectColor;\n\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/COMBAT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COMBAT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COMBAT.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 19, 1994                                           *\n *                                                                                             *\n *                  Last Update : July 26, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Combat_Anim -- Determines explosion animation to play.                                    *\n *   Explosion_Damage -- Inflict an explosion damage affect.                                   *\n *   Modify_Damage -- Adjusts damage to reflect the nature of the target.                      *\n *   Wide_Area_Damage -- Apply wide area damage to the map.                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Modify_Damage -- Adjusts damage to reflect the nature of the target.                        *\n *                                                                                             *\n *    This routine is the core of combat tactics. It implements the                            *\n *    affect various armor types have against various weapon types. By                         *\n *    careful exploitation of this table, tactical advantage can be                            *\n *    obtained.                                                                                *\n *                                                                                             *\n * INPUT:   damage   -- The damage points to process.                                          *\n *                                                                                             *\n *          warhead  -- The source of the damage points.                                       *\n *                                                                                             *\n *          armor    -- The type of armor defending against the damage.                        *\n *                                                                                             *\n *          distance -- The distance (in leptons) from the source of the damage.               *\n *                                                                                             *\n * OUTPUT:  Returns with the adjusted damage points to inflict upon the                        *\n *          target.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/16/1994 JLB : Created.                                                                 *\n *   04/17/1994 JLB : Always does a minimum of damage.                                         *\n *   01/01/1995 JLB : Takes into account distance from damage source.                          *\n *   04/11/1996 JLB : Changed damage fall-off formula for less damage fall-off.                *\n *=============================================================================================*/\nint Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance)\n{\n\tif (!damage) return(damage);\n\n\t/*\n\t**\tIf there is no raw damage value to start with, then\n\t**\tthere can be no modified damage either.\n\t*/\n\tif (Special.IsInert || !damage || warhead == WARHEAD_NONE) return(0);\n\n\t/*\n\t**\tNegative damage (i.e., heal) is always applied full strength, but only if the heal\n\t**\teffect is close enough.\n\t*/\n\tif (damage < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (distance < 0x008) {\n\t\t\tif(warhead != WARHEAD_MECHANICAL && armor == ARMOR_NONE) return(damage);\n\t\t\tif(warhead == WARHEAD_MECHANICAL && armor != ARMOR_NONE) return(damage);\n\t\t}\n#else\n\t\tif (distance < 0x008 && armor == ARMOR_NONE) return(damage);\n#endif\n\t\treturn(0);\n\t}\n\n\tWarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * whead = &Warheads[warhead];\n\n\tdamage = damage * whead->Modifier[armor];\n\n\t/*\n\t**\tReduce damage according to the distance from the impact point.\n\t*/\n\tif (damage) {\n\t\tif (!whead->SpreadFactor) {\n\t\t\tdistance /= PIXEL_LEPTON_W/4;\n\t\t} else {\n\t\t\tdistance /= whead->SpreadFactor * (PIXEL_LEPTON_W/2);\n\t\t}\n\t\tdistance = Bound(distance, 0, 16);\n\t\tif (distance) {\n\t\t\tdamage = damage / distance;\n\t\t}\n\n\t\t/*\n\t\t**\tAllow damage to drop to zero only if the distance would have\n\t\t**\treduced damage to less than 1/4 full damage. Otherwise, ensure\n\t\t**\tthat at least one damage point is done.\n\t\t*/\n\t\tif (distance < 4) {\n\t\t\tdamage = max(damage, Rule.MinDamage);\n\t\t}\n\t}\n\n\tdamage = min(damage, Rule.MaxDamage);\n\treturn(damage);\n}\n\n\n/***********************************************************************************************\n * Explosion_Damage -- Inflict an explosion damage affect.                                     *\n *                                                                                             *\n *    Processes the collateral damage affects typically caused by an                           *\n *    explosion.                                                                               *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate of ground zero.                                         *\n *                                                                                             *\n *          strength -- Raw damage points at ground zero.                                      *\n *                                                                                             *\n *          source   -- Source of the explosion (who is responsible).                          *\n *                                                                                             *\n *          warhead  -- The kind of explosion to process.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can consume some time and will affect the AI                       *\n *             of nearby enemy units (possibly).                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/16/1991 JLB : Created.                                                                 *\n *   11/30/1991 JLB : Uses coordinate system.                                                  *\n *   12/27/1991 JLB : Radius of explosion damage effect.                                       *\n *   04/13/1994 JLB : Streamlined.                                                             *\n *   04/16/1994 JLB : Warhead damage type modifier.                                            *\n *   04/17/1994 JLB : Cleaned up.                                                              *\n *   06/20/1994 JLB : Uses object pointers to distribute damage.                               *\n *   06/20/1994 JLB : Source is a pointer.                                                     *\n *   06/18/1996 JLB : Strength could be negative for healing effects.                          *\n *=============================================================================================*/\nvoid Explosion_Damage(COORDINATE coord, int strength, TechnoClass * source, WarheadType warhead)\n{\n\tCELL\t\t\t\tcell;\t\t\t// Cell number under explosion.\n\tObjectClass *\tobject;\t\t\t// Working object pointer.\n\tObjectClass *\tobjects[32];\t// Maximum number of objects that can be damaged.\n\tint\t\t\t\tdistance;\t// Distance to unit.\n\tint\t\t\t\trange;\t\t// Damage effect radius.\n\tint\t\t\t\tcount;\t\t// Number of vehicle IDs in list.\n\n\tif (!strength || Special.IsInert || warhead == WARHEAD_NONE) return;\n\n\tWarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * whead = &Warheads[warhead];\n//\trange = ICON_LEPTON_W*2;\n\trange = ICON_LEPTON_W + (ICON_LEPTON_W >> 1);\n\tcell = Coord_Cell(coord);\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return;\n\n\tCellClass * cellptr = &Map[cell];\n\tObjectClass * impacto = cellptr->Cell_Occupier();\n\n\t/*\n\t**\tFill the list of unit IDs that will have damage\n\t**\tassessed upon them. The units can be lifted from\n\t**\tthe cell data directly.\n\t*/\n\tcount = 0;\n\tfor (FacingType i = FACING_NONE; i < FACING_COUNT; i++) {\n\t\t/*\n\t\t**\tFetch a pointer to the cell to examine. This is either\n\t\t**\tan adjacent cell or the center cell. Damage never spills\n\t\t**\tfurther than one cell away.\n\t\t*/\n\t\tif (i != FACING_NONE) {\n\t\t\tcellptr = Map[cell].Adjacent_Cell(i);\n\t\t\tif (!cellptr) continue;\n\t\t}\n\n\t\t/*\n\t\t**\tAdd all objects in this cell to the list of objects to possibly apply\n\t\t** damage to. The list stops building when the object pointer list becomes\n\t\t** full.  Do not include overlapping objects; selection state can affect\n\t\t** the overlappers, and this causes multiplayer games to go out of sync.\n\t\t*/\n\t\tobject = cellptr->Cell_Occupier();\n\t\twhile (object) {\n\t\t\tif (!object->IsToDamage && object != source) {\n\t\t\t\tobject->IsToDamage = true;\n\t\t\t\tobjects[count++] = object;\n\t\t\t\tif (count >= ARRAY_SIZE(objects)) break;\n\t\t\t}\n\t\t\tobject = object->Next;\n\t\t}\n \t\tif (count >= ARRAY_SIZE(objects)) break;\n\t}\n\n\t/*\n\t**\tSweep through the units to be damaged and damage them. When damaging\n\t**\tbuildings, consider a hit on any cell the building occupies as if it\n\t**\twere a direct hit on the building's center.\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tobject = objects[index];\n\n\t\tobject->IsToDamage = false;\n\t\tif (object->IsActive) {\n\t\t\tif (object->What_Am_I() == RTTI_BUILDING && impacto == object) {\n\t\t\t\tdistance = 0;\n\t\t\t} else {\n\t\t\t\tdistance = Distance(coord, object->Center_Coord());\n\t\t\t}\n\t\t\tif (object->IsDown && !object->IsInLimbo && distance < range) {\n\t\t\t\tint damage = strength;\n\t\t\t\tobject->Take_Damage(damage, distance, warhead, source);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a wall present at this location, it may be destroyed. Check to\n\t**\tmake sure that the warhead is of the kind that can destroy walls.\n\t*/\n\tcellptr = &Map[cell];\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (optr->IsTiberium && whead->IsTiberiumDestroyer) {\n\t\t\tcellptr->Reduce_Tiberium(strength / 10);\n\t\t}\n\t\tif (optr->IsWall) {\n\t\t\tif (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)) {\n\t\t\t\tMap[cell].Reduce_Wall(strength);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a bridge at this location, then it may be destroyed by the\n\t**\tcombat damage.\n\t*/\n\tif (cellptr->TType == TEMPLATE_BRIDGE1 || cellptr->TType == TEMPLATE_BRIDGE2 ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE1H || cellptr->TType == TEMPLATE_BRIDGE2H ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_1A || cellptr->TType == TEMPLATE_BRIDGE_1B ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_2A || cellptr->TType == TEMPLATE_BRIDGE_2B ||\n\t\t cellptr->TType == TEMPLATE_BRIDGE_3A || cellptr->TType == TEMPLATE_BRIDGE_3B ) {\n\n\t\tif (((warhead == WARHEAD_AP || warhead == WARHEAD_HE) && Random_Pick(1, Rule.BridgeStrength) < strength)) {\n\t\t\tMap.Destroy_Bridge_At(cell);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Combat_Anim -- Determines explosion animation to play.                                      *\n *                                                                                             *\n *    This routine is called when a projectile impacts. This routine will determine what       *\n *    animation should be played.                                                              *\n *                                                                                             *\n * INPUT:   damage   -- The amount of damage this warhead possess (warhead size).              *\n *                                                                                             *\n *          warhead  -- The type of warhead.                                                   *\n *                                                                                             *\n *          land     -- The land type that this explosion is over. Sometimes, this makes       *\n *                      a difference (especially over water).                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the animation to play. If no animation is to be played, then          *\n *          ANIM_NONE is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimType Combat_Anim(int damage, WarheadType warhead, LandType land)\n{\n\t/*\n\t**\tFor cases of no damage or invalid warhead, don't have any\n\t**\tanimation effect at all.\n\t*/\n\tif (damage == 0 || warhead == WARHEAD_NONE) {\n\t\treturn(ANIM_NONE);\n\t}\n\n\tstatic AnimType _aplist[] = {\n\t\tANIM_VEH_HIT3,\t\t\t\t\t// Small fragment throwing explosion -- burn/exp mix.\n\t\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\t\tANIM_FRAG1,\t\t\t\t\t\t// Medium fragment throwing explosion -- short decay.\n\t\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\t};\n\n\tstatic AnimType _helist[] = {\n\t\tANIM_VEH_HIT1,\t\t\t\t\t//\tSmall fireball explosion (bulges rightward).\n\t\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\t\tANIM_ART_EXP1,\t\t\t\t\t// Large fragment throwing explosion -- many sparkles.\n\t\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\t};\n\n\tstatic AnimType _firelist[] = {\n\t\tANIM_NAPALM1,\t\t\t\t\t// Small napalm burn.\n\t\tANIM_NAPALM2,\t\t\t\t\t// Medium napalm burn.\n\t\tANIM_NAPALM3,\t\t\t\t\t// Large napalm burn.\n\t};\n\n\tstatic AnimType _waterlist[] = {\n\t\tANIM_WATER_EXP3,\n\t\tANIM_WATER_EXP2,\n\t\tANIM_WATER_EXP1,\n\t};\n\n\tWarheadTypeClass const * wptr = WarheadTypeClass::As_Pointer(warhead);\n//\tWarheadTypeClass const * wptr = &Warheads[warhead];\n\tswitch (wptr->ExplosionSet) {\n\t\tcase 6:\n\t\t\treturn(ANIM_ATOM_BLAST);\n\n\t\tcase 2:\n\t\t\tif (damage > 15) {\n\t\t\t\treturn(ANIM_PIFFPIFF);\n\t\t\t}\n\t\t\treturn(ANIM_PIFF);\n\n\t\tcase 4:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n//\tFixed math error\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 90), 90)]);\n\t\t\treturn(_aplist[(ARRAY_SIZE(_aplist)-1) * fixed(min(damage, 90), 90)]);\n\n\t\tcase 5:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 130), 130)]);\n\t\t\treturn(_helist[(ARRAY_SIZE(_helist)-1) * fixed(min(damage, 130), 130)]);\n\n\t\tcase 3:\n\t\t\tif (land == LAND_NONE) return(ANIM_FLAK);\n\t\t\tif (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 150), 150)]);\n\t\t\treturn(_firelist[(ARRAY_SIZE(_firelist)-1) * fixed(min(damage, 150), 150)]);\n\n\t\tcase 1:\n\t\t\treturn(ANIM_PIFF);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(ANIM_NONE);\n}\n\n\n/***********************************************************************************************\n * Wide_Area_Damage -- Apply wide area damage to the map.                                      *\n *                                                                                             *\n *    This routine will apply damage to a very wide area on the map. The damage will be        *\n *    spread out from the coordinate specified by the radius specified. The amount of damage   *\n *    will attenuate according to the distance from center.                                    *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate that the explosion damage will center about.            *\n *                                                                                             *\n *          radius   -- The radius of the explosion.                                           *\n *                                                                                             *\n *          damage   -- The amount of damage to apply at the center location.                  *\n *                                                                                             *\n *          source   -- Pointer to the purpetrator of the damage (if any).                     *\n *                                                                                             *\n *          warhead  -- The type of warhead that is causing the damage.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Wide_Area_Damage(COORDINATE coord, LEPTON radius, int rawdamage, TechnoClass * source, WarheadType warhead)\n{\n\tint cell_radius = (radius + CELL_LEPTON_W-1) / CELL_LEPTON_W;\n\tCELL cell = Coord_Cell(coord);\n\n\tfor (int x = -cell_radius; x <= cell_radius; x++) {\n\t\tfor (int y = -cell_radius; y <= cell_radius; y++) {\n\t\t\tint xpos = Cell_X(cell) + x;\n\t\t\tint ypos = Cell_Y(cell) + y;\n\n\t\t\t/*\n\t\t\t**\tIf the potential damage cell is outside of the map bounds,\n\t\t\t**\tthen don't process it. This unusual check method ensures that\n\t\t\t**\tdamage won't wrap from one side of the map to the other.\n\t\t\t*/\n\t\t\tif ((unsigned)xpos > MAP_CELL_W) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((unsigned)ypos > MAP_CELL_H) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCELL tcell = XY_Cell(xpos, ypos);\n\t\t\tif (!Map.In_Radar(tcell)) continue;\n\n\t\t\tint dist_from_center = Distance(XY_Coord(x+cell_radius, y+cell_radius), XY_Coord(cell_radius, cell_radius));\n\t\t\tint damage = rawdamage * Inverse(fixed(cell_radius, dist_from_center));\n\t\t\tExplosion_Damage(Cell_Coord(tcell), damage, source, warhead);\n\t\t\tif (warhead == WARHEAD_FIRE && damage > 100) {\n\t\t\t\tnew SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(tcell));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/COMBUF.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COMBUF.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMBUF.CPP                             \t*\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : October 23, 1995 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CommBufferClass::CommBufferClass -- class constructor           \t\t*\n *   CommBufferClass::~CommBufferClass -- class destructor           \t\t*\n *   CommBufferClass::Init -- initializes this queue                       *\n *   CommBufferClass::Init_Send_Queue -- Clears the send queue             *\n *   CommBufferClass::Queue_Send -- queues a message for sending           *\n *   CommBufferClass::UnQueue_Send -- removes next entry from send queue\t*\n *   CommBufferClass::Get_Send -- gets ptr to queue entry                  *\n *   CommBufferClass::Queue_Receive -- queues a received message\t\t\t\t*\n *   CommBufferClass::UnQueue_Receive -- removes next entry from send queue*\n *   CommBufferClass::Get_Receive -- gets ptr to queue entry               *\n *   CommBufferClass::Add_Delay -- adds a new delay value for response time*\n *   CommBufferClass::Avg_Response_Time -- returns average response time  \t*\n *   CommBufferClass::Max_Response_Time -- returns max response time  \t\t*\n *   CommBufferClass::Reset_Response_Time -- resets computations\t\t\t\t*\n *   Mono_Debug_Print -- Debug output routine                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n#include \"combuf.h\"\n#include \"connect.h\"\t// for command names for debug output\n#include \"wwlib32.h\"\t// to enable mono output\n\n\n/***************************************************************************\n * CommBufferClass::CommBufferClass -- class constructor             \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t# queue entries for sending\t\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t# queue entries for receiving\t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\tmaximum desired packet length, in bytes\t\t\t\t\t\t*\n *\t\textralen\t\tmax size of app-specific extra bytes (optional)\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommBufferClass::CommBufferClass(int numsend, int numreceive, int maxlen,\n\tint extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMaxSend = numsend;\n\tMaxReceive = numreceive;\n\tMaxPacketSize = maxlen;\n\tMaxExtraSize = extralen;\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate the queue entries\n\t//------------------------------------------------------------------------\n\tSendQueue = new SendQueueType[numsend];\n\tReceiveQueue = new ReceiveQueueType[numreceive];\n\n\tSendIndex = new int[numsend];\n\tReceiveIndex = new int[numreceive];\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate queue entry buffers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].Buffer = new char[maxlen];\n\t\tif (MaxExtraSize > 0) {\n\t\t\tSendQueue[i].ExtraBuffer = new char[MaxExtraSize];\n\t\t}\n\t\telse {\n\t\t\tSendQueue[i].ExtraBuffer = NULL;\n\t\t}\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].Buffer = new char[maxlen];\n\t\tif (MaxExtraSize > 0) {\n\t\t\tReceiveQueue[i].ExtraBuffer = new char[MaxExtraSize];\n\t\t}\n\t\telse {\n\t\t\tReceiveQueue[i].ExtraBuffer = NULL;\n\t\t}\n\t}\n\n\tInit();\n\n}\t/* end of CommBufferClass */\n\n\n/***************************************************************************\n * CommBufferClass::~CommBufferClass -- class destructor             \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommBufferClass::~CommBufferClass()\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tFree queue entry buffers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tdelete [] SendQueue[i].Buffer;\n\t\tif (SendQueue[i].ExtraBuffer) {\n\t\t\tdelete [] SendQueue[i].ExtraBuffer;\n\t\t}\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tdelete [] ReceiveQueue[i].Buffer;\n\t\tif (ReceiveQueue[i].ExtraBuffer) {\n\t\t\tdelete [] ReceiveQueue[i].ExtraBuffer;\n\t\t}\n\t}\n\n\tdelete [] SendQueue;\n\tdelete [] ReceiveQueue;\n\n\tdelete [] SendIndex;\n\tdelete [] ReceiveIndex;\n\n}\t/* end of ~CommBufferClass */\n\n\n/***************************************************************************\n * CommBufferClass::Init -- initializes this queue                         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/20/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Init(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit data members\n\t//------------------------------------------------------------------------\n\tSendTotal = 0L;\n\tReceiveTotal = 0L;\n\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n\tSendCount = 0;\n\n\tReceiveCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit the queue entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tSendQueue[i].BufLen = 0;\n\t\tSendQueue[i].ExtraLen = 0;\n\n\t\tSendIndex[i] = 0;\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].IsActive = 0;\n\t\tReceiveQueue[i].IsRead = 0;\n\t\tReceiveQueue[i].IsACK = 0;\n\t\tReceiveQueue[i].BufLen = 0;\n\t\tReceiveQueue[i].ExtraLen = 0;\n\n\t\tReceiveIndex[i] = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit debug values\n\t//------------------------------------------------------------------------\n\tDebugOffset = 0;\n\tDebugSize = 0;\n\tDebugNames = NULL;\n\tDebugNameCount = 0;\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * CommBufferClass::Init_Send_Queue -- Clears the send queue               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/23/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Init_Send_Queue(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tInit data members\n\t//------------------------------------------------------------------------\n\tSendCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit the queue entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tSendQueue[i].BufLen = 0;\n\t\tSendQueue[i].ExtraLen = 0;\n\n\t\tSendIndex[i] = 0;\n\t}\n\n}\t/* end of Init_Send_Queue */\n\n\n/***************************************************************************\n * CommBufferClass::Queue_Send -- queues a message for sending             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer containing extra data (optional)\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra data (optional)\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::Queue_Send(void *buf, int buflen, void *extrabuf,\n\tint extralen)\n{\n\tint i;\n\tint index;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no room in the queue\n\t//------------------------------------------------------------------------\n\tif (SendCount==MaxSend || buflen > MaxPacketSize)\n\t\treturn(0);\n\n\t//------------------------------------------------------------------------\n\t//\tFind an empty slot\n\t//------------------------------------------------------------------------\n\tindex = -1;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tif (SendQueue[i].IsActive==0) {\n\t\t\tindex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == -1)\n\t\treturn (0);\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tSendQueue[index].IsActive = 1;\t\t\t// entry is now active\n\tSendQueue[index].IsACK = 0;\t\t\t\t// entry hasn't been ACK'd\n\tSendQueue[index].FirstTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].LastTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].SendCount = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[index].BufLen = buflen;\t\t// save buffer size\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the packet data\n\t//------------------------------------------------------------------------\n\tmemcpy(SendQueue[index].Buffer,buf,buflen);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the extra data, if there is any\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {\n\t\tmemcpy(SendQueue[index].ExtraBuffer,extrabuf,extralen);\n\t\tSendQueue[index].ExtraLen = extralen;\n\t}\n\telse {\n\t\tSendQueue[index].ExtraLen = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave this entry's index\n\t//------------------------------------------------------------------------\n\tSendIndex[SendCount] = index;\n\n\t//------------------------------------------------------------------------\n\t//\tIncrement counters & entry ptr\n\t//------------------------------------------------------------------------\n\tSendCount++;\n\tSendTotal++;\n\n\treturn(1);\n\n}\t/* end of Queue_Send */\n\n\n/***************************************************************************\n * CommBufferClass::UnQueue_Send -- removes next entry from send queue\t\t*\n *                                                                         *\n * Frees the given entry; the index given by the caller is the \"active\"\t\t*\n * index value (ie the \"nth\" active entry), not the actual index in the\t\t*\n * array.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *\t\tindex\t\t\t\"index\" of entry to un-queue\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer for extra data (optional)\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tptr to length of extra data (optional)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retrieve\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::UnQueue_Send(void *buf, int *buflen, int index,\n\tvoid *extrabuf, int *extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no entry to retrieve\n\t//------------------------------------------------------------------------\n\tif (SendCount==0 || SendQueue[SendIndex[index]].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the data from the entry\n\t//------------------------------------------------------------------------\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,SendQueue[SendIndex[index]].Buffer,\n\t\t\tSendQueue[SendIndex[index]].BufLen);\n\t\t(*buflen) = SendQueue[SendIndex[index]].BufLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the extra data\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen!=NULL) {\n\t\tmemcpy(extrabuf,SendQueue[SendIndex[index]].ExtraBuffer,\n\t\t\tSendQueue[SendIndex[index]].ExtraLen);\n\t\t(*extralen) = SendQueue[SendIndex[index]].ExtraLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tSendQueue[SendIndex[index]].IsActive = 0;\n\tSendQueue[SendIndex[index]].IsACK = 0;\n\tSendQueue[SendIndex[index]].FirstTime = 0L;\n\tSendQueue[SendIndex[index]].LastTime = 0L;\n\tSendQueue[SendIndex[index]].SendCount = 0L;\n\tSendQueue[SendIndex[index]].BufLen = 0;\n\tSendQueue[SendIndex[index]].ExtraLen = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tMove Indices back one\n\t//------------------------------------------------------------------------\n\tfor (i = index; i < SendCount - 1; i++) {\n\t\tSendIndex[i] = SendIndex[i + 1];\n\t}\n\tSendIndex[SendCount - 1] = 0;\n\tSendCount--;\n\n\treturn(1);\n\n}\t/* end of UnQueue_Send */\n\n\n/***************************************************************************\n * CommBufferClass::Get_Send -- gets ptr to queue entry                    *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessible queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommBufferClass::Get_Send(int index)\n{\n\tif (SendQueue[SendIndex[index]].IsActive==0) {\n\t\treturn(NULL);\n\t}\n\telse {\n\t\treturn(&SendQueue[SendIndex[index]]);\n\t}\n\n}\t/* end of Get_Send */\n\n\n/***************************************************************************\n * CommBufferClass::Queue_Receive -- queues a received message\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer containing extra data (optional)\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra data (optional)\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::Queue_Receive(void *buf, int buflen, void *extrabuf,\n\tint extralen)\n{\n\tint i;\n\tint index;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no room in the queue\n\t//------------------------------------------------------------------------\n\tif (ReceiveCount==MaxReceive || buflen > MaxPacketSize) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFind an empty slot\n\t//------------------------------------------------------------------------\n\tindex = -1;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tif (ReceiveQueue[i].IsActive==0) {\n\t\t\tindex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == -1)\n\t\treturn (0);\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tReceiveQueue[index].IsActive = 1;\n\tReceiveQueue[index].IsRead = 0;\n\tReceiveQueue[index].IsACK = 0;\n\tReceiveQueue[index].BufLen = buflen;\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the packet data\n\t//------------------------------------------------------------------------\n\tmemcpy(ReceiveQueue[index].Buffer,buf,buflen);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the extra data, if there is any\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {\n\t\tmemcpy(ReceiveQueue[index].ExtraBuffer,extrabuf,extralen);\n\t\tReceiveQueue[index].ExtraLen = extralen;\n\t}\n\telse {\n\t\tReceiveQueue[index].ExtraLen = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave this entry's index\n\t//------------------------------------------------------------------------\n\tReceiveIndex[ReceiveCount] = index;\n\n\t//------------------------------------------------------------------------\n\t//\tIncrement counters & entry ptr\n\t//------------------------------------------------------------------------\n\tReceiveCount++;\n\tReceiveTotal++;\n\n\treturn(1);\n\n}\t/* end of Queue_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::UnQueue_Receive -- removes next entry from send queue\t*\n *                                                                         *\n * Frees the given entry; the index given by the caller is the \"active\"\t\t*\n * index value (ie the \"nth\" active entry), not the actual index in the\t\t*\n * array.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *\t\tindex\t\t\tindex of entry to un-queue\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\tbuffer for extra data (optional)\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tptr to length of extra data (optional)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retrieve\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommBufferClass::UnQueue_Receive(void *buf, int *buflen, int index,\n\tvoid *extrabuf, int *extralen)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tError if no entry to retrieve\n\t//------------------------------------------------------------------------\n\tif (ReceiveCount==0 || ReceiveQueue[ReceiveIndex[index]].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the data from the entry\n\t//------------------------------------------------------------------------\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,ReceiveQueue[ReceiveIndex[index]].Buffer,\n\t\t\tReceiveQueue[ReceiveIndex[index]].BufLen);\n\t\t(*buflen) = ReceiveQueue[ReceiveIndex[index]].BufLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the extra data\n\t//------------------------------------------------------------------------\n\tif (extrabuf!=NULL && extralen!=NULL) {\n\t\tmemcpy(extrabuf,ReceiveQueue[ReceiveIndex[index]].ExtraBuffer,\n\t\t\tReceiveQueue[ReceiveIndex[index]].ExtraLen);\n\t\t(*extralen) = ReceiveQueue[ReceiveIndex[index]].ExtraLen;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet entry flags\n\t//------------------------------------------------------------------------\n\tReceiveQueue[ReceiveIndex[index]].IsActive = 0;\n\tReceiveQueue[ReceiveIndex[index]].IsRead = 0;\n\tReceiveQueue[ReceiveIndex[index]].IsACK = 0;\n\tReceiveQueue[ReceiveIndex[index]].BufLen = 0;\n\tReceiveQueue[ReceiveIndex[index]].ExtraLen = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tMove Indices back one\n\t//------------------------------------------------------------------------\n\tfor (i = index; i < ReceiveCount - 1; i++) {\n\t\tReceiveIndex[i] = ReceiveIndex[i + 1];\n\t}\n\tReceiveIndex[ReceiveCount - 1] = 0;\n\tReceiveCount--;\n\n\treturn(1);\n\n}\t/* end of UnQueue_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::Get_Receive -- gets ptr to queue entry                 *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessible queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommBufferClass::Get_Receive(int index)\n{\n\tif (ReceiveQueue[ReceiveIndex[index]].IsActive==0) {\n\t\treturn(NULL);\n\t}\n\telse {\n\t\treturn(&ReceiveQueue[ReceiveIndex[index]]);\n\t}\n\n}\t/* end of Get_Receive */\n\n\n/***************************************************************************\n * CommBufferClass::Add_Delay -- adds a new delay value for response time  *\n *                                                                         *\n * This routine updates the average response time for this queue.  The\t\t*\n * computation is based on the average of the last 'n' delay values given,\t*\n * It computes a running total of the last n delay values, then divides \t*\n * that by n to compute the average.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * When the number of values given exceeds the max, the mean is subtracted\t*\n * off the total, then the new value is added in.  Thus, any single delay\t*\n * value will have an effect on the total that approaches 0 over time, and\t*\n * the new delay value contributes to 1/n of the mean.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdelay\t\t\tvalue to add into the response time computation\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Add_Delay(unsigned long delay)\n{\n\tint roundoff = 0;\n\n\tif (NumDelay==256) {\n\t\tDelaySum -= MeanDelay;\n\t\tDelaySum += delay;\n\t\tif ( (DelaySum & 0x00ff) > 127)\n\t\t\troundoff = 1;\n\t\tMeanDelay = (DelaySum >> 8) + roundoff;\n\t}\n\telse {\n\t\tNumDelay++;\n\t\tDelaySum += delay;\n\t\tMeanDelay = DelaySum / NumDelay;\n\t}\n\n\tif (delay > MaxDelay) {\n\t\tMaxDelay = delay;\n\t}\n\n}\t/* end of Add_Delay */\n\n\n/***************************************************************************\n * CommBufferClass::Avg_Response_Time -- returns average response time    \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommBufferClass::Avg_Response_Time(void)\n{\n\treturn(MeanDelay);\n\n}\t/* end of Avg_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Max_Response_Time -- returns max response time    \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommBufferClass::Max_Response_Time(void)\n{\n\treturn(MaxDelay);\n\n}\t/* end of Max_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Reset_Response_Time -- resets computations\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommBufferClass::Reset_Response_Time(void)\n{\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * CommBufferClass::Configure_Debug -- sets up special debug values        *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tmaxnames\t\t\tmax # in the names array; 0 if none.\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Configure_Debug(int type_offset, int type_size,\n\tchar **names, int namestart, int namecount)\n{\n\tDebugOffset = type_offset;\n\tDebugSize = type_size;\n\tDebugNames = names;\n\tDebugNameStart = namestart;\n\tDebugNameCount = namecount;\n\n}\t/* end of Configure_Debug */\n\n\n/***************************************************************************\n * Mono_Debug_Print -- Debug output routine                                *\n *                                                                         *\n * This routine leaves 5 lines at the top for the caller's use.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Mono_Debug_Print(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tstatic int send_col[] = {1,14,28};\t\t\t// coords of send queue columns\n\tstatic int receive_col[] = {40,54,68};\t\t// coords of recv queue columns\n\tint row,col;\t\t\t\t\t\t\t\t\t\t// current row,col for printing\n\tint num;\t\t\t\t\t\t\t\t\t\t\t\t// max # items to print\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t//------------------------------------------------------------------------\n\t//\tIf few enough entries, call the verbose debug version\n\t//------------------------------------------------------------------------\n\tif (MaxSend <= 16) {\n\t\tMono_Debug_Print2(refresh);\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRefresh the screen\n\t//------------------------------------------------------------------------\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct ACK   ID  Ct ACK    ID  Ct ACK ID  Rd ACK    ID  Rd ACK   ID  Rd ACK\\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Send Queue items\n\t//------------------------------------------------------------------------\n\tif (MaxSend <= 48) {\n\t\tnum = MaxSend;\n\t}\n\telse {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (send_col[col],row + 8);\n\t\tif (SendQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tMono_Printf (\"%4d %2d  %d\",hdr->PacketID, SendQueue[i].SendCount,\n\t\t\t\tSendQueue[i].IsACK);\n\t\t}\n\t\telse {\n\t\t\tMono_Printf (\"____ __  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Receive Queue items\n\t//------------------------------------------------------------------------\n\tif (MaxReceive <= 48) {\n\t\tnum = MaxSend;\n\t}\n\telse {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (receive_col[col],row + 8);\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\tMono_Printf (\"%4d  %d  %d\",hdr->PacketID, ReceiveQueue[i].IsRead,\n\t\t\t\tReceiveQueue[i].IsACK);\n\t\t}\n\t\telse {\n\t\t\tMono_Printf (\"____  _  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\n}\t/* end of Mono_Debug_Print */\n\n\n/***************************************************************************\n * CommBufferClass::Mono_Debug_Print2 -- Debug output; alternate format    *\n *                                                                         *\n * This routine prints more information than the other version; it's\t\t\t*\n * called only if the number of queue entries is small enough to support\t*\n * this format.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid CommBufferClass::Mono_Debug_Print2(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[80];\n\tint val;\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t//------------------------------------------------------------------------\n\t//\tRefresh the screen\n\t//------------------------------------------------------------------------\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct Type   Data  Name         ACK  ID  Rd Type   Data  Name         ACK \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Send Queue items\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (1,8 + i);\n\n\t\t//.....................................................................\n\t\t//\tPrint an active entry\n\t\t//.....................................................................\n\t\tif (SendQueue[i].IsActive) {\n\n\t\t\t//..................................................................\n\t\t\t//\tGet header info\n\t\t\t//..................................................................\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tSendQueue[i].SendCount,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t//..................................................................\n\t\t\t//\tDecode app's ID & its name\n\t\t\t//..................................................................\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(SendQueue[i].Buffer + DebugOffset);\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==2) {\n\t\t\t\t\tval = *((short *)(SendQueue[i].Buffer + DebugOffset));\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==4) {\n\t\t\t\t\tval = *((int *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val - DebugNameStart], SendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",\n\t\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(txt + strlen(txt),\"                    %x\",\n\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t}\n\n\t\t\tMono_Printf(\"%s\",txt);\n\t\t}\n\t\telse {\n\n\t\t\t//..................................................................\n\t\t\t//\tEntry isn't active; print blanks\n\t\t\t//..................................................................\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrint Receive Queue items\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (40,8 + i);\n\n\t\t//.....................................................................\n\t\t//\tPrint an active entry\n\t\t//.....................................................................\n\t\tif (ReceiveQueue[i].IsActive) {\n\n\t\t\t//..................................................................\n\t\t\t//\tGet header info\n\t\t\t//..................................................................\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tReceiveQueue[i].IsRead,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t//..................................................................\n\t\t\t//\tDecode app's ID & its name\n\t\t\t//..................................................................\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= ReceiveQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(ReceiveQueue[i].Buffer + DebugOffset);\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==2) {\n\t\t\t\t\tval = *((short *)(ReceiveQueue[i].Buffer + DebugOffset));\n\n\t\t\t\t}\n\t\t\t\telse if (DebugSize==4) {\n\t\t\t\t\tval = *((int *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val - DebugNameStart], ReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",\n\t\t\t\t\t\tReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(txt + strlen(txt),\"                    %x\",\n\t\t\t\t\tReceiveQueue[i].IsACK);\n\t\t\t}\n\n\t\t\tMono_Printf(\"%s\",txt);\n\t\t}\n\t\telse {\n\n\t\t\t//..................................................................\n\t\t\t//\tEntry isn't active; print blanks\n\t\t\t//..................................................................\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\n}\t/* end of Mono_Debug_Print2 */\n\n\n/************************** end of combuf.cpp ******************************/\n\n\n"
  },
  {
    "path": "REDALERT/COMBUF.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COMBUF.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMBUF.H                               \t*\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class's job is to store outgoing messages & incoming messages, \t\t*\n * and serves as a storage area for various flags for ACK & Retry logic.\t*\n *                                                                         *\n * This class stores buffers in a non-sequenced order; it allows freeing\t*\n * any entry, so the buffers can be kept clear, even if packets come in\t\t*\n * out of order.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The class also contains routines to maintain a cumulative response time\t*\n * for this queue.  It's up to the caller to call Add_Delay() whenever\t\t*\n * it detects that an outgoing message has been ACK'd; this class adds\t\t*\n * that delay into a computed average delay over the last few message \t\t*\n * delays.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMBUF_H\n#define COMBUF_H\n\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThis is one output queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK received for this packet\n\tunsigned long FirstTime;\t\t// time this packet was first sent\n\tunsigned long LastTime;\t\t\t// time this packet was last sent\n\tunsigned long SendCount;\t\t// # of times this packet has been sent\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n\tint ExtraLen;\t\t\t\t\t\t// size of extra data\n\tchar *ExtraBuffer;\t\t\t\t// extra data buffer\n} SendQueueType;\n\n/*---------------------------------------------------------------------------\nThis is one input queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsRead\t\t: 1;\t// 1 = caller has read this entry\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK sent for this packet\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n\tint ExtraLen;\t\t\t\t\t\t// size of extra data\n\tchar *ExtraBuffer;\t\t\t\t// extra data buffer\n} ReceiveQueueType;\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass CommBufferClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*\n\t\t....................... Constructor/Destructor ........................\n\t\t*/\n\t\tCommBufferClass(int numsend, int numrecieve, int maxlen, \n\t\t\tint extralen = 0);\n\t\tvirtual ~CommBufferClass();\n\t\tvoid Init(void);\n\t\tvoid Init_Send_Queue(void);\n\n\t\t/*\n\t\t......................... Send Queue routines .........................\n\t\t*/\n\t\tint Queue_Send(void *buf, int buflen, void *extrabuf = NULL,\n\t\t\tint extralen = 0);\n\t\tint UnQueue_Send(void *buf, int *buflen, int index, \n\t\t\tvoid *extrabuf = NULL, int *extralen = NULL);\n\t\tint Num_Send(void) {return (SendCount);}\t\t// # entries in queue\n\t\tint Max_Send(void) { return (MaxSend);}\t\t// max # send queue entries\n\t\tSendQueueType * Get_Send(int index);\t\t\t// random access to queue\n\t\tunsigned long Send_Total(void) {return (SendTotal);}\n\n\t\t/*\n\t\t....................... Receive Queue routines ........................\n\t\t*/\n\t\tint Queue_Receive(void *buf, int buflen, void *extrabuf = NULL,\n\t\t\tint extralen = 0);\n\t\tint UnQueue_Receive(void *buf, int *buflen, int index, \n\t\t\tvoid *extrabuf = NULL, int *extralen = NULL);\n\t\tint Num_Receive(void) {return (ReceiveCount);}\t// # entries in queue\n\t\tint Max_Receive(void) { return (MaxReceive); }\t// max # recv queue entries\n\t\tReceiveQueueType * Get_Receive(int index);\t// random access to queue\n\t\tunsigned long Receive_Total(void) {return (ReceiveTotal);}\n\n\t\t/*\n\t\t....................... Response time routines ........................\n\t\t*/\n\t\tvoid Add_Delay(unsigned long delay);\t// accumulates response time\n\t\tunsigned long Avg_Response_Time(void);\t// gets mean response time\n\t\tunsigned long Max_Response_Time(void);\t// gets max response time\n\t\tvoid Reset_Response_Time(void);\t\t\t// resets computations\n\n\t\t/*\n\t\t........................ Debug output routines ........................\n\t\t*/\n\t\tvoid Configure_Debug(int type_offset, int type_size, char **names, \n\t\t\tint namestart, int namecount);\n\t\tvoid Mono_Debug_Print(int refresh = 0);\n\t\tvoid Mono_Debug_Print2(int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*\n\t\t.......................... Limiting variables .........................\n\t\t*/\n\t\tint MaxSend;\t\t\t\t\t\t\t// max # send queue entries\n\t\tint MaxReceive;\t\t\t\t\t\t// max # receive queue entries\n\t\tint MaxPacketSize;\t\t\t\t\t// max size of a packet, in bytes\n\t\tint MaxExtraSize;\t\t\t\t\t\t// max size of extra bytes\n\n\t\t/*\n\t\t....................... Response time variables .......................\n\t\t*/\n\t\tunsigned long DelaySum;\t\t\t\t// sum of last 4 delay times\n\t\tunsigned long NumDelay;\t\t\t\t// current # delay times summed\n\t\tunsigned long MeanDelay;\t\t\t// current average delay time\n\t\tunsigned long MaxDelay;\t\t\t\t// max delay ever for this queue\n\n\t\t/*\n\t\t........................ Send Queue variables .........................\n\t\t*/\n\t\tSendQueueType * SendQueue;\t\t\t// incoming packets\n\t\tint SendCount; \t\t\t\t\t\t// # packets in the queue\n\t\tunsigned long SendTotal;\t\t\t// total # added to send queue\n\t\tint *SendIndex;\t\t\t\t\t\t// array of Send entry indices\n\n\t\t/*\n\t\t....................... Receive Queue variables .......................\n\t\t*/\n\t\tReceiveQueueType * ReceiveQueue;\t\t// outgoing packets\n\t\tint ReceiveCount;\t\t\t\t\t\t\t// # packets in the queue\n\t\tunsigned long ReceiveTotal;\t\t\t// total # added to receive queue\n\t\tint *ReceiveIndex;\t\t\t\t\t\t// array of Receive entry indices\n\n\t\t/*\n\t\t......................... Debugging Variables .........................\n\t\t*/\n\t\tint DebugOffset;\t\t\t\t\t\t\t// offset into app's packet for ID\n\t\tint DebugSize;\t\t\t\t\t\t\t\t// size of app's ID\n\t\tchar **DebugNames;\t\t\t\t\t\t// ptr to array of app-specific names\n\t\tint DebugNameStart;\t\t\t\t\t\t// number of 1st ID\n\t\tint DebugNameCount;\t\t\t\t\t\t// # of names in array\n};\n\n#endif\n\n/**************************** end of combuf.h ******************************/\n\n"
  },
  {
    "path": "REDALERT/COMINIT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//\n// If you link with this it will automatically call the COM initialization stuff \n//\n\n#include \"cominit.h\"\n//#include <stdlib.h>\n//#include <stdio.h>\n//#include <windows.h>\n#include <objbase.h>\n//#include \"externs.h\"\n//#include \"text.rh\"\n\n//#include \"WolDebug.h\"\n\nComInit::ComInit()\n{\n  //HRESULT hRes = CoInitialize(NULL);\n//\tif (SUCCEEDED(hRes)==FALSE)\n//\t\texit(0);\n\tHRESULT hRes = OleInitialize(NULL);\n}\n\nComInit::~ComInit()\n{\n//  CoUninitialize();\n//\tdebugprint( \"pre OleUninitialize\\n\" );\n\tOleUninitialize();\n//\tdebugprint( \"post OleUninitialize\\n\" );\n}\n\n// Creating this instance will setup all COM stuff & do cleanup on program exit\nComInit  Global_COM_Initializer;\n\n"
  },
  {
    "path": "REDALERT/COMINIT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef COMINIT_HEADER\n#define COMINIT_HEADER\n\n//\n// Link with this to automatically initialize COM at startup\n//  - See cominit.cpp for more info\n//\n\nclass ComInit\n{\n public:\n         ComInit();\n        ~ComInit();\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/COMPAT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COMPAT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COMPAT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/95                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMPAT_H\n#define COMPAT_H\n\n\n#define\tBuffType\t\tBufferClass\n//#define movmem(a,b,c) memmove(b,a,c)\n#define ShapeBufferSize\t_ShapeBufferSize\n\n/*=========================================================================*/\n/* Define some equates for the different graphic routines we will install\t*/\n/*\t\tlater.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n#define HIDBUFF\t  ((void *)(0xA0000))\n#define Size_Of_Region(a, b) ((a)*(b))\n\n/*=========================================================================*/\n/* Define some Graphic Routines which will only be fixed by these defines\t*/\n/*=========================================================================*/\n#define Set_Font_Palette(a) \t\tSet_Font_Palette_Range(a, 0, 15)\n\n/*\n**\tThese are the Open_File, Read_File, and Seek_File constants.\n*/\n#define READ\t\t\t\t\t\t1\t// Read access.\n#define WRITE\t\t\t\t\t\t2\t// Write access.\n\n#ifndef SEEK_SET\n#define SEEK_SET\t\t\t\t\t0\t// Seek from start of file.\n#define SEEK_CUR\t\t\t\t\t1\t// Seek relative from current location.\n#define SEEK_END\t\t\t\t\t2\t// Seek from end of file.\n#endif\n\n#define ERROR_WINDOW \t\t\t1\n#define ErrorWindow \t\t\t1\n\n\n//extern unsigned char *Palette;\nextern unsigned char MDisabled;\t\t\t// Is mouse disabled?\nextern WORD Hard_Error_Occured;\n\n/*\n**\tThis is the menu control structures.\n*/\ntypedef enum MenuIndexType {\n\tMENUX,\n\tMENUY,\n\tITEMWIDTH,\n\tITEMSHIGH,\n\tMSELECTED,\n\tNORMCOL,\n\tHILITE,\n\tMENUPADDING=0x1000\n} MenuIndexType;\n\n\n#ifdef NEVER\n#define BITSPERBYTE 8\n#define MAXSHORT    0x7FFF\n#define HIBITS      0x8000\n#define MAXLONG     0x7FFFFFFFL\n#define HIBITL      0x80000000\n\n#define MAXINT      MAXLONG\n#define HIBITI      HIBITL\n\n#define DMAXEXP     308\n#define FMAXEXP     38\n#define DMINEXP     -307\n#define FMINEXP     -37\n\n#define MAXDOUBLE   1.797693E+308\n#define MAXFLOAT    3.37E+38F\n#define MINDOUBLE   2.225074E-308\n#define MINFLOAT    8.43E-37F\n\n#define DSIGNIF     53\n#define FSIGNIF     24\n\n#define DMAXPOWTWO  0x3FF\n#define FMAXPOWTWO  0x7F\n#define DEXPLEN     11\n#define FEXPLEN     8\n#define EXPBASE     2\n#define IEEE        1\n#define LENBASE     1\n#define HIDDENBIT   1\n#define LN_MAXDOUBLE    7.0978E+2\n#define LN_MINDOUBLE    -7.0840E+2\n#endif\n\n/* These defines handle the various names given to the same color. */\n#define\tDKGREEN\tGREEN\n#define\tDKBLUE\tBLUE\n#define\tGRAY\t\tGREY\n#define\tDKGREY\tGREY\n#define\tDKGRAY\tGREY\n#define\tLTGRAY\tLTGREY\n\n\nclass IconsetClass;\n#ifndef WIN32\ntypedef struct {\n\tshort\tWidth;\t\t\t// Width of icons (pixels).\n\tshort\tHeight;\t\t\t// Height of icons (pixels).\n\tshort\tCount;\t\t\t// Number of (logical) icons in this set.\n\tshort\tAllocated;\t\t// Was this iconset allocated?\n\tshort MapWidth;\t\t// Width of map (in icons).\n\tshort MapHeight;\t\t// Height of map (in icons).\n\tlong\tSize;\t\t\t\t// Size of entire iconset memory block.\n\tlong\tIcons;\t\t\t// Offset from buffer start to icon data.\n//\tunsigned char * Icons;\t// Offset from buffer start to icon data.\n\tlong\tPalettes;\t\t// Offset from buffer start to palette data.\n\tlong\tRemaps;\t\t\t// Offset from buffer start to remap index data.\n\tlong\tTransFlag;\t\t// Offset for transparency flag table.\n\tlong\tColorMap;\t\t// Offset for color control value table.\n\tlong\tMap;\t\t\t\t// Icon map offset (if present).\n//\tunsigned char * Map;\t\t\t\t// Icon map offset (if present).\n} IControl_Type;\n#endif\n\ninline int Get_IconSet_MapWidth(void const * data)\n{\n\tif (data) {\n\t\treturn(((IControl_Type *)data)->MapWidth);\n\t}\n\treturn(0);\n}\n\ninline int Get_IconSet_MapHeight(void const * data)\n{\n\tif (data) {\n\t\treturn(((IControl_Type *)data)->MapHeight);\n\t}\n\treturn(0);\n}\n\ninline unsigned char const * Get_IconSet_ControlMap(void const * data)\n{\n\tif (data) {\n\t\treturn((unsigned char const *)((char *)data + ((IControl_Type *)data)->ColorMap));\n\t}\n\treturn(0);\n}\n\nclass IconsetClass : protected IControl_Type\n{\n\tpublic:\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tint Map_Width(void) const {return(MapWidth);};\n\t\tint Map_Height(void) const {return(MapHeight);};\n\t\tunsigned char * Control_Map(void) {return((unsigned char *)this + ColorMap);};\n\t\tunsigned char const * Control_Map(void) const {return((unsigned char const *)this + ColorMap);};\n\t\tint Icon_Count(void) const {return(Count);};\n\t\tint Pixel_Width(void) const {return(Width);};\n\t\tint Pixel_Height(void) const {return(Height);};\n\t\tint Total_Size(void) const {return(Size);};\n\t\tunsigned char const * Palette_Data(void) const {return((unsigned char const *)this + Palettes);};\n\t\tunsigned char * Palette_Data(void) {return((unsigned char *)this + Palettes);};\n\t\tunsigned char const * Icon_Data(void) const {return((unsigned char const *)this + Icons);};\n\t\tunsigned char * Icon_Data(void) {return((unsigned char *)this + Icons);};\n\t\tunsigned char const * Map_Data(void) const {return((unsigned char const *)this + Map);};\n\t\tunsigned char * Map_Data(void) {return((unsigned char *)this + Map);};\n\t\tunsigned char const * Remap_Data(void) const {return((unsigned char const *)this + Remaps);};\n\t\tunsigned char * Remap_Data(void) {return((unsigned char *)this + Remaps);};\n\t\tunsigned char const * Trans_Data(void) const {return((unsigned char const *)this + TransFlag);};\n\t\tunsigned char * Trans_Data(void) {return((unsigned char *)this + TransFlag);};\n\n\t/*\n\t**\tDisallow these operations with an IconsetClass object.\n\t*/\n\tprivate:\n\t\tIconsetClass & operator = (IconsetClass const &);\n\t\tIconsetClass(void);\n\t\tstatic void * operator new(size_t);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/COMQUEUE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\comqueue.cpv   4.1   11 Apr 1996 18:28:16   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMQUEUE.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : May 31, 1995 [BRR]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   CommQueueClass::Add_Delay -- adds a new delay value for response time *\n *   CommQueueClass::Avg_Response_Time -- returns average response time    *\n *   CommQueueClass::CommQueueClass -- class constructor                   *\n *   CommQueueClass::Configure_Debug -- sets up special debug values       * \n *   CommQueueClass::Get_Receive -- gets ptr to queue entry                *\n *   CommQueueClass::Get_Send -- gets ptr to queue entry                   *\n *   CommQueueClass::Init -- initializes this queue                        *\n *   CommQueueClass::Max_Response_Time -- returns max response time        *\n *   CommQueueClass::Mono_Debug_Print -- Debug output routine              * \n *   CommQueueClass::Mono_Debug_Print2 -- Debug output; alternate format   * \n *   CommQueueClass::Next_Receive -- gets ptr to next entry in send queue  *\n *   CommQueueClass::Next_Send -- gets ptr to next entry in send queue     *\n *   CommQueueClass::Queue_Receive -- queues a received message            *\n *   CommQueueClass::Queue_Send -- queues a message for sending            *\n *   CommQueueClass::Reset_Response_Time -- resets computations            *\n *   CommQueueClass::UnQueue_Receive -- removes next entry from send queue *\n *   CommQueueClass::UnQueue_Send -- removes next entry from send queue    *\n *   CommQueueClass::~CommQueueClass -- class destructor                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#if (0)\n#include \"function.h\"\n\n\n/***************************************************************************\n * CommQueueClass::CommQueueClass -- class constructor             \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t# queue entries for sending\t\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t# queue entries for receiving\t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\tmaximum desired packet length, in bytes\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommQueueClass::CommQueueClass(int numsend, int numreceive, int maxlen)\n{\n\tint i;\n\n\t/*\n\t**\tInit variables \n\t*/\n\tMaxSend = numsend;\n\tMaxReceive = numreceive;\n\tMaxPacketSize = maxlen;\n\n\t/*\n\t**\tAllocate the queue entries \n\t*/\n\tSendQueue = new SendQueueType[numsend];\n\tReceiveQueue = new ReceiveQueueType[numreceive];\n\n\t/*\n\t**\tAllocate queue entry buffers \n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].Buffer = new char[maxlen];\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].Buffer = new char[maxlen];\n\t}\n\n\tInit();\n}\n\n\n/***************************************************************************\n * CommQueueClass::~CommQueueClass -- class destructor             \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nCommQueueClass::~CommQueueClass()\n{\n\tint i;\n\n\t/*\n\t**\tFree queue entry buffers \n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tdelete [] SendQueue[i].Buffer;\n\t}\n\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tdelete [] ReceiveQueue[i].Buffer;\n\t}\n\n\tdelete [] SendQueue;\n\tdelete [] ReceiveQueue;\n}\n\n\n/***************************************************************************\n * CommQueueClass::Init -- initializes this queue                          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/20/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Init(void)\n{\n\tint i;\n\n\t/*\n\t**\tInit data members\n\t*/\n\tSendTotal = 0L;\n\tReceiveTotal = 0L;\n\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n\n\tSendCount = 0;\n\tSendNext = 0;\n\tSendEmpty = 0;\n\n\tReceiveCount = 0;\n\tReceiveNext = 0;\n\tReceiveEmpty = 0;\n\n\t/*\n\t**\tInit the queue entries\n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tSendQueue[i].IsActive = 0;\n\t\tSendQueue[i].IsACK = 0;\n\t\tSendQueue[i].FirstTime = 0L;\n\t\tSendQueue[i].LastTime = 0L;\n\t\tSendQueue[i].SendCount = 0L;\n\t\tReceiveQueue[i].BufLen = 0;\n\t}\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tReceiveQueue[i].IsActive = 0;\n\t\tReceiveQueue[i].IsRead = 0;\n\t\tReceiveQueue[i].IsACK = 0;\n\t\tReceiveQueue[i].BufLen = 0;\n\t}\n\t\n\t/*\n\t**\tInit debug values\n\t*/\n\tDebugOffset = 0;\n\tDebugSize = 0;\n\tDebugNames = NULL;\n\tDebugMaxNames = 0;\n}\n\n\n/***************************************************************************\n * CommQueueClass::Queue_Send -- queues a message for sending              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::Queue_Send(void *buf, int buflen)\n{\n\t/*\n\t**\tError if no room in the queue\n\t*/\n\tif (SendCount==MaxSend || SendQueue[SendEmpty].IsActive!=0) {\n\t\treturn(0); \n\t}\n\n\t/*\n\t**\tSet entry flags \n\t*/\n\tSendQueue[SendEmpty].IsActive = 1;\t\t\t// entry is now active\n\tSendQueue[SendEmpty].IsACK = 0;\t\t\t\t// entry hasn't been ACK'd\n\tSendQueue[SendEmpty].FirstTime = 0L;\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].LastTime = 0L;\t\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].SendCount = 0L;\t\t// filled in by Manager when sent\n\tSendQueue[SendEmpty].BufLen = buflen;\t\t// save buffer size\n\n\t/*\n\t**\tCopy the packet data \n\t*/\n\tmemcpy(SendQueue[SendEmpty].Buffer,buf,buflen);\n\n\t/*\n\t**\tIncrement counters & entry ptr \n\t*/\n\tSendCount++;\n\tSendEmpty++;\n\tif (SendEmpty==MaxSend) {\n\t\tSendEmpty = 0;\n\t}\n\n\tSendTotal++;\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::UnQueue_Send -- removes next entry from send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retreive\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::UnQueue_Send(void *buf, int *buflen)\n{\n\t/*\n\t**\tError if no entry to retrieve \n\t*/\n\tif (SendCount==0 || SendQueue[SendNext].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tCopy the data from the entry \n\t*/\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,SendQueue[SendNext].Buffer,SendQueue[SendNext].BufLen);\n\t\t(*buflen) = SendQueue[SendNext].BufLen;\n\t}\n\n\t/*\n\t**\tSet entry flags \n\t*/\n\tSendQueue[SendNext].IsActive = 0;\n\tSendQueue[SendNext].IsACK = 0;\n\tSendQueue[SendNext].FirstTime = 0L;\n\tSendQueue[SendNext].LastTime = 0L;\n\tSendQueue[SendNext].SendCount = 0L;\n\tSendQueue[SendNext].BufLen = 0;\n\tSendCount--;\n\tSendNext++;\n\tif (SendNext==MaxSend) {\n\t\tSendNext = 0;\n\t}\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Next_Send -- gets ptr to next entry in send queue       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry, NULL if there is none.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommQueueClass::Next_Send(void)\n{\n\tif (SendCount==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&SendQueue[SendNext]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Get_Send -- gets ptr to queue entry                     *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessable queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nSendQueueType * CommQueueClass::Get_Send(int index)\n{\n\tint i;\n\n\ti = SendNext + index;\n\tif (i >= MaxSend) {\n\t\ti -= MaxSend;\n\t}\n\n\tif (SendQueue[i].IsActive==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&SendQueue[i]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Queue_Receive -- queues a received message\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing the message\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no room in the queue\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::Queue_Receive(void *buf, int buflen)\n{\n\t/*\n\t**\tError if no room in the queue\n\t*/\n\tif (ReceiveCount==MaxReceive || ReceiveQueue[ReceiveEmpty].IsActive!=0) {\n\t\treturn(0); \n\t}\n\n\t/*\n\t**\tSet entry flags\n\t*/\n\tReceiveQueue[ReceiveEmpty].IsActive = 1;\n\tReceiveQueue[ReceiveEmpty].IsRead = 0;\n\tReceiveQueue[ReceiveEmpty].IsACK = 0;\n\tReceiveQueue[ReceiveEmpty].BufLen = buflen;\n\n\t/*\n\t**\tCopy the packet data\n\t*/\n\tmemcpy(ReceiveQueue[ReceiveEmpty].Buffer,buf,buflen);\n\n\t/*\n\t**\tIncrement counters & entry ptr \n\t*/\n\tReceiveCount++;\n\tReceiveEmpty++;\n\tif (ReceiveEmpty==MaxReceive) {\n\t\tReceiveEmpty = 0;\n\t}\n\n\tReceiveTotal++;\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::UnQueue_Receive -- removes next entry from send queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store entry's data in; if NULL, it's discarded\t*\n *\t\tbuflen\t\tfilled in with length of entry retrieved\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = no entry to retreive\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint CommQueueClass::UnQueue_Receive(void *buf, int *buflen)\n{\n\t/*\n\t**\tError if no entry to retrieve \n\t*/\n\tif (ReceiveCount==0 || ReceiveQueue[ReceiveNext].IsActive==0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tCopy the data from the entry\n\t*/\n\tif (buf!=NULL) {\n\t\tmemcpy(buf,ReceiveQueue[ReceiveNext].Buffer,\n\t\t\tReceiveQueue[ReceiveNext].BufLen);\n\t\t(*buflen) = ReceiveQueue[ReceiveNext].BufLen;\n\t}\n\n\t/*\n\t**\tSet entry flags\n\t*/\n\tReceiveQueue[ReceiveNext].IsActive = 0;\n\tReceiveQueue[ReceiveNext].IsRead = 0;\n\tReceiveQueue[ReceiveNext].IsACK = 0;\n\tReceiveQueue[ReceiveNext].BufLen = 0;\n\tReceiveCount--;\n\tReceiveNext++;\n\tif (ReceiveNext==MaxReceive) {\n\t\tReceiveNext = 0;\n\t}\n\n\treturn(1);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Next_Receive -- gets ptr to next entry in send queue    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry, NULL if there is none.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommQueueClass::Next_Receive(void)\n{\n\tif (ReceiveCount==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&ReceiveQueue[ReceiveNext]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Get_Receive -- gets ptr to queue entry                  *\n *                                                                         *\n * This routine gets a pointer to the indicated queue entry.  The index\t\t*\n * value is relative to the next-accessable queue entry; 0 = get the\t\t\t*\n * next available queue entry, 1 = get the one behind that, etc.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tindex of entry to get (0 = 1st available)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to entry\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/21/1994 BR : Created.                                              *\n *=========================================================================*/\nReceiveQueueType * CommQueueClass::Get_Receive(int index)\n{\n\tint i;\n\n\ti = ReceiveNext + index;\n\tif (i >= MaxReceive) {\n\t\ti -= MaxReceive;\n\t}\n\n\tif (ReceiveQueue[i].IsActive==0) {\n\t\treturn(NULL);\n\t} else {\n\t\treturn(&ReceiveQueue[i]);\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Add_Delay -- adds a new delay value for response time   *\n *                                                                         *\n * This routine updates the average response time for this queue.  The\t\t*\n * computation is based on the average of the last 'n' delay values given,\t*\n * It computes a running total of the last n delay values, then divides \t*\n * that by n to compute the average.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * When the number of values given exceeds the max, the mean is subtracted\t*\n * off the total, then the new value is added in.  Thus, any single delay\t*\n * value will have an effect on the total that approaches 0 over time, and\t*\n * the new delay value contributes to 1/n of the mean.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdelay\t\t\tvalue to add into the response time computation\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Add_Delay(unsigned long delay)\n{\n\tint roundoff = 0;\n\n\tif (NumDelay==256) {\n\t\tDelaySum -= MeanDelay;\n\t\tDelaySum += delay;\n\t\tif ( (DelaySum & 0x00ff) > 127) {\n\t\t\troundoff = 1;\n\t\t}\n\t\tMeanDelay = (DelaySum >> 8) + roundoff;\n\t} else {\n\t\tNumDelay++;\n\t\tDelaySum += delay;\n\t\tMeanDelay = DelaySum / NumDelay;\n\t}\n\n\tif (delay > MaxDelay) {\n\t\tMaxDelay = delay;\n\t}\n}\n\n\n/***************************************************************************\n * CommQueueClass::Avg_Response_Time -- returns average response time    \t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommQueueClass::Avg_Response_Time(void)\n{\n\treturn(MeanDelay);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Max_Response_Time -- returns max response time    \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlatest computed average response time\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nunsigned long CommQueueClass::Max_Response_Time(void)\n{\n\treturn(MaxDelay);\n}\n\n\n/***************************************************************************\n * CommQueueClass::Reset_Response_Time -- resets computations\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid CommQueueClass::Reset_Response_Time(void)\n{\n\tDelaySum = 0L;\n\tNumDelay = 0L;\n\tMeanDelay = 0L;\n\tMaxDelay = 0L;\n}\n\n\n/*************************************************************************** \n * CommQueueClass::Configure_Debug -- sets up special debug values         * \n *                                                                         * \n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\toffset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t\t*\n *\t\tsize\t\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\tptr to array of names; use ID as an index into this\t\t*\n *\t\tmaxnames\t\tmax # in the names array; 0 if none.\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/31/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Configure_Debug(int offset, int size, char **names, \n\tint maxnames)\n{\n\tDebugOffset = offset;\n\tDebugSize = size;\n\tDebugNames = names;\n\tDebugMaxNames = maxnames;\n}\n\n\n/*************************************************************************** \n * Mono_Debug_Print -- Debug output routine                                * \n *                                                                         * \n * This routine leaves 5 lines at the top for the caller's use.\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/02/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Mono_Debug_Print(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tstatic int send_col[] = {1,14,28};\t\t\t// coords of send queue columns\n\tstatic int receive_col[] = {40,54,68};\t\t// coords of recv queue columns\n\tint row,col;\t\t\t\t\t\t\t\t\t\t// current row,col for printing\n\tint num;\t\t\t\t\t\t\t\t\t\t\t\t// max # items to print\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t/*\n\t**\tIf few enough entries, call the verbose debug version\n\t*/\n\tif (MaxSend <= 16) {\n\t\tMono_Debug_Print2(refresh);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tRefresh the screen\n\t*/\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct ACK   ID  Ct ACK    ID  Ct ACK ID  Rd ACK    ID  Rd ACK   ID  Rd ACK\\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t/*\n\t**\tPrint Send Queue items\n\t*/\n\tif (MaxSend <= 48) {\n\t\tnum = MaxSend;\n\t} else {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (send_col[col],row + 8);\n\t\tif (SendQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tMono_Printf (\"%4d %2d  %d\",hdr->PacketID, SendQueue[i].SendCount,\n\t\t\t\tSendQueue[i].IsACK);\n\t\t} else {\n\t\t\tMono_Printf (\"____ __  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n\t/*\n\t**\tPrint Receive Queue items\n\t*/\n\tif (MaxReceive <= 48) {\n\t\tnum = MaxSend;\n\t} else {\n\t\tnum = 48;\n\t}\n\tcol = 0;\n\trow = 0;\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (receive_col[col],row + 8);\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\tMono_Printf (\"%4d  %d  %d\",hdr->PacketID, ReceiveQueue[i].IsRead,\n\t\t\t\tReceiveQueue[i].IsACK);\n\t\t} else {\n\t\t\tMono_Printf (\"____  _  _ \");\n\t\t}\n\n\t\trow++;\n\t\tif (row > 15) {\n\t\t\trow = 0;\n\t\t\tcol++;\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\t\n}\n\n\n/*************************************************************************** \n * CommQueueClass::Mono_Debug_Print2 -- Debug output; alternate format     * \n *                                                                         * \n * This routine prints more information than the other version; it's\t\t\t*\n * called only if the number of queue entries is small enough to support\t*\n * this format.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * INPUT:                                                                  * \n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         * \n * OUTPUT:                                                                 * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * WARNINGS:                                                               * \n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         * \n * HISTORY:                                                                * \n *   05/31/1995 BRR : Created.                                             * \n *=========================================================================*/\nvoid CommQueueClass::Mono_Debug_Print2(int refresh)\n{\n#ifdef WWLIB32_H\n\tint i;\t\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[80];\n\tint val;\n\n\tstruct CommHdr {\t\t\t\t\t\t\t\t\t// this mirrors the CommHeaderType\n\t\tunsigned short MagicNumber;\n\t\tunsigned char Code;\n\t\tunsigned long PacketID;\n\t} *hdr;\n\n\t/*\n\t**\tRefresh the screen\n\t*/\n\tif (refresh) {\n\t\tMono_Clear_Screen ();\n\t\tMono_Printf(\"Ŀ\\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"                                                                             \\n\");\n\t\tMono_Printf(\"Ĵ\\n\");\n\t\tMono_Printf(\"              Send Queue                           Receive Queue            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\" ID  Ct Type   Data  Name         ACK  ID  Rd Type   Data  Name         ACK \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"                                                                            \\n\");\n\t\tMono_Printf(\"\");\n\t}\n\n\t/*\n\t**\tPrint Send Queue items\n\t*/\n\tfor (i = 0; i < MaxSend; i++) {\n\t\tMono_Set_Cursor (1,8 + i);\n\t\t\n\t\t/*\n\t\t**\tPrint an active entry\n\t\t*/\n\t\tif (SendQueue[i].IsActive) {\n\t\t\t\n\t\t\t/*\n\t\t\t**\tGet header info\n\t\t\t*/\n\t\t\thdr = (CommHdr *)SendQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tSendQueue[i].SendCount,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\n\t\t\t/*\n\t\t\t**\tDecode app's ID & its name\n\t\t\t*/\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(SendQueue[i].Buffer + DebugOffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (DebugSize==2) {\n\t\t\t\t\t\tval = *((short *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DebugSize==4) {\n\t\t\t\t\t\t\tval = *((int *)(SendQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t}\n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugMaxNames && val > 0 && val < DebugMaxNames) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\",\n\t\t\t\t\t\tDebugNames[val],\n\t\t\t\t\t\tSendQueue[i].IsACK);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",SendQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tEntry isn't active; print blanks\n\t\t\t*/\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n\t/*\n\t**\tPrint Receive Queue items\n\t*/\n\tfor (i = 0; i < MaxReceive; i++) {\n\t\tMono_Set_Cursor (40,8 + i);\n\t\t\n\t\t/*\n\t\t**\tPrint an active entry\n\t\t*/\n\t\tif (ReceiveQueue[i].IsActive) {\n\t\t\t\n\t\t\t/*\n\t\t\t**\tGet header info\n\t\t\t*/\n\t\t\thdr = (CommHdr *)ReceiveQueue[i].Buffer;\n\t\t\thdr->MagicNumber = hdr->MagicNumber;\n\t\t\thdr->Code = hdr->Code;\n\t\t\tsprintf(txt,\"%4d %2d %-5s  \",\n\t\t\t\thdr->PacketID,\n\t\t\t\tReceiveQueue[i].IsRead,\n\t\t\t\tConnectionClass::Command_Name(hdr->Code));\n\t\t\t\n\t\t\t/*\n\t\t\t**\tDecode app's ID & its name\n\t\t\t*/\n\t\t\tif (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {\n\t\t\t\tif (DebugSize==1) {\n\t\t\t\t\tval = *(ReceiveQueue[i].Buffer + DebugOffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (DebugSize==2) {\n\t\t\t\t\t\tval = *((short *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DebugSize==4) {\n\t\t\t\t\t\t\tval = *((int *)(ReceiveQueue[i].Buffer + DebugOffset));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\tsprintf(txt + strlen(txt),\"%4d  \",val);\n\n\t\t\t\tif (DebugMaxNames && val > 0 && val < DebugMaxNames) {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"%-12s  %x\", DebugNames[val], ReceiveQueue[i].IsACK);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt + strlen(txt),\"              %x\",ReceiveQueue[i].IsACK);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tEntry isn't active; print blanks\n\t\t\t*/\n\t\t\tMono_Printf(\"____ __                            _\");\n\t\t}\n\t}\n\n#else\n\trefresh = refresh;\n#endif\t\n}\n\n\n#endif"
  },
  {
    "path": "REDALERT/COMQUEUE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\comqueue.h_v   4.1   11 Apr 1996 18:26:02   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : COMQUEUE.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class's job is to queue up outgoing messages & incoming messages, \t*\n * and serves as a storage area for various flags for ACK & Retry logic.\t*\n * It allows the application to keep track of how many messages have \t\t*\n * passed through this queue, in & out, so packets can use this as a \t\t*\n * unique ID.  (If packets have a unique ID, the application can use this \t*\n * to detect re-sends.)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The queues act as FIFO buffers (First-In, First-Out).  The first entry\t*\n * placed in a queue is the first one read from it, and so on.  The\t\t\t*\n * controlling application must ensure it places the entries on the queue\t*\n * in the order it wants to access them.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The queue is implemented as an array of Queue Entries.  Index 0 is the\t*\n * first element placed on the queue, and is the first retrieved.  Index\t*\n * 1 is the next, and so on.  When Index 0 is retrieved, the next-available*\n * entry becomes Index 1.  The array is circular; when the end is reached,\t*\n * the indices wrap around to the beginning.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The class also contains routines to maintain a cumulative response time\t*\n * for this queue.  It's up to the caller to call Add_Delay() whenever\t\t*\n * it detects that an outgoing message has been ACK'd; this class adds\t\t*\n * that delay into a computed average delay over the last few message \t\t*\n * delays.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef COMQUEUE_H\n#define COMQUEUE_H\n\n\n\n/*---------------------------------------------------------------------------\nThis is one output queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK received for this packet\n\tunsigned long FirstTime;\t\t// time this packet was first sent\n\tunsigned long LastTime;\t\t\t// time this packet was last sent\n\tunsigned long SendCount;\t\t// # of times this packet has been sent\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n} SendQueueType;\n\n/*---------------------------------------------------------------------------\nThis is one input queue entry\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned int IsActive\t: 1;\t// 1 = this entry is ready to be processed\n\tunsigned int IsRead\t\t: 1;\t// 1 = caller has read this entry\n\tunsigned int IsACK\t\t: 1;\t// 1 = ACK sent for this packet\n\tint BufLen;\t\t\t\t\t\t\t// size of the packet stored in this entry\n\tchar *Buffer;\t\t\t\t\t\t// the data packet\n} ReceiveQueueType;\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass CommQueueClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*\n\t\t....................... Constructor/Destructor ........................\n\t\t*/\n\t\tCommQueueClass(int numsend, int numrecieve, int maxlen);\n\t\tvirtual ~CommQueueClass();\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t......................... Send Queue routines .........................\n\t\t*/\n\t\tint Queue_Send(void *buf, int buflen);\t\t\t// add to Send queue\n\t\tint UnQueue_Send(void *buf, int *buflen);\t\t// remove from Send queue\n\t\tSendQueueType * Next_Send(void);\t\t\t\t\t// ptr to next avail entry\n\t\tint Num_Send(void) {return (SendCount);}\t\t// # entries in queue\n\t\tint Max_Send(void) { return (MaxSend);}\t\t// max # send queue entries\n\t\tSendQueueType * Get_Send(int index);\t\t\t// random access to queue\n\t\tunsigned long Send_Total(void) {return (SendTotal);}\n\n\t\t/*\n\t\t....................... Receive Queue routines ........................\n\t\t*/\n\t\tint Queue_Receive(void *buf, int buflen);\t\t// add to Receive queue\n\t\tint UnQueue_Receive(void *buf, int *buflen);\t// remove from Receive queue\n\t\tReceiveQueueType * Next_Receive(void);\t\t\t// ptr to next avail entry\n\t\tint Num_Receive(void) {return (ReceiveCount);}\t// # entries in queue\n\t\tint Max_Receive(void) { return (MaxReceive); }\t// max # recv queue entries\n\t\tReceiveQueueType * Get_Receive(int index);\t// random access to queue\n\t\tunsigned long Receive_Total(void) {return (ReceiveTotal);}\n\n\t\t/*\n\t\t....................... Response time routines ........................\n\t\t*/\n\t\tvoid Add_Delay(unsigned long delay);\t// accumulates response time\n\t\tunsigned long Avg_Response_Time(void);\t// gets mean response time\n\t\tunsigned long Max_Response_Time(void);\t// gets max response time\n\t\tvoid Reset_Response_Time(void);\t\t\t// resets computations\n\n\t\t/*\n\t\t........................ Debug output routines ........................\n\t\t*/\n\t\tvoid Configure_Debug(int offset, int size, char **names, int maxnames);\n\t\tvoid Mono_Debug_Print(int refresh = 0);\n\t\tvoid Mono_Debug_Print2(int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*\n\t\t.......................... Limiting variables .........................\n\t\t*/\n\t\tint MaxSend;\t\t\t\t\t\t\t// max # send queue entries\n\t\tint MaxReceive;\t\t\t\t\t\t// max # receive queue entries\n\t\tint MaxPacketSize;\t\t\t\t\t// max size of a packet, in bytes\n\n\t\t/*\n\t\t....................... Response time variables .......................\n\t\t*/\n\t\tunsigned long DelaySum;\t\t\t\t// sum of last 4 delay times\n\t\tunsigned long NumDelay;\t\t\t\t// current # delay times summed\n\t\tunsigned long MeanDelay;\t\t\t// current average delay time\n\t\tunsigned long MaxDelay;\t\t\t\t// max delay ever for this queue\n\n\t\t/*\n\t\t........................ Send Queue variables .........................\n\t\t*/\n\t\tSendQueueType * SendQueue;\t\t\t// incoming packets\n\t\tint SendCount; \t\t\t\t\t\t// # packets in the queue\n\t\tint SendNext;\t\t\t\t\t\t\t// next entry read from queue\n\t\tint SendEmpty;\t\t\t\t\t\t\t// next empty spot in queue\n\t\tunsigned long SendTotal;\t\t\t// total # added to send queue\n\n\t\t/*\n\t\t....................... Receive Queue variables .......................\n\t\t*/\n\t\tReceiveQueueType * ReceiveQueue;\t\t// outgoing packets\n\t\tint ReceiveCount;\t\t\t\t\t\t\t// # packets in the queue\n\t\tint ReceiveNext;\t\t\t\t\t\t\t// next entry read from queue\n\t\tint ReceiveEmpty;\t\t\t\t\t\t\t// next empty spot in queue\n\t\tunsigned long ReceiveTotal;\t\t\t// total # added to receive queue\n\n\t\t/*\n\t\t......................... Debugging Variables .........................\n\t\t*/\n\t\tint DebugOffset;\t\t\t\t\t\t\t// offset into app's packet for ID\n\t\tint DebugSize;\t\t\t\t\t\t\t\t// size of app's ID\n\t\tchar **DebugNames;\t\t\t\t\t\t// ptr to array of app-specific names\n\t\tint DebugMaxNames;\t\t\t\t\t\t// max # of names in array\n};\n\n#endif\n\n/*************************** end of comqueue.h *****************************/\n\n"
  },
  {
    "path": "REDALERT/CONFDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\confdlg.cpv   4.67   27 Aug 1996 15:46:52   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONFDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                  Joe L. Bostic                                              *\n *                                                                                             *\n *                   Start Date : Jan 30, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 30, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ConfirmationClass::Process -- Handles all the options graphic interface.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"confdlg.h\"\n\n\nbool ConfirmationClass::Process(int text)\n{\n\ttext;\n\treturn true;\n\t//return(Process(Text_String(text)));\n}\n\n#if (0) // ST - 5/8/2019\n/***********************************************************************************************\n * ConfirmationClass::Process -- Handles all the options graphic interface.                    *\n *                                                                                             *\n *    This dialog uses an edit box to confirm a deletion.                                      *\n *                                                                                             *\n * INPUT:   \tchar * string - display in edit box.                                            *\n *                                                                                             *\n * OUTPUT:  \tnone                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nbool ConfirmationClass::Process(char const * string)\n{\n\tenum {\n\t\tNUM_OF_BUTTONS = 2\n\t};\n\n\tchar buffer[80*3];\n\tint result = true;\n\tint width;\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint height;\n\tint selection = 0;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tstrcpy(buffer, string);\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, 200, width, height);\n\twidth += 60;\n\theight += 60;\n\tint x = (320 - width) / 2;\n\tint y = (200 - height) / 2;\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.  Button coords are in pixels, but are window-relative.\n\t*/\n\tbheight = FontHeight + FontYSpacing + 2;\n\tbwidth = max( (String_Pixel_Width( Text_String( TXT_YES ) ) + 8), 30);\n\n\tTextButtonClass yesbtn(BUTTON_YES, TXT_YES,\n\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\tx + 10, y + height - (bheight + 5), bwidth );\n\n\tTextButtonClass nobtn(BUTTON_NO, TXT_NO,\n\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\tx + width - (bwidth + 10),\n\t\ty + height - (bheight + 5), bwidth );\n\n\tnobtn.Add_Tail(yesbtn);\n\n\tcurbutton = 1;\n\tbuttons[0] = &yesbtn;\n\tbuttons[1] = &nobtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\tGadgetClass dialog(x, y, width, height, GadgetClass::LEFTPRESS);\n\tdialog.Add_Tail(yesbtn);\n\n\t/*\n\t**\tThis causes a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to options dialog.\n\t*/\n\tControlClass background(BUTTON_NO, 0, 0, 320, 200, GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);\n\tbackground.Add_Tail(yesbtn);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\tpressed = false;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t\tresult = false;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(x, y, width, height);\n\t\t\tDraw_Caption(TXT_CONFIRMATION, x, y, width);\n\t\t\tFancy_Text_Print(buffer, x+20, y+30, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tDraw the titles.\n\t\t\t*/\n\t\t\tyesbtn.Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = yesbtn.Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase KeyNumType(BUTTON_YES | KN_BUTTON):\n\t\t\t\tselection = BUTTON_YES;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase KeyNumType(BUTTON_NO | KN_BUTTON):\n\t\t\t\tselection = BUTTON_NO;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = NUM_OF_BUTTONS - 1;\n\t\t\t\t}\n\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (NUM_OF_BUTTONS - 1) ) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_YES;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_YES):\n\t\t\t\t\tresult = true;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_NO):\n\t\t\t\t\tresult  = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n\treturn(result);\n}\n#endif"
  },
  {
    "path": "REDALERT/CONFDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\confdlg.h_v   4.69   27 Aug 1996 15:43:36   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONFDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : Jan 30, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 30, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*/\n\n#ifndef CONFDLG_H\n#define CONFDLG_H\n\n#include \"gadget.h\"\n\nclass ConfirmationClass\n{\n\tprivate:\n\t\tenum ConfirmationClassEnum {\n\t\t\tBUTTON_YES=1,\t\t\t\t\t\t\t\t// Button number for \"Options menu\"\n\t\t\tBUTTON_NO\t\t\t\t\t\t\t\t\t// Button number for \"Options menu\"\n\t\t};\n\n\tpublic:\n\t\tConfirmationClass(void) {  };\n\t\tbool Process(char const * string);\n\t\tbool Process(int text);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CONNECT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONNECT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : May 31, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   ConnectionClass::ConnectionClass -- class constructor                 *\n *   ConnectionClass::~ConnectionClass -- class destructor                 *\n *   ConnectionClass::Init -- Initializes connection queue to empty\t\t\t*\n *   ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *   ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *   ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *   ConnectionClass::Service -- main polling routine; services packets\t\t*\n *   ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t*\n *   ConnectionClass::Service_Receive_Queue -- services receive queue\t\t*\n *   ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *   ConnectionClass::Command_Name -- returns name for a packet command\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n\n#include\t\"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n#include <sys\\timeb.h>\n#include \"connect.h\"\n\n//#include \"WolDebug.h\"\n\n/*\n********************************* Globals ***********************************\n*/\nchar *ConnectionClass::Commands[PACKET_COUNT] = {\n\t\"ADATA\",\n\t\"NDATA\",\n\t\"ACK\"\n};\n\n\n/***************************************************************************\n * ConnectionClass::ConnectionClass -- class constructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\textralen\t\t\tmax size of app-specific extra bytes (optional)\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::ConnectionClass (int numsend, int numreceive,\n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout, int extralen)\n{\n\t/*------------------------------------------------------------------------\n\tCompute our maximum packet length\n\t------------------------------------------------------------------------*/\n\tMaxPacketLen = maxlen + sizeof(CommHeaderType);\n\n\t/*------------------------------------------------------------------------\n\tAssign the magic number\n\t------------------------------------------------------------------------*/\n\tMagicNum = magicnum;\n\n\t/*------------------------------------------------------------------------\n\tInitialize the retry time.  This is the time that t2 - t1 must be greater\n\tthan before a retry will occur.\n\t------------------------------------------------------------------------*/\n\tRetryDelta = retry_delta;\n\n\t/*------------------------------------------------------------------------\n\tSet the maximum allowable retries.\n\t------------------------------------------------------------------------*/\n\tMaxRetries = max_retries;\n\n\t/*------------------------------------------------------------------------\n\tSet the timeout for this connection.\n\t------------------------------------------------------------------------*/\n\tTimeout = timeout;\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet staging buffer.  This will be used to\n\t------------------------------------------------------------------------*/\n\tPacketBuf = new char[ MaxPacketLen ];\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (placed there\n\tby Receive_Packet), and outgoing packets (placed there by Send_Packet).\n\tIt can optionally store \"extra\" bytes, which are stored along with each\n\tpacket, but aren't transmitted as part of the packet.  If 'extralen'\n\tis 0, the CommBufferClass ignores this parameter.\n\t------------------------------------------------------------------------*/\n\tQueue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);\n\n}\t/* end of ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::~ConnectionClass -- class destructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nConnectionClass::~ConnectionClass ()\n{\n\t/*------------------------------------------------------------------------\n\tFree memory.\n\t------------------------------------------------------------------------*/\n\tdelete [] PacketBuf;\n\tdelete Queue;\n\n}\t/* end of ~ConnectionClass */\n\n\n/***************************************************************************\n * ConnectionClass::Init -- Initializes connection queue to empty\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid ConnectionClass::Init (void)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\tLastSeqID = 0xffffffff;\n\tLastReadID = 0xffffffff;\n\n\tQueue->Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * ConnectionClass::Send_Packet -- adds a packet to the send queue\t\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK is required for this packet; 0 = isn't\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*------------------------------------------------------------------------\n\tSet the magic # for the packet\n\t------------------------------------------------------------------------*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*------------------------------------------------------------------------\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t------------------------------------------------------------------------*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t}\n\telse {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow build the packet\n\t------------------------------------------------------------------------*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*------------------------------------------------------------------------\n\tAdd it to the queue; don't add any extra data with it.\n\t------------------------------------------------------------------------*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {\n\t\tif (ack_req) {\n\t\t\tNumSendAck++;\n\t\t}\n\t\telse {\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Send_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Receive_Packet -- adds packet to receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t\t\t\t// ptr to packet header\n\tSendQueueType *send_entry;\t\t\t\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t\t\t\t// ptr to recv entry header\n\tCommHeaderType *entry_data;\t\t\t\t\t\t// ptr to queue entry data\n\tCommHeaderType ackpacket;\t\t\t\t\t\t\t// ACK packet to send\n\tint i;\n\tint save_packet = 1;\t\t\t\t\t\t\t\t\t// 0 = this is a resend\n\tint found;\n\n\t/*------------------------------------------------------------------------\n\tCheck the magic #\n\t------------------------------------------------------------------------*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber != MagicNum) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming ACK\n\t------------------------------------------------------------------------*/\n\tif (packet->Code == PACKET_ACK) {\n\n\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t/*..................................................................\n\t\t\tGet queue entry ptr\n\t\t\t..................................................................*/\n\t\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t\t/*..................................................................\n\t\t\tIf ptr is valid, get ptr to its data\n\t\t\t..................................................................*/\n\t\t\tif (send_entry != NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ACK is for this entry, mark it\n\t\t\t\t...............................................................*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID &&\n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_NOACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_NOACK) {\n\t\t/*.....................................................................\n\t\tIf there's only one slot left, don't tie up the queue with this packet\n\t\t.....................................................................*/\n\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\treturn(0);\n\t\t}\n\n\t\t/*.....................................................................\n\t\tError if we can't queue the packet\n\t\t.....................................................................*/\n\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\treturn(0);\n\t\t}\n\n\t\tNumRecNoAck++;\n\n\t\treturn(1);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_ACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_ACK) {\n\t\t/*.....................................................................\n\t\tIf this is a packet requires an ACK, and it's ID is older than our\n\t\t\"oldest\" ID, we know it's a resend; send an ACK, but don't queue it\n\t\t.....................................................................*/\n\t\tif (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {\n\t\t\tsave_packet = 0;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOtherwise, scan the queue for this entry; if it's found, it's a\n\t\tresend, so don't save it.\n\t\t.....................................................................*/\n\t\telse {\n\t\t\tsave_packet = 1;\n\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\tif (rec_entry) {\n\n\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t/*...........................................................\n\t\t\t\t\tPacket is found; it's a resend\n\t\t\t\t\t...........................................................*/\n\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\tentry_data->PacketID == packet->PacketID) {\n\t\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t/* end of scan for resend */\n\n\t\t/*.....................................................................\n\t\tQueue the packet & update our LastSeqID value.\n\t\t.....................................................................*/\n\t\tif (save_packet) {\n\t\t\t/*..................................................................\n\t\t\tIf there's only one slot left, make sure we only put a packet in it\n\t\t\tif this packet will let us increment our LastSeqID; otherwise, we'll\n\t\t\tget stuck, forever unable to increment LastSeqID.\n\t\t\t..................................................................*/\n\t\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\t\tif (packet->PacketID != (LastSeqID + 1) ) {\n\t\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tIf we can't queue the packet, return; don't send an ACK.\n\t\t\t..................................................................*/\n\t\t\tif (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\tNumRecAck++;\n\n\t\t\t/*..................................................................\n\t\t\tUpdate our LastSeqID value if we can.  Anything less than LastSeqID\n\t\t\twe'll know is a resend.\n\t\t\t..................................................................*/\n\t\t\tif (packet->PacketID == (LastSeqID + 1)) {\n\t\t\t\tLastSeqID = packet->PacketID;\n\t\t\t\t/*...............................................................\n\t\t\t\tNow that we have a new 'LastSeqID', search our Queue to see if\n\t\t\t\tthe next ID is there; if so, keep checking for the next one;\n\t\t\t\tbreak only when the next one isn't found.  This forces\n\t\t\t\tLastSeqID to be the largest possible value.\n\t\t\t\t...............................................................*/\n\t\t\t\tdo {\n\t\t\t\t\tfound = 0;\n\t\t\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\t\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t\t\t/*......................................................\n\t\t\t\t\t\t\tEntry is found\n\t\t\t\t\t\t\t......................................................*/\n\t\t\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\t\t\tentry_data->PacketID == (LastSeqID + 1)) {\n\n\t\t\t\t\t\t\t\tLastSeqID = entry_data->PacketID;\n\t\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} while (found);\n\t\t\t}\n\t\t}\t/* end of save packet */\n\n\t\t/*.....................................................................\n\t\tSend an ACK, regardless of whether this was a resend or not.\n\t\t.....................................................................*/\n\t\tackpacket.MagicNumber = Magic_Num();\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet->PacketID;\n\t\tSend ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);\n\n\t\treturn(1);\n\t}\n\n\treturn(0);\n\n}\t/* end of Receive_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Get_Packet -- gets a packet from receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\tCommHeaderType *entry_data;\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tEnsure that we read the packets in order.  LastReadID is the ID of the\n\tlast PACKET_DATA_ACK packet we read.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t/*.....................................................................\n\t\tOnly read this entry if it hasn't been yet\n\t\t.....................................................................*/\n\t\tif (rec_entry && rec_entry->IsRead==0) {\n\n\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_ACK packet, its ID must be one greater than\n\t\t\tthe last one we read.\n\t\t\t..................................................................*/\n\t\t\tif ( (entry_data->Code == PACKET_DATA_ACK) &&\n\t\t\t\t(entry_data->PacketID == (LastReadID + 1))) {\n\n\t\t\t\tLastReadID = entry_data->PacketID;\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_NOACK packet, who cares what the ID is?\n\t\t\t..................................................................*/\n\t\t\telse if (entry_data->Code == PACKET_DATA_NOACK) {\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),\n\t\t\t\t\t\tpacketlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(1);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Packet */\n\n\n/***************************************************************************\n * ConnectionClass::Service -- main polling routine; services packets\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error (connection is broken!)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service (void)\n{\n\t/*------------------------------------------------------------------------\n\tService the Send Queue:  This [re]sends packets in the Send Queue which\n\thaven't been ACK'd yet, and if their retry timeout has expired, and\n\tupdates the FirstTime, LastTime & SendCount values in the Queue entry.\n\tEntries that have been ACK'd should be removed.\n\n\tService the Receive Queue:  This sends ACKs for packets that haven't\n\tbeen ACK'd yet.  Entries that the app has read, and have been ACK'd,\n\tshould be removed.\n\t------------------------------------------------------------------------*/\n\tif ( Service_Send_Queue() && Service_Receive_Queue() ) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Service */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Send_Queue -- services the send queue\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Send_Queue (void)\n{\n\tint i;\n\tint num_entries;\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\tint bad_conn = 0;\n\n\t/*------------------------------------------------------------------------\n\tRemove any ACK'd packets from the queue\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t/*.....................................................................\n\t\tGet this queue entry\n\t\t.....................................................................*/\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t/*.....................................................................\n\t\tIf ACK has been received, unqueue it\n\t\t.....................................................................*/\n\t\tif (send_entry->IsACK) {\n\n\t\t\t/*..................................................................\n\t\t\tUpdate this queue's response time\n\t\t\t..................................................................*/\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUnqueue the packet\n\t\t\t..................................................................*/\n\t\t\tQueue->UnQueue_Send(NULL,NULL,i,NULL,NULL);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tLoop through all entries in the Send queue.  [Re]Send any entries that\n\tneed it.\n\t------------------------------------------------------------------------*/\n\tnum_entries = Queue->Num_Send();\n\n\tfor (i = 0; i < num_entries; i++) {\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\tif (send_entry->IsACK) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\n\t\t\t/*..................................................................\n\t\t\tSend the message\n\t\t\t..................................................................*/\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,\n\t\t\t\tsend_entry->ExtraLen);\n\n\t\t\t/*..................................................................\n\t\t\tFill in Time fields\n\t\t\t..................................................................*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tUpdate SendCount\n\t\t\t..................................................................*/\n\t\t\tsend_entry->SendCount++;\n\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\n\t\t\tif (Timeout != -1 &&\n\t\t\t\t(send_entry->LastTime - send_entry->FirstTime) > Timeout) {\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the connection is going bad, return an error\n\t------------------------------------------------------------------------*/\n\tif (bad_conn) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n}\t/* end of Service_Send_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Service_Receive_Queue -- services receive queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint ConnectionClass::Service_Receive_Queue (void)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tRemove all dead packets.\n\tPACKET_DATA_NOACK: if it's been read, throw it away.\n\tPACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,\n\tthrow it away.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\n\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\n\t\t\t}\n\t\t\telse if (packet_hdr->PacketID < LastSeqID) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(1);\n\n}\t/* end of Service_Receive_Queue */\n\n\n/***************************************************************************\n * ConnectionClass::Time -- gets current time\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nunsigned long ConnectionClass::Time (void)\n{\n\tstatic struct timeb mytime;\t\t\t// DOS time\n\tunsigned long msec;\n\n#ifdef WWLIB32_H\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood timer system has been activated, use TickCount's value\n\t------------------------------------------------------------------------*/\n\tif (TimerSystemOn) {\n\t\treturn(TickCount);\t\t\t\t// Westwood Library time\n\t}\n\t/*------------------------------------------------------------------------\n\tOtherwise, use the DOS timer\n\t------------------------------------------------------------------------*/\n\telse {\n\t\tftime(&mytime);\n\t\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\t\treturn((msec / 100) * 6);\n\t}\n\n#else\n\n\t/*------------------------------------------------------------------------\n\tIf the Westwood library isn't being used, use the DOS timer.\n\t------------------------------------------------------------------------*/\n\tftime(&mytime);\n\tmsec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;\n\treturn((msec / 100) * 6);\n\n#endif\n\n}\t/* end of Time */\n\n\n/***************************************************************************\n * ConnectionClass::Command_Name -- returns name for given packet command  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcommand\t\tpacket Command value to get name for\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to command name, NULL if invalid\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar *ConnectionClass::Command_Name(int command)\n{\n\tif (command >= 0 && command < PACKET_COUNT) {\n\t\treturn(Commands[command]);\n\t}\n\telse {\n\t\treturn(NULL);\n\t}\n\n}\t/* end of Command_Name */\n\n/************************** end of connect.cpp *****************************/\n\n\n"
  },
  {
    "path": "REDALERT/CONNECT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONNECT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 1, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * DESCRIPTION:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class represents a single \"connection\" with another system.  It's\t*\n * a pure virtual base class that acts as a framework for other classes.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class contains a CommBufferClass member, which stores received\t\t*\n * & transmitted packets.  The ConnectionClass has virtual functions to\t\t*\n * handle adding packets to the queue, reading them from the queue,\t\t\t*\n * a Send routine for actually sending data, and a Receive_Packet function *\n * which is used to tell the connection that a new packet has come in.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The virtual Service routines handle all ACK & Retry logic for\t\t\t\t*\n * communicating between this system & another.  Thus, any class derived\t*\n * from this class may overload the basic ACK/Retry logic.\t\t\t\t\t\t*\n *                                                                         *\n * THE PACKET HEADER:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The Connection Classes prefix every packet sent with a header that's\t\t*\n * local to this class.  The header contains a \"Magic Number\" which should\t*\n * be unique for each product, and Packet \"Code\", which will tell the\t\t*\n * receiving end if this is DATA, or an ACK packet, and a packet ID, which\t*\n * is a unique numerical ID for this packet (useful for detecting resends).*\n * The header is stored with each packet in the send & receive Queues; \t\t*\n * it's removed before it's passed back to the application, via\t\t\t\t*\n * Get_Packet()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * THE CONNECTION MANAGER:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * It is assumed that there will be a \"Connection Manager\" class which \t\t*\n * will handle parsing incoming packets; it will then tell the connection\t*\n * that new packets have come in, and the connection will process them in\t*\n * whatever way it needs to for its protocol (check for resends, handle\t\t*\n * ACK packets, etc).  The job of the connection manager is to parse\t\t\t*\n * incoming packets & distribute them to the connections that need to\t\t*\n * store them (for multi-connection protocols).\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * NOTES ON ACK/RETRY:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class provides a \"non-sequenced\" ACK/Retry approach to packet\t\t*\n * transmission.  It sends out as many packets as are in the queue, whose\t*\n * resend delta times have expired; and it ACK's any packets its received\t*\n * who haven't been ACK'd yet.  Thus, order of delivery is NOT guaranteed;\t*\n * but, the performance is better than a \"sequenced\" approach.  Also, the\t*\n * Packet ID scheme (see below) ensures that the application will read\t\t*\n * the packets in the proper order.  Thus, this class guarantees delivery\t*\n * and order of deliver.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Each packet has a unique numerical ID; the ID is set to a count of the\t*\n * number of packets sent.  Different count values are provided, for both \t*\n * DATA_ACK & DATA_NOACK packets.  This ensures that the counter can be \t*\n * used to detect resends of DATA_ACK packets; the counters for DATA_NOACK *\n * packets aren't currently used.  Other counters keep track of the \t\t\t*\n * last-sequentially-received packet ID (for DATA_ACK packets), so we\t\t*\n * can check for resends & missed packets, and the last-sequentially-read\t*\n * packet ID, so we can ensure the app reads the packets in order.\t\t\t*\n *                                                                         *\n * If the protocol being used already guarantees delivery of packets,\t\t*\n * no ACK is required for the packets.  In this case, the connection\t\t\t*\n * class for this protocol can overload the Service routine to avoid\t\t\t*\n * sending ACK packets, or the Connection Manager can just mark the\t\t\t*\n * packet as ACK'd when it adds it to the Receive Queue for the connection.*\n *                                                                         *\n *\tDerived classes must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef CONNECTION_H\n#define CONNECTION_H\n\n/*\n********************************* Includes **********************************\n*/\n#include \"combuf.h\"\n\n/*\n********************************** Defines **********************************\n*/\n#define CONN_DEBUG\t0\n/*---------------------------------------------------------------------------\nThis structure is the header prefixed to any packet sent by the application.\nMagicNumber:\tThis is a number unique to the application; it's up to the\n\t\t\t\t\tReceive_Packet routine to check this value, to be sure we're\n\t\t\t\t\tnot getting data from some other product.  This value should\n\t\t\t\t\tbe unique for each application.\nCode:\t\t\t\tThis will be one of the below-defined codes.\nPacketID:\t\tThis is a unique numerical ID for this packet.  The Connection\n\t\t\t\t\tsets this ID on all packets sent out.\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tunsigned short MagicNumber;\n\tunsigned char Code;\n\tunsigned long PacketID;\n} CommHeaderType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tThese are the possible values for the Code field of the CommHeaderType:\n\t\t.....................................................................*/\n\t\tenum ConnectionEnum {\n\t\t\tPACKET_DATA_ACK,\t\t\t// this is a data packet requiring an ACK\n\t\t\tPACKET_DATA_NOACK,\t\t// this is a data packet not requiring an ACK\n\t\t\tPACKET_ACK,\t\t\t\t\t// this is an ACK for a packet\n\t\t\tPACKET_COUNT\t\t\t\t// for computational purposes\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tConnectionClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout, int extralen = 0);\n\t\tvirtual ~ConnectionClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int * buflen);\n\n\t\t/*.....................................................................\n\t\tThe main polling routine for the connection.  Should be called as often\n\t\tas possible.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void);\n\n\t\t/*.....................................................................\n\t\tThis routine is used by the retry logic; returns the current time in\n\t\t60ths of a second.\n\t\t.....................................................................*/\n\t\tstatic unsigned long Time (void);\n\n\t\t/*.....................................................................\n\t\tUtility routines.\n\t\t.....................................................................*/\n\t\tunsigned short Magic_Num (void) { return (MagicNum); }\n\t\tunsigned long Retry_Delta (void) { return (RetryDelta); }\n\t\tvoid Set_Retry_Delta (unsigned long delta) { RetryDelta = delta;}\n\t\tunsigned long Max_Retries (void) { return (MaxRetries); }\n\t\tvoid Set_Max_Retries (unsigned long retries) { MaxRetries = retries;}\n\t\tunsigned long Time_Out (void) { return (Timeout); }\n\t\tvoid Set_TimeOut (unsigned long t) { Timeout = t;}\n\t\tunsigned long Max_Packet_Len (void) { return (MaxPacketLen); }\n\t\tstatic char * Command_Name(int command);\n\n\t\t/*.....................................................................\n\t\tThe packet \"queue\"; this non-sequenced version isn't really much of\n\t\ta queue, but more of a repository.\n\t\t.....................................................................*/\n\t\tCommBufferClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue(void);\n\t\tvirtual int Service_Receive_Queue(void);\n\n\t\t/*.....................................................................\n\t\tThis routine actually performs a hardware-dependent data send.  It's\n\t\tpure virtual, so it must be defined by a derived class.  The routine\n\t\tis protected; it's only called by the ACK/Retry logic, not the\n\t\tapplication.\n\t\t.....................................................................*/\n\t\tvirtual int Send(char *buf, int buflen, void *extrabuf,\n\t\t\tint extralen) = 0;\n\n\t\t/*.....................................................................\n\t\tThis is the maximum packet length, including our own internal header.\n\t\t.....................................................................*/\n\t\tint MaxPacketLen;\n\n\t\t/*.....................................................................\n\t\tPacket staging area; this is where the CommHeaderType gets tacked onto\n\t\tthe application's packet before it's sent.\n\t\t.....................................................................*/\n\t\tchar *PacketBuf;\n\n\t\t/*.....................................................................\n\t\tThis is the magic number assigned to this connection.  It is the first\n\t\tfew bytes of any transmission.\n\t\t.....................................................................*/\n\t\tunsigned short MagicNum;\n\n\t\t/*.....................................................................\n\t\tThis value determines the time delay before a packet is re-sent.\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\n\t\t/*.....................................................................\n\t\tThis is the maximum number of retries allowed for a packet; if this\n\t\tvalue is exceeded, the connection is probably broken.\n\t\t.....................................................................*/\n\t\tunsigned long MaxRetries;\n\n\t\t/*.....................................................................\n\t\tThis is the total timeout for this connection; if this time is exceeded\n\t\ton a packet, the connection is probably broken.\n\t\t.....................................................................*/\n\t\tunsigned long Timeout;\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK,\n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the last consecutively-received packet; anything older\n\t\tthan this, we know is a resend.  Anything newer than this MUST be lying\n\t\taround in the Queue for us to detect it as a resend.\n\t\t.....................................................................*/\n\t\tunsigned long LastSeqID;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the PACKET_DATA_ACK packet we read last; it ensures\n\t\tthat the application reads that type of packet in order.\n\t\t.....................................................................*/\n\t\tunsigned long LastReadID;\n\n\t\t/*.....................................................................\n\t\tNames of all packet commands\n\t\t.....................................................................*/\n\t\tstatic char * Commands[PACKET_COUNT];\n};\n\n#endif\n\n/**************************** end of connect.h *****************************/\n"
  },
  {
    "path": "REDALERT/CONNMGR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONNMGR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNMGR.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager base class.  This is an abstract base\t\t*\n * class that's just a shell for more functional derived classes.\t\t\t\t*\n * The main job of the Connection Manager classes is to parse a \"pool\" of\t*\n * incoming packets, which may be from different computers, and distribute\t*\n * those packets to Connection Classes via their Receive_Packet function.\t*\n *                                                                         *\n * This class should be the only access to the network/modem for the\t\t\t*\n * application, so if the app needs any functions to access the \t\t\t\t*\n * connections or the queue's, the derived versions of this class should\t*\n * provide them.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * It's up to the derived class to define:\t\t\t\t\t\t\t\t\t\t\t*\n * - Service:\t\tpolling routine; should Service each connection\t\t\t\t*\n * - Init:\t\t\tinitialization; should perform hardware-dependent\t\t\t*\n *\t\t\t\t\t\tinitialization, then Init each connection; this function\t*\n *   \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n * - Send_Message:sends a packet across the connection (this function \t\t*\n * \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n * - Get_Message:\tgets a message from the connection (this function \t\t\t*\n * \t\t\t\t\tisn't defined in this class, since the parameters will \t*\n *\t\t\t\t\t\tbe highly protocol-dependent)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * If the derived class supports multiple connections, it should provide\t*\n * functions for creating the connections, associating them with a name\t\t*\n * or ID or both, destroying them, and sending data through all or any\t\t*\n * connection.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CONNMGR_H\n#define CONNMGR_H\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tVarious useful enums:\n\t\t.....................................................................*/\n\t\tenum IPXConnTag {\n\t\t\tCONNECTION_NONE = -1\t\t\t// value of an invalid connection ID\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/Destructor.  These currently do nothing.\n\t\t.....................................................................*/\n\t\tConnManClass (void) {};\n\t\tvirtual ~ConnManClass () {};\n\n\t\t/*.....................................................................\n\t\tThe Service routine:\n\t\t- Parses incoming packets, and adds them to the Receive Queue for the\n\t\t  Connection Class(s) for this protocol\n\t\t- Invokes each connection's Service routine; returns an error if the\n\t\t  connection's Service routine indicates an error.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void) = 0;\n\n\t\t/*.....................................................................\n\t\tSending & receiving data\n\t\t.....................................................................*/\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int conn_id = CONNECTION_NONE) = 0;\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen,\n\t\t\tint *conn_id) = 0;\n\n\t\t/*.....................................................................\n\t\tConnection management\n\t\t.....................................................................*/\n\t\tvirtual int Num_Connections(void) = 0;\n\t\tvirtual int Connection_ID(int index) = 0;\n\t\tvirtual int Connection_Index(int id) = 0;\n\n\t\t/*.....................................................................\n\t\tQueue utility routines\n\t\t.....................................................................*/\n\t\tvirtual int Global_Num_Send(void) = 0;\n\t\tvirtual int Global_Num_Receive(void) = 0;\n\t\tvirtual int Private_Num_Send(int id = CONNECTION_NONE) = 0;\n\t\tvirtual int Private_Num_Receive(int id = CONNECTION_NONE) = 0;\n\n\t\t/*.....................................................................\n\t\tTiming management\n\t\t.....................................................................*/\n\t\tvirtual void Reset_Response_Time(void) = 0;\n\t\tvirtual unsigned long Response_Time(void) = 0;\n\t\tvirtual void Set_Timing (unsigned long retrydelta,\n\t\t\tunsigned long maxretries, unsigned long timeout) = 0;\n\n\t\t/*.....................................................................\n\t\tDebugging\n\t\t.....................................................................*/\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount) = 0;\n#ifdef CHEAT_KEYS\n\t\tvirtual void Mono_Debug_Print(int index, int refresh) = 0;\n#endif\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*.....................................................................\n\t\tThis abstract class contains no data members; but a derived class\n\t\twill contain:\n\t\t- An instance of one or more derived Connection Classes\n\t\t- A buffer to store incoming packets\n\t\t.....................................................................*/\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CONQUER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONQUER.CPP 6     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONQUER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 3, 1991                                                *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CC_Draw_Shape -- Custom draw shape handler.                                               *\n *   Call_Back -- Main game maintenance callback routine.                                      *\n *   Color_Cycle -- Handle the general palette color cycling.                                  *\n *   Crate_From_Name -- Given a crate name convert it to a crate type.                         *\n *   Disk_Space_Available -- returns bytes of free disk space                                  *\n *   Do_Record_Playback -- handles saving/loading map pos & current object                     *\n *   Fading_Table_Name -- Builds a theater specific fading table name.                         *\n *   Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                    *\n *   Force_CD_Available -- Ensures that specified CD is available.                             *\n *   Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                         *\n *   Handle_Team -- Processes team selection command.                                          *\n *   Handle_View -- Either records or restores the tactical view.                              *\n *   KN_To_Facing -- Converts a keyboard input number into a facing value.                     *\n *   Keyboard_Process -- Processes the tactical map input codes.                               *\n *   Language_Name -- Build filename for current language.                                     *\n *   List_Copy -- Makes a copy of a cell offset list.                                          *\n *   Main_Game -- Main game startup routine.                                                   *\n *   Main_Loop -- This is the main game loop (as a single loop).                               *\n *   Map_Edit_Loop -- a mini-main loop for map edit mode only                                  *\n *   Message_Input -- allows inter-player message input processing                             *\n *   MixFileHandler -- Handles VQ file access.                                                 *\n *   Name_From_Source -- retrieves the name for the given SourceType                           *\n *   Owner_From_Name -- Convert an owner name into a bitfield.                                 *\n *   Play_Movie -- Plays a VQ movie.                                                           *\n *   Shake_The_Screen -- Dispatcher that shakes the screen.                                    *\n *   Shape_Dimensions -- Determine the minimum rectangle for the shape.                        *\n *   Source_From_Name -- Converts ASCII name into SourceType.                                  *\n *   Sync_Delay -- Forces the game into a 15 FPS rate.                                         *\n *   Theater_From_Name -- Converts ASCII name into a theater number.                           *\n *   Unselect_All -- Causes all selected objects to become unselected.                         *\n *   VQ_Call_Back -- Maintenance callback used for VQ movies.                                  *\n *   Game_Registry_Key -- Returns pointer to string containing the registry subkey for the game.\n *   Is_Counterstrike_Installed -- Function to determine the availability of the CS expansion.\n *   Is_Aftermath_Installed -- Function to determine the availability of the AM expansion.\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifdef TESTCODE\nclass A {\n\tpublic:\n\t\tenum {VAR=1};\n};\n\ntemplate<class T>\nclass B {\n\tpublic:\n\t\tenum {VAR2=T::VAR};  // this is the line in question.\n};\n\nB<A> test;\n#endif\n\n\n\n#include\t\"function.h\"\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#else\t//WINSOCK_IPX\n#include\t\"tcpip.h\"\n#endif\t//WINSOCK_IPX\n#else\n#include\t\"fakesock.h\"\nTcpipManagerClass\tWinsock;\n#endif\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<share.h>\n#include\t\"ccdde.h\"\n#include\t\"vortex.h\"\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#define PAGE_RESPOND_KEY\tKN_RETURN\t//KN_COMMA\n#endif\n\n#ifdef MPEGMOVIE\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\n#endif\n#include \"movie.h\"\nMPG_RESPONSE far __stdcall MpegCallback(MPG_CMD cmd, LPVOID data, LPVOID user);\n#endif\n\n#define SHAPE_TRANS\t\t0x40\n\nvoid * Get_Shape_Header_Data(void * ptr);\nextern bool Spawn_WChat(bool can_launch);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nvoid Enable_Secret_Units(void);\n#endif\n\nextern bool Is_Mission_Aftermath (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nextern void Do_Draw(void);\n#endif\n\n#ifdef CHEAT_KEYS\nbool\tbNoMovies = false;\n#endif\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nbool Main_Loop(void);\nvoid Keyboard_Process(KeyNumType & input);\nstatic void Message_Input(KeyNumType &input);\nvoid Color_Cycle(void);\nbool Map_Edit_Loop(void);\n\nextern \"C\" {\n\tbool UseOldShapeDraw = false;\n}\n\n#ifdef CHEAT_KEYS\nvoid Dump_Heap_Pointers( void );\nvoid Error_In_Heap_Pointers( char * string );\n#endif\nstatic void Do_Record_Playback(void);\n\nvoid Toggle_Formation(void);\n\nextern \"C\" {\n\textern char * __nheapbeg;\n}\n\n//\n// Special module globals for recording and playback\n//\nchar TeamEvent = 0;\t\t\t// 0 = no event, 1,2,3 = team event type\nchar TeamNumber = 0;\t\t\t// which team was selected? (1-9)\nchar FormationEvent = 0;\t// 0 = no event, 1 = formation was toggled\n\n\n\t/* -----------------10/14/96 7:29PM------------------\n\n\t --------------------------------------------------*/\n\n#if(TEN)\nvoid TEN_Call_Back(void);\n#endif\t// TEN\n\n#if(MPATH)\nvoid MPATH_Call_Back(void);\n#endif\t// MPATH\n\n/***********************************************************************************************\n * Main_Game -- Main game startup routine.                                                     *\n *                                                                                             *\n *    This is the first official routine of the game. It handles game initialization and       *\n *    the main game loop control.                                                              *\n *                                                                                             *\n *    Initialization:                                                                          *\n *    - Init_Game handles one-time-only inits                                                  *\n *    - Select_Game is responsible for initializations required for each new game played       *\n *      (these may be different depending on whether a multiplayer game is selected, and       *\n *      other parameters)                                                                      *\n *    - This routine performs any un-inits required, both for each game played, and one-time   *\n *                                                                                             *\n * INPUT:   argc  -- Number of command line arguments (including program name itself).         *\n *                                                                                             *\n *          argv  -- Array of command line argument pointers.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Main_Game(int argc, char * argv[])\n{\n\tstatic bool fade = true;\n\n\t/*\n\t**\tPerform one-time-only initializations\n\t*/\n\tif (!Init_Game(argc, argv)) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGame processing loop:\n\t**\t1) Select which game to play, or whether to exit (don't fade the palette\n\t**\t\ton the first game selection, but fade it in on subsequent calls)\n\t**\t2) Invoke either the main-loop routine, or the editor-loop routine,\n\t**\t\tuntil they indicate that the user wants to exit the scenario.\n\t*/\n\twhile (Select_Game(fade)) {\n\n\t\t// ST 5/14/2019\n\t\tif (RunningAsDLL) {\n\t\t\treturn;\n\t\t}\n\n\t\tfade = false;\n\t\tScenarioInit = 0;\t\t// Kludge.\n\n\t\tfade = true;\n\n\t\t/*\n\t\t** Initialise the color lookup tables for the chronal vortex\n\t\t*/\n\t\tChronalVortex.Stop();\n\t\tChronalVortex.Setup_Remap_Tables(Scen.Theater);\n\n\t\t/*\n\t\t**\tMake the game screen visible, clear the keyboard buffer of spurious\n\t\t**\tvalues, and then show the mouse.  This PRESUMES that Select_Game() has\n\t\t**\ttold the map to draw itself.\n\t\t*/\n\t\tGamePalette.Set(FADE_PALETTE_MEDIUM);\n\t\tKeyboard->Clear();\n\t\t/*\n\t\t** Only show the mouse if we're not playing back a recording.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tHide_Mouse();\n\t\t\tTeamEvent = 0;\n\t\t\tTeamNumber = 0;\n\t\t\tFormationEvent = 0;\n\t\t} else {\n\t\t\tShow_Mouse();\n\t\t}\n\n#ifdef WIN32\n\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\tRegister_Game_Start_Time();\n\t\t\tGameStatisticsPacketSent = false;\n\t\t\tPacketLater = NULL;\n\t\t\tConnectionLost = false;\n\t\t} else {\n#ifndef WOLAPI_INTEGRATION\n\t\t\tDDEServer.Disable();\n#endif\t//\t!WOLAPI_INTEGRATION\n\t\t}\n#endif\t//WIN32\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t**\tScenario-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tNon-scenario-editor-mode: call the game's main loop\n\t\t\t*/\n\t\t\tif (!Debug_Map) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tTimeQuake = PendingTimeQuake;\n\t\t\t\tPendingTimeQuake = false;\n#else\n\t\t\t\tTimeQuake = false;\n#endif\n\t\t\t\tif (Main_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tScenario-editor-mode: call the editor's main loop\n\t\t\t\t*/\n\t\t\t\tif (Map_Edit_Loop()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t/*\n\t\t**\tNon-editor version of main-loop processing\n\t\t*/\n\t\tfor (;;) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tTimeQuake = PendingTimeQuake;\n\t\t\tPendingTimeQuake = false;\n#else\n\t\t\tTimeQuake = false;\n#endif\n\t\t\t/*\n\t\t\t**\tCall the game's main loop\n\t\t\t*/\n\t\t\tif (Main_Loop()) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the SpecialDialog flag is set, invoke the given special dialog.\n\t\t\t**\tThis must be done outside the main loop, since the dialog will call\n\t\t\t**\tMain_Loop(), allowing the game to run in the background.\n\t\t\t*/\n\t\t\tif (SpecialDialog != SDLG_NONE) {\n\t\t\t\tswitch (SpecialDialog) {\n\t\t\t\t\tcase SDLG_SPECIAL:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tSpecial_Dialog();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_OPTIONS:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tOptions.Process();\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_SURRENDER:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::DESTRUCT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n\n/*ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\t\tcase SDLG_PROPOSE_DRAW:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_WOL_PROPOSE_DRAW)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDLG_ACCEPT_DRAW:\n\t\t\t\t\t\tMap.Help_Text(TXT_NONE);\n\t\t\t\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_WOL_ACCEPT_DRAW)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ACCEPT_DRAW));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSpecialDialog = SDLG_NONE;\n\t\t\t\t\t\tMap.Revert_Mouse_Shape();\n\t\t\t\t\t\tbreak;\n#endif\n*/\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game stats to WChat if we haven't already done so\n\t\t*/\n\t\tif (!GameStatisticsPacketSent && PacketLater) {\n\t\t\tSend_Statistics_Packet();\t\t//\tAfter game sending if PacketLater set.\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tScenario is done; fade palette to black\n\t\t*/\n\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\tVisiblePage.Clear();\n\n\t\t/*\n\t\t**\tUn-initialize whatever needs it, for each game played.\n\t\t**\n\t\t**\tShut down either the modem or network; they'll get re-initialized if\n\t\t**\tthe user selections those options again in Select_Game().  This\n\t\t**\t\"re-boots\" the modem & network code, which I currently feel is safer\n\t\t**\tthan just letting it hang around.\n\t\t** (Skip this step if we're in playback mode; the modem or net won't have\n\t\t** been initialized in that case.)\n\t\t*/\n\t\tif (Session.Record || Session.Play) {\n\t\t\tSession.RecordFile.Close();\n\t\t}\n\n\t\tif (Session.Type == GAME_NULL_MODEM || Session.Type == GAME_MODEM) {\n\t\t\tif (!Session.Play) {\n\t\t\t\t//PG Modem_Signoff();\n\t\t\t}\n\t\t} else {\n\t\t\tif (Session.Type == GAME_IPX) {\n\t\t\t\tif (!Session.Play) {\n\t\t\t\t\t//PG Shutdown_Network();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if(TEN)\n\n\t\tif (Session.Type == GAME_TEN) {\n\t\t\tShutdown_TEN();\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\tif (Session.Type == GAME_MPATH) {\n\t\t\tShutdown_MPATH();\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t}\n#endif\t// MPATH\n\n\t\t/*\n\t\t**\tIf we're playing back, the mouse will be hidden; show it.\n\t\t** Also, set all variables back to normal, to return to the main menu.\n\t\t*/\n\t\tif (Session.Play) {\n\t\t\tShow_Mouse();\n\t\t\tSession.Type = GAME_NORMAL;\n\t\t\tSession.Play = 0;\n\t\t}\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t\tif (Special.IsFromWChat) {\n\t\t\t//PG Shutdown_Network();\t\t      // Clear up the pseudo IPX stuff\n#ifndef WINSOCK_IPX\n\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\tSpecial.IsFromWChat = false;\n\t\t\tSpawnedFromWChat = false;\n\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t//Make sure we dont use the same start packet twice\n\t\t\tSession.Type = GAME_NORMAL;\t\t\t//Have to do this or we will got straight to the multiplayer menu\n\t\t\tSpawn_WChat(false);\t\t//Will switch back to Wchat. It must be there because its been poking us\n\t\t}\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\t}\n\n\t/*\n\t**\tFree the scenario description buffers\n\t*/\n\tSession.Free_Scenario_Descriptions();\n}\n\n\n/***********************************************************************************************\n * Keyboard_Process -- Processes the tactical map input codes.                                 *\n *                                                                                             *\n *    This routine is used to process the input codes while the player                         *\n *    has the tactical map displayed. It handles all the keys that                             *\n *    are appropriate to that mode.                                                            *\n *                                                                                             *\n * INPUT:   input -- Input code as returned from Input_Num().                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1992 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Handles team and map control hotkeys.                                    *\n *=============================================================================================*/\nvoid Keyboard_Process(KeyNumType & input)\n{\n\tObjectClass * obj;\n\tint index;\n\n\t/*\n\t**\tDon't do anything if there is not keyboard event.\n\t*/\n\tif (input == KN_NONE) {\n\t\treturn;\n\t}\n\t/*\n\t**\tFor network & modem, process user input for inter-player messages.\n\t*/\n\tMessage_Input(input);\n\n#ifdef WIN32\n\t/*\n\t**\tThe VK_BIT must be stripped from the \"plain\" value of the key so that a comparison to\n\t**\tKN_1, for example, will yield TRUE if in fact the \"1\" key was pressed.\n\t*/\n\n\tKeyNumType plain = KeyNumType(input & ~(WWKEY_SHIFT_BIT|WWKEY_ALT_BIT|WWKEY_CTRL_BIT|WWKEY_VK_BIT));\n\tKeyNumType key = KeyNumType(input & ~WWKEY_VK_BIT);\n\n\n#else\n\tKeyNumType plain = KeyNumType(input & ~(KN_SHIFT_BIT|KN_ALT_BIT|KN_CTRL_BIT));\n\tKeyNumType key = plain;\n#endif\n\n#ifdef CHEAT_KEYS\n\n\tif (Debug_Flag) {\n\t\tHousesType h;\n\n\t\tswitch (int(input)) {\n\t\t\tcase int(int(KN_M) | int(KN_SHIFT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_ALT_BIT)):\n\t\t\tcase int(int(KN_M) | int(KN_CTRL_BIT)):\n\t\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\t\tHouses.Ptr(h)->Refund_Money(10000);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n\n#ifdef VIRGIN_CHEAT_KEYS\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n#ifdef WIN32\n\tif (Debug_Playtest && input == (KA_W|KN_ALT_BIT)) {\n#else\n\tif (Debug_Playtest && input == (KN_W|KN_ALT_BIT)) {\n#endif\n\t\tPlayerPtr->Blockage = false;\n\t\tPlayerPtr->Flag_To_Win();\n\t}\n\n\tif ((Debug_Flag || Debug_Playtest) && plain == KN_F4) {\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t}\n\n\tif (Debug_Flag && input == KN_SLASH) {\n\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\tSpecialDialog = SDLG_SPECIAL;\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tSpecial_Dialog();\n\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tProcess prerecorded team selection. This will be an additive select\n\t**\tif the SHIFT key is held down. It will create the team if the\n\t**\tCTRL or ALT key is held down.\n\t*/\n\tint action = 0;\n#ifdef WIN32\n\tif (input & WWKEY_SHIFT_BIT) action = 1;\n\tif (input & WWKEY_ALT_BIT) action = 3;\n\tif (input & WWKEY_CTRL_BIT) action = 2;\n#else\n\tif (input & KN_SHIFT_BIT) action = 1;\n\tif (input & KN_ALT_BIT) action = 3;\n\tif (input & KN_CTRL_BIT) action = 2;\n#endif\n\n\t/*\n\t**\tIf the \"N\" key is pressed, then select the next object.\n\t*/\n\tif (key != 0 && key == Options.KeyNext) {\n\t\tif (action) {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyPrevious) {\n\t\tif (action) {\n\t\t\tobj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t} else {\n\t\t\tobj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\t\t}\n\t\tif (obj != NULL) {\n\t\t\tUnselect_All();\n\t\t \tobj->Select();\n\t\t\tMap.Center_Map();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\n\t/*\n\t**\tAll selected units will go into idle mode.\n\t*/\n\tif (key != 0 && key == Options.KeyStop) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && (tech->Can_Player_Move() || (tech->Can_Player_Fire() && tech->What_Am_I() != RTTI_BUILDING))) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::IDLE, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to go into guard area mode.\n\t*/\n\tif (key != 0 && key == Options.KeyGuard) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move() && tech->Can_Player_Fire()) {\n\t\t\t\t\tOutList.Add(EventClass(TargetClass(tech), MISSION_GUARD_AREA));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tAll selected units will attempt to scatter.\n\t*/\n\tif (key != 0 && key == Options.KeyScatter) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\t\tif (tech != NULL && tech->Can_Player_Move()) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SCATTER, TargetClass(tech)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tCenter the map around the currently selected objects. If no\n\t**\tobjects are selected, then fall into the home case.\n\t*/\n\tif (key != 0 && (key == Options.KeyHome1 || key == Options.KeyHome2)) {\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\tMap.Flag_To_Redraw(true);\n#endif\n\t\t\tinput = KN_NONE;\n\t\t} else {\n\t\t\tinput = Options.KeyBase;\n\t\t}\n\t}\n\n\t/*\n\t**\tCenter the map about the construction yard or construction vehicle\n\t**\tif one is present.\n\t*/\n\tif (key != 0 && key == Options.KeyBase) {\n\t\tUnselect_All();\n\t\tif (PlayerPtr->CurBuildings) {\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\n\t\t\t\tif (building != NULL && !building->IsInLimbo && building->House == PlayerPtr && *building == STRUCT_CONST) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tbuilding->Select();\n\t\t\t\t\tif (building->IsLeader) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count() == 0 && PlayerPtr->CurUnits) {\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\t\t\tif (unit != NULL && !unit->IsInLimbo && unit->House == PlayerPtr && *unit == UNIT_MCV) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tunit->Select();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (CurrentObject.Count()) {\n\t\t\tMap.Center_Map();\n\t\t} else {\n\t\t\tif (PlayerPtr->Center != 0) {\n\t\t\t\tMap.Center_Map(PlayerPtr->Center);\n\t\t\t}\n\t\t}\n\t\tMap.Flag_To_Redraw(true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t** Toggle the status of formation for the current team\n\t*/\n\tif (key != 0 && key == Options.KeyFormation) {\n\t\tToggle_Formation();\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef TOFIX\n\t/*\n\t** For multiplayer, 'R' pops up the surrender dialog.\n\t*/\n\tif (input != 0 && input == Options.KeyResign) {\n\t\tif (!PlayerLoses && /*Session.Type != GAME_NORMAL &&*/ !PlayerPtr->IsDefeated) {\n\t\t\tSpecialDialog = SDLG_SURRENDER;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n#endif\n\n\t/*\n\t**\tHandle making and breaking alliances.\n\t*/\n\tif (key != 0 && key == Options.KeyAlliance) {\n\t\tif (Session.Type != GAME_NORMAL || Debug_Flag) {\n\t\t\tif (CurrentObject.Count() && !PlayerPtr->IsDefeated) {\n\t\t\t\tif (CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::ALLY, CurrentObject[0]->Owner()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tSelect all the units on the current display. This is equivalent to\n\t**\tdrag selecting the whole view.\n\t*/\n\tif (key != 0 && key == Options.KeySelectView) {\n\t\tMap.Select_These(0x00000000, XY_Coord(Map.TacLeptonWidth, Map.TacLeptonHeight));\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the repair state similarly to pressing the repair button.\n\t*/\n\tif (key != 0 && key == Options.KeyRepair) {\n\t\tMap.Repair_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the sell state similarly to pressing the sell button.\n\t*/\n\tif (key != 0 && key == Options.KeySell) {\n\t\tMap.Sell_Mode_Control(-1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tToggles the map zoom mode similarly to pressing the map button.\n\t*/\n\tif (key != 0 && key == Options.KeyMap) {\n\t\tMap.Zoom_Mode_Control();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar up one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarUp) {\n\t\tMap.SidebarClass::Scroll(true, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the sidebar down one slot.\n\t*/\n\tif (key != 0 && key == Options.KeySidebarDown) {\n\t\tMap.SidebarClass::Scroll(false, -1);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tBrings up the options dialog box.\n\t*/\n\tif (key != 0 && (key == Options.KeyOption1 || key == Options.KeyOption2)) {\n\t\tMap.Help_Text(TXT_NONE);\t\t\t// Turns off help text.\n\t\tQueue_Options();\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tScrolls the tactical map in the direction specified.\n\t*/\n\tint distance = CELL_LEPTON_W;\n\tif (key != 0 && key == Options.KeyScrollLeft) {\n\t\tMap.Scroll_Map(DIR_W, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollRight) {\n\t\tMap.Scroll_Map(DIR_E, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollUp) {\n\t\tMap.Scroll_Map(DIR_N, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\tif (key != 0 && key == Options.KeyScrollDown) {\n\t\tMap.Scroll_Map(DIR_S, distance, true);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tTeams are handled by the 10 special team keys. The manual comparison\n\t**\tto the KN numbers is because the Windows keyboard driver can vary\n\t**\tthe base code number for the key depending on the shift or alt key\n\t**\tstate!\n\t*/\n\tif (input != 0 && (plain == Options.KeyTeam1 || plain == KN_1)) {\n\t\tHandle_Team(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam2 || plain == KN_2)) {\n\t\tHandle_Team(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam3 || plain == KN_3)) {\n\t\tHandle_Team(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam4 || plain == KN_4)) {\n\t\tHandle_Team(3, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam5 || plain == KN_5)) {\n\t\tHandle_Team(4, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam6 || plain == KN_6)) {\n\t\tHandle_Team(5, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam7 || plain == KN_7)) {\n\t\tHandle_Team(6, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam8 || plain == KN_8)) {\n\t\tHandle_Team(7, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam9 || plain == KN_9)) {\n\t\tHandle_Team(8, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && (plain == Options.KeyTeam10 || plain == KN_0)) {\n\t\tHandle_Team(9, action);\n\t\tinput = KN_NONE;\n\t}\n\n\t/*\n\t**\tHandle the bookmark hotkeys.\n\t*/\n\tif (input != 0 && plain == Options.KeyBookmark1 && !Debug_Map) {\n\t\tHandle_View(0, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark2 && !Debug_Map) {\n\t\tHandle_View(1, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark3 && !Debug_Map) {\n\t\tHandle_View(2, action);\n\t\tinput = KN_NONE;\n\t}\n\tif (input != 0 && plain == Options.KeyBookmark4 && !Debug_Map) {\n\t\tHandle_View(3, action);\n\t\tinput = KN_NONE;\n\t}\n\n#ifdef CHEAT_KEYS\n\tif (input != 0 && Debug_Flag && input && (input & KN_RLSE_BIT) == 0) {\n\t\tDebug_Key(input);\n\t}\n#endif\n}\n\n\nvoid Toggle_Formation(void) {\n\n// MBL 03.23.2020: this has been copied to DLLExportClass::Team_Units_Formation_Toggle_On(), and modified as needed\n#if 0\n\tint team = -1;\n\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\tlong maxx = 0, maxy = 0;\n\tint index;\n\tbool setform = 0;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tFormationEvent = 1;\n\t}\n\n\t/*\n\t** Find the first selected object that is a member of a team, and\n\t** register his group as the team we're using.  Once we find the team\n\t** number, update the 'setform' flag to know whether we should be setting\n\t** the formation's offsets, or clearing them.  If they currently have\n\t** illegal offsets (as in 0x80000000), then we're setting.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\tteam = obj->Group;\n\t\t\tif (team != -1) {\n\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (team == -1) {\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) {\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->IsSelected) {\n\t\t\t\tteam = obj->Group;\n\t\t\t\tif (team != -1) {\n\t\t\t\t\tsetform = obj->XFormOffset == 0x80000000UL;\n\t\t\t\t\tTeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\tTeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team == -1) return;\n\t/*\n\t** Now that we have a team, let's go set (or clear) the formation offsets.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\tTeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < TeamMaxSpeed[team]) {\n\t\t\t\t\tTeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = 0x80000000UL;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** All the units have been counted to find the bounding rectangle and\n\t** center of the formation, or to clear their offsets.  Now, if we're to\n\t** set them into formation, proceed to do so.  Otherwise, bail.\n\t*/\n\tif (setform) {\n\t\tint centerx = (int)((maxx - minx)/2)+minx;\n\t\tint centery = (int)((maxy - miny)/2)+miny;\n\n\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Message_Input -- allows inter-player message input processing                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tinput\t\tkey value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\n//#pragma off (unreferenced)\nstatic void Message_Input(KeyNumType &input)\n{\n\tint rc;\n\tchar txt[MAX_MESSAGE_LENGTH+32];\n\tint id;\n//\tSerialPacketType * serial_packet;\n\t//int i;\n\tKeyNumType copy_input;\n\t//char *msg;\n\n\t/*\n\t**\tCheck keyboard input for a request to send a message.\n\t**\tThe 'to' argument for Add_Edit is prefixed to the message buffer; the\n\t**\tmessage buffer is big enough for the 'to' field plus MAX_MESSAGE_LENGTH.\n\t**\tTo send the message, calling Get_Edit_Buf retrieves the buffer minus the\n\t**\t'to' portion.  At the other end, the buffer allocated to display the\n\t**\tmessage must be MAX_MESSAGE_LENGTH plus the size of \"From: xxx (house)\".\n\t*/\n#ifdef WOLAPI_INTEGRATION\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && \n\t\t( ( input >= KN_F1 && input < (KN_F1 + Session.MaxPlayers) ) || input == PAGE_RESPOND_KEY ) && \n\t\t!Session.Messages.Is_Edit()) {\n#else\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && input >= KN_F1 && input < (KN_F1 + Session.MaxPlayers) && !Session.Messages.Is_Edit()) {\n#endif\n\t\tmemset (txt, 0, 40);\n\n\t\t/*\n\t\t**\tFor a serial game, send a message on F1 or F4; set 'txt' to the\n\t\t**\t\"Message:\" string & add an editable message to the list.\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tif (input==KN_F1 || input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tstrcpy(txt, Text_String(TXT_MESSAGE));\t// \"Message:\"\n\n\t\t\t\tSession.Messages.Add_Edit (Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t} else if ((Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) && !Session.Messages.Is_Edit()) {\n\t\t/*\n\t\t**\tFor a network game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.MessageAddress = IPXAddressClass();\t\t// set to broadcast\n\t\t\t\tstrcpy(txt, Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t} else if ((input - KN_F1) < Ipx.Num_Connections() && !Session.ObiWan && input != PAGE_RESPOND_KEY ) {\n#else\n\t\t\t} else if ((input - KN_F1) < Ipx.Num_Connections() && !Session.ObiWan) {\n#endif\n\t\t\t\tid = Ipx.Connection_ID(input - KN_F1);\n\t\t\t\tSession.MessageAddress = (*(Ipx.Connection_Address (id)));\n\t\t\t\tsprintf(txt, Text_String(TXT_TO), Ipx.Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n#ifdef WOLAPI_INTEGRATION\n\t\t\telse if( Session.Type == GAME_INTERNET && pWolapi && !pWolapi->bConnectionDown && input == PAGE_RESPOND_KEY )\n\t\t\t{\n\t\t\t\tif( *pWolapi->szExternalPager )\n\t\t\t\t{\n\t\t\t\t\t//\tRespond to a page from external ww online user that paged me.\n\t\t\t\t\t//\tSet MessageAddress to all zeroes, as a flag to ourselves later on.\n\t\t\t\t\tNetNumType blip;\n\t\t\t\t\tNetNodeType blop;\n\t\t\t\t\tmemset( blip, 0, 4 );\n\t\t\t\t\tmemset( blop, 0, 6 );\n\t\t\t\t\tSession.MessageAddress = IPXAddressClass( blip, blop );\n\n\t\t\t\t\t//\tTell pWolapi not to reset szExternalPager for the time being.\n\t\t\t\t\tpWolapi->bFreezeExternalPager = true;\n\n\t\t\t\t\tsprintf( txt, Text_String( TXT_TO ), pWolapi->szExternalPager );\n\n\t\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_NOTPAGED, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t\t\tSound_Effect( VOC_SYS_ERROR );\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n#if(TEN)\n\t\t/*\n\t\t**\tFor a TEN game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\telse if (Session.Type == GAME_TEN && !Session.Messages.Is_Edit()) {\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.TenMessageAddress = -1;\t\t// set to broadcast\n\t\t\t\tstrcpy(txt,Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t}  else if ((input - KN_F1) < Ten->Num_Connections() && !Session.ObiWan) {\n\n\t\t\t\tid = Ten->Connection_ID(input - KN_F1);\n\t\t\t\tSession.TenMessageAddress = Ten->Connection_Address(id);\n\t\t\t\tsprintf(txt,Text_String(TXT_TO),Ten->Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t}\n#endif\t// TEN\n#if(MPATH)\n\t\t/*\n\t\t**\tFor a MPATH game:\n\t\t**\tF1-F7 = \"To <name> (house):\" (only allowed if we're not in ObiWan mode)\n\t\t**\tF8 = \"To All:\"\n\t\t*/\n\t\telse if (Session.Type == GAME_MPATH && !Session.Messages.Is_Edit()) {\n\t\t\tif (input==(KN_F1 + Session.MaxPlayers - 1)) {\n\n\t\t\t\tSession.MPathMessageAddress = 0;\t\t\t// set to broadcast\n\t\t\t\tstrcpy(txt,Text_String(TXT_TO_ALL));\t// \"To All:\"\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t\t}  else if ((input - KN_F1) < MPath->Num_Connections() && !Session.ObiWan) {\n\n\t\t\t\tid = MPath->Connection_ID(input - KN_F1);\n\t\t\t\tSession.MPathMessageAddress = MPath->Connection_Address(id);\n\t\t\t\tsprintf(txt,Text_String(TXT_TO),MPath->Connection_Name(id));\n\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, 0, 232 * RESFACTOR);\n\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t}\n#endif\t// MPATH\n\t}\n\n\t/*\n\t**\tProcess message-system input; send the message out if RETURN is hit.\n\t*/\n\tcopy_input = input;\n\trc = Session.Messages.Input(input);\n\n\t/*\n\t**\tIf a single character has been added to an edit buffer, update the display.\n\t*/\n\tif (rc == 1 && Session.Type != GAME_NORMAL) {\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t/*\n\t**\tIf backspace was hit, redraw the map.  If the edit message was removed,\n\t** the map must be force-drawn, since it won't be able to compute the\n\t** cells to redraw; otherwise, let the map compute the cells to redraw,\n\t** by not force-drawing it, but just setting the IsToRedraw bit.\n\t*/\n\tif (rc==2 && Session.Type != GAME_NORMAL) {\n\t\tif (copy_input==KN_ESC) {\n\t\t\tMap.Flag_To_Redraw(true);\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( pWolapi )\n\t\t\t\t//\tJust in case user was responding to a page from outside the game, and we had frozen the \"szExternalPager\".\n\t\t\t\tpWolapi->bFreezeExternalPager = false;\n#endif\n\t\t} else {\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t\tMap.DisplayClass::IsToRedraw = true;\n\t}\n\n\t/*\n\t**\tSend a message\n\t*/\n\tif ((rc==3 || rc==4) && Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) {\n#if (0)\n\t\t/*\n\t\t**\tSerial game: fill in a SerialPacketType & send it.\n\t\t**\t(Note: The size of the SerialPacketType.Command must be the same as\n\t\t**\tthe EventClass.Type!)\n\t\t*/\n\t\tif (Session.Type==GAME_NULL_MODEM || Session.Type==GAME_MODEM) {\n\t\t\tserial_packet = (SerialPacketType *)NullModem.BuildBuf;\n\n\t\t\tserial_packet->Command = SERIAL_MESSAGE;\n\t\t\tstrcpy (serial_packet->Name, Session.Players[0]->Name);\n\t\t\tserial_packet->ID = Session.ColorIdx;\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (serial_packet->Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Send the message, and store this message in our LastMessage\n\t\t\t** buffer; the computer may send us a version of it later.\n\t\t\t*/\n\t\t\tNullModem.Send_Message(NullModem.BuildBuf,\n\t\t\t\tsizeof(SerialPacketType), 1);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tchar *ptr = &serial_packet->Message.Message[0];\n\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\tstrcpy(Session.LastMessage, serial_packet->Message.Message);\n\t\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n#ifdef WOLAPI_INTEGRATION\n\t\t\tNetNumType blip;\n\t\t\tNetNodeType blop;\n\t\t\tSession.MessageAddress.Get_Address( blip, blop );\n\t\t\tif(\tblip[0] + blip[1] + blip[2] + blip[3] + blop[0] + blop[1] + blop[2] + blop[3] + blop[4] + blop[5] == 0 )\n\t\t\t{\n\t\t\t\t//\tThis message is a response to the last person that paged me.\n\t\t\t\tif( pWolapi && !pWolapi->bConnectionDown )\t\t//\t(As connection may have gone down.)\n\t\t\t\t{\n\t\t\t\t\tpWolapi->Page( pWolapi->szExternalPager, Session.Messages.Get_Edit_Buf(), false );\n\t\t\t\t\tpWolapi->bFreezeExternalPager = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t{\n\n\t\t\t/*\n\t\t\t**\tNetwork game: fill in a GlobalPacketType & send it.\n\t\t\t*/\n\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\t\tif (rc==3) {\n\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t\t} else {\n\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf 'F4' was hit, MessageAddress will be a broadcast address; send\n\t\t\t\t**\tthe message to every player we have a connection with.\n\t\t\t\t*/\n\t\t\t\tif (Session.MessageAddress.Is_Broadcast()) {\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tchar *ptr = &Session.GPacket.Message.Buf[0];\n\t\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\t\t*ptr = 'X';\t\t// force it to an odd hack so we know it was broadcast.\n\t\t\tEnable_Secret_Units();\n\t\t}\n\t#endif\n\t\t\t\t\tfor (i = 0; i < Ipx.Num_Connections(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\tIpx.Connection_Address(Ipx.Connection_ID(i)));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tOtherwise, MessageAddress contains the exact address to send to.\n\t\t\t\t\t**\tSend to that address only.\n\t\t\t\t\t*/\n\t\t\t\t\tIpx.Send_Global_Message(&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t&Session.MessageAddress);\n\t\t\t\t\tIpx.Service();\n\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tStore this message in our LastMessage buffer; the computer may send\n\t\t\t\t**\tus a version of it later.\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\n#if(TEN)\n\t\t/*\n\t\t**\tTEN game: fill in a GlobalPacketType & send it.\n\t\t*/\n\t\telse if (Session.Type == GAME_TEN) {\n\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\tTen->Send_Global_Message(&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t1, Session.TenMessageAddress);\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t/*\n\t\t**\tMPATH game: fill in a GlobalPacketType & send it.\n\t\t*/\n\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\tSession.GPacket.Message.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\t\tif (rc==3) {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf, Session.Messages.Get_Edit_Buf());\n\t\t\t} else {\n\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t}\n\n\t\t\tMPath->Send_Global_Message(&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t1, Session.MPathMessageAddress);\n\t\t}\n#endif\t// MPATH\n\n\t\t/*\n\t\t**\tTell the map to completely update itself, since a message is now missing.\n\t\t*/\n\t\tMap.Flag_To_Redraw(true);\n#endif\n\t}\n}\n//#pragma on (unreferenced)\n\n\n/***********************************************************************************************\n * Color_Cycle -- Handle the general palette color cycling.                                    *\n *                                                                                             *\n *    This is a maintenance routine that handles the color cycling. It should be called as     *\n *    often as necessary to achieve smooth color cycling effects -- at least 8 times a second. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   06/10/1994 JLB : Uses new cycle color values.                                             *\n *   12/21/1994 JLB : Handles text fade color.                                                 *\n *   07/16/1996 JLB : Faster pulsing of white color.                                           *\n *=============================================================================================*/\nvoid Color_Cycle(void)\n{\n\tstatic CDTimerClass<SystemTimerClass> _timer;\n\tstatic CDTimerClass<SystemTimerClass> _ftimer;\n\tstatic bool _up = false;\n\tstatic int val = 255;\n\tbool changed = false;\n\n\tif (Options.IsPaletteScroll) {\n\t\t/*\n\t\t**\tProcess the fading white color. It is used for the radar box and other glowing\n\t\t**\tgame interface elements.\n\t\t*/\n\t\tif (!_ftimer) {\n\t\t\t_ftimer = TIMER_SECOND/6;\n\n\t\t\t#define\tSTEP_RATE\t20\n\t\t\tif (_up) {\n\t\t\t\tval += STEP_RATE;\n\t\t\t\tif (val > 150) {\n\t\t\t\t\tval = 150;\n\t\t\t\t\t_up = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval -= STEP_RATE;\n\t\t\t\tif (val < 0x20) {\n\t\t\t\t\tval = 0x20;\n\t\t\t\t\t_up = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSet the pulse color as the proportional value between white and the\n\t\t\t**\tminimum value for pulsing.\n\t\t\t*/\n\t\t\tInGamePalette[CC_PULSE_COLOR] = GamePalette[WHITE];\n\t\t\tInGamePalette[CC_PULSE_COLOR].Adjust(val, BlackColor);\n\n\t\t\t/*\n\t\t\t**\tPulse the glowing embers between medium and dark red.\n\t\t\t*/\n\t\t\tInGamePalette[CC_EMBER_COLOR] = RGBClass(255, 80, 80);\n\t\t\tInGamePalette[CC_EMBER_COLOR].Adjust(val, BlackColor);\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the color cycling effects -- water.\n\t\t*/\n\t\tif (!_timer) {\n\t\t\t_timer = TIMER_SECOND/4;\n\n\t\t\tRGBClass first = InGamePalette[CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1];\n\t\t\tfor (int index = CYCLE_COLOR_START+CYCLE_COLOR_COUNT-1; index >= CYCLE_COLOR_START; index--) {\n\t\t\t\tInGamePalette[index] = InGamePalette[index-1];\n\t\t\t}\n\t\t\tInGamePalette[CYCLE_COLOR_START] = first;\n\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*\n\t\t**\tIf any of the processing functions changed the palette, then this palette must be\n\t\t**\tpassed to the system.\n\t\t*/\n\t\tif (changed) {\n\t\t\tBStart(BENCH_PALETTE);\n\t\t\tInGamePalette.Set();\n//\t\t\tSet_Palette(InGamePalette);\n\t\t\tBEnd(BENCH_PALETTE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Call_Back -- Main game maintenance callback routine.                                        *\n *                                                                                             *\n *    This routine handles all the \"real time\" processing that needs to                        *\n *    occur. This includes palette fading and sound updating. It needs                         *\n *    to be called as often as possible.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Call_Back(void)\n{\n\t/*\n\t**\tMusic and speech maintenance\n\t*/\n\tif (SampleType) {\n\t\tSound_Callback();\n\t\tTheme.AI();\n\t\tSpeak_AI();\n\t}\n\n\t/*\n\t**\tNetwork maintenance.\n\t*/\n\tif (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\tIPX_Call_Back();\n\t}\n\n\t/*\n\t**\tSerial game maintenance.\n\t*/\n\tif (Session.Type == GAME_NULL_MODEM || ((Session.Type == GAME_MODEM) && Session.ModemService)) {\n\t\t//NullModem.Service();\t\tST - 5/7/2019\n\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tWolapi maintenance.\n\tif( pWolapi )\n\t{\n\t\tif( pWolapi->bInGame )\n\t\t{\n\t\t\tif( !pWolapi->bConnectionDown && ::timeGetTime() > pWolapi->dwTimeNextWolapiPump )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->pNetUtil->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT + 700;\t\t//\tSlower pump during games.\n\t\t\t\tif( pWolapi->bConnectionDown )\n\t\t\t\t{\n\t\t\t\t\t//\tConnection to server lost.\n\t\t\t\t\tSession.Messages.Add_Message( NULL, 0, TXT_WOL_WOLAPIGONE, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t\t\tSound_Effect( WOLSOUND_LOGOUT );\n//\tajw (Wolapi object is now left around, so we can try to send game results.)\n//\t\t\t\t\t//\tKill wolapi.\n//\t\t\t\t\tpWolapi->UnsetupCOMStuff();\n//\t\t\t\t\tdelete pWolapi;\n//\t\t\t\t\tpWolapi = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tWhen showing a modal dialog during chat, this pumping is turned on. It's turned off immediately following.\n\t\t\tif( pWolapi->bPump_In_Call_Back && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->pNetUtil->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n#if(TEN)\n\tif (Session.Type == GAME_TEN) {\n\t\tTEN_Call_Back();\n\t}\n#endif\t// TEN\n\n#if(MPATH)\n\tif (Session.Type == GAME_MPATH) {\n\t\tMPATH_Call_Back();\n\t}\n#endif\t// MPATH\n}\n\n\nvoid IPX_Call_Back(void)\n{\n#if (0)//PG\n\tIpx.Service();\n\n\t/*\n\t** Read packets only if the game is \"closed\", so we don't steal global\n\t** messages from the connection dialogs.\n\t*/\n\tif (!Session.NetOpen) {\n\t\tif (Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, &Session.GAddress, &Session.GProductID)) {\n\n\t\t\tif (Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is another player signing off, remove the connection &\n\t\t\t\t**\tmark that player's house as non-human, so the computer will take\n\t\t\t\t**\tit over.\n\t\t\t\t*/\n\t\t\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\t\t\tfor (int i = 0; i < Ipx.Num_Connections(); i++) {\n\n\t\t\t\t\t\tint id = Ipx.Connection_ID(i);\n\n\t\t\t\t\t\tif (Session.GAddress == (*Ipx.Connection_Address(id))) {\n\t\t\t\t\t\t\tDestroy_Connection(id, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess a message from another user.\n\t\t\t\t\t*/\n\n\t\t\t\t\tif (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\t\t\t\tbool msg_ok = false;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If NetProtect is set, make sure this message came from within\n\t\t\t\t\t\t** this game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!Session.NetProtect) {\n\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (Session.GPacket.Message.NameCRC ==\n\t\t\t\t\t\t\t\tCompute_Name_CRC(Session.GameName)) {\n\t\t\t\t\t\t\t\tmsg_ok = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmsg_ok = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (msg_ok) {\n\t\t\t\t\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (NewUnitsEnabled && !strncmp(Session.GPacket.Message.Buf,\"XECRET UNITS ON \",15)) {\n\t\tSession.GPacket.Message.Buf[0]='S';\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\t\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t\t\t\t**\tto redraw).\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProcess_Global_Packet(&Session.GPacket, &Session.GAddress);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n#if(TEN)\nvoid TEN_Call_Back(void)\n{\n\tint id;\n\n\tTen->Service();\n\n\tif (Ten->Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.TenAddress)) {\n\n\t\t//\n\t\t//\tIf this is another player signing off, remove the connection &\n\t\t//\tmark that player's house as non-human, so the computer will take\n\t\t//\tit over.\n\t\t//\n\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\tfor (int i = 0; i < Ten->Num_Connections(); i++) {\n\n\t\t\t\tid = Ten->Connection_ID(i);\n\n\t\t\t\tif (Session.TenAddress == Ten->Connection_Address(id)) {\n\t\t\t\t\tDestroy_TEN_Connection(id, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t//\tProcess a message from another user.\n\t\t//\n\t\telse if (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t**\tto redraw).\n\t\t\t\t*/\n\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\t// TEN\n\n\n#if(MPATH)\nvoid MPATH_Call_Back(void)\n{\n\tint id;\n\n\tMPath->Service();\n\n\tif (MPath->Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.MPathAddress)) {\n\n\t\t//\n\t\t//\tIf this is another player signing off, remove the connection &\n\t\t//\tmark that player's house as non-human, so the computer will take\n\t\t//\tit over.\n\t\t//\n\t\tif (Session.GPacket.Command == NET_SIGN_OFF) {\n\t\t\tfor (int i = 0; i < MPath->Num_Connections(); i++) {\n\n\t\t\t\tid = MPath->Connection_ID(i);\n\n\t\t\t\tif (Session.MPathAddress == MPath->Connection_Address(id)) {\n\t\t\t\t\tDestroy_MPATH_Connection(id, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t//\tProcess a message from another user.\n\t\t//\n\t\telse if (Session.GPacket.Command == NET_MESSAGE) {\n\t\t\tif (!Session.Messages.Concat_Message(Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL |\n\t\t\t\t\tTPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\t\t\t/*\n\t\t\t\t**\tTell the map to do a partial update (just to force the messages\n\t\t\t\t**\tto redraw).\n\t\t\t\t*/\n\t\t\t\tMap.Flag_To_Redraw(true);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave this message in our last-message buffer\n\t\t\t\t*/\n\t\t\t\tstrcpy(Session.LastMessage, Session.GPacket.Message.Buf);\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\t// MPATH\n\n\n/***********************************************************************************************\n * Language_Name -- Build filename for current language.                                       *\n *                                                                                             *\n *    This routine attaches a language specific suffix to the base                             *\n *    filename provided. Typical use of this is when loading language                          *\n *    specific files at game initialization time.                                              *\n *                                                                                             *\n * INPUT:   basename -- Base name to append language specific                                  *\n *                      extension to.                                                          *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to completed filename.                                        *\n *                                                                                             *\n * WARNINGS:   The return pointer value is valid only until the next time                      *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Language_Name(char const * basename)\n{\n\tstatic char _fullname[_MAX_FNAME+_MAX_EXT];\n\n\tif (!basename) return(NULL);\n\n\tsprintf(_fullname, \"%s.ENG\", basename);\n\treturn(_fullname);\n}\n\n\n/***********************************************************************************************\n * Source_From_Name -- Converts ASCII name into SourceType.                                    *\n *                                                                                             *\n *    This routine is used to convert an ASCII name representing a                             *\n *    SourceType into the actual SourceType value. Typically, this is                          *\n *    used when processing the scenario INI file.                                              *\n *                                                                                             *\n * INPUT:   name  -- The ASCII source name to process.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the SourceType represented by the name                                *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSourceType Source_From_Name(char const * name)\n{\n\tif (name) {\n\t\tfor (SourceType source = SOURCE_FIRST; source < SOURCE_COUNT; source++) {\n\t\t\tif (stricmp(SourceName[source], name) == 0) {\n\t\t\t\treturn(source);\n\t\t\t}\n\t\t}\n\t}\n\treturn(SOURCE_NONE);\n}\n\n\n/***********************************************************************************************\n * Name_From_Source -- retrieves the name for the given SourceType         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tsource\t\tSourceType to get the name for\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tname of SourceType\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   11/15/1994 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nchar const * Name_From_Source(SourceType source)\n{\n\tif ((unsigned)source < SOURCE_COUNT) {\n\t\treturn(SourceName[source]);\n\t}\n\treturn(\"None\");\n}\n\n\n/***********************************************************************************************\n * Theater_From_Name -- Converts ASCII name into a theater number.                             *\n *                                                                                             *\n *    This routine converts an ASCII representation of a theater and converts it into a        *\n *    matching theater number. If no match was found, then THEATER_NONE is returned.           *\n *                                                                                             *\n * INPUT:   name  -- Pointer to ASCII name to convert.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the name converted into a theater number.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTheaterType Theater_From_Name(char const * name)\n{\n\tTheaterType\tindex;\n\n\tif (name) {\n\t\tfor (index = THEATER_FIRST; index < THEATER_COUNT; index++) {\n\t\t\tif (stricmp(name, Theaters[index].Name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(THEATER_NONE);\n}\n\n\n/***********************************************************************************************\n * KN_To_Facing -- Converts a keyboard input number into a facing value.                       *\n *                                                                                             *\n *    This routine determine which compass direction is represented by the keyboard value      *\n *    provided. It is used for map scrolling and other directional control operations from     *\n *    the keyboard.                                                                            *\n *                                                                                             *\n * INPUT:   input -- The KN number to convert.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the facing type that the keyboard number represents. If it could      *\n *          not be translated, then FACING_NONE is returned.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFacingType KN_To_Facing(int input)\n{\n\tinput &= ~(KN_ALT_BIT|KN_SHIFT_BIT|KN_CTRL_BIT);\n\tswitch (input) {\n\t\tcase KN_LEFT:\n\t\t\treturn(FACING_W);\n\n\t\tcase KN_RIGHT:\n\t\t\treturn(FACING_E);\n\n\t\tcase KN_UP:\n\t\t\treturn(FACING_N);\n\n\t\tcase KN_DOWN:\n\t\t\treturn(FACING_S);\n\n\t\tcase KN_UPLEFT:\n\t\t\treturn(FACING_NW);\n\n\t\tcase KN_UPRIGHT:\n\t\t\treturn(FACING_NE);\n\n\t\tcase KN_DOWNLEFT:\n\t\t\treturn(FACING_SW);\n\n\t\tcase KN_DOWNRIGHT:\n\t\t\treturn(FACING_SE);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(FACING_NONE);\n}\n\n\n/***********************************************************************************************\n * Sync_Delay -- Forces the game into a 15 FPS rate.                                           *\n *                                                                                             *\n *    This routine will wait until the timer for the current frame has expired before          *\n *    returning. It is called at the end of every game loop in order to force the game loop    *\n *    to run at a fixed rate.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will delay an amount of time according to the game speed setting.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/04/1995 JLB : Created.                                                                 *\n *   03/06/1995 JLB : Fixed.                                                                   *\n *=============================================================================================*/\nstatic void Sync_Delay(void)\n{\n\t/*\n\t**\tAccumulate the number of 'spare' ticks that are frittered away here.\n\t*/\n\tSpareTicks += FrameTimer;\n\n\t/*\n\t**\tDelay until the frame timer expires. This forces the game loop to be regulated to a\n\t**\tspeed controlled by the game options slider.\n\t*/\n\twhile (FrameTimer) {\n\t\tColor_Cycle();\n\t\tCall_Back();\n\n\t\tif (SpecialDialog == SDLG_NONE) {\n#ifdef WIN32\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\t\tKeyNumType input = KN_NONE;\n\t\t\tint x, y;\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\tColor_Cycle();\n\tCall_Back();\n}\n\n\n/***********************************************************************************************\n * Main_Loop -- This is the main game loop (as a single loop).                                 *\n *                                                                                             *\n *    This function will perform one game loop.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should the game end?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Check_For_Focus_Loss(void);\nvoid Reallocate_Big_Shape_Buffer(void);\n#endif\t//WIN32\n\n\nbool Main_Loop()\n{\n\tKeyNumType\tinput;\t\t\t\t\t// Player input.\n\tint x;\n\tint y;\n\tint framedelay;\n\nMono_Set_Cursor(0,0);\n\n\tif (!GameActive) return(!GameActive);\n\n#ifdef WIN32\n\t/*\n\t** Call the focus loss handler\n\t*/\n\tCheck_For_Focus_Loss();\n\n\t/*\n\t** Allocate extra memory for uncompressed shapes as needed\n\t*/\n\tReallocate_Big_Shape_Buffer();\n#endif\n\n\t/*\n\t** Sync-bug trapping code\n\t*/\n\tif (Frame >= Session.TrapFrame) {\n\t\tSession.Trap_Object();\n\t}\n\n\t//\n\t// Initialize our AI processing timer\n\t//\n\tSession.ProcessTimer = TickCount;\n\n#if 1\n\tif (Session.TrapCheckHeap) {\n\t\tDebug_Trap_Check_Heap = true;\n\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\n\t/*\n\t**\tUpdate the running status debug display.\n\t*/\n\tSelf_Regulate();\n#endif\n\n\tBStart(BENCH_GAME_FRAME);\n\n\t/*\n\t**\tIf there is no theme playing, but it looks like one is required, then start one\n\t**\tplaying. This is usually the symptom of there being no transition score.\n\t*/\n\tif (SampleType && Theme.What_Is_Playing() == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t}\n\n\t/*\n\t**\tSetup the timer so that the Main_Loop function processes at the correct rate.\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&\n\t\tSession.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\n\t\t//\n\t\t// In playback mode, run as fast as possible.\n\t\t//\n\t\tif (Session.Play) {\n\t\t\tFrameTimer = 0;\n\t\t} else {\n#ifdef FIXIT_VERSION_3\n\t\t\tif( !Session.DesiredFrameRate )\n\t\t\t\tSession.DesiredFrameRate = 60;\t\t//\tA division by zero was happening (very rare).\n#endif\n\t\t\tframedelay = TIMER_SECOND / Session.DesiredFrameRate;\n\t\t\tFrameTimer = framedelay;\n\t\t}\n\t} else {\n\t\tif (Options.GameSpeed != 0) {\n\t\t\tFrameTimer = Options.GameSpeed +\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0) -\n\t\t\t\t(PlayerPtr->Difficulty == DIFF_HARD ? 1 : 0);\n\t\t} else {\n\t\t\tFrameTimer = Options.GameSpeed + (PlayerPtr->Difficulty == DIFF_EASY ? 1 : 0);\n\t\t}\n\t}\n\n\t/*\n\t**\tUpdate the display, unless we're inside a dialog.\n\t*/\n\tif (!Session.Play) {\n#ifdef WIN32\n\t\tif (SpecialDialog == SDLG_NONE && GameInFocus) {\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#else\n\t\tif (SpecialDialog == SDLG_NONE) {\n#endif\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input) {\n\t\t\t\tKeyboard_Process(input);\n\t\t\t}\n\t\t\tMap.Render();\n\t\t}\n\t}\n\n\t/*\n\t** Save map's position & selected objects, if we're recording the game.\n\t*/\n\tif (Session.Record || Session.Play) {\n\t\tDo_Record_Playback();\n\t}\n\n#ifndef SORTDRAW\n\t/*\n\t** Sort the map's ground layer by y-coordinate value.  This is done\n\t** outside the IsToRedraw check, for the purposes of game sync'ing\n\t** between machines; this way, all machines will sort the Map's\n\t** layer in the same way, and any processing done that's based on\n\t** the order of this layer will remain in sync.\n\t*/\n\tDisplayClass::Layer[LAYER_GROUND].Sort();\n#endif\n\n\t/*\n\t**\tAI logic operations are performed here.\n\t*/\n\tLogic.AI();\n\tTimeQuake = false;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (!PendingTimeQuake) {\n\t\tTimeQuakeCenter = 0;\n\t}\n#endif\n\n\t/*\n\t**\tManage the inter-player message list.  If Manage() returns true, it means\n\t**\ta message has expired & been removed, and the entire map must be updated.\n\t*/\n\tif (Session.Messages.Manage()) {\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\tHidPage.Clear();\n#endif\t//WIN32\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\t//\n\t// Measure how long it took to process the AI\n\t//\n\tSession.ProcessTicks += (TickCount - Session.ProcessTimer);\n\tSession.ProcessFrames++;\n\n\t/*\n\t**\tProcess all commands that are ready to be processed.\n\t*/\n\tQueue_AI();\n\n\t/*\n\t**\tKeep track of elapsed time in the game.\n\t*/\n\tScore.ElapsedTime += TIMER_SECOND / TICKS_PER_SECOND;\n\n\tCall_Back();\n\n\t/*\n\t**\tCheck for player wins or loses according to global event flag.\n\t*/\n\tif (PlayerWins) {\n\n#ifdef WIN32\n\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\t\t//\tPlayer just won.\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerLoses = false;\n\t\tPlayerWins = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Win();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerLoses) {\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game statistics to WChat.\n\t\t*/\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\t\t//\tPlayer just lost.\n\t\t}\n\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Lose();\n\t\treturn(!GameActive);\n\t}\n\tif (PlayerRestarts) {\n#ifdef WIN32\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Restart();\n\t\treturn(!GameActive);\n\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tif( Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && Session.Players.Count() == 2 &&\n\t\tScen.bLocalProposesDraw && Scen.bOtherProposesDraw )\n\t{\n\t\t//\tEnd game in a draw.\n\t\tif (Session.Type == GAME_INTERNET && !GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tSend_Statistics_Packet();\n\t\t}\n\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n\t\tMap.Help_Text(TXT_NONE);\n\t\tDo_Draw();\n\t\treturn(!GameActive);\n\t}\n#endif\n\n\t/*\n\t**\tThe frame logic has been completed. Increment the frame\n\t**\tcounter.\n\t*/\n\tFrame++;\n\n\t/*\n\t** Is there a memory trasher altering the map??\n\t*/\n\tif (Debug_Check_Map) {\n\t\tif (!Map.Validate()) {\n\t\t\tif (WWMessageBox().Process (TEXT_MAP_ERROR, TEXT_STOP, TEXT_CONTINUE)==0) {\n\t\t\t\tGameActive = 0;\n\t\t\t}\n\t\t\tMap.Validate();\t\t// give debugger a chance to catch it\n\t\t}\n\t}\n\n\n#if (0)\t//ST - 5/8/2019\n#ifdef WIN32\n\tif (Debug_MotionCapture) {\n\t\tstatic void ** _array = 0;\n\t\tstatic int _sequence = 0;\n\t\tstatic int _seqsize = Rule.MovieTime * TICKS_PER_MINUTE;\n\n\t\tif (_array == NULL) {\n\t\t\t_array = new void * [_seqsize];\n\t\t\tmemset(_array, '\\0', _seqsize * sizeof(void*));\n\t\t}\n\n\t\tif (_array == NULL) {\n\t\t\tDebug_MotionCapture = false;\n\t\t}\n\n\t\tstatic GraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\n\t\tint size = SeenBuff.Get_Width() * SeenBuff.Get_Height();\n\n\t\tif (_sequence < _seqsize) {\n\t\t\tif (_array[_sequence] == NULL) {\n\t\t\t\t_array[_sequence] = new char[size];\n\t\t\t}\n\n\t\t\tif (_array[_sequence] != NULL) {\n\t\t\t\tSeenBuff.Blit(temp_page);\n\t\t\t\tmemmove(_array[_sequence], temp_page.Get_Buffer(), size);\n\t\t\t}\n\t\t\t_sequence++;\n\n\t\t} else {\n\t\t\tDebug_MotionCapture = false;\n\n\t\t\tCDFileClass file;\n\t\t\tfile.Cache(200000);\n\t\t\tchar filename[30];\n\n\t\t\tfor (int index = 0; index < _sequence; index++) {\n\t\t\t\tmemmove(temp_page.Get_Buffer(), _array[index], size);\n\t\t\t\tsprintf(filename, \"cap%04d.pcx\", index);\n\t\t\t\tfile.Set_Name(filename);\n\n\t\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\t}\n\n\t\t\t_sequence = 0;\n\t\t}\n\t}\n#endif\n#endif\n\tBEnd(BENCH_GAME_FRAME);\n\n\tSync_Delay();\n\treturn(!GameActive);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***************************************************************************\n * Map_Edit_Loop -- a mini-main loop for map edit mode only                *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nbool Map_Edit_Loop(void)\n{\n\t/*\n\t**\tRedraw the map.\n\t*/\n\tMap.Render();\n\n\t/*\n\t**\tGet user input (keys, mouse clicks).\n\t*/\n\tKeyNumType input;\n\n#ifdef WIN32\n\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\n\tint x;\n\tint y;\n\tMap.Input(input, x, y);\n\n\t/*\n\t**\tProcess keypress.\n\t*/\n\tif (input) {\n\t\tKeyboard_Process(input);\n\t}\n\n\tCall_Back();\t\t\t\t\t\t\t\t// maintains Theme.AI() for music\n\tColor_Cycle();\n\n\treturn(!GameActive);\n}\n\n\n/***************************************************************************\n * Go_Editor -- Enables/disables the map editor\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tflag\t\ttrue = go into editor mode; false = go into game mode\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid Go_Editor(bool flag)\n{\n\t/*\n\t**\tGo into Scenario Editor mode\n\t*/\n\tif (flag) {\n\t\tDebug_Map = true;\n\t\tDebug_Unshroud = true;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Turn off the sidebar if it's on\n\t\t*/\n\t\tMap.Activate(0);\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\n\t\tHidPage.Clear();\n#endif\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\n\t} else {\n\n\t\t/*\n\t\t**\tGo into normal game mode\n\t\t*/\n\t\tDebug_Map = false;\n\t\tDebug_Unshroud = false;\n\n\t\t/*\n\t\t** Un-select any selected objects\n\t\t*/\n\t\tUnselect_All();\n\n\t\t/*\n\t\t** Reset the map's Button list for the new mode\n\t\t*/\n\t\tMap.Init_IO();\n\n\t\t/*\n\t\t** Force a complete redraw of the screen\n\t\t*/\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n}\n\n#endif\n\n#if (0)\n/***********************************************************************************************\n * MixFileHandler -- Handles VQ file access.                                                   *\n *                                                                                             *\n *    This routine is called from the VQ player when it needs to access the source file. By    *\n *    using this routine it is possible to virtualize the file system.                         *\n *                                                                                             *\n * INPUT:   vqa   -- Pointer to the VQA handle for this animation.                             *\n *                                                                                             *\n *          action-- The requested action to perform.                                          *\n *                                                                                             *\n *          buffer-- Optional buffer pointer as needed by the type of action.                  *\n *                                                                                             *\n *          nbytes-- The number of bytes (if needed) for this operation.                       *\n *                                                                                             *\n * OUTPUT:  Returns a value consistent with the action requested.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong MixFileHandler(VQAHandle * vqa, long action, void * buffer, long nbytes)\n{\n\tCCFileClass * file;\n\tlong        error;\n\n\tfile = (CCFileClass *)vqa->VQAio;\n\n\t/*\n\t**\tPerform the action specified by the stream command.\n\t*/\n\tswitch (action) {\n\n\t\t/*\n\t\t** VQACMD_READ means read NBytes from the stream and place it in the\n\t\t** memory pointed to by Buffer.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_READ.\n\t\t*/\n\t\tcase VQACMD_READ:\n\t\t\terror = (file->Read(buffer, (unsigned short)nbytes) != (unsigned short)nbytes);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_WRITE is analogous to VQACMD_READ.\n\t\t**\n\t\t** Writing is not allowed to the VQA file, VQA library will remap the\n\t\t** error into VQAERR_WRITE.\n\t\t*/\n\t\tcase VQACMD_WRITE:\n\t\t\terror = 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_SEEK asks that you perform a seek relative to the current\n\t\t** position. NBytes is a signed number, indicating seek direction\n\t\t** (positive for forward, negative for backward). Buffer has no meaning\n\t\t** here.\n\t\t**\n\t\t** Any error code returned will be remapped by VQA library into\n\t\t** VQAERR_SEEK.\n\t\t*/\n\t\tcase VQACMD_SEEK:\n\t\t\terror = (file->Seek(nbytes, SEEK_CUR) == -1);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_OPEN asks that you open your stream for access.\n\t\t*/\n\t\tcase VQACMD_OPEN:\n\t\t\tfile = new CCFileClass((char *)buffer);\n\n\t\t\tif (file != NULL && file->Is_Available()) {\n\t\t\t\terror = file->Open((char *)buffer, READ);\n\n\t\t\t\tif (error != -1) {\n\t\t\t\t\tvqa->VQAio = (unsigned long)file;\n\t\t\t\t\terror = 0;\n\t\t\t\t} else {\n\t\t\t\t\tdelete file;\n\t\t\t\t\tfile = 0;\n\t\t\t\t\terror = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terror = 1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase VQACMD_CLOSE:\n\t\t\tfile->Close();\n\t\t\tdelete file;\n\t\t\tfile = 0;\n\t\t\tvqa->VQAio = 0;\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tVQACMD_INIT means to prepare your stream for reading. This is used for\n\t\t** certain streams that can't be read immediately upon opening, and need\n\t\t** further preparation. This operation is allowed to fail; the error code\n\t\t** will be returned directly to the client.\n\t\t*/\n\t\tcase VQACMD_INIT:\n\n\t\t/*\n\t\t**\tIFFCMD_CLEANUP means to terminate the transaction with the associated\n\t\t** stream. This is used for streams that can't simply be closed. This\n\t\t** operation is not allowed to fail; any error returned will be ignored.\n\t\t*/\n\t\tcase VQACMD_CLEANUP:\n\t\t\terror = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\terror = 0;\n\t\t\tbreak;\n\t}\n\n\treturn(error);\n}\n#endif\n\nvoid Rebuild_Interpolated_Palette(unsigned char * interpal)\n{\n\tfor (int y=0; y<255; y++) {\n\t\tfor (int x=y+1; x<256; x++) {\n\t\t\t*(interpal + (y*256+x)) = *(interpal + (x*256+y));\n\t\t}\n\t}\n}\n\n\nunsigned char \t* InterpolatedPalettes[100];\nBOOL\t\t\t\tPalettesRead;\nunsigned\t\t\tPaletteCounter;\n\n\n/***********************************************************************************************\n * Load_Interpolated_Palettes -- Loads in any precalculated palettes for hires VQs             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Number of palettes loaded                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/7/96 9:49AM ST : Created                                                               *\n *=============================================================================================*/\nint Load_Interpolated_Palettes(char const * filename, BOOL add)\n{\n\tint\tnum_palettes=0;\n\tint\ti;\n\tint \tstart_palette;\n\n\tPalettesRead = FALSE;\n\tCCFileClass\tfile(filename);\n\n\tif (!add) {\n\t\tfor (i=0; i < ARRAY_SIZE(InterpolatedPalettes); i++) {\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t\tstart_palette=0;\n\t} else {\n\t\tfor (start_palette = 0; start_palette < ARRAY_SIZE(InterpolatedPalettes); start_palette++) {\n\t\t\tif (!InterpolatedPalettes[start_palette]) break;\n\t\t}\n\t}\n\n\t/*\n\t**\tHack another interpolated palette if the requested one is\n\t**\tnot present.\n\t*/\n\tif (!file.Is_Available()) {\n\t\tfile.Set_Name(\"AAGUN.VQP\");\n\t}\n\n\tif (file.Is_Available()) {\n\n\t\tfile.Open(READ);\n\t\tfile.Read(&num_palettes , 4);\n\n\t\tfor (i=0; i < num_palettes; i++) {\n\t\t\tInterpolatedPalettes[i+start_palette] = (unsigned char *)malloc (65536);\n\t\t\tmemset (InterpolatedPalettes[i+start_palette], 0, 65536);\n\t\t\tfor (int y = 0; y < 256; y++) {\n\t\t\t\tfile.Read (InterpolatedPalettes[i+start_palette] + y*256 , y+1);\n\t\t\t}\n\n\t\t\tRebuild_Interpolated_Palette(InterpolatedPalettes[i+start_palette]);\n\t\t}\n\n\t\tPalettesRead = TRUE;\n\t\tfile.Close();\n\t}\n\tPaletteCounter = 0;\n\treturn (num_palettes);\n}\n\n\nvoid Free_Interpolated_Palettes(void)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(InterpolatedPalettes) ;i++) {\n\t\tif (InterpolatedPalettes[i]) {\n\t\t\tfree(InterpolatedPalettes[i]);\n\t\t\tInterpolatedPalettes[i]=NULL;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Play_Movie -- Plays a VQ movie.                                                             *\n *                                                                                             *\n *    Use this routine to play a VQ movie. It will dispatch the specified movie to the         *\n *    VQ player. The routine will not return until the movie has finished playing.             *\n *                                                                                             *\n * INPUT:   name  -- The name of the movie file (sans \".VQA\").                                 *\n *                                                                                             *\n *          theme -- The identifier for an optional theme that should be played in the         *\n *                   background while this VQ plays.                                           *\n *                                                                                             *\n *          clrscrn -- 'true' if to clear the screen when the movie is over                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nextern void Suspend_Audio_Thread(void);\nextern void Resume_Audio_Thread(void);\n\n#ifdef MOVIE640\nextern GraphicBufferClass VQ640;\n#endif\n#endif\n\nextern void Play_Movie_GlyphX(const char * movie_name, ThemeType theme, bool immediate);\n\nvoid Play_Movie(char const * name, ThemeType theme, bool clrscrn, bool immediate)\n\t{\n#if (1)\n\tif (strcmp(name, \"x\") == 0 || strcmp(name, \"X\") == 0) {\n\t\treturn;\n\t}\n\n\tPlay_Movie_GlyphX(name, theme, immediate);\n\treturn;\n#else\n\t#ifdef MPEGMOVIE\n\t//theme = theme;\n\t//clrscrn = clrscrn;\n\tif( Using_DVD() )\n\t{\n\t\tif (PlayMpegMovie(name))\n\t\t\treturn;\n\t}\n\t#endif\n\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"Movie: %s\\n\", name);\n\t#endif\t//CHEAT_KEYS\n\t/*\n\t** Don't play movies in editor mode\n\t*/\n\tif (Debug_Map) {\n\t\treturn;\n\t}\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"A\\n\");\n\t#endif\t//CHEAT_KEYS\n\t/*\n\t** Don't play movies in multiplayer mode\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\treturn;\n\t}\n\t#ifdef CHEAT_KEYS\n\t//Mono_Printf(\"b\\n\");\n\t#endif\t//CHEAT_KEYS\n\n\tif (name) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(fullname, NULL, NULL, name, \".VQA\");\n\t\t#ifdef WIN32\n\t\tchar palname [_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(palname , NULL, NULL, name, \".VQP\");\n\t\t#endif\t//WIN32\n\t\t#ifdef CHEAT_KEYS\n\t\t//\t\t\tMono_Set_Cursor(0, 0);Mono_Printf(\"[%s]\", fullname);\n\t\t#endif\n\n\t\tif (!CCFileClass(fullname).Is_Available()){\n\t\t\t#ifdef CHEAT_KEYS\n\t\t\t//\t\t Mono_Printf(\"fullname: %s\\n\", fullname);\n\t\t\t#endif\t//CHEAT_KEYS\n\t\t return;\n\t\t}\n\t\t/*\n\t\t**\tReset the anim control structure.\n\t\t*/\n\t\tAnim_Init();\n\n\t\t/*\n\t\t**\tPrepare to play a movie. First hide the mouse and stop any score that is playing.\n\t\t**\tWhile the score (if any) is fading to silence, fade the palette to black as well.\n\t\t**\tWhen the palette has finished fading, wait until the score has finished fading\n\t\t**\tbefore launching the movie.\n\t\t*/\n\t\tHide_Mouse();\n\t\tTheme.Queue_Song(theme);\n\t\tif (PreserveVQAScreen == 0 && !clrscrn) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM);\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tPreserveVQAScreen = 0;\n\t\tKeyboard->Clear();\n\n\t\tVQAHandle * vqa = NULL;\n\n\n\t\t#ifdef WIN32\n\t\t#ifdef MOVIE640\n\t\tif(IsVQ640) {\n\t\t\tAnimControl.ImageWidth = 640;\n\t\t\tAnimControl.ImageHeight = 400;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t\t} else {\n\t\t\tAnimControl.ImageWidth = 320;\n\t\t\tAnimControl.ImageHeight = 200;\n\t\t\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n\t\t}\n\t\t#endif\n\t\t#endif\n\n\t\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t\t} else {\n\t\t\tAnimControl.OptionFlags &= ~VQAOPTF_AUDIO;\n\t\t}\n\n\t\tif ((vqa = VQA_Alloc()) != NULL) {\n\t\t\tVQA_Init(vqa, MixFileHandler);\n\n\t\t\tif (VQA_Open(vqa, fullname, &AnimControl) == 0) {\n\t\t\t\tBrokeout = false;\n\t\t\t\t#ifdef WIN32\n\t\t\t\t//Suspend_Audio_Thread();\n\t\t\t\t#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tLoad_Interpolated_Palettes(palname);\n\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\tLoad_Interpolated_Palettes(palname);\n\t\t\t\t#endif\n\t\t\t\t//Set_Palette(BlackPalette);\n\t\t\t\tSysMemPage.Clear();\n\t\t\t\tInMovie = true;\n\t\t\t\t#endif\t//WIN32\n\t\t\t\tVQA_Play(vqa, VQAMODE_RUN);\n\t\t\t\tVQA_Close(vqa);\n\t\t\t\t#ifdef WIN32\n\t\t\t\t//Resume_Audio_Thread();\n\t\t\t\tInMovie = FALSE;\n\t\t\t\t#ifdef MOVIE640\n\t\t\t\tif(!IsVQ640) {\n\t\t\t\t\tFree_Interpolated_Palettes();\n\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\tFree_Interpolated_Palettes();\n\t\t\t\t#endif\n\t\t\t\tIsVQ640 = false;\n\t\t\t\tSet_Primary_Buffer_Format();\n\t\t\t\t#endif\t//WIN32\n\n\t\t\t\t/*\n\t\t\t\t**\tAny movie that ends prematurely must have the screen\n\t\t\t\t**\tcleared to avoid any unexpected palette glitches.\n\t\t\t\t*/\n\t\t\t\tif (Brokeout) {\n\t\t\t\t\tclrscrn = true;\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tBrokeout = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t#ifndef NDEBUG\n\t\t\t\tbool error = true;\n\t\t\t\tassert(error);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tVQA_Free(vqa);\n\t\t} else {\n\t\t\tassert(vqa != NULL);\n\t\t}\n\t\t#ifdef CHEAT_KEYS\n\t\t//Mono_Printf(\"d\");\n\t\t#endif\t//CHEAT_KEYS\n\t\t/*\n\t\t**\tPresume that the screen is left in a garbage state as well as the palette\n\t\t**\tbeing in an unknown condition. Recover from this by clearing the screen and\n\t\t**\tforcing the palette to black.\n\t\t*/\n\t\tif (clrscrn) {\n\t\t\tVisiblePage.Clear();\n\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\tBlackPalette.Set();\n\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\tBlackPalette.Set();\n\t\t}\n\t\tShow_Mouse();\n\t}\n#endif\n}\n\n\nvoid Play_Movie(VQType name, ThemeType theme, bool clrscrn, bool immediate)\n{\n\tif (name != VQ_NONE) {\n\t\tif (name == VQ_REDINTRO) {\n\t\t\tIsVQ640 = true;\n\t\t}\n\t\tPlay_Movie(VQName[name], theme, clrscrn, immediate);\n\t\tIsVQ640 = false;\n\t}\n}\n\n\n// Denzil 5/18/98 - Mpeg movie playback\n#ifdef MPEGMOVIE\nextern LPDIRECTDRAWPALETTE PalettePtr;\n\nbool PlayMpegMovie(const char* name)\n\t{\n\tchar path[MAX_PATH];\n\tCCFileClass file;\n\tconst char* filename;\n\n#ifdef CHEAT_KEYS\n\tif( bNoMovies )\n\t\treturn true;\n#endif\n\n\tsprintf(path, \"movies\\\\%.8s.%.3s\", name, \"mpg\");\n\tfilename = file.Set_Name(path);\n\t\n\tif (!file.Is_Available())\n\t\t{\n\t\t#if(1)\n\t\tVisiblePage.Clear();\n\t\tGamePalette.Set();\n\t\tShow_Mouse();\n\t\tsprintf(path, \"Couldn't find %s\\n\", filename);\n\t\tWWMessageBox().Process(path);\n\t\t#endif\n\t\treturn false;\n\t\t}\n\n\t// Stop theme music\n\tif (Misc_Focus_Loss_Function)\n\t\tMisc_Focus_Loss_Function();\n\n\t// Release primary surface\n\tVisiblePage.Un_Init();\n\n\t#ifdef MCIMPEG\n\tif (MciMovie && MpgSettings && (MpgSettings->GetDeviceName() != NULL))\n\t\t{\n\t\tDirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_NORMAL);\n\n\t\tif (!MciMovie->Open(filename, MpgSettings->GetDeviceName()))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't open movie.\\n\");\n\t\t\t}\n\t\telse if (!MciMovie->Play(MainWindow))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't play movie.\\n\");\n\t\t\t}\n\n\t\tDirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);\n\t\t}\n\telse\n\t#endif\n\t\t{\n\t\tDDSURFACEDESC ddsd;\n\t\tIDirectDrawSurface* primary = NULL;\n\t\tbool modeChange = false;\n\t\tRECT rect;\n\t\n\t\tif (FAILED(DirectDrawObject->SetDisplayMode(ScreenWidth, ScreenHeight, 16)))\n\t\t\t{\n\t\t\tWWMessageBox().Process(\"Couldn't change display mode.\\n\");\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t// Create primary surface reference\n\t\t\tmemset(&ddsd, 0, sizeof(ddsd));\n\t\t\tddsd.dwSize = sizeof(ddsd);\n\t\t\tddsd.dwFlags = DDSD_CAPS;\n\t\t\tddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;\n\n\t\t\tif (FAILED(DirectDrawObject->CreateSurface(&ddsd, &primary, NULL)))\n\t\t\t\t{\n\t\t\t\tWWMessageBox().Process(\"Couldn't create primary movie surface.\\n\");\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\trect.top = rect.left = 0;\n\t\t\t\trect.bottom = ScreenHeight;\n\t\t\t\trect.right = ScreenWidth;\n\t\t\n\t\t\t\tMpgSetCallback(MpegCallback, NULL);\n\t\t\t\tMpgPlay(filename, DirectDrawObject, primary, &rect);\n\n\t\t\t\tif (primary)\n\t\t\t\t\tprimary->Release();\n\n\t\t\t\t}\n\n\t\t\tDirectDrawObject->SetDisplayMode(ScreenWidth, ScreenHeight, 8);\n\t\t\t}\n\t\t}\n\n\t// Restore surfaces\n\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\tPaletteSurface->SetPalette(PalettePtr);\n\tAllSurfaces.Set_Surface_Focus(true);\n\tAllSurfaces.Restore_Surfaces();\n\treturn true;\n\t}\n\n\nMPG_RESPONSE far __stdcall MpegCallback(MPG_CMD cmd, LPVOID data, LPVOID user)\n\t{\n\tstatic IDirectDrawPalette* _palette = NULL;\n\n\tuser = user;\n\n\tswitch (cmd)\n\t\t{\n\t\tcase MPGCMD_ERROR:\n\t\t\tWWMessageBox().Process((char const *)data);\n\t\tbreak;\n\n\t\tcase MPGCMD_INIT:\n\t\t\tVisiblePage.Clear();\n\t\tbreak;\n\n\t\tcase MPGCMD_CLEANUP:\n\t\t\tVisiblePage.Clear();\n\n\t\t\tif (_palette != NULL)\n\t\t\t\t{\n\t\t\t\tPaletteSurface->SetPalette(_palette);\n\t\t\t\t_palette->Release();\n\t\t\t\t_palette = NULL;\n\t\t\t\t}\n\t\tbreak;\n\t\t\n\t\tcase MPGCMD_PALETTE:\n\t\t\tif (FAILED(PaletteSurface->GetPalette(&_palette)))\n\t\t\t\t{\n\t\t\t\tWWMessageBox().Process(\"Couldn't get primary palette.\\n\");\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif (FAILED(PaletteSurface->SetPalette((IDirectDrawPalette*)data)))\n\t\t\t\t\t{\n\t\t\t\t\tWWMessageBox().Process(\"Couldn't set movie palette.\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\tbreak;\n\t\t\n\t\tcase MPGCMD_UPDATE:\n\t\t\tif ((BreakoutAllowed || Debug_Flag) && Keyboard->Check())\n\t\t\t\t{\n\t\t\t\tif (Keyboard->Get() == KN_ESC)\n\t\t\t\t\t{\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\treturn MPGRES_QUIT;\n\t\t\t\t\t}\n\n\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\n\t\t\tif (!GameInFocus)\n\t\t\t\t{\n\t\t\t\tMpgPause();\n\n\t\t\t\twhile (!GameInFocus)\n\t\t\t\t\t{\n\t\t\t\t\tCheck_For_Focus_Loss();\n\t\t\t\t\t}\n\n\t\t\t\tMpgResume();\n\t\t\t\treturn MPGRES_LOSTFOCUS;\n\t\t\t\t}\n\t\tbreak;\n\n\t\tdefault:\n\t\tbreak;\n\t\t}\n\n\treturn MPGRES_CONTINUE;\n\t}\n#endif\n\n/***********************************************************************************************\n * Unselect_All -- Causes all selected objects to become unselected.                           *\n *                                                                                             *\n *    This routine will unselect all objects that are currently selected.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Unselect_All(void)\n{\n\t//while (CurrentObject.Count()) {\n\t//\tCurrentObject[0]->Unselect();\n\t//}\n\n\t//Added some error handling incase there was an issue removing the object - JAS 6/28/2019\n\twhile (CurrentObject.Count()) {\n\n\t\tint count_before = CurrentObject.Count();\n\t\tCurrentObject[0]->Unselect();\n\n\t\tif (count_before <= CurrentObject.Count()) {\n\t\t\tGlyphX_Debug_Print(\"Unselect_All failed to remove an object\");\n\t\t\tCurrentObject.Delete(CurrentObject[0]);\n\t\t}\n\t}\n\t//End of change - JAS 6/28/2019\n\n}\n\n\nvoid Unselect_All_Except(ObjectClass* object)\n{\n\tint index = 0;\n\twhile (index < CurrentObject.Count()) {\n\n\t\tif (CurrentObject[index] == object) {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tint count_before = CurrentObject.Count();\n\t\tCurrentObject[index]->Unselect();\n\n\t\tif (count_before <= CurrentObject.Count()) {\n\t\t\tGlyphX_Debug_Print(\"Unselect_All failed to remove an object\");\n\t\t\tCurrentObject.Delete(CurrentObject[index]);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Fading_Table_Name -- Builds a theater specific fading table name.                           *\n *                                                                                             *\n *    This routine builds a standard fading table name. This name is dependant on the theater  *\n *    being played, since each theater has its own palette.                                    *\n *                                                                                             *\n * INPUT:   base  -- The base name of this fading table. The base name can be no longer than   *\n *                   seven characters.                                                         *\n *                                                                                             *\n *          theater  -- The theater that this fading table is specific to.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the constructed fading table filename. This pointer is   *\n *          valid until this function is called again.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * Fading_Table_Name(char const * base, TheaterType theater)\n{\n\tstatic char _buffer[_MAX_FNAME+_MAX_EXT];\n\tchar root[_MAX_FNAME];\n\n\tsprintf(root, \"%1.1s%s\", Theaters[theater].Root, base);\n\t_makepath(_buffer, NULL, NULL, root, \".MRF\");\n\treturn(_buffer);\n}\n\n\n/***********************************************************************************************\n * Get_Radar_Icon -- Builds and alloc a radar icon from a shape file                           *\n *                                                                                             *\n * INPUT:      void const * shapefile - pointer to a key framed shapefile                      *\n *             int shapenum          - shape to extract from shapefile                         *\n *                                                                                             *\n * OUTPUT:     void const *           - 3/3 icon set of shape from file                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/12/1995 PWG : Created.                                                                 *\n *   05/10/1995 JLB : Handles a null shapefile pointer.                                        *\n *=============================================================================================*/\nvoid const * Get_Radar_Icon(void const * shapefile, int shapenum, int frames, int zoomfactor)\n{\n\tstatic int _offx[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tstatic int _offy[]={\t0, 0,  -1,  1, 0, -1, 1, -1, 1};\n\tint lp,framelp;\n\tchar pixel;\n\n\tchar * retval = NULL;\n\tchar * buffer = NULL;\n\n\t/*\n\t**\tIf there is no shape file, then there can be no radar icon imagery.\n\t*/\n\tif (!shapefile) return(NULL);\n\n#if (0)\n\tCCPalette.Set();\n\tSet_Logic_Page(SeenBuff);\n\tCC_Draw_Shape(shapefile, shapenum, 64, 64, WINDOW_MAIN, SHAPE_WIN_REL);\n#endif\n\n\t/*\n\t** Get the pixel width and height of the frame we built.  This will\n\t** be used to extract icons and build pixels.\n\t*/\n\tint pixel_width  = Get_Build_Frame_Width( shapefile );\n\tint pixel_height = Get_Build_Frame_Height( shapefile );\n\n\t/*\n\t** Find the width and height in icons, adjust these by half an\n\t** icon because the artists may be sloppy and miss the edge of an\n\t** icon one way or the other.\n\t*/\n\tint icon_width\t = (pixel_width + 12) / 24;\n\tint icon_height = (pixel_height + 12) / 24;\n\n\t/*\n\t** If we have been told to build as many frames as possible, then\n\t** find out how many frames there are to build.\n\t*/\n\tif (frames == -1) frames = Get_Build_Frame_Count( shapefile );\n\n\t/*\n\t** Allocate a position to store our icons.  If the alloc fails then\n\t** we don't add these icons to the set.\n\t**/\n\tbuffer = new char[(icon_width * icon_height * 9 * frames)+2];\n\tif (!buffer) return(NULL);\n\n\t/*\n\t** Save off the return value so that we can return it to the calling\n\t** function.\n\t*/\n\tretval\t = (char *)buffer;\n\t*buffer++ = (char)icon_width;\n\t*buffer++ = (char)icon_height;\n\tint val = 24/zoomfactor;\n\n\tfor (framelp = 0; framelp < frames; framelp ++) {\n\t\t/*\n\t\t** Build the current frame.  If the frame can not be built then we\n\t\t** just need to skip past this set of icons and try to build the\n\t\t** next frame.\n\t\t*/\n#ifdef WIN32\n\t\tvoid * ptr;\n\t\tif ((ptr = (void *)(Build_Frame(shapefile, shapenum + framelp, SysMemPage.Get_Buffer()))) != NULL) {\n\t\t\tptr = Get_Shape_Header_Data(ptr);\n#else\t//WIN#@\n\t\tif (Build_Frame(shapefile, shapenum + framelp, HidPage.Get_Buffer()) <= (unsigned long)HidPage.Get_Size() ) {\n#endif\t//WIN32\n\n\t\t\t/*\n\t\t\t** Loop through the icon width and the icon height building icons\n\t\t\t** into the buffer pointer.  When the getx or gety falls outside of\n\t\t\t** the width and height of the shape, just insert transparent pixels.\n\t\t\t*/\n\t\t\tfor (int icony = 0; icony < icon_height; icony ++) {\n\t\t\t\tfor (int iconx = 0; iconx < icon_width; iconx ++) {\n#ifdef WIN32\n\n\t\t\t\t\tfor (int y = 0; y < zoomfactor; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < zoomfactor; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y * val) + (zoomfactor / 2);\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)ptr + ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n\n#else\t//WIN32\n\t\t\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\t\t\t\tint getx = (iconx * 24) + (x << 3) + 4;\n\t\t\t\t\t\t\tint gety = (icony * 24) + (y << 3) + 4;\n\t\t\t\t\t\t\tif ((getx < pixel_width) && (gety < pixel_height)) {\n\t\t\t\t\t\t\t\tfor (lp = 0; lp < 9; lp ++) {\n\t\t\t\t\t\t\t\t\tpixel\t= *(char *)((char *)HidPage.Get_Buffer(), ((gety - _offy[lp]) * pixel_width) + getx-_offx[lp]);\n#endif\t//WIN32\n\t\t\t\t\t\t\t\t\tif (pixel == LTGREEN) pixel = 0;\n\t\t\t\t\t\t\t\t\tif (pixel) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t*buffer++ = pixel;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t*buffer++ = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tbuffer += icon_width * icon_height * 9;\n\t\t}\n\t}\n\treturn(retval);\n}\n\n\nextern void DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name, char override_owner);\nextern void DLL_Draw_Pip_Intercept(const ObjectClass* object, int pip);\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation);\n\nvoid CC_Draw_Shape(const ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long virtualscale, int width, int height)\n{\n\tif (window == WINDOW_VIRTUAL) {\n\t\tif (width == 0) width = Get_Build_Frame_Width(shapefile);\n\t\tif (height == 0) height = Get_Build_Frame_Height(shapefile);\n\t\tDLL_Draw_Intercept(shapenum, x, y, width, height, (int)flags, object, rotation, virtualscale, NULL, HOUSE_NONE);\n\t\treturn;\n\t}\n\n\tCC_Draw_Shape(shapefile, shapenum, x, y, window, flags, fadingdata, ghostdata, rotation);\n}\n\nvoid CC_Draw_Shape(const ObjectClass *object, const char *shape_file_name, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long virtualscale, char override_owner)\n{\n\tif (window == WINDOW_VIRTUAL) {\n\t\tint width = Get_Build_Frame_Width(shapefile);\n\t\tint height = Get_Build_Frame_Height(shapefile);\n\t\tDLL_Draw_Intercept(shapenum, x, y, width, height, (int)flags, object, rotation, virtualscale, shape_file_name, override_owner);\n\t\treturn;\n\t}\n\n\tCC_Draw_Shape(shapefile, shapenum, x, y, window, flags, fadingdata, ghostdata, rotation);\n}\n\n\nvoid CC_Draw_Pip(const ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation)\n{\n\tif (window == WINDOW_VIRTUAL) {\n\t\tDLL_Draw_Pip_Intercept(object, shapenum);\n\t\treturn;\n\t}\n\n\tCC_Draw_Shape(shapefile, shapenum, x, y, window, flags, fadingdata, ghostdata, rotation);\n}\n\n\n/***********************************************************************************************\n * CC_Draw_Shape -- Custom draw shape handler.                                                 *\n *                                                                                             *\n *    All draw shape calls will route through this function. It handles all draws for          *\n *    C&C. Such draws always occur to the logical page and assume certain things about         *\n *    the parameters passed.                                                                   *\n *                                                                                             *\n * INPUT:   shapefile   -- Pointer to the shape data file. This data file contains all the     *\n *                         embedded shapes.                                                    *\n *                                                                                             *\n *          shapenum    -- The shape number within the shapefile that will be drawn.           *\n *                                                                                             *\n *          x,y         -- The pixel coordinates to draw the shape.                            *\n *                                                                                             *\n *          window      -- The clipping window to use.                                         *\n *                                                                                             *\n *          flags       -- The custom draw shape flags. This controls how the parameters       *\n *                         are used (if any).                                                  *\n *                                                                                             *\n *          fadingdata  -- If SHAPE_FADING is desired, then this points to the fading          *\n *                         data table.                                                         *\n *                                                                                             *\n *          ghostdata   -- If SHAPE_GHOST is desired, then this points to the ghost remap      *\n *                         table.                                                              *\n *                                                                                             *\n *          rotation    -- Rotation to apply to the shape (DIR_N = no rotation at all).        *\n *                                                                                             *\n *          scale       -- 24.8 fixed point scale factor.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation)\n{\n\tint predoffset;\n#ifdef WIN32\n\tunsigned\tlong\tshape_pointer;\n#endif\t//WIN32\n\n\n\t/*\n\t** Special kludge for E3 to prevent crashes\n\t*/\n\tif ((flags & SHAPE_GHOST) && (!ghostdata)) {\n\t\tghostdata = DisplayClass::SpecialGhost;\n\t}\n\tif ((flags & SHAPE_FADING) && (!fadingdata)) {\n\t\tfadingdata = DisplayClass::FadingShade;\n\t}\n\n\tstatic unsigned char * _xbuffer = 0;\n\n\tif (!_xbuffer) {\n\t\t_xbuffer = new unsigned char[SHAPE_BUFFER_SIZE];\n\t}\n\n\tif (shapefile != NULL && shapenum != -1) {\n\n\t\tint width = Get_Build_Frame_Width(shapefile);\n\t\tint height = Get_Build_Frame_Height(shapefile);\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tPerform a quick clip check against the destination rectangle.\n\t\t*/\n\t\tif (flags & SHAPE_CENTER) {\n\t\t\tif (x-width/2 >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y-width/2 >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width/2 < 0) return;\n\t\t\tif (y+height/2 < 0) return;\n\n\t\t} else {\n\t\t\tif (x >= WindowList[window][WINDOWWIDTH]) return;\n\t\t\tif (y >= WindowList[window][WINDOWHEIGHT]) return;\n\t\t\tif (x+width < 0) return;\n\t\t\tif (y+height < 0) return;\n\t\t}\n#endif\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** In WIn95, build shape returns a pointer to the shape not its size\n\t\t*/\n\t\tshape_pointer = Build_Frame(shapefile, shapenum, _ShapeBuffer);\n\t\tif (shape_pointer) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *) shape_pointer;\t//Get_Shape_Header_Data((void*)shape_pointer);\n\n#else\t//WIN32\n\t\tif ( Build_Frame(shapefile, shapenum, _ShapeBuffer ) <= (unsigned long)_ShapeBufferSize) {\n\t\t\tGraphicViewPortClass draw_window(LogicPage,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT]);\n\t\t\tunsigned char * buffer = (unsigned char *)_ShapeBuffer;\n#endif\t//WIN32\n\n\t\t\tUseOldShapeDraw = false;\n\t\t\t/*\n\t\t\t**\tRotation handler.\n\t\t\t*/\n\t\t\tif (rotation != DIR_N) {\n\n\t\t\t\t/*\n\t\t\t\t** Get the raw shape data without the new header and flag to use the old shape drawing\n\t\t\t\t*/\n\t\t\t\tUseOldShapeDraw = true;\n#ifdef WIN32\n\t\t\t\tbuffer = (unsigned char *) Get_Shape_Header_Data((void*)shape_pointer);\n#endif\n\n\t\t\t\tif (Debug_Rotate) {\n#if (0)//PG\n\t\t\t\t\tGraphicBufferClass src(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass dst(width, height, _xbuffer);\n\t\t\t\t\tRotate_Bitmap(&src, &dst, rotation);\n\t\t\t\t\tbuffer = _xbuffer;\n#endif\n\t\t\t\t} else {\n\n\t\t\t\t\tBitmapClass bm(width, height, buffer);\n\t\t\t\t\twidth *= 2;\n\t\t\t\t\theight *= 2;\n\t\t\t\t\tmemset(_xbuffer, '\\0', SHAPE_BUFFER_SIZE);\n\t\t\t\t\tGraphicBufferClass gb(width, height, _xbuffer);\n\t\t\t\t\tTPoint2D pt(width/2, height/2);\n\n\t\t\t\t\tgb.Scale_Rotate(bm, pt, 0x0100, (256-(rotation-64)));\n\t\t\t\t\tbuffer = _xbuffer;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial shadow drawing code (used for aircraft and bullets).\n\t\t\t*/\n\t\t\tif ((flags & (SHAPE_FADING|SHAPE_PREDATOR)) == (SHAPE_FADING|SHAPE_PREDATOR)) {\n\t\t\t\tflags = flags & ~(SHAPE_FADING|SHAPE_PREDATOR);\n\t\t\t\tflags = flags | SHAPE_GHOST;\n\t\t\t\tghostdata = DisplayClass::SpecialGhost;\n\t\t\t}\n\n\t\t\tpredoffset = Frame;\n\n\t\t\tif (x > ( WindowList[window][WINDOWWIDTH] << 2)) {\n\t\t\t\tpredoffset = -predoffset;\n\t\t\t}\n\n\t\t\tif (draw_window.Lock()) {\n\t\t\t\tif ((flags & (SHAPE_GHOST|SHAPE_FADING)) == (SHAPE_GHOST|SHAPE_FADING)) {\n\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, fadingdata, 1, predoffset);\n\t\t\t\t} else {\n\t\t\t\t\tif (flags & SHAPE_FADING) {\n\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, fadingdata, 1, predoffset);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (flags & SHAPE_PREDATOR) {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, predoffset);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tBuffer_Frame_To_Page(x, y, width, height, buffer, draw_window, flags | SHAPE_TRANS, ghostdata, predoffset);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdraw_window.Unlock();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Shape_Dimensions -- Determine the minimum rectangle for the shape.                          *\n *                                                                                             *\n *    This routine will calculate (using brute forced) the minimum rectangle that will         *\n *    enclose the pixels of the shape. This rectangle will be relative to the upper left       *\n *    corner of the maximum shape size. By using this minimum rectangle, it is possible to     *\n *    greatly optimize the map 'dirty rectangle' logic.                                        *\n *                                                                                             *\n * INPUT:   shapedata   -- Pointer to the shape data block.                                    *\n *                                                                                             *\n *          shapenum    -- The shape number to examine. Each shape would have a different      *\n *                         dimension rectangle.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the rectangle that encloses the shape.                                *\n *                                                                                             *\n * WARNINGS:   This routine uses brute force and is slow. It is presumed that the results      *\n *             will be cached for subsiquent reuse.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect const Shape_Dimensions(void const * shapedata, int shapenum)\n{\n\tRect rect;\n\n\tif (shapedata == NULL || shapenum < 0 || shapenum > Get_Build_Frame_Count(shapedata)) {\n\t\treturn(rect);\n\t}\n\n\tchar * shape;\n#ifdef WIN32\n\tvoid * sh = (void *)Build_Frame(shapedata, shapenum, _ShapeBuffer);\n\tif (sh == NULL) return(rect);\n//\tshape = (char *)sh;\n\tshape = (char *)Get_Shape_Header_Data(sh);\n#else\n\tBuild_Frame(shapedata, shapenum, _ShapeBuffer);\n\tshape = (char *)_ShapeBuffer;\n#endif\n\n\tint width = Get_Build_Frame_Width(shapedata);\n\tint height = Get_Build_Frame_Height(shapedata);\n\n\trect.X = 0;\n\trect.Y = 0;\n\tint xlimit = width-1;\n\tint ylimit = height-1;\n\n\t/*\n\t**\tFind top edge of the shape.\n\t*/\n\tfor (int y = 0; y <= ylimit; y++) {\n\t\tfor (int x = 0; x <= xlimit; x++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Y = y;\n\t\t\t\trect.X = x;\n\t\t\t\ty = ylimit+1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind bottom edge of the shape.\n\t*/\n\tfor (int y = ylimit; y >= rect.Y; y--) {\n\t\tfor (int x = xlimit; x >= 0; x--) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Height = (y-rect.Y)+1;\n\t\t\t\txlimit = x;\n\t\t\t\ty = rect.Y-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind left edge of the shape.\n\t*/\n\tfor (int x = 0; x < rect.X; x++) {\n\t\tfor (int y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.X = x;\n\t\t\t\tx = rect.X;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFind the right edge of the shape.\n\t*/\n\tfor (int x = width-1; x >= xlimit; x--) {\n\t\tfor (int y = rect.Y; y < rect.Y+rect.Height; y++) {\n\t\t\tif (shape[y*width + x] != 0) {\n\t\t\t\trect.Width = (x-rect.X)+1;\n\t\t\t\tx = xlimit-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tNormalize the rectangle around the center of the shape.\n\t*/\n\trect.X -= width / 2;\n\trect.Y -= height / 2;\n\n\t/*\n\t**\tReturn with the minimum rectangle that encloses the shape.\n\t*/\n\treturn(rect);\n}\n\n\n/***********************************************************************************************\n * Fetch_Techno_Type -- Convert type and ID into TechnoTypeClass pointer.                      *\n *                                                                                             *\n *    This routine will convert the supplied RTTI type number and the ID value into a valid    *\n *    TechnoTypeClass pointer. If there is an error in conversion, then NULL is returned.      *\n *                                                                                             *\n * INPUT:   type  -- RTTI type of the techno class object.                                     *\n *                                                                                             *\n *          id    -- Integer representation of the techno sub type number.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the techno type class object specified or NULL if the    *\n *          conversion could not occur.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * Fetch_Techno_Type(RTTIType type, int id)\n{\n\tswitch (type) {\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_UNIT:\n\t\t\treturn(&UnitTypeClass::As_Reference(UnitType(id)));\n\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(&VesselTypeClass::As_Reference(VesselType(id)));\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(&BuildingTypeClass::As_Reference(StructType(id)));\n\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(&InfantryTypeClass::As_Reference(InfantryType(id)));\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(&AircraftTypeClass::As_Reference(AircraftType(id)));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * VQ_Call_Back -- Maintenance callback used for VQ movies.                                    *\n *                                                                                             *\n *    This routine is called every frame of the VQ movie as it is being played. If this        *\n *    routine returns non-zero, then the movie will stop.                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the image buffer for the current frame.                     *\n *                                                                                             *\n *          frame    -- The frame number about to be displayed.                                *\n *                                                                                             *\n * OUTPUT:  Should the movie be stopped?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\nvoid VQA_PauseAudio(void) {};\nvoid Check_VQ_Palette_Set(void);\n\nextern GraphicBufferClass VQ640;\nextern bool IsVQ640;\nlong VQ_Call_Back(unsigned char *, long )\n{\n\treturn 0;\n#if (0)//PG\n\tint key = 0;\n\tif (Keyboard->Check()) {\n\t\tkey = Keyboard->Get();\n\t\tKeyboard->Clear();\n\t}\n\tCheck_VQ_Palette_Set();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tVQ640.Blit(SeenBuff);\n\t} else {\n\t\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n\t}\n#else\n\tInterpolate_2X_Scale(&SysMemPage, &SeenBuff, NULL);\n#endif\n\t//Call_Back();\n\n\tif ((BreakoutAllowed || Debug_Flag) && key == KN_ESC) {\n\t\tKeyboard->Clear();\n\t\tBrokeout = true;\n\t\treturn(true);\n\t}\n\n\tif (!GameInFocus) {\n\t\tVQA_PauseAudio();\n\t\twhile (!GameInFocus) {\n\t\t\tCheck_For_Focus_Loss();\n\t\t}\n\t}\n\treturn(false);\n#endif\n}\n\n#else\t//WIN32\n\nlong VQ_Call_Back(unsigned char *, long )\n{\n\tCall_Back();\n\tif ((BreakoutAllowed || Debug_Flag) && Keyboard->Check()) {\n\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\tKeyboard->Clear();\n\t\t\tBrokeout = true;\n\t\t\treturn(true);\n\t\t}\n\t\tKeyboard->Clear();\n\t}\n\treturn(false);\n}\n#endif\t//WIN32\n\n\n/***********************************************************************************************\n * Handle_Team -- Processes team selection command.                                            *\n *                                                                                             *\n *    This routine will handle creation and selection of pseudo teams that the player can      *\n *    create or control. A team in this sense is an arbitrary grouping of units such that      *\n *    rapid selection control is allowed.                                                      *\n *                                                                                             *\n * INPUT:   team  -- The logical team number to process.                                       *\n *                                                                                             *\n *          action-- The action to perform on this team:                                       *\n *                   0 - Toggle the select state for all members of this team.                 *\n *                   1 - Select the members of this team.                                      *\n *                   2 - Make all selected objects members of this team.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_Team(int team, int action)\n{\n\tint index;\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tTeamNumber = (char)team;\n\t\tTeamEvent = (char)action + 1;\n\t}\n\n\tTeamFormDataStruct& team_form_data = TeamFormData[PlayerPtr->Class->House];\n\n\tAllowVoice = true;\n\tswitch (action) {\n\n\t\t/*\n\t\t**\tToggle the team selection. If the team is selected, then merely unselect it. If the\n\t\t**\tteam is not selected, then unselect all others before selecting this team.\n\t\t*/\n\t\tcase 3:\n\t\tcase 0:\n\n\t\t\t/*\n\t\t\t**\tIf a non team member is currently selected, then deselect all objects\n\t\t\t**\tbefore selecting this team.\n\t\t\t*/\n\t\t\tfor (index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\tObjectClass * obj = CurrentObject[index];\n\t\t\t\tif (obj->Is_Foot() && ((FootClass *)obj)->Group != team) {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCenter the map around the team if the ALT key was pressed too.\n\t\t\t*/\n\t\t\tif (action == 3) {\n\t\t\t\tMap.Center_Map();\n#ifdef WIN32\n\t\t\t\tMap.Flag_To_Redraw(true);\n#endif\t//WIn32\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdditive selection of team.\n\t\t*/\n\t\tcase 1:\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->Group == team && obj->House->IsPlayerControl) {\n\t\t\t\t\tif (!obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tCreate the team.\n\t\t*/\n\t\tcase 2: {\n\t\t\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\t\t\tlong maxx = 0, maxy = 0;\n\t\t\tteam_form_data.TeamSpeed[team] = SPEED_WHEEL;\n\t\t\tteam_form_data.TeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tteam_form_data.TeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = -1;\n\t\t\t\t\tif (obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t\tteam_form_data.TeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobj->Group = team;\n\t\t\t\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl &&\n\t\t\t\t \t(obj->Group == team) && (obj->Is_Selected_By_Player()) ) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** When a team is first created, they're created without a\n\t\t\t\t\t** formation offset, so they will not be created in\n\t\t\t\t\t** formation.  Later, if they're assigned a formation, the\n\t\t\t\t\t** XFormOffset & YFormOffset numbers will change to valid\n\t\t\t\t\t** offsets, and they'll be formationed.\n\t\t\t\t\t*/\n#if(1)\n\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House->IsPlayerControl) {\n\t\t\t\t \tif (obj->Group == team) obj->Group = 0xFF;\n\t\t\t\t\tif (obj->Is_Selected_By_Player()) obj->Group = team;\n\t\t\t\t\tif (obj->Group == team  && obj->Is_Selected_By_Player()) {\n#if(1)\n\t\t\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n#else\n#if(1)\n// Old always-north formation stuff\n\t\t\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\t\t\tobj->YFormOffset = yc - centery;\n#else\n// New method: save direction and distance rather than x & y offset\n\t\t\t\t\t\tobj->XFormOffset = ::Direction(As_Coord(center), obj->Center_Coord());\n\t\t\t\t\t\tobj->YFormOffset = ::Distance (As_Coord(center), obj->Center_Coord());\n#endif\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tAllowVoice = true;\n}\n\n\n/***********************************************************************************************\n * Handle_View -- Either records or restores the tactical view.                                *\n *                                                                                             *\n *    This routine is used to record or restore the current map tactical view.                 *\n *                                                                                             *\n * INPUT:   view  -- The view number to work with.                                             *\n *                                                                                             *\n *          action-- The action to perform with this view number.                              *\n *                   0  =  Restore the view to this previously remembered location.            *\n *                   1  =  Record the current view location.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Handle_View(int view, int action)\n{\n\tif ((unsigned)view < ARRAY_SIZE(Scen.Views)) {\n\t\tif (action == 0) {\n\n\t\t\tMap.Set_Tactical_Position(Coord_Whole(Cell_Coord(Scen.Views[view] - (MAP_CELL_W * 4 * RESFACTOR) - (5*RESFACTOR))));\n\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Win95 scrolling logic cant handle just jumps in screen position so redraw the lot.\n\t\t\t*/\n\t\t\tMap.Flag_To_Redraw (true);\n#endif\t//WIN32\n\t\t} else {\n\t\t\tScen.Views[view] = Coord_Cell(Map.TacticalCoord) + (MAP_CELL_W*4*RESFACTOR) + (5*RESFACTOR);\n\t\t}\n\t}\n}\n\n\n#ifndef ROR_NOT_READY\n#define ROR_NOT_READY 21\n#endif\n\nstatic char * _CD_Volume_Label[] = {\n\t\"CD1\",\n\t\"CD2\",\n\t\"CD3\",\n\t\"CD4\",\n\t// Denzil 4/15/98\n\t#ifdef DVD\n\t\"CD1\",\t\t//\tajw - Pushes RADVD to position 5, to match enum in Force_CD_Available(). 4 will never be returned here.\n\t\"RADVD\",\n\t#endif\n};\nstatic int _Num_Volumes = ARRAY_SIZE(_CD_Volume_Label);\n\n\n#ifdef WIN32\n/***********************************************************************************************\n * Get_CD_Index -- returns the volume type of the CD in the given drive                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    drive number                                                                      *\n *           timeout                                                                           *\n *                                                                                             *\n * OUTPUT:   0 = gdi                                                                           *\n *           1 = nod                                                                           *\n *           2 = covert or CS                                                                       *\n *           3 = Aftermath\n *           5 = DVD\n *          -1 = non C&C                                                                       *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/21/96 5:27PM ST : Created                                                              *\n *    01/20/97 V.Grippi added CS support\t\t\t\t\t\t\t\t\t\t\t       *\n *=============================================================================================*/\nint Get_CD_Index (int cd_drive, int timeout)\n\t{\n\tchar\t\tvolume_name[128];\n\tchar\t\tbuffer[128];\n\tunsigned\tfilename_length;\n\tunsigned\tmisc_dword;\n\tint\t\tcount = 0;\n\n\tCountDownTimerClass timer;\n\n\ttimer.Set(timeout);\n\n\t/*\n\t** Get the volume label. If we get a 'not ready' error then retry for the timeout\n\t** period.\n\t*/\n\tfor (;;)\n\t\t{\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\n\t\tif (GetVolumeInformation ((char const *)buffer, &volume_name[0] ,\n\t\t\t\t(unsigned long)sizeof(volume_name), (unsigned long *)NULL ,\n\t\t\t\t(unsigned long *)&filename_length, (unsigned long *)&misc_dword,\n\t\t\t\t(char *)NULL, (unsigned long)0))\n\t\t\t{\n\t\t\t/*\n\t\t\t** Try opening 'movies.mix' to verify that the CD is really there and is what\n\t\t\t** it says it is.\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\n\t\t\tHANDLE handle = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n\t\t\tif (handle != INVALID_HANDLE_VALUE)\n\t\t\t\t{\n\t\t\t\tCloseHandle(handle);\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i = 0 ; i < _Num_Volumes; i++)\n\t\t\t\t\t{\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], volume_name))\n\t\t\t\t\t\treturn(i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif (!count)\n\t\t\t\t\tcount++;\n\t\t\t\telse\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/*\n\t\t\t** Failed to get the volume label on a known CD drive.\n\t\t\t** If this is a CD changer it may require time to swap the disks so dont return\n\t\t\t** immediately if the error is ROR_NOT_READY\n\t\t\t*/\n\t\t\tif (!timer.Time())\n\t\t\t\treturn -1;\n\t\t\t\t\n\t\t\tint val = GetLastError();\n\t\t\t\n\t\t\tif (val != ROR_NOT_READY)\n\t\t\t\treturn -1;\n\t\t\t}\t\n\t\t}\n\t}\n#else\nint Get_CD_Index(int cd_drive, int)\n\t{\n\tchar buffer[128];\n\n\t/*\n\t** We need to do this twice because of the possibilities of a directory\n\t** being cached.  If this is so, it will only be discovered when we\n\t** actually attempt to read a file from the drive.\n\t*/\n\tif(cd_drive) for (int count = 0; count < 2; count ++)\n\t\t{\n\t\tstruct find_t ft;\n\t\tint file;\n\t\tint open_failed;\n\n\t\t/*\n\t\t** Create a path for the cd drive and attempt to read the volume label from\n\t\t** it.\n\t\t*/\n\t\tsprintf(buffer, \"%c:\\\\\", 'A' + cd_drive);\n\n\t\t/*\n\t\t** If we are able to read the volume label, this is good but not enough.\n\t\t** Further verification must be done.\n\t\t*/\n\t\tif (!_dos_findfirst(buffer, _A_VOLID, &ft))\n\t\t\t{\n\t\t\t/*\n\t\t\t** Since some versions of disk cacheing software will cache the CD's\n\t\t\t** directory tracks, we may think the CD is in the drive when it is\n\t\t\t** actually not.  To resolve this we must attempt to open a file on\n\t\t\t** the cd.  Opening a file will always update the directory tracks\n\t\t\t** (suposedly).\n\t\t\t*/\n\t\t\tsprintf(buffer, \"%c:\\\\main.mix\", 'A' + cd_drive);\n\t\t\topen_failed = _dos_open(buffer, O_RDONLY|SH_DENYNO, &file);\n\n\t\t\tif (!open_failed)\n\t\t\t\t{\n\t\t\t\t_dos_close(file);\n\n\t\t\t\t/*\n\t\t\t\t** Hey some times the stupid dos driver appends a period to the\n\t\t\t\t** name if it is eight characters long.  If the last char is a\n\t\t\t\t** period then erase it.\n\t\t\t\t*/\n\t\t\t\tif (ft.name[strlen(ft.name)-1] == '.')\n\t\t\t\t\t{\n\t\t\t\t\tft.name[strlen(ft.name)-1] = 0;\n\t\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Match the volume label to the list of known C&C volume labels.\n\t\t\t\t*/\n\t\t\t\tfor (int i = 0 ; i < _Num_Volumes; i++)\n\t\t\t\t\t{\n\t\t\t\t\tif (!stricmp(_CD_Volume_Label[i], ft.name))\n\t\t\t\t\t\treturn (i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn -1;\n\t}\n#endif\n\n\n/***********************************************************************************************\n * Force_CD_Available -- Ensures that specified CD is available.                               *\n *                                                                                             *\n *    Call this routine when you need to ensure that the specified CD is actually in the       *\n *    CD-ROM drive.                                                                            *\n *                                                                                             *\n * INPUT:   cd    -- The CD that must be available. This will either be \"0\" for the GDI CD, or *\n *                   \"1\" for the Nod CD. If either CD will qualify, then pass in \"-1\".         *\n *                0  = CD1\n *                1  = CD2\n *                2  = Counterstrike\n *                3  = Aftermath\n *                4  = Counterstrike or Aftermath\n *                5  = DVD\n *                -1 = Any CD\n *                -2 = Local Harddisk\n *                                                                                             *\n * OUTPUT:  Is the CD inserted and available? If false is returned, then this indicates that   *\n *          the player pressed <CANCEL>.                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1995 JLB : Created.                                                                 *\n *   05/22/1996  ST : Handles multiple CD drives / CD changers                                 *\n *   01/20/1997 V.Grippi added expansion cd message\n *=============================================================================================*/\n\n#if (1) //ST - 5/13/2019\nbool Force_CD_Available(int cd)\n{\n\tstatic int _last = -1;\n\n\tif (_last != cd || cd == ALWAYS_RELOAD_CD) {\n\t\tif (cd != ALWAYS_RELOAD_CD) {\n\t\t\t_last = cd;\n\t\t}\n\t\tTheme.Stop();\n\n\t\t//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) {\n\t\t\tdelete MoviesMix;\n\t\t\tMoviesMix = 0;\n\t\t}\n\t\tif (GeneralMix) {\n\t\t\tdelete GeneralMix;\n\t\t\tGeneralMix = 0;\n\t\t}\n\t\tif (ScoreMix) {\n\t\t\tdelete ScoreMix;\n\t\t\tScoreMix = 0;\n\t\t}\n\t\tif (MainMix) {\n\t\t\tdelete MainMix;\n\t\t\tMainMix = 0;\n\t\t}\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\tassert(MainMix != NULL);\n\t\t//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available())\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\telse\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t}\n\n\treturn true;\n}\n\n\n#endif\n\n#if (0) //ST - 5/13/2019\n\ntypedef enum {\n\tCD_LOCAL = -2,\n\tCD_ANY = -1,\n\tCD_SOVIET = 0,\n\tCD_ALLIED,\n\tCD_COUNTERSTRIKE,\n\tCD_AFTERMATH,\n\tCD_CS_OR_AM,\n\tCD_DVD\n} CD_VOLUME;\n\n#ifdef FIXIT_VERSION_3\n\n#ifndef DVD\n#error DVD must be defined!\n#endif\n\nbool Force_CD_Available( int cd_desired )\t\t\t\t//\tajw\n{\n\tstatic int _last = -1;\n\tstatic void *font;\n#ifdef FRENCH\n\tstatic char * _cd_name[] = {\n\t\t\"ALERTE ROUGE CD1\",\n\t\t\"ALERTE ROUGE CD2\",\n\t\t\"CD Missions Taiga\",\n\t\t\"CD Missions M.A.D.\",\n\t\t\"ALERTE ROUGE DVD\",\n};\n#endif\n#ifdef GERMAN\n\tstatic char * _cd_name[] = {\n\t\t\"ALARMSTUFE ROT CD1\",\n\t\t\"ALARMSTUFE ROT CD2\",\n\t\t\"CD Gegenangriff einlegen\",\n\t\t\"CD TRANS einlegen\",\n\t\t\"ALARMSTUFE ROT DVD\",\n\t};\n#endif\n#ifdef ENGLISH\n\tstatic char * _cd_name[] = {\n\t\t\"RED ALERT DISK 1\",\n\t\t\"RED ALERT DISK 2\",\n\t\t\"CounterStrike CD\",\n\t\t\"Aftermath CD\",\n\t\t\"RED ALERT DVD\",\n\t};\n#endif\n\n\n\n\tint new_cd_drive = 0;\n\tint cd_current;\n\tint current_drive;\n\n\tThemeType theme_playing = THEME_NONE;\n\n\t/*\n\t** If the required CD is set to -2 then it means that the file is present\n\t** on the local hard drive and we shouldn't have to worry about it.\n\t*/\n\tif (cd_desired == CD_LOCAL) return(true);\n\n\t/*\n\t** Find out if the CD in the current drive is the one we are looking for\n \t*/\n\tcurrent_drive = CCFileClass::Get_CD_Drive();\n\tcd_current = Get_CD_Index(current_drive, 1*60);\n\n//\tdebugprint(\"Get_CD_Index just returned %d\\n\", cd_current);\n//\tdebugprint(\"We are checking for %d\\n\", cd_desired);\n//\tdebugprint(\"current_drive = %d\\n\", current_drive);\n\n\tif( Using_DVD() )\n\t{\n\t\t//\tAll requested cd indexes get rerouted to the DVD.\n\t\tcd_desired = CD_DVD;\n//\t\tif( RequiredCD != -1 )\n//\t\t\tRequiredCD = CD_DVD;\t\t//\tJust seems like a good idea. Not sure if necessary.\tajw\n\t}\n\n\tif (cd_current >= 0 )\n\t{\n\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t{\n\t\t\t// If the current cd is CS or AM then change request to whatever\n\t\t\t// is present.\n\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\tcd_desired = cd_current;\n\t\t}\n\t\t// If the current CD is requested or any CD will work\n\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t{\n\t\t\t/*\n\t\t\t** The required CD is still in the CD drive we used last time\n\t\t\t*/\n\t\t\tnew_cd_drive = current_drive;\n\t\t}\n\t}\n\n\t/*\n\t** Flag that we will have to restart the theme\n\t*/\n\ttheme_playing = Theme.What_Is_Playing();\n\tTheme.Stop();\n\n\t// Check the last drive\n\tif (!new_cd_drive)\n\t{\n\t\t/*\n\t\t** Check the last CD drive we used if it's different from the current one\n\t\t*/\n\t\tint last_drive = CCFileClass::Get_Last_CD_Drive();\n\n\t\t/*\n\t\t** Make sure the last drive is valid and it isn't the current drive\n\t\t*/\n\t\tif (last_drive && last_drive != CCFileClass::Get_CD_Drive())\t\t//\tElse we have already checked this cd.\n\t\t{\n\t\t\t/*\n\t\t\t** Find out if there is a C&C cd in the last drive and if so is it the one we are looking for\n\t\t\t** Give it a nice big timeout so the CD changer has time to swap the discs\n\t\t\t*/\n\t\t\tcd_current = Get_CD_Index(last_drive, 10*60);\n\n\t\t\tif (cd_current >= 0 )\n\t\t\t{\n\t\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\t{\n\t\t\t\t\t// If the cd is CS or AM then change request to whatever\n\t\t\t\t\t// is present.\n\t\t\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\t\t\tcd_desired = cd_current;\n\t\t\t\t}\n\t\t\t\t// If the cd is present or any cd will work\n\t\t\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** The required CD is in the CD drive we used last time\n\t\t\t\t\t*/\n\t\t\t\t\tnew_cd_drive = last_drive;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Lordy.  No sign of that blimming CD anywhere. Search all the CD drives\n\t** then if we still can't find it prompt the user to insert it.\n\t*/\n\tif (!new_cd_drive)\n\t{\n\t\t/*\n\t\t** Small timeout for the first pass through the drives\n\t\t*/\n\t\tint drive_search_timeout = 2*60;\n\n\t\tfor (;;)\n\t\t{\n\t\t\tchar buffer[128];\n\t\t\t/*\n\t\t\t** Search all present CD drives for the required disc.\n\t\t\t*/\n\t\t\tfor (int i = 0 ; i < CDList.Get_Number_Of_Drives(); i++)\n\t\t\t{\n\t\t\t\tint cd_drive = CDList.Get_Next_CD_Drive();\n\t\t\t\tcd_current = Get_CD_Index(cd_drive, drive_search_timeout);\n\n\t\t\t\tif (cd_current >= 0)\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** We found a C&C cd - lets see if it was the one we were looking for\n\t\t\t\t\t*/\n\t\t\t\t\t// Require CS or AM\n\t\t\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the cd is CS or AM then change request to whatever\n\t\t\t\t\t\t// is present.\n\t\t\t\t\t\tif( cd_current == CD_COUNTERSTRIKE || cd_current == CD_AFTERMATH )\n\t\t\t\t\t\t\tcd_desired = cd_current;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif( cd_desired == cd_current || cd_desired == CD_ANY )\n\t\t\t\t\t{\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Woohoo! The disk was in a different cd drive. Refresh the search path list\n\t\t\t\t \t\t* and return.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnew_cd_drive = cd_drive;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** A new disc has become available so break\n\t\t\t*/\n\t\t\tif (new_cd_drive) break;\n\n\t\t\t/*\n\t\t\t** Increase the timeout for subsequent drive searches.\n\t\t\t*/\n\t\t\tdrive_search_timeout = 5*60;\n\n\t\t\t/*\n\t\t\t**\tPrompt to insert the CD into the drive.\n\t\t\t*/\n\t\t\t//V.Grippi\n\t\t\tif( cd_desired == CD_CS_OR_AM )\n\t\t\t\tcd_desired = CD_AFTERMATH;\n\t\t\t\n\t\t\tif( cd_desired == CD_DVD )\n\t\t\t{\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[4]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse if( cd_desired == CD_COUNTERSTRIKE || cd_desired == CD_AFTERMATH )\n\t\t\t{\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[cd_desired]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[cd_desired]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[cd_desired]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse if( cd_desired == CD_ANY )\n\t\t\t{\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_1), cd_desired+1, _cd_name[cd_desired]);\n\t\t\t}\n\t\t\telse\t\t//\t0 or 1\n\t\t\t{\n\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_2), cd_desired+1, _cd_name[cd_desired]);\n\t\t\t}\n\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\ttheme_playing = Theme.What_Is_Playing();\n\t\t\tTheme.Stop();\n\t\t\tint hidden = Get_Mouse_State();\n\t\t\tfont = (void *)FontPtr;\n\n\t\t\t/*\n\t\t\t**\tOnly set the palette if necessary.\n\t\t\t*/\n\t\t\tif (PaletteClass::CurrentPalette[1].Red_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Blue_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Green_Component() == 0)\n\t\t\t{\n\t\t\t\tGamePalette.Set();\n\t\t\t}\n\n\t\t\tKeyboard->Clear();\n\n\t\t\twhile (Get_Mouse_State()) Show_Mouse();\n\n\t\t\tif (WWMessageBox().Process(buffer, TXT_OK, TXT_CANCEL, TXT_NONE, TRUE) == 1)\n\t\t\t{\n\t\t\t\tSet_Logic_Page(oldpage);\n#ifdef FIXIT_VERSION_3\n\t\t\t\twhile (hidden--) Hide_Mouse();\n#else\n\t\t\t\tHide_Mouse();\n#endif\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\twhile (hidden--) Hide_Mouse();\n\t\t\tSet_Font(font);\n\t\t\tSet_Logic_Page(oldpage);\n\t\t}\n\t}\n\n\tCurrentCD = cd_current;\n\n\tCCFileClass::Set_CD_Drive(new_cd_drive);\n\tCCFileClass::Refresh_Search_Drives();\n\n\t/*\n\t**\tIf it broke out of the query for CD-ROM loop, then this means that the\n\t**\tCD-ROM has been inserted.\n\t*/\n\tif (cd_desired == 4) cd_desired--;\n\n\t//\tajw - Added condition of cd_desired != 5 to the following if.\n\t//\tReason: This was triggering before Init_Secondary_Mixfiles(), which was screwing up the mixfile system somehow.\n\t//\n\t//\tSince the DVD is the only disk that can possibly be required when Using_DVD(), I never have to reload the mix\n\t//\tfiles here, because no other disk could ever have been asked for. And if not Using_DVD(), cd_desired will never\n\t//\tbe equal to 5. So this is safe.\n\tif (cd_desired > -1 && _last != cd_desired && cd_desired != 5)\n\t{\n\t\t_last = cd_desired;\n\n\t\tTheme.Stop();\n\n//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) delete MoviesMix;\n\t\tif (GeneralMix) delete GeneralMix;\n\t\tif (ScoreMix) delete ScoreMix;\n\t\tif (MainMix) delete MainMix;\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\tassert(MainMix != NULL);\n//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available())\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\telse\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t\tThemeClass::Scan();\n\t}\n\n\treturn(true);\n}\n\n#else\t\t//\tFIXIT_VERSION_3 not defined\n\nbool Force_CD_Available(int cd)\n{\n\tstatic int _last = -1;\n//\tstatic char _palette[768];\n//\tstatic char _hold[256];\n\tstatic void *font;\n#ifdef FRENCH\n\tstatic char * _cd_name[] = {\n\t\t\"ALERTE ROUGE CD1\",\n\t\t\"ALERTE ROUGE CD2\",\n\t\t\"CD Missions Taiga\",\n\t\t\"CD Missions M.A.D.\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"ALERTE ROUGE DVD\",\n\t\t#endif\n};\n\n#endif\n#ifdef GERMAN\n\tstatic char * _cd_name[] = {\n\t\t\"ALARMSTUFE ROT CD1 einlegen\",\n\t\t\"ALARMSTUFE ROT CD2 einlegen\",\n\t\t\"CD Gegenangriff einlegen\",\n\t\t\"CD TRANS einlegen\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"ALARMSTUFE ROT DVD einlegen\",\n\t\t#endif\n\t};\n#endif\n#ifdef ENGLISH\n\tstatic char * _cd_name[] = {\n\t\t\"RED ALERT DISK 1\",\n\t\t\"RED ALERT DISK 2\",\n\t\t\"CounterStrike CD\",\n\t\t\"Aftermath CD\",\n\n\t\t// Denzil 4/15/98\n\t\t#ifdef DVD\n\t\t\"RED ALERT DVD\",\n\t\t#endif\n\t};\n#endif\n\n\tint new_cd_drive = 0;\n\tint cd_index;\n\tchar buffer[128];\n\tint cd_drive;\n\tint current_drive;\n\tint drive_search_timeout;\n\n\tThemeType theme_playing = THEME_NONE;\n\n//#ifdef FIXIT_ANTS\n//\tif(Scen.ScenarioName[2] == 'A')\n//\t   cd = 2;\n//#endif\n\t/*\n\t** If the required CD is set to -2 then it means that the file is present\n\t** on the local hard drive and we shouldn't have to worry about it.\n\t*/\n\tif (cd == CD_LOCAL) return(true);\n\n\t/*\n\t** Find out if the CD in the current drive is the one we are looking for\n \t*/\n\tcurrent_drive = CCFileClass::Get_CD_Drive();\n\tcd_index = Get_CD_Index(current_drive, 1*60);\n\n\t#ifdef CHEAT_KEYS\n\t//\tMono_Printf(\"Get_CD_Index just returned %d\\n\", cd_index);\n\t//\tMono_Printf(\"We are checking for %d\\n\", cd);\n\t//\tMono_Printf(\"current_drive = %d\\n\", current_drive);\n\t#endif\t//CHEAT_KEYS\n\n\t#ifdef DVD // Denzil\n\t// CD1 and CD2 are ignored, force the DVD\n\tif (cd_index == 0 || cd_index == 1)\n\t\tcd_index = -1;\n\t#endif\n\t\n\tif (cd_index >= 0 )\n\t\t{\n\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t// Require CS or AM\n\t\tif (cd == CD_CS_OR_AM)\n\t\t\t{\n\t\t\t// If the current cd is CS or AM then change request to whatever\n\t\t\t// is present.\n\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t{\n\t\t\t\tcd = cd_index;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\n\t\t#ifdef DVD // Denzil\n\t\t// If the current drive is the DVD then requests for CD1 and CD2 are okay\n\t\tif (cd_index == 4)\n\t\t\t{\n\t\t\t// CD1, CD2 & DVD requests\n\t\t\tif (cd == 0 || cd == 1 || cd == 5)\n\t\t\t\t{\n\t\t\t\tcd_index = cd;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\t\t\n\t\t// If the current CD is requested or any CD will work\n\t\tif (cd == cd_index || cd == -1 )\n\t\t\t{\n\t\t\t/*\n\t\t\t** The required CD is still in the CD drive we used last time\n\t\t\t*/\n\t\t\tnew_cd_drive = current_drive;\n\t\t\t}\n\t\t}\n\n\t/*\n\t** Flag that we will have to restart the theme\n\t*/\n\ttheme_playing = Theme.What_Is_Playing();\n\tTheme.Stop();\n\n\t// Check the last drive\n\tif (!new_cd_drive)\n\t\t{\n\t\t/*\n\t\t** Check the last CD drive we used if it's different from the current one\n\t\t*/\n\t\tint last_drive = CCFileClass::Get_Last_CD_Drive();\n\n\t\t/*\n\t\t** Make sure the last drive is valid and it isn't the current drive\n\t\t*/\n\t\tif (last_drive && last_drive != CCFileClass::Get_CD_Drive())\n\t\t\t{\n\t\t\t/*\n\t\t\t** Find out if there is a C&C cd in the last drive and if so is it the one we are looking for\n\t\t\t** Give it a nice big timeout so the CD changer has time to swap the discs\n\t\t\t*/\n\t\t\tcd_index = Get_CD_Index(last_drive, 10*60);\n\n\t\t\t#ifdef DVD // Denzil\n\t\t\t// Ignore CD1 and CD2 disks, force DVD\n\t\t\tif (cd_index == 0 || cd_index == 1)\n\t\t\t\tcd_index = -1;\n\t\t\t#endif\n\t\t\t\n\t\t\tif (cd_index >= 0 )\n\t\t\t\t{\n\t\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t// Require CS or AM\n\t\t\t\tif (cd == 4)\n\t\t\t\t\t{\n\t\t\t\t\t// If CS or AM was the last drive then use it\n\t\t\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcd = cd_index;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t// If DVD is in drive\n\t\t\t\tif (cd_index == 4)\n\t\t\t\t\t{\n\t\t\t\t\t// CD1, CD2 and DVD requests are all on the DVD \n\t\t\t\t\tif ((cd == 0) || (cd == 1) || (cd == 5))\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcd_index = cd;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t// If the cd is present or any cd will work\n\t\t\t\tif (cd == cd_index || cd == -1 )\n\t\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** The required CD is in the CD drive we used last time\n\t\t\t\t\t*/\n\t\t\t\t\tnew_cd_drive = last_drive;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/*\n\t** Lordy.  No sign of that blimming CD anywhere. Search all the CD drives\n\t** then if we still can't find it prompt the user to insert it.\n\t*/\n\tif (!new_cd_drive)\n\t\t{\n\t\t/*\n\t\t** Small timeout for the first pass through the drives\n\t\t*/\n\t\tdrive_search_timeout = 2*60;\n\n\t\tfor (;;)\n\t\t\t{\n\t\t\t/*\n\t\t\t** Search all present CD drives for the required disc.\n\t\t\t*/\n\t\t\tfor (int i = 0 ; i < CDList.Get_Number_Of_Drives(); i++)\n\t\t\t\t{\n\t\t\t\tcd_drive = CDList.Get_Next_CD_Drive();\n\t\t\t\tcd_index = Get_CD_Index(cd_drive, drive_search_timeout);\n\n\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t// Ignore CD1 and CD2, force the DVD\n\t\t\t\tif (cd_index == 0 || cd_index == 1)\n\t\t\t\t\tcd_index = -1;\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif (cd_index >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t** We found a C&C cd - lets see if it was the one we were looking for\n\t\t\t\t\t*/\n\t\t\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t// Require CS or AM\n\t\t\t\t\tif (cd == 4)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t// If the disk is CS or AM then request it\n\t\t\t\t\t\tif (cd_index == 2 || cd_index == 3)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcd = cd_index;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\t#ifdef DVD // Denzil\n\t\t\t\t\tif (cd_index == 4)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tif ((cd == 0) || (cd == 1) || (cd == 5))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcd_index = cd;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\t\t\t\t\t\n\t\t\t\t\tif (cd == cd_index || cd == -1 || cd == -2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Woohoo! The disk was in a different cd drive. Refresh the search path list\n\t\t\t\t \t\t* and return.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnew_cd_drive = cd_drive;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/*\n\t\t\t** A new disc has become available so break\n\t\t\t*/\n\t\t\tif (new_cd_drive) break;\n\n\t\t\t/*\n\t\t\t** Increase the timeout for subsequent drive searches.\n\t\t\t*/\n\t\t\tdrive_search_timeout = 5*60;\n\n\t\t\t/*\n\t\t\t**\tPrompt to insert the CD into the drive.\n\t\t\t*/\n\t\t\t//V.Grippi\n\t\t\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif(cd == 4) cd--;\n\t\t\t\n\t\t\t// CS or AM\n\t\t\tif(cd == 2 || cd == 3)\n\t\t\t\t{\n\t\t\t#else\n\t\t\tif(cd == 2)\n\t\t   \t\t{\n\t\t\t#endif\n\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\",  _cd_name[cd]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN\n\t\t\t\tsprintf(buffer, \"Bitte %s\",  _cd_name[cd]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\",  _cd_name[cd]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t#ifdef DVD\n\t\t\t\t#ifdef FRENCH\n\t\t\t   \tsprintf(buffer, \"Insrez le %s\", _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\t#ifdef GERMAN \n\t\t\t\tsprintf(buffer, \"Bitte %s\", _cd_name[4]);\n\t\t\t\t#else\n\t\t\t\tsprintf(buffer, \"Please insert the %s\", _cd_name[4]);\n\t\t\t\t#endif\n\t\t\t\t#endif\n\t\t\t\t#else\n\t\t\t\tif (cd == -1 )\n\t\t\t\t\t{\n\t\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_1), cd+1, _cd_name[cd]);\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tsprintf(buffer, Text_String(TXT_CD_DIALOG_2), cd+1, _cd_name[cd]);\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t\t}\n\n\t\t\t#ifdef WIN32\n\t\t\tGraphicViewPortClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\t#else\n\t\t\tGraphicBufferClass * oldpage = Set_Logic_Page(SeenBuff);\n\t\t\t#endif\n\t\t\ttheme_playing = Theme.What_Is_Playing();\n\t\t\tTheme.Stop();\n\t\t\tint hidden = Get_Mouse_State();\n\t\t\tfont = (void *)FontPtr;\n\n\t\t\t/*\n\t\t\t**\tOnly set the palette if necessary.\n\t\t\t*/\n\t\t\tif (PaletteClass::CurrentPalette[1].Red_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Blue_Component() +\n\t\t\t\t\tPaletteClass::CurrentPalette[1].Green_Component() == 0)\n\t\t\t\t{\n\t\t\t\tGamePalette.Set();\n\t\t\t\t}\n\n\t\t\tKeyboard->Clear();\n\n\t\t\twhile (Get_Mouse_State()) Show_Mouse();\n\n\t\t\tif (WWMessageBox().Process(buffer, TXT_OK, TXT_CANCEL, TXT_NONE, TRUE) == 1)\n\t\t\t\t{\n\t\t\t\tSet_Logic_Page(oldpage);\n\t\t\t\tHide_Mouse();\n\t\t\t\treturn(false);\n\t\t\t\t}\n\n\t\t\twhile (hidden--) Hide_Mouse();\n\t\t\tSet_Font(font);\n\t\t\tSet_Logic_Page(oldpage);\n\t\t\t}\n\t\t}\n\n\tCurrentCD = cd_index;\n\n\tCCFileClass::Set_CD_Drive(new_cd_drive);\n\tCCFileClass::Refresh_Search_Drives();\n\n\t/*\n\t**\tIf it broke out of the query for CD-ROM loop, then this means that the\n\t**\tCD-ROM has been inserted.\n\t*/\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (cd == 4) cd--;\n\t#endif\n//\tif (cd > -3 && _last != cd) {\n\tif (cd > -1 && _last != cd)\n\t\t{\n\t\t_last = cd;\n\n\t\tTheme.Stop();\n\n//\t\tif (ConquerMix) delete ConquerMix;\n\t\tif (MoviesMix) delete MoviesMix;\n\t\tif (GeneralMix) delete GeneralMix;\n\t\tif (ScoreMix) delete ScoreMix;\n\t\tif (MainMix) delete MainMix;\n\n\t\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\t\t\n\t\tassert(MainMix != NULL);\n//\t\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\n\n\t\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available())\n\t\t\t{\n\t\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\n\t\t\t}\n\t\tassert(MoviesMix != NULL);\n\t\tGeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\n\t\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\t\tThemeClass::Scan();\n\t\t}\n\n\tif (theme_playing != THEME_NONE)\n\t\t{\n\t\tTheme.Queue_Song(theme_playing);\n\t\t}\n\n\treturn(true);\n\t}\n\n\n#endif\t//\tFIXIT_VERSION_3\n#endif\t// ST - 5/13/2019\n\n\n/***************************************************************************\n * DISK_SPACE_AVAILABLE -- returns bytes of free disk space                *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     returns amount of free disk space                           *\n *                                                                         *\n * HISTORY:                                                                *\n *   08/11/1995 PWG : Created.                                             *\n *=========================================================================*/\nunsigned long Disk_Space_Available(void)\n{\n\treturn 0x7fffffff;\t//ST - 5/8/2019\n#if (0)\n\tstruct diskfree_t diskdata;\n\tunsigned drive;\n\n\t_dos_getdrive(&drive);\n\t_dos_getdiskfree(drive, &diskdata);\n\n\treturn(diskdata.avail_clusters * diskdata.sectors_per_cluster * diskdata.bytes_per_sector);\n#endif\n}\n\n\n/***********************************************************************************************\n * Do_Record_Playback -- handles saving/loading map pos & current object                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Do_Record_Playback(void)\n{\n\tint count;\n\tTARGET tgt;\n\tint i;\n\tCOORDINATE coord;\n\tObjectClass * obj;\n\tunsigned long sum;\n\tunsigned long sum2;\n\tunsigned long ltgt;\n\n\t/*\n\t**\tRecord a game\n\t*/\n\tif (Session.Record) {\n\n\t\t/*\n\t\t**\tSave the map's location\n\t\t*/\n\t\tSession.RecordFile.Write(&Map.DesiredTacticalCoord,\n\t\t\tsizeof (Map.DesiredTacticalCoord));\n\n\t\t/*\n\t\t**\tSave the current object list count\n\t\t*/\n\t\tcount = CurrentObject.Count();\n\t\tSession.RecordFile.Write(&count, sizeof(count));\n\n\t\t/*\n\t\t**\tSave a CRC of the selected-object list.\n\t\t*/\n\t\tsum = 0;\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\tsum += ltgt;\n\t\t}\n\t\tSession.RecordFile.Write (&sum, sizeof(sum));\n\n\t\t/*\n\t\t**\tSave all selected objects.\n\t\t*/\n\t\tfor (i = 0; i < count; i++) {\n\t\t\ttgt = CurrentObject[i]->As_Target();\n\t\t\tSession.RecordFile.Write (&tgt, sizeof(tgt));\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Write (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Write (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Write (&FormationEvent, sizeof(FormationEvent));\n\t\tSession.RecordFile.Write (TeamFormData, sizeof(TeamFormData));\n\t\tSession.RecordFile.Write (&FormMove, sizeof(FormMove));\n\t\tSession.RecordFile.Write (&FormSpeed, sizeof(FormSpeed));\n\t\tSession.RecordFile.Write (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\t\tTeamEvent = 0;\n\t\tTeamNumber = 0;\n\t\tFormationEvent = 0;\n\t}\n\n\t/*\n\t**\tPlay back a game (\"attract\" mode)\n\t*/\n\tif (Session.Play) {\n\n\t\t/*\n\t\t**\tRead & set the map's location.\n\t\t*/\n\t\tif (Session.RecordFile.Read(&coord, sizeof(coord))==sizeof(coord)) {\n\t\t\tif (coord != Map.DesiredTacticalCoord) {\n\t\t\t\tMap.Set_Tactical_Position(coord);\n\t\t\t}\n\t\t}\n\n\t\tif (Session.RecordFile.Read(&count, sizeof(count))==sizeof(count)) {\n\t\t\t/*\n\t\t\t**\tCompute a CRC of the current object-selection list.\n\t\t\t*/\n\t\t\tsum = 0;\n\t\t\tfor (i = 0; i < CurrentObject.Count(); i++) {\n\t\t\t\tltgt = (unsigned long)(CurrentObject[i]->As_Target());\n\t\t\t\tsum += ltgt;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tLoad the CRC of the objects on disk; if it doesn't match, select\n\t\t\t**\tall objects as they're loaded.\n\t\t\t*/\n\t\t\tSession.RecordFile.Read (&sum2, sizeof(sum2));\n\t\t\tif (sum2 != sum) {\n\t\t\t\tUnselect_All();\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t\tfor (i = 0; i < count; i++) {\n\t\t\t\tif (Session.RecordFile.Read (&tgt, sizeof(tgt))==sizeof(tgt)) {\n\t\t\t\t\tobj = As_Object(tgt);\n\t\t\t\t\tif (obj && (sum2 != sum)) {\n\t\t\t\t\t\tobj->Select();\n\t\t\t\t\t\tAllowVoice = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAllowVoice = true;\n\n\t\t}\n\n\t\t//\n\t\t// Save team-selection and formation events\n\t\t//\n\t\tSession.RecordFile.Read (&TeamEvent, sizeof(TeamEvent));\n\t\tSession.RecordFile.Read (&TeamNumber, sizeof(TeamNumber));\n\t\tSession.RecordFile.Read (&FormationEvent, sizeof(FormationEvent));\n\t\tif (TeamEvent) {\n\t\t\tHandle_Team(TeamNumber, TeamEvent - 1);\n\t\t}\n\t\tif (FormationEvent) {\n\t\t\tToggle_Formation();\n\t\t}\n\n\t\tSession.RecordFile.Read (TeamFormData, sizeof(TeamFormData));\n\t\tSession.RecordFile.Read (&FormMove, sizeof(FormMove));\n\t\tSession.RecordFile.Read (&FormSpeed, sizeof(FormSpeed));\n\t\tSession.RecordFile.Read (&FormMaxSpeed, sizeof(FormMaxSpeed));\n\n\t\t/*\n\t\t**\tThe map isn't drawn in playback mode, so draw it here.\n\t\t*/\n\t\tMap.Render();\n\t}\n}\n\n\n/***********************************************************************************************\n * Hires_Load -- Allocates memory for, and loads, a resolution dependant file.                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of file to load                                                              *\n *                                                                                             *\n * OUTPUT:   Ptr to loaded file                                                                *\n *                                                                                             *\n * WARNINGS: Caller is responsible for releasing the memory allocated                          *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/13/96 3:20PM ST : Created                                                              *\n *=============================================================================================*/\nvoid * Hires_Load(char * name)\n{\n\tchar \tfilename[30];\n\tint \tlength;\n\tvoid * return_ptr;\n\n#ifdef WIN32\n\tsprintf(filename, \"H%s\", name);\n#else\n   strcpy(filename, name);\n#endif\n\tCCFileClass file (filename);\n\n\tif (file.Is_Available()) {\n\n\t\tlength = file.Size();\n\t\treturn_ptr = new char[length];\n\t\tfile.Read(return_ptr, length);\n\t\treturn (return_ptr);\n\n\t} else {\n\t\treturn (NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * Crate_From_Name -- Given a crate name convert it to a crate type.                           *\n *                                                                                             *\n *    Use this routine to convert an ASCII crate name into a crate type. If no match could     *\n *    be found, then CRATE_MONEY is assumed.                                                   *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the crate name text to convert into a crate type.              *\n *                                                                                             *\n * OUTPUT:  Returns with the crate name converted into a crate type.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCrateType Crate_From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (CrateType crate = CRATE_FIRST; crate < CRATE_COUNT; crate++) {\n\t\t\tif (stricmp(name, CrateNames[crate]) == 0) return(crate);\n\t\t}\n\t}\n\treturn(CRATE_MONEY);\n}\n\n\n/***********************************************************************************************\n * Owner_From_Name -- Convert an owner name into a bitfield.                                   *\n *                                                                                             *\n *    This will take an owner specification and convert it into a bitfield that represents     *\n *    it. Sometimes this will be just a single house bit, but other times it could be          *\n *    all the allies or soviet house bits combined.                                            *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to convert into a house bitfield.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the houses specified. The value is in the form of a bit field with    *\n *          one bit per house type.                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Owner_From_Name(char const * text)\n{\n\tint ownable = 0;\n\tif (stricmp(text, \"soviet\") == 0) {\n\t\townable |= HOUSEF_SOVIET;\n\t} else {\n\t\tif (stricmp(text, \"allies\") == 0 || stricmp(text, \"allied\") == 0) {\n\t\t\townable |= HOUSEF_ALLIES;\n\t\t} else {\n\t\t\tHousesType h = HouseTypeClass::From_Name(text);\n\t\t\tif (h != HOUSE_NONE && (h < HOUSE_MULTI1 || h > HOUSE_MULTI8)) {\n\t\t\t\townable |= (1 << h);\n\t\t\t}\n\t\t}\n\t}\n\treturn(ownable);\n}\n\n\n/***********************************************************************************************\n * Shake_The_Screen -- Dispatcher that shakes the screen.                                      *\n *                                                                                             *\n *    This routine will shake the game screen the number of shakes requested.                  *\n *                                                                                             *\n * INPUT:   shakes   -- The number of shakes to shake the screen.                              *\n *          house    -- House to perform the shake for (or HOUSE_NONE if all players).         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid Shake_The_Screen(int shakes, HousesType house)\n{\n\tfor (char h = HOUSE_FIRST; h < HOUSE_COUNT; ++h) {\n\t\tif ((house != HOUSE_NONE) && (h != house)) {\n\t\t\tcontinue;\n\t\t}\n\t\tHouseClass* hptr = HouseClass::As_Pointer((HousesType)h);\n\t\tif ((hptr != nullptr) && hptr->IsActive && hptr->IsHuman) {\n\t\t\thptr->ScreenShakeTime = CDTimerClass<FrameTimerClass>(hptr->ScreenShakeTime + shakes + shakes);\n\t\t\thptr->ScreenShakeTime.Start();\n\t\t}\n\t}\n#if (0)\n#ifdef WIN32\n\tshakes += shakes;\n\n\tHide_Mouse();\n\tSeenPage.Blit(HidPage);\n\tint oldyoff = 0;\n\tint newyoff = 0;\n\twhile(shakes--) {\n\t\tint x = TickCount;\n//\t\tCountDownTimer = 1;\n\t\tdo {\n\t\t\tnewyoff = Sim_Random_Pick(0,2) - 1;\n\t\t} while (newyoff == oldyoff);\n\t\tswitch (newyoff) {\n\t\t\tcase -1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,2, 0,0, 640,398);\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\t\tHidPage.Blit(SeenPage);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tHidPage.Blit(SeenPage, 0,0, 0,2, 640,398);\n\t\t\t\tbreak;\n\t\t} while (x == TickCount);\n//\t\t} while (CountDownTimer != 0) ;\n\t}\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n#else\n\tShake_Screen(shakes);\n#endif\n#endif\n}\n\n\n/***********************************************************************************************\n * List_Copy -- Makes a copy of a cell offset list.                                            *\n *                                                                                             *\n *    This routine will make a copy of a cell offset list. It will only copy the significant   *\n *    elements of the list limited by the maximum length specified.                            *\n *                                                                                             *\n * INPUT:   source   -- Pointer to a cell offset list.                                         *\n *                                                                                             *\n *          len      -- The maximum number of cell offset elements to store in to the          *\n *                      destination list pointer.                                              *\n *                                                                                             *\n *          dest     -- Pointer to the destination list to store the copy into.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Ensure that the destination list is large enough to hold the list copy.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid List_Copy(short const * source, int len, short * dest)\n{\n\tif (dest == NULL || dest == NULL) {\n\t\treturn;\n\t}\n\n\twhile (len > 0) {\n\t\t*dest = *source;\n\t\tif (*dest == REFRESH_EOL) break;\n\t\tdest++;\n\t\tsource++;\n\t\tlen--;\n\t}\n}\n\n\n\n#if 0\n//\n// Boy, this function sure is crummy\n//\nvoid Crummy(int crumb1, int crumb2)\n{\n\tif (Debug_Check_Map && Debug_Heap_Dump) {\n\t\tMono_Printf(\"Hi, I'm Crummy.  And so are these: %d, %d\\n\",crumb1,crumb2);\n\t}\n}\n#endif\n\n\n\n/***********************************************************************************************\n * Game_Registry_Key -- Returns pointer to string containing the registry subkey for the game.\n *                      This is located under HKEY_LOCAL_MACHINE.\n * HISTORY:\n *    11/19/98 ajw : Created\n *=============================================================================================*/\nconst char* Game_Registry_Key()\n{\n#ifdef ENGLISH\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Red Alert Windows 95 Edition\";\n#else\n#ifdef GERMAN\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Alarmstufe Rot Windows 95 Edition\";\n#else\n\tstatic char szKey[] = \"SOFTWARE\\\\Westwood\\\\Alerte Rouge version Windows 95\";\n#endif\n#endif\n\treturn szKey;\n}\n\n\n/***********************************************************************************************\n * Is_Counterstrike_Installed -- Function to determine the availability of the CS expansion    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if Counterstrike is present                                                  *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 11:39PM ST : Created                                                              *\n *=============================================================================================*/\nbool Is_Counterstrike_Installed (void)\n{\n\treturn true;\t\t// Remasters always have Counterstrike. ST - 10/18/2019 11:06AM\n\n#if (0)\n\t//\tajw 9/29/98\n\tstatic bool\tbAlreadyChecked = false;\n\tstatic bool bInstalled = false;\n\n\tif( !bAlreadyChecked )\n\t{\n\t\tHKEY hKey;\n\t\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\t\treturn false;\n\t\tDWORD dwValue;\n\t\tDWORD dwBufSize = sizeof( DWORD );\n\t\tif( RegQueryValueEx( hKey, \"CStrikeInstalled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbInstalled = false;\n\t\telse\n\t\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\t\tRegCloseKey( hKey );\n\t\tbAlreadyChecked = true;\n\t}\n\treturn bInstalled;\n\n//\tRawFileClass file(\"EXPAND.MIX\");\n//\treturn(file.Is_Available());\n#endif\n}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n/***********************************************************************************************\n *=============================================================================================*/\nbool Is_Aftermath_Installed (void)\n{\n\treturn true;\t\t// Remasters always have Aftermath. ST - 10/18/2019 11:06AM\n\n#if (0)\t \n\t//\tajw 9/29/98\n\tstatic bool\tbAlreadyChecked = false;\n\tstatic bool bInstalled = false;\n\n\tif( !bAlreadyChecked )\n\t{\n\t\tHKEY hKey;\n\t\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\t\treturn false;\n\t\tDWORD dwValue;\n\t\tDWORD dwBufSize = sizeof( DWORD );\n\t\tif( RegQueryValueEx( hKey, \"AftermathInstalled\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\t\tbInstalled = false;\n\t\telse\n\t\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\t\tRegCloseKey( hKey );\n\t\tbAlreadyChecked = true;\n\t}\n\treturn bInstalled;\n\n//\tRawFileClass file(\"EXPAND2.MIX\");\n//\treturn(file.Is_Available());\n#endif\n}\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nvoid Enable_Secret_Units(void)\n{\n#if 0\n\tSecretUnitsEnabled=true;\n\tUnitTypeClass::As_Reference(UNIT_PHASE).Level=10;\n\tVesselTypeClass::As_Reference(VESSEL_CARRIER).Level=10;\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildings.Ptr(index)->Update_Buildables();\n\t}\n#endif\n}\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName )\n{\n\t//\tCalls Force_CD_Available based on type of scenario. szName is assumed to be an official scenario here.\n\tif( Is_Mission_Counterstrike( (char*)szName ) )\n\t{\n//\t\tdebugprint( \"Force_Scenario_Available requiring disk 4...\\n\" );\n\t\treturn Force_CD_Available( 4 );\n\t}\n\telse if( Is_Mission_Aftermath( (char*)szName ) )\n\t{\n//\t\tdebugprint( \"Force_Scenario_Available requiring disk 3...\\n\" );\n\t\treturn Force_CD_Available( 3 );\n\t}\n\treturn true;\n}\n#endif"
  },
  {
    "path": "REDALERT/CONQUER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#define TXT_NONE                 \t0  \t//                \n#define TXT_CREDIT_FORMAT        \t1  \t// %3d.%02d\n#define TXT_TIME_FORMAT_HOURS    \t2  \t// Temps:%02d:%02d:%02d\n#define TXT_TIME_FORMAT_NO_HOURS \t3  \t// Temps:%02d:%02d\n#define TXT_BUTTON_SELL          \t4  \t// Vente\n#define TXT_SELL                 \t5  \t// Vente structure\n#define TXT_BUTTON_REPAIR        \t6  \t// Rparation\n#define TXT_YOU                  \t7  \t// Vous :\n#define TXT_ENEMY                \t8  \t// Ennemi :\n#define TXT_BUILD_DEST           \t9  \t// Btiments dtruits par\n#define TXT_UNIT_DEST            \t10 \t// Units dtruites par\n#define TXT_TIB_HARV             \t11 \t// Minerai rcolt par\n#define TXT_SCORE_1              \t12 \t// Score: %d\n#define TXT_YES                  \t13 \t// Oui\n#define TXT_NO                   \t14 \t// Non\n#define TXT_SCENARIO_WON         \t15 \t// Mission Accomplie\n#define TXT_SCENARIO_LOST        \t16 \t// Mission Echoue\n#define TXT_START_NEW_GAME       \t17 \t// Nouvelle partie\n#define TXT_INTRO                \t18 \t// Intro/Preview\n#define TXT_CANCEL               \t19 \t// Annuler\n#define TXT_ROCK                 \t20 \t// Rocher\n#define TXT_CIVILIAN             \t21 \t// Civil\n#define TXT_JP                   \t22 \t// Equipe de confinement\n#define TXT_OK                   \t23 \t// OK\n#define TXT_TREE                 \t24 \t// Arbre\n#define TXT_LEFT                 \t25 \t// \u0011\n#define TXT_RIGHT                \t26 \t// \u0010\n#define TXT_UP                   \t27 \t// \u001e\n#define TXT_DOWN                 \t28 \t// \u001f\n#define TXT_CLEAR                \t29 \t// Effacer\n#define TXT_WATER                \t30 \t// Eau\n#define TXT_ROAD                 \t31 \t// Route\n#define TXT_SLOPE                \t32 \t// Pente\n#define TXT_PATCH                \t33 \t// Patch\n#define TXT_RIVER                \t34 \t// Rivire\n#define TXT_LOAD_MISSION         \t35 \t// Charger Mission\n#define TXT_SAVE_MISSION         \t36 \t// Sauvegarder Mission\n#define TXT_DELETE_MISSION       \t37 \t// Effacer Mission\n#define TXT_LOAD_BUTTON          \t38 \t// Charger\n#define TXT_SAVE_BUTTON          \t39 \t// Sauvegarder\n#define TXT_DELETE_BUTTON        \t40 \t// Effacer\n#define TXT_GAME_CONTROLS        \t41 \t// Contrles\n#define TXT_SOUND_CONTROLS       \t42 \t// Son\n#define TXT_RESUME_MISSION       \t43 \t// Reprendre Mission\n#define TXT_VISUAL_CONTROLS      \t44 \t// Affichage\n#define TXT_QUIT_MISSION         \t45 \t// Abandonner Mission\n#define TXT_EXIT_GAME            \t46 \t// Quitter le jeu\n#define TXT_OPTIONS              \t47 \t// Options\n#define TXT_SQUISH               \t48 \t// Dbris humains\n#define TXT_CRATER               \t49 \t// Cratre\n#define TXT_SCORCH               \t50 \t// Marque de brlure\n#define TXT_BRIGHTNESS           \t51 \t// Luminosit :\n#define TXT_MUSIC                \t52 \t// Musique\n#define TXT_VOLUME               \t53 \t// Effets sonores\n#define TXT_TINT                 \t54 \t// Teintes :\n#define TXT_CONTRAST             \t55 \t// Contraste :\n#define TXT_SPEED                \t56 \t// Vitesse du jeu :\n#define TXT_SCROLLRATE           \t57 \t// Vitesse dfilement :\n#define TXT_COLOR                \t58 \t// Couleur :\n#define TXT_RETURN_TO_GAME       \t59 \t// Revenir au jeu\n#define TXT_ENEMY_SOLDIER        \t60 \t// Soldat ennemi\n#define TXT_ENEMY_VEHICLE        \t61 \t// Vhicule ennemi\n#define TXT_ENEMY_STRUCTURE      \t62 \t// Structure ennemie\n#define TXT_LTANK                \t63 \t// Tank lger\n#define TXT_MTANK                \t64 \t// Tank lourd\n#define TXT_MTANK2               \t65 \t// Tank moyen\n#define TXT_HTANK                \t66 \t// Tank Mammouth\n#define TXT_SAM                  \t67 \t// Missiles SAM\n#define TXT_JEEP                 \t68 \t// Ranger\n#define TXT_TRANS                \t69 \t// Hlicoptre Chinook\n#define TXT_HARVESTER            \t70 \t// Collecteur minerai\n#define TXT_ARTY                 \t71 \t// Artillerie\n#define TXT_E1                   \t72 \t// Mitrailleurs\n#define TXT_E2                   \t73 \t// Grenadiers\n#define TXT_E3                   \t74 \t// Bazookas\n#define TXT_E4                   \t75 \t// Lance-flammes\n#define TXT_HELI                 \t76 \t// Hlicoptre d'assaut\n#define TXT_ORCA                 \t77 \t// Hind\n#define TXT_APC                  \t78 \t// VBT\n#define TXT_GUARD_TOWER          \t79 \t// Tour de garde\n#define TXT_COMMAND              \t80 \t// Dme radar\n#define TXT_HELIPAD              \t81 \t// Hliport\n#define TXT_AIRSTRIP             \t82 \t// Piste d'atterrissage\n#define TXT_STORAGE              \t83 \t// Silo minerai\n#define TXT_CONST_YARD           \t84 \t// Chantier de construction\n#define TXT_REFINERY             \t85 \t// Raffinerie de minerai\n#define TXT_CIV1                 \t86 \t// Eglise\n#define TXT_CIV2                 \t87 \t// Chez Hans et Gretel\n#define TXT_CIV3                 \t88 \t// Manoir d'Hewitt\n#define TXT_CIV4                 \t89 \t// Maison de Ricktor\n#define TXT_CIV5                 \t90 \t// Maison de Gretchin\n#define TXT_CIV6                 \t91 \t// La grange\n#define TXT_CIV7                 \t92 \t// Pub Damon\n#define TXT_CIV8                 \t93 \t// Maison de Fran\n#define TXT_CIV9                 \t94 \t// Usine d'instruments\n#define TXT_CIV10                \t95 \t// Fabricant de jouets\n#define TXT_CIV11                \t96 \t// Maison de Ludwig\n#define TXT_CIV12                \t97 \t// Meules de foin\n#define TXT_CIV13                \t98 \t// Meule de foin\n#define TXT_CIV14                \t99 \t// Champ de bl\n#define TXT_CIV15                \t100\t// Champ en friche\n#define TXT_CIV16                \t101\t// Champ de mas\n#define TXT_CIV17                \t102\t// Champ de cleri\n#define TXT_CIV18                \t103\t// Champ de pommes de terre\n#define TXT_CIV20                \t104\t// Maison de Sala\n#define TXT_CIV21                \t105\t// Maison d'Abdul\n#define TXT_CIV22                \t106\t// Le Pub Barjo de Pablo\n#define TXT_CIV23                \t107\t// Puits du village\n#define TXT_CIV24                \t108\t// Marchand de chameaux\n#define TXT_CIV25                \t109\t// Eglise\n#define TXT_CIV26                \t110\t// Maison d'Ali\n#define TXT_CIV27                \t111\t// Ted le Marchand\n#define TXT_CIV28                \t112\t// Maison de Menelik\n#define TXT_CIV29                \t113\t// Maison du pasteur John\n#define TXT_CIV30                \t114\t// Puits du village\n#define TXT_CIV31                \t115\t// Hutte du gurisseur\n#define TXT_CIV32                \t116\t// Hutte de Rikitikitembo\n#define TXT_CIV33                \t117\t// Hutte de Roarke\n#define TXT_CIV34                \t118\t// Hutte de Moubasa'\n#define TXT_CIV35                \t119\t// Hutte d'Aksoum\n#define TXT_CIV36                \t120\t// Hutte de Mambo\n#define TXT_CIV37                \t121\t// Le studio\n#define TXT_CIVMISS              \t122\t// Centre technologique\n#define TXT_TURRET               \t123\t// Tourelle\n#define TXT_GUNBOAT              \t124\t// Aviso-torpilleur\n#define TXT_MCV                  \t125\t// Vhicule de construction\n#define TXT_POWER                \t126\t// Centrale lectrique\n#define TXT_ADVANCED_POWER       \t127\t// Centrale lectrique avance\n#define TXT_HOSPITAL             \t128\t// Hpital\n#define TXT_BARRACKS             \t129\t// Caserne\n#define TXT_PUMP                 \t130\t// Pompe\n#define TXT_TANKER               \t131\t// Ptrolier\n#define TXT_SANDBAG_WALL         \t132\t// Sacs de sable\n#define TXT_CYCLONE_WALL         \t133\t// Clture grillage\n#define TXT_BRICK_WALL           \t134\t// Mur de bton\n#define TXT_BARBWIRE_WALL        \t135\t// Clture barbele\n#define TXT_WOOD_WALL            \t136\t// Barrire de bois\n#define TXT_WEAPON_FACTORY       \t137\t// Usine d'armement\n#define TXT_AGUARD_TOWER         \t138\t// Tour de garde avance\n#define TXT_BIO_LAB              \t139\t// Laboratoire biologique\n#define TXT_FIX_IT               \t140\t// Centre de service\n#define TXT_TAB_SIDEBAR          \t141\t// Contrles\n#define TXT_TAB_BUTTON_CONTROLS  \t142\t// Options\n#define TXT_TAB_BUTTON_DATABASE  \t143\t// Base de donnes\n#define TXT_SHADOW               \t144\t// Terrain inconnu\n#define TXT_OPTIONS_MENU         \t145\t// Menu des options\n#define TXT_STOP                 \t146\t// Stop\n#define TXT_PLAY                 \t147\t// Lect\n#define TXT_SHUFFLE              \t148\t// Alat.\n#define TXT_REPEAT               \t149\t// Rpter\n#define TXT_MUSIC_VOLUME         \t150\t// Musique :\n#define TXT_SOUND_VOLUME         \t151\t// Effets sonores :\n#define TXT_ON                   \t152\t// Oui\n#define TXT_OFF                  \t153\t// Non\n#define TXT_MULTIPLAYER_GAME     \t154\t// Jeu Multijoueurs\n#define TXT_NO_FILES             \t155\t// Pas de fichiers disponibles\n#define TXT_DELETE_SINGLE_FILE   \t156\t// Voulez-vous effacer ce\n#define TXT_DELETE_MULTIPLE_FILES\t157\t// Voulez-vous effacer %d\n#define TXT_RESET_MENU           \t158\t// Dfaut\n#define TXT_CONFIRM_EXIT         \t159\t// Voulez-vous abandonner la\n#define TXT_MISSION_DESCRIPTION  \t160\t// Description de la mission\n#define TXT_C1                   \t161\t// Joe\n#define TXT_C2                   \t162\t// Barry\n#define TXT_C3                   \t163\t// Shelly\n#define TXT_C4                   \t164\t// Maria\n#define TXT_C5                   \t165\t// Karen\n#define TXT_C6                   \t166\t// Steve\n#define TXT_C7                   \t167\t// Phil\n#define TXT_C8                   \t168\t// Dwight\n#define TXT_C9                   \t169\t// Erik\n#define TXT_EINSTEIN             \t170\t// Prof. Einstein\n#define TXT_BIB                  \t171\t// Cour\n#define TXT_FASTER               \t172\t// Rapide\n#define TXT_SLOWER               \t173\t// Lent\n#define TXT_AIR_STRIKE           \t174\t// Attaque arienne\n#define TXT_STEEL_CRATE          \t175\t// Caisse d'acier\n#define TXT_WOOD_CRATE           \t176\t// Caisse de bois\n#define TXT_WATER_CRATE          \t177\t// Caisse flottante\n#define TXT_FLAG_SPOT            \t178\t// Emplacement du drapeau\n#define TXT_UNABLE_READ_SCENARIO \t179\t// Lecture scnario impossible\n#define TXT_ERROR_LOADING_GAME   \t180\t// Erreur de chargement !\n#define TXT_OBSOLETE_SAVEGAME    \t181\t// Sauvegarde obsolte\n#define TXT_MUSTENTER_DESCRIPTION\t182\t// Vous devez entrer une\n#define TXT_ERROR_SAVING_GAME    \t183\t// Erreur de sauvegarde !\n#define TXT_DELETE_FILE_QUERY    \t184\t// Effacer ce fichier ?\n#define TXT_EMPTY_SLOT           \t185\t// [EMPLACEMENT VIDE]\n#define TXT_SELECT_MPLAYER_GAME  \t186\t// Choix du jeu Multijoueurs\n#define TXT_MODEM_SERIAL         \t187\t// Modem/Srie\n#define TXT_NETWORK              \t188\t// Rseau\n#define TXT_INIT_NET_ERROR       \t189\t// Initialisation rseau\n#define TXT_JOIN_NETWORK_GAME    \t190\t// Rejoindre jeu en rseau\n#define TXT_NEW                  \t191\t// Nouveau\n#define TXT_JOIN                 \t192\t// Joindre\n#define TXT_SEND_MESSAGE         \t193\t// Envoi Message\n#define TXT_YOUR_NAME            \t194\t// Votre nom :\n#define TXT_SIDE_COLON           \t195\t// Camp :\n#define TXT_COLOR_COLON          \t196\t// Couleur :\n#define TXT_GAMES                \t197\t// Parties\n#define TXT_PLAYERS              \t198\t// Joueurs\n#define TXT_SCENARIO_COLON       \t199\t// Scnario :\n#define TXT_NOT_FOUND            \t200\t// >> NON TROUVE <<\n#define TXT_START_CREDITS_COLON  \t201\t// Crdits :\n#define TXT_BASES_COLON          \t202\t// Bases :\n#define TXT_TIBERIUM_COLON       \t203\t// Minerai :\n#define TXT_CRATES_COLON         \t204\t// Caisses :\n#define TXT_AI_PLAYERS_COLON     \t205\t// Joueurs IA :\n#define TXT_REQUEST_DENIED       \t206\t// Demande refuse.\n#define TXT_UNABLE_PLAY_WAAUGH   \t207\t// Impossible de jouer,\n#define TXT_NOTHING_TO_JOIN      \t208\t// Aucune partie disponible !\n#define TXT_NAME_ERROR           \t209\t// Vous devez entrer un nom !\n#define TXT_DUPENAMES_NOTALLOWED \t210\t// Les noms identiques ne sont\n#define TXT_YOURGAME_OUTDATED    \t211\t// La version de votre jeu est\n#define TXT_DESTGAME_OUTDATED    \t212\t// Version du jeu de\n#define TXT_THATGUYS_GAME        \t213\t// Partie de %s\n#define TXT_THATGUYS_GAME_BRACKET\t214\t// [Partie de %s]\n#define TXT_NETGAME_SETUP        \t215\t// Configuration du jeu en\n#define TXT_REJECT               \t216\t// Rejeter\n#define TXT_CANT_REJECT_SELF     \t217\t// Vous ne pouvez pas vous\n#define TXT_SELECT_PLAYER_REJECT \t218\t// Vous devez slectionner un\n#define TXT_BASES                \t219\t// Bases\n#define TXT_CRATES               \t220\t// Caisses\n#define TXT_AI_PLAYERS           \t221\t// Joueur IA\n#define TXT_SCENARIOS            \t222\t// Scnarios\n#define TXT_CREDITS_COLON        \t223\t// Crdits :\n#define TXT_ONLY_ONE             \t224\t// Un seul joueur ?\n#define TXT_OOPS                 \t225\t// Oops !\n#define TXT_TO                   \t226\t// Pour %s :\n#define TXT_TO_ALL               \t227\t// Pour tous\n#define TXT_MESSAGE              \t228\t// Message :\n#define TXT_CONNECTION_LOST      \t229\t// Perte de connexion avec %s\n#define TXT_LEFT_GAME            \t230\t// %s a quitt le jeu.\n#define TXT_PLAYER_DEFEATED      \t231\t// %s a t vaincu !\n#define TXT_WAITING_CONNECT      \t232\t// Attente de connexion...\n#define TXT_NULL_CONNERR_CHECK_CABLES\t233\t// Erreur de connexion !\n#define TXT_MODEM_CONNERR_REDIALING\t234\t// Erreur de connexion !\n#define TXT_MODEM_CONNERR_WAITING\t235\t// Erreur de connexion !\n#define TXT_SELECT_SERIAL_GAME   \t236\t// Choix du jeu en srie\n#define TXT_DIAL_MODEM           \t237\t// Appel\n#define TXT_ANSWER_MODEM         \t238\t// Attente appel\n#define TXT_NULL_MODEM           \t239\t// Null Modem\n#define TXT_SETTINGS             \t240\t// Paramtres\n#define TXT_PORT_COLON           \t241\t// Port :\n#define TXT_IRQ_COLON            \t242\t// IRQ :\n#define TXT_BAUD_COLON           \t243\t// Bauds :\n#define TXT_INIT_STRING          \t244\t// Chane d'initialisation\n#define TXT_CWAIT_STRING         \t245\t// Chane d'attente d'appel\n#define TXT_TONE_BUTTON          \t246\t// Tonalit\n#define TXT_PULSE_BUTTON         \t247\t// Impulsions\n#define TXT_HOST_SERIAL_GAME     \t248\t// Hte du jeu en srie\n#define TXT_OPPONENT_COLON       \t249\t// Adversaire :\n#define TXT_USER_SIGNED_OFF      \t250\t// Utilisateur reparti !\n#define TXT_JOIN_SERIAL_GAME     \t251\t// Rejoindre jeu en srie\n#define TXT_PHONE_LIST           \t252\t// Rpertoire\n#define TXT_ADD                  \t253\t// Ajouter\n#define TXT_EDIT                 \t254\t// Editer\n#define TXT_DIAL                 \t255\t// Appel\n#define TXT_DEFAULT              \t256\t// Dfaut\n#define TXT_DEFAULT_SETTINGS     \t257\t// Dfaut\n#define TXT_CUSTOM_SETTINGS      \t258\t// Autres paramtres\n#define TXT_PHONE_LISTING        \t259\t// Rpertoire\n#define TXT_NAME_COLON           \t260\t// Nom :\n#define TXT_NUMBER_COLON         \t261\t// Numro :\n#define TXT_UNABLE_FIND_MODEM    \t262\t// Modem non dtect. Vrifiez\n#define TXT_NO_CARRIER           \t263\t// Pas de porteuse.\n#define TXT_LINE_BUSY            \t264\t// Ligne occupe.\n#define TXT_NUMBER_INVALID       \t265\t// Numro incorrect.\n#define TXT_SYSTEM_NOT_RESPONDING\t266\t// L'autre systme ne rpond\n#define TXT_OUT_OF_SYNC          \t267\t// Mauvaise synchronisation !\n#define TXT_PACKET_TOO_LATE      \t268\t// Paquet reu trop tard !\n#define TXT_PLAYER_LEFT_GAME     \t269\t// L'autre joueur a quitt le\n#define TXT_FROM                 \t270\t// De %s:%s\n#define TXT_SCORE_TIME           \t271\t// TEMPS :\n#define TXT_SCORE_LEAD           \t272\t// COMMANDEMENT :\n#define TXT_SCORE_EFFI           \t273\t// EFFICACITE :\n#define TXT_SCORE_TOTA           \t274\t// SCORE TOTAL :\n#define TXT_SCORE_CASU           \t275\t// PERTES :\n#define TXT_SCORE_NEUT           \t276\t// NEUTRE :\n#define TXT_SCORE_BUIL           \t277\t// BATIMENTS PERDUS\n#define TXT_SCORE_BUIL1          \t278\t// BATIMENTS\n#define TXT_SCORE_BUIL2          \t279\t// PERDUS :\n#define TXT_SCORE_TOP            \t280\t// MEILLEURS SCORES\n#define TXT_SCORE_ENDCRED        \t281\t// CREDITS DE FIN :\n#define TXT_SCORE_TIMEFORMAT1    \t282\t// %dh %dm\n#define TXT_SCORE_TIMEFORMAT2    \t283\t// %dm\n#define TXT_DIALING              \t284\t// Appel...\n#define TXT_DIALING_CANCELED     \t285\t// Appel annul\n#define TXT_WAITING_FOR_CALL     \t286\t// Attente d'appel...\n#define TXT_ANSWERING_CANCELED   \t287\t// Attente d'appel annule\n#define TXT_E6                   \t288\t// Ingnieurs\n#define TXT_E8                   \t289\t// Espion\n#define TXT_MODEM_OR_LOOPBACK    \t290\t// Pas de cble Null Modem\n#define TXT_MAP                  \t291\t// Carte\n#define TXT_BLOSSOM_TREE         \t292\t// Arbre en fleurs\n#define TXT_RESTATE_MISSION      \t293\t// Briefing\n#define TXT_COMPUTER             \t294\t// Joueur IA\n#define TXT_COUNT                \t295\t// Nombre :\n#define TXT_LEVEL                \t296\t// Niveau :\n#define TXT_OPPONENT             \t297\t// Adversaire\n#define TXT_KILLS_COLON          \t298\t// Vict.:\n#define TXT_VIDEO                \t299\t// Vido\n#define TXT_C10                  \t300\t// Scientifique\n#define TXT_CAPTURE_THE_FLAG     \t301\t// Capture drapeau\n#define TXT_OBJECTIVE            \t302\t// Objectifs de mission\n#define TXT_MISSION              \t303\t// Mission\n#define TXT_NO_SAVES             \t304\t// Pas de sauvegardes\n#define TXT_CIVILIAN_BUILDING    \t305\t// Btiment civil\n#define TXT_TECHNICIAN           \t306\t// Technicien\n#define TXT_NO_SAVELOAD          \t307\t// Sauvegarde interdite en\n#define TXT_DELPHI               \t308\t// Agent Spcial 1\n#define TXT_TO_REPLAY            \t309\t// Voulez-vous recommencer\n#define TXT_RECONN_TO            \t310\t// Reconnexion vers %s.\n#define TXT_PLEASE_WAIT          \t311\t// Attendez %02d secondes.\n#define TXT_SURRENDER            \t312\t// Voulez-vous vous rendre ?\n#define TXT_SEL_TRANS            \t313\t// CHOIX DE LA TRANSMISSION\n#define TXT_GAMENAME_MUSTBE_UNIQUE\t314\t// Les sauvegardes ne peuvent\n#define TXT_GAME_IS_CLOSED       \t315\t// Partie ferme.\n#define TXT_NAME_MUSTBE_UNIQUE   \t316\t// Les noms doivent tre tous\n#define TXT_RECONNECTING_TO      \t317\t// Reconnexion vers %s\n#define TXT_WAITING_FOR_CONNECTIONS\t318\t// Attente de connexions...\n#define TXT_TIME_ALLOWED         \t319\t// Temps autoris : %02d\n#define TXT_PRESS_ESC            \t320\t// Appuyez sur Echap pour\n#define TXT_JUST_YOU_AND_ME      \t321\t// De l'ordinateur : Il ne\n#define TXT_CAPTURE_THE_FLAG_COLON\t322\t// Capture du drapeau :\n#define TXT_CHAN                 \t323\t// Agent Spcial 2\n#define TXT_HAS_ALLIED           \t324\t// %s s'est alli(e) avec %s\n#define TXT_AT_WAR               \t325\t// %s dclare la guerre  %s\n#define TXT_SEL_TARGET           \t326\t// Choisissez un cible\n#define TXT_RESIGN               \t327\t// Abandonner\n#define TXT_TIBERIUM_FAST        \t328\t// Le minerai pousse trs\n#define TXT_ANSWERING            \t329\t// Rponse en cours...\n#define TXT_INITIALIZING_MODEM   \t330\t// Initialisation Modem...\n#define TXT_SCENARIOS_DO_NOT_MATCH\t331\t// Les scnarios ne\n#define TXT_POWER_OUTPUT         \t332\t// Production d'nergie\n#define TXT_POWER_OUTPUT_LOW     \t333\t// Production d'nergie\n#define TXT_CONTINUE             \t334\t// Continuer\n#define TXT_QUEUE_FULL           \t335\t// Saturation des donnes \n#define TXT_SPECIAL_WARNING      \t336\t// %s a modifi les options de\n#define TXT_CD_DIALOG_1          \t337\t// Placez un CD d'Alerte Rouge\n#define TXT_CD_DIALOG_2          \t338\t// Placez le CD %d (%s) dans\n#define TXT_CD_ERROR1            \t339\t// Alerte Rouge n'a pas\n#define TXT_NO_SOUND_CARD        \t340\t// Pas de carte sonore\n#define TXT_UNKNOWN              \t341\t// INCONNU\n#define TXT_OLD_GAME             \t342\t// (ancien)\n#define TXT_NO_SPACE             \t343\t// Espace disque insuffisant\n#define TXT_MUST_HAVE_SPACE      \t344\t// Vous devez disposer de %d\n#define TXT_RUN_SETUP            \t345\t// Lancez d'abord le programme\n#define TXT_WAITING_FOR_OPPONENT \t346\t// Attente adversaire\n#define TXT_SELECT_SETTINGS      \t347\t// Choisissez l'option\n#define TXT_PRISON               \t348\t// Prison\n#define TXT_GAME_WAS_SAVED       \t349\t// Mission sauvegarde\n#define TXT_SPACE_CANT_SAVE      \t350\t// Espace disque insuffisant\n#define TXT_INVALID_PORT_ADDRESS \t351\t// Port/Adresse invalide. COM\n#define TXT_INVALID_SETTINGS     \t352\t// paramtres Port et/ou IRQ\n#define TXT_IRQ_ALREADY_IN_USE   \t353\t// IRQ dj utilis\n#define TXT_ABORT                \t354\t// Oui\n#define TXT_RESTART              \t355\t// Recommencer\n#define TXT_RESTARTING           \t356\t// Mission relance. Attendez\n#define TXT_LOADING              \t357\t// Chargement de la mission.\n#define TXT_ERROR_IN_INITSTRING  \t358\t// Erreur chane\n#define TXT_SHADOW_COLON         \t359\t// Ombre\n#define TXT_AVMINE               \t360\t// Mine Anti-Vhicule\n#define TXT_APMINE               \t361\t// Mine Anti-Personnel\n#define TXT_NEW_MISSIONS         \t362\t// Nouvelles missions\n#define TXT_THIEF                \t363\t// Voleur\n#define TXT_MRJ                  \t364\t// Brouilleur de radar\n#define TXT_GAP_GENERATOR        \t365\t// Gnrateur d'ombre\n#define TXT_PILLBOX              \t366\t// Bunker\n#define TXT_CAMOPILLBOX          \t367\t// Bunker camoufl\n#define TXT_CHRONOSPHERE         \t368\t// Chronosphre\n#define TXT_ENGLAND              \t369\t// Roy. Uni\n#define TXT_GERMANY              \t370\t// Allemagne\n#define TXT_SPAIN                \t371\t// Espagne\n#define TXT_USSR                 \t372\t// URSS\n#define TXT_UKRAINE              \t373\t// Ukraine\n#define TXT_GREECE               \t374\t// Grce\n#define TXT_FRANCE               \t375\t// France\n#define TXT_TURKEY               \t376\t// Turquie\n#define TXT_SHORE                \t377\t// Rivage\n#define TXT_PLACE_OBJECT         \t378\t// Choisir objet\n#define TXT_SS                   \t379\t// Sous-marin\n#define TXT_DD                   \t380\t// Contre-torpilleur\n#define TXT_CA                   \t381\t// Croiseur\n#define TXT_TRANSPORT            \t382\t// Transport\n#define TXT_PT                   \t383\t// Aviso-torpilleur\n#define TXT_LOBBY                \t384\t// Hall\n#define TXT_CHANNEL_GAMES        \t385\t// Parties\n#define TXT_SAVING_GAME          \t386\t// Sauvegarder partie...\n#define TXT_GAME_FULL            \t387\t// La partie est au complet.\n#define TXT_MUST_SELECT_GAME     \t388\t// Vous devez slectionner une\n#define TXT_S_PLAYING_S          \t389\t// %s joue contre %s\n#define TXT_ONLY_HOST_CAN_MODIFY \t390\t// Seul l'hte peut modifier\n#define TXT_GAME_CANCELLED       \t391\t// La partie a t annule.\n#define TXT_S_FORMED_NEW_GAME    \t392\t// %s a initi une nouvelle\n#define TXT_GAME_NOW_IN_PROGRESS \t393\t// La partie de %s est\n#define TXT_TESLA                \t394\t// Bobine de Tesla\n#define TXT_MGG                  \t395\t// Gnrateur d'ombre mobile\n#define TXT_FLAME_TURRET         \t396\t// Tour lance-flammes\n#define TXT_AAGUN                \t397\t// Canon Anti-Avion\n#define TXT_KENNEL               \t398\t// Niche\n#define TXT_SOVIET_TECH          \t399\t// Centre Technique\n#define TXT_BADGER               \t400\t// Bombardier\n#define TXT_MIG                  \t401\t// Mig\n#define TXT_YAK                  \t402\t// Yak\n#define TXT_FENCE                \t403\t// Barbels\n#define TXT_MEDIC                \t404\t// Mdecin\n#define TXT_SABOTEUR             \t405\t// Saboteur\n#define TXT_GENERAL              \t406\t// Gnral\n#define TXT_E7                   \t407\t// Tanya\n#define TXT_PARA_BOMB            \t408\t// Parabombes\n#define TXT_PARA_INFANTRY        \t409\t// Parachutistes\n#define TXT_PARA_SABOTEUR        \t410\t// Saboteur parachutiste\n#define TXT_SHIP_YARD            \t411\t// Chantier naval\n#define TXT_SUB_PEN              \t412\t// Port sous-marin\n#define TXT_SCENARIO_OPTIONS     \t413\t// Options Scnario\n#define TXT_SPY_MISSION          \t414\t// Avion espion\n#define TXT_U2                   \t415\t// Avion espion\n#define TXT_GUARD_DOG            \t416\t// Chien d'attaque\n#define TXT_SPY_INFO             \t417\t// Info Espion\n#define TXT_BUILDNGS             \t418\t// Btiments\n#define TXT_UNITS                \t419\t// Units\n#define TXT_INFANTRY             \t420\t// Infanterie\n#define TXT_AIRCRAFT             \t421\t// Avion\n#define TXT_TRUCK                \t422\t// Camion d'approvisionnement\n#define TXT_INVUL                \t423\t// Module d'invulnrabilit\n#define TXT_IRON_CURTAIN         \t424\t// Rideau de Fer\n#define TXT_ADVANCED_TECH        \t425\t// Centre technique avanc\n#define TXT_V2_LAUNCHER          \t426\t// Lance-roquettes V2\n#define TXT_FORWARD_COM          \t427\t// Poste de commandement\n#define TXT_DEMOLITIONER         \t428\t// Bombardeur\n#define TXT_MINE_LAYER           \t429\t// Poseur de mines\n#define TXT_FAKE_CONST           \t430\t// Chantier de construction\n#define TXT_FAKE_WEAP            \t431\t// Usine d'armement leurre\n#define TXT_FAKE_YARD            \t432\t// Chantier naval leurre\n#define TXT_FAKE_PEN             \t433\t// Port sous-marin leurre\n#define TXT_FAKE_RADAR           \t434\t// Dme radar leurre\n#define TXT_THEME_BIGF           \t435\t// Bigfoot\n#define TXT_THEME_CRUS           \t436\t// La rvolte\n#define TXT_THEME_FAC1           \t437\t// A l'attaque 1\n#define TXT_THEME_FAC2           \t438\t// A l'attaque 2\n#define TXT_THEME_HELL           \t439\t// Marche de l'enfer\n#define TXT_THEME_RUN1           \t440\t// Sauve-qui-peut\n#define TXT_THEME_SMSH           \t441\t// La dbcle\n#define TXT_THEME_TREN           \t442\t// Tranches\n#define TXT_THEME_WORK           \t443\t// Les professionnels\n#define TXT_THEME_AWAIT          \t444\t// Attente\n#define TXT_THEME_DENSE_R        \t445\t// Dense\n#define TXT_THEME_MAP            \t446\t// Slection carte\n#define TXT_THEME_FOGGER1A       \t447\t// Fogger\n#define TXT_THEME_MUD1A          \t448\t// Boue\n#define TXT_THEME_RADIO2         \t449\t// Radio 2\n#define TXT_THEME_ROLLOUT        \t450\t// Laminage\n#define TXT_THEME_SNAKE          \t451\t// Serpent\n#define TXT_THEME_TERMINAT       \t452\t// Extermination\n#define TXT_THEME_TWIN           \t453\t// Jumeau\n#define TXT_THEME_VECTOR1A       \t454\t// Vecteur\n#define TXT_TEAM_MEMBERS         \t455\t// Equipiers\n#define TXT_BRIDGE               \t456\t// Pont\n#define TXT_BARREL               \t457\t// Baril\n#define TXT_GOODGUY              \t458\t// Amical\n#define TXT_BADGUY               \t459\t// Ennemi\n#define TXT_GOLD                 \t460\t// Or\n#define TXT_GEMS                 \t461\t// Gemmes\n#define TXT_TEASER               \t462\t// Film titre\n#define TXT_MOVIES               \t463\t// Films\n#define TXT_INTERIOR             \t464\t// Intrieur\n#define TXT_SONAR_PULSE          \t465\t// Signal sonar\n#define TXT_MSLO                 \t466\t// Silo de missiles\n#define TXT_GPS_SATELLITE        \t467\t// Satellite GPS\n#define TXT_NUCLEAR_BOMB         \t468\t// Bombe atomique\n#define TXT_EASY                 \t469\t// Facile\n#define TXT_HARD                 \t470\t// Difficile\n#define TXT_NORMAL               \t471\t// Normal\n#define TXT_DIFFICULTY           \t472\t// Slectionnez un niveau de\n#define TXT_ALLIES               \t473\t// Allis\n#define TXT_SOVIET               \t474\t// Soviets\n#define TXT_THEME_INTRO          \t475\t// Thme Intro\n#define TXT_SHADOW_REGROWS       \t476\t// Progr. ombre\n#define TXT_ORE_SPREADS          \t477\t// Progr. minerai\n#define TXT_THEME_SCORE          \t478\t// Musiques\n#define TXT_INTERNET             \t479\t// Internet\n#define TXT_ICE                  \t480\t// Glace\n#define TXT_CRATE                \t481\t// Caisses\n#define TXT_SKIRMISH             \t482\t// Escarmouche\n#define TXT_CHOOSE               \t483\t// Choisissez votre camp.\n#define TXT_MINERALS             \t484\t// Minraux prcieux\n#define TXT_IGNORE               \t485\t// Ignorer\n#define TXT_ERROR_NO_RESP        \t486\t// Erreur - le modem ne rpond\n#define TXT_ERROR_NO_RESCODE     \t487\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_INIT        \t488\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_VERB        \t489\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_ECHO        \t490\t// Erreur - Le modem n'a pas\n#define TXT_ERROR_NO_DISABLE     \t491\t// Erreur - Impossible de\n#define TXT_ERROR_TOO_MANY       \t492\t// Erreur - Trop d'erreurs\n#define TXT_ERROR_ERROR          \t493\t// Erreur - Le modem a\n#define TXT_ERROR_TIMEOUT        \t494\t// Erreur - Temps d'attente de\n#define TXT_ACCOMPLISHED         \t495\t// Accompli\n#define TXT_CLICK_CONTINUE       \t496\t// Cliquez pour continuer\n#define TXT_RECEIVING_SCENARIO   \t497\t// Rception du scnario de\n#define TXT_SENDING_SCENARIO     \t498\t// Envoi du scnario aux\n#define TXT_NO_FLOW_CONTROL_RESPONSE\t499\t// Erreur - Le modem n'a pas\n#define TXT_NO_COMPRESSION_RESPONSE\t500\t// Erreur - Le modem n'a pas\n#define TXT_NO_ERROR_CORRECTION_RESPONSE\t501\t// Erreur - Le modem n'a pas\n#define TXT_EXPLAIN_REGISTRATION \t502\t// Pour jouer  Alerte Rouge\n#define TXT_ERROR_UNABLE_TO_RUN_WCHAT\t503\t// Erreur - Impossible\n#define TXT_REGISTER             \t504\t// Enregistrer\n#define TXT_ORE_MINE             \t505\t// Gisement Minerai\n#define TXT_NO_REGISTERED_MODEM  \t506\t// Aucun modem configur\n#define TXT_CHRONOSHIFT          \t507\t// Dplacement chronoporte\n#define TXT_UNABLE_TO_OPEN_PORT  \t508\t// Adresse invalide ou en\n#define TXT_NO_DIAL_TONE         \t509\t// Pas de tonalit.\n#define TXT_NO_EXPANSION_SCENARIO\t510\t// Erreur - L'autre joueur n'a\n#define TXT_STAND_BY             \t511\t// Patientez SVP...\n#define TXT_THEME_CREDITS        \t512\t// Musique du gnrique de fin\n#define TXT_POWER_AAGUN          \t513\t// Puissance faible: Canon(s)\n#define TXT_POWER_TESLA          \t514\t// Puissance faible: Bobine(s)\n#define TXT_LOW_POWER            \t515\t// Puissance Faible\n#define TXT_COMMANDER            \t516\t// Commandant:\n#define TXT_BATTLES_WON          \t517\t// Parties gagnes:\n#define TXT_MISMATCH             \t518\t// Fichier de donnes du jeu\n#define TXT_SCENARIO_ERROR       \t519\t// Votre version de jeu\n#define TXT_CONNECTING           \t520\t// Connecting\n#define TXT_MODEM_INITIALISATION \t521\t// Initialisation du Modem\n#define TXT_DATA_COMPRESSION     \t522\t// Compression des Donnes\n#define TXT_ERROR_CORRECTION     \t523\t// Correction d'Erreur\n#define TXT_HARDWARE_FLOW_CONTROL\t524\t// Contrle Matriel du Flux\n#define TXT_ADVANCED             \t525\t// Avanc\n#define TXT_THEME_2ND_HAND       \t526\t// Seconde main\n#define TXT_THEME_ARAZOID        \t527\t// Arazode\n#define TXT_THEME_BACKSTAB       \t528\t// Retour  l'envoyeur\n#define TXT_THEME_CHAOS2         \t529\t// Chaos2\n#define TXT_THEME_SHUT_IT        \t530\t// Fermez-la !\n#define TXT_THEME_TWINMIX1       \t531\t// Visite de courtoisie\n#define TXT_THEME_UNDER3         \t532\t// A couvert\n#define TXT_THEME_VR2            \t533\t// VR2\n#define TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING\t534\t// L'autre systme ne rpond\n#define TXT_ASK_EMERGENCY_SAVE_HUNG_UP\t535\t// L'autre systme a\n#define TXT_NO_REG_APP           \t536\t// Alerte Rouge n'a pu\n#define TXT_NO_CS_SCENARIOS      \t537\t// Un joueur de la partie n'a\n#define TXT_MISSILESUB           \t538\t// Sous-marin MS\n#define TXT_SHOCKTROOPER         \t539\t// Electrocuteur\n#define TXT_MECHANIC             \t540\t// Mcanicien\n#define TXT_CHRONOTANK           \t541\t// Chrono Tank\n#define TXT_TESLATANK            \t542\t// Tank Tesla\n#define TXT_MAD                  \t543\t// Tank M.A.D.\n#define TXT_DEMOTRUCK            \t544\t// Camion de dmolition\n#define TXT_PHASETRANSPORT       \t545\t// Transport Camlon\n#define TXT_THEME_BOG            \t546\t// Marcages\n#define TXT_THEME_FLOAT_V2       \t547\t// Volutes\n#define TXT_THEME_GLOOM          \t548\t// Tnbres\n#define TXT_THEME_GRNDWIRE       \t549\t// Terrain min\n#define TXT_THEME_RPT            \t550\t// Mcaniciens 2\n#define TXT_THEME_SEARCH         \t551\t// Battue\n#define TXT_THEME_TRACTION       \t552\t// Traction\n#define TXT_THEME_WASTELND       \t553\t// Chaos\n#define TXT_CARRIER              \t554\t// Hliport Mobile\n#define TXT_INSUFFICIENT_FUNDS      555"
  },
  {
    "path": "REDALERT/CONST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONST.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONST.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 20, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 20, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n**\tThese are the access passwords used to activate cheat mode, editor mode,\n**\tand special game options.\n*/\nunsigned long const PlayCodes[] = {\n\t0xE0792D6D,\t\t\t\t\t// Dwight Okahara\n\t0x90046ECF,\t\t\t\t\t// Paul S. Mudra\n\t0xC3EE9A26,\t\t\t\t\t// Frank Klepaki\n\t0xED382178,\t\t\t\t\t// Ed Del Castillo\n\t0L\n};\n\nunsigned long const CheatCodes[] = {\n\t0xA0E2AB53,\t\t\t\t\t// Joseph Hewitt\n\t0x00532693,\t\t\t\t\t// Mike Lightner\n\t0x7DDFF824,\t\t\t\t\t// Joe Bostic\n\t0x2CB5CF01,\t\t\t\t\t// Phil Gorrow\n\t0xB5B63531,\t\t\t\t\t// Bill Randolph\n\t0xDFABC23A,\t\t\t\t\t// Adam Isgreen\n\t0x52B19A22,\t\t\t\t\t// Erik Yeo\n\t0xBE79088C,\t\t\t\t\t// David Dettmer\n\t0xB216AE7E,\t\t\t\t\t// Barry Green\n\t0x0E07B213,\t\t\t\t\t// Steve Tall\n\t0L\n};\n\n\nunsigned long const EditorCodes[] = {\n\t0xA2C09326,\t\t\t\t\t// Erik Yeo\n\t0x1F944BB3,\t\t\t\t\t// Mike Lightner\n\t0xDE07154D,\t\t\t\t\t// Adam Isgreen\n\t0x0E07B213,\t\t\t\t\t// Steve Tall\n\t0x16B170B1,\t\t\t\t\t// Joe Bostic\n\t0L\n};\n\n\n/***********************************************************************************************\n**\tUnit order names. These names correspond to the player selectable orders\n**\ta unit can have. The system initiated orders have no use for the ASCII name\n**\tassociated, but they are listed here for completeness sake.\n*/\nchar const * Missions[MISSION_COUNT] = {\n\t\"Sleep\",\n\t\"Attack\",\n\t\"Move\",\n\t\"QMove\",\n\t\"Retreat\",\n\t\"Guard\",\n\t\"Sticky\",\n\t\"Enter\",\n\t\"Capture\",\n\t\"Harvest\",\n\t\"Area Guard\",\n\t\"Return\",\n\t\"Stop\",\n\t\"Ambush\",\n\t\"Hunt\",\n\t\"Unload\",\n\t\"Sabotage\",\n\t\"Construction\",\n\t\"Selling\",\n\t\"Repair\",\n\t\"Rescue\",\n\t\"Missile\",\n\t\"Harmless\"\n};\n\n\n/***************************************************************************\n**\tSpecial weapon names.\n*/\n#ifdef SCENARIO_EDITOR\nchar const * const SpecialWeaponName[SPC_COUNT] = {\n\t\"Sonar Pulse\",\n\t\"Nuclear Missile\",\n\t\"Chronosphere\",\n\t\"Parachute Bomb\",\n\t\"Paratroopers\",\n\t\"Recon Plane\",\n\t\"Iron Curtain\",\n\t\"GPS Satellite\"\n};\n#endif\nint const SpecialWeaponHelp[SPC_COUNT] = {\n\tTXT_SONAR_PULSE,\n\tTXT_NUCLEAR_BOMB,\n\tTXT_CHRONOSHIFT,\n\tTXT_PARA_BOMB,\n\tTXT_PARA_INFANTRY,\n\tTXT_SPY_MISSION,\n\tTXT_INVUL,\n\tTXT_GPS_SATELLITE\n};\nchar const * const SpecialWeaponFile[SPC_COUNT] = {\n\t\"SONR\",\n\t\"ATOM\",\n\t\"WARP\",\n\t\"PBMB\",\n\t\"PINF\",\n\t\"CAM\",\n\t\"INFX\",\n\t\"GPSS\"\n};\n\n\n/***************************************************************************\n**\tType of quarry to search out and attack. These values are used for team\n**\tattack missions.\n*/\nchar const * const QuarryName[QUARRY_COUNT] = {\n\t\"N/A\",\n\t\"Anything\",\n\t\"Buildings - any\",\n\t\"Harvesters\",\n\t\"Infantry\",\n\t\"Vehicles - any\",\n\t\"Ships - any\",\n\t\"Factories\",\n\t\"Base Defenses\",\n\t\"Base Threats\",\n\t\"Power Facilities\",\n\t\"Fake Buildings\"\n};\n\n\n/***************************************************************************\n**\tThese are the text names for the formation types.\n*/\nchar const * const FormationName[FORMATION_COUNT] = {\n\t\"None\",\n\n\t\"Tight\",\n\t\"Loose\",\n\t\"Wedge North\",\n\t\"Wedge East\",\n\t\"Wedge South\",\n\t\"Wedge West\",\n\t\"Line N/S\",\n\t\"Line E/W\"\n};\n\n\n/***************************************************************************\n**\tThese are the ASCII names for the reinforcement sources.\n*/\nchar const * const SourceName[SOURCE_COUNT] =\n{\n\t\"North\",\n\t\"East\",\n\t\"South\",\n\t\"West\",\n\t\"Air\"\n};\n\n\n/***************************************************************************\n**\tThese are the text names for the various armor types a unit may possess.\n*/\nchar const * const ArmorName[ARMOR_COUNT] = {\n\t\"none\",\n\t\"wood\",\n\t\"light\",\n\t\"heavy\",\n\t\"concrete\"\n};\n\n\n// HACK ALERT! This unused text string is here to stop Watcom from crashing. There is some\n// magic text heap length that causes a crash before the code executes. This dummy string\n// changes the text heap length enough to stop the crash. Who knows why, but it works.\nchar * __test__ = \"alskdfjlasdfjkajsdfkja;sldjfklasj9awutreqjfnfdkvnldzlknvadsjgflkasdjfkajsdfas\";\n\n\n/***************************************************************************\n**\tThe list of VQ filenames.\n*/\nchar const * const VQName[VQ_COUNT] = {\n\t\"AAGUN\",\n\t\"MIG\",\n\t\"SFROZEN\",\n\t\"AIRFIELD\",\n\t\"BATTLE\",\n\t\"BMAP\",\n\t\"BOMBRUN\",\n\t\"DPTHCHRG\",\n\t\"GRVESTNE\",\n\t\"MONTPASS\",\n\t\"MTNKFACT\",\n\t\"CRONTEST\",\n\t\"OILDRUM\",\n\t\"ALLIEND\",\n\t\"RADRRAID\",\n\t\"SHIPYARD\", // MISSING\n\t\"SHORBOMB\",\n\t\"SITDUCK\",\n\t\"SLNTSRVC\",\n\t\"SNOWBASE\",\n\t\"EXECUTE\",\n\t\"REDINTRO\",\t\t\t// low res.\n\t\"NUKESTOK\",\n\t\"V2ROCKET\",\n\t\"SEARCH\",\n\t\"BINOC\",\n\t\"ELEVATOR\",\n\t\"FROZEN\",\n\t\"MCV\",\n\t\"SHIPSINK\",\n\t\"SOVMCV\",\n\t\"TRINITY\",\n\t\"ALLYMORF\",\n\t\"APCESCPE\",\n\t\"BRDGTILT\",\n\t\"CRONFAIL\",\n\t\"STRAFE\",\n\t\"DESTROYR\",\n\t\"DOUBLE\",\n\t\"FLARE\",\n\t\"SNSTRAFE\",\n\t\"LANDING\",\n\t\"ONTHPRWL\",\n\t\"OVERRUN\",\n\t\"SNOWBOMB\",\n\t\"SOVCEMET\",\n\t\"TAKE_OFF\",\n\t\"TESLA\",\n\t\"SOVIET8\",\n\t\"SPOTTER\",\n\t\"ALLY1\",\n\t\"ALLY2\",\n\t\"ALLY4\",\n\t\"SOVFINAL\",\n\t\"ASSESS\",\n\t\"SOVIET10\",\n\t\"DUD\",\n\t\"MCV_LAND\",\n\t\"MCVBRDGE\",\n\t\"PERISCOP\",\n\t\"SHORBOM1\",\n\t\"SHORBOM2\",\n\t\"SOVBATL\",\n\t\"SOVTSTAR\",\n\t\"AFTRMATH\",\n\t\"SOVIET11\",\n\t\"MASASSLT\",\n\t\"ENGLISH\",\t\t// High res. Intro\n\t\"SOVIET1\",\n\t\"SOVIET2\",\n\t\"SOVIET3\",\n\t\"SOVIET4\",\n\t\"SOVIET5\",\n\t\"SOVIET6\",\n\t\"SOVIET7\",\n\t\"PROLOG\",\n\t\"AVERTED\",\n\t\"COUNTDWN\",\n\t\"MOVINGIN\",\n\t\"ALLY10\",\n\t\"ALLY12\",\n\t\"ALLY5\",\n\t\"ALLY6\",\n\t\"ALLY8\",\n\t\"TANYA1\",\n\t\"TANYA2\",\n\t\"ALLY10B\",\n\t\"ALLY11\",\n\t\"ALLY14\",\n\t\"ALLY9\",\n\t\"SPY\",\n\t\"TOOFAR\",\n\t\"SOVIET12\",\n\t\"SOVIET13\",\n\t\"SOVIET9\",\n\t\"BEACHEAD\",\n\t\"SOVIET14\",\n\t\"SIZZLE\",   //MISSING\n\t\"SIZZLE2\",  //MISSING\n\t\"ANTEND\",\n\t\"ANTINTRO\",\n\n\n\t\t//2019/11/12 JAS - Added for Retaliation movies\n\n\t\t\"RETALIATION_ALLIED1\",\n\t\t\"RETALIATION_ALLIED2\",\n\t\t\"RETALIATION_ALLIED3\",\n\t\t\"RETALIATION_ALLIED4\",\n\t\t\"RETALIATION_ALLIED5\",\n\t\t\"RETALIATION_ALLIED6\",\n\t\t\"RETALIATION_ALLIED7\",\n\t\t\"RETALIATION_ALLIED8\",\n\t\t\"RETALIATION_ALLIED9\",\n\t\t\"RETALIATION_ALLIED10\",\n\n\t\t\"RETALIATION_SOVIET1\",\n\t\t\"RETALIATION_SOVIET2\",\n\t\t\"RETALIATION_SOVIET3\",\n\t\t\"RETALIATION_SOVIET4\",\n\t\t\"RETALIATION_SOVIET5\",\n\t\t\"RETALIATION_SOVIET6\",\n\t\t\"RETALIATION_SOVIET7\",\n\t\t\"RETALIATION_SOVIET8\",\n\t\t\"RETALIATION_SOVIET9\",\n\t\t\"RETALIATION_SOVIET10\",\n\t\t\"RETALIATION_WINA\",\n\t\t\"RETALIATION_WINS\",\n\t\t\"RETALIATION_ANTS\"\n};\n\n\n/***************************************************************************\n**\tRelative coordinate offsets from the center of a cell for each\n**\tof the legal positions that an object in a cell may stop at. Only infantry\n**\tare allowed to stop at other than the center of the cell.\n*/\nCOORDINATE const StoppingCoordAbs[5] = {\n\t0x00800080L,\t// center\n\t0x00400040L,\t// upper left\n\t0x004000C0L,\t// upper right\n\t0x00C00040L,\t// lower left\n\t0x00C000C0L\t\t// lower right\n};\n\n\n/***************************************************************************\n**\tConverts pixel values (cell relative) into the appropriate lepton (sub cell)\n**\tvalue. This is used to convert pixel (screen) coordinates into the underlying\n**\tcoordinate system.\n*/\nunsigned char const Pixel2Lepton[24] = {\n\t0x00,0x0B,0x15,0x20,0x2B,0x35,0x40,0x4B,\n\t0x55,0x60,0x6B,0x75,0x80,0x8B,0x95,0xA0,\n\t0xAB,0xB5,0xC0,0xCB,0xD5,0xE0,0xEB,0xF5\n};\n\n\n/***************************************************************************\n**\tThis array is used to index a facing in order to retrieve a cell\n**\toffset that, when added to another cell, will achieve the adjacent cell\n**\tin the indexed direction.\n*/\nCELL const AdjacentCell[FACING_COUNT] = {\n\t-(MAP_CELL_W),\t\t\t\t// North\n\t-(MAP_CELL_W-1),\t\t\t// North East\n\t1,\t\t\t\t\t\t\t\t// East\n\tMAP_CELL_W+1,\t\t\t\t// South East\n\tMAP_CELL_W,\t\t\t\t\t// South\n\tMAP_CELL_W-1,\t\t\t\t// South West\n\t-1,\t\t\t\t\t\t\t// West\n\t-(MAP_CELL_W+1)\t\t\t// North West\n};\n\nCOORDINATE const AdjacentCoord[FACING_COUNT] = {\n\t0xFF000000L,\n\t0xFF000100L,\n\t0x00000100L,\n\t0x01000100L,\n\t0x01000000L,\n\t0x0100FF00L,\n\t0x0000FF00L,\n\t0xFF00FF00L\n};\n\n\n/***************************************************************************\n**\tThis specifies the odds of receiving the various random crate power\n**\tups. The odds are expressed as \"shares\" of 100 percent.\n*/\nint CrateShares[CRATE_COUNT] = {\n\t50,\t\t//\tCRATE_MONEY\n\t20,\t\t//\tCRATE_UNIT\n\t3,\t\t\t//\tCRATE_PARA_BOMB\n\t1,\t\t\t//\tCRATE_HEAL_BASE\n\t3,\t\t\t//\tCRATE_CLOAK\n\t5,\t\t\t//\tCRATE_EXPLOSION\n\t5,\t\t\t//\tCRATE_NAPALM\n\t20,\t\t//\tCRATE_SQUAD\n\t1,\t\t\t//\tCRATE_DARKNESS\n\t1,\t\t\t//\tCRATE_REVEAL\n\t3,\t\t\t//\tCRATE_SONAR\n\t10,\t\t//\tCRATE_ARMOR\n\t10,\t\t//\tCRATE_SPEED\n\t10,\t\t//\tCRATE_FIREPOWER\n\t1,\t\t\t//\tCRATE_ICBM\n\t1,\t\t\t//\tCRATE_TIMEQUAKE\n\t3,\t\t\t//\tCRATE_INVULN\n\t5\t\t\t// CRATE_VORTEX\n};\n\nAnimType CrateAnims[CRATE_COUNT] = {\n\tANIM_NONE,\t//\tCRATE_MONEY\n\tANIM_NONE,\t//\tCRATE_UNIT\n\tANIM_NONE,\t//\tCRATE_PARA_BOMB\n\tANIM_NONE,\t//\tCRATE_HEAL_BASE\n\tANIM_NONE,\t//\tCRATE_CLOAK\n\tANIM_NONE,\t//\tCRATE_EXPLOSION\n\tANIM_NONE,\t//\tCRATE_NAPALM\n\tANIM_NONE,\t//\tCRATE_SQUAD\n\tANIM_NONE,\t//\tCRATE_DARKNESS\n\tANIM_NONE,\t//\tCRATE_REVEAL\n\tANIM_NONE,\t//\tCRATE_SONAR\n\tANIM_NONE,\t//\tCRATE_ARMOR\n\tANIM_NONE,\t//\tCRATE_SPEED\n\tANIM_NONE,\t//\tCRATE_FIREPOWER\n\tANIM_NONE,\t//\tCRATE_ICBM\n\tANIM_NONE,\t//\tCRATE_TIMEQUAKE\n\tANIM_NONE,\t//\tCRATE_INVULN\n\tANIM_NONE   // CRATE_VORTEX\n};\n\nint CrateData[CRATE_COUNT] = {\n\t0,\t\t//\tCRATE_MONEY\n\t0,\t\t//\tCRATE_UNIT\n\t0,\t\t//\tCRATE_PARA_BOMB\n\t0,\t\t//\tCRATE_HEAL_BASE\n\t0,\t\t//\tCRATE_CLOAK\n\t0,\t\t//\tCRATE_EXPLOSION\n\t0,\t\t//\tCRATE_NAPALM\n\t0,\t\t//\tCRATE_SQUAD\n\t0,\t\t//\tCRATE_DARKNESS\n\t0,\t\t//\tCRATE_REVEAL\n\t0,\t\t//\tCRATE_SONAR\n\t0,\t\t//\tCRATE_ARMOR\n\t0,\t\t//\tCRATE_SPEED\n\t0,\t\t//\tCRATE_FIREPOWER\n\t0,\t\t//\tCRATE_ICBM\n\t0,\t\t//\tCRATE_TIMEQUAKE\n\t0,\t\t//\tCRATE_INVULN\n\t0\t\t//\tCRATE_VORTEX\n};\n\nchar const * const CrateNames[CRATE_COUNT] = {\n\t\"Money\",\n\t\"Unit\",\n\t\"ParaBomb\",\n\t\"HealBase\",\n\t\"Cloak\",\n\t\"Explosion\",\n\t\"Napalm\",\n\t\"Squad\",\n\t\"Darkness\",\n\t\"Reveal\",\n\t\"Sonar\",\n\t\"Armor\",\n\t\"Speed\",\n\t\"Firepower\",\n\t\"ICBM\",\n\t\"TimeQuake\",\n\t\"Invulnerability\",\n\t\"ChronalVortex\"\n};\n\n\n/***************************************************************************\n** This converts 0..255 facing values into either 8, 16, or 32 facing values.\n**\tNote: a simple shift won't suffice because 0..255 facing values should\n**\tbe converted to the CLOSEST appropriate facing, NOT rounded down to the\n**\tnearest facing.\n*/\nunsigned char const Facing8[256] = {\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\n\t3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n\t5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n};\n\n\nunsigned char const Facing16[256] = {\n\t0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,\n\t2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,\n\t4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,\n\t6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,\n\t8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,\n\t10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n\t12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,\n\t14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,0,0,0,0,0,0\n};\n\n\nsigned char const Rotation16[256] = {\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1\n};\n\n\n/*\n**\tThis table incorporates a compensating factor for the distortion caused\n**\tby 3D-Studio when it tries to render 45% angles.\n*/\nunsigned char const Facing32[256] = {\n\t0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,\n\t3,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,\n\t8,8,8,9,9,9,9,9,9,9,10,10,10,10,10,10,10,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,\n\t13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,\n\t16,16,16,16,16,17,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,\n\t19,20,20,20,20,20,20,21,21,21,21,21,21,21,22,22,22,22,22,22,22,23,23,23,23,23,23,23,24,24,24,24,\n\t24,24,24,25,25,25,25,25,25,25,26,26,26,26,26,26,26,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,\n\t29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,0,0,0,0,0,0\n};\n\n\n#ifdef OBSOLETE\nunsigned char const Facing32[256] = {\n\t0,0,0,0,\n\t1,1,1,1,1,1,1,1,\n\t2,2,2,2,2,2,2,2,\n\t3,3,3,3,3,3,3,3,\n\t4,4,4,4,4,4,4,4,\n\t5,5,5,5,5,5,5,5,\n\t6,6,6,6,6,6,6,6,\n\t7,7,7,7,7,7,7,7,\n\t8,8,8,8,8,8,8,8,\n\t9,9,9,9,9,9,9,9,\n\t10,10,10,10,10,10,10,10,\n\t11,11,11,11,11,11,11,11,\n\t12,12,12,12,12,12,12,12,\n\t13,13,13,13,13,13,13,13,\n\t14,14,14,14,14,14,14,14,\n\t15,15,15,15,15,15,15,15,\n\t16,16,16,16,16,16,16,16,\n\t17,17,17,17,17,17,17,17,\n\t18,18,18,18,18,18,18,18,\n\t19,19,19,19,19,19,19,19,\n\t20,20,20,20,20,20,20,20,\n\t21,21,21,21,21,21,21,21,\n\t22,22,22,22,22,22,22,22,\n\t23,23,23,23,23,23,23,23,\n\t24,24,24,24,24,24,24,24,\n\t25,25,25,25,25,25,25,25,\n\t26,26,26,26,26,26,26,26,\n\t27,27,27,27,27,27,27,27,\n\t28,28,28,28,28,28,28,28,\n\t29,29,29,29,29,29,29,29,\n\t30,30,30,30,30,30,30,30,\n\t31,31,31,31,31,31,31,31,\n\t0,0,0,0\n};\n#endif\n\n\n/***************************************************************************\n**\tThese are the movement costs (in ticks at fastest speed) to enter each\n**\tof the given terrain cells.\n*/\n\nint const GroundColor[LAND_COUNT] = {\n\t141,\t\t\t// \"Clear\" terrain.\n\t141,\t\t\t// Road terrain.\n\t172,\t\t\t// Water.\n\t21,\t\t\t// Impassable rock.\n\t21,\t\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t141,\t\t\t//\tBeach terrain.\n\t141,\t\t\t// Rocky terrain.\n\t174\t\t\t// Rocky riverbed.\n};\n\nint const SnowColor[LAND_COUNT] = {\n\t141,\t\t\t// \"Clear\" terrain.\n\t141,\t\t\t// Road terrain.\n\t172,\t\t\t// Water.\n\t21,\t\t\t// Impassable rock.\n\t21,\t\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t141,\t\t\t//\tBeach terrain.\n\t141,\t\t\t// Rocky terrain.\n\t174\t\t\t// Rocky riverbed.\n};\n\n#ifdef NEVER\nint const GroundColor[LAND_COUNT] = {\n\t46,\t\t\t// \"Clear\" terrain.\n\t44,\t\t\t// Road terrain.\n\tBLUE,\t\t\t// Water.\n\tDKGREY,\t\t// Impassable rock.\n\tDKGREY,\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\t64,\t\t\t//\tBeach terrain.\n\tDKGREY,\t\t// Rocky terrain.\n\tDKGREY\t\t// Rocky riverbed.\n};\n\nint const SnowColor[LAND_COUNT] = {\n\tWHITE, \t\t// \"Clear\" terrain.\n\tLTGRAY,\t\t// Road terrain.\n\tBLUE,\t\t\t// Water.\n\tDKGREY,\t\t// Impassable rock.\n\tDKGREY,\t\t// Wall (blocks movement).\n\t158,\t\t\t// Tiberium field.\n\tLTGRAY,\t\t//\tBeach terrain.\n\tDKGREY,\t\t// Rocky terrain.\n\tDKGREY\t\t// Rocky riverbed.\n};\n#endif\n\nGroundType Ground[LAND_COUNT];\n\n\n/***************************************************************************\n**\tThese are the names of the theaters.\n*/\nTheaterDataType const Theaters[THEATER_COUNT] = {\n\t{\"TEMPERATE\",\"TEMPERAT\",\"TEM\"},\n\t{\"SNOW\",\"SNOW\",\"SNO\"},\n\t{\"INTERIOR\",\"INTERIOR\",\"INT\"},\n};\n\n\nunsigned char const RemapCiv2[256] = {\n\t0,1,2,3,4,5,6,209,8,9,10,11,12,13,12,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,187,188,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,209,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,167, 13,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv4[256] = {\n\t0,1,2,3,4,5,6,187,8,9,10,11,12,13,14,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,118,110,119,\t\t// 96..111\n\t112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,188,207,\t// 192..207\n\t208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv5[256] = {\n\t0,1,2,3,4,5,6,109,8,9,10,11,131,13,14,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,177,110,178,\t\t// 96..111\n\t112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,111,201,202,203,204,205,111,207,\t// 192..207\n\t208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv6[256] = {\n\t0,1,2,3,4,5,6,120,8,9,10,11,12,13,238,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,236,206,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,111,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv7[256] = {\n\t0,1,2,3,4,5,6,7,8,9,10,11,12,13,131,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,157,212,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,7,\t\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,118,119,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv8[256] = {\n\t0,1,2,3,4,5,6,182,8,9,10,11,12,13,131,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,215,7,120,121,122,123,124,125,126,127,\t\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,182,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,198,199,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,111,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv9[256] = {\n\t0,1,2,3,4,5,6,7,8,9,10,11,12,13,7,15,\t\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,163,165,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,200,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,111,13,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapCiv10[256] = {\n\t0,1,2,3,4,5,6,137,8,9,10,11,12,13,15,15,\t\t\t\t\t\t\t\t\t// 0..15\n\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\t\t\t\t\t\t// 16..31\n\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\t\t\t\t\t\t// 32..47\n\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\t\t\t\t\t\t// 48..63\n\t64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,\t\t\t\t\t\t// 64..79\n\t80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,\t\t\t\t\t\t// 80..95\n\t96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,\t\t// 96..111\n\t112,113,114,115,116,117,129,131,120,121,122,123,124,125,126,127,\t// 112..127\n\t128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\t// 128..143\n\t144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,137,\t// 144..159\n\t160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,\t// 160..175\n\t176,177,178,179,180,181,182,183,184,185,186,163,165,189,190,191,\t// 176..191\n\t192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,\t// 192..207\n\t208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,\t// 208..223\n\t224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,\t// 224..239\n\t240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\t// 240..255\n};\n\nunsigned char const RemapEmber[256] = {\n#define\tCEC\tCC_EMBER_COLOR\n\t  0,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,BLACK,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,\n\tCEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC,CEC\n};\n\n\n//char const Keys[] =\n//\t\"[PublicKey]\\n\"\n//\t\"1=AgkCbXo9sKMHOBk=\\n\"\n//#ifdef CHEAT_KEYS\n//\t\"[PrivateKey]\\n\"\n//\t\"1=AggxFU55vc7LYQ==\\n\"\n//#endif\n//\t\"\\n\";\n\nchar const Keys[] =\n\"[PublicKey]\\n\"\n\"1=AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V\\n\"\n#ifdef CHEAT_KEYS\n\"[PrivateKey]\\n\"\n\"1=AigKVje8mROcR8QixnxUEF5b29Curkq01DNDWCdOG99XBqH79OaCiTCB\\n\"\n#endif\n\"\\n\";\n"
  },
  {
    "path": "REDALERT/CONTROL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONTROL.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONTROL.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : December 5, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ControlClass::Action -- Normal action for control gadget objects.                         *\n *   ControlClass::ControlClass -- Constructor for control class objects.                      *\n *   ControlClass::ControlClass -- Copy constructor for control gadget.                        *\n *   ControlClass::Draw_Me -- Draw logic for the control class object.                         *\n *   ControlClass::Get_ID -- Gets the ID number for this gadget.                               *\n *   ControlClass::Make_Peer -- Assigns a peer gadget to this gadget.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * ControlClass::ControlClass -- Constructor for control class objects.                        *\n *                                                                                             *\n *    This is the normal constructor for control class objects. At this level, it only needs   *\n *    to record the ID number assigned to this button.                                         *\n *                                                                                             *\n * INPUT:   id    -- The ID number for this gadget. If the ID number specified is 0, then      *\n *                   this tells the system that no special ID code should be returned.         *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of upper left corner of gadget's region.                 *\n *                                                                                             *\n *          w,h   -- Pixel dimensions of the gadget's region.                                  *\n *                                                                                             *\n *          flags -- The input event flags that this gadget recognizes.                        *\n *                                                                                             *\n *          sticky-- This this a \"sticky\" gadget? A sticky gadget is one that takes over the   *\n *                   gadget list while the mouse button is held down, if the mouse button was  *\n *                   initially clicked over its region. This is the behavior of \"normal\"       *\n *                   buttons in Windows.                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass::ControlClass(unsigned id, int x, int y, int w, int h, unsigned flags, int sticky) :\n\tGadgetClass(x, y, w, h, flags, sticky),\n\tID(id),\n\tPeer(0)\n{\n}\n\n\n/***********************************************************************************************\n * ControlClass::ControlClass -- Copy constructor for control gadget.                          *\n *                                                                                             *\n *    This copy constructor for a control gadget is used create a duplicate gadget that        *\n *    is functionally similar.                                                                 *\n *                                                                                             *\n * INPUT:   control  -- Reference to the gadget that is to be copied.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass::ControlClass(ControlClass const & control) :\n\tGadgetClass(control),\n\tID(control.ID),\n\tPeer(control.Peer)\n{\n}\n\n/***********************************************************************************************\n * ControlClass::Action -- Normal action for control gadget objects.                           *\n *                                                                                             *\n *    This function gets called when the input event that this control gadget is looking for   *\n *    occurs. In such a case, the return key code value is changed to the gadget's ID number   *\n *    with the special button bit flag attached.                                               *\n *                                                                                             *\n * INPUT:   flags -- The event that triggered this function call. If this value is NULL, then  *\n *                   this is a forced (probably due to the sticky flag) call and the key code  *\n *                   is not altered.                                                           *\n *                                                                                             *\n *          key   -- Reference to the key code that will be returned by the controlling        *\n *                   Input() function.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Should further list processing be aborted?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ControlClass::Action(unsigned flags, KeyNumType & key)\n{\n\n\t/*\n\t**\tOnly if the flags indicate that a recognized action has occurred, do the\n\t**\tnormal processing of this gadget and set return value to the gadget ID.\n\t*/\n\tif (flags) {\n\t\tif (ID) {\n\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t} else {\n\t\t\tkey = KN_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a peer link established, inform that gadget of this\n\t**\taction call.\n\t*/\n\tif (Peer) {\n\t\tPeer->Peer_To_Peer(flags, key, *this);\n\t}\n\n\treturn(GadgetClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * ControlClass::Make_Peer -- Assigns a peer gadget to this gadget.                            *\n *                                                                                             *\n *    This function will assign another gadget to this one. That other gadget will receive     *\n *    notification of any Action() call to this gadget. Presumably, this is how one gadget     *\n *    can automatically adapt to changes in another. Say for example, a slider bar can affect  *\n *    the list box it is attached to.                                                          *\n *                                                                                             *\n * INPUT:   gadget   -- The gadget to inform when any Action() function is called.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ControlClass::Make_Peer(GadgetClass & gadget)\n{\n\tPeer = &gadget;\n}\n\n\n/***********************************************************************************************\n * ControlClass::Get_ID -- Gets the ID number for this gadget.                                 *\n *                                                                                             *\n *    This function will query and return with the ID number for this gadget. It is primarily  *\n *    used by the Extract_Gadget() function.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the ID number for this gadget. If zero is returned, this means that   *\n *          no ID was assigned to this gadget. This is a special case since a zero value will  *\n *          never be returned as a pseudo-key as is done with non-zero values.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned ControlClass::Get_ID(void) const\n{\n\treturn(ID);\n}\n\n\n/***********************************************************************************************\n * ControlClass::Draw_Me -- Draw logic for the control class object.                           *\n *                                                                                             *\n *    This is called when the control object might need to be redrawn or when redrawing is     *\n *    necessary. Since at this level of the class hierarchy, no actual drawing occurs, this    *\n *    routine doesn't perform any rendering. It does, however, inform any peer attached        *\n *    object that a Draw_Me function has been called. Presumably, the attached peer gadget     *\n *    might very well need to be redrawn as a result of some action by this gadget. Since this *\n *    gadget might, more than likely, be of the \"sticky\" variety, a normal call to Draw_Me     *\n *    for the other gadget will not occur. It must rely on the call by this routine in order   *\n *    to update correctly. A typical example of this would be a slider that is attached to     *\n *    a list box. As the slider is being drug around, the attached list box must be redrawn.   *\n *                                                                                             *\n * INPUT:   forced   -- Should the redraw be forced regardless of the redraw flag?             *\n *                                                                                             *\n * OUTPUT:  bool; Was the gadget redrawn?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ControlClass::Draw_Me(int forced)\n{\n\tif (Peer) {\n\t\tPeer->Draw_Me();\n\t}\n\treturn(GadgetClass::Draw_Me(forced));\n}\n"
  },
  {
    "path": "REDALERT/CONTROL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CONTROL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CONTROL.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CONTROL_H\n#define CONTROL_H\n\n#include\t\"gadget.h\"\n\n/***************************************************************************\n * ControlClass -- Region tracking class\t\t\t\t\t\t\t\t\t         *\n *                                                                         *\n * INPUT:      int x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tUWORD flags -- see enumeration choices\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     0 = new scenario created, -1 = not\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\tThis class is Abstract (cannot make an instance of it)      *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/03/1995 MML : Created.                                             *\n *=========================================================================*/\nclass ControlClass : public GadgetClass\n{\n\tpublic:\n\t\tControlClass(NoInitClass const & x) : GadgetClass(x) {};\n\t\tControlClass(unsigned id, int x, int y, int w, int h, unsigned flags=LEFTPRESS|RIGHTPRESS, int sticky=false);\n\t\tControlClass(ControlClass const & control);\n\n\t\tvirtual void Make_Peer(GadgetClass & gadget);\n\n\t\t/*\n\t\t**\tRender support function.\n\t\t*/\n\t\tvirtual int Draw_Me(int forced=false);\n\n\t\t/*\n\t\t**\tThis is the ID number for this control gadget. This number is used to generate\n\t\t**\ta special pseudo-key when the gadget detects valid input.\n\t\t*/\n\t\tunsigned ID;\n\n\tprotected:\n\t\tvirtual unsigned Get_ID(void) const;\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\t\t/*\n\t\t**\tThis points to the peer button to inform when something happens to this\n\t\t**\tgadget.\n\t\t*/\n\t\tGadgetClass * Peer;\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/COORD.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/COORD.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : COORD.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 22, 1996 [JLB]                                          *\n *                                                                                             *\n * Support code to handle the coordinate system is located in this module.                     *\n * Routines here will be called QUITE frequently during play and must be                       *\n * as efficient as possible.                                                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                 *\n *   Coord_Cell -- Convert a coordinate into a cell number.                                    *\n *   Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance         *\n *   Coord_Scatter -- Determines a random coordinate from an anchor point.                     *\n *   Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified.       *\n *   Coord_Spillage_List -- Determines the offset list for cell spillage/occupation.           *\n *   Distance -- Determines the cell distance between two cells.                               *\n *   Distance -- Determines the lepton distance between two coordinates.                       *\n *   Distance -- Fetch distance between two target values.                                     *\n *   Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                *\n *   Normal_Move_Point -- Moves point with tilt compensation.                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * Coord_Cell -- Convert a coordinate into a cell number.                                      *\n *                                                                                             *\n *    This routine will convert the specified coordinate value into a cell number. This is     *\n *    useful to determine the map index number into the cell array that corresponds to a       *\n *    particular coordinate.                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to convert into a cell number.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number that corresponds to the coordinate specified.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL Coord_Cell(COORDINATE coord)\n{\n\tCELL_COMPOSITE cell;\n\tcell.Cell = 0;\n\tcell.Sub.X = ((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell;\n\tcell.Sub.Y = ((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell;\n\treturn(cell.Cell);\n//\treturn(XY_Cell(((COORD_COMPOSITE)coord).Sub.X, ((COORD_COMPOSITE)composite).Sub.Y));\n}\n\n\n/***********************************************************************************************\n * Distance -- Fetch distance between two target values.                                       *\n *                                                                                             *\n *    This routine will determine the lepton distance between the two specified target         *\n *    values.                                                                                  *\n *                                                                                             *\n * INPUT:   target1  -- First target value.                                                    *\n *                                                                                             *\n *          target2  -- Second target value.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton distance between the two target values.                    *\n *                                                                                             *\n * WARNINGS:   Be sure that the targets are legal before calling this routine. Otherwise, the  *\n *             return value is meaningless.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Distance(TARGET target1, TARGET target2)\n{\n\treturn(Distance(As_Coord(target1), As_Coord(target2)));\n}\n\n\n/***********************************************************************************************\n * Distance -- Determines the lepton distance between two coordinates.                         *\n *                                                                                             *\n *    This routine is used to determine the distance between two coordinates. It uses the      *\n *    Dragon Strike method of distance determination and thus it is very fast.                 *\n *                                                                                             *\n * INPUT:   coord1   -- First coordinate.                                                      *\n *                                                                                             *\n *          coord2   -- Second coordinate.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns the lepton distance between the two coordinates.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Distance(COORDINATE coord1, COORDINATE coord2)\n{\n\tint\tdiff1, diff2;\n\n\tdiff1 = Coord_Y(coord1) - Coord_Y(coord2);\n\tif (diff1 < 0) diff1 = -diff1;\n\tdiff2 = Coord_X(coord1) - Coord_X(coord2);\n\tif (diff2 < 0) diff2 = -diff2;\n\tif (diff1 > diff2) {\n\t\treturn(diff1 + ((unsigned)diff2 / 2));\n\t}\n\treturn(diff2 + ((unsigned)diff1 / 2));\n}\n\n\n/***********************************************************************************************\n * Coord_Spillage_List -- Determines the offset list for cell spillage/occupation.             *\n *                                                                                             *\n *    This routine will take an arbitrary position and object size and return with a list of   *\n *    cell offsets from the current cell for all cells that are overlapped by the object. The  *\n *    first cell offset is always zero, so to just get the adjacent spill cell list, add one   *\n *    to the return pointer.                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine.                                                *\n *                                                                                             *\n *          maxsize -- The maximum width/height of the object (pixels).                        *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a spillage list.                                         *\n *                                                                                             *\n * WARNINGS:   The algorithm is limited to working with a maxsize of 48 or less. Larger values *\n *             will generate an incomplete overlap list.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/06/1993 JLB : Created.                                                                 *\n *   03/25/1994 JLB : Added width optimization.                                                *\n *   04/29/1994 JLB : Converted to C.                                                          *\n *   06/03/1994 JLB : Converted to general purpose spillage functionality.                     *\n *   01/07/1995 JLB : Manually calculates spillage list for large objects.                     *\n *=============================================================================================*/\nshort const * Coord_Spillage_List(COORDINATE coord, int maxsize)\n{\n\tstatic short const _MoveSpillage[(int)FACING_COUNT+1][5] = {\n\t\t{0, -MAP_CELL_W, REFRESH_EOL, 0, 0},\t\t\t\t\t\t// N\n\t\t{0, -MAP_CELL_W, 1, -(MAP_CELL_W-1), REFRESH_EOL},\t\t// NE\n\t\t{0, 1, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t\t\t\t// E\n\t\t{0, 1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL},\t\t\t// SE\n\t\t{0, MAP_CELL_W, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t// S\n\t\t{0, -1, MAP_CELL_W, MAP_CELL_W-1, REFRESH_EOL},\t\t\t// SW\n\t\t{0, -1, REFRESH_EOL, 0, 0},\t\t\t\t\t\t\t\t\t// W\n\t\t{0, -1, -MAP_CELL_W, -(MAP_CELL_W+1), REFRESH_EOL},\t// NW\n\t\t{0, REFRESH_EOL, 0, 0, 0}\t\t\t\t\t\t\t\t\t\t// non-moving.\n\t};\n\tstatic short _manual[10];\n//;\t00 = on axis\n//;\t01 = below axis\n//;\t10 = above axis\n//;\t11 = undefined\n\tstatic signed char const _SpillTable[16]\t= {8,6,2,-1,0,7,1,-1,4,5,3,-1,-1,-1,-1,-1};\n\tint\tindex=0;\n\tint\tx,y;\n\n\t/*\n\t**\tFor mondo-enourmo-gigundo objects, use a prebuilt mammoth table\n\t**\tthat covers a 5x5 square region.\n\t*/\n\tif (maxsize > ICON_PIXEL_W * 2) {\n\t\tstatic short const _gigundo[] = {\n\t\t\t-((2*MAP_CELL_W)-2),-((2*MAP_CELL_W)-1),-((2*MAP_CELL_W)),-((2*MAP_CELL_W)+1),-((2*MAP_CELL_W)+2),\n\t\t\t-((1*MAP_CELL_W)-2),-((1*MAP_CELL_W)-1),-((1*MAP_CELL_W)),-((1*MAP_CELL_W)+1),-((1*MAP_CELL_W)+2),\n\t\t\t-((0*MAP_CELL_W)-2),-((0*MAP_CELL_W)-1),-((0*MAP_CELL_W)),-((0*MAP_CELL_W)+1),-((0*MAP_CELL_W)+2),\n\t\t\t((1*MAP_CELL_W)-2),((1*MAP_CELL_W)-1),((1*MAP_CELL_W)),((1*MAP_CELL_W)+1),((1*MAP_CELL_W)+2),\n\t\t\t+((2*MAP_CELL_W)-2),+((2*MAP_CELL_W)-1),+((2*MAP_CELL_W)),+((2*MAP_CELL_W)+1),+((2*MAP_CELL_W)+2),\n\t\t\tREFRESH_EOL\n\t\t};\n\t\treturn(&_gigundo[0]);\n\t}\n\n\t/*\n\t**\tFor very large objects, build the overlap list by hand. This is time consuming, but\n\t**\tnot nearly as time consuming as drawing even a single cell unnecessarily.\n\t*/\n\tif (maxsize > ICON_PIXEL_W) {\n\t\tmaxsize = min(maxsize, (ICON_PIXEL_W*2))/2;\n\n\t\tx = (ICON_PIXEL_W * Coord_XLepton(coord)) / ICON_LEPTON_W;\n\t\ty = (ICON_PIXEL_H * Coord_YLepton(coord)) / ICON_LEPTON_H;\n\t\tint left = x-maxsize;\n\t\tint right = x+maxsize;\n\t\tint top = y-maxsize;\n\t\tint bottom = y+maxsize;\n\n\t\t_manual[index++] = 0;\n\t\tif (left < 0) _manual[index++] = -1;\n\t\tif (right >= ICON_PIXEL_W) _manual[index++] = 1;\n\t\tif (top < 0) _manual[index++] = -MAP_CELL_W;\n\t\tif (bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W;\n\t\tif (left < 0 && top < 0) _manual[index++] = -(MAP_CELL_W+1);\n\t\tif (right >= ICON_PIXEL_W && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W+1;\n\t\tif (left < 0 && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W-1;\n\t\tif (right >= ICON_PIXEL_H && top < 0) _manual[index++] = -(MAP_CELL_W-1);\n\t\t_manual[index] = REFRESH_EOL;\n\t\treturn(&_manual[0]);\n\t}\n\n\t/*\n\t**\tDetermine the number of leptons \"leeway\" allowed this unit.\n\t*/\n\tint posval = Pixel2Lepton[(ICON_PIXEL_W-maxsize)/2];\n\n\tx = Coord_XLepton(coord) - 0x0080;\n\ty = Coord_YLepton(coord) - 0x0080;\n\tif (y > posval) index |= 0x08;\t\t\t// Spilling South.\n\tif (y < -posval) index |= 0x04;\t\t\t// Spilling North.\n\tif (x > posval) index |= 0x02;\t\t\t// Spilling East.\n\tif (x < -posval) index |= 0x01;\t\t\t// Spilling West.\n\n\treturn(&_MoveSpillage[_SpillTable[index]][0]);\n}\n\n\n/***********************************************************************************************\n * Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified.         *\n *                                                                                             *\n *    Given a center coordinate and a dirty rectangle, calcuate a cell offset list for         *\n *    determining such things as overlap and redraw logic. Optionally, the center cell         *\n *    location will not be part of the list.                                                   *\n *                                                                                             *\n * INPUT:   coord -- The center coordinate that the dirty rectangle is based off of.           *\n *                                                                                             *\n *          rect  -- Reference to the dirty rectangle.                                         *\n *                                                                                             *\n *          nocenter -- If true, then the center cell offset will not be part of the spillage  *\n *                      list returned. This is handy when the center cell is known to be       *\n *                      processed by some other method and it can be safely and efficiently    *\n *                      ignored by the list generated.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the spillage list that corresponds to the data           *\n *          specified. This is a pointer to a static buffer and as such it will only be valid  *\n *          until the next time that this routine is called.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * Coord_Spillage_List(COORDINATE coord, Rect const & rect, bool nocenter)\n{\n\tif (!rect.Is_Valid()) {\n\t\tstatic short const _list[] = {REFRESH_EOL};\n\t\treturn(_list);\n\t}\n\n\tCELL coordcell = Coord_Cell(coord);\n\tLEPTON x = Coord_X(coord);\n\tLEPTON y = Coord_Y(coord);\n\n\t/*\n\t**\tAdd the rectangle values to the coordinate in order to normalize the start and end\n\t**\tcorners of the rectangle. The values are now absolute to the real game world rather\n\t**\tthan relative to the coordinate.\n\t*/\n\tLEPTON_COMPOSITE startx;\n\tLEPTON_COMPOSITE starty;\n\tLEPTON_COMPOSITE endx;\n\tLEPTON_COMPOSITE endy;\n\tstartx.Raw = (int)x + (short)Pixel_To_Lepton(rect.X);\n\tstarty.Raw = (int)y + (short)Pixel_To_Lepton(rect.Y);\n\tendx.Raw = startx.Raw + Pixel_To_Lepton(rect.Width-1);\n\tendy.Raw = starty.Raw + Pixel_To_Lepton(rect.Height-1);\n\n\t/*\n\t**\tDetermine the upper left and lower right cell indexes. This is a simple conversion from\n\t**\ttheir lepton counterpart. These cells values are used to form the bounding box for the\n\t**\tmap offset list.\n\t*/\n\tint cellx = startx.Sub.Cell;\n\tint cellx2 = endx.Sub.Cell;\n\tint celly = starty.Sub.Cell;\n\tint celly2 = endy.Sub.Cell;\n\n\t/*\n\t**\tGenerate the spillage list by counting off the rows and colums of the cells\n\t**\tthat are affected. This is easy since the upper left and lower right corner cells\n\t**\tare known.\n\t*/\n\tint count = 0;\n\tstatic short _spillagelist[128];\n\tshort * ptr = _spillagelist;\n\tfor (int yy = celly; yy <= celly2; yy++) {\n\t\tfor (int xx = cellx; xx <= cellx2; xx++) {\n\t\t\tshort offset = (XY_Cell(xx, yy) - coordcell);\n\t\t\tif (!nocenter || offset != 0) {\n\t\t\t\t*ptr++ = offset;\n\t\t\t\tcount++;\n\t\t\t\tif (count+2 >= ARRAY_SIZE(_spillagelist)) break;\n\t\t\t}\n\t\t}\n\t\tif (count+2 >= ARRAY_SIZE(_spillagelist)) break;\n\t}\n\n\t/*\n\t**\tCap the list with the end of list marker and then return a pointer\n\t**\tto the completed list.\n\t*/\n\t*ptr = REFRESH_EOL;\n\treturn(_spillagelist);\n}\n\n\n/***********************************************************************************************\n * Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance           *\n *                                                                                             *\n *    This function will move a coordinate in a using SIN and COS arithmetic.                  *\n *                                                                                             *\n * INPUT:   start    -- The starting coordinate.                                               *\n *                                                                                             *\n *          dir      -- The direction to move the coordinate.                                  *\n *                                                                                             *\n *          distance -- The distance to move the coordinate position (in leptons).             *\n *                                                                                             *\n * OUTPUT:  Returns the new coordinate position.                                               *\n *                                                                                             *\n * WARNINGS:   This routine uses multiplies -- use with caution.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE Coord_Move(COORDINATE start, register DirType dir, unsigned short distance)\n{\n#ifdef NEVER\n\tshort x = Coord_X(start);\n\tshort y = Coord_Y(start);\n\n\tMove_Point(x, y, dir, distance);\n\treturn(XY_Coord(x,y));\n#endif\n\n\tMove_Point(*(short *)&start, *(((short *)&start)+1), dir, distance);\n\treturn(start);\n}\n\n\n/***********************************************************************************************\n * Coord_Scatter -- Determines a random coordinate from an anchor point.                       *\n *                                                                                             *\n *    This routine will perform a scatter algorithm on the specified                           *\n *    anchor point in order to return with another coordinate that is                          *\n *    randomly nearby the original. Typical use of this would be for                           *\n *    missile targeting.                                                                       *\n *                                                                                             *\n * INPUT:   coord    -- This is the anchor coordinate.                                         *\n *                                                                                             *\n *          distance -- This is the distance in pixels that the scatter                        *\n *                      should fall within.                                                    *\n *                                                                                             *\n *          lock     -- bool; Convert the new coordinate into a center                         *\n *                      cell based coordinate?                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a new coordinate that is nearby the original.                         *\n *                                                                                             *\n * WARNINGS:   Maximum pixel scatter distance is 255.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/01/1992 JLB : Created.                                                                 *\n *   05/13/1992 JLB : Only uses Random().                                                      *\n *=============================================================================================*/\nCOORDINATE Coord_Scatter(COORDINATE coord, unsigned distance, bool lock)\n{\n\tCOORDINATE\tnewcoord;\n\n\tnewcoord = Coord_Move(coord, Random_Pick(DIR_N, DIR_MAX), distance);\n\n\tif (newcoord & HIGH_COORD_MASK) newcoord = coord;\n\n\tif (lock) {\n\t\tnewcoord = Coord_Snap(newcoord);\n\t}\n\n\treturn(newcoord);\n}\n\n\nint __cdecl calcx(signed short param1, short distance)\n{\n\t__asm {\n\n\t\t//#pragma aux calcx parm [ax] [bx] \\\n\t\t\t\n\t\tmovzx\teax, [param1]\n\t\tmov\tbx, [distance]\n\t\timul \tbx\n\t\tshl\tax, 1\n\t\trcl\tdx, 1\n\t\tmov\tal, ah\n\t\tmov\tah, dl\n\t\tcwd\n\t}\n}\n\n\nint __cdecl calcy(signed short param1, short distance)\n{\n\t__asm {\n\n\t\t//#pragma aux calcy parm [ax] [bx] \\\n\t\t\t\n\t\tmovzx\teax, [param1]\n\t\tmov\tbx, [distance]\n\t\timul bx\n\t\tshl\tax, 1\n\t\trcl\tdx, 1\n\t\tmov\tal, ah\n\t\tmov\tah, dl\n\t\tcwd\n\t\tneg\teax\n\t}\n}\n\n\n#if (0)\nextern int calcx(signed short, short distance);\n#pragma aux calcx parm [ax] [bx] \\\n\tmodify [eax dx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"imul bx\"\t\t\t\t\t\t\\\n\t\"shl\tax,1\"\t\t\t\t\t\t\\\n\t\"rcl\tdx,1\"\t\t\t\t\t\t\\\n\t\"mov\tal,ah\"\t\t\t\t\t\\\n\t\"mov\tah,dl\"\t\t\t\t\t\\\n\t\"cwd\"\t\t\t\t\t\t\t\t\\\n//\t\"and\teax,0FFFFh\";\n\nextern int calcy(signed short, short distance);\n#pragma aux calcy parm [ax] [bx] \\\n\tmodify [eax dx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"imul bx\"\t\t\t\t\t\t\\\n\t\"shl\tax,1\"\t\t\t\t\t\t\\\n\t\"rcl\tdx,1\"\t\t\t\t\t\t\\\n\t\"mov\tal,ah\"\t\t\t\t\t\\\n\t\"mov\tah,dl\"\t\t\t\t\t\\\n\t\"cwd\"\t\t\t\t\t\t\t\t\\\n\t\"neg\teax\";\n//\t\"and\teax,0FFFFh\"\t\t\t\t\\\n\n#endif\n\nvoid Move_Point(short &x, short &y, register DirType dir, unsigned short distance)\n{\n\tstatic unsigned char const CosTable[256] = {\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\t};\n\n\tstatic unsigned char const SinTable[256] = {\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\t};\n\tdistance = distance;\t\t// Keep LINT quiet.\n\n#ifdef OBSOLETE\n\t/*\n\t**\tCalculate and add in the X component of the move.\n\t*/\n\t_AX = CosTable[dir];\n\tasm imul word ptr distance\n\tasm shl ax,1\n\tasm rcl dx,1\n\tasm mov al,ah\n\tasm mov ah,dl\n\t_DX = _AX;\n\tx += _DX;\n#else\n\t//\n\t// Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed.\n\t//\n\tstatic const char *_cos_table = (char*)&CosTable[0];\n\tx += calcx(_cos_table[dir], distance);\n#endif\n//\tasm add [word ptr start],ax\n\n#ifdef OBSOLETE\n\t/*\n\t**\tCalculate and add in the Y component of the move.\n\t*/\n\t_AX = SinTable[dir];\n\tasm imul word ptr distance\n\tasm shl ax,1\n\tasm rcl dx,1\n\tasm mov al,ah\n\tasm mov ah,dl\n\tasm neg ax\t\t\t\t// Subtraction needed because of inverted sine table.\n\t_DX = _AX;\n\ty += _DX;\n#else\n\t//\n\t// Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed.\n\t//\n\tstatic const char *_sin_table = (char*)&SinTable[0];\n\ty += calcy(_sin_table[dir], distance);\n#endif\n//\tasm add [word ptr start+2],ax\n\n}\n\n\n/***********************************************************************************************\n * Normal_Move_Point -- Moves point with tilt compensation.                                    *\n *                                                                                             *\n *    This routine will move the point in the direction and distance specified but it will     *\n *    take into account the tilt of the playing field. Typical use of this routine is to       *\n *    determine positioning as it relates to the playfield. Turrets are a good example of      *\n *    this.                                                                                    *\n *                                                                                             *\n * INPUT:   x,y   -- References to the coordinates to adjust.                                  *\n *                                                                                             *\n *          dir   -- The direction of the desired movement.                                    *\n *                                                                                             *\n *          distance -- The distance (in coordinate units) to move the point.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n// Loss of precision in initializations (8 bits to 7 bits) warning. Hmmm.. can this be fixed?\n//lint -e569\nvoid Normal_Move_Point(short &x, short &y, register DirType dir, unsigned short distance)\n{\n\tstatic unsigned char const CosTable[256] = {\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\t};\n\n\tstatic unsigned char const SinTable[256] = {\n\t\t0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d,\n\t\t0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76,\n\t\t0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b,\n\t\t0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b,\n\t\t0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49,\n\t\t0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,\n\t\t0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b,\n\t\t0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03,\n\n\t\t0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb,\n\t\t0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3,\n\t\t0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd,\n\t\t0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9,\n\t\t0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99,\n\t\t0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c,\n\t\t0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85,\n\t\t0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82,\n\n\t\t0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83,\n\t\t0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a,\n\t\t0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95,\n\t\t0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5,\n\t\t0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,\n\t\t0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd,\n\t\t0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5,\n\t\t0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd,\n\n\t\t0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15,\n\t\t0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d,\n\t\t0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43,\n\t\t0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57,\n\t\t0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67,\n\t\t0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74,\n\t\t0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b,\n\t\t0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,\n\t};\n\tdistance = distance;\t\t// Keep LINT quiet.\n\n\t//\n\t// Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed.\n\t//\n\tstatic const char *_sin_table = (char*)&SinTable[0];\n\tstatic const char *_cos_table = (char*)&CosTable[0];\n\n\tx += calcx(_cos_table[dir], distance);\n\n\ty += calcy(_sin_table[dir] / 2, distance);\n}\n"
  },
  {
    "path": "REDALERT/COORDA.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : COORDA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Barry W. Green                           *\n;*                                                                         *\n;*                   Start Date : February 17, 1995                        *\n;*                                                                         *\n;*                  Last Update : February 17, 1995  [BWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nglobal C\tCardinal_To_Fixed\t:NEAR\nglobal C\tFixed_To_Cardinal\t:NEAR\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                   *\n;*                                                                                             *\n;*    This utility function will convert cardinal numbers into a fixed point fraction. The     *\n;*    use of fixed point numbers occurs throughout the product -- since it is a convenient     *\n;*    tool. The fixed point number is based on the formula:                                    *\n;*                                                                                             *\n;*       result = cardinal / base                                                              *\n;*                                                                                             *\n;*    The accuracy of the fixed point number is limited to 1/65536 as the lowest and up to     *\n;*    65536 as the largest.                                                                    *\n;*                                                                                             *\n;* INPUT:   base     -- The key number to base the fraction about.                             *\n;*                                                                                             *\n;*          cardinal -- The other number (hey -- what do you call it?)                         *\n;*                                                                                             *\n;* OUTPUT:  Returns with the fixed point number of the \"cardinal\" parameter as it relates      *\n;*          to the \"base\" parameter.                                                           *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n;unsigned int Cardinal_To_Fixed(unsigned base, unsigned cardinal);\n\n\tPROC\tCardinal_To_Fixed C near\n\tUSES\tebx, edx\n\n\tARG\tbase:DWORD\n\tARG\tcardinal:DWORD\n\n\tmov\teax,0FFFFFFFFh\t\t; establish default return value\n\n\tmov\tebx,[base]\n\tor\tebx,ebx\n\tjz\tnear ??retneg1\t\t; if base==0, return 4294967295\n\n\tmov\teax,[cardinal]\t\t; otherwise, return (cardinal*65536)/base\n\tshl\teax,16\n\txor\tedx,edx\n\tdiv\tebx\n\n??retneg1:\n\tret\n\n\tENDP\tCardinal_To_Fixed\n\n\n;***********************************************************************************************\n;* Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                  *\n;*                                                                                             *\n;*    Use this routine to convert a fixed point number into a cardinal number.                 *\n;*                                                                                             *\n;* INPUT:   base     -- The base number that the original fixed point number was created from. *\n;*                                                                                             *\n;*          fixed    -- The fixed point number to convert.                                     *\n;*                                                                                             *\n;* OUTPUT:  Returns with the reconverted number.                                               *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n;unsigned int Fixed_To_Cardinal(unsigned base, unsigned fixed);\n\tPROC\tFixed_To_Cardinal C near\n\tUSES\tedx\n\n\tARG\tbase:DWORD\n\tARG\tfixed:DWORD\n\n\tmov\teax,[base]\n\tmul\t[fixed]\n\tadd\teax,08000h\t\t; eax = (base * fixed) + 0x8000\n\n\tshr\teax,16\t\t\t; return eax/65536\n\tret\n\n\tENDP\tFixed_To_Cardinal\n\n\tEND\n"
  },
  {
    "path": "REDALERT/COORDA.h",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/*\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : COORDA.ASM                               *\n;*                                                                         *\n;*                   Programmer : Barry W. Green                           *\n;*                                                                         *\n;*                   Start Date : February 17, 1995                        *\n;*                                                                         *\n;*                  Last Update : February 17, 1995  [BWG]                 *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                 *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n*/\n\n#ifndef COORD_A_H\n\n//IDEAL\n//P386\n//MODEL USE32 FLAT\n\n//global C\tCardinal_To_Fixed\t:NEAR\n//global C\tFixed_To_Cardinal\t:NEAR\n\n//\tCODESEG\n/*\n;***********************************************************************************************\n;* Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                   *\n;*                                                                                             *\n;*    This utility function will convert cardinal numbers into a fixed point fraction. The     *\n;*    use of fixed point numbers occurs throughout the product -- since it is a convenient     *\n;*    tool. The fixed point number is based on the formula:                                    *\n;*                                                                                             *\n;*       result = cardinal / base                                                              *\n;*                                                                                             *\n;*    The accuracy of the fixed point number is limited to 1/256 as the lowest and up to       *\n;*    256 as the largest.                                                                      *\n;*                                                                                             *\n;* INPUT:   base     -- The key number to base the fraction about.                             *\n;*                                                                                             *\n;*          cardinal -- The other number (hey -- what do you call it?)                         *\n;*                                                                                             *\n;* OUTPUT:  Returns with the fixed point number of the \"cardinal\" parameter as it relates      *\n;*          to the \"base\" parameter.                                                           *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n\nunsigned int __cdecl Cardinal_To_Fixed(unsigned base, unsigned cardinal);\n\n#if (0)\n\tPROC\tCardinal_To_Fixed C near\n\tUSES\tebx, edx\n\n\tARG\tbase:DWORD\n\tARG\tcardinal:DWORD\n\n\tmov\teax,0FFFFh\t\t; establish default return value\n\n\tmov\tebx,[base]\n\tor\tebx,ebx\n\tjz\tnear ??retneg1\t\t; if base==0, return 65535\n\n\tmov\teax,[cardinal]\t\t; otherwise, return (cardinal*256)/base\n\tshl\teax,8\n\txor\tedx,edx\n\tdiv\tebx\n\n??retneg1:\n\tret\n\n\tENDP\tCardinal_To_Fixed\n#endif\n\n/*\n;***********************************************************************************************\n;* Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                  *\n;*                                                                                             *\n;*    Use this routine to convert a fixed point number into a cardinal number.                 *\n;*                                                                                             *\n;* INPUT:   base     -- The base number that the original fixed point number was created from. *\n;*                                                                                             *\n;*          fixed    -- The fixed point number to convert.                                     *\n;*                                                                                             *\n;* OUTPUT:  Returns with the reconverted number.                                               *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n\nunsigned int __cdecl Fixed_To_Cardinal(unsigned base, unsigned fixed);\n\n#if (0)\n\tmov\teax,[base]\n\tmul\t[fixed]\n\tadd\teax,080h\t\t; eax = (base * fixed) + 0x80\n\n\ttest\teax,0FF000000h\t\t; if high byte set, return FFFF\n\tjnz\t??rneg1\n\tshr\teax,8\t\t\t; else, return eax/256\n\tret\n??rneg1\t:\n\tmov\teax,0FFFFh\t\t; establish default return value\n\tret\n\n\tENDP\tFixed_To_Cardinal\n\n\tEND\n#endif\n\n\n\n\n\n#endif COORD_A_H"
  },
  {
    "path": "REDALERT/CPUID.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\cpuid.asv   5.0   11 Nov 1996 09:40:28   JOE_BOSTIC  $\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : MMX.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Steve Tall                               *\n;*                                                                         *\n;*                   Start Date : May 19th, 1996                           *\n;*                                                                         *\n;*                  Last Update : May 19th 1996 [ST]                       *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n\t\t.586\n\t\t.model\tflat\n\n;\n; Variables externs\n;\nGLOBAL\tC CPUType:byte\n;externdef\tC CPUType:byte\nGLOBAL\tC VendorID:byte\n;externdef\tC VendorID:byte\n\n;\n; Function externs\n;\nGLOBAL\tC Detect_MMX_Availability:near\n;externdef\tC Detect_MMX_Availability:near\n\n\n\t\t.code\n\n\n;*********************************************************************************************\n;* Detect_MMX_Availability -- Detect the presence of MMX technology.                         *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      True if MMX technology is available.                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* Note: Based in part on CPUID32.ASM by Intel                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nDetect_MMX_Availability proc C\n\n\t\tlocal\tidflag:byte\n\t\tlocal\tcputype:byte\n\n;assume processor is at least 386\n;\n;check whether AC bit in eflags can be toggled.\n;If not then processor is 386\n\n\t\tmov\t[idflag],0\n\n\t\tpushfd\t\t\t;get Eflags in EAX\n\t\tpop\teax\n\t\tmov\tecx,eax\t\t;save eflags\n\t\txor\teax,40000h\t;toggle AC bit in eflags\n\t\tpush\teax\t\t;new eflags on stack\n\t\tpopfd\t\t\t;move new value into eflags\n\t\tpushfd\t\t\t;get new eflags back into eax\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;if AC bit not toggled then CPU=386\n\t\tmov\t[cputype],3\n\t\tjz\t@@end_get_cpu\t;cpu is 386\n\n\t\tpush\tecx\n\t\tpopfd\t\t\t;restore AC bit in eflags\n\n\n;processor is at least 486\n;\n;Check for ability to set/clear ID flag in EFLAGS\n;ID flag indicates ability of processor to execute the CPUID instruction.\n;486 not guaranteed to have CPUID inst?\n;\n\t\tmov\t[cputype],4\n\t\tmov\teax,ecx\t\t;original EFLAGS\n\t\txor\teax,200000h\t;toggle ID bit\n\t\tpush\teax\n\t\tpopfd\n\t\tpushfd\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;check if still toggled\n\t\tjz\t@@end_get_cpu\n\n\n;       Execute CPUID instruction to determine vendor, family,\n;       model and stepping.\n;\n\n\t\tmov\t[idflag],1\t;flag ID is available\n\n\t\txor\teax,eax\n\t\tcpuid\n\n\t\tmov\tdword ptr [VendorID],ebx\n\t\tmov\tdword ptr [VendorID+4],edx\n\t\tmov\tdword ptr [VendorID+8],ecx\n\t\tmov\tdword ptr [VendorID+12],\" \"\n\n\t\tcmp\teax,1\t\t;check if 1 is valid\n\t\tjl\t@@end_get_cpu\t;inp for cpuid inst.\n\n\t\txor\teax,eax\n\t\tinc\teax\n\n\t\tcpuid\t\t;get stepping, model and family\n\n\t\tand     ax,0f00H\n\t\tshr     ax,08H\n\n\t\tmov\t[cputype],al\n\n@@end_get_cpu:\tmov\tal,[cputype]\n\t\tmov\t[CPUType],al\n\n\n;\n; We have the CPU type in al now.\n; If we arent on at least a pentium then we can assume there is no MMX\n;\n\t\tcmp\tal,5\n\t\tjl\t@@no_mmx\n\n\t\tmov\teax,1\n\t\tcpuid\n\t\ttest\tedx,00800000h\n\t\tjz\t@@no_mmx\n\n;\n; MMX detected - return true\n;\n\t\tmov\teax,1\n\t\tret\n\n\n@@no_mmx:\txor\teax,eax\n\t\tret\n\n\nDetect_MMX_Availability endp\n\n\n\t\t.data\n\nCPUType\t\tdb\t0\nVendorID\tdb\t\"Not available\",0,0,0,0,0,0\n\n\nend\n\n"
  },
  {
    "path": "REDALERT/CRATE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRATE.CPP 3     3/04/97 3:12p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRATE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/26/96                                                     *\n *                                                                                             *\n *                  Last Update : October 14, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CrateClass::Create_Crate -- Create a crate in the cell specified.                         *\n *   CrateClass::Get_Crate -- Pick up a crate from the cell specified.                         *\n *   CrateClass::Put_Crate -- Generates crate overlay at cell specified.                       *\n *   CrateClass::Remove_It -- Removes the crate from wherever it is.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CrateClass::Remove_It -- Removes the crate from wherever it is.                             *\n *                                                                                             *\n *    This routine will remove the crate from whereever it happens to be.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate found and removed?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Remove_It(void)\n{\n\tif (Is_Valid()) {\n\t\tGet_Crate(Cell);\n\t\tMake_Invalid();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Create_Crate -- Create a crate in the cell specified.                           *\n *                                                                                             *\n *    This will create a crate in the cell specified. If the crate could not be crated there   *\n *    then 'false' will be returned.                                                           *\n *                                                                                             *\n * INPUT:   cell  -- The desired cell to place the crate in.                                   *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate created and placed in the cell?                                *\n *                                                                                             *\n * WARNINGS:   It is quite possible for the crate not to have been placed. Only the most clear *\n *             locations are valid for crate placement.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Create_Crate(CELL cell)\n{\n\t/*\n\t**\tRemove any existing crate that this crate class is tracking.\n\t*/\n\tRemove_It();\n\n\t/*\n\t**\tTry to place a new crate at the cell specified.\n\t*/\n\tif (Put_Crate(cell)) {\n\t\tCell = cell;\n\t\tTimer = Random_Pick(Rule.CrateTime * (TICKS_PER_MINUTE/2), Rule.CrateTime * (TICKS_PER_MINUTE*2));\n\t\tTimer.Start();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Put_Crate -- Generates crate overlay at cell specified.                         *\n *                                                                                             *\n *    This helpter routine will examine the cell and place the appropriate crate type into     *\n *    the cell specified. If the overlay could not be generated, then 'false' is returned.     *\n *                                                                                             *\n * INPUT:   cell  -- The cell to generate the crate overlay in.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the crate overlay generated?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *   10/14/1996 JLB : Takes reference to cell so that tracking can occur.                      *\n *=============================================================================================*/\nbool CrateClass::Put_Crate(CELL & cell)\n{\n\tint old = ScenarioInit;\n\tScenarioInit = 0;\n\n\tif (Map.In_Radar(cell)) {\n\t\tCellClass * cellptr = &Map[cell];\n\n\t\twhile (cellptr->Overlay != OVERLAY_NONE && !cellptr->Is_Clear_To_Build(SPEED_FLOAT) && !cellptr->Is_Clear_To_Build(SPEED_FOOT)) {\n\t\t\tcell = Map.Pick_Random_Location();\n\n\t\t\tif (Percent_Chance(100 * Rule.WaterCrateChance)) {\n\t\t\t\tcell = Map.Nearby_Location(cell, SPEED_FLOAT);\n\t\t\t} else {\n\t\t\t\tcell = Map.Nearby_Location(cell, SPEED_TRACK);\n\t\t\t}\n\t\t\tcellptr = &Map[cell];\n\t\t}\n\n\t\tif (cellptr->Is_Clear_To_Build(SPEED_FLOAT)) {\n\t\t\tnew OverlayClass(OVERLAY_WATER_CRATE, cell);\n\t\t} else {\n\t\t\tnew OverlayClass(OVERLAY_WOOD_CRATE, cell);\n\t\t}\n\t\tScenarioInit = old;\n\t\treturn(true);\n\t}\n\n\tScenarioInit = old;\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * CrateClass::Get_Crate -- Pick up a crate from the cell specified.                           *\n *                                                                                             *\n *    This will remove the crate from the cell specified.                                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine and remove any crate overlays present.                *\n *                                                                                             *\n * OUTPUT:  bool; Was a crate overlay found and removed?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CrateClass::Get_Crate(CELL cell)\n{\n\tif (Map.In_Radar(cell)) {\n\t\tCellClass * cellptr = &Map[cell];\n\n\t\tif (cellptr->Overlay == OVERLAY_WOOD_CRATE ||\n\t\t\tcellptr->Overlay == OVERLAY_STEEL_CRATE ||\n\t\t\tcellptr->Overlay == OVERLAY_WATER_CRATE) {\n\n\t\t\tcellptr->Overlay = OVERLAY_NONE;\n\t\t\tcellptr->OverlayData = 0;\n\t\t\tcellptr->Redraw_Objects();\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/CRATE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRATE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRATE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/26/96                                                     *\n *                                                                                             *\n *                  Last Update : August 26, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CRATE_H\n#define CRATE_H\n\n#include\t\"ftimer.h\"\n#include\t\"jshell.h\"\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\nclass CrateClass {\n\tpublic:\n\t\tCrateClass(void) : Timer(NoInitClass()), Cell(-1) {}\n\t\tvoid Init(void) {Make_Invalid();}\n\t\tbool Create_Crate(CELL cell);\n\t\tbool Is_Here(CELL cell) const {return(Is_Valid() && cell == Cell);}\n\t\tbool Remove_It(void);\n\t\tbool Is_Expired(void) const {return(Is_Valid() && Timer == 0);}\n\t\tbool Is_Valid(void) const {return(Cell != -1);}\n\n\tprivate:\n\t\tstatic bool Put_Crate(CELL & cell);\n\t\tstatic bool Get_Crate(CELL cell);\n\n\t\tvoid Make_Invalid(void) {Cell = -1;Timer.Stop();}\n\n\t\tCDTimerClass<FrameTimerClass> Timer;\n\t\tCELL Cell;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/CRC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRC.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRC.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/96                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCEngine::operator() -- Submits one byte of data to the CRC engine.                      *\n *   CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"crc.h\"\n\n\n/***********************************************************************************************\n * CRCEngine::operator() -- Submits one byte of data to the CRC engine.                        *\n *                                                                                             *\n *    This routine will take the specified byte of data and submit it to the CRC engine        *\n *    for processing. This routine is designed to be as fast as possible since the typical     *\n *    use of this routine is to feed one of presumably many byte sized chunks of data to the   *\n *    CRC engine.                                                                              *\n *                                                                                             *\n * INPUT:   datum -- One byte of data to submit to the CRC engine.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If possible, use the buffer/size operator to submit data rather than repeated   *\n *             calls to this routine.                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid CRCEngine::operator() (char datum)\n{\n\tStagingBuffer.Buffer[Index++] = datum;\n\n\tif (Index == sizeof(long))  {\n\t\tCRC = Value();\n\t\tStagingBuffer.Composite = 0;\n\t\tIndex = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine.                 *\n *                                                                                             *\n *    This routine will submit the specified block to the CRC engine. The block can be of      *\n *    arbitrary length.                                                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that contains the data. The buffer will not      *\n *                      be modified.                                                           *\n *                                                                                             *\n *          length   -- The length of the buffer (in bytes).                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the current CRC value accumulated so far.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCEngine::operator() (void const * buffer, int length)\n{\n\tif (buffer != NULL && length > 0)  {\n\t\tchar const * dataptr = (char const *)buffer;\n\t\tint bytes_left = length;\n\n\t\t/*\n\t\t**\tIf there are any leader bytes (needed to fill the staging buffer)\n\t\t**\tthen process those by first using them to fill up the staging\n\t\t**\tbuffer. The bulk of the data block will be processed by the high\n\t\t**\tspeed longword processing loop.\n\t\t*/\n\t\twhile (bytes_left && Buffer_Needs_Data()) {\n\t\t\toperator()(*dataptr);\n\t\t\tdataptr++;\n\t\t\tbytes_left--;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the fast 'bulk' processing by reading long word sized\n\t\t**\tdata blocks.\n\t\t*/\n\t\tlong const * longptr = (long const *)dataptr;\n\t\tint longcount = bytes_left / sizeof(long);\t\t// Whole 'long' elements remaining.\n\t\twhile (longcount--) {\n\t\t\tCRC = _lrotl(CRC, 1) + *longptr++;\n\t\t\tbytes_left -= sizeof(long);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there are remainder bytes, then process these by adding them\n\t\t**\tto the staging buffer.\n\t\t*/\n\t\tdataptr = (char const *)longptr;\n\t\twhile (bytes_left) {\n\t\t\toperator()(*dataptr);\n\t\t\tdataptr++;\n\t\t\tbytes_left--;\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn the current CRC value.\n\t*/\n\treturn(Value());\n}\n"
  },
  {
    "path": "REDALERT/CRC.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRC.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRC.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/02/96                                                     *\n *                                                                                             *\n *                  Last Update : March 2, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRC_H\n#define CRC_H\n\n#include\t<stdlib.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n/*\n**\tThis is a CRC engine class. It will process submitted data and generate a CRC from it.\n**\tWell, actually, the value returned is not a true CRC. However, it shares the same strength\n**\tcharacteristic and is faster to generate than the traditional CRC. This object is treated like\n**\ta method class. If it is called as a function (using the function operator), it will return\n**\tthe CRC value. There are other function operators to submit data for processing.\n*/\nclass CRCEngine {\n\tpublic:\n\n\t\t// Constructor for CRC engine (it can have an override initial CRC value).\n\t\tCRCEngine(long initial=0) : CRC(initial), Index(0) {\n\t\t\tStagingBuffer.Composite = 0;\n\t\t};\n\n\t\t// Fetches CRC value.\n\t\tlong operator() (void) const {return(Value());};\n\n\t\t// Submits one byte sized datum to the CRC accumulator.\n\t\tvoid operator() (char datum);\n\n\t\t// Submits an arbitrary buffer to the CRC accumulator.\n\t\tlong operator() (void const * buffer, int length);\n\n\t\t// Implicit conversion operator so this object appears like a 'long integer'.\n\t\toperator long(void) const {return(Value());};\n\n\tprotected:\n\n\t\tbool Buffer_Needs_Data(void) const {\n\t\t\treturn(Index != 0);\n\t\t};\n\n\t\tlong Value(void) const {\n\t\t\tif (Buffer_Needs_Data()) {\n\t\t\t\treturn(_lrotl(CRC, 1) + StagingBuffer.Composite);\n\t\t\t}\n\t\t\treturn(CRC);\n\t\t};\n\n\t\t/*\n\t\t**\tCurrent accumulator of the CRC value. This value doesn't take into\n\t\t**\tconsideration any pending data in the staging buffer.\n\t\t*/\n\t\tlong CRC;\n\n\t\t/*\n\t\t**\tThis is the sub index into the staging buffer used to keep track of\n\t\t**\tpartial data blocks as they are submitted to the CRC engine.\n\t\t*/\n\t\tint Index;\n\n\t\t/*\n\t\t**\tThis is the buffer that holds the incoming partial data. When the buffer\n\t\t**\tis filled, the value is transformed into the CRC and the buffer is flushed\n\t\t**\tin preparation for additional data.\n\t\t*/\n\t\tunion {\n\t\t\tlong Composite;\n\t\t\tchar Buffer[sizeof(long)];\n\t\t} StagingBuffer;\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/CRCPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRCPIPE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCPipe::Result -- Fetches the current CRC of the data.                                   *\n *   CRCPipe::Put -- Retrieves the data bytes specified and calculates CRC on it.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"crcpipe.h\"\n\n\n/***********************************************************************************************\n * CRCPipe::Put -- Retrieves the data bytes specified and calculates CRC on it.                *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested from the straw. The data is        *\n *    not modified by this straw segment, but it is examined by the CRC engine in order to     *\n *    keep an accurate CRC of the data that passes through this routine.                       *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the data requested.               *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number is  *\n *          less than the number requested, then this indicates that the data stream has been  *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CRCPipe::Put(void const * source, int slen)\n{\n\tCRC(source, slen);\n\treturn(Pipe::Put(source, slen));\n}\n\n\n/***********************************************************************************************\n * CRCPipe::Result -- Fetches the current CRC of the data.                                     *\n *                                                                                             *\n *    This routine will return the CRC of the data that has passed through the pipe up to      *\n *    this time.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the CRC value.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCPipe::Result(void) const\n{\n\treturn(CRC());\n}\n\n"
  },
  {
    "path": "REDALERT/CRCPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRCPIPE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRCPIPE_H\n#define CRCPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"crc.h\"\n\n/*\n**\tThis class doesn't modify the data being piped through, but it does examine it and build\n**\ta CRC value from the data.\n*/\nclass CRCPipe : public Pipe\n{\n\tpublic:\n\t\tCRCPipe(void) {}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Fetch the CRC value.\n\t\tlong Result(void) const;\n\n\tprotected:\n\t\tCRCEngine CRC;\n\n\tprivate:\n\t\tCRCPipe(CRCPipe & rvalue);\n\t\tCRCPipe & operator = (CRCPipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CRCSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRCSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CRCStraw::Get -- Fetch the data requested and calculate CRC on it.                        *\n *   CRCStraw::Result -- Returns with the CRC of all data passed through the straw.            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"crcstraw.h\"\n\n\n/***********************************************************************************************\n * CRCStraw::Get -- Fetch the data requested and calculate CRC on it.                          *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested. The data will not be modified     *\n *    by this straw segment, but the CRC engine will examine the data so as to keep an         *\n *    accurate CRC value.                                                                      *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored in the buffer. If this number is    *\n *          less than that requested, then this indicates that the data stream has been        *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CRCStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\tint counter = Straw::Get(source, slen);\n\tCRC(source, counter);\n\treturn(counter);\n}\n\n\n/***********************************************************************************************\n * CRCStraw::Result -- Returns with the CRC of all data passed through the straw.              *\n *                                                                                             *\n *    This routine will return the CRC value of the data that has passed through this straw    *\n *    segment.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the CRC value of the data this straw segment has seen.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong CRCStraw::Result(void) const\n{\n\treturn(CRC());\n}\n"
  },
  {
    "path": "REDALERT/CRCSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CRCSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CRCSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CRCSTRAW_H\n#define CRCSTRAW_H\n\n#include \"straw.h\"\n#include \"crc.h\"\n\n/*\n**\tThis class will build a CRC value from the data stream that is drawn through this class.\n**\tThe data is not modified, but it is examined as it passes through.\n*/\nclass CRCStraw : public Straw\n{\n\tpublic:\n\t\tCRCStraw(void) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Calculate and return the CRC value.\n\t\tlong Result(void) const;\n\n\tprotected:\n\t\tCRCEngine CRC;\n\n\tprivate:\n\t\tCRCStraw(CRCStraw & rvalue);\n\t\tCRCStraw & operator = (CRCStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/CREDITS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CREDITS.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREDITS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 17, 1994                                               *\n *                                                                                             *\n *                  Last Update : March 13, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CreditClass::AI -- Handles updating the credit display.                                   *\n *   CreditClass::CreditClass -- Default constructor for the credit class object.              *\n *   CreditClass::Graphic_Logic -- Handles the credit redraw logic.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * CreditClass::CreditClass -- Default constructor for the credit class object.                *\n *                                                                                             *\n *    This is the constructor for the credit class object. It merely sets the credit display   *\n *    state to null.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCreditClass::CreditClass(void) :\n\tCredits(0),\n\tCurrent(0),\n\tIsToRedraw(false),\n\tIsUp(false),\n\tIsAudible(false),\n\tCountdown(0)\n{\n}\n\n\n/***********************************************************************************************\n * CreditClass::Graphic_Logic -- Handles the credit redraw logic.                              *\n *                                                                                             *\n *    This routine should be called whenever the main game screen is to be updated. It will    *\n *    check to see if the credit display should be redrawn. If so, it will redraw it.          *\n *                                                                                             *\n * INPUT:   forced   -- Should the credit display be redrawn regardless of whether the redraw  *\n *                      flag is set? This is typically the case when the screen needs to be    *\n *                      redrawn from scratch.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n//#define\tXX (320-120)\n//#define\tWW\t50\nvoid CreditClass::Graphic_Logic(bool forced)\n{\n\tif (forced || IsToRedraw) {\n\t\tBStart(BENCH_TABS);\n\n\t\tint xx = SeenBuff.Get_Width() - (120 * RESFACTOR);\n\n\t\t/*\n\t\t** Adjust the credits display to be above the sidebar for 640x400\n\t\t*/\n#ifdef WIN32\n\t\txx += 80 * RESFACTOR;\n#endif\n\n\t\t/*\n\t\t**\tPlay a sound effect when the money display changes, but only if a sound\n\t\t**\teffect was requested.\n\t\t*/\n\t\tif (IsAudible) {\n\t\t\tif (IsUp) {\n\t\t\t\tSound_Effect(VOC_MONEY_UP, fixed(1, 2));\n\t\t\t} else  {\n\t\t\t\tSound_Effect(VOC_MONEY_DOWN, fixed(1, 2));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the new current value.\n\t\t*/\n\t\t// PG TabClass::Draw_Credits_Tab();\n#ifdef WIN32\n\t\t//PG Fancy_Text_Print(\"%ld\", xx, 0, &MetalScheme, TBLACK, TPF_METAL12 | TPF_CENTER | TPF_USE_GRAD_PAL, Current);\n#else\n\t\tFancy_Text_Print(\"%ld\", xx, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, Current);\n#endif\t//WIN32\n\n\t\tif (Scen.MissionTimer.Is_Active()) {\n\t\t\tlong secs = Scen.MissionTimer / TICKS_PER_SECOND;\n\t\t\tlong mins = secs / 60;\n\t\t\tlong hours = mins / 60;\n\t\t\tsecs %= 60;\n\t\t\tmins %= 60;\n#if (0) //Moved to LOGIC.CPP\n\t\t\t/*\n\t\t\t**\tSpeak mission timer reminders.\n\t\t\t*/\n\t\t\tVoxType vox = VOX_NONE;\n\t\t\tif (Scen.MissionTimer == (1 * TICKS_PER_MINUTE)) vox = VOX_TIME_1;\n\t\t\tif (Scen.MissionTimer == (2 * TICKS_PER_MINUTE)) vox = VOX_TIME_2;\n\t\t\tif (Scen.MissionTimer == (3 * TICKS_PER_MINUTE)) vox = VOX_TIME_3;\n\t\t\tif (Scen.MissionTimer == (4 * TICKS_PER_MINUTE)) vox = VOX_TIME_4;\n\t\t\tif (Scen.MissionTimer == (5 * TICKS_PER_MINUTE)) vox = VOX_TIME_5;\n\t\t\tif (Scen.MissionTimer == (10 * TICKS_PER_MINUTE)) vox = VOX_TIME_10;\n\t\t\tif (Scen.MissionTimer == (20 * TICKS_PER_MINUTE)) vox = VOX_TIME_20;\n\t\t\tif (Scen.MissionTimer == (30 * TICKS_PER_MINUTE)) vox = VOX_TIME_30;\n\t\t\tif (Scen.MissionTimer == (40 * TICKS_PER_MINUTE)) vox = VOX_TIME_40;\n\t\t\tif (vox != VOX_NONE) {\n\t\t\t\tSpeak(vox);\n\t\t\t\tMap.FlasherTimer = 7;\n\t\t\t}\n#endif\n#ifdef WIN32\n#if (0) //PG\n\t\t\tif (hours) {\n\t\t\t\tFancy_Text_Print(TXT_TIME_FORMAT_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, hours, mins, secs);\n\t\t\t} else {\n\t\t\t\tFancy_Text_Print(TXT_TIME_FORMAT_NO_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, mins, secs);\n\t\t\t}\n#endif\n#else\n\t\t\tif (hours) {\n\t\t\t\tFancy_Text_Print(\"%02d:%02d:%02d\", 120 * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, hours, mins, secs);\n\t\t\t} else {\n\t\t\t\tFancy_Text_Print(\"%02d:%02d\", 120 * RESFACTOR, 0, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_NOSHADOW|TPF_6PT_GRAD|TPF_CENTER|TPF_BRIGHT_COLOR, mins, secs);\n\t\t\t}\n#endif\t//WIN32\n\t\t}\n\n\t\tIsToRedraw = false;\n\t\tIsAudible = false;\n\t\tBEnd(BENCH_TABS);\n\t}\n}\n\n\n/***********************************************************************************************\n * CreditClass::AI -- Handles updating the credit display.                                     *\n *                                                                                             *\n *    This routine handles the logic that controls the rate of credit change in the credit     *\n *    display. It doesn't actually redraw the credit display, but will flag it to be redrawn   *\n *    if it detects that a change is to occur.                                                 *\n *                                                                                             *\n * INPUT:   forced   -- Should the credit display immediately reflect the current credit       *\n *                      total for the player? This is usually desired when initially loading   *\n *                      a scenario or saved game.                                              *\n *          player_ptr -- Player to calculate visible credits for                              *\n *          logic_only -- If true, don't flag map for redraw                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *   10/16/2019  ST : Added house and logic parameters so we can call this from HouseClass::AI *\n *=============================================================================================*/\nvoid CreditClass::AI(bool forced, HouseClass *player_ptr, bool logic_only)\n{\n\tstatic int _last = 0;\n\n\tif (!forced && !logic_only && Frame == _last) return;\n\tif (!logic_only) {\n\t\t_last = Frame;\n\t}\n\n\tif (player_ptr == NULL) {\n\t\treturn;\n\t}\n\n\tCredits = player_ptr->Available_Money();\n\n\t/*\n\t**\tMake sure that the credit counter doesn't drop below zero.\n\t*/\n\tCredits = max(Credits, 0L);\n\n\tif (Scen.MissionTimer.Is_Active() || Scen.MissionTimer) {\n\t\tIsToRedraw = true;\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\tif (Current == Credits) return;\n\n\tif (forced) {\n\t\tIsAudible = false;\n\t\tCurrent = Credits;\n\t} else {\n\n\t\tif (Countdown) Countdown--;\n\t\tif (Countdown) return;\n\n\t\t/*\n\t\t**\tDetermine the amount to change the display toward the\n\t\t**\tdesired value.\n\t\t*/\n\t\tint adder = Credits - Current;\n\n\t\tif (adder > 0) {\n\t\t\tCountdown = 1;\n\t\t} else {\n\t\t\tCountdown = 3;\n\t\t}\n\n\t\tadder = ABS(adder);\n\t\tadder >>= 3;\n//\t\tadder >>= 4;\n//\t\tadder >>= 5;\n\t\tadder = Bound(adder, 1, 71+72);\n\t\tif (Current > Credits) adder = -adder;\n\t\tCurrent += adder;\n\t\tif (Current-adder != Current) {\n\t\t\tIsAudible = true;\n\t\t\tIsUp = (adder > 0);\n\t\t}\n\t}\n\tIsToRedraw = true;\n\n\tif (!logic_only) {\n\t\tMap.Flag_To_Redraw(false);\n\t}\n}"
  },
  {
    "path": "REDALERT/CREDITS.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CREDITS.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREDIT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 19, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CREDITS_H\n#define CREDITS_H\n\nclass HouseClass;\nextern HouseClass *PlayerPtr;\n\n/****************************************************************************\n**\tThe animating credit counter display is controlled by this class.\n*/\nclass CreditClass {\n\tpublic:\n\t\tlong Credits;\t\t// Value of credits trying to update display to.\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCreditClass(void);\n\t\tCreditClass(NoInitClass const & ) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvoid Update(bool forced=false, bool redraw=false);\n\n\t\tvoid Graphic_Logic(bool forced=false);\n\t\tvoid AI(bool forced=false, HouseClass *player_ptr = PlayerPtr, bool logic_only = false);\t\t// Added house and logic_only parameters. ST - 10/16/2019 2:26PM\n\n\t\tlong\tCurrent;\t\t// Credit value currently displayed.\n\n\t\tunsigned IsToRedraw:1;\n\t\tunsigned IsUp:1;\n\t\tunsigned IsAudible:1;\n\n\tprivate:\n\t\tint\tCountdown;\t// Delay between ticks.\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CREW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CREW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREW.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n"
  },
  {
    "path": "REDALERT/CREW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CREW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CREW.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef CREW_H\n#define CREW_H\n\n\n/****************************************************************************\n**\tThis class handles the basic crew logic. This includes hero tracking,\n**\tcrew bail-out, and attached object logic.\n*/\nclass CrewClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis keeps track of the number of \"kills\" the unit as accumulated.\n\t\t**\tWhen it reaches a certain point, the unit improves.\n\t\t*/\n\t\tunsigned short Kills;\n\n\t\t/*\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tCrewClass(void) : Kills(0) {};\n\t\tCrewClass(NoInitClass const &) {};\n\t\t~CrewClass(void) {};\n\n\t\tint Made_A_Kill(void) {\n\t\t\tKills++;\n\t\t\treturn(Kills);\n\t\t};\n\n\tprivate:\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/CSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CSTRAW.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CSTRAW.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/10/96                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CacheStraw::Get -- Fetch data from the data source.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"cstraw.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * CacheStraw::Get -- Fetch data from the data source.                                         *\n *                                                                                             *\n *    This will supply the data quantity requested. It performs a regulating influence on the  *\n *    data requests passed through it. The data is requested from the next straw in the        *\n *    chain such that the data stream is requested in chunks. This serves to lessen the        *\n *    impact of multiple small data requests.                                                  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the data.                                *\n *                                                                                             *\n *          slen     -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of data bytes stored into the buffer specified. If this    *\n *          number is less than that requested, it indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint CacheStraw::Get(void * source, int slen)\n{\n\tint total = 0;\n\n\tif (Is_Valid() && source != NULL && slen > 0) {\n\n\t\t/*\n\t\t**\tKeep processing the data request until there is no more data to supply or the request\n\t\t**\thas been fulfilled.\n\t\t*/\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst try to fetch the data from data previously loaded into the buffer.\n\t\t\t*/\n\t\t\tif (Length > 0) {\n\t\t\t\tint tocopy = (Length < slen) ? Length : slen;\n\t\t\t\tmemmove(source, ((char *)BufferPtr.Get_Buffer()) + Index, tocopy);\n\t\t\t\tslen -= tocopy;\n\t\t\t\tIndex += tocopy;\n\t\t\t\ttotal += tocopy;\n\t\t\t\tLength -= tocopy;\n\t\t\t\tsource = (char*)source + tocopy;\n\t\t\t}\n\t\t\tif (slen == 0) break;\n\n\t\t\t/*\n\t\t\t**\tSince there is more to be fulfilled yet the holding buffer is empty,\n\t\t\t**\trefill the buffer with a fresh block of data from the source.\n\t\t\t*/\n\t\t\tLength = Straw::Get(BufferPtr, BufferPtr.Get_Size());\n\t\t\tIndex = 0;\n\t\t\tif (Length == 0) break;\n\t\t}\n\t}\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/CSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/CSTRAW.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : CSTRAW.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/10/96                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef CSTRAW_H\n#define CSTRAW_H\n\n#include\t\"straw.h\"\n#include\t\"buff.h\"\n\n/*\n**\tThis class handles transfer of data by perform regulated requests for data from the next\n**\tclass in the chain. It performs no translation on the data. By using this segment in a\n**\tstraw chain, data throughput can be regulated. This can yield great performance increases\n**\twhen dealing with a file source.\n*/\nclass CacheStraw : public Straw\n{\n\tpublic:\n\t\tCacheStraw(Buffer const & buffer) : BufferPtr(buffer), Index(0), Length(0) {}\n\t\tCacheStraw(int length=4096) : BufferPtr(length), Index(0), Length(0) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\t\tBuffer BufferPtr;\n\t\tint Index;\n\t\tint Length;\n\n\t\tbool Is_Valid(void) {return(BufferPtr.Is_Valid());}\n\t\tCacheStraw(CacheStraw & rvalue);\n\t\tCacheStraw & operator = (CacheStraw const & pipe);\n};\n\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/DDE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dynamic Data Encapsulation               *\n *                                                                         *\n *                    File Name : DDE.CPP\t\t                             *\n *                                                                         *\n *                   Programmer : Steve Wetherill                          *\n *                                                                         *\n *                   Start Date : June 1, 1996                             *\n *                                                                         *\n *                  Last Update : June 8, 1996 [SW]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Instance_Class::InstanceClass -- class constructor                    *\n *   Instance_Class::InstanceClass -- class destructor                     *\n *   Instance_Class::Enable_Callback -- enables local processing of pokes  *\n *   Instance_Class::Register_Servers -- registers a local DDE DNS service *\n *   Instance_Class::Cleanup_App -- currently does nothing                 *\n *   Instance_Class::Test_Server_Running -- does a trial connect to remote *\n *\t  Instance_Class::Open_Poke_Connection -- pokes some data to server\t  *\n *   Instance_Class::Close_Poke_Connectionp -- closes connection to remote *\n *   Instance_Class::Poke_Server -- sends a chunk of data to remote        *\n *   Instance_Class::dde_callback -- processes DDE transactions            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n#include\t<windows.h>\n#include\t\"dde.h\"\n\n/***************************************************************************\n * These are static members of Instance_Class\n *=========================================================================*/\n\nDWORD\tInstance_Class::id_inst;\t\t\t// instance identifier set by DdeInitialize\nBOOL\t\tInstance_Class::process_pokes;\t// controls response to pokes\nchar \tInstance_Class::ascii_name[32];\t// name of server\n\n#if (0)\t//ST - 5/8/2019\nstatic BOOL CALLBACK\t(*Instance_Class::callback) (\n\t\t\tLPBYTE pointer,\t\t// pointer to received data\n\t\t\tlong\tlength\t\t\t// length of received data or advisory flag\n\t\t\t) = NULL;\n#endif\n\n/***************************************************************************\n * Instance_Class::InstanceClass -- class constructor              \t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname1\t\tnull terminated ASCII client name\t\t\t\t\t\t\t\t\t*\n *\t\tname1\t\tnull terminated ASCII server name\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tdde_error = TRUE if error occurs when initializing DDE\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nInstance_Class::Instance_Class( LPSTR name1, LPSTR name2 )\n{\n\tname1; name2;\n\treturn;\n\n#if (0)\t//ST - 5/8/2019\n\tdde_error = FALSE;\t\t// no errors\n\tprocess_pokes = FALSE;\t// disable pokes in callback\n\n\tid_inst = 0;\t\t\t\t// set to 0 for first time through\n\tconv_handle = 0;   \t\t// conversation handle reset\n\n\tlstrcpy( ascii_name, name1 );\t// keep a record of ASCII name\n\n\tif\t( DdeInitialize(\n\t\t(LPDWORD) &id_inst,\t\t\t// instance identifier\n\t\tdde_callback,\n\t\tAPPCLASS_STANDARD | \t\t\t// filter server messages\n\t\tCBF_FAIL_SELFCONNECTIONS,\t// prevent from connecting with self\n\t\t0) != DMLERR_NO_ERROR) {   // reserved\n\t\t\tdde_error = TRUE;\t\t\t// flag an error\n\t}\n\n\tlocal_name = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n    \tname1,     \t\t\t\t// string to register\n    \tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tremote_name = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n    \tname2,     \t\t\t\t// string to register\n    \tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tpoke_topic = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\t\"POKE TOPIC\", \t\t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tpoke_item = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\t\"POKE ITEM\", \t\t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n\n\tsystem_topic = DdeCreateStringHandle(\n\t\tid_inst,         \t\t// instance identifier\n\t\tSZDDESYS_TOPIC, \t\t// System topic\n\t\tCP_WINANSI);    \t\t// Windows ANSI code page\n#endif\n}\n\n/***************************************************************************\n * Instance_Class::~Instance_Class -- class destructor\t              \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                                *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nInstance_Class::~Instance_Class()\n{\n\tDdeUninitialize( id_inst );\n}\n\n/***************************************************************************\n * Instance_Class::Enable_Callback -- enables user callback\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    TRUE = enable poke processing\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *    FALSE = disable poke processing\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\techos the input\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tuser callback must be explicitly enabled. Disbabled by default.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Enable_Callback( BOOL flag )\t\t// enable or disable callback\n{\n\treturn (process_pokes = flag);\n\n}\n\n/***************************************************************************\n * Instance_Class::Register_Server -- registers a local DDE DNS service    *\n *                                                                         *\n * INPUT:                                                                  *\n *    BOOL CALLBACK ( *callback_fnc) ( LPBYTE, DWORD) = user poke callbacl *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == success\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n#if (0)\t//ST - 5/8/2019\nBOOL\tInstance_Class::Register_Server( BOOL CALLBACK ( *callback_fnc) (LPBYTE, long) )\n{\n\n\tif (DdeNameService( id_inst, local_name,\t0L, DNS_REGISTER ) != 0L) {\n\t\tcallback = callback_fnc;\n\t\treturn ( TRUE );\n\t} else {\n\t\treturn ( FALSE );\n\t}\n}\n#endif\n\n/***************************************************************************\n * Instance_Class::Test_Server_Running -- does a trial connect to remote   *\n *                                                                         *\n * INPUT:                                                                  *\n *    name = HSZ string handle of server name.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully connected to remote\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- Can be called for local or remote server but of course will \t\t\t*\n *      fail if a called for local and local server is not \"up\".\t\t\t\t*\n *\t\t- Disconects before exiting.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Test_Server_Running( HSZ name )\n{\n\n\tif( Open_Poke_Connection( name ) == TRUE) {\n\t\tClose_Poke_Connection();\n\t\treturn( TRUE );\n\t} else {\n\t\treturn( FALSE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Open_Poke_Connection -- open a connection to server\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    name = HSZ server name.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully opened connection\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tCan be called for local or remote server but of course will \t\t\t*\n *    fail if a called for local and local server is not \"up\".\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Open_Poke_Connection( HSZ name )\n{\n\tconv_handle = DdeConnect(\n\t\tid_inst,           \t// instance identifier\n\t\tname,         \t\t\t// service name string handle\n\t\tpoke_topic,        \t// topic string handle\n\t\t(PCONVCONTEXT) NULL);// use default context\n\n\tif (conv_handle == NULL) {\n\t\treturn FALSE;\n\t} else {\n\t\treturn TRUE;\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Close_Poke_Connection -- closes poke connection\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully closed connection\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to close connection for some reason\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nBOOL\tInstance_Class::Close_Poke_Connection( void )\n{\n\tif( conv_handle ) {\n\t\tHCONV\ttemp_handle = conv_handle;\n\t\tconv_handle = NULL;\n\t\treturn( DdeDisconnect( temp_handle ));\n\t} else {\n\t\treturn( TRUE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::Poke_Server -- pokes some data to server\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *    poke_data\tpoints to data to send to remote\t\t\t\t\t\t\t\t\t*\n *    poke_length\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE == successfully poked the data\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tFALSE == failed to connect\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\thas a 3 second timeout (change POKE_TIMEOUT, in milliseconds)\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\n#define\tPOKE_TIMEOUT\t60*1000\t      // 60 sec timeout\n\nBOOL\tInstance_Class::Poke_Server( LPBYTE poke_data, DWORD poke_length )\n{\n\n\tif( DdeClientTransaction(\n\n\t\tpoke_data,\t\t\t\t\t// address of data to pass to server\n\t  \tpoke_length,\t\t\t\t// length of data\n\t\tconv_handle,\t\t\t\t// handle of conversation\n\t\tpoke_topic,\t\t\t\t\t// handle of item name string\n\t\tCF_TEXT,\t\t\t\t\t\t// no special clipboard data format\n\t\tXTYP_POKE,\t\t\t\t\t// transaction type\n\t\tPOKE_TIMEOUT,\t\t\t\t\t\t\t// time-out duration (millisecs)\n\t\t(LPDWORD) NULL\t\t \t\t// address of transaction result (don't check)\n\t   ) == 0) {\n\n\t\treturn( FALSE);\n\t} else {\n\t\treturn( TRUE );\n\t}\n}\n\n/***************************************************************************\n *\tInstance_Class::dde_callback -- callback dde event handler\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdde_event\ttransaction type\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tuFmt\t\t\tclipboard data format\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thconv\t\t\thandle of the conversation\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thsz1\t\t\thandle of a string\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thsz2\t\t\thandle of a string\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\thdata\t\t\thandle of a global memory object\t\t\t\t\t\t\t\t\t*\n *\t\tdwData1\t\ttransaction-specific data\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tdwData2 \t\ttransaction-specific data\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tcontext specific HDDEDATA object\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t  \tNOTE: declared as HDDEDATA CALLBACK which means PASCAL parameters\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   6/1/1996 SW : Created.                                                *\n *=========================================================================*/\n\nHDDEDATA CALLBACK Instance_Class::dde_callback(\n\n\tUINT  dde_event,\t// transaction type\n\tUINT  uFmt,\t\t\t// clipboard data format\n\tHCONV  ,\t\t\t\t// handle of the conversation\n\tHSZ  hsz1,\t\t\t// handle of a string\n\tHSZ  hsz2,\t\t\t// handle of a string\n\tHDDEDATA  hdata,\t// handle of a global memory object\n\tDWORD  \t\t\t,\t// transaction-specific data\n\tDWORD  \t\t\t \t// transaction-specific data\n\t)\n{\n\tdde_event;\n\tuFmt;\n\thsz1;\n\thsz2;\n\thdata;\n\treturn (HDDEDATA)NULL;\n\n#if (0) // ST 5/8/2019\n\tif (!Instance_Class::callback){\n\t\treturn (HDDEDATA) NULL;\n\t}\n\n\tswitch ( dde_event ) {\n\n\t\tcase XTYP_REGISTER:\n      case XTYP_UNREGISTER:\n\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase XTYP_ADVDATA:\n\t\t\treturn (HDDEDATA) DDE_FACK;\n\n\t\tcase XTYP_XACT_COMPLETE:\n\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase XTYP_DISCONNECT:\n\n\t\t\tInstance_Class::callback( NULL, DDE_ADVISE_DISCONNECT);\n\t\t\treturn (HDDEDATA) NULL;\n\n\t\tcase\tXTYP_CONNECT: {\n\n\t\t\tchar\tbuffer[32];\n\n\t\t\tDdeQueryString (Instance_Class::id_inst, hsz2, buffer, sizeof (buffer), 0) ;\n\n\t\t\tif (0 != strcmp (buffer, Instance_Class::ascii_name)) {\n\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t}\n\n\t\t\tDdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;\n\n\t\t\tif (0 != strcmp (buffer, \"POKE TOPIC\")) {\n\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t}\n\n\t\t\tInstance_Class::callback( NULL, DDE_ADVISE_CONNECT);\n\t\t\treturn (HDDEDATA) TRUE;\n\t\t}\n\n\t\tcase\tXTYP_POKE:\n\n\t\t\tif\t(Instance_Class::process_pokes == FALSE ) {\n\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\t// processing disabled\n\t\t\t} else {\n\n\t\t\t\tchar\tbuffer[32];\n\n\t\t\t\tDdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;\n\n\t\t\t\tif (0 != strcmp (buffer, \"POKE TOPIC\")) {\n\t\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\n\t\t\t\t} else if (uFmt == CF_TEXT) {\t\t\t\t\t// make sure it's CF_TEXT\n\n\t\t\t\t\tBOOL processed;\n\t\t\t\t\tBYTE FAR *pdata;\n\t\t\t\t\tDWORD dw_length;\n\n\t\t\t\t\tif ( (pdata = DdeAccessData( hdata, &dw_length)) == NULL ) {\n\t\t\t\t\t\treturn (HDDEDATA) DDE_FNOTPROCESSED;\n\t\t\t\t\t}\n\n\t\t\t\t\tprocessed = Instance_Class::callback((LPBYTE) pdata, dw_length);\n\n\t\t\t\t\tDdeUnaccessData( hdata );\n\n\t\t\t\t\tif (processed == TRUE) {\n\t\t\t\t\t\treturn (HDDEDATA) DDE_FACK;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn (HDDEDATA) NULL;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n      \treturn (HDDEDATA) NULL;\n    }\n#endif\n}\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/DDE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Dynamic Data Encapsulation\t\t\t\t\t*\n *                                                                         *\n *                    File Name : DDE.H\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Programmer : Steve Wetherill\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *                   Start Date : June 1, 1996\t\t                        *\n *                                                                         *\n *                  Last Update : June 8, 1996   [SW]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the DDE (Instance_Class) which provides a simple CLIENT/SERVER\t*\n * DDE model for data transactions between Windows applications.\t\t\t\t*\n * This is a fairly naieve implementation allowing only one client/server\t*\n * per Instance_Class object. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Typical uses for this class are:\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * i. Robust verification of whether an application is running\t\t\t\t\t*\n * ii. Data transfer between applications\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n/*\n***************************** Class defines *****************************\n*/\n\n#ifndef \t__DDE_H\n#define\t__DDE_H\n\n#define\tDDE_ADVISE_CONNECT\t\t-1\t\t// advisory \"client has connected\"\n#define\tDDE_ADVISE_DISCONNECT\t-2\t\t// advisory \"client has disconnected\"\n\n/*\n***************************** Class Declaration *****************************\n*/\n\nclass\tInstance_Class {\n\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\n\t\t/*.....................................................................\n\t\tConstructor:\n\t\t- takes null terminated ASCII strings names for client and server\n\t\t.....................................................................*/\n\n\t\tInstance_Class(\t\t// constructor\n\t\t\tLPSTR,\t\t\t\t// null terminated local sever name string\n\t\t\tLPSTR\t\t\t\t\t// null terminated remote server name string\n\t\t\t);\n\n\t\t/*.....................................................................\n\t\tDestructor:\n\t\t.....................................................................*/\n\t\t~Instance_Class(void);\t// the destructor\n\n\t\t/*.....................................................................\n\t\tSend data routine:\n\t\t- sends an unsolicited packet of data to the remote server\n\t\t.....................................................................*/\n\t\tBOOL\tPoke_Server( LPBYTE, DWORD);\n\n\t\t/*.....................................................................\n\t\tSend data routine:\n\t\t- sets up DNS for the server and registers a user callback to handle\n\t\t  incoming data\n\t\t.....................................................................*/\n\t\tBOOL\tRegister_Server( BOOL (CALLBACK *)(LPBYTE, long));\n\n\t\t/*.....................................................................\n\t\tDoes a trial connect to the remote server.\n\t\t- used to determine whether server is alive or not (and thus running)\n\t\t.....................................................................*/\n\t\tBOOL\tTest_Server_Running( HSZ );\n\n\t\t/*.....................................................................\n\t\tEnables user callback (disabled by default)\n\t\t.....................................................................*/\n\t\tBOOL\tEnable_Callback( BOOL );\t\t// enable or disable callback\n\n\t\t/*.....................................................................\n\t\tOpen a connection for sending data to remote server\n\t\t.....................................................................*/\n\t\tBOOL\tOpen_Poke_Connection( HSZ );\n\n\t\t/*.....................................................................\n\t\tClose connection with remote server\n\t\t.....................................................................*/\n\t\tBOOL\tClose_Poke_Connection( void );\n\n\t\t//\n\t\t// static members\n\t\t//\n\n\t\t/*.....................................................................\n\t\tUser callback - called upon receipt of incoming data (static member!)\n\t\t.....................................................................*/\n\t\tstatic BOOL (CALLBACK *callback) (\n\n\t\t\tLPBYTE pointer,\t\t// pointer to received data\n\t\t\tlong length\t\t\t\t// if >0 length of received data\n\t\t\t\t\t\t\t\t\t\t// if <0\n\t\t\t\t\t\t\t\t\t\t//\t-1 == client connect detected\n\t\t\t\t\t\t\t\t\t\t// -2 == client disconnect detected\n\t\t\t);\n\n\t\t/*.....................................................................\n\t\tDDE callback, called when DDEML has an event for us\n\t\t.....................................................................*/\n\t\tstatic HDDEDATA CALLBACK dde_callback(\n\n\t\t\tUINT  uType,\t\t// transaction type\n\t\t\tUINT  uFmt,\t\t\t// clipboard data format\n\t\t\tHCONV  hconv,\t\t// handle of the conversation\n\t\t\tHSZ  hsz1,\t\t\t// handle of a string\n\t\t\tHSZ  hsz2,\t\t\t// handle of a string\n\t\t\tHDDEDATA  hdata,\t// handle of a global memory object\n\t\t\tDWORD  dwData1,\t// transaction-specific data\n\t\t\tDWORD  dwData2 \t// transaction-specific data\n\t\t\t);\n\t\tHANDLE\tinstance;\t// this application's instance\n\t\tHWND\t\thwnd;\t\t\t// valid window handle\n\n\t\t/*.....................................................................\n\t\tmember variables\n\t\t.....................................................................*/\n\n\t\tstatic DWORD id_inst;\t\t\t// instance identifier set by DdeInitialize\n\t\tstatic BOOL\tprocess_pokes;\t\t// controls response to pokes\n\t\tstatic char ascii_name[32];\t// name of server\n\n\t\t//\n\t\t// non-static member variables\n\t\t//\n\n\t\tHSZ remote_name; \t\t// string handle for remote server name\n\t\tHSZ local_name; \t\t// string handle for local server name\n\t\tHSZ system_topic;\t\t// string handle for the \"system\" topic\n\t\tHSZ poke_topic;\t\t// string handle for poking data to server topic\n\t\tHSZ poke_item;\t\t\t// string handle for poking data to server item\n\n\t\tHCONV conv_handle;   // conversation handle\n\t\tBOOL\tdde_error;\t\t// error flag\n\n};\n\n#endif\n\n\u001a"
  },
  {
    "path": "REDALERT/DEBUG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DEBUG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DEBUG.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 18, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Self_Regulate -- Regulates the logic timer to result in smooth animation.                 *\n *   Debug_Key -- Debug mode keyboard processing.                                              *\n *   Bench_Time -- Convert benchmark timer into descriptive string.                            *\n *   Benchmarks -- Display the performance tracking benchmarks.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"vortex.h\"\n#include\t<stdarg.h>\n\n\n#ifdef CHEAT_KEYS\n\n\nstatic CDTimerClass<SystemTimerClass> DebugTimer;\n\nint VortexFrame = -1;\n\n/***********************************************************************************************\n * Debug_Key -- Debug mode keyboard processing.                                                *\n *                                                                                             *\n *    If debugging is enabled, then this routine will be called for every keystroke that the   *\n *    game doesn't recognize. These extra keys usually perform some debugging function.        *\n *                                                                                             *\n * INPUT:   input -- The key code that was pressed.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Debug_Key(unsigned input)\n{\n\tstatic int map_x = -1;\n\tstatic int map_y = -1;\n\tstatic int map_width = -1;\n\tstatic int map_height = -1;\n\n\tif (!input || input & KN_BUTTON) return;\n\n\t/*\n\t**\tProcessing of normal keystrokes.\n\t*/\n\tif (Debug_Flag) {\n\n\t\tswitch (input) {\n\n\t\t\tcase KN_BACKSPACE:\n\n\t\t\t\tif (ChronalVortex.Is_Active()) {\n\t\t\t\t\tChronalVortex.Disappear();\n\t\t\t\t} else {\n\t\t\t\t\tint xxxx = Get_Mouse_X() + Map.TacPixelX;\n\t\t\t\t\tint yyyy = Get_Mouse_Y() + Map.TacPixelY;\n\t\t\t\t\tCELL cell = Map.DisplayClass::Click_Cell_Calc(xxxx,yyyy);\n\t\t\t\t\tChronalVortex.Appear ( Cell_Coord (cell) );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#ifdef WIN32\n\t\t\tcase KN_J:\n\t\t\t\tDebug_MotionCapture = true;\n\t\t\t\tbreak;\n\n#ifdef OBSOLETE\n\t\t\tcase KN_K:\n\t\t\t\t/*\n\t\t\t\t** time to create a screen shot using the PCX code (if it works)\n\t\t\t\t*/\n\t\t\t\tif (!Debug_MotionCapture) {\n\t\t\t\t\tGraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\t\t\t\t\tCDFileClass file;\n\t\t\t\t\tchar filename[30];\n\n\t\t\t\t\tSeenBuff.Blit(temp_page);\n\t\t\t\t\tfor (int lp = 0; lp < 99; lp ++) {\n\t\t\t\t\t\tsprintf(filename, \"scrsht%02d.pcx\", lp);\n\t\t\t\t\t\tfile.Set_Name(filename);\n\t\t\t\t\t\tif (!file.Is_Available()) break;\n\t\t\t\t\t}\n\n\t\t\t\t\tfile.Cache(200000);\n\t\t\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\t\t\tSound_Effect(VOC_BEEP);\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\n#endif\n\n\t\t\tcase KN_P:\n\t\t\t\t{\n\t\t\t\t\tfor (SpecialWeaponType spc = SPC_FIRST; spc < SPC_COUNT; spc++) {\n\t\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Enable(true, true);\n\t\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Forced_Charge(true);\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, spc);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_I:\n\t\t\t\t{\n\t\t\t\t\tMap.Flash_Power();\n\t\t\t\t\tMap.Flash_Money();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_O:\n\t\t\t\t{\n\t\t\t\t\tAircraftClass * air = new AircraftClass(AIRCRAFT_HIND, PlayerPtr->Class->House);\n\t\t\t\t\tif (air) {\n\t\t\t\t\t\tair->Height = 0;\n\t\t\t\t\t\tair->Unlimbo(Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()), DIR_N);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_B:\n\t\t\t\t{\n\t\t\t\t\tAircraftClass * air = new AircraftClass(AIRCRAFT_LONGBOW, PlayerPtr->Class->House);\n\t\t\t\t\tif (air) {\n\t\t\t\t\t\tair->Height = 0;\n\t\t\t\t\t\tair->Unlimbo(Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()), DIR_N);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_GRAVE:\n\t\t\t\t{\n\t\t\t\t\tWarheadType warhead = Random_Pick(WARHEAD_HE, WARHEAD_FIRE);\n\t\t\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());\n\t\t\t\t\tint damage = 1000;\n\t\t\t\t\tnew AnimClass(Combat_Anim(damage, warhead, Map[coord].Land_Type()), coord);\n\t\t\t\t\tExplosion_Damage(coord, damage, NULL, warhead);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_C:\n\t\t\t\tDebug_Cheat = (Debug_Cheat == false);\n\t\t\t\tPlayerPtr->IsRecalcNeeded = true;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis placement might affect any prerequisite requirements for construction\n\t\t\t\t**\tlists. Update the buildable options accordingly.\n\t\t\t\t*/\n\t\t\t\tif (!ScenarioInit) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\tBuildings.Ptr(index)->Update_Buildables();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_Z|(int)KN_ALT_BIT:\n\t\t\t\tif (map_x == -1) {\n\t\t\t\t\tmap_x = Map.MapCellX;\n\t\t\t\t\tmap_y = Map.MapCellY;\n\t\t\t\t\tmap_width = Map.MapCellWidth;\n\t\t\t\t\tmap_height = Map.MapCellHeight;\n\t\t\t\t\tMap.MapCellX = 1;\n\t\t\t\t\tMap.MapCellY = 1;\n\t\t\t\t\tMap.MapCellWidth = MAP_CELL_W-2;\n\t\t\t\t\tMap.MapCellHeight = MAP_CELL_H-2;\n\t\t\t\t} else {\n\t\t\t\t\tMap.MapCellX = map_x;\n\t\t\t\t\tMap.MapCellY = map_y;\n\t\t\t\t\tMap.MapCellWidth = map_width;\n\t\t\t\t\tMap.MapCellHeight = map_height;\n\t\t\t\t\tmap_x = -1;\n\t\t\t\t\tmap_y = -1;\n\t\t\t\t\tmap_width = -1;\n\t\t\t\t\tmap_height = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_M:\n\t\t\t\tif (Debug_Flag) {\n\t\t\t\t\tif (MonoClass::Is_Enabled()) {\n\t\t\t\t\t\tMonoClass::Disable();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMonoClass::Enable();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_W|(int)KN_ALT_BIT:\n\t\t\t\tPlayerPtr->Flag_To_Win();\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_L|(int)KN_ALT_BIT:\n\t\t\t\tPlayerPtr->Flag_To_Lose();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DELETE:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\t//CurrentObject[0]->Detach_All();\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t((BuildingClass *)CurrentObject[0])->Sell_Back(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tObjectClass * object = CurrentObject[0];\n\t\t\t\t\t\tobject->Unselect();\n\t\t\t\t\t\tobject->Limbo();\n\t\t\t\t\t\tdelete object;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (int)KN_DELETE|(int)KN_SHIFT_BIT:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.Recalc();\n\t\t\t\t\tint damage = 50;\n\t\t\t\t\tCurrentObject[0]->Take_Damage(damage, 0, WARHEAD_SA);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_INSERT:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMap.PendingObject = &CurrentObject[0]->Class_Of();\n\t\t\t\t\tif (Map.PendingObject) {\n\t\t\t\t\t\tMap.PendingHouse = CurrentObject[0]->Owner();\n\t\t\t\t\t\tMap.PendingObjectPtr = Map.PendingObject->Create_One_Of(HouseClass::As_Pointer(Map.PendingHouse));\n\t\t\t\t\t\tif (Map.PendingObjectPtr) {\n\t\t\t\t\t\t\tMap.Set_Cursor_Pos();\n\t\t\t\t\t\t\tMap.Set_Cursor_Shape(Map.PendingObject->Occupy_List());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase KN_LBRACKET:\n\t\t\tcase KN_F11:\n\t\t\t\tif (MonoPage == DMONO_FIRST) {\n\t\t\t\t\tMonoPage = DMonoType(DMONO_COUNT-1);\n\t\t\t\t} else {\n\t\t\t\t\tMonoPage = DMonoType(MonoPage - 1);\n\t\t\t\t}\n\t\t\t\tDebugTimer = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RBRACKET:\n\t\t\tcase KN_F12:\n\t\t\t\tMonoPage = DMonoType(MonoPage + 1);\n\t\t\t\tif (MonoPage == DMONO_COUNT) {\n\t\t\t\t\tMonoPage = DMONO_FIRST;\n\t\t\t\t}\n\t\t\t\tDebugTimer = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_V:\n\t\t\tcase KN_F3:\n\t\t\t\tDebug_Icon = (Debug_Icon == false);\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tReveal entire map to player.\n\t\t\t*/\n//\t\t\tcase KN_F4:\n//\t\t\t\tif (Session.Type == GAME_NORMAL) {\n//\t\t\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n//\t\t\t\t\tMap.Flag_To_Redraw(true);\n//\t\t\t\t}\n//\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tShows sight and fire range in the form of circles emanating from the currently\n\t\t\t**\tselected unit. The white circle is for sight range, the red circle is for\n\t\t\t**\tfire range.\n\t\t\t*/\n\t\t\tcase KN_F7:\n\t\t\t\tif (CurrentObject.Count() && CurrentObject[0]->Is_Techno()) {\n\t\t\t\t\tTechnoTypeClass const & ttype = (TechnoTypeClass const &)CurrentObject[0]->Class_Of();\n\t\t\t\t\tint sight = ((int)ttype.SightRange)<<8;\n\t\t\t\t\tint weapon = 0;\n\t\t\t\t\tif (ttype.PrimaryWeapon != NULL) weapon = ttype.PrimaryWeapon->Range;\n\t\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\t\tCOORDINATE center = CurrentObject[0]->Center_Coord();\n\t\t\t\t\tCOORDINATE center2 = CurrentObject[0]->Fire_Coord(0);\n\n\t\t\t\t\tfor (int r = 0; r < 255; r += 10) {\n\t\t\t\t\t\tint\tx,y,x1,y1;\n\t\t\t\t\t\tDirType r1 = (DirType)r;\n\t\t\t\t\t\tDirType r2 = (DirType)((r+10) & 0xFF);\n\n\t\t\t\t\t\tif (Map.Coord_To_Pixel(Coord_Move(center, r1, sight), x, y)) {\n\t\t\t\t\t\t\tMap.Coord_To_Pixel(Coord_Move(center, r2, sight), x1, y1);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(x, y+8, x1, y1+8, WHITE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Map.Coord_To_Pixel(Coord_Move(center2, r1, weapon), x, y)) {\n\t\t\t\t\t\t\tMap.Coord_To_Pixel(Coord_Move(center2, r2, weapon), x1, y1);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(x, y+8, x1, y1+8, RED);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_F4 | (int)KN_CTRL_BIT):\n\t\t\t\tDebug_Unshroud = (Debug_Unshroud == false);\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Bench_Time -- Convert benchmark timer into descriptive string.                              *\n *                                                                                             *\n *    This routine will take the values of the benchmark timer specified and build a string    *\n *    that displays the average time each event consumed as well as the ranking of how much    *\n *    time that event took (total) during the tracking duration (one second?).                 *\n *                                                                                             *\n * INPUT:   btype -- The benchmark to convert to a descriptive string.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the descriptive string of the benchmark specified.       *\n *                                                                                             *\n * WARNINGS:   The value returned is a pointer to a static buffer. As such, it is only valid   *\n *             until the next time that this routine is called.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic char const * Bench_Time(BenchType btype)\n{\n\tstatic char buffer[32];\n\n\tint rootcount = Benches[BENCH_GAME_FRAME].Count();\n\tif (rootcount == 0) rootcount = 1;\n\tint roottime = Benches[BENCH_GAME_FRAME].Value();\n\tint count = Benches[btype].Count();\n\tint time = Benches[btype].Value();\n\tif (count > 0 && count * time > roottime * rootcount) time = roottime / count;\n\tint percent = 0;\n\tif (roottime != 0 && rootcount != 0) {\n\t\tpercent = ((count * time) * 99) / (roottime * rootcount);\n\t}\n\tif (percent > 99) percent = 99;\n\tsprintf(buffer, \"%-2d%% %7d\", percent, time);\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Benchmarks -- Display the performance tracking benchmarks.                                  *\n *                                                                                             *\n *    This will display the benchmarks for the various processes that are being tracked. The   *\n *    display will indicate the fraction that each process is consuming out of the entire      *\n *    process time as well as the time consumed by each individual event. The total fraction   *\n *    is useful for determing what should be optimized. The individual time is useful for      *\n *    guaging the effectiveness of optimization changes.                                       *\n *                                                                                             *\n * INPUT:   mono  -- Pointer to the monochrome screen that the display will use.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Benchmarks(MonoClass * mono)\n{\n\tstatic bool _first = true;\n\tif (_first) {\n\t\t_first = false;\n\t\tmono->Clear();\n\t\tmono->Set_Cursor(0, 0);\n\t\tmono->Print(Text_String(TXT_DEBUG_PERFORMANCE));\n\t\tif (Benches == NULL) {\n\t\t\tmono->Set_Cursor(20, 15);\n\t\t\tmono->Printf(TXT_NO_PENTIUM);\n\t\t}\n\t}\n\n\tif (Benches != NULL) {\n\t\tmono->Set_Cursor(1, 2);mono->Printf(\"%s\", Bench_Time(BENCH_FINDPATH));\n\t\tmono->Set_Cursor(1, 4);mono->Printf(\"%s\", Bench_Time(BENCH_GREATEST_THREAT));\n\t\tmono->Set_Cursor(1, 6);mono->Printf(\"%s\", Bench_Time(BENCH_AI));\n\t\tmono->Set_Cursor(1, 8);mono->Printf(\"%s\", Bench_Time(BENCH_PCP));\n\t\tmono->Set_Cursor(1, 10);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_OBJECT));\n\t\tmono->Set_Cursor(1, 12);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_CELL));\n\t\tmono->Set_Cursor(1, 14);mono->Printf(\"%s\", Bench_Time(BENCH_EVAL_WALL));\n\t\tmono->Set_Cursor(1, 16);mono->Printf(\"%s\", Bench_Time(BENCH_MISSION));\n\n\t\tmono->Set_Cursor(14, 2);mono->Printf(\"%s\", Bench_Time(BENCH_CELL));\n\t\tmono->Set_Cursor(14, 4);mono->Printf(\"%s\", Bench_Time(BENCH_OBJECTS));\n\t\tmono->Set_Cursor(14, 6);mono->Printf(\"%s\", Bench_Time(BENCH_ANIMS));\n\n\t\tmono->Set_Cursor(27, 2);mono->Printf(\"%s\", Bench_Time(BENCH_PALETTE));\n\n\t\tmono->Set_Cursor(40, 2);mono->Printf(\"%s\", Bench_Time(BENCH_GSCREEN_RENDER));\n\t\tmono->Set_Cursor(40, 4);mono->Printf(\"%s\", Bench_Time(BENCH_SIDEBAR));\n\t\tmono->Set_Cursor(40, 6);mono->Printf(\"%s\", Bench_Time(BENCH_RADAR));\n\t\tmono->Set_Cursor(40, 8);mono->Printf(\"%s\", Bench_Time(BENCH_TACTICAL));\n\t\tmono->Set_Cursor(40, 10);mono->Printf(\"%s\", Bench_Time(BENCH_POWER));\n\t\tmono->Set_Cursor(40, 12);mono->Printf(\"%s\", Bench_Time(BENCH_SHROUD));\n\t\tmono->Set_Cursor(40, 14);mono->Printf(\"%s\", Bench_Time(BENCH_TABS));\n\t\tmono->Set_Cursor(40, 16);mono->Printf(\"%s\", Bench_Time(BENCH_BLIT_DISPLAY));\n\n\t\tmono->Set_Cursor(66, 2);mono->Printf(\"%7d\", Benches[BENCH_RULES].Value());\n\t\tmono->Set_Cursor(66, 4);mono->Printf(\"%7d\", Benches[BENCH_SCENARIO].Value());\n\n\t\tfor (BenchType index = BENCH_FIRST; index < BENCH_COUNT; index++) {\n\t\t\tif (index != BENCH_RULES && index != BENCH_SCENARIO) Benches[index].Reset();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Self_Regulate -- Regulates the logic timer to result in smooth animation                    *\n *                                                                                             *\n *    The self regulation process checks the number of frames displayed                        *\n *    per second and from this determines the amount of time to devote                         *\n *    to internal logic processing. By adjusting the time allotted to                          *\n *    internal processing, smooth animation can be maintained.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   In order for this routine to work properly it MUST be                           *\n *             called every display loop.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1991 JLB : Created.                                                                 *\n *   07/05/1994 JLB : Handles new monochrome system.                                           *\n *=============================================================================================*/\n#define\tUPDATE_INTERVAL\tTIMER_SECOND\nvoid Self_Regulate(void)\n{\n\tstatic ObjectClass * _lastobject = 0;\n\tstatic bool _first=true;\n\n\tif (DebugTimer == 0) {\n\t\tDebugTimer = UPDATE_INTERVAL;\n\n\t\tif (MonoClass::Is_Enabled()) {\n\t\t\tif (_first) {\n\t\t\t\t_first = false;\n\t\t\t\tfor (DMonoType index = DMONO_FIRST; index < DMONO_COUNT; index++) {\n\t\t\t\t\tMonoArray[index].Clear();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAlways update the stress tracking mono display even if it\n\t\t\t**\tcurrently isn't visible.\n\t\t\t*/\n\t\t\tLogic.Debug_Dump(&MonoArray[DMONO_STRESS]);\n\n\t\t\tMonoClass * mono = &MonoArray[MonoPage];\n\t\t\tmono->Set_Default_Attribute(MonoClass::NORMAL);\n\t\t\tmono->View();\n\n\t\t\tswitch (MonoPage) {\n\t\t\t\tcase DMONO_EVENTS:\n\t\t\t\t\tBenchmarks(mono);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_OBJECT:\n\t\t\t\t\tmono->Clear();\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay the status of the currently selected object.\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\t\t_lastobject = CurrentObject[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && !_lastobject->IsActive) {\n\t\t\t\t\t\t_lastobject = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject) {\n\t\t\t\t\t\t_lastobject->Debug_Dump(mono);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_STRESS:\n#ifdef OBSOLETE\n\t\t\t\t\tmono->Set_Cursor(0, 20);\n\t\t\t\t\tmono->Printf(\n\t\t\t\t\t\t\"Heap size:%10ld \\r\"\n\t\t\t\t\t\t\"Largest:  %10ld \\r\"\n\t\t\t\t\t\t\"Ttl Free: %10ld \\r\"\n\t\t\t\t\t\t\"Frag:     %10ld \\r\",\n\t\t\t\t\t\tHeap_Size(MEM_NORMAL),\n\t\t\t\t\t\tRam_Free(MEM_NORMAL),\n\t\t\t\t\t\tTotal_Ram_Free(MEM_NORMAL),\n\t\t\t\t\t\tTotal_Ram_Free(MEM_NORMAL)-Ram_Free(MEM_NORMAL)\n\t\t\t\t\t);\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase DMONO_HOUSE:\n\t\t\t\t\tmono->Clear();\n\n\t\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\t\t_lastobject = CurrentObject[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && !_lastobject->IsActive) {\n\t\t\t\t\t\t_lastobject = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (_lastobject && _lastobject->Is_Techno()) {\n\t\t\t\t\t\t((TechnoClass *)_lastobject)->House->Debug_Dump(mono);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmono->Set_Cursor(0, 0);\n\t\t}\n\t}\n}\n#endif\n"
  },
  {
    "path": "REDALERT/DEBUG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#define TXT_CLEAR_MAP            \t0x3e8 \t// Clear the map\n#define TXT_INHERIT_MAP          \t0x3e9 \t// Inherit previous map\n#define TXT_SPECIAL_OPTIONS      \t0x3ea \t// Select Special Options\n#define TXT_VISIBLE_TARGET       \t0x3eb \t// Targeting flash visible to\n#define TXT_TREE_TARGET          \t0x3ec \t// Allow targeting of trees.\n#define TXT_MCV_DEPLOY           \t0x3ed \t// Allow undeploy of\n#define TXT_SMART_DEFENCE        \t0x3ee \t// Employ smarter self defense\n#define TXT_SLOW_BUILD           \t0x3ef \t// Moderate production speed.\n#define TXT_THREE_POINT          \t0x3f0 \t// Use three point turn logic.\n#define TXT_TIBERIUM_GROWTH      \t0x3f1 \t// Ore will grow.\n#define TXT_TIBERIUM_SPREAD      \t0x3f2 \t// Ore will spread.\n#define TXT_ROAD_PIECES          \t0x3f3 \t// Disable building \"bib\"\n#define TXT_SCATTER              \t0x3f4 \t// Allow running from\n#define TXT_SHOW_NAMES           \t0x3f5 \t// Show true object names.\n#define TXT_DEFENDER_ADVANTAGE   \t0x3f6 \t// Defender has the advantage.\n#define TXT_SEPARATE_HELIPAD     \t0x3f7 \t// Allow separate helipad\n#define TXT_PASSWORD_CAPTION     \t0x3f8 \t// Password Request\n#define TXT_PASSWORD_MESSAGE     \t0x3f9 \t// Enter Red Alert access code\n#define TXT_PASSWORD_ERROR       \t0x3fa \t// Access code error detected.\n#define TXT_TRY_AGAIN            \t0x3fb \t// Try Again\n#define TXT_MINE_AWARE           \t0x3fc \t// Friendly units avoid\n#define TXT_TRIGGER_EDITOR       \t0x3fd \t// Trigger Editor\n#define TXT_TRIGGER_JUST_EVENT   \t0x3fe \t// Just This Event\n#define TXT_TRIGGER_AND          \t0x3ff \t// ... and ...\n#define TXT_TRIGGER_OR           \t0x400 \t// ... or ...\n#define TXT_TRIGGER_LINKED       \t0x401 \t// ... linked ...\n#define TXT_TRIGGER_JUST_ACTION  \t0x402 \t// Just This Action\n#define TXT_TEAM_EDIT            \t0x403 \t// Team Editor\n#define TXT_SELLABLE             \t0x404 \t// Sellable\n#define TXT_REBUILD              \t0x405 \t// Rebuild\n#define TXT_SPEED_BUILD          \t0x406 \t// Building constructin time\n#define TXT_SCENARIO_ERRORx      \t0x407 \t// Scenario authentication\n#define TXT_DEBUG_STRESS         \t0x408 \t// Frames:F/R:CPU:F/R:\n#define TXT_DEBUG_VEHICLE        \t0x409 \t// Full\n#define TXT_DEBUG_INFANTRY       \t0x40a \t// Full\n#define TXT_DEBUG_SHIP           \t0x40b \t// Full\n#define TXT_DEBUG_BUILDING       \t0x40c \t// Full\n#define TXT_DEBUG_PERFORMANCE    \t0x40d \t//  Game Objects  Drawing  \n#define TXT_DEBUG_AIRCRAFT       \t0x40e \t// Full\n#define TXT_DEBUG_HOUSE          \t0x40f \t// Full Name:Act\n#define TXT_NO_PENTIUM           \t0x410 \t// ****************************\n#define TXT_SIZE_MAP             \t0x411 \t// Size Map\n#define TXT_TRUCK_CRATE          \t0x412 \t// Trucks drop crate when\n"
  },
  {
    "path": "REDALERT/DEFINES.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DEFINES.H 4     3/07/97 9:55a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DEFINES.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef DEFINES_H\n#define DEFINES_H\n\n/**********************************************************************\n**\tLanguage control: define the desired language for this build.\n*/\n//#define ENGLISH 1\n//#define FRENCH 1\n//#define GERMAN 1\n//#define SPAIN 1\t(never used)\n//\t- Language define is now passed in from the makefile. -\n\n/**********************************************************************\n**\tControls the nature of the game and its abilities. Only define\n**\tone of these values.\n**\n**\tInternal version -- complete with scenario editor.\n**\tPlaytest version -- no editor but does have minimal cheat keys.\n**\tRelease version -- no editor or cheat keys -- all debugging info removed.\n*/\n//#define\tINTERNAL_VERSION\n//#define\tPLAYTEST_VERSION\n#define\tRELEASE_VERSION\n\n/**********************************************************************\n** ColinM\n** Set this to enable dongle protection\n*/\n//#define DONGLE\n\n\n// Enable 640x400 VQ movie capability in WIN32 mode\n#define MOVIE640\n\n\n//#if (GERMAN | FRENCH)\n//#define\tBOGUSCD\n//#endif\n\n#define\tFIXIT_SCORE_CRASH\t\t\t// Fixes score screen crash\n#define\tFIXIT_MULTI_SAVE\t\t\t// Fixes multiplayer save/load\n#define\tFIXIT_NO_COMP_ALLY\t\t// Prevent ally with computer\n#define\tFIXIT_DESTNET\t\t\t\t// Fixes -destnet parameter in Win95\n#define\tFIXIT_RANDOM_GAME\t\t\t// Fixes random seed at start of multiplayer games\n#define\tFIXIT_FORCE_CD\t\t\t\t// Forces correct CD load after scenario #1\n#define\tFIXIT_IP_CRASH\t\t\t\t// Fixes crash if internet game aborts too quickly\n#define\tFIXIT_IP_STATS\t\t\t\t// Fixes so vessels show up in internet stat info\n#define\tFIXIT_NAME_OVERRIDE     // Allows changing of unit names\n#define\tFIXIT_RADAR_JAMMED\t\t// Fixes unjamming by merely starting to build a radar facility\n#define\tFIXIT_CAPTURE_BIB\t\t\t// Fixes so that if fake is captured, you still can't build off of it.\n#define\tFIXIT_BASE_ANNOUNCE\t\t// Fixes so player controlled buildings count as base when attacked.\n#define\tFIXIT_APTIVA_MODEM\t\t// Fixes crash with Aptiva modem.\n#define\tFIXIT_FLAG_CHECK\t\t\t// Disable placing building over a flag.\n\n#define\tFIXIT_ANTS              // Adds Ant Units\n\n#define\tFIXIT_CSII\t\t\t\t\t// Adds Aftermath CounterStrike II units\n//\tajw 9/28/98 - Note about FIXIT_CSII. Changes seem to have been made for Aftermath (\"Counterstrike II\") that: a) were\n//\tbug fixes that should never be rolled back, b) change the nature of the game, at least in multi-player. This meant\n//\tthat the \"Red Alert\" executable ( == Counterstrike executable ) could no longer be built. Apparently, at the time,\n//\tthis was justified, as it was believed that no further patches to the RA executable would ever be necessary.\n//\tGiven that Denzil's DVD changes and my WOLAPI integration are essentially a patch, we've got a problem.\n//\tWe've decided to level the field and make sure every who gets or patches to the new version of Red Alert, CS, AM, (and\n//\ttheir DVD equivalent(s)) will have the same executable. So we're assuming that all of the FIXIT_CSII changes are \n//\tpermanent (as, in fact, all prior FIXIT_'s are - makes me wonder why the old non-compiling code has to hang around\n//\tforever), and fixing the code so that the assumption \"this is an Aftermath game\" is no longer hard-coded, but can \n//\tchange at runtime. (Which is what should have been done when Aftermath was created.)\n//\t<This goes for the following three defines as well.>\n#define\tFIXIT_CARRIER\t\t\t\t// Adds Aftermath aircraft carrier\n#define\tFIXIT_PHASETRANSPORT\t\t// Adds Aftermath cloaking APC\n//\tajw - Discovered that engineer changing fields were specifically left out of aftrmath.ini, thus this has no effect.\n//\tEngineer changes (and other game rule changes) are in mplayer.ini, which was loaded before aftermath-only mplayer games.\n#define\tFIXIT_ENGINEER\t\t\t\t// Adds Engineer rules.ini overrides\n\n//#define\tFIXIT_FAST_LOAD\t\t\t// Enables faster INI loading\n\n// These fixes will cause the game to go out of sync.\n//#define\tFIXIT_ENGINEER_CAPTURE\t// If building not allied, will still capture if engineer not allied with building.\n//#define\tFIXIT_HELI_LANDING\t// Fixes so new helicopters land at free helipad\n//#define\tFIXIT_MINE_PASSABLE\t// Fixes units not driving onto mines\n\n/* Turn on these changes for the 1.08 patch */\n#define FIXIT_PATCH_108\n\n#ifdef FIXIT_PATCH_108\n#define STEVES_LOAD_OVERRIDE // Allows loading of CONQUER.ENG instead of from mix file.\n#define FIXIT_DIFFICULTY\t\t// Fixes no difficulty level for CStrike missions\n#define FIXIT_VERSION\t// Fixes version playability for 1.04, 1.07 & 1.08\n#define FIXIT_MODEM_LOAD_CRASH // Fixes crash after loading a modem game when names are the same\n#define FIXIT_PHONELIST_CRASH // Fixes crash when clicking on an empty phonelist\n#endif\n\n//\tDenotes changes made for version 3 - reunification of all existing versions and undoing of Aftermath divergence. - ajw\n#define FIXIT_VERSION_3\n#define DVD\n\n// Define DVD to turn on RADVD additions/changes - Denzil\n#ifdef DVD\n//#define INTERNET_OFF\n//#define MPEGMOVIE\t//PG\n//#define MCIMPEG\n#endif\n\n// Test to see if partial object drawing is any faster.\n//#define\tPARTIAL\n#define\tSORTDRAW\n\n/**********************************************************************\n**\tIf the scenario editor to to be active in this build then uncomment\n**\tthe following #define line.\n*/\n#ifdef INTERNAL_VERSION\n#define SCENARIO_EDITOR\n#endif\n\n\n/**********************************************************************\n**\tThis define enables the full set of cheat keys and special\n**\tcommand line options.\n*/\n#if defined(INTERNAL_VERSION) || defined(PLAYTEST_VERSION)\n#define CHEAT_KEYS\n#endif\n\n\n/**********************************************************************\n**\tIf this is defined, the special Virgin limited cheat keys\n**\tare enabled. This allows the \"cheat\" parameter and then only\n**\tallows the ALT-W to win the mission.\n*/\n#ifdef PLAYTEST_VERSION\n#define VIRGIN_CHEAT_KEYS\n#endif\n\n\n/**********************************************************************\n**\tIf this is defined, then the network code will be enabled.\n*/\n#define NETWORK\n#define TIMING_FIX\t1\n\n\n/**********************************************************************\n** Define this to 1 to enable MPath-specific code.  Do not define\n** TEN at the same time.\n*/\n#define MPATH\t0\n\n\n/**********************************************************************\n** Define this to 1 to enable TEN-specific code.  Do not define\n** MPATH at the same time.\n*/\n#define TEN\t\t0\n\n\n/**********************************************************************\n**\tIf this is defined, the DoList is \"mirrored\", for memory trasher\n** detection.\n*/\n#ifdef CHEAT_KEYS\n//#define MIRROR_QUEUE\n#endif\n\n\n/**********************************************************************\n**\tThis define tells the Version Number class to use the date/time-based\n** version numbering system.  If this define is not set, the actual\n** major/minor version numbers will be used.\n*/\n//#define DEV_VERSION\n//#define DEV_VER_NAME\n\n\n/**********************************************************************\n** This define enables a special additional foreign-version-number\n** after the other version number, for display purposes only.\n*/\n#if !defined(ENGLISH)\n#define\tFOREIGN_VERSION\n#define\tFOREIGN_VERSION_NUMBER\t7\n#endif\n\n\n/**********************************************************************\n** This is the multiplier factor to convert low resution coordinates\n**\tinto their actual resolution counterparts.\n*/\n#ifdef WIN32\n#define RESFACTOR\t2\n#else\n//#undef SCENARIO_EDITOR\n#define RESFACTOR 1\n#endif\n\n\n#define SIDEBAR_WID\t80\n\n\n/**********************************************************************\n**\tOptional parameter control for special options.\n*/\n\n/*\n**\tEnable the set of limited cheat key options.\n*/\n#ifdef VIRGIN_CHEAT_KEYS\n#define\tPARM_PLAYTEST\t\t0xF7DDC227\t\t// \"PLAYTEST\"\n#endif\n\n/*\n**\tEnable the full set of cheat key options.\n*/\n#ifdef CHEAT_KEYS\n#ifndef PARM_PLAYTEST\n#define\tPARM_PLAYTEST\t\t0xF7DDC227\t\t// \"PLAYTEST\"\n#endif\n#endif\n\n\n#define\tPARM_INSTALL\t\t0xD95C68A2\t\t//\t\"FROMINSTALL\"\n\n\n//\n// Allow normal game play in the MPath version\n//\n#if(MPATH)\n#define\tPARM_ALLOW_SOLO\t0xc901c9db\t// AllowSoloPlayOptions\n#endif\n\n//\n// Allow normal game play in the TEN version\n//\n#if(TEN)\n#define\tPARM_ALLOW_SOLO\t0xc901c9db\t// AllowSoloPlayOptions\n#endif\n\n/**********************************************************************\n**\tDefines for verifying free disk space\n*/\n#define\tINIT_FREE_DISK_SPACE\t\t8388608\n#define\tSAVE_GAME_DISK_SPACE\t\t (INIT_FREE_DISK_SPACE - (1024*4096))\n//#define\tSAVE_GAME_DISK_SPACE\t\t 100000\n\n\n/**********************************************************************\n**\tThis is the complete list of VQs allowed to be played in the game.\n*/\ntypedef enum VQType {\n\tVQ_NONE=-1,\n\tVQ_AAGUN,\n\tVQ_MIG,\n\tVQ_SFROZEN,\n\tVQ_AIRFIELD,\n\tVQ_BATTLE,\n\tVQ_BMAP,\n\tVQ_BOMBRUN,\n\tVQ_DPTHCHRG,\n\tVQ_GRVESTNE,\n\tVQ_MONTPASS,\n\tVQ_MTNKFACT,\n\tVQ_CRONTEST,\n\tVQ_OILDRUM,\n\tVQ_ALLYEND,\n\tVQ_RADRRAID,\n\tVQ_SHIPYARD,\n\tVQ_SHORBOMB,\n\tVQ_SITDUCK,\n\tVQ_SLNTSRVC,\n\tVQ_SNOWBASE,\n\tVQ_EXECUTE,\n\tVQ_TITLE,\t\t\t\t// Low res.\n\tVQ_NUKESTOK,\n\tVQ_V2ROCKET,\n\tVQ_SEARCH,\n\tVQ_BINOC,\n\tVQ_ELEVATOR,\n\tVQ_FROZEN,\n\tVQ_MCV,\n\tVQ_SHIPSINK,\n\tVQ_SOVMCV,\n\tVQ_TRINITY,\n\tVQ_ALLYMORF,\n\tVQ_APCESCPE,\n\tVQ_BRDGTILT,\n\tVQ_CRONFAIL,\n\tVQ_STRAFE,\n\tVQ_DESTROYR,\n\tVQ_DOUBLE,\n\tVQ_FLARE,\n\tVQ_SNSTRAFE,\n\tVQ_LANDING,\n\tVQ_ONTHPRWL,\n\tVQ_OVERRUN,\n\tVQ_SNOWBOMB,\n\tVQ_SOVCEMET,\n\tVQ_TAKE_OFF,\n\tVQ_TESLA,\n\tVQ_SOVIET8,\n\tVQ_SPOTTER,\n\tVQ_SCENE1,\n\tVQ_SCENE2,\n\tVQ_SCENE4,\n\tVQ_SOVFINAL,\n\tVQ_ASSESS,\n\tVQ_SOVIET10,\n\tVQ_DUD,\n\tVQ_MCV_LAND,\n\tVQ_MCVBRDGE,\n\tVQ_PERISCOP,\n\tVQ_SHORBOM1,\n\tVQ_SHORBOM2,\n\tVQ_SOVBATL,\n\tVQ_SOVTSTAR,\n\tVQ_AFTRMATH,\n\tVQ_SOVIET11,\n\tVQ_MASASSLT,\n\tVQ_REDINTRO,\t\t// High res\n\tVQ_SOVIET1,\n\tVQ_SOVIET2,\n\tVQ_SOVIET3,\n\tVQ_SOVIET4,\n\tVQ_SOVIET5,\n\tVQ_SOVIET6,\n\tVQ_SOVIET7,\n\tVQ_INTRO_MOVIE,\n\tVQ_AVERTED,\n\tVQ_COUNTDWN,\n\tVQ_MOVINGIN,\n\tVQ_ALLIED10,\n\tVQ_ALLIED12,\n\tVQ_ALLIED5,\n\tVQ_ALLIED6,\n\tVQ_ALLIED8,\n\tVQ_TANYA1,\n\tVQ_TANYA2,\n\tVQ_ALLY10B,\n\tVQ_ALLY11,\n\tVQ_ALLY14,\n\tVQ_ALLY9,\n\tVQ_SPY,\n\tVQ_TOOFAR,\n\tVQ_SOVIET12,\n\tVQ_SOVIET13,\n\tVQ_SOVIET9,\n\tVQ_BEACHEAD,\n\tVQ_SOVIET14,\n\tVQ_SIZZLE,\n\tVQ_SIZZLE2,\n\tVQ_ANTEND,\n\tVQ_ANTINTRO,\n\n\t//2019/11/12 JAS - Added for Retaliation movies\n\tVQ_RETALIATION_ALLIED1,\n\tVQ_RETALIATION_ALLIED2,\n\tVQ_RETALIATION_ALLIED3,\n\tVQ_RETALIATION_ALLIED4,\n\tVQ_RETALIATION_ALLIED5,\n\tVQ_RETALIATION_ALLIED6,\n\tVQ_RETALIATION_ALLIED7,\n\tVQ_RETALIATION_ALLIED8,\n\tVQ_RETALIATION_ALLIED9,\n\tVQ_RETALIATION_ALLIED10,\n\n\tVQ_RETALIATION_SOVIET1,\n\tVQ_RETALIATION_SOVIET2,\n\tVQ_RETALIATION_SOVIET3,\n\tVQ_RETALIATION_SOVIET4,\n\tVQ_RETALIATION_SOVIET5,\n\tVQ_RETALIATION_SOVIET6,\n\tVQ_RETALIATION_SOVIET7,\n\tVQ_RETALIATION_SOVIET8,\n\tVQ_RETALIATION_SOVIET9,\n\tVQ_RETALIATION_SOVIET10,\n\tVQ_RETALIATION_WINA,\n\tVQ_RETALIATION_WINS,\n\tVQ_RETALIATION_ANTS,\n\n\tVQ_COUNT,\n\tVQ_FIRST=0\n} VQType;\n\n\n/**********************************************************************\n**\tThese enumerations are used to implement RTTI. The target system\n**\tuses these and thus there can be no more RTTI types than can fit\n**\tin the exponent of a target value.\n*/\ntypedef enum RTTIType : unsigned char {\n\tRTTI_NONE=0,\n\tRTTI_AIRCRAFT,\n\tRTTI_AIRCRAFTTYPE,\n\tRTTI_ANIM,\n\tRTTI_ANIMTYPE,\n\tRTTI_BUILDING,\n\tRTTI_BUILDINGTYPE,\n\tRTTI_BULLET,\n\tRTTI_BULLETTYPE,\n\tRTTI_CELL,\n\tRTTI_FACTORY,\n\tRTTI_HOUSE,\n\tRTTI_HOUSETYPE,\n\tRTTI_INFANTRY,\n\tRTTI_INFANTRYTYPE,\n\tRTTI_OVERLAY,\n\tRTTI_OVERLAYTYPE,\n\tRTTI_SMUDGE,\n\tRTTI_SMUDGETYPE,\n\tRTTI_SPECIAL,\n\tRTTI_TEAM,\n\tRTTI_TEAMTYPE,\n\tRTTI_TEMPLATE,\n\tRTTI_TEMPLATETYPE,\n\tRTTI_TERRAIN,\n\tRTTI_TERRAINTYPE,\n\tRTTI_TRIGGER,\n\tRTTI_TRIGGERTYPE,\n\tRTTI_UNIT,\n\tRTTI_UNITTYPE,\n\tRTTI_VESSEL,\n\tRTTI_VESSELTYPE,\n\n\tRTTI_COUNT\n} RTTIType;\n\n\n/**********************************************************************\n**\tThese are the difficulty settings of the game.\n*/\ntypedef enum DiffType : unsigned char {\n\tDIFF_EASY,\n\tDIFF_NORMAL,\n\tDIFF_HARD,\n\n\tDIFF_COUNT,\n\tDIFF_FIRST=0\n} DiffType;\n\n\n/**********************************************************************\n**\tThis is the size of the speech buffer. This value should be as large\n**\tas the largest speech sample, plus a few bytes for overhead\n**\t(16 bytes is sufficient).\n*/\n#define SPEECH_BUFFER_SIZE\t\t50000L\n\n\n/**********************************************************************\n**\tThe theater mixfiles are cached into a buffer of this size. Ensure\n**\tthat the size specified is at least as large as the largest\n**\ttheater mixfile data block.\n*/\n#define THEATER_BUFFER_SIZE\t1100000L\n\n\n/**********************************************************************\n**\tThis is the size of the shape buffer. This buffer is used as a staging\n**\tbuffer for the shape drawing technology. It MUST be as big as the\n**\tlargest shape (uncompressed) that will be drawn. If this value is\n**\tchanged, be sure to update the makefile and rebuild all of the shape\n**\tdata files.\n*/\n#define SHAPE_BUFFER_SIZE\t\t131072L\n\n\n/**********************************************************************\n**\tFilenames of the data files it can create at run time.\n*/\n#define FAME_FILE_NAME\t\t\t\"HALLFAME.DAT\"\n#define NET_SAVE_FILE_NAME\t\t\"SAVEGAME.NET\"\n#define CONFIG_FILE_NAME\t\t\"REDALERT.INI\"\n\n\n/**********************************************************************\n**\tMap controls. The map is composed of square elements called 'cells'.\n**\tAll larger elements are build upon these.\n*/\n\n#define\tHIGH_COORD_MASK\t\t\t0x80008000L\n\n// Size of the map in cells.\n#define\tMAP_CELL_W\t\t\t\t128\n#define\tMAP_CELL_H\t\t\t\t128\n#define\tMAP_CELL_TOTAL\t\t\t(MAP_CELL_W*MAP_CELL_H)\n\n#define\tREFRESH_EOL\t\t\t\t32767\t\t// This number ends a refresh/occupy offset list.\n#define\tREFRESH_SIDEBAR\t\t32766\t\t// This number flags that sidebar needs refreshing.\n\n\n/****************************************************************************\n**\tThese are custom C&C specific types. The CELL is used for map coordinate\n**\twith cell resolution. The COORDINATE type is used for map coordinates that\n**\thave a lepton resolution. CELL is more efficient when indexing into the map\n**\tand when size is critical. COORDINATE is more efficient when dealing with\n**\taccuracy and object movement.\n*/\ntypedef unsigned short\tLEPTON;\ntypedef union {\n\tLEPTON Raw;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned char Cell;\n\t\tunsigned char Lepton;\n#else\n\t\tunsigned char Lepton;\n\t\tunsigned char Cell;\n#endif\n\t} Sub;\n} LEPTON_COMPOSITE;\n\ntypedef unsigned long\tCOORDINATE;\ntypedef union {\n\tCOORDINATE Coord;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tLEPTON_COMPOSITE Y;\n\t\tLEPTON_COMPOSITE X;\n#else\n\t\tLEPTON_COMPOSITE X;\n\t\tLEPTON_COMPOSITE Y;\n#endif\n\t} Sub;\n}\tCOORD_COMPOSITE;\n\ntypedef signed short\t\tCELL;\n#define\tSLUFF_BITS\t(sizeof(CELL)*CHAR_BIT)-(14)\ntypedef union {\n\tCELL Cell;\n\tstruct {\n#ifdef BIG_ENDIAN\n#if SLUFF_BITS\n\t\t/*\n\t\t**\tUnused upper bits will cause problems on a big-endian machine unless they\n\t\t**\tare deliberately accounted for.\n\t\t*/\n\t\tunsigned sluff:SLUF_BITS;\n#endif\n\t\tunsigned Y:7;\n\t\tunsigned X:7;\n#else\n\t\tunsigned X:7;\n\t\tunsigned Y:7;\n#endif\n\t} Sub;\n} CELL_COMPOSITE;\n\ntypedef int\t\tWAYPOINT;\n\n\n/**********************************************************************\n**\tThis is the target composit information. Notice that with an RTTI_NONE\n**\tand an index value of 0, the target value returned is identical with\n**\tTARGET_NONE. This is by design and is necessary.\n*/\ntypedef long\tTARGET;\n\n#define\tTARGET_MANTISSA\t\t\t24\t\t\t\t// Bits of value precision.\n#define\tTARGET_EXPONENT\t\t\t8\ntypedef union {\n\tTARGET Target;\n\tstruct {\n#ifdef BIG_ENDIAN\n\t\tunsigned Exponent:TARGET_EXPONENT;\n\t\tunsigned Mantissa:TARGET_MANTISSA;\n#else\n\t\tunsigned Mantissa:TARGET_MANTISSA;\n\t\tunsigned Exponent:TARGET_EXPONENT;\n#endif\n\t} Sub;\n} TARGET_COMPOSITE;\n\n\ninline TARGET Build_Target(RTTIType kind, int value)\n{\n\tTARGET_COMPOSITE target;\n\n\ttarget.Target = 0;\n\ttarget.Sub.Exponent = kind;\n\ttarget.Sub.Mantissa = value;\n\treturn(target.Target);\n}\n\n\n#define\tTARGET_NONE \t((TARGET)0)\n\n\n/*\n**\tThe map is broken down into regions of this specified dimensions.\n*/\n#define\tREGION_WIDTH\t\t4\n#define\tREGION_HEIGHT\t\t4\n#define\tMAP_REGION_WIDTH\t(((MAP_CELL_W + (REGION_WIDTH -1)) / REGION_WIDTH)+2)\n#define\tMAP_REGION_HEIGHT\t(((MAP_CELL_H + (REGION_WIDTH -1)) / REGION_HEIGHT)+2)\n#define  MAP_TOTAL_REGIONS\t(MAP_REGION_WIDTH * MAP_REGION_HEIGHT)\n\n\n/**********************************************************************\n**\tThis enumerates the various known fear states for infantry units.\n**\tAt these stages, certain events or recovery actions are performed.\n*/\ntypedef enum FearType : unsigned char {\n\tFEAR_NONE=0,\t\t\t// No fear at all (default state).\n\tFEAR_ANXIOUS=10,\t\t// Something makes them scared.\n\tFEAR_SCARED=100,\t\t// Scared enough to take cover.\n\tFEAR_PANIC=200,\t\t// Run away! Run away!\n\tFEAR_MAXIMUM=255\t\t// Scared to death.\n} FearType;\n\n\n/**********************************************************************\n**\tWhen a moving object moves, the Per_Cell_Process function is called\n**\tat various times during the move. Certain operations must be\n**\tperformed at different stages of the move. This enum specifies the\n**\tdifferent conditions under which the Per_Cell_Process function is\n**\tcalled.\n*/\ntypedef enum PCPType : unsigned char {\n\tPCP_ROTATION,\t\t\t// When sitting in place and performing rotations.\n\tPCP_DURING,\t\t\t\t// While moving between two cells.\n\tPCP_END,\t\t\t\t\t// When the 'center' of a cell is reached during movement.\n} PCPType;\n\n\n/**********************************************************************\n**\tA base is broken up into several zones. This type enumerates the\n**\tvarious zones.\n*/\ntypedef enum ZoneType : char {\n\tZONE_CORE,\t\t\t// Center of base.\n\tZONE_NORTH,\t\t\t// North section.\n\tZONE_EAST,\t\t\t// East section.\n\tZONE_SOUTH,\t\t\t// South section.\n\tZONE_WEST,\t\t\t// West section.\n\n\tZONE_COUNT,\n\tZONE_FIRST=0,\n\tZONE_NONE=-1\n} ZoneType;\n\n\n/**********************************************************************\n**\tThe map is prescanned to mark of movement zones according to certain\n**\tmovement characteristics. This enum specifies those characteristics\n**\tand movement zones kept track of.\n*/\ntypedef enum MZoneType : unsigned char {\n\tMZONE_NORMAL,\t\t\t\t// Normal terrestrial objects (can't crush walls).\n\tMZONE_CRUSHER,\t\t\t\t// Can crush crushable wall types.\n\tMZONE_DESTROYER,\t\t\t// Can destroy walls.\n\tMZONE_WATER,\t\t\t\t//\tWater based objects.\n\n\tMZONE_COUNT,\n\tMZONE_FIRST=0\n} MZoneType;\n\n#define\tMZONEF_NORMAL\t\t(1<<MZONE_NORMAL)\n#define\tMZONEF_CRUSHER\t\t(1<<MZONE_CRUSHER)\n#define\tMZONEF_DESTROYER\t(1<<MZONE_DESTROYER)\n#define\tMZONEF_WATER\t\t(1<<MZONE_WATER)\n#define\tMZONEF_ALL\t\t\t(MZONEF_NORMAL|MZONEF_CRUSHER|MZONEF_DESTROYER|MZONEF_WATER)\n\n\n/**********************************************************************\n**\tThis records the current state of the computer controlled base. The\n**\tAI will respond according to this state in order to control\n**\tproduction and unit orders.\n*/\ntypedef enum StateType : unsigned char {\n\tSTATE_BUILDUP,\t\t\t// Base is building up (defensive buildup stage).\n\tSTATE_BROKE,\t\t\t// Low on money, need cash or income source.\n\tSTATE_THREATENED,\t\t// Enemy units are designated to move close by.\n\tSTATE_ATTACKED,\t\t// Base is under direct attack.\n\tSTATE_ENDGAME\t\t\t//\tResistance is futile.\n} StateType;\n\n\n/**********************************************************************\n**\tUrgency rating used to determine what action to perform. The greater\n**\tthe urgency the more likely the corresponding action will be chosen.\n**\tThese values are assigned to each potential desired action the house\n**\tis to perform.\n*/\ntypedef enum UrgencyType : unsigned char {\n\tURGENCY_NONE,\t\t\t\t// No action on this matter is needed or desired.\n\tURGENCY_LOW,\t\t\t\t// Minimal attention requested.\n\tURGENCY_MEDIUM,\t\t\t//\tNormal attention requested.\n\tURGENCY_HIGH,\t\t\t\t// High attention requested.\n\tURGENCY_CRITICAL,\t\t\t// This matter must be addressed immediately.\n\n\tURGENCY_COUNT,\n\tURGENCY_FIRST=URGENCY_CRITICAL\n} UrgencyType;\n\n\n/**********************************************************************\n**\tThese are the various actions a house may perform. These actions refer\n**\tto global events that encompass selling and production. Low level house\n**\tspecific actions of choosing targets is handled elsewhere.\n*/\ntypedef enum StrategyType : unsigned char {\n\tSTRATEGY_BUILD_POWER,\t\t\t// Power is low, build more.\n\tSTRATEGY_BUILD_DEFENSE,\t\t\t// Defense needs boosting.\n\tSTRATEGY_BUILD_INCOME,\t\t\t// Income is low or in jeopardy, raise it.\n\tSTRATEGY_FIRE_SALE,\t\t\t\t// Situation hopeless, sell and attack.\n\tSTRATEGY_BUILD_ENGINEER,\t\t// An engineer is needed.\n\tSTRATEGY_BUILD_OFFENSE,\t\t\t// Offensive weapons are needed.\n\tSTRATEGY_RAISE_MONEY,\t\t\t// Money is low, emergency raise cash.\n\tSTRATEGY_RAISE_POWER,\t\t\t// Money is low, raise power by selling.\n\tSTRATEGY_LOWER_POWER,\t\t\t// Too much power, sell power plants.\n\tSTRATEGY_ATTACK,\t\t\t\t\t// General charge the enemy attack logic.\n\n\tSTRATEGY_COUNT,\n\tSTRATEGY_FIRST=STRATEGY_BUILD_POWER\n} StrategyType;\n\n\n/**********************************************************************\n**\tThese are the various return conditions that production may\n**\tproduce.\n*/\ntypedef enum ProdFailType : unsigned char {\n\tPROD_OK,\t\t\t\t\t\t// Production request successful.\n\tPROD_LIMIT,\t\t\t\t\t// Failed with production capacity limit reached.\n\tPROD_ILLEGAL,\t\t\t\t// Failed because of illegal request.\n\tPROD_CANT\t\t\t\t\t// Failed because unable to comply (busy or occupied).\n} ProdFailType;\n\n\n/**********************************************************************\n**\tWhen performing a landing operation, the aircraft must pass through\n**\tnavigation checkpoints. These enumerations specify the check points.\n*/\ntypedef enum CheckPointType : unsigned char {\n\tCHECK_STACK,\t\t\t\t// Holding area far away from airfield.\n\tCHECK_DOWNWIND,\t\t\t// Downwind leg of approach.\n\tCHECK_CROSSWIND\t\t\t// Crosswind leg of approach.\n} CheckPointType;\n\n\n/**********************************************************************\n**\tThese enumerate the various crate powerups that are available.\n*/\ntypedef enum CrateType : unsigned char {\n\tCRATE_MONEY,\n\tCRATE_UNIT,\n\tCRATE_PARA_BOMB,\n\tCRATE_HEAL_BASE,\n\tCRATE_CLOAK,\n\tCRATE_EXPLOSION,\n\tCRATE_NAPALM,\n\tCRATE_SQUAD,\n\tCRATE_DARKNESS,\n\tCRATE_REVEAL,\n\tCRATE_SONAR,\n\tCRATE_ARMOR,\n\tCRATE_SPEED,\n\tCRATE_FIREPOWER,\n\tCRATE_ICBM,\n\tCRATE_TIMEQUAKE,\n\tCRATE_INVULN,\n\tCRATE_VORTEX,\n\n\tCRATE_COUNT,\n\tCRATE_FIRST=0\n} CrateType;\n\n\n/**********************************************************************\n**\tThese are the special weapons that can be used in the game. The common thread\n**\twith these weapons is that they are controlled through the sidebar\n**\tmechanism.\n*/\ntypedef enum SpecialWeaponType : char {\n\tSPC_NONE=-1,\n\tSPC_SONAR_PULSE,\t\t\t// Momentarily reveals submarines.\n\tSPC_NUCLEAR_BOMB,\t\t\t//\tTactical nuclear weapon.\n\tSPC_CHRONOSPHERE,\t\t\t// Paradox device, for teleportation\n\tSPC_PARA_BOMB,\t\t\t\t// Parachute bomb delivery.\n\tSPC_PARA_INFANTRY,\t\t// Parachute reinforcement delivery.\n\tSPC_SPY_MISSION,\t\t\t// Spy plane to take photo recon mission.\n\tSPC_IRON_CURTAIN,\t\t\t// Bestow invulnerability on a unit/building\n\tSPC_GPS,\t\t\t\t\t\t// give allies free unjammable radar.\n\n\tSPC_COUNT,\n\tSPC_FIRST=0,\n\tSPC_ANY=1\n} SpecialWeaponType;\n#define\tSPC_CHRONO2\t(SPC_COUNT)\n\n\n/**********************************************************************\n**\tThe computer AI is categorized by the following enumerations. If\n**\tthe player is controlling a house, then the IQ rating is zero. When\n**\tthe IQ rating is at maximum, then the computer has complete control\n**\tof the house.\n*/\n//typedef enum IQType {\n//\tIQ_DEAD=0x0000,\t\t\t// Player controlled (computer does nothing).\n//\tIQ_IDIOT=0x0040,\n//\tIQ_IMBECILE=0x0080,\n//\tIQ_MORON=0x00C0,\n//\tIQ_MENSA=0x0100\t\t\t// Complete computer control -- look out!\n//} IQType;\n\n\n/**********************************************************************\n**\tThese are the response values when checking to see if an object\n**\tcan enter or exist at a specified location. By examining this\n**\treturn value, appropriate action may be chosen.\n**\tNOTE: If this changes, update the static array in Find_Path module.\n*/\ntypedef enum MoveType : unsigned char {\n\tMOVE_OK, \t\t\t\t// No blockage.\n\tMOVE_CLOAK,\t\t\t\t// A cloaked blocking enemy object.\n\tMOVE_MOVING_BLOCK,\t// Blocked, but only temporarily.\n\tMOVE_DESTROYABLE,\t\t// Enemy unit or building is blocking.\n\tMOVE_TEMP,  \t\t\t// Blocked by friendly unit.\n\tMOVE_NO,\t\t\t\t\t// Strictly prohibited terrain.\n\n\tMOVE_COUNT\n} MoveType;\n\n\n/**********************************************************************\n**\tThese are the themes that the game can play. They must be in exact\n**\tsame order as specified in the CONQUER.TXT file as well as the filename\n**\tlist located in the ThemeClass.\n*/\ntypedef enum ThemeType : char {\n\tTHEME_QUIET=-3,\n\tTHEME_PICK_ANOTHER=-2,\n\tTHEME_NONE=-1,\n\tTHEME_BIGF,\n\tTHEME_CRUS,\n\tTHEME_FAC1,\n\tTHEME_FAC2,\n\tTHEME_HELL,\n\tTHEME_RUN1,\n\tTHEME_SMSH,\n\tTHEME_TREN,\n\tTHEME_WORK,\n\tTHEME_AWAIT,\n\tTHEME_DENSE_R,\n\tTHEME_FOGGER1A,\n\tTHEME_MUD1A,\n\tTHEME_RADIO2,\n\tTHEME_ROLLOUT,\n\tTHEME_SNAKE,\n\tTHEME_TERMINAT,\n\tTHEME_TWIN,\n\tTHEME_VECTOR1A,\n\n\tTHEME_MAP,\n\tTHEME_SCORE,\n\tTHEME_INTRO,\n\tTHEME_CREDITS,\n\n\tTHEME_2ND_HAND,\n\tTHEME_ARAZOID,\n\tTHEME_BACKSTAB,\n\tTHEME_CHAOS2,\n\tTHEME_SHUT_IT,\n\tTHEME_TWINMIX1,\n\tTHEME_UNDER3,\n\tTHEME_VR2,\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tTHEME_BOG,\n\tTHEME_FLOAT_V2,\n\tTHEME_GLOOM,\n\tTHEME_GRNDWIRE,\n\tTHEME_RPT,\n\tTHEME_SEARCH,\n\tTHEME_TRACTION,\n\tTHEME_WASTELND,\n#endif\n\n\tTHEME_COUNT,\n\tTHEME_LAST=(int)THEME_COUNT-1,\n\tTHEME_FIRST=0\n} ThemeType;\n\n//PG inline ThemeType operator++(ThemeType &, int);\n\n\n/**********************************************************************\n**\tThis is the various threat scan methods that can be used when looking\n**\tfor targets.\n*/\ntypedef enum ThreatType : unsigned short {\n\tTHREAT_NORMAL=0x0000,\t\t// Any distance threat scan?\n\tTHREAT_RANGE=0x0001,\t\t\t// Limit scan to weapon range?\n\tTHREAT_AREA=0x0002,\t\t\t// Limit scan to general area (twice weapon range)?\n\tTHREAT_AIR=0x0004,\t\t\t// Scan for air units?\n\tTHREAT_INFANTRY=0x0008,\t\t// Scan for infantry units?\n\tTHREAT_VEHICLES=0x0010,\t\t// Scan for vehicles?\n\tTHREAT_BUILDINGS=0x0020,\t// Scan for buildings?\n\tTHREAT_TIBERIUM=0x0040,\t\t// Limit scan to Tiberium processing objects?\n\tTHREAT_BOATS=0x0080,\t\t\t// Scan for gunboats?\n\tTHREAT_CIVILIANS=0x0100,\t// Consider civilians to be primary target?\n\tTHREAT_CAPTURE=0x0200,\t\t// Consider capturable buildings only?\n\tTHREAT_FAKES=0x0400,\t\t\t// Consider fake buildings a greater target?\n\tTHREAT_POWER=0x0800,\t\t\t// Consider power generating facilities a greater target?\n\tTHREAT_FACTORIES=0x1000,\t// Consider factories a greater target?\n\tTHREAT_BASE_DEFENSE=0x2000,\t// Consider base defense buildings a greater target?\n} ThreatType;\n//PG\n//inline ThreatType operator |(ThreatType, ThreatType);\n//inline ThreatType operator &(ThreatType, ThreatType);\n//inline ThreatType operator ~(ThreatType);\n\ninline ThreatType operator|(ThreatType a, ThreatType b)\n{return static_cast<ThreatType>(static_cast<int>(a) | static_cast<int>(b));}\n\ninline ThreatType operator&(ThreatType a, ThreatType b)\n{return static_cast<ThreatType>(static_cast<int>(a) & static_cast<int>(b));}\n\ninline ThreatType operator~(ThreatType a)\n{return static_cast<ThreatType>(~static_cast<int>(a));}\n\n\n#define THREAT_GROUND\t(THREAT_VEHICLES|THREAT_BUILDINGS|THREAT_INFANTRY)\n\n\n/**********************************************************************\n**\tThese return values are used when determine if firing is legal.\n**\tBy examining this value it can be determined what should be done\n**\tto fix the reason why firing wasn't allowed.\n*/\ntypedef enum FireErrorType : unsigned char{\n\tFIRE_OK,\t\t\t\t// Weapon is allowed to fire.\n\tFIRE_AMMO,\t\t\t// No ammo available to fire?\n\tFIRE_FACING,\t\t// Not correctly facing target?\n\tFIRE_REARM,\t\t\t// It is busy rearming?\n\tFIRE_ROTATING,\t\t// Is it in process of rotating?\n\tFIRE_ILLEGAL,\t\t// Is it targeting something illegal?\n\tFIRE_CANT,\t\t\t// Is this unit one that cannot fire anything?\n\tFIRE_MOVING,\t\t// Is it moving and not allowed to fire while moving?\n\tFIRE_RANGE,\t\t\t// Is the target out of range?\n\tFIRE_CLOAKED,\t\t// Is the shooter currently cloaked?\n\tFIRE_BUSY\t\t\t// Is shooter currently doing something else?\n} FireErrorType;\n\n\n/**********************************************************************\n**\tIf an object can cloak, then it will be in one of these states.\n**\tFor objects that cannot cloak, they will always be in the\n**\tUNCLOAKED state. This state controls how the object transitions between\n**\tcloaked and uncloaked conditions.\n*/\ntypedef enum CloakType : unsigned char {\n\tUNCLOAKED,\t\t\t// Completely visible (normal state).\n\tCLOAKING,\t\t\t// In process of cloaking.\n\tCLOAKED,\t\t\t\t// Completely cloaked (invisible).\n\tUNCLOAKING\t\t\t// In process of uncloaking.\n} CloakType;\n\n\n/**********************************************************************\n**\tFor units that are cloaking, these value specify the visual character\n**\tof the object.\n*/\ntypedef enum VisualType : unsigned char{\n\tVISUAL_NORMAL,\t\t\t\t// Completely visible -- normal.\n\tVISUAL_INDISTINCT,\t\t// The edges shimmer and become indistinct.\n\tVISUAL_DARKEN,\t\t\t\t// Color and texture is muted along with shimmering.\n\tVISUAL_SHADOWY,\t\t\t// Body is translucent in addition to shimmering.\n\tVISUAL_RIPPLE,\t\t\t\t// Just a ripple (true predator effect).\n\tVISUAL_HIDDEN\t\t\t\t// Nothing at all is visible.\n} VisualType;\n\n\n/**********************************************************************\n**\tThese missions enumerate the various state machines that can apply to\n**\ta game object. Only one of these state machines is active at any one\n**\ttime.\n*/\ntypedef enum MissionType : char {\n\tMISSION_NONE=-1,\n\n\tMISSION_SLEEP,\t\t\t\t// Do nothing whatsoever.\n\tMISSION_ATTACK,\t\t\t// Attack nearest enemy.\n\tMISSION_MOVE,\t\t\t\t// Guard location or unit.\n\tMISSION_QMOVE,\t\t\t\t// A queue list movement mission.\n\tMISSION_RETREAT,\t\t\t// Return home for R & R.\n\tMISSION_GUARD,\t\t\t\t// Stay still.\n\tMISSION_STICKY,\t\t\t// Stay still -- never recruit.\n\tMISSION_ENTER,\t\t\t\t// Move into object cooperatively.\n\tMISSION_CAPTURE,\t\t\t//\tMove into in order to capture.\n\tMISSION_HARVEST,\t\t\t// Hunt for and collect nearby Tiberium.\n\tMISSION_GUARD_AREA,\t\t// Active guard of area.\n\tMISSION_RETURN,\t\t\t// Head back to refinery.\n\tMISSION_STOP,\t\t\t\t// Sit still.\n\tMISSION_AMBUSH,\t\t\t// Wait until discovered.\n\tMISSION_HUNT,\t\t\t\t// Active search and destroy.\n\tMISSION_UNLOAD,\t\t\t// Search for and deliver cargo.\n\tMISSION_SABOTAGE,\t\t\t//\tMove into in order to destroy.\n\tMISSION_CONSTRUCTION,\t// Building buildup operation.\n\tMISSION_DECONSTRUCTION,\t// Building builddown operation.\n\tMISSION_REPAIR,\t\t\t// Repair process mission.\n\tMISSION_RESCUE,\n\tMISSION_MISSILE,\n\tMISSION_HARMLESS,\t\t\t// Sit around and don't appear like a threat.\n\n\tMISSION_COUNT,\n\tMISSION_FIRST=0\n} MissionType;\n\n\n/**********************************************************************\n**\tThese are the enumerated animation sequences that a building may\n**\tbe processing. These serve to control the way that a building\n**\tappears.\n*/\ntypedef enum BStateType : char {\n\tBSTATE_NONE=-1,\n\tBSTATE_CONSTRUCTION,\t\t// Construction animation.\n\tBSTATE_IDLE,\t\t\t\t// Idle animation.\n\tBSTATE_ACTIVE,\t\t\t\t// Animation when building is \"doing its thing\".\n\tBSTATE_FULL,\t\t\t\t// Special alternate active state.\n\tBSTATE_AUX1,\t\t\t\t// Auxiliary animation.\n\tBSTATE_AUX2,\t\t\t\t// Auxiliary animation.\n\n\tBSTATE_COUNT\n} BStateType;\n\n\n/**********************************************************************\n**\tWhenever a unit is selected and a click occurs over another object\n**\tor terrain element, there is some action to initiate. This specifies\n**\tthe different types of actions possible. This also controls how the\n**\tmouse cursor looks when \"hovering\" over the spot that clicking would\n**\toccur at.\n*/\ntypedef enum ActionType : unsigned char {\n\tACTION_NONE,\t\t\t// Either undefined action or \"do nothing\".\n\tACTION_MOVE,\t\t\t// Can move there or at least try to.\n\tACTION_NOMOVE,\t\t\t// Special case for movable object, but illegal mouse position.\n\tACTION_ENTER,\t\t\t// Special case for infantry->APC or vehicle->Repair facility.\n\tACTION_SELF,\t\t\t// Self select special case.\n\tACTION_ATTACK,\t\t\t// Can attack or fire upon it in some fashion.\n\tACTION_HARVEST,\t\t// Special harvest mode.\n\tACTION_SELECT,\t\t\t// Would change selection to specified object.\n\tACTION_TOGGLE_SELECT,// Toggles select state of the object.\n\tACTION_CAPTURE,\t\t// The unit will try to capture the object.\n\tACTION_REPAIR,\t\t\t// The target object should be repaired.\n\tACTION_SELL,\t\t\t// The target building should be sold back.\n\tACTION_SELL_UNIT,\t\t// The target unit should be sold back.\n\tACTION_NO_SELL,  \t\t// No sell or no repair.\n\tACTION_NO_REPAIR,\t\t// No sell or no repair.\n\tACTION_SABOTAGE,\t\t// The unit will try to sabotage/destroy the object.\n\tACTION_PARA_BOMB,\t\t// Parachute bomb strike.\n\tACTION_PARA_INFANTRY,// Parachute infantry strike.\n\tACTION_PARA_SABOTEUR,// Parachute saboteur strike.\n\tACTION_NUKE_BOMB,\t\t// That target object should be blasted.\n\tACTION_AIR_STRIKE,\t// That target object should be blasted.\n\tACTION_CHRONOSPHERE,\t// That target object should be teleported.\n\tACTION_CHRONO2,\t\t// Teleport it to the given coordinates now.\n\tACTION_IRON_CURTAIN,\t// That target object should be invulnerable.\n\tACTION_SPY_MISSION,\t// Photo recon mission.\n\tACTION_GUARD_AREA,\t// Guard the area/object clicked on.\n\tACTION_HEAL,\t\t\t// Heal the infantryman clicked on.\n\tACTION_DAMAGE,\t\t\t// Enter and damage building.\n\tACTION_GREPAIR,\t\t// Enter and complete repair building.\n\tACTION_NO_DEPLOY,\n\tACTION_NO_ENTER,\n\tACTION_NO_GREPAIR,\n\tACTION_TOGGLE_PRIMARY,\t// Toggle the primary status of the factory.\n\n\tACTION_COUNT\n} ActionType;\n\n\n/**********************************************************************\n**\tWhen a unit gets damaged, the result of the damage is returned as\n**\tthis type. It can range from no damage taken to complete destruction.\n*/\ntypedef enum ResultType : unsigned char {\n\tRESULT_NONE,\t\t\t\t// No damage was taken by the target.\n\tRESULT_LIGHT,\t\t\t\t// Some damage was taken, but no state change occurred.\n\tRESULT_HALF,\t\t\t\t// Damaged to below half strength (only returned on transition).\n\tRESULT_MAJOR,\t\t\t\t// Damaged down to 1 hit point.\n\tRESULT_DESTROYED\t\t\t// Damaged to complete destruction.\n} ResultType;\n\n\n#ifdef OBSOLETE\n/**********************************************************************\n**\tThese are the special concrete control defines. They enumerate the\n**\tsequence order of the concrete icons in the concrete art file.\n*/\n// DEBUG === convert this to be zero based so that a nulled cell is the\n//\t\t\t \t default cell.\nenum ConcreteEnum {\n\tC_NONE=-1,\n\tC_LEFT=0,\n\tC_RIGHT=1,\n\tC_RIGHT_UPDOWN=2,\n\tC_LEFT_UPDOWN=3,\n\tC_UP_RIGHT=4,\n\tC_UP_LEFT=5,\n\tC_DOWN_RIGHT=6,\n\tC_DOWN_LEFT=7,\n\tC_RIGHT_DOWN=8,\n\tC_LEFT_DOWN=9,\n\tC_RIGHT_UP=10,\n\tC_LEFT_UP=11,\n\tC_UPDOWN_RIGHT=12,\n\tC_UPDOWN_LEFT=13\n};\n#endif\n\n\n/**********************************************************************\n**\tUnits that move can move at different speeds. These enumerate the\n**\tdifferent speeds that a unit can move.\n*/\ntypedef enum MPHType : unsigned char {\n\tMPH_IMMOBILE=0,\n\tMPH_VERY_SLOW=5,\t\t\t\t//\t2\n\tMPH_KINDA_SLOW=6,\t\t\t\t//\t3\n\tMPH_SLOW=8,\t\t\t\t\t\t//\t4\n\tMPH_SLOW_ISH=10,\t\t\t\t// 5\n\tMPH_MEDIUM_SLOW=12,\t\t\t// 6\n\tMPH_MEDIUM=18,\t\t\t\t\t// 9\n\tMPH_MEDIUM_FAST=30,\t\t\t// 12\n\tMPH_MEDIUM_FASTER=35,\t\t// 14\n\tMPH_FAST=40,\t\t\t\t\t// 16\n\tMPH_ROCKET=60,\t\t\t\t\t// 24\n\tMPH_VERY_FAST=100,\t\t\t// 40\n\tMPH_LIGHT_SPEED=255\t\t\t// 100\n} MPHType;\n\n\n/**********************************************************************\n**\tThe houses that can be played are listed here. Each has their own\n**\tpersonality and strengths.\n*/\ntypedef enum HousesType : char {\n\tHOUSE_NONE=-1,\n\tHOUSE_SPAIN,\t\t\t\t//\tGold (unremapped)\n\tHOUSE_GREECE,\t\t\t\t// LtBlue\n\tHOUSE_USSR,\t\t\t\t\t// Red\n\tHOUSE_ENGLAND,\t\t\t\t// Green\n\tHOUSE_UKRAINE,\t\t\t\t// Orange\n\tHOUSE_GERMANY,\t\t\t\t// Grey\n\tHOUSE_FRANCE,\t\t\t\t// Blue\n\tHOUSE_TURKEY,\t\t\t\t// Brown\n\tHOUSE_GOOD,\t\t\t\t\t// Global Defense Initiative\n\tHOUSE_BAD,\t\t\t\t\t// Brotherhood of Nod\n\tHOUSE_NEUTRAL,\t\t\t\t// Civilians\n\tHOUSE_JP,\t\t\t\t\t// Disaster Containment Team\n\tHOUSE_MULTI1,\t\t\t\t// Multi-Player house #1\n\tHOUSE_MULTI2,\t\t\t\t// Multi-Player house #2\n\tHOUSE_MULTI3,\t\t\t\t// Multi-Player house #3\n\tHOUSE_MULTI4,\t\t\t\t// Multi-Player house #4\n\tHOUSE_MULTI5,\t\t\t\t// Multi-Player house #5\n\tHOUSE_MULTI6,\t\t\t\t// Multi-Player house #6\n\tHOUSE_MULTI7,\t\t\t\t// Multi-Player house #7\n\tHOUSE_MULTI8,\t\t\t\t// Multi-Player house #8\n\tHOUSE_COUNT,\n\tHOUSE_FIRST=0\n} HousesType;\n\n//inline HousesType operator++(HousesType &, int) {return (HousesType)(int;\ninline HousesType operator++(HousesType &ht) { ht = (HousesType)(((int)ht)+1); return ht; }\n\n#define\tHOUSEF_ALLIES\t(HOUSEF_ENGLAND|HOUSEF_SPAIN|HOUSEF_GREECE|HOUSEF_GERMANY|HOUSEF_FRANCE|HOUSEF_TURKEY|HOUSEF_GOOD)\n#define\tHOUSEF_SOVIET\t(HOUSEF_USSR|HOUSEF_UKRAINE|HOUSEF_BAD)\n#define\tHOUSEF_OTHERS\t(HOUSEF_NEUTRAL|HOUSEF_JP|HOUSEF_MULTI1|HOUSEF_MULTI2|HOUSEF_MULTI3|HOUSEF_MULTI4|HOUSEF_MULTI5|HOUSEF_MULTI6|HOUSEF_MULTI7|HOUSEF_MULTI8)\n#define\tHOUSEF_NONE\t\t0\n\n#define\tHOUSEF_ENGLAND\t(1L<<HOUSE_ENGLAND)\n#define\tHOUSEF_SPAIN\t(1L<<HOUSE_SPAIN)\n#define\tHOUSEF_GREECE\t(1L<<HOUSE_GREECE)\n#define\tHOUSEF_USSR\t\t(1L<<HOUSE_USSR)\n#define\tHOUSEF_UKRAINE\t(1L<<HOUSE_UKRAINE)\n#define\tHOUSEF_GERMANY\t(1L<<HOUSE_GERMANY)\n#define\tHOUSEF_FRANCE\t(1L<<HOUSE_FRANCE)\n#define\tHOUSEF_TURKEY\t(1L<<HOUSE_TURKEY)\n#define\tHOUSEF_GOOD\t\t(1L<<HOUSE_GOOD)\n#define\tHOUSEF_BAD\t\t(1L<<HOUSE_BAD)\n#define\tHOUSEF_NEUTRAL\t(1L<<HOUSE_NEUTRAL)\n#define\tHOUSEF_JP\t\t(1L<<HOUSE_JP)\n#define\tHOUSEF_MULTI1\t(1L<<HOUSE_MULTI1)\n#define\tHOUSEF_MULTI2\t(1L<<HOUSE_MULTI2)\n#define\tHOUSEF_MULTI3\t(1L<<HOUSE_MULTI3)\n#define\tHOUSEF_MULTI4\t(1L<<HOUSE_MULTI4)\n#define\tHOUSEF_MULTI5\t(1L<<HOUSE_MULTI5)\n#define\tHOUSEF_MULTI6\t(1L<<HOUSE_MULTI6)\n#define\tHOUSEF_MULTI7\t(1L<<HOUSE_MULTI7)\n#define\tHOUSEF_MULTI8\t(1L<<HOUSE_MULTI8)\n\ntypedef enum PlayerColorType : char {\n\tPCOLOR_NONE = -1,\n\tPCOLOR_GOLD,\n\tPCOLOR_LTBLUE,\n\tPCOLOR_RED,\n\tPCOLOR_GREEN,\n\tPCOLOR_ORANGE,\n\tPCOLOR_BLUE,\t\t//This is actually the red scheme used in the dialogs\n\tPCOLOR_GREY,\n\tPCOLOR_BROWN,\n\tPCOLOR_TYPE,\n\tPCOLOR_REALLY_BLUE,\n\tPCOLOR_DIALOG_BLUE,\n\n\tPCOLOR_COUNT,\n\tPCOLOR_FIRST=0,\n\tPCOLOR_LAST=PCOLOR_COUNT-1\n} PlayerColorType;\n\n\n/**********************************************************************\n**\tThis enumerates the remap logic to be applied to an object type when\n**\tit appears in the construction sidebar.\n*/\ntypedef enum RemapType : unsigned char {\n\tREMAP_NONE,\n\tREMAP_NORMAL,\n\tREMAP_ALTERNATE\n} RemapType;\n\n\n/**********************************************************************\n** These are the types of games that can be played.  GDI & NOD are the\n** usual human-vs-computer games; 2-Player games are network or modem,\n** with 2 players; multi-player games are network with > 2 players.\n*/\ntypedef enum ScenarioPlayerEnum : char\n{\n\tSCEN_PLAYER_NONE = -1,\n\tSCEN_PLAYER_SPAIN,\n\tSCEN_PLAYER_GREECE,\n\tSCEN_PLAYER_USSR,\n\tSCEN_PLAYER_JP,\n\tSCEN_PLAYER_2PLAYER,\n\tSCEN_PLAYER_MPLAYER,\n\tSCEN_PLAYER_COUNT,\n\tSCEN_PLAYER_FIRST = 0\n} ScenarioPlayerType;\n\ninline ScenarioPlayerType operator++(ScenarioPlayerType &, int);\n\n\n/**********************************************************************\n** These are the directional parameters for a scenario.\n*/\ntypedef enum ScenarioDirEnum : char \n{\n\tSCEN_DIR_NONE = -1,\n\tSCEN_DIR_EAST,\n\tSCEN_DIR_WEST,\n\tSCEN_DIR_COUNT,\n\tSCEN_DIR_FIRST = 0\n} ScenarioDirType;\n\ninline ScenarioDirType operator++(ScenarioDirType &, int);\n\n\n/**********************************************************************\n** These are the random variations of a scenario.\n*/\ntypedef enum ScenarioVarEnum : char \n{\n\tSCEN_VAR_NONE = -1,\n\tSCEN_VAR_A,\n\tSCEN_VAR_B,\n\tSCEN_VAR_C,\n\tSCEN_VAR_D,\n\tSCEN_VAR_COUNT,\t\t// comes before the Lose value!\n\tSCEN_VAR_LOSE,\n\tSCEN_VAR_FIRST = 0\n} ScenarioVarType;\n\n//inline ScenarioVarType operator++(ScenarioVarType &, int);\ninline ScenarioVarType operator++(ScenarioVarType &n) { n = (ScenarioVarType)(((int)n) + 1); return n; }\n\n\n/**********************************************************************\n**\tThe objects to be drawn on the map are grouped into layers. These\n**\tenumerated values specify those layers. The ground layer is sorted\n**\tfrom back to front.\n*/\ntypedef enum LayerType : char {\n\tLAYER_NONE=-1,\n\tLAYER_SURFACE,\t\t// Flat on the ground (no sorting or apparent vertical height).\n\tLAYER_GROUND,\t\t// Touching the ground type object (units & buildings).\n\tLAYER_AIR,\t\t\t// Flying above the ground (explosions & flames).\n\tLAYER_TOP,\t\t\t// Topmost layer (aircraft & bullets).\n\n\tLAYER_COUNT,\n\tLAYER_FIRST=0\n} LayerType;\n\n//PG inline LayerType operator++(LayerType &, int);\ninline LayerType operator++(LayerType &n) { n = (LayerType)(((int)n) + 1); return n; }\n\n\n/**********************************************************************\n**\tThis enumerates the various bullet types. These types specify bullet's\n**\tvisual and explosive characteristics.\n*/\ntypedef enum BulletType : char {\n\tBULLET_NONE=-1,\n\n\tBULLET_INVISIBLE,\n\tBULLET_CANNON,\n\tBULLET_ACK,\n\tBULLET_TORPEDO,\n\tBULLET_FROG,\n\tBULLET_HEAT_SEEKER,\n\tBULLET_LASER_GUIDED,\n\tBULLET_LOBBED,\n\tBULLET_BOMBLET,\n\tBULLET_BALLISTIC,\n\tBULLET_PARACHUTE,\n\tBULLET_FIREBALL,\n\tBULLET_DOG,\n\tBULLET_CATAPULT,\n\tBULLET_AAMISSILE,\n\tBULLET_GPS_SATELLITE,\n\tBULLET_NUKE_UP,\n\tBULLET_NUKE_DOWN,\n\n\tBULLET_COUNT,\n\tBULLET_FIRST=0\n} BulletType;\n\n//PG inline BulletType operator++(BulletType &, int);\ninline BulletType operator++(BulletType &n) { n = (BulletType)(((int)n) + 1); return n; }\n\n\n/**********************************************************************\n**\tAll game buildings (structures) are enumerated here. This includes\n**\tcivilian structures as well.\n*/\ntypedef enum StructType : char {\n\tSTRUCT_NONE=-1,\n\tSTRUCT_ADVANCED_TECH,\n\tSTRUCT_IRON_CURTAIN,\n\tSTRUCT_WEAP,\n\tSTRUCT_CHRONOSPHERE,\n\tSTRUCT_PILLBOX,\n\tSTRUCT_CAMOPILLBOX,\n\tSTRUCT_RADAR,\n\tSTRUCT_GAP,\n\tSTRUCT_TURRET,\n\tSTRUCT_AAGUN,\n\tSTRUCT_FLAME_TURRET,\n\tSTRUCT_CONST,\n\tSTRUCT_REFINERY,\n\tSTRUCT_STORAGE,\n\tSTRUCT_HELIPAD,\n\tSTRUCT_SAM,\n\tSTRUCT_AIRSTRIP,\n\tSTRUCT_POWER,\n\tSTRUCT_ADVANCED_POWER,\n\tSTRUCT_SOVIET_TECH,\n\tSTRUCT_HOSPITAL,\n\tSTRUCT_BARRACKS,\n\tSTRUCT_TENT,\n\tSTRUCT_KENNEL,\n\tSTRUCT_REPAIR,\n\tSTRUCT_BIO_LAB,\n\tSTRUCT_MISSION,\n\tSTRUCT_SHIP_YARD,\n\tSTRUCT_SUB_PEN,\n\tSTRUCT_MSLO,\n\tSTRUCT_FORWARD_COM,\n\tSTRUCT_TESLA,\n\n\t/*\n\t**\tAll buildings that are never used as a prerequisite\n\t**\tfor construction, follow this point. Typically, this is\n\t**\tlimited to civilian structures. Also, the following\n\t**\tbuildings are NEVER used in the availability bit field\n\t**\trecord that each house maintains. i.e., STRUCTF_????\n\t**\tbit checking will never occur with the following\n\t**\tbuilding types.\n\t*/\n\tSTRUCT_FAKEWEAP,\n\tSTRUCT_FAKECONST,\n\tSTRUCT_FAKE_YARD,\n\tSTRUCT_FAKE_PEN,\n\tSTRUCT_FAKE_RADAR,\n\n\tSTRUCT_SANDBAG_WALL,\n\tSTRUCT_CYCLONE_WALL,\n\tSTRUCT_BRICK_WALL,\n\tSTRUCT_BARBWIRE_WALL,\n\tSTRUCT_WOOD_WALL,\n\tSTRUCT_FENCE,\n\n\tSTRUCT_AVMINE,\n\tSTRUCT_APMINE,\n\tSTRUCT_V01,\n\tSTRUCT_V02,\n\tSTRUCT_V03,\n\tSTRUCT_V04,\n\tSTRUCT_V05,\n\tSTRUCT_V06,\n\tSTRUCT_V07,\n\tSTRUCT_V08,\n\tSTRUCT_V09,\n\tSTRUCT_V10,\n\tSTRUCT_V11,\n\tSTRUCT_V12,\n\tSTRUCT_V13,\n\tSTRUCT_V14,\n\tSTRUCT_V15,\n\tSTRUCT_V16,\n\tSTRUCT_V17,\n\tSTRUCT_V18,\n\tSTRUCT_PUMP,\n\tSTRUCT_V20,\n\tSTRUCT_V21,\n\tSTRUCT_V22,\n\tSTRUCT_V23,\n\tSTRUCT_V24,\n\tSTRUCT_V25,\n\tSTRUCT_V26,\n\tSTRUCT_V27,\n\tSTRUCT_V28,\n\tSTRUCT_V29,\n\tSTRUCT_V30,\n\tSTRUCT_V31,\n\tSTRUCT_V32,\n\tSTRUCT_V33,\n\tSTRUCT_V34,\n\tSTRUCT_V35,\n\tSTRUCT_V36,\n\tSTRUCT_V37,\n\tSTRUCT_BARREL,\n\tSTRUCT_BARREL3,\n\n#ifdef FIXIT_ANTS\n\tSTRUCT_QUEEN,\n\tSTRUCT_LARVA1,\n\tSTRUCT_LARVA2,\n#endif\n\n\tSTRUCT_COUNT,\n\tSTRUCT_FIRST=0\n} StructType;\n\n//PG inline StructType operator++(StructType &, int);\ninline StructType operator++(StructType &n) { n = (StructType)(((int)n) + 1); return n; }\n\n#define\tSTRUCTF_NONE\t\t\t\t0L\n#define\tSTRUCTF_ADVANCED_TECH\t(1L << STRUCT_ADVANCED_TECH)\n#define\tSTRUCTF_IRON_CURTAIN\t\t(1L << STRUCT_IRON_CURTAIN)\n#define\tSTRUCTF_WEAP\t\t\t\t(1L << STRUCT_WEAP)\n#define\tSTRUCTF_CHRONOSPHERE\t\t(1L << STRUCT_CHRONOSPHERE)\n#define\tSTRUCTF_PILLBOX\t\t\t(1L << STRUCT_PILLBOX)\n#define\tSTRUCTF_CAMOPILLBOX\t\t(1L << STRUCT_CAMOPILLBOX)\n#define\tSTRUCTF_RADAR\t\t\t\t(1L << STRUCT_RADAR)\n#define\tSTRUCTF_GAP\t\t\t\t\t(1L << STRUCT_GAP)\n#define\tSTRUCTF_TURRET\t\t\t\t(1L << STRUCT_TURRET)\n#define\tSTRUCTF_AAGUN\t\t\t\t(1L << STRUCT_AAGUN)\n#define\tSTRUCTF_FLAME_TURRET\t\t(1L << STRUCT_FLAME_TURRET)\n#define\tSTRUCTF_CONST\t\t\t\t(1L << STRUCT_CONST)\n#define\tSTRUCTF_REFINERY\t\t\t(1L << STRUCT_REFINERY)\n#define\tSTRUCTF_STORAGE\t\t\t(1L << STRUCT_STORAGE)\n#define\tSTRUCTF_HELIPAD\t\t\t(1L << STRUCT_HELIPAD)\n#define\tSTRUCTF_SAM\t\t\t\t\t(1L << STRUCT_SAM)\n#define\tSTRUCTF_AIRSTRIP\t\t\t(1L << STRUCT_AIRSTRIP)\n#define\tSTRUCTF_POWER\t\t\t\t(1L << STRUCT_POWER)\n#define\tSTRUCTF_ADVANCED_POWER\t(1L << STRUCT_ADVANCED_POWER)\n#define\tSTRUCTF_SOVIET_TECH\t\t(1L << STRUCT_SOVIET_TECH)\n#define\tSTRUCTF_HOSPITAL\t\t\t(1L << STRUCT_HOSPITAL)\n#define\tSTRUCTF_BARRACKS\t\t\t(1L << STRUCT_BARRACKS)\n#define\tSTRUCTF_TENT\t\t\t\t(1L << STRUCT_TENT)\n#define\tSTRUCTF_KENNEL\t\t\t\t(1L << STRUCT_KENNEL)\n#define\tSTRUCTF_REPAIR\t\t\t\t(1L << STRUCT_REPAIR)\n#define\tSTRUCTF_BIO_LAB\t\t\t(1L << STRUCT_BIO_LAB)\n#define\tSTRUCTF_MISSION\t\t\t(1L << STRUCT_MISSION)\n#define\tSTRUCTF_SHIP_YARD\t\t\t(1L << STRUCT_SHIP_YARD)\n#define\tSTRUCTF_SUB_PEN\t\t\t(1L << STRUCT_SUB_PEN)\n#define\tSTRUCTF_MSLO\t\t\t\t(1L << STRUCT_MSLO)\n#define\tSTRUCTF_FAKECONST\t\t\t(1L << STRUCT_FAKECONST)\n#define\tSTRUCTF_FAKEWEAP\t\t\t(1L << STRUCT_FAKEWEAP)\n\n\n/**********************************************************************\n**\tThe overlays are enumerated here. An overlay functions similarly to\n**\ta transparent icon. It is placed over the terrain but usually falls\n**\t\"under\" buildings, trees, and units.\n*/\ntypedef enum OverlayType : char {\n\tOVERLAY_NONE=-1,\n\tOVERLAY_SANDBAG_WALL,\t// Piled sandbags.\n\tOVERLAY_CYCLONE_WALL,\t// Chain-link fence.\n\tOVERLAY_BRICK_WALL,\t\t// Solid concrete wall.\n\tOVERLAY_BARBWIRE_WALL,\t// Barbed-wire wall.\n\tOVERLAY_WOOD_WALL,\t\t// Wooden fence.\n\tOVERLAY_GOLD1,\n\tOVERLAY_GOLD2,\n\tOVERLAY_GOLD3,\n\tOVERLAY_GOLD4,\n\tOVERLAY_GEMS1,\n\tOVERLAY_GEMS2,\n\tOVERLAY_GEMS3,\n\tOVERLAY_GEMS4,\n\tOVERLAY_V12,\t\t\t\t// Haystacks\n\tOVERLAY_V13,\t\t\t\t// Haystack\n\tOVERLAY_V14,\t\t\t\t// Wheat field\n\tOVERLAY_V15,\t\t\t\t// Fallow field\n\tOVERLAY_V16,\t\t\t\t//\tCorn field\n\tOVERLAY_V17,\t\t\t\t// Celery field\n\tOVERLAY_V18,\t\t\t\t// Potato field\n\tOVERLAY_FLAG_SPOT,\t\t// Flag start location.\n\tOVERLAY_WOOD_CRATE,\t\t// Wooden goodie crate.\n\tOVERLAY_STEEL_CRATE,\t\t//\tSteel goodie crate.\n\tOVERLAY_FENCE,\t\t\t\t// New fangled fence.\n\tOVERLAY_WATER_CRATE,\t\t//\tWater goodie crate.\n\n\tOVERLAY_COUNT,\n\tOVERLAY_FIRST=0\n} OverlayType;\n\n//PG inline OverlayType operator++(OverlayType &, int);\n\n\n/**********************************************************************\n**\tThis specifies the infantry in the game. The \"E\" designation is\n**\tsimilar to the army classification of enlisted soldiers.\n*/\ntypedef enum InfantryType : char {\n\tINFANTRY_NONE=-1,\n\tINFANTRY_E1,\t\t\t\t// Mini-gun armed.\n\tINFANTRY_E2,\t\t\t\t// Grenade thrower.\n\tINFANTRY_E3,\t\t\t\t// Rocket launcher.\n\tINFANTRY_E4,\t\t\t\t// Flame thrower equipped.\n\tINFANTRY_RENOVATOR,\t\t// Engineer.\n\tINFANTRY_TANYA,\t\t\t// Saboteur.\n\tINFANTRY_SPY,\t\t\t\t// Spy.\n\tINFANTRY_THIEF,\t\t\t// Thief.\n\tINFANTRY_MEDIC,\t\t\t// Field Medic.\n\tINFANTRY_GENERAL,\t\t\t// Field Marshal.\n\tINFANTRY_DOG,\t\t\t\t// Soviet attack dog\n\n\tINFANTRY_C1,\t\t\t\t// Civilian\n\tINFANTRY_C2,\t\t\t\t// Civilian\n\tINFANTRY_C3,\t\t\t\t// Civilian\n\tINFANTRY_C4,\t\t\t\t// Civilian\n\tINFANTRY_C5,\t\t\t\t// Civilian\n\tINFANTRY_C6,\t\t\t\t// Civilian\n\tINFANTRY_C7,\t\t\t\t// Civilian\n\tINFANTRY_C8,\t\t\t\t// Civilian\n\tINFANTRY_C9,\t\t\t\t// Civilian\n\tINFANTRY_C10,\t\t\t\t// Nikumba\n\tINFANTRY_EINSTEIN,\t\t// Einstein\n\tINFANTRY_DELPHI,\t\t\t// Agent \"Delphi\"\n\tINFANTRY_CHAN,\t\t\t\t// Dr. Chan\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CounterStrike II only!\n\tINFANTRY_SHOCK,\t\t\t// Shock Trooper\n\tINFANTRY_MECHANIC,\n#endif\n\n\tINFANTRY_COUNT,\n\tINFANTRY_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tINFANTRY_RA_COUNT = INFANTRY_SHOCK\n#endif\n} InfantryType;\n\n#define INFANTRYF_DOG\t(1L << INFANTRY_DOG)\n\n//PG inline InfantryType operator++(InfantryType &, int);\n\n\n/**********************************************************************\n**\tThe game units are enumerated here. These include not only traditional\n**\tvehicles, but also hovercraft and gunboats.\n*/\ntypedef enum UnitType : char {\n\tUNIT_NONE=-1,\n\tUNIT_HTANK,\t\t\t\t\t// Mammoth tank.\n\tUNIT_MTANK,\t\t\t\t\t// Heavy tank.\n\tUNIT_MTANK2,\t\t\t\t// Medium tank.\n\tUNIT_LTANK,\t\t\t\t\t// Light tank ('Bradly').\n\tUNIT_APC,\t\t\t\t\t// APC.\n\tUNIT_MINELAYER,\t\t\t// Mine-laying vehicle.\n\tUNIT_JEEP,\t\t\t\t\t// 4x4 jeep replacement.\n\tUNIT_HARVESTER,\t\t\t// Resource gathering vehicle.\n\tUNIT_ARTY,\t\t\t\t\t// Artillery unit.\n\tUNIT_MRJ,\t\t\t\t\t// Mobile Radar Jammer.\n\tUNIT_MGG,\t\t\t\t\t// Mobile Gap Generator\n\tUNIT_MCV,\t\t\t\t\t// Mobile construction vehicle.\n\tUNIT_V2_LAUNCHER,\t\t\t// V2 rocket launcher.\n\tUNIT_TRUCK,\t\t\t\t\t// Convoy truck\n\n#ifdef FIXIT_ANTS\n\tUNIT_ANT1,\t\t\t\t\t// Warrior ant.\n\tUNIT_ANT2,\t\t\t\t\t// Warrior ant.\n\tUNIT_ANT3,\t\t\t\t\t// Warrior ant.\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CS II ONLY!\n\tUNIT_CHRONOTANK,\t\t\t// Chrono-shifting tank\n\tUNIT_TESLATANK,\t\t\t// Tesla-equipped tank\n\tUNIT_MAD,\t\t\t\t\t// Timequake tank\n\tUNIT_DEMOTRUCK,\t\t\t// Jihad truck\n#ifdef FIXIT_PHASETRANSPORT\t//\tchecked - ajw 9/28/98\n\tUNIT_PHASE,\t\t\t\t\t// cloaking APC for special missions\n#endif\n#endif\n\n\tUNIT_COUNT,\n\tUNIT_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tUNIT_RA_COUNT = UNIT_CHRONOTANK\n#endif\n} UnitType;\n\n//PG inline UnitType operator++(UnitType &, int);\n\n#define\tUNITF_HTANK\t\t\t(1L<<UNIT_HTANK)\n#define\tUNITF_MTANK\t\t\t(1L<<UNIT_MTANK)\n#define\tUNITF_MTANK2\t\t(1L<<UNIT_MTANK2)\n#define\tUNITF_LTANK\t\t\t(1L<<UNIT_LTANK)\n#define\tUNITF_STANK\t\t\t(1L<<UNIT_STANK)\n#define\tUNITF_APC\t\t\t(1L<<UNIT_APC)\n#define\tUNITF_MLRS\t\t\t(1L<<UNIT_MLRS)\n#define\tUNITF_JEEP\t\t\t(1L<<UNIT_JEEP)\n#define\tUNITF_HARVESTER\t(1L<<UNIT_HARVESTER)\n#define\tUNITF_ARTY\t\t\t(1L<<UNIT_ARTY)\n#define\tUNITF_MCV\t\t\t(1L<<UNIT_MCV)\n\n\n/**********************************************************************\n**\tThe naval vessels are enumerated below.\n*/\ntypedef enum VesselType : char {\n\tVESSEL_NONE=-1,\n\n\tVESSEL_SS,\t\t\t\t\t\t// Submarine\n\tVESSEL_DD,\t\t\t\t\t\t// Medium weapon patrol craft\n\tVESSEL_CA,\t\t\t\t\t\t// Heavy weapon patrol craft\n\tVESSEL_TRANSPORT,\t\t\t\t// Unit transporter\n\tVESSEL_PT,\t\t\t\t\t\t// Light weapon patrol craft\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// CS II ONLY\n\tVESSEL_MISSILESUB,\t\t\t// Missile-equipped submarine\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tVESSEL_CARRIER,\n#endif\n\n\tVESSEL_COUNT,\n\tVESSEL_FIRST=0\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n,\n\tVESSEL_RA_COUNT = VESSEL_MISSILESUB\n#endif\n} VesselType;\n\n//inline VesselType operator++(VesselType &, int);\n\n#define\tVESSELF_SS\t\t\t(1L<<VESSEL_SS)\n#define\tVESSELF_DD\t\t\t(1L<<VESSEL_DD)\n#define\tVESSELF_CA\t\t\t(1L<<VESSEL_CA)\n#define\tVESSELF_TRANSPORT\t(1L<<VESSEL_TRANSPORT)\n#define\tVESSELF_PT\t\t\t(1L<<VESSEL_PT)\n\n\n/**********************************************************************\n**\tThe various aircraft types are enumerated here. These include helicopters\n**\tas well as traditional aircraft.\n*/\ntypedef enum AircraftType : char {\n\tAIRCRAFT_TRANSPORT,\t\t\t// Transport helicopter.\n\tAIRCRAFT_BADGER,\t\t\t\t// Badger bomber.\n\tAIRCRAFT_U2,\t\t\t\t\t// Photo recon plane.\n\tAIRCRAFT_MIG,\t\t\t\t\t// Mig attack plane.\n\tAIRCRAFT_YAK,\t\t\t\t\t// Yak attack plane.\n\tAIRCRAFT_LONGBOW,\t\t\t\t// Apache gunship.\n\tAIRCRAFT_HIND,\t\t\t\t\t// Soviet attach helicopter.\n\n\tAIRCRAFT_COUNT,\n\tAIRCRAFT_NONE=-1,\n\tAIRCRAFT_FIRST=0\n} AircraftType;\n\n#define\tAIRCRAFTF_TRANSPORT\t(1L << AIRCRAFT_TRANSPORT)\n#define\tAIRCRAFTF_BADGER\t\t(1L << AIRCRAFT_BADGER)\n#define\tAIRCRAFTF_U2\t\t\t(1L << AIRCRAFT_U2)\n#define\tAIRCRAFTF_MIG\t\t\t(1L << AIRCRAFT_MIG)\n#define\tAIRCRAFTF_YAK\t\t\t(1L << AIRCRAFT_YAK)\n#define\tAIRCRAFTF_LONGBOW\t\t(1L << AIRCRAFT_LONGBOW)\n#define\tAIRCRAFTF_HIND\t\t\t(1L << AIRCRAFT_HIND)\n\n//PG inline AircraftType operator++(AircraftType &, int);\n\n\n/**********************************************************************\n**\tThe game templates are enumerated here. These are the underlying\n**\tterrain art. This includes everything from water to cliffs. If the\n**\tterrain is broken up into icons, is not transparent, and is drawn\n**\tas the bottom most layer, then it is a template.\n*/\ntypedef enum TemplateType : unsigned short {\n\tTEMPLATE_CLEAR1,\n\tTEMPLATE_WATER,\t\t\t// This must be the first non-clear template.\n\tTEMPLATE_WATER2,\n\tTEMPLATE_SHORE01,\n\tTEMPLATE_SHORE02,\n\tTEMPLATE_SHORE03,\n\tTEMPLATE_SHORE04,\n\tTEMPLATE_SHORE05,\n\tTEMPLATE_SHORE06,\n\tTEMPLATE_SHORE07,\n\tTEMPLATE_SHORE08,\n\tTEMPLATE_SHORE09,\n\tTEMPLATE_SHORE10,\n\tTEMPLATE_SHORE11,\n\tTEMPLATE_SHORE12,\n\tTEMPLATE_SHORE13,\n\tTEMPLATE_SHORE14,\n\tTEMPLATE_SHORE15,\n\tTEMPLATE_SHORE16,\n\tTEMPLATE_SHORE17,\n\tTEMPLATE_SHORE18,\n\tTEMPLATE_SHORE19,\n\tTEMPLATE_SHORE20,\n\tTEMPLATE_SHORE21,\n\tTEMPLATE_SHORE22,\n\tTEMPLATE_SHORE23,\n\tTEMPLATE_SHORE24,\n\tTEMPLATE_SHORE25,\n\tTEMPLATE_SHORE26,\n\tTEMPLATE_SHORE27,\n\tTEMPLATE_SHORE28,\n\tTEMPLATE_SHORE29,\n\tTEMPLATE_SHORE30,\n\tTEMPLATE_SHORE31,\n\tTEMPLATE_SHORE32,\n\tTEMPLATE_SHORE33,\n\tTEMPLATE_SHORE34,\n\tTEMPLATE_SHORE35,\n\tTEMPLATE_SHORE36,\n\tTEMPLATE_SHORE37,\n\tTEMPLATE_SHORE38,\n\tTEMPLATE_SHORE39,\n\tTEMPLATE_SHORE40,\n\tTEMPLATE_SHORE41,\n\tTEMPLATE_SHORE42,\n\tTEMPLATE_SHORE43,\n\tTEMPLATE_SHORE44,\n\tTEMPLATE_SHORE45,\n\tTEMPLATE_SHORE46,\n\tTEMPLATE_SHORE47,\n\tTEMPLATE_SHORE48,\n\tTEMPLATE_SHORE49,\n\tTEMPLATE_SHORE50,\n\tTEMPLATE_SHORE51,\n\tTEMPLATE_SHORE52,\n\tTEMPLATE_SHORE53,\n\tTEMPLATE_SHORE54,\n\tTEMPLATE_SHORE55,\n\tTEMPLATE_SHORE56,\n\tTEMPLATE_SHORECLIFF01,\n\tTEMPLATE_SHORECLIFF02,\n\tTEMPLATE_SHORECLIFF03,\n\tTEMPLATE_SHORECLIFF04,\n\tTEMPLATE_SHORECLIFF05,\n\tTEMPLATE_SHORECLIFF06,\n\tTEMPLATE_SHORECLIFF07,\n\tTEMPLATE_SHORECLIFF08,\n\tTEMPLATE_SHORECLIFF09,\n\tTEMPLATE_SHORECLIFF10,\n\tTEMPLATE_SHORECLIFF11,\n\tTEMPLATE_SHORECLIFF12,\n\tTEMPLATE_SHORECLIFF13,\n\tTEMPLATE_SHORECLIFF14,\n\tTEMPLATE_SHORECLIFF15,\n\tTEMPLATE_SHORECLIFF16,\n\tTEMPLATE_SHORECLIFF17,\n\tTEMPLATE_SHORECLIFF18,\n\tTEMPLATE_SHORECLIFF19,\n\tTEMPLATE_SHORECLIFF20,\n\tTEMPLATE_SHORECLIFF21,\n\tTEMPLATE_SHORECLIFF22,\n\tTEMPLATE_SHORECLIFF23,\n\tTEMPLATE_SHORECLIFF24,\n\tTEMPLATE_SHORECLIFF25,\n\tTEMPLATE_SHORECLIFF26,\n\tTEMPLATE_SHORECLIFF27,\n\tTEMPLATE_SHORECLIFF28,\n\tTEMPLATE_SHORECLIFF29,\n\tTEMPLATE_SHORECLIFF30,\n\tTEMPLATE_SHORECLIFF31,\n\tTEMPLATE_SHORECLIFF32,\n\tTEMPLATE_SHORECLIFF33,\n\tTEMPLATE_SHORECLIFF34,\n\tTEMPLATE_SHORECLIFF35,\n\tTEMPLATE_SHORECLIFF36,\n\tTEMPLATE_SHORECLIFF37,\n\tTEMPLATE_SHORECLIFF38,\n\tTEMPLATE_BOULDER1,\n\tTEMPLATE_BOULDER2,\n\tTEMPLATE_BOULDER3,\n\tTEMPLATE_BOULDER4,\n\tTEMPLATE_BOULDER5,\n\tTEMPLATE_BOULDER6,\n\tTEMPLATE_PATCH01,\n\tTEMPLATE_PATCH02,\n\tTEMPLATE_PATCH03,\n\tTEMPLATE_PATCH04,\n\tTEMPLATE_PATCH07,\n\tTEMPLATE_PATCH08,\n\tTEMPLATE_PATCH13,\n\tTEMPLATE_PATCH14,\n\tTEMPLATE_PATCH15,\n\tTEMPLATE_RIVER01,\n\tTEMPLATE_RIVER02,\n\tTEMPLATE_RIVER03,\n\tTEMPLATE_RIVER04,\n\tTEMPLATE_RIVER05,\n\tTEMPLATE_RIVER06,\n\tTEMPLATE_RIVER07,\n\tTEMPLATE_RIVER08,\n\tTEMPLATE_RIVER09,\n\tTEMPLATE_RIVER10,\n\tTEMPLATE_RIVER11,\n\tTEMPLATE_RIVER12,\n\tTEMPLATE_RIVER13,\n\tTEMPLATE_FALLS1,\n\tTEMPLATE_FALLS1A,\n\tTEMPLATE_FALLS2,\n\tTEMPLATE_FALLS2A,\n\tTEMPLATE_FORD1,\n\tTEMPLATE_FORD2,\n\tTEMPLATE_BRIDGE1,\n\tTEMPLATE_BRIDGE1D,\n\tTEMPLATE_BRIDGE2,\n\tTEMPLATE_BRIDGE2D,\n\tTEMPLATE_SLOPE01,\n\tTEMPLATE_SLOPE02,\n\tTEMPLATE_SLOPE03,\n\tTEMPLATE_SLOPE04,\n\tTEMPLATE_SLOPE05,\n\tTEMPLATE_SLOPE06,\n\tTEMPLATE_SLOPE07,\n\tTEMPLATE_SLOPE08,\n\tTEMPLATE_SLOPE09,\n\tTEMPLATE_SLOPE10,\n\tTEMPLATE_SLOPE11,\n\tTEMPLATE_SLOPE12,\n\tTEMPLATE_SLOPE13,\n\tTEMPLATE_SLOPE14,\n\tTEMPLATE_SLOPE15,\n\tTEMPLATE_SLOPE16,\n\tTEMPLATE_SLOPE17,\n\tTEMPLATE_SLOPE18,\n\tTEMPLATE_SLOPE19,\n\tTEMPLATE_SLOPE20,\n\tTEMPLATE_SLOPE21,\n\tTEMPLATE_SLOPE22,\n\tTEMPLATE_SLOPE23,\n\tTEMPLATE_SLOPE24,\n\tTEMPLATE_SLOPE25,\n\tTEMPLATE_SLOPE26,\n\tTEMPLATE_SLOPE27,\n\tTEMPLATE_SLOPE28,\n\tTEMPLATE_SLOPE29,\n\tTEMPLATE_SLOPE30,\n\tTEMPLATE_SLOPE31,\n\tTEMPLATE_SLOPE32,\n\tTEMPLATE_SLOPE33,\n\tTEMPLATE_SLOPE34,\n\tTEMPLATE_SLOPE35,\n\tTEMPLATE_SLOPE36,\n\tTEMPLATE_SLOPE37,\n\tTEMPLATE_SLOPE38,\n\tTEMPLATE_ROAD01,\n\tTEMPLATE_ROAD02,\n\tTEMPLATE_ROAD03,\n\tTEMPLATE_ROAD04,\n\tTEMPLATE_ROAD05,\n\tTEMPLATE_ROAD06,\n\tTEMPLATE_ROAD07,\n\tTEMPLATE_ROAD08,\n\tTEMPLATE_ROAD09,\n\tTEMPLATE_ROAD10,\n\tTEMPLATE_ROAD11,\n\tTEMPLATE_ROAD12,\n\tTEMPLATE_ROAD13,\n\tTEMPLATE_ROAD14,\n\tTEMPLATE_ROAD15,\n\tTEMPLATE_ROAD16,\n\tTEMPLATE_ROAD17,\n\tTEMPLATE_ROAD18,\n\tTEMPLATE_ROAD19,\n\tTEMPLATE_ROAD20,\n\tTEMPLATE_ROAD21,\n\tTEMPLATE_ROAD22,\n\tTEMPLATE_ROAD23,\n\tTEMPLATE_ROAD24,\n\tTEMPLATE_ROAD25,\n\tTEMPLATE_ROAD26,\n\tTEMPLATE_ROAD27,\n\tTEMPLATE_ROAD28,\n\tTEMPLATE_ROAD29,\n\tTEMPLATE_ROAD30,\n\tTEMPLATE_ROAD31,\n\tTEMPLATE_ROAD32,\n\tTEMPLATE_ROAD33,\n\tTEMPLATE_ROAD34,\n\tTEMPLATE_ROAD35,\n\tTEMPLATE_ROAD36,\n\tTEMPLATE_ROAD37,\n\tTEMPLATE_ROAD38,\n\tTEMPLATE_ROAD39,\n\tTEMPLATE_ROAD40,\n\tTEMPLATE_ROAD41,\n\tTEMPLATE_ROAD42,\n\tTEMPLATE_ROAD43,\n\tTEMPLATE_ROUGH01,\n\tTEMPLATE_ROUGH02,\n\tTEMPLATE_ROUGH03,\n\tTEMPLATE_ROUGH04,\n\tTEMPLATE_ROUGH05,\n\tTEMPLATE_ROUGH06,\n\tTEMPLATE_ROUGH07,\n\tTEMPLATE_ROUGH08,\n\tTEMPLATE_ROUGH09,\n\tTEMPLATE_ROUGH10,\n\tTEMPLATE_ROUGH11,\n\tTEMPLATE_ROAD44,\n\tTEMPLATE_ROAD45,\n\tTEMPLATE_RIVER14,\n\tTEMPLATE_RIVER15,\n\tTEMPLATE_RIVERCLIFF01,\n\tTEMPLATE_RIVERCLIFF02,\n\tTEMPLATE_RIVERCLIFF03,\n\tTEMPLATE_RIVERCLIFF04,\n\tTEMPLATE_BRIDGE_1A,\n\tTEMPLATE_BRIDGE_1B,\n\tTEMPLATE_BRIDGE_1C,\n\tTEMPLATE_BRIDGE_2A,\n\tTEMPLATE_BRIDGE_2B,\n\tTEMPLATE_BRIDGE_2C,\n\tTEMPLATE_BRIDGE_3A,\n\tTEMPLATE_BRIDGE_3B,\n\tTEMPLATE_BRIDGE_3C,\n\tTEMPLATE_BRIDGE_3D,\n\tTEMPLATE_BRIDGE_3E,\n\tTEMPLATE_BRIDGE_3F,\n\tTEMPLATE_F01,\n\tTEMPLATE_F02,\n\tTEMPLATE_F03,\n\tTEMPLATE_F04,\n\tTEMPLATE_F05,\n\tTEMPLATE_F06,\n\n\t// Custom interior pieces.\n\tTEMPLATE_ARRO0001,\n\tTEMPLATE_ARRO0002,\n\tTEMPLATE_ARRO0003,\n\tTEMPLATE_ARRO0004,\n\tTEMPLATE_ARRO0005,\n\tTEMPLATE_ARRO0006,\n\tTEMPLATE_ARRO0007,\n\tTEMPLATE_ARRO0008,\n\tTEMPLATE_ARRO0009,\n\tTEMPLATE_ARRO0010,\n\tTEMPLATE_ARRO0011,\n\tTEMPLATE_ARRO0012,\n\tTEMPLATE_ARRO0013,\n\tTEMPLATE_ARRO0014,\n\tTEMPLATE_ARRO0015,\n\tTEMPLATE_FLOR0001,\n\tTEMPLATE_FLOR0002,\n\tTEMPLATE_FLOR0003,\n\tTEMPLATE_FLOR0004,\n\tTEMPLATE_FLOR0005,\n\tTEMPLATE_FLOR0006,\n\tTEMPLATE_FLOR0007,\n\tTEMPLATE_GFLR0001,\n\tTEMPLATE_GFLR0002,\n\tTEMPLATE_GFLR0003,\n\tTEMPLATE_GFLR0004,\n\tTEMPLATE_GFLR0005,\n\tTEMPLATE_GSTR0001,\n\tTEMPLATE_GSTR0002,\n\tTEMPLATE_GSTR0003,\n\tTEMPLATE_GSTR0004,\n\tTEMPLATE_GSTR0005,\n\tTEMPLATE_GSTR0006,\n\tTEMPLATE_GSTR0007,\n\tTEMPLATE_GSTR0008,\n\tTEMPLATE_GSTR0009,\n\tTEMPLATE_GSTR0010,\n\tTEMPLATE_GSTR0011,\n\tTEMPLATE_LWAL0001,\n\tTEMPLATE_LWAL0002,\n\tTEMPLATE_LWAL0003,\n\tTEMPLATE_LWAL0004,\n\tTEMPLATE_LWAL0005,\n\tTEMPLATE_LWAL0006,\n\tTEMPLATE_LWAL0007,\n\tTEMPLATE_LWAL0008,\n\tTEMPLATE_LWAL0009,\n\tTEMPLATE_LWAL0010,\n\tTEMPLATE_LWAL0011,\n\tTEMPLATE_LWAL0012,\n\tTEMPLATE_LWAL0013,\n\tTEMPLATE_LWAL0014,\n\tTEMPLATE_LWAL0015,\n\tTEMPLATE_LWAL0016,\n\tTEMPLATE_LWAL0017,\n\tTEMPLATE_LWAL0018,\n\tTEMPLATE_LWAL0019,\n\tTEMPLATE_LWAL0020,\n\tTEMPLATE_LWAL0021,\n\tTEMPLATE_LWAL0022,\n\tTEMPLATE_LWAL0023,\n\tTEMPLATE_LWAL0024,\n\tTEMPLATE_LWAL0025,\n\tTEMPLATE_LWAL0026,\n\tTEMPLATE_LWAL0027,\n\tTEMPLATE_STRP0001,\n\tTEMPLATE_STRP0002,\n\tTEMPLATE_STRP0003,\n\tTEMPLATE_STRP0004,\n\tTEMPLATE_STRP0005,\n\tTEMPLATE_STRP0006,\n\tTEMPLATE_STRP0007,\n\tTEMPLATE_STRP0008,\n\tTEMPLATE_STRP0009,\n\tTEMPLATE_STRP0010,\n\tTEMPLATE_STRP0011,\n\tTEMPLATE_WALL0001,\n\tTEMPLATE_WALL0002,\n\tTEMPLATE_WALL0003,\n\tTEMPLATE_WALL0004,\n\tTEMPLATE_WALL0005,\n\tTEMPLATE_WALL0006,\n\tTEMPLATE_WALL0007,\n\tTEMPLATE_WALL0008,\n\tTEMPLATE_WALL0009,\n\tTEMPLATE_WALL0010,\n\tTEMPLATE_WALL0011,\n\tTEMPLATE_WALL0012,\n\tTEMPLATE_WALL0013,\n\tTEMPLATE_WALL0014,\n\tTEMPLATE_WALL0015,\n\tTEMPLATE_WALL0016,\n\tTEMPLATE_WALL0017,\n\tTEMPLATE_WALL0018,\n\tTEMPLATE_WALL0019,\n\tTEMPLATE_WALL0020,\n\tTEMPLATE_WALL0021,\n\tTEMPLATE_WALL0022,\n\tTEMPLATE_WALL0023,\n\tTEMPLATE_WALL0024,\n\tTEMPLATE_WALL0025,\n\tTEMPLATE_WALL0026,\n\tTEMPLATE_WALL0027,\n\tTEMPLATE_WALL0028,\n\tTEMPLATE_WALL0029,\n\tTEMPLATE_WALL0030,\n\tTEMPLATE_WALL0031,\n\tTEMPLATE_WALL0032,\n\tTEMPLATE_WALL0033,\n\tTEMPLATE_WALL0034,\n\tTEMPLATE_WALL0035,\n\tTEMPLATE_WALL0036,\n\tTEMPLATE_WALL0037,\n\tTEMPLATE_WALL0038,\n\tTEMPLATE_WALL0039,\n\tTEMPLATE_WALL0040,\n\tTEMPLATE_WALL0041,\n\tTEMPLATE_WALL0042,\n\tTEMPLATE_WALL0043,\n\tTEMPLATE_WALL0044,\n\tTEMPLATE_WALL0045,\n\tTEMPLATE_WALL0046,\n\tTEMPLATE_WALL0047,\n\tTEMPLATE_WALL0048,\n\tTEMPLATE_WALL0049,\n\tTEMPLATE_BRIDGE1H,\n\tTEMPLATE_BRIDGE2H,\n\tTEMPLATE_BRIDGE_1AX,\n\tTEMPLATE_BRIDGE_2AX,\n\tTEMPLATE_BRIDGE1X,\n\tTEMPLATE_BRIDGE2X,\n\n\tTEMPLATE_XTRA0001,\n\tTEMPLATE_XTRA0002,\n\tTEMPLATE_XTRA0003,\n\tTEMPLATE_XTRA0004,\n\tTEMPLATE_XTRA0005,\n\tTEMPLATE_XTRA0006,\n\tTEMPLATE_XTRA0007,\n\tTEMPLATE_XTRA0008,\n\tTEMPLATE_XTRA0009,\n\tTEMPLATE_XTRA0010,\n\tTEMPLATE_XTRA0011,\n\tTEMPLATE_XTRA0012,\n\tTEMPLATE_XTRA0013,\n\tTEMPLATE_XTRA0014,\n\tTEMPLATE_XTRA0015,\n\tTEMPLATE_XTRA0016,\n\n#ifdef FIXIT_ANTS\n\tTEMPLATE_HILL01,\n#endif\n\n\n\tTEMPLATE_COUNT,\n\tTEMPLATE_NONE=65535,\n\tTEMPLATE_FIRST=0\n} TemplateType;\n\n//PG inline TemplateType operator++(TemplateType &, int);\ninline TemplateType operator++(TemplateType &n) { n = (TemplateType)(((int)n) + 1); return n; }\n\n/**********************************************************************\n**\tThe three dimensional terrain objects are enumerated here. These\n**\tobjects function similar to buildings in that they can be driven\n**\tbehind and can take damage on an individual basis.\n*/\ntypedef enum TerrainType : char {\n\tTERRAIN_NONE=-1,\n\tTERRAIN_TREE1,\n\tTERRAIN_TREE2,\n\tTERRAIN_TREE3,\n\tTERRAIN_TREE5,\n\tTERRAIN_TREE6,\n\tTERRAIN_TREE7,\n\tTERRAIN_TREE8,\n\tTERRAIN_TREE10,\n\tTERRAIN_TREE11,\n\tTERRAIN_TREE12,\n\tTERRAIN_TREE13,\n\tTERRAIN_TREE14,\n\tTERRAIN_TREE15,\n\tTERRAIN_TREE16,\n\tTERRAIN_TREE17,\n\tTERRAIN_CLUMP1,\n\tTERRAIN_CLUMP2,\n\tTERRAIN_CLUMP3,\n\tTERRAIN_CLUMP4,\n\tTERRAIN_CLUMP5,\n\n\tTERRAIN_ICE01,\n\tTERRAIN_ICE02,\n\tTERRAIN_ICE03,\n\tTERRAIN_ICE04,\n\tTERRAIN_ICE05,\n\n\tTERRAIN_BOXES01,\n\tTERRAIN_BOXES02,\n\tTERRAIN_BOXES03,\n\tTERRAIN_BOXES04,\n\tTERRAIN_BOXES05,\n\tTERRAIN_BOXES06,\n\tTERRAIN_BOXES07,\n\tTERRAIN_BOXES08,\n\tTERRAIN_BOXES09,\n\n\tTERRAIN_MINE,\n\n\tTERRAIN_COUNT,\n\tTERRAIN_FIRST=0\n} TerrainType;\n\n//PG inline TerrainType operator++(TerrainType &, int);\n\n\n/**********************************************************************\n**\tSmudges are enumerated here. Smudges are transparent icons that are\n**\tdrawn over the underlying terrain in order to give the effect of\n**\talterations to the terrain. Craters are a good example of this.\n*/\ntypedef enum SmudgeType : char {\n\tSMUDGE_NONE=-1,\n\tSMUDGE_CRATER1,\n\tSMUDGE_CRATER2,\n\tSMUDGE_CRATER3,\n\tSMUDGE_CRATER4,\n\tSMUDGE_CRATER5,\n\tSMUDGE_CRATER6,\n\tSMUDGE_SCORCH1,\n\tSMUDGE_SCORCH2,\n\tSMUDGE_SCORCH3,\n\tSMUDGE_SCORCH4,\n\tSMUDGE_SCORCH5,\n\tSMUDGE_SCORCH6,\n\tSMUDGE_BIB1,\n\tSMUDGE_BIB2,\n\tSMUDGE_BIB3,\n\n\tSMUDGE_COUNT,\n\tSMUDGE_FIRST=0\n} SmudgeType;\n\n//PG inline SmudgeType operator++(SmudgeType &, int);\n\n\n/**********************************************************************\n**\tAnimations are enumerated here. Animations are the high speed and\n**\tshort lived effects that occur with explosions and fire.\n*/\ntypedef enum AnimType : char {\n\tANIM_NONE=-1,\n\tANIM_FBALL1,\t\t\t\t\t// Large fireball explosion (bulges rightward).\n\tANIM_FBALL_FADE,\t\t\t\t// Fading fireball puff.\n\tANIM_FRAG1,\t\t\t\t\t\t// Medium fragment throwing explosion -- short decay.\n\tANIM_VEH_HIT1,\t\t\t\t\t//\tSmall fireball explosion (bulges rightward).\n\tANIM_VEH_HIT2,\t\t\t\t\t//\tSmall fragment throwing explosion -- pop & sparkles.\n\tANIM_VEH_HIT3,\t\t\t\t\t// Small fragment throwing explosion -- burn/exp mix.\n\tANIM_ART_EXP1,\t\t\t\t\t// Large fragment throwing explosion -- many sparkles.\n\tANIM_NAPALM1,\t\t\t\t\t// Small napalm burn.\n\tANIM_NAPALM2,\t\t\t\t\t// Medium napalm burn.\n\tANIM_NAPALM3,\t\t\t\t\t// Large napalm burn.\n\tANIM_SMOKE_PUFF,\t\t\t\t// Small rocket smoke trail puff.\n\tANIM_PIFF,\t\t\t\t\t\t// Machine gun impact piffs.\n\tANIM_PIFFPIFF,\t\t\t\t\t// Chaingun impact piffs.\n\tANIM_FIRE_SMALL,\t\t\t\t// Small flame animation.\n\tANIM_FIRE_MED,\t\t\t\t\t// Medium flame animation.\n\tANIM_FIRE_MED2,\t\t\t\t// Medium flame animation (oranger).\n\tANIM_FIRE_TINY,\t\t\t\t// Very tiny flames.\n\tANIM_MUZZLE_FLASH,\t\t\t// Big cannon flash (with translucency).\n\tANIM_SMOKE_M,\t\t\t\t\t// Smoke rising from ground.\n\tANIM_BURN_SMALL,\t\t\t\t// Small combustible fire effect (with trail off).\n\tANIM_BURN_MED,\t\t\t\t\t// Medium combustible fire effect (with trail off).\n\tANIM_BURN_BIG,\t\t\t\t\t// Large combustible fire effect (with trail off).\n\tANIM_ON_FIRE_SMALL,\t\t\t// Burning effect for buildings.\n\tANIM_ON_FIRE_MED,\t\t\t\t// Burning effect for buildings.\n\tANIM_ON_FIRE_BIG,\t\t\t\t// Burning effect for buildings.\n\tANIM_SAM_N,\n\tANIM_SAM_NE,\n\tANIM_SAM_E,\n\tANIM_SAM_SE,\n\tANIM_SAM_S,\n\tANIM_SAM_SW,\n\tANIM_SAM_W,\n\tANIM_SAM_NW,\n\tANIM_GUN_N,\n\tANIM_GUN_NE,\n\tANIM_GUN_E,\n\tANIM_GUN_SE,\n\tANIM_GUN_S,\n\tANIM_GUN_SW,\n\tANIM_GUN_W,\n\tANIM_GUN_NW,\n\tANIM_LZ_SMOKE,\n\tANIM_CRATE_DEVIATOR,\t\t\t// Red finned missile.\n\tANIM_CRATE_DOLLAR,\t\t\t// Dollar sign.\n\tANIM_CRATE_EARTH,\t\t\t\t// Cracked Earth.\n\tANIM_CRATE_EMPULSE,\t\t\t// Plasma ball.\n\tANIM_CRATE_INVUN,\t\t\t\t// Orange sphere with green rings.\n\tANIM_CRATE_MINE,\t\t\t\t// Spiked mine.\n\tANIM_CRATE_RAPID,\t\t\t\t// Red skull.\n\tANIM_CRATE_STEALTH,\t\t\t// Cloaking sphere.\n\tANIM_CRATE_MISSILE,\t\t\t// Green finned missile.\n\tANIM_MOVE_FLASH,\n\tANIM_OILFIELD_BURN,\n\tANIM_ELECT_DIE,\t\t\t\t// Electrocution infantryman death from Tesla coil\n\tANIM_PARACHUTE,\t\t\t\t// Parachute (designed to be attached to object).\n\tANIM_DOG_ELECT_DIE,\t\t\t// Electrocution dog death from Tesla coil\n\tANIM_CORPSE1,\n\tANIM_CORPSE2,\n\tANIM_CORPSE3,\n\tANIM_SPUTDOOR,\n\tANIM_ATOM_BLAST,\n\tANIM_CHRONO_BOX,\n\tANIM_GPS_BOX,\n\tANIM_INVUL_BOX,\n\tANIM_PARA_BOX,\n\tANIM_SONAR_BOX,\n\tANIM_TWINKLE1,\n\tANIM_TWINKLE2,\n\tANIM_TWINKLE3,\n\tANIM_FLAK,\n\tANIM_WATER_EXP1,\n\tANIM_WATER_EXP2,\n\tANIM_WATER_EXP3,\n\tANIM_CRATE_ARMOR,\n\tANIM_CRATE_SPEED,\n\tANIM_CRATE_FPOWER,\n\tANIM_CRATE_TQUAKE,\n\tANIM_PARA_BOMB,\n\tANIM_MINE_EXP1,\n\tANIM_FLAG,\n\tANIM_BEACON,\n\n#ifdef FIXIT_ANTS\n\tANIM_ANT1_DEATH,\n\tANIM_ANT2_DEATH,\n\tANIM_ANT3_DEATH,\n#endif\n\n\tANIM_FIRE_SMALL_VIRTUAL,\t\t\t// Small flame animation.\n\tANIM_FIRE_MED_VIRTUAL,\t\t\t\t// Medium flame animation.\n\tANIM_FIRE_MED2_VIRTUAL,\t\t\t\t// Medium flame animation (oranger).\n\tANIM_FIRE_TINY_VIRTUAL,\t\t\t\t// Very tiny flames.\n\tANIM_BEACON_VIRTUAL,\t\t// Beacon (virtual).\n\n\tANIM_COUNT,\n\tANIM_FIRST=0\n} AnimType;\n\n\ninline AnimType operator++(AnimType &, int);\n\n\n/****************************************************************************\n**\tInfantry can be performing various activities. These can range from simple\n**\tidle animations to physical hand to hand combat.\n*/\ntypedef enum DoType : char {\n\tDO_NOTHING=-1,\t\t\t\t// Not performing any choreographed sequence.\n\tDO_STAND_READY=0,\n\tDO_STAND_GUARD,\n\tDO_PRONE,\n\tDO_WALK,\n\tDO_FIRE_WEAPON,\n\tDO_LIE_DOWN,\n\tDO_CRAWL,\n\tDO_GET_UP,\n\tDO_FIRE_PRONE,\n\tDO_IDLE1,\n\tDO_IDLE2,\n\tDO_GUN_DEATH,\n\tDO_EXPLOSION_DEATH,\n\tDO_EXPLOSION2_DEATH,\n\tDO_GRENADE_DEATH,\n\tDO_FIRE_DEATH,\n\tDO_GESTURE1,\n\tDO_SALUTE1,\n\tDO_GESTURE2,\n\tDO_SALUTE2,\n\tDO_DOG_MAUL,\n\n\tDO_COUNT,\n\tDO_FIRST=0\n} DoType;\n\ninline DoType operator++(DoType &, int);\n\n/*\n**\tThis structure is associated with each maneuver type. It tells whether the\n**\tmaneuver can be interrupted and the frame rate.\n*/\ntypedef struct {\n\tunsigned Interrupt:1;\t// Can it be interrupted?\n\tunsigned IsMobile:1;\t\t// Can it move while doing this?\n\tunsigned RandomStart:1;\t// Should animation be \"randomized\"?\n\tunsigned char Rate;\t\t// Frame rate.\n} DoStruct;\n\ntypedef struct {\n\tint\t\t\t\tFrame;\t// Starting frame of the animation.\n\tunsigned char\tCount;\t// Number of frames of animation.\n\tunsigned char\tJump;\t\t// Frames to jump between facings.\n} DoInfoStruct;\n\n\n/****************************************************************************\n**\tThese are the various radio message that can be transmitted between\n**\tunits and buildings. Some of these require a response from the receiver\n**\tand some don't.\n*/\ntypedef enum RadioMessageType : unsigned char {\n\tRADIO_STATIC,\t\t\t\t// \"hisssss\" -- non-message\n\tRADIO_ROGER,\t\t\t\t// \"Roger.\"\n\tRADIO_HELLO,\t\t\t\t// \"Come in. I wish to talk.\"\n\tRADIO_OVER_OUT,\t\t\t// \"Something came up, bye.\"\n\tRADIO_PICK_UP,\t\t\t\t// \"Please pick me up.\"\n\tRADIO_ATTACH,\t\t\t\t// \"Attach to transport.\"\n\tRADIO_DELIVERY,\t\t\t// \"I've got a delivery for you.\"\n\tRADIO_HOLD_STILL,\t\t\t// \"I'm performing load/unload maneuver. Be careful.\"\n\tRADIO_UNLOADED,\t\t\t// \"I'm clear.\"\n\tRADIO_UNLOAD,\t\t\t\t// \"You are clear to unload. Please start driving off now.\"\n\tRADIO_NEGATIVE,\t\t\t// \"Am unable to comply.\"\n\tRADIO_BUILDING,\t\t\t// \"I'm starting construction now... act busy.\"\n\tRADIO_COMPLETE,\t\t\t// \"I've finished construction. You are free.\"\n\tRADIO_REDRAW,\t\t\t\t// \"Oops, sorry. I might have bumped you a little.\"\n\tRADIO_DOCKING,\t\t\t\t// \"I'm trying to load up now.\"\n\tRADIO_CAN_LOAD,\t\t\t// \"May I become a passenger?\"\n\tRADIO_ARE_REFINERY,\t\t// \"Are you a refinery ready to take shipment?\"\n\tRADIO_TRYING_TO_LOAD,\t// \"Are you trying to become a passenger?\"\n\tRADIO_MOVE_HERE,\t\t\t// \"Move to location X.\"\n\tRADIO_NEED_TO_MOVE,\t\t// \"Do you need to move somewhere?\"\n\tRADIO_YEA_NOW_WHAT,\t\t// \"All right already. Now what?\"\n\tRADIO_IM_IN,\t\t\t\t// \"I'm a passenger now.\"\n\tRADIO_BACKUP_NOW,\t\t\t// \"Begin backup into refinery now.\"\n\tRADIO_RUN_AWAY,\t\t\t// \"Run away! Run away!\"\n\tRADIO_TETHER,\t\t\t\t// \"Establish tether contact.\"\n\tRADIO_UNTETHER,\t\t\t// \"Break tether contact.\"\n\tRADIO_REPAIR,\t\t\t\t// \"Repair one step.\"\n\tRADIO_PREPARED,\t\t\t// \"Are you prepared to fight?\"\n\tRADIO_ATTACK_THIS,\t\t// \"Attack this target please.\"\n\tRADIO_RELOAD,\t\t\t\t// \"Reload one step please.\"\n\tRADIO_CANT,\t\t\t\t\t// \"Circumstances prevent success.\"\n\tRADIO_ALL_DONE,\t\t\t// \"I have completed the task.\"\n\tRADIO_NEED_REPAIR,\t\t// \"Are you in need of service depot work?\"\n\tRADIO_ON_DEPOT,\t\t\t// \"Are you sitting on a service depot?\"\n\n\tRADIO_COUNT\n} RadioMessageType;\n\n\n/****************************************************************************\n**\tVarious trigger events and actions require additional data. This enumeration is\n**\tused to indicate what kind of additional data is required. This is also used\n**\tfor team mission types that might need additional data.\n*/\ntypedef enum NeedType : unsigned char {\n\tNEED_NONE,\t\t\t\t\t// No additional data is required.\n\tNEED_THEME,\t\t\t\t\t// Need a musical theme.\n\tNEED_MOVIE,\t\t\t\t\t// Need a movie to play.\n\tNEED_SOUND,\t\t\t\t\t// Sound effect.\n\tNEED_SPEECH,\t\t\t\t// Speech from EVA.\n\tNEED_INFANTRY,\t\t\t\t// Infantry type class.\n\tNEED_UNIT,\t\t\t\t\t// Unit type class.\n\tNEED_AIRCRAFT,\t\t\t\t// Aircraft type class.\n\tNEED_STRUCTURE,\t\t\t// Structure type class.\n\tNEED_WAYPOINT,\t\t\t\t// Waypoint letter.\n\tNEED_NUMBER,\t\t\t\t// General number.\n\tNEED_TRIGGER,\t\t\t\t//\tTrigger object reference.\n\tNEED_TEAM,\t\t\t\t\t// Team type class.\n\tNEED_HOUSE,\t\t\t\t\t// House type number.\n\tNEED_TIME,\t\t\t\t\t// Time delay value required.\n\tNEED_QUARRY,\t\t\t\t// Quarry type is needed.\n\tNEED_FORMATION,\t\t\t// A formation type is needed.\n\tNEED_BOOL,\t\t\t\t\t// Boolean value is needed.\n\tNEED_SPECIAL,\t\t\t\t// Special weapon ability.\n\tNEED_MISSION,\t\t\t\t// General unit mission type.\n\tNEED_HEX_NUMBER\t\t\t// General number.\n} NeedType;\n\n\n/****************************************************************************\n**\tThere are various target types that teams and special weapons can be\n**\tassigned to attack. These are general target categories since the actual\n**\tdisposition of potential targets cannot be precisely predicted -- thus these\n**\tserve as guidelines for the computer AI.\n*/\ntypedef enum QuarryType : unsigned char {\n\tQUARRY_NONE,\n\n\tQUARRY_ANYTHING,\t\t\t\t\t// Attack any enemy (same as \"hunt\").\n\tQUARRY_BUILDINGS,\t\t\t\t\t// Attack buildings (in general).\n\tQUARRY_HARVESTERS,\t\t\t\t// Attack harvesters or refineries.\n\tQUARRY_INFANTRY,\t\t\t\t\t// Attack infantry.\n\tQUARRY_VEHICLES,\t\t\t\t\t// Attack combat vehicles.\n\tQUARRY_VESSELS,\t\t\t\t\t// Attach ships.\n\tQUARRY_FACTORIES,\t\t\t\t\t// Attack factories (all types).\n\tQUARRY_DEFENSE,\t\t\t\t\t// Attack base defense buildings.\n\tQUARRY_THREAT,\t\t\t\t\t\t// Attack enemies near friendly base.\n\tQUARRY_POWER,\t\t\t\t\t\t// Attack power facilities.\n\tQUARRY_FAKES,\t\t\t\t\t\t// Prefer to attack fake buildings.\n\n\tQUARRY_COUNT,\n\tQUARRY_FIRST=0\n} QuarryType;\n\n\n/****************************************************************************\n**\tTeams can be assigned formations. This specifies the various formations that\n**\ta team can be composed into.\n*/\ntypedef enum FormationType : unsigned char {\n\tFORMATION_NONE,\n\n\tFORMATION_TIGHT,\t\t\t\t// Tight grouping (vulnerable units in center).\n\tFORMATION_LOOSE,\t\t\t\t// Loose grouping (one cell separation between units).\n\tFORMATION_WEDGE_N,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_E,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_S,\t\t\t// Wedge shape.\n\tFORMATION_WEDGE_W,\t\t\t// Wedge shape.\n\tFORMATION_LINE_NS,\t\t\t// Column formation.\n\tFORMATION_LINE_EW,\t\t\t// Line formation.\n\n\tFORMATION_COUNT,\n\tFORMATION_FIRST=0\n} FormationType;\n\n\n/****************************************************************************\n**\tSelected units have a special selected unit box around them. These are the\n**\tdefines for the two types of selected unit boxes. One is for infantry and\n**\tthe other is for regular units.\n*/\ntypedef enum SelectEnum : char {\n\tSELECT_NONE=-1,\n\tSELECT_INFANTRY,\t\t\t\t\t// Small infantry selection box.\n\tSELECT_UNIT,\t\t\t\t\t\t// Big unit selection box.\n\tSELECT_BUILDING=SELECT_UNIT,\t// Custom box for buildings.\n\tSELECT_TERRAIN=SELECT_UNIT,\t// Custom box for terrain objects.\n\tSELECT_WRENCH,\t\t\t\t\t\t// A building is repairing overlay graphic.\n\n\tSELECT_COUNT\n} SelectEnum;\n\n\n/****************************************************************************\n**\tThe pip shapes and text shapes are enumerated according to the following\n**\ttype. These special shapes are drawn over special objects or in other places\n**\twhere shape technology is needed.\n*/\ntypedef enum PipEnum : unsigned char \n{\n\tPIP_EMPTY,\t\t\t// Empty pip spot.\n\tPIP_FULL,\t\t\t// Full pip spot.\n\tPIP_PRIMARY,\t\t// \"Primary\" building marker.\n\tPIP_READY,\t\t\t// \"Ready\" construction information tag.\n\tPIP_HOLDING,\t\t// \"Hold\"ing construction information tag.\n\tPIP_ENGINEER,\t\t// Full pip with engineer coloring.\n\tPIP_CIVILIAN,\t\t// Full pip with civilian coloring.\n\tPIP_COMMANDO,\t\t// Full pip with commando coloring.\n\tPIP_NUMBERS,\t\t// digit 0\n\tPIP_NUMBER1,\t\t// digit 1\n\tPIP_NUMBER2,\t\t// digit 2\n\tPIP_NUMBER3,\t\t// digit 3\n\tPIP_NUMBER4,\t\t// digit 4\n\tPIP_NUMBER5,\t\t// digit 5\n\tPIP_NUMBER6,\t\t// digit 6\n\tPIP_NUMBER7,\t\t// digit 7\n\tPIP_NUMBER8,\t\t// digit 8\n\tPIP_NUMBER9,\t\t// digit 9\n\tPIP_DECOY,\t\t\t// word \"Decoy\" for fake buildings\n\tPIP_LETTERF,\t\t// letter 'F' for signifying in-formation\n\tPIP_MEDIC,\t\t\t// Little medic red cross.\n\tPIP_PRI\t\t\t\t// Abbreviated \"Primary\" for kennel\n} PipEnum;\n\n\n/****************************************************************************\n**\tThe radar map can be in one of several states depending on the presense of\n**\tcertain structures and power levels.\n*/\ntypedef enum RadarEnum : unsigned char\n{\n\tRADAR_NONE,\t// Radar map doesn't exist at all\n\tRADAR_OFF,\t// Radar map is present, but displayed as off and non-interactive\n\tRADAR_ON\t// Radar map is present, visible, and fully interactive\n} RadarEnum;\n\n\n/****************************************************************************\n**\tThe mouse cursor can be in different states. These states are listed\n**\tbelow. Some of these represent animating mouse cursors. The mouse\n**\tis controlled by passing one of these values to the appropriate\n**\tMouseClass member function.\n*/\ntypedef enum MouseType : unsigned char\n{\n\tMOUSE_NORMAL,\n\tMOUSE_N,\n\tMOUSE_NE,\n\tMOUSE_E,\n\tMOUSE_SE,\n\tMOUSE_S,\n\tMOUSE_SW,\n\tMOUSE_W,\n\tMOUSE_NW,\n\tMOUSE_NO_N,\n\tMOUSE_NO_NE,\n\tMOUSE_NO_E,\n\tMOUSE_NO_SE,\n\tMOUSE_NO_S,\n\tMOUSE_NO_SW,\n\tMOUSE_NO_W,\n\tMOUSE_NO_NW,\n\tMOUSE_NO_MOVE,\n\tMOUSE_CAN_MOVE,\n\tMOUSE_ENTER,\n\tMOUSE_DEPLOY,\n\tMOUSE_CAN_SELECT,\n\tMOUSE_CAN_ATTACK,\n\tMOUSE_SELL_BACK,\n\tMOUSE_SELL_UNIT,\n\tMOUSE_REPAIR,\n\tMOUSE_NO_REPAIR,\n\tMOUSE_NO_SELL_BACK,\n\tMOUSE_RADAR_CURSOR,\n\tMOUSE_NUCLEAR_BOMB,\n\tMOUSE_AIR_STRIKE,\n\tMOUSE_DEMOLITIONS,\n\tMOUSE_AREA_GUARD,\n\tMOUSE_HEAL,\n\tMOUSE_DAMAGE,\t\t\t\t\t// Engineer entering building to damage it.\n\tMOUSE_GREPAIR,\t\t\t\t\t// Engineer entering friendly building to heal it.\n\tMOUSE_STAY_ATTACK,\n\tMOUSE_NO_DEPLOY,\n\tMOUSE_NO_ENTER,\n\tMOUSE_NO_GREPAIR,\n\tMOUSE_CHRONO_SELECT,\n\tMOUSE_CHRONO_DEST,\n\n\tMOUSE_COUNT\n} MouseType;\n\n\n/**********************************************************************\n**\tThis structure is used to control the box relief style drawn by\n**\tthe Draw_Box() function.\n*/\ntypedef struct {\n\tint\tFiller;\t\t// Center box fill color.\n\tint\tShadow;\t\t// Shadow color (darker).\n\tint\tHighlight;\t// Highlight color (lighter).\n\tint\tCorner;\t\t// Corner color (transition).\n} BoxStyleType;\n\ntypedef enum BoxStyleEnum : unsigned char {\n\tBOXSTYLE_DOWN,\t\t\t\t\t// Typical depressed edge border.\n\tBOXSTYLE_RAISED,\t\t\t\t// Typical raised edge border.\n\tBOXSTYLE_DIS_DOWN,\t\t\t// Disabled but depressed.\n\tBOXSTYLE_DIS_RAISED,\t\t\t// Disabled but raised.\n\tBOXSTYLE_BOX,\t\t\t\t\t// list box.\n\tBOXSTYLE_BORDER,\t\t\t\t// main dialog box.\n\n\tBOXSTYLE_COUNT\n} BoxStyleEnum;\n\n\n/**********************************************************************\n**\tDamage, as inflicted by projectiles, has different characteristics.\n**\tThese are the different \"warhead\" types that can be assigned to the\n**\tvarious projectiles in the game.\n*/\ntypedef enum WarheadType : char {\n\tWARHEAD_NONE=-1,\n\n\tWARHEAD_SA,\t\t\t\t\t// Small arms -- good against infantry.\n\tWARHEAD_HE,\t\t\t\t\t//\tHigh explosive -- good against buildings & infantry.\n\tWARHEAD_AP,\t\t\t\t\t// Armor piercing -- good against armor.\n\tWARHEAD_FIRE,\t\t\t\t// Incendiary -- Good against flammables.\n\tWARHEAD_HOLLOW_POINT,\t// Sniper bullet type.\n\tWARHEAD_TESLA,\t\t\t\t// Electrocution warhead for infantrymen\n\tWARHEAD_DOG,\t\t\t\t// Slavering attack beast mauling infantryman\n\tWARHEAD_NUKE,\t\t\t\t// Nuclear missile\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tWARHEAD_MECHANICAL,\t\t// repair weapon for vehicles\n#endif\n\tWARHEAD_COUNT,\n\tWARHEAD_FIRST=0\n} WarheadType;\n\n\n/**********************************************************************\n**\tThis enumerates the various weapon types. The weapon is characterized\n**\tby the projectile it launches, the damage it does, and the rate of\n**\tfire.\n*/\ntypedef enum WeaponType : char {\n\tWEAPON_NONE=-1,\n\n\tWEAPON_COLT45,\n\tWEAPON_ACK_ACK,\n\tWEAPON_VULCAN,\n\tWEAPON_MAVERICK,\n\tWEAPON_CAMERA,\n\tWEAPON_FIREBALL,\n\tWEAPON_RIFLE,\n\tWEAPON_CHAIN_GUN,\n\tWEAPON_PISTOL,\n\tWEAPON_M16,\n\tWEAPON_DRAGON,\n\tWEAPON_HELLFIRE,\n\tWEAPON_GRENADE,\n\tWEAPON_75MM,\n\tWEAPON_90MM,\n\tWEAPON_105MM,\n\tWEAPON_120MM,\n\tWEAPON_TURRET_GUN,\n\tWEAPON_MAMMOTH_TUSK,\n\tWEAPON_155MM,\n\tWEAPON_M60MG,\n\tWEAPON_NAPALM,\n\tWEAPON_TESLA_ZAP,\n\tWEAPON_NIKE,\n\tWEAPON_8INCH,\n\tWEAPON_STINGER,\n\tWEAPON_TORPEDO,\n\tWEAPON_2INCH,\n\tWEAPON_DEPTH_CHARGE,\n\tWEAPON_PARA_BOMB,\n\tWEAPON_DOGJAW,\n\tWEAPON_HEAL,\n\tWEAPON_SCUD,\n\tWEAPON_FLAMER,\n\tWEAPON_REDEYE,\n\n#ifdef FIXIT_ANTS\n\tWEAPON_MANDIBLE,\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tWEAPON_PORTATESLA,\n\tWEAPON_GOODWRENCH,\n\tWEAPON_SUBSCUD,\n\tWEAPON_TTANKZAP,\n\tWEAPON_APTUSK,\n\tWEAPON_DEMOCHARGE,\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tWEAPON_CARRIER,\n#endif\n\n\n\tWEAPON_COUNT,\n\tWEAPON_FIRST=0\n} WeaponType;\n\n\n/**********************************************************************\n**\tThe various armor types are best suited to defend against a limited\n**\tkind of warheads. The game strategy revolves around proper\n**\tcombination of armor and weaponry. Each vehicle or building has armor\n**\trated according to one of the following types.\n*/\ntypedef enum ArmorType : unsigned char {\n\tARMOR_NONE,\t\t\t// Vulnerable to SA and HE.\n\tARMOR_WOOD,\t\t\t// Vulnerable to HE and Fire.\n\tARMOR_ALUMINUM,\t// Vulnerable to AP and SA.\n\tARMOR_STEEL,\t\t// Vulnerable to AP.\n\tARMOR_CONCRETE,\t// Vulnerable to HE and AP.\n\n\tARMOR_COUNT,\n\tARMOR_FIRST=0\n} ArmorType;\n\n\n/**********************************************************************\n**\tThese are the identifiers for the various monochrome debug screens.\n*/\ntypedef enum DMonoType : unsigned char {\n\tDMONO_OBJECT,\n\tDMONO_HOUSE,\n\tDMONO_STRESS,\n\tDMONO_EVENTS,\n\n\tDMONO_COUNT,\n\tDMONO_FIRST=0\n} DMonoType;\n\n/*\n**\tPerformance benchmark tracking identifiers.\n*/\ntypedef enum BenchType : unsigned char {\n\tBENCH_GAME_FRAME,\t\t\t// Whole game frame (used for normalizing).\n\tBENCH_FINDPATH,\t\t\t// Find path calls.\n\tBENCH_GREATEST_THREAT,\t// Greatest threat calculation.\n\tBENCH_AI,\t\t\t\t\t// Object AI calls.\n\tBENCH_CELL,\t\t\t\t\t// Cell draw it function.\n\tBENCH_SIDEBAR,\t\t\t\t// Sidebar (just cameo section) drawing.\n\tBENCH_RADAR,\t\t\t\t// Radar map drawing.\n\tBENCH_TACTICAL,\t\t\t// Whole tactical map.\n\tBENCH_PCP,\t\t\t\t\t// Per cell process.\n\tBENCH_EVAL_OBJECT,\t\t// Evaluate object as potential target.\n\tBENCH_EVAL_CELL,\t\t\t// Evaluate entire cell for potential targets.\n\tBENCH_EVAL_WALL,\t\t\t// Evaluate wall in cell as potential target.\n\n\tBENCH_POWER,\t\t\t\t// Power bar drawing.\n\tBENCH_TABS,\t\t\t\t\t// Tab section (top) drawing.\n\tBENCH_SHROUD,\t\t\t\t// Shroud layer drawing.\n\tBENCH_ANIMS,\t\t\t\t// Animations drawing.\n\tBENCH_OBJECTS,\t\t\t\t// All game object drawing.\n\tBENCH_PALETTE,\t\t\t\t// Color cycling palette adjustments.\n\tBENCH_GSCREEN_RENDER,\t// Rendering of the whole map layered system (with blits).\n\tBENCH_BLIT_DISPLAY,\t\t// DirectX or shadow blit of hidpage to seenpage.\n\tBENCH_MISSION,\t\t\t\t// Mission list processing.\n\n\tBENCH_RULES,\t\t\t\t// Processing of the rules.ini file.\n\tBENCH_SCENARIO,\t\t\t// Processing of the scenario.ini file.\n\n\tBENCH_COUNT,\n\tBENCH_FIRST=0\n} BenchType;\n\n\n#ifdef CHEAT_KEYS\n#define\tBStart(a)\tif (Benches != NULL) Benches[a].Begin()\n#define\tBEnd(a)\t\tif (Benches != NULL) Benches[a].End()\n#else\n#define\tBStart(a)\n#define\tBEnd(a)\n#endif\n\n\n/**********************************************************************\n**\tWorking MCGA colors that give a pleasing effect for beveled edges and\n**\tother purposes.\n*/\n#define\tMAGIC_COL_COUNT\t13\t\t// Translucent color count.\n#define\tSHADOW_COL_COUNT\t4\t\t// Terrain shroud translucent color count.\n#define\tUSHADOW_COL_COUNT\t1\t\t// Unit shadow special ghost colors.\n\n\n/**********************************************************************\n**\tColor cycling range that is used for water effects.\n*/\n#define\tCYCLE_COLOR_START\t\t(6*16)\n#define\tCYCLE_COLOR_COUNT\t\t7\n\n\n/**********************************************************************\n**\tMagic color fading pulsing effect limits -- color gun value.\n*/\n#define\tCC_PULSE_COLOR\t\t\t255\n#define\tCC_EMBER_COLOR\t\t\t(CYCLE_COLOR_START+CYCLE_COLOR_COUNT)\n\n\n/**********************************************************************\n**\tThese are the control flags for Fancy_Text_Print function.\n*/\ntypedef enum TextPrintType : unsigned short {\n\tTPF_LASTPOINT\t\t=0x0000,\t\t// Use previous font point value.\n\tTPF_6POINT\t\t\t=0x0001,\t\t// Use 6 point font.\n\tTPF_8POINT\t\t\t=0x0002,\t\t// Use 8 point font.\n\tTPF_3POINT\t\t\t=0x0003,\t\t// Use 3 point font.\n\tTPF_LED\t\t\t\t=0x0004,\t\t// Use LED font.\n\tTPF_VCR\t\t\t\t=0x0005,\t\t// Use VCR font.\n\tTPF_6PT_GRAD\t\t=0x0006,\t\t// Use 6 point gradient font.\n\tTPF_MAP\t\t\t\t=0x0007,\t\t// Font used for popup help text.\n\tTPF_METAL12\t\t\t=0x0008,    // Use 12 point tab font\n\tTPF_EFNT\t\t\t\t=0x0009,\t\t// Use scenario editor font.\n\tTPF_TYPE\t\t\t\t=0x000A,\t\t// Use teletype font\n\tTPF_SCORE\t\t\t=0x000B,\t\t// Use score screen font.\n\tTPF_LASTSHADOW\t\t=0x0000,\t\t// Use previous font palette.\n\tTPF_NOSHADOW\t\t=0x0010,\t\t// Don't have any shadow.\n\tTPF_DROPSHADOW\t\t=0x0020,\t\t//\tUse a simple drop shadow.\n\tTPF_FULLSHADOW\t\t=0x0040,\t\t// Use a full outline shadow.\n\tTPF_LIGHTSHADOW\t=0x0080,\t\t// Use engraved drop 'shadow' color.\n\tTPF_CENTER\t\t\t=0x0100,\t\t// Center about the X axis.\n\tTPF_RIGHT\t\t\t=0x0200,\t\t// Right justify text.\n\tTPF_MEDIUM_COLOR\t=0x1000,\t\t// Use medium color for all text gradient\n\tTPF_BRIGHT_COLOR\t=0x2000,\t\t// Use bright color for all text gradient\n\tTPF_USE_GRAD_PAL\t=0x4000\t\t// Use a gradient palette based on fore color\n} TextPrintType;\n\n//PG\n//inline TextPrintType operator |(TextPrintType, TextPrintType);\n//inline TextPrintType operator &(TextPrintType, TextPrintType);\n//inline TextPrintType operator ~(TextPrintType);\n\ninline TextPrintType operator|(TextPrintType a, TextPrintType b)\n{return static_cast<TextPrintType>(static_cast<int>(a) | static_cast<int>(b));}\n\ninline TextPrintType operator&(TextPrintType a, TextPrintType b)\n{return static_cast<TextPrintType>(static_cast<int>(a) & static_cast<int>(b));}\n\ninline TextPrintType operator~(TextPrintType a)\n{return static_cast<TextPrintType>(~static_cast<int>(a));}\n\n// Standard button text print flags.\n#define TPF_BUTTON\t(TPF_CENTER|TPF_6PT_GRAD|TPF_NOSHADOW)\n#define TPF_EBUTTON\t(TPF_CENTER|TPF_EFNT|TPF_NOSHADOW)\n#define TPF_TEXT\t\t(TPF_6PT_GRAD|TPF_NOSHADOW)\n\n\n/**********************************************************************\n**\tThese control the maximum number of objects in the game. Make sure that these\n**\tmaximums never exceed the maximum value for the \"ID\" element in the\n**\tobject class.\n*/\n#define\tBUILDING_MAX\t\t\t500\t\t// Lasts for hours.\n#define\tHOUSE_MAX\t\t\t\t(HOUSE_COUNT+1)\t// Lasts entire scenario.\n#define\tINFANTRY_MAX\t\t\t500\t\t// Lasts for minutes.\n#define\tUNIT_MAX\t\t\t\t\t500\t\t// Lasts for minutes.\n#define\tVESSEL_MAX\t\t\t\t100\t\t// Lasts for minutes.\n#define\tTEAMTYPE_MAX\t\t\t60\t\t\t// Lasts forever.\n\n// Save filename description.\n#define\tDESCRIP_MAX\t\t\t\t44\t\t\t// 40 chars + CR + LF + CTRL-Z + NULL\n\n#define\tCONQUER_PATH_MAX\t\t12\t\t\t// Number of cells to look ahead for movement.\n\n#define\tEACH_INFANTRY_MAX\t\t(INFANTRY_MAX/5)\t\t// Default maximum any one player can have.\n#define\tEACH_UNIT_MAX\t\t\t(UNIT_MAX/5)\t\t\t// Default maximum any one player can have.\n#define\tEACH_BUILDING_MAX\t\t(BUILDING_MAX/5)\t\t// Default maximum any one player can build.\n#define\tEACH_VESSEL_MAX\t\t(VESSEL_MAX/5)\t\t\t// Default maximum any one player can build.\n\n\n/**********************************************************************\n**\tTerrain can be of these different classes. At any point in the game\n**\ta particular piece of ground must fall under one of these classifications.\n**\tThis is true, even if it is undergoing a temporary transition.\n*/\ntypedef enum LandType : char {\n\tLAND_CLEAR,\t\t// \"Clear\" terrain.\n\tLAND_ROAD,\t\t// Road terrain.\n\tLAND_WATER,\t\t// Water.\n\tLAND_ROCK,\t\t// Impassable rock.\n\tLAND_WALL,\t\t// Wall (blocks movement).\n\tLAND_TIBERIUM,\t// Tiberium field.\n\tLAND_BEACH,\t\t//\tBeach terrain.\n\tLAND_ROUGH,\t\t// Rocky terrain.\n\tLAND_RIVER,\t\t// Rocky riverbed.\n\n\tLAND_COUNT,\n\tLAND_NONE=-1,\n\tLAND_FIRST=0\n} LandType;\n\n\n/**********************************************************************\n**\tThe theaters of operation are as follows.\n*/\ntypedef enum TheaterType : char {\n\tTHEATER_NONE=-1,\n\tTHEATER_TEMPERATE,\n\tTHEATER_SNOW,\n\tTHEATER_INTERIOR,\n\n\tTHEATER_COUNT,\n\tTHEATER_FIRST=0\n} TheaterType;\n\n//inline TheaterType operator++(TheaterType &, int);\ninline TheaterType operator++(TheaterType &n) { n = (TheaterType)(((int)n)+1); return n; }\n\n\n#define\tTHEATERF_TEMPERATE\t\t(1<<THEATER_TEMPERATE)\n#define\tTHEATERF_SNOW\t\t\t\t(1<<THEATER_SNOW)\n#define\tTHEATERF_INTERIOR\t\t\t(1<<THEATER_INTERIOR)\n\ntypedef struct {\n\tchar\t\tName[16];\n\tchar\t\tRoot[10];\n\tchar\t\tSuffix[4];\n} TheaterDataType;\n\n\n/**********************************************************************\n**\tEach building has a predetermined size. These are the size numbers.\n**\tThe trailing number is this define is the width and height (respectively)\n**\tof the building in cells.\n*/\ntypedef enum BSizeType : char {\n\tBSIZE_NONE=-1,\n\tBSIZE_11=0,\n\tBSIZE_21,\n\tBSIZE_12,\n\tBSIZE_22,\n\tBSIZE_23,\n\tBSIZE_32,\n\tBSIZE_33,\n\tBSIZE_42,\n\tBSIZE_55,\n\n\tBSIZE_COUNT\n} BSizeType;\n\ninline BSizeType operator++(BSizeType &, int);\n\n\n/**********************************************************************\n** When objects are manipulated on the map that are marked as being\n**\tremoved (up), placed down (down), or just to be redrawn (change);\n** or when an object's rendering (not logical) size changes, due to\n** its being selected or having an animation attached (overlap up/down).\n*/\ntypedef enum MarkType : unsigned char {\n\tMARK_UP,\t\t\t\t\t//\tRemoved from the map.\n\tMARK_DOWN,\t\t\t\t//\tPlaced on the map.\n\tMARK_CHANGE,\t\t\t//\tAltered in place on the map.\n\tMARK_CHANGE_REDRAW,\t//\tRedraw because of animation change.\n\tMARK_OVERLAP_DOWN,\t// Mark overlap cells on the map\n\tMARK_OVERLAP_UP\t\t// Clear overlap cells on the map\n} MarkType;\n\n\n/****************************************************************************\n**\tWindow number definition list. Each window should be referred to by\n**\tthe value given in this list.\n*/\n// Allow window number enums to be passed to library functions.\ntypedef enum WindowNumberType : unsigned char {\n\tWINDOW_MAIN,\t\t\t\t// Full screen window.\n\tWINDOW_ERROR,\t\t\t\t// Library error window.\n\tWINDOW_TACTICAL,\t\t\t// Tactical map window.\n\tWINDOW_MENU,\t\t\t\t// Main selection menu.\n\tWINDOW_SIDEBAR,\t\t\t// Sidebar (buildable list) window.\n\tWINDOW_EDITOR,\t\t\t\t// Scenario editor window.\n\tWINDOW_PARTIAL,\t\t\t// Partial object draw sub-window.\n\tWINDOW_CUSTOM,\t\t\t\t// Window that can be altered depending on circumstances\n\tWINDOW_VIRTUAL\t\t\t\t// Window that is used when we want to capture rendering information without actually rendering. ST - 1/15/2019 3:03PM\n} WindowNumberType;\n\n\n/****************************************************************************\n**\tFor every cell there are 8 adjacent cells. Use these direction numbers\n**\twhen referring to adjacent cells. This comes into play when moving\n**\tbetween cells and in the Desired_Facing() algorithm.\n*/\ntypedef enum FacingType : char {\n\tFACING_NONE=-1,\n\tFACING_N,\t\t\t// North\n\tFACING_NE,\t\t\t// North-East\n\tFACING_E,\t\t\t// East\n\tFACING_SE,\t\t\t// South-East\n\tFACING_S,\t\t\t// South\n\tFACING_SW,\t\t\t// South-West\n\tFACING_W,\t\t\t// West\n\tFACING_NW,\t\t\t// North-West\n\n\tFACING_COUNT,\t\t\t// Total of 8 directions (0..7).\n\tFACING_FIRST=0\n} FacingType;\n\n//inline FacingType operator++(FacingType &, int);\ninline FacingType operator + (FacingType f1, FacingType f2)\n{\n\treturn (FacingType)(((int)f1 + (int)f2) & 0x07);\n}\ninline FacingType operator + (FacingType f1, int f2)\n{\n\treturn (FacingType)(((int)f1 + (int)f2) & 0x07);\n}\n\ninline FacingType operator - (FacingType f1, FacingType f2)\n{\n\treturn (FacingType)(((int)f1 - (int)f2) & 0x07);\n}\ninline FacingType operator - (FacingType f1, int f2)\n{\n\treturn (FacingType)(((int)f1 - (int)f2) & 0x07);\n}\n\ninline FacingType operator += (FacingType & f1, FacingType f2)\n{\n\tf1 = (FacingType)(((int)f1 + (int)f2) & 0x07);\n\treturn(f1);\n}\ninline FacingType operator += (FacingType & f1, int f2)\n{\n\tf1 = (FacingType)(((int)f1 + (int)f2) & 0x07);\n\treturn(f1);\n}\n\ninline int operator * (FacingType f1, FacingType f2)\n{\n\treturn((int)f1 * (int)f2);\n}\n\n\n#ifdef NEVER\ntypedef enum DirType {\n\tDIR_MIN=0,\n\tDIR_N=0,\n\tDIR_NE=1<<5,\n\tDIR_E=2<<5,\n\tDIR_SE=3<<5,\n\tDIR_S=4<<5,\n\tDIR_SW=5<<5,\n\tDIR_SW_X1=(5<<5)-8,\t\t// Direction of harvester while unloading.\n\tDIR_SW_X2=(5<<5)-16,\t\t// Direction of harvester while unloading.\n\tDIR_W=6<<5,\n\tDIR_NW=7<<5,\n\tDIR_MAX=255\n} DirType;\ninline DirType operator + (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator + (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\n#endif\n#define DIR_SW_X1\tDirType((5<<5)-8)\n#define DIR_SW_X2\tDirType((5<<5)-16)\n\n\n/****************************************************************************\n**\tTimer constants. These are used when setting the countdown timer.\n**\tNote that this is based upon a timer that ticks every 60th of a second.\n*/\n#define\tTIMER_SECOND\t\t\t60\n#define\tTIMER_MINUTE\t\t\t(TIMER_SECOND*60)\n\n#define\tFADE_PALETTE_FAST\t\t(TIMER_SECOND/8)\n#define\tFADE_PALETTE_MEDIUM\t(TIMER_SECOND/4)\n#define\tFADE_PALETTE_SLOW\t\t(TIMER_SECOND/2)\n\n#define\tTICKS_PER_SECOND\t\t15\n#define\tTICKS_PER_MINUTE\t\t(TICKS_PER_SECOND * 60)\n#define\tTICKS_PER_HOUR\t\t\t(TICKS_PER_MINUTE * 60)\n\n#define\tGRAYFADETIME\t\t\t(1 * TICKS_PER_SECOND)\n\n\n/****************************************************************************\n** Each vehicle is give a speed rating. This is a combination of not only\n**\tits physical speed, but the means by which it travels (wheels, tracks,\n**\twings, etc). This is used to determine the movement table.\n*/\ntypedef enum SpeedType : char {\n\tSPEED_NONE=-1,\n\n\tSPEED_FOOT,\t\t\t\t\t// Bipedal.\n\tSPEED_TRACK,\t\t\t\t// Tracked locomotion.\n\tSPEED_WHEEL,\t\t\t\t// Balloon tires.\n\tSPEED_WINGED,\t\t\t\t// Lifter's, 'thopters, and rockets.\n\tSPEED_FLOAT,\t\t\t\t// Ships.\n\n\tSPEED_COUNT,\n\tSPEED_FIRST=SPEED_FOOT\n} SpeedType;\n\n\n/**********************************************************************\n**\tThese are the sound effect digitized sample file names.\n*/\ntypedef enum VocType : short {\n\tVOC_NONE=-1,\n\n\tVOC_GIRL_OKAY,\t\t\t// \"okay\"\n\tVOC_GIRL_YEAH,\t\t\t// \"yeah?\"\n\tVOC_GUY_OKAY,\t\t\t//\t\"okay\"\n\tVOC_GUY_YEAH,\t\t\t// \"yeah?\"\n\n\tVOC_MINELAY1,\t\t\t// mine layer sound\n\tVOC_ACKNOWL,\t\t\t//\t\"acknowledged\"\n\tVOC_AFFIRM,\t\t\t\t//\t\"affirmative\"\n\tVOC_AWAIT,\t\t\t\t//\t\"awaiting orders\"\n\tVOC_ENG_AFFIRM,\t\t// Engineer: \"affirmative\"\n\tVOC_ENG_ENG,\t\t\t// Engineer: \"engineering\"\n\tVOC_NO_PROB,\t\t\t//\t\"not a problem\"\n\tVOC_READY,\t\t\t\t//\t\"ready and waiting\"\n\tVOC_REPORT,\t\t\t\t//\t\"reporting\"\n\tVOC_RIGHT_AWAY,\t\t//\t\"right away sir\"\n\tVOC_ROGER,\t\t\t\t//\t\"roger\"\n\tVOC_UGOTIT,\t\t\t\t//\t\"you got it\"\n\tVOC_VEHIC,\t\t\t\t//\t\"vehicle reporting\"\n\tVOC_YESSIR,\t\t\t\t//\t\"yes sir\"\n\n\tVOC_SCREAM1,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM3,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM4,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM5,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM6,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM7,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM10,\t\t\t//\tshort infantry scream\n\tVOC_SCREAM11,\t\t\t//\tshort infantry scream\n\tVOC_YELL1,\t\t\t\t//\tlong infantry scream\n\n\tVOC_CHRONO,\t\t\t\t//\tChronosphere sound.\n\tVOC_CANNON1,\t\t\t// Cannon sound (medium).\n\tVOC_CANNON2,\t\t\t// Cannon sound (short).\n\tVOC_IRON1,\n\tVOC_ENG_MOVEOUT,\t\t// Engineer: \"movin' out\"\n\tVOC_SONAR,\t\t\t\t// sonar pulse\n\tVOC_SANDBAG,\t\t\t// sand bag crunch\n\tVOC_MINEBLOW,\n\tVOC_CHUTE1,\t\t\t\t// wind swoosh sound\n\tVOC_DOG_BARK,\t\t\t// dog bark\n\tVOC_DOG_WHINE,\t\t\t// dog whine\n\tVOC_DOG_GROWL2,\t\t// strong dog growl\n\tVOC_FIRE_LAUNCH,\t\t// fireball launch sound\n\tVOC_FIRE_EXPLODE,\t\t// fireball explode sound\n\tVOC_GRENADE_TOSS,\t\t// grenade toss\n\tVOC_GUN_5,\t\t\t\t// 5 round gun burst (slow).\n\tVOC_GUN_7,\t\t\t\t// 7 round gun burst (fast).\n\tVOC_ENG_YES,\t\t\t// Engineer: \"yes sir\"\n\tVOC_GUN_RIFLE,\t\t\t// Rifle shot.\n\tVOC_HEAL,\t\t\t\t// Healing effect.\n\tVOC_DOOR,\t\t\t\t// Hyrdrolic door.\n\tVOC_INVULNERABLE,\t\t// Invulnerability effect.\n\tVOC_KABOOM1,\t\t\t// Long explosion (muffled).\n\tVOC_KABOOM12,\t\t\t// Very long explosion (muffled).\n\tVOC_KABOOM15,\t\t\t// Very long explosion (muffled).\n\tVOC_SPLASH,\t\t\t\t// Water splash\n\tVOC_KABOOM22,\t\t\t// Long explosion (sharp).\n\tVOC_AACANON3,\t\t\t// AA-Cannon\n\tVOC_TANYA_DIE,\t\t\t// Tanya: scream\n\tVOC_GUN_5F,\t\t\t\t// 5 round gun burst (fast).\n\tVOC_MISSILE_1,\t\t\t// Missile with high tech effect.\n\tVOC_MISSILE_2,\t\t\t// Long missile launch.\n\tVOC_MISSILE_3,\t\t\t// Short missile launch.\n\tVOC_x6,\n\tVOC_GUN_5R,\t\t\t\t// 5 round gun burst (rattles).\n\tVOC_BEEP,\t\t\t\t// Generic beep sound.\n\tVOC_CLICK,\t\t\t\t//\tGeneric click sound.\n\tVOC_SILENCER,\t\t\t// Silencer.\n\tVOC_CANNON6,\t\t\t// Long muffled cannon shot.\n\tVOC_CANNON7,\t\t\t// Sharp mechanical cannon fire.\n\tVOC_TORPEDO,\t\t\t// Torpedo launch.\n\tVOC_CANNON8,\t\t\t// Sharp cannon fire.\n\tVOC_TESLA_POWER_UP,\t// Hum charge up.\n\tVOC_TESLA_ZAP,\t\t\t// Tesla zap effect.\n\tVOC_SQUISH,\t\t\t\t// Squish effect.\n\tVOC_SCOLD,\t\t\t\t// Scold bleep.\n\tVOC_RADAR_ON,\t\t\t// Powering up electronics.\n\tVOC_RADAR_OFF,\t\t\t// B movie power down effect.\n\tVOC_PLACE_BUILDING_DOWN,\t// Building slam down sound.\n\tVOC_KABOOM30,\t\t\t// Short explosion (HE).\n\tVOC_KABOOM25,\t\t\t// Short growling explosion.\n\tVOC_x7,\n\tVOC_DOG_HURT,\t\t\t//\tDog whine.\n\tVOC_DOG_YES,\t\t\t// Dog 'yes sir'.\n\tVOC_CRUMBLE,\t\t\t// Building crumble.\n\tVOC_MONEY_UP,\t\t\t// Rising money tick.\n\tVOC_MONEY_DOWN,\t\t// Falling money tick.\n\tVOC_CONSTRUCTION,\t\t// Building construction sound.\n\tVOC_GAME_CLOSED,\t\t// Long bleep.\n\tVOC_INCOMING_MESSAGE,\t// Soft happy warble.\n\tVOC_SYS_ERROR,\t\t\t// Sharp soft warble.\n\tVOC_OPTIONS_CHANGED,\t// Mid range soft warble.\n\tVOC_GAME_FORMING,\t\t// Long warble.\n\tVOC_PLAYER_LEFT,\t\t// Chirp sequence.\n\tVOC_PLAYER_JOINED,\t// Reverse chirp sequence.\n\tVOC_DEPTH_CHARGE,\t\t// Distant explosion sound.\n\tVOC_CASHTURN,\t\t\t// Airbrake.\n\n\tVOC_TANYA_CHEW,\t\t// Tanya: \"Chew on this\"\n\tVOC_TANYA_ROCK,\t\t// Tanya: \"Let's rock\"\n\tVOC_TANYA_LAUGH,\t\t// Tanya: \"ha ha ha\"\n\tVOC_TANYA_SHAKE,\t\t// Tanya: \"Shake it baby\"\n\tVOC_TANYA_CHING,\t\t// Tanya: \"Cha Ching\"\n\tVOC_TANYA_GOT,\t\t\t// Tanya: \"That's all you got\"\n\tVOC_TANYA_KISS,\t\t// Tanya: \"Kiss it bye bye\"\n\tVOC_TANYA_THERE,\t\t// Tanya: \"I'm there\"\n\tVOC_TANYA_GIVE,\t\t// Tanya: \"Give it to me\"\n\tVOC_TANYA_YEA,\t\t\t// Tanya: \"Yea?\"\n\tVOC_TANYA_YES,\t\t\t// Tanya: \"Yes sir?\"\n\tVOC_TANYA_WHATS,\t\t// Tanya: \"What's up.\"\n\tVOC_WALLKILL2,\t\t\t// Crushing wall sound.\n\tVOC_x8,\n\tVOC_TRIPLE_SHOT,\t\t// Three quick shots in succession.\n\tVOC_SUBSHOW,\t\t\t// Submarine surfacing.\n\tVOC_E_AH,\t\t\t\t// Einstein \"ah\"\n\tVOC_E_OK,\t\t\t\t// Einstein \"ok\"\n\tVOC_E_YES,\t\t\t\t// Einstein \"yes\"\n\tVOC_TRIP_MINE,\t\t\t// mine explosion sound\n\n\tVOC_SPY_COMMANDER,\t// Spy: \"commander?\"\n\tVOC_SPY_YESSIR,\t\t// Spy: \"yes sir\"\n\tVOC_SPY_INDEED,\t\t// Spy: \"indeed\"\n\tVOC_SPY_ONWAY,\t\t\t// Spy: \"on my way\"\n\tVOC_SPY_KING,\t\t\t// Spy: \"for king and country\"\n\tVOC_MED_REPORTING,\t// Medic: \"reporting\"\n\tVOC_MED_YESSIR,\t\t// Medic: \"yes sir\"\n\tVOC_MED_AFFIRM,\t\t// Medic: \"affirmative\"\n\tVOC_MED_MOVEOUT,\t\t// Medic: \"movin' out\"\n\tVOC_BEEP_SELECT,\t\t// map selection beep\n\n\tVOC_THIEF_YEA,\t\t\t// Thief: \"yea?\"\n\n#ifdef FIXIT_ANTS\n\tVOC_ANTDIE,\n\tVOC_ANTBITE,\n#else\n\tVOC_x9,\n\tVOC_x10,\n#endif\n\n\tVOC_THIEF_MOVEOUT,\t// Thief: \"movin' out\"\n\tVOC_THIEF_OKAY,\t\t// Thief: \"ok\"\n\tVOC_x11,\n\tVOC_THIEF_WHAT,\t\t// Thief: \"what\"\n\tVOC_THIEF_AFFIRM,\t\t// Thief: \"affirmative\"\n\n\tVOC_STAVCMDR,\n\tVOC_STAVCRSE,\n\tVOC_STAVYES,\n\tVOC_STAVMOV,\n\tVOC_BUZZY1,\n\tVOC_RAMBO1,\n\tVOC_RAMBO2,\n\tVOC_RAMBO3,\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tVOC_MECHYES1,\n\tVOC_MECHHOWDY1,\n\tVOC_MECHRISE1,\n\tVOC_MECHHUH1,\n\tVOC_MECHHEAR1,\n\tVOC_MECHLAFF1,\n\tVOC_MECHBOSS1,\n\tVOC_MECHYEEHAW1,\n\tVOC_MECHHOTDIG1,\n\tVOC_MECHWRENCH1,\n\tVOC_STBURN1,\n\tVOC_STCHRGE1,\n\tVOC_STCRISP1,\n\tVOC_STDANCE1,\n\tVOC_STJUICE1,\n\tVOC_STJUMP1,\n\tVOC_STLIGHT1,\n\tVOC_STPOWER1,\n\tVOC_STSHOCK1,\n\tVOC_STYES1,\n\n\tVOC_CHRONOTANK1,\n\tVOC_MECH_FIXIT1,\n\tVOC_MAD_CHARGE,\n\tVOC_MAD_EXPLODE,\n\tVOC_SHOCK_TROOP1,\n\n\tVOC_BEACON,\n\n#endif\n\tVOC_COUNT,\n\tVOC_FIRST=0\n} VocType;\n\n/*\n**\tEVA voices are specified by these identifiers.\n*/\ntypedef enum VoxType : char {\n\tVOX_NONE=-1,\n\tVOX_ACCOMPLISHED,\t\t\t\t\t//\tmission accomplished\n\tVOX_FAIL,\t\t\t\t\t\t\t//\tyour mission has failed\n\tVOX_NO_FACTORY,\t\t\t\t\t//\tunable to comply, building in progress\n\tVOX_CONSTRUCTION,\t\t\t\t\t//\tconstruction complete\n\tVOX_UNIT_READY,\t\t\t\t\t// unit ready\n\tVOX_NEW_CONSTRUCT,\t\t\t\t//\tnew construction options\n\tVOX_DEPLOY,\t\t\t\t\t\t\t//\tcannot deploy here\n\tVOX_STRUCTURE_DESTROYED,\t\t// structure destroyed\n\tVOX_INSUFFICIENT_POWER,\t\t\t// insufficient power\n\tVOX_NO_CASH,\t\t\t\t\t\t//\tinsufficient funds\n\tVOX_CONTROL_EXIT,\t\t\t\t\t//\tbattle control terminated\n\tVOX_REINFORCEMENTS,\t\t\t\t//\treinforcements have arrived\n\tVOX_CANCELED,\t\t\t\t\t\t//\tcanceled\n\tVOX_BUILDING,\t\t\t\t\t\t//\tbuilding\n\tVOX_LOW_POWER,\t\t\t\t\t\t//\tlow power\n\tVOX_NEED_MO_MONEY,\t\t\t\t//\tneed more funds\n\tVOX_BASE_UNDER_ATTACK,\t\t\t//\tour base is under attack\n\tVOX_UNABLE_TO_BUILD,\t\t\t\t//\tunable to build more\n\tVOX_PRIMARY_SELECTED,\t\t\t//\tprimary building selected\n#ifdef ENGLISH\n\tVOX_MADTANK_DEPLOYED,\t\t\t// M.A.D. Tank Deployed\n#else\n\tVOX_none3,\n#endif\n\tVOX_none4,\n\tVOX_UNIT_LOST,\t\t\t\t\t\t//\tunit lost\n\tVOX_SELECT_TARGET,\t\t\t\t// select target\n\tVOX_PREPARE,\t\t\t\t\t\t//\tenemy approaching\n\tVOX_NEED_MO_CAPACITY,\t\t\t//\tsilos needed\n\tVOX_SUSPENDED,\t\t\t\t\t\t//\ton hold\n\tVOX_REPAIRING,\t\t\t\t\t\t//\trepairing\n\tVOX_none5,\n\tVOX_none6,\n\tVOX_AIRCRAFT_LOST,\n\tVOX_none7,\n\tVOX_ALLIED_FORCES_APPROACHING,\n\tVOX_ALLIED_APPROACHING,\n\tVOX_none8,\n\tVOX_none9,\n\tVOX_BUILDING_INFILTRATED,\n\tVOX_CHRONO_CHARGING,\n\tVOX_CHRONO_READY,\n\tVOX_CHRONO_TEST,\n\tVOX_HQ_UNDER_ATTACK,\n\tVOX_CENTER_DEACTIVATED,\n\tVOX_CONVOY_APPROACHING,\n\tVOX_CONVOY_UNIT_LOST,\n\tVOX_EXPLOSIVE_PLACED,\n\tVOX_MONEY_STOLEN,\n\tVOX_SHIP_LOST,\n\tVOX_SATALITE_LAUNCHED,\n\tVOX_SONAR_AVAILABLE,\n\tVOX_none10,\n\tVOX_SOVIET_FORCES_APPROACHING,\n\tVOX_SOVIET_REINFORCEMENTS,\n\tVOX_TRAINING,\n\tVOX_ABOMB_READY,\n\tVOX_ABOMB_LAUNCH,\n\tVOX_ALLIES_N,\n\tVOX_ALLIES_S,\n\tVOX_ALLIES_E,\n\tVOX_ALLIES_W,\n\tVOX_OBJECTIVE1,\n\tVOX_OBJECTIVE2,\n\tVOX_OBJECTIVE3,\n\tVOX_IRON_CHARGING,\n\tVOX_IRON_READY,\n\tVOX_RESCUED,\n\tVOX_OBJECTIVE_NOT,\n\tVOX_SIGNAL_N,\n\tVOX_SIGNAL_S,\n\tVOX_SIGNAL_E,\n\tVOX_SIGNAL_W,\n\tVOX_SPY_PLANE,\n\tVOX_FREED,\n\tVOX_UPGRADE_ARMOR,\n\tVOX_UPGRADE_FIREPOWER,\n\tVOX_UPGRADE_SPEED,\n\tVOX_MISSION_TIMER,\n\tVOX_UNIT_FULL,\n\tVOX_UNIT_REPAIRED,\n\tVOX_TIME_40,\n\tVOX_TIME_30,\n\tVOX_TIME_20,\n\tVOX_TIME_10,\n\tVOX_TIME_5,\n\tVOX_TIME_4,\n\tVOX_TIME_3,\n\tVOX_TIME_2,\n\tVOX_TIME_1,\n\tVOX_TIME_STOP,\n\tVOX_UNIT_SOLD,\n\tVOX_TIMER_STARTED,\n\tVOX_TARGET_RESCUED,\n\tVOX_TARGET_FREED,\n\tVOX_TANYA_RESCUED,\n\tVOX_STRUCTURE_SOLD,\n\tVOX_SOVIET_FORCES_FALLEN,\n\tVOX_SOVIET_SELECTED,\n\tVOX_SOVIET_EMPIRE_FALLEN,\n\tVOX_OPERATION_TERMINATED,\n\tVOX_OBJECTIVE_REACHED,\n\tVOX_OBJECTIVE_NOT_REACHED,\n\tVOX_OBJECTIVE_MET,\n\tVOX_MERCENARY_RESCUED,\n\tVOX_MERCENARY_FREED,\n\tVOX_KOSOYGEN_FREED,\n\tVOX_FLARE_DETECTED,\n\tVOX_COMMANDO_RESCUED,\n\tVOX_COMMANDO_FREED,\n\tVOX_BUILDING_IN_PROGRESS,\n\tVOX_ATOM_PREPPING,\n\tVOX_ALLIED_SELECTED,\n\tVOX_ABOMB_PREPPING,\n\tVOX_ATOM_LAUNCHED,\n\tVOX_ALLIED_FORCES_FALLEN,\n\tVOX_ABOMB_AVAILABLE,\n\tVOX_ALLIED_REINFORCEMENTS,\n\tVOX_SAVE1,\n\tVOX_LOAD1,\n\n\tVOX_COUNT,\n\tVOX_FIRST=0\n} VoxType;\n\n\n/****************************************************************************\n**\tGame reinforcements are each controlled by the following structure. The\n**\tdata originates in the scenario INI file but is then carried throughout\n**\tany saved games.\n*/\ntypedef enum SourceType : char {\n\tSOURCE_NONE=-1,\t\t\t\t// No defined source (error condition).\n\tSOURCE_NORTH,\t\t\t\t\t// From north edge.\n\tSOURCE_EAST,\t\t\t\t\t// From east edge.\n\tSOURCE_SOUTH,\t\t\t\t\t// From south edge.\n\tSOURCE_WEST,\t\t\t\t\t// From west edge.\n\tSOURCE_AIR,\t\t\t\t\t\t// Dropped by air (someplace).\n\n\tSOURCE_COUNT,\n\tSOURCE_FIRST=0\n} SourceType;\n\n\n/****************************************************************************\n**\tThis entry defines a complete color scheme, with the player's remap table,\n** the font remap table, and a color scheme for dialog boxes and buttons.\n*/\ntypedef struct RemapControlType\n{\n\tunsigned char BrightColor;\t\t\t// Highlight (bright) color index.\n\tunsigned char Color;\t\t\t\t\t// Normal color index.\n\tunsigned char RemapTable[256];\t// Actual remap table.\n\tunsigned char FontRemap[16];\t\t// Remap table for gradient font.\n\tunsigned char Shadow;\t\t\t\t// Color of shadowed edge of a raised button.\n\tunsigned char Background;\t\t\t// Background fill color for buttons.\n\tunsigned char Corners;\t\t\t\t// Transition color between shadow and highlight.\n\tunsigned char Highlight;\t\t\t// Bright edge of raised button.\n\tunsigned char Box;\t\t\t\t\t// Color for dialog box border.\n\tunsigned char Bright;\t\t\t\t// Color used for highlighted text.\n\tunsigned char Underline;\t\t\t// Color for underlining dialog box titles.\n\tunsigned char Bar;\t\t\t\t\t// Selected entry list box background color.\n} RemapControlType;\n\n\n/****************************************************************************\n**\tEach type of terrain has certain characteristics. These are indicated\n**\tby the structure below. For every element of terrain there is a\n**\tcorresponding GroundType structure.\n*/\ntypedef struct {\n\tfixed\tCost[SPEED_COUNT];\t// Terrain effect cost (normal).\n\tbool\t\t\t\tBuild;\t\t\t\t\t// Can build on this terrain?\n} GroundType;\n\n\n/**************************************************************************\n**\tFind_Path returns with a pointer to this structure.\n*/\ntypedef struct {\n\tCELL\t\t\t\tStart;\t\t\t\t// Starting cell number.\n\tint\t\t\t\tCost;\t\t\t\t\t// Accumulated terrain cost.\n\tint\t\t\t\tLength;\t\t\t\t// Command string length.\n\tFacingType\t\t*Command;\t\t\t// Pointer to command string.\n\tunsigned long\t*Overlap;\t\t\t// Pointer to overlap list\n\tCELL\t\t\t\tLastOverlap;\t\t// stores position of last overlap\n\tCELL\t\t\t\tLastFixup;\t\t\t// stores position of last overlap\n} PathType;\n\n\n/**********************************************************************\n** These are special indices into the Waypoint array; slots 0-25 are\n** reserved for letter-designated Waypoints, the others are special.\n*/\ntypedef enum WaypointEnum : unsigned char \n{\n\tWAYPT_HOME = 98,\t\t\t\t// Home-cell for this scenario\n\tWAYPT_REINF,\t\t\t\t\t// cell where reinforcements arrive\n\tWAYPT_SPECIAL,\t\t\t\t\t// Used by special airdrop reinforcements.\n\tWAYPT_COUNT\n} WaypointType;\n\n\n/****************************************************************************\n**\tThis is the max number of events supported on one frame.\n*/\n#define\tMAX_EVENTS\t\t\t256\n\ntypedef enum : unsigned char {\n\tKF_NUMBER   = 0x08,\n\tKF_LCW      = 0x10,\n\tKF_DELTA    = 0x20,\n\tKF_KEYDELTA = 0x40,\n\tKF_KEYFRAME = 0x80,\n\tKF_MASK     = 0xF0\n} KeyFrameType;\n\n\n/*\n** New Config structure for .CFG files\n*/\ntypedef struct {\n   unsigned   DigitCard;      \t// SoundCardType.\n   unsigned   Port;      \t\t \t// SoundCardType.\n   unsigned   IRQ;\t\t       \t// SoundCardType.\n   unsigned   DMA;     \t\t \t\t// SoundCardType.\n   unsigned   BitsPerSample;     // bits per sound sample\n   unsigned   Channels;          // stereo/mono sound card\n   unsigned   Speed;\t\t         // stereo/mono sound card\n\tbool       Reverse;\t\t\t\t// Reverse left/right speakers\n\tchar       Language[4];\n} NewConfigType;\n\n\n/****************************************************************************\n**\tThese are the types of dialogs that can pop up outside of the main loop,\n** an call the game in the background.\n*/\ntypedef enum : unsigned char {\n\tSDLG_NONE,\n\tSDLG_OPTIONS,\n\tSDLG_SURRENDER,\n\tSDLG_SPECIAL\n} SpecialDialogType;\n\ntypedef enum : unsigned char {\n\tCC_MOUSE_COLOR=16\n} CCPaletteType;\n\n\n/****************************************************************************\n**\tThese specify the shape numbers in the OPTIONS.SHP file. These shapes\n**\tare used to dress up the dialog boxes. Many of these shapes come in pairs.\n**\tFor dialog box shapes, they are left image / right image paired. For buttons,\n**\tthey are up / down paired.\n*/\ntypedef enum OptionControlType : char {\n\tOPTION_NONE=-1,\t\t\t// No fancy shmancy shape.\n\tOPTION_DIALOG=0,\t\t\t// Small dialog boxes.\n\tOPTION_CONTROLS=2,\t\t// Large dialog boxes, game controls.\n\tOPTION_DELETE=4,\t\t\t// Delete,Load,Save game.\n\tOPTION_SERIAL=6,\t\t\t// Serial dialog.\n\tOPTION_PHONE=8,\t\t\t// Phone dialog.\n\tOPTION_VISUAL=10,\t\t\t// Visual dialog.\n\tOPTION_NETWORK=12,\t\t// Network dialog.\n\tOPTION_JOIN_NETWORK=14,\t// Join network dialog.\n\tOPTION_SOUND=16,\t\t\t// Sound controls.\n\n\tOPTION_COUNT\n} OptionControlType;\n\n\n/****************************************************************************\n**\tUsed to store firing data for a unit.\n*/\ntypedef struct {\n\tCOORDINATE Center;\n\tint Distance;\n} FireDataType;\n\n\n#define size_of(typ,id) sizeof(((typ*)0)->id)\n\n\n#define MAX_LOG_LEVEL\t\t10\n\n// Maximum number of multi players possible.\n#define\tMAX_PLAYERS\t\t\t\t\t\t8\t\t// max # of players we can have\n\n// Maximum number of teams\n#define MAX_TEAMS\t\t\t\t\t\t10\n\n#endif"
  },
  {
    "path": "REDALERT/DESCDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DESCDLG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DESCDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                  Joe L. Bostic                                              *\n *                                                                                             *\n *                   Start Date : Jan 26, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 26, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DescriptionClass::Process -- Handles all the options graphic interface.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"descdlg.h\"\n\n\n/***********************************************************************************************\n * DescriptionClass::Process -- Handles all the options graphic interface.                     *\n *                                                                                             *\n *    This dialog uses an edit box to \"fill-out\" a description.                                *\n *                                                                                             *\n * INPUT:      char *string - return answer here.                                              *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nvoid DescriptionClass::Process(char * string)\n{\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tSet_Window(WINDOW_EDITOR, OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT);\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.  Button coords are in pixels, but are window-relative.\n\t*/\n\tTextButtonClass optionsbtn(BUTTON_OPTIONS, TXT_OK, TPF_BUTTON, 0, BUTTON_Y);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 0, BUTTON_Y);\n\n\tcancelbtn.X  = OPTION_X + ((OPTION_WIDTH - optionsbtn.Width)/3)*2;\n\toptionsbtn.X = OPTION_X + ((OPTION_WIDTH - optionsbtn.Width)/3);\n\toptionsbtn.Add_Tail(cancelbtn);\n\n\tEditClass edit(\n\t\tBUTTON_EDIT,\n\t\tstring,\n\t\t31,\n\t\tTPF_6PT_GRAD,\n\t\t0,\n\t\tEDIT_Y,\n\t\tEDIT_W);\n\n\tedit.Set_Focus();\n\tedit.X = OPTION_X + (OPTION_WIDTH - edit.Width)/2,\n\toptionsbtn.Add_Tail(edit);\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\tGadgetClass dialog(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT, GadgetClass::LEFTPRESS);\n\toptionsbtn.Add_Tail(dialog);\n\n\t/*\n\t**\tThis causes a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to options dialog.\n\t*/\n\tControlClass background(BUTTON_OPTIONS, 0, 0, 320, 200, GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);\n\toptionsbtn.Add_Tail(background);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\n\t\t\tWindow_Hide_Mouse(WINDOW_EDITOR);\n\n\t\t\t/*\n\t\t\t**\tDraw the background\n\t\t\t*/\n\t\t\tWindow_Box (WINDOW_EDITOR, BOXSTYLE_BORDER); // has border, raised up\n\t\t\tDraw_Caption(TXT_MISSION_DESCRIPTION, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\n\t\t\t/*\n\t\t\t**\tDraw the titles\n\t\t\t*/\n\t\t\toptionsbtn.Draw_All();\n\t\t\tWindow_Show_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = optionsbtn.Input();\n\n\t\t/*\n\t\t**\tProcess Input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\tcase KN_RETURN:\n\t\t\tcase KeyNumType(BUTTON_OPTIONS|KN_BUTTON):\n\t\t\t\tstrtrim(string);\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_ESC:\n\t\t\tcase KeyNumType(BUTTON_CANCEL|KN_BUTTON):\n\t\t\t\tstring[0]= NULL;\n\t\t\t\tstrtrim(string);\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KeyNumType(BUTTON_EDIT|KN_BUTTON):\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/DESCDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DESCDLG.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DESCDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : Jan 26, 1995                                                 *\n *                                                                                             *\n *                  Last Update : Jan 26, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*/\n\n#ifndef DESCDLG_H\n#define DESCDLG_H\n\n#include \"gadget.h\"\n\nclass DescriptionClass \n{\n\tprivate:\n\n\t\tenum DescriptionClassEnum {\n\t\t\tOPTION_WIDTH=216,\t\t\t\t\t\t\t// Width of dialog box.\n\t\t\tOPTION_HEIGHT=122,\t\t\t\t\t\t// Height of dialog box.\n\t\t\tOPTION_X=(((320 - OPTION_WIDTH) / 2) & ~7),\n\t\t\tOPTION_Y=((200 - OPTION_HEIGHT) / 2),\n\t\t\tTEXT_X=OPTION_X+32,\t\t\t \t\t\t// Title's x pos\n\t\t\tTEXT_Y=OPTION_Y+32,  \t\t\t\t\t// Add 11 for each following line\n\t\t\tBUTTON_OPTIONS=1,\t\t\t\t\t\t\t// Button number for \"Ok\"\n\t\t\tBUTTON_CANCEL,\t\t\t\t\t\t\t\n\t\t\tBUTTON_EDIT,\n\t\t\tBUTTON_X=OPTION_X+63,\t \t\t\t\t// Options button x pos\n\t\t\tBUTTON_Y=OPTION_Y+102, \t\t\t\t\t// Options button y pos\n\t\t\tEDIT_Y  =OPTION_Y+50, \t\t\t\t\t\n\t\t\tEDIT_W  =180   //204,\n\t\t};\n\n\tpublic:\n\t\tDescriptionClass(void) {};\n\t\tvoid Process(char *string);\n};\n\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/DIAL8.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DIAL8.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIAL8.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Dial8Class::Action -- action routine for Dial8Class                                       *\n *   Dial8Class::Dial8Class -- constructor for the facing dial                                 *\n *   Dial8Class::Draw_Me -- render routine for Dial8Class                                      *\n *   Dial8Class::Get_Direction -- retrieves direction (0-255) of dial                          *\n *   Dial8Class::Set_Direction -- sets current direction (0-255) of dial                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***************************************************************************\n * Dial8Class::Dial8Class -- constructor for the facing dial               *\n *                                                                         *\n * INPUT:                                                                  *\n *      id            button ID                                            *\n *      x,y,w,h      dimensions in window-relative pixels                  *\n *      dir         numerical initial facing value (0-255); this is the    *\n *                  value returned by WWLIB Desired_Facing8()              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nDial8Class::Dial8Class(int id, int x, int y, int w, int h, DirType dir) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTHELD | LEFTRELEASE, true)\n{\n\t/*\n\t**\tCenter coordinates.\n\t*/\n\tFaceX = X + (Width / 2);\n\tFaceY = Y + (Height / 2);\n\n\t/*\n\t**\tInit directions.\n\t*/\n\tDirection = dir;\t\t\t\t\t\t\t// 0 - 255\n\tFacing = Dir_Facing(Direction);\t\t// 0 - 7\n\tOldFacing = Facing;\t\t\t\t\t\t// 0 - 7\n\n\t/*\n\t**\tCompute the drawing dimensions:  a 45-degree angle intersects a unity-\n\t**\tradius circle at (.707,.707). Make the decorations 8/10 of the radius,\n\t**\tand the line extend to 6/10 of the radius. Use Width/2 for x-radius,\n\t**\tHeight/2 for y-radius.\n\t*/\n\tFacePoint[0][0] = FaceX;\n\tFacePoint[0][1] = FaceY - (h * 8 / 2) / 10;\n\n\tFacePoint[1][0] = FaceX + (w * 7 * 8 / 2) / 100;\n\tFacePoint[1][1] = FaceY - (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[2][0] = FaceX + (w * 8 / 2) / 10;\n\tFacePoint[2][1] = FaceY;\n\n\tFacePoint[3][0] = FaceX + (w * 7 * 8 / 2) / 100;\n\tFacePoint[3][1] = FaceY + (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[4][0] = FaceX;\n\tFacePoint[4][1] = FaceY + (h * 8 / 2) / 10;\n\n\tFacePoint[5][0] = FaceX - (w * 7 * 8 / 2) / 100;\n\tFacePoint[5][1] = FaceY + (h * 7 * 8 / 2) / 100;\n\n\tFacePoint[6][0] = FaceX - (w * 8 / 2) / 10;\n\tFacePoint[6][1] = FaceY;\n\n\tFacePoint[7][0] = FaceX - (w * 7 * 8 / 2) / 100;\n\tFacePoint[7][1] = FaceY - (h * 7 * 8 / 2) / 100;\n\n\tFaceLine[0][0] = FaceX;\n\tFaceLine[0][1] = FaceY - (h * 6 / 2) / 10;\n\n\tFaceLine[1][0] = FaceX + (w * 7 * 6 / 2) / 100;\n\tFaceLine[1][1] = FaceY - (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[2][0] = FaceX + (w * 6 / 2) / 10;\n\tFaceLine[2][1] = FaceY;\n\n\tFaceLine[3][0] = FaceX + (w * 7 * 6 / 2) / 100;\n\tFaceLine[3][1] = FaceY + (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[4][0] = FaceX;\n\tFaceLine[4][1] = FaceY + (h * 6 / 2) / 10;\n\n\tFaceLine[5][0] = FaceX - (w * 7 * 6 / 2) / 100;\n\tFaceLine[5][1] = FaceY + (h * 7 * 6 / 2) / 100;\n\n\tFaceLine[6][0] = FaceX - (w * 6 / 2) / 10;\n\tFaceLine[6][1] = FaceY;\n\n\tFaceLine[7][0] = FaceX - (w * 7 * 6 / 2) / 100;\n\tFaceLine[7][1] = FaceY - (h * 7 * 6 / 2) / 100;\n}\n\n\n/***************************************************************************\n * Dial8Class::Action -- activation function for Dial8Class                *\n *                                                                         *\n * INPUT:                                                                  *\n *      flags      the reason we're being called                           *\n *      key      the KN_number that was pressed                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = event was processed, false = event not processed            *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/06/1995 BR : Created.                                              *\n *=========================================================================*/\nint Dial8Class::Action(unsigned flags, KeyNumType &key)\n{\n\tstatic int is_sel = 0;\n\n\t/*\n\t**\tWe might end up clearing the event bits. Make sure that the sticky\n\t**\tprocess is properly updated anyway.\n\t*/\n\tSticky_Process(flags);\n\n\tif (flags & LEFTPRESS) {\n\t\tis_sel = 1;\n\t}\n\n\t/*\n\t**\tIf left mouse is clicked or held, and the dial has changed its direction,\n\t**\tinvoke the parent Action routine:\n\t**\tGadgetClass::Action handles Sticky processing, & sets IsToRepaint if any\n\t**\t  flag bits are set.\n\t**\tControlClass::Action handles Peer_To_Peer notification, and substitutes\n\t**\t  'key' with the button ID if any flags are set, or 0 if no flags are set\n\t*/\n\tif (flags & LEFTPRESS || ((flags & LEFTHELD) && is_sel)) {\n\t\t/*\n\t\t**\tGet new dial position (0-255)\n\t\t*/\n\t\tDirection = (DirType)Desired_Facing8(FaceX, FaceY, Get_Mouse_X(), Get_Mouse_Y());\n\n\t\t/*\n\t\t**\tConvert to Facing value (0-7).\n\t\t*/\n\t\tFacing = Dir_Facing(Direction);\n\n\t\t/*\n\t\t**\tIf it's moved, redraw.\n\t\t*/\n\t\tif (Facing!=OldFacing) {\n\t\t\tOldFacing = Facing;\n\t\t\tControlClass::Action(flags, key);\n\t\t\treturn(true);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tDial hasn't moved; kill the event & return\n\t\t\t*/\n\t\t\tkey = KN_NONE;\n\t\t\tControlClass::Action(0, key);\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tOtherwise, no events have occurred; kill the event if it's a LEFTRELEASE,\n\t\t**\tand return\n\t\t*/\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tkey = KN_NONE;\n\t\t\tis_sel = 0;\n\t\t}\n\t\treturn(ControlClass::Action(0, key));\n\t}\n}\n\n\n/***************************************************************************\n * Dial8Class::Draw_Me -- custom render routine for Dial8Class             *\n *                                                                         *\n * INPUT:                                                                  *\n *      forced      true = draw regardless of the current redraw flag state*\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = gadget was redrawn, false = wasn't                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/06/1995 BR : Created.                                              *\n *=========================================================================*/\nint Dial8Class::Draw_Me(int forced)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tRedraw if parent indicates a redraw is needed\n\t*/\n\tif (ControlClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tDraw background & decorations.\n\t\t*/\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\t\tfor (int i=0; i<8; i++) {\n\t\t\tDraw_Box(FacePoint[i][0] - 1, FacePoint[i][1] -1, 3, 3, BOXSTYLE_RAISED, false);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the hand & its shadow.\n\t\t*/\n\t\tLogicPage->Draw_Line(FaceX+1, FaceY+1, FaceLine[Facing][0]+1, FaceLine[Facing][1]+1, scheme->Shadow);\n\t\tLogicPage->Draw_Line(FaceX, FaceY, FaceLine[Facing][0], FaceLine[Facing][1], scheme->Highlight);\n\n\t\t/*\n\t\t**\tRestore the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * Dial8Class::Get_Direction -- retrieves direction (0-255) of dial        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      DirType dial is pointing to                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nDirType Dial8Class::Get_Direction(void) const\n{\n\treturn(Direction);\n}\n\n\n/***************************************************************************\n * Dial8Class::Set_Direction -- sets current direction (0-255) of dial     *\n *                                                                         *\n * INPUT:                                                                  *\n *      DirType to set dial to                                             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid Dial8Class::Set_Direction(DirType dir)\n{\n\tDirection = dir;\n\tFacing = Dir_Facing(Direction);\n\tOldFacing = Facing;\n\tFlag_To_Redraw();\n}\n"
  },
  {
    "path": "REDALERT/DIAL8.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DIAL8.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIAL8.H                                                      *\n *                                                                                             *\n *                   Programmer : Bill Randolph\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *                   Start Date : 02/06/95                                                     *\n *                                                                                             *\n *                  Last Update : February 6, 1995 [BR]\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DIAL8_H\n#define DIAL8_H\n\nclass Dial8Class : public ControlClass\n{\n\tpublic:\n\t\t/*\n\t\t** Constructor/Destructor\n\t\t*/\n\t\tDial8Class(int id, int x, int y, int w, int h, DirType dir);\n\n\t\t/*\n\t\t** Get/Set the direction the dial is currently pointing\n\t\t*/\n\t\tDirType Get_Direction(void) const;\n\t\tvoid Set_Direction(DirType dir);\n\n\t\t/*\n\t\t** Overloaded draw routine\n\t\t*/\n\t\tvirtual int Draw_Me(int forced = false);\n\n\tprotected:\n\t\t/*\n\t\t** Overloaded event processing routine\n\t\t*/\n\t\tvirtual int Action(unsigned flags, KeyNumType &key);\n\n\tprivate:\n\t\tint FaceX;\t\t\t\t\t\t// x-coord of center of face\n\t\tint FaceY;\t\t\t\t\t\t// y-coord of center of face\n\t\tint FacePoint[8][2];\t\t\t// coords of the little dial decorations\n\t\tint FaceLine[8][2];\t\t\t// coords for drawing the dial hand\n\t\tDirType Direction;\t\t\t// 0-255 numerical direction of dial\n\t\tFacingType Facing;\t\t\t// numerical facing direction of dial (0 - 7)\n\t\tFacingType OldFacing;\t\t// previous Facing value\n\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/DIALOG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DIALOG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DIALOG.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 31, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Clip_Text_Print -- Prints text with clipping and <TAB> support.                           *\n *   Dialog_Box -- draws a dialog background box                                               *\n *   Display_Place_Building -- Displays the \"place building\" dialog box.                       *\n *   Display_Select_Target -- Displays the \"choose target\" prompt.                             *\n *   Display_Status -- Display the player scenario status box.                                 *\n *   Draw_Box -- Displays a highlighted box.                                                   *\n *   Draw_Caption -- Draws a caption on a dialog box.                                          *\n *   Fancy_Text_Print -- Prints text with a drop shadow.                                       *\n *   Plain_Text_Print -- Prints text without using a color scheme                              *\n *   Redraw_Needed -- Determine if sidebar needs to be redrawn.                                *\n *   Render_Bar_Graph -- Renders a specified bargraph.                                         *\n *   Simple_Text_Print -- Prints text with a drop shadow.                                      *\n *   Window_Box -- Draws a fancy box over the specified window.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#include   \"defines.h\"   //VG 10/17/96\n\nunsigned char * Font_Palette(int color);\n\n\n/***********************************************************************************************\n * Dialog_Box -- draws a dialog background box                                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      x,y,w,h      the usual                                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/26/1995 BR : Created.                                                                  *\n *   07/31/1996 JLB : Uses shapes to draw the box.                                             *\n *=============================================================================================*/\nvoid Dialog_Box(int x, int y, int w, int h)\n{\n// Try to expand the box a little taller and a little wider to make room for\n// the dialog box graphics in the DOS version.\n#ifndef WIN32\n\tx = max(0, x-4);\n\ty = max(0, y-4);\n\tw = min(w+8, 320-x);\n\th = min(h+8, 200-y);\n#endif\n\n\tWindowList[WINDOW_PARTIAL][WINDOWX] = x;\n\tWindowList[WINDOW_PARTIAL][WINDOWY] = y;\n\tWindowList[WINDOW_PARTIAL][WINDOWWIDTH] = w;\n\tWindowList[WINDOW_PARTIAL][WINDOWHEIGHT] = h;\n\n\t/*\n\t**\tAlways draw to the hidpage and then blit forward.\n\t*/\n#ifdef WIN32\n\tGraphicViewPortClass * oldpage = Set_Logic_Page(HidPage);\n#else\n\tGraphicBufferClass * oldpage = Set_Logic_Page(HidPage);\n#endif\n\n\t/*\n\t**\tDraw the background block.\n\t*/\n\tint cx = w/2;\n\tint cy = h/2;\n\tvoid const * shapedata = MFCD::Retrieve(\"DD-BKGND.SHP\");\n#ifdef WIN32\n\tCC_Draw_Shape(shapedata, 0, cx-312, cy-192, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 1, cx,     cy-192, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 2, cx-312, cy,     WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 3, cx,     cy,     WINDOW_PARTIAL, SHAPE_WIN_REL);\n#else\n\tCC_Draw_Shape(shapedata, 0, cx-156, cy-96, WINDOW_PARTIAL, SHAPE_WIN_REL);\n#endif\n\t/*\n\t**\tDraw the side strips.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-EDGE.SHP\");\n\tfor (int yy = 0; yy < h; yy += 6) {\n\t\tCC_Draw_Shape(shapedata, 0, 7*RESFACTOR,         yy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\t\tCC_Draw_Shape(shapedata, 1, w-((7+8)*RESFACTOR), yy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\t}\n\n\t/*\n\t**\tDraw the border bars.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-LEFT.SHP\");\n\tCC_Draw_Shape(shapedata, 0, 0, cy-100*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, 0, cy, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-RIGHT.SHP\");\n\tint rightx = w - (7*RESFACTOR);\n#ifndef WIN32\n\trightx--;\n#endif\n\tCC_Draw_Shape(shapedata, 0, rightx, cy-100*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, rightx, cy,\t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-BOTM.SHP\");\n\tCC_Draw_Shape(shapedata, 0, cx-160*RESFACTOR, h-8*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, cx, h-8*RESFACTOR, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\tshapedata = MFCD::Retrieve(\"DD-TOP.SHP\");\n\tCC_Draw_Shape(shapedata, 0, cx-160*RESFACTOR, 0, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 0, cx, 0, WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n\t/*\n\t**\tDraw the corner caps.\n\t*/\n\tshapedata = MFCD::Retrieve(\"DD-CRNR.SHP\");\n\tCC_Draw_Shape(shapedata, 0, 0,                  0, \t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 1, w-(12*RESFACTOR-1), 0, \t\t\t\t\tWINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 2, 0,                  h-(12*RESFACTOR), WINDOW_PARTIAL, SHAPE_WIN_REL);\n\tCC_Draw_Shape(shapedata, 3, w-(12*RESFACTOR-1), h-(12*RESFACTOR), WINDOW_PARTIAL, SHAPE_WIN_REL);\n\n#ifdef WIN32\n\tWWMouse->Draw_Mouse(&HidPage);\n\tHidPage.Blit(SeenBuff, x, y, x, y, w, h, false);\n\tWWMouse->Erase_Mouse(&HidPage, FALSE);\n#else\n//\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, Map.ShadowPage->Get_Buffer());\n\tHide_Mouse();\n\tHidPage.Blit(SeenBuff);\n\tShow_Mouse();\n//\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ((GraphicBufferClass*)Map.Shadow_Address())->Get_Buffer());\n#endif\n\tSet_Logic_Page(oldpage);\n}\n\n\n/***********************************************************************************************\n * Draw_Box -- Displays a highlighted box.                                                     *\n *                                                                                             *\n *    This will draw a highlighted box to the logicpage. It can                                *\n *    optionally fill the box with a color as well. This is a low level                        *\n *    function and thus, it doesn't do any graphic mode color adjustments.                     *\n *                                                                                             *\n * INPUT:   x,y   -- Upper left corner of the box to be drawn (pixels).                        *\n *                                                                                             *\n *          w,h   -- Width and height of box (in pixels).                                      *\n *                                                                                             *\n *          up    -- Is the box rendered in the \"up\" stated?                                   *\n *                                                                                             *\n *          filled-- Is the box to be filled.                                                  *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1991 JLB : Created.                                                                 *\n *   05/30/1992 JLB : Embedded color codes.                                                    *\n *   07/31/1992 JLB : Depressed option added.                                                  *\n *=============================================================================================*/\nvoid Draw_Box(int x, int y, int w, int h, BoxStyleEnum up, bool filled)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t// Filler, Shadow, Hilite, Corner colors\n\n\tBoxStyleType const ButtonColors[BOXSTYLE_COUNT] = {\n\t\t{ scheme->Background, scheme->Highlight, scheme->Shadow,  scheme->Corners},\t// Down\n\t\t{ scheme->Background, scheme->Shadow, scheme->Highlight,  scheme->Corners},\t// Raised\n\t\t{ DKGREY, WHITE,  BLACK,  DKGREY},\t\t\t\t// Disabled down\n\t\t{ DKGREY, BLACK,  LTGREY, DKGREY},\t\t\t\t// Disabled up\n\t\t{ BLACK,  scheme->Box, scheme->Box,  BLACK},\t// List box\n\t\t{ BLACK,  scheme->Box, scheme->Box,  BLACK},\t// Dialog box\n\t};\n\n\tw--;\n\th--;\n\tBoxStyleType const &style = ButtonColors[up];\n\n\tif (filled) {\n\t\tLogicPage->Fill_Rect( x, y, x+w, y+h, style.Filler);\n\t}\n\n\tswitch (up) {\n\t\tcase (BOXSTYLE_BOX):\n\t\t\tLogicPage->Draw_Rect(x, y, x+w, y+h, style.Highlight);\n\t\t\tbreak;\n\n\t\tcase (BOXSTYLE_BORDER):\n\t\t\tLogicPage->Draw_Rect(x+1, y+1, x+w-1, y+h-1, style.Highlight);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tLogicPage->Draw_Line(x, y+h, x+w, y+h, style.Shadow);\n\t\t\tLogicPage->Draw_Line(x+w, y, x+w, y+h, style.Shadow);\n\n\t\t\tLogicPage->Draw_Line(x, y, x+w, y, style.Highlight);\n\t\t\tLogicPage->Draw_Line(x, y, x, y+h, style.Highlight);\n\n\t\t\tLogicPage->Put_Pixel(x, y+h, style.Corner);\n\t\t\tLogicPage->Put_Pixel(x+w, y, style.Corner);\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * Format_Window_String -- Separates a String into Lines.                                      *\n *   This function will take a long string and break it up into lines                          *\n *   which are not longer then the window width. Any character < ' ' is                        *\n *   considered a new line marker and will be replaced by a NULL.                              *\n *                                                                                             *\n * INPUT:      char *String - string to be formated.                                           *\n *             int maxlinelen - Max length of any line in pixels.                              *\n *                                                                                             *\n * OUTPUT:     int - number of lines string is.                                                *\n *                                                                                             *\n * WARNINGS:    The string passed in will be modified - NULLs will be put                      *\n *                into each position that will be a new line.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1992  SB : Created.                                                                 *\n *   05/18/1995 JLB : Greatly revised for new font system.                                     *\n *\t  09/04/1996 BWG : Added '@' is treated as a carriage return for width calculations.\t\t  *\n *=============================================================================================*/\nint Format_Window_String(char * string, int maxlinelen, int & width, int & height)\n{\n\tint\tlinelen;\n\tint\tlines = 0;\n\twidth\t= 0;\n\theight = 0;\n\n\t// In no string was passed in, then there are no lines.\n\tif (!string) return(0);\n\n\t// While there are more letters left divide the line up.\n\twhile (*string) {\n\t\tlinelen = 0;\n\t\theight += FontHeight + FontYSpacing;\n\t\tlines++;\n\n\t\t/*\n\t\t**\tLook for special line break character and force a line break when it is\n\t\t**\tdiscovered.\n\t\t*/\n\t\tif (*string == '@') {\n\t\t\t*string = '\\r';\n\t\t}\n\n\t\t// While the current line is less then the max length...\n\t\twhile (linelen < maxlinelen && *string != '\\r' && *string != '\\0' && *string != '@') {\n\t\t\tlinelen += Char_Pixel_Width(*string++);\n\t\t}\n\n\t\t// if the line is to long...\n\t\tif (linelen >= maxlinelen) {\n\n\t\t\t/*\n\t\t\t**\tBack up to an appropriate location to break.\n\t\t\t*/\n\t\t\twhile (*string != ' ' && *string != '\\r' && *string != '\\0' && *string != '@') {\n\t\t\t\tlinelen -= Char_Pixel_Width(*string--);\n\t\t\t}\n\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the largest width of the worst case string.\n\t\t*/\n\t\tif (linelen > width) {\n\t\t\twidth = linelen;\n\t\t}\n\n\t\t/*\n\t\t**\tForce a break at the end of the line.\n\t\t*/\n\t\tif (*string) {\n\t\t \t*string++ = '\\r';\n\t\t}\n\t}\n\treturn(lines);\n}\n\n\n/***********************************************************************************************\n * Window_Box -- Draws a fancy box over the specified window.                                  *\n *                                                                                             *\n *    This routine will draw a fancy (shaded) box over the specified                           *\n *    window. This is the effect used to give the polished look to                             *\n *    screen rectangles without having to use art.                                             *\n *                                                                                             *\n * INPUT:   window   -- Specified window to fill and border.                                   *\n *                                                                                             *\n *          style    -- The style to render the window.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The rendering is done to the LogicPage.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/03/1992 JLB : Created.                                                                 *\n *   07/31/1992 JLB : Cool raised border effect.                                               *\n *   06/08/1994 JLB : Takes appropriate enumeration parameters.                                *\n *=============================================================================================*/\nvoid Window_Box(WindowNumberType window, BoxStyleEnum style)\n{\n\tint x = WindowList[window][WINDOWX];\n\tint y = WindowList[window][WINDOWY];\n\tint w = WindowList[window][WINDOWWIDTH];\n\tint h = WindowList[window][WINDOWHEIGHT];\n\n\t/*\n\t**\tIf it is to be rendered to the seenpage, then\n\t**\thide the mouse.\n\t*/\n\tif (LogicPage == (&SeenBuff)) Conditional_Hide_Mouse(x ,y, x+w, y+h);\n\n\tDraw_Box(x, y, w, h, style, true);\n\n\t/*\n\t**\tRestore the mouse if it has been hidden and return.\n\t*/\n\tif (LogicPage == &SeenBuff) Conditional_Show_Mouse();\n}\n\n\n/***********************************************************************************************\n * Simple_Text_Print -- Prints text with a drop shadow.                                        *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n *    The C&C gradient font colors are as follows:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t0\t\ttransparent (background)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t1\t\tforeground color for mono-color fonts only\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t2\t\tshadow under characters (\"drop shadow\")\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t3\t\tshadow all around characters (\"full shadow\")\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t4-10\tunused\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t11\t\ttop row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t12\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t13\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t14\t\tnext row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t15\t\tbottom row\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   text  -- Pointer to text to render.                                                *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1991 JLB : Created.                                                                 *\n *   10/26/94   JLB : Handles font X spacing in a more friendly manner.                        *\n *=============================================================================================*/\nvoid Simple_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag)\n{\n\tstatic int\t\tyspace=0;\t\t\t// Y spacing adjustment for font.\n\tstatic int\t\txspace=0;\t\t\t// Spacing adjustment for font.\n\tvoid const *\tfont=0;\t\t// Font to use.\n\tint\t\t\t\tshadow;\t\t\t\t// Requested shadow value.\n\tunsigned char\tfontpalette[16];\t// Working font palette array.\n\tint forecolor;\n\n\tif (fore == NULL) {\n\t\tfore = &ColorRemaps[PCOLOR_RED];\n\t}\n\n\t/*\n\t** Init the font palette to the given background color\n\t*/\n\tmemset(&fontpalette[0], back, 16);\n\n\tforecolor = fore->Color;\n\n\t/*\n\t**\tA gradient font always requires special fixups for the palette\n\t*/\n\tint point = (flag & (TextPrintType)0x000F);\n\tif (point == TPF_VCR || point == TPF_6PT_GRAD || point == TPF_METAL12 || point == TPF_EFNT || point == TPF_TYPE) {\n\n\t\t/*\n\t\t** If a gradient palette is specified, copy the remap table directly, otherwise\n\t\t**\tuse the foreground color as the entire font remap color.\n\t\t*/\n\t\tif (flag & TPF_USE_GRAD_PAL) {\n\t\t\tmemcpy(fontpalette, fore->FontRemap, 16);\n\t\t\tforecolor = fore->Color;\n\t\t\tif (point == TPF_TYPE) {\n\t\t\t\tforecolor = fontpalette[1];\n\t\t\t}\n\t\t} else {\n\t\t\tmemset(&fontpalette[4], fore->Color, 12);\n\t\t\tforecolor = fore->Color;\n\t\t}\n\n\t\t/*\n\t\t** Medium color: set all font colors to a medium value.  This flag\n\t\t** overrides any gradient effects.\n\t\t*/\n\t\tif (flag & TPF_MEDIUM_COLOR) {\n\t\t\tforecolor = fore->Color;\n\t\t\tmemset(&fontpalette[4], fore->Color, 12);\n\t\t}\n\n\t\t/*\n\t\t** Bright color: set all font colors to a bright value.  This flag\n\t\t** overrides any gradient effects.\n\t\t*/\n\t\tif (flag & TPF_BRIGHT_COLOR) {\n\t\t\tforecolor = fore->Bright;\n\t\t\tmemset(&fontpalette[4], fore->BrightColor, 12);\n\t\t}\n\t}\n\n\t/*\n\t**\tChange the current font if it differs from the font desired.\n\t*/\n#ifdef WIN32\n\txspace = 1;\n#else\n\txspace = 0;\n#endif\n\tyspace = 0;\n\n\tswitch (point) {\n\t\tcase TPF_SCORE:\n\t\t\tfont = ScoreFontPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_METAL12:\n\t\t\tfont = Metal12FontPtr;\n\t\t\t//xspace += 1;\n\t\t\tbreak;\n\n\t\tcase TPF_MAP:\n\t\t\tfont = MapFontPtr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_VCR:\n\t\t\tfont = VCRFontPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_6PT_GRAD:\n\t\t\tfont = GradFont6Ptr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_3POINT:\n\t\t\txspace += 1;\n\t\t\tfont = Font3Ptr;\n\t\t\tflag = flag & ~(TPF_DROPSHADOW|TPF_FULLSHADOW|TPF_NOSHADOW);\n\t\t\tbreak;\n\n\t\tcase TPF_6POINT:\n\t\t\tfont = Font6Ptr;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_EFNT:\n\t\t\tfont = EditorFont;\n#ifdef WIN32\n\t\t\tyspace += 1;\n\t\t\txspace -= 1;\n#endif\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tcase TPF_8POINT:\n\t\t\tfont = Font8Ptr;\n#ifdef WIN32\n\t\t\txspace -= 2;\n\t\t\tyspace -= 4;\n#else\n\t\t\txspace -= 1;\n\t\t\tyspace -= 2;\n#endif\n\t\t\tbreak;\n\n\t\tcase TPF_LED:\n#ifdef WIN32\n\t\t\txspace -= 4;\n#else\n\t\t\txspace -= 2;\n#endif\n\t\t\tfont = FontLEDPtr;\n\t\t\tbreak;\n\n\t\tcase TPF_TYPE:\n\t\t\tfont = TypeFontPtr;\n\t\t\txspace -= 1;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t   xspace -= 2;\n\t\t   yspace += 2;\n#else\t//\tI am implicitly assuming that TPF_TYPE was no longer being used, before I came along, despite the following. ajw\n#ifdef GERMAN\n\t\t   yspace += 4;   //VG 10/17/96\n#endif\n#endif\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfont = FontPtr;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tChange the current font palette according to the dropshadow flags.\n\t*/\n\tshadow = (flag & (TPF_NOSHADOW|TPF_DROPSHADOW|TPF_FULLSHADOW|TPF_LIGHTSHADOW));\n\tswitch (shadow) {\n\n\t\t/*\n\t\t**\tThe text is rendered plain.\n\t\t*/\n\t\tcase TPF_NOSHADOW:\n\t\t\tfontpalette[2] = back;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n#ifdef WIN32\n\t\t\tyspace -= 2;\n#else\n\t\t\tyspace -= 1;\n#endif\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe text is rendered with a simple\n\t\t**\tdrop shadow.\n\t\t*/\n\t\tcase TPF_DROPSHADOW:\n\t\t\tfontpalette[2] = BLACK;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSpecial engraved text look for the options\n\t\t**\tdialog system.\n\t\t*/\n\t\tcase TPF_LIGHTSHADOW:\n\t\t\tfontpalette[2] = ((14 * 16) + 7)+1;\n\t\t\tfontpalette[3] = back;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tEach letter is surrounded by black. This is used\n\t\t**\twhen the text will be over a non-plain background.\n\t\t*/\n\t\tcase TPF_FULLSHADOW:\n\t\t\tfontpalette[2] = BLACK;\n\t\t\tfontpalette[3] = BLACK;\n\t\t\txspace -= 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (point != TPF_TYPE) {\n\t\tfontpalette[0] = back;\n\t\tfontpalette[1] = fore->Color;\n\t}\n\n\t/*\n\t**\tSet the font and spacing according to the values they should be.\n\t*/\n\tFontXSpacing = xspace;\n\tFontYSpacing = yspace;\n\tSet_Font(font);\n\tSet_Font_Palette(fontpalette);\n\n\t/*\n\t**\tDisplay the (centered) message if there is one.\n\t*/\n\tif (text && *text) {\n\t\tswitch (flag & (TPF_CENTER|TPF_RIGHT)) {\n\t\t\tcase TPF_CENTER:\n\t\t\t\tx -= String_Pixel_Width(text)>>1;\n\t\t\t\tbreak;\n\n\t\t\tcase TPF_RIGHT:\n\t\t\t\tx -= String_Pixel_Width(text);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (x < (unsigned)LogicPage->Get_Width() && y < (unsigned)LogicPage->Get_Height()) {\n\t\t\tLogicPage->Print(text, x, y, forecolor, back);\n//\t\t\tLogicPage->Print(text, x, y, fore->Color, back);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Fancy_Text_Print -- Prints text with a drop shadow.                                         *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n * INPUT:   text  -- Text number to print.                                                     *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is much slower than normal text print and                          *\n *             if rendered to the SEENPAGE, the intermediate rendering                         *\n *             steps could be visible.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created                                                                  *\n *=============================================================================================*/\nvoid Fancy_Text_Print(int text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...)\n{\n\tchar\t\tbuffer[512];\t\t// Working staging buffer.\n\tva_list\targ;\t\t\t\t\t// Argument list var.\n\n\t/*\n\t**\tIf the text number is valid, then process it.\n\t*/\n\tif (text != TXT_NONE) {\n\t\tva_start(arg, flag);\n\n\t\t/*\n\t\t**\tThe text string must be locked since the vsprintf function doesn't know\n\t\t**\thow to handle EMS pointers.\n\t\t*/\n\t\tchar const * tptr = Text_String(text);\n\t\tvsprintf(buffer, tptr, arg);\n\t\tva_end(arg);\n\n\t\tSimple_Text_Print(buffer, x, y, fore, back, flag);\n\t} else {\n\n\t\t/*\n\t\t**\tJust the flags are to be changed, since the text number is TXT_NONE.\n\t\t*/\n\t\tSimple_Text_Print((char const *)0, x, y, fore, back, flag);\n\t}\n}\n\n\n/***********************************************************************************************\n * Fancy_Text_Print -- Prints text with a drop shadow.                                         *\n *                                                                                             *\n *    This routine functions like Text_Print, but will render a drop                           *\n *    shadow (in black).                                                                       *\n *                                                                                             *\n * INPUT:   text  -- Pointer to text to render.                                                *\n *                                                                                             *\n *          x,y   -- Pixel coordinate for to print text.                                       *\n *                                                                                             *\n *          fore  -- Foreground color.                                                         *\n *                                                                                             *\n *          back  -- Background color.                                                         *\n *                                                                                             *\n *          flag  -- Text print control flags.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is much slower than normal text print and                          *\n *             if rendered to the SEENPAGE, the intermediate rendering                         *\n *             steps could be visible.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1991 JLB : Created.                                                                 *\n *   10/26/94   JLB : Handles font X spacing in a more friendly manner.                        *\n *   11/29/1994 JLB : Separated actual draw action.                                            *\n *=============================================================================================*/\nvoid Fancy_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...)\n{\n\tchar\t\tbuffer[512];\t\t// Working staging buffer.\n\tva_list\targ;\t\t\t\t\t// Argument list var.\n\n\t/*\n\t**\tIf there is a valid text string pointer then build the final string into the\n\t**\tworking buffer before sending it to the simple string printing routine.\n\t*/\n\tif (text) {\n\n\t\t/*\n\t\t**\tSince vsprintf doesn't know about EMS pointers, be sure to surround this\n\t\t**\tcall with locking code.\n\t\t*/\n\t\tva_start(arg, flag);\n\t\tvsprintf(buffer, text, arg);\n\t\tva_end(arg);\n\n\t\tSimple_Text_Print(buffer, x, y, fore, back, flag);\n\t} else {\n\n\t\t/*\n\t\t**\tJust the flags are desired to be changed, so call the simple print routine with\n\t\t**\ta NULL text pointer.\n\t\t*/\n\t\tSimple_Text_Print((char const *)0, x, y, fore, back, flag);\n\t}\n}\n\n\n/***********************************************************************************************\n * Clip_Text_Print -- Prints text with clipping and <TAB> support.                             *\n *                                                                                             *\n *    Use this routine to print text that that should be clipped at an arbitrary right margin  *\n *    as well as possibly recognizing <TAB> characters. Typical users of this routine would    *\n *    be list boxes.                                                                           *\n *                                                                                             *\n * INPUT:   text  -- Reference to the text to print.                                           *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of the upper left corner of the text position.           *\n *                                                                                             *\n *          fore  -- The foreground color to use.                                              *\n *                                                                                             *\n *          back  -- The background color to use.                                              *\n *                                                                                             *\n *          flag  -- The text print flags to use.                                              *\n *                                                                                             *\n *          width -- The maximum pixel width to draw the text. Extra characters beyond this    *\n *                   point will not be printed.                                                *\n *                                                                                             *\n *          tabs  -- Optional pointer to a series of pixel tabstop positions.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Conquer_Clip_Text_Print(char const * text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, int width, int const * tabs)\n{\n\tchar buffer[512];\n\n\tif (text) {\n\t\tstrcpy(buffer, text);\n\n\t\t/*\n\t\t**\tSet the font and spacing characteristics according to the flag\n\t\t**\tvalue passed in.\n\t\t*/\n\t\t//PG_TO_FIX\n\t\t//Simple_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, flag);\n\n\t\tchar * source = &buffer[0];\n\t\tunsigned offset = 0;\n\t\tint processing = true;\n\t\twhile (processing && offset < (unsigned) width) {\n\t\t\tchar * ptr = strchr(source, '\\t');\n\n\t\t\t/*\n\t\t\t**\tZap the tab character. It will be processed later.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\t*ptr = '\\0';\n\t\t\t}\n\n\t\t\tif (*source) {\n\n\t\t\t\t/*\n\t\t\t\t**\tScan forward until the end of the string is reached or the\n\t\t\t\t**\tmaximum width, whichever comes first.\n\t\t\t\t*/\n\t\t\t\tint w = 0;\n\t\t\t\tchar * bptr = source;\n\t\t\t\tdo {\n\t\t\t\t\tw += Char_Pixel_Width(*bptr++);\n\t\t\t\t} while (*bptr && offset+w < (unsigned)width);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the maximum width has been exceeded, then remove the last\n\t\t\t\t**\tcharacter and signal that further processing is not necessary.\n\t\t\t\t*/\n\t\t\t\tif (offset+w >= (unsigned)width) {\n\t\t\t\t\tbptr--;\n\t\t\t\t\tw -= Char_Pixel_Width(*bptr);\n\t\t\t\t\t*bptr = '\\0';\n\t\t\t\t\tprocessing = 0;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPrint this text block and advance the offset accordingly.\n\t\t\t\t*/\n\t\t\t\tSimple_Text_Print(source, x+offset, y, fore, back, flag);\n\t\t\t\toffset += w;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a <TAB> was the terminator for this text block, then advance\n\t\t\t**\tto the next tabstop.\n\t\t\t*/\n\t\t\tif (ptr) {\n\t\t\t\tif (tabs) {\n\t\t\t\t\twhile ((int)offset > *tabs) {\n\t\t\t\t\t\ttabs++;\n\t\t\t\t\t}\n\t\t\t\t\toffset = *tabs;\n\t\t\t\t} else {\n\t\t\t\t\toffset = ((offset+1 / 50) + 1) * 50;\n\t\t\t\t}\n\t\t\t\tsource = ptr+1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/***************************************************************************\n * Plain_Text_Print -- Prints text without using a color scheme            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to print\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tx,y\t\tcoords to print at\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tfore\t\tdesired foreground color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tback\t\tdesired background color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tflag\t\ttext print control flags\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not use the gradient control flag with this routine!  For \t\t\t*\n *\t\ta gradient appearance, use Fancy_Text_Print.\t\t\t\t\t\t\t\t\t*\n *\t\tDespite this routine's name, it is actually faster to call\t\t\t\t*\n *\t\tFancy_Text_Print than this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/05/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Plain_Text_Print(int text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...)\n{\n\tRemapControlType scheme;\n\n\tmemset(&scheme, 0, sizeof(RemapControlType));\n\tmemset(&(scheme.FontRemap[4]), fore, 12);\n\n\tscheme.BrightColor = fore;\n\tscheme.Color = fore;\n\tscheme.Shadow = fore;\n\tscheme.Background = fore;\n\tscheme.Corners = fore;\n\tscheme.Highlight = fore;\n\tscheme.Box = fore;\n\tscheme.Bright = fore;\n\tscheme.Underline = fore;\n\tscheme.Bar = fore;\n\n\tFancy_Text_Print(text, x, y, &scheme, back, flag);\n}\n\n\n/***************************************************************************\n * Plain_Text_Print -- Prints text without using a color scheme            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttext\t\ttext to print\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tx,y\t\tcoords to print at\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tfore\t\tdesired foreground color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tback\t\tdesired background color\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tflag\t\ttext print control flags\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not use the gradient control flag with this routine!  For \t\t\t*\n *\t\ta gradient appearance, use Fancy_Text_Print.\t\t\t\t\t\t\t\t\t*\n *\t\tDespite this routine's name, it is actually faster to call\t\t\t\t*\n *\t\tFancy_Text_Print than this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/05/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Plain_Text_Print(char const * text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...)\n{\n\tRemapControlType scheme;\n\n\tmemset(&scheme, 0, sizeof(RemapControlType));\n\tmemset(&(scheme.FontRemap[4]), fore, 12);\n\n\tscheme.BrightColor = fore;\n\tscheme.Color = fore;\n\tscheme.Shadow = fore;\n\tscheme.Background = fore;\n\tscheme.Corners = fore;\n\tscheme.Highlight = fore;\n\tscheme.Box = fore;\n\tscheme.Bright = fore;\n\tscheme.Underline = fore;\n\tscheme.Bar = fore;\n\n\tFancy_Text_Print(text, x, y, &scheme, back, flag);\n}\n\n\n\nunsigned char * Font_Palette(int color)\n{\n\tstatic unsigned char _fpalette[16];\n\n\tmemset(_fpalette, '\\0', sizeof(_fpalette));\n\tmemset(&_fpalette[11], color, 5);\n\treturn(_fpalette);\n}\n\n\n\n/***********************************************************************************************\n * Draw_Caption -- Draws a caption on a dialog box.                                            *\n *                                                                                             *\n *    This routine draws the caption text and any fancy filigree that the dialog may require.  *\n *                                                                                             *\n * INPUT:   text  -- The text of the caption. This is the text number.                         *\n *                                                                                             *\n *          x,y   -- The dialog box X and Y pixel coordinate of the upper left corner.         *\n *                                                                                             *\n *          w     -- The width of the dialog box (in pixels).                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Draw_Caption(int text, int x, int y, int w)\n{\n\tDraw_Caption(Text_String(text), x, y, w);\n}\n\n\nvoid Draw_Caption(char const * text, int x, int y, int w)\n{\n\t/*\n\t**\tDraw the caption.\n\t*/\n\tif (text != NULL && *text != '\\0') {\n\t\tif (Debug_Map) {\n\t\t\tFancy_Text_Print(text, w/2 + x, (2 * RESFACTOR) + y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_EFNT|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t} else {\n\t\t\tFancy_Text_Print(text, w/2 + x, (8 * RESFACTOR) + y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_TEXT);\n\t\t\tint length = String_Pixel_Width(text);\n\t\t\tLogicPage->Draw_Line((x+(w/2))-(length/2), y+FontHeight+FontYSpacing + (8 * RESFACTOR), (x+(w/2))+(length/2),\n\t\t\t\ty+FontHeight+FontYSpacing + (8 * RESFACTOR), GadgetClass::Get_Color_Scheme()->Box);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/DIBAPI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef DIBAPI_H\n#define DIBAPI_H\n/*\n *  dibapi.h\n *\n *  Copyright (c) 1991 Microsoft Corporation. All rights reserved\n *\n *  Header file for Device-Independent Bitmap (DIB) API.  Provides\n *  function prototypes and constants for the following functions:\n *\n *  BitmapToDIB()        - Creates a DIB from a bitmap\n *  ChangeBitmapFormat() - Changes a bitmap to a specified DIB format\n *  ChangeDIBFormat()    - Changes a DIB's BPP and/or compression format\n *  CopyScreenToBitmap() - Copies entire screen to a standard Bitmap\n *  CopyScreenToDIB()    - Copies entire screen to a DIB\n *  CopyWindowToBitmap() - Copies a window to a standard Bitmap\n *  CopyWindowToDIB()    - Copies a window to a DIB\n *  CreateDIBPalette()   - Creates a palette from a DIB\n *  CreateDIB()          - Creates a new DIB\n *  DestroyDIB()         - Deletes DIB when finished using it\n *  DIBError()           - Displays message box with error message\n *  DIBHeight()          - Gets the DIB height\n *  DIBNumColors()       - Calculates number of colors in the DIB's color table\n *  DIBToBitmap()        - Creates a bitmap from a DIB\n *  DIBWidth()           - Gets the DIB width\n *  FindDIBBits()        - Sets pointer to the DIB bits\n *  GetSystemPalette()   - Gets the current palette\n *  LoadDIB()            - Loads a DIB from a file\n *  PaintBitmap()        - Displays standard bitmap in the specified DC\n *  PaintDIB()           - Displays DIB in the specified DC\n *  PalEntriesOnDevice() - Gets the number of palette entries\n *  PaletteSize()        - Calculates the buffer size required by a palette\n *  PrintDIB()           - Prints the specified DIB\n *  PrintScreen()        - Prints the entire screen\n *  PrintWindow()        - Prints all or part of a window\n *  SaveDIB()            - Saves the specified dib in a file\n *\n * See the file DIBAPI.TXT for more information about these functions.\n *\n *  ajw added\n *  LoadDIB_FromMemory() - Loads a DIB from BMP file data located at a location in memory.\n *\n */\n\n\n/* Handle to a DIB */\n#define HDIB HANDLE\n\n\n/* Print Area selection */\n#define PW_WINDOW        1\n#define PW_CLIENT        2\n\n\n/* Print Options selection */\n#define PW_BESTFIT       1\n#define PW_STRETCHTOPAGE 2\n#define PW_SCALE         3\n\n/* DIB Macros*/\n\n// WIDTHBYTES performs DWORD-aligning of DIB scanlines.  The \"bits\"\n// parameter is the bit count for the scanline (biWidth * biBitCount),\n// and this macro returns the number of DWORD-aligned bytes needed \n// to hold those bits.\n\n#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)\n\n/* Error constants */\nenum {\n      ERR_MIN = 0,                     // All error #s >= this value\n      ERR_NOT_DIB = 0,                 // Tried to load a file, NOT a DIB!\n      ERR_MEMORY,                      // Not enough memory!\n      ERR_READ,                        // Error reading file!\n      ERR_LOCK,                        // Error on a GlobalLock()!\n      ERR_OPEN,                        // Error opening a file!\n      ERR_CREATEPAL,                   // Error creating palette.\n      ERR_GETDC,                       // Couldn't get a DC.\n      ERR_CREATEDDB,                   // Error create a DDB.\n      ERR_STRETCHBLT,                  // StretchBlt() returned failure.\n      ERR_STRETCHDIBITS,               // StretchDIBits() returned failure.\n      ERR_SETDIBITSTODEVICE,           // SetDIBitsToDevice() failed.\n      ERR_STARTDOC,                    // Error calling StartDoc().\n      ERR_NOGDIMODULE,                 // Couldn't find GDI module in memory.\n      ERR_SETABORTPROC,                // Error calling SetAbortProc().\n      ERR_STARTPAGE,                   // Error calling StartPage().\n      ERR_NEWFRAME,                    // Error calling NEWFRAME escape.\n      ERR_ENDPAGE,                     // Error calling EndPage().\n      ERR_ENDDOC,                      // Error calling EndDoc().\n      ERR_SETDIBITS,                   // Error calling SetDIBits().\n      ERR_FILENOTFOUND,                // Error opening file in GetDib()\n      ERR_INVALIDHANDLE,               // Invalid Handle\n      ERR_DIBFUNCTION,                 // Error on call to DIB function\n      ERR_MAX                          // All error #s < this value\n     };\n\n\n\n/* Function prototypes */\n\nHDIB      FAR  BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);\nHDIB      FAR  ChangeBitmapFormat (HBITMAP  hBitmap,\n                                   WORD     wBitCount,\n                                   DWORD    dwCompression,\n                                   HPALETTE hPal);\nHDIB      FAR  ChangeDIBFormat (HDIB hDIB, WORD wBitCount,\n                                DWORD dwCompression);\nHBITMAP   FAR  CopyScreenToBitmap (LPRECT);\nHDIB      FAR  CopyScreenToDIB (LPRECT);\nHBITMAP   FAR  CopyWindowToBitmap (HWND, WORD);\nHDIB      FAR  CopyWindowToDIB (HWND, WORD);\nHPALETTE  FAR  CreateDIBPalette (HDIB hDIB);\nHDIB      FAR  CreateDIB(DWORD, DWORD, WORD);\nWORD      FAR  DestroyDIB (HDIB);\nvoid      FAR  DIBError (int ErrNo);\nDWORD     FAR  DIBHeight (LPCSTR lpDIB);\nWORD      FAR  DIBNumColors (LPCSTR lpDIB);\nHBITMAP   FAR  DIBToBitmap (HDIB hDIB, HPALETTE hPal);\nDWORD     FAR  DIBWidth (LPCSTR lpDIB);\nLPSTR     FAR  FindDIBBits (LPCSTR lpDIB);\nHPALETTE  FAR  GetSystemPalette (void);\nHDIB      FAR  LoadDIB (LPSTR);\nBOOL      FAR  PaintBitmap (HDC, LPRECT, HBITMAP, LPRECT, HPALETTE);\nBOOL      FAR  PaintDIB (HDC, LPRECT, HDIB, LPRECT, HPALETTE);\nint       FAR  PalEntriesOnDevice (HDC hDC);\nWORD      FAR  PaletteSize (LPCSTR lpDIB);\nWORD      FAR  PrintDIB (HDIB, WORD, WORD, WORD, LPSTR);\nWORD      FAR  PrintScreen (LPRECT, WORD, WORD, WORD, LPSTR);\nWORD      FAR  PrintWindow (HWND, WORD, WORD, WORD, WORD, LPSTR);\nWORD      FAR  SaveDIB (HDIB, LPSTR);\n\n//\tajw added\nHDIB\tLoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize );\n\n#endif\n"
  },
  {
    "path": "REDALERT/DIBFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//*******************************************************************\n//\n//  file.c\n//\n//  Source file for Device-Independent Bitmap (DIB) API.  Provides\n//  the following functions:\n//\n//  SaveDIB()           - Saves the specified dib in a file\n//  LoadDIB()           - Loads a DIB from a file\n//  DestroyDIB()        - Deletes DIB when finished using it\n//\n// Development Team: Mark Bader\n//                   Patrick Schreiber\n//                   Garrett McAuliffe\n//                   Eric Flo\n//                   Tony Claflin\n//\n// Written by Microsoft Product Support Services, Developer Support.\n// COPYRIGHT:\n//\n//   (C) Copyright Microsoft Corp. 1993.  All rights reserved.\n//\n//   You have a royalty-free right to use, modify, reproduce and\n//   distribute the Sample Files (and/or any modified version) in\n//   any way you find useful, provided that you agree that\n//   Microsoft has no warranty obligations or liability for any\n//   Sample Application Files which are modified.\n//\n//*******************************************************************\n#if (0) // ST - 5/8/2019\n\n#include <windows.h>\n#include <string.h>\n#include <stdio.h>\n#include <math.h>\n#include <io.h>\n#include <direct.h>\n#include <stdlib.h>\n#include \"dibutil.h\"\n#include \"dibapi.h\"\n\n//#include \"WolDebug.h\"\n\n/*\n * Dib Header Marker - used in writing DIBs to files\n */\n#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')\n\n/*********************************************************************\n *\n * Local Function Prototypes\n *\n *********************************************************************/\n\n\nHANDLE ReadDIBFile(int);\nBOOL MyRead(int, LPSTR, DWORD);\nBOOL SaveDIBFile(void);\nBOOL WriteDIB(LPSTR, HANDLE);\nDWORD PASCAL MyWrite(int, VOID FAR *, DWORD);\n\n/*************************************************************************\n *\n * LoadDIB()\n *\n * Loads the specified DIB from a file, allocates memory for it,\n * and reads the disk file into the memory.\n *\n *\n * Parameters:\n *\n * LPSTR lpFileName - specifies the file to load a DIB from\n *\n * Returns: A handle to a DIB, or NULL if unsuccessful.\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs; This\n * function will reject any file that is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Based on DIBVIEW\n *\n *************************************************************************/\n\n\nHDIB FAR LoadDIB(LPSTR lpFileName)\n{\n   HDIB hDIB;\n   int hFile;\n   OFSTRUCT ofs;\n\n   /*\n    * Set the cursor to a hourglass, in case the loading operation\n    * takes more than a sec, the user will know what's going on.\n    */\n\n   SetCursor(LoadCursor(NULL, IDC_WAIT));\n   if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)\n   {\n      hDIB = ReadDIBFile(hFile);\n      _lclose(hFile);\n      SetCursor(LoadCursor(NULL, IDC_ARROW));\n      return hDIB;\n   }\n   else\n   {\n//      DIBError(ERR_FILENOTFOUND);\n      SetCursor(LoadCursor(NULL, IDC_ARROW));\n      return NULL;\n   }\n}\n\n\n/*************************************************************************\n *\n * SaveDIB()\n *\n * Saves the specified DIB into the specified file name on disk.  No\n * error checking is done, so if the file already exists, it will be\n * written over.\n *\n * Parameters:\n *\n * HDIB hDib - Handle to the dib to save\n *\n * LPSTR lpFileName - pointer to full pathname to save DIB under\n *\n * Return value: 0 if successful, or one of:\n *        ERR_INVALIDHANDLE\n *        ERR_OPEN\n *        ERR_LOCK\n *\n * History:\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs, so this\n * function will not save a file if it is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Taken from DIBVIEW (which was taken\n *                                      from SHOWDIB)\n *            1/30/92   Mark Bader   Fixed problem of writing too many \n *                                      bytes to the file\n *            6/24/92   Mark Bader   Added check for OS/2 DIB\n *\n *************************************************************************/\n\n\nWORD FAR SaveDIB(HDIB hDib, LPSTR lpFileName)\n{\n   BITMAPFILEHEADER bmfHdr; // Header for Bitmap file\n   LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure\n   int fh;     // file handle for opened file\n   OFSTRUCT of;     // OpenFile structure\n   DWORD dwDIBSize;\n   DWORD dwError;   // Error return from MyWrite\n\n   if (!hDib)\n      return ERR_INVALIDHANDLE;\n   fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);\n   if (fh == -1)\n      return ERR_OPEN;\n\n   /*\n    * Get a pointer to the DIB memory, the first of which contains\n    * a BITMAPINFO structure\n    */\n   lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);\n   if (!lpBI)\n      return ERR_LOCK;\n\n   // Check to see if we're dealing with an OS/2 DIB.  If so, don't\n   // save it because our functions aren't written to deal with these\n   // DIBs.\n\n   if (lpBI->biSize != sizeof(BITMAPINFOHEADER))\n   {\n     GlobalUnlock(hDib);\n     return ERR_NOT_DIB;\n   }\n\n   /*\n    * Fill in the fields of the file header\n    */\n\n   /* Fill in file type (first 2 bytes must be \"BM\" for a bitmap) */\n   bmfHdr.bfType = DIB_HEADER_MARKER;  // \"BM\"\n\n   // Calculating the size of the DIB is a bit tricky (if we want to\n   // do it right).  The easiest way to do this is to call GlobalSize()\n   // on our global handle, but since the size of our global memory may have\n   // been padded a few bytes, we may end up writing out a few too\n   // many bytes to the file (which may cause problems with some apps,\n   // like HC 3.0).\n   //\n   // So, instead let's calculate the size manually.\n   //\n   // To do this, find size of header plus size of color table.  Since the\n   // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains\n   // the size of the structure, let's use this.\n\n   dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);  // Partial Calculation\n\n   // Now calculate the size of the image\n\n   if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) {\n\n      // It's an RLE bitmap, we can't calculate size, so trust the\n      // biSizeImage field\n\n      dwDIBSize += lpBI->biSizeImage;\n      }\n   else {\n      DWORD dwBmBitsSize;  // Size of Bitmap Bits only\n\n      // It's not RLE, so size is Width (DWORD aligned) * Height\n\n      dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;\n\n      dwDIBSize += dwBmBitsSize;\n      \n      // Now, since we have calculated the correct size, why don't we\n      // fill in the biSizeImage field (this will fix any .BMP files which \n      // have this field incorrect).\n\n      lpBI->biSizeImage = dwBmBitsSize;\n      }\n\n\n   // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)\n                   \n   bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);\n   bmfHdr.bfReserved1 = 0;\n   bmfHdr.bfReserved2 = 0;\n\n   /*\n    * Now, calculate the offset the actual bitmap bits will be in\n    * the file -- It's the Bitmap file header plus the DIB header,\n    * plus the size of the color table.\n    */\n   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +\n                      PaletteSize((LPSTR)lpBI);\n\n   /* Write the file header */\n   _lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));\n\n   /*\n    * Write the DIB header and the bits -- use local version of\n    * MyWrite, so we can write more than 32767 bytes of data\n    */\n   dwError = MyWrite(fh, (LPSTR)lpBI, dwDIBSize);\n   GlobalUnlock(hDib);\n   _lclose(fh);\n\n   if (dwError == 0)\n     return ERR_OPEN; // oops, something happened in the write\n   else\n     return 0; // Success code\n}\n\n\n/*************************************************************************\n *\n * DestroyDIB ()\n *\n * Purpose:  Frees memory associated with a DIB\n *\n * Returns:  Nothing\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Created\n *\n *************************************************************************/\n\n\nWORD FAR DestroyDIB(HDIB hDib)\n{\n   GlobalFree(hDib);\n   return 0;\n}\n\n\n//************************************************************************\n//\n// Auxiliary Functions which the above procedures use\n//\n//************************************************************************\n\n\n/*************************************************************************\n *\n * Function:  ReadDIBFile (int)\n *\n *  Purpose:  Reads in the specified DIB file into a global chunk of\n *            memory.\n *\n *  Returns:  A handle to a dib (hDIB) if successful.\n *            NULL if an error occurs.\n *\n * Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything\n *            from the end of the BITMAPFILEHEADER structure on is\n *            returned in the global memory handle.\n *\n *\n * NOTE: The DIB API were not written to handle OS/2 DIBs, so this\n * function will reject any file that is not a Windows DIB.\n *\n * History:   Date      Author       Reason\n *            9/15/91   Mark Bader   Based on DIBVIEW\n *            6/25/92   Mark Bader   Added check for OS/2 DIB\n *            7/21/92   Mark Bader   Added code to deal with bfOffBits\n *                                     field in BITMAPFILEHEADER      \n *            9/11/92   Mark Bader   Fixed Realloc Code to free original mem\n *\n *************************************************************************/\n\nHANDLE ReadDIBFile(int hFile)\n{\n   BITMAPFILEHEADER bmfHeader;\n   DWORD dwBitsSize;\n   UINT nNumColors;   // Number of colors in table\n   HANDLE hDIB;        \n   HANDLE hDIBtmp;    // Used for GlobalRealloc() //MPB\n   LPBITMAPINFOHEADER lpbi;\n   DWORD offBits;\n\n   /*\n    * get length of DIB in bytes for use when reading\n    */\n\n   dwBitsSize = filelength(hFile);\n\n   // Allocate memory for header & color table.\tWe'll enlarge this\n   // memory as needed.\n\n   hDIB = GlobalAlloc(GMEM_MOVEABLE,\n       (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));\n   \n   if (!hDIB) return NULL;\n\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   if (!lpbi) \n   {\n     GlobalFree(hDIB);\n     return NULL;\n   }\n\n   // read the BITMAPFILEHEADER from our file\n\n   if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))\n     goto ErrExit;\n\n   if (bmfHeader.bfType != 0x4d42)\t/* 'BM' */\n     goto ErrExit;\n\n   // read the BITMAPINFOHEADER\n\n   if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))\n     goto ErrExit;\n\n   // Check to see that it's a Windows DIB -- an OS/2 DIB would cause\n   // strange problems with the rest of the DIB API since the fields\n   // in the header are different and the color table entries are\n   // smaller.\n   //\n   // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.\n\n   if (lpbi->biSize == sizeof(BITMAPCOREHEADER))\n     goto ErrExit;\n\n   // Now determine the size of the color table and read it.  Since the\n   // bitmap bits are offset in the file by bfOffBits, we need to do some\n   // special processing here to make sure the bits directly follow\n   // the color table (because that's the format we are susposed to pass\n   // back)\n   nNumColors = (UINT)lpbi->biClrUsed;\n   if (!nNumColors)\n    {\n      // no color table for 24-bit, default size otherwise\n      if (lpbi->biBitCount != 24)\n        nNumColors = 1 << lpbi->biBitCount; /* standard size table */\n    }\n\n   // fill in some default values if they are zero\n   if (lpbi->biClrUsed == 0)\n     lpbi->biClrUsed = nNumColors;\n\n   if (lpbi->biSizeImage == 0)\n   {\n     lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)\n\t\t\t * lpbi->biHeight;\n   }\n\n   // get a proper-sized buffer for header, color table and bits\n   GlobalUnlock(hDIB);\n   hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize +\n                        nNumColors * sizeof(RGBQUAD) +\n                        lpbi->biSizeImage, 0);\n\n   if (!hDIBtmp) // can't resize buffer for loading\n     goto ErrExitNoUnlock; //MPB\n   else\n     hDIB = hDIBtmp;\n\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n   // read the color table\n   _lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));\n\n   // offset to the bits from start of DIB header\n   offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);\n\n   // If the bfOffBits field is non-zero, then the bits might *not* be\n   // directly following the color table in the file.  Use the value in\n   // bfOffBits to seek the bits.\n\n   if (bmfHeader.bfOffBits != 0L)\n      _llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);\n   \n   if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))\n     goto OKExit;\n\n\nErrExit:\n    GlobalUnlock(hDIB);    \nErrExitNoUnlock:    \n    GlobalFree(hDIB);\n    return NULL;\n\nOKExit:\n    GlobalUnlock(hDIB);\n    return hDIB;\n}\n\n/*************************************************************************\n\n  Function:  MyRead (int, LPSTR, DWORD)\n\n   Purpose:  Routine to read files greater than 64K in size.\n\n   Returns:  TRUE if successful.\n             FALSE if an error occurs.\n\n  \n  History:   Date      Author       Reason\n             9/15/91   Mark Bader   Based on DIBVIEW\n \n*************************************************************************/\n\n\nBOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)\n{\n   char huge *lpInBuf = (char huge *)lpBuffer;\n   int nBytes;\n\n   /*\n    * Read in the data in 32767 byte chunks (or a smaller amount if it's\n    * the last chunk of data read)\n    */\n\n   while (dwSize)\n   {\n      nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));\n      if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)\n         return FALSE;\n      dwSize -= nBytes;\n      lpInBuf += nBytes;\n   }\n   return TRUE;\n}\n\n\n/****************************************************************************\n\n FUNCTION   : MyWrite(int fh, VOID FAR *pv, DWORD ul)\n\n PURPOSE    : Writes data in steps of 32k till all the data is written.\n              Normal _lwrite uses a WORD as 3rd parameter, so it is\n              limited to 32767 bytes, but this procedure is not.\n\n RETURNS    : 0 - If write did not proceed correctly.\n              number of bytes written otherwise.\n \n  History:   Date      Author       Reason\n             9/15/91   Mark Bader   Based on DIBVIEW\n\n ****************************************************************************/\n\n\nDWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)\n{\n   DWORD dwBytesTmp = dwBytes;       // Save # of bytes for return value\n   BYTE huge *hpBuffer = (BYTE huge *)lpBuffer;   // make a huge pointer to the data\n\n   /*\n    * Write out the data in 32767 byte chunks.\n    */\n\n   while (dwBytes > 32767)\n   {\n      if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)\n         return 0;\n      dwBytes -= 32767;\n      hpBuffer += 32767;\n   }\n\n   /* Write out the last chunk (which is < 32767 bytes) */\n   if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)\n      return 0;\n   return dwBytesTmp;\n}\n\n//\tajw added\n//\tAdded to allow \"loading\" from a location in memory.\n//\tA modification of ReadDIBFile(), above.\n//***********************************************************************************************\nHDIB LoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize )\n{\n\tBITMAPFILEHEADER bmfHeader;\n\tUINT nNumColors;   // Number of colors in table\n\tHANDLE hDIB;        \n\tHANDLE hDIBtmp;    // Used for GlobalRealloc() //MPB\n\tLPBITMAPINFOHEADER lpbi;\n\tDWORD offBits;\n\n\tconst unsigned char* const pDataStart = pData;\n\tconst unsigned char* pDataEnd = pData + dwBitsSize;\t\t//\tOne char past end of \"file\".\n\n\t// Allocate memory for header & color table.\tWe'll enlarge this\n\t// memory as needed.\n\n//\tdebugprint( \"LoadDIB_FromMemory, GlobalAlloc\\n\" );\n\thDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));\n//\tdebugprint( \"hDIB from GlobalALloc is %i\\n\", hDIB );\n\n\tif (!hDIB)\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: failed alloc\\n\" );\n\t\treturn NULL;\n\t}\n\n//\tdebugprint( \"LoadDIB_FromMemory, lpbi Lock\\n\" );\n\tlpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n//\tdebugprint( \"lpbi is %i\\n\", lpbi );\n\tif (!lpbi) \n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: failed lock\\n\" );\n\t\tGlobalFree(hDIB);\n\t\treturn NULL;\n\t}\n\n\t// read the BITMAPFILEHEADER from our file\n//\tif (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))\n//\t\tgoto ErrExit;\n\tif( pData + sizeof( BITMAPFILEHEADER ) >= pDataEnd )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size\\n\" );\n\t\tgoto ErrExit;\n\t}\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy BITMAPFILEHEADER %i bytes\\n\", sizeof( BITMAPFILEHEADER ) );\n\tmemcpy( &bmfHeader, pData, sizeof( BITMAPFILEHEADER ) );\n\tpData += sizeof( BITMAPFILEHEADER );\n\n\tif (bmfHeader.bfType != 0x4d42)\t/* 'BM' */\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: no BM\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\t// read the BITMAPINFOHEADER\n//\tif (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))\n//\t\tgoto ErrExit;\n\tif( pData + sizeof( BITMAPINFOHEADER ) >= pDataEnd )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size 2\\n\" );\n\t\tgoto ErrExit;\n\t}\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy BITMAPINFOHEADER %i bytes\\n\", sizeof( BITMAPINFOHEADER ) );\n\tmemcpy( lpbi, pData, sizeof( BITMAPINFOHEADER ) );\n\tpData += sizeof( BITMAPINFOHEADER );\n\n\t// Check to see that it's a Windows DIB -- an OS/2 DIB would cause\n\t// strange problems with the rest of the DIB API since the fields\n\t// in the header are different and the color table entries are\n\t// smaller.\n\t//\n\t// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.\n\n\tif (lpbi->biSize == sizeof(BITMAPCOREHEADER))\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: lpbi->biSize bad\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\tif( lpbi->biCompression != BI_RGB )\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: Image is compressed\\n\" );\n\t\tgoto ErrExit;\n\t}\n\n\t// Now determine the size of the color table and read it.  Since the\n\t// bitmap bits are offset in the file by bfOffBits, we need to do some\n\t// special processing here to make sure the bits directly follow\n\t// the color table (because that's the format we are susposed to pass\n\t// back)\n\tnNumColors = (UINT)lpbi->biClrUsed;\n\tif (!nNumColors)\n\t{\n\t\t// no color table for 24-bit, default size otherwise\n\t\tif (lpbi->biBitCount != 24)\n\t\t\tnNumColors = 1 << lpbi->biBitCount; /* standard size table */\n\t}\n\n\t// fill in some default values if they are zero\n\tif (lpbi->biClrUsed == 0)\n\t\tlpbi->biClrUsed = nNumColors;\n\n//\tdebugprint( \"biSizeImage is %i. I would say it was %i, because the bpp is %i.\\n\", lpbi->biSizeImage, ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight, lpbi->biBitCount );\n\tif (lpbi->biSizeImage == 0)\n\t{\n\t\tlpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;\n\t}\n\n\t// get a proper-sized buffer for header, color table and bits\n\tGlobalUnlock(hDIB);\n//\tdebugprint( \"LoadDIB_FromMemory, GlobalReAlloc: lpbi->biSize=%i, nNumColors=%i, lpbi->biSizeImage=%i\\n\", lpbi->biSize, nNumColors,lpbi->biSizeImage );\n\thDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * sizeof(RGBQUAD) + lpbi->biSizeImage, 0);\n\n\tif (!hDIBtmp) // can't resize buffer for loading\n\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: realloc failed\\n\" );\n\t\tgoto ErrExitNoUnlock; //MPB\n\t}\n\telse\n\t\thDIB = hDIBtmp;\n\n\tlpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n\t// read the color table\n//\t_lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy color table %i colors, so %i bytes\\n\", nNumColors, nNumColors * sizeof(RGBQUAD) );\n\tmemcpy( (LPSTR)(lpbi) + lpbi->biSize, pData, nNumColors * sizeof(RGBQUAD) );\n\tpData += nNumColors * sizeof(RGBQUAD);\n\n\t// offset to the bits from start of DIB header\n\toffBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);\n\n\t// If the bfOffBits field is non-zero, then the bits might *not* be\n\t// directly following the color table in the file.  Use the value in\n\t// bfOffBits to seek the bits.\n\n\tif (bmfHeader.bfOffBits != 0L)\n//\t\t_llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);\n\t\tpData = pDataStart + bmfHeader.bfOffBits;\n\n//\tdebugprint( \"bmfHeader.bfOffBits is %i\\n\", bmfHeader.bfOffBits );\n\n//\tif (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))\n//\t\tgoto OKExit;\n//\tdebugprint( \"Checking that pData(%i) + biSizeImage(%i), which is %i, is equal to pDataEnd(%i)\\n\", \n//\t\t\t\t\tpData, lpbi->biSizeImage, pData + lpbi->biSizeImage, pDataEnd );\n//\tif( pData + lpbi->biSizeImage != pDataEnd )\t\t\tcondition relaxed\n//\t{\n//\t\tdebugprint( \"LoadDIB_FromMemory error: bad size 3\\n\" );\n//\t\tgoto ErrExit;\n//\t}\n\n//\tdebugprint( \"LoadDIB_FromMemory, memcpy the bits, %i bytes. Image is w %i, h.%i\\n\", \n//\t\t\t\t\t\t\t\tlpbi->biSizeImage, lpbi->biWidth, lpbi->biHeight );\n//\tdebugprint( \"Writing to lpbi (%i) + offBits (%i)\\n\", lpbi, offBits );\n\n\tmemcpy( (LPSTR)lpbi + offBits, pData, lpbi->biSizeImage );\n//\tpData += lpbi->biSizeImage;\n//\tif( pData != pDataEnd )\t\t//\tShould end up one byte past end of data. - condition relaxed\n//\t\tdebugprint( \"LoadDIB_FromMemory: ERROR! Ended up at %i instead of %i\\n\", pData, pDataEnd );\n\tgoto OKExit;\n\nErrExit:\n\tGlobalUnlock(hDIB);\nErrExitNoUnlock:    \n\tGlobalFree(hDIB);\n//\tdebugprint( \"LoadDIB_FromMemory Error!\\n\" );\n\treturn NULL;\n\nOKExit:\n\tGlobalUnlock(hDIB);\n\treturn hDIB;\n}\n#endif"
  },
  {
    "path": "REDALERT/DIBUTIL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//**********************************************************************\n//\n//  dibutil.c\n//\n//  Source file for Device-Independent Bitmap (DIB) API.  Provides\n//  the following functions:\n//\n//  CreateDIB()         - Creates new DIB\n//  FindDIBBits()       - Sets pointer to the DIB bits\n//  DIBWidth()          - Gets the width of the DIB\n//  DIBHeight()         - Gets the height of the DIB\n//  PaletteSize()       - Calculates the buffer size required by a palette\n//  DIBNumColors()      - Calculates number of colors in the DIB's color table\n//  CreateDIBPalette()  - Creates a palette from a DIB\n//  DIBToBitmap()       - Creates a bitmap from a DIB\n//  BitmapToDIB()       - Creates a DIB from a bitmap\n//  PalEntriesOnDevice()- Gets the number of palette entries of a device\n//  GetSystemPalette()  - Returns a handle to the current system palette\n//  AllocRoomForDIB()   - Allocates memory for a DIB\n//  ChangeDIBFormat()   - Changes a DIB's BPP and/or compression format\n//  ChangeBitmapFormat()- Changes a bitmap to a DIB with specified BPP and\n//                        compression format\n//\n// Development Team: Mark Bader\n//                   Patrick Schreiber\n//                   Garrett McAuliffe\n//                   Eric Flo\n//                   Tony Claflin\n//\n// Written by Microsoft Product Support Services, Developer Support.\n// COPYRIGHT:\n//\n//   (C) Copyright Microsoft Corp. 1993.  All rights reserved.\n//\n//   You have a royalty-free right to use, modify, reproduce and\n//   distribute the Sample Files (and/or any modified version) in\n//   any way you find useful, provided that you agree that\n//   Microsoft has no warranty obligations or liability for any\n//   Sample Application Files which are modified.\n//\n//**********************************************************************\n#if (0) // ST - 5/8/2019\n/* header files */\n#include <windows.h>\n#include <assert.h>\n#include \"dibapi.h\"\n#include \"dibutil.h\"\n#include <stdio.h>\n\n\n/*************************************************************************\n *\n * CreateDIB()\n *\n * Parameters:\n *\n * DWORD dwWidth    - Width for new bitmap, in pixels\n * DWORD dwHeight   - Height for new bitmap \n * WORD  wBitCount  - Bit Count for new DIB (1, 4, 8, or 24)\n *\n * Return Value:\n *\n * HDIB             - Handle to new DIB\n *\n * Description:\n *\n * This function allocates memory for and initializes a new DIB by\n * filling in the BITMAPINFOHEADER, allocating memory for the color\n * table, and allocating memory for the bitmap bits.  As with all\n * HDIBs, the header, colortable and bits are all in one contiguous\n * memory block.  This function is similar to the CreateBitmap() \n * Windows API.\n *\n * The colortable and bitmap bits are left uninitialized (zeroed) in the\n * returned HDIB.\n *\n *\n * History:   Date      Author              Reason\n *            3/20/92   Mark Bader          Created\n *\n ************************************************************************/\n\nHDIB FAR CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)\n{\n   BITMAPINFOHEADER bi;         // bitmap header\n   LPBITMAPINFOHEADER lpbi;     // pointer to BITMAPINFOHEADER\n   DWORD dwLen;                 // size of memory block\n   HDIB hDIB;\n   DWORD dwBytesPerLine;        // Number of bytes per scanline\n\n\n   // Make sure bits per pixel is valid\n   if (wBitCount <= 1)\n      wBitCount = 1;\n   else if (wBitCount <= 4)\n      wBitCount = 4;\n   else if (wBitCount <= 8)\n      wBitCount = 8;\n   else if (wBitCount <= 24)\n      wBitCount = 24;\n   else\n      wBitCount = 4;  // set default value to 4 if parameter is bogus\n\n   // initialize BITMAPINFOHEADER\n   bi.biSize = sizeof(BITMAPINFOHEADER);\n   bi.biWidth = dwWidth;         // fill in width from parameter\n   bi.biHeight = dwHeight;       // fill in height from parameter\n   bi.biPlanes = 1;              // must be 1\n   bi.biBitCount = wBitCount;    // from parameter\n   bi.biCompression = BI_RGB;    \n   bi.biSizeImage = 0;           // 0's here mean \"default\"\n   bi.biXPelsPerMeter = 0;\n   bi.biYPelsPerMeter = 0;\n   bi.biClrUsed = 0;\n   bi.biClrImportant = 0;\n\n   // calculate size of memory block required to store the DIB.  This\n   // block should be big enough to hold the BITMAPINFOHEADER, the color\n   // table, and the bits\n\n   dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);\n\n   // alloc memory block to store our bitmap\n   hDIB = GlobalAlloc(GHND, dwLen);\n\n   // major bummer if we couldn't get memory block\n   if (!hDIB)\n   {\n      return NULL;\n   }\n\n   // lock memory and get pointer to it\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n   // use our bitmap info structure to fill in first part of\n   // our DIB with the BITMAPINFOHEADER\n   *lpbi = bi;\n\n   // Since we don't know what the colortable and bits should contain,\n   // just leave these blank.  Unlock the DIB and return the HDIB.\n\n   GlobalUnlock(hDIB);\n\n   /* return handle to the DIB */\n   return hDIB;\n}\n\n\n\n/*************************************************************************\n *\n * FindDIBBits()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * LPSTR            - pointer to the DIB bits\n *\n * Description:\n *\n * This function calculates the address of the DIB's bits and returns a\n * pointer to the DIB bits.\n *\n * History:   Date      Author              Reason\n *            6/01/91   Garrett McAuliffe   Created\n *            9/15/91   Patrick Schreiber   Added header and comments\n *\n ************************************************************************/\n\n\nLPSTR FAR FindDIBBits(LPCSTR lpDIB)\n{\n   return (LPSTR)(lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));\n}\n\n\n/*************************************************************************\n *\n * DIBWidth()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * DWORD            - width of the DIB\n *\n * Description:\n *\n * This function gets the width of the DIB from the BITMAPINFOHEADER\n * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER\n * width field if it is an OS/2-style DIB.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nDWORD FAR DIBWidth(LPCSTR lpDIB)\n{\n   LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB\n   LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB\n\n   /* point to the header (whether Win 3.0 and OS/2) */\n\n   lpbmi = (LPBITMAPINFOHEADER)lpDIB;\n   lpbmc = (LPBITMAPCOREHEADER)lpDIB;\n\n   /* return the DIB width if it is a Win 3.0 DIB */\n   if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))\n      return lpbmi->biWidth;\n   else  /* it is an OS/2 DIB, so return its width */\n      return (DWORD)lpbmc->bcWidth;\n}\n\n\n/*************************************************************************\n *\n * DIBHeight()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * DWORD            - height of the DIB\n *\n * Description:\n *\n * This function gets the height of the DIB from the BITMAPINFOHEADER\n * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER\n * height field if it is an OS/2-style DIB.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nDWORD FAR DIBHeight(LPCSTR lpDIB)\n{\n   LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB\n   LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB\n\n   /* point to the header (whether OS/2 or Win 3.0 */\n\n   lpbmi = (LPBITMAPINFOHEADER)lpDIB;\n   lpbmc = (LPBITMAPCOREHEADER)lpDIB;\n\n   /* return the DIB height if it is a Win 3.0 DIB */\n   if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))\n      return lpbmi->biHeight;\n   else  /* it is an OS/2 DIB, so return its height */\n      return (DWORD)lpbmc->bcHeight;\n}\n\n\n/*************************************************************************\n *\n * PaletteSize()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * WORD             - size of the color palette of the DIB\n *\n * Description:\n *\n * This function gets the size required to store the DIB's palette by\n * multiplying the number of colors by the size of an RGBQUAD (for a\n * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-\n * style DIB).\n *\n * History:   Date      Author             Reason\n *            6/01/91   Garrett McAuliffe  Created\n *            9/15/91   Patrick Schreiber  Added header and comments\n *\n ************************************************************************/\n\n\nWORD FAR PaletteSize(LPCSTR lpDIB)\n{\n   /* calculate the size required by the palette */\n   if (IS_WIN30_DIB (lpDIB))\n      return (WORD FAR)(DIBNumColors(lpDIB) * sizeof(RGBQUAD));\n   else\n      return (WORD FAR)(DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));\n}\n\n\n/*************************************************************************\n *\n * DIBNumColors()\n *\n * Parameter:\n *\n * LPSTR lpDIB      - pointer to packed-DIB memory block\n *\n * Return Value:\n *\n * WORD             - number of colors in the color table\n *\n * Description:\n *\n * This function calculates the number of colors in the DIB's color table\n * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style\n * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,\n * if 24, no colors in color table.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nWORD FAR DIBNumColors(LPCSTR lpDIB)\n{\n   WORD wBitCount;  // DIB bit count\n\n   /*  If this is a Windows-style DIB, the number of colors in the\n    *  color table can be less than the number of bits per pixel\n    *  allows for (i.e. lpbi->biClrUsed can be set to some value).\n    *  If this is the case, return the appropriate value.\n    */\n\n   if (IS_WIN30_DIB(lpDIB))\n   {\n      DWORD dwClrUsed;\n\n      dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;\n      if (dwClrUsed)\n     return (WORD)dwClrUsed;\n   }\n\n   /*  Calculate the number of colors in the color table based on\n    *  the number of bits per pixel for the DIB.\n    */\n   if (IS_WIN30_DIB(lpDIB))\n      wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;\n   else\n      wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;\n\n   /* return number of colors based on bits per pixel */\n   switch (wBitCount)\n      {\n   case 1:\n      return 2;\n\n   case 4:\n      return 16;\n\n   case 8:\n      return 256;\n\n   default:\n      return 0;\n      }\n}\n\n\n/*************************************************************************\n *\n * CreateDIBPalette()\n *\n * Parameter:\n *\n * HDIB hDIB        - specifies the DIB\n *\n * Return Value:\n *\n * HPALETTE         - specifies the palette\n *\n * Description:\n *\n * This function creates a palette from a DIB by allocating memory for the\n * logical palette, reading and storing the colors from the DIB's color table\n * into the logical palette, creating a palette from this logical palette,\n * and then returning the palette's handle. This allows the DIB to be\n * displayed using the best possible colors (important for DIBs with 256 or\n * more colors).\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nHPALETTE FAR CreateDIBPalette(HDIB hDIB)\n{\n   LPLOGPALETTE lpPal;      // pointer to a logical palette\n   HANDLE hLogPal;          // handle to a logical palette\n   HPALETTE hPal = NULL;    // handle to a palette\n   int i, wNumColors;       // loop index, number of colors in color table\n   LPSTR lpbi;              // pointer to packed-DIB\n   LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)\n   LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (OS/2)\n   BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB\n\n   /* if handle to DIB is invalid, return NULL */\n\n   if (!hDIB)\n      return NULL;\n\n   /* lock DIB memory block and get a pointer to it */\n   lpbi = (LPSTR)GlobalLock(hDIB);\n\n   /* get pointer to BITMAPINFO (Win 3.0) */\n   lpbmi = (LPBITMAPINFO)lpbi;\n\n   /* get pointer to BITMAPCOREINFO (OS/2 1.x) */\n   lpbmc = (LPBITMAPCOREINFO)lpbi;\n\n   /* get the number of colors in the DIB */\n   wNumColors = DIBNumColors(lpbi);\n\n   /* is this a Win 3.0 DIB? */\n   bWinStyleDIB = IS_WIN30_DIB(lpbi);\n   if (wNumColors)\n   {\n      /* allocate memory block for logical palette */\n      hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) *\n                wNumColors);\n\n      /* if not enough memory, clean up and return NULL */\n      if (!hLogPal)\n      {\n     GlobalUnlock(hDIB);\n     return NULL;\n      }\n\n      /* lock memory block and get pointer to it */\n      lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);\n\n      /* set version and number of palette entries */\n      lpPal->palVersion = PALVERSION;\n      lpPal->palNumEntries = (WORD)wNumColors;\n\n      /*  store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)\n       *  into palette\n       */\n      for (i = 0; i < wNumColors; i++)\n      {\n     if (bWinStyleDIB)\n     {\n        lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;\n        lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;\n        lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;\n        lpPal->palPalEntry[i].peFlags = 0;\n     }\n     else\n     {\n        lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;\n        lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;\n        lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;\n        lpPal->palPalEntry[i].peFlags = 0;\n     }\n      }\n\n      /* create the palette and get handle to it */\n      hPal = CreatePalette(lpPal);\n\n      /* if error getting handle to palette, clean up and return NULL */\n      if (!hPal)\n      {\n     GlobalUnlock(hLogPal);\n     GlobalFree(hLogPal);\n     return NULL;\n      }\n   }\n\n   /* clean up */\n   GlobalUnlock(hLogPal);\n   GlobalFree(hLogPal);\n   GlobalUnlock(hDIB);\n\n   /* return handle to DIB's palette */\n   return hPal;\n}\n\n\n/*************************************************************************\n *\n * DIBToBitmap()\n *\n * Parameters:\n *\n * HDIB hDIB        - specifies the DIB to convert\n *\n * HPALETTE hPal    - specifies the palette to use with the bitmap\n *\n * Return Value:\n *\n * HBITMAP          - identifies the device-dependent bitmap\n *\n * Description:\n *\n * This function creates a bitmap from a DIB using the specified palette.\n * If no palette is specified, default is used.\n *\n * NOTE:\n *\n * The bitmap returned from this funciton is always a bitmap compatible\n * with the screen (e.g. same bits/pixel and color planes) rather than\n * a bitmap with the same attributes as the DIB.  This behavior is by\n * design, and occurs because this function calls CreateDIBitmap to\n * do its work, and CreateDIBitmap always creates a bitmap compatible\n * with the hDC parameter passed in (because it in turn calls\n * CreateCompatibleBitmap).\n *\n * So for instance, if your DIB is a monochrome DIB and you call this\n * function, you will not get back a monochrome HBITMAP -- you will\n * get an HBITMAP compatible with the screen DC, but with only 2\n * colors used in the bitmap.\n *\n * If your application requires a monochrome HBITMAP returned for a\n * monochrome DIB, use the function SetDIBits().\n *\n * Also, the DIBpassed in to the function is not destroyed on exit. This\n * must be done later, once it is no longer needed.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *            3/27/92   Mark Bader           Added comments about resulting\n *                                           bitmap format\n *\n ************************************************************************/\n\n\nHBITMAP FAR DIBToBitmap(HDIB hDIB, HPALETTE hPal)\n{\n   LPSTR lpDIBHdr, lpDIBBits;  // pointer to DIB header, pointer to DIB bits\n   HBITMAP hBitmap;            // handle to device-dependent bitmap\n   HDC hDC;                    // handle to DC\n   HPALETTE hOldPal = NULL;    // handle to a palette\n\n   /* if invalid handle, return NULL */\n\n   if (!hDIB)\n      return NULL;\n\n   /* lock memory block and get a pointer to it */\n   lpDIBHdr = (LPSTR)GlobalLock(hDIB);\n\n   /* get a pointer to the DIB bits */\n   lpDIBBits = FindDIBBits(lpDIBHdr);\n\n   /* get a DC */\n   hDC = GetDC(NULL);\n   if (!hDC)\n   {\n      /* clean up and return NULL */\n      GlobalUnlock(hDIB);\n      return NULL;\n   }\n\n   /* select and realize palette */\n   if (hPal)\n      hOldPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* create bitmap from DIB info. and bits */\n   hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT,\n                lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);\n\n   /* restore previous palette */\n   if (hOldPal)\n      SelectPalette(hDC, hOldPal, FALSE);\n\n   /* clean up */\n   ReleaseDC(NULL, hDC);\n   GlobalUnlock(hDIB);\n\n   /* return handle to the bitmap */\n   return hBitmap;\n}\n\n\n/*************************************************************************\n *\n * BitmapToDIB()\n *\n * Parameters:\n *\n * HBITMAP hBitmap  - specifies the bitmap to convert\n *\n * HPALETTE hPal    - specifies the palette to use with the bitmap\n *\n * Return Value:\n *\n * HDIB             - identifies the device-dependent bitmap\n *\n * Description:\n *\n * This function creates a DIB from a bitmap using the specified palette.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *            12/10/91  Patrick Schreiber    Added bits per pixel validation\n *                                           and check GetObject return value\n *\n ************************************************************************/\n\n\nHDIB FAR BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)\n{\n   BITMAP bm;                   // bitmap structure\n   BITMAPINFOHEADER bi;         // bitmap header\n   BITMAPINFOHEADER FAR *lpbi;  // pointer to BITMAPINFOHEADER\n   DWORD dwLen;                 // size of memory block\n   HANDLE hDIB, h;              // handle to DIB, temp handle\n   HDC hDC;                     // handle to DC\n   WORD biBits;                 // bits per pixel\n\n   /* check if bitmap handle is valid */\n\n   if (!hBitmap)\n      return NULL;\n\n   /* fill in BITMAP structure, return NULL if it didn't work */\n   if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))\n      return NULL;\n\n   /* if no palette is specified, use default palette */\n   if (hPal == NULL)\n      hPal = GetStockObject(DEFAULT_PALETTE);\n\n   /* calculate bits per pixel */\n   biBits = (WORD)( bm.bmPlanes * bm.bmBitsPixel );\n\n   /* make sure bits per pixel is valid */\n   if (biBits <= 1)\n      biBits = 1;\n   else if (biBits <= 4)\n      biBits = 4;\n   else if (biBits <= 8)\n      biBits = 8;\n   else /* if greater than 8-bit, force to 24-bit */\n      biBits = 24;\n\n   /* initialize BITMAPINFOHEADER */\n   bi.biSize = sizeof(BITMAPINFOHEADER);\n   bi.biWidth = bm.bmWidth;\n   bi.biHeight = bm.bmHeight;\n   bi.biPlanes = 1;\n   bi.biBitCount = biBits;\n   bi.biCompression = BI_RGB;\n   bi.biSizeImage = 0;\n   bi.biXPelsPerMeter = 0;\n   bi.biYPelsPerMeter = 0;\n   bi.biClrUsed = 0;\n   bi.biClrImportant = 0;\n\n   /* calculate size of memory block required to store BITMAPINFO */\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi);\n\n   /* get a DC */\n   hDC = GetDC(NULL);\n\n   /* select and realize our palette */\n   hPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* alloc memory block to store our bitmap */\n   hDIB = GlobalAlloc(GHND, dwLen);\n\n   /* if we couldn't get memory block */\n   if (!hDIB)\n   {\n      /* clean up and return NULL */\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n\n   /* lock memory and get pointer to it */\n   lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB);\n\n   /* use our bitmap info. to fill BITMAPINFOHEADER */\n   *lpbi = bi;\n\n   /*  call GetDIBits with a NULL lpBits param, so it will calculate the\n    *  biSizeImage field for us\n    */\n   GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,\n         DIB_RGB_COLORS);\n\n   /* get the info. returned by GetDIBits and unlock memory block */\n   bi = *lpbi;\n   GlobalUnlock(hDIB);\n\n   /* if the driver did not fill in the biSizeImage field, make one up */\n   if (bi.biSizeImage == 0)\n      bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;\n\n   /* realloc the buffer big enough to hold all the bits */\n   dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;\n   h = GlobalReAlloc(hDIB, dwLen, 0);\n   if (h)\n      hDIB = h;\n   else\n   {\n      /* clean up and return NULL */\n      GlobalFree(hDIB);\n      hDIB = NULL;\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n\n   /* lock memory block and get pointer to it */\n   lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB);\n\n   /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the\n    *  bits this time\n    */\n   if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi\n         ->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,\n         DIB_RGB_COLORS) == 0)\n   {\n      /* clean up and return NULL */\n      GlobalUnlock(hDIB);\n      hDIB = NULL;\n      SelectPalette(hDC, hPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n      return NULL;\n   }\n   bi = *lpbi;\n\n   /* clean up */\n   GlobalUnlock(hDIB);\n   SelectPalette(hDC, hPal, TRUE);\n   RealizePalette(hDC);\n   ReleaseDC(NULL, hDC);\n\n   /* return handle to the DIB */\n   return hDIB;\n}\n\n\n/*************************************************************************\n *\n * PalEntriesOnDevice()\n *\n * Parameter:\n *\n * HDC hDC          - device context\n *\n * Return Value:\n *\n * int              - number of palette entries on device\n *\n * Description:\n *\n * This function gets the number of palette entries on the specified device\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            9/15/91   Patrick Schreiber    Added header and comments\n *\n ************************************************************************/\n\n\nint FAR PalEntriesOnDevice(HDC hDC)\n{\n   int nColors;  // number of colors\n\n   /*  Find out the number of palette entries on this\n    *  device.\n    */\n\n   nColors = GetDeviceCaps(hDC, SIZEPALETTE);\n\n   /*  For non-palette devices, we'll use the # of system\n    *  colors for our palette size.\n    */\n   if (!nColors)\n      nColors = GetDeviceCaps(hDC, NUMCOLORS);\n   assert(nColors);\n   return nColors;\n}\n\n\n/*************************************************************************\n *\n * GetSystemPalette()\n *\n * Parameters:\n *\n * None\n *\n * Return Value:\n *\n * HPALETTE         - handle to a copy of the current system palette\n *\n * Description:\n *\n * This function returns a handle to a palette which represents the system\n * palette.  The system RGB values are copied into our logical palette using\n * the GetSystemPaletteEntries function.  \n *\n * History:   \n *            \n *    Date      Author               Reason        \n *    6/01/91   Garrett McAuliffe    Created        \n *    9/15/91   Patrick Schreiber    Added header and comments\n *    12/20/91  Mark Bader           Added GetSystemPaletteEntries call\n *\n ************************************************************************/\n\n\nHPALETTE FAR GetSystemPalette(void)\n{\n   HDC hDC;                // handle to a DC\n   static HPALETTE hPal = NULL;   // handle to a palette\n   HANDLE hLogPal;         // handle to a logical palette\n   LPLOGPALETTE lpLogPal;  // pointer to a logical palette\n   int nColors;            // number of colors\n\n   /* Find out how many palette entries we want. */\n\n   hDC = GetDC(NULL);\n   if (!hDC)\n      return NULL;\n   nColors = PalEntriesOnDevice(hDC);   // Number of palette entries\n\n   /* Allocate room for the palette and lock it. */\n   hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * sizeof(\n             PALETTEENTRY));\n\n   /* if we didn't get a logical palette, return NULL */\n   if (!hLogPal)\n      return NULL;\n\n   /* get a pointer to the logical palette */\n   lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);\n\n   /* set some important fields */\n   lpLogPal->palVersion = (WORD)PALVERSION;\n   lpLogPal->palNumEntries = (WORD)nColors;\n\n   /* Copy the current system palette into our logical palette */\n\n   GetSystemPaletteEntries(hDC, 0, nColors, \n                           (LPPALETTEENTRY)(lpLogPal->palPalEntry));\n\n   /*  Go ahead and create the palette.  Once it's created,\n    *  we no longer need the LOGPALETTE, so free it.\n    */\n\n   hPal = CreatePalette(lpLogPal);\n\n   /* clean up */\n   GlobalUnlock(hLogPal);\n   GlobalFree(hLogPal);\n   ReleaseDC(NULL, hDC);\n\n   return hPal;\n}\n\n\n/*************************************************************************\n *\n * AllocRoomForDIB()\n *\n * Parameters:\n *\n * BITMAPINFOHEADER - bitmap info header stucture\n *\n * HBITMAP          - handle to the bitmap\n *\n * Return Value:\n *\n * HDIB             - handle to memory block\n *\n * Description:\n *\n *  This routine takes a BITMAPINOHEADER, and returns a handle to global\n *  memory which can contain a DIB with that header.  It also initializes\n *  the header portion of the global memory.  GetDIBits() is used to determine\n *  the amount of room for the DIB's bits.  The total amount of memory\n *  needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.\n *\n * History:   Date      Author               Reason\n *            6/01/91   Garrett McAuliffe    Created\n *            12/11/91  Patrick Schreiber    Added header and some comments\n *\n ************************************************************************/\n\nHANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)\n{\n   DWORD              dwLen;\n   HANDLE             hDIB;\n   HDC                hDC;\n   LPBITMAPINFOHEADER lpbi;\n   HANDLE             hTemp;\n\n   /* Figure out the size needed to hold the BITMAPINFO structure\n    * (which includes the BITMAPINFOHEADER and the color table).\n    */\n\n   dwLen = bi.biSize + PaletteSize((LPSTR) &bi);\n   hDIB  = GlobalAlloc(GHND,dwLen);\n\n   /* Check that DIB handle is valid */\n   if (!hDIB)\n      return NULL;\n\n   /* Set up the BITMAPINFOHEADER in the newly allocated global memory,\n    * then call GetDIBits() with lpBits = NULL to have it fill in the\n    * biSizeImage field for us.\n    */\n   lpbi  = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   *lpbi = bi;\n\n   hDC   = GetDC(NULL);\n   GetDIBits(hDC, hBitmap, 0, (WORD) bi.biHeight,\n          NULL, (LPBITMAPINFO) lpbi, DIB_RGB_COLORS);\n   ReleaseDC(NULL, hDC);\n\n   /* If the driver did not fill in the biSizeImage field,\n    * fill it in -- NOTE: this is a bug in the driver!\n    */\n   if (lpbi->biSizeImage == 0)\n      lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount) *\n              lpbi->biHeight;\n\n   /* Get the size of the memory block we need */\n   dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;\n\n   /* Unlock the memory block */\n   GlobalUnlock(hDIB);\n\n   /* ReAlloc the buffer big enough to hold all the bits */\n   hTemp = GlobalReAlloc(hDIB,dwLen,0);\n   if (hTemp)\n      return hTemp;\n   else\n      {\n      /* Else free memory block and return failure */\n      GlobalFree(hDIB);\n      return NULL;\n      }\n}\n\n\n/*************************************************************************\n *\n * ChangeDIBFormat()\n *\n * Parameter:\n *\n * HDIB             - handle to packed-DIB in memory\n *\n * WORD             - desired bits per pixel\n *\n * DWORD            - desired compression format\n *\n * Return Value:\n *\n * HDIB             - handle to the new DIB if successful, else NULL\n *\n * Description:\n *\n * This function will convert the bits per pixel and/or the compression\n * format of the specified DIB. Note: If the conversion was unsuccessful,\n * we return NULL. The original DIB is left alone. Don't use code like the\n * following:\n *\n *    hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);\n *\n * The conversion will fail, but hMyDIB will now be NULL and the original\n * DIB will now hang around in memory. We could have returned the old\n * DIB, but we wanted to allow the programmer to check whether this\n * conversion succeeded or failed.\n *\n * History:   \n *            \n *   Date      Author             Reason         \n *   6/01/91   Garrett McAuliffe  Created         \n *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8        \n *                                  to converting RGB/RLE to RGB/RLE.         \n *                                  Added wBitCount and dwCompression         \n *                                  parameters. Also added header and         \n *                                  comments.         \n *\n ************************************************************************/\n\nHDIB FAR ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)\n{\n   HDC                hDC;             // Handle to DC\n   HBITMAP            hBitmap;         // Handle to bitmap\n   BITMAP             Bitmap;          // BITMAP data structure\n   BITMAPINFOHEADER   bi;              // Bitmap info header\n   LPBITMAPINFOHEADER lpbi;            // Pointer to bitmap info\n   HDIB               hNewDIB = NULL;  // Handle to new DIB\n   HPALETTE           hPal, hOldPal;   // Handle to palette, prev pal\n   WORD               DIBBPP, NewBPP;  // DIB bits per pixel, new bpp\n   DWORD              DIBComp, NewComp;// DIB compression, new compression\n\n   /* Check for a valid DIB handle */\n   if (!hDIB)\n      return NULL;\n\n   /* Get the old DIB's bits per pixel and compression format */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n   DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;\n   DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;\n   GlobalUnlock(hDIB);\n\n   /* Validate wBitCount and dwCompression\n    * They must match correctly (i.e., BI_RLE4 and 4 BPP or\n    * BI_RLE8 and 8BPP, etc.) or we return failure */\n   if (wBitCount == 0)\n      {\n      NewBPP = DIBBPP;\n      if ((dwCompression == BI_RLE4 && NewBPP == 4) ||\n      (dwCompression == BI_RLE8 && NewBPP == 8) ||\n      (dwCompression == BI_RGB))\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 1 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else if (wBitCount == 4)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE4)\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 8)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE8)\n     NewComp = dwCompression;\n      else\n     return NULL;\n      }\n   else if (wBitCount == 24 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else\n      return NULL;\n\n   /* Save the old DIB's palette */\n   hPal = CreateDIBPalette(hDIB);\n   if (!hPal)\n      return NULL;\n\n   /* Convert old DIB to a bitmap */\n   hBitmap = DIBToBitmap(hDIB, hPal);\n   if (!hBitmap)\n      {\n      DeleteObject(hPal);\n      return NULL;\n      }\n\n   /* Get info about the bitmap */\n   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);\n\n   /* Fill in the BITMAPINFOHEADER appropriately */\n   bi.biSize               = sizeof(BITMAPINFOHEADER);\n   bi.biWidth              = Bitmap.bmWidth;\n   bi.biHeight             = Bitmap.bmHeight;\n   bi.biPlanes             = 1;\n   bi.biBitCount           = NewBPP;\n   bi.biCompression        = NewComp;\n   bi.biSizeImage          = 0;\n   bi.biXPelsPerMeter      = 0;\n   bi.biYPelsPerMeter      = 0;\n   bi.biClrUsed            = 0;\n   bi.biClrImportant       = 0;\n\n   /* Go allocate room for the new DIB */\n   hNewDIB = AllocRoomForDIB(bi, hBitmap);\n   if (!hNewDIB)\n      return NULL;\n\n   /* Get a pointer to the new DIB */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);\n\n   /* Get a DC and select/realize our palette in it */\n   hDC  = GetDC(NULL);\n   hOldPal = SelectPalette(hDC, hPal, FALSE);\n   RealizePalette(hDC);\n\n   /* Call GetDIBits and get the new DIB bits */\n   if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,\n       (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),\n       (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))\n      {\n      GlobalUnlock(hNewDIB);\n      GlobalFree(hNewDIB);\n      hNewDIB = NULL;\n      }\n\n   /* Clean up and return */\n   SelectPalette(hDC, hOldPal, TRUE);\n   RealizePalette(hDC);\n   ReleaseDC(NULL, hDC);\n\n   if (hNewDIB)\n      /* Unlock the new DIB's memory block */\n      GlobalUnlock(hNewDIB);\n\n   DeleteObject(hBitmap);\n   DeleteObject(hPal);\n\n   return hNewDIB;\n}\n\n\n/*************************************************************************\n *\n * ChangeBitmapFormat()\n *\n * Parameter:\n *\n * HBITMAP          - handle to a bitmap\n *\n * WORD             - desired bits per pixel\n *\n * DWORD            - desired compression format\n *\n * HPALETTE         - handle to palette\n *\n * Return Value:\n *\n * HDIB             - handle to the new DIB if successful, else NULL\n *\n * Description:\n *\n * This function will convert a bitmap to the specified bits per pixel\n * and compression format. The bitmap and it's palette will remain\n * after calling this function.\n *\n * History:   \n *            \n *   Date      Author             Reason         \n *   6/01/91   Garrett McAuliffe  Created         \n *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8         \n *                                 to converting RGB/RLE to RGB/RLE.         \n *                                 Added wBitCount and dwCompression         \n *                                 parameters. Also added header and         \n *                                 comments.         \n *   12/11/91  Patrick Schreiber  Destroy old DIB if conversion was         \n *                                 successful.         \n *   12/16/91  Patrick Schreiber  Modified from converting DIB to new         \n *                                 DIB to bitmap to new DIB. Added palette\n *                                 parameter.\n *\n ************************************************************************/\n\nHDIB FAR ChangeBitmapFormat(HBITMAP  hBitmap,\n            WORD     wBitCount,\n            DWORD    dwCompression,\n            HPALETTE hPal)\n{\n   HDC                hDC;          // Screen DC\n   HDIB               hNewDIB=NULL; // Handle to new DIB\n   BITMAP             Bitmap;       // BITMAP data structure\n   BITMAPINFOHEADER   bi;           // Bitmap info. header\n   LPBITMAPINFOHEADER lpbi;         // Pointer to bitmap header\n   HPALETTE           hOldPal=NULL; // Handle to palette\n   WORD               NewBPP;       // New bits per pixel\n   DWORD              NewComp;      // New compression format\n\n   /* Check for a valid bitmap handle */\n   if (!hBitmap)\n      return NULL;\n\n   /* Validate wBitCount and dwCompression\n    * They must match correctly (i.e., BI_RLE4 and 4 BPP or\n    * BI_RLE8 and 8BPP, etc.) or we return failure\n    */\n   if (wBitCount == 0)\n      {\n      NewComp = dwCompression;\n      if (NewComp == BI_RLE4)\n     NewBPP = 4;\n      else if (NewComp == BI_RLE8)\n     NewBPP = 8;\n      else /* Not enough info */\n     return NULL;\n      }\n   else if (wBitCount == 1 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else if (wBitCount == 4)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE4)\n         NewComp = dwCompression;\n      else\n         return NULL;\n      }\n   else if (wBitCount == 8)\n      {\n      NewBPP = wBitCount;\n      if (dwCompression == BI_RGB || dwCompression == BI_RLE8)\n         NewComp = dwCompression;\n      else\n         return NULL;\n      }\n   else if (wBitCount == 24 && dwCompression == BI_RGB)\n      {\n      NewBPP = wBitCount;\n      NewComp = BI_RGB;\n      }\n   else\n      return NULL;\n\n   /* Get info about the bitmap */\n   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);\n\n   /* Fill in the BITMAPINFOHEADER appropriately */\n   bi.biSize               = sizeof(BITMAPINFOHEADER);\n   bi.biWidth              = Bitmap.bmWidth;\n   bi.biHeight             = Bitmap.bmHeight;\n   bi.biPlanes             = 1;\n   bi.biBitCount           = NewBPP;\n   bi.biCompression        = NewComp;\n   bi.biSizeImage          = 0;\n   bi.biXPelsPerMeter      = 0;\n   bi.biYPelsPerMeter      = 0;\n   bi.biClrUsed            = 0;\n   bi.biClrImportant       = 0;\n\n   /* Go allocate room for the new DIB */\n   hNewDIB = AllocRoomForDIB(bi, hBitmap);\n   if (!hNewDIB)\n      return NULL;\n\n   /* Get a pointer to the new DIB */\n   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);\n\n   /* If we have a palette, get a DC and select/realize it */\n   if (hPal)\n   {\n      hDC  = GetDC(NULL);\n      hOldPal = SelectPalette(hDC, hPal, FALSE);\n      RealizePalette(hDC);\n   }\n\n   /* Call GetDIBits and get the new DIB bits */\n   if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,\n       (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),\n       (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))\n      {\n      GlobalUnlock(hNewDIB);\n      GlobalFree(hNewDIB);\n      hNewDIB = NULL;\n      }\n\n   /* Clean up and return */\n   if (hOldPal)\n   {\n      SelectPalette(hDC, hOldPal, TRUE);\n      RealizePalette(hDC);\n      ReleaseDC(NULL, hDC);\n   }\n\n   if (hNewDIB)\n      {\n      /* Unlock the new DIB's memory block */\n      GlobalUnlock(hNewDIB);\n      }\n\n   return hNewDIB;\n}\n#endif"
  },
  {
    "path": "REDALERT/DIBUTIL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/*\n *  dibutil.h\n *\n *  Copyright (c) 1991 Microsoft Corporation. All rights reserved.\n *\n *  Header file for Device-Independent Bitmap (DIB) API.  Provides\n *  function prototypes and constants for the following functions:\n *\n *  AllocRoomForDIB()   - Allocates memory for a DIB\n *\n */\n\n\n/* DIB constants */\n#define PALVERSION   0x300\n\n/* DIB macros */\n#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))\n#define RECTWIDTH(lpRect)     ((lpRect)->right - (lpRect)->left)\n#define RECTHEIGHT(lpRect)    ((lpRect)->bottom - (lpRect)->top)\n\n/* function prototypes */\nHANDLE          AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap);\n"
  },
  {
    "path": "REDALERT/DISPLAY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DISPLAY.CPP 3     3/09/97 8:04p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DISPLAY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 20, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords.          *\n *   DisplayClass::AI -- Handles the maintenance tasks for the map display.                    *\n *   DisplayClass::All_To_Look -- Direct all objects to look around for the player.            *\n *   DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method.              *\n *   DisplayClass::Cell_Object -- Determines what has been clicked on.                         *\n *   DisplayClass::Cell_Shadow   -- Determine what shadow icon to use for the cell.            *\n *   DisplayClass::Center_Map -- Centers the map about the currently selected objects          *\n *   DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y.                       *\n *   DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free.          *\n *   DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates.                     *\n *   DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits.                  *\n *   DisplayClass::DisplayClass -- Default constructor for display class.                      *\n *   DisplayClass::Draw_It -- Draws the tactical map.                                          *\n *   DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell.             *\n *   DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn.                         *\n *   DisplayClass::Flag_To_Redraw -- Flags the display so that it will be redrawn as soon as poss*\n *   DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list   *\n *   DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality.           *\n *   DisplayClass::In_View -- Determines if cell is visible on screen.                         *\n *   DisplayClass::Init_Clear -- Clears the display to a known state.                          *\n *   DisplayClass::Init_IO -- Creates the map's button list                                    *\n *   DisplayClass::Init_Theater -- Theater-specific initialization                             *\n *   DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation.          *\n *   DisplayClass::Map_Cell -- Mark specified cell as having been mapped.                      *\n *   DisplayClass::Mouse_Left_Held -- Handles the left button held down.                       *\n *   DisplayClass::Mouse_Left_Press -- Handles the left mouse button press.                    *\n *   DisplayClass::Mouse_Left_Release -- Handles the left mouse button release.                *\n *   DisplayClass::Mouse_Left_Up -- Handles the left mouse \"cruising\" over the map.            *\n *   DisplayClass::Mouse_Right_Press -- Handles the right mouse button press.                  *\n *   DisplayClass::Next_Object -- Searches for next object on display.                         *\n *   DisplayClass::One_Time -- Performs any special one time initializations.                  *\n *   DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*\n *   DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE                       *\n *   DisplayClass::Prev_Object -- Searches for the previous object on the map.                 *\n *   DisplayClass::Read_INI -- Reads map control data from INI file.                           *\n *   DisplayClass::Redraw_Icons -- Draws all terrain icons necessary.                          *\n *   DisplayClass::Redraw_Shadow -- Draw the shadow overlay.                                   *\n *   DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn.       *\n *   DisplayClass::Refresh_Cells -- Redraws all cells in list.                                 *\n *   DisplayClass::Remove -- Removes a game object from the rendering system.                  *\n *   DisplayClass::Repair_Mode_Control -- Controls the repair mode.                            *\n *   DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction.                 *\n *   DisplayClass::Select_These -- All selectable objects in region are selected.              *\n *   DisplayClass::Sell_Mode_Control -- Controls the sell mode.                                *\n *   DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor.     *\n *   DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor.         *\n *   DisplayClass::Set_Tactical_Position -- Sets the tactical view position.                   *\n *   DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates.        *\n *   DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition.      *\n *   DisplayClass::Submit -- Adds a game object to the map rendering system.                   *\n *   DisplayClass::TacticalClass::Action -- Processes input for the tactical map.              *\n *   DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string.   *\n *   DisplayClass::Write_INI -- Write the map data to the INI file specified.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n/*\n**\tThese layer control elements are used to group the displayable objects\n**\tso that proper overlap can be obtained.\n*/\nLayerClass DisplayClass::Layer[LAYER_COUNT];\n\n/*\n** Fading tables\n*/\nunsigned char DisplayClass::FadingBrighten[256];\nunsigned char DisplayClass::FadingShade[256];\nunsigned char DisplayClass::FadingWayDark[256];\nunsigned char DisplayClass::FadingLight[256];\nunsigned char DisplayClass::FadingGreen[256];\nunsigned char DisplayClass::FadingYellow[256];\nunsigned char DisplayClass::FadingRed[256];\nunsigned char DisplayClass::TranslucentTable[(MAGIC_COL_COUNT+1)*256];\nunsigned char DisplayClass::WhiteTranslucentTable[(1+1)*256];\nunsigned char DisplayClass::MouseTranslucentTable[(4+1)*256];\nvoid const * DisplayClass::TransIconset;\nunsigned char DisplayClass::UnitShadow[(USHADOW_COL_COUNT+1)*256];\nunsigned char DisplayClass::UnitShadowAir[(USHADOW_COL_COUNT+1)*256];\nunsigned char DisplayClass::SpecialGhost[2*256];\n\nvoid const * DisplayClass::ShadowShapes;\nunsigned char DisplayClass::ShadowTrans[(SHADOW_COL_COUNT+1)*256];\n\n/*\n** Bit array of cell redraw flags\n*/\nBooleanVectorClass DisplayClass::CellRedraw;\n\n/*\n** The main button that intercepts user input to the map\n*/\nDisplayClass::TacticalClass DisplayClass::TacButton;\n\n//\n// We need a way to bypass visible view checks when we are running in the context of GlyphX without using the\n// internal C&C renderer. We shouldn't know or care what the user is actually looking at\n// ST - 4/17/2019 9:01AM\n//\nbool DisplayClass::IgnoreViewConstraints = false;\n\n\nstatic int const TEX_X = 0;\nstatic int const TEX_Y = 6;\nstatic int const TEX_W = 14;\n\n//Added for getting the input for special character keys from the client \n// - 6/26/2019 JAS \nextern bool DLL_Export_Get_Input_Key_State(KeyNumType key);\n\n\n/***********************************************************************************************\n * DisplayClass::DisplayClass -- Default constructor for display class.                        *\n *                                                                                             *\n *    This constructor for the display class just initializes some of the display settings.    *\n *    Most settings are initialized with the correct values at the time that the Init function *\n *    is called. There are some cases where default values are wise and this routine fills     *\n *    those particular ones in.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nDisplayClass::DisplayClass(void) :\n\tTacticalCoord(0),\n\tTacLeptonWidth(0),\n\tTacLeptonHeight(0),\n\tZoneCell(0),\n\tZoneOffset(0),\n\tCursorSize(0),\n\tProximityCheck(false),\n\tPendingObjectPtr(0),\n\tPendingObject(0),\n\tPendingHouse(HOUSE_NONE),\n\tTacPixelX(0),\n\tTacPixelY(0),\n\tDesiredTacticalCoord(0),\n\tIsToRedraw(true),\n\tIsRepairMode(false),\n\tIsSellMode(false),\n\tIsTargettingMode(SPC_NONE),\n\tIsRubberBand(false),\n\tIsTentative(false),\n\tIsShadowPresent(false),\n\tBandX(0),\n\tBandY(0),\n\tNewX(0),\n\tNewY(0)\n{\n\tShadowShapes = 0;\n\tTransIconset = 0;\n\n\tSet_View_Dimensions(0, 8, 320/CELL_PIXEL_W, 200/CELL_PIXEL_H);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::One_Time -- Performs any special one time initializations.                    *\n *                                                                                             *\n *    This routine is called from the game initialization process. It is to perform any one    *\n *    time initializations necessary for the map display system. It allocates the staging      *\n *    buffer needed for the radar map.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called ONCE and only once.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Handles layer system now.                                                *\n *   06/02/1994 JLB : Takes care of misc display tables and data allocation.                   *\n *=============================================================================================*/\nvoid DisplayClass::One_Time(void)\n{\n\tMapClass::One_Time();\n\n\t/*\n\t** Init the CellRedraw bit array.  Do not do this in the constructor, since the\n\t** BooleanVector may not have been constructed yet.\n\t*/\n\tCellRedraw.Resize(MAP_CELL_TOTAL);\n\n\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\tLayer[layer].One_Time();\n\t}\n\n\t/*\n\t**\tLoad the generic transparent icon set.\n\t*/\n\tTransIconset = MFCD::Retrieve(\"TRANS.ICN\");\n\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"SHADOW.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tShadowShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tShadowShapes = MFCD::Retrieve(\"SHADOW.SHP\");\n\t\t}\n\t#else\n\t\tShadowShapes = MFCD::Retrieve(\"SHADOW.SHP\");\n\t#endif\n\n\t//PG Set_View_Dimensions(0, 8 * RESFACTOR);\n\tSet_View_Dimensions(0, 0);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_Clear -- clears the display to a known state                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Init_Clear(void)\n{\n\tMapClass::Init_Clear();\n\n\t/*\n\t** Clear any object being placed\n\t*/\n\tPendingObjectPtr = 0;\n\tPendingObject = 0;\n\tPendingHouse = HOUSE_NONE;\n\tCursorSize = 0;\n\tIsTargettingMode = SPC_NONE;\n\tIsRepairMode = false;\n\tIsRubberBand = false;\n\tIsTentative = false;\n\tIsSellMode = false;\n\n\t/*\n\t** Empty all the display's layers\n\t*/\n\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\tLayer[layer].Init();\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_IO -- clears & re-builds the map's button list                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Init_IO(void)\n{\n\tMapClass::Init_IO();\n\t/*\n\t** Re-attach our buttons to the main map button list, only in non-edit mode.\n\t*/\n\tif (!Debug_Map) {\n\t\tTacButton.Zap();\n\t\tAdd_A_Button(TacButton);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Init_Theater -- Performs theater-specific initialization (mixfiles, etc)      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      theater         new theater                                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *   05/07/1996 JLB : Added translucent tables.                                                *\n *=============================================================================================*/\nvoid DisplayClass::Init_Theater(TheaterType theater)\n{\n\tchar\t\t\tfullname[16];\n\tstatic TLucentType const MouseCols[4] = {\n\t\t{BLACK, BLACK, 110, 0},\n\t\t{WHITE, WHITE, 110, 0},\n\t\t{LTGREY, LTGREY, 110, 0},\n\t\t{DKGREY, DKGREY, 110, 0}\n\t};\n\tstatic TLucentType const MagicCols[MAGIC_COL_COUNT] = {\n\t\t{32,32,110,0},\n\t\t{33,33,110,0},\n\t\t{34,34,110,0},\n\t\t{35,35,110,0},\n\t\t{36,36,110,0},\n\t\t{37,37,110,0},\n\t\t{38,38,110,0},\n\t\t{39,39,110,0},\n\t\t{BLACK, BLACK, 200, 0},\n\t\t{WHITE, BLACK, 40, 0},\n\t\t{LTGREY, BLACK, 80, 0},\n\t\t{DKGREY, BLACK, 140, 0},\n\t\t{LTGREEN,\tBLACK,130,0}\n\t};\n\tstatic TLucentType const WhiteCols[1] = {\n\t\t{1, WHITE, 80, 0}\n\t};\n\tstatic TLucentType const ShadowCols[SHADOW_COL_COUNT] = {\n\t\t{WHITE+1,\tBLACK,130,0},\n\t\t{WHITE,\t\tBLACK,170,0},\n\t\t{LTGRAY,\t\tBLACK,250,0},\n\t\t{DKGRAY,\t\tBLACK,250,0}\n\t};\n\tstatic TLucentType const UShadowCols[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tBLACK,130,0}\n\t};\n\tstatic TLucentType const UShadowColsAir[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tWHITE,0,0}\n\t};\n\tstatic TLucentType const UShadowColsSnow[USHADOW_COL_COUNT] = {\n\t\t{LTGREEN,\tBLACK,75,0}\n\t};\n\n\t/*\n\t**\tInvoke parent's init routine.\n\t*/\n\tMapClass::Init_Theater(theater);\n\n\t/*\n\t** Save the new theater value\n\t*/\n\tScen.Theater = theater;\n\n\t/*\n\t** Unload old mixfiles, and cache the new ones\n\t*/\n\tsprintf(fullname, \"%s.MIX\", Theaters[theater].Root);\n\n#ifndef WIN32\nLastTheater = THEATER_NONE;\n#endif\n\n\tif (Scen.Theater != LastTheater) {\n\t\tif (TheaterData != NULL) {\n\t\t\tdelete TheaterData;\n\t\t}\n\t\tTheaterData = new MFCD(fullname, &FastKey);\n\t\tassert(TheaterData != NULL);\n\n\t\tbool theaterload = TheaterData->Cache(TheaterBuffer);\n\t\tassert(theaterload);\n//\t\tLastTheater = Scen.Theater;\n\t}\n\n\t/*\n\t**\tLoad the custom palette associated with this theater.\n\t**\tThe fading palettes will have to be generated as well.\n\t*/\n\tsprintf(fullname, \"%s.PAL\", Theaters[theater].Root);\n\tPaletteClass const * ptr = (PaletteClass *)MFCD::Retrieve(fullname);\n\n\tGamePalette = * ptr;\n\n\tOriginalPalette = GamePalette;\n\n\tBuild_Fading_Table(GamePalette.Get_Data(), FadingGreen, GREEN, 110);\n\n\tBuild_Fading_Table(GamePalette.Get_Data(), FadingYellow, YELLOW, 140);\n\n\tBuild_Fading_Table(GamePalette.Get_Data(), FadingRed, RED, 140);\n\n\tBuild_Translucent_Table(GamePalette, &MouseCols[0], 4, MouseTranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &MagicCols[0], MAGIC_COL_COUNT, TranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &WhiteCols[0], 1, WhiteTranslucentTable);\n\n\tBuild_Translucent_Table(GamePalette, &ShadowCols[0], SHADOW_COL_COUNT, ShadowTrans);\n\n\tConquer_Build_Translucent_Table(GamePalette, &UShadowColsAir[0], USHADOW_COL_COUNT, UnitShadowAir);\n\tmemcpy(&UnitShadowAir[256], ColorRemaps[PCOLOR_GOLD].RemapTable, sizeof(ColorRemaps[PCOLOR_GOLD].RemapTable));\n\tif (theater == THEATER_SNOW) {\n\t\tConquer_Build_Translucent_Table(GamePalette, &UShadowColsSnow[0], USHADOW_COL_COUNT, UnitShadow);\n\t} else {\n\t\tConquer_Build_Translucent_Table(GamePalette, &UShadowCols[0], USHADOW_COL_COUNT, UnitShadow);\n\t}\n\n\tif (theater == THEATER_SNOW) {\n\t\tConquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 75);\n\t} else {\n\t\tConquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 130);\n\t}\n\n\tConquer_Build_Fading_Table(GamePalette, FadingLight, WHITE, 85);\n\n\t/*\n\t**\tCreate the shadow color used by aircraft.\n\t*/\n\tConquer_Build_Fading_Table(GamePalette, &SpecialGhost[256], BLACK, 100);\n\tfor (int index = 0; index < 256; index++) {\n\t\tSpecialGhost[index] = 0;\n\t}\n\n\tMake_Fading_Table(GamePalette, FadingBrighten, WHITE, 25);\n\n\tMake_Fading_Table(GamePalette, FadingWayDark, DKGRAY, 192);\n\n\t/*\n\t**\tAdjust the palette according to the visual control option settings.\n\t*/\n\tOptions.Fixup_Palette();\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string.     *\n *                                                                                             *\n *    This routine is used to create an overlap list that specifies all the cells that are     *\n *    covered by the specified text string. This overlap list is used to handle map  refresh   *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that would appear on the map and must have an         *\n *                   overlap list generated.                                                   *\n *                                                                                             *\n *          x,y   -- The coordinates that the text would appear (upper left corner).           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an overlap list that covers all cells \"under\" the text   *\n *          if were displayed at the coordinates specified. The list is actually a series of   *\n *          offsets from the display's upper left corner cell number.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *   12/07/1994 JLB : Sidebar fixup.                                                           *\n *   08/13/1995 JLB : Optimized for variable sized help text.                                  *\n *=============================================================================================*/\nshort const * DisplayClass::Text_Overlap_List(char const * text, int x, int y) const\n{\n\tstatic short _list[60];\n\tint count = ARRAY_SIZE(_list);\n\n\tif (text != NULL) {\n\t\tshort * ptr = &_list[0];\n\t\tint len = String_Pixel_Width(text)+CELL_PIXEL_W;\n\t\tint right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth);\n\n\t\t/*\n\t\t**\tIf the help text would spill into the sidebar, then flag this fact, but\n\t\t**\tshorten the apparent length so that the icon list calculation will\n\t\t**\tfunction correctly.\n\t\t*/\n\t\tif (x+len >= TacPixelX+Lepton_To_Pixel(TacLeptonWidth)) {\n\t\t\tlen = right-x;\n\t\t\t*ptr++ = REFRESH_SIDEBAR;\n\t\t\tcount--;\n\t\t}\n\n\t\t/*\n\t\t**\tBuild the list of overlap cell offset values according to the text\n\t\t**\tcoordinate and the length.\n\t\t*/\n\t\tif (x <= right) {\n\t\t\tCELL ul = Click_Cell_Calc(x, y-1);\n\t\t\tCELL lr = Click_Cell_Calc(x+len-1, Bound(y+24, TacPixelY, TacPixelY+Lepton_To_Pixel(TacLeptonHeight) - 1));\n\n\t\t\tif (ul == -1) ul = Click_Cell_Calc(x, y);\n\n\t\t\tif (ul != -1 && lr != -1) {\n\t\t\t\tfor (int yy = Cell_Y(ul); yy <= Cell_Y(lr); yy++) {\n\t\t\t\t\tfor (int xx = Cell_X(ul); xx <= Cell_X(lr); xx++) {\n\t\t\t\t\t\t*ptr++ = XY_Cell(xx, yy) - Coord_Cell(TacticalCoord);\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t\tif (count < 2) break;\n\t\t\t\t\t}\n\t\t\t\t\tif (count < 2) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t*ptr = REFRESH_EOL;\n\t}\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates.          *\n *                                                                                             *\n *    Use this routine to set the tactical map screen coordinates and dimensions. This routine *\n *    is typically used when the screen size or position changes as a result of the sidebar    *\n *    changing position or appearance.                                                         *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel position on the screen for the tactical map upper left  *\n *                   corner.                                                                   *\n *                                                                                             *\n *          width -- The width of the tactical display (in icons). If this parameter is        *\n *                   omitted, then the width will be as wide as the screen will allow.         *\n *                                                                                             *\n *          height-- The height of the tactical display (in icons). If this parameter is       *\n *                   omitted, then the width will be as wide as the screen will allow.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/06/1994 JLB : Created.                                                                 *\n *   06/27/1995 JLB : Adjusts tactical map position if necessary.                              *\n *=============================================================================================*/\nvoid DisplayClass::Set_View_Dimensions(int x, int y, int width, int height)\n{\n\tif (width == -1) {\n\t\tTacLeptonWidth = Pixel_To_Lepton(SeenBuff.Get_Width()-x);\n\t} else {\n\t\tTacLeptonWidth = width * CELL_LEPTON_W;\n\t}\n\n\t// ST - 3/1/2019 12:05PM\n\t// Made the below code more consistent with the width calculation. This is needed if we aren't going to draw the tabs at the top of the screen\n\t//\n\tif (height == -1) {\n\t\tTacLeptonHeight = Pixel_To_Lepton(SeenBuff.Get_Height() - y);\n\t\t//height = (SeenBuff.Get_Height()-y) / CELL_PIXEL_H;\n\t}\n\telse {\n\t\tTacLeptonHeight = height * CELL_LEPTON_H;\n\t}\n\t//TacLeptonHeight = height * CELL_LEPTON_H;\n\n\t/*\n\t**\tAdjust the tactical cell if it is now in an invalid position\n\t**\tbecause of the changed dimensions.\n\t*/\n\tint xx = 0;// Coord_X(TacticalCoord) - (MapCellX * CELL_LEPTON_W);\n\tint yy = 0;// Coord_Y(TacticalCoord) - (MapCellY * CELL_LEPTON_H);\n\n\tConfine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, MapCellWidth * CELL_LEPTON_W, MapCellHeight * CELL_LEPTON_H);\n\n\tSet_Tactical_Position(XY_Coord(xx + (MapCellX * CELL_LEPTON_W), yy + (MapCellY * CELL_LEPTON_H)));\n\n\tTacPixelX = x;\n\tTacPixelY = y;\n\tWindowList[WINDOW_TACTICAL][WINDOWX] = x;\n\tWindowList[WINDOW_TACTICAL][WINDOWY] = y;\n\tWindowList[WINDOW_TACTICAL][WINDOWWIDTH] = Lepton_To_Pixel(TacLeptonWidth);\n\tWindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = Lepton_To_Pixel(TacLeptonHeight);\n\tif (Window == WINDOW_TACTICAL) {\n\t\tChange_Window(0);\n\t\tChange_Window(Window);\n\t}\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n\n\tTacButton.X = TacPixelX;\n\tTacButton.Y = TacPixelY;\n\tTacButton.Width = Lepton_To_Pixel(TacLeptonWidth);\n\tTacButton.Height = Lepton_To_Pixel(TacLeptonHeight);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor.           *\n *                                                                                             *\n *    This routine is used to set up the terrain cursor according to the size of the object    *\n *    that is to be placed down. The terrain cursor looks like an arbitrary collection of      *\n *    hatched square overlays. Typical use is when placing buildings.                          *\n *                                                                                             *\n * INPUT:   list  -- A pointer to the list that contains offsets to the cells that are to      *\n *                   be marked.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1994 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Puts placement cursor into static buffer.                                *\n *=============================================================================================*/\nvoid DisplayClass::Set_Cursor_Shape(short const * list)\n{\n\tif (CursorSize) {\n\t\tCursor_Mark(ZoneCell+ZoneOffset, false);\n\t}\n\tZoneOffset = 0;\n\n\tif (list) {\n\t\tint\tw,h;\n\t\tstatic short _list[50];\n\n\t\tmemcpy(_list, list, sizeof(_list));\n\t\tCursorSize = _list;\n\t\tGet_Occupy_Dimensions (w, h, CursorSize);\n\t\tZoneOffset = -(((h/2)*MAP_CELL_W)+(w/2));\n\t\tCursor_Mark(ZoneCell+ZoneOffset, true);\n\t} else {\n\t\tCursorSize = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*\n *                                                                                             *\n *    This routine is used by the building placement cursor logic to determine whether the     *\n *    at the current cursor position if the building would be adjacent to another friendly     *\n *    building. In cases where this is not true, then the building cannot be placed at all.    *\n *    This determination is returned by the function.                                          *\n *                                                                                             *\n * INPUT:   object   -- The building object that the current placement system is examining.    *\n *                                                                                             *\n *          house    -- The house to base the proximity check upon. Typically this is the      *\n *                      player's house, but in multiplay, the computer needs to check for      *\n *                      proximity as well.                                                     *\n *                                                                                             *\n *          list     -- Pointer to the building's offset list.                                 *\n *                                                                                             *\n *          trycell  -- The cell to base the offset list on.                                   *\n *                                                                                             *\n * OUTPUT:  bool; Can the pending building object be placed at the present cursor location     *\n *                checking only for proximity to friendly buildings?  If this isn't for a      *\n *                building type object, then this routine always returns true.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/06/1994 JLB : Created.                                                                 *\n *   06/07/1994 JLB : Handles concrete check.                                                  *\n *   10/11/1994 BWG : Added IsProximate check for ore refineries                               *\n *=============================================================================================*/\nbool DisplayClass::Passes_Proximity_Check(ObjectTypeClass const * object, HousesType house, short const * list, CELL trycell) const\n{\n\tshort const * ptr;\n\tint retval = -1;\n\tbool noradar = false;\n\t//bool nomapped = false;\t\t\t    // Not used. ST - 8/6/2019 10:51AM\n\tbool shipyard = false;\n\n\tif (house == PlayerPtr->Class->House) {\n\t\tPassedProximity = false;\n\t}\n\n\t/*\n\t** In editor mode, the proximity check always passes.\n\t*/\n\tif (Debug_Map) {\n\t\treturn(true);\n\t}\n\n\tif (list == NULL || trycell == 0) {\n\t\treturn(true);\n\t}\n\n\tif (object == NULL || object->What_Am_I() != RTTI_BUILDINGTYPE) {\n\t\treturn(true);\n\t}\n\n\tBuildingTypeClass const * building = (BuildingTypeClass const *)object;\n\n\t/*\n\t**\tScan through all cells that the building foundation would cover. If any adjacent\n\t**\tcells to these are of friendly persuasion, then consider the proximity check to\n\t**\thave been a success.\n\t*/\n\tptr = list;\n//\tptr = CursorSize;\n\tCELL cell = trycell;\n//\tCELL cell = ZoneCell;\n\tif (building->Adjacent == 1) {\n\t\twhile (*ptr != REFRESH_EOL && (retval == -1) ) {\n\t\t\tcell = trycell + *ptr++;\n//\t\t\tcell = ZoneCell + ZoneOffset + *ptr++;\n\n\t\t\tif (!In_Radar(cell)) {\n\t\t\t\tretval = false;\n\t\t\t\tnoradar = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (FacingType facing = FACING_FIRST; facing < FACING_COUNT; facing++) {\n\t\t\t\tCELL\tnewcell = Adjacent_Cell(cell, facing);\n\n\t\t\t\tif (!In_Radar(newcell)) continue;\n\n\t\t\t\t// Code has no effect. ST - 8/6/2019 10:51AM\n\t\t\t\t//if (!(*this)[newcell].IsMapped) {\n\t\t\t\t//\tnomapped = true;\n\t\t\t\t//}\n\t\t\t\tBuildingClass * base = (*this)[newcell].Cell_Building();\n\n\t\t\t\t/*\n\t\t\t\t**\tThe special cell ownership flag allows building adjacent\n\t\t\t\t**\tto friendly walls and bibs even though there is no official\n\t\t\t\t**\tbuilding located there.\n\t\t\t\t*/\n\t\t\t\t//BG: Modified so only walls can be placed next to walls - buildings can't.\n\t\t\t\t//JLB: Except for bibs, in which case buildings can be placed next to these.\n\t\t\t\tif (building->IsWall ||\n\t\t\t\t\t((*this)[newcell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newcell].Smudge).IsBib)) {\n\n\t\t\t\t\tif ((*this)[newcell].Owner == house) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// we've found a building...\n\t\t\t\tif (base != NULL && base->House->Class->House == house && base->Class->IsBase) {\n\t\t\t\t\tretval = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/* BG: modifications to allow buildings one cell away from other buildings.\n\t\t\t\t** This is done by scanning each cell that fails the check (hence getting\n\t\t\t\t** to this point) and looking at the n/s/e/w adjacent cells to see if they\n\t\t\t\t** have buildings in them.  If they do, and they match us, then succeed.\n\t\t\t\t*/\n\t\t\t\tif (retval != -1) break;\n\n\t\t\t\tfor (FacingType newface = FACING_N; newface < FACING_COUNT; newface++) {\n\t\t\t\t\tCELL\tnewercell = Adjacent_Cell(newcell, newface);\n\n\t\t\t\t\tif (building->IsWall ||\n\t\t\t\t\t\t\t\t\t((*this)[newercell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newercell].Smudge).IsBib)) {\n\n\t\t\t\t\t\tif ((*this)[newercell].Owner == house) {\n\t\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tTechnoClass * newbase = (*this)[newercell].Cell_Techno();\n\n\t\t\t\t\t// we've found a building...\n\t\t\t\t\tif (newbase != NULL && newbase->What_Am_I() == RTTI_BUILDING && newbase->House->Class->House == house && ((BuildingClass const *)newbase)->Class->IsBase) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (retval != -1) break;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (retval == -1) retval = false;\n\n\tif (house == PlayerPtr->Class->House) {\n\t\tPassedProximity = (retval != false);\n\t}\n\n\t/*\n\t**\tIf this object has special dispensation to be placed further than one cell from\n\t**\tother regular buildings, then check for this case now. Only bother to check if\n\t**\tit hasn't already been given permission to be placed down.\n\t*/\n\tif (!retval && !noradar && object->What_Am_I() == RTTI_BUILDINGTYPE) {\n\n\t\t// For land mines, let's make it check proximity within 10 squares\n\t\tif (building->Adjacent > 1) {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\t\t\tif (obj != NULL && !obj->IsInLimbo && obj->House->Class->House == house && obj->Class->IsBase) {\n\t\t\t\t\tint centdist = ::Distance(obj->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\tcentdist /= CELL_LEPTON_W;\n\t\t\t\t\tcentdist -= (obj->Class->Width() + obj->Class->Height()) / 2;\n\t\t\t\t\tif (centdist <= building->Adjacent) {\n\t\t\t\t\t\tretval = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn((bool)retval);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor.       *\n *                                                                                             *\n *    This routine controls the location, display, and animation of the                        *\n *    tactical map cursor.                                                                     *\n *                                                                                             *\n * INPUT:   pos   -- Position to move the cursor do. If -1 is passed then                      *\n *                   the cursor will just be hidden. If the position                           *\n *                   passed is the same as the last position passed in,                        *\n *                   then animation could occur (based on timers).                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Converted to member function.                                            *\n *   06/08/1994 JLB : If position is -1, then follow mouse.                                    *\n *   02/28/1995 JLB : Forces placement cursor to fit on map.                                   *\n *=============================================================================================*/\nCELL DisplayClass::Set_Cursor_Pos(CELL pos)\n{\n\tCELL\tprevpos;\t\t\t// Last position of cursor (for jump-back reasons).\n\n\t/*\n\t**\tFollow the mouse position if no cell number is provided.\n\t*/\n\tif (pos == -1) {\n\t\tpos = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());\n\t}\n\n\tif (CursorSize == NULL) {\n\t\tprevpos = ZoneCell;\n\t\tZoneCell = pos;\n\t\treturn(prevpos);\n\t}\n\n\t/*\n\t**\tAdjusts the position so that the placement cursor is never part way off the\n\t**\ttactical map.\n\t*/\n\tint w,h;\n\tGet_Occupy_Dimensions(w, h, CursorSize);\n\n\tint x = Cell_X(pos + ZoneOffset);\n\tint y = Cell_Y(pos + ZoneOffset);\n\n\tif (x < Coord_XCell(TacticalCoord)) x = Coord_XCell(TacticalCoord);\n\tif (y < Coord_YCell(TacticalCoord)) y = Coord_YCell(TacticalCoord);\n\tif (x+w >= Coord_XCell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)) x = Coord_XCell(TacticalCoord)+Lepton_To_Cell(TacLeptonWidth)-w;\n\tif (y+h >= Coord_YCell(TacticalCoord) + Lepton_To_Cell(TacLeptonHeight)) y = Coord_YCell(TacticalCoord)+Lepton_To_Cell(TacLeptonHeight)-h;\n\tpos = XY_Cell(x, y) - ZoneOffset;\n\n\t/*\n\t** This checks to see if NO animation or drawing is to occur and, if so,\n\t**\texits.\n\t*/\n\tif (pos == ZoneCell) return(pos);\n\n\tprevpos = ZoneCell;\n\n\t/*\n\t**\tIf the cursor is visible, then handle the graphic update.\n\t**\tOtherwise, just update the global position of the cursor.\n\t*/\n\tif (CursorSize != NULL) {\n\n\t\t/*\n\t\t** Erase the old cursor (if it exists) AND the cursor is moving.\n\t\t*/\n\t\tif (pos != ZoneCell && ZoneCell != -1) {\n\t\t\tCursor_Mark(ZoneCell+ZoneOffset, false);\n\t\t}\n\n\t\t/*\n\t\t** Render the cursor (could just be animation).\n\t\t*/\n\t\tif (pos != -1) {\n\t\t\tCursor_Mark(pos+ZoneOffset, true);\n\t\t}\n\t}\n\tZoneCell = pos;\n\tProximityCheck = Passes_Proximity_Check(PendingObject, PendingHouse, CursorSize, ZoneCell+ZoneOffset);\n\n\treturn(prevpos);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      w      ptr to fill in with height                                                      *\n *      h      ptr to fill in with width                                                       *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/31/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Get_Occupy_Dimensions(int & w, int & h, short const * list) const\n{\n\tint min_x = MAP_CELL_W;\n\tint max_x = -MAP_CELL_W;\n\tint min_y = MAP_CELL_H;\n\tint max_y = -MAP_CELL_H;\n\tint x,y;\n\n\tw = 0;\n\th = 0;\n\n\tif (!list) {\n\t\t/*\n\t\t** Loop through all cell offsets, accumulating max & min x- & y-coords\n\t\t*/\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\t/*\n\t\t\t** Compute x & y coords of the current cell offset.  We can't use Cell_X()\n\t\t\t** & Cell_Y(), because they use shifts to compute the values, and if the\n\t\t\t** offset is negative we'll get a bogus coordinate!\n\t\t\t*/\n\t\t\tx = (*list) % MAP_CELL_W;\n\t\t\ty = (*list) / MAP_CELL_H;\n\n\t\t\tmax_x = max(max_x, x);\n\t\t\tmin_x = min(min_x, x);\n\t\t\tmax_y = max(max_y, y);\n\t\t\tmin_y = min(min_y, y);\n\n\t\t\tlist++;\n\t\t}\n\n\t\tw = max(1, max_x - min_x + 1);\n\t\th = min(1, max_y - min_y + 1);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits.                    *\n *                                                                                             *\n *    This routine will clear or set the cursor display bits on the map.                       *\n *    If the bit is set, then the cursor will be rendered on that map                          *\n *    icon.                                                                                    *\n *                                                                                             *\n * INPUT:   pos   -- Position of the upper left corner of the cursor.                          *\n *                                                                                             *\n *          on    -- Should the bit be turned on?                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that every call to set the bits is matched by a                         *\n *             corresponding call to clear the bits.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1991 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DisplayClass::Cursor_Mark(CELL pos, bool on)\n{\n\tCELL const * ptr;\n\tCellClass * cellptr;\n\n\tif ((unsigned)pos >= MAP_CELL_TOTAL) return;\n\n\t/*\n\t**\tFor every cell in the CursorSize list, invoke its Redraw_Objects and\n\t**\ttoggle its IsCursorHere flag\n\t*/\n\tptr = CursorSize;\n\twhile (*ptr != REFRESH_EOL) {\n\t\tCELL cell = pos + *ptr++;\n\t\tif (In_Radar(cell)) {\n\t\t\tcellptr = &(*this)[cell];\n\t\t\tcellptr->Redraw_Objects();\n\t\t\tif (on) {\n\t\t\t\tcellptr->IsCursorHere = true;\n\t\t\t} else {\n\t\t\t\tcellptr->IsCursorHere = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFor every cell in the PendingObjectPtr's Overlap_List, invoke its\n\t**\tRedraw_Objects routine.\n\t*/\n\tif (PendingObjectPtr && PendingObjectPtr->IsActive) {\n\t\tptr = PendingObjectPtr->Overlap_List();\n\t\twhile (*ptr != REFRESH_EOL) {\n\t\t\tCELL cell = pos + *ptr++;\n\t\t\tif (In_Radar(cell)) {\n\t\t\t\tcellptr = &(*this)[cell];\n\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::AI -- Handles the maintenance tasks for the map display.                      *\n *                                                                                             *\n *    This routine is called once per game display frame (15 times per second). It handles     *\n *    the mouse shape tracking and map scrolling as necessary.                                 *\n *                                                                                             *\n * INPUT:   input -- The next key just fetched from the input queue.                           *\n *                                                                                             *\n *          x,y   -- Mouse coordinates.                                                        *\n *                                                                                             *\n * OUTPUT:  Modifies the input code if necessary. When the input code is consumed, it gets     *\n *          set to 0.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1994 JLB : Created.                                                                 *\n *   06/02/1994 JLB : Filters mouse click input.                                               *\n *   06/07/1994 JLB : Fixed so template click will behave right.                               *\n *   10/14/1994 JLB : Changing cursor shape over target.                                       *\n *   12/31/1994 JLB : Takes mouse coordinates as parameters.                                   *\n *   06/27/1995 JLB : Breaks out of rubber band mode if mouse leaves map.                      *\n *=============================================================================================*/\nvoid DisplayClass::AI(KeyNumType & input, int x, int y)\n{\n\tif (\n\t\tIsRubberBand &&\n\t\t(Get_Mouse_X() < TacPixelX ||\n\t\tGet_Mouse_Y() < TacPixelY ||\n\t\tGet_Mouse_X() >= (TacPixelX + Lepton_To_Pixel(TacLeptonWidth)) ||\n\t\tGet_Mouse_Y() >= (TacPixelY + Lepton_To_Pixel(TacLeptonHeight)))) {\n\t\t\tMouse_Left_Release(-1, Get_Mouse_X(), Get_Mouse_Y(), NULL, ACTION_NONE);\n\t}\n\n\tMapClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Submit -- Adds a game object to the map rendering system.                     *\n *                                                                                             *\n *    This routine is used to add an arbitrary (but tangible) game object to the map. It will  *\n *    be rendered (made visible) once it is submitted to this function. This function builds   *\n *    the list of game objects that get rendered each frame as necessary. It is possible to    *\n *    submit the game object to different rendering layers. All objects in a layer get drawn   *\n *    at the same time. Using this layer method it becomes possible to have objects \"below\"    *\n *    other objects.                                                                           *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to add.                                          *\n *                                                                                             *\n *          layer    -- The layer to add the object to.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Improved layer system.                                                   *\n *   05/31/1994 JLB : Sorts object position if this is for the ground layer.                   *\n *=============================================================================================*/\nvoid DisplayClass::Submit(ObjectClass const * object, LayerType layer)\n{\n\tif (object) {\n\t\tLayer[layer].Submit(object, (layer == LAYER_GROUND));\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Remove -- Removes a game object from the rendering system.                    *\n *                                                                                             *\n *    Every object that is to disappear from the map must be removed from the rendering        *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   object   -- The object to remove.                                                  *\n *                                                                                             *\n *          layer    -- The layer to remove it from.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Improved layer system.                                                   *\n *=============================================================================================*/\nvoid DisplayClass::Remove(ObjectClass const * object, LayerType layer)\n{\n\tassert(object != 0);\n\tassert(object->IsActive);\n\n\tif (object) {\n\t\tLayer[layer].Delete((ObjectClass *)object);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y.                         *\n *                                                                                             *\n *    This routine is used to determine the cell that is located at the                        *\n *    screen pixel coordinates given. Typical use is when the player                           *\n *    clicks with the mouse on the tactical map.                                               *\n *                                                                                             *\n * INPUT:   x,y   -- Screen pixel coordinates.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with cell that is under the coordinates specified.                         *\n *          If the coordinate specified is outside of the tactical                             *\n *          map, then -1 is returned.                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL DisplayClass::Click_Cell_Calc(int x, int y) const\n{\n\tx -= TacPixelX;\n\tx = Pixel_To_Lepton(x);\n\ty -= TacPixelY;\n\ty = Pixel_To_Lepton(y);\n\n\t// Possibly ignore the view constraints if we aren't using the internal renderer. ST - 8/5/2019 11:56AM\n\tif (IgnoreViewConstraints || (unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {\n\t\tCOORDINATE tcoord = XY_Coord(Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord))), Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord))));\n\t\treturn(Coord_Cell(Coord_Add(tcoord, XY_Coord(x, y))));\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction.                   *\n *                                                                                             *\n *    This routine is used to scroll the tactical map view in the desired                      *\n *    direction. It can also be used to determine if scrolling would be                        *\n *    legal without actually performing any scrolling action.                                  *\n *                                                                                             *\n * INPUT:   facing   -- The direction to scroll the tactical map.                              *\n *                                                                                             *\n *          distance -- The distance in leptons to scroll the map.                             *\n *                                                                                             *\n *          really   -- Should the map actually be scrolled?  If false,                        *\n *                      then only the legality of a scroll is checked.                         *\n *                                                                                             *\n * OUTPUT:  bool; Would scrolling in the desired direction be possible?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/20/1994 JLB : Converted to member function.                                            *\n *   08/09/1995 JLB : Added distance parameter.                                                *\n *   08/10/1995 JLB : Any direction scrolling.                                                 *\n *=============================================================================================*/\nbool DisplayClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\t/*\n\t**\tIf the distance is invalid then no further checking is required. Bail\n\t**\twith a no-can-do flag.\n\t*/\n\tif (distance == 0) return(false);\n\tFacingType crude = Dir_Facing(facing);\n\n\tif (Coord_X(TacticalCoord) == Cell_To_Lepton(MapCellX) && crude != FACING_W) {\n\t\tif (crude == FACING_SW) facing = DIR_S;\n\t\tif (crude == FACING_NW) facing = DIR_N;\n\t}\n\tif (Coord_Y(TacticalCoord) == Cell_To_Lepton(MapCellY) && crude != FACING_N) {\n\t\tif (crude == FACING_NW) facing = DIR_W;\n\t\tif (crude == FACING_NE) facing = DIR_E;\n\t}\n\tif (Coord_X(TacticalCoord) + TacLeptonWidth == Cell_To_Lepton(MapCellX+MapCellWidth) && crude != FACING_E) {\n\t\tif (crude == FACING_NE) facing = DIR_N;\n\t\tif (crude == FACING_SE) facing = DIR_S;\n\t}\n\tif (Coord_Y(TacticalCoord) + TacLeptonHeight == Cell_To_Lepton(MapCellY+MapCellHeight) && crude != FACING_S) {\n\t\tif (crude == FACING_SE) facing = DIR_E;\n\t\tif (crude == FACING_SW) facing = DIR_W;\n\t}\n\n\t/*\n\t**\tDetermine the coordinate that it wants to scroll to.\n\t*/\n\tCOORDINATE coord = Coord_Move(TacticalCoord, facing, distance);\n\n\t/*\n\t**\tClip the new coordinate to the edges of the game world.\n\t*/\n\tint xx = (int)(short)Coord_X(coord) - (short)Cell_To_Lepton(MapCellX);\n\tint yy = (int)(short)Coord_Y(coord) - (short)Cell_To_Lepton(MapCellY);\n\tbool shifted = Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));\n\tif (xx < 0) {\n\t\txx = 0;\n\t\tshifted = true;\n\t}\n\tif (yy < 0) {\n\t\tyy = 0;\n\t\tshifted = true;\n\t}\n\tcoord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));\n\n\t/*\n\t**\tIf the desired scroll was bound by the edge of the map, then adjust the distance to more accurately\n\t**\treflect the actual distance moved.\n\t*/\n\tif (shifted) {\n\t\tdistance = Distance(TacticalCoord, coord);\n\t}\n\n\t/*\n\t**\tIf the new coordinate is the same as the old, then no scrolling would occur.\n\t*/\n\tif (!distance || coord == TacticalCoord) return(false);\n\n\t/*\n\t**\tSince the new coordinate is different than the old one, possibly adjust the real\n\t**\ttactical map accordingly.\n\t*/\n\tif (really) {\n\t\tSet_Tactical_Position(coord);\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\n\t\t/*\n\t\t**\tScrolled map REQUIRES all top layer units to be redrawn.\n\t\t*/\n\t\tint index;\n\t\tfor (index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t}\n\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t}\n\n\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Refresh_Cells -- Redraws all cells in list.                                   *\n *                                                                                             *\n *    This routine is used to flag all cells in the specified list for                         *\n *    redrawing.                                                                               *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell that the list is offset from.                             *\n *                                                                                             *\n *          list  -- Pointer to a list of offsets from the origin cell.                        *\n *                   Each cell so specified is flagged for redraw.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is rather slow (by definition).                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   08/01/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid DisplayClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tshort tlist[36];\n\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tlist++;\n\t}\n\n\tList_Copy(list, ARRAY_SIZE(tlist), tlist);\n\tshort * tt = tlist;\n\tint count = 0;\n\twhile (*tt != REFRESH_EOL) {\n\t\tif (count >= ARRAY_SIZE(tlist)) {  // Added overrun check. ST - 8/14/2019 3:14PM\t\t\n\t\t\tbreak;\n\t\t}\n\t\tCELL newcell = cell + *tt++;\n\t\tif (In_Radar(newcell)) {\n\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t}\n\t\tcount++;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cell_Shadow   -- Determine what shadow icon to use for the cell.              *\n *                                                                                             *\n *    This routine will examine the specified cell and adjacent cells to                       *\n *    determine what shadow icon to use.                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the shadow icon to use. -2= all black.                                *\n *                                                -1= map cell.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1994 JLB : Created.                                                                 *\n *   04/04/1994 JLB : Revamped for new shadow icon method.                                     *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   08/05/2019  ST : Added house parameter so we can do this per player                       ** \n *=============================================================================================*/\nint DisplayClass::Cell_Shadow(CELL cell, HouseClass *house) const\n{\n\tstatic char const _shadow[256]={\n\t\t-1,33, 2, 2,34,37, 2, 2,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t35,45,17,17,38,41,17,17,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t32,36,25,25,44,40,25,25,\n\t\t19,30,20,20,19,30,20,20,\n\t\t39,43,29,29,42,46,29,29,\n\t\t19,30,20,20,19,30,20,20,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2\n\t};\n\n\tint index = 0, value = -1;\n\n\t/*\n\t**\tDon't map cells that are at the edges. This solves\n\t**\tproblem of accessing cells off the bounds of map and into\n\t**\twho-knows-what memory.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif ((unsigned)(Cell_X(cell)-1) >= MAP_CELL_W-2) return(-1);\n\tif ((unsigned)(Cell_Y(cell)-1) >= MAP_CELL_H-2) return(-1);\n#else\n\tif ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-1);\n#endif\n\t//if ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-2);\n\n\tCellClass const * cellptr = &(*this)[cell];\n\n\t/*\n\t**\tPresume solid black if that is what is here already.\n\t*/\n\tif (!cellptr->Is_Visible(house) && !cellptr->Is_Mapped(house)) value = -2;\n\n\tif (cellptr->Is_Mapped(house) /*&& !cellptr->IsVisible*/) {\n\t\t/*\n\t\t** Build an index into the lookup table using all 8 surrounding cells.\n\t\t** We're mapping a revealed cell and we only care about the existence\n\t\t** of black cells.  Bit numbering starts at the upper-right corner and\n\t\t** goes around the cell clockwise, so 0x80 = directly north.\n\t\t*/\n\t\tcell -= MAP_CELL_W + 1; cellptr -= MAP_CELL_W + 1;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x40;\n\t\tcell++; cellptr++;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x80;\n\t\tcell++; cellptr++;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x01;\n\t\tcell += MAP_CELL_W - 2; cellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x20;\n\t\tcell += 2; cellptr += 2;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x02;\n\t\tcell += MAP_CELL_W - 2; cellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x10;\n\t\tcell++; cellptr++;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x08;\n\t\tcell++; cellptr++;\n\t\tif (!cellptr->Is_Mapped(house) && In_Radar(cell)) index |= 0x04;\n\n\t\tvalue = _shadow[index];\n\t}\n\treturn(value);\n}\n\n\n#if (0)\t\t                            // Old code for reference. ST - 8/15/2019 10:25AM\n/***********************************************************************************************\n * DisplayClass::Cell_Shadow   -- Determine what shadow icon to use for the cell.              *\n *                                                                                             *\n *    This routine will examine the specified cell and adjacent cells to                       *\n *    determine what shadow icon to use.                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the shadow icon to use. -2= all black.                                *\n *                                                -1= map cell.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1994 JLB : Created.                                                                 *\n *   04/04/1994 JLB : Revamped for new shadow icon method.                                     *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nint DisplayClass::Cell_Shadow(CELL cell) const\n{\n\tstatic char const _shadow[256]={\n\t\t-1,33, 2, 2,34,37, 2, 2,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t35,45,17,17,38,41,17,17,\n\t\t 4,26, 6, 6, 4,26, 6, 6,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t32,36,25,25,44,40,25,25,\n\t\t19,30,20,20,19,30,20,20,\n\t\t39,43,29,29,42,46,29,29,\n\t\t19,30,20,20,19,30,20,20,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\t\t 8,21,10,10,27,31,10,10,\n\t\t12,23,14,14,12,23,14,14,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\n\t\t 1, 1, 3, 3,16,16, 3, 3,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t24,24,18,18,28,28,18,18,\n\t\t 5, 5, 7, 7, 5, 5, 7, 7,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2,\n\t\t 9, 9,11,11,22,22,11,11,\n\t\t13,13,-2,-2,13,13,-2,-2\n\t};\n\n\tint index = 0, value = -1;\n\n\t/*\n\t**\tDon't map cells that are at the top or bottom edge. This solves\n\t**\tproblem of accessing cells off the top or bottom of the map and into\n\t**\twho-knows-what memory.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif ((unsigned)(Cell_Y(cell)-1) >= MAP_CELL_H-2) return(-1);\n#else\n\tif ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-1);\n#endif\n\t//if ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-2);\n\n\tCellClass const * cellptr = &(*this)[cell];\n\n\t/*\n\t**\tPresume solid black if that is what is here already.\n\t*/\n\tif (!cellptr->IsVisible && !cellptr->IsMapped) value = -2;\n\n\tif (cellptr->IsMapped /*&& !cellptr->IsVisible*/) {\n\t\t/*\n\t\t** Build an index into the lookup table using all 8 surrounding cells.\n\t\t** We're mapping a revealed cell and we only care about the existence\n\t\t** of black cells.  Bit numbering starts at the upper-right corner and\n\t\t** goes around the cell clockwise, so 0x80 = directly north.\n\t\t*/\n\t\tcellptr-= MAP_CELL_W + 1;\n\t\tif (!cellptr->IsMapped) index |= 0x40;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x80;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x01;\n\t\tcellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->IsMapped) index |= 0x20;\n\t\tcellptr += 2;\n\t\tif (!cellptr->IsMapped) index |= 0x02;\n\t\tcellptr += MAP_CELL_W - 2;\n\t\tif (!cellptr->IsMapped) index |= 0x10;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x08;\n\t\tcellptr++;\n\t\tif (!cellptr->IsMapped) index |= 0x04;\n\n\t\tvalue = _shadow[index];\n\t}\n\treturn(value);\n}\n#endif\n\n/***********************************************************************************************\n * DisplayClass::Map_Cell -- Mark specified cell as having been mapped.                        *\n *                                                                                             *\n *    This routine maps the specified cell. The cell must not already                          *\n *    have been mapped and the mapping player must be the human.                               *\n *    This routine will update any adjacent cell map icon as appropriate.                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell to be mapped.                                                    *\n *                                                                                             *\n *          house -- The player that is doing the mapping.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was action taken to map this cell?                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/24/1994 JLB : Takes pointer to HouseClass.                                             *\n *   02/20/1996 JLB : Allied units reveal the map for the player.                              *\n *   08/05/2019  ST : Use per-player mapping so we can track the shroud for all players        *\n *=============================================================================================*/\nbool DisplayClass::Map_Cell(CELL cell, HouseClass * house, bool check_radar_spied, bool and_for_allies)\n{\n\t// OK for house not to be PlayerPtr. ST - 8/6/2019 10:05AM\n\t//if (house != PlayerPtr || !In_Radar(cell)) return(false);\n\tif (house == NULL || !In_Radar(cell)) return(false);\n\t\n\tif (!house->IsHuman) {\n\t\tif (!ShareAllyVisibility || !and_for_allies && !check_radar_spied) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t/*\n\t** First check for the condition where we're spying on a house's radar\n\t** facility, to see if his mapping is applicable to us.\n\t*/\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t// Original code. ST - 8/15/2019 10:26AM\n\t\tif (house && house != PlayerPtr) {\n\t\t\tif (house->RadarSpied & (1<<(PlayerPtr->Class->House))) house = PlayerPtr;\n\t\t\tif (Session.Type == GAME_NORMAL && house->Is_Ally(PlayerPtr)) house = PlayerPtr;\n\t\t}\n\t} else {\n\t\t// Version to work with any human player, not just PlayerPtr\n\t\tif (house && check_radar_spied) {\n\t\t\t\n\t\t\tfor (int i=0 ; i<Session.Players.Count() ; i++) {\n\t\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\tif (player_ptr->IsHuman) {\n\t\t\t\t\tif (house->RadarSpied & (1<<(player_ptr->Class->House))) {\n\t\t\t\t\t\tMap_Cell(cell, player_ptr, false, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Maybe also recurse to map for allies\n\t*/\n\tif (ShareAllyVisibility && and_for_allies && Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\n\t\tfor (int i=0 ; i<Session.Players.Count() ; i++) {\n\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tif (player_ptr && player_ptr->IsActive && player_ptr->IsHuman) {\n\t\t\t\tif (player_ptr != house && house->Is_Ally(player_ptr)) {\n\t\t\t\t\tMap_Cell(cell, player_ptr, check_radar_spied, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCellClass * cellptr = &(*this)[cell];\n\n\t/*\n\t**\tDon't bother remapping this cell if it is already mapped.\n\t*/\n#if (1)\t\n\tif (cellptr->Is_Mapped(house)) {\n\t\tif (!cellptr->Is_Visible(house)) {\n\t\t\tcellptr->Redraw_Objects();\n\t\t}\n\t\treturn(false);\n\t}\n#else\n\tif (cellptr->IsMapped) {\n\t\tif (!cellptr->IsVisible) {\n\t\t\tcellptr->Redraw_Objects();\n\t\t}\n\t\treturn(false);\n\t}\n#endif\n\t/*\n\t** Mark the cell as being mapped. This must be done first because\n\t**\tif the IsVisible flag must be set, then it might affect the\n\t**\tadjacent cell processing.\n\t*/\n\t// Set per player. ST - 8/6/2019 10:18AM\n\tcellptr->Set_Mapped(house);\n\tcellptr->Redraw_Objects();\n\tif (Cell_Shadow(cell, house) == -1) {\n\t\tcellptr->Set_Visible(house);\n\t}\n\n\t/*\n\t**\tCheck out all adjacent cells to see if they need\n\t**\tto be mapped as well. This is necessary because of the\n\t**\t\"unique\" method of showing shadowed cells. Many combinations\n\t**\tare not allowed, and to fix this, just map the cells until\n\t**\tall is ok.\n\t*/\n\tint xx = Cell_X(cell);\n\tfor (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {\n\t\tint\tshadow;\n\t\tCELL\tc;\n\t\tint xdiff;\n\n\t\tc = Adjacent_Cell(cell, dir);\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)c >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(c) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > 1) continue;\n\n\t\tCellClass * cptr = &(*this)[c];\n\t\tcptr->Redraw_Objects();\n\n#if (1)\n\t\t// New client/server friendly code\n\t\tif (c != cell && !cptr->Is_Visible(house)) {\n\t\t\tshadow = Cell_Shadow(c, house);\n\n\t\t\tif (shadow == -1) {\n\t\t\t\tif (!cptr->Is_Mapped(house)) {\n\t\t\t\t\tMap_Cell(c, house, check_radar_spied, false);\n\t\t\t\t} else {\n\t\t\t\t\tcptr->Set_Visible(house);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (shadow != -2 && !cptr->Is_Mapped(house)) {\n\t\t\t\t\tMap_Cell(c, house, check_radar_spied, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#else\n\t\t// Old peer/peer code\n\t\tif (c != cell && !cptr->IsVisible) {\n\t\t\tshadow = Cell_Shadow(c);\n\n\t\t\tif (shadow == -1) {\n\t\t\t\tif (!cptr->IsMapped) {\n\t\t\t\t\tMap_Cell(c, house);\n\t\t\t\t} else {\n\t\t\t\t\tcptr->IsVisible = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (shadow != -2 && !cptr->IsMapped) {\n\t\t\t\t\tMap_Cell(c, house);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n\tTechnoClass * tech = (*this)[cell].Cell_Techno();\n\tif (tech) {\n\t\ttech->Revealed(house);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates.                       *\n *                                                                                             *\n *    This is the routine that figures out the location on the screen for                      *\n *    a specified coordinate. It is one of the fundamental routines                            *\n *    necessary for rendering the game objects. It performs some quick                         *\n *    tests to see if the coordinate is in a visible region and returns                        *\n *    this check as a boolean value.                                                           *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to check.                                                  *\n *                                                                                             *\n *          x,y   -- Reference to the pixel coordinates that this                              *\n *                   coordinate would be when rendered.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Is this coordinate in a visible portion of the map?                          *\n *                                                                                             *\n * WARNINGS:   If the coordinate is not in a visible portion of the                            *\n *             map, then this X and Y parameters are not set.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *   12/15/1994 JLB : Converted to member function.                                            *\n *   01/07/1995 JLB : Uses inline functions to extract coord components.                       *\n *   08/09/1995 JLB : Uses new coordinate system.                                              *\n *=============================================================================================*/\n#define\tEDGE_ZONE\t(CELL_LEPTON_W*2)\nbool DisplayClass::Coord_To_Pixel(COORDINATE coord, int &x, int &y) const\n{\n\tint xtac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord)));\n\tint xoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(coord)));\n\txoff = (xoff + EDGE_ZONE) - xtac;\n\n\tint ytac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord)));\n\tint yoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(coord)));\n\tyoff = (yoff + EDGE_ZONE) - ytac;\n\n\tx = Lepton_To_Pixel(xoff) - CELL_PIXEL_W * 2;\n\ty = Lepton_To_Pixel(yoff) - CELL_PIXEL_H * 2;\n\n\t// Possibly ignore the view constraints if we aren't using the internal renderer. ST - 4/17/2019 9:06AM\n\treturn(coord && (IgnoreViewConstraints || ((xoff <= TacLeptonWidth + EDGE_ZONE * 2) && (yoff <= TacLeptonHeight + EDGE_ZONE * 2))));\n}\n\n#if (0) //reference. ST - 5/8/2019\nbool DisplayClass::Coord_To_Pixel(COORDINATE coord, int &x, int &y) const\n{\n\tif (coord) {\n\t\tint xtac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord)));\n\t\tint xoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(coord)));\n\n\t\txoff = (xoff+EDGE_ZONE) - xtac;\n\t\tif ((unsigned)xoff <= TacLeptonWidth + EDGE_ZONE*2) {\n\t\t\tint ytac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord)));\n\t\t\tint yoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(coord)));\n\n\t\t\tyoff = (yoff+EDGE_ZONE) - ytac;\n\t\t\tif ((unsigned)yoff <= TacLeptonHeight + EDGE_ZONE*2) {\n\t\t\t\tx = Lepton_To_Pixel(xoff)-CELL_PIXEL_W*2;\n\t\t\t\ty = Lepton_To_Pixel(yoff)-CELL_PIXEL_H*2;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n#endif\n\n/***********************************************************************************************\n * DisplayClass::Push_Onto_TacMap -- Moves x & y coords to being on tactical map               *\n *                                                                                             *\n * This routine expects a line to be drawn between SOURCE & DEST, so it pushes the coords to   *\n * be within the region bounded by TacMapX,Y - + TacMapW,H.                                    *\n *                                                                                             *\n * INPUT:   source, dest -- References to the coordinates to check.                            *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  bool; Are these coordinates in a visible portion of the map?                       *\n *                Returns true if the pushed source & dest are visible, but if neither are     *\n *                within the map, then it returns false.                                       *\n *                                                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Push_Onto_TacMap(COORDINATE & source, COORDINATE & dest)\n{\n\tif (!source || !dest) return(false);\n\n\tint x1 = Coord_X(source);\n\tint y1 = Coord_Y(source);\n\tint x2 = Coord_X(dest);\n\tint y2 = Coord_Y(dest);\n\tint left = Coord_X(TacticalCoord);\n\tint right = Coord_X(TacticalCoord) + TacLeptonWidth;\n\tint top = Coord_Y(TacticalCoord);\n\tint bottom = Coord_Y(TacticalCoord) + TacLeptonHeight;\n\n\tif (x1 < left && x2 < left) return(false);\n\tif (x1 > right && x2 > right) return(false);\n\tif (y1 < top && y2 < top) return(false);\n\tif (y1 > bottom && y2 > bottom) return(false);\n\n\tx1 = Bound(x1, left, right);\n\tx2 = Bound(x2, left, right);\n\ty1 = Bound(y1, top, bottom);\n\ty2 = Bound(y2, top, bottom);\n\n\tsource = XY_Coord(x1, y1);\n\tdest = XY_Coord(x2, y2);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Cell_Object -- Determines what has been clicked on.                           *\n *                                                                                             *\n *    This routine is used to determine what the player has clicked on.                        *\n *    It is passed the cell that the click was on and it then examines                         *\n *    the cell and returns with a pointer to the object that is there.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that has been clicked upon.                                      *\n *                                                                                             *\n *          x,y   -- Optional offsets from the upper left corner of the cell to be used in     *\n *                   determining exactly which object in the cell is desired.                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object that is \"clickable\" in                        *\n *          the specified cell.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Cell_Object(CELL cell, int x, int y) const\n{\n\treturn(*this)[cell].Cell_Object(x, y);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Draw_It -- Draws the tactical map.                                            *\n *                                                                                             *\n *    This will draw the tactical map at the recorded position.   This                         *\n *    routine is used whenever the tactical map moves or needs to be                           *\n *    completely redrawn. It will handle making the necessary adjustments                      *\n *    to accomodate a moving cursor.                                                           *\n *                                                                                             *\n * INPUT:      forced   -- bool; force redraw of the entire display?                           *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/15/1991 JLB : Created. (benchmark = 292)                                               *\n *   04/15/1991 JLB : Added _cell2meta[] reference array (206)                                 *\n *   04/15/1991 JLB : Added actual map reference for terrain (207)                             *\n *   04/16/1991 JLB : _cell2meta converted to int (194)                                        *\n *   04/16/1991 JLB : References actual CellIcon[] array (204)                                 *\n *   04/16/1991 JLB : Cell size increased to 16 x 16 (167)                                     *\n *   04/17/1991 JLB : Cell based tactical map rendering (165)                                  *\n *   04/22/1991 JLB : Uses Draw_Stamp() for icon rendering (426)                               *\n *   04/22/1991 JLB : Draw_Stamp uses LogicPage now (276)                                      *\n *   04/23/1991 JLB : Map active location cursor (334)                                         *\n *   05/02/1991 JLB : Added smoothing and 3 icons sets (431)                                   *\n *   05/22/1991 JLB : Broken into Draw_Map() and Refresh_Map().                                *\n *   09/14/1991 JLB : Uses Refresh_Cell when new cells scroll onto display.                    *\n *   05/12/1992 JLB : Destination page support.                                                *\n *   02/14/1994 JLB : Revamped.                                                                *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *   12/15/1994 JLB : Updated to work with display hierarchy.                                  *\n *   12/24/1994 JLB : Examines redraw bit intelligently.                                       *\n *   12/24/1994 JLB : Combined with old Refresh_Map() function.                                *\n *   01/10/1995 JLB : Rubber band drawing.                                                     *\n *=============================================================================================*/\n void DisplayClass::Draw_It(bool forced)\n{\n\tint\tx,y;\t\t\t// Working cell index values.\n\n\tMapClass::Draw_It(forced);\n\n\tif (IsToRedraw || forced) {\n\t\tBStart(BENCH_TACTICAL);\n\t\tIsToRedraw = false;\n\n\t\t/*\n\t\t**\tIn rubber band mode, mark all cells under the \"rubber band\" to be\n\t\t**\tredrawn.\n\t\t*/\n\t\tRefresh_Band();\n\n\t\t/*\n\t\t** Mark all cells under the vortex to be redrawn\n\t\t*/\n\t\tChronalVortex.Set_Redraw();\n\n\n\t\t/*\n\t\t** If the multiplayer message system is displaying one or more messages,\n\t\t** flag all cells covered by the messages to redraw.  This will prevent\n\t\t** messages from smearing the map if it scrolls.\n\t\t*/\n\t\tint num = Session.Messages.Num_Messages();\n\t\tif (num > 0) {\n\t\t\tCELL cell;\n\t\t\tfor (cell = Coord_Cell(TacticalCoord); cell < Coord_Cell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t}\n\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W;\n\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t}\n\t\t\tif (num > 1) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*2;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*2 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (num > 2) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*3;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*3 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (num > 3) {\n\t\t\t\tfor (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*4;\n\t\t\t\t\tcell < Coord_Cell(TacticalCoord) + MAP_CELL_W*4 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {\n\t\t\t\t\t(*this)[cell].Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck for a movement of the tactical map. If there has been some\n\t\t**\tmovement, then part (or all) of the icons must be redrawn.\n\t\t*/\n\t\tif (Lepton_To_Pixel(Coord_X(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_X(TacticalCoord)) ||\n\t\t\tLepton_To_Pixel(Coord_Y(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_Y(TacticalCoord))) {\n\n\t\t\tint xmod = Lepton_To_Pixel(Coord_X(DesiredTacticalCoord));\n\t\t\tint ymod = Lepton_To_Pixel(Coord_Y(DesiredTacticalCoord));\n\n\t\t\tint oldx = Lepton_To_Pixel(Coord_X(TacticalCoord))-xmod;\t\t// Old relative offset.\n\t\t\tint oldy = Lepton_To_Pixel(Coord_Y(TacticalCoord))-ymod;\n\n\t\t\tint oldw = Lepton_To_Pixel(TacLeptonWidth)-ABS(oldx);\t\t\t// Replicable width.\n\t\t\tint oldh = Lepton_To_Pixel(TacLeptonHeight)-ABS(oldy);\t\t// Replicable height.\n\n\t\t\tif (oldw < 1) forced = true;\n\t\t\tif (oldh < 1) forced = true;\n\n\n#ifdef WIN32\t\t//For WIN32 only redraw the edges of the map that move into view\n\n\t\t\t/*\n\t\t\t** Work out which map edges need to be redrawn\n\t\t\t*/\n\t\t\tBOOL redraw_right = (oldx < 0) ? true : false;\t\t//Right hand edge\n\t\t\tBOOL redraw_left  = (oldx > 0) ? true : false;\t\t//Left hand edge\n\t\t\tBOOL redraw_bottom= (oldy < 0) ? true : false;\t\t//Bottom edge\n\t\t\tBOOL redraw_top\t= (oldy > 0) ? true : false;\t\t//Top edge\n\n\t\t\t/*\n\t\t\t**\tBlit any replicable block to avoid having to drawstamp.\n\t\t\t*/\n\t\t\tif (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {\n\t\t\t\tSet_Cursor_Pos(-1);\n\n\t\t\t\t/*\n\t\t\t\t** If hid page is in video memory then blit from the seen page to avoid blitting\n\t\t\t\t**  an overlapped region.\n\t\t\t\t*/\n\t\t\t\tif (HidPage.Get_IsDirectDraw()) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\t\tSeenBuff.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\t\toldh);\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else {\n\t\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\t\toldh);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tforced = true;\n\t\t\t}\n\n\t\t\tif (oldx < 0) oldx = 0;\n\t\t\tif (oldy < 0) oldy = 0;\n\n\t\t\t/*\n\t\t\t** Record new map position for future reference.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\tScenarioInit--;\n\n\t\t\tif (!forced) {\n\n\t\t\t\t/*\n\t\t\t\t**\n\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t**\n\t\t\t\t*/\n\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\toldw -= 24;\n\t\t\t\toldh -= 24;\n\n\t\t\t\tif (abs(oldx) < 0x25 && abs(oldy) < 0x25) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** The width of the area we redraw depends on the scroll speed\n\t\t\t\t\t*/\n\t\t\t\t\tint extra_x = (abs(oldx)>=16) ? 2 : 1;\n\t\t\t\t\tint extra_y = (abs(oldy)>=16) ? 2 : 1;\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells across the top of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_top) {\n\t\t\t\t\t\tfor (y = starty; y <= starty+CELL_PIXEL_H*extra_y; y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells across the bottom of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_bottom) {\n\t\t\t\t\t\tfor (y = Lepton_To_Pixel(TacLeptonHeight)-CELL_PIXEL_H*(1+extra_y); y <= Lepton_To_Pixel(TacLeptonHeight)+CELL_PIXEL_H*3; y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells down the left of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_left) {\n\t\t\t\t\t\tfor (x = startx; x <= startx + CELL_PIXEL_W*extra_x; x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag the cells down the right of the visible area if required\n\t\t\t\t\t*/\n\t\t\t\t\tif (redraw_right) {\n\t\t\t\t\t\tfor (x = Lepton_To_Pixel(TacLeptonWidth)-CELL_PIXEL_W*(extra_x+1); x <= Lepton_To_Pixel(TacLeptonWidth)+CELL_PIXEL_W*3; x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) (*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t\t*/\n\t\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\t\toldw -= 24;\n\t\t\t\t\toldh -= 24;\n\t\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\t\tif (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {\n\t\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\t\tif (c > 0) {\n\t\t\t\t\t\t\t\t\t(*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSet the tactical coordinate just in case the desired tactical has changed but\n\t\t\t**\tnot enough to result in any visible map change. This is likely to occur with very\n\t\t\t**\tslow scroll rates.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tif (DesiredTacticalCoord != TacticalCoord) {\n\t\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n\n\n#else\t//WIN32\n\t\t\t/*\n\t\t\t**\tBlit any replicable block to avoid having to drawstamp.\n\t\t\t*/\n\t\t\tif (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {\n\t\t\t\tSet_Cursor_Pos(-1);\n\n\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t((oldx < 0) ? -oldx : 0) +TacPixelX,\n\t\t\t\t\t\t\t\t((oldy < 0) ? -oldy : 0) +TacPixelY,\n\t\t\t\t\t\t\t\t((oldx < 0) ? 0 : oldx) +TacPixelX,\n\t\t\t\t\t\t\t\t((oldy < 0) ? 0 : oldy) +TacPixelY,\n\t\t\t\t\t\t\t\toldw,\n\t\t\t\t\t\t\t\toldh);\n\t\t\t} else {\n\t\t\t\tforced = true;\n\t\t\t}\n\n\t\t\tif (oldx < 0) oldx = 0;\n\t\t\tif (oldy < 0) oldy = 0;\n\n\t\t\t/*\n\t\t\t** Record new map position for future reference.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\tScenarioInit--;\n\n\t\t\tif (!forced) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet the 'redraw stamp' bit for any cells that could not be copied.\n\t\t\t\t*/\n\t\t\t\tint startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));\n\t\t\t\tint starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));\n\t\t\t\toldw -= 24;\n\t\t\t\toldh -= 24;\n\t\t\t\tfor (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {\n\t\t\t\t\tfor (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {\n\t\t\t\t\t\tif (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {\n\t\t\t\t\t\t\tCELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,\n\t\t\t\t\t\t\t\t\t\tBound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);\n\n\t\t\t\t\t\t\tif (c > 0) {\n\t\t\t\t\t\t\t\t(*this)[c].Redraw_Objects(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSet the tactical coordinate just in case the desired tactical has changed but\n\t\t\t**\tnot enough to result in any visible map change. This is likely to occur with very\n\t\t\t**\tslow scroll rates.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tif (DesiredTacticalCoord != TacticalCoord) {\n\t\t\t\tSet_Tactical_Position(DesiredTacticalCoord);\n\t\t\t}\n\t\t\tScenarioInit--;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tIf the entire tactical map is forced to be redrawn, then set all the redraw flags\n\t\t**\tand let the normal processing take care of the rest.\n\t\t*/\n\t\tif (forced) {\n\t\t\tCellRedraw.Set();\n\t\t}\n\n\t\t/*\n\t\t**\tThe first order of business is to redraw all the underlying icons that are\n\t\t**\tflagged to be redrawn.\n\t\t*/\n\t\tif (HidPage.Lock()) {\n\t\t\tRedraw_Icons();\n\n\t\t\t/*\n\t\t\t**\tDraw the infantry bodies in this special layer.\n\t\t\t*/\n//\t\t\tfor (int index = 0; index < Anims.Count(); index++) {\n//\t\t\t\tAnimClass * anim = Anims.Ptr(index);\n//\t\t\t\tif (*anim >= ANIM_CORPSE1 && *anim <= ANIM_CORPSE3) {\n//\t\t\t\t\tanim->Render(forced);\n//\t\t\t\t}\n//\t\t\t}\n\n#ifdef SORTDRAW\n\t\t\t/*\n\t\t\t** Draw the vortex effect over the terrain\n\t\t\t*/\n\t\t\tChronalVortex.Render();\n\n\t\t\tRedraw_OIcons();\n#endif\n\n\t\t\tHidPage.Unlock();\n\t\t}\n\n#ifndef WIN32\n\t\t/*\n\t\t**\tOnce the icons are drawn, duplicate the bottom line of the screen into the phantom\n\t\t**\tarea one line below the screen. This causes the predator effect to work on any\n\t\t**\tshape drawn at the bottom of the screen.\n\t\t*/\n\t\tHidPage.Blit(HidPage, 0, HidPage.Get_Height()-1, 0, HidPage.Get_Height(), HidPage.Get_Width(), 1, false);\n#endif\n\n\t\tif (HidPage.Lock()) {\n\n#ifndef SORTDRAW\n\t\t\t/*\n\t\t\t** Draw the vortex effect over the terrain\n\t\t\t*/\n\t\t\tChronalVortex.Render();\n#endif\n\n\t\t\t/*\n\t\t\t**\tRedraw the game objects layer by layer. The layer drawing occurs on the ground layer\n\t\t\t**\tfirst and then followed by all the layers in increasing altitude.\n\t\t\t*/\n\t\t\tBStart(BENCH_OBJECTS);\n\t\t\tfor (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {\n\t\t\t\tfor (int index = 0; index < Layer[layer].Count(); index++) {\n\t\t\t\t\tObjectClass * ptr = Layer[layer][index];\n\n#ifdef SORTDRAW\n\t\t\t\t\t/*\n\t\t\t\t\t**\tTechno objects are drawn as part of the cell redraw process since techno\n\t\t\t\t\t**\tobjects in the ground layer are handled by the Occupier and Overlapper\n\t\t\t\t\t**\tpointer lists.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!Debug_Map && ptr->Is_Techno() && layer == LAYER_GROUND && ((TechnoClass*)ptr)->Visual_Character() == VISUAL_NORMAL) continue;\n#endif\n\n//\t\t\t\t\tif (ptr->What_Am_I() == RTTI_ANIM && *((AnimClass*)ptr) >= ANIM_CORPSE1 && *((AnimClass*)ptr) <= ANIM_CORPSE3) {\n//\t\t\t\t\t\tcontinue;\n//\t\t\t\t\t}\n\t\t\t\t\tassert(ptr->IsActive);\n\t\t\t\t\tptr->Render(forced);\n\t\t\t\t}\n\t\t\t}\n\t\t\tBEnd(BENCH_OBJECTS);\n\n\t//ChronalVortex.Render();\n\t\t\t/*\n\t\t\t**\tFinally, redraw the shadow overlay as necessary.\n\t\t\t*/\n\t\t\tBStart(BENCH_SHROUD);\n\t\t\tRedraw_Shadow();\n\t\t\tBEnd(BENCH_SHROUD);\n\t\t}\n\t\tHidPage.Unlock();\n\n#ifdef SORTDRAW\n\t\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\t\tLayer[LAYER_GROUND][index]->IsToDisplay = false;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tDraw the rubber band over the top of it all.\n\t\t*/\n\t\tif (IsRubberBand) {\n\t\t\tLogicPage->Draw_Rect(BandX+TacPixelX, BandY+TacPixelY, NewX+TacPixelX, NewY+TacPixelY, WHITE);\n\t\t}\n\n\t\t/*\n\t\t**\tClear the redraw flags so that normal redraw flag setting can resume.\n\t\t*/\n\t\tCellRedraw.Reset();\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t**\tIf we're placing an object (PendingObject is non-NULL), and that object\n\t\t**\tis NOT an icon, smudge, or overlay, draw it here.\n\t\t**\tTerrain, Buildings & Aircraft aren't drawn at the cell's center coord;\n\t\t**\tthey're drawn at the upper left coord, so I have to AND the coord value\n\t\t**\twith 0xFF00FF00 to strip off the lepton coordinates, but leave the\n\t\t**\tcell coordinates.\n\t\t*/\n\t\tif (Debug_Map && PendingObjectPtr) {\n\t\t\tPendingObjectPtr->Coord = PendingObjectPtr->Class_Of().Coord_Fixup(Cell_Coord(ZoneCell + ZoneOffset));\n\t\t\tPendingObjectPtr->Render(true);\n\t\t}\n#endif\n\t\tBEnd(BENCH_TACTICAL);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Redraw_Icons -- Draws all terrain icons necessary.                            *\n *                                                                                             *\n *    This routine will redraw all of the terrain icons that are flagged                       *\n *    to be redrawn.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1994 JLB : Created.                                                                 *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *   06/20/1994 JLB : Uses cell drawing support function.                                      *\n *   12/06/1994 JLB : Scans tactical view in separate row/column loops                         *\n *   12/24/1994 JLB : Uses the cell bit flag array to determine what to redraw.                *\n *=============================================================================================*/\nvoid DisplayClass::Redraw_Icons(void)\n{\n\tIsShadowPresent = false;\n\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t/*\n\t\t\t**\tOnly cells flagged to be redraw are examined.\n\t\t\t*/\n\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\tint xpixel;\n\t\t\t\tint ypixel;\n\n\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf there is a portion of the underlying icon that could be visible,\n\t\t\t\t\t**\tthen draw it.  Also draw the cell if the shroud is off.\n\t\t\t\t\t*/\n\t\t\t\t\t//if (cellptr->IsMapped || Debug_Unshroud) {\n\t\t\t\t\tif (cellptr->Is_Mapped(PlayerPtr) || Debug_Unshroud) {\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 3/6/2019 2:49PM\n\t\t\t\t\t\tcellptr->Draw_It(xpixel, ypixel);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any cell is not fully mapped, then flag it so that the shadow drawing\n\t\t\t\t\t**\tprocess will occur.  Only draw the shadow if Debug_Unshroud is false.\n\t\t\t\t\t*/\n\t\t\t\t\t//if (!cellptr->IsVisible && !Debug_Unshroud) {\n\t\t\t\t\tif (!cellptr->Is_Visible(PlayerPtr) && !Debug_Unshroud) {\t// Use PlayerPtr since we won't be rendering in MP. ST - 3/6/2019 2:49PM\n\t\t\t\t\t\tIsShadowPresent = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n#ifdef SORTDRAW\nvoid DisplayClass::Redraw_OIcons(void)\n{\n\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t/*\n\t\t\t**\tOnly cells flagged to be redraw are examined.\n\t\t\t*/\n\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\tint xpixel;\n\t\t\t\tint ypixel;\n\n\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf there is a portion of the underlying icon that could be visible,\n\t\t\t\t\t**\tthen draw it.  Also draw the cell if the shroud is off.\n\t\t\t\t\t*/\n\t\t\t\t\t//if (cellptr->IsMapped || Debug_Unshroud) {\n\t\t\t\t\tif (cellptr->Is_Mapped(PlayerPtr) || Debug_Unshroud) {\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 3/6/2019 2:49PM\n\t\t\t\t\t\tcellptr->Draw_It(xpixel, ypixel, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * DisplayClass::Redraw_Shadow -- Draw the shadow overlay.                                     *\n *                                                                                             *\n *    This routine is called after all other tactical map rendering takes place. It draws      *\n *    the shadow map over the tactical map.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Clips the fill rect if necessary.                                        *\n *=============================================================================================*/\nvoid DisplayClass::Redraw_Shadow(void)\n{\n\tif (IsShadowPresent) {\n\t\tfor (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {\n\t\t\tfor (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {\n\t\t\t\tCOORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));\n\t\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\t\tcoord = Coord_Whole(Cell_Coord(cell));\n\n\t\t\t\t/*\n\t\t\t\t**\tOnly cells flagged to be redrawn are examined.\n\t\t\t\t*/\n\t\t\t\tif (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\t\tint xpixel;\n\t\t\t\t\tint ypixel;\n\n\t\t\t\t\tif (Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\t\tCellClass * cellptr = &(*this)[coord];\n\t\t\t\t\t\t//if (cellptr->IsVisible) continue;\n\t\t\t\t\t\tif (cellptr->Is_Visible(PlayerPtr)) continue;\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 8/6/2019 10:44AM\n\t\t\t\t\t\tint shadow = -2;\n\t\t\t\t\t\t//if (cellptr->IsMapped) {\n\t\t\t\t\t\tif (cellptr->Is_Mapped(PlayerPtr)) {\t\t\t\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 8/6/2019 10:44AM\n\t\t\t\t\t\t\tshadow = Cell_Shadow(cell, PlayerPtr);\t\t\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 8/6/2019 10:44AM\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (shadow >= 0) {\n\t\t\t\t\t\t\tCC_Draw_Shape(ShadowShapes, shadow, xpixel, ypixel, WINDOW_TACTICAL, SHAPE_GHOST, NULL, ShadowTrans);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (shadow != -1) {\n\t\t\t\t\t\t\t\tint ww = CELL_PIXEL_W;\n\t\t\t\t\t\t\t\tint hh = CELL_PIXEL_H;\n\n\t\t\t\t\t\t\t\tif (Clip_Rect(&xpixel, &ypixel, &ww, &hh, Lepton_To_Pixel(TacLeptonWidth), Lepton_To_Pixel(TacLeptonHeight)) >= 0) {\n\t\t\t\t\t\t\t\t\tLogicPage->Fill_Rect(TacPixelX+xpixel, TacPixelY+ypixel, TacPixelX+xpixel+ww-1, TacPixelY+ypixel+hh-1, BLACK);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Next_Object -- Searches for next object on display.                           *\n *                                                                                             *\n *    This utility routine is used to find the \"next\" object from the object specified. This   *\n *    is typically used when <TAB> is pressed and the current object shifts.                   *\n *                                                                                             *\n * INPUT:   object   -- The current object to base the \"next\" calculation off of.              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the next object. If there is no objects available,       *\n *          then NULL is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Next_Object(ObjectClass * object) const\n{\n\tObjectClass * firstobj = NULL;\n\tbool foundmatch = false;\n\n\tif (object == NULL) {\n\t\tfoundmatch = true;\n\t}\n\tfor (unsigned uindex = 0; uindex < (unsigned)Layer[LAYER_GROUND].Count(); uindex++) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][uindex];\n\n\t\t/*\n\t\t**\tVerify that the object can be selected by and is owned by the player.\n\t\t*/\n\t\tif (obj != NULL && obj->Is_Players_Army()) {\n\t\t\tif (firstobj == NULL) firstobj = obj;\n\t\t\tif (foundmatch) return(obj);\n\t\t\tif (object == obj) foundmatch = true;\n\t\t}\n\t}\n\treturn(firstobj);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Prev_Object -- Searches for the previous object on the map.                   *\n *                                                                                             *\n *    This routine will search for the previous object. Previous is defined as the one listed  *\n *    before the specified object in the ground layer. If there is no specified object, then   *\n *    the last object in the ground layer is returned.                                         *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that \"previous\" is to be defined from.           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object previous to the specified one.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * DisplayClass::Prev_Object(ObjectClass * object)  const\n{\n\tObjectClass * firstobj = NULL;\n\tbool foundmatch = false;\n\n\tif (object == NULL) {\n\t\tfoundmatch = true;\n\t}\n\tfor (int uindex = Layer[LAYER_GROUND].Count()-1; uindex >= 0; uindex--) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][uindex];\n\n\t\t/*\n\t\t**\tVerify that the object can be selected by and is owned by the player.\n\t\t*/\n\t\tif (obj != NULL && obj->Is_Players_Army()) {\n\t\t\tif (firstobj == NULL) firstobj = obj;\n\t\t\tif (foundmatch) return(obj);\n\t\t\tif (object == obj) foundmatch = true;\n\t\t}\n\t}\n\n\treturn(firstobj);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      x,y      pixel coordinates to convert                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      COORDINATE of pixel                                                                    *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1994 BR : Created.                                                                  *\n *   12/06/1994 JLB : Uses map dimension variables in display class.                           *\n *   12/10/1994 JLB : Uses union to speed building coordinate value.                           *\n *=============================================================================================*/\nCOORDINATE DisplayClass::Pixel_To_Coord(int x, int y) const\n{\n\t/*\n\t**\tNormalize the pixel coordinates to be relative to the upper left corner\n\t**\tof the tactical map. The coordinates are expressed in leptons.\n\t*/\n\tx -= TacPixelX;\n\tx = Pixel_To_Lepton(x);\n\ty -= TacPixelY;\n\ty = Pixel_To_Lepton(y);\n\n\t/*\n\t**\tIf pixel coordinate is over the tactical map, then translate it into a coordinate\n\t**\tvalue. If not, then just return with NULL.\n\t*/\n\t// Possibly ignore the view constraints if we aren't using the internal renderer. ST - 8/6/2019 10:47AM\n\t//if ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {\n\tif (IgnoreViewConstraints || ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight)) {\n\t\treturn(Coord_Add(TacticalCoord, XY_Coord(x, y)));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method.                *\n *                                                                                             *\n *    Find a cell meeting the specified requirements. This function is                         *\n *    used for scenario reinforcements.                                                        *\n *                                                                                             *\n * INPUT:   dir   -- Method of picking a map cell.                                             *\n *                                                                                             *\n *          waypoint -- Closest waypoint to use for finding appropriate map edge.              *\n *                                                                                             *\n *          cell  -- Cell to find closest edge to if waypoint not specified.                   *\n *                                                                                             *\n *          loco  -- The locomotion of the reinforcements that are trying to enter.            *\n *                                                                                             *\n *          zonecheck   -- Is zone checking required?                                          *\n *                                                                                             *\n *          mzone    -- The movement zone type to check against (only if zone checking).       *\n *                                                                                             *\n * OUTPUT:  Returns with the calculated cell. If 0, then this indicates                        *\n *          that no legal cell was found.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/11/1994 JLB : Revamped.                                                                *\n *   05/18/1994 JLB : Converted to member function.                                            *\n *   12/18/1995 JLB : Handles edge preference scan.                                            *\n *   06/24/1996 JLB : Removed Dune II legacy code.                                             *\n *   06/25/1996 JLB : Rewrote and greatly simplified.                                          *\n *   10/05/1996 JLB : Checks for zone and crushable status.                                    *\n *=============================================================================================*/\nCELL DisplayClass::Calculated_Cell(SourceType dir, WAYPOINT waypoint, CELL cell, SpeedType loco, bool zonecheck, MZoneType mzone) const\n{\n\tbool vert = false;\n\tbool horz = false;\n\tint x = 0;\n\tint y = 0;\n\tCELL punt = 0;\t\t\t// If all else fails, return this cell location.\n\tint zone = -1;\t\t\t// Tentative zone for legality checking.\n\n\t/*\n\t**\tWaypoint edge detection for ground based reinforcements that have a waypoint origin are\n\t**\tdetermined by finding the closest map edge to the waypoint. Reinforcement location\n\t**\tscanning starts from that position.\n\t*/\n\tCELL trycell = -1;\n\tif (waypoint != -1) {\n\t\ttrycell = Scen.Waypoint[waypoint];\n\t}\n\tif (trycell == -1) {\n\t\ttrycell = cell;\n\t}\n\n\t/*\n\t**\tIf zone checking is requested, then find the correct zone to use.\n\t*/\n\tif (zonecheck && trycell != -1) {\n\t\tzone = (*this)[trycell].Zones[mzone];\n\t}\n\n\t/*\n\t**\tIf the cell or waypoint specified as been detected as legal, then set up the map edge\n\t**\tscanning values accordingly.\n\t*/\n\tif (trycell != -1) {\n\t\tx = Cell_X(trycell) - MapCellX;\n\t\tx = min(x, (-Cell_X(trycell) + (MapCellX+MapCellWidth)));\n\n\t\ty = Cell_Y(trycell) - MapCellY;\n\t\ty = min(y, (-Cell_Y(trycell) + (MapCellY+MapCellHeight)));\n\n\t\tif (x < y) {\n\t\t\tvert = true;\n\t\t\thorz = false;\n\t\t\tif ((Cell_X(trycell)-MapCellX) < MapCellWidth/2) {\n\t\t\t\tx = -1;\n\t\t\t} else {\n\t\t\t\tx = MapCellWidth;\n\t\t\t}\n\t\t\ty = Cell_Y(trycell) - MapCellY;\n\n\t\t} else {\n\n\t\t\tvert = false;\n\t\t\thorz = true;\n\t\t\tif ((Cell_Y(trycell)-MapCellY) < MapCellHeight/2) {\n\t\t\t\ty = -1;\n\t\t\t} else {\n\t\t\t\ty = MapCellHeight;\n\t\t\t}\n\t\t\tx = Cell_X(trycell) - MapCellX;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf no map edge can be inferred from the waypoint, then go with the\n\t**\tmap edge specified by the edge parameter.\n\t*/\n\tif (!vert && !horz) {\n\t\tswitch (dir) {\n\t\t\tdefault:\n\t\t\tcase SOURCE_NORTH:\n\t\t\t\thorz = true;\n\t\t\t\ty = -1;\n\t\t\t\tx = Random_Pick(0, MapCellWidth-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_SOUTH:\n\t\t\t\thorz = true;\n\t\t\t\ty = MapCellHeight;\n\t\t\t\tx = Random_Pick(0, MapCellWidth-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_EAST:\n\t\t\t\tvert = true;\n\t\t\t\tx = MapCellWidth;\n\t\t\t\ty = Random_Pick(0, MapCellHeight-1);\n\t\t\t\tbreak;\n\n\t\t\tcase SOURCE_WEST:\n\t\t\t\tvert = true;\n\t\t\t\tx = -1;\n\t\t\t\ty = Random_Pick(0, MapCellHeight-1);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the default reinforcement cell if all else fails.\n\t*/\n\tpunt = XY_Cell(x + MapCellX, y + MapCellY);\n\n\t/*\n\t**\tScan through the vertical and horizontal edges of the map looking for\n\t**\ta relatively clear cell for object placement. The cell scanned is\n\t**\tfrom the edge position specified by the X and Y variables.\n\t*/\n\tif (vert) {\n\t\tint modifier = (x > MapCellX) ? -1 : 1;\n\n\t\tfor (int index = 0; index < MapCellHeight; index++) {\n\t\t\tCELL trycell = XY_Cell(x + MapCellX, ((y + index) % MapCellHeight) + MapCellY);\n\n\t\t\tif (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {\n\t\t\t\treturn(trycell);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (horz) {\n\t\tint modifier = (y > MapCellY) ? -MAP_CELL_W : MAP_CELL_W;\n\n\t\tfor (int index = 0; index < MapCellWidth; index++) {\n\t\t\tCELL trycell = XY_Cell(((x + index) % MapCellWidth) + MapCellX, y + MapCellY);\n\n\t\t\tif (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {\n\t\t\t\treturn(trycell);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there was no success in finding a suitable reinforcement edge cell, then return\n\t**\twith the default 'punt' cell location.\n\t*/\n\treturn(punt);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality.             *\n *                                                                                             *\n *    This routine will check the secified cell (given the specified conditions) and determine *\n *    if that is a good cell for reinforcement purposes. It checks for passability of the cell *\n *    as well as zone and whether blocking walls can be crushed.                               *\n *                                                                                             *\n * INPUT:   outcell  -- The cell that is just outside the edge of the map.                     *\n *                                                                                             *\n *          incell   -- The cell that is just inside the edge of the map.                      *\n *                                                                                             *\n *          loco     -- The locomotion type of the reinforcement.                              *\n *                                                                                             *\n *          zone     -- The zone that the eventual movement destination lies. A reinforcement  *\n *                      edge must fall within the same zone.                                   *\n *                                                                                             *\n *          mzone    -- The zone check type to check against (if zone checking required)       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified cell good for reinforcement purposes?                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Good_Reinforcement_Cell(CELL outcell, CELL incell, SpeedType loco, int zone, MZoneType mzone) const\n{\n\t/*\n\t**\tIf the map edge location is not clear for object placement, then this is not\n\t**\ta good cell for reinforcement purposes.\n\t*/\n\tif (!(*this)[outcell].Is_Clear_To_Move(loco, false, false)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it looks like the on-map cell cannot be driven on to, then return with\n\t**\tthe failure code.\n\t*/\n\tif (!(*this)[incell].Is_Clear_To_Move(loco, false, false, zone, mzone)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the reinforcement cell is already occupied, then return a failure code.\n\t*/\n\tif ((*this)[outcell].Cell_Techno() != NULL) {\n\t\treturn(false);\n\t}\n\tif ((*this)[incell].Cell_Techno() != NULL) return(false);\n\n\t/*\n\t**\tAll tests have passed, return with success code.\n\t*/\n//Mono_Printf(\"<%04X>\\n\", incell);Keyboard->Get();\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Select_These -- All selectable objects in region are selected.                *\n *                                                                                             *\n *    Use this routine to simultaneously select all objects within the coordinate region       *\n *    specified. This routine is used by the multi-select rubber band handler.                 *\n *                                                                                             *\n * INPUT:   coord1   -- Coordinate of one corner of the selection region.                      *\n *                                                                                             *\n *          coord2   -- The opposite corner of the selection region.                           *\n *                                                                                             *\n *          additive -- Does this add to the existing selection or replace it.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   04/25/1995 JLB : Limited to non-building type.                                            *\n *   03/06/1996 JLB : Allows selection of aircraft with bounding box.                          *\n *=============================================================================================*/\nstatic bool should_exclude_from_selection(ObjectClass* obj)\n{\n\treturn (obj->What_Am_I() == RTTI_UNIT) &&\n\t\t(((UnitClass *)obj)->Class->IsToHarvest ||\n\t\t*((UnitClass *)obj) == UNIT_MCV);\n}\n\nvoid DisplayClass::Select_These(COORDINATE coord1, COORDINATE coord2, bool additive)\n{\n\tCOORDINATE tcoord = TacticalCoord;\t//Cell_Coord(TacticalCell) & 0xFF00FF00L;\n\n\tcoord1 = Coord_Add(tcoord, coord1);\n\tcoord2 = Coord_Add(tcoord, coord2);\n\tint x1 = Coord_X(coord1);\n\tint x2 = Coord_X(coord2);\n\tint y1 = Coord_Y(coord1);\n\tint y2 = Coord_Y(coord2);\n\n\t/*\n\t**\tEnsure that coordinate number one represents the upper left corner\n\t**\tand coordinate number two represents the lower right corner.\n\t*/\n\tif (x1 > x2) {\n\t\tint temp = x1;\n\t\tx1 = x2;\n\t\tx2 = temp;\n\t}\n\tif (y1 > y2) {\n\t\tint temp = y1;\n\t\ty1 = y2;\n\t\ty2 = temp;\n\t}\n\n\t/*\n\t**\tSweep through all ground layer objects and select the ones within the\n\t**\tbounding box.\n\t*/\n\tif (!additive) {\n\t\tUnselect_All();\n\t}\n\tAllowVoice = true;\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * obj = Layer[LAYER_GROUND][index];\n\t\tCOORDINATE ocoord = obj->Center_Coord();\n\t\tint x = Coord_X(ocoord);\n\t\tint y = Coord_Y(ocoord);\n\n\t\t/*\n\t\t**\tOnly try to select objects that are allowed to be selected, and are within the bounding box.\n\t\t*/\n\t\tHouseClass * hptr = HouseClass::As_Pointer(obj->Owner());\n\t\tif (\tobj->Class_Of().IsSelectable &&\n\t\t\t\tobj->What_Am_I() != RTTI_BUILDING &&\n\t\t\t\t(!obj->Is_Techno() || !((TechnoClass*)obj)->Is_Cloaked(PlayerPtr)) &&\n\t\t\t\tx >= x1 && x <= x2 && y >= y1 && y <= y2) {\n\t\t\tbool old_allow_voice = AllowVoice;\n\t\t\tbool is_player_controlled = (hptr != NULL) && hptr->IsPlayerControl;\n\t\t\tAllowVoice &= is_player_controlled;\n\t\t\tif (obj->Select(true)) {\n\t\t\t\tif (is_player_controlled) {\n\t\t\t\t\told_allow_voice = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tAllowVoice = old_allow_voice;\n\t\t}\n\t}\n\n\t/*\n\t**\tSelect any aircraft with the bounding box.\n\t*/\n\tfor (int air_index = 0; air_index < Aircraft.Count(); air_index++) {\n\t\tAircraftClass * aircraft = Aircraft.Ptr(air_index);\n\t\tCOORDINATE ocoord = aircraft->Center_Coord();\n\t\tint x = Coord_X(ocoord);\n\t\tint y = Coord_Y(ocoord);\n\n\t\t/*\n\t\t**\tOnly try to select objects that are allowed to be selected, and are within the bounding box.\n\t\t*/\n\t\tif (\taircraft->Class->IsSelectable &&\n\t\t\t\t!aircraft->Is_Cloaked(PlayerPtr) &&\n\t\t\t\t!aircraft->Is_Selected_By_Player() &&\n\t\t\t\tx >= x1 && x <= x2 && y >= y1 && y <= y2) {\n\t\t\tbool old_allow_voice = AllowVoice;\n\t\t\tbool is_player_controlled = aircraft->House->IsPlayerControl;\n\t\t\tAllowVoice &= is_player_controlled;\n\t\t\tif (aircraft->Select(true)) {\n\t\t\t\tif (is_player_controlled) {\n\t\t\t\t\told_allow_voice = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tAllowVoice = old_allow_voice;\n\t\t}\n\t}\n\n\t/*\n\t** If a mix of player and non-player controlled units were selected, make sure non-player controlled units are de-selected\n\t*/\n\tbool player_controlled_units = false, non_player_controlled_units = false;\n\tfor (int i = 0; (i < CurrentObject.Count()) && (!player_controlled_units || !non_player_controlled_units); ++i) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(CurrentObject[i]->Owner());\n\t\tif (hptr->IsPlayerControl) {\n\t\t\tplayer_controlled_units = true;\n\t\t}\n\t\telse {\n\t\t\tnon_player_controlled_units = true;\n\t\t}\n\t}\n\tif (player_controlled_units && non_player_controlled_units) {\n\t\tfor (int i = 0; i < CurrentObject.Count(); ++i) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(CurrentObject[i]->Owner());\n\t\t\tif (!hptr->IsPlayerControl) {\n\t\t\t\tint count_before = CurrentObject.Count();\n\t\t\t\tCurrentObject[i]->Unselect();\n\t\t\t\tif (count_before <= CurrentObject.Count()) {\n\t\t\t\t\tGlyphX_Debug_Print(\"Select_These failed to remove an object\");\n\t\t\t\t\tCurrentObject.Delete(CurrentObject[i]);\n\t\t\t\t}\n\t\t\t\t--i;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** If player-controlled units are non-additively selected, remove harvesters and MCVs if they aren't the only types of units selected\n\t*/\n\tif (!additive && player_controlled_units) {\n\t\tbool any_to_exclude = false, all_to_exclude = true;\n\t\tfor (int i = 0; i < CurrentObject.Count(); ++i) {\n\t\t\tbool exclude = should_exclude_from_selection(CurrentObject[i]);\n\t\t\tany_to_exclude |= exclude;\n\t\t\tall_to_exclude &= exclude;\n\t\t}\n\t\tif (any_to_exclude && !all_to_exclude) {\n\t\t\tfor (int i = 0; i < CurrentObject.Count(); ++i) {\n\t\t\t\tif (should_exclude_from_selection(CurrentObject[i])) {\n\t\t\t\t\tint count_before = CurrentObject.Count();\n\t\t\t\t\tCurrentObject[i]->Unselect();\n\t\t\t\t\tif (count_before <= CurrentObject.Count()) {\n\t\t\t\t\t\tGlyphX_Debug_Print(\"Select_These failed to remove an object\");\n\t\t\t\t\t\tCurrentObject.Delete(CurrentObject[i]);\n\t\t\t\t\t}\n\t\t\t\t\t--i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tAllowVoice = true;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn.         *\n *                                                                                             *\n *    Use this routine to flag all cells that are covered in some fashion by the multi-unit    *\n *    select \"rubber band\" to be redrawn. This is necessary whenever the rubber band changes   *\n *    size or is being removed.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Refresh_Band(void)\n{\n\tif (IsRubberBand) {\n\n\t\t/*\n\t\t**\tIn rubber band mode, mark all cells under the \"rubber band\" to be\n\t\t**\tredrawn.\n\t\t*/\n\t\tint x1 = BandX+TacPixelX;\n\t\tint y1 = BandY+TacPixelY;\n\t\tint x2 = NewX+TacPixelX;\n\t\tint y2 = NewY+TacPixelY;\n\n\t\tif (x1 > x2) {\n\t\t\tint temp = x1;\n\t\t\tx1 = x2;\n\t\t\tx2 = temp;\n\t\t}\n\t\tif (y1 > y2) {\n\t\t\tint temp = y1;\n\t\t\ty1 = y2;\n\t\t\ty2 = temp;\n\t\t}\n\n\t\tCELL cell;\n\t\tfor (int y = y1; y <= y2+CELL_PIXEL_H; y += CELL_PIXEL_H) {\n\t\t\tcell = Click_Cell_Calc(x1, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\n\t\t\tcell = Click_Cell_Calc(x2, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\t\t}\n\n\t\tfor (int x = x1; x <= x2+CELL_PIXEL_W; x += CELL_PIXEL_W) {\n\t\t\tcell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y1);\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\n\t\t\tcell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y2);\n\t\t\tif (cell != -1) (*this)[cell].Redraw_Objects();\n\t\t}\n\n\t\t/*\n\t\t**\tStretching the rubber band requires all objects to be redrawn.\n\t\t*/\n\t\tint index;\n\t\tfor (index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t}\n\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::TacticalClass::Action -- Processes input for the tactical map.                *\n *                                                                                             *\n *    This routine handles the input directed at the tactical map. Since input, in this        *\n *    regard, includes even the presence of the mouse over the tactical map, this routine      *\n *    is called nearly every game frame. It handles adjusting the mouse shape as well as       *\n *    giving orders to units.                                                                  *\n *                                                                                             *\n * INPUT:   flags -- The gadget event flags that triggered the call to this function.          *\n *                                                                                             *\n *          key   -- A reference to the keyboard event (if any).                               *\n *                                                                                             *\n * OUTPUT:  bool; Should processing be aborted on any succeeding buttons in the chain?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint DisplayClass::TacticalClass::Action(unsigned flags, KeyNumType & key)\n{\n\tint\t\tx,y;\t\t\t\t\t// Sub cell pixel coordinates.\n\tbool\t\tshadow;\n\tObjectClass * object = 0;\n\tActionType action = ACTION_NONE;\t\t// Action possible with currently selected object.\n\n\t/*\n\t**\tSet some working variables that depend on the mouse position. For the press\n\t**\tor release event, special mouse queuing storage variables are used. Other\n\t**\tevents must use the current mouse position globals.\n\t*/\n\tif (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t} else {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\t}\n\tbool edge = (y == 0 || x == 0 || x == SeenBuff.Get_Width()-1 || y == SeenBuff.Get_Height()-1);\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\tif (coord) {\n\n\t\t//shadow = (!Map[cell].IsMapped && !Debug_Unshroud);\n\t\tshadow = (!Map[cell].Is_Mapped(PlayerPtr) && !Debug_Unshroud);\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 8/6/2019 10:49AM\n\t\tx -= Map.TacPixelX;\n\t\ty -= Map.TacPixelY;\n\n\t\t/*\n\t\t** Cause any displayed cursor to move along with the mouse cursor.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine the object that the mouse is currently over.\n\t\t*/\n\t\tif (!shadow) {\n\t\t\tobject = Map.Close_Object(coord);\n\n\t\t\t/*\n\t\t\t**\tSpecial case check to ignore cloaked object if not allied with the player.\n\t\t\t*/\n\t\t\tif (object != NULL && object->Is_Techno() && ((TechnoClass *)object)->Is_Cloaked(PlayerPtr, true)) {\n\t\t\t\tobject = NULL;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a currently selected object, then the action to perform if\n\t\t**\tthe left mouse button were clicked must be determined.\n\t\t*/\n\t\tif (CurrentObject.Count()) {\n\t\t\tif (object != NULL) {\n\t\t\t\taction = Best_Object_Action(object);\n\t\t\t} else {\n\t\t\t\taction = Best_Object_Action(cell);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif (object && object->Class_Of().IsSelectable) {\n\t\t\t\taction = ACTION_SELECT;\n\t\t\t}\n\n\t\t\tif (Map.IsRepairMode) {\n\t\t\t\tif (object && object->Owner() == PlayerPtr->Class->House && object->Can_Repair()) {\n\t\t\t\t\taction = ACTION_REPAIR;\n\t\t\t\t} else {\n\t\t\t\t\taction = ACTION_NO_REPAIR;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Map.IsSellMode) {\n\t\t\t\tif (object && object->Owner() == PlayerPtr->Class->House && object->Can_Demolish()) {\n\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\taction = ACTION_SELL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_SELL_UNIT;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCheck to see if the cursor is over an owned wall.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map[cell].Overlay != OVERLAY_NONE &&\n\t\t\t\t\t\tOverlayTypeClass::As_Reference(Map[cell].Overlay).IsWall &&\n\t\t\t\t\t\tMap[cell].Owner == PlayerPtr->Class->House) {\n\t\t\t\t\t\t\taction = ACTION_SELL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_NO_SELL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {\n\t\t\t\taction = ACTION_NUKE_BOMB;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_PARA_BOMB) {\n\t\t\t\taction = ACTION_PARA_BOMB;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_PARA_INFANTRY) {\n\t\t\t\taction = ACTION_PARA_INFANTRY;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_SPY_MISSION) {\n\t\t\t\taction = ACTION_SPY_MISSION;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_IRON_CURTAIN) {\n\t\t\t\taction = ACTION_IRON_CURTAIN;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE) {\n\t\t\t\taction = ACTION_CHRONOSPHERE;\n\t\t\t}\n\n\t\t\tif (Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\taction = ACTION_CHRONO2;\n\t\t\t\tif (shadow) action = ACTION_NOMOVE;\n\t\t\t\tObjectClass const * tobject = As_Object(PlayerPtr->UnitToTeleport);\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the object can be teleported to the destination cell.\n\t\t\t\t*/\n\t\t\t\tif (tobject != NULL && tobject->Is_Techno()) {\n\t\t\t\t\tTechnoClass const * uobject = (TechnoClass const *)tobject;\n\t\t\t\t\tif (!uobject->Can_Teleport_Here(cell)) {\n//\t\t\t\t\tif (((UnitClass *)As_Object(PlayerPtr->UnitToTeleport))->Can_Enter_Cell(cell, FACING_NONE) != MOVE_OK) {\n\t\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\t}\n\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\telse {\t// If the object is no longer valid, cancel targetting mode.\n\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tif (Map.PendingObject) {\n\t\t\t\taction = ACTION_NONE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tMove any cursor displayed.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\t/*\n\t\t**\tA right mouse button press cancels the current action or selection.\n\t\t*/\n\t\tif (flags & RIGHTPRESS) {\n\t\t\tMap.Mouse_Right_Press();\n\t\t}\n\n\t\t/*\n\t\t**\tMake sure that if the mouse button has been released and the map doesn't know about it,\n\t\t**\tthen it must be informed. Do this by faking a mouse release event.\n\t\t*/\n\t\tif ((flags & LEFTUP) && Map.IsRubberBand) {\n\t\t\tflags |= LEFTRELEASE;\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the mouse buttons aren't pressed, only the mouse cursor shape is processed.\n\t\t**\tThe shape changes depending on what object the mouse is currently over and what\n\t\t**\tobject is currently selected.\n\t\t*/\n\t\tif (!edge) {\n\t\t\tif (flags & LEFTUP) {\n\t\t\t\tMap.Mouse_Left_Up(cell, shadow, object, action);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tNormal actions occur when the mouse button is released. The press event is\n\t\t**\tintercepted and possible rubber-band mode is flagged.\n\t\t*/\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tMap.Mouse_Left_Release(cell, x, y, object, action);\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the mouse is first pressed on the map, then record the mouse\n\t\t**\tposition so that a proper check before going into rubber band\n\t\t**\tmode can be made. Rubber band mode starts when the mouse is\n\t\t**\theld down and moved a certain minimum distance.\n\t\t*/\n\t\tif (!edge && (flags & LEFTPRESS)) {\n\t\t\tMap.Mouse_Left_Up(cell, shadow, object, action);\n\t\t\tMap.Mouse_Left_Press(x, y);\n\t\t}\n\n\t\t/*\n\t\t**\tWhile the mouse is being held down, determine if rubber band mode should\n\t\t**\tstart. If rubber band mode is already active, then update the size\n\t\t**\tand flag the map to redraw it.\n\t\t*/\n\t\tif (flags & LEFTHELD) {\n\t\t\tMap.Mouse_Left_Held(x, y);\n\t\t}\n\t}\n\n\treturn(GadgetClass::Action(0, key));\n}\n\n\n/***********************************************************************************************\n * DisplayClass::TacticalClass::Selection_At_Mouse --  Object selection\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *     Selects any objects at the current mouse position.\t\t                                *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t        *\n *                                                                                             *\n * INPUT:   flags -- The gadget event flags that triggered the call to this function.          *\n *                                                                                             *\n *          key   -- A reference to the keyboard event (if any).                               *\n *                                                                                             *\n * OUTPUT:  bool; Should processing be aborted on any succeeding buttons in the chain?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   2019/09/17  JAS\t\t\t\t\t                                                              *\n *=============================================================================================*/\nint DisplayClass::TacticalClass::Selection_At_Mouse(unsigned flags, KeyNumType & key)\n{\n\tint\t\tx, y;\t\t\t\t\t// Sub cell pixel coordinates.\n\tbool edge = false;\n\tif (flags & (LEFTPRESS | LEFTRELEASE | RIGHTPRESS | RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t}\n\telse {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\n\t\tif (x == 0 || y == 199 || x == 319) edge = true;\n\t}\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tif (coord) {\n\t\tbool shadow = (!Map[cell].Is_Visible(PlayerPtr) && !Debug_Unshroud);\t\t\t\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 3/6/2019 2:49PM\n\t\tx -= Map.TacPixelX;\n\t\ty -= Map.TacPixelY;\n\n\t\t/*\n\t\t** Cause any displayed cursor to move along with the mouse cursor.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\tObjectClass* object = nullptr;\n\n\t\t/*\n\t\t**\tDetermine the object that the mouse is currently over.\n\t\t*/\n\t\tif (!shadow) {\n\t\t\tobject = Map.Close_Object(coord);\n\t\t}\n\n\t\tif (object != nullptr)\n\t\t{\n\t\t\tbool shiftdown = DLL_Export_Get_Input_Key_State(KN_LSHIFT);\n\n\t\t\tif (shiftdown)\n\t\t\t{\n\t\t\t\tMap.Mouse_Left_Release(cell, x, y, object, ACTION_TOGGLE_SELECT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tMap.Mouse_Left_Release(cell, x, y, object, ACTION_SELECT);\n\t\t\t}\n\n\t\t}\n\t\telse\n\t\t{\n\t\t\tUnselect_All();\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/***********************************************************************************************\n * DisplayClass::TacticalClass::Command_Object --  Commanding Units\t\t\t\t\t\t\t\t     *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *     Issues a command to the currently selected unit.\t\t\t                                *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t        *\n *                                                                                             *\n * INPUT:   flags -- The gadget event flags that triggered the call to this function.          *\n *                                                                                             *\n *          key   -- A reference to the keyboard event (if any).                               *\n *                                                                                             *\n * OUTPUT:  bool; Should processing be aborted on any succeeding buttons in the chain?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   2019/09/17  JAS\t\t\t\t\t                                                              *\n *=============================================================================================*/\nint DisplayClass::TacticalClass::Command_Object(unsigned flags, KeyNumType & key)\n{\n\tint\t\tx, y;\t\t\t\t\t// Sub cell pixel coordinates.\n\tbool edge = false;\n\tif (flags & (LEFTPRESS | LEFTRELEASE | RIGHTPRESS | RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t}\n\telse {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\n\t\tif (x == 0 || y == 199 || x == 319) edge = true;\n\t}\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tActionType action = ACTION_NONE;\n\n\tif (coord) {\n\t\tbool shadow = (!Map[cell].Is_Mapped(PlayerPtr) && !Debug_Unshroud);\t\t\t\t\t// Use PlayerPtr since we won't be rendering in MP. ST - 3/6/2019 2:49PM\n\t\tx -= Map.TacPixelX;\n\t\ty -= Map.TacPixelY;\n\n\t\t/*\n\t\t** Cause any displayed cursor to move along with the mouse cursor.\n\t\t*/\n\t\tif (cell != Map.ZoneCell) {\n\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t}\n\n\t\tObjectClass* object = nullptr;\n\n\t\t/*\n\t\t**\tDetermine the object that the mouse is currently over.\n\t\t*/\n\t\tif (!shadow) {\n\t\t\tobject = Map.Close_Object(coord);\n\t\t}\n\n\t\tif (CurrentObject.Count()) {\n\t\t\tif (object) {\n\t\t\t\taction = Best_Object_Action(object);\n\t\t\t}\n\t\t\telse {\n\t\t\t\taction = Best_Object_Action(cell);\n\t\t\t}\n\t\t}\n\n\t\tif (action != ACTION_SELECT)\n\t\t{\n\t\t\tMap.Mouse_Left_Release(cell, x, y, object, action);\n\t\t}\n\t}\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Right_Press -- Handles the right mouse button press.                    *\n *                                                                                             *\n *    This routine is called when the right mouse button is pressed. This action is supposed   *\n *    to cancel whatever mode or process is active. If there is nothing to cancel, then it     *\n *    will default to unselecting any units that might be currently selected.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Right_Press(void)\n{\n\tif (PendingObjectPtr && PendingObjectPtr->Is_Techno()) {\n\t\t//PendingObjectPtr->Transmit_Message(RADIO_OVER_OUT);\n\t\tPendingObjectPtr = 0;\n\t\tPendingObject = 0;\n\t\tPendingHouse = HOUSE_NONE;\n\t\tSet_Cursor_Shape(0);\n\t} else {\n\t\tif (IsRepairMode) {\n\t\t\tIsRepairMode = false;\n\t\t} else {\n\t\t\tif (IsSellMode) {\n\t\t\t\tIsSellMode = false;\n\t\t\t} else {\n\t\t\t\tif (IsTargettingMode != SPC_NONE) {\n\t\t\t\t\tIsTargettingMode = SPC_NONE;\n\t\t\t\t} else {\n\t\t\t\t\tUnselect_All();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If it breaks... call 228.\n\tSet_Default_Mouse(MOUSE_NORMAL, Map.IsSmall);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Up -- Handles the left mouse \"cruising\" over the map.              *\n *                                                                                             *\n *    This routine is called continuously while the mouse is over the tactical map but there   *\n *    are no mouse buttons pressed. Typically, this adjusts the mouse shape and the pop-up     *\n *    help text.                                                                               *\n *                                                                                             *\n * INPUT:   shadow   -- Is the mouse hovering over shadowed terrain?                           *\n *                                                                                             *\n *          object   -- Pointer to the object that the mouse is currently over (may be NULL).  *\n *                                                                                             *\n *          action   -- This is the action that the currently selected object (if any) will    *\n *                      perform if the left mouse button were clicked at this location.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *   07/05/1995 JLB : Removed pop up help text for shadow and terrain after #3.                *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Up(CELL cell, bool shadow, ObjectClass * object, ActionType action, bool wsmall)\n{\n\tIsTentative = false;\n\n\tTARGET target = TARGET_NONE;\n\tif (object != NULL) {\n\t\ttarget = object->As_Target();\n\t} else {\n\t\tif (cell != -1) {\n\t\t\ttarget = As_Target(cell);\n\t\t}\n\t}\n\n\t/*\n\t**\tDon't allow selection of an object that is located in shadowed terrain.\n\t**\tIn fact, just show the normal move cursor in order to keep the shadowed\n\t**\tterrain a mystery.\n\t*/\n\tif (shadow) {\n\t\tswitch (action) {\n\t\t\tcase ACTION_NO_DEPLOY:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_ENTER:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_DAMAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GUARD_AREA:\n\t\t\t\tSet_Default_Mouse(MOUSE_AREA_GUARD, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NONE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_SELL:\n\t\t\tcase ACTION_SELL:\n\t\t\tcase ACTION_SELL_UNIT:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_REPAIR:\n\t\t\tcase ACTION_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NUKE_BOMB:\n\t\t\t\tSet_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_AIR_STRIKE:\n\t\t\tcase ACTION_PARA_BOMB:\n\t\t\tcase ACTION_PARA_INFANTRY:\n\t\t\tcase ACTION_SPY_MISSION:\n\t\t\tcase ACTION_IRON_CURTAIN:\n\t\t\t\tSet_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONOSPHERE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONO2:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_HEAL:\n\t\t\t\tSet_Default_Mouse(MOUSE_HEAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NOMOVE:\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tMouseType mouse_type = MOUSE_NO_MOVE;\n\t\t\t\t\tfor (int i = 0; i < CurrentObject.Count(); ++i) {\n\t\t\t\t\t\tif (CurrentObject[i]->What_Am_I() != RTTI_AIRCRAFT) {\n\t\t\t\t\t\t\tmouse_type = MOUSE_CAN_MOVE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tSet_Default_Mouse(mouse_type, wsmall);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Fall into next case for non aircraft object types.\n\n\t\t\tdefault:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tChange the mouse shape according to the default action that will occur\n\t\t**\tif the mouse button were clicked at this location.\n\t\t*/\n\t\tswitch (action) {\n\t\t\tcase ACTION_NO_DEPLOY:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_ENTER:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_DAMAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_DAMAGE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GREPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_GREPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_TOGGLE_SELECT:\n\t\t\tcase ACTION_SELECT:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_MOVE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_GUARD_AREA:\n\t\t\t\tSet_Default_Mouse(MOUSE_AREA_GUARD, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_ATTACK:\n\t\t\t\tif (Target_Legal(target) && CurrentObject.Count() == 1 && CurrentObject[0]->Is_Techno() && ((TechnoClass *)CurrentObject[0])->In_Range(target, 0)) {\n\t\t\t\t\tSet_Default_Mouse(MOUSE_STAY_ATTACK, wsmall);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// fall into next case.\n\n\t\t\tcase ACTION_HARVEST:\n\t\t\t\tSet_Default_Mouse(MOUSE_CAN_ATTACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SABOTAGE:\n\t\t\t\tSet_Default_Mouse(MOUSE_DEMOLITIONS, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_ENTER:\n\t\t\tcase ACTION_CAPTURE:\n\t\t\t\tSet_Default_Mouse(MOUSE_ENTER, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NOMOVE:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_MOVE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_SELL:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NO_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_NO_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELF:\n\t\t\t\tSet_Default_Mouse(MOUSE_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_REPAIR:\n\t\t\t\tSet_Default_Mouse(MOUSE_REPAIR, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELL_UNIT:\n\t\t\t\tSet_Default_Mouse(MOUSE_SELL_UNIT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_SELL:\n\t\t\t\tSet_Default_Mouse(MOUSE_SELL_BACK, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_NUKE_BOMB:\n\t\t\t\tSet_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_AIR_STRIKE:\n\t\t\tcase ACTION_PARA_BOMB:\n\t\t\tcase ACTION_PARA_INFANTRY:\n\t\t\tcase ACTION_SPY_MISSION:\n\t\t\tcase ACTION_IRON_CURTAIN:\n\t\t\t\tSet_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONOSPHERE:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CHRONO2:\n\t\t\t\tSet_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_HEAL:\n\t\t\t\tSet_Default_Mouse(MOUSE_HEAL, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_TOGGLE_PRIMARY:\n\t\t\t\tSet_Default_Mouse(MOUSE_DEPLOY, wsmall);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\tbreak;\n\t\t}\n\t}\n#if 0\n\t/*\n\t**\tNever display help text if the mouse is held over the radar map.\n\t*/\n\tif (wsmall) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGive a generic help message when over shadow terrain.\n\t*/\n\tif (shadow) {\n//\t\tif (Scen.Scenario < 4) {\n\t\t\tHelp_Text(TXT_SHADOW);\n//\t\t} else {\n//\t\t\tHelp_Text(TXT_NONE);\n//\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the mouse is held over objects on the map, then help text may\n\t\t**\tpop up that tells what the object is. This call informs the help\n\t\t**\tsystem of the text name for the object under the mouse.\n\t\t*/\n\t\tif (object != NULL) {\n\t\t\tint text;\n\t\t\tint color = LTGREY;\n\n\t\t\t/*\n\t\t\t**\tFetch the appropriate background color for help text.\n\t\t\t*/\n\t\t\tif (PlayerPtr->Is_Ally(object)) {\n\t\t\t\tcolor = GREEN;\n\t\t\t} else {\n\t\t\t\tif (object->Owner() == HOUSE_NONE || object->Owner() == HOUSE_NEUTRAL) {\n\t\t\t\t\tcolor = LTGREY;\n\t\t\t\t} else {\n\t\t\t\t\tcolor = PINK;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch the name of the object. If it is an enemy object, then\n\t\t\t**\tthe exact identity is glossed over with a generic text.\n\t\t\t*/\n\t\t\ttext = object->Full_Name();\n\t\t\tif (object->Is_Techno() && !((TechnoTypeClass const &)object->Class_Of()).IsNominal) {\n\n\t\t\t\tif (!((TechnoClass *)object)->House->Is_Ally(PlayerPtr)) {\n//\t\t\t\tif (!PlayerPtr->Is_Ally(object)) {\n\t\t\t\t\tswitch (object->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_SOLDIER;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_VEHICLE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\ttext = TXT_ENEMY_STRUCTURE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (/*Scen.Scenario > 3 ||*/ object->What_Am_I() != RTTI_TERRAIN) {\n\t\t\t\tHelp_Text(text, -1, -1, color);\n\t\t\t} else {\n\t\t\t\tHelp_Text(TXT_NONE);\n\t\t\t}\n\t\t} else {\n\t\t\tif ((*this)[cell].Land_Type() == LAND_TIBERIUM) {\n\t\t\t\tHelp_Text(TXT_MINERALS);\n\t\t\t} else {\n\t\t\t\tHelp_Text(TXT_NONE);\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Release -- Handles the left mouse button release.                  *\n *                                                                                             *\n *    This routine is called when the left mouse button is released over the tactical map.     *\n *    The release event is the workhorse of the game. Most actions occur at the moment of      *\n *    mouse release.                                                                           *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the mouse is over.                                       *\n *                                                                                             *\n *          x,y      -- The mouse pixel coordinate.                                            *\n *                                                                                             *\n *          object   -- Pointer to the object that the mouse is over.                          *\n *                                                                                             *\n *          action   -- The action that the currently selected object (if any) will            *\n *                      perform.                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *   03/27/1995 JLB : Handles sell and repair actions.                                         *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Release(CELL cell, int x, int y, ObjectClass * object, ActionType action, bool wsmall)\n{\n\tif (PendingObjectPtr) {\n\t\t/*\n\t\t**\tTry to place the pending object onto the map.\n\t\t*/\n\t\tif (ProximityCheck) {\n\t\t\tOutList.Add(EventClass(EventClass::PLACE, PendingObjectPtr->What_Am_I(), cell + ZoneOffset));\n\t\t} else {\n\t\t\tSpeak(VOX_DEPLOY);\n\t\t}\n\n\t} else {\n\n\t\tif (IsRubberBand) {\n\t\t\tRefresh_Band();\n\t\t\tSelect_These(XYP_Coord(BandX, BandY), XYP_Coord(x, y));\n\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\tIsRubberBand = false;\n\t\t\tIsTentative = false;\n\t\t\tMap.DisplayClass::IsToRedraw = true;\n\t\t\tMap.Flag_To_Redraw(false);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tToggle the select state of the object.\n\t\t\t*/\n\t\t\tif (action == ACTION_TOGGLE_SELECT) {\n\t\t\t\tif (!object || !CurrentObject.Count()) {\n\t\t\t\t\taction = ACTION_SELECT;\n\t\t\t\t} else {\n\t\t\t\t\tif (object->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobject->Unselect();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobject->Select();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSelection of other object action.\n\t\t\t*/\n\t\t\tif (action == ACTION_SELECT || (action == ACTION_NONE && object && object->Class_Of().IsSelectable && !object->Is_Selected_By_Player())) {\n\t\t\t\tif (object->Is_Selected_By_Player()) {\n\t\t\t\t\tobject->Unselect();\n\t\t\t\t}\n\t\t\t\tif (object->Select()) {\n\t\t\t\t\tUnselect_All_Except(object);\n\t\t\t\t\tSet_Default_Mouse(MOUSE_NORMAL, wsmall);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf an action was detected as possible, then pass this action event\n\t\t\t**\tto all selected objects.\n\t\t\t*/\n\t\t\tif (action != ACTION_NONE && action != ACTION_SELECT && action != ACTION_TOGGLE_SELECT) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPass the action to all the selected objects. But first, redetermine\n\t\t\t\t**\twhat action that object should perform. This, seemingly redundant\n\t\t\t\t**\tprocess, is necessary since multiple objects could be selected and each\n\t\t\t\t**\tmight perform a different action when the click occurs.\n\t\t\t\t*/\n\t\t\t\tbool doflash = true;\n\t\t\t\tAllowVoice = true;\n\t\t\t\tFormMove = false;\n\t\t\t\tFormSpeed = SPEED_WHEEL;\n\t\t\t\tFormMaxSpeed = MPH_LIGHT_SPEED;\n\n\t\t\t\tif ( (action == ACTION_MOVE || action == ACTION_NOMOVE) && CurrentObject.Count()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Scan all units.  If any are selected that shouldn't be, or aren't\n\t\t\t\t\t** selected but should be, then this is not a formation move.\n\t\t\t\t\t*/\n\t\t\t\t\tint group = 254;\t// init to invalid group #\n\n\t\t\t\t\tif (CurrentObject[0]->Is_Foot()) {\n\t\t\t\t\t\tgroup = ((FootClass *)CurrentObject[0])->Group;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPresume this is a formation move unless something is detected\n\t\t\t\t\t**\tthat will prevent it.\n\t\t\t\t\t*/\n\t\t\t\t\tFormMove = true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFirst scan through all the selected units to make sure that they\n\t\t\t\t\t**\tare all of the same team and have been assigned a particular formation\n\t\t\t\t\t*/\n\t\t\t\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\t\t\tObjectClass const * tobject = CurrentObject[index];\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tOnly moveable (i.e., FootClass) objects can ever be in a formation\n\t\t\t\t\t\t**\tso if a selected object isn't of a FootClass type then it can't be\n\t\t\t\t\t\t**\ta formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (tobject->Is_Foot() == false) {\n\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf the object is not part of the same team as the rest of the\n\t\t\t\t\t\t**\tselected group, or it just plain has never been assigned a\n\t\t\t\t\t\t**\tformation offset, then it can't be a formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tFootClass const * foot = (FootClass *)tobject;\n\t\t\t\t\t\tif (foot->Group != group || foot->XFormOffset == 0x80000000) {\n\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetermine the formation speed on the presumption that this\n\t\t\t\t\t\t**\twill turn out to be a formation move.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMPHType maxspeed = foot->Techno_Type_Class()->MaxSpeed;\n\t\t\t\t\t\tif (maxspeed < FormMaxSpeed) {\n\t\t\t\t\t\t\tFormMaxSpeed = maxspeed;\n\t\t\t\t\t\t\tFormSpeed = foot->Techno_Type_Class()->Speed;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLoop through all objects (that can theoretically be part of a team) and\n\t\t\t\t\t**\tif there are any that are part of the currently selected team, but\n\t\t\t\t\t**\tare not currently selected themselves, then this will force this move\n\t\t\t\t\t**\tto NOT be a formation move.\n\t\t\t\t\t*/\n\t\t\t\t\tif (FormMove) {\n\t\t\t\t\t\tfor (int index = 0; index < ::Logic.Count(); index++) {\n\t\t\t\t\t\t\tObjectClass const * obj = ::Logic[index];\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the object is selected, then it has already been scanned\n\t\t\t\t\t\t\t**\tby the previous loop.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (obj->Is_Selected_By_Player()) continue;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tOnly consider footclass objects.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!obj->Is_Foot()) continue;\n\n\t\t\t\t\t\t\tFootClass const * foot = (FootClass *)obj;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tOnly consider objects that are owned by the player.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!foot->Is_Owned_By_Player()) continue;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf another member of this team has been discovered and\n\t\t\t\t\t\t\t**\tit isn't selected, then the formation move cannot take\n\t\t\t\t\t\t\t**\tplace.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (foot->Group == group) {\n\t\t\t\t\t\t\t\tFormMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\t\t\tObjectClass * tobject = CurrentObject[index];\n\n\t\t\t\t\tif (object != NULL) {\n\t\t\t\t\t\ttobject->Active_Click_With(tobject->What_Action(object), object);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Trap for formation moves: if this unit is part of a\n\t\t\t\t\t\t** formation (being part of a team qualifies) and they're\n\t\t\t\t\t\t** told to move, adjust the target destination so they stay\n\t\t\t\t\t\t** in formation when they arrive.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL newmove = cell;\n\t\t\t\t\t\tint whatami = tobject->What_Am_I();\n\t\t\t\t\t\tif (action == ACTION_MOVE && tobject->Is_Foot()) {\n\t\t\t\t\t\t\tint oldisform;\n\t\t\t\t\t\t\tFootClass * foot = (FootClass *)tobject;\n\t\t\t\t\t\t\toldisform = foot->IsFormationMove;\n\t\t\t\t\t\t\tfoot->IsFormationMove = FormMove;\n\t\t\t\t\t\t\tif (FormMove && foot->Group != 255 ) {\n\t\t\t\t\t\t\t\tnewmove = foot->Adjust_Dest(cell);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfoot->IsFormationMove = oldisform;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttobject->Active_Click_With(tobject->What_Action(cell), newmove);\n\t\t\t\t\t}\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\tAllowVoice = true;\n\t\t\t\tFormMove = false;\n\n\t\t\t\tif (action == ACTION_REPAIR && object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::REPAIR, TargetClass(object)));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SELL_UNIT && object) {\n\t\t\t\t\tswitch (object->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(object)));\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SELL) {\n\t\t\t\t\tif (object) {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, TargetClass(object)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELLCELL, cell));\n//\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SELL, ::As_Target(cell)));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (action == ACTION_NUKE_BOMB) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_NUCLEAR_BOMB, cell));\n\t\t\t\t}\n\n\t\t\t\tif (action == ACTION_PARA_BOMB) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_BOMB, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_PARA_INFANTRY) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_INFANTRY, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_SPY_MISSION) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_SPY_MISSION, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_IRON_CURTAIN) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_IRON_CURTAIN, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_CHRONOSPHERE) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONOSPHERE, cell));\n\t\t\t\t}\n\t\t\t\tif (action == ACTION_CHRONO2) {\n\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONO2, cell));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tIsTentative = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Press -- Handles the left mouse button press.                      *\n *                                                                                             *\n *    Handle the left mouse button press while over the tactical map. If it isn't is           *\n *    repair or sell mode, then a tentative transition to rubber band mode is flagged. If the  *\n *    mouse moves a sufficient distance from this recorded position, then rubber band mode     *\n *    is officially started.                                                                   *\n *                                                                                             *\n * INPUT:   x,y   -- The mouse coordinates at the time of the press.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Press(int x, int y)\n{\n\tif (!IsRepairMode && !IsSellMode && IsTargettingMode == SPC_NONE && !PendingObject) {\n\t\tIsTentative = true;\n\t\tBandX = x;\n\t\tBandY = y;\n\t\tNewX = x;\n\t\tNewY = y;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Mouse_Left_Held -- Handles the left button held down.                         *\n *                                                                                             *\n *    This routine is called continuously while the left mouse button is held down over        *\n *    the tactical map. This handles the rubber band mode detection and dragging.              *\n *                                                                                             *\n * INPUT:   x,y   -- The mouse coordinate.                                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Mouse_Left_Held(int x, int y)\n{\n\tif (IsRubberBand) {\n\t\tif (x != NewX || y != NewY) {\n\t\t\tx = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);\n\t\t\ty = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);\n\t\t\tRefresh_Band();\n\t\t\tNewX = x;\n\t\t\tNewY = y;\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf the mouse is still held down while a tentative extended select is possible, then\n\t\t**\tcheck to see if the mouse has moved a sufficient distance in order to activate\n\t\t**\textended select mode.\n\t\t*/\n\t\tif (IsTentative) {\n\n\t\t\t/*\n\t\t\t**\tThe mouse must have moved a minimum distance before rubber band mode can be\n\t\t\t**\tinitiated.\n\t\t\t*/\n\t\t\tif (ABS(x - BandX) > 4 || ABS(y - BandY) > 4) {\n\t\t\t\tIsRubberBand = true;\n\t\t\t\tx = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);\n\t\t\t\ty = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);\n\t\t\t\tNewX = x;\n\t\t\t\tNewY = y;\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\n\t\t\t\t/*\n\t\t\t\t**\tStretching the rubber band requires all objects to be redrawn.\n\t\t\t\t*/\n\t\t\t\tint index;\n\t\t\t\tfor (index = 0; index < Layer[LAYER_TOP].Count(); index++) {\n\t\t\t\t\tLayer[LAYER_TOP][index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tfor (index = 0; index < Layer[LAYER_AIR].Count(); index++) {\n\t\t\t\t\tLayer[LAYER_AIR][index]->Mark(MARK_CHANGE);\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n// Needed to accomodate Glyphx client sidebar. ST - 4/12/2019 5:29PM\nextern int GlyphXClientSidebarWidthInLeptons;\n\n/***********************************************************************************************\n * DisplayClass::Set_Tactical_Position -- Sets the tactical view position.                     *\n *                                                                                             *\n *    This routine is used to set the tactical view position. The requested position is        *\n *    clipped to the map dimensions as necessary.                                              *\n *                                                                                             *\n * INPUT:   coord -- The coordinate desired for the upper left corner.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Set_Tactical_Position(COORDINATE coord)\n{\n\t/*\n\t**\tBound the desired location to fit the legal map edges.\n\t*/\n\tint xx = 0;// (int)Coord_X(coord) - (int)Cell_To_Lepton(MapCellX);\n\tint yy = 0;// (int)Coord_Y(coord) - (int)Cell_To_Lepton(MapCellY);\n\n\tConfine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth) + GlyphXClientSidebarWidthInLeptons, Cell_To_Lepton(MapCellHeight));\t\t// Needed to accomodate Glyphx client sidebar. ST - 4/12/2019 5:29PM\n//\tConfine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));\n\tcoord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));\n\n\tif (ScenarioInit) {\n\t\tTacticalCoord = coord;\n\t}\n\tDesiredTacticalCoord = coord;\n\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords.            *\n *                                                                                             *\n * Use this function in multiplayer games, to compute the scenario starting Tactical Pos.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  x, y -- Player starting location                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/28/1995 JLB : Commented.                                                               *\n *   06/26/1995 JLB : Fixed building loop.                                                     *\n *   10/20/1996 JLB : Doesn't wrap.                                                            *\n *=============================================================================================*/\nvoid DisplayClass::Compute_Start_Pos(long& x, long& y)\n{\n\t/*\n\t**\tFind the summation cell-x & cell-y for all the player's units, infantry,\n\t**\tand buildings.  Buildings are weighted so that they count 16 times more\n\t**\tthan units or infantry.\n\t*/\n\tx = 0;\n\ty = 0;\n\tlong num = 0;\n\tint i;\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tInfantryClass * infp = Infantry.Ptr(i);\n\t\tif (!infp->IsInLimbo && infp->Is_Owned_By_Player()) {\n\t\t\tx += (long)Coord_XCell(infp->Coord);\n\t\t\ty += (long)Coord_YCell(infp->Coord);\n\t\t\tnum++;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Units.Count(); i++) {\n\t\tUnitClass * unitp = Units.Ptr(i);\n\t\tif (!unitp->IsInLimbo && unitp->Is_Owned_By_Player()) {\n\t\t\tx += (long)Coord_XCell(unitp->Coord);\n\t\t\ty += (long)Coord_YCell(unitp->Coord);\n\t\t\tnum++;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tBuildingClass * bldgp = Buildings.Ptr(i);\n\t\tif (!bldgp->IsInLimbo && bldgp->Is_Owned_By_Player()) {\n\t\t\tx += (((long)Coord_XCell(bldgp->Coord)) * 16);\n\t\t\ty += (((long)Coord_YCell(bldgp->Coord)) * 16);\n\t\t\tnum += 16;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\tVesselClass * bldgp = Vessels.Ptr(i);\n\t\tif (!bldgp->IsInLimbo && bldgp->Is_Owned_By_Player()) {\n\t\t\tx += (((long)Coord_XCell(bldgp->Coord)));\n\t\t\ty += (((long)Coord_YCell(bldgp->Coord)));\n\t\t\tnum++;\n\t\t}\n\t}\n\n\t/*\n\t**\tDivide each coord by 'num' to compute the average value\n\t*/\n\tif (num > 0) {\n\t\tx /= num;\n\t} else {\n\t\tx = 0;\n\t}\n\n\tif (num > 0) {\n\t\ty /= num;\n\t} else {\n\t\ty = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Sell_Mode_Control -- Controls the sell mode.                                  *\n *                                                                                             *\n *    This routine will control the sell mode for the player.                                  *\n *                                                                                             *\n * INPUT:   control  -- The mode to set the sell state to.                                     *\n *                      0  = Turn sell mode off.                                               *\n *                      1  = Turn sell mode on.                                                *\n *                      -1 = Toggle sell mode.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Sell_Mode_Control(int control)\n{\n\tbool mode = IsSellMode;\n\tswitch (control) {\n\t\tcase 0:\n\t\t\tmode = false;\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tmode = (IsSellMode == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tmode = true;\n\t\t\tbreak;\n\t}\n\n\tif (mode != IsSellMode && !PendingObject) {\n\t\tIsRepairMode = false;\n\t\tif (mode && PlayerPtr->BScan) {\n\t\t\tIsSellMode = true;\n\t\t\tUnselect_All();\n\t\t} else {\n\t\t\tIsSellMode = false;\n\t\t\tRevert_Mouse_Shape();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Repair_Mode_Control -- Controls the repair mode.                              *\n *                                                                                             *\n *    This routine is used to control the repair mode for the player.                          *\n *                                                                                             *\n * INPUT:   control  -- The mode to set the repair to.                                         *\n *                      0 = Turn repair off.                                                   *\n *                      1 = Turn repair on.                                                    *\n *                      -1= Toggle repair state.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Repair_Mode_Control(int control)\n{\n\tbool mode = IsRepairMode;\n\tswitch (control) {\n\t\tcase 0:\n\t\t\tmode = false;\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tmode = (IsRepairMode == false);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tmode = true;\n\t\t\tbreak;\n\t}\n\n\tif (mode != IsRepairMode && !PendingObject) {\n\t\tIsSellMode = false;\n\t\tif (mode && PlayerPtr->BScan) {\n\t\t\tIsRepairMode = true;\n\t\t\tUnselect_All();\n\t\t} else {\n\t\t\tIsRepairMode = false;\n\t\t\tRevert_Mouse_Shape();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::In_View -- Determines if cell is visible on screen.                           *\n *                                                                                             *\n *    Use this routine to determine if the specified cell is visible on                        *\n *    the display. This is a useful fact, since many display operations                        *\n *    can be skipped if the cell is not visible.                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to check.                                                 *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell visible on the display?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/30/1994 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nbool DisplayClass::In_View(register CELL cell) const\n{\n\tif (cell & 0xC000) return(false);\n\n\tCOORDINATE coord = Coord_Whole(Cell_Coord(cell));\n\tCOORDINATE tcoord = Coord_Whole(TacticalCoord);\n\n\tif ((Coord_X(coord) - Coord_X(tcoord)) > TacLeptonWidth+CELL_LEPTON_W-1) return(false);\n\tif ((Coord_Y(coord) - Coord_Y(tcoord)) > TacLeptonHeight+CELL_LEPTON_H-1) return(false);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free.            *\n *                                                                                             *\n *    Use this routine to find the sub cell spot closest to the coordinate specified that is   *\n *    free from occupation. Typical use of this is for infantry destination calculation.       *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to use as the starting point when finding the closest      *\n *                   free spot.                                                                *\n *                                                                                             *\n *          any   -- Ignore occupation and just return the closest sub cell spot?              *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate of the closest free (possibly) sub cell location.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE DisplayClass::Closest_Free_Spot(COORDINATE coord, bool any) const\n{\n\tif (coord & HIGH_COORD_MASK) {\n\t\treturn(0x00800080);\n\t}\n\treturn Map[coord].Closest_Free_Spot(coord, any);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation.            *\n *                                                                                             *\n *    Use this routine to determine if the coordinate (rounded to the nearest sub cell         *\n *    position) is free for placement. Typical use of this would be for infantry placement.    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine for \"freeness\". The coordinate is rounded to    *\n *          the nearest free sub cell spot.                                                    *\n *                                                                                             *\n * OUTPUT:  Is the sub spot indicated by the coordinate free from previous occupation?         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DisplayClass::Is_Spot_Free(COORDINATE coord) const\n{\n\t// This can't be right. Copy/paste error, maybe? ST - 5/8/2019\n\t//if (coord & HIGH_COORD_MASK) {\n\t//\treturn(0x00800080);\n\t//}\n\treturn Map[coord].Is_Spot_Free(CellClass::Spot_Index(coord));\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Center_Map -- Centers the map about the currently selected objects            *\n *                                                                                             *\n *    This routine will average the position of all the selected objects and then center       *\n *    the map about those objects.                                                             *\n *                                                                                             *\n * INPUT:   center   -- The is an optional center about override coordinate. If specified,     *\n *                      then the map will be centered about that coordinate. Otherwise it      *\n *                      will center about the average location of all selected objects.        *\n *                                                                                             *\n * OUTPUT:  The center coordinate.                                                             *\n *                                                                                             *\n * WARNINGS:   The map position changes by this routine.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/22/1995 JLB : Created.                                                                 *\n *   09/16/1996 JLB : Takes coordinate to center about (as override).                          *\n *=============================================================================================*/\nCOORDINATE DisplayClass::Center_Map(COORDINATE center)\n{\n \tint x = 0;\n//\tunsigned x = 0;\n \tint y = 0;\n//\tunsigned y = 0;\n\tbool centerit = false;\n\n\tif (CurrentObject.Count()) {\n\n\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\tCOORDINATE coord = CurrentObject[index]->Center_Coord();\n\n\t\t\tx += Coord_X(coord);\n\t\t\ty += Coord_Y(coord);\n\t\t}\n\n\t\tx /= CurrentObject.Count();\n\t\ty /= CurrentObject.Count();\n\t\tcenterit = true;\n\t}\n\n\tif (center != 0L) {\n\t\tx = Coord_X(center);\n\t\ty = Coord_Y(center);\n\t\tcenterit = true;\n\t}\n\n\tif (centerit) {\n\t\tcenter = XY_Coord(x, y);\n\n\t\tx = x - (int)TacLeptonWidth/2;\n\t\tif (x < Cell_To_Lepton(MapCellX)) x = Cell_To_Lepton(MapCellX);\n\n\t\ty = y - (int)TacLeptonHeight/2;\n\t\tif (y < Cell_To_Lepton(MapCellY)) y = Cell_To_Lepton(MapCellY);\n\n\t\tSet_Tactical_Position(XY_Coord(x, y));\n\n\t\treturn center;\n\t}\n\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell.               *\n *                                                                                             *\n *    This routine will cause the shadow to creep back by one cell. Multiple calls to this     *\n *    routine will result in the shadow becoming more and more invasive until only the sight   *\n *    range of player controlled units will keep the shadow pushed back.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *          house -- Player to apply shroud to                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 JLB : Created.                                                                 *\n *   08/06/2019  ST: Added house parameter for multiplayer                                     *\n *=============================================================================================*/\nvoid DisplayClass::Encroach_Shadow(HouseClass * house)\n{\n\tCELL cell;\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (!In_Radar(cell)) continue;\n\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tif (cellptr->Is_Visible(house) || !cellptr->Is_Mapped(house)) continue;\n\n\t\tcellptr->IsToShroud = true;\t\t// IsToShroud isn't used outside this function. ST - 8/6/2019 2:28PM\n\t}\n\n\t/*\n\t**\tMark all shadow edge cells to be fully shrouded. All adjacent mapped\n\t**\tcell should become partially shrouded.\n\t*/\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (!In_Radar(cell)) continue;\n\n\t\tif ((*this)[cell].IsToShroud) {\n\t\t\t(*this)[cell].IsToShroud = false;\n\t\t\tShroud_Cell(cell, house);\n\t\t}\n\t}\n\n\tAll_To_Look(house);\n\n\tFlag_To_Redraw(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition.        *\n *                                                                                             *\n *    This routine is called to add the shroud back to the cell specified. Typical of this     *\n *    would be when the shroud is to regenerate.                                               *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the shroud is to be regenerated upon.                       *\n *          house -- Player to apply shroud to                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Adjacent cells might be affected by this routine. The affect is determined      *\n *             according to the legality of the partial shadow artwork. In the illegal cases   *\n *             the adjacent cell might become shrouded as well.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 JLB : Created.                                                                 *\n *   06/17/1996 JLB : Modified to handle the new shadow pieces.                                *\n *   08/06/2019  ST: Added house parameter for multiplayer                                     *\n *=============================================================================================*/\nvoid DisplayClass::Shroud_Cell(CELL cell, HouseClass * house)\n{\n\tif (house->IsGPSActive) {\n\t\tif ( (*this)[cell].Is_Jamming(house)  ) {\n\t\t\treturn;\n\t\t}\n\t}\n\tif (!In_Radar(cell)) return;\n\n\tCellClass * cellptr = &(*this)[cell];\n\tif (cellptr->Is_Mapped(house)) {\n\n\t\tcellptr->Set_Mapped(house, false);\n\t\tcellptr->Set_Visible(house, false);\n\t\tcellptr->Redraw_Objects();\n\n\t\t/*\n\t\t**\tCheck adjacent cells. There might be some weird combination of\n\t\t**\tshrouded cells such that more cells must be shrouded in order for\n\t\t**\tthis to work.\n\t\t*/\n\t\tfor (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {\n\t\t\tCELL c = Adjacent_Cell(cell, dir);\n\t\t\tCellClass * cptr = &(*this)[c];\n\n\t\t\t/*\n\t\t\t**\tIf this adjacent cell must be completely shrouded as a result\n\t\t\t**\tof the map change, yet it isn't already shrouded, then recursively\n\t\t\t**\tshroud that cell.\n\t\t\t*/\n\t\t\tif (c != cell) {\n\t\t\t\tcptr->Set_Visible(house, false);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAlways redraw the cell because, more than likely, the shroud\n\t\t\t**\tedge will change shape because of the map change.\n\t\t\t*/\n\t\t\tcptr->Redraw_Objects();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Read_INI -- Reads map control data from INI file.                             *\n *                                                                                             *\n *    This routine is used to read the map control data from the INI                           *\n *    file.                                                                                    *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded INI file data.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The TriggerClass INI data must have been read before calling this function.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Read_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tRead the map dimensions.\n\t*/\n\tchar const * const name = \"Map\";\n\tint x = ini.Get_Int(name, \"X\", 1);\n\tint y = ini.Get_Int(name, \"Y\", 1);\n\tint w = ini.Get_Int(name, \"Width\", MAP_CELL_W-2);\n\tint h = ini.Get_Int(name, \"Height\", MAP_CELL_H-2);\n\n#ifndef FIXIT_VERSION_3\t\t//\tMap size no longer restricted.\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\tif(Session.Type >= GAME_MODEM && Session.Type <= GAME_INTERNET && PlayingAgainstVersion < VERSION_AFTERMATH_CS) {\n\t\t/*\n\t\t**\tHACK ALERT:\n\t\t**\tForce the map to be limited to the size that 96x96 would be. If the\n\t\t**\tsize is greater (due to hacking?) then shrink it down to legal size.\n\t\t** BG Note: only do this for multiplayer games against non-AfterMath.\n\t\t*/\n\t\tif (w * h > 96 * 96) {\n\t\t\th -= (((w*h) - (96*96)) / w) + 1;\n\t\t}\n\t}\n#else\n\t/*\n\t**\tHACK ALERT:\n\t**\tForce the map to be limited to the size that 96x96 would be. If the\n\t**\tsize is greater (due to hacking?) then shrink it down to legal size.\n\t*/\n\tif (w * h > 96 * 96) {\n\t\th -= (((w*h) - (96*96)) / w) + 1;\n\t}\n#endif\n\n#endif\t//\t!FIXIT_VERSION_3\n\n\tSet_Map_Dimensions( x, y, w, h );\n\n\t/*\n\t**\tThe theater is determined at this point. There is specific data that\n\t**\tis custom to this data. Load the custom data (as it related to terrain)\n\t**\tat this point.\n\t*/\n\tScen.Theater = ini.Get_TheaterType(name, \"Theater\", THEATER_TEMPERATE);\n\tif (Scen.Theater == THEATER_NONE) {\n\t\tScen.Theater = THEATER_TEMPERATE;\n\t}\n\n\t/*\n\t** Remove any old theater specific uncompressed shapes\n\t*/\n#ifdef WIN32\n\tif (Scen.Theater != LastTheater) {\n\t\tReset_Theater_Shapes();\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tNow that the theater is known, init the entire map hierarchy\n\t*/\n\tInit(Scen.Theater);\n\n\t/*\n\t**\tSpecial initializations occur when the theater is known.\n\t*/\n\tTerrainTypeClass::Init(Scen.Theater);\n\tTemplateTypeClass::Init(Scen.Theater);\n\tOverlayTypeClass::Init(Scen.Theater);\n\tUnitTypeClass::Init(Scen.Theater);\n\tInfantryTypeClass::Init(Scen.Theater);\n\tBuildingTypeClass::Init(Scen.Theater);\n\tBulletTypeClass::Init(Scen.Theater);\n\tAnimTypeClass::Init(Scen.Theater);\n\tAircraftTypeClass::Init(Scen.Theater);\n\tVesselTypeClass::Init(Scen.Theater);\n\tSmudgeTypeClass::Init(Scen.Theater);\n\n\t/*\n\t**\tRead the Waypoint entries.\n\t*/\n\tfor (int i = 0; i < WAYPT_COUNT; i++) {\n\t\tchar buf[20];\n\t\tsprintf(buf, \"%d\", i);\n\t\tScen.Waypoint[i] = ini.Get_Int(\"Waypoints\", buf, -1);\n\n\t\tif (Scen.Waypoint[i] != -1) {\n\t\t\t(*this)[Scen.Waypoint[i]].IsWaypoint = 1;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the starting position (do this after Init(), which clears the cells'\n\t**\tIsWaypoint flags).\n\t*/\n\tif (Scen.Waypoint[WAYPT_HOME] == -1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + 5*RESFACTOR, MapCellY + 4*RESFACTOR);\n\t}\n\n\tScen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME];\n\tSet_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR)));\n\n\t/*\n\t**\tLoop through all CellTrigger entries.\n\t*/\n\tint len = ini.Entry_Count(\"CellTriggers\");\n\tfor (int index = 0; index < len; index++) {\n\n\t\t/*\n\t\t**\tGet a cell trigger and cell assignment.\n\t\t*/\n\t\tchar const * cellentry = ini.Get_Entry(\"CellTriggers\", index);\n\t\tTriggerTypeClass * tp = ini.Get_TriggerType(\"CellTriggers\", cellentry);\n\t\tCELL cell = atoi(cellentry);\n\n\t\tif (tp != NULL && !(*this)[cell].Trigger.Is_Valid()) {\n\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\tif (tt) {\n\t\t\t\ttt->AttachCount++;\n\t\t\t\ttt->Cell = cell;\n\t\t\t\t(*this)[cell].Trigger = tt;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRead the map template data.\n\t*/\n\tstatic char const * const MAPPACK = \"MapPack\";\n\tlen = ini.Get_UUBlock(MAPPACK, _staging_buffer, sizeof(_staging_buffer));\n\tBufferStraw bstraw(_staging_buffer, len);\n\tMap.Read_Binary(bstraw);\n\n\tLastTheater = Scen.Theater;\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Write_INI -- Write the map data to the INI file specified.                    *\n *                                                                                             *\n *    This routine will output all the data of this map to the INI database specified.         *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI handler to store the map data to.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Any existing map data in the INI database will be replaced by this function.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Write_INI(CCINIClass & ini)\n{\n\tchar entry[20];\n\n\t/*\n\t**\tSave the map parameters.\n\t*/\n\tstatic char const * const NAME = \"Map\";\n\tini.Clear(NAME);\n\tini.Put_TheaterType(NAME, \"Theater\", Scen.Theater);\n\tini.Put_Int(NAME, \"X\", MapCellX);\n\tini.Put_Int(NAME, \"Y\", MapCellY);\n\tini.Put_Int(NAME, \"Width\", MapCellWidth);\n\tini.Put_Int(NAME, \"Height\", MapCellHeight);\n\n\t/*\n\t**\tSave the Waypoint entries.\n\t*/\n\tstatic char const * const WAYNAME = \"Waypoints\";\n\tini.Clear(WAYNAME);\n\tfor (int i = 0; i < WAYPT_COUNT; i++) {\n\t\tif (Scen.Waypoint[i] != -1) {\n\t\t\tsprintf(entry, \"%d\", i);\n\t\t\tini.Put_Int(WAYNAME, entry, Scen.Waypoint[i]);\n\t\t}\n\t}\n\n\t/*\n\t**\tSave the cell's triggers.\n\t*/\n\tstatic char const * const CELLTRIG = \"CellTriggers\";\n\tini.Clear(CELLTRIG);\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif ((*this)[cell].Trigger.Is_Valid()) {\n\t\t\tTriggerClass * tp = (*this)[cell].Trigger;\n\t\t\tif (tp != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGenerate entry name.\n\t\t\t\t*/\n\t\t\t\tsprintf(entry, \"%d\", cell);\n\n\t\t\t\t/*\n\t\t\t\t**\tSave entry.\n\t\t\t\t*/\n\t\t\t\tini.Put_TriggerType(CELLTRIG, entry, tp->Class);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWrite the map template data out to the ini file.\n\t*/\n\tstatic char const * const MAPPACK = \"MapPack\";\n\tBufferPipe bpipe(_staging_buffer, sizeof(_staging_buffer));\n\tint len = Map.Write_Binary(bpipe);\n\tini.Clear(MAPPACK);\n\tif (len) {\n\t\tini.Put_UUBlock(MAPPACK, _staging_buffer, len);\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::All_To_Look -- Direct all objects to look around for the player.              *\n *                                                                                             *\n *    This routine will scan through all objects and tell them to look if they are supposed    *\n *    to be able to reveal the map for the player. This routine may be necessary in cases      *\n *    of gap generator reshroud logic.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *   08/06/2019  ST : Added house parameter so it can work for multiple players                *\n *=============================================================================================*/\nvoid DisplayClass::All_To_Look(HouseClass *house, bool units_only)\n{\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * object = Layer[LAYER_GROUND][index];\n\t\tif (object != NULL && object->Is_Techno()) {\n\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;\n\n\t\t\tif (tech->House == house) {\n\t\t\t\tif (tech->Is_Discovered_By_Player(house)) {\n\t\t\t\t\tobject->Look();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t//if (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)) {\n\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(house)) {\n\t\t\t\t\ttech->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/*\n** Added house parameter for client/server multiplayer. ST - 8/12/2019 11:48AM\n** \n** \n*/\nvoid DisplayClass::Constrained_Look(COORDINATE center, LEPTON distance, HouseClass *house)\n{\n\tfor (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {\n\t\tObjectClass * object = Layer[LAYER_GROUND][index];\n\t\tif (object != NULL && object->Is_Techno()) {\n\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n//\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;\n\n\t\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (tech->House->IsPlayerControl) {\n\t\t\t\t\tif (tech->IsDiscoveredByPlayer && Distance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\t\t\t\t\t\tobject->Look();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr) &&\n\t\t\t\t\t\tDistance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\n\t\t\t\t\t\ttech->Look();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tif (tech->House->IsHuman) {\n\n\t\t\t\t\tif (tech->House == house) {\n\t\t\t\t\t\tif (tech->Is_Discovered_By_Player(house) && Distance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\t\t\t\t\t\t\tobject->Look();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(house) && \n\t\t\t\t\t\t\tDistance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {\n\t\t\t\t\t\t\ttech->Look();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn.                           *\n *                                                                                             *\n *    This will flag the cell to be redrawn.                                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell to be flagged.                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DisplayClass::Flag_Cell(CELL cell)\n{\n\tFlag_To_Redraw(false);\n\tIsToRedraw = true;\n\tCellRedraw[cell] = true;\n}\n\nstatic ActionType _priority_actions[] = {\n\tACTION_ATTACK,\n\tACTION_ENTER,\n\tACTION_HEAL,\n\tACTION_REPAIR,\n\tACTION_SABOTAGE,\n\tACTION_CAPTURE,\n\tACTION_MOVE\n};\n\nstatic int get_action_priority(ActionType action)\n{\n\tfor (int i = 0; i < ARRAY_LENGTH(_priority_actions); ++i) {\n\t\tif (_priority_actions[i] == action) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn INT_MAX;\n}\n\ntemplate <typename T>\nstatic int index_of(const DynamicVectorClass<T*>& list, T* object)\n{\n\tfor (int i = 0; i < list.Count(); i++) {\n\t\tif (list[i] == object) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\ntemplate <typename T>\nstatic ObjectClass* Best_Object_With_ActionT(DynamicVectorClass<ObjectClass*>& objects, T subject)\n{\n\tDynamicVectorClass<const ObjectTypeClass*> checked_types;\n\n\tif (objects.Count()) {\n\t\tint best_priority = INT_MAX;\n\t\tObjectClass* best_object = objects[0];\n\t\tfor (int i = 0; i < objects.Count(); ++i) {\n\t\t\tObjectClass* object = objects[i];\n\t\t\tconst ObjectTypeClass* type = &object->Class_Of();\n\t\t\tif (index_of(checked_types, type) != -1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tchecked_types.Add(type);\n\t\t\tActionType action = object->What_Action(subject);\n\t\t\tint priority = get_action_priority(action);\n\t\t\tif (priority < best_priority) {\n\t\t\t\tbest_priority = priority;\n\t\t\t\tbest_object = object;\n\t\t\t\tif (best_priority == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn best_object;\n\t}\n\treturn NULL;\n}\n\nObjectClass* Best_Object_With_Action(DynamicVectorClass<ObjectClass*>& objects, const ObjectClass* object)\n{\n\treturn Best_Object_With_ActionT(objects, object);\n}\n\nObjectClass* Best_Object_With_Action(DynamicVectorClass<ObjectClass*>& objects, CELL cell)\n{\n\treturn Best_Object_With_ActionT(objects, cell);\n}\n\nActionType Best_Object_Action(DynamicVectorClass<ObjectClass*>& objects, const ObjectClass* object)\n{\n\tObjectClass* obj = Best_Object_With_Action(objects, object);\n\treturn (obj != NULL) ? obj->What_Action(object) : ACTION_NONE;\n}\n\nActionType Best_Object_Action(DynamicVectorClass<ObjectClass*>& objects, CELL cell)\n{\n\tObjectClass* obj = Best_Object_With_Action(objects, cell);\n\treturn (obj != NULL) ? obj->What_Action(cell) : ACTION_NONE;\n}\n\nObjectClass* Best_Object_With_Action(const ObjectClass* object)\n{\n\treturn Best_Object_With_Action(CurrentObject.Raw(), object);\n}\n\nObjectClass* Best_Object_With_Action(CELL cell)\n{\n\treturn Best_Object_With_Action(CurrentObject.Raw(), cell);\n}\n\nActionType Best_Object_Action(const ObjectClass* object)\n{\n\treturn Best_Object_Action(CurrentObject.Raw(), object);\n}\n\nActionType Best_Object_Action(CELL cell)\n{\n\treturn Best_Object_Action(CurrentObject.Raw(), cell);\n}"
  },
  {
    "path": "REDALERT/DISPLAY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DISPLAY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DISPLAY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 1, 1994                                                  *\n *                                                                                             *\n *                  Last Update : May 1, 1994   [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DISPLAY_H\n#define DISPLAY_H\n\n#include\t\"map.h\"\n#include\t\"layer.h\"\n\n\n#define\tICON_PIXEL_W\t \t\t24\n#define\tICON_PIXEL_H\t\t\t24\n#define\tICON_LEPTON_W\t\t\t256\n#define\tICON_LEPTON_H\t\t\t256\n#define\tCELL_PIXEL_W\t \t\tICON_PIXEL_W\n#define\tCELL_PIXEL_H\t\t\tICON_PIXEL_H\n#define\tCELL_LEPTON_W\t\t\tICON_LEPTON_W\n#define\tCELL_LEPTON_H\t\t\tICON_LEPTON_H\n\n//\t-----------------------------------------------------------\n#define\tPIXEL_LEPTON_W\t\t\t(ICON_LEPTON_W/ICON_PIXEL_W)\n#define\tPIXEL_LEPTON_H\t\t\t(ICON_LEPTON_H/ICON_PIXEL_H)\n\n#define\tSIDE_BAR_TAC_WIDTH\t10\n#define  SIDE_BAR_TAC_HEIGHT\t8\n\nextern COORDINATE Coord_Add(COORDINATE coord1, COORDINATE coord2);\n\nclass DisplayClass: public MapClass\n{\n\tpublic:\n\t\tfriend class DLLExportClass;\t// ST - 5/13/2019\n\n\t\t/*\n\t\t** The tactical map display position is indicated by the cell of the\n\t\t**\tupper left hand corner. These should not be altered directly. Use\n\t\t**\tthe Set_Tactical_Position function instead.\n\t\t*/\n\t\tCOORDINATE TacticalCoord;\n\n\t\t/*\n\t\t**\tThe dimensions (in cells) of the visible window onto the game map. This tactical\n\t\t**\tmap is how the player interacts and views the game world.\n\t\t*/\n\t\tLEPTON TacLeptonWidth;\n\t\tLEPTON TacLeptonHeight;\n\n\t\t/*\n\t\t**\tThese layer control elements are used to group the displayable objects\n\t\t**\tso that proper overlap can be obtained.\n\t\t*/\n\t\tstatic LayerClass Layer[LAYER_COUNT];\n\n\t\t/*\n\t\t**\tThis records the position and shape of a placement cursor to display\n\t\t**\tover the map. This cursor is used when placing buildings and also used\n\t\t**\textensively by the scenario editor.\n\t\t*/\n\t\tCELL ZoneCell;\n\t\tshort ZoneOffset;\n\t\tshort const *CursorSize;\n\t\tshort CursorShapeSave[256];\t// For save/load\n\t\tbool ProximityCheck;\t\t\t\t// Is proximity check ok?\n\n\t\t/*\n\t\t** This holds the building type that is about to be placed upon the map.\n\t\t**\tIt is only valid during the building placement state. The PendingLegal\n\t\t**\tflag is updated as the cursor moves and it reflects the legality of\n\t\t**\tplacing the building at the desired location.\n\t\t*/\n\t\tObjectClass * PendingObjectPtr;\n\t\tObjectTypeClass const * PendingObject;\n\t\tHousesType PendingHouse;\n\n\t\tstatic unsigned char FadingBrighten[256];\n\t\tstatic unsigned char FadingShade[256];\n\t\tstatic unsigned char FadingWayDark[256];\n\t\tstatic unsigned char FadingLight[256];\n\t\tstatic unsigned char FadingGreen[256];\n\t\tstatic unsigned char FadingYellow[256];\n\t\tstatic unsigned char FadingRed[256];\n\t\tstatic unsigned char TranslucentTable[(MAGIC_COL_COUNT+1)*256];\n\t\tstatic unsigned char WhiteTranslucentTable[(1+1)*256];\n\t\tstatic unsigned char MouseTranslucentTable[(4+1)*256];\n\t\tstatic void const *TransIconset;\n\t\tstatic unsigned char UnitShadow[(USHADOW_COL_COUNT+1)*256];\n\t\tstatic unsigned char UnitShadowAir[(USHADOW_COL_COUNT+1)*256];\n\t\tstatic unsigned char SpecialGhost[2*256];\n\n\t\t//-------------------------------------------------------------------------\n\t\tDisplayClass(void);\n\t\tDisplayClass(NoInitClass const & x) : MapClass(x) {};\n\n\t\tvirtual void Read_INI(CCINIClass & ini);\n\t\tvoid Write_INI(CCINIClass & ini);\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\n\t\t/*\n\t\t**\tGeneral display/map/interface support functionality.\n\t\t*/\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\n\t\t/*\n\t\t**\tAdded functionality.\n\t\t*/\n\t\tvoid All_To_Look(HouseClass *house, bool units_only=false);\t\t\t\t\t\t\t\t\t\t// Added house parameter so it can work for multiple players. ST - 8/6/2019 2:30PM\n\t\tvoid Constrained_Look(COORDINATE coord, LEPTON distance, HouseClass *house);\t\t\t\t// Added house parameter for client/server multiplayer. ST - 8/12/2019 3:25PM\n\t\tvoid Shroud_Cell(CELL cell, HouseClass *house);\n\t\tvoid Encroach_Shadow(HouseClass *house);\n\t\tCOORDINATE Center_Map(COORDINATE center=0L);\n\t\tvirtual bool Map_Cell(CELL cell, HouseClass *house, bool check_radar_spied = true, bool and_for_allies = true);\t\t// Added check_radar_spied parameter to prevent recursion. ST - 8/6/2019 10:16AM. Added and_for_allies ST - 10/31/2019 1:18PM\n\t\tvirtual CELL Click_Cell_Calc(int x, int y) const;\n\t\tvirtual void Help_Text(int , int =-1, int =-1, int =YELLOW, bool =false) {};\n\t\tvirtual MouseType Get_Mouse_Shape(void) const = 0;\n\t\tvirtual bool Scroll_Map(DirType facing, int & distance, bool really);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvirtual void Set_View_Dimensions(int x, int y, int width=-1, int height=-1);\n\n\t\t/*\n\t\t**\tPending object placement control.\n\t\t*/\n\t\tvirtual void Put_Place_Back(TechnoClass * ) {}; // Affects 'pending' system.\n\t\tvoid Cursor_Mark(CELL pos, bool on);\n\t\tvoid Set_Cursor_Shape(short const * list);\n\t\tCELL Set_Cursor_Pos(CELL pos = -1);\n\t\tvoid Get_Occupy_Dimensions(int & w, int & h, short const *list) const;\n\n\t\t/*\n\t\t**\tTactical map only functionality.\n\t\t*/\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\t\tvoid Refresh_Band(void);\n\t\tvoid Select_These(COORDINATE coord1, COORDINATE coord2, bool additive = false);\n\t\tCOORDINATE Pixel_To_Coord(int x, int y) const;\n\t\tbool Coord_To_Pixel(COORDINATE coord, int & x, int & y) const;\n\t\tbool Push_Onto_TacMap(COORDINATE &source, COORDINATE &dest);\n\t\tvoid Remove(ObjectClass const * object, LayerType layer);\n\t\tvoid Submit(ObjectClass const * object, LayerType layer);\n\t\tCELL Calculated_Cell(SourceType dir, WAYPOINT waypoint=-1, CELL cell=-1, SpeedType loco=SPEED_FOOT, bool zonecheck=true, MZoneType mzone=MZONE_NORMAL) const;\n\t\tbool In_View(register CELL cell) const;\n\t\tbool Passes_Proximity_Check(ObjectTypeClass const * object, HousesType house, short const * list, CELL trycell) const;\n\t\tObjectClass * Cell_Object(CELL cell, int x=0, int y=0) const;\n\t\tObjectClass * Next_Object(ObjectClass * object) const;\n\t\tObjectClass * Prev_Object(ObjectClass * object) const;\n\t\tint Cell_Shadow(CELL cell, HouseClass *house) const;\n\t\tshort const * Text_Overlap_List(char const * text, int x, int y) const;\n\t\tbool Is_Spot_Free(COORDINATE coord) const;\n\t\tCOORDINATE Closest_Free_Spot(COORDINATE coord, bool any=false) const;\n\t\tvoid Sell_Mode_Control(int control);\n\t\tvoid Repair_Mode_Control(int control);\n\n\t\tvirtual void Flag_Cell(CELL cell);\n\t\tbool Is_Cell_Flagged(CELL cell) const {return CellRedraw.Is_True(cell);};\n\n\t\t/*\n\t\t** Computes starting position based on player's units' Coords.\n\t\t*/\n\t\tvoid Compute_Start_Pos(long& x, long& y);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\tprotected:\n\t\tvirtual void Mouse_Right_Press(void);\n\t\tvirtual void Mouse_Left_Press(int x, int y);\n\t\tvirtual void Mouse_Left_Up(CELL cell, bool shadow, ObjectClass * object, ActionType action, bool wsmall = false);\n\t\tvirtual void Mouse_Left_Held(int x, int y);\n\t\tvirtual void Mouse_Left_Release(CELL cell, int x, int y, ObjectClass * object, ActionType action, bool wsmall = false);\n\n\tpublic:\n\t\t/*\n\t\t**\tThis is the pixel offset for the upper left corner of the tactical map.\n\t\t*/\n\t\tint TacPixelX;\n\t\tint TacPixelY;\n\n\t\t/*\n\t\t**\tThis is the coordinate that the tactical map should be in at next available opportunity.\n\t\t*/\n\t\tCOORDINATE DesiredTacticalCoord;\n\n\t\t/*\n\t\t**\tIf something in the tactical map is to be redrawn, this flag is set to true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\t/*\n\t\t**\tIf the player is currently wielding a wrench (to select buildings for repair),\n\t\t**\tthen this flag is true. In such a state, normal movement and combat orders\n\t\t**\tare preempted.\n\t\t*/\n\t\tunsigned IsRepairMode:1;\n\n\t\t/*\n\t\t**\tIf the player is currently in \"sell back\" mode, then this flag will be\n\t\t**\ttrue. While in this mode, anything clicked on will be sold back to the\n\t\t**\t\"factory\".\n\t\t*/\n\t\tunsigned IsSellMode:1;\n\n\t\t/*\n\t\t**\tIf the player is currently in ion cannon targeting mode, then this\n\t\t** flag will be true.  While in this mode, anything clicked on will be\n\t\t** be destroyed by the ION cannon.\n\t\t*/\n\t\tSpecialWeaponType IsTargettingMode;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf it is currently in rubber band mode (multi unit selection), then this\n\t\t**\tflag will be true. While in such a mode, normal input is preempted while\n\t\t**\tthe extended selection is in progress.\n\t\t*/\n\t\tunsigned IsRubberBand:1;\n\n\t\t/*\n\t\t**\tThe moment the mouse is held down, this flag gets set. If the mouse is dragged\n\t\t**\ta sufficient distance while held down, then true rubber band mode selection\n\t\t**\tcan begin. Using a minimum distance prevents accidental rubber band selection\n\t\t**\tmode from being initiated.\n\t\t*/\n\t\tunsigned IsTentative:1;\n\n\t\t/*\n\t\t**\tThis gadget class is used for capturing input to the tactical map. All mouse input\n\t\t**\twill be routed through this gadget.\n\t\t*/\n\t\tclass TacticalClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tTacticalClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\t\tint Selection_At_Mouse(unsigned flags, KeyNumType & key);\n\t\t\t\tint Command_Object(unsigned flags, KeyNumType & key);\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t};\n\t\tfriend class TacticalClass;\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\npublic:\t\t//ST - 1/21/2019 11:59AM\n\t\tstatic TacticalClass TacButton;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a utility flag that is set during the icon draw process only if there\n\t\t**\twas at least one shadow icon detected that should be redrawn. When the shadow\n\t\t**\tdrawing logic is to take place, but this flag is false, then the shadow drawing\n\t\t**\twill be skipped since it would perform no function.\n\t\t*/\n\t\tunsigned IsShadowPresent:1;\n\n\t\t/*\n\t\t**\tRubber band mode consists of stretching a box from the anchor point (specified\n\t\t**\there) to the current cursor position.\n\t\t*/\n\t\tint BandX,BandY;\n\t\tint NewX,NewY;\n\n\t\tstatic void const *ShadowShapes;\n\t\tstatic unsigned char ShadowTrans[(SHADOW_COL_COUNT+1)*256];\n\n\t\tvoid Redraw_Icons(void);\n\t\tvoid Redraw_OIcons(void);\n\t\tvoid Redraw_Shadow(void);\n\n\t\t/*\n\t\t**\tThis bit array is used to flag cells to be redrawn. If the icon needs to\n\t\t**\tbe redrawn for a cell, then the corresponding flag will be true.\n\t\t*/\n\t\tstatic BooleanVectorClass CellRedraw;\n\n\t\tbool Good_Reinforcement_Cell(CELL outcell, CELL incell, SpeedType loco, int zone, MZoneType mzone) const;\n\n\t\t//\n\t\t// We need a way to bypass visible view checks when we are running in the context of GlyphX without using the\n\t\t// internal C&C renderer. We shouldn't know or care what the user is actually looking at\n\t\t// ST - 4/17/2019 9:01AM\n\t\t//\n\t\tstatic bool IgnoreViewConstraints;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[1024];\n\n};\n\n\n#endif"
  },
  {
    "path": "REDALERT/DLLInterface.cpp",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/*\n** DLLInterfac.cpp\n** \n**\tThis is where we implement the API expected by the Instance Server. \n** \n** The Instance Server will pass in requests for loading and starting maps, control input from players,\n** and requests for game simulation and rendering states.\n** \n** \n*/\n\n// Exception handling isn't enabled\n#pragma warning (disable : 4530)\t\t//warning C4530: C++ exception handler used, but unwind semantics are not enabled.\n\n#include <string>\n#include <vector>\n#include <set>\n\n#include\t\"function.h\"\n#include \"externs.h\"\n#include \"DLLInterface.h\"\n#include \"Gadget.h\"\n#include \"defines.h\" // VOC_COUNT, VOX_COUNT\n#include \"SidebarGlyphx.h\"\n\n#include <chrono>\n\n\n\n/*\n** Externs\n*/\nextern int DLL_Startup(const char * command_line);\nextern void Reallocate_Big_Shape_Buffer(void);\nextern bool ProgEndCalled;\nextern int Write_PCX_File(char* name, GraphicViewPortClass& pic, unsigned char* palette );\nextern void Color_Cycle(void);\n\nbool Debug_Write_Shape_Type(const ObjectTypeClass *type, int shapenum);\nbool Debug_Write_Shape(const char *file_name, void const * shapefile, int shapenum, int flags = 0, void const * ghostdata = NULL);\n\ntypedef void (__cdecl* CNC_Event_Callback_Type)(const EventCallbackStruct &event);\ntypedef unsigned __int64 uint64;\ntypedef __int64 int64;\n\n\t\t  \n\n\n/*\n** Audio defines\n** \n** \n** \n** \n** \n*/\n// For compatibility with Watcom in audio enums\n#pragma warning (disable : 4091)\n\n// From RedAlert\\Audio.cpp \nenum ContextType;\nextern struct SoundEffectNameStruct {\n\tchar const *Name;\t\t\t// Digitized voice file name.\n\tint\t\t\tPriority;\t// Playback priority of this sample.\n\tContextType\tWhere;\t\t// In what game context does this sample exist.\n} SoundEffectName[VOC_COUNT];\n\n// From RedAlert\\Audio.cpp \nextern char const* Speech[VOX_COUNT];\n\n// From RedAlert\\Audio.cpp \ntypedef enum {\n\tIN_NOVAR,\t\t\t// No variation or alterations allowed.\n\tIN_VAR\t\t\t\t// Infantry variance response modification.\n};\n\n\n\n\n/*\n** Misc defines\n** \n** \n** \n** \n** \n*/\n#define GAME_TO_PLAY Session.Type\n#define MULTIPLAYER_COUNT Session.Players.Count()\n#define KEYBOARD Keyboard\n\n#define RANDOM_START_POSITION 0x7f\n\n#define KILL_PLAYER_ON_DISCONNECT 1\n\n\n\n/*\n**  DLL Interface\n** \n** \n** \n** \n** \n*/\nextern \"C\" __declspec(dllexport) unsigned int __cdecl CNC_Version(unsigned int version_in);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Init(const char *command_line, CNC_Event_Callback_Type event_callback);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Config(const CNCRulesDataStruct& rules);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Add_Mod_Path(const char *mod_path);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Visible_Page(unsigned char *buffer_in, unsigned int &width, unsigned int &height);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Palette(unsigned char(&palette_in)[256][3]);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Instance(int scenario_index, int build_level, const char *faction, const char *game_type, const char *content_directory, int sabotaged_structure, const char *override_map_name);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Instance_Variation(int scenario_index, int scenario_variation, int scenario_direction, int build_level, const char *faction, const char *game_type, const char *content_directory, int sabotaged_structure, const char *override_map_name);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Custom_Instance(const char* content_directory, const char* directory_path, const char* scenario_name, int build_level, bool multiplayer);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Advance_Instance(uint64 player_id);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Game_State(GameStateRequestEnum state_type, uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Read_INI(int scenario_index, int scenario_variation, int scenario_direction, const char *content_directory, const char *override_map_name, char *ini_buffer, int _ini_buffer_size);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Set_Home_Cell(int x, int y, uint64 player_id);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Game_Request(GameRequestEnum request_type);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Game_Settings_Request(int health_bar_display_mode, int resource_bar_display_mode);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Input(InputRequestEnum mouse_event, unsigned char special_key_flags, uint64 player_id, int x1, int y1, int x2, int y2);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Structure_Request(StructureRequestEnum request_type, uint64 player_id, int object_id);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Unit_Request(UnitRequestEnum request_type, uint64 player_id);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Sidebar_Request(SidebarRequestEnum request_type, uint64 player_id, int buildable_type, int buildable_id, short cell_x, short cell_y);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_SuperWeapon_Request(SuperWeaponRequestEnum request_type, uint64 player_id, int buildable_type, int buildable_id, int x1, int y1);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_ControlGroup_Request(ControlGroupRequestEnum request_type, uint64 player_id, unsigned char control_group_index);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Debug_Request(DebugRequestEnum debug_request_type, uint64 player_id, const char *object_name, int x, int y, bool unshroud, bool enemy);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Beacon_Request(BeaconRequestEnum beacon_request_type, uint64 player_id, int pixel_x, int pixel_y);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scenario_index, CNCMultiplayerOptionsStruct &game_options, int num_players, CNCPlayerInfoStruct *player_list, int max_players);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Clear_Object_Selection(uint64 player_id);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Select_Object(uint64 player_id, int object_type_id, int object_to_select_id);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Save_Load(bool save, const char *file_path_and_name, const char *game_type);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Set_Difficulty(int difficulty);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Restore_Carryover_Objects(const CarryoverObjectStruct* objects);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Player_Switch_To_AI(uint64 player_id);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Human_Team_Wins(uint64 player_id);\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Start_Mission_Timer(int time);\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Start_Game_Info(uint64 player_id, int &start_location_waypoint_index);\n\n\n\n\n/*\n** Class to implement the interface, and contain additional game state required by the conversion from peer/peer to client/server\n** \n** \n** \n** \n** \n*/\nclass DLLExportClass {\n\tpublic:\n\t\n\t\tstatic void Init(void);\n\t\tstatic void Shutdown(void);\n\t\tstatic void Config(const CNCRulesDataStruct& rules);\n\t\tstatic void Add_Mod_Path(const char *mod_path);\n\t\tstatic void Set_Home_Cell(int x, int y, uint64 player_id);\n\t\tstatic void Set_Content_Directory(const char *dir);\n\n\t\tstatic bool Get_Layer_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic bool Get_Sidebar_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic bool Start_Construction(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Hold_Construction(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Cancel_Construction(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Start_Placement(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic BuildingClass *Get_Pending_Placement_Object(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Get_Placement_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic void Convert_Type(const ObjectClass *object, CNCObjectStruct &object_out);\n\t\tstatic void DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name = NULL, char override_owner = HOUSE_NONE);\n\t\tstatic void DLL_Draw_Pip_Intercept(const ObjectClass* object, int pip);\n\t\tstatic bool Place(uint64 player_id, int buildable_type, int buildable_id, short cell_x, short cell_y);\n\t\tstatic bool Cancel_Placement(uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Place_Super_Weapon(uint64 player_id, int buildable_type, int buildable_id, int x, int y);\n\t\tstatic bool Create_Control_Group(unsigned char control_group_index);\n\t\tstatic bool Add_To_Control_Group(unsigned char control_group_index);\n\t\tstatic bool Toggle_Control_Group_Selection(unsigned char control_group_index);\n\t\tstatic bool Construction_Action(SidebarRequestEnum construction_action, uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool MP_Construction_Action(SidebarRequestEnum construction_action, uint64 player_id, int buildable_type, int buildable_id);\n\t\tstatic bool Passes_Proximity_Check(CELL cell_in, BuildingTypeClass *placement_type, unsigned char* placement_distance);\n\t\tstatic void Calculate_Start_Positions(void);\n\t\tstatic void Computer_Message(bool last_player_taunt);\n\n\t\tstatic void Repair_Mode(uint64 player_id);\n\t\tstatic void Repair(uint64 player_id, int object_id);\n\t\tstatic void Sell_Mode(uint64 player_id);\n\t\tstatic void Sell(uint64 player_id, int object_id);\n\t\tstatic void Repair_Sell_Cancel(uint64 player_id);\n\n\t\tstatic void Scatter_Selected(uint64 player_id);\n\t\tstatic void Select_Next_Unit(uint64 player_id);\n\t\tstatic void Select_Previous_Unit(uint64 player_id);\n\t\tstatic void Selected_Guard_Mode(uint64 player_id);\n\t\tstatic void Selected_Stop(uint64 player_id);\n\t\tstatic void Team_Units_Formation_Toggle_On(uint64 player_id);\n\t\tstatic void Units_Queued_Movement_Toggle(uint64 player_id, bool toggle);\n\n\t\tstatic void Cell_Class_Draw_It(CNCDynamicMapStruct *dynamic_map, int &entry_index, CellClass *cell_ptr, int xpixel, int ypixel, bool debug_output);\n\t\tstatic bool Get_Dynamic_Map_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic bool Get_Shroud_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic bool Get_Occupier_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\t\tstatic bool Get_Player_Info_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size);\n\n\n\t\tstatic void Set_Event_Callback(CNC_Event_Callback_Type event_callback) {EventCallback = event_callback;}\n\t\tstatic void Debug_Spawn_Unit(const char *object_name, int x, int y, bool enemy = false);\n\t\tstatic void Debug_Spawn_All(int x, int y);\n\t\tstatic bool Try_Debug_Spawn_Unlimbo(TechnoClass *techno, int &cell_x, int &cell_y);\n\t\tstatic void Debug_Kill_Unit(int x, int y);\n\t\tstatic void Debug_Heal_Unit(int x, int y);\n\n\t\tstatic void On_Play_Movie(const char * movie_name, ThemeType theme, bool immediate);\n\t\tstatic void On_Display_Briefing_Text();\n\n\t\tstatic void On_Sound_Effect(const HouseClass* player_ptr, int sound_effect_index, const char* extension, int variation, COORDINATE coord);\n\t\tstatic void On_Speech(const HouseClass* player_ptr, int speech_index);\n\t\tstatic void On_Message(const HouseClass* player_ptr, const char* message, float timeout_seconds, EventCallbackMessageEnum message_type, int64 message_id);\n\t\tstatic void On_Update_Map_Cell(int cell_x, int cell_y, const char* template_type_name);\n\t\tstatic void On_Special_Weapon_Targetting(const HouseClass* player_ptr, SpecialWeaponType weapon_type);\n\t\tstatic void On_Ping(const HouseClass* player_ptr, COORDINATE coord);\n\n\t\tstatic void On_Game_Over(uint64 glyphx_player_id, bool player_wins);\n\t\tstatic void On_Multiplayer_Game_Over(void);\n\n\t\tstatic void On_Debug_Output(const char *debug_text);\n\n\t\tstatic void On_Achievement(const HouseClass* player_ptr, const char *achievement_type, const char *achievement_reason);\n\n\t\tstatic void On_Center_Camera(const HouseClass* player_ptr, int coord_x, int coord_y);\n\n\t\tstatic void Glyphx_Queue_AI();\n\n\t\tstatic void Store_Carryover_Objects();\n\n\t\tstatic void Force_Human_Team_Wins(uint64 quitting_player_id);\n\t\t\n\t\t/*\n\t\t** Player context switching for input/output\n\t\t*/\n\t\tstatic bool Set_Player_Context(uint64 glyphx_player, bool force = false);\n\t\tstatic void Reset_Player_Context(void);\n\t\tstatic void Adjust_Internal_View(bool force_ignore_view_constraints = false);\n\t\tstatic void Logic_Switch_Player_Context(ObjectClass *object);\n\t\tstatic void Logic_Switch_Player_Context(HouseClass *house);\n\t\tstatic void Refresh_Player_Control_Flags(void);\n\t\tstatic __int64 Get_GlyphX_Player_ID(const HouseClass *house);\n\n\t\tstatic void Recalculate_Placement_Distances();\n\t\t\t\t\n\t\tstatic void Reset_Sidebars(void);\n\n\t\tstatic SidebarGlyphxClass *Get_Current_Context_Sidebar(HouseClass *player_ptr = NULL);\n\n\t\tstatic uint64 GlyphxPlayerIDs[MAX_PLAYERS];\n\n\n\n\t\tstatic const void *Get_Shadow_Shapes(void) {return Map.ShadowShapes;}\n\t\tstatic const unsigned char *Get_Shadow_Trans(void) {return &Map.ShadowTrans[0];}\n\n\t\tstatic bool Legacy_Render_Enabled(void);\n\n\t\tstatic bool Get_Input_Key_State(KeyNumType key);\n\n\t\tstatic void Set_Special_Key_Flags(unsigned char special_key_flags);\n\t\tstatic void Clear_Special_Key_Flags();\n\n\t\tstatic bool Load(Straw &file);\n\t\tstatic bool Save(Pipe &file);\n\t\tstatic void Code_Pointers(void);\n\t\tstatic void Decode_Pointers(void);\n\n\t\tstatic bool Get_Game_Over() { return GameOver; }\n\n\tprivate:\n\t\tstatic void Calculate_Single_Player_Score(EventCallbackStruct&);\n\n  \t\tstatic int RA_Calculate_Leadership( HousesType player_house, int units_lost, int buildings_lost );\n\t\tstatic int RA_Calculate_Economy( long available_money, int stolen_buildings_credits, unsigned harvested_credits, long initial_credits );\n  \t  \tstatic int RA_Calculate_Score( int uspoints, int leadership, int economy );\n\n\t\tstatic void Convert_Action_Type(ActionType type, ObjectClass* object, TARGET target, DllActionTypeEnum& dll_type);\n\t\tstatic void Convert_Special_Weapon_Type(SpecialWeaponType weapon_type, DllSuperweaponTypeEnum& dll_weapon_type, char* weapon_name);\n\t\tstatic void Fill_Sidebar_Entry_From_Special_Weapon(CNCSidebarEntryStruct& sidebar_entry_out, SuperClass*& super_weapon_out, SpecialWeaponType weapon_type);\n\n\t\tstatic void Calculate_Placement_Distances(BuildingTypeClass* placement_type, unsigned char* placement_distance);\n\n\t\tstatic int CurrentDrawCount;\n\t\tstatic int TotalObjectCount;\n\t\tstatic int SortOrder;\n\t\tstatic int ExportLayer;\n\n\t\tstatic CNCObjectListStruct *ObjectList;\n\n\t\tstatic CNC_Event_Callback_Type EventCallback;\n\n\n\t\tstatic int CurrentLocalPlayerIndex;\n\n\t\tstatic bool GameOver;\n\n\t\tstatic std::set<int64> MessagesSent;\n\n\t\t/*\n\t\t** Pseudo sidebars for players in multiplayer\n\t\t*/\n\t\tstatic SidebarGlyphxClass MultiplayerSidebars[MAX_PLAYERS];\n\n\t\tstatic CELL MultiplayerStartPositions[MAX_PLAYERS];\n\n\t\tstatic BuildingTypeClass *PlacementType[MAX_PLAYERS];\n\n\t\tstatic unsigned char PlacementDistance[MAX_PLAYERS][MAP_CELL_TOTAL];\n\n\t\tstatic unsigned char SpecialKeyFlags[MAX_PLAYERS];\n\n\t\t/*\n\t\t** Mod directories\n\t\t*/\n\t\tstatic DynamicVectorClass<char *> ModSearchPaths;\n\n};\n\n\n\n/*\n** DLLExportClass static data\n** \n** \n** \n** \n** \n*/\nint DLLExportClass::CurrentDrawCount = 0;\nint DLLExportClass::TotalObjectCount = 0;\nint DLLExportClass::SortOrder = 0;\nint DLLExportClass::ExportLayer = 0;\nCNCObjectListStruct *DLLExportClass::ObjectList = NULL;\nSidebarGlyphxClass DLLExportClass::MultiplayerSidebars [MAX_PLAYERS];\nuint64 DLLExportClass::GlyphxPlayerIDs[MAX_PLAYERS] = {0xffffffffl};\nint DLLExportClass::CurrentLocalPlayerIndex = -1;\nCELL DLLExportClass::MultiplayerStartPositions[MAX_PLAYERS];\nBuildingTypeClass *DLLExportClass::PlacementType[MAX_PLAYERS];\nunsigned char DLLExportClass::PlacementDistance[MAX_PLAYERS][MAP_CELL_TOTAL];\nunsigned char DLLExportClass::SpecialKeyFlags[MAX_PLAYERS] = { 0U };\nDynamicVectorClass<char *> DLLExportClass::ModSearchPaths;\nstd::set<int64> DLLExportClass::MessagesSent;\nbool DLLExportClass::GameOver = false;\n\n\n\n/*\n** Global variables\n** \n** \n** \n** \n** \n*/\nint DLLForceMouseX = 0;\nint DLLForceMouseY = 0;\n\nCNC_Event_Callback_Type DLLExportClass::EventCallback = NULL;\n\n// Needed to accomodate Glyphx client sidebar. ST - 4/12/2019 5:29PM\nint GlyphXClientSidebarWidthInLeptons = 0;\n\nbool MPlayerIsHuman[MAX_PLAYERS];\nint MPlayerTeamIDs[MAX_PLAYERS];\nint MPlayerStartLocations[MAX_PLAYERS];\n\nbool MPSuperWeaponDisable = false;\nbool ShareAllyVisibility = true;\nbool UseGlyphXStartLocations = true;\n\nSpecialClass* SpecialBackup = NULL;\n\n\nint GetRandSeed()\n{\n\tusing namespace std::chrono;\n\ttime_point<system_clock> time_since_epoch = system_clock::now();\n\tauto microseconds_since_epoch = floor<std::chrono::microseconds>(time_since_epoch);\n\n\treturn abs( static_cast<int>(microseconds_since_epoch.time_since_epoch().count()) );\n}\n\n\n\nvoid Play_Movie_GlyphX(const char * movie_name, ThemeType theme, bool immediate = false)\n{\n\tif ((movie_name[0] == 'x' || movie_name[0] == 'X') && movie_name[1] == 0) {\n\t\treturn;\n\t}\n\n\tDLLExportClass::On_Play_Movie(movie_name, theme, immediate);\n}\n\nvoid Display_Briefing_Text_GlyphX()\n{\n\tDLLExportClass::On_Display_Briefing_Text();\n}\n\n\nvoid On_Sound_Effect(int sound_index, int variation, COORDINATE coord, int house)\n{\n\tint voc = sound_index;\n\tif (voc == VOC_NONE)\n\t{\n\t\treturn;\n\t}\n\n\t// Borrowed from RedAlert\\AUDIO.CPP Sound_Effect()\n\t//\n\t#if 1\n\t\t/*\n\t\t**\tFetch a pointer to the sound effect data. Modify the sound as appropriate and desired.\n\t\t*/\n\t\tchar const * ext = \"\"; // \".AUD\";\n\t\tif (SoundEffectName[voc].Where == IN_VAR) {\n\t\n\t\t\t/*\n\t\t\t**\tIf there is no forced  house, then use the current player\n\t\t\t**\tact like house.\n\t\t\t*/\n\t\t\tif (house == HOUSE_NONE) {\n\t\t\t\thouse = PlayerPtr->ActLike;\n\t\t\t}\n\t\n\t\t\t/*\n\t\t\t**\tChange the extension based on the variation and house accent requested.\n\t\t\t*/\n\t\t\tif (((1 << house) & HOUSEF_ALLIES) != 0) {\n\t\n\t\t\t\t/*\n\t\t\t\t**\tFor infantry, use a variation on the response. For vehicles, always\n\t\t\t\t**\tuse the vehicle response table.\n\t\t\t\t*/\n\t\t\t\tif (variation < 0) {\n\t\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\t\text = \".V00\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\text = \".V02\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (variation % 2) {\n\t\t\t\t\t\text = \".V01\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\text = \".V03\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation < 0) {\n\t\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\t\text = \".R00\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\text = \".R02\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (variation % 2) {\n\t\t\t\t\t\text = \".R01\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\text = \".R03\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t#endif\n\t// END MBL \n\n\tDLLExportClass::On_Sound_Effect(PlayerPtr, sound_index, ext, variation, coord);\n\n\n#if 0\n\tint voc = sound_index;\n\tif (voc == VOC_NONE)\n\t{\n\t\treturn;\n\t}\n\n\t// Borrowed from AUDIO.CPP Sound_Effect()\n\t//\n\tchar const * ext = \"\"; // \".AUD\";\n#ifdef TIBERIAN_DAWN\n\tif (Special.IsJuvenile && SoundEffectName[voc].Where == IN_JUV) {\n\t\text = \".JUV\";\n\t} else {\n#endif\n\t\tif (SoundEffectName[voc].Where == IN_VAR) {\n\t\t\t/*\n\t\t\t**\tFor infantry, use a variation on the response. For vehicles, always\n\t\t\t**\tuse the vehicle response table.\n\t\t\t*/\n\t\t\tif (variation < 0) {\n\t\t\t\tif (ABS(variation) % 2) {\n\t\t\t\t\text = \".V00\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V02\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (variation % 2) {\n\t\t\t\t\text = \".V01\";\n\t\t\t\t} else {\n\t\t\t\t\text = \".V03\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#ifdef TIBERIAN_DAWN\n\t}\n#endif\n\t// END MBL \n\n\tDLLExportClass::On_Sound_Effect(PlayerPtr, sound_index, ext, variation, coord);\n#endif\n}\n\n\nvoid On_Speech(int speech_index, HouseClass *house)\n{\n\tif (house == NULL) {\n\t\tDLLExportClass::On_Speech(PlayerPtr, speech_index);\n\t}\n\telse\n\t{\n\t\tDLLExportClass::On_Speech(house, speech_index);\n\t}\n}\n\n\nvoid On_Message(const char* message, float timeout_seconds, int64 id)\n{\n\tDLLExportClass::On_Message(PlayerPtr, message, timeout_seconds, MESSAGE_TYPE_DIRECT, id);\n}\n\nvoid On_Update_Map_Cell(int cell_x, int cell_y, const char* template_type_name)\n{\n\tDLLExportClass::On_Update_Map_Cell(cell_x, cell_y, template_type_name);\n}\n\nvoid On_Special_Weapon_Targetting(const HouseClass* player_ptr, SpecialWeaponType weapon_type)\n{\n\tDLLExportClass::On_Special_Weapon_Targetting(player_ptr, weapon_type);\n}\n\nvoid On_Ping(const HouseClass* player_ptr, COORDINATE coord)\n{\n\tDLLExportClass::On_Ping(player_ptr, coord);\n}\n\nvoid On_Defeated_Message(const char* message, float timeout_seconds)\n{\n\tDLLExportClass::On_Message(PlayerPtr, message, timeout_seconds, MESSAGE_TYPE_PLAYER_DEFEATED, -1);\n}\n\nvoid GlyphX_Debug_Print(const char *debug_text)\n{\n\tDLLExportClass::On_Debug_Output(debug_text);\n}\n\nvoid On_Achievement_Event(const HouseClass* player_ptr, const char *achievement_type, const char *achievement_reason)\n{\n\tDLLExportClass::On_Achievement(player_ptr, achievement_type, achievement_reason);\n}\t\t\t  \n\n\n\n\n\n/**************************************************************************************************\n* CNC_Version -- Check DLL/Server version\n*\n* In:\t\tVersion expected\n*\n* Out:\tActual version\n*\n*\n*\n* History: 4/9/2020 2:12PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) unsigned int __cdecl CNC_Version(unsigned int version_in)\n{\n\t// Unreferenced, but potentially useful to know which version the server is expecting\n\tversion_in;\n\n\treturn CNC_DLL_API_VERSION;\n}\n\n\n\n/**************************************************************************************************\n* CNC_Init -- Initialize the .DLL\n*\n* In:   Command line\n*\n* Out:\n*\n*\n*\n* History: 1/3/2019 11:33AM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Init(const char *command_line, CNC_Event_Callback_Type event_callback)\n{\n\tDLLExportClass::Set_Content_Directory(NULL);\n\t\t  \n\tDLL_Startup(command_line);\n\n\tDLLExportClass::Set_Event_Callback( event_callback );\n\n\tDLLExportClass::Init();\n}\n\n\n\n/**************************************************************************************************\n* DLL_Shutdown -- Shutdown the .DLL\n*\n* In:   \n*\n* Out:\n*\n*\n*\n* History: 2/20/2020 1:58PM - ST\n**************************************************************************************************/\nvoid DLL_Shutdown(void)\n{\n\tDLLExportClass::Shutdown();\n}\n\n\n\n\n\n/**************************************************************************************************\n* CNC_Config -- Configure the plugin\n*\n* In:   Configuration data\n*\n* Out:\n*\n*\n*\n* History: 10/03/2019 - SKY\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Config(const CNCRulesDataStruct& rules)\n{\n\tDLLExportClass::Config(rules);\n}\n\n\n\n\n/**************************************************************************************************\n* CNC_Add_Mod_Path -- Add a path to load mod files from\n*\n* In:   Path to load mods from\n*\n* Out:\n*\n*\n*\n* History: 2/20/2020 2:04PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Add_Mod_Path(const char *mod_path)\n{\n\tDLLExportClass::Add_Mod_Path(mod_path);\n}\n\n\n\n\n\n/**************************************************************************************************\n* CNC_Get_Visible_Page -- Get the screen buffer 'SeenBuff' from the game\n*\n* In:   If buffer_in is null, just return info about page\n*\n* Out:  false if not changed since last call\n*\n*\n*\n* History: 1/3/2019 11:33AM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Visible_Page(unsigned char *buffer_in, unsigned int &width, unsigned int &height)\n{\n\tif (!DLLExportClass::Legacy_Render_Enabled() || (buffer_in == NULL)) {\n\t\treturn false;\n\t}\n\n\t/*\n\t** Assume the seen page viewport is the same size as the page\n\t*/\n\n\tGraphicBufferClass *gbuffer = HidPage.Get_Graphic_Buffer();\n\tif (gbuffer == NULL) {\n\t\treturn false;\n\t}\n\n\tint view_port_width = Map.MapCellWidth * CELL_PIXEL_W;\n\tint view_port_height = Map.MapCellHeight * CELL_PIXEL_H;\n\n\tif (view_port_width == 0 || view_port_height == 0) {\n\t\treturn false;\n\t}\n\n\tunsigned char *raw_buffer = (unsigned char*) gbuffer->Get_Buffer();\n\tlong raw_size = gbuffer->Get_Size();\n\tif (raw_buffer == NULL || gbuffer->Get_Width() < view_port_width || gbuffer->Get_Height() < view_port_height) {\n\t\treturn false;\n\t}\n\n\twidth = view_port_width;\n\theight = view_port_height;\n\n\tint pitch = gbuffer->Get_Width();\n\tfor (int i = 0; i < view_port_height; ++i, buffer_in += view_port_width, raw_buffer += pitch) {\n\t\tmemcpy(buffer_in, raw_buffer, view_port_width);\n\t}\n\n\treturn true;\n}\n\n\n\n\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Palette(unsigned char(&palette_in)[256][3])\n{\n\tmemcpy(palette_in, CurrentPalette, sizeof(palette_in));\n\treturn true;\n}\n\n\n\n\n/**************************************************************************************************\n* CNC_Set_Multiplayer_Data -- Set up for a multiplayer match\n*\n* In:   Multiplayer data\n*\n* Out:  false if data is bad\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scenario_index, CNCMultiplayerOptionsStruct &game_options, int num_players, CNCPlayerInfoStruct *player_list, int max_players)\n{\n\t\n\tif (num_players <= 0) {\n\t\treturn false;\n\t}\n\t\n\tif (num_players > min(MAX_PLAYERS, max_players)) {\n\t\treturn false;\n\t}\n\n\tDLLExportClass::Init();\n\n\tSession.Options.Bases\t \t= game_options.MPlayerBases;\t\t\t// 1 = bases are on for this scenario\n\tSession.Options.Credits\t \t= game_options.MPlayerCredits;\t\t// # credits everyone gets\n\tSession.Options.Tiberium\t= game_options.MPlayerTiberium;\t\t// 1 = tiberium enabled for this scenario\n\tSession.Options.Goodies\t\t= game_options.MPlayerGoodies;\t\t// 1 = goodies enabled for this scenario\n\tSession.Options.Ghosts\t\t= game_options.MPlayerGhosts;\t\t\t// 1 = houses with no players will still play\n\t//MPlayerSolo\t\t\t= game_options.MPlayerSolo;\t\t\t// 1 = allows a single-player net game\n\tSession.Options.UnitCount\t= game_options.MPlayerUnitCount;\t\t// # units for non-base multiplayer scenarios\n\n\tSpecial.IsShadowGrow = game_options.MPlayerShadowRegrow;\n\tSpecial.IsCaptureTheFlag = game_options.CaptureTheFlag;\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\tSession.Options.ScenarioIndex = scenario_index;\n\n\tSpecial.IsMCVDeploy = game_options.IsMCVDeploy;\n\tSpecial.UseMCVDeploy = true;\n\n\tMPSuperWeaponDisable = !game_options.EnableSuperweapons;\t\t\t// Are superweapons available\n\n\t//Session.Options.AIPlayers = WWGetPrivateProfileInt(\"Options\", \"AI\", 0, buffer);\t\t//Number of AI players\n\n\tSpecial.IsEarlyWin = game_options.DestroyStructures;\n\n\tSpecial.ModernBalance = game_options.ModernBalance;\n\n\t/*\n\t** Enable Counterstrike/Aftermath units\n\t*/\n\tOverrideNewUnitsEnabled = game_options.MPlayerAftermathUnits;\n\n\twhile (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\t\n\tfor (int i=0 ; i<num_players ; i++) {\n\t\tCNCPlayerInfoStruct &player_info = player_list[i];\n\n\t\tNodeNameType *who = new NodeNameType;\n\t\tstrncpy(who->Name, player_info.Name, MPLAYER_NAME_MAX);\n\t\twho->Name[MPLAYER_NAME_MAX - 1] = 0;\t\t\t// Make sure it's terminated\n\t\twho->Player.House = (HousesType)player_info.House;\n\t\twho->Player.Color = (PlayerColorType) player_info.ColorIndex;\n\t\tSession.Players.Add (who);\n\n\t\t/*\n\t\t** Player IDs are done differently in Red Alert vs. TD.\n\t\t** In TD, the ID is created from the house/color combination\n\t\t** In RA, the ID is HOUSE_MULTI1 + the index into the Session.Players vector\n\t\t*/\n\t\tDLLExportClass::GlyphxPlayerIDs[i] = player_info.GlyphxPlayerID;\n\n\t\tMPlayerIsHuman[i] = !player_info.IsAI;\n\t\tMPlayerTeamIDs[i] = player_info.Team;\n\t\tMPlayerStartLocations[i] = player_info.StartLocationIndex;\n\n\t\t/*\n\t\t** Temp fix for custom maps that don't have valid start positions set from matchmaking\n\t\t*/\n\t\tif (i > 0 && MPlayerStartLocations[i] == 0 && MPlayerStartLocations[0] == 0) {\n\t\t\tMPlayerStartLocations[i] = i;\n\t\t}\n\t}\n\n\t/*\n\t** Force smart defense always on for multiplayer/skirmish\n\t*/\n\tRule.IsSmartDefense = true;\n\n\t/*\n\t** Backup special\n\t*/\n\tif (SpecialBackup != NULL) {\n\t\tmemcpy(SpecialBackup, &Special, sizeof(SpecialClass));\n\t}\n\n\treturn true;\n}\n\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Clear_Object_Selection(uint64 player_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tUnselect_All();\n\n\treturn true;\n}\n\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Select_Object(uint64 player_id, int object_type_id, int object_to_select_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tswitch (object_type_id)\n\t{\n\tcase INFANTRY:\n\t{\n\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\n\t\t\tif (obj\n\t\t\t\t&& !obj->IsInLimbo\n\t\t\t\t&& obj->House->IsPlayerControl\n\t\t\t\t&& Infantry.ID((InfantryClass*)obj) == object_to_select_id)\n\t\t\t{\n\t\t\t\tif (!obj->Is_Selected_By_Player())\n\t\t\t\t{\n\t\t\t\t\tobj->Select();\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tbreak;\n\tcase UNIT:\n\t{\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\n\t\t\tif (obj\n\t\t\t\t&& !obj->IsInLimbo\n\t\t\t\t&& obj->House->IsPlayerControl\n\t\t\t\t&& Units.ID((UnitClass*)obj) == object_to_select_id)\n\t\t\t{\n\t\t\t\tif (!obj->Is_Selected_By_Player())\n\t\t\t\t{\n\t\t\t\t\tobj->Select();\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tbreak;\n\tcase AIRCRAFT:\n\t{\n\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass * obj = Aircraft.Ptr(index);\n\n\t\t\tif (obj\n\t\t\t\t&& !obj->IsInLimbo\n\t\t\t\t&& obj->House->IsPlayerControl\n\t\t\t\t&& Aircraft.ID((AircraftClass*)obj) == object_to_select_id)\n\t\t\t{\n\t\t\t\tif (!obj->Is_Selected_By_Player())\n\t\t\t\t{\n\t\t\t\t\tobj->Select();\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tbreak;\n\tcase BUILDING:\n\t{\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\t\tif (obj\n\t\t\t\t&& !obj->IsInLimbo\n\t\t\t\t&& obj->House->IsPlayerControl\n\t\t\t\t&& Buildings.ID((BuildingClass*)obj) == object_to_select_id)\n\t\t\t{\n\t\t\t\tif (!obj->Is_Selected_By_Player())\n\t\t\t\t{\n\t\t\t\t\tobj->Select();\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tbreak;\n\tcase VESSEL:\n\t{\n\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\n\t\t\tif (obj\n\t\t\t\t&& !obj->IsInLimbo\n\t\t\t\t&& obj->House->IsPlayerControl\n\t\t\t\t&& Vessels.ID((VesselClass*)obj) == object_to_select_id)\n\t\t\t{\n\t\t\t\tif (!obj->Is_Selected_By_Player())\n\t\t\t\t{\n\t\t\t\t\tobj->Select();\n\t\t\t\t\tAllowVoice = false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tbreak;\n\t}\n\n\treturn false;\n}\n\n\n/**************************************************************************************************\n* GlyphX_Assign_Houses -- Replacement for Assign_Houses in INI.CPP / SCNEARIO.CPP\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 8/8/2019 12:37PM - ST\n**************************************************************************************************/\nvoid GlyphX_Assign_Houses(void)\n{\n\t/*\n\t** RA version\n\t*/\n\textern int _build_tech[11];\n\n\tint assigned[MAX_PLAYERS];\n\tbool preassigned;\n\tint i,j,random_start_location;\n\tHousesType house, house2;\n\tHouseClass * housep, *housep2;\n\tint lowest_color;\n\tint index;\n\n\tsrand(timeGetTime());\n\n\t/*\n\t** Use pre-selected start locations as long as at least one has been defined, otherwise let the original code\n\t** in SCENARIO.CPP figure it out\n\t*/\n\tUseGlyphXStartLocations = false;\n\n\t/*\n\t** Assign random start positions if needed.\n\t*/\n\tint random_start_locations[26];\n\tint num_start_locations = 0;\n\tint num_random_start_locations = 0;\n\tfor (i = 0; i < 26; i++) {\n\t\tif (Scen.Waypoint[i] != -1) {\n\t\t\tpreassigned = false;\n\t\t\tfor (j = 0; !preassigned && (j < Session.Players.Count()); j++) {\n\t\t\t\tif (MPlayerStartLocations[j] == num_start_locations) {\n\t\t\t\t\tpreassigned = true;\n\t\t\t\t\tUseGlyphXStartLocations = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!preassigned && i < MAX_PLAYERS) {\n\t\t\t\trandom_start_locations[num_random_start_locations] = num_start_locations;\n\t\t\t\tnum_random_start_locations++;\n\t\t\t}\n\t\t\tnum_start_locations++;\n\t\t}\n\t}\n\n\tif (num_random_start_locations > 1)\t{\n\t\tfor (i = 0; i < num_random_start_locations - 1; i++) {\n\t\t\tj = i + rand() / (RAND_MAX / (num_random_start_locations - i) + 1);\n\t\t\tint t = random_start_locations[j];\n\t\t\trandom_start_locations[j] = random_start_locations[i];\n\t\t\trandom_start_locations[i] = t;\n\t\t}\n\t}\n\n\n\t//------------------------------------------------------------------------\n\t// Initialize\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\tassigned[i] = 0;\n\t}\n\n\trandom_start_location = 0;\n\n//\tdebugprint( \"Assign_Houses()\\n\" );\n\t//------------------------------------------------------------------------\n\t// Assign each player in 'Players' to a multiplayer house.  Players will\n\t// be sorted by their chosen color value (this value must be unique among\n\t// all the players).\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t//.....................................................................\n\t\t// Find the player with the lowest color index\n\t\t//.....................................................................\n\t\tindex = 0;\n\t\tlowest_color = 255;\n\t\tfor (j = 0; j < Session.Players.Count(); j++) {\n\t\t\t//..................................................................\n\t\t\t// If we've already assigned this house, skip it.\n\t\t\t//..................................................................\n\t\t\tif (assigned[j]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (Session.Players[j]->Player.Color < lowest_color) {\n\t\t\t\tlowest_color = Session.Players[j]->Player.Color;\n\t\t\t\tindex = j;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Mark this player as having been assigned.\n\t\t//.....................................................................\n\t\tassigned[index] = 1;\n\n\t\t//.....................................................................\n\t\t// Assign the lowest-color'd player to the next available slot in the\n\t\t// HouseClass array.\n\t\t//.....................................................................\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tmemset((char *)housep->IniName, 0, MPLAYER_NAME_MAX);\n\t\tstrncpy((char *)housep->IniName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tMake another copy of name, permanent throughout entire game.\n\t\tstrncpy((char *)housep->InitialName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#endif\n\t\thousep->IsHuman = MPlayerIsHuman[index];\n\t\thousep->IsPlayerControl = housep->IsHuman;\n\n\t\tif (!housep->IsHuman) {\n\t\t\thousep->IsStarted = true;\n\t\t\tstrncpy(housep->IniName, Text_String(TXT_COMPUTER), HOUSE_NAME_MAX);\n\t\t\thousep->IQ = Rule.MaxIQ;\n\t\t\t//housep->Control.TechLevel = _build_tech[BuildLevel];\n\t\t} else {\n\t\t\thousep->IQ = 0;\n\t\t}\n\n\n\t\thousep->Init_Data((PlayerColorType)(Session.Players[index]->Player.Color),\n\t\t\tSession.Players[index]->Player.House, Session.Options.Credits);\n\n\t\t/*\n\t\t**\tSet the start location override\n\t\t*/\n\t\tif (MPlayerStartLocations[index] != RANDOM_START_POSITION) {\n\t\t\thousep->StartLocationOverride = MPlayerStartLocations[index];\n\t\t} else {\n\t\t\tif (random_start_location < num_random_start_locations) {\n\t\t\t\thousep->StartLocationOverride = random_start_locations[random_start_location++];\n\t\t\t} else {\n\t\t\t\thousep->StartLocationOverride = -1;\n\t\t\t}\n\t\t}\n\n\t\tif (index == 0) {\n\t\t\tPlayerPtr = housep;\n\t\t}\n\t\t/*\n\t\t**\tConvert the build level into an actual tech level to assign to the house.\n\t\t**\tThere isn't a one-to-one correspondence.\n\t\t*/\n\t\thousep->Control.TechLevel = _build_tech[BuildLevel];\n\n\t\thousep->Assign_Handicap(Scen.Difficulty);\n\n\t\t//.....................................................................\n\t\t// Record where we placed this player\n\t\t//.....................................................................\n\t\tSession.Players[index]->Player.ID = house;\n\n//\t\tdebugprint( \"Assigned ID of %i to %s\\n\", house, Session.Players[index]->Name );\n\t}\n\n\tfor (i = Session.Players.Count(); i < Rule.MaxPlayers; i++) {\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (housep != NULL) {\n\t\t\thousep->IsDefeated = true;\n\t\t}\n\t}\n\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\n\t\thouse = Session.Players[i]->Player.ID;\n\t\thousep = HouseClass::As_Pointer(house);\n\n\t\tif (housep) {\n\n\t\t\tint team = MPlayerTeamIDs[i];\n\n\t\t\tfor (int j=0 ; j < Session.Players.Count(); j++) {\n\t\t\t\n\t\t\t\tif (i != j) {\n\n\t\t\t\t\tif (team == MPlayerTeamIDs[j]) {\n\t\t\t\t\t\t\n\t\t\t\t\t\thouse2 = Session.Players[j]->Player.ID;\n\t\t\t\t\t\thousep2 = HouseClass::As_Pointer(house2);\n\n\t\t\t\t\t\tif (housep2) {\n\t\t\t\t\t\t\thousep->Make_Ally(house2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n/**************************************************************************************************\n* CNC_Set_Home_Cell -- Allows overriding the start position for the camera\n*\n*\n* History: 2/14/2020 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Set_Home_Cell(int x, int y, uint64 player_id)\n{\n\tDLLExportClass::Set_Home_Cell(x, y, player_id);\n}\n\n\n/**************************************************************************************************\n* CNC_Start_Instance -- Load and start a cnc map -> WITHOUT SPECIFYING A SCENARIO VARIATION (SCEN_VAR)\n*\n* In:   Map initialization parameters \n*\n* Out:  false if map load failed\n*\n*\n*\n* History: 7/10/2019 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Instance(int scenario_index, int build_level, const char *faction, const char *game_type, const char *content_directory, int sabotaged_structure, const char *override_map_name)\n{\n\treturn CNC_Start_Instance_Variation(scenario_index, (int)SCEN_VAR_NONE, (int)SCEN_DIR_EAST, build_level, faction, game_type, content_directory, sabotaged_structure, override_map_name);\n}\n\n\n/**************************************************************************************************\n* CNC_Start_Instance -- Load and start a cnc map\n*\n* In:   Map initialization parameters\n*\n* Out:  false if map load failed\n*\n*\n* Renamed and modified to accept a scenario variation 7/10/2019 - LLL\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Instance_Variation(int scenario_index, int scenario_variation, int scenario_direction,\tint build_level, const char *faction, const char *game_type, const char *content_directory, int sabotaged_structure, const char *override_map_name)\n{\n\tif (game_type == NULL) {\n\t\treturn false;\n\t}\n\n\tif (faction == NULL) {\n\t\treturn false;\n\t}\n\n\tif (content_directory == NULL) {\n\t\treturn false;\n\t}\n\n\tScenarioPlayerType scen_player = SCEN_PLAYER_NONE;\n\n\tif (stricmp(faction, \"SPAIN\") == 0) {\n\t\tscen_player = SCEN_PLAYER_SPAIN;\n\t\tWhom = HOUSE_GOOD;\n\t}\n\t\n\tif (stricmp(faction, \"GREECE\") == 0 || stricmp(faction, \"ALLY\") == 0) {\n\t\tscen_player = SCEN_PLAYER_GREECE;\n\t\tWhom = HOUSE_GOOD;\n\t}\n\n\tif (stricmp(faction, \"USSR\") == 0) {\n\t\tscen_player = SCEN_PLAYER_USSR;\n\t\tWhom = HOUSE_BAD;\n\t}\n\n\n\n\tDLLExportClass::Set_Content_Directory(content_directory);\n\n\tBuildLevel = build_level;\n\tScen.Scenario = scenario_index;\n\tScenarioDirType scen_dir = (ScenarioDirType)scenario_direction;\n\tif (stricmp(game_type, \"GAME_NORMAL\") == 0) {\n\t\tGAME_TO_PLAY = GAME_NORMAL;\n\t\tif (scen_player == SCEN_PLAYER_NONE) {\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\tif (stricmp(game_type, \"GAME_GLYPHX_MULTIPLAYER\") == 0) {\n\t\t\tGAME_TO_PLAY = GAME_GLYPHX_MULTIPLAYER;\n\t\t\tscen_player = SCEN_PLAYER_MPLAYER;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/*\n\t**\tLoad the scenario.  Specify variation 'A' for the editor; for the game,\n\t**\tdon't specify a variation, to make 'Set_Scenario_Name()' pick a random one.\n\t**\tSkip this if we've already loaded a save-game.\n\t*/\n\tForce_CD_Available(ALWAYS_RELOAD_CD);\n\n\tif (override_map_name && strlen(override_map_name)) {\n\t\tstrcpy(Scen.ScenarioName, override_map_name);\n\t} else {\n\t\tScen.Set_Scenario_Name(Scen.Scenario, scen_player, scen_dir, (ScenarioVarType)scenario_variation);\n\t}\n\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n\n\t/*\n\t** Set the mouse to some position where it's not going to scroll, or do something else wierd.\n\t*/\n\tDLLForceMouseX = 100;\n\tDLLForceMouseY = 100;\n\tKEYBOARD->MouseQX = 100;\n\tKEYBOARD->MouseQY = 100;\n\n\tGlyphXClientSidebarWidthInLeptons = 0;\n\n\tSeed = GetRandSeed();\n\tScen.RandomNumber = Seed;\n\n\tif (!Start_Scenario(Scen.ScenarioName)) {\n\t\treturn(false);\n\t}\n\n\tDLLExportClass::Reset_Sidebars();\n\tDLLExportClass::Reset_Player_Context();\n\tDLLExportClass::Calculate_Start_Positions();\n\n\t/*\n\t** Make sure the scroll constraints are applied. This is important for GDI 1 where the map isn't wide enough for the screen\n\t*/\n\tCOORDINATE origin_coord = Coord_Add(Map.TacticalCoord, XY_Coord(1, 0));\n\tMap.Set_Tactical_Position(origin_coord);\n\torigin_coord = Coord_Add(Map.TacticalCoord, XY_Coord(-1, 0));\n\tMap.Set_Tactical_Position(origin_coord);\n\n\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tMPSuperWeaponDisable = false;\n\t} else {\n\t\tif (MPSuperWeaponDisable) {\n\t\t\t/*\n\t\t\t** Write over the tecb level settings we just loaded from the Rules ini\n\t\t\t*/\n\t\t\tRule.GPSTechLevel = 100;\n\t\t\tRule.ParaInfantryTechLevel = 100;\n\t\t\tRule.SpyPlaneTechLevel = 100;\n\t\t\tRule.ParaBombTechLevel = 100;\n\t\t\tRule.ChronoTechLevel = 100;\n\t\t}\t\n\t}\t\n\n\t/*\n\t**\tHide the SeenBuff; force the map to render one frame.  The caller can\n\t**\tthen fade the palette in.\n\t**\t(If we loaded a game, this step will fade out the title screen.  If we\n\t**\tstarted a scenario, Start_Scenario() will have played a couple of VQ\n\t**\tmovies, which will have cleared the screen to black already.)\n\t*/\n\n\t//Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n\tSet_Logic_Page(SeenBuff);\n\t\n\t/*\n\t** Sidebar is always active in hi-res.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n\t}\n\t\n\tMap.Flag_To_Redraw(true);\n\n\tSet_Palette(GamePalette.Get_Data());\n\tMap.Render();\n\n\tSet_Palette(GamePalette.Get_Data());\n\t\n\treturn true;\n}\n\n\n/**************************************************************************************************\n* CNC_Read_INI -- Load an ini file into the supplied buffer\n*\n* In:   Map initialization parameters\n*\n* Out:  false if ini load failed\n*\n*\n* History: 12/16/2019 11:44AM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Read_INI(int scenario_index, int scenario_variation, int scenario_direction, const char *content_directory, const char *override_map_name, char *ini_buffer, int _ini_buffer_size)\n{\n\tif (content_directory == NULL) {\n\t\treturn false;\n\t}\n\n\tDLLExportClass::Set_Content_Directory(content_directory);\n\n\tScen.Scenario = scenario_index;\n\tScenarioDirType scen_dir = (ScenarioDirType)scenario_direction;\n\t\n\tGAME_TO_PLAY = GAME_GLYPHX_MULTIPLAYER;\n\tScenarioPlayerType scen_player = SCEN_PLAYER_MPLAYER;\n\n\tForce_CD_Available(ALWAYS_RELOAD_CD);\n\n\tif (override_map_name && strlen(override_map_name)) {\n\t\tstrcpy(Scen.ScenarioName, override_map_name);\n\t} else {\n\t\tScen.Set_Scenario_Name(Scen.Scenario, scen_player, scen_dir, (ScenarioVarType)scenario_variation);\n\t}\n\n\n\tif (_ini_buffer_size < _ShapeBufferSize) {\n\t\tGlyphX_Debug_Print(\"INI file buffer may be too small\");\n\t\treturn false;\n\t}\n\n\tif (!ini_buffer) {\n\t\tGlyphX_Debug_Print(\"No INI file buffer\");\n\t\treturn false;\n\t}\n\n\tmemset(ini_buffer, _ini_buffer_size, 0);\n\n\tCCFileClass file(Scen.ScenarioName);\n\tif (!file.Is_Available()) {\n\t\tGlyphX_Debug_Print(\"Failed to find scenario file\");\n\t\tGlyphX_Debug_Print(Scen.ScenarioName);\n\t\treturn(false);\n\n\t} else {\n\t\t\n\t\tGlyphX_Debug_Print(\"Opened scenario file\");\n\t\tGlyphX_Debug_Print(Scen.ScenarioName);\n\t\t\n\t\tint bytes_read = file.Read(ini_buffer, _ini_buffer_size-1);\n\t\tif (bytes_read == _ini_buffer_size - 1) {\n\t\t\tGlyphX_Debug_Print(\"INI file buffer is too small\");\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/*\n\t** Ini buffer should be zero terminated\n\t*/\n\tif ((int) strlen(ini_buffer) >= _ini_buffer_size) {\n\t\tGlyphX_Debug_Print(\"INI file buffer overrun\");\n\t\treturn false;\n\t}\n\n\treturn true;\n}\t\t\t  \n\n\n/**************************************************************************************************\n* CNC_Start_Custom_Instance -- Load and start a custom map\n*\n* In:   Map initialization parameters\n*\n* Out:  false if map load failed\n*\n*\n*\n* History: 2019/10/28 - JAS\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Start_Custom_Instance(const char* content_directory, const char* directory_path, const char* scenario_name, int build_level, bool multiplayer)\n{\n\n\tDLLExportClass::Set_Content_Directory(content_directory);\n\n\tchar\tfullname[_MAX_FNAME + _MAX_EXT];\n\n\tsnprintf(fullname, _MAX_FNAME + _MAX_EXT, \"%s%s.mpr\", directory_path, scenario_name);\n\n\n\tchar name_buffer[128];\n\tchar digest_buffer[32];\n\n\tCCFileClass file(fullname);\n\n\tINIClass ini;\n\tini.Load(file);\n\n\tini.Get_String(\"Basic\", \"Name\", \"No Name\", name_buffer, sizeof(name_buffer));\n\tini.Get_String(\"Digest\", \"1\", \"No Digest\", digest_buffer, sizeof(digest_buffer));\n\tSession.Scenarios.Add(new MultiMission(fullname, name_buffer, digest_buffer, ini.Get_Bool(\"Basic\", \"Official\", false), false));\n\n\n\tBuildLevel = build_level;\n\n\tScenarioPlayerType scen_player;\n\tstrncpy(Scen.ScenarioName, fullname, _MAX_FNAME + _MAX_EXT);\n\n\tif (multiplayer) {\n\t\tGAME_TO_PLAY = GAME_GLYPHX_MULTIPLAYER;\n\t} else {\n\t\tGAME_TO_PLAY = GAME_NORMAL;\n\t}\t\n\tscen_player = SCEN_PLAYER_MPLAYER;\n\n\t//Scen.Scenario = scenario_index;\n\t//ScenarioDirType scen_dir = (ScenarioDirType)scenario_direction;\n\n\t//if (stricmp(game_type, \"GAME_NORMAL\") == 0) {\n\t//\tGAME_TO_PLAY = GAME_NORMAL;\n\t//}\n\t//else {\n\t//\tif (stricmp(game_type, \"GAME_GLYPHX_MULTIPLAYER\") == 0) {\n\t//\t\tGAME_TO_PLAY = GAME_GLYPHX_MULTIPLAYER;\n\t//\t\tscen_player = SCEN_PLAYER_MPLAYER;\n\t//\t}\n\t//\telse {\n\t//\t\treturn false;\n\t//\t}\n\t//}\n\n\t///*\n\t//**\tLoad the scenario.  Specify variation 'A' for the editor; for the game,\n\t//**\tdon't specify a variation, to make 'Set_Scenario_Name()' pick a random one.\n\t//**\tSkip this if we've already loaded a save-game.\n\t//*/\n\n\t//Force_CD_Available(ALWAYS_RELOAD_CD);\n\n\t//if (override_map_name && strlen(override_map_name)) {\n\t//\tstrcpy(Scen.ScenarioName, override_map_name);\n\t//}\n\t//else {\n\t//\tScen.Set_Scenario_Name(Scen.Scenario, scen_player, scen_dir, (ScenarioVarType)scenario_variation);\n\t//}\n\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n\n\t/*\n\t** Set the mouse to some position where it's not going to scroll, or do something else wierd.\n\t*/\n\tDLLForceMouseX = 100;\n\tDLLForceMouseY = 100;\n\tKEYBOARD->MouseQX = 100;\n\tKEYBOARD->MouseQY = 100;\n\n\tGlyphXClientSidebarWidthInLeptons = 0;\n\n\tSeed = GetRandSeed();\n\tScen.RandomNumber = Seed;\n\n\tif (!Start_Scenario(Scen.ScenarioName)) {\n\t\treturn(false);\n\t}\n\n\tDLLExportClass::Reset_Sidebars();\n\tDLLExportClass::Reset_Player_Context();\n\tDLLExportClass::Calculate_Start_Positions();\n\n\t/*\n\t** Make sure the scroll constraints are applied. This is important for GDI 1 where the map isn't wide enough for the screen\n\t*/\n\tCOORDINATE origin_coord = Coord_Add(Map.TacticalCoord, XY_Coord(1, 0));\n\tMap.Set_Tactical_Position(origin_coord);\n\torigin_coord = Coord_Add(Map.TacticalCoord, XY_Coord(-1, 0));\n\tMap.Set_Tactical_Position(origin_coord);\n\n\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tMPSuperWeaponDisable = false;\n\t}\n\telse {\n\t\tif (MPSuperWeaponDisable) {\n\t\t\t/*\n\t\t\t** Write over the tecb level settings we just loaded from the Rules ini\n\t\t\t*/\n\t\t\tRule.GPSTechLevel = 100;\n\t\t\tRule.ParaInfantryTechLevel = 100;\n\t\t\tRule.SpyPlaneTechLevel = 100;\n\t\t\tRule.ParaBombTechLevel = 100;\n\t\t\tRule.ChronoTechLevel = 100;\n\t\t}\n\t}\n\n\t/*\n\t**\tHide the SeenBuff; force the map to render one frame.  The caller can\n\t**\tthen fade the palette in.\n\t**\t(If we loaded a game, this step will fade out the title screen.  If we\n\t**\tstarted a scenario, Start_Scenario() will have played a couple of VQ\n\t**\tmovies, which will have cleared the screen to black already.)\n\t*/\n\n\t//Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n\tSet_Logic_Page(SeenBuff);\n\t/*\n\t** Sidebar is always active in hi-res.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n\t}\n\tMap.Flag_To_Redraw(true);\n\n\tSet_Palette(GamePalette.Get_Data());\n\tMap.Render();\n\n\tSet_Palette(GamePalette.Get_Data());\n\n\treturn true;\n}\n\n\nbool Debug_Write_Shape_Type(const ObjectTypeClass *type, int shapenum)\n{\t\t\n\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\tchar\tbuffer[_MAX_FNAME];\n\tCCFileClass\tfile;\n\n\tif (type->ImageData != NULL) {\n\n\t\tsprintf(buffer, \"%s_%d\", type->IniName, shapenum);\n\t\t_makepath(fullname, NULL, NULL, buffer, \".PCX\");\n\n\t\treturn Debug_Write_Shape(fullname, type->ImageData, shapenum);\n\t}\n\n\treturn false;\n}\n\n\nbool Debug_Write_Shape(const char *file_name, void const * shapefile, int shapenum, int flags, void const * ghostdata)\n{\n\t/*\n\t** Build frame returns a pointer now instead of the shapes length\n\t*/\n\tchar *shape_pointer = (char*) Build_Frame(shapefile , shapenum , _ShapeBuffer);\n\tif (shape_pointer == NULL) {\n\t\treturn false;;\n\t}\n\tif (Get_Last_Frame_Length() > _ShapeBufferSize) {\n\t\treturn false;;\n\t}\n\n\tint width = Get_Build_Frame_Width(shapefile);\n\tint height = Get_Build_Frame_Height(shapefile);\n\n\tGraphicBufferClass temp_gbuffer(width, height);\n\tGraphicViewPortClass\ttemp_viewport(&temp_gbuffer, 0, 0, width, height);\n\n\tWindowList[WINDOW_CUSTOM][WINDOWX] = 0;\n\tWindowList[WINDOW_CUSTOM][WINDOWY] = 0;\n\tWindowList[WINDOW_CUSTOM][WINDOWWIDTH] = width;\n\tWindowList[WINDOW_CUSTOM][WINDOWHEIGHT] = height;\n\n\tstatic const char _shape_trans = 0x40;\n\n\tif (flags == 0) {\n\t\tBuffer_Frame_To_Page(0, 0, width, height, shape_pointer, temp_viewport, SHAPE_NORMAL|SHAPE_WIN_REL|_shape_trans);\t//, ghostdata, predoffset);\n\t} else {\n\t\tBuffer_Frame_To_Page(0, 0, width, height, shape_pointer, temp_viewport, flags, ghostdata);\n\t}\t\n\tWrite_PCX_File((char*)file_name, temp_viewport, (unsigned char*)GamePalette.Get_Data());\n\treturn true;\n}\n\n\n\n/**************************************************************************************************\n* CNC_Advance_Instance -- Process one logic frame\n*\n* In:   \n*\n* Out:  Is game still playing?\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Advance_Instance(uint64 player_id)\n{\n\t//DLLExportClass::Set_Event_Callback(event_callback);\n\n\tif (Frame <= 10) {\t\t// Don't spam forever, but useful to know that we actually started advancing\n\t\tGlyphX_Debug_Print(\"CNC_Advance_Instance - RA\");\n\t}\n\n\t/*\n\t** Shouldn't really need to do this, but I like the idea of always running the main loop in the context of the same player.\n\t** Might make tbe bugs more repeatable and consistent. ST - 3/15/2019 11:58AM\n\t*/\n\tif (player_id != 0) {\n\t\tDLLExportClass::Set_Player_Context(player_id);\n\t} else {\n\t\tDLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0]);\n\t}\n\n\t/*\n\t** Restore special from backup\n\t*/\n\tif (SpecialBackup != NULL) {\n\t\tmemcpy(&Special, SpecialBackup, sizeof(SpecialClass));\n\t}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tTimeQuake = PendingTimeQuake;\n\tPendingTimeQuake = false;\n#else\n\tTimeQuake = false;\n#endif\n\t\t\t\n\t/*\n\t** Allocate extra memory for uncompressed shapes as needed\n\t*/\n\tReallocate_Big_Shape_Buffer();\n\n\t/*\n\t**\tIf there is no theme playing, but it looks like one is required, then start one\n\t**\tplaying. This is usually the symptom of there being no transition score.\n\t*/\n\t//if (SampleType && Theme.What_Is_Playing() == THEME_NONE) {\n\t//\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t//}\n\n\t/*\n\t**\tUpdate the display, unless we're inside a dialog.\n\t*/\n\t//if (SpecialDialog == SDLG_NONE && GameInFocus) {\n\n\t\t//WWMouse->Erase_Mouse(&HidPage, TRUE);\n\t\t//Map.Input(input, x, y);\n\t\t//if (input) {\n\t\t//\tKeyboard_Process(input);\n\t\t//}\n\t\t/*\n\t\t** The main loop passes these in uninitialized. ST - 2/7/2019 4:36PM\n\t\t*/\n\t\tKeyNumType input = KN_NONE;\t\t\t\t\t// Player input.\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tMap.Input(input, x, y);\n\t\t//if (input) {\n\t\t//\tKeyboard_Process(input);\n\t\t//}\n\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t/*\n\t\t\t** Process the sidebar. ST - 4/18/2019 11:59AM\n\t\t\t*/\n\t\t\tHouseClass *old_player_ptr = PlayerPtr;\n\t\t\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\tDLLExportClass::Logic_Switch_Player_Context(player_ptr);\n\t\t\t\tSidebar_Glyphx_AI(player_ptr, input);\n\t\t\t}\n\t\t\tDLLExportClass::Logic_Switch_Player_Context(old_player_ptr);\n\t\t}\n\n\t//}\n\n\t/*\n\t** Sort the map's ground layer by y-coordinate value.  This is done\n\t** outside the IsToRedraw check, for the purposes of game sync'ing\n\t** between machines; this way, all machines will sort the Map's\n\t** layer in the same way, and any processing done that's based on\n\t** the order of this layer will sync on different machines.\n\t*/\n\tMap.Layer[LAYER_GROUND].Sort();\n\n\t/*\n\t**\tAI logic operations are performed here.\n\t*/\n\t//Skip this block of code on first update of single-player games. This helps prevents trigger generated messages on the first update from being lost during loading screen or movie. - LLL\n\tstatic bool FirstUpdate = GAME_TO_PLAY != GAME_GLYPHX_MULTIPLAYER;;\n\tif (!FirstUpdate) {\n\t\tHouseClass *old_player_ptr = PlayerPtr;\n\t\tLogic.Clear_Recently_Created_Bits();\n\t\tLogic.AI();\n\t\tDLLExportClass::Logic_Switch_Player_Context(old_player_ptr);\n\t}\n\tFirstUpdate = false;\n\n\tTimeQuake = false;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (!PendingTimeQuake) {\n\t\tTimeQuakeCenter = 0;\n\t}\n#endif\n\n\t/*\n\t**\tManage the inter-player message list.  If Manage() returns true, it means\n\t**\ta message has expired & been removed, and the entire map must be updated.\n\t*/\n\tif (Session.Messages.Manage()) {\n#ifdef WIN32\n\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\tHidPage.Clear();\n#endif\t//WIN32\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\t/*\n\t**\tProcess all commands that are ready to be processed.\n\t*/\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tQueue_AI();\n\t} else {\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tDLLExportClass::Glyphx_Queue_AI();\n\n\t\t\t/*\n\t\t\t** Process the sidebar. ST - 3/22/2019 2:07PM\n\t\t\t*/\n\t\t\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\tSidebar_Glyphx_Recalc(player_ptr);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tKeep track of elapsed time in the game.\n\t*/\n\t//Score.ElapsedTime += TIMER_SECOND / TICKS_PER_SECOND;\n\n\t/*\n\t**\tPerform any win/lose code as indicated by the global control flags.\n\t*/\n\t/*\n\t**\tCheck for player wins or loses according to global event flag.\n\t*/\n\tif (PlayerWins) {\n\n\t\t//WWMouse->Erase_Mouse(&HidPage, TRUE);\n\t\tPlayerLoses = false;\n\t\tPlayerWins = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tGlyphX_Debug_Print(\"PlayerWins = true\");\n\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tDLLExportClass::On_Multiplayer_Game_Over();\n\t\t} else {\n\t\t\tDLLExportClass::On_Game_Over(player_id, true);\n\t\t}\n\n\t\t//DLLExportClass::Set_Event_Callback(NULL);\n\t\treturn false;\n\t}\n\tif (PlayerLoses) {\n\n\t\t//WWMouse->Erase_Mouse(&HidPage, TRUE);\n\t\tPlayerWins = false;\n\t\tPlayerLoses = false;\n\t\tPlayerRestarts = false;\n\t\tMap.Help_Text(TXT_NONE);\n\t\tGlyphX_Debug_Print(\"PlayerLoses = true\");\n\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tDLLExportClass::On_Multiplayer_Game_Over();\n\t\t} else {\n\t\t\tDLLExportClass::On_Game_Over(player_id, false);\n\t\t}\n\n\t\t//DLLExportClass::Set_Event_Callback(NULL);\n\t\treturn false;\n\t}\n\n\t/*\n\t**\tThe frame logic has been completed. Increment the frame\n\t**\tcounter.\n\t*/\n\tFrame++;\n\n\t/*\n\t** Very rarely, the human players will get a message from the computer.\n\t**\n\t** This was disabled in the RA source code, so copying over the functionality from TD\n\t*/\n\tif (GAME_TO_PLAY != GAME_NORMAL && Session.Options.Ghosts && IRandom(0,10000) == 1) {\n\t\tDLLExportClass::Computer_Message(false);\n\t}\n\n\tif (ProgEndCalled) {\n\t\tGlyphX_Debug_Print(\"ProgEndCalled - GameActive = false\");\n\t\tGameActive = false;\n\t}\n\n\tif (DLLExportClass::Legacy_Render_Enabled()) {\n\t\tMap.Render();\n\t}\n\n\t//Sync_Delay();\n\t//DLLExportClass::Set_Event_Callback(NULL);\n\tColor_Cycle();\n\t\n\t\n\t/*\n\t** Don't respect GameActive. Game will end in multiplayer on win/loss\n\t*/\n\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\treturn true;\n\t}\n\n\treturn(GameActive);\n}\n\n\n\n/**************************************************************************************************\n* CNC_Save_Load -- Process a save or load game action\n*\n* In:   \n*\n* Out:  Success?\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Save_Load(bool save, const char *file_path_and_name, const char *game_type)\n{\n\tbool result = false;\n\t\n\tif (save) {\n\t\tresult = Save_Game(file_path_and_name, \"internal\");\n\t} else {\n\t\t\n\t\tif (game_type == NULL) {\n\t\t\treturn false;\n\t\t}\n\t\n\t\tif (stricmp(game_type, \"GAME_NORMAL\") == 0) {\n\t\t\tGAME_TO_PLAY = GAME_NORMAL;\n\t\t} else {\n\t\t\tif (stricmp(game_type, \"GAME_GLYPHX_MULTIPLAYER\") == 0) {\n\t\t\t\tGAME_TO_PLAY = GAME_GLYPHX_MULTIPLAYER;\n\t\t\t\t//ScenPlayer = SCEN_PLAYER_MPLAYER;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\twhile (Session.Players.Count() > 0) {\n\t\t\tdelete Session.Players[0];\n\t\t\tSession.Players.Delete(Session.Players[0]);\n\t\t}\n\t\t\n\t\tresult = Load_Game(file_path_and_name);\n\n\t\tif (result == false)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tDLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0], true);\n\t\tDLLExportClass::Cancel_Placement(DLLExportClass::GlyphxPlayerIDs[0], -1, -1);\n\t\tSet_Logic_Page(SeenBuff);\n\t\tVisiblePage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tif (DLLExportClass::Legacy_Render_Enabled()) {\n\t\t\tMap.Render();\n\t\t}\n\t\tSet_Palette(GamePalette.Get_Data());\n\t}\n\n\treturn result;\n}\n\n\n/**************************************************************************************************\n* CNC_Set_Difficulty -- Set game difficulty\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 10/02/2019 - SKY\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Set_Difficulty(int difficulty)\n{\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tSet_Scenario_Difficulty(difficulty);\n\t}\n}\n\n\n/**************************************************************************************************\n* CNC_Restore_Carryover_Objects\n*\n* History: 11/15/2019 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Restore_Carryover_Objects(const CarryoverObjectStruct* objects)\n{\n\t//Delete the list\n\twhile (Carryover) {\n\t\tCarryoverClass* cptr = (CarryoverClass*)Carryover->Get_Next();\n\t\tdelete Carryover;\n\t\tCarryover = cptr;\n\t}\n\n\t//Populate the list\n\tconst CarryoverObjectStruct* next_object = objects;\n\twhile (next_object) {\n\t\tCarryoverClass* cptr = new CarryoverClass();\n\n\t\tcptr->RTTI = (RTTIType)next_object->RTTI;\n\t\tcptr->Type.Building = (StructType)next_object->Type; //This works regardless of what the RTTI-type and the enum type, because they're all enums. - LLL\n\t\tcptr->Cell = (CELL)next_object->Cell;\n\t\tcptr->House = (HousesType)next_object->House;\n\t\tcptr->Strength = next_object->Strength;\n\n\t\tnext_object = next_object->Next;\n\n\t\tif (Carryover == NULL) {\n\t\t\tCarryover = cptr;\n\t\t}\n\t\telse {\n\t\t\tcptr->Add_Tail(*Carryover);\n\t\t}\n\t}\n}\n\n\n\n/**************************************************************************************************\n* CNC_Handle_Player_Switch_To_AI -- Renamed 3/9/2020 - LLL\n* CNC_Handle_Player_Disconnect -- Handle player disconnected during multiplayer game\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 12/3/2019 1:46PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Player_Switch_To_AI(uint64 player_id)\n{\n\tif (PlayerWins || PlayerLoses || DLLExportClass::Get_Game_Over()) {\n\t\treturn;\n\t}\n\n\tGlyphX_Debug_Print(\"CNC_Handle_Player_Switch_To_AI\");\n\t\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\treturn;\n\t}\n\n#ifdef KILL_PLAYER_ON_DISCONNECT\n\n\t/*\n\t** Kill player's units on disconnect.\n\t*/\n\tif (player_id != 0) {\n\t\tDLLExportClass::Set_Player_Context(player_id);\n\n\t\tif (PlayerPtr) {\n\t\t\tPlayerPtr->Flag_To_Die();\n\t\t}\n\t}\n\n#else //KILL_PLAYER_ON_DISCONNECT\n\n\tif (player_id != 0) {\n\t\t\n\t\tHousesType house;\n  \t\tHouseClass *ptr;\n\t\n\t\tDLLExportClass::Set_Player_Context(player_id);\n\n\t\tif (PlayerPtr) {\n\t\t\tPlayerPtr->WasHuman = true;\n\t\t\tPlayerPtr->IsHuman = false;\n\t\t\tPlayerPtr->IQ = Rule.MaxIQ;\n\t\t\tstrcpy (PlayerPtr->IniName, Text_String(TXT_COMPUTER));\n\n\t\t\tPlayerPtr->IsBaseBuilding = true;\n\n\t\t\t/*\n\t\t\t** Start the unload mission for MCVs\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass * obj = Units.Ptr(index);\n\n\t\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr) {\n\t\t\t\t\tif (*obj == UNIT_MCV) {\n\t\t\t\t\t\tobj->Assign_Mission(MISSION_GUARD);\n\t\t\t\t\t\tobj->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\tobj->Assign_Destination(TARGET_NONE);\n\t\t\t\t\t\tobj->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t\t\tobj->Commence();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDLLExportClass::On_Message(PlayerPtr, \"\", 60.0f, MESSAGE_TYPE_PLAYER_DISCONNECTED, -1);\n\n\t\t\t/*\n\t\t\t** Send the disconnect taunt message\n\t\t\t*/\n\t\t\tint human_count = 0;\n\t\t\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + MULTIPLAYER_COUNT); house++) {\n\t\t\t\tptr = HouseClass::As_Pointer(house);\n\n\t\t\t\tif (ptr && ptr->IsHuman && !ptr->IsDefeated) {\n\t\t\t\t\thuman_count++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (human_count == 1) {\n\t\t\t\tDLLExportClass::Computer_Message(true);\n\t\t\t}\n\t\t}\n\t}\n\n#endif //KILL_PLAYER_ON_DISCONNECT\n\n}\n\n\n/**************************************************************************************************\n* CNC_Handle_Human_Team_Wins\n*\n* History: 3/10/2020 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Human_Team_Wins(uint64 quitting_player_id)\n{\n\tGlyphX_Debug_Print(\"CNC_Handle_Human_Team_Wins\");\n\tDLLExportClass::Force_Human_Team_Wins(quitting_player_id);\n}\n\n\n/**************************************************************************************************\n* CNC_Start_Mission_Timer\n*\n* History: 11/25/2019 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Start_Mission_Timer(int time)\n{\n\tif (GameActive)\n\t{\n\t\tScen.MissionTimer = time;\n\n\t\tif (!Scen.MissionTimer.Is_Active()) {\n\t\t\tScen.MissionTimer.Start();\n\t\t}\n\n\t\tMap.Redraw_Tab();\n\t}\n}\n\n\n/**************************************************************************************************\n* CNC_Get_Start_Game_Info\n*\n* History: 8/31/2020 11:37AM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Start_Game_Info(uint64 player_id, int &start_location_waypoint_index)\n{\n\tstart_location_waypoint_index = 0;\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\t\n\tstart_location_waypoint_index = PlayerPtr->StartLocationOverride;\n\treturn true;\n}\n\n\n/**************************************************************************************************\n* Is_Legacy_Render_Enabled -- Is the legacy rendering enabled?\n*\n* In:   \n*\n* Out: True if only one human player \n*\n*\n*\n* History: 8/25/2020 5:55PM - ST\n**************************************************************************************************/\nbool Is_Legacy_Render_Enabled(void)\n{\n\treturn DLLExportClass::Legacy_Render_Enabled();\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Init -- Init the class\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/12/2019 10:52AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Init(void)\n{\n\tfor (int i=0 ; i<MAX_PLAYERS ; i++) {\n\t\tGlyphxPlayerIDs[i] = 0xffffffffull;\n\t}\n\n\tCurrentLocalPlayerIndex = 0;\n\n\tMessagesSent.clear();\n\n\tif (SpecialBackup == NULL) {\n\t\tSpecialBackup = new SpecialClass;\n\t}\n\tmemcpy(SpecialBackup, &Special, sizeof(SpecialClass));\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Shutdown -- Shutdown\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/20/2020 1:59PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Shutdown(void)\n{\n\tdelete SpecialBackup;\n\tSpecialBackup = NULL;\n\n\tfor (int i=0 ; i<ModSearchPaths.Count() ; i++) {\n\t\tdelete [] ModSearchPaths[i];\n\t}\n\tModSearchPaths.Clear();\n}\n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Add_Mod_Path -- Add a path to load mod files from\n*\n* In: Mod path  \n*\n* Out:  \n*\n*\n*\n* History: 2/20/2020 2:03PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Add_Mod_Path(const char *mod_path)\n{\n\tchar *copy_path = strdup(mod_path);\n\tModSearchPaths.Add(copy_path);\n}\n\t\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Set_Content_Directory -- Update the locations that the original code will load from\n*\n* In: Main (official) content directory\n*\n* Out:  \n*\n*\n*\n* History: 2/20/2020 2:03PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Set_Content_Directory(const char *content_directory)\n{\n\tCCFileClass::Clear_Search_Drives();\n\tCCFileClass::Reset_Raw_Path();\n\n\tif ((content_directory == NULL || strlen(content_directory) == 0) && ModSearchPaths.Count() == 0) {\n\t\treturn;\n\t}\n\n\tchar *all_paths = new char [_MAX_PATH * 100];\n\t*all_paths = 0;\n\n\tfor (int i=0 ; i<ModSearchPaths.Count() ; i++) {\n\t\tif (i != 0) {\n\t\t\tstrcat(all_paths, \";\");\n\t\t}\n\t\tstrcat(all_paths, ModSearchPaths[i]);\n\t}\n\n\tif (ModSearchPaths.Count() && content_directory && strlen(content_directory)) {\n\t\tstrcat(all_paths, \";\");\n\t}\n\tif (content_directory) {\n\t\tstrcat(all_paths, content_directory);\n\t}\n\n\tCCFileClass::Set_Search_Drives(all_paths);\n\tdelete [] all_paths;\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Config\n*\n* History: 1/16/2020 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::Config(const CNCRulesDataStruct& rules)\n{\n\tfor (int i = 0; i < 3; ++i)\n\t{\n\t\tRule.Diff[i].FirepowerBias = rules.Difficulties[i].FirepowerBias;\n\t\tRule.Diff[i].GroundspeedBias = rules.Difficulties[i].GroundspeedBias;\n\t\tRule.Diff[i].AirspeedBias = rules.Difficulties[i].AirspeedBias;\n\t\tRule.Diff[i].ArmorBias = rules.Difficulties[i].ArmorBias;\n\t\tRule.Diff[i].ROFBias = rules.Difficulties[i].ROFBias;\n\t\tRule.Diff[i].CostBias = rules.Difficulties[i].CostBias;\n\t\tRule.Diff[i].BuildSpeedBias = rules.Difficulties[i].BuildSpeedBias;\n\t\tRule.Diff[i].RepairDelay = rules.Difficulties[i].RepairDelay;\n\t\tRule.Diff[i].BuildDelay = rules.Difficulties[i].BuildDelay;\n\t\tRule.Diff[i].IsBuildSlowdown = rules.Difficulties[i].IsBuildSlowdown ? 1 : 0;\n\t\tRule.Diff[i].IsWallDestroyer = rules.Difficulties[i].IsWallDestroyer ? 1 : 0;\n\t\tRule.Diff[i].IsContentScan = rules.Difficulties[i].IsContentScan ? 1 : 0;\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Set_Home_Cell\n*\n* History: 2/14/2020 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Set_Home_Cell(int x, int y, uint64 player_id)\n{\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tMultiplayerStartPositions[0] = XY_Cell(x, y);\n\t}\n\telse {\n\t\tfor (int i = 0; i < MAX_PLAYERS && i < 4; i++) {\n\t\t\tif (GlyphxPlayerIDs[i] == player_id) {\n\t\t\t\tMultiplayerStartPositions[i] = XY_Cell(x, y);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::On_Play_Movie\n*\n* History: 7/23/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::On_Play_Movie(const char * movie_name, ThemeType theme, bool immediate)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_MOVIE;\n\tnew_event.Movie.MovieName = movie_name;\n\tnew_event.Movie.Theme = (int)theme;\n\tnew_event.Movie.Immediate = immediate;\n\n\tEventCallback(new_event);\n}\n\n/**************************************************************************************************\n* DLLExportClass::On_Display_Briefing_Text\n*\n* Called when Red Alert wants to display the mission breifing screen before a mission.\n*\n* History: 12/04/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::On_Display_Briefing_Text()\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_BRIEFING_SCREEN;\n\tEventCallback(new_event);\n}\n\n/**************************************************************************************************\n* DLLExportClass::On_Sound_Effect -- Called when C&C wants to play a sound effect\n*\n* In:   \n*\n* Out:\n*\n*\n*\n* History: 2/20/2019 2:39PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::On_Sound_Effect(const HouseClass* player_ptr, int sound_effect_index, const char* extension, int variation, COORDINATE coord)\n{\n\t// player_ptr could be NULL\n\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_SOUND_EFFECT;\n\tnew_event.SoundEffect.SFXIndex = sound_effect_index;\n\tnew_event.SoundEffect.Variation = variation;\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif ( player_ptr != NULL ) \n\t{\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tif ( coord == 0 ) \n\t{\n\t\tnew_event.SoundEffect.PixelX = -1;\n\t\tnew_event.SoundEffect.PixelY = -1;\n\t}\n\telse\n\t{\n\t\t// Use world pixel coordinates\n\t\tnew_event.SoundEffect.PixelX = Lepton_To_Pixel(Coord_X(coord));\n\t\tnew_event.SoundEffect.PixelY = Lepton_To_Pixel(Coord_Y(coord));\n\t}\n\n\tif ( sound_effect_index >= VOC_FIRST && sound_effect_index < VOC_COUNT )\t\n\t{\n\t\tstrncpy( new_event.SoundEffect.SoundEffectName, SoundEffectName[ sound_effect_index ].Name , 16);\n\t\tif ( extension != NULL ) \n\t\t{\n\t\t\tstrncat( new_event.SoundEffect.SoundEffectName, extension , 16);\n\t\t}\n\t\tnew_event.SoundEffect.SoundEffectPriority = SoundEffectName[ sound_effect_index ].Priority;\n\t\tnew_event.SoundEffect.SoundEffectContext = SoundEffectName[ sound_effect_index ].Where;\n\t}\n\telse\n\t{\n\t\tstrncpy( new_event.SoundEffect.SoundEffectName, \"BADINDEX\", 16 );\n\t\tnew_event.SoundEffect.SoundEffectPriority = -1;\n\t\tnew_event.SoundEffect.SoundEffectContext = -1;\n\t}\n\n\tEventCallback(new_event);\n}\n\n\n\t  \n/**************************************************************************************************\n* DLLExportClass::On_Speech -- Called when C&C wants to play a speech line\n*\n* In:   \n*\n* Out:\n*\n*\n*\n* History: 2/20/2019 2:39PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::On_Speech(const HouseClass* player_ptr, int speech_index)\n{\n\t// player_ptr could be NULL\n\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_SPEECH;\n\tnew_event.Speech.SpeechIndex = speech_index;\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL)\n\t{\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tif (speech_index >= VOX_FIRST && speech_index < VOX_COUNT)\n\t{\n\t\tstrncpy(new_event.Speech.SpeechName, Speech[speech_index], 16);\n\t}\n\telse\n\t{\n\t\tstrncpy(new_event.Speech.SpeechName, \"BAD_SPEECH_INDEX\", 16);\n\t}\n\n\tEventCallback(new_event);\n}\n\n/**************************************************************************************************\n* DLLExportClass::RA_Calculate_Leadership --\n*\n* History: 10.30.2019 MBL (Based on LLL's Calculate_Single_Player_Score())\n**************************************************************************************************/\nint DLLExportClass::RA_Calculate_Leadership( HousesType player_house, int units_lost, int buildings_lost )\n{\n\tint house = (player_house == HOUSE_USSR || player_house == HOUSE_UKRAINE);\t// 0 or 1\n\n\tint leadership = 0;\n\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\tObjectClass* object = Logic[index];\n\t\tHousesType owner = object->Owner();\n\t\tif ((house) && (owner == HOUSE_USSR || owner == HOUSE_BAD || owner == HOUSE_UKRAINE)) {\n\t\t\tleadership++;\n\t\t}\n\t\telse {\n\t\t\tif ((!house) && (object->Owner() == HOUSE_GREECE)) {\n\t\t\t\tleadership++;\n\t\t\t}\n\t\t}\n\t}\n\tif (!leadership) leadership++;\n\tleadership = 100 * fixed(leadership, (units_lost + buildings_lost + leadership));\n\tleadership = min(150, leadership);\n\n\treturn leadership;\n}\n\n/**************************************************************************************************\n* DLLExportClass::RA_Calculate_Economy --\n*\n* History: 10.30.2019 MBL (Based on LLL's Calculate_Single_Player_Score())\n**************************************************************************************************/\nint DLLExportClass::RA_Calculate_Economy( long available_money, int stolen_buildings_credits, unsigned harvested_credits, long initial_credits )\n{\n\tint economy = 100 * fixed((unsigned)available_money + 1 + stolen_buildings_credits, harvested_credits + (unsigned)initial_credits + 1);\n\teconomy = min(economy, 150);\n\n\treturn economy;\n}\n\n/**************************************************************************************************\n* DLLExportClass::RA_Calculate_Score --\n*\n* History: 10.30.2019 MBL (Based on LLL's Calculate_Single_Player_Score())\n**************************************************************************************************/\nint DLLExportClass::RA_Calculate_Score( int uspoints, int leadership, int economy )\n{\n\tint score_total = ((uspoints * leadership) / 100) + ((uspoints * economy) / 100);\n\tif (score_total < -9999) score_total = -9999;\n\tscore_total = min(score_total, 99999);\n\n\treturn score_total;\n}\n\n/**************************************************************************************************\n* DLLExportClass::CalculateScore*\n*\n* History: 10/16/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Calculate_Single_Player_Score(EventCallbackStruct& event)\n{\n\t//Adapted from Red Alert SCORE.CPP Presentation() - LLL\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\t\t// 0 or 1\n\n\tint good_units_lost = (HouseClass::As_Pointer(HOUSE_GOOD))->UnitsLost;\n\tint bad_units_lost = (HouseClass::As_Pointer(HOUSE_BAD))->UnitsLost;\n\tint neutral_units_lost = (HouseClass::As_Pointer(HOUSE_NEUTRAL))->UnitsLost;\n\tint good_buildings_lost = (HouseClass::As_Pointer(HOUSE_GOOD))->BuildingsLost;\n\tint bad_buildings_lost = (HouseClass::As_Pointer(HOUSE_BAD))->BuildingsLost;\n\tint neutral_buildings_lost = (HouseClass::As_Pointer(HOUSE_NEUTRAL))->BuildingsLost;\n\tint good_credits_harvested = (HouseClass::As_Pointer(HOUSE_GOOD))->HarvestedCredits;\n\tint bad_credits_harvested = (HouseClass::As_Pointer(HOUSE_BAD))->HarvestedCredits;\n\n\tint uspoints = 0;\n\n\tfor (HousesType hous = HOUSE_SPAIN; hous <= HOUSE_BAD; hous++) {\n\t\tHouseClass *hows = HouseClass::As_Pointer(hous);\n\t\tif (hous == HOUSE_USSR || hous == HOUSE_BAD || hous == HOUSE_UKRAINE) {\n\t\t\tbad_units_lost += hows->UnitsLost;\n\t\t\tbad_buildings_lost += hows->BuildingsLost;\n\t\t}\n\t\telse {\n\t\t\tgood_units_lost += hows->UnitsLost;\n\t\t\tgood_buildings_lost += hows->BuildingsLost;\n\t\t}\n\t\tif (PlayerPtr->Is_Ally(hous)) {\n\t\t\tuspoints += hows->PointTotal;\n\t\t}\n\t}\n\t//\tif(uspoints < 0) uspoints = 0;\n\t//\tuspoints += 1000; //BG 1000 bonus points for winning mission\n\n\t/*\n\t**\tBias the base score upward according to the difficulty level.\n\t*/\n\tswitch (PlayerPtr->Difficulty) {\n\t\tcase DIFF_EASY:\n\t\tuspoints += 500;\n\t\tbreak;\n\n\t\tcase DIFF_NORMAL:\n\t\tuspoints += 1500;\n\t\tbreak;\n\n\t\tcase DIFF_HARD:\n\t\tuspoints += 3500;\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tDetermine leadership rating.\n\t*/\n\tint leadership = 0;\n\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\tObjectClass * object = Logic[index];\n\t\tHousesType owner = object->Owner();\n\t\tif ((house) && (owner == HOUSE_USSR || owner == HOUSE_BAD || owner == HOUSE_UKRAINE)) {\n\t\t\tleadership++;\n\t\t}\n\t\telse {\n\t\t\tif ((!house) && (object->Owner() == HOUSE_GREECE)) {\n\t\t\t\tleadership++;\n\t\t\t}\n\t\t}\n\t}\n\tif (!leadership) leadership++;\n\tleadership = 100 * fixed(leadership, (house ? bad_units_lost + bad_buildings_lost + leadership : good_units_lost + good_buildings_lost + leadership));\n\tleadership = min(150, leadership);\n\n\t/*\n\t**\tDetermine economy rating.\n\t*/\n\t// int init = PlayerPtr->Control.InitialCredits;\n\t// int cred = PlayerPtr->Available_Money();\n\n\tint economy = 100 * fixed((unsigned)PlayerPtr->Available_Money() + 1 + PlayerPtr->StolenBuildingsCredits, PlayerPtr->HarvestedCredits + (unsigned)PlayerPtr->Control.InitialCredits + 1);\n\teconomy = min(economy, 150);\n\n\tint score_total = ((uspoints * leadership) / 100) + ((uspoints * economy) / 100);\n\tif (score_total < -9999) score_total = -9999;\n\tscore_total = min(score_total, 99999);\n\n\t//Score Stats\n\tevent.GameOver.Leadership = leadership;\n\tevent.GameOver.Efficiency = economy;\n\tevent.GameOver.Score = score_total;\n\tevent.GameOver.CategoryTotal = uspoints;\n\tevent.GameOver.NODKilled = bad_units_lost;\n\tevent.GameOver.GDIKilled = good_units_lost;\n\tevent.GameOver.CiviliansKilled = neutral_units_lost;\n\tevent.GameOver.NODBuildingsDestroyed = bad_buildings_lost;\n\tevent.GameOver.GDIBuildingsDestroyed = good_buildings_lost;\n\tevent.GameOver.CiviliansBuildingsDestroyed = neutral_buildings_lost;\n\tevent.GameOver.RemainingCredits = PlayerPtr->Available_Money();\n\n\tif (Scen.IsSkipScore) {\n\t\tevent.GameOver.Score = -1;\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Message -- Called when the game wants to display a message (ex. tutorial text)\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 10/16/2019 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::On_Message(const HouseClass* player_ptr, const char* message, float timeout_seconds, EventCallbackMessageEnum message_type, int64 message_id)\n{\n\tif (EventCallback == NULL)\n\t{\n\t\treturn;\n\t}\n\n\tconst char* p_msg = message;\n\n\tstd::string localized_text_name;\n\tif (message_id != -1) {\n\t\tif (message_id == TXT_INSUFFICIENT_FUNDS) {\n\t\t\tlocalized_text_name = \"TEXT_INSUFFICIENT_FUNDS_MESSAGE\";\n\t\t}\n\t\telse if (message_id == TXT_LOW_POWER) {\n\t\t\tlocalized_text_name = \"TEXT_LOW_POWER_MESSAGE_001\";\n\t\t}\n\t\telse if (message_id == TXT_POWER_TESLA) {\n\t\t\tlocalized_text_name = \"TEXT_LOW_POWER_MESSAGE_002\";\n\t\t}\n\t\telse if (message_id == TXT_POWER_AAGUN) {\n\t\t\tlocalized_text_name = \"TEXT_LOW_POWER_MESSAGE_003\";\n\t\t}\n\t\telse {\n\t\t\tif (MessagesSent.find(message_id) != MessagesSent.end()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tMessagesSent.insert(message_id);\n\n\t\t\tlocalized_text_name = \"TEXT_RA_TUTORIAL_MESSAGE_\";\n\t\t\tlocalized_text_name += std::to_string(message_id);\n\t\t}\n\t\tp_msg = localized_text_name.c_str();\n\n\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_MESSAGE;\n\tnew_event.Message.Message = p_msg;\n\tnew_event.Message.TimeoutSeconds = timeout_seconds;\n\tnew_event.Message.MessageType = message_type;\n\tnew_event.Message.MessageParam1 = message_id;\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL)\n\t{\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tEventCallback(new_event);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Update_Map_Cell -- Called when an individual map cell template is updated\n*\n*\n* History: 11/7/2019 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::On_Update_Map_Cell(int cell_x, int cell_y, const char* template_type_name)\n{\n\tif (EventCallback == NULL)\n\t{\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_UPDATE_MAP_CELL;\n\tnew_event.UpdateMapCell.CellX = cell_x;\n\tnew_event.UpdateMapCell.CellY = cell_y;\n\tstrncpy(new_event.UpdateMapCell.TemplateTypeName, template_type_name, 32);\n\tnew_event.UpdateMapCell.TemplateTypeName[31] = '\\0';\n\n\tEventCallback(new_event);\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Special_Weapon_Targetting -- Called when the server initiates targetting\n*\n*\n* History: 11/19/2019 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::On_Special_Weapon_Targetting(const HouseClass* player_ptr, SpecialWeaponType weapon_type)\n{\n\tif (EventCallback == NULL)\n\t{\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_SPECIAL_WEAPON_TARGETTING;\n\tnew_event.SpecialWeaponTargetting.Type = RTTI_SPECIAL;\n\tnew_event.SpecialWeaponTargetting.ID = weapon_type;\n\tConvert_Special_Weapon_Type(weapon_type, new_event.SpecialWeaponTargetting.WeaponType, new_event.SpecialWeaponTargetting.Name);\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL)\n\t{\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tEventCallback(new_event);\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Ping -- Called when a radar ping is needed\n*\n*\n* History: 05/15/2019 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::On_Ping(const HouseClass* player_ptr, COORDINATE coord)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_PING;\n\tnew_event.Ping.CoordX = Coord_X(coord);\n\tnew_event.Ping.CoordY = Coord_Y(coord);\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL)\n\t{\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tEventCallback(new_event);\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Game_Over -- Called when the C&C campaign game finishes\n*\n*\n* History: 6/19/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::On_Game_Over(uint64 glyphx_Player_id, bool player_wins)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tGameOver = true;\n\n\tSaveTanya = IsTanyaDead;\n\tScen.CarryOverTimer = Scen.MissionTimer;\n\t//\tint timer = Scen.MissionTimer;\n\n\tScen.CarryOverMoney = PlayerPtr->Credits;\n\n\tDLLExportClass::Store_Carryover_Objects();\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_GAME_OVER;\n\tnew_event.GlyphXPlayerID = glyphx_Player_id;\n\tnew_event.GameOver.PlayerWins = player_wins;\n\tnew_event.GameOver.AfterScoreMovieName = \"\";\n\tnew_event.GameOver.Multiplayer = false;\n\tnew_event.GameOver.MultiPlayerTotalPlayers = 0;\n\n\tCalculate_Single_Player_Score(new_event);\n\n\tVQType movie = player_wins ? Scen.WinMovie : Scen.LoseMovie;\n\tif (movie > VQ_NONE && movie < VQ_COUNT) {\n\t\tnew_event.GameOver.MovieName = VQName[movie];\n\t} else {\n\t\tnew_event.GameOver.MovieName = \"\";\n\t}\n\n\tmovie = player_wins ? Scen.WinMovie2 : VQ_NONE;\n\tif (movie > VQ_NONE && movie < VQ_COUNT) {\n\t\tnew_event.GameOver.MovieName2 = VQName[movie];\n\t}\n\telse {\n\t\tnew_event.GameOver.MovieName2 = \"\";\n\t}\n\n\tmovie = player_wins ? Scen.WinMovie3 : VQ_NONE;\n\tif (movie > VQ_NONE && movie < VQ_COUNT) {\n\t\tnew_event.GameOver.MovieName3 = VQName[movie];\n\t}\n\telse {\n\t\tnew_event.GameOver.MovieName3 = \"\";\n\t}\n\n\tmovie = player_wins ? Scen.WinMovie4 : VQ_NONE;\n\tif (movie > VQ_NONE && movie < VQ_COUNT) {\n\t\tnew_event.GameOver.MovieName4 = VQName[movie];\n\t}\n\telse {\n\t\tnew_event.GameOver.MovieName4 = \"\";\n\t}\n\n\t//Campaign win & credits\n\tif (Scen.IsEndOfGame) {\n\t\tif (PlayerPtr->ActLike == HOUSE_USSR) {\n\t\t\tnew_event.GameOver.AfterScoreMovieName = VQName[VQ_SOVFINAL];\n\t\t}\n\t\telse {\n\t\t\tnew_event.GameOver.AfterScoreMovieName = VQName[VQ_ALLYEND];\n\t\t}\n\t}\n\n\tnew_event.GameOver.SabotagedStructureType = -1;\n\tnew_event.GameOver.TimerRemaining = Scen.MissionTimer.Was_Started() ? Scen.MissionTimer.Value() : -1;\n\n\tEventCallback(new_event);\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Multiplayer_Game_Over -- Called when the C&C multiplayer game finishes\n*\n*\n* History: 6/19/2019 - LLL\n* History: 10/31/2019 - MBL - Adding the multi-player score stats support for debrief\n**************************************************************************************************/\nvoid DLLExportClass::On_Multiplayer_Game_Over(void)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tGameOver = true;\n\n\tEventCallbackStruct event;\n\n\tevent.EventType = CALLBACK_EVENT_GAME_OVER;\n\n\t// Includes AI's for skirmish\n\tint player_count = Session.Players.Count(); \n\n\t// Multiplayer players data for debrief stats\n\n\tevent.GameOver.Multiplayer = true;\n\tevent.GameOver.MultiPlayerTotalPlayers = player_count;\n\n\tfor ( int player_index = 0; player_index < player_count; player_index ++ ) \n\t{\n\t\tHouseClass* player_ptr = HouseClass::As_Pointer(Session.Players[ player_index ]->Player.ID);\n\t\tif ( player_ptr != NULL )\n\t\t{\n\t\t\tHousesType player_house = PlayerPtr->Class->House;\n\n\t\t\tint uspoints = 0;\n\t\t\tfor (HousesType hous = HOUSE_SPAIN; hous <= HOUSE_BAD; hous++) {\n\t\t\t\tHouseClass* hows = HouseClass::As_Pointer(hous);\n\t\t\t\tif (player_ptr->Is_Ally(hous)) {\n\t\t\t\t\tuspoints += hows->PointTotal;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//\tif(uspoints < 0) uspoints = 0;\n\t\t\t//\tuspoints += 1000; //BG 1000 bonus points for winning mission\n\n\t\t\t// N/A for multi-player\n\t\t\t#if 0\n\t\t\t\t// Bias the base score upward according to the difficulty level.\n\t\t\t\tswitch (PlayerPtr->Difficulty) {\n\t\t\t\t\tcase DIFF_EASY:\n\t\t\t\t\tuspoints += 500;\n\t\t\t\t\tbreak;\n\t\t\t\n\t\t\t\t\tcase DIFF_NORMAL:\n\t\t\t\t\tuspoints += 1500;\n\t\t\t\t\tbreak;\n\t\t\t\n\t\t\t\t\tcase DIFF_HARD:\n\t\t\t\t\tuspoints += 3500;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\tint leadership = RA_Calculate_Leadership( player_ptr->Class->House, player_ptr->UnitsLost, player_ptr->BuildingsLost );\n\t\t\tint economy = RA_Calculate_Economy( player_ptr->Available_Money(), player_ptr->StolenBuildingsCredits, player_ptr->HarvestedCredits, player_ptr->Control.InitialCredits );\n\t\t  \tint total_score = RA_Calculate_Score( uspoints, leadership, economy );\n\n\t\t\tint units_killed = 0;\n\t\t\tint structures_killed = 0;\n\t\t\tfor ( unsigned int house_index = 0; house_index < HOUSE_COUNT; house_index ++ ) \n\t\t\t{\n\t\t\t\tunits_killed += player_ptr->UnitsKilled[ house_index ];\n\t\t\t\tstructures_killed += player_ptr->BuildingsKilled[ house_index ];\n\t\t\t}\n\n\t\t\t// Populate and copy the multiplayer player data structure \n\n\t\t\tGameOverMultiPlayerStatsStruct multi_player_data;\n\n\t\t\tmulti_player_data.GlyphXPlayerID = Get_GlyphX_Player_ID( player_ptr );\n\t\t\tmulti_player_data.IsHuman = (player_ptr->IsHuman || player_ptr->WasHuman);\n\t\t\tmulti_player_data.WasHuman = player_ptr->WasHuman;\n\t\t\tmulti_player_data.IsWinner = !player_ptr->IsDefeated;\n\t\t\tmulti_player_data.Efficiency = economy;\n\t\t\tmulti_player_data.Score = total_score;\n\t\t\tmulti_player_data.ResourcesGathered = player_ptr->HarvestedCredits;\n\t\t\tmulti_player_data.TotalUnitsKilled = units_killed;\n\t\t\tmulti_player_data.TotalStructuresKilled = structures_killed;\n\n\t\t\tif ( player_index < GAME_OVER_MULTIPLAYER_MAX_PLAYERS_TRACKED ) \n\t\t\t{\n\t\t\t\tevent.GameOver.MultiPlayerPlayersData[ player_index ] = multi_player_data;\n\t\t\t}\n\t\t}\n\t}\n\tfor ( int player_index = player_count; player_index < GAME_OVER_MULTIPLAYER_MAX_PLAYERS_TRACKED; player_index ++ ) \n\t{\n\t\tmemset( &event.GameOver.MultiPlayerPlayersData[ player_index ], 0, sizeof( GameOverMultiPlayerStatsStruct ) );\n\t}\n\n\t// Single-player N/A stuff\n\n\tevent.GameOver.MovieName = \"\";\n\tevent.GameOver.MovieName2 = \"\";\n\tevent.GameOver.MovieName3 = \"\";\n\tevent.GameOver.MovieName4 = \"\";\n\tevent.GameOver.AfterScoreMovieName = \"\";\n\tevent.GameOver.Leadership = 0;\n\tevent.GameOver.Efficiency = 0;\n\tevent.GameOver.Score = 0;\n\tevent.GameOver.NODKilled = 0;\n\tevent.GameOver.GDIKilled = 0;\n\tevent.GameOver.CiviliansKilled = 0;\n\tevent.GameOver.NODBuildingsDestroyed = 0;\n\tevent.GameOver.GDIBuildingsDestroyed = 0;\n\tevent.GameOver.CiviliansBuildingsDestroyed = 0;\n\tevent.GameOver.RemainingCredits = 0;\n\tevent.GameOver.SabotagedStructureType = 0;\n\tevent.GameOver.TimerRemaining = -1;\n\n\t// Trigger an event for each human player, winner first (even if it's an AI)\n\tfor (int i = 0; i < player_count; i++) {\n\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tif (!player_ptr->IsDefeated) {\n\t\t\tevent.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t\t\tevent.GameOver.IsHuman = player_ptr->IsHuman;\n\t\t\tevent.GameOver.PlayerWins = true;\n\t\t\tevent.GameOver.RemainingCredits = player_ptr->Available_Money();\n\t\t\tEventCallback(event);\n\t\t}\n\t}\n\n\tfor (int i = 0; i < player_count; i++) {\n\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tif (player_ptr->IsHuman && player_ptr->IsDefeated) {\n\t\t\tevent.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t\t\tevent.GameOver.IsHuman = true;\n\t\t\tevent.GameOver.PlayerWins = false;\n\t\t\tevent.GameOver.RemainingCredits = player_ptr->Available_Money();\n\t\t\tEventCallback(event);\n\t\t}\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Achievement -- Called when something achievement-related happens\n*\n* In:   Type of achievement, reason this happened\n*\n* Out:\n*\n*\n*\n* History: 11/11/2019 11:37AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::On_Achievement(const HouseClass* player_ptr, const char *achievement_type, const char *achievement_reason)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_ACHIEVEMENT;\n\tnew_event.Achievement.AchievementType = achievement_type;\n\tnew_event.Achievement.AchievementReason = achievement_reason;\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL) {\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tEventCallback(new_event);\n}\t\t\t  \n\n\nvoid DLLExportClass::On_Center_Camera(const HouseClass* player_ptr, int coord_x, int coord_y)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_CENTER_CAMERA;\n\tnew_event.CenterCamera.CoordX = coord_x;\n\tnew_event.CenterCamera.CoordY = coord_y;\n\n\tnew_event.GlyphXPlayerID = 0;\n\tif (player_ptr != NULL) {\n\t\tnew_event.GlyphXPlayerID = Get_GlyphX_Player_ID(player_ptr);\n\t}\n\n\tEventCallback(new_event);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::On_Debug_Output -- Called when C&C wants to print debug output\n*\n* In:   String to print to GlyphX log system\n*\n* Out:\n*\n*\n*\n* History: 2/20/2019 2:39PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::On_Debug_Output(const char *debug_text)\n{\n\tif (EventCallback == NULL) {\n\t\treturn;\n\t}\n\n\tEventCallbackStruct new_event;\n\tnew_event.EventType = CALLBACK_EVENT_DEBUG_PRINT;\n\tnew_event.DebugPrint.PrintString = debug_text;\n\tEventCallback(new_event);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Force_Human_Team_Wins\n*\n* History: 3/10/2020 - LL\n**************************************************************************************************/\nvoid DLLExportClass::Force_Human_Team_Wins(uint64 quitting_player_id)\n{\n\tint winning_team = -1;\n\n\t//Find the first human's multiplayer team.\n\tfor (int i = 0; i < Session.Players.Count(); i++)\n\t{\n\t\tif (GlyphxPlayerIDs[i] != quitting_player_id) {\n\t\t\tHousesType house_type = Session.Players[i]->Player.ID;\n\t\t\tHouseClass* house_class = HouseClass::As_Pointer(house_type);\n\t\t\tif (house_class && house_class->IsHuman && !house_class->IsDefeated) {\n\t\t\t\twinning_team = MPlayerTeamIDs[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t//Mark all players not on that team as defeated.\n\tfor (int i = 0; i < Session.Players.Count(); i++)\n\t{\n\t\tHousesType house_type = Session.Players[i]->Player.ID;\n\t\tHouseClass* house_class = HouseClass::As_Pointer(house_type);\n\t\tif (house_class) {\n\t\t\thouse_class->IsDefeated = MPlayerTeamIDs[i] != winning_team;\n\t\t}\n\t}\n\n\tPlayerWins = true;\n}\n\n\n/**************************************************************************************************\n* CNC_Get_Game_State -- Get game state\n*\n* In:   Type of state requested\n*       Player perspective\n*       Buffer to contain game state\n*       Size of buffer\n*\n* Out:  Game state returned in buffer\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) bool __cdecl CNC_Get_Game_State(GameStateRequestEnum state_type, uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\tbool got_state = false;\n\n\tswitch (state_type) {\n\t\t\n\t\tcase GAME_STATE_LAYERS:\n\t\t{\n\t\t\tgot_state = DLLExportClass::Get_Layer_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\t\t}\t\t \n\n\t\tcase GAME_STATE_SIDEBAR:\n\t\t{\t\n\t\t\tgot_state = DLLExportClass::Get_Sidebar_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase GAME_STATE_PLACEMENT:\n\t\t{\n\t\t\tgot_state = DLLExportClass::Get_Placement_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\t\t}\t\t\t\n\t\t\n\t\tcase GAME_STATE_DYNAMIC_MAP:\n\t\t\tgot_state = DLLExportClass::Get_Dynamic_Map_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\n\t\tcase GAME_STATE_SHROUD:\n\t\t\tgot_state = DLLExportClass::Get_Shroud_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\n\t\tcase GAME_STATE_OCCUPIER:\n\t\t\tgot_state = DLLExportClass::Get_Occupier_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\n\t\tcase GAME_STATE_PLAYER_INFO:\n\t\t\tgot_state = DLLExportClass::Get_Player_Info_State(player_id, buffer_in, buffer_size);\n\t\t\tbreak;\n\n\t\tcase GAME_STATE_STATIC_MAP:\n\t\t{\t\n\t\t\tif (buffer_size < sizeof(CNCMapDataStruct)) {\n\t\t\t\tgot_state = false;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tint map_cell_x = Map.MapCellX;\n\t\t\tint map_cell_y = Map.MapCellY;\n\t\t\tint map_cell_width = Map.MapCellWidth;\n\t\t\tint map_cell_height = Map.MapCellHeight;\n\n\t\t\tCNCMapDataStruct *map_data = (CNCMapDataStruct *)buffer_in;\n\t\t\t\n\t\t\tmap_data->OriginalMapCellX = map_cell_x;\n\t\t\tmap_data->OriginalMapCellY = map_cell_y;\n\t\t\tmap_data->OriginalMapCellWidth = map_cell_width;\n\t\t\tmap_data->OriginalMapCellHeight = map_cell_height;\n\n\t\t\tif (map_cell_x > 0) {\n\t\t\t\tmap_cell_x--;\n\t\t\t\tmap_cell_width++;\n\t\t\t}\n\n\t\t\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\t\t\tmap_cell_width++;\n\t\t\t}\n\n\t\t\tif (map_cell_y > 0) {\n\t\t\t\tmap_cell_y--;\n\t\t\t\tmap_cell_height++;\n\t\t\t}\n\n\t\t\tif (map_cell_height < MAP_MAX_CELL_HEIGHT) {\n\t\t\t\tmap_cell_height++;\n\t\t\t}\n\n\t\t\tmap_data->MapCellX = map_cell_x;\n\t\t\tmap_data->MapCellY = map_cell_y;\n\t\t\tmap_data->MapCellWidth = map_cell_width;\n\t\t\tmap_data->MapCellHeight = map_cell_height;\n\n\t\t\tmap_data->Theater = (CnCTheaterType) Scen.Theater;\n\n\t\t\tchar* dot_ptr = strchr(Scen.ScenarioName, '.');\n\t\t\tconst int count = (dot_ptr != nullptr) ? (dot_ptr - Scen.ScenarioName) : sizeof(Scen.ScenarioName);\n\t\t\tmemset(map_data->ScenarioName, 0, sizeof(map_data->ScenarioName));\n\t\t\tstrncpy(map_data->ScenarioName, Scen.ScenarioName, min(sizeof(map_data->ScenarioName) - 1, count));\n\n\t\t\tint cell_index = 0;\n\t\t\tchar cell_name[_MAX_PATH];\n\t\t\tchar icon_number[32];\n\t\t\t\t\n\t\t\tfor (int y = 0 ; y < map_cell_height ; y++) {\n\t\t\t\tfor (int x = 0 ; x < map_cell_width ; x++) {\n\t\t\t\t\tCELL cell = XY_Cell(map_cell_x+x, map_cell_y+y);\n\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\n\t\t\t\t\tcell_name[0] = 0;\n\t\t\t\t\tint icon = 0;\n\t\t\t\t\tvoid *image_data = 0;\n\t\t\t\t\tif (cellptr->Get_Template_Info(cell_name, icon, image_data)) {\n\t\t\t\t\t\titoa(icon, icon_number, 10);\n\t\t\t\t\t\tstrncat(cell_name, \"_i\", 32);\n\t\t\t\t\t\tstrncat(cell_name, icon_number, 32);\n\t\t\t\t\t\tstrncat(cell_name, \".tga\", 32);\n\n\t\t\t\t\t\tCNCStaticCellStruct &cell_info = map_data->StaticCells[cell_index++];\n\t\t\t\t\t\tstrncpy(cell_info.TemplateTypeName, cell_name, 32);\n\t\t\t\t\t\tcell_info.IconNumber = icon;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\t\n\t\t\tgot_state = true;\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t\t{\n\t\t\t\tgot_state = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\n\treturn got_state;\n}\n\n\n/**************************************************************************************************\n* CNC_Handle_Game_Request\n*\n* Callback for when the requested movie is done playing.\n*\n* 7/23/2019 - LLL\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Game_Request(GameRequestEnum request_type)\n{\n\tswitch (request_type)\n\t{\n\t\tcase INPUT_GAME_MOVIE_DONE:\n\t\tbreak;\n\t}\n}\n\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Game_Settings_Request(int health_bar_display_mode, int resource_bar_display_mode)\n{\n\tif (!DLLExportClass::Legacy_Render_Enabled()) {\n\t\treturn;\n\t}\n\n\tRulesClass::eHealthBarDisplayMode new_hb_mode = (RulesClass::eHealthBarDisplayMode)health_bar_display_mode;\n\tif (new_hb_mode != Rule.HealthBarDisplayMode) {\n\t\tRule.HealthBarDisplayMode = new_hb_mode;\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\tRulesClass::eResourceBarDisplayMode new_rb_mode = (RulesClass::eResourceBarDisplayMode)resource_bar_display_mode;\n\tif (new_rb_mode != Rule.ResourceBarDisplayMode) {\n\t\tRule.ResourceBarDisplayMode = new_rb_mode;\n\t\tMap.Flag_To_Redraw(true);\n\t}\n}\n\n\n\t\n\n\t\n\nvoid DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name, char override_owner)\n{\n\tDLLExportClass::DLL_Draw_Intercept(shape_number, x, y, width, height, flags, object, rotation, scale, shape_file_name, override_owner);\n}\t\t\t  \n\n\nvoid DLL_Draw_Pip_Intercept(const ObjectClass* object, int pip)\n{\n\tDLLExportClass::DLL_Draw_Pip_Intercept(object, pip);\n}\n\n\nvoid DLLExportClass::DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name, char override_owner)\n{\n\tCNCObjectStruct& new_object = ObjectList->Objects[TotalObjectCount + CurrentDrawCount];\n\tmemset(&new_object, 0, sizeof(new_object));\n\tConvert_Type(object, new_object);\n\tif (new_object.Type == UNKNOWN) {\n\t\treturn;\n\t}\n\n\tCNCObjectStruct* base_object = NULL;\n\tchar sub_object = 0;\n\tfor (int i = 0; i < CurrentDrawCount; ++i) {\n\t\tCNCObjectStruct& draw_object = ObjectList->Objects[TotalObjectCount + i];\n\t\tif (draw_object.CNCInternalObjectPointer == object) {\n\t\t\tif (base_object == NULL) {\n\t\t\t\tbase_object = &draw_object;\n\t\t\t}\n\t\t\tsub_object++;\n\t\t}\n\t}\n\n\tnew_object.CNCInternalObjectPointer = (void*)object;\n\tnew_object.OccupyListLength = 0;\n\tif (CurrentDrawCount == 0) {\n\t\tnew_object.SortOrder = (ExportLayer << 29) + (object->Sort_Y() >> 3);\n\t} else {\n\t\tnew_object.SortOrder = ObjectList->Objects[TotalObjectCount].SortOrder + CurrentDrawCount;\n\t}\t\n\n\tstrncpy(new_object.TypeName, object->Class_Of().IniName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\n\tif (shape_file_name != NULL) {\n\t\tstrncpy(new_object.AssetName, shape_file_name, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t}\n\telse {\n\t\tstrncpy(new_object.AssetName, object->Class_Of().Graphic_Name(), CNC_OBJECT_ASSET_NAME_LENGTH);\n\t}\n\n\tnew_object.Owner = (base_object != NULL) ? ((override_owner != HOUSE_NONE) ? override_owner : base_object->Owner) : (char)object->Owner();\n\n\tHouseClass* owner_house = nullptr;\n\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\tHouseClass* hptr = Houses.Ptr(i);\n\t\tif ((hptr != nullptr) && (hptr->Class->House == new_object.Owner)) {\n\t\t\towner_house = hptr;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tnew_object.RemapColor = (owner_house != nullptr) ? owner_house->RemapColor : -1;\n\n\tif (base_object == NULL) {\n\t\tCNCObjectStruct& root_object = ObjectList->Objects[TotalObjectCount];\n\n\t\tif (new_object.Type == BUILDING) {\n\t\t\tBuildingClass *building = (BuildingClass*)object;\n\t\t\tif (building->BState == BSTATE_CONSTRUCTION) {\n\t\t\t\tstrncat(new_object.AssetName, \"MAKE\", CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t}\n\t\t\tconst BuildingTypeClass *building_type = building->Class;\n\t\t\tshort const *occupy_list = building_type->Occupy_List();\n\t\t\tif (occupy_list) {\n\t\t\t\twhile (*occupy_list != REFRESH_EOL && new_object.OccupyListLength < MAX_OCCUPY_CELLS) {\n\t\t\t\t\tnew_object.OccupyList[new_object.OccupyListLength] = *occupy_list;\n\t\t\t\t\tnew_object.OccupyListLength++;\n\t\t\t\t\toccupy_list++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCOORDINATE coord = object->Render_Coord();\n\t\tCELL cell = Coord_Cell(coord);\n\t\tint dimx, dimy;\n\t\tobject->Class_Of().Dimensions(dimx, dimy);\n\n\t\tnew_object.PositionX = x;\n\t\tnew_object.PositionY = y;\n\t\tnew_object.Width = width;\n\t\tnew_object.Height = height;\n\t\tnew_object.Altitude = object->Height;\n\t\tnew_object.DrawFlags = flags;\n\t\tnew_object.SubObject = 0;\n\t\tnew_object.ShapeIndex = (unsigned short)shape_number;\n\t\tnew_object.IsTheaterSpecific = IsTheaterShape;\n\t\tnew_object.Rotation = (unsigned char)rotation;\n\t\tnew_object.Scale = scale;\n\t\tnew_object.FlashingFlags = 0;\n\t\tnew_object.Cloak = (CurrentDrawCount > 0) ? root_object.Cloak : UNCLOAKED;\n\t\tnew_object.VisibleFlags = CNCObjectStruct::VISIBLE_FLAGS_ALL;\n\t\tnew_object.SpiedByFlags = 0U;\n\n\t\tnew_object.IsSelectable = object->Class_Of().IsSelectable;\n\t\tnew_object.IsSelectedMask = object->IsSelectedMask;\n\t\tnew_object.MaxStrength = object->Class_Of().MaxStrength;\n\t\tnew_object.Strength = object->Strength;\n\t\tnew_object.CellX = (CurrentDrawCount > 0) ? root_object.CellX : Cell_X(cell);\n\t\tnew_object.CellY = (CurrentDrawCount > 0) ? root_object.CellY : Cell_Y(cell);\n\t\tnew_object.CenterCoordX = Coord_X(object->Center_Coord());\n\t\tnew_object.CenterCoordY = Coord_Y(object->Center_Coord());\n\t\tnew_object.DimensionX = dimx;\n\t\tnew_object.DimensionY = dimy;\n\t\tnew_object.SimLeptonX = (CurrentDrawCount > 0) ? root_object.SimLeptonX : 0;\n\t\tnew_object.SimLeptonY = (CurrentDrawCount > 0) ? root_object.SimLeptonY : 0;\n\t\tnew_object.BaseObjectID = ((CurrentDrawCount > 0) && (root_object.Type != BUILDING) && (root_object.Type != VESSEL)) ? root_object.ID : 0;\n\t\tnew_object.BaseObjectType = ((CurrentDrawCount > 0) && (root_object.Type != BUILDING) && (root_object.Type != VESSEL)) ? root_object.Type : UNKNOWN;\n\t\tnew_object.NumLines = 0;\n\t\tnew_object.RecentlyCreated = object->IsRecentlyCreated;\n\t\tnew_object.NumPips = 0;\n\t\tnew_object.MaxPips = 0;\n\t\tnew_object.CanDemolish = object->Can_Demolish();\n\t\tnew_object.CanDemolishUnit = object->Can_Demolish_Unit();\n\t\tnew_object.CanRepair = object->Can_Repair();\n\t\tmemset(new_object.CanMove, false, sizeof(new_object.CanMove));\n\t\tmemset(new_object.CanFire, false, sizeof(new_object.CanFire));\n\t\tmemset(new_object.ActionWithSelected, DAT_NONE, sizeof(new_object.ActionWithSelected));\n\n\t\tHouseClass* old_player_ptr = PlayerPtr;\n\t\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\t\tHouseClass* hptr = Houses.Ptr(i);\n\t\t\tif ((hptr != nullptr) && hptr->IsActive && hptr->IsHuman) {\n\t\t\t\tHousesType house = hptr->Class->House;\n\t\t\t\tDynamicVectorClass<ObjectClass*>& selected_objects = CurrentObject.Raw(house);\n\t\t\t\tif (selected_objects.Count() > 0) {\n\t\t\t\t\tLogic_Switch_Player_Context(hptr);\n\t\t\t\t\tConvert_Action_Type(Best_Object_Action(selected_objects, object), (selected_objects.Count() == 1) ? selected_objects[0] : NULL, object->As_Target(), new_object.ActionWithSelected[house]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tLogic_Switch_Player_Context(old_player_ptr);\n\n\t\tRTTIType what_is_object = object->What_Am_I();\n\n\t\tnew_object.IsRepairing = false;\n\t\tnew_object.IsDumping = false;\n\t\tnew_object.IsALoaner = false;\n\t\tnew_object.IsFactory = false;\n\t\tnew_object.IsPrimaryFactory = false;\n\t\tnew_object.IsNominal = false;\n\t\tnew_object.IsDog = false;\n\t\tnew_object.IsIronCurtain = false;\n\t\tnew_object.IsAntiGround = false;\n\t\tnew_object.IsAntiAircraft = false;\n\t\tnew_object.IsSubSurface = false;\n\t\tnew_object.IsFake = false;\n\t\tnew_object.ProductionAssetName[0] = '\\0';\n\t\tnew_object.OverrideDisplayName = \"\\0\";\n\n\t\tbool is_building = what_is_object == RTTI_BUILDING;\n\t\tif (is_building) {\n\t\t\tconst BuildingClass* building = static_cast<const BuildingClass*>(object);\n\t\t\tnew_object.IsRepairing = building->IsRepairing;\n\t\t\tnew_object.IsFactory = building->Class->Is_Factory();\n\t\t\tnew_object.IsPrimaryFactory = building->IsLeader;\n\t\t\tnew_object.IsFake = building->Class->IsFake;\n\t\t}\n\n\t\tif (object->Is_Techno()) {\n\t\t\tconst TechnoClass* techno_object = static_cast<const TechnoClass*>(object);\n\t\t\tconst TechnoTypeClass *ttype = techno_object->Techno_Type_Class();\n\n\t\t\tnew_object.MaxSpeed = (unsigned char)ttype->MaxSpeed;\n\t\t\tnew_object.IsALoaner = techno_object->IsALoaner;\n\t\t\tnew_object.IsNominal = ttype->IsNominal;\n\t\t\tnew_object.MaxPips = ttype->Max_Pips();\n\t\t\tnew_object.IsAntiGround = (ttype->PrimaryWeapon != NULL) && (ttype->PrimaryWeapon->Bullet != NULL) && ttype->PrimaryWeapon->Bullet->IsAntiGround;\n\t\t\tnew_object.IsAntiAircraft = (ttype->PrimaryWeapon != NULL) && (ttype->PrimaryWeapon->Bullet != NULL) && ttype->PrimaryWeapon->Bullet->IsAntiAircraft;\n\t\t\tnew_object.IsSubSurface = (ttype->PrimaryWeapon != NULL) && (ttype->PrimaryWeapon->Bullet != NULL) && ttype->PrimaryWeapon->Bullet->IsSubSurface;\n\t\t\tnew_object.IsIronCurtain = techno_object->IronCurtainCountDown > 0;\n\n\t\t\tint full_name = techno_object->Full_Name();\n\t\t\tif (full_name < 0)\n\t\t\t{\n\t\t\t\tnew_object.OverrideDisplayName = Text_String(full_name);\n\t\t\t}\n\n\t\t\tHouseClass* old_player_ptr = PlayerPtr;\n\t\t\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\t\t\tHouseClass* hptr = Houses.Ptr(i);\n\t\t\t\tif ((hptr != nullptr) && hptr->IsActive && hptr->IsHuman) {\n\t\t\t\t\tLogic_Switch_Player_Context(hptr);\n\t\t\t\t\tHousesType house = hptr->Class->House;\n\t\t\t\t\tnew_object.CanMove[house] = techno_object->Can_Player_Move();\n\t\t\t\t\tnew_object.CanFire[house] = techno_object->Can_Player_Fire();\n\t\t\t\t}\n\t\t\t}\n\t\t\tLogic_Switch_Player_Context(old_player_ptr);\n\t\t}\n\n\t\tnew_object.ControlGroup = (unsigned char)(-1);\n\t\tnew_object.IsInFormation = false;\n\t\tnew_object.CanPlaceBombs = false;\n\n\t\tif (object->Is_Foot()) {\n\t\t\tconst FootClass* foot = static_cast<const FootClass*>(object);\n\t\t\tnew_object.ControlGroup = foot->Group;\n\t\t\tnew_object.IsInFormation = foot->XFormOffset != 0x80000000UL;\n\t\t}\n\n\t\tbool is_infantry = what_is_object == RTTI_INFANTRY;\n\t\tif (is_infantry) {\n\t\t\tconst InfantryClass* infantry = static_cast<const InfantryClass*>(object);\n\t\t\tnew_object.IsDog = infantry->Class->IsDog;\n\t\t\tnew_object.CanPlaceBombs = infantry->Class->IsBomber;\n\t\t}\n\n\t\tnew_object.CanHarvest = false;\n\t\tbool is_unit = what_is_object == RTTI_UNIT;\n\t\tif (is_unit) {\n\t\t\tconst UnitClass* unit = static_cast<const UnitClass*>(object);\n\t\t\tif (unit->Class->Type == UNIT_HARVESTER)\n\t\t\t{\n\t\t\t\tnew_object.CanHarvest = true;\n\t\t\t}\n\n\t\t\tnew_object.IsDumping = unit->IsDumping;\n\t\t}\n\n\t\tnew_object.IsFixedWingedAircraft = false;\n\t\tbool is_aircraft = what_is_object == RTTI_AIRCRAFT;\n\t\tif (is_aircraft) {\n\t\t\tconst AircraftClass* aircraft = static_cast<const AircraftClass*>(object);;\n\t\t\tnew_object.IsFixedWingedAircraft = aircraft->Class->IsFixedWing;\n\t\t}\n\n\t\tswitch (what_is_object)\n\t\t{\n\t\t\tcase RTTI_INFANTRY:\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tcase RTTI_UNIT:\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tcase RTTI_BUILDING:\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tcase RTTI_VESSEL:\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t{\n\t\t\t\tconst TechnoClass* techno_object = static_cast<const TechnoClass*>(object);\n\t\t\t\tnew_object.FlashingFlags = techno_object->Get_Flashing_Flags();\n\t\t\t\tnew_object.Cloak = techno_object->Cloak;\n\t\t\t\tnew_object.SpiedByFlags = techno_object->Spied_By();\n\n\t\t\t\tif (techno_object->Techno_Type_Class()->IsInvisible) {\n\t\t\t\t\t// Hide for enemy players\n\t\t\t\t\tHouseClass* owner = HouseClass::As_Pointer(object->Owner());\n\t\t\t\t\tif (owner != nullptr) {\n\t\t\t\t\t\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\t\t\t\t\t\tHouseClass* hptr = Houses.Ptr(i);\n\t\t\t\t\t\t\tif ((hptr != nullptr) && hptr->IsActive && !owner->Is_Ally(hptr)) {\n\t\t\t\t\t\t\t\tnew_object.VisibleFlags &= ~(1 << hptr->Class->House);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t\tcase RTTI_ANIM:\n\t\t\tcase RTTI_ANIMTYPE:\n\t\t\t{\n\t\t\t\tconst AnimClass* anim_object = static_cast<const AnimClass*>(object);\n\t\t\t\tnew_object.Owner = anim_object->OwnerHouse;\n\t\t\t\tnew_object.RemapColor = -1;\n\t\t\t\tnew_object.VisibleFlags = anim_object->Get_Visible_Flags();\n\n\t\t\t\tconst AnimTypeClass& anim_type = static_cast<const AnimTypeClass&>(anim_object->Class_Of());\n\t\t\t\tif (anim_type.VirtualName != NULL) {\n\t\t\t\t\tstrncpy(new_object.AssetName, anim_type.VirtualName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t\tcase RTTI_TERRAIN:\n\t\t\tcase RTTI_TERRAINTYPE:\n\t\t\t{\n\t\t\t\tif (strncmp(new_object.AssetName, \"MINE\", CNC_OBJECT_ASSET_NAME_LENGTH) == 0) {\n\t\t\t\t\tstrncpy(new_object.AssetName, \"OREMINE\", CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t}\n\telse {\n\t\tnew_object.MaxStrength = 0;\n\t\tnew_object.MaxSpeed = 0;\n\t\tnew_object.Strength = 0;\n\t\tnew_object.CellX = base_object->CellX;\n\t\tnew_object.CellY = base_object->CellY;\n\t\tnew_object.CenterCoordX = base_object->CenterCoordX;\n\t\tnew_object.CenterCoordY = base_object->CenterCoordY;\n\t\tnew_object.DimensionX = base_object->DimensionX;\n\t\tnew_object.DimensionY = base_object->DimensionY;\n\t\tnew_object.IsSelectable = false;\n\t\tnew_object.IsSelectedMask = 0U;\n\t\tnew_object.SimLeptonX = base_object->SimLeptonX;\n\t\tnew_object.SimLeptonY = base_object->SimLeptonY;\n\n\t\tnew_object.PositionX = x;\n\t\tnew_object.PositionY = y;\n\t\tnew_object.Width = width;\n\t\tnew_object.Height = height;\n\t\tnew_object.Altitude = base_object->Altitude;\n\t\tnew_object.DrawFlags = flags;\n\t\tnew_object.ShapeIndex = (unsigned short)shape_number;\n\t\tnew_object.IsTheaterSpecific = IsTheaterShape;\n\t\tnew_object.Rotation = (unsigned char)rotation;\n\t\tnew_object.Scale = scale;\n\t\tnew_object.SubObject = sub_object;\n\t\tnew_object.BaseObjectID = base_object->ID;\n\t\tnew_object.BaseObjectType = base_object->Type;\n\n\t\tnew_object.FlashingFlags = base_object->FlashingFlags;\n\t\tnew_object.Cloak = base_object->Cloak;\n\t\tnew_object.OccupyListLength = 0;\n\t\tnew_object.NumPips = 0;\n\t\tnew_object.MaxPips = 0;\n\t\tnew_object.NumLines = 0;\n\t\tnew_object.IsRepairing = false;\n\t\tnew_object.IsDumping = false;\n\t\tnew_object.IsALoaner = base_object->IsALoaner;\n\t\tnew_object.CanDemolish = base_object->CanDemolish;\n\t\tnew_object.CanDemolishUnit = base_object->CanDemolishUnit;\n\t\tnew_object.CanRepair = base_object->CanRepair;\n\t\tnew_object.RecentlyCreated = base_object->RecentlyCreated;\n\t\tnew_object.IsFactory = base_object->IsFactory;\n\t\tnew_object.IsPrimaryFactory = base_object->IsPrimaryFactory;\n\t\tnew_object.IsAntiGround = base_object->IsAntiGround;\n\t\tnew_object.IsAntiAircraft = base_object->IsAntiAircraft;\n\t\tnew_object.IsSubSurface = base_object->IsSubSurface;\n\t\tnew_object.IsNominal = base_object->IsNominal;\n\t\tnew_object.IsDog = base_object->IsDog;\n\t\tnew_object.IsIronCurtain = base_object->IsIronCurtain;\n\t\tnew_object.IsInFormation = false;\n\t\tnew_object.CanHarvest = base_object->CanHarvest;\n\t\tnew_object.CanPlaceBombs = base_object->CanPlaceBombs;\n\t\tnew_object.ControlGroup = base_object->ControlGroup;\n\t\tnew_object.VisibleFlags = base_object->VisibleFlags;\n\t\tnew_object.SpiedByFlags = base_object->SpiedByFlags;\n\t\tnew_object.IsFixedWingedAircraft = base_object->IsFixedWingedAircraft;\n\t\tnew_object.IsFake = base_object->IsFake;\n\t\tnew_object.ProductionAssetName[0] = '\\0';\n\t\tnew_object.OverrideDisplayName = \"\\0\";\n\t\tmemset(new_object.CanMove, false, sizeof(new_object.CanMove));\n\t\tmemset(new_object.CanFire, false, sizeof(new_object.CanFire));\n\t\tmemset(new_object.ActionWithSelected, DAT_NONE, sizeof(new_object.ActionWithSelected));\n\t}\n\n\tCurrentDrawCount++;\n}\n\n\n\nvoid DLLExportClass::DLL_Draw_Pip_Intercept(const ObjectClass* object, int pip)\n{\n\tCNCObjectStruct* base_object = NULL;\n\tfor (int i = 0; i < CurrentDrawCount; ++i) {\n\t\tCNCObjectStruct& draw_object = ObjectList->Objects[TotalObjectCount + i];\n\t\tif (draw_object.CNCInternalObjectPointer == object) {\n\t\t\tbase_object = &draw_object;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((base_object != NULL) && (base_object->NumPips < MAX_OBJECT_PIPS)) {\n\t\tbase_object->Pips[base_object->NumPips] = pip;\n\t\tbase_object->NumPips++;\n\t\tbase_object->MaxPips = max(base_object->MaxPips, base_object->NumPips);\n\t}\n}\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Layer_State -- Get game objects from the layers\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/29/2019 11:37AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Layer_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\tplayer_id;\n\n\tstatic int _export_count = 0;\n\n\tbool got_state = false;\n\n\tObjectList = (CNCObjectListStruct*) buffer_in;\n\n\tTotalObjectCount = 0;\n\n\t/*\n\t** Get a reference draw coordinate for cells\n\t*/\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t}\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t}\n\n\tSortOrder = 0;\n\n\t/*\n\t**\tGet the ground layer first and then followed by all the layers in increasing altitude.\n\t*/\n\tfor (int layer = 0; layer < DLL_LAYER_COUNT; layer++) {\n\t\t\n\t\tExportLayer = layer;\n\t\t\n\t\tfor (int index = 0; index < Map.Layer[layer].Count(); index++) {\n\t\t\t\n\t\t\tObjectClass *object = Map.Layer[layer][index];\n\t\t\tif (object->IsActive) {\n\t\t\t\t\n\t\t\t\tunsigned int memory_needed = sizeof(CNCObjectListStruct);\n\t\t\t\tmemory_needed += (TotalObjectCount + 10) * sizeof(CNCObjectStruct);\n\t\t\t\tif (memory_needed >= buffer_size) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (object->Is_Techno()) {\n\t\t\t\t\t/*\n\t\t\t\t\t**  Skip units tethered to buildings, since the building will draw them itself\n\t\t\t\t\t*/\n\t\t\t\t\tTechnoClass* techno_object = static_cast<TechnoClass*>(object);\n\t\t\t\t\tTechnoClass* contact_object = techno_object->In_Radio_Contact() ? techno_object->Contact_With_Whom() : nullptr;\n\t\t\t\t\tif ((object->What_Am_I() != RTTI_BUILDING) && (contact_object != nullptr) && (contact_object->What_Am_I() == RTTI_BUILDING) && contact_object->IsTethered && *((BuildingClass*)contact_object) == STRUCT_WEAP) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**  Skip units tethered to vessels, since the vessel will draw them itself\n\t\t\t\t\t*/\n\t\t\t\t\tif ((contact_object != nullptr) && (contact_object->What_Am_I() == RTTI_VESSEL) && !contact_object->Is_Door_Closed() && contact_object->IsTethered && !techno_object->IsInLimbo) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (Debug_Map || Debug_Unshroud || (object->IsDown && !object->IsInLimbo)) {\n\t\t\t\t\tint\tx, y;\n\t\t\t\t\tMap.Coord_To_Pixel(object->Render_Coord(), x, y);\n\t\t\t\t\t\n\t\t\t\t\t/*\n\t\t\t\t\t** Call to Draw_It can result in multiple callbacks to the draw intercept\n\t\t\t\t\t*/\n\t\t\t\t\tCurrentDrawCount = 0;\n\t\t\t\t\tobject->Draw_It(x, y, WINDOW_VIRTUAL);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the root object is a factory, then the last base object is the object in production (rendered after infiltrated buildings when selected).\n\t\t\t\t\t** The root object is updated with the production asset name, but otherwise a separate object isn't created.\n\t\t\t\t\t** This only occurs in skirmish and multiplayer.\n\t\t\t\t\t*/\n\t\t\t\t\tif ((GAME_TO_PLAY != GAME_NORMAL) && (CurrentDrawCount > 0)) {\n\t\t\t\t\t\tCNCObjectStruct& root_object = ObjectList->Objects[TotalObjectCount];\n\t\t\t\t\t\tif (root_object.IsFactory) {\n\t\t\t\t\t\t\tBuildingClass* building = (BuildingClass*)root_object.CNCInternalObjectPointer;\n\t\t\t\t\t\t\tFactoryClass* factory = building->House->IsHuman ? building->House->Fetch_Factory(building->Class->ToBuild) : building->Factory;\n\t\t\t\t\t\t\tif (factory != nullptr) {\n\t\t\t\t\t\t\t\tfor (int i = CurrentDrawCount - 1; i > 0; --i) {\n\t\t\t\t\t\t\t\t\tCNCObjectStruct& base_object = ObjectList->Objects[TotalObjectCount + i];\n\t\t\t\t\t\t\t\t\tif (base_object.SubObject) {\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tstrncpy(root_object.ProductionAssetName, base_object.TypeName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t\t\t\t\t\t\tvoid* production_object = base_object.CNCInternalObjectPointer;\n\t\t\t\t\t\t\t\t\tint new_draw_count = i;\n\t\t\t\t\t\t\t\t\tfor (int j = i + 1; j < CurrentDrawCount; ++j) {\n\t\t\t\t\t\t\t\t\t\tCNCObjectStruct& cnc_object = ObjectList->Objects[TotalObjectCount + j];\n\t\t\t\t\t\t\t\t\t\tif (cnc_object.CNCInternalObjectPointer != production_object) {\n\t\t\t\t\t\t\t\t\t\t\tmemcpy(ObjectList->Objects + TotalObjectCount + new_draw_count, &cnc_object, sizeof(CNCObjectStruct));\n\t\t\t\t\t\t\t\t\t\t\tnew_draw_count++;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tmemset(ObjectList->Objects + TotalObjectCount + new_draw_count, 0, (CurrentDrawCount - new_draw_count) * sizeof(CNCObjectStruct));\n\t\t\t\t\t\t\t\t\tCurrentDrawCount = new_draw_count;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Shadows need to be rendered before the base object so they appear underneath,\n\t\t\t\t\t** even though they get drawn as sub-objects (after the base object)\n\t\t\t\t\t*/\n\t\t\t\t\tfor (int i = 1; i < CurrentDrawCount; ++i) {\n\t\t\t\t\t\tCNCObjectStruct& sub_object = ObjectList->Objects[TotalObjectCount + i];\n\t\t\t\t\t\tif (!sub_object.SubObject) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstatic const int shadow_flags = SHAPE_PREDATOR | SHAPE_FADING;\n\t\t\t\t\t\tif (((sub_object.DrawFlags & shadow_flags) == shadow_flags) || (strncmp(sub_object.AssetName, \"WAKE\", CNC_OBJECT_ASSET_NAME_LENGTH) == 0)) {\n\t\t\t\t\t\t\tif ((strncmp(sub_object.AssetName, \"RROTOR\", CNC_OBJECT_ASSET_NAME_LENGTH) != 0) &&\n\t\t\t\t\t\t\t\t(strncmp(sub_object.AssetName, \"LROTOR\", CNC_OBJECT_ASSET_NAME_LENGTH) != 0)) {\n\t\t\t\t\t\t\t\tfor (int j = i - 1; j >= 0; --j) {\n\t\t\t\t\t\t\t\t\tCNCObjectStruct& base_object = ObjectList->Objects[TotalObjectCount + j];\n\t\t\t\t\t\t\t\t\tif (!base_object.SubObject && (base_object.CNCInternalObjectPointer == sub_object.CNCInternalObjectPointer)) {\n\t\t\t\t\t\t\t\t\t\tint sort_order = base_object.SortOrder;\n\t\t\t\t\t\t\t\t\t\tbase_object.SortOrder = sub_object.SortOrder;\n\t\t\t\t\t\t\t\t\t\tsub_object.SortOrder = sort_order;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tTotalObjectCount += CurrentDrawCount;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tObjectList->Count = TotalObjectCount;\n\n\tif (ObjectList->Count) {\n\t\t_export_count++;\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n\n\n\nvoid DLLExportClass::Convert_Type(const ObjectClass *object, CNCObjectStruct &object_out)\n{\t\n\tobject_out.Type = UNKNOWN;\n\tobject_out.ID = -1;\n\t\n\tif (object == NULL) {\n\t\treturn;\n\t}\t  \n\n\tRTTIType type = object->What_Am_I();\n\t\n\tswitch (type) {\n\t\tdefault:\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tobject_out.Type = VESSEL;\n\t\t\tobject_out.ID = Vessels.ID((VesselClass*)object);\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tobject_out.Type = INFANTRY;\n\t\t\tobject_out.ID = Infantry.ID((InfantryClass*)object);\n\t\t\tbreak;\n\t\t\t\t\t\t\n\t\tcase RTTI_UNIT:\n\t\t\tobject_out.Type = UNIT;\n\t\t\tobject_out.ID = Units.ID((UnitClass*)object);\n\t\t\tbreak;\n\t\t\t\t\t\t\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tobject_out.Type = AIRCRAFT;\n\t\t\tobject_out.ID = Aircraft.ID((AircraftClass*)object);\n\t\t\tbreak;\n\t\t\t\t\t\n\t\tcase RTTI_BUILDING:\n\t\t\tobject_out.Type = BUILDING;\n\t\t\tobject_out.ID = Buildings.ID((BuildingClass*)object);\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tobject_out.Type = BULLET;\n\t\t\tobject_out.ID = Bullets.ID((BulletClass*)object);\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tobject_out.Type = ANIM;\n\t\t\tobject_out.ID = Anims.ID((AnimClass*)object);\n\t\t\tbreak;\n\n\t\tcase RTTI_SMUDGE:\n\t\t\tobject_out.Type = SMUDGE;\n\t\t\tobject_out.ID = Smudges.ID((SmudgeClass*)object);\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tobject_out.Type = TERRAIN;\n\t\t\tobject_out.ID = Terrains.ID((TerrainClass*)object);\n\t\t\tbreak;\n\t}\n}\n\n\n\n\n\n\n/**************************************************************************************************\n* CNC_Handle_Input -- Process input to the game\n*\n* In:   \n*       \n*       \n*       \n*\n* Out:  Game state returned in buffer\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Input(InputRequestEnum input_event, unsigned char special_key_flags, uint64 player_id, int x1, int y1, int x2, int y2)\n{\n\t\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tswitch (input_event) {\n\n\t\t/*\n\t\t** Special keys have changed\n\t\t*/\n\t\tcase INPUT_REQUEST_SPECIAL_KEYS:\n\t\t{\n\t\t\tDLLExportClass::Set_Special_Key_Flags(special_key_flags);\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** The mouse is moving\n\t\t*/\n\t\tcase INPUT_REQUEST_MOUSE_MOVE:\n\t\t{\t\n\t\t\tif (!DLLExportClass::Legacy_Render_Enabled()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKEYBOARD->MouseQX = x1;\n\t\t\tKEYBOARD->MouseQY = y1;\n\n\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(x1, y1);\n\t\t\tCELL cell = Coord_Cell(coord);\n\t\t\tif (coord) {\n\t\t\t\t//x -= Map.TacPixelX;\n\t\t\t\t//y -= Map.TacPixelY;\n\n\t\t\t\t/*\n\t\t\t\t** Cause any displayed cursor to move along with the mouse cursor.\n\t\t\t\t*/\n\t\t\t\tif (cell != Map.ZoneCell) {\n\t\t\t\t\tMap.Set_Cursor_Pos(cell);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t** Player left-clicked\n\t\t*/\n\t\tcase INPUT_REQUEST_MOUSE_LEFT_CLICK:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\t\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKEYBOARD->MouseQX = x1;\n\t\t\tKEYBOARD->MouseQY = y1;\n\n\t\t\tKeyNumType key = (KeyNumType)(KN_LMOUSE | KN_RLSE_BIT);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1)) {\n\t\t\t\t//DisplayClass::TacButton.Clicked_On(key, GadgetClass::LEFTRELEASE, x1, y1);\n\t\t\t\tDisplayClass::TacButton.Clicked_On(key, GadgetClass::LEFTRELEASE, 100, 100);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\t\n\t\t\n\t\t/*\n\t\t** Player right-clicked (on up)\n\t\t*/\n\t\tcase INPUT_REQUEST_MOUSE_RIGHT_CLICK:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\t\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKEYBOARD->MouseQX = x1;\n\t\t\tKEYBOARD->MouseQY = y1;\n\n\t\t\tKeyNumType key = (KeyNumType)(KN_RMOUSE | KN_RLSE_BIT);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1)) {\n\t\t\t\t//DisplayClass::TacButton.Clicked_On(key, GadgetClass::RIGHTRELEASE, x1, y1);\n\t\t\t\tDisplayClass::TacButton.Clicked_On(key, GadgetClass::RIGHTRELEASE, 100, 100);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\t\n\n\t\t/*\n\t\t** Player right button down\n\t\t*/\n\t\tcase INPUT_REQUEST_MOUSE_RIGHT_DOWN:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\t\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKEYBOARD->MouseQX = x1;\n\t\t\tKEYBOARD->MouseQY = y1;\n\n\t\t\tKeyNumType key = (KeyNumType)(KN_RMOUSE);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1)) {\n\t\t\t\t//DisplayClass::TacButton.Clicked_On(key, GadgetClass::RIGHTPRESS, x1, y1);\n\t\t\t\tDisplayClass::TacButton.Clicked_On(key, GadgetClass::RIGHTPRESS, 100, 100);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\t\n\n\t\t\t\n\t\t/*\n\t\t** Player drag selected\n\t\t*/\n\t\tcase INPUT_REQUEST_MOUSE_AREA:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tMap.Select_These(XYP_Coord(x1, y1), XYP_Coord(x2, y2), false);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase INPUT_REQUEST_MOUSE_AREA_ADDITIVE:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tMap.Select_These(XYP_Coord(x1, y1), XYP_Coord(x2, y2), true);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase INPUT_REQUEST_SELL_AT_POSITION:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKEYBOARD->MouseQX = x1;\n\t\t\tKEYBOARD->MouseQY = y1;\n\n\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(x1, y1);\n\t\t\tCELL cell = Coord_Cell(coord);\n\n\t\t\tPlayerPtr->Sell_Wall(cell);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase INPUT_REQUEST_SELECT_AT_POSITION:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKeyboard->MouseQX = x1;\n\t\t\tKeyboard->MouseQY = y1;\n\n\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(x1, y1);\n\t\t\tCELL cell = Coord_Cell(coord);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1))\n\t\t\t{\n\t\t\t\tKeyNumType key = (KeyNumType)(KN_LMOUSE | KN_RLSE_BIT);\n\n\t\t\t\tDisplayClass::TacButton.Selection_At_Mouse(GadgetClass::LEFTRELEASE, key);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase INPUT_REQUEST_COMMAND_AT_POSITION:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKeyboard->MouseQX = x1;\n\t\t\tKeyboard->MouseQY = y1;\n\n\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(x1, y1);\n\t\t\tCELL cell = Coord_Cell(coord);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1))\n\t\t\t{\n\t\t\t\tKeyNumType key = (KeyNumType)(KN_LMOUSE | KN_RLSE_BIT);\n\t\t\t\tDisplayClass::TacButton.Command_Object(GadgetClass::LEFTRELEASE, key);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\t// MBL 09.08.2020 - Mod Support\n\t\tcase INPUT_REQUEST_MOD_GAME_COMMAND_1_AT_POSITION:\n\t\tcase INPUT_REQUEST_MOD_GAME_COMMAND_2_AT_POSITION:\n\t\tcase INPUT_REQUEST_MOD_GAME_COMMAND_3_AT_POSITION:\n\t\tcase INPUT_REQUEST_MOD_GAME_COMMAND_4_AT_POSITION:\n\t\t{\n\t\t\tDLLExportClass::Adjust_Internal_View();\n\t\t\tDLLForceMouseX = x1;\n\t\t\tDLLForceMouseY = y1;\n\t\t\tKeyboard->MouseQX = x1;\n\t\t\tKeyboard->MouseQY = y1;\n\n\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(x1, y1);\n\t\t\tCELL cell = Coord_Cell(coord);\n\n\t\t\tif (Map.Pixel_To_Coord(x1, y1))\n\t\t\t{\n\t\t\t\t// TBD: For our ever-awesome Community Modders!\n\t\t\t\t//\n\t\t\t\t// PlayerPtr->Handle_Mod_Game_Command(cell, input_event - INPUT_REQUEST_MOD_GAME_COMMAND_1_AT_POSITION);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\t\t\t\n\n\n\n\n/**************************************************************************************************\n* CNC_Handle_Structure_Request -- Process requests to repair and sell structures.\n*\n* In:\n*\n*\n* Out:\n*\n*\n*\n* History: 4/29/2019 - LLL\n**************************************************************************************************/\n\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Structure_Request(StructureRequestEnum request_type, uint64 player_id, int object_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tswitch (request_type) \n\t{\n\tcase INPUT_STRUCTURE_REPAIR_START: \n\t\tDLLExportClass::Repair_Mode(player_id);\n\t\tbreak;\n\tcase INPUT_STRUCTURE_REPAIR:\n\t\tDLLExportClass::Repair(player_id, object_id);\n\t\tbreak;\n\tcase INPUT_STRUCTURE_SELL_START: \n\t\tDLLExportClass::Sell_Mode(player_id);\n\t\tbreak;\n\tcase INPUT_STRUCTURE_SELL:\n\t\tDLLExportClass::Sell(player_id, object_id);\n\t\tbreak;\n\tcase INPUT_STRUCTURE_CANCEL:\n\t\tDLLExportClass::Repair_Sell_Cancel(player_id);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n\n\n/**************************************************************************************************\n* CNC_Handle_Unit_Request -- Process requests on selected units.\n*\n* In:\n*\n*\n* Out:\n*\n*\n*\n* History: 10/15/2019 - SKY\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Unit_Request(UnitRequestEnum request_type, uint64 player_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tswitch (request_type)\n\t{\n\t\tcase INPUT_UNIT_SCATTER:\n\t\t\tDLLExportClass::Scatter_Selected(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_SELECT_NEXT:\n\t\t\tDLLExportClass::Select_Next_Unit(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_SELECT_PREVIOUS:\n\t\t\tDLLExportClass::Select_Previous_Unit(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_GUARD_MODE:\n\t\t\tDLLExportClass::Selected_Guard_Mode(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_STOP:\n\t\t\tDLLExportClass::Selected_Stop(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_FORMATION_TOGGLE:\n\t\t\tDLLExportClass::Team_Units_Formation_Toggle_On(player_id);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_QUEUED_MOVEMENT_ON:\n\t\t\t// Red Alert Only\n\t\t\tDLLExportClass::Units_Queued_Movement_Toggle(player_id, true);\n\t\t\tbreak;\n\t\tcase INPUT_UNIT_QUEUED_MOVEMENT_OFF:\n\t\t\t// Red Alert Only\n\t\t\tDLLExportClass::Units_Queued_Movement_Toggle(player_id, false);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n\n/**************************************************************************************************\n* CNC_Handle_Sidebar_Request -- Process an input request to the sidebar\n*\n* In:   \n*       \n*       \n* Out:\n*\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Sidebar_Request(SidebarRequestEnum request_type, uint64 player_id, int buildable_type, int buildable_id, short cell_x, short cell_y)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\t\n\tswitch (request_type) {\n\t\t\n\t\t// Changing right-click support for first put building on hold, and then subsequenct right-clicks to decrement that queue count for 1x or 5x; Then, 1x or 5x Left click will resume from hold\t\t\n\t\t// Handle and fall through to start construction (from hold state) below  \n\t\tcase SIDEBAR_REQUEST_START_CONSTRUCTION_MULTI:\n\n\t\tcase SIDEBAR_REQUEST_START_CONSTRUCTION:\n\t\t\tDLLExportClass::Start_Construction(player_id, buildable_type, buildable_id);\n\t\t\tbreak;\n\t\t\t\n\t\tcase SIDEBAR_REQUEST_HOLD_CONSTRUCTION:\n\t\t\tDLLExportClass::Hold_Construction(player_id, buildable_type, buildable_id);\n\t\t\tbreak;\n\t\t\t\n\t\tcase SIDEBAR_REQUEST_CANCEL_CONSTRUCTION:\n\t\t\tDLLExportClass::Cancel_Construction(player_id, buildable_type, buildable_id);\n\t\t\tbreak;\n\n\t\tcase SIDEBAR_REQUEST_START_PLACEMENT:\n\t\t\tDLLExportClass::Start_Placement(player_id, buildable_type, buildable_id);\n\t\t\tbreak;\n\t\t\t\n\t\tcase SIDEBAR_REQUEST_PLACE:\n\t\t\tDLLExportClass::Place(player_id, buildable_type, buildable_id, cell_x, cell_y);\n\t\t\tbreak;\n\n\t\tcase SIDEBAR_CANCEL_PLACE:\n\t\t\tDLLExportClass::Cancel_Placement(player_id, buildable_type, buildable_id);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\t\t\t  \n\n/**************************************************************************************************\n* CNC_Handle_SuperWeapon_Request\n*\n* In:\n*\n*\n* Out:\n*\n*\n*\n* History:\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_SuperWeapon_Request(SuperWeaponRequestEnum request_type, uint64 player_id, int buildable_type, int buildable_id, int x1, int y1)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tswitch (request_type)\n\t{\n\tcase SUPERWEAPON_REQUEST_PLACE_SUPER_WEAPON:\n\t\tDLLExportClass::Place_Super_Weapon(player_id, buildable_type, buildable_id, x1, y1);\n\t\tbreak;\n\t}\n}\n\n/**************************************************************************************************\n* CNC_Handle_ControlGroup_Request\n*\n* In:\n*\n*\n* Out:\n*\n*\n*\n* History:\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_ControlGroup_Request(ControlGroupRequestEnum request_type, uint64 player_id, unsigned char control_group_index)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tswitch (request_type)\n\t{\n\tcase CONTROL_GROUP_REQUEST_CREATE:\n\t\tDLLExportClass::Create_Control_Group(control_group_index);\n\t\tbreak;\n\tcase CONTROL_GROUP_REQUEST_TOGGLE:\n\t\tDLLExportClass::Toggle_Control_Group_Selection(control_group_index);\n\t\tbreak;\n\tcase CONTROL_GROUP_REQUEST_ADDITIVE_SELECTION:\n\t\tDLLExportClass::Add_To_Control_Group(control_group_index);\n\t\tbreak;\n\n\t}\n}\n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Layer_State -- Get a snapshot of the sidebar state\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/29/2019 11:37AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Sidebar_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tCNCSidebarStruct *sidebar = (CNCSidebarStruct*) buffer_in;\n\t\n\tunsigned int memory_needed = sizeof(*sidebar);\t// Base amount needed. Will need more depending on how many entries there are\n\t\n\tint entry_index = 0;\n\n\tsidebar->Credits = 0;\n\tsidebar->CreditsCounter = 0;\n\tsidebar->Tiberium = 0;\n\tsidebar->MaxTiberium = 0;\n\tsidebar->PowerProduced = 0;\n\tsidebar->PowerDrained = 0;\n\tsidebar->RepairBtnEnabled = false;\n\tsidebar->SellBtnEnabled = false;\n\tsidebar->RadarMapActive = false;\n\tsidebar->MissionTimer = Scen.MissionTimer.Is_Active() ? (Scen.MissionTimer / TICKS_PER_SECOND) : -1;\n\n\tsidebar->UnitsKilled = 0;\n\tsidebar->BuildingsKilled = 0;\n\tsidebar->UnitsLost = 0;\n\tsidebar->BuildingsLost = 0;\n\tsidebar->TotalHarvestedCredits = 0;\n\n\tif (PlayerPtr) {\n\t\tsidebar->Credits = PlayerPtr->Credits; \n\t\tsidebar->CreditsCounter = PlayerPtr->VisibleCredits.Current; \t\t// Timed display\n\t\t// sidebar->CreditsCounter = PlayerPtr->VisibleCredits.Credits;\t// Actual \n\t\tsidebar->Tiberium = PlayerPtr->Tiberium;\n\t\tsidebar->MaxTiberium = PlayerPtr->Capacity;\n\t\tsidebar->PowerProduced = PlayerPtr->Power;\n\t\tsidebar->PowerDrained = PlayerPtr->Drain;\n\n\t\tsidebar->RepairBtnEnabled = PlayerPtr->BScan > 0;\n\t\tsidebar->SellBtnEnabled = PlayerPtr->BScan > 0;\n\t\tsidebar->RadarMapActive = PlayerPtr->Radar == RADAR_ON;\n\n\n\t\t// A. Get the DestroyedBuildings and DestroyedInfantry stats if they are available at this point\n\t\tif (PlayerPtr->DestroyedBuildings) {\n\t\t\tfor ( int index = 0; index < PlayerPtr->DestroyedBuildings->Get_Unit_Count(); index ++ )\n\t\t\t{\n\t\t\t\tunsigned int count = (unsigned int) PlayerPtr->DestroyedBuildings->Get_Unit_Total( index );\n\t\t\t\tsidebar->BuildingsKilled += count;\n\t\t\t}\n\t\t}\n\t\tif (PlayerPtr->DestroyedInfantry) {\n\t\t\tfor ( int index = 0; index < PlayerPtr->DestroyedInfantry->Get_Unit_Count(); index ++ )\n\t\t\t{\n\t\t\t\tunsigned int count = (unsigned int) PlayerPtr->DestroyedInfantry->Get_Unit_Total( index );\n\t\t\t\tsidebar->UnitsKilled += count; // Includes Infantry, Vehicles, Aircraft\n\t\t\t}\n\t\t}\n\t\tif (PlayerPtr->DestroyedUnits) {\n\t\t\tfor ( int index = 0; index < PlayerPtr->DestroyedUnits->Get_Unit_Count(); index ++ )\n\t\t\t{\n\t\t\t\tunsigned int count = (unsigned int) PlayerPtr->DestroyedUnits->Get_Unit_Total( index );\n\t\t\t\tsidebar->UnitsKilled += count; // Includes Infantry, Vehicles, Aircraft\n\t\t\t}\n\t\t}\n\t\tif (PlayerPtr->DestroyedAircraft) {\n\t\t\tfor ( int index = 0; index < PlayerPtr->DestroyedAircraft->Get_Unit_Count(); index ++ )\n\t\t\t{\n\t\t\t\tunsigned int count = (unsigned int) PlayerPtr->DestroyedAircraft->Get_Unit_Total( index );\n\t\t\t\tsidebar->UnitsKilled += count; // Includes Infantry, Vehicles, Aircraft\n\t\t\t}\n\t\t}\n\n\t\t// B. If the DestroyedBuildings and DestroyedInfantry stats seemed to be unvailable, this is another way to do it\n\t\t// Note that we need to do both of these depending on which type of match we are running, as well as for Replays/Observer and live stats reporting\n\t\t// We can't just do it this way for everything, as it does not work for all cases\n\t\tif (sidebar->BuildingsKilled == 0)\n\t\t{\n\t\t\tfor (unsigned int house_index = 0; house_index < HOUSE_COUNT; house_index ++)\n\t\t\t{\n\t\t\t\tsidebar->BuildingsKilled += PlayerPtr->BuildingsKilled[ house_index ];\n\t\t\t}\n\t\t}\n\t\tif (sidebar->UnitsKilled == 0)\n\t\t{\n\t\t\tfor (unsigned int house_index = 0; house_index < HOUSE_COUNT; house_index ++)\n\t\t\t{\n\t\t\t\tsidebar->UnitsKilled += PlayerPtr->UnitsKilled[ house_index ]; // Includes Infantry, Vehicles, Aircraft\n\t\t\t}\n\t\t}\n\n\n\n\t\tsidebar->UnitsLost = PlayerPtr->UnitsLost;\n\t\tsidebar->BuildingsLost = PlayerPtr->BuildingsLost;\n\t\tsidebar->TotalHarvestedCredits = PlayerPtr->HarvestedCredits;\n\t}\n\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\n\t\t/*\n\t\t** Get each sidebar column\n\t\t*/\n\t\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t\tsidebar->EntryCount[c] = Map.Column[c].BuildableCount;\n\t\t\t\t\n\t\t\t/*\n\t\t\t** Each production slot in the column\n\t\t\t*/\n\t\t\tfor (int b=0 ; b < Map.Column[c].BuildableCount ; b++) {\n\t\t\t\n\t\t\t\tCNCSidebarEntryStruct &sidebar_entry = sidebar->Entries[entry_index++];\n\t\t\t\tif ((entry_index + 1) * sizeof(CNCSidebarEntryStruct) + memory_needed > buffer_size) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tmemset(&sidebar_entry, 0, sizeof(sidebar_entry));\n\n\t\t\t\tsidebar_entry.AssetName[0] = 0;\n\t\t\t\tsidebar_entry.Type = UNKNOWN;\n\t\t\t\tsidebar_entry.BuildableID = Map.Column[c].Buildables[b].BuildableID;\n\t\t\t\tsidebar_entry.BuildableType = Map.Column[c].Buildables[b].BuildableType;\n\t\t\t\tsidebar_entry.BuildableViaCapture = Map.Column[c].Buildables[b].BuildableViaCapture;\n\t\t\t   sidebar_entry.Fake = false;\n\n\t\t\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(Map.Column[c].Buildables[b].BuildableType, Map.Column[c].Buildables[b].BuildableID);\n\t\t\t\t\n\t\t\t\tsidebar_entry.SuperWeaponType = SW_NONE;\n\n\t\t\t\tif (tech) {\n\t\t\t\t\tsidebar_entry.Cost = tech->Cost * PlayerPtr->CostBias; // If this gets modified, also modify below for skirmish and multiplayer\n\t\t\t\t\tsidebar_entry.PowerProvided = 0;\n\t\t\t\t\tsidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60;\n\t\t\t\t\tstrncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t\t} else {\n\t\t\t\t\tsidebar_entry.Cost = 0;\n\t\t\t\t\tsidebar_entry.AssetName[0] = 0;\n\t\t\t\t}\t\n\t\t\t\t\n\t\t\t\tSuperClass* super_weapon = nullptr;\n\t\t\t\t\n\t\t\t\tbool isbusy = false;\n\n\t\t\t\tswitch (Map.Column[c].Buildables[b].BuildableType) {\n\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\tsidebar_entry.Type = INFANTRY_TYPE;\n\t\t\t\t\t\tisbusy = (PlayerPtr->InfantryFactory != -1);\n\t\t\t\t\t\tisbusy |= Infantry.Avail() <= 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\tisbusy = (PlayerPtr->UnitFactory != -1);\n\t\t\t\t\t\tisbusy |= Units.Avail() <= 0;\n\t\t\t\t\t\tsidebar_entry.Type = UNIT_TYPE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\tisbusy = (PlayerPtr->AircraftFactory != -1);\n\t\t\t\t\t\tisbusy |= Aircraft.Avail() <= 0;\n\t\t\t\t\t\tsidebar_entry.Type = AIRCRAFT_TYPE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\t\t{\n\t\t\t\t\t\tisbusy = (PlayerPtr->BuildingFactory != -1);\n\t\t\t\t\t\tisbusy |= Buildings.Avail() <= 0;\n\t\t\t\t\t\tsidebar_entry.Type = BUILDING_TYPE;\n\n\t\t\t\t\t\tconst BuildingTypeClass* build_type = static_cast<const BuildingTypeClass*>(tech);\n\t\t\t\t\t\tsidebar_entry.PowerProvided = build_type->Power - build_type->Drain;\n\t\t\t   \t\tsidebar_entry.Fake = build_type->IsFake;\n\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\t\t\tsidebar_entry.Type = VESSEL_TYPE;\n\t\t\t\t\t\tisbusy = (PlayerPtr->VesselFactory != -1);\n\t\t\t\t\t\tisbusy |= Vessels.Avail() <= 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsidebar_entry.Type = UNKNOWN;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase RTTI_SPECIAL:\n\t\t\t\t\t\tFill_Sidebar_Entry_From_Special_Weapon(sidebar_entry, super_weapon, (SpecialWeaponType)Map.Column[c].Buildables[b].BuildableID);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (super_weapon != nullptr)\n\t\t\t\t{\n\t\t\t\t\tsidebar_entry.Progress = (float)super_weapon->Anim_Stage() / (float)SuperClass::ANIMATION_STAGES;\n\t\t\t\t\tsidebar_entry.Completed = super_weapon->Is_Ready();\n\t\t\t\t\tsidebar_entry.Constructing = super_weapon->Anim_Stage() != SuperClass::ANIMATION_STAGES;\n\t\t\t\t\tsidebar_entry.ConstructionOnHold = false;\n\t\t\t\t\tsidebar_entry.PlacementListLength = 0;\n\t\t\t\t\tsidebar_entry.PowerProvided = 0;\n\t\t\t\t\tsidebar_entry.BuildTime = super_weapon->Get_Recharge_Time();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\n\t\t\t\t\tint fnumber = Map.Column[c].Buildables[b].Factory;\n\t\t\t\t\tFactoryClass * factory = NULL;\n\t\t\t\t\tif (tech && fnumber != -1) {\n\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t}\n\n\t\t\t\t\tsidebar_entry.Completed = false;\n\t\t\t\t\tsidebar_entry.Constructing = false;\n\t\t\t\t\tsidebar_entry.ConstructionOnHold = false;\n\t\t\t\t\tsidebar_entry.Progress = 0.0f;\n\t\t\t\t\tsidebar_entry.Busy = isbusy;\n\t\t\t\t\tsidebar_entry.PlacementListLength = 0;\n\n\t\t\t\t\tif (factory) {\n\t\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\t\tsidebar_entry.Constructing = true;\n\t\t\t\t\t\t\tsidebar_entry.Progress = (float)factory->Completion() / (float)FactoryClass::STEP_COUNT;\n\t\t\t\t\t\t\tsidebar_entry.Completed = factory->Has_Completed();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsidebar_entry.Completed = factory->Has_Completed();\n\n\t\t\t\t\t\t\tif (!sidebar_entry.Completed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsidebar_entry.ConstructionOnHold = true;\n\t\t\t\t\t\t\t\tsidebar_entry.Progress = (float)factory->Completion() / (float)FactoryClass::STEP_COUNT;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (sidebar_entry.Completed && sidebar_entry.Type == BUILDING_TYPE) {\n\t\t\t\t\t\t\t\tif (tech) {\n\t\t\t\t\t\t\t\t\tBuildingTypeClass *building_type = (BuildingTypeClass*)tech;\n\t\t\t\t\t\t\t\t\tshort const *occupy_list = building_type->Occupy_List(true);\n\t\t\t\t\t\t\t\t\tif (occupy_list) {\n\t\t\t\t\t\t\t\t\t\twhile (*occupy_list != REFRESH_EOL && sidebar_entry.PlacementListLength < MAX_OCCUPY_CELLS) {\n\t\t\t\t\t\t\t\t\t\t\tsidebar_entry.PlacementList[sidebar_entry.PlacementListLength] = *occupy_list;\n\t\t\t\t\t\t\t\t\t\t\tsidebar_entry.PlacementListLength++;\n\t\t\t\t\t\t\t\t\t\t\toccupy_list++;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\n\t} else {\n\t\t\n\t\t\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\n\t\t\tSidebarGlyphxClass *context_sidebar = DLLExportClass::Get_Current_Context_Sidebar();\n\t\t\t\n\t\t\t/*\n\t\t\t** Get each sidebar column\n\t\t\t*/\n\t\t\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t\t\tsidebar->EntryCount[c] = context_sidebar->Column[c].BuildableCount;\n\t\t\t\t\n\t\t\t\t/*\n\t\t\t\t** Each production slot in the column\n\t\t\t\t*/\n\t\t\t\tfor (int b=0 ; b < context_sidebar->Column[c].BuildableCount ; b++) {\n\t\t\t\n\t\t\t\t\tCNCSidebarEntryStruct &sidebar_entry = sidebar->Entries[entry_index++];\n\t\t\t\t\tif ((entry_index + 1) * sizeof(CNCSidebarEntryStruct) + memory_needed > buffer_size) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tmemset(&sidebar_entry, 0, sizeof(sidebar_entry));\n\n\t\t\t\t\tsidebar_entry.AssetName[0] = 0;\n\t\t\t\t\tsidebar_entry.Type = UNKNOWN;\n\t\t\t\t\tsidebar_entry.BuildableID = context_sidebar->Column[c].Buildables[b].BuildableID;\n\t\t\t\t\tsidebar_entry.BuildableType = context_sidebar->Column[c].Buildables[b].BuildableType;\n\t\t\t\t\tsidebar_entry.BuildableViaCapture = context_sidebar->Column[c].Buildables[b].BuildableViaCapture;\n\t\t\t   \tsidebar_entry.Fake = false;\n\t\t\t\n\t\t\t\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(context_sidebar->Column[c].Buildables[b].BuildableType, context_sidebar->Column[c].Buildables[b].BuildableID);\n\t\t\t\t\n\t\t\t\t\tsidebar_entry.SuperWeaponType = SW_NONE;\n\n\t\t\t\t\tif (tech) {\n\n\t\t\t\t\t\t// Updated to apply and difficulty abd/or faction price modifier; See https://jaas.ea.com/browse/TDRA-6864\n\t\t\t\t\t\t// If this gets modified, also modify above for non-skirmish / non-multiplayer\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// sidebar_entry.Cost = tech->Cost;\n\t\t\t\t\t\tsidebar_entry.Cost = tech->Cost * PlayerPtr->CostBias;\n\n\t\t\t\t\t\tsidebar_entry.PowerProvided = 0;\n\t\t\t\t\t\tsidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60;\n\t\t\t\t\t\tstrncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsidebar_entry.Cost = 0;\n\t\t\t\t\t\tsidebar_entry.AssetName[0] = 0;\n\t\t\t\t\t}\t\n\t\t\t\t\t\n\t\t\t\t\tSuperClass* super_weapon = nullptr;\n\t\t\t\t\tbool isbusy = false;\n\n\t\t\t\t\tswitch (context_sidebar->Column[c].Buildables[b].BuildableType) {\n\t\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\t\tsidebar_entry.Type = INFANTRY_TYPE;\n\t\t\t\t\t\t\tisbusy = (PlayerPtr->InfantryFactory != -1);\n\t\t\t\t\t\t\tisbusy |= Infantry.Avail() <= 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\t\tisbusy = (PlayerPtr->UnitFactory != -1);\n\t\t\t\t\t\t\tisbusy |= Units.Avail() <= 0;\n\t\t\t\t\t\t\tsidebar_entry.Type = UNIT_TYPE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\t\tisbusy = (PlayerPtr->AircraftFactory != -1);\n\t\t\t\t\t\t\tisbusy |= Aircraft.Avail() <= 0;\n\t\t\t\t\t\t\tsidebar_entry.Type = AIRCRAFT_TYPE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\t\t\t{\t\n\t\t\t\t\t\t\tisbusy = (PlayerPtr->BuildingFactory != -1);\n\t\t\t\t\t\t\tisbusy |= Buildings.Avail() <= 0;\n\t\t\t\t\t\t\tsidebar_entry.Type = BUILDING_TYPE;\n\n\t\t\t\t\t\t\tconst BuildingTypeClass* build_type = static_cast<const BuildingTypeClass*>(tech);\n\t\t\t\t\t\t\tsidebar_entry.PowerProvided = build_type->Power - build_type->Drain;\n\t\t\t   \t\t\tsidebar_entry.Fake = build_type->IsFake;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\t\t\t\tisbusy = (PlayerPtr->VesselFactory != -1);\n\t\t\t\t\t\t\tisbusy |= Vessels.Avail() <= 0;\n\t\t\t\t\t\t\tsidebar_entry.Type = VESSEL_TYPE;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tsidebar_entry.Type = UNKNOWN;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_SPECIAL:\n\t\t\t\t\t\t\tFill_Sidebar_Entry_From_Special_Weapon(sidebar_entry, super_weapon, (SpecialWeaponType)sidebar_entry.BuildableID);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (super_weapon != nullptr)\n\t\t\t\t\t{\n\t\t\t\t\t\tsidebar_entry.Progress = (float)super_weapon->Anim_Stage() / (float)SuperClass::ANIMATION_STAGES;\n\t\t\t\t\t\tsidebar_entry.Completed = super_weapon->Is_Ready();\n\t\t\t\t\t\tsidebar_entry.Constructing = super_weapon->Anim_Stage() != SuperClass::ANIMATION_STAGES;\n\t\t\t\t\t\tsidebar_entry.ConstructionOnHold = false;\n\t\t\t\t\t\tsidebar_entry.PlacementListLength = 0;\n\t\t\t\t\t\tsidebar_entry.PowerProvided = 0;\n\t\t\t\t\t\tsidebar_entry.BuildTime = super_weapon->Get_Recharge_Time();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\n\t\t\t\t\t\tint fnumber = context_sidebar->Column[c].Buildables[b].Factory;\n\t\t\t\t\t\tFactoryClass * factory = NULL;\n\t\t\t\t\t\tif (tech && fnumber != -1) {\n\t\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t\t}\n\t\t\t\n\t\t\t\t\t\tsidebar_entry.Completed = false;\n\t\t\t\t\t\tsidebar_entry.Constructing = false;\n\t\t\t\t\t\tsidebar_entry.ConstructionOnHold = false;\n\t\t\t\t\t\tsidebar_entry.Progress = 0.0f;\n\t\t\t\t\t\tsidebar_entry.Busy = isbusy;\n\t\t\t\t\t\tsidebar_entry.PlacementListLength = 0;\n\t\t\t  \n\t\t\t\t\t\tif (factory) {\n\t\t\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\t\t\tsidebar_entry.Constructing = true;\n\t\t\t\t\t\t\t\tsidebar_entry.Progress = (float)factory->Completion() / (float)FactoryClass::STEP_COUNT;\n\t\t\t\t\t\t\t\tsidebar_entry.Completed = factory->Has_Completed();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tsidebar_entry.Completed = factory->Has_Completed();\n\n\t\t\t\t\t\t\t\tif (!sidebar_entry.Completed)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsidebar_entry.ConstructionOnHold = true;\n\t\t\t\t\t\t\t\t\tsidebar_entry.Progress = (float)factory->Completion() / (float)FactoryClass::STEP_COUNT;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (sidebar_entry.Completed && sidebar_entry.Type == BUILDING_TYPE) {\n\t\t\t\t\t\t\t\t\tif (tech) {\n\t\t\t\t\t\t\t\t\t\tBuildingTypeClass *building_type = (BuildingTypeClass*)tech;\n\t\t\t\t\t\t\t\t\t\tshort const *occupy_list = building_type->Occupy_List(true);\n\t\t\t\t\t\t\t\t\t\tif (occupy_list) {\n\t\t\t\t\t\t\t\t\t\t\twhile (*occupy_list != REFRESH_EOL && sidebar_entry.PlacementListLength < MAX_OCCUPY_CELLS) {\n\t\t\t\t\t\t\t\t\t\t\t\tsidebar_entry.PlacementList[sidebar_entry.PlacementListLength] = *occupy_list;\n\t\t\t\t\t\t\t\t\t\t\t\tsidebar_entry.PlacementListLength++;\n\t\t\t\t\t\t\t\t\t\t\t\toccupy_list++;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\treturn true;\n}\n\n\nvoid DLLExportClass::Convert_Action_Type(ActionType type, ObjectClass* object, TARGET target, DllActionTypeEnum& dll_type)\n{\n\tswitch (type)\n\t{\n\t\tcase ACTION_NONE:\n\t\tdefault:\n\t\t\tdll_type = DAT_NONE;\n\t\t\tbreak;\n\t\tcase ACTION_MOVE:\n\t\t\tdll_type = DAT_MOVE;\n\t\t\tbreak;\n\t\tcase ACTION_NOMOVE:\n\t\t\tdll_type = DAT_NOMOVE;\n\t\t\tbreak;\n\t\tcase ACTION_ENTER:\n\t\t\tdll_type = DAT_ENTER;\n\t\t\tbreak;\n\t\tcase ACTION_SELF:\n\t\t\tdll_type = DAT_SELF;\n\t\t\tbreak;\n\t\tcase ACTION_ATTACK:\n\t\t\tif (Target_Legal(target) && (object != NULL) && object->Is_Techno() && ((TechnoClass*)object)->In_Range(target, 0)) {\n\t\t\t\tdll_type = DAT_ATTACK;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdll_type = DAT_ATTACK_OUT_OF_RANGE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ACTION_GUARD_AREA:\n\t\t\tdll_type = DAT_GUARD;\n\t\t\tbreak;\n\t\tcase ACTION_HARVEST:\n\t\t\tdll_type = DAT_ATTACK;\n\t\t\tbreak;\n\t\tcase ACTION_SELECT:\n\t\tcase ACTION_TOGGLE_SELECT:\n\t\t\tdll_type = DAT_SELECT;\n\t\t\tbreak;\n\t\tcase ACTION_CAPTURE:\n\t\t\tdll_type = DAT_CAPTURE;\n\t\t\tbreak;\n\t\tcase ACTION_DAMAGE:\n\t\t\tdll_type = DAT_DAMAGE;\n\t\t\tbreak;\n\t\tcase ACTION_SABOTAGE:\n\t\t\tdll_type = DAT_SABOTAGE;\n\t\t\tbreak;\n\t\tcase ACTION_HEAL:\n\t\t\tdll_type = DAT_HEAL;\n\t\t\tbreak;\n\t\tcase ACTION_TOGGLE_PRIMARY:\n\t\t\tdll_type = DAT_TOGGLE_PRIMARY;\n\t\t\tbreak;\n\t\tcase ACTION_NO_DEPLOY:\n\t\t\tdll_type = DAT_CANT_DEPLOY;\n\t\t\tbreak;\n\t\tcase ACTION_GREPAIR:\n\t\t\tdll_type = DAT_REPAIR;\n\t\t\tbreak;\n\t\tcase ACTION_NO_GREPAIR:\n\t\t\tdll_type = DAT_CANT_REPAIR;\n\t\t\tbreak;\n\t}\n}\n\n\nvoid DLLExportClass::Convert_Special_Weapon_Type(SpecialWeaponType weapon_type, DllSuperweaponTypeEnum& dll_weapon_type, char* weapon_name)\n{\n\tswitch (weapon_type) \n\t{\n\tcase SPC_SONAR_PULSE:\n\t\tdll_weapon_type = SW_SONAR_PULSE;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_SonarPulse\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_NUCLEAR_BOMB:\n\t\tdll_weapon_type = SW_NUKE;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_Nuke\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_CHRONOSPHERE:\n\t\tdll_weapon_type = SW_CHRONOSPHERE;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_Chrono\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_PARA_BOMB:\n\t\tdll_weapon_type = SW_PARA_BOMB;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_ParaBomb\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_PARA_INFANTRY:\n\t\tdll_weapon_type = SW_PARA_INFANTRY;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_ParaInfantry\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_SPY_MISSION:\n\t\tdll_weapon_type = SW_SPY_MISSION;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_SpyMission\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_IRON_CURTAIN:\n\t\tdll_weapon_type = SW_IRON_CURTAIN;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_IronCurtain\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_GPS:\n\t\tdll_weapon_type = SW_GPS;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_GPS\", 16);\n\t\t}\n\t\tbreak;\n\tcase SPC_CHRONO2:\n\t\tdll_weapon_type = SW_CHRONOSPHERE_DESTINATION;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tstrncpy(weapon_name, \"SW_Chrono2\", 16);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tdll_weapon_type = SW_UNKNOWN;\n\t\tif (weapon_name != NULL)\n\t\t{\n\t\t\tweapon_name[0] = '\\0';\n\t\t}\n\t\tbreak;\n\t}\n}\n\n\nvoid DLLExportClass::Fill_Sidebar_Entry_From_Special_Weapon(CNCSidebarEntryStruct& sidebar_entry_out, SuperClass*& super_weapon_out, SpecialWeaponType weapon_type)\n{\n\tsidebar_entry_out.Type = SPECIAL;\n\n\tswitch (weapon_type) \n\t{\n\tcase SPC_SONAR_PULSE:\n\tcase SPC_NUCLEAR_BOMB:\n\tcase SPC_CHRONOSPHERE:\n\tcase SPC_PARA_BOMB:\n\tcase SPC_PARA_INFANTRY:\n\tcase SPC_SPY_MISSION:\n\tcase SPC_IRON_CURTAIN:\n\tcase SPC_GPS:\n\tcase SPC_CHRONO2:\n\t\tConvert_Special_Weapon_Type(weapon_type, sidebar_entry_out.SuperWeaponType, sidebar_entry_out.AssetName);\n\t\tbreak;\n\tdefault:\n\t\tsidebar_entry_out.SuperWeaponType = SW_UNKNOWN;\n\t\tsidebar_entry_out.Type = UNKNOWN;\n\t\tsuper_weapon_out = nullptr;\n\t\treturn;\n\t}\n\n\tsuper_weapon_out = &(PlayerPtr->SuperWeapon[weapon_type]);\n}\n\nstatic const int _map_width_shift_bits = 7;\n\nvoid DLLExportClass::Calculate_Placement_Distances(BuildingTypeClass* placement_type, unsigned char* placement_distance)\n{\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_height++;\n\t}\n\n\tstatic const FacingType _scan_facings[] = {\n\t\tFACING_E,\n\t\tFACING_S,\n\t\tFACING_W,\n\t\tFACING_N\n\t};\n\n\tmemset(placement_distance, 255U, MAP_CELL_TOTAL);\n\tfor (int y = 0; y < map_cell_height; y++) {\n\t\tfor (int x = 0; x < map_cell_width; x++) {\n\t\t\tCELL cell = (CELL)map_cell_x + x + ((map_cell_y + y) << _map_width_shift_bits);\n\t\t\tBuildingClass* base = (BuildingClass*)Map[cell].Cell_Find_Object(RTTI_BUILDING);\n\t\t\tif ((base && base->House->Class->House == PlayerPtr->Class->House && base->Class->IsBase) ||\n\t\t\t\t((placement_type->IsWall || ((Map[cell].Smudge != SMUDGE_NONE) && SmudgeTypeClass::As_Reference(Map[cell].Smudge).IsBib)) &&\n\t\t\t\t\tMap[cell].Owner == PlayerPtr->Class->House)) {\n\t\t\t\tplacement_distance[cell] = 0U;\n\t\t\t\tCELL startcell = cell;\n\t\t\t\tfor (unsigned char distance = 1U; distance <= (placement_type->Adjacent + 1U); distance++) {\n\t\t\t\t\tstartcell = Adjacent_Cell(startcell, FACING_NW);\n\t\t\t\t\tCELL scancell = startcell;\n\t\t\t\t\tfor (int i = 0; i < ARRAY_SIZE(_scan_facings); i++) {\n\t\t\t\t\t\tCELL nextcell = scancell;\n\t\t\t\t\t\tfor (unsigned char scan = 0U; scan <= (distance * 2U); scan++) {\n\t\t\t\t\t\t\tscancell = nextcell;\n\t\t\t\t\t\t\tif (Map.In_Radar(scancell)) {\n\t\t\t\t\t\t\t\tplacement_distance[scancell] = min(placement_distance[scancell], distance);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnextcell = Adjacent_Cell(scancell, _scan_facings[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Recalculate_Placement_Distances()\n{\n\tDLLExportClass::Recalculate_Placement_Distances();\n}\n\nvoid DLLExportClass::Recalculate_Placement_Distances()\n{\n\tif (PlacementType[CurrentLocalPlayerIndex] != NULL) {\n\t\tCalculate_Placement_Distances(PlacementType[CurrentLocalPlayerIndex], PlacementDistance[CurrentLocalPlayerIndex]);\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Get_Placement_State -- Get a snapshot of legal validity of placing a structure on all map cells\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/4/2019 3:11PM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Placement_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tif (PlacementType[CurrentLocalPlayerIndex] == NULL) {\n\t\treturn false;\n\t}\n\n\tCNCPlacementInfoStruct *placement_info = (CNCPlacementInfoStruct*) buffer_in;\n\t\n\tunsigned int memory_needed = sizeof(*placement_info);\t// Base amount needed. Will need more depending on how many entries there are\n\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_height++;\n\t}\n\n\tmemory_needed += map_cell_width * map_cell_height * sizeof(CNCPlacementCellInfoStruct);\n\n\tif (memory_needed + 128 >= buffer_size) {\n\t\treturn false;\n\t}\n\n\tplacement_info->Count = map_cell_width * map_cell_height;\n\n\tint index = 0;\n\tfor (int y=0 ; y < map_cell_height ; y++) {\n\t\tfor (int x=0 ; x < map_cell_width ; x++) {\n\n\t\t\tCELL cell = (CELL) map_cell_x + x + ((map_cell_y + y) << _map_width_shift_bits);\n\n\t\t\tbool pass = Passes_Proximity_Check(cell, PlacementType[CurrentLocalPlayerIndex], PlacementDistance[CurrentLocalPlayerIndex]);\n\n\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\tbool clear = cellptr->Is_Clear_To_Build(PlacementType[CurrentLocalPlayerIndex]->Speed);\n\n\t\t\tCNCPlacementCellInfoStruct &placement_cell_info = placement_info->CellInfo[index++];\n\t\t\tplacement_cell_info.PassesProximityCheck = pass;\n\t\t\tplacement_cell_info.GenerallyClear = clear;\n\t\t}\t\n\t}\n\n\tMap.ZoneOffset = 0;\n\n\treturn true;\n}\n\n\nbool DLLExportClass::Passes_Proximity_Check(CELL cell_in, BuildingTypeClass *placement_type, unsigned char* placement_distance)\n{\n\t\t\t  \n\t/*\n\t**\tScan through all cells that the building foundation would cover. If any adjacent\n\t**\tcells to these are of friendly persuasion, then consider the proximity check to\n\t**\thave been a success.\n\t*/\n\tshort const *occupy_list = placement_type->Occupy_List(true);\n\t\n\twhile (*occupy_list != REFRESH_EOL) {\n\n\t\tCELL center_cell = cell_in + *occupy_list++;\n\n\t\tif (!Map.In_Radar(center_cell)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (placement_distance[center_cell] <= (placement_type->Adjacent + 1)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Start_Construction -- Start sidebar construction\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/29/2019 11:37AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Start_Construction(uint64 player_id, int buildable_type, int buildable_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\treturn Construction_Action(SIDEBAR_REQUEST_START_CONSTRUCTION, player_id, buildable_type, buildable_id);\n\t}\n\treturn MP_Construction_Action(SIDEBAR_REQUEST_START_CONSTRUCTION, player_id, buildable_type, buildable_id);\n}\n\n/**************************************************************************************************\n* DLLExportClass::Hold_Construction -- Pause sidebar construction\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 6/12/2019 JAS\n**************************************************************************************************/\nbool DLLExportClass::Hold_Construction(uint64 player_id, int buildable_type, int buildable_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id))\n\t{\n\t\treturn false;\n\t}\n\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\treturn Construction_Action(SIDEBAR_REQUEST_HOLD_CONSTRUCTION, player_id, buildable_type, buildable_id);\n\t}\n\treturn MP_Construction_Action(SIDEBAR_REQUEST_HOLD_CONSTRUCTION, player_id, buildable_type, buildable_id);\n}\n\n/**************************************************************************************************\n* DLLExportClass::Cancel_Construction -- Stop sidebar construction\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 6/12/2019 JAS\n**************************************************************************************************/\nbool DLLExportClass::Cancel_Construction(uint64 player_id, int buildable_type, int buildable_id)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id))\n\t{\n\t\treturn false;\n\t}\n\n\treturn Cancel_Placement(player_id, buildable_type, buildable_id) &&\n\t\t((GAME_TO_PLAY == GAME_NORMAL) ?\n\t\t\tConstruction_Action(SIDEBAR_REQUEST_CANCEL_CONSTRUCTION, player_id, buildable_type, buildable_id) :\n\t\t\tMP_Construction_Action(SIDEBAR_REQUEST_CANCEL_CONSTRUCTION, player_id, buildable_type, buildable_id));\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Construction_Action -- Reproduce actions on the sidebar\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/29/2019 11:37AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Construction_Action(SidebarRequestEnum construction_action, uint64 player_id, int buildable_type, int buildable_id)\n{\t\t\n\t\t\n\t/*\n\t** \n\t** Based on SidebarClass::StripClass::SelectClass::Action\n\t** \n\t** Most of this code is validating that the game is in the correct state to be able to act on a sidebar icon\n\t** \n\t*/\n\t\t\t\n\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t/*\n\t\t** Each production slot in the column\n\t\t*/\n\t\tfor (int b=0 ; b < Map.Column[c].BuildableCount ; b++) {\n\t\t\tif (Map.Column[c].Buildables[b].BuildableID == buildable_id) {\n\t\t\t\tif (Map.Column[c].Buildables[b].BuildableType == buildable_type) {\n\t\t\t\t\t\n\t\t\t\t\tint fnumber = Map.Column[c].Buildables[b].Factory;\n\t\t\t\t\tint spc = 0;\n\t\t\t\t\tObjectTypeClass const * choice = NULL;\n\n\t\t\t\t\tif (buildable_type != RTTI_SPECIAL) {\n\t\t\t\t\t\tchoice  = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tspc = buildable_id;\n\t\t\t\t\t}\n\n\t\t\t\t\tFactoryClass * factory = PlayerPtr->Fetch_Factory((RTTIType)buildable_type);\n\t\t\t\t\tif (fnumber != -1) {\n\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (spc == 0 && choice) {\n\t\t\t\t\t\tif (fnumber == -1 && factory != NULL) {\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (factory) {\n\n\t\t\t\t\t\t\tswitch (construction_action)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_CANCEL_CONSTRUCTION:\n\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_CANCELED); // Speak(VOX_CANCELED);\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_HOLD_CONSTRUCTION:\n\t\t\t\t\t\t\t\tif (factory->Is_Building())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_SUSPENDED); // Speak(VOX_SUSPENDED);\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SUSPEND, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tIf this object is currently being built, then give a scold sound and text and then\n\t\t\t\t\t\t\t\t**\tbail.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); //Speak(VOX_NO_FACTORY); // \"Cannot Comply\"\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\t\t\t\t// TO_DO\n\t\t\t\t\t\t\t\t\t\t\t//Map.IsTargettingMode = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); //Speak(VOX_NO_FACTORY); // \"Cannot Comply\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (construction_action == SIDEBAR_REQUEST_START_PLACEMENT) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tFor objects that can leave the factory under their own\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tpower, queue this event and process through normal house\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tproduction channels.\n\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\t\t//OutList.Add(EventClass(EventClass::PLACE, otype, -1));\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t**\tThe factory must have been in a suspended state. Resume construction\n\t\t\t\t\t\t\t\t\t\t**\tnormally.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tif (construction_action == SIDEBAR_REQUEST_START_CONSTRUCTION) {\n\t\t\t\t\t\t\t\t\t\t\tif ((RTTIType)buildable_type == RTTI_INFANTRYTYPE) \n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_TRAINING); // Speak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_BUILDING); // Speak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tswitch (construction_action)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_CANCEL_CONSTRUCTION:\n\t\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_HOLD_CONSTRUCTION:\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf this side strip is already busy with production, then ignore the\n\t\t\t\t\t\t\t\t\t**\tinput and announce this fact.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif ((RTTIType)buildable_type == RTTI_INFANTRYTYPE)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_TRAINING); // Speak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_BUILDING); // Speak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, (RTTIType)buildable_type, buildable_id));\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Execute immediately so we get the sidebar feedback\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tQueue_AI();\n\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\t\t\t  \n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::MP_Construction_Action -- Reproduce actions on the sidebar\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/26/2019 1:02PM - ST\n**************************************************************************************************/\nbool DLLExportClass::MP_Construction_Action(SidebarRequestEnum construction_action, uint64 player_id, int buildable_type, int buildable_id)\n{\t\t\n\t\t\n\t/*\n\t** \n\t** Based on SidebarClass::StripClass::SelectClass::Action\n\t** \n\t** Most of this code is validating that the game is in the correct state to be able to act on a sidebar icon\n\t** \n\t*/\n\t\t\t\n\tSidebarGlyphxClass *context_sidebar = DLLExportClass::Get_Current_Context_Sidebar();\n\t\n\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t/*\n\t\t** Each production slot in the column\n\t\t*/\n\t\tfor (int b=0 ; b < context_sidebar->Column[c].BuildableCount ; b++) {\n\t\t\tif (context_sidebar->Column[c].Buildables[b].BuildableID == buildable_id) {\n\t\t\t\tif (context_sidebar->Column[c].Buildables[b].BuildableType == buildable_type) {\n\t\t\t\t\t\n\t\t\t\t\tint genfactory = -1;\n\t\t\t\t\tswitch (buildable_type) {\n\t\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\t\tgenfactory = PlayerPtr->InfantryFactory;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\t\tgenfactory = PlayerPtr->UnitFactory;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\t\tgenfactory = PlayerPtr->AircraftFactory;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\t\t\t\tgenfactory = PlayerPtr->BuildingFactory;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tgenfactory = -1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tint fnumber = context_sidebar->Column[c].Buildables[b].Factory;\n\t\t\t\t\tint spc = 0;\n\t\t\t\t\tObjectTypeClass const * choice = NULL;\n\n\t\t\t\t\tif (buildable_type != RTTI_SPECIAL) {\n\t\t\t\t\t\tchoice  = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tspc = buildable_id;\n\t\t\t\t\t}\n\n\t\t\t\t\tFactoryClass * factory = NULL;\n\t\t\t\t\tif (fnumber != -1) {\n\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (spc == 0 && choice) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf there is already a factory attached to this strip but the player didn't click\n\t\t\t\t\t\t**\ton the icon that has the attached factory, then say that the factory is busy and\n\t\t\t\t\t\t**\tignore the click.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (fnumber == -1 && genfactory != -1) {\n\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); //Speak(VOX_NO_FACTORY); // \"Cannot Comply\"\n\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (factory) {\n\n\t\t\t\t\t\t\tswitch (construction_action)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_CANCEL_CONSTRUCTION:\n\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_CANCELED); // Speak(VOX_CANCELED);\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_HOLD_CONSTRUCTION:\n\t\t\t\t\t\t\t\tif (factory->Is_Building())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_SUSPENDED); // Speak(VOX_SUSPENDED);\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SUSPEND, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tIf this object is currently being built, then give a scold sound and text and then\n\t\t\t\t\t\t\t\t**\tbail.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); //Speak(VOX_NO_FACTORY); // \"Cannot Comply\"\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\t\t\t\t// TO_DO\n\t\t\t\t\t\t\t\t\t\t\t//Map.IsTargettingMode = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); //Speak(VOX_NO_FACTORY); // \"Cannot Comply\"\n\t\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\t\t//Speak(VOX_NO_FACTORY);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (construction_action == SIDEBAR_REQUEST_START_PLACEMENT) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (DLLExportClass::Legacy_Render_Enabled()) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tUnselect_All();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tFor objects that can leave the factory under their own\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tpower, queue this event and process through normal house\n\t\t\t\t\t\t\t\t\t\t\t\t\t**\tproduction channels.\n\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\t\t//OutList.Add(EventClass(EventClass::PLACE, otype, -1));\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t**\tThe factory must have been in a suspended state. Resume construction\n\t\t\t\t\t\t\t\t\t\t**\tnormally.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tif (construction_action == SIDEBAR_REQUEST_START_CONSTRUCTION) {\n\t\t\t\t\t\t\t\t\t\t\tif ((RTTIType)buildable_type == RTTI_INFANTRYTYPE) \n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_TRAINING); // Speak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_BUILDING); // Speak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, (RTTIType)buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tswitch (construction_action)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_CANCEL_CONSTRUCTION:\n\t\t\t\t\t\t\t\tcase SIDEBAR_REQUEST_HOLD_CONSTRUCTION:\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif ((RTTIType)buildable_type == RTTI_INFANTRYTYPE)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_TRAINING); // Speak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_BUILDING); // Speak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, (RTTIType)buildable_type, buildable_id));\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Execute immediately so we get the sidebar feedback\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tDLLExportClass::Glyphx_Queue_AI();\n\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\t\t\t  \n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Start_Placement -- Start placing a completed structure\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/29/2019 11:37AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Start_Placement(uint64 player_id, int buildable_type, int buildable_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tBuildingClass *building = Get_Pending_Placement_Object(player_id, buildable_type, buildable_id);\t\n\n\tif (building) {\n\t\t\n\t\tTechnoTypeClass const * tech = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\n\t\tif (tech) {\n\t\t\tBuildingTypeClass *building_type = (BuildingTypeClass*) tech;\n\t\t\t//short const *occupy_list = building_type->Get_Occupy_List(true);\n\n\t\t\tPlacementType[CurrentLocalPlayerIndex] = building_type;\n\t\t\tRecalculate_Placement_Distances();\n\n\t\t\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\t\t\treturn Construction_Action(SIDEBAR_REQUEST_START_PLACEMENT, player_id, buildable_type, buildable_id);\n\t\t\t}\n\t\t\treturn MP_Construction_Action(SIDEBAR_REQUEST_START_PLACEMENT, player_id, buildable_type, buildable_id);\n\t\t}\n\t}\n\treturn true;\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Cancel_Placement -- Cancel placing a completed structure\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/7/2019 10:52AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Cancel_Placement(uint64 player_id, int buildable_type, int buildable_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\n\tPlacementType[CurrentLocalPlayerIndex] = NULL;\n\n\tMap.PendingObjectPtr = 0;\n\tMap.PendingObject = 0;\n\tMap.PendingHouse = HOUSE_NONE;\n\tMap.IsTargettingMode = SPC_NONE;\n\tMap.Set_Cursor_Shape(0);\n\n\treturn true;\n}\n\t\t\t\n\n\n/**************************************************************************************************\n* DLLExportClass::Place -- Place a completed structure down\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/6/2019 11:51AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Place(uint64 player_id, int buildable_type, int buildable_id, short cell_x, short cell_y)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\t\n\tstatic const int _map_width_shift_bits = 7;\n\n\tBuildingClass *building = Get_Pending_Placement_Object(player_id, buildable_type, buildable_id);\t\n\n\tif (building) {\n\t\t\n\t\tTechnoTypeClass const * tech = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\n\t\tif (tech) {\n\t\t\tBuildingTypeClass *building_type = (BuildingTypeClass*) tech;\n\t\t\t//short const *occupy_list = building_type->Get_Occupy_List(true);\n\n\t\t\tPlacementType[CurrentLocalPlayerIndex] = building_type;\n\n\t\t\t/*\n\t\t\t** The cell coordinates passed in will be relative to the playable area that the client knows about\n\t\t\t*/\n\n\t\t\tint map_cell_x = Map.MapCellX;\n\t\t\tint map_cell_y = Map.MapCellY;\n\t\t\tint map_cell_width = Map.MapCellWidth;\n\t\t\tint map_cell_height = Map.MapCellHeight;\n\n\t\t\tif (map_cell_x > 0) {\n\t\t\t\tmap_cell_x--;\n\t\t\t\tmap_cell_width++;\n\t\t\t}\n\n\t\t\tif (map_cell_y > 0) {\n\t\t\t\tmap_cell_y--;\n\t\t\t\tmap_cell_height++;\n\t\t\t}\n\n\t\t\tCELL cell = (CELL) (map_cell_x + cell_x) + ( (map_cell_y + cell_y) << _map_width_shift_bits);\n\n\t\t\t/*\n\t\t\t** Call the place directly instead of queueing it, so we can evaluate the return code.\n\t\t\t*/\n\t\t\tif (PlayerPtr->Place_Object(building->What_Am_I(), cell + Map.ZoneOffset)) {\n\t\t\t\tPlacementType[CurrentLocalPlayerIndex] = NULL;\n\t\t\t}\t\n\t\t}\n\t}\n\treturn true;\n\n}\t\t\t  \n\n\n\n\nBuildingClass *DLLExportClass::Get_Pending_Placement_Object(uint64 player_id, int buildable_type, int buildable_id)\n{\t\t\n\t/*\n\t** \n\t** Based on SidebarClass::StripClass::SelectClass::Action\n\t** \n\t** \n\t*/\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\n\t\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t\t/*\n\t\t\t** Each production slot in the column\n\t\t\t*/\n\t\t\tfor (int b=0 ; b < Map.Column[c].BuildableCount ; b++) {\n\t\t\t\tif (Map.Column[c].Buildables[b].BuildableID == buildable_id) {\n\t\t\t\t\tif (Map.Column[c].Buildables[b].BuildableType == buildable_type) {\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tint genfactory = -1;\n\t\t\t\t\t\tswitch (buildable_type) {\n\t\t\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->InfantryFactory;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->UnitFactory;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->AircraftFactory;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->BuildingFactory;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tgenfactory = -1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tint fnumber = Map.Column[c].Buildables[b].Factory;\n\t\t\t\t\t\tint spc = 0;\n\t\t\t\t\t\tObjectTypeClass const * choice = NULL;\n\n\t\t\t\t\t\tif (buildable_type != RTTI_SPECIAL) {\n\t\t\t\t\t\t\tchoice  = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tspc = buildable_id;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tFactoryClass * factory = NULL;\n\t\t\t\t\t\tif (fnumber != -1) {\n\t\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (spc == 0 && choice) {\n\t\t\t\t\t\t\tif (fnumber == -1 && genfactory != -1) {\n\t\t\t\t\t\t\t\treturn(NULL);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (factory) {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (factory->Has_Completed()) {\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\t\t\t//Map.IsTargettingMode = true;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); // Speak(VOX_NO_FACTORY);\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn (BuildingClass*)pending;\n\t\t\t\t\t\t\t\t\t\t \t\t//PlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t\n\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\n\t\t\t\n\t\t\tSidebarGlyphxClass *context_sidebar = DLLExportClass::Get_Current_Context_Sidebar();\n\t\t\n\t\t\tfor (int c = 0 ; c < 2 ; c++) {\n\t\t\n\t\t\t\t/*\n\t\t\t\t** Each production slot in the column\n\t\t\t\t*/\n\t\t\t\tfor (int b=0 ; b < context_sidebar->Column[c].BuildableCount ; b++) {\n\t\t\t\t\tif (context_sidebar->Column[c].Buildables[b].BuildableID == buildable_id) {\n\t\t\t\t\t\tif (context_sidebar->Column[c].Buildables[b].BuildableType == buildable_type) {\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\tint genfactory = -1;\n\t\t\t\t\t\t\tswitch (buildable_type) {\n\t\t\t\t\t\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->InfantryFactory;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->UnitFactory;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->AircraftFactory;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\t\t\t\t\t\tgenfactory = PlayerPtr->BuildingFactory;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tgenfactory = -1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tint fnumber = context_sidebar->Column[c].Buildables[b].Factory;\n\t\t\t\t\t\t\tint spc = 0;\n\t\t\t\t\t\t\tObjectTypeClass const * choice = NULL;\n\n\t\t\t\t\t\t\tif (buildable_type != RTTI_SPECIAL) {\n\t\t\t\t\t\t\t\tchoice  = Fetch_Techno_Type((RTTIType)buildable_type, buildable_id);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tspc = buildable_id;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tFactoryClass * factory = NULL;\n\t\t\t\t\t\t\tif (fnumber != -1) {\n\t\t\t\t\t\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (spc == 0 && choice) {\n\t\t\t\t\t\t\t\tif (fnumber == -1 && genfactory != -1) {\n\t\t\t\t\t\t\t\t\treturn(NULL);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (factory) {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (factory->Has_Completed()) {\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\t\t\t\t//Map.IsTargettingMode = true;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, buildable_type, buildable_id));\n\t\t\t\t\t\t\t\t\t\t\t\tOn_Speech(PlayerPtr, VOX_NO_FACTORY); // Speak(VOX_NO_FACTORY);\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn (BuildingClass*)pending;\n\t\t\t\t\t\t\t\t\t\t\t \t\t//PlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\t\n\treturn NULL;\n}\t\t\t  \n\n/**************************************************************************************************\n* DLLExportClass::Place_Super_Weapon\n*\n* History:\n**************************************************************************************************/\nbool DLLExportClass::Place_Super_Weapon(uint64 player_id, int buildable_type, int buildable_id, int x, int y)\n{\n\tif (buildable_type != RTTI_SPECIAL)\n\t{\n\t\treturn false;\n\t}\n\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tSpecialWeaponType weapon_type = (SpecialWeaponType)buildable_id;\n\n\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, weapon_type, cell));\n\n\treturn true;\n}\n\n/**************************************************************************************************\n* DLLExportClass::Create_Control_Group\n*\n* History:\n**************************************************************************************************/\nbool DLLExportClass::Create_Control_Group(unsigned char control_group_index)\n{\n\tHandle_Team(control_group_index, 2);\n\n\treturn true;\n}\n\n/**************************************************************************************************\n* DLLExportClass::Add_To_Control_Group\n*\n* History:\n**************************************************************************************************/\nbool DLLExportClass::Add_To_Control_Group(unsigned char control_group_index)\n{\n\tHandle_Team(control_group_index, 1);\n\n\treturn true;\n}\n\n/**************************************************************************************************\n* DLLExportClass::Toggle_Control_Group_Selection\n*\n* History:\n**************************************************************************************************/\nbool DLLExportClass::Toggle_Control_Group_Selection(unsigned char control_group_index)\n{\n\tHandle_Team(control_group_index, 0);\n\n\treturn true;\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Shroud_State -- Get a snapshot of the shroud for the given player\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/12/2019 3:44PM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Shroud_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\t\n\t/*\n\t** Apply mobile gap generators\n\t*/\n\tstatic unsigned int _shroud_bits[UNIT_MAX];\n\n\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj->Class->IsGapper && obj->IsActive && obj->Strength) {\n\t\t\t\tif (!obj->House->Is_Ally(PlayerPtr)) {\n\t\t\t\t\t_shroud_bits[index] = obj->Apply_Temporary_Jamming_Shroud(PlayerPtr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCNCShroudStruct *shroud = (CNCShroudStruct*) buffer_in;\n\t\n\tunsigned int memory_needed = sizeof(*shroud) + 256;\t\t// Base amount needed. Will need more depending on how many entries there are\n\n\tint entry_index = 0;\n\n\t/*\n\t**\n\t**  Based loosely on DisplayClass::Redraw_Icons\n\t**\n\t**\n\t*/\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_HEIGHT) {\n\t\tmap_cell_height++;\n\t}\n\n\tfor (int y = 0; y < map_cell_height; y++) {\n\t\tfor (int x = 0; x < map_cell_width; x++) {\n\t\t\tCELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);\n\t\t\tCOORDINATE coord = Cell_Coord(cell) & 0xFF00FF00L;\n\n\t\t\tmemory_needed += sizeof(CNCShroudEntryStruct);\n\t\t\tif (memory_needed >= buffer_size) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tint xpixel;\n\t\t\tint ypixel;\n\n\t\t\tMap.Coord_To_Pixel(coord, xpixel, ypixel);\n\n\t\t\tCellClass * cellptr = &Map[Coord_Cell(coord)];\n\n\t\t\tCNCShroudEntryStruct &shroud_entry = shroud->Entries[entry_index];\n\n\t\t\tshroud_entry.IsVisible = cellptr->Is_Visible(PlayerPtr);\n\t\t\tshroud_entry.IsMapped = cellptr->Is_Mapped(PlayerPtr);\n\t\t\tshroud_entry.IsJamming = cellptr->Is_Jamming(PlayerPtr);\n\t\t\t//shroud_entry.IsVisible = cellptr->IsVisible;\n\t\t\t//shroud_entry.IsMapped = cellptr->IsMapped;\n\t\t\tshroud_entry.ShadowIndex = -1;\n\n\t\t\tif (shroud_entry.IsMapped) {\n\t\t\t\tif (!shroud_entry.IsVisible) {\n\t\t\t\t\tshroud_entry.ShadowIndex = (char)Map.Cell_Shadow(cell, PlayerPtr);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tentry_index++;\n\t\t}\n\t}\n\n\tshroud->Count = entry_index;\n\n\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj->Class->IsGapper && obj->IsActive && obj->Strength) {\n\t\t\t\tif (!obj->House->Is_Ally(PlayerPtr)) {\n\t\t\t\t\tobj->Unapply_Temporary_Jamming_Shroud(PlayerPtr, _shroud_bits[index]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn true;\n}\t\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Occupier_State -- Get the occupier state for this player\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 10/25/2019 - SKY\n**************************************************************************************************/\nbool DLLExportClass::Get_Occupier_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\tUNREFERENCED_PARAMETER(player_id);\n\n\tCNCOccupierHeaderStruct* occupiers = (CNCOccupierHeaderStruct*)buffer_in;\n\tCNCOccupierEntryHeaderStruct* entry = reinterpret_cast<CNCOccupierEntryHeaderStruct*>(occupiers + 1U);\n\toccupiers->Count = 0;\n\n\tunsigned int memory_needed = sizeof(CNCOccupierHeaderStruct);\n\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_HEIGHT) {\n\t\tmap_cell_height++;\n\t}\n\n\tfor (int y = 0; y < map_cell_height; y++) {\n\t\tfor (int x = 0; x < map_cell_width; x++, occupiers->Count++) {\n\t\t\tCELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);\n\t\t\tCellClass * cellptr = &Map[cell];\n\n\t\t\tint occupier_count = 0;\n\t\t\tObjectClass* optr = cellptr->Cell_Occupier();\n\t\t\twhile (optr != NULL) {\n\t\t\t\toccupier_count++;\n\t\t\t\toptr = optr->Next;\n\t\t\t}\n\n\t\t\tmemory_needed += sizeof(CNCOccupierEntryHeaderStruct) + (sizeof(CNCOccupierObjectStruct) * occupier_count);\n\t\t\tif (memory_needed >= buffer_size) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tCNCOccupierObjectStruct* occupier = reinterpret_cast<CNCOccupierObjectStruct*>(entry + 1U);\n\t\t\tentry->Count = 0;\n\n\t\t\toptr = cellptr->Cell_Occupier();\n\t\t\tfor (int i = 0; i < occupier_count; i++, occupier++, entry->Count++) {\n\t\t\t\tCNCObjectStruct object;\n\t\t\t\tConvert_Type(optr, object);\n\t\t\t\toccupier->Type = object.Type;\n\t\t\t\toccupier->ID = object.ID;\n\t\t\t\toptr = optr->Next;\n\t\t\t}\n\n\t\t\tentry = reinterpret_cast<CNCOccupierEntryHeaderStruct*>(occupier + 1U);\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Player_Info_State -- Get the multiplayer info for this player\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/22/2019 10:33AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Player_Info_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn false;\n\t}\n\t\n\tCNCPlayerInfoStruct *player_info = (CNCPlayerInfoStruct*) buffer_in;\n\t\n\tunsigned int memory_needed = sizeof(*player_info) + 32;  // A little extra for no reason\n\n\tif (memory_needed >= buffer_size) {\n\t\treturn false;\n\t}\n\t\n\tplayer_info->GlyphxPlayerID = 0;\n\n\tif (PlayerPtr == NULL) {\n\t\treturn false;;\n\t}\n\n\tif (Session.Players.Count() > CurrentLocalPlayerIndex) {\n\t\tstrncpy(&player_info->Name[0], Session.Players[CurrentLocalPlayerIndex]->Name, MPLAYER_NAME_MAX);\n\t}\n\t\n\tplayer_info->Name[MPLAYER_NAME_MAX - 1] = 0;\t\t\t// Make sure it's terminated\n\tplayer_info->House = PlayerPtr->Class->House;\n\tplayer_info->AllyFlags = PlayerPtr->Get_Ally_Flags();\n\t\n\tif (Session.Players.Count() > CurrentLocalPlayerIndex) {\n\t\tplayer_info->ColorIndex = Session.Players[CurrentLocalPlayerIndex]->Player.Color;\n\t}\telse {\n\t\tplayer_info->ColorIndex = (PlayerPtr->Class->House == HOUSE_USSR) ? 2 : 1; // Fudge to a sensible color in campaign; 2 = red, 1 = blue\n\t}\n\t\n\tplayer_info->GlyphxPlayerID = player_id;\n\tplayer_info->HomeCellX = Cell_X(MultiplayerStartPositions[CurrentLocalPlayerIndex]);\n\tplayer_info->HomeCellY = Cell_Y(MultiplayerStartPositions[CurrentLocalPlayerIndex]);\n\tplayer_info->IsDefeated = PlayerPtr->IsDefeated;\n\n\t// Can see other players' power if ally (except for the player themself) or spying on a power plant\n\t// Can see other players' money if spying on a resource building\n\tplayer_info->SpiedPowerFlags = 0U;\n\tplayer_info->SpiedMoneyFlags = 0U;\n\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\tHouseClass* house = Houses.Ptr(i);\n\t\tif ((house != nullptr) && house->IsActive && (house != PlayerPtr) && house->Is_Ally(PlayerPtr)) {\n\t\t\tplayer_info->SpiedPowerFlags |= 1U << house->Class->House;\n\t\t}\n\t}\n\tfor (int i = 0; i < Buildings.Count(); ++i) {\n\t\tBuildingClass* building = Buildings.Ptr(i);\n\t\tif ((building != nullptr) && building->IsActive && (building->Spied_By() & (1U << PlayerPtr->Class->House))) {\n\t\t\tif ((*building == STRUCT_POWER) || (*building == STRUCT_ADVANCED_POWER)) {\n\t\t\t\tplayer_info->SpiedPowerFlags |= 1U << building->House->Class->House;\n\t\t\t} else if ((*building == STRUCT_REFINERY) || (*building == STRUCT_STORAGE)) {\n\t\t\t\tplayer_info->SpiedMoneyFlags |= 1U << building->House->Class->House;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Populate spied data\n\tfor (char house = 0; house < MAX_HOUSES; ++house) {\n\t\tHouseClass* hptr = HouseClass::As_Pointer((HousesType)house);\n\t\tif ((hptr != nullptr) && hptr->IsActive) {\n\t\t\tif (player_info->SpiedPowerFlags & (1U << house)) {\n\t\t\t\tplayer_info->SpiedInfo[house].Power = hptr->Power;\n\t\t\t\tplayer_info->SpiedInfo[house].Drain = hptr->Drain;\n\t\t\t}\n\t\t\tif (player_info->SpiedMoneyFlags & (1U << house)) {\n\t\t\t\tplayer_info->SpiedInfo[house].Money = hptr->Available_Money();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Populate selection info\n\tif (CurrentObject.Count() > 0) {\n\t\tCNCObjectStruct object;\n\t\tConvert_Type(CurrentObject[0], object);\n\t\tplayer_info->SelectedID = object.ID;\n\t\tplayer_info->SelectedType = object.Type;\n\n\t\tconst int left = Map.MapCellX;\n\t\tconst int right = Map.MapCellX + Map.MapCellWidth - 1;\n\t\tconst int top = Map.MapCellY;\n\t\tconst int bottom = Map.MapCellY + Map.MapCellHeight - 1;\n\n\t\t// Use first object with a weapon, or first object if none\n\t\tObjectClass* action_object = nullptr;\n\t\tfor (int i = 0; i < CurrentObject.Count(); ++i) {\n\t\t\tObjectClass* object = CurrentObject[i];\n\t\t\tif (object->Is_Techno()) {\n\t\t\t\tTechnoClass* techno = (TechnoClass*)object;\n\t\t\t\tif (techno->Techno_Type_Class()->PrimaryWeapon != NULL || techno->Techno_Type_Class()->SecondaryWeapon != NULL) {\n\t\t\t\t\taction_object = object;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (action_object == nullptr) {\n\t\t\taction_object = CurrentObject[0];\n\t\t}\n\n\t\tint index = 0;\n\t\tfor (int y = top; y <= bottom; ++y) {\n\t\t\tfor (int x = left; x <= right; ++x, ++index) {\n\t\t\t\tConvert_Action_Type(action_object->What_Action(XY_Cell(x, y)), (CurrentObject.Count() == 1) ? action_object : NULL, As_Target(XY_Cell(x, y)), player_info->ActionWithSelected[index]);\n\t\t\t}\n\t\t}\n\n\t\tplayer_info->ActionWithSelectedCount = Map.MapCellWidth * Map.MapCellHeight;\n\t}\n\telse {\n\t\tplayer_info->SelectedID = -1;\n\t\tplayer_info->SelectedType = UNKNOWN;\n\t\tplayer_info->ActionWithSelectedCount = 0U;\n\t}\n\n\t// Screen shake\n\tplayer_info->ScreenShake = PlayerPtr->ScreenShakeTime;\n\n\t// Radar jammed\n\tplayer_info->IsRadarJammed = Map.Get_Jammed(PlayerPtr);\n\n\treturn true;\n};\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Dynamic_Map_State -- Get a snapshot of the smudges and overlays on the terrain\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/8/2019 10:45AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Get_Dynamic_Map_State(uint64 player_id, unsigned char *buffer_in, unsigned int buffer_size)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tplayer_id;\n\n\tstatic int _call_count = 0;\n\n\tCNCDynamicMapStruct *dynamic_map = (CNCDynamicMapStruct*) buffer_in;\n\t\n\tunsigned int memory_needed = sizeof(*dynamic_map) + 256;\t\t// Base amount needed. Will need more depending on how many entries there are\n\n\tint entry_index = 0;\n\n\t/*\n\t** \n\t**  Based loosely on DisplayClass::Redraw_Icons\n\t** \n\t** \n\t*/\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_height++;\n\t}\n\n\tint cell_index = 0;\n\n\tbool debug_output = false;\n\t//if (_call_count == 20) {\n\t\t//debug_output = true;\n\t//}\n\t\t\t\t\n\t// Need to ignore view constraints for dynamic map updates, so the radar map\n\t// has the latest tiberium state for cells outside the tactical view\n\tDLLExportClass::Adjust_Internal_View(true);\n\n\tfor (int y = 0 ; y < map_cell_height ; y++) {\n\t\tfor (int x = 0 ; x < map_cell_width ; x++) {\n\t\t\tCELL cell = XY_Cell(map_cell_x+x, map_cell_y+y);\n\t\t\tCOORDINATE coord = Cell_Coord(cell) & 0xFF00FF00L;\n\n\t\t\tmemory_needed += sizeof(CNCDynamicMapEntryStruct) * 2;\n\t\t\tif (memory_needed >= buffer_size) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tOnly cells flagged to be redraw are examined.\n\t\t\t*/\n\t\t\t//if (In_View(cell) && Is_Cell_Flagged(cell)) {\n\t\t\t\tint xpixel;\n\t\t\t\tint ypixel;\n\n\t\t\t\tif (Map.Coord_To_Pixel(coord, xpixel, ypixel)) {\n\t\t\t\t\tCellClass * cellptr = &Map[Coord_Cell(coord)];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf there is a portion of the underlying icon that could be visible,\n\t\t\t\t\t**\tthen draw it.  Also draw the cell if the shroud is off.\n\t\t\t\t\t*/\n\t\t\t\t\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER || cellptr->IsMapped || Debug_Unshroud) {\n\t\t\t\t\t\tCell_Class_Draw_It(dynamic_map, entry_index, cellptr, xpixel, ypixel, debug_output);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf any cell is not fully mapped, then flag it so that the shadow drawing\n\t\t\t\t\t**\tprocess will occur.  Only draw the shadow if Debug_Unshroud is false.\n\t\t\t\t\t*/\n\t\t\t\t\t//if (!cellptr->IsMapped && !Debug_Unshroud) {\n\t\t\t\t\t//\tIsShadowPresent = true;\n\t\t\t\t\t//}\n\t\t\t\t}\n\t\t\t//}\n\t\t}\n\t}\n\n\tif (entry_index) {\n\t\t_call_count++;\n\t}\n\n\tdynamic_map->Count = entry_index;\n\n\tdynamic_map->VortexActive = ChronalVortex.Is_Active();\n\tdynamic_map->VortexX = Coord_X(ChronalVortex.Get_Position());\n\tdynamic_map->VortexY = Coord_Y(ChronalVortex.Get_Position());\n\tdynamic_map->VortexWidth = Pixel_To_Lepton(64);\n\tdynamic_map->VortexHeight = Pixel_To_Lepton(64);\n\n\treturn true;\n}\n\n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Cell_Class_Draw_It -- Go through the motions of drawing a cell to get the smudge and overlay info\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 2/8/2019 11:09AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Cell_Class_Draw_It(CNCDynamicMapStruct *dynamic_map, int &entry_index, CellClass *cell_ptr, int xpixel, int ypixel, bool debug_output)\n{\n\t/*\n\t** \n\t**  Based on CellClass::Draw_It and SmudgeTypeClass::Draw_It\n\t** \n\t** \n\t*/\n\n\tCELL\tcell = cell_ptr->Cell_Number();\n\n\t/*\n\t**\tRedraw any smudge.\n\t*/\n\tif (cell_ptr->Smudge != SMUDGE_NONE) {\n\t\t//SmudgeTypeClass::As_Reference(Smudge).Draw_It(x, y, SmudgeData);\n\t\t\n\t\tconst SmudgeTypeClass &smudge_type = SmudgeTypeClass::As_Reference(cell_ptr->Smudge);\n\n\t\tif (smudge_type.Get_Image_Data() != NULL) {\n\nif (debug_output) {\n\tIsTheaterShape = true;\n\tDebug_Write_Shape_Type(&smudge_type, 0);\n\tIsTheaterShape = false;\n}\n\t\t\t\n\t\t\tCNCDynamicMapEntryStruct &smudge_entry = dynamic_map->Entries[entry_index++];\n\n\t\t\tstrncpy(smudge_entry.AssetName, smudge_type.IniName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\tsmudge_entry.Type = (short) cell_ptr->Smudge;\n\t\t\tsmudge_entry.Owner = (char)cell_ptr->Owner;\n\t\t\tsmudge_entry.DrawFlags = SHAPE_WIN_REL;\t\t\t// Looks like smudges are drawn top left\n\t\t\tsmudge_entry.PositionX = xpixel;\n\t\t\tsmudge_entry.PositionY = ypixel;\n\t\t\tsmudge_entry.Width = Get_Build_Frame_Width(smudge_type.Get_Image_Data());\n\t\t\tsmudge_entry.Height = Get_Build_Frame_Height(smudge_type.Get_Image_Data());\n\t\t\tsmudge_entry.CellX = Cell_X(cell);\n\t\t\tsmudge_entry.CellY = Cell_Y(cell);\n\t\t\tsmudge_entry.ShapeIndex = cell_ptr->SmudgeData;\n\t\t\tsmudge_entry.IsSmudge = true;\n\t\t\tsmudge_entry.IsOverlay = false;\n\t\t\tsmudge_entry.IsResource = false;\n\t\t\tsmudge_entry.IsSellable = false;\n\t\t\tsmudge_entry.IsTheaterShape = true;\t\t// Smudges are always theater-specific\n\t\t\tsmudge_entry.IsFlag = false;\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the overlay object.\n\t*/\n\tif (cell_ptr->Overlay != OVERLAY_NONE) {\n\t\t//OverlayTypeClass const & otype = OverlayTypeClass::As_Reference(Overlay);\n\t\t//IsTheaterShape = (bool)otype.IsTheater;\n\t\t//CC_Draw_Shape(otype.Get_Image_Data(), OverlayData, (x+(CELL_PIXEL_W>>1)), (y+(CELL_PIXEL_H>>1)), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, Map.UnitShadow);\n\t\t//IsTheaterShape = false;\n\t\t\n\t\tconst OverlayTypeClass &overlay_type = OverlayTypeClass::As_Reference(cell_ptr->Overlay);\n\n\t\tif (overlay_type.Get_Image_Data() != NULL) {\n\t\t\t\n\t\t\tCNCDynamicMapEntryStruct &overlay_entry = dynamic_map->Entries[entry_index++];\n\n\nif (debug_output) {\n\tIsTheaterShape = (bool)overlay_type.IsTheater;\n\tDebug_Write_Shape_Type(&overlay_type, 0);\n\tIsTheaterShape = false;\n}\n\n\t\t\tstrncpy(overlay_entry.AssetName, overlay_type.IniName, CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\toverlay_entry.Type = (short)cell_ptr->Overlay;\n\t\t\toverlay_entry.Owner = (char)cell_ptr->Owner;\n\t\t\toverlay_entry.DrawFlags = SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST;\t\t// Looks like overlays are drawn centered and translucent\n\t\t\toverlay_entry.PositionX = xpixel + (CELL_PIXEL_W>>1);\n\t\t\toverlay_entry.PositionY = ypixel + (CELL_PIXEL_H>>1);\n\t\t\toverlay_entry.Width = Get_Build_Frame_Width(overlay_type.Get_Image_Data());\n\t\t\toverlay_entry.Height = Get_Build_Frame_Height(overlay_type.Get_Image_Data());\n\t\t\toverlay_entry.CellX = Cell_X(cell);\n\t\t\toverlay_entry.CellY = Cell_Y(cell);\n\t\t\toverlay_entry.ShapeIndex = cell_ptr->OverlayData;\n\t\t\toverlay_entry.IsSmudge = false;\n\t\t\toverlay_entry.IsOverlay = true;\n\t\t\toverlay_entry.IsResource = overlay_entry.Type >= OVERLAY_GOLD1 && overlay_entry.Type <= OVERLAY_GEMS4;\n\t\t\toverlay_entry.IsSellable = (overlay_entry.Type >= OVERLAY_SANDBAG_WALL && overlay_entry.Type <= OVERLAY_WOOD_WALL) || overlay_entry.Type == OVERLAY_FENCE;\n\t\t\toverlay_entry.IsTheaterShape = (bool)overlay_type.IsTheater;\n\t\t\toverlay_entry.IsFlag = false;\n\t\t}\n\t}\n\n\n\tif (cell_ptr->IsFlagged) {\n\n\t\tconst void* image_data = MFCD::Retrieve(\"FLAGFLY.SHP\");\n\t\tif (image_data != NULL) {\n\n\t\t\tCNCDynamicMapEntryStruct &flag_entry = dynamic_map->Entries[entry_index++];\n\n\t\t\tstrncpy(flag_entry.AssetName, \"FLAGFLY\", CNC_OBJECT_ASSET_NAME_LENGTH);\n\t\t\tflag_entry.AssetName[CNC_OBJECT_ASSET_NAME_LENGTH - 1] = 0;\n\t\t\tflag_entry.Type = -1;\n\t\t\tflag_entry.Owner = cell_ptr->Owner;\n\t\t\tflag_entry.DrawFlags = SHAPE_CENTER|SHAPE_GHOST|SHAPE_FADING;\n\t\t\tflag_entry.PositionX = xpixel + (ICON_PIXEL_W / 2);\n\t\t\tflag_entry.PositionY = ypixel + (ICON_PIXEL_H / 2);\n\t\t\tflag_entry.Width = Get_Build_Frame_Width(image_data);\n\t\t\tflag_entry.Height = Get_Build_Frame_Height(image_data);\n\t\t\tflag_entry.CellX = Cell_X(cell);\n\t\t\tflag_entry.CellY = Cell_Y(cell);\n\t\t\tflag_entry.ShapeIndex = Frame % 14;\n\t\t\tflag_entry.IsSmudge = false;\n\t\t\tflag_entry.IsOverlay = false;\n\t\t\tflag_entry.IsResource = false;\n\t\t\tflag_entry.IsSellable = false;\n\t\t\tflag_entry.IsTheaterShape = false;\n\t\t\tflag_entry.IsFlag = true;\n\t\t}\n\n\t}\n\t\t  \n}\t\t\t  \n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Glyphx_Queue_AI -- Special queue processing for Glyphx multiplayer mode\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/12/2019 10:52AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Glyphx_Queue_AI(void)\n{\n\t\n\t//------------------------------------------------------------------------\n\t//\tMove events from the OutList (events generated by this player) into the\n\t//\tDoList (the list of events to execute).\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count) {\n\t\tOutList.First().IsExecuted = false;\n\t\tif (!DoList.Add(OutList.First())) {\n\t\t\t;\n\t\t}\n\t\tOutList.Next();\n\t}\n\n\t/*\n\t** Based on Execute_DoList in queue.cpp\n\t** \n\t** The events have the ID of the player encoded in them, so no special per-player processing should be needed.\n\t** When the event is created, the 'local player' is assumed to be the originator of the event, so PlayerPtr will need\n\t** to be swapped out to represent the real originating player prior to any events being created as a result of GlyphX input\n\t** \n\t** ST - 3/12/2019 10:51AM\n\t*/\n\n\tfor (int i = 0; i < MULTIPLAYER_COUNT; i++) {\n\n\t\tHousesType house;\n\t\tHouseClass *housep;\n\n\t\thouse = Session.Players[i]->Player.ID;\n\t\t\n\t\thousep= HouseClass::As_Pointer (house);\n\n\t\t//.....................................................................\n\t\t// If for some reason this house doesn't exist, skip it.\n\t\t// Also, if this house has exited the game, skip it.  (The user can\n\t\t// generate events after he exits, because the exit event is scheduled\n\t\t// at least FrameSendRate*3 frames ahead.  If one system gets these\n\t\t// packets & another system doesn't, they'll go out of sync because\n\t\t// they aren't checking the CommandCount for that house, since that\n\t\t// house isn't connected any more.)\n\t\t//.....................................................................\n\t\tif (!housep){\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!housep->IsHuman){\n\t\t\tcontinue;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tLoop through all events\n\t\t//.....................................................................\n\t\tfor (int j = 0; j < DoList.Count; j++) {\n\n\t\t\tif (!DoList[j].IsExecuted && (unsigned)Frame >= DoList[j].Frame) {\n\t\t\t\tDoList[j].Execute();\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tMark this event as executed.\n\t\t\t\t//...............................................................\n\t\t\t\tDoList[j].IsExecuted = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\twhile (DoList.Count) {\n\n\t\t//.....................................................................\n\t\t//\tDiscard events that have been executed, OR it's too late to execute.\n\t\t//\t(This happens if another player exits the game; he'll leave FRAMEINFO\n\t\t//\tevents lying around in my queue.  They won't have been \"executed\",\n\t\t//\tbecause his IPX connection was destroyed.)\n\t\t//.....................................................................\n\t\tif ( (DoList.First().IsExecuted) || ((unsigned)Frame > DoList.First().Frame) ) {\n\t\t\tDoList.Next();\n\t\t}\n\t\telse {\n\t\t\tbreak;\n\t\t}\n\t}\n\n}\n\nCarryoverClass Test_CC(CarryoverObjectStruct* cptr)\n{\n\tCarryoverClass cc;\n\n\tcc.RTTI = (RTTIType)cptr->RTTI;\n\tcc.Type.Building = (StructType)cptr->Type; //This works regardless of what the RTTI-type and the enum type, because they're all enums. - LLL\n\tcc.Cell = (CELL)cptr->Cell;\n\tcc.House = (HousesType)cptr->House;\n\tcc.Strength = cptr->Strength;\n\n\treturn cc;\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Reset_Sidebars -- Init the multiplayer sidebars\n*\n*\n*\n* History: 11/8/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Store_Carryover_Objects()\n{\n\tif (EventCallback == NULL || Scen.IsToCarryOver == false) {\n\t\treturn;\n\t}\n\n\tCarryoverObjectStruct* carryover_list = 0;\n\tCarryoverObjectStruct* carryover_list_tail = 0;\n\n\t/*\n\t**\tRecord all objects, that are to be part of the carry over set, into the carry over list.\n\t*/\n\tfor (int building_index = 0; building_index < Buildings.Count(); building_index++) {\n\t\tBuildingClass * building = Buildings.Ptr(building_index);\n\n\t\tif (building && !building->IsInLimbo && building->Strength > 0) {\n\t\t\tCarryoverClass carryover = CarryoverClass(building);\n\t\t\tCarryoverObjectStruct* cptr = new CarryoverObjectStruct();\n\t\t\tif (cptr) {\n\t\t\t\tcptr->RTTI = carryover.RTTI;\n\t\t\t\tcptr->Type = (int)carryover.Type.Building;\n\t\t\t\tcptr->House = carryover.House;\n\t\t\t\tcptr->Cell = carryover.Cell;\n\t\t\t\tcptr->Strength = carryover.Strength;\n\n\t\t\t\tCarryoverClass cc = Test_CC(cptr);\n\t\t\t\tcc;\n\n\t\t\t\tif (!carryover_list_tail) {\n\t\t\t\t\tcarryover_list = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcarryover_list_tail->Next = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int unit_index = 0; unit_index < Units.Count(); unit_index++) {\n\t\tUnitClass * unit = Units.Ptr(unit_index);\n\n\t\tif (unit && !unit->IsInLimbo && unit->Strength > 0) {\n\t\t\tCarryoverClass carryover = CarryoverClass(unit);\n\t\t\tCarryoverObjectStruct* cptr = new CarryoverObjectStruct();\n\t\t\tif (cptr) {\n\t\t\t\tcptr->RTTI = carryover.RTTI;\n\t\t\t\tcptr->Type = (int)carryover.Type.Unit;\n\t\t\t\tcptr->House = carryover.House;\n\t\t\t\tcptr->Cell = carryover.Cell;\n\t\t\t\tcptr->Strength = carryover.Strength;\n\n\t\t\t\tCarryoverClass cc = Test_CC(cptr);\n\t\t\t\tcc;\n\n\t\t\t\tif (!carryover_list_tail) {\n\t\t\t\t\tcarryover_list = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcarryover_list_tail->Next = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int infantry_index = 0; infantry_index < Infantry.Count(); infantry_index++) {\n\t\tInfantryClass * infantry = Infantry.Ptr(infantry_index);\n\n\t\tif (infantry && !infantry->IsInLimbo && infantry->Strength > 0) {\n\t\t\tCarryoverClass carryover = CarryoverClass(infantry);\n\t\t\tCarryoverObjectStruct* cptr = new CarryoverObjectStruct();\n\t\t\tif (cptr) {\n\t\t\t\tcptr->RTTI = carryover.RTTI;\n\t\t\t\tcptr->Type = (int)carryover.Type.Building;\n\t\t\t\tcptr->House = carryover.House;\n\t\t\t\tcptr->Cell = carryover.Cell;\n\t\t\t\tcptr->Strength = carryover.Strength;\n\n\t\t\t\tCarryoverClass cc = Test_CC(cptr);\n\t\t\t\tcc;\n\n\t\t\t\tif (!carryover_list_tail) {\n\t\t\t\t\tcarryover_list = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcarryover_list_tail->Next = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int vessel_index = 0; vessel_index < Vessels.Count(); vessel_index++) {\n\t\tVesselClass * vessel = Vessels.Ptr(vessel_index);\n\n\t\tif (vessel && !vessel->IsInLimbo && vessel->Strength > 0) {\n\t\t\tCarryoverClass carryover = CarryoverClass(vessel);\n\t\t\tCarryoverObjectStruct* cptr = new CarryoverObjectStruct();\n\t\t\tif (cptr) {\n\t\t\t\tcptr->RTTI = carryover.RTTI;\n\t\t\t\tcptr->Type = (int)carryover.Type.Building;\n\t\t\t\tcptr->House = carryover.House;\n\t\t\t\tcptr->Cell = carryover.Cell;\n\t\t\t\tcptr->Strength = carryover.Strength;\n\n\t\t\t\tCarryoverClass cc = Test_CC(cptr);\n\t\t\t\tcc;\n\n\t\t\t\tif (!carryover_list_tail) {\n\t\t\t\t\tcarryover_list = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcarryover_list_tail->Next = cptr;\n\t\t\t\t\tcarryover_list_tail = cptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//Make & Send Event\n\tEventCallbackStruct event;\n\tevent.EventType = CALLBACK_EVENT_STORE_CARRYOVER_OBJECTS;\n\tevent.CarryoverObjects.CarryoverList = carryover_list;\n\tEventCallback(event);\n\n\t//Delete the list\n\twhile (carryover_list) {\n\t\tCarryoverObjectStruct* cptr = (CarryoverObjectStruct*)carryover_list->Next;\n\t\tdelete carryover_list;\n\t\tcarryover_list = cptr;\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Reset_Sidebars -- Init the multiplayer sidebars\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/14/2019 3:10PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Reset_Sidebars(void)\n{\n\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\tif (i >= Session.Players.Count()) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (Session.Players[i] == NULL) {\n\t\t\tcontinue;\n\t\t}\n\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tMultiplayerSidebars[i].Init_Clear(player_ptr);\n\t}\n}\t\t\t  \n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Set_Player_Context -- Switch the C&C local player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/14/2019 3:20PM - ST\n**************************************************************************************************/\nbool DLLExportClass::Set_Player_Context(uint64 glyphx_player_id, bool force)\n{\n\t/*\n\t** Context never needs to change in single player\n\t*/\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tif (PlayerPtr) {\n\t\t\tCurrentObject.Set_Active_Context(PlayerPtr->Class->House);\n\t\t}\n\t\treturn true;\n\t}\n\t\t \n\t/*\n\t** C&C relies a lot on PlayerPtr, which is a pointer to the 'local' player's house. Historically, in a peer-to-peer \n\t** multiplayer game, each player's PlayerPtr pointed to their own local player.\n\t** \n\t** Since much of the IO logic depends on PlayerPtr being the player performing the action, we need to set PlayerPtr\n\t** correctly depending on which player generated input or needs output\n\t*/\n\n\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\tif (GlyphxPlayerIDs[i] == glyphx_player_id) {\n\t\t\t\n\t\t\tif (!force && i == CurrentLocalPlayerIndex) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tPlayerPtr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tCurrentObject.Set_Active_Context(PlayerPtr->Class->House);\n\t\t\tCurrentLocalPlayerIndex = i;\n\t\t\t\n\t\t\tRefresh_Player_Control_Flags();\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Reset_Player_Context -- Clear out old player context data\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/16/2019 10:36AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Reset_Player_Context(void)\n{\n\tCurrentLocalPlayerIndex = 0;\n\tCurrentObject.Clear_All();\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Refresh_Player_Control_Flags -- Set the IsPlayerControl flags so that the player\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  in context has IsPlayerControl\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/16/2019 10:36AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Refresh_Player_Control_Flags(void)\n{\n\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\n\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\n\t\tif (player_ptr) {\n\t\t\t  \n\t\t\tif (i == CurrentLocalPlayerIndex && player_ptr->IsHuman) {\n\t\t\t\tplayer_ptr->IsPlayerControl = true;\n\t\t\t} else {\n\t\t\t\tplayer_ptr->IsPlayerControl = false;\n\t\t\t}\n\t\t}\n\t}\n}\t\t\t  \n\n\n/**************************************************************************************************\n* Logic_Switch_Player_Context -- Called when the internal game locic needs to switch player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/17/2019 9:45AM - ST\n**************************************************************************************************/\nvoid Logic_Switch_Player_Context(ObjectClass *object)\n{\n\tDLLExportClass::Logic_Switch_Player_Context(object);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Logic_Switch_Player_Context -- Called when the internal game locic needs to switch player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/17/2019 9:45AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Logic_Switch_Player_Context(ObjectClass *object)\n{\n\tif (object == NULL) {\n\t\treturn;\n\t}\n\t \n\t/*\n\t** If it's not a techno, it can't be owned.\n\t*/\n\tif (!object->Is_Techno()) {\n\t\treturn;\n\t}\n\t\t\n\tTechnoClass *tech = static_cast<TechnoClass*>(object);\n\n\t//HousesType house = tech->House->Class->House;\n\tDLLExportClass::Logic_Switch_Player_Context(tech->House);\n}\t\n\t\t\n\t\t\n\t\t\n/**************************************************************************************************\n* Logic_Switch_Player_Context -- Called when the internal game locic needs to switch player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/17/2019 9:45AM - ST\n**************************************************************************************************/\nvoid Logic_Switch_Player_Context(HouseClass *object)\n{\n\tDLLExportClass::Logic_Switch_Player_Context(object);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Logic_Switch_Player_Context -- Called when the internal game locic needs to switch player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/17/2019 9:45AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Logic_Switch_Player_Context(HouseClass *house)\n{\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tCurrentObject.Set_Active_Context(PlayerPtr->Class->House);\n\t\treturn;\n\t}\n\n\tif (house == NULL) {\n\t\treturn;\n\t}\n\t \n\t/*\n\t** C&C relies a lot on PlayerPtr, which is a pointer to the 'local' player's house. Historically, in a peer-to-peer \n\t** multiplayer game, each player's PlayerPtr pointed to their own local player.\n\t** \n\t** Since much of the IO logic depends on PlayerPtr being the player performing the action, we need to set PlayerPtr\n\t** correctly depending on which player generated input or needs output\n\t*/\n\n\tHousesType house_type = house->Class->House;\n\n\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\t\n\t\tif (house_type == Session.Players[i]->Player.ID) {\n\t\t\n\t\t\tif (i == CurrentLocalPlayerIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPlayerPtr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tCurrentObject.Set_Active_Context(PlayerPtr->Class->House);\n\t\t\tCurrentLocalPlayerIndex = i;\n\n\t\t\tRefresh_Player_Control_Flags();\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Calculate_Start_Positions -- Calculate the initial view positions for the players\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/16/2019 6/12/2019 3:00PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Calculate_Start_Positions(void)\n{\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\tMultiplayerStartPositions[0] = Scen.Views[0];\n\t\treturn;\n\t}\n\n\tHouseClass *player_ptr = PlayerPtr;\n\t\n\tScenarioInit++;\n\tCOORDINATE old_tac = Map.TacticalCoord;\n\tfor (int i=0 ; i< MULTIPLAYER_COUNT; i++) {\n\t\tPlayerPtr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\tif (PlayerPtr) {\n\t\t\tlong x, y;\n\t\t\tMap.Compute_Start_Pos(x, y);\n\t\t\tMultiplayerStartPositions[i] = XY_Cell(x, y);\n\t\t}\n\t}\n\tMap.TacticalCoord = old_tac;\n\tScenarioInit--;\n\n\tPlayerPtr = player_ptr;\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_GlyphX_Player_ID -- Get the external GlyphX player ID from the C&C house/player pointer\n*                                         Returns 0 in single player or if player ID isn't found\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/22/2019 6:23PM - ST\n**************************************************************************************************/\n__int64 DLLExportClass::Get_GlyphX_Player_ID(const HouseClass *house)\n{\n\t/*\n\t** C&C relies a lot on PlayerPtr, which is a pointer to the 'local' player's house. Historically, in a peer-to-peer \n\t** multiplayer game, each player's PlayerPtr pointed to their own local player.\n\t** \n\t** Since much of the IO logic depends on PlayerPtr being the player performing the action, we need to set PlayerPtr\n\t** correctly depending on which player generated input or needs output\n\t*/\n\t\n\tif (GAME_TO_PLAY == GAME_NORMAL) {\n\t\treturn 0;\n\t}\n\n\tif (house == NULL) {\n\t\treturn 0;\n\t}\n\t \n\tHousesType house_type = house->Class->House;\n\n\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\tif (house_type == Session.Players[i]->Player.ID) {\n\t\t\treturn GlyphxPlayerIDs[i];\n\t\t}\n\t}\n\n\t/*\n\t** Failure case.\n\t*/\n\treturn 0;\n}\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Adjust_Internal_View -- Set the internal tactical view to encompass the input coordinates\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/16/2019 3:00PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Adjust_Internal_View(bool force_ignore_view_constraints)\n{\n\t/*\n\t** When legacy rendering is disabled (especially in multiplayer) we can get input coordinates that\n\t** fall outside the engine's tactical view. In this case, we need to adjust the tactical view before the\n\t** input will behave as expected.\n\t*/\n\t\n\tif (!force_ignore_view_constraints && Legacy_Render_Enabled()) {\n\t\t/*\n\t\t** Render view should already be tracking the player's local view\n\t\t*/\n\t\tDisplayClass::IgnoreViewConstraints = false;\n\t\treturn;\n\t}\n\n\tDisplayClass::IgnoreViewConstraints = true;\n}\t\t\t  \n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Get_Current_Context_Sidebar -- Get the sidebar data for the current player context\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/14/2019 3:20PM - ST\n**************************************************************************************************/\nSidebarGlyphxClass *DLLExportClass::Get_Current_Context_Sidebar(HouseClass *player_ptr)\n{\n\tif (player_ptr) {\n\t\t\n\t\tfor (int i=0 ; i<MULTIPLAYER_COUNT ; i++) {\n\t\t\tif (player_ptr == HouseClass::As_Pointer(Session.Players[i]->Player.ID)) {\n\t\t\t\treturn &MultiplayerSidebars[i];\n\t\t\t}\n\t\t}\n\t}\n\treturn &MultiplayerSidebars[CurrentLocalPlayerIndex];\n}\t\t\t  \n\n\nSidebarGlyphxClass *Get_Current_Context_Sidebar(HouseClass *player_ptr)\n{\n\treturn DLLExportClass::Get_Current_Context_Sidebar(player_ptr);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Repair_Mode -- Starts the player's repair mode. All it does here is unselect all units.\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 5/1/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Repair_Mode(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tUnselect_All();\n}\n\n/**************************************************************************************************\n* DLLExportClass::Repair -- Repairs a specific building\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 5/1/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Repair(uint64 player_id, int object_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tTARGET target = Build_Target(RTTI_BUILDING, object_id);\n\tif (target != TARGET_NONE)\n\t{\n\t\tBuildingClass* building = As_Building(target);\n\t\tif (building) {\n\t\t\tif (!building->IsActive) {\n\t\t\t\tGlyphX_Debug_Print(\"DLLExportClass::Repair -- trying to repair a non-active building\");\n\t\t\t} else {\n\n\t\t\t\tif (building->Can_Repair() && building->House.Is_Valid() && building->House->Class->House == PlayerPtr->Class->House)\n\t\t\t\t{\n\t\t\t\t\tbuilding->Repair(-1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Sell_Mode -- Starts the player's sell mode. All it does here is unselect all units.\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 5/1/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Sell_Mode(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tUnselect_All();\n}\n\n/**************************************************************************************************\n* DLLExportClass::Sell -- Sell's a player's speceific building.\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 5/1/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Sell(uint64 player_id, int object_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tTARGET target = Build_Target(RTTI_BUILDING, object_id);\n\tif (target != TARGET_NONE)\n\t{\n\t\tBuildingClass* building = As_Building(target);\n\t\tif (building) {\n\t\t\tif (!building->IsActive) {\n\t\t\t\tGlyphX_Debug_Print(\"DLLExportClass::Sell -- trying to sell a non-active building\");\n\t\t\t} else {\n\t\t\t\tif (building->Can_Demolish() && building->House.Is_Valid() && building->House->Class->House == PlayerPtr->Class->House)\n\t\t\t\t{\n\t\t\t\t\tbuilding->Sell_Back(1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Repair_Sell_Cancel -- Ends the player's repair or sell mode. Doesn't do anything right now.\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 5/1/2019 - LLL\n**************************************************************************************************/\nvoid DLLExportClass::Repair_Sell_Cancel(uint64 player_id)\n{\n\t//OutputDebugString(\"Repair_Sell_Cancel\\n\");\n}\n\n/**************************************************************************************************\n* DLLExportClass::Scatter_Selected -- Scatter the selected units\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 10/15/2019 - SKY\n**************************************************************************************************/\nvoid DLLExportClass::Scatter_Selected(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tif (CurrentObject.Count()) {\n\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\tif (tech != NULL && tech->Can_Player_Move()) {\n\t\t\t\tOutList.Add(EventClass(EventClass::SCATTER, TargetClass(tech)));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Select_Next_Unit\n*\n* History: 03.02.2020 MBL\n**************************************************************************************************/\nvoid DLLExportClass::Select_Next_Unit(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tObjectClass* obj = Map.Next_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\tif (obj) {\n\t\tUnselect_All();\n\t\tobj->Select();\n\n\t\tCOORDINATE center = Map.Center_Map();\n\t\tMap.Flag_To_Redraw(true);\n\t\tif (center) {\n\t\t\tOn_Center_Camera(PlayerPtr, Coord_X(center), Coord_Y(center));\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Select_Previous_Unit\n*\n* History: 03.02.2020 MBL\n**************************************************************************************************/\nvoid DLLExportClass::Select_Previous_Unit(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tObjectClass* obj = Map.Prev_Object(CurrentObject.Count() ? CurrentObject[0] : NULL);\n\tif (obj) {\n\t\tUnselect_All();\n\t\tobj->Select();\n\n\t\tCOORDINATE center = Map.Center_Map();\n\t\tMap.Flag_To_Redraw(true);\n\t\tif (center) {\n\t\t\tOn_Center_Camera(PlayerPtr, Coord_X(center), Coord_Y(center));\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Selected_Guard_Mode\n*\n* History: 03.03.2020 MBL\n**************************************************************************************************/\nvoid DLLExportClass::Selected_Guard_Mode(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tif (CurrentObject.Count()) {\n\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\tif (tech != NULL && tech->Can_Player_Fire()) {\n\t\t\t\tif (tech->Can_Player_Move()) {\n\t\t\t\t\tOutList.Add(EventClass(TargetClass(tech), MISSION_GUARD_AREA));\n\t\t\t\t} else {\n\t\t\t\t\tOutList.Add(EventClass(TargetClass(tech), MISSION_GUARD));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Selected_Stop\n*\n* History: 03.03.2020 MBL\n**************************************************************************************************/\nvoid DLLExportClass::Selected_Stop(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\t// Copied from RedAlert/Conquer.cpp - Keyboard_Process() with Options.KeyStop (VK_S)\n\tif (CurrentObject.Count()) {\n\t\tfor (int index = 0; index < CurrentObject.Count(); index++) {\n\t\t\tObjectClass const * tech = CurrentObject[index];\n\n\t\t\tif (tech != NULL && (tech->Can_Player_Move() || (tech->Can_Player_Fire() && tech->What_Am_I() != RTTI_BUILDING))) {\n\t\t\t\tOutList.Add(EventClass(EventClass::IDLE, TargetClass(tech)));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Units_Queued_Movement_Toggle\n*\n* History: 03.03.2020 MBL\n**************************************************************************************************/\nvoid DLLExportClass::Units_Queued_Movement_Toggle(uint64 player_id, bool toggle)\n{\n\t// Currently Red Alert only\n\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\tif (PlayerPtr != NULL) \n\t{\n\t\tPlayerPtr->IsQueuedMovementToggle = toggle;\n\t}\n}\n\n/**************************************************************************************************\n* DLLExportClass::Team_Units_Formation_Toggle_On\n*\n* History: 03.03.2020 MBL\n**************************************************************************************************/\n// extern void Toggle_Formation(void); // Code\\RedAlert\\Conquer.cpp\nextern char FormationEvent; // Code\\RedAlert\\Conquer.cpp \nvoid DLLExportClass::Team_Units_Formation_Toggle_On(uint64 player_id)\n{\n\t/*\n\t** Get the player for this...\n\t*/\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\t//\n\t// Code here copied and modified from Toggle_Formation(), since obj->IsSelected is not supported\n\t// Replacing with ObjectClass::Is_Selected_By_Player(HouseClass *player);\n\t//\n\n\tint team = MAX_TEAMS;\n\tlong minx = 0x7FFFFFFFL, miny = 0x7FFFFFFFL;\n\tlong maxx = 0, maxy = 0;\n\tint index;\n\tbool setform = 0;\n\n\tTeamFormDataStruct& team_form_data = TeamFormData[PlayerPtr->Class->House];\n\n\t//\n\t// Recording support\n\t//\n\tif (Session.Record) {\n\t\tFormationEvent = 1;\n\t}\n\n\t/*\n\t** Find the first selected object that is a member of a team, and\n\t** register his group as the team we're using.  Once we find the team\n\t** number, update the 'setform' flag to know whether we should be setting\n\t** the formation's offsets, or clearing them.  If they currently have\n\t** illegal offsets (as in 0x80000000), then we're setting.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj) {\n\t\t\tif (obj->House == PlayerPtr) {\n\t\t\t\tif (!obj->IsInLimbo) {\n\t\t\t\t\tif (obj->Is_Selected_By_Player(PlayerPtr)) {\n\t\t\t\t\t\tteam = obj->Group;\n\t\t\t\t\t\tif (team < MAX_TEAMS) {\n\t\t\t\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\t\t\t\tteam_form_data.TeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (team >= MAX_TEAMS) {\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj) {\n\t\t\t\tif (obj->House == PlayerPtr) {\n\t\t\t\t\tif (!obj->IsInLimbo) {\n\t\t\t\t\t\tif (obj->Is_Selected_By_Player(PlayerPtr)) {\n\t\t\t\t\t\t\tteam = obj->Group;\n\t\t\t\t\t\t\tif (team < MAX_TEAMS) {\n\t\t\t\t\t\t\t\tsetform = obj->XFormOffset == (int)0x80000000;\n\t\t\t\t\t\t\t\tteam_form_data.TeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team >= MAX_TEAMS) {\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj) {\n\t\t\t\tif (obj->House == PlayerPtr) {\n\t\t\t\t\tif (!obj->IsInLimbo) {\n\t\t\t\t\t\tif (obj->Is_Selected_By_Player(PlayerPtr)) {\n\t\t\t\t\t\t\tteam = obj->Group;\n\t\t\t\t\t\t\tif (team < MAX_TEAMS) {\n\t\t\t\t\t\t\t\tsetform = obj->XFormOffset == 0x80000000UL;\n\t\t\t\t\t\t\t\tteam_form_data.TeamSpeed[team] = SPEED_WHEEL;\n\t\t\t\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = MPH_LIGHT_SPEED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (team >= MAX_TEAMS) return;\n\t/*\n\t** Now that we have a team, let's go set (or clear) the formation offsets.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * obj = Units.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t\tteam_form_data.TeamSpeed[team] = obj->Class->Speed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = (int)0x80000000;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\tobj->Mark(MARK_CHANGE);\n\t\t\tif (setform) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tif (xc < minx) minx = xc;\n\t\t\t\tif (xc > maxx) maxx = xc;\n\t\t\t\tif (yc < miny) miny = yc;\n\t\t\t\tif (yc > maxy) maxy = yc;\n\t\t\t\tif (obj->Class->MaxSpeed < team_form_data.TeamMaxSpeed[team]) {\n\t\t\t\t\tteam_form_data.TeamMaxSpeed[team] = obj->Class->MaxSpeed;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->XFormOffset = obj->YFormOffset = 0x80000000UL;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** All the units have been counted to find the bounding rectangle and\n\t** center of the formation, or to clear their offsets.  Now, if we're to\n\t** set them into formation, proceed to do so.  Otherwise, bail.\n\t*/\n\tif (setform) {\n\t\tint centerx = (int)((maxx - minx)/2)+minx;\n\t\tint centery = (int)((maxy - miny)/2)+miny;\n\n\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * obj = Units.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * obj = Vessels.Ptr(index);\n\t\t\tif (obj && !obj->IsInLimbo && obj->House == PlayerPtr && obj->Group == team ) {\n\t\t\t\tlong xc = Cell_X(Coord_Cell(obj->Center_Coord()));\n\t\t\t\tlong yc = Cell_Y(Coord_Cell(obj->Center_Coord()));\n\n\t\t\t\tobj->XFormOffset = xc - centerx;\n\t\t\t\tobj->YFormOffset = yc - centery;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/**************************************************************************************************\n* CNC_Handle_Debug_Request -- Process a debug input request\n*\n* In:   \n*       \n*\n* Out:\n*\n*\n* History: 1/7/2019 5:20PM - ST\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Debug_Request(DebugRequestEnum debug_request_type, uint64 player_id, const char *object_name, int x, int y, bool unshroud, bool enemy)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\t\n\tswitch (debug_request_type) {\n\t\t\n\t\tcase DEBUG_REQUEST_SPAWN_OBJECT:\n\t\t\tDLLExportClass::Debug_Spawn_Unit(object_name, x, y, enemy);\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_FORCE_CRASH:\n\t\t\tDebug_Force_Crash = true;\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_KILL_OBJECT:\n\t\t\tif (strcmp(object_name, \"HEAL\") == 0) {\n\t\t\t\tDLLExportClass::Debug_Heal_Unit(x, y);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tDLLExportClass::Debug_Kill_Unit(x, y);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_END_GAME:\n\t\t\t{\n\t\t\t\tbool win = true;\n\n\t\t\t\tconst char lose[] =  \"LOSE\";\n\t\t\t\tif (strcmp(lose, object_name) == 0) {\n\t\t\t\t\twin = false;\n\t\t\t\t}\n\n\t\t\t\tPlayerWins = win;\n\t\t\t\tPlayerLoses = !win;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_UNSHROUD:\n\t\t\tDebug_Unshroud = unshroud;\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_SUPERWEAPON_RECHARGE:\n\t\t\tfor (int i = 0; i < SPC_COUNT; ++i)\n\t\t\t{\n\t\t\t\tPlayerPtr->SuperWeapon[i].Forced_Charge(true);\n\t\t\t}\n\t\t\tbreak;\n\t\t\t\n\t\tcase DEBUG_REQUEST_END_PRODUCTION:\n\t\t\t{\t\n\t\t\t\tfor (int index = 0; index < Factories.Count(); index++) {\n\t\t\t\t\tFactoryClass* factory = Factories.Ptr(index);\n\t\t\t\t\tif (factory->Get_House()->IsHuman) {\n\t\t\t\t\t\tFactories.Ptr(index)->Force_Complete();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_ADD_RESOURCES:\n\t\t\t{\n\t\t\t\tif (object_name) {\n\t\t\t\t\tint amount = atoi(object_name);\n\t\t\t\t\tPlayerPtr->Credits += amount;\n\t\t\t\t\tif (PlayerPtr->Credits < 0) {\n\t\t\t\t\t\tPlayerPtr->Credits = 0;\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\n\t\t\t}\t\t \n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_UNLOCK_BUILDABLES:\n\t\t\tPlayerPtr->DebugUnlockBuildables = !PlayerPtr->DebugUnlockBuildables;\n\t\t\tPlayerPtr->IsRecalcNeeded = true;\n\t\t\tbreak;\n\n\t\tcase DEBUG_REQUEST_SET_GLOBAL_FLAG:\n\t\t\tScen.Set_Global_To(x, true);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\t\t\t  \n\n\nextern \"C\" __declspec(dllexport) void __cdecl CNC_Handle_Beacon_Request(BeaconRequestEnum beacon_request_type, uint64 player_id, int pixel_x, int pixel_y)\n{\n\tif (!DLLExportClass::Set_Player_Context(player_id)) {\n\t\treturn;\n\t}\n\n\t// Beacons are only available if legacy rendering is disabled\n\tif (DLLExportClass::Legacy_Render_Enabled()) {\n\t\treturn;\n\t}\n\n\t// Only allow one beacon per player\n\tfor (int index = 0; index < Anims.Count(); ++index) {\n\t\tAnimClass* anim = Anims.Ptr(index);\n\t\tif (anim != NULL &&\n\t\t\t(*anim == ANIM_BEACON || *anim == ANIM_BEACON_VIRTUAL) &&\n\t\t\tanim->OwnerHouse == PlayerPtr->Class->House) {\n\t\t\tdelete anim;\n\t\t}\n\t}\n\n\tOutList.Add(EventClass(ANIM_BEACON, PlayerPtr->Class->House, Map.Pixel_To_Coord(pixel_x, pixel_y), PlayerPtr->Get_Allies()));\n\n\t// Send sound effect to allies\n\tfor (int index = 0; index < Houses.Count(); ++index) {\n\t\tHouseClass* hptr = Houses.Ptr(index);\n\t\tif (hptr != NULL && hptr->IsActive && hptr->IsHuman && PlayerPtr->Is_Ally(hptr)) {\n\t\t\tDLLExportClass::On_Sound_Effect(hptr, VOC_BEACON, \"\", 0, 0);\n\t\t}\n\t}\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Debug_Spawn_All -- Debug spawn all buildable units and structures\n*\n* In:   Object to unlimbo , x & y cell positions\n*\n*\n* Out:  True if unlimbo succeeded\n*\n*\n*\n* History: 1/22/2020 2:57PM - ST\n**************************************************************************************************/\nbool DLLExportClass::Try_Debug_Spawn_Unlimbo(TechnoClass *techno, int &cell_x, int &cell_y)\n{\n\tif (techno) {\n\t\t\n\t\tint map_cell_x = Map.MapCellX;\n\t\tint map_cell_y = Map.MapCellY;\n\t\tint map_cell_right = map_cell_x + Map.MapCellWidth;\n\t\tint map_cell_bottom = map_cell_y + Map.MapCellHeight;\n\n\t\tmap_cell_right = min(map_cell_right, cell_x + 26);\t\t// Generally try to prevent the objects from spawing off the right of the screen\n\t\t\n\t\tint try_x = cell_x;\n\t\tint try_y = cell_y;\n\t\t\t\t\t\n\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\t\n\t\t\tCELL cell = XY_Cell(try_x, try_y);\n\t\t\t\t\t\n\t\t\tif (techno->Unlimbo(Cell_Coord(cell))) {\n\t\t\t\t\n\t\t\t\ttry_x++;\n\t\t\t\tif (try_x > map_cell_right - 2) {\n\t\t\t\t\ttry_x = cell_x;\t//map_cell_x + 2;\n\t\t\t\t\ttry_y++;\n\t\t\t\t}\n\n\t\t\t\tcell_x = try_x;\n\t\t\t\tcell_y = try_y;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\ttry_x++;\n\t\t\tif (try_x > map_cell_right - 2) {\n\t\t\t\ttry_x = cell_x;\t//map_cell_x + 2;\n\t\t\t\ttry_y++;\n\t\t\t}\n\t\t}\n\n\t\tcell_x = try_x;\n\t\tcell_y = try_y;\n\t}\n\treturn false;\n}\t\t\t  \n\n\n/**************************************************************************************************\n* DLLExportClass::Debug_Spawn_All -- Debug spawn all buildable units and structures\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 1/22/2020 2:57PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Debug_Spawn_All(int x, int y)\n{\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\n\tint map_cell_bottom = map_cell_y + Map.MapCellHeight;\n\n\tint origin_x = map_cell_x + 2;\n\tint origin_y = map_cell_y + 2;\n\n\tif (x != 0 || y != 0) {\n\t\tCELL screen_cell = Coord_Cell(Map.Pixel_To_Coord(x, y));\n\t\torigin_x = Cell_X(screen_cell);\n\t\torigin_y = Cell_Y(screen_cell);\n\t}\n\n\tint try_x = origin_x;\n\tint try_y = origin_y;\n\n\tHousesType house = PlayerPtr->Class->House;\n\n\t\t\n\tfor (StructType sindex = STRUCT_FIRST; sindex < STRUCT_COUNT; sindex++) {\n\t\tBuildingTypeClass const & building_type = BuildingTypeClass::As_Reference(sindex);\n\n\t\tif (building_type.Get_Ownable() && building_type.Level != -1) {\n\t\t\t\t\n\t\t\tBuildingClass * building = new BuildingClass(building_type, house);\n\t\t\tif (building) {\n\t\t\t\t\n\t\t\t\ttry_x = origin_x;\n\t\t\t\ttry_y = origin_y;\n\t\t\t\t\t\n\t\t\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\tif (Try_Debug_Spawn_Unlimbo(building, try_x, try_y)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t}\n\n\n\tfor (UnitType index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\tUnitTypeClass const & unit_type = UnitTypeClass::As_Reference(index);\n\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (unit_type.Get_Ownable() && unit_type.Level != -1) {\n\t\t\t\t\n\t\t\tUnitClass * unit = (UnitClass*) unit_type.Create_One_Of(PlayerPtr);\n\t\t\tif (unit) {\n\t\t\t\t\n\t\t\t\ttry_x = origin_x;\n\t\t\t\ttry_y = origin_y;\n\t\t\t\t\t  \n\t\t\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\tif (Try_Debug_Spawn_Unlimbo(unit, try_x, try_y)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\t\n\t\t}\n\t}\n\n\n\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\tInfantryTypeClass\tconst &infantry_type = InfantryTypeClass::As_Reference(index);\n\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (infantry_type.Get_Ownable() && infantry_type.Level != -1) {\n\t\t\t\t\n\t\t\tInfantryClass * inf = (InfantryClass*) infantry_type.Create_One_Of(PlayerPtr);\n\t\t\tif (inf) {\n\t\t\t\t\n\t\t\t\ttry_x = origin_x;\n\t\t\t\ttry_y = origin_y;\n\t\t\t\t\n\t\t\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\tif (Try_Debug_Spawn_Unlimbo(inf, try_x, try_y)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\t\n\t\t}\n\t}\n\n\tfor (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {\n\t\tAircraftTypeClass\tconst &aircraft_type = AircraftTypeClass::As_Reference(index);\n\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (aircraft_type.Get_Ownable() && aircraft_type.Level != -1) {\n\t\t\t\t\n\t\t\tAircraftClass * air = (AircraftClass*) aircraft_type.Create_One_Of(PlayerPtr);\n\t\t\tif (air) {\n\t\t\t\t\n\t\t\t\ttry_x = origin_x;\n\t\t\t\ttry_y = origin_y;\n\t\t\t\t\t  \n\t\t\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\tif (Try_Debug_Spawn_Unlimbo(air, try_x, try_y)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\t\n\t\t}\n\t}\n\n\n\tfor (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {\n\t\tVesselTypeClass\tconst &vessel_type = VesselTypeClass::As_Reference(index);\n\n\t\t/*\n\t\t**\tFetch the sidebar cameo image for this building.\n\t\t*/\n\t\tif (vessel_type.Get_Ownable() && vessel_type.Level != -1) {\n\t\t\t\t\n\t\t\tVesselClass * boat = (VesselClass*) vessel_type.Create_One_Of(PlayerPtr);\n\t\t\tif (boat) {\n\t\t\t\t\n\t\t\t\ttry_x = origin_x;\n\t\t\t\ttry_y = origin_y;\n\t\t\t\t\t  \n\t\t\t\twhile (try_y < map_cell_bottom) {\n\t\t\t\t\tif (Try_Debug_Spawn_Unlimbo(boat, try_x, try_y)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\t\n\t\t}\n\t}\n}\t\t\t  \n\n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Debug_Spawn_Unit -- Debug spawn a unit at the specified location\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 3/14/2019 3:20PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Debug_Spawn_Unit(const char *object_name, int x, int y, bool enemy)\n{\n\tif (object_name == NULL) {\n\t\treturn;\n\t}\n\t\n\tif (strlen(object_name) == 0) {\n\t\treturn;\n\t}\n\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tHousesType house = PlayerPtr->Class->House;\n\n\t/*\n\t** Place all?\n\t*/\n\tif (stricmp(object_name, \"ALLOBJECTS\") == 0) {\n\t\tDebug_Spawn_All(x, y);\n\t\treturn;\n\t}\n\n\t/*\n\t** If this is for the enemy, find the enemy with the most stuff\n\t*/\n\n\tif (enemy) {\n\t\tunsigned max_count = 0;\n\t\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\t\tconst HouseClass* player = Houses.Ptr(i);\n\t\t\tconst unsigned count = player->CurUnits + player->CurBuildings + player->CurInfantry + player->CurVessels + player->CurAircraft;\n\t\t\tif (!PlayerPtr->Is_Ally(player) && (count >= max_count)) {\n\t\t\t\thouse = player->Class->House;\n\t\t\t\tmax_count = count;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** What is this thing?\n\t*/\n\n\tStructType structure_type = BuildingTypeClass::From_Name(object_name);\n\tif (structure_type != STRUCT_NONE) {\n\t\t\n\t\tBuildingClass * building = new BuildingClass(structure_type, house);\n\t\tif (building) {\n\t\t\tif (!building->Unlimbo(Cell_Coord(cell))) {\n\t\t\t\tdelete building;\n\t\t\t}\n\t\t}\n\t\t\n#if (0)\t\t \n\t\tMap.PendingObject = &BuildingTypeClass::As_Reference(structure_type);\n\t\tMap.PendingHouse = PlayerPtr->ActLike;\n\t\tMap.PendingObjectPtr = Map.PendingObject->Create_One_Of(PlayerPtr);\n\t\tif (Map.PendingObjectPtr) {\n\t\t\tMap.Set_Cursor_Pos();\n\t\t\tMap.Set_Cursor_Shape(Map.PendingObject->Occupy_List());\n\n\t\t\t//OutList.Add(EventClass(EventClass::PLACE, RTTI_BUILDING, (CELL)(cell + Map.ZoneOffset)));\n\t\t}\n#endif\t\t\n\t\treturn;\n\t}\n\n\t\n\tUnitType unit_type = UnitTypeClass::From_Name(object_name);\n\tif (unit_type != UNIT_NONE) {\n\t\t\n\t\tUnitClass * unit = new UnitClass(unit_type, house);\n\t\tif (unit) {\n\t\t\tunit->Unlimbo(Map.Pixel_To_Coord(x, y), DIR_N);\n\t\t}\n\t\t\n\t\treturn;\n\t}\n\n\n\tInfantryType infantry_type = InfantryTypeClass::From_Name(object_name);\n\tif (infantry_type != INFANTRY_NONE) {\n\t\t\n\t\tInfantryClass * inf = new InfantryClass(infantry_type, house);\n\t\tif (inf) {\n\t\t\tinf->Unlimbo(Map.Pixel_To_Coord(x, y), DIR_N);\n\t\t}\n\t\treturn;\n\t}\n\n\tAircraftType aircraft_type = AircraftTypeClass::From_Name(object_name);\n\tif (aircraft_type != AIRCRAFT_NONE) {\n\n\t\tAircraftClass * air = new AircraftClass(aircraft_type, house);\n\t\tif (air) {\n\t\t\tair->Unlimbo(Map.Pixel_To_Coord(x, y), DIR_N);\n\t\t}\n\t\treturn;\n\t}\n\n\tVesselType vessel_type = VesselTypeClass::From_Name(object_name);\n\tif (vessel_type != VESSEL_NONE) {\n\t\t\n\t\tVesselClass *boat = new VesselClass(vessel_type, house);\n\t\tif (boat != NULL) {\n\t\t\t\n\t\t\tif (boat->Unlimbo(Map.Pixel_To_Coord(x, y), DIR_N)) {\n\t\t\t\tboat->Enter_Idle_Mode();\n\t\t\t} else {\n\t\t\t\tdelete boat;\n\t\t\t}\t\n\t\t}\n\t}\n\n\tOverlayType overlay_type = OverlayTypeClass::From_Name(object_name);\n\tif (overlay_type != OVERLAY_NONE)\n\t{\n\t\tnew OverlayClass(overlay_type, cell);\n\n\t\treturn;\n\t}\n\n}\t\t\t  \n\n\n/**************************************************************************************************\n* DLLExportClass::Debug_Kill_Unit -- Kill a unit at the specified location\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 8/19/2019 3:09PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Debug_Kill_Unit(int x, int y)\n{\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tCellClass * cellptr = &Map[cell];\n\n\tif (cellptr) {\n\t\tObjectClass *obj = cellptr->Cell_Object();\n\t\tstatic const int debug_damage = 100; // 100 = Incremental damage\n\t\tif (obj) {\n\t\t\tint damage = debug_damage;\n\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE, 0, true);\n\t\t} else {\n\t\t\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\t\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\t\t\t\tif (optr->IsTiberium) {\n\t\t\t\t\tcellptr->Reduce_Tiberium(1);\n\t\t\t\t}\n\t\t\t\tif (optr->IsWall) {\n\t\t\t\t\tMap[cell].Reduce_Wall(debug_damage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE1 || cellptr->TType == TEMPLATE_BRIDGE2 ||\n\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE1H || cellptr->TType == TEMPLATE_BRIDGE2H ||\n\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE_1A || cellptr->TType == TEMPLATE_BRIDGE_1B ||\n\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE_2A || cellptr->TType == TEMPLATE_BRIDGE_2B ||\n\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE_3A || cellptr->TType == TEMPLATE_BRIDGE_3B) {\n\t\t\t\tMap.Destroy_Bridge_At(cell);\n\t\t\t}\n\t\t}\n\t}\n}\t\t\t  \n\nvoid DLLExportClass::Debug_Heal_Unit(int x, int y)\n{\n\tCOORDINATE coord = Map.Pixel_To_Coord(x, y);\n\tCELL cell = Coord_Cell(coord);\n\n\tCellClass * cellptr = &Map[cell];\n\n\tif (cellptr) {\n\t\tObjectClass *obj = cellptr->Cell_Object();\n\t\tif (obj) {\n\t\t\tobj->Strength = obj->Class_Of().MaxStrength;\n\t\t}\n\t\telse {\n\t\t\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\t\t\tOverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);\n\t\t\t\tif (optr->IsTiberium) {\n\t\t\t\t\tconst int cellcount = (int)FACING_COUNT + 1;\n\t\t\t\t\tCellClass* cells[cellcount];\n\t\t\t\t\tcells[0] = cellptr;\n\t\t\t\t\tfor (FacingType index = FACING_N; index < FACING_COUNT; index++) {\n\t\t\t\t\t\tcells[(int)index + 1] = cellptr->Adjacent_Cell(index);\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (int index = 0; index < cellcount; index++) {\n\t\t\t\t\t\tCellClass * newcell = cells[index];\n\n\t\t\t\t\t\tif (newcell != NULL) {\n\t\t\t\t\t\t\tif (newcell->Can_Tiberium_Germinate()) {\n\t\t\t\t\t\t\t\tswitch (cellptr->Overlay) {\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD1:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD2:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD3:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD4:\n\t\t\t\t\t\t\t\t\t\tnew OverlayClass(Random_Pick(OVERLAY_GOLD1, OVERLAY_GOLD4), newcell->Cell_Number());\n\t\t\t\t\t\t\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS1:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS2:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS3:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS4:\n\t\t\t\t\t\t\t\t\t\tnew OverlayClass(Random_Pick(OVERLAY_GEMS1, OVERLAY_GEMS4), newcell->Cell_Number());\n\t\t\t\t\t\t\t\t\t\tnewcell->OverlayData = 0;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (newcell->Land_Type() == LAND_TIBERIUM) {\n\t\t\t\t\t\t\t\tswitch (newcell->Overlay) {\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD1:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD2:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD3:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GOLD4:\n\t\t\t\t\t\t\t\t\t\tnewcell->OverlayData = MIN(newcell->OverlayData + 1, 11);\n\t\t\t\t\t\t\t\t\t\tnewcell->Recalc_Attributes();\n\t\t\t\t\t\t\t\t\t\tnewcell->Redraw_Objects();\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS1:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS2:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS3:\n\t\t\t\t\t\t\t\t\tcase OVERLAY_GEMS4:\n\t\t\t\t\t\t\t\t\t\tnewcell->OverlayData = MIN(newcell->OverlayData + 1, 2);\n\t\t\t\t\t\t\t\t\t\tnewcell->Recalc_Attributes();\n\t\t\t\t\t\t\t\t\t\tnewcell->Redraw_Objects();\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Legacy_Render_Enabled -- Is the legacy rendering enabled?\n*\n* In:   \n*\n* Out:  \n*\n*\n*\n* History: 4/15/2019 5:46PM - ST\n**************************************************************************************************/\nbool DLLExportClass::Legacy_Render_Enabled(void)\n{\n\tif (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {\n\t\tunsigned int num_humans = 0U;\n\t\tfor (int i = 0; i < MULTIPLAYER_COUNT; ++i) {\n\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tif (player_ptr && player_ptr->IsHuman) {\n\t\t\t\tif (++num_humans > 1) break;\n\t\t\t}\n\t\t}\n\t\treturn num_humans < 2;\n\t}\n\n\t//return false;\n\treturn true;\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Computer_Message -- Replacement for original Computer_Message function\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 1/27/2020 1:42PM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Computer_Message(bool last_player_taunt)\n{\n\tHousesType house;\n\tHouseClass *ptr;\n\n\tHouseClass *ai_players[MAX_PLAYERS];\n\tint ai_player_count = 0;\n\n\t/*------------------------------------------------------------------------\n\tFind the computer house that the message will be from\n\t------------------------------------------------------------------------*/\n\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + MULTIPLAYER_COUNT); house++) {\n\t\tptr = HouseClass::As_Pointer(house);\n\n\t\tif (!ptr || ptr->IsHuman || ptr->IsDefeated) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tai_players[ai_player_count++] = ptr;\n\t}\n\n\tif (ai_player_count) {\n\t\tint ai_player_index = 0;\n\t\tif (ai_player_count > 1) {\n\t\t\tai_player_index = IRandom(0, ai_player_count - 1);\n\t\t}\n\n\t\tint taunt_index;\n\t\tif (last_player_taunt) {\n\t\t\ttaunt_index = 13;\n\t\t} else {\n\t\t\ttaunt_index = IRandom(0,12);\n\t\t}\n\n\t\tOn_Message(ai_players[ai_player_index], \"\", 15.0f, MESSAGE_TYPE_COMPUTER_TAUNT, taunt_index);\n\t}\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Set_Special_Key_Flags --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 6/27/2019 - JAS\n**************************************************************************************************/\nvoid DLLExportClass::Set_Special_Key_Flags(unsigned char special_key_flags)\n{\n\tSpecialKeyFlags[CurrentLocalPlayerIndex] = special_key_flags;\n}\n\n/**************************************************************************************************\n* DLLExportClass::Clear_Special_Key_Flags --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 6/27/2019 - JAS\n**************************************************************************************************/\nvoid DLLExportClass::Clear_Special_Key_Flags()\n{\n\tSpecialKeyFlags[CurrentLocalPlayerIndex] = 0;\n}\n\n/**************************************************************************************************\n* DLLExportClass::Get_Input_Key_State --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 6/27/2019 - JAS\n**************************************************************************************************/\nbool DLLExportClass::Get_Input_Key_State(KeyNumType key)\n{\n\tswitch (key)\n\t{\n\tcase KN_LCTRL:\n\t\treturn (SpecialKeyFlags[CurrentLocalPlayerIndex] & INPUT_SPECIAL_KEY_CTRL) != 0;\n\t\tbreak;\n\tcase KN_LSHIFT:\n\t\treturn (SpecialKeyFlags[CurrentLocalPlayerIndex] & INPUT_SPECIAL_KEY_SHIFT) != 0;\n\t\tbreak;\n\tcase KN_LALT:\n\t\treturn (SpecialKeyFlags[CurrentLocalPlayerIndex] & INPUT_SPECIAL_KEY_ALT) != 0;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t};\n\n\treturn false;\n\n}\n\n/**************************************************************************************************\n* Get_Input_Key_State\n*\n* History: 6/27/2019 - JAS\n**************************************************************************************************/\nbool DLL_Export_Get_Input_Key_State(KeyNumType key)\n{\n\treturn DLLExportClass::Get_Input_Key_State(key);\n}\n\n\n\n\nbool DLLSave(Pipe &file)\n{\n\treturn DLLExportClass::Save(file);\n}\n\nbool DLLLoad(Straw &file)\n{\n\treturn DLLExportClass::Load(file);\n}\n\n\n/**************************************************************************************************\n* DLLExportClass::Save --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 9/10/2019 10:24AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Save(Pipe & pipe)\n{\n\t/*\n\t** Version first\n\t*/\n\tunsigned int version = CNC_DLL_API_VERSION;\n\tpipe.Put(&version, sizeof(version));\n\t\n\tpipe.Put(MultiplayerStartPositions, sizeof(MultiplayerStartPositions));\n\n\tpipe.Put(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs));\n\n\tpipe.Put(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons));\n\n\tpipe.Put(MPlayerIsHuman, sizeof(MPlayerIsHuman));\n\n\tpipe.Put(MultiplayerStartPositions, sizeof(MultiplayerStartPositions));\n\n\tpipe.Put(PlacementType, sizeof(PlacementType));\n\n\tpipe.Put(&OverrideNewUnitsEnabled, sizeof(OverrideNewUnitsEnabled));\n\n\tfor (int i=0 ; i<MAX_PLAYERS ; i++) {\n\t\tSidebar_Glyphx_Save(pipe, &MultiplayerSidebars[i]);\n\n\t\tint has_player = false;\n\t\tif (i < Session.Players.Count() && Session.Players[i]) {\n\t\t\thas_player = true;\n\t\t\tpipe.Put(&has_player, sizeof(has_player));\n\t\t\tpipe.Put(Session.Players[i], sizeof(NodeNameType));\n\t\t} else {\n\t\t\tpipe.Put(&has_player, sizeof(has_player));\n\t\t}\t\n\t}\n\n\tpipe.Put(&Special, sizeof(Special));\n\n\t/*\n\t** Special case for MPSuperWeaponDisable - store negated value so it defaults to enabled\n\t*/\n\tbool not_allow_super_weapons = !MPSuperWeaponDisable;\n\tpipe.Put(&not_allow_super_weapons, sizeof(not_allow_super_weapons));\n\n\t/*\n\t** Room for save game expansion\n\t*/\n\tunsigned char padding[4095];\n\tmemset(padding, 0, sizeof(padding));\n\t\n\tpipe.Put(padding, sizeof(padding));\n\n\n\treturn true;\n}\n\t \n\n/**************************************************************************************************\n* DLLExportClass::Load --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 9/10/2019 10:24AM - ST\n**************************************************************************************************/\nbool DLLExportClass::Load(Straw & file)\n{\n\tunsigned int version = 0;\n\n\tif (file.Get(&version, sizeof(version)) != sizeof(version)) {\n\t\treturn false;\n\t}\n\t\n\tif (file.Get(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) {\n\t\treturn false;\n\t}\n\n\tif (file.Get(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs)) != sizeof(GlyphxPlayerIDs)) {\n\t\treturn false;\n\t}\n\t\n\tif (file.Get(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons)) != sizeof(GlyphXClientSidebarWidthInLeptons)) {\n\t\treturn false;\n\t}\n\n\tif (file.Get(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) {\n\t\treturn false;\n\t}\n\n\tif (file.Get(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) {\n\t\treturn false;\n\t}\n\n\tif (file.Get(PlacementType, sizeof(PlacementType)) != sizeof(PlacementType)) {\n\t\treturn false;\n\t}\n\t\n\tif (file.Get(&OverrideNewUnitsEnabled, sizeof(OverrideNewUnitsEnabled)) != sizeof(OverrideNewUnitsEnabled)) {\n\t\treturn false;\n\t}\n\n\tif (Is_Aftermath_Installed()) {\n\t\tif (Session.Type == GAME_SKIRMISH || Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tbAftermathMultiplayer = NewUnitsEnabled = OverrideNewUnitsEnabled;\n\t\t}\n\t}\t\n\n\tSession.NumPlayers = 0;\n\n\tfor (int i=0 ; i<MAX_PLAYERS ; i++) {\n\t\tSidebar_Glyphx_Load(file, &MultiplayerSidebars[i]);\n\n\t\tint has_player = false;\n\t\tfile.Get(&has_player, sizeof(has_player));\n\t\t\n\t\tif (has_player) {\n\t\t\tNodeNameType *who = new NodeNameType;\n\t\t\tfile.Get(who, sizeof(NodeNameType));\n\t\t\tSession.Players.Add (who);\n\t\t\tSession.NumPlayers++;\n\t\t}\n\t}\n\n\tif (file.Get(&Special, sizeof(Special)) != sizeof(Special)) {\n\t\treturn false;\n\t}\n\n\t/*\n\t** Restore backup\n\t*/\n\tif (SpecialBackup != NULL) {\n\t\tmemcpy(SpecialBackup, &Special, sizeof(SpecialClass));\n\t}\n\n\t/*\n\t** Special case for MPSuperWeaponDisable - store negated value so it defaults to enabled\n\t*/\n\tbool not_allow_super_weapons = false;\n\tif (file.Get(&not_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) {\n\t\treturn false;\n\t}\n\tMPSuperWeaponDisable = !not_allow_super_weapons;\n\n\tunsigned char padding[4095];\n\t\n\tif (file.Get(padding, sizeof(padding)) != sizeof(padding)) {\n\t\treturn false;\n\t}\n\n\n\treturn true;\n}\n\n\n\n/**************************************************************************************************\n* DLLExportClass::Code_Pointers --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 9/10/2019 10:24AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Code_Pointers(void)\n{\n\tfor (int i=0 ; i<MAX_PLAYERS ; i++) {\n\t\tSidebar_Glyphx_Code_Pointers(&MultiplayerSidebars[i]);\n\t\t\n\t\tif (PlacementType[i]) {\n\t\t\tPlacementType[i] = (BuildingTypeClass *) PlacementType[i]->Type;\n\t\t}\n\t}\n}\n\n\t \n\n/**************************************************************************************************\n* DLLExportClass::Decode_Pointers --\n*\n* In:\n*\n* Out:\n*\n*\n*\n* History: 9/10/2019 10:24AM - ST\n**************************************************************************************************/\nvoid DLLExportClass::Decode_Pointers(void)\n{\n\tfor (int i=0 ; i<MAX_PLAYERS ; i++) {\n\t\tSidebar_Glyphx_Decode_Pointers(&MultiplayerSidebars[i]);\n\n\t\tif (PlacementType[i]) {\n\t\t\tStructType type = (StructType) reinterpret_cast<unsigned int>(PlacementType[i]);\n\t\t\tPlacementType[i] = NULL;\n\t\t\tif (type >= STRUCT_FIRST && type < STRUCT_COUNT) {\n\t\t\t\t\n\t\t\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(RTTI_BUILDINGTYPE, type);\n\t\t\t\tif (tech) {\n\t\t\t\t\tBuildingTypeClass* build_type = (BuildingTypeClass*)(tech);\n\t\t\t\t\tif (build_type) {\n\t\t\t\t\t\tPlacementType[i] = build_type;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid DLL_Code_Pointers(void)\n{\n\tDLLExportClass::Code_Pointers();\n}\n\nvoid DLL_Decode_Pointers(void)\n{\n\tDLLExportClass::Decode_Pointers();\n}"
  },
  {
    "path": "REDALERT/DLLInterface.h",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#pragma once\n\n#ifndef DLL_INTERFACE_H\n#define DLL_INTERFACE_H\n\t\t\nstruct CarryoverObjectStruct;\n\n\n\n/*\n** DLL Interface version\n** \n** \n** \n*/\n#include \"DLLInterfaceVersion.h\"\n\n\n\n\n#define MAX_EXPORT_CELLS\t\t\t(128 * 128)\n\n#ifdef TIBERIAN_DAWN\n#define MAP_MAX_CELL_WIDTH 64\n#define MAP_MAX_CELL_HEIGHT 64\n#else\n#define MAP_MAX_CELL_WIDTH 128\n#define MAP_MAX_CELL_HEIGHT 128\n#endif\n\n\n\n\n/*\n** Interface structs require stricter packing\n** \n** \n*/\n#pragma pack(push)\n#pragma pack(1)\n\n\n\n\n/**************************************************************************************\n** \n** Game state request types\n** \n** \n*/\nenum GameStateRequestEnum {\n\tGAME_STATE_NONE,\n\tGAME_STATE_STATIC_MAP,\n\tGAME_STATE_DYNAMIC_MAP,\n\tGAME_STATE_LAYERS,\n\tGAME_STATE_SIDEBAR,\n\tGAME_STATE_PLACEMENT,\n\tGAME_STATE_SHROUD,\n\tGAME_STATE_OCCUPIER,\n\tGAME_STATE_PLAYER_INFO\n};\t\n\n\n\n\n/**************************************************************************************\n** \n** Static map data (tiles)\n** \n** \n*/\nstruct CNCStaticCellStruct {\n\tchar\tTemplateTypeName[32];\n\tint\tIconNumber;\n};\n\n\n\nenum CnCTheaterType {\n\tCNC_THEATER_NONE=-1,\n\tCNC_THEATER_DESERT,\n\tCNC_THEATER_JUNGLE,\n\tCNC_THEATER_TEMPERATE,\n\tCNC_THEATER_WINTER,\n\n\tCNC_THEATER_COUNT,\n\tCNC_THEATER_FIRST=0\n};\n\n\nstruct CNCMapDataStruct {\n\tint\tMapCellX;\n\tint\tMapCellY;\n\tint\tMapCellWidth;\n\tint\tMapCellHeight;\n\tint\tOriginalMapCellX;\n\tint\tOriginalMapCellY;\n\tint\tOriginalMapCellWidth;\n\tint\tOriginalMapCellHeight;\n\n\tCnCTheaterType Theater;\n\tchar ScenarioName[_MAX_FNAME+_MAX_EXT];\n\t\n\tCNCStaticCellStruct StaticCells[MAX_EXPORT_CELLS];\n};\n\n\n\n\n/**************************************************************************************\n** \n**  Object type enum\n** \n** \n*/\n#define DLL_LAYER_COUNT 4\n\nenum DllObjectTypeEnum {\n\tUNKNOWN,\n\tINFANTRY,\n\tUNIT,\n\tAIRCRAFT,\n\tBUILDING,\n\tTERRAIN,\n\tANIM,\n\tBULLET,\n\tOVERLAY,\n\tSMUDGE,\n\tOBJECT,\n\tSPECIAL,\n\tINFANTRY_TYPE,\n\tUNIT_TYPE,\n\tAIRCRAFT_TYPE,\n\tBUILDING_TYPE,\n\tVESSEL,\n\tVESSEL_TYPE\n};\t\n\n\n\n\n\n/**************************************************************************************\n**\n**  Object action types\n**\n**\n*/\nenum DllActionTypeEnum : unsigned char {\n\tDAT_NONE,\n\tDAT_MOVE,\n\tDAT_NOMOVE,\n\tDAT_ENTER,\n\tDAT_SELF,\n\tDAT_ATTACK,\n\tDAT_ATTACK_OUT_OF_RANGE,\n\tDAT_GUARD,\n\tDAT_SELECT,\n\tDAT_CAPTURE,\n\tDAT_SABOTAGE,\n\tDAT_HEAL,\n\tDAT_DAMAGE,\n\tDAT_TOGGLE_PRIMARY,\n\tDAT_CANT_DEPLOY,\n\tDAT_REPAIR,\n\tDAT_CANT_REPAIR\n};\n\n\n\n\n\n/**************************************************************************************\n** \n**  Object state data\n** \n** \n*/\n\n#define MAX_OCCUPY_CELLS 36\n#define MAX_OBJECT_PIPS 18\n#define MAX_OBJECT_LINES 3\n#define MAX_HOUSES 32\n\nstruct CNCObjectLineStruct {\n\tint X;\n\tint Y;\n\tint X1;\n\tint Y1;\n\tint Frame;\n\tunsigned char Color;\n};\n\n#define CNC_OBJECT_ASSET_NAME_LENGTH 16\nstruct CNCObjectStruct {\n\tvoid\t\t\t\t*CNCInternalObjectPointer;\n\tchar\t\t\t\tTypeName[CNC_OBJECT_ASSET_NAME_LENGTH];\n\tchar \t\t\t\tAssetName[CNC_OBJECT_ASSET_NAME_LENGTH];\t\t// CNC uses 8.3 filenames, so it shouldn't need to be bigger than 9\n\tDllObjectTypeEnum\tType;\t\n\tint\t\t\t\t\tID;\n\tint\t\t\t\t\tBaseObjectID;\n\tDllObjectTypeEnum\tBaseObjectType;\t\n\tint\t\t\t\t\tPositionX;\n\tint\t\t\t\t\tPositionY;\n\tint\t\t\t\t\tWidth;\n\tint\t\t\t\t\tHeight;\n\tint\t\t\t\t\tAltitude;\n\tint\t\t\t\t\tSortOrder;\n\tint\t\t\t\t\tScale;\n\tint\t\t\t\t\tDrawFlags;\n\tshort\t\t\t\tMaxStrength;\n\tshort\t\t\t\tStrength;\n\tunsigned short\t\tShapeIndex;\n\tunsigned short\t\tCellX;\n\tunsigned short\t\tCellY;\n\tunsigned short\t\tCenterCoordX;\n\tunsigned short\t\tCenterCoordY;\n\tshort\t\t\t\tSimLeptonX;\n\tshort\t\t\t\tSimLeptonY;\n\tunsigned char\t\tDimensionX;\n\tunsigned char\t\tDimensionY;\n\tunsigned char\t\tRotation;\n\tunsigned char\t\tMaxSpeed;\n\tchar\t\t\t\tOwner;\n\tchar\t\t\t\tRemapColor;\n\tchar\t\t\t\tSubObject;\n\tbool\t\t\t\tIsSelectable;\n\tunsigned int\t\tIsSelectedMask;\n\tbool\t\t\t\tIsRepairing;\n\tbool\t\t\t\tIsDumping;\n\tbool\t\t\t\tIsTheaterSpecific;\n\tunsigned int\t\tFlashingFlags;\n\tunsigned char\t\tCloak;\n\tbool\t\t\t\tCanRepair;\n\tbool\t\t\t\tCanDemolish;\n\tbool\t\t\t\tCanDemolishUnit;\n\tshort\t\t\t\tOccupyList[MAX_OCCUPY_CELLS];\n\tint\t\t\t\t\tOccupyListLength;\n\tint\t\t\t\t\tPips[MAX_OBJECT_PIPS];\n\tint\t\t\t\t\tNumPips;\n\tint\t\t\t\t\tMaxPips;\n\tCNCObjectLineStruct\tLines[MAX_OBJECT_LINES];\n\tint\t\t\t\t\tNumLines;\n\tbool\t\t\t\tRecentlyCreated;\n\tbool\t\t\t\tIsALoaner;\n\tbool\t\t\t\tIsFactory;\n\tbool\t\t\t\tIsPrimaryFactory;\n\tbool\t\t\t\tIsDeployable;\n\tbool\t\t\t\tIsAntiGround;\n\tbool\t\t\t\tIsAntiAircraft;\n\tbool\t\t\t\tIsSubSurface;\n\tbool\t\t\t\tIsNominal;\n\tbool\t\t\t\tIsDog;\n\tbool\t\t\t\tIsIronCurtain;\n\tbool\t\t\t\tIsInFormation;\n\tbool\t\t\t\tCanMove[MAX_HOUSES];\n\tbool\t\t\t\tCanFire[MAX_HOUSES];\n\tbool\t\t\t\tCanDeploy;\n\tbool\t\t\t\tCanHarvest;\n\tbool\t\t\t\tCanPlaceBombs;\n\tbool\t\t\t\tIsFixedWingedAircraft;\n\tbool\t\t\t\tIsFake;\n\tunsigned char\t\tControlGroup;\n\tunsigned int\t\tVisibleFlags;\n\tunsigned int\t\tSpiedByFlags;\n\tchar \t\t\t\tProductionAssetName[CNC_OBJECT_ASSET_NAME_LENGTH];\n\tconst char*\t\t\tOverrideDisplayName;\n\tDllActionTypeEnum\tActionWithSelected[MAX_HOUSES];\n\n\tstatic const unsigned int VISIBLE_FLAGS_ALL = 0xffffffff;\n};\n\nstruct CNCObjectListStruct {\n\tint\t\t\t\t\tCount;\n\tCNCObjectStruct\tObjects[1];\t\t// Variable length\n};\n\n\n\n\n/**************************************************************************************\n** \n**  Placement validity data\n** \n**  Used to pass back info about tructure placement validity\n*/\nstruct CNCPlacementCellInfoStruct {\n\tbool\tPassesProximityCheck;\t\t\t// If the structure was placed in this cell, does that satisfy the proximity check for the whole structure?\n\tbool\tGenerallyClear;\t\t\t\t\t// Is this cell generally clear of obstructions that would prevent placement?\n};\n\nstruct CNCPlacementInfoStruct {\n\tint\t\t\t\t\t\t\t\tCount;\n\tCNCPlacementCellInfoStruct CellInfo[1];\t\t// Variable length\n};\n\n\n\n\n\n/**************************************************************************************\n** \n**  Sidebar/construction state data\n** \n** \n*/\nenum DllSuperweaponTypeEnum {\n\tSW_NONE,\n\tSW_UNKNOWN,\n\n\t//TD values\n\tSW_NUKE,\n\tSW_AIR_STRIKE,\n\tSW_ION_CANNON,\n\n\t//RA values\n\tSW_SONAR_PULSE,\n\tSW_CHRONOSPHERE,\n\tSW_PARA_BOMB,\n\tSW_PARA_INFANTRY,\n\tSW_SPY_MISSION,\n\tSW_IRON_CURTAIN,\n\tSW_GPS,\n\tSW_CHRONOSPHERE_DESTINATION\n};\n\nstruct CNCSidebarEntryStruct {\n\tchar\t\t\t\t\t\t\tAssetName[16];\t\t\t\t\t\t// CNC uses 8.3 filenames, so it shouldn't need to be bigger than 9\n\tint\t\t\t\t\t\t\tBuildableType;\t\t\t\t\t\t// This is the original buildable type that should be passed back if we want to start/cancel construction\n\tint\t\t\t\t\t\t\tBuildableID;\t   \t\t\t\t// This is the original buildable id that should be passed back if we want to start/cancel construction\n\tDllObjectTypeEnum\t\t\tType;\t\t\t\t\t\t\t\t\t// Type converted to shared enum\n\tDllSuperweaponTypeEnum\tSuperWeaponType;\n\tint\t\t\t\t\t\t\tCost;\t\t\t\t\t\t\t\t\t// Cost to construct\n\tint\t\t\t\t\t\t\tPowerProvided;\t\t\t\t\t\t// Power cost to construct\n\tint\t\t\t\t\t\t\tBuildTime;\t\t\t\t\t\t\t// Cost to construct\n\tfloat\t\t\t\t\t\t\tProgress;\t\t\t\t\t\t\t// Construction progress (0.0 - 1.0)\n\tshort\t\t\t\t\t\t\tPlacementList[MAX_OCCUPY_CELLS];\t// Which cells this structure occupies for placement (if structure)\n\tint\t\t\t\t\t\t\tPlacementListLength;\t\t\t\t\t// How many cells\n\tbool\t\t\t\t\t\t\tCompleted;\t\t\t\t\t\t\t// Construction has completed\n\tbool\t\t\t\t\t\t\tConstructing;\t\t\t\t\t\t// Is it currently constructing\n\tbool\t\t\t\t\t\t\tConstructionOnHold;\t\t\t\t// Is the current construction on hold\n\tbool\t\t\t\t\t\t\tBusy;\t\t\t\t\t\t\t\t\t// Is the associated factory busy\n\tbool\t\t\t\t\t\t\tBuildableViaCapture;\t\t\t\t// Is this buildable due to the capture of a structure of a different faction. This will be false for captured structures of the same faction (ActLike)\n\tbool\t\t\t\t\t\t\tFake;\t\t\t\t\t\t\t\t\t// Is this a fake structure?\n};\n\n\nstruct CNCSidebarStruct {\n\tint\t\t\t\t\t\t\tEntryCount[2];\t\t\t// Counts for the left and right columns\n\tint\t\t\t\t\t\t\tCredits;\t\t\t  \t\t// Amount of currency available (excluding Tiberium)\n\tint\t\t\t\t\t\t\tCreditsCounter;\t\t// Visible credits to display in the sidebar (includes count up/down logic)\n\tint\t\t\t\t\t\t\tTiberium;\t\t\t\t// Amount of Tiberium in reserve\n\tint\t\t\t\t\t\t\tMaxTiberium;\t\t\t// Maximum amount of Tiberium storage available\n\tint\t\t\t\t\t\t\tPowerProduced;\n\tint\t\t\t\t\t\t\tPowerDrained;\n\tint\t\t\t\t\t\t\tMissionTimer;\n\tunsigned int\t  \t\t\tUnitsKilled;\t\t\t\t// Total count of enemy units killed by this player; Includes Infantry, Vehicles, Aircraft\n\tunsigned int\t  \t\t\tBuildingsKilled;        // Total count of enemy structures killed by this player\n\tunsigned int\t  \t\t\tUnitsLost;              // Total count player-owned units killed/lost           \n\tunsigned int\t  \t\t\tBuildingsLost;          // Total count player-owned structures killed/lost      \n\tunsigned int\t\t\t\tTotalHarvestedCredits;  // Complete total of gained credits over the match (does not include starting credits)\n\tbool\t\t\t\t\t\t\tRepairBtnEnabled;\n\tbool\t\t\t\t\t\t\tSellBtnEnabled;\n\tbool\t\t\t\t\t\t\tRadarMapActive;\n\n\tCNCSidebarEntryStruct\tEntries[1];\t\t\t// Variable length column entries\n};\n\n\n\nenum SidebarRequestEnum {\n\tSIDEBAR_REQUEST_START_CONSTRUCTION,\n\tSIDEBAR_REQUEST_HOLD_CONSTRUCTION,\n\tSIDEBAR_REQUEST_CANCEL_CONSTRUCTION,\n\tSIDEBAR_REQUEST_START_PLACEMENT,\n\tSIDEBAR_REQUEST_PLACE,\n\tSIDEBAR_CANCEL_PLACE,\n\tSIDEBAR_CLICK_REPAIR,\n\tSIDEBAR_REQUEST_ENABLE_QUEUE,\n\tSIDEBAR_REQUEST_DISABLE_QUEUE,\n\tSIDEBAR_REQUEST_START_CONSTRUCTION_MULTI,\n\tSIDEBAR_REQUEST_CANCEL_CONSTRUCTION_MULTI\n};\t\n\nenum SuperWeaponRequestEnum {\n\tSUPERWEAPON_REQUEST_PLACE_SUPER_WEAPON\n};\nenum ControlGroupRequestEnum {\n\tCONTROL_GROUP_REQUEST_CREATE,\n\tCONTROL_GROUP_REQUEST_TOGGLE,\n\tCONTROL_GROUP_REQUEST_ADDITIVE_SELECTION,\n};\n\n\n/**************************************************************************************\n** \n**  Input events sent into the DLL\n** \n** \n*/\nenum InputRequestEnum {\n\tINPUT_REQUEST_NONE,\n\tINPUT_REQUEST_MOUSE_MOVE,\n\tINPUT_REQUEST_MOUSE_LEFT_CLICK,\n\tINPUT_REQUEST_MOUSE_RIGHT_DOWN,\n\tINPUT_REQUEST_MOUSE_RIGHT_CLICK,\n\tINPUT_REQUEST_MOUSE_AREA,\n\tINPUT_REQUEST_MOUSE_AREA_ADDITIVE,\n\tINPUT_REQUEST_SELL_AT_POSITION,\n\tINPUT_REQUEST_SELECT_AT_POSITION,\n\tINPUT_REQUEST_COMMAND_AT_POSITION,\n\tINPUT_REQUEST_SPECIAL_KEYS,\n\tINPUT_REQUEST_MOD_GAME_COMMAND_1_AT_POSITION,\n\tINPUT_REQUEST_MOD_GAME_COMMAND_2_AT_POSITION,\n\tINPUT_REQUEST_MOD_GAME_COMMAND_3_AT_POSITION,\n\tINPUT_REQUEST_MOD_GAME_COMMAND_4_AT_POSITION,\n};\n\n\n/**************************************************************************************\n**\n**  Structure Requests Repair, Sell\n**\n**\n*/\nenum StructureRequestEnum {\n\tINPUT_STRUCTURE_NONE,\n\tINPUT_STRUCTURE_REPAIR_START,\n\tINPUT_STRUCTURE_REPAIR,\n\tINPUT_STRUCTURE_SELL_START,\n\tINPUT_STRUCTURE_SELL,\n\tINPUT_STRUCTURE_CANCEL,\n};\n\n\n/**************************************************************************************\n**\n**  Unit Requests Scatter, Select Next, Select Previous, Guard Mode, Stop\n**\n**\n*/\nenum UnitRequestEnum {\n\tINPUT_UNIT_NONE,\n\tINPUT_UNIT_SCATTER,\n\tINPUT_UNIT_SELECT_NEXT,\n\tINPUT_UNIT_SELECT_PREVIOUS,\n\tINPUT_UNIT_GUARD_MODE,\n\tINPUT_UNIT_STOP,\n\tINPUT_UNIT_FORMATION_TOGGLE,\t\t// RA Only\n\tINPUT_UNIT_QUEUED_MOVEMENT_ON, \t// RA Only\n\tINPUT_UNIT_QUEUED_MOVEMENT_OFF,\t// RA Only\n};\n\n\n/**************************************************************************************\n**\n**  Game Action Requests\n**\n**\n*/\nenum GameRequestEnum {\n\tINPUT_GAME_MOVIE_DONE,\n\tINPUT_GAME_LOADING_DONE,\n};\n\n\n/**************************************************************************************\n**\n**  Beacon Requests\n**\n**\n*/\nenum BeaconRequestEnum {\n\tINPUT_BEACON_NONE,\n\tINPUT_BEACON_PLACE,\n};\n\n\n/**************************************************************************************\n**\n**  Special Keys\n**\n**\n*/\nenum SpecialKeyRequestEnum {\n\tINPUT_SPECIAL_KEY_CTRL =\t0b00000001,\n\tINPUT_SPECIAL_KEY_ALT =\t\t0b00000010,\n\tINPUT_SPECIAL_KEY_SHIFT =\t0b00000100,\n};\n\n\n\n/**************************************************************************************\n** \n**  Non-static map data.\n** \n**  Per-cell smudges and overlays. Smudges are used for things like craters and structure bibs that draw under units. \n**  Overlays are things like walls and tiberium that can't move from the cell but aren't flat like smudges.\n** \n** \n*/\nstruct CNCDynamicMapEntryStruct {\n\tchar\t\t\t\t\t\tAssetName[16];\n\tint\t\t\t\t\t\tPositionX;\n\tint\t\t\t\t\t\tPositionY;\n\tint\t\t\t\t\t\tWidth;\n\tint\t\t\t\t\t\tHeight;\n\tshort\t\t\t\t\t\tType;\n\tchar\t\t\t\t\t\tOwner;\n\tint\t\t\t\t\t\tDrawFlags;\n\tunsigned char\t\t\tCellX;\n\tunsigned char\t\t\tCellY;\n\tunsigned char\t\t\tShapeIndex;\n\tbool\t\t\t\t\t\tIsSmudge;\n\tbool\t\t\t\t\t\tIsOverlay;\n\tbool\t\t\t\t\t\tIsResource;\n\tbool\t\t\t\t\t\tIsSellable;\n\tbool\t\t\t\t\t\tIsTheaterShape;\n\tbool\t\t\t\t\t\tIsFlag;\n};\n\nstruct CNCDynamicMapStruct {\n\tbool\t\t\t\t\t\t\tVortexActive;\n\tint\t\t\t\t\t\t\t\tVortexX;\n\tint\t\t\t\t\t\t\t\tVortexY;\n\tint\t\t\t\t\t\t\t\tVortexWidth;\n\tint\t\t\t\t\t\t\t\tVortexHeight;\n\tint\t\t\t\t\t\t\t\tCount;\n\tCNCDynamicMapEntryStruct\tEntries[1];\t\t\t// Variable length\n};\n\n\n\n\n\n/**************************************************************************************\n** \n**  Event data\n** \n**  Used to call back into the GlyphX engine for one-time events like sound effect triggers\n** \n** \n*/\nenum EventCallbackType {\n\tCALLBACK_EVENT_INVALID = -1,\n\tCALLBACK_EVENT_SOUND_EFFECT = 0,\n\tCALLBACK_EVENT_SPEECH,\n\tCALLBACK_EVENT_GAME_OVER,\n\tCALLBACK_EVENT_DEBUG_PRINT,\n\tCALLBACK_EVENT_MOVIE,\n\tCALLBACK_EVENT_MESSAGE,\n\tCALLBACK_EVENT_UPDATE_MAP_CELL,\n\tCALLBACK_EVENT_ACHIEVEMENT,\n\tCALLBACK_EVENT_STORE_CARRYOVER_OBJECTS,\n\tCALLBACK_EVENT_SPECIAL_WEAPON_TARGETTING,\n\tCALLBACK_EVENT_BRIEFING_SCREEN,\n\tCALLBACK_EVENT_CENTER_CAMERA,\n\tCALLBACK_EVENT_PING\n};\n\n\nstruct GameOverMultiPlayerStatsStruct\n{\n\tGameOverMultiPlayerStatsStruct()\n\t:\n\t\tGlyphXPlayerID( 0 ),\n\t\tIsHuman( false ),\n\t\tWasHuman( false ),\n\t\tIsWinner( false ),\n\t\tResourcesGathered( 0 ),\n\t\tTotalUnitsKilled( 0 ),\n\t\tTotalStructuresKilled( 0 ),\n\t\tEfficiency( 0 ),\n\t\tScore( 0 )\n\t{\n\t}\n\t__int64 GlyphXPlayerID;\n\tbool IsHuman;\n\tbool WasHuman;\n\tbool IsWinner;\n\tint ResourcesGathered;\n\tint TotalUnitsKilled;\n\tint TotalStructuresKilled;\n\tint Efficiency; // AKA Economy\n\tint Score;\n};\n\n#define GAME_OVER_MULTIPLAYER_MAX_PLAYERS_TRACKED\t8\n\n\nenum EventCallbackMessageEnum {\n\tMESSAGE_TYPE_DIRECT = 0,\n\tMESSAGE_TYPE_PLAYER_DEFEATED,\n\tMESSAGE_TYPE_COMPUTER_TAUNT,\n\tMESSAGE_TYPE_PLAYER_DISCONNECTED\n};\n\nstruct EventCallbackStruct {\n\n\tEventCallbackStruct::EventCallbackStruct(void) : EventType(CALLBACK_EVENT_INVALID), GlyphXPlayerID(0) { }\n\n\tEventCallbackType EventType;\n\n\t__int64 GlyphXPlayerID;\n\n\tunion {\n\t\t\n\t\tstruct SoundEffectEvent {\n\t\t\tint SFXIndex;\n\t\t\tint Variation;\n\t\t\tint PixelX;\n\t\t\tint PixelY;\n\t\t\tint PlayerID;\t\t//TO_FIX\n\t\t\tchar SoundEffectName[ 16 ];\n\t\t\tint SoundEffectPriority;\n\t\t\tint SoundEffectContext;\n\t\t} SoundEffect;\n\t\t\n\t\tstruct SpeechEvent {\n\t\t\tint SpeechIndex;\n\t\t\tint PlayerID;\t\t//TO_FIX\n\t\t\tchar SpeechName[ 16 ];\n\t\t} Speech;\n\t\t\t  \n\t\tstruct GameOverEvent {\n\t\t\tbool Multiplayer;\n\t\t\t//\n\t\t\t// Single-player data\n\t\t\t//\n\t\t\tbool IsHuman;\n\t\t\tbool PlayerWins; //This should specify player id\n\t\t\tconst char* MovieName;\n\t\t\tconst char* MovieName2;\n\t\t\tconst char* MovieName3;\n\t\t\tconst char* MovieName4;\n\t\t\tconst char* AfterScoreMovieName;\n\t\t\tint Score;\n\t\t\tint Leadership;\n\t\t\tint Efficiency;\n\t\t\tint CategoryTotal;\n\t\t\tint NODKilled;\n\t\t\tint GDIKilled;\n\t\t\tint CiviliansKilled;\n\t\t\tint NODBuildingsDestroyed;\n\t\t\tint GDIBuildingsDestroyed;\n\t\t\tint CiviliansBuildingsDestroyed;\n\t\t\tint RemainingCredits;\n\t\t\tint SabotagedStructureType;\n\t\t\tint TimerRemaining;\n\t\t\t//\n\t\t\t// Multi-player data\n\t\t\t//\n\t\t\tint MultiPlayerTotalPlayers;\n\t\t\tGameOverMultiPlayerStatsStruct MultiPlayerPlayersData[ GAME_OVER_MULTIPLAYER_MAX_PLAYERS_TRACKED ];\n\t\t} GameOver;\n\t\t\n\t\tstruct DebugPrintEvent {\n\t\t\tconst char *PrintString;\n\t\t} DebugPrint;\n\n\t\tstruct MovieEvent {\n\t\t\tconst char* MovieName;\n\t\t\tint Theme;\n\t\t\tbool Immediate;\n\t\t} Movie;\n\n\t\tstruct MessageEvent {\n\t\t\tconst char* Message;\n\t\t\tfloat TimeoutSeconds;\n\t\t\tEventCallbackMessageEnum MessageType;\n\t\t\t__int64 MessageParam1;\n\t\t} Message;\n\n\t\tstruct UpdateMapCellEvent {\n\t\t\tint CellX;\n\t\t\tint CellY;\n\t\t\tchar TemplateTypeName[32];\n\t\t} UpdateMapCell;\n\n\t\tstruct AchievementEvent {\n\t\t\tconst char* AchievementType;\n\t\t\tconst char* AchievementReason;\n\t\t} Achievement;\n\n\t\tstruct StoreCarryoverObjectsEvent {\n\t\t\tconst CarryoverObjectStruct* CarryoverList;\n\t\t} CarryoverObjects;\n\n\t\tstruct SpecialWeaponTargettingEvent {\n\t\t\tint Type;\n\t\t\tint ID;\n\t\t\tchar Name[16];\n\t\t\tDllSuperweaponTypeEnum WeaponType;\n\t\t} SpecialWeaponTargetting;\n\n\t\tstruct CenterCameraEvent {\n\t\t\tint CoordX;\n\t\t\tint CoordY;\n\t\t} CenterCamera;\n\n\t\tstruct PingEvent {\n\t\t\tint CoordX;\n\t\t\tint CoordY;\n\t\t} Ping;\n\t};\n\n};\n\n\n\n\n\n\n\n\n/**************************************************************************************\n** \n**  Multiplayer setup data\n** \n**  Used to pass multiplayer setup info into the C&C code from the GlyphX engine\n** \n** \n*/\n\n\n\nstruct CNCMultiplayerOptionsStruct {\n\t//int MPlayerPrefColor;\t\t\t\t// preferred color index for this player\n\t//int MPlayerColorIdx;\t\t\t\t\t// actual color index of this player\n\t//CnCHousesType MPlayerHouse;\t\t// House of this player (GDI/NOD)\n\t//unsigned char MPlayerLocalID;\t\t// ID of this player\n\tint MPlayerCount;\t\t\t\t\t\t// # of human players in this game\n\tint MPlayerBases;\t\t\t\t\t\t// 1 = bases are on for this scenario\n\tint MPlayerCredits;\t\t\t\t\t// # credits everyone gets\n\tint MPlayerTiberium;\t\t\t\t\t// >0 = tiberium enabled for this scenario\n\tint MPlayerGoodies;\t\t\t\t\t// 1 = goodies enabled for this scenario\n\tint MPlayerGhosts;\t\t\t\t\t// 1 = houses with no players will still play\n\tint MPlayerSolo;\t\t\t\t\t\t// 1 = allows a single-player net game\n\tint MPlayerUnitCount;\t\t\t\t// # units for non-base multiplayer scenarios\n\tbool IsMCVDeploy;\t\t\t\t\t\t// MCV undeploys instead of selling\n\tbool SpawnVisceroids;\t\t\t\t// Do visceroids spawn\n\tbool EnableSuperweapons;\t\t\t// Are superweapons available\n\tbool MPlayerShadowRegrow;\n\tbool MPlayerAftermathUnits;\n\tbool CaptureTheFlag;\n\tbool DestroyStructures;\t\t\t\t// New early win condition via destroying all a player's structures\n\tbool ModernBalance;\n};\n\n\n\nstruct CNCSpiedInfoStruct {\n\tint Power;\n\tint Drain;\n\tint Money;\n};\n\n\nstruct CNCPlayerInfoStruct {\n\tchar\t\t\t\t\tName[64];\n\tunsigned char\t\tHouse;\n\tint\t\t\t\t\tColorIndex;\n\tunsigned __int64\tGlyphxPlayerID;\n\tint\t\t\t\t\tTeam;\n\tint\t\t\t\t\tStartLocationIndex;\n\tunsigned char\t\tHomeCellX;\n\tunsigned char\t\tHomeCellY;\n\tbool\t\t\t\t\tIsAI;\n\tunsigned int\t\tAllyFlags;\n\tbool\t\t\t\t\tIsDefeated;\n\tunsigned int\t\tSpiedPowerFlags;\n\tunsigned int\t\tSpiedMoneyFlags;\n\tCNCSpiedInfoStruct\tSpiedInfo[MAX_HOUSES];\n\tint\t\t\t\t\tSelectedID;\n\tDllObjectTypeEnum\tSelectedType;\n\tDllActionTypeEnum\tActionWithSelected[MAX_EXPORT_CELLS];\n\tunsigned int\t\tActionWithSelectedCount;\n\tunsigned int\t\tScreenShake;\n\tbool\t\t\t\tIsRadarJammed;\n};\n\n\n//\nenum GameRequestType {\n\tGAME_REQUEST_MOVIE_DONE,\n};\n\n\n/**************************************************************************************\n**\n**  Rules configuration data\n**\n**\n*/\nstruct CNCDifficultyDataStruct\n{\n\tfloat FirepowerBias;\n\tfloat GroundspeedBias;\n\tfloat AirspeedBias;\n\tfloat ArmorBias;\n\tfloat ROFBias;\n\tfloat CostBias;\n\tfloat BuildSpeedBias;\n\n\tfloat RepairDelay;\n\tfloat BuildDelay;\n\n\tbool IsBuildSlowdown;\n\tbool IsWallDestroyer;\n\tbool IsContentScan;\n};\n\nstruct CNCRulesDataStruct\n{\n\tCNCDifficultyDataStruct Difficulties[3];\n};\n\n\n/**************************************************************************************\n** \n**  Debug input interface\n** \n** \n*/\n\nenum DebugRequestEnum {\n\tDEBUG_REQUEST_SPAWN_OBJECT,\n\tDEBUG_REQUEST_END_GAME,\n\tDEBUG_REQUEST_UNSHROUD,\n\tDEBUG_REQUEST_SUPERWEAPON_RECHARGE,\n\tDEBUG_REQUEST_KILL_OBJECT,\n\tDEBUG_REQUEST_END_PRODUCTION,\n\tDEBUG_REQUEST_ADD_RESOURCES,\n\tDEBUG_REQUEST_UNLOCK_BUILDABLES,\n\tDEBUG_REQUEST_FORCE_CRASH,\n\tDEBUG_REQUEST_SET_GLOBAL_FLAG,\n};\n\n\n\n\n\n\n/**************************************************************************************\n** \n**  Shroud data.\n** \n**  Per-cell shroud info\n** \n** \n*/\nstruct CNCShroudEntryStruct {\n\tchar\t\t\tShadowIndex;\n\tbool\t\t\tIsVisible;\n\tbool\t\t\tIsMapped;\n\tbool\t\t\tIsJamming;\n};\n\nstruct CNCShroudStruct {\n\tint\t\t\t\t\t\t\tCount;\n\tCNCShroudEntryStruct\t\tEntries[1];\t\t\t// Variable length\n};\n\n\n\n\n\n\n/**************************************************************************************\n**\n**  Occupier data.\n**\n**  Per-cell occupier info\n**\n**\n*/\nstruct CNCOccupierObjectStruct {\n\tDllObjectTypeEnum\t\t\tType;\n\tint\t\t\t\t\t\t\tID;\n};\n\nstruct CNCOccupierEntryHeaderStruct {\n\tint\t\t\t\t\t\t\tCount;\n};\n\nstruct CNCOccupierHeaderStruct {\n\tint\t\t\t\t\t\t\tCount;\n};\n\n\n\n\n/**************************************************************************************\n**\n**  Carryover object.\n**\n**  Used to store object data that persists between missions\n**\n**\n*/\nstruct CarryoverObjectStruct\n{\n\tCarryoverObjectStruct() : Next(0) {}\n\n\tCarryoverObjectStruct* Next;\n\n\tint RTTI;\n\tint Type;\n\tint Cell;\n\tint Strength;\n\tint House;\n};\n\n\n\n\n/*\n** End of strict structure packing\n** \n** \n*/\n#pragma pack(pop)\n\n\n\n#endif //DLL_INTERFACE_H"
  },
  {
    "path": "REDALERT/DLLInterfaceEditor.cpp",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//#include <string>\n#include <stdio.h>\n\n#include\t\"function.h\"\n#include \"externs.h\"\n#include \"DLLInterface.h\"\n#include \"Gadget.h\"\n#include \"defines.h\" // VOC_COUNT, VOX_COUNT\n#include \"SidebarGlyphx.h\"\n#include\t\"mixfile.h\"\n#include \"ccini.H\"\n\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Startup();\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Cleanup();\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map(char* cncdata_directory, char* house_name, int scenario_index, char* east_west, char* variant);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map_By_Scenario_Name(char* cncdata_directory, char* scenario_name);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Clear_Map();\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Map_Stats(int& map_width, int& map_height, int& theater);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data_By_Index(int cell_index, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data(int x, int y, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Texture_Buffer(int x, int y, int& out_width, int& out_height, SAFEARRAY*& out_texture_array);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Scenario_Names(char* cncdata_directory);\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Template_Data(int template_type_index, SAFEARRAY*& template_points);\n\nint LoadScenario();\n\nextern int DLL_Startup(const char * command_line);\n\nchar EditorMapINIBuffer[SHAPE_BUFFER_SIZE];\nbool EditorMapInitialized = false;\n\nconst static int EDITOR_COMMMAND_SUCCESS = 0;\nconst static int EDITOR_COMMMAND_FAILURE = 1;\n\nconst char* CD1Path = \"\\\\RED_ALERT\\\\CD1\\\\\";\nconst char* CD2Path = \"\\\\RED_ALERT\\\\COUNTERSTRIKE\\\\\";\nconst char* CD3Path = \"\\\\RED_ALERT\\\\AFTERMATH\\\\\";\n\nchar RedAlertINI[_MAX_PATH];\n\n/**************************************************************************************************\n* CNC_Editor_Startup\n* Initializes the system to allow map loading for the editor\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Startup()\n{\n\t/*\n\tBlackPalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];\n\tGamePalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];\n\tOriginalPalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];\n\tWhitePalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];\n\tmemset(WhitePalette, 63, 768);\n\n\n\tSet_Palette(GamePalette);\n\n\tTheaterData = 0;\n\tTheaterIcons = 0;\n\tLowTheaterData = 0;\n\t*/\n\n\tRunningFromEditor = true;\n\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\n/**************************************************************************************************\n* CNC_Editor_Cleanup\n* Cleans up systems initialized by the editor\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Cleanup()\n{\n\t/*\n\tif (BlackPalette)\n\t{\n\t\tdelete[] BlackPalette;\n\t}\n\n\tif (GamePalette)\n\t{\n\t\tdelete[] GamePalette;\n\t}\n\n\tif (OriginalPalette)\n\t{\n\t\tdelete[] OriginalPalette;\n\t}\n\tif (WhitePalette)\n\t{\n\t\tdelete[] WhitePalette;\n\t}\n\t*/\n\n\treturn EDITOR_COMMMAND_SUCCESS;\n}\n/**************************************************************************************************\n* CNC_Editor_Load_Mix_Files\n* Loads all the Mix files for Tiberian Dawn\n**************************************************************************************************/\nvoid CNC_Editor_Load_Mix_Files()\n{\n\tconst char* MixFileNames[] =\n\t{\n\t\t\"MAIN.MIX\",\n\t\t\"REDALERT.MIX\",\n\t\t\"EXPAND2.MIX\",\n\t\t\"EXPAND.MIX\",\n\t\t\"HIRES1.MIX\",\n\t\t//\"LORES1.MIX\"\n\t\t\n\t\t\"GENERAL.MIX\",\t\t\n\t\t\n\t\t\"LOCAL.MIX\",\n\t\t\"HIRES.MIX\",\n\t\t\"NCHIRES.MIX\",\n\t\t\"CONQUER.MIX\",\n\t\t\n\t\t\"RUSSIAN.MIX\",\n\t\t\"ALLIES.MIX\",\n\n\t\t\"SNOW.MIX\",\n\t\t\"TEMPERAT.MIX\",\n\t\t\"INTERIOR.MIX\",\n\t};\n\n\tint count = sizeof(MixFileNames) / sizeof(MixFileNames[0]);\n\n\tfor (int i = count - 1; i >= 0; --i)\n\t{\n\t\tMFCD::Free(MixFileNames[i]);\n\t}\n\n\tfor (int i = 0; i < count; ++i)\n\t{\n\t\tMFCD* file = new MFCD(MixFileNames[i], &FastKey);\n\t\tfile->Cache();\n\t\t\n\t}\n\t\n}\n\n/**************************************************************************************************\n* CNC_Editor_Setup_Content_Directory\n* Sets up where the system should load map data from.\n*\n* cncdata_directory: path of the base CNC data directory\n* CD1: if true, consider this disc 1, otherwise consider this disc 2.\n**************************************************************************************************/\nvoid CNC_Editor_Setup_Content_Directory(char* cncdata_directory, int CD, char (&content_directory)[_MAX_PATH])\n{\n\n\tswitch (CD)\n\t{\n\tdefault:\n\tcase 1:\n\t\tsprintf(content_directory, \"%s%s\", cncdata_directory, CD1Path);\n\t\tbreak;\n\tcase 2:\n\t\tsprintf(content_directory, \"%s%s\", cncdata_directory, CD2Path);\n\t\tbreak;\n\tcase 3:\n\t\tsprintf(content_directory, \"%s%s\", cncdata_directory, CD3Path);\n\t\tbreak;\n\t}\n\n\t//Setup red alert path\n\tsprintf(RedAlertINI, \"%sREDALERT.INI\",content_directory);\n\n\tif (strlen(content_directory) != 0) {\n\t\tCCFileClass::Clear_Search_Drives();\n\t\tCCFileClass::Reset_Raw_Path();\n\t\tchar *dll_dir = strdup(content_directory);\n\t\tCCFileClass::Set_Search_Drives(dll_dir);\n\t\tfree(dll_dir);\n\t}\n}\n\n/**************************************************************************************************\n* CNC_Editor_Load_Map\n* Loads the map with the given parameters.\n*\n* cncdata_directory: path of the base CNC data directory\n* faction: the name of the faction we are loading the map for\n* scenario_index: int scenario index\n* east_west:\n* variant:\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map(\n\tchar* cncdata_directory,\n\tchar* house_name,\n\tint scenario_index,\n\tchar* east_west,\n\tchar* variant)\n{\n\n\tCNC_Editor_Clear_Map();\n\n\tScenarioPlayerType scen_player;\n\tint CD = 1;\n\tif (stricmp(house_name, \"SPAIN\") == 0) {\n\t\tscen_player = SCEN_PLAYER_SPAIN;\n\t\tWhom = HOUSE_GOOD;\n\n\t\tif (scenario_index >= 40)\n\t\t{\n\t\t\tCD = 3;\n\t\t}\n\t\telse if (scenario_index >= 15)\n\t\t{\n\t\t\tCD = 2;\n\t\t}\n\t}\n\n\tif (stricmp(house_name, \"GREECE\") == 0 || stricmp(house_name, \"ALLY\") == 0) {\n\t\tscen_player = SCEN_PLAYER_GREECE;\n\t\tWhom = HOUSE_GOOD;\n\n\t\tif (scenario_index >= 40)\n\t\t{\n\t\t\tCD = 3;\n\t\t}\n\t\telse if (scenario_index >= 15)\n\t\t{\n\t\t\tCD = 2;\n\t\t}\n\t}\n\n\tif (stricmp(house_name, \"USSR\") == 0) {\n\t\tscen_player = SCEN_PLAYER_USSR;\n\t\tWhom = HOUSE_BAD;\n\n\t\tif (scenario_index >= 40)\n\t\t{\n\t\t\tCD = 3;\n\t\t}\n\t\telse if (scenario_index >= 15)\n\t\t{\n\t\t\tCD = 2;\n\t\t}\n\t}\n\n\tif (stricmp(house_name, \"MULTI\") == 0)\n\t{\n\t\tscen_player = SCEN_PLAYER_MPLAYER;\n\t\tWhom = HOUSE_MULTI1;\n\n\t\tif (scenario_index >= 25)\n\t\t{\n\t\t\tCD = 3;\n\t\t}\n\n\t}\n\n\tif (stricmp(house_name, \"JAPAN\") == 0)\n\t{\n\t\tscen_player = SCEN_PLAYER_JP;\n\t\tWhom = HOUSE_JP;\n\t}\n\n\tchar content_directory[_MAX_PATH];\n\n\tCNC_Editor_Setup_Content_Directory(cncdata_directory, CD, content_directory);\n\n\tchar command_line[_MAX_PATH];\n\tsprintf(command_line, \"-CD%s\", content_directory);\n\n\tDLL_Startup(command_line);\n\n\tScen.Scenario = scenario_index;\n\tScenarioDirType scen_dir;\n\tBuildLevel = 7;\n\n\tif (stricmp(east_west, \"w\") == 0)\n\t{\n\t\tscen_dir = SCEN_DIR_WEST;\n\t}\n\telse\n\t{\n\t\tscen_dir = SCEN_DIR_EAST;\n\t}\n\n\tScenarioVarType variant_enum;\n\n\tif (stricmp(variant, \"b\") == 0)\n\t{\n\t\tvariant_enum = SCEN_VAR_B;\n\t}\n\telse if (stricmp(variant, \"c\") == 0)\n\t{\n\t\tvariant_enum = SCEN_VAR_C;\n\t}\n\telse if (stricmp(variant, \"d\") == 0)\n\t{\n\t\tvariant_enum = SCEN_VAR_D;\n\t}\n\telse\n\t{\n\t\tvariant_enum = SCEN_VAR_A;\n\t}\n\n\tScen.Set_Scenario_Name(Scen.Scenario, scen_player, scen_dir, (ScenarioVarType)variant_enum);\n\n\treturn LoadScenario();\n}\n\n/**************************************************************************************************\n* CNC_Editor_Load_Map_By_Scenario_Name\n* Loads the map with the given parameters.\n*\n* cncdata_directory: path of the base CNC data directory\n* scenario_name: name of the scnario to load\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map_By_Scenario_Name(\n\tchar* cncdata_directory,\n\tchar* scenario_name)\n{\n\tint CD = 3; // Always use the aftermath cd\n\tif (strnlen(scenario_name, _MAX_PATH) >= 3 && (scenario_name[2] == 'a' || scenario_name[2] == 'A'))\n\t{\n\t\t// Ant missions are CD 2\n\t\tCD = 2;\n\t}\n\n\tCNC_Editor_Clear_Map();\n\n\tchar content_directory[_MAX_PATH];\n\n\tCNC_Editor_Setup_Content_Directory(cncdata_directory, CD, content_directory);\n\n\tchar command_line[_MAX_PATH];\n\tsprintf(command_line, \"-CD%s\", content_directory);\n\n\tDLL_Startup(command_line);\n\n\tsnprintf(Scen.ScenarioName, _MAX_FNAME + _MAX_EXT, \"%s.ini\", scenario_name);\n\n\treturn LoadScenario();\n}\n\nint LoadScenario()\n{\n\tCCFileClass file(Scen.ScenarioName);\n\t\n\tif (!file.Is_Available())\n\t{\n\t\treturn(EDITOR_COMMMAND_FAILURE);\n\t}\n\n\n\tCCINIClass ini;\n\tint result = ini.Load(file,true);\n\tif (result == 0)\n\t{\n\t\treturn(EDITOR_COMMMAND_FAILURE);\n\t}\n\n\tif (result == 2) \n\t{\n\t\t//\t\tif (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMake a special exception so that multiplayer maps from 1 through\n\t\t\t\t\t**\t24 will not care if the message digest is in error. All other\n\t\t\t\t\t**\tmaps will abort the scenario load.\n\t\t\t\t\t*/\n\t\tif (Scen.ScenarioName[2] != 'M' || Scen.Scenario >= 25) \n\t\t{\n\t\t\treturn(EDITOR_COMMMAND_FAILURE);\n\t\t}\n\t}\n\n\tconst char * const BASIC = \"Basic\";\n\tNewINIFormat = ini.Get_Int(BASIC, \"NewINIFormat\", 0);\n\n\tMap.One_Time();\n\tMap.Read_INI(ini);\n\n\tEditorMapInitialized = true;\n\t\n\treturn EDITOR_COMMMAND_SUCCESS;\n}\n\n/**************************************************************************************************\n*\tCNC_Editor_Clear_Map\n*\tDeletes the data for the currently loaded map.\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Clear_Map()\n{\n\tif (EditorMapInitialized)\n\t{\n\t\tMap.Init_Clear();\n\t\tEditorMapInitialized = false;\n\n\t\treturn EDITOR_COMMMAND_SUCCESS;\n\t}\n\telse\n\t{\n\t\treturn EDITOR_COMMMAND_FAILURE;\n\t}\n\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\n/**************************************************************************************************\n* CNC_Editor_Get_Map_Stats\n* Gets the stats for the currently loaded map\n*\n* map_width: out parameter storing the width of the map\n* map_height: out parameter storing the height of the map\n* theater: out paramter storing the theater of the map\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Map_Stats(int& map_width, int& map_height, int& theater)\n{\n\tif (EditorMapInitialized)\n\t{\n\t\tmap_width = Map.MapCellWidth + 1;\n\t\tmap_height = Map.MapCellHeight + 1;\n\t\ttheater = Scen.Theater;\n\t\treturn EDITOR_COMMMAND_SUCCESS;\n\t}\n\n\tmap_width = -1;\n\tmap_height = -1;\n\ttheater = -1;\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\n/**************************************************************************************************\n* CNC_Editor_Get_Cell_Data_By_Index\n* Get the data from the given cell.\n*\n* cell_index: The index of the desired cell.\n* cell_name: out buffer to be filled with the name of the given cell.\n* cell_name_size: the size of the cell name buffer.\n*\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data_By_Index(int cell_index, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index)\n{\n\tCELL index = (CELL)cell_index;\n\n\tCellClass * cellptr = &Map[index];\n\n\tcell_name[0] = 0;\n\tint icon = 0;\n\tvoid *image_data = 0;\n\n\tchar template_name[10];\n\tif (cellptr->Get_Template_Info(template_name, icon, image_data))\n\t{\n\t\tsnprintf(cell_name, cell_name_size, \"%s-%04d\", template_name, icon);\n\n\t\ttemplate_type = cellptr->TType;\n\t\ttemplate_icon_index = icon;\n\n\t\t//TemplateTypeClass::As_Reference(ptr->TType).\n\n\t\treturn EDITOR_COMMMAND_SUCCESS;\n\t}\n\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\n/**************************************************************************************************\n* CNC_Editor_Get_Cell_Data\n* Get the data from the given cell.\n*\n* x,y: The corrdinates of the desired cell.\n* cell_name: out buffer to be filled with the name of the given cell.\n* cell_name_size: the size of the cell name buffer.\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\n\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data(int x, int y, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index)\n{\n\tif (!EditorMapInitialized)\n\t{\n\t\treturn EDITOR_COMMMAND_FAILURE;\n\t}\n\n\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_HEIGHT) {\n\t\tmap_cell_height++;\n\t}\n\n\tCELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);\n\n\treturn CNC_Editor_Get_Cell_Data_By_Index((int)cell, cell_name, cell_name_size, template_type, template_icon_index);\n}\n\n/**************************************************************************************************\n* CNC_Editor_Get_Cell_Texture_Buffer\n*\n* x,y:\n* out_width, out_height: dimensions of the outputed texture array\n* out_texture_array: output array of unsigned chars storing the color data for the requested object,\n*\t\t\t\t\t\t\tevery 3 chars is a set of RGB values\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Texture_Buffer(int x, int y, int& out_width, int& out_height, SAFEARRAY*& out_texture_array)\n{\n\n\tint map_cell_x = Map.MapCellX;\n\tint map_cell_y = Map.MapCellY;\n\tint map_cell_width = Map.MapCellWidth;\n\tint map_cell_height = Map.MapCellHeight;\n\n\tif (map_cell_x > 0) {\n\t\tmap_cell_x--;\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_width < MAP_MAX_CELL_WIDTH) {\n\t\tmap_cell_width++;\n\t}\n\n\tif (map_cell_y > 0) {\n\t\tmap_cell_y--;\n\t\tmap_cell_height++;\n\t}\n\n\tif (map_cell_height < MAP_MAX_CELL_HEIGHT) {\n\t\tmap_cell_height++;\n\t}\n\n\tCELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);\n\tCellClass * cellptr = &Map[cell];\n\n\tchar cell_name[_MAX_PATH];\n\n\tint icon = 0;\n\tvoid *image_data = 0;\n\tif (cellptr->Get_Template_Info(cell_name, icon, image_data))\n\t{\n\t\tGraphicBufferClass temp_gbuffer(24, 24);\n\t\tGraphicViewPortClass\ttemp_viewport(&temp_gbuffer, 0, 0, 24, 24);\n\n\t\tWindowList[WINDOW_CUSTOM][WINDOWX] = 0;\n\t\tWindowList[WINDOW_CUSTOM][WINDOWY] = 0;\n\t\tWindowList[WINDOW_CUSTOM][WINDOWWIDTH] = 24;\n\t\tWindowList[WINDOW_CUSTOM][WINDOWHEIGHT] = 24;\n\n\t\ttemp_viewport.Draw_Stamp(image_data, icon, 0, 0, NULL, WINDOW_CUSTOM);\n\n\t\tout_width = temp_viewport.Get_Width();\n\t\tout_height = temp_viewport.Get_Height();\n\n\t\tconst int COLOR_SIZE = 3;\n\n\t\tSAFEARRAYBOUND  Bound;\n\t\tBound.lLbound = 0;\n\t\tBound.cElements = out_width * out_height * COLOR_SIZE;\n\n\t\tout_texture_array = SafeArrayCreate(VT_UI1, 1, &Bound);\n\n\t\tunsigned char* out_buffer;\n\n\t\tHRESULT hr = SafeArrayAccessData(out_texture_array, (void **)&out_buffer);\n\t\tif (SUCCEEDED(hr))\n\t\t{\n\t\t\tGraphicBufferClass* Graphic_Buffer = temp_viewport.Get_Graphic_Buffer();\n\n\t\t\tint VP_Scan_Line = temp_viewport.Get_Width() + temp_viewport.Get_XAdd();\n\n\t\t\tchar * start_ptr;\n\t\t\tstart_ptr = (char *)Graphic_Buffer->Get_Buffer();\n\t\t\tstart_ptr += ((temp_viewport.Get_YPos() * VP_Scan_Line) + temp_viewport.Get_XPos());\n\n\t\t\tfor (int y = 0; y < out_height; ++y)\n\t\t\t{\n\t\t\t\tunsigned char* scanline_ptr = (unsigned char*)start_ptr + y * VP_Scan_Line;\n\t\t\t\tunsigned char* out_buffer_y_ptr = out_buffer + (y * out_width * COLOR_SIZE);\n\t\t\t\tfor (int x = 0; x < out_width; ++x)\n\t\t\t\t{\n\t\t\t\t\tunsigned char* pallete_index_ptr = scanline_ptr + x;\n\t\t\t\t\tunsigned char* out_buffer_ptr = out_buffer_y_ptr + (x * COLOR_SIZE);\n\n\t\t\t\t\tint palette_index = (*pallete_index_ptr);\n\t\t\t\t\tout_buffer_ptr[0] = ((unsigned char)GamePalette[palette_index].Red_Component());\n\t\t\t\t\tout_buffer_ptr[1] = ((unsigned char)GamePalette[palette_index].Green_Component());\n\t\t\t\t\tout_buffer_ptr[2] = ((unsigned char)GamePalette[palette_index].Blue_Component());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSafeArrayUnaccessData(out_texture_array);\n\n\t\t\treturn EDITOR_COMMMAND_SUCCESS;\n\t\t}\n\t}\n\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\n/**************************************************************************************************\n* CNC_Editor_Get_Template_Data\n* Get the data from the given tile template type.\n*\n* template_type_index: The index of the template type to use. should come from the Get_Cell_Data function.\n* template_positions: Out buffer to be filled with the list of positions of the tiles as offsets from the origin of the template.\n*\t\t\t\t\t\t\tThis data is store is an X, Y, X, Y, X, Y format.\n*\n* returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure\n**************************************************************************************************/\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Template_Data(int template_type_index, SAFEARRAY*& template_points)\n{\n\tif (template_type_index >= TEMPLATE_COUNT || template_type_index == TEMPLATE_NONE)\n\t{\n\t\treturn EDITOR_COMMMAND_FAILURE;\n\t}\n\n\tconst TemplateTypeClass& template_type = TemplateTypeClass::As_Reference((TemplateType)template_type_index);\n\tif (template_type.Get_Image_Data() == nullptr)\n\t{\n\t\treturn EDITOR_COMMMAND_FAILURE;\n\t}\n\n\n\tshort const * occupy_list = template_type.Occupy_List();\n\n\tshort const * counter = occupy_list;\n\twhile (counter && *counter != REFRESH_EOL)\n\t{\n\t\tcounter++;\n\t}\n\n\tint occupy_list_size = counter - occupy_list;\n\n\n\tSAFEARRAYBOUND  bounds;\n\tbounds.lLbound = 0;\n\tbounds.cElements = occupy_list_size * 2;\n\ttemplate_points = SafeArrayCreate(VT_I4, 1, &bounds);\n\n\tint *pData;\n\tHRESULT hr = SafeArrayAccessData(template_points, (void **)&pData);\n\tif (SUCCEEDED(hr))\n\t{\n\t\tfor (int i = 0; i < occupy_list_size; i++)\n\t\t{\n\t\t\tCELL cell = occupy_list[i];\n\n\t\t\tint x = Cell_X(cell);\n\t\t\tint y = Cell_Y(cell);\n\n\t\t\tpData[i * 2] = x;\n\t\t\tpData[i * 2 + 1] = y;\n\t\t}\n\n\t\tSafeArrayUnaccessData(template_points);\n\n\t\treturn EDITOR_COMMMAND_SUCCESS;\n\t}\n\n\treturn EDITOR_COMMMAND_FAILURE;\n}\n\nextern \"C\" __declspec(dllexport) int __cdecl CNC_Editor_Get_Scenario_Names(char* cncdata_directory)\n{\n\tchar content_directory[_MAX_PATH];\n\n\tCNC_Editor_Setup_Content_Directory(cncdata_directory,false, content_directory);\n\n\tchar command_line[_MAX_PATH];\n\tsprintf(command_line, \"-CD%s\", content_directory);\n\tDLL_Startup(command_line);\n\n\tchar team_ids[] =\n\t{\n\t\t'a',\n\t\t'b',\n\t\t'c',\n\t\t'd',\n\t\t'e',\n\t\t'f',\n\t\t'g',\n\t\t'h',\n\t\t'i',\n\t\t'j',\n\t\t'k',\n\t\t'l',\n\t\t'm',\n\t\t'n',\n\t\t'o',\n\t\t'p',\n\t\t'q',\n\t\t'r',\n\t\t's',\n\t\t't',\n\t\t'u',\n\t\t'v',\n\t\t'w',\n\t\t'x',\n\t\t'y',\n\t\t'z',\n\t};\n\t/*\n\t{\n\t\t'g',\n\t\t'a',\n\t\t'u',\n\t\t'm'\n\t};\n\t*/\n\tconst int team_count = sizeof(team_ids) / sizeof(char);\n\n\tchar direction_ids[] =\n\t{\n\t\t'e',\n\t\t'w',\n\t};\n\tconst int direction_count = sizeof(direction_ids) / sizeof(char);\n\n\tchar variant_ids[] =\n\t{\n\t\t'a',\n\t\t'b',\n\t\t'c',\n\t\t'd',\n\t\t'e',\n\t\t'f',\n\t\t'g',\n\t\t'h',\n\t\t'i',\n\t\t'j',\n\t\t'k',\n\t\t'l',\n\t\t'm',\n\t\t'n',\n\t\t'o',\n\t\t'p',\n\t\t'q',\n\t\t'r',\n\t\t's',\n\t\t't',\n\t\t'u',\n\t\t'v',\n\t\t'w',\n\t\t'x',\n\t\t'y',\n\t\t'z',\n\t};\n\t/*\n\t{\n\t\t'a',\n\t\t'b',\n\t\t'c',\n\t\t'd'\n\t};\n\t*/\n\tconst int variant_count = sizeof(variant_ids) / sizeof(char);\n\n\tconst int min_scenario_index = 1;\n\tconst int max_scenario_index = 99;\n\n\tchar scenario_name[_MAX_FNAME + _MAX_EXT];\n\tchar file_name[_MAX_FNAME + _MAX_EXT];\n\n\tFILE * names_file = fopen(\"d:\\\\RA_Disk2.txt\", \"w+\");\n\n\tfor (int team_index = 0; team_index < team_count; team_index++)\n\t{\n\t\tfor (int scenario_index = min_scenario_index; scenario_index <= max_scenario_index; ++scenario_index)\n\t\t{\n\t\t\tfor (int direction_index = 0; direction_index < direction_count; direction_index++)\n\t\t\t{\n\t\t\t\tfor (int variant_index = 0; variant_index < variant_count; variant_index++)\n\t\t\t\t{\n\t\t\t\t\tsprintf(scenario_name, \"sc%c%.2d%c%c\",\n\t\t\t\t\t\tteam_ids[team_index],\n\t\t\t\t\t\tscenario_index,\n\t\t\t\t\t\tdirection_ids[direction_index],\n\t\t\t\t\t\tvariant_ids[variant_index]);\n\n\t\t\t\t\tsprintf(file_name, \"%s.INI\", scenario_name);\n\t\t\t\t\tCCFileClass file(file_name);\n\t\t\t\t\tif (file.Is_Available())\n\t\t\t\t\t{\n\t\t\t\t\t\tfprintf(names_file, \"%s\\n\", scenario_name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfclose(names_file);\n\n\treturn EDITOR_COMMMAND_SUCCESS;\n}"
  },
  {
    "path": "REDALERT/DLLInterfaceVersion.h",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#pragma once\n\n#ifndef DLL_INTERFACE_VERSION_H\n#define DLL_INTERFACE_VERSION_H\n\n\n/*\n** DLL Interface version\n** \n** \n** \n*/\n#define CNC_DLL_API_VERSION\t\t0x102\n\n\n\n#endif //DLL_INTERFACE_VERSION_H\n"
  },
  {
    "path": "REDALERT/DOOR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DOOR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DOOR.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/11/95                                                     *\n *                                                                                             *\n *                  Last Update : June 14, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DoorClass::AI -- Handles the door processing logic.                                       *\n *   DoorClass::Close_Door -- Try to close the unit's door.                                    *\n *   DoorClass::DoorClass -- Constructor for the DoorClass object.                             *\n *   DoorClass::Door_Stage -- Fetches the current door animation frame.                        *\n *   DoorClass::Open_Door -- Opens the door for this unit.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * DoorClass::DoorClass -- Constructor for the DoorClass object.                               *\n *                                                                                             *\n *    This constructor sets the door to an initial closed state.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nDoorClass::DoorClass(void)\n{\n\tState = IS_CLOSED;\n\tIsToRedraw = false;\n\tStages = 0;\n}\n\n\n/***********************************************************************************************\n * DoorClass::AI -- Handles the door processing logic.                                         *\n *                                                                                             *\n *    This routine should be called every game frame. It handles the door closing and opening  *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DoorClass::AI(void)\n{\n\tif (Control.Graphic_Logic()) {\n\t\tif (Control.Fetch_Stage() >= Stages) {\n\t\t\tControl.Set_Rate(0);\n\t\t\tswitch (State) {\n\t\t\t\tcase IS_OPENING:\n\t\t\t\t\tState = IS_OPEN;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase IS_CLOSING:\n\t\t\t\t\tState = IS_CLOSED;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tIsToRedraw = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * DoorClass::Open_Door -- Opens the door for this unit.                                       *\n *                                                                                             *\n *    This routine will perform the door open operation for this unit. It will control vehicle *\n *    rotation if necessary.                                                                   *\n *                                                                                             *\n * INPUT:   rate     -- The animation rate (delay) to use for the door animation logic.        *\n *                                                                                             *\n *          stages   -- The number of animations stages that this door must pass through.      *\n *                                                                                             *\n * OUTPUT:  Was action initiated to open the door?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DoorClass::Open_Door(int rate, int stages)\n{\n\tswitch (State) {\n\t\tcase IS_CLOSED:\n\t\tcase IS_CLOSING:\n\t\t\tState = IS_OPENING;\n\t\t\tStages = stages-1;\n\t\t\tControl.Set_Stage(0);\n\t\t\tControl.Set_Rate(rate);\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DoorClass::Close_Door -- Try to close the unit's door.                                      *\n *                                                                                             *\n *    This routine will attempt to close the unit's door. If the door is already closed or     *\n *    in the process of closing, then no action is performed.                                  *\n *                                                                                             *\n * INPUT:   rate     -- The animation rate (delay) to use for the door animation logic.        *\n *                                                                                             *\n *          stages   -- The number of animations stages that this door must pass through.      *\n *                                                                                             *\n * OUTPUT:  Action was initiated to close the door?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DoorClass::Close_Door(int rate, int stages)\n{\n\tswitch (State) {\n\t\tcase IS_OPEN:\n\t\tcase IS_OPENING:\n\t\t\tState = IS_CLOSING;\n\t\t\tStages = stages-1;\n\t\t\tControl.Set_Stage(0);\n\t\t\tControl.Set_Rate(rate);\n\t\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DoorClass::Door_Stage -- Fetches the current door animation frame.                          *\n *                                                                                             *\n *    Use this routine to fetch the current door animation frame number. Frame zero is the     *\n *    closed frame and frame 'N' is the open frame. If the door is in the process of opening   *\n *    or closing, the appropriate frame number is used. 'N' is defined as the number of        *\n *    stages in the animation minus 1 (e.g., a four frame animation will return a door stage   *\n *    number between 0 and 3, inclusive).                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the door animation frame number.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint DoorClass::Door_Stage(void) const\n{\n\tswitch (State) {\n\t\tcase IS_CLOSING:\n\t\t\treturn((Stages-1) - Control.Fetch_Stage());\n\n\t\tcase IS_CLOSED:\n\t\t\treturn(0);\n\n\t\tcase IS_OPENING:\n\t\t\treturn(Control.Fetch_Stage());\n\n\t\tcase IS_OPEN:\n\t\t\treturn(Stages-1);\n\t}\n\treturn(0);\n}\n"
  },
  {
    "path": "REDALERT/DOOR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DOOR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DOOR.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/11/95                                                     *\n *                                                                                             *\n *                  Last Update : June 11, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DOOR_H\n#define DOOR_H\n\nclass DoorClass\n{\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the animation control handler.\n\t\t*/\n\t\tStageClass Control;\n\n\t\t/*\n\t\t**\tThis is the recorded number of stages of the current\n\t\t**\tdoor animation process.\n\t\t*/\n\t\tunsigned char Stages;\n\n\t\t/*\n\t\t**\tThis is the door state.\n\t\t*/\n\t\tenum {\n\t\t\tIS_CLOSED,\t\t// Door is closed.\n\t\t\tIS_OPENING,\t\t// Door is in the process of opening.\n\t\t\tIS_OPEN,\t\t\t// Door is fully open.\n\t\t\tIS_CLOSING\t\t//\tDoor is in the process of closing.\n\t\t} State;\n\n\t\t/*\n\t\t**\tIf the animation for this door indicates that the object it is\n\t\t**\tattached to should be redrawn, then this flag will be true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\tpublic:\n\t\tDoorClass(void);\n\t\tDoorClass(NoInitClass const & x) : Control(x) {};\n\n\t\tbool Time_To_Redraw(void) {return(IsToRedraw);};\n\t\tvoid Clear_Redraw_Flag(void) {IsToRedraw = false;};\n\t\tvoid AI(void);\n\t\tint Door_Stage(void) const;\n\t\tbool Is_Door_Opening(void) const {return(State == IS_OPENING);};\n\t\tbool Is_Door_Closing(void) const {return(State == IS_CLOSING);};\n\t\tbool Open_Door(int rate, int stages);\n\t\tbool Close_Door(int rate, int stages);\n\t\tbool Is_Door_Open(void) const {return(State == IS_OPEN);};\n\t\tbool Is_Door_Closed(void) const {return(State == IS_CLOSED);};\n\t\tbool Is_Ready_To_Open(void) const;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/DPMI.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\dpmi.cpv   4.41   04 Jul 1996 16:12:42   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DPMI.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0)\n#ifdef __FLAT__\n#pragma inline\n#endif\n\n//#include\t\"function.h\"\n#include \"dpmi.h\"\n\n#ifndef __FLAT__\n\nvoid DOSSegmentClass::Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\tif (!size) return;\n\n\tunsigned short ssel = src.Selector;\n\tunsigned short dsel = dest.Selector;\n\n\tasm {\n\t\tpush\tes\n\t\tpush\tds\n\n\t\tmov\tsi,soffset\n\t\tmov\tdi,doffset\n\t\tmov\tcx,size\n\t\tmov\tax,ssel\n\t\tmov\tdx,dsel\n\t\tmov\tds,ax\n\t\tmov\tes,dx\n\t}\nagain:\n\tasm {\n\t\tmov\tal,ds:[si]\n\t\tmov\tah,es:[di]\n\t\tmov\tds:[si],ah\n\t\tmov\tes:[di],al\n\t\tinc\tdi\n\t\tinc\tsi\n\t\tdec\tcx\n\t\tjnz\tagain\n\n\t\tpop\tds\n\t\tpop\tes\n\t}\n}\n#endif\n\n\nvoid DOSSegmentClass::Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\textern void dss_swap(char *src, char *dest, int size);\n\n\t#pragma aux dss_swap = \t\t\\\n\t\"again: mov\tal,[esi]\"\t\\\n\t\t\"mov\tah,[edi]\"\t\t\\\n\t\t\"mov\t[esi],ah\"\t\t\\\n\t\t\"stosb\"\t\t\t\t\t\\\n\t\t\"inc\tesi\"\t\t\t\t\\\n\t\t\"loop\tagain\"\t\t\t\\\n\t\tparm\t[esi] [edi] [ecx]\t\\\n\t\tmodify [ax];\n\n\tif (!size) return;\n\tdss_swap((char *)(src.Selector + soffset), (char *)(dest.Selector + doffset), size);\n}\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size)\n{\n\textern void dss_copy(char *src, char *dest, int size);\n\t#pragma aux dss_copy = \t\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcopskip1\"\t\t\\\n\t\t\"rep \t\tmovsd\"\t\t\t\\\n\"copskip1: mov ecx,ebx\"\t\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcopskip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"copskip2:\"\t\t\t\t\t\t\t\\\n\t\tparm\t[esi edi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy((char *)(src.Selector + soffset), (char *)(dest.Selector + doffset), size);\n}\n#endif\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy_To(void *source, int dest, int size)\n{\n\textern void dss_copy_to(void *src, (void *)dest, int size);\n\n\t#pragma aux dss_copy_to =\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcop2skip1\"\t\t\\\n\t\t\"rep\t\tmovsd\"\t\t\t\\\n\"cop2skip1: mov ecx,ebx\"\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcop2skip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"cop2skip2:\"\t\t\t\t\t\t\\\n\t\tparm\t[esi edi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy_to(src, (void *)(Selector + dest), size);\n\n}\n#endif\n\n#ifdef OBSOLETE\nvoid DOSSegmentClass::Copy_From(void *dest, int source, int size)\n{\n\textern void dss_copy_from(void *dest, (void *)source, int size);\n\n\t#pragma aux dss_copy_from =\t\\\n\t\t\"mov\t\tebx,ecx\"\t\t\t\\\n\t\t\"shr\t\tecx,2\"\t\t\t\\\n\t\t\"jecxz\tcopfskip1\"\t\t\\\n\t\t\"rep\t\tmovsd\"\t\t\t\\\n\"copfskip1: mov ecx,ebx\"\t\t\\\n\t\t\"and\t\tecx,3\"\t\t\t\\\n\t\t\"jecxz\tcopfskip2\"\t\t\\\n\t\t\"rep\t\tmovsb\"\t\t\t\\\n\"copfskip2:\"\t\t\t\t\t\t\\\n\t\tparm\t[edi esi ecx]\t\t\\\n\t\tmodify [ebx];\n\n\tif (!size) return;\n\tdss_copy_from(dest, (void *)(Selector + source), size);\n}\n#endif\n#endif"
  },
  {
    "path": "REDALERT/DPMI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\dpmi.h_v   4.43   05 Jul 1996 17:58:40   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DPMI.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef DPMI_Hx\n#define DPMI_Hx\n#include\t<dos.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n//#include\t<mem.h>\n\n\nextern void output(short port, short data);\n\n\nclass DOSSegmentClass {\n\t\t/*\n\t\t**\tThis is the selector/segment value. In real mode it is the segment, in protected\n\t\t**\tmode it is the selector (also 16 bits). This value is moved into DS or ES when\n\t\t**\taccessing memory.\n\t\t** Note: in Watcom flat addressing, Selector == Segment<<4 (ex: 0A0000h)\n\t\t*/\n\t\tunsigned int Selector;\n\n\t\t/*\n\t\t**\tThese are C equivalents for pushing and popping the DS segment register. By using\n\t\t**\tthese, it is possible to create very small code that uses a segment and\n\t\t**\toffset without damaging the DS register. These are especially useful in protected\n\t\t**\tmode, but they are legal in real mode as well.\n\t\t*/\n\t\tvoid Push_DS(void) {/*__emit__(0x1E);*/};\n\t\tvoid Pop_DS(void) {/*__emit__(0x1F);*/};\n\n\tpublic:\n\t\tDOSSegmentClass(void);\n\t\t~DOSSegmentClass(void);\n\t\tDOSSegmentClass(unsigned short segment, long size=(1024L*64L));\n\n\t\tunsigned int Get_Selector(void);\n\n\t\t/*\n\t\t**\tThis routine is used to assign where the descriptor actually points to in\n\t\t**\tlow DOS memory. In real mode, this is a simple segment assignment and the size\n\t\t**\tis always 64K regardless of what is specified. In protected mode, the segment\n\t\t**\tis used to update the selector and the size can be any length.\n\t\t** In Watcom flat mode, it sets Selector == segment<<4\n\t\t*/\n\t\tvoid Assign(unsigned short segment, long size=(1024L*64L));\n\n\t\t/*\n\t\t**\tThese routines will move the data to/from regular memory and the segment/descriptor\n\t\t**\tmemory.\n\t\t*/\n\t\tvoid Copy_To(void *source, int dest, int size);\n\t\tvoid Copy_From(void *dest, int source, int size);\n\t\tvoid Copy_Word_To(short data, int dest);\n\t\tvoid Copy_Byte_To(char data, int dest);\n\t\tvoid Copy_DWord_To(long data, int dest);\n\t\tshort Copy_Word_From(int source);\n\t\tchar Copy_Byte_From(int source);\n\t\tlong Copy_DWord_From(int source);\n\n\t\t/*\n\t\t**\tThese routines move data around between sections of segmented (descriptor) memory.\n\t\t**\tTypically, this is used when accessing DOS memory in protected mode or when dealing\n\t\t**\twith hard memory areas such as the screen.\n\t\t*/\n\t\tstatic void Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size);\n\t\tstatic void Swap(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size);\n};\n\n\ninline DOSSegmentClass::DOSSegmentClass(void)\n{\n\tSelector = 0xB0000;\n}\n\ninline DOSSegmentClass::~DOSSegmentClass(void)\n{\n}\n\ninline void DOSSegmentClass::Copy_Word_To(short data, int dest)\n{\n\t*(short *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Copy_Byte_To(char data, int dest)\n{\n\t*(char *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Copy_DWord_To(long data, int dest)\n{\n\t*(long *)(Selector+dest) = data;\n}\n\ninline void DOSSegmentClass::Assign(unsigned short segment, long)\n{\n\tSelector = (long)(segment)<<4L;\n}\n\ninline DOSSegmentClass::DOSSegmentClass(unsigned short segment, long)\n{\n\tAssign(segment);\n}\n\ninline void DOSSegmentClass::Copy_To(void *source, int dest, int size)\n{\n\tmemmove((void*)(Selector+dest), source, (unsigned)size);\n}\n\ninline void DOSSegmentClass::Copy_From(void *dest, int source, int size)\n{\n\tmemmove(dest, (void*)(Selector+source), (unsigned)size);\n}\n\ninline void DOSSegmentClass::Copy(DOSSegmentClass &src, int soffset, DOSSegmentClass &dest, int doffset, int size) {\n\tmemmove((void*)(dest.Selector+doffset), (void*)(src.Selector+soffset), (unsigned)size);\n}\n\ninline short DOSSegmentClass::Copy_Word_From(int source)\n{\n\treturn *(short*)(Selector+source);\n}\n\ninline char DOSSegmentClass::Copy_Byte_From(int source)\n{\n\treturn *(char*)(Selector+source);\n}\n\ninline long DOSSegmentClass::Copy_DWord_From(int source)\n{\n\treturn *(long*)(Selector+source);\n}\n\ninline unsigned int DOSSegmentClass::Get_Selector(void)\n{\n\treturn Selector;\n}\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/DRIVE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DRIVE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DRIVE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 22, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 31, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   DriveClass::AI -- Processes unit movement and rotation.                                   *\n *   DriveClass::Approach_Target -- Handles approaching the target in order to attack it.      *\n *   DriveClass::Assign_Destination -- Set the unit's NavCom.                                  *\n *   DriveClass::Class_Of -- Fetches a reference to the class type for this object.            *\n *   DriveClass::Debug_Dump -- Displays status information to monochrome screen.               *\n *   DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.              *\n *   DriveClass::DriveClass -- Constructor for drive class object.                             *\n *   DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                 *\n *   DriveClass::Force_Track -- Forces the unit to use the indicated track.                    *\n *   DriveClass::Lay_Track -- Handles track laying logic for the unit.                         *\n *   DriveClass::Limbo -- Prepares vehicle and then limbos it.                                 *\n *   DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                    *\n *   DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                  *\n *   DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.          *\n *   DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.  *\n *   DriveClass::Response_Move -- Voice feedback when ordering the unit to move.               *\n *   DriveClass::Response_Select -- Voice feedback when selecting the unit.                    *\n *   DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                   *\n *   DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.        *\n *   DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                  *\n *   DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.           *\n *   DriveClass::Teleport_To -- Teleport object to specified location.                         *\n *   DriveClass::While_Moving -- Processes unit movement.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef NEVER\nvoid test(void)\n{\n\tenum nums {one, two, three};\n\n   nums x;\n   nums *ptr;\n\n   ptr = &x;\n}\n#endif\n\n\n/***********************************************************************************************\n * DriveClass::Response_Select -- Voice feedback when selecting the unit.                      *\n *                                                                                             *\n *    This is the voice to play when the unit is selected.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Select(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_VEHIC,\n\t\tVOC_REPORT,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_YESSIR,\n\t\tVOC_AWAIT\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Response_Move -- Voice feedback when ordering the unit to move.                 *\n *                                                                                             *\n *    This plays the audio feedback when ordering this unit to move to a new destination.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Move(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_ACKNOWL,\n\t\tVOC_AFFIRM,\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.    *\n *                                                                                             *\n *    This plays the audio feedback when ordering this unit to attack.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Response_Attack(void)\n{\n\tassert(IsActive);\n\n\tstatic VocType _response[] = {\n\t\tVOC_AFFIRM,\n\t\tVOC_ACKNOWL\n\t};\n\tVocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];\n\tif (AllowVoice) {\n\t\tSound_Effect(response, fixed(1), -(ID+1));\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                     *\n *                                                                                             *\n *    This routine is called when the unit discovers that it should get out of the \"hot seat\"  *\n *    and move to an adjacent cell. Since the safety of the adjacent cell is not determined    *\n *    before the move begins, it will appear that the unit is just scattering (which it        *\n *    should).                                                                                 *\n *                                                                                             *\n * INPUT:   threat   -- The coordinate of the source of the threat. The unit will try to move  *\n *                      roughly away from the threat.                                          *\n *                                                                                             *\n *          forced   -- The threat is real and a serious effort to scatter should be made.     *\n *                                                                                             *\n *          nokidding-- The scatter should affect the player's infantry even if it otherwise   *\n *                      wouldn't have.                                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1994 JLB : Created.                                                                 *\n *   09/27/1995 JLB : Revised to never scatter if already moving.                              *\n *   07/09/1996 JLB : Moved to DriveClass so that ships will scatter too.                      *\n *   08/02/1996 JLB : Added the \"nokidding\" parameter.                                         *\n *=============================================================================================*/\nvoid DriveClass::Scatter(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (MissionControl[Mission].IsParalyzed) return;\n\n\tif ((What_Am_I() != RTTI_UNIT || !((UnitClass *)this)->IsDumping) && (!Target_Legal(NavCom) || (nokidding && !IsRotating))) {\n\t\tif (!Target_Legal(TarCom) || forced || Random_Pick(1, 4) == 1) {\n\t\t\tFacingType\ttoface;\n\t\t\tFacingType\tnewface;\n\t\t\tCELL\t\t\tnewcell;\n\n\t\t\tif (threat != 0) {\n\t\t\t\ttoface = Dir_Facing(Direction8(threat, Coord));\n\t\t\t\ttoface = toface + FacingType(Random_Pick(0, 2)-1);\n\t\t\t} else {\n\t\t\t\ttoface = Dir_Facing(PrimaryFacing.Current());\n\t\t\t\ttoface = toface + FacingType(Random_Pick(0, 2)-1);\n\t\t\t}\n\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\tnewface = toface + face;\n\t\t\t\tnewcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\t\tif (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Limbo -- Prepares vehicle and then limbos it.                                   *\n *                                                                                             *\n *    This routine removes the occupation bits for the vehicle and also handles cleaning up    *\n *    any vehicle reservation bits. After this, it then proceeds with limboing the unit.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the vehicle limboed?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Limbo(void)\n{\n\tif (!IsInLimbo) {\n\t\tStop_Driver();\n\t\tTrackNumber = -1;\n\t}\n\treturn(FootClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.             *\n *                                                                                             *\n *    This routine will remove the \"reservation\" flag (if present) when the vehicle is         *\n *    required to stop movement.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the vehicle stopped?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Stop_Driver(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t** We only need to do something if the vehicle is actually going\n\t** somewhere.\n\t*/\n\tif (Head_To_Coord()) {\n\n\t\t/*\n\t\t** Safe off whether the vehicle is down or not so we know whether\n\t\t** we have to put it back down.\n\t\t*/\n\t\tint temp = IsDown;\n\n\t\t/*\n\t\t** If the vehicle is down, pick it up so it doesn't interfere with\n\t\t** our flags.\n\t\t*/\n\t\tif (temp) {\n\t\t\tMark(MARK_UP);\n\t\t}\n\n\t\t/*\n\t\t** Call the drive class function which will let us release the\n\t\t** reserved track.\n\t\t*/\n\t\tMark_Track(Head_To_Coord(), MARK_UP);\n\n\t\t/*\n\t\t** If it was down it should be down when we are done.\n\t\t*/\n\t\tif (temp) {\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t}\n\treturn(FootClass::Stop_Driver());\n}\n\n\n/***********************************************************************************************\n * DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.                *\n *                                                                                             *\n *    This routine will set the vehicle to rotate to the direction specified. For tracked      *\n *    vehicles, it is just a simple rotation. For wheeled vehicles, it performs a series       *\n *    of short drives (three point turn) to face the desired direction.                        *\n *                                                                                             *\n * INPUT:   dir   -- The direction that this vehicle should face.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Do_Turn(DirType dir)\n{\n\tassert(IsActive);\n\n\tif (dir != PrimaryFacing) {\n\n#ifdef TOFIX\n\t\t/*\n\t\t**\tSpecial rotation track is needed for units that\n\t\t**\tcannot rotate in place.\n\t\t*/\n\t\tif (Special.IsThreePoint && TrackNumber == -1 && Techno_Type_Class()->Speed == SPEED_WHEEL) {\n\t\t\tint\t\t\tfacediff;\t// Signed difference between current and desired facing.\n\t\t\tFacingType\tface;\t\t\t// Current facing (ordinal value).\n\n\t\t\tfacediff = PrimaryFacing.Difference(dir) >> 5;\n\t\t\tfacediff = Bound(facediff, -2, 2);\n\t\t\tif (facediff) {\n\t\t\t\tface = Dir_Facing(PrimaryFacing);\n\n\t\t\t\tIsOnShortTrack = true;\n\t\t\t\tForce_Track(face*FACING_COUNT + (face + facediff), Coord);\n\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\tSet_Speed(0xFF);\t\t// Full speed.\n\t\t\t}\n\t\t} else {\n\t\t\tPrimaryFacing.Set_Desired(dir);\n\t\t}\n#else\n\t\t\tPrimaryFacing.Set_Desired(dir);\n//\t\t\tIsRotating = true;\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Teleport_To -- Teleport object to specified location.                           *\n *                                                                                             *\n *    This will teleport the object to the specified location or as close as possible to it    *\n *    if the destination is blocked.                                                           *\n *                                                                                             *\n * INPUT:   cell  -- The desired destination cell to teleport to.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the teleport successful?                                                 *\n *                                                                                             *\n * WARNINGS:   All current activity of this object will be terminated by the teleport. It will *\n *             arrive at the destination in static guard mode.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *   10/31/1996 JLB : Handles flag teleport case.                                              *\n *=============================================================================================*/\nbool DriveClass::Teleport_To(CELL cell)\n{\n\t/*\n\t**\tAll cargo gets destroyed.\n\t*/\n\tif (Rule.IsChronoKill) {\n\t\tKill_Cargo(NULL);\n\t}\n\n\tStop_Driver();\n\tForce_Track(-1, 0);\n\tPrimaryFacing.Set_Current(PrimaryFacing.Desired());\n\tTransmit_Message(RADIO_OVER_OUT);\n\tAssign_Destination(TARGET_NONE);\n\tAssign_Target(TARGET_NONE);\n\tAssign_Mission(MISSION_NONE);\n\tCommence();\n\tMark(MARK_UP);\n\n\t/*\n\t**\tA teleported unit will drop the flag right where it's at.\n\t*/\n\tif (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Flagged != HOUSE_NONE) {\n\t\tHouseClass::As_Pointer(((UnitClass *)this)->Flagged)->Flag_Attach(Coord_Cell(Coord));\n\t}\n\n\tif (Can_Enter_Cell(cell) != MOVE_OK) {\n\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);\n\t}\n\tCoord = Cell_Coord(cell);\n\tMark(MARK_DOWN);\n\tLook(false);\n\tPer_Cell_Process(PCP_END);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Force_Track -- Forces the unit to use the indicated track.                      *\n *                                                                                             *\n *    This override (nuclear bomb) style routine is to be used when a unit needs to start      *\n *    on a movement track but is outside the normal movement system. This occurs when a        *\n *    harvester starts driving off of a refinery.                                              *\n *                                                                                             *\n * INPUT:   track -- The track number to start on.                                             *\n *                                                                                             *\n *          coord -- The coordinate that the unit will end up at when the movement track       *\n *                   is completed.                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Force_Track(int track, COORDINATE coord)\n{\n\tassert(IsActive);\n\n\tTrackNumber = track;\n\tTrackIndex = 0;\n\tif (coord != 0) {\n\t\tStart_Driver(coord);\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::DriveClass -- Constructor for drive class object.                               *\n *                                                                                             *\n *    This will initialize the drive class to its default state. It is called as a result      *\n *    of creating a unit.                                                                      *\n *                                                                                             *\n * INPUT:   classid  -- The unit's ID class. It is passed on to the foot class constructor.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/13/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nDriveClass::DriveClass(RTTIType rtti, int id, HousesType house) :\n\tFootClass(rtti, id, house),\n\tIsMoebius(false),\n\tIsHarvesting(false),\n\tIsTurretLockedDown(false),\n\tIsOnShortTrack(false),\n\tSpeedAccum(0),\n\tMoebiusCountDown(0),\n\tMoebiusCell(0),\n\tTrackNumber(-1),\n\tTrackIndex(0)\n{\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * DriveClass::Debug_Dump -- Displays status information to monochrome screen.                 *\n *                                                                                             *\n *    This debug utility function will display the status of the drive class to the mono       *\n *    screen. It is through this information that bugs can be tracked down.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Fill_Attrib(66, 14, 12, 1, IsMoebius ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.          *\n *                                                                                             *\n *    This routine calculates the new coordinate value needed for the                          *\n *    smooth turn logic. The adjustment and flag values must be                                *\n *    determined prior to entering this routine.                                               *\n *                                                                                             *\n * INPUT:   adj      -- The adjustment coordinate as lifted from the                           *\n *                      correct smooth turn table.                                             *\n *                                                                                             *\n *          dir      -- Pointer to dir for possible modification                               *\n *                      according to the flag bits.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the unit should positioned to.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1994 JLB : Created.                                                                 *\n *   07/13/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nCOORDINATE DriveClass::Smooth_Turn(COORDINATE adj, DirType & dir)\n{\n\tassert(IsActive);\n\n\tDirType workdir = dir;\n\tint x,y;\n\tint temp;\n\tTrackControlType flags = TrackControl[TrackNumber].Flag;\n\n\tx = Coord_X(adj);\n\ty = Coord_Y(adj);\n\n\tif (flags & F_T) {\n\t\ttemp\t= x;\n\t\tx\t\t= y;\n\t\ty \t\t= temp;\n\t\tworkdir = (DirType)(DIR_W - workdir);\n\t}\n\n\tif (flags & F_X) {\n\t\tx \t\t = -x;\n\t\tworkdir = (DirType)-workdir;\n\t}\n\n\tif (flags & F_Y) {\n\t\ty = -y;\n\t\tworkdir = (DirType)(DIR_S - workdir);\n\t}\n\n\tdir = workdir;\n\n\treturn(XY_Coord( (LEPTON)(Coord_X(Head_To_Coord()) + x), (LEPTON)(Coord_Y(Head_To_Coord()) + y)));\n}\n\n\n/***********************************************************************************************\n * DriveClass::Assign_Destination -- Set the unit's NavCom.                                    *\n *                                                                                             *\n *    This routine is used to set the unit's navigation computer to the                        *\n *    specified target. Once the navigation computer is set, the unit                          *\n *    will start planning and moving toward the destination.                                   *\n *                                                                                             *\n * INPUT:   target   -- The destination target for the unit to head to.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tAbort early if there is anything wrong with the parameters\n\t**\tor the unit already is assigned the specified destination.\n\t*/\n\tif (target == NavCom) return;\n\n\t/*\n\t**\tFor harvesting type vehicles, it might go into a dock and unload procedure\n\t**\twhen the harvester is full and an empty refinery is selected as a target.\n\t*/\n\tBuildingClass * b = As_Building(target);\n\n\t/*\n\t**\tIf the player clicked on refinery but it is not busy, then assign\n\t**\tit to unload at the refinery.\n\t*/\n\tif (b != NULL && *b == STRUCT_REFINERY && What_Am_I() == RTTI_UNIT && ((UnitTypeClass *)Techno_Type_Class())->IsToHarvest) {\n\t\tif (Contact_With_Whom() != b && !b->In_Radio_Contact()) {\n\t\t\t/*\n\t\t\t**\tEstablish radio contact protocol. If the facility responds correctly,\n\t\t\t**\tthen remain in radio contact and proceed toward the desired destination.\n\t\t\t*/\n\t\t\tif (Transmit_Message(RADIO_HELLO, b) == RADIO_ROGER) {\n\t\t\t\tif (Mission != MISSION_ENTER && Mission != MISSION_HARVEST) {\n\t\t\t\t\tAssign_Mission(MISSION_ENTER);\n\t\t\t\t\ttarget = TARGET_NONE;\n\t\t\t\t} else {\n//\t\t\t\t\ttarget = TARGET_NONE;\n\t\t\t\t}\n\t\t\t} else {\n//\t\t\t\ttarget = TARGET_NONE;\n\t\t\t}\n\t\t} else {\n//\t\t\ttarget = TARGET_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the unit's navigation computer.\n\t*/\n\tFootClass::Assign_Destination(target);\n\n\tPath[0] = FACING_NONE;\t\t\t// Force recalculation of path.\n\tif (!IsDriving && Mission != MISSION_UNLOAD) {\n\t\tStart_Of_Move();\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::While_Moving -- Processes unit movement.                                        *\n *                                                                                             *\n *    This routine is used to process movement for the units as they move.                     *\n *    It is called many times for each cell's worth of movement.   This                        *\n *    routine only applies after the next cell HeadTo has been determined.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true/false; Should this routine be called again?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1992 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nbool DriveClass::While_Moving(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tPerform quick legality checks.\n\t*/\n\tif (!IsDriving || TrackNumber == -1 || (IsRotating && !Techno_Type_Class()->IsTurretEquipped)) {\n\t\tSpeedAccum = 0;\t\t// Kludge?  No speed should accumulate if movement is on hold.\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf enough movement has accumulated so that the unit can\n\t**\tvisibly move on the map, then process accordingly.\n\t** Slow the unit down if he's carrying a flag.\n\t*/\n\tMPHType maxspeed = MPHType(min(Techno_Type_Class()->MaxSpeed * SpeedBias * House->GroundspeedBias, (int)MPH_LIGHT_SPEED));\n\tif (IsFormationMove) maxspeed = FormationMaxSpeed;\n\n\tint actual;\t\t\t// Working movement addition value.\n\tif (((UnitClass *)this)->Flagged != HOUSE_NONE) {\n\t\tactual = SpeedAccum + ((int)maxspeed/2) * fixed(Speed, 256);\n\t} else {\n\t\tactual = SpeedAccum + maxspeed * fixed(Speed, 256);\n\t}\n\n\tif (actual > PIXEL_LEPTON_W) {\n\t\tTurnTrackType\tconst * track;\t// Track control pointer.\n\t\tTrackType\t\tconst\t* ptr;\t\t// Pointer to coord offset values.\n\t\tint\t\t\t\ttracknum;\t\t// The track number being processed.\n\t\tFacingType\t\tnextface;\t\t// Next facing queued in path.\n\t\tbool\t\t\t\tadj;\t\t\t\t// Is a turn coming up?\n\n\t\ttrack = &TrackControl[TrackNumber];\n\t\tif (IsOnShortTrack) {\n\t\t\ttracknum = track->StartTrack;\n\t\t} else {\n\t\t\ttracknum = track->Track;\n\t\t}\n\t\tptr = RawTracks[tracknum-1].Track;\n\t\tnextface = Path[0];\n\n\t\t/*\n\t\t**\tDetermine if there is a turn coming up. If there is\n\t\t**\ta turn, then track jumping might occur.\n\t\t*/\n\t\tadj = false;\n\t\tif (nextface != FACING_NONE && Dir_Facing(track->Facing) != nextface) {\n\t\t\tadj = true;\n\t\t}\n\n\t\t/*\n\t\t**\tSkip ahead the number of track steps required (limited only\n\t\t**\tby track length). Set the unit to the new position and\n\t\t**\tflag the unit accordingly.\n\t\t*/\n\t\tMark(MARK_UP);\n\t\twhile (actual > PIXEL_LEPTON_W) {\n\t\t\tCOORDINATE\t\toffset;\n\t\t\tDirType\tdir;\n\n\t\t\tactual -= PIXEL_LEPTON_W;\n\n\t\t\toffset = ptr[TrackIndex].Offset;\n\t\t\tif (offset || !TrackIndex) {\n\t\t\t\tdir = ptr[TrackIndex].Facing;\n\t\t\t\tCoord = Smooth_Turn(offset, dir);\n\n\t\t\t\tPrimaryFacing.Set(dir);\n\n\t\t\t\t/*\n\t\t\t\t**\tSee if \"per cell\" processing is necessary.\n\t\t\t\t*/\n\t\t\t\tif (TrackIndex && RawTracks[tracknum-1].Cell == TrackIndex) {\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t\tPer_Cell_Process(PCP_DURING);\n\t\t\t\t\tif (!IsActive) {\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t}\n\t\t\t\t\tMark(MARK_UP);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tThe unit could \"jump tracks\". Check to see if the unit should\n\t\t\t\t**\tdo so.\n\t\t\t\t*/\n\t\t\t\tif (/**this != UNIT_GUNBOAT &&*/ nextface != FACING_NONE && adj && RawTracks[tracknum-1].Jump == TrackIndex && TrackIndex) {\n\t\t\t\t\tTurnTrackType const * newtrack;\t\t// Proposed jump-to track.\n\t\t\t\t\tint\ttnum;\n\n\t\t\t\t\ttnum = (int)(Dir_Facing(track->Facing) * FACING_COUNT) + (int)nextface;\n\t\t\t\t\tnewtrack = &TrackControl[tnum];\n\t\t\t\t\tif (newtrack->Track && RawTracks[newtrack->Track-1].Entry) {\n\t\t\t\t\t\tCOORDINATE\tc = Head_To_Coord();\n\t\t\t\t\t\tint oldspeed = Speed;\n\n\t\t\t\t\t\tc = Adjacent_Cell(c, nextface);\n\n\t\t\t\t\t\tswitch (Can_Enter_Cell(Coord_Cell(c), nextface)) {\n\t\t\t\t\t\t\tcase MOVE_OK:\n\t\t\t\t\t\t\t\tIsOnShortTrack = false;\t\t// Shouldn't be necessary, but...\n\t\t\t\t\t\t\t\tTrackNumber = tnum;\n\t\t\t\t\t\t\t\ttrack = newtrack;\n\n\t\t\t\t\t\t\t\ttracknum = track->Track;\n\t\t\t\t\t\t\t\tTrackIndex = RawTracks[tracknum-1].Entry-1;\t// Anticipate increment.\n\t\t\t\t\t\t\t\tptr = RawTracks[tracknum-1].Track;\n\t\t\t\t\t\t\t\tadj = false;\n\n\t\t\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\t\t\tIsDriving = true;\n\t\t\t\t\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\t\t\t\t\tIsDriving = false;\n\t\t\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t\t\t\tif (Start_Driver(c)) {\n\t\t\t\t\t\t\t\t\tSet_Speed(oldspeed);\n\t\t\t\t\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);\n\t\t\t\t\t\t\t\t\tPath[CONQUER_PATH_MAX-1] = FACING_NONE;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\t\t\t\t\tTrackNumber = -1;\n\t\t\t\t\t\t\t\t\tactual = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase MOVE_CLOAK:\n\t\t\t\t\t\t\t\tMap[c].Shimmer();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase MOVE_TEMP:\n#ifdef TOFIX\n\t\t\t\t\t\t\t\tif (*this == UNIT_HARVESTER || !House->IsHuman) {\n#else\n\t\t\t\t\t\t\t\tif (!House->IsHuman) {\n#endif\n\t\t\t\t\t\t\t\t\tMap[c].Incoming(0, true, true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTrackIndex++;\n\n\t\t\t} else {\n\t\t\t\tactual = 0;\n\t\t\t\tCoord = Head_To_Coord();\n\t\t\t\tStop_Driver();\n\t\t\t\tTrackNumber = -1;\n\t\t\t\tTrackIndex = NULL;\n\n\t\t\t\t/*\n\t\t\t\t**\tPerform \"per cell\" activities.\n\t\t\t\t*/\n\t\t\t\tMark(MARK_DOWN);\n\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\tif (!IsActive) return(false);\n\t\t\t\tMark(MARK_UP);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (IsActive) {\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t}\n\n\t/*\n\t**\tReplace any remainder back into the unit's movement\n\t**\taccumulator to be processed next pass.\n\t*/\n\tSpeedAccum = actual;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.            *\n *                                                                                             *\n *    This routine is called when a unit has mostly or completely                              *\n *    entered a cell. The unit might be in the middle of a movement track                      *\n *    when this routine is called. It's primary purpose is to perform                          *\n *    sighting and other \"per cell\" activities.                                                *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/03/1993 JLB : Created.                                                                 *\n *   03/30/1994 JLB : Revamped for track system.                                               *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   06/18/1994 JLB : Converted to virtual function.                                           *\n *   06/18/1994 JLB : Distinguishes between center and near-center conditions.                 *\n *=============================================================================================*/\nvoid DriveClass::Per_Cell_Process(PCPType why)\n{\n\tassert(IsActive);\n\n\tif (why == PCP_END) {\n\t\tCELL\tcell = Coord_Cell(Coord);\n\n\t\t/*\n\t\t**\tCheck to see if it has reached its destination. If so, then clear the NavCom\n\t\t**\tregardless of the remaining path list.\n\t\t*/\n\t\tif (As_Cell(NavCom) == cell) {\n\t\t\tIsTurretLockedDown = false;\n\t\t\tNavCom = TARGET_NONE;\n\t\t\tPath[0] = FACING_NONE;\n\t\t}\n\n\t\tLay_Track();\n\t}\n\n\tFootClass::Per_Cell_Process(why);\n}\n\n\n/***********************************************************************************************\n * DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                    *\n *                                                                                             *\n *    This will try to start a unit advancing toward the cell it is                            *\n *    facing. It will check for and handle legality and reserving of the                       *\n *    necessary cell.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true/false; Should this routine be called again because                            *\n *                      initial start operation is temporarily delayed?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1992 JLB : Created.                                                                 *\n *   10/18/1993 JLB : This should be called repeatedly until HeadTo is not NULL.               *\n *   03/16/1994 JLB : Revamped for track logic.                                                *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   06/19/1995 JLB : Fixed so that it won't fire on ground unnecessarily.                     *\n *   07/13/1995 JLB : Handles bumping into cloaked objects.                                    *\n *   09/22/1995 JLB : Breaks out of hopeless hunt mode.                                        *\n *   07/10/1996 JLB : Sets scan limit if necessary.                                            *\n *=============================================================================================*/\nbool DriveClass::Start_Of_Move(void)\n{\n\tassert(IsActive);\n\n\tFacingType\t\tfacing;\t\t\t\t// Direction movement will commence.\n\tDirType\t\t\tdir;\t\t\t\t// Desired actual facing toward destination.\n\tint\t\t\t\tfacediff;\t\t\t// Difference between current and desired facing.\n\tint\t\t\t\tspeed;\t\t\t\t// Speed of unit.\n\tCELL\t\t\t\tdestcell;\t\t\t// Cell of destination.\n\tLandType\t\t\tground;\t\t\t\t// Ground unit is entering.\n\tCOORDINATE\t\t\t\tdest;\t\t\t\t\t// Destination coordinate.\n\n\tfacing = Path[0];\n\n\tif (!Target_Legal(NavCom) && facing == FACING_NONE) {\n\t\tIsTurretLockedDown = false;\n\t\tStop_Driver();\n\t\tif (Mission == MISSION_MOVE) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t\treturn(false);\t\t// Why is it calling this routine!?!\n\t}\n\n\t/*\n\t**\tReduce the path length if the target is a unit and the\n\t**\trange to the unit is less than the precalculated path steps.\n\t*/\n\tif (facing != FACING_NONE) {\n\t\tint\tdist;\n\n\t\tif (Is_Target_Vessel(NavCom) || Is_Target_Unit(NavCom) || Is_Target_Infantry(NavCom)) {\n\t\t\tdist = Lepton_To_Cell((LEPTON)Distance(NavCom));\n\n\t\t\tif (dist < ARRAY_SIZE(Path)) {\n\t\t\t\tPath[dist] = FACING_NONE;\n\t\t\t\tfacing = Path[0];\t\t// Maybe needed.\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the path is invalid at this point, then generate one. If\n\t**\tgenerating a new path fails, then abort NavCom.\n\t*/\n\tif (facing == FACING_NONE) {\n\n\t\t/*\n\t\t**\tIf after a path search, there is still no valid path, then set the\n\t\t**\tNavCom to null and let the script take care of assigning a new\n\t\t**\tnavigation target.\n\t\t*/\n\t\tif (PathDelay != 0) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (!Basic_Path()) {\n\n\t\t\t/*\n\t\t\t**\tIf the unit is close enough to the target then just stop\n\t\t\t**\tdriving now. This prevents the fidgeting that would occur\n\t\t\t**\tif they mindlessly kept trying to get to the exact location\n\t\t\t**\tdesired. This is quite necessary since it is typical to move\n\t\t\t**\tseveral units with the same mouse click.\n\t\t\t*/\n\t\t\tif (!Is_On_Priority_Mission() && Distance(NavCom) < Rule.CloseEnoughDistance && (Mission == MISSION_MOVE || Mission == MISSION_GUARD_AREA)) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tif (!IsActive) return(false);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tIf a basic path could not be found, but the immediate move destination is\n\t\t\t\t**\tblocked by a friendly temporary blockage, then cause that blockage\n\t\t\t\t**\tto scatter.\n\t\t\t\t*/\n\t\t\t\tCELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), PrimaryFacing.Current());\n\t\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\t\tMoveType ok = Can_Enter_Cell(cell);\n\t\t\t\t\tif (ok == MOVE_TEMP) {\n\t\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\t\t\tTechnoClass * blockage = cellptr->Cell_Techno();\n\t\t\t\t\t\tif (blockage && House->Is_Ally(blockage)) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the target can be told to get out of the way, only bother\n\t\t\t\t\t\t\t**\tto do so if we aren't very close to the target and this\n\t\t\t\t\t\t\t**\tobject can just say \"good enough\" and stop here.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {\n\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t\treturn(false);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcellptr->Incoming(0, true, false);\n//\t\t\t\t\t\t\t\tcellptr->Incoming(0, true, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (TryTryAgain > 0) {\n\t\t\t\t\tTryTryAgain--;\n\t\t\t\t} else {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\tIsNewNavCom = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince the path was blocked, check to make sure that it was completely\n\t\t\t**\tblocked. If so and it has a valid TarCom and it is out of range of the\n\t\t\t**\tTarCom, then give this unit a range limit so that it might not pick\n\t\t\t**\ta \"can't reach\" target again.\n\t\t\t*/\n\t\t\tif (!Target_Legal(NavCom) && Target_Legal(TarCom) && !In_Range(TarCom)) {\n\t\t\t\tIsScanLimited = true;\n\t\t\t\tif (Team.Is_Valid()) Team->Scan_Limit();\n\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tStop the movement, for now, and let the subsequent logic in later game\n\t\t\t**\tframes resume movement as appropriate.\n\t\t\t*/\n\t\t\tStop_Driver();\n\t\t\tTrackNumber = -1;\n\t\t\tIsTurretLockedDown = false;\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tIf a basic path could be found, but the immediate move destination is\n\t\t**\tblocked by a friendly temporary blockage, then cause that blockage\n\t\t**\tto scatter.\n\t\t*/\n\t\tCELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0]);\n\t\tif (Map.In_Radar(cell)) {\n\t\t\tMoveType ok = Can_Enter_Cell(cell);\n\t\t\tif (ok == MOVE_TEMP) {\n\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\tTechnoClass * blockage = cellptr->Cell_Techno();\n\t\t\t\tif (blockage && House->Is_Ally(blockage)) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the target can be told to get out of the way, only bother\n\t\t\t\t\t**\tto do so if we aren't very close to the target and this\n\t\t\t\t\t**\tobject can just say \"good enough\" and stop here.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\treturn(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcellptr->Incoming(0, true, false);\n//\t\t\t\t\t\tcellptr->Incoming(0, true, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tTryTryAgain = PATH_RETRY;\n\t\tfacing = Path[0];\n\t}\n\n\t/*\n\t**\tDetermine the coordinate of the next cell to move into.\n\t*/\n\tdest = Adjacent_Cell(Coord, facing);\n\tdir = Facing_Dir(facing);\n\n\t/*\n\t**\tSet the facing correctly if it isn't already correct. This\n\t**\tmeans starting a rotation track if necessary.\n\t*/\n\tfacediff = PrimaryFacing.Difference(dir);\n\tif (facediff) {\n\n\t\t/*\n\t\t**\tRequest a change of facing.\n\t\t*/\n\t\tDo_Turn(dir);\n\t\treturn(true);\n\n\t} else {\n\n\t\t/* NOTE:  Beyond this point, actual track assignment can begin.\n\t\t**\n\t\t**\tIf the cell to move into is impassable (probably for some unexpected\n\t\t**\treason), then abort the path list and set the speed to zero. The\n\t\t** next time this routine is called, a new path will be generated.\n\t\t*/\n\t\tdestcell = Coord_Cell(dest);\n\t\tMark(MARK_UP);\n\t\tMoveType cando = Can_Enter_Cell(destcell, facing);\n\t\tMark(MARK_DOWN);\n\n\t\tif (cando != MOVE_OK) {\n\n\t\t\tif (Mission == MISSION_MOVE /*KO&& House->IsHuman */&& Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tif (!IsActive) return(false);//BG\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a temporary friendly object is blocking the path, then cause it to\n\t\t\t**\tget out of the way.\n\t\t\t*/\n\t\t\tif (cando == MOVE_TEMP) {\n\t\t\t\tMap[destcell].Incoming(0, true, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a cloaked object is blocking, then shimmer the cell.\n\t\t\t*/\n\t\t\tif (cando == MOVE_CLOAK) {\n\t\t\t\tMap[destcell].Shimmer();\n\t\t\t}\n\n\t\t\tStop_Driver();\n\t\t\tif (cando != MOVE_MOVING_BLOCK) {\n\t\t\t \tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If blocked by a moving block then just exit start of move and\n\t\t\t** try again next tick.\n\t\t\t*/\n\t\t\tif (cando == MOVE_DESTROYABLE) {\n\t\t\t\tif (Map[destcell].Cell_Object()) {\n\t\t\t\t\tif (!House->Is_Ally(Map[destcell].Cell_Object())) {\n\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {\n\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tIsNewNavCom = false;\n\t\t\tTrackNumber = -1;\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tDetermine the speed that the unit can travel to the desired square.\n\t\t*/\n\t\tground = Map[destcell].Land_Type();\n\t\tspeed = Ground[ground].Cost[Techno_Type_Class()->Speed] * 255;\n\n\t\t/* change speed if it's related to a team move */\n\t\tif (IsFormationMove) speed = Ground[ground].Cost[FormationSpeed] * 255;\n\t\tif (!speed) speed = 128;\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tSet the jiggle flag if the terrain would cause the unit\n\t\t**\tto jiggle when travelled over.\n\t\t*/\n\t\tBaseF &= ~BASEF_JIGGLE;\n\t\tif (Ground[ground].Jiggle) {\n\t\t\tBaseF |= BASEF_JIGGLE;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tA damaged unit has a reduced speed.\n\t\t*/\n\t\tif (Health_Ratio() <= Rule.ConditionYellow /*(Techno_Type_Class()->MaxStrength>>1) > Strength*/) {\n\t\t\tspeed -= (speed/4);\t// Three quarters speed.\n\t\t}\n\t\tif ((speed != Speed)/* || !SpeedAdd*/) {\n\t\t\tSet_Speed(speed);\t\t// Full speed.\n\t\t}\n\n\t\t/*\n\t\t**\tReserve the destination cell so that it won't become\n\t\t**\toccupied AS this unit is moving into it.\n\t\t*/\n\t\tif (cando != MOVE_OK) {\n\t\t \tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\tTrackNumber = -1;\n\t\t \tdest = NULL;\n\t\t} else {\n\n\t\t\tOverrun_Square(Coord_Cell(dest), true);\n\n\t\t\t/*\n\t\t\t**\tDetermine which track to use (based on recorded path).\n\t\t\t*/\n\t\t\tFacingType nextface = Path[1];\n\t\t\tif (nextface == FACING_NONE) nextface = facing;\n\n\t\t\tIsOnShortTrack = false;\n\t\t\tTrackNumber = facing * FACING_COUNT + (int)nextface;\n\t\t\tif (TrackControl[TrackNumber].Track == 0) {\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\tTrackNumber = -1;\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tif (TrackControl[TrackNumber].Flag & F_D) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the middle cell of a two cell track contains a crate,\n\t\t\t\t\t**\tthe check for goodies before movement starts.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!Map[destcell].Goodie_Check(this)) {\n\t\t\t\t\t\tcando = MOVE_NO;\n\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!IsActive) return(false);\n\t\t\t\t\t\tdest = Adjacent_Cell(dest, nextface);\n\t\t\t\t\t\tdestcell = Coord_Cell(dest);\n\t\t\t\t\t\tcando = Can_Enter_Cell(destcell);\n\t\t\t\t\t}\n\t\t\t\t\tif (!IsActive) return(false);\n\n\t\t\t\t\tif (cando != MOVE_OK) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf a temporary friendly object is blocking the path, then cause it to\n\t\t\t\t\t\t**\tget out of the way.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cando == MOVE_TEMP) {\n\t\t\t\t\t\t\tMap[destcell].Incoming(0, true, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf a cloaked object is blocking, then shimmer the cell.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cando == MOVE_CLOAK) {\n\t\t\t\t\t\t\tMap[destcell].Shimmer();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tPath[0] = FACING_NONE;\t\t// Path is blocked!\n\t\t\t\t\t\tTrackNumber = -1;\n\t\t\t\t\t\tdest = NULL;\n\t\t\t\t\t\tif (cando == MOVE_DESTROYABLE) {\n\n\t\t\t\t\t\t\tif (Map[destcell].Cell_Object()) {\n\t\t\t\t\t\t\t\tif (!House->Is_Ally(Map[destcell].Cell_Object())) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tIsNewNavCom = false;\n\t\t\t\t\t\t\tTrackIndex = 0;\n\t\t\t\t\t\t\treturn(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[2], CONQUER_PATH_MAX-2);\n\t\t\t\t\t\tPath[CONQUER_PATH_MAX-2] = FACING_NONE;\n\t\t\t\t\t\tIsPlanningToLook = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tmemcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);\n\t\t\t\t}\n\t\t\t\tPath[CONQUER_PATH_MAX-1] = FACING_NONE;\n\t\t\t}\n\t\t}\n\n\t\tIsNewNavCom = false;\n\t\tTrackIndex = 0;\n\t\tif (!Start_Driver(dest)) {\n\t\t\tTrackNumber = -1;\n\t\t\tPath[0] = FACING_NONE;\n\t\t\tSet_Speed(0);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DriveClass::AI -- Processes unit movement and rotation.                                     *\n *                                                                                             *\n *    This routine is used to process unit movement and rotation. It                           *\n *    functions autonomously from the script system. Thus, once a unit                         *\n *    is give rotation command or movement path, it will follow this                           *\n *    until specifically instructed to stop. The advantage of this                             *\n *    method is that it allows smooth movement of units, faster game                           *\n *    execution, and reduced script complexity (since actual movement                          *\n *    dynamics need not be controlled directly by the scripts).                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine relies on the process control bits for the                         *\n *             specified unit (for speed reasons). Thus, only setting                          *\n *             movement, rotation, or path list will the unit perform                          *\n *             any physics.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/26/1993 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::AI(void)\n{\n\tassert(IsActive);\n\n\tFootClass::AI();\n\tif (!IsActive || Height > 0) return;\n\n\t/*\n\t** Is this a unit that's been teleported using the chronosphere, and if so,\n\t** has his timer expired such that he needs to teleport back?\n\t*/\n\tif (IsMoebius) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t if (What_Am_I() != RTTI_UNIT || ((UnitClass *)this)->Class->Type != UNIT_CHRONOTANK) {\n#endif\n\t\tif (MoebiusCountDown == 0) {\n\t\t\tIsMoebius = false;\n\t\t\tTeleport_To(MoebiusCell);\n\t\t\tMoebiusCell = 0;\n\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t }\n#endif\n\t}\n\n\t/*\n\t**\tIf the unit is following a track, then continue\n\t**\tto do so -- mindlessly.\n\t*/\n\tif (TrackNumber != -1) {\n\n\t\t/*\n\t\t**\tPerform the movement accumulation.\n\t\t*/\n\t\tWhile_Moving();\n\t\tif (!IsActive) return;\n\t\tif (TrackNumber == -1 && (Target_Legal(NavCom) || Path[0] != FACING_NONE) && (What_Am_I() != RTTI_UNIT || !((UnitClass*)this)->IsDumping)) {\n\t\t\tStart_Of_Move();\n\t\t\tif (!IsActive) return;\n\t\t\tWhile_Moving();\n\t\t\tif (!IsActive) return;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tFor tracked units that are rotating in place, perform the rotation now.\n\t\t*/\n#ifdef TOFIX\n\t\tif ((Class->Speed == SPEED_FLOAT || Class->Speed == SPEED_HOVER || Class->Speed == SPEED_TRACK || (Class->Speed == SPEED_WHEEL && !Special.IsThreePoint)) && PrimaryFacing.Is_Rotating()) {\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Class->ROT)) {\n\t\t\t\tMark(MARK_CHANGE);\n\t\t\t}\n#else\n\t\tif (PrimaryFacing.Is_Rotating()) {\n\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\tif (PrimaryFacing.Rotation_Adjust(Techno_Type_Class()->ROT * House->GroundspeedBias)) {\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t}\n#endif\n\t\t\tif (!IsRotating) {\n\t\t\t\tPer_Cell_Process(PCP_ROTATION);\n\t\t\t\tif (!IsActive) return;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThe unit has no track to follow, but if there\n\t\t\t**\tis a navigation target or a remaining path,\n\t\t\t**\tthen start on a new track.\n\t\t\t*/\n\t\t\tif ((Mission != MISSION_GUARD || Target_Legal(NavCom)) && Mission != MISSION_UNLOAD) {\n\t\t\t\tif (Target_Legal(NavCom) || Path[0] != FACING_NONE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDouble check to make sure that the movement destination is\n\t\t\t\t\t**\tin a zone that this unit can travel to. If not, then abort\n\t\t\t\t\t**\tthe navigation target. Exception is to allow units to leave\n\t\t\t\t\t**\timpassable cells regardless of zone checks.\n\t\t\t\t\t*/\n\t\t\t\t\tLandType land = LAND_NONE;\n\t\t\t\t\tif (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\tland = Map[Center_Coord()].Land_Type();\n\t\t\t\t\t}\n\t\t\t\t\tif (IsLocked && Mission != MISSION_ENTER && Target_Legal(NavCom) && !Is_In_Same_Zone(As_Cell(NavCom)) &&\n\t\t\t\t\t\tland != LAND_ROCK && land != LAND_WATER && land != LAND_RIVER && !Team) {\n\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStart_Of_Move();\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t\tWhile_Moving();\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tStop_Driver();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                   *\n *                                                                                             *\n *    This routine modifies the path of the specified unit so that it                          *\n *    will not start out with a rotation. This is necessary for those                          *\n *    vehicles that have difficulty with rotating in place. Typically,                         *\n *    this includes wheeled vehicles.                                                          *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit to adjust.                                            *\n *                                                                                             *\n *          path  -- Pointer to path structure.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only units that require a fixup get modified. The                               *\n *             modification only occurs, if there is a legal path to                           *\n *             do so.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/03/1994 JLB : Created.                                                                 *\n *   04/06/1994 JLB : Uses path structure.                                                     *\n *   04/10/1994 JLB : Diagonal smooth turn added.                                              *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid DriveClass::Fixup_Path(PathType * path)\n{\n\tassert(IsActive);\n\n\tFacingType stage[6]={FACING_N,FACING_N,FACING_N,FACING_N,FACING_N,FACING_N};\t\t// Prefix path elements.\n\tint\tfacediff;\t\t// The facing difference value (0..4 | 0..-4).\n\tstatic FacingType _path[4][6] = {\n\t\t{(FacingType)2,(FacingType)0,(FacingType)2,(FacingType)0,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}\n\t};\n\tstatic FacingType _dpath[4][6] = {\n\t\t{(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},\n\t\t{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0},\n\t\t{(FacingType)5,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}\n\t};\n\n\tint\t\t\tindex;\n\tint\t\t\tcounter;\t\t\t// Path addition\n\tFacingType\t* ptr;\t\t\t\t// Path list pointer.\n\tFacingType\t* ptr2;\t\t\t// Copy of new path list pointer.\n\tFacingType\tnextpath;\t\t// Next path value.\n\tCELL\t\t\tcell;\t\t\t\t// Working cell value.\n\tbool\t\t\tok;\n\n\t/*\n\t**\tVerify that the unit is valid and there is a path problem to resolve.\n\t*/\n\tif (!path || path->Command[0] == FACING_NONE) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOnly wheeled vehicles need a path fixup -- to avoid 3 point turns.\n\t*/\n#ifdef TOFIX\n\tif (!Special.IsThreePoint || Class->Speed != SPEED_WHEEL) {\n#else\n\tif (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) {\n//\tif (What_Am_I() == RTTI_UNIT) {\n#endif\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the original path starts in the same direction as the unit, then\n\t**\tthere is no problem to resolve -- abort.\n\t*/\n\tfacediff = PrimaryFacing.Difference((DirType)(path->Command[0]<<5)) >> 5;\n\n\tif (!facediff) return;\n\n\tif (Dir_Facing(PrimaryFacing) & FACING_NE) {\n\t\tptr = &_dpath[(FacingType)ABS((int)facediff)-FACING_NE][1];\t\t\t// Pointer to path adjust list.\n \t\tcounter = (int)_dpath[(FacingType)ABS((int)facediff)-FACING_NE][0];\t\t// Number of path adjusts.\n\t} else {\n\t\tptr = &_path[(FacingType)ABS((int)facediff)-FACING_NE][1];\t\t\t// Pointer to path adjust list.\n \t\tcounter = (int)_path[(FacingType)ABS((int)facediff)-FACING_NE][0];\t\t// Number of path adjusts.\n\t}\n\tptr2 = ptr;\n\n\tok = true;\t\t\t\t\t\t\t\t\t\t// Presume adjustment is all ok.\n\tcell = Coord_Cell(Coord);\t// Starting cell.\n\tnextpath = Dir_Facing(PrimaryFacing);\t// Starting path.\n\tfor (index = 0; index < counter; index++) {\n\n\t\t/*\n\t\t**\tDetermine next path element and add it to the\n\t\t**\tworking path list.\n\t\t*/\n\t\tif (facediff > 0) {\n\t\t\tnextpath = nextpath + *ptr++;\n\t\t} else {\n\t\t\tnextpath = nextpath - *ptr++;\n\t\t}\n\t\tstage[index] = nextpath;\n\t\tcell = Adjacent_Cell(cell, nextpath);\n\t\t//cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));\n\n\t\t/*\n\t\t**\tIf it can't enter this cell, then abort the path\n\t\t**\tbuilding operation without adjusting the unit's\n\t\t**\tpath.\n\t\t*/\n\t\tif (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {\n\t\t\tok = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf veering to the left was not successful, then try veering\n\t**\tto the right. This only makes sense if the vehicle is trying\n\t**\tto turn 180 degrees.\n\t*/\n\tif (!ok && ABS(facediff) == 4) {\n\t\tptr = ptr2;\t\t\t\t\t\t\t\t\t\t\t// Pointer to path adjust list.\n\t\tfacediff = -facediff;\n\t\tok = true;\t\t\t\t\t\t\t\t\t\t\t// Presume adjustment is all ok.\n\t\tcell = Coord_Cell(Coord);\t\t\t\t\t\t// Starting cell.\n\t\tnextpath = Dir_Facing(PrimaryFacing);\t\t// Starting path.\n\t\tfor (index = 0; index < counter; index++) {\n\n\t\t\t/*\n\t\t\t**\tDetermine next path element and add it to the\n\t\t\t**\tworking path list.\n\t\t\t*/\n\t\t\tif (facediff > 0) {\n\t\t\t\tnextpath = nextpath + *ptr++;\n\t\t\t} else {\n\t\t\t\tnextpath = nextpath - *ptr++;\n\t\t\t}\n\t\t\tstage[index] = nextpath;\n\t\t\tcell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));\n\n\t\t\t/*\n\t\t\t**\tIf it can't enter this cell, then abort the path\n\t\t\t**\tbuilding operation without adjusting the unit's\n\t\t\t**\tpath.\n\t\t\t*/\n\t\t\tif (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {\n\t\t\t\tok = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a legal path addition was created, then install it in place\n\t**\tof the first path value. The initial path entry is to be replaced\n\t**\twith a sequence of path entries that create smooth turning.\n\t*/\n\tif (ok) {\n\t\tif (path->Length <= 1) {\n\t\t\tmemmove((char *)&stage[0], (char*)path->Command, max(counter, 1));\n\t\t\tpath->Length = counter;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tOptimize the transition path step from the smooth turn\n\t\t\t**\tfirst part as it joins with the rest of the normal\n\t\t\t**\tpath. The normal prefix path steps are NOT to be optimized.\n\t\t\t*/\n\t\t\tif (counter) {\n\t\t\t\tcounter--;\n\t\t\t\tpath->Command[0] = stage[counter];\n\t\t\t\tOptimize_Moves(path, MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is more than one prefix path element, then\n\t\t\t**\tinsert the rest now.\n\t\t\t*/\n\t\t\tif (counter) {\n\t\t\t\tmemmove((char*)&path->Command[0], (char*)&path->Command[counter], 40-counter);\n\t\t\t\tmemmove((char*)&stage[0], (char*)&path->Command[0], counter);\n\t\t\t\tpath->Length += counter;\n\t\t\t}\n\t\t}\n\t\tpath->Command[path->Length] = FACING_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Lay_Track -- Handles track laying logic for the unit.                           *\n *                                                                                             *\n *    This routine handles the track laying for the unit. This entails examining the unit's    *\n *    current location as well as the direction and whether this unit is allowed to lay        *\n *    tracks in the first place.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Lay_Track(void)\n{\n\tassert(IsActive);\n\n#ifdef NEVER\n\tstatic IconCommandType * _trackdirs[8] = {\n\t\tTrackN_S,\n\t\tTrackNE_SW,\n\t\tTrackE_W,\n\t\tTrackNW_SE,\n\t\tTrackN_S,\n\t\tTrackNE_SW,\n\t\tTrackE_W,\n\t\tTrackNW_SE\n\t};\n\n\tif (!(ClassF & CLASSF_TRACKS)) return;\n\n\tIcon_Install(Coord_Cell(Coord), _trackdirs[Facing_To_8(BodyFacing)]);\n#endif\n}\n\n\n/***********************************************************************************************\n * DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                      *\n *                                                                                             *\n *    This routine will ensure that the midpoint (if any) of the track that the unit is        *\n *    following, will be marked according to the mark type specified.                          *\n *                                                                                             *\n * INPUT:   headto   -- The head to coordinate.                                                *\n *                                                                                             *\n *          type     -- The type of marking to perform.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid DriveClass::Mark_Track(COORDINATE headto, MarkType type)\n{\n\tassert(IsActive);\n\n\tint value;\n\n\tif (type == MARK_UP) {\n\t\tvalue = false;\n\t} else {\n\t\tvalue = true;\n\t}\n\n\tif (headto) {\n\t\tif (!IsOnShortTrack && TrackNumber != -1) {\n\n\t\t\t/*\n\t\t\t** If we have not passed the per cell process point we need\n\t\t\t** to deal with it.\n\t\t\t*/\n\t\t\tint tracknum = TrackControl[TrackNumber].Track;\n\t\t\tif (tracknum) {\n\t\t\t\tTrackType const * ptr = RawTracks[tracknum - 1].Track;\n\t\t\t\tint cellidx = RawTracks[tracknum - 1].Cell;\n\t\t\t\tif (cellidx > -1) {\n\t\t\t\t\tDirType dir = ptr[cellidx].Facing;\n\n\t\t\t\t\tif (TrackIndex < cellidx && cellidx != -1) {\n\t\t\t\t\t\tCOORDINATE offset = Smooth_Turn(ptr[cellidx].Offset, dir);\n\t\t\t\t\t\tMap[offset].Flag.Occupy.Vehicle = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMap[headto].Flag.Occupy.Vehicle = value;\n\t}\n}\n\n\n/***********************************************************************************************\n * DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                    *\n *                                                                                             *\n *    This routine is used to verify that this object is allowed to move. Some objects can     *\n *    be temporarily occupied and thus cannot move until the situation permits.                *\n *                                                                                             *\n * INPUT:   direction   -- The direction that movement would be desired.                       *\n *                                                                                             *\n * OUTPUT:  Can the unit move in the direction specified?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool DriveClass::Ok_To_Move(DirType ) const\n{\n\tassert(IsActive);\n\n\treturn true;\n}\n\n\n/***************************************************************************\n**\tSmooth turn track tables. These are coordinate offsets from the center\n**\tof the destination cell. These are the raw tracks that are modified\n**\tby negating the X and Y portions as necessary. Also for reverse travelling\n**\tdirection, the track list can be processed backward.\n**\n**\tTrack 1 = N\n**\tTrack 2 = NE\n**\tTrack 3 = N->NE 45 deg (double path consumption)\n**\tTrack 4 = N->E 90 deg (double path consumption)\n**\tTrack 5 = NE->SE 90 deg (double path consumption)\n** Track 6 = NE->N 45 deg (double path consumption)\n**\tTrack 7 = N->NE (facing change only)\n**\tTrack 8 = NE->E (facing change only)\n**\tTrack 9 = N->E (facing change only)\n**\tTrack 10= NE->SE (facing change only)\n**\tTrack 11= back up into refinery\n**\tTrack 12= drive out of refinery\n*/\n//#pragma warn -ias\nDriveClass::TrackType const DriveClass::Track1[24] = {\n\t{0x00F50000L,(DirType)0},\n\t{0x00EA0000L,(DirType)0},\n\t{0x00DF0000L,(DirType)0},\n\t{0x00D40000L,(DirType)0},\n\t{0x00C90000L,(DirType)0},\n\t{0x00BE0000L,(DirType)0},\n\t{0x00B30000L,(DirType)0},\n\t{0x00A80000L,(DirType)0},\n\t{0x009D0000L,(DirType)0},\n\t{0x00920000L,(DirType)0},\n\t{0x00870000L,(DirType)0},\n\t{0x007C0000L,(DirType)0},\t\t// Track jump check here.\n\t{0x00710000L,(DirType)0},\n\t{0x00660000L,(DirType)0},\n\t{0x005B0000L,(DirType)0},\n\t{0x00500000L,(DirType)0},\n\t{0x00450000L,(DirType)0},\n\t{0x003A0000L,(DirType)0},\n\t{0x002F0000L,(DirType)0},\n\t{0x00240000L,(DirType)0},\n\t{0x00190000L,(DirType)0},\n\t{0x000E0000L,(DirType)0},\n\t{0x00030000L,(DirType)0},\n\t{0x00000000L,(DirType)0}\n};\n\nDriveClass::TrackType const DriveClass::Track2[] = {\n\t{0x00F8FF08L,(DirType)32},\n\t{0x00F0FF10L,(DirType)32},\n\t{0x00E8FF18L,(DirType)32},\n\t{0x00E0FF20L,(DirType)32},\n\t{0x00D8FF28L,(DirType)32},\n\t{0x00D0FF30L,(DirType)32},\n\t{0x00C8FF38L,(DirType)32},\n\t{0x00C0FF40L,(DirType)32},\n\t{0x00B8FF48L,(DirType)32},\n\t{0x00B0FF50L,(DirType)32},\n\t{0x00A8FF58L,(DirType)32},\n\t{0x00A0FF60L,(DirType)32},\n\t{0x0098FF68L,(DirType)32},\n\t{0x0090FF70L,(DirType)32},\n\t{0x0088FF78L,(DirType)32},\n\t{0x0080FF80L,(DirType)32},\t\t// Track jump check here.\n\t{0x0078FF88L,(DirType)32},\n\t{0x0070FF90L,(DirType)32},\n\t{0x0068FF98L,(DirType)32},\n\t{0x0060FFA0L,(DirType)32},\n\t{0x0058FFA8L,(DirType)32},\n\t{0x0050FFB0L,(DirType)32},\n\t{0x0048FFB8L,(DirType)32},\n\t{0x0040FFC0L,(DirType)32},\n\t{0x0038FFC8L,(DirType)32},\n\t{0x0030FFD0L,(DirType)32},\n\t{0x0028FFD8L,(DirType)32},\n\t{0x0020FFE0L,(DirType)32},\n\t{0x0018FFE8L,(DirType)32},\n\t{0x0010FFF0L,(DirType)32},\n\t{0x0008FFF8L,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track3[] = {\n\t{0x01F5FF00L,(DirType)0},\n\t{0x01EAFF00L,(DirType)0},\n\t{0x01DFFF00L,(DirType)0},\n\t{0x01D4FF00L,(DirType)0},\n\t{0x01C9FF00L,(DirType)0},\n\t{0x01BEFF00L,(DirType)0},\n\t{0x01B3FF00L,(DirType)0},\n\t{0x01A8FF00L,(DirType)0},\n\t{0x019DFF00L,(DirType)0},\n\t{0x0192FF00L,(DirType)0},\n\t{0x0187FF00L,(DirType)0},\n\t{0x0180FF00L,(DirType)0},\n\t{0x0175FF00L,(DirType)0},\t\t// Jump entry point here.\n\t{0x016BFF00L,(DirType)0},\n\t{0x0160FF02L,(DirType)1},\n\t{0x0155FF04L,(DirType)3},\n\t{0x014CFF06L,(DirType)4},\n\t{0x0141FF08L,(DirType)5},\n\t{0x0137FF0BL,(DirType)7},\n\t{0x012EFF0FL,(DirType)8},\n\t{0x0124FF13L,(DirType)9},\n\t{0x011AFF17L,(DirType)11},\n\t{0x0110FF1BL,(DirType)12},\n\t{0x0107FF1FL,(DirType)13},\t\t// Center cell processing here.\n\t{0x00FCFF24L,(DirType)15},\n\t{0x00F3FF28L,(DirType)16},\n\t{0x00ECFF2CL,(DirType)17},\n\t{0x00E0FF32L,(DirType)19},\n\t{0x00D7FF36L,(DirType)20},\n\t{0x00CFFF3DL,(DirType)21},\n\t{0x00C6FF42L,(DirType)23},\n\t{0x00BAFF49L,(DirType)24},\n\t{0x00B0FF4DL,(DirType)25},\n\t{0x00A8FF58L,(DirType)27},\n\t{0x00A0FF60L,(DirType)28},\n\t{0x0098FF68L,(DirType)29},\n\t{0x0090FF70L,(DirType)31},\n\t{0x0088FF78L,(DirType)32},\n\t{0x0080FF80L,(DirType)32},\t\t// Track jump check here.\n\t{0x0078FF88L,(DirType)32},\n\t{0x0070FF90L,(DirType)32},\n\t{0x0068FF98L,(DirType)32},\n\t{0x0060FFA0L,(DirType)32},\n\t{0x0058FFA8L,(DirType)32},\n\t{0x0050FFB0L,(DirType)32},\n\t{0x0048FFB8L,(DirType)32},\n\t{0x0040FFC0L,(DirType)32},\n\t{0x0038FFC8L,(DirType)32},\n\t{0x0030FFD0L,(DirType)32},\n\t{0x0028FFD8L,(DirType)32},\n\t{0x0020FFE0L,(DirType)32},\n\t{0x0018FFE8L,(DirType)32},\n\t{0x0010FFF0L,(DirType)32},\n\t{0x0008FFF8L,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track4[] = {\n\t{0x00F5FF00L,(DirType)0},\n\t{0x00EBFF00L,(DirType)0},\n\t{0x00E0FF00L,(DirType)0},\n\t{0x00D5FF00L,(DirType)0},\n\t{0x00CBFF01L,(DirType)0},\n\t{0x00C0FF03L,(DirType)0},\n\t{0x00B5FF05L,(DirType)1},\n\t{0x00ABFF07L,(DirType)1},\n\t{0x00A0FF0AL,(DirType)2},\n\t{0x0095FF0DL,(DirType)3},\n\t{0x008BFF10L,(DirType)4},\n\t{0x0080FF14L,(DirType)5},\t\t// Track entry here.\n\t{0x0075FF18L,(DirType)8},\n\t{0x006DFF1CL,(DirType)12},\n\t{0x0063FF22L,(DirType)16},\n\t{0x005AFF25L,(DirType)20},\n\t{0x0052FF2BL,(DirType)23},\n\t{0x0048FF32L,(DirType)27},\n\t{0x0040FF37L,(DirType)32},\n\t{0x0038FF3DL,(DirType)36},\n\t{0x0030FF46L,(DirType)39},\n\t{0x002BFF4FL,(DirType)43},\n\t{0x0024FF58L,(DirType)47},\n\t{0x0020FF60L,(DirType)51},\n\t{0x001BFF6DL,(DirType)54},\n\t{0x0017FF79L,(DirType)57},\n\t{0x0014FF82L,(DirType)60},\t\t// Track jump here.\n\t{0x0011FF8FL,(DirType)62},\n\t{0x000DFF98L,(DirType)63},\n\t{0x0009FFA2L,(DirType)64},\n\t{0x0006FFACL,(DirType)64},\n\t{0x0004FFB5L,(DirType)66},\n\t{0x0003FFC0L,(DirType)64},\n\t{0x0002FFCBL,(DirType)64},\n\t{0x0001FFD5L,(DirType)64},\n\t{0x0000FFE0L,(DirType)64},\n\t{0x0000FFEBL,(DirType)64},\n\t{0x0000FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track5[] = {\n\t{0xFFF8FE08L,(DirType)32},\n\t{0xFFF0FE10L,(DirType)32},\n\t{0xFFE8FE18L,(DirType)32},\n\t{0xFFE0FE20L,(DirType)32},\n\t{0xFFD8FE28L,(DirType)32},\n\t{0xFFD0FE30L,(DirType)32},\n\t{0xFFC8FE38L,(DirType)32},\n\t{0xFFC0FE40L,(DirType)32},\n\t{0xFFB8FE48L,(DirType)32},\n\t{0xFFB0FE50L,(DirType)32},\n\t{0xFFA8FE58L,(DirType)32},\n\t{0xFFA0FE60L,(DirType)32},\n\t{0xFF98FE68L,(DirType)32},\n\t{0xFF90FE70L,(DirType)32},\n\t{0xFF88FE78L,(DirType)32},\n\t{0xFF80FE80L,(DirType)32},\t\t// Track entry here.\n\t{0xFF78FE88L,(DirType)32},\n\t{0xFF71FE90L,(DirType)32},\n\t{0xFF6AFE97L,(DirType)32},\n\t{0xFF62FE9FL,(DirType)32},\n\t{0xFF5AFEA8L,(DirType)32},\n\t{0xFF53FEB0L,(DirType)35},\n\t{0xFF4BFEB7L,(DirType)38},\n\t{0xFF44FEBEL,(DirType)41},\n\t{0xFF3EFEC4L,(DirType)44},\n\t{0xFF39FECEL,(DirType)47},\n\t{0xFF34FED8L,(DirType)50},\n\t{0xFF30FEE0L,(DirType)53},\n\t{0xFF2DFEEBL,(DirType)56},\n\t{0xFF2CFEF5L,(DirType)59},\n\t{0xFF2BFF00L,(DirType)62},\n\t{0xFF2CFF0BL,(DirType)66},\n\t{0xFF2DFF15L,(DirType)69},\n\t{0xFF30FF1FL,(DirType)72},\n\t{0xFF34FF28L,(DirType)75},\n\t{0xFF39FF30L,(DirType)78},\n\t{0xFF3EFF3AL,(DirType)81},\n\t{0xFF44FF44L,(DirType)84},\n\t{0xFF4BFF4BL,(DirType)87},\n\t{0xFF53FF50L,(DirType)90},\n\t{0xFF5AFF58L,(DirType)93},\n\t{0xFF62FF60L,(DirType)96},\n\t{0xFF6AFF68L,(DirType)96},\n\t{0xFF71FF70L,(DirType)96},\n\t{0xFF78FF78L,(DirType)96},\n\t{0xFF80FF80L,(DirType)96},\t\t// Track jump check here.\n\t{0xFF88FF88L,(DirType)96},\n\t{0xFF90FF90L,(DirType)96},\n\t{0xFF98FF98L,(DirType)96},\n\t{0xFFA0FFA0L,(DirType)96},\n\t{0xFFA8FFA8L,(DirType)96},\n\t{0xFFB0FFB0L,(DirType)96},\n\t{0xFFB8FFB8L,(DirType)96},\n\t{0xFFC0FFC0L,(DirType)96},\n\t{0xFFC8FFC8L,(DirType)96},\n\t{0xFFD0FFD0L,(DirType)96},\n\t{0xFFD8FFD8L,(DirType)96},\n\t{0xFFE0FFE0L,(DirType)96},\n\t{0xFFE8FFE8L,(DirType)96},\n\t{0xFFF0FFF0L,(DirType)96},\n\t{0xFFF8FFF8L,(DirType)96},\n\t{0x00000000L,(DirType)96}\n};\n\nDriveClass::TrackType const DriveClass::Track6[] = {\n\t{0x0100FE00L,(DirType)32},\n\t{0x00F8FE08L,(DirType)32},\n\t{0x00F0FE10L,(DirType)32},\n\t{0x00E8FE18L,(DirType)32},\n\t{0x00E0FE20L,(DirType)32},\n\t{0x00D8FE28L,(DirType)32},\n\t{0x00D0FE30L,(DirType)32},\n\t{0x00C8FE38L,(DirType)32},\n\t{0x00C0FE40L,(DirType)32},\n\t{0x00B8FE48L,(DirType)32},\n\t{0x00B0FE50L,(DirType)32},\n\t{0x00A8FE58L,(DirType)32},\n\t{0x00A0FE60L,(DirType)32},\n\t{0x0098FE68L,(DirType)32},\n\t{0x0090FE70L,(DirType)32},\n\t{0x0088FE78L,(DirType)32},\n\t{0x0080FE80L,(DirType)32},\t\t// Jump entry point here.\n\t{0x0078FE88L,(DirType)32},\n\t{0x0070FE90L,(DirType)32},\n\t{0x0068FE98L,(DirType)32},\n\t{0x0060FEA0L,(DirType)32},\n\t{0x0058FEA8L,(DirType)32},\n\t{0x0055FEAEL,(DirType)32},\n\t{0x004EFEB8L,(DirType)35},\n\t{0x0048FEC0L,(DirType)37},\n\t{0x0042FEC9L,(DirType)40},\n\t{0x003BFED2L,(DirType)43},\n\t{0x0037FEDAL,(DirType)45},\n\t{0x0032FEE3L,(DirType)48},\n\t{0x002BFEEBL,(DirType)51},\n\t{0x0026FEF5L,(DirType)53},\n\t{0x0022FEFEL,(DirType)56},\n\t{0x001CFF08L,(DirType)59},\n\t{0x0019FF12L,(DirType)61},\n\t{0x0015FF1BL,(DirType)64},\n\t{0x0011FF26L,(DirType)64},\n\t{0x000EFF30L,(DirType)64},\n\t{0x000BFF39L,(DirType)64},\n\t{0x0009FF43L,(DirType)64},\n\t{0x0007FF4EL,(DirType)64},\n\t{0x0005FF57L,(DirType)64},\n\t{0x0003FF62L,(DirType)64},\n\t{0x0001FF6DL,(DirType)64},\n\t{0x0000FF77L,(DirType)64},\n\t{0x0000FF80L,(DirType)64},\t\t// Track jump check here.\n\t{0x0000FF8BL,(DirType)64},\n\t{0x0000FF95L,(DirType)64},\n\t{0x0000FFA0L,(DirType)64},\n\t{0x0000FFABL,(DirType)64},\n\t{0x0000FFB5L,(DirType)64},\n\t{0x0000FFC0L,(DirType)64},\n\t{0x0000FFCBL,(DirType)64},\n\t{0x0000FFD5L,(DirType)64},\n\t{0x0000FFE0L,(DirType)64},\n\t{0x0000FFEBL,(DirType)64},\n\t{0x0000FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track7[] = {\n\t{0x0006FFFFL,(DirType)0},\n\t{0x000CFFFEL,(DirType)4},\n\t{0x0011FFFCL,(DirType)8},\n\t{0x0018FFFAL,(DirType)12},\n\t{0x001FFFF6L,(DirType)16},\n\t{0x0024FFF3L,(DirType)19},\n\t{0x002BFFF0L,(DirType)22},\n\t{0x0030FFFDL,(DirType)23},\n\t{0x0035FFEBL,(DirType)24},\n\t{0x0038FFE8L,(DirType)25},\n\t{0x003CFFE6L,(DirType)26},\n\t{0x0040FFE3L,(DirType)27},\n\t{0x0043FFE0L,(DirType)28},\n\t{0x0046FFDDL,(DirType)29},\n\t{0x0043FFDFL,(DirType)30},\n\t{0x0040FFE1L,(DirType)30},\n\t{0x003CFFE3L,(DirType)30},\n\t{0x0038FFE5L,(DirType)30},\n\t{0x0035FFE7L,(DirType)31},\n\t{0x0030FFE9L,(DirType)31},\n\t{0x002BFFEBL,(DirType)31},\n\t{0x0024FFEDL,(DirType)31},\n\t{0x001FFFF1L,(DirType)31},\n\t{0x0018FFF4L,(DirType)32},\n\t{0x0011FFF7L,(DirType)32},\n\t{0x000CFFFAL,(DirType)32},\n\t{0x0006FFFDL,(DirType)32},\n\t{0x00000000L,(DirType)32}\n};\n\nDriveClass::TrackType const DriveClass::Track8[] = {\n\t{0x0003FFFCL,(DirType)32},\n\t{0x0006FFF7L,(DirType)36},\n\t{0x000AFFF1L,(DirType)40},\n\t{0x000CFFEBL,(DirType)44},\n\t{0x000DFFE4L,(DirType)46},\n\t{0x000EFFDCL,(DirType)48},\n\t{0x000FFFD5L,(DirType)50},\n\t{0x0010FFD0L,(DirType)52},\n\t{0x0011FFC9L,(DirType)54},\n\t{0x0012FFC2L,(DirType)56},\n\t{0x0011FFC0L,(DirType)58},\n\t{0x0010FFC2L,(DirType)60},\n\t{0x000EFFC9L,(DirType)62},\n\t{0x000CFFCFL,(DirType)64},\n\t{0x000AFFD5L,(DirType)64},\n\t{0x0008FFDAL,(DirType)64},\n\t{0x0006FFE2L,(DirType)64},\n\t{0x0004FFE9L,(DirType)64},\n\t{0x0002FFEFL,(DirType)64},\n\t{0x0001FFF5L,(DirType)64},\n\t{0x0000FFF9L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track9[] = {\n\t{0xFFF50002L,(DirType)0},\n\t{0xFFEB0004L,(DirType)2},\n\t{0xFFE00006L,(DirType)4},\n\t{0xFFD50009L,(DirType)6},\n\t{0xFFCE000CL,(DirType)9},\n\t{0xFFC8000FL,(DirType)11},\n\t{0xFFC00012L,(DirType)13},\n\t{0xFFB80015L,(DirType)16},\n\t{0xFFC00012L,(DirType)18},\n\t{0xFFC8000EL,(DirType)20},\n\t{0xFFCE000AL,(DirType)22},\n\t{0xFFD50004L,(DirType)24},\n\t{0xFFDE0000L,(DirType)26},\n\t{0xFFE9FFF8L,(DirType)28},\n\t{0xFFEEFFF2L,(DirType)30},\n\t{0xFFF5FFEBL,(DirType)32},\n\t{0xFFFDFFE1L,(DirType)34},\n\t{0x0002FFD8L,(DirType)36},\n\t{0x0007FFD2L,(DirType)39},\n\t{0x000BFFCBL,(DirType)41},\n\t{0x0010FFC5L,(DirType)43},\n\t{0x0013FFBEL,(DirType)45},\n\t{0x0015FFB7L,(DirType)48},\n\t{0x0013FFBEL,(DirType)50},\n\t{0x0011FFC5L,(DirType)52},\n\t{0x000BFFCCL,(DirType)54},\n\t{0x0008FFD4L,(DirType)56},\n\t{0x0005FFDFL,(DirType)58},\n\t{0x0003FFEBL,(DirType)62},\n\t{0x0001FFF5L,(DirType)64},\n\t{0x00000000L,(DirType)64}\n};\n\nDriveClass::TrackType const DriveClass::Track10[] = {\n\t{0xFFF6000BL,(DirType)32},\n\t{0xFFF00015L,(DirType)37},\n\t{0xFFEB0020L,(DirType)42},\n\t{0xFFE9002BL,(DirType)47},\n\t{0xFFE50032L,(DirType)52},\n\t{0xFFE30038L,(DirType)57},\n\t{0xFFE00040L,(DirType)60},\n\t{0xFFE20038L,(DirType)62},\n\t{0xFFE40032L,(DirType)64},\n\t{0xFFE5002AL,(DirType)68},\n\t{0xFFE6001EL,(DirType)70},\n\t{0xFFE70015L,(DirType)72},\n\t{0xFFE8000BL,(DirType)74},\n\t{0xFFE90000L,(DirType)76},\n\t{0xFFE8FFF5L,(DirType)78},\n\t{0xFFE7FFEBL,(DirType)80},\n\t{0xFFE6FFE0L,(DirType)82},\n\t{0xFFE5FFD5L,(DirType)84},\n\t{0xFFE4FFCEL,(DirType)86},\n\t{0xFFE2FFC5L,(DirType)88},\n\t{0xFFE0FFC0L,(DirType)90},\n\t{0xFFE3FFC5L,(DirType)92},\n\t{0xFFE5FFCEL,(DirType)94},\n\t{0xFFE9FFD5L,(DirType)95},\n\t{0xFFEBFFE0L,(DirType)96},\n\t{0xFFF0FFEBL,(DirType)96},\n\t{0xFFF6FFF5L,(DirType)96},\n\t{0x00000000L,(DirType)96}\n};\n\nDriveClass::TrackType const DriveClass::Track11[] = {\n\t{0x01000000L,DIR_SW},\n\t{0x00F30008L,DIR_SW},\n\t{0x00E50010L,DIR_SW_X1},\n\t{0x00D60018L,DIR_SW_X1},\n\t{0x00C80020L,DIR_SW_X1},\n\t{0x00B90028L,DIR_SW_X1},\n\t{0x00AB0030L,DIR_SW_X2},\n\t{0x009C0038L,DIR_SW_X2},\n\t{0x008D0040L,DIR_SW_X2},\n\t{0x007F0048L,DIR_SW_X2},\n\t{0x00710050L,DIR_SW_X2},\n\t{0x00640058L,DIR_SW_X2},\n\t{0x00550060L,DIR_SW_X2},\n\n\t{0x00000000L,DIR_SW_X2}\n};\n\nDriveClass::TrackType const DriveClass::Track12[] = {\n\t{0xFF550060L,DIR_SW_X2},\n\t{0xFF640058L,DIR_SW_X2},\n\t{0xFF710050L,DIR_SW_X2},\n\t{0xFF7F0048L,DIR_SW_X2},\n\t{0xFF8D0040L,DIR_SW_X2},\n\t{0xFF9C0038L,DIR_SW_X2},\n\t{0xFFAB0030L,DIR_SW_X2},\n\t{0xFFB90028L,DIR_SW_X1},\n\t{0xFFC80020L,DIR_SW_X1},\n\t{0xFFD60018L,DIR_SW_X1},\n\t{0xFFE50010L,DIR_SW_X1},\n\t{0xFFF30008L,DIR_SW},\n\n\t{0x00000000L,DIR_SW}\n};\n\n#if(1)\n/*\n**\tDrive out of weapon's factory.\n*/\nDriveClass::TrackType const DriveClass::Track13[] = {\n\t{XYP_COORD(0,-35),DIR_S},\n\t{XYP_COORD(0,-34),DIR_S},\n\t{XYP_COORD(0,-33),DIR_S},\n\t{XYP_COORD(0,-32),DIR_S},\n\t{XYP_COORD(0,-31),DIR_S},\n\t{XYP_COORD(0,-30),DIR_S},\n\t{XYP_COORD(0,-29),DIR_S},\n\t{XYP_COORD(0,-28),DIR_S},\n\t{XYP_COORD(0,-27),DIR_S},\n\t{XYP_COORD(0,-26),DIR_S},\n\t{XYP_COORD(0,-25),DIR_S},\n\t{XYP_COORD(0,-24),DIR_S},\n\t{XYP_COORD(0,-23),DIR_S},\n\t{XYP_COORD(0,-22),DIR_S},\n\t{XYP_COORD(0,-21),DIR_S},\n\t{XYP_COORD(0,-20),DIR_S},\n\t{XYP_COORD(0,-19),DIR_S},\n\t{XYP_COORD(0,-18),DIR_S},\n\t{XYP_COORD(0,-17),DIR_S},\n\t{XYP_COORD(0,-16),DIR_S},\n\t{XYP_COORD(0,-15),DIR_S},\n\t{XYP_COORD(0,-14),DIR_S},\n\t{XYP_COORD(0,-13),DIR_S},\n\t{XYP_COORD(0,-12),DIR_S},\n\t{XYP_COORD(0,-11),DIR_S},\n\t{XYP_COORD(0,-10),DIR_S},\n\t{XYP_COORD(0,-9),DIR_S},\n\t{XYP_COORD(0,-8),DIR_S},\n\t{XYP_COORD(0,-7),DIR_S},\n\t{XYP_COORD(0,-6),DIR_S},\n\t{XYP_COORD(0,-5),DIR_S},\n\t{XYP_COORD(0,-4),DIR_S},\n\t{XYP_COORD(0,-3),DIR_S},\n\t{XYP_COORD(0,-2),DIR_S},\n\t{XYP_COORD(0,-1),DIR_S},\n\n\t{0x00000000L,DIR_S}\n};\n#else\n/*\n**\tDrive out of weapon's factory.\n*/\nDriveClass::TrackType const DriveClass::Track13[] = {\n\t{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(9,-17),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(8,-16),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(8,-15),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(7,-14),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(7,-13),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(6,-12),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(6,-11),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(5,-10),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(5,-9),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(4,-8),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(4,-7),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(3,-6),(DirType)(DIR_SW-10)},\n\t{XYP_COORD(3,-5),(DirType)(DIR_SW-9)},\n\t{XYP_COORD(2,-4),(DirType)(DIR_SW-7)},\n\t{XYP_COORD(2,-3),(DirType)(DIR_SW-5)},\n\t{XYP_COORD(1,-2),(DirType)(DIR_SW-3)},\n\t{XYP_COORD(1,-1),(DirType)(DIR_SW-1)},\n\n\t{0x00000000L,DIR_SW}\n};\n#endif\n\n/*\n**\tThere are a limited basic number of tracks that a vehicle can follow. These\n**\tare they. Each track can be interpreted differently but this is controlled\n**\tby the TrackControl structure elaborated elsewhere.\n*/\nDriveClass::RawTrackType const DriveClass::RawTracks[13] = {\n\t{Track1, -1, 0, -1},\n\t{Track2, -1, 0, -1},\n\t{Track3, 37, 12, 22},\n\t{Track4, 26, 11, 19},\n\t{Track5, 45, 15, 31},\n\t{Track6, 44, 16, 27},\n\t{Track7, -1, 0, -1},\n\t{Track8, -1, 0, -1},\n\t{Track9, -1, 0, -1},\n\t{Track10, -1, 0, -1},\n\t{Track11, -1, 0, -1},\n\t{Track12, -1, 0, -1},\n\t{Track13, -1, 0, -1}\n};\n\n\n/***************************************************************************\n**\tSmooth turning control table. Given two directions in a path list, this\n**\ttable determines which track to use and what modifying operations need\n**\tbe performed on the track data.\n*/\nDriveClass::TurnTrackType const DriveClass::TrackControl[67] = {\n\t{1,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-0\n\t{3,\t7,\t\tDIR_NE,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-1 (raw chart)\n\t{4,\t9,\t\tDIR_E,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-2 (raw chart)\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-3 !\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-4 !\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t0-5 !\n\t{4,\t9,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t0-6\n\t{3,\t7,\t\tDIR_NW,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t0-7\n\t{6,\t8,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t1-0\n\t{2,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-1 (raw chart)\n\t{6,\t8,\t\tDIR_E,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-2 (raw chart)\n\t{5,\t10,\tDIR_SE,\tF_D},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-3 (raw chart)\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-4 !\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-5 !\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t1-6 !\n\t{5,\t10,\tDIR_NW,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t1-7\n\t{4,\t9,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t2-0\n\t{3,\t7,\t\tDIR_NE,\t(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},\t//\t2-1\n\t{1,\t0,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_T|F_X)},\t\t\t\t//\t2-2\n\t{3,\t7,\t\tDIR_SE,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t2-3\n\t{4,\t9,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t2-4\n\t{0,\t0,\t\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-5 !\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-6 !\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t2-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-0 !\n\t{5,\t10,\tDIR_NE,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t3-1\n\t{6,\t8,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t3-2\n\t{2,\t0,\t\tDIR_SE,\tF_Y},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-3\n\t{6,\t8,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t3-4\n\t{5,\t10,\tDIR_SW,\t(DriveClass::TrackControlType)(F_T|F_X|F_D)},\t\t//\t3-5\n\t{0,\t0,\t\tDIR_W,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-6 !\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t3-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-0 !\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-1 !\n\t{4,\t9,\t\tDIR_E,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t4-2\n\t{3,\t7,\t\tDIR_SE,\t(DriveClass::TrackControlType)(F_Y|F_D)},\t\t\t\t//\t4-3\n\t{1,\t0,\t\tDIR_S,\tF_Y},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-4\n\t{3,\t7,\t\tDIR_SW,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t4-5\n\t{4,\t9,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t4-6\n\t{0,\t0,\t\tDIR_NW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t4-7 !\n\t{0,\t0,\t\tDIR_N,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-0 !\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-1 !\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-2 !\n\t{5,\t10,\tDIR_SE,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t5-3\n\t{6,\t8,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t5-4\n\t{2,\t0,\t\tDIR_SW,\tF_T},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t5-5\n\t{6,\t8,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t5-6\n\t{5,\t10,\tDIR_NW,\t(DriveClass::TrackControlType)(F_X|F_Y|F_D)},\t\t//\t5-7\n\t{4,\t9,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t6-0\n\t{0,\t0,\t\tDIR_NE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-1 !\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-2 !\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-3 !\n\t{4,\t9,\t\tDIR_S,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t6-4\n\t{3,\t7,\t\tDIR_SW,\t(DriveClass::TrackControlType)(F_T|F_D)},\t\t\t\t//\t6-5\n\t{1,\t0,\t\tDIR_W,\tF_T},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t6-6\n\t{3,\t7,\t\tDIR_NW,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t6-7\n\t{6,\t8,\t\tDIR_N,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t7-0\n\t{5,\t10,\tDIR_NE,\t(DriveClass::TrackControlType)(F_T|F_Y|F_D)},\t\t//\t7-1\n\t{0,\t0,\t\tDIR_E,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-2 !\n\t{0,\t0,\t\tDIR_SE,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-3 !\n\t{0,\t0,\t\tDIR_S,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-4 !\n\t{5,\t10,\tDIR_SW,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t7-5\n\t{6,\t8,\t\tDIR_W,\t(DriveClass::TrackControlType)(F_X|F_D)},\t\t\t\t//\t7-6\n\t{2,\t0,\t\tDIR_NW,\tF_X},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\t7-7\n\n\t{11,\t11,\tDIR_SW,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Backup harvester into refinery.\n\t{12,\t12,\tDIR_SW_X2,\tF_},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Drive back into refinery.\n\t{13,\t13,\tDIR_SW,\tF_}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Drive out of weapons factory.\n};\n\n\n\n"
  },
  {
    "path": "REDALERT/DRIVE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DRIVE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DRIVE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DRIVE_H\n#define DRIVE_H\n\n#include\t\"foot.h\"\n\n/****************************************************************************\n**\tMovable objects are handled by this class definition. Moveable objects\n**\tcover everything except buildings.\n*/\nclass DriveClass : public FootClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tIf this unit performing harvesting action, then this flag is true. The flag\n\t\t**\tis located here because the other bit flags here give it a free place to\n\t\t**\treside.\n\t\t*/\n\t\tunsigned IsHarvesting:1;\n\n\t\t/*\n\t\t** This flag controls whether the unit has been moebius'd into a\n\t\t** different location, and whether the MoebiusCountDown timer should be\n\t\t** used to take him back where he belongs.\n\t\t*/\n\t\tunsigned IsMoebius:1;\n\n\t\t/*\n\t\t** This controls how long a unit can exist in its alternate location\n\t\t** before being pulled back by the chronosphere into its normal location.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> MoebiusCountDown;\n\n\t\t/*\n\t\t** This is the coord the unit will be taken back to once its moebius\n\t\t** effect wears off.\n\t\t*/\n\t\tCELL MoebiusCell;\n\n\t\t/*\n\t\t**\tSome units must have their turret locked down to face their body direction.\n\t\t**\tWhen this flag is set, this condition is in effect. This flag is a more\n\t\t**\taccurate check than examining the TrackNumber since the turret may be\n\t\t**\trotating into position so that a pending track may start. During this process\n\t\t**\tthe track number does not indicate anything.\n\t\t*/\n\t\tunsigned IsTurretLockedDown:1;\n\n\t\t/*\n\t\t**\tThis vehicle could be processing a \"short track\". A short track is one that\n\t\t**\tdoesn't actually go anywhere. Kind of like turning in place.\n\t\t*/\n\t\tunsigned IsOnShortTrack:1;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tDriveClass(RTTIType rtti, int id, HousesType house);\n\t\tDriveClass(NoInitClass const & x) : FootClass(x), MoebiusCountDown(x) {};\n\t\tvirtual ~DriveClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool Teleport_To(CELL cell);\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\t\tvirtual bool Limbo(void);\n\t\tvoid Do_Turn(DirType dir);\n\t\tvirtual void Overrun_Square(CELL , bool =true) {};\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual bool Ok_To_Move(DirType ) const;\n\t\tvirtual void AI(void);\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid Force_Track(int track, COORDINATE coord);\n\t\tvirtual bool Stop_Driver(void);\n\n\t\tvoid Mark_Track(COORDINATE headto, MarkType type);\n\n\t\t/**********************************************************************\n\t\t**\tThese enumerations are used as working constants that exist only\n\t\t**\tin the DriveClass namespace.\n\t\t*/\n\t\tenum DriveClassEnum {\n\t\t\tBACKUP_INTO_REFINERY=64,\t\t// Track to backup into refinery.\n\t\t\tOUT_OF_REFINERY,\t\t\t\t\t// Track to leave refinery.\n\t\t\tOUT_OF_WEAPON_FACTORY\t\t\t// Track to leave weapons factory.\n\t\t};\n\n\t\t/****************************************************************************\n\t\t**\tSmooth turning tracks are controlled by this structure and these\n\t\t**\tprocessing bits.\n\t\t*/\n\t\ttypedef enum TrackControlType : unsigned char\t\t{\n\t\t\tF_=0x00,\t\t// No translation necessary?\n\t\t\tF_T=0x01,\t// Transpose X and Y components?\n\t\t\tF_X=0x02,\t// Reverse X component sign?\n\t\t\tF_Y=0x04,\t// Reverse Y component sign?\n\t\t\tF_D=0x08\t\t// Two cell consumption?\n\t\t} TrackControlType;\n\n\tprivate:\n\n\t\ttypedef struct {\n\t\t\tchar\t\t\t\t\tTrack;\t\t// Which track to use.\n\t\t\tchar\t\t\t\t\tStartTrack;\t// Track when starting from stand-still.\n\t\t\tDirType\t\t\t\tFacing;\t\t// Facing when track has been completed.\n\t\t\tDriveClass::TrackControlType\tFlag;\t\t\t// List processing flag bits.\n\t\t} TurnTrackType;\n\n\t\ttypedef struct {\n\t\t\tCOORDINATE\t\tOffset;\t\t// Offset to origin coordinate.\n\t\t\tDirType\tFacing;\t\t// Facing (primary track).\n\t\t} TrackType;\n\n\t\ttypedef struct {\n\t\t\tTrackType const * Track;\t// Pointer to track list.\n\t\t\tint\tJump;\t\t// Index where track jumping is allowed.\n\t\t\tint\tEntry;\t// Entry point if jumping to this track.\n\t\t\tint\tCell;\t\t// Per cell process should occur at this index.\n\t\t} RawTrackType;\n\n\t\t/*\n\t\t**\tThese speed values are used to accumulate movement and then\n\t\t**\tconvert them into pixel \"steps\" that are then translated through\n\t\t**\tthe currently running track so that the unit will move.\n\t\t*/\n\t\tint SpeedAccum;\n\n\t\t/*\n\t\t**\tThis the track control logic (used for ground vehicles only). The 'Track'\n\t\t**\tvariable holds the track being followed (0 == not following track). The\n\t\t**\t'TrackIndex' variable holds the current index into the specified track\n\t\t**\t(starts at 0).\n\t\t*/\n\t\tint TrackNumber;\n\t\tint TrackIndex;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvirtual void Fixup_Path(PathType *path);\n\t\tbool While_Moving(void);\n\t\tbool Start_Of_Move(void);\n\t\tvoid Lay_Track(void);\n\t\tCOORDINATE Smooth_Turn(COORDINATE adj, DirType & dir);\n\n\t\tstatic TurnTrackType const TrackControl[67];\n\t\tstatic RawTrackType const RawTracks[13];\n\t\tstatic TrackType const Track13[];\n\t\tstatic TrackType const Track12[];\n\t\tstatic TrackType const Track11[];\n\t\tstatic TrackType const Track10[];\n\t\tstatic TrackType const Track9[];\n\t\tstatic TrackType const Track8[];\n\t\tstatic TrackType const Track7[];\n\t\tstatic TrackType const Track6[];\n\t\tstatic TrackType const Track5[];\n\t\tstatic TrackType const Track4[];\n\t\tstatic TrackType const Track3[];\n\t\tstatic TrackType const Track2[];\n\t\tstatic TrackType const Track1[24];\n};\n\n//PG inline DriveClass::TrackControlType operator |(DriveClass::TrackControlType, DriveClass::TrackControlType);\n//PG inline DriveClass::TrackControlType operator &(DriveClass::TrackControlType, DriveClass::TrackControlType);\n//PG inline DriveClass::TrackControlType operator ~(DriveClass::TrackControlType);\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/DROP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DROP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DROP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/24/96                                                     *\n *                                                                                             *\n *                  Last Update : January 24, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"drop.h\"\n\n\nDropListClass::DropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down) :\n\tEditClass(id, text, max_len, flags, x, y, w, 9*RESFACTOR, ALPHANUMERIC),\n\tIsDropped(false),\n\tListHeight(h),\n\tDropButton(0, down, x+w, y),\n\tList(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down)\n{\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, flags);\n\tEditClass::Height = FontHeight+1;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\nvoid DropListClass::Zap(void)\n{\n\tCollapse();\n\tList.Zap();\n\tDropButton.Zap();\n\tEditClass::Zap();\n}\n\nDropListClass & DropListClass::Add(LinkClass & object)\n{\n\tDropButton.Add(object);\n\treturn((DropListClass &)EditClass::Add(object));\n}\n\nDropListClass & DropListClass::Add_Tail(LinkClass & object)\n{\n\tDropButton.Add_Tail(object);\n\treturn((DropListClass &)EditClass::Add_Tail(object));\n}\n\nDropListClass & DropListClass::Add_Head(LinkClass & object)\n{\n\tDropButton.Add_Head(object);\n\treturn((DropListClass &)EditClass::Add_Head(object));\n}\n\nDropListClass * DropListClass::Remove(void)\n{\n\tif (IsDropped) {\n\t\tCollapse();\n\t}\n\tDropButton.Remove();\n\treturn((DropListClass *)EditClass::Remove());\n}\n\nint DropListClass::Add_Item(char const * text)\n{\n\tstrncpy(String, text, MaxLength);\n\tFlag_To_Redraw();\n\treturn(List.Add_Item(text));\n}\n\nchar const * DropListClass::Current_Item(void)\n{\n\treturn(List.Current_Item());\n}\n\nint DropListClass::Current_Index(void)\n{\n\treturn(List.Current_Index());\n}\n\nvoid DropListClass::Set_Selected_Index(int index)\n{\n\tif (index < List.Count()) {\n\t\tList.Set_Selected_Index(index);\n\t\tstrcpy(String, List.Get_Item(Current_Index()));\n\t} else {\n\t\tString[0] = '\\0';\n\t}\n}\n\n\nvoid DropListClass::Clear_Focus(void)\n{\n\tCollapse();\n}\n\nvoid DropListClass::Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom)\n{\n\tif (&whom == &DropButton) {\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tif (IsDropped) {\n\t\t\t\tCollapse();\n\t\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t\t} else {\n\t\t\t\tExpand();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (&whom == &List) {\n\t\tstrncpy(String, List.Current_Item(), MaxLength);\n\t\tFlag_To_Redraw();\n\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t}\n}\n\nvoid DropListClass::Expand(void)\n{\n\tif (!IsDropped) {\n\t\tList.X = X;\n\t\tList.Y = Y+9*RESFACTOR;\n\t\tList.Width = Width;\n\t\tList.Height = ListHeight;\n\t\tList.Add(Head_Of_List());\n\t\tList.Flag_To_Redraw();\n\t\tIsDropped = true;\n\t}\n}\n\nvoid DropListClass::Collapse(void)\n{\n\tif (IsDropped) {\n\t\tList.Remove();\n\t\tIsDropped = false;\n\t}\n}\n\n\nDropListClass & DropListClass::operator = (DropListClass const & list)\n{\n\tif (this == &list) return(*this);\n\tEditClass::operator =(list);\n\tList = list.List;\n\tIsDropped = list.IsDropped;\n\tListHeight = list.ListHeight;\n\tDropButton = list.DropButton;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n\treturn(*this);\n}\n\n\nDropListClass::DropListClass(DropListClass const & list) :\n\tEditClass(list),\n\tIsDropped(list.IsDropped),\n\tListHeight(list.ListHeight),\n\tDropButton(list.DropButton),\n\tList(list.List)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\nvoid DropListClass::Set_Position(int x, int y)\n{\n\tEditClass::Set_Position(x, y);\n\tList.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data()));\n\tDropButton.Set_Position(x + Width, y);\n}\n\n\nvoid DropListClass::Set_Selected_Index(char const * text)\n{\n\tif (text) {\n\t\tfor (int index = 0; index < Count(); index++) {\n\t\t\tif (stricmp(text, List.Get_Item(index)) == 0) {\n\t\t\t\tSet_Selected_Index(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef WOLAPI_INTEGRATION\nvoid DropListClass::Flag_To_Redraw(void)\n{\n\tif( IsDropped )\n\t\tList.Flag_To_Redraw();\n\tEditClass::Flag_To_Redraw();\n}\n#endif\n"
  },
  {
    "path": "REDALERT/DROP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DROP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : DROP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef DROP_H\n#define DROP_H\n\n#include\t\"list.h\"\n#include\t\"edit.h\"\n\nclass DropListClass : public EditClass {\n\tpublic:\n\t\tDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down);\n\t\tvirtual ~DropListClass(void) {};\n\n\t\tvirtual DropListClass & Add(LinkClass & object);\n\t\tvirtual DropListClass & Add_Tail(LinkClass & object);\n\t\tvirtual DropListClass & Add_Head(LinkClass & object);\n\t\tvirtual DropListClass * Remove(void);\n\t\tvirtual void Zap(void);\n\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual char const * Current_Item(void);\n\t\tvirtual int Current_Index(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual int Count(void) const {return(List.Count());};\n\t\tvirtual char const * Get_Item(int index) const {return(List.Get_Item(index));};\n\n#ifdef WOLAPI_INTEGRATION\n\t\tvirtual void Flag_To_Redraw(void);\n#endif\n\n\t\tvoid Expand(void);\n\t\tvoid Collapse(void);\n\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\tDropListClass & operator = (DropListClass const & list);\n\t\tDropListClass(DropListClass const & list);\n\n\t\t/*\n\t\t**\tIndicates whether the list box has dropped down or not.\n\t\t*/\n\t\tunsigned IsDropped:1;\n\n\t\t/*\n\t\t**\tHeight of list box when it is expanded.\n\t\t*/\n\t\tint ListHeight;\n\n\t\t/*\n\t\t**\tDrop down button.\n\t\t*/\n\t\tShapeButtonClass DropButton;\n\n\t\t/*\n\t\t**\tList object when it is expanded.\n\t\t*/\n\t\tListClass List;\n};\n\n\n\n\ntemplate<class T>\nclass TDropListClass : public EditClass {\n\tpublic:\n\t\tTDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down);\n\t\tTDropListClass(TDropListClass<T> const & list);\n\t\tvirtual ~TDropListClass(void) {};\n\n\t\tT operator [] (int index) const {return(List[index]);};\n\t\tT & operator [] (int index) {return(List[index]);};\n\n\t\tvirtual TDropListClass<T> & Add(LinkClass & object);\n\t\tvirtual TDropListClass<T> & Add_Tail(LinkClass & object);\n\t\tvirtual TDropListClass<T> & Add_Head(LinkClass & object);\n\t\tvirtual TDropListClass<T> * Remove(void);\n\t\tvoid Zap(void);\n\n\t\tvirtual int Add_Item(T text);\n\t\tvirtual T Current_Item(void);\n\t\tvirtual int Current_Index(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(T item);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual int Count(void) const {return(List.Count());};\n\t\tvirtual T Get_Item(int index) const {return(List.Get_Item(index));};\n\n\n\t\tvoid Expand(void);\n\t\tvoid Collapse(void);\n\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\tTDropListClass<T> & operator = (TDropListClass<T> const & list);\n\n\t\t/*\n\t\t**\tIndicates whether the list box has dropped down or not.\n\t\t*/\n\t\tunsigned IsDropped:1;\n\n\t\t/*\n\t\t**\tHeight of list box when it is expanded.\n\t\t*/\n\t\tint ListHeight;\n\n\t\t/*\n\t\t**\tDrop down button.\n\t\t*/\n\t\tShapeButtonClass DropButton;\n\n\t\t/*\n\t\t**\tList object when it is expanded.\n\t\t*/\n\t\tTListClass<T> List;\n};\n\n\ntemplate<class T>\nTDropListClass<T>::TDropListClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, void const * up, void const * down) :\n\tEditClass(id, text, max_len, flags, x, y, w, 9, ALPHANUMERIC),\n\tIsDropped(false),\n\tListHeight(h),\n\tDropButton(0, down, x+w, y),\n\tList(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Zap(void)\n{\n\tCollapse();\n\tList.Zap();\n\tDropButton.Zap();\n\tEditClass::Zap();\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add(LinkClass & object)\n{\n\tDropButton.Add(object);\n\treturn((TDropListClass &)EditClass::Add(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add_Tail(LinkClass & object)\n{\n\tDropButton.Add_Tail(object);\n\treturn((TDropListClass &)EditClass::Add_Tail(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::Add_Head(LinkClass & object)\n{\n\tDropButton.Add_Head(object);\n\treturn((TDropListClass &)EditClass::Add_Head(object));\n}\n\n\ntemplate<class T>\nTDropListClass<T> * TDropListClass<T>::Remove(void)\n{\n\tif (IsDropped) {\n\t\tCollapse();\n\t}\n\tDropButton.Remove();\n\treturn((TDropListClass *)EditClass::Remove());\n}\n\n\ntemplate<class T>\nint TDropListClass<T>::Add_Item(T item)\n{\n\tstrncpy(String, item->Description(), MaxLength);\n\tFlag_To_Redraw();\n\treturn(List.Add_Item(item));\n}\n\n\ntemplate<class T>\nT TDropListClass<T>::Current_Item(void)\n{\n\treturn(List.Current_Item());\n}\n\n\ntemplate<class T>\nint TDropListClass<T>::Current_Index(void)\n{\n\treturn(List.Current_Index());\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Selected_Index(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Set_Selected_Index(index);\n\t\tstrncpy(String, List.Get_Item(Current_Index())->Description(), MaxLength);\n\t} else {\n\t\tString[0] = '\\0';\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Clear_Focus(void)\n{\n\tCollapse();\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom)\n{\n\tif (&whom == &DropButton) {\n\t\tif (flags & LEFTRELEASE) {\n\t\t\tif (IsDropped) {\n\t\t\t\tCollapse();\n\t\t\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t\t\t} else {\n\t\t\t\tExpand();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (&whom == &List) {\n\t\tstrncpy(String, List.Current_Item()->Description(), MaxLength);\n\t\tFlag_To_Redraw();\n\t\tkey = (KeyNumType)(ID | KN_BUTTON);\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Expand(void)\n{\n\tif (!IsDropped) {\n\t\tList.X = X;\n\t\tList.Y = Y+9;\n\t\tList.Width = Width;\n\t\tList.Height = ListHeight;\n\t\tList.Add(Head_Of_List());\n\t\tList.Flag_To_Redraw();\n\t\tIsDropped = true;\n\t}\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Collapse(void)\n{\n\tif (IsDropped) {\n\t\tList.Remove();\n\t\tIsDropped = false;\n\t}\n}\n\n\ntemplate<class T>\nTDropListClass<T> & TDropListClass<T>::operator = (TDropListClass<T> const & list)\n{\n\tif (this == &list) return(*this);\n\tEditClass::operator =(list);\n\tList = list.List;\n\tIsDropped = list.IsDropped;\n\tListHeight = list.ListHeight;\n\tDropButton = list.DropButton;\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n\treturn(*this);\n}\n\n\ntemplate<class T>\nTDropListClass<T>::TDropListClass(TDropListClass<T> const & list) :\n\tEditClass(list),\n\tIsDropped(list.IsDropped),\n\tListHeight(list.ListHeight),\n\tDropButton(list.DropButton),\n\tList(list.List)\n{\n\tList.Make_Peer(*this);\n\tDropButton.Make_Peer(*this);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Position(int x, int y)\n{\n\tEditClass::Set_Position(x, y);\n\tList.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data()));\n\tDropButton.Set_Position(x + Width, y);\n}\n\n\ntemplate<class T>\nvoid TDropListClass<T>::Set_Selected_Index(T text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif (text == List.Get_Item(index)) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/DTABLE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\nlong DiffTable[] = {\n\t0,\t// Index = 0, Token = 0\n\t1,\t// Index = 0, Token = 1\n\t3,\t// Index = 0, Token = 2\n\t4,\t// Index = 0, Token = 3\n\t7,\t// Index = 0, Token = 4\n\t8,\t// Index = 0, Token = 5\n\t10,\t// Index = 0, Token = 6\n\t11,\t// Index = 0, Token = 7\n\t0,\t// Index = 0, Token = 8\n\t-1,\t// Index = 0, Token = 9\n\t-3,\t// Index = 0, Token = 10\n\t-4,\t// Index = 0, Token = 11\n\t-7,\t// Index = 0, Token = 12\n\t-8,\t// Index = 0, Token = 13\n\t-10,\t// Index = 0, Token = 14\n\t-11,\t// Index = 0, Token = 15\n\t1,\t// Index = 1, Token = 0\n\t3,\t// Index = 1, Token = 1\n\t5,\t// Index = 1, Token = 2\n\t7,\t// Index = 1, Token = 3\n\t9,\t// Index = 1, Token = 4\n\t11,\t// Index = 1, Token = 5\n\t13,\t// Index = 1, Token = 6\n\t15,\t// Index = 1, Token = 7\n\t-1,\t// Index = 1, Token = 8\n\t-3,\t// Index = 1, Token = 9\n\t-5,\t// Index = 1, Token = 10\n\t-7,\t// Index = 1, Token = 11\n\t-9,\t// Index = 1, Token = 12\n\t-11,\t// Index = 1, Token = 13\n\t-13,\t// Index = 1, Token = 14\n\t-15,\t// Index = 1, Token = 15\n\t1,\t// Index = 2, Token = 0\n\t3,\t// Index = 2, Token = 1\n\t5,\t// Index = 2, Token = 2\n\t7,\t// Index = 2, Token = 3\n\t10,\t// Index = 2, Token = 4\n\t12,\t// Index = 2, Token = 5\n\t14,\t// Index = 2, Token = 6\n\t16,\t// Index = 2, Token = 7\n\t-1,\t// Index = 2, Token = 8\n\t-3,\t// Index = 2, Token = 9\n\t-5,\t// Index = 2, Token = 10\n\t-7,\t// Index = 2, Token = 11\n\t-10,\t// Index = 2, Token = 12\n\t-12,\t// Index = 2, Token = 13\n\t-14,\t// Index = 2, Token = 14\n\t-16,\t// Index = 2, Token = 15\n\t1,\t// Index = 3, Token = 0\n\t3,\t// Index = 3, Token = 1\n\t6,\t// Index = 3, Token = 2\n\t8,\t// Index = 3, Token = 3\n\t11,\t// Index = 3, Token = 4\n\t13,\t// Index = 3, Token = 5\n\t16,\t// Index = 3, Token = 6\n\t18,\t// Index = 3, Token = 7\n\t-1,\t// Index = 3, Token = 8\n\t-3,\t// Index = 3, Token = 9\n\t-6,\t// Index = 3, Token = 10\n\t-8,\t// Index = 3, Token = 11\n\t-11,\t// Index = 3, Token = 12\n\t-13,\t// Index = 3, Token = 13\n\t-16,\t// Index = 3, Token = 14\n\t-18,\t// Index = 3, Token = 15\n\t1,\t// Index = 4, Token = 0\n\t3,\t// Index = 4, Token = 1\n\t6,\t// Index = 4, Token = 2\n\t8,\t// Index = 4, Token = 3\n\t12,\t// Index = 4, Token = 4\n\t14,\t// Index = 4, Token = 5\n\t17,\t// Index = 4, Token = 6\n\t19,\t// Index = 4, Token = 7\n\t-1,\t// Index = 4, Token = 8\n\t-3,\t// Index = 4, Token = 9\n\t-6,\t// Index = 4, Token = 10\n\t-8,\t// Index = 4, Token = 11\n\t-12,\t// Index = 4, Token = 12\n\t-14,\t// Index = 4, Token = 13\n\t-17,\t// Index = 4, Token = 14\n\t-19,\t// Index = 4, Token = 15\n\t1,\t// Index = 5, Token = 0\n\t4,\t// Index = 5, Token = 1\n\t7,\t// Index = 5, Token = 2\n\t10,\t// Index = 5, Token = 3\n\t13,\t// Index = 5, Token = 4\n\t16,\t// Index = 5, Token = 5\n\t19,\t// Index = 5, Token = 6\n\t22,\t// Index = 5, Token = 7\n\t-1,\t// Index = 5, Token = 8\n\t-4,\t// Index = 5, Token = 9\n\t-7,\t// Index = 5, Token = 10\n\t-10,\t// Index = 5, Token = 11\n\t-13,\t// Index = 5, Token = 12\n\t-16,\t// Index = 5, Token = 13\n\t-19,\t// Index = 5, Token = 14\n\t-22,\t// Index = 5, Token = 15\n\t1,\t// Index = 6, Token = 0\n\t4,\t// Index = 6, Token = 1\n\t7,\t// Index = 6, Token = 2\n\t10,\t// Index = 6, Token = 3\n\t14,\t// Index = 6, Token = 4\n\t17,\t// Index = 6, Token = 5\n\t20,\t// Index = 6, Token = 6\n\t23,\t// Index = 6, Token = 7\n\t-1,\t// Index = 6, Token = 8\n\t-4,\t// Index = 6, Token = 9\n\t-7,\t// Index = 6, Token = 10\n\t-10,\t// Index = 6, Token = 11\n\t-14,\t// Index = 6, Token = 12\n\t-17,\t// Index = 6, Token = 13\n\t-20,\t// Index = 6, Token = 14\n\t-23,\t// Index = 6, Token = 15\n\t1,\t// Index = 7, Token = 0\n\t4,\t// Index = 7, Token = 1\n\t8,\t// Index = 7, Token = 2\n\t11,\t// Index = 7, Token = 3\n\t15,\t// Index = 7, Token = 4\n\t18,\t// Index = 7, Token = 5\n\t22,\t// Index = 7, Token = 6\n\t25,\t// Index = 7, Token = 7\n\t-1,\t// Index = 7, Token = 8\n\t-4,\t// Index = 7, Token = 9\n\t-8,\t// Index = 7, Token = 10\n\t-11,\t// Index = 7, Token = 11\n\t-15,\t// Index = 7, Token = 12\n\t-18,\t// Index = 7, Token = 13\n\t-22,\t// Index = 7, Token = 14\n\t-25,\t// Index = 7, Token = 15\n\t2,\t// Index = 8, Token = 0\n\t6,\t// Index = 8, Token = 1\n\t10,\t// Index = 8, Token = 2\n\t14,\t// Index = 8, Token = 3\n\t18,\t// Index = 8, Token = 4\n\t22,\t// Index = 8, Token = 5\n\t26,\t// Index = 8, Token = 6\n\t30,\t// Index = 8, Token = 7\n\t-2,\t// Index = 8, Token = 8\n\t-6,\t// Index = 8, Token = 9\n\t-10,\t// Index = 8, Token = 10\n\t-14,\t// Index = 8, Token = 11\n\t-18,\t// Index = 8, Token = 12\n\t-22,\t// Index = 8, Token = 13\n\t-26,\t// Index = 8, Token = 14\n\t-30,\t// Index = 8, Token = 15\n\t2,\t// Index = 9, Token = 0\n\t6,\t// Index = 9, Token = 1\n\t10,\t// Index = 9, Token = 2\n\t14,\t// Index = 9, Token = 3\n\t19,\t// Index = 9, Token = 4\n\t23,\t// Index = 9, Token = 5\n\t27,\t// Index = 9, Token = 6\n\t31,\t// Index = 9, Token = 7\n\t-2,\t// Index = 9, Token = 8\n\t-6,\t// Index = 9, Token = 9\n\t-10,\t// Index = 9, Token = 10\n\t-14,\t// Index = 9, Token = 11\n\t-19,\t// Index = 9, Token = 12\n\t-23,\t// Index = 9, Token = 13\n\t-27,\t// Index = 9, Token = 14\n\t-31,\t// Index = 9, Token = 15\n\t2,\t// Index = 10, Token = 0\n\t6,\t// Index = 10, Token = 1\n\t11,\t// Index = 10, Token = 2\n\t15,\t// Index = 10, Token = 3\n\t21,\t// Index = 10, Token = 4\n\t25,\t// Index = 10, Token = 5\n\t30,\t// Index = 10, Token = 6\n\t34,\t// Index = 10, Token = 7\n\t-2,\t// Index = 10, Token = 8\n\t-6,\t// Index = 10, Token = 9\n\t-11,\t// Index = 10, Token = 10\n\t-15,\t// Index = 10, Token = 11\n\t-21,\t// Index = 10, Token = 12\n\t-25,\t// Index = 10, Token = 13\n\t-30,\t// Index = 10, Token = 14\n\t-34,\t// Index = 10, Token = 15\n\t2,\t// Index = 11, Token = 0\n\t7,\t// Index = 11, Token = 1\n\t12,\t// Index = 11, Token = 2\n\t17,\t// Index = 11, Token = 3\n\t23,\t// Index = 11, Token = 4\n\t28,\t// Index = 11, Token = 5\n\t33,\t// Index = 11, Token = 6\n\t38,\t// Index = 11, Token = 7\n\t-2,\t// Index = 11, Token = 8\n\t-7,\t// Index = 11, Token = 9\n\t-12,\t// Index = 11, Token = 10\n\t-17,\t// Index = 11, Token = 11\n\t-23,\t// Index = 11, Token = 12\n\t-28,\t// Index = 11, Token = 13\n\t-33,\t// Index = 11, Token = 14\n\t-38,\t// Index = 11, Token = 15\n\t2,\t// Index = 12, Token = 0\n\t7,\t// Index = 12, Token = 1\n\t13,\t// Index = 12, Token = 2\n\t18,\t// Index = 12, Token = 3\n\t25,\t// Index = 12, Token = 4\n\t30,\t// Index = 12, Token = 5\n\t36,\t// Index = 12, Token = 6\n\t41,\t// Index = 12, Token = 7\n\t-2,\t// Index = 12, Token = 8\n\t-7,\t// Index = 12, Token = 9\n\t-13,\t// Index = 12, Token = 10\n\t-18,\t// Index = 12, Token = 11\n\t-25,\t// Index = 12, Token = 12\n\t-30,\t// Index = 12, Token = 13\n\t-36,\t// Index = 12, Token = 14\n\t-41,\t// Index = 12, Token = 15\n\t3,\t// Index = 13, Token = 0\n\t9,\t// Index = 13, Token = 1\n\t15,\t// Index = 13, Token = 2\n\t21,\t// Index = 13, Token = 3\n\t28,\t// Index = 13, Token = 4\n\t34,\t// Index = 13, Token = 5\n\t40,\t// Index = 13, Token = 6\n\t46,\t// Index = 13, Token = 7\n\t-3,\t// Index = 13, Token = 8\n\t-9,\t// Index = 13, Token = 9\n\t-15,\t// Index = 13, Token = 10\n\t-21,\t// Index = 13, Token = 11\n\t-28,\t// Index = 13, Token = 12\n\t-34,\t// Index = 13, Token = 13\n\t-40,\t// Index = 13, Token = 14\n\t-46,\t// Index = 13, Token = 15\n\t3,\t// Index = 14, Token = 0\n\t10,\t// Index = 14, Token = 1\n\t17,\t// Index = 14, Token = 2\n\t24,\t// Index = 14, Token = 3\n\t31,\t// Index = 14, Token = 4\n\t38,\t// Index = 14, Token = 5\n\t45,\t// Index = 14, Token = 6\n\t52,\t// Index = 14, Token = 7\n\t-3,\t// Index = 14, Token = 8\n\t-10,\t// Index = 14, Token = 9\n\t-17,\t// Index = 14, Token = 10\n\t-24,\t// Index = 14, Token = 11\n\t-31,\t// Index = 14, Token = 12\n\t-38,\t// Index = 14, Token = 13\n\t-45,\t// Index = 14, Token = 14\n\t-52,\t// Index = 14, Token = 15\n\t3,\t// Index = 15, Token = 0\n\t10,\t// Index = 15, Token = 1\n\t18,\t// Index = 15, Token = 2\n\t25,\t// Index = 15, Token = 3\n\t34,\t// Index = 15, Token = 4\n\t41,\t// Index = 15, Token = 5\n\t49,\t// Index = 15, Token = 6\n\t56,\t// Index = 15, Token = 7\n\t-3,\t// Index = 15, Token = 8\n\t-10,\t// Index = 15, Token = 9\n\t-18,\t// Index = 15, Token = 10\n\t-25,\t// Index = 15, Token = 11\n\t-34,\t// Index = 15, Token = 12\n\t-41,\t// Index = 15, Token = 13\n\t-49,\t// Index = 15, Token = 14\n\t-56,\t// Index = 15, Token = 15\n\t4,\t// Index = 16, Token = 0\n\t12,\t// Index = 16, Token = 1\n\t21,\t// Index = 16, Token = 2\n\t29,\t// Index = 16, Token = 3\n\t38,\t// Index = 16, Token = 4\n\t46,\t// Index = 16, Token = 5\n\t55,\t// Index = 16, Token = 6\n\t63,\t// Index = 16, Token = 7\n\t-4,\t// Index = 16, Token = 8\n\t-12,\t// Index = 16, Token = 9\n\t-21,\t// Index = 16, Token = 10\n\t-29,\t// Index = 16, Token = 11\n\t-38,\t// Index = 16, Token = 12\n\t-46,\t// Index = 16, Token = 13\n\t-55,\t// Index = 16, Token = 14\n\t-63,\t// Index = 16, Token = 15\n\t4,\t// Index = 17, Token = 0\n\t13,\t// Index = 17, Token = 1\n\t22,\t// Index = 17, Token = 2\n\t31,\t// Index = 17, Token = 3\n\t41,\t// Index = 17, Token = 4\n\t50,\t// Index = 17, Token = 5\n\t59,\t// Index = 17, Token = 6\n\t68,\t// Index = 17, Token = 7\n\t-4,\t// Index = 17, Token = 8\n\t-13,\t// Index = 17, Token = 9\n\t-22,\t// Index = 17, Token = 10\n\t-31,\t// Index = 17, Token = 11\n\t-41,\t// Index = 17, Token = 12\n\t-50,\t// Index = 17, Token = 13\n\t-59,\t// Index = 17, Token = 14\n\t-68,\t// Index = 17, Token = 15\n\t5,\t// Index = 18, Token = 0\n\t15,\t// Index = 18, Token = 1\n\t25,\t// Index = 18, Token = 2\n\t35,\t// Index = 18, Token = 3\n\t46,\t// Index = 18, Token = 4\n\t56,\t// Index = 18, Token = 5\n\t66,\t// Index = 18, Token = 6\n\t76,\t// Index = 18, Token = 7\n\t-5,\t// Index = 18, Token = 8\n\t-15,\t// Index = 18, Token = 9\n\t-25,\t// Index = 18, Token = 10\n\t-35,\t// Index = 18, Token = 11\n\t-46,\t// Index = 18, Token = 12\n\t-56,\t// Index = 18, Token = 13\n\t-66,\t// Index = 18, Token = 14\n\t-76,\t// Index = 18, Token = 15\n\t5,\t// Index = 19, Token = 0\n\t16,\t// Index = 19, Token = 1\n\t27,\t// Index = 19, Token = 2\n\t38,\t// Index = 19, Token = 3\n\t50,\t// Index = 19, Token = 4\n\t61,\t// Index = 19, Token = 5\n\t72,\t// Index = 19, Token = 6\n\t83,\t// Index = 19, Token = 7\n\t-5,\t// Index = 19, Token = 8\n\t-16,\t// Index = 19, Token = 9\n\t-27,\t// Index = 19, Token = 10\n\t-38,\t// Index = 19, Token = 11\n\t-50,\t// Index = 19, Token = 12\n\t-61,\t// Index = 19, Token = 13\n\t-72,\t// Index = 19, Token = 14\n\t-83,\t// Index = 19, Token = 15\n\t6,\t// Index = 20, Token = 0\n\t18,\t// Index = 20, Token = 1\n\t31,\t// Index = 20, Token = 2\n\t43,\t// Index = 20, Token = 3\n\t56,\t// Index = 20, Token = 4\n\t68,\t// Index = 20, Token = 5\n\t81,\t// Index = 20, Token = 6\n\t93,\t// Index = 20, Token = 7\n\t-6,\t// Index = 20, Token = 8\n\t-18,\t// Index = 20, Token = 9\n\t-31,\t// Index = 20, Token = 10\n\t-43,\t// Index = 20, Token = 11\n\t-56,\t// Index = 20, Token = 12\n\t-68,\t// Index = 20, Token = 13\n\t-81,\t// Index = 20, Token = 14\n\t-93,\t// Index = 20, Token = 15\n\t6,\t// Index = 21, Token = 0\n\t19,\t// Index = 21, Token = 1\n\t33,\t// Index = 21, Token = 2\n\t46,\t// Index = 21, Token = 3\n\t61,\t// Index = 21, Token = 4\n\t74,\t// Index = 21, Token = 5\n\t88,\t// Index = 21, Token = 6\n\t101,\t// Index = 21, Token = 7\n\t-6,\t// Index = 21, Token = 8\n\t-19,\t// Index = 21, Token = 9\n\t-33,\t// Index = 21, Token = 10\n\t-46,\t// Index = 21, Token = 11\n\t-61,\t// Index = 21, Token = 12\n\t-74,\t// Index = 21, Token = 13\n\t-88,\t// Index = 21, Token = 14\n\t-101,\t// Index = 21, Token = 15\n\t7,\t// Index = 22, Token = 0\n\t22,\t// Index = 22, Token = 1\n\t37,\t// Index = 22, Token = 2\n\t52,\t// Index = 22, Token = 3\n\t67,\t// Index = 22, Token = 4\n\t82,\t// Index = 22, Token = 5\n\t97,\t// Index = 22, Token = 6\n\t112,\t// Index = 22, Token = 7\n\t-7,\t// Index = 22, Token = 8\n\t-22,\t// Index = 22, Token = 9\n\t-37,\t// Index = 22, Token = 10\n\t-52,\t// Index = 22, Token = 11\n\t-67,\t// Index = 22, Token = 12\n\t-82,\t// Index = 22, Token = 13\n\t-97,\t// Index = 22, Token = 14\n\t-112,\t// Index = 22, Token = 15\n\t8,\t// Index = 23, Token = 0\n\t24,\t// Index = 23, Token = 1\n\t41,\t// Index = 23, Token = 2\n\t57,\t// Index = 23, Token = 3\n\t74,\t// Index = 23, Token = 4\n\t90,\t// Index = 23, Token = 5\n\t107,\t// Index = 23, Token = 6\n\t123,\t// Index = 23, Token = 7\n\t-8,\t// Index = 23, Token = 8\n\t-24,\t// Index = 23, Token = 9\n\t-41,\t// Index = 23, Token = 10\n\t-57,\t// Index = 23, Token = 11\n\t-74,\t// Index = 23, Token = 12\n\t-90,\t// Index = 23, Token = 13\n\t-107,\t// Index = 23, Token = 14\n\t-123,\t// Index = 23, Token = 15\n\t9,\t// Index = 24, Token = 0\n\t27,\t// Index = 24, Token = 1\n\t45,\t// Index = 24, Token = 2\n\t63,\t// Index = 24, Token = 3\n\t82,\t// Index = 24, Token = 4\n\t100,\t// Index = 24, Token = 5\n\t118,\t// Index = 24, Token = 6\n\t136,\t// Index = 24, Token = 7\n\t-9,\t// Index = 24, Token = 8\n\t-27,\t// Index = 24, Token = 9\n\t-45,\t// Index = 24, Token = 10\n\t-63,\t// Index = 24, Token = 11\n\t-82,\t// Index = 24, Token = 12\n\t-100,\t// Index = 24, Token = 13\n\t-118,\t// Index = 24, Token = 14\n\t-136,\t// Index = 24, Token = 15\n\t10,\t// Index = 25, Token = 0\n\t30,\t// Index = 25, Token = 1\n\t50,\t// Index = 25, Token = 2\n\t70,\t// Index = 25, Token = 3\n\t90,\t// Index = 25, Token = 4\n\t110,\t// Index = 25, Token = 5\n\t130,\t// Index = 25, Token = 6\n\t150,\t// Index = 25, Token = 7\n\t-10,\t// Index = 25, Token = 8\n\t-30,\t// Index = 25, Token = 9\n\t-50,\t// Index = 25, Token = 10\n\t-70,\t// Index = 25, Token = 11\n\t-90,\t// Index = 25, Token = 12\n\t-110,\t// Index = 25, Token = 13\n\t-130,\t// Index = 25, Token = 14\n\t-150,\t// Index = 25, Token = 15\n\t11,\t// Index = 26, Token = 0\n\t33,\t// Index = 26, Token = 1\n\t55,\t// Index = 26, Token = 2\n\t77,\t// Index = 26, Token = 3\n\t99,\t// Index = 26, Token = 4\n\t121,\t// Index = 26, Token = 5\n\t143,\t// Index = 26, Token = 6\n\t165,\t// Index = 26, Token = 7\n\t-11,\t// Index = 26, Token = 8\n\t-33,\t// Index = 26, Token = 9\n\t-55,\t// Index = 26, Token = 10\n\t-77,\t// Index = 26, Token = 11\n\t-99,\t// Index = 26, Token = 12\n\t-121,\t// Index = 26, Token = 13\n\t-143,\t// Index = 26, Token = 14\n\t-165,\t// Index = 26, Token = 15\n\t12,\t// Index = 27, Token = 0\n\t36,\t// Index = 27, Token = 1\n\t60,\t// Index = 27, Token = 2\n\t84,\t// Index = 27, Token = 3\n\t109,\t// Index = 27, Token = 4\n\t133,\t// Index = 27, Token = 5\n\t157,\t// Index = 27, Token = 6\n\t181,\t// Index = 27, Token = 7\n\t-12,\t// Index = 27, Token = 8\n\t-36,\t// Index = 27, Token = 9\n\t-60,\t// Index = 27, Token = 10\n\t-84,\t// Index = 27, Token = 11\n\t-109,\t// Index = 27, Token = 12\n\t-133,\t// Index = 27, Token = 13\n\t-157,\t// Index = 27, Token = 14\n\t-181,\t// Index = 27, Token = 15\n\t13,\t// Index = 28, Token = 0\n\t39,\t// Index = 28, Token = 1\n\t66,\t// Index = 28, Token = 2\n\t92,\t// Index = 28, Token = 3\n\t120,\t// Index = 28, Token = 4\n\t146,\t// Index = 28, Token = 5\n\t173,\t// Index = 28, Token = 6\n\t199,\t// Index = 28, Token = 7\n\t-13,\t// Index = 28, Token = 8\n\t-39,\t// Index = 28, Token = 9\n\t-66,\t// Index = 28, Token = 10\n\t-92,\t// Index = 28, Token = 11\n\t-120,\t// Index = 28, Token = 12\n\t-146,\t// Index = 28, Token = 13\n\t-173,\t// Index = 28, Token = 14\n\t-199,\t// Index = 28, Token = 15\n\t14,\t// Index = 29, Token = 0\n\t43,\t// Index = 29, Token = 1\n\t73,\t// Index = 29, Token = 2\n\t102,\t// Index = 29, Token = 3\n\t132,\t// Index = 29, Token = 4\n\t161,\t// Index = 29, Token = 5\n\t191,\t// Index = 29, Token = 6\n\t220,\t// Index = 29, Token = 7\n\t-14,\t// Index = 29, Token = 8\n\t-43,\t// Index = 29, Token = 9\n\t-73,\t// Index = 29, Token = 10\n\t-102,\t// Index = 29, Token = 11\n\t-132,\t// Index = 29, Token = 12\n\t-161,\t// Index = 29, Token = 13\n\t-191,\t// Index = 29, Token = 14\n\t-220,\t// Index = 29, Token = 15\n\t16,\t// Index = 30, Token = 0\n\t48,\t// Index = 30, Token = 1\n\t81,\t// Index = 30, Token = 2\n\t113,\t// Index = 30, Token = 3\n\t146,\t// Index = 30, Token = 4\n\t178,\t// Index = 30, Token = 5\n\t211,\t// Index = 30, Token = 6\n\t243,\t// Index = 30, Token = 7\n\t-16,\t// Index = 30, Token = 8\n\t-48,\t// Index = 30, Token = 9\n\t-81,\t// Index = 30, Token = 10\n\t-113,\t// Index = 30, Token = 11\n\t-146,\t// Index = 30, Token = 12\n\t-178,\t// Index = 30, Token = 13\n\t-211,\t// Index = 30, Token = 14\n\t-243,\t// Index = 30, Token = 15\n\t17,\t// Index = 31, Token = 0\n\t52,\t// Index = 31, Token = 1\n\t88,\t// Index = 31, Token = 2\n\t123,\t// Index = 31, Token = 3\n\t160,\t// Index = 31, Token = 4\n\t195,\t// Index = 31, Token = 5\n\t231,\t// Index = 31, Token = 6\n\t266,\t// Index = 31, Token = 7\n\t-17,\t// Index = 31, Token = 8\n\t-52,\t// Index = 31, Token = 9\n\t-88,\t// Index = 31, Token = 10\n\t-123,\t// Index = 31, Token = 11\n\t-160,\t// Index = 31, Token = 12\n\t-195,\t// Index = 31, Token = 13\n\t-231,\t// Index = 31, Token = 14\n\t-266,\t// Index = 31, Token = 15\n\t19,\t// Index = 32, Token = 0\n\t58,\t// Index = 32, Token = 1\n\t97,\t// Index = 32, Token = 2\n\t136,\t// Index = 32, Token = 3\n\t176,\t// Index = 32, Token = 4\n\t215,\t// Index = 32, Token = 5\n\t254,\t// Index = 32, Token = 6\n\t293,\t// Index = 32, Token = 7\n\t-19,\t// Index = 32, Token = 8\n\t-58,\t// Index = 32, Token = 9\n\t-97,\t// Index = 32, Token = 10\n\t-136,\t// Index = 32, Token = 11\n\t-176,\t// Index = 32, Token = 12\n\t-215,\t// Index = 32, Token = 13\n\t-254,\t// Index = 32, Token = 14\n\t-293,\t// Index = 32, Token = 15\n\t21,\t// Index = 33, Token = 0\n\t64,\t// Index = 33, Token = 1\n\t107,\t// Index = 33, Token = 2\n\t150,\t// Index = 33, Token = 3\n\t194,\t// Index = 33, Token = 4\n\t237,\t// Index = 33, Token = 5\n\t280,\t// Index = 33, Token = 6\n\t323,\t// Index = 33, Token = 7\n\t-21,\t// Index = 33, Token = 8\n\t-64,\t// Index = 33, Token = 9\n\t-107,\t// Index = 33, Token = 10\n\t-150,\t// Index = 33, Token = 11\n\t-194,\t// Index = 33, Token = 12\n\t-237,\t// Index = 33, Token = 13\n\t-280,\t// Index = 33, Token = 14\n\t-323,\t// Index = 33, Token = 15\n\t23,\t// Index = 34, Token = 0\n\t70,\t// Index = 34, Token = 1\n\t118,\t// Index = 34, Token = 2\n\t165,\t// Index = 34, Token = 3\n\t213,\t// Index = 34, Token = 4\n\t260,\t// Index = 34, Token = 5\n\t308,\t// Index = 34, Token = 6\n\t355,\t// Index = 34, Token = 7\n\t-23,\t// Index = 34, Token = 8\n\t-70,\t// Index = 34, Token = 9\n\t-118,\t// Index = 34, Token = 10\n\t-165,\t// Index = 34, Token = 11\n\t-213,\t// Index = 34, Token = 12\n\t-260,\t// Index = 34, Token = 13\n\t-308,\t// Index = 34, Token = 14\n\t-355,\t// Index = 34, Token = 15\n\t26,\t// Index = 35, Token = 0\n\t78,\t// Index = 35, Token = 1\n\t130,\t// Index = 35, Token = 2\n\t182,\t// Index = 35, Token = 3\n\t235,\t// Index = 35, Token = 4\n\t287,\t// Index = 35, Token = 5\n\t339,\t// Index = 35, Token = 6\n\t391,\t// Index = 35, Token = 7\n\t-26,\t// Index = 35, Token = 8\n\t-78,\t// Index = 35, Token = 9\n\t-130,\t// Index = 35, Token = 10\n\t-182,\t// Index = 35, Token = 11\n\t-235,\t// Index = 35, Token = 12\n\t-287,\t// Index = 35, Token = 13\n\t-339,\t// Index = 35, Token = 14\n\t-391,\t// Index = 35, Token = 15\n\t28,\t// Index = 36, Token = 0\n\t85,\t// Index = 36, Token = 1\n\t143,\t// Index = 36, Token = 2\n\t200,\t// Index = 36, Token = 3\n\t258,\t// Index = 36, Token = 4\n\t315,\t// Index = 36, Token = 5\n\t373,\t// Index = 36, Token = 6\n\t430,\t// Index = 36, Token = 7\n\t-28,\t// Index = 36, Token = 8\n\t-85,\t// Index = 36, Token = 9\n\t-143,\t// Index = 36, Token = 10\n\t-200,\t// Index = 36, Token = 11\n\t-258,\t// Index = 36, Token = 12\n\t-315,\t// Index = 36, Token = 13\n\t-373,\t// Index = 36, Token = 14\n\t-430,\t// Index = 36, Token = 15\n\t31,\t// Index = 37, Token = 0\n\t94,\t// Index = 37, Token = 1\n\t157,\t// Index = 37, Token = 2\n\t220,\t// Index = 37, Token = 3\n\t284,\t// Index = 37, Token = 4\n\t347,\t// Index = 37, Token = 5\n\t410,\t// Index = 37, Token = 6\n\t473,\t// Index = 37, Token = 7\n\t-31,\t// Index = 37, Token = 8\n\t-94,\t// Index = 37, Token = 9\n\t-157,\t// Index = 37, Token = 10\n\t-220,\t// Index = 37, Token = 11\n\t-284,\t// Index = 37, Token = 12\n\t-347,\t// Index = 37, Token = 13\n\t-410,\t// Index = 37, Token = 14\n\t-473,\t// Index = 37, Token = 15\n\t34,\t// Index = 38, Token = 0\n\t103,\t// Index = 38, Token = 1\n\t173,\t// Index = 38, Token = 2\n\t242,\t// Index = 38, Token = 3\n\t313,\t// Index = 38, Token = 4\n\t382,\t// Index = 38, Token = 5\n\t452,\t// Index = 38, Token = 6\n\t521,\t// Index = 38, Token = 7\n\t-34,\t// Index = 38, Token = 8\n\t-103,\t// Index = 38, Token = 9\n\t-173,\t// Index = 38, Token = 10\n\t-242,\t// Index = 38, Token = 11\n\t-313,\t// Index = 38, Token = 12\n\t-382,\t// Index = 38, Token = 13\n\t-452,\t// Index = 38, Token = 14\n\t-521,\t// Index = 38, Token = 15\n\t38,\t// Index = 39, Token = 0\n\t114,\t// Index = 39, Token = 1\n\t191,\t// Index = 39, Token = 2\n\t267,\t// Index = 39, Token = 3\n\t345,\t// Index = 39, Token = 4\n\t421,\t// Index = 39, Token = 5\n\t498,\t// Index = 39, Token = 6\n\t574,\t// Index = 39, Token = 7\n\t-38,\t// Index = 39, Token = 8\n\t-114,\t// Index = 39, Token = 9\n\t-191,\t// Index = 39, Token = 10\n\t-267,\t// Index = 39, Token = 11\n\t-345,\t// Index = 39, Token = 12\n\t-421,\t// Index = 39, Token = 13\n\t-498,\t// Index = 39, Token = 14\n\t-574,\t// Index = 39, Token = 15\n\t42,\t// Index = 40, Token = 0\n\t126,\t// Index = 40, Token = 1\n\t210,\t// Index = 40, Token = 2\n\t294,\t// Index = 40, Token = 3\n\t379,\t// Index = 40, Token = 4\n\t463,\t// Index = 40, Token = 5\n\t547,\t// Index = 40, Token = 6\n\t631,\t// Index = 40, Token = 7\n\t-42,\t// Index = 40, Token = 8\n\t-126,\t// Index = 40, Token = 9\n\t-210,\t// Index = 40, Token = 10\n\t-294,\t// Index = 40, Token = 11\n\t-379,\t// Index = 40, Token = 12\n\t-463,\t// Index = 40, Token = 13\n\t-547,\t// Index = 40, Token = 14\n\t-631,\t// Index = 40, Token = 15\n\t46,\t// Index = 41, Token = 0\n\t138,\t// Index = 41, Token = 1\n\t231,\t// Index = 41, Token = 2\n\t323,\t// Index = 41, Token = 3\n\t417,\t// Index = 41, Token = 4\n\t509,\t// Index = 41, Token = 5\n\t602,\t// Index = 41, Token = 6\n\t694,\t// Index = 41, Token = 7\n\t-46,\t// Index = 41, Token = 8\n\t-138,\t// Index = 41, Token = 9\n\t-231,\t// Index = 41, Token = 10\n\t-323,\t// Index = 41, Token = 11\n\t-417,\t// Index = 41, Token = 12\n\t-509,\t// Index = 41, Token = 13\n\t-602,\t// Index = 41, Token = 14\n\t-694,\t// Index = 41, Token = 15\n\t51,\t// Index = 42, Token = 0\n\t153,\t// Index = 42, Token = 1\n\t255,\t// Index = 42, Token = 2\n\t357,\t// Index = 42, Token = 3\n\t459,\t// Index = 42, Token = 4\n\t561,\t// Index = 42, Token = 5\n\t663,\t// Index = 42, Token = 6\n\t765,\t// Index = 42, Token = 7\n\t-51,\t// Index = 42, Token = 8\n\t-153,\t// Index = 42, Token = 9\n\t-255,\t// Index = 42, Token = 10\n\t-357,\t// Index = 42, Token = 11\n\t-459,\t// Index = 42, Token = 12\n\t-561,\t// Index = 42, Token = 13\n\t-663,\t// Index = 42, Token = 14\n\t-765,\t// Index = 42, Token = 15\n\t56,\t// Index = 43, Token = 0\n\t168,\t// Index = 43, Token = 1\n\t280,\t// Index = 43, Token = 2\n\t392,\t// Index = 43, Token = 3\n\t505,\t// Index = 43, Token = 4\n\t617,\t// Index = 43, Token = 5\n\t729,\t// Index = 43, Token = 6\n\t841,\t// Index = 43, Token = 7\n\t-56,\t// Index = 43, Token = 8\n\t-168,\t// Index = 43, Token = 9\n\t-280,\t// Index = 43, Token = 10\n\t-392,\t// Index = 43, Token = 11\n\t-505,\t// Index = 43, Token = 12\n\t-617,\t// Index = 43, Token = 13\n\t-729,\t// Index = 43, Token = 14\n\t-841,\t// Index = 43, Token = 15\n\t61,\t// Index = 44, Token = 0\n\t184,\t// Index = 44, Token = 1\n\t308,\t// Index = 44, Token = 2\n\t431,\t// Index = 44, Token = 3\n\t555,\t// Index = 44, Token = 4\n\t678,\t// Index = 44, Token = 5\n\t802,\t// Index = 44, Token = 6\n\t925,\t// Index = 44, Token = 7\n\t-61,\t// Index = 44, Token = 8\n\t-184,\t// Index = 44, Token = 9\n\t-308,\t// Index = 44, Token = 10\n\t-431,\t// Index = 44, Token = 11\n\t-555,\t// Index = 44, Token = 12\n\t-678,\t// Index = 44, Token = 13\n\t-802,\t// Index = 44, Token = 14\n\t-925,\t// Index = 44, Token = 15\n\t68,\t// Index = 45, Token = 0\n\t204,\t// Index = 45, Token = 1\n\t340,\t// Index = 45, Token = 2\n\t476,\t// Index = 45, Token = 3\n\t612,\t// Index = 45, Token = 4\n\t748,\t// Index = 45, Token = 5\n\t884,\t// Index = 45, Token = 6\n\t1020,\t// Index = 45, Token = 7\n\t-68,\t// Index = 45, Token = 8\n\t-204,\t// Index = 45, Token = 9\n\t-340,\t// Index = 45, Token = 10\n\t-476,\t// Index = 45, Token = 11\n\t-612,\t// Index = 45, Token = 12\n\t-748,\t// Index = 45, Token = 13\n\t-884,\t// Index = 45, Token = 14\n\t-1020,\t// Index = 45, Token = 15\n\t74,\t// Index = 46, Token = 0\n\t223,\t// Index = 46, Token = 1\n\t373,\t// Index = 46, Token = 2\n\t522,\t// Index = 46, Token = 3\n\t672,\t// Index = 46, Token = 4\n\t821,\t// Index = 46, Token = 5\n\t971,\t// Index = 46, Token = 6\n\t1120,\t// Index = 46, Token = 7\n\t-74,\t// Index = 46, Token = 8\n\t-223,\t// Index = 46, Token = 9\n\t-373,\t// Index = 46, Token = 10\n\t-522,\t// Index = 46, Token = 11\n\t-672,\t// Index = 46, Token = 12\n\t-821,\t// Index = 46, Token = 13\n\t-971,\t// Index = 46, Token = 14\n\t-1120,\t// Index = 46, Token = 15\n\t82,\t// Index = 47, Token = 0\n\t246,\t// Index = 47, Token = 1\n\t411,\t// Index = 47, Token = 2\n\t575,\t// Index = 47, Token = 3\n\t740,\t// Index = 47, Token = 4\n\t904,\t// Index = 47, Token = 5\n\t1069,\t// Index = 47, Token = 6\n\t1233,\t// Index = 47, Token = 7\n\t-82,\t// Index = 47, Token = 8\n\t-246,\t// Index = 47, Token = 9\n\t-411,\t// Index = 47, Token = 10\n\t-575,\t// Index = 47, Token = 11\n\t-740,\t// Index = 47, Token = 12\n\t-904,\t// Index = 47, Token = 13\n\t-1069,\t// Index = 47, Token = 14\n\t-1233,\t// Index = 47, Token = 15\n\t90,\t// Index = 48, Token = 0\n\t271,\t// Index = 48, Token = 1\n\t452,\t// Index = 48, Token = 2\n\t633,\t// Index = 48, Token = 3\n\t814,\t// Index = 48, Token = 4\n\t995,\t// Index = 48, Token = 5\n\t1176,\t// Index = 48, Token = 6\n\t1357,\t// Index = 48, Token = 7\n\t-90,\t// Index = 48, Token = 8\n\t-271,\t// Index = 48, Token = 9\n\t-452,\t// Index = 48, Token = 10\n\t-633,\t// Index = 48, Token = 11\n\t-814,\t// Index = 48, Token = 12\n\t-995,\t// Index = 48, Token = 13\n\t-1176,\t// Index = 48, Token = 14\n\t-1357,\t// Index = 48, Token = 15\n\t99,\t// Index = 49, Token = 0\n\t298,\t// Index = 49, Token = 1\n\t497,\t// Index = 49, Token = 2\n\t696,\t// Index = 49, Token = 3\n\t895,\t// Index = 49, Token = 4\n\t1094,\t// Index = 49, Token = 5\n\t1293,\t// Index = 49, Token = 6\n\t1492,\t// Index = 49, Token = 7\n\t-99,\t// Index = 49, Token = 8\n\t-298,\t// Index = 49, Token = 9\n\t-497,\t// Index = 49, Token = 10\n\t-696,\t// Index = 49, Token = 11\n\t-895,\t// Index = 49, Token = 12\n\t-1094,\t// Index = 49, Token = 13\n\t-1293,\t// Index = 49, Token = 14\n\t-1492,\t// Index = 49, Token = 15\n\t109,\t// Index = 50, Token = 0\n\t328,\t// Index = 50, Token = 1\n\t547,\t// Index = 50, Token = 2\n\t766,\t// Index = 50, Token = 3\n\t985,\t// Index = 50, Token = 4\n\t1204,\t// Index = 50, Token = 5\n\t1423,\t// Index = 50, Token = 6\n\t1642,\t// Index = 50, Token = 7\n\t-109,\t// Index = 50, Token = 8\n\t-328,\t// Index = 50, Token = 9\n\t-547,\t// Index = 50, Token = 10\n\t-766,\t// Index = 50, Token = 11\n\t-985,\t// Index = 50, Token = 12\n\t-1204,\t// Index = 50, Token = 13\n\t-1423,\t// Index = 50, Token = 14\n\t-1642,\t// Index = 50, Token = 15\n\t120,\t// Index = 51, Token = 0\n\t360,\t// Index = 51, Token = 1\n\t601,\t// Index = 51, Token = 2\n\t841,\t// Index = 51, Token = 3\n\t1083,\t// Index = 51, Token = 4\n\t1323,\t// Index = 51, Token = 5\n\t1564,\t// Index = 51, Token = 6\n\t1804,\t// Index = 51, Token = 7\n\t-120,\t// Index = 51, Token = 8\n\t-360,\t// Index = 51, Token = 9\n\t-601,\t// Index = 51, Token = 10\n\t-841,\t// Index = 51, Token = 11\n\t-1083,\t// Index = 51, Token = 12\n\t-1323,\t// Index = 51, Token = 13\n\t-1564,\t// Index = 51, Token = 14\n\t-1804,\t// Index = 51, Token = 15\n\t132,\t// Index = 52, Token = 0\n\t397,\t// Index = 52, Token = 1\n\t662,\t// Index = 52, Token = 2\n\t927,\t// Index = 52, Token = 3\n\t1192,\t// Index = 52, Token = 4\n\t1457,\t// Index = 52, Token = 5\n\t1722,\t// Index = 52, Token = 6\n\t1987,\t// Index = 52, Token = 7\n\t-132,\t// Index = 52, Token = 8\n\t-397,\t// Index = 52, Token = 9\n\t-662,\t// Index = 52, Token = 10\n\t-927,\t// Index = 52, Token = 11\n\t-1192,\t// Index = 52, Token = 12\n\t-1457,\t// Index = 52, Token = 13\n\t-1722,\t// Index = 52, Token = 14\n\t-1987,\t// Index = 52, Token = 15\n\t145,\t// Index = 53, Token = 0\n\t436,\t// Index = 53, Token = 1\n\t728,\t// Index = 53, Token = 2\n\t1019,\t// Index = 53, Token = 3\n\t1311,\t// Index = 53, Token = 4\n\t1602,\t// Index = 53, Token = 5\n\t1894,\t// Index = 53, Token = 6\n\t2185,\t// Index = 53, Token = 7\n\t-145,\t// Index = 53, Token = 8\n\t-436,\t// Index = 53, Token = 9\n\t-728,\t// Index = 53, Token = 10\n\t-1019,\t// Index = 53, Token = 11\n\t-1311,\t// Index = 53, Token = 12\n\t-1602,\t// Index = 53, Token = 13\n\t-1894,\t// Index = 53, Token = 14\n\t-2185,\t// Index = 53, Token = 15\n\t160,\t// Index = 54, Token = 0\n\t480,\t// Index = 54, Token = 1\n\t801,\t// Index = 54, Token = 2\n\t1121,\t// Index = 54, Token = 3\n\t1442,\t// Index = 54, Token = 4\n\t1762,\t// Index = 54, Token = 5\n\t2083,\t// Index = 54, Token = 6\n\t2403,\t// Index = 54, Token = 7\n\t-160,\t// Index = 54, Token = 8\n\t-480,\t// Index = 54, Token = 9\n\t-801,\t// Index = 54, Token = 10\n\t-1121,\t// Index = 54, Token = 11\n\t-1442,\t// Index = 54, Token = 12\n\t-1762,\t// Index = 54, Token = 13\n\t-2083,\t// Index = 54, Token = 14\n\t-2403,\t// Index = 54, Token = 15\n\t176,\t// Index = 55, Token = 0\n\t528,\t// Index = 55, Token = 1\n\t881,\t// Index = 55, Token = 2\n\t1233,\t// Index = 55, Token = 3\n\t1587,\t// Index = 55, Token = 4\n\t1939,\t// Index = 55, Token = 5\n\t2292,\t// Index = 55, Token = 6\n\t2644,\t// Index = 55, Token = 7\n\t-176,\t// Index = 55, Token = 8\n\t-528,\t// Index = 55, Token = 9\n\t-881,\t// Index = 55, Token = 10\n\t-1233,\t// Index = 55, Token = 11\n\t-1587,\t// Index = 55, Token = 12\n\t-1939,\t// Index = 55, Token = 13\n\t-2292,\t// Index = 55, Token = 14\n\t-2644,\t// Index = 55, Token = 15\n\t194,\t// Index = 56, Token = 0\n\t582,\t// Index = 56, Token = 1\n\t970,\t// Index = 56, Token = 2\n\t1358,\t// Index = 56, Token = 3\n\t1746,\t// Index = 56, Token = 4\n\t2134,\t// Index = 56, Token = 5\n\t2522,\t// Index = 56, Token = 6\n\t2910,\t// Index = 56, Token = 7\n\t-194,\t// Index = 56, Token = 8\n\t-582,\t// Index = 56, Token = 9\n\t-970,\t// Index = 56, Token = 10\n\t-1358,\t// Index = 56, Token = 11\n\t-1746,\t// Index = 56, Token = 12\n\t-2134,\t// Index = 56, Token = 13\n\t-2522,\t// Index = 56, Token = 14\n\t-2910,\t// Index = 56, Token = 15\n\t213,\t// Index = 57, Token = 0\n\t639,\t// Index = 57, Token = 1\n\t1066,\t// Index = 57, Token = 2\n\t1492,\t// Index = 57, Token = 3\n\t1920,\t// Index = 57, Token = 4\n\t2346,\t// Index = 57, Token = 5\n\t2773,\t// Index = 57, Token = 6\n\t3199,\t// Index = 57, Token = 7\n\t-213,\t// Index = 57, Token = 8\n\t-639,\t// Index = 57, Token = 9\n\t-1066,\t// Index = 57, Token = 10\n\t-1492,\t// Index = 57, Token = 11\n\t-1920,\t// Index = 57, Token = 12\n\t-2346,\t// Index = 57, Token = 13\n\t-2773,\t// Index = 57, Token = 14\n\t-3199,\t// Index = 57, Token = 15\n\t234,\t// Index = 58, Token = 0\n\t703,\t// Index = 58, Token = 1\n\t1173,\t// Index = 58, Token = 2\n\t1642,\t// Index = 58, Token = 3\n\t2112,\t// Index = 58, Token = 4\n\t2581,\t// Index = 58, Token = 5\n\t3051,\t// Index = 58, Token = 6\n\t3520,\t// Index = 58, Token = 7\n\t-234,\t// Index = 58, Token = 8\n\t-703,\t// Index = 58, Token = 9\n\t-1173,\t// Index = 58, Token = 10\n\t-1642,\t// Index = 58, Token = 11\n\t-2112,\t// Index = 58, Token = 12\n\t-2581,\t// Index = 58, Token = 13\n\t-3051,\t// Index = 58, Token = 14\n\t-3520,\t// Index = 58, Token = 15\n\t258,\t// Index = 59, Token = 0\n\t774,\t// Index = 59, Token = 1\n\t1291,\t// Index = 59, Token = 2\n\t1807,\t// Index = 59, Token = 3\n\t2324,\t// Index = 59, Token = 4\n\t2840,\t// Index = 59, Token = 5\n\t3357,\t// Index = 59, Token = 6\n\t3873,\t// Index = 59, Token = 7\n\t-258,\t// Index = 59, Token = 8\n\t-774,\t// Index = 59, Token = 9\n\t-1291,\t// Index = 59, Token = 10\n\t-1807,\t// Index = 59, Token = 11\n\t-2324,\t// Index = 59, Token = 12\n\t-2840,\t// Index = 59, Token = 13\n\t-3357,\t// Index = 59, Token = 14\n\t-3873,\t// Index = 59, Token = 15\n\t284,\t// Index = 60, Token = 0\n\t852,\t// Index = 60, Token = 1\n\t1420,\t// Index = 60, Token = 2\n\t1988,\t// Index = 60, Token = 3\n\t2556,\t// Index = 60, Token = 4\n\t3124,\t// Index = 60, Token = 5\n\t3692,\t// Index = 60, Token = 6\n\t4260,\t// Index = 60, Token = 7\n\t-284,\t// Index = 60, Token = 8\n\t-852,\t// Index = 60, Token = 9\n\t-1420,\t// Index = 60, Token = 10\n\t-1988,\t// Index = 60, Token = 11\n\t-2556,\t// Index = 60, Token = 12\n\t-3124,\t// Index = 60, Token = 13\n\t-3692,\t// Index = 60, Token = 14\n\t-4260,\t// Index = 60, Token = 15\n\t312,\t// Index = 61, Token = 0\n\t936,\t// Index = 61, Token = 1\n\t1561,\t// Index = 61, Token = 2\n\t2185,\t// Index = 61, Token = 3\n\t2811,\t// Index = 61, Token = 4\n\t3435,\t// Index = 61, Token = 5\n\t4060,\t// Index = 61, Token = 6\n\t4684,\t// Index = 61, Token = 7\n\t-312,\t// Index = 61, Token = 8\n\t-936,\t// Index = 61, Token = 9\n\t-1561,\t// Index = 61, Token = 10\n\t-2185,\t// Index = 61, Token = 11\n\t-2811,\t// Index = 61, Token = 12\n\t-3435,\t// Index = 61, Token = 13\n\t-4060,\t// Index = 61, Token = 14\n\t-4684,\t// Index = 61, Token = 15\n\t343,\t// Index = 62, Token = 0\n\t1030,\t// Index = 62, Token = 1\n\t1717,\t// Index = 62, Token = 2\n\t2404,\t// Index = 62, Token = 3\n\t3092,\t// Index = 62, Token = 4\n\t3779,\t// Index = 62, Token = 5\n\t4466,\t// Index = 62, Token = 6\n\t5153,\t// Index = 62, Token = 7\n\t-343,\t// Index = 62, Token = 8\n\t-1030,\t// Index = 62, Token = 9\n\t-1717,\t// Index = 62, Token = 10\n\t-2404,\t// Index = 62, Token = 11\n\t-3092,\t// Index = 62, Token = 12\n\t-3779,\t// Index = 62, Token = 13\n\t-4466,\t// Index = 62, Token = 14\n\t-5153,\t// Index = 62, Token = 15\n\t378,\t// Index = 63, Token = 0\n\t1134,\t// Index = 63, Token = 1\n\t1890,\t// Index = 63, Token = 2\n\t2646,\t// Index = 63, Token = 3\n\t3402,\t// Index = 63, Token = 4\n\t4158,\t// Index = 63, Token = 5\n\t4914,\t// Index = 63, Token = 6\n\t5670,\t// Index = 63, Token = 7\n\t-378,\t// Index = 63, Token = 8\n\t-1134,\t// Index = 63, Token = 9\n\t-1890,\t// Index = 63, Token = 10\n\t-2646,\t// Index = 63, Token = 11\n\t-3402,\t// Index = 63, Token = 12\n\t-4158,\t// Index = 63, Token = 13\n\t-4914,\t// Index = 63, Token = 14\n\t-5670,\t// Index = 63, Token = 15\n\t415,\t// Index = 64, Token = 0\n\t1246,\t// Index = 64, Token = 1\n\t2078,\t// Index = 64, Token = 2\n\t2909,\t// Index = 64, Token = 3\n\t3742,\t// Index = 64, Token = 4\n\t4573,\t// Index = 64, Token = 5\n\t5405,\t// Index = 64, Token = 6\n\t6236,\t// Index = 64, Token = 7\n\t-415,\t// Index = 64, Token = 8\n\t-1246,\t// Index = 64, Token = 9\n\t-2078,\t// Index = 64, Token = 10\n\t-2909,\t// Index = 64, Token = 11\n\t-3742,\t// Index = 64, Token = 12\n\t-4573,\t// Index = 64, Token = 13\n\t-5405,\t// Index = 64, Token = 14\n\t-6236,\t// Index = 64, Token = 15\n\t457,\t// Index = 65, Token = 0\n\t1372,\t// Index = 65, Token = 1\n\t2287,\t// Index = 65, Token = 2\n\t3202,\t// Index = 65, Token = 3\n\t4117,\t// Index = 65, Token = 4\n\t5032,\t// Index = 65, Token = 5\n\t5947,\t// Index = 65, Token = 6\n\t6862,\t// Index = 65, Token = 7\n\t-457,\t// Index = 65, Token = 8\n\t-1372,\t// Index = 65, Token = 9\n\t-2287,\t// Index = 65, Token = 10\n\t-3202,\t// Index = 65, Token = 11\n\t-4117,\t// Index = 65, Token = 12\n\t-5032,\t// Index = 65, Token = 13\n\t-5947,\t// Index = 65, Token = 14\n\t-6862,\t// Index = 65, Token = 15\n\t503,\t// Index = 66, Token = 0\n\t1509,\t// Index = 66, Token = 1\n\t2516,\t// Index = 66, Token = 2\n\t3522,\t// Index = 66, Token = 3\n\t4529,\t// Index = 66, Token = 4\n\t5535,\t// Index = 66, Token = 5\n\t6542,\t// Index = 66, Token = 6\n\t7548,\t// Index = 66, Token = 7\n\t-503,\t// Index = 66, Token = 8\n\t-1509,\t// Index = 66, Token = 9\n\t-2516,\t// Index = 66, Token = 10\n\t-3522,\t// Index = 66, Token = 11\n\t-4529,\t// Index = 66, Token = 12\n\t-5535,\t// Index = 66, Token = 13\n\t-6542,\t// Index = 66, Token = 14\n\t-7548,\t// Index = 66, Token = 15\n\t553,\t// Index = 67, Token = 0\n\t1660,\t// Index = 67, Token = 1\n\t2767,\t// Index = 67, Token = 2\n\t3874,\t// Index = 67, Token = 3\n\t4981,\t// Index = 67, Token = 4\n\t6088,\t// Index = 67, Token = 5\n\t7195,\t// Index = 67, Token = 6\n\t8302,\t// Index = 67, Token = 7\n\t-553,\t// Index = 67, Token = 8\n\t-1660,\t// Index = 67, Token = 9\n\t-2767,\t// Index = 67, Token = 10\n\t-3874,\t// Index = 67, Token = 11\n\t-4981,\t// Index = 67, Token = 12\n\t-6088,\t// Index = 67, Token = 13\n\t-7195,\t// Index = 67, Token = 14\n\t-8302,\t// Index = 67, Token = 15\n\t608,\t// Index = 68, Token = 0\n\t1825,\t// Index = 68, Token = 1\n\t3043,\t// Index = 68, Token = 2\n\t4260,\t// Index = 68, Token = 3\n\t5479,\t// Index = 68, Token = 4\n\t6696,\t// Index = 68, Token = 5\n\t7914,\t// Index = 68, Token = 6\n\t9131,\t// Index = 68, Token = 7\n\t-608,\t// Index = 68, Token = 8\n\t-1825,\t// Index = 68, Token = 9\n\t-3043,\t// Index = 68, Token = 10\n\t-4260,\t// Index = 68, Token = 11\n\t-5479,\t// Index = 68, Token = 12\n\t-6696,\t// Index = 68, Token = 13\n\t-7914,\t// Index = 68, Token = 14\n\t-9131,\t// Index = 68, Token = 15\n\t669,\t// Index = 69, Token = 0\n\t2008,\t// Index = 69, Token = 1\n\t3348,\t// Index = 69, Token = 2\n\t4687,\t// Index = 69, Token = 3\n\t6027,\t// Index = 69, Token = 4\n\t7366,\t// Index = 69, Token = 5\n\t8706,\t// Index = 69, Token = 6\n\t10045,\t// Index = 69, Token = 7\n\t-669,\t// Index = 69, Token = 8\n\t-2008,\t// Index = 69, Token = 9\n\t-3348,\t// Index = 69, Token = 10\n\t-4687,\t// Index = 69, Token = 11\n\t-6027,\t// Index = 69, Token = 12\n\t-7366,\t// Index = 69, Token = 13\n\t-8706,\t// Index = 69, Token = 14\n\t-10045,\t// Index = 69, Token = 15\n\t736,\t// Index = 70, Token = 0\n\t2209,\t// Index = 70, Token = 1\n\t3683,\t// Index = 70, Token = 2\n\t5156,\t// Index = 70, Token = 3\n\t6630,\t// Index = 70, Token = 4\n\t8103,\t// Index = 70, Token = 5\n\t9577,\t// Index = 70, Token = 6\n\t11050,\t// Index = 70, Token = 7\n\t-736,\t// Index = 70, Token = 8\n\t-2209,\t// Index = 70, Token = 9\n\t-3683,\t// Index = 70, Token = 10\n\t-5156,\t// Index = 70, Token = 11\n\t-6630,\t// Index = 70, Token = 12\n\t-8103,\t// Index = 70, Token = 13\n\t-9577,\t// Index = 70, Token = 14\n\t-11050,\t// Index = 70, Token = 15\n\t810,\t// Index = 71, Token = 0\n\t2431,\t// Index = 71, Token = 1\n\t4052,\t// Index = 71, Token = 2\n\t5673,\t// Index = 71, Token = 3\n\t7294,\t// Index = 71, Token = 4\n\t8915,\t// Index = 71, Token = 5\n\t10536,\t// Index = 71, Token = 6\n\t12157,\t// Index = 71, Token = 7\n\t-810,\t// Index = 71, Token = 8\n\t-2431,\t// Index = 71, Token = 9\n\t-4052,\t// Index = 71, Token = 10\n\t-5673,\t// Index = 71, Token = 11\n\t-7294,\t// Index = 71, Token = 12\n\t-8915,\t// Index = 71, Token = 13\n\t-10536,\t// Index = 71, Token = 14\n\t-12157,\t// Index = 71, Token = 15\n\t891,\t// Index = 72, Token = 0\n\t2674,\t// Index = 72, Token = 1\n\t4457,\t// Index = 72, Token = 2\n\t6240,\t// Index = 72, Token = 3\n\t8023,\t// Index = 72, Token = 4\n\t9806,\t// Index = 72, Token = 5\n\t11589,\t// Index = 72, Token = 6\n\t13372,\t// Index = 72, Token = 7\n\t-891,\t// Index = 72, Token = 8\n\t-2674,\t// Index = 72, Token = 9\n\t-4457,\t// Index = 72, Token = 10\n\t-6240,\t// Index = 72, Token = 11\n\t-8023,\t// Index = 72, Token = 12\n\t-9806,\t// Index = 72, Token = 13\n\t-11589,\t// Index = 72, Token = 14\n\t-13372,\t// Index = 72, Token = 15\n\t980,\t// Index = 73, Token = 0\n\t2941,\t// Index = 73, Token = 1\n\t4902,\t// Index = 73, Token = 2\n\t6863,\t// Index = 73, Token = 3\n\t8825,\t// Index = 73, Token = 4\n\t10786,\t// Index = 73, Token = 5\n\t12747,\t// Index = 73, Token = 6\n\t14708,\t// Index = 73, Token = 7\n\t-980,\t// Index = 73, Token = 8\n\t-2941,\t// Index = 73, Token = 9\n\t-4902,\t// Index = 73, Token = 10\n\t-6863,\t// Index = 73, Token = 11\n\t-8825,\t// Index = 73, Token = 12\n\t-10786,\t// Index = 73, Token = 13\n\t-12747,\t// Index = 73, Token = 14\n\t-14708,\t// Index = 73, Token = 15\n\t1078,\t// Index = 74, Token = 0\n\t3235,\t// Index = 74, Token = 1\n\t5393,\t// Index = 74, Token = 2\n\t7550,\t// Index = 74, Token = 3\n\t9708,\t// Index = 74, Token = 4\n\t11865,\t// Index = 74, Token = 5\n\t14023,\t// Index = 74, Token = 6\n\t16180,\t// Index = 74, Token = 7\n\t-1078,\t// Index = 74, Token = 8\n\t-3235,\t// Index = 74, Token = 9\n\t-5393,\t// Index = 74, Token = 10\n\t-7550,\t// Index = 74, Token = 11\n\t-9708,\t// Index = 74, Token = 12\n\t-11865,\t// Index = 74, Token = 13\n\t-14023,\t// Index = 74, Token = 14\n\t-16180,\t// Index = 74, Token = 15\n\t1186,\t// Index = 75, Token = 0\n\t3559,\t// Index = 75, Token = 1\n\t5932,\t// Index = 75, Token = 2\n\t8305,\t// Index = 75, Token = 3\n\t10679,\t// Index = 75, Token = 4\n\t13052,\t// Index = 75, Token = 5\n\t15425,\t// Index = 75, Token = 6\n\t17798,\t// Index = 75, Token = 7\n\t-1186,\t// Index = 75, Token = 8\n\t-3559,\t// Index = 75, Token = 9\n\t-5932,\t// Index = 75, Token = 10\n\t-8305,\t// Index = 75, Token = 11\n\t-10679,\t// Index = 75, Token = 12\n\t-13052,\t// Index = 75, Token = 13\n\t-15425,\t// Index = 75, Token = 14\n\t-17798,\t// Index = 75, Token = 15\n\t1305,\t// Index = 76, Token = 0\n\t3915,\t// Index = 76, Token = 1\n\t6526,\t// Index = 76, Token = 2\n\t9136,\t// Index = 76, Token = 3\n\t11747,\t// Index = 76, Token = 4\n\t14357,\t// Index = 76, Token = 5\n\t16968,\t// Index = 76, Token = 6\n\t19578,\t// Index = 76, Token = 7\n\t-1305,\t// Index = 76, Token = 8\n\t-3915,\t// Index = 76, Token = 9\n\t-6526,\t// Index = 76, Token = 10\n\t-9136,\t// Index = 76, Token = 11\n\t-11747,\t// Index = 76, Token = 12\n\t-14357,\t// Index = 76, Token = 13\n\t-16968,\t// Index = 76, Token = 14\n\t-19578,\t// Index = 76, Token = 15\n\t1435,\t// Index = 77, Token = 0\n\t4306,\t// Index = 77, Token = 1\n\t7178,\t// Index = 77, Token = 2\n\t10049,\t// Index = 77, Token = 3\n\t12922,\t// Index = 77, Token = 4\n\t15793,\t// Index = 77, Token = 5\n\t18665,\t// Index = 77, Token = 6\n\t21536,\t// Index = 77, Token = 7\n\t-1435,\t// Index = 77, Token = 8\n\t-4306,\t// Index = 77, Token = 9\n\t-7178,\t// Index = 77, Token = 10\n\t-10049,\t// Index = 77, Token = 11\n\t-12922,\t// Index = 77, Token = 12\n\t-15793,\t// Index = 77, Token = 13\n\t-18665,\t// Index = 77, Token = 14\n\t-21536,\t// Index = 77, Token = 15\n\t1579,\t// Index = 78, Token = 0\n\t4737,\t// Index = 78, Token = 1\n\t7896,\t// Index = 78, Token = 2\n\t11054,\t// Index = 78, Token = 3\n\t14214,\t// Index = 78, Token = 4\n\t17372,\t// Index = 78, Token = 5\n\t20531,\t// Index = 78, Token = 6\n\t23689,\t// Index = 78, Token = 7\n\t-1579,\t// Index = 78, Token = 8\n\t-4737,\t// Index = 78, Token = 9\n\t-7896,\t// Index = 78, Token = 10\n\t-11054,\t// Index = 78, Token = 11\n\t-14214,\t// Index = 78, Token = 12\n\t-17372,\t// Index = 78, Token = 13\n\t-20531,\t// Index = 78, Token = 14\n\t-23689,\t// Index = 78, Token = 15\n\t1737,\t// Index = 79, Token = 0\n\t5211,\t// Index = 79, Token = 1\n\t8686,\t// Index = 79, Token = 2\n\t12160,\t// Index = 79, Token = 3\n\t15636,\t// Index = 79, Token = 4\n\t19110,\t// Index = 79, Token = 5\n\t22585,\t// Index = 79, Token = 6\n\t26059,\t// Index = 79, Token = 7\n\t-1737,\t// Index = 79, Token = 8\n\t-5211,\t// Index = 79, Token = 9\n\t-8686,\t// Index = 79, Token = 10\n\t-12160,\t// Index = 79, Token = 11\n\t-15636,\t// Index = 79, Token = 12\n\t-19110,\t// Index = 79, Token = 13\n\t-22585,\t// Index = 79, Token = 14\n\t-26059,\t// Index = 79, Token = 15\n\t1911,\t// Index = 80, Token = 0\n\t5733,\t// Index = 80, Token = 1\n\t9555,\t// Index = 80, Token = 2\n\t13377,\t// Index = 80, Token = 3\n\t17200,\t// Index = 80, Token = 4\n\t21022,\t// Index = 80, Token = 5\n\t24844,\t// Index = 80, Token = 6\n\t28666,\t// Index = 80, Token = 7\n\t-1911,\t// Index = 80, Token = 8\n\t-5733,\t// Index = 80, Token = 9\n\t-9555,\t// Index = 80, Token = 10\n\t-13377,\t// Index = 80, Token = 11\n\t-17200,\t// Index = 80, Token = 12\n\t-21022,\t// Index = 80, Token = 13\n\t-24844,\t// Index = 80, Token = 14\n\t-28666,\t// Index = 80, Token = 15\n\t2102,\t// Index = 81, Token = 0\n\t6306,\t// Index = 81, Token = 1\n\t10511,\t// Index = 81, Token = 2\n\t14715,\t// Index = 81, Token = 3\n\t18920,\t// Index = 81, Token = 4\n\t23124,\t// Index = 81, Token = 5\n\t27329,\t// Index = 81, Token = 6\n\t31533,\t// Index = 81, Token = 7\n\t-2102,\t// Index = 81, Token = 8\n\t-6306,\t// Index = 81, Token = 9\n\t-10511,\t// Index = 81, Token = 10\n\t-14715,\t// Index = 81, Token = 11\n\t-18920,\t// Index = 81, Token = 12\n\t-23124,\t// Index = 81, Token = 13\n\t-27329,\t// Index = 81, Token = 14\n\t-31533,\t// Index = 81, Token = 15\n\t2312,\t// Index = 82, Token = 0\n\t6937,\t// Index = 82, Token = 1\n\t11562,\t// Index = 82, Token = 2\n\t16187,\t// Index = 82, Token = 3\n\t20812,\t// Index = 82, Token = 4\n\t25437,\t// Index = 82, Token = 5\n\t30062,\t// Index = 82, Token = 6\n\t34687,\t// Index = 82, Token = 7\n\t-2312,\t// Index = 82, Token = 8\n\t-6937,\t// Index = 82, Token = 9\n\t-11562,\t// Index = 82, Token = 10\n\t-16187,\t// Index = 82, Token = 11\n\t-20812,\t// Index = 82, Token = 12\n\t-25437,\t// Index = 82, Token = 13\n\t-30062,\t// Index = 82, Token = 14\n\t-34687,\t// Index = 82, Token = 15\n\t2543,\t// Index = 83, Token = 0\n\t7630,\t// Index = 83, Token = 1\n\t12718,\t// Index = 83, Token = 2\n\t17805,\t// Index = 83, Token = 3\n\t22893,\t// Index = 83, Token = 4\n\t27980,\t// Index = 83, Token = 5\n\t33068,\t// Index = 83, Token = 6\n\t38155,\t// Index = 83, Token = 7\n\t-2543,\t// Index = 83, Token = 8\n\t-7630,\t// Index = 83, Token = 9\n\t-12718,\t// Index = 83, Token = 10\n\t-17805,\t// Index = 83, Token = 11\n\t-22893,\t// Index = 83, Token = 12\n\t-27980,\t// Index = 83, Token = 13\n\t-33068,\t// Index = 83, Token = 14\n\t-38155,\t// Index = 83, Token = 15\n\t2798,\t// Index = 84, Token = 0\n\t8394,\t// Index = 84, Token = 1\n\t13990,\t// Index = 84, Token = 2\n\t19586,\t// Index = 84, Token = 3\n\t25183,\t// Index = 84, Token = 4\n\t30779,\t// Index = 84, Token = 5\n\t36375,\t// Index = 84, Token = 6\n\t41971,\t// Index = 84, Token = 7\n\t-2798,\t// Index = 84, Token = 8\n\t-8394,\t// Index = 84, Token = 9\n\t-13990,\t// Index = 84, Token = 10\n\t-19586,\t// Index = 84, Token = 11\n\t-25183,\t// Index = 84, Token = 12\n\t-30779,\t// Index = 84, Token = 13\n\t-36375,\t// Index = 84, Token = 14\n\t-41971,\t// Index = 84, Token = 15\n\t3077,\t// Index = 85, Token = 0\n\t9232,\t// Index = 85, Token = 1\n\t15388,\t// Index = 85, Token = 2\n\t21543,\t// Index = 85, Token = 3\n\t27700,\t// Index = 85, Token = 4\n\t33855,\t// Index = 85, Token = 5\n\t40011,\t// Index = 85, Token = 6\n\t46166,\t// Index = 85, Token = 7\n\t-3077,\t// Index = 85, Token = 8\n\t-9232,\t// Index = 85, Token = 9\n\t-15388,\t// Index = 85, Token = 10\n\t-21543,\t// Index = 85, Token = 11\n\t-27700,\t// Index = 85, Token = 12\n\t-33855,\t// Index = 85, Token = 13\n\t-40011,\t// Index = 85, Token = 14\n\t-46166,\t// Index = 85, Token = 15\n\t3385,\t// Index = 86, Token = 0\n\t10156,\t// Index = 86, Token = 1\n\t16928,\t// Index = 86, Token = 2\n\t23699,\t// Index = 86, Token = 3\n\t30471,\t// Index = 86, Token = 4\n\t37242,\t// Index = 86, Token = 5\n\t44014,\t// Index = 86, Token = 6\n\t50785,\t// Index = 86, Token = 7\n\t-3385,\t// Index = 86, Token = 8\n\t-10156,\t// Index = 86, Token = 9\n\t-16928,\t// Index = 86, Token = 10\n\t-23699,\t// Index = 86, Token = 11\n\t-30471,\t// Index = 86, Token = 12\n\t-37242,\t// Index = 86, Token = 13\n\t-44014,\t// Index = 86, Token = 14\n\t-50785,\t// Index = 86, Token = 15\n\t3724,\t// Index = 87, Token = 0\n\t11172,\t// Index = 87, Token = 1\n\t18621,\t// Index = 87, Token = 2\n\t26069,\t// Index = 87, Token = 3\n\t33518,\t// Index = 87, Token = 4\n\t40966,\t// Index = 87, Token = 5\n\t48415,\t// Index = 87, Token = 6\n\t55863,\t// Index = 87, Token = 7\n\t-3724,\t// Index = 87, Token = 8\n\t-11172,\t// Index = 87, Token = 9\n\t-18621,\t// Index = 87, Token = 10\n\t-26069,\t// Index = 87, Token = 11\n\t-33518,\t// Index = 87, Token = 12\n\t-40966,\t// Index = 87, Token = 13\n\t-48415,\t// Index = 87, Token = 14\n\t-55863,\t// Index = 87, Token = 15\n\t4095,\t// Index = 88, Token = 0\n\t12286,\t// Index = 88, Token = 1\n\t20478,\t// Index = 88, Token = 2\n\t28669,\t// Index = 88, Token = 3\n\t36862,\t// Index = 88, Token = 4\n\t45053,\t// Index = 88, Token = 5\n\t53245,\t// Index = 88, Token = 6\n\t61436,\t// Index = 88, Token = 7\n\t-4095,\t// Index = 88, Token = 8\n\t-12286,\t// Index = 88, Token = 9\n\t-20478,\t// Index = 88, Token = 10\n\t-28669,\t// Index = 88, Token = 11\n\t-36862,\t// Index = 88, Token = 12\n\t-45053,\t// Index = 88, Token = 13\n\t-53245,\t// Index = 88, Token = 14\n\t-61436\t// Index = 88, Token = 15\n};\n\n"
  },
  {
    "path": "REDALERT/DYNAVEC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/DYNAVEC.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Red Alert                                *\n *                                                                         *\n *                    File Name : DYNAVEC.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R Randolph                          *\n *                                                                         *\n *                   Start Date : 09/18/96                                 *\n *                                                                         *\n *                  Last Update : September 18, 1996 [BRR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   DynamicVectorClass<T>::Add -- Add an element to the vector.           *\n *   DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.  *\n *   DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.  *\n *   DynamicVectorClass<T>::Delete -- Deletes specified index from vector. *\n *   DynamicVectorClass<T>::Delete -- Remove specified object from vector. *\n *   DynamicVectorClass<T>::DynamicVectorClass -- Constructor              *\n *   DynamicVectorClass<T>::ID -- Find matching value in dynamic vector.   *\n *   DynamicVectorClass<T>::Resize -- Changes size of a dynamic vector.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0)\n#include\t\"function.h\"\n#include \"vector.h\"\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#include\t\"WSPUDP.h\"\n#endif\t//WINSOCK_IPX\n//#include\t<mem.h>\n#include\t<stdio.h>\n\n\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::DynamicVectorClass -- Constructor for dynamic vector.                *\n *                                                                                             *\n *    This is the normal constructor for the dynamic vector class. It is similar to the normal *\n *    vector class constructor. The vector is initialized to contain the number of elements    *\n *    specified in the \"size\" parameter. The memory is allocated from free store unless the    *\n *    optional array parameter is provided. In this case it will place the vector at the       *\n *    memory location specified.                                                               *\n *                                                                                             *\n * INPUT:   size  -- The maximum number of objects allowed in this vector.                     *\n *                                                                                             *\n *          array -- Optional pointer to the memory area to place the vector at.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nDynamicVectorClass<T>::DynamicVectorClass(unsigned size, T const * array)\n\t: VectorClass<T>(size, array)\n{\n\tGrowthStep = 10;\n\tActiveCount = 0;\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Resize -- Changes the size of a dynamic vector.                      *\n *                                                                                             *\n *    Use this routine to change the size of the vector. The size changed is the maximum       *\n *    number of allocated objects within this vector. If a memory buffer is provided, then     *\n *    the vector will be located there. Otherwise, the memory will be allocated out of free    *\n *    store.                                                                                   *\n *                                                                                             *\n * INPUT:   newsize  -- The desired maximum size of this vector.                               *\n *                                                                                             *\n *          array    -- Optional pointer to a previously allocated memory array.               *\n *                                                                                             *\n * OUTPUT:  bool; Was vector successfully resized according to specifications?                 *\n *                                                                                             *\n * WARNINGS:   Failure to resize the vector could be the result of lack of free store.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Resize(unsigned newsize, T const * array)\n{\n\tif (VectorClass<T>::Resize(newsize, array)) {\n\t\tif (Length() < (unsigned)ActiveCount) ActiveCount = Length();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::ID -- Find matching value in the dynamic vector.                     *\n *                                                                                             *\n *    Use this routine to find a matching object (by value) in the vector. Unlike the base     *\n *    class ID function of similar name, this one restricts the scan to the current number     *\n *    of valid objects.                                                                        *\n *                                                                                             *\n * INPUT:   object   -- A reference to the object that a match is to be found in the           *\n *                      vector.                                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the index number of the object that is equivalent to the one          *\n *          specified. If no equivalent object could be found then -1 is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::ID(T const & object)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif ((*this)[index] == object) return(index);\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Add -- Add an element to the vector.                                 *\n *                                                                                             *\n *    Use this routine to add an element to the vector. The vector will automatically be       *\n *    resized to accomodate the new element IF the vector was allocated previously and the     *\n *    growth rate is not zero.                                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object that will be added to the vector.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully? If so, the object is added to the end     *\n *                of the vector.                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Add(T const & object)\n{\n\tif (ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the end of the object vector.\n\t*/\n\t(*this)[ActiveCount++] = object;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Add_Head -- Adds element to head of the list.                        *\n *                                                                                             *\n *    This routine will add the specified element to the head of the vector. If necessary,     *\n *    the vector will be expanded accordingly.                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object to add to the head of this vector.             *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added without error?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Add_Head(T const & object)\n{\n\tif (ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the end of the object vector.\n\t*/\n\tif (ActiveCount) {\n\t\tmemmove(&(*this)[1], &(*this)[0], ActiveCount * sizeof(T));\n\t}\n\t(*this)[0] = object;\n\tActiveCount++;\n//\t(*this)[ActiveCount++] = object;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Delete -- Remove the specified object from the vector.               *\n *                                                                                             *\n *    This routine will delete the object referenced from the vector. All objects in the       *\n *    vector that follow the one deleted will be moved \"down\" to fill the hole.                *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object in this vector that is to be deleted.          *\n *                                                                                             *\n * OUTPUT:  bool; Was the object deleted successfully? This should always be true.             *\n *                                                                                             *\n * WARNINGS:   Do no pass a reference to an object that is NOT part of this vector. The        *\n *             results of this are undefined and probably catastrophic.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Delete(T const & object)\n{\n\treturn(Delete(ID(object)));\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Delete -- Deletes the specified index from the vector.               *\n *                                                                                             *\n *    Use this routine to delete the object at the specified index from the objects in the     *\n *    vector. This routine will move all the remaining objects \"down\" in order to fill the     *\n *    hole.                                                                                    *\n *                                                                                             *\n * INPUT:   index -- The index number of the object in the vector that is to be deleted.       *\n *                                                                                             *\n * OUTPUT:  bool; Was the object index deleted successfully? Failure might mean that the index *\n *                specified was out of bounds.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint DynamicVectorClass<T>::Delete(int index)\n{\n\tif ((unsigned)index < ActiveCount) {\n\t\tActiveCount--;\n\n\t\t/*\n\t\t**\tIf there are any objects past the index that was deleted, copy those\n\t\t**\tobjects down in order to fill the hole. A simple memory copy is\n\t\t**\tnot sufficient since the vector could contain class objects that\n\t\t**\tneed to use the assignment operator for movement.\n\t\t*/\n\t\tfor (int i = index; i < ActiveCount; i++) {\n\t\t\t(*this)[i] = (*this)[i+1];\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n/************************** end of dynavec.cpp *****************************/\n#endif"
  },
  {
    "path": "REDALERT/EDIT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/EDIT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EDIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EditClass::Action -- Handles input events.                                                *\n *   EditClass::Draw_Background -- Draw the background to the edit gadget.                     *\n *   EditClass::Draw_Me -- Draws the edit box and embedded text.                               *\n *   EditClass::Draw_Text -- Draws the edit gadget text.                                       *\n *   EditClass::EditClass -- Normal constructor for edit class object.                         *\n *   EditClass::Handle_Key -- Handles keyboard input to edit gadget.                           *\n *   EditClass::Set_Text -- Sets the text to the edit gadget.                                  *\n *   EditClass::~EditClass -- Default destructor for the edit gadget.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * EditClass::EditClass -- Normal constructor for edit class object.                           *\n *                                                                                             *\n *    This is the normal constructor used to create an edit object.                            *\n *                                                                                             *\n * INPUT:   id    -- The ID number for this edit object. This is the ID number that will be    *\n *                   returned by the Input() function when the <RETURN> key is pressed if this *\n *                   gadget has the keyboard input focus.                                      *\n *                                                                                             *\n *          text  -- Reference to the text buffer that the edit gadget will modify as keyboard *\n *                   input is processed. The value that this buffer contains is the default    *\n *                   text displayed.                                                           *\n *                                                                                             *\n *          maxlen-- The maximum size of the text buffer specified. This length INCLUDES the   *\n *                   trailing null character so a simple sizeof() function call can be used.   *\n *                                                                                             *\n *          flags -- These are the text print control flags. It is used to control how the     *\n *                   text looks in the edit box. Use the normal TPF_??? flags.                 *\n *                                                                                             *\n *          x,y   -- The pixel coordinates of the upper left corner of the edit gadget area.   *\n *                                                                                             *\n *          w,h   -- The pixel dimensions of the edit box. If either of these are no provided, *\n *                   or set to -1, then the dimension is determined from the string itself.    *\n *                                                                                             *\n *          sytle -- This style flag parameter control what kind of characters are allowed in  *\n *                   the edit box. The initial string in the text buffer may contain illegal   *\n *                   characters, but they are NOT removed regardless of this parameter.        *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/05/1995 MML : Created.                                                                 *\n *   01/21/1995 JLB : Modified.                                                                *\n *=============================================================================================*/\nEditClass::EditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, EditStyle style) :\n\tControlClass (id, x, y, w, h, LEFTPRESS), String(text)\n{\n\tTextFlags = flags & ~(TPF_CENTER);\n\tEditFlags = style;\n\tSet_Text(text, max_len);\n\tColor = GadgetClass::Get_Color_Scheme();\n\n\tif (w == -1 || h == -1) {\n\t\t// PG_TO_FIX\n\t\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight+1;\n\t\t}\n\t\tif (w == -1) {\n\t\t\tif (strlen(String) > 0) {\n\t\t\t\tWidth = String_Pixel_Width(String) + 6;\n\t\t\t} else {\n\t\t\t\tWidth = ((Char_Pixel_Width('X')+FontXSpacing) * (MaxLength+1)) + 2;\n\t\t\t}\n    \t}\n\t}\n\n\tIsReadOnly = 0;\n}\n\n\n/***********************************************************************************************\n * EditClass::~EditClass -- Default destructor for the edit gadget.                            *\n *                                                                                             *\n *    This default destructor removes the focus setting if it currently has it.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEditClass::~EditClass(void)\n{\n\tif (Has_Focus()) {\n\t\tClear_Focus();\n\t}\n}\n\n\n/***********************************************************************************************\n * EditClass::Set_Text -- Sets the text to the edit gadget.                                    *\n *                                                                                             *\n *    Use this routine to change the text that this edit gadget refers to.                     *\n *                                                                                             *\n * INPUT:   text     -- Reference to the character array that this edit gadget will be         *\n *                      modifying.                                                             *\n *          max_len  -- The maximum size of the buffer that will be modified.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Set_Text(char * text, int max_len)\n{\n\tString = text;\n\tMaxLength = max_len-1;\n\tLength = strlen(String);\n\tFlag_To_Redraw();\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Me -- Draws the edit box and embedded text.                                 *\n *                                                                                             *\n *    This routine will render the edit box. This will show the box outline as well as any     *\n *    text it may contain.                                                                     *\n *                                                                                             *\n * INPUT:   forced   -- Should the edit box be drawn even if it thinks it doesn't have to?     *\n *                                                                                             *\n * OUTPUT:  Was the edit box drawn?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint EditClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color.\n\t\t*/\n\t\tDraw_Background();\n\n\t\t/*\n\t\t**\tDisplay the text.\n\t\t*/\n\t\tDraw_Text(String);\n\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * EditClass::Action -- Handles input events.                                                  *\n *                                                                                             *\n *    This routine will handle all mouse and keyboard events directed at this edit box         *\n *    gadget. For keyboard events, this will insert the characters into the edit box.          *\n *                                                                                             *\n * INPUT:   flags -- The event flag that triggered this function call.                         *\n *                                                                                             *\n *          key   -- Reference to the keyboard/mouse event that triggered this function call.  *\n *                                                                                             *\n * OUTPUT:  Should the list be processed further?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint EditClass::Action(unsigned flags, KeyNumType & key)\n{\n\t/*\n\t** If this is a read-only edit box, it's a display-only device\n\t*/\n\tif (IsReadOnly) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the left mouse button is pressed over this gadget, then set the focus to\n\t**\tthis gadget. The event flag is cleared so that no button ID number is returned.\n\t*/\n\tif ((flags & LEFTPRESS)) {\n\t\tflags &= ~LEFTPRESS;\n\t\tSet_Focus();\n\t\tFlag_To_Redraw();\t\t// force to draw cursor\n\t}\n\n\t/*\n\t**\tHandle keyboard events here. Normally, the key is added to the string, but if the\n\t**\tRETURN key is pressed, then the button ID number is returned from the Input()\n\t**\tfunction.\n\t*/\n\tif ((flags & KEYBOARD) && Has_Focus()) {\n\n\t\t/*\n\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t**\tso that the edit gadget ID number is not returned.\n\t\t*/\n\t\tif (key == KN_ESC) {\n\n\t\t\tClear_Focus();\n\t\t\tflags = 0;\n\n\t\t} else {\n#ifdef WIN32\n\n\t\t\tKeyASCIIType ascii = (KeyASCIIType)(Keyboard->To_ASCII(key) & 0xff);\n\n\t\t\t/*\n\t\t\t** Allow numeric keypad presses to map to ascii numbers\n\t\t\t*/\n\t\t\tif ((key & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {\n\n\t\t\t\tkey = (KeyNumType)(key & ~WWKEY_VK_BIT);\n\t\t\t\tif ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\tif (Handle_Key (ascii) ) {\n\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** Filter out all special keys except return and backspace\n\t\t\t\t*/  \tif ((!(key & WWKEY_VK_BIT) && ascii >= ' ' && ascii <= 255)\n\t\t\t\t\t|| key == KN_RETURN || key == KN_BACKSPACE) {\n\n\n\n\t\t\t\t\tif ((!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))) {\n\t\t\t\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\t\tkey = KN_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#else\t//WIN32\n\t\t\tif (Handle_Key(Keyboard->To_ASCII(key))) {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t\tkey = KN_NONE;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\t}\n\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Background -- Draw the background to the edit gadget.                       *\n *                                                                                             *\n *    This routine will redraw the edit gadget background. The overlaying text is handled by   *\n *    a different routine. The mouse is guaranteed to be hidden when this routine is called.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Draw_Background(void)\n{\n\tDraw_Box (X, Y, Width, Height, BOXSTYLE_BOX, true);\n}\n\n\n/***********************************************************************************************\n * EditClass::Draw_Text -- Draws the edit gadget text.                                         *\n *                                                                                             *\n *    This routine is called when the edit gadget text needs to be drawn. The background has   *\n *    already been drawn by the time this function is called. The mouse is guaranteed to be    *\n *    hidden as well.                                                                          *\n *                                                                                             *\n * INPUT:   text  -- The text to draw in the edit gadget.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EditClass::Draw_Text(char const * text)\n{\n\tTextPrintType flags;\n\n\tif (Has_Focus()) {\n\t\tflags = TPF_BRIGHT_COLOR;\n\t} else {\n\t\tflags = (TextPrintType)0;\n\t}\n\n\tConquer_Clip_Text_Print(text, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);\n\n\tif (Has_Focus() && (int)strlen(text) < MaxLength &&\n\t\t((int)String_Pixel_Width(text) + (int)String_Pixel_Width (\"_\") < Width-2) ) {\n\t\tConquer_Clip_Text_Print( \"_\", X+1+String_Pixel_Width(text), Y+1, Color, TBLACK, TextFlags | flags);\n\t}\n}\n\n\n/***********************************************************************************************\n * EditClass::Handle_Key -- Handles keyboard input to edit gadget.                             *\n *                                                                                             *\n *    This is the gruntwork routine that processes keyboard input to the edit gadget. This     *\n *    routine will be called when keyboard input has been detected and this gadget has the     *\n *    current focus.                                                                           *\n *                                                                                             *\n * INPUT:   ascii -- The ASCII key code that was fetched from the keyboard buffer.             *\n *                                                                                             *\n * OUTPUT:  bool; Should this keyboard input NOT cause the gadget ID number to be returned     *\n *                from the controlling Input() routine? Typically, the return value would be   *\n *                true unless the focus is lost due to the <RETURN> key being pressed.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool EditClass::Handle_Key(KeyASCIIType ascii)\n{\n\tswitch (ascii) {\n\t\t/*\n\t\t**\tHandle the special case of a non-keyboard event. It is possible that this\n\t\t**\tkey code might be passed to this routine if this routine has been overridden\n\t\t**\tand the key event was consumed.\n\t\t*/\n\t\tcase 0:\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the return key is pressed, then remove the focus from this edit\n\t\t**\tgadget but otherwise let the normal gadget processing proceed. This\n\t\t**\tcauses the gadget ID number to be returned from the Input() function\n\t\t**\tso that the controlling program will know that the text can be\n\t\t**\tprocessed.\n\t\t*/\n\t\tcase KA_RETURN:\n\t\t\tClear_Focus();\n\t\t\treturn(false);\n\n\t\t/*\n\t\t**\tWhen the BACKSPACE key is pressed, remove the last character in the edit string.\n\t\t*/\n\t\tcase KA_BACKSPACE:\n\t\t\tif (Length) {\n\t\t\t\tLength--;\n\t\t\t\tString[Length] = '\\0';\n\t\t\t\tFlag_To_Redraw();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the keyboard event was not a recognized special key, then examine to see\n\t\t**\tif it can legally be added to the edit string and do so if possible.\n\t\t*/\n\t\tdefault:\n\n\t\t\t/*\n\t\t\t**\tDon't add a character if the length is greater than edit width.\n\t\t\t*/\n\t\t\tif (((int)String_Pixel_Width(String) + (int)Char_Pixel_Width(ascii) ) >= (Width-2)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDon't add a character if the length is already at maximum.\n\t\t\t*/\n\t\t\tif (Length >= MaxLength) break;\n\n\t\t\t/*\n\t\t\t**\tInvisible characters are never added to the string. This is\n\t\t\t**\tespecially true for spaces at the beginning of the string.\n\t\t\t*/\n\t\t\tif (!isgraph(ascii) && ascii != ' ') break;\n\t\t\tif (ascii == ' ' && Length == 0) break;\n\n\t\t\t/*\n\t\t\t**\tIf this is an upper case only edit gadget, then force the alphabetic\n\t\t\t**\tcharacter to upper case.\n\t\t\t*/\n\t\t\tif ((EditFlags & UPPERCASE) && isalpha(ascii)) {\n\t\t\t\tascii = (KeyASCIIType)toupper(ascii);\n\t\t\t}\n\n\t\t\tif ((!(EditFlags & NUMERIC) || !isdigit(ascii)) &&\n\t\t\t\t(!(EditFlags & ALPHA) || !isalpha(ascii)) &&\n\t\t\t\t(!(EditFlags & MISC) || isalnum(ascii)) &&\n\t\t\t\tascii != ' ') {\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThe character passed all legality checks, so add it to the edit string\n\t\t\t**\tand flag this gadget to be redrawn. The manual flag to redraw is needed\n\t\t\t**\tbecause the event flag has been cleared. This prevents the gadget's ID\n\t\t\t**\tnumber from being returned just because the gadget has been edited.\n\t\t\t*/\n\t\t\tString[Length++] = ascii;\n\t\t\tString[Length] = '\\0';\n\t\t\tFlag_To_Redraw();\n\t\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\nvoid EditClass::Set_Focus(void)\n{\n\tLength = 0;\n\tif (String) {\n\t\tLength = strlen(String);\n\t}\n\tControlClass::Set_Focus();\n}\n"
  },
  {
    "path": "REDALERT/EDIT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/EDIT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EDIT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EDIT_H\n#define EDIT_H\n\nclass EditClass : public ControlClass\n{\n\tpublic:\n\t\ttypedef enum EditStyle {\n\t\t\tALPHA\t\t\t=0x0001,\t\t// Edit accepts alphabetic characters.\n\t\t\tNUMERIC\t\t=0x0002,\t\t// Edit accepts numbers.\n\t\t\tMISC\t\t\t=0x0004,\t\t// Edit accepts misc graphic characters.\n\t\t\tUPPERCASE\t=0x0008,\t\t// Force to upper case.\n\t\t\tALPHANUMERIC=(int)ALPHA|(int)NUMERIC|(int)MISC\n\t\t} EditStyle;\n\n\t\tEditClass (int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1, EditStyle style=ALPHANUMERIC);\n\t\tvirtual ~EditClass(void);\n\n\t\tvirtual void Set_Focus(void);\n\t\tvirtual int  Draw_Me(int forced);\n\t\tvirtual void Set_Text(char * text, int max_len);\n\t\tvirtual char * Get_Text(void) {return(String);};\n\t\tvoid Set_Color (RemapControlType * color) { Color = color; }\n\n\t\tvoid Set_Read_Only(int rdonly) {IsReadOnly = rdonly;}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThese are the text size and style flags to be used when displaying the text\n\t\t**\tof the edit gadget.\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tInput flags that control what characters are allowed in the string.\n\t\t*/\n\t\tEditStyle EditFlags;\n\n\t\t/*\n\t\t**\tPointer to text staging buffer and the maximum length of the string it\n\t\t**\tcan contain.\n\t\t*/\n\t\tchar *String;\n\t\tint MaxLength;\n\n\t\t/*\n\t\t**\tThis is the current length of the string. This length will never exceed the\n\t\t**\tMaxLength allowed.\n\t\t*/\n\t\tint Length;\n\n\t\t/*\n\t\t**\tThis is the desired color of the edit control.\n\t\t*/\n\t\tRemapControlType * Color;\n\n\t\tvirtual int Action (unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Background(void);\n\t\tvirtual void Draw_Text(char const * text);\n\t\tvirtual bool Handle_Key(KeyASCIIType ascii);\n\n\tprivate:\n\t\tint IsReadOnly;\n};\n\n//PG inline EditClass::EditStyle operator |(EditClass::EditStyle, EditClass::EditStyle);\n//PG inline EditClass::EditStyle operator &(EditClass::EditStyle, EditClass::EditStyle);\n//PG inline EditClass::EditStyle operator ~(EditClass::EditStyle);\n\ninline EditClass::EditStyle operator|(EditClass::EditStyle a, EditClass::EditStyle b)\n{\n\treturn static_cast<EditClass::EditStyle>(static_cast<int>(a) | static_cast<int>(b));\n}\n\ninline EditClass::EditStyle operator&(EditClass::EditStyle a, EditClass::EditStyle b)\n{\n\treturn static_cast<EditClass::EditStyle>(static_cast<int>(a) & static_cast<int>(b));\n}\n\ninline EditClass::EditStyle operator~(EditClass::EditStyle a)\n{\n\treturn static_cast<EditClass::EditStyle>(~static_cast<int>(a));\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/EGOS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/EGOS.CPP 2     3/10/97 3:19p Steve_tall $ */\n/*************************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : EGOS.CPP                                           *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : September 4th, 1996                                *\n *                                                                                   *\n *                  Last Update : September 4th, 1996 [ST]                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *   Scrolling movie style credits.                                                  *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if(0)\n//PG_TO_FIX\n#include \t\"function.h\"\n\n/*\n** List of Ego Class instances\n**  There will be one instance for each line of text.\n*/\nDynamicVectorClass<EgoClass *> EgoList;\n\n/*\n** Number of slideshow pictures\n*/\n\n#define NUM_SLIDES 17\n\n/*\n** Length of time frame is displayed for\n*/\n#define FRAME_DELAY\t150\n\n/*\n** Number of frames that palete fade occurs over\n*/\n#define FADE_DELAY\t\t37\n\n/*\n** Names of slideshow pictures to play behind the text\n*/\nchar SlideNames[NUM_SLIDES][13]={\n\n\t\"aftr_hi.pcx\",\n\t\"aly1.pcx\",\n\t\"apc_hi.pcx\",\n\t\"aphi0049.pcx\",\n\t\"bnhi0020.pcx\",\n\t\"dchi0040.pcx\",\n\t\"frhi0166.pcx\",\n\t\"lab.pcx\",\n\t\"landsbrg.pcx\",\n\t\"mahi0107.pcx\",\n\t\"mig_hi.pcx\",\n\t\"mtfacthi.pcx\",\n\t\"needle.pcx\",\n\t\"sov2.pcx\",\n\t\"spy.pcx\",\n\t\"stalin.pcx\",\n\t\"tent.pcx\"\n};\n\n/*\n** Names of low res slideshow pictures to play behind the text\n*/\nchar LoresSlideNames[NUM_SLIDES][13]={\n\t\"malo0107.cps\",\n\t\"mig_lo.cps\",\n\t\"mtfactlo.cps\",\n\t\"needl-lo.cps\",\n\t\"sov2-lo.cps\",\n\t\"spy-lo.cps\",\n\t\"staln-lo.cps\",\n\t\"tent-lo.cps\",\n\t\"aftr_lo.cps\",\n\t\"aly1-lo.cps\",\n\t\"apc_lo.cps\",\n\t\"aplo0049.cps\",\n\t\"bnlo0020.cps\",\n\t\"dclo0040.cps\",\n\t\"frlo0166.cps\",\n\t\"lab-lo.cps\",\n\t\"lands-lo.cps\"\n};\n\n/*\n** Array of all the palettes required for the slides\n*/\nchar SlidePals[NUM_SLIDES][256*3];\n\n/*\n** Array of graphic buffers containing the slides\n*/\nGraphicBufferClass *SlideBuffers[NUM_SLIDES];\n\n/*\n** Original copy of slide (pref in video mem) that we use to undraw the text\n*/\nGraphicBufferClass *BackgroundPage;\n\n/*\n**  This palette contains both the font palette entries and the slide\n**  palette.\n*/\nPaletteClass ComboPalette;\n\n/*\n** Ptr to the combo palette.\n*/\nunsigned char *ComboPalPtr;\n\n/*\n** Lookup table. If an entry is non-zero then it should be faded in/out when the slide changes.\n*/\nchar PaletteLUT[256];\n\n/*\n** Height of the strips that are blitted from the slides to the backgound and hid pages.\n** We blit in several strips over several frames so as not to impact on the frame rate.\n*/\n#define CHUNK_HEIGHT RESFACTOR * 50\n\n\n\n#ifndef\tWIN32\nextern void Vsync(void);\n#pragma aux Vsync modify [edx ebx eax] = \\\n\t\"mov\tedx,03DAh\"\t\t\t\t\\\n\t\"mov\tebx,[VertBlank]\"\t\t\\\n\t\"and\tbl,001h\"\t\t\t\t\t\\\n\t\"shl\tbl,3\"\t\t\t\t\t\t\\\n\t\"in_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"je\tin_vbi\"\t\t\t\t\t\\\n\t\"out_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"jne\tout_vbi\"\n#endif\t//WIN32\n\n\n\n/***********************************************************************************************\n * EC::EgoClass -- EgoClass constructor                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    x position of text                                                                *\n *           y position of text                                                                *\n *           ptr to text string                                                                *\n *           flags to print text with                                                          *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:53PM ST : Created                                                              *\n *=============================================================================================*/\nEgoClass::EgoClass (int x, int y, char *text, TextPrintType flags)\n{\n\tXPos = x;\n\tYPos = y;\n\tFlags= flags;\n\tText = new char [strlen (text)+1];\n\tstrcpy (Text, text);\n}\n\n\n/***********************************************************************************************\n * EC::~EgoClass -- EgoClass destructor                                                        *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:54PM ST : Created                                                              *\n *=============================================================================================*/\nEgoClass::~EgoClass(void)\n{\n\tdelete [] Text;\n}\n\n\n/***********************************************************************************************\n * EC::Scroll -- Apply the given distance to the y position of the text.                       *\n *               A positive distance scrolls up.                                               *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    distance in pixels to scroll up                                                   *\n *                                                                                             *\n * OUTPUT:   true if text scrolled beyond the top of the screen                                *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:55PM ST : Created                                                              *\n *=============================================================================================*/\nbool EgoClass::Scroll(int distance)\n{\n\tYPos -= distance;\n\tif (YPos < -20) {\n\t\treturn (true);\n\t}else{\n\t\treturn (false);\n\t}\n}\n\n\n/***********************************************************************************************\n * EC::Render -- Draws the text to the logic page                                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:57PM ST : Created                                                              *\n *=============================================================================================*/\nvoid EgoClass::Render (void)\n{\n\tif (YPos < LogicPage->Get_Height() && YPos > -16) {\n\t\tFancy_Text_Print(Text, XPos, YPos, GadgetClass::Get_Color_Scheme(), TBLACK, Flags);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * EC::Wipe -- Wipes the previously rendered text by blitting a rectangle from the given       *\n *             background screen.                                                              *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to screen containing original background                                      *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:58PM ST : Created                                                              *\n *=============================================================================================*/\nvoid EgoClass::Wipe (GraphicBufferClass *background)\n{\n\tint width = String_Pixel_Width (Text);\n\tint x = XPos;\n\n\tif (Flags & TPF_RIGHT) {\n\t\tx -= width;\n\t}else{\n\t\tif (Flags & TPF_CENTER){\n\t\t\tx -= width/2;\n\t\t}\n\t}\n\n\tbackground->Blit(*LogicPage, x-1, YPos, x-1, YPos, width+2, 7 * RESFACTOR +1, false);\n}\n\n\n\n/***********************************************************************************************\n * Set_Pal -- Low level palette set                                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/9/96 11:59PM ST : Created                                                              *\n *=============================================================================================*/\nvoid Set_Pal(char *palette)\n{\n//#ifndef WIN32\n\t//Vsync();\n\t//unsigned char *rgbptr = (unsigned char *) palette;\n\t//outportb(0x03C8, 0);\t\t\t\t\t\t\t\t\t\t\t\t//Start from color 0\n\n\t//for (int index = 0; index < 256; index++) {\n\t//\toutrgb(rgbptr[index*3], rgbptr[index*3+1], rgbptr[index*3+2]);\n\t//}\n//#else\t//WIN32\n\n\tSet_Palette((void*)palette);\n//#endif\n}\n\n\n/***********************************************************************************************\n * Slide_Show -- Handles the blitting and fading of the background pictures.                   *\n *                                                                                             *\n *  The picture frame number is used to trigger blitting and fading events                     *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    picture number                                                                    *\n *           frame                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/10/96 0:16AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Slide_Show (int slide, int frame)\n{\n\n\t/*\n\t** Temprary storage to save CCPalette to\n\t*/\n\tchar save_palette[256*3];\n\n\n\tif (frame >= 1 && frame <=4){\n\t\t/*\n\t\t** Blit in a quarter of the new frame to the background page.\n\t\t*/\n\t\tSlideBuffers[slide]->Blit (*BackgroundPage, \t0, (frame-1) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, (frame-1) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width(), CHUNK_HEIGHT, false);\n\t\treturn;\n\t}\n\n\tif (frame >= 5 && frame <=8 ){\n\t\t/*\n\t\t** Blit in a quarter of the new frame to the hid page.\n\t\t*/\n\t\tBackgroundPage->Blit (HidPage,\t0, (frame-5) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\t0, (frame-5) * CHUNK_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width(), CHUNK_HEIGHT, false);\n\t\treturn;\n\t}\n\n\tif (frame ==9){\n\t\t/*\n\t\t** Create the combo palette from the font entries and the picture entries.\n\t\t*/\n\t\tfor (int index = 0 ; index < 256 ; index++ ){\n\t\t\tif (PaletteLUT[index]) {\n\t\t\t\tComboPalPtr[index*3] = SlidePals[slide][index*3];\n\t\t\t\tComboPalPtr[index*3+1] = SlidePals[slide][index*3+1];\n\t\t\t\tComboPalPtr[index*3+2] = SlidePals[slide][index*3+2];\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\n\tif (frame >10 && frame < FADE_DELAY+10){\n\t\t/*\n\t\t** Fade up the picture in the background. The text colors never fade.\n\t\t*/\n\t\tmemcpy (save_palette, CCPalette, sizeof(save_palette));\n\t\t//CCPalette.Partial_Adjust (MIN (6*(frame-5), 255), ComboPalette, PaletteLUT);\n\t\tCCPalette.Partial_Adjust (MIN ((255/FADE_DELAY)*(frame-10), 255), ComboPalette, PaletteLUT);\n\t\tSet_Pal ( (char *) &CCPalette);\n\t\tif (frame != 9+FADE_DELAY){\n\t\t\tmemcpy (CCPalette, save_palette, sizeof(save_palette));\n\t\t}else{\n\t\t\tmemcpy (CCPalette, CurrentPalette, sizeof (CCPalette));\n\t\t}\n\t\treturn;\n\t}\n\n\n\tif (frame >FRAME_DELAY && frame < FRAME_DELAY+FADE_DELAY){\n\t\t/*\n\t\t** Fade down the picture in the background. The text colors never fade.\n\t\t*/\n\t\tmemcpy (save_palette, CCPalette, sizeof(save_palette));\n\t\tCCPalette.Partial_Adjust (MIN ((255/FADE_DELAY)*(frame-FRAME_DELAY), 255), PaletteLUT);\n\t\tif (frame != FRAME_DELAY+FADE_DELAY-1){\n\t\t\tSet_Pal ( (char *) &CCPalette);\n\t\t\tmemcpy (CCPalette, save_palette, sizeof(save_palette));\n\t\t}else{\n\t\t\t/*\n\t\t\t** If this is the last fade down frame then zero the picture palette entries.\n\t\t\t*/\n\t\t\tunsigned char *ccpalptr = (unsigned char*)CCPalette;\n\t\t\tfor (int index = 0 ; index < 256 ; index++){\n\t\t\t\tif (PaletteLUT[index]){\n\t\t\t\t\tccpalptr[index*3] = 0;\n\t\t\t\t\tccpalptr[index*3+1] = 0;\n\t\t\t\t\tccpalptr[index*3+2] = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSet_Pal ( (char *) &CCPalette);\n\t\t}\n\n\t}\n\n}\n\n\n\n\n/***********************************************************************************************\n * Show_Who_Was_Responsible -- Main function to print the credits.                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    9/10/96 0:20AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Show_Who_Was_Responsible (void)\n{\n\n\tint\ti;\n\tint\tkey;\n\n\t/*\n\t** Deault speed of credits scolling. This is the frame delay between pixel scrolls.\n\t*/\n\tstatic int speed = 3;\n\n\t/*\n\t** In DOS we need to scroll slower so we have a bool that lets us do it every other time\n\t*/\n#ifndef WIN32\n\tbool\tscroll_now = false;\n#endif\t//WIN32\n\n\t/*\n\t** Read in the credits file to be displayed\n\t**\n\t** Lines of text in CREDITS.TXT are treated as follows....\n\t**\n\t**  If the text starts and ends to the left of column 40 then text will be right justified.\n\t**  If the text starts before column 40 and ends after it then it will be centered.\n\t**  If the text starts after column 40 it will be right justified.\n\t*/\n\tCCFileClass creditsfile (\"credits.txt\");\n\tif ( !creditsfile.Is_Available()) return;\n\tchar *credits = new char [creditsfile.Size()+1];\n\tcreditsfile.Read (credits, creditsfile.Size());\n\n\t/*\n\t** Initialise the text printing system.\n\t*/\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_GREEN]);\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\t/*\n\t** Miscellaneous stuff for parsing the credits text file.\n\t*/\n\tint \t\t\t\tlength = creditsfile.Size();\n\tint \t\t\t\tline   = 0;\n\tint \t\t\t\tcolumn = 0;\n\tchar\t\t\t\t*cptr = credits;\n\tchar\t\t\t\tch, lastchar, oldchar;\n\tchar\t\t\t\t*strstart, *strparse;\n\tbool\t\t\t\tgotendstr;\n\tint\t\t\t\tstartcolumn, endcolumn, x;\n\tint\t\t\t\ty=SeenBuff.Get_Height()+2;\n\tEgoClass \t\t*ego;\n\tTextPrintType \tflags;\n\n\n\t/*\n\t** Search through the text file and extract the strings, using each string to create\n\t** a new EgoClass\n\t*/\n\tdo {\n\t\t/*\n\t\t** Search for text\n\t\t*/\n\t\tch = *cptr++;\n\t\tlength --;\n\n\t\t/*\n\t\t** Look for a non whitespace character.\n\t\t*/\n\t\tswitch ( ch ){\n\n\t\t\tcase 13:\n\t\t\t\t/*\n\t\t\t\t** Char was carriage return. Go on to the next line starting at column 0.\n\t\t\t\t*/\n\t\t\t\tline++;\n\t\t\t\tcolumn = 0;\n\t\t\t\tbreak;\n\n\n\t\t\tcase 10:\n\t\t\t\t/*\n\t\t\t\t** Ignore line feed. CR does both.\n\t\t\t\t*/\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t** Space character. Just advance the cursor and move on.\n\t\t\t\t*/\n\t\t\tcase 32:\n\t\t\t\tcolumn++;\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t** Tab char. Advance to the next tab column. Tabs are every 8 columns.\n\t\t\t\t*/\n\t\t\tcase 9:\n\t\t\t\tcolumn += 8;\n\t\t\t\tcolumn &= 0xfffffff8;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/*\n\t\t\t\t** Found new string. Work out where it ends so we know how to treat it.\n\t\t\t\t*/\n\t\t\t\tlastchar = ch;\n\t\t\t\tstrstart = cptr-1;\n\t\t\t\tstrparse = cptr-1;\n\t\t\t\tendcolumn = startcolumn = column;\n\t\t\t\tgotendstr = false;\n\n\t\t\t\tdo\t{\n\t\t\t\t\tch = *strparse++;\n\t\t\t\t\tswitch ( ch ){\n\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\tcase 10:\n\t\t\t\t\t\tcase 13:\n\t\t\t\t\t\t\tgotendstr = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 32:\n\t\t\t\t\t\t\tif (lastchar == 32) gotendstr = true;\n\t\t\t\t\t\t\tendcolumn++;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tendcolumn++;\n\t\t\t\t\t}\n\t\t\t\t\tif (strparse >= cptr+length) gotendstr = true;\n\n\t\t\t\t\tlastchar = ch;\n\t\t\t\t}while (!gotendstr);\n\n\n\t\t\t\tif (strparse >= cptr+length) break;\n\n\t\t\t\t/*\n\t\t\t\t** Strip off any trailing space.\n\t\t\t\t*/\n\t\t\t\tif (*(strparse-2) == 32){\n\t\t\t\t\tstrparse--;\n\t\t\t\t\tendcolumn -= 2;\n\t\t\t\t}\n\n\n\t\t\t\t/*\n\t\t\t\t** If string straddles the center column then center it.\n\t\t\t\t**\n\t\t\t\t** If string is on the left hand side then right justify it.\n\t\t\t\t**\n\t\t\t\t** If string is on the right hand side then left justify it.\n\t\t\t\t*/\n\t\t\t\tflags = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_DROPSHADOW;\t//TPF_NOSHADOW;\n\n\t\t\t\tif (startcolumn <40 && endcolumn >40){\n\t\t\t\t\tflags = flags | TPF_CENTER;\n\t\t\t\t\tx = SeenBuff.Get_Width() / 2;\n\t\t\t\t}else{\n\t\t\t\t\tif (startcolumn <40){\n\t\t\t\t\t\tflags = flags | TPF_RIGHT;\n\t\t\t\t\t\tx = endcolumn *SeenBuff.Get_Width() /80;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tx = startcolumn * SeenBuff.Get_Width() / 80;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Temporarily terminate the string.\n\t\t\t\t*/\n\t\t\t\toldchar = *(strparse-1);\n\t\t\t\t*(strparse-1) = 0;\n\n\t\t\t\t/*\n\t\t\t\t** Create the new class and add it to our list.\n\t\t\t\t*/\n\t\t\t\tego = new EgoClass (x, y+ line *8 *RESFACTOR, strstart, flags);\n\n\t\t\t\tEgoList.Add (ego);\n\n\t\t\t\t/*\n\t\t\t\t** Restore the character that was lost when we added the terminator.\n\t\t\t\t*/\n\t\t\t\t*(strparse-1) = oldchar;\n\n\t\t\t\t/*\n\t\t\t\t** Fix up our outer loop parsing variables.\n\t\t\t\t*/\n\t\t\t\tcptr = strparse;\n\t\t\t\tcolumn += strparse - strstart;\n\t\t\t\tlength -= strparse - strstart-1;\n\n\t\t\t\tif (ch == 13) {\n\t\t\t\t\tline++;\n\t\t\t\t\tcolumn = 0;\n\t\t\t\t}else{\n\t\t\t\t\tif (ch == 9){\n\t\t\t\t\t\tcolumn += 7;\n\t\t\t\t\t\tcolumn &= 0xfffffff8;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t} while ( length>0 );\n\n\n\t/*\n\t** Work out which palette entries the font needs so we dont fade those colors.\n\t*/\n\tmemset (PaletteLUT, 1, sizeof (PaletteLUT));\n\tint pcolor = PCOLOR_GREEN;\n\n\tfor (int index = 0; index < 6; index++) {\n\t\tPaletteLUT[ColorRemaps[pcolor].FontRemap[10+index]] =0;\n\t}\n\t//PaletteLUT[ColorRemaps[pcolor].BrightColor] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Color] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Shadow] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Background] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Corners] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Highlight] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Bright] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Underline] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Bar] = 0;\n\tPaletteLUT[ColorRemaps[pcolor].Box] = 0;\n\n\n\t/*\n\t** Stop the music.\n\t*/\n\tTheme.Stop();\n\n\t/*\n\t** Fade to black.\n\t*/\n\tBlackPalette.Set(TIMER_SECOND*2, Call_Back);\n\n\t/*\n\t** Load the reference palette for the font.\n\t*/\n\t//Load_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Picture(\"EGOPAL.CPS\", SysMemPage, SysMemPage, CCPalette, BM_DEFAULT);\n//#else\t//WIN32\n//\tLoad_Picture(\"EGOPAL.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n//#endif\t//WIN32\n\n\n\tCCFileClass(\"EGOPAL.PAL\").Read(&CCPalette, sizeof(CCPalette));\n\n\t/*\n\t** Copy the font palette entries into the combo palette.\n\t*/\n\tPaletteClass credit_palette;\n\tComboPalPtr = (unsigned char *) &ComboPalette;\n\tunsigned char *creditpal_ptr = (unsigned char *) &credit_palette;\n\tmemcpy (ComboPalette, CCPalette, sizeof (ComboPalette));\n\n\tfor (index = 0 ; index < 256 ; index++ ){\n\t\tif (PaletteLUT[index]) {\n\t\t\tComboPalPtr[index*3] = 0;\n\t\t\tComboPalPtr[index*3+1] = 0;\n\t\t\tComboPalPtr[index*3+2] = 0;\n\t\t}\n\t}\n\n\t/*\n\t** Clear the Seen Page since we will not be blitting to all of it.\n\t*/\n\tSeenBuff.Clear();\n\tHidPage.Clear();\n\n\t/*\n\t** Set the font palette.\n\t*/\n\tmemcpy ( CCPalette, ComboPalette, sizeof (ComboPalette) );\n\tCCPalette.Set();\n\n\t/*\n\t** Loop through and load up all the slideshow pictures\n\t*/\n\tfor (index = 0 ; index < NUM_SLIDES ; index++){\n#ifdef WIN32\n\t\tSlideBuffers[index] = new GraphicBufferClass;\n\t\tSlideBuffers[index]->Init (SeenBuff.Get_Width(), SeenBuff.Get_Height(), NULL , 0 , (GBC_Enum)0);\n\t\tLoad_Title_Screen(&SlideNames[index][0], SlideBuffers[index], (unsigned char*) &SlidePals[index][0]);\n#else\t//WIN32\n\t\tSlideBuffers[index] = new GraphicBufferClass (SeenBuff.Get_Width(), SeenBuff.Get_Height(), (void*)NULL);\n\t\tLoad_Picture(&LoresSlideNames[index][0], *SlideBuffers[index], *SlideBuffers[index], (unsigned char *)&SlidePals[index][0], BM_DEFAULT);\n#endif\t//WIN32\n\t}\n\n\t/*\n\t** Create a new graphic buffer to restore the background from. Initialise it to black so\n\t** we can start scrolling before the first slideshow picture is blitted.\n\t*/\n#ifdef WIN32\n\tBackgroundPage = new GraphicBufferClass;\n\tBackgroundPage->Init (SeenBuff.Get_Width(), SeenBuff.Get_Height(), NULL , 0 , (GBC_Enum)(GBC_VIDEOMEM));\n#else\t//WIN32\n\tBackgroundPage = new GraphicBufferClass (SeenBuff.Get_Width(), SeenBuff.Get_Height(), (void*)NULL );\n#endif\t//WIN32\n\n\tSeenBuff.Blit(*BackgroundPage);\n\n\t/*\n\t** Go away nasty keyboard.\n\t*/\n\tKeyboard->Clear();\n\n\tSet_Logic_Page(HidPage);\n\n\t/*\n\t** Start any old song.\n\t*/\n\tfixed oldvolume = Options.ScoreVolume;\n\tif (oldvolume == 0) {\n\t\tOptions.Set_Score_Volume(fixed(4, 10), false);\n\t}\n\tTheme.Queue_Song(THEME_CREDITS);\n\n\t/*\n\t** Init misc timing variables.\n\t*/\n\tint time  = TickCount;\n\tint frame = 0;\n\tint picture_frame = 0;\n\tint slide_number = 0;\n\n\tHide_Mouse();\n\n\t/*\n\t** Save the priority of this process so we can change it back later\n\t*/\n\t//DWORD process_priority = GetPriorityClass(GetCurrentProcess());\n\n\t/*\n\t** Main scrolling loop.\n\t** Keeps going until all the EgoClass objects are deleted or esc is pressed.\n\t*/\n\twhile ( EgoList.Count() ){\n\n\t\tframe++;\n\n\t\t/*\n\t\t** Once we have been running for a few frames, and Windows has time to do its virtual\n\t\t** memory stuff, increase our priority level.\n\t\t*/\n\t\t//if (frame == 30){\n\t\t//\tSetPriorityClass (GetCurrentProcess() , HIGH_PRIORITY_CLASS);\n\t\t//}\n\n\t\t/*\n\t\t** Update the slideshow frame and switch to the next picture if its time.\n\t\t*/\n\t\tpicture_frame++;\n\n\t\tif (picture_frame > FRAME_DELAY+50){\n\t\t\tif (slide_number <NUM_SLIDES-1){\n\t\t\t\tslide_number++;\n\t\t\t\tpicture_frame = 0;\n\t\t\t}else{\n\t\t\t\tslide_number = 0;\n\t\t\t\tpicture_frame = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Do the slideshow background.\n\t\t*/\n\t\tSlide_Show (slide_number, picture_frame);\n\n\n\t\t/*\n\t\t** Scroll the text. If any text goes off the top then delete that object.\n\t\t*/\n#ifndef WIN32\n\t\tscroll_now = !scroll_now;\n\t\tif (scroll_now){\n#endif\t//WIN32\n\t\t\tfor (i=EgoList.Count()-1 ; i>=0 ; i--){\n\t\t\t\tEgoList[i]->Wipe(BackgroundPage);\n\t\t\t\tif ( EgoList[i]->Scroll(1) ){\n\t\t\t\t\tEgoList.Delete(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n#ifndef WIN32\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Render all the text strings in their new positions.\n\t\t*/\n\t\tif (LogicPage->Lock()){\n\t\t\tfor (i=EgoList.Count()-1 ; i>=0 ; i--){\n\t\t\t\tEgoList[i]->Render();\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\tif (frame > 1000 && !Theme.Still_Playing()){\n\t\t\tTheme.Queue_Song(THEME_CREDITS);\t//NONE);\n\t\t}\n\n\t\t/*\n\t\t** Stop calling Theme.AI after a while so a different song doesnt start playing\n\t\t*/\n\t\tCall_Back();\n//\t\tif (frame <1000 ){\n//\t\t\tTheme.AI();\n//\t\t}else{\n//\t\t\tSound_Callback();\n//\t\t}\n\n\t\t/*\n\t\t** Kill any spare time before blitting the hid page forward.\n\t\t*/\n\t\twhile (TickCount - time < frame *speed && !Keyboard->Check()) {}\n\n\t\t/*\n\t\t** Blit all but the top and bottom of the hid page. This is beacuse the text print doesn't\n\t\t** clip vertically and looks ugly when it suddenly appears and disappears.\n\t\t*/\n#ifndef WIN32\n\t\tWait_Vert_Blank(VertBlank);\n\t\t//Vsync();\n#endif\t//WIN32\n\t\tHidPage.Blit(SeenBuff, 0, 8*RESFACTOR, 0, 8*RESFACTOR, SeenBuff.Get_Width(), SeenBuff.Get_Height() - 16*RESFACTOR, false);\n\n\t\t/*\n\t\t** Try and prevent Win95 from swapping out pictures we havnt used yet.\n\t\t*/\n#ifdef WIN32\n\t\tif (frame && 3 == 3){\n\t\t\tfor (i=slide_number+1 ; i<NUM_SLIDES ; i++){\n\t\t\t\tif ( !SlideBuffers[i]->Get_IsDirectDraw() ){\n\t\t\t\t\tForce_VM_Page_In ((void*)SlideBuffers[i]->Get_Offset(), SeenBuff.Get_Width() * SeenBuff.Get_Height() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t** If user hits escape then break.\n\t\t*/\n\t\tkey = KN_NONE;\n\t\tif (Keyboard->Check()){\n\t\t\tkey = Keyboard->Get();\n\t\t\tif (key == KN_ESC){\n\t\t\t\tbreak;\n\t\t\t}\n#if (0)\n\t\t\tif (key == KN_Z){\n\t\t\t\tspeed--;\n\t\t\t\tif (speed <1 ) speed=1;\n\t\t\t\ttime = TickCount;\n\t\t\t\tframe = 0;\n\t\t\t}\n\t\t\tif (key == KN_X){\n\t\t\t\tspeed++;\n\t\t\t\ttime = TickCount;\n\t\t\t\tframe = 0;\n\t\t\t}\n#endif\t//(0)\n\n\t\t}\n\n\t}\n\n\tif (key == KN_ESC){\n\t\tTheme.Fade_Out();\n\t\tBlackPalette.Set(TIMER_SECOND*2, Call_Back);\n\t}else{\n\t\t/*\n\t\t** Wait for the picture to fade down\n\t\t*/\n\t\twhile (picture_frame <= FADE_DELAY+FRAME_DELAY){\n\t\t\tif (picture_frame < FRAME_DELAY && picture_frame > 10+FADE_DELAY){\n\t\t\t\tpicture_frame = FRAME_DELAY;\n\t\t\t}\n\t\t\tframe++;\n\t\t\tpicture_frame++;\n\n\t\t\tSlide_Show (slide_number, picture_frame);\n\n\t\t\tCall_Back();\n//\t\t\tSound_Callback();\t\t//Theme.AI();\n\n\t\t\t/*\n\t\t\t** Kill any spare time\n\t\t\t*/\n\t\t\twhile (TickCount - time < frame *speed && !Keyboard->Check()) {}\n\n\t\t}\n\t}\n\n\t/*\n\t** Tidy up.\n\t*/\n\t//SetPriorityClass (GetCurrentProcess() , process_priority);\n\tSeenBuff.Clear();\n\n\tShow_Mouse();\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n\n\tTheme.Stop();\n\tOptions.Set_Score_Volume(oldvolume, false);\n\n\tfor (index = 0 ; index < NUM_SLIDES ; index++){\n\t\tdelete SlideBuffers[index];\n\t}\n\n\tdelete BackgroundPage;\n\n\tdelete [] credits;\n\n\tEgoList.Clear();\n}\n\n#endif\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "REDALERT/EGOS.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/*************************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : EGOS.H                                             *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : September 4th, 1996                                *\n *                                                                                   *\n *                  Last Update : September 4th, 1996 [ST]                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *   Scrolling movie style credits.                                                  *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nclass EgoClass {\n\n\tpublic:\n\n\t\tEgoClass (int x, int y, char *text, TextPrintType flags);\n\t\t~EgoClass ();\n\n\t\tbool Scroll (int distance);\n\t\tvoid Render (void);\n\t\tvoid Wipe (GraphicBufferClass *background);\n\n\n\t\tchar\t\t\t\t*Text;\n\t\tint\t\t\t\tXPos;\n\t\tint\t\t\t\tYPos;\n\t\tTextPrintType \tFlags;\n};\n\n\n"
  },
  {
    "path": "REDALERT/ENDING.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ENDING.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ENDING.H                                                     *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : July 10, 1995                                                *\n *                                                                                             *\n *                  Last Update : July 10, 1995 [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nvoid GDI_Ending(void)\n{\n#ifdef NEVER\n\tif (TempleIoned) {\n\t\tPlay_Movie(\"GDIFINB\");\n\t} else {\n\t\tPlay_Movie(\"GDIFINA\");\n\t}\n\n\tScore.Presentation();\n\n\tif (TempleIoned) {\n\t\tPlay_Movie(\"GDIEND2\");\n\t} else {\n\t\tPlay_Movie(\"GDIEND1\");\n\t}\n\tPlay_Movie(\"CC2TEASE\");\n#endif\n}\n\n\n/***********************************************************************************************\n * Nod_Ending -- play ending movies for Nod players                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   7/10/1995 BWG : Created.                                                                  *\n *=============================================================================================*/\nvoid Nod_Ending(void)\n{\n#ifdef NEVER\n\tstatic char const _tanpal[]={0x0,0x0,0xED,0x0,0x2C,0x0,0xFB,0x0,0xFD,0x0,0x0,0x0,0x0,0x0,0x52,0x0};\n\n\tchar fname[12];\n\tchar * satpic = new char[64000];\n\tint oldfontxspacing = FontXSpacing;\n\tvoid const * oldfont;\n\n\tScore.Presentation();\n\n\toldfont = Set_Font(ScoreFontPtr);\n\n\tvoid * localpal = Load_Alloc_Data(CCFileClass(\"SATSEL.PAL\"));\n\tLoad_Uncompress(CCFileClass(\"SATSEL.CPS\"), HidPage, HidPage);\n\tmemcpy(satpic, HidPage.Get_Buffer(), 64000);\n\n\tvoid * kanefinl = Load_Sample(\"KANEFINL.AUD\");\n\tvoid * loopie6m = Load_Sample(\"LOOPIE6M.AUD\");\n\n\tPlay_Movie(\"NODFINAL\", THEME_NONE, false);\n\n\tHide_Mouse();\n\tWait_Vert_Blank(VertBlank);\n\tSet_Palette(localpal);\n\tmemcpy(SeenBuff.Get_Buffer(), satpic, 64000);\n\tShow_Mouse();\n\n\tKeyboard->Clear();\n\tPlay_Sample(kanefinl, 255, 128);\n\tPlay_Sample(loopie6m, 255, 128);\n\n\tbool mouseshown = false;\n\tbool done = false;\n\tint selection = 1;\n\tbool printedtext = false;\n\twhile (!done) {\n\t\tif (!printedtext && !Is_Sample_Playing(kanefinl)) {\n\t\t\tprintedtext++;\n\t\t\tAlloc_Object(new ScorePrintClass(Text_String(TXT_SEL_TARGET), 0, 180, _tanpal));\n\t\t\tmouseshown = true;\n\t\t\tShow_Mouse();\n\t\t}\n\t\tCall_Back_Delay(1);\n\t\tif (!Keyboard->Check()) {\n\t\t\tif (!Is_Sample_Playing(loopie6m))\tPlay_Sample(loopie6m, 255, 128);\n\t\t} else {\n\t\t\tif (Is_Sample_Playing(kanefinl)) {\n\t\t\t\tClear_KeyBuffer();\n\t\t\t} else {\n\t\t\t\tint key = Keyboard->Get();\n\t\t\t\tif ((key & 0xFF) == KN_LMOUSE && !(key & KN_RLSE_BIT)) {\n\t\t\t\t\tint mousex = MouseQX;\n\t\t\t\t\tint mousey = MouseQY;\n\t\t\t\t\tif (mousey >= 22 && mousey <= 177) {\n\t\t\t\t\t\tdone++;\n\t\t\t\t\t\tif (mousex <  160 && mousey <  100) selection = 2;\n\t\t\t\t\t\tif (mousex <  160 && mousey >= 100) selection = 3;\n\t\t\t\t\t\tif (mousex >= 160 && mousey >= 100) selection = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (mouseshown) Hide_Mouse();\n\tdelete satpic;\n\n/* get rid of all the animating objects */\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\t// erase the \"choose a target\" text\n\tSeenBuff.Fill_Rect(0, 180, 319, 199, 0);\n\n\tHide_Mouse();\n\tKeyboard->Clear();\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tFree_Sample(kanefinl);\n\tFree_Sample(loopie6m);\n\n\tsprintf(fname, \"NODEND%d\", selection);\n\tPreserveVQAScreen = 1;\n\tPlay_Movie(fname);\n\n\tPlay_Movie(\"CC2TEASE\");\n#endif\n}\n"
  },
  {
    "path": "REDALERT/ENDING.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ENDING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ENDING.H                                                     *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : July 10, 1995                                                *\n *                                                                                             *\n *                  Last Update : July 10, 1995 [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef ENDING_H\n#define ENDING_H\n\nvoid Nod_Ending(void);\n\n#endif\n"
  },
  {
    "path": "REDALERT/EVENT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/EVENT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EVENT.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/09/94                                                     *\n *                                                                                             *\n *                  Last Update : November 10, 1995 [BRR]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EventClass::EventClass -- Construct an id and cell based event.                           *\n *   EventClass::EventClass -- Construct simple target type event.                             *\n *   EventClass::EventClass -- Constructor for mission change events.                          *\n *   EventClass::EventClass -- Constructor for navigation computer events.                     *\n *   EventClass::EventClass -- Constructor for object types affecting cells event.             *\n *   EventClass::EventClass -- Constructor for sidebar build events.                           *\n *   EventClass::EventClass -- Constructs event to transfer special flags.                     *\n *   EventClass::EventClass -- Default constructor for event objects.                          *\n *   EventClass::EventClass -- Event for sequencing animations.                                *\n *   EventClass::EventClass -- Megamission assigned to unit.                                   *\n *   EventClass::Execute -- Execute a queued command.                                          *\n *   EventClass::EventClass -- construct a variable-sized event                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef WIN32\n#include \"ccdde.h\"\n#endif\t//WIN32\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\n/***************************************************************************\n** Table of what data is really used in the EventClass struct for different\n** events.  This table must be kept current with the EventType enum.\n*/\nunsigned char EventClass::EventLength[EventClass::LAST_EVENT] = {\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// EMPTY\n\tsize_of(EventClass, Data.General ),\t\t\t\t// ALLY\n\tsize_of(EventClass, Data.MegaMission ),\t\t// MEGAMISSION\n\tsize_of(EventClass, Data.MegaMission_F ),\t\t// MEGAMISSION_F\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// IDLE\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// SCATTER\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// DESTRUCT\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// DEPLOY\n\tsize_of(EventClass, Data.Place ),\t\t\t\t// PLACE\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// OPTIONS\n\tsize_of(EventClass, Data.General ),\t\t\t\t// GAMESPEED\n\tsize_of(EventClass, Data.Specific ),\t\t\t// PRODUCE\n\tsize_of(EventClass, Data.Specific.Type ),\t\t// SUSPEND\n\tsize_of(EventClass, Data.Specific.Type ),\t\t// ABANDON\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// PRIMARY\n\tsize_of(EventClass, Data.Special ),\t\t\t\t// SPECIAL_PLACE\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// EXIT\n\tsize_of(EventClass, Data.Anim ),\t\t\t\t\t// ANIMATION\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// REPAIR\n\tsize_of(EventClass, Data.Target ),\t\t\t\t// SELL\n\tsize_of(EventClass, Data.SellCell),\t\t\t\t// SELLCELL\n\tsize_of(EventClass, Data.Options ),\t\t\t\t// SPECIAL\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// FRAMESYNC\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tMESSAGE\n\tsize_of(EventClass, Data.FrameInfo.Delay ),\t// RESPONSE_TIME\n\tsize_of(EventClass, Data.FrameInfo ),\t\t\t// FRAMEINFO\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tSAVEGAME\n\tsize_of(EventClass, Data.NavCom ),\t\t\t\t// ARCHIVE\n\tsize_of(EventClass, Data.Variable.Size),\t\t// ADDPLAYER\n\tsize_of(EventClass, Data.Timing ),\t\t\t\t// TIMING\n\tsize_of(EventClass, Data.ProcessTime ),\t\t// PROCESS_TIME\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t//\tPROPOSE_DRAW\n\t0,\t\t\t\t\t\t\t\t\t\t\t\t//\tRETRACT_DRAW\n#endif\n};\n\nchar * EventClass::EventNames[EventClass::LAST_EVENT] = {\n\t\"EMPTY\",\n\t\"ALLY\",\n\t\"MEGAMISSION\",\n\t\"MEGAMISSION_F\",\n\t\"IDLE\",\n\t\"SCATTER\",\n\t\"DESTRUCT\",\n\t\"DEPLOY\",\n\t\"PLACE\",\n\t\"OPTIONS\",\n\t\"GAMESPEED\",\n\t\"PRODUCE\",\n\t\"SUSPEND\",\n\t\"ABANDON\",\n\t\"PRIMARY\",\n\t\"SPECIAL_PLACE\",\n\t\"EXIT\",\n\t\"ANIMATION\",\n\t\"REPAIR\",\n\t\"SELL\",\n\t\"SELLCELL\",\n\t\"SPECIAL\",\n\t\"FRAMESYNC\",\n\t\"MESSAGE\",\n\t\"RESPONSE_TIME\",\n\t\"FRAMEINFO\",\n\t\"SAVEGAME\",\n\t\"ARCHIVE\",\n\t\"ADDPLAYER\",\n\t\"TIMING\",\n\t\"PROCESS_TIME\",\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\"PROPOSE_DRAW\",\n\t\"RETRACT_DRAW\",\n#endif\n};\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructs event to transfer special flags.                       *\n *                                                                                             *\n *    This constructs an event that will transfer the special flags.                           *\n *                                                                                             *\n * INPUT:   data  -- The special flags to be transported to all linked computers.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(SpecialClass data)\n{\n\tID = PlayerPtr->ID;\n\tType = SPECIAL;\n\tFrame = ::Frame;\n\tData.Options.Data = data;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Construct simple target type event.                               *\n *                                                                                             *\n *    This will construct a generic event that needs only a target parameter. The actual       *\n *    event and target values are specified as parameters.                                     *\n *                                                                                             *\n * INPUT:   type  -- The event type to construct.                                              *\n *                                                                                             *\n *          target-- The target value that this event is to apply to.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, TargetClass target)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Target.Whom = target;\n}\n\n\nEventClass::EventClass(EventType type, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.SellCell.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Default constructor for event objects.                            *\n *                                                                                             *\n *    This constructs a simple event object that requires no parameters other than the         *\n *    type of event it is.                                                                     *\n *                                                                                             *\n * INPUT:   type  -- The type of event to construct.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for general-purpose-data events.                      *\n *                                                                                             *\n * INPUT:   type  -- The type of event to construct.                                           *\n *            val   -- data value                                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, int val)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tData.General.Value = val;\n\tFrame = ::Frame;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for navigation computer events.                       *\n *                                                                                             *\n *    Constructor for events that are used to assign the navigation computer.                  *\n *                                                                                             *\n * INPUT:   type     -- The type of event (this constructor can be used by other navigation    *\n *                      type events).                                                          *\n *                                                                                             *\n *          src      -- The object that the event should apply to.                             *\n *                                                                                             *\n *          dest     -- The destination (or target) that the event needs to complete.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, TargetClass src, TargetClass dest)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.NavCom.Whom = src;\n\tData.NavCom.Where = TargetClass(dest);\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Event for sequencing animations.                                  *\n *                                                                                             *\n *    This constructor is used for animations that must be created through the event system.   *\n *                                                                                             *\n * INPUT:   anim  -- The animation that will be created.                                       *\n *                                                                                             *\n *          coord -- The location where the animation is to be created.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(AnimType anim, HousesType owner, COORDINATE coord, int visible)\n{\n\tID = PlayerPtr->ID;\n\tType = ANIMATION;\n\tFrame = ::Frame;\n\tData.Anim.What = anim;\n\tData.Anim.Owner = owner;\n\tData.Anim.Where = coord;\n\tData.Anim.Visible = visible;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Megamission assigned to unit.                                     *\n *                                                                                             *\n *    This is the event that is used to assign most missions to units. It combines both the    *\n *    mission and the target (navcom and tarcom).                                              *\n *                                                                                             *\n * INPUT:   src      -- The object that this mission is to apply to.                           *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target to assign to this object's TarCom.                          *\n *                                                                                             *\n *          destination -- The destination to assign to this object's NavCom.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination)\n{\n\tID = PlayerPtr->ID;\n\tType = MEGAMISSION;\n\tFrame = ::Frame;\n\tData.MegaMission.Whom = src;\n\tData.MegaMission.Mission = mission;\n\tData.MegaMission.Target = target;\n\tData.MegaMission.Destination = destination;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Megamission assigned to unit.                                     *\n *                                                                                             *\n *    This is the event that is used to assign most missions to units. It combines both the    *\n *    mission and the target (navcom and tarcom).  This variation is used for formation moves. *\n *                                                                                             *\n * INPUT:   src      -- The object that this mission is to apply to.                           *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target to assign to this object's TarCom.                          *\n *                                                                                             *\n *          destination -- The destination to assign to this object's NavCom.                  *\n *                                                                                             *\n *          speed    -- The formation override speed for this move.                            *\n *                                                                                             *\n *          maxspeed -- The formation override maximum speed for this move.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination, SpeedType speed, MPHType maxspeed)\n{\n\tID = PlayerPtr->ID;\n\tType = MEGAMISSION_F;\n\tFrame = ::Frame;\n\tData.MegaMission_F.Whom = src;\n\tData.MegaMission_F.Mission = mission;\n\tData.MegaMission_F.Target = TargetClass(target);\n\tData.MegaMission_F.Destination = TargetClass(destination);\n\tData.MegaMission_F.Speed = speed;\n\tData.MegaMission_F.MaxSpeed = maxspeed;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for sidebar build events.                             *\n *                                                                                             *\n *    This constructor is used for events that deal with an object type and an object ID.      *\n *    Typically, this is used exclusively by the sidebar.                                      *\n *                                                                                             *\n * INPUT:   type     -- The event type of this object.                                         *\n *                                                                                             *\n *          object   -- The object type number.                                                *\n *                                                                                             *\n *          id       -- The object sub-type number.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, RTTIType object, int id)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Specific.Type = object;\n\tData.Specific.ID = id;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Constructor for object types affecting cells event.               *\n *                                                                                             *\n *    This constructor is used for those events that have an object type and associated cell.  *\n *    Typically, this is for building placement after construction has completed.              *\n *                                                                                             *\n * INPUT:   type     -- The event type for this object.                                        *\n *                                                                                             *\n *          object   -- The object type number (actual object is probably inferred from the    *\n *                      sidebar data).                                                         *\n *                                                                                             *\n *          cell     -- The cell location where this event is to occur.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, RTTIType object, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Place.Type = object;\n\tData.Place.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- Construct an id and cell based event.                             *\n *                                                                                             *\n *    This constructor is used for those events that require an ID number and a cell location. *\n *                                                                                             *\n * INPUT:   type  -- The event type this will be.                                              *\n *                                                                                             *\n *          id    -- The arbitrary id number to assign.                                        *\n *                                                                                             *\n *          cell  -- The location for this event.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, int id, CELL cell)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Special.ID \t= id;\n\tData.Special.Cell = cell;\n}\n\n\n/***********************************************************************************************\n * EventClass::EventClass -- construct a variable-sized event                                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tptr\t\tptr to data associated with this event\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nEventClass::EventClass(EventType type, void * ptr, unsigned long size)\n{\n\tID = PlayerPtr->ID;\n\tType = type;\n\tFrame = ::Frame;\n\tData.Variable.Pointer = ptr;\n\tData.Variable.Size = size;\n}\n\n\n/***********************************************************************************************\n * EventClass::Execute -- Execute a queued command.                                            *\n *                                                                                             *\n *    This routine executes an event. The even must already have been confirmed by any         *\n *    remote machine before calling this routine.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EventClass::Execute(void)\n{\n\tTechnoClass * techno;\n\tAnimClass * anim = 0;\n\tHouseClass * house = 0;\n//\tCELL cell = 0;\n\tchar txt[80];\n\tbool formation = false;\n//\tRTTIType rt;\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"(%d) Executing %s ID:%d Frame:%d \",\n\t\t\t::Frame, EventNames[Type], ID, Frame);\n\t}\n\n\tswitch (Type) {\n\n\t\t/*\n\t\t**\tUpdate the archive target for this building.\n\t\t*/\n\t\tcase ARCHIVE:\n\t\t\ttechno = Data.NavCom.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive) {\n\t\t\t\ttechno->ArchiveTarget = Data.NavCom.Where.As_TARGET();\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMake or break alliance.\n\t\t*/\n\t\tcase ALLY:\n\t\t\thouse = Houses.Raw_Ptr(Data.General.Value);\n\t\t\tif (Houses.Raw_Ptr(ID)->Is_Ally(house)) {\n\t\t\t\tHouses.Raw_Ptr(ID)->Make_Enemy((HousesType)Data.General.Value);\n\t\t\t} else {\n\t\t\t\tHouses.Raw_Ptr(ID)->Make_Ally((HousesType)Data.General.Value);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSpecial self destruct action requested. This is active in the multiplayer mode.\n\t\t*/\n\t\tcase DESTRUCT:\n\t\t\tHouses.Raw_Ptr(ID)->Flag_To_Die();\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tUpdate the special control flags. This is necessary so that in a multiplay\n\t\t**\tgame, all machines will agree on the rules. If these options change during\n\t\t**\tgame play, then all players are informed that options have changed.\n\t\t*/\n\t\tcase SPECIAL:\n\t\t\t{\n\t\t\t\tSpecial = Data.Options.Data;\n\t\t\t\tHouseClass * house = Houses.Raw_Ptr(ID);\n\n\t\t\t\t//sprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->Name);\t// Should be IniName? ST - 5/8/2019\n\t\t\t\tsprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->IniName);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt,\n\t\t\t\t\thouse->RemapColor,\n\t\t\t\t\tTPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1200);\n\t\t\t\tMap.Flag_To_Redraw(false);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tStarts or stops repair on the specified object. This event is triggered by the\n\t\t**\tplayer clicking the repair wrench on a building.\n\t\t*/\n\t\tcase REPAIR:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive) {\n\t\t\t\ttechno->Repair(-1);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTells a building/unit to sell. This event is triggered by the player clicking the\n\t\t**\tsell animating cursor over the building or unit.\n\t\t*/\n\t\tcase SELL:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive && techno->House == Houses.Raw_Ptr(ID)) {\n\t\t\t\tif (techno->What_Am_I() == RTTI_BUILDING || (techno->What_Am_I() == RTTI_UNIT && Map[techno->Center_Coord()].Cell_Building() != 0)) {\n\t\t\t\t\ttechno->Sell_Back(-1);\n\t\t\t\t}\n\t\t\t} else {\n//\t\t\t\tif (Is_Target_Cell(Data.Target.Whom)) {\n//\t\t\t\t\tHouses.Raw_Ptr(ID)->Sell_Wall(As_Cell(Data.Target.Whom));\n//\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTells the wall at the specified location to sell off.\n\t\t*/\n\t\tcase SELLCELL:\n//\t\t\tcell = Data.SellCell.Cell;\n\t\t\tHouses.Raw_Ptr(ID)->Sell_Wall(Data.SellCell.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis even is used to trigger an animation that is generated as a direct\n\t\t**\tresult of player intervention.\n\t\t*/\n\t\tcase ANIMATION:\n\t\t\tanim = new AnimClass(Data.Anim.What, Data.Anim.Where);\n\t\t\tif (anim) {\n\t\t\t\tanim->Set_Owner(Data.Anim.Owner);\n\t\t\t\tanim->Set_Visible_Flags(static_cast<unsigned int>(Data.Anim.Visible));\n\t\t\t\t/*\n\t\t\t\t**\tBeacons have a 30-second kill time.\n\t\t\t\t*/\n\t\t\t\tif (Data.Anim.What == ANIM_BEACON) {\n\t\t\t\t\tFILETIME ft;\n\t\t\t\t\tGetSystemTimeAsFileTime(&ft);\n\n\t\t\t\t\tunsigned long long kill_time = ((unsigned long long)ft.dwLowDateTime + ((unsigned long long)ft.dwHighDateTime << 32ULL)) + 300000000ULL;\n\t\t\t\t\tanim->Kill_At(kill_time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event will place the specified object at the specified location.\n\t\t**\tThe event is used to place newly constructed buildings down on the map. The\n\t\t**\tobject type is specified. From this object type, the house can determine the\n\t\t**\texact factory and real object pointer to use.\n\t\t*/\n\t\tcase PLACE:\n\t\t\tHouses.Raw_Ptr(ID)->Place_Object(Data.Place.Type, Data.Place.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event starts production of the specified object type. The house can\n\t\t**\tdetermine from the type and ID value, what object to begin production on and\n\t\t**\twhat factory to use.\n\t\t*/\n\t\tcase PRODUCE:\n\t\t\tHouses.Raw_Ptr(ID)->Begin_Production(Data.Specific.Type, Data.Specific.ID);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event is generated when the player puts production on hold. From the\n\t\t**\tobject type, the factory can be inferred.\n\t\t*/\n\t\tcase SUSPEND:\n\t\t\tHouses.Raw_Ptr(ID)->Suspend_Production(Data.Specific.Type);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis event is generated when the player cancels production of the specified\n\t\t**\tobject type. From the object type, the exact factory can be inferred.\n\t\t*/\n\t\tcase ABANDON:\n\t\t\tHouses.Raw_Ptr(ID)->Abandon_Production(Data.Specific.Type);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tToggles the primary factory state of the specified building.\n\t\t*/\n\t\tcase PRIMARY:\n\t\t\t{\n\t\t\t\tBuildingClass * building = Data.Target.Whom.As_Building();\n\t\t\t\tif (building && building->IsActive) {\n\t\t\t\t\tbuilding->Toggle_Primary();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThis is the general purpose mission control event. Most player\n\t\t**\taction routes through this event. It sets a unit's mission, TarCom,\n\t\t**\tand NavCom to the values specified.\n\t\t*/\n\t\tcase MEGAMISSION_F:\n\t\t\ttechno = Data.MegaMission_F.Whom.As_Techno();\n\t\t\tif (techno && techno->IsActive && techno->Is_Foot()) {\n\t\t\t\t((FootClass *)techno)->IsFormationMove = true;\n\t\t\t\t((FootClass *)techno)->FormationSpeed = Data.MegaMission_F.Speed;\n\t\t\t\t((FootClass *)techno)->FormationMaxSpeed = Data.MegaMission_F.MaxSpeed;\n\t\t\t\tFormMove = true;\n\t\t\t\tFormSpeed = Data.MegaMission_F.Speed;\n\t\t\t\tFormMaxSpeed = Data.MegaMission_F.MaxSpeed;\n\t\t\t\tformation = true;\n\t\t\t}\n\t\t\t// Fall thru to next case...\n\n\t\tcase MEGAMISSION:\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"Whom:%x Tgt:%x Dest:%x \",\n\t\t\t\t\tData.MegaMission.Whom.As_TARGET(),\n\t\t\t\t\tData.MegaMission.Target.As_TARGET(),\n\t\t\t\t\tData.MegaMission.Destination.As_TARGET());\n\t\t\t}\n\t\t\ttechno = Data.MegaMission.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->IsActive && techno->Strength > 0 && !techno->IsInLimbo) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFetch a pointer to the object of the mission. If there is an error with\n\t\t\t\t**\tthis object, such as it is dead, then bail.\n\t\t\t\t*/\n\t\t\t\tObjectClass * object = NULL;\n\t\t\t\tif (Data.MegaMission.Target.Is_Valid()) {\n\t\t\t\t\tobject = Data.MegaMission.Target.As_Object();\n\t\t\t\t\tif (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {\n\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\tobject = NULL;\n//\t\t\t\t\t\tData.MegaMission.Target.Invalidate();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the destination target is invalid because the object is dead, then\n\t\t\t\t**\tbail from processing this mega mission.\n\t\t\t\t*/\n\t\t\t\tif (Data.MegaMission.Destination.Is_Valid()) {\n\t\t\t\t\tobject = Data.MegaMission.Destination.As_Object();\n\t\t\t\t\tif (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {\n\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\tobject = NULL;\n//\t\t\t\t\t\tData.MegaMission.Destination.Invalidate();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tBreak any existing tether or team contact, since it is now invalid.\n\t\t\t\t*/\n\t\t\t\tif (!techno->IsTethered) {\n\t\t\t\t\ttechno->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\tif (!formation) ((FootClass *)techno)->IsFormationMove = false;\n\t\t\t\t\tif (((FootClass *)techno)->Team) {\n\t\t\t\t\t\t((FootClass *)techno)->Team->Remove((FootClass *)techno);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (object != NULL) {\n\n\t\t\t\t\t// 2019/09/20 JAS - Added record of who clicked on the object\n\t\t\t\t\tHouseClass* house = Houses.Raw_Ptr(ID);\n\t\t\t\t\tbool is_allied = house != nullptr && house->Is_Ally(techno);\n\t\t\t\t\tif (is_allied) {\n\t\t\t\t\t\tobject->Clicked_As_Target((HousesType)ID);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTest to see if the navigation target should really be queued rather\n\t\t\t\t**\tthan assigned to the object. This would be the case if this is a\n\t\t\t\t**\tspecial queued move mission and there is already a valid navigation\n\t\t\t\t**\ttarget for this unit.\n\t\t\t\t*/\n\t\t\t\tbool q = (Data.MegaMission.Mission == MISSION_QMOVE);\n\n\t\t\t\ttechno->Assign_Mission(Data.MegaMission.Mission);\n\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t((FootClass*)techno)->SuspendedNavCom = TARGET_NONE;\n\t\t\t\t}\n\t\t\t\ttechno->SuspendedTarCom = TARGET_NONE;\n\n\t\t\t\t/*\n\t\t\t\t**\tGuard area mode is handled with care. The specified target is actually\n\t\t\t\t**\tassigned as the location that should be guarded. In addition, the\n\t\t\t\t**\tmovement destination is immediately set to this new location.\n\t\t\t\t*/\n\t\t\t\tif (Data.MegaMission.Mission == MISSION_GUARD_AREA && techno->Is_Foot()) {\n\t\t\t\t\ttechno->Assign_Target(TARGET_NONE);\n\t\t\t\t\ttechno->Assign_Destination(Data.MegaMission.Target.As_TARGET());\n\t\t\t\t\ttechno->ArchiveTarget = Data.MegaMission.Target.As_TARGET();\n\t\t\t\t} else if (Data.MegaMission.Mission == MISSION_ENTER &&\n\t\t\t\t\t\t\tobject != NULL &&\n\t\t\t\t\t\t\tobject->What_Am_I() == RTTI_BUILDING &&\n\t\t\t\t\t\t\t*((BuildingClass*)object) == STRUCT_REFINERY) {\n\t\t\t\t\ttechno->Transmit_Message(RADIO_HELLO, (BuildingClass*)object);\n\t\t\t\t\ttechno->Assign_Destination(TARGET_NONE);\n\t\t\t\t} else {\n\t\t\t\t\tif (q && techno->Is_Foot()) {\n\t\t\t\t\t\t((FootClass *)techno)->Queue_Navigation_List(Data.MegaMission.Destination.As_TARGET());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t\t\t((FootClass *)techno)->Clear_Navigation_List();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttechno->Assign_Target(Data.MegaMission.Target.As_TARGET());\n\t\t\t\t\t\ttechno->Assign_Destination(Data.MegaMission.Destination.As_TARGET());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Special case for ship repairing: If the assigned mission is to\n\t\t\t\t// move, and 'techno' is a Vessel:\n\t\t\t\t//   If the destination is a shipyard or sub pen, set the IsToSelfRepair flag\n\t\t\t\t//   Otherwise, clear both IsToSelfRepair and IsSelfRepairing\n\t\t\t\t//\n\t\t\t\tRTTIType rt = techno->What_Am_I();\n//\t\t\t\trt = Data.MegaMission.Whom;\n\t\t\t\tif (rt == RTTI_VESSEL && techno != NULL && techno->What_Am_I() == RTTI_VESSEL) {\n\t\t\t\t\tVesselClass *ship = (VesselClass *)techno;\n\t\t\t\t\tif (Data.MegaMission.Mission == MISSION_MOVE) {\n\t\t\t\t\t\tif (object != NULL) {\n\t\t\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING &&\n\t\t\t\t\t\t\t\t((BuildingClass *)object)->House->Is_Ally(techno) &&\n//\t\t\t\t\t\t\tif ((RTTIType)Data.MegaMission.Destination == RTTI_BUILDING &&\n\t\t\t\t\t\t\t\t(((BuildingClass *)object)->Class->Type == STRUCT_SHIP_YARD ||\n\t\t\t\t\t\t\t\t((BuildingClass *)object)->Class->Type == STRUCT_SUB_PEN)) {\n\t\t\t\t\t\t\t\tship->IsToSelfRepair = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tship->IsToSelfRepair = false;\n\t\t\t\t\t\t\t\tship->IsSelfRepairing = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tship->IsToSelfRepair = false;\n\t\t\t\t\t\t\tship->IsSelfRepairing = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tship->IsToSelfRepair = false;\n\t\t\t\t\t\tship->IsSelfRepairing = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n#ifdef NEVER\n\t\t\t\tif ((techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_INFANTRY) &&\n\t\t\t\t\t\tData.MegaMission.Mission == MISSION_GUARD_AREA) {\n\n\t\t\t\t\t((FootClass *)techno)->ArchiveTarget = Data.MegaMission.Destination;\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRequest that the unit/infantry/aircraft go into idle mode.\n\t\t*/\n\t\tcase IDLE:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered && techno->What_Am_I() != RTTI_BUILDING) {\n\t\t\t\ttechno->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\ttechno->Assign_Destination(TARGET_NONE);\n\t\t\t\ttechno->Assign_Target(TARGET_NONE);\n\t\t\t\ttechno->Enter_Idle_Mode();\n\t\t\t\tif (techno->Is_Foot()) {\n\t\t\t\t\t((FootClass *)techno)->Clear_Navigation_List();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRequest that the unit/infantry/aircraft scatter from its current location.\n\t\t*/\n\t\tcase SCATTER:\n\t\t\ttechno = Data.Target.Whom.As_Techno();\n\t\t\tif (techno != NULL && techno->Is_Foot() && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {\n\t\t\t\t((FootClass *)techno)->IsScattering = true;\n\t\t\t\ttechno->Scatter(0, true, false);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf we are placing down the ion cannon blast then lets take\n\t\t** care of it.\n\t\t*/\n\t\tcase SPECIAL_PLACE:\n\t\t\tHouses.Raw_Ptr(ID)->Place_Special_Blast((SpecialWeaponType)Data.Special.ID, Data.Special.Cell);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tExit the game.\n\t\t** Give parting message while palette is fading to black.\n\t\t*/\n\t\tcase EXIT:\n\t\t\tTheme.Queue_Song(THEME_NONE);\n\t\t\tStop_Speaking();\n\t\t\tSpeak(VOX_CONTROL_EXIT);\n\t\t\twhile (Is_Speaking()) {\n\t\t\t\tCall_Back();\n\t\t\t}\n\t\t\tGameActive = false;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tProcess the options menu, unless we're playing back a recording.\n\t\t*/\n\t\tcase OPTIONS:\n\t\t\tif (!Session.Play) {\n\t\t\t\tSpecialDialog = SDLG_OPTIONS;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tProcess the options Game Speed\n\t\t*/\n\t\tcase GAMESPEED:\n\t\t\tOptions.GameSpeed = Data.General.Value;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tAdjust connection timing for multiplayer games\n\t\t*/\n\t\tcase RESPONSE_TIME:\n\t\t\tSession.MaxAhead = Data.FrameInfo.Delay;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSave a multiplayer game (this event is only generated in multiplayer mode)\n\t\t*/\n\t\tcase SAVEGAME:\n\t\t\t/*\n\t\t\t** Show the user what's going on with a message box (but only if\n\t\t\t** we're not already inside a dialog box routine!)\n\t\t\t*/\n\t\t\tif (SpecialDialog == SDLG_NONE) {\n\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n\t\t\t\t//timer.Start();\n\t\t\t\ttimer = TICKS_PER_SECOND * 4;\n\n\t\t\t\tWWMessageBox().Process(TXT_SAVING_GAME, TXT_NONE);\n\n\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\n\t\t\t\twhile (timer > 0) {\n\t\t\t\t\tCall_Back();\n\t\t\t\t}\n\n\t\t\t\tHidPage.Clear();\n\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\tMap.Render();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Add a new player to the game:\n\t\t** - Form a network connection to him\n\t\t** - Add his name, ID, House etc to our list of players\n\t\t** - Re-sort the ID array\n\t\t** - Place his units on the map\n\t\t*/\n\t\tcase ADDPLAYER:\n\t\t\tint i;\n\t\t\tprintf(\"ADDPLAYER EVENT!\\n\");\n\t\t\tfor (i=0;i<(int)Data.Variable.Size;i++) {\n\t\t\t\tprintf(\"%d\\n\", ((char *)Data.Variable.Pointer)[i]);\n\t\t\t}\n\t\t\tif (ID != PlayerPtr->ID) {\n\t\t\t\tdelete [] Data.Variable.Pointer;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t//\n\t\t// This event tells all systems to use new timing values.  It's like\n\t\t// RESPONSE_TIME, only it works.  It's only used with the\n\t\t// COMM_MULTI_E_COMP protocol.\n\t\t//\n\t\tcase TIMING:\n#if(TIMING_FIX)\n\t\t\t//\n\t\t\t// If MaxAhead is about to increase, we're vulnerable to a Packet-\n\t\t\t// Received-Too-Late error, if any system generates an event after\n\t\t\t// this TIMING event, but before it executes.  So, record the\n\t\t\t// period of vulnerability's frame start & end values, so we\n\t\t\t// can reschedule these events to execute after it's over.\n\t\t\t//\n\t\t\tif (Data.Timing.MaxAhead > Session.MaxAhead) {\n\t\t\t\tNewMaxAheadFrame1 = Frame;\n\t\t\t\tNewMaxAheadFrame2 = Frame + Data.Timing.MaxAhead;\n\t\t\t}\n#endif\n\t\t\tSession.DesiredFrameRate = Data.Timing.DesiredFrameRate;\n\t\t\tSession.MaxAhead = Data.Timing.MaxAhead;\n\n#ifndef WOLAPI_INTEGRATION\n\t\t\t/*\n\t\t\t** If spawned from WChat then we should be getting poked every minute. If not then\n\t\t\t** deliberately break the max ahead value\n\t\t\t*/\n#ifdef WIN32\n\t\t\tif (Special.IsFromWChat) {\n\t\t\t\tSession.MaxAhead += DDEServer.Time_Since_Heartbeat()/(70*60);\n\t\t\t}\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"DesiredFrameRate:%d MaxAhead:%d \",\n\t\t\t\t\tSession.DesiredFrameRate,\n\t\t\t\t\tSession.MaxAhead);\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\t//\n\t\t// This event tells all systems what the other systems' process\n\t\t// timing requirements are; it's used to compute a desired frame rate\n\t\t// for the game.\n\t\t//\n\t\tcase PROCESS_TIME:\n\t\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\t\tif (ID == Session.Players[i]->Player.ID) {\n\t\t\t\t\tSession.Players[i]->Player.ProcessTime = Data.ProcessTime.AverageTicks;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tcase PROPOSE_DRAW:\n\t\t\tif( ID == PlayerPtr->ID )\n\t\t\t{\n\t\t\t\tif( Scen.bOtherProposesDraw )\n\t\t\t\t{\n\t\t\t\t\t//\tBoth sides agree to draw. Game will end in a tie.\n\t\t\t\t\tScen.bLocalProposesDraw = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tScen.bLocalProposesDraw = true;\n\t\t\t\t//PG Session.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_PROPOSED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t{\n\t\t\t\t\t//\tBoth sides agree to draw. Game will end in a tie.\n\t\t\t\t\tScen.bOtherProposesDraw = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchar szMessage[ 100 ];\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) \n\t\t\t\t{\n\t\t\t\t\tif (ID == Session.Players[i]->Player.ID) \n\t\t\t\t\t{\n\t\t\t\t\t\t//PG sprintf( szMessage, TXT_WOL_DRAW_PROPOSED_OTHER, Session.Players[i]->Name );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tScen.bOtherProposesDraw = true;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\tbreak;\n\n\t\tcase RETRACT_DRAW:\n\t\t\tif( ID == PlayerPtr->ID )\n\t\t\t{\n\t\t\t\tScen.bLocalProposesDraw = false;\n\t\t\t\t//PG Session.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_RETRACTED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchar szMessage[ 100 ];\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) \n\t\t\t\t{\n\t\t\t\t\tif (ID == Session.Players[i]->Player.ID) \n\t\t\t\t\t{\n\t\t\t\t\t\t//PG sprintf( szMessage, TXT_WOL_DRAW_RETRACTED_OTHER, Session.Players[i]->Name );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tScen.bOtherProposesDraw = false;\n\t\t\t\tSession.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\t\t}\n\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\tbreak;\n#endif\n\n\t\t/*\n\t\t**\tDefault: do nothing.\n\t\t*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n\");\n\t}\n\n}\n"
  },
  {
    "path": "REDALERT/EVENT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/EVENT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EVENT.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/09/94                                                     *\n *                                                                                             *\n *                  Last Update : December 9, 1994 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EVENT_H\n#define EVENT_H\n\n/*\n**\tThis event class is used to contain all external game events (things that the player can\n**\tdo at any time) so that these events can be transported between linked computers. This\n**\tencapsulation is required in order to ensure that each event affects all computers at the\n**\tsame time (same game frame).\n** NOTE: If you add or remove an event type, you must also update the globals\n** EventLength[] and EventNames[].\n*/\nclass EventClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tAll external events are identified by these labels.\n\t\t*/\n\t\ttypedef enum EventType : unsigned char\t{\n\t\t\tEMPTY,\n\n\t\t\tALLY,\t\t\t\t\t// Make allie of specified house.\n\t\t\tMEGAMISSION,\t\t// Full change of mission with target and destination.\n\t\t\tMEGAMISSION_F,\t\t// Full change of mission with target and destination, and formation overrides.\n\t\t\tIDLE,\t\t\t\t\t// Request to enter idle mode.\n\t\t\tSCATTER,\t\t\t\t// Request to scatter from current location.\n\t\t\tDESTRUCT,\t\t\t// Self destruct request (surrender action).\n\t\t\tDEPLOY,\t\t\t\t// MCV is to deploy at current location.\n\t\t\tPLACE,\t\t\t\t// Place building at location specified.\n\t\t\tOPTIONS,\t\t\t\t// Bring up options screen.\n\t\t\tGAMESPEED,\t\t\t// Set game speed\n\t\t\tPRODUCE,\t\t\t\t// Start or Resume production.\n\t\t\tSUSPEND,\t\t\t\t// Suspend production.\n\t\t\tABANDON,\t\t\t\t// Abandon production.\n\t\t\tPRIMARY,\t\t\t\t// Primary factory selected.\n\t\t\tSPECIAL_PLACE,\t\t// Special target location selected\n\t\t\tEXIT,\t\t\t\t\t// Exit game.\n\t\t\tANIMATION,\t\t\t// Flash ground as movement feedback.\n\t\t\tREPAIR,\t\t\t\t// Repair specified object.\n\t\t\tSELL,\t\t\t\t\t//\tSell specified object.\n\t\t\tSELLCELL,\t\t\t// Sell wall at specified cell.\n\t\t\tSPECIAL,\t\t\t\t// Special options control.\n\n\t\t\t// Private events.\n\t\t\tFRAMESYNC,\t\t\t// Game-connection packet; includes Scenario CRC & sender's frame #\n\t\t\t\t\t\t\t\t\t// Used to initiate game connection phase & to reconnect;\n\t\t\t\t\t\t\t\t\t// When one of these is received, the receiver knows there are\n\t\t\t\t\t\t\t\t\t// no associated commands in this packet.\n\t\t\tMESSAGE,\t\t\t\t// Message to another player (The message is the 40 bytes\n\t\t\t\t\t\t\t\t\t// after the event class).\n\t\t\tRESPONSE_TIME,\t\t// use a new propagation delay value\n\t\t\tFRAMEINFO,\t\t\t// Game-heartbeat packet; includes Game CRC & command count\n\t\t\t\t\t\t\t\t\t// All packets sent for a frame are prefixed with one of these\n\t\t\tSAVEGAME,\t\t\t// allows multiplayer games to save\n\t\t\tARCHIVE,\t\t\t\t// Updates archive target on specified object.\n\t\t\tADDPLAYER,\t\t\t// Add a new player\n\n\t\t\tTIMING,\t\t\t\t// new timing values for all systems to use\n\t\t\tPROCESS_TIME,\t\t// a system's average processing time, in ticks per frame\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tPROPOSE_DRAW,\t\t//\tPlayers proposes that 2-player game be called a stalemate.\n\t\t\tRETRACT_DRAW,\t\t//\tPlayer retracts proposed draw offer.\n#endif\n\n\t\t\tLAST_EVENT,\t\t\t// one past the last event\n\t\t} EventType;\n\n\t\tEventType Type;\t\t// Type of queue command object.\n\n\t\t/*\n\t\t** 'Frame' is the frame that the command should execute on.\n\t\t** 27 bits gives over 25 days of playing time without wrapping,\n\t\t** at 30 frames per second, so it should be plenty!\n\t\t*/\n\t\tunsigned Frame : 26;\n\n\t\t/*\n\t\t** House index of the player originating this event\n\t\t*/\n\t\tunsigned ID : 5;\n\n\t\t/*\n\t\t** This bit tells us if we've already executed this event.\n\t\t*/\n\t\tunsigned IsExecuted: 1;\n\n\t\t/*\n\t\t**\tThis union contains the specific data that the event requires.\n\t\t*/\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tSpecialClass\tData;\t\t// The special option flags.\n\t\t\t} Options;\n\t\t\tstruct {\n\t\t\t\tCELL\t\t\tCell;\t\t\t// The cell to sell wall at.\n\t\t\t} SellCell;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// The object to apply the event to.\n\t\t\t} Target;\n\t\t\tstruct {\n\t\t\t\tAnimType\t\tWhat;\t\t\t// The animation to create.\n\t\t\t\tHousesType\tOwner;\t\t// The owner of the animation (when it matters).\n\t\t\t\tCOORDINATE\t\t\tWhere;\t\t// The location to place the animation.\n\t\t\t\tint\t\t\tVisible;\t// Who this animation is visible to.\n\t\t\t} Anim;\n\t\t\tstruct {\n\t\t\t\tint \t\t\tValue;\t\t// general-purpose data\n\t\t\t} General;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType\tMission;\t\t// What mission to apply.\n\t\t\t\txTargetClass\tTarget;\t\t// Target to assign.\n\t\t\t\txTargetClass\tDestination;// Destination to assign.\n\t\t\t} MegaMission;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType\tMission;\t\t// What mission to apply.\n\t\t\t\txTargetClass\tTarget;\t\t// Target to assign.\n\t\t\t\txTargetClass\tDestination;// Destination to assign.\n\t\t\t\tSpeedType\tSpeed;\t\t// Formation override speed.\n\t\t\t\tMPHType\t\tMaxSpeed;\t// Formation override maximum speed.\n\t\t\t} MegaMission_F;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply mission to.\n\t\t\t\tMissionType Mission;\t\t// What mission to apply.\n\t\t\t} Mission;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply movement change to.\n\t\t\t\txTargetClass\tWhere;\t\t// Where to set NavCom to.\n\t\t\t} NavCom;\n\t\t\tstruct {\n\t\t\t\txTargetClass\tWhom;\t\t\t// Whom to apply attack change to.\n\t\t\t\txTargetClass\tTarget;\t\t// What to set TarCom to.\n\t\t\t} TarCom;\n\t\t\tstruct {\n\t\t\t\tRTTIType\t\tType;\n\t\t\t\tint\t\t\tID;\n\t\t\t} Specific;\n\t\t\tstruct {\n\t\t\t\tRTTIType\t\tType;\n\t\t\t\tCELL\t\t\tCell;\n\t\t\t} Place;\n\t\t\tstruct {\n\t\t\t\tint\t\t\tID;\n\t\t\t\tCELL\t\t\tCell;\n\t\t\t} Special;\n\n\t\t\t/*\n\t\t\t** This structure is used for FRAMEINFO, FRAMESYNC, and RESPONSE_TIME\n\t\t\t** events; exactly one of these will be sent each frame, whether there's\n\t\t\t** data that frame or not.\n\t\t\t** CRC: the game CRC when this packet was generated; used to detect sync errors\n\t\t\t** CommandCount: # of commands the sender has sent; used to detect missed packets\n\t\t\t** Delay: sender's propagation delay value for this frame\n\t\t\t*/\n\t\t\tstruct {\n\t\t\t\tunsigned long CRC;\n\t\t\t\tunsigned short CommandCount;\t// # commands sent so far\n\t\t\t\tunsigned char Delay;\t\t\t\t// propagation delay used this frame\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// (Frame - Delay = sender's current frame #)\n\t\t\t} FrameInfo;\n\t\t\t/*\n\t\t\t** This structure is used for the special variable-length event.  This event\n\t\t\t** can be anything the application wants it to be.  Its purpose is to allow\n\t\t\t** relatively large amounts of data to be associated with the event, without\n\t\t\t** bloating the size of this union (and thus all other event types).\n\t\t\t*/\n\t\t\tstruct {\n\t\t\t\tvoid * Pointer;\n\t\t\t\tunsigned long Size;\n\t\t\t} Variable;\n\n\t\t\t//\n\t\t\t// This structure sets new timing values for all systems in a multiplayer\n\t\t\t// game.  This structure replaces the RESPONSE_TIME event for\n\t\t\t// the COMM_MULTI_E_COMP protocol.\n\t\t\t//\n\t\t\tstruct {\n\t\t\t\tunsigned short DesiredFrameRate;\n\t\t\t\tunsigned short MaxAhead;\n\t\t\t} Timing;\n\n\t\t\t//\n\t\t\t// This structure is transmitted by all systems, and is used to compute\n\t\t\t// the \"desired\" frame rate for the game.\n\t\t\t//\n\t\t\tstruct {\n\t\t\t\tunsigned short AverageTicks;\n\t\t\t} ProcessTime;\n\n\t\t} Data;\n\n\t\t//-------------- Constructors ---------------------\n\t\tEventClass(void) {Type = EMPTY;};\n\t\tEventClass(SpecialClass data);\n\t\tEventClass(EventType type, TargetClass target);\n\t\tEventClass(EventType type);\n\t\tEventClass(EventType type, int val);\n\t\tEventClass(EventType type, CELL cell);\n\t\tEventClass(EventType type, TargetClass src, TargetClass dest);\n\t\tEventClass(TargetClass src, MissionType mission, TargetClass target=TARGET_NONE, TargetClass destination=TARGET_NONE);\n\n\t\tEventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination, SpeedType speed, MPHType maxspeed);\n\n\t\tEventClass(EventType type, RTTIType object, int id);\n\t\tEventClass(EventType type, RTTIType object, CELL cell);\n\t\tEventClass(EventType type, int id, CELL cell);\n\t\tEventClass(AnimType anim, HousesType owner, COORDINATE coord, int visible = -1);\n\t\tEventClass(void *ptr, unsigned long size);\n\t\tEventClass(EventType type, void *ptr, unsigned long size);\n\n\t\t// Process the event.\n\t\tvoid Execute(void);\n\n\t\tint operator == (EventClass & q) {\n\t\t\treturn memcmp(this, &q, sizeof(q)) == 0;\n\t\t};\n\n\t\tstatic unsigned char EventLength[LAST_EVENT];\n\t\tstatic char * EventNames[LAST_EVENT];\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/EXPAND.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/EXPAND.CPP 7     3/17/97 1:05a Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EXPAND.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/03/95                                                     *\n *                                                                                             *\n *                  Last Update : Mar 01, 1997 [V.Grippi]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   EListClass::Draw_Entry -- Draws entry for expansion scenario.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef FIXIT_VERSION_3\n#include \"WolStrng.h\"\n#endif\n\n//#define CS_DEBUG\n\n#define ARRAYOFFSET 20\n\n\n/***********************************************************************************************\n * Expansion_CS_Present -- Is the Counterstrike expansion available?                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if counterstrike installed                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/5/97 1:59PM ST : Fixed to check for EXPAND.MIX                                         *\n *=============================================================================================*/\nbool Expansion_CS_Present(void)\n{\n\t//\tajw 9/29/98\n\treturn Is_Counterstrike_Installed();\n//\tRawFileClass file(\"EXPAND.MIX\");\n//\treturn(file.Is_Available());\n}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n/***********************************************************************************************\n * Expansion_AM_Present -- Is the Aftermath expansion available?                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if AfterMath is installed                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    7/9/97 1:59PM BG : Fixed to check for EXPAND2.MIX                                        *\n *=============================================================================================*/\nbool Expansion_AM_Present(void)\n{\n\t//\tajw 9/29/98\n\treturn Is_Aftermath_Installed();\n//\tRawFileClass file(\"EXPAND2.MIX\");\n//\treturn(file.Is_Available());\n}\n#endif\n\n\nconst char* ExpandNames[] = {\n\t\"SCG20EA\",\n\t\"SCG21EA\",\n\t\"SCG22EA\",\n\t\"SCG23EA\",\n\t\"SCG24EA\",\n\t\"SCG26EA\",\n\t\"SCG27EA\",\n\t\"SCG28EA\",\n\t\"SCU31EA\",\n\t\"SCU32EA\",\n\t\"SCU33EA\",\n\t\"SCU34EA\",\n\t\"SCU35EA\",\n\t\"SCU36EA\",\n\t\"SCU37EA\",\n\t\"SCU38EA\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\"SCG43EA\",\t\t// Harbor Reclamation\n\t\"SCG41EA\",\t\t// In the nick of time\n\t\"SCG40EA\",\t\t// Caught in the act\n\t\"SCG42EA\",\t\t// Production Disruption\n\t\"SCG47EA\",\t\t// Negotiations\n\t\"SCG45EA\",\t\t// Monster Tank Madness\n\t\"SCG44EA\",\t\t// Time Flies\n\t\"SCG48EA\",\t\t// Absolut MADness\n\t\"SCG46EA\",\t\t// Pawn\n\n\t\"SCU43EA\",\t\t// Testing Grounds\n\t\"SCU40EA\",\t\t// Shock Therapy\n\t\"SCU42EA\",\t\t// Let's Make a Steal\n\t\"SCU41EA\",\t\t// Test Drive\n\t\"SCU45EA\",\t\t// Don't Drink The Water\n\t\"SCU44EA\",\t\t// Situation Critical\n\t\"SCU46EA\",\t\t// Brothers in Arms\n\t\"SCU47EA\",\t\t// Deus Ex Machina\n\t\"SCU48EA\",\t\t// Grunyev Revolution\n#endif\n\tNULL\n\t};\n\nconst char* TestNames2[] = {\n\t\"SCG01EA\",\n\t\"SCG02EA\",\n\t\"SCG03EA\",\n\t\"SCG04EA\",\n\t\"SCG05EA\",\n\t\"SCG06EA\",\n\t\"SCG07EA\",\n\t\"SCG08EA\",\n\t\"SCU01EA\",\n\t\"SCU02EA\",\n\t\"SCU03EA\",\n\t\"SCU04EA\",\n\t\"SCU05EA\",\n\t\"SCU06EA\",\n\t\"SCU07EA\",\n\t\"SCU08EA\",\n\t\"SCU09EA\",\n\tNULL\n};\n\n#ifdef GERMAN\nconst char* XlatNames[] = {\n\t\"Zusammenstoss\",\n\t\"Unter Tage\",\n\t\"Kontrollierte Verbrennung\",\n\t\"Griechenland 1 - Stavros\",\n\t\"Griechenland 2 - Evakuierung\",\n\t\"Sibirien 1 - Frische Spuren\",\n\t\"Sibirien 2 - In der Falle\",\n\t\"Sibirien 3 - Wildnis\",\n\t\"Das Feld der Ehre\",\n\t\"Belagerung\",\n\t\"Mausefalle\",\n\t\"Teslas Erbe\",\n\t\"Soldat Volkov\",\n\t\"Die Spitze der Welt\",\n\t\"Paradoxe Gleichung\",\n\t\"Nukleare Eskalation\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\"Ein sicherer Hafen\",\t\t\t  //\t\"SCG43EA\",\t\t// Harbor Reclamation\n\t\"Zeitkritische Routine\",\t\t  //\t\"SCG41EA\",\t\t// In the nick of time\n\t\"Auf frischer Tat ertappt\",\t  //\t\"SCG40EA\",\t\t// Caught in the act\n\t\"Drastischer Baustopp\",\t\t\t  //\t\"SCG42EA\",\t\t// Production Disruption\n\t\"Harte Verhandlungen\",\t\t\t  //\t\"SCG47EA\",\t\t// Negotiations\n\t\"Ferngelenktes Kriegsspielzeug\",//\t\"SCG45EA\",\t\t// Monster Tank Madness\n\t\"Licht aus\",\t\t\t\t\t\t  //\t\"SCG44EA\",\t\t// Time Flies\n\t\"Molekulare Kriegsfhrung\",\t  //\t\"SCG48EA\",\t\t// Absolut MADness\n\t\"Bauernopfer\",\t\t\t\t\t\t  //\t\"SCG46EA\",\t\t// Pawn\n\n\t\"Testgelnde\",\t\t\t\t\t\t  //\t\"SCU43EA\",\t\t// Testing Grounds\n\t\"Schocktherapie\",\t\t\t\t\t  //\t\"SCU40EA\",\t\t// Shock Therapy\n\t\"Der Letzte seiner Art\",\t\t  //\t\"SCU42EA\",\t\t// Let's Make a Steal\n\t\"Probefahrt\",\t\t\t\t\t\t  //\t\"SCU41EA\",\t\t// Test Drive\n\t\"Schlaftrunk\",\t\t\t\t\t\t  //\t\"SCU45EA\",\t\t// Don't Drink The Water\n\t\"Der jngste Tag\",\t\t\t\t  //\t\"SCU44EA\",\t\t// Situation Critical\n\t\"Waffenbrder\",\t\t\t\t\t  //\t\"SCU46EA\",\t\t// Brothers in Arms\n\t\"Deus Ex Machina\",\t\t\t\t  //\t\"SCU47EA\",\t\t// Deus Ex Machina\n\t\"Die Replikanten von Grunyev\",  //\t\"SCU48EA\",\t\t// Grunyev Revolution\n\n#endif\n\tNULL\n};\n\n#endif\n\n#ifdef FRENCH\nconst char* XlatNames[] = {\n\t\"Gaz Sarin 1: Ravitaillement Fatal\",\n\t\"Gaz Sarin 2: En Sous-sol\",\n\t\"Gaz Sarin 3: Attaque Chirurgicale\",\n\t\"Grce Occupe 1: Guerre Prive\",\n\t\"Grce Occupe 2: Evacuation\",\n\t\"Conflit Sibrien 1: Traces Fraches\",\n\t\"Conflit Sibrien 2: Pris au Pige\",\n\t\"Conflit Sibrien 3: Terres de Glace\",\n\t\"Mise  l'Epreuve\",\n\t\"Assigs\",\n\t\"La Souricire\",\n\t\"L'Hritage de Tesla\",\n\t\"Tandem de Choc\",\n\t\"Jusqu'au Sommet du Monde\",\n\t\"Effets Secondaires\",\n\t\"Intensification nuclaire\",\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\"Le vieux port\",\t\t\t\t//\t\"SCG43EA\",\t\t// Harbor Reclamation\n\"Juste  temps\",\t\t\t\t//\t\"SCG41EA\",\t\t// In the nick of time\n\"La main dans le sac\",\t\t//\t\"SCG40EA\",\t\t// Caught in the act\n\"Production interrompue\",\t//\t\"SCG42EA\",\t\t// Production Disruption\n\"Ngociations\",\t\t\t\t//\t\"SCG47EA\",\t\t// Negotiations\n\"Tanks en folie!\",\t\t\t//\t\"SCG45EA\",\t\t// Monster Tank Madness\n\"Le temps passe\",\t\t\t\t//\t\"SCG44EA\",\t\t// Time Flies\n\"Dmence absolue\",\t\t\t//\t\"SCG48EA\",\t\t// Absolut MADness\n\"Le pion\",\t\t\t\t\t\t//\t\"SCG46EA\",\t\t// Pawn\n\n\"Terrains d'essais\",\t\t\t//\t\"SCU43EA\",\t\t// Testing Grounds\n\"Thrapie de choc\",\t\t\t//\t\"SCU40EA\",\t\t// Shock Therapy\n\"Au voleur!\",\t\t\t\t\t//\t\"SCU42EA\",\t\t// Let's Make a Steal\n\"Essai de conduite\",\t\t\t//\t\"SCU41EA\",\t\t// Test Drive\n\"Ne buvez pas la tasse\",\t//\t\"SCU45EA\",\t\t// Don't Drink The Water\n\"Situation critique\",\t\t//\t\"SCU44EA\",\t\t// Situation Critical\n\"Frres d'armes\",\t\t\t\t//\t\"SCU46EA\",\t\t// Brothers in Arms\n\"Deus Ex Machina\",\t\t\t//\t\"SCU47EA\",\t\t// Deus Ex Machina\n\"La Rvolution de Grunyev\",//\t\"SCU48EA\",\t\t// Grunyev Revolution\n\n#endif\n\n\tNULL,\n};\n\n#endif\n\n\n\n#ifndef WIN32\t //VG\n\n\t#define\tOPTION_WIDTH\t236\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#error Can never again build without WIN32 defined.\n\t#define\tOPTION_HEIGHT\t162\n#else\n\t#define\tOPTION_HEIGHT\t162\n#endif\n\t#define\tOPTION_X\t\t\t((320 - OPTION_WIDTH) / 2)\n\t#define\tOPTION_Y\t\t\t(200 - OPTION_HEIGHT) / 2\n\n#else\n\n\t#define\tOPTION_WIDTH\t560\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t#define\tOPTION_HEIGHT\t332\n#else\n\t#define\tOPTION_HEIGHT\t300\n#endif\n\t#define\tOPTION_X\t\t\t((640 - OPTION_WIDTH) / 2)\n\t#define\tOPTION_Y\t\t\t(400 - OPTION_HEIGHT) / 2\n#endif\n\nstruct EObjectClass\n{\n\tHousesType House;\n\tint Scenario;\n\tchar Name[128];\n\tchar FullName[128];\n};\n\n\n/*\n**\tDerived from list class to handle expansion scenario listings. The listings\n**\tare recorded as EObjectClass objects. The data contained specifies the scenario\n**\tnumber, side, and text description.\n*/\nclass EListClass : public ListClass\n{\n\tpublic:\n\t\tEListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\t\t\tListClass(id, x, y, w, h, flags, up, down) {};\n\n\t\tvirtual int Add_Object(EObjectClass * obj) {\n\t\t\treturn(ListClass::Add_Item((char const *)obj));\n\t\t}\n\t\tvirtual EObjectClass * Get_Object(int index) const {\n\t\t\treturn((EObjectClass *)ListClass::Get_Item(index));\n\t\t}\n\t\tvirtual EObjectClass * Current_Object(void) {\n\t\t\treturn((EObjectClass *)ListClass::Current_Item());\n\t\t}\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\tprivate:\n\t\tvirtual int Add_Item(char const * text) {return(ListClass::Add_Item(text));};\n\t\tvirtual int Add_Item(int text) {return(ListClass::Add_Item(text));};\n\t\tvirtual char const * Current_Item(void) const {return(ListClass::Current_Item());};\n\t\tvirtual char const * Get_Item(int index) const {return(ListClass::Get_Item(index));};\n};\n\n\n/***********************************************************************************************\n * EListClass::Draw_Entry -- Draws entry for expansion scenario.                               *\n *                                                                                             *\n *    This overrides the normal list class draw action so that the scenario name will be       *\n *    displayed along with the house name.                                                     *\n *                                                                                             *\n * INPUT:   index    -- The index of the entry that should be drawn.                           *\n *                                                                                             *\n *          x,y      -- Coordinate of upper left region to draw the entry into.                *\n *                                                                                             *\n *          width    -- Width of region (pixels) to draw the entry.                            *\n *                                                                                             *\n *          selected -- Is this entry considered selected?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid EListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tchar buffer[128];\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint text = TXT_NONE;\n\tif (Get_Object(index)->House == HOUSE_GOOD) {\n\t\ttext = TXT_ALLIES;\n\t} else {\n\t\ttext = TXT_SOVIET;\n\t}\n\tsprintf(buffer, \"%s: %s\", Text_String(text), Get_Object(index)->Name);\n\n\tTextPrintType flags = TextFlags;\n\n\tif (selected) {\n\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, 1);\n\t} else {\n\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t}\n\t}\n\n#ifndef WIN32\n        Conquer_Clip_Text_Print(buffer, x, y, scheme, TBLACK, flags & ~(TPF_CENTER), width, Tabs);\n#else\n\tConquer_Clip_Text_Print(buffer, x + 100, y, scheme, TBLACK, flags & ~(TPF_CENTER), width, Tabs);\n#endif\n}\n\n#ifdef FIXIT_VERSION_3\nbool Expansion_Dialog( bool bCounterstrike )\t\t//\tIf not bCounterstrike, then this was called for Aftermath.\n#else\nbool Expansion_Dialog(void)\n#endif\n{\n\tGadgetClass * buttons = NULL;\n\n#ifndef WIN32\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+40, OPTION_Y+OPTION_HEIGHT-15);\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-85, OPTION_Y+OPTION_HEIGHT-15);\n#else\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+40, OPTION_Y + OPTION_HEIGHT - 50 );\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-85, OPTION_Y + OPTION_HEIGHT - 50 );\n#endif\n\n#ifndef WIN32\n\tEListClass list(202, OPTION_X + 20, OPTION_Y+20, OPTION_WIDTH-40, OPTION_HEIGHT-40, TPF_BUTTON, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#else\n\tEListClass list(202, OPTION_X+35, OPTION_Y + 30, OPTION_WIDTH-70, OPTION_HEIGHT - 85, TPF_BUTTON, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n#endif\n\tbuttons = &ok;\n\tcancel.Add(*buttons);\n\tlist.Add(*buttons);\n\n\t/*\n\t**\tAdd in all the expansion scenarios.\n\t*/\n\tCCFileClass file;\n\tchar buffer[128], buffer2[128];\n\tchar * sbuffer = (char*)_ShapeBuffer;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Though disgusted.\n\tfor (int index = 20; index < (36+18); index++) {\n#else\n\tfor (int index = 20; index < 36; index++) {\n#endif\n\n#ifndef CS_DEBUG\n\t\tstrcpy(buffer,ExpandNames[index - 20]);\n\t\tstrcpy(buffer2, ExpandNames[index - 20]);\n#else\n\t\tstrcpy(buffer, TestNames2[index]);\n\t\tstrcpy(buffer2, TestNames2[index]);\n#endif\n\t\tif(buffer[0] == NULL)\n\t\t   break;\n\n     \tstrcat(buffer, \".INI\");\n\t\tstrcat(buffer2, \".INI\");\n\t\tScen.Set_Scenario_Name(buffer);\n\t\tScen.Scenario = index;\n\t\tfile.Set_Name(buffer);\n#ifdef FIXIT_VERSION_3\n\t\tbool bOk;\n\t\tif( index < 36 )\n\t\t\tbOk = bCounterstrike;\n\t\telse\n\t\t\tbOk = !bCounterstrike;\n\n\t\tif( bOk && file.Is_Available() )\n\t\t{\n#else\t//\tFIXIT_VERSION_3\n\t\tif (file.Is_Available()) {\n#endif\t//\tFIXIT_VERSION_3\n\t\t    EObjectClass * obj = new EObjectClass;\n            switch(buffer[2]){\n\n\t\tcase 'G':\n\t\tcase 'g':\n\t\t\tfile.Read(sbuffer, 2000);\n\t\t\tsbuffer[2000] = '\\r';\n\t\t\tsbuffer[2000+1] = '\\n';\n\t\t\tsbuffer[2000+2] = '\\0';\n\t\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"x\", buffer, sizeof(buffer), sbuffer);\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tstrcpy(obj->Name, XlatNames[index - ARRAYOFFSET]);\n#else\n\t\t\tstrcpy(obj->Name, buffer);\n#endif\n//\t\t\tstrcpy(obj->Name, buffer);\n\t\t\tstrcpy(obj->FullName, buffer2);\n\t\t\tobj->House = HOUSE_GOOD;\n\t\t\tobj->Scenario = index;\n\t\t\tlist.Add_Object(obj);\n\t\t\tbreak;\n\n\t\tcase 'U':\n\t\tcase 'u':\n\t\t  \tfile.Read(sbuffer, 2000);\n\t\t    \tsbuffer[2000] = '\\r';\n\t\t        sbuffer[2000+1] = '\\n';\n\t\t\tsbuffer[2000+2] = '\\0';\n\t\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"x\", buffer, sizeof(buffer), sbuffer);\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tstrcpy(obj->Name, XlatNames[index - ARRAYOFFSET]);\n#else\n\t\t\tstrcpy(obj->Name, buffer);\n#endif\n//\t\t     \tstrcpy(obj->Name, buffer);\n\t\t\tstrcpy(obj->FullName, buffer2);\n\t\t\tobj->House = HOUSE_BAD;\n\t\t\tobj->Scenario = index;\n\t\t\tlist.Add_Object(obj);\n\t       \t\tbreak;\n\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t    }\n\t}\n\n\tSet_Logic_Page(SeenBuff);\n\tbool recalc = true;\n\tbool display = true;\n\tbool process = true;\n\tbool okval = true;\n\n\n\twhile (process) {\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n#endif\n\n\t\tCall_Back();\n\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tLoad the background picture.\n\t\t\t*/\n\t\t\tLoad_Title_Page();\n\t\t\tCCPalette.Set();\n\n\t\t\tDialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT);\n#ifdef FIXIT_VERSION_3\n\t\t\tif (bCounterstrike)\n\t\t\t{\n\t\t\t\t//PG Draw_Caption( TXT_WOL_CS_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//PG Draw_Caption( TXT_WOL_AM_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\t\t\t}\n#else\n\t\t\tDraw_Caption(TXT_NEW_MISSIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n#endif\n\t\t\tbuttons->Draw_All();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\tKeyNumType input = buttons->Input();\n\t\tswitch (input) {\n\t\t\tcase 200|KN_BUTTON:\n\t\t\t      \tWhom = list.Current_Object()->House;\n\t\t\t\tScen.Scenario = list.Current_Object()->Scenario;\n\t\t\t\tstrcpy(Scen.ScenarioName, list.Current_Object()->FullName);\n\t\t\t\tprocess = false;\n\t\t\t\tokval = true;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_ESC:\n\t\t\tcase 201|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tokval = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tWhom = list.Current_Object()->House;\n\t\t\t\tScen.Scenario = list.Current_Object()->Scenario;\n\t\t\t\tstrcpy(Scen.ScenarioName, list.Current_Object()->FullName);\n\t\t\t\tprocess = false;\n\t\t\t\tokval = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tFree up the allocations for the text lines in the list box.\n\t*/\n \tfor (int index = 0; index < list.Count(); index++) {\n \t\tdelete list.Get_Object(index);\n \t}\n\n\treturn(okval);\n\n}\n\n"
  },
  {
    "path": "REDALERT/EXTERNS.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/EXTERNS.H 2     3/10/97 6:23p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : EXTERNS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 27, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 27, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef EXTERNS_H\n#define EXTERNS_H\n\n#include\t\"cell.h\"\n\n#ifdef SCENARIO_EDITOR\n#include\t\"mapedit.h\"\n#endif\n#include\t\"techno.h\"\n#include\t\"type.h\"\n#include\t\"building.h\"\n#include\t\"unit.h\"\n#include\t\"credits.h\"\n#include\t\"goptions.h\"\n#include\t\"options.h\"\n#include\t\"infantry.H\"\n#include \"DSOUND.H\"\n\nextern char _staging_buffer[32000];\nextern \"C\" {\nvoid _PRO(void);\n}\n\n/*\n**\tConvenient alias for MixFileClass<CDFileClass> object. This allows\n**\teasier entry into the code and less clutter.\n*/\ntypedef MixFileClass<CCFileClass>\tMFCD;\n\nextern bool IsVQ640;\nextern unsigned long GameVersion;\nextern bool Debug_MotionCapture;\nextern bool Debug_Rotate;\nextern bool Debug_Quiet;\nextern bool Debug_Cheat;\nextern bool Debug_Remap;\nextern bool Debug_Flag;\nextern bool Debug_Lose;\nextern bool Debug_Map;\nextern bool Debug_Win;\nextern bool Debug_Icon;\nextern bool Debug_Passable;\nextern bool Debug_Unshroud;\nextern bool Debug_Threat;\nextern bool Debug_Find_Path;\nextern bool Debug_Check_Map;\nextern bool Debug_Playtest;\n\nextern bool Debug_Heap_Dump;\nextern bool Debug_Smart_Print;\nextern bool Debug_Trap_Check_Heap;\nextern bool Debug_Modem_Dump;\nextern bool Debug_Print_Events;\nextern bool Debug_Force_Crash;\n\nextern void const *LightningShapes;\n\nextern int NewINIFormat;\n\n\n#ifdef FIXIT_ANTS\nextern bool AntsEnabled;\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool NewUnitsEnabled;\nextern bool SecretUnitsEnabled;\nextern int MTankDistance;\nextern bool OverrideNewUnitsEnabled;\t // ST - 12/13/2019 12:19PM\t\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\nextern int CarrierLaunchDelay;\n#endif\n#endif\n\n#ifdef FIXIT_NAME_OVERRIDE\nextern char const * NameOverride[25];\nextern int NameIDOverride[25];\n#endif\n\n#ifdef WIN32\nextern bool\t\t\t\t\tGameInFocus;\nextern unsigned char \t*InterpolatedPalettes[100];\nextern BOOL\t\t\t\t\tPalettesRead;\nextern unsigned\t\t\tPaletteCounter;\nextern int \t\t\t\t\tAllDone;\nextern HANDLE \t\t\t\thInstance;\nextern bool \t\t\t\tInMovie;\nextern WinTimerClass\t*\t\tWindowsTimer;\nextern WWMouseClass *\t\tWWMouse;\nextern GraphicBufferClass\tHiddenPage;\n#define\tSeenPage\t\tSeenBuff\nextern GraphicBufferClass\t\tVisiblePage;\nextern GraphicViewPortClass\tSeenBuff;\nextern GraphicBufferClass\t\tSysMemPage;\nextern LPDIRECTSOUND\t\t\t\tSoundObject;\nextern LPDIRECTSOUNDBUFFER\t\tPrimaryBufferPtr;\nextern int\t\t\t\t\t\t\tScreenWidth;\nextern int\t\t\t\t\t\t\tScreenHeight;\nextern GraphicBufferClass\t\tModeXBuff;\n\n#else\n\nextern VideoBufferClass\t\tSeenPage;\nextern GraphicBufferClass\tSeenBuff;\nextern GraphicBufferClass &\tVisiblePage;\n#endif\n\n\n/*\n**\tDynamic global variables (these change or are initialized at run time).\n*/\nextern MissionControlClass\t\tMissionControl[MISSION_COUNT];\nextern char const *\t\t\t\tTutorialText[225];\nextern Buffer *\t\t\t\t\tTheaterBuffer;\nextern GetCDClass\t\t\t\t\tCDList;\nextern CCINIClass\t\t\t\t\tRuleINI;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern CCINIClass\t\t\t\t\tAftermathINI;\n#endif\n//extern Benchmark *\t\t\t\tBenches;\nextern int\t\t\t\t\t\t\tMapTriggerID;\nextern int\t\t\t\t\t\t\tLogicTriggerID;\nextern PKey\t\t\t\t\t\t\tFastKey;\nextern PKey\t\t\t\t\t\t\tSlowKey;\nextern RulesClass\t\t\t\t\tRule;\nextern KeyboardClass *\t\t\tKeyboard;\nextern RandomStraw\t\t\t\tCryptRandom;\nextern RandomClass\t\t\t\tNonCriticalRandomNumber;\nextern CarryoverClass *\t\t\tCarryover;\nextern ScenarioClass\t\t\t\tScen;\nextern RemapControlType\t\t\tColorRemaps[PCOLOR_COUNT];\nextern RemapControlType\t\t\tMetalScheme;\nextern RemapControlType\t\t\tGreyScheme;\nextern VersionClass\t\t\t\tVerNum;\nextern bool\t\t\t\t\t\t\tSlowPalette;\nextern bool\t\t\t\t\t\t\tScoresPresent;\nextern bool\t\t\t\t\t\t\tAllowVoice;\nextern NewConfigType\t\t\t\tNewConfig;\nextern VoxType\t\t\t\t\t\tSpeakQueue;\nextern bool\t\t\t\t\t\t\tPlayerWins;\nextern bool\t\t\t\t\t\t\tPlayerLoses;\nextern bool\t\t\t\t\t\t\tPlayerRestarts;\nextern long\t\t\t\t\t\t\tFrame;\nextern VoxType\t\t\t\t\t\tSpeechRecord[2];\nextern void *\t\t\t\t\t\tSpeechBuffer[2];\nextern int\t\t\t\t\t\t\tPreserveVQAScreen;\nextern bool\t\t\t\t\t\t\tBreakoutAllowed;\nextern bool\t\t\t\t\t\t\tBrokeout;\n\nextern GameOptionsClass \t\tOptions;\n\nextern LogicClass \t\t\t\tLogic;\n#ifdef SCENARIO_EDITOR\nextern MapEditClass \t\t\t\tMap;\n#else\nextern MouseClass \t\t\t\tMap;\n#endif\nextern ScoreClass \t\t\t\tScore;\nextern MonoClass \t\t\t\t\tMonoArray[DMONO_COUNT];\nextern MFCD *\t\t\t\t\t\tTheaterData;\nextern MFCD *\t\t\t\t\t\tMoviesMix;\nextern MFCD *\t\t\t\t\t\tGeneralMix;\nextern MFCD *\t\t\t\t\t\tScoreMix;\nextern MFCD *\t\t\t\t\t\tMainMix;\nextern MFCD *\t\t\t\t\t\tConquerMix;\nextern ThemeClass \t\t\t\tTheme;\nextern SpecialClass \t\t\t\tSpecial;\n\n/*\n**\tGame object allocation and tracking classes.\n*/\nextern TFixedIHeapClass<AircraftClass>\t\t\t\t\t\tAircraft;\nextern TFixedIHeapClass<AnimClass>\t\t\t\t\t\t\tAnims;\nextern TFixedIHeapClass<BuildingClass>\t\t\t\t\t\tBuildings;\nextern TFixedIHeapClass<BulletClass>\t\t\t\t\t\tBullets;\nextern TFixedIHeapClass<FactoryClass>\t\t\t\t\t\tFactories;\nextern TFixedIHeapClass<HouseClass>\t\t\t\t\t\t\tHouses;\nextern TFixedIHeapClass<InfantryClass>\t\t\t\t\t\tInfantry;\nextern TFixedIHeapClass<OverlayClass>\t\t\t\t\t\tOverlays;\nextern TFixedIHeapClass<SmudgeClass>\t\t\t\t\t\tSmudges;\nextern TFixedIHeapClass<TeamClass>\t\t\t\t\t\t\tTeams;\nextern TFixedIHeapClass<TeamTypeClass>\t\t\t\t\t\tTeamTypes;\nextern TFixedIHeapClass<TemplateClass>\t\t\t\t\t\tTemplates;\nextern TFixedIHeapClass<TerrainClass>\t\t\t\t\t\tTerrains;\nextern TFixedIHeapClass<TriggerClass>\t\t\t\t\t\tTriggers;\nextern TFixedIHeapClass<UnitClass>\t\t\t\t\t\t\tUnits;\nextern TFixedIHeapClass<VesselClass>\t\t\t\t\t\tVessels;\nextern TFixedIHeapClass<TriggerTypeClass>\t\t\t\t\tTriggerTypes;\n\nextern TFixedIHeapClass<HouseTypeClass>\t\t\t\t\tHouseTypes;\nextern TFixedIHeapClass<BuildingTypeClass>\t\t\t\tBuildingTypes;\nextern TFixedIHeapClass<AircraftTypeClass>\t\t\t\tAircraftTypes;\nextern TFixedIHeapClass<InfantryTypeClass>\t\t\t\tInfantryTypes;\nextern TFixedIHeapClass<BulletTypeClass>\t\t\t\t\tBulletTypes;\nextern TFixedIHeapClass<AnimTypeClass>\t\t\t\t\t\tAnimTypes;\nextern TFixedIHeapClass<UnitTypeClass>\t\t\t\t\t\tUnitTypes;\nextern TFixedIHeapClass<VesselTypeClass>\t\t\t\t\tVesselTypes;\nextern TFixedIHeapClass<TemplateTypeClass>\t\t\t\tTemplateTypes;\nextern TFixedIHeapClass<TerrainTypeClass>\t\t\t\t\tTerrainTypes;\nextern TFixedIHeapClass<OverlayTypeClass>\t\t\t\t\tOverlayTypes;\nextern TFixedIHeapClass<SmudgeTypeClass>\t\t\t\t\tSmudgeTypes;\n\nextern FixedIHeapClass *\t\t\t\t\t\t\t\t\t\tHeapPointers[RTTI_COUNT];\n\nextern TFixedIHeapClass<WeaponTypeClass>\t\t\t\t\tWeapons;\nextern TFixedIHeapClass<WarheadTypeClass>\t\t\t\t\tWarheads;\n\nextern QueueClass<EventClass, MAX_EVENTS>\t\t\t\t\tOutList;\nextern QueueClass<EventClass, (MAX_EVENTS * 64)>\t\tDoList;\n\n#ifdef MIRROR_QUEUE\nextern QueueClass<EventClass, (MAX_EVENTS * 64)>\t\tMirrorList;\n#endif\n\ntypedef DynamicVectorArrayClass<ObjectClass *, HOUSE_COUNT, HOUSE_FIRST> SelectedObjectsType;\nextern SelectedObjectsType\t\t\t\t\t\t\t\t\tCurrentObject;\nextern DynamicVectorClass<TriggerClass *>\t\t\t\t\tLogicTriggers;\nextern DynamicVectorClass<TriggerClass *>\t\t\t\t\tMapTriggers;\nextern DynamicVectorClass<TriggerClass *> \t\t\t\tHouseTriggers[HOUSE_COUNT];\n\nextern BaseClass\t\t\t\t\t\t\t\t\t\t\t\t\tBase;\n\n/* These variables are used to keep track of the slowest speed of a team */\nextern TeamFormDataStruct TeamFormData[HOUSE_COUNT];\nextern bool FormMove;\nextern SpeedType FormSpeed;\nextern MPHType FormMaxSpeed;\n\nextern bool IsTanyaDead;\nextern bool SaveTanya;\n\nextern bool TimeQuake;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool PendingTimeQuake;\nextern TARGET TimeQuakeCenter;\nextern fixed QuakeUnitDamage;\nextern fixed QuakeBuildingDamage;\nextern int QuakeInfantryDamage;\nextern int QuakeDelay;\nextern fixed ChronoTankDuration;\t\t// chrono override for chrono tanks\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\nextern fixed EngineerDamage;\t\t\t// Amount of damage an engineer does\nextern fixed EngineerCaptureLevel;\t// Building damage level before engineer can capture\n#endif\n#endif\n\n/*\n**\tLoaded data file pointers.\n*/\nextern void const *\t\tMetal12FontPtr;\nextern void const *\t\tMapFontPtr;\nextern void const *\t\tVCRFontPtr;\nextern void const *\t\tTypeFontPtr;\nextern void const *\t\tFont3Ptr;\nextern void const *\t\tFont6Ptr;\nextern void const *\t\tEditorFont;\nextern void const *\t\tFont8Ptr;\nextern void const *\t\tFontLEDPtr;\nextern void const *\t\tScoreFontPtr;\nextern void const *\t\tGradFont6Ptr;\nextern char const *\t\tSystemStrings;\nextern char const *\t\tDebugStrings;\n\n/*\n**\tMiscellaneous globals.\n*/\nextern ChronalVortexClass\t\tChronalVortex;\nextern TTimerClass<SystemTimerClass> TickCount;\nextern bool\t\t\t\t\t\t\tPassedProximity;\t// used in display.cpp\nextern HousesType\t\t\t\t\tWhom;\n//extern _VQAConfig\t\t\t\t\tAnimControl;\nextern long\t\t\t\t\t\t\tSpareTicks;\nextern long\t\t\t\t\t\t\tPathCount;\nextern long\t\t\t\t\t\t\tCellCount;\nextern long\t\t\t\t\t\t\tTargetScan;\nextern long\t\t\t\t\t\t\tSidebarRedraws;\nextern DMonoType\t\t\t\t\tMonoPage;\nextern bool\t\t\t\t\t\t\tGameActive;\nextern bool\t\t\t\t\t\t\tSpecialFlag;\nextern int\t\t\t\t\t\t\tScenarioInit;\nextern HouseClass *\t\t\t\tPlayerPtr;\nextern PaletteClass \t\t\t\tCCPalette;\nextern PaletteClass \t\t\t\tBlackPalette;\nextern PaletteClass \t\t\t\tWhitePalette;\nextern PaletteClass \t\t\t\tGamePalette;\n//extern PaletteClass \t\t\t\tInGamePalette;\n#define InGamePalette GamePalette\nextern PaletteClass \t\t\t\tOriginalPalette;\nextern PaletteClass\t\t\t\tScorePalette;\nextern int\t\t\t\t\t\t\tBuildLevel;\nextern unsigned long\t\t\t\tScenarioCRC;\n\n#ifdef FIXIT_VERSION_3\nextern bool\t\t\t\t\t\t\tbAftermathMultiplayer;\t\t//\tIs multiplayer game being played with Aftermath rules?\n#else\nextern unsigned long \t\t\t\tPlayingAgainstVersion;\t\t// Negotiated version number\nextern bool\t\t\t\t\t\t\tVersion107InMix;\t\t\t\t// Is there a v1.07 in the game\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\nextern bool\t\t\t\t\t\t\tbAutoSonarPulse;\n#endif\n\n#ifdef SCENARIO_EDITOR\nextern CELL \t\t\t\t\t\tCurrentCell;\n#endif\n\nextern SessionClass\t\t\t\tSession;\n//extern NullModemClass \t\t\tNullModem;\nextern IPXManagerClass \t \t\tIpx;\n\n#if(TEN)\nextern TenConnManClass\t\t\t*Ten;\n#endif\n\n#if(MPATH)\nextern MPlayerManClass\t\t\t*MPath;\n#endif\n\n#if(TIMING_FIX)\nextern int\t\t\t\t\t\t\t\t\t\tNewMaxAheadFrame1;\nextern int\t\t\t\t\t\t\t\t\t\tNewMaxAheadFrame2;\n#endif\n\nextern int\t\t\t\t\t\t\tSeed;\nextern int\t\t\t\t\t\t\tCustomSeed;\nextern GroundType  \t\t\t\tGround[LAND_COUNT];\n\n/*\n**\tConstant externs (data is not modified during game play).\n*/\nextern char const *\t\t\t\t\t\t\tMissions[MISSION_COUNT];\nextern char const\t\t\t\t\t\t\t\tKeys[];\nextern char const * const\t\t\t\t\tVQName[VQ_COUNT];\nextern int\t\t\t\t\t\t\t\t\t\tCrateData[CRATE_COUNT];\nextern char const * const\t\t\t\t\tCrateNames[CRATE_COUNT];\nextern int\t\t\t\t\t\t\t\t\t\tCrateShares[CRATE_COUNT];\nextern AnimType\t\t\t\t\t\t\t\tCrateAnims[CRATE_COUNT];\nextern char const * const\t\t\t\t\tSpecialWeaponName[SPC_COUNT];\nextern int const\t\t\t\t\t\t\t\tSpecialWeaponHelp[SPC_COUNT];\nextern char const * const\t\t\t\t\tSpecialWeaponFile[SPC_COUNT];\nextern char const * const\t\t\t\t\tArmorName[ARMOR_COUNT];\nextern char const * const\t\t\t\t\tQuarryName[QUARRY_COUNT];\nextern char const * const\t\t\t\t\tFormationName[FORMATION_COUNT];\nextern unsigned long const\t\t\t\t\tPlayCodes[];\nextern unsigned long const\t\t\t\t\tCheatCodes[];\n//extern char const * const\t\t\t\t\tProjectileNames[];\nextern unsigned long const\t\t\t\t\tEditorCodes[];\nextern char const * const\t\t\t\t\tSourceName[SOURCE_COUNT];\nextern int const\t\t\t\t\t\t\t\tGroundColor[LAND_COUNT];\nextern int const\t\t\t\t\t\t\t\tSnowColor[LAND_COUNT];\nextern TheaterDataType const \t\t\t\tTheaters[THEATER_COUNT];\nextern unsigned char const \t\t\t\tFacing32[256];\nextern unsigned char const\t\t\t\t\tFacing16[256];\nextern signed char const\t\t\t\t\tRotation16[256];\nextern unsigned char const \t\t\t\tFacing8[256];\nextern unsigned char const\t\t\t\t\tPixel2Lepton[24];\nextern COORDINATE const \t\t\t\t\tStoppingCoordAbs[5];\nextern CELL const \t\t\t\t\t\t\tAdjacentCell[FACING_COUNT];\nextern COORDINATE const \t\t\t\t\tAdjacentCoord[FACING_COUNT];\nextern unsigned char const\t\t\t\t\tRemapCiv2[];\nextern unsigned char const\t\t\t\t\tRemapCiv4[];\nextern unsigned char const\t\t\t\t\tRemapCiv5[];\nextern unsigned char const\t\t\t\t\tRemapCiv6[];\nextern unsigned char const\t\t\t\t\tRemapCiv7[];\nextern unsigned char const\t\t\t\t\tRemapCiv8[];\nextern unsigned char const\t\t\t\t\tRemapCiv9[];\nextern unsigned char const\t\t\t\t\tRemapCiv10[];\nextern unsigned char const\t\t\t\t\tRemapEmber[];\n\nextern int SoundOn;\n\n#ifdef WIN32\nextern GraphicViewPortClass\tHidPage;\n#else\nextern GraphicBufferClass\tHidPage;\n#endif\nextern int \t\t\t\t\t\tMenuList[][8];\nextern CDTimerClass<SystemTimerClass> FrameTimer;\nextern CDTimerClass<SystemTimerClass> CountDownTimer;\n\nextern SpecialDialogType\tSpecialDialog;\n\nextern int RequiredCD;\nextern int CurrentCD;\nextern int MouseInstalled;\n\n\nextern int LogLevel;\nextern unsigned long LogLevelTime[ MAX_LOG_LEVEL ];\nextern unsigned long LogLastTime;\n\nextern class DynamicVectorClass<EventChoiceClass> test2;\nextern class DynamicVectorClass<ActionChoiceClass> test3;\n\nextern bool LogDump_Print;\n\nextern \"C\"{\n\textern bool IsTheaterShape;\n}\n\nextern void Reset_Theater_Shapes(void);\nextern TheaterType LastTheater;\nvoid Coordinate_Remap ( GraphicViewPortClass *inbuffer, int x, int y, int width, int height, unsigned char *remap_table);\nvoid Do_Vortex (int x, int y, int frame);\n\n\n/************************************************************\n** Win32 specific externs\n*/\n#ifdef WIN32\nextern int ReadyToQuit;\t\t\t\t\t\t\t//Are we about to exit cleanly\nextern bool InDebugger;\t\t\t\t\t\t\t//Are we being run from a debugger\nvoid Memory_Error_Handler(void);\t\t\t\t//Memory error handler function\nvoid WWDebugString (char *string);\n#else\nextern bool IsTheaterShape;\n#endif\t//WIN32\n\n\n/*************************************************************\n** Internet specific externs\n*/\n#ifdef WIN32\n\nextern char PlanetWestwoodHandle[];\t\t\t//Planet WW user name\nextern char PlanetWestwoodPassword[];\t\t//Planet WW password\nextern char PlanetWestwoodIPAddress[];\t\t//IP of server or other player\nextern long PlanetWestwoodPortNumber;\t\t//Port number to send to\nextern bool PlanetWestwoodIsHost;\t\t\t\t//Flag true if player has control of game options\nextern unsigned long PlanetWestwoodGameID;\t//Game ID\nextern HWND\tWChatHWND;\t\t\t\t\t\t\t//Handle to Wchat window.\nextern bool\tGameStatisticsPacketSent;\nextern bool\tConnectionLost;\nextern void *PacketLater;\nextern bool SpawnedFromWChat;\nextern int ShowCommand;\nvoid\tRegister_Game_Start_Time(void);\nvoid\tRegister_Game_End_Time(void);\nvoid\tSend_Statistics_Packet(void);\nvoid \tCheck_From_WChat(char *wchat_name);\nbool \tDo_The_Internet_Menu_Thang (void);\nbool \tServer_Remote_Connect(void);\nbool \tClient_Remote_Connect(void);\nextern\tint UnitBuildPenalty;\n\n\n#endif\t //WIN32\n\n/*\n** From SENDFILE.CPP - externs for scenario file transfers\n*/\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, unsigned int crc, int gametype);\nbool Send_Remote_File ( char *file_name, int gametype );\nbool Get_Scenario_File_From_Host(char *return_name, int gametype);\nbool Find_Local_Scenario (char *description, char *filename, unsigned int length, char *digest, bool official);\n\n#ifdef MPEGMOVIE // Denzil 6/15/98\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\nextern MCIMovie* MciMovie;\n#endif\n\n#include \"mpgset.h\"\nextern MPGSettings* MpgSettings;\n#endif\n\nextern \"C\" bool MMXAvailable;\n\nextern bool ShareAllyVisibility;\n\n#endif\n"
  },
  {
    "path": "REDALERT/FACE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/08/96                                                     *\n *                                                                                             *\n *                  Last Update : March 8, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Desired_Facing8 -- Determines facing from one coordinate to another.                      *\n *   Desired_Facing256 -- Determines facing from one coordinate to another.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * Desired_Facing8 -- Determines facing from one coordinate to another.                        *\n *                                                                                             *\n *    This routine will find the facing (compass direction) from one location to another.      *\n *    Typical use of this is in find path and other 'monster' movement logic.                  *\n *                                                                                             *\n * INPUT:   x1,y1    -- X and Y coordinates for the source location. The coordinate 0,0 is     *\n *                      presumed to be the northwest corner of the map.                        *\n *                                                                                             *\n *          x2,y2    -- X and Y coordinates for the destination (target) location.             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing from the first coordinate to the second coordinate. The    *\n *          value returned will range from 0 being North, increasing clockwise until reaching  *\n *          255 which is just shy of North in a Westerly direction.                            *\n *                                                                                             *\n * WARNINGS:   This routine is only accurate to the 8 primary compass directions. It is much   *\n *             faster than the Desired_Facing256() function so it should be used where speed   *\n *             is more important than accuracy.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType Desired_Facing8(int x1, int y1, int x2, int y2)\n{\n\tint index = 0;\t\t\t\t// Facing composite value.\n\n\t/*\n\t**\tFigure the absolute X difference. This determines\n\t**\tif the facing is leftward or not.\n\t*/\n\tint xdiff = x2-x1;\n\tif (xdiff < 0) {\n\t\tindex |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFigure the absolute Y difference. This determines\n\t**\tif the facing is downward or not. This also clarifies\n\t**\texactly which quadrant the facing lies.\n\t*/\n\tint ydiff = y1-y2;\n\tif (ydiff < 0) {\n\t\tindex ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tIf on the diagonal, then incorporate this into the facing\n\t**\tand then bail. The facing is known.\n\t*/\n\tif (((bigger+1)/2) <= smaller) {\n\t\tindex += 0x0020;\n\t\treturn(DirType(index));\n\t}\n\n\t/*\n\t**\tDetermine if the facing is closer to the Y axis or\n\t**\tthe X axis.\n\t*/\n\tint adder = (index & 0x0040);\n\tif (xdiff == bigger) {\n\t\tadder ^= 0x0040;\n\t}\n\tindex += adder;\n\n\treturn(DirType(index));\n}\n\n\n/***********************************************************************************************\n * Desired_Facing256 -- Determines facing from one coordinate to another.                      *\n *                                                                                             *\n *    This routine will figure the facing from the source coordinate toward the destination    *\n *    coordinate. Typically, this routine is used for movement and other 'monster' logic. It   *\n *    is more accurate than the corresponding Desired_Facing8() function, but is slower.       *\n *                                                                                             *\n * INPUT:   srcx, srcy  -- The source coordinate to determine the facing from.                 *\n *                                                                                             *\n *          dstx, dsty  -- The destination (or target) coordinate to determine the facing      *\n *                         toward.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing from the source coordinate toward the destination          *\n *          coordinate with 0 being North increasing in a clockwise direction. 64 is East,     *\n *          128 is South, etc.                                                                 *\n *                                                                                             *\n * WARNINGS:   The coordinate 0,0 is presumed to be in the Northwest corner of the map.        *\n *             Although this routine is fast, it is not as fast as Desired_Facing8().          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nDirType Desired_Facing256(int srcx, int srcy, int dstx, int dsty)\n{\n\tint composite=0;\t\t// Facing built from intermediate calculations.\n\n\t/*\n\t**\tFetch the absolute X difference. This also gives a clue as\n\t**\tto which hemisphere the direction lies.\n\t*/\n\tint xdiff = dstx - srcx;\n\tif (xdiff < 0) {\n\t\tcomposite |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFetch the absolute Y difference. This clarifies the exact\n\t**\tquadrant that the direction lies.\n\t*/\n\tint ydiff = srcy - dsty;\n\tif (ydiff < 0) {\n\t\tcomposite ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tBail early if the coordinates are the same. This check also\n\t**\thas the added bonus of ensuring that checking for division\n\t**\tby zero is not needed in the following section.\n\t*/\n\tif (xdiff == 0 && ydiff == 0) return(DirType(0xFF));\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tNow that the quadrant is known, we need to determine how far\n\t**\tfrom the orthogonal directions, the facing lies. This value\n\t**\tis calculated as a ratio from 0 (matches orthogonal) to 31\n\t**\t(matches diagonal).\n\t*/\n\t//lint -e414\t\tDivision by zero cannot occur here.\n\tint frac = (smaller * 32U) / bigger;\n\n\t/*\n\t**\tGiven the quadrant and knowing whether the facing is closer\n\t**\tto the X or Y axis, we must make an adjustment toward the\n\t**\tsubsequent quadrant if necessary.\n\t*/\n\tint adder = (composite & 0x0040);\n\tif (xdiff > ydiff) {\n\t\tadder ^= 0x0040;\n\t}\n\tif (adder) {\n\t\tfrac = (adder - frac)-1;\n\t}\n\n\t/*\n\t**\tIntegrate the fraction value into the quadrant.\n\t*/\n\tcomposite += frac;\n\n\t/*\n\t**\tReturn with the final facing value.\n\t*/\n\treturn(DirType(composite & 0x00FF));\n}\n"
  },
  {
    "path": "REDALERT/FACE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/08/96                                                     *\n *                                                                                             *\n *                  Last Update : March 8, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACE_H\n#define FACE_H\n\n// Enumerations of the facing values returned from Desired_Facing().\ntypedef enum DirType : unsigned char {\n\tDIR_MIN=0,\n\tDIR_N=0,\n\tDIR_NE=1<<5,\n\tDIR_E=2<<5,\n\tDIR_SE=3<<5,\n\tDIR_S=4<<5,\n\tDIR_SW=5<<5,\n\tDIR_W=6<<5,\n\tDIR_NW=7<<5,\n\tDIR_MAX=255\n} DirType;\n\n// Operators that allow simple math with DirType.\ninline DirType operator + (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator + (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 + (int)f2) & 0x00FF);\n}\ninline DirType operator - (DirType f1, DirType f2)\n{\n\treturn (DirType)(((int)f1 - (int)f2) & 0x00FF);\n}\ninline DirType operator - (DirType f1, int f2)\n{\n\treturn (DirType)(((int)f1 - (int)f2) & 0x00FF);\n}\n\n\n// Function prototypes.\nDirType Desired_Facing8(int x1, int y1, int x2, int y2);\nDirType Desired_Facing256(int srcx, int srcy, int dstx, int dsty);\n\n#endif\n\n\n\n"
  },
  {
    "path": "REDALERT/FACING.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACING.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACING.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/21/95                                                     *\n *                                                                                             *\n *                  Last Update : March 21, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FacingClass::FacingClass -- Default constructor for the facing class.                     *\n *   FacingClass::Rotation_Adjust -- Perform a rotation adjustment to current facing.          *\n *   FacingClass::Set_Current -- Sets the current rotation value.                              *\n *   FacingClass::Set_Desired -- Sets the desired facing  value.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"facing.h\"\n\n\n/***********************************************************************************************\n * FacingClass::FacingClass -- Default constructor for the facing class.                       *\n *                                                                                             *\n *    This default constructor merely sets the desired and current facing values to be the     *\n *    same (North).                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFacingClass::FacingClass(void)\n{\n\tCurrentFacing = DIR_N;\n\tDesiredFacing = DIR_N;\n}\n\n\n/***********************************************************************************************\n * FacingClass::Set_Desired -- Sets the desired facing  value.                                 *\n *                                                                                             *\n *    This routine is used to set the desired facing value without altering the current        *\n *    facing setting. Typical use of this routine is when a vehicle needs to face a           *\n *    direction, but currently isn't facing the correct direction. After this routine is       *\n *    called, it is presumed that subsequent calls to Rotation_Adjust() will result in the     *\n *    eventual alignment of the current facing.                                                *\n *                                                                                             *\n * INPUT:   facing   -- The new facing to assign to the desired value.                         *\n *                                                                                             *\n * OUTPUT:  bool; Did the desired facing value actually change by this routine call?           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Set_Desired(DirType facing)\n{\n\tif (DesiredFacing != facing) {\n\t\tDesiredFacing = facing;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FacingClass::Set_Current -- Sets the current rotation value.                                *\n *                                                                                             *\n *    This routine will set the current rotation value. It is used to override the facing      *\n *    value without adjusting the desired setting.                                             *\n *                                                                                             *\n * INPUT:   facing   -- The new facing to assign to the current facing value.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the current setting changed by this routine. Failure means that the      *\n *                current setting was already at the value specified.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Set_Current(DirType facing)\n{\n\tif (CurrentFacing != facing) {\n\t\tCurrentFacing = facing;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FacingClass::Rotation_Adjust -- Perform a rotation adjustment to current facing.            *\n *                                                                                             *\n *    This routine is used when the current and desired facings differ but the current         *\n *    facing should be adjusted toward the desired facing. The amount of rotation to adjust    *\n *    is provided as a rotation rate parameter. Typical use of this routine is for turrets     *\n *    and other vehicle related rotating.                                                      *\n *                                                                                             *\n * INPUT:   rate  -- The rotation rate to use when adjusting the current facing toward the     *\n *                   desired facing. A value of 127 means instantaneous rotation.              *\n *                                                                                             *\n * OUTPUT:  bool; Did the rotation result in the current facing transitioning from one         *\n *                1/32 zone to another? If true, then the owning object most likely will       *\n *                need to be redrawn to reflect the change.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FacingClass::Rotation_Adjust(int rate)\n{\n\t/*\n\t**\tOnly perform the rotation adjustment if the desired facing is not the\n\t**\tsame as the current facing.\n\t*/\n\tif (Is_Rotating()) {\n\t\trate = min(rate, 127);\n\n\t\tDirType oldfacing = CurrentFacing;\n\t\tint diff = Difference();\n\n\t\t/*\n\t\t**\tIf the allowed facing change is greater than the difference between\n\t\t**\tthe current facing and the desired facing, then just snap the\n\t\t**\tfacing to the new value.\n\t\t*/\n\t\tif (ABS(diff) < rate) {\n\t\t\tCurrentFacing = DesiredFacing;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tAdjust the current facing clockwise or counterclockwise depending\n\t\t\t**\ton the shortest distance to the desired facing from the current\n\t\t\t**\tfacing.\n\t\t\t*/\n\t\t\tif (diff < 0) {\n\t\t\t\tCurrentFacing = (DirType)(CurrentFacing - (DirType)rate);\n\t\t\t} else {\n\t\t\t\tCurrentFacing = (DirType)(CurrentFacing + (DirType)rate);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this facing adjustment caused the current facing to rotate into a\n\t\t**\tnew 1/32 rotation zone (likely to cause a redraw), then return\n\t\t**\tthis fact with a true value.\n\t\t*/\n\t\treturn(Dir_To_32(CurrentFacing) != Dir_To_32(oldfacing));\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/FACING.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACING.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACING.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/21/95                                                     *\n *                                                                                             *\n *                  Last Update : March 21, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACING_H\n#define FACING_H\n\n/*\n**\tThis is a general facing handler class. It is used in those cases where facing needs to be\n**\tkept track of, but there could also be an associated desired facing. The current facing\n**\tis supposed to transition to the desired state over time. Using this class facilitates this\n**\tprocessing as well as isolating the rest of the code from the internals.\n*/\nclass FacingClass\n{\n\tpublic:\n\t\tFacingClass(void);\n\t\tFacingClass(DirType dir) : CurrentFacing(dir), DesiredFacing(dir) {};\n\t\tFacingClass(NoInitClass const & ) {};\n\n\t\toperator DirType (void) const {return(CurrentFacing);};\n\n\t\tDirType Current(void) const {return(CurrentFacing);};\n\t\tDirType Desired(void) const {return(DesiredFacing);};\n\n\t\tint Set_Desired(DirType facing);\n\t\tint Set_Current(DirType facing);\n\n\t\tvoid Set(DirType facing) {\n\t\t\tSet_Current(facing);\n\t\t\tSet_Desired(facing);\n\t\t};\n\n\t\tDirType Get(void) const { return CurrentFacing; }\n\n\t\tint Is_Rotating(void) const {return (DesiredFacing != CurrentFacing);};\n\t\tint Difference(void) const {return (int)(signed char)((int)DesiredFacing - (int)CurrentFacing);}\n\t\tint Difference(DirType facing) const {return (int)(signed char)((int)facing - (int)CurrentFacing);}\n\t\tint Rotation_Adjust(int rate);\n\n\tprivate:\n\t\tDirType CurrentFacing;\n\t\tDirType DesiredFacing;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/FACTORY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACTORY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACTORY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/26/94                                                     *\n *                                                                                             *\n *                  Last Update : May 22, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FactoryClass::AI -- Process factory production logic.                                     *\n *   FactoryClass::Abandon -- Abandons current construction with money refunded.               *\n *   FactoryClass::Completed -- Clears factory object after a completed production process.    *\n *   FactoryClass::Completion -- Fetches the completion step for this factory.                 *\n *   FactoryClass::Cost_Per_Tick -- Breaks entire production cost into manageable chunks.      *\n *   FactoryClass::FactoryClass -- Default constructor for factory objects.                    *\n *   FactoryClass::Get_Object -- Fetches pointer to object being constructed.                  *\n *   FactoryClass::Get_Special_Item -- gets factory's spc prod item                            *\n *   FactoryClass::Has_Changed -- Checks to see if a production step has occurred?             *\n *   FactoryClass::Has_Completed -- Checks to see if object has completed production.          *\n *   FactoryClass::Set -- Assigns a factory to produce an object.                              *\n *   FactoryClass::Set -- Force factory to \"produce\" special object.                           *\n *   FactoryClass::Start -- Resumes production after suspension or creation.                   *\n *   FactoryClass::Suspend -- Temporarily stop production.                                     *\n *   FactoryClass::operator delete -- Returns a factory to the free factory pool.              *\n *   FactoryClass::operator new -- Allocates a factory object from the free factory pool.      *\n *   FactoryClass::~FactoryClass -- Default destructor for factory objects.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FactoryClass::FactoryClass -- Default constructor for factory objects.                      *\n *                                                                                             *\n *    This brings the factory into a null state. It is called when a factory object is         *\n *    created.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass::FactoryClass(void) :\n\tRTTI(RTTI_FACTORY),\n\tID(Factories.ID(this)),\n\tIsSuspended(false),\n\tIsDifferent(false),\n\tIsBlocked(false),\n\tBalance(0),\n\tOriginalBalance(0),\n\tObject(0),\n\tSpecialItem(SPC_NONE),\n\tHouse(0)\n{\n\tSet_Rate(0);\n\tSet_Stage(0);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::~FactoryClass -- Default destructor for factory objects.                      *\n *                                                                                             *\n *    This cleans up a factory object in preparation for deletion. If there is currently       *\n *    an object in production, it is abandoned and money is refunded.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass::~FactoryClass(void)\n{\n\tif (GameActive) {\n\t\tAbandon();\n\t}\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Init -- Clears all units for scenario preparation.                            *\n *                                                                                             *\n *    This routine will zero out the factory list and objects. This routine is typically       *\n *    used in preparation for a new scenario load. All factory are guaranteed to be eliminated *\n *    by this routine.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::Init(void)\n{\n\tFactories.Free_All();\n}\n\n\n/***********************************************************************************************\n * FactoryClass::operator new -- Allocates a factory object from the free factory pool.        *\n *                                                                                             *\n *    This routine allocates a factory from the free factory pool. If there is no more room    *\n *    to allocate a factory, then NULL is returned.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the newly allocated factory object.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FactoryClass::operator new(size_t)\n{\n\tvoid * ptr = Factories.Allocate();\n\tif (ptr) {\n\t\t((FactoryClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::operator delete -- Returns a factory to the free factory pool.                *\n *                                                                                             *\n *    This returns the factory object back to the factory allocation pool. The factory is then *\n *    available to be allocated.                                                               *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the factory object to delete.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((FactoryClass *)ptr)->IsActive = false;\n\t}\n\tFactories.Free((FactoryClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::AI -- Process factory production logic.                                       *\n *                                                                                             *\n *    This routine should be called once per game tick. It handles the production process.     *\n *    As production proceeds, money is deducted from the owner object's house. When production *\n *    completes, the factory stop processing. A call to Abandon, Delete, or Completed is       *\n *    required after that point.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *   01/04/1995 JLB : Uses exact installment payment method.                                   *\n *=============================================================================================*/\nvoid FactoryClass::AI(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (!IsSuspended && (Object != NULL || SpecialItem)) {\n\t\tfor (int index = 0; index < 1; index++) {\n\t\t\tif (!Has_Completed() && Graphic_Logic() ) {\n\t\t\t\tIsDifferent = true;\n\n\t\t\t\tint cost = Cost_Per_Tick();\n\n\t\t\t\tcost = min(cost, Balance);\n\n\t\t\t\t/*\n\t\t\t\t**\tEnough time has expired so that another production step can occur.\n\t\t\t\t**\tIf there is insufficient funds, then go back one production step and\n\t\t\t\t**\tcontinue the countdown. The idea being that by the time the next\n\t\t\t\t**\tproduction step occurs, there may be sufficient funds available.\n\t\t\t\t*/\n\t\t\t\tif (cost > House->Available_Money()) {\n\t\t\t\t\tSet_Stage(Fetch_Stage()-1);\n\t\t\t\t} else {\n\t\t\t\t\tHouse->Spend_Money(cost);\n\t\t\t\t\tBalance -= cost;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the production has completed, then suspend further production.\n\t\t\t\t*/\n\t\t\t\tif (Fetch_Stage() == STEP_COUNT) {\n\t\t\t\t\tIsSuspended = true;\n\t\t\t\t\tSet_Rate(0);\n\t\t\t\t\tHouse->Spend_Money(Balance);\n\t\t\t\t\tBalance = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * FactoryClass::Force_Complete -- Force the factory to finish what it's building              *\n *                                                                                             *\n *    For debugging/testing support                                                            *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   8/23/2019 3:54PM ST : Created.                                                            *\n *=============================================================================================*/\nvoid FactoryClass::Force_Complete(void)\n{\n\tassert(Factories.ID(this) == ID);\n\t\n\tif (!IsSuspended && (Object != NULL || SpecialItem)) {\n\t\tSet_Stage(STEP_COUNT);\n\t\tIsSuspended = true;\n\t\tSet_Rate(0);\n\t\tBalance = 0;\n\t\tIsDifferent = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Has_Changed -- Checks to see if a production step has occurred?               *\n *                                                                                             *\n *    Use this routine to determine if production has advanced at least one step. By using     *\n *    this function, intelligent rendering may be performed.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Has the production process advanced one step since the last time this        *\n *                function was called?                                                         *\n *                                                                                             *\n * WARNINGS:   This function clears the changed status flag as a side effect.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Has_Changed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tbool changed = IsDifferent;\n\tIsDifferent = false;\n\treturn(changed);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Set -- Assigns a factory to produce an object.                                *\n *                                                                                             *\n *    This routine initializes a factory to produce the object specified. The desired object   *\n *    type is created and placed in suspended animation (limbo) until such time as production  *\n *    completes. Production is not actually started by this routine. An explicit call to       *\n *    Start() is required to begin production.                                                 *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object type class that is to be produced.             *\n *                                                                                             *\n *          house    -- Reference to the owner of the object to be produced.                   *\n *                                                                                             *\n * OUTPUT:  bool; Was production successfully prepared for this factory object. Failure means  *\n *                that the object could not be created. This is catastrophic and in such       *\n *                cases, the factory object should be deleted.                                 *\n *                                                                                             *\n * WARNINGS:   Be sure to examine the return value from this function. Failure to initialize   *\n *             the factory means that the factory is useless and should be deleted.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Set(TechnoTypeClass const & object, HouseClass & house)\n{\n\tassert(Factories.ID(this) == ID);\n\n\t/*\n\t**\tIf there is any production currently in progress, abandon it.\n\t*/\n\tAbandon();\n\n\t/*\n\t**\tSet up the factory for the new production process.\n\t*/\n\tIsDifferent = true;\n\tIsSuspended = true;\n\tSet_Rate(0);\n\tSet_Stage(0);\n\n\t/*\n\t**\tCreate an object of the type requested.\n\t*/\n\tObject = (TechnoClass *)object.Create_One_Of(&house);\n\n\t/*\n\t**\tBuildings that are constructed, will default to rebuilding on so that\n\t**\trepair can commence and base rebuilding can occur.\n\t*/\n\tif (!house.IsHuman && Object != NULL && Object->What_Am_I() == RTTI_BUILDING) {\n\t\t((BuildingClass *)Object)->IsToRebuild = true;\n\t}\n\n\tif (Object) {\n\t\tHouse  = Object->House;\n\t\tBalance = object.Cost_Of() * house.CostBias;\n\t\tObject->PurchasePrice = Balance;\n\t}\n\n\t/*\n\t**\tIf all was set up successfully, then return true.\n\t*/\n\treturn(Object != NULL);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Set -- Fills a factory with an already completed object.                      *\n *                                                                                             *\n *    This routine is called when a produced object is in placement mode but then placement    *\n *    is suspended. The object must then return to the factory as if it were newly completed   *\n *    and awaiting removal.                                                                    *\n *                                                                                             *\n * INPUT:   object   -- The object to return to the factory.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This will abandon any current object being produced at the factory in order     *\n *             to set the new object into it.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FactoryClass::Set(TechnoClass & object)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tAbandon();\n\tObject = &object;\n\tHouse  = Object->House;\n\tBalance = 0;\n\tSet_Rate(0);\n\tSet_Stage(STEP_COUNT);\n\tIsDifferent = true;\n\tIsSuspended = true;\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Suspend -- Temporarily stop production.                                       *\n *                                                                                             *\n *    This routine will suspend production until a subsequent call to Start() or Abandon().    *\n *    Typical use of this function is when the player puts production on hold or when there    *\n *    is insufficient funds.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was production actually stopped? A false return value indicates that the     *\n *                factory was empty or production was already stopped (or never started).      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Suspend(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (!IsSuspended) {\n\t\tIsSuspended = true;\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Start -- Resumes production after suspension or creation.                     *\n *                                                                                             *\n *    This function will start the production process. It works for newly created factory      *\n *    objects, as well as if production had been suspended previously.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was production started? A false return value means that the factory is       *\n *                empty or there is insufficient credits to begin production.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Start(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif ((Object || SpecialItem) && IsSuspended && !Has_Completed()) {\n\t\tif (House->IsHuman || House->Available_Money() >= Cost_Per_Tick()) {\n\t\t\tint time;\n\n\t\t\tif (Object) {\n\t\t\t\ttime = Object->Class_Of().Time_To_Build(House->Class->House);\n\t\t\t}\n\n\t\t\ttime /= STEP_COUNT;\n\t\t\ttime = Bound(time, 1, 255);\n\n\t\t\tSet_Rate(time);\n\t\t\tIsSuspended = false;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Abandon -- Abandons current construction with money refunded.                 *\n *                                                                                             *\n *    This routine is used when construction is to be abandoned and current money spend is     *\n *    to be refunded. This function effectively clears out this factory of all record of the   *\n *    producing object so that it may either be deleted or started anew with the Set()         *\n *    function.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was an object actually abandoned? A false return value indicates that the    *\n *                factory was not producing any object.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Abandon(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object) {\n\n\t\tif (Object) {\n\t\t\t/*\n\t\t\t**\tRefund all money expended so far, back to the owner of the object under construction.\n\t\t\t*/\n\t\t\tint money = Object->Class_Of().Cost_Of() * Object->House->CostBias;\n\t\t\tHouse->Refund_Money(money - Balance);\n\t\t\tBalance = 0;\n\n\t\t\t/*\n\t\t\t**\tDelete the object under construction.\n\t\t\t*/\n\t\t\tScenarioInit++;\n\t\t\tdelete Object;\n\t\t\tObject = NULL;\n\t\t\tScenarioInit--;\n\t\t}\n\t\tif (SpecialItem) {\n\t\t\tSpecialItem = SPC_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the factory back to the idle and empty state.\n\t\t*/\n\t\tSet_Rate(0);\n\t\tSet_Stage(0);\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Completion -- Fetches the completion step for this factory.                   *\n *                                                                                             *\n *    Use this routine to determine what animation (or completion step) the factory is         *\n *    currently on.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a completion step number between 0 (uncompleted), to STEP_COUNT (completed)*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FactoryClass::Completion(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(Fetch_Stage());\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Has_Completed -- Checks to see if object has completed production.            *\n *                                                                                             *\n *    Use this routine to examine the factory object in order to determine if the associated   *\n *    object has completed production and is awaiting placement.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the associated object to the factory completed and ready for placement?   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Has_Completed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object && Fetch_Stage() == STEP_COUNT) {\n\t\treturn(true);\n\t}\n\tif (SpecialItem && Fetch_Stage() == STEP_COUNT) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Get_Object -- Fetches pointer to object being constructed.                    *\n *                                                                                             *\n *    This routine gets the pointer to the currently constructing object.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object undergoing construction.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * FactoryClass::Get_Object(void) const\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(Object);\n}\n\n\n/***************************************************************************\n * FactoryClass::Get_Special_Item -- gets factory spc prod item            *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:     int the item the factory is currently working on            *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 PWG : Created.                                             *\n *=========================================================================*/\nint FactoryClass::Get_Special_Item(void) const\n{\n\tassert(Factories.ID(this) == ID);\n\n\treturn(SpecialItem);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Cost_Per_Tick -- Breaks entire production cost into manageable chunks.        *\n *                                                                                             *\n *    Use this routine to determine the cost per game \"tick\" to produce the object.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of credits necessary to advance production one game tick.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FactoryClass::Cost_Per_Tick(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object) {\n\t\tint steps = STEP_COUNT - Fetch_Stage();\n\t\tif (steps) {\n\t\t\treturn(Balance / steps);\n\t\t}\n\t\treturn(Balance);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Completed -- Clears factory object after a completed production process.      *\n *                                                                                             *\n *    This routine is called after production completes, and the object produced has been      *\n *    placed into the game. It resets the factory for deletion or starting of new production.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Did any resetting occur? Failure is the result of the factory not having     *\n *                any completed object. An immediate second call to this routine will also     *\n *                yield false.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FactoryClass::Completed(void)\n{\n\tassert(Factories.ID(this) == ID);\n\n\tif (Object && Fetch_Stage() == STEP_COUNT) {\n\t\tObject = NULL;\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\t\tSet_Stage(0);\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\n\tif (SpecialItem && Fetch_Stage() == STEP_COUNT) {\n\t\tSpecialItem = SPC_NONE;\n\t\tIsSuspended = true;\n\t\tIsDifferent = true;\n\t\tSet_Stage(0);\n\t\tSet_Rate(0);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/FACTORY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FACTORY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FACTORY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/26/94                                                     *\n *                                                                                             *\n *                  Last Update : December 26, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FACTORY_H\n#define FACTORY_H\n\n#include\t\"stage.h\"\n\nclass FactoryClass : private StageClass\n{\n\tpublic:\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\n\t\tFactoryClass(void);\n\t\tFactoryClass(NoInitClass const & x) : StageClass(x) {};\n\t\t~FactoryClass(void);\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\tbool Abandon(void);\n\t\tbool Completed(void);\n\t\tbool Has_Changed(void);\n\t\tbool Has_Completed(void);\n\t\tbool Is_Building(void) const {return(Fetch_Rate() != 0);};\n\t\tbool Set(TechnoTypeClass const & object, HouseClass & house);\n\t\tbool Set(int const & type, HouseClass & house);\n\t\tbool Start(void);\n\t\tbool Suspend(void);\n\t\tint Completion(void);\n\t\tTechnoClass * Get_Object(void) const;\n\t\tint Get_Special_Item(void) const;\n\t\tvoid AI(void);\n\t\tvoid Set(TechnoClass & object);\n\t\tHouseClass * Get_House(void) {return(House);};\n\t\tchar const * Name(void) {return(\"Factory\");}\n\t\tbool Is_Blocked(void) {return IsBlocked;}\n\t\tvoid Set_Is_Blocked(bool set) {IsBlocked = set;}\n\n\t\t/*\n\t\t** Added for debugging / testing. ST - 8/23/2019 3:52PM\n\t\t*/\n\t\tvoid Force_Complete(void);\n\n\t\t/*\n\t\t**\tThis flag is used to maintain the pool of factory class objects. If the object has\n\t\t**\tbeen allocated, then this flag is true. Otherwise, the object is free to be\n\t\t**\tallocated.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\tenum StepCountEnum {\n\t\t\tSTEP_COUNT=54\t\t\t// Number of steps to break production down into.\n\t\t};\n\tprotected:\n\n\t\tint Cost_Per_Tick(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIf production is temporarily suspended, then this flag will be true. A factory\n\t\t**\tis suspended when it is first created, when production has completed, and when\n\t\t**\texplicitly instructed to Suspend() production. Suspended production is not\n\t\t**\tabandoned. It may be resumed with a call to Start().\n\t\t*/\n\t\tunsigned IsSuspended:1;\n\n\t\t/*\n\t\t**\tIf the AI process detected that the production process has advanced far enough\n\t\t**\tthat a change in the building animation would occur, this flag will be true.\n\t\t**\tExamination of this flag (through the Has_Changed function) allows intelligent\n\t\t**\tupdating of any production graphic.\n\t\t*/\n\t\tunsigned IsDifferent:1;\n\n\t\t/*\n\t\t** The exit from the factory is blocked by something, which means a unit is prevented from exiting after construction\n\t\t** has completed. ST - 2/25/2020 11:29AM\n\t\t*/\n\t\tunsigned IsBlocked:1;\n\n\t\t/*\n\t\t**\tThis records the balance due on the current production item. This value will\n\t\t**\tbe reduced as production proceeds. It will reach zero the moment production has\n\t\t**\tfinished. Using this method ensures that the total production cost will be EXACT\n\t\t**\tregardless of the number of installment payments that are made.\n\t\t*/\n\t\tint Balance;\n\t\tint OriginalBalance;\n\n\t\t/*\n\t\t**\tThis is the object that is being produced. It is held in a state of limbo while\n\t\t**\tundergoing production. Since the object is created at the time production is\n\t\t**\tstarted, it is always available when production completes.\n\t\t*/\n\t\tTechnoClass * Object;\n\n\t\t/*\n\t\t**\tIf the factory is not producing an object and is instead producing\n\t\t** a special item, then special item will be set.\n\t\t*/\n\t\tint SpecialItem;\n\n\t\t/*\n\t\t** The factory has to be doing production for one house or another.\n\t\t** The house pointer will point to whichever house it is being done\n\t\t** for.\n\t\t*/\n\t\tHouseClass  * House;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[32];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/FAKESOCK.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/*************************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : FAKESOCK.H                                         *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : August 6th, 1996                                   *\n *                                                                                   *\n *                  Last Update : August 6th, 1996 [ST]                              *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Stub replacement for the Winsock interface in DOS                                *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef WIN32\n\nclass TcpipManagerClass {\n\n\tpublic:\n\t\tinline BOOL Get_Connected(void) {return (FALSE);}\n\n};\n\nextern TcpipManagerClass\tWinsock;\n#endif\n"
  },
  {
    "path": "REDALERT/FIELD.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : FIELD.CPP                                *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 22, 1996 [PWG]                     *\n *                                                                         *\n *  Actual member function for the field class.                            *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include <string.h>\n#include \"field.h\"\n\nFieldClass::FieldClass(char *id, char data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_CHAR;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned char data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_CHAR;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, short data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_SHORT;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned short data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_SHORT;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, long data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_LONG;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, unsigned long data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_UNSIGNED_LONG;\n\tSize\t\t= sizeof(data);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, &data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, char *data)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_STRING;\n\tSize\t\t= (unsigned short)(strlen(data)+1);\n\tData\t\t= new char[Size];\n\tmemcpy(Data, data, Size);\n\tNext\t\t= NULL;\n}\n\nFieldClass::FieldClass(char *id, void *data, int length)\n{\n\tstrncpy(ID, id, sizeof(ID));\n\tDataType = TYPE_CHUNK;\n\tSize\t\t= (unsigned short)length;\n\tData\t\t= new char[Size];\n\tmemcpy(Data, data, Size);\n\tNext\t\t= NULL;\n}\n\n\n/**************************************************************************\n * PACKETCLASS::HOST_TO_NET_FIELD -- Converts host field to net format    *\n *                                                                        *\n * INPUT:\t\tFIELD \t* to the data field we need to convert\t\t\t\t  *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid FieldClass::Host_To_Net(void)\n{\n\t//\n\t// Before we convert the data type, we should convert the actual data\n\t//  sent.\n\t//\n\tswitch (DataType) {\n\t\tcase TYPE_CHAR:\n\t\tcase TYPE_UNSIGNED_CHAR:\n\t\tcase TYPE_STRING:\n\t\tcase TYPE_CHUNK:\n\t\t\tbreak;\n\n\t\tcase TYPE_SHORT:\n\t\tcase TYPE_UNSIGNED_SHORT:\n\t\t\t*((unsigned short *)Data) = htons(*((unsigned short *)Data));\n\t\t\tbreak;\n\n\t\tcase TYPE_LONG:\n\t\tcase TYPE_UNSIGNED_LONG:\n\t\t\t*((unsigned long *)Data) = htonl(*((unsigned long *)Data));\n\t\t\tbreak;\n\n\t\t//\n\t\t// Might be good to insert some type of error message here for unknown\n\t\t//   datatypes -- but will leave that for later.\n\t\t//\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\t//\n\t// Finally convert over the data type and the size of the packet.\n\t//\n\tDataType = htons(DataType);\n\tSize \t \t= htons(Size);\n}\n/**************************************************************************\n * PACKETCLASS::NET_TO_HOST_FIELD -- Converts net field to host format    *\n *                                                                        *\n * INPUT:\t\tFIELD \t* to the data field we need to convert\t\t\t\t  *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid FieldClass::Net_To_Host(void)\n{\n\t//\n\t// Convert the variables to host order.  This needs to be converted so\n\t// the switch statement does compares on the data that follows.\n\t//\n\tSize \t \t= ntohs(Size);\n\n\tDataType = ntohs(DataType);\n\n\t//\n\t// Before we convert the data type, we should convert the actual data\n\t//  sent.\n\t//\n\tswitch (DataType) {\n\t\tcase TYPE_CHAR:\n\t\tcase TYPE_UNSIGNED_CHAR:\n\t\tcase TYPE_STRING:\n\t\tcase TYPE_CHUNK:\n\t\t\tbreak;\n\n\t\tcase TYPE_SHORT:\n\t\tcase TYPE_UNSIGNED_SHORT:\n\t\t\t*((unsigned short *)Data) = ntohs(*((unsigned short *)Data));\n\t\t\tbreak;\n\n\t\tcase TYPE_LONG:\n\t\tcase TYPE_UNSIGNED_LONG:\n\t\t\t*((unsigned long *)Data) = ntohl(*((unsigned long *)Data));\n\t\t\tbreak;\n\n\t\t//\n\t\t// Might be good to insert some type of error message here for unknown\n\t\t//   datatypes -- but will leave that for later.\n\t\t//\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/FIELD.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : FIELD.H                                  *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 22, 1996 [PWG]                     *\n *                                                                         *\n * This module takes care of maintaining the field list used to process    *\n * packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef __FIELD_H\n#define __FIELD_H\n\n#include <windows.h>\n#include <winsock.h>\n\n#define FIELD_HEADER_SIZE\t(sizeof(FieldClass) - (sizeof(void *) * 2))\n\n#define TYPE_CHAR\t\t\t\t\t\t1\n#define TYPE_UNSIGNED_CHAR\t\t\t2\n#define TYPE_SHORT\t\t\t\t\t3\n#define TYPE_UNSIGNED_SHORT\t\t4\n#define TYPE_LONG\t\t\t\t\t\t5\n#define TYPE_UNSIGNED_LONG\t\t\t6\n#define TYPE_STRING\t\t\t\t\t7\n#define TYPE_CHUNK\t\t\t\t\t20\n\nclass PacketClass;\n\nclass FieldClass {\n\n\tpublic:\n\t\tfriend class PacketClass;\n\t\t//\n\t\t// Define constructors to be able to create all the different kinds\n\t\t// of fields.\n\t\t//\n\t\tFieldClass(void) {};\n\t\tFieldClass(char *id, char data);\n\t\tFieldClass(char *id, unsigned char data);\n\t\tFieldClass(char *id, short data);\n\t\tFieldClass(char *id, unsigned short data);\n\t\tFieldClass(char *id, long data);\n\t\tFieldClass(char *id, unsigned long data);\n\t\tFieldClass(char *id, char *data);\n\t\tFieldClass(char *id, void *data, int length);\n\n\t\tvoid Host_To_Net(void);\n\t\tvoid Net_To_Host(void);\n\n\tprivate:\n\t\tchar\t\t\t\tID[4];\t\t\t\t// id value of this field\n\t\tunsigned short\tDataType;\t\t\t// id of the data type we are using\n\t\tunsigned short Size;\t\t\t\t\t// size of the data portion of this field\n\t\tvoid  \t\t\t*Data;\t\t\t\t// pointer to the data portion of this field\n\t\tFieldClass\t\t*Next;\t\t\t\t// pointer to the next field in the field list\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/FILEPCX.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : iff                                      *\n;*                                                                         *\n;*                    File Name : FILEPCX.H                                *\n;*                                                                         *\n;*                   Programmer : Julio R. Jerez                           *\n;*                                                                         *\n;*                   Start Date : May 2, 1995                              *\n;*                                                                         *\n;*                  Last Update : May 2, 1995   [JRJ]                      *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);\n;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff); \n;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*\n;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/\n#include <gbuffer.h>\n#include <string.h>\n#include <buffer.h>\n#include\t<file.h>\n\n#ifndef PCX_H\n#define PCX_H\n\n\ntypedef\tstruct {\n\t\t\t\t\t\t  char\tred ;\n\t\t\t\t\t\t  char\tgreen ;\n\t\t\t\t\t\t  char\tblue ;\n\t\t\t\t\t} RGB ;\n\ntypedef\tstruct\t{\n\t\t\t\t\t\t  char      id ;\n\t\t\t\t\t\t  char\t   version ;\n\t\t\t\t\t\t  char\t   encoding ;\n\t\t\t\t\t\t  char\t   pixelsize ;\n\t\t\t\t\t\t  short \t   x ;\n\t\t\t\t\t\t  short\t\ty ;\n\t\t\t\t\t\t  short     width ;\n\t\t\t\t\t\t  short\t\theight ;\n\t\t\t\t\t\t  short \t   xres ;\n\t\t\t\t\t\t  short\t\tyres ;\n\t\t\t\t\t\t  RGB       ega_palette [ 16 ] ;\n\t\t\t\t\t\t  char\t   nothing ;\n\t\t\t\t\t\t  char      color_planes ;\n\t\t\t\t\t\t  short \t\tbyte_per_line ;\n\t\t\t\t\t\t  short \t \tpalette_type ;\n\t\t\t\t\t\t  char\t   filler [ 58 ] ;\n\t\t\t\t\t\t} PCX_HEADER ;\n\nGraphicBufferClass* Read_PCX_File (char* name, char* palette= NULL,void *buff=NULL, long size=0);\nGraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette= NULL) ;\nint Write_PCX_File (char* name, GraphicViewPortClass& pic, unsigned char* palette );\n\n#endif\n"
  },
  {
    "path": "REDALERT/FINDPATH.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FINDPATH.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FINDPATH.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : May 25, 1995   [PWG]                                         *\n *                                                                                             *\n * The path algorithm works by following a LOS path to the target. If it                       *\n * collides with an impassable spot, it uses an Edge following routine to                      *\n * get around it. The edge follower moves along the edge in a clockwise or                     *\n * counter clockwise fashion until finding the destination spot. The                           *\n * destination is determined by Find_Path. It is the first passable that                       *\n * can be reached (so it will handle the doughnut case, where there is                         *\n * a passable in the center of an unreachable area).                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Clear_Path_Overlap -- clears the path overlap list                                        *\n *   Find_Path -- Find a path from point a to point b.                                         *\n *   Find_Path_Cell -- Finds a given cell on a specified path                                  *\n *   Follow_Edge -- Follow an edge to get around an impassable spot.                           *\n *   FootClass::Unravel_Loop -- Unravels a loop in the movement path                           *\n *   Get_New_XY -- Get the new x,y based on current position and direction.                    *\n *   Optimize_Moves -- Optimize the move list.                                                 *\n *   Set_Path_Overlap -- Sets the overlap bit for given cell                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n//#include\t<string.h>\n\n/*\n**\tWhen an edge search is started, it can be performed CLOCKwise or\n**\tCOUNTERCLOCKwise direction.\n*/\n#define\tCLOCK\t\t\t\t(FacingType)1\t// Clockwise.\n#define\tCOUNTERCLOCK\t(FacingType)-1\t// Counterclockwise.\n\n/*\n**\tIf defined, diagonal moves are allowed, else no diagonals.\n*/\n#define\tDIAGONAL\n\n/*\n**\tThis is the marker to signify the end of the path list.\n*/\n#define\tEND\t\t\tFACING_NONE\n\n/*\n**\t\"- 1\" test for bit manipulation.\n*/\n#define TEST\n\n/*\n**\tIf memory is more important than speed, set this define to\n**\ttrue. It will then perform intermediate optimizations to get the most\n**\tmilage out of a limited movement list staging area. If this value\n**\tis true then it figures paths a bit more intelligently.\n*/\n#define\tSAVEMEM\t\ttrue\n\n/*\n**\tModify this macro so that given two cell values, it will return\n**\ta value between 0 and 7, with 0 being North and moving\n**\tclockwise (just like map degrees).\n*/\n#define\tCELL_FACING(a, b)\t\tDir_Facing(::Direction((a), (b)))\n\n\n/*-------------------------------------------------------------------------*/\n/*\n**\tCells values are really indexes into the 'map'. The following value is\n**\tthe X width of the map.\n*/\n#define\tMODULO\tMAP_CELL_W\n\n/*\n**\tMaximum lookahead cells. Twice this value in bytes will be\n**\treserved on the stack. The smaller this number, the faster the processing.\n*/\n#define MAX_MLIST_SIZE\t\t300\n#define THREAT_THRESHOLD\t5\n\n\n#define\tMAX_PATH_EDGE_FOLLOW\t400\n\n#ifdef NEVER\ntypedef enum {\n\tFACING_N,\t\t\t// North\n\tFACING_NE,\t\t\t// North-East\n\tFACING_E,\t\t\t// East\n\tFACING_SE,\t\t\t// South-East\n\tFACING_S,\t\t\t// South\n\tFACING_SW,\t\t\t// South-West\n\tFACING_W,\t\t\t// West\n\tFACING_NW,\t\t\t// North-West\n\n\tFACING_COUNT\t\t\t// Total of 8 directions (0..7).\n} FacingType;\n#endif\n\n\n/*-------------------------------------------------------------------------*/\n//static bool DrawPath;\n\ninline FacingType Opposite(FacingType face)\n{\n\treturn( (FacingType) (face ^ 4));\n}\n\n\ninline static FacingType Next_Direction(FacingType facing, FacingType dir)\n{\n\tfacing = facing + dir;\n\t#ifndef DIAGONAL\n\t\tfacing = (FacingType)(facing & 0x06);\n\t#endif\n\treturn(facing);\n}\n\n/*=========================================================================*/\n/* Define a couple of variables which are private to the module they are   */\n/*      declared in.                                                       */\n/*=========================================================================*/\nstatic unsigned long MainOverlap[MAP_CELL_TOTAL/32];\t\t// overlap list for the main path\nstatic unsigned long LeftOverlap[MAP_CELL_TOTAL/32];\t\t// overlap list for the left path\nstatic unsigned long RightOverlap[MAP_CELL_TOTAL/32];\t// overlap list for the right path\n\n\n//static CELL MoveMask = 0;\nstatic CELL DestLocation;\nstatic CELL StartLocation;\n\n/***************************************************************************\n * Point_Relative_To_Line -- Relation between a point and a line           *\n *                                                                         *\n *      If a point is on a line then the following function holds true:    *\n *      (x - x2)(z1 - z2) = (z - z2)(x1 - x2) given x,z a point on the     *\n *      line (x1,z1),(x2,z2).                                              *\n *      If the right side is > then the left side then the point is on one *\n *      side of the line and if the right side is < the the left side, then*\n *      the point is on the other side of the line.  By subtracting one side*\n *      from the other we can determine on what side (if any) the point is on*\n *      by testing the side of the resulting subtraction.                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      int   x    - x pos of point.                                       *\n *      int   z    - z pos of point.                                       *\n *      int   x1 - x pos of first end of line segment.                     *\n *      int   z1 - z pos of first end of line segment.                     *\n *      int   x1 - x pos of second end of line segment.                    *\n *      int   z1 - z pos of second end of line segment.                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   Assuming (x1,z1) is north, (x2,z2) is south:                          *\n *       0 : point is on line.                                             *\n *       > 0 : point is east of line.                                      *\n *       < 0 : point is west of line.                                      *\n *                                                                         *\n * WARNINGS:                                                               *\n *    Remember that int means that assumes 16 bits of precision.           *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/28/1994 SKB : Created.                                             *\n *=========================================================================*/\nint Point_Relative_To_Line(int x, int z, int x1, int z1, int x2, int z2)\n{\n\treturn((((long)x - (long)x2) * ((long)z1 - (long)z2)) - (((long)z - (long)z2) * ((long)x1 - (long)x2)));\n}\n\n\n/***************************************************************************\n * FootClass::Unravel_Loop -- Unravels a loop in the movement path         *\n *                                                                         *\n * While in the midst of the Follow Edge logic, it is possible (due to the *\n * fact that we support diagonal movement) to begin looping around a       *\n * column of some type.  The Unravel loop function will scan backward      *\n * through the list and fixup the path to try to prevent the loop.         *\n *                                                                         *\n * INPUT:      path   -   pointer to the generated path so we can pull the *\n *                         commands out of it.                             *\n *               cell   -   the cell we tried to enter that generated the  *\n *                        double overlap condition.                        *\n *               dir    -   the direction we tried to enter from when we   *\n *                        generated the double overlap condition           *\n *               startx -   the start x position of this path segment      *\n *               starty - the start y position of this path segment        *\n *               destx    - the dest x position for this path segment      *\n *               desty    - the dest y position for this path segment      *\n *                                                                         *\n * OUTPUT:      TRUE    - loop has been successfully unravelled             *\n *               FALSE  - loop can not be unravelled so abort follow edge  *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Unravel_Loop(PathType * path, CELL &cell, FacingType &dir, int sx, int sy, int dx, int dy, MoveType threshhold)\n{\n\t/*\n\t** Walk back to the actual cell before we advanced our position\n\t*/\n\tFacingType\tcurr_dir\t= dir;\n\tCELL\t\t\tcurr_pos = Adjacent_Cell(cell, Opposite(curr_dir));\n\tint\t\t\tidx\t\t= path->Length;\t\t\t// start at the last position\n\tFacingType\t* list\t\t= &path->Command[idx-1];\t// point to the last command\n\tint\t\t\tcheckx;\n\tint\t\t\tchecky;\n\tint\t\t\tlast_was_line\t= false;\n\n\t/*\n\t** loop backward through the list searching for a point that is\n\t** on the line.  If the point was a diagonal move then adjust\n\t** it.\n\t*/\n\twhile (idx) {\n\t\tcheckx\t\t= Cell_X(curr_pos);\n\t\tchecky\t\t= Cell_Y(curr_pos);\n\n\t\tif (!Point_Relative_To_Line(checkx, checky, sx, sy, dx, dy) || last_was_line) {\n\n\t\t\t/*\n\t\t\t** We have now found a point on the line.  Now we must check to see\n\t\t\t** if we left the line on a diagonal.  If we did then we need to fix\n\t\t\t** it up.\n\t\t\t*/\n\t\t\tif (curr_dir & 1 && curr_pos != path->LastFixup) {\n\t\t\t\tcell \t\t\t\t = curr_pos;\n\t\t\t\tdir  \t\t\t\t = *(list-1);\n\t\t\t\tpath->Length\t = idx;\n\t\t\t\tpath->LastFixup = curr_pos;\n\t\t\t\treturn(true);\n\t\t\t}\n\n\t\t\tlast_was_line = !last_was_line;\n\t\t}\n\n\t\t/*\n\t\t** Since this cell will not be in the list, then pull out its cost\n\t\t*/\n\t\tpath->Cost -= Passable_Cell(curr_pos, *list, -1, threshhold);\n\n\t\t/*\n\t\t** Remove this cells flag from the overlap list for the path\n\t\t*/\n#ifdef TEST\n\t\tpath->Overlap[curr_pos >> 5] &= ~(1 << ((curr_pos & 31)));\n#else\n\t\tpath->Overlap[curr_pos >> 5] &= ~(1 << ((curr_pos & 31) - 1));\n#endif\n\n\t\t/*\n\t\t** Adjust to the next list position and direction.\n\t\t*/\n\t\tcurr_dir = *list--;\n\t\tcurr_pos\t= Adjacent_Cell(curr_pos, Opposite(curr_dir));\n\t\tidx--;\n\t}\n\n\t/*\n\t** If we can't modify the list to eliminate the problem, then we have\n\t** a larger problem in that we have deleted all of the cells in the\n\t** list.\n\t*/\n\treturn(false);\n}\n\n\n/***************************************************************************\n * Register_Cell -- registers a cell on our path and check for backtrack   *\n *                                                                         *\n * This function adds a new cell to our path.  If the cell has already     *\n * been recorded as part of our path, then this function moves back down   *\n * the list truncating it at the point we registered that cell.  This      *\n * function will eliminate all backtracking from the list.                 *\n *                                                                         *\n * INPUT:      long   * list - the list to set the overlap bit for         *\n *               CELL  cell    - the cell to mark on the overlap list      *\n *                                                                         *\n * OUTPUT:     BOOL - TRUE if bit has been set, FALSE if bit already set   *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/23/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Register_Cell(PathType * path, CELL cell, FacingType dir, int cost, MoveType threshhold)\n{\n\tFacingType  * list;\n\tint \tpos  = cell >> 5;\n#ifdef TEST\n\tint\tbit  = (cell & 31);\n#else\n\tint\tbit  = (cell & 31) - 1;\n#endif\n\n\t/*\n\t** See if this point has already been registered as on the list.  If so\n\t** we need to truncate the list back to this point and register the\n\t** new direction.\n\t*/\n\tif (path->Overlap[pos] & (1 << bit)) {\n\t\t/*\n\t\t** If this is not a case of immediate back tracking then handle\n\t\t** by searching the list to see what we find.  However is this is\n\t\t** an immediate back track, then pop of the last direction\n\t\t** and unflag the cell we are in (not the cell we are moving to).\n\t\t** Note: That we do not check for a zero length cell because we\n\t\t** could not have a duplicate unless there are cells in the list.\n\t\t*/\n\n\t\tif (path->Command[path->Length - 1] == Opposite(dir)) {\n\t\t\tCELL pos = Adjacent_Cell(cell, Opposite(dir));\n#ifdef TEST\n\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31)));\n#else\n\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31) - 1));\n#endif\n\t\t\tpath->Length--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If this overlap is in the same place as we had our last overlap\n\t\t\t** then we are in a loop condition.  We need to signify that we\n\t\t\t** cannot register this cell.\n\t\t\t*/\n\t\t\tif (path->LastOverlap == cell) {\n\t\t\t\treturn(false);\n\t\t\t} else {\n\t\t\t\tpath->LastOverlap = cell;\n\t\t\t}\n\n\t\t\tCELL pos \t  \t= path->Start;\n\t\t\tint newlen\t\t= 0;\n\t\t\tint idx \t\t   = 0;\n\t\t\tlist\t\t      = path->Command;\n\n\t\t\t/*\n\t\t\t** Note that the cell has to be in this list, so theres no sense\n\t\t\t** in checking whether we found it (famous last words).\n\t\t\t**\n\t\t\t** PWG 8/16/95 - However there is no sense searching the list if\n\t\t\t**               the cell we have overlapped on is the cell we\n\t\t\t**               started in.\n\t\t\t*/\n\n\t\t\tif (pos != cell) {\n\t\t\t\twhile (idx < path->Length) {\n\t\t\t\t\tpos = Adjacent_Cell(pos, *list);\n\t\t\t  \t\tif (pos == cell) {\n\t\t\t\t\t\tidx++;\n\t\t\t\t\t\tlist++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tidx++;\n\t\t\t\t\tlist++;\n\t\t\t\t}\n\t\t\t\tnewlen = idx;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Now we are pointing at the next command in the list.  From here on\n\t\t\t** out we need to unmark the fact that we have entered these cells and\n\t\t\t** adjust the cost of our path to reflect that we have not entered\n\t\t\t** then.\n\t\t\t*/\n\t\t\twhile (idx < path->Length) {\n\t\t\t\tpos\t\t\t= Adjacent_Cell(pos, *list);\n\t\t\t\tpath->Cost -= Passable_Cell(pos, *list, -1, threshhold);\n#ifdef TEST\n\t\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31)));\n#else\n\t\t\t\tpath->Overlap[pos >> 5] &= ~(1 << ((pos & 31) - 1));\n#endif\n\t\t\t\tidx++;\n\t\t\t\tlist++;\n\t\t\t}\n\t\t\tpath->Length = newlen;\n\t\t}\n\t} else {\n\t\t/*\n\t\t** Now we need to register the new direction, updating the cell structure\n\t\t** and the cost.\n\t\t*/\n\t\tint cpos \t\t\t\t= path->Length++;\n\t\tpath->Command[cpos]\t= dir;\t\t\t// save of the direction we moved\n\t\tpath->Cost \t\t\t  += cost;\t\t\t// figure new cost for cell\n\t\tpath->Overlap[pos]  |= (1 << bit);\t// mark the we have entered point\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Find_Path -- Find a path from point a to point b.                                           *\n *                                                                                             *\n * INPUT:      int source x,y, int destination x,y, char *final moves                          *\n *             array to store moves, int maximum moves we may attempt                          *\n *                                                                                             *\n * OUTPUT:     int number of moves it took (IMPOSSIBLE_MOVES if we could                       *\n *             not reach the destination                                                       *\n *                                                                                             *\n * WARNINGS:   This algorithm assumes that the target is NOT situated                          *\n *             inside an impassable. If this case may arise, the do-while                      *\n *             statement inside the inner while (true) must be changed                         *\n *             to include a check to se if the next_x,y is equal to the                        *\n *             dest_x,y. If it is, then return(IMPOSSIBLE_MOVES).                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *=============================================================================================*/\nPathType * FootClass::Find_Path(CELL dest, FacingType * final_moves, int maxlen, MoveType threshhold)\n{\n\tCELL\t\t\t\t\tsource = Coord_Cell(Coord);\t\t// Source expressed as cell\n\tstatic PathType\tpath;\t\t\t\t\t\t\t\t\t\t// Main path control.\n\tCELL\t\t\t\t\tnext;\t\t\t\t\t\t\t\t\t\t// Next cell to enter\n\tCELL\t\t\t\t\tstartcell;\t\t\t\t\t\t\t\t// Cell we started in\n\tFacingType\t\t\tdirection;\t\t\t\t\t\t\t\t// Working direction of look ahead.\n\tFacingType\t\t\tnewdir;\t\t\t\t\t\t\t\t\t// Tentative facing value.\n\n\tbool\t\t\t\t\tleft=false, \t\t\t\t\t\t\t// Was leftward path legal?\n\t\t\t\t\t\t\tright=false;\t\t\t\t\t\t\t// Was rightward path legal?\n\n\tint\t\t\t\t\tlen;\t\t\t\t\t\t\t\t\t\t// Length of detour command list.\n\tint\t\t\t\t\tunit_threat;\t\t\t\t\t\t\t// Calculated unit threat rating\n\tint\t\t\t\t\tcost;\t\t\t\t\t\t\t\t\t\t// Cost to enter the square\n\tFacingType\t\t\tmoves_left[MAX_MLIST_SIZE+2], \t// Counterclockwise move list.\n\t\t\t\t\t\t\tmoves_right[MAX_MLIST_SIZE+2];\t// Clockwise move list.\n\tPathType\t\t\t\tpleft,pright;\t\t\t\t\t\t\t// Path control structures.\n\tPathType *\t\t\twhich;\t\t\t\t\t\t\t\t\t// Which path to actually use.\n\tint\t\t\t\t\tthreat = 0;\t\t\t//\n\tint\t\t\t\t\tthreat_stage = 0; //These weren't initialized. ST - 1/8/2019 12:03PM\n\n\n\t/*\n\t** If we have been provided an illegal place to store our final moves\n\t** then forget it.\n\t*/\n\tif (!final_moves) return(NULL);\n\n\tBStart(BENCH_FINDPATH);\n\n\tPathCount++;\n\n\tif (Team && Team->Class->IsRoundAbout) {\n\t\tunit_threat\t\t\t= (Team) ? Team->Risk : Risk();\n\t\tthreat_stage\t\t= 0;\n\t\tthreat\t\t\t\t= 0;\n\t} else {\n\t\tunit_threat = threat = -1;\n\t}\n\n\tStartLocation = source;\n\tDestLocation = dest;\n\n\t/*\n\t** Initialize the path structure so that we can keep track of the\n\t** path.\n\t*/\n\tpath.Start\t\t\t= source;\n\tpath.Cost\t\t\t= 0;\n\tpath.Length \t\t= 0;\n\tpath.Command \t\t= final_moves;\n\tpath.Command[0] \t= END;\n\tpath.Overlap\t\t= MainOverlap;\n\tpath.LastOverlap\t= -1;\n\tpath.LastFixup\t\t= -1;\n\n\tmemset(path.Overlap, 0, sizeof(MainOverlap));\n\n\t/*\n\t** Clear the over lap list and then make sure that our starting position is marked\n\t** on the overlap list.  (Otherwise the harvesters will drive in circles... )\n\t*/\n#ifdef TEST\n\tpath.Overlap[source >> 5] |= (1 << ((source & 31)));\n#else\n\tpath.Overlap[source >> 5] |= (1 << ((source & 31) - 1));\n#endif\n\n\tstartcell \t\t\t= source;\n\n\t/*\n\t**\tAccount for trailing end of list command, so reduce the maximum\n\t**\tallowed legal commands to reflect this.\n\t*/\n\tmaxlen--;\n\n\t/*\n\t**\tAs long as there is room to put commands in the movement command list,\n\t** then put commands in it.  We build the path using the following\n\t** methodology.\n\t**\n\t** 1. Scan through the desired straight line path until we either hit an\n\t**    impassable or have created a valid path.\n\t**\n\t** 2. If we have hit an impassable, walk through the impassable to make\n\t**    sure that there is a passable on the other side.  If there is not\n\t**    and we can not change the impassable, then this list is dead.\n\t**\n\t** 3. Walk around the impassable on both the left and right edges and\n\t**    take the shorter of the two paths.\n\t**\n\t** 4. Taking the new location as our start location start again with\n\t**    step #1.\n\t*/\n\twhile (path.Length < maxlen) {\n\ntop_of_list:\n\t\t/*\n\t\t**\tHave we reached the destination already?  If so abort any further\n\t\t**\tcommand building.\n\t\t*/\n\t\tif (startcell == dest) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tFind the absolute correct direction to reach the next straight\n\t\t** line cell and what cell it is.\n\t\t*/\n\t\tdirection\t= CELL_FACING(startcell, dest);\n\t\tnext\t\t\t= Adjacent_Cell(startcell, direction);\n\n\t\t/*\n\t\t**\tIf we can move here, then make this our next move.\n\t\t*/\n\t\tcost = Passable_Cell(next, direction, threat, threshhold);\n\t\tif (cost) {\n\t\t\tRegister_Cell(&path, next, direction, cost, threshhold);\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tIf the impassable location is actually the destination,\n\t\t\t**\tthen stop here and consider this \"good enough\".\n\t\t\t*/\n\t\t\tif (next == dest) break;\n\n\t\t\t/*\n\t\t\t**\tWe could not move to the next cell, so follow through the\n\t\t\t**\timpassable until we find a passable spot that can be reached.\n\t\t\t** Once we find a passable, figure out the shortest path to it.\n\t\t\t** Since we have variable passable conditions this is not as\n\t\t\t** simple as it used to be.  The limiter loop below allows us to\n\t\t\t** step through ten doughnuts before we give up.\n\t\t\t*/\n\t\t\tfor (int limiter = 0; limiter < 5; limiter++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGet the next passable position by zipping through the\n\t\t\t\t** impassable positions until a passable position is found\n\t\t\t\t**\tor the destination is reached.\n\t\t\t\t*/\n\t\t\t\tfor (;;) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove one step closer toward destination.\n\t\t\t\t\t*/\n\t\t\t\t\tnewdir\t= CELL_FACING(next, dest);\n\t\t\t\t\tnext\t\t= Adjacent_Cell(next, newdir);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the cell is passable then we have been completely\n\t\t\t\t\t** successful.  If the cell is not passable then continue.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Passable_Cell(next, FACING_NONE, threat, threshhold)) {\n//\t\t\t\t\tif ((Passable_Cell(next, FACING_NONE, threat, threshhold)) || (next == dest)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf we reached destination while in this loop, we\n\t\t\t\t\t**\tknow that either the destination is impassible (if\n\t\t\t\t\t**\twe are ignoring) or that we need to up our threat\n\t\t\t\t\t** tolerance and try again.\n\t\t\t\t\t*/\n\t\t\t\t\tif (next == dest) {\n\t\t\t\t\t\tif (threat != -1) {\n\t\t\t\t\t\t\tswitch (threat_stage++) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tthreat = unit_threat >> 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tthreat += unit_threat;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tthreat = -1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgoto top_of_list;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgoto end_of_list;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to find a path to the passable position by following\n\t\t\t\t**\tthe edge of the blocking object in both CLOCKwise and\n\t\t\t\t**\tCOUNTERCLOCKwise fashions.\n\t\t\t\t*/\n\t\t\t\tint follow_len = maxlen + (maxlen >> 1);\n\n\t\t\t\tMem_Copy(&path, &pleft, sizeof(PathType));\n\t\t\t\tpleft.Command \t= &moves_left[0];\n\t\t\t\tpleft.Overlap \t= LeftOverlap;\n\t\t\t\tMem_Copy(path.Command, pleft.Command, path.Length);\n\t\t\t\tMem_Copy(path.Overlap, pleft.Overlap, sizeof(LeftOverlap));\n\n\t\t\t\t// MBL 09.30.2019: We hit a runtime bounds crash where END (-1 / 0xFF) was being poked into +1 just past the end of the moves_right[] array;\n\t\t\t\t// The FacingType moves_left[] and moves_right[] arrays already have MAX_MLIST_SIZE+2 as their size, which may have been a previous attempted fix;\n\t\t\t\t// We are now passing MAX_MLIST_SIZE, since the sizeof calculations included the +2 buffering;\n\t\t\t\t#if 0\n\t\t\t\tleft = Follow_Edge(startcell, next, &pleft, COUNTERCLOCK, direction, threat, threat_stage, sizeof(moves_left)/sizeof(moves_left[0]), threshhold);\n//\t\t\t\tleft = Follow_Edge(startcell, next, &pleft, COUNTERCLOCK, direction, threat, threat_stage, follow_len, threshhold);\n\t\t\t\t#endif\n\t\t\t\tleft = Follow_Edge(startcell, next, &pleft, COUNTERCLOCK, direction, threat, threat_stage, MAX_MLIST_SIZE, threshhold);\n\n\n\t\t\t\tif (left) {\n\t\t\t\t\tfollow_len = min(maxlen, pleft.Length + (pleft.Length >> 1));\n\t\t\t\t}\n\n\t\t\t\tMem_Copy(&path, &pright, sizeof(PathType));\n\t\t\t\tpright.Command = &moves_right[0];\n\t\t\t\tpright.Overlap = RightOverlap;\n\t\t\t\tMem_Copy(path.Command, pright.Command, path.Length);\n\t\t\t\tMem_Copy(path.Overlap, pright.Overlap, sizeof(RightOverlap));\n\n\t\t\t\t// MBL 09.30.2019: We hit a runtime bounds crash where END (-1 / 0xFF) was being poked into +1 just past the end of the moves_right[] array;\n\t\t\t\t// The FacingType moves_left[] and moves_right[] arrays already have MAX_MLIST_SIZE+2 as their size, which may have been a previous attempted fix;\n\t\t\t\t// We are now passing MAX_MLIST_SIZE, since the sizeof calculations included the +2 buffering;\n\t\t\t\t#if 0\n\t\t\t\tright = Follow_Edge(startcell, next, &pright, CLOCK, direction, threat, threat_stage, sizeof(moves_right)/sizeof(moves_right[0]), threshhold);\n//\t\t\t\tright = Follow_Edge(startcell, next, &pright, CLOCK, direction, threat, threat_stage, follow_len, threshhold);\n\t\t\t\t#endif\n\t\t\t\tright = Follow_Edge(startcell, next, &pright, CLOCK, direction, threat, threat_stage, MAX_MLIST_SIZE, threshhold);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf we could find a path, break from this loop. Otherwise this\n\t\t\t\t**\tmeans that we have found a \"hole\" of passable terrain that\n\t\t\t\t**\tcannot be reached by normal means. Scan forward looking for\n\t\t\t\t**\tthe other side of the \"doughnut\".\n\t\t\t\t*/\n\t\t\t\tif (left || right) break;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no path can be found to the intermediate cell, then\n\t\t\t\t**\tpresume we have found a doughnut of some sort. Scan\n\t\t\t\t**\tforward until the next impassable is found and then\n\t\t\t\t**\tprocess this loop again.\n\t\t\t\t*/\n\t\t\t\tdo {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf we reached destination while in this loop, we\n\t\t\t\t\t**\tknow that either the destination is impassible (if\n\t\t\t\t\t**\twe are ignoring) or that we need to up our threat\n\t\t\t\t\t** tolerance and try again.\n\t\t\t\t\t*/\n\t\t\t\t\tif (next == dest) {\n\t\t\t\t\t\tif (threat != -1) {\n\t\t\t\t\t\t\tswitch (threat_stage++) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tthreat = unit_threat >> 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tthreat += unit_threat;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tthreat = -1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgoto top_of_list;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgoto end_of_list;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewdir\t= CELL_FACING(next, dest);\n\t\t\t\t\tnext\t\t= Adjacent_Cell(next, newdir);\n\t\t\t\t} while (Passable_Cell(next, newdir, threat, threshhold));\n\t\t\t}\n\n\t\t\tif (!left && !right) break;\n\n\t\t\t/*\n\t\t\t**\tWe found a path around the impassable locations, so figure out\n\t\t\t**\twhich one was the smallest and copy those moves into the\n\t\t\t**\tpath.Command array.\n\t\t\t*/\n\t\t\twhich = &pleft;\n\t\t\tif (right) {\n\t\t\t\twhich = &pright;\n\t\t\t\tif (left) {\n\t\t\t\t\tif (pleft.Length < pright.Length) {\n\t\t\t\t\t\twhich = &pleft;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twhich = &pright;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRecord as much as possible of the shorter of the two\n\t\t\t**\tpaths. The trailing EOL command is not copied because\n\t\t\t**\tthis may not be the end of the find path logic.\n\t\t\t*/\n\t\t\tlen = which->Length;\n\t\t\tlen = min(len, maxlen);\n\t\t\tif (len > 0) {\n\t\t\t\tmemcpy(&path.Overlap[0], &which->Overlap[0], sizeof(LeftOverlap));\n\t\t\t\tmemcpy(&path.Command[0], &which->Command[0], len * sizeof(FacingType));\n\t\t\t\tpath.Length \t\t= len;\n\t\t\t\tpath.Cost   \t\t= which->Cost;\n\t\t\t\tpath.LastOverlap \t= -1;\n\t\t\t\tpath.LastFixup\t \t= -1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tstartcell = next;\n\t}\n\nend_of_list:\n\t/*\n\t**\tPoke in the stop command.\n\t*/\n\tif (path.Length < maxlen) {\n\t\tpath.Command[path.Length++] = END;\n\t}\n\n\t/*\n\t**\tOptimize the move list but only necessary if\n\t**\tdiagonal moves are allowed.\n\t*/\n\t#ifdef DIAGONAL\n\t\tOptimize_Moves(&path, threshhold);\n\t#endif\n\n\tBEnd(BENCH_FINDPATH);\n\n\treturn(&path);\n}\n\n\n/***********************************************************************************************\n * Follow_Edge -- Follow an edge to get around an impassable spot.                             *\n *                                                                                             *\n * INPUT:   start    -- cell to head from                                                      *\n *                                                                                             *\n *            target   -- Target cell to head to.                                              *\n *                                                                                             *\n *          path     -- Pointer to path list structure.                                        *\n *                                                                                             *\n *          search   -- Direction of search (1=clock, -1=counterclock).                        *\n *                                                                                             *\n *          olddir   -- Facing impassible direction from start.                                *\n *                                                                                             *\n *          callback -- Function pointer for determining if a cell is                          *\n *                      passable or not.                                                       *\n *                                                                                             *\n * OUTPUT:  bool: Could a path be found to the desired cell?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *   06/01/1992  JLB : Optimized & commented.                                                  *\n *=============================================================================================*/\nbool FootClass::Follow_Edge(CELL start, CELL target, PathType * path, FacingType search, FacingType olddir, int threat, int , int max_cells, MoveType threshhold)\n{\n\tFacingType\tnewdir;\t\t\t// Direction of facing before surrounding cell check.\n\tCELL\t\t\toldcell,\t\t// Current cell.\n\t\t\t\t\tnewcell;\t\t// Tentative new cell.\n\tint\t\t\tcost;\t\t\t\t// Working cost value.\n\tint\t\t\tstartx;\n\tint\t\t\tstarty;\n\tint\t\t\tonline=true;\n\tint\t\t\ttargetx;\n\tint\t\t\ttargety;\n\tint\t\t\toldval = 0;\n\tint\t\t\tcellcount=0;\n\tint\t\t\tforceout = false;\n\tFacingType\tfirstdir = (FacingType)-1;\n\tCELL\t\t\tfirstcell = -1;\n\tbool\t\t\tstepped_off_line = false;\n\tstartx \t= Cell_X(start);\n\tstarty\t= Cell_Y(start);\n\ttargetx  = Cell_X(target);\n\ttargety\t= Cell_Y(target);\n\n\tif (!path) return(false);\n\tpath->LastOverlap = -1;\n\tpath->LastFixup\t= -1;\n\n\t#ifndef DIAGONAL\n\t\t/*\n\t\t**\tThe edge following algorithm doesn't \"do\" diagonals. Force initial facing\n\t\t**\tto be an even 90 degree value. Adjust it in the direction it should be\n\t\t**\trotating.\n\t\t*/\n\t\tif (olddir & 0x01) {\n\t\t\tolddir = Next_Direction(olddir, search);\n\t\t}\n\t#endif\n\n\tnewdir\t\t= Next_Direction(olddir, search);\n\toldcell \t\t= start;\n\tnewcell \t\t= Adjacent_Cell(oldcell, newdir);\n\n\t/*\n\t**\tContinue until we find our target, find our original starting spot,\n\t**\tor run out of moves.\n\t*/\n\twhile (path->Length < max_cells) {\n\n\t\t/*\n\t\t**\tLook in all the adjacent cells to determine a passable one that\n\t\t**\tmost closely matches the desired direction (working in the specified\n\t\t**\tdirection).\n\t\t*/\n\t\tnewdir = olddir;\n\t\tfor (;;) {\n\t\t\tbool\tforcefail;\t\t// Is failure forced?\n\n\t\t\tforcefail = false;\n\n\t\t\t#ifdef DIAGONAL\n\t\t\t\t/*\n\t\t\t\t**\tRotate 45/90 degrees in desired direction.\n\t\t\t\t*/\n\t\t\t\tnewdir = Next_Direction(newdir, search);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf facing a diagonal we must check the next 90 degree location\n\t\t\t\t**\tto make sure that we don't walk right by the destination. This\n\t\t\t\t**\twill happen if the destination it is at the corner edge of an\n\t\t\t\t**\timpassable that we are moving around.\n\t\t\t\t*/\n\t\t\t\tif (newdir & FACING_NE) {\n\t\t\t\t\tCELL\tcheckcell;\t\t// Non-diagonal check cell.\n\t\t\t\t\t//int\tx,y;\n\n\t\t\t\t\tcheckcell = Adjacent_Cell(oldcell, Next_Direction(newdir, search));\n\n\t\t\t\t\tif (checkcell == target) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tThis only works if in fact, it is possible to move to the\n\t\t\t\t\t\t**\tcell from the current location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcost = Passable_Cell(checkcell, Next_Direction(newdir, search), threat, threshhold);\n\t\t\t\t\t\tif (cost) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tYES! The destination is at the corner of an impassable, so\n\t\t\t\t\t\t\t**\tset the direction to point directly at it and then the\n\t\t\t\t\t\t\t**\tscanning will terminate later.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tnewdir = Next_Direction(newdir, search);\n\t\t\t\t\t\t\tnewcell = Adjacent_Cell(oldcell, newdir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPerform special diagonal check. If the edge follower would cross the\n\t\t\t\t\t**\tdiagonal or fall on the diagonal line from the source, then consider\n\t\t\t\t\t**\tthat cell impassible. Otherwise, the find path algorithm will fail\n\t\t\t\t\t**\twhen there are two impassible locations located on a diagonal\n\t\t\t\t\t**\tthat is lined up between the source and destination location.\n\t\t\t\t\t**\n\t\t\t\t\t** P.S. It might help if you check the right cell rather than using\n\t\t\t\t\t**      the value that just happened to be in checkcell.\n\t\t\t\t\t*/\n\n\t\t\t\t\tcheckcell = Adjacent_Cell(oldcell, newdir);\n\n\t\t\t\t\tint checkx\t\t= Cell_X(checkcell);\n\t\t\t\t\tint checky\t\t= Cell_Y(checkcell);\n\t\t\t\t\tint checkval\t= Point_Relative_To_Line(checkx, checky, startx, starty, targetx, targety);\n\t\t\t\t\tif (checkval && !online) {\n\t\t\t\t\t\tforcefail = ((checkval ^ oldval) < 0);\n\t\t\t\t\t} else {\n\t\t\t \t\t\tforcefail = false;\n\t\t\t\t\t}\n\t\t\t\t\t/*\n\t\t\t\t\t** The only exception to the above is when we are directly backtracking\n\t\t\t\t\t** because we could be trying to escape from a culdesack!\n\t\t\t\t\t*/\n\t\t\t\t\tif (forcefail && path->Length > 0 && (FacingType)(newdir ^ 4) == path->Command[path->Length - 1]) {\n\t\t\t\t\t\tforcefail = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t#else\n\t\t\t\tnewdir = Next_Direction(newdir, search*2);\n\t\t\t#endif\n\n\t\t\t/*\n\t\t\t**\tIf we have just checked the same heading we started with,\n\t\t\t**\twe are surrounded by impassable characters and we exit.\n\t\t\t*/\n\t\t\tif (newdir == olddir) {\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGet the new cell.\n\t\t\t*/\n\t\t\tnewcell = Adjacent_Cell(oldcell, newdir);\n\n\t\t\t/*\n\t\t\t**\tIf we found a passable position, this is where we should move.\n\t\t\t*/\n\t\t\tif (!forcefail && ((cost = Passable_Cell(newcell, newdir, threat, threshhold)) != 0)) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tif (newcell == target) {\n\t\t\t\t\tforceout = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the direction.\n\t\t*/\n\t\tif (!forceout) {\n\t\t\t/*\n\t\t\t** Mark the cell because this is where we need to be.  If register\n\t\t\t** cell fails then the list has been shortened and we need to adjust\n\t\t\t** the new direction.\n\t\t\t*/\n\t\t\tif (!Register_Cell(path, newcell, newdir, cost, threshhold)) {\n\t\t\t\t/*\n\t\t\t\t** The only reason we could not register a cell is that we are in\n\t\t\t\t** a looping situation.  So we need to try and unravel the loop if\n\t\t\t\t** we can.\n\t\t\t\t*/\n\t\t\t\tif (!Unravel_Loop(path, newcell, newdir, startx, starty, targetx, targety, threshhold)) {\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t** Since we need to eliminate a diagonal we must pretend the upon\n\t\t\t\t** attaining this square, we were moving turned further in the\n\t\t\t\t** search direction then we really were.\n\t\t\t\t*/\n\t\t\t\tnewdir = Next_Direction(newdir, (FacingType)(search*2));\n\t\t\t}\n\t\t\t/*\n\t\t\t** Find out which side of the line this cell is on.  If it is on\n\t\t\t** a side, then store off that side.\n\t\t\t*/\n\t\t\tint newx\t= Cell_X(newcell);\n\t\t\tint newy\t= Cell_Y(newcell);\n\t\t\tint val\t= Point_Relative_To_Line(newx, newy, startx, starty, targetx, targety);\n\t\t\tif (val) {\n\t\t\t\toldval = val;\n\t\t\t\tonline = false;\n\t\t\t} else {\n\t\t\t\tonline = true;\n\t\t\t}\n\t\t\tcellcount++;\n\t\t\tif (cellcount == MAX_PATH_EDGE_FOLLOW) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf we have found the target spot, we are done.\n\t\t*/\n\t\tif (newcell == target) {\n\t\t\tpath->Command[path->Length] = END;\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tIf we make a full circle back to our original spot, get out.\n\t\t*/\n\t\tif (newcell == firstcell && newdir == firstdir) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (firstcell == -1) {\n\t\t\tfirstcell = newcell;\n\t\t\tfirstdir  = newdir;\n\t\t}\n\n\t\t/*\n\t\t**\tBecause we moved, our facing is now incorrect. We want to face toward\n\t\t**\tthe impassable edge we are following (well, not actually toward, but\n\t\t**\ta little past so that we can turn corners). We have to turn 45/90 degrees\n\t\t**\tmore than expected in anticipation of the pending 45/90 degree turn at\n\t\t**\tthe start of this loop.\n\t\t*/\n\t\t#ifdef DIAGONAL\n\t\t\tolddir = Next_Direction(newdir, (FacingType)(-(int)search*3));\n\t\t#else\n\t\t\tolddir = Next_Direction(newdir, (FacingType)(-(int)search*4));\n\t\t#endif\n\t\toldcell = newcell;\n\t}\n\n\t/*\n\t**\tThe maximum search path is exhausted... abort with a failure.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Optimize_Moves -- Optimize the move list.                                                   *\n *                                                                                             *\n * INPUT:      char *moves to optimize                                                         *\n *                                                                                             *\n * OUTPUT:     none (list is optimized)                                                        *\n *                                                                                             *\n * WARNINGS:   EMPTY moves are used to hold the place of eliminated                            *\n *             commands. Also, NEVER call this routine with a list that                        *\n *             contains illegal commands. The list MUST be terminated                          *\n *             with a EOL command                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1991  CY : Created.                                                                 *\n *   06/01/1992  JLB : Optimized and commented.                                                *\n *=============================================================================================*/\n#define\tEMPTY\t\t(FacingType)-2\nint FootClass::Optimize_Moves(PathType * path, MoveType threshhold)\n//int Optimize_Moves(PathType *path, int (*callback)(CELL, FacingType), int threshold)\n{\n\t/*\n\t**\tFacing command pair adjustment table. Compare the facing difference between\n\t**\tthe two commands. 0 means no optimization is possible. 3 means backtracking\n\t**\tso eliminate both commands. Any other value adjusts the first command facing.\n\t*/\n#ifdef DIAGONAL\n\tstatic FacingType _trans[FACING_COUNT] = {(FacingType)0, (FacingType)0, (FacingType)1, (FacingType)2, (FacingType)3, (FacingType)-2, (FacingType)-1, (FacingType)0};\t// Smoothing.\n#else\n\tstatic FacingType _trans[FACING_COUNT] = {(FacingType)0, (FacingType)0, (FacingType)0, (FacingType)2, (FacingType)3, (FacingType)-2, (FacingType)0, (FacingType)0};\n#endif\n\tFacingType\t* cmd1,\t\t// Floating first command pointer.\n\t\t\t\t\t* cmd2,\t\t// Floating second command pointer.\n\t\t\t\t\tnewcmd;\t\t// Calculated new optimized command.\n\tFacingType\tnewdir;\t\t// Tentative new direction for smoothing.\n\tCELL\t\t\tcell;\t\t\t// Working cell (as it moves along path).\n\n\t/*\n\t**\tAbort if there is any illegal parameter.\n\t*/\n\tif (!path || !path->Command) return(0);\n\n\t/*\n\t**\tOptimization loop -- start scanning with the\n\t**\tfirst pair of commands (if there are at least two\n\t**\tin the command list).\n\t*/\n\tpath->Command[path->Length] = END;\t\t// Force end of list.\n\n\tif (path->Length == 0) return(0);\n\n\tcell = path->Start;\n\tif (path->Length > 1) {\n\t\tcmd2 = path->Command + 1;\n\t\twhile (*cmd2 != END) {\n\n\t\t\t/*\n\t\t\t**\tSet the cmd1 pointer to point to the valid command closest, but\n\t\t\t**\tprevious to cmd2. Be sure not to go previous to the head of the\n\t\t\t**\tcommand list.\n\t\t\t*/\n\t\t\tcmd1 = cmd2-1;\n\t\t\twhile (*cmd1 == EMPTY && cmd1 != path->Command) {\n\t\t\t\tcmd1--;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there isn't any valid previous command, then bump the\n\t\t\t**\tcmd pointers to the next command pair and continue...\n\t\t\t*/\n\t\t\tif (*cmd1 == EMPTY) {\n\t\t\t\tcmd2++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch precalculated command change value. 0 means leave\n\t\t\t**\tcommand set alone, 3 means backtrack and eliminate two\n\t\t\t**\tcommands. Any other value is new direction and eliminate\n\t\t\t**\tone command.\n\t\t\t*/\n\t\t\tnewcmd = (FacingType)(*cmd2 - *cmd1);\n\t\t\tif (newcmd < FACING_N) newcmd = (FacingType)(newcmd + FACING_COUNT);\n\t\t\tnewcmd = _trans[newcmd];\n\n\t\t\t/*\n\t\t\t**\tCheck for backtracking. If this occurs, then eliminate the\n\t\t\t**\ttwo commands. This is the easiest optimization.\n\t\t\t*/\n\t\t\tif (newcmd == FACING_SE) {\n\t\t\t\t*cmd1 = EMPTY;\n\t\t\t\t*cmd2++ = EMPTY;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf an optimization code was found the process it. The command is a facing\n\t\t\t**\toffset to more directly travel toward the immediate destination cell.\n\t\t\t*/\n\t\t\tif (newcmd) {\n\n\t\t\t\t/*\n\t\t\t\t**\tOptimizations differ when dealing with diagonals. Especially when dealing\n\t\t\t\t**\twith diagonals of 90 degrees. In such a case, 90 degree optimizations can\n\t\t\t\t**\tonly be optimized if the intervening cell is passable. The distance travelled\n\t\t\t\t**\tis the same, but the path is less circuitous.\n\t\t\t\t*/\n\t\t\t\tif (*cmd1 & FACING_NE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDiagonal optimizations are always only 45\n\t\t\t\t\t**\tdegree adjustments.\n\t\t\t\t\t*/\n\t\t\t\t\tnewdir = Next_Direction(*cmd1, (newcmd < FACING_N) ? (FacingType)-1 : (FacingType)1);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDiagonal 90 degree changes can be smoothed, although\n\t\t\t\t\t**\tthe path isn't any shorter.\n\t\t\t\t\t*/\n\t\t\t\t\tif (ABS((int)newcmd) == 1) {\n\t\t\t\t\t\tif (Passable_Cell(Adjacent_Cell(cell, newdir), newdir, -1, threshhold)) {\n\t\t\t\t\t\t\t*cmd2 = newdir;\n\t\t\t\t\t\t\t*cmd1 = newdir;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// BOB 16.12.92\n\t\t\t\t\t\tcell = Adjacent_Cell(cell, *cmd1);\n\t\t\t\t\t\tcmd2++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewdir = Next_Direction(*cmd1, newcmd);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAllow shortening turn only on right angle moves that are based on\n\t\t\t\t**\t90 degrees. Always allow 135 degree optimizations.\n\t\t\t\t*/\n\t\t\t\t*cmd2 = newdir;\n\t\t\t\t*cmd1 = EMPTY;\n\n\t\t\t\t/*\n\t\t\t\t**\tBackup what it thinks is the current cell.\n\t\t\t\t*/\n\t\t\t\twhile (*cmd1 == EMPTY && cmd1 != path->Command) {\n\t\t\t\t\tcmd1--;\n\t\t\t\t}\n\t\t\t\tif (*cmd1 != EMPTY) {\n\t\t\t\t\tcell = Adjacent_Cell(cell, Next_Direction(*cmd1, FACING_S));\n\t\t\t\t} else {\n\t\t\t\t\tcell = path->Start;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSince we could not make an optimization, we move our\n\t\t\t**\thead pointer forward.\n\t\t\t*/\n\t\t\tcell = Adjacent_Cell(cell, *cmd1);\n\t\t\tcmd2++;\n\t\t}\n\t}\n\n\t/*\n\t**\tPack the command list to remove any EMPTY command entries.\n\t*/\n\tcmd1 = path->Command;\n\tcmd2 = path->Command;\n\tcell = path->Start;\n\tpath->Cost = 0;\n\tpath->Length = 0;\n\twhile (*cmd2 != END) {\n\t\tif (*cmd2 != EMPTY) {\n\t\t\tcell = Adjacent_Cell(cell, *cmd2);\n\t\t\tpath->Cost+= Passable_Cell(cell, *cmd2, -1, threshhold);\n\t\t\tpath->Length++;\n\t\t\t*cmd1++ = *cmd2;\n\t\t}\n\t\tcmd2++;\n\t}\n\tpath->Length++;\n\t*cmd1 = END;\n\treturn(path->Length);\n}\n\n\nCELL FootClass::Safety_Point(CELL src, CELL dst, int start, int max)\n{\n\tFacingType dir;\n\tCELL\t\t  next;\n\tint \t\t  lp;\n\n\tdir = (FacingType)(CELL_FACING(src, dst) ^ 4) - 1;\n\n\t/*\n\t** Loop through the different acceptable distances.\n\t*/\n\tfor (int dist = start; dist < max; dist ++) {\n\n\t\t/*\n\t\t** Move to the starting location.\n\t\t*/\n\t\tnext = dst;\n\n\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\tnext = Adjacent_Cell(next, dir);\n\t\t}\n\n\t\tif (dir & 1) {\n\t\t\t/*\n\t\t\t** If our direction is diagonal than we need to check\n\t\t\t** only one side which is as long as both of the old sides\n\t\t\t** together.\n\t\t\t*/\n\t\t\tfor (lp = 0; lp < dist << 1; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 3);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t** If our direction is not diagonal than we need to check two\n\t\t\t** sides so that we are checking a corner like location.\n\t\t\t*/\n\t\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 2);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (lp = 0; lp < dist; lp ++) {\n\t\t\t\tnext = Adjacent_Cell(next, dir + 4);\n\t\t\t\tif (!Can_Enter_Cell(next)) {\n\t\t\t\t\treturn(next);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(-1);\n}\n\n\n\n\nint FootClass::Passable_Cell(CELL cell, FacingType face, int threat, MoveType threshhold)\n{\n\tMoveType move = Can_Enter_Cell(cell, face);\n\n\tif (move < MOVE_MOVING_BLOCK && Distance(Cell_Coord(cell)) > 0x0100) threshhold = MOVE_MOVING_BLOCK;\n\n\tif (move > threshhold) return(0);\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tif (threat != -1) {\n\t\t\tif (::Distance(Cell_Coord(cell), Cell_Coord(DestLocation)) > (THREAT_THRESHOLD * CELL_LEPTON_W)) {\n//\t\t\tif (Map.Cell_Distance(cell, DestLocation) > THREAT_THRESHOLD) {\n\t\t\t\tif (Map.Cell_Threat(cell, Owner()) > threat)\n\t\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic int _value[MOVE_COUNT] = {\n\t\t1,\t\t\t//\tMOVE_OK\n\t\t1,\t\t\t//\tMOVE_CLOAK\n\t\t3,\t\t\t//\tMOVE_MOVING_BLOCK\n\t\t8,\t\t\t//\tMOVE_DESTROYABLE\n\t\t10,\t\t//\tMOVE_TEMP\n\t\t0\t\t\t//\tMOVE_NO\n\t};\n\treturn(_value[move]);\n}\n\n"
  },
  {
    "path": "REDALERT/FIXED.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FIXED.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FIXED.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/20/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.          *\n *   fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                     *\n *   fixed::fixed -- Constructor for fixed integral from ASCII initializer.                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"fixed.h\"\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<ctype.h>\n\n\n/*\n**\tThese are some handy fixed point constants. Using these constants instead of manually\n**\tconstructing them is not only faster, but more readable.\n*/\nconst fixed fixed::_1_2(1, 2);\t\t// 1/2\nconst fixed fixed::_1_3(1, 3);\t\t// 1/3\nconst fixed fixed::_1_4(1, 4);\t\t// 1/4\nconst fixed fixed::_3_4(3, 4);\t\t// 3/4\nconst fixed fixed::_2_3(2, 3);\t\t// 2/3\n\n\nfixed::fixed(int numerator, int denominator)\n{\n\tif (denominator == 0) {\n\t\tData.Raw = 0U;\n\t} else {\n\t\tData.Raw = (unsigned int)(((unsigned __int64)numerator * PRECISION) / denominator);\n\t}\n}\n\n\n/***********************************************************************************************\n * fixed::fixed -- Constructor for fixed integral from ASCII initializer.                      *\n *                                                                                             *\n *    This will parse the ASCII initialization string into a fixed point number.               *\n *    The source string can be a conventional fixed point representation (e.g., \"1.0\", \".25\")  *\n *    or a percent value (e.g. \"100%\", \"25%\", \"150%\"). For percent values, the trailing \"%\"    *\n *    is required.                                                                             *\n *                                                                                             *\n * INPUT:   ascii -- Pointer to the ascii source to translate into a fixed point number.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It is possible to specify an ASCII string that has more precision and           *\n *             magnitude than can be represented by the fixed point number. In such a case,    *\n *             the resulting value is undefined.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed::fixed(char const * ascii)\n{\n\t/*\n\t**\tIf there is no valid pointer, then default to zero value. This takes care of any\n\t**\tcompiler confusion that would call this routine when the programmer wanted the\n\t**\tinteger parameter constructor to be called.\n\t*/\n\tif (ascii == NULL) {\n\t\tData.Raw = 0U;\n\t\treturn;\n\t}\n\n\t/*\n\t**\tThe whole part (if any) always starts with the first legal characters.\n\t*/\n\tchar const * wholepart = ascii;\n\n\t/*\n\t**\tSkip any leading white space.\n\t*/\n\twhile (isspace(*ascii)) {\n\t\tascii++;\n\t}\n\n\t/*\n\t**\tDetermine if the number is expressed as a percentage. Detect this by\n\t**\tseeing if there is a trailing \"%\" character.\n\t*/\n\tchar const * tptr = ascii;\n\twhile (isdigit(*tptr)) {\n\t\ttptr++;\n\t}\n\n\t/*\n\t**\tPercentage value is specified as a whole number but is presumed to be\n\t**\tdivided by 100 to get mathematical fixed point percentage value.\n\t*/\n\tif (*tptr == '%') {\t\t\t// Removed '/' preceding '%'. ST - 5/8/2019\n\t\tData.Raw = (unsigned int)(((unsigned __int64)atoi(ascii) * PRECISION) / 100ULL);\n\t} else {\n\n\t\tData.Composite.Whole = Data.Composite.Fraction = 0U;\n\t\tif (wholepart && *wholepart != '.') {\n\t\t\tData.Composite.Whole = (unsigned short)atoi(wholepart);\n\t\t}\n\n\t\tconst char * fracpart = strchr(ascii, '.');\n\t\tif (fracpart) fracpart++;\n\t\tif (fracpart) {\n\t\t\tunsigned int frac = (unsigned int)atoi(fracpart);\n\n\t\t\tint len = 0;\n\t\t\tunsigned int base = 1;\n\t\t\tchar const * fptr = fracpart;\n\t\t\twhile (isdigit(*fptr)) {\n\t\t\t\tfptr++;\n\t\t\t\tlen++;\n\t\t\t\tbase *= 10U;\n\t\t\t}\n\n\t\t\tData.Composite.Fraction = (unsigned short)(((unsigned __int64)frac * PRECISION) / base);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                       *\n *                                                                                             *\n *    Use this routine to convert this fixed point number into an ASCII null terminated        *\n *    string. This is the counterpart to the fixed point constructor that takes an ASCII       *\n *    string.                                                                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to hold the fixed point ASCII string.            *\n *                                                                                             *\n *          maxlen   -- The length of the buffer.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters placed in the buffer. The trailing null is   *\n *          not counted in this total.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint fixed::To_ASCII(char * buffer, int maxlen) const\n{\n\tif (buffer == NULL) return(0);\n\n\t/*\n\t**\tDetermine the whole and fractional parts of the number. The fractional\n\t**\tpart number is the value in 1000ths.\n\t*/\n\tunsigned int whole = Data.Composite.Whole;\n\tunsigned int frac = ((unsigned int)Data.Composite.Fraction * 1000U) / PRECISION;\n\tchar tbuffer[32];\n\n\t/*\n\t**\tIf there number consists only of a whole part, then the number is simply\n\t**\tprinted into the buffer. If there is a fractional part, then there\n\t**\twill be a decimal place followed by up to three digits of accuracy for the\n\t**\tfractional component.\n\t*/\n\tif (frac == 0) {\n\t\tsprintf(tbuffer, \"%u\", whole);\n\t} else {\n\t\tsprintf(tbuffer, \"%u.%02u\", whole, frac);\n\n\t\tchar * ptr = &tbuffer[strlen(tbuffer)-1];\n\t\twhile (*ptr == '0') {\n\t\t\t*ptr = '\\0';\n\t\t\tptr--;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf no maximum length to the output buffer was specified, then presume the\n\t**\toutput buffer is just long enough to store the number and the trailing\n\t**\tzero.\n\t*/\n\tif (maxlen == -1) {\n\t\tmaxlen = strlen(tbuffer)+1;\n\t}\n\n\t/*\n\t**\tFill the output buffer with the ASCII number.\n\t*/\n\tstrncpy(buffer, tbuffer, maxlen);\n\n\t/*\n\t**\tReturn with the number of ASCII characters placed into the output buffer.\n\t*/\n\tint len = strlen(tbuffer);\n\tif (len < maxlen-1) return(len);\n\treturn(maxlen-1);\n}\n\n\n/***********************************************************************************************\n * fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.            *\n *                                                                                             *\n *    This number will be converted into an ASCII string (using a static buffer) and the       *\n *    string pointer will be returned.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII representation of this fixed point number.     *\n *                                                                                             *\n * WARNINGS:   As with all static return pointers, the pointer is valid only until such time   *\n *             as this routine is called again.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * fixed::As_ASCII(void) const\n{\n\tstatic char buffer[32];\n\n\tTo_ASCII(buffer, sizeof(buffer));\n\treturn(buffer);\n}\n"
  },
  {
    "path": "REDALERT/FIXED.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FIXED.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FIXED.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/19/96                                                     *\n *                                                                                             *\n *                  Last Update : June 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef FIXED_H\n#define FIXED_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n//#pragma warning 604 9\n//#pragma warning 595 9\n\n/*\n**\tThis is a very simple fixed point class that functions like a regular integral type. However\n**\tit is under certain restrictions. The whole part must not exceed 65535. The fractional part is\n**\tlimited to an accuracy of 1/65536. It cannot represent or properly handle negative values. It\n**\treally isn't all that fast (if an FPU is guaranteed to be present than using \"float\" might be\n**\tmore efficient). It doesn't detect overflow or underflow in mathematical or bit-shift operations.\n**\n**\tTake careful note that the normal mathematical operators return integers and not fixed point\n**\tvalues if either of the components is an integer. This is the normal C auto-upcasting rule\n**\tas it would apply presuming that integers are considered to be of higher precision than\n**\tfixed point numbers. This allows the result of these operators to generate values with greater\n**\tmagnitude than is normally possible if the result were coerced into a fixed point number.\n**\tIf the result should be fixed point, then ensure that both parameters are fixed point.\n**\n**\tNote that although integers are used as the parameters in the mathematical operators, this\n**\tdoes not imply that negative parameters are supported. The use of integers is as a convenience\n**\tto the programmer -- constant integers are presumed signed. If unsigned parameters were\n**\tspecified, then the compiler would have ambiguous conversion situation in the case of constant\n** integers (e.g. 1, 10, 32, etc). This is most important for the constructor when dealing with the\n**\t\"0\" parameter case. In that situation the compiler might interpret the \"0\" as a null pointer rather\n**\tthan an unsigned integer. There should be no adverse consequences of using signed integer parameters\n**\tsince the precision/magnitude of these integers far exceeds the fixed point component counterparts.\n**\n**\tNote that when integer values are returns from the arithmetic operators, the value is rounded\n**\tto the nearest whole integer value. This differs from normal integer math that always rounds down.\n*/\nclass fixed\n{\n\tstatic constexpr unsigned int PRECISION = 1 << 16;\n\n\tpublic:\n\t\t// The default constructor must not touch the data members in any way.\n\t\tfixed(void) {}\n\n\t\t// Copy constructor\n\t\tfixed(fixed const & rvalue) {Data.Raw = rvalue.Data.Raw;}\n\n\t\t// Convenient constructor if numerator and denominator components are known.\n\t\tfixed(int numerator, int denominator);\n\n\t\t// Conversion constructor to get fixed point from integer.\n\t\tfixed(int value) {Data.Composite.Fraction = 0U;Data.Composite.Whole = (unsigned short)value;}\n\t\tfixed(unsigned int value) {Data.Composite.Fraction = 0U;Data.Composite.Whole = (unsigned short)value;}\n\n\t\t// Conversion constructor to get fixed point from floating-point.\n\t\tfixed(float value) {value += 1.0f/(PRECISION<<1);Data.Composite.Fraction = (unsigned short)((value - (unsigned short)value) * PRECISION);Data.Composite.Whole = (unsigned short)value;}\n\n\t\t// Constructor if ASCII image of number is known.\n\t\tfixed(char const * ascii);\n\n\t\t// Convert to integer when implicitly required.\n\t\toperator unsigned (void) const {return(unsigned)(((unsigned __int64)Data.Raw+(PRECISION>>1)) / PRECISION);}\n\n\t\t/*\n\t\t**\tThe standard operators as they apply to in-place operation.\n\t\t*/\n\t\tfixed & operator *= (fixed const & rvalue) {Data.Raw = (unsigned int)(((unsigned __int64)Data.Raw * rvalue.Data.Raw) / PRECISION);return(*this);}\n\t\tfixed & operator *= (int rvalue) {Data.Raw *= (unsigned int)rvalue;return(*this);}\n\t\tfixed & operator /= (fixed const & rvalue) {if (rvalue.Data.Raw != 0U && rvalue.Data.Raw != PRECISION) Data.Raw = (unsigned int)((((unsigned __int64)Data.Raw * PRECISION)+(PRECISION>>1)) / rvalue.Data.Raw);return(*this);}\n\t\tfixed & operator /= (int rvalue) {if (rvalue) Data.Raw /= (unsigned int)rvalue;return(*this);}\n\t\tfixed & operator += (fixed const & rvalue) {Data.Raw += rvalue.Data.Raw;return(*this);}\n\t\tfixed & operator -= (fixed const & rvalue) {Data.Raw -= rvalue.Data.Raw;return(*this);}\n\n\t\t/*\n\t\t**\tThe standard \"My Dear Aunt Sally\" operators. The integer versions of multiply\n\t\t**\tand divide are more efficient than using the fixed point counterparts.\n\t\t*/\n\t\tconst fixed operator * (fixed const & rvalue) const { return fixed(*this) *= rvalue; }\n\t\tconst int operator * (int rvalue) const { return fixed(*this) *= rvalue; }\n\t\tconst fixed operator / (fixed const & rvalue) const { return fixed(*this) /= rvalue; }\n\t\tconst int operator / (int rvalue) const { return fixed(*this) /= rvalue; }\n\t\tconst fixed operator + (fixed const & rvalue) const { return fixed(*this) += rvalue; }\n\t\tconst int operator + (int rvalue) const { return fixed(*this) += rvalue; }\n\t\tconst fixed operator - (fixed const & rvalue) const { return fixed(*this) -= rvalue; }\n\t\tconst int operator - (int rvalue) const { return fixed(*this) -= rvalue; }\n\n\t\t/*\n\t\t**\tThe Shift operators are more efficient than using multiplies or divides by power-of-2 numbers.\n\t\t*/\n\t\tfixed & operator >>= (unsigned rvalue) {Data.Raw >>= rvalue;return(*this);}\n\t\tfixed & operator <<= (unsigned rvalue) {Data.Raw <<= rvalue;return(*this);}\n\t\tconst fixed operator >> (unsigned rvalue) const {return fixed(*this) >>= rvalue;}\n\t\tconst fixed operator << (unsigned rvalue) const {return fixed(*this) <<= rvalue;}\n\n\t\t/*\n\t\t**\tThe full set of comparison operators.\n\t\t*/\n\t\tbool operator == (fixed const & rvalue) const {return(Data.Raw == rvalue.Data.Raw);}\n\t\tbool operator != (fixed const & rvalue) const {return(Data.Raw != rvalue.Data.Raw);}\n\t\tbool operator < (fixed const & rvalue) const {return(Data.Raw < rvalue.Data.Raw);}\n\t\tbool operator > (fixed const & rvalue) const {return(Data.Raw > rvalue.Data.Raw);}\n\t\tbool operator <= (fixed const & rvalue) const {return(Data.Raw <= rvalue.Data.Raw);}\n\t\tbool operator >= (fixed const & rvalue) const {return(Data.Raw >= rvalue.Data.Raw);}\n\t\tbool operator ! (void) const {return(Data.Raw == 0U);}\n\n\t\t/*\n\t\t**\tComparison to integers requires consideration of fractional component.\n\t\t*/\n\t\tbool operator < (int rvalue) const {return(Data.Raw < ((unsigned int)rvalue*PRECISION));}\n\t\tbool operator > (int rvalue) const {return(Data.Raw > ((unsigned int)rvalue*PRECISION));}\n\t\tbool operator <= (int rvalue) const {return(Data.Raw <= ((unsigned int)rvalue*PRECISION));}\n\t\tbool operator >= (int rvalue) const {return(Data.Raw >= ((unsigned int)rvalue*PRECISION));}\n\t\tbool operator == (int rvalue) const {return(Data.Raw == ((unsigned int)rvalue*PRECISION));}\n\t\tbool operator != (int rvalue) const {return(Data.Raw != ((unsigned int)rvalue*PRECISION));}\n\n\t\t/*\n\t\t**\tFriend functions to handle the alternate positioning of fixed and integer parameters.\n\t\t*/\n\t\tfriend const int operator * (int lvalue, fixed const & rvalue) { return fixed(lvalue) * rvalue; }\n\t\tfriend const int operator / (int lvalue, fixed const & rvalue) { return fixed(lvalue) / rvalue; }\n\t\tfriend const int operator + (int lvalue, fixed const & rvalue) { return fixed(lvalue) + rvalue; }\n\t\tfriend const int operator - (int lvalue, fixed const & rvalue) { return fixed(lvalue) - rvalue; }\n\t\tfriend bool operator < (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) < rvalue; }\n\t\tfriend bool operator > (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) > rvalue; }\n\t\tfriend bool operator <= (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) <= rvalue; }\n\t\tfriend bool operator >= (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) >= rvalue; }\n\t\tfriend bool operator == (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) == rvalue; }\n\t\tfriend bool operator != (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) != rvalue; }\n\t\tfriend int operator *= (int & lvalue, fixed const & rvalue) { lvalue = lvalue * rvalue; return(lvalue); }\n\t\tfriend int operator /= (int & lvalue, fixed const & rvalue) { lvalue = lvalue / rvalue; return(lvalue); }\n\t\tfriend int operator += (int & lvalue, fixed const & rvalue) { lvalue = lvalue + rvalue; return(lvalue); }\n\t\tfriend int operator -= (int & lvalue, fixed const & rvalue) { lvalue = lvalue - rvalue; return(lvalue); }\n\n\t\t/*\n\t\t**\tHelper functions to handle simple and common operations on fixed point numbers.\n\t\t*/\n\t\tvoid Round_Up(void) {Data.Raw += (PRECISION-1U);Data.Composite.Fraction = 0U;}\n\t\tvoid Round_Down(void) {Data.Composite.Fraction = 0U;}\n\t\tvoid Round(void) {if (Data.Composite.Fraction >= PRECISION>>1) Round_Up();Round_Down();}\n\t\tvoid Saturate(unsigned capvalue) {if (Data.Raw > (capvalue*PRECISION)) Data.Raw = capvalue*PRECISION;}\n\t\tvoid Saturate(fixed const & capvalue) {if (*this > capvalue) *this = capvalue;}\n\t\tvoid Sub_Saturate(unsigned capvalue) {if (Data.Raw >= (capvalue*PRECISION)) Data.Raw = (capvalue*PRECISION)-1U;}\n\t\tvoid Sub_Saturate(fixed const & capvalue) {if (*this >= capvalue) Data.Raw = capvalue.Data.Raw-1U;}\n\t\tvoid Inverse(void) {*this = fixed(1) / *this;}\n\n\t\t/*\n\t\t**\tFriend helper functions that work in the typical C fashion of passing the object to\n\t\t**\tbe processed as a parameter to the function.\n\t\t*/\n\t\tfriend const fixed Round_Up(fixed const & value) {fixed temp = value; temp.Round_Up();return(temp);}\n\t\tfriend const fixed Round_Down(fixed const & value) {fixed temp = value; temp.Round_Down();return(temp);}\n\t\tfriend const fixed Round(fixed const & value) {fixed temp = value; temp.Round();return(temp);}\n\t\tfriend const fixed Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Sub_Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Sub_Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}\n\t\tfriend const fixed Inverse(fixed const & value) {fixed temp = value;temp.Inverse();return(temp);}\n\n\t\t/*\n\t\t**\tConversion of the fixed point number into an ASCII string.\n\t\t*/\n\t\tint To_ASCII(char * buffer, int maxlen=-1) const;\n\t\tchar const * As_ASCII(void) const;\n\n\t\t/*\n\t\t**\tHelper constants that provide some convenient fixed point values.\n\t\t*/\n\t\tstatic const fixed _1_2;\n\t\tstatic const fixed _1_3;\n\t\tstatic const fixed _1_4;\n\t\tstatic const fixed _3_4;\n\t\tstatic const fixed _2_3;\n\n\tprivate:\n\t\tunion {\n\t\t\tstruct {\n#ifdef BIG_ENDIAN\n\t\t\t\tunsigned short Whole;\n\t\t\t\tunsigned short Fraction;\n#else\n\t\t\t\tunsigned short Fraction;\n\t\t\t\tunsigned short Whole;\n#endif\n\t\t\t} Composite;\n\t\t\tunsigned int Raw;\n\t\t} Data;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/FLASHER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FLASHER.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLASHER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 28, 1994                                                 *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FlasherClass::Debug_Dump -- Displays current status to the monochrome screen.             *\n *   FlasherClass::Process -- Performs the logic processing for the flashing ability.          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * FlasherClass::Debug_Dump -- Displays current status to the monochrome screen.               *\n *                                                                                             *\n *    This utility function will output the current status of the FlasherClass to the mono     *\n *    screen. It is through this display that bugs may be fixed or detected.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FlasherClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(50, 7);\n\tmono->Printf(\"%2d\", FlashCount);\n}\n#endif\n\n\n/***********************************************************************************************\n * FlasherClass::Process -- Performs the logic processing for the flashing ability.            *\n *                                                                                             *\n *    The ability for an object to flash is controlled by this logic processing routine. It    *\n *    should be called once per game tick per unit.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should the associated object be redrawn?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   06/20/1994 JLB : Is now independent of object it represents.                              *\n *=============================================================================================*/\nbool FlasherClass::Process(void)\n{\n\t// 2019/09/20 JAS - Flashing info needs to exist per player\n\tfor (int i = 0; i < HOUSE_COUNT; i++)\n\t{\n\t\tif (FlashCountPerPlayer[i])\n\t\t{\n\t\t\tFlashCountPerPlayer[i]--;\n\t\t}\n\t}\n\n\tif (FlashCount) {\n\t\tFlashCount--;\n\t\tIsBlushing = false;\n\n\t\tif (FlashCount & 0x01) {\n\t\t\tIsBlushing = true;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FlasherClass::Get_Flashing_Flags --\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Gets the flags tell which players this object should flash for.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  unsigned int; Flag representing the players to flash for                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   2019/09/20 JAS : Created.                                                                 *\n *=============================================================================================*/\nunsigned int FlasherClass::Get_Flashing_Flags() const\n{\n\tunsigned flags = 0;\n\tfor (int i = 0; i < HOUSE_COUNT; ++i)\n\t{\n\t\tif (FlashCountPerPlayer[i] > 0)\n\t\t{\n\t\t\tflags |= (1 << i);\n\t\t}\n\t}\n\n\treturn flags;\n}"
  },
  {
    "path": "REDALERT/FLASHER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FLASHER.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLASHER.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 28, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 28, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FLASHER_H\n#define FLASHER_H\n\nclass FlasherClass {\n\tpublic:\n\t\t/*\n\t\t**\tWhen this object is targeted, it will flash a number of times. This is the\n\t\t**\tflash control number. It counts down to zero and then stops. Odd values\n\t\t**\tcause the object to be rendered in a lighter color.\n\t\t*/\n\t\tunsigned FlashCount:7;\n\n\t\t/*\n\t\t**\tWhen an object is targeted, it flashes several times to give visual feedback\n\t\t**\tto the player. Every other game \"frame\", this flag is true until the flashing\n\t\t**\tis determined to be completed.\n\t\t*/\n\t\tunsigned IsBlushing:1;\n\n\t\t// 2019/09/20 JAS - Flashing info needs to exist per player\n\t\tunsigned int Get_Flashing_Flags() const;\n\t\tunsigned int FlashCountPerPlayer[HOUSE_COUNT];\n\n\t\t// 2019/09/20 JAS - Flashing info needs to exist per player\n\t\tFlasherClass(void) {\n\t\t\tFlashCount = 0;\n\t\t\tIsBlushing = false;\n\n\t\t\tfor (int i = 0; i < HOUSE_COUNT; ++i)\n\t\t\t{\n\t\t\t\tFlashCountPerPlayer[i] = 0;\n\t\t\t}\n\t\t}\n\n\t\tFlasherClass(NoInitClass const & ) {};\n\t\t~FlasherClass(void) {};\n\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tbool Process(void);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/FLY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FLY.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLY.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : June 5, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FlyClass::Fly_Speed -- Sets the flying object to the speed specified.                     *\n *   FlyClass::Physics -- Performs vector physics (movement).                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FlyClass::Physics -- Performs vector physics (movement).                                    *\n *                                                                                             *\n *    This routine performs movement (vector) physics. It takes the                            *\n *    specified location and moves it according to the facing and speed                        *\n *    of the vector. It returns the status of the move.                                        *\n *                                                                                             *\n * INPUT:   coord -- Reference to the coordinate that the vector will                          *\n *                   be applied to.                                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the status of the vector physics. This could                          *\n *          range from no effect, to exiting the edge of the world.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *   06/05/1995 JLB : Simplified to just do movement.                                          *\n *=============================================================================================*/\nImpactType FlyClass::Physics(COORDINATE & coord, DirType facing)\n{\n\tif (SpeedAdd != MPH_IMMOBILE) {\n\t\tint actual = (int)SpeedAdd + SpeedAccum;\n\t\tdiv_t result = div(actual, PIXEL_LEPTON_W);\n\t\tSpeedAccum = result.rem;\n\t\tactual -= result.rem;\n\t\tCOORDINATE old = coord;\n\n\t\t/*\n\t\t**\tIf movement occurred that is at least one\n\t\t**\tpixel, then check update the coordinate and\n\t\t**\tcheck for edge of world collision.\n\t\t*/\n\t\tif (result.quot) {\n\t\t\tCOORDINATE\t\tnewcoord;\t\t// New working coordinate.\n\t\t\tnewcoord = Coord_Move(coord, facing, actual);\n\t\t\t/*\n\t\t\t**\tIf no movement occurred, then presume it hasn't moved at all\n\t\t\t**\tand return immediately with this indication.\n\t\t\t*/\n\t\t\tif (newcoord == coord) {\n\t\t\t\treturn(IMPACT_NONE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRemember the new position.\n\t\t\t*/\n\t\t\tcoord = newcoord;\n\n\t\t\t/*\n\t\t\t**\tIf the new coordinate is off the edge of the world, then report\n\t\t\t**\tthis.\n\t\t\t*/\n\t\t\tif (newcoord & HIGH_COORD_MASK /*|| !Map.In_Radar(Coord_Cell(newcoord))*/) {\n//\t\t\tif (!Map.In_Radar(Coord_Cell(newcoord))) {\n\t\t\t\tcoord = old;\n\t\t\t\treturn(IMPACT_EDGE);\n\t\t\t}\n\n\t\t\treturn(IMPACT_NORMAL);\n\t\t}\n\t}\n\treturn(IMPACT_NONE);\n}\n\n\n/***********************************************************************************************\n * FlyClass::Fly_Speed -- Sets the flying object to the speed specified.                       *\n *                                                                                             *\n *    This sets the speed of the projectile. It basically functions like a throttle value      *\n *    where 0 equals stop and 255 equals maximum speed (whatever that is for the particular    *\n *    object).                                                                                 *\n *                                                                                             *\n * INPUT:   speed -- Speed setting from 0 to 255.                                              *\n *                                                                                             *\n *          maximum  -- The maximum speed of the object.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1994 JLB : Created.                                                                 *\n *   07/26/1994 JLB : Added maximum speed as guiding value.                                    *\n *=============================================================================================*/\nvoid FlyClass::Fly_Speed(int speed, MPHType maximum)\n{\n\tSpeedAdd = (MPHType)( maximum * fixed(speed, 256));\n//\tSpeedAdd = (MPHType)Fixed_To_Cardinal((int)maximum, speed);\n}\n\n\n"
  },
  {
    "path": "REDALERT/FLY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FLY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FLY.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 24, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FLY_H\n#define FLY_H\n\ntypedef enum ImpactType : unsigned char {\n\tIMPACT_NONE,\t\t// No movement (of significance) occurred.\n\tIMPACT_NORMAL,\t\t// Some (non eventful) movement occurred.\n\tIMPACT_EDGE\t\t\t// The edge of the world was reached.\n} ImpactType;\n\n\n/****************************************************************************\n**\tFlying objects are handled by this class definition.\n*/\nclass FlyClass {\n\tpublic:\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tFlyClass(void) : SpeedAccum(0), SpeedAdd(MPH_IMMOBILE) {};\n\t\tFlyClass(NoInitClass const &) {};\n\t\t~FlyClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tvoid Fly_Speed(int speed, MPHType maximum);\n\t\tImpactType Physics(COORDINATE &coord, DirType facing);\n\t\tMPHType Get_Speed(void) const {return(SpeedAdd);};\n\n\tprivate:\n\t\t/*\n\t\t**\tObject movement consists of incrementing the accumulator until enough \"distance\"\n\t\t**\thas accumulated so that moving the object becomes reasonable.\n\t\t*/\n\t\tunsigned SpeedAccum;\t\t\t// Lepton accumulator.\n\t\tMPHType SpeedAdd;\t\t\t// Lepton add (per frame).\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/FOOT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FOOT.CPP 2     3/06/97 1:46p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FOOT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 22, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 5, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FootClass::AI -- Handle general movement AI.                                              *\n *   FootClass::Active_Click_With -- Initiates attack or move according to target clicked on.  *\n *   FootClass::Active_Click_With -- Performs action as a result of left mouse click.          *\n *   FootClass::Adjust_Dest -- Adjust candidate movement cell to account for formation.        *\n *   FootClass::Approach_Target -- Sets the navigation computer to approach target object.     *\n *   FootClass::Assign_Destination -- Assigns specified destination to NavCom.                 *\n *   FootClass::Basic_Path -- Finds the basic path for a ground object.                        *\n *   FootClass::Body_Facing -- Set the body rotation/facing.                                   *\n *   FootClass::Can_Demolish -- Checks to see if this object can be sold back.                 *\n *   FootClass::Can_Enter_Cell -- Checks to see if the object can enter cell specified.        *\n *   FootClass::Clear_Navigation_List -- Clears out the navigation queue.                      *\n *   FootClass::Death_Announcement -- Announces the death of a unit.                           *\n *   FootClass::Debug_Dump -- Displays the status of the FootClass to the mono monitor.        *\n *   FootClass::Detach -- Detaches a target from tracking systems.                             *\n *   FootClass::Detach_All -- Removes this object from the game system.                        *\n *   FootClass::Enters_Building -- When unit enters a building for some reason.                *\n *   FootClass::FootClass -- Normal constructor for the foot class object.                     *\n *   FootClass::Greatest_Threat -- Fetches the greatest threat to this object.                 *\n *   FootClass::Handle_Navigation_List -- Processes the navigation queue.                      *\n *   FootClass::Is_Allowed_To_Leave_Map -- Checks to see if it can leave the map and the game. *\n *   FootClass::Is_On_Priority_Mission -- Checks to see if this object should be given priority*\n *   FootClass::Is_Recruitable -- Determine if this object is recruitable as a team members.   *\n *   FootClass::Likely_Coord -- Fetches the coordinate the object will be at shortly.          *\n *   FootClass::Mark -- Unit interface to map rendering system.                                *\n *   FootClass::Mission_Attack -- AI for heading towards and firing upon target.               *\n *   FootClass::Mission_Capture -- Handles the capture mission.                                *\n *   FootClass::Mission_Enter -- Enter (cooperatively) mission handler.                        *\n *   FootClass::Mission_Guard_Area -- Causes unit to guard an area about twice weapon range.   *\n *   FootClass::Mission_Hunt -- Handles the default hunt order.                                *\n *   FootClass::Mission_Move -- AI process for moving a vehicle to its destination.            *\n *   FootClass::Mission_Retreat -- Handle reatreat from map mission for mobile objects.        *\n *   FootClass::Offload_Tiberium_Bail -- Fetches the Tiberium to offload per step.             *\n *   FootClass::Override_Mission -- temporarily overrides a units mission                      *\n *   FootClass::Per_Cell_Process -- Perform action based on once-per-cell condition.           *\n *   FootClass::Queue_Navigation_List -- Add a target to the objects navigation list.          *\n *   FootClass::Receive_Message -- Movement related radio messages are handled here.           *\n *   FootClass::Rescue_Mission -- Calls this unit to the rescue.                               *\n *   FootClass::Restore_Mission -- Restores an overridden mission                              *\n *   FootClass::Sell_Back -- Causes this object to be sold back.                               *\n *   FootClass::Set_Speed -- Initiate unit movement physics.                                   *\n *   FootClass::Sort_Y -- Determine the sort coordinate for foot class objects.                *\n *   FootClass::Start_Driver -- This starts the driver heading to the destination desired.     *\n *   FootClass::Stop_Driver -- This routine clears the driving state of the object.            *\n *   FootClass::Stun -- Prepares a ground travelling object for removal.                       *\n *   FootClass::Take_Damage -- Handles taking damage to this object.                           *\n *   FootClass::Unlimbo -- Unlimbos object and performs special fixups.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FootClass::FootClass -- Default constructor for foot class objects.                         *\n *                                                                                             *\n *    This is the default constructor for FootClass objects. It sets the foot class values to  *\n *    their default starting settings.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nFootClass::FootClass(RTTIType rtti, int id, HousesType house) :\n\tTechnoClass(rtti, id, house),\n\tIsScanLimited(false),\n\tIsInitiated(false),\n\tIsNewNavCom(false),\n\tIsPlanningToLook(false),\n\tIsDeploying(false),\n\tIsFiring(false),\n\tIsRotating(false),\n\tIsDriving(false),\n\tIsUnloading(false),\n\tIsFormationMove(false),\n\tIsNavQueueLoop(false),\n\tIsScattering(false),\n\tIsMovingOntoBridge(false),\n\tSpeed(0),\n\tSpeedBias(1),\n\tXFormOffset(0x80000000),\n\tYFormOffset(0x80000000),\n\tNavCom(TARGET_NONE),\n\tSuspendedNavCom(TARGET_NONE),\n\tTeam(0),\n\tGroup(255),\n\tMember(0),\n\tPathThreshhold(MOVE_CLOAK),\n\tPathDelay(0),\n\tTryTryAgain(PATH_RETRY),\n\tBaseAttackTimer(0),\n\tFormationSpeed(SPEED_FOOT),\n\tFormationMaxSpeed(MPH_IMMOBILE),\n\tHeadToCoord(0)\n{\n\tPath[0] = FACING_NONE;\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tNavQueue[index] = TARGET_NONE;\n\t}\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * FootClass::Debug_Dump -- Displays the status of the FootClass to the mono monitor.          *\n *                                                                                             *\n *    This routine is used to output the current status of the foot class to the mono          *\n *    monitor. Through this display bugs may be tracked down or eliminated.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *   07/04/1995 JLB : Handles aircraft special case.                                           *\n *=============================================================================================*/\nvoid FootClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Fill_Attrib(53, 13, 12, 1, IsInitiated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 18, 12, 1, IsPlanningToLook ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 14, 12, 1, IsDeploying ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 15, 12, 1, IsFiring ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 16, 12, 1, IsRotating ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 17, 12, 1, IsDriving ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(53, 18, 12, 1, IsUnloading ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 18, 12, 1, IsFormationMove ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Set_Cursor(45, 1);mono->Printf(\"%02X\", Speed);\n\tif (NavCom) {\n\t\tmono->Set_Cursor(29, 5);\n\t\tmono->Printf(\"%08X\", NavCom);\n\t}\n\tif (SuspendedNavCom) {\n\t\tmono->Set_Cursor(38, 5);\n\t\tmono->Printf(\"%08X\", SuspendedNavCom);\n\t}\n\n\tif (Team) Team->Debug_Dump(mono);\n\tif (Group != 255) {\n\t\tmono->Set_Cursor(59, 1);mono->Printf(\"%d\", Group);\n\t}\n\n\tstatic char\tconst * _p2c[9] = {\"-\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\"};\n\tfor (int index = 0; index < min(12, ARRAY_SIZE(Path)); index++) {\n\t\tmono->Set_Cursor(54+index, 3);\n\t\tmono->Printf(\"%s\", _p2c[((ABS((int)Path[index]+1)) % ARRAY_SIZE(_p2c))]);\n\t}\n\tmono->Set_Cursor(54, 5);mono->Printf(\"%2d\", PathThreshhold);\n\tmono->Set_Cursor(72, 3);mono->Printf(\"%4d\", (long)PathDelay);\n\tmono->Set_Cursor(67, 3);mono->Printf(\"%3d\", TryTryAgain);\n\tif (HeadToCoord) {\n\t\tmono->Set_Cursor(60, 5);mono->Printf(\"%08X\", HeadToCoord);\n\t}\n\n\tTechnoClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * FootClass::Set_Speed -- Initiate unit movement physics.                                     *\n *                                                                                             *\n *    This routine is used to set a unit's velocity control structure.                         *\n *    The game will then process the unit's movement during the momentum                       *\n *    physics calculation.                                                                     *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the unit to alter.                                             *\n *                                                                                             *\n *          speed -- Throttle setting (0=stop, 255=full throttle).                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/07/1992 JLB : Created.                                                                 *\n *   09/24/1993 JLB : Revised for faster speed.                                                *\n *   04/02/1994 JLB : Revised for new system.                                                  *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   07/21/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid FootClass::Set_Speed(int speed)\n{\n\tassert(IsActive);\n\n\tspeed &= 0xFF;\n\t((unsigned char &)Speed) = speed;\n}\n\n\n/***********************************************************************************************\n * FootClass::Mark -- Unit interface to map rendering system.                                  *\n *                                                                                             *\n *    This routine is the interface function for units as they relate to                       *\n *    the map rendering system. Whenever a unit's imagery changes, this                        *\n *    function is called.                                                                      *\n *                                                                                             *\n * INPUT:   mark  -- Type of image change (MARK_UP, _DOWN, _CHANGE)                            *\n *             MARK_UP  -- Unit is removed.                                                    *\n *             MARK_CHANGE -- Unit alters image but doesn't move.                              *\n *             MARK_DOWN -- Unit is overlaid onto existing icons.                              *\n *                                                                                             *\n * OUTPUT:  bool; Did the marking operation succeed? Failure could be the result of marking    *\n *                down when it is already down, or visa versa.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1991 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *   12/23/1994 JLB : Performs low level check before processing.                              *\n *=============================================================================================*/\nbool FootClass::Mark(MarkType mark)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (TechnoClass::Mark(mark)) {\n//\t\tshort list[32];\n\t\tCELL cell = Coord_Cell(Coord);\n\n#ifndef PARTIAL\n\t\tif (In_Which_Layer() != LAYER_GROUND && (mark == MARK_UP || mark == MARK_DOWN)) mark = MARK_CHANGE;\n#endif\n\n\t\t/*\n\t\t**\tInform the map of the refresh, occupation, and overlap\n\t\t**\trequest.\n\t\t*/\n\t\tswitch (mark) {\n\t\t\tcase MARK_UP:\n\t\t\t\tMap.Pick_Up(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_DOWN:\n\t\t\t\tMap.Place_Down(cell, this);\n\t\t\t\tbreak;\n\n\t\t\tcase MARK_CHANGE_REDRAW:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List(true));\n\t\t\t\tMap.Refresh_Cells(cell, Occupy_List());\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tMap.Refresh_Cells(cell, Overlap_List());\n\t\t\t\tMap.Refresh_Cells(cell, Occupy_List());\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Basic_Path -- Finds the basic path for a ground object.                          *\n *                                                                                             *\n *    This is a common routine used by both infantry and other ground travelling units. It     *\n *    will fill in the unit's basic path to the NavCom destination.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was a path found? A failure to find a path means either the target cannot    *\n *                be found or the terrain prohibits the unit's movement.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Basic_Path(void)\n{\n\tassert(IsActive);\n\n\tPathType\t\t* path;\t\t\t// Pointer to path control structure.\n\tCELL\t\t\tcell;\n\tint \t\t\tskip_path = false;\n\n\tPath[0] = FACING_NONE;\n\n\tif (Target_Legal(NavCom)) {\n\t\tcell = As_Cell(NavCom);\n\n\t\t/*\n\t\t**\tWhen the navigation computer is set to a location that is impassible, then\n\t\t**\tfind a nearby cell that can be entered and try to head toward that instead.\n\t\t**\tEXCEPT when that cell is very close -- then just bail.\n\t\t*/\n\t\tint dist = Distance(NavCom);\n\t\tint checkdist = Team.Is_Valid() ? Rule.StrayDistance : Rule.CloseEnoughDistance;\n\t\tif (Can_Enter_Cell(cell) > MOVE_CLOAK && dist > checkdist) {\n\t\t\tCELL cell2 = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\tif (cell2 != 0 && ::Distance(Cell_Coord(cell), Cell_Coord(cell2)) < dist) cell = cell2;\n\t\t}\n\n\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\tCELL mycell = Coord_Cell(Center_Coord());\n\t\t\tObjectClass * obj = Map[mycell].Cell_Occupier();\n\t\t\twhile (obj) {\n\t\t\t\tif (obj != this && obj->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\tInfantryClass * inf = (InfantryClass *)obj;\n\t\t\t\t\tif (inf->NavCom == NavCom && inf->Path[0] != FACING_NONE) {\n\t\t\t\t\t\tif (Coord_Cell(inf->Head_To_Coord()) == Coord_Cell(inf->Coord)) {\n\t\t\t\t\t\t\tMem_Copy(&inf->Path[1], Path, sizeof(Path)-sizeof(Path[0]));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMem_Copy(inf->Path, Path, sizeof(Path));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Path[0] != FACING_NONE) {\n\t\t\t\t\t\t\tskip_path = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tobj = obj->Next;\n\t\t\t}\n\t\t}\n\n\t\tif (!skip_path) {\n\t\t\tMark(MARK_UP);\n\t\t\tPath[0] = FACING_NONE;\t\t// Probably not necessary, but...\n\n\t\t\t/*\n\t\t\t**\tTry to find a path to the destination. If a failure occurs, then keep trying\n\t\t\t**\twith greater determination until either a complete failure occurs, or a decent\n\t\t\t**\tpath was found.\n\t\t\t*/\n\t\t\tbool\t\t\tfound1=false;\t\t// Found a best path yet?\n\t\t\tPathType\t   path1;\n\t\t\tFacingType\tworkpath1[200];\t// Staging area for path list.\n//\t\t\tFacingType\tworkpath2[200];\t// Staging area for path list.\n\t\t\tMoveType\t\tmaxtype = MOVE_TEMP;\n\t\t\tif (!House->IsHuman) {\n\t\t\t\tmaxtype = MOVE_TEMP;\n//\t\t\t\tmaxtype = MOVE_DESTROYABLE;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tFor simple movement missions by the human player, then don't\n\t\t\t\t**\tconsider friendly units as passable if close to the destination.\n\t\t\t\t**\tThis will prevent a human controlled unit from just sitting next\n\t\t\t\t**\tto a destination just because there is another friendly unit\n\t\t\t\t**\toccupying the destination location.\n\t\t\t\t*/\n\t\t\t\tif (Mission == MISSION_MOVE && Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\t\tmaxtype = MOVE_DESTROYABLE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTry to find a path to the destination. If there is a path\n\t\t\t**\tfailure, then try a more severe path method until the\n\t\t\t**\tmaximum severity is reached.\n\t\t\t*/\n\t\t\tfor (;;) {\n\t\t\t\tpath = Find_Path(cell, &workpath1[0], sizeof(workpath1), PathThreshhold);\n\t\t\t\tif (path && path->Cost) {\n\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\tfound1 = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA valid path was not found. Try the next greater path severity\n\t\t\t\t**\tlevel if the severity can be increased. If not, then consider this\n\t\t\t\t**\ta total failure.\n\t\t\t\t*/\n\t\t\t\tPathThreshhold++;\n\t\t\t\tif (PathThreshhold > maxtype) break;\n\t\t\t}\n\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tDetermine if ANY path could be calculated by first examining the most\n\t\t\t**\taggressive case. If this fails, then no path will succeed. Further\n\t\t\t**\tscanning is unnecessary.\n\t\t\t*/\n\t\t\tpath = Find_Path(cell, &workpath1[0], sizeof(workpath1), maxtype);\n\t\t\tif (path && path->Cost) {\n\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\tfound1 = true;\n\n\t\t\t\t/*\n\t\t\t\t**\tScan for the best path possible. If this succeeds, then do a simple\n\t\t\t\t**\tcomparison with the most aggressive path. If they are very close, then\n\t\t\t\t**\tgo with the best (easiest) path method.\n\t\t\t\t*/\n\t\t\t\tpath = Find_Path(cell, &workpath2[0], sizeof(workpath2), MOVE_CLOAK);\n\t\t\t\tif (path && path->Cost && path->Cost < max((path1.Cost + (path1.Cost/2)), 3)) {\n\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\tmemcpy(workpath1, workpath2, sizeof(workpath1));\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe easiest path method didn't result in a satisfactory path. Scan through\n\t\t\t\t\t**\tthe rest of the path options, looking for the best one.\n\t\t\t\t\t*/\n\t\t\t\t\tfor (MoveType move = (MoveType)(MOVE_CLOAK+1); move < (MoveType)(maxtype-1); move++) {\n//\t\t\t\t\tfor (MoveType move = MOVE_MOVING_BLOCK; move < maxtype-1; move++) {\n\t\t\t\t\t\tpath = Find_Path(cell, &workpath2[0], sizeof(workpath2), move);\n\t\t\t\t\t\tif (path && path->Cost && path->Cost < max((path1.Cost + (path1.Cost/2)), 3)) {\n\t\t\t\t\t\t\tmemcpy(&path1, path, sizeof(path1));\n\t\t\t\t\t\t\tmemcpy(workpath1, workpath2, sizeof(workpath1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\n\t\t\t/*\n\t\t\t**\tIf a good path was found, then record it in the object's path\n\t\t\t**\tlist.\n\t\t\t*/\n\t\t\tif (found1) {\n\t\t\t\tFixup_Path(&path1);\n\t\t\t\tmemcpy(&Path[0], &workpath1[0], min(path->Length, (int)sizeof(Path)));\n\t\t\t}\n\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\n\t\tPathDelay = Rule.PathDelay * TICKS_PER_MINUTE;\n\t\tif (Path[0] != FACING_NONE) return(true);\n\n\t\t/*\n\t\t**\tIf a basic path couldn't be determined, then abort the navigation process.\n\t\t*/\n\t\tStop_Driver();\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Move -- AI process for moving a vehicle to its destination.              *\n *                                                                                             *\n *    This simple AI script handles moving the vehicle to its desired destination. Since       *\n *    simple movement is handled directly by the engine, this routine merely waits until       *\n *    the unit has reached its destination, and then causes the unit to enter idle mode.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *   10/02/1996 JLB : Player controlled or human owned units don't scan for targets.           *\n *=============================================================================================*/\nint FootClass::Mission_Move(void)\n{\n\tassert(IsActive);\n\n\tif (!Target_Legal(NavCom) && !IsDriving && MissionQueue == MISSION_NONE) {\n\t\tEnter_Idle_Mode();\n\t\treturn(1);\n\t}\n//\tif (!Target_Legal(TarCom) && !House->IsPlayerControl && !House->IsHuman) {\n\tif (!Target_Legal(TarCom) && !House->IsPlayerControl && !House->IsHuman && (!Team.Is_Valid() || !Team->Class->IsSuicide)) {\n\t\tTarget_Something_Nearby(THREAT_RANGE);\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Capture -- Handles the capture mission.                                  *\n *                                                                                             *\n *    Capture missions are nearly the same as normal movement missions. The only difference    *\n *    is that the final destination is handled in a special way so that it is not marked as    *\n *    impassable. This allows the object (usually infantry) the ability to walk onto the       *\n *    object and thus capture it.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game ticks to delay before calling this routine.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Capture(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf there is a valid TarCom but the NavCom isn't set, then set the NavCom accordingly.\n\t*/\n\tif (Is_Target_Building(TarCom) && !Target_Legal(NavCom) && What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsBomber) {\n\t\tAssign_Destination(TarCom);\n\t}\n\n\tif (!Target_Legal(NavCom) /*&& !In_Radio_Contact()*/) {\n\t\tEnter_Idle_Mode();\n\t\tif (Map[Center_Coord()].Cell_Building()) {\n\t\t\tScatter(0, true);\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Attack -- AI for heading towards and firing upon target.                 *\n *                                                                                             *\n *    This AI routine handles heading to within range of the target and then firing upon       *\n *    it until it is destroyed. If the target is destroyed, then the unit will change          *\n *    missions to match its \"idle mode\" of operation (usually guarding).                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Attack(void)\n{\n\tassert(IsActive);\n\tif (Target_Legal(TarCom)) {\n\t\tApproach_Target();\n\t} else {\n\t\tEnter_Idle_Mode();\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Guard -- Handles the AI for guarding in place.                           *\n *                                                                                             *\n *    Units that are performing stationary guard duty use this AI process. They will sit       *\n *    still and target any enemies that get within range.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the delay before calling this routine again.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Guard(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this unit is on an impassable cell for any reason, it needs to scatter immediately\n\t*/\n\tif (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT) {\n\t\tLandType land = Map[Coord].Land_Type();\n\t\tif (!Target_Legal(NavCom) && (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER)) {\n\t\t\tScatter(0, true, true);\n\t\t\tShorten_Mission_Timer();\n\t\t}\n\t}\n\n\tif (!Target_Something_Nearby(THREAT_RANGE)) {\n\t\tRandom_Animate();\n\t}\n\n\tint dtime = MissionControl[Mission].Normal_Delay();\n\tif (What_Am_I() == RTTI_VESSEL) {\n\t\tswitch (((VesselClass *)this)->Class->Type) {\n\t\t\tcase VESSEL_DD:\n\t\t\tcase VESSEL_PT:\n\t\t\t\tdtime = MissionControl[Mission].AA_Delay();\n\t\t\t\tbreak;\n\n\t\t\tcase VESSEL_CA:\n\t\t\t\tdtime *= 2;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (What_Am_I() == RTTI_INFANTRY) {\n\n\t\t/*\n\t\t**\tIf this is a bomber type infantry and the current target is a building, then go into\n\t\t**\tsabotage mode if not already.\n\t\t*/\n\t\tif (!House->IsHuman && Is_Target_Building(TarCom) && ((InfantryClass *)this)->Class->IsBomber && Mission != MISSION_SABOTAGE) {\n\t\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\t}\n\n\t\tswitch (((InfantryClass *)this)->Class->Type) {\n\t\t\tcase INFANTRY_E1:\n\t\t\tcase INFANTRY_E3:\n\t\t\t\tdtime = MissionControl[Mission].AA_Delay();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn((Arm != 0) ? (int)Arm : (dtime+Random_Pick(0, 2)));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Hunt -- Handles the default hunt order.                                  *\n *                                                                                             *\n *    This routine is the default hunt order for game objects. It handles searching for a      *\n *    nearby object and heading toward it. The act of targeting will cause it to attack        *\n *    the target it selects.                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the game tick delay before calling this routine again.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Hunt(void)\n{\n\tassert(IsActive);\n\tif (!Target_Something_Nearby(THREAT_NORMAL)) {\n#if(0)\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)this == INFANTRY_GENERAL && House->Class->House==HOUSE_UKRAINE && Scen.Scenario==47) {\n\t\tfor(int index=0; index < Buildings.Count(); index++) {\n\t\t\tif(Buildings.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Buildings.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Units.Count(); index++) {\n\t\t\tif(Units.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Units.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Infantry.Count(); index++) {\n\t\t\tif(Infantry.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Infantry.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor(index=0; index < Aircraft.Count(); index++) {\n\t\t\tif(Aircraft.Ptr(index)->IsOwnedByPlayer) {\n\t\t\t\tAssign_Target(Aircraft.Ptr(index)->As_Target());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n#endif\n\t\tRandom_Animate();\n\t} else {\n\t\tif (What_Am_I() == RTTI_INFANTRY && ( ((InfantryTypeClass const &)Class_Of()).Type == INFANTRY_RENOVATOR || ((InfantryTypeClass const &)Class_Of()).Type == INFANTRY_THIEF) ) {\n\t\t\tAssign_Destination(TarCom);\n\t\t\tAssign_Mission(MISSION_CAPTURE);\n\t\t} else {\n\t\t\tif (What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)this)->Class->IsBomber && Is_Target_Building(TarCom)) {\n\t\t\t\tAssign_Destination(TarCom);\n\t\t\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\t\t} else {\n\t\t\t\tApproach_Target();\n\t\t\t}\n\t\t}\n\t}\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Stop_Driver -- This routine clears the driving state of the object.              *\n *                                                                                             *\n *    This is the counterpart routine to the Start_Driver function. It clears the driving      *\n *    status flags and destination coordinate record.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was driving stopped?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nbool FootClass::Stop_Driver(void)\n{\n\tassert(IsActive);\n\n\tif (HeadToCoord) {\n\t\tHeadToCoord = NULL;\n\t\tSet_Speed(0);\n\t\tIsDriving = false;\n\t\tIsMovingOntoBridge = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Start_Driver -- This starts the driver heading to the destination desired.       *\n *                                                                                             *\n *    Before a unit can move it must be started by this routine. This routine handles          *\n *    reserving the cell and setting the driving flag.                                         *\n *                                                                                             *\n * INPUT:   headto   -- The coordinate of the immediate drive destination. This is one cell    *\n *                      away from the unit's current location.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was driving initiated?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Uses simple spot index finder.                                           *\n *=============================================================================================*/\nbool FootClass::Start_Driver(COORDINATE &headto)\n{\n\tassert(IsActive);\n\n\tStop_Driver();\n\tif (headto) {\n\t\tHeadToCoord = headto;\n\t\tIsDriving = true;\n\n\t\tCellClass * cellptr = &Map[headto];\n\t\tTemplateType ttype = cellptr->TType;\n\t\tIsMovingOntoBridge = (ttype >= TEMPLATE_BRIDGE1 && ttype <= TEMPLATE_BRIDGE2D) || (ttype >= TEMPLATE_BRIDGE_1A && ttype <= TEMPLATE_BRIDGE_3F);\n\n\t\t/*\n\t\t**\tCheck for crate goodie finder here.\n\t\t*/\n\t\tif (Map[headto].Goodie_Check(this)) {\n\t\t\treturn(true);\n\t\t}\n\t\tif (!IsActive) return(false);\n\n\t\tHeadToCoord = NULL;\n\t\tIsDriving = false;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Sort_Y -- Determine the sort coordinate for foot class objects.                  *\n *                                                                                             *\n *    This routine will determine the sort coordinate for foot class object. This coordinate   *\n *    is usually the coordinate of the object. The exception is if the object is tethered.     *\n *    In this case (presumes offloading to the north), the sorting coordinate is adjusted      *\n *    so that the object will be drawn on top of the transport unit.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to use for sorting.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   11/04/1994 JLB : Sort value is different when unloading from aircraft.                    *\n *=============================================================================================*/\nCOORDINATE FootClass::Sort_Y(void) const\n{\n\tassert(IsActive);\n\n\tif (IsUnloading) {\n\t\treturn(Coord_Add(Coord, 0x01000000L));\n\t}\n\tif (In_Radio_Contact() && IsTethered && Contact_With_Whom()->What_Am_I() == RTTI_UNIT) {\n\t\treturn(Coord_Add(Coord, 0x01000000L));\n\t}\n\treturn(Coord_Add(Coord, 0x00300000L));\n}\n\n\n/***********************************************************************************************\n * FootClass::Stun -- Prepares a ground travelling object for removal.                         *\n *                                                                                             *\n *    This routine clears the units' navigation computer in preparation for removal from the   *\n *    game. This is probably called as a result of unit destruction in combat. Clearing the    *\n *    navigation computer ensures that the normal AI process won't start it moving again while *\n *    the object is undergoing any death animations.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Stun(void)\n{\n\tassert(IsActive);\n\n\tAssign_Destination(TARGET_NONE);\n\tPath[0] = FACING_NONE;\n\tStop_Driver();\n\tTechnoClass::Stun();\n}\n\n\n/***********************************************************************************************\n * FootClass::Approach_Target -- Sets the navigation computer to approach target object.       *\n *                                                                                             *\n *    This routine will set the navigation computer to approach the target indicated by the    *\n *    targeting computer. It is through this function that the unit nears the target so        *\n *    that weapon firing may occur.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/13/1994 JLB : Made part of TechnoClass.                                                *\n *   12/22/1994 JLB : Enhanced search algorithm.                                               *\n *   05/20/1995 JLB : Always approaches if the object is off the map.                          *\n *=============================================================================================*/\nvoid FootClass::Approach_Target(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tDetermine that if there is an existing target it is still legal\n\t**\tand within range.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\n\t\t/*\n\t\t**\tIf the target is too far away then head toward it.\n\t\t*/\n\t\tint maxrange = Weapon_Range(primary);\n//\t\tint maxrange = max(Weapon_Range(0), Weapon_Range(1));\n\n\t\tif (!Target_Legal(NavCom) && (!In_Range(TarCom, primary) || !IsLocked)) {\n//\t\tif (!Target_Legal(NavCom) && (Distance(TarCom) > maxrange || !IsLocked)) {\n\n\t\t\t/*\n\t\t\t** If the object that we are attacking is a building adjust the unit's\n\t\t\t** max range so that people can stand far away from the buildings and\n\t\t\t** hit them.\n\t\t\t*/\n\t\t\tBuildingClass * obj = As_Building(TarCom);\n\t\t\tif (obj) {\n\t\t\t\tmaxrange += ((obj->Class->Width() + obj->Class->Height()) * (0x100 / 4));\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Adjust the max range of an infantry unit for where he is standing\n\t\t\t** in the room.\n\t\t\t*/\n\t\t\tmaxrange -= 0x00B7;\n#ifdef OBSOLETE\n\t\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\tmaxrange -= 0x0111;\n\t\t\t} else {\n\t\t\t\tmaxrange -= 0x00B7;\n\t\t\t}\n#endif\n\t\t\tmaxrange = max(maxrange, 0);\n\n\t\t\tCOORDINATE tcoord = ::As_Coord(TarCom);\n\t\t\tCOORDINATE trycoord = 0;\n\t\t\tCELL tcell = Coord_Cell(tcoord);\n\t\t\tCELL trycell = tcell;\n\t\t\tDirType dir = Direction256(tcoord, Center_Coord());\n\t\t\tbool found = false;\n\n\t\t\t/*\n\t\t\t**\tSweep through the cells between the target and the unit, looking for\n\t\t\t**\ta cell that the unit can enter but which is also within weapon range\n\t\t\t**\tof the target. If after a reasonable search, no appropriate cell could\n\t\t\t**\tbe found, then the target will be assigned as the movement destination\n\t\t\t**\tand let \"the chips fall where they may.\"\n\t\t\t*/\n\t\t\tfor (int range = maxrange; range > 0x0080; range -= 0x0100) {\n\t\t\t\tstatic int _angles[] = {0, 8, -8, 16, -16, 24, -24, 32, -32, 48, -48, 64, -64};\n\n\t\t\t\tfor (int index = 0; index < (sizeof(_angles)/sizeof(_angles[0])); index++) {\n\t\t\t\t\ttrycoord = Coord_Move(tcoord, (DirType)(dir + _angles[index]), range);\n\n\t\t\t\t\tif (::Distance(trycoord, tcoord) < range) {\n\t\t\t\t\t\ttrycell = Coord_Cell(trycoord);\n\t\t\t\t\t\tif (Map.In_Radar(trycell) && Map[trycell].Is_Clear_To_Move(Techno_Type_Class()->Speed, false, false, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone)) {\n//\t\t\t\t\t\tif (Can_Enter_Cell(trycell) <= MOVE_CLOAK && Map.In_Radar(trycell)) {\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found) break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a suitable intermediate location was found, then head toward it.\n\t\t\t**\tOtherwise, head toward the enemy unit directly.\n\t\t\t**\tInfantry always head towards the target since they can enter a cell\n\t\t\t**\tin range, but still not be able to hit the target if the spot is out of range.\n\t\t\t*/\n\t\t\tif (What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\tAssign_Destination(TarCom);\n\t\t\t} else if (found) {\n\t\t\t\tAssign_Destination(::As_Target(trycell));\n\t\t\t} else {\n\n\t\t\t\ttrycell = Map.Nearby_Location(trycell, Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\t\tAssign_Destination(::As_Target(trycell));\n//\t\t\t\tAssign_Destination(TarCom);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Guard_Area -- Causes unit to guard an area about twice weapon range.     *\n *                                                                                             *\n *    This mission routine causes the unit to scan for targets out to twice its weapon range   *\n *    from the home point. If a target was found, then it will be attacked. The unit will      *\n *    chase the target until it gets up to to its weapon range from the home position.         *\n *    In that case, it will return to home position and start scanning for another target.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with time delay before calling this routine again.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *   07/27/1995 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nint FootClass::Mission_Guard_Area(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf this unit is on an impassable cell for any reason, it needs to scatter immediately\n\t*/\n\tif (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT) {\n\t\tLandType land = Map[Coord].Land_Type();\n\t\tif (!Target_Legal(NavCom) && (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER)) {\n\t\t\tScatter(0, true, true);\n\t\t\tShorten_Mission_Timer();\n\t\t}\n\t}\n\n\tif (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Class->IsToHarvest) {\n\t\tAssign_Mission(MISSION_HARVEST);\n\t\treturn(1+Random_Pick(1, 10));\n\t}\n\n\t/*\n\t**\tEnsure that the archive target is valid.\n\t*/\n\tif (!Target_Legal(ArchiveTarget)) {\n\t\tArchiveTarget = ::As_Target(Coord);\n\t}\n\n\t/*\n\t**\tEnsure units aren't trying to guard cells off the map.\n\t*/\n\tif (Target_Legal(NavCom) && Is_Target_Cell(NavCom)) {\n\t\tCELL cell = As_Cell(NavCom);\n\t\tint x = Cell_X(cell);\n\t\tint y = Cell_Y(cell);\n\t\tif (x < Map.MapCellX || y < Map.MapCellY || x >= (Map.MapCellX + Map.MapCellWidth) || y >= (Map.MapCellY + Map.MapCellHeight)) {\n\t\t\tAssign_Target(TARGET_NONE);\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\tArchiveTarget = ::As_Target(Coord);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this is a bomber type infantry and the current target is a building, then go into\n\t**\tsabotage mode if not already.\n\t*/\n\tif (!House->IsHuman && What_Am_I() ==  RTTI_INFANTRY && Is_Target_Building(TarCom) && ((InfantryClass *)this)->Class->IsBomber && Mission != MISSION_SABOTAGE) {\n\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\treturn(1);\n\t}\n\n\t/*\n\t**\tMake sure that the unit has not strayed too far from the home position.\n\t**\tIf it has, then race back to it.\n\t*/\n\tint maxrange = Threat_Range(1)/2;\n\n\tif (!IsFiring && !Target_Legal(NavCom) && Distance(ArchiveTarget) > maxrange) {\n\t\tAssign_Target(TARGET_NONE);\n\t\tAssign_Destination(ArchiveTarget);\n\t}\n\n\tif (!Target_Legal(TarCom)) {\n\t\tCOORDINATE old = Coord;\n\t\tCoord = As_Coord(ArchiveTarget);\n\t\tTarget_Something_Nearby(THREAT_AREA);\n\t\tCoord = old;\n\t\tif (Target_Legal(TarCom)) {\n\t\t\treturn(1);\n\t\t}\n\t\tRandom_Animate();\n\t} else {\n\t\tApproach_Target();\n\t}\n\n\tint dtime = MissionControl[Mission].Normal_Delay();\n\tif (What_Am_I() == RTTI_AIRCRAFT) {\n\t\tdtime *= 2;\n\t}\n\treturn(dtime + Random_Pick(1, 5));\n}\n\n\n/***********************************************************************************************\n * FootClass::Unlimbo -- Unlimbos object and performs special fixups.                          *\n *                                                                                             *\n *    This routine will make sure that the home position for the foot class object gets        *\n *    reset. This is necessary since the home position may change depending on the unit's      *\n *    transition between limbo and non-limbo condition.                                        *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to unlimbo the unit at.                                 *\n *                                                                                             *\n *          dir      -- The initial direction to give the unit.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the unit unlimboed successfully?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Unlimbo(COORDINATE coord, DirType dir)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tTry to unlimbo the unit.\n\t*/\n\tif (TechnoClass::Unlimbo(coord, dir)) {\n\n\t\t/*\n\t\t**\tMobile units are always revealed to the house that owns them.\n\t\t*/\n\t\tRevealed(House);\n\n\t\t/*\n\t\t**\tStart in a still (non-moving) state.\n\t\t*/\n\t\tPath[0] = FACING_NONE;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Take_Damage -- Handles taking damage to this object.                             *\n *                                                                                             *\n *    This routine intercepts the damage assigned to this object and if this object is         *\n *    a member of a team, it informs the team that the damage has occurred. The team may       *\n *    change it's priority or action based on this event.                                      *\n *                                                                                             *\n * INPUT:   damage      -- The damage points inflicted on the unit.                            *\n *                                                                                             *\n *          distance    -- The distance from the point of damage to the unit itself.           *\n *                                                                                             *\n *          warhead     -- The type of damage that is inflicted.                               *\n *                                                                                             *\n *          source      -- The perpetrator of the damage. By knowing who caused the damage,    *\n *                         the team know's who to \"get even with\".                             *\n *                                                                                             *\n * OUTPUT:  Returns with the result type of the damage.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nResultType FootClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(IsActive);\n\n\tResultType result = TechnoClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\tif (result != RESULT_NONE && Team) {\n\n\t\tTeam->Took_Damage(this, result, source);\n\n\t} else {\n\n\t\tif (result != RESULT_DESTROYED && result != RESULT_NONE) {\n\n\t\t\t/*\n\t\t\t**\tDetermine if the target that is currently being attacked has a weapon that can\n\t\t\t**\tdo harm to a ground based unit. This information is needed so that an appropriate\n\t\t\t**\tresponse will occur when damage is taken.\n\t\t\t*/\n//\t\t\tbool tweap = false;\n//\t\t\tif (As_Techno(TarCom)) {\n//\t\t\t\ttweap = (As_Techno(TarCom)->Techno_Type_Class()->PrimaryWeapon != NULL);\n//\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThis ensures that if a unit is in sticky mode, then it will snap out of\n\t\t\t**\tit when it takes damage.\n\t\t\t*/\n\t\t\tif (source != NULL && MissionControl[Mission].IsNoThreat && !MissionControl[Mission].IsZombie) {\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this object is not part of a team and it can retaliate for the damage, then have\n\t\t\t**\tit try to do so. This prevents it from just sitting there and taking damage.\n\t\t\t*/\n\t\t\tif (Is_Allowed_To_Retaliate(source)) {\n\n\t\t\t\tint primary = What_Weapon_Should_I_Use(source->As_Target());\n\t\t\t\tif (In_Range(source, primary) || !House->IsHuman) {\n\t\t\t\t\tAssign_Target(source->As_Target());\n\t\t\t\t}\n\n\t\t\t\tif (Mission == MISSION_AMBUSH) {\n\t\t\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSimple retaliation cannot occur because the source of the damage\n\t\t\t\t**\tis too far away. If scatter logic is enabled, then scatter now.\n\t\t\t\t*/\n\t\t\t\tif (!Target_Legal(TarCom) && !Target_Legal(NavCom) && Rule.IsScatter) {\n\t\t\t\t\tScatter(0, true);\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this object isn't doing anything important, then scatter.\n\t\t\t\t*/\n\t\t\t\tif (MissionControl[Mission].IsScatter && !IsTethered && !IsDriving && !Target_Legal(TarCom) && !Target_Legal(NavCom) && What_Am_I() != RTTI_AIRCRAFT && What_Am_I() != RTTI_VESSEL) {\n\t\t\t\t\tif (!House->IsHuman || Rule.IsScatter) {\n\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * FootClass::Active_Click_With -- Initiates attack or move according to target clicked on.    *\n *                                                                                             *\n *    At this level, the object is known to have the ability to attack or move to the          *\n *    target specified (in theory). Perform the attack or move as indicated.                   *\n *                                                                                             *\n * INPUT:   target   -- The target clicked upon that will precipitate action.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the type of action performed.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/06/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(IsActive);\n\tassert(object != NULL);\n\n\tswitch (action) {\n\t\tcase ACTION_GUARD_AREA:\n\t\t\tif (Can_Player_Fire() && Can_Player_Move()) {\n\t\t\t\tif (What_Am_I() == RTTI_INFANTRY &&\n\t\t\t\t\t\t((InfantryClass *)this)->Class->IsBomber &&\n\t\t\t\t\t\tobject->What_Am_I() == RTTI_BUILDING &&\n\t\t\t\t\t\t!House->Is_Ally(object)) {\n\n\t\t\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, object->As_Target());\n\t\t\t\t} else {\n\t\t\t\t\tPlayer_Assign_Mission(MISSION_GUARD_AREA, object->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SELF:\n\t\t\tPlayer_Assign_Mission(MISSION_UNLOAD);\n\t\t\tbreak;\n\n\t\tcase ACTION_ATTACK:\n\t\t\tif (Can_Player_Fire()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_ATTACK, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_ENTER:\n\t\t\tif (Can_Player_Move() && object && object->Is_Techno() /*&& !((RadioClass *)object)->In_Radio_Contact()*/) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_ENTER, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_CAPTURE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_CAPTURE, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, object->As_Target());\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_NOMOVE:\n\t\tcase ACTION_MOVE:\n\t\t\tif (Can_Player_Move()) {\n\n\t\t\t\tTARGET targ = object->As_Target();\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the destination object is not the same zone, then pick a nearby location.\n\t\t\t\t*/\n\t\t\t\tif (object->What_Am_I() != RTTI_AIRCRAFT && Techno_Type_Class()->Speed != SPEED_WINGED && Map[Coord].Zones[Techno_Type_Class()->MZone] != Map[object->Center_Coord()].Zones[Techno_Type_Class()->MZone]) {\n\n#ifdef FIXIT_MINE_PASSABLE\n\t\t\t\t\t// Fixes units not driving onto mines.\n\t\t\t\t\tif (Can_Enter_Cell(Coord_Cell(object->Center_Coord())) > MOVE_OK) {\n\t\t\t\t\t\ttarg = ::As_Target(Map.Nearby_Location(Coord_Cell(object->Center_Coord()), Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone));\n\t\t\t\t\t}\n#else\n\t\t\t\t\ttarg = ::As_Target(Map.Nearby_Location(Coord_Cell(object->Center_Coord()), Techno_Type_Class()->Speed, Map[Coord].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone));\n#endif\n\t\t\t\t}\n\n\t\t\t\tPlayer_Assign_Mission(MISSION_MOVE, TARGET_NONE, targ);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_NO_DEPLOY:\n\t\t\tSpeak(VOX_DEPLOY);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Active_Click_With -- Performs action as a result of left mouse click.            *\n *                                                                                             *\n *    This routine performs the action requested when the left mouse button was clicked over   *\n *    a cell. Typically, this is just a move command.                                          *\n *                                                                                             *\n * INPUT:   action   -- The predetermined action that should occur.                            *\n *                                                                                             *\n *          cell     -- The cell number that the action should occur at.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Active_Click_With(ActionType action, CELL cell)\n{\n\tassert(IsActive);\n\n\taction = What_Action(cell);\n\tswitch (action) {\n\t\tcase ACTION_HARVEST:\n\t\t\tPlayer_Assign_Mission(MISSION_HARVEST, TARGET_NONE, ::As_Target(cell));\n\t\t\tbreak;\n\n\t\tcase ACTION_MOVE:\n\t\t\tif (AllowVoice) {\n\t\t\t\tCOORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());\n\t\t\t\tOutList.Add(EventClass(ANIM_MOVE_FLASH, PlayerPtr->Class->House, coord, 1 << PlayerPtr->Class->House));\n\t\t\t}\n\t\t\t// Fall into next case.\n\n\t\tcase ACTION_NOMOVE:\n\t\t\t//using function for IsVisible so we have different results for different players - JAS 2019/09/30\n\t\t\tif (What_Am_I() != RTTI_AIRCRAFT || Map[cell].Is_Visible(PlayerPtr)) {\n\n\t\t\t\t/*\n\t\t\t\t** Find the closest same-zoned cell to where the unit currently is.\n\t\t\t\t** This will allow the unit to come as close to the destination cell\n\t\t\t\t** as is reasonably possible, when clicking on an impassable cell\n\t\t\t\t** (as is likely when clicking in the shroud.)  It looks for the\n\t\t\t\t** nearest cell using an expanding-radius box, and ignores cells\n\t\t\t\t** off the edge of the map.\n\t\t\t\t*/\n\t\t\t\tCellClass const * cellptr = &Map[::As_Cell(::As_Target(Center_Coord()))];\n\t\t\t\tif (What_Am_I() != RTTI_AIRCRAFT) {\n\n\t\t\t\t\tif (Can_Enter_Cell(Coord_Cell(Center_Coord())) == MOVE_OK) {\n\t\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, cellptr->Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);\n\t\t\t\t\t}\n#ifdef OBSOLETE\n\t\t\t\t\tcell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed, cellptr->Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone);\n#endif\n\t\t\t\t}\n\n\t\t\t\tPlayer_Assign_Mission(MISSION_MOVE, TARGET_NONE, ::As_Target(cell));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_ATTACK:\n\t\t\tPlayer_Assign_Mission(MISSION_ATTACK, ::As_Target(cell));\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Engineer attempting to capture bridge to repair it\n\t\t*/\n\t\tcase ACTION_CAPTURE:\n\t\t\tif (Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_CAPTURE, TARGET_NONE, ::As_Target(cell));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\t\tPlayer_Assign_Mission(MISSION_SABOTAGE, TARGET_NONE, ::As_Target(cell) );\n\t\t\tbreak;\n\n\t\t// MBL 05.15.2020 - Adding support for CTRL+ALT clicking the ground to have units move to an area and guard it\n\t\tcase ACTION_GUARD_AREA:\n\t\t\tif (Can_Player_Fire() && Can_Player_Move()) {\n\t\t\t\tPlayer_Assign_Mission(MISSION_GUARD_AREA, ::As_Target(cell));\n\t\t\t}\n\t\t\tbreak;\n\t\t// END MBL 05.15.2020 \n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Per_Cell_Process -- Perform action based on once-per-cell condition.             *\n *                                                                                             *\n *    This routine is called as this object moves from cell to cell. When the center of the    *\n *    cell is reached, check to see if any trigger should be sprung. For moving units, reduce  *\n *    the path to the distance to the target. This forces path recalculation in an effort to   *\n *    avoid units passing each other.                                                          *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   07/08/1995 JLB : Handles generic enter trigger event.                                     *\n *   07/16/1995 JLB : If next to a scanner and cloaked, then shimmer.                          *\n *=============================================================================================*/\nvoid FootClass::Per_Cell_Process(PCPType why)\n{\n\tassert(IsActive);\n\n\tif (why == PCP_END) {\n\n\t\tIsScattering = false;\n\n\t\t/*\n\t\t**\tClear any unloading flag if necessary.\n\t\t*/\n\t\tIsUnloading = false;\n\n\t\t/*\n\t\t**\tIf adjacent to an enemy techno that has the ability to reveal a sub,\n\t\t**\tthen shimmer the cloaked object.\n\t\t*/\n\t\tif (Cloak == CLOAKED) {\n\t\t\tfor (FacingType face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\t\tCELL cell = Adjacent_Cell(Coord_Cell(Coord), face);\n\n\t\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\t\tTechnoClass const * techno = Map[cell].Cell_Techno();\n\n\t\t\t\t\tif (techno && !techno->House->Is_Ally(this) && techno->Techno_Type_Class()->IsScanner) {\n\t\t\t\t\t\tDo_Shimmer();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tShorten the path if the target is now within weapon range of this\n\t\t**\tunit and this unit is on an attack type mission. But only if the target\n\t\t**\tis slow enough for leading to make sense.\n\t\t*/\n\t\tif (Target_Legal(TarCom) && (What_Am_I() != RTTI_INFANTRY || !((InfantryClass *)this)->Class->IsDog)) {\n\t\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\t\t\tbool inrange = In_Range(TarCom, primary);\n\t\t\tTechnoClass const * techno = As_Techno(TarCom);\n\t\t\tif (techno != NULL && techno->Is_Foot()) {\n\t\t\t\tFootClass const * foot = (FootClass const *)techno;\n\t\t\t\tMPHType speed = ((TechnoTypeClass const &)techno->Class_Of()).MaxSpeed;\n\t\t\t\tCOORDINATE rangecoord = (speed > MPH_SLOW) ? foot->Likely_Coord() : foot->Target_Coord();\n\t\t\t\tinrange = In_Range(rangecoord, primary);\n\t\t\t}\n\n\t\t\tif ((Mission == MISSION_RESCUE || Mission == MISSION_GUARD_AREA || Mission == MISSION_ATTACK || Mission == MISSION_HUNT) && inrange) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTrigger event associated with the player entering the cell.\n\t\t*/\n\t\tif (Cloak != CLOAKED) {\n\t\t\tTriggerClass * trigger = Map[Coord].Trigger;\n\t\t\tif (trigger != NULL) {\n\t\t\t\ttrigger->Spring(TEVENT_PLAYER_ENTERED, this, Coord_Cell(Coord));\n\t\t\t\tif (!IsActive) return;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for horizontal trigger crossing.\n\t\t\t*/\n\t\t\tint x = Cell_X(Coord_Cell(Coord));\n\t\t\tint y = Cell_Y(Coord_Cell(Coord));\n\t\t\tint index;\n\t\t\tfor (index = 0; index < Map.MapCellWidth; index++) {\n\t\t\t\ttrigger = Map[XY_Cell(index+Map.MapCellX, y)].Trigger;\n\t\t\t\tif (trigger != NULL) {\n\t\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_CROSS_HORIZONTAL || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_CROSS_HORIZONTAL)) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_CROSS_HORIZONTAL, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for vertical trigger crossing.\n\t\t\t*/\n\t\t\tfor (index = 0; index < Map.MapCellHeight; index++) {\n\t\t\t\ttrigger = Map[XY_Cell(x, index+Map.MapCellY)].Trigger;\n\t\t\t\tif (trigger != NULL) {\n\t\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_CROSS_VERTICAL || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_CROSS_VERTICAL)) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_CROSS_VERTICAL, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCheck for zone entry trigger events.\n\t\t\t*/\n\t\t\tfor (MapTriggerID = 0; MapTriggerID < MapTriggers.Count(); MapTriggerID++) {\n\t\t\t\ttrigger = MapTriggers[MapTriggerID];\n\t\t\t\tif (trigger->Class->Event1.Event == TEVENT_ENTERS_ZONE || (trigger->Class->EventControl != MULTI_ONLY && trigger->Class->Event2.Event == TEVENT_ENTERS_ZONE)) {\n\t\t\t\t\tif (Map[trigger->Cell].Zones[Techno_Type_Class()->MZone] == Map[Coord].Zones[Techno_Type_Class()->MZone]) {\n\t\t\t\t\t\ttrigger->Spring(TEVENT_ENTERS_ZONE, this, Coord_Cell(Coord));\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf any of these triggers cause this unit to be destroyed, then\n\t\t\t**\tstop all further processing for this unit.\n\t\t\t*/\n\t\t\tif (!IsActive) return;\n\t\t}\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Flag any gap generators to re-draw\n\t\t*/\n\t\tfor (int index = 0; index <Buildings.Count(); index++) {\n\t\t\tBuildingClass * obj = Buildings.Ptr(index);\n\t\t\tif (obj && *obj == STRUCT_GAP && !obj->IsInLimbo && (HouseClass *)obj->House != PlayerPtr) {\n\t\t\t\tint dist = Distance(obj) / CELL_LEPTON_W;\n\t\t\t\tif (dist < (6 + Rule.GapShroudRadius) ) {\n\t//\t\t\tif (dist < (6 + obj->Class->SightRange) ) {\n\t\t\t\t\tobj->IsJamming = false;\t// lie so it'll re-jam now\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\t}\n\n\tTechnoClass::Per_Cell_Process(why);\n}\n\n\n/***************************************************************************\n * FootClass::Override_Mission -- temporarily overrides a units mission    *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:\t\tMissionType mission - the mission we want to override       *\n *\t\t\t\t\tTARGET\t   tarcom  - the new target we want to override\t\t*\n *\t\t\t\t\tTARGET\t\tnavcom  - the new navigation point to override\t*\n *                                                                         *\n * OUTPUT:\t\tnone                                                        *\n *                                                                         *\n * WARNINGS:   If a mission is already overridden, the current mission is  *\n *\t\t\t\t\tjust re-assigned.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid FootClass::Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom)\n{\n\tassert(IsActive);\n\n \tSuspendedNavCom = NavCom;\n\tTechnoClass::Override_Mission(mission, tarcom, navcom);\n\n\tAssign_Destination(navcom);\n}\n\n\n/***************************************************************************\n * FootClass::Restore_Mission -- Restores an overridden mission            *\n *                                                                         *\n * INPUT:\t\tnone                                                        *\n *                                                                         *\n * OUTPUT:     none                                                        *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/28/1995 PWG : Created.                                             *\n *=========================================================================*/\nbool FootClass::Restore_Mission(void)\n{\n\tassert(IsActive);\n\n\tif (TechnoClass::Restore_Mission()) {\n\t\tAssign_Destination(SuspendedNavCom);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Receive_Message -- Movement related radio messages are handled here.             *\n *                                                                                             *\n *    This routine handles radio message that are related to movement. These are used for      *\n *    complex coordinated maneuvers.                                                           *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the originator of this radio message.                       *\n *                                                                                             *\n *          message  -- The radio message that is being received.                              *\n *                                                                                             *\n *          param    -- The optional parameter (could be a movement destination).              *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response appropriate to the message received. Usually the   *\n *          response is RADIO_ROGER.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType FootClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tAnswers if this object is located on top of a service depot.\n\t\t*/\n\t\tcase RADIO_ON_DEPOT:\n\t\t\tif (Map[Center_Coord()].Cell_Building() != NULL) {\n\t\t\t\tBuildingClass const * building = Map[Center_Coord()].Cell_Building();\n\t\t\t\tif (*building == STRUCT_REPAIR) {\n\t\t\t\t\treturn(RADIO_ROGER);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tIntercept the repair request and if this object is moving, then no repair\n\t\t**\tis possible.\n\t\t*/\n\t\tcase RADIO_REPAIR:\n\t\t\tif (Target_Legal(NavCom)) return(RADIO_NEGATIVE);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSomething bad has happened to the object in contact with. Abort any coordinated\n\t\t**\tactivity with this object. Basically, ... run away! Run away!\n\t\t*/\n\t\tcase RADIO_RUN_AWAY:\n\t\t\tif (In_Radio_Contact()) {\n\t\t\t\tif (NavCom == Contact_With_Whom()->As_Target()) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Mission == MISSION_SLEEP) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\tCommence();\n\t\t\t}\n\t\t\tif (Mission == MISSION_ENTER) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t\tif (!IsRotating && !Target_Legal(NavCom)) {\n\t\t\t\tScatter(0, true, true);\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tChecks to see if this unit needs to move somewhere. If it is already in motion,\n\t\t**\tthen it doesn't need further movement instructions.\n\t\t*/\n\t\tcase RADIO_NEED_TO_MOVE:\n\t\t\tparam = (long)NavCom;\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\treturn(RADIO_NEGATIVE);\n\n\t\t/*\n\t\t**\tRadio request to move to location specified. Typically this is used\n\t\t**\tfor complex loading and unloading missions.\n\t\t*/\n\t\tcase RADIO_MOVE_HERE:\n\t\t\tif (NavCom != (TARGET)param) {\n\t\t\t\tif (::As_Target(Coord_Cell(Coord)) == (TARGET)param) {\n\t\t\t\t\treturn(RADIO_YEA_NOW_WHAT);\n\t\t\t\t} else {\n\t\t\t\t\tif (Mission == MISSION_GUARD && MissionQueue == MISSION_NONE) {\n\t\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\t\t\t}\n\t\t\t\t\tAssign_Destination((TARGET)param);\n\t\t\t\t\tShorten_Mission_Timer();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RADIO_ROGER);\n\n\t\t/*\n\t\t** Requests if this unit is trying to cooperatively load up. Typically, this occurs\n\t\t**\tfor passengers and when vehicles need to be repaired.\n\t\t*/\n\t\tcase RADIO_TRYING_TO_LOAD:\n\t\t\tif (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {\n\t\t\t\tTechnoClass::Receive_Message(from, message, param);\n\t\t\t\treturn(RADIO_ROGER);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn(TechnoClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Enter -- Enter (cooperatively) mission handler.                          *\n *                                                                                             *\n *    This mission handler will cooperatively coordinate the object to maneuver into the       *\n *    object it is in radio contact with. This is used by infantry when they wish to load      *\n *    into an APC as well as by vehicles when they wish to enter a repair facility.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game ticks before this routine should be called again.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/15/1995 JLB : Created.                                                                 *\n *   09/22/1995 JLB : Modified to handle the \"on hold\" condition.                              *\n *=============================================================================================*/\nint FootClass::Mission_Enter(void)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tFind out who to coordinate with. If in radio contact, then this the transporter is\n\t**\tdefined. If not in radio contact, then try the archive target value to see if that\n\t**\tis suitable.\n\t*/\n\tTechnoClass * contact = Contact_With_Whom();\n\tif (contact == NULL) {\n\t\tcontact = As_Techno(ArchiveTarget);\n\t}\n\n\t/*\n\t**\tIf in contact, then let the transporter handle the movement coordination.\n\t*/\n\tif (contact != NULL) {\n\n\t\t/*\n\t\t**\tIf the transport says to \"bug off\", then abort the enter mission. The transport may\n\t\t**\tlikely say all is 'ok' with the \"RADIO ROGER\", then try again later.\n\t\t*/\n\t\tif (Transmit_Message(RADIO_DOCKING, contact) != RADIO_ROGER && !IsTethered) {\n\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tSince there is no potential object to enter, then abort this\n\t\t**\tmission with some default standby mission.\n\t\t*/\n\t\tif (MissionQueue == MISSION_NONE) {\n\t\t\t/*\n\t\t\t**\tIf this is a harvester, then return to harvesting.\n\t\t\t**\tSet a hacky target so we know to skip to the proper state.\n\t\t\t*/\n\t\t\tif (What_Am_I() == RTTI_UNIT && ((UnitClass*)this)->Class->IsToHarvest) {\n\t\t\t\tAssign_Mission(MISSION_HARVEST);\n\t\t\t\tAssign_Target(As_Target());\n\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t} else {\n\t\t\t\tEnter_Idle_Mode();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}\n\n\n/***********************************************************************************************\n * FootClass::Assign_Destination -- Assigns specified destination to NavCom.                   *\n *                                                                                             *\n *    This routine will assign the specified target to the navigation computer. No legality    *\n *    checks are performed.                                                                    *\n *                                                                                             *\n * INPUT:   target   -- The target value to assign to the navigation computer.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Assign_Destination(TARGET target)\n{\n\tassert(IsActive);\n\n\tNavCom = target;\n\n\t/*\n\t**\tPresume that the easiest path is tried first. As the findpath proceeds, when\n\t**\ta failure occurs, this threshhold will be increased until path failure\n\t**\tcannot be prevent. At this point, all movement should cease.\n\t*/\n\tPathThreshhold = MOVE_CLOAK;\n}\n\n\n/***********************************************************************************************\n * FootClass::Detach_All -- Removes this object from the game system.                          *\n *                                                                                             *\n *    This routine will remove this object from the game system. This routine is called when   *\n *    this object is about to be deleted. All other objects should no longer reference this    *\n *    object in that case.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Detach_All(bool all)\n{\n\tassert(IsActive);\n\n\tif (Team && !ScenarioInit) {\n\t\tTeam->Remove(this);\n\t\tTeam = NULL;\n\t}\n\n\tTechnoClass::Detach_All(all);\n}\n\n\n/***********************************************************************************************\n * FootClass::Rescue_Mission -- Calls this unit to the rescue.                                 *\n *                                                                                             *\n *    This routine is called when the house determines that it should attack the specified     *\n *    target. This routine will determine if it can attack the target specified and if so,     *\n *    the amount of power it can throw at it. This returned power value is used to allow       *\n *    intelligent distribution of retaliation.                                                 *\n *                                                                                             *\n * INPUT:   target   -- The target that this object just might be assigned to attack and thus  *\n *                      how much power it can bring to bear should be returned.                *\n *                                                                                             *\n * OUTPUT:  Returns with the amount of power that this object can bring to bear against the    *\n *          potential target specified.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Rescue_Mission(TARGET tarcom)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf the target specified is not legal, then it cannot be attacked. Always return\n\t**\tzero in this case.\n\t*/\n\tif (!Target_Legal(tarcom)) return(0);\n\n\t/*\n\t** If the unit is already assigned to destroy the tarcom then we need\n\t** to return a negative value which tells the computer to lower the\n\t** desired threat rating.\n\t*/\n\tif (TarCom == tarcom) {\n\t\treturn(-Risk());\n\t}\n\n\t/*\n\t** If the unit is currently attacking a target that has a weapon then we\n\t** cannot abandon it as it will destroy us if we return to base.\n\t*/\n\tif (Target_Legal(TarCom)) {\n\t\tTechnoClass * techno = As_Techno(TarCom);\n\t\tif (techno != NULL && techno->Is_Weapon_Equipped()) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\t/*\n\t** If the unit is in a harvest mission or is currently attacking\n\t** something, or is not very effective, then it will be of no help\n\t** at all.\n\t*/\n\tif (Team.Is_Valid() || Mission == MISSION_HARVEST || !Risk()) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t** Find the distance to the target modified by the range.  If the\n\t** the distance is 0, then things are ok.\n\t*/\n\tint dist = Distance(tarcom) - Weapon_Range(0);\n\tint threat = Risk() * 1024;\n\tint speed = -1;\n\tif (dist > 0) {\n\n\t\t/*\n\t\t** Next we need to figure out how fast the unit moves because this\n\t\t** decreases the distance penalty.\n\t\t*/\n\t\tspeed = max((unsigned)Techno_Type_Class()->MaxSpeed, (unsigned)1);\n\n\t\tint ratio = (speed > 0) ? Max(dist / speed, 1) : 1;\n\n\t\t/*\n\t\t** Finally modify the threat by the distance the unit is away.\n\t\t*/\n\t\tthreat = max(threat/ratio, 1);\n\t}\n\treturn(threat);\n}\n\n\n/***********************************************************************************************\n * FootClass::Death_Announcement -- Announces the death of a unit.                             *\n *                                                                                             *\n *    This routine is called when a unit (infantry, vehicle, or aircraft) is destroyed.        *\n *                                                                                             *\n * INPUT:   source   -- The perpetrator of this death.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Death_Announcement(TechnoClass const * ) const\n{\n\tassert(IsActive);\n\n\t//if (IsOwnedByPlayer) {\n\tif ((Session.Type == GAME_GLYPHX_MULTIPLAYER && House->IsHuman) || (Session.Type != GAME_GLYPHX_MULTIPLAYER && IsOwnedByPlayer)) {\n\t\tif (What_Am_I() == RTTI_VESSEL) {\n\t\t\t// Speak(VOX_SHIP_LOST); // MBL 02.06.2020\n\t\t\tSpeak(VOX_SHIP_LOST, House, Center_Coord());\n\t\t} else {\n\t\t\t// Speak(VOX_UNIT_LOST); // MBL 02.06.2020\n\t\t\tSpeak(VOX_UNIT_LOST, House, Center_Coord());\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Greatest_Threat -- Fetches the greatest threat to this object.                   *\n *                                                                                             *\n *    This routine will return with the greatest threat (best target) for this object. For     *\n *    movable ground object, they won't automatically return ANY target if this object is      *\n *    cloaked. Otherwise, cloaking is relatively useless.                                      *\n *                                                                                             *\n * INPUT:   method   -- The request method (bit flags) to use when scanning for a target.      *\n *                                                                                             *\n * OUTPUT:  Returns with the best target to attack. If there is no target that qualifies, then *\n *          TARGET_NONE is returned.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles scan range limitation.                                           *\n *=============================================================================================*/\nTARGET FootClass::Greatest_Threat(ThreatType method) const\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tIf the scan is forced to be limited, then limit the scan now.\n\t*/\n\tif (IsScanLimited) {\n\t\tmethod = method & ~THREAT_AREA;\n\t\tmethod = method | THREAT_RANGE;\n\t}\n\n\t/*\n\t**\tIf this object can cloak, then it won't select a target automatically.\n\t*/\n\tif (House->IsHuman && IsCloakable && Mission == MISSION_GUARD) {\n\t\treturn(TARGET_NONE);\n\t}\n\n\tif (!(method & (THREAT_INFANTRY|THREAT_VEHICLES|THREAT_BUILDINGS|THREAT_TIBERIUM|THREAT_BOATS|THREAT_CIVILIANS|THREAT_POWER|THREAT_FAKES|THREAT_FACTORIES|THREAT_BASE_DEFENSE))) {\n\t\tif (What_Am_I() != RTTI_VESSEL) {\n\t\t\tmethod = method | THREAT_GROUND;\n\t\t} else {\n\t\t\tmethod = method | THREAT_BOATS|THREAT_GROUND;\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform the search for the target.\n\t*/\n\tTARGET target = TechnoClass::Greatest_Threat(method);\n\n\t/*\n\t**\tIf no target could be located and this object is under scan range\n\t**\trestrictions, then this restriction must be lifted now.\n\t*/\n\tif (IsScanLimited && target == TARGET_NONE) {\n\t\tconst_cast<FootClass*>(this)->IsScanLimited = false;\t\t// const_cast ST - 5/8/2019\n\t}\n\n\t/*\n\t**\tReturn with final target found.\n\t*/\n\treturn(target);\n}\n\n\n/***********************************************************************************************\n * FootClass::Detach -- Detaches a target from tracking systems.                               *\n *                                                                                             *\n *    This routine will detach the specified target from the tracking systems of this object.  *\n *    It will be removed from the navigation computer and any queued mission record.           *\n *                                                                                             *\n * INPUT:   target   -- The target to be removed from this object.                             *\n *                                                                                             *\n *          all      -- Is the unit really about to be eliminated? If this is true then even   *\n *                      friendly contact (i.e., radio) must be eliminated.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1995 JLB : Created.                                                                 *\n *   07/24/1996 JLB : Removes target from NavQueue list.                                       *\n *=============================================================================================*/\nvoid FootClass::Detach(TARGET target, bool all)\n{\n\tassert(IsActive);\n\n\tTechnoClass::Detach(target, all);\n\n\tif (!SpecialFlag) {\n\t\tif (ArchiveTarget == target) {\n\t\t\tArchiveTarget = TARGET_NONE;\n\t\t}\n\t}\n\n\tif (SuspendedNavCom == target) {\n\t\tSuspendedNavCom = TARGET_NONE;\n\t\tSuspendedMission = MISSION_NONE;\n\t}\n\n\t/*\n\t**\tIf the navigation computer is assigned to the target, then the navigation\n\t**\tcomputer must be cleared.\n\t*/\n\tif (NavCom == target) {\n\t\tNavCom = TARGET_NONE;\n\t\tPath[0] = FACING_NONE;\n\t\tRestore_Mission();\n\t}\n\n\t/*\n\t**\tRemove the target from the NavQueue list as well.\n\t*/\n\tint loop_count = 0;\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tif (NavQueue[index] == target) {\n\t\t\tNavQueue[index] = TARGET_NONE;\n\t\t\tif (index < ARRAY_SIZE(NavQueue)-1) {\n\t\t\t\tmemmove(&NavQueue[index], &NavQueue[index+1], ((ARRAY_SIZE(NavQueue)-index)-1) * sizeof(NavQueue[0]));\n\t\t\t\tNavQueue[ARRAY_SIZE(NavQueue)-1] = TARGET_NONE;\n\t\t\t\tindex--;\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** Extra safety check\n\t\t*/\n\t\tloop_count++;\n\t\tif (loop_count > ARRAY_SIZE(NavQueue)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf targeting the specified object and this unit is obviously heading\n\t**\ttoward the target to get within range, then abort the path.\n\t*/\n\tif (TarCom == target && House->IsHuman) {\n\t\tPath[0] = FACING_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Offload_Tiberium_Bail -- Fetches the Tiberium to offload per step.               *\n *                                                                                             *\n *    This routine is called when a packet/package/bail of Tiberium needs to be offloaded      *\n *    from the object. This function is overridden for those objects that can contain          *\n *    Tiberium.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of credits offloaded from the object.                      *\n *                                                                                             *\n * WARNINGS:   This routine must be called multiple times in order to completely offload the   *\n *             Tiberium. When this routine return 0, all Tiberium has been offloaded.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Offload_Tiberium_Bail(void)\n{\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FootClass::Can_Enter_Cell -- Checks to see if the object can enter cell specified.          *\n *                                                                                             *\n *    This routine examines the specified cell to see if the object can enter it. This         *\n *    function is to be overridden for objects that could have the possibility of not being    *\n *    allowed to enter the cell. Typical objects at the FootClass level always return          *\n *    MOVE_OK.                                                                                 *\n *                                                                                             *\n * INPUT:   cell     -- The cell to examine.                                                   *\n *                                                                                             *\n *          facing   -- The direction that this cell might be entered from.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the move check result type. This will be MOVE_OK if there is not      *\n *          blockage. There are various other values that represent other blockage types.      *\n *          The value returned will indicated the most severe reason why entry into the cell   *\n *          is blocked.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType FootClass::Can_Enter_Cell(CELL , FacingType) const\n{\n\tassert(IsActive);\n\n\treturn MOVE_OK;\n}\n\n\n/***********************************************************************************************\n * FootClass::Can_Demolish -- Checks to see if this object can be sold back.                   *\n *                                                                                             *\n *    This routine determines if it is legal to sell the object back. A foot class object can  *\n *    only be sold back if it is sitting on a repair bay.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the object successfully sold back?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Can_Demolish(void) const\n{\n\tassert(IsActive);\n\n\tStructType sell_struct = STRUCT_NONE;\n\tswitch (What_Am_I()) {\n\t\tcase RTTI_UNIT:\n\t\t\tsell_struct = STRUCT_REPAIR;\n\t\t\tbreak;\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tsell_struct = STRUCT_AIRSTRIP;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (sell_struct != STRUCT_NONE) {\n\t\tif (In_Radio_Contact() &&\n\t\t\tContact_With_Whom()->What_Am_I() == RTTI_BUILDING &&\n\t\t\t*((BuildingClass *)Contact_With_Whom()) == sell_struct &&\n\t\t\tDistance(Contact_With_Whom()) < 0x0080) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(TechnoClass::Can_Demolish());\n}\n\n\n/***********************************************************************************************\n * FootClass::Sell_Back -- Causes this object to be sold back.                                 *\n *                                                                                             *\n *    When an object is sold back, a certain amount of money is refunded to the owner and then *\n *    the object is removed from the game system.                                              *\n *                                                                                             *\n * INPUT:   control  -- The action to perform. The only supported action is \"1\", which means   *\n *                      to sell back.                                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Sell_Back(int control)\n{\n\tassert(IsActive);\n\n\tif (control != 0) {\n\t\tif (House == PlayerPtr) {\n\t\t\tSpeak(VOX_UNIT_SOLD);\n\t\t\tSound_Effect(VOC_CASHTURN);\n\t\t}\n\t\tHouse->Refund_Money(Refund_Amount());\n\t\tStun();\n\t\tLimbo();\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Likely_Coord -- Fetches the coordinate the object will be at shortly.            *\n *                                                                                             *\n *    This routine comes in handy when determining where a travelling object will be at        *\n *    when considering the amount of time it would take for a normal unit to travel one cell.  *\n *    Using this information, an intelligent \"approach target\" logic can be employed.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the object is at or soon will be.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE FootClass::Likely_Coord(void) const\n{\n\tassert(IsActive);\n\n\tif (Head_To_Coord()) {\n\t\treturn(Head_To_Coord());\n\t}\n\treturn(Target_Coord());\n}\n\n\n/***********************************************************************************************\n * FootClass::Adjust_Dest -- Adjust candidate movement cell to account for formation.          *\n *                                                                                             *\n *    This routine modify the specified cell if the unit is part of a formation. The           *\n *    adjustment will take into consideration the formation relative offset from the           *\n *    (presumed) center cell specified.                                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to presume as the desired center point of the formation.         *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that should be used as the actual destination. If this       *\n *          object is part of a formation, then the cell location will be appropriately        *\n *          adjusted.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL FootClass::Adjust_Dest(CELL cell) const\n{\n\tassert(IsActive);\n\n\tif (IsFormationMove) {\n\t\tint xdest = Cell_X(cell);\n\t\tint ydest = Cell_Y(cell);\n\n\t\tint newx = Bound(XFormOffset + xdest, Map.MapCellX, Map.MapCellX + Map.MapCellWidth -1);\n\t\tint newy = Bound(YFormOffset + ydest, Map.MapCellY, Map.MapCellY + Map.MapCellHeight -1);\n\n\t\tcell = XY_Cell(newx, newy);\n\t}\n\treturn(cell);\n}\n\n\n/***********************************************************************************************\n * FootClass::Handle_Navigation_List -- Processes the navigation queue.                        *\n *                                                                                             *\n *    This routine will process the navigation queue. If the queue is present and valid and    *\n *    there is currently no navigation target assigned to this object, then the first entry    *\n *    of the queue will be assigned. The remaining entries will move down. If the queue is     *\n *    to be processed as a circular list, then the first entry is appended to the end.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine might end up assigning a movement destination.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Handle_Navigation_List(void)\n{\n\t/*\n\t**\tThe navigation queue only needs to be processed if there is\n\t**\tcurrently no navigation target for this object.\n\t*/\n\tif (!Target_Legal(NavCom)) {\n\t\tTARGET target = NavQueue[0];\n\n\t\t/*\n\t\t**\tCheck to see if the navigation queue even exists and\n\t\t**\thas at least one valid entry. If it does, then process it by\n\t\t**\tassigning the object's NavCom to the first entry on the list.\n\t\t*/\n\t\tif (Target_Legal(target)) {\n\t\t\tAssign_Destination(target);\n\t\t\tmemmove(&NavQueue[0], &NavQueue[1], sizeof(NavQueue)-sizeof(NavQueue[0]));\n\t\t\tNavQueue[ARRAY_SIZE(NavQueue)-1] = TARGET_NONE;\n\n\t\t\t/*\n\t\t\t**\tIf the navigation queue is to loop (indefinately), then append the\n\t\t\t**\ttarget value from the first part to the end of the queue.\n\t\t\t*/\n\t\t\tif (IsNavQueueLoop) {\n\t\t\t\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\t\t\t\tif (NavQueue[index] == TARGET_NONE) {\n\t\t\t\t\t\tNavQueue[index] = target;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Queue_Navigation_List -- Add a target to the objects navigation list.            *\n *                                                                                             *\n *    This routine will append the destination target to the object's NavQueue list. After     *\n *    doing so, if the object is not doing anything important, then it will be started on      *\n *    that destination. This is functionally the same as Assign_Destination, but it stores     *\n *    the target to the NavQueue first.                                                        *\n *                                                                                             *\n * INPUT:   target   -- The movement target destination to append the queue.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The queue is of finite size and any queue requests that would exceed that size  *\n *             are ignored. If there are no queue entries pending and the unit is not          *\n *             otherwise occupied, then the queue target might be carried directly into the    *\n *             NavCom.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Queue_Navigation_List(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\tint count;\n\t\tfor (count = 0; count < ARRAY_SIZE(NavQueue); count++) {\n\t\t\tif (!Target_Legal(NavQueue[count])) break;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the target is this object itself, then this indicates that the\n\t\t**\tqueue list is to be processed as a loop. Otherwise, just tack the\n\t\t**\tnavigation target to the end of the list.\n\t\t*/\n\t\tif (target == As_Target() && count > 0) {\n\t\t\tIsNavQueueLoop = true;\n\t\t} else {\n\t\t\tif (count == 0) {\n\t\t\t\tIsNavQueueLoop = false;\n\t\t\t}\n\t\t\tif (count < ARRAY_SIZE(NavQueue)) {\n\t\t\t\tNavQueue[count] = target;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this object isn't doing anything, then start acting on the\n\t\t**\tnavigation queue now.\n\t\t*/\n\t\tif (!Target_Legal(NavCom) && Mission == MISSION_GUARD) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Clear_Navigation_List -- Clears out the navigation queue.                        *\n *                                                                                             *\n *    This routine will clear out any values in the navigation queue. This is the preferred    *\n *    way of aborting a navigation queue for a unit. If the unit is already travelling, it     *\n *    won't be interrupted by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This will clear the navigation list but not the navigation computer. Thus a     *\n *             unit will still travel to its current immediate destination.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::Clear_Navigation_List(void)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {\n\t\tNavQueue[index] = TARGET_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_Allowed_To_Leave_Map -- Checks to see if it can leave the map and the game.   *\n *                                                                                             *\n *    This routine will determine if this object has permission to leave the map and thus      *\n *    leave the game. Typical objects with this permission are transports used to drop of      *\n *    reinforcements.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this object have permission to travel off the map edge and leave the    *\n *                game?                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_Allowed_To_Leave_Map(void) const\n{\n\t/*\n\t**\tIf the unit hasn't entered the map yet, then don't allow leave the game.\n\t*/\n\tif (!IsLocked) return(false);\n\n\t/*\n\t**\tA unit that isn't marked as a loaner is a gift to the player. Such objects can never\n\t**\tleave the map unless they are part of a team that gives it special permision.\n\t*/\n\tif (!IsALoaner && Mission != MISSION_RETREAT && (!Team.Is_Valid() || !Team->Is_Leaving_Map())) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_Recruitable -- Determine if this object is recruitable as a team members.     *\n *                                                                                             *\n *    This will examine this object to determine if it is suitable as a team recruit. Some     *\n *    objects are disqualified if they are otherwise premptively occupied.                     *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that is trying to recruit this object.               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object suitable for recruitment by a team.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_Recruitable(HouseClass const * house) const\n{\n\t/*\n\t**\tIf not of the correct house presuasion, then recruitment is not allowed.\n\t*/\n\tif (house != NULL && house != House) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the object is not a playing member of the game, then don't consider it available.\n\t*/\n\tif (IsInLimbo) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it is already part of another team, then it is not available for\n\t**\tgeneral recruitment.\n\t*/\n\tif (Team.Is_Valid()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf it is currently in a mission the precludes recruitment into a team, then\n\t**\treturn with this information.\n\t*/\n\tif (!Is_Recruitable_Mission(Mission)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIt was not disqualified for general team recruitment, so return that\n\t**\tit is available.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * FootClass::AI -- Handle general movement AI.                                                *\n *                                                                                             *\n *    This basically just sees if this object is within weapon range of the target and if      *\n *    so, it will stop movement so that firing may commence. This prevents the occasional      *\n *    case of an attacker driving right up to the defender before firing.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FootClass::AI(void)\n{\n\tTechnoClass::AI();\n\n// FootClass::Per_Cell_Process does this function already.\n#ifdef OBSOLETE\n\tif (IsActive) {\n\t\tif (!IsScattering && !IsTethered && !IsInLimbo && What_Am_I() != RTTI_AIRCRAFT && Target_Legal(TarCom) && In_Range(TarCom)) {\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * FootClass::Is_On_Priority_Mission -- Checks to see if this object should be given priority. *\n *                                                                                             *\n *    Some objects are on an important mission that must succeed. If the object is on such     *\n *    a mission, then it will be more aggressive in its movement action.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this object on a priority mission?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FootClass::Is_On_Priority_Mission(void) const\n{\n\tif (Mission == MISSION_ENTER) return(true);\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FootClass::Mission_Retreat -- Handle reatreat from map mission for mobile objects.          *\n *                                                                                             *\n *    This will try to make this mobile object leave the map. It does this by assigning a      *\n *    movement destination that is located off the edge of the map.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *\n *          again.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FootClass::Mission_Retreat(void)\n{\n\tassert(IsActive);\n\n\tenum {\n\t\tFIND_EDGE,\n\t\tTRAVELLING\n\t};\n\n\tswitch (Status) {\n\n\t\t/*\n\t\t**\tFind a suitable edge to travel to and then assign destination there.\n\t\t*/\n\t\tcase FIND_EDGE:\n\t\t\tif (Target_Legal(NavCom)) {\n\t\t\t\tStatus = TRAVELLING;\n\t\t\t} else {\n\n\t\t\t\tCELL cell = 0;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is part of a team, then pick the edge where the team as likely\n\t\t\t\t**\tentered from.\n\t\t\t\t*/\n\t\t\t\tif (Team.Is_Valid() && Team->Class->Origin != -1) {\n\t\t\t\t\tcell = Map.Calculated_Cell(House->Control.Edge, Team->Class->Origin, Coord_Cell(Center_Coord()), Techno_Type_Class()->Speed);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an edge hasn't been found, then try to find one that is not based on any\n\t\t\t\t**\tteam information.\n\t\t\t\t*/\n\t\t\t\tif (cell == 0) {\n\t\t\t\t\tcell = Map.Calculated_Cell(House->Control.Edge, -1, Coord_Cell(Center_Coord()), Techno_Type_Class()->Speed);\n\t\t\t\t}\n\n\t\t\t\tassert(cell == 0);\t\t// An edge cell must be found!\n\n\t\t\t\tAssign_Destination(::As_Target(cell));\n\t\t\t\tStatus = TRAVELLING;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhile travelling, monitor that all is proceeding according to plan.\n\t\t*/\n\t\tcase TRAVELLING:\n\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\tStatus = FIND_EDGE;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));\n}"
  },
  {
    "path": "REDALERT/FOOT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FOOT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FOOT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 14, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FOOT_H\n#define FOOT_H\n\n#include\t\"target.h\"\n#include\t\"type.h\"\n#include\t\"techno.h\"\n#include\t\"ftimer.h\"\n\nclass UnitClass;\nclass BuildingClass;\n\n\n/****************************************************************************\n**\tMovable objects are handled by this class definition. Moveable objects\n**\tcover everything except buildings.\n*/\nclass FootClass :\tpublic TechnoClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis flag controls whether a range limiting effect should be in place. If\n\t\t**\ttrue, then target scanning will be limited to the range of the object\n\t\t**\tregardless of what was requested from the target scanning logic. This value\n\t\t**\tis used for ships so that they won't permanently stick on a an attack mission\n\t\t**\tfor a target they can never get within range of. This value will toggle when\n\t\t**\ta path cannot be generated and the target is not within range. It will also\n\t\t**\ttoggle when path limiting is true, but there is not target found within\n\t\t**\tthe limited range.\n\t\t*/\n\t\tunsigned IsScanLimited:1;\n\n\t\t/*\n\t\t**\tIf this unit has officially joined the team's group, then this flag is\n\t\t**\ttrue. A newly assigned unit to a team is not considered part of the\n\t\t**\tteam until it actually reaches the location where the team is. By\n\t\t**\tusing this flag, it allows a team to continue to intelligently attack\n\t\t**\ta target without falling back to regroup the moment a distant member\n\t\t**\tjoins.\n\t\t*/\n\t\tunsigned IsInitiated:1;\n\n\t\t/*\n\t\t**\tWhen the player gives this object a navigation target AND that target\n\t\t**\tdoes not result in any movement of the unit, then a beep should be\n\t\t**\tsounded. This typically occurs when selecting an invalid location for\n\t\t**\tmovement. This flag is cleared if any movement was able to be performed.\n\t\t**\tIt never gets set for computer controlled units.\n\t\t*/\n\t\tunsigned IsNewNavCom:1;\n\n\t\t/*\n\t\t**\tThere are certain cases where a unit should perform a full scan rather than\n\t\t**\tthe more efficient \"ring scan\". This situation occurs when a unit first\n\t\t**\tappears on the map or when it finishes a multiple cell movement track.\n\t\t*/\n\t\tunsigned IsPlanningToLook:1;\n\n\t\t/*\n\t\t**\tCertain units have the ability to metamorphize into a building. When this\n\t\t**\toperation begins, certain processes must occur. During these operations, this\n\t\t**\tflag will be true. This ensures that any necessary special case code gets\n\t\t**\tproperly executed for this unit.\n\t\t*/\n\t\tunsigned IsDeploying:1;\n\n\t\t/*\n\t\t**\tThis flag tells the system that the unit is doing a firing animation. This is\n\t\t**\tcritical to the firing logic.\n\t\t*/\n\t\tunsigned IsFiring:1;\n\n\t\t/*\n\t\t**\tThis unit could be either rotating its body or rotating its turret. During the\n\t\t**\tprocess of rotation, this flag is set. By examining this flag, unnecessary logic\n\t\t**\tcan be avoided.\n\t\t*/\n\t\tunsigned IsRotating:1;\n\n\t\t/*\n\t\t**\tIf this object is current driving to a short range destination, this flag is\n\t\t**\ttrue. A short range destination is either the next cell or the end of the\n\t\t**\tcurrent \"curvy\" track. An object that is driving is not allowed to do anything\n\t\t**\telse until it reaches its destination. The exception is when infantry wish to\n\t\t**\thead to a different destination, they are allowed to start immediately.\n\t\t*/\n\t\tunsigned IsDriving:1;\n\n\t\t/*\n\t\t**\tIf this object is unloading from a hover transport, then this flag will be\n\t\t**\tset to true. This handles the unusual case of an object disembarking from the\n\t\t**\thover lander yet not necessarily tethered but still located in an overlapping\n\t\t**\tposition. This flag will be cleared automatically when the object moves to the\n\t\t**\tcenter of a cell.\n\t\t*/\n\t\tunsigned IsUnloading:1;\n\n\t\t/*\n\t\t** If this object is part of a formation, this bit will be set.  The\n\t\t** formation only occurs when every member of a team is selected, and\n\t\t** only those members of the team are the ones selected.\n\t\t*/\n\t\tunsigned IsFormationMove:1;\n\n\t\t/*\n\t\t**\tIf the navigation movement queue is to be looped rather than consumed, then\n\t\t**\tthis flag will be true. By looping, the unit will travel through the locations\n\t\t**\tin the queue indefinately.\n\t\t*/\n\t\tunsigned IsNavQueueLoop:1;\n\n\t\t/*\n\t\t**\tIf this object is scattering, then this flag will be true. While true, the\n\t\t**\tNavCom should not be arbitrarily changed. This flag will automatcially be\n\t\t**\tcleared when the object moves one cell.\n\t\t*/\n\t\tunsigned IsScattering:1;\n\n\t\t/*\n\t\t**\tIf this object is moving onto a bridge, then this flag will be true.\n\t\t*/\n\t\tunsigned IsMovingOntoBridge:1;\n\n\t\t/*\n\t\t**\tThis is the \"throttle setting\" of the unit. It is a fractional value with 0 = stop\n\t\t**\tand 255 = full speed.\n\t\t*/\n\t\tint Speed;\n\n\t\t/*\n\t\t**\tThis is the override speed adjuster. Normally, this is a fixed point\n\t\t**\tvalue of 0x0100, but it can be modified by crate powerups.\n\t\t*/\n\t\tfixed SpeedBias;\n\n\t\t/*\n\t\t** For units in a formation, these values represent the distance from\n\t\t** the target destination where the unit should move to.  For example,\n\t\t** in a horizontal line formation, XFormOffset would be set to some\n\t\t** value, and YFormOffset would be zero.\n\t\t*/\n\t\tint XFormOffset;\n\t\tint YFormOffset;\n\n\t\t/*\n\t\t**\n\t\t**\tThis is the desired destination of the unit. The unit will attempt to head\n\t\t**\ttoward this target (avoiding intervening obstacles).\n\t\t*/\n\t\tTARGET NavCom;\n\t\tTARGET SuspendedNavCom;\n\n\t\t/*\n\t\t**\tA sequence of move destinations can be given to a unit. The sequence is\n\t\t**\tstores as an array of movement targets. The list is terminated with a\n\t\t**\tTARGET_NONE.\n\t\t*/\n\t\tTARGET NavQueue[10];\n\n\t\t/*\n\t\t**\tThis points to the team that \"owns\" this object. This pointer is used to\n\t\t**\tquickly process the team when this object is the source of the change. An\n\t\t**\texample would be if this object were to be destroyed, it would inform the\n\t\t**\tteam of this fact by using this pointer.\n\t\t*/\n\t\tCCPtr<TeamClass> Team;\n\n\t\t/*\n\t\t**\tIf this object is part of a pseudo-team that the player is managing, then\n\t\t**\tthis will be set to the team number (0 - 9). If it is not part of any\n\t\t**\tpseudo-team, then the number will be -1.\n\t\t*/\n\t\tunsigned char Group;\n\n\t\t/*\n\t\t**\tThis points to the next member in the team that this object is part of. This\n\t\t**\tis used to quickly process each team member when the team class is the source\n\t\t**\tof the change. An example would be if the team decided that everyone is going\n\t\t**\tto move to a new location, it would inform each of the objects by chaining\n\t\t**\tthrough this pointer.\n\t\t*/\n\t\tFootClass * Member;\n\n\t\t/*\n\t\t**\tSince all objects derived from this class move according to a path list.\n\t\t**\tThis is the path list. It specifies, as a simple list of facings, the\n\t\t**\tpath that the object should follow in order to reach its destination.\n\t\t**\tThis path list is limited in size, so it might require several generations\n\t\t**\tof path lists before the ultimate destination is reached. The game logic\n\t\t**\thandles regenerating the path list as necessary.\n\t\t*/\n\t\tFacingType Path[CONQUER_PATH_MAX];\n\n\t\t/*\n\t\t**\tThis value keeps track of how serious the unit is in trying to reach the\n\t\t**\tdestination specified. As blockages arise, this threshold will rise\n\t\t**\tunit it reaches the point of complete failure. When that event occurs, the\n\t\t**\tunit will realize that it cannot get to its specified destination and will\n\t\t**\ttry to perform some other action instead.\n\t\t*/\n\t\tMoveType PathThreshhold;\n\n\t\t/*\n\t\t**\tWhen there is a complete findpath failure, this timer is initialized so\n\t\t**\tthat a findpath won't be calculated until this timer expires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> PathDelay;\n\t\tenum {PATH_RETRY=10};\n\t\tint TryTryAgain;\t\t// Number of retry attempts remaining.\n\n\t\t/*\n\t\t** If the object has recently attacked a base, then this timer will not\n\t\t** have expired yet.  It is used so a building does not keep calling\n\t\t** for help from the same attacker.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> BaseAttackTimer;\n\n\t\t/*\n\t\t** For formation moves, this will be the override speed.\n\t\t*/\n\t\tSpeedType FormationSpeed;\n\n\t\t/*\n\t\t** For formation moves, this will be the override maximum speed.\n\t\t*/\n\t\tMPHType\tFormationMaxSpeed;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tFootClass(NoInitClass const & x) : TechnoClass(x), Team(x), PathDelay(x), BaseAttackTimer(x) {};\n\t\tFootClass(RTTIType rtti, int id, HousesType house);\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool Basic_Path(void);\n\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tbool Is_Recruitable(HouseClass const * house=NULL) const;\n\t\tbool Is_On_Priority_Mission(void) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual COORDINATE Likely_Coord(void) const;\n\n\t\t/*\n\t\t**\tDriver control support functions. These are used to control cell\n\t\t**\toccupation flags and driver instructions.\n\t\t*/\n\t\tCOORDINATE Head_To_Coord(void) const {return (HeadToCoord);};\n\t\tvirtual bool Start_Driver(COORDINATE &headto);\n\t\tvirtual bool Stop_Driver(void);\n\t\tvirtual void Assign_Destination(TARGET target);\n\t\tbool Is_Allowed_To_Leave_Map(void) const;\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE , DirType dir = DIR_N);\n\t\tvirtual bool Mark(MarkType mark=MARK_CHANGE);\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual void Stun(void);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual void Death_Announcement(TechnoClass const * source=0) const;\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void);\n\t\tvirtual void Sell_Back(int control);\n\t\tvirtual int Offload_Tiberium_Bail(void);\n\t\tvirtual TARGET Greatest_Threat(ThreatType method) const;\n\t\tvirtual void Detach(TARGET target, bool all);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Capture(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Hunt(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvoid Handle_Navigation_List(void);\n\t\tvoid Queue_Navigation_List(TARGET target);\n\t\tvoid Clear_Navigation_List(void);\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Approach_Target(void);\n\t\tvirtual void Fixup_Path(PathType *) {};\n\t\tvirtual void Set_Speed(int speed);\n\t\tvirtual MoveType Can_Enter_Cell(CELL cell, FacingType from=FACING_NONE) const;\n\t\tint Optimize_Moves(PathType *path, MoveType threshhold);\n\t\tvirtual void Override_Mission(MissionType mission, TARGET tarcom, TARGET navcom);\n\t\tvirtual bool Restore_Mission(void);\n\t\tCELL Adjust_Dest(CELL cell) const;\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\tCELL Safety_Point(CELL src, CELL dst, int start, int max);\n\t\tint Rescue_Mission(TARGET tarcom);\n\n\tprivate:\n\t\tint Passable_Cell(CELL cell, FacingType face, int threat, MoveType threshhold);\n\t\tPathType * Find_Path(CELL dest, FacingType *final_moves, int maxlen, MoveType threshhold);\n\t\tvoid Debug_Draw_Map(char const * txt, CELL start, CELL dest, bool pause);\n\t\tvoid Debug_Draw_Path(PathType *path);\n\t\tbool Follow_Edge(CELL start, CELL target, PathType *path, FacingType search, FacingType olddir, int threat, int threat_stage, int max_cells, MoveType threshhold);\n\t\tbool Register_Cell(PathType *path, CELL cell, FacingType dir, int cost, MoveType threshhold);\n\t\tbool Unravel_Loop(PathType *path, CELL &cell, FacingType &dir, int sx, int sy, int dx, int dy, MoveType threshhold);\n\n\t\t/*\n\t\t**\tThis is the coordinate that the unit is heading to\n\t\t**\tas an immediate destination. This coordinate is never further\n\t\t**\tthan once cell (or track) from the unit's location. When this coordinate\n\t\t**\tis reached, then the next location in the path list becomes the\n\t\t**\tnext HeadTo coordinate.\n\t\t*/\n\t\tCOORDINATE HeadToCoord;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[16];\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/FTIMER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FTIMER.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FTIMER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/16/95                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BasicTimerClass<T>::BasicTimerClass -- Constructor for basic timer class.                 *\n *   BasicTimerClass<T>::operator () -- Function operator for timer object.                    *\n *   BasicTimerClass<T>::operator long -- Conversion to long operator.                         *\n *   BasicTimerClass<T>::~BasicTimerClass -- Destructor for basic timer object.                *\n *   TTimerClass<T>::Is_Active -- Checks to see if the timer is counting.                      *\n *   TTimerClass<T>::Start -- Starts (resumes) a stopped timer.                                *\n *   TTimerClass<T>::Stop -- Stops the current timer from incrementing.                        *\n *   TTimerClass<T>::TTimerClass -- Constructor for timer class object.                        *\n *   TTimerClass<T>::operator () -- Function operator for timer object.                        *\n *   TTimerClass<T>::operator long -- Conversion operator for timer object.                    *\n *   CDTimerClass<T>::CDTimerClass -- Constructor for count down timer.                        *\n *   CDTimerClass<T>::Is_Active -- Checks to see if the timer object is active.                *\n *   CDTimerClass<T>::Start -- Starts (resumes) the count down timer.                          *\n *   CDTimerClass<T>::Stop -- Stops (pauses) the count down timer.                             *\n *   CDTimerClass<T>::operator () -- Function operator for the count down timer.               *\n *   CDTimerClass<T>::operator long -- Conversion to long operator function.                   *\n *   CDTimerClass<T>::~CDTimerClass -- Destructor for the count down timer object.             *\n *   TTimerClass<T>::Value -- Returns with the current value of the timer.                     *\n *   CDTimerClass<T>::Value -- Fetches the current value of the countdown timer.               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FTIMER_H\n#define FTIMER_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/**********************************************************************\n**\tThis class is solely used as a parameter to a constructor that does\n**\tabsolutely no initialization to the object being constructed. By using\n**\tthis method, it is possible to load and save data directly from a\n**\tclass that has virtual functions. The construction process automatically\n**\ttakes care of initializing the virtual function table pointer and the\n**\trest of the constructor doesn't initialize any data members. After loading\n**\tinto a class object, simply perform an in-place new operation.\n*/\n#ifndef NOINITCLASS\n#define NOINITCLASS\nstruct NoInitClass {\n\tpublic:\n\t\tvoid operator () (void) const {};\n};\n#endif\n\n\n/*\n**\tThis is a timer class that watches a constant rate timer (specified by the parameter\n**\ttype class) and provides basic timer functionality. It is possible to set the start value\n**\tWITHOUT damaging or otherwise affecting any other timer that may be built upon the same\n**\tspecified timer class object. Treat an object of this type as if it were a \"magic\" integral\n**\tlong that automatically advances at the speed of the timer class object controlling it.\n*/\n// Let lint know that non-virtual destructor is OK for this class.\n//lint -esym(1509,BasicTimerClass)\ntemplate<class T>\nclass BasicTimerClass {\n \tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tBasicTimerClass(unsigned long set=0);\n\t\tBasicTimerClass(NoInitClass const & );\n\n\t\t~BasicTimerClass(void);\n\n\t\t// Fetch current value of timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\tprotected:\n\t\tT Timer;\t\t\t// Timer regulator (ticks at constant rate).\n\t\tunsigned long Started;\t// Time started.\n};\n\n\ntemplate<class T>\ninline BasicTimerClass<T>::BasicTimerClass(NoInitClass const & )\n{\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::BasicTimerClass -- Constructor for basic timer class.                   *\n *                                                                                             *\n *    This is the constructor for the basic timer class object. It sets the timer counting     *\n *    up from zero at the rate of the controlling timer class object.                          *\n *                                                                                             *\n * INPUT:   set   -- Alternate initial start value for the counter. If not specified, then     *\n *                   the timer is assumed to start at zero and count upwards.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n//lint -esym(1403,BasicTimerClass<class FrameTimerClass>::Timer)\n//lint -esym(1403,BasicTimerClass<class SystemTimerClass>::Timer)\ntemplate<class T>\ninline BasicTimerClass<T>::BasicTimerClass(unsigned long set) :\n\tStarted(Timer()-set)\n{\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::~BasicTimerClass -- Destructor for basic timer object.                  *\n *                                                                                             *\n *    The destructor for the basic timer object doesn't have to do anything.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline BasicTimerClass<T>::~BasicTimerClass(void)\n{\n}\n\n\ntemplate<class T>\ninline unsigned long BasicTimerClass<T>::Value(void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::operator long -- Conversion to long operator.                           *\n *                                                                                             *\n *    This conversion operator allows the basic timer object to function in much the same      *\n *    manner as the integral \"long\" type. One can assign a long with a timer object and the    *\n *    actual value of the timer is extracted from the object and used.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the timer value expressed as a long.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline BasicTimerClass<T>::operator unsigned long(void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/***********************************************************************************************\n * BasicTimerClass<T>::operator () -- Function operator for timer object.                      *\n *                                                                                             *\n *    This function operator allows the timer to also serve as the parameter type class for    *\n *    additional timer objects. This allows one to instantiate a controlling timer class that  *\n *    can control (e.g., turn on or off) all timers that are based upon it.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current timer value expressed as a long.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long BasicTimerClass<T>::operator () (void) const\n{\n\treturn(Timer()-Started);\n}\n\n\n/*\n**\tThis timer class functions similarly to the basic timer class. In addition to the\n**\tnormal timer operation, this class has the ability to be stopped and started at\n**\twill. If you have no need to start or stop the timer, then use the basic timer\n**\tclass instead.\n*/\ntemplate<class T>\nclass TTimerClass : public BasicTimerClass<T> {\n \tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tTTimerClass(unsigned long set=0);\n\t\tTTimerClass(NoInitClass const & x);\n\n\t\t~TTimerClass(void) {};\n\n\t\t// Fetches current value of timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\t\t// Stops (pauses) the timer.\n\t\tvoid Stop(void);\n\n\t\t// Starts (resumes) the timer.\n\t\tvoid Start(void);\n\n\t\t// Queries whether the timer is currently active.\n\t\tbool Is_Active(void) const;\n\n\tprivate:\n\t\tunsigned long Accumulated;\t\t\t\t//\tTotal accumulated ticks.\n};\n\n\ntemplate<class T>\ninline TTimerClass<T>::TTimerClass(NoInitClass const & x) :\n\tBasicTimerClass<T>(x)\n{\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::TTimerClass -- Constructor for timer class object.                          *\n *                                                                                             *\n *    This is the constructor for the advanced timer class object. This object class can start *\n *    or stop the timer under user control.                                                    *\n *                                                                                             *\n * INPUT:   set   -- The initial value to set the timer to. If no value is specified, then     *\n *                   the timer is assumed to start from zero.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline TTimerClass<T>::TTimerClass(unsigned long set) :\n\tBasicTimerClass<T>(set),\n\tAccumulated(0)\n{\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Value -- Returns with the current value of the timer.                       *\n *                                                                                             *\n *    This routine will return with the current value of the timer. It takes into account      *\n *    whether the timer has stopped or not so as to always return the correct value regardless *\n *    of that condition.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current value of the timer.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long TTimerClass<T>::Value(void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::operator long -- Conversion operator for timer object.                      *\n *                                                                                             *\n *    This conversion operator allows this timer object to function as an \"rvalue\" of a \"long\" *\n *    type. This is consistent with the integral \"long\" value. It is possible to assign a      *\n *    timer object to a long and have the long initialized with the current value of the       *\n *    timer.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current time value expressed as a long.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline TTimerClass<T>::operator unsigned long(void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::operator () -- Function operator for timer object.                          *\n *                                                                                             *\n *    This function operator for the timer class allows this timer class to be used as the     *\n *    template parameter for other timer class objects. With this ability, one can control     *\n *    several timers (e.g., start or stop them) by using a single controlling timer class      *\n *    that other timers are instantiated from.                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current time expressed as a long.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long TTimerClass<T>::operator () (void) const\n{\n\tunsigned long value = Accumulated;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tvalue += BasicTimerClass<T>::Value();\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Stop -- Stops the current timer from incrementing.                          *\n *                                                                                             *\n *    This routine will stop (pause) the timer from further increments. To cause the timer     *\n *    to begin anew, call the Start() function.                                                *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TTimerClass<T>::Stop(void)\n{\n\tif (Started != 0xFFFFFFFFU) {\n\t\tAccumulated += BasicTimerClass<T>::operator unsigned long();\n\t\tStarted = 0xFFFFFFFFU;\n\t}\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Start -- Starts (resumes) a stopped timer.                                  *\n *                                                                                             *\n *    This routine will resume a timer that was previously stopped with the Stop() function.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TTimerClass<T>::Start(void)\n{\n\tif (Started == 0xFFFFFFFFU) {\n\t\tStarted = Timer();\n\t}\n}\n\n\n/***********************************************************************************************\n * TTimerClass<T>::Is_Active -- Checks to see if the timer is counting.                        *\n *                                                                                             *\n *    Since this timer can be paused, this routine is used to examine the timer to see if it   *\n *    is currently paused or active. If the timer is active, then the return value will be     *\n *    true.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this timer currently active?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline bool TTimerClass<T>::Is_Active(void) const\n{\n\treturn(Started != 0xFFFFFFFFU);\n}\n\n\n/*\n**\tThis timer counts down from the specified (or constructed) value down towards zero.\n**\tThe countdown rate is controlled by the timer object specified. This timer object can\n**\tbe started or stopped. It can also be tested to see if it has expired or not. An expired\n**\tcount down timer is one that has value of zero. You can treat this class object as if it\n**\twere an integral \"magic\" long that automatically counts down toward zero.\n*/\ntemplate<class T>\nclass CDTimerClass : public BasicTimerClass<T> {\n\tpublic:\n\t\t// Constructor allows assignment as if class was integral 'long' type.\n\t\tCDTimerClass(unsigned long set=0);\n\t\tCDTimerClass(NoInitClass const & x);\n\n\t\t~CDTimerClass(void);\n\n\t\t// Fetches current value of count down timer.\n\t\tunsigned long Value(void) const;\n\n\t\t// Conversion operator to allow consistent treatment with integral types.\n\t\toperator unsigned long(void) const;\n\n\t\t// Function operator to allow timer object definition to be cascaded.\n\t\tunsigned long operator () (void) const;\n\n\t\t// Stops (pauses) the timer.\n\t\tvoid Stop(void);\n\n\t\t// Starts (resumes) the timer.\n\t\tvoid Start(void);\n\n\t\t// Queries whether the timer is currently active.\n\t\tbool Is_Active(void) const;\n\n\t\tbool Was_Started(void) const { return WasStarted; }\n\n\tprivate:\n\t\tunsigned long DelayTime;\t\t\t// Ticks remaining before countdown timer expires.\n\t\tbool WasStarted;\n};\n\n\ntemplate<class T>\ninline CDTimerClass<T>::CDTimerClass(NoInitClass const & x) :\n\tBasicTimerClass<T>(x), WasStarted(false)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::CDTimerClass -- Constructor for count down timer.                          *\n *                                                                                             *\n *    This is the constructor for the count down timer object. The optional starting value     *\n *    can be used to initiate the timer. Because of this constructor it is possible to assign  *\n *    a long to a count down timer object in order to begin the countdown process.             *\n *                                                                                             *\n * INPUT:   set   -- The initial starting value for the countdown timer.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::CDTimerClass(unsigned long set) :\n\tBasicTimerClass<T>(0),\n\tDelayTime(set),\n\tWasStarted(false)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::~CDTimerClass -- Destructor for the count down timer object.               *\n *                                                                                             *\n *    The destructor for the count down timer object does nothing.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::~CDTimerClass(void)\n{\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Value -- Fetches the current value of the countdown timer.                 *\n *                                                                                             *\n *    Use this routine to fetch the current value of the timer. It takes into consideration    *\n *    whether the timer has been stopped or not. It returns the correct value regardless of    *\n *    this condition.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the correct value of this count down timer.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long CDTimerClass<T>::Value(void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::operator long -- Conversion to long operator function.                     *\n *                                                                                             *\n *    This conversion operator allows the count down timer object to be used as if it were     *\n *    a \"magic\" long that automatically counted downward at the controller class tick rate.    *\n *    The count down object can be used in any place that an rvalue long could be used.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current count down time expressed in the form of a long value.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline CDTimerClass<T>::operator unsigned long(void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::operator () -- Function operator for the count down timer.                 *\n *                                                                                             *\n *    This is the function operator for the count down timer object. By supporting this        *\n *    function operator, this class (or one derived from this class) could be used as the      *\n *    controlling timer to the timer templates.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current count down time expressed in the form of a long.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline unsigned long CDTimerClass<T>::operator () (void) const\n{\n\tunsigned long remain = DelayTime;\n\tif (Started != 0xFFFFFFFFU) {\n\t\tunsigned long value = BasicTimerClass<T>::Value();\n\t\tif (value < remain) {\n\t\t\treturn(remain - value);\n\t\t} else {\n\t\t\treturn(0);\n\t\t}\n\t}\n\treturn(remain);\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Stop -- Stops (pauses) the count down timer.                               *\n *                                                                                             *\n *    This routine is used to stop (pause) the count down timer object. A timer object paused  *\n *    in this fashion will be resumed by a call to Start() or by assigning a new count down    *\n *    value to the timer.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid CDTimerClass<T>::Stop(void)\n{\n\tif (Started != 0xFFFFFFFFU) {\n\t\tDelayTime = *this;\n\t\tStarted = 0xFFFFFFFFU;\n\t}\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Start -- Starts (resumes) the count down timer.                            *\n *                                                                                             *\n *    This routine is used to start (resume) the count down timer that was previously stopped  *\n *    with the Stop() function. The timer will also resume when a new timer value is assigned. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid CDTimerClass<T>::Start(void)\n{\n\tWasStarted = true;\n\n\tif (Started == 0xFFFFFFFFU) {\n\t\tStarted = Timer();\n\t}\n}\n\n\n/***********************************************************************************************\n * CDTimerClass<T>::Is_Active -- Checks to see if the timer object is active.                  *\n *                                                                                             *\n *    Because the timer object counting can be stopped, this routine is used to determine      *\n *    if the timer is currently paused or active.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the timer currently active?                                               *\n *                                                                                             *\n * WARNINGS:   Note that if the timer has counted down to zero, then it may be active, but     *\n *             the value will, naturally, not change.                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\ninline bool CDTimerClass<T>::Is_Active(void) const\n{\n\treturn(Started != 0xFFFFFFFFU);\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/FUNCTION.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FUNCTION.H 2     3/13/97 2:05p Steve_tall $*/\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUNCTION.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 27, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 27, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FUNCTION_H\n#define FUNCTION_H\n\n/*\n**\t!!!DEFINE!!!  \"NDEBUG\" if the assertion code is to be !!!REMOVED!!! from the project.\n*/\n//#define\tNDEBUG\t\t// ST - 5/13/2019\n\n//#pragma warn -hid\n\n#ifdef NEVER\nMap (screen) class heirarchy.\n\n MapeditClass (most derived class) -- scenario editor\n        \n   MouseClass -- handles mouse animation and display control\n        \n  ScrollClass -- map scroll handler\n        \n    HelpClass -- pop-up help text handler\n        \n     TabClass -- file folder tab screen mode control dispatcher\n        \n SidebarClass -- displays and controls construction list sidebar\n        \n   PowerClass -- display power production/consumption bargraph\n        \n   RadarClass -- displays and controls radar map\n        \n DisplayClass -- general tactical map display handler\n        \n     MapClass -- general tactical map data handler\n        \n GScreenClass (pure virtual base class) -- generic screen control\n\n                          AbstractClass\n                                  \n                                  \n                                  \n                                  \n                            ObjectClass\n                                  \n       Ŀ\n   AnimClass    TemplateClass             FuseClass         TerrainClass\n                                          FlyClass      \n                                   BulletClass            \n       OverlayClass        MissionClass               SmudgeClass\n                                  \n                             RadioClass\n                                  \n                                   CrewClass\n                                   FlasherClass\n                                   StageClass\n                                   CargoClass\n                            TechnoClass\n                                  \n                       Ŀ\n                   FootClass                           BuildingClass\n                       \n         Ŀ\n    DriveClass  InfantryClass          FlyClass\n                               AircraftClass\n       Ŀ\n                  \n            VesselClass\n       \n    UnitClass\n\n\n                            AbstractTypeClass\n                                    \n                              ObjectTypeClass\n                                    \n             Ŀ\n                                                                \n       TechnoTypeClass                                           \n                             BulletTypeClass                     \n                                        TemplateTypeClass         \n    Ŀ    TerrainTypeClass\n                                                   \nUnitTypeClass         BuildingTypeClass        VesselTypeClass\n                                             \n           AircraftTypeClass          InfantryTypeClass\n#endif\n\n\n#include\t\"watcom.h\"\n#include \"lint.h\"\n\n\n#ifdef WIN32\n//#define WIN32_LEAN_AND_MEAN\n#include\t<windows.h>\n#define WWFILE_H\n#define RAWFILE_H\n#define MONOC_H\n\n#define\t_MAX_NAME\t_MAX_FNAME\n\n#endif\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#if (0)\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n#endif\n\n#ifndef BITMAPCLASS\n#define BITMAPCLASS\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\n/**********************************************************************\n**\tThis class is solely used as a parameter to a constructor that does\n**\tabsolutely no initialization to the object being constructed. By using\n**\tthis method, it is possible to load and save data directly from a\n**\tclass that has virtual functions. The construction process automatically\n**\ttakes care of initializing the virtual function table pointer and the\n**\trest of the constructor doesn't initialize any data members. After loading\n**\tinto a class object, simply perform an in-place new operation.\n*/\n#ifndef NOINITCLASS\n#define NOINITCLASS\nstruct NoInitClass {\n\tpublic:\n\t\tvoid operator () (void) const {};\n};\n#endif\n\n\n#define FILE_H\n#define WWMEM_H\n\n#ifndef WIN32\n#define TIMER_H\n#endif\n\n#ifdef WIN32\n#include\t\"key.h\"\n#endif\n\n#include <wwlib32.h>\n#include\t\"mpu.h\"\n#include\t\"bench.h\"\n#include\t\"rect.h\"\n#include\t\"jshell.h\"\n#include\t\"buff.h\"\n#include\t\"face.h\"\n#include\t\"random.h\"\n#include\t\"crc.h\"\n#include \"compat.h\"\n#include\t\"fixed.h\"\n#include\t\"base64.h\"\n#include\t\"pipe.h\"\n#include\t\"xpipe.h\"\n#include\t\"ramfile.h\"\n#include\t\"lcw.h\"\n#include\t\"lzw.h\"\n#include\t\"lcwpipe.h\"\n#include\t\"lzwpipe.h\"\n#include\t\"lzopipe.h\"\n#include\t\"crcpipe.h\"\n#include\t\"shapipe.h\"\n#include\t\"b64pipe.h\"\n#include\t\"straw.h\"\n#include\t\"xstraw.h\"\n#include\t\"b64straw.h\"\n#include\t\"lcwstraw.h\"\n#include\t\"lzwstraw.h\"\n#include\t\"lzostraw.h\"\n#include\t\"crcstraw.h\"\n#include\t\"shastraw.h\"\n#include\t\"rndstraw.h\"\n\n// Should be part of WWLIB.H. This is used in JSHELL.CPP.\ntypedef struct {\n\tunsigned char\tSourceColor;\n\tunsigned char\tDestColor;\n\tunsigned char\tFading;\n\tunsigned char\treserved;\n} TLucentType;\n\n\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<stddef.h>\n//#include\t<mem.h>\n//#include\t<dos.h>\n#include\t<direct.h>\n#include\t<stdarg.h>\n#include\t<ctype.h>\n#include\t<assert.h>\n#include\t<process.h>\n//#include\t<new.h>\n\n\n\n#ifdef WIN32\n#define\tint386x(a,b,c,d)\t0\n#define\tint386(a,b,c)\t0\n#endif\n\n\n/*\n**\tVQ player specific includes.\n*/\n//#include <vqa32\\vqaplay.h>\n//#include <vqa32\\vqafile.h>\n\nextern bool GameActive;\nextern long LParam;\n\n#include\t<assert.h>\n#include\t\"vector.h\"\n#include\t\"heap.h\"\n#include\t\"ccfile.h\"\n#include\t\"monoc.h\"\n#include\t\"conquer.h\"\n//#include\t\"debug.h\"\n#include \"special.h\"\n#include\t\"defines.h\"\n#include\t\"ccini.h\"\n#include\t\"ccptr.h\"\n#include\t\"bar.h\"\n\n/*\n**\tGreenleaf specific includes.\n*/\n//#include <modem.h>\n//#include <fast.h>\n\n\nextern long Frame;\nCELL Coord_Cell(COORDINATE coord);\n\n#include\t\"utracker.h\"\n#include\t\"crate.h\"\n#include\t\"rules.h\"\n#include\t\"ini.h\"\n#include\t\"int.h\"\n#include\t\"pk.h\"\n#include\t\"pkpipe.h\"\n#include\t\"pkstraw.h\"\n#include\t\"sha.h\"\n#include\t\"blowfish.h\"\n#include\t\"blowpipe.h\"\n#include\t\"blwstraw.h\"\n#include\t\"language.h\"\n#include\t\"hsv.h\"\n#include\t\"rgb.h\"\n#include\t\"palette.h\"\n#include\t\"palettec.h\" //ST 5/13/2019\n#include \"version.h\"\n#include\t\"facing.h\"\n#include\t\"ftimer.h\"\n#include\t\"theme.h\"\n#include\t\"link.h\"\n#include\t\"gadget.h\"\n#include\t\"control.h\"\n#include\t\"toggle.h\"\n#include\t\"checkbox.h\"\n#include\t\"shapebtn.h\"\n#include\t\"textbtn.h\"\n#include\t\"statbtn.h\"\n#include\t\"slider.h\"\n#include \"list.h\"\n#include\t\"drop.h\"\n#include \"cheklist.h\"\n#include \"colrlist.h\"\n#include\t\"edit.h\"\n#include\t\"gauge.h\"\n#include\t\"msgbox.h\"\n#include\t\"dial8.h\"\n#include\t\"txtlabel.h\"\n#include \"loaddlg.h\"\n#include\t\"super.h\"\n#include\t\"house.h\"\n#include\t\"gscreen.h\"\n#include\t\"map.h\"\n#include\t\"display.h\"\n#include\t\"radar.h\"\n#include\t\"power.h\"\n#include\t\"sidebar.h\"\n#include\t\"tab.h\"\n#include\t\"help.h\"\n#include\t\"mouse.h\"\n#include\t\"help.h\"\n#include\t\"target.h\"\n#include\t\"theme.h\"\n#include\t\"team.h\"\t\t\t\t// Team objects.\n#include\t\"warhead.h\"\n#include\t\"weapon.h\"\n#include\t\"trigtype.h\"\n#include\t\"teamtype.h\"\t\t// Team type objects.\n#include\t\"taction.h\"\n#include\t\"tevent.h\"\n#include\t\"trigger.h\"\t\t\t// Trigger event objects.\n#include\t\"mapedit.h\"\t\t\t// map editor class\n#include\t\"abstract.h\"\n#include \"object.h\"\n#include \"mission.h\"\n#include\t\"door.h\"\n#include\t\"bullet.h\"\t\t\t// Bullet objects.\n#include\t\"terrain.h\"\t\t\t// Terrain objects.\n#include\t\"anim.h\"\t\t\t\t// Animation objects.\n#include\t\"template.h\"\t\t// Icon template objects.\n#include\t\"overlay.h\"\t\t\t// Overlay objects.\n#include\t\"smudge.h\"\t\t\t// Stains on the terrain objects.\n#include\t\"aircraft.h\"\t\t// Aircraft objects.\n#include\t\"unit.h\"\t\t\t\t// Ground unit objects.\n#include \"vessel.h\"\t\t\t// Sea unit objects.\n#include\t\"infantry.h\"\t\t// Infantry objects.\n#include\t\"credits.h\"\t\t\t// Credit counter class.\n#include\t\"score.h\"\t\t\t// Scoring system class.\n#include\t\"factory.h\"\t\t\t// Production manager class.\n#include \"intro.h\"\n#include \"ending.h\"\n#include\t\"logic.h\"\n#include\t\"queue.h\"\n#include\t\"event.h\"\n#include \"base.h\"\t\t\t\t// defines the AI's pre-built base\n#include\t\"carry.h\"\n#include\t\"scenario.h\"\n#include \"msglist.h\"\t\t\t// Multiplayer chat message system\n#include \"session.h\"\t\t\t// Multiplayer session class\n//#include \"phone.h\"\t\t\t// Phone list manager\n#include \"ipxmgr.h\"\t\t\t// IPX connection manager\n//#include\t\"nullmgr.h\"\t\t\t// Modem connection manager\n#include\t\"readline.h\"\n#include\t\"vortex.h\"\n#include \"egos.h\"\n#ifdef WIN32\n//#include\t\"pcx.h\"\n#endif\n\n#if(TEN)\n#include \"tenmgr.h\"\n#endif\n\n#if(MPATH)\n#ifdef WIN32\n#include \"mpmgrw.h\"\n#else\n#include \"mpmgrd.h\"\n#endif\n#endif\n\n// Denzil 5/18/98 - Mpeg movie playback\n#ifdef MPEGMOVIE\nbool InitDDraw(void);\nbool PlayMpegMovie(const char* name);\n#endif\n\n#include\t\"externs.h\"\n\n\nextern int Get_CD_Drive(void);\nextern void Fatal(char const *message, ...);\n\n#ifdef WIN32\n\n/*\n** For WIN32, replace the assert macro so we get an error on the debugger screen\n**  where we can see it.\n**\n*/\n#ifndef __BORLANDC__\n#ifdef assert\n#undef assert\n#endif\t//assert\nvoid Assert_Failure (char *expression, int line, char *file);\n\n#ifdef NDEBUG\n #define assert(__ignore) ((void)0)\n#else\n #define assert(expr)   ((expr)?(void)0:Assert_Failure(#expr,__LINE__,__FILE__))\n#endif\t//NDEBUG\n\n#endif\t//__BORLANDC__\n\n\nextern void Free_Interpolated_Palettes(void);\nextern int Load_Interpolated_Palettes(char const *filename, BOOL add=FALSE);\nextern void Rebuild_Interpolated_Palette(unsigned char *interpal);\nextern void Interpolate_2X_Scale( GraphicBufferClass *source, GraphicViewPortClass *dest ,char const *palette_file_name);\nvoid Increase_Palette_Luminance (unsigned char *palette , int red_percentage , int green_percentage , int blue_percentage ,int cap);\n#endif\n\n/*\n**\tADATA.CPP\n*/\nchar const * Anim_Name(AnimType anim);\n\n/*\n**\tAIRCRAFT.CPP\n*/\nbool Building_Check(void);\n\n/*\n**\tANIM.CPP\n*/\nvoid Shorten_Attached_Anims(ObjectClass * obj);\nAnimType Anim_From_Name(char const * name);\n\n/*\n**\tAUDIO.CPP\n*/\nVocType Voc_From_Name(char const * name);\nchar const * Speech_Name(VoxType speech);\nchar const * Voc_Name(VocType voc);\nint Sound_Effect(VocType voc, fixed volume=1, int variation=1, signed short panvalue=0, HousesType house=HOUSE_NONE);\n// void Speak(VoxType voice); // MBL 02.06.2020\nvoid Speak(VoxType voice, HouseClass *house=NULL, COORDINATE coord=0);\nvoid Speak_AI(void);\nvoid Stop_Speaking(void);\nvoid Sound_Effect(VocType voc, COORDINATE coord, int variation=1, HousesType house=HOUSE_NONE);\nbool Is_Speaking(void);\n\n/*\n**\tCDFILE.CPP\n*/\n#ifdef WIN32\nint harderr_handler(unsigned, unsigned, unsigned *);\n#else\nint harderr_handler(unsigned, unsigned, unsigned __far *);\n#endif\n\n/*\n**\tCOMBAT.CPP\n*/\nint Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance);\nvoid Explosion_Damage(COORDINATE coord, int strength, TechnoClass * source, WarheadType warhead);\nAnimType Combat_Anim(int damage, WarheadType warhead, LandType land);\nvoid Wide_Area_Damage(COORDINATE coord, LEPTON radius, int damage, TechnoClass * source, WarheadType warhead);\n\n/*\n**\tCONQUER.CPP\n*/\nvoid List_Copy(short const * source, int len, short * dest);\nint Get_CD_Index (int cd_drive, int timeout);\nint Owner_From_Name(char const * text);\nCrateType Crate_From_Name(char const * name);\nRect const Shape_Dimensions(void const * shapedata, int shapenum);\nvoid IPX_Call_Back(void);\nbool Is_Counterstrike_Installed (void);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Aftermath_Installed (void);\n#endif\n\n\n#if(TEN)\nvoid Ten_Call_Back(void);\n#endif\t// TEN\n\n#if(MPATH)\nvoid MPATH_Call_Back(void);\n#endif\t// MPATH\n\n#define ALWAYS_RELOAD_CD 1000\n\nvoid Center_About_Objects(void);\nbool Force_CD_Available(int cd);\nvoid Handle_View(int view, int action=0);\nvoid Handle_Team(int team, int action=0);\nTechnoTypeClass const * Fetch_Techno_Type(RTTIType type, int id);\nchar const * Fading_Table_Name(char const * base, TheaterType theater);\nvoid Unselect_All(void);\nvoid Unselect_All_Except(ObjectClass* object);\nvoid Play_Movie(char const * name, ThemeType theme=THEME_NONE, bool clrscrn=true, bool immediate = false);\nvoid Play_Movie(VQType name, ThemeType theme=THEME_NONE, bool clrscrn=true, bool immediate=false);\nbool Main_Loop(void);\nTheaterType Theater_From_Name(char const * name);\nvoid Main_Game(int argc, char * argv[]);\nlong VQ_Call_Back(unsigned char * buffer=NULL, long frame=0);\nvoid Call_Back(void);\nchar const *Language_Name(char const * basename);\nSourceType Source_From_Name(char const * name);\nchar const *Name_From_Source(SourceType source);\nFacingType KN_To_Facing(int input);\nvoid const *Get_Radar_Icon(void const * shapefile, int shapenum, int frames, int zoomfactor);\n//void CC_Draw_Shape(ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata=0, void const * ghostdata=0, DirType rotation=DIR_N, long scale=0x0100);\nvoid CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata = 0, void const * ghostdata = 0, DirType rotation = DIR_N);\n\n// Added for draw intercept. ST - 1/17/2019 12:31PM\nvoid CC_Draw_Shape(const ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata = 0, void const * ghostdata = 0, DirType rotation = DIR_N, long virtualscale = 0x0100, int width = 0, int height = 0);\nvoid CC_Draw_Shape(const ObjectClass *object, const char *shape_file_name, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata = 0, void const * ghostdata = 0, DirType rotation = DIR_N, long virtualscale = 0x0100, char override_owner = HOUSE_NONE);\n\n// Added for pip draw intercept - SKY\nvoid CC_Draw_Pip(const ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata = 0, void const * ghostdata = 0, DirType rotation = DIR_N);\n\nvoid Go_Editor(bool flag);\n//long MixFileHandler(VQAHandle * vqa, long action, void * buffer, long nbytes);\nchar *CC_Get_Shape_Filename(void const * shapeptr );\nvoid CC_Add_Shape_To_Global(void const * shapeptr, char * filename, char code );\nvoid Bubba_Print(char * format,...);\nvoid Heap_Dump_Check(char * string );\nvoid Dump_Heap_Pointers(void);\nunsigned long Disk_Space_Available(void);\nvoid * Hires_Load(char * name);\nvoid Shake_The_Screen(int shakes, HousesType house = HOUSE_NONE);\n\n/*\n**\tCOORD.CPP\n*/\nshort const * Coord_Spillage_List(COORDINATE coord, Rect const & rect, bool nocenter=true);\nvoid Normal_Move_Point(short &x, short &y, register DirType dir, unsigned short distance);\nvoid Move_Point(short &x, short &y, register DirType dir, unsigned short distance);\nCOORDINATE Coord_Move(COORDINATE start, DirType facing, unsigned short distance);\nCOORDINATE Coord_Scatter(COORDINATE coord, unsigned distance, bool lock=false);\nDirType Direction(CELL cell1, CELL cell2);\nDirType Direction(COORDINATE coord1, COORDINATE coord2);\nDirType Direction256(COORDINATE coord1, COORDINATE coord2);\nDirType Direction8(COORDINATE coord1, COORDINATE coord2);\nint Distance(COORDINATE coord1, COORDINATE coord2);\nint Distance(TARGET target1, TARGET target2);\nshort const * Coord_Spillage_List(COORDINATE coord, int maxsize);\n\n/*\n**\tDEBUG.CPP\n*/\nvoid Log_Event(char const *text, ...);\nvoid Debug_Key(unsigned input);\nvoid Self_Regulate(void);\n\n/*\n**\tDIALOG.CPP\n*/\nvoid Draw_Caption(int text, int x, int y, int w);\nvoid Draw_Caption(char const * text, int x, int y, int w);\nint Format_Window_String(char * string, int maxlinelen, int & width, int & height);\nextern void Dialog_Box(int x, int y, int w, int h);\nvoid Conquer_Clip_Text_Print(char const *, unsigned x, unsigned y, RemapControlType * fore, unsigned back=(unsigned)TBLACK, TextPrintType flag=TPF_8POINT|TPF_DROPSHADOW, int width=-1, int const * tabs=0);\nvoid Draw_Box(int x, int y, int w, int h, BoxStyleEnum up, bool filled);\nint cdecl Dialog_Message(char *errormsg, ...);\nvoid Window_Box(WindowNumberType window, BoxStyleEnum style);\nvoid Fancy_Text_Print(char const *text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...);\nvoid Fancy_Text_Print(int text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag, ...);\nvoid Simple_Text_Print(char const *text, unsigned x, unsigned y, RemapControlType * fore, unsigned back, TextPrintType flag);\nvoid Plain_Text_Print(int text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...);\nvoid Plain_Text_Print(char const *text, unsigned x, unsigned y, unsigned fore, unsigned back, TextPrintType flag, ...);\n\n/*\n**\tDISPLAY.CPP\n*/\nObjectClass* Best_Object_With_Action(DynamicVectorClass<ObjectClass*>& objects, const ObjectClass* object);\nObjectClass* Best_Object_With_Action(DynamicVectorClass<ObjectClass*>& objects, CELL cell);\n\nActionType Best_Object_Action(DynamicVectorClass<ObjectClass*>& objects, const ObjectClass* object);\nActionType Best_Object_Action(DynamicVectorClass<ObjectClass*>& objects, CELL cell);\n\nObjectClass* Best_Object_With_Action(const ObjectClass* object);\nObjectClass* Best_Object_With_Action(CELL cell);\n\nActionType Best_Object_Action(const ObjectClass* object);\nActionType Best_Object_Action(CELL cell);\n\n/*\n**\tENDING.CPP\n*/\nvoid GDI_Ending(void);\nvoid Nod_Ending(void);\n\n/*\n**\tEXPAND.CPP\n*/\nbool Expansion_Present(void);\nbool Expansion_Dialog(void);\nbool Expansion_CS_Present(void);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Expansion_AM_Present(void);\n#endif\n/*\n**\tFINDPATH.CPP\n*/\nint Optimize_Moves(PathType *path, int (*callback)(CELL, FacingType), int threshhold);\n\n/*\n**\tGOPTIONS.CPP\n*/\n\n/*\n**\tINI.CPP\n*/\nvoid Write_Scenario_INI(char *root);\nbool Read_Scenario_INI(char *root, bool fresh=true);\nint Scan_Place_Object(ObjectClass *obj, CELL cell);\nvoid Assign_Houses(void);\n\n/*\n**\tINIBIN.CPP\n*/\nunsigned long Ini_Binary_Version( void );\nbool Read_Scenario_INB( CCFileClass *file, char *root, bool fresh );\nbool Valid_Scenario_INB( CCFileClass *file );\n\n/*\n**\tINICODE.CPP\n*/\nbool Read_Scenario_INI_Write_INB( char *root, bool fresh );\n\n/*\n**\tINIT.CPP\n*/\nvoid Load_Title_Page(bool visible=false);\nlong Obfuscate(char const * string);\nvoid Anim_Init(void);\nbool Init_Game(int argc, char *argv[]);\nbool Select_Game(bool fade = false);\nbool Parse_Command_Line(int argc, char *argv[]);\nvoid Parse_INI_File(void);\n\n/*\n** INTERPAL.CPP\n*/\n#define SIZE_OF_PALETTE 256\nextern\t\"C\" unsigned char *InterpolationPalette;\nextern\tBOOL\tInterpolationPaletteChanged;\nextern\tvoid \tInterpolate_2X_Scale( GraphicBufferClass *source, GraphicViewPortClass *dest ,char const *palette_file_name);\nvoid Read_Interpolation_Palette (char const *palette_file_name);\nvoid Write_Interpolation_Palette (char const *palette_file_name);\nvoid Increase_Palette_Luminance(unsigned char *InterpolationPalette ,\tint RedPercentage ,int GreenPercentage ,int BluePercentage ,int cap);\nextern \"C\"{\n\textern unsigned char PaletteInterpolationTable[SIZE_OF_PALETTE][SIZE_OF_PALETTE];\n\textern unsigned char *InterpolationPalette;\n\tvoid __cdecl Asm_Create_Palette_Interpolation_Table(void);\n}\n\n/*\n** JSHELL.CPP\n*/\nint Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format);\nvoid * Conquer_Build_Fading_Table(PaletteClass const & palette, void *dest, int color, int frac);\nvoid * Small_Icon(void const * iconptr, int iconnum);\nvoid Set_Window(int window, int x, int y, int w, int h);\nvoid * Load_Alloc_Data(FileClass &file);\nlong Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void *reserved_data);\nlong Translucent_Table_Size(int count);\nvoid *Build_Translucent_Table(PaletteClass const & palette, TLucentType const *control, int count, void *buffer);\nvoid *Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const *control, int count, void *buffer);\nvoid * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac);\n\n/*\n**\tKEYFBUFF.ASM\n*/\nextern \"C\" {\n\tlong __cdecl Buffer_Frame_To_Page(int x, int y, int w, int h, void *Buffer, GraphicViewPortClass &view, int flags, ...);\n}\n\n/*\n**\tKEYFRAME.CPP\n*/\nunsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr);\nunsigned short Get_Build_Frame_Count(void const *dataptr);\nunsigned short Get_Build_Frame_X(void const *dataptr);\nunsigned short Get_Build_Frame_Y(void const *dataptr);\nunsigned short Get_Build_Frame_Width(void const *dataptr);\nunsigned short Get_Build_Frame_Height(void const *dataptr);\nbool Get_Build_Frame_Palette(void const *dataptr, void *palette);\nint Get_Last_Frame_Length(void);\n\n\n/*\n**\tMAP.CPP\n*/\nint Terrain_Cost(CELL cell, FacingType facing);\nint Coord_Spillage_Number(COORDINATE coord, int maxsize);\n\n/*\n**\tMENUS.CPP\n*/\nvoid Setup_Menu(int menu, char const *text[], unsigned long field, int index, int skip);\nint Check_Menu(int menu, char const *text[], char *selection, long field, int index);\nint Do_Menu(char const **strings, bool blue);\nextern int UnknownKey;\nint Main_Menu(unsigned long timeout);\n\n/*\n** MPLAYER.CPP\n*/\nGameType Select_MPlayer_Game (void);\nvoid Clear_Listbox(ListClass *list);\nvoid Clear_Vector(DynamicVectorClass <NodeNameType *> *vector);\nvoid Computer_Message(void);\nint Surrender_Dialog(int text);\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(const char* text);\nbool Determine_If_Using_DVD();\nbool Using_DVD();\n#endif\nint Abort_Dialog(void);\n\n#if(TEN)\nint Read_TEN_Game_Options(void);\n#endif\t// TEN\n\n#if(MPATH)\nint Read_MPATH_Game_Options(void);\n#endif\t// MPATH\n\n#if(TEN)\n/*\n** CCTEN.CPP\n*/\nint Init_TEN(void);\nvoid Shutdown_TEN(void);\nvoid Connect_TEN(void);\nvoid Destroy_TEN_Connection(int id, int error);\nvoid Send_TEN_Win_Packet(void);\nvoid Send_TEN_Alliance(char *whom, int ally);\nvoid Send_TEN_Out_Of_Sync(void);\nvoid Send_TEN_Packet_Too_Late(void);\n#endif\t// TEN\n\n#if(MPATH)\n/*\n** CCMPATH.CPP\n*/\nint Init_MPATH(void);\nvoid Shutdown_MPATH(void);\nvoid Connect_MPATH(void);\nvoid Destroy_MPATH_Connection(int id, int error);\n#endif\t// MPATH\n\n/*\n** NETDLG.CPP\n*/\nbool Init_Network (void);\nvoid Shutdown_Network (void);\nbool Remote_Connect (void);\nvoid Destroy_Connection(int id, int error);\nbool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address);\nunsigned long Compute_Name_CRC(char *name);\nvoid Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index, unsigned long timeval);\n\n/*\n** NULLDLG.CPP\n*/\nint Init_Null_Modem( SerialSettingsType *settings );\nvoid Shutdown_Modem( void );\nvoid Modem_Signoff( void );\nint Test_Null_Modem( void );\nint Reconnect_Modem( void );\nvoid Destroy_Null_Connection(int id, int error);\nGameType Select_Serial_Dialog( void );\nint Com_Scenario_Dialog(bool skirmish=false);\nint Com_Show_Scenario_Dialog(void);\n\nvoid Smart_Printf( char *format, ... );\nvoid Hex_Dump_Data( char *buffer, int length );\nvoid itoh( int i, char *s);\nvoid Log_Start_Time( char *string );\nvoid Log_End_Time( char *string );\nvoid Log_Time( char *string );\nvoid Log_Start_Nest_Time( char *string );\nvoid Log_End_Nest_Time( char *string );\n\n/*\n**\tOBJECT.CPP\n*/\n\n/*\n**\tPROFILE.CPP\n*/\nint WWGetPrivateProfileInt(char const *section, char const *entry, int def, char *profile);\nbool WWWritePrivateProfileInt(char const *section, char const *entry, int value, char *profile);\nbool WWWritePrivateProfileString(char const *section, char const *entry, char const *string, char *profile);\nchar * WWGetPrivateProfileString(char const *section, char const *entry, char const *def, char *retbuffer, int retlen, char const * profile);\nunsigned WWGetPrivateProfileHex (char const *section, char const *entry, char * profile);\n\nchar *Read_Bin_Buffer( void );\nbool Read_Bin_Init( char *buffer, int length );\nint Read_Bin_Length( char *buffer );\nbool Read_Bin_Num( void *num, int length, char *buffer );\nint Read_Bin_Pos( char *buffer );\nint Read_Bin_PosSet( unsigned int pos, char *buffer );\nbool Read_Bin_String( char *string, char *buffer );\n\nchar *Write_Bin_Buffer( void );\nbool Write_Bin_Init( char *buffer, int length );\nint Write_Bin_Length( char *buffer );\nbool Write_Bin_Num( void *num, int length, char *buffer );\nint Write_Bin_Pos( char *buffer );\nint Write_Bin_PosSet( unsigned int pos, char *buffer );\nbool Write_Bin_String( char *string, int length, char *buffer );\n\n/*\n** QUEUE.CPP\n*/\nbool Queue_Target(TargetClass whom, TARGET target);\nbool Queue_Destination(TargetClass whom, TARGET target);\nbool Queue_Mission(TargetClass whom, MissionType mission);\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination);\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination, SpeedType speed, MPHType maxspeed);\nbool Queue_Options(void);\nbool Queue_Exit(void);\nvoid Queue_AI(void);\nvoid Add_CRC(unsigned long *crc, unsigned long val);\n\n/*\n**\tRANDOM.CPP\n*/\n\n/*\n**\tREINF.CPP\n*/\nbool Do_Reinforcements(TeamTypeClass const * team);\nbool Create_Special_Reinforcement(HouseClass * house, TechnoTypeClass const * type, TechnoTypeClass const * another, TeamMissionType mission = TMISSION_NONE, int argument =0);\nint Create_Air_Reinforcement(HouseClass *house, AircraftType air, int number, MissionType mission, TARGET tarcom, TARGET navcom, InfantryType passenger=INFANTRY_NONE);\n\n/*\n**\tROTBMP.CPP\n*/\nint Rotate_Bitmap(GraphicViewPortClass *srcvp,GraphicViewPortClass *destvp,int angle);\n\n/*\n**\tRULES.CPP\n*/\nbool Is_MCV_Deploy();\n\n/*\n**\tSAVELOAD.CPP\n*/\nbool Load_Misc_Values(Straw & file);\nbool Save_Misc_Values(Pipe & file);\nbool Load_MPlayer_Values(Straw & file);\nbool Save_MPlayer_Values(Pipe & file);\nbool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep);\nbool Load_Game(int id);\nbool Load_Game(const char *file_name);\n//bool Read_Object (void * ptr, int base_size, int class_size, FileClass & file, void * vtable);  // Original Read_Object prototype. ST - 9/17/2019 12:50PM\t\t\nbool Read_Object(void *ptr, int class_size, FileClass & file, bool has_vtable);\nbool Save_Game(int id, char const * descr, bool bargraph=false);\nbool Save_Game(const char *file_name, const char *descr);\nbool Write_Object (void * ptr, int class_size, FileClass & file);\nvoid Code_All_Pointers(void);\nvoid Decode_All_Pointers(void);\nvoid Dump(void);\n\n/*\n** SCENARIO.CPP\n*/\nvoid Disect_Scenario_Name(char const * name, int & scenario, ScenarioPlayerType & player, ScenarioDirType & dir, ScenarioVarType & var);\nvoid Post_Load_Game(int load_net);\nbool End_Game(void);\nbool Read_Scenario(char *root);\nbool Start_Scenario(char *root, bool briefing=true);\nvoid Set_Scenario_Difficulty(int difficulty);\nHousesType Select_House(void);\nvoid Clear_Scenario(void);\nvoid Do_Briefing(char const * text);\nvoid Do_Lose(void);\nvoid Do_Win(void);\nvoid Do_Restart(void);\nvoid Fill_In_Data(void);\nbool Restate_Mission(char const * name, int button1, int button2);\nint BGMessageBox(char const *text, int button1, int button2);\n\n/*\n**\tSCORE.CPP\n*/\nchar const * Map_Selection(void);\nvoid Bit_It_In(int x, int y, int w, int h, GraphicBufferClass *src, GraphicBufferClass *dest, int delay=0, int dagger=0);\nvoid Call_Back_Delay(int time);\nint Alloc_Object(ScoreAnimClass *obj);\n\n/*\n**\tSPECIAL.CPP\n*/\nvoid Special_Dialog(bool simple=false);\nchar const * Fetch_Password(int caption, int message, int btext=TXT_OK);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nint Fetch_Difficulty(bool amath=false);\n#else\nint Fetch_Difficulty(void);\n#endif\n\n/*\n**\tSTARTUP.CPP\n*/\nvoid Print_Error_End_Exit(char *string);\nvoid Emergency_Exit ( int code );\n\n/*\n**\tSUPPORT.ASM\n*/\n\n/*\n** TARGET.CPP\n*/\nTechnoTypeClass const * As_TechnoType(TARGET target);\nCOORDINATE As_Movement_Coord(TARGET target);\nAircraftClass * As_Aircraft(TARGET target, bool check_active = true);\nAnimClass * As_Animation(TARGET target, bool check_active = true);\nBuildingClass * As_Building(TARGET target, bool check_active = true);\nBulletClass * As_Bullet(TARGET target, bool check_active = true);\nCELL As_Cell(TARGET target);\nCOORDINATE As_Coord(TARGET target);\nInfantryClass * As_Infantry(TARGET target, bool check_active = true);\nTeamClass * As_Team(TARGET target, bool check_active = true);\nTeamTypeClass * As_TeamType(TARGET target);\nTechnoClass * As_Techno(TARGET target, bool check_active = true);\nTriggerClass * As_Trigger(TARGET target, bool check_active = true);\nTriggerTypeClass * As_TriggerType(TARGET target);\nUnitClass * As_Unit(TARGET target, bool check_active = true);\nVesselClass * As_Vessel(TARGET target, bool check_active = true);\nbool Target_Legal(TARGET target);\nObjectClass * As_Object(TARGET target, bool check_active = true);\n\n/*\n**\tTEAMTYPE.CPP\n*/\nNeedType TeamMission_Needs(TeamMissionType tmtype);\n\n/*\n**\tTRACKER.CPP\n*/\nvoid Detach_This_From_All(TARGET target, bool all=true);\n\n/*\n**\tTRIGGER.CPP\n*/\nTriggerClass * Find_Or_Make(TriggerTypeClass * trigtype);\n\n/*\n** ULOGIC.CPP\n*/\nint Terrain_Cost(CELL cell, FacingType facing);\n\n/*\n**\tVERSION.CPP\n*/\nchar const * Version_Name(void);\n\n/*\n**\tWEAPON.CPP\n*/\nWeaponType Weapon_From_Name(char const * name);\nArmorType Armor_From_Name(char const * name);\n\n/*\n** Winstub.cpp\n*/\nvoid Load_Title_Screen(char *name, GraphicViewPortClass *video_page, unsigned char *palette);\n\n/*\n** Egos.CPP\n*/\nvoid Show_Who_Was_Responsible (void);\n\n\n//\n// We need to know when the visible page changes\n// ST - 1/4/2019 10:31AM\n//\nvoid Blit_Hid_Page_To_Seen_Buff(void);\nextern bool RunningAsDLL;\nextern bool RunningFromEditor;\n\n\n#include\t\"inline.h\"\n\n/*\n**\tThese declarations ensure that the templates will be expanded for these specified\n**\ttypes. Doing this is required because some of the body functions for this template class\n**\tare located in a .CPP module. Doing so results in faster compilation but requires declarations\n**\tsuch as this for all types that will be required. There are no actual objects of with these\n**\tnames ever created, however there are other objects of this type (with different names) that\n**\tare created.\n*/\nextern CCPtr<AircraftClass> _wefwefy1;\t\t// Previus definition was function???\nextern CCPtr<AnimClass> y2;\nextern CCPtr<BuildingClass> y3;\nextern CCPtr<BulletClass> y4;\nextern CCPtr<FactoryClass> y5;\nextern CCPtr<HouseClass> y6;\nextern CCPtr<InfantryClass> y7;\nextern CCPtr<OverlayClass> y8;\nextern CCPtr<SmudgeClass> y9;\nextern CCPtr<TeamClass> y10;\nextern CCPtr<TeamTypeClass> y11;\nextern CCPtr<TemplateClass> y12;\nextern CCPtr<TerrainClass> y13;\nextern CCPtr<TriggerClass> y14;\nextern CCPtr<TriggerTypeClass> y15;\nextern CCPtr<HouseTypeClass>\t\ty16;\nextern CCPtr<BuildingTypeClass>\ty17;\nextern CCPtr<AircraftTypeClass>\ty18;\nextern CCPtr<InfantryTypeClass>\ty19;\nextern CCPtr<BulletTypeClass>\t\ty20;\nextern CCPtr<AnimTypeClass>\t\ty21;\nextern CCPtr<UnitTypeClass>\t\ty22;\nextern CCPtr<VesselTypeClass>\t\ty23;\nextern CCPtr<TemplateTypeClass>\ty24;\nextern CCPtr<TerrainTypeClass>\ty25;\nextern CCPtr<OverlayTypeClass>\ty26;\nextern CCPtr<SmudgeTypeClass>\t\ty27;\ntemplate <> class DynamicVectorClass<CCPtr<TeamTypeClass> >;\nextern DynamicVectorClass<CCPtr<TeamTypeClass> > y002;\ntemplate <>class DynamicVectorClass<CCPtr<TriggerTypeClass> >;\nextern DynamicVectorClass<CCPtr<TriggerTypeClass> > y001;\ntemplate <>class DynamicVectorClass<TeamMissionClass *>;\nextern DynamicVectorClass<TeamMissionClass *> xxx1;\ntemplate <>class DynamicVectorClass<EventChoiceClass *>;\nextern DynamicVectorClass<EventChoiceClass *> xxx2;\ntemplate <>class DynamicVectorClass<ActionChoiceClass *>;\nextern DynamicVectorClass<ActionChoiceClass *> xxx3;\ntemplate <>class DynamicVectorClass<EgoClass *>;\nextern DynamicVectorClass<EgoClass *> whatever;\n\n/*\n** Debug output. ST - 6/27/2019 10:00PM\n*/\nvoid GlyphX_Debug_Print(const char *debug_text);\n\nvoid Disable_Uncompressed_Shapes (void);\nvoid Enable_Uncompressed_Shapes (void);\n\n/*\n** Achievement event. ST - 11/11/2019 11:39AM\n*/\nvoid On_Achievement_Event(const HouseClass* player_ptr, const char *achievement_type, const char *achievement_reason);\n\n#endif"
  },
  {
    "path": "REDALERT/FUSE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FUSE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUSE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 17, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FuseClass::Arm_Fuse -- Sets up fuse for detonation check.                                 *\n *   FuseClass::Fuse_Checkup -- Determines if the fuse triggers.                               *\n *   FuseClass::Fuse_Read -- Reads the fuse class data from the save game file.                *\n *   FuseClass::Fuse_Write -- Writes the fuse data to the save game file.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * FuseClass::FuseClass -- Constructor.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1995 BRR : Created.  Gosh, what a lotta work.                                       *\n *=============================================================================================*/\nFuseClass::FuseClass(void)\n{\n\tTimer = 0;\n\tArming = 0;\n\tHeadTo = 0;\n\tProximity = 0;\n}\n\n\n/***********************************************************************************************\n * FuseClass::Arm_Fuse -- Sets up fuse for detonation check.                                   *\n *                                                                                             *\n *    This starts a fuse. Fuses are proximity detonation variety but                           *\n *    can be modified to have a minimum time to elapse before detonation                       *\n *    and a maximum time to exist before detonation. Typically, the                            *\n *    timing values are used for missiles that have a minimum arming                           *\n *    distance and a limited amount of fuel.                                                   *\n *                                                                                             *\n * INPUT:   location -- The coordinate where the projectile start. This                        *\n *                      is needed for proper proximity tracking.                               *\n *                                                                                             *\n *          target   -- The actual impact point. Fuses are based on real                       *\n *                      word coordinates.                                                      *\n *                                                                                             *\n *          time     -- The maximum time that the fuse may work before                         *\n *                      explosion is forced.                                                   *\n *                                                                                             *\n *          arming   -- The minimum time that must elapse before the                           *\n *                      fuse may explode.                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Arm_Fuse(COORDINATE location, COORDINATE target, int timeto, int arming)\n{\n\ttimeto = max(timeto, arming);\n\tTimer = min(timeto, 0xFF);\n\tArming = min(arming, 0xFF);\n\tHeadTo = target;\n\tProximity = Distance(location, target);\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Checkup -- Determines if the fuse triggers.                                 *\n *                                                                                             *\n *    This will process the fuse and update the internal clocks as well                        *\n *    as check to see if the fuse should trigger (explode) or not.                             *\n *                                                                                             *\n * INPUT:   newlocation -- The new location of the fuse. This is needed                        *\n *                         to determine proximity explosions.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the fuse triggered to explode now?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool FuseClass::Fuse_Checkup(COORDINATE newlocation)\n{\n\tint\tproximity;\n\n\t/*\n\t**\tAlways decrement the fuse timer.\n\t*/\n\tif (Timer) Timer--;\n\n\t/*\n\t**\tIf the arming countdown has not expired, then do nothing.\n\t*/\n\tif (Arming) {\n\t\tArming--;\n\t} else {\n\n\t\t/*\n\t\t**\tIf the timer has run out, then the warhead explodes.\n\t\t*/\n\t\tif (!Timer) return(true);\n\n\t\tproximity = Distance(newlocation, HeadTo);\n\t\tif (proximity < 0x0010) return(true);\n\t\tif (proximity < ICON_LEPTON_W && proximity > Proximity) {\n\t\t\treturn(true);\n\t\t}\n\t\tProximity = proximity;\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Write -- Writes the fuse data to the save game file.                        *\n *                                                                                             *\n *    Use this routine to output the fuse class data to the save game file specified.          *\n *                                                                                             *\n * INPUT:   file  -- The file to output the data to.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Fuse_Write(FileClass & file)\n{\n\tfile.Write(&Timer, sizeof(Timer));\n\tfile.Write(&Arming, sizeof(Arming));\n\tfile.Write(&HeadTo, sizeof(HeadTo));\n\tfile.Write(&Proximity, sizeof(Proximity));\n}\n\n\n/***********************************************************************************************\n * FuseClass::Fuse_Read -- Reads the fuse class data from the save game file.                  *\n *                                                                                             *\n *    Use this routine to input the fuse class data from the save game file specified.         *\n *                                                                                             *\n * INPUT:   file  -- The file to input the data from.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FuseClass::Fuse_Read(FileClass & file)\n{\n\tfile.Read(&Timer, sizeof(Timer));\n\tfile.Read(&Arming, sizeof(Arming));\n\tfile.Read(&HeadTo, sizeof(HeadTo));\n\tfile.Read(&Proximity, sizeof(Proximity));\n}\n\n\n"
  },
  {
    "path": "REDALERT/FUSE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/FUSE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : FUSE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 24, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 24, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef FUSE_H\n#define FUSE_H\n\n/****************************************************************************\n**\tThe fuse is used by projectiles to determine whether detonation should\n**\toccur. This is usually determined by tracking the distance to the\n**\tdesignated target reaches zero or when the timer expires.\n*/\nclass FuseClass {\n\tpublic:\n\t\tFuseClass(void);\n\t\tFuseClass(NoInitClass const &) {};\n\t\t~FuseClass(void) {};\n\n\t\tvoid Arm_Fuse(COORDINATE location, COORDINATE target, int time=0xFF, int arming=0);\n\t\tbool Fuse_Checkup(COORDINATE newlocation);\n\t\tvoid Fuse_Write(FileClass & file);\n\t\tvoid Fuse_Read(FileClass & file);\n\t\tCOORDINATE Fuse_Target(void);\n\n\t\t/*\n\t\t**\tFuses can detonate if enough time has elapsed. This value counts\n\t\t**\tdown. When it reaches zero, detonation occurs.\n\t\t*/\n\t\tunsigned char Timer;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tSome fuses need a certain amount of time before detonation can\n\t\t**\toccur. This counts down and when it reaches zero, normal fuse\n\t\t**\tdetonation checking can occur.\n\t\t*/\n\t\tunsigned char Arming;\n\n\t\t/*\n\t\t**\tThis is the designated impact point of the projectile. The fuse\n\t\t**\twill trip when the closest point to this location has been reached.\n\t\t*/\n\t\tCOORDINATE HeadTo;\n\n\t\t/*\n\t\t**\tThis is the running proximity value to the impact point. This value\n\t\t**\twill progressively get smaller. Detonation occurs when it reaches\n\t\t**\tzero or when it starts to grow larger.\n\t\t*/\n\t\tshort Proximity;\n};\n\ninline COORDINATE FuseClass::Fuse_Target(void)\n{\n\treturn(HeadTo);\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/GADGET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GADGET.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GADGET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/03/95                                                     *\n *                                                                                             *\n *                  Last Update : August 1, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GadgetClass::Action -- Base action for gadget.                                            *\n *   GadgetClass::Clear_Focus -- Clears the focus if this gadget has it.                       *\n *   GadgetClass::Delete_List -- Deletes all gadget objects in list.                           *\n *   GadgetClass::Disable -- Disables the gadget from input processing.                        *\n *   GadgetClass::Draw_All -- Forces all gadgets in list to be redrawn.                        *\n *   GadgetClass::Draw_Me -- Gadget redraw action (flag control).                              *\n *   GadgetClass::Enable -- Enables the gadget.                                                *\n *   GadgetClass::Extract_Gadget -- Sweeps through the gadget chain to find gadget specified.  *\n *   GadgetClass::Flag_To_Redraw -- Flags this gadget to be redrawn.                           *\n *   GadgetClass::GadgetClass -- Constructor for gadget object.                                *\n *   GadgetClass::GadgetClass -- Default constructor for a gadget class object.                *\n *   GadgetClass::Get_Next -- Returns a pointer to the next gadget in the chain.               *\n *   GadgetClass::Get_Prev -- Fetches a pointer to the previous gadget.                        *\n *   GadgetClass::Has_Focus -- Checks if this object currently has the keyboard focus.         *\n *   GadgetClass::Remove -- Removes the specified gadget from the list.                        *\n *   GadgetClass::Set_Focus -- Sets focus to this gadget.                                      *\n *   GadgetClass::Sticky_Process -- Handles the sticky flag processing.                        *\n *   GadgetClass::~GadgetClass -- Destructor for gadget object.                                *\n *   GadgetClass::Is_List_To_Redraw -- tells if any gadget in the list needs redrawing         *\n *   GadgetClass::GadgetClass -- Constructor for the gadget object.                            *\n *   GadgetClass::Set_Position -- Set the coordinate position of this gadget.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/*\n**\tThis records the current gadget the the gadget system is \"stuck on\". Such a\n**\tgadget will be processed to the exclusion of all others until the mouse button\n**\tis no longer pressed.\n*/\nGadgetClass * GadgetClass::StuckOn = 0;\n\n/*\n**\tThis is a copy of a pointer to the last list used by the gadget input system.\n**\tIf a change of list is detected, then all gadgets are forced to be redrawn.\n*/\nGadgetClass * GadgetClass::LastList = 0;\n\n\n/*\n**\tThis points to the gadget that is intercepting all keyboard events.\n*/\nGadgetClass * GadgetClass::Focused = 0;\n\n\n/*\n** This points to the current color scheme for drawing all gadgets.\n*/\nstatic RemapControlType _GreyScheme = {15};\nRemapControlType * GadgetClass::ColorScheme = &_GreyScheme;\n\n\n/***********************************************************************************************\n * GadgetClass::GadgetClass -- Constructor for gadget object.                                  *\n *                                                                                             *\n *    This is the normal constructor for gadget objects. A gadget object is only concerned     *\n *    with the region on the screen to considered \"its own\" as well as the flags that tell     *\n *    what mouse action should be recognized when the mouse is over this screen area.          *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinates (in pixels) of the upper left hand corner of the region that  *\n *                   will be \"owned\" by this gadget.                                           *\n *                                                                                             *\n *          w,h   -- Width and height (in pixels) of this gadget's region.                     *\n *                                                                                             *\n *          flags -- The flags (mouse conditions) that will cause this gadget's action         *\n *                   function to be called.                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::GadgetClass(int x, int y, int w, int h, unsigned flags, int sticky) :\n\tX(x), Y(y), Width(w), Height(h), IsToRepaint(false), IsSticky(sticky), IsDisabled(false), Flags(flags)\n{\n\tif (IsSticky) {\n\t\tFlags |= LEFTPRESS|LEFTRELEASE;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::GadgetClass -- Constructor for the gadget object.                              *\n *                                                                                             *\n *    This is the copy constructor for the gadget object. It will try to duplicate the         *\n *    righthand gadget.                                                                        *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the initilization gadget.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::GadgetClass(GadgetClass const & gadget) :\n\tX(gadget.X),\n\tY(gadget.Y),\n\tWidth(gadget.Width),\n\tHeight(gadget.Height),\n\tIsToRepaint(gadget.IsToRepaint),\n\tIsSticky(gadget.IsSticky),\n\tIsDisabled(gadget.IsDisabled),\n\tFlags(gadget.Flags)\n{\n}\n\n\n/***********************************************************************************************\n * GadgetClass::~GadgetClass -- Destructor for gadget object.                                  *\n *                                                                                             *\n *    This is the destructor for the gadget object. It will clear the focus from this gadget   *\n *    if this gadget currently has the focus.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass::~GadgetClass(void)\n{\n\tif (Has_Focus()) {\n\t\tClear_Focus();\n\t}\n\n\tif (this == StuckOn) {\n\t\tStuckOn = NULL;\n\t}\n\n\tif (this == LastList) {\n\t\tLastList = NULL;\n\t}\n\n\tif (this == Focused) {\n\t\tFocused = NULL;\n\t}\n}\n\n\n/***************************************************************************\n * GADGETCLASS::CLICKEDON -- If a mouse click is detected within gadget's  *\n *      area and the appropriate flag is set, then call Action().          *\n *                                                                         *\n * INPUT:      int key, int mousex, int mousey                             *\n *                                                                         *\n * OUTPUT:     true or false                                               *\n *                                                                         *\n * WARNINGS:   none.                                                       *\n *                                                                         *\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nint GadgetClass::Clicked_On(KeyNumType & key, unsigned flags, int mousex, int mousey)\n{\n\t/*\n\t**\tSet flags to match only those events that occur AND are being looked for. If\n\t**\tthe result is NULL, then we know that this button should be ignored.\n\t*/\n\tflags &= Flags;\n\n\t/*\n\t**\tIf keyboard input should be processed by this \"gadget\" and keyboard input is\n\t**\tdetected, then always call the action function. It is up to the action function\n\t**\tin this case to either ignore the keyboard input or not.\n\t**\n\t**\tFor mouse actions, check to see if the mouse is in the region of the button\n\t**\tbefore calling the associated action function. This is the typical action for\n\t**\tbuttons.\n\t*/\n\tif (this == StuckOn ||\n\t\t(flags & KEYBOARD) ||\n\t\t(flags && (mousex - X) < Width  && (mousey - Y) < Height)) {\n\n\t\treturn(Action(flags, key));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Enable -- Enables the gadget.                                                  *\n *                                                                                             *\n *    This function enables the gadget. An enabled gadget will be processed for input          *\n *    purposes.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Enable(void)\n{\n\tIsDisabled = false;\n\tIsToRepaint = true;\n\tClear_Focus();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Disable -- Disables the gadget from input processing.                          *\n *                                                                                             *\n *    This routine will disable the gadget. A disabled gadget might be rendered, but is        *\n *    ignored for input processing.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Disable(void)\n{\n\tIsDisabled = true;\n\tIsToRepaint = true;\n\tClear_Focus();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Remove -- Removes the specified gadget from the list.                          *\n *                                                                                             *\n *    Use this routine if an individual gadget needs to be removed from the list of gadgets.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the specified gadget found and removed? A false indicates that the       *\n *                gadget wasn't in the list.                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Remove(void)\n{\n\tClear_Focus();\n\treturn(GadgetClass *)LinkClass::Remove();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Get_Next -- Returns a pointer to the next gadget in the chain.                 *\n *                                                                                             *\n *    This returns with the next gadget's pointer. It is identical to the base Get_Next()      *\n *    function, but returns a pointer to a GadgetClass object.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the next gadget in the list.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Get_Next(void) const\n{\n\treturn(GadgetClass*)LinkClass::Get_Next();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Get_Prev -- Fetches a pointer to the previous gadget.                          *\n *                                                                                             *\n *    This routine will return the previous gadget in the list. It is identical to the base    *\n *    function Get_Prev, but returns a pointer to a GadgetClass object.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the previous gadget in the list.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * GadgetClass::Get_Prev(void) const\n{\n\treturn(GadgetClass*)LinkClass::Get_Prev();\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Delete_List -- Deletes all gadget objects in list.                             *\n *                                                                                             *\n *    This function will delete all gadgets in the list. It is the counterpart to the          *\n *    Create_One_Of functions.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Any references to these gadget become invalidated by this routine.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Delete_List(void)\n{\n\tGadgetClass * g = this;\n\n\t/*\n\t**\tMove to head of the list.\n\t*/\n\twhile (g->Get_Prev()) {\n\t\tg = g->Get_Prev();\n\t}\n\n\t/*\n\t**\tFirst delete all the gadgets following the first one. The reason the first one\n\t**\tis kept around is that sometimes deleting one gadget will result in related gadgets\n\t**\tin the same list also being deleted. The first gadget will always contain the\n\t**\tcorrect gadget pointer.\n\t*/\n\twhile (g) {\n\t\tg->Clear_Focus();\n\n\t\tGadgetClass * temp = g;\n\t\tg = g->Get_Next();\n\t\tdelete temp;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Action -- Base action for gadget.                                              *\n *                                                                                             *\n *    This handles the base level action that a gadget performs when a qualifying input event  *\n *    is detected. This sets the redraw flag and returns true (to stop further processing).    *\n *    If no qualifying input event was detected, but this routine was called anyway, then      *\n *    don't perform any action. The call to this routine, in that case, must have been forced  *\n *    for some other reason.                                                                   *\n *                                                                                             *\n * INPUT:   flag  -- The input event bits that qualify for this gadget. A NULL indicates that  *\n *                   no qualifying event occurred.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Should further gadget list processing be aborted?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Action(unsigned flags, KeyNumType &)\n{\n\t/*\n\t**\tIf any of the event flags are active, then this indicates that something probably\n\t**\thas changed the gadget. Flag the gadget to be redrawn. Also, make sure that\n\t**\tany sticky flags are cleared up.\n\t*/\n\tif (flags) {\n\t\tIsToRepaint = true;\n\t\tSticky_Process(flags);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Draw_Me -- Gadget redraw action (flag control).                                *\n *                                                                                             *\n *    At this level, there is no actual rendering taking place with the call to Draw_Me, but   *\n *    the IsToRepaint flag must be cleared. Derived objects will call this routine and if it   *\n *    returns true, they will perform their custom rendering.                                  *\n *                                                                                             *\n * INPUT:   forced   -- Is this redraw forced by outside circumstances?                        *\n *                                                                                             *\n * OUTPUT:  bool; Should the gadget imagery be redrawn?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/14/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Draw_Me(int forced)\n{\n\tif (forced || IsToRepaint) {\n\t\tIsToRepaint = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Draw_All -- Forces all gadgets in list to be redrawn.                          *\n *                                                                                             *\n *    Use this function to cause all gadget in the list to be redrawn regardless of the state  *\n *    of the IsToRepaint flag.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Draw_All(bool forced)\n{\n\tGadgetClass * gadget = this;\n\n\twhile (gadget != NULL) {\n\t\tgadget->Draw_Me(forced);\n\t\tgadget = gadget->Get_Next();\n\t}\n}\n\n\n/***************************************************************************\n * GADGETCLASS::PROCESSLIST -- Check list for a mouse click within a gadget*\n *                                                                         *\n * INPUT:      none.                                                       *\n *                                                                         *\n * OUTPUT:     key pressed.                                                *\n *                                                                         *\n * WARNINGS:   none.                                                       *\n *                                                                         *\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nKeyNumType GadgetClass::Input(void)\n{\n\tint mousex, mousey;\n\tKeyNumType key;\n\tunsigned flags;\n\tint forced = false;\n\n\t/*\n\t**\tRecord this list so that a forced redraw only occurs the FIRST time the\n\t**\tgadget list is passed to this routine.\n\t*/\n\tif (LastList != this) {\n\t\tLastList = this;\n\t\tforced = true;\n\t\tStuckOn = NULL;\n\t\tFocused = NULL;\n\t}\n\n\t/*\n\t**\tFetch any pending keyboard input.\n\t*/\n\tkey = Keyboard->Check();\n\tif (key != 0) {\n\t\tkey = Keyboard->Get();\n\t}\n\n#ifdef WIN32\n#ifdef CHEAT_KEYS\n\tif (key == KN_K && !Debug_Map && (Debug_Flag || Debug_Playtest)) {\n\t\t/*\n\t\t** time to create a screen shot using the PCX code (if it works)\n\t\t*/\n\t\tif (!Debug_MotionCapture) {\n\t\t\tGraphicBufferClass temp_page(\tSeenBuff.Get_Width(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Height(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSeenBuff.Get_Width() * SeenBuff.Get_Height());\n\t\t\tCDFileClass file;\n\t\t\tchar filename[30];\n\n//\t\t\tHide_Mouse();\n\t\t\tSeenBuff.Blit(temp_page);\n//\t\t\tShow_Mouse();\n\t\t\tfor (int lp = 0; lp < 99; lp ++) {\n\t\t\t\tsprintf(filename, \"scrsht%02d.pcx\", lp);\n\t\t\t\tfile.Set_Name(filename);\n\t\t\t\tif (!file.Is_Available()) break;\n\t\t\t}\n\n\t\t\tfile.Cache(200000);\n\t\t\tWrite_PCX_File(file, temp_page, & GamePalette);\n\t\t\tSound_Effect(VOC_BEEP);\n\t\t}\n\t}\n#endif\n#endif\n\n\t/*\n\t**\tFor mouse button clicks, the mouse position is actually held in the MouseQ...\n\t**\tglobals rather than their normal Mouse... globals. This is because we need to\n\t**\tknow the position of the mouse at the exact instant when the click occurred\n\t**\trather the the mouse position at the time we get around to this function.\n\t*/\n\tif (((key&0xFF) == KN_LMOUSE) || ((key&0xFF) == KN_RMOUSE)) {\n\t   mousex = Keyboard->MouseQX;\n\t   mousey = Keyboard->MouseQY;\n\t} else {\n\t   mousex = Get_Mouse_X();\n\t   mousey = Get_Mouse_Y();\n\t}\n\n\t/*\n\t**\tSet the mouse button state flags. These will be passed to the individual\n\t**\tbuttons so that they can determine what action to perform (if any).\n\t*/\n\tflags = 0;\n\tif (key) {\n\t\tif (key == KN_LMOUSE) {\n\t\t\tflags |= LEFTPRESS;\n\t\t}\n\t\tif (key == KN_RMOUSE) {\n\t\t\tflags |= RIGHTPRESS;\n\t\t}\n\t\tif (key == (KN_LMOUSE | KN_RLSE_BIT)) {\n\t\t\tflags |= LEFTRELEASE;\n\t\t}\n\t\tif (key == (KN_RMOUSE | KN_RLSE_BIT)) {\n\t\t\tflags |= RIGHTRELEASE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the mouse wasn't responsible for this key code, then it must be from\n\t**\tthe keyboard. Flag this fact.\n\t*/\n\tif (key && !flags) {\n\t\tflags |= KEYBOARD;\n\t}\n\n\t/*\n\t**\tMouse button up or down action is ignored if there is a keyboard event. This\n\t**\tallows keyboard events to fall through normally even if the mouse is over a\n\t**\tgadget that is flagged for LEFTUP or RIGHTUP.\n\t*/\n\tif (!key) {\n\n\t\t/*\n\t\t**\tCheck for the mouse being held down. We can't use the normal input system\n\t\t**\tfor this, so we must examine the actual current state of the mouse\n\t\t**\tbuttons. As a side note, if we determine that the mouse button isn't being\n\t\t**\theld down, then we automatically know that it must be up -- set the flag\n\t\t**\taccordingly.\n\t\t*/\n\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t\t\tflags |= LEFTHELD;\n\t\t} else {\n\t\t\tflags |= LEFTUP;\n\t\t}\n\t\tif (Keyboard->Down(KN_RMOUSE)) {\n\t\t\tflags |= RIGHTHELD;\n\t\t} else {\n\t\t\tflags |= RIGHTUP;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf \"sticky\" processing is active, then only process the stuck gadget.\n\t*/\n\tif (StuckOn) {\n\t\tStuckOn->Draw_Me(false);\n\t\tGadgetClass * oldstuck = StuckOn;\n\t\tStuckOn->Clicked_On(key, flags, mousex, mousey);\n\t\tif (StuckOn) {\n\t\t\tStuckOn->Draw_Me(false);\n\t\t} else {\n\t\t\toldstuck->Draw_Me(false);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tIf there is a gadget that has the keyboard focus, then route all keyboard\n\t\t**\tevents to it.\n\t\t*/\n\t\tif (Focused && (flags & KEYBOARD)) {\n\t\t\tFocused->Draw_Me(false);\n\t\t\tFocused->Clicked_On(key, flags, mousex, mousey);\n\t\t\tif (Focused) {\n\t\t\t\tFocused->Draw_Me(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSweep through all the buttons in the chain and pass the current button state\n\t\t\t**\tand keyboard input data to them. These routines will detect whether they should\n\t\t\t**\tperform some action and return a flag to this effect. They also have the option\n\t\t\t**\tof changing the key value so that an appropriate return value is use for this\n\t\t\t**\tprocessing routine.\n\t\t\t*/\n\t\t\tGadgetClass * next_button = this;\n\t\t\twhile (next_button != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tMaybe redraw the button if it needs to or is being forced to redraw.\n\t\t\t\t*/\n\t\t\t\tnext_button->Draw_Me(forced);\n\n\t\t\t\tif (!next_button->IsDisabled) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tProcess this button. If the button was recognized and action was\n\t\t\t\t\t**\tperformed, then bail from further processing (speed reasons?).\n\t\t\t\t\t*/\n\t\t\t\t\tif (next_button->Clicked_On(key, flags, mousex, mousey)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSome buttons will require repainting when they perform some action.\n\t\t\t\t\t\t**\tDo so at this time.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tnext_button->Draw_Me(false);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnext_button = next_button->Get_Next();\n\t\t\t}\n\t\t}\n\t}\n\treturn(key);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Extract_Gadget -- Sweeps through the gadget chain to find gadget specified.    *\n *                                                                                             *\n *    This examines the gadget list looking for on that has the same ID as specified. If that  *\n *    gadget was found, then a pointer to it is returned. Since only ControlClass gadgets      *\n *    or ones derived from it can have an ID value, we know that the returned pointer is at    *\n *    least of the ControlClass type.                                                          *\n *                                                                                             *\n * INPUT:   id -- The ID number to scan for. Zero is not a legal ID number and if passed in,   *\n *                a NULL will always be returned.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ControlClass gadget that has the matching ID number. *\n *          If no matching gadget was found, then NULL is returned.                            *\n *                                                                                             *\n * WARNINGS:   If there happens to be more than one gadget with a matching ID, this routine    *\n *             will return a pointer to the first one only.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nControlClass * GadgetClass::Extract_Gadget(unsigned id)\n{\n\tGadgetClass * g = this;\n\n\tif (id != 0) {\n\t\twhile (g != NULL) {\n\t\t\tif (g->Get_ID() == id) {\n\t\t\t\treturn((ControlClass *)g);\n\t\t\t}\n\t\t\tg = g->Get_Next();\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Flag_To_Redraw -- Flags this gadget to be redrawn.                             *\n *                                                                                             *\n *    Use this routine to flag the gadget to be redrawn. A gadget so flagged will have its     *\n *    Draw_Me function called at the next available opportunity. Usually, this is the next     *\n *    time the Input() function is called.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Flag_To_Redraw(void)\n{\n\tIsToRepaint = true;\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Sticky_Process -- Handles the sticky flag processing.                          *\n *                                                                                             *\n *    This function examines the event flags and handles any \"sticky\" processing required.     *\n *    Sticky processing is when the button is flagged with the \"IsSticky\" bit and it will      *\n *    be processed to the exclusion of all other gadgets while the mouse button is held        *\n *    down.                                                                                    *\n *                                                                                             *\n * INPUT:   flags -- The event flags that triggered the call to this routine.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Sticky_Process(unsigned flags)\n{\n\tif (IsSticky && (flags & LEFTPRESS)) {\n\t\tStuckOn = this;\n\t}\n\tif (StuckOn == this && (flags & LEFTRELEASE)) {\n\t\tStuckOn = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Set_Focus -- Sets focus to this gadget.                                        *\n *                                                                                             *\n *    This will set the focus to this gadget regardless of any current focus setting. If there *\n *    is another gadget that has focus, it will have its focus cleared before this gadget will *\n *    get the focus. A focused gadget is one that has all keyboard input routed to it.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Set_Focus(void)\n{\n\tif (Focused) {\n\t\tFocused->Flag_To_Redraw();\n\t\tFocused->Clear_Focus();\n\t}\n\tFlags |= KEYBOARD;\n\tFocused = this;\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Clear_Focus -- Clears the focus if this gadget has it.                         *\n *                                                                                             *\n *    Use this function to clear the focus for the gadget. If the gadget doesn't currently     *\n *    have focus, then this routine will do nothing. For added functionality, overload this    *\n *    virtual function so that gadget specific actions may be take when focus is lost.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Clear_Focus(void)\n{\n\tif (Focused == this) {\n\t\tFlags &= ~KEYBOARD;\n\t\tFocused = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Has_Focus -- Checks if this object currently has the keyboard focus.           *\n *                                                                                             *\n *    If this object has the keyboard focus, then this routine will return true. When the      *\n *    gadget has keyboard focus, all keyboard events get routed to the gadget.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this gadget have the keyboard focus?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool GadgetClass::Has_Focus(void)\n{\n\treturn(this == Focused);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Is_List_To_Redraw -- tells if any gadget in the list needs redrawing           *\n *                                                                                             *\n * This function is mostly for supporting HidPage drawing.  If it returns true, it means       *\n * the application needs to re-blit the HidPage forward, after calling the list's Input().     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  true = an item needs redrawing, false = no items need redrawing                    *\n *                                                                                             *\n * WARNINGS:   It is assumed 'this' is the head of the list.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *=============================================================================================*/\nint GadgetClass::Is_List_To_Redraw(void)\n{\n\tGadgetClass * gadget = this;\n\n\twhile (gadget != NULL) {\n\t\tif (gadget->IsToRepaint) {\n\t\t\treturn (true);\n\t\t}\n\t\tgadget = gadget->Get_Next();\n\t}\n\treturn (false);\n}\n\n\n/***********************************************************************************************\n * GadgetClass::Set_Position -- Set the coordinate position of this gadget.                    *\n *                                                                                             *\n *    This routine helps with moving a gadget's location. It will set the gadgets upper        *\n *    left corner to the pixel location specified.                                             *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y position to put the gadget's upper left corner to.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GadgetClass::Set_Position(int x, int y)\n{\n\tX = x;\n\tY = y;\n}\n\n"
  },
  {
    "path": "REDALERT/GADGET.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GADGET.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GADGET.H                                                     *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg                                  *\n *                                                                                             *\n *                   Start Date : January 3, 1995                                              *\n *                                                                                             *\n *                  Last Update : January 3, 1995   [MML]                                      *\n *                                                                                             *\n *                                                                                             *\n *        LinkClass [This is the linked list manager class. It keeps a record                  *\n *                  of the next and previous gadget in the list. It is possible               *\n *                  delete a gadget out of the middle of the list with this                   *\n *                  class.]                                                                   *\n *                                                                                            *\n *       GadgetClass [The is the basic gadget class. It handles processing of                  *\n *                   input events and dispatching the appropriate functions.                  *\n *                   All gadgets must be derived from this class.]                            *\n *            Ŀ                                                                           *\n *                                                                                           *\n *              ListClass [This list class functions like a list box does in Windows. It      *\n *                         keeps track of a list of text strings. This list can be            *\n *                         scrolled and an item selected. If the list becomes larger than     *\n *                         can be completely displayed, it will automatically create a        *\n *                         slider (at the right edge) to manage the scrolling.]               *\n *                                                                                            *\n *      ControlClass [This class adds the concept of giving an ID number to the                *\n *                   gadget. This ID can then be returned from the Input()                    *\n *                   function as if it were a pseudo-keystroke. Additionally,                 *\n *                   the ability to inform another button that this button has                *\n *                   been actioned is allowed. This ability allows one button                 *\n *                   to watch what happens to another button. Example: a list                 *\n *                   box gadget can tell when an attached slider has been                     *\n *                   touched.]                                                                *\n *    Ŀ                                                                           *\n *                                                                                          *\n *             GaugeClass [This class looks similar to Windows slider, but has               *\n *                        a different controlling logic. There is no thumb and              *\n *                        it serves as a simple variable control setting. This              *\n *                        is analogous to a volume slider.]                                 *\n *                                                                                          *\n *            SliderClass [The slider class is similar to the typical Windows slider. It     *\n *                         has a current setting, a thumb, and a controllable scale. This    *\n *                         is the object created to handle a scrolling list box.]            *\n *                                                                                           *\n *       EditClass                                                                            *\n *                                                                                            *\n *                                                                                            *\n * ToggleClass [The toggle class is used for buttons that have an image and behave just        *\n *             like the buttons in Windows do. That is, they have a separate visual for       *\n *             when they are pressed and raised. They are officially triggered (return        *\n *             their ID number) when the mouse button is released while over the button.      *\n *             This class doesn't perform any rendering itself. It merely provides the        *\n *             logic so that the derived classes will function correctly.]                    *\n *  Ŀ                                                                                   *\n *                                                                                           *\n *     TextButtonClass [The text button functions like a normal Windows style button, but     *\n *                      the imagery is based on text that is displayed on the button. A       *\n *                      typical example would be the \"OK\" or \"Cancel\" buttons.]               *\n *                                                                                            *\n * ShapeButtonClass [The shape buttons is similar to the TextButton but instead of text        *\n *                   being used to give the button its imagery, an actual shape is used        *\n *                   instead. This allows graphic buttons. These are similar to the up/down    *\n *                   arrows seen in a Windows slider.]                                         *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GADGET_H\n#define GADGET_H\n\n#include \"link.h\"\n\nclass ControlClass;\n\nclass GadgetClass : public LinkClass\n{\n\tpublic:\n\t\tfriend class DLLExportClass;\t// ST - 5/13/2019\n\n\t\ttypedef enum FlagEnum {\n\t\t\tLEFTPRESS    = 0x0001,\t// Left mouse button press.\n\t\t\tLEFTHELD     = 0x0002,\t// Left mouse button is being held down.\n\t\t\tLEFTRELEASE  = 0x0004,\t// Left mouse button released.\n\t\t\tLEFTUP       = 0x0008,\t// Left mouse button is being held up.\n\t\t\tRIGHTPRESS   = 0x0010,\t// Right mouse button press.\n\t\t\tRIGHTHELD    = 0x0020,\t// Right mouse button is being held down.\n\t\t\tRIGHTRELEASE = 0x0040,\t// Right mouse button released.\n\t\t\tRIGHTUP      = 0x0080,\t// Right mouse button is being held up.\n\t\t\tKEYBOARD     = 0x0100\t// Keyboard input processing (maybe).\n\t\t} FlagEnum;\n\n\t\tGadgetClass(int x, int y, int w, int h, unsigned flags, int sticky=false);\n\t\tGadgetClass(NoInitClass const & x) : LinkClass(x) {};\n\t\tGadgetClass(void) {};\n\t\tGadgetClass(GadgetClass const & gadget);\n\t\tvirtual ~GadgetClass(void);\n\n\t\t/*\n\t\t**\tGadget list management functions.\n\t\t*/\n\t\tvirtual KeyNumType Input(void);\n\t\tvirtual void Draw_All(bool forced=true);\n\t\tvirtual void Delete_List(void);\n\t\tvirtual ControlClass * Extract_Gadget(unsigned id);\n\t\tvirtual void Flag_List_To_Redraw(void) {LastList = 0;};\n\t\tvirtual GadgetClass * Remove(void);\n\t\tvirtual GadgetClass * Get_Next(void) const;\n\t\tvirtual GadgetClass * Get_Prev(void) const;\n\n\t\t/*\n\t\t**\tManages individual gadget states and actions.\n\t\t*/\n\t\tvirtual void Disable(void);\n\t\tvirtual void Enable(void);\n\t\tvirtual unsigned Get_ID(void) const {return 0;};\n\t\tvirtual void Flag_To_Redraw(void);\n\t\tvirtual void Peer_To_Peer(unsigned , KeyNumType & , ControlClass & ) {};\n\t\tvirtual void Set_Focus(void);\n\t\tvirtual void Clear_Focus(void);\n\t\tvirtual bool Has_Focus(void);\n\t\tvirtual int  Is_List_To_Redraw(void);\n\t\tvirtual bool Is_To_Redraw(void) {return (IsToRepaint);}\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t**\tGeneral render function.\n\t\t*/\n\t\tvirtual int Draw_Me(int forced=false);\n\n\t\t/*\n\t\t** Sets the current color scheme\n\t\t*/\n\t\tstatic void Set_Color_Scheme(RemapControlType *scheme)\n\t\t\t{ ColorScheme = scheme; }\n\n\t\tstatic RemapControlType * Get_Color_Scheme(void)\n\t\t\t{ return (ColorScheme); }\n\n\t\t/*\n\t\t**\tThis is the coordinates and dimensions of the gadget region. These are in\n\t\t**\tabsolute screen pixel coordinates.\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\t\tint Width;\n\t\tint Height;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tProcesses the event flags so that if this gadget needs to \"stick\" or\n\t\t**\t\"unstick\", it will be properly flagged. Call this function if you are\n\t\t**\tgoing to clear the button press flags before calling the base class\n\t\t**\tAction() function. Otherwise, calling this function manually, is\n\t\t**\tunnecessary since the base class Action() function already does so.\n\t\t*/\n\t\tvirtual void Sticky_Process(unsigned flags);\n\n\t\t/*\n\t\t**\tThis is the action function that will be called whenever the flags and mouse\n\t\t**\tinput indicates. This is the main method by which this button performs a useful\n\t\t**\tfunction.\n\t\t*/\n\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\n\t\t/*\n\t\t**\tThis is a record of the last list passed to the Input() function. If a list\n\t\t**\tdifferent than the last recorded one is detected, then the draw function is\n\t\t**\tcalled for every gadget in the list. This causes all buttons to be redrawn the\n\t\t**\tfire time Input() is called without forced a manual call to Draw_All().\n\t\t*/\n\t\tstatic GadgetClass * LastList;\n\n\t\t/*\n\t\t**\tThis points to the gadget that has the keyboard focus. All keyboard only\n\t\t**\tevents are fed to this gadget to the exclusion of all others.\n\t\t*/\n\t\tstatic GadgetClass * Focused;\n\n\t\t/*\n\t\t**\tThis button should call the Draw_Me function because some graphic element needs\n\t\t**\tto be redrawn. This flag is set by default if the Action function is called.\n\t\t*/\n\t\tunsigned IsToRepaint:1;\n\n\tpublic:\t\t// HACK HACK HACK.. this is here because the sidebar buttons are static.\n\t\t/*\n\t\t**\tA sticky button is one that is processed to the exclusion of all other buttons\n\t\t**\tIF the mouse was pressed down while over this button and the mouse continues\n\t\t**\tto remain pressed. This is the standard behavior for all normal Windows style\n\t\t**\tbuttons.\n\t\t*/\n\t\tunsigned IsSticky:1;\n\n\t\t//\tajw - Publicized StuckOn 7/30/98 (was protected)\n\t\t/*\n\t\t**\tIf there is a sticky button being processed, then this will point to it. A sticky\n\t\t**\tbutton is one that will ONLY be processed while the mouse button is being\n\t\t**\theld down.\n\t\t*/\n\t\tstatic GadgetClass * StuckOn;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the button is disabled, then it won't be processed by the input function. It will\n\t\t**\thave its Draw_Me function called as necessary. In order to not display the button\n\t\t**\tat all, the appropriate draw function should perform no action -- just return. Or,\n\t\t**\tjust remove the button from the list.\n\t\t*/\n\t\tunsigned IsDisabled:1;\n\n\t\t/*\n\t\t**\tThese are the action flags that are used to determine when the action function\n\t\t**\tshould be called. Example: If this gadget only wants the action button called when\n\t\t**\tthe left mouse button is pressed over the its region, then the flag will be set\n\t\t**\tto LEFTPRESS.\n\t\t*/\n\t\tunsigned Flags;\n\n\t\t/*\n\t\t** This is the current color scheme; it must be initialized by the app.\n\t\t*/\n\t\tstatic RemapControlType *ColorScheme;\n\n\tprivate:\npublic:\t\t//ST - 5/14/2019\n\t\tvirtual int Clicked_On(KeyNumType & key, unsigned flags, int x, int y);\n};\n\n//PG\n//inline GadgetClass::FlagEnum operator |(GadgetClass::FlagEnum, GadgetClass::FlagEnum);\n//inline GadgetClass::FlagEnum operator &(GadgetClass::FlagEnum, GadgetClass::FlagEnum);\n//inline GadgetClass::FlagEnum operator ~(GadgetClass::FlagEnum);\n\ninline GadgetClass::FlagEnum operator|(GadgetClass::FlagEnum a, GadgetClass::FlagEnum b)\n{\n\treturn static_cast<GadgetClass::FlagEnum>(static_cast<int>(a) | static_cast<int>(b));\n}\n\ninline GadgetClass::FlagEnum operator&(GadgetClass::FlagEnum a, GadgetClass::FlagEnum b)\n{\n\treturn static_cast<GadgetClass::FlagEnum>(static_cast<int>(a) & static_cast<int>(b));\n}\n\ninline GadgetClass::FlagEnum operator~(GadgetClass::FlagEnum a)\n{\n\treturn static_cast<GadgetClass::FlagEnum>(~static_cast<int>(a));\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/GAMEDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GAMEDLG.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAMEDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"gamedlg.h\"\n#include \"sounddlg.h\"\n#include \"visudlg.h\"\n#define GERMAN_OFFSET_Y   4      //VG\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\nbool WOL_Options_Dialog( WolapiObject* pWO, bool bCalledFromGame );\n#endif\n\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   12/31/1994 MML : Created.                                                                 *\n *=============================================================================================*/\nvoid GameControlsClass::Process(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint\td_dialog_w = 232 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint\td_dialog_h = 141 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint\td_dialog_x = ((SeenBuff.Get_Width() - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint\td_dialog_y = ((SeenBuff.Get_Height() - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint\td_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\tint\td_top_margin = 25 * RESFACTOR;\n\n\tint\td_txt6_h = (6 * RESFACTOR) + 1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint\td_margin1 = (5 * RESFACTOR);\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\tint\td_margin2 = (2 * RESFACTOR);\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\tint\td_speed_w = d_dialog_w - (34 * RESFACTOR);\n\tint\td_speed_h = 6 * RESFACTOR;\n\tint\td_speed_x = d_dialog_x + (17 * RESFACTOR);\n#ifdef GERMAN\n\tint\td_speed_y = d_dialog_y + d_top_margin + d_margin1 + d_txt6_h - GERMAN_OFFSET_Y;\n#else\n\tint\td_speed_y = d_dialog_y + d_top_margin + d_margin1 + d_txt6_h;\n#endif\n\n\tint\td_scroll_w = d_dialog_w - (34 * RESFACTOR);\n\tint\td_scroll_h = 6 * RESFACTOR;\n\tint\td_scroll_x = d_dialog_x + (17 * RESFACTOR);\n#ifdef GERMAN\n\tint\td_scroll_y = d_speed_y + d_speed_h + d_txt6_h + (d_margin1 * 2) + d_txt6_h - GERMAN_OFFSET_Y;\n#else\n\tint\td_scroll_y = d_speed_y + d_speed_h + d_txt6_h + (d_margin1 * 2) + d_txt6_h;\n#endif\n\n\tint\td_visual_w = d_dialog_w - (40 * RESFACTOR);\n\tint\td_visual_h = 9 * RESFACTOR;\n\tint\td_visual_x = d_dialog_x + (20 * RESFACTOR);\n\tint\td_visual_y = d_scroll_y + d_scroll_h + d_txt6_h + (d_margin1 * 2);\n\n\tint\td_sound_w = d_dialog_w - (40 * RESFACTOR);\n\tint\td_sound_h = (9 * RESFACTOR);\n\tint\td_sound_x = d_dialog_x + (20 * RESFACTOR);\n\tint\td_sound_y = d_visual_y + d_visual_h + d_margin1;\n\n\tint\td_ok_w = 20 * RESFACTOR;\n\tint\td_ok_h = 9 * RESFACTOR;\n\tint\td_ok_x = d_dialog_cx - (d_ok_w / 2);\n\tint\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - (4 * RESFACTOR);\n\n#ifdef WOLAPI_INTEGRATION\n\tint d_wol_x = d_sound_x;\n\tint d_wol_y = d_sound_y + d_sound_h + d_margin1;\n\tint d_wol_w = d_sound_w;\n\tint d_wol_h = d_sound_h;\n\n\tbool bShowWolapi = ( pWolapi && !pWolapi->bConnectionDown );\n\tif( bShowWolapi )\n\t{\n\t\t//\tEnlarge dialog and shift ok button down.\n\t\td_dialog_h += d_wol_h + d_margin1;\n\t\td_dialog_y = ((SeenBuff.Get_Height() - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\t//d_ok_y += d_wol_h + d_margin1;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - (4 * RESFACTOR);\n\t}\n#endif\n\n\t/*\n\t**\tButton Enumerations\n\t*/\n#ifdef WOLAPI_INTEGRATION\n\tenum {\n\t\tBUTTON_SPEED = 100,\n\t\tBUTTON_SCROLLRATE,\n\t\tBUTTON_VISUAL,\n\t\tBUTTON_SOUND,\n\t\tBUTTON_WOLAPI,\n\t\tBUTTON_OK,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_FIRST = BUTTON_SPEED,\n\t};\n#else\n\tenum {\n\t\tBUTTON_SPEED = 100,\n\t\tBUTTON_SCROLLRATE,\n\t\tBUTTON_VISUAL,\n\t\tBUTTON_SOUND,\n\t\tBUTTON_OK,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_FIRST = BUTTON_SPEED,\n\t};\n#endif\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tKeyNumType input;\n\n\tint gamespeed = Options.GameSpeed;\n\tint scrollrate = Options.ScrollRate;\n\tint selection;\n\tbool pressed = false;\n\tint curbutton = 0;\n\tTextButtonClass *buttons[BUTTON_COUNT - BUTTON_FIRST];\n\tTextPrintType style;\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tGadgetClass * commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tSliderClass gspeed_btn(BUTTON_SPEED, d_speed_x, d_speed_y, d_speed_w, d_speed_h, true);\n\tSliderClass scrate_btn(BUTTON_SCROLLRATE, d_scroll_x, d_scroll_y, d_scroll_w, d_scroll_h, true);\n\tTextButtonClass visual_btn(BUTTON_VISUAL, TXT_VISUAL_CONTROLS, TPF_BUTTON, d_visual_x, d_visual_y, d_visual_w, d_visual_h);\n\tTextButtonClass sound_btn(BUTTON_SOUND, TXT_SOUND_CONTROLS, TPF_BUTTON, d_sound_x, d_sound_y, d_sound_w, d_sound_h);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OPTIONS_MENU, TPF_BUTTON, d_ok_x, d_ok_y);\n\tokbtn.X = (SeenBuff.Get_Width()-okbtn.Width)/2;\n\n#ifdef WOLAPI_INTEGRATION\n\tTextButtonClass wol_btn( BUTTON_WOLAPI, TXT_WOL_OPTTITLE, TPF_BUTTON, d_wol_x, d_wol_y, d_wol_w, d_wol_h );\n#endif\n\n\t/*\n\t**\tVarious Inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tBuild button list\n\t*/\n\tcommands = &okbtn;\n\tgspeed_btn.Add_Tail(*commands);\n\tscrate_btn.Add_Tail(*commands);\n\tvisual_btn.Add_Tail(*commands);\n\tsound_btn.Add_Tail(*commands);\n#ifdef WOLAPI_INTEGRATION\n\tif( bShowWolapi )\n\t\twol_btn.Add_Tail(*commands);\n#endif\n\t/*\n\t**\tInit button states\n\t**\tFor sliders, the thumb ranges from 0 - (maxval-1), so to convert the\n\t**\tthumb value to a real-world value:\n\t**\t\tval = (MAX - slider.Get_Value()) - 1;\n\t**\tand,\n\t**\t\tslider.Set_Value(-(val + 1 - MAX));\n\t*/\n\tgspeed_btn.Set_Maximum(OptionsClass::MAX_SPEED_SETTING);\t// varies from 0 - 7\n\tgspeed_btn.Set_Thumb_Size(1);\n\tgspeed_btn.Set_Value((OptionsClass::MAX_SPEED_SETTING-1) - gamespeed);\n\n\tscrate_btn.Set_Maximum(OptionsClass::MAX_SCROLL_SETTING);\t// varies from 0 - 7\n\tscrate_btn.Set_Thumb_Size(1);\n\tscrate_btn.Set_Value((OptionsClass::MAX_SCROLL_SETTING-1) - scrollrate);\n\n\t/*\n\t**\tFill array of button ptrs.\n\t*/\n\tbuttons[0] = NULL;\n\tbuttons[1] = NULL;\n\tbuttons[2] = &visual_btn;\n\tbuttons[3] = &sound_btn;\n#ifdef WOLAPI_INTEGRATION\n\tbuttons[4] = &wol_btn;\n\tbuttons[5] = &okbtn;\n#else\n\tbuttons[4] = &okbtn;\n#endif\n\t/*\n\t**\tProcessing loop.\n\t*/\n\tbool process = true;\n\tbool display = true;\n\tbool refresh = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tMap.Render();\n\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\tDraw_Caption(TXT_GAME_CONTROLS, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\trefresh = true;\n\t\t}\n\n\t\tif (refresh) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tLabel the game speed slider\n\t\t\t*/\n\t\t\tstyle = TPF_TEXT;\n\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST)) {\n\t\t\t\tstyle = (TextPrintType)(style | TPF_BRIGHT_COLOR);\n\t\t\t}\n\t\t\tFancy_Text_Print(TXT_SPEED, d_speed_x, d_speed_y - d_txt6_h, scheme, TBLACK, style);\n\n\t\t\tFancy_Text_Print(TXT_SLOWER, d_speed_x, d_speed_y + d_speed_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT);\n\t\t\tFancy_Text_Print(TXT_FASTER, d_speed_x + d_speed_w, d_speed_y + d_speed_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\t/*\n\t\t\t**\tLabel the scroll rate slider\n\t\t\t*/\n\t\t\tstyle = TPF_TEXT;\n\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST)) {\n\t\t\t\tstyle = (TextPrintType)(style | TPF_BRIGHT_COLOR);\n\t\t\t}\n\t\t\tFancy_Text_Print(TXT_SCROLLRATE, d_scroll_x, d_scroll_y - d_txt6_h, scheme, TBLACK, style);\n\n\t\t\tFancy_Text_Print (TXT_SLOWER, d_scroll_x, d_scroll_y + d_scroll_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT);\n\t\t\tFancy_Text_Print (TXT_FASTER, d_scroll_x + d_scroll_w, d_scroll_y + d_scroll_h + (1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\tcommands->Draw_All();\n\n\t\t\tShow_Mouse();\n\t\t\trefresh = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_SPEED | KN_BUTTON):\n\t\t\t\tcurbutton = (BUTTON_SPEED - BUTTON_FIRST);\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SCROLLRATE | KN_BUTTON):\n\t\t\t\tcurbutton = (BUTTON_SCROLLRATE - BUTTON_FIRST);\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_VISUAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_VISUAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SOUND | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SOUND;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tselection = BUTTON_OK;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tcase (BUTTON_WOLAPI | KN_BUTTON):\n\t\t\t\tselection = BUTTON_WOLAPI;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST) ) {\n\t\t\t\t\tgspeed_btn.Bump(1);\n\t\t\t\t} else\n\t\t\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST) ) {\n\t\t\t\t\t\tscrate_btn.Bump(1);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tif (curbutton == (BUTTON_SPEED - BUTTON_FIRST) ) {\n\t\t\t\t\tgspeed_btn.Bump(0);\n\t\t\t\t} else\n\t\t\t\t\tif (curbutton == (BUTTON_SCROLLRATE - BUTTON_FIRST) ) {\n\t\t\t\t\t\tscrate_btn.Bump(0);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton--;\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tif( !bShowWolapi )\n\t\t\t\t{\n\t\t\t\t\tif( curbutton == BUTTON_WOLAPI - BUTTON_FIRST )\n\t\t\t\t\t\tcurbutton--;\t\t//\tSkip over missing button.\n\t\t\t\t}\n#endif\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = (BUTTON_COUNT - BUTTON_FIRST - 1);\n\t\t\t\t}\n\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\n\t\t\t\tcurbutton++;\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tif( !bShowWolapi )\n\t\t\t\t{\n\t\t\t\t\tif( curbutton == BUTTON_WOLAPI - BUTTON_FIRST )\n\t\t\t\t\t\tcurbutton++;\t\t//\tSkip over missing button.\n\t\t\t\t}\n#endif\n\t\t\t\tif (curbutton > (BUTTON_COUNT - BUTTON_FIRST - 1) ) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\n\t\t\t\tif (buttons[curbutton]) {\n\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\trefresh = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_FIRST;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform some action. Either to exit the dialog or bring up another.\n\t\t*/\n\t\tif (pressed) {\n\n\t\t\t/*\n\t\t\t**\tRecord the new options slider settings.\n\t\t\t** The GameSpeed data member MUST NOT BE SET HERE!  It will cause multiplayer\n\t\t\t** games to go out of sync.  It's set by virtue of the event being executed.\n\t\t\t*/\n\t\t\tif (gamespeed != ((OptionsClass::MAX_SPEED_SETTING-1) - gspeed_btn.Get_Value()) ) {\n\t\t\t\tgamespeed = (OptionsClass::MAX_SPEED_SETTING-1) - gspeed_btn.Get_Value();\n\t\t\t\tOutList.Add(EventClass(EventClass::GAMESPEED, gamespeed));\n\t\t\t}\n\n\t\t\tif (scrollrate != ((OptionsClass::MAX_SCROLL_SETTING-1) - scrate_btn.Get_Value()) ) {\n\t\t\t\tscrollrate = (OptionsClass::MAX_SCROLL_SETTING-1) - scrate_btn.Get_Value();\n\t\t\t\tOptions.ScrollRate = scrollrate;\n\t\t\t}\n\t\t\tprocess = false;\n\n\t\t\t/*\n\t\t\t** Save the settings in such a way that the GameSpeed is only set during\n\t\t\t** the save process; restore it when we're done, so multiplayer games don't\n\t\t\t** go out of sync.\n\t\t\t*/\n\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\tOptions.GameSpeed = gamespeed;\n\t\t\t\tOptions.Save_Settings();\t\t\t// save new value\n\t\t\t} else {\n\t\t\t\tint old = Options.GameSpeed;\t\t// save orig value\n\t\t\t\tOptions.GameSpeed = gamespeed;\n\t\t\t\tOptions.Save_Settings();\t\t\t// save new value\n\t\t\t\tOptions.GameSpeed = old;\t\t\t// restore old value\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPossibly launch into another dialog if so directed.\n\t\t\t*/\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_VISUAL):\n\t\t\t\t\tVisualControlsClass().Process();\n\t\t\t\t\tprocess = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\trefresh = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SOUND):\n\t\t\t\t\tif (!SoundType) {\n\t\t\t\t\t\tWWMessageBox().Process(Text_String(TXT_NO_SOUND_CARD));\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSoundControlsClass().Process();\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tcase BUTTON_WOLAPI:\n\t\t\t\t\tif( WOL_Options_Dialog( pWolapi, true ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tThe game ended while in this dialog.\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\trefresh = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_OK):\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "REDALERT/GAMEDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GAMEDLG.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAMEDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GAMEDLG_H\n#define GAMEDLG_H\n\n#include \"gadget.h\"\n\nclass GameControlsClass \n{\n\tpublic:\n\t\tGameControlsClass(void) {};\n\t\tvoid Process(void);\n};\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/GAUGE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GAUGE.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAUGE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 16, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GaugeClass::Action -- Handles input events for the gauge.                                 *\n *   GaugeClass::Draw_Me -- Draws the body of the gauge.                                       *\n *   GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value.                  *\n *   GaugeClass::Set_Maximum -- Sets the maximum value for the gauge.                          *\n *   GaugeClass::Set_Value -- Set the value of the gauge.                                      *\n *   GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * GaugeClass::GaugeClass -- class constructor                             *\n *                                                                         *\n * INPUT:    id                     -- button ID                           *\n *                                                                         *\n *             x,y                     -- upper-left corner, in pixels     *\n *                                                                         *\n *             w,h                     -- width, height, in pixels         *\n *                                                                         *\n * OUTPUT:   none.                                                         *\n *                                                                         *\n * WARNINGS: none.                                                         *\n *                                                                         *\n * HISTORY:  01/05/1995 MML : Created.                                     *\n *=========================================================================*/\nGaugeClass::GaugeClass(unsigned id, int x, int y, int w, int h)\n\t: ControlClass(id, x, y, w, h, LEFTHELD|LEFTPRESS|LEFTRELEASE, true)\n{\n\tSet_Maximum(255);\n\tSet_Value(0);\n\n\tHasThumb = true;\n\tIsHorizontal = (w > h);\n\tIsColorized = true;\n\n\tClickDiff = 0;\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Set_Maximum -- Sets the maximum value for the gauge.                            *\n *                                                                                             *\n *    This routine will set the maximum value for the gauge. This is the largest value that    *\n *    the current setting may reach. The ability to change this allows the gauge to use and    *\n *    return values that are convenient for the programmer's current needs.                    *\n *                                                                                             *\n * INPUT:   value -- The value to use as the gauge maximum.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the gauge maximum changed? A false indicates that the specified value    *\n *                already matches the current maximum.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Set_Maximum(int value)\n{\n\tif (value != MaxValue) {\n\t   MaxValue = value;\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Set_Value -- Set the value of the gauge.                                        *\n *                                                                                             *\n *    This routine will set the current value for the gauge. This value is clipped to the      *\n *    limits of the gauge maximum.                                                             *\n *                                                                                             *\n * INPUT:   value -- The value to set at the new current value.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the current setting changed? A false indicates that the setting          *\n *                specified is the same as what was already there.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Set_Value(int value)\n{\n\tvalue = Bound(value, 0, MaxValue);\n\tif (value != CurValue) {\n\t\tCurValue = value;\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value.                    *\n *                                                                                             *\n *    Use this routine to convert the specified pixel offset into a gauge value. This is used   *\n *    in translating mouse clicks into a corresponding setting for the gauge.                  *\n *                                                                                             *\n * INPUT:   pixel -- The pixel offset form the start of the gauge.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the setting value in gauge coordinates.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Pixel_To_Value(int pixel)\n{\n\tint maximum;\n\n\tif (IsHorizontal) {\n\t\tpixel -= X+1;\n\t\tmaximum = Width;\n\t} else {\n\t\tpixel -= Y+1;\n\t\tmaximum = Height;\n\t}\n\tmaximum -= 2;\n\tpixel = Bound(pixel, 0, maximum);\n\treturn(MaxValue * fixed(pixel, maximum));\n//\treturn(Fixed_To_Cardinal(MaxValue, Cardinal_To_Fixed(maximum, pixel)));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset.                          *\n *                                                                                             *\n *    Use this routine to convert the specified gauge value into a pixel offset from the       *\n *    star of the gauge. This is used for thumb positioning.                                   *\n *                                                                                             *\n * INPUT:   value -- The value to convert to a pixel offset.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the pixel offset of the specified value from the start of the         *\n *          gauge.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Value_To_Pixel(int value)\n{\n\tint maximum;\n\tint start;\n\tif (IsHorizontal) {\n\t\tmaximum = Width;\n\t\tstart = X;\n\t} else {\n\t\tmaximum = Height;\n\t\tstart = Y;\n\t}\n\tmaximum -= 2;\n\treturn(start + maximum * fixed(value, MaxValue));\n//\treturn(start + Fixed_To_Cardinal(maximum, Cardinal_To_Fixed(MaxValue, value)));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Draw_Me -- Draws the body of the gauge.                                         *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      forced   -- Should the gauge be redrawn regardless of the current redraw flag?  *\n *                                                                                             *\n * OUTPUT:     bool; Was the gauge redrawn?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint GaugeClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tHide the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color\n\t\t*/\n\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\n\t\t/*\n\t\t**\tColourize the inside of the gauge if indicated.\n\t\t*/\n\t\tif (IsColorized) {\n\t\t\tint middle = Value_To_Pixel(CurValue);\n\t\t\tint color = GadgetClass::Get_Color_Scheme()->Bright;\n\t\t\tif (IsHorizontal) {\n\t\t\t\tif (middle >= (X + 1))\n\t\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, color);\n\t\t\t} else {\n\t\t\t\tif (middle >= (Y + 1))\n\t\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, color);\n\t\t\t}\n\t\t}\n\n\t\tif (HasThumb) {\n\t\t\tDraw_Thumb();\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Action -- Handles input events for the gauge.                                   *\n *                                                                                             *\n *    This routine will handle input event processing for the gauge. It will adjust the        *\n *    current setting of the gauge according to the mouse position.                            *\n *                                                                                             *\n * INPUT:   flags -- The input event that is the reason for this function call.                *\n *          key   -- The key code that caused the event.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the even recognized, processed, and no further gadget scanning is        *\n *                desired (for this pass).                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint GaugeClass::Action(unsigned flags, KeyNumType &key)\n{\n\t/*\n\t** If there's no thumb on this gauge, it's a display-only device.\n\t*/\n\tif (!HasThumb) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWe might end up clearing the event bits. Make sure that the sticky\n\t**\tprocess is properly updated anyway.\n\t*/\n\tSticky_Process(flags);\n\n\t/*\n\t**\tIf the thumb is currently being \"dragged around\", then update the slider\n\t**\tposition according to the mouse position. In all other cases, ignore the\n\t**\tbutton being held down.\n\t*/\n\tif ((flags & LEFTPRESS) || ((flags & LEFTHELD) && StuckOn == this)) {\n\n\t\t/*\n\t\t** Compute the difference between where we clicked, and the edge of\n\t\t** the thumb (only if we clicked on the thumb.)\n\t\t*/\n\t\tif (flags & LEFTPRESS) {\n\t\t\tint curpix = Value_To_Pixel(CurValue);\n\t\t\tint clickpix = (IsHorizontal ? Get_Mouse_X() : Get_Mouse_Y());\n\n\t\t\tif ( (clickpix > curpix) && (clickpix - curpix) < Thumb_Pixels()) {\n\t\t\t\tClickDiff = (clickpix - curpix);\n\t\t\t} else {\n\t\t\t\tClickDiff = 0;\n\t\t\t}\n\n\t\t\tint testval = Pixel_To_Value(IsHorizontal ?\n\t\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);\n\n\t\t\t/*\n\t\t\t** Correct for round-down errors in Pixel_To_Value() and\n\t\t\t** Value_To_Pixel(); make ClickDiff exactly right so that\n\t\t\t** at this point, Get_Mouse_n() - ClickDiff converts to\n\t\t\t** CurValue.\n\t\t\t*/\n\t\t\twhile (testval < CurValue && ClickDiff > 0) {\n\t\t\t\tClickDiff--;\n\t\t\t\ttestval = Pixel_To_Value(IsHorizontal ?\n\t\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf no change occurred in the gauge, just call Control's Action routine,\n\t\t** but turn off the flags so it won't fill in 'key' with the button ID.\n\t\t** Thus, no button ID will be returned by Input.\n\t\t*/\n\t\tif (!Set_Value(Pixel_To_Value(IsHorizontal ?\n\t\t\tGet_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff))) {\n\n\t\t\tflags &= ~(LEFTHELD|LEFTRELEASE|LEFTPRESS);\n\t\t\tControlClass::Action(0, key);\n\t\t\tkey = KN_NONE;\n\t\t\treturn(true);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIgnore the left mouse button being held down if this gauge is not\n\t\t**\tcurrently in \"sticky\" mode. This allows processing of the LEFTPRESS\n\t\t**\tby any derived classes such that this gauge can be more closely\n\t\t**\tcontrolled.\n\t\t*/\n\t\tflags &= ~LEFTHELD;\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * GaugeClass::Draw_Thumb -- Draws the body of the gauge.                                      *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      none.                                                                           *\n *                                                                                             *\n * OUTPUT:     none.                                                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nvoid GaugeClass::Draw_Thumb(void)\n{\n\tint x = Value_To_Pixel(CurValue);\n\n\tif ((x + 4) > Value_To_Pixel(MaxValue)) {\n\t\tx = Value_To_Pixel(MaxValue) - 2;\n\t}\n\n\tif (x < X) {\n\t\tx = X;\n\t}\n\n\tif (IsHorizontal) {\n\t\tDraw_Box(x, Y, 4, Height, BOXSTYLE_RAISED, true);\n\t} else {\n\t\tDraw_Box(X, x, Width, 4,  BOXSTYLE_RAISED, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::TriColorGaugeClass -- Constructor for 3 color (red\\yellow\\green) gauge. *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:      See below.                                                                      *\n *                                                                                             *\n * OUTPUT:     none.                                                                           *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nTriColorGaugeClass::TriColorGaugeClass(unsigned id, int x, int y, int w, int h)\n\t: GaugeClass(id, x, y, w, h)\n{\n\tRedLimit = 0;\t\t\t\t// maximum value for red\n\tYellowLimit = 0;\t\t\t// maximum value for yellow\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Set_Red_Limit -- Set the value for the red area of gauge.               *\n *                                                                                             *\n * INPUT:      int value.                                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Set_Red_Limit(int value)\n{\n\tif (value >= 0 && value < MaxValue) {\n\n//\t\tif (value > YellowLimit) {\n//\t\t\tRedLimit = YellowLimit;\n//\t\t\tYellowLimit = value;\n//\t\t} else {\n\t\t\tRedLimit = value;\n//\t\t}\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Set_Yellow_Limit -- Set the value for the yellow area of gauge.         *\n *                                                                                             *\n * INPUT:      int value.                                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Set_Yellow_Limit(int value)\n{\n\tif (value >= 0 && value < MaxValue) {\n\n//\t\tif (value < RedLimit) {\n//\t\t\tYellowLimit = RedLimit;\n//\t\t\tRedLimit = value;\n//\t\t} else {\n\t\t\tYellowLimit = value;\n//\t\t}\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * TriColorGaugeClass::Draw_Me -- Draw the tri color gauge.                                    *\n *                                                                                             *\n * INPUT:      int forced -- draw or not?                                                      *\n *                                                                                             *\n * OUTPUT:     bool true of false.                                                             *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:    01/16/1995 MML : Created.                                                       *\n *=============================================================================================*/\nint TriColorGaugeClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tHide the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color\n\t\t*/\n\t\tDraw_Box (X, Y, Width, Height, (IsDisabled ? BOXSTYLE_RAISED : BOXSTYLE_DOWN), true);\n\n\t\t/*\n\t\t**\tColourize the inside of the gauge if indicated.\n\t\t*/\n\t\tint red    = Value_To_Pixel(RedLimit);\n\t\tint yellow = Value_To_Pixel(YellowLimit);\n\t\tint middle = Value_To_Pixel(CurValue);\n\n\t\tif (CurValue <= RedLimit) {\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, PINK);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, PINK);\n\t\t\t}\n\t\t} else if (CurValue > RedLimit && CurValue <= YellowLimit) {\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, red,    Y+Height-2, PINK);\n\t\t\t\tLogicPage->Fill_Rect(red, Y+1, middle, Y+Height-2, YELLOW);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red,    PINK);\n\t\t\t\tLogicPage->Fill_Rect(X+1, red, X+Width-2, middle, YELLOW);\n\t\t\t}\n\t\t} else if (CurValue > YellowLimit && CurValue <= MaxValue) {\n\n\t\t\tif (IsHorizontal) {\n\t\t\t\tLogicPage->Fill_Rect(X+1,    Y+1, red,    Y+Height-2, PINK);\n\t\t\t\tLogicPage->Fill_Rect(red,    Y+1, yellow, Y+Height-2, YELLOW);\n\t\t\t\tLogicPage->Fill_Rect(yellow, Y+1, middle, Y+Height-2, GREEN);\n\t\t\t} else {\n\t\t\t\tLogicPage->Fill_Rect(X+1, Y+1,    X+Width-2, red,    PINK);\n\t\t\t\tLogicPage->Fill_Rect(X+1, red,    X+Width-2, yellow, YELLOW);\n\t\t\t\tLogicPage->Fill_Rect(X+1, yellow, X+Width-2, middle, GREEN);\n\t\t\t}\n\t\t}\n\n\t\tif (HasThumb) {\n\t\t\tDraw_Thumb();\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the mouse\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n"
  },
  {
    "path": "REDALERT/GAUGE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GAUGE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GAUGE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic, Maria del Mar McCready Legg                   *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GAUGE_H\n#define GAUGE_H\n\nclass GaugeClass : public ControlClass\n{\n\tpublic:\n\n\t\tGaugeClass(unsigned id, int x, int y, int w, int h);\n\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual int Set_Maximum(int value);\n\t\tvirtual int Set_Value(int value);\n\t\tvirtual int Get_Value(void) const {return (CurValue);};\n\t\tvirtual void Use_Thumb(int value) { HasThumb = value ? true : false; };\n\n\t\tvirtual int Thumb_Pixels(void) { return (4);}\n\n\t\t/*\n\t\t**\tIf this gauge has a color to the left of the current setting, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsColorized:1;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf a thumb is desired, set to true.\n\t\t*/\n\t\tunsigned HasThumb:1;\n\n\t\t/*\n\t\t**\tIs this a horizontal slider?\n\t\t*/\n\t\tunsigned IsHorizontal:1;\n\n\t\tint MaxValue;\t\t\t\t// maximum value (in application units)\n\t\tint CurValue;\t\t\t\t// index of 1st displayed string in box\n\t\t\t\t\t\t\t\t\t\t//  (in application units)\n\n\t\t/*\n\t\t** This value records the difference between where the user clicked\n\t\t** and the edge of the thumb, so that the thumb follows the mouse\n\t\t** with the proper offset.\n\t\t*/\n\t\tint ClickDiff;\n\n\tprotected:\n\t\tvirtual void Draw_Thumb(void);\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual int  Pixel_To_Value(int pixel);\n\t\tvirtual int  Value_To_Pixel(int value);\n};\n\n\n\nclass TriColorGaugeClass : public GaugeClass\n{\n\tpublic:\n\t\tTriColorGaugeClass(unsigned id, int x, int y, int w, int h);\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual int Set_Red_Limit(int value);\n\t\tvirtual int Set_Yellow_Limit(int value);\n\n\tprotected:\n\t\tint RedLimit;\t\t\t\t// maximum value for red\n\t\tint YellowLimit;\t\t\t// maximum value for yellow\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/GETCPU.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GETCPU.CPP 1     3/03/97 10:24a Joe_bostic $*/\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : GETCPU                                                       *\n *                                                                                             *\n *                    File Name : GETCPU.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 6/26/96                                                      *\n *                                                                                             *\n *                  Last Update : June 26th 1996 [ST]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *   Example of interface to assembly language code to find CPU type                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n *   Get_CPU_Type -- interface to ASM detection code                                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n//#define WIN32\n//#include <windows.h>\n#include <stdio.h>\n#include\t<string.h>\n\n\n#define\tbool\tint\n\n/*\n** Prototypes for linkage to assembly module\n*/\n\nextern \"C\" {\n\tbool __cdecl Detect_MMX_Availability(void);\n\tvoid __cdecl Init_MMX(void);\n\n\textern char CPUType;\n\textern char VendorID;\n}\n\n\n/***********************************************************************************************\n * Get_CPU_Type -- Find out what kind of CPU we are running on                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    int   - reference to cpu type                                                     *\n *           bool  - reference to mmx availability flag                                        *\n *           char* - ptr to buffer to receive chip vendor info                                 *\n *           int   - length of above buffer                                                    *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/26/96 10:15AM ST : Created                                                             *\n *=============================================================================================*/\nvoid Get_CPU_Type(int & cpu_type, bool & mmx, char * vendor_id, int vendor_id_length)\n{\n\t/*\n\t** Call the asm CPU detection code\n\t*/\n\tmmx = Detect_MMX_Availability();\n\n\t/*\n\t** Return the promised results\n\t*/\n\tcpu_type = (int)CPUType;\n\tchar * vendor_ptr = &VendorID;\n\tstrncpy(vendor_id, vendor_ptr, vendor_id_length);\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "REDALERT/GLOBALS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/GLOBALS.CPP 2     3/10/97 6:22p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GLOBALS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nbool IsVQ640 = false;\nunsigned long GameVersion = 0;\nbool Debug_MotionCapture = false;\nbool Debug_Rotate = false;\t\t\t\t// Rotation algorithm control.\nbool Debug_Quiet = false;\nbool Debug_Cheat = false;\nbool Debug_Remap = false;\nbool Debug_Icon = false;\nbool Debug_Flag = false;\nbool Debug_Lose = false;\nbool Debug_Win = false;\nbool Debug_Map = false;\t\t\t\t\t// true = map editor mode\nbool Debug_Passable = false;\t\t\t// true = show passable/impassable terrain\nbool Debug_Unshroud = false;\t\t\t// true = hide the shroud\nbool Debug_Threat = false;\nbool Debug_Find_Path = false;\nbool Debug_Check_Map = false;\t\t\t// true = validate the map each frame\nbool Debug_Playtest = false;\n\nbool Debug_Heap_Dump = false;\t\t\t// true = print the Heap Dump\nbool Debug_Smart_Print = false;\t\t// true = print everything that calls Smart_Printf\nbool Debug_Trap_Check_Heap = false;\t// true = check the Heap\nbool Debug_Modem_Dump = false;\t\t// true = print the Modem Stuff\nbool Debug_Print_Events = false;\t\t// true = print event & packet processing\nbool Debug_Force_Crash = false;\n\nTFixedIHeapClass<AircraftClass>\t\tAircraft;\nTFixedIHeapClass<AnimClass>\t\t\tAnims;\nTFixedIHeapClass<BuildingClass>\t\tBuildings;\nTFixedIHeapClass<BulletClass>\t\t\tBullets;\nTFixedIHeapClass<FactoryClass>\t\tFactories;\nTFixedIHeapClass<HouseClass>\t\t\tHouses;\nTFixedIHeapClass<InfantryClass>\t\tInfantry;\nTFixedIHeapClass<OverlayClass>\t\tOverlays;\nTFixedIHeapClass<SmudgeClass>\t\t\tSmudges;\nTFixedIHeapClass<TeamClass>\t\t\tTeams;\nTFixedIHeapClass<TeamTypeClass>\t\tTeamTypes;\nTFixedIHeapClass<TemplateClass>\t\tTemplates;\nTFixedIHeapClass<TerrainClass>\t\tTerrains;\nTFixedIHeapClass<TriggerClass>\t\tTriggers;\nTFixedIHeapClass<UnitClass>\t\t\tUnits;\nTFixedIHeapClass<VesselClass>\t\t\tVessels;\nTFixedIHeapClass<TriggerTypeClass>\tTriggerTypes;\n\nTFixedIHeapClass<HouseTypeClass>\t\tHouseTypes;\nTFixedIHeapClass<BuildingTypeClass>\tBuildingTypes;\nTFixedIHeapClass<AircraftTypeClass>\tAircraftTypes;\nTFixedIHeapClass<InfantryTypeClass>\tInfantryTypes;\nTFixedIHeapClass<BulletTypeClass>\tBulletTypes;\nTFixedIHeapClass<AnimTypeClass>\t\tAnimTypes;\nTFixedIHeapClass<UnitTypeClass>\t\tUnitTypes;\nTFixedIHeapClass<VesselTypeClass>\tVesselTypes;\nTFixedIHeapClass<TemplateTypeClass>\tTemplateTypes;\nTFixedIHeapClass<TerrainTypeClass>\tTerrainTypes;\nTFixedIHeapClass<OverlayTypeClass>\tOverlayTypes;\nTFixedIHeapClass<SmudgeTypeClass>\tSmudgeTypes;\n\n\n/*\n**\tThese are the instantiate static heap pointers for the various\n**\tCCPtr class objects that are allowed to exist. If the linker generates\n**\tan error about a missing heap pointer, then this indicates that CCPtr objects\n**\tfor that type are not allowed. For every case of a TFixedIHeap manager of\n**\tgame objects, then a CCPtr can be instantiated for it.\n*/\n#if (0)\t//Moved to runtime initialization. ST - 5/20/2019\ntemplate<> FixedIHeapClass * CCPtr<AircraftClass>::Heap = &Aircraft;\ntemplate<> FixedIHeapClass * CCPtr<AnimClass>::Heap = &Anims;\ntemplate<> FixedIHeapClass * CCPtr<BuildingClass>::Heap = &Buildings;\ntemplate<> FixedIHeapClass * CCPtr<BulletClass>::Heap = &Bullets;\ntemplate<> FixedIHeapClass * CCPtr<FactoryClass>::Heap = &Factories;\ntemplate<> FixedIHeapClass * CCPtr<HouseClass>::Heap = &Houses;\ntemplate<> FixedIHeapClass * CCPtr<InfantryClass>::Heap = &Infantry;\ntemplate<> FixedIHeapClass * CCPtr<OverlayClass>::Heap = &Overlays;\ntemplate<> FixedIHeapClass * CCPtr<SmudgeClass>::Heap = &Smudges;\ntemplate<> FixedIHeapClass * CCPtr<TeamClass>::Heap = &Teams;\ntemplate<> FixedIHeapClass * CCPtr<TeamTypeClass>::Heap = &TeamTypes;\ntemplate<> FixedIHeapClass * CCPtr<TemplateClass>::Heap = &Templates;\ntemplate<> FixedIHeapClass * CCPtr<TerrainClass>::Heap = &Terrains;\ntemplate<> FixedIHeapClass * CCPtr<TriggerClass>::Heap = &Triggers;\ntemplate<> FixedIHeapClass * CCPtr<TriggerTypeClass>::Heap = &TriggerTypes;\n\ntemplate<> FixedIHeapClass * CCPtr<HouseTypeClass>::Heap = &HouseTypes;\ntemplate<> FixedIHeapClass * CCPtr<BuildingTypeClass>::Heap = &BuildingTypes;\ntemplate<> FixedIHeapClass * CCPtr<AircraftTypeClass>::Heap = &AircraftTypes;\ntemplate<> FixedIHeapClass * CCPtr<InfantryTypeClass>::Heap = &InfantryTypes;\ntemplate<> FixedIHeapClass * CCPtr<BulletTypeClass>::Heap = &BulletTypes;\ntemplate<> FixedIHeapClass * CCPtr<AnimTypeClass>::Heap = &AnimTypes;\ntemplate<> FixedIHeapClass * CCPtr<UnitTypeClass>::Heap = &UnitTypes;\ntemplate<> FixedIHeapClass * CCPtr<VesselTypeClass>::Heap = &VesselTypes;\ntemplate<> FixedIHeapClass * CCPtr<TemplateTypeClass>::Heap = &TemplateTypes;\ntemplate<> FixedIHeapClass * CCPtr<TerrainTypeClass>::Heap = &TerrainTypes;\ntemplate<> FixedIHeapClass * CCPtr<OverlayTypeClass>::Heap = &OverlayTypes;\ntemplate<> FixedIHeapClass * CCPtr<SmudgeTypeClass>::Heap = &SmudgeTypes;\n#endif\n\n/* These variables are used to keep track of the slowest speed of a team */\nTeamFormDataStruct TeamFormData[HOUSE_COUNT];\nbool FormMove;\nSpeedType FormSpeed;\nMPHType FormMaxSpeed;\n\n\nchar _staging_buffer[32000];\n\n/*\n** Global flag for the life of Tanya.  If this flag is set, she is\n** no longer available.\n*/\nbool IsTanyaDead;\nbool SaveTanya;\n\n#ifdef FIXIT_ANTS\nbool AntsEnabled = false;\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool NewUnitsEnabled = false;\nbool SecretUnitsEnabled = false;\nint MTankDistance = 15;\nbool OverrideNewUnitsEnabled = false;\t // ST - 12/13/2019 12:21PM\t\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\nint CarrierLaunchDelay = 60;\n#endif\n#endif\n\nint NewINIFormat = 0;\n\nbool TimeQuake;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool PendingTimeQuake;\nTARGET TimeQuakeCenter;\nfixed QuakeUnitDamage=0x300;\nfixed QuakeBuildingDamage=0x300;\nint QuakeInfantryDamage=25;\nint QuakeDelay;\nfixed ChronoTankDuration=0x300;\t// chrono override for chrono tanks\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\nfixed EngineerDamage=0x55;\t\t\t// Amount of damage an engineer does\nfixed EngineerCaptureLevel=0x40;\t// Building damage level before engineer can capture\n#endif\n#endif\n\n#ifdef WIN32\nunsigned short\t\t\tHard_Error_Occured = 0;\nWWMouseClass *\t\t\tWWMouse = NULL;\nGraphicBufferClass\tSysMemPage(DEFAULT_SCREEN_WIDTH, 200, (void*)NULL);\nWinTimerClass *\t\tWindowsTimer=NULL;\nint\t\t\t\t\t\tScreenWidth=3072;\nint\t\t\t\t\t\tScreenHeight=3072;\nGraphicBufferClass\tModeXBuff;\nbool\t\t\t\t\t\tInMovie = FALSE;\t//Are we currently playing a VQ movie?\nHANDLE\t\t\t\t\thInstance;\nint\t\t\t\t\t\tAllDone;\n\n\n/***************************************************************************\n**\tThis is true if the game is the currently in focus windows app\n**\n*/\nbool GameInFocus = false;\n\n#endif\n\n\n/***************************************************************************\n**\tEncryption keys.\n*/\nPKey FastKey;\n#ifdef CHEAT_KEYS\nPKey SlowKey;\n#endif\n\n#ifdef FIXIT_NAME_OVERRIDE\n/***************************************************************************\n**\tThis is where the name overrides for the units will reside.\n*/\nchar const * NameOverride[25];\nint NameIDOverride[25];\n#endif\n\n/***************************************************************************\n**\tThese are the mission control structures. They hold the information about\n**\thow the missions should behave in the system.\n*/\nMissionControlClass MissionControl[MISSION_COUNT];\n\n\n/***************************************************************************\n**\tThere are various tutorial messages that can appear in the game. These\n**\tare called upon by number and pointed to by this array.\n*/\nchar const * TutorialText[225];\n\n\n/***************************************************************************\n**\tThis holds the rules database. The rules database won't change during the\n**\tprogram's run, but may need to be referenced intermitently.\n*/\nCCINIClass RuleINI;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nCCINIClass AftermathINI;\n#endif\n\n/***************************************************************************\n**\tThis points to the benchmark objects that are allocated only if the\n**\tmachine is running on a Pentium and this is a debug version.\n*/\n//Benchmark * Benches;\n\n\n/***************************************************************************\n**\tGeneral rules that control the game.\n*/\nRulesClass Rule;\n\n\n/***************************************************************************\n** All keyboard input is routed through the object pointed to by this\n**\tkeyboard class pointer.\n*/\nKeyboardClass * Keyboard;\n\n\n/***************************************************************************\n**\tRemap control array. This is used to hold the remap\n**\ttables for the various possible player colors, and the color schemes\n** for dialogs.\n*/\nRemapControlType ColorRemaps[PCOLOR_COUNT];\n\n/*\n** Special remap scheme for font that hs to print over metallic tabs\n*/\nRemapControlType MetalScheme;\n\n/*\n** This remap table is for special purposes.  It consists of dark grey shades,\n** and is used for dimming things out.\n*/\nRemapControlType GreyScheme;\n\n\n/***************************************************************************\n**\tThis is the source of the random numbers used in the game. This controls\n**\tthe game logic and thus must be in sync with any networked machines.\n*/\nRandomClass NonCriticalRandomNumber;\nRandomStraw CryptRandom;\n\n\n/***************************************************************************\n**\tThis tracks all selected objects per house (for this map).\n*/\nSelectedObjectsType CurrentObject;\n\n\n/***************************************************************************\n**\tThis is the game version.\n*/\n//PG VersionClass VerNum;\n\n\n/***************************************************************************\n**\tThis is the VQ animation controller structure. It is filled in by reading\n**\tthe PLAYER.INI and overridden through program control.\n*/\n//VQAConfig AnimControl;\n\nint PreserveVQAScreen;\t\t\t// Used for screen mode transition control.\nbool BreakoutAllowed = true;\t// \"true\" if aborting of movies is allowed.\nbool Brokeout;\t\t\t\t\t\t// Was the movie broken out of?\nbool SlowPalette = false;\t\t// Slow palette flag set?\n\n\n/***************************************************************************\n**\tThese are the movie names to use for mission briefing, winning, and losing\n**\tsequences. They are read from the INI file.\n*/\nScenarioClass Scen;\n\n\n/***************************************************************************\n**\tThis is the pending speech sample to play. This sample will be played\n**\tat the first opportunity.\n*/\nVoxType SpeakQueue = VOX_NONE;\n\n\n/***************************************************************************\n**\tThis records if the score (music) file is present. If not, then much of\n**\tthe streaming score system can be disabled.\n*/\nbool ScoresPresent;\n\n\n/***************************************************************************\n**\tThis flag will control whether there is a response from game units.\n**\tBy carefully controlling this global, multiple responses are suppressed\n**\twhen a large group of infantry is given the movement order.\n*/\nbool AllowVoice = true;\n\n\n/***************************************************************************\n**\tThis is the current frame number. This number is guaranteed to count\n**\tupward at the rate of one per game logic process. The target rate is 15\n**\tper second. This value is saved and restored with the saved game.\n*/\nlong Frame = 0;\n\n\n/***************************************************************************\n**\tThese globals are constantly monitored to determine if the player\n**\thas won or lost. They get set according to the trigger events associated\n**\twith the scenario.\n*/\nbool PlayerWins;\nbool PlayerLoses;\nbool PlayerRestarts;\n\n/*\n** This flag is set if the player neither wins nor loses; it's mostly for\n** multiplayer mode.\n*/\nbool PlayerAborts;\n\n\n/***************************************************************************\n**\tThis is the pointer for the speech staging buffer. This buffer is used\n**\tto hold the currently speaking voice data. Since only one speech sample\n**\tis played at a time, this buffer is only as big as the largest speech\n**\tsample that can be played.\n*/\nvoid * SpeechBuffer[2];\nVoxType SpeechRecord[2];\n\n\n/***************************************************************************\n**\tThe theater specific mixfiles are cached into the buffer pointed to by\n**\tthis global.\n*/\nBuffer * TheaterBuffer;\n\n\n/***************************************************************************\n**\tThis is a running accumulation of the number of ticks that were unused.\n** This accumulates into a useful value that contributes to a\n**\thistogram of game performance.\n*/\nlong SpareTicks;\nlong PathCount;\t\t\t// Number of findpaths called.\nlong CellCount;\t\t\t// Number of cells redrawn.\nlong TargetScan;\t\t\t// Number of target scans.\nlong SidebarRedraws;\t\t// Number of sidebar redraws.\n\n\n/***************************************************************************\n**\tThis is the monochrome debug page array. The various monochrome data\n**\tscreens are located here.\n*/\nMonoClass MonoArray[DMONO_COUNT];\nDMonoType MonoPage = DMONO_STRESS;\t// The current page.\n\n\n/***************************************************************************\n**\tThis holds the theater specific mixfiles.\n*/\nMFCD * TheaterData = 0;\nMFCD * MoviesMix = 0;\nMFCD * GeneralMix = 0;\nMFCD * ScoreMix = 0;\nMFCD * MainMix = 0;\nMFCD * ConquerMix = 0;\n\n\n/***************************************************************************\n**\tThis is the options control class. The options control such things as\n**\tgame speed, visual controls, and other user settings.\n*/\nGameOptionsClass Options;\n\n\n/***************************************************************************\n**\tLogic processing is controlled by this element. It handles both graphic\n**\tand AI logic.\n*/\nLogicClass Logic;\n\n\n/***************************************************************************\n**\tThis handles the background music.\n*/\nThemeClass Theme;\n\n\n/***************************************************************************\n**\tThis is the main control class for the map.\n*/\n#ifdef SCENARIO_EDITOR\nMapEditClass Map;\n#else\nMouseClass Map;\n#endif\n\n\n/**************************************************************************\n**\tThe running game score is handled by this class (and member functions).\n*/\nScoreClass Score;\n\n\n/***************************************************************************\n**\tThe running credit display is controlled by this class (and member\n**\tfunctions.\n*/\nCreditClass CreditDisplay;\n\n\n/**************************************************************************\n** This class records the special command override options that C&C\n**\tsupports.\n*/\nSpecialClass Special;\n\n\nbool PassedProximity;\t// used in display.cpp\n\n\n/***************************************************************************\n**\tThis is the scenario data for the currently loaded scenario.\n** These variables should all be set together.\n*/\nHousesType Whom;\t\t\t\t\t\t\t// Initial command line house choice.\nint ScenarioInit;\nbool SpecialFlag = false;\n\n\n/***************************************************************************\n** This value tells the sidebar what items it's allowed to add.  The\n** lower the value, the simpler the sidebar will be. This value is the\n**\tdisplayed value for tech level in the multiplay dialogs. It remaps to\n**\tthe in-game rules.ini tech levels.\n*/\nint BuildLevel = 10;\t\t\t\t// Buildable level (1 = simplest)\n\n\n/***************************************************************************\n**\tThe various tutor and dialog messages are located in the data block\n**\treferenced by this pointer.\n*/\nchar const * SystemStrings;\nchar const * DebugStrings;\n\n\n/***************************************************************************\n**\tThe game plays as long as this var is true.\n*/\nbool GameActive;\n\n\n/***************************************************************************\n**\tThis is a scratch variable that is used to when a reference is needed to\n**\ta long, but the value wasn't supplied to a function. This is used\n**\tspecifically for the default reference value. As such, it is not stable.\n*/\nlong LParam;\n\n\n#ifdef SCENARIO_EDITOR\n/***************************************************************************\n** The currently-selected cell for the Scenario Editor\n*/\nCELL CurrentCell = 0;\n#endif\n\n\n/***************************************************************************\n**\tMost of the text in the game will use the six point font. These are the\n**\tpointers to the fonts. If it is NULL, then the font hasn't been loaded\n**\tyet.\n*/\nvoid const * Metal12FontPtr;\t//Font for use on in-game tabs in hires\nvoid const * MapFontPtr;\t\t// Standard very small font.\nvoid const * TypeFontPtr;\t\t// Teletype font for mission briefings.\nvoid const * Font3Ptr;\t\t\t// Standard very small font.\nvoid const * Font6Ptr;\t\t\t// Standard small font.\nvoid const * EditorFont;\t\t// Font used for scenario editor.\nvoid const * Font8Ptr;\t\t\t// 8 point proportional.\nvoid const * FontLEDPtr;\t\t// LED fixed point font.\nvoid const * VCRFontPtr;\t\t// VCR font pointer.\nvoid const * ScoreFontPtr;\t\t// font for score & map selection screens\nvoid const * GradFont6Ptr;\t\t// gradient 6 point font pointer.\n\n\n/***************************************************************************\n**\tThis is the house that the human player is currently playing.\n*/\nHouseClass * PlayerPtr;\n\n\n/***************************************************************************\n**\tSpecial palettes for MCGA mode goes here. These palette buffers are used\n**\tfor pictures that do not use the game palette or are used for fading to\n**\tblack.\n*/\nPaletteClass CCPalette;\nPaletteClass GamePalette;\n//PaletteClass InGamePalette;\nPaletteClass BlackPalette(RGBClass(0, 0, 0));\nPaletteClass WhitePalette(RGBClass(RGBClass::MAX_VALUE, RGBClass::MAX_VALUE, RGBClass::MAX_VALUE));\nPaletteClass OriginalPalette;\nPaletteClass ScorePalette;\n\n\n/***************************************************************************\n**\tThese are the event queues. One is for holding events until they are ready to be\n**\tsent to the remote computer for processing. The other list is for incoming events\n**\tthat need to be executed when the correct frame has been reached.\n*/\nQueueClass<EventClass, MAX_EVENTS> OutList;\nQueueClass<EventClass, (MAX_EVENTS * 64)> DoList;\n\n#ifdef MIRROR_QUEUE\nQueueClass<EventClass, (MAX_EVENTS * 64)> MirrorList;\n#endif\n\n\n/***************************************************************************\n**\tThese are arrays/lists of trigger pointers for each cell & the houses.\n*/\nDynamicVectorClass<TriggerClass *> HouseTriggers[HOUSE_COUNT];\nDynamicVectorClass<TriggerClass *> MapTriggers;\nint MapTriggerID;\nDynamicVectorClass<TriggerClass *> LogicTriggers;\nint LogicTriggerID;\n\n\n/***************************************************************************\n**\tThis is the list of BuildingTypes that define the AI's base.\n*/\nBaseClass Base;\n\n\n/***************************************************************************\n**\tThis is the list of carry over objects. These objects are part of the\n**\tpseudo saved game that might be carried along with the current saved\n**\tgame.\n*/\nCarryoverClass * Carryover;\n\n\n/***************************************************************************\n** This value is computed every time a new scenario is loaded; it's a\n** CRC of the INI and binary map files.\n*/\nunsigned long ScenarioCRC;\n\n\n/***************************************************************************\n** This class manages data specific to multiplayer games.\n*/\nSessionClass Session;\n#if(TIMING_FIX)\n//\n// These values store the min & max frame #'s for when MaxAhead >>increases<<.\n// If MaxAhead increases, and the other systems free-run to the new MaxAhead\n// value, they may miss an event generated after the MaxAhead event was sent,\n// but before it executed, since it will have been scheduled with the older,\n// shorter MaxAhead value.  This will cause a Packet_Received_Too_Late error.\n// The frames from the point where the new MaxAhead takes effect, up to that\n// frame Plus the new MaxAhead, represent a \"period of vulnerability\"; any\n// events received that are scheduled to execute during this period should\n// be re-scheduled for after that period.\n//\nint NewMaxAheadFrame1;\nint NewMaxAheadFrame2;\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool\tbAftermathMultiplayer;\t\t//\tIs multiplayer game being played with Aftermath rules?\n#else\nunsigned long \tPlayingAgainstVersion;\t\t// Negotiated version number\nbool\t\t\t\tVersion107InMix;\t\t\t\t// Is there a v1.07 in the game\n#endif\n\n/***************************************************************************\n**\tThis is the null modem manager class.  Declaring this class doesn't\n** perform any allocations;\n*/\n#if (0)\nNullModemClass NullModem (\n   16,\t\t\t\t\t\t\t\t\t\t\t// number of send entries\n\t16,\t\t\t\t\t\t\t\t\t\t\t// number of receive entries\n\t(MAX_SERIAL_PACKET_SIZE / sizeof(EventClass) ) * sizeof(EventClass) + sizeof( CommHeaderType ),\n\t0x1234);\t\t\t\t\t\t\t\t\t\t// Magic number must have each digit unique\n\t\t\t\t\t\t\t\t\t\t\t\t\t// and different from the queue magic number\n#endif\n\n\n/***************************************************************************\n**\tThis is the network IPX manager class.  It handles multiple remote\n** connections.  Declaring this class doesn't perform any allocations;\n** the class itself is 140 bytes.\n*/\n//IPXManagerClass Ipx (\n//\tMAX (sizeof (GlobalPacketType), sizeof(RemoteFileTransferType)),\t\t// size of Global Channel packets\n//\t((546 - sizeof(CommHeaderType)) / sizeof(EventClass) ) * sizeof(EventClass),\n//\t10, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Global Queue\n//\t8, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Private Queues\n//\tVIRGIN_SOCKET, \t\t\t\t\t\t\t\t\t// Socket ID #\n//\tIPXGlobalConnClass::COMMAND_AND_CONQUER0);// Product ID #\n\nIPXManagerClass Ipx (\n\tMAX (sizeof (GlobalPacketType), sizeof(RemoteFileTransferType)),\t\t// size of Global Channel packets\n\t((546 - sizeof(CommHeaderType)) / sizeof(EventClass) ) * sizeof(EventClass),\n\t160, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Global Queue\n\t32, \t\t\t\t\t\t\t\t\t\t\t\t\t// # entries in Private Queues\n\tVIRGIN_SOCKET, \t\t\t\t\t\t\t\t\t// Socket ID #\n\tIPXGlobalConnClass::COMMAND_AND_CONQUER0);// Product ID #\n\n\n#if(TEN)\n/***************************************************************************\n** This is the connection manager for Ten.  Special Ten notes:\n** - TEN connection ID's are equal to the HousesType for that player.\n** - The TEN internal player ID is used to determine the player's color.\n** - Ten's broadcast destination address -1\n*/\nTenConnManClass *Ten = NULL;\n\n#endif\n\n\n#if(MPATH)\n/***************************************************************************\n** This is the connection manager for Ten.  Special Ten notes:\n** - MPATH connection ID's are equal to the HousesType for that player.\n** - The player's color is read from the OPTIONS.INI file\n** - MPath's broadcast destination address is 0\n*/\nMPlayerManClass *MPath = NULL;\n\n#endif\n\n\n/***************************************************************************\n**\tThis is the random-number seed; it's synchronized between systems for\n** multiplayer games.\n*/\nint Seed = 0;\n\n\n/***************************************************************************\n** If this value is non-zero, use it as the random # seed instead; this should\n** help reproduce some bugs.\n*/\nint CustomSeed = 0;\n\nint WindowList[][9] = {\n/* xbyte, ypixel, bytewid, pixelht, cursor color, bkgd color,\tcursor x, cursor y */\n\n\t/* do not change the first 2 entries!! they are necc. to the system */\n\n\t{0,0,40*8*RESFACTOR,200*RESFACTOR,WHITE,BLACK,0,0},\t/* screen window */\n\t{1*8,75,38*8,100,WHITE,BLACK,0,0},\t/* DOS Error window */\n\n\t// Tactical map.\n\t{0, 0, 40*8*RESFACTOR, 200*RESFACTOR, WHITE,LTGREY,0,0},\n\n\t// Initial menu window.\n\t{12*8, 199-42, 16*8, 42, LTGREY, DKGREY, 0, 0},\n\n\t// Sidebar clipping window.\n\t{0,0,0,0,0,0,0,0},\n\n\t// Scenario editor window.\n\t{5*8, 30, 30*8, 140, 0, 0, 0, 0},\n\n\t// Partial object draw sub-window.\n\t{0,0,0,0,WHITE,BLACK,0,0},\n\n\t// Custom window.\n\t{0, 0, 0, 0, 0, 0, 0, 0},\n\n\t// Virtual window for external rendering. ST - 1/15/2019 3:02PM\n\t{0, 0, 0, 0, 0, 0, 0, 0}\n\n};\n\n\n/* X,Y,Item Width,Items High,Selected,Norm Color,Sel Color,zero \t*/\nint MenuList[][8]={\n\t\t{1, 3, 12, 3, 0, WHITE, PINK, 0},\n};\n\n\n#ifdef WIN32\nGraphicBufferClass\tVisiblePage;\nGraphicBufferClass\tHiddenPage;\nGraphicViewPortClass\tSeenBuff(&VisiblePage, 0, 0, 3072, 3072);\nGraphicViewPortClass\tHidPage(&HiddenPage, 0, 0, 3072, 3072);\n#else\nGraphicBufferClass\tHidPage(DEFAULT_SCREEN_WIDTH, 201, (void*)NULL);\nGraphicBufferClass\tSeenBuff(320, 200, (void *)0xA0000L);\nVideoBufferClass\t\tSeenPage;\nGraphicBufferClass & VisiblePage = SeenBuff;\n#endif\n\n\n#ifdef WIN32\n#else\n#endif\n\nint \t\t\t\t\t\tSoundOn;\nCDTimerClass<SystemTimerClass> FrameTimer;\nCDTimerClass<SystemTimerClass> CountDownTimer;\n\nNewConfigType NewConfig;\nTheaterType LastTheater = THEATER_NONE;\t//Lets us know when theater type changes.\n\n\n/***************************************************************************\n**\tThis flag is for popping up dialogs that call the main loop.\n*/\nSpecialDialogType SpecialDialog = SDLG_NONE;\n\n\nint RequiredCD = -1;\nint CurrentCD = -1;\nint MouseInstalled;\n\n//\n// Variables for helping track how much time goes bye in routines\n//\nint LogLevel = 0;\nunsigned long LogLevelTime[ MAX_LOG_LEVEL ] = { 0 };\nunsigned long LogLastTime = 0;\nbool LogDump_Print = false;\t\t// true = print the Log time Stuff\n\n\n/***************************************************************************\n** Tick Count global timer object.\n*/\nTTimerClass<SystemTimerClass> TickCount = 0;\n\n\n/***************************************************************************\n**  Win32 specific globals\n*/\n#ifdef WIN32\n\nbool InDebugger = false;\nint ReadyToQuit = 0;\n\n#else\nbool IsTheaterShape = false;\t// must be defined only if not Win32\n#endif\t//WIN32\n\n//PG GetCDClass\t\tCDList;\nint UnitBuildPenalty = 100;\n\n#ifdef MPEGMOVIE // Denzil 6/15/98\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\nMCIMovie* MciMovie = NULL;\n#endif\n\n#include \"mpgset.h\"\nMPGSettings* MpgSettings = NULL;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\nbool bAutoSonarPulse = false;\n#endif\n\nbool MMXAvailable = false;\n\n\n// ST - 5/14/2019\nbool RunningAsDLL = false;\nbool RunningFromEditor = false;\n"
  },
  {
    "path": "REDALERT/GOPTIONS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/GOPTIONS.CPP 6     3/15/97 7:18p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 27, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#include \"goptions.h\"\n#include \"loaddlg.h\"\n#include \"sounddlg.h\"\n#include \"visudlg.h\"\n#include \"gamedlg.h\"\n#include \"textbtn.h\"\n#include \"descdlg.h\"\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\nbool RedrawOptionsMenu;\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:      none                                                                         *\n *                                                                                             *\n * HISTORY:     12/31/1994 MML : Created.                                                      *\n *   06/23/1995 JLB : Handles restating the mission objective.                                 *\n *   07/27/1995 JLB : Adjusts menu for multiplay mode.                                         *\n *=============================================================================================*/\nvoid GameOptionsClass::Process(void)\n{\n\tstatic struct {\n\t\tint ID;\t\t\t\t// Button ID to use.\n\t\tint Text;\t\t\t// Text number to use for this button.\n\t\tbool Multiplay;\t// Allowed in multiplayer version?\n\t} _constants[] = {\n\t\t{BUTTON_LOAD,  \tTXT_LOAD_MISSION,    false},\n#ifdef FIXIT_MULTI_SAVE\n\t\t{BUTTON_SAVE,  \tTXT_SAVE_MISSION,    true},\n#else\n\t\t{BUTTON_SAVE,  \tTXT_SAVE_MISSION,    false},\n#endif\n\t\t{BUTTON_DELETE,\tTXT_DELETE_MISSION,  true},\n\t\t{BUTTON_GAME,  \tTXT_GAME_CONTROLS,   true},\n\t\t{BUTTON_QUIT,  \tTXT_QUIT_MISSION,    true},\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t{BUTTON_DRAW,  \tTXT_OK,    true},\n#endif\n\t\t{BUTTON_RESUME,\tTXT_RESUME_MISSION,  true},\n\t\t{BUTTON_RESTATE,\tTXT_RESTATE_MISSION, false},\n\t};\n\n\t/*\n\t**\tVariables.\n\t*/\n\tTextButtonClass * buttons = 0;\n\tint selection;\n\tbool pressed;\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tint curbutton = 7;\n#else\n\tint curbutton = 6;\n#endif\n\tint y;\n\tTextButtonClass * buttonsel[ARRAY_SIZE(_constants)];\n\tstatic int num_buttons = sizeof(_constants)/sizeof(_constants[0]);\n\n\n\tint num_players = 0;\n\tint i;\n\n\t//\n\t// Compute the number of real players in the game; only allow saves\n\t// if there are more than 1.\n\t//\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!(HouseClass::As_Pointer(Session.Players[i]->Player.ID)->IsDefeated)) {\n\t\t\tnum_players++;\n\t\t}\n\t}\n\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tBuild the button list for all of the buttons for this dialog.\n\t*/\n\tint maxwidth = 0;\n\n\tfor (int index = 0; index < num_buttons ; index++ ) {\n\t\tint text = _constants[index].Text;\n\t\tbuttonsel[index] = NULL;\n\n\t\tif (Session.Type != GAME_NORMAL && !_constants[index].Multiplay) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( (Session.Type == GAME_SKIRMISH ||\n\t\t\t\t\tSession.Type == GAME_INTERNET) && text == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\n\t\tif (Session.Type != GAME_NORMAL && ( num_players < 2 ) &&\n\t\t\t\t\ttext == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n#else\n#ifdef FIXIT_MULTI_SAVE\n\t\tif (Session.Type != GAME_NORMAL && (num_players < 2 || PlayingAgainstVersion == VERSION_RED_ALERT_104) &&\n\t\t\t\t\ttext == TXT_SAVE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n#endif\t//FIXIT_MULTI_SAVE\n#endif\n\n\t\tif (Session.Type == GAME_SKIRMISH && text == TXT_DELETE_MISSION) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Session.Type != GAME_NORMAL && text == TXT_DELETE_MISSION) {\n\t\t\ttext = TXT_RESIGN;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tif (index < 6) {\n#else\n\t\tif (index < 5) {\n#endif\n\t\t\ty = (SeenBuff.Get_Height() - OptionHeight)/2 + ButtonY + ((OButtonHeight+2) * index);\n\t\t} else {\n\t\t\ty = OptionY + ButtonResumeY;\n\t\t}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tTextButtonClass* g;\n\t\tif( _constants[index].ID == BUTTON_DRAW )\n\t\t{\n\t\t\tif( Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH && Session.Players.Count() == 2 )\n\t\t\t{\n\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t{\n\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_RETRACT_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t\telse\n\t\t\t\t\t\tcontinue;\t\t//\tGame will end now anyway.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_PROPOSE_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t\telse\n\t\t\t\t\t\tg = new TextButtonClass( BUTTON_DRAW, TXT_WOL_ACCEPT_DRAW, TPF_BUTTON, 0, y );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t\tg = new TextButtonClass(_constants[index].ID, text, TPF_BUTTON, 0, y);\n#else\n\t\tTextButtonClass * g = new TextButtonClass(_constants[index].ID, text, TPF_BUTTON, 0, y);\n#endif\n\n\t\tif (g->Width > maxwidth) {\n\t\t\tmaxwidth = g->Width;\n\t\t}\n\t\tif (buttons == NULL) {\n\t\t\tbuttons = g;\n\t\t} else {\n\t\t\tg->Add_Tail(*buttons);\n\t\t}\n\n\t\tbuttonsel[index] = g;\n\t}\n\n\t/*\n\t** BG: In skirmish mode, there is no 'restate' button, so we have to\n\t**     backtrack through the list to find the last valid button.\n\t*/\n\twhile(!buttonsel[curbutton-1]) curbutton--;\n\n\tbuttonsel[curbutton-1]->Turn_On();\n\n\t/*\n\t**\tForce all button lengths to match the maximum length of the widest button.\n\t*/\n\tGadgetClass * g = buttons;\n\twhile (g != NULL) {\n\t\tg->Width = max(maxwidth, 90 * RESFACTOR);\n\t\tg->X = OptionX+(OptionWidth-g->Width)/2;\n\t\tg = g->Get_Next();\n\t}\n//#ifdef FRENCH\n//\tbuttonsel[BUTTON_RESUME-1]->Width = 110 * RESFACTOR;\n//\tbuttonsel[BUTTON_RESUME-1]->X = OptionX + (17 * RESFACTOR) - 5;\n//#else\n\tbuttonsel[BUTTON_RESUME-1]->Width = 90 * RESFACTOR;\n\tbuttonsel[BUTTON_RESUME-1]->X = OptionX + (17 * RESFACTOR);\n//#endif\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tbuttonsel[BUTTON_RESTATE-1]->Width = 90 * RESFACTOR;\n\t\tbuttonsel[BUTTON_RESTATE-1]->X = OptionX+OptionWidth-(buttonsel[BUTTON_RESTATE-1]->Width+(17 * RESFACTOR));\n\t}\n\n\t/*\n\t**\tThis causes left mouse button clicking within the confines of the dialog to\n\t**\tbe ignored if it wasn't recognized by any other button or slider.\n\t*/\n\t(new GadgetClass(OptionX, OptionY, OptionWidth, OptionHeight, GadgetClass::LEFTPRESS))->Add_Tail(*buttons);\n\n\t/*\n\t**\tThis cause a right click anywhere or a left click outside the dialog region\n\t**\tto be equivalent to clicking on the return to game button.\n\t*/\n\t(new ControlClass(BUTTON_RESUME, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(), GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS))->Add_Tail(*buttons);\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_TEXT);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\tpressed = false;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display || RedrawOptionsMenu) {\n\n\t\t\t/*\n\t\t\t**\tRedraw the map.\n\t\t\t*/\n\t\t\tHidPage.Clear();\n\t\t\tMap.Flag_To_Redraw(true);\n\t\t\tMap.Render();\n\n\t\t\t/*\n\t\t\t**\tReset up the window.  Window x-coords are in bytes not pixels.\n\t\t\t*/\n\t\t\tSet_Window(WINDOW_EDITOR, OptionX, OptionY, OptionWidth, OptionHeight);\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(OptionX, OptionY, OptionWidth, OptionHeight);\n\n\t\t\t/*\n\t\t\t**\tDraw the arrows border if requested.\n\t\t\t*/\n \t\t\tDraw_Caption(TXT_OPTIONS, OptionX, OptionY, OptionWidth);\n\n\t\t\t/*\n\t\t\t**\tDisplay the version number at the bottom of the dialog box.\n\t\t\t*/\n#ifndef WIN32\n\t\t\tFancy_Text_Print(\"%s\\rV%s\",\n\t\t\t\t\t(OptionX+OptionWidth)-(17 * RESFACTOR),\n\t\t\t\t\tOptionY+OptionHeight-((Session.Type == GAME_NORMAL) ? (32 * RESFACTOR) : (24 * RESFACTOR)),\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\t\tScen.ScenarioName,\n\t\t\t\t\tVersion_Name());\n\n#else\n#if (0)//PG\n\t\t\tFancy_Text_Print(\"%s\\rV%s\",\n\t\t\t\t\t(OptionX+OptionWidth)-(25 * RESFACTOR),\n\t\t\t\t\tOptionY+OptionHeight-((Session.Type == GAME_NORMAL) ? (32 * RESFACTOR) : (24 * RESFACTOR)),\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\t\tScen.ScenarioName,\n\t\t\t\t\tVersion_Name());\n#endif\n#endif\n\n\t\t\tbuttons->Draw_All();\n\t\t\tTabClass::Hilite_Tab(0);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\tRedrawOptionsMenu = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = buttons->Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_RESTATE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_RESTATE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tselection = BUTTON_LOAD;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SAVE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DELETE;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_QUIT | KN_BUTTON):\n\t\t\t\tselection = BUTTON_QUIT;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_GAME | KN_BUTTON):\n\t\t\t\tselection = BUTTON_GAME;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tcase (BUTTON_DRAW | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DRAW;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_RESUME | KN_BUTTON):\n\t\t\t\tselection = BUTTON_RESUME;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tdo {\n\t\t\t\t\tcurbutton--;\n\t\t\t\t\tif (curbutton < 1) curbutton = num_buttons;\n\t\t\t\t} while (!buttonsel[curbutton-1]);\n\n\t\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tdo {\n\t\t\t\t\tcurbutton++;\n\t\t\t\t\tif ( curbutton > num_buttons ) curbutton = 1;\n\t\t\t\t} while (!buttonsel[curbutton-1]);\n\n\t\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tbuttonsel[curbutton-1]->IsPressed = true;\n\t\t\t\tbuttonsel[curbutton-1]->Draw_Me(true);\n\t\t\t\tselection = curbutton;\n\t\t\t\tpressed = true;\n\t\t\t\tKeyboard->Clear();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\n\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t\tcurbutton = selection;\n\t\t\tbuttonsel[curbutton-1]->Turn_On();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase BUTTON_RESTATE:\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (!Restate_Mission(Scen.ScenarioName, TXT_VIDEO, TXT_RESUME_MISSION/*KOTXT_OPTIONS*/)) {\n\t\t\t\t\t\tBreakoutAllowed = true;\n\t\t\t\t\t\tPlay_Movie(Scen.BriefMovie);\n\t\t\t\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tGamePalette.Set();\n\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tTheme.Queue_Song(THEME_PICK_ANOTHER);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tBlackPalette.Adjust(0x08, WhitePalette);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tBlackPalette.Adjust(0xFF);\n\t\t\t\t\t\tBlackPalette.Set();\n\t\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_LOAD):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SAVE):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\t\t\tLoadOptionsClass(LoadOptionsClass::SAVE).Process();\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SAVEGAME));\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_DELETE):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_SURRENDER)) {\n\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::DESTRUCT));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLoadOptionsClass(LoadOptionsClass::WWDELETE).Process();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_QUIT):\n\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CONFIRM_EXIT, TXT_ABORT, TXT_CANCEL, TXT_RESTART)) {\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tQueue_Exit();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tPlayerRestarts = true;\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Surrender_Dialog(TXT_CONFIRM_EXIT)) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tQueue_Exit();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//if (WWMessageBox().Process(TXT_CONFIRM_EXIT, TXT_YES, TXT_NO) == 0) {\n\t\t\t\t\t\t\t//process = false;\n\t\t\t\t\t\t\t//Queue_Exit();\n\t\t\t\t\t\t//} else {\n\t\t\t\t\t\t\t//display = true;\n\t\t\t\t\t\t//}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\tcase BUTTON_DRAW:\n\t\t\t\t\tif( Scen.bLocalProposesDraw )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tRetract draw offer.\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::RETRACT_DRAW));\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif( !Scen.bOtherProposesDraw )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tPropose a draw?\n\t\t\t\t\t\t\tif( Surrender_Dialog( TXT_WOL_PROPOSE_DRAW_CONFIRM ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tAccept a draw?\n\t\t\t\t\t\t\tif( Surrender_Dialog( TXT_WOL_ACCEPT_DRAW_CONFIRM ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PROPOSE_DRAW));\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_GAME):\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tGameControlsClass().Process();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_RESUME):\n\t\t\t\t\tSave_Settings();\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t\tbuttonsel[curbutton-1]->IsPressed = false;\n\t\t\tbuttonsel[curbutton-1]->Turn_Off();\n\t\t\tbuttonsel[curbutton-1]->Flag_To_Redraw();\n\t\t}\n\t}\n\n\t/*\n\t**\tClean up and re-enter the game.\n\t*/\n\tbuttons->Delete_List();\n\n\t/*\n\t**\tRedraw the map.\n\t*/\n\tKeyboard->Clear();\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n}\n\n\nvoid GameOptionsClass::Adjust_Variables_For_Resolution(void)\n{\n\tOptionWidth\t\t=\t(216+8) * RESFACTOR;\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tOptionHeight\t=\t111 * RESFACTOR;\n#else\n\tOptionHeight\t=\t100 * RESFACTOR;\n#endif\n\tOptionX\t\t\t=\t((SeenBuff.Get_Width() - OptionWidth) / 2);\n\tOptionY\t\t\t=\t((SeenBuff.Get_Height() - OptionHeight) / 2);\n\tButtonWidth\t\t=\t130 * RESFACTOR;\n\tOButtonHeight\t=\t9 * RESFACTOR;\n\tCaptionYPos\t\t=\t5 * RESFACTOR;\n\tButtonY\t\t\t=\t21 * RESFACTOR;\n\tBorder1Len\t\t=\t72 * RESFACTOR;\n\tBorder2Len\t\t=\t16 * RESFACTOR;\n\tButtonResumeY\t=\t(OptionHeight - (19 * RESFACTOR));\n}\n"
  },
  {
    "path": "REDALERT/GOPTIONS.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GOPTIONS.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GOPTIONS_H\n#define GOPTIONS_H\n\n#include \"options.h\"\n#include \"gadget.h\"\n\n\nclass GameOptionsClass : public OptionsClass {\n\t\tenum GameOptionsButtonEnum {\n\t\t\tBUTTON_LOAD=1,\n\t\t\tBUTTON_SAVE,\n\t\t\tBUTTON_DELETE,\n\t\t\tBUTTON_GAME,\n\t\t\tBUTTON_QUIT,\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tBUTTON_DRAW,\n#endif\n\t\t\tBUTTON_RESUME,\n\t\t\tBUTTON_RESTATE,\n\n\t\t\tBUTTON_COUNT\n\t\t};\n\n\t\tenum GameOptionsEnum {\n\t\t\tOPTION_WIDTH=(216+8),\n\t\t\tOPTION_HEIGHT=100,\n\t\t\tOPTION_X=((320 - (216+8)) / 2),\n\t\t\tOPTION_Y=((200 - 100) / 2),\n#ifdef FRENCH\n\t\t\tBUTTON_WIDTH=142,\n#else\n\t\t\tBUTTON_WIDTH=130,\n#endif\n\t\t\tNUMBER_OF_BUTTONS=6,\t\t//\tajw Not used.\n\t\t\tCAPTION_Y_POS=5,\n\t\t\tBUTTON_Y=21,\n\t\t\tBORDER1_LEN=72,\n\t\t\tBORDER2_LEN=16,\n\t\t\tBUTTON_RESUME_Y=(100-15)\n\t\t};\n\n\tpublic:\n\t\tGameOptionsClass(void): OptionsClass () { };\n\t\tvoid  Adjust_Variables_For_Resolution(void);\n\t\tvoid Process(void);\n\n\tprivate:\n\t\tint\tOptionWidth;\n\t\tint \tOptionHeight;\n\t\tint \tOptionX;\n\t\tint \tOptionY;\n\t\tint \tButtonWidth;\n\t\tint \tOButtonHeight;\n\t\tint \tCaptionYPos;\n\t\tint \tButtonY;\n\t\tint \tBorder1Len;\n\t\tint \tBorder2Len;\n\t\tint \tButtonResumeY;\n\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/GSCREEN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GSCREEN.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GSCREEN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   GScreenClass::Add_A_Button -- Add a gadget to the game input system.                      *\n *   GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage.        *\n *   GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn.                          *\n *   GScreenClass::GScreenClass -- Default constructor for GScreenClass.                       *\n *   GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines.   *\n *   GScreenClass::Init_Clear -- Sets the map to a known state.                                *\n *   GScreenClass::Init_IO -- Initializes the Button list ('Buttons').                         *\n *   GScreenClass::Init_Theater -- Performs theater-specific initializations.                  *\n *   GScreenClass::Input -- Fetches input and processes gadgets.                               *\n *   GScreenClass::One_Time -- Handles one time class setups.                                  *\n *   GScreenClass::Remove_A_Button -- Removes a gadget from the game input system.             *\n *   GScreenClass::Render -- General drawing dispatcher an display update function.            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\nGadgetClass * GScreenClass::Buttons = 0;\n\nGraphicBufferClass * GScreenClass::ShadowPage = 0;\n\n\n/***********************************************************************************************\n * GScreenClass::GScreenClass -- Default constructor for GScreenClass.                         *\n *                                                                                             *\n *    This constructor merely sets the display system, so that it will redraw the first time   *\n *    the render function is called.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nGScreenClass::GScreenClass(void)\n{\n\tIsToUpdate = true;\n\tIsToRedraw = true;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::One_Time -- Handles one time class setups.                                    *\n *                                                                                             *\n * This routine (and all those that overload it) must perform truly one-time initialization.   *\n * Such init's would normally be done in the constructor, but other aspects of the game may    *\n * not have been initialized at the time the constructors are called (such as the file system, *\n * the display, or other WWLIB subsystems), so many initializations should be deferred to the  *\n * One_Time init's.                                                                            *\n *                                                                                             *\n * Any variables set in this routine should be declared as static, so they won't be modified   *\n * by the load/save process.  Non-static variables will be over-written by a loaded game.      *\n *                                                                                             *\n * This function allocates the shadow buffer that is used for quick screen updates. If         *\n * there were any data files to load, they would be loaded at this time as well.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only ONCE at the beginning of the game.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::One_Time(void)\n{\n\t/*\n\t**\tAllocate the screen shadow page. This page is used to reduce access to the\n\t**\tactual screen memory. It contains a duplicate of what the SEENPAGE is.\n\t*/\n\tButtons = 0;\n\tShadowPage = new GraphicBufferClass(320, 200);\n\tif (ShadowPage) {\n\t\tShadowPage->Clear();\n\t\tHidPage.Clear();\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines.     *\n *                                                                                             *\n * This routine shouldn't be overloaded.  It's the main map initialization routine, and will   *\n * perform a complete map initialization, from mixfiles to clearing the buffers.  Calling this *\n * routine results in calling every initialization routine in the entire map hierarchy.        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      theater      theater to initialize to                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init(TheaterType theater)\n{\n\tInit_Clear();\n\tInit_IO();\n\tInit_Theater(theater);\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_Clear -- Sets the map to a known state.                                  *\n *                                                                                             *\n * This routine (and those that overload it) clears any buffers and variables to a known       *\n * state.  It assumes that all buffers are allocated & valid.  The map should be displayable   *\n * after calling this function, and should draw basically an empty display.                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_Clear(void)\n{\n\t/*\n\t** Clear the ShadowPage & HidPage to force a complete shadow blit.\n\t*/\n\tif (ShadowPage) {\n\t\tShadowPage->Clear();\n\t\tHidPage.Clear();\n\t}\n\n\tIsToRedraw = true;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_Theater -- Performs theater-specific initializations.                    *\n *                                                                                             *\n * This routine (and those that overload it) performs any theater-specific initializations     *\n * needed.  This will include setting the palette, setting up remap tables, etc.  This routine *\n * only needs to be called when the theater has changed.                                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_Theater(TheaterType )\n{\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Init_IO -- Initializes the Button list ('Buttons').                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/28/1994 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid GScreenClass::Init_IO(void)\n{\n\t/*\n\t** Reset the button list.  This means that any other elements of the map that need\n\t** buttons must attach them after this routine is called!\n\t*/\n\tButtons = 0;\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn.                            *\n *                                                                                             *\n *    This function is used to flag the display system whether any rendering is needed. The    *\n *    parameter tells the system either to redraw EVERYTHING, or just that something somewhere *\n *    has changed and the individual Draw_It functions must be called. When a sub system       *\n *    determines that it needs to render something local to itself, it would call this routine *\n *    with a false parameter. If the entire screen gets trashed or needs to be rebuilt, then   *\n *    this routine will be called with a true parameter.                                       *\n *                                                                                             *\n * INPUT:   complete -- bool; Should the ENTIRE screen be redrawn?                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This doesn't actually draw the screen, it merely sets flags so that when the    *\n *             Render() function is called, the appropriate drawing steps will be performed.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Flag_To_Redraw(bool complete)\n{\n\tIsToUpdate = true;\n\tif (complete) {\n\t\tIsToRedraw = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Input -- Fetches input and processes gadgets.                                 *\n *                                                                                             *\n *    This routine will fetch the keyboard/mouse input and dispatch this through the gadget    *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   key      -- Reference to the key code (for future examination).                    *\n *                                                                                             *\n *          x,y      -- Reference to mouse coordinates (for future examination).               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Input(KeyNumType & key, int & x, int & y)\n{\n\tkey = Keyboard->Check();\n\n\tx = Keyboard->Mouse_X();\n\ty = Keyboard->Mouse_Y();\n\n\tif (Buttons != NULL) {\n\n\t\t/*\n\t\t** If any buttons need redrawing, they will do so in the Input routine, and\n\t\t** they should draw themselves to the HidPage.  So, flag ourselves for a Blit\n\t\t** to show the newly drawn buttons.\n\t\t*/\n\t\tif (Buttons->Is_List_To_Redraw()) {\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n#ifdef WIN32\n\t\tGraphicViewPortClass * oldpage= Set_Logic_Page(HidPage);\n#else\n\t\tGraphicBufferClass * oldpage= Set_Logic_Page(HidPage);\n#endif\n\n\t\tkey = Buttons->Input();\n\n\t\tSet_Logic_Page(oldpage);\n\n\t} else {\n\n\t\tif (key != 0) {\n\t\t\tkey = Keyboard->Get();\n\t\t}\n\t}\n\n\tAI(key, x, y);\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Add_A_Button -- Add a gadget to the game input system.                        *\n *                                                                                             *\n *    This will add a gadget to the game input system. The gadget will be processed in         *\n *    subsequent calls to the GScreenClass::Input() function.                                  *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the gadget that will be added to the input system.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Add_A_Button(GadgetClass & gadget)\n{\n\t/*\n\t**\tIf this gadget is already in the list, remove it before adding it in:\n\t**\t- If 1st gadget in list, use Remove_A_Button to remove it, to reset the\n\t**\t  value of 'Buttons' appropriately\n\t**\t- Otherwise, just call the Remove function for that gadget to remove it\n\t**\t  from any list it may be in\n\t*/\n\tif (Buttons == &gadget) {\n\t\tRemove_A_Button(gadget);\n\t} else {\n\t\tgadget.Remove();\n\t}\n\n\t/*\n\t**\tNow add the gadget to our list:\n\t**\t- If there are not buttons, start the list with this one\n\t**\t- Otherwise, add it to the tail of the existing list\n\t*/\n\tif (Buttons) {\n\t\tgadget.Add_Tail(*Buttons);\n\t} else {\n\t\tButtons = &gadget;\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Remove_A_Button -- Removes a gadget from the game input system.               *\n *                                                                                             *\n * INPUT:   gadget   -- Reference to the gadget that will be removed from the input system.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   'gadget' MUST be already a part of 'Buttons', or the new value of 'Buttons'     *\n *               will be invalid!                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Remove_A_Button(GadgetClass & gadget)\n{\n\tButtons = gadget.Remove();\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Render -- General drawing dispatcher an display update function.              *\n *                                                                                             *\n *    This routine should be called in the main game loop (once every game frame). It will     *\n *    call the Draw_It() function if necessary. All rendering is performed to the LogicPage    *\n *    which is set to the HIDPAGE. After rendering has been performed, the HIDPAGE is          *\n *    copied to the visible page.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This actually updates the graphic display. As a result it can take quite a      *\n *             while to perform.                                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid GScreenClass::Render(void)\n{\n\t//This is unnessasary surely?\tST - 10/16/96 2:30PM\n\t//if (Buttons && Buttons->Is_List_To_Redraw()) {\n\t//\tIsToRedraw = true;\n\t//}\n\n\n\tif (IsToUpdate || IsToRedraw) {\n\t\tBStart(BENCH_GSCREEN_RENDER);\n\n#ifdef WIN32\n\t\tGraphicViewPortClass * oldpage= Set_Logic_Page(HidPage);\n#else\n\t\tGraphicBufferClass * oldpage= Set_Logic_Page(HidPage);\n\n\t\tif (IsToRedraw) {\n\t\t\tHide_Mouse();\n\t\t\tSeenPage.To_Buffer(0, 0, 320, 200, ShadowPage);\n\t\t\tShow_Mouse();\n\t\t}\n#endif\n\n\t\tDraw_It(IsToRedraw);\n\n\t\tif (Buttons) Buttons->Draw_All(false);\n\n#ifdef SCENARIO_EDITOR\n\t\t/*\n\t\t** Draw the Editor's buttons\n\t\t*/\n\t\tif (Debug_Map) {\n\t\t\tif (Buttons) {\n\t\t\t\tButtons->Draw_All();\n\t\t\t}\n\t\t}\n#endif\n\t\t/*\n\t\t** Draw the multiplayer message system to the Hidpage at this point.\n\t\t** This way, they'll Blit along with the rest of the map.\n\t\t*/\n\t\tif (Session.Messages.Num_Messages() > 0) {\n\t\t\tSession.Messages.Set_Width(\n\t\t\t\tLepton_To_Cell(Map.TacLeptonWidth) * ICON_PIXEL_W);\n\t\t}\n\t\tSession.Messages.Draw();\n\n\t\t//Blit_Display(); // 5/19/20 SKY - Skip copying to scene page, we can get the data directly from hidden page\n\t\tIsToUpdate = false;\n\t\tIsToRedraw = false;\n\n\t\tBEnd(BENCH_GSCREEN_RENDER);\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\n\n/***********************************************************************************************\n * GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage.          *\n *                                                                                             *\n *    This routine is used to copy the correct display from the HIDPAGE                        *\n *    to the SEENPAGE.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1994 JLB : Created.                                                                 *\n *   05/01/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nextern \"C\" {\n\tvoid ModeX_Blit (GraphicBufferClass * source);\n}\n\nvoid GScreenClass::Blit_Display(void)\n{\n\tBStart(BENCH_BLIT_DISPLAY);\n\t#ifdef WIN32\n\t\tif (SeenBuff.Get_Width()!=320) {\n\t\t\tWWMouse->Draw_Mouse(&HidPage);\n\t\t\tHidPage.Blit(SeenBuff , 0 , 0 , 0 , 0 , HidPage.Get_Width() , HidPage.Get_Height() , (BOOL) FALSE );\n\t\t\tWWMouse->Erase_Mouse(&HidPage, FALSE);\n\t\t} else {\n\t\t\t//PG ModeX_Blit(&HiddenPage);\n\t\t}\n\t#else\n\t\tShadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ShadowPage->Get_Buffer());\n\t#endif\n\tBEnd(BENCH_BLIT_DISPLAY);\n}\n\n\n"
  },
  {
    "path": "REDALERT/GSCREEN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/GSCREEN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : GSCREEN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef GSCREEN_H\n#define GSCREEN_H\n\n#include\t\"function.h\"\n#include\t\"cell.h\"\n\nclass GScreenClass\n{\n\tpublic:\n\n\t\tGScreenClass(void);\n\t\tGScreenClass(NoInitClass const &) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time initializations\n\t\tvirtual void Init(TheaterType = THEATER_NONE);\t// Inits everything\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\n\t\t/*\n\t\t**\tPlayer I/O is routed through here. It is called every game tick.\n\t\t*/\n\t\tvirtual void Input(KeyNumType & key, int & x, int & y);\n\t\tvirtual void AI(KeyNumType &, int, int) {};\n\t\tvirtual void Add_A_Button(GadgetClass & gadget);\n\t\tvirtual void Remove_A_Button(GadgetClass & gadget);\n\n\t\t/*\n\t\t**\tCalled when map needs complete updating.\n\t\t*/\n\t\tvirtual void Flag_To_Redraw(bool complete=false);\n\n\t\t/*\n\t\t**\tRender maintenance routine (call every game tick). Probably no need\n\t\t**\tto override this in derived classes.\n\t\t*/\n\t\tvirtual void Render(void);\n\n\t\t/*\n\t\t**\tIs called when actual drawing is required. This is the function to\n\t\t**\toverride in derived classes.\n\t\t*/\n\t\tvirtual void Draw_It(bool =false) {};\n\n\t\t/*\n\t\t**\tThis moves the hidpage up to the seenpage.\n\t\t*/\n\t\tvirtual void Blit_Display(void);\n\n\t\t/*\n\t\t**\tChanges the mouse shape as indicated.\n\t\t*/\n\t\tvirtual void Set_Default_Mouse(MouseType mouse, bool wsmall) = 0;\n\t\tvirtual bool Override_Mouse_Shape(MouseType mouse, bool wsmall) = 0;\n\t\tvirtual void Revert_Mouse_Shape(void) = 0;\n\t\tvirtual void Mouse_Small(bool wsmall) = 0;\n\n\t\t/*\n\t\t**\tMisc routines.\n\t\t*/\n\t\tvirtual void * Shadow_Address(void) {return(ShadowPage);};\n\n\t\t/*\n\t\t**\tThis points to the buttons that are used for input. All of the derived classes will\n\t\t**\tattached their specific buttons to this list.\n\t\t*/\n\t\tstatic GadgetClass * Buttons;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tIf the entire map is required to redraw, then this flag is true. This flag\n\t\t**\tis set by the Flag_To_Redraw function. Typically, this occurs when the screen\n\t\t**\thas been trashed or is first created.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\t/*\n\t\t**\tIf only a sub-system of the map must be redrawn, then this flag will be set.\n\t\t**\tAn example of something that would set this flag would be an animating icon\n\t\t**\tin the sidebar. In such a case, complete redrawing of the entire display is not\n\t\t**\tnecessary, but the Draw_It function should still be called so that the appropriate\n\t\t**\tclass can perform it's rendering.\n\t\t*/\n\t\tunsigned IsToUpdate:1;\n\n\t\t/*\n\t\t**\tPointer to an exact copy of the visible graphic page. This copy is used to speed\n\t\t**\tdisplay rendering by using an only-update-changed-pixels algorithm.\n\t\t*/\n\t\tstatic GraphicBufferClass * ShadowPage;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[1024];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/HDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HDATA.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 22, 1994                                                 *\n *                                                                                             *\n *                  Last Update : September 4, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HouseTypeClass::As_Reference -- Fetches a reference to the house specified.               *\n *   HouseTypeClass::From_Name -- Fetch house pointer from its name.                           *\n *   HouseTypeClass::HouseTypeClass -- Constructor for house type objects.                     *\n *   HouseTypeClass::Init_Heap -- Allocate all heap objects for the house types.               *\n *   HouseTypeClass::One_Time -- One-time initialization                                       *\n *   HouseTypeClass::Read_INI -- Fetch the house control values from ini database.             *\n *   HouseTypeClass::Remap_Table -- Fetches the remap table for this house.                    *\n *   HouseTypeClass::operator delete -- Returns a house type object back to the heap.          *\n *   HouseTypeClass::operator new -- Allocates a house type class object from special heap.    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nstatic HouseTypeClass const HouseEngland(\n\tHOUSE_ENGLAND,\n\t\"England\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_ENGLAND,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"ENG\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREEN,\t\t\t\t// Remap color ID number.\n\t'E'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGermany(\n\tHOUSE_GERMANY,\n\t\"Germany\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GERMANY,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GER\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREY,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseFrance(\n\tHOUSE_FRANCE,\n\t\"France\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_FRANCE,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"FRA\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BLUE,\t\t\t\t// Remap color ID number.\n\t'F'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseUkraine(\n\tHOUSE_UKRAINE,\n\t\"Ukraine\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_UKRAINE,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"UKA\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_ORANGE,\t\t\t\t// Remap color ID number.\n\t'K'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseUSSR(\n\tHOUSE_USSR,\n\t\"USSR\",\t\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_USSR,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"RED\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'U'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGreece(\n\tHOUSE_GREECE,\n\t\"Greece\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GREECE,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GRE\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseTurkey(\n\tHOUSE_TURKEY,\n\t\"Turkey\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_TURKEY,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"TRK\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BROWN,\t\t\t\t// Remap color ID number.\n\t'T'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseSpain(\n\tHOUSE_SPAIN,\n\t\"Spain\",\t\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_SPAIN,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"SPN\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'S'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseGood(\n\tHOUSE_GOOD,\n\t\"GoodGuy\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_GOODGUY,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"GDI\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'G'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseBad(\n\tHOUSE_BAD,\n\t\"BadGuy\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_BADGUY,\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"NOD\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'B'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseCivilian(\n\tHOUSE_NEUTRAL,\n\t\"Neutral\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"CIV\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'C'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseJP(\n\tHOUSE_JP,\n\t\"Special\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_JP,\t\t\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"JP\",\t\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'J'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti1(\n\tHOUSE_MULTI1,\n\t\"Multi1\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP1\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GOLD,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti2(\n\tHOUSE_MULTI2,\n\t\"Multi2\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP2\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_LTBLUE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti3(\n\tHOUSE_MULTI3,\n\t\"Multi3\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP3\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_RED,\t\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti4(\n\tHOUSE_MULTI4,\n\t\"Multi4\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP4\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREEN,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti5(\n\tHOUSE_MULTI5,\n\t\"Multi5\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP5\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_ORANGE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti6(\n\tHOUSE_MULTI6,\n\t\"Multi6\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP6\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_GREY,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti7(\n\tHOUSE_MULTI7,\n\t\"Multi7\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP7\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BLUE,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\nstatic HouseTypeClass const HouseMulti8(\n\tHOUSE_MULTI8,\n\t\"Multi8\",\t\t\t\t\t//\tNAME:\t\t\tHouse name.\n\tTXT_CIVILIAN,\t\t\t\t// FULLNAME:\tTranslated house name.\n\t\"MP8\",\t\t\t\t\t\t// SUFFIX:\t\tHouse file suffix.\n\t0,\t\t\t\t\t\t\t\t// LEMON:\t\tLemon vehicle frequency.\n\tPCOLOR_BROWN,\t\t\t\t// Remap color ID number.\n\t'M'\t\t\t\t\t\t\t// VOICE:\t\tVoice prefix character.\n);\n\n#ifdef OBSOLETE\nHouseTypeClass const * const HouseTypeClass::Pointers[HOUSE_COUNT] = {\n\t&HouseSpain,\n\t&HouseGreece,\n\t&HouseUSSR,\n\t&HouseEngland,\n\t&HouseUkraine,\n\t&HouseGermany,\n\t&HouseFrance,\n\t&HouseTurkey,\n\t&HouseGood,\n\t&HouseBad,\n\t&HouseCivilian,\n\t&HouseJP,\n\t&HouseMulti1,\n\t&HouseMulti2,\n\t&HouseMulti3,\n\t&HouseMulti4,\n\t&HouseMulti5,\n\t&HouseMulti6,\n\t&HouseMulti7,\n\t&HouseMulti8,\n};\n#endif\n\n\n/***********************************************************************************************\n * HouseTypeClass::HouseTypeClass -- Constructor for house type objects.                       *\n *                                                                                             *\n *    This is the constructor for house type objects. This object holds the constant data      *\n *    for the house type.                                                                      *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseTypeClass::HouseTypeClass(\n\t\t\t\tHousesType house,\n\t\t\t\tchar const * ini,\n\t\t\t\tint fullname,\n\t\t\t\tchar const * ext,\n\t\t\t\tint lemon,\n\t\t\t\tPlayerColorType remapcolor,\n\t\t\t\tchar prefix) :\n\tAbstractTypeClass(RTTI_HOUSETYPE, house, fullname, ini),\n//\tRTTI(RTTI_HOUSETYPE),\n//\tID(house),\n\tHouse(house),\n//\tIniName(ini),\n//\tFullName(fullname),\n\tLemon(lemon),\n\tRemapColor(remapcolor),\n\tPrefix(prefix),\n\tFirepowerBias(1),\n\tGroundspeedBias(1),\n\tAirspeedBias(1),\n\tArmorBias(1),\n\tROFBias(1),\n\tCostBias(1),\n\tBuildSpeedBias(1)\n{\n\tstrncpy(Suffix, ext, 3);\n\tSuffix[3] = '\\0';\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::operator new -- Allocates a house type class object from special heap.      *\n *                                                                                             *\n *    This will allocate a house type object from the special heap that is used to maintain    *\n *    objects of this type.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the newly allocated house type object.                        *\n *                                                                                             *\n * WARNINGS:   If there is insufficient room, this routine may return NULL.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * HouseTypeClass::operator new(size_t)\n{\n\treturn(HouseTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::operator delete -- Returns a house type object back to the heap.            *\n *                                                                                             *\n *    This will return the house type object specified back into the special heap that         *\n *    is used to maintain house type objects.                                                  *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the house type object to delete.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseTypeClass::operator delete(void * ptr)\n{\n\tHouseTypes.Free((HouseTypeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Init_Heap -- Allocate all heap objects for the house types.                 *\n *                                                                                             *\n *    This will preallocate all the house types. They must be allocated in a particular order. *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine should be called only once at the beginning of the game.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese house type class objects must be allocated in the exact order that they\n\t**\tare specified in the HousesType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew HouseTypeClass(HouseSpain);\n\tnew HouseTypeClass(HouseGreece);\n\tnew HouseTypeClass(HouseUSSR);\n\tnew HouseTypeClass(HouseEngland);\n\tnew HouseTypeClass(HouseUkraine);\n\tnew HouseTypeClass(HouseGermany);\n\tnew HouseTypeClass(HouseFrance);\n\tnew HouseTypeClass(HouseTurkey);\n\tnew HouseTypeClass(HouseGood);\n\tnew HouseTypeClass(HouseBad);\n\tnew HouseTypeClass(HouseCivilian);\n\tnew HouseTypeClass(HouseJP);\n\tnew HouseTypeClass(HouseMulti1);\n\tnew HouseTypeClass(HouseMulti2);\n\tnew HouseTypeClass(HouseMulti3);\n\tnew HouseTypeClass(HouseMulti4);\n\tnew HouseTypeClass(HouseMulti5);\n\tnew HouseTypeClass(HouseMulti6);\n\tnew HouseTypeClass(HouseMulti7);\n\tnew HouseTypeClass(HouseMulti8);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::From_Name -- Fetch house pointer from its name.                             *\n *                                                                                             *\n *    This routine will convert the ASCII house name specified into a                          *\n *    real house number. Typically, this is used when processing a                             *\n *    scenario INI file.                                                                       *\n *                                                                                             *\n * INPUT:   name  -- ASCII name of house to process.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with actual house number represented by the ASCII                          *\n *          name specified.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/21/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nHousesType HouseTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tif (stricmp(As_Reference(house).IniName, name) == 0) {\n//\t\t\tif (stricmp(Pointers[house]->IniName, name) == 0) {\n\t\t\t\treturn(house);\n\t\t\t}\n\t\t}\n\t}\n\treturn(HOUSE_NONE);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::One_Time -- One-time initialization                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/21/1994 JLB : Converted to member function.                                            *\n *   06/19/1996 JLB : Converted to regular heap class management.                              *\n *=============================================================================================*/\nvoid HouseTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::As_Reference -- Fetches a reference to the house specified.                 *\n *                                                                                             *\n *    Use this routine to fetch a reference to the house number specified.                     *\n *                                                                                             *\n * INPUT:   house -- The house number (HousesType) to look up.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the HouseTypeClass object that matches the house       *\n *          number specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseTypeClass & HouseTypeClass::As_Reference(HousesType house)\n{\n\treturn(*HouseTypes.Ptr(house));\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Remap_Table -- Fetches the remap table for this house.                      *\n *                                                                                             *\n *    Use this routine to fetch the remap table assigned to this house. The remap table is     *\n *    what gives the house's units/buildings their distinctive color.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the remap table to use for this house.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned char const * HouseTypeClass::Remap_Table(void) const\n{\n\treturn(ColorRemaps[RemapColor].RemapTable);\n}\n\n\n/***********************************************************************************************\n * HouseTypeClass::Read_INI -- Fetch the house control values from ini database.               *\n *                                                                                             *\n *    This routine will fetch the rules controllable values for the house type from the        *\n *    INI database specified.                                                                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to fetch the house control values from.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the house section found and processed?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tFirepowerBias = ini.Get_Fixed(Name(), \"Firepower\", FirepowerBias);\n\t\tGroundspeedBias = ini.Get_Fixed(Name(), \"Groundspeed\", GroundspeedBias);\n\t\tAirspeedBias = ini.Get_Fixed(Name(), \"Airspeed\", AirspeedBias);\n\t\tArmorBias = ini.Get_Fixed(Name(), \"Armor\", ArmorBias);\n\t\tROFBias = ini.Get_Fixed(Name(), \"ROF\", ROFBias);\n\t\tCostBias = ini.Get_Fixed(Name(), \"Cost\", CostBias);\n\t\tBuildSpeedBias = ini.Get_Fixed(Name(), \"BuildTime\", BuildSpeedBias);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/HEAP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HEAP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HEAP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/18/95                                                     *\n *                                                                                             *\n *                  Last Update : May 6, 1996 [JLB]                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   FixedHeapClass::Allocate -- Allocate a sub-block from the heap.                           *\n *   FixedHeapClass::Clear -- Clears (and frees) the heap manager memory.                      *\n *   FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class.           *\n *   FixedHeapClass::Free -- Frees a sub-block in the heap.                                    *\n *   FixedHeapClass::Free_All -- Frees all objects in the fixed heap.                          *\n *   FixedHeapClass::ID -- Converts a pointer to a sub-block index number.                     *\n *   FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager.                 *\n *   FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class.                 *\n *   FixedIHeapClass::Allocate -- Allocate an object from the heap.                            *\n *   FixedIHeapClass::Clear -- Clears the fixed heap of all entries.                           *\n *   FixedIHeapClass::Free -- Frees an object in the heap.                                     *\n *   FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap.                   *\n *   FixedIHeapClass::Logical_ID -- Fetches the logical ID number.                             *\n *   FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided.                         *\n *   TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save   *\n *   TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading       *\n *   TFixedIHeapClass::Load -- Loads all active objects                                        *\n *   TFixedIHeapClass::Save -- Saves all active objects                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t\"heap.h\"\n//#include\t<mem.h>\n#include\t<stdio.h>\n#include\t<stddef.h>\n#include\t<conio.h>\n#include\t<string.h>\n\n\ntemplate class TFixedIHeapClass<AircraftClass>;\ntemplate class TFixedIHeapClass<AircraftTypeClass>;\ntemplate class TFixedIHeapClass<AnimClass>;\ntemplate class TFixedIHeapClass<AnimTypeClass>;\ntemplate class TFixedIHeapClass<BuildingClass>;\ntemplate class TFixedIHeapClass<BuildingTypeClass>;\ntemplate class TFixedIHeapClass<BulletClass>;\ntemplate class TFixedIHeapClass<BulletTypeClass>;\ntemplate class TFixedIHeapClass<FactoryClass>;\ntemplate class TFixedIHeapClass<HouseClass>;\ntemplate class TFixedIHeapClass<HouseTypeClass>;\ntemplate class TFixedIHeapClass<InfantryClass>;\ntemplate class TFixedIHeapClass<InfantryTypeClass>;\ntemplate class TFixedIHeapClass<OverlayClass>;\ntemplate class TFixedIHeapClass<OverlayTypeClass>;\ntemplate class TFixedIHeapClass<SmudgeClass>;\ntemplate class TFixedIHeapClass<SmudgeTypeClass>;\ntemplate class TFixedIHeapClass<TeamClass>;\ntemplate class TFixedIHeapClass<TeamClass>;\ntemplate class TFixedIHeapClass<TeamTypeClass>;\ntemplate class TFixedIHeapClass<TemplateClass>;\ntemplate class TFixedIHeapClass<TemplateTypeClass>;\ntemplate class TFixedIHeapClass<TerrainClass>;\ntemplate class TFixedIHeapClass<TerrainTypeClass>;\ntemplate class TFixedIHeapClass<TriggerClass>;\ntemplate class TFixedIHeapClass<TriggerTypeClass>;\ntemplate class TFixedIHeapClass<UnitClass>;\ntemplate class TFixedIHeapClass<UnitTypeClass>;\ntemplate class TFixedIHeapClass<VesselClass>;\ntemplate class TFixedIHeapClass<VesselTypeClass>;\ntemplate class TFixedIHeapClass<WarheadTypeClass>;\ntemplate class TFixedIHeapClass<WeaponTypeClass>;\n\n\n/***********************************************************************************************\n * FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class.             *\n *                                                                                             *\n *    This is the normal constructor used for the heap manager class. This initializes         *\n *    the class but doesn't yet assign actual heap memory to this manager. That is handled     *\n *    by the Set_Heap() function.                                                              *\n *                                                                                             *\n * INPUT:   size  -- The size of the individual sub-blocks in this heap. This value is         *\n *                   typically the size of some class or structure.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The heap must first be assigned a block of memory to manage before it can       *\n *             be used.                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFixedHeapClass::FixedHeapClass(int size) :\n\tIsAllocated(false),\n\tSize(size),\n\tTotalCount(0),\n\tActiveCount(0),\n\tBuffer(0)\n{\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class.                   *\n *                                                                                             *\n *    This is the default constructor for the heap manager class. It handles freeing the       *\n *    memory assigned to this heap.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFixedHeapClass::~FixedHeapClass(void)\n{\n\tFixedHeapClass::Clear();\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager.                   *\n *                                                                                             *\n *    This routine is used to assign a memory heap to this object. A memory heap so assigned   *\n *    will start with all sub-blocks unallocated. After this routine is called, normal         *\n *    allocation and freeing may occur. This routine will allocate necessary memory if the     *\n *    buffer parameter is NULL.                                                                *\n *                                                                                             *\n * INPUT:   count    -- The number of objects that this heap should manage.                    *\n *                                                                                             *\n *          buffer   -- Pointer to pre-allocated buffer that this manager will use. If this    *\n *                      parameter is NULL, then memory will be automatically allocated.        *\n *                                                                                             *\n * OUTPUT:  bool; Was the heap successfully initialized?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Set_Heap(int count, void * buffer)\n{\n\t/*\n\t**\tClear out the old heap data.\n\t*/\n\tClear();\n\n\t/*\n\t**\tIf there is no size to the objects in the heap, then this block memory\n\t**\thandler can NEVER function. Return with a failure condition.\n\t*/\n\tif (!Size) return(false);\n\n\t/*\n\t**\tIf there is no count specified, then this indicates that the heap should\n\t**\tbe disabled.\n\t*/\n\tif (!count) return(true);\n\n\t/*\n\t**\tInitialize the free boolean vector and the buffer for the actual\n\t**\tallocation objects.\n\t*/\n\tif (FreeFlag.Resize(count)) {\n\t\tif (!buffer) {\n\t\t\tbuffer = new char[count * Size];\n\t\t\tif (!buffer) {\n\t\t\t\tFreeFlag.Clear();\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t\tIsAllocated = true;\n\t\t}\n\t\tBuffer = buffer;\n\t\tTotalCount = count;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Allocate -- Allocate a sub-block from the heap.                             *\n *                                                                                             *\n *    Finds the first available sub-block in the heap and returns a pointer to it. The sub-    *\n *    block is marked as allocated by this routine. If there are no more sub-blocks            *\n *    available, then this routine will return NULL.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the newly allocated sub-block.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FixedHeapClass::Allocate(void)\n{\n\tif (ActiveCount < TotalCount) {\n\t\tint index = FreeFlag.First_False();\n\n\t\tif (index != -1) {\n\t\t\tActiveCount++;\n\t\t\tFreeFlag[index] = true;\n\t\t\treturn((*this)[index]);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Free -- Frees a sub-block in the heap.                                      *\n *                                                                                             *\n *    Use this routine to free a previously allocated sub-block in the heap.                   *\n *                                                                                             *\n * INPUT:   pointer  -- A pointer to the sub-block to free. This is the same pointer that      *\n *                      was returned from the Allocate() function.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the deallocation successful? Failure could indicate a pointer that       *\n *                doesn't refer to this heap or a null pointer.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Free(void * pointer)\n{\n\tif (pointer && ActiveCount) {\n\t\tint index = ID(pointer);\n\n\t\tif (index < TotalCount) {\n\t\t\tif (FreeFlag[index]) {\n\t\t\t\tActiveCount--;\n\t\t\t\tFreeFlag[index] = false;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::ID -- Converts a pointer to a sub-block index number.                       *\n *                                                                                             *\n *    Use this routine to convert a pointer (returned by Allocate) into the sub-block          *\n *    index number. This index number can be used as a form of identifier for the block.       *\n *                                                                                             *\n * INPUT:   pointer  -- A pointer to the sub-block to convert into an ID number.               *\n *                                                                                             *\n * OUTPUT:  Returns with the index (ID) number for the sub-block specified. This number will   *\n *          range between 0 and the sub-block max -1. If -1 is returned, then the pointer      *\n *          was invalid.                                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::ID(void const * pointer) const\n{\n\tif (pointer && Size) {\n\t\treturn((int)(((char *)pointer - (char *)Buffer) / Size));\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Clear -- Clears (and frees) the heap manager memory.                        *\n *                                                                                             *\n *    This routine is used to bring the heap manager back into a non-functioning state. All    *\n *    memory allocated by this manager is freed. Any previous pointers to allocated blocks     *\n *    from this heap are now invalid.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FixedHeapClass::Clear(void)\n{\n\t/*\n\t**\tFree the old buffer (if present).\n\t*/\n\tif (Buffer && IsAllocated) {\n\t\tdelete[] Buffer;\n\t}\n\tBuffer = 0;\n\tIsAllocated = false;\n\tActiveCount = 0;\n\tTotalCount = 0;\n\tFreeFlag.Clear();\n}\n\n\n/***********************************************************************************************\n * FixedHeapClass::Free_All -- Frees all objects in the fixed heap.                            *\n *                                                                                             *\n *    This routine will free all previously allocated objects out of the heap. Use this        *\n *    routine to ensure that the heap is empty.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the heap successfully cleared of all objects?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedHeapClass::Free_All(void)\n{\n\tActiveCount = 0;\n\tFreeFlag.Reset();\n\treturn(true);\n}\n\n\n/////////////////////////////////////////////////////////////////////\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap.                     *\n *                                                                                             *\n *    Use this routine to free all previously allocated objects in the heap. This routine will *\n *    also clear out the allocated object vector as well.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the heap successfully cleared of objects?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Free_All(void)\n{\n\tActivePointers.Delete_All();\n\treturn(FixedHeapClass::Free_All());\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Clear -- Clears the fixed heap of all entries.                             *\n *                                                                                             *\n *    This routine will clear the entire heap. All memory that was allocation, will be freed   *\n *    by this routine. After calling this routine, the heap must either be resized or          *\n *    a new heap memory block specifically attached, before it can be used again.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid FixedIHeapClass::Clear(void)\n{\n\tFixedHeapClass::Clear();\n\tActivePointers.Clear();\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided.                           *\n *                                                                                             *\n *    This routine will set the heap to use the buffer specified. Use this routine when a      *\n *    pre-allocated buffer is to be used for the heap. A heap that is assigned in this         *\n *    manner cannot be resized.                                                                *\n *                                                                                             *\n * INPUT:   count -- The number of objects that the buffer pointer can be used to track.       *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer to use when keeping track of the objects.        *\n *                                                                                             *\n * OUTPUT:  Was the heap assigned successfully?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Set_Heap(int count, void * buffer)\n{\n\tClear();\n\tif (FixedHeapClass::Set_Heap(count, buffer)) {\n\t\tActivePointers.Resize(count);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Allocate -- Allocate an object from the heap.                              *\n *                                                                                             *\n *    This routine will allocate an object located in the heap. If no free object space        *\n *    could be found, then NULL is returned.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated object memory block.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * FixedIHeapClass::Allocate(void)\n{\n\tvoid * ptr = FixedHeapClass::Allocate();\n\tif (ptr)\t{\n\t\tActivePointers.Add(ptr);\n\t\tmemset (ptr, 0, Size);\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Free -- Frees an object in the heap.                                       *\n *                                                                                             *\n *    This routine is used to free an object in the heap. Freeing is accomplished by marking   *\n *    the object's memory as free to be reallocated. The object is also removed from the       *\n *    allocated object pointer vector.                                                         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the object that is to be removed from the heap.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Free(void * pointer)\n{\n\tif (FixedHeapClass::Free(pointer)) {\n\t\tActivePointers.Delete(pointer);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * FixedIHeapClass::Logical_ID -- Fetches the logical ID number.                               *\n *                                                                                             *\n *    Ths logical ID number of a memory block is the index number of the block as if the       *\n *    heap consisted only of valid allocated blocks. This knowledge comes in handy when        *\n *    the real index number must be anticipated before a memory block packing process.         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to an allocated block in the heap.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the logical index number of this block. The number returned must not  *\n *          be used as a regular index into the heap until such time as the heap has been      *\n *          compacted (by some means or another) without modifying the block order.            *\n *                                                                                             *\n * WARNINGS:   Runs in linear time.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint FixedIHeapClass::Logical_ID(void const * pointer) const\n{\n\tif (pointer != NULL) {\n\t\tfor (int index = 0; index < Count(); index++) {\n\t\t\tif (Active_Ptr(index) == pointer) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(-1);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Save -- Saves all active objects                                          *\n *                                                                                             *\n * INPUT:   file      file to write to                                                         *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *   03/12/1996 JLB : Uses in-place new operator for virtual table control.                    *\n *=============================================================================================*/\ntemplate<class T>\nint TFixedIHeapClass<T>::Save(Pipe & file) const\n{\n\t/*\n\t** Save the number of instances of this class\n\t*/\n\tfile.Put(&ActiveCount, sizeof(ActiveCount));\n\n\t/*\n\t** Save each instance of this class\n\t*/\n\tfor (int i = 0; i < ActiveCount; i++) {\n\n\t\t/*\n\t\t** Save the array index of the object, so it can be loaded back into the\n\t\t** same array location (so TARGET translations will work)\n\t\t*/\n\t\tint idx = ID(Ptr(i));\n\t\tfile.Put(&idx, sizeof(idx));\n\n\t\t/*\n\t\t** Save the object itself\n\t\t*/\n\t\tfile.Put(Ptr(i), sizeof(T));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Load -- Loads all active objects                                          *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint TFixedIHeapClass<T>::Load(Straw & file)\n{\n\tint i;\t\t\t// loop counter\n\tint idx;\t\t\t// object index\n\tT * ptr;\t\t\t// object pointer\n\tint a_count;\n\n\t/*\n\t** Read the number of instances of this class\n\t*/\n\tif (file.Get(&a_count, sizeof(a_count)) != sizeof(a_count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Error if more objects than we can hold\n\t*/\n\tif (a_count > TotalCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Read each class instance\n\t*/\n\tfor (i = 0; i < a_count; i++) {\n\t\t/*\n\t\t** Read the object's array index\n\t\t*/\n\t\tif (file.Get(&idx, sizeof(idx)) != sizeof(idx)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t** Get a pointer to the object, activate that object\n\t\t*/\n\t\tptr = (T *)(*this)[idx];\n\t\tFreeFlag[idx] = true;\n\t\tActiveCount++;\n\t\tActivePointers.Add(ptr);\n\n\t\t/*\n\t\t** Load the object\n\t\t*/\n\t\tfile.Get(ptr, sizeof(T));\n\t\tnew(ptr) T(NoInitClass());\n//\t\tif (!ptr->Load(file)) {\n//\t\t\treturn(false);\n//\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save     *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TFixedIHeapClass<T>::Code_Pointers(void)\n{\n\tint i;\n\n\tfor (i = 0; i < ActiveCount; i++) {\n\t\tPtr(i)->Code_Pointers();\n\t}\n}\n\n\n/***********************************************************************************************\n * TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading         *\n *                                                                                             *\n * INPUT:   file      file to read from                                                        *\n *                                                                                             *\n * OUTPUT:  true = OK, false = error                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid TFixedIHeapClass<T>::Decode_Pointers(void)\n{\n\tint i;\n\n\tfor (i = 0; i < ActiveCount; i++) {\n\t\tPtr(i)->Decode_Pointers();\n\t}\n}\n"
  },
  {
    "path": "REDALERT/HEAP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HEAP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HEAP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/18/95                                                     *\n *                                                                                             *\n *                  Last Update : February 18, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HEAP_H\n#define HEAP_H\n\n#include \"vector.h\"\n\n/**************************************************************************\n**\tThis is a block memory management handler. It is used when memory is to\n**\tbe treated as a series of blocks of fixed size. This is similar to an\n**\tarray of integral types, but unlike such an array, the memory blocks\n**\tare anonymously. This facilitates the use of this class when overloading\n**\tthe new and delete operators for a normal class object.\n*/\nclass FixedHeapClass\n{\n\tpublic:\n\t\tFixedHeapClass(int size);\n\t\tvirtual ~FixedHeapClass(void);\n\n\t\tint Count(void) const {return ActiveCount;};\n\t\tint Length(void) const {return TotalCount;};\n\t\tint Avail(void) const {return TotalCount-ActiveCount;};\n\n\t\tvirtual int ID(void const * pointer) const;\n\t\tvirtual int Set_Heap(int count, void * buffer=0);\n\t\tvirtual void * Allocate(void);\n\t\tvirtual void Clear(void);\n\t\tvirtual int Free(void * pointer);\n\t\tvirtual int Free_All(void);\n\n\t\tvoid * operator[](int index) {return ((char *)Buffer) + (index * Size);};\n\t\tvoid const * operator[](int index) const {return ((char *)Buffer) + (index * Size);};\n\n\tprotected:\n\t\t/*\n\t\t**\tIf the memory block buffer was allocated by this class, then this flag\n\t\t**\twill be true. The block must be deallocated by this class if true.\n\t\t*/\n\t\tunsigned IsAllocated:1;\n\n\t\t/*\n\t\t**\tThis is the size of each sub-block within the buffer.\n\t\t*/\n\t\tint Size;\n\n\t\t/*\n\t\t**\tThis records the absolute number of sub-blocks in the buffer.\n\t\t*/\n\t\tint TotalCount;\n\n\t\t/*\n\t\t**\tThis is the total blocks allocated out of the heap. This number\n\t\t**\twill never exceed Count.\n\t\t*/\n\t\tint ActiveCount;\n\n\t\t/*\n\t\t**\tPointer to the heap's memory buffer.\n\t\t*/\n\t\tvoid * Buffer;\n\n\t\t/*\n\t\t**\tThis is a boolean vector array of allocation flag bits.\n\t\t*/\n\t\tBooleanVectorClass FreeFlag;\n\n\tprivate:\n\t\t// The assignment operator is not supported.\n\t\tFixedHeapClass & operator = (FixedHeapClass const &);\n\n\t\t// The copy constructor is not supported.\n\t\tFixedHeapClass(FixedHeapClass const &);\n};\n\n\n/**************************************************************************\n**\tThis template serves only as an interface to the heap manager class. By\n**\tusing this template, the object pointers are automatically converted\n**\tto the correct type without any code overhead.\n*/\ntemplate<class T>\nclass TFixedHeapClass : public FixedHeapClass\n{\n\tpublic:\n\t\tTFixedHeapClass(void) : FixedHeapClass(sizeof(T)) {};\n\t\tvirtual ~TFixedHeapClass(void) {};\n\n\n\t\tvirtual int ID(T const * pointer) const {return FixedHeapClass::ID(pointer);};\n\t\tvirtual T * Alloc(void) {return (T*)FixedHeapClass::Allocate();};\n\t\tvirtual int Free(T * pointer) {return(FixedHeapClass::Free(pointer));};\n\n\t\tT & operator[](int index) {return *(T *)(((char *)Buffer) + (index * Size));};\n\t\tT const & operator[](int index) const {return *(T*)(((char *)Buffer) + (index * Size));};\n};\n\n\n/**************************************************************************\n**\tThis is a derivative of the fixed heap class. This class adds the\n**\tability to quickly iterate through the active (allocated) objects. Since the\n**\tactive array is a sequence of pointers, the overhead of this class\n**\tis 4 bytes per potential allocated object (be warned).\n*/\nclass FixedIHeapClass : public FixedHeapClass\n{\n\tpublic:\n\t\tFixedIHeapClass(int size) : FixedHeapClass(size) {};\n\t\tvirtual ~FixedIHeapClass(void) {};\n\n\t\tvirtual int Set_Heap(int count, void * buffer=0);\n\t\tvirtual void * Allocate(void);\n\t\tvirtual void Clear(void);\n\t\tvirtual int Free(void * pointer);\n\t\tvirtual int Free_All(void);\n\t\tvirtual int Logical_ID(void const * pointer) const;\n\t\tvirtual int Logical_ID(int id) const {return(Logical_ID((*this)[id]));}\n\n\t\tvirtual void * Active_Ptr(int index) {return ActivePointers[index];};\n\t\tvirtual void const * Active_Ptr(int index) const {return ActivePointers[index];};\n\n\t\t/*\n\t\t**\tThis is an array of pointers to allocated objects. Using this array\n\t\t**\tto control iteration through the objects ensures a minimum of processing.\n\t\t**\tIt also allows access to this array so that custom sorting can be\n\t\t**\tperformed.\n\t\t*/\n\t\tDynamicVectorClass<void *> ActivePointers;\n};\n\n\n/**************************************************************************\n**\tThis template serves only as an interface to the iteratable heap manager\n**\tclass. By using this template, the object pointers are automatically converted\n**\tto the correct type without any code overhead.\n*/\nclass FileClass;\ntemplate<class T>\nclass TFixedIHeapClass : public FixedIHeapClass\n{\n\tpublic:\n\t\tTFixedIHeapClass(void) : FixedIHeapClass(sizeof(T)) {};\n\t\tvirtual ~TFixedIHeapClass(void) {};\n\n\t\tvirtual int ID(T const * pointer) const {return FixedIHeapClass::ID(pointer);};\n\t\tvirtual int Logical_ID(T const * pointer) const {return(FixedIHeapClass::Logical_ID(pointer));}\n\t\tvirtual int Logical_ID(int id) const {return(FixedIHeapClass::Logical_ID(id));}\n\t\tvirtual T * Alloc(void) {return (T*)FixedIHeapClass::Allocate();};\n\t\tvirtual int Free(T * pointer) {return FixedIHeapClass::Free(pointer);};\n\t\tvirtual int Free(void * pointer) {return FixedIHeapClass::Free(pointer);};\n\t\tvirtual int Save(Pipe & file) const;\n\t\tvirtual int Load(Straw & file);\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\tvirtual T * Ptr(int index) const {return (T*)FixedIHeapClass::ActivePointers[index];};\n\t\tvirtual T * Raw_Ptr(int index) {return (index >= 0 && index < Length()) ? (T*)((*this)[index]) : NULL;};\n};\n\n\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/HELP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HELP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HELP.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HelpClass::Draw_Help -- Display the help message (if necessary).                          *\n *   HelpClass::HelpClass -- Default constructor for the help processor.                       *\n *   HelpClass::Help_AI -- Handles the help text logic.                                        *\n *   HelpClass::Help_Text -- Assigns text as the current help text.                            *\n *   HelpClass::Init_Clear -- Sets help system to a known state.                               *\n *   HelpClass::Overlap_List -- Returns with offset list for cells under help text.            *\n *   HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                  *\n *   HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.          *\n *   HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                *\n *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *\n *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *\n *   HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the holding buffer for the text overlap list. This buffer must be in the near\n**\tdata segment. It will be filled in by the Set_Text() function.\n*/\n//short const HelpClass::OverlapList[60] = {  // Can't be const - it's expected to be written to. ST - 2/7/2019 5:16PM\t\t\nshort HelpClass::OverlapList[60] = {\n\tREFRESH_EOL\n};\n\nchar const * HelpClass::HelpText;\n\n\n/***********************************************************************************************\n * HelpClass::HelpClass -- Default constructor for the help processor.                         *\n *                                                                                             *\n *    The help processor is initialized by this routine. It merely sets up the help engine     *\n *    to the default state. The default state will not display any help text. Call the         *\n *    Help_Text() function to enable help processing.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nHelpClass::HelpClass(void) :\n\tHelpX(0),\n\tHelpY(0),\n\tHelpWidth(0),\n\tIsRight(false),\n\tCost(0),\n\tX(0),\n\tY(0),\n\tDrawX(0),\n\tDrawY(0),\n\tWidth(0),\n\tText(TXT_NONE),\n\tColor(LTGREY),\n\tCountDownTimer(0)\n{\n}\n\n\n/***********************************************************************************************\n * HelpClass::Init_Clear -- Sets help system to a known state.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Init_Clear(void)\n{\n\tTabClass::Init_Clear();\n\n\tSet_Text(TXT_NONE);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Overlap_List -- Returns with offset list for cells under help text.              *\n *                                                                                             *\n *    Use this routine to fetch an offset list for the cells under the text displayed. If      *\n *    there is no text displayed, then the list will consist of just the terminator code.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the offset list for the help text overlap. The offset    *\n *          list is based on the tactical map upper left corner cell.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * HelpClass::Overlap_List(void) const\n{\n\tif (Text == TXT_NONE || CountDownTimer) {\n\t\t((short &)(OverlapList[0])) = REFRESH_EOL;\n\t}\n\treturn(OverlapList);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Help_AI -- Handles the help text logic.                                          *\n *                                                                                             *\n *    This routine handles tracking the mouse position to see if the mouse remains stationary  *\n *    for the required amount of time. If the time requirement has been met, then it flags     *\n *    the help system to display the help text the next time the Draw_Help() function is       *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   key   -- Keyboard input code.                                                      *\n *                                                                                             *\n *          x,y   -- Mouse coordinates.                                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine must be called once and only once per game frame (15 times per     *\n *             second).                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinates as passed in.                                     *\n *=============================================================================================*/\nvoid HelpClass::AI(KeyNumType &key, int x, int y)\n{\n\tif (!CountDownTimer && !IsRight && (x != X || y != Y)) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\n\t/*\n\t**\tProcess the countdown timer only if it hasn't already expired and there is\n\t**\ta real help text message to display.\n\t*/\n\tif (CountDownTimer && !HelpText && Text != TXT_NONE) {\n\n\t\t/*\n\t\t**\tIf the mouse has moved, then reset the timer since a moving mouse is not\n\t\t**\tsupposed to bring up the help text.\n\t\t*/\n\t\tif (!IsRight && (X != x || Y != y)) {\n\t\t\tX = x;\n\t\t\tY = y;\n\t\t\tCountDownTimer = HELP_DELAY;\n\t\t\tHelp_Text(TXT_NONE);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the delay has expired, then the text must be drawn. Build the help text\n\t\t\t**\toverlay list at this time. Better to do it now, when we KNOW it is needed, then\n\t\t\t**\tto do it earlier when it might not be needed.\n\t\t\t*/\n\t\t\tSet_Text(Text);\n\t\t}\n\t}\n\n\tTabClass::AI(key, x, y);\n}\n\n\n/***********************************************************************************************\n * HelpClass::Help_Text -- Assigns text as the current help text.                              *\n *                                                                                             *\n *    Use this routine to change the help text that will pop up if the cursor isn't moved      *\n *    for the help delay duration. Call this routine as often as desired.                      *\n *                                                                                             *\n * INPUT:   text  -- The text number for the help text to use.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Help_Text(int text, int x, int y, int color, bool quick)\n{\n\tif (text != Text) {\n\n\t\t/*\n\t\t**\tIf there is an existing text message, then flag the map to redraw the underlying\n\t\t**\ticons so that the text message is erased.\n\t\t*/\n\t\tif (Text != TXT_NONE) {\n\t\t\tRefresh_Cells(Coord_Cell(TacticalCoord), &OverlapList[0]);\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the position of the mouse. This recorded position will be used to determine\n\t\t**\tif the mouse has moved. A moving mouse prevents the help text from popping up.\n\t\t*/\n\t\tX = x;\n\t\tif (x == -1) X = Get_Mouse_X();\n\t\tY = y;\n\t\tif (y == -1) Y = Get_Mouse_Y();\n\t\tIsRight = (y != -1) || (x != -1);\n\n\t\tif (quick) {\n\t\t\tCountDownTimer = 1;\n\t\t} else {\n\t\t\tCountDownTimer = HELP_DELAY;\n\t\t}\n\n\t\t/*\n\t\t** All help text prints in the same color for E3\n\t\t*/\n\t\t//Color = color;\n\t\tcolor = color;\n\t\tColor = HELP_TEXT_COLOR;\n\t\tText = text;\n\t\tCost = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Draw_Help -- Display the help message (if necessary).                            *\n *                                                                                             *\n *    This function will print the help text if it thinks it should. The timer and text        *\n *    message can control whether this occurs. If there is no help text or the countdown timer *\n *    has not expired, then no text will be printed.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Draw_It(bool forced)\n{\n\tTabClass::Draw_It(forced);\n\n\tforced = false;\t\t// TCTCTCTC\n\tif (Text != TXT_NONE && (forced || !CountDownTimer)) {\n\n\t\tif (LogicPage->Lock()) {\n\t\t\tPlain_Text_Print(Text, DrawX, DrawY, Color, BLACK, TPF_MAP|TPF_NOSHADOW);\n\t\t\tLogicPage->Draw_Rect(DrawX-1, DrawY-1, DrawX+Width+1, DrawY+FontHeight, Color);\n\n\t\t\tif (Cost) {\n\t\t\t\tchar buffer[15];\n\t\t\t\tsprintf(buffer, \"$%d\", Cost);\n\t\t\t\tint width = String_Pixel_Width(buffer);\n\n\t\t\t\tPlain_Text_Print(buffer, DrawX, DrawY+FontHeight, Color, BLACK, TPF_MAP|TPF_NOSHADOW);\n\t\t\t\tLogicPage->Draw_Rect(DrawX-1, DrawY+FontHeight, DrawX+width+1, DrawY+FontHeight+FontHeight-1, Color);\n\t\t\t\tLogicPage->Draw_Line(DrawX, DrawY+FontHeight, DrawX+min(width+1, Width)-1, DrawY+FontHeight, BLACK);\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                    *\n *                                                                                             *\n *    This routine is used to build the overlap list -- used for icon refreshing. It also      *\n *    determines if the text can fit on the screen and makes adjustments so that it will.      *\n *                                                                                             *\n * INPUT:   text  -- The text number to set the help system to use.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/18/1994 JLB : Created.                                                                 *\n *   12/11/1994 JLB : Won't draw past tactical map edges.                                      *\n *=============================================================================================*/\nvoid HelpClass::Set_Text(int text)\n{\n\tif (text != TXT_NONE) {\n\t\tText = text;\n\t\tPlain_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_MAP|TPF_NOSHADOW);\n\t\tWidth = String_Pixel_Width(Text_String(Text));\n\t\tif (IsRight) {\n\t\t\tDrawX = X - Width;\n\t\t\tDrawY = Y;\n\t\t} else {\n\t\t\tint right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth) - 3*RESFACTOR;\n\t\t\tint bottom = TacPixelY + Lepton_To_Pixel(TacLeptonHeight) - 1*RESFACTOR;\n\n\t\t\tDrawX = X+X_OFFSET;\n\t\t\tDrawY = Y+Y_OFFSET;\n\t\t\tif (DrawX + Width > right) {\n\t\t\t\tDrawX -= (DrawX+Width) - right;\n\t\t\t}\n\t\t\tif (DrawY + 10*RESFACTOR > bottom) {\n\t\t\t\tDrawY -= (DrawY+10*RESFACTOR) - bottom;\n\t\t\t}\n\t\t\tif (DrawX < TacPixelX+1) DrawX = TacPixelX+1;\n\t\t\tif (DrawY < TacPixelY+1) DrawY = TacPixelY+1;\n\t\t}\n\t\tmemcpy((void*)OverlapList, Text_Overlap_List(Text_String(Text), DrawX-1, DrawY), sizeof(OverlapList));\n\t\t*(short *)&OverlapList[ARRAY_SIZE(OverlapList)-1] = REFRESH_EOL;\n\t}\n}\n\n\n/***********************************************************************************************\n * HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                    *\n *                                                                                             *\n *    This routine intercepts the map scrolling request and then makes sure that if, in fact,  *\n *    the map is going to scroll, then reset and erase the help text so that it doesn't        *\n *    mess up the display.                                                                     *\n *                                                                                             *\n * INPUT:   facing   -- The direction to scroll (unused by this routine).                      *\n *                                                                                             *\n *          really   -- If the scroll is actually going to occur, rather than just be examined *\n *                      for legality, then this parameter will be true. If this parameter is   *\n *                      true, then the help text is reset.                                     *\n *                                                                                             *\n * OUTPUT:  Returns if it can, or did, scroll in the requested direction.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/15/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HelpClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\tif (really) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\treturn(TabClass::Scroll_Map(facing, distance, really));\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.            *\n *                                                                                             *\n *    Use this routine after the Help_Text() function to activate the second line. The second  *\n *    line displays a cost. Typically, this is used by the sidebar to display the cost of the  *\n *    specified item.                                                                          *\n *                                                                                             *\n * INPUT:   cost  -- The cost to associate with this help text. If this value is zero, then    *\n *                   no second line is displayed, so don't pass in zero.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/09/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Set_Cost(int cost)\n{\n\tCost = cost;\n}\n\n\n/***********************************************************************************************\n * HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                  *\n *                                                                                             *\n *    This routine will set the position of the tactical map. At this class level, it merely   *\n *    makes sure that the help text disappears when this happens. The lower level classes      *\n *    actually change the map's position.                                                      *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to make the upper left corner of the visible display.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HelpClass::Set_Tactical_Position(COORDINATE coord)\n{\n\tif (TacticalCoord != coord) {\n\t\tHelp_Text(TXT_NONE);\n\t}\n\tTabClass::Set_Tactical_Position(coord);\n}\n"
  },
  {
    "path": "REDALERT/HELP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HELP.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HELP.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : November 18, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HELP_H\n#define HELP_H\n\n#include\t\"tab.h\"\n\n#define HELP_TEXT_COLOR 80\t//158\t\t//Goldy/orange\n\nclass HelpClass: public TabClass\n{\n\tpublic:\n\t\tHelpClass(void);\n\t\tHelpClass(NoInitClass const & x) : TabClass(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual bool Scroll_Map(DirType facing, int &distance, bool really);\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\n\t\tvoid Help_Text(int text, int x=-1, int y=-1, int color=LTGREY, bool quick=false);\n\t\tvoid Set_Cost(int cost);\n\t\tshort const * Overlap_List(void) const;\n\n\tprivate:\n\n\t\tstatic char const *HelpText;\n\t\tint HelpX;\n\t\tint HelpY;\n\t\tint HelpWidth;\n\n\n\t\tvoid Set_Text(int text);\n\n\t\t/*\n\t\t**\tIf the help text is right justified (as with the help text that pops up over the\n\t\t**\tsidebar icons), then this flag is set to true.\n\t\t*/\n\t\tunsigned IsRight:1;\n\n\t\t/*\n\t\t**\tIf the optional second line of text that displays cost is desired, then this\n\t\t**\tvalue will be non-zero. Typically, this is true when the help text is associated\n\t\t**\twith one of the sidebar construction icons.\n\t\t*/\n\t\tint Cost;\n\n\t\t/*\n\t\t**\tThis is the recorded position of the cursor at the time the help text\n\t\t**\tpops up. The help text is rendered as an offset from this pixel position.\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\n\t\t/*\n\t\t**\tThis is the draw X and Y coordinate. This position is relative to the X and\n\t\t**\tY coordinates but adjusted for screen edges as necessary.\n\t\t*/\n\t\tint DrawX;\n\t\tint DrawY;\n\n\t\t/*\n\t\t**\tThe width of the help text (in pixels) is stored here. This is a convenience\n\t\t**\tsince calculating the width takes a bit of time.\n\t\t*/\n\t\tint Width;\n\n\t\t/*\n\t\t**\tThe text number of the help text to display is held here. If no text is to be\n\t\t**\tdisplayed, then this value will be TXT_NONE.\n\t\t*/\n\t\tint Text;\n\n\t\t/*\n\t\t**\tThis is the background color to use for the help text. It can change according\n\t\t**\tto the message displayed.\n\t\t*/\n\t\tint Color;\n\n\t\t/*\n\t\t**\tThis countdown timer controls when the help text will pop up. If the mouse\n\t\t**\tremains stationary while this countdown timer expires, then the help text\n\t\t**\twill pop up.\n\t\t*/\n\t\tCDTimerClass<SystemTimerClass> CountDownTimer;\n\n\t\t/*\n\t\t**\tThis is a calculated cell offset list (from the Map.TacticalCell) that indicates\n\t\t**\twhich cells are under the help text and thus which cells need to be redrawn if\n\t\t**\tthe help text is to be erased.\n\t\t*/\n\t\t//static short const OverlapList[60];  // Can't be const - it's expected to be written to. ST - 2/7/2019 5:16PM\t\t\n\t\tstatic short OverlapList[60];\n\n\t\tenum HelpClassEnum {\n\t\t\tHELP_DELAY=TIMER_SECOND*1,\t\t\t\t// The countdown timer delay before help text pops up.\n\t\t\tY_OFFSET=0,\t\t\t\t\t// The Y pixel offset from cursor for help text print.\n\t\t\tX_OFFSET=12\t\t\t\t\t// The X pixel offset from cursor for help text print.\n\t\t};\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/HOUSE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/HOUSE.CPP 4     3/13/97 7:11p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 21, 1994                                                 *\n *                                                                                             *\n *                  Last Update : November 4, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HouseClass::AI -- Process house logic.                                                    *\n *   HouseClass::AI_Aircraft -- Determines what aircraft to build next.                        *\n *   HouseClass::AI_Attack -- Handles offensive attack logic.                                  *\n *   HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                 *\n *   HouseClass::AI_Building -- Determines what building to build.                             *\n *   HouseClass::AI_Fire_Sale -- Check for and perform a fire sale.                            *\n *   HouseClass::AI_Infantry -- Determines the infantry unit to build.                         *\n *   HouseClass::AI_Money_Check -- Handles money production logic.                             *\n *   HouseClass::AI_Power_Check -- Handle the power situation.                                 *\n *   HouseClass::AI_Unit -- Determines what unit to build next.                                *\n *   HouseClass::Abandon_Production -- Abandons production of item type specified.             *\n *   HouseClass::Active_Add -- Add an object to active duty for this house.                    *\n *   HouseClass::Active_Remove -- Remove this object from active duty for this house.          *\n *   HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.               *\n *   HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                    *\n *   HouseClass::Adjust_Power -- Adjust the power value of the house.                          *\n *   HouseClass::Adjust_Threat -- Adjust threat for the region specified.                      *\n *   HouseClass::As_Pointer -- Converts a house number into a house object pointer.            *\n *   HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.        *\n *   HouseClass::Attacked -- Lets player know if base is under attack.                         *\n *   HouseClass::Available_Money -- Fetches the total credit worth of the house.               *\n *   HouseClass::Begin_Production -- Starts production of the specified object type.           *\n *   HouseClass::Blowup_All -- blows up everything                                             *\n *   HouseClass::Can_Build -- General purpose build legality checker.                          *\n *   HouseClass::Clobber_All -- removes all objects for this house                             *\n *   HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.            *\n *   HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                 *\n *   HouseClass::Detach -- Removes specified object from house tracking systems.               *\n *   HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                     *\n *   HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.     *\n *   HouseClass::Expert_AI -- Handles expert AI processing.                                    *\n *   HouseClass::Factory_Count -- Fetches the number of factories for specified type.          *\n *   HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.            *\n *   HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified. *\n *   HouseClass::Find_Build_Location -- Finds a suitable building location.                    *\n *   HouseClass::Find_Building -- Finds a building of specified type.                          *\n *   HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.            *\n *   HouseClass::Find_Juicy_Target -- Finds a suitable field target.                           *\n *   HouseClass::Fire_Sale -- Cause all buildings to be sold.                                  *\n *   HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                *\n *   HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                    *\n *   HouseClass::Flag_Remove -- Removes the flag from the specified target.                    *\n *   HouseClass::Flag_To_Die -- Flags the house to blow up soon.                               *\n *   HouseClass::Flag_To_Lose -- Flags the house to die soon.                                  *\n *   HouseClass::Flag_To_Win -- Flags the house to win soon.                                   *\n *   HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.   *\n *   HouseClass::Get_Quantity -- Gets the quantity of the building type specified.             *\n *   HouseClass::Harvested -- Adds Tiberium to the harvest storage.                            *\n *   HouseClass::HouseClass -- Constructor for a house object.                                 *\n *   HouseClass::Init -- init's in preparation for new scenario                                *\n *   HouseClass::Init_Data -- Initializes the multiplayer color data.                          *\n *   HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.      *\n *   HouseClass::Is_Ally -- Checks to see if the object is an ally.                            *\n *   HouseClass::Is_Ally -- Determines if the specified house is an ally.                      *\n *   HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?    *\n *   HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.         *\n *   HouseClass::MPlayer_Defeated -- multiplayer; house is defeated                            *\n *   HouseClass::Make_Ally -- Make the specified house an ally.                                *\n *   HouseClass::Make_Enemy -- Make an enemy of the house specified.                           *\n *   HouseClass::Manual_Place -- Inform display system of building placement mode.             *\n *   HouseClass::One_Time -- Handles one time initialization of the house array.               *\n *   HouseClass::Place_Object -- Places the object (building) at location specified.           *\n *   HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.    *\n *   HouseClass::Power_Fraction -- Fetches the current power output rating.                    *\n *   HouseClass::Production_Begun -- Records that production has begun.                        *\n *   HouseClass::Read_INI -- Reads house specific data from INI.                               *\n *   HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                       *\n *   HouseClass::Recalc_Center -- Recalculates the center point of the base.                   *\n *   HouseClass::Refund_Money -- Refunds money to back to the house.                           *\n *   HouseClass::Remap_Table -- Fetches the remap table for this house object.                 *\n *   HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                *\n *   HouseClass::Set_Factory -- Assign specified factory to house tracking.                    *\n *   HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                  *\n *   HouseClass::Special_Weapon_AI -- Fires special weapon.                                    *\n *   HouseClass::Spend_Money -- Removes money from the house.                                  *\n *   HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.       *\n *   HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.      *\n *   HouseClass::Suggested_New_Team -- Determine what team should be created.                  *\n *   HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.  *\n *   HouseClass::Suspend_Production -- Temporarily puts production on hold.                    *\n *   HouseClass::Tally_Score -- Fills in the score system for this round                       *\n *   HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.            *\n *   HouseClass::Tracking_Add -- Informs house of new inventory item.                          *\n *   HouseClass::Tracking_Remove -- Remove object from house tracking system.                  *\n *   HouseClass::Where_To_Go -- Determines where the object should go and wait.                *\n *   HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                      *\n *   HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.          *\n *   HouseClass::Which_Zone -- Determines which base zone the specified object lies in.        *\n *   HouseClass::Write_INI -- Writes the house data to the INI database.                       *\n *   HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                *\n *   HouseClass::delete -- Deallocator function for a house object.                            *\n *   HouseClass::new -- Allocator for a house class.                                           *\n *   HouseClass::operator HousesType -- Conversion to HousesType operator.                     *\n *   HouseClass::~HouseClass -- Default destructor for a house object.                         *\n *   HouseStaticClass::HouseStaticClass -- Default constructor for house static class.         *\n *   HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.         *\n *   HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                  *\n *   HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified. *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n//#include \"WolDebug.h\"\n\n/*\n** New sidebar for GlyphX multiplayer. ST - 8/7/2019 10:10AM\n*/\n#include \"SidebarGlyphx.h\"\n\nTFixedIHeapClass<HouseClass::BuildChoiceClass> HouseClass::BuildChoice;\n\nint TFixedIHeapClass<HouseClass::BuildChoiceClass>::Save(Pipe &) const\n{\n\treturn(true);\n}\n\nint TFixedIHeapClass<HouseClass::BuildChoiceClass>::Load(Straw &)\n{\n\treturn(0);\n}\n\nvoid TFixedIHeapClass<HouseClass::BuildChoiceClass>::Code_Pointers(void)\n{\n}\n\nvoid TFixedIHeapClass<HouseClass::BuildChoiceClass>::Decode_Pointers(void)\n{\n}\n\nextern bool RedrawOptionsMenu;\n\n/***********************************************************************************************\n * HouseClass::operator HousesType -- Conversion to HousesType operator.                       *\n *                                                                                             *\n *    This operator will automatically convert from a houses class object into the HousesType  *\n *    enumerated value.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the object's HousesType value.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseClass::operator HousesType(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Class->House);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.              *\n *                                                                                             *\n *    This will calculate the current tiberium (gold) load as a ratio of the maximum storage   *\n *    capacity.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current tiberium storage situation as a ratio of load over capacity.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed HouseClass::Tiberium_Fraction(void) const\n{\n\tif (Tiberium == 0) {\n\t\treturn(0);\n\t}\n\treturn(fixed(Tiberium, Capacity));\n}\n\n\n/***********************************************************************************************\n * HouseClass::As_Pointer -- Converts a house number into a house object pointer.              *\n *                                                                                             *\n *    Use this routine to convert a house number into the house pointer that it represents.    *\n *    A simple index into the Houses template array is not sufficient, since the array order   *\n *    is arbitrary. An actual scan through the house object is required in order to find the   *\n *    house object desired.                                                                    *\n *                                                                                             *\n * INPUT:   house -- The house type number to look up.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the house object that the house number represents.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseClass * HouseClass::As_Pointer(HousesType house)\n{\n\tif (house != HOUSE_NONE) {\n\t\tfor (int index = 0; index < Houses.Count(); index++) {\n\t\t\tif (Houses.Ptr(index)->Class->House == house) {\n\t\t\t\treturn(Houses.Ptr(index));\n\t\t\t}\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::One_Time -- Handles one time initialization of the house array.                 *\n *                                                                                             *\n *    This basically calls the constructor for each of the houses in the game. All other       *\n *    data specific to the house is initialized when the scenario is loaded.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this ONCE at the beginning of the game.                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::One_Time(void)\n{\n\tBuildChoice.Set_Heap(STRUCT_COUNT);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.          *\n *                                                                                             *\n *    The handicap rating will affect combat, movement, and production for the house. It can   *\n *    either make it more or less difficult for the house (controlled by the handicap value).  *\n *                                                                                             *\n * INPUT:   handicap -- The handicap value to assign to this house. The default value for      *\n *                      a house is DIFF_NORMAL.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the old handicap value.                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *   10/22/1996 JLB : Uses act like value for multiplay only.                                  *\n *=============================================================================================*/\nDiffType HouseClass::Assign_Handicap(DiffType handicap)\n{\n\tDiffType old = Difficulty;\n\tDifficulty = handicap;\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tHouseTypeClass const * hptr = &HouseTypeClass::As_Reference(ActLike);\n\t\tFirepowerBias = hptr->FirepowerBias * Rule.Diff[handicap].FirepowerBias;\n\t\tGroundspeedBias = hptr->GroundspeedBias * Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;\n\t\tAirspeedBias = hptr->AirspeedBias * Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;\n\t\tArmorBias = hptr->ArmorBias * Rule.Diff[handicap].ArmorBias;\n\t\tROFBias = hptr->ROFBias * Rule.Diff[handicap].ROFBias;\n\t\tCostBias = hptr->CostBias * Rule.Diff[handicap].CostBias;\n\t\tRepairDelay = Rule.Diff[handicap].RepairDelay;\n\t\tBuildDelay = Rule.Diff[handicap].BuildDelay;\n\t\tBuildSpeedBias = hptr->BuildSpeedBias * Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;\n\t} else {\n\t\tFirepowerBias = Rule.Diff[handicap].FirepowerBias;\n\t\tGroundspeedBias = Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;\n\t\tAirspeedBias = Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;\n\t\tArmorBias = Rule.Diff[handicap].ArmorBias;\n\t\tROFBias = Rule.Diff[handicap].ROFBias;\n\t\tCostBias = Rule.Diff[handicap].CostBias;\n\t\tRepairDelay = Rule.Diff[handicap].RepairDelay;\n\t\tBuildDelay = Rule.Diff[handicap].BuildDelay;\n\t\tBuildSpeedBias = Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;\n\t}\n\n\treturn(old);\n}\n\n\n\n#ifdef CHEAT_KEYS\n\nvoid HouseClass::Print_Zone_Stats(int x, int y, ZoneType zone, MonoClass * mono) const\n{\n\tmono->Set_Cursor(x, y);\n\tmono->Printf(\"A:%-5d I:%-5d V:%-5d\", ZoneInfo[zone].AirDefense, ZoneInfo[zone].InfantryDefense, ZoneInfo[zone].ArmorDefense);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                   *\n *                                                                                             *\n *    This utility function will output the current status of the house class to the mono      *\n *    screen. Through this information bugs may be fixed or detected.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_HOUSE));\n\n\tmono->Set_Cursor(1, 1);mono->Printf(\"[%d]%14.14s\", Class->House, Name());\n\tmono->Set_Cursor(20, 1);mono->Printf(\"[%d]%13.13s\", ActLike, HouseTypeClass::As_Reference(ActLike).Name());\n\tmono->Set_Cursor(39, 1);mono->Printf(\"%2d\", Control.TechLevel);\n\tmono->Set_Cursor(45, 1);mono->Printf(\"%2d\", Difficulty);\n\tmono->Set_Cursor(52, 1);mono->Printf(\"%2d\", State);\n\tmono->Set_Cursor(58, 1);mono->Printf(\"%2d\", Blockage);\n\tmono->Set_Cursor(65, 1);mono->Printf(\"%2d\", IQ);\n\tmono->Set_Cursor(72, 1);mono->Printf(\"%5d\", (long)RepairTimer);\n\n\tmono->Set_Cursor(1, 3);mono->Printf(\"%08X\", AScan);\n\tmono->Set_Cursor(10, 3);mono->Printf(\"%8.8s\", (BuildAircraft == AIRCRAFT_NONE) ? \" \" : AircraftTypeClass::As_Reference(BuildAircraft).Graphic_Name());\n\tmono->Set_Cursor(21, 3);mono->Printf(\"%3d\", CurAircraft);\n\tmono->Set_Cursor(27, 3);mono->Printf(\"%8d\", Credits);\n\tmono->Set_Cursor(37, 3);mono->Printf(\"%5d\", Power);\n\tmono->Set_Cursor(45, 3);mono->Printf(\"%04X\", RadarSpied);\n\tmono->Set_Cursor(52, 3);mono->Printf(\"%5d\", PointTotal);\n\tmono->Set_Cursor(62, 3);mono->Printf(\"%5d\", (long)TeamTime);\n\tmono->Set_Cursor(71, 3);mono->Printf(\"%5d\", (long)AlertTime);\n\n\tmono->Set_Cursor(1, 5);mono->Printf(\"%08X\", BScan);\n\tmono->Set_Cursor(10, 5);mono->Printf(\"%8.8s\", (BuildStructure == STRUCT_NONE) ? \" \" : BuildingTypeClass::As_Reference(BuildStructure).Graphic_Name());\n\tmono->Set_Cursor(21, 5);mono->Printf(\"%3d\", CurBuildings);\n\tmono->Set_Cursor(27, 5);mono->Printf(\"%8d\", Tiberium);\n\tmono->Set_Cursor(37, 5);mono->Printf(\"%5d\", Drain);\n\tmono->Set_Cursor(44, 5);mono->Printf(\"%16.16s\", QuarryName[PreferredTarget]);\n\tmono->Set_Cursor(62, 5);mono->Printf(\"%5d\", (long)TriggerTime);\n\tmono->Set_Cursor(71, 5);mono->Printf(\"%5d\", (long)BorrowedTime);\n\n\tmono->Set_Cursor(1, 7);mono->Printf(\"%08X\", UScan);\n\tmono->Set_Cursor(10, 7);mono->Printf(\"%8.8s\", (BuildUnit == UNIT_NONE) ? \" \" : UnitTypeClass::As_Reference(BuildUnit).Graphic_Name());\n\tmono->Set_Cursor(21, 7);mono->Printf(\"%3d\", CurUnits);\n\tmono->Set_Cursor(27, 7);mono->Printf(\"%8d\", Control.InitialCredits);\n\tmono->Set_Cursor(38, 7);mono->Printf(\"%5d\", UnitsLost);\n\tmono->Set_Cursor(44, 7);mono->Printf(\"%08X\", Allies);\n\tmono->Set_Cursor(71, 7);mono->Printf(\"%5d\", (long)Attack);\n\n\tmono->Set_Cursor(1, 9);mono->Printf(\"%08X\", IScan);\n\tmono->Set_Cursor(10, 9);mono->Printf(\"%8.8s\", (BuildInfantry == INFANTRY_NONE) ? \" \" : InfantryTypeClass::As_Reference(BuildInfantry).Graphic_Name());\n\tmono->Set_Cursor(21, 9);mono->Printf(\"%3d\", CurInfantry);\n\tmono->Set_Cursor(27, 9);mono->Printf(\"%8d\", Capacity);\n\tmono->Set_Cursor(38, 9);mono->Printf(\"%5d\", BuildingsLost);\n\tmono->Set_Cursor(45, 9);mono->Printf(\"%4d\", Radius / CELL_LEPTON_W);\n\tmono->Set_Cursor(71, 9);mono->Printf(\"%5d\", (long)AITimer);\n\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%08X\", VScan);\n\tmono->Set_Cursor(10, 11);mono->Printf(\"%8.8s\", (BuildVessel == VESSEL_NONE) ? \" \" : VesselTypeClass::As_Reference(BuildVessel).Graphic_Name());\n\tmono->Set_Cursor(21, 11);mono->Printf(\"%3d\", CurVessels);\n\tmono->Set_Cursor(54, 11);mono->Printf(\"%04X\", Coord_Cell(Center));\n\tmono->Set_Cursor(71, 11);mono->Printf(\"%5d\", (long)DamageTime);\n\n\n\tfor (int index = 0; index < ARRAY_SIZE(Scen.GlobalFlags); index++) {\n\t\tmono->Set_Cursor(1+index, 15);\n\t\tif (Scen.GlobalFlags[index] != 0) {\n\t\t\tmono->Print(\"1\");\n\t\t} else {\n\t\t\tmono->Print(\"0\");\n\t\t}\n\t\tif (index >= 24) break;\n\t}\n\tif (Enemy != HOUSE_NONE) {\n\t\tchar const * name = \"\";\n\t\tname = HouseClass::As_Pointer(Enemy)->Name();\n\t\tmono->Set_Cursor(53, 15);mono->Printf(\"[%d]%21.21s\", Enemy, HouseTypeClass::As_Reference(Enemy).Name());\n\t}\n\n\tPrint_Zone_Stats(27, 11, ZONE_NORTH, mono);\n\tPrint_Zone_Stats(27, 13, ZONE_CORE, mono);\n\tPrint_Zone_Stats(27, 15, ZONE_SOUTH, mono);\n\tPrint_Zone_Stats(1, 13, ZONE_WEST, mono);\n\tPrint_Zone_Stats(53, 13, ZONE_EAST, mono);\n\n\tmono->Fill_Attrib(1, 17, 12, 1, IsActive ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 18, 12, 1, IsHuman ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 19, 12, 1, IsPlayerControl ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 20, 12, 1, IsAlerted ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 21, 12, 1, IsDiscovered ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 22, 12, 1, IsMaxedOut ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(14, 17, 12, 1, IsDefeated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 18, 12, 1, IsToDie ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 19, 12, 1, IsToWin ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 20, 12, 1, IsToLose ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 21, 12, 1, IsCivEvacuated ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 22, 12, 1, IsRecalcNeeded ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(27, 17, 12, 1, IsVisionary ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 18, 12, 1, IsTiberiumShort ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 19, 12, 1, IsSpied ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 20, 12, 1, IsThieved ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 21, 12, 1, IsGPSActive ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(27, 22, 12, 1, IsStarted ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tmono->Fill_Attrib(40, 17, 12, 1, IsResigner ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 18, 12, 1, IsGiverUpper ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 19, 12, 1, IsBuiltSomething ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(40, 20, 12, 1, IsBaseBuilding ? MonoClass::INVERSE : MonoClass::NORMAL);\n}\n#endif\n\n\n/***********************************************************************************************\n * HouseClass::new -- Allocator for a house class.                                             *\n *                                                                                             *\n *    This is the allocator for a house class. Since there can be only                         *\n *    one of each type of house, this is allocator has restricted                              *\n *    functionality. Any attempt to allocate a house structure for a                           *\n *    house that already exists, just returns a pointer to the previously                      *\n *    allocated house.                                                                         *\n *                                                                                             *\n * INPUT:   house -- The house to allocate a class object for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated class object.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * HouseClass::operator new(size_t)\n{\n\tvoid * ptr = Houses.Allocate();\n\tif (ptr) {\n\t\t((HouseClass *)ptr)->IsActive = true;\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * HouseClass::delete -- Deallocator function for a house object.                              *\n *                                                                                             *\n *    This function marks the house object as \"deallocated\". Such a                            *\n *    house object is available for reallocation later.                                        *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the house object to deallocate.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((HouseClass *)ptr)->IsActive = false;\n\t}\n\tHouses.Free((HouseClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * HouseClass::HouseClass -- Constructor for a house object.                                   *\n *                                                                                             *\n *    This function is the constructor and it marks the house object                           *\n *    as being allocated.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#define \tVOX_NOT_READY\tVOX_NONE\nHouseClass::HouseClass(HousesType house) :\n\tRTTI(RTTI_HOUSE),\n\tID(Houses.ID(this)),\n\tClass(HouseTypes.Ptr(house)),\n\tDifficulty(Scen.CDifficulty),\n\tFirepowerBias(1),\n\tGroundspeedBias(1),\n\tAirspeedBias(1),\n\tArmorBias(1),\n\tROFBias(1),\n\tCostBias(1),\n\tBuildSpeedBias(1),\n\tRepairDelay(0),\n\tBuildDelay(0),\n\tActLike(Class->House),\n\tIsHuman(false),\n\tWasHuman(false),\n\tIsPlayerControl(false),\n\tIsStarted(false),\n\tIsAlerted(false),\n\tIsBaseBuilding(false),\n\tIsDiscovered(false),\n\tIsMaxedOut(false),\n\tIsDefeated(false),\n\tIsToDie(false),\n\tIsToLose(false),\n\tIsToWin(false),\n\tIsCivEvacuated(false),\n\tIsRecalcNeeded(true),\n\tIsVisionary(false),\n\tIsTiberiumShort(false),\n\tIsSpied(false),\n\tIsThieved(false),\n\tIsGPSActive(false),\n\tIsBuiltSomething(false),\n\tIsResigner(false),\n\tIsGiverUpper(false),\n\tIsParanoid(false),\n\tIsToLook(true),\n\tIsQueuedMovementToggle(false),\n\tDidRepair(false),\n\tIQ(Control.IQ),\n\tState(STATE_BUILDUP),\n\tJustBuiltStructure(STRUCT_NONE),\n\tJustBuiltInfantry(INFANTRY_NONE),\n\tJustBuiltUnit(UNIT_NONE),\n\tJustBuiltAircraft(AIRCRAFT_NONE),\n\tJustBuiltVessel(VESSEL_NONE),\n\tBlockage(0),\n\tRepairTimer(0),\n\tAlertTime(0),\n\tBorrowedTime(0),\n\tBScan(0),\n\tActiveBScan(0),\n\tOldBScan(0),\n\tUScan(0),\n\tActiveUScan(0),\n\tOldUScan(0),\n\tIScan(0),\n\tActiveIScan(0),\n\tOldIScan(0),\n\tAScan(0),\n\tActiveAScan(0),\n\tOldAScan(0),\n\tVScan(0),\n\tActiveVScan(0),\n\tOldVScan(0),\n\tCreditsSpent(0),\n\tHarvestedCredits(0),\n\tStolenBuildingsCredits(0),\n\tCurUnits(0),\n\tCurBuildings(0),\n\tCurInfantry(0),\n\tCurVessels(0),\n\tCurAircraft(0),\n\tTiberium(0),\n\tCredits(0),\n\tCapacity(0),\n\tAircraftTotals(NULL),\n\tInfantryTotals(NULL),\n\tUnitTotals(NULL),\n\tBuildingTotals(NULL),\n\tVesselTotals(NULL),\n\tDestroyedAircraft(NULL),\n\tDestroyedInfantry(NULL),\n\tDestroyedUnits(NULL),\n\tDestroyedBuildings(NULL),\n\tDestroyedVessels(NULL),\n\tCapturedBuildings(NULL),\n\tTotalCrates(NULL),\n\tAircraftFactories(0),\n\tInfantryFactories(0),\n\tUnitFactories(0),\n\tBuildingFactories(0),\n\tVesselFactories(0),\n\tPower(0),\n\tDrain(0),\n\tAircraftFactory(-1),\n\tInfantryFactory(-1),\n\tUnitFactory(-1),\n\tBuildingFactory(-1),\n\tVesselFactory(-1),\n\tRadar(RADAR_NONE),\n\tFlagLocation(TARGET_NONE),\n\tFlagHome(0),\n\tUnitsLost(0),\n\tBuildingsLost(0),\n\tWhoLastHurtMe(house),\n\tStartLocationOverride(-1),\n\tCenter(0),\n\tRadius(0),\n\tLATime(0),\n\tLAType(RTTI_NONE),\n\tLAZone(ZONE_NONE),\n\tLAEnemy(HOUSE_NONE),\n\tToCapture(TARGET_NONE),\n\tRadarSpied(0),\n\tPointTotal(0),\n\tPreferredTarget(QUARRY_ANYTHING),\n\tScreenShakeTime(0),\n\tAttack(0),\n\tEnemy(HOUSE_NONE),\n\tAITimer(0),\n\tUnitToTeleport(0),\n\tBuildStructure(STRUCT_NONE),\n\tBuildUnit(UNIT_NONE),\n\tBuildInfantry(INFANTRY_NONE),\n\tBuildAircraft(AIRCRAFT_NONE),\n\tBuildVessel(VESSEL_NONE),\n\tNukeDest(0),\n\tAllies(0),\n\tDamageTime(TICKS_PER_MINUTE * Rule.DamageDelay),\n\tTeamTime(TICKS_PER_MINUTE * Rule.TeamDelay),\n\tTriggerTime(0),\n\tSpeakAttackDelay(1),\n\tSpeakPowerDelay(1),\n\tSpeakMoneyDelay(1),\n\tSpeakMaxedDelay(1),\n\tRemapColor(Class->RemapColor),\n\tDebugUnlockBuildables(false)\n{\n\t/*\n\t**\tExplicit in-place construction of the super weapons is\n\t**\trequired here because the default constructor for super\n\t**\tweapons must serve as a no-initialization constructor (save/load reasons).\n\t*/\n\tnew (&SuperWeapon[SPC_NUCLEAR_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.NukeTime, true, VOX_ABOMB_PREPPING, VOX_ABOMB_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_SONAR_PULSE]) SuperClass(TICKS_PER_MINUTE * Rule.SonarTime, false, VOX_NONE, VOX_SONAR_AVAILABLE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_CHRONOSPHERE]) SuperClass(TICKS_PER_MINUTE * Rule.ChronoTime, true, VOX_CHRONO_CHARGING, VOX_CHRONO_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_PARA_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.ParaBombTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_PARA_INFANTRY]) SuperClass(TICKS_PER_MINUTE * Rule.ParaInfantryTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_SPY_MISSION]) SuperClass(TICKS_PER_MINUTE * Rule.SpyTime, false, VOX_NONE, VOX_SPY_PLANE, VOX_NOT_READY, VOX_NOT_READY);\n\tnew (&SuperWeapon[SPC_IRON_CURTAIN]) SuperClass(TICKS_PER_MINUTE * Rule.IronCurtainTime, true, VOX_IRON_CHARGING, VOX_IRON_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\tnew (&SuperWeapon[SPC_GPS]) SuperClass(TICKS_PER_MINUTE * Rule.GPSTime, true, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);\n\n\tmemset(UnitsKilled, '\\0', sizeof(UnitsKilled));\n\tmemset(BuildingsKilled, '\\0', sizeof(BuildingsKilled));\n\tmemset(BQuantity, '\\0', sizeof(BQuantity));\n\tmemset(UQuantity, '\\0', sizeof(UQuantity));\n\tmemset(IQuantity, '\\0', sizeof(IQuantity));\n\tmemset(AQuantity, '\\0', sizeof(AQuantity));\n\tmemset(VQuantity, '\\0', sizeof(VQuantity));\n\tstrcpy(IniName, Text_String(TXT_COMPUTER));\t// Default computer name.\n\tHouseTriggers[house].Clear();\n\tmemset((void *)&Regions[0], 0x00, sizeof(Regions));\n\tMake_Ally(house);\n\tAssign_Handicap(Scen.CDifficulty);\n\n\t/*\n\t**\tSet the time of the first AI attack.\n\t*/\n\tAttack = Rule.AttackDelay * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n\n\tInit_Unit_Trackers();\n}\n\n\n/***********************************************************************************************\n * HouseClass::~HouseClass -- House class destructor                                           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/6/96 4:48PM ST : Created                                                               *\n *=============================================================================================*/\nHouseClass::~HouseClass (void)\n{\n\tClass = 0;\n\n\tFree_Unit_Trackers();\n}\n\n\n/***********************************************************************************************\n * HouseStaticClass::HouseStaticClass -- Default constructor for house static class.           *\n *                                                                                             *\n *    This is the default constructor that initializes all the values to their default         *\n *    settings.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHouseStaticClass::HouseStaticClass(void) :\n\tIQ(0),\n\tTechLevel(1),\n\tAllies(0),\n\tMaxUnit(Rule.UnitMax/6),\n\tMaxBuilding(Rule.BuildingMax/6),\n\tMaxInfantry(Rule.InfantryMax/6),\n\tMaxVessel(Rule.VesselMax/6),\n\tMaxAircraft(Rule.UnitMax/6),\n\tInitialCredits(0),\n\tEdge(SOURCE_NORTH)\n{\n}\n\n\n/***********************************************************************************************\n * HouseClass::Can_Build -- General purpose build legality checker.                            *\n *                                                                                             *\n *    This routine is called when it needs to be determined if the specified object type can   *\n *    be built by this house. Production and sidebar maintenance use this routine heavily.     *\n *                                                                                             *\n * INPUT:   type  -- Pointer to the type of object that legality is to be checked for.         *\n *                                                                                             *\n *          house -- This is the house to check for legality against. Note that this might     *\n *                   not be 'this' house since the check could be from a captured factory.     *\n *                   Captured factories build what the original owner of them could build.     *\n *                                                                                             *\n * OUTPUT:  Can the specified object be built?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *   08/12/1995 JLB : Updated for GDI building sandbag walls in #9.                            *\n *   10/23/1996 JLB : Hack to allow Tanya to both sides in multiplay.                          *\n *   11/04/1996 JLB : Computer uses prerequisite record.                                       *\n *=============================================================================================*/\nbool HouseClass::Can_Build(ObjectTypeClass const * type, HousesType house) const\n{\n\tassert(Houses.ID(this) == ID);\n\tassert(type != NULL);\n\n\t/*\n\t**\tAn object with a prohibited tech level availability will never be allowed, regardless\n\t**\tof who requests it.\n\t*/\n\tif (((TechnoTypeClass const *)type)->Level == -1) return(false);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t/*\n\t** If this is a CounterStrike II-only unit, and we're playing a multiplayer\n\t** game in 'downshifted' mode against CounterStrike or Red Alert, then\n\t** don't allow building this unit.\n\t*/\n\tif (!NewUnitsEnabled) {\n\t\tswitch(type->What_Am_I()) {\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tif ( ((InfantryTypeClass *)type)->ID >= INFANTRY_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tif ( ((UnitTypeClass *)type)->ID >= UNIT_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tif ( ((VesselTypeClass *)type)->ID >= VESSEL_RA_COUNT)\n\t\t\t\t\treturn(false);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tThe computer can always build everything.\n\t*/\n\tif (!IsHuman && Session.Type == GAME_NORMAL) return(true);\n\n\t/*\n\t**\tSpecial hack to get certain objects to exist for both sides in the game.\n\t*/\n\tint own = type->Get_Ownable();\n\n\t/*\n\t**\tCheck to see if this owner can build the object type specified.\n\t*/\n\tif (((1L << house) & own) == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tPerform some equivalency fixups for the building existence flags.\n\t*/\n\tlong flags = ActiveBScan;\n\n\t/*\n\t**\tThe computer records prerequisite buildings because it can't relay on the\n\t**\tsidebar to keep track of this information.\n\t*/\n\tif (!IsHuman) {\n\t\tflags = OldBScan;\n\t}\n\n\tint pre = ((TechnoTypeClass const *)type)->Prerequisite;\n\n\t/*\n\t**\tAdvanced power also serves as a prerequisite for normal power.\n\t*/\n\tif (flags & STRUCTF_ADVANCED_POWER) flags |= STRUCTF_POWER;\n\n\t/*\n\t**\tEither tech center counts as a prerequisite.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif ((flags & (STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH)) != 0) flags |= STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH;\n\t}\n\n\tint level = Control.TechLevel;\n#ifdef CHEAT_KEYS\n\tif (Debug_Cheat) {\n\t\tlevel = 98;\n\t\tpre = 0;\n\t}\n#endif\n\n\t// ST - 8/23/2019 4:53PM\n\tif (DebugUnlockBuildables) {\n\t\tlevel = 98;\n\t\tpre = 0;\n\t}\t\t\t\n\n\t/*\n\t**\tSee if the prerequisite requirements have been met.\n\t*/\n\treturn((pre & flags) == pre && ((TechnoTypeClass const *)type)->Level <= (unsigned)level);\n}\n\n\n/***************************************************************************\n * HouseClass::Init -- init's in preparation for new scenario              *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *   12/17/1994 JLB : Resets tracker bits.                                 *\n *=========================================================================*/\nvoid HouseClass::Init(void)\n{\n\tHouses.Free_All();\n\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\tHouseTriggers[index].Clear();\n\t}\n}\n\n// Object selection list is switched with player context for GlyphX. ST - 8/7/2019 10:11AM\nextern void Logic_Switch_Player_Context(HouseClass *house);\nextern bool MPSuperWeaponDisable;\n\n/***********************************************************************************************\n * HouseClass::AI -- Process house logic.                                                      *\n *                                                                                             *\n *    This handles the AI for the house object. It should be called once per house per game    *\n *    tick. It processes all house global tasks such as low power damage accumulation and      *\n *    house specific trigger events.                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *   07/17/1995 JLB : Limits EVA speaking unless the player can do something.                  *\n *=============================================================================================*/\nextern void Recalculate_Placement_Distances();\n\nvoid HouseClass::AI(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t// Set PlayerPtr to be this house. ST - 8/7/2019 10:12AM\n\tLogic_Switch_Player_Context(this);\n\n\t/*\n\t**\tIf base building has been turned on by a trigger, then force the house to begin\n\t**\tproduction and team creation as well. This is also true if the IQ is high enough to\n\t**\tbeing base building.\n\t*/\n\tif (!IsHuman && (IsBaseBuilding || IQ >= Rule.IQProduction)) {\n\t\tIsBaseBuilding = true;\n\t\tIsStarted = true;\n\t\tIsAlerted = true;\n\t}\n\n\t/*\n\t**\tCheck to see if the house wins.\n\t*/\n\tif (Session.Type == GAME_NORMAL && IsToWin && BorrowedTime == 0 && Blockage <= 0) {\n\t\tIsToWin = false;\n\t\tif (this == PlayerPtr) {\n\t\t\tPlayerWins = true;\n\t\t} else {\n\t\t\tPlayerLoses = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the house loses.\n\t*/\n\tif (Session.Type == GAME_NORMAL && IsToLose && BorrowedTime == 0) {\n\t\tIsToLose = false;\n\t\tif (this == PlayerPtr) {\n\t\t\tPlayerLoses = true;\n\t\t} else {\n\t\t\tPlayerWins = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if all objects of this house should be blown up.\n\t*/\n\tif (IsToDie && BorrowedTime == 0) {\n\t\tIsToDie = false;\n\t\tBlowup_All();\n\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tMPlayer_Defeated();\n\t\t}\n\t}\n\n\t/*\n\t**\tDouble check power values to correct illegal conditions. It is possible to\n\t**\tget a power output of negative (one usually) as a result of damage sustained\n\t**\tand the fixed point fractional math involved with power adjustments. If the\n\t**\tpower rating drops below zero, then make it zero.\n\t*/\n\tPower = max(Power, 0);\n\tDrain = max(Drain, 0);\n\n\t/*\n\t**\tIf the base has been alerted to the enemy and should be attacking, then\n\t**\tsee if the attack timer has expired. If it has, then create the attack\n\t**\tteams.\n\t*/\n\tif (IsAlerted && AlertTime == 0) {\n\n\t\t/*\n\t\t**\tAdjusted to reduce maximum number of teams created.\n\t\t*/\n\t\tint maxteams = Random_Pick(2, (int)(((Control.TechLevel-1)/3)+1));\n\t\tfor (int index = 0; index < maxteams; index++) {\n\t\t\tTeamTypeClass const * ttype = Suggested_New_Team(true);\n\t\t\tif (ttype != NULL) {\n\t\t\t\tScenarioInit++;\n\t\t\t\tttype->Create_One_Of();\n\t\t\t\tScenarioInit--;\n\t\t\t}\n\t\t}\n\t\tAlertTime = Rule.AutocreateTime * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n//\t\tint mintime = Rule.AutocreateTime * (TICKS_PER_MINUTE/2);\n//\t\tint maxtime = Rule.AutocreateTime * (TICKS_PER_MINUTE*2);\n//\t\tAlertTime = Random_Pick(mintime, maxtime);\n\t}\n\n\t/*\n\t**\tIf this house's flag waypoint is a valid cell, see if there's\n\t**\tsomeone sitting on it.  If so, make the scatter.\n\t*/\n\tif (FlagHome != 0 && (Frame % TICKS_PER_SECOND) == 0) {\n\n\t\tTechnoClass * techno = Map[FlagHome].Cell_Techno();\n\t\tif (techno != NULL) {\n\t\t\tbool moving = false;\n\t\t\tif (techno->Is_Foot()) {\n\t\t\t\tif (Target_Legal(((FootClass *)techno)->NavCom)) {\n\t\t\t\t\tmoving = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!moving) {\n\t\t\t\ttechno->Scatter(0, true, true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCreate teams for this house if necessary.\n\t** (Use the same timer for some extra capture-the-flag logic.)\n\t*/\n\tif (!IsAlerted && !TeamTime) {\n\n\t\tTeamTypeClass const * ttype = Suggested_New_Team(false);\n\t\tif (ttype) {\n\t\t\tttype->Create_One_Of();\n\t\t}\n\n\t\tTeamTime = Rule.TeamDelay * TICKS_PER_MINUTE;\n\t}\n\n\t/*\n\t**\tIf there is insufficient power, then all buildings that are above\n\t**\thalf strength take a little bit of damage.\n\t*/\n\tif (DamageTime == 0) {\n\n\t\t/*\n\t\t**\tWhen the power is below required, then the buildings will take damage over\n\t\t**\ttime.\n\t\t*/\n\t\tif (Power_Fraction() < 1) {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass & b = *Buildings.Ptr(index);\n\n\t\t\t\tif (b.House == this && b.Health_Ratio() > Rule.ConditionYellow) {\n\t\t\t\t\t// BG: Only damage buildings that require power, to keep the\n\t\t\t\t\t//     land mines from blowing up under low-power conditions\n\t\t\t\t\tif (b.Class->Drain) {\n\t\t\t\t\t\tint damage = 1;\n\t\t\t\t\t\tb.Take_Damage(damage, 0, WARHEAD_AP, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tDamageTime = TICKS_PER_MINUTE * Rule.DamageDelay;\n\t}\n\n\t/*\n\t**\tIf there are no more buildings to sell, then automatically cancel the\n\t**\tsell mode.\n\t*/\n\tif (PlayerPtr == this && !ActiveBScan && Map.IsSellMode) {\n\t\tMap.Sell_Mode_Control(0);\n\t}\n\n\t/*\n\t**\tVarious base conditions may be announced to the player. Typically, this would be\n\t**\tlow tiberium capacity or low power.\n\t*/\n\tif (PlayerPtr == this) {\n\n\t\tif (SpeakMaxedDelay == 0 && Available_Money() < 100 && UnitFactories+BuildingFactories+InfantryFactories > 0) {\n\t\t\tSpeak(VOX_NEED_MO_MONEY);\n\t\t\tMap.Flash_Money();\n\t\t\tSpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\n\t\t\tint text_id = TXT_INSUFFICIENT_FUNDS;\n\t\t\tchar const * text = Text_String(TXT_INSUFFICIENT_FUNDS);\n\t\t\tif (text != NULL) {\n\t\t\t\tSession.Messages.Add_Message(NULL, text_id, text, PCOLOR_GREEN, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\t}\n\t\t}\n\n\t\tif (SpeakMaxedDelay == 0 && IsMaxedOut) {\n\t\t\tIsMaxedOut = false;\n\t\t\tif ((Capacity - Tiberium) < 300 && Capacity > 500 && (ActiveBScan & (STRUCTF_REFINERY | STRUCTF_CONST))) {\n \t\t\t\tSpeak(VOX_NEED_MO_CAPACITY);\n\t\t\t\tSpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\t\t\t}\n\t\t}\n\t\tif (SpeakPowerDelay == 0 && Power_Fraction() < 1) {\n\t\t\tif (ActiveBScan & STRUCTF_CONST) {\n\t\t\t\tSpeak(VOX_LOW_POWER);\n\t\t\t\tSpeakPowerDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);\n\t\t\t\tMap.Flash_Power();\n\n\t\t\t\tint text_id = -1;\n\t\t\t\tchar const * text = NULL;\n\t\t\t\tif (BQuantity[STRUCT_AAGUN] > 0) {\n\t\t\t\t\ttext = Text_String(TXT_POWER_AAGUN);\n\t\t\t\t\ttext_id = TXT_POWER_AAGUN;\n\t\t\t\t}\n\t\t\t\tif (BQuantity[STRUCT_TESLA] > 0) {\n\t\t\t\t\ttext = Text_String(TXT_POWER_TESLA);\n\t\t\t\t\ttext_id = TXT_POWER_TESLA;\n\t\t\t\t}\n\t\t\t\tif (text == NULL) {\n\t\t\t\t\ttext = Text_String(TXT_LOW_POWER);\n\t\t\t\t\ttext_id = TXT_LOW_POWER;\n\t\t\t\t}\n\t\t\t\tif (text != NULL) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, text_id, text, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a flag associated with this house, then mark it to be\n\t**\tredrawn.\n\t*/\n\tif (Target_Legal(FlagLocation)) {\n\t\tUnitClass * unit = As_Unit(FlagLocation);\n\t\tif (unit) {\n\t\t\tunit->Mark(MARK_CHANGE);\n\t\t} else {\n\t\t\tCELL cell = As_Cell(FlagLocation);\n\t\t\tMap[cell].Flag_Update();\n\t\t\tMap[cell].Redraw_Objects();\n\t\t}\n\t}\n\n\tbool is_time = false;\n\n\t/*\n\t**\tTriggers are only checked every so often. If the trigger timer has expired,\n\t**\tthen set the trigger processing flag.\n\t*/\n\tif (TriggerTime == 0 || IsBuiltSomething) {\n\t\tis_time = true;\n\t\tTriggerTime = TICKS_PER_MINUTE/10;\n\t\tIsBuiltSomething = false;\n\t}\n\n\t/*\n\t**\tProcess any super weapon logic required.\n\t*/\n\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER || !MPSuperWeaponDisable) {\n\t\tSuper_Weapon_Handler();\n\t}\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tif( (Session.Type != GAME_NORMAL || !IsHuman) && Scen.AutoSonarTimer == 0 )\n\t{\n\t\t//\tIf house has nothing but subs left, do an automatic sonar pulse to reveal them.\n\t\tif( VQuantity[ VESSEL_SS ] > 0 )\t\t//\tIncludes count of VESSEL_MISSILESUBs. ajw\n\t\t{\n\t\t\tint iCount = 0;\n\t\t\tint i;\n\t\t\tfor( i = 0; i != STRUCT_COUNT-3; ++i )\n\t\t\t{\n\t\t\t\tiCount += BQuantity[ i ];\n\t\t\t}\n\t\t\tif( !iCount )\n\t\t\t{\n\t\t\t\tfor( i = 0; i != UNIT_RA_COUNT-3; ++i )\n\t\t\t\t{\n\t\t\t\t\tiCount += UQuantity[ i ];\n\t\t\t\t}\n\t\t\t\tif( !iCount )\n\t\t\t\t{\n\t\t\t\t\t//\tajw - Found bug - house's civilians are not removed from IQuantity when they die.\n\t\t\t\t\t//\tWorkaround...\n\t\t\t\t\tfor( i = 0; i <= INFANTRY_DOG; ++i )\n\t\t\t\t\t{\n\t\t\t\t\t\tiCount += IQuantity[ i ];\n\t\t\t\t\t}\n\t\t\t\t\tif( !iCount )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor( i = 0; i != AIRCRAFT_COUNT; ++i )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiCount += AQuantity[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( !iCount )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor( i = 0; i != VESSEL_RA_COUNT; ++i )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif( i != VESSEL_SS )\n\t\t\t\t\t\t\t\t\tiCount += VQuantity[ i ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( !iCount )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tDo the ping.\n\t\t\t\t\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\t\t\t\t\tVesselClass * sub = Vessels.Ptr(index);\n\t\t\t\t\t\t\t\t\tif (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {\n\t\t\t\t\t\t\t\t\t\tsub->PulseCountDown = 15 * TICKS_PER_SECOND;\n\t\t\t\t\t\t\t\t\t\tsub->Do_Uncloak();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbAutoSonarPulse = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tif (Session.Type != GAME_NORMAL) {\n\t\tCheck_Pertinent_Structures();\n\t}\n\n\t/*\n\t** Special win/lose check for multiplayer games; by-passes the\n\t** trigger system.  We must wait for non-zero frame, because init\n\t** may not properly set IScan etc for each house; you have to go\n\t** through each object's AI before it will be properly set.\n\t*/\n\tif (Session.Type != GAME_NORMAL && !IsDefeated &&\n\t\t!ActiveBScan && !ActiveAScan && !UScan && !ActiveIScan && !ActiveVScan && Frame > 0) {\n\t\tMPlayer_Defeated();\n\t}\n\n\t/*\n\t**\tTry to spring all events attached to this house. The triggers will check\n\t**\tfor themselves if they actually need to be sprung or not.\n\t*/\n\tfor (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {\n\t\tif (HouseTriggers[Class->House][index]->Spring() && index > 0) {\n\t\t\tindex--;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf a radar facility is not present, but the radar is active, then turn the radar off.\n\t**\tThe radar also is turned off when the power gets below 100% capacity.\n\t*/\n\tif (PlayerPtr == this) {\n\t\tbool jammed = true;\n\n\t\t/*\n\t\t** Find if there are any radar facilities, and if they're jammed or not\n\t\t*/\n\n\t\tif (IsGPSActive) {\n\t\t\tjammed = false;\n\t\t} else {\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n#ifdef FIXIT_RADAR_JAMMED\n\t\t\t\tif (building != NULL && !building->IsInLimbo && building->House == PlayerPtr) {\n#else\n\t\t\t\tif (building && building->House == PlayerPtr) {\n#endif\n\t\t\t\t\tif (*building == STRUCT_RADAR /* || *building == STRUCT_EYE */) {\n\t\t\t\t\t\tif (!building->IsJammed) {\n\t\t\t\t\t\t\tjammed = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tMap.Set_Jammed(this, jammed);\n// Need to add in here where we activate it when only GPS is active.\n\t\tif (Map.Is_Radar_Active()) {\n\t\t\tif (ActiveBScan & STRUCTF_RADAR) {\n\t\t\t\tif (Power_Fraction() < 1 && !IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(0);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (IsGPSActive || (ActiveBScan & STRUCTF_RADAR)) {\n\t\t\t\tif (Power_Fraction() >= 1 || IsGPSActive) {\n\t\t\t\t\tMap.Radar_Activate(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Map.Is_Radar_Existing()) {\n\t\t\t\t\tMap.Radar_Activate(4);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!IsGPSActive && !(ActiveBScan & STRUCTF_RADAR)) {\n\t\t\tRadar = RADAR_NONE;\n\t\t} else {\n\t\t\tRadar = (Map.Is_Radar_Active() || Map.Is_Radar_Activating()) ? RADAR_ON : RADAR_OFF;\n\t\t}\n\t}\n\n\tVisibleCredits.AI(false, this, true);\n\n\t/*\n\t**\tPerform any expert system AI processing.\n\t*/\n\tif (IsBaseBuilding && AITimer == 0) {\n\t\tAITimer = Expert_AI();\n\t}\n\n\tif (!IsBaseBuilding && State == STATE_ENDGAME) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t}\n\n\tAI_Building();\n\tAI_Unit();\n\tAI_Vessel();\n\tAI_Infantry();\n\tAI_Aircraft();\n\n\n\t/*\n\t**\tIf the production possibilities need to be recalculated, then do so now. This must\n\t**\toccur after the scan bits have been properly updated.\n\t*/\n\tif (PlayerPtr == this && IsRecalcNeeded) {\n\t\tIsRecalcNeeded = false;\n\t\tMap.Recalc();\n\n\t\t/*\n\t\t**\tThis placement might affect any prerequisite requirements for construction\n\t\t**\tlists. Update the buildable options accordingly.\n\t\t*/\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\tif (building && building->Strength > 0 && building->Owner() == Class->House && building->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION) {\n\n\t\t\t\tif (PlayerPtr == building->House) {\n\t\t\t\t\tbuilding->Update_Buildables();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tRecalculate_Placement_Distances();\n\t\tCheck_Pertinent_Structures();\n\t}\n\n\t/*\n\t** See if it's time to re-set the can-repair flag\n\t*/\n\tif (DidRepair && RepairTimer == 0) {\n\t\tDidRepair = false;\n\t}\n\n\tif (this == PlayerPtr && IsToLook) {\n\t\tIsToLook = false;\n\t\tMap.All_To_Look(PlayerPtr);\n\t}\n}\n\n/***********************************************************************************************\n * HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.    *\n *                                                                                             *\n *    This handles any super weapons assigned to this house. It also performs any necessary    *\n *    maintenance that the super weapons require.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Super_Weapon_Handler(void)\n{\n\t/*\n\t**\tPerform all super weapon AI processing. This just checks to see if\n\t**\tthe graphic needs changing for the special weapon and updates the\n\t**\tsidebar as necessary.\n\t*/\n\tfor (SpecialWeaponType special = SPC_FIRST; special < SPC_COUNT; special++) {\n\t\tSuperClass * super = &SuperWeapon[special];\n\n\t\tif (super->Is_Present()) {\n\n\t\t\t/*\n\t\t\t**\tPerform any charge-up logic for the super weapon. If the super\n\t\t\t**\tweapon is owned by the player and a graphic change is detected, then\n\t\t\t**\tflag the sidebar to be redrawn so the player will see the change.\n\t\t\t*/\n\t\t\tif (super->AI(this == PlayerPtr)) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRepeating super weapons that require power will be suspended if there\n\t\t\t**\tis insufficient power available.\n\t\t\t*/\n\t\t\tif (!super->Is_Ready() && super->Is_Powered() && !super->Is_One_Time()) {\n\t\t\t\tsuper->Suspend(Power_Fraction() < 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Check to see if they have launched the GPS, but subsequently lost their\n\t** tech center.  If so, remove the GPS, and shroud the map.\n\t*/\n\tif (IsGPSActive && !(ActiveBScan & STRUCTF_ADVANCED_TECH) ) {\n\t\tIsGPSActive = false;\n\n\t\t/*\n\t\t** Updated for client/server multiplayer. ST  - 8/12/2019 11:32AM\n\t\t*/\n\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tif (IsPlayerControl) {\n\t\t\t\tMap.Shroud_The_Map(PlayerPtr);\n\t\t\t}\n\t\t\n\t\t} else {\n\t\t\t\n\t\t\tif (IsHuman) {\n\t\t\t\tMap.Shroud_The_Map(this);\n\t\t\t}\n\t\t}\t\n\t}\n\n\t/*\n\t**\tCheck to see if the GPS Satellite should be removed from the sidebar\n\t**\tbecause of outside circumstances. The advanced technology facility\n\t**\tbeing destroyed is a good example of this.  Having fired the satellite\n\t** is another good example, because it's a one-shot item.\n\t*/\n\tif (SuperWeapon[SPC_GPS].Is_Present()) {\n\t\tif (!(ActiveBScan & STRUCTF_ADVANCED_TECH) || IsGPSActive || IsDefeated) {\n\t\t\t/*\n\t\t\t**\tRemove the missile capability when there is no advanced tech facility.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_GPS].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t** Auto-fire the GPS satellite if it's charged up.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_GPS].Is_Ready()) {\n\t\t\t\tSuperWeapon[SPC_GPS].Discharged(this == PlayerPtr);\n\t\t\t\tif (SuperWeapon[SPC_GPS].Remove()) {\n\t\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\tBuildingClass * bldg = Buildings.Ptr(index);\n\t\t\t\t\tif (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this) {\n\t\t\t\t\t\tbldg->HasFired = true;\n\t\t\t\t\t\tbldg->Assign_Mission(MISSION_MISSILE);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no GPS satellite present, but there is a GPS satellite\n\t\t**\tfacility available, then make the GPS satellite available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_ADVANCED_TECH) != 0 &&\n\t\t\t!IsGPSActive &&\n\t\t\tControl.TechLevel >= Rule.GPSTechLevel &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tbool canfire = false;\n\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass * bldg = Buildings.Ptr(index);\n\t\t\t\tif (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this && !bldg->IsInLimbo) {\n\t\t\t\t\tif (!bldg->HasFired) {\n\t\t\t\t\t\tcanfire = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (canfire) {\n\t\t\t\tSuperWeapon[SPC_GPS].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t\t/*\n\t\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t\t*/\n\t\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\tif (IsHuman) {\n\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_GPS, this);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_GPS);\n\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the chronosphere should be removed from the sidebar\n\t**\tbecause of outside circumstances. The chronosphere facility\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_CHRONOSPHERE].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_CHRONOSPHERE) && !SuperWeapon[SPC_CHRONOSPHERE].Is_One_Time()) || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the chronosphere when there is no chronosphere facility.\n\t\t\t**\tNote that this will not remove the one time created chronosphere.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_CHRONOSPHERE].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE || Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\t\tTechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);\n\t\t\t\t\t\t\tif (tech && tech->IsActive && tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#else\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_CHRONOSPHERE ||\n\t\t\t\t\t\t Map.IsTargettingMode == SPC_CHRONO2) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no chronosphere present, but there is a chronosphere\n\t\t**\tfacility available, then make the chronosphere available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_CHRONOSPHERE) &&\n//\t\t\t(ActLike == HOUSE_GOOD || Session.Type != GAME_NORMAL) &&\n\t\t\t(unsigned)Control.TechLevel >= BuildingTypeClass::As_Reference(STRUCT_CHRONOSPHERE).Level &&\n//\t\t\tControl.TechLevel >= Rule.ChronoTechLevel &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_CHRONOSPHERE].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_CHRONOSPHERE, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_CHRONOSPHERE);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the iron curtain should be removed from the sidebar\n\t**\tbecause of outside circumstances. The iron curtain facility\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_IRON_CURTAIN].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_IRON_CURTAIN) && !SuperWeapon[SPC_IRON_CURTAIN].Is_One_Time())  || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the iron curtain when there is no iron curtain facility.\n\t\t\t**\tNote that this will not remove the one time created iron curtain.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_IRON_CURTAIN].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_IRON_CURTAIN) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tIf there is no iron curtain present, but there is an iron curtain\n\t\t**\tfacility available, then make the iron curtain available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_IRON_CURTAIN) &&\n\t\t\t(ActLike == HOUSE_USSR || ActLike == HOUSE_UKRAINE || Session.Type != GAME_NORMAL) &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_IRON_CURTAIN].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_IRON_CURTAIN, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_IRON_CURTAIN);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the sonar pulse should be removed from the sidebar\n\t**\tbecause of outside circumstances. The spied-upon enemy sub pen\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_SONAR_PULSE].Is_Present()) {\n\t\tint usspy = 1 << (Class->House);\n\t\tbool present = false;\n\t\tbool powered = false;\n\t\tfor (int q = 0; q < Buildings.Count() && !powered; q++) {\n\t\t\tBuildingClass * bldg = Buildings.Ptr(q);\n\t\t\tif ((*bldg == STRUCT_SUB_PEN) && (bldg->House->Class->House != Class->House) && (bldg->Spied_By() & usspy) ) {\n\t\t\t\tpresent = true;\n\t\t\t\tpowered = !(bldg->House->Power_Fraction() < 1);\n\t\t\t}\n\t\t}\n\t\tif ( (!present && !SuperWeapon[SPC_SONAR_PULSE].Is_One_Time())  || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the sonar pulse when there is no spied-upon enemy sub pen.\n\t\t\t**\tNote that this will not remove the one time created sonar pulse.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_SONAR_PULSE].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck to see if the nuclear weapon should be removed from the sidebar\n\t**\tbecause of outside circumstances. The missile silos\n\t**\tbeing destroyed is a good example of this.\n\t*/\n\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Present()) {\n\t\tif ( (!(ActiveBScan & STRUCTF_MSLO) && !SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) || IsDefeated) {\n\n\t\t\t/*\n\t\t\t**\tRemove the nuke when there is no missile silo.\n\t\t\t**\tNote that this will not remove the one time created nuke.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Remove()) {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tif (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {\n\t\t\t\t\t\t Map.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tAllow the computer to fire the nuclear weapon when the weapon is\n\t\t\t**\tready and the owner is the computer.\n\t\t\t*/\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_NUCLEAR_BOMB);\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t**\tIf there is no nuclear missile present, but there is a missile\n\t\t**\tsilo available, then make the missile available as well.\n\t\t*/\n\t\tif ((ActiveBScan & STRUCTF_MSLO) &&\n\t\t\t((ActLike != HOUSE_USSR && ActLike != HOUSE_UKRAINE) || Session.Type != GAME_NORMAL) &&\n\t\t\t(IsHuman || IQ >= Rule.IQSuperWeapons)) {\n\n\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Enable(false, this == PlayerPtr, Power_Fraction() < 1);\n\n\t\t\t/*\n\t\t\t**\tFlag the sidebar to be redrawn if necessary.\n\t\t\t*/\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (SuperWeapon[SPC_SPY_MISSION].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (this == PlayerPtr && !SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {\n\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t}\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_SPY_MISSION);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && !Scen.IsNoSpyPlane && Control.TechLevel >= Rule.SpyPlaneTechLevel) {\n\t\t\tSuperWeapon[SPC_SPY_MISSION].Enable(false, this == PlayerPtr, false);\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_SPY_MISSION, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SPY_MISSION);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (SuperWeapon[SPC_PARA_BOMB].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_PARA_BOMB);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaBombTechLevel && Session.Type == GAME_NORMAL) {\n\t\t\tSuperWeapon[SPC_PARA_BOMB].Enable(false, this == PlayerPtr, false);\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_BOMB, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_BOMB);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Present()) {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Remove()) {\n\t\t\t\tif (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready() && !IsHuman) {\n\t\t\t\tSpecial_Weapon_AI(SPC_PARA_INFANTRY);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaInfantryTechLevel) {\n\t\t\tSuperWeapon[SPC_PARA_INFANTRY].Enable(false, this == PlayerPtr, false);\n\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\tif (IsHuman) {\n\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_INFANTRY, this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_INFANTRY);\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Attacked -- Lets player know if base is under attack.                           *\n *                                                                                             *\n *    Call this function whenever a building is attacked (with malice). This function will     *\n *    then announce to the player that his base is under attack. It checks to make sure that   *\n *    this is referring to the player's house rather than the enemy's.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Attacked(BuildingClass* source)\n{\n\tassert(Houses.ID(this) == ID);\n\n#ifdef FIXIT_BASE_ANNOUNCE\n\tif (SpeakAttackDelay == 0 && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) {\n#else\n\tif (SpeakAttackDelay == 0 && PlayerPtr->Class->House == Class->House) {\n#endif\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tSpeak(VOX_BASE_UNDER_ATTACK, NULL, source ? source->Center_Coord() : 0);\n\t\t} else {\n\t\t\tSpeak(VOX_BASE_UNDER_ATTACK, this);\n\t\t}\n\n\t\t// MBL 06.13.2020 - Timing change from 2 minute cooldown, per https://jaas.ea.com/browse/TDRA-6784\n\t\t// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay); // 2 minutes\n\t\t// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE/2); // 30 seconds as requested\n\t\tSpeakAttackDelay = Options.Normalize_Delay( (TICKS_PER_MINUTE/2)+(TICKS_PER_SECOND*5) ); // Tweaked for accuracy\n\n\t\t/*\n\t\t**\tIf there is a trigger event associated with being attacked, process it\n\t\t**\tnow.\n\t\t*/\n\t\tfor (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {\n\t\t\tHouseTriggers[Class->House][index]->Spring(TEVENT_ATTACKED);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Harvested -- Adds Tiberium to the harvest storage.                              *\n *                                                                                             *\n *    Use this routine whenever Tiberium is harvested. The Tiberium is stored equally between  *\n *    all storage capable buildings for the house. Harvested Tiberium adds to the credit       *\n *    value of the house, but only up to the maximum storage capacity that the house can       *\n *    currently maintain.                                                                      *\n *                                                                                             *\n * INPUT:   tiberium -- The number of Tiberium credits to add to the House's total.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Harvested(unsigned tiberium)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldtib = Tiberium;\n\n\tTiberium += tiberium;\n\tif (Tiberium > Capacity) {\n\t\tTiberium = Capacity;\n\t\tIsMaxedOut = true;\n\t}\n\tHarvestedCredits += tiberium;\n\tSilo_Redraw_Check(oldtib, Capacity);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Stole -- Accounts for the value of a captured building.\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Use this routine whenever a building is captured.  It keeps track of the cost of the     *\n *    building for use in the scoring routine, because you get an 'economy' boost for the      *\n *    value of the stolen building (but you don't get the credit value for it.)                *\n *                                                                                             *\n * INPUT:   worth -- The worth of the building we captured (stole).            \t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/05/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Stole(unsigned worth)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tStolenBuildingsCredits += worth;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Available_Money -- Fetches the total credit worth of the house.                 *\n *                                                                                             *\n *    Use this routine to determine the total credit value of the house. This is the sum of    *\n *    the harvested Tiberium in storage and the initial unspent cash reserves.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total credit value of the house.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong HouseClass::Available_Money(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Tiberium + Credits);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Spend_Money -- Removes money from the house.                                    *\n *                                                                                             *\n *    Use this routine to extract money from the house. Typically, this is a result of         *\n *    production spending. The money is extracted from available cash reserves first. When     *\n *    cash reserves are exhausted, then Tiberium is consumed.                                  *\n *                                                                                             *\n * INPUT:   money -- The amount of money to spend.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *   06/20/1995 JLB : Spends Tiberium before spending cash.                                    *\n *=============================================================================================*/\nvoid HouseClass::Spend_Money(unsigned money)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldtib = Tiberium;\n\tif (money > (unsigned)Tiberium) {\n\t\tmoney -= (unsigned)Tiberium;\n\t\tTiberium = 0;\n\t\tCredits -= money;\n\t} else {\n\t\tTiberium -= money;\n\t}\n\tSilo_Redraw_Check(oldtib, Capacity);\n\tCreditsSpent += money;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Refund_Money -- Refunds money to back to the house.                             *\n *                                                                                             *\n *    Use this routine when money needs to be refunded back to the house. This can occur when  *\n *    construction is aborted. At this point, the exact breakdown of Tiberium or initial       *\n *    credits used for the orignal purchase is lost. Presume as much of the money is in the    *\n *    form of Tiberium as storage capacity will allow.                                         *\n *                                                                                             *\n * INPUT:   money -- The number of credits to refund back to the house.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *   06/01/1995 JLB : Refunded money is never lost                                             *\n *=============================================================================================*/\nvoid HouseClass::Refund_Money(unsigned money)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tCredits += money;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.                 *\n *                                                                                             *\n *    Use this routine to adjust the maximum storage capacity for the house. This storage      *\n *    capacity will limit the number of Tiberium credits that can be stored at any one time.   *\n *                                                                                             *\n * INPUT:   adjust   -- The adjustment to the Tiberium storage capacity.                       *\n *                                                                                             *\n *          inanger  -- Is this a forced adjustment to capacity due to some hostile event?     *\n *                                                                                             *\n * OUTPUT:  Returns with the number of Tiberium credits lost.                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Adjust_Capacity(int adjust, bool inanger)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tlong oldcap = Capacity;\n\tint retval = 0;\n\n\tCapacity += adjust;\n\tCapacity = max(Capacity, 0L);\n\tif (Tiberium > Capacity) {\n\t\tretval = Tiberium - Capacity;\n\t\tTiberium = Capacity;\n\t\tif (!inanger) {\n\t\t\tRefund_Money(retval);\n\t\t\tretval = 0;\n\t\t} else {\n\t\t\tIsMaxedOut = true;\n\t\t}\n\t}\n\tSilo_Redraw_Check(Tiberium, oldcap);\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                    *\n *                                                                                             *\n *    Call this routine when either the capacity or tiberium levels change for a house. This   *\n *    routine will determine if the aggregate tiberium storage level will result in the        *\n *    silos changing their imagery. If this is detected, then all the silos for this house     *\n *    are flagged to be redrawn.                                                               *\n *                                                                                             *\n * INPUT:   oldtib   -- Pre-change tiberium level.                                             *\n *                                                                                             *\n *          oldcap   -- Pre-change tiberium storage capacity.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Silo_Redraw_Check(long oldtib, long oldcap)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint oldratio = 0;\n\tif (oldcap) oldratio = (oldtib * 5) / oldcap;\n\tint newratio = 0;\n\tif (Capacity) newratio = (Tiberium * 5) / Capacity;\n\n\tif (oldratio != newratio) {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\t\t\tif (b && !b->IsInLimbo && b->House == this && *b == STRUCT_STORAGE) {\n\t\t\t\tb->Mark(MARK_CHANGE);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *\n *                                                                                             *\n *    This routine will determine if the house number specified is a ally to this house.       *\n *                                                                                             *\n * INPUT:   house -- The house number to check to see if it is an ally.                        *\n *                                                                                             *\n * OUTPUT:  Is the house an ally?                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(HousesType house) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house != HOUSE_NONE) {\n\t\treturn(((1<<house) & Allies) != 0);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *\n *                                                                                             *\n *    This routine will examine the specified house and determine if it is an ally.            *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house object to check for ally relationship.               *\n *                                                                                             *\n * OUTPUT:  Is the specified house an ally?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(HouseClass const * house) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house) {\n\t\treturn(Is_Ally(house->Class->House));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Ally -- Checks to see if the object is an ally.                              *\n *                                                                                             *\n *    This routine will examine the specified object and return whether it is an ally or not.  *\n *                                                                                             *\n * INPUT:   object   -- The object to examine to see if it is an ally.                         *\n *                                                                                             *\n * OUTPUT:  Is the specified object an ally?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Ally(ObjectClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (object) {\n\t\treturn(Is_Ally(object->Owner()));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Make_Ally -- Make the specified house an ally.                                  *\n *                                                                                             *\n *    This routine will make the specified house an ally to this house. An allied house will   *\n *    not be considered a threat or potential target.                                          *\n *                                                                                             *\n * INPUT:   house -- The house to make an ally of this house.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   08/08/1995 JLB : Breaks off combat when ally commences.                                   *\n *   10/17/1995 JLB : Added reveal base when allied.                                           *\n *=============================================================================================*/\nvoid HouseClass::Make_Ally(HousesType house)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Is_Allowed_To_Ally(house)) {\n\n\t\tAllies |= (1L << house);\n\n\t\t/*\n\t\t**\tDon't consider the newfound ally to be an enemy -- of course.\n\t\t*/\n\t\tif (Enemy == house) {\n\t\t\tEnemy = HOUSE_NONE;\n\t\t}\n\n\t\tif (ScenarioInit) {\n\t\t\tControl.Allies |= (1L << house);\n\t\t}\n\n\t\tif (Session.Type != GAME_NORMAL && !ScenarioInit) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\n\t\t\t/*\n\t\t\t**\tAn alliance with another human player will cause the computer\n\t\t\t**\tplayers (if present) to become paranoid.\n\t\t\t*/\n\t\t\tif (hptr != NULL && IsHuman && Rule.IsComputerParanoid) {\n//\t\t\tif (hptr != NULL && hptr->IsHuman) {\n//\t\t\t\tif (!hptr->IsHuman) {\n//\t\t\t\t\thptr->Make_Ally(Class->House);\n//\t\t\t\t}\n\t\t\t\tComputer_Paranoid();\n\t\t\t}\n\n\t\t\tchar buffer[80];\n\n\t\t\t/*\n\t\t\t**\tSweep through all techno objects and perform a cheeseball tarcom clear to ensure\n\t\t\t**\tthat fighting will most likely stop when the cease fire begins.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\t\t\tObjectClass * object = Logic[index];\n\n\t\t\t\tif (object != NULL && object->Is_Techno() && !object->IsInLimbo && object->Owner() == Class->House) {\n\t\t\t\t\tTARGET target = ((TechnoClass *)object)->TarCom;\n\t\t\t\t\tif (Target_Legal(target) && As_Techno(target) != NULL) {\n\t\t\t\t\t\tif (Is_Ally(As_Techno(target))) {\n\t\t\t\t\t\t\t((TechnoClass *)object)->Assign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tCause all structures to be revealed to the house that has been\n\t\t\t**\tallied with.\n\t\t\t*/\n\t\t\tif (Rule.IsAllyReveal && house == PlayerPtr->Class->House) {\n\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\t\tif (b && !b->IsInLimbo && (HouseClass *)b->House == this) {\n\t\t\t\t\t\tMap.Sight_From(Coord_Cell(b->Center_Coord()), b->Class->SightRange, PlayerPtr, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (IsHuman) {\n\t\t\t\tsprintf(buffer, Text_String(TXT_HAS_ALLIED), IniName, HouseClass::As_Pointer(house)->IniName);\n//\t\t\t\tsprintf(buffer, Text_String(TXT_HAS_ALLIED), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[((HouseClass::As_Pointer(house))->Class->House) - HOUSE_MULTI1]->Name);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);\n\t\t\t}\n\n#if(TEN)\n\t\t\t//\n\t\t\t// Notify the TEN server of the new alliance\n\t\t\t//\n\t\t\tif (this == PlayerPtr && hptr != NULL && Session.Type == GAME_TEN) {\n\t\t\t\tSend_TEN_Alliance(hptr->IniName, 1);\n\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t//\n\t\t\t// Notify the MPATH server of the new alliance\n\t\t\t//\n\t\t\t//if (this == PlayerPtr && hptr != NULL && Session.Type == GAME_MPATH) {\n\t\t\t\t//Send_MPATH_Alliance(hptr->IniName, 1);\n\t\t\t//}\n#endif\t// MPATH\n\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Make_Enemy -- Make an enemy of the house specified.                             *\n *                                                                                             *\n *    This routine will flag the house specified so that it will be an enemy to this house.    *\n *    Enemy houses are legal targets for attack.                                               *\n *                                                                                             *\n * INPUT:   house -- The house to make an enemy of this house.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   07/27/1995 JLB : Making war is a bilateral action.                                        *\n *=============================================================================================*/\nvoid HouseClass::Make_Enemy(HousesType house)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (house != HOUSE_NONE && Is_Ally(house)) {\n\t\tHouseClass * enemy = HouseClass::As_Pointer(house);\n\t\tAllies &= ~(1L << house);\n\n\t\tif (ScenarioInit) {\n\t\t\tControl.Allies &= !(1L << house);\n\t\t}\n\n\t\t/*\n\t\t**\tBreaking an alliance is a bilateral event.\n\t\t*/\n\t\tif (enemy != NULL && enemy->Is_Ally(this)) {\n\t\t\tenemy->Allies &= ~(1L << Class->House);\n\n\t\t\tif (ScenarioInit) {\n\t\t\t\tControl.Allies &= ~(1L << Class->House);\n\t\t\t}\n\t\t}\n\n\t\tif ((Debug_Flag || Session.Type != GAME_NORMAL) && !ScenarioInit && IsHuman) {\n\t\t\tchar buffer[80];\n\n\t\t\tsprintf(buffer, Text_String(TXT_AT_WAR), IniName, HouseClass::As_Pointer(house)->IniName);\n//\t\t\tsprintf(buffer, Text_String(TXT_AT_WAR), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[enemy->Class->House - HOUSE_MULTI1]->Name);\n\t\t\tSession.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);\n\t\t\tMap.Flag_To_Redraw(false);\n\n#if(TEN)\n\t\t\t//\n\t\t\t// Notify the TEN server of the broken alliance\n\t\t\t//\n\t\t\tif (this == PlayerPtr && enemy != NULL && Session.Type == GAME_TEN) {\n\t\t\t\tSend_TEN_Alliance(enemy->IniName, 0);\n\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t//\n\t\t\t// Notify the MPATH server of the broken alliance\n\t\t\t//\n\t\t\t//if (this == PlayerPtr && enemy != NULL && Session.Type == GAME_MPATH) {\n\t\t\t\t//Send_MPATH_Alliance(enemy->IniName, 0);\n\t\t\t//}\n#endif\t// MPATH\n\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Remap_Table -- Fetches the remap table for this house object.                   *\n *                                                                                             *\n *    This routine will return with the remap table to use when displaying an object owned     *\n *    by this house. If the object is blushing (flashing), then the lightening remap table is  *\n *    always used. The \"unit\" parameter allows proper remap selection for those houses that    *\n *    have a different remap table for buildings or units.                                     *\n *                                                                                             *\n * INPUT:   blushing -- Is the object blushing (flashing)?                                     *\n *                                                                                             *\n *          remap    -- The remap control value to use.                                        *\n *                      REMAP_NONE     No remap pointer returned at all.                       *\n *                      REMAP_NORMAL   Return the remap pointer for this house.                *\n *                      REMAP_ALTERNATE   (Nod solo play only -- forces red remap).            *\n *                                        Multiplay returns same as REMAP_NORMAL               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the remap table to use when drawing this object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   10/25/1995 JLB : Uses remap control value.                                                *\n *=============================================================================================*/\nunsigned char const * HouseClass::Remap_Table(bool blushing, RemapType remap) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (blushing) return(&Map.FadingLight[0]);\n\n\tif (remap == REMAP_NONE) return(0);\n\n\treturn(ColorRemaps[RemapColor].RemapTable);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggested_New_Team -- Determine what team should be created.                    *\n *                                                                                             *\n *    This routine examines the house condition and returns with the team that it thinks       *\n *    should be created. The units that are not currently a member of a team are examined      *\n *    to determine the team needed.                                                            *\n *                                                                                             *\n * INPUT:   alertcheck  -- Select from the auto-create team list.                              *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type that should be created. If no team should  *\n *          be created, then NULL is returned.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamTypeClass const * HouseClass::Suggested_New_Team(bool alertcheck)\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(TeamTypeClass::Suggested_New_Team(this, AScan, UScan, IScan, VScan, alertcheck));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Threat -- Adjust threat for the region specified.                        *\n *                                                                                             *\n *    This routine is called when the threat rating for a region needs to change. The region   *\n *    and threat adjustment are provided.                                                      *\n *                                                                                             *\n * INPUT:   region   -- The region that adjustment is to occur on.                             *\n *                                                                                             *\n *          threat   -- The threat adjustment to perform.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Threat(int region, int threat)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tstatic int _val[] = {\n\t\t-MAP_REGION_WIDTH - 1,\t-MAP_REGION_WIDTH, -MAP_REGION_WIDTH + 1,\n\t\t-1,\t\t\t\t\t\t\t0,\t\t\t\t\t\t 1,\n\t\tMAP_REGION_WIDTH -1,\t\tMAP_REGION_WIDTH,\t MAP_REGION_WIDTH +1\n\t};\n\tstatic int _thr[] = {\n\t\t2, 1, 2,\n\t\t1, 0, 1,\n\t\t2, 1,\t2\n\t};\n\tint neg;\n\tint * val = &_val[0];\n\tint * thr = &_thr[0];\n\n\tif (threat < 0) {\n\t\tthreat = -threat;\n\t\tneg = true;\n\t} else {\n\t\tneg = false;\n\t}\n\n\tfor (int lp = 0; lp < 9; lp ++) {\n\t\tRegions[region + *val].Adjust_Threat(threat >> *thr, neg);\n\t\tval++;\n\t\tthr++;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Begin_Production -- Starts production of the specified object type.             *\n *                                                                                             *\n *    This routine is called from the event system. It will start production for the object    *\n *    type specified. This will be reflected in the sidebar as well as the house factory       *\n *    tracking variables.                                                                      *\n *                                                                                             *\n * INPUT:   type  -- The type of object to begin production on.                                *\n *                                                                                             *\n *          id    -- The subtype of object.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the reason why, or why not, production was started.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   10/21/1996 JLB : Handles max object case.                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Begin_Production(RTTIType type, int id)\n{\n\tassert(Houses.ID(this) == ID);\n\tint result = true;\n\tbool initial_start = false;\n\tFactoryClass * fptr;\n\tTechnoTypeClass const * tech = Fetch_Techno_Type(type, id);\n\n\tfptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf the house is already busy producing the requested object, then\n\t**\treturn with this failure code, unless we are restarting production.\n\t*/\n\tif (fptr != NULL) {\n\t\tif (fptr->Is_Building()) {\n\t\t\treturn(PROD_CANT);\n\t\t}\n\t} else {\n\t\tfptr = new FactoryClass();\n\t\tif (!fptr) return(PROD_CANT);\n\t\tSet_Factory(type, fptr);\n\t\tresult = fptr->Set(*tech, *this);\n\t\tinitial_start = true;\n\n\t\t/*\n\t\t** If set failed, we probably reached the production cap. Don't let the factory linger, preventing further production attempts.\n\t\t** ST - 3/17/2020 2:03PM\n\t\t*/\n\t\tif (!result) {\n\t\t\tSet_Factory(type, NULL);\n\t\t\tdelete fptr;\n\t\t\tfptr = NULL;\n\t\t}\n\t}\n\n\tif (result) {\n\t\tfptr->Start();\n\n\t\t/*\n\t\t**\tLink this factory to the sidebar so that proper graphic feedback\n\t\t**\tcan take place.\n\t\t*/\n\t\t// Handle Glyphx multiplayer sidebar. ST - 8/14/2019 1:26PM\n\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tif (IsHuman) {\n\t\t\t\tSidebar_Glyphx_Factory_Link(fptr->ID, type, id, this);\n\t\t\t}\n\t\t} else {\t\t \n\t\t\tif (PlayerPtr == this) {\n\t\t\t\tMap.Factory_Link(fptr->ID, type, id);\n\t\t\t}\n\t\t}\n\n\t\treturn(PROD_OK);\n\t}\n\n\tdelete fptr;\n\treturn(PROD_CANT);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suspend_Production -- Temporarily puts production on hold.                      *\n *                                                                                             *\n *    This routine is called from the event system whenever the production of the specified    *\n *    type needs to be suspended. The suspended production will be reflected in the sidebar    *\n *    as well as in the house control structure.                                               *\n *                                                                                             *\n * INPUT:   type  -- The type of object that production is being suspended for.                *\n *                                                                                             *\n * OUTPUT:  Returns why, or why not, production was suspended.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Suspend_Production(RTTIType type)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tFactoryClass * fptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf the house is already busy producing the requested object, then\n\t**\treturn with this failure code.\n\t*/\n\tif (fptr == NULL) return(PROD_CANT);\n\n\t/*\n\t**\tActually suspend the production.\n\t*/\n\tfptr->Suspend();\n\n\t/*\n\t**\tTell the sidebar that it needs to be redrawn because of this.\n\t*/\n\tif (PlayerPtr == this) {\n\t\tMap.SidebarClass::IsToRedraw = true;\n\t\tif (!RunningAsDLL) {\t\t// Don't force a redraw when running under GlyphX. PlayerPtr==this will always be true in this case, and we don't want to force a redraw even for AI players\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t}\n\t}\n\n\treturn(PROD_OK);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Abandon_Production -- Abandons production of item type specified.               *\n *                                                                                             *\n *    This routine is called from the event system whenever production must be abandoned for   *\n *    the type specified. This will remove the factory and pending object from the sidebar as  *\n *    well as from the house factory record.                                                   *\n *                                                                                             *\n * INPUT:   type  -- The object type that production is being suspended for.                   *\n *                                                                                             *\n * OUTPUT:  Returns the reason why or why not, production was suspended.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nProdFailType HouseClass::Abandon_Production(RTTIType type)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tFactoryClass * fptr = Fetch_Factory(type);\n\n\t/*\n\t**\tIf there is no factory to abandon, then return with a failure code.\n\t*/\n\tif (fptr == NULL) return(PROD_CANT);\n\n\t/*\n\t**\tTell the sidebar that it needs to be redrawn because of this.\n\t*/\n\t// Handle Glyphx multiplayer sidebar. ST - 8/7/2019 10:18AM\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (IsHuman) {\n\t\t\tSidebar_Glyphx_Abandon_Production(type, fptr->ID, this);\n\t\t\t\n\t\t\t// Need to clear pending object here if legacy renderer enabled\n\n\t\t\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING && Map.PendingObjectPtr) {\n\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\tMap.PendingObject = 0;\n\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (PlayerPtr == this) {\n\t\t\tMap.Abandon_Production(type, fptr->ID);\n\n\t\t\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {\n\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\tMap.PendingObject = 0;\n\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tAbandon production of the object.\n\t*/\n\tfptr->Abandon();\n\tSet_Factory(type, NULL);\n\tdelete fptr;\n\n\treturn(PROD_OK);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Special_Weapon_AI -- Fires special weapon.                                      *\n *                                                                                             *\n *    This routine will pick a good target to fire the special weapon specified.               *\n *                                                                                             *\n * INPUT:   id -- The special weapon id to fire.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Special_Weapon_AI(SpecialWeaponType id)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t** Loop through all of the building objects on the map\n\t** and see which ones are available.\n \t*/\n\tBuildingClass * bestptr = NULL;\n\tint best = -1;\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * b = Buildings.Ptr(index);\n\n\t\t/*\n\t\t** If the building is valid, not in limbo, not in the process of\n\t\t** being destroyed and not our ally, then we can consider it.\n\t\t*/\n\t\tif (b != NULL && !b->IsInLimbo && b->Strength && !Is_Ally(b)) {\n\t\t\tif (Percent_Chance(90) && (b->Value() > best || best == -1)) {\n\t\t\t\tbest = b->Value();\n\t\t\t\tbestptr = b;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bestptr) {\n\t\tCELL cell = Coord_Cell(bestptr->Center_Coord());\n\t\tPlace_Special_Blast(id, cell);\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.      *\n *                                                                                             *\n *    This routine will create a blast effect at the cell specified. This is the result of     *\n *    the special weapons.                                                                     *\n *                                                                                             *\n * INPUT:   id    -- The special weapon id number.                                             *\n *                                                                                             *\n *          cell  -- The location where the special weapon attack is to occur.                 *\n *                                                                                             *\n * OUTPUT:  Was the special weapon successfully fired at the location specified?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : commented.                                                               *\n *   07/25/1995 JLB : Added scatter effect for nuclear bomb.                                   *\n *   07/28/1995 JLB : Revamped to use super weapon class controller.                           *\n *=============================================================================================*/\nextern void Logic_Switch_Player_Context(ObjectClass *object);\nextern void Logic_Switch_Player_Context(HouseClass *object);\nextern void On_Special_Weapon_Targetting(const HouseClass* player_ptr, SpecialWeaponType weapon_type);\n\nbool HouseClass::Place_Special_Blast(SpecialWeaponType id, CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t// Added. ST - 12/2/2019 11:26AM\n\tbool fired = false;\n\tconst char *what = NULL;\n\n\tBuildingClass * launchsite = 0;\n\tAnimClass * anim = 0;\n\tswitch (id) {\n\t\tcase SPC_SONAR_PULSE:\n\t\t\t// Automatically discharge the sonar pulse and uncloak all subs.\n\t\t\tif (SuperWeapon[SPC_SONAR_PULSE].Is_Ready()) {\n\t\t\t\tSuperWeapon[SPC_SONAR_PULSE].Discharged(this == PlayerPtr);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\tMap.Activate_Pulse();\n\t\t\t\t}\n\t\t\t\tSound_Effect(VOC_SONAR);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"SONAR\";\n\t\t\t\tfor (int index = 0; index < Vessels.Count(); index++) {\n\t\t\t\t\tVesselClass * sub = Vessels.Ptr(index);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {\n#else\n\t\t\t\t\tif (*sub == VESSEL_SS) {\n#endif\n\t\t\t\t\t\tsub->PulseCountDown = 15 * TICKS_PER_SECOND;\n\t\t\t\t\t\tsub->Do_Uncloak();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_NUCLEAR_BOMB:\n\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready()) {\n\t\t\t\tif (SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) {\n\t\t\t\t\tBulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(cell), 0, 200, WARHEAD_NUKE, MPH_VERY_FAST);\n\t\t\t\t\tif (bullet) {\n\t\t\t\t\t\tint celly = Cell_Y(cell);\n\t\t\t\t\t\tcelly -= 15;\n\t\t\t\t\t\tif (celly < 1) celly = 1;\n\t\t\t\t\t\tCOORDINATE start = Cell_Coord(XY_Cell(Cell_X(cell), celly));\n\t\t\t\t\t\tif (!bullet->Unlimbo(start, DIR_S)) {\n\t\t\t\t\t\t\tdelete bullet;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\t\t\tfired = true;\n\t\t\t\t\t\twhat = \"NUKE\";\n\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSearch for a suitable launch site for this missile.\n\t\t\t\t\t*/\n\t\t\t\t\tlaunchsite = Find_Building(STRUCT_MSLO);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf a launch site was found, then proceed with the normal launch\n\t\t\t\t\t**\tsequence.\n\t\t\t\t\t*/\n\t\t\t\t\tif (launchsite) {\n\t\t\t\t\t\tlaunchsite->Assign_Mission(MISSION_MISSILE);\n\t\t\t\t\t\tlaunchsite->Commence();\n\t\t\t\t\t\tNukeDest = cell;\n\t\t\t\t\t}\n\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tSuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\t\tfired = true;\n\t\t\t\t\twhat = \"NUKE\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_PARA_INFANTRY:\n\t\t\tif (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready()) {\n\n\t\t\t\tTeamTypeClass * ttype = TeamTypeClass::As_Pointer(\"@PINF\");\n\t\t\t\tif (ttype == NULL) {\n\t\t\t\t\tttype = new TeamTypeClass;\n\t\t\t\t\tif (ttype != NULL) {\n\t\t\t\t\t\tstrcpy(ttype->IniName, \"@PINF\");\n\t\t\t\t\t\tttype->IsTransient = true;\n\t\t\t\t\t\tttype->IsPrebuilt = false;\n\t\t\t\t\t\tttype->IsReinforcable = false;\n\t\t\t\t\t\tttype->Origin = WAYPT_SPECIAL;\n\t\t\t\t\t\tttype->MissionCount = 1;\n\t\t\t\t\t\tttype->MissionList[0].Mission = TMISSION_ATT_WAYPT;\n\t\t\t\t\t\tttype->MissionList[0].Data.Value = WAYPT_SPECIAL;\n\t\t\t\t\t\tttype->ClassCount = 2;\n\t\t\t\t\t\tttype->Members[0].Quantity = AircraftTypeClass::As_Reference(AIRCRAFT_BADGER).Max_Passengers();\n\t\t\t\t\t\tttype->Members[0].Class = &InfantryTypeClass::As_Reference(INFANTRY_E1);\n\t\t\t\t\t\tttype->Members[1].Quantity = 1;\n\t\t\t\t\t\tttype->Members[1].Class = &AircraftTypeClass::As_Reference(AIRCRAFT_BADGER);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (ttype != NULL) {\n\t\t\t\t\tttype->House = Class->House;\n\t\t\t\t\tScen.Waypoint[WAYPT_SPECIAL] = Map.Nearby_Location(cell, SPEED_FOOT);\n\t\t\t\t\tDo_Reinforcements(ttype);\n\t\t\t\t}\n\n//\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_BADGER, 1, MISSION_HUNT, ::As_Target(cell), TARGET_NONE, INFANTRY_E1);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_PARA_INFANTRY].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"PARA\";\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_SPY_MISSION:\n\t\t\tif (SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {\n\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_U2, 1, MISSION_HUNT, ::As_Target(cell), ::As_Target(cell));\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_SPY_MISSION].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"SPY\";\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_PARA_BOMB:\n\t\t\tif (SuperWeapon[SPC_PARA_BOMB].Is_Ready()) {\n\t\t\t\tCreate_Air_Reinforcement(this, AIRCRAFT_BADGER, Rule.BadgerBombCount, MISSION_HUNT, ::As_Target(cell), TARGET_NONE);\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n\t\t\t\tSuperWeapon[SPC_PARA_BOMB].Discharged(this == PlayerPtr);\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"PARABOMB\";\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_IRON_CURTAIN:\n\t\t\tif (SuperWeapon[SPC_IRON_CURTAIN].Is_Ready()) {\n\t\t\t\tint x = Keyboard->MouseQX - Map.TacPixelX;\n\t\t\t\tint y = Keyboard->MouseQY - Map.TacPixelY;\n\t\t\t\tTechnoClass * tech = Map[cell].Cell_Techno(x, y);\n\t\t\t\tif (tech) {\n\t\t\t\t\tswitch (tech->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\ttech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_MINUTE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {\n\t\t\t\t\t\t\t\ttech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_SECOND;\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\ttech->Mark(MARK_CHANGE);\n\t\t\t\t\t\t\tSound_Effect(VOC_IRON1, tech->Center_Coord());\n\t\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSuperWeapon[SPC_IRON_CURTAIN].Discharged(this == PlayerPtr);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"IRON\";\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_CHRONOSPHERE:\n\t\t\tif (SuperWeapon[SPC_CHRONOSPHERE].Is_Ready()) {\n\t\t\t\tint x = Keyboard->MouseQX - Map.TacPixelX;\n\t\t\t\tint y = Keyboard->MouseQY - Map.TacPixelY;\n\t\t\t\tTechnoClass * tech = Map[cell].Cell_Techno(x, y);\n\t\t\t\tif (tech && Is_Ally(tech)) {\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_UNIT ||\n\t\t\t\t\t\ttech->What_Am_I() == RTTI_INFANTRY ||\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t(tech->What_Am_I() == RTTI_VESSEL && (*((VesselClass *)tech) != VESSEL_TRANSPORT && *((VesselClass *)tech) != VESSEL_CARRIER) )) {\n#else\n\t\t\t\t\t\t(tech->What_Am_I() == RTTI_VESSEL && *((VesselClass *)tech) != VESSEL_TRANSPORT)) {\n#endif\n\n\t\t\t\t\t\tif (tech->What_Am_I() != RTTI_UNIT || !((UnitClass *)tech)->IsDeploying) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tbool porthim = true;\n\tif(tech->What_Am_I() == RTTI_UNIT && ((UnitClass *)tech)->Class->Type == UNIT_CHRONOTANK) {\n\t\tporthim = false;\n\t}\n\tif (porthim) {\n#endif\n\t\t\t\t\t\t\tHouseClass* old_player_ptr = PlayerPtr;\n\t\t\t\t\t\t\tLogic_Switch_Player_Context(this);\n\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_CHRONO2;\n\t\t\t\t\t\t\tOn_Special_Weapon_Targetting(PlayerPtr, Map.IsTargettingMode);\n\t\t\t\t\t\t\tLogic_Switch_Player_Context(old_player_ptr);\n\t\t\t\t\t\t\tUnitToTeleport = tech->As_Target();\n\t\t\t\t\t\t\tfired = true;\n\t\t\t\t\t\t\twhat = \"CHRONO\";\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase SPC_CHRONO2:\n\t\t\t{\n\t\t\t\tTechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);\n\t\t\t\tCELL oldcell = cell;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (tech != NULL && tech->IsActive && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {\n#else\n\t\t\t\tif (tech != NULL && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {\n#endif\n\t\t\t\t\t/*\n\t\t\t\t\t** Destroy any infantryman that gets teleported\n\t\t\t\t\t*/\n\t\t\t\t\tif (tech->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\t\tInfantryClass * inf = (InfantryClass *)tech;\n\t\t\t\t\t\tinf->Mark(MARK_UP);\n\t\t\t\t\t\tinf->Coord = Cell_Coord(cell);\n\t\t\t\t\t\tinf->Mark(MARK_DOWN);\n\t\t\t\t\t\tint damage = inf->Strength;\n\t\t\t\t\t\tinf->Take_Damage(damage, 0, WARHEAD_FIRE, 0, true);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t} else if(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {\n\t\t\t\t\t\ttech->Assign_Target(tech->As_Target());\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tWarp the unit to the new location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tDriveClass * drive = (DriveClass *)tech;\n\t\t\t\t\t\tdrive->MoebiusCell = Coord_Cell(drive->Coord);\n\t\t\t\t\t\toldcell = drive->MoebiusCell;\n\t\t\t\t\t\tdrive->Teleport_To(cell);\n\t\t\t\t\t\tdrive->IsMoebius = true;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\tdrive->IsMoebius = false;\n\t}\n\tdrive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;\n\tif (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {\n\t\tdrive->MoebiusCountDown = ChronoTankDuration * TICKS_PER_MINUTE;\n\t}\n#else\n\t\t\t\t\t\tdrive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;\n#endif\n\t\t\t\t\t\tScen.Do_BW_Fade();\n\t\t\t\t\t\tSound_Effect(VOC_CHRONO, drive->Coord);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSet active animation on Chronospheres.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); ++index) {\n\t\t\t\t\t\t\tBuildingClass* building = Buildings.Ptr(index);\n\t\t\t\t\t\t\tif (building != nullptr && building->IsActive && building->Owner() == Class->House && *building == STRUCT_CHRONOSPHERE) {\n\t\t\t\t\t\t\t\tbuilding->Begin_Mode(BSTATE_ACTIVE);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tUnitToTeleport = TARGET_NONE;\n\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK)) {\n#endif\n\t\t\t\tSuperWeapon[SPC_CHRONOSPHERE].Discharged(this == PlayerPtr);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t}\n#endif\n\t\t\t\tIsRecalcNeeded = true;\n\t\t\t\tfired = true;\n\t\t\t\twhat = \"CHRONO2\";\n\n\t\t\t\t/*\n\t\t\t\t** Now set a percentage chance that a time quake will occur.\n\t\t\t\t*/\n\t\t\t\tif (!TimeQuake) {\n\t\t\t\t\tTimeQuake = Percent_Chance(Rule.QuakeChance * 100);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Now set a percentage chance that a chronal vortex will appear. It\n\t\t\t\t**\tmight appear where the object teleported to or it might appear\n\t\t\t\t**\twhere it teleported from -- random chance.\n\t\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// Don't allow a vortex if the teleportation was due to a chrono tank.\n\tif(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK))\n#endif\n\t\t\t\tif (!ChronalVortex.Is_Active() && Percent_Chance(Rule.VortexChance * 100)) {\n\t\t\t\t\tint x = Random_Pick(0, Map.MapCellWidth-1);\n\t\t\t\t\tint y = Random_Pick(0, Map.MapCellHeight-1);\n\t\t\t\t\tChronalVortex.Appear(Cell_Coord(XY_Cell(Map.MapCellX + x, Map.MapCellY + y)));\n\n//\t\t\t\t\tif (Percent_Chance(50)) {\n//\t\t\t\t\t\tChronalVortex.Appear(Cell_Coord(oldcell));\n//\t\t\t\t\t} else {\n//\t\t\t\t\t\tChronalVortex.Appear(Cell_Coord(cell));\n//\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\n\t/*\n\t** Maybe trigger an achivement. ST - 12/2/2019 11:25AM\n\t*/\n\tif (IsHuman && fired && what) {\n\t\tOn_Achievement_Event(this, \"SUPERWEAPON_FIRED\", what);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Place_Object -- Places the object (building) at location specified.             *\n *                                                                                             *\n *    This routine is called when a building has been produced and now must be placed on       *\n *    the map. When the player clicks on the map, this routine is ultimately called when the   *\n *    event passes through the event queue system.                                             *\n *                                                                                             *\n * INPUT:   type  -- The object type to place. The actual object is lifted from the sidebar.   *\n *                                                                                             *\n *                                                                                             *\n *          cell  -- The location to place the object on the map.                              *\n *                                                                                             *\n * OUTPUT:  Was the placement successful?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern void On_Ping(const HouseClass* player_ptr, COORDINATE coord);\n\nbool HouseClass::Place_Object(RTTIType type, CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tTechnoClass * tech = 0;\n\tFactoryClass * factory = Fetch_Factory(type);\n\n\t/*\n\t**\tOnly if there is a factory active for this type, can it be \"placed\".\n\t**\tIn the case of a missing factory, then this request is completely bogus --\n\t**\tignore it. This might occur if, between two events to exit the same\n\t**\tobject, the mouse was clicked on the sidebar to start building again.\n\t**\tThe second placement event should NOT try to place the object that is\n\t**\tjust starting construction.\n\t*/\n\tif (factory && factory->Has_Completed()) {\n\t\ttech = factory->Get_Object();\n\n\t\tif (cell == -1) {\n\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\tif (pending != NULL) {\n\n#ifdef FIXIT_HELI_LANDING\n\t\t\t\t/*\n\t\t\t\t**\tTry to find a place for the object to appear from. For helicopters, it has the\n\t\t\t\t**\toption of finding a nearby helipad if no helipads are free.\n\t\t\t\t*/\n\t\t\t\tTechnoClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\tif (builder == NULL && pending->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass *)pending)->Class->IsFixedWing) {\n\t\t\t\t\tbuilder = pending->Who_Can_Build_Me(true, false);\n\n\t\t\t\t}\n#else\n\t\t\t\tbool intheory = false;\n\t\t\t\tif (pending->What_Am_I() == RTTI_AIRCRAFT) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** BG hack - helicopters don't need a specific building to\n\t\t\t\t\t** emerge from, in fact, they'll land next to a building if\n\t\t\t\t\t** need be.\n\t\t\t\t\t*/\n\t\t\t\t\tif( !((AircraftClass *)pending)->Class->IsFixedWing) {\n\t\t\t\t\t\tintheory = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTechnoClass * builder = pending->Who_Can_Build_Me(intheory, false);\n#endif\n\t\t\t\tTechnoTypeClass const *object_type = pending->Techno_Type_Class();\n\t\t\t\tif (builder != NULL && builder->Exit_Object(pending)) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSince the object has left the factory under its own power, delete\n\t\t\t\t\t**\tthe production manager tied to this slot in the sidebar. Its job\n\t\t\t\t\t**\thas been completed.\n\t\t\t\t\t*/\n\t\t\t\t\tfactory->Set_Is_Blocked(false);\n\t\t\t\t\tfactory->Completed();\n\t\t\t\t\tAbandon_Production(type);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Could be tied to an achievement. ST - 11/11/2019 11:56AM\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsHuman) {\n\t\t\t\t\t\tif (object_type) {\n\t\t\t\t\t\t\tOn_Achievement_Event(this, \"UNIT_CONSTRUCTED\", object_type->IniName);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pending->IsActive) {\n\t\t\t\t\t\t\tOn_Ping(this, pending->Center_Coord());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (pending->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tJustBuiltUnit = ((UnitClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\t\tJustBuiltVessel = ((VesselClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\tJustBuiltInfantry = ((InfantryClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\tJustBuiltStructure = ((BuildingClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\tJustBuiltAircraft = ((AircraftClass*)pending)->Class->Type;\n\t\t\t\t\t\t\tIsBuiltSomething = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThe object could not leave under it's own power. Just wait\n\t\t\t\t\t**\tuntil the player tries to place the object again.\n\t\t\t\t\t*/\n\t\t\t\t\t\n\t\t\t\t\t/*\n\t\t\t\t\t** Flag that it's blocked so we can re-try the exit later.\n\t\t\t\t\t** This would have been a bad idea under the old peer-peer code since it would have pumped events into\n\t\t\t\t\t** the queue too often. ST - 2/25/2020 11:56AM\n\t\t\t\t\t*/\n\t\t\t\t\tfactory->Set_Is_Blocked(true);\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (tech) {\n\t\t\t\tTechnoClass * builder = tech->Who_Can_Build_Me(false, false);\n\t\t\t\tif (builder) {\n\n\t\t\t\t\tbuilder->Transmit_Message(RADIO_HELLO, tech);\n\t\t\t\t\tif (tech->Unlimbo(Cell_Coord(cell))) {\n\t\t\t\t\t\tfactory->Completed();\n\t\t\t\t\t\tAbandon_Production(type);\n\n\t\t\t\t\t\tif (PlayerPtr == this) {\n\t\t\t\t\t\t\tSound_Effect(VOC_PLACE_BUILDING_DOWN);\n\t\t\t\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\t\t\t\tMap.PendingObject = 0;\n\t\t\t\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (this == PlayerPtr) {\n\t\t\t\t\t\t\tSpeak(VOX_DEPLOY);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbuilder->Transmit_Message(RADIO_OVER_OUT);\n\t\t\t\t}\n\t\t\t\treturn(false);\n\n\t\t\t} else {\n\n\t\t\t\t// Play a bad sound here?\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Manual_Place -- Inform display system of building placement mode.               *\n *                                                                                             *\n *    This routine will inform the display system that building placement mode has begun.      *\n *    The cursor will be created that matches the layout of the building shape.                *\n *                                                                                             *\n * INPUT:   builder  -- The factory that is building this object.                              *\n *                                                                                             *\n *          object   -- The building that is going to be placed down on the map.               *\n *                                                                                             *\n * OUTPUT:  Was the building placement mode successfully initiated?                            *\n *                                                                                             *\n * WARNINGS:   This merely adjusts the cursor shape. Nothing that affects networked games      *\n *             is affected.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/04/1995 JLB : Created.                                                                 *\n *   05/30/1995 JLB : Uses the Bib_And_Offset() function to determine bib size.                *\n *=============================================================================================*/\nbool HouseClass::Manual_Place(BuildingClass * builder,  BuildingClass * object)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (this == PlayerPtr && !Map.PendingObject && builder && object) {\n\t\t/*\n\t\t**\tEnsures that object selection doesn't remain when\n\t\t**\tbuilding placement takes place.\n\t\t*/\n\t\tUnselect_All();\n\n\t\tMap.Repair_Mode_Control(0);\n\t\tMap.Sell_Mode_Control(0);\n\n\t\tMap.PendingObject = object->Class;\n\t\tMap.PendingObjectPtr = object;\n\t\tMap.PendingHouse = Class->House;\n\n\t\tMap.Set_Cursor_Shape(object->Occupy_List(true));\n\t\tMap.Set_Cursor_Pos(Coord_Cell(builder->Coord));\n\t\tbuilder->Mark(MARK_CHANGE);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * HouseClass::Clobber_All -- removes all objects for this house\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      This routine removes the house itself, so the multiplayer code\t\t*\n *\t\t  must not rely on there being \"empty\" houses lying around.\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 BRR : Created.                                             *\n *   06/09/1995 JLB : Handles aircraft.                                    *\n *=========================================================================*/\nvoid HouseClass::Clobber_All(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint i;\n\n\tfor (i = 0; i < ::Aircraft.Count(); i++) {\n\t\tif (::Aircraft.Ptr(i)->House == this) {\n\t\t\tdelete ::Aircraft.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < ::Units.Count(); i++) {\n\t\tif (::Units.Ptr(i)->House == this) {\n\t\t\tdelete ::Units.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < ::Vessels.Count(); i++) {\n\t\tif (::Vessels.Ptr(i)->House == this) {\n\t\t\tdelete ::Vessels.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tif (Infantry.Ptr(i)->House == this) {\n\t\t\tdelete Infantry.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tif (Buildings.Ptr(i)->House == this) {\n\t\t\tdelete Buildings.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < TeamTypes.Count(); i++) {\n\t\tif (TeamTypes.Ptr(i)->House == Class->House) {\n\t\t\tdelete TeamTypes.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < Triggers.Count(); i++) {\n\t\tif (Triggers.Ptr(i)->Class->House == Class->House) {\n\t\t\tdelete Triggers.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\tfor (i = 0; i < TriggerTypes.Count(); i++) {\n\t\tif (TriggerTypes.Ptr(i)->House == Class->House) {\n\t\t\tdelete TriggerTypes.Ptr(i);\n\t\t\ti--;\n\t\t}\n\t}\n\n\tdelete this;\n}\n\n\n/***********************************************************************************************\n * HouseClass::Detach -- Removes specified object from house tracking systems.                 *\n *                                                                                             *\n *    This routine is called when an object is to be removed from the game system. If the      *\n *    specified object is part of the house tracking system, then it will be removed.          *\n *                                                                                             *\n * INPUT:   target   -- The target value of the object that is to be removed from the game.    *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : commented                                                                *\n *=============================================================================================*/\nvoid HouseClass::Detach(TARGET target, bool )\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (ToCapture == target) {\n\t\tToCapture = TARGET_NONE;\n\t}\n\n\tif (Is_Target_Trigger(target)) {\n\t\tHouseTriggers[ID].Delete(As_Trigger(target));\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.       *\n *                                                                                             *\n *    This routine will examine the enemy houses and if there is a building owned by one       *\n *    of those house, true will be returned.                                                   *\n *                                                                                             *\n * INPUT:   btype -- The building type to check for.                                           *\n *                                                                                             *\n * OUTPUT:  Does a building of the specified type exist for one of the enemy houses?           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Does_Enemy_Building_Exist(StructType btype) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint bflag = 1L << btype;\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\tHouseClass * house = HouseClass::As_Pointer(index);\n\n\t\tif (house && !Is_Ally(house) && (house->ActiveBScan & bflag) != 0) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.        *\n *                                                                                             *\n *    This routine will examine the house status and return with a techno type pointer to      *\n *    the object type that it thinks should be created. The type is restricted to match the    *\n *    type specified. Typical use of this routine is by computer controlled factories.         *\n *                                                                                             *\n * INPUT:   objecttype  -- The type of object to restrict the scan for.                        *\n *                                                                                             *\n *          kennel      -- Is this from a kennel? There are special hacks to ensure that only  *\n *                         dogs can be produced from a kennel.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a techno type for the object type that should be         *\n *          created. If no object should be created, then NULL is returned.                    *\n *                                                                                             *\n * WARNINGS:   This is a time consuming routine. Only call when necessary.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * HouseClass::Suggest_New_Object(RTTIType objecttype, bool kennel) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tTechnoTypeClass const * techno = NULL;\n\n\tswitch (objecttype) {\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tif (BuildAircraft != AIRCRAFT_NONE) {\n\t\t\t\treturn(&AircraftTypeClass::As_Reference(BuildAircraft));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tif (BuildVessel != VESSEL_NONE) {\n\t\t\t\treturn(&VesselTypeClass::As_Reference(BuildVessel));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tUnit construction is based on the rule that up to twice the number required\n\t\t**\tto fill all teams will be created.\n\t\t*/\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tif (BuildUnit != UNIT_NONE) {\n\t\t\t\treturn(&UnitTypeClass::As_Reference(BuildUnit));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tInfantry construction is based on the rule that up to twice the number required\n\t\t**\tto fill all teams will be created.\n\t\t*/\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tif (BuildInfantry != INFANTRY_NONE) {\n\t\t\t\tif (kennel && BuildInfantry != INFANTRY_DOG) return(NULL);\n\t\t\t\tif (!kennel && BuildInfantry == INFANTRY_DOG) return(NULL);\n\t\t\t\treturn(&InfantryTypeClass::As_Reference(BuildInfantry));\n\t\t\t}\n\t\t\treturn(NULL);\n\n\t\t/*\n\t\t**\tBuilding construction is based upon the preconstruction list.\n\t\t*/\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tif (BuildStructure != STRUCT_NONE) {\n\t\t\t\treturn(&BuildingTypeClass::As_Reference(BuildStructure));\n\t\t\t}\n\t\t\treturn(NULL);\n\t}\n\treturn(techno);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Remove -- Removes the flag from the specified target.                      *\n *                                                                                             *\n *    This routine will remove the flag attached to the specified target object or cell.       *\n *    Call this routine before placing the object down. This is called inherently by the       *\n *    the Flag_Attach() functions.                                                             *\n *                                                                                             *\n * INPUT:   target   -- The target that the flag was attached to but will be removed from.     *\n *                                                                                             *\n *          set_home -- if true, clears the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully removed from the specified target?                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_Remove(TARGET target, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tbool rc = false;\n\n\tif (Target_Legal(target)) {\n\n\t\t/*\n\t\t**\tRemove the flag from a unit\n\t\t*/\n\t\tUnitClass * object = As_Unit(target);\n\t\tif (object) {\n\t\t\trc = object->Flag_Remove();\n\t\t\tif (rc && FlagLocation == target) {\n\t\t\t\tFlagLocation = TARGET_NONE;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tRemove the flag from a cell\n\t\t\t*/\n\t\t\tCELL cell = As_Cell(target);\n\t\t\tif (Map.In_Radar(cell)) {\n\t\t\t\trc = Map[cell].Flag_Remove();\n\t\t\t\tif (rc && FlagLocation == target) {\n\t\t\t\t\tFlagLocation = TARGET_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tHandle the flag home cell:\n\t\t**\tIf 'set_home' is set, clear the home value & the cell's overlay\n\t\t*/\n\t\tif (set_home) {\n\t\t\tif (FlagHome != 0) {\n\t\t\t\tMap[FlagHome].Overlay = OVERLAY_NONE;\n\t\t\t\tMap.Flag_Cell(FlagHome);\n\t\t\t\tFlagHome = 0;\n\t\t\t}\n\t\t}\n\t}\n\treturn(rc);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                  *\n *                                                                                             *\n *    This routine will attach the house flag to the location specified. If the location       *\n *    cannot contain the flag, then a suitable nearby location will be selected.               *\n *                                                                                             *\n * INPUT:   cell  -- The desired cell location to place the flag.                              *\n *                                                                                             *\n *          set_home -- if true, resets the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag successfully placed?                                                  *\n *                                                                                             *\n * WARNINGS:   The cell picked for the flag might very likely not be the cell requested.       *\n *             Check the FlagLocation value to determine the final cell resting spot.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *   10/08/1996 JLB : Uses map nearby cell scanning handler.                                   *\n *=============================================================================================*/\nbool HouseClass::Flag_Attach(CELL cell, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tbool rc;\n\tbool clockwise;\n\n\t/*\n\t**\tRandomly decide if we're going to search cells clockwise or counter-\n\t**\tclockwise\n\t*/\n\tclockwise = Percent_Chance(50);\n\n\t/*\n\t**\tOnly continue if this cell is a legal placement cell.\n\t*/\n\tif (Map.In_Radar(cell)) {\n\n\t\t/*\n\t\t**\tIf the flag already exists, then it must be removed from the object\n\t\t**\tit is attached to.\n\t\t*/\n\t\tFlag_Remove(FlagLocation, set_home);\n\n\t\t/*\n\t\t**\tAttach the flag to the cell specified. If it can't be placed, then pick\n\t\t**\ta nearby cell where it can be placed.\n\t\t*/\n\t\tCELL newcell = cell;\n\t\trc = Map[newcell].Flag_Place(Class->House);\n\t\tif (!rc) {\n\t\t\tnewcell = Map.Nearby_Location(cell, SPEED_TRACK, -1, MZONE_NORMAL, true);\n\t\t\tif (newcell != 0) {\n\t\t\t\trc = Map[newcell].Flag_Place(Class->House);\n\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t/*\n\t\t\t**\tLoop for increasing distance from the desired cell.\n\t\t\t**\tFor each distance, randomly pick a starting direction.  Between\n\t\t\t**\tthis and the clockwise/counterclockwise random value, the flag\n\t\t\t**\tshould appear to be placed fairly randomly.\n\t\t\t*/\n\t\t\tfor (int dist = 1; dist < 32; dist++) {\n\t\t\t\tFacingType fcounter;\n\t\t\t\tFacingType rot;\n\n\t\t\t\t/*\n\t\t\t\t**\tClockwise search.\n\t\t\t\t*/\n\t\t\t\tif (clockwise) {\n\t\t\t\t\trot = Random_Pick(FACING_N, FACING_NW);\n\t\t\t\t\tfor (fcounter = FACING_N; fcounter <= FACING_NW; fcounter++) {\n\t\t\t\t\t\tnewcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));\n\t\t\t\t\t\tif (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {\n\t\t\t\t\t\t\tdist = 32;\n\t\t\t\t\t\t\trc = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trot++;\n\t\t\t\t\t\tif (rot > FACING_NW) rot = FACING_N;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCounter-clockwise search\n\t\t\t\t\t*/\n\t\t\t\t\trot = Random_Pick(FACING_N, FACING_NW);\n\t\t\t\t\tfor (fcounter = FACING_NW; fcounter >= FACING_N; fcounter--) {\n\t\t\t\t\t\tnewcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));\n\t\t\t\t\t\tif (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {\n\t\t\t\t\t\t\tdist = 32;\n\t\t\t\t\t\t\trc = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trot--;\n\t\t\t\t\t\tif (rot < FACING_N)\n\t\t\t\t\t\t\trot = FACING_NW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\n\t\t/*\n\t\t**\tIf we've found a spot for the flag, place the flag at the new cell.\n\t\t**\tif 'set_home' is set, OR this house has no current flag home cell,\n\t\t**\tmark that cell as this house's flag home cell. Otherwise fall back\n\t\t**\ton returning the flag to its home.\n\t\t*/\n\t\tif (rc) {\n\t\t\tFlagLocation = As_Target(newcell);\n\n\t\t\tif (set_home || FlagHome == 0) {\n\t\t\t\tMap[newcell].Overlay = OVERLAY_FLAG_SPOT;\n\t\t\t\tMap[newcell].OverlayData = 0;\n\t\t\t\tMap[newcell].Recalc_Attributes();\n\t\t\t\tFlagHome = newcell;\n\t\t\t}\n\t\t}\n\t\telse if (FlagHome != 0) {\n\t\t\trc = Map[FlagHome].Flag_Place(Class->House);\n\t\t}\n\n\t\treturn(rc);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                      *\n *                                                                                             *\n *    This routine will attach the house flag to the specified unit. This routine is called    *\n *    when a unit drives over a cell containing a flag.                                        *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that the house flag is to be attached to.        *\n *                                                                                             *\n *          set_home -- if true, clears the flag's waypoint designation                        *\n *                                                                                             *\n * OUTPUT:  Was the flag attached successfully?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_Attach(UnitClass * object, bool set_home)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (object && !object->IsInLimbo) {\n\t\tFlag_Remove(FlagLocation, set_home);\n\n\t\t/*\n\t\t**\tAttach the flag to the object.\n\t\t*/\n\t\tobject->Flag_Attach(Class->House);\n\t\tFlagLocation = object->As_Target();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\nextern void On_Defeated_Message(const char* message, float timeout_seconds);\n\n/***************************************************************************\n * HouseClass::MPlayer_Defeated -- multiplayer; house is defeated          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/25/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid HouseClass::MPlayer_Defeated(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tchar txt[80];\n\tint i,j;\n\tunsigned char id;\n\tHouseClass * hptr;\n\tHouseClass * hptr2;\n\tint num_alive;\n\tint num_humans;\n\tint all_allies;\n\n\t/*\n\t**\tSet the defeat flag for this house\n\t*/\n\tIsDefeated = true;\n\n\t/*\n\t**\tIf this is a computer controlled house, then all computer controlled\n\t**\thouses become paranoid.\n\t*/\n\tif (IQ == Rule.MaxIQ && !IsHuman && Rule.IsComputerParanoid) {\n\t\tComputer_Paranoid();\n\t}\n\n\t/*\n\t**\tRemove this house's flag & flag home cell\n\t*/\n\tif (Special.IsCaptureTheFlag) {\n\t\tif (FlagLocation) {\n\t\t\tFlag_Remove(FlagLocation, true);\n\t\t} else {\n\t\t\tif (FlagHome != 0) {\n\t\t\t\tFlag_Remove(FlagHome, true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRemove any one-time superweapons the player might have.\n\t*/\n\tfor (i = SPC_FIRST; i < SPC_COUNT; i++) {\n\t\tSuperWeapon[i].Remove(true);\n\t}\n\n\t/*\n\t**\tIf this is me:\n\t**\t- Set MPlayerObiWan, so I can only send messages to all players, and\n\t**\t  not just one (so I can't be obnoxiously omnipotent)\n\t**\t- Reveal the map\n\t**\t- Add my defeat message\n\t*/\n\tif (PlayerPtr == this) {\n\t\tSession.ObiWan = 1;\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\n\t\t/*\n\t\t**\tPop up a message showing that I was defeated\n\t\t*/\n\t\tsprintf(txt, Text_String(TXT_PLAYER_DEFEATED), IniName);\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tSession.Messages.Add_Message(NULL, 0, txt, Session.ColorIdx,\n\t\t\t\tTPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t}\n\t\tMap.Flag_To_Redraw(false);\n\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tint timeout = Rule.MessageDelay * TICKS_PER_MINUTE;\n\t\t\tOn_Defeated_Message(txt, timeout * 60.0f / TICKS_PER_MINUTE);\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf it wasn't me, find out who was defeated\n\t\t*/\n\t\tif (IsHuman) {\n\t\t\tsprintf (txt, Text_String(TXT_PLAYER_DEFEATED), IniName);\n\n\t\t\t//Session.Messages.Add_Message(NULL, 0, txt, RemapColor,\n\t\t\t//\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\tMap.Flag_To_Redraw(false);\n\t\t\tRedrawOptionsMenu = true;\n\n\t\t\tint timeout = Rule.MessageDelay * TICKS_PER_MINUTE;\n\t\t\tOn_Defeated_Message(txt, timeout * 60.0f / TICKS_PER_MINUTE);\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t}\n\t}\n\n\t/*\n\t**\tFind out how many players are left alive.\n\t*/\n\tnum_alive = 0;\n\tnum_humans = 0;\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\t\thptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));\n\t\tif (hptr && !hptr->IsDefeated) {\n\t\t\tif (hptr->IsHuman) {\n\t\t\t\tnum_humans++;\n\t\t\t}\n\t\t\tnum_alive++;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf all the houses left alive are allied with each other, then in reality\n\t**\tthere's only one player left:\n\t*/\n\tall_allies = 1;\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\n\t\t/*\n\t\t**\tGet a pointer to this house\n\t\t*/\n\t\thptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));\n\t\tif (!hptr || hptr->IsDefeated)\n\t\t\tcontinue;\n\n\t\t/*\n\t\t**\tLoop through all houses; if there's one left alive that this house\n\t\t**\tisn't allied with, then all_allies will be false\n\t\t*/\n\t\tfor (j = 0; j < Session.MaxPlayers; j++) {\n\t\t\thptr2 = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + j));\n\t\t\tif (!hptr2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!hptr2->IsDefeated && !hptr->Is_Ally(hptr2)) {\n\t\t\t\tall_allies = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!all_allies) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf all houses left are allies, set 'num_alive' to 1; game over.\n\t*/\n\tif (all_allies) {\n\t\tnum_alive = 1;\n\t}\n\n\t/*\n\t**\tIf there's only one human player left or no humans left, the game is over:\n\t**\t- Determine whether this player wins or loses, based on the state of the\n\t**\t  player's IsDefeated flag\n\t**\t- Find all players' indices in the Session.Score array\n\t**\t- Tally up scores for this game\n\t*/\n\tif (num_alive == 1 || num_humans == 0) {\n\t\tif (PlayerPtr->IsDefeated) {\n\t\t\tPlayerLoses = true;\n\t\t} else {\n\t\t\tPlayerWins = true;\n\t\t}\n\n\t\t/*\n\t\t** Add up the scores\n\t\t*/\n\t\tTally_Score();\n\n\t\t/*\n\t\t**\tDestroy all the IPX connections, since we have to go through the rest\n\t\t**\tof the Main_Loop() before we detect that the game is over, and we'll\n\t\t**\tend up waiting for frame sync packets from the other machines.\n\t\t*/\n\t\tif (Session.Type==GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\ti = 0;\n\t\t\twhile (Ipx.Num_Connections() && (i++ < 1000) ) {\n\t\t\t\tid = Ipx.Connection_ID(0);\n\t\t\t\tIpx.Delete_Connection(id);\n\t\t\t}\n\t\t\tSession.NumPlayers = 0;\n\t\t}\n\n#if(TEN)\n\t\t//\n\t\t// Tell the TEN server who won\n\t\t//\n\t\tif (Session.Type == GAME_TEN) {\n\t\t\tSend_TEN_Win_Packet();\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t//\n\t\t// Tell the MPATH server who won\n\t\t//\n\t\tif (Session.Type == GAME_MPATH) {\n\t\t\tFILE *fp;\n\n\t\t\tfp = fopen(\"winner.txt\",\"wt\");\n\t\t\tif (fp) {\n\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\t\t\thptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\t\tif (!hptr->IsDefeated) {\n\t\t\t\t\t\tfprintf(fp,\"%s\\n\",hptr->IniName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfclose(fp);\n\t\t\t}\n\t\t}\n#endif\t// MPATH\n\n\t}\n}\n\n\n/***************************************************************************\n * HouseClass::Tally_Score -- Fills in the score system for this round     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid HouseClass::Tally_Score(void)\n{\n\tHousesType house;\n\tHousesType house2;\n\tHouseClass * hptr;\n\tint score_index;\n\tint i,j,k;\n\tint max_index;\n\tint max_count;\n\tint count;\n\n\t/*\n\t** Loop through all houses, tallying up each player's score\n\t*/\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thptr = HouseClass::As_Pointer(house);\n\t\t/*\n\t\t** Skip this house if it's not human.\n\t\t*/\n\t\tif (!hptr || !hptr->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\t\t/*\n\t\t** Now find out where this player is in the score array\n\t\t*/\n\t\tscore_index = -1;\n\t\tfor (i = 0; i < Session.NumScores; i++) {\n\t\t\tif (!stricmp(hptr->IniName, Session.Score[i].Name)) {\n\t\t\t\tscore_index = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the index is still -1, the name wasn't found; add a new entry.\n\t\t*/\n\t\tif (score_index == -1) {\n\t\t\t/*\n\t\t\t** Just add this player to the end of the array, if there's room\n\t\t\t*/\n\t\t\tif (Session.NumScores < MAX_MULTI_NAMES) {\n\t\t\t\tscore_index = Session.NumScores;\n\t\t\t\tSession.NumScores++;\n\t\t\t}\n\t\t\t/*\n\t\t\t** If there's not room, we have to remove somebody.\n\t\t\t**\tFor each player in the scores array, count the # of '-1' entries\n\t\t\t**\tfrom this game backwards; the one with the most is the one that\n\t\t\t**\thasn't played the longest; replace him with this new guy.\n\t\t\t*/\n\t\t\telse {\n\t\t\t\tmax_index = 0;\n\t\t\t\tmax_count = 0;\n\t\t\t\tfor (j = 0; j < Session.NumScores; j++) {\n\t\t\t\t\tcount = 0;\n\t\t\t\t\tfor (k = Session.NumScores - 1; k >= 0; k--) {\n\t\t\t\t\t\tif (Session.Score[j].Kills[k]==-1) {\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (count > max_count) {\n\t\t\t\t\t\tmax_count = count;\n\t\t\t\t\t\tmax_index = j;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tscore_index = max_index;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInitialize this new score entry\n\t\t\t*/\n\t\t\tSession.Score[score_index].Wins = 0;\n\t\t\tstrcpy (Session.Score[score_index].Name, hptr->IniName);\n\t\t\tfor (j = 0; j < MAX_MULTI_GAMES; j++)\n\t\t\t\tSession.Score[score_index].Kills[j] = -1;\n\t\t}\n\n\t\t/*\n\t\t**\tInit this player's Kills to 0 (-1 means he didn't play this round;\n\t\t**\t0 means he played but got no kills).\n\t\t*/\n\t\tSession.Score[score_index].Kills[Session.CurGame] = 0;\n\n\t\t/*\n\t\t**\tInit this player's color to his last-used color index\n\t\t*/\n\t\tSession.Score[score_index].Color = hptr->RemapColor;\n\n\t\t/*\n\t\t**\tIf this house was undefeated, it must have been the winner.\n\t\t** (If no human houses are undefeated, the computer won.)\n\t\t*/\n\t\tif (!hptr->IsDefeated) {\n\t\t\tSession.Score[score_index].Wins++;\n\t\t\tSession.Winner = score_index;\n\t\t}\n\n\t\t/*\n\t\t**\tTally up all kills for this player\n\t\t*/\n\t\tfor (house2 = HOUSE_FIRST; house2 < HOUSE_COUNT; house2++) {\n\t\t\tSession.Score[score_index].Kills[Session.CurGame] += hptr->UnitsKilled[house2];\n\t\t\tSession.Score[score_index].Kills[Session.CurGame] += hptr->BuildingsKilled[house2];\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * HouseClass::Blowup_All -- blows up everything                           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1995 BRR : Created.                                             *\n *   06/09/1995 JLB : Handles aircraft.                                    *\n *   05/07/1996 JLB : Handles ships.                                       *\n *=========================================================================*/\nvoid HouseClass::Blowup_All(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint i;\n\tint damage;\n\tUnitClass * uptr;\n\tInfantryClass * iptr;\n\tBuildingClass * bptr;\n\tint count;\n\tWarheadType warhead;\n\n\t/*\n\t**\tFind everything owned by this house & blast it with a huge amount of damage\n\t**\tat zero range.  Do units before infantry, so the units' drivers are killed\n\t**\ttoo.  Using Explosion_Damage is like dropping a big bomb right on the\n\t**\tobject; it will also damage anything around it.\n\t*/\n\tfor (i = 0; i < ::Units.Count(); i++) {\n\t\tif (::Units.Ptr(i)->House == this && !::Units.Ptr(i)->IsInLimbo) {\n\t\t\tuptr = ::Units.Ptr(i);\n\n\t\t\t/*\n\t\t\t**\tSome units can't be killed with one shot, so keep damaging them until\n\t\t\t**\tthey're gone.  The unit will destroy itself, and put an infantry in\n\t\t\t**\tits place.  When the unit destroys itself, decrement 'i' since\n\t\t\t**\tits pointer will be removed from the active pointer list.\n\t\t\t*/\n\t\t\tcount = 0;\n\t\t\twhile (::Units.Ptr(i)==uptr && uptr->Strength) {\n\n\t\t\t\t// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840\n\t\t\t\t// Likely due to damage biasing based on RA factions and/or difficulty settings\n\t\t\t\t// Applying this to units (vehicles), ships, buildings, and infantry, too\n\t\t\t\t//\n\t\t\t\t// damage = uptr->Strength; // Original\n\t\t\t\tdamage = 0x7fff; // Copied from TD\n\n\t\t\t\tuptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5 && uptr->IsActive) {\n\t\t\t\t\tdelete uptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*\n\t**\tDestroy all aircraft owned by this house.\n\t*/\n\tfor (i = 0; i < ::Aircraft.Count(); i++) {\n\t\tif (::Aircraft.Ptr(i)->House == this && !::Aircraft.Ptr(i)->IsInLimbo) {\n\t\t\tAircraftClass * aptr = ::Aircraft.Ptr(i);\n\n\t\t\t// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840\n\t\t\t// Likely due to damage biasing based on RA factions and/or difficulty settings\n\t\t\t// Applying this to units (vehicles), ships, buildings, and infantry, too\n\t\t\t//\n\t\t\t// damage = aptr->Strength; // Original\n\t\t\tdamage = 0x7fff; // Copied from TD\n\n\t\t\taptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\tif (!aptr->IsActive) {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDestroy all vessels owned by this house.\n\t*/\n\tfor (i = 0; i < ::Vessels.Count(); i++) {\n\t\tif (::Vessels.Ptr(i)->House == this && !::Vessels.Ptr(i)->IsInLimbo) {\n\t\t\tVesselClass * vptr = ::Vessels.Ptr(i);\n\n\t\t\t// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840\n\t\t\t// Likely due to damage biasing based on RA factions and/or difficulty settings\n\t\t\t// Applying this to units (vehicles), ships, buildings, and infantry, too\n\t\t\t//\n\t\t\t// damage = vptr->Strength; // Original\n\t\t\tdamage = 0x7fff; // Copied from TD \n\n\t\t\tvptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\tif (!vptr->IsActive) {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tBuildings don't delete themselves when they die; they shake the screen\n\t**\tand begin a countdown, so don't decrement 'i' when it's destroyed.\n\t*/\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tif (Buildings.Ptr(i)->House == this && !Buildings.Ptr(i)->IsInLimbo) {\n\t\t\tbptr = Buildings.Ptr(i);\n\n\t\t\tcount = 0;\n\t\t\twhile (Buildings.Ptr(i)==bptr && bptr->Strength) {\n\n\t\t\t\t// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840\n\t\t\t\t// Likely due to damage biasing based on RA factions and/or difficulty settings\n\t\t\t\t// Applying this to units (vehicles), ships, buildings, and infantry, too\n\t\t\t\t//\n\t\t\t\t// damage = bptr->Strength; // Original\n\t\t\t\tdamage = 0x7fff; // Copied from TD \n\n\t\t\t\tbptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5) {\n\t\t\t\t\tdelete bptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tInfantry don't delete themselves when they die; they go into a death-\n\t**\tanimation sequence, so there's no need to decrement 'i' when they die.\n\t**\tInfantry should die by different types of warheads, so their death\n\t**\tanims aren't all synchronized.\n\t*/\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tif (Infantry.Ptr(i)->House == this && !Infantry.Ptr(i)->IsInLimbo) {\n\t\t\tiptr = Infantry.Ptr(i);\n\n\t\t\tcount = 0;\n\t\t\twhile (Infantry.Ptr(i)==iptr && iptr->Strength) {\n\n\t\t\t\t// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840\n\t\t\t\t// Likely due to damage biasing based on RA factions and/or difficulty settings\n\t\t\t\t// Applying this to units (vehicles), ships, buildings, and infantry, too\n\t\t\t\t//\n\t\t\t\t// damage = iptr->Strength; // Original\n\t\t\t\tdamage = 0x7fff; // Copied from TD \n\n\t\t\t\twarhead = Random_Pick(WARHEAD_SA, WARHEAD_FIRE);\n\t\t\t\tiptr->Take_Damage(damage, 0, warhead, NULL, true);\n\n\t\t\t\tcount++;\n\t\t\t\tif (count > 5) {\n\t\t\t\t\tdelete iptr;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Die -- Flags the house to blow up soon.                                 *\n *                                                                                             *\n *    When this routine is called, the house will blow up after a period of time. Typically    *\n *    this is called when the flag is captured or the HQ destroyed.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the house flagged to blow up?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Die(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsToWin && !IsToDie && !IsToLose) {\n\t\tIsToDie = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToDie);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Win -- Flags the house to win soon.                                     *\n *                                                                                             *\n *    When this routine is called, the house will be declared the winner after a period of     *\n *    time.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the house flagged to win?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Win(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsToWin && !IsToDie && !IsToLose) {\n\t\tIsToWin = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToWin);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Flag_To_Lose -- Flags the house to die soon.                                    *\n *                                                                                             *\n *    When this routine is called, it will spell the doom of this house. In a short while      *\n *    all of the object owned by this house will explode. Typical use of this routine is when  *\n *    the flag has been captured or the command vehicle has been destroyed.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Has the doom been initiated?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Flag_To_Lose(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tIsToWin = false;\n\tif (!IsToDie && !IsToLose) {\n\t\tIsToLose = true;\n\t\tBorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;\n\t}\n\treturn(IsToLose);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Init_Data -- Initializes the multiplayer color data.                            *\n *                                                                                             *\n *    This routine is called when initializing the color and remap data for this house. The    *\n *    primary user of this routine is the multiplayer version of the game, especially for\t\t  *\n *    saving & loading multiplayer games.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   color    -- The color of this house.                                               *\n *                                                                                             *\n *          house    -- The house that this should act like.                                   *\n *                                                                                             *\n *          credits  -- The initial credits to assign to this house.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern bool NowSavingGame; // TEMP MBL: Need to discuss better solution with Steve\nvoid HouseClass::Init_Data(PlayerColorType color, HousesType house, int credits)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tCredits = Control.InitialCredits = credits;\n\tVisibleCredits.Current = Credits;\n\tRemapColor = color;\n\tActLike = house;\n\n\t// MBL 03.20.2020 \n\t// Attempt to fix Red Alert credit tick-up bug after saving a game that has had harvesting underway\n\t// Note that this code gets called with both game loads and saves\n\t// When this function is called, sometimes credits value has Tiberium (or HarvestedCredits?) variables applied, and sometimes now\n\t//\n\tif (NowSavingGame == true) \n\t{\n\t\t// At this point VisibleCredits.Current (set above) does not have harvested ore/tiberium applied, but VisibleCredits.Credits does\n\t\tVisibleCredits.Current = VisibleCredits.Credits;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Power_Fraction -- Fetches the current power output rating.                      *\n *                                                                                             *\n *    Use this routine to fetch the current power output as a fixed point fraction. The        *\n *    value 0x0100 is 100% power.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with power rating as a fixed pointer number.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed HouseClass::Power_Fraction(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Power >= Drain || Drain == 0) return(1);\n\n\tif (Power) {\n\t\treturn(fixed(Power, Drain));\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                  *\n *                                                                                             *\n *    This routine will try to sell the wall at the specified location. If there is a wall     *\n *    present and it is owned by this house, then it can be sold.                              *\n *                                                                                             *\n * INPUT:   cell  -- The cell that wall selling is desired.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1995 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Checks unsellable bit for wall type.                                     *\n *=============================================================================================*/\nvoid HouseClass::Sell_Wall(CELL cell)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif ((unsigned)cell > 0) {\n\t\tOverlayType overlay = Map[cell].Overlay;\n\n\t\tif (overlay != OVERLAY_NONE && Map[cell].Owner == Class->House) {\n\t\t\tOverlayTypeClass const & optr = OverlayTypeClass::As_Reference(overlay);\n\n\t\t\tif (optr.IsWall) {\n\t\t\t\tBuildingTypeClass const * btype = NULL;\n\t\t\t\tswitch (overlay) {\n\t\t\t\t\tcase OVERLAY_SANDBAG_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_SANDBAG_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_CYCLONE_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_CYCLONE_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_BRICK_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_BRICK_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_BARBWIRE_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_BARBWIRE_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_WOOD_WALL:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_WOOD_WALL);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OVERLAY_FENCE:\n\t\t\t\t\t\tbtype = &BuildingTypeClass::As_Reference(STRUCT_FENCE);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (btype != NULL && !btype->IsUnsellable) {\n\n\t\t\t\t\tif (PlayerPtr == this) {\n\t\t\t\t\t\tSound_Effect(VOC_CASHTURN);\n\t\t\t\t\t}\n\n\t\t\t\t\tRefund_Money(btype->Raw_Cost() * Rule.RefundPercent);\n\t\t\t\t\tMap[cell].Overlay = OVERLAY_NONE;\n\t\t\t\t\tMap[cell].OverlayData = 0;\n\t\t\t\t\tMap[cell].Owner = HOUSE_NONE;\n\t\t\t\t\tMap[cell].Wall_Update();\n\t\t\t\t\tCellClass * ncell = Map[cell].Adjacent_Cell(FACING_N);\n\t\t\t\t\tif (ncell) ncell->Wall_Update();\n\t\t\t\t\tCellClass * wcell = Map[cell].Adjacent_Cell(FACING_W);\n\t\t\t\t\tif (wcell) wcell->Wall_Update();\n\t\t\t\t\tCellClass * scell = Map[cell].Adjacent_Cell(FACING_S);\n\t\t\t\t\tif (scell) scell->Wall_Update();\n\t\t\t\t\tCellClass * ecell = Map[cell].Adjacent_Cell(FACING_E);\n\t\t\t\t\tif (ecell) ecell->Wall_Update();\n\t\t\t\t\tMap[cell].Recalc_Attributes();\n\t\t\t\t\tMap[cell].Redraw_Objects();\n\t\t\t\t\tMap.Radar_Pixel(cell);\n\t\t\t\t\tDetach_This_From_All(::As_Target(cell), true);\n\n\t\t\t\t\tif (optr.IsCrushable) {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_NORMAL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMap.Zone_Reset(MZONEF_CRUSHER|MZONEF_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.         *\n *                                                                                             *\n *    This routine is called when a construction yard needs to know what to build next. It     *\n *    will either examine the prebuilt base list or try to figure out what to build next       *\n *    based on the current game situation.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building type class to build.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingTypeClass const * HouseClass::Suggest_New_Building(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildStructure != STRUCT_NONE) {\n\t\treturn(&BuildingTypeClass::As_Reference(BuildStructure));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Building -- Finds a building of specified type.                            *\n *                                                                                             *\n *    This routine is used to find a building of the specified type. This is particularly      *\n *    useful for when some event requires a specific building instance. The nuclear missile    *\n *    launch is a good example.                                                                *\n *                                                                                             *\n * INPUT:   type  -- The building type to scan for.                                            *\n *                                                                                             *\n *          zone  -- The zone that the building must be located in. If no zone specific search *\n *                   is desired, then pass ZONE_NONE.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building type requested. If there is no building     *\n *          of the type requested, then NULL is returned.                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *   10/02/1995 JLB : Allows for zone specifics.                                               *\n *=============================================================================================*/\nBuildingClass * HouseClass::Find_Building(StructType type, ZoneType zone) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tOnly scan if we KNOW there is at least one building of the type\n\t**\trequested.\n\t*/\n\tif (BQuantity[type] > 0) {\n\n\t\t/*\n\t\t**\tSearch for a suitable launch site for this missile.\n\t\t*/\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\t\t\tif (b && !b->IsInLimbo && b->House == this && *b == type) {\n\t\t\t\tif (zone == ZONE_NONE || Which_Zone(b) == zone) {\n\t\t\t\t\treturn(b);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Build_Location -- Finds a suitable building location.                      *\n *                                                                                             *\n *    This routine is used to find a suitable building location for the building specified.    *\n *    The auto base building logic uses this when building the base for the computer.          *\n *                                                                                             *\n * INPUT:   building -- Pointer to the building that needs to be placed down.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to place the building at. If there are no suitable     *\n *          locations, then NULL is returned.                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE HouseClass::Find_Build_Location(BuildingClass * building) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint zonerating[ZONE_COUNT];\n\tstruct {\n\t\tint AntiAir;\t\t\t// Average air defense for the base.\n\t\tint AntiArmor;\t\t\t// Average armor defense for the base.\n\t\tint AntiInfantry;\t\t// Average infantry defense for the base.\n\t} zoneinfo = {0,0,0};\n\tint antiair = building->Anti_Air();\n\tint antiarmor = building->Anti_Armor();\n\tint antiinfantry = building->Anti_Infantry();\n\tbool adj = true;\n\n\t/*\n\t**\tNever place combat buildings adjacent to each other. This is partly\n\t**\tbecause combat buildings don't have a bib and jamming will occur as well\n\t**\tas because spacing defensive buildings out will yield a better\n\t**\tdefense.\n\t*/\n\tif (antiair || antiarmor || antiinfantry) {\n\t\tadj = false;\n\t}\n\n\t/*\n\t**\tDetermine the average zone strengths for the base. This value is\n\t**\tused to determine what zones are considered under or over strength.\n\t*/\n\tZoneType z;\n\tfor (z = ZONE_NORTH; z < ZONE_COUNT; z++) {\n\t\tzoneinfo.AntiAir += ZoneInfo[z].AirDefense;\n\t\tzoneinfo.AntiArmor += ZoneInfo[z].ArmorDefense;\n\t\tzoneinfo.AntiInfantry += ZoneInfo[z].InfantryDefense;\n\t}\n\tzoneinfo.AntiAir /= ZONE_COUNT-ZONE_NORTH;\n\tzoneinfo.AntiArmor /= ZONE_COUNT-ZONE_NORTH;\n\tzoneinfo.AntiInfantry /= ZONE_COUNT-ZONE_NORTH;\n\n\t/*\n\t**\tGive each zone a rating for value. The higher the value the more desirable\n\t**\tto place the specified building in that zone. Factor the average value of\n\t**\tzone defense such that more weight is given to zones that are very under\n\t**\tdefended.\n\t*/\n\tmemset(&zonerating[0], '\\0', sizeof(zonerating));\n\tfor (z = ZONE_FIRST; z < ZONE_COUNT; z++) {\n\t\tint diff;\n\n\t\tdiff = zoneinfo.AntiAir-ZoneInfo[z].AirDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiair, diff);\n\t\t}\n\n\t\tdiff = zoneinfo.AntiArmor-ZoneInfo[z].ArmorDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiarmor, diff);\n\t\t}\n\n\t\tdiff = zoneinfo.AntiInfantry-ZoneInfo[z].InfantryDefense;\n\t\tif (z == ZONE_CORE) diff /= 2;\n\t\tif (diff > 0) {\n\t\t\tzonerating[z] += min(antiinfantry, diff);\n\t\t}\n\t}\n\n\t/*\n\t**\tNow that each zone has been given a desirability rating, find the zone\n\t**\twith the greatest value and try to place the building in that zone.\n\t*/\n\tZoneType zone = Random_Pick(ZONE_FIRST, ZONE_WEST);\n\tint largest = 0;\n\tfor (z = ZONE_FIRST; z < ZONE_COUNT; z++) {\n\t\tif (zonerating[z] > largest) {\n\t\t\tzone = z;\n\t\t\tlargest = zonerating[z];\n\t\t}\n\t}\n\n\tCELL zcell = Find_Cell_In_Zone(building, zone);\n\tif (zcell) {\n\t\treturn(Cell_Coord(zcell));\n\t}\n\n\t/*\n\t**\tCould not build in preferred zone, so try building in any zone.\n\t*/\n\tstatic ZoneType _zones[] = {ZONE_CORE, ZONE_NORTH, ZONE_SOUTH, ZONE_EAST, ZONE_WEST};\n\tint start = Random_Pick(0, ARRAY_SIZE(_zones)-1);\n\tfor (int zz = 0; zz < ARRAY_SIZE(_zones); zz++) {\n\t\tZoneType tryzone = _zones[(zz + start) % ARRAY_SIZE(_zones)];\n\t\tzcell = Find_Cell_In_Zone(building, tryzone);\n\t\tif (zcell) return(zcell);\n\t}\n\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Recalc_Center -- Recalculates the center point of the base.                     *\n *                                                                                             *\n *    This routine will average the location of the base and record the center point. The      *\n *    recorded center point is used to determine such things as how far the base is spread     *\n *    out and where to protect the most. This routine should be called whenever a building     *\n *    is created or destroyed.                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Recalc_Center(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tFirst presume that there is no base. If there is a base, then these values will be\n\t**\tproperly filled in below.\n\t*/\n\tCenter = 0;\n\tRadius = 0;\n\tfor (ZoneType zone = ZONE_FIRST; zone < ZONE_COUNT; zone++) {\n\t\tZoneInfo[zone].AirDefense = 0;\n\t\tZoneInfo[zone].ArmorDefense = 0;\n\t\tZoneInfo[zone].InfantryDefense = 0;\n\t}\n\n\t/*\n\t**\tOnly process the center base size/position calculation if there are buildings to\n\t**\tconsider. When no buildings for this house are present, then no processing need\n\t**\toccur.\n\t*/\n\tif (CurBuildings > 0) {\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tint count = 0;\n\t\tint index;\n\n\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tGive more \"weight\" to buildings that cost more. The presumption is that cheap\n\t\t\t\t**\tbuildings don't affect the base disposition as much as the more expensive\n\t\t\t\t**\tbuildings do.\n\t\t\t\t*/\n\t\t\t\tint weight = (b->Class->Cost_Of() / 1000)+1;\n\t\t\t\tfor (int i = 0; i < weight; i++) {\n\t\t\t\t\tx += Coord_X(b->Center_Coord());\n\t\t\t\t\ty += Coord_Y(b->Center_Coord());\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThis second check for quantity of buildings is necessary because the first\n\t\t**\tcheck against CurBuildings doesn't take into account if the building is in\n\t\t**\tlimbo, but for base calculation, the limbo state disqualifies a building\n\t\t**\tfrom being processed. Thus, CurBuildings may indicate a base, but count may\n\t\t**\tnot match.\n\t\t*/\n\t\tif (count > 0) {\n\t\t\tx /= count;\n\t\t\ty /= count;\n\n#ifdef NEVER\n\t\t\t/*\n\t\t\t**\tBias the center of the base away from the edges of the map.\n\t\t\t*/\n\t\t\tLEPTON left = Cell_To_Lepton(Map.MapCellX + 10);\n\t\t\tLEPTON top = Cell_To_Lepton(Map.MapCellY + 10);\n\t\t\tLEPTON right = Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth - 10);\n\t\t\tLEPTON bottom = Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight - 10);\n\t\t\tif (x < left) x = left;\n\t\t\tif (x > right) x = right;\n\t\t\tif (y < top) y = top;\n\t\t\tif (y > bottom) y = bottom;\n#endif\n\n\t\t\tCenter = XY_Coord(x, y);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there were any buildings discovered as legal to consider as part of the base,\n\t\t**\tthen figure out the general average radius of the building disposition as it\n\t\t**\trelates to the center of the base.\n\t\t*/\n\t\tif (count > 1) {\n\t\t\tint radius = 0;\n\t\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\t\t\t\t\tradius += Distance(Center, b->Center_Coord());\n\t\t\t\t}\n\t\t\t}\n\t\t\tRadius = max(radius / count, 2 * CELL_LEPTON_W);\n\n\t\t\t/*\n\t\t\t**\tDetermine the relative strength of each base defense zone.\n\t\t\t*/\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\t\tBuildingClass const * b = Buildings.Ptr(index);\n\n\t\t\t\tif (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {\n\t\t\t\t\tZoneType z = Which_Zone(b);\n\n\t\t\t\t\tif (z != ZONE_NONE) {\n\t\t\t\t\t\tZoneInfo[z].ArmorDefense += b->Anti_Armor();\n\t\t\t\t\t\tZoneInfo[z].AirDefense += b->Anti_Air();\n\t\t\t\t\t\tZoneInfo[z].InfantryDefense += b->Anti_Infantry();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tRadius = 0x0200;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Expert_AI -- Handles expert AI processing.                                      *\n *                                                                                             *\n *    This routine is called when the computer should perform expert AI processing. This       *\n *    method of AI is categorized as an \"Expert System\" process.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of game frames to delay before calling this routine again.      *\n *                                                                                             *\n * WARNINGS:   This is relatively time consuming -- call periodically.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Expert_AI(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tBuildingClass * b = 0;\n\tbool stop = false;\n\tint time = TICKS_PER_SECOND * 10;\n\n\t/*\n\t**\tIf the current enemy no longer has a base or is defeated, then don't consider\n\t**\tthat house a threat anymore. Clear out the enemy record and then try\n\t**\tto find a new enemy.\n\t*/\n\tif (Enemy != HOUSE_NONE) {\n\t\tHouseClass * h = HouseClass::As_Pointer(Enemy);\n\n\t\tif (h == NULL || !h->IsActive || h->IsDefeated || Is_Ally(h) || h->BScan == 0) {\n\t\t\tEnemy = HOUSE_NONE;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is no enemy assigned to this house, then assign one now. The\n\t**\tenemy that is closest is picked. However, don't pick an enemy if the\n\t**\tbase has not been established yet.\n\t*/\n\tif (ActiveBScan && Center && Attack == 0) {\n\t\tint close = 0;\n\t\tHousesType enemy = HOUSE_NONE;\n\t\tint maxunit = 0;\n\t\tint maxinfantry = 0;\n\t\tint maxvessel = 0;\n\t\tint maxaircraft = 0;\n\t\tint maxbuilding = 0;\n\t\tint enemycount = 0;\n\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\t\t\tif (h != NULL && h->IsActive && !h->IsDefeated && !Is_Ally(h)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPerform a special restriction check to ensure that no enemy is chosen if\n\t\t\t\t**\tthere is even one enemy that has not established a base yet. This will\n\t\t\t\t**\tensure an accurate first pick for enemy since the distance to base\n\t\t\t\t**\tvalue can be determined.\n\t\t\t\t*/\n\t\t\t\tif (!h->IsStarted) {\n\t\t\t\t\tenemy = HOUSE_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tKeep track of the number of buildings and units owned by the\n\t\t\t\t**\tenemy. This is used to bring up the maximum allowed to match.\n\t\t\t\t*/\n\t\t\t\tmaxunit += h->CurUnits;\n\t\t\t\tmaxbuilding += h->CurBuildings;\n\t\t\t\tmaxinfantry += h->CurInfantry;\n\t\t\t\tmaxvessel += h->CurVessels;\n\t\t\t\tmaxaircraft += h->CurAircraft;\n\t\t\t\tenemycount++;\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine a priority value based on distance to the center of the\n\t\t\t\t**\tcandidate base. The higher the value, the better the candidate house\n\t\t\t\t**\tis to becoming the preferred enemy for this house.\n\t\t\t\t*/\n\t\t\t\tint value = ((MAP_CELL_W*2)-Distance(Center, h->Center));\n\t\t\t\tvalue *= 2;\n\n\t\t\t\t/*\n\t\t\t\t**\tIn addition to distance, record the number of kills directed\n\t\t\t\t**\tagainst this house. The enemy that does more damage might be\n\t\t\t\t**\tconsidered a greater threat.\n\t\t\t\t*/\n\t\t\t\tvalue += h->BuildingsKilled[Class->House]*5;\n\t\t\t\tvalue += h->UnitsKilled[Class->House];\n\n\t\t\t\t/*\n\t\t\t\t**\tFactor in the relative sizes of the bases. An enemy that has a\n\t\t\t\t**\tlarger base will be considered a bigger threat. Conversely, a\n\t\t\t\t**\tsmaller base is considered a lesser threat.\n\t\t\t\t*/\n\t\t\t\tvalue += h->CurUnits - CurUnits;\n\t\t\t\tvalue += h->CurBuildings - CurBuildings;\n\t\t\t\tvalue += (h->CurInfantry - CurInfantry)/4;\n\n\t\t\t\t/*\n\t\t\t\t**\tWhoever last attacked is given a little more priority as\n\t\t\t\t**\ta potential designated enemy.\n\t\t\t\t*/\n\t\t\t\tif (house == LAEnemy) {\n\t\t\t\t\tvalue += 100;\n\t\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t\t/*\n\t\t\t\t**\tHuman players are a given preference as the target.\n\t\t\t\t*/\n\t\t\t\tif (h->IsHuman) {\n\t\t\t\t\tvalue *= 2;\n\t\t\t\t}\n#endif\n\n\t\t\t\t/*\n\t\t\t\t**\tCompare the calculated value for this candidate house and if it is\n\t\t\t\t**\tgreater than the previously recorded maximum, record this house as\n\t\t\t\t**\tthe prime candidate for enemy.\n\t\t\t\t*/\n\t\t\t\tif (value > close) {\n\t\t\t\t\tenemy = house;\n\t\t\t\t\tclose = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRecord this closest enemy base as the first enemy to attack.\n\t\t*/\n\t\tEnemy = enemy;\n\n\t\t/*\n\t\t**\tUp the maximum allowed units and buildings to match a rough average\n\t\t**\tof what the enemies are allowed.\n\t\t*/\n\t\tif (enemycount) {\n\t\t\tmaxunit /= enemycount;\n\t\t\tmaxbuilding /= enemycount;\n\t\t\tmaxinfantry /= enemycount;\n\t\t\tmaxvessel /= enemycount;\n\t\t\tmaxaircraft /= enemycount;\n\t\t}\n\n\t\tif (Control.MaxBuilding < (unsigned)maxbuilding + 10) {\n\t\t\tControl.MaxBuilding = maxbuilding + 10;\n\t\t}\n\t\tif (Control.MaxUnit < (unsigned)maxunit + 10) {\n\t\t\tControl.MaxUnit = maxunit + 10;\n\t\t}\n\t\tif (Control.MaxInfantry < (unsigned)maxinfantry + 10) {\n\t\t\tControl.MaxInfantry = maxinfantry + 10;\n\t\t}\n\t\tif (Control.MaxVessel < (unsigned)maxvessel + 10) {\n\t\t\tControl.MaxVessel = maxvessel + 10;\n\t\t}\n\t\tif (Control.MaxAircraft < (unsigned)maxaircraft + 10) {\n\t\t\tControl.MaxAircraft = maxaircraft + 10;\n\t\t}\n\t}\n\n\t/*\n\t**\tHouse state transition check occurs here. Transitions that occur here are ones\n\t**\tthat relate to general base condition rather than specific combat events.\n\t**\tTypically, this is limited to transitions between normal buildup mode and\n\t**\tbroke mode.\n\t*/\n\tif (State == STATE_ENDGAME) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t} else {\n\t\tif (State == STATE_BUILDUP) {\n\t\t\tif (Available_Money() < 25) {\n\t\t\t\tState = STATE_BROKE;\n\t\t\t}\n\t\t}\n\t\tif (State == STATE_BROKE) {\n\t\t\tif (Available_Money() >= 25) {\n\t\t\t\tState = STATE_BUILDUP;\n\t\t\t}\n\t\t}\n\t\tif (State == STATE_ATTACKED && LATime + TICKS_PER_MINUTE < Frame) {\n\t\t\tState = STATE_BUILDUP;\n\t\t}\n\t\tif (State != STATE_ATTACKED && LATime + TICKS_PER_MINUTE > Frame) {\n\t\t\tState = STATE_ATTACKED;\n\t\t}\n\t}\n\n\t/*\n\t**\tRecords the urgency of all actions possible.\n\t*/\n\tUrgencyType urgency[STRATEGY_COUNT];\n\tStrategyType strat;\n\tfor (strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {\n\t\turgency[strat] = URGENCY_NONE;\n\n\t\tswitch (strat) {\n\t\t\tcase STRATEGY_BUILD_POWER:\n\t\t\t\turgency[strat] = Check_Build_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_DEFENSE:\n\t\t\t\turgency[strat] = Check_Build_Defense();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_INCOME:\n\t\t\t\turgency[strat] = Check_Build_Income();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_FIRE_SALE:\n\t\t\t\turgency[strat] = Check_Fire_Sale();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_ENGINEER:\n\t\t\t\turgency[strat] = Check_Build_Engineer();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_BUILD_OFFENSE:\n\t\t\t\turgency[strat] = Check_Build_Offense();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_RAISE_MONEY:\n\t\t\t\turgency[strat] = Check_Raise_Money();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_RAISE_POWER:\n\t\t\t\turgency[strat] = Check_Raise_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_LOWER_POWER:\n\t\t\t\turgency[strat] = Check_Lower_Power();\n\t\t\t\tbreak;\n\n\t\t\tcase STRATEGY_ATTACK:\n\t\t\t\turgency[strat] = Check_Attack();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\turgency[strat] = URGENCY_NONE;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPerforms the action required for each of the strategies that share\n\t**\tthe most urgent category. Stop processing if any strategy at the\n\t**\thighest urgency performed any action. This is because higher urgency\n\t**\tactions tend to greatly affect the lower urgency actions.\n\t*/\n\tfor (UrgencyType u = URGENCY_CRITICAL; u >= URGENCY_LOW; u--) {\n\t\tbool acted = false;\n\n\t\tfor (strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {\n\t\t\tif (urgency[strat] == u) {\n\t\t\t\tswitch (strat) {\n\t\t\t\t\tcase STRATEGY_BUILD_POWER:\n\t\t\t\t\t\tacted |= AI_Build_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_DEFENSE:\n\t\t\t\t\t\tacted |= AI_Build_Defense(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_INCOME:\n\t\t\t\t\t\tacted |= AI_Build_Income(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_FIRE_SALE:\n\t\t\t\t\t\tacted |= AI_Fire_Sale(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_ENGINEER:\n\t\t\t\t\t\tacted |= AI_Build_Engineer(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_BUILD_OFFENSE:\n\t\t\t\t\t\tacted |= AI_Build_Offense(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_RAISE_MONEY:\n\t\t\t\t\t\tacted |= AI_Raise_Money(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_RAISE_POWER:\n\t\t\t\t\t\tacted |= AI_Raise_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_LOWER_POWER:\n\t\t\t\t\t\tacted |= AI_Lower_Power(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase STRATEGY_ATTACK:\n\t\t\t\t\t\tacted |= AI_Attack(u);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND*5 + Random_Pick(1, TICKS_PER_SECOND/2));\n}\n\n\nUrgencyType HouseClass::Check_Build_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tfixed frac = Power_Fraction();\n\tUrgencyType urgency = URGENCY_NONE;\n\n\tif (frac < 1 && Can_Make_Money()) {\n\t\turgency = URGENCY_LOW;\n\n\t\t/*\n\t\t**\tVery low power condition is considered a higher priority.\n\t\t*/\n\t\tif (frac < fixed::_3_4) urgency = URGENCY_MEDIUM;\n\n\t\t/*\n\t\t**\tWhen under attack and there is a need for power in defense,\n\t\t**\tthen consider power building a higher priority.\n\t\t*/\n\t\tif (State == STATE_THREATENED || State == STATE_ATTACKED) {\n\t\t\tif (BScan | (STRUCTF_CHRONOSPHERE)) {\n\t\t\t\turgency = URGENCY_HIGH;\n\t\t\t}\n\t\t}\n\n\t}\n\treturn(urgency);\n}\n\n\nUrgencyType HouseClass::Check_Build_Defense(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine determines what urgency level that base defense\n\t**\tshould be given. The more vulnerable the base is, the higher\n\t**\tthe urgency this routine should return.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Offense(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine determines what urgency level that offensive\n\t**\tweaponry should be given. Surplus money or a very strong\n\t**\tdefense will cause the offensive urgency to increase.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n/*\n**\tDetermines what the attack state of the base is. The higher the state,\n**\tthe greater the immediate threat to base defense is.\n*/\nUrgencyType HouseClass::Check_Attack(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Frame > TICKS_PER_MINUTE && Attack == 0) {\n\t\tif (State == STATE_ATTACKED) {\n\t\t\treturn(URGENCY_LOW);\n\t\t}\n\t\treturn(URGENCY_CRITICAL);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Income(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine should determine if income processing buildings\n\t**\tshould be constructed and at what urgency. The lower the money,\n\t**\tthe lower the refineries, or recent harvester losses should\n\t**\tcause a greater urgency to be returned.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Fire_Sale(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tIf there are no more factories at all, then sell everything off because the game\n\t**\tis basically over at this point.\n\t*/\n\tif (State != STATE_ATTACKED && CurBuildings && !(ActiveBScan & (STRUCTF_TENT|STRUCTF_BARRACKS|STRUCTF_CONST|STRUCTF_AIRSTRIP|STRUCTF_WEAP|STRUCTF_HELIPAD))) {\n\t\treturn(URGENCY_CRITICAL);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n\nUrgencyType HouseClass::Check_Build_Engineer(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tThis routine should check to see what urgency that the production of\n\t**\tengineers should be. If a friendly building has been captured or the\n\t**\tenemy has weak defenses, then building an engineer would be a priority.\n\t*/\n\treturn(URGENCY_NONE);\n}\n\n\n/*\n**\tChecks to see if money is critically low and something must be done\n**\tto immediately raise cash.\n*/\nUrgencyType HouseClass::Check_Raise_Money(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUrgencyType urgency = URGENCY_NONE;\n\tif (Available_Money() < 100) {\n\t\turgency = URGENCY_LOW;\n\t}\n\tif (Available_Money() < 2000 && !Can_Make_Money()) {\n\t\turgency++;\n\t}\n\n\treturn(urgency);\n}\n\n/*\n**\tChecks to see if power is very low and if so, a greater urgency to\n**\tbuild more power is returned.\n*/\nUrgencyType HouseClass::Check_Lower_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (Power > Drain+300) {\n\t\treturn(URGENCY_LOW);\n\t}\n\treturn(URGENCY_NONE);\n}\n\n/*\n**\tThis routine determines if there is a power emergency. Such an\n**\temergency might require selling of structures in order to free\n**\tup power. This might occur if the base is being attacked and there\n**\tare defenses that require power, but are just short of having\n**\tenough.\n*/\nUrgencyType HouseClass::Check_Raise_Power(void) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUrgencyType urgency = URGENCY_NONE;\n\n\tif (Power_Fraction() < Rule.PowerEmergencyFraction && Power < Drain - 400) {\n//\tif (Power_Fraction() < Rule.PowerEmergencyFraction && (BQuantity[STRUCT_CONST] == 0 || Available_Money() < 200 || Power < Drain-400)) {\n\t\turgency = URGENCY_MEDIUM;\n\t\tif (State == STATE_ATTACKED) {\n\t\t\turgency++;\n\t\t}\n\t}\n\treturn(urgency);\n}\n\n\nbool HouseClass::AI_Attack(UrgencyType )\n{\n\tassert(Houses.ID(this) == ID);\n\n\tbool shuffle = !((Frame > TICKS_PER_MINUTE && !CurBuildings) || Percent_Chance(33));\n\tbool forced = (CurBuildings == 0);\n\tint index;\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * a = Aircraft.Ptr(index);\n\n\t\tif (a != NULL && !a->IsInLimbo && a->House == this && a->Strength > 0) {\n\t\t\tif (!shuffle && a->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {\n\t\t\t\ta->Assign_Mission(MISSION_HUNT);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * u = Units.Ptr(index);\n\n\t\tif (u != NULL && !u->IsInLimbo && u->House == this && u->Strength > 0) {\n\t\t\tif (!shuffle && u->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {\n\t\t\t\tu->Assign_Mission(MISSION_HUNT);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this unit is guarding the base, then cause it to shuffle\n\t\t\t\t**\tlocation instead.\n\t\t\t\t*/\n\t\t\t\tif (Percent_Chance(20) && u->Mission == MISSION_GUARD_AREA && Which_Zone(u) != ZONE_NONE) {\n\t\t\t\t\tu->ArchiveTarget = ::As_Target(Where_To_Go(u));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * i = Infantry.Ptr(index);\n\n\t\tif (i != NULL && !i->IsInLimbo && i->House == this && i->Strength > 0) {\n\t\t\tif (!shuffle && (i->Is_Weapon_Equipped() || *i == INFANTRY_RENOVATOR) && (forced || Percent_Chance(75))) {\n\t\t\t\ti->Assign_Mission(MISSION_HUNT);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this soldier is guarding the base, then cause it to shuffle\n\t\t\t\t**\tlocation instead.\n\t\t\t\t*/\n\t\t\t\tif (Percent_Chance(20) && i->Mission == MISSION_GUARD_AREA && Which_Zone(i) != ZONE_NONE) {\n\t\t\t\t\ti->ArchiveTarget = ::As_Target(Where_To_Go(i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAttack = Rule.AttackInterval * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);\n\treturn(true);\n}\n\n\n/*\n**\tGiven the specified urgency, build a power structure to meet\n**\tthis need.\n*/\nbool HouseClass::AI_Build_Power(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n\n/*\n**\tGiven the specified urgency, build base defensive structures\n**\taccording to need and according to existing base disposition.\n*/\nbool HouseClass::AI_Build_Defense(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build offensive units according\n**\tto need and according to the opponents base defenses.\n*/\nbool HouseClass::AI_Build_Offense(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build income producing\n**\tstructures according to need.\n*/\nbool HouseClass::AI_Build_Income(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n\nbool HouseClass::AI_Fire_Sale(UrgencyType urgency)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (CurBuildings && urgency == URGENCY_CRITICAL) {\n\t\tFire_Sale();\n\t\tDo_All_To_Hunt();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, build an engineer.\n*/\nbool HouseClass::AI_Build_Engineer(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(false);\n}\n\n/*\n**\tGiven the specified urgency, sell of some power since\n**\tthere appears to be excess.\n*/\nbool HouseClass::AI_Lower_Power(UrgencyType ) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tBuildingClass * b = Find_Building(STRUCT_POWER);\n\tif (b != NULL) {\n\t\tb->Sell_Back(1);\n\t\treturn(true);\n\t}\n\n\tb = Find_Building(STRUCT_ADVANCED_POWER);\n\tif (b != NULL) {\n\t\tb->Sell_Back(1);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.           *\n *                                                                                             *\n *    This routine is called when the computer needs to raise power by selling off buildings.  *\n *    Usually this occurs because of some catastrophe that has lowered power levels to         *\n *    the danger zone.                                                                         *\n *                                                                                             *\n * INPUT:   urgency  -- The urgency that the power needs to be raised. This controls what      *\n *                      buildings will be sold.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Was a building sold to raise power?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::AI_Raise_Power(UrgencyType urgency) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tSell off structures in this order.\n\t*/\n\tstatic struct {\n\t\tStructType Structure;\n\t\tUrgencyType Urgency;\n\t} _types[] = {\n\t\t{STRUCT_CHRONOSPHERE, URGENCY_LOW},\n\t\t{STRUCT_SHIP_YARD, URGENCY_LOW},\n\t\t{STRUCT_SUB_PEN, URGENCY_LOW},\n\t\t{STRUCT_ADVANCED_TECH, URGENCY_LOW},\n\t\t{STRUCT_FORWARD_COM, URGENCY_LOW},\n\t\t{STRUCT_SOVIET_TECH, URGENCY_LOW},\n\t\t{STRUCT_IRON_CURTAIN, URGENCY_MEDIUM},\n\t\t{STRUCT_RADAR, URGENCY_MEDIUM},\n\t\t{STRUCT_REPAIR, URGENCY_MEDIUM},\n\t\t{STRUCT_TESLA, URGENCY_HIGH}\n\t};\n\n\t/*\n\t**\tFind a structure to sell and then sell it. Bail from further scanning until\n\t**\tthe next time.\n\t*/\n\tfor (int i = 0; i < ARRAY_SIZE(_types); i++) {\n\t\tif (urgency >= _types[i].Urgency) {\n\t\t\tBuildingClass * b = Find_Building(_types[i].Structure);\n\t\t\tif (b != NULL) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                    *\n *                                                                                             *\n *    This routine handles the situation where the computer desperately needs cash but cannot  *\n *    wait for normal harvesting to raise it. Buildings must be sold.                          *\n *                                                                                             *\n * INPUT:   urgency  -- The urgency level that cash must be raised. The greater the urgency,   *\n *                      the more important the buildings that can be sold become.              *\n *                                                                                             *\n * OUTPUT:  bool; Was a building sold to raise cash?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::AI_Raise_Money(UrgencyType urgency) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tSell off structures in this order.\n\t*/\n\tstatic struct {\n\t\tStructType\tStructure;\n\t\tUrgencyType\tUrgency;\n\t} _types[] = {\n\t\t{STRUCT_CHRONOSPHERE, URGENCY_LOW},\n\t\t{STRUCT_SHIP_YARD, URGENCY_LOW},\n\t\t{STRUCT_SUB_PEN, URGENCY_LOW},\n\t\t{STRUCT_ADVANCED_TECH, URGENCY_LOW},\n\t\t{STRUCT_FORWARD_COM, URGENCY_LOW},\n\t\t{STRUCT_SOVIET_TECH, URGENCY_LOW},\n\t\t{STRUCT_STORAGE,URGENCY_LOW},\n\t\t{STRUCT_REPAIR,URGENCY_LOW},\n\t\t{STRUCT_TESLA,URGENCY_MEDIUM},\n\t\t{STRUCT_HELIPAD,URGENCY_MEDIUM},\n\t\t{STRUCT_POWER,URGENCY_HIGH},\n\t\t{STRUCT_AIRSTRIP,URGENCY_HIGH},\n//\t\t{STRUCT_WEAP,URGENCY_HIGH},\n//\t\t{STRUCT_BARRACKS,URGENCY_HIGH},\n//\t\t{STRUCT_TENT,URGENCY_HIGH},\n\t\t{STRUCT_CONST,URGENCY_CRITICAL}\n\t};\n\tBuildingClass * b = 0;\n\n\t/*\n\t**\tFind a structure to sell and then sell it. Bail from further scanning until\n\t**\tthe next time.\n\t*/\n\tfor (int i = 0; i < ARRAY_SIZE(_types); i++) {\n\t\tif (urgency >= _types[i].Urgency) {\n\t\t\tb = Find_Building(_types[i].Structure);\n\t\t\tif (b != NULL) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#ifdef NEVER\n\n/***********************************************************************************************\n * HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                   *\n *                                                                                             *\n *    This logic is used to maintain a base defense.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Base_Defense(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\t/*\n\t**\tCheck to find if any zone of the base is over defended. Such zones should have\n\t**\tsome of their defenses sold off to make better use of the money.\n\t*/\n\n\t/*\n\t**\tMake sure that the core defense is only about 1/2 of the perimeter defense average.\n\t*/\n\tint average = 0;\n\tfor (ZoneType z = ZONE_NORTH; z < ZONE_COUNT; z++) {\n\t\taverage += ZoneInfo[z].AirDefense;\n\t\taverage += ZoneInfo[z].ArmorDefense;\n\t\taverage += ZoneInfo[z].InfantryDefense;\n\t}\n\taverage /= (ZONE_COUNT-ZONE_NORTH);\n\n\t/*\n\t**\tIf the core value is greater than the average, then sell off some of the\n\t**\tinner defensive structures.\n\t*/\n\tint core = ZoneInfo[ZONE_CORE].AirDefense + ZoneInfo[ZONE_CORE].ArmorDefense + ZoneInfo[ZONE_CORE].InfantryDefense;\n\tif (core >= average) {\n\t\tstatic StructType _stype[] = {\n\t\t\tSTRUCT_GTOWER,\n\t\t\tSTRUCT_TURRET,\n\t\t\tSTRUCT_ATOWER,\n\t\t\tSTRUCT_OBELISK,\n\t\t\tSTRUCT_TESLA,\n\t\t\tSTRUCT_SAM\n\t\t};\n\t\tBuildingClass * b;\n\n\t\tfor (int index = 0; index < sizeof(_stype)/sizeof(_stype[0]); index++) {\n\t\t\tb = Find_Building(_stype[index], ZONE_CORE);\n\t\t\tif (b) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the enemy doesn't have any offensive air capability, then sell off any\n\t**\tSAM sites. Only do this when money is moderately low.\n\t*/\n\tif (Available_Money() < 1000 && (ActiveBScan & STRUCTF_SAM)) {\n\n\t\t/*\n\t\t**\tScan to find if ANY human opponents have aircraft or a helipad. If one\n\t\t** is found then consider that opponent to have a valid air threat potential.\n\t\t**\tDon't sell off SAM sites in that case.\n\t\t*/\n\t\tbool nothreat = true;\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tHouseClass * house = HouseClass::As_Pointer(h);\n\n\t\t\tif (house && house->IsActive && house->IsHuman && !Is_Ally(house)) {\n\t\t\t\tif ((house->ActiveAScan & (AIRCRAFTF_ORCA|AIRCRAFTF_TRANSPORT|AIRCRAFTF_HELICOPTER)) || (house->ActiveBScan & STRUCTF_HELIPAD)) {\n\t\t\t\t\tnothreat = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND*5);\n}\n#endif\n\n\n/***********************************************************************************************\n * HouseClass::AI_Building -- Determines what building to build.                               *\n *                                                                                             *\n *    This routine handles the general case of determining what building to build next.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *   11/03/1996 JLB : Tries to match aircraft of enemy                                         *\n *=============================================================================================*/\nint HouseClass::AI_Building(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildStructure != STRUCT_NONE) return(TICKS_PER_SECOND);\n\n\tif (Session.Type == GAME_NORMAL && Base.House == Class->House) {\n\t\tBaseNodeClass * node = Base.Next_Buildable();\n\t\tif (node) {\n\t\t\tBuildStructure = node->Type;\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\t\t/*\n\t\t**\tDon't suggest anything to build if the base is already big enough.\n\t\t*/\n\t\tunsigned int quant = 0;\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tHouseClass const * hptr = HouseClass::As_Pointer(h);\n\n\t\t\tif (hptr != NULL && hptr->IsActive && hptr->IsHuman && quant < hptr->CurBuildings) {\n\t\t\t\tquant = hptr->CurBuildings;\n\t\t\t}\n\t\t}\n\t\tquant += Rule.BaseSizeAdd;\n\n// TCTC -- Should multiply largest player base by some rational number.\n//\t\tif (CurBuildings >= quant) return(TICKS_PER_SECOND);\n\n\t\tBuildChoice.Free_All();\n\t\tBuildChoiceClass * choiceptr;\n\t\tStructType stype = STRUCT_NONE;\n\t\tint money = Available_Money();\n\t\tint level = Control.TechLevel;\n\t\tbool hasincome = (BQuantity[STRUCT_REFINERY] > 0 && !IsTiberiumShort && UQuantity[UNIT_HARVESTER] > 0);\n\t\tBuildingTypeClass const * b = NULL;\n\t\tHouseClass const * enemy = NULL;\n\t\tif (Enemy != HOUSE_NONE) {\n\t\t\tenemy = HouseClass::As_Pointer(Enemy);\n\t\t}\n\n\t\tlevel = Control.TechLevel;\n\n\t\t/*\n\t\t**\tTry to build a power plant if there is insufficient power and there is enough\n\t\t**\tmoney available.\n\t\t*/\n\t\tb = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_POWER);\n\t\tif (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {\n\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\tif (choiceptr != NULL) {\n\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t}\n\t\t} else {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_POWER);\n\t\t\tif (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a refinery if there isn't one already available.\n\t\t*/\n\t\tunsigned int current = BQuantity[STRUCT_REFINERY];\n\t\tif (!IsTiberiumShort && current < Round_Up(Rule.RefineryRatio*fixed(CurBuildings)) && current < (unsigned)Rule.RefineryLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_REFINERY);\n\t\t\tif (Can_Build(b, ActLike) && (money > b->Cost_Of() || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAlways make sure there is a barracks available, but only if there\n\t\t**\twill be sufficient money to train troopers.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_BARRACKS] + BQuantity[STRUCT_TENT];\n\t\tif (current < Round_Up(Rule.BarracksRatio*fixed(CurBuildings)) && current < (unsigned)Rule.BarracksLimit && (money > 300 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_BARRACKS);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TENT);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTry to build one dog house.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_KENNEL];\n\t\tif (current < 1 && (money > 300 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_KENNEL);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTry to build one gap generator.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_GAP];\n\t\tif (current < 1 && Power_Fraction() >= 1 && hasincome) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_GAP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tA source of combat vehicles is always needed, but only if there will\n\t\t**\tbe sufficient money to build vehicles.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_WEAP];\n\t\tif (current < Round_Up(Rule.WarRatio*fixed(CurBuildings)) && current < (unsigned)Rule.WarLimit && (money > 2000 || hasincome)) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_WEAP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAlways build up some base defense.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_PILLBOX] + BQuantity[STRUCT_CAMOPILLBOX] + BQuantity[STRUCT_TURRET] + BQuantity[STRUCT_FLAME_TURRET];\n\t\tif (current < Round_Up(Rule.DefenseRatio*fixed(CurBuildings)) && current < (unsigned)Rule.DefenseLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_FLAME_TURRET);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Percent_Chance(50)) {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_PILLBOX);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TURRET);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild some air defense.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_SAM] + BQuantity[STRUCT_AAGUN];\n\t\tif (current < Round_Up(Rule.AARatio*fixed(CurBuildings)) && current < (unsigned)Rule.AALimit) {\n\n\t\t\t/*\n\t\t\t**\tBuilding air defense only makes sense if the opponent has aircraft\n\t\t\t**\tof some kind.\n\t\t\t*/\n\t\t\tbool airthreat = false;\n\t\t\tint threat_quantity = 0;\n\t\t\tif (enemy != NULL && enemy->AScan != 0) {\n\t\t\t\tairthreat = true;\n\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t}\n\t\t\tif (!airthreat) {\n\t\t\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\t\t\t\t\tif (h != NULL && !Is_Ally(house) && h->AScan != 0) {\n\t\t\t\t\t\tairthreat = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (airthreat) {\n\n\t\t\t\tif (BQuantity[STRUCT_RADAR] == 0) {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_RADAR);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_HIGH, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_SAM);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass((current < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_AAGUN);\n\t\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t\t*choiceptr = BuildChoiceClass((current < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAdvanced base defense would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_TESLA];\n\t\tif (current < Round_Up(Rule.TeslaRatio*fixed(CurBuildings)) && current < (unsigned)Rule.TeslaLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_TESLA);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a tech center as soon as possible.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_ADVANCED_TECH] + BQuantity[STRUCT_SOVIET_TECH];\n\t\tif (current < 1) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_TECH);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_SOVIET_TECH);\n\t\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {\n\t\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tA helipad would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_HELIPAD];\n\t\tif (current < Round_Up(Rule.HelipadRatio*fixed(CurBuildings)) && current < (unsigned)Rule.HelipadLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_HELIPAD);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\tint threat_quantity = 0;\n\t\t\t\t\tif (enemy != NULL) {\n\t\t\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t\t\t}\n\n\t\t\t\t\t*choiceptr = BuildChoiceClass((CurAircraft < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tAn airstrip would be good.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_AIRSTRIP];\n\t\tif (current < Round_Up(Rule.AirstripRatio*fixed(CurBuildings)) && current < (unsigned)Rule.AirstripLimit) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_AIRSTRIP);\n\t\t\tif (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr != NULL) {\n\t\t\t\t\tint threat_quantity = 0;\n\t\t\t\t\tif (enemy != NULL) {\n\t\t\t\t\t\tthreat_quantity = enemy->CurAircraft;\n\t\t\t\t\t}\n\n\t\t\t\t\t*choiceptr = BuildChoiceClass((CurAircraft < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#ifdef OLD\n\t\t/*\n\t\t**\tBuild a repair bay if there isn't one already available.\n\t\t*/\n\t\tcurrent = BQuantity[STRUCT_REPAIR];\n\t\tif (current == 0) {\n\t\t\tb = &BuildingTypeClass::As_Reference(STRUCT_REPAIR);\n\t\t\tif (Can_Build(b, ActLike) && b->Cost_Of() < money) {\n\t\t\t\tchoiceptr = BuildChoice.Alloc();\n\t\t\t\tif (choiceptr) {\n\t\t\t\t\t*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tPick the choice that is the most urgent.\n\t\t*/\n\t\tUrgencyType best = URGENCY_NONE;\n\t\tint bestindex;\n\t\tfor (int index = 0; index < BuildChoice.Count(); index++) {\n\t\t\tif (BuildChoice.Ptr(index)->Urgency > best) {\n\t\t\t\tbestindex = index;\n\t\t\t\tbest = BuildChoice.Ptr(index)->Urgency;\n\t\t\t}\n\t\t}\n\t\tif (best != URGENCY_NONE) {\n\t\t\tBuildStructure = BuildChoice.Ptr(bestindex)->Structure;\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Unit -- Determines what unit to build next.                                  *\n *                                                                                             *\n *    This routine handles the general case of determining what units to build next.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of games frames to delay before calling this routine again.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Unit(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildUnit != UNIT_NONE) return(TICKS_PER_SECOND);\n\tif (CurUnits >= Control.MaxUnit) return(TICKS_PER_SECOND);\n\n\t/*\n\t**\tA computer controlled house will try to build a replacement\n\t**\tharvester if possible.\n\t*/\n\tif (IQ >= Rule.IQHarvester && !IsTiberiumShort && !IsHuman && BQuantity[STRUCT_REFINERY] > UQuantity[UNIT_HARVESTER] && Difficulty != DIFF_HARD) {\n\t\tif (UnitTypeClass::As_Reference(UNIT_HARVESTER).Level <= (unsigned)Control.TechLevel) {\n\t\t\tBuildUnit = UNIT_HARVESTER;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\t}\n\n\tif (Session.Type == GAME_NORMAL) {\n\n\t\tint counter[UNIT_COUNT];\n\t\tmemset(counter, 0x00, sizeof(counter));\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tint index;\n\t\tfor (index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr != NULL) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tTechnoTypeClass const * memtype = team->Members[subindex].Class;\n\t\t\t\t\t\tif (memtype->What_Am_I() == RTTI_UNITTYPE) {\n\t\t\t\t\t\t\tcounter[((UnitTypeClass const *)memtype)->Type] = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team != NULL && team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\tTechnoTypeClass const * memtype = team->Members[subindex].Class;\n\n\t\t\t\t\tif (memtype->What_Am_I() == RTTI_UNITTYPE) {\n\t\t\t\t\t\tint subtype = ((UnitTypeClass const *)memtype)->Type;\n\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int uindex = 0; uindex < Units.Count(); uindex++) {\n\t\t\tUnitClass * unit = Units.Ptr(uindex);\n\t\t\tif (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {\n\t\t\t\tcounter[unit->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those objects that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tUnitType bestlist[UNIT_COUNT];\n\t\tfor (UnitType utype = UNIT_FIRST; utype < UNIT_COUNT; utype++) {\n\t\t\tif (counter[utype] > 0 && Can_Build(&UnitTypeClass::As_Reference(utype), Class->House) && UnitTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\tbestcount = 0;\n\t\t\t\t}\n\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe unit type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tBuildUnit = bestlist[Random_Pick(0, bestcount-1)];\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\n\t\tint counter[UNIT_COUNT];\n\t\tint total = 0;\n\t\tUnitType index;\n\t\tfor (index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\t\tUnitTypeClass const * utype = &UnitTypeClass::As_Reference(index);\n\t\t\tif (Can_Build(utype, ActLike) && utype->Type != UNIT_HARVESTER) {\n\t\t\t\tif (utype->PrimaryWeapon != NULL) {\n\t\t\t\t\tcounter[index] = 20;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[index] = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcounter[index] = 0;\n\t\t\t}\n\t\t\ttotal += counter[index];\n\t\t}\n\n\t\tif (total > 0) {\n\t\t\tint choice = Random_Pick(0, total-1);\n\t\t\tfor (index = UNIT_FIRST; index < UNIT_COUNT; index++) {\n\t\t\t\tif (choice < counter[index]) {\n\t\t\t\t\tBuildUnit = index;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchoice -= counter[index];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\nint HouseClass::AI_Vessel(void)\n{\n\tassert(Houses.ID(this) == ID);\n\tif (BuildVessel != VESSEL_NONE) return(TICKS_PER_SECOND);\n\n\tif (CurVessels >= Control.MaxVessel) {\n\t\treturn(TICKS_PER_SECOND);\n\t}\n\n\tif (Session.Type == GAME_NORMAL) {\n\n\t\tint counter[VESSEL_COUNT];\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tmemset(counter, 0x00, sizeof(counter));\n\t\t} else {\n\t\t\tfor (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {\n\t\t\t\tif (Can_Build(&VesselTypeClass::As_Reference(index), Class->House) && VesselTypeClass::As_Reference(index).Level <= (unsigned)Control.TechLevel) {\n\t\t\t\t\tcounter[index] = 16;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[index] = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tint index;\n\t\tfor (index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {\n\t\t\t\t\t\t\tcounter[((VesselTypeClass const *)(team->Members[subindex].Class))->Type] = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team) {\n\t\t\t\tif (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {\n\t\t\t\t\t\t\tint subtype = ((VesselTypeClass const *)(team->Members[subindex].Class))->Type;\n\t\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int vindex = 0; vindex < Vessels.Count(); vindex++) {\n\t\t\tVesselClass * unit = Vessels.Ptr(vindex);\n\t\t\tif (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {\n\t\t\t\tcounter[unit->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those object that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tVesselType bestlist[VESSEL_COUNT];\n\t\tfor (VesselType utype = VESSEL_FIRST; utype < VESSEL_COUNT; utype++) {\n\t\t\tif (counter[utype] > 0 && Can_Build(&VesselTypeClass::As_Reference(utype), Class->House) && VesselTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\tbestcount = 0;\n\t\t\t\t}\n\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe unit type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tBuildVessel = bestlist[Random_Pick(0, bestcount-1)];\n\t\t}\n\t}\n\n\tif (IsBaseBuilding) {\n\t\tBuildVessel = VESSEL_NONE;\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n\n/***********************************************************************************************\n * HouseClass::AI_Infantry -- Determines the infantry unit to build.                           *\n *                                                                                             *\n *    This routine handles the general case of determining what infantry unit to build         *\n *    next.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before being called again.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Infantry(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (BuildInfantry != INFANTRY_NONE) return(TICKS_PER_SECOND);\n\tif (CurInfantry >= Control.MaxInfantry) return(TICKS_PER_SECOND);\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tTechnoTypeClass const * techno = 0;\n\t\tint counter[INFANTRY_COUNT];\n\t\tmemset(counter, 0x00, sizeof(counter));\n\n\t\t/*\n\t\t**\tBuild a list of the maximum of each type we wish to produce. This will be\n\t\t**\ttwice the number required to fill all teams.\n\t\t*/\n\t\tint index;\n\t\tfor (index = 0; index < Teams.Count(); index++) {\n\t\t\tTeamClass * tptr = Teams.Ptr(index);\n\t\t\tif (tptr != NULL) {\n\t\t\t\tTeamTypeClass const * team = tptr->Class;\n\n\t\t\t\tif (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tcounter[((InfantryTypeClass const *)(team->Members[subindex].Class))->Type] += team->Members[subindex].Quantity + (team->IsReinforcable ? 1 : 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTeam types that are flagged as prebuilt, will always try to produce enough\n\t\t**\tto fill one team of this type regardless of whether there is a team active\n\t\t**\tof that type.\n\t\t*/\n\t\tfor (index = 0; index < TeamTypes.Count(); index++) {\n\t\t\tTeamTypeClass const * team = TeamTypes.Ptr(index);\n\t\t\tif (team != NULL) {\n\t\t\t\tif (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {\n\t\t\t\t\tfor (int subindex = 0; subindex < team->ClassCount; subindex++) {\n\t\t\t\t\t\tif (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tint subtype = ((InfantryTypeClass const *)(team->Members[subindex].Class))->Type;\n//\t\t\t\t\t\t\t\t\tcounter[subtype] = 1;\n\t\t\t\t\t\t\tcounter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);\n\t\t\t\t\t\t\tcounter[subtype] = min(counter[subtype], 5);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tReduce the theoretical maximum by the actual number of objects currently\n\t\t**\tin play.\n\t\t*/\n\t\tfor (int uindex = 0; uindex < Infantry.Count(); uindex++) {\n\t\t\tInfantryClass * infantry = Infantry.Ptr(uindex);\n\t\t\tif (infantry != NULL && infantry->Is_Recruitable(this) && counter[infantry->Class->Type] > 0) {\n\t\t\t\tcounter[infantry->Class->Type]--;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tPick to build the most needed object but don't consider those object that\n\t\t**\tcan't be built because of scenario restrictions or insufficient cash.\n\t\t*/\n\t\tint bestval = -1;\n\t\tint bestcount = 0;\n\t\tInfantryType bestlist[INFANTRY_COUNT];\n\t\tfor (InfantryType utype = INFANTRY_FIRST; utype < INFANTRY_COUNT; utype++) {\n\n\t\t\tif (utype != INFANTRY_DOG || !(IScan & INFANTRYF_DOG)) {\n\t\t\t\tif (counter[utype] > 0 && Can_Build(&InfantryTypeClass::As_Reference(utype), Class->House) && InfantryTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {\n\t\t\t\t\tif (bestval == -1 || bestval < counter[utype]) {\n\t\t\t\t\t\tbestval = counter[utype];\n\t\t\t\t\t\tbestcount = 0;\n\t\t\t\t\t}\n\t\t\t\t\tbestlist[bestcount++] = utype;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tThe infantry type to build is now known. Fetch a pointer to the techno type class.\n\t\t*/\n\t\tif (bestcount) {\n\t\t\tint pick = Random_Pick(0, bestcount-1);\n\t\t\tBuildInfantry = bestlist[pick];\n\t\t}\n\n\t}\n\n\tif (IsBaseBuilding) {\n\t\tHouseClass const * enemy = NULL;\n\t\tif (Enemy != HOUSE_NONE) {\n\t\t\tenemy = HouseClass::As_Pointer(Enemy);\n\t\t}\n\n\t\t/*\n\t\t**\tThis structure is used to keep track of the list of infantry types that should be\n\t\t**\tbuilt. The infantry type and the value assigned to it is recorded.\n\t\t*/\n\t\tstruct {\n\t\t\tInfantryType\tType;\t\t// Infantry type.\n\t\t\tint\t\t\t\tValue;\t// Relative value assigned.\n\t\t} typetrack[INFANTRY_COUNT];\n\t\tint count = 0;\n\t\tint total = 0;\n\t\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\t\tif (Can_Build(&InfantryTypeClass::As_Reference(index), ActLike) && InfantryTypeClass::As_Reference(index).Level <= (unsigned)Control.TechLevel) {\n\t\t\t\ttypetrack[count].Value = 0;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 This looks like a potential bug. It is prob. for save game format compatibility.\n\t\t\t\tint clipindex = index;\n\t\t\t\tif (clipindex >= INFANTRY_RA_COUNT) clipindex -= INFANTRY_RA_COUNT;\n\t\t\t\tif ((enemy != NULL && enemy->IQuantity[clipindex] > IQuantity[clipindex]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {\n#else\n\t\t\t\tif ((enemy != NULL && enemy->IQuantity[index] > IQuantity[index]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {\n#endif\n\n\t\t\t\t\tswitch (index) {\n\t\t\t\t\t\tcase INFANTRY_E1:\n\t\t\t\t\t\t\ttypetrack[count].Value = 3;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E2:\n\t\t\t\t\t\t\ttypetrack[count].Value = 5;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E3:\n\t\t\t\t\t\t\ttypetrack[count].Value = 2;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_E4:\n\t\t\t\t\t\t\ttypetrack[count].Value = 5;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\t\t\t\tif (CurInfantry > 5) {\n\t\t\t\t\t\t\t\ttypetrack[count].Value = 1 - max(IQuantity[index], 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase INFANTRY_TANYA:\n\t\t\t\t\t\t\ttypetrack[count].Value = 1 - max(IQuantity[index], 0);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\ttypetrack[count].Value = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (typetrack[count].Value > 0) {\n\t\t\t\t\ttypetrack[count].Type = index;\n\t\t\t\t\ttotal += typetrack[count].Value;\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is at least one choice, then pick it. The object picked\n\t\t**\tis influenced by the weight (value) assigned to it. This is accomplished\n\t\t**\tby picking a number between 0 and the total weight value. The appropriate\n\t\t**\tinfantry object that matches the number picked is then selected to be built.\n\t\t*/\n\t\tif (count > 0) {\n\t\t\tint pick = Random_Pick(0, total-1);\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tif (pick < typetrack[index].Value) {\n\t\t\t\t\tBuildInfantry = typetrack[index].Type;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpick -= typetrack[index].Value;\n\t\t\t}\n\t\t}\n\t}\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::AI_Aircraft -- Determines what aircraft to build next.                          *\n *                                                                                             *\n *    This routine is used to determine the general case of what aircraft to build next.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of frame to delay before calling this routine again.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::AI_Aircraft(void)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!IsHuman && IQ >= Rule.IQAircraft) {\n\t\tif (BuildAircraft != AIRCRAFT_NONE) return(TICKS_PER_SECOND);\n\t\tif (CurAircraft >= Control.MaxAircraft) return(TICKS_PER_SECOND);\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW).Level <= (unsigned)Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {\n\t\t\tBuildAircraft = AIRCRAFT_LONGBOW;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_HIND), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Level <= (unsigned)Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {\n\t\t\tBuildAircraft = AIRCRAFT_HIND;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_MIG), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_MIG).Level <= (unsigned)Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {\n\t\t\tBuildAircraft = AIRCRAFT_MIG;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\n\t\tif (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_YAK), ActLike) &&\n\t\t\t\t AircraftTypeClass::As_Reference(AIRCRAFT_YAK).Level <= (unsigned)Control.TechLevel &&\n\t\t\t\t BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {\n\t\t\tBuildAircraft = AIRCRAFT_YAK;\n\t\t\treturn(TICKS_PER_SECOND);\n\t\t}\n\t}\n\n\treturn(TICKS_PER_SECOND);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Production_Begun -- Records that production has begun.                          *\n *                                                                                             *\n *    This routine is used to inform the Expert System that production of the specified object *\n *    has begun. This allows the AI to proceed with picking another object to begin production *\n *    on.                                                                                      *\n *                                                                                             *\n * INPUT:   product  -- Pointer to the object that production has just begun on.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Production_Begun(TechnoClass const * product)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (product != NULL) {\n\t\tswitch (product->What_Am_I()) {\n\t\t\tcase RTTI_UNIT:\n\t\t\t\tif (*((UnitClass*)product) == BuildUnit) {\n\t\t\t\t\tBuildUnit = UNIT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSEL:\n\t\t\t\tif (*((VesselClass*)product) == BuildVessel) {\n\t\t\t\t\tBuildVessel = VESSEL_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRY:\n\t\t\t\tif (*((InfantryClass*)product) == BuildInfantry) {\n\t\t\t\t\tBuildInfantry = INFANTRY_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tif (*((BuildingClass*)product) == BuildStructure) {\n\t\t\t\t\tBuildStructure = STRUCT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\tif (*((AircraftClass*)product) == BuildAircraft) {\n\t\t\t\t\tBuildAircraft = AIRCRAFT_NONE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tracking_Remove -- Remove object from house tracking system.                    *\n *                                                                                             *\n *    This routine informs the Expert System that the specified object is no longer part of    *\n *    this house's inventory. This occurs when the object is destroyed or captured.            *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object to remove from the tracking systems of this      *\n *                      house.                                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Tracking_Remove(TechnoClass const * techno)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tint type;\n\n\tswitch (techno->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tCurBuildings--;\n\t\t\tBQuantity[((BuildingTypeClass const &)techno->Class_Of()).Type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tCurAircraft--;\n\t\t\tAQuantity[((AircraftTypeClass const &)techno->Class_Of()).Type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tCurInfantry--;\n\t\t\tif (!((InfantryClass *)techno)->IsTechnician) {\n\t\t\t\ttype = ((InfantryTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (type >= INFANTRY_RA_COUNT) type -= INFANTRY_RA_COUNT;\n#endif\n\t\t\t\tIQuantity[type]--;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tCurUnits--;\n\t\t\ttype = ((UnitTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (type >= UNIT_RA_COUNT) type -= UNIT_RA_COUNT;\n#endif\n\t\t\tUQuantity[type]--;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tCurVessels--;\n\t\t\ttype = ((VesselTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (type >= VESSEL_RA_COUNT) type -= VESSEL_RA_COUNT;\n#endif\n\t\t\tVQuantity[type]--;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Tracking_Add -- Informs house of new inventory item.                            *\n *                                                                                             *\n *    This function is called when the specified object is now available as part of the house's*\n *    inventory. This occurs when the object is newly produced and also when it is captured    *\n *    by this house.                                                                           *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is now part of the house inventory.         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Tracking_Add(TechnoClass const * techno)\n{\n\tassert(Houses.ID(this) == ID);\n\n\tStructType building;\n\tAircraftType aircraft;\n\tInfantryType infantry;\n\tUnitType unit;\n\tVesselType vessel;\n\tint quant;\n\n\tswitch (techno->What_Am_I()) {\n\t\tcase RTTI_BUILDING:\n\t\t\tCurBuildings++;\n\t\t\tbuilding = ((BuildingTypeClass const &)techno->Class_Of()).Type;\n\t\t\tBQuantity[building]++;\n\t\t\tBScan |= (1L << building);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tBuildingTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tCurAircraft++;\n\t\t\taircraft = ((AircraftTypeClass const &)techno->Class_Of()).Type;\n\t\t\tAQuantity[aircraft]++;\n\t\t\tAScan |= (1L << aircraft);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tAircraftTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tCurInfantry++;\n\t\t\tinfantry = ((InfantryTypeClass const &)techno->Class_Of()).Type;\n\t\t\tif (!((InfantryClass *)techno)->IsTechnician) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tquant = infantry;\n\t\t\t\tif (quant >= INFANTRY_RA_COUNT) quant -= INFANTRY_RA_COUNT;\n\t\t\t\tIQuantity[quant]++;\n#else\n\t\t\t\tIQuantity[infantry]++;\n#endif\n\t\t\t\tif (!((InfantryTypeClass const &)techno->Class_Of()).IsCivilian && Session.Type == GAME_INTERNET) {\n\t\t\t\t\tInfantryTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t\t}\n\t\t\t\tIScan |= (1L << infantry);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tCurUnits++;\n\t\t\tunit = ((UnitTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tquant = unit;\n\t\t\tif (quant >= UNIT_RA_COUNT) quant -= UNIT_RA_COUNT;\n\t\t\tUQuantity[quant]++;\n#else\n\t\t\tUQuantity[unit]++;\n#endif\n\t\t\tUScan |= (1L << unit);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tUnitTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tCurVessels++;\n\t\t\tvessel = ((VesselTypeClass const &)techno->Class_Of()).Type;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tquant = vessel;\n\t\t\tif (quant >= VESSEL_RA_COUNT) quant -= VESSEL_RA_COUNT;\n\t\t\tVQuantity[quant]++;\n#else\n\t\t\tVQuantity[vessel]++;\n#endif\n\t\t\tVScan |= (1L << vessel);\n\t\t\tif (Session.Type == GAME_INTERNET) {\n\t\t\t\tVesselTotals->Increment_Unit_Total(techno->Class_Of().ID);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.              *\n *                                                                                             *\n *    Use this routine to fetch a pointer to the variable that holds the number of factories   *\n *    that can produce the specified object type. This is a helper routine used when           *\n *    examining the number of factories as well as adjusting their number.                     *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object that could be produced.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of factories owned by this house that could produce the    *\n *          object of the type specified.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint * HouseClass::Factory_Counter(RTTIType rtti)\n{\n\tswitch (rtti) {\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_UNIT:\n\t\t\treturn(&UnitFactories);\n\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_VESSEL:\n\t\t\treturn(&VesselFactories);\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn(&AircraftFactories);\n\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn(&InfantryFactories);\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\tcase RTTI_BUILDING:\n\t\t\treturn(&BuildingFactories);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Active_Remove -- Remove this object from active duty for this house.            *\n *                                                                                             *\n *    This routine will recognize the specified object as having been removed from active      *\n *    duty.                                                                                    *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object to remove from active duty.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Active_Remove(TechnoClass const * techno)\n{\n\tif (techno == NULL) return;\n\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tint * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);\n\t\tif (fptr != NULL) {\n\t\t\t*fptr = *fptr - 1;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Active_Add -- Add an object to active duty for this house.                      *\n *                                                                                             *\n *    This routine will recognize the specified object as having entered active duty. Any      *\n *    abilities granted to the house by that object are now available.                         *\n *                                                                                             *\n * INPUT:   techno   -- Pointer to the object that is entering active duty.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Active_Add(TechnoClass const * techno)\n{\n\tif (techno == NULL) return;\n\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tint * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);\n\t\tif (fptr != NULL) {\n\t\t\t*fptr = *fptr + 1;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                        *\n *                                                                                             *\n *    This routine will determine what zone the specified coordinate lies in with respect to   *\n *    this house's base. A location that is too distant from the base, even though it might    *\n *    be a building, is not considered part of the base and returns ZONE_NONE.                 *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to examine.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the base zone that the specified coordinate lies in.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(COORDINATE coord) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (coord == 0) return(ZONE_NONE);\n\n\tint distance = Distance(Center, coord);\n\tif (distance <= Radius) return(ZONE_CORE);\n\tif (distance > Radius*4) return(ZONE_NONE);\n\n\tDirType facing = Direction(Center, coord);\n\tif (facing < DIR_NE || facing > DIR_NW) return(ZONE_NORTH);\n\tif (facing >= DIR_NE && facing < DIR_SE) return(ZONE_EAST);\n\tif (facing >= DIR_SE && facing < DIR_SW) return(ZONE_SOUTH);\n\treturn(ZONE_WEST);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines which base zone the specified object lies in.          *\n *                                                                                             *\n *    Use this routine to determine what zone the specified object lies in.                    *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that will be checked for zone occupation.        *\n *                                                                                             *\n * OUTPUT:  Returns with the base zone that the object lies in. For objects that are too       *\n *          distant from the center of the base, ZONE_NONE is returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(ObjectClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tif (!object) return(ZONE_NONE);\n\treturn(Which_Zone(object->Center_Coord()));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.            *\n *                                                                                             *\n *    This routine is used to determine what base zone the specified cell is in.               *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the base zone that the cell lies in or ZONE_NONE if the cell is too far    *\n *          away.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nZoneType HouseClass::Which_Zone(CELL cell) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\treturn(Which_Zone(Cell_Coord(cell)));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                         *\n *                                                                                             *\n *    This routine will go through all game objects and reset the existence bits for the       *\n *    owning house. This method ensures that if the object exists, then the corresponding      *\n *    existence bit is also set.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Recalc_Attributes(void)\n{\n\t/*\n\t**\tClear out all tracking values that will be filled in by this\n\t**\troutine. This allows the filling in process to not worry about\n\t**\told existing values.\n\t*/\n\tint index;\n\tfor (index = 0; index < Houses.Count(); index++) {\n\t\tHouseClass * house = Houses.Ptr(index);\n\n\t\tif (house != NULL) {\n\t\t\thouse->BScan = 0;\n\t\t\thouse->ActiveBScan = 0;\n\t\t\thouse->IScan = 0;\n\t\t\thouse->ActiveIScan = 0;\n\t\t\thouse->UScan = 0;\n\t\t\thouse->ActiveUScan = 0;\n\t\t\thouse->AScan = 0;\n\t\t\thouse->ActiveAScan = 0;\n\t\t\thouse->VScan = 0;\n\t\t\thouse->ActiveVScan = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tA second pass through the sentient objects is required so that the appropriate scan\n\t**\tbits will be set for the owner house.\n\t*/\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass const * unit = Units.Ptr(index);\n\t\tunit->House->UScan |= (1L << unit->Class->Type);\n\t\tif (unit->IsLocked && (Session.Type != GAME_NORMAL || !unit->House->IsHuman || unit->IsDiscoveredByPlayer)) {\n\t\t\tif (!unit->IsInLimbo) {\n\t\t\t\tunit->House->ActiveUScan |= (1L << unit->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass const * infantry = Infantry.Ptr(index);\n\t\tinfantry->House->IScan |= (1L << infantry->Class->Type);\n\t\tif (infantry->IsLocked && (Session.Type != GAME_NORMAL || !infantry->House->IsHuman || infantry->IsDiscoveredByPlayer)) {\n\t\t\tif (!infantry->IsInLimbo) {\n\t\t\t\tinfantry->House->ActiveIScan |= (1L << infantry->Class->Type);\n\t\t\t\tinfantry->House->OldIScan |= (1L << infantry->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass const * aircraft = Aircraft.Ptr(index);\n\t\taircraft->House->AScan |= (1L << aircraft->Class->Type);\n\t\tif (aircraft->IsLocked && (Session.Type != GAME_NORMAL || !aircraft->House->IsHuman || aircraft->IsDiscoveredByPlayer)) {\n\t\t\tif (!aircraft->IsInLimbo) {\n\t\t\t\taircraft->House->ActiveAScan |= (1L << aircraft->Class->Type);\n\t\t\t\taircraft->House->OldAScan |= (1L << aircraft->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass const * building = Buildings.Ptr(index);\n\t\tif (building->Class->Type < 32) {\n\t\t\tbuilding->House->BScan |= (1L << building->Class->Type);\n\t\t\tif (building->IsLocked && (Session.Type != GAME_NORMAL || !building->House->IsHuman || building->IsDiscoveredByPlayer)) {\n\t\t\t\tif (!building->IsInLimbo) {\n\t\t\t\t\tbuilding->House->ActiveBScan |= (1L << building->Class->Type);\n\t\t\t\t\tbuilding->House->OldBScan |= (1L << building->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass const * vessel = Vessels.Ptr(index);\n\t\tvessel->House->VScan |= (1L << vessel->Class->Type);\n\t\tif (vessel->IsLocked && (Session.Type != GAME_NORMAL || !vessel->House->IsHuman || vessel->IsDiscoveredByPlayer)) {\n\t\t\tif (!vessel->IsInLimbo) {\n\t\t\t\tvessel->House->ActiveVScan |= (1L << vessel->Class->Type);\n\t\t\t\tvessel->House->OldVScan |= (1L << vessel->Class->Type);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                  *\n *                                                                                             *\n *    This routine is used to find the cell that is closest to the center point of the         *\n *    zone specified. Typical use of this routine is for building and unit placement so that   *\n *    they can \"cover\" the specified zone.                                                     *\n *                                                                                             *\n * INPUT:   zone  -- The zone that the center point is to be returned.                         *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is closest to the center point of the zone specified.   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL HouseClass::Zone_Cell(ZoneType zone) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tswitch (zone) {\n\t\tcase ZONE_CORE:\n\t\t\treturn(Coord_Cell(Center));\n\n\t\tcase ZONE_NORTH:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_N, Radius*3)));\n\n\t\tcase ZONE_EAST:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_E, Radius*3)));\n\n\t\tcase ZONE_WEST:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_W, Radius*3)));\n\n\t\tcase ZONE_SOUTH:\n\t\t\treturn(Coord_Cell(Coord_Move(Center, DIR_S, Radius*3)));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Where_To_Go -- Determines where the object should go and wait.                  *\n *                                                                                             *\n *    This function is called for every new unit produced or delivered in order to determine   *\n *    where the unit should \"hang out\" to await further orders. The best area for the          *\n *    unit to loiter is returned as a cell location.                                           *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that needs to know where to go.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the unit should move to.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/1995 JLB : Created.                                                                 *\n *   11/04/1996 JLB : Simplified to use helper functions                                       *\n *=============================================================================================*/\nCELL HouseClass::Where_To_Go(FootClass const * object) const\n{\n\tassert(Houses.ID(this) == ID);\n\tassert(object != NULL);\n\n\tZoneType zone;\t\t\t// The zone that the object should go to.\n\tif (object->Anti_Air() + object->Anti_Armor() + object->Anti_Infantry() == 0) {\n\t\tzone = ZONE_CORE;\n\t} else {\n\t\tzone = Random_Pick(ZONE_NORTH, ZONE_WEST);\n\t}\n\n\tCELL cell = Random_Cell_In_Zone(zone);\n\tassert(cell != 0);\n\n\treturn(Map.Nearby_Location(cell, SPEED_TRACK, Map[cell].Zones[MZONE_NORMAL], MZONE_NORMAL));\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Juicy_Target -- Finds a suitable field target.                             *\n *                                                                                             *\n *    This routine is used to find targets out in the field and away from base defense.        *\n *    Typical of this would be the attack helicopters and the roving attack bands of           *\n *    hunter killers.                                                                          *\n *                                                                                             *\n * INPUT:   coord -- The coordinate of the attacker. Closer targets are given preference.      *\n *                                                                                             *\n * OUTPUT:  Returns with a suitable target to attack.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/12/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET HouseClass::Find_Juicy_Target(COORDINATE coord) const\n{\n\tassert(Houses.ID(this) == ID);\n\n\tUnitClass * best = 0;\n\tint value = 0;\n\n\tfor (int index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\tif (unit && !unit->IsInLimbo && !Is_Ally(unit) && unit->House->Which_Zone(unit) == ZONE_NONE) {\n\t\t\tint val = Distance(coord, unit->Center_Coord());\n\n\t\t\tif (unit->Anti_Air()) val *= 2;\n\n\t\t\tif (*unit == UNIT_HARVESTER) val /= 2;\n\n\t\t\tif (value == 0 || val < value) {\n\t\t\t\tvalue = val;\n\t\t\t\tbest = unit;\n\t\t\t}\n\t\t}\n\t}\n\tif (best) {\n\t\treturn(best->As_Target());\n\t}\n\treturn(TARGET_NONE);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.     *\n *                                                                                             *\n *    Call this routine to fetch the total quantity of aircraft of the type specified that is  *\n *    owned by this house.                                                                     *\n *                                                                                             *\n * INPUT:   aircraft -- The aircraft type to check the quantity of.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the total quantity of all aircraft of that type that is owned by this *\n *          house.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint  HouseClass::Get_Quantity(AircraftType aircraft)\n{\n\treturn(AQuantity[aircraft]);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified.   *\n *                                                                                             *\n *    This is the counterpart to the Set_Factory function. It will return with a factory       *\n *    pointer that is associated with the object type specified.                               *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object type to find the factory for.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the factory (if present) that can manufacture the        *\n *          object type specified.                                                             *\n *                                                                                             *\n * WARNINGS:   If this returns a non-NULL pointer, then the factory is probably already busy   *\n *             producing another unit of that category.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nFactoryClass * HouseClass::Fetch_Factory(RTTIType rtti) const\n{\n\tint factory_index = -1;\n\n\tswitch (rtti) {\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tfactory_index = InfantryFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tfactory_index = UnitFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tfactory_index = BuildingFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tfactory_index = AircraftFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tfactory_index = VesselFactory;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfactory_index = -1;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tFetch the actual pointer to the factory object. If there is\n\t**\tno object factory that matches the specified rtti type, then\n\t**\tnull is returned.\n\t*/\n\tif (factory_index != -1) {\n\t\treturn(Factories.Raw_Ptr(factory_index));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Set_Factory -- Assign specified factory to house tracking.                      *\n *                                                                                             *\n *    Call this routine when a factory has been created and it now must be passed on to the    *\n *    house for tracking purposes. The house maintains several factory pointers and this       *\n *    routine will ensure that the factory pointer gets stored correctly.                      *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI of the object the factory it to manufacture.                     *\n *                                                                                             *\n *          factory  -- The factory object pointer.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Set_Factory(RTTIType rtti, FactoryClass * factory)\n{\n\tint * factory_index = 0;\n\n\tassert(rtti != RTTI_NONE);\n\n\tswitch (rtti) {\n\t\tcase RTTI_UNIT:\n\t\tcase RTTI_UNITTYPE:\n\t\t\tfactory_index = &UnitFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\tfactory_index = &InfantryFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\tcase RTTI_VESSELTYPE:\n\t\t\tfactory_index = &VesselFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tfactory_index = &BuildingFactory;\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tfactory_index = &AircraftFactory;\n\t\t\tbreak;\n\t}\n\n\tassert(factory_index != NULL);\n\n\t/*\n\t**\tAssign the factory to the appropriate slot. For the case of clearing\n\t**\tthe factory out, then -1 is assigned.\n\t*/\n\tif (factory != NULL) {\n\t\t*factory_index = factory->ID;\n\t} else {\n\t\t*factory_index = -1;\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Factory_Count -- Fetches the number of factories for specified type.            *\n *                                                                                             *\n *    This routine will count the number of factories owned by this house that can build       *\n *    objects of the specified type.                                                           *\n *                                                                                             *\n * INPUT:   rtti  -- The type of object (RTTI) that the factories are to be counted for.       *\n *                                                                                             *\n * OUTPUT:  Returns with the number of factories that can build the object type specified.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HouseClass::Factory_Count(RTTIType rtti) const\n{\n\tint const * ptr = ((HouseClass *)this)->Factory_Counter(rtti);\n\tif (ptr != NULL) {\n\t\treturn(*ptr);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Get_Quantity -- Gets the quantity of the building type specified.               *\n *                                                                                             *\n *    This will return the total number of buildings of that type owned by this house.         *\n *                                                                                             *\n * INPUT:   building -- The building type to check.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of buildings of that type owned by this house.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint  HouseClass::Get_Quantity(StructType building)\n{\n\treturn(BQuantity[building]);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Read_INI -- Reads house specific data from INI.                                 *\n *                                                                                             *\n *    This routine reads the house specific data for a particular                              *\n *    scenario from the scenario INI file. Typical data includes starting                      *\n *    credits, maximum unit count, etc.                                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to loaded scenario INI file.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *   05/18/1995 JLB : Creates all houses.                                                      *\n *=============================================================================================*/\nvoid HouseClass::Read_INI(CCINIClass & ini)\n{\n\tHouseClass \t* p;\t\t\t\t// Pointer to current player data.\n\tchar const\t* hname;\t\t\t//\tPointer to house name.\n\n\tfor (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {\n\t\thname = HouseTypeClass::As_Reference(index).IniName;\n\n\t\tp = new HouseClass(index);\n\t\tp->Control.TechLevel = ini.Get_Int(hname, \"TechLevel\", Scen.Scenario);\n\t\tp->Control.MaxBuilding = ini.Get_Int(hname, \"MaxBuilding\", p->Control.MaxBuilding);\n\t\tp->Control.MaxUnit = ini.Get_Int(hname, \"MaxUnit\", p->Control.MaxUnit);\n\t\tp->Control.MaxInfantry = ini.Get_Int(hname, \"MaxInfantry\", p->Control.MaxInfantry);\n\t\tp->Control.MaxVessel = ini.Get_Int(hname, \"MaxVessel\", p->Control.MaxVessel);\n\t\tif (p->Control.MaxVessel == 0) p->Control.MaxVessel = p->Control.MaxUnit;\n\t\tp->Control.InitialCredits = ini.Get_Int(hname, \"Credits\", 0) * 100;\n\t\tp->Credits = p->Control.InitialCredits;\n\n\t\tint iq = ini.Get_Int(hname, \"IQ\", 0);\n\t\tif (iq > Rule.MaxIQ) iq = 1;\n\t\tp->IQ = p->Control.IQ = iq;\n\n\t\tp->Control.Edge = ini.Get_SourceType(hname, \"Edge\", SOURCE_NORTH);\n\t\tp->IsPlayerControl = ini.Get_Bool(hname, \"PlayerControl\", false);\n\n\t\tint owners = ini.Get_Owners(hname, \"Allies\", (1 << HOUSE_NEUTRAL));\n\t\tp->Make_Ally(index);\n\t\tp->Make_Ally(HOUSE_NEUTRAL);\n\t\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tif ((owners & (1 << h)) != 0) {\n\t\t\t\tp->Make_Ally(h);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Write_INI -- Writes the house data to the INI database.                         *\n *                                                                                             *\n *    This routine will write out all data necessary to recreate it in anticipation of a       *\n *    new scenario. All houses (that are active) will have their scenario type data written    *\n *    out.                                                                                     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to write the data to.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tThe identity house control object. Only if the house value differs from the\n\t**\tidentity, will the data be written out.\n\t*/\n\tHouseStaticClass control;\n\n\tfor (HousesType i = HOUSE_FIRST; i < HOUSE_COUNT; i++) {\n\t\tHouseClass * p = As_Pointer(i);\n\n\t\tif (p != NULL) {\n\t\t\tchar const * name = p->Class->IniName;\n\n\t\t\tini.Clear(name);\n\t\t\tif (i >= HOUSE_MULTI1) continue;\n\n\t\t\tif (p->Control.InitialCredits != control.InitialCredits) {\n\t\t\t\tini.Put_Int(name, \"Credits\", (int)(p->Control.InitialCredits / 100));\n\t\t\t}\n\n\t\t\tif (p->Control.Edge != control.Edge) {\n\t\t\t\tini.Put_SourceType(name, \"Edge\", p->Control.Edge);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxUnit > 0 && p->Control.MaxUnit != control.MaxUnit) {\n\t\t\t\tini.Put_Int(name, \"MaxUnit\", p->Control.MaxUnit);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxInfantry > 0 && p->Control.MaxInfantry != control.MaxInfantry) {\n\t\t\t\tini.Put_Int(name, \"MaxInfantry\", p->Control.MaxInfantry);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxBuilding > 0 && p->Control.MaxBuilding != control.MaxBuilding) {\n\t\t\t\tini.Put_Int(name, \"MaxBuilding\", p->Control.MaxBuilding);\n\t\t\t}\n\n\t\t\tif (p->Control.MaxVessel > 0 && p->Control.MaxVessel != control.MaxVessel) {\n\t\t\t\tini.Put_Int(name, \"MaxVessel\", p->Control.MaxVessel);\n\t\t\t}\n\n\t\t\tif (p->Control.TechLevel != control.TechLevel) {\n\t\t\t\tini.Put_Int(name, \"TechLevel\", p->Control.TechLevel);\n\t\t\t}\n\n\t\t\tif (p->Control.IQ != control.IQ) {\n\t\t\t\tini.Put_Int(name, \"IQ\", p->Control.IQ);\n\t\t\t}\n\n\t\t\tif (p->IsPlayerControl != false && p != PlayerPtr) {\n\t\t\t\tini.Put_Bool(name, \"PlayerControl\", p->IsPlayerControl);\n\t\t\t}\n\n\t\t\tini.Put_Owners(name, \"Allies\", p->Control.Allies & ~((1 << p->Class->House) | (1 << HOUSE_NEUTRAL)));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.           *\n *                                                                                             *\n *    This routine will examine the current yak and mig situation verses airfields. If there   *\n *    are equal aircraft to airfields, then this routine will return TRUE.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Are all airfields full and thus no more yaks or migs are allowed?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_No_YakMig(void) const\n{\n\tint quantity = AQuantity[AIRCRAFT_YAK] + AQuantity[AIRCRAFT_MIG];\n\n\t/*\n\t**\tAdjust the quantity down one if there is an aircraft in production. This will\n\t**\tallow production to resume after being held.\n\t*/\n\tFactoryClass const * factory = Fetch_Factory(RTTI_AIRCRAFT);\n\tif (factory != NULL && factory->Get_Object() != NULL) {\n\t\tAircraftClass const * air = (AircraftClass const *)factory->Get_Object();\n\t\tif (*air == AIRCRAFT_MIG || *air == AIRCRAFT_YAK) {\n\t\t\tquantity -= 1;\n\t\t}\n\t}\n\n\tif (quantity >= BQuantity[STRUCT_AIRSTRIP]) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?      *\n *                                                                                             *\n *    This is a special hack check routine to see if the object type and id specified is       *\n *    prevented from being produced. The Yak and the Mig are so prevented if there would be    *\n *    insufficient airfields for them to land upon.                                            *\n *                                                                                             *\n * INPUT:   rtti  -- The RTTI type of the value specified.                                     *\n *                                                                                             *\n *          value -- The type number (according to the RTTI type specified).                   *\n *                                                                                             *\n * OUTPUT:  bool; Is production of this object prohibited?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Hack_Prevented(RTTIType rtti, int value) const\n{\n\tif (rtti == RTTI_AIRCRAFTTYPE && (value == AIRCRAFT_MIG || value == AIRCRAFT_YAK)) {\n\t\treturn(Is_No_YakMig());\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Fire_Sale -- Cause all buildings to be sold.                                    *\n *                                                                                             *\n *    This routine will sell back all buildings owned by this house.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was a fire sale performed?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Fire_Sale(void)\n{\n\tif (CurBuildings > 0) {\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * b = Buildings.Ptr(index);\n\n\t\t\tif (b != NULL && !b->IsInLimbo && b->House == this && b->Strength > 0) {\n\t\t\t\tb->Sell_Back(1);\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                       *\n *                                                                                             *\n *    This routine will cause all combatants of this house to go into hunt mode. The effect of *\n *    this is to throw everything this house has to muster at the enemies of this house.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *   10/02/1996 JLB : Handles aircraft too.                                                    *\n *=============================================================================================*/\nvoid HouseClass::Do_All_To_Hunt(void) const\n{\n\tint index;\n\n\tfor (index = 0; index < Units.Count(); index++) {\n\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\tif (unit->House == this && unit->IsDown && !unit->IsInLimbo) {\n\t\t\tif (unit->Team) unit->Team->Remove(unit);\n\t\t\tunit->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\n\t\tif (infantry->House == this && infantry->IsDown && !infantry->IsInLimbo) {\n\t\t\tif (infantry->Team) infantry->Team->Remove(infantry);\n\t\t\tinfantry->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\tVesselClass * vessel = Vessels.Ptr(index);\n\n\t\tif (vessel->House == this && vessel->IsDown && !vessel->IsInLimbo) {\n\t\t\tif (vessel->Team) vessel->Team->Remove(vessel);\n\t\t\tvessel->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n\n\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * aircraft = Aircraft.Ptr(index);\n\n\t\tif (aircraft->House == this && aircraft->IsDown && !aircraft->IsInLimbo) {\n\t\t\tif (aircraft->Team) aircraft->Team->Remove(aircraft);\n\t\t\taircraft->Assign_Mission(MISSION_HUNT);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.        *\n *                                                                                             *\n *    Use this routine to determine if this house is legally allowed to ally with the          *\n *    house specified. There are many reason why an alliance is not allowed. Typically, this   *\n *    is when there would be no more opponents left to fight or if this house has been         *\n *    defeated.                                                                                *\n *                                                                                             *\n * INPUT:   house -- The house that alliance with is desired.                                  *\n *                                                                                             *\n * OUTPUT:  bool; Is alliance with the house specified prohibited?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool HouseClass::Is_Allowed_To_Ally(HousesType house) const\n{\n\t/*\n\t**\tIs not allowed to ally with a house that is patently invalid, such\n\t**\tas one that is illegally defined.\n\t*/\n\tif (house == HOUSE_NONE) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOne cannot ally twice with the same house.\n\t*/\n\tif (Is_Ally(house)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tIf the scenario is being set up, then alliances are always\n\t**\tallowed. No further checking is required.\n\t*/\n\tif (ScenarioInit) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tAlliances (outside of scneario init time) are allowed only if\n\t**\tthis is a multiplayer game. Otherwise, they are prohibited.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen the house is defeated, it can no longer make alliances.\n\t*/\n\tif (IsDefeated) {\n\t\treturn(false);\n\t}\n\n#ifdef FIXIT_VERSION_3\n\t// Fix to prevent ally with computer.\n\tif ( !HouseClass::As_Pointer(house)->IsHuman) {\n\t\treturn(false);\n\t}\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_NO_COMP_ALLY\n\t// Fix to prevent ally with computer.\n\tif (PlayingAgainstVersion > VERSION_RED_ALERT_104 && !HouseClass::As_Pointer(house)->IsHuman) {\n\t\treturn(false);\n\t}\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\n\t/*\n\t**\tCount the number of active houses in the game as well as the\n\t**\tnumber of existing allies with this house.\n\t*/\n\tint housecount = 0;\n\tint allycount = 0;\n\tfor (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house2);\n\t\tif (hptr != NULL && hptr->IsActive && !hptr->IsDefeated) {\n\t\t\thousecount++;\n\t\t\tif (Is_Ally(hptr)) {\n\t\t\t\tallycount++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tAlliance is not allowed if there wouldn't be any enemies left to\n\t**\tfight.\n\t*/\n\tif (housecount == allycount+1) {\n\t\treturn(false);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.              *\n *                                                                                             *\n *    This routine will cause the computer players to become suspicious of the human           *\n *    players and thus the computer players will band together in order to defeat the          *\n *    human players.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Computer_Paranoid(void)\n{\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\t\t// Re-enable this for multiplayer if we support classic team/ally mode. ST - 10/29/2019\n\t\n\t\t/*\n\t\t**\tLoop through every computer controlled house and make allies with all other computer\n\t\t**\tcontrolled houses and then make enemies with all other human controlled houses.\n\t\t*/\n\t\tfor (HousesType house = HOUSE_MULTI1; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr != NULL && hptr->IsActive && !hptr->IsDefeated && !hptr->IsHuman) {\n\t\t\t\thptr->IsParanoid = true;\n\n\t\t\t\t/*\n\t\t\t\t**\tBreak alliance with every human it is allied with and make friends with\n\t\t\t\t**\tany other computer players.\n\t\t\t\t*/\n\t\t\t\tfor (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {\n\t\t\t\t\tHouseClass * hptr2 = HouseClass::As_Pointer(house2);\n\t\t\t\t\tif (hptr2 != NULL && hptr2->IsActive && !hptr2->IsDefeated) {\n\t\t\t\t\t\tif (hptr2->IsHuman) {\n\t\t\t\t\t\t\thptr->Make_Enemy(house2);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thptr->Make_Ally(house2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Power -- Adjust the power value of the house.                            *\n *                                                                                             *\n *    This routine will update the power output value of the house. It will cause any buildgins*\n *    that need to be redrawn to do so.                                                        *\n *                                                                                             *\n * INPUT:   adjust   -- The amount to adjust the power output value.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Power(int adjust)\n{\n\tPower += adjust;\n\n\tUpdate_Spied_Power_Plants();\n}\n\n\n/***********************************************************************************************\n * HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                      *\n *                                                                                             *\n *    This routine will update the drain value of the house. It will cause any buildings that  *\n *    need to be redraw to do so.                                                              *\n *                                                                                             *\n * INPUT:   adjust   -- The amount to adjust the drain (positive means more drain).            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Adjust_Drain(int adjust)\n{\n\tDrain += adjust;\n\tUpdate_Spied_Power_Plants();\n}\n\n\n/***********************************************************************************************\n * HouseClass::Update_Spied_Power_Plants -- Redraw power graphs on spied-upon power plants.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/11/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid HouseClass::Update_Spied_Power_Plants(void)\n{\n\tint count = CurrentObject.Count();\n\tif (count) {\n\t\tfor (int index = 0; index < count; index++) {\n\t\t\tObjectClass const * tech = CurrentObject[index];\n\t\t\tif (tech && tech->What_Am_I()==RTTI_BUILDING) {\n\t\t\t\tBuildingClass *bldg = (BuildingClass *)tech;\n\t\t\t\tif (!bldg->IsOwnedByPlayer && *bldg == STRUCT_POWER || *bldg == STRUCT_ADVANCED_POWER) {\n\t\t\t\t\tif ( bldg->Spied_By() & (1<<(PlayerPtr->Class->House)) ) {\n\t\t\t\t\t\tbldg->Mark(MARK_CHANGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.              *\n *                                                                                             *\n *    Use this routine to determine where the specified object should go if it were to go      *\n *    some random (but legal) location within the zone specified.                              *\n *                                                                                             *\n * INPUT:   techno   -- The object that is desirous of going into the zone specified.          *\n *                                                                                             *\n *          zone     -- The zone to find a location within.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that the specified object could be placed in the zone. If    *\n *          no valid location could be found, then 0 is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1996 JLB : Created.                                                                 *\n *   11/04/1996 JLB : Not so strict on zone requirement.                                       *\n *=============================================================================================*/\nCELL HouseClass::Find_Cell_In_Zone(TechnoClass const * techno, ZoneType zone) const\n{\n\tif (techno == NULL) return(0);\n\n\tint bestval = -1;\n\tint bestcell = 0;\n\tTechnoTypeClass const * ttype = techno->Techno_Type_Class();\n\n\t/*\n\t**\tPick a random location within the zone specified.\n\t*/\n\tCELL trycell = Random_Cell_In_Zone(zone);\n\n\tshort const * list = NULL;\n\tif (techno->What_Am_I() == RTTI_BUILDING) {\n\t\tlist = techno->Occupy_List(true);\n\t}\n\n\t/*\n\t**\tFind a legal placement position as close as possible to the picked location while still\n\t**\tremaining within the zone.\n\t*/\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n//\t\tif (Map.In_Radar(cell)) {\n\t\tif (Map.In_Radar(cell) && Which_Zone(cell) != ZONE_NONE) {\n\t\t\tbool ok = ttype->Legal_Placement(cell);\n\n\t\t\t/*\n\t\t\t**\tAnother (adjacency) check is required for buildings.\n\t\t\t*/\n\t\t\tif (ok && list != NULL && !Map.Passes_Proximity_Check(ttype, techno->House->Class->House, list, cell)) {\n\t\t\t\tok = false;\n\t\t\t}\n\n\t\t\tif (ok) {\n\t\t\t\tint dist = Distance(Cell_Coord(cell), Cell_Coord(trycell));\n\t\t\t\tif (bestval == -1 || dist < bestval) {\n\t\t\t\t\tbestval = dist;\n\t\t\t\t\tbestcell = cell;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn the best location to move to.\n\t*/\n\treturn(bestcell);\n}\n\n\n/***********************************************************************************************\n * HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified.   *\n *                                                                                             *\n *    This routine will pick a random cell within the zone specified. The pick will be         *\n *    clipped to the map edge when necessary.                                                  *\n *                                                                                             *\n * INPUT:   zone  -- The zone to pick a cell from.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with a picked cell within the zone. If the entire zone lies outside of the *\n *          map, then a cell in the core zone is returned instead.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL HouseClass::Random_Cell_In_Zone(ZoneType zone) const\n{\n\tCOORDINATE coord = 0;\n\tint maxdist = 0;\n\tswitch (zone) {\n\t\tcase ZONE_CORE:\n\t\t\tcoord = Coord_Scatter(Center, Random_Pick(0, Radius), true);\n\t\t\tbreak;\n\n\t\tcase ZONE_NORTH:\n\t\t\tmaxdist = min(Radius*3, (Coord_Y(Center) - Cell_To_Lepton(Map.MapCellY)) - CELL_LEPTON_H);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, (DirType)(Random_Pick(DIR_N, DIR_E)-((DirType)32)), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_EAST:\n\t\t\tmaxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth) - Coord_X(Center)) - CELL_LEPTON_W);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_NE, DIR_SE), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_SOUTH:\n\t\t\tmaxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight) - Coord_Y(Center)) - CELL_LEPTON_H);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_SE, DIR_SW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\n\t\tcase ZONE_WEST:\n\t\t\tmaxdist = min(Radius*3, (Coord_X(Center) - Cell_To_Lepton(Map.MapCellX)) - CELL_LEPTON_W);\n\t\t\tif (maxdist < 0) break;\n\t\t\tcoord = Coord_Move(Center, Random_Pick(DIR_SW, DIR_NW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tDouble check that the location is valid and if so, convert it into a cell\n\t**\tnumber.\n\t*/\n\tCELL cell;\n\tif (coord == 0 || !Map.In_Radar(Coord_Cell(coord))) {\n\t\tif (zone == ZONE_CORE) {\n\n\t\t\t/*\n\t\t\t**\tFinding a cell within the core failed, so just pick the center\n\t\t\t**\tcell. This cell is guaranteed to be valid.\n\t\t\t*/\n\t\t\tcell = Coord_Cell(Center);\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the edge fails, then try to find a cell within the core.\n\t\t\t*/\n\t\t\tcell = Random_Cell_In_Zone(ZONE_CORE);\n\t\t}\n\t} else {\n\t\tcell = Coord_Cell(coord);\n\t}\n\n\t/*\n\t**\tIf the randomly picked location is not in the legal map area, then clip it to\n\t**\tthe legal map area.\n\t*/\n\tif (!Map.In_Radar(cell)) {\n\t\tint x = Cell_X(cell);\n\t\tint y = Cell_Y(cell);\n\n\t\tif (x < Map.MapCellX) x = Map.MapCellX;\n\t\tif (y < Map.MapCellY) y = Map.MapCellY;\n\t\tif (x >= Map.MapCellX + Map.MapCellWidth) x = Map.MapCellX + Map.MapCellWidth -1;\n\t\tif (y >= Map.MapCellY + Map.MapCellHeight) y = Map.MapCellY + Map.MapCellHeight -1;\n\t\tcell = XY_Cell(x, y);\n\t}\n\treturn(cell);\n}\n\n/***********************************************************************************************\n * HouseClass::Get_Ally_Flags --  Get the bit flags denoting the allies this house has.\t\t  *\n *                                                                                             *\n * INPUT:   none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  Returns the bit field storing which houses this house is allied with.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/12/2019 JAS : Created.                                                                 *\n *=============================================================================================*/\nunsigned HouseClass::Get_Ally_Flags()\n{\n\treturn Allies;\n}\n\n\n\n/***********************************************************************************************\n * HouseClass::Check_Pertinent_Structures -- See if any useful structures remain               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   1/31/2020 3:34PM ST : Created.                                                            *\n *=============================================================================================*/\nvoid HouseClass::Check_Pertinent_Structures(void)\n{\n\t/*\n\t** New default win mode to avoid griefing. ST - 1/31/2020 3:33PM\n\t**\n\t** Game is over when no pertinent structures remain\n\t*/\n\n\tif (!Special.IsEarlyWin) {\n\t\treturn;\n\t}\n\t\t  \n\tif (IsToDie || IsToWin || IsToLose) {\n\t\treturn;\n\t}\n\n\t// MBL 07.15.2020 - Prevention of recent issue with constant \"player defeated logic\" and message to client spamming\n\t// Per https://jaas.ea.com/browse/TDRA-7433\n\t//\n\tif (IsDefeated) {\n\t\treturn;\n\t}\n\n\tbool any_good_buildings = false;\n\t\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass *b = Buildings.Ptr(index);\n\n\t\tif (b && b->IsActive && b->House == this) {\n\t\t\tif (!b->Class->IsWall && *b != STRUCT_APMINE && *b != STRUCT_AVMINE) {\n\t\t\t\tif (!Special.ModernBalance || (*b != STRUCT_SHIP_YARD && *b != STRUCT_FAKE_YARD && *b != STRUCT_SUB_PEN && *b != STRUCT_FAKE_PEN)) {\n\t\t\t\t\tif (!b->IsInLimbo && b->Strength > 0) {\n\t\t\t\t\t\tany_good_buildings = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (!any_good_buildings) {\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * unit = Units.Ptr(index);\n\n\t\t\tif (unit && unit->IsActive && *unit == UNIT_MCV && unit->House == this) {\n\t\t\t\tif (!unit->IsInLimbo && unit->Strength > 0) {\n\t\t\t\t\tany_good_buildings = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!any_good_buildings) {\n\t\tFlag_To_Die();\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * HouseClass::Init_Unit_Trackers -- Allocate the unit trackers for the house                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   4/23/2020 11:06PM ST : Created.                                                           *\n *=============================================================================================*/\nvoid HouseClass::Init_Unit_Trackers(void)\n{\t\t\n\tif (Session.Type == GAME_INTERNET || Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\tAircraftTotals = new UnitTrackerClass( (int) AIRCRAFT_COUNT);\n\t\tInfantryTotals = new UnitTrackerClass( (int) INFANTRY_COUNT);\n\t\tUnitTotals = new UnitTrackerClass ( (int) UNIT_COUNT);\n\t\tBuildingTotals = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tVesselTotals = new UnitTrackerClass ( (int) VESSEL_COUNT);\n\n\t\tDestroyedAircraft = new UnitTrackerClass ( (int) AIRCRAFT_COUNT);\n\t\tDestroyedInfantry = new UnitTrackerClass( (int) INFANTRY_COUNT);\n\t\tDestroyedUnits = new UnitTrackerClass ( (int) UNIT_COUNT);\n\t\tDestroyedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tDestroyedVessels = new UnitTrackerClass ( (int) VESSEL_COUNT);\n\n\t\tCapturedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);\n\t\tTotalCrates = new UnitTrackerClass ( CRATE_COUNT );\n\t} else {\n\t\t\n\t\tAircraftTotals = NULL;\n\t\tInfantryTotals = NULL;\n\t\tUnitTotals = NULL;\n\t\tBuildingTotals = NULL;\n\t\tVesselTotals = NULL;\n\n\t\tDestroyedAircraft = NULL;\n\t\tDestroyedInfantry = NULL;\n\t\tDestroyedUnits = NULL;\n\t\tDestroyedBuildings = NULL;\n\t\tDestroyedVessels = NULL;\n\n\t\tCapturedBuildings = NULL;\n\t\tTotalCrates = NULL;\n\t}\t\n}\n\n\n\n/***********************************************************************************************\n * HouseClass::Free_Unit_Trackers -- Free the unit trackers for the house                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   4/23/2020 11:06PM ST : Created.                                                           *\n *=============================================================================================*/\nvoid HouseClass::Free_Unit_Trackers(void)\n{\t\t\n\tif (AircraftTotals) {\n\t\tdelete AircraftTotals;\n\t\tAircraftTotals = NULL;\n\t}\n\n\tif (InfantryTotals) {\n\t\tdelete InfantryTotals;\n\t\tInfantryTotals = NULL;\n\t}\n\n\tif (UnitTotals) {\n\t\tdelete UnitTotals;\n\t\tUnitTotals = NULL;\n\t}\n\n\tif (BuildingTotals) {\n\t\tdelete BuildingTotals;\n\t\tBuildingTotals = NULL;\n\t}\n\n\tif (VesselTotals) {\n\t\tdelete VesselTotals;\n\t\tVesselTotals = NULL;\n\t}\n\n\tif (DestroyedAircraft) {\n\t\tdelete DestroyedAircraft;\n\t\tDestroyedAircraft = NULL;\n\t}\n\n\tif (DestroyedInfantry) {\n\t\tdelete DestroyedInfantry;\n\t\tDestroyedInfantry = NULL;\n\t}\n\n\tif (DestroyedUnits) {\n\t\tdelete DestroyedUnits;\n\t\tDestroyedUnits = NULL;\n\t}\n\n\tif (DestroyedBuildings) {\n\t\tdelete DestroyedBuildings;\n\t\tDestroyedBuildings = NULL;\n\t}\n\n\tif (DestroyedVessels) {\n\t\tdelete DestroyedVessels;\n\t\tDestroyedVessels = NULL;\n\t}\n\n\tif (CapturedBuildings) {\n\t\tdelete CapturedBuildings;\n\t\tCapturedBuildings = NULL;\n\t}\n\n\tif (TotalCrates) {\n\t\tdelete TotalCrates;\n\t\tTotalCrates = NULL;\n\t}\n}"
  },
  {
    "path": "REDALERT/HOUSE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HOUSE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 21, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 21, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef HOUSE_H\n#define HOUSE_H\n\n#include\t\"type.h\"\n#include\t\"region.h\"\n#include\t\"vector.h\"\n#include \"Credits.h\"\n\nclass TriggerClass;\nclass FootClass;\nclass FactoryClass;\n\n#define HOUSE_NAME_MAX\t12\n\n\n/****************************************************************************\n**\tCertain aspects of the house \"country\" are initially set by the scenario\n**\tcontrol file. This information is static for the duration of the current\n**\tscenario, but is dynamic between scenarios. As such, it can't be placed in\n**\tthe static HouseTypeClass structure, but is embedded into the house\n**\tclass instead.\n*/\nclass HouseStaticClass {\n\tpublic:\n\t\tHouseStaticClass(void);\n\t\tHouseStaticClass(NoInitClass const & ) {};\n\n\t\t/*\n\t\t**\tThis value indicates the degree of smartness to assign to this house.\n\t\t**\tA value is zero is presumed for human controlled houses.\n\t\t*/\n\t\tint IQ;\n\n\t\t/*\n\t\t**\tThis is the buildable tech level for this house. This value is used\n\t\t**\tfor when the computer is deciding what objects to build.\n\t\t*/\n\t\tint TechLevel;\n\n\t\t/*\n\t\t**\tThis is the original ally specification to use at scenario\n\t\t**\tstart. Various forces during play may adjust the ally state\n\t\t**\tof this house.\n\t\t*/\n\t\tint Allies;\n\n\t\t/*\n\t\t**\tThis is the maximum number allowed to be built by this house. The\n\t\t**\tvalue depends on the scenario being played.\n\t\t*/\n\t\tunsigned MaxUnit;\n\t\tunsigned MaxBuilding;\n\t\tunsigned MaxInfantry;\n\t\tunsigned MaxVessel;\n\t\tunsigned MaxAircraft;\n\n\t\t/*\n\t\t**\tThis records the initial credits assigned to this house when the scenario\n\t\t**\twas loaded.\n\t\t*/\n\t\tlong InitialCredits;\n\n\t\t/*\n\t\t**\tFor generic (unspecified) reinforcements, they arrive by a common method. This\n\t\t**\tspecifies which method is to be used.\n\t\t*/\n\t\tSourceType Edge;\n};\n\n\n/****************************************************************************\n**\tPlayer control structure. Each player (computer or human) has one of\n**\tthese structures associated. These are located in a global array.\n*/\nclass HouseClass {\n\tpublic:\n\t\tRTTIType RTTI;\n\t\tint ID;\n\n\t\t/*\n\t\t**\tPointer to the HouseTypeClass that this house is \"owned\" by.\n\t\t**\tAll constant data for a house type is stored in that class.\n\t\t*/\n\t\tCCPtr<HouseTypeClass> Class;\n\n\t\t/*\n\t\t**\tThis is the handicap (difficulty level) assigned to this house.\n\t\t*/\n\t\tDiffType Difficulty;\n\n\t\t/*\n\t\t**\tOverride handicap control values.\n\t\t*/\n\t\tfixed FirepowerBias;\n\t\tfixed GroundspeedBias;\n\t\tfixed AirspeedBias;\n\t\tfixed ArmorBias;\n\t\tfixed ROFBias;\n\t\tfixed CostBias;\n\t\tfixed BuildSpeedBias;\n\t\tfixed RepairDelay;\n\t\tfixed BuildDelay;\n\n\t\t/*\n\t\t**\tThe initial house data as loaded from the scenario control file is\n\t\t**\tstored here. Although this data changes for each scenario, it remains\n\t\t**\tstatic for the duration of the current scenario.\n\t\t*/\n\t\tHouseStaticClass Control;\n\n\t\t/*\n\t\t**\tThis is the house type that this house object should act like. This\n\t\t**\tvalue controls production choices and radar cover plate imagery.\n\t\t*/\n\t\tHousesType ActLike;\n\n\t\t/*\n\t\t**\tIs this player active?  Usually that answer is true, but for civilians, it\n\t\t**\tmight possibly be false.\n\t\t*/\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tIf this house is controlled by the player, then this flag will be true. The\n\t\t**\tcomputer controls all other active houses.\n\t\t*/\n\t\tunsigned IsHuman:1;\n\t\tunsigned WasHuman:1;\n\n\t\t/*\n\t\t**\tIf the player can control units of this house even if the player doesn't\n\t\t**\town units of this house, then this flag will be true.\n\t\t*/\n\t\tunsigned IsPlayerControl:1;\n\n\t\t/*\n\t\t**\tThis flag enables production. If the flag is false, production is disabled.\n\t\t**\tBy timing when this flag gets set, the player can be given some breathing room.\n\t\t*/\n\t\tunsigned IsStarted:1;\n\n\t\t/*\n\t\t**\tWhen alerted, the house will create teams of the special \"auto\" type and\n\t\t**\twill generate appropriate units to fill those team types.\n\t\t*/\n\t\tunsigned IsAlerted:1;\n\n\t\t/*\n\t\t**\tIf automatic base building is on, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsBaseBuilding:1;\n\n\t\t/*\n\t\t**\tIf the house has been discovered, then this flag will be set\n\t\t**\tto true. However, the trigger even associated with discovery\n\t\t**\twill only be executed during the next house AI process.\n\t\t*/\n\t\tunsigned IsDiscovered:1;\n\n\t\t/*\n\t\t**\tIf Tiberium storage is maxed out, then this flag will be set. At some point\n\t\t**\tthe player is told of this fact and then this flag is cleared. This allows the\n\t\t**\tplayer to be told, but only occasionally rather than continuously.\n\t\t*/\n\t\tunsigned IsMaxedOut:1;\n\n\t\t/*\n\t\t** If this house is played by a human in a multiplayer game, this flag\n\t\t** keeps track of whether this house has been defeated or not.\n\t\t*/\n\t\tunsigned IsDefeated:1;\n\n\t\t/*\n\t\t**\tThese flags are used in conjunction with the BorrowedTime timer. When\n\t\t**\tthat timer expires and one of these flags are set, then that event is\n\t\t**\tapplied to the house. This allows a dramatic pause between the event\n\t\t**\ttrigger and the result.\n\t\t*/\n\t\tunsigned IsToDie:1;\n\t\tunsigned IsToWin:1;\n\t\tunsigned IsToLose:1;\n\n\t\t/*\n\t\t**\tThis flag is set when a transport carrying a civilian has been\n\t\t**\tsuccessfully evacuated. It is presumed that a possible trigger\n\t\t**\tevent will be sprung by this event.\n\t\t*/\n\t\tunsigned IsCivEvacuated:1;\n\n\t\t/*\n\t\t**\tIf potentially something changed that might affect the sidebar list of\n\t\t**\tbuildable objects, then this flag indicates that at the first LEGAL opportunity,\n\t\t**\tthe sidebar will be recalculated.\n\t\t*/\n\t\tunsigned IsRecalcNeeded:1;\n\n\t\t/*\n\t\t**\tIf the map has been completely revealed to the player, then this flag\n\t\t**\twill be set to true. By examining this flag, a second \"reveal all map\"\n\t\t**\tcrate won't be given to the player.\n\t\t*/\n\t\tunsigned IsVisionary:1;\n\n\t\t/*\n\t\t**\tThis flag is set to true when the house has determined that\n\t\t**\tthere is insufficient Tiberium to keep the harvesters busy.\n\t\t**\tIn such a case, the further refinery/harvester production\n\t\t**\tshould cease. This is one of the first signs that the endgame\n\t\t**\thas begun.\n\t\t*/\n\t\tunsigned IsTiberiumShort:1;\n\n\t\t/*\n\t\t**\tThese flags are used for the general house trigger events of being\n\t\t**\tspied and thieved. The appropriate flag will be set when the event\n\t\t**\toccurs.\n\t\t*/\n\t\tunsigned IsSpied:1;\n\t\tunsigned IsThieved:1;\n\n\t\t/*\n\t\t** This flag is used to control non-human repairing of buildings.  Each\n\t\t** house gets to repair one building per loop, and this flag controls\n\t\t** whether this house has 'spent' its repair option this time through.\n\t\t*/\n\t\tunsigned DidRepair:1;\n\n\t\t/*\n\t\t** This flag is used to control whether or not this house has the GPS\n\t\t** satellite in orbit.  If the satellite's there, they have unlimited\n\t\t** radar and the map is fully revealed.\n\t\t*/\n\t\tunsigned IsGPSActive:1;\n\n\t\t/*\n\t\t**\tIf the JustBuilt??? variable has changed, then this flag will\n\t\t**\tbe set to true.\n\t\t*/\n\t\tunsigned IsBuiltSomething:1;\n\n\t\t/*\n\t\t** Did this house lose via resignation?\n\t\t*/\n\t\tunsigned IsResigner:1;\n\n\t\t/*\n\t\t** Did this house lose because the player quit?\n\t\t*/\n\t\tunsigned IsGiverUpper:1;\n\n\t\t/*\n\t\t**\tIf this computer controlled house has reason to be mad at humans,\n\t\t**\tthen this flag will be true. Such a condition prevents alliances with\n\t\t**\ta human and encourages the computers players to ally amongst themselves.\n\t\t*/\n\t\tunsigned IsParanoid:1;\n\n\t\t/*\n\t\t**\tA gap generator shrouded cells and all units of this house must perform\n\t\t**\ta look just in case their look radius intersects the shroud area.\n\t\t*/\n\t\tunsigned IsToLook:1;\n\n\t\t/*\n\t\t**\tMBL 03.23.2020 - Support for queued movement mode (informed from the client)\n\t\t*/\n\t\tunsigned IsQueuedMovementToggle:1;\n\n\t\t/*\n\t\t**\tThis value indicates the degree of smartness to assign to this house.\n\t\t**\tA value of zero indicates that the player controls everything.\n\t\t*/\n\t\tint IQ;\n\n\t\t/*\n\t\t**\tThis records the current state of the base. This state is used to control\n\t\t**\twhat action the base will perform and directly affects production and\n\t\t**\tunit disposition. The state will change according to time and combat\n\t\t**\tevents.\n\t\t*/\n\t\tStateType State;\n\n\t\t/*\n\t\t**\tThese super weapon control objects are used to control the recharge\n\t\t**\tand availability of these special weapons to this house.\n\t\t*/\n\t\tSuperClass SuperWeapon[SPC_COUNT];\n\n\t\t/*\n\t\t**\tThis is a record of the last building that was built. For buildings that\n\t\t**\twere built as a part of scenario creation, it will be the last one\n\t\t**\tdiscovered.\n\t\t*/\n\t\tStructType JustBuiltStructure;\n\t\tInfantryType JustBuiltInfantry;\n\t\tUnitType JustBuiltUnit;\n\t\tAircraftType JustBuiltAircraft;\n\t\tVesselType JustBuiltVessel;\n\n\t\t/*\n\t\t**\tThis records the number of triggers associated with this house that are\n\t\t**\tblocking a win condition. A win will only occur if all the blocking\n\t\t**\ttriggers have been deleted.\n\t\t*/\n\t\tint Blockage;\n\n\t\t/*\n\t\t**\tFor computer controlled houses, there is an artificial delay between\n\t\t**\tperforming repair actions. This timer regulates that delay. If the\n\t\t**\ttimer has not expired, then no repair initiation is allowed.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> RepairTimer;\n\n\t\t/*\n\t\t**\tThis timer controls the computer auto-attack logic. When this timer expires\n\t\t**\tand the house has been alerted, then it will create a set of attack\n\t\t**\tteams.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> AlertTime;\n\n\t\t/*\n\t\t**\tThis timer is used to handle the delay between some catastrophic\n\t\t**\tevent trigger and when it is actually carried out.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> BorrowedTime;\n\n\t\t/*\n\t\t**\tThis is the last working scan bits for buildings. If a building is\n\t\t**\tactive and owned by this house, it will have a bit set in this element\n\t\t**\tthat corresponds to the building type number. Since this value is\n\t\t**\taccumulated over time, the \"New\" element contains the under-construction\n\t\t**\tversion.\n\t\t*/\n\t\tunsigned long BScan;\n\t\tunsigned long ActiveBScan;\n\t\tunsigned long OldBScan;\n\n\t\t/*\n\t\t**\tThis is the last working scan bits for units. For every existing unit\n\t\t**\ttype owned by this house, a corresponding bit is set in this element. As\n\t\t**\tthe scan bits are being constructed, they are built into the \"New\" element\n\t\t**\tand then duplicated into the regular element at the end of every logic cycle.\n\t\t*/\n\t\tunsigned long UScan;\n\t\tunsigned long ActiveUScan;\n\t\tunsigned long OldUScan;\n\n\t\t/*\n\t\t**\tInfantry type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long IScan;\n\t\tunsigned long ActiveIScan;\n\t\tunsigned long OldIScan;\n\n\t\t/*\n\t\t**\tAircraft type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long AScan;\n\t\tunsigned long ActiveAScan;\n\t\tunsigned long OldAScan;\n\n\t\t/*\n\t\t**\tVessel type existence bits. Similar to unit and building bits.\n\t\t*/\n\t\tunsigned long VScan;\n\t\tunsigned long ActiveVScan;\n\t\tunsigned long OldVScan;\n\n\t\t/*\n\t\t**\tRecord of gains and losses for this house during the course of the\n\t\t**\tscenario.\n\t\t*/\n\t\tunsigned CreditsSpent;\n\t\tunsigned HarvestedCredits;\n\t\tint StolenBuildingsCredits;\n\n\t\t/*\n\t\t**\tThis is the running count of the number of units owned by this house. This\n\t\t**\tvalue is used to keep track of ownership limits.\n\t\t*/\n\t\tunsigned CurUnits;\n\t\tunsigned CurBuildings;\n\t\tunsigned CurInfantry;\n\t\tunsigned CurVessels;\n\t\tunsigned CurAircraft;\n\n\t\t/*\n\t\t**\tThis is the running total of the number of credits this house has accumulated.\n\t\t*/\n\t\tlong Tiberium;\n\t\tlong Credits;\n\t\tlong Capacity;\n\n\t\t/*\n\t\t** Stuff to keep track of the total number of units built by this house.\n\t\t*/\n\t\tUnitTrackerClass * AircraftTotals;\n\t\tUnitTrackerClass * InfantryTotals;\n\t\tUnitTrackerClass * UnitTotals;\n\t\tUnitTrackerClass * BuildingTotals;\n\t\tUnitTrackerClass * VesselTotals;\n\n\t\t/*\n\t\t** Total number of units destroyed by this house\n\t\t*/\n\t\tUnitTrackerClass * DestroyedAircraft;\n\t\tUnitTrackerClass * DestroyedInfantry;\n\t\tUnitTrackerClass * DestroyedUnits;\n\t\tUnitTrackerClass * DestroyedBuildings;\n\t\tUnitTrackerClass * DestroyedVessels;\n\n\t\t/*\n\t\t** Total number of enemy buildings captured by this house\n\t\t*/\n\t\tUnitTrackerClass * CapturedBuildings;\n\n\t\t/*\n\t\t** Total number of crates found by this house\n\t\t*/\n\t\tUnitTrackerClass * TotalCrates;\n\n\t\t/*\n\t\t**\tRecords the number of infantry and vehicle factories active. This value is\n\t\t**\tused to regulate the speed of production.\n\t\t*/\n\t\tint AircraftFactories;\n\t\tint InfantryFactories;\n\t\tint UnitFactories;\n\t\tint VesselFactories;\n\t\tint BuildingFactories;\n\n\t\t/*\n\t\t**\tThis is the accumulation of the total power and drain factors. From these\n\t\t**\tvalues a ratio can be derived. This ratio is used to control the rate\n\t\t**\tof building decay.\n\t\t*/\n\t\tint Power;\t\t\t\t\t// Current power output.\n\t\tint Drain;\t\t\t\t\t// Power consumption.\n\n\t\t/*\n\t\t**\tFor human controlled houses, only one type of unit can be produced\n\t\t**\tat any one instant. These factory objects control this production.\n\t\t*/\n\t\tint AircraftFactory;\n\t\tint InfantryFactory;\n\t\tint UnitFactory;\n\t\tint VesselFactory;\n\t\tint BuildingFactory;\n\n\t\t/*\n\t\t**\tFor human controlled houses, the current state of the radar map\n\t\t*/\n\t\tRadarEnum Radar;\n\n\t\t/*\n\t\t**\tThis target value specifies where the flag is located. It might be a cell\n\t\t**\tor it might be an object.\n\t\t*/\n\t\tTARGET FlagLocation;\n\n\t\t/*\n\t\t** This is the flag-home-cell for this house.  This is where we must bring\n\t\t** another house's flag back to, to defeat that house.\n\t\t*/\n\t\tCELL FlagHome;\n\n\t\t/*\n\t\t** For multiplayer games, each house needs to keep track of how many\n\t\t** objects of each other house they've killed.\n\t\t*/\n\t\tunsigned UnitsKilled[HOUSE_COUNT];\n\t\tunsigned UnitsLost;\n\t\tunsigned BuildingsKilled[HOUSE_COUNT];\n\t\tunsigned BuildingsLost;\n\n\t\t/*\n\t\t** This keeps track of the last house to destroy one of my units.\n\t\t** It's used for scoring multiplayer games.\n\t\t*/\n\t\tHousesType WhoLastHurtMe;\n\n\t\t/*\n\t\t** Start location (waypoint index) passed in from GlyphX\n\t\t*/\n\t\tint StartLocationOverride;\n\n\t\t/*\n\t\t**\tThis records information about the location and size of\n\t\t**\tthe base.\n\t\t*/\n\t\tCOORDINATE Center;\t\t\t// Center of the base.\n\t\tint Radius;\t\t\t\t// Average building distance from center (leptons).\n\t\tstruct {\n\t\t\tint AirDefense;\n\t\t\tint ArmorDefense;\n\t\t\tint InfantryDefense;\n\t\t} ZoneInfo[ZONE_COUNT];\n\n\t\t/*\n\t\t**\tThis records information about the last time a building of this\n\t\t**\tside was attacked. This information is used to determine proper\n\t\t**\tresponse.\n\t\t*/\n\t\tint LATime;\t\t\t\t\t\t// Time of attack.\n\t\tRTTIType LAType;\t\t\t\t// Type of attacker.\n\t\tZoneType LAZone;\t\t\t\t// Last zone that was attacked.\n\t\tHousesType LAEnemy;\t\t\t// Owner of attacker.\n\n\t\t/*\n\t\t**\tThis target value is the building that must be captured as soon as possible.\n\t\t**\tTypically, this will be one of the buildings of this house that has been\n\t\t**\tcaptured and needs to be recaptured.\n\t\t*/\n\t\tTARGET ToCapture;\n\n\t\t/*\n\t\t** This value shows who is spying on this house's radar facilities.\n\t\t** This is used for the other side to be able to update their radar\n\t\t** map based on the cells that this house's units reveal.\n\t\t*/\n\t\tint RadarSpied;\n\n\t\t/*\n\t\t** Running score, based on units destroyed and units lost.\n\t\t*/\n\t\tint PointTotal;\n\n\t\t/*\n\t\t**\tThis is the targeting directions for when this house gets a\n\t\t**\tspecial weapon.\n\t\t*/\n\t\tQuarryType PreferredTarget;\n\n\t\t/*\n\t\t**\tScreen shake timer.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> ScreenShakeTime;\n\n\tprivate:\n\t\t/*\n\t\t**\tTracks number of each building type owned by this house. Even if the\n\t\t**\tbuilding is in construction, it will be reflected in this total.\n\t\t*/\n#ifdef FIXIT_ANTS\n\t\tint BQuantity[STRUCT_COUNT-3];\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint UQuantity[UNIT_RA_COUNT-3];\n#else\n\t\tint UQuantity[UNIT_COUNT-3];\n#endif\n#else\n\t\tint BQuantity[STRUCT_COUNT];\n\t\tint UQuantity[UNIT_COUNT];\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint IQuantity[INFANTRY_RA_COUNT];\n#else\n\t\tint IQuantity[INFANTRY_COUNT];\n#endif\n\t\tint AQuantity[AIRCRAFT_COUNT];\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint VQuantity[VESSEL_RA_COUNT];\n#else\n\t\tint VQuantity[VESSEL_COUNT];\n#endif\n\n\t\t/*\n\t\t**\tThis timer keeps track of when an all out attack should be performed.\n\t\t**\tWhen this timer expires, send most of this house's units in an\n\t\t**\tattack.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Attack;\n\n\tpublic:\n\t\t/*\n\t\t**\tThis records the overriding enemy that the computer will try to\n\t\t**\tdestroy. Typically, this is the last house to attack, but can be\n\t\t**\tinfluenced by nearness.\n\t\t*/\n\t\tHousesType Enemy;\n\n\t\t/*\n\t\t**\tThe house expert system is regulated by this timer. Each computer controlled\n\t\t**\thouse will process the Expert System AI at intermittent intervals. Not only will\n\t\t**\tthis distribute the overhead more evenly, but will add variety to play.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> AITimer;\n\n\t\t/*\n\t\t** For the moebius effect, this is a pointer to the unit that we\n\t\t** selected to teleport.  Only one teleporter should be active per house.\n\t\t*/\n\t\tTARGET UnitToTeleport;\n\n\t\t/*\n\t\t**\tThis elaborates the suggested objects to construct. When the specified object\n\t\t**\tis constructed, then this corresponding value will be reset to nill state. The\n\t\t**\texpert system decides what should be produced, and then records the\n\t\t**\trecommendation in these variables.\n\t\t*/\n\t\tStructType BuildStructure;\n\t\tUnitType BuildUnit;\n\t\tInfantryType BuildInfantry;\n\t\tAircraftType BuildAircraft;\n\t\tVesselType BuildVessel;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tHouseClass(HousesType house);\n\t\tHouseClass(NoInitClass const & x) : Class(x), Control(x), AlertTime(x), BorrowedTime(x), Attack(x), AITimer(x), DamageTime(x), TeamTime(x), TriggerTime(x), SpeakAttackDelay(x), SpeakPowerDelay(x), SpeakMoneyDelay(x), SpeakMaxedDelay(x) {};\n\t\t~HouseClass(void);\n\t\toperator HousesType(void) const;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tCELL Random_Cell_In_Zone(ZoneType zone) const;\n\t\tstatic void Computer_Paranoid(void);\n\t\tbool Is_Allowed_To_Ally(HousesType house) const;\n\t\tvoid Do_All_To_Hunt(void) const;\n\t\tvoid Super_Weapon_Handler(void);\n\t\tint * Factory_Counter(RTTIType rtti);\n\t\tint Factory_Count(RTTIType rtti) const;\n\t\tDiffType Assign_Handicap(DiffType handicap);\n\t\tTARGET Find_Juicy_Target(COORDINATE coord) const;\n\t\tvoid Print_Zone_Stats(int x, int y, ZoneType zone, MonoClass * mono) const;\n\t\tCELL Where_To_Go(FootClass const * object) const;\n\t\tCELL Zone_Cell(ZoneType zone) const;\n\t\tZoneType Which_Zone(COORDINATE coord) const;\n\t\tZoneType Which_Zone(ObjectClass const * object) const;\n\t\tZoneType Which_Zone(CELL cell) const;\n\t\tCELL Find_Cell_In_Zone(TechnoClass const * techno, ZoneType zone) const;\n\t\tProdFailType Begin_Production(RTTIType type, int id);\n\t\tProdFailType Suspend_Production(RTTIType type);\n\t\tProdFailType Abandon_Production(RTTIType type);\n\t\tbool Place_Object(RTTIType type, CELL cell);\n\t\tbool Manual_Place(BuildingClass * builder, BuildingClass * object);\n\t\tvoid Special_Weapon_AI(SpecialWeaponType id);\n\t\tbool Place_Special_Blast(SpecialWeaponType id, CELL cell);\n\t\tbool Flag_Attach(CELL cell, bool set_home = false);\n\t\tbool Flag_Attach(UnitClass * object, bool set_home = false);\n\t\tbool Flag_Remove(TARGET target, bool set_home = false);\n\t\tvoid Init_Data(PlayerColorType color, HousesType house, int credits);\n\t\tCOORDINATE Find_Build_Location(BuildingClass * building) const;\n\t\tBuildingClass * Find_Building(StructType type, ZoneType zone=ZONE_NONE) const;\n\t\tchar const * Name(void) const {return(Class->Name());}\n\n\t\t// Added so the ally flags could be sent to client machines - 09 / 12 / 2019 JAS\n\t\tunsigned Get_Ally_Flags();\n\n\t\tbool Fire_Sale(void);\n\t\tbool Is_Hack_Prevented(RTTIType rtti, int value) const;\n\t\tbool Is_No_YakMig(void) const;\n\t\tint Expert_AI(void);\n\t\tvoid Production_Begun(TechnoClass const * rtti);\n\t\tvoid Sell_Wall(CELL cell);\n\t\tbool Flag_To_Die(void);\n\t\tbool Flag_To_Win(void);\n\t\tbool Flag_To_Lose(void);\n\t\tvoid Make_Ally(HousesType house);\n\t\tvoid Make_Ally(ObjectClass * object) {if (object) Make_Ally(object->Owner());};\n\t\tvoid Make_Enemy(HousesType house);\n\t\tvoid Make_Enemy(ObjectClass * object) {if (object) Make_Enemy(object->Owner());};\n\t\tbool Is_Ally(HousesType house) const;\n\t\tbool Is_Ally(HouseClass const * house) const;\n\t\tbool Is_Ally(ObjectClass const * object) const;\n\t\tunsigned int Get_Allies(void) const {return Allies;}\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvoid AI(void);\n\t\tbool Can_Build(RTTIType rtti, int type, HousesType house) const;\n\n\t\t// Factory controls.\n\t\tFactoryClass * Fetch_Factory(RTTIType rtti) const;\n\t\tvoid Set_Factory(RTTIType rtti, FactoryClass * factory);\n\n\t\tbool Can_Build(ObjectTypeClass const * type, HousesType house) const;\n\n\t\tint  Get_Quantity(AircraftType aircraft);\n\t\tint  Get_Quantity(StructType building);\n\t\tunsigned char const * Remap_Table(bool blushing=false, RemapType remap=REMAP_NORMAL) const;\n\n\t\tTechnoTypeClass const * Suggest_New_Object(RTTIType objectype, bool kennel=false) const;\n\t\tBuildingTypeClass const * Suggest_New_Building(void) const;\n\t\tvoid Recalc_Center(void);\n\t\tbool Does_Enemy_Building_Exist(StructType) const;\n\t\tvoid Harvested(unsigned tiberium);\n\t\tvoid Stole(unsigned worth);\n\t\tlong Available_Money(void) const;\n\t\tvoid Spend_Money(unsigned money);\n\t\tvoid Refund_Money(unsigned money);\n\t\tvoid Attacked(BuildingClass* source);\n\t\tvoid Adjust_Power(int adjust);\n\t\tvoid Adjust_Drain(int adjust);\n\t\tvoid Update_Spied_Power_Plants(void);\n\t\tint Adjust_Capacity(int adjust, bool inanger=false);\n\t\tfixed Power_Fraction(void) const;\n\t\tfixed Tiberium_Fraction(void) const;\n\t\tvoid Begin_Production(void) {IsStarted = true;};\n\t\tTeamTypeClass const * Suggested_New_Team(bool alertcheck = false);\n\t\tvoid Adjust_Threat(int region, int threat);\n\t\tvoid Tracking_Remove(TechnoClass const * techno);\n\t\tvoid Tracking_Add(TechnoClass const * techno);\n\t\tvoid Active_Remove(TechnoClass const * techno);\n\t\tvoid Active_Add(TechnoClass const * techno);\n\n\t\tUrgencyType Check_Attack(void) const;\n\t\tUrgencyType Check_Build_Power(void) const;\n\t\tUrgencyType Check_Build_Defense(void) const;\n\t\tUrgencyType Check_Build_Offense(void) const;\n\t\tUrgencyType Check_Build_Income(void) const;\n\t\tUrgencyType Check_Fire_Sale(void) const;\n\t\tUrgencyType Check_Build_Engineer(void) const;\n\t\tUrgencyType Check_Raise_Money(void) const;\n\t\tUrgencyType Check_Raise_Power(void) const;\n\t\tUrgencyType Check_Lower_Power(void) const;\n\n\t\tbool AI_Attack(UrgencyType urgency);\n\t\tbool AI_Build_Power(UrgencyType urgency) const;\n\t\tbool AI_Build_Defense(UrgencyType urgency) const;\n\t\tbool AI_Build_Offense(UrgencyType urgency) const;\n\t\tbool AI_Build_Income(UrgencyType urgency) const;\n\t\tbool AI_Fire_Sale(UrgencyType urgency);\n\t\tbool AI_Build_Engineer(UrgencyType urgency) const;\n\t\tbool AI_Raise_Money(UrgencyType urgency) const;\n\t\tbool AI_Raise_Power(UrgencyType urgency) const;\n\t\tbool AI_Lower_Power(UrgencyType urgency) const;\n\n\t\tbool Can_Make_Money(void) const {\n\t\t\treturn(Available_Money() > 300 || (BScan & STRUCTF_REFINERY));\n\t\t};\n\n\t\tstatic void Init(void);\n\t\tstatic void One_Time(void);\n\t\tstatic HouseClass * As_Pointer(HousesType house);\n\t\tstatic void Recalc_Attributes(void);\n\n\t\t/*\n\t\t** New default win mode to avoid griefing. ST - 1/31/2020 3:33PM\n\t\t*/\n\t\tvoid\tCheck_Pertinent_Structures(void);\n\n\t\tvoid Init_Unit_Trackers(void);\n\t\tvoid Free_Unit_Trackers(void);\n\n\t\t// MBL 09.08.2020 Mod support stub\n\t\tvoid Handle_Mod_Game_Command(CELL cell, int mod_command_index); // mod_command_index = 0-3\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic void Read_Flag_INI(char *buffer);\n\t\tstatic void Write_Flag_INI(char *buffer);\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tSpecial house actions.\n\t\t*/\n\t\tvoid Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tThis vector holds the recorded status of the map regions. It is through\n\t\t**\tthis region information that team paths are calculated.\n\t\t*/\n\t\tRegionClass Regions[MAP_TOTAL_REGIONS];\n\n\t\t/*\n\t\t**\tThis count down timer class decrements and then changes\n\t\t** the Atomic Bomb state.\n\t\t*/\n\t\tCELL NukeDest;\n\n\t\t/*\n\t\t** Per-house credits class to track the visible credits state for each house. Redundant in the original game, but needed\n\t\t** to preserve the exact credits count behavior in the GlyphX client. ST - 10/16/2019 2:31PM\n\t\t*/\n\t\tCreditClass VisibleCredits;\n\t\t\n\t\tbool DebugUnlockBuildables;\n\n\t\t/*\n\t\t** This routine completely removes this house & all its objects from the game.\n\t\t*/\n\t\tvoid Clobber_All(void);\n\n\t\t/*\n\t\t** This routine blows up everything in this house.  Fun!\n\t\t*/\n\t\tvoid Blowup_All(void);\n\n\t\t/*\n\t\t** This routine gets called in multiplayer games when every unit, building,\n\t\t** and infantry for a house is destroyed.\n\t\t*/\n\t\tvoid MPlayer_Defeated(void);\n\n\t\t/*\n\t\t** When the game's over, this routine assigns everyone their score.\n\t\t*/\n\t\tvoid Tally_Score(void);\n\n\t\tfriend class MapEditClass;\n\n\tprivate:\n\t\tvoid Silo_Redraw_Check(long oldtib, long oldcap);\n\t\tint AI_Building(void);\n\t\tint AI_Unit(void);\n\t\tint AI_Vessel(void);\n\t\tint AI_Infantry(void);\n\t\tint AI_Aircraft(void);\n\n\t\t/*\n\t\t**\tThis is a bit field record of all the other houses that are allies with\n\t\t**\tthis house. It is presumed that any house that isn't an ally, is therefore\n\t\t**\tan enemy. A house is always considered allied with itself.\n\t\t*/\n\t\tunsigned Allies;\n\n\t\t/*\n\t\t**\tGeneral low-power related damaged is doled out whenever this timer\n\t\t**\texpires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> DamageTime;\n\n\t\t/*\n\t\t**\tTeam creation is done whenever this timer expires.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> TeamTime;\n\n\t\t/*\n\t\t**\tThis controls the rate that the trigger time logic is processed.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> TriggerTime;\n\n\t\t/*\n\t\t**\tAt various times, the computer may announce the player's condition. The following\n\t\t**\tvariables are used as countdown timers so that these announcements are paced\n\t\t**\tfar enough apart to reduce annoyance.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> SpeakAttackDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakPowerDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakMoneyDelay;\n\t\tCDTimerClass<FrameTimerClass> SpeakMaxedDelay;\n\n\t\t/*\n\t\t**\tThis structure is used to record a build request as determined by\n\t\t**\tthe house AI processing. Higher priority build requests take precidence.\n\t\t*/\n\t\tstruct BuildChoiceClass {\n\t\t\tstatic void * operator new(size_t, void * ptr) {return(ptr);};\n\t\t\tUrgencyType\tUrgency;\t\t\t// The urgency of the build request.\n\t\t\tStructType\tStructure;\t\t// The type of building to produce.\n\n\t\t\tBuildChoiceClass(UrgencyType u, StructType s) : Urgency(u), Structure(s) {};\n\t\t\tBuildChoiceClass(NoInitClass const & ) {};\n\t\t\tint Save(Pipe &) const {return(true);};\n\t\t\tint Load(Straw &) {return(true);};\n\t\t\tvoid Code_Pointers(void) {};\n\t\t\tvoid Decode_Pointers(void) {};\n\t\t};\n\n\t\tstatic TFixedIHeapClass<BuildChoiceClass> BuildChoice;\n\n\n\t/*\n\t** These values are for multiplay only.\n\t*/\n\tpublic:\n\t\t/*\n\t\t** For multiplayer games, each house instance has a remap table; the table\n\t\t** in the HousesTypeClass isn't used.  This variable is set to the remap\n\t\t** table for the color the player wants to play.\n\t\t*/\n\t\tPlayerColorType RemapColor;\n\n\t\t/*\n\t\t** This is the name (\"handle\") the player has chosen for himself.\n\t\t*/\n\t\tchar IniName[HOUSE_NAME_MAX];\n\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tFor Internet games only, unchanging name of player when game began.\n\t\t//\tThis name does not get changed to \"Computer\" if computer takes over for player.\n\t\tchar InitialName[HOUSE_NAME_MAX];\n#endif\n\n\t\tint QuantityB(int index) {return(BQuantity[index]);}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tint QuantityU(int index) {\n\t\t\tif(index >= UNIT_RA_COUNT) index -= UNIT_RA_COUNT;\n\t\t\treturn(UQuantity[index]);\n\t\t}\n\t\tint QuantityI(int index) {\n\t\t\tif(index >= INFANTRY_RA_COUNT) index -= INFANTRY_RA_COUNT;\n\t\t\treturn(IQuantity[index]);\n\t\t}\n\t\tint QuantityA(int index) {return(AQuantity[index]);}\n\t\tint QuantityV(int index) {\n\t\t\tif(index >= VESSEL_RA_COUNT) index -= VESSEL_RA_COUNT;\n\t\t\treturn(VQuantity[index]);\n\t\t}\n#else\n\t\tint QuantityU(int index) {return(UQuantity[index]);}\n\t\tint QuantityI(int index) {return(IQuantity[index]);}\n\t\tint QuantityA(int index) {return(AQuantity[index]);}\n\t\tint QuantityV(int index) {return(VQuantity[index]);}\n#endif\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[256];\n\n};\n\n#endif"
  },
  {
    "path": "REDALERT/HSV.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HSV.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HSV.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : February 20, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   HSVClass::Adjust -- Adjust an HSV color toward specified color.                           *\n *   HSVClass::Difference -- Finds the difference between two HSV color objects.               *\n *   HSVClass::Set -- Set the palette for this color object.                                   *\n *   HSVClass::operator RGBClass -- Conversion operator for RGBClass object.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"watcom.h\"\n#include\t\"hsv.h\"\n#include\t\"rgb.h\"\n\nHSVClass const HSVClass::BlackColor(0, 0, 0);\n\n\n/***********************************************************************************************\n * HSVClass::Adjust -- Adjust an HSV color toward specified color.                             *\n *                                                                                             *\n *    This routine will adjust the HSV color object toward the color of the specified HSV      *\n *    object. Typical users of this would be palette morphing or fading routines.              *\n *                                                                                             *\n * INPUT:   ratio    -- The ratio to move the HSV object toward the color specified. A value   *\n *                      of zero means no movement at all. A value of 255 means move completely *\n *                      toward the specified color (changed completely).                       *\n *                                                                                             *\n *          hsv      -- A reference to the color that the current HSV object is to change      *\n *                      toward.                                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HSVClass::Adjust(int ratio, HSVClass const & hsv)\n{\n\t/*\n\t**\tRatio conversion is limited to 0 through 100%. This is\n\t**\tthe range of 0 to 255.\n\t*/\n\tratio &= 0x00FF;\n\n\t/*\n\t**\tAdjust the color guns by the ratio specified toward the\n\t**\tdestination color.\n\t*/\n\tint value = hsv.Value_Component() - Value_Component();\n\tValue = Value_Component() + (value * ratio) / 256;\n\n\tint saturation = hsv.Saturation_Component() - Saturation_Component();\n\tSaturation = Saturation_Component() + (saturation * ratio) / 256;\n\n\tint hue = hsv.Hue_Component() - Hue_Component();\n\tHue = Hue_Component() + (hue * ratio) / 256;\n}\n\n\n/***********************************************************************************************\n * HSVClass::Difference -- Finds the difference between two HSV color objects.                 *\n *                                                                                             *\n *    This routine will determine a color difference between two HSV objects. The difference   *\n *    has no particular meaning other that larger numbers meaning greater difference.          *\n *                                                                                             *\n * INPUT:   hsv   -- The other HSV object to compare this HSV object to.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a relative distance (in arbitrary units) between this HSV object and  *\n *          the HSV object supplied.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint HSVClass::Difference(HSVClass const & hsv) const\n{\n\tint hue = (int)Hue - (int)hsv.Hue;\n\tif (hue < 0) hue = -hue;\n\n\tint saturation = (int)Saturation - (int)hsv.Saturation;\n\tif (saturation < 0) saturation = -saturation;\n\n\tint value = (int)Value - (int)hsv.Value;\n\tif (value < 0) value = -value;\n\n\treturn(hue*hue + saturation*saturation + value*value);\n}\n\n\n/***********************************************************************************************\n * HSVClass::operator RGBClass -- Conversion operator for RGBClass object.                     *\n *                                                                                             *\n *    This conversion operator will convert the HSV object into an RGB object.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference (implied) of the RGBClass object that most closely        *\n *          matches this HSVClass object.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nHSVClass::operator RGBClass (void) const\n{\n\tunsigned int i;\t\t\t\t// Integer part.\n\tunsigned int f;\t\t\t\t// Fractional or remainder part.  f/HSV_BASE gives fraction.\n\tunsigned int tmp;\t\t\t// Temporary variable to help with calculations.\n\tunsigned int values[7];\t// Possible rgb values.  Don't use zero.\n\n\tint hue = Hue_Component();\n\tint saturation = Saturation_Component();\n\tint value = Value_Component();\n\tint red, green, blue;\n\n\n\thue *= 6;\n\tf = hue % 255;\n\n\t// Set up possible red, green and blue values.\n\tvalues[1] =\n\tvalues[2] = value;\n\n\t//\n\t// The following lines of code change\n\t//\tvalues[3] = (v * (255 - ( (s * f) / 255) )) / 255;\n\t//\tvalues[4] = values[5] = (v * (255 - s)) / 255;\n\t// values[6] = (v * (255 - (s * (255 - f)) / 255)) / 255;\n\t// so that the are rounded divides.\n\t//\n\n\ttmp = (saturation * f) / 255;\n\tvalues[3] = (value * (255 - tmp)) / 255;\n\n\tvalues[4] =\n\tvalues[5] = (value * (255 - saturation)) / 255;\n\n\ttmp = 255 - (saturation * (255 - f)) / 255;\n\tvalues[6] = (value * tmp) / 255;\n\n\n\t// This should not be rounded.\n\ti = hue / 255;\n\n\ti += (i > 4) ? -4 : 2;\n\tred = values[i];\n\n\ti += (i > 4) ? -4 : 2;\n\tblue = values[i];\n\n\ti += (i > 4) ? -4 : 2;\n\tgreen = values[i];\n\n\treturn(RGBClass(red, green, blue));\n}\n\n\n/***********************************************************************************************\n * HSVClass::Set -- Set the palette for this color object.                                     *\n *                                                                                             *\n *    The palette will be set for this color object. Use this routine to set an arbitrary      *\n *    color index with the HSVClass object.                                                    *\n *                                                                                             *\n * INPUT:   color -- The color index to change.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid HSVClass::Set(int color) const\n{\n\tRGBClass rgb = *this;\n\trgb.Set(color);\n}\n"
  },
  {
    "path": "REDALERT/HSV.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/HSV.H 1     3/03/97 10:24a Joe_bostic $ */\n/*********************************************************************************************** \n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : HSV.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : December 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef HSV_H\n#define HSV_H\n\nclass RGBClass;\nclass HSVClass;\n\n/*\n**\tEach color entry is represented by this class. It holds the values for the color\n**\tattributes. The values are recorded in a range from 0 to 255 with 255 being the\n**\tmaximum.\n*/\nclass HSVClass\n{\n\tprivate:\n\t\tstatic HSVClass const BlackColor;\n\n\tpublic:\n\t\tHSVClass(void) : Hue(0), Saturation(0), Value(0) {};\n\t\tHSVClass(unsigned char hue, unsigned char saturation, unsigned char value) :\n\t\t\t\tHue(hue),\n\t\t\t\tSaturation(saturation),\n\t\t\t\tValue(value)\n\t\t\t{};\n\t\toperator RGBClass (void) const;\n\n\t\tenum {\n\t\t\tMAX_VALUE=255\n\t\t};\n\n\t\tvoid Adjust(int ratio, HSVClass const & hsv);\n\t\tint Difference(HSVClass const & hsv) const;\n\t\tint Hue_Component(void) const {return(Hue);};\n\t\tint Saturation_Component(void) const {return(Saturation);};\n\t\tint Value_Component(void) const {return(Value);};\n\t\tvoid Set(int color) const;\n\n\tprivate:\n\t\tunsigned char Hue;\n\t\tunsigned char Saturation;\n\t\tunsigned char Value;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/ICONLIST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tIconlist.cpp - created by ajw 07/07/98\n\n//\tIconListClass is ListClass plus the option to include an icon on each line entry,\n//\tthe option to have the class maintain its own copies of strings passed to it\n//\tfor display, and the option to limit the maximum number of these strings that are\n//\tkept (entries are removed from the top when this maximum is reached).\n//\tAlso added: multiple item selection capability. Note that the old selection code\n//\truns as normal, but it simply not used when it comes time to display.\n//\tAlso added: if mem. allocation is being done by this, the ability to break new items\n//\tinto multiple lines of text is enabled.\n//\tAlso added: extra data can be invisibly stored with each item, if memory allocation is\n//\tbeing done by this.\n//\tExtra data included 3 item preceding icons, 1 fixed position icon, an extra string,\n//\tan extra void pointer, and a color remapping value.\n\n#include \"iconlist.h\"\n#include \"dibapi.h\"\n\nint Format_Window_String_New( const char* string, int maxlinelen, int& width, int& height, char* szReturn, int iExtraChars );\nvoid CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window );\n\n//***********************************************************************************************\nIconListClass::IconListClass( int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down, \n\t\t\t\t\t\t\t\tbool bResponsibleForStringAlloc, int iSelectionType, int iMaxItemsSaved ) :\n\tListClass( id, x, y, w, h, flags, up, down )\n{\n\t//\tIf bResponsibleForStringAlloc, COPIES of strings are stored in the list. Deletion is\n\t//\thandled by this class. Icons are different - the caller is responsible for what's on\n\t//\tthe other end of the pointer.\n\tbDoAlloc = bResponsibleForStringAlloc;\n\t//\tiSelectionType = 0 for no selection shown, 1 for normal ListClass selection, 2 for n multiple selections\n\tif( iSelectionType < 0 || iSelectionType > 2 )\t\tiSelectionType = 1;\n\tiSelectType = iSelectionType;\n\t//\tIf iMaxItemsSaved is 0, there is no limit to the number of text lines. The list can grow forever.\n\t//\tOtherwise items are deleted from the head of the list when the maximum is passed.\n\t//\tiMaxItemsSaved only applies when bResponsibleForStringAlloc.\n\tiMaxItems = iMaxItemsSaved;\n}\n\n//***********************************************************************************************\nIconListClass::~IconListClass( void )\n{\n\t//\tDelete the IconList_ItemExtras structs created to hold extra info on each item.\n\tfor( int i = 0; i < ExtrasList.Count(); i++ )\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ i ];\n\n\tif( bDoAlloc )\n\t{\n\t\t//\tDelete all alloc'ed strings.\n\t\tfor( int i = 0; i < List.Count(); i++ )\n\t\t\tdelete [] (char*)List[i];\n\t}\n}\n\n/***********************************************************************************************\n * IconListClass::Add_Item -- Adds an item to the list box.                                        *\n *                                                                                             *\n *    This will add the specified string to the list box. The string is added to the end       *\n *    of the list.                                                                             *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to add to the list box.                          *\n *             pIcon -- Pointer to the shape to add.\n *             IconKind -- Indicates what type of image pIcon points to.\n *             szExtraDataString -- Extra string data that gets copied and stored along with item.\n *             szExtraDataPtr -- Extra data that gets stored along with item.\n *             pColorRemap -- Points to a color remapping used when drawing the item.\n *\n * OUTPUT:     Returns new item index.                                                         *\n * WARNINGS:   none                                                                            *\n * HISTORY:    07/07/1998 ajw : Created.                                                       *\n *=============================================================================================*/\nint IconListClass::Add_Item(char const * text)\n{\n\treturn Add_Item( text, NULL, NULL, ICON_SHAPE );\n}\n\nint IconListClass::Add_Item( const char* text, const char* szHelp, \n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString /* = NULL */, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr /* = NULL */, RemapControlType* pColorRemap /* = NULL */,\n\t\t\t\t\t\t\t\tvoid* pIcon1 /* = NULL */, ICONKIND IconKind1 /* = ICON_SHAPE */, \n\t\t\t\t\t\t\t\tvoid* pIcon2 /* = NULL */, ICONKIND IconKind2 /* = ICON_SHAPE */,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon /* = NULL */, ICONKIND FixedIconKind /* = ICON_SHAPE */, int iXFixedIcon /* = 0 */, int iYFixedIcon /* = 0 */, int iFixedIconWidth /* = -1 */ )\n{\n\tif( text )\n\t{\n\t\tif( bDoAlloc )\n\t\t{\n\t\t\tint iRetVal;\n\n\t\t\tchar* szText = new char[ strlen( text ) + 51 ];\t\t\t//\t50 extra chars added for line breaks later.\n\t\t\tstrcpy( szText, text );\n\n\t\t\tint iWidthMax, iHeight;\n\t\t\t//\tStupid usage of globals for font stuff... <grumble>\n\t\t\tif( TextFlags == TPF_TYPE )\n\t\t\t{\n\t\t\t\tvoid* pFontBefore = Set_Font( TypeFontPtr );\n\t\t\t\tDWORD FontXSpacingBefore = FontXSpacing;\n\t\t\t\tFontXSpacing = -2;\n\n\t\t\t\tint iWidthToClipAt = IsScrollActive ? Width : Width - UpGadget.Width;\n\t\t\t\t//\tThis call will place '\\r's in the string where line breaks should occur.\n\t\t\t\tFormat_Window_String_New( text, iWidthToClipAt, iWidthMax, iHeight, szText, 50 );\n\n\t\t\t\tSet_Font( pFontBefore );\n\t\t\t\tFontXSpacing = FontXSpacingBefore;\t\t//\tJust in case it matters... Doubt it.\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tCurrently never called. Test well if you use IconList with a font other than TPF_TYPE,\n\t\t\t\t//\tas the character spacing globals get set weirdly, I've found.\n\t\t\t\tint iWidthToClipAt = IsScrollActive ? Width : Width - UpGadget.Width;\n\t\t\t\t//\tThis call will place '\\r's in the string where line breaks should occur.\n\t\t\t\tFormat_Window_String_New( text, iWidthToClipAt, iWidthMax, iHeight, szText, 50 );\n\t\t\t}\n\n\t\t\t//\tEach break character causes a line to be added to list.\n\t\t\tchar szBreakchars[] = \"\\r\\n\\v\\f\";\n\t\t\tchar* szToken;\n\t\t\tchar* szNextChar = szText;\n\t\t\tszToken = strtok( szText, szBreakchars );\n\t\t\twhile( szToken )\n\t\t\t{\n\t\t\t\twhile( szNextChar < szToken )\n\t\t\t\t{\n\t\t\t\t\t//\tWe expected szToken to begin at szNextChar. Since it doesn't, extra break\n\t\t\t\t\t//\tcharacters must have been removed by strtok as they were adjacent. We want \n\t\t\t\t\t//\ta line break for every break character, so add lines for each space that\n\t\t\t\t\t//\tszNextChar is off by.\n\t\t\t\t\tszNextChar++;\n\t\t\t\t\tAdd_Item_Detail( \" \", szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, pIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n\t\t\t\t}\n\t\t\t\tiRetVal = Add_Item_Detail( szToken, szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, pIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n\n\t\t\t\t//\tExpect next token two chars after the end of this one.\n\t\t\t\tszNextChar = szToken + strlen( szToken ) + 1;\n\n\t\t\t\t//\tGet next token.\n\t\t\t\tszToken = strtok( NULL, szBreakchars );\n\t\t\t}\n\t\t\tdelete [] szText;\n\t\t\treturn iRetVal;\t\t\t\t//\tLast value returned by ListClass::Add_Item\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tAdd one item to list.\n\t\t\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\t\t\tpItemExtra->bMultiSelected = false;\n\t\t\tpItemExtra->pIcon[0] = pIcon0;\n\t\t\tpItemExtra->IconKind[0] = IconKind0;\n\t\t\tpItemExtra->pIcon[1] = pIcon1;\n\t\t\tpItemExtra->IconKind[1] = IconKind1;\n\t\t\tpItemExtra->pIcon[2] = pIcon2;\n\t\t\tpItemExtra->IconKind[2] = IconKind2;\n\t\t\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\t\t\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\t\t\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\t\t\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\t\t\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\t\t\tpItemExtra->pvExtraData = pvExtraDataPtr;\n\t\t\tpItemExtra->pColorRemap = pColorRemap;\n\t\t\tif( szHelp )\n\t\t\t{\n\t\t\t\t//\tCopy help into new help string.\n\t\t\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\t\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t\t\t}\n\t\t\tif( szExtraDataString )\n\t\t\t{\n\t\t\t\t//\tCopy special data string into new extradata string.\n\t\t\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\t\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t\t\t}\n\t\t\tExtrasList.Add( pItemExtra );\n\n\t\t\treturn ListClass::Add_Item( text );\n\t\t}\n\t}\n\telse\n\t{\n\t\t//\t(no text for new item)\n\t\tif( pIcon0 || pIcon1 || pIcon2 )\n\t\t{\n\t\t\t//\tNote: Cannot add an entry without text unless string allocation is being handled by me.\n\t\t\t//\tOtherwise, because we want the icon to show up, create a blank entry for the ListClass.\n\t\t\tif( bDoAlloc )\n\t\t\t{\n\t\t\t\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\t\t\t\tpItemExtra->bMultiSelected = false;\n\t\t\t\tpItemExtra->pIcon[0] = pIcon0;\n\t\t\t\tpItemExtra->IconKind[0] = IconKind0;\n\t\t\t\tpItemExtra->pIcon[1] = pIcon1;\n\t\t\t\tpItemExtra->IconKind[1] = IconKind1;\n\t\t\t\tpItemExtra->pIcon[2] = pIcon2;\n\t\t\t\tpItemExtra->IconKind[2] = IconKind2;\n\t\t\t\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\t\t\t\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\t\t\t\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\t\t\t\tpItemExtra->pvExtraData = pvExtraDataPtr;\n\t\t\t\tpItemExtra->pColorRemap = pColorRemap;\n\t\t\t\tif( szHelp )\n\t\t\t\t{\n\t\t\t\t\t//\tCopy help into new help string.\n\t\t\t\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\t\t\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t\t\t\t}\n\t\t\t\tif( szExtraDataString )\n\t\t\t\t{\n\t\t\t\t\t//\tCopy special data string into new extradata string.\n\t\t\t\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\t\t\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t\t\t\t}\n\t\t\t\tExtrasList.Add( pItemExtra );\n\n\t\t\t\tif( iMaxItems && List.Count() == iMaxItems )\n\t\t\t\t{\n\t\t\t\t\t//\tDelete head of list.\n\t\t\t\t\tRemove_Item( 0 );\n\t\t\t\t}\n\t\t\t\t//\tCreate new string, essentially blank.\n\t\t\t\tchar* szText = new char[2];\n\t\t\t\tstrcpy( szText, \" \" );\n\t\t\t\treturn ListClass::Add_Item( szText );\n\t\t\t}\n\t\t\telse\n\t\t\t\t//\tCannot add entry, as text is blank and ListClass::Add_Item will do nothing.\n\t\t\t\t//\tThe Icon we want will not show up.\n\t\t\t\treturn List.Count() - 1;\n\t\t}\n\t\telse\n\t\t\treturn ListClass::Add_Item( text );\n\t}\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item_Detail( const char* szToken, const char* szHelp,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString, \n\t\t\t\t\t\t\t\t\t\tvoid* pvExtraData, RemapControlType* pColorRemap,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon1, ICONKIND IconKind1, \n\t\t\t\t\t\t\t\t\t\tvoid* pIcon2, ICONKIND IconKind2,\n\t\t\t\t\t\t\t\t\t\tvoid* pFixedIcon, ICONKIND FixedIconKind, int iXFixedIcon, int iYFixedIcon, int iFixedIconWidth )\n{\n\t//\tBroken out of above function as it is repeated.\n\n\t//\tAdd one item to list.\n\t//\tToo many entries?\n\tif( iMaxItems && List.Count() == iMaxItems )\n\t{\n\t\t//\tDelete head of list.\n\t\tRemove_Item( 0 );\n\t}\n\t//\tCreate icon entry.\n\tIconList_ItemExtras* pItemExtra = new IconList_ItemExtras;\n\tpItemExtra->bMultiSelected = false;\n\tpItemExtra->pIcon[0] = pIcon0;\t\t\t\t//\tajw - Question: repeat the icon for each entry? make it optional?\n\tpItemExtra->IconKind[0] = IconKind0;\n\tpItemExtra->pIcon[1] = pIcon1;\n\tpItemExtra->IconKind[1] = IconKind1;\n\tpItemExtra->pIcon[2] = pIcon2;\n\tpItemExtra->IconKind[2] = IconKind2;\n\tpItemExtra->FixedIcon.pIcon = pFixedIcon;\n\tpItemExtra->FixedIcon.IconKind = FixedIconKind;\n\tpItemExtra->FixedIcon.xOffset = iXFixedIcon;\n\tpItemExtra->FixedIcon.yOffset = iYFixedIcon;\n\tpItemExtra->FixedIcon.iWidth = iFixedIconWidth;\n\tpItemExtra->pvExtraData = pvExtraData;\n\tpItemExtra->pColorRemap = pColorRemap;\n\tif( szHelp )\n\t{\n\t\t//\tCopy help into new help string.\n\t\tpItemExtra->szHelp = new char[ strlen( szHelp ) + 1 ];\n\t\tstrcpy( pItemExtra->szHelp, szHelp );\n\t}\n\tif( szExtraDataString )\n\t{\n\t\t//\tCopy special data string into new extradata string.\n\t\tpItemExtra->szExtraData = new char[ strlen( szExtraDataString ) + 1 ];\n\t\tstrcpy( pItemExtra->szExtraData, szExtraDataString );\n\t}\n\tExtrasList.Add( pItemExtra );\n\t//\tCreate text entry.\n\t//\tCopy text to new string.\n\tchar* szTextBit = new char[ strlen( szToken ) + 1 ];\n\tstrcpy( szTextBit, szToken );\n\treturn ListClass::Add_Item( szTextBit );\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item( int text )\n{\n\treturn Add_Item( Text_String(text), NULL, NULL, ICON_SHAPE );\n}\n\n//***********************************************************************************************\nint IconListClass::Add_Item( int text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString /* = NULL */, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr /* = NULL */, RemapControlType* pColorRemap /* = NULL */,\n\t\t\t\t\t\t\t\tvoid* pIcon1 /* = NULL */, ICONKIND IconKind1 /* = ICON_SHAPE */, \n\t\t\t\t\t\t\t\tvoid* pIcon2 /* = NULL */, ICONKIND IconKind2 /* = ICON_SHAPE */,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon /* = NULL */, ICONKIND FixedIconKind /* = ICON_SHAPE */, int iXFixedIcon /* = 0 */, int iYFixedIcon /* = 0 */, int iFixedIconWidth /* = -1 */ )\n{\n\treturn Add_Item( Text_String(text), szHelp, pIcon0, IconKind0, szExtraDataString, pvExtraDataPtr, pColorRemap, \n\t\t\t\t\t\tpIcon1, IconKind1, pIcon2, IconKind2, pFixedIcon, FixedIconKind, iXFixedIcon, iYFixedIcon, iFixedIconWidth );\n}\n\n//***********************************************************************************************\nvoid IconListClass::Remove_Item( char const * text )\n{\n\tif( text )\n\t\tRemove_Item( List.ID(text) );\n}\n\n//***********************************************************************************************\nvoid IconListClass::Remove_Item( int index )\n{\n\tif( (unsigned)index < List.Count() )\n\t{\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ index ];\n\t\tExtrasList.Delete( index );\n\t\tif( bDoAlloc )\n\t\t\t//\tDelete alloc'ed string.\n\t\t\tdelete [] (char*)List[index];\n\t\tListClass::Remove_Item( index );\n\t\t\n\t\t//\tI should probably put this in ListClass:Remove_Item(), as it seems clearly to be\n\t\t//\tmissing, but I want to only affect my own new code, to not introduce possible bugs.\n\t\t//\tShift the selected index if appropriate...\n\t\tif( SelectedIndex >= index )\n\t\t{\n\t\t\tSelectedIndex--;\n\t\t\tif( SelectedIndex < 0 )\n\t\t\t\tSelectedIndex = 0;\n\t\t}\n\t}\n}\n\n/***********************************************************************************************\n * IconListClass::Draw_Entry -- Calls ListClass::Draw_Entry, then adds icon.                   *\n *                                                                                             *\n *    This routine is called by the Draw_Me function when it desired to redraw a particular    *\n *    text line in the list box.                                                               *\n *                                                                                             *\n * INPUT:   index    -- The index of the list entry to draw. This index is based on the        *\n *                      total list and NOT the current visible view page.                      *\n *                                                                                             *\n *          x,y      -- Pixel coordinates for the upper left corner of the text entry.         *\n *                                                                                             *\n *          width    -- The maximum width that the text may draw over. It is expected that     *\n *                      this drawing routine entirely fills this length.                       *\n *                                                                                             *\n *          selected -- bool; Is this a selected (highlighted) listbox entry?                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   07/07/1998  ajw: Created.                                                                 *\n *=============================================================================================*/\n\n#define PREICONGAP\t\t1\n#define ICONTEXTGAP\t\t2\n\nvoid IconListClass::Draw_Entry( int index, int x, int y, int width, int selected )\n{\n\tIconList_ItemExtras* pExtras = (IconList_ItemExtras*)ExtrasList[ index ];\n\n\tint xText = x;\n\t//\tajw If I end up needing to use SHAPEs for icons, figure out shape width here and offset x.\n\tbool bIconsPresent = false;\n\tfor( int iIcon = 0; iIcon != 3; iIcon++ )\n\t\tif( pExtras->pIcon[ iIcon ] && pExtras->IconKind[ iIcon ] == ICON_DIB )\n\t\t{\n\t\t\t//\tPush text over to accommodate icon.\n\t\t\tint iWidthIcon = PREICONGAP + DIBWidth( (char*)pExtras->pIcon[ iIcon ] );\n\t\t\txText += iWidthIcon;\n\t\t\twidth -= iWidthIcon;\n\t\t\tbIconsPresent = true;\n\t\t}\n\tif( bIconsPresent )\n\t{\n\t\txText += ICONTEXTGAP;\n\t\twidth -= ICONTEXTGAP;\n\t}\n\n\tRemapControlType* pRemap = pExtras->pColorRemap;\n\tif( !pRemap )\n\t{\n\t\t//\tTabs hack. If there are icons, and a tab, push back the FIRST tab appropriately.\n\t\t//\t(Ignore others. This is a hack because having more than one tab will now break this.)\n\t\t//\tSee local version of this same hack, below.\n\t\tint TempTabs;\n\t\tconst int* TabsSave;\n\t\tif( Tabs )\n\t\t{\n\t\t\tTempTabs = *Tabs - ( xText - x );\n\t\t\tTabsSave = Tabs;\n\t\t\tTabs = &TempTabs;\n\t\t}\n\t\tswitch( iSelectType )\n\t\t{\n\t\tcase 0:\n\t\t\t//\tDon't draw any items selected (even if they are, really, in ListClass).\n\t\t\tListClass::Draw_Entry( index, xText, y, width, false );\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tListClass::Draw_Entry( index, xText, y, width, selected );\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t//\tIgnore 'selected' parameter. We use our own records.\n\t\t\tListClass::Draw_Entry( index, xText, y, width, pExtras->bMultiSelected );\n\t\t\tbreak;\n\t\t}\n\t\t//\tRestore Tabs.\n\t\tif( Tabs )\n\t\t\tTabs = TabsSave;\n\t}\n\telse\n\t{\n\t\t//\tUse different color remapping.\n\t\t//\tThis is largely copied straight from ListClass::Draw_Entry()...\n\n\t\tTextPrintType flags = TextFlags;\n\n\t\tbool bShowSelected;\n\n\t\tswitch( iSelectType )\n\t\t{\n\t\tcase 0:\n\t\t\tbShowSelected = false;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tbShowSelected = selected;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tbShowSelected = pExtras->bMultiSelected;\n\t\t\tbreak;\n\t\t}\n\n\t\tif( bShowSelected )\n\t\t{\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect( xText, y, xText + width - 1, y + LineHeight - 1, pRemap->Shadow );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL))\n\t\t\t{\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\t\t//\tTabs hack. If there are icons, and a tab, push back the FIRST tab appropriately.\n\t\t//\t(Ignore others. This is a hack because having more than one tab will now break this.)\n\t\tif( Tabs )\n\t\t{\n\t\t\tint tab = *Tabs - ( xText - x );\n\t\t\tConquer_Clip_Text_Print( List[index], xText, y, pRemap, TBLACK, flags, width, &tab );\n\t\t}\n\t\telse\n\t\t\tConquer_Clip_Text_Print( List[index], xText, y, pRemap, TBLACK, flags, width, NULL );\n\t}\n\n\t//\tDraw fixed position icon.\n\tif( pExtras->FixedIcon.pIcon )\n\t{\n\t\tif( pExtras->FixedIcon.IconKind == ICON_SHAPE )\n\t\t\tCC_Draw_Shape( pExtras->FixedIcon.pIcon, 0, x + pExtras->FixedIcon.xOffset, y + pExtras->FixedIcon.yOffset, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\t//\tPut similar code in here for shapes if used...\n\t\telse\n\t\t\tCC_Draw_DIB( (char*)pExtras->FixedIcon.pIcon, x + pExtras->FixedIcon.xOffset, y + pExtras->FixedIcon.yOffset, pExtras->FixedIcon.iWidth, WINDOW_MAIN );\n\t}\n\n\t//\tDraw variable position left-of-text icons.\n\tfor( iIcon = 0; iIcon != 3; iIcon++ )\n\t{\n\t\tif( pExtras->pIcon[ iIcon ] )\n\t\t{\n\t\t\tx += PREICONGAP;\n\t\t\tif( pExtras->IconKind[ iIcon ] == ICON_SHAPE )\n\t\t\t\tCC_Draw_Shape( pExtras->pIcon[ iIcon ], 0, x, y, WINDOW_MAIN, SHAPE_NORMAL );\n\t\t\t\t//\tPut similar code in here for shapes if used...\n\t\t\telse\n\t\t\t{\n\t\t\t\tCC_Draw_DIB( (char*)pExtras->pIcon[ iIcon ], x, y, 9999, WINDOW_MAIN );\n\t\t\t\tx += DIBWidth( (char*)pExtras->pIcon[ iIcon ] );\n\t\t\t}\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nint IconListClass::Action(unsigned flags, KeyNumType & key)\n{\n\t//\tOverriding of function is for the sake of MultiSelecting only.\n\tif( iSelectType == 2 )\n\t{\n\t\tif( !( flags & LEFTRELEASE ) )\n\t\t{\n\t\t\tif( !( flags & KEYBOARD ) )\n\t\t\t{\n\t\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\t\tindex = index / LineHeight;\n\t\t\t\tint iSelected = CurrentTopIndex + index;\n\t\t\t\tiSelected = min( iSelected, List.Count() - 1 );\n\t\t\t\tif( iSelected >= 0 )\n\t\t\t\t\t((IconList_ItemExtras*)ExtrasList[ iSelected ])->bMultiSelected = \n\t\t\t\t\t\t!((IconList_ItemExtras*)ExtrasList[ iSelected ])->bMultiSelected;\n\t\t\t}\n\t\t}\n\t}\n\treturn ListClass::Action( flags, key );\n}\n\n//***********************************************************************************************\n// * IconListClass::Show_Last_Item -- Scrolls listbox down to ensure that last entry is visible.\n//\tajw 07/09/98\nvoid IconListClass::Show_Last_Item()\n{\n\tint iItemLast = List.Count() - 1;\n\tif( iItemLast - LineCount + 1 != CurrentTopIndex )\n\t{\n\t\tFlag_To_Redraw();\n\t\tSet_View_Index( iItemLast - LineCount + 1 );\n\t}\n}\n\n//***********************************************************************************************\nbool IconListClass::bItemIsMultiSelected( int index ) const\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->bMultiSelected;\n\telse\n\t\treturn false;\n}\n\n//***********************************************************************************************\nvoid IconListClass::MultiSelect( int index, bool bSelect )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->bMultiSelected = bSelect;\n}\n\n//***********************************************************************************************\nconst char* IconListClass::Get_Item_ExtraDataString( int index ) const\n{\n\t//\tReturns const pointer to the hidden \"extra data\" string that can be associated with each item.\n\t//\tThis is NULL if no extra data was assigned.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t{\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->szExtraData;\n\t}\n\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_ExtraDataString( int index, const char* szNewString )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t{\n\t\tIconList_ItemExtras* pItemExtra = (IconList_ItemExtras*)ExtrasList[ index ];\n\t\tif( pItemExtra->szExtraData )\n\t\t{\n\t\t\t//\tDelete the existing string.\n\t\t\tdelete [] pItemExtra->szExtraData;\n\t\t}\n\t\tif( szNewString )\n\t\t{\n\t\t\t//\tCopy special data string into new extradata string.\n\t\t\tpItemExtra->szExtraData = new char[ strlen( szNewString ) + 1 ];\n\t\t\tstrcpy( pItemExtra->szExtraData, szNewString );\n\t\t}\n\t\telse\n\t\t\tpItemExtra->szExtraData = NULL;\n\t}\n}\n\t\t\t\t\n//***********************************************************************************************\nvoid* IconListClass::Get_Item_ExtraDataPtr( int index ) const\n{\n\t//\tReturns the hidden \"extra data\" void pointer that can be associated with each item.\n\t//\tThis is NULL if no value was assigned.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->pvExtraData;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_ExtraDataPtr( int index, void* pNewValue )\n{\n\t//\tSets the hidden \"extra data\" void pointer that can be associated with each item.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pvExtraData = pNewValue;\n}\n\n//***********************************************************************************************\nconst IconList_ItemExtras* IconListClass::Get_ItemExtras( int index ) const\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn (IconList_ItemExtras*)ExtrasList[ index ];\n\telse\n\t\treturn NULL;\n}\n\t\t\n//***********************************************************************************************\nconst char* IconListClass::Get_Item_Help( int index ) const\n{\n\t//\tReturns pointer to the string allocated for tooltip help.\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->szHelp;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Clear()\n{\n\t//\tRemoves all items from list.\n\n\t//\tDelete the IconList_ItemExtras structs created to hold extra info on each item.\n\tfor( int i = 0; i < ExtrasList.Count(); i++ )\n\t\tdelete (IconList_ItemExtras*)ExtrasList[ i ];\n\tExtrasList.Clear();\n\n\tif( bDoAlloc )\n\t{\n\t\t//\tDelete all alloc'ed strings.\n\t\tfor( int i = 0; i < List.Count(); i++ )\n\t\t\tdelete [] (char*)List[i];\n\t}\n\n\tList.Clear();\n\tRemove_Scroll_Bar();\n\tCurrentTopIndex = 0;\n}\n\n//***********************************************************************************************\nRemapControlType* IconListClass::Get_Item_Color( int index )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\treturn ( (IconList_ItemExtras*)ExtrasList[ index ] )->pColorRemap;\n\telse\n\t\treturn NULL;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Set_Item_Color( int index, RemapControlType* pColorRemap )\n{\n\tif( index < ExtrasList.Count() && index > -1 )\n\t\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pColorRemap = pColorRemap;\n}\n\n//***********************************************************************************************\nint IconListClass::Find( const char* szItemToFind )\n{\n\t//\tReturns -1 if szItemToFind is not found as the text BEGINNING one of the list entries, else index of item.\n\t//\tCompare is case-sensitive.\n\tfor( int i = 0; i < List.Count(); i++ )\n\t{\n\t\tif( strncmp( List[ i ], szItemToFind, strlen( szItemToFind ) ) == 0 )\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\n//***********************************************************************************************\nint IconListClass::FindColor( RemapControlType* pColorRemap )\n{\n\t//\tReturns -1 if no items of specified color are found, else first index. Assumes colorptr == colorptr is a valid equality test.\n\tfor( int i = 0; i < List.Count(); i++ )\n\t{\n\t\tif( Get_Item_Color( i ) == pColorRemap )\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\n//***********************************************************************************************\nbool IconListClass::Set_Item( unsigned int index, const char* szText )\n{\n\t//\tResets the text string allocated for an item.\n\tif( !bDoAlloc || index >= List.Count() )\n\t\treturn false;\n\n\t//\tDelete alloc'ed string.\n\tdelete [] (char*)List[ index ];\n\n\t//\tCopy text to new string.\n\tchar* szTextNew = new char[ strlen( szText ) + 1 ];\n\tstrcpy( szTextNew, szText );\n\n\t//\tReassign List's ptr.\n\tList[ index ] = szTextNew;\n\n\treturn true;\n}\n\n//***********************************************************************************************\nbool IconListClass::Set_Icon( unsigned int index, unsigned int iIconNumber, void* pIcon, ICONKIND IconKind )\n{\n\tif( index >= List.Count() )\n\t\treturn false;\n\n\t//\tSets one of the left-aligned icons.\n\t( (IconList_ItemExtras*)ExtrasList[ index ] )->pIcon[ iIconNumber ] = pIcon;\n\t( (IconList_ItemExtras*)ExtrasList[ index ] )->IconKind[ iIconNumber ] = IconKind;\n\treturn true;\n}\n\n//***********************************************************************************************\nint IconListClass::GetRealWidth()\t\t//\tsigh\n{\n\tif( IsScrollActive )\n\t\treturn Width + ScrollGadget.Width;\n\treturn Width;\n}\n\n//***********************************************************************************************\nvoid IconListClass::Resize( int x, int y, int w, int h )\n{\n\tRemove_Scroll_Bar();\t//\tIf there is one.\n\n\tX = x;\n\tY = y;\n\tWidth = w;\n\tHeight = h;\n\n\tSet_Position( x, y );\n\n\tLineCount = (h-1) / LineHeight;\n\n\n\tif (List.Count() > LineCount) {\n\t\tAdd_Scroll_Bar();\n\t}\n\n\tFlag_To_Redraw();\n}\n\n//***********************************************************************************************\nint IconListClass::IndexUnderMouse()\n{\n\t//\tReturns index of line that mouse is currently over, or -1 for mouse not hitting valid index.\n\t//\tAssumes that x position of mouse is already known to be over the iconlist.\n\tint index = Get_Mouse_Y() - (Y+1);\n\tindex = index / LineHeight + CurrentTopIndex;\n\tif( index > List.Count() - 1 || index < 0 )\n\t\treturn -1;\n\treturn index;\n}\n\n//***********************************************************************************************\nint IconListClass::OffsetToIndex( int iIndex, int y )\n{\n\t//\tFinds the current offset of item iIndex from the current top view index, in pixels, and add it to y.\n\treturn y + ( iIndex - CurrentTopIndex ) * LineHeight;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\n//\t* Format_Window_String_New\n//\tFunctions like Format_Window_String except it fixes an infinite loop bug that occurred when strings\n//\tlacked suitable break points, eliminates the '@' as an escape character, and operates differently\n//\tin that it leaves the original string along, writing results instead to a second string parameter,\n//\tthat is iExtraChars longer than the original string. This is all a big hack so that I can insert \n//\textra break characters when a break in a long single word has to be made.\n//\tHey - it's better than an infinite loop that forces you to reset your machine, as in the original code...\n\nint Format_Window_String_New( const char* string, int maxlinelen, int& width, int& height, char* szReturn, int iExtraChars )\n{\n\tint\tlinelen;\n\tint\tlines = 0;\n\twidth\t= 0;\n\theight = 0;\n\n\t// In no string was passed in, then there are no lines.\n\tif (!string) return(0);\n\n\t// While there are more letters left divide the line up.\n\twhile (*string) {\n\t\tlinelen = 0;\n\t\theight += FontHeight + FontYSpacing;\n\t\tlines++;\n\n\t\t// While the current line is less then the max length...\n\t\t*szReturn = *string;\n\t\tlinelen += Char_Pixel_Width( *string );\n\t\twhile ( linelen < maxlinelen && *string != '\\r' && *string != '\\0' )\n\t\t{\n\t\t\t*++szReturn = *++string;\n\t\t\tlinelen += Char_Pixel_Width( *string );\n\t\t}\n\n\t\t// if the line is too long...\n\t\tif (linelen >= maxlinelen) \n\t\t{\n\t\t\t/*\n\t\t\t**\tBack up to an appropriate location to break.\n\t\t\t*/\n\t\t\tconst char* stringOverEnd = string;\n\t\t\twhile( linelen > 0 && *string != ' ' && *string != '\\r' && *string != '\\0' )\n\t\t\t{\n\t\t\t\tlinelen -= Char_Pixel_Width(*string--);\n\t\t\t}\n\t\t\tif( linelen <= 0 )\n\t\t\t{\n\t\t\t\t//\tWe could not find a nice break point.\n\t\t\t\t//\tGo back one char from over-the-end point and add in a break there.\n\t\t\t\tstring = stringOverEnd - 1;\n\t\t\t\tif( iExtraChars > 0 )\n\t\t\t\t\tiExtraChars--;\t\t\t//\tOne less to make use of later.\n\t\t\t\telse\n\t\t\t\t\t//\tWe've used up all our extras characters.\n\t\t\t\t\t//\tPut in a break below by wiping out a valid char here.\n\t\t\t\t\tszReturn--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tBack up szReturn to same location.\n\t\t\t\tszReturn -= ( stringOverEnd - string );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRecord the largest width of the worst case string.\n\t\t*/\n\t\tif (linelen > width) {\n\t\t\twidth = linelen;\n\t\t}\n\n\t\t/*\n\t\t**\tForce a break at the end of the line.\n\t\t*/\n\t\tif (*string) {\n\t\t \t*szReturn++ = '\\r';\n\t\t\tstring++;\n\t\t}\n\t}\n\treturn(lines);\n}\n\n//***********************************************************************************************\nvoid CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window )\n{\n\t//\tA very basic DIB drawing routine. No clipping. No edge of window overrun checking.\n\t//\tIf iWidth is too large, default width of dib is used.\n\t//\tIf iWidth is negative, dib isn't drawn.\n\tif( pDIB && iWidth >= 0 )\n\t{\n\n\t\tint iWidthDIB = DIBWidth( pDIB );\n\t\tint iHeight = DIBHeight( pDIB );\n\t\tconst char* pBits = FindDIBBits( pDIB );\n\n\t\tint iSrcPitch = ( iWidthDIB + 3 ) & ~3;\n\n\t\tif( iWidth > iWidthDIB )\n\t\t\tiWidth = iWidthDIB;\n\n\t\tGraphicViewPortClass draw_window(\tLogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWX] + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWY] + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWWIDTH],\n\t\t\t\t\t\t\t\t\t\t\tWindowList[window][WINDOWHEIGHT] );\n\t\tif( draw_window.Lock() )\n\t\t{\n\t\t\tint iDestPitch = draw_window.Get_Pitch() + draw_window.Get_Width();\t//\tMeaning of \"Pitch\" in this class seems to mean the eol skip.\n\t\t\tchar* pLineDest = (char*)draw_window.Get_Offset() + xDest + ( yDest + iHeight - 1 ) * iDestPitch;\n\n\t\t\tconst char* pLineSrc = pBits;\n\t\t\tfor( int y = 0; y != iHeight; y++ )\n\t\t\t{\n\t\t\t\tchar* pDest = pLineDest;\n\t\t\t\tconst char* pSrc = pLineSrc;\n\t\t\t\tfor( int x = 0; x != iWidth; x++ )\n\t\t\t\t{\n\t\t\t\t\t*pDest++ = *pSrc++;\n\t\t\t\t}\n\t\t\t\tpLineDest -= iDestPitch;\n\t\t\t\tpLineSrc += iSrcPitch;\n\t\t\t}\n\t\t\tdraw_window.Unlock();\n\t\t}\n\t}\n//\telse\n//\t\tdebugprint( \"CC_Draw_DIB bad case ------------ pDib %i, iWidth %i\\n\", pDIB, iWidth );\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/ICONLIST.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n/***************************************************************************\n * IconListClass -- Exactly like ListClass, but displays an icon as well\n *                  (actually a 'shape' image), left-aligned, covering\n *                  any text that happens to be there...\n *                  Also, I've added the option of making this class\n *                  responsible for the mem alloc. of the strings, and\n *\t\t\t\t\tan automatic limiting of entries to a set maximum.\n *                                                                         *\n * HISTORY:    07/07/1998 ajw : Created, largely in hack mode.             *\n *=========================================================================*/\n\n#ifndef ICONLIST_H\n#define ICONLIST_H\n\n#include \"function.h\"\n#include \"vector.h\"\n\nenum ICONKIND\n{\n\tICON_SHAPE = 0,\t\t//\tpIcon points to a shape.\n\tICON_DIB\t\t\t//\tpIcon points to DIBitmap data.\n};\n\nstruct FIXEDICON\t\t//\tFor putting icons in list entries at a specific fixed offset.\n{\n\tvoid*\t\tpIcon;\n\tICONKIND\tIconKind;\n\tint\t\t\txOffset;\n\tint\t\t\tyOffset;\n\tint\t\t\tiWidth;\n};\n\nstruct IconList_ItemExtras\n{\n\tIconList_ItemExtras() : bMultiSelected( false ), szHelp( NULL ), szExtraData( NULL ), pvExtraData( NULL )\n\t{\n\t\tpIcon[0] = NULL;\n\t\tpIcon[1] = NULL;\n\t\tpIcon[2] = NULL;\n\t}\n\tvirtual ~IconList_ItemExtras()\n\t{\n\t\tdelete [] szHelp;\n\t\tdelete [] szExtraData;\n\t}\n\n\tbool\t\tbMultiSelected;\t\t//\tTrue if selected when bMultiSelect is on.\n\tvoid*\t\tpIcon[3];\t\t\t//\tIcon that appears before an item.\n\tICONKIND\tIconKind[3];\t\t//\tSpecifies what kind of image data pIcon points to.\n\tchar*\t\tszHelp;\t\t\t\t//\tTooltip help string that can be associated with item. Allocated and deleted here.\n\tchar*\t\tszExtraData;\t\t//\tExtra string that can be associated with item. Allocated and deleted here.\n\tvoid*\t\tpvExtraData;\t\t//\tHidden pointer that can be associated with item.\n\tRemapControlType*\tpColorRemap;\t//\tPointer to a color remap, or null for default colored text.\n\tFIXEDICON\tFixedIcon;\n};\n\nclass IconListClass : public ListClass\n{\n\tpublic:\n\t\tIconListClass( int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down, bool bResponsibleForStringAlloc = FALSE, int iSelectionType = 1, int iMaxItemsSaved = 0 );\n//\t\tIconListClass( const IconListClass& list );\n\t\tvirtual ~IconListClass( void );\n\n\t\tvirtual int Add_Item( char const * text );\n\t\tvirtual int Add_Item( const char* text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString = NULL, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr = NULL, RemapControlType* pColorRemap = NULL,\n\t\t\t\t\t\t\t\tvoid* pIcon1 = NULL, ICONKIND IconKind1 = ICON_SHAPE, \n\t\t\t\t\t\t\t\tvoid* pIcon2 = NULL, ICONKIND IconKind2 = ICON_SHAPE,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon = NULL, ICONKIND FixedIconKind = ICON_SHAPE, int iXFixedIcon = 0, int iYFixedIcon = 0, int iFixedIconWidth = -1 );\n\n\t\tvirtual int Add_Item( int text );\n\t\tvirtual int Add_Item( int text, const char* szHelp,\n\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString = NULL, \n\t\t\t\t\t\t\t\tvoid* pvExtraDataPtr = NULL, RemapControlType* pColorRemap = NULL,\n\t\t\t\t\t\t\t\tvoid* pIcon1 = NULL, ICONKIND IconKind1 = ICON_SHAPE, \n\t\t\t\t\t\t\t\tvoid* pIcon2 = NULL, ICONKIND IconKind2 = ICON_SHAPE,\n\t\t\t\t\t\t\t\tvoid* pFixedIcon = NULL, ICONKIND FixedIconKind = ICON_SHAPE, int iXFixedIcon = 0, int iYFixedIcon = 0, int iFixedIconWidth = -1 );\n\n//\t\tvirtual int Add_Scroll_Bar(void);\n//\t\tvirtual void Bump(int up);\n//\t\tvirtual int Count(void) const {return List.Count();};\n//\t\tvirtual int Current_Index(void) const;\n//\t\tvirtual char const * Current_Item(void) const;\n//\t\tvirtual int Draw_Me(int forced);\n//\t\tvirtual char const * Get_Item(int index) const;\n//\t\tvirtual int Step_Selected_Index(int forward);\n//\t\tvirtual void Flag_To_Redraw(void);\n\n//\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item( char const * text );\n\t\tvirtual void Remove_Item( int );\n//\t\tvirtual int  Remove_Scroll_Bar(void);\n//\t\tvirtual void Set_Selected_Index(int index);\n//\t\tvirtual void Set_Selected_Index(char const * text);\n//\t\tvirtual void Set_Tabs(int const * tabs);\n//\t\tvirtual int  Set_View_Index(int index);\n//\t\tvirtual void Step(int up);\n//\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n//\t\tvirtual LinkClass & Add(LinkClass & object);\n//\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n//\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n//\t\tvirtual GadgetClass * Remove(void);\n\n\t\tvirtual void\t\tShow_Last_Item();\n\t\tvirtual bool\t\tbItemIsMultiSelected( int index ) const;\n\t\tvirtual void\t\tMultiSelect( int index, bool bSelect );\n\t\tvirtual const char*\tGet_Item_ExtraDataString( int index ) const;\n\t\tvirtual void\t\tSet_Item_ExtraDataString( int index, const char* szNewString );\n\t\tvirtual void*\t\tGet_Item_ExtraDataPtr( int index ) const;\n\t\tvirtual void\t\tSet_Item_ExtraDataPtr( int index, void* pNewValue );\n\t\tconst char*\t\t\tGet_Item_Help( int index ) const;\n\t\tvirtual RemapControlType*\tGet_Item_Color( int index );\n\t\tvirtual void\t\t\t\tSet_Item_Color( int index, RemapControlType* pColorRemap );\n\t\tvirtual const IconList_ItemExtras*\tGet_ItemExtras( int index ) const;\n\t\tvirtual void\t\tClear();\n\t\tvirtual int\t\t\tGet_View_Index()\t{\treturn CurrentTopIndex;\t\t}\n\t\tbool bScrollBeingDragged()\n\t\t{\n\t\t\t//\tReturns true if the scroll bar of the list is being dragged by the user.\n\t\t\treturn ( GadgetClass::StuckOn == &ScrollGadget );\n\t\t}\n\n\t\tvirtual int\t\t\tFind( const char* szItemToFind );\n\t\tvirtual int\t\t\tFindColor( RemapControlType* pColorRemap );\n\n\t\tvirtual bool\t\tSet_Item( unsigned int index, const char* szText );\n\t\tvirtual bool\t\tSet_Icon( unsigned int index, unsigned int iIconNumber, void* pIcon, ICONKIND IconKind );\n\n\t\tvirtual int\t\t\tGetRealWidth();\n\t\tvirtual void\t\tResize( int x, int y, int w, int h );\n\t\tvirtual int\t\t\tIndexUnderMouse();\n\t\tvirtual int\t\t\tOffsetToIndex( int iIndex, int y );\n\n\t\tvirtual int\t\t\tSetSelectType( int iSelectTypeNew )\n\t\t{\n\t\t\t//\tProvided to enable horrible hacks, mainly involved with dealing with ListClass's inability\n\t\t\t//\tto have no item selected...\n\t\t\tint iSelectTypeOld = iSelectType;\n\t\t\tiSelectType = iSelectTypeNew;\n\t\t\treturn iSelectTypeOld;\n\t\t}\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry( int index, int x, int y, int width, int selected );\n\n\t\tvirtual int  Add_Item_Detail( const char* szToken, const char* szHelp,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon0, ICONKIND IconKind0, const char* szExtraDataString, \n\t\t\t\t\t\t\t\t\t\tvoid* pvExtraData, RemapControlType* pColorRemap,\n\t\t\t\t\t\t\t\t\t\tvoid* pIcon1, ICONKIND IconKind1, void* pIcon2, ICONKIND IconKind2,\n\t\t\t\t\t\t\t\t\t\tvoid* pFixedIcon, ICONKIND FixedIconKind, int iXFixedIcon, int iYFixedIcon, int iFixedIconWidth );\n\n\t\t//\tThe list of Icons.\n\t\t//DynamicVectorClass<void*> IconList;\n\t\t//DynamicVectorClass< IconList_ItemExtras* > ExtrasList;\t\tajw: creates hellacious linking problems\n\t\tDynamicVectorClass< void* > ExtrasList;\n\n\t\tbool bDoAlloc;\t\t//\tTrue if I am responsible for mem. allocation/deletion of strings.\n//\t\tbool bMultiSelect;\t//\tTrue if we are using the multiple item selection feature.\n\t\tint iSelectType;\t//\t0 for no selection shown, 1 for normal ListClass selection, 2 for n multiple selections\n\t\tint\tiMaxItems;\t\t//\tNumber of items to limit list to, if bDoAlloc is true.\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/IDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IDATA.CPP 3     3/16/97 10:16p Joe_b $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : July 19, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   InfantryTypeClass::As_Reference -- Fetches a reference to the infantry type specified.    *\n *   InfantryTypeClass::Create_And_Place -- Creates and places infantry object onto the map.   *\n *   InfantryTypeClass::Create_One_Of -- Creates an infantry object.                           *\n *   InfantryTypeClass::Display -- Displays a generic infantry object.                         *\n *   InfantryTypeClass::From_Name -- Converts an ASCII name into an infantry type number.      *\n *   InfantryTypeClass::Full_Name -- Fetches the full name text number.                        *\n *   InfantryTypeClass::Get_Cameo_Data -- Fetches the small cameo shape for sidebar strip.     *\n *   InfantryTypeClass::InfantryTypeClass -- Constructor for infantry type class objects.      *\n *   InfantryTypeClass::Init_Heap -- Initialize the infantry type class heap.                  *\n *   InfantryTypeClass::Occupy_List -- Returns with default infantry occupation list.          *\n *   InfantryTypeClass::One_Time -- Performs any one time processing for infantry system.      *\n *   InfantryTypeClass::Prep_For_Add -- Prepares the scenario editor for adding of infantry obj*\n *   InfantryTypeClass::Read_INI -- Fetches infantry override values from the INI database.    *\n *   InfantryTypeClass::operator delete -- Frees an infantry type class object.                *\n *   InfantryTypeClass::operator new -- Allocate an infanty type class object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\nstatic DoInfoStruct DogDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t// NA\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{104,\t14,14},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{0,\t0,\t0},\t\t\t\t\t// DO_LIE_DOWN\t\t// NA\n\t{56,\t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0,\t0,\t0},\t\t\t\t\t// DO_GET_UP\n\t{104,\t14,14},\t\t\t\t\t// DO_FIRE_PRONE\n\t{216,\t18,0},\t\t\t\t\t// DO_IDLE1\n\t{216,\t18,0},\t\t\t\t\t// DO_IDLE2\n\t{235,\t7,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{242,\t9,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{242,\t9,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{242,\t9, 0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{251,\t14,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{106,\t12,14},\t\t\t\t\t//\tDO_DOG_MAUL\n};\n\n\n//\n// For the virtual do controls, we are using the TD infantry asset animation frame numbers, take out the -94 frame offsets that were added in RA\n//\n\nstatic DoInfoStruct E1DoControlsVirtual[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,\t8},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t6,\t8},\t\t\t\t\t// DO_FIRE_PRONE\n\t{256,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{382,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{398,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{398,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{406,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{418,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{436,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{460,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{484,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{508,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E2DoControlsVirtual[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{288,\t1,\t12},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t20,20},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{224,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{240,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{272,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{288,\t8,\t12},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{526,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{546,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{564,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{588,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{612,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{636,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E3DoControlsVirtual[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,10},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t10,10},\t\t\t\t\t// DO_FIRE_PRONE\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{288,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{398,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{414,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{414,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{422,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{434,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{452,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{476,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{500,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{524,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E4DoControlsVirtual[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{256,\t1,16},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t16,16},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{192,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{208,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{240,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{256,\t16,16},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{526,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{546,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{564,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{588,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{612,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{636,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n\n\nstatic DoInfoStruct E1DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,\t8},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t6,\t8},\t\t\t\t\t// DO_FIRE_PRONE\n\t{256,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{382-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{398-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{398-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{406-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{418-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{436-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{460-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{484-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{508-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E2DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{288,\t1,\t12},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t20,20},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{224,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{240,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{272,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{288,\t8,\t12},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{546-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{564-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{588-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{612-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{636-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E3DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{192,\t1,10},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t10,10},\t\t\t\t\t// DO_FIRE_PRONE\n\t{272,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{288,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{398-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{414-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{414-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{422-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{434-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{452-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{476-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{500-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{524-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E4DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{256,\t1,16},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t16,16},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{192,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{208,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{240,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{256,\t16,16},\t\t\t\t\t// DO_FIRE_PRONE\n\t{384,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{400,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{510-94,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{526-94,\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{534-94,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{546-94,\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{564-94,\t3,\t3},\t\t\t\t// DO_GESTURE1\n\t{588-94,\t3,\t3},\t\t\t\t// DO_SALUTE1\n\t{612-94,\t3,\t3},\t\t\t\t// DO_GESTURE2\n\t{636-94,\t3,\t3},\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n\nstatic DoInfoStruct E6DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{82,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{67,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{82,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{114,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{130,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{130,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{146,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{154,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{162,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{170,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{182,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{200,\t3,\t3},\t\t\t\t\t// DO_GESTURE1\n\t{224,\t3,\t3},\t\t\t\t\t// DO_SALUTE1\n\t{200,\t3,\t3},\t\t\t\t\t// DO_GESTURE2\n\t{224,\t3,\t3},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E7DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{128,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t7,\t7},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{113,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{128,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{161,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{176,\t7,\t7},\t\t\t\t\t// DO_FIRE_PRONE\n\t{232,\t17,0},\t\t\t\t\t// DO_IDLE1\n\t{249,\t13,0},\t\t\t\t\t// DO_IDLE2\n\t{262,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{270,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{278,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{286,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{298,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n//Spy\nstatic DoInfoStruct SpyDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{144,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{16,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{64,\t8,\t8},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{128,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{144,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{176,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{192,\t8,\t8},\t\t\t\t\t// DO_FIRE_PRONE\n\t{256,\t14,0},\t\t\t\t\t// DO_IDLE1\n\t{270,\t18,0},\t\t\t\t\t// DO_IDLE2\n\t{288,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{296,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{304,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{312,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{324,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct E9DoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{8,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{72,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{56,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{72,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{108,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{120,\t19,0},\t\t\t\t\t// DO_IDLE1\n\t{120,\t19,0},\t\t\t\t\t// DO_IDLE2\n\t{139,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{147,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{155,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{163,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{175,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct MedicDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{130,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t28,0},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{114,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{130,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{162,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{56,\t28,0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{178,\t15,0},\t\t\t\t\t// DO_IDLE1\n\t{178,\t15,0},\t\t\t\t\t// DO_IDLE2\n\t{193,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{210,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{202,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{217,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{229,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct GeneralDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{104,\t1,\t4},\t\t\t\t\t// DO_PRONE\n\t{8,\t6,\t6},\t\t\t\t\t// DO_WALK\n\t{56,\t4,\t4},\t\t\t\t\t// DO_FIRE_WEAPON\n\t{88,\t2,\t2},\t\t\t\t\t// DO_LIE_DOWN\n\t{104,\t4,\t4},\t\t\t\t\t// DO_CRAWL\n\t{136,\t2,\t2},\t\t\t\t\t// DO_GET_UP\n\t{152,\t4,\t4},\t\t\t\t\t// DO_FIRE_PRONE\n\t{184,\t26,0},\t\t\t\t\t// DO_IDLE1\n\t{184,\t26,0},\t\t\t\t\t// DO_IDLE2\n\t{210,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{226,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{218,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{234,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{246,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE1\n\t{0,\t1,\t0},\t\t\t\t\t// DO_GESTURE2\n\t{0,\t1,\t0},\t\t\t\t\t// DO_SALUTE2\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct CivilianDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t\t// N/A\n\t{56, \t6,\t6},\t\t\t\t\t// DO_WALK\n\t{205-85,\t4, 4},\t\t\t\t// DO_FIRE_WEAPON\n\t{0, \t1,\t1},\t\t\t\t\t// DO_LIE_DOWN\t\t\t// N/A\n\t{8, \t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0, \t1,\t1},\t\t\t\t\t// DO_GET_UP\t\t\t// N/A\n\t{205-85,\t4,\t4},\t\t\t\t// DO_FIRE_PRONE\n\t{189-85,\t10,0},\t\t\t\t// DO_IDLE1\n\t{199-85,\t6,\t0},\t\t\t\t// DO_IDLE2\n\t{152,\t8,\t0},\t\t\t\t\t// DO_GUN_DEATH\n\t{160,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION_DEATH\n\t{160,\t8,\t0},\t\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{168,\t12,0},\t\t\t\t\t// DO_GRENADE_DEATH\n\t{180,\t18,0},\t\t\t\t\t// DO_FIRE_DEATH\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE2\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE2\t\t\t// N/A\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct CivilianDoControlsVirtual[DO_COUNT] = {\n\t{0,\t\t\t1,\t1},\t\t\t\t// DO_STAND_READY\n\t{0,\t\t\t1,\t1},\t\t\t\t// DO_STAND_GUARD\n\t{0,\t\t\t1,\t1},\t\t\t\t// DO_PRONE\t\t\t\t// N/A\n\t{56, \t\t6,\t6},\t\t\t\t// DO_WALK\n\t{205,\t\t4, 4},\t\t\t\t// DO_FIRE_WEAPON\n\t{0, \t\t1,\t1},\t\t\t\t// DO_LIE_DOWN\t\t\t// N/A\n\t{8, \t\t6,\t6},\t\t\t\t// DO_CRAWL\n\t{0, \t\t1,\t1},\t\t\t\t// DO_GET_UP\t\t\t// N/A\n\t{205,\t\t4,\t4},\t\t\t\t// DO_FIRE_PRONE\n\t{189,\t\t10,0},\t\t\t\t// DO_IDLE1\n\t{199,\t\t6,\t0},\t\t\t\t// DO_IDLE2\n\t{329,\t\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{337,\t\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{337,\t\t8,\t0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{345,\t\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{357,\t\t18,0},\t\t\t\t// DO_FIRE_DEATH\n\t{0, \t\t1,\t0},\t\t\t\t// DO_GESTURE1\t\t\t// N/A\n\t{0, \t\t1,\t0},\t\t\t\t// DO_SALUTE1\t\t\t// N/A\n\t{0, \t\t1,\t0},\t\t\t\t// DO_GESTURE2\t\t\t// N/A\n\t{0, \t\t1,\t0},\t\t\t\t// DO_SALUTE2\t\t\t// N/A\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\nstatic DoInfoStruct EinsteinDoControls[DO_COUNT] = {\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_READY\n\t{0,\t1,\t1},\t\t\t\t\t// DO_STAND_GUARD\n\t{0,\t1,\t1},\t\t\t\t\t// DO_PRONE\t\t\t\t// N/A\n\t{56, \t6,\t6},\t\t\t\t\t// DO_WALK\n\t{205-92,\t4, 4},\t\t\t\t// DO_FIRE_WEAPON\n\t{0, \t1,\t1},\t\t\t\t\t// DO_LIE_DOWN\t\t\t// N/A\n\t{8, \t6,\t6},\t\t\t\t\t// DO_CRAWL\n\t{0, \t1,\t1},\t\t\t\t\t// DO_GET_UP\t\t\t// N/A\n\t{0,\t0,\t0},\t\t\t\t\t// DO_FIRE_PRONE\n\t{104,\t16,0},\t\t\t\t\t// DO_IDLE1\n\t{104,\t16,0},\t\t\t\t\t// DO_IDLE2\n\t{212-92,\t8,\t0},\t\t\t\t// DO_GUN_DEATH\n\t{220-92,\t8,\t0},\t\t\t\t// DO_EXPLOSION_DEATH\n\t{228-92,\t12,0},\t\t\t\t// DO_EXPLOSION2_DEATH\n\t{228-92,\t12,0},\t\t\t\t// DO_GRENADE_DEATH\n\t{240-92,\t17,0},\t\t\t\t// DO_FIRE_DEATH\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE1\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_GESTURE2\t\t\t// N/A\n\t{0, \t1,\t0},\t\t\t\t\t// DO_SALUTE2\t\t\t// N/A\n\t{0,\t0, 0},\t\t\t\t\t//\tDO_DOG_MAUL\t\t\t// N/A\n};\n\n// Attack dogs\nstatic InfantryTypeClass const Dog(\n\tINFANTRY_DOG,\t\t\t\t// Infantry type number.\n\tTXT_GUARD_DOG,\t\t\t\t// Translate name number for infantry type.\n\t\"DOG\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0015,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tDogDoControls,\n\tDogDoControls,\n\t1,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t1,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Minigunners\nstatic InfantryTypeClass const E1(\n\tINFANTRY_E1,\t\t\t\t// Infantry type number.\n\tTXT_E1,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E1\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE1DoControls,\n\tE1DoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Grenadiers\nstatic InfantryTypeClass const E2(\n\tINFANTRY_E2,\t\t\t\t// Infantry type number.\n\tTXT_E2,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E2\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE2DoControls,\n\tE2DoControlsVirtual,\n\t14,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t6,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Bazooka\nstatic InfantryTypeClass const E3(\n\tINFANTRY_E3,\t\t\t\t// Infantry type number.\n\tTXT_E3,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E3\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE3DoControls,\n\tE3DoControlsVirtual,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Flamethrower\nstatic InfantryTypeClass const E4(\n\tINFANTRY_E4,\t\t\t\t// Infantry type number.\n\tTXT_E4,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E4\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE4DoControls,\n\tE4DoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Renovator\nstatic InfantryTypeClass const E6(\n\tINFANTRY_RENOVATOR,\t\t\t\t// Infantry type number.\n\tTXT_E6,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E6\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tE6DoControls,\n\tE6DoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Spy\nstatic InfantryTypeClass const E8(\n\tINFANTRY_SPY,\t\t\t\t// Infantry type number.\n\tTXT_E8,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"SPY\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tSpyDoControls,\n\tSpyDoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Thief\nstatic InfantryTypeClass const E9(\n\tINFANTRY_THIEF,\t\t\t\t// Infantry type number.\n\tTXT_THIEF,\t\t\t\t\t// Translate name number for infantry type.\n\t\"THF\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tE9DoControls,\n\tE9DoControls,\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t3,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Tanya\nstatic InfantryTypeClass const E7(\n\tINFANTRY_TANYA,\t\t\t// Infantry type number.\n\tTXT_E7,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"E7\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_COMMANDO,\t\t\t\t// Transport pip shape/color to use.\n\tE7DoControls,\n\tE7DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Medic(\n\tINFANTRY_MEDIC,\t\t\t// Infantry type number.\n\tTXT_MEDIC,\t\t\t\t\t// Translate name number for infantry type.\n\t\"MEDI\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tMedicDoControls,\n\tMedicDoControls,\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const General(\n\tINFANTRY_GENERAL,\t\t\t// Infantry type number.\n\tTXT_GENERAL,\t\t\t\t// Translate name number for infantry type.\n\t\"GNRL\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tGeneralDoControls,\n\tGeneralDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Civilians\nstatic InfantryTypeClass const C1(\n\tINFANTRY_C1,\t\t\t\t// Infantry type number.\n\tTXT_C1,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C1\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C2(\n\tINFANTRY_C2,\t\t\t\t// Infantry type number.\n\tTXT_C2,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C2\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv2\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C3(\n\tINFANTRY_C3,\t\t\t\t// Infantry type number.\n\tTXT_C3,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C3\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\ttrue,\t\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C4(\n\tINFANTRY_C4,\t\t\t\t// Infantry type number.\n\tTXT_C4,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C4\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\ttrue,\t\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv4\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C5(\n\tINFANTRY_C5,\t\t\t\t// Infantry type number.\n\tTXT_C5,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C5\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv5\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C6(\n\tINFANTRY_C6,\t\t\t\t// Infantry type number.\n\tTXT_C6,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C6\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv6\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C7(\n\tINFANTRY_C7,\t\t\t\t// Infantry type number.\n\tTXT_C7,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C7\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv7\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C8(\n\tINFANTRY_C8,\t\t\t\t// Infantry type number.\n\tTXT_C8,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C8\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv8\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const C9(\n\tINFANTRY_C9,\t\t\t\t// Infantry type number.\n\tTXT_C9,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C9\",\t\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_CIVILIAN,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv9\t\t\t\t\t\t// pointer to override remap table\n);\n\n// Nikoomba\nstatic InfantryTypeClass const C10(\n\tINFANTRY_C10,\t\t\t\t// Infantry type number.\n\tTXT_C10,\t\t\t\t\t\t// Translate name number for infantry type.\n\t\"C10\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\ttrue,\t\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\tRemapCiv10\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Einstein(\n\tINFANTRY_EINSTEIN,\t\t// Infantry type number.\n\tTXT_EINSTEIN,\t\t\t\t// Translate name number for infantry type.\n\t\"EINSTEIN\",\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tEinsteinDoControls,\n\tEinsteinDoControls,\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const Delphi(\n\tINFANTRY_DELPHI,\t\t\t// Infantry type number.\n\tTXT_DELPHI,\t\t\t\t\t// Translate name number for infantry type.\n\t\"DELPHI\",\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tCivilianDoControls,\n\tCivilianDoControlsVirtual,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\nstatic InfantryTypeClass const DrChan(\n\tINFANTRY_CHAN,\t\t\t\t// Infantry type number.\n\tTXT_CHAN,\t\t\t\t\t// Translate name number for infantry type.\n\t\"CHAN\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\tfalse,\t\t\t\t\t\t// Has crawling animation frames?\n\ttrue,\t\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\ttrue,\t\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tEinsteinDoControls,\n\tEinsteinDoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\n// Shock Trooper\nstatic InfantryTypeClass const ShockTrooper(\n\tINFANTRY_SHOCK,\t\t\t// Infantry type number.\n\tTXT_SHOCKTROOPER,\t\t\t// Translate name number for infantry type.\n\t\"SHOK\",\t\t\t\t\t\t// INI name for infantry.\n\t-0x0010,\t\t\t\t\t//\tVertical offset.\n\t0x0038,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_FULL,\t\t\t\t\t// Transport pip shape/color to use.\n\tE4DoControls,\n\tE4DoControls,\n\t2,\t\t\t\t\t\t\t\t// Frame of projectile launch.\n\t0,\t\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0,\t\t\t\t\t\t\t\t// pointer to override remap table\n\t0x0018\t\t\t\t\t\t//\tHorizontal offset.\n);\n\n\nstatic InfantryTypeClass const Mechanic(\n\tINFANTRY_MECHANIC,\t\t// Infantry type number.\n\tTXT_MECHANIC,\t\t\t\t\t// Translate name number for infantry type.\n\t\"MECH\",\t\t\t\t\t\t// INI name for infantry.\n\t0x0035,\t\t\t\t\t\t//\tVertical offset.\n\t0x0010,\t\t\t\t\t\t// Primary weapon offset along turret centerline.\n\tfalse,\t\t\t\t\t\t// Is this a female type?\n\ttrue,\t\t\t\t\t\t\t// Has crawling animation frames?\n\tfalse,\t\t\t\t\t\t// Is this a civilian?\n\tfalse,\t\t\t\t\t\t// Does this unit use the override remap table?\n\tfalse,\t\t\t\t\t\t// Always use the given name for the infantry?\n\tfalse,\t\t\t\t\t\t// Theater specific graphic image?\n\tPIP_ENGINEER,\t\t\t\t// Transport pip shape/color to use.\n\tMedicDoControls,\n\tMedicDoControls,\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch.\n\t25,\t\t\t\t\t\t\t// Frame of projectile launch while prone.\n\t0\t\t\t\t\t\t\t\t// pointer to override remap table\n);\n#endif\n\n/***********************************************************************************************\n * InfantryTypeClass::InfantryTypeClass -- Constructor for infantry type class objects.        *\n *                                                                                             *\n *    This routine will construct the infantry type objects. It is use to create the static    *\n *    infantry types that are used to give each of the infantry objects their characteristics. *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   02/16/1996 JLB : Greatly simplified.                                                      *\n *=============================================================================================*/\nInfantryTypeClass::InfantryTypeClass (\n\t\t\t\t\t\tInfantryType type,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ininame,\n\t\t\t\t\t\tint verticaloffset,\n\t\t\t\t\t\tint primaryoffset,\n\t\t\t\t\t\tbool is_female,\n\t\t\t\t\t\tbool is_crawling,\n\t\t\t\t\t\tbool is_civilian,\n\t\t\t\t\t\tbool is_remap_override,\n\t\t\t\t\t\tbool is_nominal,\n\t\t\t\t\t\tbool is_theater,\n\t\t\t\t\t\tPipEnum pip,\n\t\t\t\t\t\tDoInfoStruct const * control,\n\t\t\t\t\t\tDoInfoStruct const * virtual_control,\n\t\t\t\t\t\tint firelaunch,\n\t\t\t\t\t\tint pronelaunch,\n\t\t\t\t\t\tunsigned char const * override_remap,\n\t\t\t\t\t\tint horizontaloffset)\n\t: TechnoTypeClass(RTTI_INFANTRYTYPE,\n\t\t\t\t\t\t\tint(type),\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tininame,\n\t\t\t\t\t\t\tREMAP_NORMAL,\n\t\t\t\t\t\t\tverticaloffset,\n\t\t\t\t\t\t\tprimaryoffset,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\t0x0000,\n\t\t\t\t\t\t\tis_nominal,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tis_theater,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t8,\n\t\t\t\t\t\t\tSPEED_FOOT,\n\t\t\t\t\t\t\thorizontaloffset),\n\tIsFemale(is_female),\n\tIsCrawling(is_crawling),\n\tIsCapture(false),\n\tIsFraidyCat(false),\n\tIsCivilian(is_civilian),\n\tIsBomber(false),\n\tIsDog(false),\n\tIsRemapOverride(is_remap_override),\n\tType(type),\n\tPip(pip),\n\tDoControls(control),\n\tDoControlsVirtual(virtual_control),\n\tFireLaunch(firelaunch),\n\tProneLaunch(pronelaunch),\n\tOverrideRemap(override_remap)\n{\n\t/*\n\t**\tForced infantry overrides from the default.\n\t*/\n\tIsCrushable = true;\n\tIsScanner = true;\n\tIsRepairable = false;\n\tIsCrew = false;\n\tSpeed = SPEED_FOOT;\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::operator new -- Allocate an infanty type class object.                   *\n *                                                                                             *\n *    This will allocate an infantry type class object from the special memory pool of that    *\n *    purpose.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the infantry type class object allocated. If there was   *\n *          insufficient memory to fulfill the request, then NULL is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * InfantryTypeClass::operator new(size_t)\n{\n\treturn(InfantryTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::operator delete -- Frees an infantry type class object.                  *\n *                                                                                             *\n *    This will return a previously allocated infantry type class object back to the memory    *\n *    pool from whence it came.                                                                *\n *                                                                                             *\n * INPUT:   pointer  -- The pointer to the infantry type class object to free.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::operator delete(void * pointer)\n{\n\tInfantryTypes.Free((InfantryTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Init_Heap -- Initialize the infantry type class heap.                    *\n *                                                                                             *\n *    This will pre-allocate all known infantry types.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine once and before the rules.ini file is processed.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese infantry type class objects must be allocated in the exact order that they\n\t**\tare specified in the InfantryType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew InfantryTypeClass(E1);\n\tnew InfantryTypeClass(E2);\n\tnew InfantryTypeClass(E3);\n\tnew InfantryTypeClass(E4);\n\tnew InfantryTypeClass(E6);\n\tnew InfantryTypeClass(E7);\n\tnew InfantryTypeClass(E8);\n\tnew InfantryTypeClass(E9);\n\tnew InfantryTypeClass(Medic);\n\tnew InfantryTypeClass(General);\n\tnew InfantryTypeClass(Dog);\n\tnew InfantryTypeClass(C1);\n\tnew InfantryTypeClass(C2);\n\tnew InfantryTypeClass(C3);\n\tnew InfantryTypeClass(C4);\n\tnew InfantryTypeClass(C5);\n\tnew InfantryTypeClass(C6);\n\tnew InfantryTypeClass(C7);\n\tnew InfantryTypeClass(C8);\n\tnew InfantryTypeClass(C9);\n\tnew InfantryTypeClass(C10);\n\tnew InfantryTypeClass(Einstein);\n\tnew InfantryTypeClass(Delphi);\n\tnew InfantryTypeClass(DrChan);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew InfantryTypeClass(ShockTrooper);\n\tnew InfantryTypeClass(Mechanic);\n#endif\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Create_One_Of -- Creates an infantry object.                             *\n *                                                                                             *\n *    This creates an infantry object, but does not attempt to place it on the map. It is      *\n *    typically used by the scenario editor when an object is needed, but the location has     *\n *    not yet been specified for where it should appear on the map.                            *\n *                                                                                             *\n * INPUT:   house -- The owner of the infantry object.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the created infantry object. If an object could not be   *\n *          created, then NULL is returned.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * InfantryTypeClass::Create_One_Of(HouseClass * house) const\n{\n\treturn(new InfantryClass(Type, house->Class->House));\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Create_And_Place -- Creates and places infantry object onto the map.     *\n *                                                                                             *\n *    This routine is used by the scenario editor to create and place an infantry object onto  *\n *    the map at the location specified.                                                       *\n *                                                                                             *\n * INPUT:   cell     -- The cell location to place the infantry object at.                     *\n *                                                                                             *\n *          house    -- The owner of the infantry object.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry object successfully created and placed at the location      *\n *                specified?                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryTypeClass::Create_And_Place(CELL cell, HousesType house) const\n{\n\tInfantryClass * i = new InfantryClass(Type, house);\n\tif (i != NULL) {\n\t\tCOORDINATE coord = Map[cell].Closest_Free_Spot(Cell_Coord(cell));\n\t\tif (coord) {\n\t\t\treturn(i->Unlimbo(coord, DIR_E));\n\t\t} else {\n\t\t\tdelete i;\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Occupy_List -- Returns with default infantry occupation list.            *\n *                                                                                             *\n *    This routine will return with a cell offset occupation list for a generic infantry       *\n *    object. This is typically just a single cell since infantry are never bigger than one    *\n *    cell and this routine presumes the infantry is located in the center of the cell.        *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a cell offset list for the infantry object as if it were located      *\n *          in the center of a cell.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * InfantryTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\n\treturn(&_list[0]);\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * InfantryTypeClass::Display -- Displays a generic infantry object.                           *\n *                                                                                             *\n *    This routine is used by the scenario editor to display a generic representation of the   *\n *    infantry object for the scenario editor. It simply draws a single (nice profile) view    *\n *    of the infantry type.                                                                    *\n *                                                                                             *\n * INPUT:   x,y      -- The display coordinates to render the infantry object at.              *\n *                                                                                             *\n *          window   -- The window that the display coordinates are relative to.               *\n *                                                                                             *\n *          house    -- The house colors to use when rendering this infantry object.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Display(int x, int y, WindowNumberType window, HousesType house) const\n{\n\tif (house != HOUSE_NONE) {\n\n\t\tint shape = 0;\n\t\tvoid const * ptr = Get_Cameo_Data();\n\t\tif (ptr == NULL) {\n\t\t\tptr = Get_Image_Data();\n\t\t\tshape = 2;\n\t\t}\n\n\t\tCC_Draw_Shape(ptr, shape, x, y, window, SHAPE_NORMAL|SHAPE_CENTER|SHAPE_WIN_REL);\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Prep_For_Add -- Prepares the scenario editor for adding of infantry object.*\n *                                                                                             *\n *    This routine will prepare the scenario editor so that the infantry objects appear on     *\n *    the object list.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::Prep_For_Add(void)\n{\n\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\tMap.Add_To_List(&As_Reference(index));\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * InfantryTypeClass::From_Name -- Converts an ASCII name into an infantry type number.        *\n *                                                                                             *\n *    This routine is used to convert the infantry ASCII name as specified into an infantry    *\n *    type number. This is called from the INI reader routine in the process if creating the   *\n *    infantry objects needed for the scenario.                                                *\n *                                                                                             *\n * INPUT:   name  -- The ASCII name to convert into an infantry type number.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the infantry type number that corresponds to the infantry ASCII name  *\n *          specified. If no match could be found, then INFANTRY_NONE is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryType InfantryTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (InfantryType classid = INFANTRY_FIRST; classid < INFANTRY_COUNT; classid++) {\n\t\t\tif (stricmp(As_Reference(classid).IniName, name) == 0) {\n\t\t\t\treturn(classid);\n\t\t\t}\n\t\t}\n\t}\n\treturn(INFANTRY_NONE);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::One_Time -- Performs any one time processing for infantry system.        *\n *                                                                                             *\n *    This routine will perform one time processing for the infantry type system. This is      *\n *    generally restricted to loading of the infantry shape data.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryTypeClass::One_Time(void)\n{\n\tfor (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {\n\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\n\t\tInfantryTypeClass\tconst * uclass;\n\t\tCCFileClass\tfile;\n\n\t\tuclass = &As_Reference(index);\n\n\t\t/*\n\t\t**\tGeneric shape for all houses load method.\n\t\t*/\n\t\t_makepath(fullname, NULL, NULL, uclass->Graphic_Name(), \".SHP\");\n\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass sfile(fullname);\n\t\t\tif (sfile.Is_Available()) {\n\t\t\t\t((void const *&)uclass->ImageData) = Load_Alloc_Data(sfile);\n\t\t\t} else {\n\t\t\t\t((void const *&)uclass->ImageData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t#else\n\t\t\t((void const *&)uclass->ImageData) = MFCD::Retrieve(fullname);\n\t\t#endif\n\n\t\t/*\n\t\t**\tThe small build image icon sized shapes are always generic.\n\t\t*/\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%.4sICON\", uclass->Graphic_Name());\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass ifile(fullname);\n\t\t\tif (ifile.Is_Available()) {\n\t\t\t\t((void const *&)uclass->CameoData) = Load_Alloc_Data(ifile);\n\t\t\t} else {\n\t\t\t\t((void const *&)uclass->CameoData) = MFCD::Retrieve(fullname);\n\t\t\t}\n\t\t#else\n\t\t\t((void const *&)uclass->CameoData) = MFCD::Retrieve(fullname);\n\t\t#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Full_Name -- Fetches the full name text number.                          *\n *                                                                                             *\n *    This routine will fetch the full name text number for this infantry type. It examines    *\n *    the special custom name flag to determine whether the custom name or the generic name    *\n *    is to be used.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with text number for the name to give this infantry type object.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint InfantryTypeClass::Full_Name(void) const\n{\n\tif (Debug_Map || !IsNominal || Rule.IsNamed || Type == INFANTRY_C10 || Type == INFANTRY_DELPHI || Type == INFANTRY_EINSTEIN) {\n\t\treturn(TechnoTypeClass::Full_Name());\n\t}\n\treturn(TXT_CIVILIAN);\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::As_Reference -- Fetches a reference to the infantry type specified.      *\n *                                                                                             *\n *    Use this routine to convert an infantry type number into a reference to the infantry     *\n *    type class object it represents.                                                         *\n *                                                                                             *\n * INPUT:   type  -- The infantry type number to convert into a infantry type class object.    *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the infantry type class object specified.              *\n *                                                                                             *\n * WARNINGS:   Be sure that the type parameter is legal, otherwise the results are undefined.  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryTypeClass & InfantryTypeClass::As_Reference(InfantryType type)\n{\n\treturn(*InfantryTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * InfantryTypeClass::Read_INI -- Fetches infantry override values from the INI database.      *\n *                                                                                             *\n *    This routine will retrieve the override values for this infantry type class object from  *\n *    the INI database specified.                                                              *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to retrieve the data from.                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry section for this type found and data retrieved from it?     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryTypeClass::Read_INI(CCINIClass & ini)\n{\n\tif (TechnoTypeClass::Read_INI(ini)) {\n\t\tIsFraidyCat = ini.Get_Bool(Name(), \"Fraidycat\", IsFraidyCat);\n\t\tIsCapture = ini.Get_Bool(Name(), \"Infiltrate\", IsCapture);\n\t\tIsBomber = ini.Get_Bool(Name(), \"C4\", IsBomber);\n\t\tIsDog = ini.Get_Bool(Name(), \"IsCanine\", IsDog);\n\t\tif (IsBomber) IsCapture = true;\n\t\tif (IsDog) IsLeader = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid InfantryTypeClass::Dimensions(int & width, int & height) const\n{\n#ifdef WIN32\n\twidth = 14;\n\theight = 20;\n#else\n\twidth = 12;\n\theight = 16;\n#endif\n}"
  },
  {
    "path": "REDALERT/INFANTRY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INFANTRY.CPP 2     3/03/97 10:35p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INFANTRY.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : October 28, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   InfantryClass::AI -- Handles the infantry non-graphic related AI processing.              *\n *   InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.   *\n *   InfantryClass::Assign_Destination -- Gives the infantry a movement destination.           *\n *   InfantryClass::Assign_Target -- Gives the infantry a combat target.                       *\n *   InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified. *\n *   InfantryClass::Can_Fire -- Can the infantry fire its weapon?                              *\n *   InfantryClass::Class_Of -- Returns the class reference for this object.                   *\n *   InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell                       *\n *   InfantryClass::Debug_Dump -- Displays debug information about infantry unit.              *\n *   InfantryClass::Detach -- Removes the specified target from targeting computer.            *\n *   InfantryClass::Do_Action -- Launches the infantry into an animation sequence.             *\n *   InfantryClass::Doing_AI -- Handles the animation AI processing.                           *\n *   InfantryClass::Draw_It -- Draws a unit object.                                            *\n *   InfantryClass::Edge_Of_World_AI -- Detects when infantry has left the map.                *\n *   InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.     *\n *   InfantryClass::Fear_AI -- Process any fear related affects on this infantry.              *\n *   InfantryClass::Fire_At -- Fires projectile from infantry unit.                            *\n *   InfantryClass::Firing_AI -- Handles firing and combat AI for the infantry.                *\n *   InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                   *\n *   InfantryClass::Get_Image_Data -- Fetches the image data for this infantry unit.           *\n *   InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.  *\n *   InfantryClass::InfantryClass -- The constructor for infantry objects.                     *\n *   InfantryClass::Init -- Initialize the infantry object system.                             *\n *   InfantryClass::Is_Ready_To_Random_Anima -- Checks to see if it is ready to perform an idle*\n *   InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                 *\n *   InfantryClass::Mission_Attack -- Intercept attack mission for special handling.           *\n *   InfantryClass::Movement_AI -- This routine handles all infantry movement logic.           *\n *   InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't o*\n *   InfantryClass::Paradrop -- Handles paradropping infantry.                                 *\n *   InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.   *\n *   InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                    *\n *   InfantryClass::Read_INI -- Reads units from scenario INI file.                            *\n *   InfantryClass::Response_Attack -- Plays infantry audio response to attack order.          *\n *   InfantryClass::Response_Move -- Plays infantry response to movement order.                *\n *   InfantryClass::Response_Select -- Plays infantry audio response due to being selected.    *\n *   InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                  *\n *   InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos\t                    *\n *   InfantryClass::Set_Primary_Facing -- Change infantry primary facing -- always and instantl*\n *   InfantryClass::Shape_Number -- Fetch the shape number for this infantry.                  *\n *   InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.      *\n *   InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                 *\n *   InfantryClass::Take_Damage -- Applies damage to the infantry unit.                        *\n *   InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                    *\n *   InfantryClass::What_Action -- Determines what action to perform for the cell specified.   *\n *   InfantryClass::What_Action -- Infantry units might be able to capture -- check.           *\n *   InfantryClass::Write_INI -- Store the infantry to the INI database.                       *\n *   InfantryClass::operator delete -- Returns the infantry object back to the free pool       *\n *   InfantryClass::operator new -- Allocates an infantry object from the free pool.           *\n *   InfantryClass::~InfantryClass -- Default destructor for infantry units.                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n/*\n** New sidebar for GlyphX multiplayer. ST - 8/7/2019 10:10AM\n*/\n#include \"SidebarGlyphx.h\"\n\n\nint const InfantryClass::HumanShape[32] = {0,0,7,7,7,7,6,6,6,6,5,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,1,1,1,1,1,0};\n\n\n/***************************************************************************\n** This is the array of constant data associated with infantry maneuvers. It\n**\tspecifies the frame rate as well as if the animation can be aborted.\n*/\n// interruptible, mobile, randomstart, rate\nDoStruct const InfantryClass::MasterDoControls[DO_COUNT] = {\n\t{true,\tfalse,\tfalse,\t0},\t// DO_STAND_READY\n\t{true,\tfalse,\tfalse,\t0},\t// DO_STAND_GUARD\n\t{true,\tfalse,\tfalse,\t0},\t// DO_PRONE\n\t{true,\ttrue,\t\ttrue,\t\t2},\t// DO_WALK\n\t{true,\tfalse,\tfalse,\t1},\t// DO_FIRE_WEAPON\n\t{false,\ttrue,\t\tfalse,\t2},\t// DO_LIE_DOWN\n\t{true,\ttrue,\t\ttrue,\t\t2},\t// DO_CRAWL\n\t{false,\tfalse,\tfalse,\t3},\t// DO_GET_UP\n\t{true,\tfalse,\tfalse,\t1},\t// DO_FIRE_PRONE\n\t{true,\tfalse,\tfalse,\t2},\t// DO_IDLE1\n\t{true,\tfalse,\tfalse,\t2},\t// DO_IDLE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GUN_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_EXPLOSION_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_EXPLOSION2_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GRENADE_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_FIRE_DEATH\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GESTURE1\n\t{false,\tfalse,\tfalse,\t2},\t// DO_SALUTE1\n\t{false,\tfalse,\tfalse,\t2},\t// DO_GESTURE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_SALUTE2\n\t{false,\tfalse,\tfalse,\t2},\t// DO_DOG_MAUL\n};\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * InfantryClass::Debug_Dump -- Displays debug information about infantry unit.                *\n *                                                                                             *\n *    This routine is used by the debug version to display pertinent information about the     *\n *    infantry unit.                                                                           *\n *                                                                                             *\n * INPUT:   mono  -- The monochrome screen to display the debug information to.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tmono->Set_Cursor(0, 0);\n\n\tmono->Print(Text_String(TXT_DEBUG_INFANTRY));\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", Doing);\n\tmono->Set_Cursor(8, 11);mono->Printf(\"%3d\", Fear);\n\n\tmono->Fill_Attrib(66, 13, 12, 1, IsTechnician ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 14, 12, 1, IsStoked ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(66, 15, 12, 1, IsProne ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tFootClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * InfantryClass::InfantryClass -- The constructor for infantry objects.                       *\n *                                                                                             *\n *    This is the constructor used when creating an infantry unit. All values are required     *\n *    except for facing and position. If these are absent, then the infantry is created in     *\n *    a state of limbo -- not placed upon the map.                                             *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass::InfantryClass(InfantryType classid, HousesType house) :\n\tFootClass(RTTI_INFANTRY, Infantry.ID(this), house),\n\tClass(InfantryTypes.Ptr((int)classid)),\n\tDoing(DO_NOTHING),\n\tComment(0),\n\tIsTechnician(false),\n\tIsStoked(false),\n\tIsProne(false),\n\tIsZoneCheat(false),\n\tWasSelected(false),\n\tFear(FEAR_NONE),\n\tStopDriverFrame(-1),\n\tLookCell(0)\n{\n\tHouse->Tracking_Add(this);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tIsCloakable = Class->IsCloakable;\n#endif\n\t/*\n\t**\tFor two shooters, clear out the second shot flag -- it will be set the first time\n\t**\tthe object fires. For non two shooters, set the flag since it will never be cleared\n\t**\tand the second shot flag tells the system that normal rearm times apply -- this is\n\t**\twhat is desired for non two shooters.\n\t*/\n\tif (Class->Is_Two_Shooter()) {\n\t\tIsSecondShot = false;\n\t} else {\n\t\tIsSecondShot = true;\n\t}\n\tStrength = Class->MaxStrength;\n\n\t/*\n\t**\tCivilians carry much less ammo than soldiers do.\n\t*/\n\tAmmo = Class->MaxAmmo;\n}\n\n\n/***********************************************************************************************\n * InfantryClass::~InfantryClass -- Default destructor for infantry units.                     *\n *                                                                                             *\n *    This is the default destructor for infantry type units. It will put the infantry into    *\n *    a limbo state if it isn't already in that state and the game is still active.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass::~InfantryClass(void)\n{\n\tif (GameActive && Class.Is_Valid()) {\n\n\t\t/*\n\t\t**\tRemove this member from any team it may be associated with. This must occur at the\n\t\t**\ttop most level of the inheritance hierarchy because it may call virtual functions.\n\t\t*/\n\t\tif (Team.Is_Valid()) {\n\t\t\tTeam->Remove(this);\n\t\t\tTeam = NULL;\n\t\t}\n\n\t\tHouse->Tracking_Remove(this);\n\t\tLimbo();\n\t}\n\tID = -1;\n}\n\n\n/***********************************************************************************************\n * InfantryClass::operator new -- Allocates an infantry object from the free pool.             *\n *                                                                                             *\n *    This will allocate an infantry object from the infantry object free pool. If there is    *\n *    no available slot, then NULL is returned.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated infantry object or NULL if none could be   *\n *          allocated.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * InfantryClass::operator new(size_t)\n{\n\tvoid * ptr = Infantry.Allocate();\n\tif (ptr != NULL) {\n\t\t((InfantryClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::operator delete -- Returns the infantry object back to the free pool         *\n *                                                                                             *\n *    This routine is used return an infantry object back to the system.                       *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the infantry object to delete.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((InfantryClass *)ptr)->IsActive = false;\n\t}\n\tInfantry.Free((InfantryClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Take_Damage -- Applies damage to the infantry unit.                          *\n *                                                                                             *\n *    This routine applies the damage specified to the infantry object. It is possible that    *\n *    this routine will DESTROY the infantry unit in the process.                              *\n *                                                                                             *\n * INPUT:   damage   -- The damage points to inflict.                                          *\n *                                                                                             *\n *          distance -- The distance from the damage center point to the object's center point.*\n *                                                                                             *\n *          warhead  -- The warhead type that is inflicting the damage.                        *\n *                                                                                             *\n *          source   -- Who is responsible for inflicting the damage.                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit destroyed by this damage?                              *\n *                                                                                             *\n * WARNINGS:   Since the infantry unit could be destroyed by this routine, be sure to check    *\n *             for this in the code that follows the call to Take_Damage().                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *\n *   03/31/1995 JLB : Revenge factor.                                                          *\n *=============================================================================================*/\nResultType InfantryClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tResultType res = RESULT_NONE;\n\n\t/*\n\t**\tProne infantry take only half damage, but never below one damage point.\n\t*/\n\tif (IsProne && damage > 0) {\n\t\tdamage = damage * Rule.ProneDamageBias;\n\t}\n\n\t/*\n\t** If we're taking damage from a dog, we have to decide if we're the\n\t** target of the dog.  Dogs don't spill collateral damage onto anyone\n\t** else, so if we're the target of a valid dog, take full damage, but if\n\t** we're not the target, or the dog doesn't exist, then take no damage.\n\t*/\n\tif (source != NULL && source->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)source)->Class->IsDog) {\n\t\tif (source->TarCom == As_Target()) {\n\t\t\tdamage = Strength;\n\t\t} else {\n\t\t\tdamage = 0;\n\t\t}\n\t}\n\tres = FootClass::Take_Damage(damage, distance, warhead, source, forced);\n\n\t/*\n\t** hack for dog: if you're hit by a dog, and you're the target, your\n\t** damage gets upped to max.\n\t*/\n\n\tif (res == RESULT_NONE) return(res);\n\n\tif (res == RESULT_DESTROYED) {\n\t\tif (*this == INFANTRY_TANYA) {\n\t\t\tIsTanyaDead = true;\n\t\t}\n\t\tDeath_Announcement(source);\n\t\tStop_Driver();\n\t\tStun();\n\t\tMission = MISSION_NONE;\n\t\tAssign_Mission(MISSION_GUARD);\n\t\tCommence();\n\n\t\tVocType sound;\n\t\tVocType altsound;\n\t\tsound = Sim_Random_Pick(VOC_SCREAM1, VOC_SCREAM11);\n\t\taltsound = VOC_YELL1;\n\t\tif (*this == INFANTRY_TANYA) {\n\t\t\tsound = altsound = VOC_TANYA_DIE;\n\t\t}\n\t\tif (Class->IsDog) {\n\t\t\tsound = altsound = VOC_DOG_HURT;\n\t\t}\n\n\t\t/*\n\t\t**\tThe type of warhead determines the animation the infantry\n\t\t**\twill perform when killed.\n\t\t*/\n\t\tbool delthis = false;\n\t\tTARGET us = As_Target();\n\t\tswitch (WarheadTypeClass::As_Pointer(warhead)->InfantryDeath) {\n\t\t\tdefault:\n\t\t\tcase 0:\n\t\t\t\tdelthis = true;\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_GUN_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_EXPLOSION_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tDo_Action(DO_GRENADE_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tSound_Effect(altsound, Coord);\n\t\t\t\tDo_Action(DO_FIRE_DEATH, true);\n\t\t\t\tbreak;\n\n\t\t\tcase 5:\n\t\t\t\tSound_Effect(sound, Coord);\n\t\t\t\tAnimType anim = ANIM_ELECT_DIE;\n\t\t\t\tif (Class->IsDog) anim = ANIM_DOG_ELECT_DIE;\n\t\t\t\tnew AnimClass(anim, Coord);\n\t\t\t\tdelthis = true;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (delthis) {\n\t\t\tdelete this;\n\t\t}\n\t\treturn(res);\n\t}\n\n\t/*\n\t**\tWhen infantry gets hit, it gets scared.\n\t*/\n\tif (res != RESULT_DESTROYED) {\n\t\tCOORDINATE source_coord = (source) ? source->Coord : NULL;\n\n\t\t/*\n\t\t**\tIf an engineer is damaged and it is just sitting there, then tell it\n\t\t**\tto go do something since it will definitely die if it doesn't.\n\t\t*/\n\t\tif (!House->IsHuman && *this == INFANTRY_RENOVATOR && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA)) {\n\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t}\n\n\t\tif (source != NULL) {\n\t\t\tScatter(source_coord);\n\t\t}\n\n\t\tif (source != NULL && Fear < FEAR_SCARED) {\n\t\t\tif (Class->IsFraidyCat) {\n\t\t\t\tFear = FEAR_PANIC;\n\t\t\t} else {\n\t\t\t\tFear = FEAR_SCARED;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncrease the fear of the infantry by a bit. The fear increases more\n\t\t\t**\tquickly if the infantry is damaged.\n\t\t\t*/\n\t\t\tint morefear = FEAR_ANXIOUS;\n\t\t\tif (Health_Ratio() > Rule.ConditionRed) morefear /= 2;\n\t\t\tif (Health_Ratio() > Rule.ConditionYellow) morefear /= 2;\n\t\t\tFear = FearType(min((int)Fear + morefear, FEAR_MAXIMUM));\n\t\t}\n\t}\n\treturn(res);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Shape_Number -- Fetch the shape number for this infantry.                    *\n *                                                                                             *\n *    This will determine the shape number to use for this infantry soldier. The shape number  *\n *    is relative to the shape file associated with this infantry unit.                        *\n *                                                                                             *\n * INPUT:   Window we will be drawing into                                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the shape number for this infantry object to be used when drawing.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *   9/4/2019 1:45PM ST : Added window parameter                                               *\n *=============================================================================================*/\nint InfantryClass::Shape_Number(WindowNumberType window) const\n{\n\t/*\n\t**\tFetch the shape pointer to use for the infantry. This is controlled by what\n\t**\tchoreograph sequence the infantry is performing, it's facing, and whether it\n\t**\tis prone.\n\t*/\n\tDoType doit = Doing;\n\tif (doit == DO_NOTHING) doit = DO_STAND_READY;\n\n\t/*\n\t** Hold the walk pose for a couple of frames after we come to a stop to try and avoid the problem where a moving infantry\n\t** goes into the stand pose for a single frame when pausing in the assigned cell destination. ST - 9/4/2019 1:39PM\n\t*/\n\tif (doit == DO_STAND_READY) {\n\t\tif (window == WINDOW_VIRTUAL) {\n\t\t\tif (StopDriverFrame != -1) {\n\t\t\t\tif (Frame - StopDriverFrame <= 2) {\n\t\t\t\t\tif (Path[0] != FACING_NONE) {\n\t\t\t\t\t\tdoit = DO_WALK;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\t\t\t  \n\t}\n\n\t/*\n\t** The animation frame numbers may be different when rendering in legacy mode vs. exporting for render in GlyphX. ST - 9/5/2019 12:34PM\n\t*/\n\tconst DoInfoStruct *do_controls = (window == WINDOW_VIRTUAL) ? Class->DoControlsVirtual : Class->DoControls;\n\tif (window != WINDOW_VIRTUAL && !IsOwnedByPlayer && *this == INFANTRY_SPY) {\n\t\tdo_controls = InfantryTypeClass::As_Reference(INFANTRY_E1).DoControls;\n\t}\n\t\t\t\n\t/*\n\t**\tThe infantry shape is always modulo the number of animation frames\n\t**\tof the action stage that the infantry is doing.\n\t*/\n\tint shapenum = Fetch_Stage() % max(do_controls[doit].Count, 1);\n\n\t/*\n\t**\tIf facing makes a difference, then the shape number will be incremented\n\t**\tby the facing accordingly.\n\t*/\n\tif (do_controls[doit].Jump) {\n\t\tshapenum += HumanShape[Dir_To_32(PrimaryFacing.Current())] * do_controls[doit].Jump;\n\t}\n\t\n\t/*\n\t**\tFinally, the shape number is biased according to the starting frame number for\n\t**\tthat action in the infantry shape file.\n\t*/\n\tshapenum += do_controls[doit].Frame;\n\n\t/*\n\t**\tReturn with the final infantry shape number.\n\t*/\n\treturn(shapenum);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Draw_It -- Draws a unit object.                                              *\n *                                                                                             *\n *    This routine is the one that actually draws a unit object. It displays the unit          *\n *    according to its current state flags and centered at the location specified.             *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y coordinate of where to draw the unit.                         *\n *                                                                                             *\n *          window   -- The clipping window to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/20/1994 JLB : Created.                                                                 *\n *   06/27/1994 JLB : Takes a window parameter.                                                *\n *   08/15/1994 JLB : Converted to infantry support.                                           *\n *   08/14/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid InfantryClass::Draw_It(int x, int y, WindowNumberType window) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tVerify the legality of the unit class by seeing if there is shape imagery for it. If\n\t**\tthere is no shape image, then it certainly can't be drawn -- bail.\n\t*/\n\tvoid const * shapefile = Get_Image_Data();\n\n\tif (shapefile == NULL) return;\n\n\ty += 4;\n\tx -= 2;\n\n\t/*\n\t**\tActually draw the root body of the unit.\n\t*/\n\tTechno_Draw_Object(shapefile, Shape_Number(window), x, y, window);\n\n\tFootClass::Draw_It(x, y, window);\n}\n\nextern bool MPSuperWeaponDisable;\n\n/***********************************************************************************************\n * InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.     *\n *                                                                                             *\n *    This routine will handle any special operations that need to be performed once each      *\n *    cell travelled. This includes radioing a transport that it is now clear and the          *\n *    transport is free to leave.                                                              *\n *                                                                                             *\n * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   03/01/1995 JLB : Capture building options.                                                *\n *   05/31/1995 JLB : Capture is always successful now.                                        *\n *=============================================================================================*/\nvoid InfantryClass::Per_Cell_Process(PCPType why)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tBStart(BENCH_PCP);\n\tCellClass * cellptr = &Map[Coord];\n\n\tif (why == PCP_END) {\n\n\t\t/*\n\t\t**\tIf the infantry unit is entering a cell that contains the building it is trying to\n\t\t**\tcapture, then capture it.\n\t\t*/\n\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\tTechnoClass * tech = cellptr->Cell_Building();\n\t\t\tif (tech != NULL) {\n\t\t\t\tif ((tech->As_Target() == NavCom || tech->As_Target() == TarCom) && !tech->Can_Capture()) {\n\t\t\t\t\ttech = NULL;\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttech = cellptr->Cell_Techno();\n\t\t\t}\n\t\t\tif (tech != NULL && (tech->As_Target() == NavCom || tech->As_Target() == TarCom)) {\n\t\t\t\tif (*this == INFANTRY_RENOVATOR) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAn engineer will either mega-repair a friendly or allied\n\t\t\t\t\t**\tbuilding or it will damage/capture an enemy building. Whether\n\t\t\t\t\t**\tit damages or captures depends on how badly damaged the\n\t\t\t\t\t**\tenemy building is.\n\t\t\t\t\t*/\n#ifdef FIXIT_ENGINEER_CAPTURE\n\t\t\t\t\tif (House->Is_Ally(tech)) {\n#else\n\t\t\t\t\tif (tech->House->Is_Ally(House)) {\n#endif\n\t\t\t\t\t\tif (tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttech->Renovate();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbool iscapturable = false;\n\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\tiscapturable = tech->Can_Capture();\n\t\t\t\t\t\t}\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (tech->Health_Ratio() <= EngineerCaptureLevel && iscapturable) {\n#else\n\t\t\t\t\t\tif (tech->Health_Ratio() <= Rule.ConditionRed && iscapturable) {\n#endif\n\t\t\t\t\t\t\tif (tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttech->House->IsThieved = true;\n\t\t\t\t\t\t\ttech->Captured(House);\n\t\t\t\t\t\t} else {\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tint damage = min( (short)((int)(tech->Techno_Type_Class()->MaxStrength) * EngineerDamage), tech->Strength-1);\n#else\n\t\t\t\t\t\t\tint damage = min( (tech->Techno_Type_Class()->MaxStrength) / 3, tech->Strength-1);\n#endif\n\t\t\t\t\t\t\ttech->Take_Damage(damage, 0, WARHEAD_HE, this, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tif (*this != INFANTRY_SPY && tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_PLAYER_ENTERED, this);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (*this == INFANTRY_SPY) {\n\t\t\t\t\t\tint housespy = (1 << (House->Class->House));\n//\t\t\t\t\t\ttech->House->IsSpied = true;\n\n\t\t\t\t\t\tif (tech->Trigger.Is_Valid()) {\n\t\t\t\t\t\t\ttech->Trigger->Spring(TEVENT_SPIED, this);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (IsOwnedByPlayer) Speak(VOX_BUILDING_INFILTRATED);\n\n\t\t\t\t\t\ttech->Mark(MARK_OVERLAP_UP);\n\t\t\t\t\t\ttech->SpiedBy |= housespy;\n\t\t\t\t\t\ttech->Mark(MARK_OVERLAP_DOWN);\n\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\tStructType build = *(BuildingClass *)tech;\n\t\t\t\t\t\t\tif (build == STRUCT_RADAR /* || build == STRUCT_EYE */ ) {\n\t\t\t\t\t\t\t\ttech->House->RadarSpied |= housespy;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL || !MPSuperWeaponDisable) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t// If they're spying on a sub pen, give 'em a sonar pulse\n\t\t\t\t\t\t\t\tif (build == STRUCT_SUB_PEN) {\n\t\t\t\t\t\t\t\t\tHouse->SuperWeapon[SPC_SONAR_PULSE].Enable(false, true, false);\n\t\t\t\t\t\t\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\t\t\t\tif (House->IsHuman) {\n\t\t\t\t\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_SONAR_PULSE, House);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_SONAR_PULSE);\n\t\t\t\t\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// If they're spying on an airfield, they get Parabombs\n\t\t\t\t\t\t\t\tif (build == STRUCT_AIRSTRIP) {\n\t\t\t\t\t\t\t\t\tHouse->SuperWeapon[SPC_PARA_BOMB].Enable(true, true, false);\n\t\t\t\t\t\t\t\t\t// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM\n\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\t\t\t\t\t\t\t\tif (House->IsHuman) {\n\t\t\t\t\t\t\t\t\t\t\tSidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_BOMB, House);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tif (IsOwnedByPlayer) {\n\t\t\t\t\t\t\t\t\t\t\tMap.Add(RTTI_SPECIAL, SPC_PARA_BOMB);\n\t\t\t\t\t\t\t\t\t\t\tMap.Column[1].Flag_To_Redraw();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif (*this == INFANTRY_THIEF) {\t// Thief just raided a storage facility\n\t\t\t\t\t\t\ttech->House->IsThieved = true;\n\n\t\t\t\t\t\t\tif (tech->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\tBuildingClass * bldg = (BuildingClass *)tech;\n\t\t\t\t\t\t\t\tif (bldg->Class->Capacity) {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** If we just raided a storage facility (refinery or silo)\n\t\t\t\t\t\t\t\t\t** then give the thief up to half the capacity of the\n\t\t\t\t\t\t\t\t\t** storage facility.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (IsOwnedByPlayer || bldg->IsOwnedByPlayer) Speak(VOX_MONEY_STOLEN);\n#ifdef OBSOLETE\n\t\t\t\t\t\t\t\t\tlong capacity = bldg->Class->Capacity * 256;\n\t\t\t\t\t\t\t\t\tcapacity /= (bldg->House->Tiberium+1);\n\t\t\t\t\t\t\t\t\tint bldgcap = bldg->Class->Capacity;\n\n\t\t\t\t\t\t\t\t\tlong cash = (bldgcap * 256) / (capacity+1);\n\t\t\t\t\t\t\t\t\tif (cash > (bldgcap / 2)) cash = bldgcap / 2;\n#else\n\t\t\t\t\t\t\t\t\tlong cash = bldg->House->Available_Money() / 2;\n#endif\n\t\t\t\t\t\t\t\t\tbldg->House->Spend_Money(cash);\n\t\t\t\t\t\t\t\t\tHouse->Refund_Money(cash);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\tdelete this;\n\t\t\t\treturn;\n\n\t\t\t} else {\n\n\t#ifdef OBSOLETE\n\t\t\t\t// are we trying to repair a bridge?\n\t\t\t\tif (Is_Target_Cell(TarCom) ) {\n\t\t\t\t\tCELL cell = Coord_Cell(Coord);\n\t\t\t\t\tif (cell == ::As_Cell(NavCom)) {\n\t\t\t\t\t\tTemplateType tt = cellptr->TType;\n\t\t\t\t\t\tint icon = cellptr->TIcon;\n\t\t\t\t\t\tint w = TemplateTypeClass::As_Reference(cellptr->TType).Width;\n\t\t\t\t\t\tint h = TemplateTypeClass::As_Reference(cellptr->TType).Height;\n\n\t\t\t\t\t\tcell -= icon % w;\n\t\t\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\t\t\tif (tt == TEMPLATE_BRIDGE1D || tt == TEMPLATE_BRIDGE2D) {\n\t\t\t\t\t\t\tnew TemplateClass(TemplateType(cellptr->TType-1), cell);\n\t\t\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Trying to repair multi-segment bridge.  Look for the\n\t\t\t\t\t\t\t// start tile, then fix it, and determine the direction to\n\t\t\t\t\t\t\t// go in and repair it all that way.\n\t\t\t\t\t\t\tTemplateType newtt = TEMPLATE_BRIDGE_1A;\n\t\t\t\t\t\t\tint xmov = -1;\t// coords to move to for next template\n\t\t\t\t\t\t\tint ymov = 2;\n\t\t\t\t\t\t\tbool valid = false;\n\t\t\t\t\t\t\tswitch (tt) {\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_1C:\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_2B:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_2C:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_2A;\n\t\t\t\t\t\t\t\t\txmov = 2;\n\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3D:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3E:\n\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\txmov = 2;\n\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Did we find a valid repairable bridge piece?\n\t\t\t\t\t\t\tif (valid) {\n\t\t\t\t\t\t\t\tbool doing = true;\n\t\t\t\t\t\t\t\twhile (doing) {\n\t\t\t\t\t\t\t\t\tnew TemplateClass(TemplateType(newtt), cell);\n\t\t\t\t\t\t\t\t\tcell += (MAP_CELL_W * ymov) + xmov;\n\t\t\t\t\t\t\t\t\tif (xmov < 0) {\n\t\t\t\t\t\t\t\t\t\txmov = -1;\n\t\t\t\t\t\t\t\t\t\tymov = 1;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\txmov = 1;\n\t\t\t\t\t\t\t\t\t\tymov = -1;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcellptr = &Map[cell];\n\t\t\t\t\t\t\t\t\ttt = cellptr->TType;\n\t\t\t\t\t\t\t\t\tif ((tt >= TEMPLATE_BRIDGE_3B && tt <= TEMPLATE_BRIDGE_3F) ||\n\t\t\t\t\t\t\t\t\t\t  tt == TEMPLATE_BRIDGE_1B || tt == TEMPLATE_BRIDGE_1C ||\n\t\t\t\t\t\t\t\t\t\t  tt == TEMPLATE_BRIDGE_2B || tt == TEMPLATE_BRIDGE_2C ) {\n\n\t\t\t\t\t\t\t\t\t\tif (tt >= TEMPLATE_BRIDGE_3B) {\n\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_3A;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif (tt < TEMPLATE_BRIDGE_2A) {\n\t\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_1A;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tnewtt = TEMPLATE_BRIDGE_2A;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\ticon = cellptr->TIcon;\n\t\t\t\t\t\t\t\t\t\tw = TemplateTypeClass::As_Reference(cellptr->TType).Width;\n\t\t\t\t\t\t\t\t\t\th = TemplateTypeClass::As_Reference(cellptr->TType).Height;\n\n\t\t\t\t\t\t\t\t\t\tcell -= icon % w;\n\t\t\t\t\t\t\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdoing = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\t\t\t\tdelete this;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t#endif\n\t\t\t\t\tif (!Target_Legal(NavCom)) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t\tif (Map[Coord].Cell_Building()) {\n\t\t\t\t\t\t\tScatter(0, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t#ifdef OBSOLETE\n\t\t\t\t}\n\t#endif\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tInfantry entering a transport vehicle will break radio contact\n\t\t**\tat attach itself to the transporter.\n\t\t*/\n\t\tTechnoClass * techno = Contact_With_Whom();\n\t\tif (Mission == MISSION_ENTER && techno != NULL && Coord_Cell(Coord) == Coord_Cell(techno->Coord) && techno == As_Techno(NavCom)) {\n\t\t\tif (Transmit_Message(RADIO_IM_IN) == RADIO_ATTACH) {\n\t\t\t\tLimbo();\n\t\t\t\ttechno->Attach(this);\n\t\t\t}\n\t\t\tBEnd(BENCH_PCP);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the infantry unit is entering a cell that contains the building it is trying to\n\t\t**\tsabotage, then sabotage it.\n\t\t*/\n\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\tBuildingClass * building = cellptr->Cell_Building();\n\t\t\tif (building != NULL && building->As_Target() == NavCom) {\n\t\t\t\tif (!building->IronCurtainCountDown && building->Mission != MISSION_DECONSTRUCTION) {\n\t\t\t\t\tbuilding->IsGoingToBlow = true;\n\t\t\t\t\tbuilding->Clicked_As_Target(PlayerPtr->Class->House, (Rule.C4Delay * TICKS_PER_MINUTE) / 2); // 2019/09/20 JAS - Added record of who clicked on the object\n\t\t\t\t\tbuilding->Clicked_As_Target(building->Owner(), (Rule.C4Delay * TICKS_PER_MINUTE) / 2);\n\t\t\t\t\tbuilding->CountDown = Rule.C4Delay * TICKS_PER_MINUTE;\n\t\t\t\t\tbuilding->WhomToRepay = As_Target();\n\t\t\t\t}\n\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\tDo_Uncloak();\n\t\t\t\tArm = Rearm_Delay(true);\n\t\t\t\tScatter(building->Center_Coord(), true, true);\t// RUN AWAY!\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tif (::As_Target(Coord_Cell(Center_Coord())) == NavCom) {\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, this, WARHEAD_HE);\n\n\t\t\t\t\tStop_Driver();\n\t\t\t\t\tScatter(Adjacent_Cell(Coord, PrimaryFacing), true, true);\n\t\t\t\t\tAssign_Mission(MISSION_MOVE);\n\n\t\t\t\t\tCELL cell = Coord_Cell(Center_Coord());\n\t\t\t\t\tCellClass * cellptr = &Map[cell];\n\t\t\t\t\tif (!Target_Legal(NavCom) || Map[As_Cell(NavCom)].Land_Type() == LAND_WATER) {\n\t\t\t\t\t\tMark(MARK_DOWN);\t\t// Needed only so that Tanya will get destroyed by the explosion.\n\t\t\t\t\t}\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, NULL, WARHEAD_HE);\n\t\t\t\t\tExplosion_Damage(Coord, Rule.BridgeStrength, NULL, WARHEAD_HE);\n\t\t\t\t\tif (!IsActive) {\n\t\t\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tMark(MARK_DOWN);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this unit is on a teather, then cut it at this time so that\n\t\t**\tthe \"parent\" unit is free to proceed. Note that the parent\n\t\t**\tunit might actually be a building.\n\t\t*/\n\t\tif (IsTethered) {\n\t\t\tTransmit_Message(RADIO_UNLOADED);\n\t\t\tif (House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_UKRAINE) {\n\t\t\t\tDo_Action(DO_GESTURE1);\n\t\t\t} else  {\n\t\t\t\tDo_Action(DO_GESTURE2);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial voice play.\n\t\t\t*/\n\t\t\tif (*this ==  INFANTRY_TANYA) {\n\t\t\t\tSound_Effect(VOC_TANYA_LAUGH, Coord);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the cell is now full of infantry, tell them all to scatter\n\t\t\t**\tin order to make room for more.\n\t\t\t*/\n\t\t\tif ((cellptr->Flag.Composite & 0x01F) == 0x01F) {\n\t\t\t\tcellptr->Incoming(0, true, true);\n//\t\t\t\tcellptr->Incoming(0, true);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tWhen the infantry reaches the center of the cell, it may begin a new mission.\n\t\t*/\n\t\tif (MissionQueue == MISSION_NONE && !Target_Legal(NavCom) && !Target_Legal(TarCom) && !In_Radio_Contact()) {\n\t\t\tEnter_Idle_Mode();\n\t\t}\n\t\tCommence();\n\n\t\t/*\n\t\t** If entering a cell with a land mine in it, blow up the mine.\n\t\t*/\n\t\tBuildingClass * bldng = cellptr->Cell_Building();\n\t\tif (bldng != NULL && *bldng == STRUCT_APMINE) {\n\t\t\t/*\n\t\t\t** Show the animation and get rid of the land mine\n\t\t\t*/\n\t\t\tCOORDINATE blcoord = bldng->Center_Coord();\n\t\t\tnew AnimClass(Combat_Anim(Rule.APMineDamage, WARHEAD_HE, cellptr->Land_Type()), blcoord);\n\t\t\tdelete bldng;\n\t\t\tint damage;\n\t\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\t\tInfantryClass * obj = Infantry.Ptr(index);\n\t\t\t\tif (obj != NULL && !obj->IsInLimbo) {\n\t\t\t\t\tint dist = ::Distance(obj->Coord, blcoord);\n\t\t\t\t\tif (dist <= 0xC0) {\n\t\t\t\t\t\tdamage = Rule.APMineDamage;\n\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!IsActive) {\n\t\t\t\tBEnd(BENCH_PCP);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf the last cell we looked from isn't adjacent to our current cell,\n\t\t**\tperform a full look.\n\t\t*/\n\t\tCELL cell = Coord_Cell(Coord);\n\t\tif (::Distance(Cell_X(cell), Cell_Y(cell), Cell_X(LookCell), Cell_Y(LookCell)) > 1) {\n\t\t\tLook(false);\n\t\t} else {\n\t\t\tLook(true);\n\t\t}\n\n#if 1\n/*\n**\tIf after all is said and done, the unit finishes its move on an impassable cell, then\n**\tit must presume that it is in the case of a unit driving onto a bridge that blows up\n**\tbefore the unit completes it's move. In such a case the unit should have been destroyed\n**\tanyway, so blow it up now.\n*/\nLandType land = Map[Coord].Land_Type();\nif (!IsDriving && !Class->IsBomber && (land == LAND_ROCK || land == LAND_WATER || land == LAND_RIVER)) {\n\tint damage = Strength;\n\tTake_Damage(damage, 0, WARHEAD_AP, NULL, true);\n\treturn;\n}\n#endif\n\n\t}\n\n\tif (IsActive) {\n\t\tFootClass::Per_Cell_Process(why);\n\t}\n\tBEnd(BENCH_PCP);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Detach -- Removes the specified target from targeting computer.              *\n *                                                                                             *\n *    This is a support routine that removes the target specified from any targeting or        *\n *    navigation computers. When a target is destroyed or removed from the game system,        *\n *    the target must be removed from any tracking systems of the other units. This routine    *\n *    handles removal for infantry units.                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from the infantry unit's tracking systems.        *\n *                                                                                             *\n *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Detach(TARGET target, bool all)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (TarCom == target) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tIsFiring = false;\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n\tFootClass::Detach(target, all);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Init -- Initialize the infantry object system.                               *\n *                                                                                             *\n *    This routine will force the infantry object system into its empty initial state. It      *\n *    is called when the scenario needs to be cleared in preparation for a scenario load.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Init(void)\n{\n\tInfantry.Free_All();\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Assign_Destination -- Gives the infantry a movement destination.             *\n *                                                                                             *\n *    This routine updates the infantry's navigation computer so that the infantry will        *\n *    travel to the destination target specified.                                              *\n *                                                                                             *\n * INPUT:   target   -- The target to have the infantry unit move to.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Assign_Destination(TARGET target)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tSpecial flag so that infantry will start heading in the right direction immediately.\n\t*/\n\tif (IsDriving && !IsFormationMove && Target_Legal(target) && Map[Center_Coord()].Is_Clear_To_Move(Class->Speed, true, false)) {\n\t\tStop_Driver();\n\t}\n\n\t/*\n\t**\tWhen telling an infantry soldier to move to a location twice, then this\n\t**\tmeans that movement is more important than safety. Get up and run!\n\t*/\n\tif (House->IsHuman && Target_Legal(target) && NavCom == target && IsProne && !Class->IsFraidyCat && !Class->IsDog) {\n\t\tDo_Action(DO_GET_UP);\n\t}\n\n\t/*\n\t** If telling a dog to attack a human, start the dog running\n\t*/\n\tTechnoClass * tech = As_Techno(target);\n\n\t/*\n\t**\tHandle entry logic here.\n\t*/\n\tif (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {\n\n\t\t/*\n\t\t**\tIf not already in radio contact (presumed with the transport), then\n\t\t**\teither try to establish contact if allowed, or just move close and\n\t\t**\twait until radio contact can be established.\n\t\t*/\n\t\tif (!In_Radio_Contact()) {\n\t\t\tTechnoClass * techno = As_Techno(target);\n\t\t\tif (techno != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the transport is already in radio contact. If so, then just move\n\t\t\t\t**\ttoward the transport and try to establish contact at a later time.\n\t\t\t\t*/\n\t\t\t\tif (techno->In_Radio_Contact()) {\n// TCTCTC -- call for an update from the transport to get a good rendezvous position.\n\n\t\t\t\t\tArchiveTarget = target;\n\t\t\t\t} else {\n\t\t\t\t\tif (Transmit_Message(RADIO_HELLO, techno) == RADIO_ROGER) {\n\t\t\t\t\t\tif (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {\n\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t//BG: keep retransmitted navcom from radio-move-here.\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tPath[0] = FACING_NONE;\n\t\t}\n\t} else {\n\t\tPath[0] = FACING_NONE;\n\t}\n\tFootClass::Assign_Destination(target);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Assign_Target -- Gives the infantry a combat target.                         *\n *                                                                                             *\n *    This routine will update the infantry's targeting computer so that it will try to        *\n *    attack the target specified. This might result in it moving to be within range and thus  *\n *    also cause adjustment of the navigation computer.                                        *\n *                                                                                             *\n * INPUT:   target   -- The target that this infantry should attack.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   06/30/1995 JLB : Tries to capture target if possible.                                     *\n *=============================================================================================*/\nvoid InfantryClass::Assign_Target(TARGET target)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tPath[0] = FACING_NONE;\n\tif (Class->IsDog) {\n\t\tif (::As_Object(target) && ::As_Object(target)->What_Am_I() != RTTI_INFANTRY) {\n\t\t\ttarget = TARGET_NONE;\n\t\t}\n\t}\n\tFootClass::Assign_Target(target);\n\n\t/*\n\t**\tIf this is an infantry that can only capture, then also assign its destination to the\n\t**\ttarget specified.\n\t*/\n\tif (!Target_Legal(NavCom) && Class->IsCapture && !Is_Weapon_Equipped()) {\n\t\tBuildingClass const * building = As_Building(target);\n\t\tif (building != NULL && building->Can_Capture()) {\n\t\t\tAssign_Destination(target);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::AI -- Handles the infantry non-graphic related AI processing.                *\n *                                                                                             *\n *    This routine is used to handle the non-graphic AI processing the infantry requires.      *\n *    Call this routine ONCE per game frame.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/08/1994 JLB : Created.                                                                 *\n *   08/14/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid InfantryClass::AI(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tFootClass::AI();\n\n\tif (!IsActive) {\n\t\treturn;\n\t}\n\n\tif (IsUnloading) Mark(MARK_CHANGE_REDRAW);\n\n\t/*\n\t**\tInfantry that are not on the ground should always be redrawn. Such is\n\t**\tthe case when they are parachuting to the ground.\n\t*/\n\tif (In_Which_Layer() != LAYER_GROUND) {\n\t\tMark(MARK_CHANGE);\n\t}\n\n\t/*\n\t**\tSpecial hack to make sure that if this infantry is in firing animation, but the\n\t**\tstage class isn't set, then abort the firing flag.\n\t*/\n\tif (IsFiring && Fetch_Rate() == 0) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tIsFiring = false;\n\t\tDo_Action(DO_STAND_READY);\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Edge_Of_World_AI()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tAct on new orders if the unit is at a good position to do so.\n\t*/\n\tif (!IsFiring && !IsFalling && !IsDriving && (Doing == DO_NOTHING || MasterDoControls[Doing].Interrupt)) {\n\t\tif (Mission == MISSION_NONE && MissionQueue == MISSION_NONE) Enter_Idle_Mode();\n\t\tCommence();\n\t}\n\n\t/*\n\t**\tSpecial hack to make sure the dog never attacks a cell.\n\t*/\n\tif (Class->IsDog && Target_Legal(TarCom) && Is_Target_Cell(TarCom)) {\n\t\tAssign_Target(TARGET_NONE);\n\t}\n\n\t/*\n\t**\tHandle any infantry fear logic or related actions.\n\t*/\n\tFear_AI();\n\n\t/*\n\t**\tSpecial victory dance action.\n\t*/\n\tif (!Target_Legal(NavCom) && !IsProne && IsStoked && Comment == 0) {\n\t\tIsStoked = false;\n\t\tDo_Action(Percent_Chance(50) ? DO_GESTURE1 : DO_GESTURE2);\n\t}\n\n\t/*\n\t**\tDetermine if this infantry unit should fire off an\n\t**\tattack or not.\n\t*/\n\tFiring_AI();\n\n\t/*\n\t**\tHandle the completion of the animation sequence.\n\t*/\n\tDoing_AI();\n\n\t/*\n\t**\tPerform movement operations at this time.\n\t*/\n\tMovement_AI();\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified.   *\n *                                                                                             *\n *    This routine is used to examine the cell specified and determine if the infantry is      *\n *    allowed to enter it. It is used by the path finding algorithm.                           *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns the type of blockage in the cell.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMoveType InfantryClass::Can_Enter_Cell(CELL cell, FacingType ) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** If we are moving into an illegal cell, then we can't do that.\n\t*/\n\tif ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);\n\n\t/*\n\t**\tIf moving off the edge of the map, then consider that an illegal move.\n\t*/\n\tif (!ScenarioInit && !Map.In_Radar(cell) && !Is_Allowed_To_Leave_Map()) {\n\t\treturn(MOVE_NO);\n\t}\n\n\tCellClass * cellptr = &Map[cell];\n\n\t/*\n\t**\tWalls are considered impassable for infantry UNLESS the wall has a hole\n\t**\tin it.\n\t*/\n\tif (cellptr->Overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const & otype = OverlayTypeClass::As_Reference(cellptr->Overlay);\n\n\t\tif (otype.IsCrate && !((Session.Type == GAME_NORMAL) ? House->IsPlayerControl : House->IsHuman) && Session.Type == GAME_NORMAL) {\n\t\t\treturn(MOVE_NO);\n\t\t}\n\n\t\tif (otype.IsWall) {\n\t\t\tif ((cellptr->OverlayData / 16) != otype.DamageLevels) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the wall can be destroyed, then return this fact instead of\n\t\t\t\t**\ta complete failure to enter.\n\t\t\t\t*/\n\t\t\t\tif (Is_Weapon_Equipped() && Class->PrimaryWeapon->Is_Wall_Destroyer()) {\n\t\t\t\t\treturn(MOVE_DESTROYABLE);\n\t\t\t\t}\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Loop through all of the objects in the square setting a bit\n\t** for how they affect movement.\n\t*/\n\tMoveType retval = MOVE_OK;\n\tObjectClass * obj = cellptr->Cell_Occupier();\n\twhile (obj != NULL) {\n\n\t\tif (obj != this) {\n\n\t\t\t/*\n\t\t\t**\tAlways allow movement if the cell is the object to be captured or sabotaged.\n\t\t\t*/\n\t\t\tif (((Mission == MISSION_ENTER && In_Radio_Contact()) || Mission == MISSION_CAPTURE || Mission == MISSION_SABOTAGE) &&\n\t\t\t\t(obj->As_Target() == NavCom || obj->As_Target() == TarCom)) {\n\n\t\t\t\treturn(MOVE_OK);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tGuard area should not allow the guarding unit to enter the cell with the\n\t\t\t**\tguarded unit.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_GUARD_AREA && ArchiveTarget == obj->As_Target() && Is_Target_Unit(ArchiveTarget)) {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If object is a land mine, allow movement\n\t\t\t*/\n\t\t\tif (obj->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_AVMINE) {\n\t\t\t\t\tobj = obj->Next;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tif (!Rule.IsMineAware || !((BuildingClass *)obj)->House->Is_Ally(House)) {\n\t\t\t\t\t\tif ((*(BuildingClass *)obj) == STRUCT_APMINE) {\n\t\t\t\t\t\t\tobj = obj->Next;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSpecial case check so that a landed aircraft that is in radio contact, will not block\n\t\t\t**\ta capture attempt. It is presumed that this case happens when a helicopter is landed\n\t\t\t**\tat a helipad.\n\t\t\t*/\n//\t\t\tif ((Mission != MISSION_CAPTURE && Mission != MISSION_SABOTAGE) || obj->What_Am_I() != RTTI_AIRCRAFT || !((AircraftClass *)obj)->In_Radio_Contact()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial check to always allow entry into the building that this infantry\n\t\t\t\t**\tis trying to capture.\n\t\t\t\t*/\n//\t\t\t\tif (obj->What_Am_I() == RTTI_BUILDING || obj->What_Am_I() == RTTI_AIRCRAFT || obj->What_Am_I() == RTTI_UNIT) {\n//\t\t\t\t\tif ((Mission == MISSION_CAPTURE || Mission == MISSION_SABOTAGE) && (obj->As_Target() == NavCom || obj->As_Target() == TarCom)) {\n//\t\t\t\t\t\treturn(MOVE_OK);\n//\t\t\t\t\t}\n//\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial check to always allow entry into the building that this infantry\n\t\t\t\t**\tis trying to capture.\n\t\t\t\t*/\n\t\t\t\tif (Mission == MISSION_ENTER && obj->As_Target() == NavCom && IsTethered) {\n\t\t\t\t\treturn(MOVE_OK);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAllied objects block movement using different rules than for enemy\n\t\t\t\t**\tobjects.\n\t\t\t\t*/\n\t\t\t\tif (House->Is_Ally(obj) || ScenarioInit) {\n\t\t\t\t\tswitch (obj->What_Am_I()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tA unit blocks as either a moving blockage or a stationary temp blockage.\n\t\t\t\t\t\t**\tThis depends on whether the unit is currently moving or not.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\tif (((UnitClass *)obj)->IsDriving || Target_Legal(((UnitClass *)obj)->NavCom)) {\n\t\t\t\t\t\t\t\tif (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (retval < MOVE_TEMP) retval = MOVE_TEMP;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAircraft and buildings always block movement. If for some reason there is an\n\t\t\t\t\t\t**\tallied terrain object, that blocks movement as well.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase RTTI_TERRAIN:\n\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\treturn(MOVE_NO);\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCloaked enemy objects are not considered if this is a Find_Path()\n\t\t\t\t\t**\tcall.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!obj->Is_Techno() || !((TechnoClass *)obj)->Is_Cloaked(this)) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAny non-allied blockage is considered impassible if the infantry\n\t\t\t\t\t\t**\tis not equipped with a weapon.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Combat_Damage() <= 0) return(MOVE_NO);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSome kinds of terrain are considered destroyable if the infantry is equipped\n\t\t\t\t\t\t**\twith the weapon that can destroy it. Otherwise, the terrain is considered\n\t\t\t\t\t\t**\timpassable.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tswitch (obj->What_Am_I()) {\n\t\t\t\t\t\t\tcase RTTI_TERRAIN:\n#ifdef OBSOLETE\n\t\t\t\t\t\t\t\tif (((TerrainClass *)obj)->Class->Armor == ARMOR_WOOD &&\n\t\t\t\t\t\t\t\t\t\tClass->PrimaryWeapon->WarheadPtr->IsWoodDestroyer) {\n\n\t\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn(MOVE_NO);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n#else\n\t\t\t\t\t\t\t\treturn(MOVE_NO);\n#endif\n\t\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\t\tif ( *(InfantryClass *)obj == INFANTRY_SPY && !Class->IsDog) {\n\t\t\t\t\t\t\t\t\tretval = MOVE_TEMP;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// otherwise, fall thru.\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tif (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (retval < MOVE_CLOAK) retval = MOVE_CLOAK;\n\t\t\t\t\t}\n\t\t\t\t}\n//\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tMove to next object in chain.\n\t\t*/\n\t\tobj = obj->Next;\n\t}\n\n\t/*\n\t**\tIf foot soldiers cannot travel on the cell -- consider it impassable.\n\t*/\n\tif (retval == MOVE_OK && !IsTethered && Ground[cellptr->Land_Type()].Cost[SPEED_FOOT] == 0) {\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Special case - if it's an engineer, and the cell under consideration\n\t\t** is his NavCom, and his mission is mission_capture, then he's most\n\t\t** likely moving to his final destination to repair a bridge, so we\n\t\t** should let him.\n\t\t*/\n\t\tif (*this == INFANTRY_RENOVATOR && Is_Target_Cell(TarCom) && (cell == ::As_Cell(NavCom)) && (cellptr->TType == TEMPLATE_BRIDGE1D || cellptr->TType == TEMPLATE_BRIDGE2D || (cellptr->TType >= TEMPLATE_BRIDGE_1C && cellptr->TType <= TEMPLATE_BRIDGE_3E) ) ) {\n\t\t\treturn(MOVE_OK);\n\t\t}\n#endif\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t** if a unit has the cell reserved then we just can't go in there.\n\t*/\n\tif (retval == MOVE_OK && cellptr->Flag.Occupy.Vehicle) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t** if a block of infantry has the cell reserved then there are two\n\t** possibilities...\n\t*/\n\tif (cellptr->InfType != HOUSE_NONE) {\n\t\tif (House->Is_Ally(cellptr->InfType)) {\n\t\t\tif ((cellptr->Flag.Composite & 0x1F) == 0x1f) {\n\t\t\t\tif (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;\n\t\t\t}\n\t\t} else {\n\t\t\tif (Combat_Damage() > 0) {\n\t\t\t\tif (retval < MOVE_DESTROYABLE) {\n\t\t\t\t\tretval = MOVE_DESTROYABLE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn(MOVE_NO);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it is still ok to move the infantry, then perform the last check\n\t**\tto see if the cell is already full of infantry.\n\t*/\n\tif (retval == MOVE_OK && (cellptr->Flag.Composite & 0x1F) == 0x1F) {\n\t\treturn(MOVE_NO);\n\t}\n\n\t/*\n\t**\tReturn with the most severe reason why this cell would be impassable.\n\t*/\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't occ*\n *                                                                                             *\n *    This is a rendering support routine that will return a pointer to a list of cell offsets *\n *    that specify the cells the infantry unit is currently overlapping (graphic wise) but     *\n *    is not considered to occupy. This list is used to update the map display.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to an offset list for cells that the unit overlaps but doesn't   *\n *          occupy.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef PARTIAL\nshort const * InfantryClass::Overlap_List(bool redraw) const\n#else\nshort const * InfantryClass::Overlap_List(bool ) const\n#endif\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsDog) {\n\t\treturn(Coord_Spillage_List(Coord, 24 + (Doing == DO_DOG_MAUL ? 40 : 0) + (Doing >= DO_GUN_DEATH && Doing <= DO_FIRE_DEATH ? 40 : 0) ));\n\t} else {\n\n\t\t/*\n\t\t**\tThe default infantry rectangle will be as large as the largest shape the infantry\n\t\t**\tcan be.\n\t\t*/\n\n#ifdef PARTIAL\n\t\tRect rect(-16, -24, 32, 36);\n\n\t\t/*\n\t\t**\tIf this is for a visual change redraw, then the overlap list will be based\n\t\t**\ton the actual dimensions of the shape data. If the dimensions have already\n\t\t**\tbeen calculated then use them, otherwise, use the default large rectangle\n\t\t**\tpreviously created.\n\t\t*/\n\t\tif (Height == 0 && !Is_Selected_By_Player() && redraw && Class->DimensionData != NULL) {\n\t\t\tint shapenum = Shape_Number();\n\t\t\tif (!Class->DimensionData[shapenum].Is_Valid()) {\n\t\t\t\tClass->DimensionData[shapenum] = Shape_Dimensions(Get_Image_Data(), shapenum);\n\t\t\t}\n\t\t\trect = Class->DimensionData[shapenum];\n\t\t\trect.Y += 4;\n\t\t\trect.X -= 2;\n\t\t}\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n#else\n\n\t\tstatic Rect rect(-16, -24, 32, 36);\n\t\treturn(Coord_Spillage_List(Coord, rect, true));\n#endif\n\n//\t\treturn(Coord_Spillage_List(Coord, 24 /*+ ((Doing > DO_WALK || IsSelected)?12:0)*/ ));\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Can_Fire -- Can the infantry fire its weapon?                                *\n *                                                                                             *\n *    Determines if the infantry unit can fire on the target. If it can't fire, then the       *\n *    reason why is returned.                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target to determine if the infantry can fire upon.                 *\n *                                                                                             *\n * OUTPUT:  Returns the fire error type that indicates if the infantry can fire and if it      *\n *          can't, why not.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   06/27/1995 JLB : Flame thrower can fire while prone now.                                  *\n *=============================================================================================*/\nFireErrorType InfantryClass::Can_Fire(TARGET target, int which) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tDon't allow firing if the infantry is still firing on previous target.\n\t*/\n//\tif (IsFiring) return(FIRE_REARM);\n\n\t/*\n\t** If a medic is shooting at a healed target, let's declare the target\n\t** illegal so he won't be constantly healing healed infantrymen.\n\t*/\n\tif (Combat_Damage() < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tTechnoClass * targ = As_Techno(target);\n#else\n\t\tInfantryClass * targ = As_Infantry(target);\n#endif\n\t\tif (targ == NULL || targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\treturn(FIRE_ILLEGAL);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this unit cannot fire while moving, then bail.\n\t*/\n\tif (IsDriving || (Target_Legal(NavCom) && Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt)) {\n\t\treturn(FIRE_MOVING);\n\t}\n\n\t/*\n\t** Only one dog can fire on an infantry at a time\n\t*/\n\tif (Class->IsDog) {\n\t\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass *dog = Infantry.Ptr(index);\n\t\t\tif (dog != this && dog->Class->IsDog && (dog->IsFiring || dog->IsInLimbo) && dog->TarCom == target) {\n\t\t\t\treturn(FIRE_ILLEGAL);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(FootClass::Can_Fire(target, which));\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Fire_Coord -- Determine the coordinate where bullets appear.                   *\n *                                                                                             *\n *    This routine will determine the coordinate to use when this infantry fires. The          *\n *    coordinate is the location where bullets appear (or fire effects appear) when the        *\n *    object fires its weapon.                                                                 *\n *                                                                                             *\n * INPUT:   which -- Which weapon is the coordinate to be calculated for? 0 means primary      *\n *                   weapon, 1 means secondary weapon.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that any bullets fired from the specified weapon       *\n *          should appear.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/12/2019 SKY : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE InfantryClass::Fire_Coord(int which) const\n{\n\tCOORDINATE coord = FootClass::Fire_Coord(which);\n\n\t/*\n\t**  Since electric weapons draw a zap between start and end points, prone infantry that fire one\n\t**  need to adjust their fire coordinate so the start point looks correct.\n\t*/\n\tif (IsProne) {\n\t\tTechnoTypeClass const & tclass = *Techno_Type_Class();\n\t\tWeaponTypeClass const * weapon = (which == 0) ? tclass.PrimaryWeapon : tclass.SecondaryWeapon;\n\t\tif (weapon && weapon->IsElectric) {\n\t\t\tcoord = Coord_Add(coord, XY_Coord(0, 48));\n\t\t}\n\t}\n\n\treturn coord;\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.       *\n *                                                                                             *\n *    Use this routine when the infantry unit as accomplished its task and needs to find       *\n *    something to do. The default behavior is to enter some idle state such as guarding.      *\n *                                                                                             *\n * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *\n *                      or is initially placed on the map?                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Enter_Idle_Mode(bool )\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tMissionType order = MISSION_GUARD;\n\n\tif (Target_Legal(TarCom)) {\n\t\torder = MISSION_ATTACK;\n\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\torder = MISSION_SABOTAGE;\n\t\t}\n\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\torder = MISSION_CAPTURE;\n\t\t}\n\t} else {\n\n\t\tHandle_Navigation_List();\n\n\t\tif (Target_Legal(NavCom)) {\n\t\t\torder = MISSION_MOVE;\n\t\t\tif (Mission == MISSION_CAPTURE) {\n\t\t\t\torder = MISSION_CAPTURE;\n\t\t\t}\n\t\t\tif (Mission == MISSION_SABOTAGE) {\n\t\t\t\torder = MISSION_SABOTAGE;\n\t\t\t}\n\t\t} else {\n\n\t\t\tif (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA || MissionControl[Mission].IsZombie || MissionControl[Mission].IsParalyzed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (Class->IsDog) {\n\t\t\t\tif (House->IsHuman || Team.Is_Valid()) {\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t} else {\n\t\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t\t\tArchiveTarget = ::As_Target(Coord_Cell(Center_Coord()));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (House->IsHuman || Team.Is_Valid()) {\n\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t} else {\n\t\t\t\t\tif (House->IQ < Rule.IQGuardArea) {\n\t\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Is_Weapon_Equipped()) {\n\t\t\t\t\t\t\torder = MISSION_GUARD_AREA;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\torder = MISSION_GUARD;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tAssign_Mission(order);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                      *\n *                                                                                             *\n *    This routine is the random animator initiator for infantry units. This routine should    *\n *    be called regularly. On occasion, it will cause the infantry to go into an idle          *\n *    animation.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   12/13/1994 JLB : Does random facing change.                                               *\n *   07/02/1995 JLB : Nikoomba special effects.                                                *\n *=============================================================================================*/\nbool InfantryClass::Random_Animate(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Is_Ready_To_Random_Animate()) {\n\t\tIdleTimer = Random_Pick(Rule.RandomAnimateTime * (TICKS_PER_MINUTE/2), Rule.RandomAnimateTime * (TICKS_PER_MINUTE*2));\n\n\t\t/*\n\t\t**\tScared infantry will always follow the golden rule of civilians;\n\t\t**\t\t\"When in darkness or in doubt, run in circles, scream, and shout!\"\n\t\t*/\n\t\tif (Class->IsFraidyCat && !House->IsHuman && Fear > FEAR_ANXIOUS) {\n\t\t\tScatter(NULL, true);\n\t\t\treturn(true);\n\t\t}\n\n\t\tswitch (Random_Pick(0, 10)) {\n\t\t\tcase 0:\n\t\t\t\tif (Class->IsDog) {\n\t\t\t\t\tDo_Action(DO_IDLE1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tDo_Action(DO_SALUTE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\t\t\t\tDo_Action(DO_SALUTE2);\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tDo_Action(DO_GESTURE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 4:\n\t\t\t\tDo_Action(DO_GESTURE2);\n\t\t\t\tbreak;\n\n\t\t\tcase 5:\n\t\t\t\tDo_Action(DO_IDLE1);\n\t\t\t\tbreak;\n\n\t\t\tcase 6:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tbreak;\n\n\t\t\tcase 7:\n\t\t\t\tDo_Action(DO_IDLE2);\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tif (!Is_Selected_By_Player() && IsOwnedByPlayer && *this == INFANTRY_TANYA && Sim_Random_Pick(0, 2) == 0) {\n\t\t\t\t\tSound_Effect(VOC_TANYA_SHAKE, Coord);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOn occasion, civilian types will wander about.\n\t\t\t*/\n\t\t\tcase 8:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tif (!House->IsHuman && Class->IsFraidyCat) {\n\t\t\t\t\tScatter(NULL, true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 9:\n\t\t\tcase 10:\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\t\t\t\tPrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));\n\t\t\t\tMark(MARK_CHANGE_REDRAW);\n\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                    *\n *                                                                                             *\n *    This routine is used when the infantry should scatter to a nearby cell. Scattering       *\n *    occurs as an occasional consequence of being fired upon. It is one of the features       *\n *    that makes infantry so \"charming\".                                                       *\n *                                                                                             *\n * INPUT:   threat   -- The coordinate source of the threat that is causing the infantry to    *\n *                      scatter. If the threat isn't from a particular direction, then this    *\n *                      parameter will be NULL.                                                *\n *                                                                                             *\n *          forced   -- The threat is real and a serious effort to scatter should be made.     *\n *                                                                                             *\n *          nokidding-- The scatter should affect the player's infantry even if it otherwise   *\n *                      wouldn't have.                                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/12/1994 JLB : Flame thrower infantry always scatter.                                   *\n *   08/02/1996 JLB : Added the nokidding parameter                                            *\n *=============================================================================================*/\nvoid InfantryClass::Scatter(COORDINATE threat, bool forced, bool nokidding)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tA unit that is in the process of going somewhere will never scatter.\n\t*/\n\tif (IsDriving) forced = false;\n\n\t/*\n\t**\tCertain missions prevent scattering regardless of whether it would be\n\t**\ta good idea or not.\n\t*/\n\tif (!MissionControl[Mission].IsScatter && !forced) return;\n\n\t/*\n\t**\tIf the infantry is currently engaged in legitimate combat, then don't\n\t**\tscatter unless forced to.\n\t*/\n\tif (!Class->IsFraidyCat && Target_Legal(TarCom) && !forced) return;\n\n\t/*\n\t**\tDon't scatter if performing an action that can't be interrupted.\n\t*/\n\tif (Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt) return;\n\n\t/*\n\t**\tFor human players, don't scatter the infantry, if the special\n\t**\tflag has not been enabled that allows infantry scatter.\n\t*/\n\tif (!Rule.IsScatter && !nokidding && House->IsHuman && !forced && !Team.Is_Valid()) return;\n\n\tif (forced || Class->IsFraidyCat /*|| !(Random_Pick(1, 4) == 1)*/) {\n\t\tFacingType\ttoface;\n\n\t\tif (threat) {\n\t\t\ttoface = Dir_Facing(Direction8(threat, Coord));\n\t\t\ttoface = toface + FacingType(Random_Pick(0, 4)-2);\n\t\t} else {\n\t\t\tCOORDINATE coord = Coord_Fraction(Center_Coord());\n\n\t\t\tif (coord != 0x00800080L) {\n\t\t\t\ttoface = Dir_Facing((DirType)Desired_Facing8(0x0080, 0x0080, Coord_X(coord), Coord_Y(coord)));\n\t\t\t} else {\n\t\t\t\ttoface = Dir_Facing(PrimaryFacing.Current());\n\t\t\t}\n\t\t\ttoface = toface + FacingType(Random_Pick(0, 4)-2);\n\t\t}\n\n\t\tCELL newcell = 0;\n\t\tCELL altcell = 0;\n\t\tFacingType face;\n\t\tfor (face = FACING_N; face < FACING_COUNT; face++) {\n\t\t\tFacingType newface = toface + face;\n\t\t\tnewcell = Adjacent_Cell(Coord_Cell(Coord), newface);\n\n\t\t\tif (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {\n\t\t\t\tif (altcell == 0) altcell = newcell;\n\t\t\t\tif (!Map[newcell].Is_Bridge_Here()) break;\n//\t\t\t\tAssign_Mission(MISSION_MOVE);\n//\t\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t\t}\n\t\t}\n\t\tif (face == FACING_COUNT) {\n\t\t\tnewcell = 0;\n\t\t}\n\n\t\tif (newcell == 0) {\n\t\t\tnewcell = altcell;\n\t\t}\n\n\t\tif (newcell != 0) {\n\t\t\tAssign_Mission(MISSION_MOVE);\n\t\t\tAssign_Destination(::As_Target(newcell));\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Look -- Performs a look around (map reveal) action.                          *\n *                                                                                             *\n *    This routine will reveal the map around this object.                                     *\n *                                                                                             *\n * INPUT:   incremental -- This parameter can enable a more efficient map reveal logic.        *\n *                         If it is absolutely known that the object has only moved one        *\n *                         cell from its previous location that it performed a Look() at,      *\n *                         then set this parameter to TRUE. It will only perform the look      *\n *                         check on the perimeter cells.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is slow, try to call it only when necessary.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Look(bool incremental)\n{\n\tLookCell = Coord_Cell(Coord);\n\tFootClass::Look(incremental);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Do_Action -- Launches the infantry into an animation sequence.               *\n *                                                                                             *\n *    This starts the infantry into a choreographed animation sequence. These sequences can    *\n *    be as simple as standing up or lying down, but can also be complex, such as dying or     *\n *    performing some idle animation.                                                          *\n *                                                                                             *\n * INPUT:   todo     -- The choreographed sequence to start.                                   *\n *                                                                                             *\n *          force    -- Force starting this animation even if the current animation is flagged *\n *                      as uninterruptible. This is necessary for death animations.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the animation started?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Do_Action(DoType todo, bool force)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (todo == DO_NOTHING || Class->DoControls[todo].Count == 0) {\n\t\treturn(false);\n\t}\n\n\tif (*this == INFANTRY_SPY && todo >= DO_GESTURE1) {\n\t\ttodo = (DoType)(DO_IDLE1 + Random_Pick(0,1));\n\t}\n\n\tif (todo != Doing && (Doing == DO_NOTHING || force || MasterDoControls[Doing].Interrupt)) {\n\t\tMark(MARK_OVERLAP_UP);\n\t\tDoing = todo;\n\t\tMark(MARK_OVERLAP_DOWN);\n\t\tif (todo == DO_IDLE1 || todo == DO_IDLE2) {\n\t\t\tSet_Rate(Options.Normalize_Delay(MasterDoControls[Doing].Rate));\n\t\t} else {\n\t\t\tSet_Rate(MasterDoControls[Doing].Rate);\n\t\t}\n\t\tSet_Stage(0);\n\n\t\t/*\n\t\t**\tKludge to make sure that if infantry is in the dying animation, it isn't still\n\t\t**\tmoving as well.\n\t\t*/\n\t\tif (Strength == 0) {\n\t\t\tStop_Driver();\n\t\t}\n\n\t\t/*\n\t\t**\tMake sure dogs don't try to go somewhere while they're mauling\n\t\t*/\n\t\tif (todo == DO_DOG_MAUL) {\n\t\t\tStop_Driver();\n\t\t\tAssign_Destination(TARGET_NONE);\n\t\t}\n\n\t\t/*\n\t\t**\tSince the animation sequence might be interrupted. Set any flags\n\t\t**\tnecessary so that if interrupted, the affect on the infantry is\n\t\t**\tstill accomplished.\n\t\t*/\n\t\tswitch (todo) {\n\t\t\tcase DO_LIE_DOWN:\n\t\t\t\tIsProne = true;\n\t\t\t\tbreak;\n\n\t\t\tcase DO_GET_UP:\n\t\t\t\tIsProne = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                   *\n *                                                                                             *\n *    This is used to stop the infantry from animating in movement. This function will stop    *\n *    the infantry moving and revert it to either a prone or standing.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the driving stopped?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Stop_Driver(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Head_To_Coord()) {\n\n\t\t/*\n\t\t**\tRemove the \"reservation\" bit in the destination location.\n\t\t*/\n\t\tClear_Occupy_Bit(Head_To_Coord());\n\t}\n\n\t/*\n\t**\tSet the occupation bit at the current location.\n\t*/\n\tSet_Occupy_Bit(Coord);\n\n\tif (Doing != DO_STAND_READY) {\n\t\tStopDriverFrame = Frame;\n\t}\n\n\tif (Class->IsDog) {\n\t\tDo_Action(DO_STAND_READY);\n\t} else {\n\t\tif (IsProne) {\n\t\t\tDo_Action(DO_PRONE);\n\t\t} else {\n\t\t\tDo_Action(DO_STAND_READY);\n\t\t}\n\t}\n\n\tif (Can_Enter_Cell(Coord_Cell(Coord)) == MOVE_OK) {\n\t\tIsZoneCheat = false;\n\t} else {\n\t\tIsZoneCheat = true;\n\t}\n\n\treturn(FootClass::Stop_Driver());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.        *\n *                                                                                             *\n *    Use this routine to being the infantry moving toward the destination specified. The      *\n *    destination is first checked to see if there is a free spot available. Then the infantry *\n *    reserves that spot and begins movement toward it.                                        *\n *                                                                                             *\n * INPUT:   headto   -- The coordinate location desired for the infantry to head to.           *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry successfully started on its journey? Failure may be because *\n *                the specified destination could not contain the infantry unit.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/21/1994 JLB : Created.                                                                 *\n *   05/14/1995 JLB : Tries to move to closest spot possible.                                  *\n *   05/15/1995 JLB : Uses closest spot if moving onto transport.                              *\n *=============================================================================================*/\nbool InfantryClass::Start_Driver(COORDINATE & headto)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tCOORDINATE old = headto;\n\n\t/*\n\t**\tConvert the head to coordinate to a legal sub-position location.\n\t*/\n\theadto = Map[headto].Closest_Free_Spot(Coord_Move(headto, Direction(headto)+DIR_S, 0x007C));\n\tif (!headto && Can_Enter_Cell(Coord_Cell(old)) == MOVE_OK) {\n\t\theadto = Map[old].Closest_Free_Spot(Coord_Move(old, Direction(headto)+DIR_S, 0x0080), true);\n\t}\n\n\t/*\n\t**\tIf the infantry started moving, then fixup the occupation bits.\n\t*/\n\tif (headto && FootClass::Start_Driver(headto)) {\n\t\tif (!IsActive) return(false);\n\n\t\t/*\n\t\t**\tRemove the occupation bit from the infantry's current location.\n\t\t*/\n  \t\tClear_Occupy_Bit(Coord);\n\n\t\t/*\n\t\t**\tSet the occupation bit for the new headto location.\n\t\t*/\n\t\tSet_Occupy_Bit(headto);\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                   *\n *                                                                                             *\n *    This routine will clean up the infantry occupation bits (as necessary) as well as stop   *\n *    the infantry movement process when it gets limboed.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit limboed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Limbo(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\t\tStop_Driver();\n\n\t\tClear_Occupy_Bit(Coord);\n\t}\n\treturn(FootClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Fire_At -- Fires projectile from infantry unit.                              *\n *                                                                                             *\n *    Use this routine when the infantry unit wishes to fire a projectile. This routine        *\n *    will launch the projectile and perform any other necessary infantry specific operations. *\n *                                                                                             *\n * INPUT:   target   -- The target of the attack.                                              *\n *                                                                                             *\n *          which    -- Which weapon to use for firing. 0=primary, 1=secondary.                *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the projectile launched. If none could be launched, then   *\n *          NULL is returned. If there is already the maximum bullet objects in play, then     *\n *          this could happen.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * InfantryClass::Fire_At(TARGET target, int which)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tMark(MARK_OVERLAP_UP);\n\tIsFiring = false;\n\tMark(MARK_OVERLAP_DOWN);\n\n\tBulletClass * bullet = FootClass::Fire_At(target, which);\n\tif (bullet != NULL && !IsInLimbo) {\n\n\t\t/*\n\t\t**\tFor fraidycat infantry that run out of ammo, always go into\n\t\t**\ta maximum fear state at that time.\n\t\t*/\n\t\tif (Class->IsFraidyCat && !Ammo) {\n\t\t\tFear = FEAR_MAXIMUM;\n\t\t\tif (Mission == MISSION_ATTACK || Mission == MISSION_HUNT) {\n\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t}\n\t\t}\n\t}\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                      *\n *                                                                                             *\n *    This will attempt to unlimbo the infantry unit at the designated coordinate, but will    *\n *    ensure that the coordinate is a legal subposition.                                       *\n *                                                                                             *\n * INPUT:   coord    -- The coordinate to unlimbo the infantry at.                             *\n *                                                                                             *\n *          facing   -- The desired initial facing for the infantry unit.                      *\n *                                                                                             *\n *          strength -- The desired initial strength for the infantry unit.                    *\n *                                                                                             *\n *          mission  -- The desired initial mission for the infantry unit.                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unlimboed successfully?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Unlimbo(COORDINATE coord, DirType facing)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tMake sure that the infantry start in a legal position on the map.\n\t*/\n\tcoord = Map[coord].Closest_Free_Spot(coord, ScenarioInit);\n\tif (coord == NULL) {\n\t\treturn(false);\n\t}\n\n\tif (FootClass::Unlimbo(coord, facing)) {\n\n\t\t/*\n\t\t**\tEnsure that the owning house knows about the\n\t\t**\tnew object.\n\t\t*/\n\t\tHouse->IScan |= (1L << Class->Type);\n\t\tHouse->ActiveIScan |= (1L << Class->Type);\n\n\t\t/*\n\t\t**\tIf there is no sight range, then this object isn't discovered by the player unless\n\t\t**\tit actually appears in a cell mapped by the player.\n\t\t*/\n\t\tif (Class->SightRange == 0) {\n\t\t\tIsDiscoveredByPlayer = false;\n\t\t}\n\n\t\tSet_Occupy_Bit(coord);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.    *\n *                                                                                             *\n *    This routine intercepts the Greatest_Threat request and adds the appropriate target      *\n *    types to search for. For regular infantry, this consists of all the ground types. For    *\n *    rocket launching infantry, this also includes aircraft.                                  *\n *                                                                                             *\n * INPUT:   threat   -- The basic threat control value.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the best target for this infantry unit to attack. If no suitable      *\n *          target could be found, then TARGET_NONE is returned.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   09/28/1995 JLB : Engineers try to recapture buildings first.                              *\n *=============================================================================================*/\nTARGET InfantryClass::Greatest_Threat(ThreatType threat) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t**\tEngineers consider only buildings that can be captured as being a threat. All others\n\t**\tare ignored. If there is a building that needs to be recaptured and it is nearby\n\t**\tthen automatically head toward it to recapture it.\n\t*/\n\tif (!House->IsHuman && Class->IsCapture && !Is_Weapon_Equipped()) {\n\t\tif (House->ToCapture != TARGET_NONE && Distance(House->ToCapture) < 0x0F00) {\n\t\t\treturn(House->ToCapture);\n\t\t}\n\t\tthreat = threat | THREAT_CAPTURE;\n\t}\n\n\tif (!Is_Weapon_Equipped()) {\n\t\tif (!Class->IsCapture && *this != INFANTRY_RENOVATOR && *this != INFANTRY_SPY && *this != INFANTRY_THIEF) {\n\t\t\treturn(TARGET_NONE);\n\t\t}\n\t}\n\n\t/*\n\t**\tSpecial hack to make Tanya not auto-fire if controlled by a\n\t**\thuman player.\n\t*/\n\tif (*this == INFANTRY_TANYA && House->IsHuman) {\n\t\treturn(TARGET_NONE);\n\t}\n\n\tif (Class->PrimaryWeapon != NULL) {\n\t\tthreat = threat | Class->PrimaryWeapon->Allowed_Threats();\n\t}\n\tif (Class->SecondaryWeapon != NULL) {\n\t\tthreat = threat | Class->SecondaryWeapon->Allowed_Threats();\n\t}\n\n\t/*\n\t**\tOrganic weapon types don't consider anything but infantry to be a threat. Such\n\t**\tweapon types would be the dog jaw and the medic first aid kit.\n\t*/\n\tif (Is_Weapon_Equipped() && Class->PrimaryWeapon->WarheadPtr->IsOrganic) {\n\t\tthreat = threat & ~(THREAT_BUILDINGS|THREAT_VEHICLES|THREAT_BOATS|THREAT_AIR);\n\t}\n\n\t/*\n\t**\tHuman controlled infantry don't automatically fire upon buildings.\n\t*/\n\tif (Is_Weapon_Equipped() && House->IsHuman) {\n\t\tthreat = threat & ~THREAT_BUILDINGS;\n\t}\n\n\t/*\n\t**\tIf this is a bomber type, then allow buildings to be considered a threat.\n\t*/\n\tif (Class->IsBomber && !House->IsHuman) {\n\t\tthreat = threat | THREAT_BUILDINGS;\n\t}\n\n\t/*\n\t** Special hack: if it's a thief, then the only possible objects to\n\t** consider are tiberium-processing objects (silos & refineries).\n\t*/\n\tif (*this == INFANTRY_THIEF) {\n\t\tthreat = threat | THREAT_CAPTURE | THREAT_TIBERIUM;\n//\t\tthreat = (ThreatType)(THREAT_CAPTURE | THREAT_TIBERIUM);\n\t}\n\treturn(FootClass::Greatest_Threat(threat));\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Select -- Plays infantry audio response due to being selected.      *\n *                                                                                             *\n *    This routine handles playing an audio response as a result of the player selecting the   *\n *    infantry unit. This occurs prior to giving it an order and may not be followed by any    *\n *    order at all.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Select(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response = VOC_NONE;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_YEAH;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_YEAH;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_YES,VOC_ENG_ENG};\n\t\tstatic VocType _ein_response[] = {VOC_E_AH};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_YES};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_COMMANDER,VOC_SPY_YESSIR};\n\t\tstatic VocType _medic_response[] = {VOC_MED_REPORTING,VOC_MED_YESSIR};\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_YEA,VOC_TANYA_YES,VOC_TANYA_WHATS};\n\t\tstatic VocType _thief_response[] = {VOC_THIEF_YEA,VOC_THIEF_WHAT};\n\t\tstatic VocType _default_response[] = {VOC_ACKNOWL,VOC_REPORT,VOC_REPORT,VOC_YESSIR,VOC_YESSIR,VOC_READY,VOC_AWAIT};\n\t\tstatic VocType _stavros[] = {VOC_STAVCMDR,VOC_STAVYES};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic_response[] = {VOC_MECHHOWDY1,VOC_MECHHUH1,VOC_MECHLAFF1};\n\t\tstatic VocType _shock_response[] = {VOC_STYES1,VOC_STJUMP1,VOC_STJUICE1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic_response;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic_response);\n\t\t\t\tbreak;\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock_response;\n\t\t\t\tsize = ARRAY_SIZE(_shock_response);\n\t\t\t\tbreak;\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Move -- Plays infantry response to movement order.                  *\n *                                                                                             *\n *    When the infantry is given the order to move, this routine handles the audio response    *\n *    generated by the infantry unit.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Move(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_OKAY;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_OKAY;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_AFFIRM,VOC_ENG_AFFIRM};\n\t\tstatic VocType _ein_response[] = {VOC_E_OK,VOC_E_YES};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_BARK};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_ONWAY,VOC_SPY_KING,VOC_SPY_INDEED};\n\t\tstatic VocType _medic_response[] = {VOC_MED_AFFIRM,VOC_MED_MOVEOUT};\n#ifdef ENGLISH\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_THERE,VOC_TANYA_ROCK};\n#else\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_THERE,VOC_TANYA_GIVE};\n#endif\n\t\tstatic VocType _thief_response[] = {VOC_THIEF_MOVEOUT,VOC_THIEF_OKAY,VOC_THIEF_AFFIRM};\n\t\tstatic VocType _default_response[] = {VOC_ROGER,VOC_RIGHT_AWAY,VOC_UGOTIT,VOC_AFFIRM,VOC_AFFIRM};\n\t\tstatic VocType _stavros[] = {VOC_STAVMOV,VOC_STAVCRSE};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic[] = {VOC_MECHYES1,VOC_MECHRISE1,VOC_MECHHEAR1,VOC_MECHBOSS1};\n\t\tstatic VocType _shock[] = {VOC_STPOWER1,VOC_STDANCE1,VOC_STCHRGE1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock;\n\t\t\t\tsize = ARRAY_SIZE(_shock);\n\t\t\t\tbreak;\n\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Response_Attack -- Plays infantry audio response to attack order.            *\n *                                                                                             *\n *    When the player gives an infantry unit the order to attack, this routine handles         *\n *    the audio response by that unit.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *   05/05/1995 JLB : Rambo response types added.                                              *\n *=============================================================================================*/\nvoid InfantryClass::Response_Attack(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (!AllowVoice) return;\n\n\tif (Class->IsCivilian && *this != INFANTRY_EINSTEIN) {\n\t\tVocType response;\n\t\tif (Class->IsFemale) {\n\t\t\tresponse = VOC_GIRL_OKAY;\n\t\t} else {\n\t\t\tresponse = VOC_GUY_OKAY;\n\t\t}\n\t\tSound_Effect(response, fixed(1), ID+1);\n\n\t} else {\n\t\tstatic VocType _eng_response[] = {VOC_ENG_AFFIRM,VOC_ENG_AFFIRM};\n\t\tstatic VocType _dog_response[] = {VOC_DOG_GROWL2};\n\t\tstatic VocType _ein_response[] = {VOC_E_OK,VOC_E_YES};\n\t\tstatic VocType _spy_response[] = {VOC_SPY_ONWAY,VOC_SPY_KING,VOC_SPY_INDEED};\n\t\tstatic VocType _medic_response[] = {VOC_MED_AFFIRM,VOC_MED_MOVEOUT};\n#ifdef ENGLISH\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_CHEW,VOC_TANYA_CHING,VOC_TANYA_LAUGH};\n#else\n\t\tstatic VocType _tanya_response[] = {VOC_TANYA_CHEW,VOC_TANYA_CHING,VOC_TANYA_LAUGH,VOC_TANYA_ROCK};\n#endif\n\t\tstatic VocType _thief_response[] = {VOC_NONE};\n\t\tstatic VocType _default_response[] = {VOC_RIGHT_AWAY,VOC_AFFIRM,VOC_AFFIRM,VOC_UGOTIT,VOC_NO_PROB,VOC_YESSIR,VOC_YESSIR,VOC_YESSIR};\n\t\tstatic VocType _stavros[] = {VOC_STAVCRSE};\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tstatic VocType _mechanic[] = {VOC_MECHYEEHAW1,VOC_MECHHOTDIG1,VOC_MECHWRENCH1};\n\t\tstatic VocType _shock[] = {VOC_STLIGHT1,VOC_STBURN1,VOC_STCRISP1,VOC_STSHOCK1};\n#endif\n\n\t\tint size = 0;\n\t\tVocType * response = NULL;\n\t\tHousesType house = PlayerPtr->ActLike;\n\t\tswitch (Class->Type) {\n\t\t\tcase INFANTRY_GENERAL:\n\t\t\t\tif (house != HOUSE_USSR && house != HOUSE_BAD) {\n\t\t\t\t\tresponse = _stavros;\n\t\t\t\t\tsize = ARRAY_SIZE(_stavros);\n\t\t\t\t} else {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_DOG:\n\t\t\t\tresponse = _dog_response;\n\t\t\t\tsize = ARRAY_SIZE(_dog_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SPY:\n\t\t\t\tresponse = _spy_response;\n\t\t\t\tsize = ARRAY_SIZE(_spy_response);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(house == HOUSE_USSR) {\n\t\t\t\t\tresponse = _default_response;\n\t\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_EINSTEIN:\n\t\t\t\tresponse = _ein_response;\n\t\t\t\tsize = ARRAY_SIZE(_ein_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_RENOVATOR:\n\t\t\t\tresponse = _eng_response;\n\t\t\t\tsize = ARRAY_SIZE(_eng_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_MEDIC:\n\t\t\t\tresponse = _medic_response;\n\t\t\t\tsize = ARRAY_SIZE(_medic_response);\n\t\t\t\tbreak;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tcase INFANTRY_MECHANIC:\n\t\t\t\tresponse = _mechanic;\n\t\t\t\tsize = ARRAY_SIZE(_mechanic);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_SHOCK:\n\t\t\t\tresponse = _shock;\n\t\t\t\tsize = ARRAY_SIZE(_shock);\n\t\t\t\tbreak;\n#endif\n\t\t\tcase INFANTRY_TANYA:\n\t\t\t\tresponse = _tanya_response;\n\t\t\t\tsize = ARRAY_SIZE(_tanya_response);\n\t\t\t\tbreak;\n\n\t\t\tcase INFANTRY_THIEF:\n\t\t\t\tresponse = _thief_response;\n\t\t\t\tsize = ARRAY_SIZE(_thief_response);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresponse = _default_response;\n\t\t\t\tsize = ARRAY_SIZE(_default_response);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (response != NULL) {\n\t\t\tSound_Effect(response[Sim_Random_Pick(0, size-1)], fixed(1), ID+1, 0, house);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::What_Action -- Infantry units might be able to capture -- check.             *\n *                                                                                             *\n *    This routine checks to see if the infantry unit can capture the specified object rather  *\n *    than merely attacking it. If this is the case, then ACTION_CAPTURE will be returned.     *\n *                                                                                             *\n * INPUT:   object   -- The object that the mouse is currently over.                           *\n *                                                                                             *\n * OUTPUT:  Returns the action that will be performed if the mouse were clicked over the       *\n *          object specified.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType InfantryClass::What_Action(ObjectClass const * object) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\tassert(object != NULL);\n\n\tActionType action = FootClass::What_Action(object);\n\n\t/*\n\t** If this is an engineer/renovator, we have to make some adjustments.\n\t** If the cursor is over an enemy building, return action-none.  If it's\n\t** over a friendly building, we have to return action-capture so he can\n\t** renovate it.\n\t** However, abort the whole thing if the building is a barrel or mine.\n\t*/\n\tif (*this == INFANTRY_RENOVATOR && object->What_Am_I() == RTTI_BUILDING && House->IsPlayerControl) {\n\t\tBuildingClass const * bldg = (BuildingClass *)object;\n\t\tif (bldg->Class->IsRepairable) {\n\t\t\tif (House->Is_Ally(bldg)) {\n\t\t\t\tif (bldg->Health_Ratio() == 1) {\n\t\t\t\t\treturn(ACTION_NO_GREPAIR);\n\t\t\t\t}\n\t\t\t\treturn(ACTION_GREPAIR);\n\t\t\t} else {\n\n\t\t\t\tif (bldg->Can_Capture()) {\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (bldg->Health_Ratio() <= EngineerCaptureLevel) {\n#else\n\t\t\t\t\tif (bldg->Health_Ratio() <= Rule.ConditionRed) {\n#endif\n\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t}\n\t\t\t\t\treturn(ACTION_DAMAGE);\n\t\t\t\t}\n\n//\t\t\t\tif (bldg->Health_Ratio() <= Rule.ConditionRed && bldg->Can_Capture()) {\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** If this is a medic, and the cursor's over a friendly infantryman,\n\t** execute an action-attack.  In CSII, if this is a mechanic and the\n\t** cursor's over a friendly vehicle, execute an action-attack.\n\t*/\n\tif (Combat_Damage() < 0 && House->IsPlayerControl) {\n\t\tif (House->Is_Ally(object)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif( (object->What_Am_I() == RTTI_INFANTRY && object != this && *this == INFANTRY_MEDIC) ||\n\t\t\t    (*this == INFANTRY_MECHANIC && (object->What_Am_I() == RTTI_UNIT || object->What_Am_I() == RTTI_AIRCRAFT) ) ) {\n\n\t\t\t\t\tif (object->Health_Ratio() < Rule.ConditionGreen) {\n// If it's a mechanic force-moving into an APC, don't try to heal it.\n\t\t\t\t\t\tif(*this == INFANTRY_MECHANIC && object->What_Am_I() == RTTI_UNIT && *(UnitClass *)object == UNIT_APC && (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)) ) {\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn(ACTION_HEAL);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n#else\n\t\t\tif(object->What_Am_I() == RTTI_INFANTRY && object != this) {\n\t\t\t\tif (object->Health_Ratio() < Rule.ConditionGreen) {\n\t\t\t\t\treturn(ACTION_HEAL);\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tif(!object->Is_Techno() || !((TechnoClass *)object)->Techno_Type_Class()->Max_Passengers()) {\n\t\t\t\tif (action == ACTION_GUARD_AREA || action == ACTION_MOVE) {\n\t\t\t\t\treturn(action);\n\t\t\t\t}\n\t\t\t\treturn ((action == ACTION_TOGGLE_SELECT) ? ACTION_TOGGLE_SELECT : ACTION_SELECT);\n\t\t\t}\n\t\t} else {\n\t\t\treturn(ACTION_NOMOVE);\n\t\t}\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t** See if it's a thief attacking an enemy vehicle, let him CAPTURE it.\n\t*/\n\tif (*this == INFANTRY_THIEF && object->What_Am_I() == RTTI_UNIT) {\n\t\tif (((UnitClass *)object)->House != House) {\n\t\t\treturn(ACTION_CAPTURE);\n\t\t}\n\t}\n#endif\n\n\t/*\n\t** Dogs can only attack infantrymen\n\t*/\n\tif (Class->IsDog && action == ACTION_ATTACK && object->What_Am_I() != RTTI_INFANTRY) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tSee if it's a commando, and if he's attacking a building,\n\t** have him return ACTION_SABOTAGE instead\n\t*/\n\tif (Class->IsBomber && action == ACTION_ATTACK && object->What_Am_I() == RTTI_BUILDING) {\n\t\tBuildingClass const * obj = (BuildingClass *)object;\n\t\t/*\n\t\t** Hack: Tanya should shoot barrels, bomb other structures.\n\t\t*/\n\t\tif (obj->Class->IsRepairable) {\n//\t\tif (*obj != STRUCT_BARREL && *obj != STRUCT_BARREL3) {\n\t\t\treturn(ACTION_SABOTAGE);\n\t\t} else {\n\t\t\treturn(ACTION_ATTACK);\n\t\t}\n\t}\n\n\t/*\n\t** See if this infantry is trying to move onto where a land mine is.\n\t*/\n\tif (action == ACTION_NONE && object->What_Am_I() == RTTI_BUILDING && House->IsPlayerControl) {\n\t\tStructType blah = *((BuildingClass *)object);\n\t\tif (blah == STRUCT_AVMINE || blah == STRUCT_APMINE) return(ACTION_MOVE);\n\t}\n\n\t/*\n\t**\tThere is no self-select action available for infantry types.\n\t*/\n\tif (action == ACTION_SELF) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t**\tCheck to see if it can enter a transporter.\n\t*/\n\tif (\n\t\tHouse->Is_Ally(object) &&\n\t\tHouse->IsPlayerControl && object->Is_Techno()) {\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n if (object->What_Am_I() != RTTI_VESSEL || *(VesselClass *)object != VESSEL_CARRIER) {\n#endif\n\t\tswitch (((InfantryClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object)) {\n\t\t\tcase RADIO_ROGER:\n\t\t\t\taction = ACTION_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tcase RADIO_NEGATIVE:\n\t\t\t\taction = ACTION_NO_ENTER;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n }\n#endif\n\t}\n\n\tif (Class->IsCapture && action == ACTION_ATTACK) {\n\t\tif (!House->Is_Ally(object) && (\n//Disable capturing of helicopters\t\t\t (object->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)object)->Pip_Count() == 0 && *((AircraftClass *)object) == AIRCRAFT_TRANSPORT) ||\n\t\t\t (object->What_Am_I() == RTTI_BUILDING && object->Can_Capture()) )\n\t\t\t) {\n\n\t\t\t\tif (*this == INFANTRY_THIEF && (object->What_Am_I() == RTTI_BUILDING && ((BuildingClass *)object)->Class->Capacity == 0)) {\n\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If we're trying to capture a building, make sure we can get\n\t\t\t\t\t** to it.  Find an adjacent cell that's the same zone as us.\n\t\t\t\t\t** The target circumstance is a naval yard that doesn't touch\n\t\t\t\t\t** the shore - a total island.  In that case, we can't capture\n\t\t\t\t\t** it, so we shouldn't show the action-capture cursor.\n\t\t\t\t\t*/\n\t\t\t\t\taction = ACTION_CAPTURE;\n\t\t\t\t\tif (object->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\tCELL cell = ::As_Cell(object->As_Target());\n\t\t\t\t\t\tint targzone = Map[::As_Cell(As_Target())].Zones[Class->MZone];\n\t\t\t\t\t\tshort const *list = ((BuildingClass *)object)->Class->Occupy_List(false);\n\t\t\t\t\t\tbool found = false;\n\t\t\t\t\t\twhile (*list != REFRESH_EOL && !found) {\n\t\t\t\t\t\t\tCELL newcell = cell + *list++;\n\t\t\t\t\t\t\tfor (FacingType i=FACING_N; i < FACING_COUNT; i++) {\n\t\t\t\t\t\t\t\tCELL adjcell = Adjacent_Cell(newcell, i);\n\t\t\t\t\t\t\t\tif ((unsigned)adjcell >= MAP_CELL_TOTAL) continue;\n\t\t\t\t\t\t\t\tif (Map[adjcell].Zones[Class->MZone] == targzone) {\n\t\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t} else {\n\t\t\tif (!Is_Weapon_Equipped()) {\n\t\t\t\taction = ACTION_NONE;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it doesn't know what to do with the object, then just\n\t**\tsay it can't move there.\n\t*/\n\tif (action == ACTION_NONE) action = ACTION_NOMOVE;\n\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.     *\n *                                                                                             *\n *    This routine is called when the player clicks over an object while this infantry soldier *\n *    is selected. Capture attempts are prohibited if the infantry cannot capture. The         *\n *    command might respond if told to sabotage something.                                     *\n *                                                                                             *\n * INPUT:   action   -- The action that is nominally to be performed.                          *\n *                                                                                             *\n *          object   -- The object over which the mouse was clicked.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Active_Click_With(ActionType action, ObjectClass * object)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\taction = What_Action(object);\n\n\tswitch (action) {\n\t\tcase ACTION_GREPAIR:\n\t\tcase ACTION_DAMAGE:\n\t\tcase ACTION_CAPTURE:\n\t\t\taction = ACTION_CAPTURE;\n\t\t\tbreak;\n\n\t\tcase ACTION_HEAL:\n\t\t\taction = ACTION_ATTACK;\n\t\t\tbreak;\n\n//\t\tcase ACTION_ENTER:\n//\t\t\taction = ACTION_MOVE;\n//\t\t\tbreak;\n\n\t\tcase ACTION_SABOTAGE:\n\t\tcase ACTION_ATTACK:\n\t\tcase ACTION_GUARD_AREA:\n\t\tcase ACTION_MOVE:\n\t\t\taction = action;\n\t\t\tbreak;\n\n\t\tdefault:\n//\t\t\taction = ACTION_NONE;\n\t\t\tbreak;\n\t}\n\n\tFootClass::Active_Click_With(action, object);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos                       *\n *                                                                                             *\n * INPUT:      CELL      - the cell we are setting the bit in                                  *\n *                                                                                             *\n *               int      - the spot index we are setting the bit for                          *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/08/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Set_Occupy_Bit(CELL cell, int spot_index)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** Set the occupy position for the spot that we passed in\n\t*/\n\tMap[cell].Flag.Composite |= (1 << spot_index);\n\n\t/*\n\t** Record the type of infantry that now owns the cell\n\t*/\n\tMap[cell].InfType = Owner();\n}\n\n\n/***************************************************************************\n * InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid InfantryClass::Clear_Occupy_Bit(CELL cell, int spot_index)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\t/*\n\t** Clear the occupy bit for the infantry in that cell\n\t*/\n\tMap[cell].Flag.Composite &= ~(1 << spot_index);\n\n\t/*\n\t** If he was the last infantry recorded in the cell then\n\t** remove the infantry ownership flag.\n\t*/\n\tif (!(Map[cell].Flag.Composite & 0x1F)) {\n\t\tMap[cell].InfType = HOUSE_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                     *\n *                                                                                             *\n *    This routine will return with the full name (as a text number) for this infantry         *\n *    unit. Typically, this is the normal name, but in cases of civilian type survivors from   *\n *    a building explosion, it might be a technician instead. In such a case, the special      *\n *    technician name number is returned instead.                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the full name to use for this infantry unit.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/30/1995 JLB : Created.                                                                 *\n *   10/28/1996 JLB : Spy returns \"enemy soldier\" text name.                                   *\n *=============================================================================================*/\nint InfantryClass::Full_Name(void) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (IsTechnician) {\n\t\treturn(TXT_TECHNICIAN);\n\t}\n\n\tif (*this == INFANTRY_SPY && !House->IsPlayerControl) {\n\t\treturn(TXT_E1);\n\t}\n\n\treturn(Class->Full_Name());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Mission_Attack -- Intercept attack mission for special handling.             *\n *                                                                                             *\n *    This routine intercepts the normal attack mission and if an engineer is detected and the *\n *    target is a building, then the engineer will be automatically assigned the capture       *\n *    mission. In other cases, the normal attack logic will proceed.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *   04/15/1996 BWG : Engineers can only attack their own house's buildings now.               *\n *   05/29/1996 JLB : Engineers can now damage/capture enemy buildings.                        *\n *=============================================================================================*/\nint InfantryClass::Mission_Attack(void)\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsBomber && As_Building(TarCom)) {\n\t\tAssign_Destination(TarCom);\n\t\tAssign_Mission(MISSION_SABOTAGE);\n\t\treturn(1);\n\t}\n\n\tif (Class->IsCapture && As_Building(TarCom) != NULL && As_Building(TarCom)->Can_Capture()) {\n\t\tAssign_Destination(TarCom);\n\t\tAssign_Mission(MISSION_CAPTURE);\n\t\treturn(1);\n\t}\n\n\treturn(FootClass::Mission_Attack());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::What_Action -- Determines what action to perform for the cell specified.     *\n *                                                                                             *\n *    This routine will determine what action to perform if the mouse was clicked on the cell  *\n *    specified. This is just a courier function since the lower level classes actually        *\n *    perform the work. The need for this routine at this level is due to the existence of     *\n *    a similarly named function at this level as well.  C++ namespace rules require this      *\n *    function courier to be in place or an error will result.                                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse might be clicked upon.                            *\n *                                                                                             *\n * OUTPUT:  Returns with the action that would be given to this infantry unit if the mouse     *\n *          were clicked at the cell specified.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType InfantryClass::What_Action(CELL cell) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\tActionType action = FootClass::What_Action(cell);\n\n\t/*\n\t** Dogs can only attack infantrymen\n\t*/\n\tif (Class->IsDog && action == ACTION_ATTACK) {\n\t\taction = ACTION_NONE;\n\t}\n\n\t/*\n\t** If this is a medic, and the cursor's over a friendly infantryman,\n\t** execute an action-attack.\n\t*/\n\tif (Combat_Damage() < 0 && House->IsPlayerControl) {\n\t\tif (action == ACTION_ATTACK) {\n\t\t\taction = ACTION_NOMOVE;\n\t\t}\n\t}\n\n\t/*\n\t**\tDemolitioners may destroy a bridge\n\t*/\n\tif (Class->IsBomber && action == ACTION_MOVE && !Special.IsCaptureTheFlag) {\n\t\tswitch (Map[cell].TType) {\n\t\t\tcase TEMPLATE_BRIDGE1:\n\t\t\tcase TEMPLATE_BRIDGE2:\n\t\t\tcase TEMPLATE_BRIDGE1H:\n\t\t\tcase TEMPLATE_BRIDGE2H:\n\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\tcase TEMPLATE_BRIDGE_2A:\n\t\t\tcase TEMPLATE_BRIDGE_2B:\n//\t\t\tcase TEMPLATE_BRIDGE_3A:\n//\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\treturn(ACTION_SABOTAGE);\n\t\t}\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t** Engineers may repair a destroyed bridge.\n\t*/\n\tif (*this == INFANTRY_RENOVATOR && action == ACTION_NOMOVE) {\n\t\t/*\n\t\t** If they're pointing on the wrong side of the bridge, ignore it\n\t\t** 'cause we can't get there.\n\t\t*/\n\t\tTemplateType tt = Map[cell].TType;\n\t\tif (tt == TEMPLATE_BRIDGE1D || tt == TEMPLATE_BRIDGE2D ||\n\t\t\ttt == TEMPLATE_BRIDGE_1C || tt == TEMPLATE_BRIDGE_2C ||\n\t\t\t(tt >= TEMPLATE_BRIDGE_3C && tt <= TEMPLATE_BRIDGE_3E) ) {\n\t\t\t/*\n\t\t\t** We know they're pointing at a destroyed bridge cell.  If the cell\n\t\t\t** they're pointing at is surrounded by impassables, return this\n\t\t\t** cell as impassable.  But, if any cell surrounding this cell is\n\t\t\t** passable, return that this is a capturable cell.\n\t\t\t*/\n\t\t\tif (Map[cell].Land_Type() == LAND_ROCK) {\n\t\t\t\tif (tt == TEMPLATE_BRIDGE_3C) return(ACTION_CAPTURE);\n\n\t\t\t\tif (tt == TEMPLATE_BRIDGE_3C) return(ACTION_CAPTURE);\n\t\t\t\tint y = Cell_Y(cell);\n\t\t\t\tif (y) {\n\t\t\t\t\tLandType above = Map[(CELL)(cell-(MAP_CELL_W-1))].Land_Type();\n\t\t\t\t\tif (above == LAND_CLEAR || above == LAND_ROAD) {\n\t\t\t\t\t\tif (Map[(CELL)(cell-(MAP_CELL_W-1))].Zone == Map[As_Cell(As_Target())].Zone) {\n\t\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(ACTION_NOMOVE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (y < MAP_CELL_H) {\n\t\t\t\t\tLandType below = Map[(CELL)(cell + MAP_CELL_W-1)].Land_Type();\n\t\t\t\t\tif (below == LAND_CLEAR || below == LAND_ROAD) {\n\t\t\t\t\t\tif (Map[(CELL)(cell+MAP_CELL_W-1)].Zone == Map[As_Cell(As_Target())].Zone) {\n\t\t\t\t\t\t\treturn(ACTION_CAPTURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(ACTION_NOMOVE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(ACTION_NOMOVE);\n\t\t}\n\t}\n#endif\n\treturn(action);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Class_Of -- Returns the class reference for this object.                     *\n *                                                                                             *\n *    This routine will return a reference to the infantry type class object that describes    *\n *    this infantry's characteristics.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the InfantryTypeClass object associated with this      *\n *          infantry object.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass const & InfantryClass::Class_Of(void) const\n{\n\tassert(Infantry.ID(this) == ID);\n\tassert(IsActive);\n\n\treturn(*Class);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Read_INI -- Reads units from scenario INI file.                              *\n *                                                                                             *\n *    This routine is used to read all the starting units from the                             *\n *    scenario control INI file. The units are created and placed on the                       *\n *    map by this routine.                                                                     *\n *                                                                                             *\n *    INI entry format:                                                                        *\n *      Housename, Typename, Strength, Cellnum, CellSublocation, Missionname,                  *\n *         Facingnum, Triggername                                                              *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the loaded scenario INI file.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Read_INI(CCINIClass & ini)\n{\n\tInfantryClass\t* infantry;\t\t\t// Working infantry pointer.\n\tHousesType\t\tinhouse;\t\t\t// Infantry house.\n\tInfantryType\tclassid;\t\t\t// Infantry class.\n\tchar\t\t\t\tbuf[128];\n\tchar\t\t\t\t* validation;\n\tDirType \t\t\tdir;\n\tTriggerTypeClass\t* tp;\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\n\t\t/*\n\t\t**\tGet an infantry entry\n\t\t*/\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\n\t\t/*\n\t\t**\t1st token: house name.\n\t\t*/\n\t\tinhouse = HouseTypeClass::From_Name(strtok(buf, \",\\n\\r\"));\n\t\tif (inhouse != HOUSE_NONE) {\n\n\t\t\t/*\n\t\t\t**\t2nd token: infantry type name.\n\t\t\t*/\n\t\t\tclassid = InfantryTypeClass::From_Name(strtok(NULL, \",\\n\\r\"));\n\n\t\t\tif (classid != INFANTRY_NONE) {\n\n\t\t\t\tif (HouseClass::As_Pointer(inhouse) != NULL) {\n\t\t\t\t\tinfantry = new InfantryClass(classid, inhouse);\n\t\t\t\t\tif (infantry != NULL) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\t3rd token: strength.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tint strength = atoi(strtok(NULL, \",\\n\\r\"));\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\t4th token: cell #.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tCELL cell = atoi(strtok(NULL, \",\\n\\r\"));\n\t\t\t\t\t\tCOORDINATE coord = Cell_Coord(cell);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\t5th token: cell sub-location.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tint sub = atoi(strtok(NULL, \",\"));\n\t\t\t\t\t\tcoord = Coord_Add(Coord_Whole(coord), StoppingCoordAbs[ sub ]);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFetch the mission and facing.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tMissionType mission = MissionClass::Mission_From_Name(strtok(NULL, \",\\n\\r\"));\n\t\t\t\t\t\tvalidation = strtok(NULL, \",\\n\\r\");\n\t\t\t\t\t\tif (validation) {\n\t\t\t\t\t\t\tdir = (DirType)atoi(validation);\n\t\t\t\t\t\t\tvalidation = strtok(NULL, \",\\n\\r\");\n\t\t\t\t\t\t\tif (validation) {\n\t\t\t\t\t\t\t\ttp = TriggerTypeClass::From_Name(validation);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttp = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdir = (DirType)0;\n\t\t\t\t\t\t\ttp = NULL;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tinfantry->Trigger = NULL;\n\t\t\t\t\t\tif (tp != NULL) {\n\t\t\t\t\t\t\tTriggerClass * tt = Find_Or_Make(tp);\n\t\t\t\t\t\t\tif (tt != NULL) {\n\t\t\t\t\t\t\t\ttt->AttachCount++;\n\t\t\t\t\t\t\t\tinfantry->Trigger = tt;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (infantry->Unlimbo(coord, dir)) {\n\t\t\t\t\t\t\tinfantry->Strength = (int)infantry->Class_Of().MaxStrength * fixed(strength, 256);\n\t\t\t\t\t\t\tif (infantry->Strength > infantry->Class->MaxStrength-3) infantry->Strength = infantry->Class->MaxStrength;\n\t//\t\t\t\t\t\tinfantry->Strength = Fixed_To_Cardinal(infantry->Class_Of().MaxStrength, strength);\n\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL || infantry->House->IsHuman) {\n\t\t\t\t\t\t\t\tinfantry->Assign_Mission(mission);\n\t\t\t\t\t\t\t\tinfantry->Commence();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tinfantry->Enter_Idle_Mode();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the infantry could not be unlimboed, then this is a big error.\n\t\t\t\t\t\t\t**\tDelete the infantry.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tdelete infantry;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Write_INI -- Store the infantry to the INI database.                         *\n *                                                                                             *\n *    This will store all the infantry objects to the INI database specified.                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to store the infantry data to.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing infantry data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tWrite the infantry data out.\n\t*/\n\tfor (int index = 0; index < Infantry.Count(); index++) {\n\t\tInfantryClass * infantry = Infantry.Ptr(index);\n\t\tif (!infantry->IsInLimbo) {\n\t\t\tchar\tuname[10];\n\t\t\tchar\tbuf[128];\n\n\t\t\tsprintf(uname, \"%d\", index);\n\t\t\tsprintf(buf, \"%s,%s,%d,%u,%d,%s,%d,%s\",\n\t\t\t\t\tinfantry->House->Class->IniName,\n\t\t\t\t\tinfantry->Class->IniName,\n\t\t\t\t\tinfantry->Health_Ratio()*256,\n\t\t\t\t\tCoord_Cell(infantry->Coord),\n\t\t\t\t\tCellClass::Spot_Index(infantry->Coord),\n\t\t\t\t\tMissionClass::Mission_Name((infantry->Mission == MISSION_NONE) ?\n\t\t\t\t\t\tinfantry->MissionQueue : infantry->Mission),\n\t\t\t\t\tinfantry->PrimaryFacing.Current(),\n\t\t\t\t\tinfantry->Trigger.Is_Valid() ? infantry->Trigger->Class->IniName : \"None\"\n\t\t\t\t);\n\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Fear_AI -- Process any fear related affects on this infantry.                *\n *                                                                                             *\n *    Use this routine to handle the fear logic for this infantry. It will slowly increase     *\n *    the bravery of the infantry as well as cause it to stand up or lie down as appropriate.  *\n *    It will even handle the special fraidy cat logic for civilian infantry.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this once per game logic loop per infantry unit.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Fear_AI(void)\n{\n\t/*\n\t**\tAfter a time, the infantry will gain courage.\n\t*/\n\tif (Fear > 0) {\n\n\t\tFear--;\n\n\t\t/*\n\t\t**\tWhen an armed civilian becomes unafraid, he will then reload\n\t\t**\tanother clip into his pistol.\n\t\t*/\n\t\tif (Fear == 0 && Ammo == 0 && Is_Weapon_Equipped()) {\n\t\t\tAmmo = Class->MaxAmmo;\n\t\t}\n\n\t\t/*\n\t\t**\tStand up if brave and lie down if afraid.\n\t\t*/\n\t\tif (IsProne) {\n\t\t\tif (Fear < FEAR_ANXIOUS) {\n\t\t\t\tDo_Action(DO_GET_UP);\n\t\t\t}\n\t\t} else  {\n\n\t\t\t/*\n\t\t\t**\tDrop to the ground if anxious. Don't drop to the ground while moving\n\t\t\t**\tand the special elite flag is active.\n\t\t\t*/\n\t\t\tif (!Class->IsDog && Height == 0 && Fear >= FEAR_ANXIOUS && ((!Target_Legal(NavCom) && !IsDriving))) {\n\t\t\t\tDo_Action(DO_LIE_DOWN);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWhen in darkness or in doubt,\n\t**\t\trun in circles, scream, and shout.\n\t*/\n\tif (Class->IsFraidyCat && Fear > FEAR_ANXIOUS && !IsFalling && !IsDriving && !Target_Legal(NavCom)) {\n\t\tScatter(0, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Edge_Of_World_AI -- Detects when infantry has left the map.                  *\n *                                                                                             *\n *    This routine will detect when the infantry has left the edge of the world and will       *\n *    delete it as necessary.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the infantry unit deleted by this routine?                               *\n *                                                                                             *\n * WARNINGS:   Be sure the check the return value and if true, abort any further processing    *\n *             for this infantry unit.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Edge_Of_World_AI(void)\n{\n\t/*\n\t**\tDelete this unit if it finds itself off the edge of the map and it is in\n\t**\tguard or other static mission mode.\n\t*/\n\tif (Team.Is_Valid() && IsLocked) Team->IsLeaveMap = true;\n\n\tif (!Team.Is_Valid() && Mission == MISSION_GUARD && !Map.In_Radar(Coord_Cell(Coord))) {\n\t\tStun();\n\t\tdelete this;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Firing_AI -- Handles firing and combat AI for the infantry.                  *\n *                                                                                             *\n *    This will examine the infantry and determine what firing action is required. It will     *\n *    search for targets, starting firing animations, and launch bullets as necessary.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry per game logic loop.                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Firing_AI(void)\n{\n\tif (Target_Legal(TarCom)) {\n\t\tint primary = What_Weapon_Should_I_Use(TarCom);\n\n\t\tif (!IsFiring) {\n\t\t\tswitch (Can_Fire(TarCom, primary)) {\n\t\t\t\tcase FIRE_ILLEGAL:\n\t\t\t\t\tif (Combat_Damage(primary) < 0) {\n\t\t\t\t\t\tObjectClass * targ= As_Object(TarCom);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tif (targ) {\n\t\t\t\t\t\t\tif( (targ->What_Am_I() == RTTI_INFANTRY && *this == INFANTRY_MEDIC) ||\n\t\t\t\t\t\t\t\t (*this == INFANTRY_MECHANIC && (targ->What_Am_I() == RTTI_AIRCRAFT || targ->What_Am_I() == RTTI_UNIT )) ) {\n\n\t\t\t\t\t\t\t\t\tif (targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\tif (targ && targ->What_Am_I() == RTTI_INFANTRY) {\n\t\t\t\t\t\t\tif (targ->Health_Ratio() >= Rule.ConditionGreen) {\n\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t} else if (Class->IsDog) {\n\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_CLOAKED:\n\t\t\t\t\tDo_Uncloak();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase FIRE_OK:\n\t\t\t\t\t/*\n\t\t\t\t\t**\tStart firing animation.\n\t\t\t\t\t*/\n\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\tDo_Action(DO_FIRE_PRONE);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDo_Action(DO_FIRE_WEAPON);\n\t\t\t\t\t}\n\n\t\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\t\tIsFiring = true;\n\t\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\n\t\t\t\t\tPrimaryFacing.Set(Direction8(Center_Coord(), As_Coord(TarCom)));\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the target is in range, and the NavCom is the same, then just\n\t\t\t\t\t**\tstop and keep firing.\n\t\t\t\t\t*/\n\t\t\t\t\tif (TarCom == NavCom) {\n\t\t\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf in the middle of firing animation, then only\n\t\t**\tprocess that. Infantry cannot fire and move simultaneously.\n\t\t**\tAt some point in the firing animation process, a projectile\n\t\t**\twill be launched. When the required animation frames have\n\t\t**\tbeen completed, the firing animation stops.\n\t\t*/\n\t\tint firestage = Class->FireLaunch;\n\t\tif (IsProne) firestage = Class->ProneLaunch;\n\n\t\tif (IsFiring && Fetch_Stage() == firestage) {\n\n\t\t\t/*\n\t\t\t**\tTarget might have changed during the firing animation\n\t\t\t*/\n\t\t\tif (Can_Fire(TarCom, primary) == FIRE_OK) {\n\t\t\t\tFire_At(TarCom, primary);\n\n\t\t\t\t/*\n\t\t\t\t**\tRun away from slowly approaching projectiles.\n\t\t\t\t*/\n\t\t\t\tif (Class->PrimaryWeapon->MaxSpeed < Rule.Incoming) {\n\t\t\t\t\tMap[::As_Cell(TarCom)].Incoming(Coord, true);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If it's a dog, get rid of him (he'll be re-created when he hits)\n\t\t\t\t*/\n\t\t\t\tif (Class->IsDog) {\n\t\t\t\t\tWasSelected = IsSelected;\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tLimbo();\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\t\tIsFiring = false;\n\t\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (IsFiring) {\n\t\t\tMark(MARK_OVERLAP_UP);\n\t\t\tIsFiring = false;\n\t\t\tMark(MARK_OVERLAP_DOWN);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Doing_AI -- Handles the animation AI processing.                             *\n *                                                                                             *\n *    Infantry can be in one of many different animation sequences. At the conclusion of each  *\n *    sequence, the infantry will quite likely transition to a new animation state. This       *\n *    routine handles detecting when that trasition should occur and starting the infantry     *\n *    into its new state.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry unit per game logic loop.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Doing_AI(void)\n{\n\tif (Doing == DO_NOTHING || Fetch_Stage() >= Class->DoControls[Doing].Count) {\n\t\tswitch (Doing) {\n\t\t\tdefault:\n\t\t\t\tif (IsDriving) {\n\t\t\t\t\tif (Class->IsDog) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDog crawl animation is actually the run animation.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\tDo_Action(DO_CRAWL, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_WALK, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\tDo_Action(DO_CRAWL, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_WALK, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (Class->IsDog) {\n\t\t\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\tDo_Action(DO_PRONE, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase DO_DOG_MAUL:\n\t\t\t\tDo_Action(DO_STAND_READY, true);\n\t\t\t\tbreak;\n\n\t\t\tcase DO_GUN_DEATH:\n\t\t\tcase DO_EXPLOSION_DEATH:\n\t\t\tcase DO_EXPLOSION2_DEATH:\n\t\t\tcase DO_GRENADE_DEATH:\n\t\t\tcase DO_FIRE_DEATH:\n\t\t\t\tif (Fetch_Stage() >= Class->DoControls[Doing].Count) {\n\t\t\t\t\tAnimClass* anim = NULL;\n\t\t\t\t\tLandType land = Map[Center_Coord()].Land_Type();\n\t\t\t\t\tif (land != LAND_ROCK && land != LAND_WATER && land != LAND_RIVER) {\n\t\t\t\t\t\tif (Doing == DO_GUN_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\t\tanim = new AnimClass(ANIM_CORPSE1, Coord_Add(Center_Coord(), XYP_Coord(-2, 4)));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Doing == DO_GRENADE_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\t\tanim = new AnimClass(ANIM_CORPSE1, Coord_Add(Center_Coord(), XYP_Coord(-10, 3)));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Doing == DO_EXPLOSION_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\t\tanim = new AnimClass(ANIM_CORPSE3, Coord_Add(Center_Coord(), XYP_Coord(-2, 4)));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Doing == DO_EXPLOSION2_DEATH && !Class->IsDog && Height==0) {\n\t\t\t\t\t\t\tanim = new AnimClass(ANIM_CORPSE2, Center_Coord());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (anim != NULL) {\n\t\t\t\t\t\tanim->Set_Owner(House->Class->House);\n\t\t\t\t\t}\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Movement_AI -- This routine handles all infantry movement logic.             *\n *                                                                                             *\n *    It examines the infantry state and determines what movement action should be initiated   *\n *    or processed. It handles the actual movement of the infantry as well as any path finding *\n *    or infantry startup logic.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once per infantry unit per game logic loop.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid InfantryClass::Movement_AI(void)\n{\n\t/*\n\t**\tSpecial hack check to ensure that infantry will never get stuck in a movement order if\n\t**\tthere is no place to go.\n\t*/\n\tif (Mission == MISSION_MOVE && !Target_Legal(NavCom)) {\n\t\tEnter_Idle_Mode();\n\t}\n\n\tif (!IsFiring && !IsFalling && Doing != DO_DOG_MAUL) {\n\t\tif (!IsDriving) {\n\n\t\t\t/*\n\t\t\t**\tWhen in guard mode, never allow a valid navcom.\n\t\t\t*/\n\t\t\tif (Mission == MISSION_GUARD && MissionQueue == MISSION_NONE && Target_Legal(NavCom)) {\n\t\t\t\tAssign_Destination(TARGET_NONE);\n//\t\t\t\tif (IsTethered) Scatter(0, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tScatter infantry off buildings in guard modes.\n\t\t\t*/\n\t\t\tif (!IsTethered && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA) && MissionQueue == MISSION_NONE && Map[Coord].Cell_Building() != NULL) {\n\t\t\t\tScatter(0, true, true);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDouble check to make sure it doesn't have a movement destination into a zone\n\t\t\t**\tthat it can't travel to. In such a case, abort the movement process by clearing\n\t\t\t**\tthe navigation computer.\n\t\t\t*/\n\t\t\tif ((!IsZoneCheat || Can_Enter_Cell(Coord_Cell(Coord)) != MOVE_NO) && !IsDriving && !IsTethered && Target_Legal(NavCom) && IsLocked && Map[Coord].Zones[Class->MZone] != Map[As_Cell(NavCom)].Zones[Class->MZone]) {\n// hack: if it's tanya, spy, or engineer, let 'em move there anyway.\n\t\t\t\tif (!Class->IsCapture && Mission != MISSION_ENTER) {\n//\t\t\t\tif (*this != INFANTRY_TANYA && *this != INFANTRY_SPY && *this != INFANTRY_RENOVATOR) {\n\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA head to coordinate is needed. If there is no path\n\t\t\t**\tavailable, then create one.\n\t\t\t*/\n\t\t\tif (Target_Legal(NavCom) && Strength && Mission != MISSION_GUARD) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine if the next cell in the list is available\n\t\t\t\t**\tto be entered. If not, then abort the path and try\n\t\t\t\t**\tagain.\n\t\t\t\t*/\n\t\t\t\tif (Path[0] != FACING_NONE && Can_Enter_Cell(Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0])) != MOVE_OK) {\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck to see if the target is closer than expected. This occurs\n\t\t\t\t**\twhen heading toward a moving object and that object is heading\n\t\t\t\t**\ttoward the unit. Shorten the precalculated path to be no longer\n\t\t\t\t**\tthan the distance to the target.\n\t\t\t\t*/\n\t\t\t\tint d = Lepton_To_Cell(Distance(NavCom));\n\t\t\t\tif (d < CONQUER_PATH_MAX) {\n\t\t\t\t\tPath[d] = FACING_NONE;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tFind a path to follow if one isn't already calculated.\n\t\t\t\t*/\n\t\t\t\tif (Path[0] == FACING_NONE) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCalculate the path from the current location to the\n\t\t\t\t\t**\tdestination indicated by the navigation computer. If there\n\t\t\t\t\t**\twas a fundamental error with finding a path, then this\n\t\t\t\t\t**\tindicates that basic path & movement logic needs to be\n\t\t\t\t\t**\taborted.\n\t\t\t\t\t*/\n\t\t\t\t\tif (PathDelay != 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!Basic_Path()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCheck to ensure that if a computer controlled unit is in\n\t\t\t\t\t\t**\thunt mode, but cannot reach the target it would like to,\n\t\t\t\t\t\t**\tabort the target tracking and let the normal hunt logic\n\t\t\t\t\t\t**\tassign a new one.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!House->IsHuman && Mission == MISSION_HUNT) {\n\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf the infantry unit is close enough to the target, then\n\t\t\t\t\t\t\t**\ttell it to stop.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Distance(NavCom) < Rule.CloseEnoughDistance && !IsTethered) {\n\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tUpdate the try try again counter so that this\n\t\t\t\t\t\t\t\t**\tinfantry unit will try again at a later time.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (TryTryAgain) {\n\t\t\t\t\t\t\t\t\tTryTryAgain--;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\t\t\t\t\tIsNewNavCom = false;\n\n\t\t\t\t\t\t\t\t\t//If we're trying to enter a transport we need to fail so others can try to enter. - LLL 4/17/2020\n\t\t\t\t\t\t\t\t\tif (Mission == MISSION_ENTER) {\n\t\t\t\t\t\t\t\t\t\tMission = MISSION_NONE;\n\t\t\t\t\t\t\t\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t\t\t\tCommence();\n\n\t\t\t\t\t\t\t\t\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tAbort the target and destination process since the path\n\t\t\t\t\t\t\t\t\t**\tcould not be found. In such a case, processing should stop\n\t\t\t\t\t\t\t\t\t**\tor else the game will bog down with repeated path failures.\n\t\t\t\t\t\t\t\t\t**\tOnly perform the abort of the target is in a different zone.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif ((!IsZoneCheat || Can_Enter_Cell(Coord_Cell(Coord)) != MOVE_NO) && IsLocked && Target_Legal(NavCom) && Map[As_Cell(NavCom)].Zones[Class->MZone] != Map[Coord].Zones[Class->MZone]) {\n\t\t\t\t\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (IsLocked && Target_Legal(TarCom) && Map[As_Cell(TarCom)].Zones[Class->MZone] != Map[Coord].Zones[Class->MZone]) {\n\t\t\t\t\t\t\t\t\t\tAssign_Target(TARGET_NONE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tStop_Driver();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tTryTryAgain = PATH_RETRY;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDetermine the coordinate to head to based on the infantry's\n\t\t\t\t**\tcurrent location and the next location in the path.\n\t\t\t\t*/\n\t\t\t\tCOORDINATE acoord = Adjacent_Cell(Coord, Path[0]);\n\t\t\t\tCELL acell = Coord_Cell(acoord);\n\n\t\t\t\tif (Can_Enter_Cell(acell) != MOVE_OK) {\n\n\t\t\t\t\tif ((Mission == MISSION_MOVE || Mission == MISSION_ENTER) && !IsTethered /*&& House->IsHuman*/ && Distance(NavCom) < Rule.CloseEnoughDistance) {\n\t\t\t\t\t\tAssign_Destination(TARGET_NONE);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If blocked by a moving block then just exit start of move and\n\t\t\t\t\t\t** try again next tick.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Can_Enter_Cell(acell) == MOVE_DESTROYABLE) {\n\t\t\t\t\t\t\tif (Map[acell].Cell_Object()) {\n\t\t\t\t\t\t\t\tif (!House->Is_Ally(Map[acell].Cell_Object())) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, Map[acell].Cell_Object()->As_Target(), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (Map[acell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[acell].Overlay).IsWall) {\n\t\t\t\t\t\t\t\t\tOverride_Mission(MISSION_ATTACK, ::As_Target(acell), TARGET_NONE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t\tStop_Driver();\n\t\t\t\t\tif (IsNewNavCom) Sound_Effect(VOC_SCOLD);\n\t\t\t\t\tIsNewNavCom = false;\n\n\t\t\t\t} else {\n\t\t\t\t\tif (Start_Driver(acoord)) {\n\t\t\t\t\t\tif (!IsActive) return;\n\t\t\t\t\t\tPrimaryFacing.Set(Direction8(Center_Coord(), Head_To_Coord()));\n\t\t\t\t\t\tif (IsFormationMove) {\n\t\t\t\t\t\t\tSet_Speed(Ground[Map[Coord].Land_Type()].Cost[FormationSpeed] * 255);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSet_Speed(0xFF);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Class->IsDog) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tDog crawl animation is actually the run animation.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Target_Legal(TarCom)) {\n\t\t\t\t\t\t\t\tDo_Action(DO_CRAWL);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDo_Action(DO_WALK);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (IsProne) {\n\t\t\t\t\t\t\t\tDo_Action(DO_CRAWL);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDo_Action(DO_WALK);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tThe infantry knows where it should be headed, so head there. Check\n\t\t\t**\tto see if the infantry is \"close enough\" to the desired location that\n\t\t\t**\tit should just consider itself to have arrived. In this case, force\n\t\t\t**\tthe infantry to the destination location and mark this path step\n\t\t\t**\tas complete.\n\t\t\t*/\n\t\t\tMark(MARK_UP);\n\t\t\tif (Distance(Head_To_Coord()) < 0x0010) {\n\n\t\t\t\tmemcpy(&Path[0], &Path[1], sizeof(Path)-sizeof(Path[0]));\n\t\t\t\tPath[(sizeof(Path)/sizeof(Path[0]))-1] = FACING_NONE;\n\t\t\t\tCoord = Head_To_Coord();\n\t\t\t\tPer_Cell_Process(PCP_END);\n\t\t\t\tif (!IsActive || IsInLimbo) return;\n\n\t\t\t\tStop_Driver();\n\t\t\t\tif (!IsActive || IsInLimbo) return;\n\n\t\t\t\tif (Coord_Cell(Coord) == As_Cell(NavCom)) {\n\t\t\t\t\tNavCom = TARGET_NONE;\n\t\t\t\t\tif (Mission == MISSION_MOVE) {\n\t\t\t\t\t\tEnter_Idle_Mode();\n\t\t\t\t\t}\n\t\t\t\t\t//Stop_Driver();\n\t\t\t\t\tPath[0] = FACING_NONE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tint\tmovespeed = Speed;\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen prone, the infantry moves at half speed or double\n\t\t\t\t**\tspeed. This depends on whether the infantry actually has\n\t\t\t\t**\tprone animation stages. Civilians don't, and so they\n\t\t\t\t**\trun instead.\n\t\t\t\t*/\n\t\t\t\tif (Class->IsDog && Target_Legal(TarCom)) {\n\t\t\t\t\tmovespeed *= 2;\n\t\t\t\t}\n\n\t\t\t\tif (IsProne && !Class->IsDog) {\n\t\t\t\t\tif ((Class->IsFraidyCat && !Class->IsCrawling) ) {\n\t\t\t\t\t\tmovespeed = Speed*2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmovespeed = Speed/2;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (IsTethered) {\n\t\t\t\t\tTransmit_Message(RADIO_REDRAW);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAdvance the infantry as far as it should go.\n\t\t\t\t*/\n\t\t\t\tMPHType maxspeed = MPHType(min(Class->MaxSpeed * SpeedBias * House->GroundspeedBias, MPH_LIGHT_SPEED));\n\n\t\t\t\tif (IsFormationMove) maxspeed = FormationMaxSpeed;\n\n\t\t\t\tCoord = Coord_Move(Coord, Direction(Head_To_Coord()), maxspeed * fixed(movespeed, 256));\n\t\t\t}\n\t\t\tMark(MARK_DOWN);\n\t\t}\n\t\tIsNewNavCom = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Get_Image_Data -- Fetches the image data for this infantry unit.             *\n *                                                                                             *\n *    The image data for the infantry differs from normal if this is a spy. A spy always       *\n *    appears like a minigunner to the non-owning players.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the image data to use for this infantry soldier.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * InfantryClass::Get_Image_Data(void) const\n{\n\tif (!IsOwnedByPlayer && *this == INFANTRY_SPY) {\n\t\treturn(MFCD::Retrieve(\"E1.SHP\"));\n\t}\n\treturn(TechnoClass::Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Is_Ready_To_Random_Anima -- Checks to see if it is ready to perform an idle  *\n *                                                                                             *\n *    This routine will examine this infantry and determine if it is allowed and ready to      *\n *    perform an idle animation. The conditions under which idle animations can be performed   *\n *    are restrictive. Hence this routine.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is this infantry ready to do an idle animation?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Is_Ready_To_Random_Animate(void) const\n{\n\t/*\n\t**\tSee if the base classes (more rudimentary checking) determines that idle animations\n\t**\tcannot occur. If they cannot, then return with the failure code.\n\t*/\n\tif (!FootClass::Is_Ready_To_Random_Animate()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhile the infantry is in the air (such as when paradropping), it won't be allowed\n\t**\tto idle animate.\n\t*/\n\tif (Height > 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen the infantry is walking or otherwise engauged in travel, it won't idle animate.\n\t*/\n\tif (IsDriving) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen prone, idle animations cannot occur. This is primarily because there are no prone\n\t**\tidle animations.\n\t*/\n\tif (IsProne) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tWhen firing, the infantry should not perform any idle animations.\n\t*/\n\tif (IsFiring) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOnly if the infantry is in guard or ready stance is idle animations allowed. This is\n\t**\tbecause the idle animations start and end with these frames.\n\t*/\n\tif (Doing != DO_STAND_GUARD && Doing != DO_STAND_READY) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSince no reason was found to indicate it is not a good time to idle\n\t**\tanimate, then it must be a good time to do so.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * InfantryClass::Paradrop -- Handles paradropping infantry.                                   *\n *                                                                                             *\n *    This routine will paradrop this soldier at the location specified. It will cause the     *\n *    soldier to hunt if controlled by the computer and to guard if controlledy by the         *\n *    human.                                                                                   *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to paradrop the soldier to.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the paradrop successful?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool InfantryClass::Paradrop(COORDINATE coord)\n{\n\tif (FootClass::Paradrop(coord)) {\n\t\tif (House->IsHuman) {\n\t\t\tAssign_Mission(MISSION_GUARD);\n\t\t} else {\n\t\t\tAssign_Mission(MISSION_HUNT);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}"
  },
  {
    "path": "REDALERT/INFANTRY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INFANTRY.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INFANTRY.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 15, 1994                                              *\n *                                                                                             *\n *                  Last Update : August 15, 1994   [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INFANTRY_H\n#define INFANTRY_H\n\n\nclass InfantryClass : public FootClass\n{\n\tpublic:\n\t\tCCPtr<InfantryTypeClass> Class;\n\n\t\t/*\n\t\t**\tIf the infantry is undergoing some choreographed animation sequence, then\n\t\t**\tthis holds the particular sequence number. The frame of animation is kept\n\t\t**\ttrack of by the regular frame tracking system. When performing an animation\n\t\t**\tsequence, the infantry cannot perform anything else (even move).\n\t\t*/\n\t\tDoType Doing;\n\n\t\t/*\n\t\t**\tCertain infantry will either perform some comment or say something after an\n\t\t**\tamount of time has expired subsequent to an significant event. This is the\n\t\t**\ttimer the counts down.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Comment;\n\n\t\t/*\n\t\t**\tIf this civilian is actually a technician, then this flag will be true.\n\t\t**\tIt should only be set for the civilian type infantry. Typically, the\n\t\t**\ttechnician appears after a building is destroyed.\n\t\t*/\n\t\tunsigned IsTechnician:1;\n\n\t\t/*\n\t\t**\tIf the infantry just performed some feat, then it may respond with an action.\n\t\t**\tThis flag will be true if an action is to be performed when the Comment timer\n\t\t**\thas expired.\n\t\t*/\n\t\tunsigned IsStoked:1;\n\n\t\t/*\n\t\t**\tThis flag indicates if the infantry unit is prone. Prone infantry become that way\n\t\t**\twhen they are fired upon. Infantry in the prone position are less vulnerable to\n\t\t**\tcombat.\n\t\t*/\n\t\tunsigned IsProne:1;\n\n\t\t/*\n\t\t**\tIf the infantry is allowed to move one cell from one zone to another, then this\n\t\t**\tflag will be true. It exists only so that when a bridge is destroyed, the bomb\n\t\t**\tplacer is allowed to run from the destroyed bridge cell back onto a real cell.\n\t\t*/\n\t\tunsigned IsZoneCheat:1;\n\n\t\t/*\n\t\t** This flag is set for the dogs, when they launch into bullet mode.\n\t\t** it's to remember if the unit was selected, and if it was, then\n\t\t** when the dog is re-enabled, he'll reselect himself.\n\t\t*/\n\t\tunsigned WasSelected:1;\n\n\t\t/*\n\t\t**\tThe fear rating of this infantry unit. The more afraid the infantry, the more\n\t\t**\tlikely it is to panic and seek cover.\n\t\t*/\n\t\tFearType Fear;\n\n\t\t/*\n\t\t** Track when movement last stopped.\n\t\t*/\n\t\tlong StopDriverFrame;\n\n\t\t/*\n\t\t** Track the last cell we looked from.\n\t\t*/\n\t\tCELL LookCell;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tInfantryClass(InfantryType classid, HousesType house);\n\t\tInfantryClass(NoInitClass const & x) : FootClass(x), Class(x), Comment(x) {};\n\t\tvirtual ~InfantryClass(void);\n\t\toperator InfantryType(void) const {return Class->Type;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\tvirtual void Assign_Destination(TARGET);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual bool Is_Ready_To_Random_Animate(void) const;\n\t\tvoid const * Get_Image_Data(void) const;\n\t\tint Shape_Number(WindowNumberType window = WINDOW_MAIN) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const;\n\t\tvirtual int Full_Name(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Unlimbo(COORDINATE coord, DirType facing);\n\t\tvirtual bool Paradrop(COORDINATE coord);\n\t\tvirtual bool Limbo(void);\n\t\tvirtual void Detach(TARGET target, bool all);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual short const * Overlap_List(bool redraw = false) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType window) const;\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Response_Select(void);\n\t\tvirtual void Response_Move(void);\n\t\tvirtual void Response_Attack(void);\n\t\tvirtual void Active_Click_With(ActionType action, ObjectClass * object);\n\t\tvirtual void Active_Click_With(ActionType action, CELL cell) {FootClass::Active_Click_With(action, cell);}\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual ActionType What_Action(ObjectClass const * object) const;\n\t\tvirtual ActionType What_Action(CELL cell) const;\n\t\tvirtual BulletClass * Fire_At(TARGET target, int which);\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual FireErrorType Can_Fire(TARGET target, int which) const;\n\t\tvirtual COORDINATE Fire_Coord(int which) const;\n\t\tvirtual void Assign_Target(TARGET);\n\t\tvoid Set_Occupy_Bit(COORDINATE coord) {Set_Occupy_Bit(Coord_Cell(coord), CellClass::Spot_Index(coord));};\n\t\tvoid Set_Occupy_Bit(CELL cell, int spot_index);\n\t\tvoid Clear_Occupy_Bit(COORDINATE coord) {Clear_Occupy_Bit(Coord_Cell(coord), CellClass::Spot_Index(coord));};\n\t\tvoid Clear_Occupy_Bit(CELL cell, int spot_index);\n\n\t\t/*\n\t\t**\tDriver control support functions. These are used to control cell\n\t\t**\toccupation flags and driver instructions.\n\t\t*/\n\t\tvirtual bool Stop_Driver(void);\n\t\tvirtual bool Start_Driver(COORDINATE & coord);\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void AI(void);\n\t\tvoid Fear_AI(void);\n\t\tvirtual TARGET Greatest_Threat(ThreatType threat) const;\n\t\tvirtual int Mission_Attack(void);\n\t\tbool Edge_Of_World_AI(void);\n\t\tvoid Firing_AI(void);\n\t\tvoid Doing_AI(void);\n\t\tvoid Movement_AI(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"INFANTRY\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tMovement and animation.\n\t\t*/\n\t\tvirtual bool Do_Action(DoType todo, bool force=false);\n\t\tvirtual bool Random_Animate(void);\n\t\tvirtual MoveType Can_Enter_Cell(CELL , FacingType =FACING_NONE) const;\n\t\tvirtual void Per_Cell_Process(PCPType why);\n\t\tvirtual void Enter_Idle_Mode(bool initial=false);\n\t\tvirtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);\n\t\tvirtual void Look(bool incremental=false);\n\n\t\t/*\n\t\t**\tTranslation table to convert facing into infantry shape number. This special\n\t\t**\ttable is needed since several facing stages are reused and flipped about the Y\n\t\t**\taxis.\n\t\t*/\n\t\tstatic int const HumanShape[32];\n\n\tprivate:\n\n\t\tstatic DoStruct const MasterDoControls[DO_COUNT];\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[32];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/INI.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INI.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INI.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   INIClass::Clear -- Clears out a section (or all sections) of the INI data.                *\n *   INIClass::Entry_Count -- Fetches the number of entries in a specified section.            *\n *   INIClass::Find_Entry -- Find specified entry within section.                              *\n *   INIClass::Find_Section -- Find the specified section within the INI data.                 *\n *   INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.          *\n *   INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name*\n *   INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.               *\n *   INIClass::Put_Fixed -- Store a fixed point number to the INI database.                    *\n *   INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.   *\n *   INIClass::Get_Int -- Fetch an integer entry from the specified section.                   *\n *   INIClass::Get_PKey -- Fetch a key from the ini database.                                  *\n *   INIClass::Get_String -- Fetch the value of a particular entry in a specified section.     *\n *   INIClass::Get_TextBlock -- Fetch a block of normal text.                                  *\n *   INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.               *\n *   INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.    *\n *   INIClass::Load -- Load INI data from the file specified.                                  *\n *   INIClass::Load -- Load the INI data from the data stream (straw).                         *\n *   INIClass::Put_Bool -- Store a boolean value into the INI database.                        *\n *   INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.        *\n *   INIClass::Put_Int -- Stores a signed integer into the INI data base.                      *\n *   INIClass::Put_PKey -- Stores the key to the INI database.                                 *\n *   INIClass::Put_String -- Output a string to the section and entry specified.               *\n *   INIClass::Put_TextBlock -- Stores a block of text into an INI section.                    *\n *   INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.         *\n *   INIClass::Save -- Save the ini data to the file specified.                                *\n *   INIClass::Save -- Saves the INI data to a pipe stream.                                    *\n *   INIClass::Section_Count -- Counts the number of sections in the INI data.                 *\n *   INIClass::Strip_Comments -- Strips comments of the specified text line.                   *\n *   INIClass::~INIClass -- Destructor for INI handler.                                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<stddef.h>\n#include\t<stdio.h>\n#include\t<ctype.h>\n#include\t\"ini.h\"\n#include\t\"readline.h\"\n#include\t\"xpipe.h\"\n#include\t\"b64pipe.h\"\n#include\t\"xstraw.h\"\n#include\t\"b64straw.h\"\n\n\n#ifdef FIXIT_FAST_LOAD\n#include\t\"cstraw.h\"\n#endif\n\n\n\n// Disable the \"temporary object used to initialize a non-constant reference\" warning.\n//#pragma warning 665 9\n\n\n/***********************************************************************************************\n * INIClass::~INIClass -- Destructor for INI handler.                                          *\n *                                                                                             *\n *    This is the destructor for the INI class. It handles deleting all of the allocations     *\n *    it might have done.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nINIClass::~INIClass(void)\n{\n\tClear();\n}\n\n\n/***********************************************************************************************\n * INIClass::Clear -- Clears out a section (or all sections) of the INI data.                  *\n *                                                                                             *\n *    This routine is used to clear out the section specified. If no section is specified,     *\n *    then the entire INI data is cleared out. Optionally, this routine can be used to clear   *\n *    out just an individual entry in the specified section.                                   *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section to clear out [pass NULL to clear all].          *\n *                                                                                             *\n *          entry    -- Pointer to optional entry specifier. If this parameter is specified,   *\n *                      then only this specific entry (if found) will be cleared. Otherwise,   *\n *                      the entire section specified will be cleared.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   08/21/1996 JLB : Optionally clears section too.                                           *\n *   11/02/1996 JLB : Updates the index list.                                                  *\n *=============================================================================================*/\nbool INIClass::Clear(char const * section, char const * entry)\n{\n\tif (section == NULL) {\n\t\tSectionList.Delete();\n\t\tSectionIndex.Clear();\n\t} else {\n\t\tINISection * secptr = Find_Section(section);\n\t\tif (secptr != NULL) {\n\t\t\tif (entry != NULL) {\n\t\t\t\tINIEntry * entptr = secptr->Find_Entry(entry);\n\t\t\t\tif (entptr != NULL) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRemove the entry from the entry index list.\n\t\t\t\t\t*/\n\t\t\t\t\tsecptr->EntryIndex.Remove_Index(entptr->Index_ID());\n\n\t\t\t\t\tdelete entptr;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t**\tRemove this section index from the section index list.\n\t\t\t\t*/\n\t\t\t\tSectionIndex.Remove_Index(secptr->Index_ID());\n\n\t\t\t\tdelete secptr;\n\t\t\t}\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Load -- Load INI data from the file specified.                                    *\n *                                                                                             *\n *    Use this routine to load the INI class with the data from the specified file.            *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file that will be used to fill up this INI manager.      *\n *                                                                                             *\n * OUTPUT:  bool; Was the file loaded successfully?                                            *\n *                                                                                             *\n * WARNINGS:   This routine allocates memory.                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Load(FileClass & file)\n{\n\treturn(Load(FileStraw(file)));\n}\n\n\n/***********************************************************************************************\n * INIClass::Load -- Load the INI data from the data stream (straw).                           *\n *                                                                                             *\n *    This will fetch data from the straw and build an INI database from it.                   *\n *                                                                                             *\n * INPUT:   straw -- The straw that the data will be provided from.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the database loaded ok?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef FIXIT_FAST_LOAD\nbool INIClass::Load(Straw & ffile)\n#else\nbool INIClass::Load(Straw & file)\n#endif\n{\n\tbool end_of_file = false;\n\tchar buffer[MAX_LINE_LENGTH];\n\n#ifdef FIXIT_FAST_LOAD\n\tCacheStraw file;\n\tfile.Get_From(ffile);\n#endif\n\n\t/*\n\t**\tPrescan until the first section is found.\n\t*/\n\twhile (!end_of_file) {\n\t\tRead_Line(file, buffer, sizeof(buffer), end_of_file);\n\t\tif (end_of_file) return(false);\n\t\tif (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;\n\t}\n\n\t/*\n\t**\tProcess a section. The buffer is prefilled with the section name line.\n\t*/\n\twhile (!end_of_file) {\n\n\t\tbuffer[0] = ' ';\n\t\tchar * ptr = strchr(buffer, ']');\n\t\tif (ptr) *ptr = '\\0';\n\t\tstrtrim(buffer);\n\t\tINISection * secptr = new INISection(strdup(buffer));\n\t\tif (secptr == NULL) {\n\t\t\tClear();\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tRead in the entries of this section.\n\t\t*/\n\t\twhile (!end_of_file) {\n\n\t\t\t/*\n\t\t\t**\tIf this line is the start of another section, then bail out\n\t\t\t**\tof the entry loop and let the outer section loop take\n\t\t\t**\tcare of it.\n\t\t\t*/\n\t\t\tint len = Read_Line(file, buffer, sizeof(buffer), end_of_file);\n\t\t\tif (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;\n\n\t\t\t/*\n\t\t\t**\tDetermine if this line is a comment or blank line. Throw it out if it is.\n\t\t\t*/\n\t\t\tStrip_Comments(buffer);\n\t\t\tif (len == 0 || buffer[0] == ';' || buffer[0] == '=') continue;\n\n\t\t\t/*\n\t\t\t**\tThe line isn't an obvious comment. Make sure that there is the \"=\" character\n\t\t\t**\tat an appropriate spot.\n\t\t\t*/\n\t\t\tchar * divider = strchr(buffer, '=');\n\t\t\tif (!divider) continue;\n\n\t\t\t/*\n\t\t\t**\tSplit the line into entry and value sections. Be sure to catch the\n\t\t\t**\t\"=foobar\" and \"foobar=\" cases. These lines are ignored.\n\t\t\t*/\n\t\t\t*divider++ = '\\0';\n\t\t\tstrtrim(buffer);\n\t\t\tif (!strlen(buffer)) continue;\n\n\t\t\tstrtrim(divider);\n\t\t\tif (!strlen(divider)) continue;\n\n\t\t\tINIEntry * entryptr = new INIEntry(strdup(buffer), strdup(divider));\n\t\t\tif (entryptr == NULL) {\n\t\t\t\tdelete secptr;\n\t\t\t\tClear();\n\t\t\t\treturn(false);\n\t\t\t}\n\n\t\t\tsecptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);\n\t\t\tsecptr->EntryList.Add_Tail(entryptr);\n\t\t}\n\n\t\t/*\n\t\t**\tAll the entries for this section have been parsed. If this section is blank, then\n\t\t**\tdon't bother storing it.\n\t\t*/\n\t\tif (secptr->EntryList.Is_Empty()) {\n\t\t\tdelete secptr;\n\t\t} else {\n\t\t\tSectionIndex.Add_Index(secptr->Index_ID(), secptr);\n\t\t\tSectionList.Add_Tail(secptr);\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Save -- Save the ini data to the file specified.                                  *\n *                                                                                             *\n *    Use this routine to save the ini data to the file specified. All existing data in the    *\n *    file, if it was present, is replaced.                                                    *\n *                                                                                             *\n * INPUT:   file  -- Reference to the file to write the INI data to.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the data written to the file?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Save(FileClass & file) const\n{\n\treturn(Save(FilePipe(file)));\n}\n\n\n/***********************************************************************************************\n * INIClass::Save -- Saves the INI data to a pipe stream.                                      *\n *                                                                                             *\n *    This routine will output the data of the INI file to a pipe stream.                      *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the pipe stream to pump the INI image to.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output to the pipe.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Save(Pipe & pipe) const\n{\n\tint total = 0;\n\n\tINISection * secptr = SectionList.First();\n\twhile (secptr && secptr->Is_Valid()) {\n\n\t\t/*\n\t\t**\tOutput the section identifier.\n\t\t*/\n\t\ttotal += pipe.Put(\"[\", 1);\n\t\ttotal += pipe.Put(secptr->Section, strlen(secptr->Section));\n\t\ttotal += pipe.Put(\"]\", 1);\n\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\t/*\n\t\t**\tOutput all the entries and values in this section.\n\t\t*/\n\t\tINIEntry * entryptr = secptr->EntryList.First();\n\t\twhile (entryptr && entryptr->Is_Valid()) {\n\t\t\ttotal += pipe.Put(entryptr->Entry, strlen(entryptr->Entry));\n\t\t\ttotal += pipe.Put(\"=\", 1);\n\t\t\ttotal += pipe.Put(entryptr->Value, strlen(entryptr->Value));\n\t\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\t\tentryptr = entryptr->Next();\n\t\t}\n\n\t\t/*\n\t\t**\tAfter the last entry in this section, output an extra\n\t\t**\tblank line for readability purposes.\n\t\t*/\n\t\ttotal += pipe.Put(\"\\r\\n\", strlen(\"\\r\\n\"));\n\n\t\tsecptr = secptr->Next();\n\t}\n\ttotal += pipe.End();\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Find_Section -- Find the specified section within the INI data.                   *\n *                                                                                             *\n *    This routine will scan through the INI data looking for the section specified. If the    *\n *    section could be found, then a pointer to the section control data is returned.          *\n *                                                                                             *\n * INPUT:   section  -- The name of the section to search for. Don't enclose the name in       *\n *                      brackets. Case is NOT sensitive in the search.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the INI section control structure if the section was     *\n *          found. Otherwise, NULL is returned.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nINIClass::INISection * INIClass::Find_Section(char const * section) const\n{\n\tif (section != NULL) {\n\n\t\tlong crc = CRCEngine()(section, strlen(section));\n\n\t\tif (SectionIndex.Is_Present(crc)) {\n\t\t\treturn(SectionIndex.Fetch_Index(crc));\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Section_Count -- Counts the number of sections in the INI data.                   *\n *                                                                                             *\n *    This routine will scan through all the sections in the INI data and return a count       *\n *    of the number it found.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of sections recorded in the INI data.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nint INIClass::Section_Count(void) const\n{\n\treturn(SectionIndex.Count());\n}\n\n\n/***********************************************************************************************\n * INIClass::Entry_Count -- Fetches the number of entries in a specified section.              *\n *                                                                                             *\n *    This routine will examine the section specified and return with the number of entries    *\n *    associated with it.                                                                      *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section that will be examined.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the number entries in the specified section.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index manager.                                                      *\n *=============================================================================================*/\nint INIClass::Entry_Count(char const * section) const\n{\n\tINISection * secptr = Find_Section(section);\n\tif (secptr != NULL) {\n\t\treturn(secptr->EntryIndex.Count());\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * INIClass::Find_Entry -- Find specified entry within section.                                *\n *                                                                                             *\n *    This support routine will find the specified entry in the specified section. If found,   *\n *    a pointer to the entry control structure will be returned.                               *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section name to search under.                           *\n *                                                                                             *\n *          entry    -- Pointer to the entry name to search for.                               *\n *                                                                                             *\n * OUTPUT:  If the entry was found, then a pointer to the entry control structure will be      *\n *          returned. Otherwise, NULL will be returned.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nINIClass::INIEntry * INIClass::Find_Entry(char const * section, char const * entry) const\n{\n\tINISection * secptr = Find_Section(section);\n\tif (secptr != NULL) {\n\t\treturn(secptr->Find_Entry(entry));\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name. *\n *                                                                                             *\n *    This will return the identifier name for the entry under the section specified. The      *\n *    ordinal number specified is used to determine which entry to retrieve. The entry         *\n *    identifier is the text that appears to the left of the \"=\" character.                    *\n *                                                                                             *\n * INPUT:   section  -- The section to use.                                                    *\n *                                                                                             *\n *          index    -- The ordinal number to use when fetching an entry name.                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the entry name.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * INIClass::Get_Entry(char const * section, int index) const\n{\n\tINISection * secptr = Find_Section(section);\n\n\tif (secptr != NULL && index < secptr->EntryIndex.Count()) {\n\t\tINIEntry * entryptr = secptr->EntryList.First();\n\n\t\twhile (entryptr != NULL && entryptr->Is_Valid()) {\n\t\t\tif (index == 0) return(entryptr->Entry);\n\t\t\tindex--;\n\t\t\tentryptr = entryptr->Next();\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.           *\n *                                                                                             *\n *    Use this routine to store an arbitrary length binary block of data into the INI database.*\n *    This routine will covert the data into displayable form and then break it into lines     *\n *    that are stored in sequence to the section. A section used to store data in this         *\n *    fashion can not be used for any other entries.                                           *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the data into.                         *\n *                                                                                             *\n *          block    -- Pointer to the block of binary data to store.                          *\n *                                                                                             *\n *          len      -- The length of the binary data.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the data stored to the database?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_UUBlock(char const * section, void const * block, int len)\n{\n\tif (section == NULL || block == NULL || len < 1) return(false);\n\n\tClear(section);\n\n\tBufferStraw straw(block, len);\n\tBase64Straw bstraw(Base64Straw::ENCODE);\n\tbstraw.Get_From(straw);\n\n\tint counter = 1;\n\n\tfor (;;) {\n\t\tchar buffer[71];\n\t\tchar sbuffer[32];\n\n\t\tint length = bstraw.Get(buffer, sizeof(buffer)-1);\n\t\tbuffer[length] = '\\0';\n\t\tif (length == 0) break;\n\n\t\tsprintf(sbuffer, \"%d\", counter);\n\t\tPut_String(section, sbuffer, buffer);\n\t\tcounter++;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.                 *\n *                                                                                             *\n *    This routine will take all the entries in the specified section and decompose them into  *\n *    a binary block of data that will be stored into the buffer specified. By using this      *\n *    routine [and the Put_UUBLock counterpart], arbitrary blocks of binary data may be        *\n *    stored in the INI file. A section processed by this routine can contain no other         *\n *    entries than those put there by a previous call to Put_UUBlock.                          *\n *                                                                                             *\n * INPUT:   section  -- The section name to process.                                           *\n *                                                                                             *\n *          block    -- Pointer to the buffer that will hold the retrieved data.               *\n *                                                                                             *\n *          len      -- The length of the buffer. The retrieved data will not fill past this   *\n *                      limit.                                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes decoded into the buffer specified.                *\n *                                                                                             *\n * WARNINGS:   If the number of bytes retrieved exactly matches the length of the buffer       *\n *             specified, then you might have a condition of buffer \"overflow\".                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_UUBlock(char const * section, void * block, int len) const\n{\n\tif (section == NULL) return(0);\n\n\tBase64Pipe b64pipe(Base64Pipe::DECODE);\n\tBufferPipe bpipe(block, len);\n\n\tb64pipe.Put_To(&bpipe);\n\n\tint total = 0;\n\tint counter = Entry_Count(section);\n\tfor (int index = 0; index < counter; index++) {\n\t\tchar buffer[128];\n\n\t\tint length = Get_String(section, Get_Entry(section, index), \"=\", buffer, sizeof(buffer));\n\t\tint outcount = b64pipe.Put(buffer, length);\n\t\ttotal += outcount;\n\t}\n\ttotal += b64pipe.End();\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_TextBlock -- Stores a block of text into an INI section.                      *\n *                                                                                             *\n *    This routine will take an arbitrarily long block of text and store it into the INI       *\n *    database. The text is broken up into lines and each line is then stored as a numbered    *\n *    entry in the specified section. A section used to store text in this way can not be used *\n *    to hold any other entries. The text is presumed to contain space characters scattered    *\n *    throughout it and that one space between words and sentences is natural.                 *\n *                                                                                             *\n * INPUT:   section  -- The section to place the text block into.                              *\n *                                                                                             *\n *          text     -- Pointer to a null terminated text string that holds the block of       *\n *                      text. The length can be arbitrary.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the text block placed into the database?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_TextBlock(char const * section, char const * text)\n{\n\tif (section == NULL) return(false);\n\n\tClear(section);\n\n\tint index = 1;\n\twhile (text != NULL && *text != NULL) {\n\n\t\tchar buffer[128];\n\n\t\tstrncpy(buffer, text, 75);\n\t\tbuffer[75] = '\\0';\n\n\t\tchar b[32];\n\t\tsprintf(b, \"%d\", index);\n\n\t\t/*\n\t\t**\tScan backward looking for a good break position.\n\t\t*/\n\t\tint count = strlen(buffer);\n\t\tif (count > 0) {\n\t\t\tif (count >= 75) {\n\t\t\t\twhile (count) {\n\t\t\t\t\tchar c = buffer[count];\n\n\t\t\t\t\tif (isspace(c)) break;\n\t\t\t\t\tcount--;\n\t\t\t\t}\n\n\t\t\t\tif (count == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tbuffer[count] = '\\0';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstrtrim(buffer);\n\t\t\tPut_String(section, b, buffer);\n\t\t\tindex++;\n\t\t\ttext = ((char  *)text) + count;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_TextBlock -- Fetch a block of normal text.                                    *\n *                                                                                             *\n *    This will take all entries in the specified section and format them into a block of      *\n *    normalized text. That is, text with single spaces between each concatenated line. All    *\n *    entries in the specified section are processed by this routine. Use Put_TextBlock to     *\n *    build the entries in the section.                                                        *\n *                                                                                             *\n * INPUT:   section  -- The section name to process.                                           *\n *                                                                                             *\n *          buffer   -- Pointer to the buffer that will hold the complete text.                *\n *                                                                                             *\n *          len      -- The length of the buffer specified. The text will, at most, fill this  *\n *                      buffer with the last character being forced to null.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters placed into the buffer. The trailing null    *\n *          is not counted.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_TextBlock(char const * section, char * buffer, int len) const\n{\n\tif (len <= 0) return(0);\n\n\tbuffer[0] = '\\0';\n\tif (len <= 1) return(0);\n\n\tint elen = Entry_Count(section);\n\tint total = 0;\n\tfor (int index = 0; index < elen; index++) {\n\n\t\t/*\n\t\t**\tAdd spacers between lines of fetched text.\n\t\t*/\n\t\tif (index > 0) {\n\t\t\t*buffer++ = ' ';\n\t\t\tlen--;\n\t\t\ttotal++;\n\t\t}\n\n\t\tGet_String(section, Get_Entry(section, index), \"\", buffer, len);\n\n\t\tint partial = strlen(buffer);\n\t\ttotal += partial;\n\t\tbuffer += partial;\n\t\tlen -= partial;\n\t\tif (len <= 1) break;\n\t}\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Int -- Stores a signed integer into the INI data base.                        *\n *                                                                                             *\n *    Use this routine to store an integer value into the section and entry specified.         *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *\n *                                                                                             *\n *          entry    -- The entry identifier used for the integer number.                      *\n *                                                                                             *\n *          number   -- The integer number to store in the database.                           *\n *                                                                                             *\n *          format   -- The format to store the integer. The format is generally only a        *\n *                      cosmetic affect. The Get_Int operation will interpret the value the    *\n *                      same regardless of what format was used to store the integer.          *\n *                                                                                             *\n *                      0  : plain decimal digit                                               *\n *                      1  : hexadecimal digit (trailing \"h\")                                  *\n *                      2  : hexadecimal digit (leading \"$\")                                   *\n *                                                                                             *\n * OUTPUT:  bool; Was the number stored?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles multiple integer formats.                                        *\n *=============================================================================================*/\nbool INIClass::Put_Int(char const * section, char const * entry, int number, int format)\n{\n\tchar buffer[MAX_LINE_LENGTH];\n\n\tswitch (format) {\n\t\tdefault:\n\t\tcase 0:\n\t\t\tsprintf(buffer, \"%d\", number);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tsprintf(buffer, \"%Xh\", number);\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tsprintf(buffer, \"$%X\", number);\n\t\t\tbreak;\n\t}\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Int -- Fetch an integer entry from the specified section.                     *\n *                                                                                             *\n *    This routine will fetch an integer value from the entry and section specified. If no     *\n *    entry could be found, then the default value will be returned instead.                   *\n *                                                                                             *\n * INPUT:   section  -- The section name to search under.                                      *\n *                                                                                             *\n *          entry    -- The entry name to search for.                                          *\n *                                                                                             *\n *          defvalue -- The default value to use if the specified entry could not be found.    *\n *                                                                                             *\n * OUTPUT:  Returns with the integer value specified in the INI database or else returns the   *\n *          default value.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Handles multiple integer formats.                                        *\n *=============================================================================================*/\nint INIClass::Get_Int(char const * section, char const * entry, int defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\n\t\tif (*entryptr->Value == '$') {\n\t\t\tsscanf(entryptr->Value, \"$%x\", &defvalue);\n\t\t} else {\n\t\t\tif (tolower(entryptr->Value[strlen(entryptr->Value)-1]) == 'h') {\n\t\t\t\tsscanf(entryptr->Value, \"%xh\", &defvalue);\n\t\t\t} else {\n\t\t\t\tdefvalue = atoi(entryptr->Value);\n\t\t\t}\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.          *\n *                                                                                             *\n *    This routine is similar to the Put_Int routine, but the number is stored as a hexadecimal*\n *    number.                                                                                  *\n *                                                                                             *\n * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *\n *                                                                                             *\n *          entry    -- The entry identifier to tag to the integer number specified.           *\n *                                                                                             *\n *          number   -- The number to assign the the specified entry and placed in the         *\n *                      specified section.                                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the number placed into the INI database?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Hex(char const * section, char const * entry, int number)\n{\n\tchar buffer[MAX_LINE_LENGTH];\n\n\tsprintf(buffer, \"%X\", number);\n\treturn(Put_String(section, entry, buffer));\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.     *\n *                                                                                             *\n *    This routine will search under the section specified, looking for a matching entry. The  *\n *    value is interpreted as a hexadecimal number and then returned. If no entry could be     *\n *    found, then the default value is returned instead.                                       *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to search under.                                *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- The default value to use if the entry could not be located.            *\n *                                                                                             *\n * OUTPUT:  Returns with the integer value from the specified section and entry. If no entry   *\n *          could be found, then the default value will be returned instead.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_Hex(char const * section, char const * entry, int defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\t\tsscanf(entryptr->Value, \"%x\", &defvalue);\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_String -- Output a string to the section and entry specified.                 *\n *                                                                                             *\n *    This routine will put an arbitrary string to the section and entry specified. Any        *\n *    previous matching entry will be replaced.                                                *\n *                                                                                             *\n * INPUT:   section  -- The section identifier to place the string under.                      *\n *                                                                                             *\n *          entry    -- The entry identifier to identify this string [placed under the section]*\n *                                                                                             *\n *          string   -- Pointer to the string to assign to this entry.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the entry assigned without error?                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index handler.                                                      *\n *=============================================================================================*/\nbool INIClass::Put_String(char const * section, char const * entry, char const * string)\n{\n\tif (section == NULL || entry == NULL) return(false);\n\n\tINISection * secptr = Find_Section(section);\n\n\tif (secptr == NULL) {\n\t\tsecptr = new INISection(strdup(section));\n\t\tif (secptr == NULL) return(false);\n\t\tSectionList.Add_Tail(secptr);\n\t\tSectionIndex.Add_Index(secptr->Index_ID(), secptr);\n\t}\n\n\t/*\n\t**\tRemove the old entry if found.\n\t*/\n\tINIEntry * entryptr = secptr->Find_Entry(entry);\n\tif (entryptr != NULL) {\n\t\tsecptr->EntryIndex.Remove_Index(entryptr->Index_ID());\n\t\tdelete entryptr;\n\t}\n\n\t/*\n\t**\tCreate and add the new entry.\n\t*/\n\tif (string != NULL && strlen(string) > 0) {\n\t\tentryptr = new INIEntry(strdup(entry), strdup(string));\n\n\t\tif (entryptr == NULL) {\n\t\t\treturn(false);\n\t\t}\n\t\tsecptr->EntryList.Add_Tail(entryptr);\n\t\tsecptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_String -- Fetch the value of a particular entry in a specified section.       *\n *                                                                                             *\n *    This will retrieve the entire text to the right of the \"=\" character. The text is        *\n *    found by finding a matching entry in the section specified. If no matching entry could   *\n *    be found, then the default value will be stored in the output string buffer.             *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section name to search under.                           *\n *                                                                                             *\n *          entry    -- The entry identifier to search for.                                    *\n *                                                                                             *\n *          defvalue -- If no entry could be found, then this text will be returned.           *\n *                                                                                             *\n *          buffer   -- Output buffer to store the retrieved string into.                      *\n *                                                                                             *\n *          size     -- The size of the output buffer. The maximum string length that could    *\n *                      be retrieved will be one less than this length. This is due to the     *\n *                      forced trailing zero added to the end of the string.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the length of the string retrieved.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint INIClass::Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally legal.\n\t*/\n\tif (section == NULL || entry == NULL) {\n\t\tif (buffer != NULL && size > 0) {\n\t\t\tbuffer[0] = '\\0';\n\t\t}\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tFetch the entry string if it is present. If not, then the normal default\n\t**\tvalue will be used as the entry value.\n\t*/\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr) {\n\t\tif (entryptr->Value) {\n\t\t\tdefvalue = entryptr->Value;\n\t\t}\n\t}\n\n\t/*\n\t**\tFill in the buffer with the entry value and return with the length of the string.\n\t*/\n\tif (buffer == NULL || !size) {\n\t\treturn(0);\n\t} else if (defvalue == NULL) {\n\t\tbuffer[0] = '\\0';\n\t\treturn(0);\n\t} else if (buffer == defvalue) {\n\t\treturn(strlen(buffer));\n\t} else {\n\t\tstrncpy(buffer, defvalue, size);\n\t\tbuffer[size-1] = '\\0';\n\t\tstrtrim(buffer);\n\t\treturn(strlen(buffer));\n\t}\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Bool -- Store a boolean value into the INI database.                          *\n *                                                                                             *\n *    Use this routine to place a boolean value into the INI database. The boolean value will  *\n *    be stored as \"yes\" or \"no\".                                                              *\n *                                                                                             *\n * INPUT:   section  -- The section to place the entry and boolean value into.                 *\n *                                                                                             *\n *          entry    -- The entry identifier to tag to the boolean value.                      *\n *                                                                                             *\n *          value    -- The boolean value to place into the database.                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the boolean value placed into the database?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Bool(char const * section, char const * entry, bool value)\n{\n\tif (value) {\n\t\treturn(Put_String(section, entry, \"yes\"));\n\t} else {\n\t\treturn(Put_String(section, entry, \"no\"));\n\t}\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.            *\n *                                                                                             *\n *    This routine will search under the section specified, looking for a matching entry. If   *\n *    one is found, the value is interpreted as a boolean value and then returned. In the case *\n *    of no matching entry, the default value will be returned instead. The boolean value      *\n *    is interpreted using the standard boolean conventions. e.g., \"Yes\", \"Y\", \"1\", \"True\",    *\n *    \"T\" are all consider to be a TRUE boolean value.                                         *\n *                                                                                             *\n * INPUT:   section  -- The section to search under.                                           *\n *                                                                                             *\n *          entry    -- The entry to search for.                                               *\n *                                                                                             *\n *          defvalue -- The default value to use if no matching entry could be located.        *\n *                                                                                             *\n * OUTPUT:  Returns with the boolean value of the specified section and entry. If no match     *\n *          then the default boolean value is returned.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Get_Bool(char const * section, char const * entry, bool defvalue) const\n{\n\t/*\n\t**\tVerify that the parameters are nominally correct.\n\t*/\n\tif (section == NULL || entry == NULL) return(defvalue);\n\n\tINIEntry * entryptr = Find_Entry(section, entry);\n\tif (entryptr && entryptr->Value != NULL) {\n\t\tswitch (toupper(*entryptr->Value)) {\n\t\t\tcase 'Y':\n\t\t\tcase 'T':\n\t\t\tcase '1':\n\t\t\t\treturn(true);\n\n\t\t\tcase 'N':\n\t\t\tcase 'F':\n\t\t\tcase '0':\n\t\t\t\treturn(false);\n\t\t}\n\t}\n\treturn(defvalue);\n}\n\n\n/***********************************************************************************************\n * INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.      *\n *                                                                                             *\n *    This routine scans the supplied entry for the section specified. This is used for        *\n *    internal database maintenance.                                                           *\n *                                                                                             *\n * INPUT:   entry -- The entry to scan for.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the entry control structure if the entry was found.      *\n *          Otherwise it returns NULL.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *   11/02/1996 JLB : Uses index handler.                                                      *\n *=============================================================================================*/\nINIClass::INIEntry * INIClass::INISection::Find_Entry(char const * entry) const\n{\n\tif (entry != NULL) {\n\t\tint crc = CRCEngine()(entry, strlen(entry));\n\t\tif (EntryIndex.Is_Present(crc)) {\n\t\t\treturn(EntryIndex.Fetch_Index(crc));\n\t\t}\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_PKey -- Stores the key to the INI database.                                   *\n *                                                                                             *\n *    The key stored to the database will have both the exponent and modulus portions saved.   *\n *    Since the fast key only requires the modulus, it is only necessary to save the slow      *\n *    key to the database. However, storing the slow key stores the information necessary to   *\n *    generate the fast and slow keys. Because public key encryption requires one key to be    *\n *    completely secure, only store the fast key in situations where the INI database will     *\n *    be made public.                                                                          *\n *                                                                                             *\n * INPUT:   key   -- The key to store the INI database.                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the key stored to the database?                                          *\n *                                                                                             *\n * WARNINGS:   Store the fast key for public INI database availability. Store the slow key if  *\n *             the INI database is secure.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_PKey(PKey const & key)\n{\n\tchar buffer[512];\n\n\tint len = key.Encode_Modulus(buffer);\n\tPut_UUBlock(\"PublicKey\", buffer, len);\n\n\tlen = key.Encode_Exponent(buffer);\n\tPut_UUBlock(\"PrivateKey\", buffer, len);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_PKey -- Fetch a key from the ini database.                                    *\n *                                                                                             *\n *    This routine will fetch the key from the INI database. The key fetched is controlled by  *\n *    the parameter. There are two choices of key -- the fast or slow key.                     *\n *                                                                                             *\n * INPUT:   fast  -- Should the fast key be retrieved? The fast key has the advantage of       *\n *                   requiring only the modulus value.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the key retrieved.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKey INIClass::Get_PKey(bool fast) const\n{\n\tPKey key;\n\tchar buffer[512];\n\n\t/*\n\t**\tWhen retrieving the fast key, the exponent is a known constant. Don't parse the\n\t**\texponent from the database.\n\t*/\n\tif (fast) {\n\t\tBigInt exp = PKey::Fast_Exponent();\n\t\texp.DEREncode((unsigned char *)buffer);\n\t\tkey.Decode_Exponent(buffer);\n\t} else {\n\t\tGet_UUBlock(\"PrivateKey\", buffer, sizeof(buffer));\n\t\tkey.Decode_Exponent(buffer);\n\t}\n\n\tGet_UUBlock(\"PublicKey\", buffer, sizeof(buffer));\n\tkey.Decode_Modulus(buffer);\n\n\treturn(key);\n}\n\n\n/***********************************************************************************************\n * INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.                 *\n *                                                                                             *\n *    This routine will examine the section and entry specified and interpret the value        *\n *    as if it were a fixed point number. The format of the fixed point number can be          *\n *    percentage (e.g. 100%) or a floating point number (e.g., 1.7).                           *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section identifier to look under.                       *\n *                                                                                             *\n *          entry    -- Pointer to the entry identifier to examine.                            *\n *                                                                                             *\n *          defvalue -- If the section and entry could not be found, then this value will      *\n *                      be returned.                                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the fixed point number that occurs at the section and entry           *\n *          specified. If it could not be found, then the default value is returned.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed INIClass::Get_Fixed(char const * section, char const * entry, fixed defvalue) const\n{\n\tchar buffer[128];\n\tfixed retval = defvalue;\n\n\tif (Get_String(section, entry, \"\", buffer, sizeof(buffer))) {\n\t\tretval = fixed(buffer);\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * INIClass::Put_Fixed -- Store a fixed point number to the INI database.                      *\n *                                                                                             *\n *    Use this routine to output a fixed point number to the database. The entry will be       *\n *    placed in the section and entry specified. If there was any existing entry, it will      *\n *    be replaced.                                                                             *\n *                                                                                             *\n * INPUT:   section  -- Pointer to the section identifier.                                     *\n *                                                                                             *\n *          entry    -- Pointer to the entry identifier to use for this value.                 *\n *                                                                                             *\n *          value    -- The value to store in the database.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the data stored?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool INIClass::Put_Fixed(char const * section, char const * entry, fixed value)\n{\n\treturn(Put_String(section, entry, value.As_ASCII()));\n}\n\n\n/***********************************************************************************************\n * INIClass::Strip_Comments -- Strips comments of the specified text line.                     *\n *                                                                                             *\n *    This routine will scan the string (text line) supplied and if any comment portions are   *\n *    found, they will be trimmed off. Leading and trailing blanks are also removed.           *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the null terminate string to be processed.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid INIClass::Strip_Comments(char * buffer)\n{\n\tif (buffer != NULL) {\n\t\tchar * comment = strchr(buffer, ';');\n\t\tif (comment) {\n\t\t\t*comment = '\\0';\n\t\t\tstrtrim(buffer);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/INI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INI.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INI.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/15/96                                                     *\n *                                                                                             *\n *                  Last Update : May 15, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef INI_H\n#define INI_H\n\n#include\t<stdlib.h>\n#include\t\"listnode.h\"\n#include\t\"pipe.h\"\n#include\t\"wwfile.h\"\n#include\t\"pk.h\"\n#include\t\"fixed.h\"\n#include\t\"crc.h\"\n#include\t\"search.h\"\n\n/*\n**\tThis is an INI database handler class. It handles a database with a disk format identical\n**\tto the INI files commonly used by Windows.\n*/\nclass INIClass {\n\tpublic:\n\t\tINIClass(void) {}\n\t\t~INIClass(void);\n\n\t\t/*\n\t\t**\tFetch and store INI data.\n\t\t*/\n\t\tbool Load(FileClass & file);\n\t\tbool Load(Straw & file);\n\t\tint Save(FileClass & file) const;\n\t\tint Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tErase all data within this INI file manager.\n\t\t*/\n\t\tbool Clear(char const * section = 0, char const * entry = 0);\n\n\t\tint Line_Count(char const * section) const;\n\t\tbool Is_Loaded(void) const {return(!SectionList.Is_Empty());}\n\t\tint Size(void) const;\n\t\tbool Is_Present(char const * section, char const * entry = 0) const {if (entry == 0) return(Find_Section(section) != 0);return(Find_Entry(section, entry) != 0);}\n\n\t\t/*\n\t\t**\tFetch the number of sections in the INI file or verify if a specific\n\t\t**\tsection is present.\n\t\t*/\n\t\tint Section_Count(void) const;\n\t\tbool Section_Present(char const * section) const {return(Find_Section(section) != NULL);}\n\n\t\t/*\n\t\t**\tFetch the number of entries in a section or get a particular entry in a section.\n\t\t*/\n\t\tint Entry_Count(char const * section) const;\n\t\tchar const * Get_Entry(char const * section, int index) const;\n\n\t\t/*\n\t\t**\tGet the various data types from the section and entry specified.\n\t\t*/\n\t\tint Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const;\n\t\tint Get_Int(char const * section, char const * entry, int defvalue=0) const;\n\t\tint Get_Hex(char const * section, char const * entry, int defvalue=0) const;\n\t\tbool Get_Bool(char const * section, char const * entry, bool defvalue=false) const;\n\t\tint Get_TextBlock(char const * section, char * buffer, int len) const;\n\t\tint Get_UUBlock(char const * section, void * buffer, int len) const;\n\t\tPKey Get_PKey(bool fast) const;\n\t\tfixed Get_Fixed(char const * section, char const * entry, fixed defvalue) const;\n\n\t\t/*\n\t\t**\tPut a data type to the section and entry specified.\n\t\t*/\n\t\tbool Put_Fixed(char const * section, char const * entry, fixed value);\n\t\tbool Put_String(char const * section, char const * entry, char const * string);\n\t\tbool Put_Hex(char const * section, char const * entry, int number);\n\t\tbool Put_Int(char const * section, char const * entry, int number, int format=0);\n\t\tbool Put_Bool(char const * section, char const * entry, bool value);\n\t\tbool Put_TextBlock(char const * section, char const * text);\n\t\tbool Put_UUBlock(char const * section, void const * block, int len);\n\t\tbool Put_PKey(PKey const & key);\n\n\tprotected:\n\t\tenum {MAX_LINE_LENGTH=128};\n\n\t\t/*\n\t\t**\tThe value entries for the INI file are stored as objects of this type.\n\t\t**\tThe entry identifier and value string are combined into this object.\n\t\t*/\n\t\tstruct INIEntry : Node<INIEntry> {\n\t\t\tINIEntry(char * entry = 0, char * value = 0) : Entry(entry), Value(value) {}\n\t\t\t~INIEntry(void) {free(Entry);Entry = 0;free(Value);Value = 0;}\n\t\t\tint Index_ID(void) const {return(CRCEngine()(Entry, strlen(Entry)));};\n\n\t\t\tchar * Entry;\n\t\t\tchar * Value;\n\t\t};\n\n\t\t/*\n\t\t**\tEach section (bracketed) is represented by an object of this type. All entries\n\t\t**\tsubordinate to this section are attached.\n\t\t*/\n\t\tstruct INISection : Node<INISection> {\n\t\t\tINISection(char * section) : Section(section) {}\n\t\t\t~INISection(void) {free(Section);Section = 0;EntryList.Delete();}\n\t\t\tINIEntry * Find_Entry(char const * entry) const;\n\t\t\tint Index_ID(void) const {return(CRCEngine()(Section, strlen(Section)));};\n\n\t\t\tchar * Section;\n\t\t\tList<INIEntry> EntryList;\n\t\t\tIndexClass<INIEntry *>EntryIndex;\n\t\t};\n\n\t\t/*\n\t\t**\tUtility routines to help find the appropriate section and entry objects.\n\t\t*/\n\t\tINISection * Find_Section(char const * section) const;\n\t\tINIEntry * Find_Entry(char const * section, char const * entry) const;\n\t\tstatic void Strip_Comments(char * buffer);\n\n\t\t/*\n\t\t**\tThis is the list of all sections within this INI file.\n\t\t*/\n\t\tList<INISection> SectionList;\n\n\t\tIndexClass<INISection *> SectionIndex;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/INIBIN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\inibin.cpv   4.40   04 Jul 1996 16:14:52   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INIBIN.CPP                                                   *\n *                                                                                             *\n *                   Programmer : David R. Dettmer                                             *\n *                                                                                             *\n *                   Start Date : October 20, 1995                                             *\n *                                                                                             *\n *                  Last Update : November 7, 1995   [DRD]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n"
  },
  {
    "path": "REDALERT/INICODE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\inicode.cpv   4.38   03 Jul 1996 05:14:04   JOE_BOSTIC  $ */\n/***************************************************************************\n **     C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S       **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : INICODE.CPP                              *\n *                                                                         *\n *                   Programmer : David R Dettmer                          *\n *                                                                         *\n *                   Start Date : November 7, 1995                         *\n *                                                                         *\n *                  Last Update : February 20, 1996 [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#ifdef TOFIX\n\nvoid Get_Scenario_Digest(char * digest, char * buffer)\n{\n\tchar buf[128];\t// Working string staging buffer.\n\tchar stage[sizeof(BigInt)*2];\n\n\tchar * stage_ptr = &stage[0];\n\tint len = strlen(buffer) + 2;\n\tchar * tbuffer = buffer + len;\n\n\tWWGetPrivateProfileString(\"DIGEST\", NULL, NULL, tbuffer, sizeof(_staging_buffer)-len, buffer);\n\tstage[0] = '\\0';\n\twhile (*tbuffer != '\\0') {\n\n\t\tWWGetPrivateProfileString(\"DIGEST\", tbuffer, NULL, buf, sizeof(buf)-1, buffer);\n\t\tstrcat(stage, buf);\n\t\ttbuffer += strlen(tbuffer)+1;\n\t}\n\n\tlen = strlen(stage);\n\tchar * dbuffer = &stage[0];\n\ttbuffer = &stage[0];\n\tfor (int index = 0; index < len/2; index++) {\n\t\tint c;\n\t\tif (isdigit(*tbuffer)) {\n\t\t\tc = (*tbuffer) - '0';\n\t\t} else {\n\t\t\tc = 10 + (toupper(*tbuffer) - 'A');\n\t\t}\n\t\ttbuffer++;\n\t\tc <<= 4;\n\t\tif (isdigit(*tbuffer)) {\n\t\t\tc |= (*tbuffer) - '0';\n\t\t} else {\n\t\t\tc |= 10 + (toupper(*tbuffer) - 'A');\n\t\t}\n\t\ttbuffer++;\n\t\t*dbuffer++ = c;\n\t}\n\n\t/*\n\t**\tDecode and decrypt the number.\n\t*/\n\tBigInt hash = 0;\n\thash.DERDecode((unsigned char*)stage);\n\n\tBigInt d;\n\td = d.Decode_ASCII(KEY_D);\n\tBigInt n;\n\tn = n.Decode_ASCII(KEY_N);\n\n\thash = hash.exp_b_mod_c(d, n);\n\n\tmemcpy(digest, &hash, 20);\n\n\tbuffer = strstr(buffer, \"[DIGEST]\");\n\tif (buffer) {\n\t\t*buffer = '\\0';\n\t}\n}\n\n\nbool Read_Scenario_INI_Write_INB( char *root, bool fresh)\n{\n\tchar *buffer;\t\t\t\t// Scenario.ini staging buffer pointer.\n\tchar *binbuf;\t\t\t\t// Scenario.inb staging buffer pointer.\n\tchar fname[_MAX_FNAME+_MAX_EXT];\t\t\t// full INI filename\n\tchar buf[256];\t\t\t\t// Working string staging buffer.\n\tchar scenarioname[40];\n\tint len;\n\tunsigned char val;\n\n\t/*\n\t**\tFetch working pointer to the INI staging buffer. Make sure that the buffer\n\t**\tis cleared out before proceeding.  (Don't use the HidPage for this, since\n\t**\tthe HidPage may be needed for various uncompressions during the INI\n\t**\tparsing.)\n\t*/\n\tbuffer = (char *)_staging_buffer;\n\tmemset(buffer, '\\0', sizeof(_staging_buffer));\n\n\t/*\n\t**\tCreate scenario filename and read the file.\n\t** The previous routine verifies that the file is available.\n\t*/\n\n\tsprintf(fname,\"%s.INI\",root);\n\tCCFileClass file(fname);\n\n\tfile.Read(buffer, sizeof(_staging_buffer)-1);\n\n\t/*\n\t**\tFetch and slice off any message digest attached.\n\t*/\n\tchar digest[20];\n\tGet_Scenario_Digest(digest, buffer);\n\n\tchar real_digest[20];\n\tSHAEngine digest_engine;\n\tdigest_engine.Hash(buffer, strlen(buffer));\n\tdigest_engine.Result(real_digest);\n\n\tif (memcmp(digest, real_digest, sizeof(real_digest)) != 0) {\n\t\tWWMessageBox().Process(TXT_SCENARIO_ERROR, TXT_OK);\n\t}\n\n\t/*\n\t** Init the Scenario CRC value\n\t*/\n\tScenarioCRC = 0;\n\tlen = strlen(buffer);\n\tfor (int i = 0; i < len; i++) {\n\t\tval = (unsigned char)buffer[i];\n\t\tAdd_CRC(&ScenarioCRC, (unsigned long)val);\n\t}\n\n\tsprintf(fname,\"%s.INB\",root);\n\tfile.Set_Name(fname);\n\tfile.Cache(16384);\n\tfile.Open(WRITE);\n\n\tunsigned long crc = Ini_Binary_Version();\n\n\tfile.Write( (char *)&crc, sizeof(crc) );\n\n\tbinbuf = (char *)Alloc( sizeof(_staging_buffer), MEM_NORMAL );\n\n\tif (binbuf) {\n\t\tWrite_Bin_Init( binbuf, sizeof(_staging_buffer) );\n\t} else {\n\t\tPrint_Error_End_Exit( \"Unable to alloc space for writing INB\" );\n\t}\n\n\t/*\n\t**\tFetch the appropriate movie names from the INI file.\n\t*/\n\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"\", scenarioname, sizeof(scenarioname), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Intro\", \"x\", Scen.IntroMovie, sizeof(Scen.IntroMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Brief\", \"x\", Scen.BriefMovie, sizeof(Scen.BriefMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Win\", \"x\", Scen.WinMovie, sizeof(Scen.WinMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Lose\", \"x\", Scen.LoseMovie, sizeof(Scen.LoseMovie), buffer);\n\tWWGetPrivateProfileString(\"Basic\", \"Action\", \"x\", Scen.ActionMovie, sizeof(Scen.ActionMovie), buffer);\n\tScen.IsToCarryOver = WWGetPrivateProfileInt(\"Basic\", \"ToCarryOver\", 0, buffer);\n\tScen.IsToInherit = WWGetPrivateProfileInt(\"Basic\", \"ToInherit\", 0, buffer);\n\n\tWrite_Bin_String( scenarioname, strlen(scenarioname), binbuf );\n\tWrite_Bin_String( Scen.IntroMovie, strlen(Scen.IntroMovie), binbuf );\n\tWrite_Bin_String( Scen.BriefMovie, strlen(Scen.BriefMovie), binbuf );\n\tWrite_Bin_String( Scen.WinMovie, strlen(Scen.WinMovie), binbuf );\n\tWrite_Bin_String( Scen.LoseMovie, strlen(Scen.LoseMovie), binbuf );\n\tWrite_Bin_String( Scen.ActionMovie, strlen(Scen.ActionMovie), binbuf );\n\n\t/*\n\t**\tFetch the transition theme for this scenario.\n\t*/\n\tScen.TransitTheme = THEME_NONE;\n\tWWGetPrivateProfileString(\"Basic\", \"Theme\", \"No Theme\", buf, sizeof(buf), buffer);\n\tScen.TransitTheme = Theme.From_Name(buf);\n\n\tWWGetPrivateProfileString( \"Basic\", \"Player\", \"Greece\", buf, 127, buffer);\n\tScen.PlayerHouse = HouseTypeClass::From_Name(buf);\n\tif (Scen.PlayerHouse >= HOUSE_MULTI1) {\n\t\tScen.PlayerHouse = HOUSE_GREECE;\n\t}\n// TCTC To Fix?\n//\tScen.CarryOverPercent = WWGetPrivateProfileInt( \"Basic\", \"CarryOverMoney\", 100, buffer);\n\tScen.CarryOverCap = WWGetPrivateProfileInt( \"Basic\", \"CarryOverCap\", -1, buffer);\n\tScen.Percent = WWGetPrivateProfileInt( \"Basic\", \"Percent\", 0, buffer);\n\n\tWrite_Bin_Num( &Scen.TransitTheme, sizeof(Scen.TransitTheme), binbuf );\n\tWrite_Bin_Num( &Scen.PlayerHouse, sizeof(Scen.PlayerHouse), binbuf );\n\tWrite_Bin_Num( &Scen.CarryOverPercent, 1, binbuf );\n\tWrite_Bin_Num( &Scen.CarryOverCap, 2, binbuf );\n\tWrite_Bin_Num( &Scen.Percent, 1, binbuf );\n\n\t/*\n\t**\tRead in the specific information for each of the house types.  This creates\n\t**\tthe houses of different types.\n\t*/\n\tHouseClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the team-type data. The team types must be created before any\n\t**\ttriggers can be created.\n\t*/\n\tTeamTypeClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tAssign PlayerPtr by reading the player's house from the INI;\n\t**\tMust be done before any TechnoClass objects are created.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tScen.CarryOverPercent = Cardinal_To_Fixed(100, Scen.CarryOverPercent);\n\n\t\tPlayerPtr = HouseClass::As_Pointer( Scen.PlayerHouse );\n\t\tassert(PlayerPtr != NULL);\n\t\tPlayerPtr->IsHuman = true;\n\n\t\tint carryover;\n\t\tif (Scen.CarryOverCap != -1) {\n\t\t\tcarryover = MIN(Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent), (Scen.CarryOverCap * 100) );\n\t\t} else {\n\t\t\tcarryover = Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent);\n\t\t}\n\t\tPlayerPtr->Credits += carryover;\n\t\tPlayerPtr->Control.InitialCredits += carryover;\n\t} else {\n\n\t\tAssign_Houses();\n\t}\n\n\t/*\n\t**\tRead in the trigger data. The triggers must be created before any other\n\t**\tobjects can be initialized.\n\t*/\n\tTriggerClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the map control values. This includes dimensions\n\t**\tas well as theater information.\n\t*/\n\tMap.Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tAttempt to read the map's binary image file; if fails, read the\n\t**\ttemplate data from the INI, for backward compatibility\n\t*/\n\tif (fresh) {\n\t\tif (!Map.Read_Binary(root, &ScenarioCRC)) {\n\t\t\treturn( false );\n\t\t}\n\t}\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the 3D terrain objects.\n\t*/\n\tTerrainClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the units (all sides).\n\t*/\n\tUnitClass::Read_INI(buffer);\n\tCall_Back();\n\n\tAircraftClass::Read_INI(buffer);\n\tCall_Back();\n\n\tVesselClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the infantry units (all sides).\n\t*/\n\tInfantryClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place all the buildings on the map.\n\t*/\n\tBuildingClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the AI's base information.\n\t*/\n\tBase.Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any normal overlay objects.\n\t*/\n\tOverlayClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any smudge overlays.\n\t*/\n\tSmudgeClass::Read_INI(buffer);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any briefing text.\n\t*/\n\tchar * stage = &Scen.BriefingText[0];\n\t*stage = '\\0';\n\tint index = 1;\n\n\t/*\n\t**\tBuild the full text of the mission objective.\n\t*/\n\tfor (;;) {\n\t\tchar buff[16];\n\n\t\tsprintf(buff, \"%d\", index++);\n\t\t*stage = '\\0';\n\t\tWWGetPrivateProfileString(\"Briefing\", buff, \"\", stage, 255, buffer);\n\t\tif (strlen(stage) == 0) break;\n\t\tstrcat(stage, \" \");\n\t\tstage += strlen(stage);\n\t}\n\n\tlen = Write_Bin_Length( binbuf );\n\tif (len != -1) {\n\t\tfile.Write( binbuf, len );\n\t}\n\n\tFree( binbuf );\n\tfile.Close();\n\n\treturn(true);\n}\n\n#endif\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "REDALERT/INIT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INIT.CPP 8     3/14/97 5:15p Joe_b $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INIT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : January 20, 1992                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Anim_Init -- Initialize the VQ animation control structure.                               *\n *   Bootstrap -- Perform the initial bootstrap procedure.                                     *\n *   Calculate_CRC -- Calculates a one-way hash from a data block.                             *\n *   Init_Authorization -- Verifies that the player is authorized to play the game.            *\n *   Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.    *\n *   Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                          *\n *   Init_CDROM_Access -- Initialize the CD-ROM access handler.                                *\n *   Init_Color_Remaps -- Initialize the text remap tables.                                    *\n *   Init_Expansion_Files -- Fetch any override expansion mixfiles.                            *\n *   Init_Fonts -- Initialize all the game font pointers.                                      *\n *   Init_Game -- Main game initialization routine.                                            *\n *   Init_Heaps -- Initialize the game heaps and buffers.                                      *\n *   Init_Keys -- Initialize the cryptographic keys.                                           *\n *   Init_Mouse -- Initialize the mouse system.                                                *\n *   Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                   *\n *   Init_Random -- Initializes the random-number generator                                    *\n *   Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                         *\n *   Load_Recording_Values -- Loads recording values from recording file                       *\n *   Load_Title_Page -- Load the background art for the title page.                            *\n *   Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                   *\n *   Parse_Command_Line -- Parses the command line parameters.                                 *\n *   Parse_INI_File -- Parses CONQUER.INI for special options                                  *\n *   Play_Intro -- plays the introduction & logo movies                                        *\n *   Save_Recording_Values -- Saves recording values to a recording file                       *\n *   Select_Game -- The game's main menu                                                       *\n *   Load_Prolog_Page -- Loads the special pre-prolog \"please wait\" page.                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"loaddlg.h\"\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#include\t\"WSPUDP.h\"\n#include\t\"WSPIPX.h\"\n#include\t\"internet.h\"\n#else\t//WINSOCK_IPX\n#include\t\"tcpip.h\"\n#endif\t//WINSOCK_IPX\n\n#endif\n#include\t<conio.h>\n#include\t<dos.h>\n#ifndef WIN32\n#include\t<sys\\timeb.h>\n#endif\n#include  \"ccdde.h\"\n\n#include <time.h>\n\n#ifdef DONGLE\n#include \"cbn_.h\"\n#endif\n\n#ifdef MPEGMOVIE // Denzil 6/25/98\n#include \"mpgset.h\"\n#endif\n\nRemapControlType SidebarScheme;\n\n//#include \"WolDebug.h\"\n\n#ifdef CHEAT_KEYS\nextern bool bNoMovies;\n#endif\n\n/****************************************\n**\tFunction prototypes for this module **\n*****************************************/\nstatic void Play_Intro(bool sequenced=false);\nstatic void Init_Color_Remaps(void);\nstatic void Init_Heaps(void);\nstatic void Init_Expansion_Files(void);\nstatic void Init_One_Time_Systems(void);\nstatic void Init_Fonts(void);\nstatic void Init_CDROM_Access(void);\nstatic void Init_Bootstrap_Mixfiles(void);\nstatic void Init_Secondary_Mixfiles(void);\nstatic void Init_Mouse(void);\nstatic void Bootstrap(void);\n//static void Init_Authorization(void);\nstatic void Init_Bulk_Data(void);\nstatic void Init_Keys(void);\n\nextern int UnitBuildPenalty;\n\nextern \"C\" {\nextern long RandNumb;\n}\n#ifndef WIN32\nstatic int UsePageFaultHandler = 1;\t\t\t\t// 1 = install PFH\n#endif\t//WIN32\n\n//extern int SimRandIndex;\nvoid Init_Random(void);\n\n#define ATTRACT_MODE_TIMEOUT\t3600\t\t// timeout for attract mode\n\nbool Load_Recording_Values(CCFileClass & file);\nbool Save_Recording_Values(CCFileClass & file);\n\n#ifdef WOLAPI_INTEGRATION\nextern int WOL_Main();\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Expansion_Dialog( bool bCounterstrike );\n#endif\n\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n/***********************************************************************************************\n * Load_Prolog_Page -- Loads the special pre-prolog \"please wait\" page.                        *\n *                                                                                             *\n *    This loads and displays the prolog page that is displayed before the prolog movie        *\n *    is played. This page is necessary because there is much loading that occurs before       *\n *    the prolog movie is played and looking at a picture is better than looking at a blank    *\n *    screen.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Load_Prolog_Page(void)\n{\n\tHide_Mouse();\n#ifdef WIN32\n\tLoad_Title_Screen(\"PROLOG.PCX\", &HidPage, (unsigned char*)CCPalette.Get_Data());\n\tHidPage.Blit(SeenPage);\n#else\n\tLoad_Picture(\"PROLOG.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n\tHidPage.Blit(SeenPage);\n#endif\n\tCCPalette.Set();\n\tShow_Mouse();\n}\n\n\n/***********************************************************************************************\n * Init_Game -- Main game initialization routine.                                              *\n *                                                                                             *\n *    Perform all one-time game initializations here. This includes all                        *\n *    allocations and table setups. The intro and other one-time startup                       *\n *    tasks are also performed here.                                                           *\n *                                                                                             *\n * INPUT:   argc,argv   -- Command line arguments.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this ONCE!                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\n#include\t\"sha.h\"\n//#include    <locale.h>\nbool Init_Game(int , char * [])\n{\n\t/*\n\t**\tAllocate the benchmark tracking objects only if the machine and\n\t**\tcompile flags indicate.\n\t*/\n\t#ifdef CHEAT_KEYS\n\tif (Processor() >= 2) {\n\t\tBenches = new Benchmark [BENCH_COUNT];\n\t}\n\t#endif\n\n\t/*\n\t**\tInitialize the encryption keys.\n\t*/\n\tInit_Keys();\n\n\t/*\n\t**\tBootstrap as much as possible before error-prone initializations are\n\t**\tperformed. This bootstrap process will enable the error message\n\t**\thandler to function.\n\t*/\n\tBootstrap();\n\n\t////////////////////////////////////////\n\t// The editor needs to not start the mouse up. - 7/22/2019 JAS \n\tif (!RunningFromEditor)\n\t{\n\t\t/*\n\t\t**\tCheck for an initialize a working mouse pointer. Display error and bail if\n\t\t**\tno mouse driver is installed.\n\t\t*/\n\t\tInit_Mouse();\n\t}\n\t/*\n\t**\tInitialize access to the CD-ROM and ensure that the CD is inserted. This can, and\n\t**\tmost likely will, result in a visible prompt.\n\t*/\n#if (0) //PG\n\tInit_CDROM_Access();\n#endif\n\n\tif (Special.IsFromInstall) {\n\t\tLoad_Prolog_Page();\n\t}\n\n\t/*\n\t**\tRegister and cache any secondary mixfiles.\n\t*/\n\tInit_Secondary_Mixfiles();\n\n\t/*\n\t**\tThis is a special hack to initialize the heaps that must be in place before the\n\t**\trules file is processed. These heaps should properly be allocated as a consequence\n\t**\tof processing the rules.ini file, but that is a bit beyond the capabilities of\n\t**\tthe rule parser routine (currently).\n\t*/\n\tHouseTypes.Set_Heap(HOUSE_COUNT);\n\tBuildingTypes.Set_Heap(STRUCT_COUNT);\n\tAircraftTypes.Set_Heap(AIRCRAFT_COUNT);\n\tInfantryTypes.Set_Heap(INFANTRY_COUNT);\n\tBulletTypes.Set_Heap(BULLET_COUNT);\n\tAnimTypes.Set_Heap(ANIM_COUNT);\n\tUnitTypes.Set_Heap(UNIT_COUNT);\n\tVesselTypes.Set_Heap(VESSEL_COUNT);\n\tTemplateTypes.Set_Heap(TEMPLATE_COUNT);\n\tTerrainTypes.Set_Heap(TERRAIN_COUNT);\n\tOverlayTypes.Set_Heap(OVERLAY_COUNT);\n\tSmudgeTypes.Set_Heap(SMUDGE_COUNT);\n\n\tHouseTypeClass::Init_Heap();\n\tBuildingTypeClass::Init_Heap();\n\tAircraftTypeClass::Init_Heap();\n\tInfantryTypeClass::Init_Heap();\n\tBulletTypeClass::Init_Heap();\n\tAnimTypeClass::Init_Heap();\n\tUnitTypeClass::Init_Heap();\n\tVesselTypeClass::Init_Heap();\n\tTemplateTypeClass::Init_Heap();\n\tTerrainTypeClass::Init_Heap();\n\tOverlayTypeClass::Init_Heap();\n\tSmudgeTypeClass::Init_Heap();\n\n\t\t// Heap init moved here from globals.cpp. ST - 5/20/2019\n\tCCPtr<AircraftClass>::Set_Heap(&Aircraft);\n\tCCPtr<AnimClass>::Set_Heap(&Anims);\n\tCCPtr<BuildingClass>::Set_Heap(&Buildings);\n\tCCPtr<BulletClass>::Set_Heap(&Bullets);\n\tCCPtr<FactoryClass>::Set_Heap(&Factories);\n\tCCPtr<HouseClass>::Set_Heap(&Houses);\n\tCCPtr<InfantryClass>::Set_Heap(&Infantry);\n\tCCPtr<OverlayClass>::Set_Heap(&Overlays);\n\tCCPtr<SmudgeClass>::Set_Heap(&Smudges);\n\tCCPtr<TeamClass>::Set_Heap(&Teams);\n\tCCPtr<TeamTypeClass>::Set_Heap(&TeamTypes);\n\tCCPtr<TemplateClass>::Set_Heap(&Templates);\n\tCCPtr<TerrainClass>::Set_Heap(&Terrains);\n\tCCPtr<TriggerClass>::Set_Heap(&Triggers);\n\tCCPtr<TriggerTypeClass>::Set_Heap(&TriggerTypes);\n\n\tCCPtr<HouseTypeClass>::Set_Heap(&HouseTypes);\n\tCCPtr<BuildingTypeClass>::Set_Heap(&BuildingTypes);\n\tCCPtr<AircraftTypeClass>::Set_Heap(&AircraftTypes);\n\tCCPtr<InfantryTypeClass>::Set_Heap(&InfantryTypes);\n\tCCPtr<BulletTypeClass>::Set_Heap(&BulletTypes);\n\tCCPtr<AnimTypeClass>::Set_Heap(&AnimTypes);\n\tCCPtr<UnitTypeClass>::Set_Heap(&UnitTypes);\n\tCCPtr<VesselTypeClass>::Set_Heap(&VesselTypes);\n\tCCPtr<TemplateTypeClass>::Set_Heap(&TemplateTypes);\n\tCCPtr<TerrainTypeClass>::Set_Heap(&TerrainTypes);\n\tCCPtr<OverlayTypeClass>::Set_Heap(&OverlayTypes);\n\tCCPtr<SmudgeTypeClass>::Set_Heap(&SmudgeTypes);\n\n\t/*\n\t**\tFind and process any rules for this game.\n\t*/\n\tif (RuleINI.Load(CCFileClass(\"RULES.INI\"), false)) {\n\t\tRule.Process(RuleINI);\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t//  Aftermath runtime change 9/29/98\n\t//\tThis is safe to do, as only rules for aftermath units are included in this ini.\n\tif (Is_Aftermath_Installed() == true) {\n\t\tif (AftermathINI.Load(CCFileClass(\"AFTRMATH.INI\"), false)) {\n\t\t\tRule.Process(AftermathINI);\n\t\t}\n\t}\n#endif\n\n\tSession.MaxPlayers = Rule.MaxPlayers;\n\n\t/*\n\t**\tInitialize the game object heaps as well as other rules-dependant buffer allocations.\n\t*/\n\tInit_Heaps();\n\n\t/*\n\t**\tInitialize the animation system.\n\t*/\n\tAnim_Init();\n\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n#ifdef WIN32\n\tif (SpawnedFromWChat){\n\t\tSpecial.IsFromWChat = true;\n\t}\n#endif\n#endif\n\n\t#ifdef MPEGMOVIE // Denzil 6/15/98\n\tif( Using_DVD() )\n\t{\n\t\t#ifdef MCIMPEG\n\t\tMciMovie = new MCIMovie(MainWindow);\n\t\t#endif\n\t\tMpgSettings = new MPGSettings(NULL); //RawFileClass(CONFIG_FILE_NAME));\n\t}\n\t#endif\n\n\t/*\n\t**\tPlay the startup animation.\n\t*/\n\tif (!Special.IsFromInstall && !Special.IsFromWChat) {\n\t\tVisiblePage.Clear();\n//\t\tMono_Printf(\"Playing Intro\\n\");\n\t\tPlay_Intro();\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t\tWhitePalette.Set();\n\t} else {\n\t\tmemset(CurrentPalette, 0x01, 768);\n\t}\n\n\t/*\n\t**\tInitialize the text remap tables.\n\t*/\n\tInit_Color_Remaps();\n\n\t/*\n\t**\tGet authorization to access the game.\n\t*/\n//\tInit_Authorization();\n//\tShow_Mouse();\n\n\t/*\n\t**\tSet the logic page to the seenpage.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tIf not automatically launching into the intro, then display the title\n\t**\tpage while the bulk data is cached.\n\t*/\n\tif (!Special.IsFromInstall) {\n\t\tLoad_Title_Page(true);\n\n\t\tHide_Mouse();\n\t\tFancy_Text_Print(TXT_STAND_BY, 160*RESFACTOR, 120*RESFACTOR, &ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TPF_CENTER|TPF_TEXT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\n\n\t\tCCPalette.Set(FADE_PALETTE_SLOW);\n\t\tCall_Back();\n\t}\n\n\t/*\n\t**\tInitialize the bulk data. This takes the longest time and must be performed once\n\t**\tbefore the regular game starts.\n\t*/\n\tInit_Bulk_Data();\n\n\t/*\n\t**\tInitialize the multiplayer score values\n\t*/\n\tSession.GamesPlayed = 0;\n\tSession.NumScores = 0;\n\tSession.CurGame = 0;\n\tfor (int i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\tSession.Score[i].Name[0] = '\\0';\n\t\tSession.Score[i].Wins = 0;\n\t\tfor (int j = 0; j < MAX_MULTI_GAMES; j++) {\n\t\t\tSession.Score[i].Kills[j] = -1;\t// -1 = this player didn't play this round\n\t\t}\n\t}\n\n\t/*\n\t** Copy the title screen's palette into the GamePalette & OriginalPalette,\n\t** because the options Load routine uses these palettes to set the brightness, etc.\n\t*/\n\tGamePalette = CCPalette;\n//\tInGamePalette = CCPalette;\n\tOriginalPalette = CCPalette;\n\n\t/*\n\t**\tRead game options, so the GameSpeed is initialized when multiplayer\n\t** dialogs are invoked.  (GameSpeed must be synchronized between systems.)\n\t*/\n\tOptions.Load_Settings();\n\n\t/*\n\t** Initialise the color lookup tables for the chronal vortex\n\t*/\n\tChronalVortex.Stop();\n\tChronalVortex.Setup_Remap_Tables(Scen.Theater);\n\n\t/*\n\t**\tClear out name overrides array\n\t*/\n#ifdef FIXIT_NAME_OVERRIDE\n\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\tNameOverride[index] = NULL;\n\t\tNameIDOverride[index] = 0;\n\t}\n#endif //FIXIT_NAME_OVERRIDE\n\n\treturn(true);\n}\n\n#ifdef WINSOCK_IPX\t\t\t//\tSteve Tall missed this one - ajw\nextern bool Get_Broadcast_Addresses (void);\n#endif\n\n/***********************************************************************************************\n * Select_Game -- The game's main menu                                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *\t\tfade\t\tif true, will fade the palette in gradually\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nbool Select_Game(bool fade)\n{\n\t//\tEnums in Select_Game() must match order of buttons in Main_Menu().\n#ifdef FIXIT_VERSION_3\n\tenum {\n\t\tSEL_TIMEOUT = -1,\t\t\t\t// main menu timeout--go into attract mode\n\t\tSEL_NEW_SCENARIO_CS,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_NEW_SCENARIO_AM,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_START_NEW_GAME,\t\t\t// start a new game\n\t\tSEL_LOAD_MISSION,\t\t\t\t// load a saved game\n\t\tSEL_MULTIPLAYER_GAME,\t\t// play modem/null-modem/network game\n\t\tSEL_INTRO,\t\t\t\t\t\t// couch-potato mode\n\t\tSEL_EXIT,\t\t\t\t\t\t// exit to DOS\n\t\tSEL_FAME,\t\t\t\t\t\t// view the hall o' fame\n\t\tSEL_NONE,\t\t\t\t\t\t// placeholder default value\n\t};\n#else\t//\tFIXIT_VERSION_3\n\tenum {\n\t\tSEL_TIMEOUT = -1,\t\t\t\t// main menu timeout--go into attract mode\n\t\tSEL_NEW_SCENARIO,\t\t\t\t// Expansion scenario to play.\n\t\tSEL_START_NEW_GAME,\t\t\t// start a new game\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\tSEL_INTERNET,\n#endif\t//WIN32\n//#if defined(MPEGMOVIE) // Denzil 6/25/98\n//\t\tSEL_MOVIESETTINGS,\n//#endif\n\t\tSEL_LOAD_MISSION,\t\t\t\t// load a saved game\n\t\tSEL_MULTIPLAYER_GAME,\t\t// play modem/null-modem/network game\n\t\tSEL_INTRO,\t\t\t\t\t\t// couch-potato mode\n\t\tSEL_EXIT,\t\t\t\t\t\t// exit to DOS\n\t\tSEL_FAME,\t\t\t\t\t\t// view the hall o' fame\n\t\tSEL_NONE,\t\t\t\t\t\t// placeholder default value\n\t};\n#endif\t//\tFIXIT_VERSION_3\n\n\tbool gameloaded=false;\t\t\t// Has the game been loaded from the menu?\n\tint selection;\t\t\t\t\t\t// the default selection\n\tbool process = true;\t\t\t\t// false = break out of while loop\n\tbool display = true;\n\n#ifdef DONGLE\n\t/* These where added by ColinM for the dongle checking */\n\tshort iRet = 0;\n\tunsigned short iPortNr = 1;  /* automatic port scan enabled */\n\tunsigned char cSCodeSER[] = \"\\x41\\x42\";\n\tunsigned long ulIdRet = 0;\n\tunsigned char cBoxName[]= \"\\x00\\x00\";\n#endif\n\t\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tint cdcheck = 0;\n\tbool cs = Is_Counterstrike_Installed();\n#endif\n\n//\t#ifndef DVD // Denzil - We want the menu screen\t\t\tajw No we don't\n//\tif (Special.IsFromInstall) {\n//\t\tdisplay = false;\n//\t}\n//\t#endif\n\n\tShow_Mouse();\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tNewUnitsEnabled = SecretUnitsEnabled = 0;\t// Assume new units disabled, unless specifically .INI enabled or multiplayer negotiations enable it.\n#endif\n\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t/*\n\t** Enable the DDE Server so we can get internet start game packets from WChat\n\t*/\n\tDDEServer.Enable();\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\t/*\n\t**\t[Re]set any globals that need it, in preparation for a new scenario\n\t*/\n\tGameActive = true;\n\tDoList.Init();\n\t#ifdef MIRROR_QUEUE\n\tMirrorList.Init();\n\t#endif\n\tOutList.Init();\n\tFrame = 0;\n\tScen.MissionTimer = 0;\n\tScen.MissionTimer.Stop();\n\tScen.CDifficulty = DIFF_NORMAL;\n\tScen.Difficulty = DIFF_NORMAL;\n\tPlayerWins = false;\n\tPlayerLoses = false;\n\tSession.ObiWan = false;\n\tDebug_Unshroud = false;\n\tMap.Set_Cursor_Shape(0);\n\tMap.PendingObjectPtr = 0;\n\tMap.PendingObject = 0;\n\tMap.PendingHouse = HOUSE_NONE;\n\n\tSession.ProcessTicks = 0;\n\tSession.ProcessFrames = 0;\n\tSession.DesiredFrameRate = 30;\n#if(TIMING_FIX)\n\tNewMaxAheadFrame1 = 0;\n\tNewMaxAheadFrame2 = 0;\n#endif\n\n/* ColinM added to check for dongle */\n#ifdef DONGLE\n\tiRet = CbN_BoxReady( iPortNr , cBoxName);\n\tif (cBoxName[0] != 0xc5 && cBoxName[0] != 0xc9) \n\t{\n\tWWMessageBox().Process(\"Please ensure dongle is attached. Run the dongle batch file too.\", TXT_OK);\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n\n\tiRet = CbN_ReadSER( iPortNr, cSCodeSER, &ulIdRet);\n\tif (ulIdRet != 0xa0095)\n\t{\n\tWWMessageBox().Process(\"Please ensure dongle is attached. Run the dongle batch file too.\", TXT_OK);\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n#endif\n\n\t/*\n\t**\tInit multiplayer game scores.  Let Wins accumulate; just init the current\n\t** Kills for this game.  Kills of -1 means this player didn't play this round.\n\t*/\n\tfor (int i = 0 ; i < MAX_MULTI_GAMES; i++) {\n\t\tSession.Score[i].Kills[Session.CurGame] = -1;\n\t}\n\n\t/*\n\t**\tSet default mouse shape\n\t*/\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\n\t/*\n\t**\tIf the last game we played was a multiplayer game, jump right to that\n\t**\tmenu by pre-setting 'selection'.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tselection = SEL_NONE;\n\t} else {\n\t\tselection = SEL_MULTIPLAYER_GAME;\n\t}\n\n\t/*\n\t**\tMain menu processing; only do this if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\n\t\t/*\n\t\t**\tMenu selection processing loop\n\t\t*/\n\t\tTheme.Queue_Song(THEME_CRUS);\n\n\t\t/*\n\t\t** If we're playing back a recording, load all pertinent values & skip\n\t\t** the menu loop.  Hide the now-useless mouse pointer.\n\t\t*/\n\t\tif (Session.Play && Session.RecordFile.Is_Available()) {\n\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\tprocess = false;\n\t\t\t\tTheme.Fade_Out();\n\t\t\t} else\n\t\t\t\tSession.Play = false;\n\t\t}\n\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t/*\n\t\t** Handle case where we were spawned from Wchat\n\t\t*/\n\t\tif (SpawnedFromWChat) {\n\t\t\tSpecial.IsFromInstall = false;\t//Dont play intro if we were spawned from wchat\n\t\t\tselection = SEL_INTERNET;\n\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\tSession.Type = GAME_INTERNET;\n\t\t\tdisplay = false;\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t}\n#endif\t//WIN32\n#endif\n\n\t\twhile (process) {\n\n\t\t\t/*\n\t\t\t**\tRedraw the title page if needed\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tHide_Mouse();\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the title page; fade it in if this is the first time\n\t\t\t\t**\tthrough the loop, and the 'fade' flag is true\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page();\n\t\t\t\tGamePalette = CCPalette;\n\n\t\t\t\tHidPage.Blit(SeenPage);\n//\t\t\t\tif (fade) {\n//\t\t\t\t\tWhitePalette.Set();\n//\t\t\t\t\tCCPalette.Set(FADE_PALETTE_SLOW, Call_Back);\n//\t\t\t\t\tfade = false;\n//\t\t\t\t} else {\n\t\t\t\t\tCCPalette.Set();\n//\t\t\t\t}\n\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tdisplay = false;\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (RunningAsDLL) {\t//PG\n\t\t\t\t\treturn true;;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDisplay menu and fetch selection from player.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) selection = SEL_START_NEW_GAME;\n\n#ifndef WOLAPI_INTEGRATION\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t/*\n\t\t\t** Handle case where we were spawned from Wchat and our start game\n\t\t\t**  packet has already arrived\n\t\t\t*/\n\t\t\tif (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\tTheme.Queue_Song(THEME_QUIET);\n\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** We werent spawned but we could still receive a DDE packet from wchat\n\t\t\t\t*/\n\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure top and bottom of screen are clear in 640x480 mode\n\t\t\t\t\t*/\n\t\t\t\t\tif (ScreenHeight == 480) {\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 0, 639, 40, 0);\n\t\t\t\t\t\tVisiblePage.Fill_Rect (0, 440, 639, 479, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\t//WIN32\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( pWolapi )\n\t\t\t\tselection =\tSEL_MULTIPLAYER_GAME;\t\t//\tWe are returning from a game.\n#endif\n\n\t\t\tif (selection == SEL_NONE) {\n#ifdef FIXIT_ANTS\n\t\t\t\tAntsEnabled = false;\n#endif\n\t\t\t\tselection = Main_Menu(ATTRACT_MODE_TIMEOUT);\n\t\t\t}\n\t\t\tCall_Back();\n\n\t\t\tswitch (selection) {\n\n\t\t\t\t/*\n\t\t\t\t**\tPick an expansion scenario.\n\t\t\t\t*/\n#ifdef FIXIT_VERSION_3\n\t\t\t\tcase SEL_NEW_SCENARIO_CS:\n\t\t\t\tcase SEL_NEW_SCENARIO_AM:\n#else\t//\tFIXIT_VERSION_3\n\t\t\t\tcase SEL_NEW_SCENARIO:\n#endif\t//\tFIXIT_VERSION_3\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tif( selection == SEL_NEW_SCENARIO_CS )\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!Force_CD_Available(2)) {\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!Expansion_Dialog( true )){\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!Force_CD_Available(3)) {\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!Expansion_Dialog( false )){\n\t\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t\t   break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#else\t//\tFIXIT_VERSION_3\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif (cs) {\n\t\t\t\t\t\tcdcheck = 2;\n\t\t\t\t\t}\n\t\t\t\t\tif (Is_Aftermath_Installed()) {\n\t\t\t\t\t\tif (!cdcheck) {\n\t\t\t\t\t\t\tcdcheck = 3;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcdcheck = 4;\t// special case: means check for 3 or 4\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(!Force_CD_Available(cdcheck)) {\n\t\t\t\t\t   return(false);\n\t\t\t\t\t}\n\t#else\n\t\t\t\t\tif(!Force_CD_Available(2)) {\n\t\t\t\t\t   return(false);\n\t\t\t\t\t}\n\t#endif\n\t\t\t\t\tif(!Expansion_Dialog()){\n\t\t\t\t\t   selection = SEL_NONE;\n\t\t\t\t\t   break;\n\t\t\t\t\t}\n#endif\t//\tFIXIT_VERSION_3\n\n#ifdef FIXIT_DIFFICULTY\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tswitch (Fetch_Difficulty(cdcheck >= 3)) {\n\t#else\n\t\t\t\t\tswitch (Fetch_Difficulty()) {\n\t#endif\n\t\t \t\t\t\tcase 0:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_START_NEW_GAME: Play the game\n\t\t\t\t*/\n\t\t\t\tcase SEL_START_NEW_GAME:\n\t\t\t\t\tif (Special.IsFromInstall) {\n\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tswitch (Fetch_Difficulty()) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tBuildLevel = 10;\n\t\t\t\t\tIsTanyaDead = false;\n\t\t\t\t\tSaveTanya = false;\n\t\t\t\t\tWhom = HOUSE_GOOD;\n\n\t\t\t\t\tif (!Special.IsFromInstall) {\n#ifdef FIXIT_ANTS\n\t\t\t\t\t\tif (AntsEnabled)  {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCA01EA.INI\");\n\t\t\t\t\t\t} else {\n#endif\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_CANCEL, TXT_SOVIET)) {\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\tcontinue;\n#else\n\t\t\t\t\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET)) {\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n#endif\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n#ifdef FIXIT_ANTS\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\tLoad_Title_Page();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTheme.Fade_Out();\n#ifdef DVD // Denzil\t\t\tajw Presumably a bug fix.\n\t\t\t\t\t\tChoose_Side();\n\t\t\t\t\t\tHide_Mouse();\n#else\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tChoose_Side();\n#endif\n\t\t\t\t\t\tif (CurrentCD == 0) {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tScen.Set_Scenario_Name(\"SCU01EA.INI\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved button from main menu.\n\t\t\t\t#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t\t/*\n\t\t\t\t** Internet game is requested\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTERNET:\n\t\t\t\t\t/*\n\t\t\t\t\t** Only call up the internet menu code if we dont already have connect info from WChat\n\t\t\t\t\t*/\n\t\t\t\t\tif (!DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\tif (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t\t\t\tdisplay = false;\n\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t#endif\t//WIN32\n#endif\n\n//\t\t\t\t#if defined(MPEGMOVIE) // Denzil 6/25/98\n//\t\t\t\tcase SEL_MOVIESETTINGS:\n//\t\t\t\t\tMpgSettings->Dialog();\n//\t\t\t\t\tdisplay = true;\n//\t\t\t\t\tselection = SEL_NONE;\n//\t\t\t\tbreak;\n//\t\t\t\t#endif\n\n\t\t\t\t/*\n\t\t\t\t**\tLoad a saved game.\n\t\t\t\t*/\n\t\t\t\tcase SEL_LOAD_MISSION:\n\t\t\t\t\tif (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {\n\t\t\t\t\t\tTheme.Queue_Song(THEME_FIRST);\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tgameloaded = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tSEL_MULTIPLAYER_GAME: set 'Session.Type' to NULL-modem, modem, or\n\t\t\t\t**\tnetwork play.\n\t\t\t\t*/\n\t\t\t\tcase SEL_MULTIPLAYER_GAME:\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\tif( !pWolapi )\n\t\t\t\t\t{\n#endif\n\t\t\t\t\tswitch (Session.Type) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf 'Session.Type' isn't already set up for a multiplayer game,\n\t\t\t\t\t\t**\twe must prompt the user for which type of multiplayer game\n\t\t\t\t\t\t**\tthey want.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_NORMAL:\n\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n#if (0)//PG\n\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog(true) ) {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tEver hits? Session.Type set to GAME_SKIRMISH without user selecting in Select_MPlayer_Game()?\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t//\tIf mission is Counterstrike, CS CD will be required. But aftermath units require AM CD.\n\t\t\t\t\t\t\t\tbAftermathMultiplayer = Is_Aftermath_Installed() && !Is_Mission_Counterstrike( Scen.ScenarioName );\n\t\t\t\t\t\t\t\t//\tajw I'll bet this was needed before also...\n\t\t\t\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n#endif\n\t\t\t\t\t\t\t}\n#endif//PG\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n\t\t\t\t\t\tcase GAME_MODEM:\n#if (0)\n\t\t\t\t\t\t\tif ( Session.Type != GAME_SKIRMISH && NullModem.Num_Connections() ) {\n\t\t\t\t\t\t\t\tNullModem.Init_Send_Queue();\n\n\t\t\t\t\t\t\t\tif ((Session.Type == GAME_NULL_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_NULL_HOST) ||\n\t\t\t\t\t\t\t\t\t(Session.Type == GAME_MODEM &&\n\t\t\t\t\t\t\t\t\tSession.ModemType == MODEM_DIALER) ) {\n\n\t\t\t\t\t\t\t\t\tif ( !Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif ( !Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\t\tSession.Type = Select_Serial_Dialog();\n\t\t\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// user hit Cancel\n\t\t\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\tbreak;\n\n#ifndef WOLAPI_INTEGRATION\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Handle being spawned from WChat. Internet play based on IPX code.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_INTERNET:\t\t\t\t\t\t//\tajw\t\tNo longer hit.\n\t\t\t\t\t\t\tif (Special.IsFromWChat) {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Give myself focus.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\t\t\t\t\tShowWindow ( MainWindow, ShowCommand );\n\n#ifdef WINSOCK_IPX\n\n\t\t\t\t\t\t\t\tif (PacketTransport ) delete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\n\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n\n\t\t\t\t\t\t\t\tif (PacketTransport->Init()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to read multiplayer settings.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Read_MultiPlayer_Settings ();\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Start_Server or Start_Client.\\n\");\n\t\t\t\t\t\t\t\t\tPacketTransport->Start_Listening();\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Flush out any pending packets from a previous game.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tPacketTransport->Discard_In_Buffers();\n\t\t\t\t\t\t\t\t\tPacketTransport->Discard_Out_Buffers();\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Winsock failed to initialise.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tselection = SEL_EXIT;\n\t\t\t\t\t\t\t\t\tSpecial.IsFromWChat = false;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\t\tInit_Network();\n\n\n#else\t//WINSOCK_IPX\n\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to initialise Winsock.\\n\");\n\t\t\t\t\t\t\t\tif (Winsock.Init()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to read multiplayer settings.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Read_MultiPlayer_Settings ();\n\t\t\t\t\t\t\t\t\tServer = PlanetWestwoodIsHost;\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to set addresses.\\n\");\n\t\t\t\t\t\t\t\t\tWinsock.Set_Host_Address(PlanetWestwoodIPAddress);\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Start_Server or Start_Client.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server) {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Server();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tWinsock.Start_Client();\n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Flush out any pending packets from a previous game.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to flush packet queue.\\n\");\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Allocating scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tchar *temp_buffer = new char[1024];\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Creating timer class instance.\\n\");\n\t\t\t\t\t\t\t\t\tCountDownTimerClass ptimer;\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Entering read loop.\\n\");\n\t\t\t\t\t\t\t\t\twhile (Winsock.Read(temp_buffer, 1024)) {\n\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Discarding a packet.\\n\");\n\t\t\t\t\t\t\t\t\t\tptimer.Set (30, true);\n\t\t\t\t\t\t\t\t\t\twhile (ptimer.Time()) {};\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Ready to check for more packets.\\n\");\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to delete scrap memory.\\n\");\n\t\t\t\t\t\t\t\t\tdelete temp_buffer;\n\n\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Winsock failed to initialise.\\n\");\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tselection = SEL_EXIT;\n\t\t\t\t\t\t\t\t\tSpecial.IsFromWChat = false;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\t\tInit_Network();\n\n\t\t\t\t\t\t\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Read_Game_Options.\\n\");\n\t\t\t\t\t\t\t\t\tRead_Game_Options( NULL );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tRead_Game_Options( \"C&CSPAWN.INI\" );\n\t\t\t\t\t\t\t\t}\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to set addresses.\\n\");\n\t\t\t\t\t\t\t\tPacketTransport->Set_Broadcast_Address (PlanetWestwoodIPAddress);\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\tif (PlanetWestwoodIsHost) {\n\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Server_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Server_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Server_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#else\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();\t// Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Client_Remote_Connect.\\n\");\n\t\t\t\t\t\t\t\t\tif (Client_Remote_Connect()) {\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Client_Remote_Connect returned success.\\n\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We failed to connect to the other player\n\t\t\t\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#else\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tWinsock.Close();\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t\t\tDDEServer.Delete_MPlayer_Game_Info();  // Make sure we dont go round in an infinite loop\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSession.Type = Select_MPlayer_Game();\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_NORMAL) {\t\t// 'Cancel'\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#endif\t//WIN32\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\t\t\t\t\t}\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\t}\t//\tif( !pWolapi )\n\n\t\t\t\t\tif( pWolapi )\n\t\t\t\t\t\tSession.Type = GAME_INTERNET;\n#endif\n//debugprint( \"Session.Type = %i\\n\", Session.Type );\n\t\t\t\t\tswitch (Session.Type) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tModem, Null-Modem or internet\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_MODEM:\n\t\t\t\t\t\tcase GAME_NULL_MODEM:\n#ifndef WOLAPI_INTEGRATION\n\t\t\t\t\t\tcase GAME_INTERNET:\n#endif\n\t\t\t\t\t\tcase GAME_SKIRMISH:\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\t\t//\timplies also WINSOCK_IPX\n\t\t\t\t\t\tcase GAME_INTERNET:\n\t\t\t\t\t\t\tif( PacketTransport )\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\n\t\t\t\t\t\t\tassert( PacketTransport != NULL );\n\t\t\t\t\t\t\tif( PacketTransport->Init() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tswitch( WOL_Main() )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t//\tStart game.\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t//\tUser cancelled.\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\t//SEL_NONE;\n\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase -1:\n\t\t\t\t\t\t\t\t\t//\tPatch was downloaded. Exit app.\n\t\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t\t\tBlackPalette.Set( FADE_PALETTE_SLOW );\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_MULTIPLAYER_GAME;\t//SEL_NONE;\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tNetwork (IPX): start a new network game.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_IPX:\n\t\t\t\t\t\t\tWWDebugString (\"RA95 - Game type is IPX.\\n\");\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Init network system & remote-connect\n\t\t\t\t\t\t\t*/\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\tif (PacketTransport ) delete PacketTransport;\n//\t\t\t\t\t\t\tif (WWMessageBox().Process(\"Select a protocol to use for network play.\", \"UDP\", \"IPX\")) {\n\t\t\t\t\t\t\t\tPacketTransport = new IPXInterfaceClass;\n\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n//\t\t\t\t\t\t\t}else{\n//\t\t\t\t\t\t\t\tPacketTransport = new UDPInterfaceClass;\t//IPXInterfaceClass;\n//\t\t\t\t\t\t\t\tassert ( PacketTransport != NULL);\n//\t\t\t\t\t\t\t\tif (!Get_Broadcast_Addresses()) {\n//\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n//\t\t\t\t\t\t\t\t\tdisplay = true;\n//\t\t\t\t\t\t\t\t\tselection = SEL_NONE;\n//\t\t\t\t\t\t\t\t\tdelete PacketTransport;\n//\t\t\t\t\t\t\t\t\tPacketTransport = NULL;\n//\t\t\t\t\t\t\t\t\tbreak;\n//\t\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\t}\n\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\tWWDebugString (\"RA95 - About to call Init_Network.\\n\");\n\t\t\t\t\t\t\tif (Session.Type == GAME_IPX && Init_Network() && Remote_Connect()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\t\t\t\t\t\t// user hit cancel, or init failed\n\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\tdisplay = true;\n\t\t\t\t\t\t\t\tselection = SEL_NONE;\n#ifdef WINSOCK_IPX\n\t\t\t\t\t\t\t\tdelete PacketTransport;\n\t\t\t\t\t\t\t\tPacketTransport = NULL;\n#endif\t//WINSOCK_IPX\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tTEN: jump straight into the game\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_TEN:\n\t\t\t\t\t\t\tif (Init_TEN()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(\"Unable to initialize TEN!\");\n\t\t\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\t\t\tEmergency_Exit(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tMPATH: jump straight into the game\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcase GAME_MPATH:\n\t\t\t\t\t\t\tif (Init_MPATH()) {\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = Options.MultiScoreVolume;\n#else\n\t\t\t\t\t\t\t\tOptions.ScoreVolume = 0;\n#endif\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(\"Unable to initialize MPATH!\");\n\t\t\t\t\t\t\t\t//Prog_End();\n\t\t\t\t\t\t\t\tEmergency_Exit(1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\t// MPATH\n\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlay a VQ\n\t\t\t\t*/\n\t\t\t\tcase SEL_INTRO:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tif (Debug_Flag) {\n\t\t\t\t\t\tPlay_Intro(Debug_Flag);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, true);\t\t// no transition picture to briefing\n\t\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\t\tPlay_Movie(VQ_SIZZLE, THEME_NONE, true);\n\t\t\t\t\t\tPlay_Movie(VQ_SIZZLE2, THEME_NONE, true);\n//\t\t\t\t\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, false);\t\t// has transitino picture to briefing\n\t\t\t\t\t}\n\t\t\t\t\tTheme.Queue_Song(THEME_CRUS);\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tfade = true;\n\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tExit to DOS.\n\t\t\t\t*/\n\t\t\t\tcase SEL_EXIT:\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\t\t\t\treturn(false);\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the hall of fame.\n\t\t\t\t*/\n\t\t\t\tcase SEL_FAME:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEL_TIMEOUT:\n\t\t\t\t\tif (Session.Attract && Session.RecordFile.Is_Available()) {\n\t\t\t\t\t\tSession.Play = true;\n\t\t\t\t\t\tif (Session.RecordFile.Open(READ)) {\n\t\t\t\t\t\t\tLoad_Recording_Values(Session.RecordFile);\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSession.Play = false;\n\t\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = SEL_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t** For Debug_Map (editor) mode to load scenario\n\t\t*/\n\t\tScen.Set_Scenario_Name(\"SCG01EA.INI\");\n\t}\n\n\t/*\n\t**\tDon't carry stray keystrokes into game.\n\t*/\n\tKeyboard->Clear();\n\n\t/*\n\t** Initialize the random number generator(s)\n\t*/\n\tInit_Random();\n\n\t/*\n\t** Save initialization values if we're recording this game.\n\t*/\n\tif (Session.Record) {\n\t\tif (Session.RecordFile.Open(WRITE)) {\n\t\t\tSave_Recording_Values(Session.RecordFile);\n\t\t} else {\n\t\t\tSession.Record = false;\n\t\t}\n\t}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tswitch(Session.Type) {\n\t\tcase GAME_MODEM:\n\t\tcase GAME_NULL_MODEM:\n\t\tcase GAME_IPX:\n#ifdef FIXIT_VERSION_3\n\t\t\tif( !bAftermathMultiplayer ) {\n#else\n\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS) {\n#endif\n\t\t\t\tNewUnitsEnabled = SecretUnitsEnabled = false;\n\t\t\t} else {\n\t\t\t\tNewUnitsEnabled = true;\n\t\t\t}\n//\t\t\tdebugprint( \"Non Internet game: NewUnitsEnabled = %i\\n\", NewUnitsEnabled );\n\t\t\tbreak;\n\t\tcase GAME_INTERNET:\n#if (0)\n\t\t\tif( !pWolapi )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pWolapi is null on internet game!\" );\n\t\t\t\tFatal( \"pWolapi is null on internet game!\" );\n\t\t\t}\n\t\t\t//if( pWolapi->bEnableNewAftermathUnits )\n\t\t\tif( bAftermathMultiplayer )\n\t\t\t\tNewUnitsEnabled = true;\n\t\t\telse\n\t\t\t\tNewUnitsEnabled = SecretUnitsEnabled = false;\n//\t\t\tdebugprint( \"Internet game: NewUnitsEnabled = %i\\n\", NewUnitsEnabled );\n#endif\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n#endif\n\t/*\n\t**\tLoad the scenario.  Specify variation 'A' for the editor; for the game,\n\t**\tdon't specify a variation, to make 'Set_Scenario_Name()' pick a random one.\n\t**\tSkip this if we've already loaded a save-game.\n\t*/\n\tif (!gameloaded && !Session.LoadGame) {\n//\t\tif (Debug_Map) {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, SCEN_VAR_A);\n//\t\t}  else {\n//\t\t\tSet_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir);\n//\t\t}\n\n\t\t/*\n\t\t** Start_Scenario() changes the palette; so, fade out & clear the screen\n\t\t** before calling it.\n\t\t*/\n\t\tHide_Mouse();\n\n\t\tif (selection != SEL_START_NEW_GAME) {\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n\t\t\tHiddenPage.Clear();\n\t\t\tVisiblePage.Clear();\n#else\n\t\t\tHidPage.Clear();\n\t\t\tSeenPage.Clear();\n#endif\t//WIN32\n\t\t}\n\t\tShow_Mouse();\n//Mono_Printf(\"About to call Start Scenario with %s\\n\", Scen.ScenarioName);\n\t\tif (!Start_Scenario(Scen.ScenarioName)) {\n\t\t\treturn(false);\n\t\t}\n\t\tif (Special.IsFromInstall) Show_Mouse();\n\t\tSpecial.IsFromInstall = false;\n\t}\n\n\t/*\n\t**\tFor multiplayer games, initialize the inter-player message system.\n\t**\tDo this after loading the scenario, so the map's upper-left corner is\n\t**\tproperly set.\n\t*/\n\tSession.Messages.Init(\n\t\tMap.TacPixelX, Map.TacPixelY, \t// x,y for messages\n\t\t6, \t\t\t\t\t\t\t\t\t\t// max # msgs\n\t\tMAX_MESSAGE_LENGTH-14,\t\t\t\t// max msg length\n\t\t7 * RESFACTOR,\t\t\t\t\t\t\t// font height in pixels\n\t\t-1, -1, \t\t\t\t\t\t\t\t\t// x,y for edit line (appears above msgs)\n\t\t0,//BG\t\t1,\t\t\t\t\t\t\t// enable edit overflow\n\t\t20,          \t\t\t\t\t\t\t// min,\n\t\tMAX_MESSAGE_LENGTH - 14,\t\t\t//    max for trimming overflow\n#ifdef WIN32\n\t\tLepton_To_Pixel(Map.TacLeptonWidth));\t// Width in pixels of buffer\n#else\n\t\t(320-SIDEBAR_WID));\t// Width in pixels of buffer\n#endif\n\n\tif (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&\n\t\t!Session.Play) {\n\t\tif (Session.Type == GAME_TEN) {\n#if(TEN)\n\t\t\tSession.Create_TEN_Connections();\n#endif\t// TEN\n\t\t} else if (Session.Type == GAME_MPATH) {\n#if(MPATH)\n\t\t\tSession.Create_MPATH_Connections();\n#endif\n\t\t} else {\n\t\t\tSession.Create_Connections();\n\t\t}\n\t}\n\n\n\t/*\n\t** If this isnt an internet game that set the unit build rate to its default value\n\t*/\n\tif (Session.Type != GAME_INTERNET){\n\t\tUnitBuildPenalty = 100;\n\t}\n\n\t/*\n\t**\tHide the SeenPage; force the map to render one frame.  The caller can\n\t**\tthen fade the palette in.\n\t**\t(If we loaded a game, this step will fade out the title screen.  If we\n\t**\tstarted a scenario, Start_Scenario() will have played a couple of VQ\n\t**\tmovies, which will have cleared the screen to black already.)\n\t*/\n\tCall_Back();\n\tHide_Mouse();\n\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n//\tFade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);\n#ifdef WIN32\n\tHiddenPage.Clear();\n\tVisiblePage.Clear();\n#else\n\tHidPage.Clear();\n\tSeenPage.Clear();\n#endif\t//WIN32\n\tShow_Mouse();\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\t/*\n\t** Sidebar is always active in hi-res.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n\t}\n#endif\t//WIN32\n\tMap.Flag_To_Redraw();\n\tCall_Back();\n\tMap.Render();\n\n#ifdef WOLAPI_INTEGRATION\n\n\t\t\t\t\t\t//ajw debugging only\n//\t\t\t\t\t\tdebugprint( \"Debugging Session...\\n\" );\n//\t\t\t\t\t\tdebugprint( \"Session.Players count is %i.\\n\", Session.Players.Count() );\n\t\t\t\t\t\tfor (i = 0; i < Session.Players.Count(); i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tNetNumType net;\n\t\t\t\t\t\t\tNetNodeType node;\n\t\t\t\t\t\t\tSession.Players[i]->Address.Get_Address( net, node );\n//\t\t\t\t\t\t\tdebugprint( \"Player %i, %s, color %i, ip %i.%i.%i.%i.%i.%i\\n\", i, Session.Players[i]->Name, \n//\t\t\t\t\t\t\t\tSession.Players[i]->Player.Color, node[0], node[1], node[2], node[3], node[4], node[5] );\n\t\t\t\t\t\t}\n//\t\t\t\t\t\tdebugprint( \"PlanetWestwoodPortNumber is %i\\n\", PlanetWestwoodPortNumber );\n\n#endif\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Play_Intro -- plays the introduction & logo movies                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/06/1995 BRR : Created.                                                                 *\n *   05/08/1996 JLB : Modified for Red Alert and direction control.                            *\n *=============================================================================================*/\nstatic void Play_Intro(bool sequenced)\n{\n\tstatic VQType _counter = VQ_FIRST;\n\n\tKeyboard->Clear();\n\tif (sequenced) {\n\t\tif (_counter <= VQ_FIRST) _counter = VQ_COUNT;\n\t\tif (_counter == VQ_COUNT) _counter--;\n\t\tif (_counter == VQ_REDINTRO) _counter--;\n\t\tif (_counter == VQ_TITLE) _counter--;\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(VQType(_counter--), THEME_NONE);\n\t\t\n//\t\tShow_Mouse();\n\t} else {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n#ifdef WIN32\n\t\tPlay_Movie(VQ_REDINTRO, THEME_NONE, false);\n#else\n\t\tPlay_Movie(VQ_TITLE, THEME_NONE, false);\n#endif\n\t}\n}\n\n\n/***********************************************************************************************\n * Anim_Init -- Initialize the VQ animation control structure.                                 *\n *                                                                                             *\n *    VQ animations are controlled by a structure passed to the VQ player. This routine        *\n *    initializes the structure to values required by C&C.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only need to call this routine once at the beginning of the game.               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\n\n#ifdef WIN32\n#ifdef MOVIE640\n//GraphicBufferClass VQ640(711, 400, (void *)NULL);\n#endif\n#endif\nvoid Anim_Init(void)\n{\n#if (0)\n#ifdef WIN32\n\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n\tAnimControl.DrawFlags = VQACFGF_TOPLEFT;\n\tAnimControl.DrawFlags |= VQACFGF_BUFFER;\n//AnimControl.DrawFlags |= VQACFGF_NODRAW;\n//BG - M. Grayford says turn this off\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\n\tAnimControl.DrawFlags |= VQACFGF_NOSKIP;\n\tAnimControl.FrameRate = -1;\n\tAnimControl.DrawRate = -1;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();\n#ifdef MOVIE640\n\tif(IsVQ640) {\n\t\tAnimControl.ImageWidth = 711;\n\t\tAnimControl.ImageHeight = 400;\n\t\tAnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();\n\t}\n#endif\n\tAnimControl.Vmode = 0;\n\tAnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n\tif (SlowPalette) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_SLOWPAL;\n\t}\n\tAnimControl.SoundObject = SoundObject;\n\tAnimControl.PrimaryBufferPtr = PrimaryBufferPtr;\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#else\t//WIN32\n\t/* Configure player with INI file */\n\tVQA_DefaultConfig(&AnimControl);\n//\tvoid const * font = Load_Font(FONT8);\n//\tAnimControl.EVAFont = (char *)font;\n//\tAnimControl.CapFont = (char *)font;\n\tAnimControl.DrawerCallback = VQ_Call_Back;\n\tAnimControl.ImageWidth = 320;\n\tAnimControl.ImageHeight = 200;\n\tAnimControl.Vmode = MCGA_MODE;\n\tAnimControl.VBIBit = VertBlank;\n\tAnimControl.DrawFlags |= VQACFGF_TOPLEFT;\n\tAnimControl.OptionFlags |= VQAOPTF_HMIINIT|VQAOPTF_CAPTIONS|VQAOPTF_EVA;\n//\tAnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();\n//\tAnimControl.AudioBufSize = 32768U;\n\tAnimControl.DigiCard = NewConfig.DigitCard;\n\tAnimControl.HMIBufSize = 8192;\n\tAnimControl.DigiHandle = Get_Digi_Handle();\n\tAnimControl.Volume = 0x00FF;\n\tAnimControl.AudioRate = 22050;\n//\tif (NewConfig.Speed) AnimControl.AudioRate = 11025;\n\n\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t}\n\n\tif (MonoClass::Is_Enabled()) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_MONO;\n\t}\n\n#endif\t//WIN32\n#endif\n}\n\n\n/***********************************************************************************************\n * Parse_Command_Line -- Parses the command line parameters.                                   *\n *                                                                                             *\n *    This routine should be called before the graphic mode is initialized. It examines the    *\n *    command line parameters and sets the appropriate globals. If there is an error, then     *\n *    it outputs a command summary and then returns false.                                     *\n *                                                                                             *\n * INPUT:   argc  -- The number of command line arguments.                                     *\n *                                                                                             *\n *          argv  -- Pointer to character string array that holds the individual arguments.    *\n *                                                                                             *\n * OUTPUT:  bool; Was the command line parsed successfully?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Parse_Command_Line(int argc, char * argv[])\n{\n\t/*\n\t**\tParse the command line and set globals to reflect the parameters\n\t**\tpassed in.\n\t*/\n\tWhom = HOUSE_GOOD;\n\tSpecial.Init();\n\n\tDebug_Map = false;\n\tDebug_Unshroud = false;\n\n\tfor (int index = 1; index < argc; index++) {\n\t\tchar * string;\t\t// Pointer to argument.\n\t\tlong code = 0;\n\n\t\tchar arg_string[512];\n\t\tint str_len = strlen(argv[index]);\n\t\tchar *src = argv[index];\n\t\tchar *dest = arg_string; \n\t\tfor (int i=0 ; i<str_len ; i++) {\n\t\t\tif (*src == '\\\"') {\n\t\t\t\tsrc++;\n\t\t\t} else {\n\t\t\t\t*dest++ = *src++;\n\t\t\t}\n\t\t}\n\t\t*dest++ = 0;\n\t\tstring = arg_string;\n\t\tstrupr(string);\n\n\t\t//string = strupr(argv[index]);\n\n\t\t/*\n\t\t**\tPrint usage text only if requested.\n\t\t*/\n\t\tif (stricmp(\"/?\", string) == 0 || stricmp(\"-?\", string) == 0 || stricmp(\"-h\", string) == 0 || stricmp(\"/h\", string) == 0) {\n\t\t\t/*\n\t\t\t**\tUnrecognized command line parameter... Display usage\n\t\t\t**\tand then exit.\n\t\t\t*/\n\t\t\tputs(TEXT_OPTIONS);\n\t\t\treturn(false);\n\t\t}\n\n\n\t\tbool processed = true;\n\t\tlong ob = Obfuscate(string);\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\tlong const * optr = (const long*)&CheatCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a cheat enabling one.\n\t\t*/\n\t\toptr = (const long*)&PlayCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCheck to see if the parameter is a scenario editor\n\t\t**\tenabling one.\n\t\t*/\n\t\toptr = (const long*)&EditorCodes[0];\n\t\twhile (*optr) {\n\t\t\tif (*optr++ == ob) {\n\t\t\t\tDebug_Map = true;\n\t\t\t\tDebug_Unshroud = true;\n\t\t\t\tDebug_Flag = true;\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tswitch (ob) {\n\n#ifdef VIRGIN_CHEAT_KEYS\n\t\t\tcase PARM_PLAYTEST:\n\t\t\t\tDebug_Playtest = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*\n\t\t\t** Special flag - is C&C being run from the install program?\n\t\t\t*/\n\t\t\tcase PARM_INSTALL:\n\t\t\t\tSpecial.IsFromInstall = true;\n// If uncommented, will disable the <ESC> key during the first movie run.\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\tcase PARM_ALLOW_SOLO:\n\t\t\t\tSession.AllowSolo = 1;\n\t\t\t\tbreak;\n#endif\n\n#if(MPATH)\n\t\t\tcase PARM_ALLOW_SOLO:\n\t\t\t\tSession.AllowSolo = 1;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tdefault:\n\t\t\t\tprocessed = false;\n\t\t\t\tbreak;\n\t\t}\n\t\tif (processed) continue;\n\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tScenario Editor Mode\n\t\t*/\n\t\tif (stricmp(string, \"-CHECKMAP\") == 0) {\n\t\t\tDebug_Check_Map = true;\n\t\t\tcontinue;\n\t\t}\n\n#endif\n\n\t\t/*\n\t\t**\tFile search path override.\n\t\t*/\n\t\tif (strstr(string, \"-CD\")) {\n\t\t\tCCFileClass::Set_Search_Drives(&string[3]);\n\t\t\tcontinue;\n\t\t}\n\n#if (0)\n\t\t/*\n\t\t** Build speed modifier\n\t\t*/\n\t\tif (strstr (string, \"-UNITRATE:\")){\n\t\t\tint unit_rate;\n\t\t\tsscanf (string, \"-UNITRATE:%d\", &unit_rate);\n\t\t\tUnitBuildPenalty = unit_rate;\n\t\t}\n#endif\t//(0)\n\n\t\t/*\n\t\t**\tSpecify destination connection for network play\n\t\t*/\n\t\tif (strstr(string, \"-DESTNET\")) {\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\n\t\t\t/*\n\t\t\t** Scan the command-line string, pulling off each address piece\n\t\t\t*/\n\t\t\tint i = 0;\n\t\t\tchar * p = strtok(string + 8, \".\");\n\t\t\twhile (p) {\n\t\t\t\tint x;\n\n\t\t\t\tsscanf(p, \"%x\", &x);\t\t\t// convert from hex string to int\n\t\t\t\tif (i < 4) {\n\t\t\t\t\tnet[i] = (char)x;\t\t\t// fill NetNum\n\t\t\t\t} else {\n\t\t\t\t\tnode[i-4] = (char)x;\t\t// fill NetNode\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tp = strtok(NULL, \".\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If all the address components were successfully read, fill in the\n\t\t\t** BridgeNet with a broadcast address to the network across the bridge.\n\t\t\t*/\n\t\t\tif (i >= 4) {\n\t\t\t\tSession.IsBridge = 1;\n\t\t\t\tmemset(node, 0xff, 6);\n\t\t\t\tSession.BridgeNet = IPXAddressClass(net, node);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSpecify socket ID, as an offset from 0x4000.\n\t\t*/\n\t\tif (strstr(string, \"-SOCKET\")) {\n\t\t\tunsigned short socket;\n\n\t\t\tsocket = (unsigned short)(atoi(string + strlen(\"SOCKET\")));\n\t\t\tsocket += 0x4000;\n\t\t\tif (socket >= 0x4000 && socket < 0x8000) {\n\t\t\t\tIpx.Set_Socket (socket);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Stealth option\n\t\t*/\n\t\tif (strstr(string, \"-STEALTH\")) {\n\t\t\tSession.NetStealth = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the Net Protection option\n\t\t*/\n\t\tif (strstr(string, \"-MESSAGES\")) {\n\t\t\tSession.NetProtect = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tAllow \"attract\" mode\n\t\t*/\n\t\tif (strstr(string, \"-ATTRACT\")) {\n\t\t\tSession.Attract = true;\n\t\t\tcontinue;\n\t\t}\n\n\n#ifdef WIN32\n\t\t/*\n\t\t** Set screen to 640x480 instead of 640x400\n\t\t*/\n\t\tif (strstr(string, \"-480\")) {\n\t\t\tScreenHeight = 480;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t** Check for spawn from WChat\n\t\t*/\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n\t\tif (strstr(string,\"-WCHAT\")){\n\t\t\tSpawnedFromWChat = true;\n\t\t}\n#endif\n\n#endif\n\n#ifdef CHEAT_KEYS\n\t\t/*\n\t\t**\tSpecify the random number seed (for debugging)\n\t\t*/\n\t\tif (strstr(string, \"-SEED\")) {\n\t\t\tCustomSeed = (unsigned short)(atoi(string + strlen(\"SEED\")));\n\t\t\tcontinue;\n\t\t}\n\n#ifndef WIN32\n\t\t/*\n\t\t**\tDon't install Page Fault Handler (MUST use this for debugger)\n\t\t*/\n\t\tif (stricmp(string, \"-NOPFS\") == 0) {\n\t\t\tUsePageFaultHandler = 0;\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#endif\n\n\n#if(TEN)\n\t\t/*\n\t\t**\tEnable TEN\n\t\t*/\n\t\tif (strstr(string, \"TEN\")) {\n\n#ifdef CHEAT_KEYS\n\t\t\tDebug_Flag = true;\n\t\t\tMonoClass::Enable();\n#endif\n\n\t\t\tSession.Type = GAME_TEN;\n\t\t\tSpecial.IsFromInstall = false;\n\t\t\t//\n\t\t\t// Create the Ten network manager.  This allows us to keep\n\t\t\t// the packet queues clean even while we're initializing the game,\n\t\t\t// so the queues don't fill up in case we're slow, or the user\n\t\t\t// didn't insert a CD.\n\t\t\t//\n\t\t\tTen = new TenConnManClass();\n\t\t\tTen->Init();\n\t\t\tstrcpy(Session.OptionsFile, \"OPTIONS.INI\");\n\t\t\tTen->Flush_All();\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the game options filename\n\t\t*/\n\t\tif (strstr(string, \"OPTIONS:\")) {\n\t\t\tstrcpy(Session.OptionsFile, string + 8);\n\t\t\tcontinue;\n\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t/*\n\t\t**\tEnable MPATH\n\t\t*/\n\t\tif (strstr(string, \"MPATH\")) {\n\n#ifdef CHEAT_KEYS\n\t\t\tDebug_Flag = true;\n\t\t\tMonoClass::Enable();\n#endif\n\n\t\t\tSession.Type = GAME_MPATH;\n\t\t\tSpecial.IsFromInstall = false;\n\t\t\t//\n\t\t\t// Create the MPath network manager.  This allows us to keep\n\t\t\t// the packet queues clean even while we're initializing the game,\n\t\t\t// so the queues don't fill up in case we're slow, or the user\n\t\t\t// didn't insert a CD.\n\t\t\t//\n\t\t\tMPath = new MPlayerManClass();\n\t\t\tMPath->Init();\n\t\t\tstrcpy(Session.OptionsFile, \"OPTIONS.INI\");\n\t\t\tMPath->Flush_All();\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tSet the game options filename\n\t\t*/\n\t\tif (strstr(string, \"OPTIONS:\")) {\n\t\t\tstrcpy(Session.OptionsFile, string + 8);\n\t\t\tcontinue;\n\t\t}\n#endif\t// MPATH\n\n\n#ifdef NEVER\n\t\t/*\n\t\t**\tHandle the prog init differently in this case.\n\t\t*/\n\t\tif (strstr(string, \"-V\")) {\n\t\t\tcontinue;\n\t\t}\n#endif\n\n\t\t/*\n\t\t** look for passed-in video mode to default to\n\t\t*/\n#ifndef\tWIN32\n\t\tif (strnicmp(string, \"-V\", strlen(\"-V\")) == 0) {\n\t\t\tSet_Video_Mode(MCGA_MODE);\t// do this to get around first_time variable...\n\t\t\tSet_Original_Video_Mode(atoi(string+2));\n\t\t\tcontinue;\n\t\t}\n#endif\n\n#ifdef CHEAT_KEYS\n\t\tif (strstr(string,\"-NOMOVIES\")){\n\t\t\tbNoMovies = true;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tSpecial command line control parsing.\n\t\t*/\n\t\tif (strnicmp(string, \"-X\", strlen(\"-O\")) == 0) {\n\t\t\tstring += strlen(\"-X\");\n\t\t\twhile (*string) {\n\t\t\t\tchar code = *string++;\n\t\t\t\tswitch (toupper(code)) {\n\n#ifdef  CHEAT_KEYS\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMonochrome debug screen enable.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tMonoClass::Enable();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tInert weapons -- no units take damage.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'I':\n\t\t\t\t\t\tSpecial.IsInert = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tHussled recharge timer.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'H':\n\t\t\t\t\t\tSpecial.IsSpeedBuild = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Record\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'X':\n\t\t\t\t\t\tSession.Record = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t\"Play Back\" a multi-player game\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Y':\n\t\t\t\t\t\tSession.Play = 1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrint lots of debug stuff about events & packets\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'P':\n\t\t\t\t\t\tDebug_Print_Events = true;\n\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tQuiet mode override control.\n\t\t\t\t\t*/\n\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\tDebug_Quiet = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tputs(TEXT_INVALID);\n\t\t\t\t\t\treturn(false);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Obfuscate -- Sufficiently transform parameter to thwart casual hackers.                     *\n *                                                                                             *\n *    This routine borrows from CRC and PGP technology to sufficiently alter the parameter     *\n *    in order to make it difficult to reverse engineer the key phrase. This is designed to    *\n *    be used for hidden game options that will be released at a later time over Westwood's    *\n *    Web page or through magazine hint articles.                                              *\n *                                                                                             *\n *    This algorithm is cryptographically categorized as a \"one way hash\".                     *\n *                                                                                             *\n *    Since this is a one way transformation, it becomes much more difficult to reverse        *\n *    engineer the pass phrase even if the resultant pass code is known. This has an added     *\n *    benefit of making this algorithm immune to traditional cryptographic attacks.            *\n *                                                                                             *\n *    The largest strength of this transformation algorithm lies in the restriction on the     *\n *    source vector being legal ASCII uppercase characters. This restriction alone makes even  *\n *    a simple CRC transformation practically impossible to reverse engineer. This algorithm   *\n *    uses far more than a simple CRC transformation to achieve added strength from advanced   *\n *    attack methods.                                                                          *\n *                                                                                             *\n * INPUT:   string   -- Pointer to the key phrase that will be transformed into a code.        *\n *                                                                                             *\n * OUTPUT:  Returns with the code that the key phrase is translated into.                      *\n *                                                                                             *\n * WARNINGS:   A zero length pass phrase results in a 0x00000000 result code.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Obfuscate(char const * string)\n{\n\tchar buffer[1024];\n\n\tif (!string) return(0);\n\tmemset(buffer, '\\xA5', sizeof(buffer));\n\n\t/*\n\t**\tCopy key phrase into a working buffer. This hides any transformation done\n\t**\tto the string.\n\t*/\n\tstrncpy(buffer, string, sizeof(buffer));\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\tint length = strlen(buffer);\n\n\t/*\n\t**\tOnly upper case letters are significant.\n\t*/\n\tstrupr(buffer);\n\n\t/*\n\t**\tEnsure that only visible ASCII characters compose the key phrase. This\n\t**\tdiscourages the direct forced illegal character input method of attack.\n\t*/\n\tint index;\n\tfor (index = 0; index < length; index++) {\n\t\tif (!isgraph(buffer[index])) {\n\t\t\tbuffer[index] = 'A' + (index%26);\n\t\t}\n\t}\n\n\t/*\n\t**\tIncrease the strength of even short pass phrases by extending the\n\t**\tlength to be at least a minimum number of characters. This helps prevent\n\t**\ta weak pass phrase from compromising the obfuscation process. This\n\t**\tprocess also forces the key phrase to be an even multiple of four.\n\t**\tThis is necessary to support the cypher process that occurs later.\n\t*/\n\tif (length < 16 || (length & 0x03)) {\n\t\tint maxlen = 16;\n\t\tif (((length+3) & 0x00FC) > maxlen) {\n\t\t\tmaxlen = ((length+3) & 0x00FC);\n\t\t}\n\t\tfor (index = length; index < maxlen; index++) {\n\t\t\tbuffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);\n\t\t}\n\t\tlength = index;\n\t\tbuffer[length] = '\\0';\n\t}\n\n\t/*\n\t**\tTransform the buffer into a number. This transformation is character\n\t**\torder dependant.\n\t*/\n\tlong code = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tRecord a copy of this initial transformation to be used in a later\n\t**\tself referential transformation.\n\t*/\n\tlong copy = code;\n\n\t/*\n\t**\tReverse the character string and combine with the previous transformation.\n\t**\tThis doubles the workload of trying to reverse engineer the CRC calculation.\n\t*/\n\tstrrev(buffer);\n\tcode ^= Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tPerform a self referential transformation. This makes a reverse engineering\n\t**\tby using a cause and effect attack more difficult.\n\t*/\n\tcode = code ^ copy;\n\n\t/*\n\t**\tUnroll and combine the code value into the pass phrase and then perform\n\t**\tanother self referential transformation. Although this is a trivial cypher\n\t**\tprocess, it gives the sophisticated hacker false hope since the strong\n\t**\tcypher process occurs later.\n\t*/\n\tstrrev(buffer);\t\t// Restore original string order.\n\tfor (index = 0; index < length; index++) {\n\t\tcode ^= (unsigned char)buffer[index];\n\t\tunsigned char temp = (unsigned char)code;\n\t\tbuffer[index] ^= temp;\n\t\tcode >>= 8;\n\t\tcode |= (((long)temp)<<24);\n\t}\n\n\t/*\n\t**\tIntroduce loss into the vector. This strengthens the key against traditional\n\t**\tcryptographic attack engines. Since this also weakens the key against\n\t**\tunconventional attacks, the loss is limited to less than 10%.\n\t*/\n\tfor (index = 0; index < length; index++) {\n\t\tstatic unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};\n\t\tstatic unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};\n\n\t\tbuffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];\n\t\tbuffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];\n\t}\n\n\t/*\n\t**\tPerform a general cypher transformation on the vector\n\t**\tand use the vector itself as the cypher key. This is a variation on the\n\t**\tcypher process used in PGP. It is a very strong cypher process with no known\n\t**\tweaknesses. However, in this case, the cypher key is the vector itself and this\n\t**\topens up a weakness against attacks that have access to this transformation\n\t**\talgorithm. The sheer workload of reversing this transformation should be enough\n\t**\tto discourage even the most determined hackers.\n\t*/\n\tfor (index = 0; index < length; index += 4) {\n\t\tshort key1 = buffer[index];\n\t\tshort key2 = buffer[index+1];\n\t\tshort key3 = buffer[index+2];\n\t\tshort key4 = buffer[index+3];\n\t\tshort val1 = key1;\n\t\tshort val2 = key2;\n\t\tshort val3 = key3;\n\t\tshort val4 = key4;\n\n\t\tval1 *= key1;\n\t\tval2 += key2;\n\t\tval3 += key3;\n\t\tval4 *= key4;\n\n\t\tshort s3 = val3;\n\t\tval3 ^= val1;\n\t\tval3 *= key1;\n\t\tshort s2 = val2;\n\t\tval2 ^= val4;\n\t\tval2 += val3;\n\t\tval2 *= key3;\n\t\tval3 += val2;\n\n\t\tval1 ^= val2;\n\t\tval4 ^= val3;\n\n\t\tval2 ^= s3;\n\t\tval3 ^= s2;\n\n\t\tbuffer[index] = val1;\n\t\tbuffer[index+1] = val2;\n\t\tbuffer[index+2] = val3;\n\t\tbuffer[index+3] = val4;\n\t}\n\n\t/*\n\t**\tConvert this final vector into a cypher key code to be\n\t**\treturned by this routine.\n\t*/\n\tcode = Calculate_CRC(buffer, length);\n\n\t/*\n\t**\tReturn the final code value.\n\t*/\n\treturn(code);\n}\n\n\n/***********************************************************************************************\n * Calculate_CRC -- Calculates a one-way hash from a data block.                               *\n *                                                                                             *\n *    This routine is used to create a hash value from a data block. The algorithm is similar  *\n *    to a CRC, but is faster.                                                                 *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to a buffer of data to be 'hashed'.                            *\n *                                                                                             *\n *          len      -- The length of the buffer to compute the hash upon.                     *\n *                                                                                             *\n * OUTPUT:  Returns with a 32bit hash value calculated from the specified buffer.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern \"C\"  {\nlong Calculate_CRC(void * buffer, long len)\n{\n\treturn(CRCEngine()(buffer, len));\n}\n}\n\n\n/***************************************************************************\n * Init_Random -- Initializes the random-number generator                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Init_Random(void)\n{\n\t#ifdef WIN32\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the system timer. Actually, only the\n\t\t**\tlow order millisecond bits are secure. The other bits could be\n\t\t**\teasily guessed from the system clock (most clocks are fairly accurate\n\t\t**\tand thus predictable).\n\t\t*/\n\t\tSYSTEMTIME t;\n\t\tGetSystemTime(&t);\n\t\tCryptRandom.Seed_Byte(t.wMilliseconds);\n\t\tCryptRandom.Seed_Bit(t.wSecond);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>1);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>2);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>3);\n\t\tCryptRandom.Seed_Bit(t.wSecond>>4);\n\t\tCryptRandom.Seed_Bit(t.wMinute);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>1);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>2);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>3);\n\t\tCryptRandom.Seed_Bit(t.wMinute>>4);\n\t\tCryptRandom.Seed_Bit(t.wHour);\n\t\tCryptRandom.Seed_Bit(t.wDay);\n\t\tCryptRandom.Seed_Bit(t.wDayOfWeek);\n\t\tCryptRandom.Seed_Bit(t.wMonth);\n\t\tCryptRandom.Seed_Bit(t.wYear);\n\t#else\n\n\t\t/*\n\t\t**\tGather some \"random\" bits from the DOS mode timer.\n\t\t*/\n\t\tstruct timeb t;\n\t\tftime(&t);\n\t\tCryptRandom.Seed_Byte(t.millitm);\n\t\tCryptRandom.Seed_Byte(t.time);\n\t#endif\n\n#ifdef FIXIT_MULTI_SAVE\n\t//\n\t// If we've loaded a multiplayer save game, return now; the random #\n\t// class is loaded along with ScenarioClass.\n\t//\n\tif (Session.LoadGame) {\n\t\treturn;\n\t}\n\n\t//\n\t// If we're playing a recording, the Seed is loaded in\n\t// Load_Recording_Values().  Just init the random # and return.\n\t//\n\tif (Session.Play) {\n\t\tRandNumb = Seed;\n\t\tScen.RandomNumber = Seed;\n\t\treturn;\n\t}\n#else\n\t/*\n\t** Do nothing if we've loaded a multiplayer game, or we're playing back\n\t** a recording; the random number generator is initialized by loading\n\t** the game.\n\t*/\n\tif (Session.LoadGame || Session.Play) {\n\t\tRandNumb = Seed;\n\t\tScen.RandomNumber = Seed;\n\t\treturn;\n\t}\n#endif\t// FIXIT_MULTI_SAVE\n\n\t/*\n\t**\tInitialize the random number Seed.  For multiplayer, this will have been done\n\t** in the connection dialogs.  For single-player games, AND if we're not playing\n\t** back a recording, init the Seed to a random value.\n\t*/\n\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH &&\n\t\t!Session.Play) {\n\n\t\t/*\n\t\t** Set the optional user-specified seed\n\t\t*/\n\t\tif (CustomSeed != 0) {\n\t\t\tSeed = CustomSeed;\n\t\t} else {\n\t\t\tsrand(time(NULL));\n\t\t\tSeed = rand();\n\t\t}\n\t}\n\n\t/*\n\t**\tInitialize the random-number generators\n\t*/\n\tScen.RandomNumber = Seed;\n\tRandNumb = Seed;\n}\n\n\n/***********************************************************************************************\n * Load_Title_Page -- Load the background art for the title page.                              *\n *                                                                                             *\n *    This routine will load the background art in a machine independent format. There is      *\n *    different art required for the hi-res and lo-res versions of the game.                   *\n *                                                                                             *\n * INPUT:   visible  -- Should the title page art be copied to the visible page by this        *\n *                      routine?                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the mouse is hidden if the image is to be copied to the visible page.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Load_Title_Page(bool visible)\n{\n#ifdef WIN32\n\tLoad_Title_Screen(\"TITLE.PCX\", &HidPage, (unsigned char*)CCPalette.Get_Data());\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#else\n\tLoad_Picture(\"TITLE.CPS\", HidPage, HidPage, CCPalette, BM_DEFAULT);\n\tif (visible) {\n\t\tHidPage.Blit(SeenPage);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Init_Color_Remaps -- Initialize the text remap tables.                                      *\n *                                                                                             *\n *    There are various color scheme remap tables that are dependant upon the color remap      *\n *    information embedded within the palette control file. This routine will fetch that       *\n *    data and build the text remap tables as indicated.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *   09/11/2019 ST : The default resolution doesn't have to match the size of the palette image*\n *=============================================================================================*/\nstatic void Init_Color_Remaps(void)\n{\n\t/*\n\t**\tSetup the remap tables.  PALETTE.CPS contains a special set of pixels in\n\t** the upper-left corner.  Each row of 16 pixels is one range of colors.  The\n\t** first row represents unity (the default color units are drawn in); rows\n\t** after that are the remap colors.\n\t*/\n\n#ifdef WIN32\n\tGraphicBufferClass temp_page(320, 200, (void*)NULL);\n\ttemp_page.Clear();\n\tLoad_Picture(\"PALETTE.CPS\", temp_page, temp_page, NULL, BM_DEFAULT);\n\ttemp_page.Blit(HidPage);\n#else\n\tLoad_Picture(\"PALETTE.CPS\", HidPage, HidPage, NULL, BM_DEFAULT);\n#endif\n\tfor (PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++) {\n\n\t\tunsigned char * ptr = ColorRemaps[pcolor].RemapTable;\n\n\t\tfor (int color = 0; color < 256; color++) {\n\t\t\tptr[color] = color;\n\t\t}\n\t\t\n\t\tint index;\n\t\tfor (index = 0; index < 16; index++) {\n\t\t\tptr[HidPage.Get_Pixel(index, 0)] = HidPage.Get_Pixel(index, pcolor);\n\t\t}\n\t\tfor (index = 0; index < 6; index++) {\n\t\t\tColorRemaps[pcolor].FontRemap[10+index] = HidPage.Get_Pixel(2+index, pcolor);\n\t\t}\n\t\tColorRemaps[pcolor].BrightColor = WHITE;\n//\t\tColorRemaps[pcolor].BrightColor = HidPage.Get_Pixel(1, pcolor);\n\t\tColorRemaps[pcolor].Color = HidPage.Get_Pixel(4, pcolor);\n\n\t\tColorRemaps[pcolor].Shadow = HidPage.Get_Pixel(10, pcolor);\n\t\tColorRemaps[pcolor].Background = HidPage.Get_Pixel(9, pcolor);\n\t\tColorRemaps[pcolor].Corners = HidPage.Get_Pixel(7, pcolor);\n\t\tColorRemaps[pcolor].Highlight = HidPage.Get_Pixel(4, pcolor);\n\t\tColorRemaps[pcolor].Bright = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Underline = HidPage.Get_Pixel(0, pcolor);\n\t\tColorRemaps[pcolor].Bar = HidPage.Get_Pixel(6, pcolor);\n\n\t\t/*\n\t\t**\tThis must grab from column 4 because the multiplayer color dialog palette counts\n\t\t**\ton this to be true.\n\t\t*/\n\t\tColorRemaps[pcolor].Box = HidPage.Get_Pixel(4, pcolor);\n\t}\n\n\t/* 12/9/2019 SKY - Swap Blue and Grey color remaps */\n\t{\n\t\tRemapControlType temp;\n\t\tmemcpy(&temp, &ColorRemaps[PCOLOR_BLUE], sizeof(RemapControlType));\n\t\tmemcpy(&ColorRemaps[PCOLOR_BLUE], &ColorRemaps[PCOLOR_GREY], sizeof(RemapControlType));\n\t\tmemcpy(&ColorRemaps[PCOLOR_GREY], &temp, sizeof(RemapControlType));\n\t}\n\n\t/*\n\t** Now do the special dim grey scheme\n\t*/\n\tfor (int color = 0; color < 256; color++) {\n\t\tGreyScheme.RemapTable[color] = color;\n\t}\n\tfor (int index = 0; index < 6; index++) {\n\t\tGreyScheme.FontRemap[10+index] = HidPage.Get_Pixel(9+index, PCOLOR_GREY) & 0x00FF;\n\t}\n\tGreyScheme.BrightColor = HidPage.Get_Pixel(3, PCOLOR_GREY) & 0x00FF;\n\tGreyScheme.Color = HidPage.Get_Pixel(7, PCOLOR_GREY) & 0x00FF;\n\n\tGreyScheme.Shadow = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(15, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Background = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(14, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Corners = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(13, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Highlight = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(9, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bright = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Underline = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Bar = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\tGreyScheme.Box = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];\n\n\t/*\n\t** Set up the metallic remap table for the font that prints over the tabs\n\t*/\n\tmemset ((void*)&MetalScheme, 4, sizeof(MetalScheme));\n\tfor (int color_counter = 0; color_counter < 16; color_counter++) {\n\t\tMetalScheme.FontRemap[color_counter] = color_counter;\n\t}\n\tMetalScheme.FontRemap[1] = 128;\n\tMetalScheme.FontRemap[2] = 12;\n\tMetalScheme.FontRemap[3] = 13;\n\tMetalScheme.FontRemap[4] = 14;\n\tMetalScheme.Color = 128;\n\tMetalScheme.Background = 0;\n\tMetalScheme.Underline = 128;\n\n\t/*\n\t** Set up the font remap table for the mission briefing font\n\t*/\n\tfor (int colr = 0; colr < 16; colr++) {\n\t\tColorRemaps[PCOLOR_TYPE].FontRemap[colr] = HidPage.Get_Pixel(colr, PCOLOR_TYPE);\n\t}\n\n\tColorRemaps[PCOLOR_TYPE].Shadow = 11;\n\tColorRemaps[PCOLOR_TYPE].Background = 10;\n\tColorRemaps[PCOLOR_TYPE].Corners = 10;\n\tColorRemaps[PCOLOR_TYPE].Highlight = 9;\n\tColorRemaps[PCOLOR_TYPE].Bright = 15;\n\tColorRemaps[PCOLOR_TYPE].Underline = 11;\n\tColorRemaps[PCOLOR_TYPE].Bar = 11;\n\tColorRemaps[PCOLOR_TYPE].Box = 10;\n\tColorRemaps[PCOLOR_TYPE].BrightColor = 15;\n\tColorRemaps[PCOLOR_TYPE].Color = 9;\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n//\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_BLUE]);\n}\n\n\n/***********************************************************************************************\n * Init_Heaps -- Initialize the game heaps and buffers.                                        *\n *                                                                                             *\n *    This routine will allocate the game heaps and buffers. The rules file has already been   *\n *    processed by the time that this routine is called.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Heaps(void)\n{\n\t/*\n\t**\tInitialize the game object heaps.\n\t*/\n\tVessels.Set_Heap(Rule.VesselMax);\n\tUnits.Set_Heap(Rule.UnitMax);\n\tFactories.Set_Heap(Rule.FactoryMax);\n\tTerrains.Set_Heap(Rule.TerrainMax);\n\tTemplates.Set_Heap(Rule.TemplateMax);\n\tSmudges.Set_Heap(Rule.SmudgeMax);\n\tOverlays.Set_Heap(Rule.OverlayMax);\n\tInfantry.Set_Heap(Rule.InfantryMax);\n\tBullets.Set_Heap(Rule.BulletMax);\n\tBuildings.Set_Heap(Rule.BuildingMax);\n\tAnims.Set_Heap(Rule.AnimMax);\n\tAircraft.Set_Heap(Rule.AircraftMax);\n\tTriggers.Set_Heap(Rule.TriggerMax);\n\tTeamTypes.Set_Heap(Rule.TeamTypeMax);\n\tTeams.Set_Heap(Rule.TeamMax);\n\tHouses.Set_Heap(HOUSE_MAX);\n\tTriggerTypes.Set_Heap(Rule.TrigTypeMax);\n//\tWeapons.Set_Heap(Rule.WeaponMax);\n\n\t/*\n\t**\tSpeech holding tank buffer. Since speech does not mix, it can be placed\n\t**\tinto a custom holding tank only as large as the largest speech file to\n\t**\tbe played.\n\t*/\n\tfor (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {\n\t\tSpeechBuffer[index] = new char [SPEECH_BUFFER_SIZE];\n\t\tSpeechRecord[index] = VOX_NONE;\n\t\tassert(SpeechBuffer[index] != NULL);\n\t}\n\n\t/*\n\t**\tAllocate the theater buffer block.\n\t*/\n\tTheaterBuffer = new Buffer(THEATER_BUFFER_SIZE);\n\tassert(TheaterBuffer != NULL);\n}\n\n\n/***********************************************************************************************\n * Init_Expansion_Files -- Fetch any override expansion mixfiles.                              *\n *                                                                                             *\n *    This routine will search for and register/cache any override mixfiles found.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Expansion_Files(void)\n{\n\t/*\n\t** Need to search the search paths. ST - 3/15/2019 2:18PM\n\t*/\n\tconst char *path = \".\\\\\";\n\tchar search_path[_MAX_PATH];\n\tchar scan_path[_MAX_PATH];\n\n\tfor (int p = 0; p < 100; p++) {\n\n\t\tstrcpy(search_path, path);\n\t\tif (search_path[strlen(search_path) - 1] != '\\\\') {\n\t\t\tstrcat(search_path, \"\\\\\");\n\t\t}\n\n\t\tstrcpy(scan_path, search_path);\n\t\tstrcat(scan_path, \"SC*.MIX\");\n\n\t\tWIN32_FIND_DATA find_data;\n\t\tmemset(&find_data, 0, sizeof(find_data));\n\t\tHANDLE file_handle = FindFirstFile(scan_path, &find_data);\n\t\tif (file_handle != INVALID_HANDLE_VALUE)\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tchar *ptr = strdup(find_data.cFileName);\n\t\t\t\tnew MFCD(ptr, &FastKey);\n\t\t\t} while (FindNextFile(file_handle, &find_data));\n\t\t\tFindClose(file_handle);\n\t\t}\n\n\t\tmemset(&find_data, 0, sizeof(find_data));\n\t\tstrcpy(scan_path, search_path);\n\t\tstrcat(scan_path, \"Ss*.MIX\");\n\t\tfile_handle = FindFirstFile(scan_path, &find_data);\n\t\tif (file_handle != INVALID_HANDLE_VALUE)\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tchar *ptr = strdup(find_data.cFileName);\n\t\t\t\tnew MFCD(ptr, &FastKey);\n\t\t\t} while (FindNextFile(file_handle, &find_data));\n\t\t\tFindClose(file_handle);\n\t\t}\n\n\t\tpath = CDFileClass::Get_Search_Path(p);\n\n\t\tif (path == NULL) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n#if (0)\n\t/*\n\t**\tBefore all else, cache any additional mixfiles.\n\t*/\n\tstruct find_t ff;\t\t// for _dos_findfirst\n\tif (!_dos_findfirst(\"SC*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t\tMFCD::Cache(ptr);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n\tif (!_dos_findfirst(\"SS*.MIX\", _A_NORMAL, &ff)) {\n\t\tchar * ptr;\n\t\tdo {\n\t\t\tptr = strdup(ff.name);\n\t\t\tnew MFCD(ptr, &FastKey);\n\t\t} while (!_dos_findnext(&ff));\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * Init_One_Time_Systems -- Initialize internal pointers to the bulk data.                     *\n *                                                                                             *\n *    This performs the one-time processing required after the bulk data has been cached but   *\n *    before the game actually starts. Typically, this routine extracts pointers to all the    *\n *    embedded data sub-files within the main game data mixfile. This routine must be called   *\n *    AFTER the bulk data has been cached.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine AFTER the bulk data has been cached.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_One_Time_Systems(void)\n{\n\tCall_Back();\n\tMap.One_Time();\n\tLogic.One_Time();\n\tOptions.One_Time();\n\tSession.One_Time();\n\n\tObjectTypeClass::One_Time();\n\tBuildingTypeClass::One_Time();\n\tBulletTypeClass::One_Time();\n\tHouseTypeClass::One_Time();\n\tTemplateTypeClass::One_Time();\n\tOverlayTypeClass::One_Time();\n\tSmudgeTypeClass::One_Time();\n\tTerrainTypeClass::One_Time();\n\tUnitTypeClass::One_Time();\n\tVesselTypeClass::One_Time();\n\tInfantryTypeClass::One_Time();\n\tAnimTypeClass::One_Time();\n\tAircraftTypeClass::One_Time();\n\tHouseClass::One_Time();\n}\n\n\n/***********************************************************************************************\n * Init_Fonts -- Initialize all the game font pointers.                                        *\n *                                                                                             *\n *    This routine is used to fetch pointers to the game fonts. The mixfile containing these   *\n *    fonts must have been previously cached. This routine is a necessary prerequisite to      *\n *    displaying any dialogs or printing any text.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Fonts(void)\n{\n\tMetal12FontPtr = MFCD::Retrieve(\"12METFNT.FNT\");\n\tMapFontPtr = MFCD::Retrieve(\"HELP.FNT\");\n\tFont6Ptr = MFCD::Retrieve(\"6POINT.FNT\");\n\tGradFont6Ptr = MFCD::Retrieve(\"GRAD6FNT.FNT\");\n\tEditorFont = MFCD::Retrieve(\"EDITFNT.FNT\");\n\tFont8Ptr = MFCD::Retrieve(\"8POINT.FNT\");\n\tFontPtr = (char *)Font8Ptr;\n\tSet_Font(FontPtr);\n\tFont3Ptr = MFCD::Retrieve(\"3POINT.FNT\");\n\tScoreFontPtr = MFCD::Retrieve(\"SCOREFNT.FNT\");\n\tFontLEDPtr = MFCD::Retrieve(\"LED.FNT\");\n\tVCRFontPtr = MFCD::Retrieve(\"VCR.FNT\");\n\tTypeFontPtr = MFCD::Retrieve(\"8POINT.FNT\");    //(\"TYPE.FNT\"); //VG 10/17/96\n}\n\n\n/***********************************************************************************************\n * Init_CDROM_Access -- Initialize the CD-ROM access handler.                                  *\n *                                                                                             *\n *    This routine is called to setup the CD-ROM access or emulation handler. It will ensure   *\n *    that the appropriate CD-ROM is present (dependant on the RequiredCD global).             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The fonts, palettes, and other bootstrap systems must have been initialized     *\n *             prior to calling this routine since this routine will quite likely display      *\n *             a dialog box requesting the appropriate CD be inserted.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_CDROM_Access(void)\n{\n\tVisiblePage.Clear();\n\tHidPage.Clear();\n\n#ifdef FIXIT_VERSION_3\n\t//\tDetermine if we're going to be running from a DVD.\n\t//\tThe entire session will either require a DVD, or the regular CDs. Never both.\n\t//\tCall Using_DVD() to determine which case it is.\n\t//\tHere we set the value that Using_DVD() returns.\n\tDetermine_If_Using_DVD();\n\t//\tForce_CD_Available() is modified when Using_DVD() is true so that all requests become requests for the DVD.\n#endif\n\n\t/*\n\t**\tAlways try to look at the CD-ROM for data files.\n\t*/\n\tif (!CCFileClass::Is_There_Search_Drives()) {\n\n\t\t/*\n\t\t**\tThis call is needed because of a side effect of this function. It will examine the\n\t\t**\tCD-ROMs attached to this computer and set the appropriate status values. Without this\n\t\t**\tcall, the \"?:\\\\\" could not be filled in correctly.\n\t\t*/\n\t\tForce_CD_Available(-1);\n\n\t\t/*\n\t\t** If there are no search drives specified then we must be playing\n\t\t** off cd, so read files from there.\n\t\t*/\n\t\tint error;\n\n\t\tdo {\n\t\t\terror = CCFileClass::Set_Search_Drives(\"?:\\\\\");\n\t\t\tswitch (error) {\n\t\t\t\tcase 1:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tWWMessageBox().Process(TXT_CD_ERROR1, TXT_OK);\n\t\t\t\t\tProg_End(\"Init_CDROM_Access - CD_ERROR1\", true);\n\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\n\t\t\t\tcase 2:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tGamePalette.Set();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (WWMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {\n\t\t\t\t\t\tProg_End(\"Init_CDROM_Access - CD_ERROR2\", true);\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tif (!Force_CD_Available(RequiredCD)) {\n\t\t\t\t\t\tProg_End(\"Init_CDROM_Access - Force_CD_Available failed\", true);\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (error);\n\n\t\tRequiredCD = -1;\n\t} else {\n\n\t\t/*\n\t\t** If there are search drives specified then all files are to be\n\t\t** considered local.\n\t\t*/\n\t\tRequiredCD = -2;\n\t}\n}\n\n\n/***********************************************************************************************\n * Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping.      *\n *                                                                                             *\n *    This routine will register the initial mixfiles that are required to display error       *\n *    messages and get input from the player.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine before any dialogs would be displayed to the       *\n *             player.                                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bootstrap_Mixfiles(void)\n{\n\tint temp = RequiredCD;\n\tRequiredCD = -2;\n\n#ifdef WOLAPI_INTEGRATION\n\tCCFileClass fileWolapiMix( \"WOLAPI.MIX\" );\n\tif( fileWolapiMix.Is_Available() )\n\t{\n\t\tnew MFCD( \"WOLAPI.MIX\", &FastKey );\n\t\tMFCD::Cache( \"WOLAPI.MIX\" );\n\t}\n#endif\n\n#ifdef FIXIT_CSII\t//\tOk. ajw\n\tCCFileClass file2(\"EXPAND2.MIX\");\n\tif (file2.Is_Available()) {\n\t\tnew MFCD(\"EXPAND2.MIX\", &FastKey);\n\t\tbool ok = MFCD::Cache(\"EXPAND2.MIX\");\n\t\tassert(ok);\n\t}\n#endif\n\n#ifdef FIXIT_CSII\t//\tOk. ajw\n\tbool ok1;\n #if 0\n\tnew MFCD(\"HIRES1.MIX\", &FastKey);\n\tok1 = MFCD::Cache(\"HIRES1.MIX\");\n\tassert(ok1);\n #else\n\tnew MFCD(\"LORES1.MIX\", &FastKey);\n\tok1 = MFCD::Cache(\"LORES1.MIX\");\n\tassert(ok1);\n #endif\n#endif\n\n#ifdef FIXIT_ANTS\t//\tOk. ajw\n\tCCFileClass file(\"EXPAND.MIX\");\n\tif (file.Is_Available()) {\n\t\tnew MFCD(\"EXPAND.MIX\", &FastKey);\n\t\tbool ok = MFCD::Cache(\"EXPAND.MIX\");\n\t\tassert(ok);\n\t}\n#endif\n\n\tnew MFCD(\"REDALERT.MIX\", &FastKey);\n\n\t/*\n\t**\tBootstrap enough of the system so that the error dialog box can successfully\n\t**\tbe displayed.\n\t*/\n\tnew MFCD(\"LOCAL.MIX\", &FastKey);\t\t\t// Cached.\n\tbool ok = MFCD::Cache(\"LOCAL.MIX\");\n\tassert(ok);\n\n#if 0\n\tnew MFCD(\"HIRES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"HIRES.MIX\");\n\tassert(ok);\n\n\tnew MFCD(\"NCHIRES.MIX\", &FastKey);\t\t//Non-cached hires stuff incl VQ palettes\n#else\n\tnew MFCD(\"LORES.MIX\", &FastKey);\n\tok = MFCD::Cache(\"LORES.MIX\");\n\tassert(ok);\n#endif\t//WIN32\n\n\tRequiredCD = temp;\n}\n\n\n/***********************************************************************************************\n * Init_Secondary_Mixfiles -- Register and cache secondary mixfiles.                           *\n *                                                                                             *\n *    This routine is used to register the mixfiles that are needed for main menu processing.  *\n *    Call this routine before the main menu is display and processed.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n//#define DENZIL_MIXEXTRACT\n#ifdef DENZIL_MIXEXTRACT\nvoid Extract(char* filename, char* outfile);\n#endif\n \nstatic void Init_Secondary_Mixfiles(void)\n{\n\tMainMix = new MFCD(\"MAIN.MIX\", &FastKey);\n\tassert(MainMix != NULL);\n\n\t//Denzil extract mixfile\n\t#ifdef DENZIL_MIXEXTRACT\n\t#if(0)\n\tExtract(\"CONQUER.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\conquer.mix\");\n\tExtract(\"EDHI.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edhi.mix\");\n\tExtract(\"EDLO.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edlo.mix\");\n\tExtract(\"GENERAL.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\general.mix\");\n\tExtract(\"INTERIOR.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\interior.mix\");\n\tExtract(\"MOVIES1.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\movies1.mix\");\n\tExtract(\"SCORES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\scores.mix\");\n\tExtract(\"SNOW.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\snow.mix\");\n\tExtract(\"SOUNDS.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\sounds.mix\");\n\tExtract(\"RUSSIAN.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\russian.mix\");\n\tExtract(\"ALLIES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\allies.mix\");\n\tExtract(\"TEMPERAT.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\temperat.mix\");\n\t#else\n\tExtract(\"CONQUER.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\conquer.mix\");\n\tExtract(\"EDHI.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edhi.mix\");\n\tExtract(\"EDLO.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\edlo.mix\");\n\tExtract(\"GENERAL.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\general.mix\");\n\tExtract(\"INTERIOR.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\interior.mix\");\n\tExtract(\"MOVIES2.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\movies2.mix\");\n\tExtract(\"SCORES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\scores.mix\");\n\tExtract(\"SNOW.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\snow.mix\");\n\tExtract(\"SOUNDS.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\sounds.mix\");\n\tExtract(\"RUSSIAN.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\russian.mix\");\n\tExtract(\"ALLIES.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\allies.mix\");\n\tExtract(\"TEMPERAT.MIX\", \"o:\\\\projects\\\\radvd\\\\data\\\\extract\\\\temperat.mix\");\n\t#endif\n\t#endif\n\t\n\t/*\n\t**\tInform the file system of the various MIX files.\n\t*/\n\tConquerMix = new MFCD(\"CONQUER.MIX\", &FastKey);\t\t\t// Cached.\n//\tnew MFCD(\"TRANSIT.MIX\", &FastKey);\n\n\tif (GeneralMix == NULL) GeneralMix = new MFCD(\"GENERAL.MIX\", &FastKey);\t\t\t// Never cached.\n\n\tif (CCFileClass(\"MOVIES1.MIX\").Is_Available()) {\n\t\tMoviesMix = new MFCD(\"MOVIES1.MIX\", &FastKey);\t\t\t// Never cached.\n\t} else {\n\t\tMoviesMix = new MFCD(\"MOVIES2.MIX\", &FastKey);\t\t\t// Never cached.\n\t}\n\tassert(MoviesMix != NULL);\n\n\t/*\n\t**\tRegister the score mixfile.\n\t*/\n\tScoresPresent = true;\n\tScoreMix = new MFCD(\"SCORES.MIX\", &FastKey);\n\tThemeClass::Scan();\n\n\t/*\n\t**\tThese are sound card specific, but the install program would have\n\t**\tcopied the correct versions to the hard drive.\n\t*/\n\tnew MFCD(\"SPEECH.MIX\", &FastKey);\t\t\t// Never cached.\n\tnew MFCD(\"SOUNDS.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"RUSSIAN.MIX\", &FastKey);\t\t\t// Cached.\n\tnew MFCD(\"ALLIES.MIX\", &FastKey);\t\t\t// Cached.\n}\n\n\n/***********************************************************************************************\n * Bootstrap -- Perform the initial bootstrap procedure.                                       *\n *                                                                                             *\n *    This routine will load and initialize the game engine such that a dialog box could be    *\n *    displayed. Because this is very critical, call this routine before any other game        *\n *    initialization code.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Bootstrap(void)\n{\n\tBlackPalette.Set();\n\n\t/*\n\t**\tBe sure to short circuit the CD-ROM check if there is a CD-ROM override\n\t**\tpath.\n\t*/\n\tif (CCFileClass::Is_There_Search_Drives()) {\n\t\tRequiredCD = -2;\n\t}\n\n\t/*\n\t** Process the message loop until we are in focus. We need to be in focus to read pixels from\n\t** the screen.\n\t*/\n#if (0) //PG\n\t#ifdef WIN32\n\tdo {\n\t\tKeyboard->Check();\n\t} while (!GameInFocus);\n\tAllSurfaces.SurfacesRestored = false;\n\t#endif\n\n\t/*\n\t**\tPerform any special debug-only processing. This includes preparing the\n\t**\tmonochrome screen.\n\t*/\n\tMono_Clear_Screen();\n#endif\n\t/*\n\t**\tRegister and make resident all local mixfiles with particular emphasis\n\t**\ton the mixfiles that are necessary to display and error messages and\n\t**\tprocess further initialization.\n\t*/\n\tInit_Bootstrap_Mixfiles();\n\n\t/*\n\t**\tInitialize the resident font pointers.\n\t*/\n\tInit_Fonts();\n\n#ifndef WIN32\n\t/*\n\t**\tInstall the hard error handler.\n\t*/\n\t_harderr(harderr_handler);\t\t// BG: Install hard error handler\n\n\t/*\n\t** Install a Page Fault handler\n\t*/\n\tif (UsePageFaultHandler) {\n\t\tInstall_Page_Fault_Handle();\n\t}\n#endif\n\n\t/*\n\t**\tSetup the keyboard processor in preparation for the game.\n\t*/\n\t#ifdef WIN32\n\t\tKeyboard->Clear();\n\t#else\n\t\tKeyboard_Attributes_Off(BREAKON | SCROLLLOCKON | TRACKEXT | PAUSEON | CTRLSON | CTRLCON | FILTERONLY | TASKSWITCHABLE);\n\t\tKeyboard_Attributes_On(PASSBREAKS);\n\t\tKeyboard->Clear();\n\t#endif\n\n\t/*\n\t**\tThis is the shape staging buffer. It must always be available, so it is\n\t**\tallocated here and never freed. The library sets the globals ShapeBuffer\n\t**\tand ShapeBufferSize to these values, so it can be accessed for other\n\t**\tpurposes.\n\t*/\n\tSet_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);\n\n\t/*\n\t**\tFetch the language text from the hard drive first. If it cannot be\n\t**\tfound on the hard drive, then look for it in the mixfile.\n\t*/\n#ifdef STEVES_LOAD_OVERRIDE\n\tRawFileClass strings (\"CONQUER.ENG\");\n\tif (strings.Is_Available()){\n\t\tSystemStrings = new char [strings.Size()];\n\t\tstrings.Read((void*)SystemStrings, strings.Size());\n\t}else{\n\t\tSystemStrings = (char const *)MFCD::Retrieve(Language_Name(\"CONQUER\"));\n\t}\n#else\n\tSystemStrings = (char const *)MFCD::Retrieve(Language_Name(\"CONQUER\"));\n#endif\n\tDebugStrings = (char const *)MFCD::Retrieve(\"DEBUG.ENG\");\n\n\t/*\n\t**\tDefault palette initialization.\n\t*/\n\t// PG_TO_FIX. This doesn't seem right. ST - 5/9/2019\n\t//memmove((unsigned char *)&GamePalette[0], (void *)MFCD::Retrieve(\"TEMPERAT.PAL\"), 768L);\n\t//WhitePalette[0] = BlackPalette[0];\n//\tGamePalette.Set();\n\n\t/*\n\t**\tInitialize expansion files (if present). Expansion files must be located\n\t**\tin the current directory.\n\t*/\n\tInit_Expansion_Files();\n\n\tSidebarScheme.Background \t= BLACK;\n\tSidebarScheme.Corners    \t= LTGREY;\n\tSidebarScheme.Shadow\t\t \t= DKGREY;\n\tSidebarScheme.Highlight  \t= WHITE;\n\tSidebarScheme.Color\t\t \t= LTGREY;\n\tSidebarScheme.Bright\t\t \t= WHITE;\n\tSidebarScheme.BrightColor\t= WHITE;\n\tSidebarScheme.Box\t\t \t \t= LTGREY;\n\tGadgetClass::Set_Color_Scheme(&SidebarScheme);\n}\n\n\n/***********************************************************************************************\n * Init_Mouse -- Initialize the mouse system.                                                  *\n *                                                                                             *\n *    This routine will ensure that a valid mouse driver is present and a working mouse        *\n *    pointer can be displayed. The mouse is hidden when this routine exits.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Mouse(void)\n{\n\t/*\n\t** Since there is no mouse shape currently available we need\n\t** to set one of our own.\n\t*/\n#ifdef WIN32\n\tShowCursor(false);\n#endif\n\tif (MouseInstalled) {\n\t\tvoid const * temp_mouse_shapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t\tif (temp_mouse_shapes) {\n\t\t\tSet_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes, 0));\n\t\t\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\t\t}\n\t} else {\n\t\tchar buffer[255];\n\t\tGamePalette.Set();\n\t\tGamePalette.Set();\n\t\tsprintf(buffer, TEXT_NO_MOUSE);\n\t\tVisiblePage.Clear();\n\t\tWWMessageBox().Process(buffer, TXT_OK);\n\t\tProg_End(\"Init_Mouse\", true);\n\t\tEmergency_Exit(1);\n\t}\n\n\tMap.Set_Default_Mouse(MOUSE_NORMAL, false);\n\tShow_Mouse();\n\twhile (Get_Mouse_State() > 1) Show_Mouse();\n\tCall_Back();\n\tHide_Mouse();\n}\n\n\n#ifdef OBSOLETE\n/***********************************************************************************************\n * Init_Authorization -- Verifies that the player is authorized to play the game.              *\n *                                                                                             *\n *    This is a development routine that restricts access to the game by way of passwords.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Authorization(void)\n{\n\tif (Special.IsFromInstall) return;\n\n\tLoad_Title_Page();\n#ifdef WIN32\n\tWait_Vert_Blank();\n#else\t//WIN32\n\tInit_Delay();\n\tWait_Vert_Blank(VertBlank);\n#endif\t//WIN32\n\n\tCCPalette.Set();\n//\t\tSet_Palette(Palette);\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\n\t/*\n\t**\tFetch the type of game to be played. This will be either\n\t**\tC&C:Red Alert or C&C:Plus.\n\t*/\n//tryagain:\n\n\tbool ok = Debug_Flag;\n\tint counter = 3;\n\n\tif (Debug_Flag) ok = true;\n\n\t/*\n\t**\tC&C:Red Alert requires a password for legal entry. Try (three times) to get a correct\n\t**\tpassword. If not found, then try again.\n\t*/\n\tbool skipper = false;\n#ifdef NEVER\n\twhile (!ok && counter) {\n\t\tSmartPtr<char const> str = Fetch_Password(TXT_PASSWORD_CAPTION, TXT_PASSWORD_MESSAGE, TXT_OK);\n\t\tSmartPtr<long const> lptr = &CheatCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &EditorCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlptr = &PlayCodes[0];\n\t\twhile (*lptr) {\n\t\t\tif (Obfuscate(str) == *lptr++) {\n\t\t\t\tok = true;\n\t\t\t\tskipper = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ok) break;\n\n\t\tHide_Mouse();\n\t\tLoad_Title_Page();\n\t\tHidPage.Blit(SeenPage);\n\t\tShow_Mouse();\n\t\tDelay(TIMER_SECOND*(4-counter)*1);\n\t\tif (WWMessageBox().Process(TXT_PASSWORD_ERROR, TXT_TRY_AGAIN, TXT_CANCEL)) {\n\t\t\tgoto tryagain;\n\t\t}\n\n\t\tcounter--;\n\t\tif (counter == 0) goto tryagain;\n\t}\n#endif\n\n\tif (!skipper) {\n\t\tCCPalette.Set();\n\t}\n\n\tHide_Mouse();\n\tLoad_Title_Page();\n\tHidPage.Blit(SeenPage);\n\tShow_Mouse();\n\tCall_Back();\n}\n#endif\n\n\n/***********************************************************************************************\n * Init_Bulk_Data -- Initialize the time-consuming mixfile caching.                            *\n *                                                                                             *\n *    This routine is called to handle the time consuming process of game initialization.      *\n *    The title page will be displayed when this routine is called.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will take a very long time.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Bulk_Data(void)\n{\n\t/*\n\t**\tCache the main game data. This operation can take a very long time.\n\t*/\n\tMFCD::Cache(\"CONQUER.MIX\");\n\tif (SampleType != 0 && !Debug_Quiet) {\n\t\tMFCD::Cache(\"SOUNDS.MIX\");\n\t\tMFCD::Cache(\"RUSSIAN.MIX\");\n\t\tMFCD::Cache(\"ALLIES.MIX\");\n\t}\n\tCall_Back();\n\n\t/*\n\t**\tFetch the tutorial message data.\n\t*/\n\tINIClass ini;\n\tini.Load(CCFileClass(\"TUTORIAL.INI\"));\n\tfor (int index = 0; index < ARRAY_SIZE(TutorialText); index++) {\n\t\tTutorialText[index] = NULL;\n\n\t\tchar buffer[128];\n\t\tchar num[10];\n\t\tsprintf(num, \"%d\", index);\n\t\tif (ini.Get_String(\"Tutorial\", num, \"\", buffer, sizeof(buffer))) {\n\t\t\tTutorialText[index] = strdup(buffer);\n\t\t}\n\t}\n\n\t/*\n\t**\tPerform one-time game system initializations.\n\t*/\n\tInit_One_Time_Systems();\n}\n\n\n/***********************************************************************************************\n * Init_Keys -- Initialize the cryptographic keys.                                             *\n *                                                                                             *\n *    This routine will initialize the fast cryptographic key. It will also initialize the     *\n *    slow one if this is a scenario editor version of the game.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Init_Keys(void)\n{\n\tRAMFileClass file((void*)Keys, strlen(Keys));\n\tINIClass ini;\n\tini.Load(file);\n\n\tFastKey = ini.Get_PKey(true);\n#ifdef SCENARIO_EDITOR\n\tSlowKey = ini.Get_PKey(false);\n#endif\n}\n\n\n/***************************************************************************\n * Save_Recording_Values -- Saves multiplayer-specific values              *\n *                                                                         *\n * This routine saves multiplayer values that need to be restored for a\t\t*\n * save game.  In addition to saving the random # seed for this scenario, \t*\n * it saves the contents of the actual random number generator; this \t\t*\n * ensures that the random # sequencer will pick up where it left off when\t*\n * the game was saved.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine also saves the header for a Recording file, so it must \t\t*\n * save some data not needed specifically by a save-game file (ie Seed).\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Save_Recording_Values(CCFileClass & file)\n{\n\tSession.Save(file);\n\tfile.Write(&BuildLevel, sizeof(BuildLevel));\n\tfile.Write(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Write(&Seed, sizeof(Seed));\n\tfile.Write(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Write(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Write(&Whom, sizeof(Whom));\n\tfile.Write(&Special, sizeof(SpecialClass));\n\tfile.Write(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***************************************************************************\n * Load_Recording_Values -- Loads multiplayer-specific values              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Load_Recording_Values(CCFileClass & file)\n{\n\tSession.Load(file);\n\tfile.Read(&BuildLevel, sizeof(BuildLevel));\n\tfile.Read(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Read(&Seed, sizeof(Seed));\n\tfile.Read(&Scen.Scenario, sizeof(Scen.Scenario));\n\tfile.Read(Scen.ScenarioName, sizeof(Scen.ScenarioName));\n\tfile.Read(&Whom, sizeof(Whom));\n\tfile.Read(&Special, sizeof(SpecialClass));\n\tfile.Read(&Options, sizeof(GameOptionsClass));\n\treturn (true);\n}\n\nextern \"C\" {\nvoid __PRO(void) {\n//\tprintf(\"_pro\\n\");\n}\n}\n\n#ifdef DENZIL_MIXEXTRACT\nvoid Extract(char* filename, char* outname)\n\t{\n\tCCFileClass inFile(filename);\n\tCCFileClass outFile(outname);\n\n\tinFile.Open();\n\toutFile.Open(WRITE);\n\t\n\tvoid* buffer = malloc(32768);\n\n\tif (buffer)\n\t\t{\n\t\tunsigned long size = inFile.Size();\n\t\tunsigned long bytes;\n\n\t\twhile (size > 0)\n\t\t\t{\n\t\t\tbytes = inFile.Read(buffer, 32768);\n\t\t\toutFile.Write(buffer, bytes);\n\t\t\tsize -= bytes;\n\t\t\t}\n\t\t\n\t\tfree(buffer);\n\t\t}\n\t}\n#endif\n\n\n#ifdef FIXIT_VERSION_3\n\nbool bUsingDVD = false;\n\nconst char* Game_Registry_Key();\n\n//***********************************************************************************************\nbool Is_DVD_Installed()\n{\n\tbool bInstalled;\n\tHKEY hKey;\n\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )\n\t\treturn false;\n\tDWORD dwValue;\n\tDWORD dwBufSize = sizeof( DWORD );\n\tif( RegQueryValueEx( hKey, \"DVD\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )\n\t\tbInstalled = false;\n\telse\n\t\tbInstalled = (bool)dwValue;\t\t\t//\t(Presumably true, if it's there...)\n\n\tRegCloseKey( hKey );\n\n\treturn bInstalled;\n}\n\n//***********************************************************************************************\nbool Determine_If_Using_DVD()\n{\n\t//\tDetermines if the user has a DVD currently available. If they do, we'll use it throughout the\n\t//\tsession. Else we won't check for it again and will always ask for CDs.\n\tif( Is_DVD_Installed() )\n\t{\n\t\tif( Force_CD_Available( 5 ) )\n\t\t{\n\t\t\tbUsingDVD = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tUser hit cancel. Allow things to progress normally. They will be prompted for\n\t\t\t//\ta Red Alert disk as usual.\n\t\t\tbUsingDVD = false;\n\t\t}\n\t}\n\telse\n\t\tbUsingDVD = false;\n\t\n\treturn bUsingDVD;\n}\n\n//***********************************************************************************************\nbool Using_DVD()\n{\n\treturn bUsingDVD;\n}\n\n#endif\n\n\n\n\n/***********************************************************************************************\n * Free_Heaps -- Clear out the heaps before exit                                               *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/18/2019 11:59AM ST : Created.                                                                 *\n *=============================================================================================*/\nvoid Free_Heaps(void)\n{\n\tHouseTypes.Clear();\n\tBuildingTypes.Clear();\n\tAircraftTypes.Clear();\n\tInfantryTypes.Clear();\n\tBulletTypes.Clear();\n\tAnimTypes.Clear();\n\tUnitTypes.Clear();\n\tVesselTypes.Clear();\n\tTemplateTypes.Clear();\n\tTerrainTypes.Clear();\n\tOverlayTypes.Clear();\n\tSmudgeTypes.Clear();\n#if (0)\n\tHouseTypeClass::Init_Heap();\n\tBuildingTypeClass::Init_Heap();\n\tAircraftTypeClass::Init_Heap();\n\tInfantryTypeClass::Init_Heap();\n\tBulletTypeClass::Init_Heap();\n\tAnimTypeClass::Init_Heap();\n\tUnitTypeClass::Init_Heap();\n\tVesselTypeClass::Init_Heap();\n\tTemplateTypeClass::Init_Heap();\n\tTerrainTypeClass::Init_Heap();\n\tOverlayTypeClass::Init_Heap();\n\tSmudgeTypeClass::Init_Heap();\n\n\t\t// Heap init moved here from globals.cpp. ST - 5/20/2019\n\tCCPtr<AircraftClass>::Set_Heap(&Aircraft);\n\tCCPtr<AnimClass>::Set_Heap(&Anims);\n\tCCPtr<BuildingClass>::Set_Heap(&Buildings);\n\tCCPtr<BulletClass>::Set_Heap(&Bullets);\n\tCCPtr<FactoryClass>::Set_Heap(&Factories);\n\tCCPtr<HouseClass>::Set_Heap(&Houses);\n\tCCPtr<InfantryClass>::Set_Heap(&Infantry);\n\tCCPtr<OverlayClass>::Set_Heap(&Overlays);\n\tCCPtr<SmudgeClass>::Set_Heap(&Smudges);\n\tCCPtr<TeamClass>::Set_Heap(&Teams);\n\tCCPtr<TeamTypeClass>::Set_Heap(&TeamTypes);\n\tCCPtr<TemplateClass>::Set_Heap(&Templates);\n\tCCPtr<TerrainClass>::Set_Heap(&Terrains);\n\tCCPtr<TriggerClass>::Set_Heap(&Triggers);\n\tCCPtr<TriggerTypeClass>::Set_Heap(&TriggerTypes);\n\n\tCCPtr<HouseTypeClass>::Set_Heap(&HouseTypes);\n\tCCPtr<BuildingTypeClass>::Set_Heap(&BuildingTypes);\n\tCCPtr<AircraftTypeClass>::Set_Heap(&AircraftTypes);\n\tCCPtr<InfantryTypeClass>::Set_Heap(&InfantryTypes);\n\tCCPtr<BulletTypeClass>::Set_Heap(&BulletTypes);\n\tCCPtr<AnimTypeClass>::Set_Heap(&AnimTypes);\n\tCCPtr<UnitTypeClass>::Set_Heap(&UnitTypes);\n\tCCPtr<VesselTypeClass>::Set_Heap(&VesselTypes);\n\tCCPtr<TemplateTypeClass>::Set_Heap(&TemplateTypes);\n\tCCPtr<TerrainTypeClass>::Set_Heap(&TerrainTypes);\n\tCCPtr<OverlayTypeClass>::Set_Heap(&OverlayTypes);\n\tCCPtr<SmudgeTypeClass>::Set_Heap(&SmudgeTypes);\n#endif\n\n\tVessels.Clear();\n\tUnits.Clear();\n\tFactories.Clear();\n\tTerrains.Clear();\n\tTemplates.Clear();\n\tSmudges.Clear();\n\tOverlays.Clear();\n\tInfantry.Clear();\n\tBullets.Clear();\n\tBuildings.Clear();\n\tAnims.Clear();\n\tAircraft.Clear();\n\tTriggers.Clear();\n\tTeamTypes.Clear();\n\tTeams.Clear();\n\tHouses.Clear();\n\tTriggerTypes.Clear();\n\n\t/*\n\t**\tSpeech holding tank buffer. Since speech does not mix, it can be placed\n\t**\tinto a custom holding tank only as large as the largest speech file to\n\t**\tbe played.\n\t*/\n\tfor (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {\n\t\tif (SpeechBuffer[index]) {\n\t\t\tdelete [] SpeechBuffer[index];\n\t\t\tSpeechBuffer[index] = NULL;\n\t\t}\n\t}\n\n\t/*\n\t**\tAllocate the theater buffer block.\n\t*/\n\tif (TheaterBuffer) {\n\t\tdelete TheaterBuffer;\n\t\tTheaterBuffer = NULL;\n\t}\n}"
  },
  {
    "path": "REDALERT/INLINE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INLINE.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INLINE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/21/96                                                     *\n *                                                                                             *\n *                  Last Update : September 30, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                  *\n *   Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                  *\n *   Cell_Coord -- Convert a cell to a coordinate value.                                       *\n *   Cell_To_Lepton -- Convert a cell distance into a lepton distance.                         *\n *   Cell_X -- Fetch the X cell component from the cell value.                                 *\n *   Cell_Y -- Fetch the Y cell component from the cell value specified.                       *\n *   Coord_Add -- Adds coordinates together.                                                   *\n *   Coord_Fraction -- Discards all but the sub-cell components of the coordinate.             *\n *   Coord_Mid -- Finds the midpoint between two coordinates.                                  *\n *   Coord_Snap -- Coerce coordinate to refer to center of a cell.                             *\n *   Coord_Sub -- Subtracts one coordinate from another.                                       *\n *   Coord_Whole -- Discards the sub-cell components of the coordinate.                        *\n *   Coord_X -- Fetches the X lepton component from a coordinate value.                        *\n *   Coord_XCell -- Fetch the X cell component from a coordinate value.                        *\n *   Coord_XLepton -- Fetch the X sub-cell lepton component from the coordinate.               *\n *   Coord_Y -- Fetch the Y lepton component from the coordinate value.                        *\n *   Coord_YCell -- Fetch the Y cell component from a coordinate.                              *\n *   Coord_YLepton -- Fetches the Y lepton sub-cell component from the coordinate.             *\n *   Dir_Facing -- Convert a DirType into a FacingType value.                                  *\n *   Dir_To_16 -- Convert a facing to a 0..15 value.                                           *\n *   Dir_To_32 -- Convert a DirType into a 0..31 value.                                        *\n *   Dir_To_8 -- Convert a DirType into a value from 0 to 7.                                   *\n *   Direction -- Calculates the DirType from one cell to another.                             *\n *   Direction -- Determines the facing value from one coordinate to another.                  *\n *   Direction256 -- Calculate the facing value from one coordinate to another.                *\n *   Direction8 -- Fetches the direction from one coordinate to another.                       *\n *   Distance -- Finds the distance between two arbitrary points.                              *\n *   Facing_Dir -- Convert a FacingType into a DirType.                                        *\n *   Lepton_To_Cell -- Convert lepton distance to cell distance.                               *\n *   Lepton_To_Pixel -- Convert a lepton value into pixel value.                               *\n *   Percent_Chance -- Calculate a percentage chance event.                                    *\n *   Pixel_To_Lepton -- Convert pixel value into lepton equivalent.                            *\n *   Random_Pick -- Pick a random number in a specified range.                                 *\n *   Sim_Percent_Chance -- Calculates a percentage chance event for local events.              *\n *   Sim_Random_Pick -- Picks a random number that will not affect the game.                   *\n *   Text_String -- Convert a text number into a text pointer.                                 *\n *   XYP_COORD -- Convert pixel components into a coordinate value.                            *\n *   XYP_Coord -- Combine pixel values into a coordinate.                                      *\n *   XY_Cell -- Create a cell from X and Y cell components.                                    *\n *   XY_Coord -- Convert X Y lepton components into a COORD.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INLINE_H\n#define INLINE_H\n\n\n/***********************************************************************************************\n * Lepton_To_Pixel -- Convert a lepton value into pixel value.                                 *\n *                                                                                             *\n *    Use this routine to convert the specified lepton value into it's pixel corresponding     *\n *    value. The pixel value returned will be the closest pixel value to the lepton value. It  *\n *    will round up or down as necessary.                                                      *\n *                                                                                             *\n * INPUT:   lepton   -- The lepton value to convert into a pixel value.                        *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton value rounded to the nearest pixel component.              *\n *                                                                                             *\n * WARNINGS:   Precision is not maintained by this routine. Thus, if a value is converted to   *\n *             pixel and then back to leptons, the value will probably not be the same.        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Lepton_To_Pixel(LEPTON lepton)\n{\n\treturn (((int)(signed short)lepton * ICON_PIXEL_W) + (ICON_LEPTON_W / 2) - ((lepton < 0) ? (ICON_LEPTON_W - 1) : 0)) / ICON_LEPTON_W;\n}\n\n\n/***********************************************************************************************\n * Pixel_To_Lepton -- Convert pixel value into lepton equivalent.                              *\n *                                                                                             *\n *    This routine will take the specified pixel value and convert it into lepton value.       *\n *                                                                                             *\n * INPUT:   pixel -- The pixel value to convert.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton equivalent of the pixel value specified.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Pixel_To_Lepton(int pixel)\n{\n\treturn (LEPTON)(((pixel * ICON_LEPTON_W) + (ICON_PIXEL_W / 2) - ((pixel < 0) ? (ICON_PIXEL_W - 1) : 0)) / ICON_PIXEL_W);\n}\n\n\n/***********************************************************************************************\n * XY_Coord -- Convert X Y lepton components into a COORD.                                     *\n *                                                                                             *\n *    This routine will take the specified X and Y lepton components and combine them into     *\n *    a coordinate value.                                                                      *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y lepton components to combine.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a coordinate value that is created from the X and Y lepton components.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XY_Coord(LEPTON x, LEPTON y)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = x;\n\tcoord.Sub.Y.Raw = y;\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * XYP_COORD -- Convert pixel components into a coordinate value.                              *\n *                                                                                             *\n *    This routine will take the specified pixel components and convert and combine them into  *\n *    a coordinate value.                                                                      *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel components to coerce into a coordinate value.           *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate value that matches the pixel values specified.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XYP_COORD(int x, int y)\n{\n\treturn(XY_Coord(Pixel_To_Lepton(x), Pixel_To_Lepton(y)));\n}\n\n\n/***********************************************************************************************\n * Coord_XCell -- Fetch the X cell component from a coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the X cell component from the coordinate value specified and   *\n *    return the value.                                                                        *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to extract the X component from.                     *\n *                                                                                             *\n * OUTPUT:  Returns with the X cell component of the coordinate value.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Coord_XCell(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * Coord_YCell -- Fetch the Y cell component from a coordinate.                                *\n *                                                                                             *\n *    This routine will extract the Y cell component from the coordinate value specified.      *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to extract the Y cell from.                                *\n *                                                                                             *\n * OUTPUT:  Returns with just the Y cell component of the coordinate value.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Coord_YCell(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * XY_Cell -- Create a cell from X and Y cell components.                                      *\n *                                                                                             *\n *    This routine will construct a cell value by taking the X and Y cell value components     *\n *    and combining them appropriately.                                                        *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y cell components to combine.                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the CELL value created from the specified components.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL XY_Cell(int x, int y)\n{\n\tCELL_COMPOSITE cell;\n\tcell.Cell = 0;\n\tcell.Sub.X = x;\n\tcell.Sub.Y = y;\n\treturn(cell.Cell);\n}\n\n\n/***********************************************************************************************\n * Cell_To_Lepton -- Convert a cell distance into a lepton distance.                           *\n *                                                                                             *\n *    This routine will take the cell distance specified and convert it into a lepton distance.*\n *                                                                                             *\n * INPUT:   cell_distance  -- The distance in cells to convert.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the lepton equivalent of the cell distance specified.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Cell_To_Lepton(int cell_distance)\n{\n\tLEPTON_COMPOSITE lepton;\n\tlepton.Sub.Cell = (unsigned char)cell_distance;\n\tlepton.Sub.Lepton = 0;\n\treturn(lepton.Raw);\n}\n\n\n/***********************************************************************************************\n * Lepton_To_Cell -- Convert lepton distance to cell distance.                                 *\n *                                                                                             *\n *    This routine will convert the specified lepton distance into the closest cell distance   *\n *    possible. This might require rounding up or down as necessary.                           *\n *                                                                                             *\n * INPUT:   lepton_distance   -- The lepton distance to convert.                               *\n *                                                                                             *\n * OUTPUT:  Returns with the cell distance that most closely corresponds to the lepton         *\n *          distance specified.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Lepton_To_Cell(LEPTON lepton_distance)\n{\n\tif (((LEPTON_COMPOSITE &)lepton_distance).Sub.Lepton >= (CELL_LEPTON_W/2)) {\n\t\treturn(((LEPTON_COMPOSITE &)lepton_distance).Sub.Cell + 1);\n\t}\n\treturn(((LEPTON_COMPOSITE &)lepton_distance).Sub.Cell);\n}\n\n\n/***********************************************************************************************\n * Coord_X -- Fetches the X lepton component from a coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the X lepton component from the coordinate.                    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to extract the X lepton equivalent from.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the X lepton portion of the coordinate value specified.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Coord_X(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Raw);\n}\n\n\n/***********************************************************************************************\n * Coord_Y -- Fetch the Y lepton component from the coordinate value.                          *\n *                                                                                             *\n *    This routine will extract the Y lepton component from the coordinate value specified.    *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to dissect.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the Y lepton component from the specified coordinate value.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline LEPTON Coord_Y(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Raw);\n}\n\n\n/***********************************************************************************************\n * Cell_X -- Fetch the X cell component from the cell value.                                   *\n *                                                                                             *\n *    This routine will extract the X cell component from the cell value specified.            *\n *                                                                                             *\n * INPUT:   cell  -- The cell to extract.                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the X cell component portion of the cell value specified.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Cell_X(CELL cell)\n{\n\treturn(((CELL_COMPOSITE &)cell).Sub.X);\n}\n\n\n/***********************************************************************************************\n * Cell_Y -- Fetch the Y cell component from the cell value specified.                         *\n *                                                                                             *\n *    This routine will extract the Y cell component from the cell value.                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell value to extract from.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the Y cell component of the cell value specified.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Cell_Y(CELL cell)\n{\n\treturn(((CELL_COMPOSITE &)cell).Sub.Y);\n}\n\n\n/***********************************************************************************************\n * Coord_XLepton -- Fetch the X sub-cell lepton component from the coordinate.                 *\n *                                                                                             *\n *    This routine will extract just the X sub cell lepton component from the coordinate       *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   coord -- The coordinate value to extract from.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the X lepton component of the coordinate that is part of the cell.    *\n *          Thus, a coordinate that exactly lines up on the left edge of a cell would return   *\n *          zero. One that exactly lines up on the right edge would return CELL_LEPTON_W.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Coord_XLepton(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton);\n}\n\n\n/***********************************************************************************************\n * Coord_YLepton -- Fetches the Y lepton sub-cell component from the coordinate.               *\n *                                                                                             *\n *    This routine will extract the sub-cell Y lepton portion of the coordinate.               *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to dissect.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with just the Y lepton portion of the coordinate and only for the sub-cell *\n *          it refers to.                                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Coord_YLepton(COORDINATE coord)\n{\n\treturn(((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton);\n}\n\n\n/***********************************************************************************************\n * XYP_Coord -- Combine pixel values into a coordinate.                                        *\n *                                                                                             *\n *    This will convert X and Y pixel values into a coordinate. Primarily this is used for     *\n *    converting mouse clicks into coordinate values.                                          *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y pixel coordinates to convert. Origin is upper left corner.    *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that most closely corresponds to the pixel values      *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   The coordinate is relative to the upper left corner (0,0). To conver the        *\n *             coordinate to a game relative one, it must be biased by the display coordinate  *\n *             of the tactical map and the screen position of the tactical display.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE XYP_Coord(int x, int y)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = Pixel_To_Lepton(x);\n\tcoord.Sub.Y.Raw = Pixel_To_Lepton(y);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Cell_Coord -- Convert a cell to a coordinate value.                                         *\n *                                                                                             *\n *    This routine will convert the specified cell into a coordinat value. The coordinate      *\n *    will refer to the center of the cell specified.                                          *\n *                                                                                             *\n * INPUT:   cell  -- The cell to convert into a coordinate.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that refers to the center of the cell specified.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Cell_Coord(CELL cell)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Sub.Cell = (unsigned char)(((CELL_COMPOSITE &)cell).Sub.X);\n\tcoord.Sub.X.Sub.Lepton = (unsigned char)(CELL_LEPTON_W / 2);\n\tcoord.Sub.Y.Sub.Cell = (unsigned char)(((CELL_COMPOSITE &)cell).Sub.Y);\n\tcoord.Sub.Y.Sub.Lepton = (unsigned char)(CELL_LEPTON_W / 2);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Snap -- Coerce coordinate to refer to center of a cell.                               *\n *                                                                                             *\n *    This routine will take the specified coordinate and force it to refer to the center of   *\n *    the cell.                                                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the specified coordinate after it has been modified to refer to the   *\n *          center of the cell.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Snap(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton = CELL_LEPTON_W/2;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton = CELL_LEPTON_W/2;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Fraction -- Discards all but the sub-cell components of the coordinate.               *\n *                                                                                             *\n *    Use this routine to discard the cell components of the coordinate, leaving only the      *\n *    sub-cell component.                                                                      *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with just the sub-cell components intact from the supplied coordinate.     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Fraction(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell = 0;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell = 0;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Whole -- Discards the sub-cell components of the coordinate.                          *\n *                                                                                             *\n *    This routine will discard the sub-cell components, leaving only the whole cell portion.  *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to modify.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with only the whole cell components of the coordinate intact. The          *\n *          resulting coordinate will refer to the upper left corner of the cell.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Whole(COORDINATE coord)\n{\n\t((COORD_COMPOSITE &)coord).Sub.X.Sub.Lepton = 0;\n\t((COORD_COMPOSITE &)coord).Sub.Y.Sub.Lepton = 0;\n\treturn(coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Add -- Adds coordinates together.                                                     *\n *                                                                                             *\n *    This routine will add one coordinate to another. Actually, it adds the X and Y components*\n *    separately (signed) and then recombines them back into a coordinate.                     *\n *                                                                                             *\n * INPUT:   coord1   -- One coordinate to add.                                                 *\n *                                                                                             *\n *          coord2   -- The other coordinate to add.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the logical add of the two coordinates.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Add(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.X.Raw + (int)(short)((COORD_COMPOSITE &)coord2).Sub.X.Raw);\n\tcoord.Sub.Y.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.Y.Raw + (int)(short)((COORD_COMPOSITE &)coord2).Sub.Y.Raw);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Sub -- Subtracts one coordinate from another.                                         *\n *                                                                                             *\n *    This routine will subtract one coordinate from the other. The coordinates are broken     *\n *    up into their X and Y components, the subtraction is performed, and then they are        *\n *    recombined back into a coordinate to be returned.                                        *\n *                                                                                             *\n * INPUT:   coord1   -- The coordinate to be subtracted from.                                  *\n *                                                                                             *\n *          coord2   -- The coordinate to subtract.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the result of subtracting coord2 from coord1.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Sub(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.X.Raw - (int)(short)((COORD_COMPOSITE &)coord2).Sub.X.Raw);\n\tcoord.Sub.Y.Raw = (LEPTON)((int)(short)((COORD_COMPOSITE &)coord1).Sub.Y.Raw - (int)(short)((COORD_COMPOSITE &)coord2).Sub.Y.Raw);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Coord_Mid -- Finds the midpoint between two coordinates.                                    *\n *                                                                                             *\n *    This will find the coordinate that is exactly between the two coordinates specified.     *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate.                                                  *\n *                                                                                             *\n *          coord2   -- The second coordinate.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the midpoint between the two coordinates.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Coord_Mid(COORDINATE coord1, COORDINATE coord2)\n{\n\tCOORD_COMPOSITE coord;\n\n\tcoord.Sub.X.Raw = (LEPTON)(((int)((COORD_COMPOSITE &)coord1).Sub.X.Raw + (int)((COORD_COMPOSITE &)coord2).Sub.X.Raw) / 2);\n\tcoord.Sub.Y.Raw = (LEPTON)(((int)((COORD_COMPOSITE &)coord1).Sub.Y.Raw + (int)((COORD_COMPOSITE &)coord2).Sub.Y.Raw) / 2);\n\treturn(coord.Coord);\n}\n\n\n/***********************************************************************************************\n * Dir_Facing -- Convert a DirType into a FacingType value.                                    *\n *                                                                                             *\n *    Use this routine to convert the specified DirType value into the closest FacingType      *\n *    value that matches it.                                                                   *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with a FacingType value that most closely matches the DirType specified.   *\n *                                                                                             *\n * WARNINGS:   Precision of direction is lost by this transformation.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline FacingType Dir_Facing(DirType facing)\n{\n\treturn (FacingType)(((unsigned char)((int)facing+0x10)&0xFF)>>5);\n}\n\n\n/***********************************************************************************************\n * Facing_Dir -- Convert a FacingType into a DirType.                                          *\n *                                                                                             *\n *    This will conver the specified FacingType value into the DirType that exactly matches    *\n *    it.                                                                                      *\n *                                                                                             *\n * INPUT:   facing   -- The FacingType to convert.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that exactly matches the facing.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Facing_Dir(FacingType facing)\n{\n\treturn (DirType)((int)facing << 5);\n}\n\n\n/***********************************************************************************************\n * Dir_To_16 -- Convert a facing to a 0..15 value.                                             *\n *                                                                                             *\n *    Use this routine to convert a DirType into a 0 through 15 value.                         *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert into a 0..15 value.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the facing converted into a value where 0 equals North, 4 equals      *\n *          East, 8 equals South, etc.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Dir_To_16(DirType facing)\n{\n\treturn Facing16[facing];\n}\n\n\n/***********************************************************************************************\n * Dir_To_32 -- Convert a DirType into a 0..31 value.                                          *\n *                                                                                             *\n *    This will convert the DirType specified, into a 0 through 31 value where zero is North,  *\n *    and rotates clockwise. The return value is baised to take into consideration the         *\n *    distortion caused by 3D studio upon the game vehicle objects.                            *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the facing converted into a value from zero to 31.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Dir_To_32(DirType facing)\n{\n\treturn Facing32[facing];\n}\n\n\n/***********************************************************************************************\n * Direction256 -- Calculate the facing value from one coordinate to another.                  *\n *                                                                                             *\n *    This will calculate the facing from the first coordinate to the second.                  *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate that facing will be calculated from.              *\n *                                                                                             *\n *          coord2   -- The second coordinate that facing will be calcuated to.                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that is the facing from coord1 to coord2.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction256(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing256(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction -- Determines the facing value from one coordinate to another.                    *\n *                                                                                             *\n *    This will determine the DirType from the first coordinate to the second.                 *\n *                                                                                             *\n * INPUT:   coord1   -- The first coordinate that facing will be calculated from.              *\n *                                                                                             *\n *          coord2   -- The second coordinate to calculate facing to.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType that represents the facing from coordinate 1 to coordinate*\n *          2.                                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing256(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction8 -- Fetches the direction from one coordinate to another.                         *\n *                                                                                             *\n *    This will calculate the facing from the first coordinate to the second. The return value *\n *    is of limited accuracy, but the calculation is fast.                                     *\n *                                                                                             *\n * INPUT:   coord1   -- The coordinate to calculate the facing from.                           *\n *                                                                                             *\n *          coord2   -- The coordinate to figure the facing to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType to get from coordinate 1 to coordinate 2.                 *\n *                                                                                             *\n * WARNINGS:   The return DirType is only accurate to the 8 primary compass rose directions.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction8(COORDINATE coord1, COORDINATE coord2)\n{\n\treturn (Desired_Facing8(Coord_X(coord1), Coord_Y(coord1), Coord_X(coord2), Coord_Y(coord2)));\n}\n\n\n/***********************************************************************************************\n * Direction -- Calculates the DirType from one cell to another.                               *\n *                                                                                             *\n *    This routine will calculate the facing to get from one cell to another. Since dealing    *\n *    with cells is much less precise than with coordinates, the return value is only          *\n *    accurate to 8 facings.                                                                   *\n *                                                                                             *\n * INPUT:   cell1 -- The cell to calculate the DirType from.                                   *\n *                                                                                             *\n *          cell2 -- The cell to calculate the DirType to.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType to get from the first cell to the second.                 *\n *                                                                                             *\n * WARNINGS:   The return value is only accurate to the 8 primary compass rose directions.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline DirType Direction(CELL cell1, CELL cell2)\n{\n\treturn (Desired_Facing8(Cell_X(cell1), Cell_Y(cell1), Cell_X(cell2), Cell_Y(cell2)));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This will coerce the coordinate specified so that it will refer to the immediately       *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to calculate the adjacency from.                           *\n *                                                                                             *\n *          dir   -- The direction to travel to calculate the adjacent cell.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the refers to the adjacent cell in the direciton       *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Adjacent_Cell(COORDINATE coord, FacingType dir)\n{\n\treturn (Coord_Snap(Coord_Add(AdjacentCoord[(int)dir & 0x07], coord)));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This will coerce the coordinate specified so that it will refer to the immediately       *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to calculate the adjacency from.                           *\n *                                                                                             *\n *          dir   -- The direction to travel to calculate the adjacent cell.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate the refers to the adjacent cell in the direciton       *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline COORDINATE Adjacent_Cell(COORDINATE coord, DirType dir)\n{\n\treturn Adjacent_Cell(coord, Dir_Facing(dir));\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This routine will take the specified cell and coerce it to refer to the immediately      *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell to coerce into an adjacent cell.                                 *\n *                                                                                             *\n *          dir   -- The direction to determine the adjacent cell.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell value that represents the adjacent cell in the direction     *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Adjacent_Cell(CELL cell, FacingType dir)\n{\n\treturn (CELL)(cell + AdjacentCell[dir]);\n}\n\n\n/***********************************************************************************************\n * Adjacent_Cell -- Calculate the adjacent cell in the direction specified.                    *\n *                                                                                             *\n *    This routine will take the specified cell and coerce it to refer to the immediately      *\n *    adjacent cell in the direction specified.                                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell to coerce into an adjacent cell.                                 *\n *                                                                                             *\n *          dir   -- The direction to determine the adjacent cell.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the cell value that represents the adjacent cell in the direction     *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline CELL Adjacent_Cell(CELL cell, DirType dir)\n{\n\treturn (CELL)(cell + AdjacentCell[Dir_Facing(dir)]);\n}\n\n\n/***********************************************************************************************\n * Dir_To_8 -- Convert a DirType into a value from 0 to 7.                                     *\n *                                                                                             *\n *    This routine will convert a DirType value into a facing number from 0 to 7.              *\n *                                                                                             *\n * INPUT:   facing   -- The DirType to convert.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the DirType converted to a number from 0 to 7 with 0 being North and  *\n *          rotating clockwise.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline FacingType Dir_To_8(DirType facing)\n{\n\treturn (FacingType)(((unsigned char)((int)facing|0x10))>>5);\n}\n\n\n/***********************************************************************************************\n * Text_String -- Convert a text number into a text pointer.                                   *\n *                                                                                             *\n *    This routine will convert text numbers (as generated elsewhere) into an actual text      *\n *    pointer that can be used for normal purposes.                                            *\n *                                                                                             *\n * INPUT:   string   -- The text number to extract a pointer to.                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text that represents the text number specified.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * Text_String(int string)\n{\n#ifdef FIXIT_NAME_OVERRIDE\n\tif (string < 0 && abs(string) < ARRAY_SIZE(NameOverride)) {\n\t\treturn(NameOverride[-(string+1)]);\n\t}\n#endif\n\n\tif (string < 1000) return(Extract_String(SystemStrings, string));\n\treturn(Extract_String(DebugStrings, string-1000));\n}\n\n\n/***********************************************************************************************\n * Random_Pick -- Pick a random number in a specified range.                                   *\n *                                                                                             *\n *    This routine is used to pick a game influencing random number between (inclusive) the    *\n *    range specified.                                                                         *\n *                                                                                             *\n * INPUT:   a  -- Low limit of range to pick from.                                             *\n *                                                                                             *\n *          b  -- High limit of range to pick from.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with a random number picked between (inclusive) the range of values        *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T> inline T Random_Pick(T a, T b)\n{\n\treturn T(Scen.RandomNumber((int)a, (int)b));\n};\n\n\n/***********************************************************************************************\n * Percent_Chance -- Calculate a percentage chance event.                                      *\n *                                                                                             *\n *    This will calculate a percentage chance and return with 'true' as likely as the          *\n *    chance value would occur (or less) on a random pick from 1 to 100. Thus a                *\n *    Percent_Chance(50) would return 'true' 50 percent of the time. Percent_Chance(25) would  *\n *    return 'true' 25% of the time, etc.                                                      *\n *                                                                                             *\n * INPUT:   percent  -- The percent value to calculate the chance upon.                        *\n *                                                                                             *\n * OUTPUT:  Returns with 'true' in the same percentage as the percentage number supplied.      *\n *                                                                                             *\n * WARNINGS:   This affects the game syncronization random number generator and should be used *\n *             for those events that could affect the game engine.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline bool Percent_Chance(int percent)\n{\n\treturn (Scen.RandomNumber(0, 99) < percent);\n}\n\n\n/***********************************************************************************************\n * Sim_Random_Pick -- Picks a random number that will not affect the game.                     *\n *                                                                                             *\n *    Use this routine to pick a random number such that it will be used so that it won't      *\n *    actually affect the outcome of the game. It is critical to use this routine for any      *\n *    random need that won't be needed on other machines in a multiplayer game. The result     *\n *    can be freely used as long as it doesn't affect the outcome of the game.                 *\n *                                                                                             *\n * INPUT:   a  -- Low range of the random number to pick.                                      *\n *                                                                                             *\n *          b  -- High range of the random number to pick.                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a random number between (inclusive) the range limit values            *\n *          specified.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nextern RandomClass NonCriticalRandomNumber;\ntemplate<class T> inline T Sim_Random_Pick(T a, T b)\n{\n\treturn T(NonCriticalRandomNumber((int)a, (int)b));\n};\n\n\n/***********************************************************************************************\n * Sim_Percent_Chance -- Calculates a percentage chance event for local events.                *\n *                                                                                             *\n *    This routine is similar to the normal Percent_Chance() routine except that it doesn't    *\n *    alter the main random number gerenator sequence. As such, this routine should be used    *\n *    for those events that should have a random character, but will either not affect the     *\n *    game engine or are only calculated on one machine in a multiplayer game.                 *\n *                                                                                             *\n * INPUT:   percent  -- The percent chance to calculate the possible return of 'true' on.      *\n *                                                                                             *\n * OUTPUT:  Returns 'true' with the same percentage chance as the percent number specified.    *\n *          A percent value of 50 means 50%, 25 means 25%, etc.                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline bool Sim_Percent_Chance(int percent)\n{\n\treturn (NonCriticalRandomNumber(0, 99) < percent);\n}\n\n\n/***********************************************************************************************\n * Distance -- Finds the distance between two arbitrary points.                                *\n *                                                                                             *\n *    This finds the (Dragon Strike) distance between two arbitrary points in flat space.      *\n *    It does this by adding 1/2 the smaller absolute axis difference to the other absolute    *\n *    axis distance. The result is rough but quick to calculate.                               *\n *                                                                                             *\n * INPUT:   x1,y1 -- Coordinate location for point 1.                                          *\n *                                                                                             *\n *          x2,y2 -- Coordinate location for point 2.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the rough distance between the two points. The value returned is      *\n *          expressed in the same units as the parameters were specified in.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int Distance(int x1, int y1, int x2, int y2)\n{\n\tint diff1 = y1 - y2;\n\tif (diff1 < 0) diff1 = -diff1;\n\tint diff2 = x1 - x2;\n\tif (diff2 < 0) diff2 = -diff2;\n\tif (diff1 > diff2) {\n\t\treturn(diff1 + ((unsigned)diff2 / 2));\n\t}\n\treturn(diff2 + ((unsigned)diff1 / 2));\n}\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/INT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INT.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INT.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"mp.h\"\n#include \"int.h\"\n\nint bignum::Error = 0;\nbool bignum::Carry = false;\nbool bignum::Borrow = false;\nbignum bignum::Remainder;\n\n"
  },
  {
    "path": "REDALERT/INT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INT.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INT.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef INT_H\n#define INT_H\n\n#include <memory.h>\n#include\t<limits.h>\n#include\t<assert.h>\n#include\t\"mp.h\"\n#include\t\"straw.h\"\n\n//#pragma warn -inl\n\ntemplate<int PRECISION>\nclass Int {\n\tpublic:\n\n\t\t/*\n\t\t**\tConstructors and initializers.\n\t\t*/\n\t\tInt(void) {XMP_Init(&reg[0], 0, PRECISION);}\n\t\tInt(unsigned long value) {XMP_Init(&reg[0], value, PRECISION);}\n\n\t\tvoid Randomize(Straw & rng, int bitcount) {XMP_Randomize(&reg[0], rng, bitcount, PRECISION);}\n\t\tvoid Randomize(Straw & rng, const Int & minval, const Int & maxval) {XMP_Randomize(&reg[0], rng, minval, maxval, PRECISION); reg[0] |= 1;}\n\n\t\t/*\n\t\t**\tConvenient conversion operators to get at the underlying array of\n\t\t**\tintegers. Big number math is basically manipulation of arbitrary\n\t\t**\tlength arrays.\n\t\t*/\n\t\toperator digit * () {return & reg[0];}\n\t\toperator const digit * () const {return & reg[0];}\n\n\t\t/*\n\t\t**\tArray access operator (references bit position). Bit 0 is the first bit.\n\t\t*/\n\t\tbool operator[](unsigned bit) const {return(XMP_Test_Bit(&reg[0], bit));}\n\n\t\t/*\n\t\t**\tUnary operators.\n\t\t*/\n\t\tInt & operator ++ (void) {XMP_Inc(&reg[0], PRECISION);return(*this);}\n\t\tInt & operator -- (void) {XMP_Dec(&reg[0], PRECISION);return(*this);}\n\t\tint operator ! (void) const {return(XMP_Test_Eq_Int(&reg[0], 0, PRECISION));}\n\t\tInt operator ~ (void) {XMP_Not(&reg[0], PRECISION);return(*this);}\n\t\tInt operator - (void) const {Int a = *this;a.Negate();return (a);}\n\n\t\t/*\n\t\t**\tAttribute query functions.\n\t\t*/\n\t\tint ByteCount(void) const {return(XMP_Count_Bytes(&reg[0], PRECISION));}\n\t\tint BitCount(void) const {return(XMP_Count_Bits(&reg[0], PRECISION));}\n\t\tbool Is_Negative(void) const {return(XMP_Is_Negative(&reg[0], PRECISION));}\n\t\tunsigned MaxBitPrecision() const {return PRECISION*(sizeof(unsigned long)*CHAR_BIT);}\n\t\tbool IsSmallPrime(void) const {return(XMP_Is_Small_Prime(&reg[0], PRECISION));}\n\t\tbool SmallDivisorsTest(void) const {return(XMP_Small_Divisors_Test(&reg[0], PRECISION));}\n\t\tbool FermatTest(unsigned rounds) const {return(XMP_Fermat_Test(&reg[0], rounds, PRECISION));}\n\t\tbool IsPrime(void) const {return(XMP_Is_Prime(&reg[0], PRECISION));}\n\t\tbool RabinMillerTest(Straw & rng, unsigned int rounds) const {return(XMP_Rabin_Miller_Test(rng, &reg[0], rounds, PRECISION));}\n\n\t\t/*\n\t\t**\t'in-place' binary operators.\n\t\t*/\n\t\tInt & operator += (const Int & number) {Carry = XMP_Add(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}\n\t\tInt & operator -= (const Int & number) {Borrow = XMP_Sub(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}\n\t\tInt & operator *= (const Int & multiplier) {Remainder = *this;Error=XMP_Signed_Mult(&reg[0], Remainder, multiplier, PRECISION);return(*this);}\n\t\tInt & operator /= (const Int & t) {*this = (*this) / t;return *this;}\n\t\tInt & operator %= (const Int & t) {*this = (*this) % t;return *this;}\n\t\tInt &  operator <<= (int bits) {XMP_Shift_Left_Bits(&reg[0], bits, PRECISION);return *this;}\n\t\tInt &  operator >>= (int bits) {XMP_Shift_Right_Bits(&reg[0], bits, PRECISION);return *this;}\n\n\t\t/*\n\t\t**\tMathematical binary operators.\n\t\t*/\n\t\tInt operator + (const Int & number) const {Int term;Carry = XMP_Add(term, &reg[0], number, 0, PRECISION);return(term);}\n\t\tInt operator + (unsigned short b) const {Int result;Carry=XMP_Add_Int(result, &reg[0], b, 0, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator + (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) + a);}\n\t\tInt operator - (const Int & number) const {Int term;Borrow = XMP_Sub(term, &reg[0], number, 0, PRECISION);return(term);}\n\t\tInt operator - (unsigned short b) const {Int result;Borrow = XMP_Sub_Int(result, &reg[0], b, 0, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator - (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) - a);}\n\t\tInt operator * (const Int & multiplier) const {Int result;Error=XMP_Signed_Mult(result, &reg[0], multiplier, PRECISION);return result;}\n\t\tInt operator * (unsigned short b) const {Int result;Error=XMP_Unsigned_Mult_Int(result, &reg[0], b, PRECISION);return(result);}\n//\t\tfriend Int<PRECISION> operator * (digit b, const Int<PRECISION> & a) {return(Int<PRECISION>(b) * a);}\n\t\tInt operator / (const Int & divisor) const {Int quotient = *this;XMP_Signed_Div(Remainder, quotient, &reg[0], divisor, PRECISION);return (quotient);}\n\t\tInt operator / (unsigned long b) const {return(*this / Int<PRECISION>(b));}\n\t\tInt operator / (unsigned short divisor) const {Int quotient;Error=XMP_Unsigned_Div_Int(quotient, &reg[0], divisor, PRECISION);return(quotient);}\n//\t\tfriend Int<PRECISION> operator / (digit a, const Int<PRECISION> & b) {return(Int<PRECISION>(a) / b);}\n\t\tInt operator % (const Int & divisor) const {Int remainder;XMP_Signed_Div(remainder, Remainder, &reg[0], divisor, PRECISION);return(remainder);}\n\t\tInt operator % (unsigned long b) const {return(*this % Int<PRECISION>(b));}\n\t\tunsigned short operator % (unsigned short divisor) const {return(XMP_Unsigned_Div_Int(Remainder, &reg[0], divisor, PRECISION));}\n//\t\tfriend Int<PRECISION> operator % (digit a, const Int<PRECISION> & b) {return(Int<PRECISION>(a) % b);}\n\n\t\t/*\n\t\t**\tBitwise binary operators.\n\t\t*/\n\t\tInt operator >> (int bits) const {Int result = *this; XMP_Shift_Right_Bits(result, bits, PRECISION);return result;}\n\t\tInt operator << (int bits) const {Int result = *this; XMP_Shift_Left_Bits(result, bits, PRECISION);return result;}\n\n\t\t/*\n\t\t**\tComparison binary operators.\n\t\t*/\n\t\tint operator == (const Int &b) const {return (memcmp(&reg[0], &b.reg[0], (MAX_BIT_PRECISION/CHAR_BIT))==0);}\n\t\tint operator != (const Int& b) const {return !(*this == b);}\n\t\tint operator > (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) > 0);}\n\t\tint operator >= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) >= 0);}\n\t\tint operator < (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) < 0);}\n\t\tint operator <= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) <= 0);}\n\n\t\t/*\n\t\t**\tMisc. mathematical and logical functions.\n\t\t*/\n\t\tvoid Negate(void) {XMP_Neg(&reg[0], PRECISION);}\n\t\tInt Abs(void) {XMP_Abs(&reg[0], PRECISION);return(*this);}\n\t\tInt times_b_mod_c(Int const & multiplier, Int const & modulus) const {\n\t\t\tInt result;\n\t\t\tError=xmp_stage_modulus(modulus, PRECISION);\n\t\t\tError=XMP_Mod_Mult(result, &reg[0], multiplier, PRECISION);\n\t\t\tXMP_Mod_Mult_Clear(PRECISION);\n\t\t\treturn result;\n\t\t}\n\n\t\tInt exp_b_mod_c(const Int & e, const Int & m) const {\n\t\t\tInt result;\n\t\t\tError=xmp_exponent_mod(result, &reg[0], e, m, PRECISION);\n\t\t\treturn result;\n\t\t}\n\n\n\t\tstatic Int Unsigned_Mult(Int const & multiplicand, Int const & multiplier) {Int product;Error=XMP_Unsigned_Mult(&product.reg[0], &multiplicand.reg[0], &multiplier.reg[0], PRECISION);return(product);}\n\t\tstatic void Unsigned_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {Error=XMP_Unsigned_Div(remainder, quotient, dividend, divisor, PRECISION);}\n\t\tstatic void Signed_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {XMP_Signed_Div(remainder, quotient, dividend, divisor, PRECISION);}\n\t\tInt Inverse(const Int & modulus) const {Int result;XMP_Inverse_A_Mod_B(result, &reg[0], modulus, PRECISION);return(result);}\n\n\t\tstatic Int Decode_ASCII(char const * string) {Int result;XMP_Decode_ASCII(string, result, PRECISION);return(result);}\n\n\t\t// Number (sign independand) inserted into buffer.\n\t\tint Encode(unsigned char *output) const {return(XMP_Encode(output, &reg[0], PRECISION));}\n\t\tint Encode(unsigned char * output, unsigned length) const {return(XMP_Encode(output, length, &reg[0], PRECISION));}\n\t\tvoid Signed_Decode(const unsigned char * from, int frombytes) {XMP_Signed_Decode(&reg[0], from, frombytes, PRECISION);}\n\t\tvoid Unsigned_Decode(const unsigned char * from, int frombytes) {XMP_Unsigned_Decode(&reg[0], from, frombytes, PRECISION);}\n\n\t\t// encode Int using Distinguished Encoding Rules, returns size of output\n\t\tint DEREncode(unsigned char * output) const {return(XMP_DER_Encode(&reg[0], output, PRECISION));}\n\t\tvoid DERDecode(const unsigned char *input) {XMP_DER_Decode(&reg[0], input, PRECISION);}\n\n\t\t// Friend helper functions.\n\t\tfriend Int<PRECISION> Generate_Prime(Straw & rng, int pbits, Int<PRECISION> const * = 0);\n\t\tfriend Int<PRECISION> Gcd(const Int<PRECISION> & a, const Int<PRECISION> & b);\n//\t\tfriend bool NextPrime(Int<PRECISION> & p, const Int<PRECISION> & max, bool blumInt=false);\n//\t\tfriend Int<PRECISION> a_exp_b_mod_pq(const Int<PRECISION> & a, const Int<PRECISION> & ep, const Int<PRECISION> & eq, const Int<PRECISION> & p, const Int<PRECISION> & q, const Int<PRECISION> & u);\n\n\t\tstatic int Error;\n\n\t\t// Carry result from last addition.\n\t\tstatic bool Carry;\n\n\t\t// Borrow result from last subtraction.\n\t\tstatic bool Borrow;\n\n\t\t// Remainder value from the various division routines.\n\t\tstatic Int Remainder;\n\n\n\tprivate:\n\t\tdigit reg[PRECISION];\n\n\n\t\tstruct RemainderTable\n\t\t{\n\t\t\tRemainderTable(const Int<PRECISION> & p) : HasZeroEntry(false)\n\t\t\t{\n\t\t\t\tfor (unsigned i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] = p % primeTable[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tbool HasZero() const {return(HasZeroEntry);}\n\t\t\tvoid Increment(unsigned short increment = 1)\n\t\t\t{\n\t\t\t\tHasZeroEntry = false;\n\t\t\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] += increment;\n\t\t\t\t\twhile (table[i] >= primeTable[i]) {\n\t\t\t\t\t\ttable[i] -= primeTable[i];\n\t\t\t\t\t}\n\t\t\t\t\tHasZeroEntry = (HasZeroEntry || !table[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvoid Increment(const RemainderTable & rtQ)\n\t\t\t{\n\t\t\t\tHasZeroEntry = false;\n\t\t\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\t\t\t\ttable[i] += rtQ.table[i];\n\t\t\t\t\tif (table[i] >= primeTable[i]) {\n\t\t\t\t\t\ttable[i] -= primeTable[i];\n\t\t\t\t\t}\n\t\t\t\t\tHasZeroEntry = (HasZeroEntry || !table[i]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbool HasZeroEntry;\n\t\t\tunsigned short table[ARRAY_SIZE(primeTable)];\n\t\t};\n\n};\n\n\ntemplate<class T>\nT Gcd(const T & a, const T & n)\n{\n\tT g[3]={n, a, 0UL};\n\n\tunsigned int i = 1;\n\twhile (!!g[i%3]) {\n\t\tg[(i+1)%3] = g[(i-1)%3] % g[i%3];\n\t\ti++;\n\t}\n\treturn g[(i-1)%3];\n}\n\n\n\n//#pragma warning 604 9\n//#pragma warning 595 9\ntemplate<class T>\nT Generate_Prime(Straw & rng, int pbits, T const *)\n{\n\tT minQ = (T(1UL) << (unsigned short)(pbits-(unsigned short)2));\n\tT maxQ = ((T(1UL) << (unsigned short)(pbits-(unsigned short)1)) - (unsigned short)1);\n\n\tT q;\n\tT p;\n\n\tdo {\n\t\tq.Randomize(rng, minQ, maxQ);\n\t\tp = (q*2) + (unsigned short)1;\n\n\t\tT::RemainderTable rtQ(q);\n\t\tT::RemainderTable rtP(p);\n\n\t\twhile (rtQ.HasZero() || rtP.HasZero() || !q.IsPrime() || !p.IsPrime()) {\n\t\t\tq += 2;\n\t\t\tp += 4;\n\t\t\tif (q > maxQ) break;\n\n\t\t\trtQ.Increment(2);\n\t\t\trtP.Increment(4);\n\t\t}\n\t} while (q > maxQ);\n\n\treturn(p);\n}\n\n\n\n\n\n\ntypedef Int<MAX_UNIT_PRECISION>\tbignum;\ntypedef Int<MAX_UNIT_PRECISION>\tBigInt;\n\n\n\n//BigInt Gcd(const BigInt & a, const BigInt & n);\n//BigInt Generate_Prime(RandomNumberGenerator & rng, int pbits, BigInt const * dummy);\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/INTERNET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/INTERNET.CPP 6     3/17/97 1:05a Steve_tall $ */\n/*************************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : INTERNET.CPP                                       *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : March 11th, 1996                                   *\n *                                                                                   *\n *                  Last Update : August 5th, 1996 [ST]                              *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Miscellaneous junk related to H2H internet connection.                           *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *  Check_From_WChat -- Interprets start game packet from WChat           \t \t\t\t*\n *  Read_Game_Options -- Read the game setup options from the wchat packet\t \t\t\t*\n *  Is_User_WChat_Registered -- retrieve the users wchat entry from registry \t\t\t*\n *  Spawn_WChat -- spawns or switches focus to wchat                         \t\t\t*\n *  Spawn_Registration_App -- spawns the C&C/Planet westwood registration app\t\t\t*\n *  Do_The_Internet_Menu_Thang -- Handle case where user clicks on 'Internet' button *\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifdef WIN32\n\n#include \"function.h\"\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\n\nextern bool SpawnedFromWChat;\n\n#ifndef WOLAPI_INTEGRATION\nint Read_Game_Options(void);\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_126x126 (char *file_name);\nextern bool Is_Mission_Aftermath (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\n#endif\n\n/***************************************************************************\n** Internet specific globals\n*/\nchar PlanetWestwoodHandle[] = {\"Handle\"};\t\t\t\t//Planet WW user name\nchar PlanetWestwoodPassword[] = {\"Password\"};\t\t\t//Planet WW password\nchar PlanetWestwoodIPAddress[IP_ADDRESS_MAX] = {\"206.154.108.87\"};\t//IP of server or other player\nlong PlanetWestwoodPortNumber = 1234;\t\t\t\t\t//Port number to send to\nbool PlanetWestwoodIsHost = false;\t\t\t\t\t\t//Flag true if player has control of game options\nunsigned long PlanetWestwoodGameID;\t\t\t\t\t\t//Game ID\nunsigned long PlanetWestwoodStartTime;\t\t\t\t\t//Time that game was started\nHWND\tWChatHWND = 0;\t\t\t\t\t\t\t\t\t\t\t//Handle to Wchat window.\nbool\tGameStatisticsPacketSent;\t\t\t\t\t\t\t//Flag that game stats have been sent to wchat\nbool\tConnectionLost;\t\t\t\t\t\t\t\t\t\t//Flag that the connection to the other player was lost\nint\t\tWChatMaxAhead;\nint\t\tWChatSendRate;\nbool\tSpawnedFromWChat;\nint\t\tShowCommand;\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Connexion En Cours...\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_CONNECTING)\n#endif\n\n/***********************************************************************************************\n * Check_From_WChat -- This function reads in C&CSPAWN.INI and interprets it.                  *\n *                     C&CSPAWN.INI is now sent to us by WCHAT via DDE                         *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Name of C&CSPAWN.INI file. If NULL then get file from DDE Server.                 *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/9/96 1:44PM ST : Created                                                               *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nvoid Check_From_WChat(char *wchat_name)\n{\n\n\tchar\tdefault_string[] = {\"Error\"};\n\tchar\tkey_string[256];\n\tchar *ini_file;\n\tRawFileClass wchat_file;\n\n\t/*\n\t** Get a pointer to C&CSPAWN.INI either by reading it from disk or getting it from\n\t** the DDE server.\n\t*/\n\tif (wchat_name){\n\t\tini_file = new char [8192];\n\t}else{\n\t\tini_file = DDEServer.Get_MPlayer_Game_Info();\n\n#ifdef NEVER\n\t\t/*\n\t\t** Save it to disk as well so I can see it\n\t\t*/\n\t\tRawFileClass anotherfile (\"FROMCHAT.TXT\");\n\t\tanotherfile.Write(ini_file, DDEServer.Get_MPlayer_Game_Info_Length());\n#endif\n\n\t}\n\n\tif (wchat_name){\n\t\twchat_file.Set_Name(wchat_name);\n\t}\n\n\tif (!wchat_name || wchat_file.Is_Available()){\n\n\t\t/*\n\t\t** Read the ini file from disk if we founf it there\n\t\t*/\n\t\tif (wchat_name){\n\t\t\twchat_file.Read(ini_file, wchat_file.Size());\n\t\t}\n\n\t\t/*\n\t\t** Get the IP address\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Address\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\t\tstrcpy (PlanetWestwoodIPAddress, key_string);\n\n\n\n\t\t/*\n\t\t** Get the port number\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Port\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\n\t\tPlanetWestwoodPortNumber = atol(key_string);\n\n\n\t\t/*\n\t\t** Get host or client\n\t\t*/\n\t\tkey_string[0] = 0;\n\n\t\tWWGetPrivateProfileString(\"Internet\",\n\t\t\t\t\t\t\t\t\t\t\"Host\",\n\t\t\t\t\t\t\t\t\t\tdefault_string,\n\t\t\t\t\t\t\t\t\t\tkey_string,\n\t\t\t\t\t\t\t\t\t\tsizeof(key_string),\n\t\t\t\t\t\t\t\t\t\tini_file);\n\n\n\t\tif (!strcmp (key_string, default_string)) {\n\t\t\tif (wchat_name) delete ini_file;\n\t\t\treturn;\n\t\t}\n\n\t\tif (strchr (key_string, '1')){\n\t\t\tPlanetWestwoodIsHost = true;\n\t\t}else{\n\t\t\tPlanetWestwoodIsHost = false;\n\t\t}\n\n\n\t\tSpecial.IsFromWChat = true;\n\t}\n\n\tif (wchat_name) delete ini_file;\n\n}\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\n/***************************************************************************\n * Read_Game_Options -- reads multiplayer game options from disk           *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname of C&CSPAWN.INI file. Null if data should be got from DDE server*                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                          \\                                     *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\n#ifndef WOLAPI_INTEGRATION\nint Read_Game_Options(char *name)\n{\n\tchar *buffer;\n\n\tchar filename[256] = {\"INVALID.123\"};\n\n\tif (name){\n\t\tstrcpy (filename, name);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCreate filename and read the file.\n\t------------------------------------------------------------------------*/\n\tCCFileClass file (filename);\n\n\tif (name && !file.Is_Available()) {\n\t\treturn(0);\n\t} else {\n\t\tif (name){\n\t\t\tbuffer = new char [8192];\t\t\t\t\t\t\t// INI staging buffer pointer.\n\t\t\tmemset(buffer, '\\0', 8192);\n\t\t\tfile.Read(buffer, 8192-1);\n\t\t\tfile.Close();\n\t\t}else{\n\t\t\tbuffer = DDEServer.Get_MPlayer_Game_Info();\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tGet the player's name\n\t------------------------------------------------------------------------*/\n\tWWGetPrivateProfileString(\"Options\", \"Handle\", \"Noname\", Session.Handle,\n\t\tsizeof(Session.Handle), buffer);\n\tstrcpy(Session.GameName, Session.Handle);\n\tSession.ColorIdx = (PlayerColorType) WWGetPrivateProfileInt(\"Options\", \"Color\", 0, buffer);\n\tSession.PrefColor = Session.ColorIdx;\n\tint temp = WWGetPrivateProfileInt(\"Options\", \"Side\", 0, buffer);\n\tSession.House = (HousesType) ((int)HOUSE_USSR + temp);\n\n\tSession.Options.Credits = WWGetPrivateProfileInt(\"Options\", \"Credits\", 0, buffer);\n\tSession.Options.Bases = WWGetPrivateProfileInt(\"Options\", \"Bases\", 0, buffer);\n\tSession.Options.Tiberium = WWGetPrivateProfileInt(\"Options\", \"Tiberium\", 0, buffer);\n\tSession.Options.Goodies = WWGetPrivateProfileInt(\"Options\", \"Crates\", 0, buffer);\n\tSpecial.IsShadowGrow = WWGetPrivateProfileInt (\"Options\", \"Shadow\", 0, buffer);\n\tBuildLevel = WWGetPrivateProfileInt(\"Options\", \"BuildLevel\", 0, buffer);\n\tSession.Options.UnitCount = WWGetPrivateProfileInt(\"Options\", \"UnitCount\", 0, buffer);\n\tSeed = WWGetPrivateProfileInt(\"Options\", \"Seed\", 0, buffer);\n\tSpecial.IsCaptureTheFlag = WWGetPrivateProfileInt(\"Options\", \"CapFlag\", 0, buffer);\n\tUnitBuildPenalty = WWGetPrivateProfileInt (\"Options\", \"BuildRate\", 100, buffer);\n\n\tPlanetWestwoodGameID = WWGetPrivateProfileInt(\"Internet\", \"GameID\", 0, buffer);\n\tPlanetWestwoodStartTime = WWGetPrivateProfileInt (\"Internet\", \"StartTime\", 0, buffer);\n\tWChatHWND = (HWND) WWGetPrivateProfileInt(\"Internet\", \"HWND\", (int)FindWindow(\"OWL_Window\", \"Westwood Chat\"), buffer);\n\n\tSession.Options.AIPlayers = WWGetPrivateProfileInt(\"Options\", \"AI\", 0, buffer);\t\t//Number of AI players\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tWWGetPrivateProfileString(\"Options\", \"Scenario\", \"SCM01EA.INI\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription),\n\t\t\t\t\t\t\t\t\t\tbuffer);\n\t//WWDebugString (\"RA95I - Scenario is \");\n\t//WWDebugString (Session.Options.ScenarioDescription);\n\t//WWDebugString (\"\\n\");\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (PlanetWestwoodIsHost){\n\t\t/*\n\t\t** Special new kludge for counterstrike.\n\t\t**\n\t\t** The only time the file can be unavailable is if its a counterstrike\n\t\t** mission and the CS CD is not in the drive so\n\t\t** make sure the counterstrike CD is in the drive.\n\t\t**\n\t\t** If Counterstrike is installed then force the CD\n\t\t** to be there.\n\t\t**\n\t\t*/\n\t\tif (Session.Options.ScenarioIndex == -1) {\n\t\t\t//WWDebugString (\"RA95I - Session.Options.ScenarioIndex == -1\\n\");\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t    (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) {\n#else\n\t\t\tif ( Expansion_CS_Present() ) {\n#endif\n\n\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tint index=Get_CD_Index(current_drive, 1*60);\n\t\t\t\tbool needcd = false;\n\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (needcd) {\n#else\n\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\tRequiredCD = 2;\n#endif\n\t\t\t\t\t//WWDebugString (\"RA95I - CounterStrike CD not in drive\\n\");\n\n\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\tif (!RunningAsDLL) {\t//PG\n\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//WWDebugString (\"RA95I - Returned from Force_CD_Available()\\n\");\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t** list.\n\t\t\t\t\t*/\n\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** See if that scenario is available now. Its fatal if it isnt.\n\t\t\t*/\n\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\t\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//if (Session.Options.ScenarioIndex == -1)\n\t\t\t//\tWWDebugString (\"RA95I - Session.Options.ScenarioIndex is still -1\\n\");\n\n\t\t}\n\t}\n\n\n\tOptions.GameSpeed = 0;\n\n\n\t//MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);\n\n\tSession.MaxAhead = WChatMaxAhead = WWGetPrivateProfileInt(\"Timing\", \"MaxAhead\", 9, buffer);\n\tSession.FrameSendRate = WChatSendRate = WWGetPrivateProfileInt(\"Timing\", \"SendRate\", 3, buffer);\n\n\tif (name) delete buffer;\n\treturn (1);\n\n}\n#endif\t//\t!WOLAPI_INTEGRATION\n\n\n\n\n/***********************************************************************************************\n * Get_Registry_Sub_Key -- search a registry key for a sub-key                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    handle of key to search                                                           *\n *           text to search for                                                                *\n *           true if old key should be closed when new key opened                              *\n *                                                                                             *\n * OUTPUT:   handle to the key we found or 0                                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:11PM ST : Created                                                              *\n *=============================================================================================*/\n\nextern HKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close);\n\n\n\nvoid Just_Path(char *path, char *destpath)\n{\n\tchar *terminator = NULL;\t\t//He'll be back.\n\n\tstrcpy  (destpath, path);\n\tterminator = strrchr (destpath, '\\\\');\n\tif (terminator){\n\t\t*terminator = 0;\n\t}\n}\n\n\n\n\n\n/***********************************************************************************************\n * Is_User_WChat_Registered -- retrieve the users wchat entry from the registry                *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:  Nothing                                                                             *\n *                                                                                             *\n * OUTPUT:   TRUE if users wchat entry was found in the registry                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    1/12/96 2:13PM ST : Created                                                              *\n *=============================================================================================*/\nbool Is_User_WChat_Registered(char *buffer, int buffer_len)\n{\n\t// ST - 5/13/2019\n\tbuffer; buffer_len;\n\treturn false;\n\n#if (0)\n\tHKEY\tkey;\n\tchar\tuser_handle[256];\n\tDWORD\tuser_handle_size = sizeof (user_handle);\n\tchar\tuser_pword[256];\n\tDWORD\tuser_pword_size = sizeof (user_pword);\n\n\n\t/*\n\t** Check HKEY_CLASSES_ROOT first. Old versions of Wchat register there\n\t*/\n\tkey = Get_Registry_Sub_Key (HKEY_CLASSES_ROOT, \"Wchat\", FALSE);\n\n\tif (key){\n\t\tkey = Get_Registry_Sub_Key (key, \"Nick1\", TRUE);\n\t\tif (key){\n\n\t\t\tif (RegQueryValue(key, \"Nick\", user_handle, (long*)&user_handle_size) == ERROR_SUCCESS){\n\n\t\t\t\tif (RegQueryValue(key, \"Pass\", user_pword, (long*)&user_pword_size) == ERROR_SUCCESS){\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the first char of the users name is non-numberic and there is a password\n\t\t\t\t\t** then return success\n\t\t\t\t\t*/\n\t\t\t\t\tif ((user_handle[0] < '0' || user_handle[0] > '9') && user_pword[0]){\n\t\t\t\t\t\tRegCloseKey( key );\n\t\t\t\t\t\treturn (TRUE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tRegCloseKey ( key );\n\t}\n\n\n\n\t/*\n\t** Check HKEY_LOCAL_MACKINE/Software\n\t*/\n\tuser_handle_size = sizeof (user_handle);\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"InetReg\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"UserName\", NULL, NULL, (unsigned char*)user_handle, &user_handle_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\tmemcpy (buffer, user_handle, min((unsigned)buffer_len, user_handle_size));\n\n\t/*\n\t** If the first char of the users name is non-numeric then return success\n\t*/\n\tif (user_handle[0] < '0' || user_handle[0] > '9'){\n\t\treturn (TRUE);\n\t}else{\n\t\treturn (FALSE);\n\t}\n#endif\n}\n\n\n\n/***********************************************************************************************\n * Spawn_WChat -- spawns or switches focus to wchat                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    can launch. If set then we are allowed to launch WChat if not already running     *\n *                                                                                             *\n * OUTPUT:   True if wchat was spawned                                                         *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 12:33PM ST : Created                                                              *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Poke_WChat(void);\nbool Spawn_WChat(bool can_launch)\n{\n\t// ST - 5/13/2019\n\tcan_launch;\n\treturn false;\n\n#if (0)\n\tWWDebugString (\"RA95 - In Spawn_WChat.\\n\");\n\tchar packet[10] = {\"Hello\"};\n\tHWND chat_window = NULL;\n\n\t/*\n\t** See if WChat is already running...\n\t*/\n\tif (WChatHWND && IsWindow (WChatHWND) ){\n\t\tchat_window = WChatHWND;\n\t}else{\n\t\tchat_window = FindWindow ( \"OWL_Window\", \"Westwood Chat\" );\n\t}\n\n\tif (chat_window){\n\t/*\n\t** WChat is already running. Minimize myself then try to give it focus.\n\t*/\n\t\tBlackPalette.Set();\n\t\tVisiblePage.Clear();\n\t\tShowWindow (MainWindow, SW_MINIMIZE);\n\t\t/*\n\t\t** Give windoze a couple of secs to sort itself out.\n\t\t*/\n\t\tCountDownTimerClass wibble_timer;\n\t\twibble_timer.Set ( 60 * 3, true);\n\n\t\twhile (wibble_timer.Time()){\n\t\t\t/*\n\t\t\t** Call our message loop to make sure we get all the messages that are sent to us\n\t\t\t** when we minimise.\n\t\t\t*/\n\t\t\tKeyboard->Check();\n\t\t}\n\n\t\t/*\n\t\t** Send chat a tickle message so it knows to send the game stats to the server.\n\t\t*/\n\t\tif (GameStatisticsPacketSent && !PlanetWestwoodIsHost) {\n\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_TICKLE);\n\t\t}\n\n\t\t//Send_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_TICKLE);\n\t\t/*\n\t\t** Give the focus to WChat\n\t\t*/\n\t\tSetForegroundWindow ( chat_window );\n\t\tShowWindow ( chat_window, SW_RESTORE );\n\t\treturn(true);\n\t}\n\n\n\t/*\n\t** Fail if we aren't allowed to launch wchat and we couldnt find its window.\n\t*/\n\tif (!can_launch) return (false);\n\n\n\t/*\n\t** Find where WChat was installed to\n\t*/\n\tHKEY\tkey;\n\tchar\twchat_loc[256];\n\tDWORD\twchat_loc_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"WChat\", TRUE);\n\tif (!key) return (FALSE);\n\n\t//key = Get_Registry_Sub_Key (key, \"UserName\", TRUE);\n\t//if (!key) return (FALSE);\n\n\t//key = Get_Registry_Sub_Key (key, \"Nick\", TRUE);\n\t//if (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"InstallPath\", NULL, NULL, (unsigned char*)wchat_loc, &wchat_loc_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\n\tPROCESS_INFORMATION process_info;\n\tSTARTUPINFO start_info;\n\tmemset ((void*)&start_info, 0, sizeof(start_info));\n\tstart_info.cb = sizeof(start_info);\n\tchar justpath [256];\n\tJust_Path(wchat_loc, justpath);\n\n\t/*\n\t** We found WChat in the registry. Minimize myself then try to spawn it.\n\t*/\n\tBlackPalette.Set();\n\tVisiblePage.Clear();\n\tShowWindow (MainWindow, SW_MINIMIZE);\n\t/*\n\t** Give windoze a couple of secs to sort itself out.\n\t*/\n\tCountDownTimerClass wibble_timer;\n\twibble_timer.Set ( 60 * 3, true);\n\n\twhile (wibble_timer.Time()){\n\t\t/*\n\t\t** Call our message loop to make sure we get all the messages that are sent to us\n\t\t** when we minimise.\n\t\t*/\n\t\tKeyboard->Check();\n\t}\n\tbool success = CreateProcess (wchat_loc, NULL, NULL, NULL, false, 0, NULL, justpath, &start_info, &process_info);\n\n\tif (success){\n\t\treturn (true);\n\t}else{\n\t\tShowWindow (MainWindow, SW_RESTORE);\n\t\twhile ( Keyboard->Check() ) {};\n\t\treturn (false);\n\t}\n#endif\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n/***********************************************************************************************\n * Spawn_Registration_App -- spawns the C&C/Planet westwood registration app                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   True if app was spawned                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/8/96 12:33PM ST : Created                                                              *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Spawn_Registration_App(void)\n{\n\t// ST - 5/13/2019\n\treturn false;\n#if (0)\n\t/*\n\t** Find where inetreg was installed to\n\t*/\n\n\tHKEY\tkey;\n\tchar\tinetreg_loc[256];\n\tDWORD\tinetreg_loc_size = 256;\n\n\tkey = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, \"SOFTWARE\", FALSE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"Westwood\", TRUE);\n\tif (!key) return (FALSE);\n\n\tkey = Get_Registry_Sub_Key (key, \"InetReg\", TRUE);\n\tif (!key) return (FALSE);\n\n\tif (RegQueryValueEx(key, \"InstallPath\", NULL, NULL, (unsigned char*)inetreg_loc, &inetreg_loc_size) != ERROR_SUCCESS){\n\t\tRegCloseKey(key);\n\t\treturn (FALSE);\n\t}\n\n\tRegCloseKey(key);\n\n\tPROCESS_INFORMATION process_info;\n\tSTARTUPINFO start_info;\n\tchar justpath \t[256];\n\tmemset ((void*)&start_info, 0, sizeof(start_info));\n\tstart_info.cb = sizeof(start_info);\n\tJust_Path(inetreg_loc, justpath);\n\n\tBOOL success = CreateProcess (inetreg_loc, NULL, NULL, NULL, false, 0, NULL, justpath, &start_info, &process_info);\n\tif (success){\n\t\t//WaitForSingleObject (process_info.hProcess, 1000*10000);\n\t\t//SetForegroundWindow ( MainWindow );\n\t\t//ShowWindow ( MainWindow, SW_RESTORE );\n\t}\n\treturn (success);\n#endif\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n\n/***********************************************************************************************\n * Do_The_Internet_Menu_Thang -- Handle case where user clicks on 'Internet' button            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 8:30PM ST : Created                                                               *\n *=============================================================================================*/\n#ifndef WOLAPI_INTEGRATION\nbool Do_The_Internet_Menu_Thang(void)\n{\n#if (0) //PG\n\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\tchar packet[10] = {\"Hello\"};\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 120 *factor;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 80*factor;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*factor - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*factor - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*factor;\n#else\n\tint d_cancel_w = 40*factor;\n#endif\n\tint d_cancel_h = 9*factor;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;\n\n\tint\twidth;\n\tint\theight;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//buttons = &cancelbtn;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\tchar users_name[256];\n\tint  buffer_len = sizeof (users_name);\n\tbool process;\n\tbool display;\n\tKeyNumType input;\n\n\n\tif (!Special.IsFromWChat && !SpawnedFromWChat){\n\t\t/*\n\t\t** If the user is registered with Planet Westwood then spawn WChat.\n\t\t*/\n\t\tif (Is_User_WChat_Registered(users_name, buffer_len)){\n\t\t\tGameStatisticsPacketSent = false;\n\t\t\tif (!Spawn_WChat(true)){\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\t\t\t\tWWMessageBox().Process(TXT_ERROR_UNABLE_TO_RUN_WCHAT, TXT_OK);\n\t\t\t\tLogicPage->Clear();\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** OK, whatever, just run WChat anyway.\n\t\t\t*/\n\t\t\tif (!Spawn_WChat (true)){\n\n\t\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\t//WWMessageBox().Process(TXT_EXPLAIN_REGISTRATION, TXT_CANCEL);\n\t\t\t\tWWMessageBox().Process(TXT_NO_REG_APP, TXT_CANCEL);\n\t\t\t}\n\t\t\tLoad_Title_Page(true);\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\n\t** User is registered and we spawned WChat. Wait for a game start message from WChat.\n\t**\n\t*/\n\n\tprocess = true;\n\tdisplay = true;\n\n\twhile (process){\n\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\tAllSurfaces.SurfacesRestored = FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\n\t\tif (display) {\n\t\t\tSet_Logic_Page(SeenBuff);\n\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t** Redraw backgound & dialog box\n\t\t\t*/\n\t\t\tLoad_Title_Page(true);\n\t\t\tSet_Palette(CCPalette);\n\n\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t/*\n\t\t\t** Dialog & Field labels\n\t\t\t*/\n\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*factor,\n\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t//cancelbtn.Zap();\n\t\t\t//buttons = &cancelbtn;\n\n\t\t\t/*\n\t\t\t.................... Rebuild the button list ....................\n\t\t\t*/\n\t\t\t//buttons->Draw_All();\n\t\t\tcancelbtn.Draw_Me(true);\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\n\t\t/*\n\t\t** See if the game start packet has arrived from wchat yet.\n\t\t*/\n\t\tif (DDEServer.Get_MPlayer_Game_Info()){\n\t\t\t//MessageBox (NULL, \"About to restore focus to C&C95\", \"C&C95\", MB_OK);\n\t\t\t//SetForegroundWindow ( MainWindow );\n\t\t\t//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED\t);\n\t\t\treturn(true);\n\t\t}\n\n\t\t//input = buttons->Input();\n\t\tinput = cancelbtn.Input();\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t** Cancel. Just return to the main menu\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\tSpawn_WChat(false);\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n#endif\n\treturn (false);\n}\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/INTERNET.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                     $Archive:: /Sun/Internet.h                                             $*\n *                                                                                             *\n *                      $Author:: Joe_b                                                       $*\n *                                                                                             *\n *                     $Modtime:: 8/05/97 6:45p                                               $*\n *                                                                                             *\n *                    $Revision:: 7                                                           $*\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INTERNET_H\n#define INTERNET_H\n\n#define IP_ADDRESS_MAX 40\n\n\nvoid\tRegister_Game_Start_Time(void);\nvoid\tRegister_Game_End_Time(void);\nvoid\tSend_Statistics_Packet(void);\nvoid \tCheck_From_WChat(char *wchat_name);\nbool \tDo_The_Internet_Menu_Thang (void);\nbool \tServer_Remote_Connect(void);\nbool \tClient_Remote_Connect(void);\nint \tRead_Game_Options(char *name);\n\nextern char PlanetWestwoodIPAddress[IP_ADDRESS_MAX];\nextern long PlanetWestwoodPortNumber;\nextern bool PlanetWestwoodIsHost;\n\n#endif\n"
  },
  {
    "path": "REDALERT/INTERPAL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INTERPAL.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTERPAL.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : December 7th 1995                                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  This module contains functions to allow use of old 320x200 animations on a 640x400 screen  *\n *                                                                                             *\n * Functions:                                                                                  *\n *  Read_Interpolation_Palette -- reads an interpolation palette table from disk               *\n *  Write_Interpolation_Palette -- writes an interpolation palette to disk                     *\n *  Create_Palette_Interpolation_Table -- build the palette interpolation table                *\n *  Increase_Palette_Luminance -- increase the contrast of a palette                           *\n *  Interpolate_2X_Scale -- Stretch a 320x200 graphic buffer into 640x400                      *\n *                                                                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nBOOL\tInterpolationPaletteChanged = FALSE;\nextern \"C\" {\nextern void __cdecl Asm_Interpolate (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\nextern void __cdecl Asm_Interpolate_Line_Double (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\nextern void __cdecl Asm_Interpolate_Line_Interpolate (unsigned char* src_ptr ,\n\t\t\t\t\t\t \t\t\t\t\t\tunsigned char* dest_ptr ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tlines ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tsrc_width ,\n\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\tdest_width);\n\n}\n\n#define SIZE_OF_PALETTE\t256\nextern \"C\"{\n\tunsigned char PaletteInterpolationTable[SIZE_OF_PALETTE][SIZE_OF_PALETTE];\n\tunsigned char * InterpolationPalette;\n}\n\n\n\n/***********************************************************************************************\n * Read_Interpolation_Palette -- reads an interpolation palette table from disk               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:15PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Read_Interpolation_Palette (char const * palette_file_name)\n{\n\tCCFileClass palette_file(palette_file_name);\n\n\tif (palette_file.Is_Available()) {\n\t\tpalette_file.Open(READ);\n\t\tpalette_file.Read(&PaletteInterpolationTable[0][0], 256*256);\n\t\tpalette_file.Close();\n\t\tInterpolationPaletteChanged = FALSE;\n\t}\n}\n\n\n/***********************************************************************************************\n * Write_Interpolation_Palette -- writes an interpolation palette table to disk               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    name of palette file                                                              *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:15PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Write_Interpolation_Palette (char const * palette_file_name)\n{\n\tCCFileClass palette_file(palette_file_name);\n\n\tif (!palette_file.Is_Available()) {\n\t\tpalette_file.Open(WRITE);\n\t\tpalette_file.Write(&PaletteInterpolationTable[0][0], 256*256);\n\t\tpalette_file.Close();\n\t}\n}\n\n\n\n\n\n/***************************************************************************\n * CREATE_PALETTE_INTERPOLATION_TABLE                                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Create_Palette_Interpolation_Table( void )\n{\n\n//\tAsm_Create_Palette_Interpolation_Table();\n\n\t#if (1)\n\n\tint \t\t\t\ti;\n\tint \t\t\t\tj;\n\tint \t\t\t\tp;\n\tunsigned char\t* first_palette_ptr;\n\tunsigned char\t* second_palette_ptr;\n\tunsigned char\t* match_pal_ptr;\n\tint\t\t\t\tfirst_r;\n\tint\t\t\t\tfirst_g;\n\tint\t\t\t\tfirst_b;\n\tint\t\t\t\tsecond_r;\n\tint\t\t\t\tsecond_g;\n\tint\t\t\t\tsecond_b;\n\tint\t\t\t\tdiff_r;\n\tint\t\t\t\tdiff_g;\n\tint\t\t\t\tdiff_b;\n\tint\t\t\t\tdest_r;\n\tint\t\t\t\tdest_g;\n\tint\t\t\t\tdest_b;\n\tint \t\t\t\tdistance;\n\tint \t\t\t\tclosest_distance;\n\tint \t\t\t\tindex_of_closest_color;\n\n\t//\n\t// Create an interpolation table for the current palette.\n\t//\n\tfirst_palette_ptr = (unsigned char *) InterpolationPalette;\n\tfor ( i = 0; i < SIZE_OF_PALETTE; i ++ ) {\n\n\t\t//\n\t\t// Get the first palette entry's RGB.\n\t\t//\n\t\tfirst_r = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_g = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\t\tfirst_b = *first_palette_ptr;\n\t\tfirst_palette_ptr ++;\n\n\t\tsecond_palette_ptr = (unsigned char *) InterpolationPalette;\n\t\tfor  ( j = 0; j < SIZE_OF_PALETTE; j ++ ) {\n\t\t\t//\n\t\t\t// Get the second palette entry's RGB.\n\t\t\t//\n\t\t\tsecond_r = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_g = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\t\t\tsecond_b = *second_palette_ptr;\n\t\t\tsecond_palette_ptr ++;\n\n\t\t\t//\n\t\t\t// Now calculate the RGB halfway between the first and second colors.\n\t\t\t//\n\t\t\tdest_r = ( first_r + second_r ) >> 1;\n\t\t\tdest_g = ( first_g + second_g ) >> 1;\n\t\t\tdest_b = ( first_b + second_b ) >> 1;\n\n\t\t\t//\n\t\t\t// Now find the color in the palette that most closely matches the interpolated color.\n\t\t\t//\n\t\t\tindex_of_closest_color = 0;\n//\t\t\tclosest_distance = (256 * 256) * 3;\n\t\t\tclosest_distance = 500000;\n\t\t\tmatch_pal_ptr = (unsigned char *) InterpolationPalette;\n\t\t\tfor ( p = 0; p < SIZE_OF_PALETTE; p ++ ) {\n\t\t\t\tdiff_r = ( ((int) (*match_pal_ptr)) - dest_r );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_g = ( ((int) (*match_pal_ptr)) - dest_g );\n\t\t\t\tmatch_pal_ptr ++;\n\t\t\t\tdiff_b = ( ((int) (*match_pal_ptr)) - dest_b );\n\t\t\t\tmatch_pal_ptr ++;\n\n\t\t\t\tdistance = ( diff_r * diff_r ) + ( diff_g * diff_g ) + ( diff_b * diff_b );\n\t\t\t\tif ( distance < closest_distance ) {\n\t\t\t\t\tclosest_distance = distance;\n\t\t\t\t\tindex_of_closest_color = p;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPaletteInterpolationTable[ i ][ j ] = (unsigned char) index_of_closest_color;\n\t\t}\n\t}\n\n\t#endif\n\tInterpolationPaletteChanged = FALSE;\n\treturn;\n\n}\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Increase_Palette_Luminance -- increase contrast of colours in a palette                     *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to palette                                                                    *\n *           percentage increase of red                                                        *\n *           percentage increase of green                                                      *\n *           percentage increase of blue                                                       *\n *           cap value for colours                                                             *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/12/95 12:16PM ST : Created                                                            *\n *=============================================================================================*/\n\nvoid Increase_Palette_Luminance (unsigned char * palette , int red_percentage , int green_percentage , int blue_percentage , int cap)\n{\n\n\tunsigned\tint\tred;\n\tunsigned\tint\tgreen;\n\tunsigned\tint\tblue;\n\tfor (int i=0 ; i<SIZE_OF_PALETTE*3 ; i+=3) {\n\n\t\tred \t= (unsigned)*(palette+i);\n\t\tgreen = (unsigned)*(palette+i+1);\n\t\tblue\t= (unsigned)*(palette+i+2);\n\n\t\tred \t+= red*red_percentage/100;\n\t\tgreen\t+= green*green_percentage/100;\n\t\tblue\t+= blue*blue_percentage/100;\n\n\t\tred \t= MIN (cap, (int)red);\n\t\tgreen\t= MIN (cap, (int)green);\n\t\tblue\t= MIN (cap, (int)blue);\n\n\t\t*(palette+i)\t=(unsigned char)red;\n\t\t*(palette+i+1)\t=(unsigned char)green;\n\t\t*(palette+i+2)\t=(unsigned char)blue;\n\n\t}\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\nint\tCopyType\t=0;\n\n#ifdef WIN32\n/***************************************************************************\n * INTERPOLATE_2X_SCALE                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/06/1995  MG : Created.                                             *\n *=========================================================================*/\nvoid Interpolate_2X_Scale( GraphicBufferClass * source, GraphicViewPortClass * dest , char const * palette_file_name)\n{\n\t// Not needed. ST - 5/13/2019\n\tsource; dest; palette_file_name;\n#if (0)\n\tunsigned char\t* src_ptr;\n\tunsigned char\t* dest_ptr;\n\tunsigned char\t* last_dest_ptr;\n\tunsigned char\t* end_of_source;\n\tint\tsrc_width;\n\tint\tdest_width;\n//\tint\twidth_counter;\n\tBOOL\tsource_locked = FALSE;\n\tBOOL\tdest_locked = FALSE;\n\n\n\t/*\n\t**If a palette table exists on disk then read it in otherwise create it\n\t*/\n\tif (InterpolationPaletteChanged) {\n\t\tif (palette_file_name) {\n\t\t\tRead_Interpolation_Palette(palette_file_name);\n\t\t}\n\t\tif (InterpolationPaletteChanged) {\n\t\t\tCreate_Palette_Interpolation_Table();\n\t\t}\n\t}\n\n\t/*\n\t** Write the palette table to disk so we don't have to create it again next time\n\t*/\n\tif (palette_file_name) {\n\t\tWrite_Interpolation_Palette(palette_file_name);\n\t}\n\tif ( dest == &SeenBuff ) Hide_Mouse();\n\n\tWait_Blit();\n\n\t/*\n\t** Lock video surfaces if required\n\t*/\n\tif (source->Get_IsDirectDraw()) {\n\t\tif (!source->Lock()) {\n\t\t\tif (dest == &SeenBuff) Show_Mouse();\n\t\t\treturn;\n\t\t}\n\t\tsource_locked = TRUE;\n\t}\n\tif (dest->Get_IsDirectDraw()) {\n\t\tif (!dest->Lock()) {\n\t\t\tif (source_locked) {\n\t\t\t\tsource->Unlock();\n\t\t\t}\n\t\t\tif (dest == &SeenBuff) Show_Mouse();\n\t\t\treturn;\n\t\t}\n\t\tdest_locked = TRUE;\n\t}\n\n\n\t//\n\t// Get pointers to the source and destination buffers.\n\t//\n\tsrc_ptr = (unsigned char *) source->Get_Offset();\n\tdest_ptr = (unsigned char *) dest->Get_Offset();\n\tend_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );\n\n\t//\n\t// Get width of source and dest buffers.\n\t//\n\tsrc_width = source->Get_Width();\n\tdest_width = 2*(dest->Get_Width() + dest->Get_XAdd() + dest->Get_Pitch());\n\tlast_dest_ptr = dest_ptr;\n\n\t/*\n\t** Call the appropriate assembly language copy routine\n\t*/\n#if (1)\n\tswitch (CopyType) {\n\t\tcase 0:\n\t\t\tAsm_Interpolate ( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tAsm_Interpolate_Line_Double( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tAsm_Interpolate_Line_Interpolate( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);\n\t\t\tbreak;\n\t}\n#endif\n\n#if (0)\n\t//\n\t// Copy over the first pixel (upper left).\n\t//\n\t*dest_ptr = *src_ptr;\n\tsrc_ptr ++;\n\tdest_ptr ++;\n\n\t//\n\t// Scale copy.\n\t//\n\twidth_counter = 0;\n\twhile ( src_ptr < end_of_source ) {\n\n\t\t//\n\t\t// Blend this pixel with the one to the left and place this new color in the dest buffer.\n\t\t//\n\t\t*dest_ptr = PaletteInterpolationTable[ (*src_ptr) ][ (*( src_ptr - 1 )) ];\n\t\tdest_ptr ++;\n\n\t\t//\n\t\t// Now place the source pixel into the dest buffer.\n\t\t//\n\t\t*dest_ptr = *src_ptr;\n\n\t\tsrc_ptr ++;\n\t\tdest_ptr ++;\n\n\t\twidth_counter ++;\n\t\tif ( width_counter == src_width ) {\n\t\t\twidth_counter = 0;\n\t\t\tlast_dest_ptr += dest_width;\n\t\t\tdest_ptr = last_dest_ptr;\n\t\t}\n\t}\n\n#endif\n\tif (source_locked) source->Unlock();\n\tif (dest_locked) dest->Unlock();\n\tif (dest == &SeenBuff) Show_Mouse();\n\n//BG\tlong *longptr = (long *)&PaletteInterpolationTable[0][0];\n//BG\tMono_Printf(\"Clock cycles: %08x\\n\",*longptr);\n#endif\n}\n#endif\n\n\n\n\n\n"
  },
  {
    "path": "REDALERT/INTRO.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INTRO.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTRO.H                                                      *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : May 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : May 8, 1995  [BWG]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n#if (0) //PG\nVQAHandle * Open_Movie(char * name);\nVQAHandle * Open_Movie(char * name)\n{\n\tif (!Debug_Quiet && Get_Digi_Handle() != -1) {\n\t\tAnimControl.OptionFlags |= VQAOPTF_AUDIO;\n\t} else {\n\t\tAnimControl.OptionFlags &= ~VQAOPTF_AUDIO;\n\t}\n\n\tVQAHandle * vqa = VQA_Alloc();\n\tif (vqa) {\n\t\tVQA_Init(vqa, MixFileHandler);\n\n\t\tif (VQA_Open(vqa, name, &AnimControl) != 0) {\n\t\t\tVQA_Free(vqa);\n\t\t\tvqa = 0;\n\t\t}\n\t}\n\treturn(vqa);\n}\n#endif\n\n/***********************************************************************************************\n * Choose_Side -- play the introduction movies, select house                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   5/08/1995 BWG : Created.                                                                  *\n *=============================================================================================*/\nvoid Choose_Side(void)\t\t//\tajw - In RA, all this did was play a movie. Denzil is using it in its original sense.\n{\n\n\tWhom = HOUSE_GOOD;\n\n#if (0)\t//PG\n\tif (Special.IsFromInstall) {\n\t\t#ifdef DVD // Denzil\n\t\tif( Using_DVD() )\n\t\t{\n\t\t\tHide_Mouse();\n\t\t\tLoad_Title_Page();\n\t\t\tGamePalette = CCPalette;\n\t\t\tHidPage.Blit(SeenPage);\n\t\t\tCCPalette.Set();\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\tShow_Mouse();\n\t\t\t\n\t\t\tswitch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET))\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\t\tCurrentCD = 0;\n\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\tCurrentCD = 1;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tHide_Mouse();\n\t\t\tBlackPalette.Set(FADE_PALETTE_SLOW);\n\t\t\tSeenPage.Clear();\n\t\t}\n\t\t#endif\n\t\t\n\t\tPlay_Movie(VQ_INTRO_MOVIE, THEME_NONE, false);\n\t}\n#endif\n//\tScen.ScenPlayer = SCEN_PLAYER_GREECE;\n\n#ifdef OBSOLETE\n\tstatic char const _yellowpal[]={0x0,0x0,0xC9,0x0,0xBA,0x0,0x93,0x0,0x61,0x0,0x0,0x0,0x0,0x0,0xEE,0x0};\n\tstatic char const _redpal[]   ={0x0,0x0,0xA8,0x0,0xD9,0x0,0xDA,0x0,0xE1,0x0,0x0,0x0,0x0,0x0,0xD4,0x0};\n\tstatic char const _graypal[]  ={0x0,0x0,0x17,0x0,0x10,0x0,0x12,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0x1C,0x0};\n\n\tvoid * anim;\n\tVQAHandle * gdibrief=0, * nodbrief=0;\n\tvoid const * staticaud, * oldfont;\n\tvoid const * speechg, * speechn, * speech;\n\tint statichandle, speechhandle, speechplaying = 0;\n\tint oldfontxspacing = FontXSpacing;\n\tint setpalette = 0;\n\n\tint frame = 0, endframe = 255, selection = 0, lettersdone = 0;\n\n\tHide_Mouse();\n/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\n\tCall_Back();\n\n\tstaticaud = Load_Alloc_Data(CCFileClass(\"STRUGGLE.AUD\"));\n\tspeechg = Load_Alloc_Data(CCFileClass(\"GDI_SLCT.AUD\"));\n\tspeechn = Load_Alloc_Data(CCFileClass(\"NOD_SLCT.AUD\"));\n\n//\tstaticaud = MixFileClass::Retrieve(\"STRUGGLE.AUD\");\n//\tspeechg = MixFileClass::Retrieve(\"GDI_SLCT.AUD\");\n//\tspeechn = MixFileClass::Retrieve(\"NOD_SLCT.AUD\");\n\n\tanim = Open_Animation(\"CHOOSE.WSA\", NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), Palette);\n\tCall_Back();\n\n\tnodbrief = Open_Movie(\"NOD1PRE.VQA\");\n\tCall_Back();\n\tgdibrief = Open_Movie(\"GDI1.VQA\");\n\n\tif (Special.IsFromInstall) {\n\t\tSet_Video_Mode(MCGA_MODE);\n\t\tPreserveVQAScreen = 1;\n//\t\tHide_Mouse();\n\t\tPlay_Movie(\"INTRO2\", THEME_NONE, false);\n\t\tShow_Mouse();\n\t}\n\n\tHidPage.Clear();\n\tif (!Special.IsFromInstall) {\n\t\tSeenPage.Clear();\n//\t\tSet_Palette(Palette);\n\t\tPalette.Set();\n\t} else {\n\t\tsetpalette = 1;\n\t}\n\n\tstatichandle = Play_Sample(staticaud, 255, 64);\n\tAlloc_Object(new ScorePrintClass(TXT_GDI_NAME,   0, 180, _yellowpal));\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_GDI_NAME2,  0, 187, _yellowpal));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_NOD_NAME, 180, 180, _redpal));\n\n#ifdef GERMAN\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 57, 190, _graypal));\n#else\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 103, 194, _graypal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SEL_TRANS, 103, 190, _graypal));\n#endif\n#endif\n\tKeyboard->Clear();\n\n\twhile (endframe != frame || (speechplaying && Is_Sample_Playing(speech)) ) {\n\t\tAnimate_Frame(anim, HidPage, frame++);\n\t\tHide_Mouse();\n\t\tif (setpalette) {\n\t\t\tWait_Vert_Blank(VertBlank);\n\t\t\t//Set_Palette(Palette);\n\t\t\tPalette.Set();\n\t\t\tsetpalette = 0;\n\t\t}\n\t\tHidPage.Blit(SeenPage, 0, 22, 0, 22, 320, 156);\n\t\tShow_Mouse();\n\n\t\tif (!Is_Sample_Playing(staticaud)) statichandle = Play_Sample(staticaud, 255, 64);\n\t\tCall_Back_Delay(3);\t// delay only if haven't clicked\n\n\t\t/* keep the mouse hidden until the letters are thru printing */\n\t\tif (!lettersdone) {\n\t\t\tlettersdone = true;\n\t\t\tfor (int i=0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) lettersdone = 0;\n\t\t\tif (lettersdone) {\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t}\n\t\tif (frame >= Get_Animation_Frame_Count(anim)) frame = 0;\n\t\tif (Keyboard->Check() && endframe == 255) {\n\t\t\tif ((Keyboard->Get() & 0xFF) == KN_LMOUSE) {\n\t\t\t\tif ((MouseQY > 48) && (MouseQY < 150)) {\n\t\t\t\t\tif ((MouseQX > 18) && (MouseQX < 148)) {\n\n\t\t\t\t\t// Chose GDI\n\t\t\t\t\t\tWhom = HOUSE_GOOD;\n\t\t\t\t\t\tScenPlayer = SCEN_PLAYER_GDI;\n\t\t\t\t\t\tendframe = 0;\n\t\t\t\t\t\tspeechhandle = Play_Sample(speechg);\n\t\t\t\t\t\tspeechplaying = true;\n\t\t\t\t\t\tspeech = speechg;\n\t\t\t\t\t} else if ((MouseQX > 160) && (MouseQX < 300)) {\n\t\t\t\t\t// Chose Nod\n\t\t\t\t\t\tselection = 1;\n\t\t\t\t\t\tendframe = 14;\n\t\t\t\t\t\tWhom = HOUSE_BAD;\n\t\t\t\t\t\tScenPlayer = SCEN_PLAYER_NOD;\n\t\t\t\t\t\tspeechhandle = Play_Sample(speechn);\n\t\t\t\t\t\tspeechplaying = true;\n\t\t\t\t\t\tspeech = speechn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tHide_Mouse();\n\tClose_Animation(anim);\n\n\t// erase the \"choose side\" text\n\tSeenBuff.Fill_Rect(0, 180, 319, 199, 0);\n\n\tKeyboard->Clear();\n\n\t/* play the scenario 1 briefing movie */\n\tif (Whom == HOUSE_GOOD) {\n\t\tif (nodbrief) {\n\t\t\tVQA_Close(nodbrief);\n\t\t\tVQA_Free(nodbrief);\n\t\t}\n\t\tif (gdibrief) {\n#ifdef CHEAT_KEYS\n#else\n\t\t\tVQA_Play(gdibrief, VQAMODE_RUN);\n#endif\n\t\t\tVQA_Close(gdibrief);\n\t\t\tVQA_Free(gdibrief);\n\t\t}\n\t} else {\n\t\tif (gdibrief) {\n\t\t\tVQA_Close(gdibrief);\n\t\t\tVQA_Free(gdibrief);\n\t\t}\n\t\tif (nodbrief) {\n#ifdef CHEAT_KEYS\n#else\n\t\t\tVQA_Play(nodbrief, VQAMODE_RUN);\n#endif\n\t\t\tVQA_Close(nodbrief);\n\t\t\tVQA_Free(nodbrief);\n\t\t}\n\t}\n\n/* get rid of all the animating objects */\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\n\tif (Whom == HOUSE_GOOD) {\n\t\t/*\n\t\t** Make sure the screen's fully clear after the movie plays\n\t\t*/\n\t\tSeenPage.Clear();\n\n\t\tBlackPalette.Adjust(WhitePalette, 0x08);\n\t\tBlackPalette.Set();\n\t\tBlackPalette.Adjust(0xFF);\n\t\tBlackPalette.Set();\n\n//\t\tmemset(BlackPalette, 0x01, 768);\n//\t\tSet_Palette(BlackPalette);\n//\t\tmemset(BlackPalette, 0x00, 768);\n\t} else {\n\t\tPreserveVQAScreen = 1;\n\t}\n\tFree(staticaud);\n\tFree(speechg);\n\tFree(speechn);\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n#endif\n}\n"
  },
  {
    "path": "REDALERT/INTRO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/INTRO.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : INTRO.H                                                      *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : May 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : May 8, 1995  [BWG]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef INTRO_H\n#define INTRO_H\n\nvoid Choose_Side(void);\n\n#endif\n"
  },
  {
    "path": "REDALERT/IOMAP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IOMAP.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IOMAP.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : January 16, 1995                                             *\n *                                                                                             *\n *                  Last Update : March 12, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * All map-related loading/saving routines should go in this module, so it can be overlayed.   *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   CellClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   CellClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   CellClass::Load -- Reads from a save game file.                                           *\n *   CellClass::Save -- Write to a save game file.                                             *\n *   CellClass::Should_Save -- Should the cell be written to disk?                             *\n *   DisplayClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   DisplayClass::Decode_Pointers -- decodes pointers for load/save                           *\n *   MapClass::Code_Pointers -- codes class's pointers for load/save                           *\n *   MapClass::Decode_Pointers -- decodes pointers for load/save                               *\n *   MouseClass::Load -- Loads from a save game file.                                          *\n *   MouseClass::Save -- Saves to a save game file.                                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * CellClass::Should_Save -- Should the cell be written to disk?                               *\n *                                                                                             *\n *    This function will determine if the cell needs to be written to disk. Any cell that      *\n *    contains special data should be written to disk.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Should this cell's data be written to disk?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Should_Save(void) const\n{\n\tstatic CellClass const _identity_cell;\n\n\treturn(memcmp(&_identity_cell, this, sizeof(*this)) != 0);\n}\n\n\n/***********************************************************************************************\n * CellClass::Load -- Loads from a save game file.                                             *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Load(Straw & file)\n{\n\tfile.Get(this, sizeof(*this));\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Save -- Write to a save game file.                                               *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool CellClass::Save(Pipe & file) const\n{\n\tfile.Put(this, sizeof(*this));\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * CellClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CellClass::Code_Pointers(void)\n{\n\tif (Cell_Occupier() != NULL) {\n\t\tOccupierPtr = (ObjectClass *)OccupierPtr->As_Target();\n\t}\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] != NULL && Overlapper[index]->IsActive) {\n\t\t\tOverlapper[index] = (ObjectClass *)Overlapper[index]->As_Target();\n\t\t} else {\n\t\t\tOverlapper[index] = NULL;\n\t\t}\n\t}\n\n\tassert(CTFFlag == NULL);\n}\n\n\n/***********************************************************************************************\n * CellClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid CellClass::Decode_Pointers(void)\n{\n\tif (OccupierPtr != NULL) {\n\t\tOccupierPtr = As_Object((TARGET)OccupierPtr, false);\n\t\tassert(OccupierPtr != NULL);\n\t}\n\n\tfor (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {\n\t\tif (Overlapper[index] != NULL) {\n\t\t\tOverlapper[index] = As_Object((TARGET)Overlapper[index], false);\n\t\t\tassert(Overlapper[index] != NULL);\n\t\t}\n\t}\n\n\tCTFFlag = NULL;\n}\n\n\n/***********************************************************************************************\n * MouseClass::Load -- Loads from a save game file.                                            *\n *                                                                                             *\n * Loading the map is very complicated.  Here are the steps:                                   *\n * - Read the Theater for this save-game                                                       *\n * - call Init_Theater to perform theater-specific inits                                       *\n * - call Free_Cells to free the cell array, because loading the map object will overwrite     *\n *   the pointer to the cell array                                                             *\n * - read the map object from disk                                                             *\n * - call Alloc_Cells to re-allocate the cell array                                            *\n * - call Init_Cells to set the cells to a known state, because not every cell will be loaded  *\n * - read the cell objects into the cell array                                                 *\n * - After the map & all objects have been loaded & the pointers decoded, Init_IO() >MUST< be  *\n *   called to restore the map's button list to the proper state.                              *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nbool MouseClass::Load(Straw & file)\n{\n\t/*\n\t**\tLoad Theater:  Even though this value is located in the DisplayClass,\n\t**\tit must be loaded first so initialization can be done before any other\n\t**\tmap data is loaded.  If initialization isn't done first, data read from\n\t**\tdisk will be over-written when initialization occurs.  This code must\n\t**\tgo in the most-derived Map class.\n\t*/\n\tTheaterType theater;\n\tif (file.Get(&theater, sizeof(theater)) != sizeof(theater)) {\n\t\treturn(false);\n\t}\n\n#ifdef WIN32\nLastTheater = THEATER_NONE;\n#endif\n\n\t/*\n\t** Remove any old theater specific uncompressed shapes\n\t*/\n#ifdef WIN32\n//\tif (theater != LastTheater) {\n\t\tReset_Theater_Shapes();\n//\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tInit display mixfiles\n\t*/\n\tInit_Theater(theater);\n\tTerrainTypeClass::Init(Scen.Theater);\n\tTemplateTypeClass::Init(Scen.Theater);\n\tOverlayTypeClass::Init(Scen.Theater);\n\tUnitTypeClass::Init(Scen.Theater);\n\tInfantryTypeClass::Init(Scen.Theater);\n\tBuildingTypeClass::Init(Scen.Theater);\n\tBulletTypeClass::Init(Scen.Theater);\n\tAnimTypeClass::Init(Scen.Theater);\n\tAircraftTypeClass::Init(Scen.Theater);\n\tVesselTypeClass::Init(Scen.Theater);\n\tSmudgeTypeClass::Init(Scen.Theater);\n\n\t//LastTheater = Scen.Theater;\n\n\t/*\n\t** Free the cell array, because we're about to overwrite its pointers\n\t*/\n\tFree_Cells();\n\n\t/*\n\t** Read the entire map object in.  Only read in sizeof(MouseClass), so if we're\n\t** in editor mode, none of the map editor object is read in.\n\t*/\n\tfile.Get(this, sizeof(*this));\n#ifdef SCENARIO_EDITOR\n\tnew(this) MapEditClass(NoInitClass());\n#else\n\tnew(this) MouseClass(NoInitClass());\n#endif\n\n\t/*\n\t** Reallocate the cell array\n\t*/\n\tAlloc_Cells();\n\n\t/*\n\t** Init all cells to empty\n\t*/\n\tInit_Cells();\n\n\t/*\n\t**\tRead # cells saved\n\t*/\n\tint count;\n\tif (file.Get(&count, sizeof(count)) != sizeof(count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead cells\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tCELL cell = 0;\n\t\tif (file.Get(&cell, sizeof(cell)) != sizeof(cell)) {\n\t\t\treturn(false);\n\t\t}\n\n\t\tif (!(*this)[cell].Load(file)) {\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\tLastTheater = Scen.Theater;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Save -- Save to a save game file.                                               *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/26/1996 JLB : Cleaned up.                                                              *\n *=============================================================================================*/\nbool MouseClass::Save(Pipe & file) const\n{\n\t/*\n\t**\tSave Theater >first<\n\t*/\n\tTheaterType theater = Scen.Theater;\n\tfile.Put(&theater, sizeof(theater));\n\n\tfile.Put(this, sizeof(*this));\n\n\t/*\n\t**\tCount how many cells will be saved.\n\t*/\n\tint count = 0;\n\tCellClass const * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (cellptr->Should_Save()) {\n\t\t\tcount++;\n\t\t}\n\t\tcellptr++;\n\t}\n\n\t/*\n\t**\twrite out count of the cells.\n\t*/\n\tfile.Put(&count, sizeof(count));\n\n\t/*\n\t**\tSave cells that need it\n\t*/\n\tcellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tif (cellptr->Should_Save()) {\n\t\t\tfile.Put(&cell, sizeof(cell));\n\t\t\tcellptr->Save(file);\n\t\t\tcount--;\n\t\t}\n\t\tcellptr++;\n\t}\n\n\tif (count != 0) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid DisplayClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode PendingObjectPtr.\n\t*/\n\tif (PendingObjectPtr) {\n\t\tPendingObjectPtr = (ObjectClass *)PendingObjectPtr->As_Target();\n\t}\n\n\t/*\n\t** Fix for saving game while in structure placement mode. ST - 4/15/2020 2:41PM\n\t*/\n\tmemset(CursorShapeSave, 0, sizeof(CursorShapeSave));\n\tif (CursorSize && CursorSize != CursorShapeSave) {\n\n\t\tint save_buffer_element_size = sizeof(CursorShapeSave) / sizeof(CursorShapeSave[0]);\n\t\t\n\t\tint index = 0;\n\n\t\twhile (index < save_buffer_element_size - 2 && CursorSize[index] != REFRESH_EOL) {\n\t\t\tCursorShapeSave[index] = CursorSize[index];\n\t\t\tindex++;\n\t\t}\n\t\tCursorShapeSave[index] = REFRESH_EOL;\n\t}\n\n\t/*\n\t**\tChain to parent.\n\t*/\n\tMapClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * DisplayClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid DisplayClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode PendingObjectPtr.  We can't decode PendingObject here, because we'd\n\t**\thave to reference PendingObjectPtr->Class_Of(), and the object that\n\t**\tPendingObjectPtr is pointing to hasn't been decoded yet.  Since we can't\n\t**\tdecode PendingObjectPtr, we can't set the placement cursor shape here\n\t**\teither.  These have to be done as last-minute fixups.\n\t*/\n\tif (PendingObjectPtr) {\n\t\tPendingObjectPtr = As_Object((TARGET)PendingObjectPtr, false);\n\t\tassert(PendingObjectPtr != NULL);\n\t}\n\n\tif (CursorSize) {\n\t\tCursorSize = CursorShapeSave;\n\t}\n\n\t/*\n\t**\tChain to parent.\n\t*/\n\tMapClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * MapClass::Code_Pointers -- codes class's pointers for load/save                             *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid MapClass::Code_Pointers(void)\n{\n\tCELL cell;\n\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t(*this)[cell].Flag_Destroy();\n\t}\n\n\tCellClass * cellptr = &(*this)[(CELL)0];\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tcellptr->Code_Pointers();\n\t\tcellptr++;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Decode_Pointers -- decodes pointers for load/save                                 *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid MapClass::Decode_Pointers(void)\n{\n\tCellClass * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tcellptr->Decode_Pointers();\n\t\tcellptr++;\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/IOOBJ.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IOOBJ.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : IOOBJ.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : January 16, 1995                                             *\n *                                                                                             *\n *                  Last Update : May 13, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   BulletClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   BulletClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   CargoClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   CargoClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   FactoryClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   FactoryClass::Decode_Pointers -- decodes pointers for load/save                           *\n *   FootClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   FootClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   HouseClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   HouseClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   LayerClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   LayerClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   LayerClass::Load -- Reads from a save game file.                                          *\n *   LayerClass::Save -- Write to a save game file.                                            *\n *   ObjectClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   ObjectClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   RadioClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   RadioClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   ReinforcementClass::Code_Pointers -- codes class's pointers for load/save                 *\n *   ReinforcementClass::Decode_Pointers -- decodes pointers for load/save                     *\n *   ScoreClass::Code_Pointers -- codes class's pointers for load/save                         *\n *   ScoreClass::Decode_Pointers -- decodes pointers for load/save                             *\n *   TeamClass::Code_Pointers -- codes class's pointers for load/save                          *\n *   TeamClass::Decode_Pointers -- decodes pointers for load/save                              *\n *   TeamTypeClass::Code_Pointers -- codes class's pointers for load/save                      *\n *   TeamTypeClass::Decode_Pointers -- decodes pointers for load/save                          *\n *   TechnoClass::Code_Pointers -- codes class's pointers for load/save                        *\n *   TechnoClass::Decode_Pointers -- decodes pointers for load/save                            *\n *   TriggerClass::Code_Pointers -- codes class's pointers for load/save                       *\n *   TriggerClass::Decode_Pointers -- decodes pointers for load/save                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/***********************************************************************************************\n * TeamTypeClass::Code_Pointers -- codes class's pointers for load/save                        *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TeamTypeClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode the Class array\n\t*/\n\tfor (int i = 0; i < ClassCount; i++) {\n\t\tMembers[i].Class = (TechnoTypeClass *)Members[i].Class->As_Target();\n\t\tassert(Members[i].Class != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamTypeClass::Decode_Pointers -- decodes pointers for load/save                            *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TeamTypeClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode the Class array\n\t*/\n\tfor (int i = 0; i < ClassCount; i++) {\n\t\tMembers[i].Class =  As_TechnoType((TARGET)Members[i].Class);\n\t\tassert(Members[i].Class != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   05/13/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid TeamClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode the 'Member'\n\t*/\n\tif (Member) {\n\t\tMember = (FootClass *)Member->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * TeamClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nvoid TeamClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode the 'Member'\n\t*/\n\tif (Member) {\n\t\tMember = (FootClass *)As_Techno((TARGET)Member, false);\n\t\tassert(Member != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Code_Pointers(void)\n{\n\tAction1.Code_Pointers();\n\tAction2.Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * TriggerClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TriggerTypeClass::Decode_Pointers(void)\n{\n\tAction1.Decode_Pointers();\n\tAction2.Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid BulletClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'Payback'\n\t*/\n\tif (Payback) {\n\t\tPayback = (TechnoClass *)Payback->As_Target();\n\t}\n\n\t/*\n\t**\tChain to parent\n\t*/\n\tObjectClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * BulletClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid BulletClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'Payback'\n\t*/\n\tif (Payback) {\n\t\tPayback = As_Techno((TARGET)Payback, false);\n\t\tassert(Payback != NULL);\n\t}\n\n\t/*\n\t**\tChain to parent\n\t*/\n\tObjectClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Code_Pointers -- codes class's pointers for load/save                         *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FactoryClass::Code_Pointers(void)\n{\n\tif (Object) {\n\t\tObject = (TechnoClass *)Object->As_Target();\n\t}\n\n\t((HouseClass *&)House) = (HouseClass *)House->Class->House;\n}\n\n\n/***********************************************************************************************\n * FactoryClass::Decode_Pointers -- decodes pointers for load/save                             *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FactoryClass::Decode_Pointers(void)\n{\n\tif (Object) {\n\t\tObject = As_Techno((TARGET)Object, false);\n\t\tassert(Object != NULL);\n\t}\n\n\tunsigned int house_ptr_val = *((unsigned int*)&House);\n\t((HouseClass *&)House) = HouseClass::As_Pointer((HousesType)house_ptr_val);\n\n\tassert(House != NULL);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Load -- Loads from a save game file.                                            *\n *                                                                                             *\n * INPUT:   file  -- The file to read the cell's data from.                                    *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool LayerClass::Load(Straw & file)\n{\n\t/*\n\t**\tRead # elements in the layer\n\t*/\n\tint count;\n\tif (file.Get(&count, sizeof(count)) != sizeof(count)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tClear the array\n\t*/\n\tClear();\n\n\t/*\n\t**\tRead in all array elements\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tObjectClass * ptr;\n\t\tif (file.Get(&ptr, sizeof(ObjectClass *)) != sizeof(ObjectClass *)) {\n\t\t\treturn(false);\n\t\t}\n\t\tAdd(ptr);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Save -- Write to a save game file.                                              *\n *                                                                                             *\n * INPUT:   file  -- The file to write the cell's data to.                                     *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool LayerClass::Save(Pipe & file) const\n{\n\t/*\n\t**\tSave # array elements\n\t*/\n\tint count = Count();\n\tfile.Put(&count, sizeof(count));\n\n\t/*\n\t**\tSave all elements\n\t*/\n\tfor (int index = 0; index < count; index++) {\n\t\tObjectClass * ptr = (*this)[index];\n\t\tfile.Put(&ptr, sizeof(ObjectClass *));\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LayerClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LayerClass::Code_Pointers(void)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tObjectClass * obj = (*this)[index];\n\t\tassert(obj != NULL);\n\t\t(*this)[index] = (ObjectClass *)(obj->As_Target());\n\t}\n}\n\n\n/***********************************************************************************************\n * LayerClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LayerClass::Decode_Pointers(void)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tTARGET target = (TARGET)(*this)[index];\n\t\t(*this)[index] = (ObjectClass *)As_Object(target, false);\n\t\tassert((*this)[index] != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * HouseClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid HouseClass::Code_Pointers(void)\n{\n}\n\n\n/***********************************************************************************************\n * HouseClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid HouseClass::Decode_Pointers(void)\n{\n\t/*\n\t** Re-assign the house's remap table (for multiplayer game loads)\n\t** Loading the house from disk will have over-written the house's RemapTable, so\n\t** Init_Data() is called to reset it to a valid pointer.\n\t*/\n\t\n\tInit_Data(RemapColor, ActLike, Credits);\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ScoreClass::Code_Pointers(void)\n{\n\tRealTime.Stop();\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ScoreClass::Decode_Pointers(void)\n{\n\tRealTime.Start();\n}\n\n\n/***********************************************************************************************\n * FootClass::Code_Pointers -- codes class's pointers for load/save                            *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FootClass::Code_Pointers(void)\n{\n\tif (Member != NULL && Member->IsActive) {\n\t\tMember = (FootClass *)Member->As_Target();\n\t} else {\n\t\tMember = TARGET_NONE;\n\t}\n\n\tTechnoClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * FootClass::Decode_Pointers -- decodes pointers for load/save                                *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid FootClass::Decode_Pointers(void)\n{\n\tif ((TARGET)Member != TARGET_NONE) {\n\t\tMember = (FootClass *)As_Techno((TARGET)Member, false);\n\t\tassert(Member != NULL);\n\t}\n\n\tTechnoClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * RadioClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid RadioClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'Radio'\n\t*/\n\tif (Radio) {\n\t\tRadio = (RadioClass *)Radio->As_Target();\n\t}\n\n\tMissionClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * RadioClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid RadioClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'Radio'\n\t*/\n\tif (Radio) {\n\t\tRadio = As_Techno((TARGET)Radio, false);\n\t\tassert(Radio != NULL);\n\t}\n\n\tMissionClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TechnoClass::Code_Pointers(void)\n{\n\tCargoClass::Code_Pointers();\n\tRadioClass::Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * TechnoClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid TechnoClass::Decode_Pointers(void)\n{\n\tCargoClass::Decode_Pointers();\n\tRadioClass::Decode_Pointers();\n}\n\n\n/***********************************************************************************************\n * CargoClass::Code_Pointers -- codes class's pointers for load/save                           *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CargoClass::Code_Pointers(void)\n{\n\t/*\n\t**\tCode 'CargoHold'\n\t*/\n\tif (CargoHold) {\n\t\tCargoHold = (FootClass *)CargoHold->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * CargoClass::Decode_Pointers -- decodes pointers for load/save                               *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid CargoClass::Decode_Pointers(void)\n{\n\t/*\n\t**\tDecode 'CargoHold'\n\t*/\n\tif (CargoHold) {\n\t\tCargoHold = (FootClass *)As_Techno((TARGET)CargoHold, false);\n\t\tassert(CargoHold != NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Code_Pointers -- codes class's pointers for load/save                          *\n *                                                                                             *\n * This routine \"codes\" the pointers in the class by converting them to a number               *\n * that still represents the object pointed to, but isn't actually a pointer.  This            *\n * allows a saved game to properly load without relying on the games data still                *\n * being in the exact same location.                                                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ObjectClass::Code_Pointers(void)\n{\n\tif (Next) {\n\t\tNext = (ObjectClass *)Next->As_Target();\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Decode_Pointers -- decodes pointers for load/save                              *\n *                                                                                             *\n * This routine \"decodes\" the pointers coded in Code_Pointers by converting the                *\n * code values back into object pointers.                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/02/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid ObjectClass::Decode_Pointers(void)\n{\n\tif (Next) {\n\t\tNext = As_Object((TARGET)Next, false);\n\t\tassert(Next != NULL);\n\t}\n}\n"
  },
  {
    "path": "REDALERT/IPX.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPX.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX.CPP                                  *\n *                                                                         *\n *                   Programmer : Barry Nance\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t from Client/Server LAN Programming\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t Westwood-ized by Bill Randolph\t\t\t\t*\n *                                                                         *\n *                   Start Date : December 14, 1994                        *\n *                                                                         *\n *                  Last Update : December 15, 1994   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Pitfalls:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Never try to use a closed socket; always check the return code from\t*\n *   IPX_Open_Socket().\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Always give IPX an outstanding ECB for listening, before you send.\t\t*\n * - It turns out that IPX is pretty bad about saving registers, so if\t\t*\n *   you have any register variables in your program, they may get\t\t\t*\n *   trashed.  To circumvent this, all functions in this module save &\t\t*\n *   restore the registers before invoking any IPX or NETX function.\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   IPX_SPX_Installed -- checks for installation of IPX/SPX               *\n *   IPX_Open_Socket -- opens an IPX socket for sending or receiving       *\n *   IPX_Close_Socket -- closes an open socket                             *\n *   IPX_Get_Connection_Number -- gets local Connection Number\t\t\t\t\t*\n *   IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user  *\n *   IPX_Get_Internet_Address -- gets Network Number & Node Address\t\t\t*\n *   IPX_Get_User_ID -- gets user ID from Connection Number                *\n *   IPX_Listen_For_Packet -- commands IPX to listen for a packet          *\n *   IPX_Send_Packet -- commands IPX to send a packet                      *\n *   IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB        *\n *   IPX_Cancel_Event -- cancels an operation in progress                  *\n *   Let_IPX_Breath -- gives IPX some CPU time                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n//#include <i86.h>\n#include \"ipx.h\"\n\n#ifdef WIN32\n#include \"ipx95.h\"\n#endif\t//WIN32\n\n\n// Turn off \"expression is not meaningful\".\n//#pragma warning 628 9\n\n\n/***************************************************************************\n * IPX_SPX_Installed -- checks for installation of IPX/SPX                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = not installed; 1 = IPX only, 2 = IPX and SPX are installed\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/14/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPX_SPX_Installed(void)\n{\n\treturn false;\n#ifdef WIN32\n\n#ifdef TIBERIAN_SUN\n\treturn(false);\n#else\n#if (0)//PG\n\tif ( Load_IPX_Dll () ){\n\t\treturn ( IPX_Initialise() );\n\t}else{\n\t\treturn(false);\n\t}\n#endif\n#endif\n\n#else\t//WIN32\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tInit all registers to 0's\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0, sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0, sizeof(rmi));\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call, function 0x300\n\t//------------------------------------------------------------------------\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x002f;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the real-mode interrupt handler.\n\t//\tTo test for the presence of IPX, set AH to 0x7a, AL to 0, and invoke\n\t//\tinterrupt 0x2f (the \"multiplex\" interrupt).  If IPX is installed,\n\t//\tAL will be 0xff, and ES:DI will contain the IPX/SPX function address.\n\t//------------------------------------------------------------------------\n\trmi.eax = 0x00007a00;\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tIf IPX isn't there, return 0\n\t//------------------------------------------------------------------------\n\tif ( (rmi.eax & 0x00ff) != 0xff) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTest for SPX by invoking the IPX_SPX function with BX = 0x10, and AL = 0.\n\t//\tIf SPX is present, AL will be 0xff.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = 0x00000010;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tSPX is installed; return '2'\n\t//------------------------------------------------------------------------\n\tif ( (rmi.eax & 0x00ff) == 0xff) {\n\t\treturn(2);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSPX is not installed; return '1'\n\t//------------------------------------------------------------------------\n\treturn(1);\n#endif\t//WIN32\n\n}\t/* end of IPX_SPX_Installed */\n\n\n/***************************************************************************\n * IPX_Open_Socket -- opens an IPX socket for sending or receiving         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tthe socket number to open\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t-1 = IPX not installed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t0xfe = socket table is full\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t0xff = socket is already open\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe application must define its socket number carefully.  Use\t\t\t*\n *\t\tvalues from 0x4000 to 0x8000 for custom socket numbers.  The app\t\t*\n *\t\tmust know its own socket number as well as the socket number of\t\t*\n *\t\ta destination workstation.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\n\nint IPX_Open_Socket(unsigned short socket)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tOpen the socket:\n\t//\tDX = socket number\n\t//\tAL = 0 for short-lived socket, 0xff for long-lived socket\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG (&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF (&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_OPEN_SOCKET;\t\t\t// function code\n\trmi.edx = socket;\t\t\t\t\t\t// desired socket #\n\trmi.eax = 0x00ff;\t\t\t\t\t\t// make this a long-lived socket\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0xff);\n\n\treturn(rc);\n\n}\t/* end of IPX_Open_Socket */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Close_Socket -- closes an open socket                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tsocket number to close\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = ok, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\n\nint IPX_Close_Socket(unsigned short socket)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tClose the socket:\n\t//\tDX = socket number\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_CLOSE_SOCKET;\n\trmi.edx = socket;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\treturn(0);\n\n}\t/* end of IPX_Close_Socket */\n#endif\t\t//WIN32\n\n\n/***************************************************************************\n * IPX_Get_Connection_Number -- gets local Connection Number\t\t\t\t\t*\n *                                                                         *\n * This Novell call will the return the user's local \"Connection Number\".\t*\n * This value will be 0 if the user isn't logged into Novell, so this\t\t*\n * routine can be used to detect if other calls (such as Get_Local_Target)\t*\n * will be OK.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tConnection Number, 0 = none\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Connection_Number(void)\n{\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tint num;\n\n\t//------------------------------------------------------------------------\n\t//\tCall Interrupt 0x21, with AH = 0xdc.  This tells Novell to put the local\n\t//\tconnection number into AL.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000dc00;\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\tnum = rmi.eax & 0x00ff;\n\n\treturn(num);\n\n}\t/* end of IPX_Get_Connection_Number */\n#endif\t//WIN32\n\n\n/***************************************************************************\n * IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user    *\n *                                                                         *\n * This gets the Connection Number for the given User ID.  Since a user\t\t*\n * may be logged in more than once, this just returns the first connection\t*\n * found and ignores the others.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tusername\t\tname of the user to get the Connection Number for\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tfirst-found Connection Number for that user, 0 if user not logged in\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_1st_Connection_Num (char * username)\n{\n\tstruct request_buffer {\n\t\tunsigned short len;\t\t\t\t\t\t\t// username length + 5\n\t\tunsigned char buffer_type;\t\t\t\t\t// ConnectionNum = 0x15\n\t\tunsigned short object_type;\t\t\t\t// set ot 0x0100\n\t\tunsigned char name_len;\t\t\t\t\t\t// length of username\n\t\tchar name [48];\t\t\t\t\t\t\t\t// copy of username\n\t\tunsigned short reserved;\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   number_connections;\t\t// will be 0 - 100\n\t\tunsigned char   connection_num [100];\t// array of connection numbers\n\t\tunsigned short  reserved[2];\n\t};\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\tint num_conns;\t\t\t\t\t\t\t\t\t\t// # connections returned\n\tint conn_num;\t\t\t\t\t\t\t\t\t\t// connection number\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = (unsigned short)(strlen(username) + 5);\n\treqbuf->buffer_type = 0x15;\n\treqbuf->object_type = 0x0100;\n\treqbuf->name_len    = (unsigned char) strlen(username);\n\tstrcpy(reqbuf->name, username);\n\treqbuf->reserved = reqbuf->reserved;\t\t\t\t// prevent compiler warning\n\treplybuf->len = 101;\n\treplybuf->reserved[0] = replybuf->reserved[0];\t// prevent compiler warning\n\treplybuf->reserved[0] = replybuf->reserved[1];\t// prevent compiler warning\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tStash the 1st connection number\n\t//------------------------------------------------------------------------\n\trc = (rmi.eax & 0x00ff);\t\t\t\t\t\t\t\t// if AL !=0, error\n\tnum_conns = replybuf->number_connections;\t\t\t// # times user is logged in\n\tconn_num = (int )replybuf->connection_num[0];\t// 1st connection #\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tReturn error if function failed, or user not logged in\n\t//------------------------------------------------------------------------\n\tif (rc != 0 || num_conns==0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(conn_num);\n\t}\n\n}\t/* end of IPX_Get_1st_Connection_Num */\n\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_Internet_Address -- gets Network Number & Node Address\t\t\t\t*\n *                                                                         *\n * Once you've obtained a Connection Number from IPX_Get_Connection_Number\t*\n * or IPX_Get_1st_Connection_Num, use this function to translate it into\t*\n * a Network Number and Node Address; then, place those numbers in the\t\t*\n * IPX header for outgoing packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tconnection_number\t\tConnection Number to translate\t\t\t\t\t\t*\n *\t\tnetwork_number\t\t\tptr: will hold Network Number\t\t\t\t\t\t\t*\n *\t\tphysical_node\t\t\tptr: will hold Node Address\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf connection_number is 0 and NETX isn't running, this routine\t\t\t*\n *\t\twill just put garbage into the network_number and physical_node.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Internet_Address(int connection_number,\n\tunsigned char * network_number, unsigned char * physical_node)\n{\n\tstruct request_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   buffer_type;\t\t\t\t// Internet = 0x13\n\t\tunsigned char   connection_number;\t\t// Conn. Number to translate\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   network_number [4];\t\t// filled in by IPX\n\t\tunsigned char   physical_node  [6];\t\t// filled in by IPX\n\t\tunsigned short  server_socket;\t\t\t// filled in by IPX, but don't use!\n\t};\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tError if invalid connection is given\n\t//------------------------------------------------------------------------\n\tif (connection_number==0) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = 2;\n\treqbuf->buffer_type = 0x13;\n\treqbuf->connection_number = (unsigned char)connection_number;\n\treplybuf->len = 12;\n\treplybuf->network_number[0] = replybuf->network_number[0];\t// suppress warning\n\treplybuf->physical_node[0] = replybuf->physical_node[0];\t\t// suppress warning\n\treplybuf->server_socket = replybuf->server_socket;\t\t\t\t// suppress warning\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\tmemcpy(network_number, replybuf->network_number, 4);\n\tmemcpy(physical_node,  replybuf->physical_node,  6);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(0);\n\n}\t/* end of IPX_Get_Internet_Address */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_User_ID -- gets user ID from Connection Number                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tconnection_number\t\tConnection Number to get User ID for\t\t\t\t*\n *\t\tuser_id\t\t\t\t\tptr to buffer to put User ID into; \t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\tsize must be >= 48 chars\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, -1 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_User_ID(int connection_number, char * user_id)\n{\n\tstruct request_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   buffer_type;\t\t\t// 0x16 = UserID buffer type\n\t\tunsigned char   connection_number;\t// Connection Number to get ID for\n\t};\n\tstruct reply_buffer {\n\t\tunsigned short  len;\n\t\tunsigned char   object_id[4];\n\t\tunsigned char   object_type[2];\n\t\tchar            object_name[48];\n\t\tchar            login_time[7];\n\t\tunsigned short  reserved;\n\t};\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\tstruct request_buffer * reqbuf;\n\tstruct reply_buffer * replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tError if invalid connection is given\n\t//------------------------------------------------------------------------\n\tif (connection_number==0) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\treqbuf->len = 2;\n\treqbuf->buffer_type = 0x16;\n\treqbuf->connection_number = (unsigned char)connection_number;\n\treplybuf->len = sizeof(struct reply_buffer) - 2;\n\treplybuf->object_id[0] = replybuf->object_id[0];\t\t// suppress warnings\n\treplybuf->object_type[0] = replybuf->object_type[0];\t// suppress warnings\n\treplybuf->login_time[0] = replybuf->login_time[0];\t\t// suppress warnings\n\treplybuf->reserved = replybuf->reserved;\t\t\t\t\t// suppress warnings\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = 0x21;\t\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.eax = 0x0000e300;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the caller's buffer with the user name\n\t//------------------------------------------------------------------------\n\tstrncpy(user_id, replybuf->object_name, 48);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(0);\n\n}\t/* end of IPX_Get_User_ID */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Listen_For_Packet -- commands IPX to listen for a packet            *\n *                                                                         *\n * Before calling this function, you must fill in an ECB:\t\t\t\t\t\t*\n *\t\tSocketNumber:\t\t\t\tmust contain the socket you've opened,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\tand are \"listening\" on\t\t\t\t\t\t\t\t*\n *\t\tEvent_Service_Routine:\toptionally points to a callback routine\t\t*\n *\t\tPacketCount:\t\t\t\tset to 2, to tell IPX there are 2 areas to\t*\n *\t\t\t\t\t\t\t\t\t\tstore the incoming data in\t\t\t\t\t\t\t*\n *\t\tPacket[0].Address:\t\tset to the address of an IPXHeaderType\t\t\t*\n *\t\tPacket[0].Length:\t\t\tsizeof(IPXHeaderType)\t\t\t\t\t\t\t\t*\n *\t\tPacket[1].Address:\t\taddress of data buffer, for the packet\t\t\t*\n *\t\tPacket[1].Length:\t\t\tsize of the data buffer\t\t\t\t\t\t\t\t*\n *                                                                         *\n * When the packet is received, ECBType.CompletionCode will be 0 if \t\t\t*\n * successful.  Otherwise, some error occurred.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * You should initialize the ECB to 0's before filling it in.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to a filled-in ECB; MUST be real-mode memory\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, IPX error otherwise\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Listen_For_Packet(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tCall IPX with ES:SI=ecb_ptr\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_LISTEN_FOR_PACKET;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\treturn(rmi.eax & 0x00ff);\n\n}\t/* end of IPX_Listen_For_Packet */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Send_Packet -- commands IPX to send a packet                        *\n *                                                                         *\n * Before calling this function, you must fill in an ECB:\t\t\t\t\t\t*\n *\t\tSocketNumber:\t\t\t\tmust contain the socket you've opened,\t\t\t*\n *\t\t\t\t\t\t\t\t\t\tand are sending on\t\t\t\t\t\t\t\t\t*\n *\t\tEvent_Service_Routine:\toptionally points to a callback routine\t\t*\n *\t\tPacketCount:\t\t\t\tset to 2, to tell IPX there are 2 areas the\t*\n *\t\t\t\t\t\t\t\t\t\toutgoing data is stored in\t\t\t\t\t\t\t*\n *\t\tPacket[0].Address:\t\tset to the address of an IPXHeaderType\t\t\t*\n *\t\tPacket[0].Length:\t\t\tsizeof(IPXHeaderType)\t\t\t\t\t\t\t\t*\n *\t\tPacket[1].Address:\t\taddress of buffer containing data to send\t\t*\n *\t\tPacket[1].Length:\t\t\tsize of the data buffer\t\t\t\t\t\t\t\t*\n *\t\tImmediateAddress:\t\t\tmust be filled in with the node address of\t*\n *\t\t\t\t\t\t\t\t\t\tthe bridge that will route the message;\t\t*\n *\t\t\t\t\t\t\t\t\t\tfill this in by calling IPX_Get_Local_Target\t*\n *                                                                         *\n * Also, you must fill in the IPXHeaderType with certain values:\t\t\t\t*\n *\t\tPacketType:\t\t\t\t\tset to 4 for IPX\t\t\t\t\t\t\t\t\t\t*\n *\t\tDestNetworkNumber:\t\tNetwork Number of the destination system\t\t*\n *\t\tDestNetworkNode:\t\t\tNode Address of the destination system\t\t\t*\n *\t\tDestNetworkSocket:\t\tthe destination system's socket to send to;\t*\n *\t\t\t\t\t\t\t\t\t\tthis doesn't have to be the same as the\t\t*\n *\t\t\t\t\t\t\t\t\t\tsocket opened on the local machine.\t\t\t\t*\n *                                                                         *\n * You should initialize the ECB & IPXHeader to 0's before filling them in.*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to a filled-in ECB\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.  This function doesn't return anything; the caller must check\t*\n *    its ECB.CompletionCode for: 0 = OK, IPX Error otherwise.\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nvoid IPX_Send_Packet(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tCall IPX with ES:SI=ecb_ptr\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_SEND_PACKET;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n}\t/* end of IPX_Send_Packet */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB          *\n *                                                                         *\n * Use this function to fill in the ECB's ImmediateAddress field when\t\t*\n * sending a packet.  The Immediate Address is the node address of the\t\t*\n * bridge that must route the message.  If there is no bridge, it's \t\t\t*\n * filled in with the destination Node Address.  In either case, it\t\t\t*\n * will contain the proper value for sending.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdest_network\t\t\tdestination Network Number\t\t\t\t\t\t\t\t*\n *\t\tdest_node\t\t\t\tdestination Node Address\t\t\t\t\t\t\t\t*\n *\t\tdest_socket\t\t\t\tdestination Socket Number\t\t\t\t\t\t\t\t*\n *\t\tbridge_address\t\t\tfield to fill in with Immediate Address\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = OK, error otherwise\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf the Connection Number is 0 (user not logged in), dest_network\t\t*\n *\t\tand dest_node will be garbage, and this routine will probably crash.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Get_Local_Target(unsigned char *dest_network, unsigned char *dest_node,\n\tunsigned short dest_socket, unsigned char *bridge_address)\n{\n\tstruct request_buffer {\n\t\tunsigned char   network_number [4];\n\t\tunsigned char   physical_node  [6];\n\t\tunsigned short  socket;\n\t};\n\tstruct reply_buffer {\n\t\tunsigned char   local_target [6];\n\t};\n\tunsigned int rc;\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tRMIType rmi;\n\tstruct request_buffer *reqbuf;\n\tstruct reply_buffer *replybuf;\n\tunsigned short segment;\t\t\t\t\t\t\t// for DOS allocation\n\tunsigned short selector;\t\t\t\t\t\t// for DOS allocation\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory to store the buffers passed to the interrupt\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = (sizeof(struct request_buffer) + \t// # paragraphs to allocate\n\t\tsizeof(struct reply_buffer) + 15) >> 4;\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(-1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tGet pointers to allocated memory.\n\t//\t'reqbuf' is just the returned real-mode segment, multiplied by 16.\n\t//\t'replybuf' is an offset from 'reqbuf'.\n\t//------------------------------------------------------------------------\n\tsegment = regs.w.ax;\n\tselector = regs.w.dx;\n\treqbuf = (struct request_buffer *)(segment << 4);\n\treplybuf = (struct reply_buffer *)\n\t\t(((char *)reqbuf) + sizeof (struct request_buffer));\n\n\t//------------------------------------------------------------------------\n\t//\tInit the contents of the request & reply buffers\n\t//------------------------------------------------------------------------\n\tmemcpy(reqbuf->network_number, dest_network, 4);\n\tmemcpy(reqbuf->physical_node, dest_node, 6);\n\treqbuf->socket = dest_socket;\n\n\t//------------------------------------------------------------------------\n\t//\tInvoke IPX with DS:SI=&request_buffer, ES:DI=&reply_buffer\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tFill in registers for the DPMI call\n\t//........................................................................\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//........................................................................\n\t//\tFill in registers for the interrupt call\n\t//........................................................................\n\trmi.ebx = IPX_GET_LOCAL_TARGET;\n\trmi.ds = segment;\n\trmi.esi = 0;\n\trmi.es = segment;\n\trmi.edi = sizeof(struct request_buffer);\n\t//........................................................................\n\t//\tcall DPMI\n\t//........................................................................\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0x00ff);\n\tmemcpy(bridge_address, replybuf->local_target, 6);\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\treturn(rc);\n\n}\t/* end of IPX_Get_Local_Target */\n#endif\t//WIN32\n\n/***************************************************************************\n * IPX_Cancel_Event -- cancels an operation in progress                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tecb_ptr\t\tpointer to ECB event to cancel\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t???\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe ECB must be located in real-mode memory, as well as the values\t*\n *\t\tpointed to in the ECB (the IPX Header, the buffer to send, etc.)\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nint IPX_Cancel_Event(struct ECB *ecb_ptr)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\tunsigned int rc;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the interrupt call\n\t//------------------------------------------------------------------------\n\trmi.ebx = IPX_CANCEL_EVENT;\n\trmi.es = (short)((long)ecb_ptr >> 4);\n\trmi.esi = (long)((long)ecb_ptr & 0x000f);\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n\trc = (rmi.eax & 0x00ff);\n\n\treturn(rc);\n\n}\t/* end of IPX_Cancel_Event */\n#endif\t//WIN32\n\n/***************************************************************************\n * Let_IPX_Breath -- gives IPX some CPU time                               *\n *                                                                         *\n * Use this function if you're polling the ECB's InUse flag, waiting\t\t\t*\n * for it to go to 0:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n *\t\twhile ECBType.InUse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\tLet_IPX_Breath();\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/15/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifndef WIN32\t\t// WIN32 version is in IPX95.CPP\nvoid Let_IPX_Breath(void)\n{\n\tunion REGS      regs;\n\tstruct SREGS    sregs;\n\tRMIType rmi;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the DPMI call\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tmemset (&rmi, 0 ,sizeof(rmi));\n\tregs.w.ax = DPMI_CALL_REAL_INT;\t// DPMI function to call\n\tregs.w.bx = IPX_INT;\t\t\t\t\t// interrupt # to invoke\n\tsregs.es = FP_SEG(&rmi);\t\t\t// tell DPMI where the RMI is\n\tregs.x.edi = FP_OFF(&rmi);\n\n\t//------------------------------------------------------------------------\n\t//\tFill in registers for the interrupt call\n\t//------------------------------------------------------------------------\n\trmi.ebx = IPX_RELINQUISH_CONTROL;\n\n\t//------------------------------------------------------------------------\n\t//\tcall DPMI\n\t//------------------------------------------------------------------------\n\tint386x(DPMI_INT, &regs, &regs, &sregs);\n\n}\t/* end of Let_IPX_Breath */\n#endif\t//WIN32\n/**************************** end of ipx.cpp *******************************/\n"
  },
  {
    "path": "REDALERT/IPX.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPX.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX.H                                    *\n *                                                                         *\n *                   Programmer : Barry Nance\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t from Client/Server LAN Programming\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t Westwood-ized by Bill Randolph\t\t\t\t*\n *                                                                         *\n *                   Start Date : December 14, 1994                        *\n *                                                                         *\n *                  Last Update : December 14, 1994   [BR]                 *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPX_H\n#define IPX_H\n\n/*\n******************************** Structures *********************************\n*/\ntypedef unsigned char NetNumType[4];\ntypedef unsigned char NetNodeType[6];\ntypedef char UserID[48];\n\n/*---------------------------------------------------------------------------\nThis is the IPX Packet structure.  It's followed by the data itself, which\ncan be up to 546 bytes long.  Annotation of 'IPX' means IPX will set this\nfield; annotation of 'APP' means the application must set the field.\nNOTE: All header fields are ordered high-byte,low-byte.\n---------------------------------------------------------------------------*/\ntypedef struct IPXHEADER {\n\tunsigned short CheckSum;\t\t\t\t\t// IPX: Not used; always 0xffff\n\tunsigned short Length;\t\t\t\t\t\t// IPX: Total size, incl header & data\n\tunsigned char TransportControl;\t\t\t// IPX: # bridges message crossed\n\tunsigned char PacketType;\t\t\t\t\t// APP: Set to 4 for IPX (5 for SPX)\n\tunsigned char DestNetworkNumber[4];\t\t// APP: destination Network Number\n\tunsigned char DestNetworkNode[6];\t\t// APP: destination Node Address\n\tunsigned short DestNetworkSocket;\t\t// APP: destination Socket Number\n\tunsigned char SourceNetworkNumber[4];\t// IPX: source Network Number\n\tunsigned char SourceNetworkNode[6];\t\t// IPX: source Node Address\n\tunsigned short SourceNetworkSocket;\t\t// IPX: source Socket Number\n} IPXHeaderType;\n\n/*---------------------------------------------------------------------------\nThis is the IPX Event Control Block.  It serves as a communications area\nbetween IPX and the application for a single IPX operation.  You should set\nup a separate ECB for each IPX operation you perform.\n---------------------------------------------------------------------------*/\ntypedef struct ECB {\n\tvoid *Link_Address;\n\tvoid (*Event_Service_Routine)(void);\t// APP: event handler (NULL=none)\n\tunsigned char InUse;\t\t\t\t\t\t\t// IPX: 0 = event complete\n\tunsigned char CompletionCode;\t\t\t\t// IPX: event's return code\n\tunsigned short SocketNumber;\t\t\t\t// APP: socket to send data through\n\tunsigned short ConnectionID;\t\t\t\t// returned by Listen (???)\n\tunsigned short RestOfWorkspace;\n\tunsigned char DriverWorkspace[12];\n\tunsigned char ImmediateAddress[6];\t\t// returned by Get_Local_Target\n\tunsigned short PacketCount;\n\tstruct {\n\t\tvoid *Address;\n\t\tunsigned short Length;\n\t} Packet[2];\n} ECBType;\n\n\n/*---------------------------------------------------------------------------\nThis structure is used for calling DPMI function 0x300, Call-Real-Mode-\nInterrupt.  It passes register values to & from the interrupt handler.\n---------------------------------------------------------------------------*/\ntypedef struct {\n\tlong edi;\n\tlong esi;\n\tlong ebp;\n\tlong Reserved;\n\tlong ebx;\n\tlong edx;\n\tlong ecx;\n\tlong eax;\n\tshort Flags;\n\tshort es;\n\tshort ds;\n\tshort fs;\n\tshort gs;\n\tshort ip;\n\tshort cs;\n\tshort sp;\n\tshort ss;\n} RMIType;\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThese defines are for the IPX functions.  The function number is specified \nby placing it in BX when IPX is called.  There are two ways to invoke IPX: \nuse interrupt 0x7a, or use a function whose address is obtained by calling \ninterrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.  \nThis is the preferred method, since other apps are known to use int 0x7a.\n---------------------------------------------------------------------------*/\n#define\tIPX_OPEN_SOCKET\t\t\t\t\t\t0x0000\n#define\tIPX_CLOSE_SOCKET\t\t\t\t\t\t0x0001\n#define\tIPX_GET_LOCAL_TARGET\t\t\t\t\t0x0002\n#define\tIPX_SEND_PACKET\t\t\t\t\t\t0x0003\n#define\tIPX_LISTEN_FOR_PACKET\t\t\t\t0x0004\n#define\tIPX_SCHEDULE_EVENT\t\t\t\t\t0x0005\n#define\tIPX_CANCEL_EVENT\t\t\t\t\t\t0x0006\n#define\tIPX_GET_INTERVAL_MARKER\t\t\t\t0x0008\n#define\tIPX_GET_INTERNETWORK_ADDRESS\t\t0x0009\n#define\tIPX_RELINQUISH_CONTROL\t\t\t\t0x000A\n#define\tIPX_DISCONNECT_FROM_TARGET\t\t\t0x000B\n\n/*---------------------------------------------------------------------------\nThese defines are for various IPX error codes:\n---------------------------------------------------------------------------*/\n#define\tIPXERR_CONNECTION_SEVERED\t\t\t0x00ec\n#define\tIPXERR_CONNECTION_FAILED\t\t\t0x00ed\n#define\tIPXERR_NO_CONNECTION\t\t\t\t\t0x00ee\n#define\tIPXERR_CONNECTION_TABLE_FULL\t\t0x00ef\n#define\tIPXERR_NO_CANCEL_ECB\t\t\t\t\t0x00f9\n#define\tIPXERR_NO_PATH\t\t\t\t\t\t\t0x00fa\n#define\tIPXERR_ECB_INACTIVE\t\t\t\t\t0x00fc\n#define\tIPXERR_INVALID_PACKET_LENGTH\t\t0x00fd\n#define\tIPXERR_SOCKET_TABLE_FULL\t\t\t0x00fe\n#define\tIPXERR_SOCKET_ERROR\t\t\t\t\t0x00ff\n\n/*---------------------------------------------------------------------------\nThese defines are for various interrupt vectors and DPMI functions:\n---------------------------------------------------------------------------*/\n#define\tIPX_INT\t\t\t\t\t\t\t\t\t0x007a\n#define\tDPMI_INT\t\t\t\t\t\t\t\t\t0x0031\n#define\tDPMI_ALLOC_DOS_MEM\t\t\t\t\t0x0100\n#define\tDPMI_FREE_DOS_MEM\t\t\t\t\t\t0x0101\n#define\tDPMI_CALL_REAL_INT\t\t\t\t\t0x0300\n#define\tDPMI_LOCK_MEM\t\t\t\t\t\t\t0x0600\n#define\tDPMI_UNLOCK_MEM\t\t\t\t\t\t0x0601\n\n/*\n******************************** Prototypes *********************************\n*/\n/*---------------------------------------------------------------------------\nNOTE: All routines return 0 for a success code and one of the above IPX\nerror codes if there's an error, EXCEPT:\n- IPX_SPX_Installed (0 = not installed)\n- Get_Connection_Number / Get_1st_Connection_Number (0 = no connection)\n---------------------------------------------------------------------------*/\n/*\n.................................. ipx.cpp ..................................\n*/\nint IPX_SPX_Installed(void);\nint IPX_Open_Socket(unsigned short socket);\nint IPX_Close_Socket(unsigned short socket);\nint IPX_Get_Connection_Number(void);\nint IPX_Get_1st_Connection_Num (char *username);\nint IPX_Get_Internet_Address(int connection_number, \n\tunsigned char *network_number, unsigned char *physical_node);\nint IPX_Get_User_ID(int connection_number, char *user_id);\nint IPX_Listen_For_Packet(struct ECB *ecb_ptr);\nvoid IPX_Send_Packet(struct ECB *ecb_ptr);\nint IPX_Get_Local_Target(unsigned char *dest_network, unsigned char *dest_node,\n\tunsigned short dest_socket, unsigned char *bridge_address);\nint IPX_Cancel_Event(struct ECB *ecb_ptr);\nvoid Let_IPX_Breath(void);\n\n#endif\n\n/***************************** end of ipx.h ********************************/\n\n"
  },
  {
    "path": "REDALERT/IPX95.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX95PP                                  *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : January 22nd, 1996                       *\n *                                                                         *\n *                  Last Update : July 10th, 1996   [ST]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Overview:                                                               *\n *                                                                         *\n *  Windows 95 equivelent functions from IPX.CPP                           *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n\n#ifdef WIN32\n\n#include \"ipx95.h\"\n\n // Stub in old IPX here ST - 12/20/2018 1:53PM\nextern \"C\" {\n\textern BOOL __stdcall IPX_Initialise(void) { return 0; }\n\textern BOOL __stdcall IPX_Get_Outstanding_Buffer95(unsigned char *buffer) { return 0; }\n\textern void __stdcall IPX_Shut_Down95(void) {}\n\textern int  __stdcall IPX_Send_Packet95(unsigned char *, unsigned char *, int, unsigned char*, unsigned char*) { return 0; }\n\textern int  __stdcall IPX_Broadcast_Packet95(unsigned char *, int) { return 0; }\n\textern BOOL __stdcall IPX_Start_Listening95(void) { return 0; }\n\textern int  __stdcall IPX_Open_Socket95(int socket) { return 0; }\n\textern void __stdcall IPX_Close_Socket95(int socket) {}\n\textern int  __stdcall IPX_Get_Connection_Number95(void) { return 0; }\n\textern int  __stdcall IPX_Get_Local_Target95(unsigned char *, unsigned char*, unsigned short, unsigned char*) { return 0; }\n}\n\n#if (0)\n/*\n** Instance handle for the THIPX32 .DLL\n*/\nHINSTANCE\tIpxDllInstance = NULL;\n\n/*\n** Function pointers\n*/\n//extern \"C\" {\n\tIPXInitialiseType\t\t\t\t\tIPX_Initialise = NULL;\n\tIPXGetOutstandingBuffer95Type\tIPX_Get_Outstanding_Buffer95 = NULL;\n\tIPXShutDown95Type             IPX_Shut_Down95 = NULL;\n\tIPXSendPacket95Type           IPX_Send_Packet95 = NULL;\n\tIPXBroadcastPacket95Type      IPX_Broadcast_Packet95 = NULL;\n\tIPXStartListening95Type       IPX_Start_Listening95 = NULL;\n\tIPXOpenSocket95Type           IPX_Open_Socket95 = NULL;\n\tIPXCloseSocket95Type          IPX_Close_Socket95 = NULL;\n\tIPXGetConnectionNumber95Type  IPX_Get_Connection_Number95 = NULL;\n\tIPXGetLocalTarget95           IPX_Get_Local_Target95 = NULL;\n//}\n\nchar const *FunctionNames[] = {\n\t\"_IPX_Initialise\",\n\t\"_IPX_Get_Outstanding_Buffer95\",\n\t\"_IPX_Shut_Down95\",\n\t\"_IPX_Send_Packet95\",\n\t\"_IPX_Broadcast_Packet95\",\n\t\"_IPX_Start_Listening95\",\n\t\"_IPX_Open_Socket95\",\n\t\"_IPX_Close_Socket95\",\n\t\"_IPX_Get_Connection_Number95\",\n\t\"_IPX_Get_Local_Target95\",\n\tNULL\n};\n#endif\n\nextern void Get_OS_Version (void);\nbool\t\t\t\tWindowsNT = false;\n\n\n/***********************************************************************************************\n * Load_IPX_Dll -- Loads the THIPX32 DLL                                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true if DLL loaded                                                                *\n *                                                                                             *\n * WARNINGS: This call will fail under NT due to a side effect of loading the THIPX32.DLL      *\n *           which causes the 16 bit DLL THIPX16.DLL to load.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 11:40AM ST : Created                                                              *\n *=============================================================================================*/\nbool Load_IPX_Dll (void)\n{\n\t//ST 5/13/2019\n\treturn false;\n\n#if (0)\n\tGet_OS_Version();\n\tif (WindowsNT) return (false);\n\n\tSetErrorMode( SEM_NOOPENFILEERRORBOX );\n\tIpxDllInstance = LoadLibrary ( \"THIPX32.DLL\" );\n\tSetErrorMode ( 0 );\n\n\tif ( IpxDllInstance ){\n\n\t\tconst char\t\t*function_name;\n\t\tunsigned long \t*fptr = (unsigned long *) &IPX_Initialise;\n\t\tint\t\t\t\tcount = 0;\n\n\t\tdo {\n\t\t\tfunction_name = FunctionNames[count];\n\t\t\tif (function_name){\n\t\t\t\t*fptr = (unsigned long) GetProcAddress (IpxDllInstance, function_name);\n\t\t\t\tassert (*fptr != NULL);\n\t\t\t\tfptr++;\n\t\t\t\tcount++;\n\t\t\t}\n\n\t\t} while ( function_name );\n\n\t\treturn (true);\n\n\t}else{\n\t\treturn (false);\n\t}\n#endif\n}\n\n\n\n/***********************************************************************************************\n * Unload_IPX_Dll -- Frees the THIPX32 library                                                 *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    4/1/97 2:37PM ST : Created                                                               *\n *=============================================================================================*/\nvoid Unload_IPX_Dll (void)\n{\n\t//ST 5/13/2019\n\n#if (0)\n\tif (IpxDllInstance){\n\t\tFreeLibrary (IpxDllInstance);\n\t\tIpxDllInstance = NULL;\n\t}\n#endif\n}\n\n\nint IPX_Open_Socket(unsigned short socket)\n{\n\treturn -1;\t//ST 5/13/2019\n\t//return ( IPX_Open_Socket95((int)socket));\n}\n\nint IPX_Close_Socket(unsigned short socket)\n{\n\t//ST 5/13/2019 IPX_Close_Socket95((int)socket);\n\treturn (0);\n}\n\n\nint IPX_Get_Connection_Number(void)\n{\n\treturn -1;//ST 5/13/2019\n\t//return (IPX_Get_Connection_Number95());\n}\n\n\n\nint IPX_Broadcast_Packet(unsigned char * buf, int buflen)\n{\n\treturn 0; //ST 5/13/2019\n\t//return(IPX_Broadcast_Packet95(buf, buflen));\n}\n\n#if (0) //ST 5/13/2019\nextern \"C\"{\n\textern void __cdecl Int3(void);\n}\n#endif\n\nint IPX_Get_Local_Target(unsigned char * dest_network, unsigned char * dest_node,\n\tunsigned short dest_socket, unsigned char * bridge_address)\n{\n\t//Int3();\n\t\n\treturn 0; //ST 5/13/2019\n\t//return (IPX_Get_Local_Target95(dest_network, dest_node, dest_socket, bridge_address));\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/IPX95.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPX95PP                                  *\n *                                                                         *\n *                   Programmer : Steve Tall                               *\n *                                                                         *\n *                   Start Date : January 22nd, 1996                       *\n *                                                                         *\n *                  Last Update : January 22nd, 1996   [ST]                *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#if (0)\n\n/*\n** Types for function pointers\n*/\ntypedef BOOL __stdcall (*IPXInitialiseType) (void);\ntypedef BOOL __stdcall (*IPXGetOutstandingBuffer95Type) (unsigned char*);\ntypedef void __stdcall (*IPXShutDown95Type) (void);\ntypedef int  __stdcall (*IPXSendPacket95Type) (unsigned char *, unsigned char *, int, unsigned char*, unsigned char*);\ntypedef int  __stdcall (*IPXBroadcastPacket95Type) (unsigned char *, int);\ntypedef BOOL __stdcall (*IPXStartListening95Type) (void);\ntypedef int  __stdcall (*IPXOpenSocket95Type) (int);\ntypedef void __stdcall (*IPXCloseSocket95Type) (int);\ntypedef int  __stdcall (*IPXGetConnectionNumber95Type) (void);\ntypedef int  __stdcall (*IPXGetLocalTarget95) (unsigned char *, unsigned char*, unsigned short, unsigned char*);\n\n\n\n/*\n** Function pointers\n*/\n//extern \"C\"{\n\textern IPXInitialiseType\t\t\t\t\tIPX_Initialise;\n\textern IPXGetOutstandingBuffer95Type  \tIPX_Get_Outstanding_Buffer95;\n\textern IPXShutDown95Type              \tIPX_Shut_Down95;\n\textern IPXSendPacket95Type            \tIPX_Send_Packet95;\n\textern IPXBroadcastPacket95Type       \tIPX_Broadcast_Packet95;\n\textern IPXStartListening95Type        \tIPX_Start_Listening95;\n\textern IPXOpenSocket95Type            \tIPX_Open_Socket95;\n\textern IPXCloseSocket95Type           \tIPX_Close_Socket95;\n\textern IPXGetConnectionNumber95Type   \tIPX_Get_Connection_Number95;\n\textern IPXGetLocalTarget95            \tIPX_Get_Local_Target95;\n//}\n\n/*\n** Functions\n*/\nbool Load_IPX_Dll (void);\nvoid Unload_IPX_Dll (void);\n#endif\n\n#if (1)\nextern \"C\"{\n\textern BOOL __stdcall IPX_Initialise(void);\n\textern BOOL __stdcall IPX_Get_Outstanding_Buffer95(unsigned char *buffer);\n\textern void __stdcall IPX_Shut_Down95(void);\n\textern int  __stdcall IPX_Send_Packet95(unsigned char *, unsigned char *, int, unsigned char*, unsigned char*);\n\textern int  __stdcall IPX_Broadcast_Packet95(unsigned char *, int);\n\textern BOOL __stdcall IPX_Start_Listening95(void);\n\textern int  __stdcall IPX_Open_Socket95(int socket);\n\textern void __stdcall IPX_Close_Socket95(int socket);\n\textern int  __stdcall IPX_Get_Connection_Number95(void);\n\textern int  __stdcall IPX_Get_Local_Target95(unsigned char *, unsigned char*, unsigned short, unsigned char*);\n}\n#endif\t//(1)\n\nextern bool WindowsNT;\n\n"
  },
  {
    "path": "REDALERT/IPXADDR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXADDR.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXADDR.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : December 19, 1994   [BR]                 *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   IPXAddressClass::IPXAddressClass -- class constructor                 *\n *   IPXAddressClass::IPXAddressClass -- class constructor form 2\t\t\t\t*\n *   IPXAddressClass::IPXAddressClass -- class constructor form 3\t\t\t\t*\n *   IPXAddressClass::Set_Address -- sets the IPX address values        \t*\n *   IPXAddressClass::Set_Address -- sets the IPX values from a header\t\t*\n *   IPXAddressClass::Get_Address -- retrieves the IPX address values      *\n *   IPXAddressClass::Get_Address -- copies address into an IPX header\t\t*\n *   IPXAddressClass::Is_Broadcast -- tells if this is a broadcast address *\n *   IPXAddressClass::operator== -- overloaded comparison operator         *\n *   IPXAddressClass::operator!= -- overloaded comparison operator         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n#include \"ipxaddr.h\"\n\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#endif\t//WINSOCK_IPX\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor                   *\n *                                                                         *\n * This default constructor generates a broadcast address.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(void)\n{\n\tNetworkNumber[0] = 0xff;\n\tNetworkNumber[1] = 0xff;\n\tNetworkNumber[2] = 0xff;\n\tNetworkNumber[3] = 0xff;\n\tNodeAddress[0] = 0xff;\n\tNodeAddress[1] = 0xff;\n\tNodeAddress[2] = 0xff;\n\tNodeAddress[3] = 0xff;\n\tNodeAddress[4] = 0xff;\n\tNodeAddress[5] = 0xff;\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor form 2\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(NetNumType net, NetNodeType node)\n{\n\tmemcpy(NetworkNumber, net, 4);\n\tmemcpy(NodeAddress, node, 6);\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::IPXAddressClass -- class constructor form 3\t\t\t\t*\n *                                                                         *\n * This form of the constructor takes an IPX header as an argument.  It\t\t*\n * extracts the address from the Source address fields in the header.\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\theader\tHeader from which to extract the address\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass::IPXAddressClass(IPXHeaderType *header)\n{\n\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\n}\t/* end of IPXAddressClass */\n\n\n/***************************************************************************\n * IPXAddressClass::Set_Address -- sets the IPX address values        \t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Set_Address(NetNumType net, NetNodeType node)\n{\n\tmemcpy(NetworkNumber,net,4);\n\tmemcpy(NodeAddress,node,6);\n\n}\t/* end of Set_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Set_Address -- sets the IPX values from a header\t\t\t*\n *                                                                         *\n * This routine extracts the source addresses from the given IPX header.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Set_Address(IPXHeaderType *header)\n{\n#ifdef WINSOCK_IPX\n\tProtocolEnum protocol = PROTOCOL_IPX;\n\tif ( PacketTransport ) protocol = PacketTransport->Get_Protocol();\n\n\tswitch ( protocol ) {\n\n\t\tcase PROTOCOL_IPX:\n\t\t\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\t\t\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\t\t\tbreak;\n\n\t\tcase PROTOCOL_UDP:\n\t\t\tunsigned char *addr = (unsigned char*) header;\n\t\t\tmemset (NodeAddress, 0, 6);\n\t\t\tmemcpy (NodeAddress, addr, 4);\n\t\t\tmemset (NetworkNumber, 0, 4);\n\t\t\tbreak;\n\t}\n#else\t//WINSOCK_IPX\n\n\tif (header) {\n\t\tmemcpy(NetworkNumber,header->SourceNetworkNumber,4);\n\t\tmemcpy(NodeAddress,header->SourceNetworkNode,6);\n\t} else {\n\t\t/*\n\t\t** Address is meaningless when using winsock\n\t\t*/\n\t\tmemset(NetworkNumber, 1 ,4);\n\t\tmemset(NodeAddress, 1, 6);\n\t}\n\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Set_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Get_Address -- retrieves the IPX address values        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Get_Address(NetNumType net, NetNodeType node)\n{\n\tmemcpy(net,NetworkNumber,4);\n\tmemcpy(node,NodeAddress,6);\n\n}\t/* end of Get_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Get_Address -- copies address into an IPX header\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tNetwork Number for this address\t\t\t\t\t\t\t\t\t\t*\n *\t\tnode\t\tNode Address for this address\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXAddressClass::Get_Address(IPXHeaderType *header)\n{\n\tmemcpy(header->DestNetworkNumber,NetworkNumber,4);\n\tmemcpy(header->DestNetworkNode,NodeAddress,6);\n\n}\t/* end of Get_Address */\n\n\n/***************************************************************************\n * IPXAddressClass::Is_Broadcast -- tells if this is a broadcast address   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::Is_Broadcast(void)\n{\n\tif (\tNetworkNumber[0] == 0xff &&\n\t\t\tNetworkNumber[1] == 0xff &&\n\t\t\tNetworkNumber[2] == 0xff &&\n\t\t\tNetworkNumber[3] == 0xff &&\n\t\t\tNodeAddress[0] == 0xff &&\n\t\t\tNodeAddress[1] == 0xff &&\n\t\t\tNodeAddress[2] == 0xff &&\n\t\t\tNodeAddress[3] == 0xff &&\n\t\t\tNodeAddress[4] == 0xff &&\n\t\t\tNodeAddress[5] == 0xff) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n\n}\t/* end of Is_Broadcast */\n\n\n/***************************************************************************\n * IPXAddressClass::operator== -- overloaded comparison operator           *\n *                                                                         *\n * Since, if NETX isn't running, the network number on a received packet\t*\n * can be bogus (all 0's), only the node address is used for comparison \t*\n * purposes here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = not equal, 1 = equal\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator == (IPXAddressClass & addr)\n{\n\t//------------------------------------------------------------------------\n\t//\tIf either Network Number is all 0's (which can happen if the system is\n\t//\tnot running NETX), compare only the Node Addresses.\n\t//------------------------------------------------------------------------\n\tif ( (NetworkNumber[0]==0 &&\n\t\t\tNetworkNumber[1]==0 &&\n\t\t\tNetworkNumber[2]==0 &&\n\t\t\tNetworkNumber[3]==0) ||\n\t\t  (addr.NetworkNumber[0]==0 &&\n\t\t\taddr.NetworkNumber[1]==0 &&\n\t\t\taddr.NetworkNumber[2]==0 &&\n\t\t\taddr.NetworkNumber[3]==0) ) {\n\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0) {\n\t\t\treturn(1);\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, compare both the Network Numbers and Node Addresses\n\t//------------------------------------------------------------------------\n\telse {\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0 &&\n\t\t\tmemcmp(NetworkNumber,addr.NetworkNumber,4)==0) {\n\t\t\treturn(1);\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n}\t/* end of operator== */\n\n\n/***************************************************************************\n * IPXAddressClass::operator!= -- overloaded comparison operator           *\n *                                                                         *\n * Since, if NETX isn't running, the network number on a received packet\t*\n * can be bogus (all 0's), only the node address is used for comparison \t*\n * purposes here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = equal, 1 = not equal\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator != (IPXAddressClass & addr)\n{\n\t//------------------------------------------------------------------------\n\t//\tIf either Network Number is all 0's (which can happen if the system is\n\t//\tnot running NETX), compare only the Node Addresses.\n\t//------------------------------------------------------------------------\n\tif ( (NetworkNumber[0]==0 &&\n\t\t\tNetworkNumber[1]==0 &&\n\t\t\tNetworkNumber[2]==0 &&\n\t\t\tNetworkNumber[3]==0) ||\n\t\t  (addr.NetworkNumber[0]==0 &&\n\t\t\taddr.NetworkNumber[1]==0 &&\n\t\t\taddr.NetworkNumber[2]==0 &&\n\t\t\taddr.NetworkNumber[3]==0) ) {\n\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0) {\n\t\t\treturn(0);\n\t\t}\n\t\telse {\n\t\t\treturn(1);\n\t\t}\n\t}\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, compare both the Network Numbers and Node Addresses\n\t//------------------------------------------------------------------------\n\telse {\n\t\tif (memcmp(NodeAddress,addr.NodeAddress,6)==0 &&\n\t\t\tmemcmp(NetworkNumber,addr.NetworkNumber,4)==0) {\n\t\t\treturn(0);\n\t\t}\n\t\telse {\n\t\t\treturn(1);\n\t\t}\n\t}\n\n}\t/* end of operator!= */\n\n\n/***************************************************************************\n * IPXAddressClass::operator > -- overloaded comparison operator           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = greater, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator > (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) > 0);\n\n}\t/* end of operator> */\n\n\n/***************************************************************************\n * IPXAddressClass::operator < -- overloaded comparison operator           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = less, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator < (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) < 0);\n\n}\t/* end of operator< */\n\n\n/***************************************************************************\n * IPXAddressClass::operator >= -- overloaded comparison operator          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = greater or equal, FALSE = not\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator >= (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) >= 0);\n\n}\t/* end of operator>= */\n\n\n/***************************************************************************\n * IPXAddressClass::operator <= -- overloaded comparison operator          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\taddr\t\taddress to compare to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tTRUE = less or equal, FALSE = not\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/19/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXAddressClass::operator <= (IPXAddressClass & addr)\n{\n\treturn(memcmp(this, &addr, 10) <= 0);\n\n}\t/* end of operator<= */\n\n/************************** end of ipxaddr.cpp *****************************/\n"
  },
  {
    "path": "REDALERT/IPXADDR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXADDR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXADDR.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : December 19, 1994   [BR]                 *\n *                                                                         *\n * This class is useful for any IPX-related code.  It's just a utility\t\t*\n * to help manage those annoying IPX address fields.  This class lets you\t*\n * compare addresses, copy addresses to & from the IPX header, etc.\t\t\t*\n *                                                                         *\n * The class has no virtual functions, so you can treat this class just\t\t*\n * like a data structure; it can be loaded & saved, and even transmitted\t*\n * across the net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXADDR_H\n#define IPXADDR_H\n\n#include \"ipx.h\"\t\t\t\t// for NetNumType & NetNodeType\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXAddressClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructors:\n\t\t.....................................................................*/\n\t\tIPXAddressClass(void);\n\t\tIPXAddressClass(NetNumType net, NetNodeType node);\n\t\tIPXAddressClass(IPXHeaderType *header);\n\n\t\t/*.....................................................................\n\t\tSet the address from explicit variables, or from the SOURCE values\n\t\tin an IPX packet header.\n\t\t.....................................................................*/\n\t\tvoid Set_Address(NetNumType net, NetNodeType node);\n\t\tvoid Set_Address(IPXHeaderType *header);\n\t\t/*.....................................................................\n\t\tGet the address values explicitly, or copy them into the DESTINATION\n\t\tvalues in an IPX packet header.\n\t\t.....................................................................*/\n\t\tvoid Get_Address (NetNumType net, NetNodeType node);\n\t\tvoid Get_Address(IPXHeaderType *header);\n\n\t\t/*.....................................................................\n\t\tTells if this address is a broadcast address\n\t\t.....................................................................*/\n\t\tint Is_Broadcast(void);\n\n\t\t/*.....................................................................\n\t\tOverloaded operators:\n\t\t.....................................................................*/\n\t\tint operator == (IPXAddressClass & addr);\n\t\tint operator != (IPXAddressClass & addr);\n\t\tint operator > (IPXAddressClass &addr);\n\t\tint operator < (IPXAddressClass &addr);\n\t\tint operator >= (IPXAddressClass &addr);\n\t\tint operator <= (IPXAddressClass &addr);\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\tNetNumType NetworkNumber;\n\t\tNetNodeType NodeAddress;\n};\n\n#endif\n\n/**************************** end of ipxaddr.h *****************************/\n"
  },
  {
    "path": "REDALERT/IPXCONN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXCONN.CPP 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   IPXConnClass::IPXConnClass -- class constructor           \t\t\t\t*\n *   IPXConnClass::~IPXConnClass -- class destructor           \t\t\t\t*\n *   IPXConnClass::Init -- hardware-specific initialization routine\t\t\t*\n *   IPXConnClass::Configure -- One-time initialization routine\t\t\t\t*\n *   IPXConnClass::Start_Listening -- commands IPX to listen               *\n *   IPXConnClass::Stop_Listening -- commands IPX to stop  listen          *\n *   IPXConnClass::Send -- sends a packet; invoked by SequencedConnection\t*\n *   IPXConnClass::Open_Socket -- opens communications socket    \t\t\t\t*\n *   IPXConnClass::Close_Socket -- closes the socket \t\t\t\t\t\t\t\t*\n *   IPXConnClass::Send_To -- sends the packet to the given address\t\t\t*\n *   IPXConnClass::Broadcast -- broadcasts the given packet\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n#include <string.h>\n#include \"ipxconn.h\"\n\n#ifdef WINSOCK_IPX\n#include \"WSProto.h\"\n\n#else\n\n#include \"ipx95.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#else\t//WIN32\n#include \"fakesock.h\"\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n\n\n/*\n********************************* Globals ***********************************\n*/\nunsigned short \tIPXConnClass::Socket;\nint\t\t\t \t\tIPXConnClass::ConnectionNum;\nECBType *\t\t\tIPXConnClass::ListenECB;\nIPXHeaderType *\tIPXConnClass::ListenHeader;\nchar *\t\t\t\tIPXConnClass::ListenBuf;\nECBType *\t\t\tIPXConnClass::SendECB;\nIPXHeaderType *\tIPXConnClass::SendHeader;\nchar *\t\t\t\tIPXConnClass::SendBuf;\nlong \t\t\t\t\tIPXConnClass::Handler;\nint \t\t\t\t\tIPXConnClass::Configured = 0;\nint \t\t\t\t\tIPXConnClass::SocketOpen = 0;\nint \t\t\t\t\tIPXConnClass::Listening = 0;\nint\t\t\t\t\tIPXConnClass::PacketLen;\n\n\n/***************************************************************************\n * IPXConnClass::IPXConnClass -- class constructor             \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\taddress\t\t\taddress of destination (NULL = no address)\t\t\t\t*\n *\t\tid\t\t\t\t\tconnection's unique numerical ID\t\t\t\t\t\t\t\t*\n *\t\tname\t\t\t\tconnection's name\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t\tmax size of app-specific extra bytes (optional)\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen,\n\tunsigned short magicnum, IPXAddressClass *address, int id, char *name,\n\tint extralen) :\n\tConnectionClass (numsend, numreceive, maxlen, magicnum,\n\t\t2,\t\t\t// retry delta\n\t\t-1,\t\t// max retries\n\t\t60,\t\t// timeout\n\t\textralen)\t// (currently, this is only used by the Global Channel)\n{\n\tNetNumType net;\n\tNetNodeType node;\n\n\t/*------------------------------------------------------------------------\n\tSave the values passed in\n\t------------------------------------------------------------------------*/\n\tif (address)\n\t\tAddress = (*address);\n\tID = id;\n\tstrcpy (Name, name);\n\n#ifdef WINSOCK_IPX\n\tAddress.Get_Address(net,node);\n\tmemcpy(ImmediateAddress,node,6);\n\tImmed_Set = 0;\n#else\n\tif ( !Winsock.Get_Connected() ) {\n\t\t/*------------------------------------------------------------------------\n\t\tIf our Address field is an actual address (ie NULL wasn't passed to the\n\t\tconstructor), pre-compute the ImmediateAddress value for the SendECB.\n\t\tThis allows pre-computing of the ImmediateAddress for all connections\n\t\tcreated after Configure() is called.\n\t\t------------------------------------------------------------------------*/\n\t\tif (!Address.Is_Broadcast() && Configured==1) {\n\t\t\tAddress.Get_Address(net,node);\n\n\t\t\t/*.....................................................................\n\t\t\tIf the user is logged in & has a valid Novell Connection Number, get\n\t\t\tthe bridge address the \"official\" way\n\t\t\t.....................................................................*/\n\t\t\tif (ConnectionNum != 0) {\n\t\t\t\tif (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0) {\n\t\t\t\t\tmemcpy(ImmediateAddress,node,6);\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*.....................................................................\n\t\t\tOtherwise, use the destination node address as the ImmediateAddress,\n\t\t\tand just hope there's no network bridge in the path.\n\t\t\t.....................................................................*/\n\t\t\telse {\n\t\t\t\tmemcpy(ImmediateAddress,node,6);\n\t\t\t}\n\n\t\t\tImmed_Set = 1;\n\t\t}\n\t\telse {\n\t\t\tmemset (ImmediateAddress, 0, 6);\n\t\t\tImmed_Set = 0;\n\t\t}\n\t}\n#endif\t//WINSOCK_IPX\n}\t/* end of IPXConnClass */\n\n\n/***************************************************************************\n * IPXConnClass::Init -- hardware-specific initialization routine\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Init (void)\n{\n\t/*------------------------------------------------------------------------\n\tInvoke the parent's Init routine\n\t------------------------------------------------------------------------*/\n\tConnectionClass::Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * IPXConnClass::Configure -- One-time initialization routine\t\t\t\t\t*\n *                                                                         *\n * This routine sets up static members that are shared by all IPX\t\t\t\t*\n * connections (ie those variables used by the Send/Listen/Broadcast\t\t\t*\n * routines).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * INPUT:                                                                  *\n *\t\tsocket\t\t\t\tsocket ID for sending & receiving\t\t\t\t\t\t*\n *\t\tconn_num\t\t\t\tlocal IPX Connection Number (0 = not logged in)\t\t*\n *\t\tlisten_ecb\t\t\tptr to ECBType for listening\t\t\t\t\t\t\t\t*\n *\t\tsend_ecb\t\t\t\tptr to ECBType for sending\t\t\t\t\t\t\t\t\t*\n *\t\tlisten_header\t\tptr to IPXHeaderType for listening\t\t\t\t\t\t*\n *\t\tsend_header\t\t\tptr to IPXHeaderType for sending\t\t\t\t\t\t\t*\n *\t\tlisten_buf\t\t\tptr to buffer for listening\t\t\t\t\t\t\t\t*\n *\t\tsend_buf\t\t\t\tptr to buffer for sending\t\t\t\t\t\t\t\t\t*\n *\t\thandler_rm_ptr\t\tREAL-MODE pointer to event service routine\t\t\t*\n *\t\t\t\t\t\t\t\t(high word = segment, low word = offset)\t\t\t\t*\n *\t\tmaxpacketlen\t\tmax packet size to listen for\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- All pointers must be protected-mode pointers, but must point to\t\t*\n *\t\t  DOS real-mode memory (except the Handler segment/offset)\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Configure (unsigned short socket, int conn_num,\n\tECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header,\n\tIPXHeaderType *send_header, char *listen_buf, char *send_buf,\n\tlong handler_rm_ptr, int maxpacketlen)\n{\n\t/*------------------------------------------------------------------------\n\tSave the values passed in\n\t------------------------------------------------------------------------*/\n\tSocket = socket;\n\tConnectionNum = conn_num;\n\tListenECB = listen_ecb;\n\tSendECB = send_ecb;\n\tListenHeader = listen_header;\n\tSendHeader = send_header;\n\tListenBuf = listen_buf;\n\tSendBuf = send_buf;\n\tHandler = handler_rm_ptr;\n\tPacketLen = maxpacketlen;\n\n\tConfigured = 1;\n\n}\t/* end of Configure */\n\n\n/***************************************************************************\n * IPXConnClass::Start_Listening -- commands IPX to listen                 *\n *                                                                         *\n * This routine may be used to start listening in polled mode (if the \t\t*\n * ECB's Event_Service_Routine is NULL), or in interrupt mode; it's\t\t\t*\n * up to the caller to fill the ECB in.  If in polled mode, Listening\t\t*\n * must be restarted every time a packet comes in.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- The ListenECB must have been properly filled in by the IPX Manager.*\n *\t\t- Configure must be called before calling this routine.\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Start_Listening(void)\n{\n#ifdef WIN32\n\n#ifdef WINSOCK_IPX\n\t/*\n\t** Open the socket.\n\t*/\n\tif (!Open_Socket(Socket))\n\t\treturn(false);\n\n\t/*\n\t** start listening on the socket.\n\t*/\n\tif ( PacketTransport->Start_Listening () ) {\n\t\tListening =1;\n\t\treturn (true);\n\t} else {\n\t\tClose_Socket(Socket);\n\t\treturn (false);\n\t}\n\n#else\n\tif (Winsock.Get_Connected ()) return (true);\n\n\t/*------------------------------------------------------------------------\n\tOpen the Socket\n\t------------------------------------------------------------------------*/\n\tif (!Open_Socket(Socket))\n\t\treturn(false);\n\n\tif (IPX_Start_Listening95()) {\n\t\tListening =1;\n\t\treturn (true);\n\t} else {\n\t\tClose_Socket(Socket);\n\t\treturn (false);\n\t}\n#endif\t//WINSOCK_IPX\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tunsigned long hdr_val;\n\tvoid *buf_ptr;\n\tunsigned long buf_val;\n\tint rc;\n\n\t/*------------------------------------------------------------------------\n\tDon't do a thing unless we've been configured, and we're not listening.\n\t------------------------------------------------------------------------*/\n\tif (Configured==0 || Listening==1) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Socket\n\t------------------------------------------------------------------------*/\n\tif (!Open_Socket(Socket)) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(ListenECB, 0, sizeof(ECBType));\n\tmemset(ListenHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)ListenHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\n\tbuf_val = (unsigned long)ListenBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in the ECB\n\t------------------------------------------------------------------------*/\n\tListenECB->SocketNumber = Socket;\n\tListenECB->PacketCount = 2;\n\tListenECB->Packet[0].Address = hdr_ptr;\n\tListenECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tListenECB->Packet[1].Address = buf_ptr;\n\tListenECB->Packet[1].Length = (unsigned short)PacketLen;\n\n\t((long &)ListenECB->Event_Service_Routine) = Handler;\n\n\t/*------------------------------------------------------------------------\n\tCommand IPX to listen\n\t------------------------------------------------------------------------*/\n\trc = IPX_Listen_For_Packet(ListenECB);\n\tif (rc!=0) {\n\t\tClose_Socket(Socket);\n\t\treturn(0);\n\t}\n\telse {\n\t\tListening = 1;\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Start_Listening */\n\n\n/***************************************************************************\n * IPXConnClass::Stop_Listening -- commands IPX to stop  listen            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t- This routine MUST NOT be called if IPX is not listening already!\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Stop_Listening(void)\n{\n#ifdef WINSOCK_IPX\n\tif ( PacketTransport ) PacketTransport->Stop_Listening();\n\tListening = 0;\n\n\t//\tAll done.\n\treturn(1);\n#else\n\t/*------------------------------------------------------------------------\n\tDon't do anything unless we're already Listening.\n\t------------------------------------------------------------------------*/\n\tif (Listening==0) {\n\t\treturn(0);\n\t}\n\n#ifdef WIN32\n\n\tif (Winsock.Get_Connected()) {\n\t\tListening = 0;\n\t\treturn (true);\n\t} else {\n\t\tIPX_Shut_Down95();\n\t\tClose_Socket(Socket);\n\t}\n\n#else\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tShut IPX down.\n\t------------------------------------------------------------------------*/\n\tIPX_Cancel_Event(ListenECB);\n\tClose_Socket(Socket);\n\n#endif\t//WIN32\n\n\tListening = 0;\n\n\t/*------------------------------------------------------------------------\n\tAll done.\n\t------------------------------------------------------------------------*/\n\treturn(1);\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Stop_Listening */\n\n\n/***************************************************************************\n * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Send(char *buf, int buflen, void *, int)\n{\n\t/*------------------------------------------------------------------------\n\tInvoke our own Send_To routine, filling in our Address as the destination.\n\t------------------------------------------------------------------------*/\n\tif (Immed_Set) {\n\t\treturn(Send_To (buf, buflen, &Address, ImmediateAddress));\n\t}\n\telse {\n\t\treturn(Send_To (buf, buflen, &Address, NULL));\n\t}\n\n}\t/* end of Send */\n\n\n/***************************************************************************\n * IPXConnClass::Open_Socket -- opens communications socket    \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Open_Socket(unsigned short socket)\n{\n\tint rc;\n#ifdef WINSOCK_IPX\n\trc = PacketTransport->Open_Socket(socket);\n\n\tSocketOpen = rc;\n\treturn ( rc );\n\n#else\t//WINSOCK_IPX\n\tif (Winsock.Get_Connected()) {\n\t\tSocketOpen = 1;\n\t\treturn (true);\n\t}\n\n\tSocketOpen = 0;\n\n\t/*------------------------------------------------------------------------\n\tTry to open a listen socket.  The socket may have been left open by\n\ta previously-crashed program, so ignore the state of the SocketOpen\n\tflag for this call; use IPX to determine if the socket was already open.\n\t------------------------------------------------------------------------*/\n\trc = IPX_Open_Socket(socket);\n\tif (rc) {\n\n\t\t/*.....................................................................\n\t\tIf already open, close & reopen it\n\t\t.....................................................................*/\n\t\tif (rc==IPXERR_SOCKET_ERROR) {\n#ifdef WIN32\n\t\t\tWWDebugString (\"Error -- Specified socket is already open\");\n#endif\t//WIN32\n\t\t\tIPX_Close_Socket(socket);\n\t\t\trc = IPX_Open_Socket(socket);\n\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tStill can't open: return error\n\t\t\t..................................................................*/\n\t\tif (rc) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tSocketOpen = 1;\n\n\treturn(1);\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Open_Socket */\n\n\n/***************************************************************************\n * IPXConnClass::Close_Socket -- closes the socket \t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tCalling this routine when the sockets aren't open may crash!\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXConnClass::Close_Socket(unsigned short socket)\n{\n#ifdef WINSOCK_IPX\n\tsocket = socket;\n\tPacketTransport->Close_Socket();\n\tSocketOpen = 0;\n#else\t//WINSOCK_IPX\n\tif (Winsock.Get_Connected()) {\n\t\tSocketOpen = 0;\n\t\treturn;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNever, ever, ever, under any circumstances whatsoever, close a socket\n\tthat isn't open.  You'll regret it forever (or until at least until\n\tyou're through rebooting, which, if you're on a Pentium is the same\n\tthing).\n\t------------------------------------------------------------------------*/\n\tif (SocketOpen==1) {\n\t\tIPX_Close_Socket(socket);\n\t}\n\n\tSocketOpen = 0;\n#endif\t//WINSOCK_IPX\n}\t/* end of Close_Socket */\n\n\n/***************************************************************************\n * IPXConnClass::Send_To -- sends the packet to the given address\t\t\t\t*\n *                                                                         *\n * The \"ImmediateAddress\" field of the SendECB must be filled in with the\t*\n * address of a bridge, or the node address of the destination if there\t\t*\n * is no bridge.  The NETX call to find this address will always crash\t\t*\n * if NETX isn't loaded (ConnectionNum is 0), so this case is trapped &\t\t*\n * prevented.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Also, if the address of this IPX connection is known when the \t\t\t\t*\n * constructor is called, and Configure has been called, Get_Local_Target \t*\n * is called to precompute the ImmediateAddress; this case is detected & \t*\n * if the value is already computed, it's just memcpy'd over.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tAddress to send to\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\timmed\t\t\tImmediateAddress value, NULL if none\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address,\n\tNetNodeType immed)\n{\n#ifdef WINSOCK_IPX\n\n\timmed = immed;\n\tassert ( immed == NULL );\n\tPacketTransport->WriteTo ( (void*)buf, buflen, (void*) address );\n\treturn (true);\n\n#else\t//WINSOCK_IPX\n\tNetNumType net;\n\tNetNodeType node;\n\tint rc;\n\n#ifdef WIN32\n\n\tunsigned char\tsend_address[6];\n\n\tif (Winsock.Get_Connected()) {\n\t\tWinsock.Write((void*)buf, buflen);\n\t\treturn (true);\n\t}\n\n\tif (immed) {\n\t\tmemcpy(send_address, immed, 6);\n#ifdef FIXIT_DESTNET\n\t\t// fixes DESTNET\n\t\taddress->Get_Address(net,node);\n#else\n\t\t// breaks DESTNET\n\t\tmemcpy(node, immed, 6);\n\t\tmemset (net, 0, sizeof(net) );\n#endif\n\t} else {\n\t\taddress->Get_Address(net,node);\n\t\t/*.....................................................................\n\t\tIf the user is logged in & has a valid Novell Connection Number, get the\n\t\tbridge address the \"official\" way\n\t\t.....................................................................*/\n\t\tif (ConnectionNum != 0) {\n\t\t\trc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]);\n\t\t\tif (rc!=0) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\t\t\t/*.....................................................................\n\t\t\tOtherwise, use the destination node address as the ImmediateAddress, and\n\t\t\tjust hope there's no network bridge in the path.\n\t\t\t.....................................................................*/\n\t\t\tmemcpy(send_address,node,6);\n\t\t}\n\t}\n\n\treturn (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node));\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tvoid *buf_ptr;\n\tunsigned long hdr_val;\n\tunsigned long buf_val;\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(SendECB, 0, sizeof(ECBType));\n\tmemset(SendHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tCopy the message into the SendBuf\n\t------------------------------------------------------------------------*/\n\tmemcpy (SendBuf,buf,buflen);\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)SendHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\tbuf_val = (unsigned long)SendBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in ECB\n\t------------------------------------------------------------------------*/\n\tSendECB->SocketNumber = Socket;\t\t\t\t\t\t// my output socket\n\tSendECB->PacketCount = 2;\t\t\t\t\t\t\t\t// 2 data areas\n\tSendECB->Packet[0].Address = hdr_ptr;\n\tSendECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tSendECB->Packet[1].Address = buf_ptr;\n\tSendECB->Packet[1].Length = (unsigned short)buflen;\n\n\t/*------------------------------------------------------------------------\n\tGet the bridge address\n\t------------------------------------------------------------------------*/\n\tif (immed) {\n\t\tmemcpy(SendECB->ImmediateAddress, immed, 6);\n\t}\n\telse {\n\t\taddress->Get_Address(net,node);\n\n\t\t/*.....................................................................\n\t\tIf the user is logged in & has a valid Novell Connection Number, get\n\t\tthe bridge address the \"official\" way\n\t\t.....................................................................*/\n\t\tif (ConnectionNum != 0) {\n\t\t\trc = IPX_Get_Local_Target (net, node, Socket,\n\t\t\t\tSendECB->ImmediateAddress);\n\t\t\tif (rc!=0) {\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\t\t/*.....................................................................\n\t\tOtherwise, use the destination node address as the ImmediateAddress,\n\t\tand just hope there's no network bridge in the path.\n\t\t.....................................................................*/\n\t\telse {\n\t\t\tmemcpy(SendECB->ImmediateAddress,node,6);\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tFill in outgoing header\n\t------------------------------------------------------------------------*/\n\tSendHeader->PacketType = 4;\t\t\t\t\t\t\t// 4 = IPX packet\n\taddress->Get_Address(SendHeader);\t\t\t\t\t// fill in header addresses\n\tSendHeader->DestNetworkSocket = Socket;\t\t\t// destination socket id\n\n\t/*------------------------------------------------------------------------\n\tSend the packet\n\t------------------------------------------------------------------------*/\n\tIPX_Send_Packet(SendECB);\n\n\t/*------------------------------------------------------------------------\n\tWait for send to complete\n\t------------------------------------------------------------------------*/\n\twhile (SendECB->InUse)\n\t\tLet_IPX_Breath();\n\n\tif (SendECB->CompletionCode!=0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n}\t/* end of Send_To */\n\n\n/***************************************************************************\n * IPXConnClass::Broadcast -- broadcasts the given packet\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\t\tdesired socket ID number\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/16/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXConnClass::Broadcast(char *buf, int buflen)\n{\n#ifdef WINSOCK_IPX\n\tPacketTransport->Broadcast (buf, buflen);\n\treturn (true);\n\n#else\t//WINSOCK_IPX\n\n#ifdef WIN32\n\n\tif (Winsock.Get_Connected()) {\n\t\tWinsock.Write((void*)buf, buflen);\n\t\treturn(true);\n\t} else {\n\t\treturn (IPX_Broadcast_Packet95((unsigned char*)buf, buflen));\n\t}\n\n#else\t//WIN32\n\n\tvoid *hdr_ptr;\n\tvoid *buf_ptr;\n\tunsigned long hdr_val;\n\tunsigned long buf_val;\n\n\t/*------------------------------------------------------------------------\n\tClear the ECB & header\n\t------------------------------------------------------------------------*/\n\tmemset(SendECB, 0, sizeof(ECBType));\n\tmemset(SendHeader, 0, sizeof(IPXHeaderType));\n\n\t/*------------------------------------------------------------------------\n\tCopy the message into the SendBuf\n\t------------------------------------------------------------------------*/\n\tmemcpy (SendBuf,buf,buflen);\n\n\t/*------------------------------------------------------------------------\n\tConvert protected-mode ptrs to real-mode ptrs\n\t------------------------------------------------------------------------*/\n\thdr_val = (unsigned long)SendHeader;\n\thdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));\n\tbuf_val = (unsigned long)SendBuf;\n\tbuf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));\n\n\t/*------------------------------------------------------------------------\n\tFill in ECB\n\t------------------------------------------------------------------------*/\n\tSendECB->SocketNumber = Socket;\t\t\t\t\t\t// my output socket\n\tSendECB->PacketCount = 2;\t\t\t\t\t\t\t\t// 2 data areas\n\tSendECB->Packet[0].Address = hdr_ptr;\n\tSendECB->Packet[0].Length = sizeof(IPXHeaderType);\n\tSendECB->Packet[1].Address = buf_ptr;\n\tSendECB->Packet[1].Length = (unsigned short)buflen;\n\tSendECB->ImmediateAddress[0] = 0xff;\n\tSendECB->ImmediateAddress[1] = 0xff;\n\tSendECB->ImmediateAddress[2] = 0xff;\n\tSendECB->ImmediateAddress[3] = 0xff;\n\tSendECB->ImmediateAddress[4] = 0xff;\n\tSendECB->ImmediateAddress[5] = 0xff;\n\n\t/*------------------------------------------------------------------------\n\tFill in outgoing header\n\t------------------------------------------------------------------------*/\n\tSendHeader->PacketType = 4;\t\t\t\t\t\t\t// 4 = IPX packet\n\tSendHeader->DestNetworkNumber[0] = 0xff;\t\t\t// 0xff = broadcast\n\tSendHeader->DestNetworkNumber[1] = 0xff;\n\tSendHeader->DestNetworkNumber[2] = 0xff;\n\tSendHeader->DestNetworkNumber[3] = 0xff;\n\tSendHeader->DestNetworkNode[0] = 0xff;\t\t\t\t// 0xff = broadcast\n\tSendHeader->DestNetworkNode[1] = 0xff;\n\tSendHeader->DestNetworkNode[2] = 0xff;\n\tSendHeader->DestNetworkNode[3] = 0xff;\n\tSendHeader->DestNetworkNode[4] = 0xff;\n\tSendHeader->DestNetworkNode[5] = 0xff;\n\tSendHeader->DestNetworkSocket = Socket;\t\t\t// destination socket #\n\n\t/*------------------------------------------------------------------------\n\tSend the packet\n\t------------------------------------------------------------------------*/\n\tIPX_Send_Packet(SendECB);\n\n\t/*------------------------------------------------------------------------\n\tWait for send to complete\n\t------------------------------------------------------------------------*/\n\twhile (SendECB->InUse) {\n\t\tLet_IPX_Breath();\n\t}\n\n\tif (SendECB->CompletionCode!=0) {\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n}\t/* end of Broadcast */\n\n/************************** end of ipxconn.cpp *****************************/\n\n"
  },
  {
    "path": "REDALERT/IPXCONN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXCONN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXCONN.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Class for IPX communications.  It inherits\t\t\t*\n * a Queue, PacketBuf, timeout variables from ConnectionClass.  It \t\t\t*\n * inherits its Send_/Receive_/Get_Packet functions, and the sequenced\t\t*\n * ACK/Retry logic in Service_Send_Queue & Service_Receive_Queue from\t\t*\n * SequencedConnClass.  It guarantees order of delivery of packets.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXCONN_H\n#define IPXCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n#include \"ipxaddr.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tVarious useful enums:\n\t\t.....................................................................*/\n\t\tenum IPXConnTag {\n\t\t\tCONN_NAME_MAX = 40\t\t\t// max # chars allowed for connection name\n\t\t};\n\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tIPXConnClass(int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum, IPXAddressClass *address, int id, char *name,\n\t\t\tint extralen = 0);\n\t\tvirtual ~IPXConnClass () {};\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tThe Configure function is for configuring all connections at once.\n\t\tIt's static because it doesn't apply to any specific connection, but\n\t\tall of them.\n\t\t.....................................................................*/\n\t\tstatic void Configure(unsigned short socket,\n\t\t\tint conn_num, ECBType *listen_ecb, ECBType *send_ecb,\n\t\t\tIPXHeaderType *listen_header, IPXHeaderType *send_header,\n\t\t\tchar *listen_buf, char *send_buf, long handler_rm_ptr,\n\t\t\tint maxpacketlen);\n\n\t\t/*.....................................................................\n\t\tThese routines tell IPX to start listening for packets, and to stop\n\t\tlistening for packets.  They're static because they affect all\n\t\tconnections at once (there's no way to turn listening on for only one\n\t\tconnection; it's all or nothing).\n\t\t.....................................................................*/\n\t\tstatic int Start_Listening (void);\n\t\tstatic int Stop_Listening (void);\n\n\t\t/*.....................................................................\n\t\tThe Destination IPX Address for this connection\n\t\t.....................................................................*/\n\t\tIPXAddressClass Address;\n\n\t\t/*.....................................................................\n\t\tThe \"Immediate\" (Bridge) address for this connection, and a flag\n\t\ttelling if the address has been precomputed.\n\t\t.....................................................................*/\n\t\tNetNodeType ImmediateAddress;\n\t\tint Immed_Set;\n\n\t\t/*.....................................................................\n\t\tEach IPX Connection can have a Name & Unique numerical ID\n\t\t.....................................................................*/\n\t\tint ID;\n\t\tchar Name[CONN_NAME_MAX];\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\n\t\t/*.....................................................................\n\t\tThis is the overloaded Send routine declared in ConnectionClass, and\n\t\tused in SequencedConnClass.\n\t\t.....................................................................*/\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n\n\t\t/*.....................................................................\n\t\tThese are the routines that access IPX.  Open_Socket & Close_Socket are\n\t\tstatic because they're called by Start_Listening & Stop_Listening.\n\t\tSend_To & Broadcast are static since they're direct interfaces to IPX,\n\t\tand there's only one IPX instance running.\n\t\t.....................................................................*/\n\t\tstatic int Open_Socket(unsigned short socket);\n\t\tstatic void Close_Socket(unsigned short socket);\n\t\tstatic int Send_To(char *buf, int buflen, IPXAddressClass *address,\n\t\t\tNetNodeType immed);\n\t\tstatic int Broadcast(char *buf, int buflen);\n\n\t\t/*.....................................................................\n\t\tThe socket ID for this connection\n\t\t.....................................................................*/\n\t\tstatic unsigned short Socket;\n\n\t\t/*.....................................................................\n\t\tUser's local Connection # (0 = not logged in)\n\t\t.....................................................................*/\n\t\tstatic int ConnectionNum;\n\n\t\t/*.....................................................................\n\t\tThis is a static version of MaxPacketLen, which is the size of the\n\t\tapp's packets, plus our internal CommHeaderType.  It's used in the\n\t\tStart_Listening routine.\n\t\t.....................................................................*/\n\t\tstatic int PacketLen;\n\n\t\t/*.....................................................................\n\t\tVariables for Listening (created by the IPXManagerClass, and passed\n\t\tin via Init).  All IPX connections share these buffers.\n\t\t.....................................................................*/\n\t\tstatic ECBType *ListenECB;\n\t\tstatic IPXHeaderType *ListenHeader;\n\t\tstatic char *ListenBuf;\n\n\t\t/*.....................................................................\n\t\tVariables for Sending (created by the IPXManagerClass, and passed\n\t\tin via Init).  All IPX connections share these buffers.\n\t\t.....................................................................*/\n\t\tstatic ECBType *SendECB;\n\t\tstatic IPXHeaderType *SendHeader;\n\t\tstatic char *SendBuf;\n\n\t\t/*.....................................................................\n\t\tThis is a REAL-MODE pointer to the event-service-routine for IPX.\n\t\tIf it's 0, IPX will operate in polled mode.  Otherwise, the high word\n\t\tmust contain the segment, and the low word must contain the offset.\n\t\tCS will be the high word value when the routine is called.  (Requiring\n\t\tthe segment/offset to be computed by the caller gives the caller\n\t\tcontrol over CS.)\n\t\t.....................................................................*/\n\t\tstatic long Handler;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if Configure() has been called or not.\n\t\t.....................................................................*/\n\t\tstatic int Configured;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if the socket has been opened or not.\n\t\t.....................................................................*/\n\t\tstatic int SocketOpen;\n\n\t\t/*.....................................................................\n\t\tThis status flag tells us if Start_Listening() has been called or not.\n\t\t.....................................................................*/\n\t\tstatic int Listening;\n};\n\n#endif\n\n/*************************** end of ipxconn.h ******************************/\n"
  },
  {
    "path": "REDALERT/IPXGCONN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXGCONN.CPP 3     10/13/97 2:20p Steve_t $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXGCONN.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : July 6, 1995 [BRR]                       *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   IPXGlobalConnClass::IPXGlobalConnClass -- class constructor           *\n *   IPXGlobalConnClass::~IPXGlobalConnClass -- class destructor           *\n *   IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *   IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue*\n *   IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue*\n *   IPXGlobalConnClass::Send -- sends a packet\t\t\t\t\t\t\t\t\t\t*\n *   IPXGlobalConnClass::Service_Receive_Queue -- services receive queue\t*\n *   IPXGlobalConnClass::Set_Bridge -- Sets up connection to cross a bridge*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <stdio.h>\n//#include <mem.h>\n#include \"ipxgconn.h\"\n\n\n/***************************************************************************\n * IPXGlobalConnClass::IPXGlobalConnClass -- class constructor             *\n *                                                                         *\n * This routine chains to the parent constructor, but it adjusts the size\t*\n * of the packet by the added bytes in the GlobalHeaderType structure.  \t*\n * This forces the parent classes to allocate the proper sized PacketBuf\t*\n * for outgoing packets, and to set MaxPacketLen to the proper value.\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the receive queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\tunique ID for this product\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXGlobalConnClass::IPXGlobalConnClass (int numsend, int numreceive,\n\tint maxlen, unsigned short product_id) :\n\tIPXConnClass (numsend, numreceive,\n\t\tmaxlen + sizeof(GlobalHeaderType) - sizeof(CommHeaderType),\n\t\tGLOBAL_MAGICNUM, \t\t// magic number for this connection\n\t\tNULL,\t\t\t\t\t\t// IPX Address (none)\n\t\t0, \t\t\t\t\t\t// Connection ID\n\t\t\"\",\t\t\t\t\t\t// Connection Name\n\t\tsizeof (IPXAddressClass))\t// extra storage for the sender's address\n{\n\tint i;\n\n\tProductID = product_id;\n\tIsBridge = 0;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tLastPacketID[i] = 0xffffffff;\n\t}\n\tLastRXIndex = 0;\n\n}\t/* end of IPXGlobalConnClass */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a GlobalHeaderType and\t\t*\n * queues the resulting packet into the Send Queue.  The packet's \t\t\t*\n * MagicNumber, Code, PacketID, destination Address and ProductID are set \t*\n * here. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\taddress to send the packet to (NULL = Broadcast)\t\t\t*\n *\t\tack_req\t\t1 = ACK is required for this packet; 0 = isn't\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Send_Packet (void * buf, int buflen,\n\tIPXAddressClass *address, int ack_req)\n{\n\tIPXAddressClass dest_addr;\n\n\t/*------------------------------------------------------------------------\n\tStore the packet's Magic Number\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->Header.MagicNumber = MagicNum;\n\n\t/*------------------------------------------------------------------------\n\tIf this is a ACK-required packet, sent to a specific system, mark it as\n\tACK-required; otherwise, mark as no-ACK-required.\n\t------------------------------------------------------------------------*/\n\tif (ack_req && address != NULL) {\n\t\t((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_ACK;\n\t}\n\telse {\n\t\t((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_NOACK;\n\t}\n\n\t/*------------------------------------------------------------------------\n\tFill in the packet ID.  This will have very limited meaning; it only\n\tallows us to determine if an ACK packet we receive later goes with this\n\tpacket; it doesn't let us detect re-sends of other systems' packets.\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->Header.PacketID = Queue->Send_Total();\n\n\t/*------------------------------------------------------------------------\n\tSet the product ID for this packet.\n\t------------------------------------------------------------------------*/\n\t((GlobalHeaderType *)PacketBuf)->ProductID = ProductID;\n\n\t/*------------------------------------------------------------------------\n\tSet this packet's destination address.  If no address is specified, use\n\ta Broadcast address (which IPXAddressClass's default constructor creates).\n\t------------------------------------------------------------------------*/\n\tif (address != NULL) {\n\t\tdest_addr = (*address);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCopy the application's data\n\t------------------------------------------------------------------------*/\n\tmemcpy(PacketBuf + sizeof(GlobalHeaderType), buf, buflen);\n\n\t/*------------------------------------------------------------------------\n\tQueue it, along with the destination address\n\t------------------------------------------------------------------------*/\n\treturn(Queue->Queue_Send(PacketBuf,buflen + sizeof(GlobalHeaderType),\n\t\t&dest_addr, sizeof (IPXAddressClass)));\n\n}\t/* end of Send_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes GlobalHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *\t\taddress\tthe address of the sender (the IPX Manager class must\t\t\t*\n *\t\t\t\t\textract this from the IPX Header of the received packet.)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Receive_Packet (void * buf, int buflen,\n\tIPXAddressClass *address)\n{\n\tGlobalHeaderType *packet;\t\t\t\t// ptr to this packet\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tGlobalHeaderType *entry_data;\t\t\t// ptr to queue entry data\n\tGlobalHeaderType ackpacket;\t\t\t// ACK packet to send\n\tint i;\n\tint resend;\n\n\t/*------------------------------------------------------------------------\n\tCheck the magic #\n\t------------------------------------------------------------------------*/\n\tpacket = (GlobalHeaderType *)buf;\n\tif (packet->Header.MagicNumber!=MagicNum) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tProcess the packet based on its Code\n\t------------------------------------------------------------------------*/\n\tswitch (packet->Header.Code) {\n\t\t//.....................................................................\n\t\t// DATA_ACK: Check for a resend by comparing the source address &\n\t\t// ID of this packet with our last 4 received packets.\n\t\t// Send an ACK for the packet, regardless of whether it's a resend\n\t\t// or not.\n\t\t//.....................................................................\n\t\tcase PACKET_DATA_ACK:\n\t\t{\n\t\t\t//..................................................................\n\t\t\t// Check for a resend\n\t\t\t//..................................................................\n\t\t\tresend = 0;\n\t\t\tfor (i = 0; i < 4; i++) {\n\t\t\t\tif ((unsigned int)i >= Queue->Receive_Total()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ((*address)==LastAddress[i] &&\n\t\t\t\t\tpacket->Header.PacketID==LastPacketID[i]) {\n\t\t\t\t\tresend = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbool send_ack = true;\n\n\t\t\t//..................................................................\n\t\t\t// If it's not a resend, queue it; then, record the sender's address\n\t\t\t// & the packet ID for future resend detection.\n\t\t\t//..................................................................\n\t\t\tif (!resend) {\n\t\t\t\tif (Queue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass))) {\n\t\t\t\t\tLastAddress[LastRXIndex] = (*address);\n\t\t\t\t\tLastPacketID[LastRXIndex] = packet->Header.PacketID;\n\t\t\t\t\tLastRXIndex++;\n\t\t\t\t\tif (LastRXIndex >= 4) {\n\t\t\t\t\t\tLastRXIndex = 0;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t//..................................................................\n\t\t\t\t\t// Don't send an ack if we didn't have room to store the packet.\n\t\t\t\t\t//..................................................................\n\t\t\t\t\tsend_ack = false;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t//..................................................................\n\t\t\t// Send an ACK for this packet\n\t\t\t//..................................................................\n\t\t\tif (send_ack) {\n\t\t\t\tackpacket.Header.MagicNumber = MagicNum;\n\t\t\t\tackpacket.Header.Code = PACKET_ACK;\n\t\t\t\tackpacket.Header.PacketID = packet->Header.PacketID;\n\t\t\t\tackpacket.ProductID = ProductID;\n\t\t\t\tSend ((char *)&ackpacket, sizeof(GlobalHeaderType),\n\t\t\t\t\taddress, sizeof(IPXAddressClass));\n\t\t\t}\n\n\n\t\t\tbreak;\n\t\t}\n\t\t/*.....................................................................\n\t\tDATA_NOACK: Queue this message, along with the sender's address.\n\t\tDon't bother checking for a Re-Send, since the other system will only\n\t\tsend this packet once.\n\t\t.....................................................................*/\n\t\tcase PACKET_DATA_NOACK:\n\t\t\tQueue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass));\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tACK: If this ACK is for any of my packets, mark that packet as\n\t\tacknowledged, then throw this packet away.  Otherwise, ignore the ACK\n\t\t(if we re-sent before we received the other system's first ACK, this\n\t\tACK will be a leftover)\n\t\t.....................................................................*/\n\t\tcase PACKET_ACK:\n\t\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t\t/*...............................................................\n\t\t\t\tGet queue entry ptr\n\t\t\t\t...............................................................*/\n\t\t\t\tsend_entry = Queue->Get_Send(i);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ptr is valid, get ptr to its data\n\t\t\t\t...............................................................*/\n\t\t\t\tentry_data = (GlobalHeaderType *)(send_entry->Buffer);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf ACK is for this entry, mark it\n\t\t\t\t...............................................................*/\n\t\t\t\tif (packet->Header.PacketID==entry_data->Header.PacketID &&\n\t\t\t\t\tentry_data->Header.Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tDefault: ignore the packet\n\t\t.....................................................................*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn(1);\n\n}\t/* end of Receive_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t*\n *\t\taddress\t\tfilled in with sender's address\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\tfilled in with sender's ProductID\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Get_Packet (void * buf, int *buflen,\n\tIPXAddressClass *address, unsigned short *product_id)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tGlobalHeaderType *packet;\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\n\t/*------------------------------------------------------------------------\n\tReturn if nothing to do\n\t------------------------------------------------------------------------*/\n\tif (Queue->Num_Receive() == 0) {\n\t\treturn(0);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tGet ptr to the next available entry\n\t------------------------------------------------------------------------*/\n\trec_entry = Queue->Get_Receive(0);\n\n\t/*------------------------------------------------------------------------\n\tRead it if it's un-read\n\t------------------------------------------------------------------------*/\n\tif (rec_entry!=NULL && rec_entry->IsRead==0) {\n\n\t\t/*.....................................................................\n\t\tMark as read\n\t\t.....................................................................*/\n\t\trec_entry->IsRead = 1;\n\n\t\t/*.....................................................................\n\t\tCopy data packet\n\t\t.....................................................................*/\n\t\tpacket = (GlobalHeaderType *)(rec_entry->Buffer);\n\t\tpacketlen = rec_entry->BufLen - sizeof(GlobalHeaderType);\n\t\tif (packetlen > 0) {\n\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(GlobalHeaderType), packetlen);\n\t\t}\n\t\t(*buflen) = packetlen;\n\t\t(*product_id) = packet->ProductID;\n\t\t(*address) = (*((IPXAddressClass *)(rec_entry->ExtraBuffer)));\n\n\t\treturn(1);\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Packet */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Send -- sends a packet\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine gets invoked by NonSequencedConn, when it's processing\t\t*\n * the Send & Receive Queues.  The buffer provided will already have the\t*\n * GlobalHeaderType header embedded in it.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\textra buffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\tlength of extra buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Send(char *buf, int buflen, void *extrabuf, int )\n{\n\tIPXAddressClass *addr;\n\tint rc;\n\n\t/*------------------------------------------------------------------------\n\tExtract the packet's embedded IPX address\n\t------------------------------------------------------------------------*/\n\taddr = (IPXAddressClass *)extrabuf;\n\n\t/*------------------------------------------------------------------------\n\tIf it's a broadcast address, broadcast it\n\t------------------------------------------------------------------------*/\n\tif (addr->Is_Broadcast()) {\n\t\treturn(Broadcast (buf, buflen));\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOtherwise, send it\n\t------------------------------------------------------------------------*/\n\telse {\n\t\tif (IsBridge && !memcmp (addr, BridgeNet, 4)) {\n\t\t\trc = Send_To (buf, buflen, addr, BridgeNode);\n\t\t}\n\t\telse {\n\t\t\trc = Send_To (buf, buflen, addr, NULL);\n\t\t}\n\t\treturn (rc);\n\t}\n\n} \t/* end of Send */\n\n\n/***************************************************************************\n * IPXGlobalConnClass::Service_Receive_Queue -- services the receive queue\t*\n *                                                                         *\n * This routine is necessary because the regular ConnectionClass checks\t\t*\n * for sequential packet ID's before removing them from the receive queue;\t*\n * this class cannot do that.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXGlobalConnClass::Service_Receive_Queue (void)\n{\n\tint i;\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\n\t//------------------------------------------------------------------------\n\t// Remove all dead packets:  If a packet's been read, throw it away.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tQueue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);\n\t\t\ti--;\n\t\t}\n\t}\n\n\treturn (1);\n\n} \t/* end of Service_Receive_Queue */\n\n\n/***************************************************************************\n * Set_Bridge -- Sets up connection to cross a bridge                      *\n *                                                                         *\n * This routine is designed to prevent the connection from having to\t\t\t*\n * call Get_Local_Target, except the minimum number of times, since that\t*\n * routine is buggy & goes away for long periods sometimes.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbridge\t\tnetwork number of the destination bridge\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXGlobalConnClass::Set_Bridge(NetNumType bridge)\n{\n#ifdef WINSOCK_IPX\n\n\tif (Configured) {\n\t\tbridge = bridge;\n\t\tIsBridge = 0;\n\t}\n\n#else\t//WINSOCK_IPX\n\tif (Configured) {\n\t\tmemcpy (BridgeNet, bridge, 4);\n\t\tmemset (BridgeNode, 0xff, 6);\n\n\t\tif (IPX_Get_Local_Target (BridgeNet, BridgeNode, Socket, BridgeNode)==0) {\n\t\t\tIsBridge = 1;\n\t\t}\n\t\telse {\n\t\t\tIsBridge = 0;\n\t\t}\n\t}\n#endif\t//WINSOCK_IPX\n\n} \t/* end of Set_Bridge */\n\n\n/************************** end of ipxgconn.cpp ****************************/\n"
  },
  {
    "path": "REDALERT/IPXGCONN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXGCONN.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXGCONN.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 11, 1995   [BR]                 \t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class is a special type of IPX Connection.  It can talk to more\t\t*\n * than one system at a time.  It can Broadcast packets to all systems,\t\t*\n * or send a packet to one individual system.  The packets it sends to\t\t*\n * individual systems can be DATA_NOACK or DATA_ACK packets, but the\t\t\t*\n * packets broadcast have to be DATA_NOACK packets.  This class is for\t\t*\n * only the crudest \"Who-are-you\" type of network communications.  Once\t\t*\n * the IPX Address of another system is identified, a \"real\" IPX\t\t\t\t*\n * Connection should be created, & further communications done through it.\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This means that the packet ID field no longer can be used to detect\t\t*\n * resends, since the receive queue may receive a lot more packets than\t\t*\n * we send out.  So, re-sends cannot be detected; the application must be\t*\n * designed so that it can handle multiple copies of the same packet.\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The class uses a slightly different header from the normal Connections;\t*\n * this header includes the ProductID of the sender, so multiple \t\t\t\t*\n * applications can share the same socket, but by using different product\t*\n * ID's, can distinguish between their own packets & others.\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tBecause of this additional header, and because Receive ACK/Retry logic\t*\n * is different (we can't detect resends), the following routines are\t\t*\n * overloaded:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tSend_Packet:\t\tmust embed the product ID into the packet header\t*\n *\t\tReceive_Packet:\tmust detect resends via the LastAddress & \t\t\t*\n *\t\t\t\t\t\t\t\tLastPacketID arrays. This class doesn't ACK \t\t\t*\n *\t\t\t\t\t\t\t\tpackets until Service_Receive_Queue is called; \t\t*\n *\t\t\t\t\t\t\t\tthe parent classes ACK the packet when it's \t\t\t*\n *\t\t\t\t\t\t\t\treceived.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tGet_Packet:\t\t\textracts the product ID from the header;\t\t\t\t*\n *\t\t\t\t\t\t\t\tdoesn't care about reading packets in order\t\t\t*\n *\t\tSend\t\t\t\t\tis capable of broadcasting the packet, or sending\t*\n *\t\t\t\t\t\t\t\tto a specific address\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tThis class also has the ability to cross a Novell Network Bridge.\t\t\t*\n * You provide the class with the bridge address, and subsequent\t\t\t\t*\n * broadcasts are sent across the bridge as well as to the local network.\t*\n * Address-specific sends contain the destination network's address,\t\t\t*\n * so they cross a bridge automatically; it's just the broadcasts\t\t\t\t*\n * that need to know the bridge address.\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXGLOBALCONN_H\n#define IPXGLOBALCONN_H\n\n\n#include \"ipxconn.h\"\n\n\n/*\n********************************** Defines **********************************\n*/\n//---------------------------------------------------------------------------\n// This is the header for Global Connection messages.  It includes the usual\n// \"standard\" header that the other connections do; but it also includes an\n// IPX address field, so the application can get the address of the sender\n// of this message.  This address field must be provided in by the IPX\n// Connection Manager class, when it calls this class's Receive_Packet\n// function.\n//---------------------------------------------------------------------------\ntypedef struct {\n\tCommHeaderType Header;\n\tunsigned short ProductID;\n} GlobalHeaderType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXGlobalConnClass : public IPXConnClass\n{\n\t//------------------------------------------------------------------------\n\t// Public Interface\n\t//------------------------------------------------------------------------\n\tpublic:\n\t\t//.....................................................................\n\t\t// Some useful enums:\n\t\t//.....................................................................\n\t\tenum GlobalConnectionEnum {\n\t\t\t//..................................................................\n\t\t\t// This is the magic number for all Global Connections.  Having the\n\t\t\t// same magic number across products lets us ID different products\n\t\t\t// on the net.  If you change the fundamental connection protocol,\n\t\t\t// you must use a different magic number.\n\t\t\t//..................................................................\n\t\t\t//GLOBAL_MAGICNUM = 0x1234,\t// used for C&C 1\n\t\t\tGLOBAL_MAGICNUM = 0x1235,\t\t// used for C&C 0\n\t\t\t//..................................................................\n\t\t\t// These are the values used for the ProductID field in the Global\n\t\t\t// Message structure.  It also should be the Magic Number used for\n\t\t\t// the private connections within that product.\n\t\t\t// This list should be continually updated & kept current.  Never\n\t\t\t// ever ever use an old product ID for your product!\n\t\t\t//..................................................................\n\t\t\tCOMMAND_AND_CONQUER = 0xaa01,\n\t\t\tCOMMAND_AND_CONQUER0 = 0xaa00\n\t\t};\n\n\t\t//.....................................................................\n\t\t// Constructor/destructor.\n\t\t//.....................................................................\n\t\tIPXGlobalConnClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short product_id);\n\t\tvirtual ~IPXGlobalConnClass () {};\n\n\t\t//.....................................................................\n\t\t// Send/Receive routines.\n\t\t//.....................................................................\n\t\tvirtual int Send_Packet (void * buf, int buflen,\n\t\t\tIPXAddressClass *address, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen,\n\t\t\tIPXAddressClass *address);\n\t\tvirtual int Get_Packet (void * buf, int *buflen,\n\t\t\tIPXAddressClass *address, unsigned short *product_id);\n\n\t\t//.....................................................................\n\t\t// This is for telling the connection it can cross a bridge.\n\t\t//.....................................................................\n\t\tvoid Set_Bridge (NetNumType bridge);\n\n\t\t//.....................................................................\n\t\t// The Product ID for this product.\n\t\t//.....................................................................\n\t\tunsigned short ProductID;\n\n\t\t//.....................................................................\n\t\t// This describes the address of a bridge we have to cross.  This class\n\t\t// supports crossing only one bridge.  Storing the bridge's network\n\t\t// number allows us to obtain its local target address only once, then\n\t\t// re-use it.\n\t\t//.....................................................................\n\t\tNetNumType BridgeNet;\n\t\tNetNodeType BridgeNode;\n\t\tint IsBridge;\n\n\t//------------------------------------------------------------------------\n\t// Protected Interface\n\t//------------------------------------------------------------------------\n\tprotected:\n\n\t\t//.....................................................................\n\t\t// This is the overloaded Send routine declared in ConnectionClass, and\n\t\t// used in SequencedConnClass.  This special version sends to the address\n\t\t// stored in the extra buffer within the Queue.\n\t\t//.....................................................................\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n\n\t\t//.....................................................................\n\t\t// This routine is overloaded from SequencedConnClass, because the\n\t\t// Global Connection needs to ACK its packets differently from the\n\t\t// other connections.\n\t\t//.....................................................................\n\t\tvirtual int Service_Receive_Queue (void);\n\n\tprivate:\n\t\t//.....................................................................\n\t\t// Since we can't detect resends by using the PacketID (since we're\n\t\t// receiving packets from a variety of sources, all using different\n\t\t// ID's), we'll have to remember the last 'n' packet addresses & id's\n\t\t// for comparison purposes.\n\t\t// Note that, if network traffic is heavy, it's still possible for an\n\t\t// app to receive the same packet twice!\n\t\t//.....................................................................\n\t\tIPXAddressClass LastAddress[4];\t// array of last 4 addresses\n\t\tunsigned long LastPacketID[4];\t// array of last 4 packet ID's\n\t\tint LastRXIndex;\t\t\t\t\t\t// index of next avail pos\n};\n\n#endif\n\n/*************************** end of ipxgconn.h *****************************/\n"
  },
  {
    "path": "REDALERT/IPXMGR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXMGR.CPP 3     10/13/97 2:20p Steve_t $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXMGR.CPP                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : May 4, 1995 [BRR]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                       \t\t\t*\n *   IPXManagerClass::IPXManagerClass -- class constructor                 *\n *   IPXManagerClass::~IPXManagerClass -- class destructor                 *\n *   IPXManagerClass::Init -- initialization routine\t\t\t\t\t\t\t\t*\n *   IPXManagerClass::Is_IPX -- tells if IPX is installed or not\t\t\t\t*\n *   IPXManagerClass::Set_Timing -- sets timing for all connections\t\t\t*\n *   IPXManagerClass::Create_Connection -- creates a new connection        *\n *   IPXManagerClass::Delete_Connection -- deletes a connection            *\n *   IPXManagerClass::Num_Connections -- gets the # of connections\t\t\t*\n *   IPXManagerClass::Connection_ID -- gets the given connection's ID      *\n *   IPXManagerClass::Connection_Name -- gets name for given connection    *\n *   IPXManagerClass::Connection_Address -- retrieves connection's address\t*\n *   IPXManagerClass::Connection_Index -- gets given connection's index    *\n *   IPXManagerClass::Set_Connection_Parms -- sets connection's name & id\t*\n *   IPXManagerClass::Send_Global_Message -- sends a Global Message\t\t\t*\n *   IPXManagerClass::Get_Global_Message -- polls the Global Message queue\t*\n *   IPXManagerClass::Send_Private_Message -- Sends a Private Message\t\t*\n *   IPXManagerClass::Get_Private_Message -- Polls Private Message queue\t*\n *   IPXManagerClass::Service -- main polling routine for IPX Connections\t*\n *   IPXManagerClass::Get_Bad_Connection -- returns bad connection ID      *\n *   IPXManagerClass::Global_Num_Send\t-- gets # entries in send queue\t   *\n *   IPXManagerClass::Global_Num_Receive -- gets # entries in recv queue   *\n *   IPXManagerClass::Private_Num_Send -- gets # entries in send queue\t   *\n *   IPXManagerClass::Private_Num_Receive -- gets # entries in recv queue  *\n *   IPXManagerClass::Set_Bridge -- prepares to cross a bridge             *\n *   IPXManagerClass::Set_Socket -- sets socket ID for all connections\t\t*\n *   IPXManagerClass::Response_Time -- Returns largest Avg Response Time   *\n *   IPXManagerClass::Global_Response_Time -- Returns Avg Response Time    *\n *   IPXManagerClass::Reset_Response_Time -- Reset response time \t\t\t\t*\n *   IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf           *\n *   IPXManagerClass::Mono_Debug_Print -- debug output routine\t\t\t\t\t*\n *   IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory\t\t*\n *   IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include <stdio.h>\n//#include <mem.h> PG\n//#include <i86.h> PG\n#include \"ipxmgr.h\"\n#include \"wwlib32.h\"\t// to enable mono output\n\n#ifdef WINSOCK_IPX\n\n#include \"WSProto.h\"\n#include \"WSPIPX.h\"\n\n#else\t//WINSOCK_IPX\n\n#include \"ipx95.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#else\n#include\t\"fakesock.h\"\n#endif\t//WIN32\n\n#endif\t//WINSOCK_IPX\n\n// Turn off \"expression is not meaningful\".\n//#pragma warning 628 9\n\n//#include \"WolDebug.h\"\n\n/***************************************************************************\n * IPXManagerClass::IPXManagerClass -- class constructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tglb_maxlen\t\tGlobal Channel maximum packet length\t\t\t\t\t\t*\n *\t\tpvt_maxlen\t\tPrivate Channel maximum packet length\t\t\t\t\t\t*\n *\t\tsocket\t\t\tsocket ID to use\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\ta unique numerical ID for this product\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThe socket number is byte-swapped, since IPX requires socket ID's\t\t*\n *\t\tto be stored high/low.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXManagerClass::IPXManagerClass (int glb_maxlen, int pvt_maxlen,\n\tint glb_num_packets, int pvt_num_packets, unsigned short socket,\n\tunsigned short product_id)\n{\n\tint i;\n#ifdef WINSOCK_IPX\n\t/*\n\t** Find out if Packet protocol services are available through Winsock.\n\t*/\n\tif ( PacketTransport ) {\n\t\tdelete  PacketTransport;\n\t\tPacketTransport = NULL;\n\t}\n\tPacketTransport = new WinsockInterfaceClass;\n\tassert ( PacketTransport != NULL );\n\n\tif ( PacketTransport->Init() ){\n\t\tIPXStatus = 1;\n\t}else{\n\t\tIPXStatus = 0;\n\t}\n\tdelete PacketTransport;\n\tPacketTransport = NULL;\n\n#else\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize data members\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t//\tIPXStatus = 1 if IPX is installed, 0 if not\n\t//........................................................................\n\tif (IPX_SPX_Installed()==0) {\n\t\tIPXStatus = 0;\n\t}\n\telse {\n\t\tIPXStatus = 1;\n\t}\n#endif\t//WINSOCK_IPX\n\n\t//........................................................................\n\t//\tSet listening state flag to off\n\t//........................................................................\n\tListening = 0;\n\n\t//........................................................................\n\t//\tNo memory has been alloc'd yet\n\t//........................................................................\n\tRealMemAllocd = 0;\n\n\t//........................................................................\n\t//\tSet max packet sizes, for allocating real-mode memory\n\t//........................................................................\n\tGlb_MaxPacketLen = glb_maxlen;\n\tGlb_NumPackets = glb_num_packets;\n\tPvt_MaxPacketLen = pvt_maxlen;\n\tPvt_NumPackets = pvt_num_packets;\n\n\t//........................................................................\n\t//\tSave the app's product ID\n\t//........................................................................\n\tProductID = product_id;\n\n\t//........................................................................\n\t//\tSave our socket ID number\n\t//........................................................................\n\tSocket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |\n\t\t(((unsigned long)socket & 0xff00) >> 8));\n\n\t//------------------------------------------------------------------------\n\t//\tGet the user's IPX local connection number\n\t//------------------------------------------------------------------------\n\tConnectionNum = 0;\n#ifndef WINSOCK_IPX\n\tif (IPXStatus) {\n\t\tConnectionNum = IPX_Get_Connection_Number();\n\t}\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tInit connection states\n\t//------------------------------------------------------------------------\n\tNumConnections = 0;\n\tCurConnection = 0;\n\tfor (i = 0; i < CONNECT_MAX; i++) {\n\t\tConnection[i] = 0;\n\t}\n\tGlobalChannel = 0;\n\n\tSendOverflows = 0;\n\tReceiveOverflows = 0;\n\tBadConnection = CONNECTION_NONE;\n\n\t//------------------------------------------------------------------------\n\t//\tInit timing parameters\n\t//------------------------------------------------------------------------\n\tRetryDelta = 2;\t\t// 2 ticks between retries\n\tMaxRetries = -1;\t\t// disregard # retries\n\tTimeout = 60;\t\t\t// report bad connection after 1 second\n\n}\t/* end of IPXManagerClass */\n\n\n/***************************************************************************\n * IPXManagerClass::~IPXManagerClass -- class destructor                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nIPXManagerClass::~IPXManagerClass()\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tStop all IPX events\n\t//------------------------------------------------------------------------\n\tif (Listening) {\n\t\tIPXConnClass::Stop_Listening();\n\t\tListening = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree all protected-mode memory\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tdelete GlobalChannel;\n\t\tGlobalChannel = 0;\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tdelete Connection[i];\n\t\tConnection[i] = 0;\n\t}\n\tNumConnections = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tFree all real-mode memory\n\t//------------------------------------------------------------------------\n\tif (RealMemAllocd) {\n\t\tFree_RealMode_Mem();\n\t\tRealMemAllocd = 0;\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n#ifndef WINSOCK_IPX\n//PG\tUnload_IPX_Dll();\n#endif\n#endif\n#endif\n}\t/* end of ~IPXManagerClass */\n\n\n/***************************************************************************\n * IPXManagerClass::Init -- initialization routine\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine allocates memory, & initializes variables\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Init()\n{\n\tint i;\n\n\tif (Session.Type != GAME_INTERNET) {\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tError if IPX not installed\n\t\t//------------------------------------------------------------------------\n\t\tif (!IPXStatus) {\n\t\t\treturn(0);\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tStop Listening\n\t\t//------------------------------------------------------------------------\n\t\tif (Listening) {\n\t\t\tIPXConnClass::Stop_Listening();\n\t\t\tListening = 0;\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tFree Real-mode memory\n\t\t//------------------------------------------------------------------------\n\t\tif (RealMemAllocd) {\n\t\t\tFree_RealMode_Mem();\n\t\t\tRealMemAllocd = 0;\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t** Pretend IPX is available for Internet games whether it is or not\n\t\t*/\n\t\tIPXStatus = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree protected-mode memory\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tdelete GlobalChannel;\n\t\tGlobalChannel = 0;\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tdelete Connection[i];\n\t\tConnection[i] = 0;\n\t}\n\tNumConnections = 0;\n\n\tif (Session.Type != GAME_INTERNET) {\n\t\t//------------------------------------------------------------------------\n\t\t//\tAllocate real-mode memory\n\t\t//------------------------------------------------------------------------\n\t\tif (!Alloc_RealMode_Mem()) return(0);\n\t\tRealMemAllocd = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate the Global Channel\n\t//------------------------------------------------------------------------\n\tGlobalChannel = new IPXGlobalConnClass (Glb_NumPackets, Glb_NumPackets,\n\t\tGlb_MaxPacketLen, ProductID);\n\tif (!GlobalChannel) {\n\t\treturn(0);\n\t}\n\tGlobalChannel->Init();\n\tGlobalChannel->Set_Retry_Delta (RetryDelta);\n\tGlobalChannel->Set_Max_Retries (MaxRetries);\n\tGlobalChannel->Set_TimeOut (Timeout);\n\n\t//------------------------------------------------------------------------\n\t//\tConfigure the IPX Connections\n\t//------------------------------------------------------------------------\n\tIPXConnClass::Configure(Socket, ConnectionNum, ListenECB, SendECB,\n\t\tFirstHeaderBuf, SendHeader, FirstDataBuf, SendBuf, Handler, PacketLen);\n\n\t//------------------------------------------------------------------------\n\t//\tStart Listening\n\t//------------------------------------------------------------------------\n\tif (Session.Type != GAME_INTERNET) {\n\t\tif (!IPXConnClass::Start_Listening()) return(0);\n\t}\n\tListening = 1;\n\n\treturn(1);\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * IPXManagerClass::Is_IPX -- tells if IPX is installed or not\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = IPX is installed; 0 = isn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Is_IPX(void)\n{\n\treturn(IPXStatus);\n\n}\t/* end of Is_IPX */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Timing -- sets timing for all connections\t\t\t\t*\n *                                                                         *\n * This will set the timing parameters for all existing connections, and\t*\n * all connections created from now on.  This allows an application to\t\t*\n * measure the Response_Time while running, and adjust timing accordingly.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tretrydelta\tvalue to set for retry delta \t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxretries\tvalue to set for max # retries\t\t\t\t\t\t\t\t\t*\n *\t\ttimeout\t\tvalue to set for connection timeout\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Timing (unsigned long retrydelta,\n\tunsigned long maxretries, unsigned long timeout)\n{\n\tint i;\n\n\tRetryDelta = retrydelta;\n\tMaxRetries = maxretries;\n\tTimeout = timeout;\n\n\tif (GlobalChannel) {\n\t\tGlobalChannel->Set_Retry_Delta (RetryDelta);\n\t\tGlobalChannel->Set_Max_Retries (MaxRetries);\n\t\tGlobalChannel->Set_TimeOut (Timeout);\n\t}\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tConnection[i]->Set_Retry_Delta (RetryDelta);\n\t\tConnection[i]->Set_Max_Retries (MaxRetries);\n\t\tConnection[i]->Set_TimeOut (Timeout);\n\t}\n\n}\t/* end of Set_Timing */\n\n\n/***************************************************************************\n * IPXManagerClass::Create_Connection -- creates a new connection          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\t\tapplication-specific numerical ID for this connection\t\t*\n *\t\tnode\t\t\tptr to IPXNodeIDType (name & address)\t\t\t\t\t\t\t*\n *\t\taddress\t\tIPX address for this connection\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNever create a connection with an 'id' of -1.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Create_Connection(int id, char *name,\n\tIPXAddressClass *address)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tError if no more room\n\t//------------------------------------------------------------------------\n\tif (NumConnections==CONNECT_MAX) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCreate new connection\n\t//------------------------------------------------------------------------\n\tConnection[NumConnections] = new IPXConnClass(Pvt_NumPackets,\n\t\tPvt_NumPackets, Pvt_MaxPacketLen, ProductID, address, id, name);\n\tif (!Connection[NumConnections]) {\n\t\treturn(0);\n\t}\n\n\tConnection[NumConnections]->Init ();\n\tConnection[NumConnections]->Set_Retry_Delta (RetryDelta);\n\tConnection[NumConnections]->Set_Max_Retries (MaxRetries);\n\tConnection[NumConnections]->Set_TimeOut (Timeout);\n\n\tNumConnections++;\n\n\treturn(1);\n\n}\t/* end of Create_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Delete_Connection -- deletes a connection              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to delete\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Delete_Connection(int id)\n{\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tError if no connections to delete\n\t//------------------------------------------------------------------------\n\tif (NumConnections==0) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLoop through all connections\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumConnections; i++) {\n\t\t//.....................................................................\n\t\t//\tIf a match, delete it\n\t\t//.....................................................................\n\t\tif (Connection[i]->ID==id) {\n\t\t\tdelete Connection[i];\n\n\t\t\t//..................................................................\n\t\t\t//\tMove array elements back one index\n\t\t\t//..................................................................\n\t\t\tfor (j = i; j < NumConnections - 1; j++) {\n\t\t\t\tConnection[j] = Connection[j+1];\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tAdjust counters\n\t\t\t//..................................................................\n\t\t\tNumConnections--;\n\t\t\tif (CurConnection >= NumConnections)\n\t\t\t\tCurConnection = 0;\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNo match; error\n\t//------------------------------------------------------------------------\n\treturn(0);\n\n}\t/* end of Delete_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Num_Connections -- gets the # of connections\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# of connections\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Num_Connections(void)\n{\n\treturn(NumConnections);\n\n}\t/* end of Num_Connections */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_ID -- gets the given connection's ID        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex of connection to retrieve\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tID for that connection, CONNECTION_NONE if invalid index\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Connection_ID(int index)\n{\n\tif (index >= 0 && index < NumConnections) {\n\t\treturn(Connection[index]->ID);\n\t}\n\telse {\n\t\treturn(CONNECTION_NONE);\n\t}\n}\t/* end of Connection_ID */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Name -- retrieves name for given connection *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to get name of\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to connection's name, NULL if not found\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nchar *IPXManagerClass::Connection_Name(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(Connection[i]->Name);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t/* end of Connection_Name */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Address -- retrieves connection's address\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to get address for\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tpointer to IXPAddressClass, NULL if not found\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/19/1995 BR : Created.                                              *\n *=========================================================================*/\nIPXAddressClass * IPXManagerClass::Connection_Address(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(&Connection[i]->Address);\n\t\t}\n\t}\n\n\treturn(NULL);\n\n}\t/* end of Connection_Address */\n\n\n/***************************************************************************\n * IPXManagerClass::Connection_Index -- gets given connection's index      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tID to retrieve index for\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tindex for this connection, CONNECTION_NONE if not found\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Connection_Index(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (Connection[i]->ID==id) {\n\t\t\treturn(i);\n\t\t}\n\t}\n\n\treturn(CONNECTION_NONE);\n\n}\t/* end of Connection_Index */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Connection_Parms -- sets connection's name & id\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\tconnection index\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\tnew connection ID\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tname\t\tnew connection name\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Connection_Parms(int index, int id, char *name)\n{\n\tif (index >= NumConnections)\n\t\treturn;\n\n\tConnection[index]->ID = id;\n\tstrcpy(Connection[index]->Name,name);\n\n}\t/* end of Set_Connection_Parms */\n\n\n/***************************************************************************\n * IPXManagerClass::Send_Global_Message -- sends a Global Message\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buf\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK required; 0 = no ACK required\t\t\t\t\t\t\t*\n *\t\taddress\t\taddress to send to; NULL = broadcast\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Send_Global_Message(void *buf, int buflen,\n\tint ack_req, IPXAddressClass *address)\n{\n\tint rc;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) return(0);\n\n\trc = GlobalChannel->Send_Packet (buf, buflen, address, ack_req);\n\tif (!rc) {\n\t\tSendOverflows++;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Send_Global_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Get_Global_Message -- polls the Global Message queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store received packet\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\t\tlength of data placed in 'buf'\t\t\t\t\t\t\t\t*\n *\t\taddress\t\t\tIPX address of sender\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tproduct_id\t\tproduct ID of sender\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Get_Global_Message(void *buf, int *buflen,\n\tIPXAddressClass *address, unsigned short *product_id)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) return(0);\n\n\treturn(GlobalChannel->Get_Packet (buf, buflen, address, product_id));\n\n}\t/* end of Get_Global_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Send_Private_Message -- Sends a Private Message\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tconnection ID to send to (CONNECTION_NONE = all)\t\t\t*\n *\t\tack_req\t\t1 = ACK required; 0 = no ACK required\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Send_Private_Message(void *buf, int buflen, int ack_req,\n\tint conn_id)\n{\n\tint i;\t\t\t\t\t\t// loop counter\n\tint connect_idx;\t\t\t// index of channel to send to, if specified\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the message to all connections\n\t//------------------------------------------------------------------------\n\tif (conn_id==CONNECTION_NONE) {\n\t\t//.....................................................................\n\t\t//\tCheck for room in all connections\n\t\t//.....................................................................\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Send() ==\n\t\t\t\tConnection[i]->Queue->Max_Send()) {\n\t\t\t\tSendOverflows++;\n\t\t\t\treturn(0);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend packet to all connections\n\t\t//.....................................................................\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tConnection[i]->Send_Packet (buf, buflen, ack_req);\n\t\t}\n\t\treturn(1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the message to the specified connection\n\t//------------------------------------------------------------------------\n\telse {\n\t\tconnect_idx = Connection_Index (conn_id);\n\t\tif (connect_idx == CONNECTION_NONE) {\n\t\t\tSendOverflows++;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tCheck for room in the connection\n\t\t//.....................................................................\n\t\tif (Connection[connect_idx]->Queue->Num_Send() ==\n\t\t\tConnection[connect_idx]->Queue->Max_Send()) {\n\t\t\tSendOverflows++;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend the packet to that connection\n\t\t//.....................................................................\n\t\tConnection[connect_idx]->Send_Packet (buf, buflen, ack_req);\n\t\treturn(1);\n\t}\n\n}\t/* end of Send_Private_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Get_Private_Message -- Polls the Private Message queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store incoming packet\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of data placed in 'buf'\t\t\t\t\t\t\t\t\t*\n *\t\tconn_id\t\tfilled in with connection ID of sender\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Get_Private_Message(void *buf, int *buflen, int *conn_id)\n{\n\tint i;\n\tint rc;\n\tint c_id;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSafety check: ensure CurConnection is in range.\n\t//------------------------------------------------------------------------\n\tif (CurConnection >= NumConnections) {\n\t\tCurConnection = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tScan all connections for a received packet, starting with 'CurConnection'\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumConnections; i++) {\n\n\t\t//.....................................................................\n\t\t//\tCheck this connection for a packet\n\t\t//.....................................................................\n\t\trc = Connection[CurConnection]->Get_Packet (buf, buflen);\n\t\tc_id = Connection[CurConnection]->ID;\n\n\t\t//.....................................................................\n\t\t//\tIncrement CurConnection to the next connection index\n\t\t//.....................................................................\n\t\tCurConnection++;\n\t\tif (CurConnection >= NumConnections) {\n\t\t\tCurConnection = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf we got a packet, return the connection ID\n\t\t//.....................................................................\n\t\tif (rc) {\n\t\t\t(*conn_id) = c_id;\n\t\t\treturn(1);\n\t\t}\n\t}\n\n\treturn(0);\n\n}\t/* end of Get_Private_Message */\n\n\n/***************************************************************************\n * IPXManagerClass::Service -- main polling routine for IPX Connections\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Service(void)\n{\n\tint rc = 1;\n\tint i;\n\tCommHeaderType *packet;\n\tint packetlen;\n\tIPXAddressClass address;\n\n#ifdef WINSOCK_IPX\n\n\n\tunsigned char temp_receive_buffer[1024];\n\tint\ttemp_receive_buffer_len;\n\tint\ttemp_address_len;\n\n\n\tchar temp_address [128];\n\n\tif ( PacketTransport ) {\n\n\t\tdo {\n\t\t\ttemp_receive_buffer_len = sizeof (temp_receive_buffer);\n\t\t\ttemp_address_len = sizeof (temp_address);\n\t\t\tpacketlen = PacketTransport->Read ( temp_receive_buffer, temp_receive_buffer_len, temp_address, temp_address_len );\n\t\t\tif ( packetlen ) {\n\t\t\t\tCurDataBuf = (char*)temp_receive_buffer;\n\t\t\t\taddress = *((IPXAddressClass*) temp_address);\n\n\t\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Put the packet in the Global Queue\n\t\t\t\t\t*/\n\t\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t} else {\n\t\t\t\t\tif (packet->MagicNumber == ProductID) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Find the Private Queue that this packet is for\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbool found_address = false;\n\t\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\t\tfound_address = true;\n\t\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( Session.Type == GAME_INTERNET )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** This packet came from an unknown source. If it looks like one of our players\n\t\t\t\t\t\t\t** packets then it might be from a player whos IP has changed.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (!found_address) {\n\t\t\t\t\t\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_NOACK){\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** Magic number and packet code are valid. It's probably a C&C packet.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tEventClass *event = (EventClass*) (((char*) packet) + sizeof (CommHeaderType));\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** If this is a framesync packet then grab the address and match it to an existing player.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (event->Type == EventClass::FRAMESYNC) {\n\t\t\t\t\t\t\t\t\t\tint id = event->ID;\n\n\t\t\t\t\t\t\t\t\t\tassert (id != PlayerPtr->ID);\n\t\t\t\t\t\t\t\t\t\tfor ( int i=1 ; i<Session.Players.Count() ; i++) {\n\t\t\t\t\t\t\t\t\t\t\tif (Session.Players[i]->Player.ID == id) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tint iConnectionIndex = Connection_Index(id);\n\t\t\t\t\t\t\t\t\t\t\t\tif( iConnectionIndex != CONNECTION_NONE ) //\t(else Create_Connections() has not yet been called)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\t\t\t** Found a likely candidate. Update his address. It should be OK to drop this\n\t\t\t\t\t\t\t\t\t\t\t\t\t** packet since it's a framesync packet and will will pick up the next one.\n\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.Players[i]->Address = address;\n\t\t\t\t\t\t\t\t\t\t\t\t\tConnection[iConnectionIndex]->Address = address;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (packetlen);\n\n\t}\n\n\n\n\n#else\t//WINSOCK_IPX\n\n#ifdef WIN32\n\n\tunsigned char temp_receive_buffer[1024];\n\tint\trecv_length;\n\n\tif (Winsock.Get_Connected() || Special.IsFromWChat) {\n\n\t\tif (!Winsock.Get_Connected()) return (0);\n\n\t\t/*\n\t\t** This is an internet connection so get the packets from winsock\n\t\t*/\n\t\twhile ((recv_length = Winsock.Read(temp_receive_buffer, 1024))!=0) {\n\n\t\t\tCurHeaderBuf = NULL;\n\t\t\tCurDataBuf = (char*)&temp_receive_buffer[0];\n\n\t\t\t/*.....................................................................\n\t\t\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t\t.....................................................................*/\n\t\t\tpacketlen = recv_length;\n\n\t\t\t/*.....................................................................\n\t\t\tExtract the sender's address from the IPX header\n\t\t\t.....................................................................*/\n\t\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t\t/*.....................................................................\n\t\t\tExamine the Magic Number of the received packet to determine if this\n\t\t\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t\t.....................................................................*/\n\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\t\t\t\t/*..................................................................\n\t\t\t\tPut the packet in the Global Queue\n\t\t\t\t..................................................................*/\n\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\tReceiveOverflows++;\n\t\t\t} else {\n\t\t\t\tif (packet->MagicNumber == ProductID) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tFind the Private Queue that this packet is for\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t} else {\n#if(0)//PG\n\t\twhile (IPX_Get_Outstanding_Buffer95(&temp_receive_buffer[0])) {\n\n\t\t\tCurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0];\n\t\t\tCurDataBuf = (char*)&temp_receive_buffer[sizeof(IPXHeaderType)];\n\n\t\t\t/*.....................................................................\n\t\t\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t\t.....................................................................*/\n\t\t\tpacketlen = ((CurHeaderBuf->Length & 0xff) << 8) |\n\t\t\t\t(CurHeaderBuf->Length >> 8);\n\t\t\tpacketlen -= sizeof(IPXHeaderType);\n\n\t\t\t/*.....................................................................\n\t\t\tExtract the sender's address from the IPX header\n\t\t\t.....................................................................*/\n\t\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t\t/*.....................................................................\n\t\t\tExamine the Magic Number of the received packet to determine if this\n\t\t\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t\t.....................................................................*/\n\t\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\t\t\t\t/*..................................................................\n\t\t\t\tPut the packet in the Global Queue\n\t\t\t\t..................................................................*/\n\t\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address))\n\t\t\t\t\tReceiveOverflows++;\n\t\t\t} else {\n\t\t\t\tif (packet->MagicNumber == ProductID) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tFind the Private Queue that this packet is for\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen))\n\t\t\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n\n#else\t//WIN32\n\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLoop until there are no more packets to process.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\n\t\t//.....................................................................\n\t\t//\tCheck the BufferFlags for the \"current\" buffer; if it's empty,\n\t\t//\tbreak; out of the loop.\n\t\t//.....................................................................\n\t\tif (BufferFlags[CurIndex]==0) {\n\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tCompute the length of the packet (byte-swap the length in the IPX hdr)\n\t\t//.....................................................................\n\t\tpacketlen = ((CurHeaderBuf->Length & 0xff) << 8) |\n\t\t\t(CurHeaderBuf->Length >> 8);\n\t\tpacketlen -= sizeof(IPXHeaderType);\n\n\t\t//.....................................................................\n\t\t//\tExtract the sender's address from the IPX header\n\t\t//.....................................................................\n\t\taddress.Set_Address (CurHeaderBuf);\n\n\t\t//.....................................................................\n\t\t//\tExamine the Magic Number of the received packet to determine if this\n\t\t//\tpacket goes into the Global Queue, or into one of the Private Queues\n\t\t//.....................................................................\n\t\tpacket = (CommHeaderType *)CurDataBuf;\n\t\tif (packet->MagicNumber == GlobalChannel->Magic_Num()) {\n\n\t\t\t//..................................................................\n\t\t\t//\tPut the packet in the Global Queue\n\t\t\t//..................................................................\n\t\t\tif (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) {\n\t\t\t\tReceiveOverflows++;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tFind the Private Queue that this packet is for\n\t\t//.....................................................................\n\t\telse if (packet->MagicNumber == ProductID) {\n\t\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\t\tif (Connection[i]->Address == address) {\n\t\t\t\t\tif (!Connection[i]->Receive_Packet (packet, packetlen)) {\n\t\t\t\t\t\tReceiveOverflows++;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSet the current BufferFlags to 0 (since we've cleaned out this buffer)\n\t\t//.....................................................................\n\t\tBufferFlags[CurIndex] = 0;\n\n\t\t//.....................................................................\n\t\t//\tGo to the next packet buffer\n\t\t//.....................................................................\n\t\tCurIndex++;\n\t\tCurHeaderBuf = (IPXHeaderType *)(((char *)CurHeaderBuf) + FullPacketLen);\n\t\tCurDataBuf = ((char *)CurDataBuf) + FullPacketLen;\n\t\tif (CurIndex >= NumBufs) {\n\t\t\tCurHeaderBuf = FirstHeaderBuf;\n\t\t\tCurDataBuf = FirstDataBuf;\n\t\t\tCurIndex = 0;\n\t\t}\n\t}\n\n#endif\t//WIN32\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tService all connections.  If a connection reports that it's gone \"bad\",\n\t//\treport an error to the caller.  If it's the Global Channel, un-queue the\n\t//\tsend entry that's holding things up.  This will keep the Global Channel\n\t//\tfrom being clogged by one un-ACK'd outgoing packet.\n\t//------------------------------------------------------------------------\n\tif (GlobalChannel) {\n\t\tif (!GlobalChannel->Service()) {\n\t\t\tGlobalChannel->Queue->UnQueue_Send (NULL, NULL, 0);\n\t\t\trc = 0;\n\t\t}\n\t}\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tif (!Connection[i]->Service()) {\n\t\t\trc = 0;\n\t\t\tBadConnection = Connection[i]->ID;\n\t\t}\n\t}\n\n\tif (rc) {\n\t\tBadConnection = CONNECTION_NONE;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Service */\n\n/***************************************************************************\n * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tID of bad connection; CONNECTION_NONE if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint IPXManagerClass::Get_Bad_Connection(void)\n{\n\treturn(BadConnection);\n\n}\t/* end of Get_Bad_Connection */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Num_Send\t-- reports # entries in send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Global Send Queue\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Global_Num_Send(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\treturn(GlobalChannel->Queue->Num_Send());\n\n}\t/* end of Global_Num_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Num_Receive -- reports # entries in recv queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Global Receive Queue\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Global_Num_Receive(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening) {\n\t\treturn(0);\n\t}\n\n\treturn(GlobalChannel->Queue->Num_Receive());\n\n}\t/* end of Global_Num_Receive */\n\n\n/***************************************************************************\n * IPXManagerClass::Private_Num_Send -- reports # entries in send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\t# entries in the Private Send Queue\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Private_Num_Send(int id)\n{\n\tint i;\n\tint maxnum;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf connection ID specified, return that connection's # of packets\n\t//------------------------------------------------------------------------\n\tif (id != CONNECTION_NONE) {\n\t\ti = Connection_Index(id);\n\t\tif (i != CONNECTION_NONE) {\n\t\t\treturn(Connection[i]->Queue->Num_Send());\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, return the max # of all connections\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmaxnum = 0;\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Send() > maxnum) {\n\t\t\t\tmaxnum = Connection[i]->Queue->Num_Send();\n\t\t\t}\n\t\t}\n\t\treturn(maxnum);\n\t}\n\n}\t/* end of Private_Num_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Private_Num_Receive -- reports # entries in recv queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\tID of connection to query\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# entries in the Private Receive Queue\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Private_Num_Receive(int id)\n{\n\tint i;\n\tint maxnum;\n\n\t//------------------------------------------------------------------------\n\t//\tError if IPX not installed or not Listening\n\t//------------------------------------------------------------------------\n\tif (!IPXStatus || !Listening || (NumConnections==0))\n\t\treturn(0);\n\n\t//------------------------------------------------------------------------\n\t//\tIf connection ID specified, return that connection's # of packets\n\t//------------------------------------------------------------------------\n\tif (id != CONNECTION_NONE) {\n\t\ti = Connection_Index(id);\n\t\tif (i != CONNECTION_NONE) {\n\t\t\treturn(Connection[i]->Queue->Num_Receive());\n\t\t}\n\t\telse {\n\t\t\treturn(0);\n\t\t}\n\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tOtherwise, return the max # of all connections\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmaxnum = 0;\n\t\tfor (i = 0; i < NumConnections; i++) {\n\t\t\tif (Connection[i]->Queue->Num_Receive() > maxnum) {\n\t\t\t\tmaxnum = Connection[i]->Queue->Num_Receive();\n\t\t\t}\n\t\t}\n\t\treturn(maxnum);\n\t}\n\n}\t/* end of Private_Num_Receive */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Socket -- sets socket ID for all connections\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsocket\tnew socket ID to use\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tDo not call this function after communications have started; you\t\t*\n *\t\tmust call it before calling Init().\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tThe socket number is byte-swapped, since IPX requires socket ID's\t\t*\n *\t\tto be stored high/low.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Socket(unsigned short socket)\n{\n\tSocket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |\n\t\t(((unsigned long)socket & 0xff00) >> 8));\n\n}\t/* end of Set_Socket */\n\n\n/***************************************************************************\n * IPXManagerClass::Response_Time -- Returns largest Avg Response Time     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tlargest avg response time\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long IPXManagerClass::Response_Time(void)\n{\n\tunsigned long resp;\n\tunsigned long maxresp = 0;\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tresp = Connection[i]->Queue->Avg_Response_Time();\n\t\tif (resp > maxresp) {\n\t\t\tmaxresp = resp;\n\t\t}\n\t}\n\n\treturn(maxresp);\n\n}\t/* end of Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tavg global channel response time\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long IPXManagerClass::Global_Response_Time(void)\n{\n\tif (GlobalChannel) {\n\t\treturn (GlobalChannel->Queue->Avg_Response_Time());\n\t}\n\telse {\n\t\treturn (0);\n\t}\n\n}\t/* end of Global_Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Reset_Response_Time -- Reset response time\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Reset_Response_Time(void)\n{\n\tint i;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\t\tConnection[i]->Queue->Reset_Response_Time();\n\t}\n\n\tif (GlobalChannel)\n\t\tGlobalChannel->Queue->Reset_Response_Time();\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tbuf ptr\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid * IPXManagerClass::Oldest_Send(void)\n{\n\tint i,j;\n\tunsigned long time;\n\tunsigned long mintime = 0xffffffff;\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tCommHeaderType *packet;\n\tvoid *buf = NULL;\n\n\tfor (i = 0; i < NumConnections; i++) {\n\n\t\tsend_entry = NULL;\n\n\t\tfor (j = 0; j < Connection[i]->Queue->Num_Send(); j++) {\n\t\t\tsend_entry = Connection[i]->Queue->Get_Send(j);\n\t\t\tif (send_entry) {\n\t\t\t\tpacket = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_ACK &&\n\t\t\t\t\tsend_entry->IsACK == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsend_entry = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (send_entry!=NULL) {\n\n\t\t\ttime = send_entry->FirstTime;\n\n\t\t\tif (time < mintime) {\n\t\t\t\tmintime = time;\n\t\t\t\tbuf = send_entry->Buffer;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(buf);\n\n}\t/* end of Oldest_Send */\n\n\n/***************************************************************************\n * IPXManagerClass::Set_Bridge -- prepares to cross a bridge               *\n *                                                                         *\n * This routine is designed to prevent the connection from having to\t\t\t*\n * call Get_Local_Target, except the minimum number of times, since that\t*\n * routine is buggy & goes away for long periods sometimes.\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbridge\t\tnetwork number of the destination bridge\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Set_Bridge(NetNumType bridge)\n{\n\tif (GlobalChannel) {\n\t\tGlobalChannel->Set_Bridge(bridge);\n\t}\n\n}\t/* end of Set_Bridge */\n\n\n/***************************************************************************\n * IPXManagerClass::Configure_Debug -- sets up special debug values        *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t\tconnection index to configure (-1 = Global Channel)\t*\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tnamestart\t\tnumerical value of 1st name in the array\t\t\t\t\t*\n *\t\tnamecount\t\t# in the names array; 0 if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid IPXManagerClass::Configure_Debug(int index, int type_offset,\n\tint type_size, char **names, int namestart, int namecount)\n{\n\tif (index == -1) {\n\t\tGlobalChannel->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n\t}\n\telse if (Connection[index]) {\n\t\tConnection[index]->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n\t}\n\n}\t/* end of Configure_Debug */\n\n\n/***************************************************************************\n * IPXManagerClass::Mono_Debug_Print -- debug output routine\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\tindex of connection to display (-1 = Global Channel)\t\t*\n *\t\trefresh\t\t1 = complete screen refresh\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/25/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid IPXManagerClass::Mono_Debug_Print(int index, int refresh)\n{\n#ifdef WWLIB32_H\n\tchar txt[80];\n\tint i;\n\n\tif (index == -1)\n\t\tGlobalChannel->Queue->Mono_Debug_Print (refresh);\n\n\telse if (Connection[index])\n\t\tConnection[index]->Queue->Mono_Debug_Print (refresh);\n\n\tif (refresh) {\n\t\tMono_Set_Cursor (20,1);\n\t\tMono_Printf (\"IPX Queue:\");\n\n\t\tMono_Set_Cursor (9,2);\n\t\tMono_Printf (\"Average Response Time:\");\n\n\t\tMono_Set_Cursor (43,1);\n\t\tMono_Printf (\"Send Overflows:\");\n\n\t\tMono_Set_Cursor (40,2);\n\t\tMono_Printf (\"Receive Overflows:\");\n\n\t}\n\n\tMono_Set_Cursor (32,1);\n\tMono_Printf (\"%d\",index);\n\n\tMono_Set_Cursor (32,2);\n\tif (index == -1) {\n\t\tMono_Printf (\"%d  \", GlobalChannel->Queue->Avg_Response_Time());\n\t}\n\telse {\n\t\tMono_Printf (\"%d  \", Connection[index]->Queue->Avg_Response_Time());\n\t}\n\n\tMono_Set_Cursor (59,1);\n\tMono_Printf (\"%d  \", SendOverflows);\n\n\tMono_Set_Cursor (59,2);\n\tMono_Printf (\"%d  \", ReceiveOverflows);\n\n\tfor (i = 0; i < NumBufs; i++) {\n\t\tif (BufferFlags[i]) {\n\t\t\ttxt[i] = 'X';\n\t\t}\n\t\telse {\n\t\t\ttxt[i] = '_';\n\t\t}\n\t}\n\ttxt[i] = 0;\n\tMono_Set_Cursor ((80-NumBufs)/2,3);\n\tMono_Printf (\"%s\",txt);\n\n#else\n\tindex = index;\n\trefresh = refresh;\n#endif\n\n}\t/* end of Mono_Debug_Print */\n\n\n/***************************************************************************\n * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Alloc_RealMode_Mem(void)\n{\n\n#ifdef WIN32\n\treturn (1);\n#else\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tint size;\t\t\t\t\t\t\t\t\t// required size of allocation\n\tunsigned char *realmode;\t\t\t\t// start addresses of real-mode data\n\tint realmodelen;\t\t\t\t\t\t\t// length of real-mode data\n\tunsigned long func_val;\n\tchar *p;\t\t\t\t\t\t\t\t\t\t// for parsing buffer\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute # of buffers we need to allocate, & the max size of each one\n\t//------------------------------------------------------------------------\n\tNumBufs = Glb_NumPackets + (Pvt_NumPackets * CONNECT_MAX);\n\n\tPacketLen = Glb_MaxPacketLen + sizeof (GlobalHeaderType);\n\tif (Pvt_MaxPacketLen + sizeof (CommHeaderType) > PacketLen)\n\t\tPacketLen = Pvt_MaxPacketLen + sizeof (CommHeaderType);\n\n\tFullPacketLen = PacketLen + sizeof(IPXHeaderType);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the size of everything we'll ever need, allocate it in one big\n\t//\tchunk.  The memory is used as follows:\n\t//\t- Real-mode assembly IPX callback routine, plus its data,\n\t//\t  (which includes the ListenECB)\n\t//\t- Array of IPX Packet buffers (IPXHeader plus data buffer)\n\t//\t- SendECB: ECB for sending\n\t//\t- SendHeader: IPX Header for sending\n\t//\t- SendBuf: Packet buffer for sending\n\t//\t- BufferFlags: 1 byte for each incoming packet buffer; 1=in use, 0=free\n\t//------------------------------------------------------------------------\n\trealmode = (unsigned char *)Get_RM_IPX_Address();\n\trealmodelen = Get_RM_IPX_Size();\n\tsize = realmodelen + \t\t\t\t// assembly routine & its data\n\t\t(FullPacketLen * NumBufs) +\t// array of packet buffers\n\t\tsizeof(ECBType) +\t\t\t\t\t// SendECB\n\t\tFullPacketLen +\t\t\t\t\t// SendHeader & SendBuf\n\t\tNumBufs;\t\t\t\t\t\t\t\t// BufferFlags\n\tif (size > 65535) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAllocate DOS memory for the ECB, IPXHeader & packet buffers:\n\t//\tAX = 0x100\n\t//\tBX = # paragraphs to allocate\n\t//\t- if Success, AX = real-mode segment, DX = selector\n\t//\t- if Failure, carry flag is set\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_ALLOC_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((size + 15) >> 4);\t\t\t\t\t\t// # paragraphs to allocate\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// allocate the memory\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the values of the returned segment & selector\n\t//------------------------------------------------------------------------\n\tSelector = regs.w.dx;\n\tSegment = regs.w.ax;\n\tRealMemSize = size;\n\tRealModeData = (RealModeDataType *)(((long)Segment) << 4);\n\n\t//------------------------------------------------------------------------\n\t//\tLock the memory (since we're servicing interrupts with it)\n\t//\tAX = 0x600\n\t//\tBX:CX = starting linear address of memory to lock\n\t//\tSI:DI = size of region to lock (in bytes)\n\t//\t- If Failure, carry flag is set.\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_LOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)RealModeData & 0x0000ffff);\n\tregs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)RealMemSize & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\tmemset (&regs, 0 ,sizeof(regs));\n\t\tsegread (&sregs);\n\t\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\t\tregs.x.edx = Selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\t\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// free the memory\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the Real-mode code into our memory buffer\n\t//------------------------------------------------------------------------\n\tp = (char *)(((long)Segment) << 4);\n\tmemcpy (p,realmode,realmodelen);\n\tp += realmodelen;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute & save the entry point for the real-mode packet handler\n\t//------------------------------------------------------------------------\n\tfunc_val = (unsigned long)RealModeData;\n\tHandler = (((func_val & 0xffff0) << 12) |\n\t\t((func_val & 0x000f) + RealModeData->FuncOffset));\n\n\t//------------------------------------------------------------------------\n\t//\tFill in buffer pointers\n\t//------------------------------------------------------------------------\n\tListenECB = &(RealModeData->ListenECB);\n\n\tFirstHeaderBuf = (IPXHeaderType *)p;\n\tFirstDataBuf = (((char *)FirstHeaderBuf) + sizeof(IPXHeaderType));\n\tCurIndex = 0;\n\tCurHeaderBuf = FirstHeaderBuf;\n\tCurDataBuf = FirstDataBuf;\n\tp += FullPacketLen * NumBufs;\n\n\tSendECB = (ECBType *)p;\n\tp += sizeof (ECBType);\n\n\tSendHeader = (IPXHeaderType *)p;\n\tp += sizeof (IPXHeaderType);\n\n\tSendBuf = (char *)p;\n\tp += PacketLen;\n\n\tBufferFlags = (char *)p;\n\n\t//------------------------------------------------------------------------\n\t//\tFill in the real-mode routine's data (The ECB will be filled in when we\n\t//\tcommand IPX to Listen).\n\t//------------------------------------------------------------------------\n\tRealModeData->NumBufs = (short)NumBufs;\n\tRealModeData->BufferFlags = (char *)\n\t\t((((long)BufferFlags & 0xffff0) << 12) |\n\t\t((long)BufferFlags & 0x0000f));\n\tRealModeData->PacketSize = (short)FullPacketLen;\n\tRealModeData->FirstPacketBuf = (IPXHeaderType *)\n\t\t((((long)FirstHeaderBuf & 0xffff0) << 12) |\n\t\t((long)FirstHeaderBuf & 0x0000f));\n\tRealModeData->CurIndex = 0;\n\tRealModeData->CurPacketBuf = RealModeData->FirstPacketBuf;\n\tRealModeData->Semaphore = 0;\n\tRealModeData->ReEntrantCount = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit state of all buffers to empty\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < NumBufs; i++) {\n\t\tBufferFlags[i] = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCheck the start & end markers in the real-mode memory area\n\t//------------------------------------------------------------------------\n\tif (RealModeData->Marker1 != 0x1111 ||\n\t\tRealModeData->Marker2 != 0x2222) {\n\t\tFree_RealMode_Mem();\n\t\treturn(0);\n\t}\n\telse {\n\t\treturn(1);\n\t}\n#endif\t//WIN32\n}\t/* end of Alloc_Realmode_Mem */\n\n\n/***************************************************************************\n * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint IPXManagerClass::Free_RealMode_Mem(void)\n{\n\n#ifdef WIN32\n\n\treturn (1);\n\n#else\t//WIN32\n\n\tunion REGS regs;\n\tstruct SREGS sregs;\n\tint rc = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tUnlock the memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_UNLOCK_MEM;\t\t\t\t\t\t\t// DPMI function to call\n\tregs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;\n\tregs.x.ecx = ((long)RealModeData & 0x0000ffff);\n\tregs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;\n\tregs.x.edi = ((long)RealMemSize & 0x0000ffff);\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// call DPMI\n\n\t//------------------------------------------------------------------------\n\t//\tIf the carry flag is set, DPMI is indicating an error.\n\t//------------------------------------------------------------------------\n\tif (regs.x.cflag) {\n\t\trc = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFree DOS memory\n\t//------------------------------------------------------------------------\n\tmemset (&regs, 0 ,sizeof(regs));\n\tsegread (&sregs);\n\tregs.x.eax = DPMI_FREE_DOS_MEM;\t\t\t\t\t\t// DPMI function to call\n\tregs.x.edx = Selector;\t\t\t\t\t\t\t\t\t// ptr to free\n\tint386x (DPMI_INT, &regs, &regs, &sregs);\t\t\t// free the memory\n\n\treturn(rc);\n#endif\t//WIN32\n\n}\t/* end of Free_Realmode_Mem */\n\n/*************************** end of ipxmgr.cpp *****************************/\n"
  },
  {
    "path": "REDALERT/IPXMGR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/IPXMGR.H 1     3/03/97 10:24a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : IPXMGR.H                                 *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager for IPX network communications.  It\t\t*\n * creates, manages, & orchestrates multiple IPX connections, as well as\t*\n * the \"global\" connection (\"Global Channel\"), which can talk to any \t\t*\n * system on the net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Use the Global Channel to query systems for their names, ID's, &\t\t\t*\n * IPX addresses.  Then, create a Private Connection with each system\t\t*\n * that joins your game, and use the Private Channel to send game packets\t*\n * (the private channel will perform somewhat faster, & gives you better\t*\n * control than the Global Channel; it can detect retries, and the Global\t*\n * Channel can't).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * HOW THIS CLASS WORKS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This class has to set up an IPX Event Service Routine in low (DOS)\t\t*\n * memory.  So, it uses DPMI to allocate & lock a chunk of DOS memory;\t\t*\n * this memory is used for all incoming packet buffers, the outgoing\t\t\t*\n * packet buffer, and the actual code for the event handler.  The real-\t\t*\n * mode handler code & this class share a portion of memory that's mapped\t*\n * into a \"RealModeDataType\" structure.  As packets come in, the handler\t*\n * points IPX to the next available packet buffer & restarts listening;\t\t*\n * it sets a flag to tell this class that a packet is present at that\t\t*\n * buffer slot.  This class must read all the packets & determine which\t\t*\n * connection they go with (the Global Channel, or one of the Private\t\t*\n * Channels).  This parsing is done in the Service routine for this class.\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Constructor:\tJust inits some variables, checks to see if IPX is there\t*\n * Destructor:\t\tComplete shutdown; stops IPX listening, frees all memory\t*\n * Init:\t\t\t\tShould only be called once (but can be called more); \t\t*\n * \t\t\t\t\tallocates all memory, creates the Global Channel\t\t\t*\n * \t\t\t\t\tconnection, starts IPX listening.  By not placing this \t*\n * \t\t\t\t\tstep in the constructor, the app can control when \t\t\t*\n * \t\t\t\t\tlistening actually starts; also, you don't get a bunch\t*\n *\t\t\t\t\t\tof allocations just by declaring an IPXManagerClass\t\t*\n *\t\t\t\t\t\tinstance.  You have to call Init() for the allocations\t*\n *\t\t\t\t\t\tto occur.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Connection utilities: Create & manage Private Connections.  Each \t\t\t*\n *\t\t\t\t\t\tconnection has its own IPX address, numerical ID, and\t\t*\n *\t\t\t\t\t\tcharacter name (presumably the name of the other\t\t\t*\n *\t\t\t\t\t\tplayer).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Send/Get_Global_Message: adds a packet to the Global Connection queue,\t*\n *\t\t\t\t\t\tor reads from the queue.  The caller should check the\t\t*\n *\t\t\t\t\t\tProductID value from returned packets to be sure it's\t\t*\n *\t\t\t\t\t\ttalking to the right product.\t\t\t\t\t\t\t\t\t\t*\n * Send/Get_Private_Message: adds a packet to a Private Connection queue,\t*\n *\t\t\t\t\t\tor reads from the queue\t\t\t\t\t\t\t\t\t\t\t\t*\n * Service:\t\t\tChecks the Real-Mode-Memory packet array to see if any\t*\n *\t\t\t\t\t\tnew packets have come in; if they have, it parses them\t*\n *\t\t\t\t\t\t& distributes them to the right connection queue.  The\t*\n *\t\t\t\t\t\tqueue's Service routine handles ACK'ing or Resending\t\t*\n *\t\t\t\t\t\tpackets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tHere's a memory map of the Real-Mode memory block.  'N' is the number\t*\n * of packet buffers allocated in low memory:\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t----------------------------------\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|       Shared-memory data       |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  Real-mode event handler code  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 0  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 1  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer 2  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|             . . .              |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|  IPX Header & Packet Buffer N  |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|    Send Event Control Block    |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|         Send IPX Header        |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|       Send Packet Buffer       |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|--------------------------------|\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t|        Flags Array [N]         |\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t----------------------------------\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef IPXMANAGER_H\n#define IPXMANAGER_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"ipxconn.h\"\n#include \"ipxgconn.h\"\n#include \"ipxaddr.h\"\n#include \"connmgr.h\"\n\n/*\n********************************** Defines **********************************\n*/\n/*---------------------------------------------------------------------------\nThis is Virgin Interactive Entertainment's registered socket ID.\n---------------------------------------------------------------------------*/\n#define\tVIRGIN_SOCKET\t\t0x8813\n\n/*---------------------------------------------------------------------------\nThis is the maximum number of IPX connections supported.  Just change this\nvalue to support more.\n---------------------------------------------------------------------------*/\n#define\tCONNECT_MAX\t\t\t7\n\n/*---------------------------------------------------------------------------\nThese routines report the location & length of the real-mode routine, as\nit's stored in protected-mode memory.\n---------------------------------------------------------------------------*/\nextern \"C\" {\n\tvoid * __cdecl Get_RM_IPX_Address(void);\n\tlong __cdecl Get_RM_IPX_Size(void);\n}\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass IPXManagerClass : public ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tIPXManagerClass (int glb_maxlen, int pvt_maxlen, int glb_num_packets,\n\t\t\tint pvt_num_packets, unsigned short socket, unsigned short product_id);\n\t\tvirtual ~IPXManagerClass ();\t// stop listening\n\n\t\t/*.....................................................................\n\t\tInitialization routines.\n\t\t.....................................................................*/\n\t\tint Init (void);\n\t\tint Is_IPX(void);\n\t\tvirtual void Set_Timing (unsigned long retrydelta, unsigned long maxretries,\n\t\t\tunsigned long timeout);\n\t\tvoid Set_Bridge(NetNumType bridge);\n\n\t\t/*.....................................................................\n\t\tThese routines control creation of the \"Connections\" (data queues) for\n\t\teach remote system.\n\t\t.....................................................................*/\n\t\tint Create_Connection(int id, char *name, IPXAddressClass *address);\n\t\tint Delete_Connection(int id);\n\t\tvirtual int Num_Connections(void);\n\t\tvirtual int Connection_ID(int index);\n\t\tchar *Connection_Name(int id);\n\t\tIPXAddressClass * Connection_Address(int id);\n\t\tvirtual int Connection_Index(int id);\n\t\tvoid Set_Connection_Parms(int index, int id, char *name);\n\n\t\t/*.....................................................................\n\t\tThis is how the application sends & receives messages.\n\t\t.....................................................................*/\n\t\tint Send_Global_Message (void *buf, int buflen, int ack_req = 0,\n\t\t\tIPXAddressClass *address = NULL);\n\t\tint Get_Global_Message (void *buf, int *buflen, IPXAddressClass *address,\n\t\t\tunsigned short *product_id);\n\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int conn_id = CONNECTION_NONE);\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen, int *conn_id);\n\n\t\t/*.....................................................................\n\t\tThe main polling routine; should be called as often as possible.\n\t\t.....................................................................*/\n\t\tvirtual int Service (void);\n\n\t\t/*.....................................................................\n\t\tThis routine reports which connection has an error on it.\n\t\t.....................................................................*/\n\t\tint Get_Bad_Connection(void);\n\n\t\t/*.....................................................................\n\t\tQueue utility routines.  The application can determine how many\n\t\tmessages are in the send/receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Global_Num_Send(void);\n\t\tvirtual int Global_Num_Receive(void);\n\t\tvirtual int Private_Num_Send(int id = CONNECTION_NONE);\n\t\tvirtual int Private_Num_Receive(int id = CONNECTION_NONE);\n\n\t\t/*.....................................................................\n\t\tThis routine changes the socket ID assigned the IPX Manager when it\n\t\twas constructed.  Do not call this function after calling Init()!\n\t\tThe Socket ID should be known by both ends of the communications before\n\t\tany packets are sent.\n\t\t.....................................................................*/\n\t\tvoid Set_Socket(unsigned short socket);\n\n\t\t/*.....................................................................\n\t\tRoutines to return the largest average queue response time, and to\n\t\treset the response time for all queues.\n\t\t.....................................................................*/\n\t\tvirtual unsigned long Response_Time(void);\n\t\tunsigned long Global_Response_Time(void);\n\t\tvirtual void Reset_Response_Time(void);\n\n\t\t/*.....................................................................\n\t\tThis routine returns a pointer to the oldest non-ACK'd buffer I've sent.\n\t\t.....................................................................*/\n\t\tvoid * Oldest_Send(void);\n\n\t\t/*.....................................................................\n\t\tDebug routines\n\t\t.....................................................................*/\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount);\n\t\tvirtual void Mono_Debug_Print(int index, int refresh = 0);\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprivate:\n\t\t/*.....................................................................\n\t\tThese routines allocate & free the DOS Real-mode memory block.\n\t\t.....................................................................*/\n\t\tint Alloc_RealMode_Mem(void);\n\t\tint Free_RealMode_Mem(void);\n\n\t\t/*.....................................................................\n\t\tMisc variables\n\t\t.....................................................................*/\n\t\tunsigned int IPXStatus : 1;\t\t// 0 = no IPX, 1 = IPX found\n\t\tunsigned int Listening : 1;\t\t// 1 = Listening is on\n\t\tunsigned int RealMemAllocd : 1;\t// 1 = Real-mode memory has been alloc'd\n\n\t\t/*.....................................................................\n\t\tPacket Sizes, used for allocating real-mode memory\n\t\t.....................................................................*/\n\t\tint Glb_MaxPacketLen;\t\t\t\t// Global Channel maximum packet size\n\t\tint Glb_NumPackets;\t\t\t\t\t// # Global send/receive packets\n\t\tint Pvt_MaxPacketLen;\t\t\t\t// Private Channel maximum packet size\n\t\tint Pvt_NumPackets;\t\t\t\t\t// # Private send/receive packets\n\n\t\t/*.....................................................................\n\t\tThe ProductID is used in the Global Channel's packet header, and it's\n\t\tused for the Private Channels' Magic Number.\n\t\t.....................................................................*/\n\t\tunsigned short ProductID;\t\t\t// product ID\n\n\t\t/*.....................................................................\n\t\tThe Socket ID, and local Novell Connection Number\n\t\t.....................................................................*/\n\t\tunsigned short Socket;\t\t\t\t// Our socket ID for sending/receiving\n\t\tint ConnectionNum;\t\t\t\t\t// local connection #, 0=not logged in\n\n\t\t/*.....................................................................\n\t\tArray of connection queues\n\t\t.....................................................................*/\n\t\tIPXConnClass * Connection[CONNECT_MAX]; // array of connection object ptrs\n\t\tint NumConnections;\t\t\t\t\t\t// # connection objects in use\n\t\tIPXGlobalConnClass *GlobalChannel;\t// the Global Channel\n\n\t\t/*.....................................................................\n\t\tCurrent queue for polling for received packets\n\t\t.....................................................................*/\n\t\tint CurConnection;\n\n\t\t/*.....................................................................\n\t\tTiming parameters for all connections\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\t\tunsigned long MaxRetries;\n\t\tunsigned long Timeout;\n\n\t\t/*---------------------------------------------------------------------\n\t\tReal-mode memory pointers and such\n\t\t---------------------------------------------------------------------*/\n\t\t/*.....................................................................\n\t\tThis is a structure that mirrors data in real-mode memory:\n\t\t.....................................................................*/\n\t\ttypedef struct {\n\t\t\tshort Marker1;\t\t\t\t\t\t\t// the byte ID marker\n\t\t\tECBType ListenECB;\t\t\t\t\t// the Listening ECB\n\t\t\tshort NumBufs;\t\t\t\t\t\t\t// # of buffers we're giving to the handler\n\t\t\tchar *BufferFlags;\t\t\t\t\t// array of buffer-avail flags\n\t\t\tshort PacketSize;\t\t\t\t\t\t// size of packet including IPX header\n\t\t\tIPXHeaderType *FirstPacketBuf;\t// ptr to 1st packet buffer\n\t\t\tshort CurIndex;\t\t\t\t\t\t// handler's current packet index\n\t\t\tIPXHeaderType *CurPacketBuf;\t\t// handler's current packet buf\n\t\t\tshort FuncOffset;\t\t\t\t\t\t// contains offset of code\n\t\t\tchar Semaphore;\t\t\t\t\t\t// prevents re-entrancy\n\t\t\tshort ReEntrantCount;\t\t\t\t// times we've been called re-entrantly\n\t\t\tshort StackPtr;\t\t\t\t\t\t// real-mode stack pointer\n\t\t\tshort StackSeg;\t\t\t\t\t\t// real-mode stack segment\n\t\t\tshort StackPtr_int;\t\t\t\t\t// internal stack pointer\n\t\t\tshort StackSeg_int;\t\t\t\t\t// internal stack segment\n\t\t\tshort StackCheck;\t\t\t\t\t\t// stack check value (0x1234)\n\t\t\tshort Stack[256];\t\t\t\t\t\t// actual stack space\n\t\t\tshort StackSpace;\t\t\t\t\t\t// label for top of stack\n\t\t\tshort Marker2;\t\t\t\t\t\t\t// the byte ID marker\n\t\t} RealModeDataType;\n\n\t\t/*.....................................................................\n\t\tThe number & size of packet buffers in low memory\n\t\t.....................................................................*/\n\t\tint NumBufs;\t\t\t\t\t\t\t\t// # packet buffers allocated\n\t\tint PacketLen;\t\t\t\t\t\t\t\t// size of packet without IPX header\n\t\tint FullPacketLen;\t\t\t\t\t\t// size of packet including IPX header\n\n\t\t/*.....................................................................\n\t\tSelector & Segment of the DOS allocation;\n\t\tSize of the allocation;\n\t\tPtr to the real-mode assembly data area\n\t\t.....................................................................*/\n\t\tunsigned short Selector;\t\t\t\t// selector of DOS allocation pointer\n\t\tunsigned short Segment;\t\t\t\t\t// real-mode segment of DOS allocation\n\t\tint RealMemSize;\t\t\t\t\t\t\t// size of real mode memory allocated\n\t\tRealModeDataType *RealModeData;\t\t// assembly routine & its data\n\n\t\t/*.....................................................................\n\t\tThis is a real-mode pointer to the address of the real-mode assembly\n\t\tentry point.\n\t\t.....................................................................*/\n\t\tlong Handler;\n\n\t\t/*.....................................................................\n\t\tEvent Control Block for listening; contained within the real-mode\n\t\tassembly routine's data area\n\t\t.....................................................................*/\n\t\tECBType *ListenECB;\t\t\t\t\t\t// ECB for listening\n\n\t\t/*.....................................................................\n\t\tptr to the 1st header & data buffers in the packet buffer array\n\t\t.....................................................................*/\n\t\tIPXHeaderType *FirstHeaderBuf;\t\t// array of packet headers & buffers\n\t\tchar *FirstDataBuf;\t\t\t\t\t\t// 1st data buffer area\n\n\t\t/*.....................................................................\n\t\tCurrent packet index & ptrs for parsing packets\n\t\t.....................................................................*/\n\t\tint CurIndex;\t\t\t\t\t\t\t\t// Current packet index, for reading\n\t\tIPXHeaderType *CurHeaderBuf;\t\t\t// Current packet ptr, for reading\n\t\tchar *CurDataBuf;\t\t\t\t\t\t\t// Current actual data ptr\n\n\t\t/*.....................................................................\n\t\tECB, header, & buffer for sending\n\t\t.....................................................................*/\n\t\tECBType *SendECB;\t\t\t\t\t\t\t// ECB for sending\n\t\tIPXHeaderType *SendHeader;\t\t\t\t// Header for sending\n\t\tchar *SendBuf;\t\t\t\t\t\t\t\t// buffer for sending\n\n\t\t/*.....................................................................\n\t\tFlags indicating whether a buffer contains data or not (1 = full)\n\t\tThe IPXManager must clear this flag; the real-mode routine will set it.\n\t\t.....................................................................*/\n\t\tchar *BufferFlags;\t\t\t\t\t\t// array of rx-buffer-avail flags\n\n\t\t/*.....................................................................\n\t\tVarious Statistics\n\t\t.....................................................................*/\n\t\tint SendOverflows;\n\t\tint ReceiveOverflows;\n\t\tint BadConnection;\n};\n\n#endif\n\n/*************************** end of ipxmgr.h *******************************/\n"
  },
  {
    "path": "REDALERT/IPXPROT.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n\n;!!!!!!!!!!!!!!!!!!! lock the allocation\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : VQLIB                                    *\n;*                                                                         *\n;*                    File Name : HANDLER.ASM                              *\n;*                                                                         *\n;*                   Programmer : Bill Randolph                            *\n;*                                                                         *\n;*                   Start Date : April 7, 1995                            *\n;*                                                                         *\n;*                  Last Update : April 7, 1995   [BRR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   IPXHandler -- callback routine for IPX                                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nP386\nMODEL USE32 FLAT\nLOCALS ??\n\n\n;******************************** Includes *********************************\n\n\n;******************************** Defines ***********************************\n\n\n;****************************** Declarations ********************************\nGLOBAL\t C Get_RM_IPX_Address:NEAR\nGLOBAL\t C Get_RM_IPX_Size:NEAR\n\n;********************************* Data ************************************\n\tDATASEG\n\nLABEL \tRealBinStart\tBYTE\ninclude \"obj\\win32\\ipxreal.ibn\"\nLABEL\tRealBinEnd\tBYTE\n\n;********************************* Data ************************************\n\tCODESEG\n\n;***************************************************************************\n;* Get_RM_IPX_Address -- Return address of real mode code for copy.        *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t\t\t\t   *\n;*\tnone                                                               *\n;*                                                                         *\n;* OUTPUT:      \t\t\t\t\t\t\t   *\n;*\tVOID * to the address of the real mode IPX code\t\t\t   *\n;*                                                                         *\n;* PROTO:\t\t\t\t\t\t\t\t   *\n;*\tVOID\t*Get_RM_IPX_Address(VOID);\t\t\t           *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_IPX_Address C Near\n\n\tmov\teax, OFFSET RealBinStart\n\tret\n\n\tENDP\n\n;***************************************************************************\n;* Get_RM_IPX_Size -- return size of real mode IPX code.                   *\n;*                                                                         *\n;* INPUT:\t\t\t\t\t   \t\t\t   *\n;*\tnone                                                               *\n;*                                                                         *\n;* OUTPUT:      \t\t\t\t   \t\t\t   *\n;*\tLONG size of the real mode IPX code                                *\n;*                                                                         *\n;* PROTO:\t\t\t\t\t   \t\t\t   *\n;*\tLONG\tGet_RM_IPX_Size(VOID);\t\t\t\t   \t   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/06/1994 SKB : Created.                                             *\n;*=========================================================================*\n\tPROC\tGet_RM_IPX_Size C Near\n\n\tmov\teax, OFFSET RealBinEnd - OFFSET RealBinStart\n\tret\n\n\tENDP\n\n\tEND\n\n;************************** End of handler.asm *****************************\n"
  },
  {
    "path": "REDALERT/IPXREAL.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : VQLIB                                    *\n;*                                                                         *\n;*                    File Name : HANDLER.ASM                              *\n;*                                                                         *\n;*                   Programmer : Bill Randolph                            *\n;*                                                                         *\n;*                   Start Date : April 7, 1995                            *\n;*                                                                         *\n;*                  Last Update : April 7, 1995   [BRR]                    *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   IPXHandler -- callback routine for IPX                                *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n;********************* Model & Processor Directives ************************\nIDEAL\nMODEL LARGE\nP386N\nLOCALS ??\n\n\n;******************************** Includes *********************************\n\n\n;******************************** Defines ***********************************\n\n\n;****************************** Declarations ********************************\nGLOBAL\tIPXHandler:FAR\n\n\n;********************************* Code ************************************\n\tCODESEG\n\n\n;---------------------------------------------------------------------------\n; The markers let the application verify that it's mapping this memory\n; correctly.\n;---------------------------------------------------------------------------\nMarker1\t\t\tDW 1111h\t; placeholder to find data start\n\n;---------------------------------------------------------------------------\n; This is the IPX Event Control Block:\n;---------------------------------------------------------------------------\nECB_LinkAddress\t\tDD ?\nECB_EventServiceRoutine\tDD ?\t\t; Event Handler ptr\nECB_InUse\t\tDB ?\t\t; 0 = event is complete\nECB_CompletionCode\tDB ?\t\t; 0 = OK, IPX error otherwise\nECB_SocketNumber\tDW ?\t\t; socket to listen/send on\nECB_ConnectionID\tDW ?\nECB_RestOfWorkspace\tDW ?\nECB_DriverWorkSpace\tDB 12 DUP (?)\nECB_ImmediateAddress\tDB 6 DUP (?)\t; bridge address\nECB_PacketCount\t\tDW ?\t\t; # data areas (2)\nECB_HeaderAddress\tDD ?\t\t; ptr to IPX header buffer\nECB_HeaderLength\tDW ?\t\t; length of IPX header buffer\nECB_PacketAddress\tDD ? \t\t; ptr to packet buffer\nECB_PacketLength\tDW ?\t\t; length of packet buffer\n\n;---------------------------------------------------------------------------\n; The rest of the variables are for telling IPX which buffer to store the\n; next incoming packet in.  They must be initialized by the application.\n;---------------------------------------------------------------------------\nNumBufs\t\tDW 0\t\t\t; # buffers provided by app\nBufferFlags\tDD 0\t\t\t; array of in-use flags (1 = in use)\nPacketSize\tDW 0\t\t\t; total size of 1 buf (incl IPX hdr)\nFirstPacketBuf\tDD 0\t\t\t; ptr to 1st packet buffer\nCurIndex\tDW 0\t\t\t; current packet/flag index\nCurPacketBuf\tDD 0\t\t\t; ptr to current packet buf\nFuncOffset\tDW StartLabel\t\t; offset of our routine\n\n;---------------------------------------------------------------------------\n; These values are for preventing re-entrancy; they're currently not used.\n;---------------------------------------------------------------------------\nSemaphore\tDB 0\t\t\t; prevents re-entrancy\nReEntrantCount\tDW 0\t\t\t; times we've been called re-entrantly\n\n;---------------------------------------------------------------------------\n; Local stack space\n;---------------------------------------------------------------------------\nStackPtr\tDW 0\t\t\t; saved copy of stack ptr\nStackSeg\tDW 0\t\t\t; saved copy of stack seg\nStackPtr_int\tDW 0\t\t\t; our internal stack ptr\nStackSeg_int\tDW 0\t\t\t; our internal stack seg\nStackCheck\tDW 1234h\t\t; check for stack overflow\n\t\tDW 256 DUP (0)\t\t; stack storage space\nStackSpace\tDW 0\t\t\t; label for our stack space\n\n;---------------------------------------------------------------------------\n; These bytes mark the end of the real-mode data area\n;---------------------------------------------------------------------------\nMarker2\t\tDW 2222h\t\t; placeholder to find data end\n\n\n;***************************************************************************\n;* IPXHandler -- IPX callback routine\t\t\t\t\t   *\n;*                                                                         *\n;* This routine is assembled as a stand-alone executable, then loaded      *\n;* into low DOS memory by a protected-mode application.                    *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* OUTPUT: \t\t\t                                           *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*\tnone.\t\t\t\t\t\t\t\t   *\n;* \t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   04/07/1995 BRR : Created.                                             *\n;*=========================================================================*\n\tlabel StartLabel\n\tPROC\tIPXHandler C FAR USES\n\n\t;...................................................................\n\t; Turn off interrupts; make sure memory copies go forward\n\t;...................................................................\n\tpushf\n\tcli\n\tcld\n\n\t;...................................................................\n\t; Set up segment registers to point DS to CS\n\t;...................................................................\n\tpush\tds\n\tpush\tax\n\tmov\tax,cs\n\tmov\tds,ax\n\n\t;...................................................................\n\t; Set up our local stack; save SS & SP first.\n\t;...................................................................\n\tmov\t[StackSeg],ss\n\tmov\t[StackPtr],sp\n\tmov\t[StackPtr_int], OFFSET StackSpace\n\tmov\t[StackSeg_int], SEG StackSpace\n\tlss\tsp, [DWORD PTR StackPtr_int]\n\t\n\n\t;...................................................................\n\t; Save all registers\n\t;...................................................................\n\tpushad\n\tpush\tes\n\n\t;...................................................................\n\t; If we've been called re-entrantly, just exit\n\t;...................................................................\n\tcmp\t[Semaphore],0\n\tjz\t??Start_Handler\n\tadd\t[ReEntrantCount],1\n\tjmp\t??Exit_Handler\n\n??Start_Handler:\n\t;...................................................................\n\t; Set our semaphore\n\t;...................................................................\n\tmov\t[Semaphore],1\n\n\t;-------------------------------------------------------------------\n\t; Set 'CurIndex' to the index of the next-available receive buffer,\n\t; and 'CurPacketBuf to the next-available packet buffer\n\t;-------------------------------------------------------------------\n\t;...................................................................\n\t; Get 'CurIndex' & increment it.  Wrap to 0 if we reach 'NumBufs'\n\t; Since I'm treating 'CurPacketBuf' as a long integer (and not as\n\t; a segment:offset), the entire data area can't be larger than 64K.\n\t;...................................................................\n\tmov\tdx,[CurIndex]\t\t; DX = CurIndex\n\tmov\teax,[CurPacketBuf]\t; EAX = current packet buffer addr\n\tinc\tdx\t\t\t; DX = next index\n\tadd\tax,[PacketSize]\t\t; EAX = next buffer ptr\n\tcmp\tdx,[NumBufs]\t\t; see if DX is past # buffers\n\tjb\t??Get_Flag\n\tmov\tdx,0\t\t\t; wrap to 1st index\n\tmov\teax,[FirstPacketBuf]\t; wrap to 1st packet buffer\n\n??Get_Flag:\n\t;...................................................................\n\t; Get the next buffer-in-use flag; if it's 0, load [CurIndex] with \n\t; the value of SI (the next index).  If it's 1, skip the updating of\n\t; the index, flag & buffer ptr.\n\t; DX = new CurIndex\n\t; EAX = new CurPacketBuf\n\t;...................................................................\n\tles\tdi,[BufferFlags]\t; ES:DI = BufferFlags address\n\tmov\tbx,di\t\t\t; BX = DI + new CurIndex\n\tadd\tbx,dx\n\n\tcmp\t[BYTE PTR es:bx],0\t; compare next flag to 0 (avail)\n\tjne\t??Set_ECB\t\t; if not avail, skip setting new values\n\n\t;...................................................................\n\t; The next buffer is available; so, set this buffer's In-Use flag\n\t; to 1, and move on to the next buffer.  Do not set this buffer's\n\t; flag to 1 until we move on to the next buffer, to prevent the\n\t; application from reading the currently-in-use packet buffer.\n\t; DX = new CurIndex\n\t; EAX = new CurPacketBuf\n\t; ES:DI = BufferFlags address\n\t;...................................................................\n\tmov\tbx,di\t\t\t; BX = DI + old CurIndex\n\tadd\tbx,[CurIndex]\n\tmov\t[BYTE PTR es:bx],1\t; set old BufferFlags value to in-use\n\n\tmov\t[CurIndex],dx\t\t; save new index\n\tmov\t[CurPacketBuf],eax\t; save new packet address\n\n\t;-------------------------------------------------------------------\n\t; Set up the Event Control Block to tell IPX to start listening.\n\t; The following entries are filled in by the app, and should be left\n\t; alone:\n\t; - EventServiceRoutine\n\t; - SocketNumber\n\t; The rest should be re-initialized.  Note that EBX is now pointing\n\t; to an unavailable buffer if the next buffer was already in use;\n\t; so it must be reloaded with the correct buffer address from\n\t; [CurPacketBuf].\n\t;-------------------------------------------------------------------\n??Set_ECB:\n\tmov\t[ECB_LinkAddress],0\t\t; default\n\tmov\t[ECB_InUse],0\t\t\t; default\n\tmov\t[ECB_CompletionCode],0\t\t; default\n\tmov\t[ECB_ConnectionID],0\t\t; default\n\tmov\t[ECB_RestOfWorkspace],0\t\t; default\n\tmov\t[ECB_DriverWorkSpace],0\t\t; default\n\tmov\t[ECB_ImmediateAddress],0\t; default\n\tmov\t[ECB_PacketCount],2\t\t; use 2 data areas\n\tmov\tebx,[CurPacketBuf]\t\t; get current buffer address\n\tmov\t[ECB_HeaderAddress],ebx\t\t; set header address\n\tmov\t[ECB_HeaderLength],30\t\t; size of IPX header\n\tadd\tebx,30\t\t\t\t; point to past the header\n\tmov\t[ECB_PacketAddress],ebx\t\t; set packet data address\n\tmov\tax,[PacketSize]\t\t\t; get size of one buffer\n\tsub\tax,30\t\t\t\t; remove size of IPX header\n\tmov\t[ECB_PacketLength],ax\t\t; set size of packet data\n\n\t;-------------------------------------------------------------------\n\t; Clear the IPX header for this packet\n\t;-------------------------------------------------------------------\n\tles\tdi,[ECB_HeaderAddress]\t\t; ES:DI = IPX Listen Header\n\tmov\tcx,30\t\t\t\t; (30 bytes = size of header)\n\tmov\tal,0\n\trep\tstosb\t\t\t\t; clear to 0's\n\n\t;-------------------------------------------------------------------\n\t; Command IPX to start listening again.\n\t;-------------------------------------------------------------------\n\tmov\tbx,4\t\t\t\t; IPX code for Listen\n\tmov\tax,ds\t\t\t\t; ES = segment of ListenECB\n\tmov\tes,ax\n\tmov\tax,OFFSET ECB_LinkAddress\t\n\tmov\tsi,ax\t\t\t\t; ES:SI = address of ECB\n\tint\t07ah\t\t\t\t; call IPX interrupt\n\n\t;...................................................................\n\t; Clear our semaphore\n\t;...................................................................\n\tmov\t[Semaphore],0\n\n??Exit_Handler:\n\t;...................................................................\n\t; Pop values from our local stack\n\t;...................................................................\n\tpop\tes\n\tpopad\n\n\t;...................................................................\n\t; Check our stack-check value; if the stack has overflowed, generate\n\t; a debugger break.\n\t;...................................................................\n\tcmp\t[StackCheck],1234h\n\tje\t??Restore_Stack\n\tint\t3\n\n\t;...................................................................\n\t; Restore the stack to its previous value\n\t;...................................................................\n??Restore_Stack:\n\tlss\tsp, [DWORD PTR StackPtr]\n\n\t;...................................................................\n\t; Pop the rest of the registers\n\t;...................................................................\n\tpop\tax\n\tpop\tds\n\n\tpopf\n\n\tret\n\nENDP\t\tIPXHandler\n\nEND\n\n;************************** End of handler.asm *****************************\n"
  },
  {
    "path": "REDALERT/ITABLE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\nunsigned short IndexTable[] = {\n\t0,\t// Index = 0, Token = 0\n\t0,\t// Index = 0, Token = 1\n\t0,\t// Index = 0, Token = 2\n\t0,\t// Index = 0, Token = 3\n\t32,\t// Index = 0, Token = 4\n\t64,\t// Index = 0, Token = 5\n\t96,\t// Index = 0, Token = 6\n\t128,\t// Index = 0, Token = 7\n\t0,\t// Index = 0, Token = 8\n\t0,\t// Index = 0, Token = 9\n\t0,\t// Index = 0, Token = 10\n\t0,\t// Index = 0, Token = 11\n\t32,\t// Index = 0, Token = 12\n\t64,\t// Index = 0, Token = 13\n\t96,\t// Index = 0, Token = 14\n\t128,\t// Index = 0, Token = 15\n\t0,\t// Index = 1, Token = 0\n\t0,\t// Index = 1, Token = 1\n\t0,\t// Index = 1, Token = 2\n\t0,\t// Index = 1, Token = 3\n\t48,\t// Index = 1, Token = 4\n\t80,\t// Index = 1, Token = 5\n\t112,\t// Index = 1, Token = 6\n\t144,\t// Index = 1, Token = 7\n\t0,\t// Index = 1, Token = 8\n\t0,\t// Index = 1, Token = 9\n\t0,\t// Index = 1, Token = 10\n\t0,\t// Index = 1, Token = 11\n\t48,\t// Index = 1, Token = 12\n\t80,\t// Index = 1, Token = 13\n\t112,\t// Index = 1, Token = 14\n\t144,\t// Index = 1, Token = 15\n\t16,\t// Index = 2, Token = 0\n\t16,\t// Index = 2, Token = 1\n\t16,\t// Index = 2, Token = 2\n\t16,\t// Index = 2, Token = 3\n\t64,\t// Index = 2, Token = 4\n\t96,\t// Index = 2, Token = 5\n\t128,\t// Index = 2, Token = 6\n\t160,\t// Index = 2, Token = 7\n\t16,\t// Index = 2, Token = 8\n\t16,\t// Index = 2, Token = 9\n\t16,\t// Index = 2, Token = 10\n\t16,\t// Index = 2, Token = 11\n\t64,\t// Index = 2, Token = 12\n\t96,\t// Index = 2, Token = 13\n\t128,\t// Index = 2, Token = 14\n\t160,\t// Index = 2, Token = 15\n\t32,\t// Index = 3, Token = 0\n\t32,\t// Index = 3, Token = 1\n\t32,\t// Index = 3, Token = 2\n\t32,\t// Index = 3, Token = 3\n\t80,\t// Index = 3, Token = 4\n\t112,\t// Index = 3, Token = 5\n\t144,\t// Index = 3, Token = 6\n\t176,\t// Index = 3, Token = 7\n\t32,\t// Index = 3, Token = 8\n\t32,\t// Index = 3, Token = 9\n\t32,\t// Index = 3, Token = 10\n\t32,\t// Index = 3, Token = 11\n\t80,\t// Index = 3, Token = 12\n\t112,\t// Index = 3, Token = 13\n\t144,\t// Index = 3, Token = 14\n\t176,\t// Index = 3, Token = 15\n\t48,\t// Index = 4, Token = 0\n\t48,\t// Index = 4, Token = 1\n\t48,\t// Index = 4, Token = 2\n\t48,\t// Index = 4, Token = 3\n\t96,\t// Index = 4, Token = 4\n\t128,\t// Index = 4, Token = 5\n\t160,\t// Index = 4, Token = 6\n\t192,\t// Index = 4, Token = 7\n\t48,\t// Index = 4, Token = 8\n\t48,\t// Index = 4, Token = 9\n\t48,\t// Index = 4, Token = 10\n\t48,\t// Index = 4, Token = 11\n\t96,\t// Index = 4, Token = 12\n\t128,\t// Index = 4, Token = 13\n\t160,\t// Index = 4, Token = 14\n\t192,\t// Index = 4, Token = 15\n\t64,\t// Index = 5, Token = 0\n\t64,\t// Index = 5, Token = 1\n\t64,\t// Index = 5, Token = 2\n\t64,\t// Index = 5, Token = 3\n\t112,\t// Index = 5, Token = 4\n\t144,\t// Index = 5, Token = 5\n\t176,\t// Index = 5, Token = 6\n\t208,\t// Index = 5, Token = 7\n\t64,\t// Index = 5, Token = 8\n\t64,\t// Index = 5, Token = 9\n\t64,\t// Index = 5, Token = 10\n\t64,\t// Index = 5, Token = 11\n\t112,\t// Index = 5, Token = 12\n\t144,\t// Index = 5, Token = 13\n\t176,\t// Index = 5, Token = 14\n\t208,\t// Index = 5, Token = 15\n\t80,\t// Index = 6, Token = 0\n\t80,\t// Index = 6, Token = 1\n\t80,\t// Index = 6, Token = 2\n\t80,\t// Index = 6, Token = 3\n\t128,\t// Index = 6, Token = 4\n\t160,\t// Index = 6, Token = 5\n\t192,\t// Index = 6, Token = 6\n\t224,\t// Index = 6, Token = 7\n\t80,\t// Index = 6, Token = 8\n\t80,\t// Index = 6, Token = 9\n\t80,\t// Index = 6, Token = 10\n\t80,\t// Index = 6, Token = 11\n\t128,\t// Index = 6, Token = 12\n\t160,\t// Index = 6, Token = 13\n\t192,\t// Index = 6, Token = 14\n\t224,\t// Index = 6, Token = 15\n\t96,\t// Index = 7, Token = 0\n\t96,\t// Index = 7, Token = 1\n\t96,\t// Index = 7, Token = 2\n\t96,\t// Index = 7, Token = 3\n\t144,\t// Index = 7, Token = 4\n\t176,\t// Index = 7, Token = 5\n\t208,\t// Index = 7, Token = 6\n\t240,\t// Index = 7, Token = 7\n\t96,\t// Index = 7, Token = 8\n\t96,\t// Index = 7, Token = 9\n\t96,\t// Index = 7, Token = 10\n\t96,\t// Index = 7, Token = 11\n\t144,\t// Index = 7, Token = 12\n\t176,\t// Index = 7, Token = 13\n\t208,\t// Index = 7, Token = 14\n\t240,\t// Index = 7, Token = 15\n\t112,\t// Index = 8, Token = 0\n\t112,\t// Index = 8, Token = 1\n\t112,\t// Index = 8, Token = 2\n\t112,\t// Index = 8, Token = 3\n\t160,\t// Index = 8, Token = 4\n\t192,\t// Index = 8, Token = 5\n\t224,\t// Index = 8, Token = 6\n\t256,\t// Index = 8, Token = 7\n\t112,\t// Index = 8, Token = 8\n\t112,\t// Index = 8, Token = 9\n\t112,\t// Index = 8, Token = 10\n\t112,\t// Index = 8, Token = 11\n\t160,\t// Index = 8, Token = 12\n\t192,\t// Index = 8, Token = 13\n\t224,\t// Index = 8, Token = 14\n\t256,\t// Index = 8, Token = 15\n\t128,\t// Index = 9, Token = 0\n\t128,\t// Index = 9, Token = 1\n\t128,\t// Index = 9, Token = 2\n\t128,\t// Index = 9, Token = 3\n\t176,\t// Index = 9, Token = 4\n\t208,\t// Index = 9, Token = 5\n\t240,\t// Index = 9, Token = 6\n\t272,\t// Index = 9, Token = 7\n\t128,\t// Index = 9, Token = 8\n\t128,\t// Index = 9, Token = 9\n\t128,\t// Index = 9, Token = 10\n\t128,\t// Index = 9, Token = 11\n\t176,\t// Index = 9, Token = 12\n\t208,\t// Index = 9, Token = 13\n\t240,\t// Index = 9, Token = 14\n\t272,\t// Index = 9, Token = 15\n\t144,\t// Index = 10, Token = 0\n\t144,\t// Index = 10, Token = 1\n\t144,\t// Index = 10, Token = 2\n\t144,\t// Index = 10, Token = 3\n\t192,\t// Index = 10, Token = 4\n\t224,\t// Index = 10, Token = 5\n\t256,\t// Index = 10, Token = 6\n\t288,\t// Index = 10, Token = 7\n\t144,\t// Index = 10, Token = 8\n\t144,\t// Index = 10, Token = 9\n\t144,\t// Index = 10, Token = 10\n\t144,\t// Index = 10, Token = 11\n\t192,\t// Index = 10, Token = 12\n\t224,\t// Index = 10, Token = 13\n\t256,\t// Index = 10, Token = 14\n\t288,\t// Index = 10, Token = 15\n\t160,\t// Index = 11, Token = 0\n\t160,\t// Index = 11, Token = 1\n\t160,\t// Index = 11, Token = 2\n\t160,\t// Index = 11, Token = 3\n\t208,\t// Index = 11, Token = 4\n\t240,\t// Index = 11, Token = 5\n\t272,\t// Index = 11, Token = 6\n\t304,\t// Index = 11, Token = 7\n\t160,\t// Index = 11, Token = 8\n\t160,\t// Index = 11, Token = 9\n\t160,\t// Index = 11, Token = 10\n\t160,\t// Index = 11, Token = 11\n\t208,\t// Index = 11, Token = 12\n\t240,\t// Index = 11, Token = 13\n\t272,\t// Index = 11, Token = 14\n\t304,\t// Index = 11, Token = 15\n\t176,\t// Index = 12, Token = 0\n\t176,\t// Index = 12, Token = 1\n\t176,\t// Index = 12, Token = 2\n\t176,\t// Index = 12, Token = 3\n\t224,\t// Index = 12, Token = 4\n\t256,\t// Index = 12, Token = 5\n\t288,\t// Index = 12, Token = 6\n\t320,\t// Index = 12, Token = 7\n\t176,\t// Index = 12, Token = 8\n\t176,\t// Index = 12, Token = 9\n\t176,\t// Index = 12, Token = 10\n\t176,\t// Index = 12, Token = 11\n\t224,\t// Index = 12, Token = 12\n\t256,\t// Index = 12, Token = 13\n\t288,\t// Index = 12, Token = 14\n\t320,\t// Index = 12, Token = 15\n\t192,\t// Index = 13, Token = 0\n\t192,\t// Index = 13, Token = 1\n\t192,\t// Index = 13, Token = 2\n\t192,\t// Index = 13, Token = 3\n\t240,\t// Index = 13, Token = 4\n\t272,\t// Index = 13, Token = 5\n\t304,\t// Index = 13, Token = 6\n\t336,\t// Index = 13, Token = 7\n\t192,\t// Index = 13, Token = 8\n\t192,\t// Index = 13, Token = 9\n\t192,\t// Index = 13, Token = 10\n\t192,\t// Index = 13, Token = 11\n\t240,\t// Index = 13, Token = 12\n\t272,\t// Index = 13, Token = 13\n\t304,\t// Index = 13, Token = 14\n\t336,\t// Index = 13, Token = 15\n\t208,\t// Index = 14, Token = 0\n\t208,\t// Index = 14, Token = 1\n\t208,\t// Index = 14, Token = 2\n\t208,\t// Index = 14, Token = 3\n\t256,\t// Index = 14, Token = 4\n\t288,\t// Index = 14, Token = 5\n\t320,\t// Index = 14, Token = 6\n\t352,\t// Index = 14, Token = 7\n\t208,\t// Index = 14, Token = 8\n\t208,\t// Index = 14, Token = 9\n\t208,\t// Index = 14, Token = 10\n\t208,\t// Index = 14, Token = 11\n\t256,\t// Index = 14, Token = 12\n\t288,\t// Index = 14, Token = 13\n\t320,\t// Index = 14, Token = 14\n\t352,\t// Index = 14, Token = 15\n\t224,\t// Index = 15, Token = 0\n\t224,\t// Index = 15, Token = 1\n\t224,\t// Index = 15, Token = 2\n\t224,\t// Index = 15, Token = 3\n\t272,\t// Index = 15, Token = 4\n\t304,\t// Index = 15, Token = 5\n\t336,\t// Index = 15, Token = 6\n\t368,\t// Index = 15, Token = 7\n\t224,\t// Index = 15, Token = 8\n\t224,\t// Index = 15, Token = 9\n\t224,\t// Index = 15, Token = 10\n\t224,\t// Index = 15, Token = 11\n\t272,\t// Index = 15, Token = 12\n\t304,\t// Index = 15, Token = 13\n\t336,\t// Index = 15, Token = 14\n\t368,\t// Index = 15, Token = 15\n\t240,\t// Index = 16, Token = 0\n\t240,\t// Index = 16, Token = 1\n\t240,\t// Index = 16, Token = 2\n\t240,\t// Index = 16, Token = 3\n\t288,\t// Index = 16, Token = 4\n\t320,\t// Index = 16, Token = 5\n\t352,\t// Index = 16, Token = 6\n\t384,\t// Index = 16, Token = 7\n\t240,\t// Index = 16, Token = 8\n\t240,\t// Index = 16, Token = 9\n\t240,\t// Index = 16, Token = 10\n\t240,\t// Index = 16, Token = 11\n\t288,\t// Index = 16, Token = 12\n\t320,\t// Index = 16, Token = 13\n\t352,\t// Index = 16, Token = 14\n\t384,\t// Index = 16, Token = 15\n\t256,\t// Index = 17, Token = 0\n\t256,\t// Index = 17, Token = 1\n\t256,\t// Index = 17, Token = 2\n\t256,\t// Index = 17, Token = 3\n\t304,\t// Index = 17, Token = 4\n\t336,\t// Index = 17, Token = 5\n\t368,\t// Index = 17, Token = 6\n\t400,\t// Index = 17, Token = 7\n\t256,\t// Index = 17, Token = 8\n\t256,\t// Index = 17, Token = 9\n\t256,\t// Index = 17, Token = 10\n\t256,\t// Index = 17, Token = 11\n\t304,\t// Index = 17, Token = 12\n\t336,\t// Index = 17, Token = 13\n\t368,\t// Index = 17, Token = 14\n\t400,\t// Index = 17, Token = 15\n\t272,\t// Index = 18, Token = 0\n\t272,\t// Index = 18, Token = 1\n\t272,\t// Index = 18, Token = 2\n\t272,\t// Index = 18, Token = 3\n\t320,\t// Index = 18, Token = 4\n\t352,\t// Index = 18, Token = 5\n\t384,\t// Index = 18, Token = 6\n\t416,\t// Index = 18, Token = 7\n\t272,\t// Index = 18, Token = 8\n\t272,\t// Index = 18, Token = 9\n\t272,\t// Index = 18, Token = 10\n\t272,\t// Index = 18, Token = 11\n\t320,\t// Index = 18, Token = 12\n\t352,\t// Index = 18, Token = 13\n\t384,\t// Index = 18, Token = 14\n\t416,\t// Index = 18, Token = 15\n\t288,\t// Index = 19, Token = 0\n\t288,\t// Index = 19, Token = 1\n\t288,\t// Index = 19, Token = 2\n\t288,\t// Index = 19, Token = 3\n\t336,\t// Index = 19, Token = 4\n\t368,\t// Index = 19, Token = 5\n\t400,\t// Index = 19, Token = 6\n\t432,\t// Index = 19, Token = 7\n\t288,\t// Index = 19, Token = 8\n\t288,\t// Index = 19, Token = 9\n\t288,\t// Index = 19, Token = 10\n\t288,\t// Index = 19, Token = 11\n\t336,\t// Index = 19, Token = 12\n\t368,\t// Index = 19, Token = 13\n\t400,\t// Index = 19, Token = 14\n\t432,\t// Index = 19, Token = 15\n\t304,\t// Index = 20, Token = 0\n\t304,\t// Index = 20, Token = 1\n\t304,\t// Index = 20, Token = 2\n\t304,\t// Index = 20, Token = 3\n\t352,\t// Index = 20, Token = 4\n\t384,\t// Index = 20, Token = 5\n\t416,\t// Index = 20, Token = 6\n\t448,\t// Index = 20, Token = 7\n\t304,\t// Index = 20, Token = 8\n\t304,\t// Index = 20, Token = 9\n\t304,\t// Index = 20, Token = 10\n\t304,\t// Index = 20, Token = 11\n\t352,\t// Index = 20, Token = 12\n\t384,\t// Index = 20, Token = 13\n\t416,\t// Index = 20, Token = 14\n\t448,\t// Index = 20, Token = 15\n\t320,\t// Index = 21, Token = 0\n\t320,\t// Index = 21, Token = 1\n\t320,\t// Index = 21, Token = 2\n\t320,\t// Index = 21, Token = 3\n\t368,\t// Index = 21, Token = 4\n\t400,\t// Index = 21, Token = 5\n\t432,\t// Index = 21, Token = 6\n\t464,\t// Index = 21, Token = 7\n\t320,\t// Index = 21, Token = 8\n\t320,\t// Index = 21, Token = 9\n\t320,\t// Index = 21, Token = 10\n\t320,\t// Index = 21, Token = 11\n\t368,\t// Index = 21, Token = 12\n\t400,\t// Index = 21, Token = 13\n\t432,\t// Index = 21, Token = 14\n\t464,\t// Index = 21, Token = 15\n\t336,\t// Index = 22, Token = 0\n\t336,\t// Index = 22, Token = 1\n\t336,\t// Index = 22, Token = 2\n\t336,\t// Index = 22, Token = 3\n\t384,\t// Index = 22, Token = 4\n\t416,\t// Index = 22, Token = 5\n\t448,\t// Index = 22, Token = 6\n\t480,\t// Index = 22, Token = 7\n\t336,\t// Index = 22, Token = 8\n\t336,\t// Index = 22, Token = 9\n\t336,\t// Index = 22, Token = 10\n\t336,\t// Index = 22, Token = 11\n\t384,\t// Index = 22, Token = 12\n\t416,\t// Index = 22, Token = 13\n\t448,\t// Index = 22, Token = 14\n\t480,\t// Index = 22, Token = 15\n\t352,\t// Index = 23, Token = 0\n\t352,\t// Index = 23, Token = 1\n\t352,\t// Index = 23, Token = 2\n\t352,\t// Index = 23, Token = 3\n\t400,\t// Index = 23, Token = 4\n\t432,\t// Index = 23, Token = 5\n\t464,\t// Index = 23, Token = 6\n\t496,\t// Index = 23, Token = 7\n\t352,\t// Index = 23, Token = 8\n\t352,\t// Index = 23, Token = 9\n\t352,\t// Index = 23, Token = 10\n\t352,\t// Index = 23, Token = 11\n\t400,\t// Index = 23, Token = 12\n\t432,\t// Index = 23, Token = 13\n\t464,\t// Index = 23, Token = 14\n\t496,\t// Index = 23, Token = 15\n\t368,\t// Index = 24, Token = 0\n\t368,\t// Index = 24, Token = 1\n\t368,\t// Index = 24, Token = 2\n\t368,\t// Index = 24, Token = 3\n\t416,\t// Index = 24, Token = 4\n\t448,\t// Index = 24, Token = 5\n\t480,\t// Index = 24, Token = 6\n\t512,\t// Index = 24, Token = 7\n\t368,\t// Index = 24, Token = 8\n\t368,\t// Index = 24, Token = 9\n\t368,\t// Index = 24, Token = 10\n\t368,\t// Index = 24, Token = 11\n\t416,\t// Index = 24, Token = 12\n\t448,\t// Index = 24, Token = 13\n\t480,\t// Index = 24, Token = 14\n\t512,\t// Index = 24, Token = 15\n\t384,\t// Index = 25, Token = 0\n\t384,\t// Index = 25, Token = 1\n\t384,\t// Index = 25, Token = 2\n\t384,\t// Index = 25, Token = 3\n\t432,\t// Index = 25, Token = 4\n\t464,\t// Index = 25, Token = 5\n\t496,\t// Index = 25, Token = 6\n\t528,\t// Index = 25, Token = 7\n\t384,\t// Index = 25, Token = 8\n\t384,\t// Index = 25, Token = 9\n\t384,\t// Index = 25, Token = 10\n\t384,\t// Index = 25, Token = 11\n\t432,\t// Index = 25, Token = 12\n\t464,\t// Index = 25, Token = 13\n\t496,\t// Index = 25, Token = 14\n\t528,\t// Index = 25, Token = 15\n\t400,\t// Index = 26, Token = 0\n\t400,\t// Index = 26, Token = 1\n\t400,\t// Index = 26, Token = 2\n\t400,\t// Index = 26, Token = 3\n\t448,\t// Index = 26, Token = 4\n\t480,\t// Index = 26, Token = 5\n\t512,\t// Index = 26, Token = 6\n\t544,\t// Index = 26, Token = 7\n\t400,\t// Index = 26, Token = 8\n\t400,\t// Index = 26, Token = 9\n\t400,\t// Index = 26, Token = 10\n\t400,\t// Index = 26, Token = 11\n\t448,\t// Index = 26, Token = 12\n\t480,\t// Index = 26, Token = 13\n\t512,\t// Index = 26, Token = 14\n\t544,\t// Index = 26, Token = 15\n\t416,\t// Index = 27, Token = 0\n\t416,\t// Index = 27, Token = 1\n\t416,\t// Index = 27, Token = 2\n\t416,\t// Index = 27, Token = 3\n\t464,\t// Index = 27, Token = 4\n\t496,\t// Index = 27, Token = 5\n\t528,\t// Index = 27, Token = 6\n\t560,\t// Index = 27, Token = 7\n\t416,\t// Index = 27, Token = 8\n\t416,\t// Index = 27, Token = 9\n\t416,\t// Index = 27, Token = 10\n\t416,\t// Index = 27, Token = 11\n\t464,\t// Index = 27, Token = 12\n\t496,\t// Index = 27, Token = 13\n\t528,\t// Index = 27, Token = 14\n\t560,\t// Index = 27, Token = 15\n\t432,\t// Index = 28, Token = 0\n\t432,\t// Index = 28, Token = 1\n\t432,\t// Index = 28, Token = 2\n\t432,\t// Index = 28, Token = 3\n\t480,\t// Index = 28, Token = 4\n\t512,\t// Index = 28, Token = 5\n\t544,\t// Index = 28, Token = 6\n\t576,\t// Index = 28, Token = 7\n\t432,\t// Index = 28, Token = 8\n\t432,\t// Index = 28, Token = 9\n\t432,\t// Index = 28, Token = 10\n\t432,\t// Index = 28, Token = 11\n\t480,\t// Index = 28, Token = 12\n\t512,\t// Index = 28, Token = 13\n\t544,\t// Index = 28, Token = 14\n\t576,\t// Index = 28, Token = 15\n\t448,\t// Index = 29, Token = 0\n\t448,\t// Index = 29, Token = 1\n\t448,\t// Index = 29, Token = 2\n\t448,\t// Index = 29, Token = 3\n\t496,\t// Index = 29, Token = 4\n\t528,\t// Index = 29, Token = 5\n\t560,\t// Index = 29, Token = 6\n\t592,\t// Index = 29, Token = 7\n\t448,\t// Index = 29, Token = 8\n\t448,\t// Index = 29, Token = 9\n\t448,\t// Index = 29, Token = 10\n\t448,\t// Index = 29, Token = 11\n\t496,\t// Index = 29, Token = 12\n\t528,\t// Index = 29, Token = 13\n\t560,\t// Index = 29, Token = 14\n\t592,\t// Index = 29, Token = 15\n\t464,\t// Index = 30, Token = 0\n\t464,\t// Index = 30, Token = 1\n\t464,\t// Index = 30, Token = 2\n\t464,\t// Index = 30, Token = 3\n\t512,\t// Index = 30, Token = 4\n\t544,\t// Index = 30, Token = 5\n\t576,\t// Index = 30, Token = 6\n\t608,\t// Index = 30, Token = 7\n\t464,\t// Index = 30, Token = 8\n\t464,\t// Index = 30, Token = 9\n\t464,\t// Index = 30, Token = 10\n\t464,\t// Index = 30, Token = 11\n\t512,\t// Index = 30, Token = 12\n\t544,\t// Index = 30, Token = 13\n\t576,\t// Index = 30, Token = 14\n\t608,\t// Index = 30, Token = 15\n\t480,\t// Index = 31, Token = 0\n\t480,\t// Index = 31, Token = 1\n\t480,\t// Index = 31, Token = 2\n\t480,\t// Index = 31, Token = 3\n\t528,\t// Index = 31, Token = 4\n\t560,\t// Index = 31, Token = 5\n\t592,\t// Index = 31, Token = 6\n\t624,\t// Index = 31, Token = 7\n\t480,\t// Index = 31, Token = 8\n\t480,\t// Index = 31, Token = 9\n\t480,\t// Index = 31, Token = 10\n\t480,\t// Index = 31, Token = 11\n\t528,\t// Index = 31, Token = 12\n\t560,\t// Index = 31, Token = 13\n\t592,\t// Index = 31, Token = 14\n\t624,\t// Index = 31, Token = 15\n\t496,\t// Index = 32, Token = 0\n\t496,\t// Index = 32, Token = 1\n\t496,\t// Index = 32, Token = 2\n\t496,\t// Index = 32, Token = 3\n\t544,\t// Index = 32, Token = 4\n\t576,\t// Index = 32, Token = 5\n\t608,\t// Index = 32, Token = 6\n\t640,\t// Index = 32, Token = 7\n\t496,\t// Index = 32, Token = 8\n\t496,\t// Index = 32, Token = 9\n\t496,\t// Index = 32, Token = 10\n\t496,\t// Index = 32, Token = 11\n\t544,\t// Index = 32, Token = 12\n\t576,\t// Index = 32, Token = 13\n\t608,\t// Index = 32, Token = 14\n\t640,\t// Index = 32, Token = 15\n\t512,\t// Index = 33, Token = 0\n\t512,\t// Index = 33, Token = 1\n\t512,\t// Index = 33, Token = 2\n\t512,\t// Index = 33, Token = 3\n\t560,\t// Index = 33, Token = 4\n\t592,\t// Index = 33, Token = 5\n\t624,\t// Index = 33, Token = 6\n\t656,\t// Index = 33, Token = 7\n\t512,\t// Index = 33, Token = 8\n\t512,\t// Index = 33, Token = 9\n\t512,\t// Index = 33, Token = 10\n\t512,\t// Index = 33, Token = 11\n\t560,\t// Index = 33, Token = 12\n\t592,\t// Index = 33, Token = 13\n\t624,\t// Index = 33, Token = 14\n\t656,\t// Index = 33, Token = 15\n\t528,\t// Index = 34, Token = 0\n\t528,\t// Index = 34, Token = 1\n\t528,\t// Index = 34, Token = 2\n\t528,\t// Index = 34, Token = 3\n\t576,\t// Index = 34, Token = 4\n\t608,\t// Index = 34, Token = 5\n\t640,\t// Index = 34, Token = 6\n\t672,\t// Index = 34, Token = 7\n\t528,\t// Index = 34, Token = 8\n\t528,\t// Index = 34, Token = 9\n\t528,\t// Index = 34, Token = 10\n\t528,\t// Index = 34, Token = 11\n\t576,\t// Index = 34, Token = 12\n\t608,\t// Index = 34, Token = 13\n\t640,\t// Index = 34, Token = 14\n\t672,\t// Index = 34, Token = 15\n\t544,\t// Index = 35, Token = 0\n\t544,\t// Index = 35, Token = 1\n\t544,\t// Index = 35, Token = 2\n\t544,\t// Index = 35, Token = 3\n\t592,\t// Index = 35, Token = 4\n\t624,\t// Index = 35, Token = 5\n\t656,\t// Index = 35, Token = 6\n\t688,\t// Index = 35, Token = 7\n\t544,\t// Index = 35, Token = 8\n\t544,\t// Index = 35, Token = 9\n\t544,\t// Index = 35, Token = 10\n\t544,\t// Index = 35, Token = 11\n\t592,\t// Index = 35, Token = 12\n\t624,\t// Index = 35, Token = 13\n\t656,\t// Index = 35, Token = 14\n\t688,\t// Index = 35, Token = 15\n\t560,\t// Index = 36, Token = 0\n\t560,\t// Index = 36, Token = 1\n\t560,\t// Index = 36, Token = 2\n\t560,\t// Index = 36, Token = 3\n\t608,\t// Index = 36, Token = 4\n\t640,\t// Index = 36, Token = 5\n\t672,\t// Index = 36, Token = 6\n\t704,\t// Index = 36, Token = 7\n\t560,\t// Index = 36, Token = 8\n\t560,\t// Index = 36, Token = 9\n\t560,\t// Index = 36, Token = 10\n\t560,\t// Index = 36, Token = 11\n\t608,\t// Index = 36, Token = 12\n\t640,\t// Index = 36, Token = 13\n\t672,\t// Index = 36, Token = 14\n\t704,\t// Index = 36, Token = 15\n\t576,\t// Index = 37, Token = 0\n\t576,\t// Index = 37, Token = 1\n\t576,\t// Index = 37, Token = 2\n\t576,\t// Index = 37, Token = 3\n\t624,\t// Index = 37, Token = 4\n\t656,\t// Index = 37, Token = 5\n\t688,\t// Index = 37, Token = 6\n\t720,\t// Index = 37, Token = 7\n\t576,\t// Index = 37, Token = 8\n\t576,\t// Index = 37, Token = 9\n\t576,\t// Index = 37, Token = 10\n\t576,\t// Index = 37, Token = 11\n\t624,\t// Index = 37, Token = 12\n\t656,\t// Index = 37, Token = 13\n\t688,\t// Index = 37, Token = 14\n\t720,\t// Index = 37, Token = 15\n\t592,\t// Index = 38, Token = 0\n\t592,\t// Index = 38, Token = 1\n\t592,\t// Index = 38, Token = 2\n\t592,\t// Index = 38, Token = 3\n\t640,\t// Index = 38, Token = 4\n\t672,\t// Index = 38, Token = 5\n\t704,\t// Index = 38, Token = 6\n\t736,\t// Index = 38, Token = 7\n\t592,\t// Index = 38, Token = 8\n\t592,\t// Index = 38, Token = 9\n\t592,\t// Index = 38, Token = 10\n\t592,\t// Index = 38, Token = 11\n\t640,\t// Index = 38, Token = 12\n\t672,\t// Index = 38, Token = 13\n\t704,\t// Index = 38, Token = 14\n\t736,\t// Index = 38, Token = 15\n\t608,\t// Index = 39, Token = 0\n\t608,\t// Index = 39, Token = 1\n\t608,\t// Index = 39, Token = 2\n\t608,\t// Index = 39, Token = 3\n\t656,\t// Index = 39, Token = 4\n\t688,\t// Index = 39, Token = 5\n\t720,\t// Index = 39, Token = 6\n\t752,\t// Index = 39, Token = 7\n\t608,\t// Index = 39, Token = 8\n\t608,\t// Index = 39, Token = 9\n\t608,\t// Index = 39, Token = 10\n\t608,\t// Index = 39, Token = 11\n\t656,\t// Index = 39, Token = 12\n\t688,\t// Index = 39, Token = 13\n\t720,\t// Index = 39, Token = 14\n\t752,\t// Index = 39, Token = 15\n\t624,\t// Index = 40, Token = 0\n\t624,\t// Index = 40, Token = 1\n\t624,\t// Index = 40, Token = 2\n\t624,\t// Index = 40, Token = 3\n\t672,\t// Index = 40, Token = 4\n\t704,\t// Index = 40, Token = 5\n\t736,\t// Index = 40, Token = 6\n\t768,\t// Index = 40, Token = 7\n\t624,\t// Index = 40, Token = 8\n\t624,\t// Index = 40, Token = 9\n\t624,\t// Index = 40, Token = 10\n\t624,\t// Index = 40, Token = 11\n\t672,\t// Index = 40, Token = 12\n\t704,\t// Index = 40, Token = 13\n\t736,\t// Index = 40, Token = 14\n\t768,\t// Index = 40, Token = 15\n\t640,\t// Index = 41, Token = 0\n\t640,\t// Index = 41, Token = 1\n\t640,\t// Index = 41, Token = 2\n\t640,\t// Index = 41, Token = 3\n\t688,\t// Index = 41, Token = 4\n\t720,\t// Index = 41, Token = 5\n\t752,\t// Index = 41, Token = 6\n\t784,\t// Index = 41, Token = 7\n\t640,\t// Index = 41, Token = 8\n\t640,\t// Index = 41, Token = 9\n\t640,\t// Index = 41, Token = 10\n\t640,\t// Index = 41, Token = 11\n\t688,\t// Index = 41, Token = 12\n\t720,\t// Index = 41, Token = 13\n\t752,\t// Index = 41, Token = 14\n\t784,\t// Index = 41, Token = 15\n\t656,\t// Index = 42, Token = 0\n\t656,\t// Index = 42, Token = 1\n\t656,\t// Index = 42, Token = 2\n\t656,\t// Index = 42, Token = 3\n\t704,\t// Index = 42, Token = 4\n\t736,\t// Index = 42, Token = 5\n\t768,\t// Index = 42, Token = 6\n\t800,\t// Index = 42, Token = 7\n\t656,\t// Index = 42, Token = 8\n\t656,\t// Index = 42, Token = 9\n\t656,\t// Index = 42, Token = 10\n\t656,\t// Index = 42, Token = 11\n\t704,\t// Index = 42, Token = 12\n\t736,\t// Index = 42, Token = 13\n\t768,\t// Index = 42, Token = 14\n\t800,\t// Index = 42, Token = 15\n\t672,\t// Index = 43, Token = 0\n\t672,\t// Index = 43, Token = 1\n\t672,\t// Index = 43, Token = 2\n\t672,\t// Index = 43, Token = 3\n\t720,\t// Index = 43, Token = 4\n\t752,\t// Index = 43, Token = 5\n\t784,\t// Index = 43, Token = 6\n\t816,\t// Index = 43, Token = 7\n\t672,\t// Index = 43, Token = 8\n\t672,\t// Index = 43, Token = 9\n\t672,\t// Index = 43, Token = 10\n\t672,\t// Index = 43, Token = 11\n\t720,\t// Index = 43, Token = 12\n\t752,\t// Index = 43, Token = 13\n\t784,\t// Index = 43, Token = 14\n\t816,\t// Index = 43, Token = 15\n\t688,\t// Index = 44, Token = 0\n\t688,\t// Index = 44, Token = 1\n\t688,\t// Index = 44, Token = 2\n\t688,\t// Index = 44, Token = 3\n\t736,\t// Index = 44, Token = 4\n\t768,\t// Index = 44, Token = 5\n\t800,\t// Index = 44, Token = 6\n\t832,\t// Index = 44, Token = 7\n\t688,\t// Index = 44, Token = 8\n\t688,\t// Index = 44, Token = 9\n\t688,\t// Index = 44, Token = 10\n\t688,\t// Index = 44, Token = 11\n\t736,\t// Index = 44, Token = 12\n\t768,\t// Index = 44, Token = 13\n\t800,\t// Index = 44, Token = 14\n\t832,\t// Index = 44, Token = 15\n\t704,\t// Index = 45, Token = 0\n\t704,\t// Index = 45, Token = 1\n\t704,\t// Index = 45, Token = 2\n\t704,\t// Index = 45, Token = 3\n\t752,\t// Index = 45, Token = 4\n\t784,\t// Index = 45, Token = 5\n\t816,\t// Index = 45, Token = 6\n\t848,\t// Index = 45, Token = 7\n\t704,\t// Index = 45, Token = 8\n\t704,\t// Index = 45, Token = 9\n\t704,\t// Index = 45, Token = 10\n\t704,\t// Index = 45, Token = 11\n\t752,\t// Index = 45, Token = 12\n\t784,\t// Index = 45, Token = 13\n\t816,\t// Index = 45, Token = 14\n\t848,\t// Index = 45, Token = 15\n\t720,\t// Index = 46, Token = 0\n\t720,\t// Index = 46, Token = 1\n\t720,\t// Index = 46, Token = 2\n\t720,\t// Index = 46, Token = 3\n\t768,\t// Index = 46, Token = 4\n\t800,\t// Index = 46, Token = 5\n\t832,\t// Index = 46, Token = 6\n\t864,\t// Index = 46, Token = 7\n\t720,\t// Index = 46, Token = 8\n\t720,\t// Index = 46, Token = 9\n\t720,\t// Index = 46, Token = 10\n\t720,\t// Index = 46, Token = 11\n\t768,\t// Index = 46, Token = 12\n\t800,\t// Index = 46, Token = 13\n\t832,\t// Index = 46, Token = 14\n\t864,\t// Index = 46, Token = 15\n\t736,\t// Index = 47, Token = 0\n\t736,\t// Index = 47, Token = 1\n\t736,\t// Index = 47, Token = 2\n\t736,\t// Index = 47, Token = 3\n\t784,\t// Index = 47, Token = 4\n\t816,\t// Index = 47, Token = 5\n\t848,\t// Index = 47, Token = 6\n\t880,\t// Index = 47, Token = 7\n\t736,\t// Index = 47, Token = 8\n\t736,\t// Index = 47, Token = 9\n\t736,\t// Index = 47, Token = 10\n\t736,\t// Index = 47, Token = 11\n\t784,\t// Index = 47, Token = 12\n\t816,\t// Index = 47, Token = 13\n\t848,\t// Index = 47, Token = 14\n\t880,\t// Index = 47, Token = 15\n\t752,\t// Index = 48, Token = 0\n\t752,\t// Index = 48, Token = 1\n\t752,\t// Index = 48, Token = 2\n\t752,\t// Index = 48, Token = 3\n\t800,\t// Index = 48, Token = 4\n\t832,\t// Index = 48, Token = 5\n\t864,\t// Index = 48, Token = 6\n\t896,\t// Index = 48, Token = 7\n\t752,\t// Index = 48, Token = 8\n\t752,\t// Index = 48, Token = 9\n\t752,\t// Index = 48, Token = 10\n\t752,\t// Index = 48, Token = 11\n\t800,\t// Index = 48, Token = 12\n\t832,\t// Index = 48, Token = 13\n\t864,\t// Index = 48, Token = 14\n\t896,\t// Index = 48, Token = 15\n\t768,\t// Index = 49, Token = 0\n\t768,\t// Index = 49, Token = 1\n\t768,\t// Index = 49, Token = 2\n\t768,\t// Index = 49, Token = 3\n\t816,\t// Index = 49, Token = 4\n\t848,\t// Index = 49, Token = 5\n\t880,\t// Index = 49, Token = 6\n\t912,\t// Index = 49, Token = 7\n\t768,\t// Index = 49, Token = 8\n\t768,\t// Index = 49, Token = 9\n\t768,\t// Index = 49, Token = 10\n\t768,\t// Index = 49, Token = 11\n\t816,\t// Index = 49, Token = 12\n\t848,\t// Index = 49, Token = 13\n\t880,\t// Index = 49, Token = 14\n\t912,\t// Index = 49, Token = 15\n\t784,\t// Index = 50, Token = 0\n\t784,\t// Index = 50, Token = 1\n\t784,\t// Index = 50, Token = 2\n\t784,\t// Index = 50, Token = 3\n\t832,\t// Index = 50, Token = 4\n\t864,\t// Index = 50, Token = 5\n\t896,\t// Index = 50, Token = 6\n\t928,\t// Index = 50, Token = 7\n\t784,\t// Index = 50, Token = 8\n\t784,\t// Index = 50, Token = 9\n\t784,\t// Index = 50, Token = 10\n\t784,\t// Index = 50, Token = 11\n\t832,\t// Index = 50, Token = 12\n\t864,\t// Index = 50, Token = 13\n\t896,\t// Index = 50, Token = 14\n\t928,\t// Index = 50, Token = 15\n\t800,\t// Index = 51, Token = 0\n\t800,\t// Index = 51, Token = 1\n\t800,\t// Index = 51, Token = 2\n\t800,\t// Index = 51, Token = 3\n\t848,\t// Index = 51, Token = 4\n\t880,\t// Index = 51, Token = 5\n\t912,\t// Index = 51, Token = 6\n\t944,\t// Index = 51, Token = 7\n\t800,\t// Index = 51, Token = 8\n\t800,\t// Index = 51, Token = 9\n\t800,\t// Index = 51, Token = 10\n\t800,\t// Index = 51, Token = 11\n\t848,\t// Index = 51, Token = 12\n\t880,\t// Index = 51, Token = 13\n\t912,\t// Index = 51, Token = 14\n\t944,\t// Index = 51, Token = 15\n\t816,\t// Index = 52, Token = 0\n\t816,\t// Index = 52, Token = 1\n\t816,\t// Index = 52, Token = 2\n\t816,\t// Index = 52, Token = 3\n\t864,\t// Index = 52, Token = 4\n\t896,\t// Index = 52, Token = 5\n\t928,\t// Index = 52, Token = 6\n\t960,\t// Index = 52, Token = 7\n\t816,\t// Index = 52, Token = 8\n\t816,\t// Index = 52, Token = 9\n\t816,\t// Index = 52, Token = 10\n\t816,\t// Index = 52, Token = 11\n\t864,\t// Index = 52, Token = 12\n\t896,\t// Index = 52, Token = 13\n\t928,\t// Index = 52, Token = 14\n\t960,\t// Index = 52, Token = 15\n\t832,\t// Index = 53, Token = 0\n\t832,\t// Index = 53, Token = 1\n\t832,\t// Index = 53, Token = 2\n\t832,\t// Index = 53, Token = 3\n\t880,\t// Index = 53, Token = 4\n\t912,\t// Index = 53, Token = 5\n\t944,\t// Index = 53, Token = 6\n\t976,\t// Index = 53, Token = 7\n\t832,\t// Index = 53, Token = 8\n\t832,\t// Index = 53, Token = 9\n\t832,\t// Index = 53, Token = 10\n\t832,\t// Index = 53, Token = 11\n\t880,\t// Index = 53, Token = 12\n\t912,\t// Index = 53, Token = 13\n\t944,\t// Index = 53, Token = 14\n\t976,\t// Index = 53, Token = 15\n\t848,\t// Index = 54, Token = 0\n\t848,\t// Index = 54, Token = 1\n\t848,\t// Index = 54, Token = 2\n\t848,\t// Index = 54, Token = 3\n\t896,\t// Index = 54, Token = 4\n\t928,\t// Index = 54, Token = 5\n\t960,\t// Index = 54, Token = 6\n\t992,\t// Index = 54, Token = 7\n\t848,\t// Index = 54, Token = 8\n\t848,\t// Index = 54, Token = 9\n\t848,\t// Index = 54, Token = 10\n\t848,\t// Index = 54, Token = 11\n\t896,\t// Index = 54, Token = 12\n\t928,\t// Index = 54, Token = 13\n\t960,\t// Index = 54, Token = 14\n\t992,\t// Index = 54, Token = 15\n\t864,\t// Index = 55, Token = 0\n\t864,\t// Index = 55, Token = 1\n\t864,\t// Index = 55, Token = 2\n\t864,\t// Index = 55, Token = 3\n\t912,\t// Index = 55, Token = 4\n\t944,\t// Index = 55, Token = 5\n\t976,\t// Index = 55, Token = 6\n\t1008,\t// Index = 55, Token = 7\n\t864,\t// Index = 55, Token = 8\n\t864,\t// Index = 55, Token = 9\n\t864,\t// Index = 55, Token = 10\n\t864,\t// Index = 55, Token = 11\n\t912,\t// Index = 55, Token = 12\n\t944,\t// Index = 55, Token = 13\n\t976,\t// Index = 55, Token = 14\n\t1008,\t// Index = 55, Token = 15\n\t880,\t// Index = 56, Token = 0\n\t880,\t// Index = 56, Token = 1\n\t880,\t// Index = 56, Token = 2\n\t880,\t// Index = 56, Token = 3\n\t928,\t// Index = 56, Token = 4\n\t960,\t// Index = 56, Token = 5\n\t992,\t// Index = 56, Token = 6\n\t1024,\t// Index = 56, Token = 7\n\t880,\t// Index = 56, Token = 8\n\t880,\t// Index = 56, Token = 9\n\t880,\t// Index = 56, Token = 10\n\t880,\t// Index = 56, Token = 11\n\t928,\t// Index = 56, Token = 12\n\t960,\t// Index = 56, Token = 13\n\t992,\t// Index = 56, Token = 14\n\t1024,\t// Index = 56, Token = 15\n\t896,\t// Index = 57, Token = 0\n\t896,\t// Index = 57, Token = 1\n\t896,\t// Index = 57, Token = 2\n\t896,\t// Index = 57, Token = 3\n\t944,\t// Index = 57, Token = 4\n\t976,\t// Index = 57, Token = 5\n\t1008,\t// Index = 57, Token = 6\n\t1040,\t// Index = 57, Token = 7\n\t896,\t// Index = 57, Token = 8\n\t896,\t// Index = 57, Token = 9\n\t896,\t// Index = 57, Token = 10\n\t896,\t// Index = 57, Token = 11\n\t944,\t// Index = 57, Token = 12\n\t976,\t// Index = 57, Token = 13\n\t1008,\t// Index = 57, Token = 14\n\t1040,\t// Index = 57, Token = 15\n\t912,\t// Index = 58, Token = 0\n\t912,\t// Index = 58, Token = 1\n\t912,\t// Index = 58, Token = 2\n\t912,\t// Index = 58, Token = 3\n\t960,\t// Index = 58, Token = 4\n\t992,\t// Index = 58, Token = 5\n\t1024,\t// Index = 58, Token = 6\n\t1056,\t// Index = 58, Token = 7\n\t912,\t// Index = 58, Token = 8\n\t912,\t// Index = 58, Token = 9\n\t912,\t// Index = 58, Token = 10\n\t912,\t// Index = 58, Token = 11\n\t960,\t// Index = 58, Token = 12\n\t992,\t// Index = 58, Token = 13\n\t1024,\t// Index = 58, Token = 14\n\t1056,\t// Index = 58, Token = 15\n\t928,\t// Index = 59, Token = 0\n\t928,\t// Index = 59, Token = 1\n\t928,\t// Index = 59, Token = 2\n\t928,\t// Index = 59, Token = 3\n\t976,\t// Index = 59, Token = 4\n\t1008,\t// Index = 59, Token = 5\n\t1040,\t// Index = 59, Token = 6\n\t1072,\t// Index = 59, Token = 7\n\t928,\t// Index = 59, Token = 8\n\t928,\t// Index = 59, Token = 9\n\t928,\t// Index = 59, Token = 10\n\t928,\t// Index = 59, Token = 11\n\t976,\t// Index = 59, Token = 12\n\t1008,\t// Index = 59, Token = 13\n\t1040,\t// Index = 59, Token = 14\n\t1072,\t// Index = 59, Token = 15\n\t944,\t// Index = 60, Token = 0\n\t944,\t// Index = 60, Token = 1\n\t944,\t// Index = 60, Token = 2\n\t944,\t// Index = 60, Token = 3\n\t992,\t// Index = 60, Token = 4\n\t1024,\t// Index = 60, Token = 5\n\t1056,\t// Index = 60, Token = 6\n\t1088,\t// Index = 60, Token = 7\n\t944,\t// Index = 60, Token = 8\n\t944,\t// Index = 60, Token = 9\n\t944,\t// Index = 60, Token = 10\n\t944,\t// Index = 60, Token = 11\n\t992,\t// Index = 60, Token = 12\n\t1024,\t// Index = 60, Token = 13\n\t1056,\t// Index = 60, Token = 14\n\t1088,\t// Index = 60, Token = 15\n\t960,\t// Index = 61, Token = 0\n\t960,\t// Index = 61, Token = 1\n\t960,\t// Index = 61, Token = 2\n\t960,\t// Index = 61, Token = 3\n\t1008,\t// Index = 61, Token = 4\n\t1040,\t// Index = 61, Token = 5\n\t1072,\t// Index = 61, Token = 6\n\t1104,\t// Index = 61, Token = 7\n\t960,\t// Index = 61, Token = 8\n\t960,\t// Index = 61, Token = 9\n\t960,\t// Index = 61, Token = 10\n\t960,\t// Index = 61, Token = 11\n\t1008,\t// Index = 61, Token = 12\n\t1040,\t// Index = 61, Token = 13\n\t1072,\t// Index = 61, Token = 14\n\t1104,\t// Index = 61, Token = 15\n\t976,\t// Index = 62, Token = 0\n\t976,\t// Index = 62, Token = 1\n\t976,\t// Index = 62, Token = 2\n\t976,\t// Index = 62, Token = 3\n\t1024,\t// Index = 62, Token = 4\n\t1056,\t// Index = 62, Token = 5\n\t1088,\t// Index = 62, Token = 6\n\t1120,\t// Index = 62, Token = 7\n\t976,\t// Index = 62, Token = 8\n\t976,\t// Index = 62, Token = 9\n\t976,\t// Index = 62, Token = 10\n\t976,\t// Index = 62, Token = 11\n\t1024,\t// Index = 62, Token = 12\n\t1056,\t// Index = 62, Token = 13\n\t1088,\t// Index = 62, Token = 14\n\t1120,\t// Index = 62, Token = 15\n\t992,\t// Index = 63, Token = 0\n\t992,\t// Index = 63, Token = 1\n\t992,\t// Index = 63, Token = 2\n\t992,\t// Index = 63, Token = 3\n\t1040,\t// Index = 63, Token = 4\n\t1072,\t// Index = 63, Token = 5\n\t1104,\t// Index = 63, Token = 6\n\t1136,\t// Index = 63, Token = 7\n\t992,\t// Index = 63, Token = 8\n\t992,\t// Index = 63, Token = 9\n\t992,\t// Index = 63, Token = 10\n\t992,\t// Index = 63, Token = 11\n\t1040,\t// Index = 63, Token = 12\n\t1072,\t// Index = 63, Token = 13\n\t1104,\t// Index = 63, Token = 14\n\t1136,\t// Index = 63, Token = 15\n\t1008,\t// Index = 64, Token = 0\n\t1008,\t// Index = 64, Token = 1\n\t1008,\t// Index = 64, Token = 2\n\t1008,\t// Index = 64, Token = 3\n\t1056,\t// Index = 64, Token = 4\n\t1088,\t// Index = 64, Token = 5\n\t1120,\t// Index = 64, Token = 6\n\t1152,\t// Index = 64, Token = 7\n\t1008,\t// Index = 64, Token = 8\n\t1008,\t// Index = 64, Token = 9\n\t1008,\t// Index = 64, Token = 10\n\t1008,\t// Index = 64, Token = 11\n\t1056,\t// Index = 64, Token = 12\n\t1088,\t// Index = 64, Token = 13\n\t1120,\t// Index = 64, Token = 14\n\t1152,\t// Index = 64, Token = 15\n\t1024,\t// Index = 65, Token = 0\n\t1024,\t// Index = 65, Token = 1\n\t1024,\t// Index = 65, Token = 2\n\t1024,\t// Index = 65, Token = 3\n\t1072,\t// Index = 65, Token = 4\n\t1104,\t// Index = 65, Token = 5\n\t1136,\t// Index = 65, Token = 6\n\t1168,\t// Index = 65, Token = 7\n\t1024,\t// Index = 65, Token = 8\n\t1024,\t// Index = 65, Token = 9\n\t1024,\t// Index = 65, Token = 10\n\t1024,\t// Index = 65, Token = 11\n\t1072,\t// Index = 65, Token = 12\n\t1104,\t// Index = 65, Token = 13\n\t1136,\t// Index = 65, Token = 14\n\t1168,\t// Index = 65, Token = 15\n\t1040,\t// Index = 66, Token = 0\n\t1040,\t// Index = 66, Token = 1\n\t1040,\t// Index = 66, Token = 2\n\t1040,\t// Index = 66, Token = 3\n\t1088,\t// Index = 66, Token = 4\n\t1120,\t// Index = 66, Token = 5\n\t1152,\t// Index = 66, Token = 6\n\t1184,\t// Index = 66, Token = 7\n\t1040,\t// Index = 66, Token = 8\n\t1040,\t// Index = 66, Token = 9\n\t1040,\t// Index = 66, Token = 10\n\t1040,\t// Index = 66, Token = 11\n\t1088,\t// Index = 66, Token = 12\n\t1120,\t// Index = 66, Token = 13\n\t1152,\t// Index = 66, Token = 14\n\t1184,\t// Index = 66, Token = 15\n\t1056,\t// Index = 67, Token = 0\n\t1056,\t// Index = 67, Token = 1\n\t1056,\t// Index = 67, Token = 2\n\t1056,\t// Index = 67, Token = 3\n\t1104,\t// Index = 67, Token = 4\n\t1136,\t// Index = 67, Token = 5\n\t1168,\t// Index = 67, Token = 6\n\t1200,\t// Index = 67, Token = 7\n\t1056,\t// Index = 67, Token = 8\n\t1056,\t// Index = 67, Token = 9\n\t1056,\t// Index = 67, Token = 10\n\t1056,\t// Index = 67, Token = 11\n\t1104,\t// Index = 67, Token = 12\n\t1136,\t// Index = 67, Token = 13\n\t1168,\t// Index = 67, Token = 14\n\t1200,\t// Index = 67, Token = 15\n\t1072,\t// Index = 68, Token = 0\n\t1072,\t// Index = 68, Token = 1\n\t1072,\t// Index = 68, Token = 2\n\t1072,\t// Index = 68, Token = 3\n\t1120,\t// Index = 68, Token = 4\n\t1152,\t// Index = 68, Token = 5\n\t1184,\t// Index = 68, Token = 6\n\t1216,\t// Index = 68, Token = 7\n\t1072,\t// Index = 68, Token = 8\n\t1072,\t// Index = 68, Token = 9\n\t1072,\t// Index = 68, Token = 10\n\t1072,\t// Index = 68, Token = 11\n\t1120,\t// Index = 68, Token = 12\n\t1152,\t// Index = 68, Token = 13\n\t1184,\t// Index = 68, Token = 14\n\t1216,\t// Index = 68, Token = 15\n\t1088,\t// Index = 69, Token = 0\n\t1088,\t// Index = 69, Token = 1\n\t1088,\t// Index = 69, Token = 2\n\t1088,\t// Index = 69, Token = 3\n\t1136,\t// Index = 69, Token = 4\n\t1168,\t// Index = 69, Token = 5\n\t1200,\t// Index = 69, Token = 6\n\t1232,\t// Index = 69, Token = 7\n\t1088,\t// Index = 69, Token = 8\n\t1088,\t// Index = 69, Token = 9\n\t1088,\t// Index = 69, Token = 10\n\t1088,\t// Index = 69, Token = 11\n\t1136,\t// Index = 69, Token = 12\n\t1168,\t// Index = 69, Token = 13\n\t1200,\t// Index = 69, Token = 14\n\t1232,\t// Index = 69, Token = 15\n\t1104,\t// Index = 70, Token = 0\n\t1104,\t// Index = 70, Token = 1\n\t1104,\t// Index = 70, Token = 2\n\t1104,\t// Index = 70, Token = 3\n\t1152,\t// Index = 70, Token = 4\n\t1184,\t// Index = 70, Token = 5\n\t1216,\t// Index = 70, Token = 6\n\t1248,\t// Index = 70, Token = 7\n\t1104,\t// Index = 70, Token = 8\n\t1104,\t// Index = 70, Token = 9\n\t1104,\t// Index = 70, Token = 10\n\t1104,\t// Index = 70, Token = 11\n\t1152,\t// Index = 70, Token = 12\n\t1184,\t// Index = 70, Token = 13\n\t1216,\t// Index = 70, Token = 14\n\t1248,\t// Index = 70, Token = 15\n\t1120,\t// Index = 71, Token = 0\n\t1120,\t// Index = 71, Token = 1\n\t1120,\t// Index = 71, Token = 2\n\t1120,\t// Index = 71, Token = 3\n\t1168,\t// Index = 71, Token = 4\n\t1200,\t// Index = 71, Token = 5\n\t1232,\t// Index = 71, Token = 6\n\t1264,\t// Index = 71, Token = 7\n\t1120,\t// Index = 71, Token = 8\n\t1120,\t// Index = 71, Token = 9\n\t1120,\t// Index = 71, Token = 10\n\t1120,\t// Index = 71, Token = 11\n\t1168,\t// Index = 71, Token = 12\n\t1200,\t// Index = 71, Token = 13\n\t1232,\t// Index = 71, Token = 14\n\t1264,\t// Index = 71, Token = 15\n\t1136,\t// Index = 72, Token = 0\n\t1136,\t// Index = 72, Token = 1\n\t1136,\t// Index = 72, Token = 2\n\t1136,\t// Index = 72, Token = 3\n\t1184,\t// Index = 72, Token = 4\n\t1216,\t// Index = 72, Token = 5\n\t1248,\t// Index = 72, Token = 6\n\t1280,\t// Index = 72, Token = 7\n\t1136,\t// Index = 72, Token = 8\n\t1136,\t// Index = 72, Token = 9\n\t1136,\t// Index = 72, Token = 10\n\t1136,\t// Index = 72, Token = 11\n\t1184,\t// Index = 72, Token = 12\n\t1216,\t// Index = 72, Token = 13\n\t1248,\t// Index = 72, Token = 14\n\t1280,\t// Index = 72, Token = 15\n\t1152,\t// Index = 73, Token = 0\n\t1152,\t// Index = 73, Token = 1\n\t1152,\t// Index = 73, Token = 2\n\t1152,\t// Index = 73, Token = 3\n\t1200,\t// Index = 73, Token = 4\n\t1232,\t// Index = 73, Token = 5\n\t1264,\t// Index = 73, Token = 6\n\t1296,\t// Index = 73, Token = 7\n\t1152,\t// Index = 73, Token = 8\n\t1152,\t// Index = 73, Token = 9\n\t1152,\t// Index = 73, Token = 10\n\t1152,\t// Index = 73, Token = 11\n\t1200,\t// Index = 73, Token = 12\n\t1232,\t// Index = 73, Token = 13\n\t1264,\t// Index = 73, Token = 14\n\t1296,\t// Index = 73, Token = 15\n\t1168,\t// Index = 74, Token = 0\n\t1168,\t// Index = 74, Token = 1\n\t1168,\t// Index = 74, Token = 2\n\t1168,\t// Index = 74, Token = 3\n\t1216,\t// Index = 74, Token = 4\n\t1248,\t// Index = 74, Token = 5\n\t1280,\t// Index = 74, Token = 6\n\t1312,\t// Index = 74, Token = 7\n\t1168,\t// Index = 74, Token = 8\n\t1168,\t// Index = 74, Token = 9\n\t1168,\t// Index = 74, Token = 10\n\t1168,\t// Index = 74, Token = 11\n\t1216,\t// Index = 74, Token = 12\n\t1248,\t// Index = 74, Token = 13\n\t1280,\t// Index = 74, Token = 14\n\t1312,\t// Index = 74, Token = 15\n\t1184,\t// Index = 75, Token = 0\n\t1184,\t// Index = 75, Token = 1\n\t1184,\t// Index = 75, Token = 2\n\t1184,\t// Index = 75, Token = 3\n\t1232,\t// Index = 75, Token = 4\n\t1264,\t// Index = 75, Token = 5\n\t1296,\t// Index = 75, Token = 6\n\t1328,\t// Index = 75, Token = 7\n\t1184,\t// Index = 75, Token = 8\n\t1184,\t// Index = 75, Token = 9\n\t1184,\t// Index = 75, Token = 10\n\t1184,\t// Index = 75, Token = 11\n\t1232,\t// Index = 75, Token = 12\n\t1264,\t// Index = 75, Token = 13\n\t1296,\t// Index = 75, Token = 14\n\t1328,\t// Index = 75, Token = 15\n\t1200,\t// Index = 76, Token = 0\n\t1200,\t// Index = 76, Token = 1\n\t1200,\t// Index = 76, Token = 2\n\t1200,\t// Index = 76, Token = 3\n\t1248,\t// Index = 76, Token = 4\n\t1280,\t// Index = 76, Token = 5\n\t1312,\t// Index = 76, Token = 6\n\t1344,\t// Index = 76, Token = 7\n\t1200,\t// Index = 76, Token = 8\n\t1200,\t// Index = 76, Token = 9\n\t1200,\t// Index = 76, Token = 10\n\t1200,\t// Index = 76, Token = 11\n\t1248,\t// Index = 76, Token = 12\n\t1280,\t// Index = 76, Token = 13\n\t1312,\t// Index = 76, Token = 14\n\t1344,\t// Index = 76, Token = 15\n\t1216,\t// Index = 77, Token = 0\n\t1216,\t// Index = 77, Token = 1\n\t1216,\t// Index = 77, Token = 2\n\t1216,\t// Index = 77, Token = 3\n\t1264,\t// Index = 77, Token = 4\n\t1296,\t// Index = 77, Token = 5\n\t1328,\t// Index = 77, Token = 6\n\t1360,\t// Index = 77, Token = 7\n\t1216,\t// Index = 77, Token = 8\n\t1216,\t// Index = 77, Token = 9\n\t1216,\t// Index = 77, Token = 10\n\t1216,\t// Index = 77, Token = 11\n\t1264,\t// Index = 77, Token = 12\n\t1296,\t// Index = 77, Token = 13\n\t1328,\t// Index = 77, Token = 14\n\t1360,\t// Index = 77, Token = 15\n\t1232,\t// Index = 78, Token = 0\n\t1232,\t// Index = 78, Token = 1\n\t1232,\t// Index = 78, Token = 2\n\t1232,\t// Index = 78, Token = 3\n\t1280,\t// Index = 78, Token = 4\n\t1312,\t// Index = 78, Token = 5\n\t1344,\t// Index = 78, Token = 6\n\t1376,\t// Index = 78, Token = 7\n\t1232,\t// Index = 78, Token = 8\n\t1232,\t// Index = 78, Token = 9\n\t1232,\t// Index = 78, Token = 10\n\t1232,\t// Index = 78, Token = 11\n\t1280,\t// Index = 78, Token = 12\n\t1312,\t// Index = 78, Token = 13\n\t1344,\t// Index = 78, Token = 14\n\t1376,\t// Index = 78, Token = 15\n\t1248,\t// Index = 79, Token = 0\n\t1248,\t// Index = 79, Token = 1\n\t1248,\t// Index = 79, Token = 2\n\t1248,\t// Index = 79, Token = 3\n\t1296,\t// Index = 79, Token = 4\n\t1328,\t// Index = 79, Token = 5\n\t1360,\t// Index = 79, Token = 6\n\t1392,\t// Index = 79, Token = 7\n\t1248,\t// Index = 79, Token = 8\n\t1248,\t// Index = 79, Token = 9\n\t1248,\t// Index = 79, Token = 10\n\t1248,\t// Index = 79, Token = 11\n\t1296,\t// Index = 79, Token = 12\n\t1328,\t// Index = 79, Token = 13\n\t1360,\t// Index = 79, Token = 14\n\t1392,\t// Index = 79, Token = 15\n\t1264,\t// Index = 80, Token = 0\n\t1264,\t// Index = 80, Token = 1\n\t1264,\t// Index = 80, Token = 2\n\t1264,\t// Index = 80, Token = 3\n\t1312,\t// Index = 80, Token = 4\n\t1344,\t// Index = 80, Token = 5\n\t1376,\t// Index = 80, Token = 6\n\t1408,\t// Index = 80, Token = 7\n\t1264,\t// Index = 80, Token = 8\n\t1264,\t// Index = 80, Token = 9\n\t1264,\t// Index = 80, Token = 10\n\t1264,\t// Index = 80, Token = 11\n\t1312,\t// Index = 80, Token = 12\n\t1344,\t// Index = 80, Token = 13\n\t1376,\t// Index = 80, Token = 14\n\t1408,\t// Index = 80, Token = 15\n\t1280,\t// Index = 81, Token = 0\n\t1280,\t// Index = 81, Token = 1\n\t1280,\t// Index = 81, Token = 2\n\t1280,\t// Index = 81, Token = 3\n\t1328,\t// Index = 81, Token = 4\n\t1360,\t// Index = 81, Token = 5\n\t1392,\t// Index = 81, Token = 6\n\t1408,\t// Index = 81, Token = 7\n\t1280,\t// Index = 81, Token = 8\n\t1280,\t// Index = 81, Token = 9\n\t1280,\t// Index = 81, Token = 10\n\t1280,\t// Index = 81, Token = 11\n\t1328,\t// Index = 81, Token = 12\n\t1360,\t// Index = 81, Token = 13\n\t1392,\t// Index = 81, Token = 14\n\t1408,\t// Index = 81, Token = 15\n\t1296,\t// Index = 82, Token = 0\n\t1296,\t// Index = 82, Token = 1\n\t1296,\t// Index = 82, Token = 2\n\t1296,\t// Index = 82, Token = 3\n\t1344,\t// Index = 82, Token = 4\n\t1376,\t// Index = 82, Token = 5\n\t1408,\t// Index = 82, Token = 6\n\t1408,\t// Index = 82, Token = 7\n\t1296,\t// Index = 82, Token = 8\n\t1296,\t// Index = 82, Token = 9\n\t1296,\t// Index = 82, Token = 10\n\t1296,\t// Index = 82, Token = 11\n\t1344,\t// Index = 82, Token = 12\n\t1376,\t// Index = 82, Token = 13\n\t1408,\t// Index = 82, Token = 14\n\t1408,\t// Index = 82, Token = 15\n\t1312,\t// Index = 83, Token = 0\n\t1312,\t// Index = 83, Token = 1\n\t1312,\t// Index = 83, Token = 2\n\t1312,\t// Index = 83, Token = 3\n\t1360,\t// Index = 83, Token = 4\n\t1392,\t// Index = 83, Token = 5\n\t1408,\t// Index = 83, Token = 6\n\t1408,\t// Index = 83, Token = 7\n\t1312,\t// Index = 83, Token = 8\n\t1312,\t// Index = 83, Token = 9\n\t1312,\t// Index = 83, Token = 10\n\t1312,\t// Index = 83, Token = 11\n\t1360,\t// Index = 83, Token = 12\n\t1392,\t// Index = 83, Token = 13\n\t1408,\t// Index = 83, Token = 14\n\t1408,\t// Index = 83, Token = 15\n\t1328,\t// Index = 84, Token = 0\n\t1328,\t// Index = 84, Token = 1\n\t1328,\t// Index = 84, Token = 2\n\t1328,\t// Index = 84, Token = 3\n\t1376,\t// Index = 84, Token = 4\n\t1408,\t// Index = 84, Token = 5\n\t1408,\t// Index = 84, Token = 6\n\t1408,\t// Index = 84, Token = 7\n\t1328,\t// Index = 84, Token = 8\n\t1328,\t// Index = 84, Token = 9\n\t1328,\t// Index = 84, Token = 10\n\t1328,\t// Index = 84, Token = 11\n\t1376,\t// Index = 84, Token = 12\n\t1408,\t// Index = 84, Token = 13\n\t1408,\t// Index = 84, Token = 14\n\t1408,\t// Index = 84, Token = 15\n\t1344,\t// Index = 85, Token = 0\n\t1344,\t// Index = 85, Token = 1\n\t1344,\t// Index = 85, Token = 2\n\t1344,\t// Index = 85, Token = 3\n\t1392,\t// Index = 85, Token = 4\n\t1408,\t// Index = 85, Token = 5\n\t1408,\t// Index = 85, Token = 6\n\t1408,\t// Index = 85, Token = 7\n\t1344,\t// Index = 85, Token = 8\n\t1344,\t// Index = 85, Token = 9\n\t1344,\t// Index = 85, Token = 10\n\t1344,\t// Index = 85, Token = 11\n\t1392,\t// Index = 85, Token = 12\n\t1408,\t// Index = 85, Token = 13\n\t1408,\t// Index = 85, Token = 14\n\t1408,\t// Index = 85, Token = 15\n\t1360,\t// Index = 86, Token = 0\n\t1360,\t// Index = 86, Token = 1\n\t1360,\t// Index = 86, Token = 2\n\t1360,\t// Index = 86, Token = 3\n\t1408,\t// Index = 86, Token = 4\n\t1408,\t// Index = 86, Token = 5\n\t1408,\t// Index = 86, Token = 6\n\t1408,\t// Index = 86, Token = 7\n\t1360,\t// Index = 86, Token = 8\n\t1360,\t// Index = 86, Token = 9\n\t1360,\t// Index = 86, Token = 10\n\t1360,\t// Index = 86, Token = 11\n\t1408,\t// Index = 86, Token = 12\n\t1408,\t// Index = 86, Token = 13\n\t1408,\t// Index = 86, Token = 14\n\t1408,\t// Index = 86, Token = 15\n\t1376,\t// Index = 87, Token = 0\n\t1376,\t// Index = 87, Token = 1\n\t1376,\t// Index = 87, Token = 2\n\t1376,\t// Index = 87, Token = 3\n\t1408,\t// Index = 87, Token = 4\n\t1408,\t// Index = 87, Token = 5\n\t1408,\t// Index = 87, Token = 6\n\t1408,\t// Index = 87, Token = 7\n\t1376,\t// Index = 87, Token = 8\n\t1376,\t// Index = 87, Token = 9\n\t1376,\t// Index = 87, Token = 10\n\t1376,\t// Index = 87, Token = 11\n\t1408,\t// Index = 87, Token = 12\n\t1408,\t// Index = 87, Token = 13\n\t1408,\t// Index = 87, Token = 14\n\t1408,\t// Index = 87, Token = 15\n\t1392,\t// Index = 88, Token = 0\n\t1392,\t// Index = 88, Token = 1\n\t1392,\t// Index = 88, Token = 2\n\t1392,\t// Index = 88, Token = 3\n\t1408,\t// Index = 88, Token = 4\n\t1408,\t// Index = 88, Token = 5\n\t1408,\t// Index = 88, Token = 6\n\t1408,\t// Index = 88, Token = 7\n\t1392,\t// Index = 88, Token = 8\n\t1392,\t// Index = 88, Token = 9\n\t1392,\t// Index = 88, Token = 10\n\t1392,\t// Index = 88, Token = 11\n\t1408,\t// Index = 88, Token = 12\n\t1408,\t// Index = 88, Token = 13\n\t1408,\t// Index = 88, Token = 14\n\t1408\t// Index = 88, Token = 15\n};\n\n"
  },
  {
    "path": "REDALERT/JSHELL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/JSHELL.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : JSHELL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 2, 1994                                                *\n *                                                                                             *\n *                  Last Update : May 11, 1995 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Build_Translucent_Table -- Creates a translucent control table.                           *\n *   Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.            *\n *   Fatal -- General purpose fatal error handler.                                             *\n *   Load_Alloc_Data -- Allocates a buffer and loads the file into it.                         *\n *   Load_Uncompress -- Loads and uncompresses data to a buffer.                               *\n *   Set_Window -- Sets the window dimensions to that specified.                               *\n *   Small_Icon -- Create a small icon from a big one.                                         *\n *   Translucent_Table_Size -- Determines the size of a translucent table.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"wwfile.h\"\n\n\n/***********************************************************************************************\n * Small_Icon -- Create a small icon from a big one.                                           *\n *                                                                                             *\n *    This routine will extract the specified icon from the icon data file and convert that    *\n *    icon into a small (3x3) representation. Typical use of this mini-icon is for the radar   *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   iconptr  -- Pointer to the icon data file.                                         *\n *                                                                                             *\n *          iconnum  -- The embedded icon number to convert into a small image.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the small icon imagery. This is exactly 9 bytes long.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/11/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Small_Icon(void const * iconptr, int iconnum)\n{\n\tstatic unsigned char _icon[9];\n\tIControl_Type const * iptr = (IControl_Type const *)iconptr;\n\tunsigned char * data;\n\n\tif (iconptr) {\n\t\ticonnum = ((char *)((char *)iptr + iptr->Map))[iconnum];\n\t\tdata = &((unsigned char *)((unsigned char *)iptr + iptr->Icons))[iconnum*(24*24)];\n//\t\tdata = &iptr->Icons[iconnum*(24*24)];\n\n\t\tfor (int index = 0; index < 9; index++) {\n\t\t\tint _offsets[9] = {\n\t\t\t\t4+4*24,\n\t\t\t\t12+4*24,\n\t\t\t\t20+4*24,\n\t\t\t\t4+12*24,\n\t\t\t\t12+12*24,\n\t\t\t\t20+12*24,\n\t\t\t\t4+20*24,\n\t\t\t\t12+20*24,\n\t\t\t\t20+20*24\n\t\t\t};\n\t\t\t_icon[index] = data[_offsets[index]];\n\t\t}\n\t}\n\n\treturn(_icon);\n}\n\n\n/***********************************************************************************************\n * Set_Window -- Sets the window dimensions to that specified.                                 *\n *                                                                                             *\n *    Use this routine to set the windows dimensions to the coordinates and dimensions         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   x     -- Window X pixel position.                                                  *\n *                                                                                             *\n *          y     -- Window Y pixel position.                                                  *\n *                                                                                             *\n *          w     -- Window width in pixels.                                                   *\n *                                                                                             *\n *          h     -- Window height in pixels.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The X and width values are truncated to an even 8 pixel boundary. This is       *\n *             the same as stripping off the lower 3 bits.                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Set_Window(int window, int x, int y, int w, int h)\n{\n\tWindowList[window][WINDOWWIDTH] = w;\n\tWindowList[window][WINDOWHEIGHT] = h;\n\tWindowList[window][WINDOWX] = x;\n\tWindowList[window][WINDOWY] = y;\n}\n\n\n/***********************************************************************************************\n * Fatal -- General purpose fatal error handler.                                               *\n *                                                                                             *\n *    This is a very simple general purpose fatal error handler. It goes directly to text      *\n *    mode, prints the error, and then aborts with a failure code.                             *\n *                                                                                             *\n * INPUT:   message  -- The text message to display.                                           *\n *                                                                                             *\n *          ...      -- Any optional parameters that are used in formatting the message.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine never returns. The game exits immediately.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Fatal(char const * message, ...)\n{\n\tva_list\tva;\n\n\tva_start(va, message);\n\tProg_End(message, true);\n\tvfprintf(stderr, message, va);\n\tMono_Printf(message);\n\tif (!RunningAsDLL) {\t//PG\n\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n}\n\n\n#ifdef NEVER\nvoid File_Fatal(char const * message)\n{\n\t//Prog_End();\n\tperror(message);\n\tEmergency_Exit(EXIT_FAILURE);\n}\n#endif\n\n\n\n/***********************************************************************************************\n * Load_Uncompress -- Loads and uncompresses data to a buffer.                                 *\n *                                                                                             *\n *    This is the C++ counterpart to the Load_Uncompress function. It will load the file       *\n *    specified into the graphic buffer indicated and uncompress it.                           *\n *                                                                                             *\n * INPUT:   file     -- The file to load and uncompress.                                       *\n *                                                                                             *\n *          uncomp_buff -- The graphic buffer that initial loading will use.                   *\n *                                                                                             *\n *          dest_buff   -- The buffer that will hold the uncompressed data.                    *\n *                                                                                             *\n *          reserved_data  -- This is an optional pointer to a buffer that will hold any       *\n *                            reserved data the compressed file may contain. This is           *\n *                            typically a palette.                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the size of the uncompressed data in the destination buffer.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void * reserved_data)\n{\n\tunsigned short\tsize;\n\tvoid\t* sptr = uncomp_buff.Get_Buffer();\n\tvoid\t* dptr = dest_buff.Get_Buffer();\n\tint\topened = false;\n\tCompHeaderType\theader;\n\n\t/*\n\t**\tThe file must be opened in order to be read from. If the file\n\t**\tisn't opened, then open it. Record this fact so that it can be\n\t**\trestored to its closed state at the end.\n\t*/\n\tif (!file.Is_Open()) {\n\t\tif (!file.Open()) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tRead in the size of the file (supposedly).\n\t*/\n\tfile.Read(&size, sizeof(size));\n\n\t/*\n\t**\tRead in the header block. This block contains the compression type\n\t**\tand skip data (among other things).\n\t*/\n\tfile.Read(&header, sizeof(header));\n\tsize -= sizeof(header);\n\n\t/*\n\t**\tIf there are skip bytes then they must be processed. Either read\n\t**\tthem into the buffer provided or skip past them. No check is made\n\t**\tto ensure that the reserved data buffer is big enough (watch out!).\n\t*/\n\tif (header.Skip) {\n\t\tsize -= header.Skip;\n\t\tif (reserved_data) {\n\t\t\tfile.Read(reserved_data, header.Skip);\n\t\t} else {\n\t\t\tfile.Seek(header.Skip, SEEK_CUR);\n\t\t}\n\t\theader.Skip = 0;\n\t}\n\n\t/*\n\t**\tDetermine where is the proper place to load the data. If both buffers\n\t**\tspecified are identical, then the data should be loaded at the end of\n\t**\tthe buffer and decompressed at the beginning.\n\t*/\n\tif (uncomp_buff.Get_Buffer() == dest_buff.Get_Buffer()) {\n\t\tsptr = (char *)sptr + uncomp_buff.Get_Size()-(size+sizeof(header));\n\t}\n\n\t/*\n\t**\tRead in the bulk of the data.\n\t*/\n\tMem_Copy(&header, sptr, sizeof(header));\n\tfile.Read((char *)sptr + sizeof(header), size);\n\n\t/*\n\t**\tDecompress the data.\n\t*/\n\tsize = (unsigned int) Uncompress_Data(sptr, dptr);\n\n\t/*\n\t**\tClose the file if necessary.\n\t*/\n\tif (opened) {\n\t\tfile.Close();\n\t}\n\treturn((long)size);\n}\n\n\nint Load_Picture(char const * filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char * palette, PicturePlaneType )\n{\n\treturn(Load_Uncompress(CCFileClass(filename), scratchbuf, destbuf,  palette ) / 8000);\n}\n\n\n/***********************************************************************************************\n * Load_Alloc_Data -- Allocates a buffer and loads the file into it.                           *\n *                                                                                             *\n *    This is the C++ replacement for the Load_Alloc_Data function. It will allocate the       *\n *    memory big enough to hold the file and then read the file into it.                       *\n *                                                                                             *\n * INPUT:   file  -- The file to read.                                                         *\n *                                                                                             *\n *          mem   -- The memory system to use for allocation.                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated and filled memory block.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Load_Alloc_Data(FileClass &file)\n{\n\tvoid * ptr = 0;\n\tlong size = file.Size();\n\n\tptr = new char [size];\n\tif (ptr) {\n\t\tfile.Read(ptr, size);\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * Translucent_Table_Size -- Determines the size of a translucent table.                       *\n *                                                                                             *\n *    Use this routine to determine how big the translucent table needs                        *\n *    to be given the specified number of colors. This value is typically                      *\n *    used when allocating the buffer for the translucent table.                               *\n *                                                                                             *\n * INPUT:   count -- The number of colors that are translucent.                                *\n *                                                                                             *\n * OUTPUT:  Returns the size of the translucent table.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong Translucent_Table_Size(int count)\n{\n\treturn(256L + (256L * count));\n}\n\n\n/***********************************************************************************************\n * Build_Translucent_Table -- Creates a translucent control table.                             *\n *                                                                                             *\n *    The table created by this routine is used by Draw_Shape (GHOST) to                       *\n *    achieve a translucent affect. The original color of the shape will                       *\n *    show through. This differs from the fading effect, since that                            *\n *    affect only alters the background color toward a single destination                      *\n *    color.                                                                                   *\n *                                                                                             *\n * INPUT:   palette  -- Pointer to the control palette.                                        *\n *                                                                                             *\n *          control  -- Pointer to array of structures that control how                        *\n *                      the translucent table will be built.                                   *\n *                                                                                             *\n *          count    -- The number of entries in the control array.                            *\n *                                                                                             *\n *          buffer   -- Pointer to buffer to place the translucent table.                      *\n *                      If NULL is passed in, then the buffer will be                          *\n *                      allocated.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to the translucent table.                                     *\n *                                                                                             *\n * WARNINGS:   This routine is exceedingly slow. Use sparingly.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)\n{\n\tunsigned char\tconst *table;\t\t// Remap table pointer.\n\tint\t\t\tindex;\t\t// Working color index.\n\n\tif (count && control/* && palette*/) {\t\t// palette can't be NULL... ST - 5/9/2019\n\t\tif (!buffer) {\n\t\t\tbuffer = new char [Translucent_Table_Size(count)];\n\t\t}\n\n\t\tif (buffer) {\n\t\t\tmemset(buffer, -1, 256);\n\t\t\ttable = (unsigned char*)buffer + 256;\n\n\t\t\t/*\n\t\t\t**\tBuild the individual remap tables for each translucent color.\n\t\t\t*/\n\t\t\tfor (index = 0; index < count; index++) {\n\t\t\t\t((unsigned char*)buffer)[control[index].SourceColor] = index;\n\t\t\t\tBuild_Fading_Table(palette.Get_Data(), (void*)table, control[index].DestColor, control[index].Fading);\n\t\t\t\ttable = (unsigned char*)table + 256;\n\t\t\t}\n\t\t}\n\t}\n\treturn(buffer);\n}\n\n\n/***********************************************************************************************\n * Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.              *\n *                                                                                             *\n *    This routine will build a translucent (fading) table to remap colors into the shadow     *\n *    color region of the palette. Shadow colors are not affected by this translucent table.   *\n *    This means that a shape can be overlapped any number of times and the imagery will       *\n *    remain deterministic (and constant).                                                     *\n *                                                                                             *\n * INPUT:   palette  -- Pointer to the palette to base the translucent process on.             *\n *                                                                                             *\n *          control  -- Pointer to special control structure that specifies the                *\n *                      target color, and percentage of fade.                                  *\n *                                                                                             *\n *          count    -- The number of colors to be remapped (entries in the control array).    *\n *                                                                                             *\n *          buffer   -- Pointer to the staging buffer that will hold the translucent table     *\n *                      data. If this parameter is NULL, then an appropriate sized table       *\n *                      will be allocated.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the translucent table data.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)\n{\n\tunsigned char\tconst *table;\t\t// Remap table pointer.\n\n\tif (count && control) {\n\t\tif (!buffer) {\n\t\t\tbuffer = new char [Translucent_Table_Size(count)];\n\t\t}\n\n\t\tif (buffer) {\n\t\t\tmemset(buffer, -1, 256);\n\t\t\ttable = (unsigned char*)buffer + 256;\n\n\t\t\t/*\n\t\t\t**\tBuild the individual remap tables for each translucent color.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\t((unsigned char*)buffer)[control[index].SourceColor] = index;\n\t\t\t\tConquer_Build_Fading_Table(palette, (void*)table, control[index].DestColor, control[index].Fading);\n\t\t\t\ttable = (unsigned char*)table + 256;\n\t\t\t}\n\t\t}\n\t}\n\treturn(buffer);\n}\n\n\nvoid * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)\n{\n\tif (dest) {\n\t\tunsigned char * ptr = (unsigned char *)dest;\n\n\t\t/*\n\t\t**\tFind an appropriate remap color index for every color in the palette.\n\t\t**\tThere are certain exceptions to this, but they are trapped within the\n\t\t**\tloop.\n\t\t*/\n\t\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\n\t\t\t/*\n\t\t\t**\tFind the color that, ideally, the working color should be remapped\n\t\t\t**\tto in the special remap range.\n\t\t\t*/\n\t\t\tRGBClass trycolor = palette[index];\n\t\t\ttrycolor.Adjust(frac, palette[color]);\t\t\t// Try to match this color.\n\n\t\t\t/*\n\t\t\t**\tSearch through the remap range to find the color that should be remapped\n\t\t\t**\tto. This special range is used for shadows or other effects that are\n\t\t\t**\tnot compounded if additively applied.\n\t\t\t*/\n\t\t\t*ptr++ = palette.Closest_Color(trycolor);\n\t\t}\n\t}\n\treturn(dest);\n}\n\n\nvoid * Conquer_Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)\n{\n\tif (dest) {\n\t\tunsigned char * ptr = (unsigned char *)dest;\n//\t\tHSVClass desthsv = palette[color];\n\n\t\t/*\n\t\t**\tFind an appropriate remap color index for every color in the palette.\n\t\t**\tThere are certain exceptions to this, but they are trapped within the\n\t\t**\tloop.\n\t\t*/\n\t\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\n\t\t\t/*\n\t\t\t**\tIf this color should not be remapped, then it will be stored as a remap\n\t\t\t**\tto itself. This is effectively no remap.\n\t\t\t*/\n\t\t\tif (index > PaletteClass::COLOR_COUNT-16 || index == 0) {\n\t\t\t\t*ptr++ = index;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tFind the color that, ideally, the working color should be remapped\n\t\t\t\t**\tto in the special remap range.\n\t\t\t\t*/\n\t\t\t\tRGBClass trycolor = palette[index];\n\t\t\t\ttrycolor.Adjust(frac, palette[color]);\t\t\t// Try to match this color.\n\n\t\t\t\t/*\n\t\t\t\t**\tSearch through the remap range to find the color that should be remapped\n\t\t\t\t**\tto. This special range is used for shadows or other effects that are\n\t\t\t\t**\tnot compounded if additively applied.\n\t\t\t\t*/\n\t\t\t\tint best = -1;\n\t\t\t\tint bvalue = 0;\n\t\t\t\tfor (int id = PaletteClass::COLOR_COUNT-16; id < PaletteClass::COLOR_COUNT-1; id++) {\n\t\t\t\t\tint diff = palette[id].Difference(trycolor);\n\t\t\t\t\tif (best == -1 || diff < bvalue) {\n\t\t\t\t\t\tbest = id;\n\t\t\t\t\t\tbvalue = diff;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t*ptr++ = best;\n\t\t\t}\n\t\t}\n\t}\n\treturn(dest);\n}\n\n\n#ifdef OBSOLETE\n//int Desired_Facing8(int x1, int y1, int x2, int y2)\nDirType xDesired_Facing8(int x1, int y1, int x2, int y2)\n{\n\tint index = 0;\t\t\t\t// Facing composite value.\n\n\t/*\n\t**\tFigure the absolute X difference. This determines\n\t**\tif the facing is leftward or not.\n\t*/\n\tint xdiff = x2-x1;\n\tif (xdiff < 0) {\n\t\tindex |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFigure the absolute Y difference. This determines\n\t**\tif the facing is downward or not. This also clarifies\n\t**\texactly which quadrant the facing lies.\n\t*/\n\tint ydiff = y1-y2;\n\tif (ydiff < 0) {\n\t\tindex ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tIf on the diagonal, then incorporate this into the facing\n\t**\tand then bail. The facing is known.\n\t*/\n\tif (((bigger+1)/2) <= smaller) {\n\t\tindex += 0x0020;\n\t\treturn(DirType(index));\n\t}\n\n\t/*\n\t**\tDetermine if the facing is closer to the Y axis or\n\t**\tthe X axis.\n\t*/\n\tint adder = (index & 0x0040);\n\tif (xdiff == bigger) {\n\t\tadder ^= 0x0040;\n\t}\n\tindex += adder;\n\n\treturn(DirType(index));\n}\n\n\n//int Desired_Facing256(int srcx, int srcy, int dstx, int dsty)\nDirType xDesired_Facing256(int srcx, int srcy, int dstx, int dsty)\n{\n\tint composite=0;\t\t// Facing built from intermediate calculations.\n\n\t/*\n\t**\tFetch the absolute X difference. This also gives a clue as\n\t**\tto which hemisphere the direction lies.\n\t*/\n\tint xdiff = dstx - srcx;\n\tif (xdiff < 0) {\n\t\tcomposite |= 0x00C0;\n\t\txdiff = -xdiff;\n\t}\n\n\t/*\n\t**\tFetch the absolute Y difference. This clarifies the exact\n\t**\tquadrant that the direction lies.\n\t*/\n\tint ydiff = srcy - dsty;\n\tif (ydiff < 0) {\n\t\tcomposite ^= 0x0040;\n\t\tydiff = -ydiff;\n\t}\n\n\t/*\n\t**\tBail early if the coordinates are the same. This check also\n\t**\thas the added bonus of ensuring that checking for division\n\t**\tby zero is not needed in the following section.\n\t*/\n\tif (xdiff == 0 && ydiff == 0) return(DirType(0xFF));\n\n\t/*\n\t**\tDetermine which of the two direction offsets it bigger. The\n\t**\toffset direction that is bigger (X or Y) will indicate which\n\t**\torthogonal direction the facing is closer to.\n\t*/\n\tunsigned bigger;\n\tunsigned smaller;\n\tif (xdiff < ydiff) {\n\t\tsmaller = xdiff;\n\t\tbigger = ydiff;\n\t} else {\n\t\tsmaller = ydiff;\n\t\tbigger = xdiff;\n\t}\n\n\t/*\n\t**\tNow that the quadrant is known, we need to determine how far\n\t**\tfrom the orthogonal directions, the facing lies. This value\n\t**\tis calculated as a ratio from 0 (matches orthogonal) to 31\n\t**\t(matches diagonal).\n\t*/\n\tint frac = (smaller * 32U) / bigger;\n\n\t/*\n\t**\tGiven the quadrant and knowing whether the facing is closer\n\t**\tto the X or Y axis, we must make an adjustment toward the\n\t**\tsubsequent quadrant if necessary.\n\t*/\n\tint adder = (composite & 0x0040);\n\tif (xdiff > ydiff) {\n\t\tadder ^= 0x0040;\n\t}\n\tif (adder) {\n\t\tfrac = (adder - frac)-1;\n\t}\n\n\t/*\n\t**\tIntegrate the fraction value into the quadrant.\n\t*/\n\tcomposite += frac;\n\n\t/*\n\t**\tReturn with the final facing value.\n\t*/\n\treturn(DirType(composite & 0x00FF));\n}\n#endif\n"
  },
  {
    "path": "REDALERT/JSHELL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/JSHELL.H 1     3/03/97 10:24a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : JSHELL.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/13/95                                                     *\n *                                                                                             *\n *                  Last Update : March 13, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef JSHELL_H\n#define JSHELL_H\n\n\n#include\t<assert.h>\n\n#ifdef WIN32\n//#define getch\tGet_Key_Num\n//#define kbhit\tCheck_Key_Num\n#include\t\"key.h\"\n#else\n#include\t<conio.h>\n#endif\n\n/*\n**\tInterface class to the keyboard. This insulates the game from library vagaries. Most\n**\tnotable being the return values are declared as \"int\" in the library whereas C&C\n**\texpects it to be of KeyNumType.\n*/\n#ifdef WIN32\n//#define KeyNumType\tint\n//#define KeyASCIIType\tint\n\n//lint -esym(1725,KeyboardClass::MouseQX,KeyboardClass::MouseQY)\nstruct KeyboardClass : public WWKeyboardClass\n\n#else\nstruct KeyboardClass\n#endif\n{\n\n\t/*\n\t**\tThis flag is used to indicate whether the WW library has taken over\n\t**\tthe keyboard or not. If not, then the normal console input\n\t**\ttakes precedence.\n\t*/\n\tunsigned IsLibrary;\n\n#ifndef WIN32\n\tint &MouseQX;\n\tint &MouseQY;\n\n\tKeyboardClass() :\n\t\tIsLibrary(true),\n\t\tMouseQX(::MouseQX),\n\t\tMouseQY(::MouseQY)\n\t{}\n\tKeyNumType Get(void) {return (IsLibrary ? (KeyNumType)Get_Key_Num() : (KeyNumType)getch());};\n\tKeyNumType Check(void) {return (IsLibrary ? (KeyNumType)Check_Key_Num() : (KeyNumType)kbhit());};\n\tKeyASCIIType To_ASCII(KeyNumType key) {return((KeyASCIIType)KN_To_KA(key));};\n\tvoid Clear(void) {if (IsLibrary) Clear_KeyBuffer();};\n\tint Down(KeyNumType key) {return(Key_Down(key));};\n#else\n\tKeyboardClass() : IsLibrary(true) {}\n\tKeyNumType Get(void) {return ((KeyNumType)WWKeyboardClass::Get());};\n\tKeyNumType Check(void) {return ((KeyNumType)WWKeyboardClass::Check());};\n\tKeyASCIIType To_ASCII(KeyNumType key) {return((KeyASCIIType)WWKeyboardClass::To_ASCII(key));};\n\tvoid Clear(void) {WWKeyboardClass::Clear();};\n\tint Down(KeyNumType key) {return(WWKeyboardClass::Down(key));};\n#endif\n\n\tint Mouse_X(void) {return(Get_Mouse_X());};\n\tint Mouse_Y(void) {return(Get_Mouse_Y());};\n};\n\n\n/*\n**\tThese templates allow enumeration types to have simple bitwise\n**\tarithmatic performed. The operators must be instatiated for the\n**\tenumerated types desired.\n*/\ntemplate<class T> inline T operator ++(T & a)\n{\n\ta = (T)((int)a + (int)1);\n\treturn(a);\n}\ntemplate<class T> inline T operator ++(T & a, int)\n{\n\tT aa = a;\n\ta = (T)((int)a + (int)1);\n\treturn(aa);\n}\ntemplate<class T> inline T operator --(T & a)\n{\n\ta = (T)((int)a - (int)1);\n\treturn(a);\n}\ntemplate<class T> inline T operator --(T & a, int)\n{\n\tT aa = a;\n\ta = (T)((int)a - (int)1);\n\treturn(aa);\n}\ntemplate<class T> inline T operator |(T t1, T t2)\n{\n\treturn((T)((int)t1 | (int)t2));\n}\ntemplate<class T> inline T operator &(T t1, T t2)\n{\n\treturn((T)((int)t1 & (int)t2));\n}\ntemplate<class T> inline T operator ~(T t1)\n{\n\treturn((T)(~(int)t1));\n}\n\n#ifndef WIN32\ntemplate<class T> inline T min(T value1, T value2)\n{\n\tif (value1 < value2) {\n\t\treturn(value1);\n\t}\n\treturn(value2);\n}\nint min(int, int);\nlong min(long, long);\n\ntemplate<class T> inline T max(T value1, T value2)\n{\n\tif (value1 > value2) {\n\t\treturn(value1);\n\t}\n\treturn(value2);\n}\nint max(int, int);\nlong max(long, long);\n#endif\n\ntemplate<class T> inline void swap(T &value1, T &value2)\n{\n\tT temp = value1;\n\tvalue1 = value2;\n\tvalue2 = temp;\n}\nint swap(int, int);\nlong swap(long, long);\n\ntemplate<class T> inline\nT Bound(T original, T minval, T maxval)\n{\n\tif (original < minval) return(minval);\n\tif (original > maxval) return(maxval);\n\treturn(original);\n};\nint Bound(signed int, signed int, signed int);\nunsigned Bound(unsigned, unsigned, unsigned);\nlong Bound(long, long, long);\n\ntemplate<class T>\nT _rotl(T X, int n)\n{\n\treturn((T)(( ( ( X ) << n ) | ( ( X ) >> ( (sizeof(T)*8) - n ) ) )));\n}\n\n\n/*\n**\tThis macro serves as a general way to determine the number of elements\n**\twithin an array.\n*/\n#define\tARRAY_LENGTH(x)\tint(sizeof(x)/sizeof(x[0]))\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/*\n**\tThe shape flags are likely to be \"or\"ed together and other such bitwise\n**\tmanipulations. These instatiated operator templates allow this.\n*/\ninline ShapeFlags_Type operator |(ShapeFlags_Type, ShapeFlags_Type);\ninline ShapeFlags_Type operator &(ShapeFlags_Type, ShapeFlags_Type);\ninline ShapeFlags_Type operator ~(ShapeFlags_Type);\n\n\nvoid __cdecl Set_Bit(void * array, int bit, int value);\nint __cdecl Get_Bit(void const * array, int bit);\nint __cdecl First_True_Bit(void const * array);\nint __cdecl First_False_Bit(void const * array);\nint __cdecl Bound(int original, int min, int max);\n\n#if (0)\nvoid Set_Bit(void * array, int bit, int value);\n#pragma aux Set_Bit parm [esi] [ecx] [eax] \\\n\tmodify [esi ebx] = \t\t\t\\\n\t\"mov\tebx,ecx\"\t\t\t\t\t\\\n\t\"shr\tebx,5\"\t\t\t\t\t\\\n\t\"and\tecx,01Fh\"\t\t\t\t\\\n\t\"btr\t[esi+ebx*4],ecx\"\t\t\\\n\t\"or\teax,eax\"\t\t\t\t\t\\\n\t\"jz\tok\"\t\t\t\t\t\t\\\n\t\"bts\t[esi+ebx*4],ecx\"\t\t\\\n\t\"ok:\"\n\nint Get_Bit(void const * array, int bit);\n#pragma aux Get_Bit parm [esi] [eax] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\tebx,eax\"\t\t\t\t\t\\\n\t\"shr\tebx,5\"\t\t\t\t\t\\\n\t\"and\teax,01Fh\"\t\t\t\t\\\n\t\"bt\t[esi+ebx*4],eax\"\t\t\\\n\t\"setc\tal\"\n\nint First_True_Bit(void const * array);\n#pragma aux First_True_Bit parm [esi] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\teax,-32\"\t\t\t\t\t\\\n\t\"again:\"\t\t\t\t\t\t\t\\\n\t\"add\teax,32\"\t\t\t\t\t\\\n\t\"mov\tebx,[esi]\"\t\t\t\t\\\n\t\"add\tesi,4\"\t\t\t\t\t\\\n\t\"bsf\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tagain\"\t\t\t\t\t\\\n\t\"add\teax,ebx\"\n\nint First_False_Bit(void const * array);\n#pragma aux First_False_Bit parm [esi] \\\n\tmodify [esi ebx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mov\teax,-32\"\t\t\t\t\t\\\n\t\"again:\"\t\t\t\t\t\t\t\\\n\t\"add\teax,32\"\t\t\t\t\t\\\n\t\"mov\tebx,[esi]\"\t\t\t\t\\\n\t\"not\tebx\"\t\t\t\t\t\t\\\n\t\"add\tesi,4\"\t\t\t\t\t\\\n\t\"bsf\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tagain\"\t\t\t\t\t\\\n\t\"add\teax,ebx\"\n\n#ifdef OBSOLETE\nextern int Bound(int original, int min, int max);\n#pragma aux Bound parm [eax] [ebx] [ecx] \\\n\tmodify [eax] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"cmp\tebx,ecx\"\t\t\t\t\t\\\n\t\"jl\tokorder\"\t\t\t\t\t\\\n\t\"xchg\tebx,ecx\"\t\t\t\t\t\\\n\t\"okorder: cmp\teax,ebx\"\t\t\\\n\t\"jg\tokmin\"\t\t\t\t\t\\\n\t\"mov\teax,ebx\"\t\t\t\t\t\\\n\t\"okmin: cmp\teax,ecx\"\t\t\t\\\n\t\"jl\tokmax\"\t\t\t\t\t\\\n\t\"mov\teax,ecx\"\t\t\t\t\t\\\n\t\"okmax:\"\n\nextern unsigned Bound(unsigned original, unsigned min, unsigned max);\n#pragma aux Bound parm [eax] [ebx] [ecx] \\\n\tmodify [eax] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"cmp\tebx,ecx\"\t\t\t\t\t\\\n\t\"jb\tokorder\"\t\t\t\t\t\\\n\t\"xchg\tebx,ecx\"\t\t\t\t\t\\\n\t\"okorder: cmp\teax,ebx\"\t\t\\\n\t\"ja\tokmin\"\t\t\t\t\t\\\n\t\"mov\teax,ebx\"\t\t\t\t\t\\\n\t\"okmin: cmp\teax,ecx\"\t\t\t\\\n\t\"jb\tokmax\"\t\t\t\t\t\\\n\t\"mov\teax,ecx\"\t\t\t\t\t\\\n\t\"okmax:\"\n#endif\n\n\nunsigned Fixed_To_Cardinal(unsigned base, unsigned fixed);\n#pragma aux Fixed_To_Cardinal parm [eax] [edx] \\\n\tmodify [edx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"mul\tedx\"\t\t\t\t\t\t\\\n\t\"add\teax,080h\"\t\t\t\t\\\n\t\"test\teax,0FF000000h\"\t\t\\\n\t\"jz\tok\"\t\t\t\t\t\t\\\n\t\"mov\teax,000FFFFFFh\"\t\t\\\n\t\"ok:\"\t\t\t\t\t\t\t\t\\\n\t\"shr\teax,8\"\n\n\nunsigned Cardinal_To_Fixed(unsigned base, unsigned cardinal);\n#pragma aux Cardinal_To_Fixed parm [ebx] [eax] \\\n\tmodify [edx] \\\n\tvalue [eax]\t\t= \t\t\t\t\\\n\t\"or\tebx,ebx\"\t\t\t\t\t\\\n\t\"jz\tfini\"\t\t\t\t\t\t\\\n\t\"shl\teax,8\"\t\t\t\t\t\\\n\t\"xor\tedx,edx\"\t\t\t\t\t\\\n\t\"div\tebx\"\t\t\t\t\t\t\\\n\t\"fini:\"\n\n\n#ifndef OUTPORTB\n#define OUTPORTB\nextern void outportb(int port, unsigned char data);\n#pragma aux outportb parm [edx] [al] =\t\t\\\n\t\t\"out\tdx,al\"\n\nextern void outport(int port, unsigned short data);\n#pragma aux outport parm [edx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n#endif\n\n#endif\n\n/*\n**\tTimer objects that fetch the appropriate timer value according to\n**\tthe type of timer they are.\n*/\nextern long Frame;\nclass FrameTimerClass\n{\n\tpublic:\n\t\tlong operator () (void) const {return(Frame);};\n\t\toperator long (void) const {return(Frame);};\n};\n\n\n#ifndef WIN32\nextern bool TimerSystemOn;\nextern \"C\" {\n\tlong Get_System_Tick_Count(void);\n\tlong Get_User_Tick_Count(void);\n}\n//bool Init_Timer_System(unsigned int freq, int partial=false);\nbool Remove_Timer_System(void);\n#else\nextern WinTimerClass\t*\t\tWindowsTimer;\n#endif\n\n#ifndef SYSTEM_TIMER_CLASS\n#define SYSTEM_TIMER_CLASS\nclass SystemTimerClass\n{\n\tpublic:\n\t\t#ifdef WIN32\n\t\t\tlong operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t\toperator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t#else\n\t\t\tlong operator () (void) const {return(Get_System_Tick_Count());};\n\t\t\toperator long (void) const {return(Get_System_Tick_Count());};\n\t\t#endif\n};\n#endif\n\n\nclass UserTimerClass\n{\n\tpublic:\n\t\t#ifdef WIN32\n\t\t\tlong operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_User_Tick_Count());};\n\t\t\toperator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_User_Tick_Count());};\n\t\t#else\n\t\t\tlong operator () (void) const {return(Get_User_Tick_Count());};\n\t\t\toperator long (void) const {return(Get_User_Tick_Count());};\n\t\t#endif\n};\n\n\ntemplate<class T>\nvoid Bubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (array[index] > array[index+1]) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nvoid PBubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (*array[index] > *array[index+1]) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nvoid PNBubble_Sort(T * array, int count)\n{\n\tif (array != NULL && count > 1) {\n\t\tbool swapflag;\n\n\t\tdo {\n\t\t\tswapflag = false;\n\t\t\tfor (int index = 0; index < count-1; index++) {\n\t\t\t\tif (stricmp(array[index]->Name(), array[index+1]->Name()) > 0) {\n\t\t\t\t\tT temp = array[index];\n\t\t\t\t\tarray[index] = array[index+1];\n\t\t\t\t\tarray[index+1] = temp;\n\t\t\t\t\tswapflag = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (swapflag);\n\t}\n}\n\ntemplate<class T>\nclass SmartPtr\n{\n\tpublic:\n\t\tSmartPtr(NoInitClass const &) {}\n\t\tSmartPtr(T * realptr = 0) : Pointer(realptr) {}\n\t\tSmartPtr(SmartPtr const & rvalue) : Pointer(rvalue.Pointer) {}\n\t\t~SmartPtr(void) {Pointer = 0;}\n\n\t\toperator T * (void) const {return(Pointer);}\n\n\t\toperator long (void) const {return((long)Pointer);}\n\n\t\tSmartPtr<T> operator ++ (int) {assert(Pointer != 0);SmartPtr<T> temp = *this;++Pointer;return(temp);}\n\t\tSmartPtr<T> & operator ++ (void) {assert(Pointer != 0);++Pointer;return(*this);}\n\t\tSmartPtr<T> operator -- (int) {assert(Pointer != 0);SmartPtr<T> temp = *this;--Pointer;return(temp);}\n\t\tSmartPtr<T> & operator -- (void) {assert(Pointer != 0);--Pointer;return(*this);}\n\n\t\tSmartPtr & operator = (SmartPtr const & rvalue) {Pointer = rvalue.Pointer;return(*this);}\n\t\tT * operator -> (void) const {assert(Pointer != 0);return(Pointer);}\n\t\tT & operator * (void) const {assert(Pointer != 0);return(*Pointer);}\n\n\tprivate:\n\t\tT * Pointer;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/KEY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/KEY.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Clear -- Clears the keyboard buffer.                                     *\n *   WWKeyboardClass::Down -- Checks to see if the specified key is being held down.           *\n *   WWKeyboardClass::Fetch_Element -- Extract the next element in the keyboard buffer.        *\n *   WWKeyboardClass::Fill_Buffer_From_Syste -- Extract and process any queued windows messages*\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Is_Buffer_Empty -- Checks to see if the keyboard buffer is empty.        *\n *   WWKeyboardClass::Is_Buffer_Full -- Determines if the keyboard buffer is full.             *\n *   WWKeyboardClass::Is_Mouse_Key -- Checks to see if specified key refers to the mouse.      *\n *   WWKeyboardClass::Message_Handler -- Process a windows message as it relates to the keyboar*\n *   WWKeyboardClass::Peek_Element -- Fetches the next element in the keyboard buffer.         *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Put_Element -- Put a keyboard data element into the buffer.              *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::To_ASCII -- Convert the key value into an ASCII representation.          *\n *   WWKeyboardClass::Available_Buffer_Room -- Fetch the quantity of free elements in the keybo*\n *   WWKeyboardClass::Put_Mouse_Message -- Stores a mouse type message into the keyboard buffer*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"key.h\"\n\n#include\t\"monoc.h\"\n\n//void Message_Loop(void);\n\n//WWKeyboardClass * _Kbd = NULL;\n\n\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void) :\n\tMouseQX(0),\n\tMouseQY(0),\n\tHead(0),\n\tTail(0)\n{\n//\t_Kbd = this;\n\n\tmemset(KeyState, '\\0', sizeof(KeyState));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\n\tunsigned short temp = Fetch_Element();\n\tif (Is_Mouse_Key(temp)) {\n\t\tMouseQX = Fetch_Element();\n\t\tMouseQY = Fetch_Element();\n\t}\n\treturn(temp);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Mouse_Key -- Checks to see if specified key refers to the mouse.        *\n *                                                                                             *\n *    This checks the specified key code to see if it refers to the mouse buttons.             *\n *                                                                                             *\n * INPUT:   key   -- The key to check.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Is the key a mouse button key?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Mouse_Key(unsigned short key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *   09/24/1996 JLB : Converted to new style keyboard system.                                  *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Check(void) const\n{\n\t((WWKeyboardClass *)this)->Fill_Buffer_From_System();\n\tif (Is_Buffer_Empty()) return(false);\n\treturn(Peek_Element());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\treturn (Buff_Get());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put(unsigned short key)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tPut_Element(key);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release)\n{\n\t/*\n\t** Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t** to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t** that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t** would be incompatible with the dos version.\n\t*/\n\tif (!Is_Mouse_Key(vk_key)) {\n\t\tif (((GetKeyState(VK_SHIFT) & 0x8000) != 0) ||\n\t\t\t((GetKeyState(VK_CAPITAL) & 0x0008) != 0) ||\n\t\t\t((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) {\n\n\t\t\tvk_key |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_MENU) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_ALT_BIT;\n\t\t}\n\t}\n\n\tif (release) {\n\t\tvk_key |= WWKEY_RLS_BIT;\n\t}\n\n\t/*\n\t** Finally use the put command to enter the key into the keyboard\n\t** system.\n\t*/\n\treturn(Put(vk_key));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Mouse_Message -- Stores a mouse type message into the keyboard buffer. *\n *                                                                                             *\n *    This routine will store the mouse type event into the keyboard buffer. It also checks    *\n *    to ensure that there is enough room in the buffer so that partial mouse events won't     *\n *    be recorded.                                                                             *\n *                                                                                             *\n * INPUT:   vk_key   -- The mouse key message itself.                                          *\n *                                                                                             *\n *          x,y      -- The mouse coordinates at the time of the event.                        *\n *                                                                                             *\n *          release  -- Is this a mouse button release?                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the event stored sucessfully into the keyboard buffer?                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Mouse_Message(unsigned short vk_key, int x, int y, bool release)\n{\n\tif (Available_Buffer_Room() >= 3 && Is_Mouse_Key(vk_key)) {\n\t\tPut_Key_Message(vk_key, release);\n\t\tPut((unsigned short)x);\n\t\tPut((unsigned short)y);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::To_ASCII -- Convert the key value into an ASCII representation.            *\n *                                                                                             *\n *    This routine will convert the key code specified into an ASCII value. This takes into    *\n *    consideration the language and keyboard mapping of the host Windows system.              *\n *                                                                                             *\n * INPUT:   key   -- The key code to convert into ASCII.                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the key converted into ASCII. If the key has no ASCII equivalent,     *\n *          then '\\0' is returned.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar WWKeyboardClass::To_ASCII(unsigned short key)\n{\n\t/*\n\t**\tReleased keys never translate into an ASCII value.\n\t*/\n\tif (key & WWKEY_RLS_BIT) {\n\t\treturn('\\0');\n\t}\n\n\t/*\n\t**\tSet the KeyState buffer to reflect the shift bits stored in the key value.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0x80;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0x80;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0x80;\n\t}\n\n\t/*\n\t**\tAsk windows to translate the key into an ASCII equivalent.\n\t*/\n\tchar buffer[10];\n\tint result = 1;\n\tint scancode = 0;\n\n\tscancode = MapVirtualKey(key & 0xFF, 0);\n\tresult = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0);\n\n\t/*\n\t**\tRestore the KeyState buffer back to pristine condition.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0;\n\t}\n\n\t/*\n\t**\tIf Windows could not perform the translation as expected, then\n\t**\treturn with a null ASCII value.\n\t*/\n\tif (result != 1) {\n\t\treturn('\\0');\n\t}\n\n\treturn(buffer[0]);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Down -- Checks to see if the specified key is being held down.             *\n *                                                                                             *\n *    This routine will examine the key specified to see if it is currently being held down.   *\n *                                                                                             *\n * INPUT:   key   -- The key to check.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified key currently being held down?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Down(unsigned short key)\n{\n\treturn(GetAsyncKeyState(key & 0xFF) == 0 ? false : true);\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Fetch_Element -- Extract the next element in the keyboard buffer.          *\n *                                                                                             *\n *    This routine will extract the next pending element in the keyboard queue. If there is    *\n *    no element available, then NULL is returned.                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the element extracted from the queue. An empty queue is signified     *\n *          by a 0 return value.                                                               *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Fetch_Element(void)\n{\n\tunsigned short val = 0;\n\tif (Head != Tail) {\n\t\tval = Buffer[Head];\n\n\t\tHead = (Head + 1) % ARRAY_SIZE(Buffer);\n\t}\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Peek_Element -- Fetches the next element in the keyboard buffer.           *\n *                                                                                             *\n *    This routine will examine and return with the next element in the keyboard buffer but    *\n *    it will not alter or remove that element. Use this routine to see what is pending in     *\n *    the keyboard queue.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the next element in the keyboard queue. If the keyboard buffer is     *\n *          empty, then 0 is returned.                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Peek_Element(void) const\n{\n\tif (!Is_Buffer_Empty()) {\n\t\treturn(Buffer[Head]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Element -- Put a keyboard data element into the buffer.                *\n *                                                                                             *\n *    This will put one keyboard data element into the keyboard buffer. Typically, this data   *\n *    is a key code, but it might be mouse coordinates.                                        *\n *                                                                                             *\n * INPUT:   val   -- The data element to add to the keyboard buffer.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the keyboard element added successfully? A failure would indicate that   *\n *                the keyboard buffer is full.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Element(unsigned short val)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tint temp = (Tail+1) % ARRAY_SIZE(Buffer);\n\t\tBuffer[Tail] = val;\n\t\tTail = temp;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Buffer_Full -- Determines if the keyboard buffer is full.               *\n *                                                                                             *\n *    This routine will examine the keyboard buffer to determine if it is completely           *\n *    full of queued keyboard events.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the keyboard buffer completely full?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Buffer_Full(void) const\n{\n\tif ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Is_Buffer_Empty -- Checks to see if the keyboard buffer is empty.          *\n *                                                                                             *\n *    This routine will examine the keyboard buffer to see if it contains no events at all.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the keyboard buffer currently without any pending events queued?          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Is_Buffer_Empty(void) const\n{\n\tif (Head == Tail) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Fill_Buffer_From_Syste -- Extract and process any queued windows messages. *\n *                                                                                             *\n *    This routine will extract and process any windows messages in the windows message        *\n *    queue. It is presumed that the normal message handler will call the keyboard             *\n *    message processing function.                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WWKeyboardClass::Fill_Buffer_From_System(void)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tMSG\tmsg;\n\t\twhile (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {\n\t\t  \tif (!GetMessage( &msg, NULL, 0, 0 )) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Clear -- Clears the keyboard buffer.                                       *\n *                                                                                             *\n *    This routine will clear the keyboard buffer of all pending keyboard events.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid WWKeyboardClass::Clear(void)\n{\n\t/*\n\t**\tExtract any windows pending keyboard message events and then clear out the keyboard\n\t**\tbuffer.\n\t*/\n\tFill_Buffer_From_System();\n\tHead = Tail;\n\n\t/*\n\t**\tPerform a second clear to handle the rare case of the keyboard buffer being full and there\n\t**\tstill remains keyboard related events in the windows message queue.\n\t*/\n\tFill_Buffer_From_System();\n\tHead = Tail;\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Message_Handler -- Process a windows message as it relates to the keyboard *\n *                                                                                             *\n *    This routine will examine the Windows message specified. If the message relates to an    *\n *    event that the keyboard input system needs to process, then it will be processed         *\n *    accordingly.                                                                             *\n *                                                                                             *\n * INPUT:   window   -- Handle to the window receiving the message.                            *\n *                                                                                             *\n *          message  -- The message number of this event.                                      *\n *                                                                                             *\n *          wParam   -- The windows specific word parameter (meaning depends on message).      *\n *                                                                                             *\n *          lParam   -- The windows specific long word parameter (meaning is message dependant)*\n *                                                                                             *\n * OUTPUT:  bool; Was this keyboard message recognized and processed? A 'false' return value   *\n *                means that the message should be processed normally.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Message_Handler(HWND window, UINT message, UINT wParam, LONG lParam)\n{\n// ST - 5/13/2019\n#if (0)\n\tbool processed = false;\n\n\t/*\n\t**\tExamine the message to see if it is one that should be processed. Only keyboard and\n\t**\tpertinant mouse messages are processed.\n\t*/\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tSystem key has been pressed. This is the normal keyboard event message.\n\t\t*/\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif (wParam == VK_SCROLL) {\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message((unsigned short)wParam);\n\t\t\t}\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tThe key has been released. This is the normal key release message.\n\t\t*/\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message((unsigned short)wParam, true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPress of the left mouse button.\n\t\t*/\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRelease of the left mouse button.\n\t\t*/\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDouble click of the left mouse button. Fake this into being\n\t\t**\tjust a rapid click of the left button twice.\n\t\t*/\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_LBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPress of the middle mouse button.\n\t\t*/\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRelease of the middle mouse button.\n\t\t*/\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMiddle button double click gets translated into two\n\t\t**\tregular middle button clicks.\n\t\t*/\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_MBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRight mouse button press.\n\t\t*/\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRight mouse button release.\n\t\t*/\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTranslate a double click of the right button\n\t\t**\tinto being just two regular right button clicks.\n\t\t*/\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam));\n\t\t\tPut_Mouse_Message(VK_RBUTTON, LOWORD(lParam), HIWORD(lParam), true);\n\t\t\tprocessed = true;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tIf the message is not pertinant to the keyboard system,\n\t\t**\tthen do nothing.\n\t\t*/\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tIf this message has been processed, then pass it on to the system\n\t**\tdirectly.\n\t*/\n\tif (processed) {\n\t\tDefWindowProc(window, message, wParam, lParam);\n\t\treturn(true);\n\t}\n#endif\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Available_Buffer_Room -- Fetch the quantity of free elements in the keyboa *\n *                                                                                             *\n *    This examines the keyboard buffer queue and determine how many elements are available    *\n *    for use before the buffer becomes full. Typical use of this would be when inserting      *\n *    mouse events that require more than one element. Such an event must detect when there    *\n *    would be insufficient room in the buffer and bail accordingly.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of elements that may be stored in to the keyboard buffer   *\n *          before it becomes full and cannot accept any more elements.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWKeyboardClass::Available_Buffer_Room(void) const\n{\n\tint avail;\n\tif (Head == Tail) {\n\t\tavail = ARRAY_SIZE(Buffer);\n\t}\n\tif (Head < Tail) {\n\t\tavail = Tail - Head;\n\t}\n\tif (Head > Tail) {\n\t\tavail = (Tail + ARRAY_SIZE(Buffer)) - Head;\n\t}\n\treturn(avail);\n}\n"
  },
  {
    "path": "REDALERT/KEY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/KEY.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n#ifndef WIN32\n#include\t\"..\\wwflat32\\include\\keyboard.h\"\n#else\n\n#include\t<windows.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\tWWKeyboardClass();\n\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\tunsigned short Check(void) const;\n\t\tunsigned short Get(void);\n\t\tbool Put(unsigned short key);\n\t\tvoid Clear(void);\n\t\tchar To_ASCII(unsigned short num);\n\t\tbool Down(unsigned short key);\n\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\tbool Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\tint MouseQX;\n\t\tint MouseQY;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a keyboard state array that is used to aid in translating\n\t\t**\tKN_ keys into KA_ keys.\n\t\t*/\n\t\tunsigned char KeyState[256];\n\n\t\t/*\n\t\t**\tThis is the circular keyboard holding buffer. It holds the VK key and\n\t\t**\tthe current shift state at the time the key was added to the queue.\n\t\t*/\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\n\t\tunsigned short Buff_Get(void);\n\t\tunsigned short Fetch_Element(void);\n\t\tunsigned short Peek_Element(void) const;\n\t\tbool Put_Element(unsigned short val);\n\t\tbool Is_Buffer_Full(void) const;\n\t\tbool Is_Buffer_Empty(void) const;\n\t\tstatic bool Is_Mouse_Key(unsigned short key);\n\t\tvoid Fill_Buffer_From_System(void);\n\t\tbool Put_Key_Message(unsigned short vk_key, bool release = false);\n\t\tbool Put_Mouse_Message(unsigned short vk_key, int x, int y, bool release = false);\n\t\tint Available_Buffer_Room(void) const;\n\n\t\t/*\n\t\t**\tThese are the tracking pointers to maintain the\n\t\t**\tcircular keyboard list.\n\t\t*/\n\t\tint Head;\n\t\tint Tail;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\t//\t;\n#define\tVK_NONE_BB\t\t\t  0xBB\t// =\n#define\tVK_NONE_BC\t\t\t  0xBC\t// ,\n#define\tVK_NONE_BD\t\t\t  0xBD\t// -\n#define\tVK_NONE_BE\t\t\t  0xBE\t// .\n#define\tVK_NONE_BF\t\t\t  0xBF\t// /\n#define\tVK_NONE_C0\t\t\t  0xC0\t// `\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\t\t// [\n#define\tVK_NONE_DC\t\t\t  0xDC\t\t// '\\'\n#define\tVK_NONE_DD\t\t\t  0xDD\t\t// ]\n#define\tVK_NONE_DE\t\t\t  0xDE\t\t// '\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\ntypedef enum KeyASCIIType {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE,\n\tKA_EXTEND \t\t\t= VK_ESCAPE,\n\tKA_RETURN \t\t\t= VK_RETURN,\n\tKA_BACKSPACE \t\t= VK_BACK,\n\tKA_TAB \t\t\t\t= VK_TAB ,\n\tKA_DELETE\t\t\t= VK_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT,\n\tKA_DOWN\t\t\t\t= VK_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR,\n\tKA_UP\t\t\t\t\t= VK_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME,\n\tKA_F12\t\t\t\t= VK_F12,\n\tKA_F11\t\t\t\t= VK_F11,\n\tKA_F10\t\t\t\t= VK_F10,\n\tKA_F9 \t\t\t\t= VK_F9,\n\tKA_F8\t\t\t\t\t= VK_F8,\n\tKA_F7\t\t\t\t\t= VK_F7,\n\tKA_F6\t\t\t\t\t= VK_F6,\n\tKA_F5\t\t\t\t\t= VK_F5,\n\tKA_F4\t\t\t\t\t= VK_F4,\n\tKA_F3\t\t\t\t\t= VK_F3,\n\tKA_F2\t\t\t\t\t= VK_F2,\n\tKA_F1\t\t\t\t\t= VK_F1,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n} KeyASCIIType;\n\n\ntypedef enum KeyNumType {\n\tKN_NONE\t\t\t\t= 0,\n\n\tKN_0 \t\t\t\t\t= VK_0,\n\tKN_1 \t\t\t\t\t= VK_1,\n\tKN_2 \t\t\t\t\t= VK_2,\n\tKN_3 \t\t\t\t\t= VK_3,\n\tKN_4 \t\t\t\t\t= VK_4,\n\tKN_5 \t\t\t\t\t= VK_5,\n\tKN_6 \t\t\t\t\t= VK_6,\n\tKN_7 \t\t\t\t\t= VK_7,\n\tKN_8 \t\t\t\t\t= VK_8,\n\tKN_9 \t\t\t\t\t= VK_9,\n\tKN_A \t\t\t\t\t= VK_A,\n\tKN_B \t\t\t\t\t= VK_B,\n\tKN_BACKSLASH\t\t= VK_NONE_DC,\n\tKN_BACKSPACE\t\t= VK_BACK,\n\tKN_C \t\t\t\t\t= VK_C,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL,\n\tKN_CENTER\t\t\t= VK_CLEAR,\n\tKN_COMMA \t\t\t= VK_NONE_BC,\n\tKN_D \t\t\t\t\t= VK_D,\n\tKN_DELETE\t\t\t= VK_DELETE,\n\tKN_DOWN\t\t\t\t= VK_DOWN,\n\tKN_DOWNLEFT\t\t\t= VK_END,\n\tKN_DOWNRIGHT\t\t= VK_NEXT,\n\tKN_E \t\t\t\t\t= VK_E,\n\tKN_END\t\t\t\t= VK_END,\n\tKN_EQUAL \t\t\t= VK_NONE_BB,\n\tKN_ESC\t\t\t\t= VK_ESCAPE,\n\tKN_E_DELETE \t\t= VK_DELETE,\n\tKN_E_DOWN\t\t\t= VK_NUMPAD2,\n\tKN_E_END\t\t\t\t= VK_NUMPAD1,\n\tKN_E_HOME\t\t\t= VK_NUMPAD7,\n\tKN_E_INSERT\t\t\t= VK_INSERT,\n\tKN_E_LEFT\t\t\t= VK_NUMPAD4,\n\tKN_E_PGDN   \t\t= VK_NUMPAD3,\n\tKN_E_PGUP\t\t\t= VK_NUMPAD9,\n\tKN_E_RIGHT\t\t\t= VK_NUMPAD6,\n\tKN_E_UP\t\t\t\t= VK_NUMPAD8,\n\tKN_F \t\t\t\t\t= VK_F,\n\tKN_F1\t\t\t\t\t= VK_F1,\n\tKN_F10\t\t\t\t= VK_F10,\n\tKN_F11\t\t\t\t= VK_F11,\n\tKN_F12\t\t\t\t= VK_F12,\n\tKN_F2\t\t\t\t\t= VK_F2,\n\tKN_F3\t\t\t\t\t= VK_F3,\n\tKN_F4\t\t\t\t\t= VK_F4,\n\tKN_F5\t\t\t\t\t= VK_F5,\n\tKN_F6\t\t\t\t\t= VK_F6,\n\tKN_F7\t\t\t\t\t= VK_F7,\n\tKN_F8\t\t\t\t\t= VK_F8,\n\tKN_F9\t\t\t\t\t= VK_F9,\n\tKN_G \t\t\t\t\t= VK_G,\n\tKN_GRAVE \t\t\t= VK_NONE_C0,\n\tKN_H \t\t\t\t\t= VK_H,\n\tKN_HOME\t\t\t\t= VK_HOME,\n\tKN_I \t\t\t\t\t= VK_I,\n\tKN_INSERT\t\t\t= VK_INSERT,\n\tKN_J \t\t\t\t\t= VK_J,\n\tKN_K \t\t\t\t\t= VK_K,\n\tKN_KEYPAD_ASTERISK= VK_MULTIPLY,\n\tKN_KEYPAD_MINUS\t= VK_SUBTRACT,\n\tKN_KEYPAD_PLUS\t\t= VK_ADD,\n\tKN_KEYPAD_RETURN\t= VK_RETURN,\n\tKN_KEYPAD_SLASH\t= VK_DIVIDE,\n\tKN_L \t\t\t\t\t= VK_L,\n\tKN_LALT\t\t\t\t= VK_MENU,\n\tKN_LBRACKET\t\t\t= VK_NONE_DB,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL,\n\tKN_LEFT\t\t\t\t= VK_LEFT,\n\tKN_LMOUSE\t\t\t= VK_LBUTTON,\n\tKN_LSHIFT\t\t\t= VK_SHIFT,\n\tKN_M \t\t\t\t\t= VK_M,\n\tKN_MINUS \t\t\t= VK_NONE_BD,\n\tKN_N \t\t\t\t\t= VK_N,\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK,\n\tKN_O \t\t\t\t\t= VK_O,\n\tKN_P \t\t\t\t\t= VK_P,\n\tKN_PAUSE\t\t\t\t= VK_PAUSE,\n\tKN_PERIOD \t\t\t= VK_NONE_BE,\n\tKN_PGDN\t\t\t\t= VK_NEXT,\n\tKN_PGUP\t\t\t\t= VK_PRIOR,\n\tKN_PRNTSCRN\t\t\t= VK_PRINT,\n\tKN_Q \t\t\t\t\t= VK_Q,\n\tKN_R \t\t\t\t\t= VK_R,\n\tKN_RALT\t\t\t\t= VK_MENU,\n\tKN_RBRACKET\t\t\t= VK_NONE_DD,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL,\n\tKN_RETURN \t\t\t= VK_RETURN,\n\tKN_RIGHT\t\t\t\t= VK_RIGHT,\n\tKN_RMOUSE\t\t\t= VK_RBUTTON,\n\tKN_RSHIFT\t\t\t= VK_SHIFT,\n\tKN_S \t\t\t\t\t= VK_S,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL,\n\tKN_SEMICOLON \t\t= VK_NONE_BA,\n\tKN_SLASH \t\t\t= VK_NONE_BF,\n\tKN_SPACE \t\t\t= VK_SPACE,\n\tKN_SQUOTE \t\t\t= VK_NONE_DE,\n\tKN_T \t\t\t\t\t= VK_T,\n\tKN_TAB\t\t\t\t= VK_TAB,\n\tKN_U \t\t\t\t\t= VK_U,\n\tKN_UP\t\t\t\t\t= VK_UP,\n\tKN_UPLEFT\t\t\t= VK_HOME,\n\tKN_UPRIGHT\t\t\t= VK_PRIOR,\n\tKN_V \t\t\t\t\t= VK_V,\n\tKN_W \t\t\t\t\t= VK_W,\n\tKN_X \t\t\t\t\t= VK_X,\n\tKN_Y \t\t\t\t\t= VK_Y,\n\tKN_Z \t\t\t\t\t= VK_Z,\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n} KeyNumType;\n\n\n//extern WWKeyboardClass *_Kbd;\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/KEYBOARD.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\conquer.cpv   4.74   23 Sep 1996 12:36:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : September 24, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *\n *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *\n *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *\n *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *\n *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *\n *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *\n *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *\n *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *\n *   Check_Key -- compatability routine for old 32 bit library                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"keyboard.h\"\n\n#include\t\"monoc.h\"\n\n//void Message_Loop(void);\n\nWWKeyboardClass * _Kbd = NULL;\n\n\n#define\tARRAY_SIZE(x)\t\tint(sizeof(x)/sizeof(x[0]))\n\n\n/***********************************************************************************************\n * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *\n *                                                                                             *\n * INPUT:\t\tnone\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * OUTPUT:     none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nWWKeyboardClass::WWKeyboardClass(void) :\n\tMouseQX(0),\n\tMouseQY(0),\n\tHead(0),\n\tTail(0)\n//\tMState(0),\n//\tConditional(0),\n//\tCurrentCursor(0)\n{\n\t_Kbd = this;\n\n\tmemset(KeyState, '\\0', sizeof(KeyState));\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the key value that was pulled from buffer (includes bits)\t\t\t\t  *                                                                                *\n *                                                                                             *\n * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Buff_Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t\t\t// wait for key in buffer\n\n\tunsigned short temp = Fetch_Element();\n\tif (Is_Mouse_Key(temp)) {\n\t\tMouseQX = Fetch_Element();\n\t\tMouseQY = Fetch_Element();\n\t}\n\treturn(temp);\n}\n\n\nbool WWKeyboardClass::Is_Mouse_Key(unsigned short key)\n{\n\tkey &= 0xFF;\n\treturn (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *   09/24/1996 JLB : Converted to new style keyboard system.                                  *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Check(void) const\n{\n\t((WWKeyboardClass *)this)->Fill_Buffer_From_System();\n\tif (Is_Buffer_Empty()) return(false);\n\treturn(Peek_Element());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *\n *                                                                                             *\n * INPUT:\t\tnone                                                        \t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     int\t\t- the meta key taken from the buffer.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:\tThis routine will not return until a keypress is received\t\t\t\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nunsigned short WWKeyboardClass::Get(void)\n{\n\twhile (!Check()) {}\t\t\t\t\t\t\t\t// wait for key in buffer\n\treturn (Buff_Get());\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *\n *                                                                                             *\n * INPUT:\t\tint\t \t- the key to insert into the buffer          \t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:     bool\t\t- true if key is sucessfuly inserted.\t\t\t\t\t\t\t              *\n *                                                                                             *\n * WARNINGS:   none\t\t\t\t\t\t\t                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put(unsigned short key)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tPut_Element(key);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/16/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release)\n{\n\t//\n\t// Get the status of all of the different keyboard modifiers.  Note, only pay attention\n\t// to numlock and caps lock if we are dealing with a key that is affected by them.  Note\n\t// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this\n\t// would be incompatible with the dos version.\n\t//\n\tif (!Is_Mouse_Key(vk_key)) {\n\t\tif (((GetKeyState(VK_SHIFT) & 0x8000) != 0) ||\n\t\t\t((GetKeyState(VK_CAPITAL) & 0x0008) != 0) ||\n\t\t\t((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) {\n\n\t\t\tvk_key |= WWKEY_SHIFT_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_CTRL_BIT;\n\t\t}\n\t\tif ((GetKeyState(VK_MENU) & 0x8000) != 0) {\n\t\t\tvk_key |= WWKEY_ALT_BIT;\n\t\t}\n\t}\n\n\tif (release) {\n\t\tvk_key |= WWKEY_RLS_BIT;\n\t}\n\n\t//\n\t// Finally use the put command to enter the key into the keyboard\n\t// system.\n\t//\n\treturn(Put(vk_key));\n\n\n\n}\n\n#pragma warning (disable : 4065)\nchar WWKeyboardClass::To_ASCII(unsigned short key)\n{\n\t/*\n\t**\tReleased keys never translate into an ASCII value.\n\t*/\n\tif (key & WWKEY_RLS_BIT) {\n\t\treturn('\\0');\n\t}\n\n\t/*\n\t**\tSet the KeyState buffer to reflect the shift bits stored in the key value.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0x80;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0x80;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0x80;\n\t}\n\n\t/*\n\t**\tAsk windows to translate the key into an ASCII equivalent.\n\t*/\n\tchar buffer[10];\n\tint result = 1;\n\tint scancode = 0;\n\tchar override = '\\0';\n\n\tswitch (key & 0xFF) {\n//\t\tcase KN_RETURN:\n//\t\t\toverride = KA_RETURN;\n//\t\t\tbreak;\n\n//\t\tcase KN_BACKSPACE:\n//\t\t\toverride = KA_BACKSPACE;\n//\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tscancode = MapVirtualKey(key & 0xFF, 0);\n\t\t\tresult = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0);\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tRestore the KeyState buffer back to pristine condition.\n\t*/\n\tif (key & WWKEY_SHIFT_BIT) {\n\t\tKeyState[VK_SHIFT] = 0;\n\t}\n\tif (key & WWKEY_CTRL_BIT) {\n\t\tKeyState[VK_CONTROL] = 0;\n\t}\n\tif (key & WWKEY_ALT_BIT) {\n\t\tKeyState[VK_MENU] = 0;\n\t}\n\n\t/*\n\t**\tIf Windows could not perform the translation as expected, then\n\t**\treturn with a null ASCII value.\n\t*/\n\tif (result != 1) {\n\t\treturn('\\0');\n\t}\n\n\tif (override != 0) {\n\t\treturn(override);\n\t}\n\n\treturn(buffer[0]);\n}\n\n\nbool WWKeyboardClass::Down(unsigned short key)\n{\n\treturn(GetAsyncKeyState(key & 0xFF) == 0 ? false : true);\n}\n\n\nextern \"C\" {\n\tvoid __cdecl Stop_Execution (void);\n}\n\n\n\nunsigned short WWKeyboardClass::Fetch_Element(void)\n{\n\tunsigned short val = 0;\n\tif (Head != Tail) {\n\t\tval = Buffer[Head];\n\n\t\tHead = (Head + 1) % ARRAY_SIZE(Buffer);\n\t}\n\treturn(val);\n}\n\n\nunsigned short WWKeyboardClass::Peek_Element(void) const\n{\n\tif (!Is_Buffer_Empty()) {\n\t\treturn(Buffer[Head]);\n\t}\n\treturn(0);\n}\n\n\nbool WWKeyboardClass::Put_Element(unsigned short val)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tint temp = (Tail+1) % ARRAY_SIZE(Buffer);\n\t\tBuffer[Tail] = val;\n\t\tTail = temp;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nbool WWKeyboardClass::Is_Buffer_Full(void) const\n{\n\tif ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nbool WWKeyboardClass::Is_Buffer_Empty(void) const\n{\n\tif (Head == Tail) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\nvoid WWKeyboardClass::Fill_Buffer_From_System(void)\n{\n\tif (!Is_Buffer_Full()) {\n\t\tMSG\tmsg;\n\t\twhile (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {\n\t\t  \tif (!GetMessage( &msg, NULL, 0, 0 )) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTranslateMessage(&msg);\n\t\t\tDispatchMessage(&msg);\n\t\t}\n\t}\n}\n\n\nvoid WWKeyboardClass::Clear(void)\n{\n\tHead = Tail;\n}\n\n\nvoid WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)\n{\n\tswitch (message) {\n\t\tcase WM_SYSKEYDOWN:\n\t\tcase WM_KEYDOWN:\n\t\t\tif ( wParam==VK_SCROLL ){\n\t\t\t\tStop_Execution();\n\t\t\t} else {\n\t\t\t\tPut_Key_Message((unsigned short)wParam);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_SYSKEYUP:\n\t\tcase WM_KEYUP:\n\t\t\tPut_Key_Message((unsigned short)wParam, true);\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_LBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONUP:\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_LBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_LBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_MBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONUP:\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_MBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_MBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t\tPut_Key_Message(VK_RBUTTON);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONUP:\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n\t\tcase WM_RBUTTONDBLCLK:\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tPut_Key_Message(VK_RBUTTON, true);\n\t\t\tPut(LOWORD(lParam));\n\t\t\tPut(HIWORD(lParam));\n\t\t\tbreak;\n\n//\t\tcase WM_MOUSEMOVE:\n//\t\t\tif (CurrentCursor)\n//\t\t\t\tSetCursor(CurrentCursor);\n//\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "REDALERT/KEYBOARD.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\conquer.cpv   4.74   23 Sep 1996 12:36:00   JOE_BOSTIC  $ */\n/***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Keyboard Library                                    *\n *                                                                                             *\n *                    File Name : KEYBOARD.H                                                   *\n *                                                                                             *\n *                   Programmer : Philip W. Gorrow                                             *\n *                                                                                             *\n *                   Start Date : 10/16/95                                                     *\n *                                                                                             *\n *                  Last Update : October 16, 1995 [PWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef KEYBOARD_H\n#define KEYBOARD_H\n\n#include\t<windows.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\ntypedef enum {\n\tWWKEY_SHIFT_BIT\t= 0x100,\n\tWWKEY_CTRL_BIT\t\t= 0x200,\n\tWWKEY_ALT_BIT\t\t= 0x400,\n\tWWKEY_RLS_BIT\t\t= 0x800,\n\tWWKEY_VK_BIT\t\t= 0x1000,\n\tWWKEY_DBL_BIT\t\t= 0x2000,\n\tWWKEY_BTN_BIT\t\t= 0x8000,\n} WWKey_Type;\n\n\nclass WWKeyboardClass\n{\n\tpublic:\n\t\t/* Define the base constructor and destructors for the class\t\t\t*/\n\t\tWWKeyboardClass();\n\n\t\t/* Define the functions which work with the Keyboard Class\t\t\t\t*/\n\t\tunsigned short Check(void) const;\n\t\tunsigned short Get(void);\n\t\tbool Put(unsigned short key);\n\t\tvoid Clear(void);\n\t\tchar To_ASCII(unsigned short num);\n\t\tbool Down(unsigned short key);\n\n\t\t/* Define the main hook for the message processing loop.\t\t\t\t\t*/\n\t\tvoid Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);\n\n\t\t/* Define the public access variables which are used with the\t\t\t*/\n\t\t/*   Keyboard Class.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n\t\tint MouseQX;\n\t\tint MouseQY;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a keyboard state array that is used to aid in translating\n\t\t**\tKN_ keys into KA_ keys.\n\t\t*/\n\t\tunsigned char KeyState[256];\n\n\t\t/*\n\t\t**\tThis is the circular keyboard holding buffer. It holds the VK key and\n\t\t**\tthe current shift state at the time the key was added to the queue.\n\t\t*/\n\t\tunsigned short Buffer[256];\t\t// buffer which holds actual keypresses\n\n\t\tunsigned short Buff_Get(void);\n\t\tunsigned short Fetch_Element(void);\n\t\tunsigned short Peek_Element(void) const;\n\t\tbool Put_Element(unsigned short val);\n\t\tbool Is_Buffer_Full(void) const;\n\t\tbool Is_Buffer_Empty(void) const;\n\t\tstatic bool Is_Mouse_Key(unsigned short key);\n\t\tvoid Fill_Buffer_From_System(void);\n\t\tbool Put_Key_Message(unsigned short vk_key, bool release = false);\n\n\t\t/*\n\t\t**\tThese are the tracking pointers to maintain the\n\t\t**\tcircular keyboard list.\n\t\t*/\n\t\tint Head;\n\t\tint Tail;\n};\n\n\n#define\tVK_NONE\t\t\t\t  0x00\n#define\tVK_LBUTTON          0x01\n#define\tVK_RBUTTON          0x02\n#define\tVK_CANCEL           0x03\n#define\tVK_MBUTTON          0x04\n#define\tVK_NONE_05\t\t\t  0x05\n#define\tVK_NONE_06\t\t\t  0x06\n#define\tVK_NONE_07\t\t\t  0x07\n#define\tVK_BACK             0x08\n#define\tVK_TAB              0x09\n#define\tVK_NONE_0A\t\t\t  0x0A\n#define\tVK_NONE_0B\t\t\t  0x0B\n#define\tVK_CLEAR            0x0C\n#define\tVK_RETURN           0x0D\n#define\tVK_NONE_0E\t\t\t  0x0E\n#define\tVK_NONE_0F\t\t\t  0x0F\n#define\tVK_SHIFT            0x10\n#define\tVK_CONTROL          0x11\n#define\tVK_MENU             0x12\n#define\tVK_PAUSE            0x13\n#define\tVK_CAPITAL          0x14\n#define\tVK_NONE_15\t\t\t  0x15\n#define\tVK_NONE_16\t\t\t  0x16\n#define\tVK_NONE_17\t\t\t  0x17\n#define\tVK_NONE_18\t\t\t  0x18\n#define\tVK_NONE_19\t\t\t  0x19\n#define\tVK_NONE_1A\t\t\t  0x1A\n#define\tVK_ESCAPE           0x1B\n#define\tVK_NONE_1C\t\t\t  0x1C\n#define\tVK_NONE_1D\t\t\t  0x1D\n#define\tVK_NONE_1E\t\t\t  0x1E\n#define\tVK_NONE_1F\t\t\t  0x1F\n#define\tVK_SPACE            0x20\n#define\tVK_PRIOR            0x21\n#define\tVK_NEXT             0x22\n#define\tVK_END              0x23\n#define\tVK_HOME             0x24\n#define\tVK_LEFT             0x25\n#define\tVK_UP               0x26\n#define\tVK_RIGHT            0x27\n#define\tVK_DOWN             0x28\n#define\tVK_SELECT           0x29\n#define\tVK_PRINT            0x2A\n#define\tVK_EXECUTE          0x2B\n#define\tVK_SNAPSHOT         0x2C\n#define\tVK_INSERT           0x2D\n#define\tVK_DELETE           0x2E\n#define\tVK_HELP             0x2F\n#define\tVK_0\t\t\t\t\t  0x30\n#define\tVK_1\t\t\t\t\t  0x31\n#define\tVK_2\t\t\t\t\t  0x32\n#define\tVK_3\t\t\t\t\t  0x33\n#define\tVK_4\t\t\t\t\t  0x34\n#define\tVK_5\t\t\t\t\t  0x35\n#define\tVK_6\t\t\t\t\t  0x36\n#define\tVK_7\t\t\t\t\t  0x37\n#define\tVK_8\t\t\t\t\t  0x38\n#define\tVK_9\t\t\t\t\t  0x39\n#define\tVK_NONE_3B\t\t\t  0x3B\n#define\tVK_NONE_3C\t\t\t  0x3C\n#define\tVK_NONE_3D\t\t\t  0x3D\n#define\tVK_NONE_3E\t\t\t  0x3E\n#define\tVK_NONE_3F\t\t\t  0x3F\n#define\tVK_NONE_40\t\t\t  0x40\n#define\tVK_A\t\t\t\t\t  0x41\n#define\tVK_B\t\t\t\t\t  0x42\n#define\tVK_C\t\t\t\t\t  0x43\n#define\tVK_D\t\t\t\t\t  0x44\n#define\tVK_E\t\t\t\t\t  0x45\n#define\tVK_F\t\t\t\t\t  0x46\n#define\tVK_G\t\t\t\t\t  0x47\n#define\tVK_H\t\t\t\t\t  0x48\n#define\tVK_I\t\t\t\t\t  0x49\n#define\tVK_J\t\t\t\t\t  0x4A\n#define\tVK_K\t\t\t\t\t  0x4B\n#define\tVK_L\t\t\t\t\t  0x4C\n#define\tVK_M\t\t\t\t\t  0x4D\n#define\tVK_N\t\t\t\t\t  0x4E\n#define\tVK_O\t\t\t\t\t  0x4F\n#define\tVK_P\t\t\t\t\t  0x50\n#define\tVK_Q\t\t\t\t\t  0x51\n#define\tVK_R\t\t\t\t\t  0x52\n#define\tVK_S\t\t\t\t\t  0x53\n#define\tVK_T\t\t\t\t\t  0x54\n#define\tVK_U\t\t\t\t\t  0x55\n#define\tVK_V\t\t\t\t\t  0x56\n#define\tVK_W\t\t\t\t\t  0x57\n#define\tVK_X\t\t\t\t\t  0x58\n#define\tVK_Y\t\t\t\t\t  0x59\n#define\tVK_Z\t\t\t\t\t  0x5A\n#define\tVK_NONE_5B\t\t\t  0x5B\n#define\tVK_NONE_5C\t\t\t  0x5C\n#define\tVK_NONE_5D\t\t\t  0x5D\n#define\tVK_NONE_5E\t\t\t  0x5E\n#define\tVK_NONE_5F\t\t\t  0x5F\n#define\tVK_NUMPAD0          0x60\n#define\tVK_NUMPAD1          0x61\n#define\tVK_NUMPAD2          0x62\n#define\tVK_NUMPAD3          0x63\n#define\tVK_NUMPAD4          0x64\n#define\tVK_NUMPAD5          0x65\n#define\tVK_NUMPAD6          0x66\n#define\tVK_NUMPAD7          0x67\n#define\tVK_NUMPAD8          0x68\n#define\tVK_NUMPAD9          0x69\n#define\tVK_MULTIPLY         0x6A\n#define\tVK_ADD              0x6B\n#define\tVK_SEPARATOR        0x6C\n#define\tVK_SUBTRACT         0x6D\n#define\tVK_DECIMAL          0x6E\n#define\tVK_DIVIDE           0x6F\n#define\tVK_F1               0x70\n#define\tVK_F2               0x71\n#define\tVK_F3               0x72\n#define\tVK_F4               0x73\n#define\tVK_F5               0x74\n#define\tVK_F6               0x75\n#define\tVK_F7               0x76\n#define\tVK_F8               0x77\n#define\tVK_F9               0x78\n#define\tVK_F10              0x79\n#define\tVK_F11              0x7A\n#define\tVK_F12              0x7B\n#define\tVK_F13              0x7C\n#define\tVK_F14              0x7D\n#define\tVK_F15              0x7E\n#define\tVK_F16              0x7F\n#define\tVK_F17              0x80\n#define\tVK_F18              0x81\n#define\tVK_F19              0x82\n#define\tVK_F20              0x83\n#define\tVK_F21              0x84\n#define\tVK_F22              0x85\n#define\tVK_F23              0x86\n#define\tVK_F24              0x87\n#define\tVK_NONE_88          0x88\n#define\tVK_NONE_89          0x89\n#define\tVK_NONE_8A          0x8A\n#define\tVK_NONE_8B          0x8B\n#define\tVK_NONE_8C          0x8C\n#define\tVK_NONE_8D          0x8D\n#define\tVK_NONE_8E          0x8E\n#define\tVK_NONE_8F          0x8F\n#define\tVK_NUMLOCK          0x90\n#define\tVK_SCROLL           0x91\n#define\tVK_NONE_92\t\t\t  0x92\n#define\tVK_NONE_93\t\t\t  0x93\n#define\tVK_NONE_94\t\t\t  0x94\n#define\tVK_NONE_95\t\t\t  0x95\n#define\tVK_NONE_96\t\t\t  0x96\n#define\tVK_NONE_97\t\t\t  0x97\n#define\tVK_NONE_98\t\t\t  0x98\n#define\tVK_NONE_99\t\t\t  0x99\n#define\tVK_NONE_9A\t\t\t  0x9A\n#define\tVK_NONE_9B\t\t\t  0x9B\n#define\tVK_NONE_9C\t\t\t  0x9C\n#define\tVK_NONE_9D\t\t\t  0x9D\n#define\tVK_NONE_9E\t\t\t  0x9E\n#define\tVK_NONE_9F\t\t\t  0x9F\n#define\tVK_NONE_A0\t\t\t  0xA0\n#define\tVK_NONE_A1\t\t\t  0xA1\n#define\tVK_NONE_A2\t\t\t  0xA2\n#define\tVK_NONE_A3\t\t\t  0xA3\n#define\tVK_NONE_A4\t\t\t  0xA4\n#define\tVK_NONE_A5\t\t\t  0xA5\n#define\tVK_NONE_A6\t\t\t  0xA6\n#define\tVK_NONE_A7\t\t\t  0xA7\n#define\tVK_NONE_A8\t\t\t  0xA8\n#define\tVK_NONE_A9\t\t\t  0xA9\n#define\tVK_NONE_AA\t\t\t  0xAA\n#define\tVK_NONE_AB\t\t\t  0xAB\n#define\tVK_NONE_AC\t\t\t  0xAC\n#define\tVK_NONE_AD\t\t\t  0xAD\n#define\tVK_NONE_AE\t\t\t  0xAE\n#define\tVK_NONE_AF\t\t\t  0xAF\n#define\tVK_NONE_B0\t\t\t  0xB0\n#define\tVK_NONE_B1\t\t\t  0xB1\n#define\tVK_NONE_B2\t\t\t  0xB2\n#define\tVK_NONE_B3\t\t\t  0xB3\n#define\tVK_NONE_B4\t\t\t  0xB4\n#define\tVK_NONE_B5\t\t\t  0xB5\n#define\tVK_NONE_B6\t\t\t  0xB6\n#define\tVK_NONE_B7\t\t\t  0xB7\n#define\tVK_NONE_B8\t\t\t  0xB8\n#define\tVK_NONE_B9\t\t\t  0xB9\n#define\tVK_NONE_BA\t\t\t  0xBA\t//\t;\n#define\tVK_NONE_BB\t\t\t  0xBB\t// =\n#define\tVK_NONE_BC\t\t\t  0xBC\t// ,\n#define\tVK_NONE_BD\t\t\t  0xBD\t// -\n#define\tVK_NONE_BE\t\t\t  0xBE\t// .\n#define\tVK_NONE_BF\t\t\t  0xBF\t// /\n#define\tVK_NONE_C0\t\t\t  0xC0\t// `\n#define\tVK_NONE_C1\t\t\t  0xC1\n#define\tVK_NONE_C2\t\t\t  0xC2\n#define\tVK_NONE_C3\t\t\t  0xC3\n#define\tVK_NONE_C4\t\t\t  0xC4\n#define\tVK_NONE_C5\t\t\t  0xC5\n#define\tVK_NONE_C6\t\t\t  0xC6\n#define\tVK_NONE_C7\t\t\t  0xC7\n#define\tVK_NONE_C8\t\t\t  0xC8\n#define\tVK_NONE_C9\t\t\t  0xC9\n#define\tVK_NONE_CA\t\t\t  0xCA\n#define\tVK_NONE_CB\t\t\t  0xCB\n#define\tVK_NONE_CC\t\t\t  0xCC\n#define\tVK_NONE_CD\t\t\t  0xCD\n#define\tVK_NONE_CE\t\t\t  0xCE\n#define\tVK_NONE_CF\t\t\t  0xCF\n#define\tVK_NONE_D0\t\t\t  0xD0\n#define\tVK_NONE_D1\t\t\t  0xD1\n#define\tVK_NONE_D2\t\t\t  0xD2\n#define\tVK_NONE_D3\t\t\t  0xD3\n#define\tVK_NONE_D4\t\t\t  0xD4\n#define\tVK_NONE_D5\t\t\t  0xD5\n#define\tVK_NONE_D6\t\t\t  0xD6\n#define\tVK_NONE_D7\t\t\t  0xD7\n#define\tVK_NONE_D8\t\t\t  0xD8\n#define\tVK_NONE_D9\t\t\t  0xD9\n#define\tVK_NONE_DA\t\t\t  0xDA\n#define\tVK_NONE_DB\t\t\t  0xDB\t\t// [\n#define\tVK_NONE_DC\t\t\t  0xDC\t\t// '\\'\n#define\tVK_NONE_DD\t\t\t  0xDD\t\t// ]\n#define\tVK_NONE_DE\t\t\t  0xDE\t\t// '\n#define\tVK_NONE_DF\t\t\t  0xDF\n#define\tVK_NONE_E0\t\t\t  0xE0\n#define\tVK_NONE_E1\t\t\t  0xE1\n#define\tVK_NONE_E2\t\t\t  0xE2\n#define\tVK_NONE_E3\t\t\t  0xE3\n#define\tVK_NONE_E4\t\t\t  0xE4\n#define\tVK_NONE_E5\t\t\t  0xE5\n#define\tVK_NONE_E6\t\t\t  0xE6\n#define\tVK_NONE_E7\t\t\t  0xE7\n#define\tVK_NONE_E8\t\t\t  0xE8\n#define\tVK_NONE_E9\t\t\t  0xE9\n#define\tVK_NONE_EA\t\t\t  0xEA\n#define\tVK_NONE_EB\t\t\t  0xEB\n#define\tVK_NONE_EC\t\t\t  0xEC\n#define\tVK_NONE_ED\t\t\t  0xED\n#define\tVK_NONE_EE\t\t\t  0xEE\n#define\tVK_NONE_EF\t\t\t  0xEF\n#define\tVK_NONE_F0\t\t\t  0xF0\n#define\tVK_NONE_F1\t\t\t  0xF1\n#define\tVK_NONE_F2\t\t\t  0xF2\n#define\tVK_NONE_F3\t\t\t  0xF3\n#define\tVK_NONE_F4\t\t\t  0xF4\n#define\tVK_NONE_F5\t\t\t  0xF5\n#define\tVK_NONE_F6\t\t\t  0xF6\n#define\tVK_NONE_F7\t\t\t  0xF7\n#define\tVK_NONE_F8\t\t\t  0xF8\n#define\tVK_NONE_F9\t\t\t  0xF9\n#define\tVK_NONE_FA\t\t\t  0xFA\n#define\tVK_NONE_FB\t\t\t  0xFB\n#define\tVK_NONE_FC\t\t\t  0xFC\n#define\tVK_NONE_FD\t\t\t  0xFD\n#define\tVK_NONE_FE\t\t\t  0xFE\n#define\tVK_NONE_FF\t\t\t  0xFF\n\n#define\tVK_UPLEFT\t\t\t  VK_HOME\n#define\tVK_UPRIGHT\t\t\t  VK_PRIOR\n#define\tVK_DOWNLEFT\t\t\t  VK_END\n#define\tVK_DOWNRIGHT\t\t  VK_NEXT\n#define\tVK_ALT\t\t\t\t  VK_MENU\n\nenum {\n\t//\n\t// Define all the KA types as variations of the VK types.  This is\n\t// so the KA functions will work properly under windows 95.\n\t//\n\tKA_NONE\t\t\t\t= 0,\n\tKA_MORE \t\t\t\t= 1,\n\tKA_SETBKGDCOL \t\t= 2,\n\tKA_SETFORECOL \t\t= 6,\n\tKA_FORMFEED \t\t= 12,\n\tKA_SPCTAB \t\t\t= 20,\n\tKA_SETX \t\t\t\t= 25,\n\tKA_SETY \t\t\t\t= 26,\n\n\tKA_SPACE\t\t\t\t= 32,\t\t\t\t\t/*   */\n\tKA_EXCLAMATION,\t\t\t\t\t\t\t/* ! */\n\tKA_DQUOTE,\t\t\t\t\t\t\t\t\t/* \" */\n\tKA_POUND,\t\t\t\t\t\t\t\t\t/* # */\n\tKA_DOLLAR,\t\t\t\t\t\t\t\t\t/* $ */\n\tKA_PERCENT,\t\t\t\t\t\t\t\t\t/* % */\n\tKA_AMPER,\t\t\t\t\t\t\t\t\t/* & */\n\tKA_SQUOTE,\t\t\t\t\t\t\t\t\t/* ' */\n\tKA_LPAREN,\t\t\t\t\t\t\t\t\t/* ( */\n\tKA_RPAREN,\t\t\t\t\t\t\t\t\t/* ) */\n\tKA_ASTERISK,\t\t\t\t\t\t\t\t/* * */\n\tKA_PLUS,\t\t\t\t\t\t\t\t\t\t/* + */\n\tKA_COMMA,\t\t\t\t\t\t\t\t\t/* , */\n\tKA_MINUS,\t\t\t\t\t\t\t\t\t/* - */\n\tKA_PERIOD,\t\t\t\t\t\t\t\t\t/* . */\n\tKA_SLASH,\t\t\t\t\t\t\t\t\t/* / */\n\n\tKA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,\n\tKA_COLON,\t\t\t\t\t\t\t\t\t/* : */\n\tKA_SEMICOLON,\t\t\t\t\t\t\t\t/* ; */\n\tKA_LESS_THAN,\t\t\t\t\t\t\t\t/* < */\n\tKA_EQUAL,\t\t\t\t\t\t\t\t\t/* = */\n\tKA_GREATER_THAN,\t\t\t\t\t\t\t/* > */\n\tKA_QUESTION,\t\t\t\t\t\t\t\t/* ? */\n\n\tKA_AT,\t\t\t\t\t\t\t\t\t\t/* @ */\n\tKA_A,\t\t\t\t\t\t\t\t\t\t\t/* A */\n\tKA_B,\t\t\t\t\t\t\t\t\t\t\t/* B */\n\tKA_C,\t\t\t\t\t\t\t\t\t\t\t/* C */\n\tKA_D,\t\t\t\t\t\t\t\t\t\t\t/* D */\n\tKA_E,\t\t\t\t\t\t\t\t\t\t\t/* E */\n\tKA_F,\t\t\t\t\t\t\t\t\t\t\t/* F */\n\tKA_G,\t\t\t\t\t\t\t\t\t\t\t/* G */\n\tKA_H,\t\t\t\t\t\t\t\t\t\t\t/* H */\n\tKA_I,\t\t\t\t\t\t\t\t\t\t\t/* I */\n\tKA_J,\t\t\t\t\t\t\t\t\t\t\t/* J */\n\tKA_K,\t\t\t\t\t\t\t\t\t\t\t/* K */\n\tKA_L,\t\t\t\t\t\t\t\t\t\t\t/* L */\n\tKA_M,\t\t\t\t\t\t\t\t\t\t\t/* M */\n\tKA_N,\t\t\t\t\t\t\t\t\t\t\t/* N */\n\tKA_O,\t\t\t\t\t\t\t\t\t\t\t/* O */\n\n\tKA_P,\t\t\t\t\t\t\t\t\t\t\t/* P */\n\tKA_Q,\t\t\t\t\t\t\t\t\t\t\t/* Q */\n\tKA_R,\t\t\t\t\t\t\t\t\t\t\t/* R */\n\tKA_S,\t\t\t\t\t\t\t\t\t\t\t/* S */\n\tKA_T,\t\t\t\t\t\t\t\t\t\t\t/* T */\n\tKA_U,\t\t\t\t\t\t\t\t\t\t\t/* U */\n\tKA_V,\t\t\t\t\t\t\t\t\t\t\t/* V */\n\tKA_W,\t\t\t\t\t\t\t\t\t\t\t/* W */\n\tKA_X,\t\t\t\t\t\t\t\t\t\t\t/* X */\n\tKA_Y,\t\t\t\t\t\t\t\t\t\t\t/* Y */\n\tKA_Z,\t\t\t\t\t\t\t\t\t\t\t/* Z */\n\tKA_LBRACKET,\t\t\t\t\t\t\t\t/* [ */\n\tKA_BACKSLASH,\t\t\t\t\t\t\t\t/* \\ */\n\tKA_RBRACKET,\t\t\t\t\t\t\t\t/* ] */\n\tKA_CARROT,\t\t\t\t\t\t\t\t\t/* ^ */\n\tKA_UNDERLINE,\t\t\t\t\t\t\t\t/* _ */\n\n\tKA_GRAVE,\t\t\t\t\t\t\t\t\t/* ` */\n\tKA_a,\t\t\t\t\t\t\t\t\t\t\t/* a */\n\tKA_b,\t\t\t\t\t\t\t\t\t\t\t/* b */\n\tKA_c,\t\t\t\t\t\t\t\t\t\t\t/* c */\n\tKA_d,\t\t\t\t\t\t\t\t\t\t\t/* d */\n\tKA_e,\t\t\t\t\t\t\t\t\t\t\t/* e */\n\tKA_f,\t\t\t\t\t\t\t\t\t\t\t/* f */\n\tKA_g,\t\t\t\t\t\t\t\t\t\t\t/* g */\n\tKA_h,\t\t\t\t\t\t\t\t\t\t\t/* h */\n\tKA_i,\t\t\t\t\t\t\t\t\t\t\t/* i */\n\tKA_j,\t\t\t\t\t\t\t\t\t\t\t/* j */\n\tKA_k,\t\t\t\t\t\t\t\t\t\t\t/* k */\n\tKA_l,\t\t\t\t\t\t\t\t\t\t\t/* l */\n\tKA_m,\t\t\t\t\t\t\t\t\t\t\t/* m */\n\tKA_n,\t\t\t\t\t\t\t\t\t\t\t/* n */\n\tKA_o,\t\t\t\t\t\t\t\t\t\t\t/* o */\n\n\tKA_p,\t\t\t\t\t\t\t\t\t\t\t/* p */\n\tKA_q,\t\t\t\t\t\t\t\t\t\t\t/* q */\n\tKA_r,\t\t\t\t\t\t\t\t\t\t\t/* r */\n\tKA_s,\t\t\t\t\t\t\t\t\t\t\t/* s */\n\tKA_t,\t\t\t\t\t\t\t\t\t\t\t/* t */\n\tKA_u,\t\t\t\t\t\t\t\t\t\t\t/* u */\n\tKA_v,\t\t\t\t\t\t\t\t\t\t\t/* v */\n\tKA_w,\t\t\t\t\t\t\t\t\t\t\t/* w */\n\tKA_x,\t\t\t\t\t\t\t\t\t\t\t/* x */\n\tKA_y,\t\t\t\t\t\t\t\t\t\t\t/* y */\n\tKA_z,\t\t\t\t\t\t\t\t\t\t\t/* z */\n\tKA_LBRACE,\t\t\t\t\t\t\t\t\t/* { */\n\tKA_BAR,\t\t\t\t\t\t\t\t\t\t/* | */\n\tKA_RBRACE,\t\t\t\t\t\t\t\t\t/* ] */\n\tKA_TILDA,\t\t\t\t\t\t\t\t\t/* ~ */\n\n\tKA_ESC \t\t\t\t= VK_ESCAPE,\n\tKA_EXTEND \t\t\t= VK_ESCAPE,\n\tKA_RETURN \t\t\t= VK_RETURN,\n\tKA_BACKSPACE \t\t= VK_BACK,\n\tKA_TAB \t\t\t\t= VK_TAB ,\n\tKA_DELETE\t\t\t= VK_DELETE,\t\t\t\t\t\t\t\t\t/* <DELETE> */\n\tKA_INSERT\t\t\t= VK_INSERT,\t\t\t\t\t\t\t\t\t/* <INSERT> */\n\tKA_PGDN\t\t\t\t= VK_NEXT,\t\t\t\t\t\t\t\t\t\t/* <PAGE DOWN> */\n\tKA_DOWNRIGHT \t\t= VK_NEXT,\n\tKA_DOWN\t\t\t\t= VK_DOWN,\t\t\t\t\t\t\t\t\t\t/* <DOWN ARROW> */\n\tKA_END\t\t\t\t= VK_END,\t\t\t\t\t\t\t\t\t\t/* <END> */\n\tKA_DOWNLEFT \t\t= VK_END,\n\tKA_RIGHT\t\t\t\t= VK_RIGHT,\t\t\t\t\t\t\t\t\t/* <RIGHT ARROW> */\n\tKA_KEYPAD5\t\t\t= VK_SELECT,\t\t\t\t\t\t\t\t\t/* NUMERIC KEY PAD <5> */\n\tKA_LEFT\t\t\t\t= VK_LEFT,\t\t\t\t\t\t\t\t\t\t/* <LEFT ARROW> */\n\tKA_PGUP\t\t\t\t= VK_PRIOR,\t\t\t\t\t\t\t\t\t\t/* <PAGE UP> */\n\tKA_UPRIGHT \t\t\t= VK_PRIOR,\n\tKA_UP\t\t\t\t\t= VK_UP,\t\t\t\t\t\t\t\t\t\t/* <UP ARROW> */\n\tKA_HOME\t\t\t\t= VK_HOME,\t\t\t\t\t\t\t\t\t\t/* <HOME> */\n\tKA_UPLEFT \t\t\t= VK_HOME,\n\tKA_F12\t\t\t\t= VK_F12,\n\tKA_F11\t\t\t\t= VK_F11,\n\tKA_F10\t\t\t\t= VK_F10,\n\tKA_F9 \t\t\t\t= VK_F9,\n\tKA_F8\t\t\t\t\t= VK_F8,\n\tKA_F7\t\t\t\t\t= VK_F7,\n\tKA_F6\t\t\t\t\t= VK_F6,\n\tKA_F5\t\t\t\t\t= VK_F5,\n\tKA_F4\t\t\t\t\t= VK_F4,\n\tKA_F3\t\t\t\t\t= VK_F3,\n\tKA_F2\t\t\t\t\t= VK_F2,\n\tKA_F1\t\t\t\t\t= VK_F1,\n\tKA_LMOUSE \t \t\t= VK_LBUTTON,\n\tKA_RMOUSE \t \t\t= VK_RBUTTON,\n\n\tKA_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKA_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKA_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKA_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n};\n\n\ntypedef enum KeyNumType {\n\tKN_NONE\t\t\t\t= 0,\n\n\tKN_0 \t\t\t\t\t= VK_0,\n\tKN_1 \t\t\t\t\t= VK_1,\n\tKN_2 \t\t\t\t\t= VK_2,\n\tKN_3 \t\t\t\t\t= VK_3,\n\tKN_4 \t\t\t\t\t= VK_4,\n\tKN_5 \t\t\t\t\t= VK_5,\n\tKN_6 \t\t\t\t\t= VK_6,\n\tKN_7 \t\t\t\t\t= VK_7,\n\tKN_8 \t\t\t\t\t= VK_8,\n\tKN_9 \t\t\t\t\t= VK_9,\n\tKN_A \t\t\t\t\t= VK_A,\n\tKN_B \t\t\t\t\t= VK_B,\n\tKN_BACKSLASH\t\t= VK_NONE_DC,\n\tKN_BACKSPACE\t\t= VK_BACK,\n\tKN_C \t\t\t\t\t= VK_C,\n\tKN_CAPSLOCK\t\t\t= VK_CAPITAL,\n\tKN_CENTER\t\t\t= VK_CLEAR,\n\tKN_COMMA \t\t\t= VK_NONE_BC,\n\tKN_D \t\t\t\t\t= VK_D,\n\tKN_DELETE\t\t\t= VK_DELETE,\n\tKN_DOWN\t\t\t\t= VK_DOWN,\n\tKN_DOWNLEFT\t\t\t= VK_END,\n\tKN_DOWNRIGHT\t\t= VK_NEXT,\n\tKN_E \t\t\t\t\t= VK_E,\n\tKN_END\t\t\t\t= VK_END,\n\tKN_EQUAL \t\t\t= VK_NONE_BB,\n\tKN_ESC\t\t\t\t= VK_ESCAPE,\n\tKN_E_DELETE \t\t= VK_DELETE,\n\tKN_E_DOWN\t\t\t= VK_NUMPAD2,\n\tKN_E_END\t\t\t\t= VK_NUMPAD1,\n\tKN_E_HOME\t\t\t= VK_NUMPAD7,\n\tKN_E_INSERT\t\t\t= VK_INSERT,\n\tKN_E_LEFT\t\t\t= VK_NUMPAD4,\n\tKN_E_PGDN   \t\t= VK_NUMPAD3,\n\tKN_E_PGUP\t\t\t= VK_NUMPAD9,\n\tKN_E_RIGHT\t\t\t= VK_NUMPAD6,\n\tKN_E_UP\t\t\t\t= VK_NUMPAD8,\n\tKN_F \t\t\t\t\t= VK_F,\n\tKN_F1\t\t\t\t\t= VK_F1,\n\tKN_F10\t\t\t\t= VK_F10,\n\tKN_F11\t\t\t\t= VK_F11,\n\tKN_F12\t\t\t\t= VK_F12,\n\tKN_F2\t\t\t\t\t= VK_F2,\n\tKN_F3\t\t\t\t\t= VK_F3,\n\tKN_F4\t\t\t\t\t= VK_F4,\n\tKN_F5\t\t\t\t\t= VK_F5,\n\tKN_F6\t\t\t\t\t= VK_F6,\n\tKN_F7\t\t\t\t\t= VK_F7,\n\tKN_F8\t\t\t\t\t= VK_F8,\n\tKN_F9\t\t\t\t\t= VK_F9,\n\tKN_G \t\t\t\t\t= VK_G,\n\tKN_GRAVE \t\t\t= VK_NONE_C0,\n\tKN_H \t\t\t\t\t= VK_H,\n\tKN_HOME\t\t\t\t= VK_HOME,\n\tKN_I \t\t\t\t\t= VK_I,\n\tKN_INSERT\t\t\t= VK_INSERT,\n\tKN_J \t\t\t\t\t= VK_J,\n\tKN_K \t\t\t\t\t= VK_K,\n\tKN_KEYPAD_ASTERISK= VK_MULTIPLY,\n\tKN_KEYPAD_MINUS\t= VK_SUBTRACT,\n\tKN_KEYPAD_PLUS\t\t= VK_ADD,\n\tKN_KEYPAD_RETURN\t= VK_RETURN,\n\tKN_KEYPAD_SLASH\t= VK_DIVIDE,\n\tKN_L \t\t\t\t\t= VK_L,\n\tKN_LALT\t\t\t\t= VK_MENU,\n\tKN_LBRACKET\t\t\t= VK_NONE_DB,\n\tKN_LCTRL\t\t\t\t= VK_CONTROL,\n\tKN_LEFT\t\t\t\t= VK_LEFT,\n\tKN_LMOUSE\t\t\t= VK_LBUTTON,\n\tKN_LSHIFT\t\t\t= VK_SHIFT,\n\tKN_M \t\t\t\t\t= VK_M,\n\tKN_MINUS \t\t\t= VK_NONE_BD,\n\tKN_N \t\t\t\t\t= VK_N,\n\tKN_NUMLOCK\t\t\t= VK_NUMLOCK,\n\tKN_O \t\t\t\t\t= VK_O,\n\tKN_P \t\t\t\t\t= VK_P,\n\tKN_PAUSE\t\t\t\t= VK_PAUSE,\n\tKN_PERIOD \t\t\t= VK_NONE_BE,\n\tKN_PGDN\t\t\t\t= VK_NEXT,\n\tKN_PGUP\t\t\t\t= VK_PRIOR,\n\tKN_PRNTSCRN\t\t\t= VK_PRINT,\n\tKN_Q \t\t\t\t\t= VK_Q,\n\tKN_R \t\t\t\t\t= VK_R,\n\tKN_RALT\t\t\t\t= VK_MENU,\n\tKN_RBRACKET\t\t\t= VK_NONE_DD,\n\tKN_RCTRL\t\t\t\t= VK_CONTROL,\n\tKN_RETURN \t\t\t= VK_RETURN,\n\tKN_RIGHT\t\t\t\t= VK_RIGHT,\n\tKN_RMOUSE\t\t\t= VK_RBUTTON,\n\tKN_RSHIFT\t\t\t= VK_SHIFT,\n\tKN_S \t\t\t\t\t= VK_S,\n\tKN_SCROLLLOCK\t\t= VK_SCROLL,\n\tKN_SEMICOLON \t\t= VK_NONE_BA,\n\tKN_SLASH \t\t\t= VK_NONE_BF,\n\tKN_SPACE \t\t\t= VK_SPACE,\n\tKN_SQUOTE \t\t\t= VK_NONE_DE,\n\tKN_T \t\t\t\t\t= VK_T,\n\tKN_TAB\t\t\t\t= VK_TAB,\n\tKN_U \t\t\t\t\t= VK_U,\n\tKN_UP\t\t\t\t\t= VK_UP,\n\tKN_UPLEFT\t\t\t= VK_HOME,\n\tKN_UPRIGHT\t\t\t= VK_PRIOR,\n\tKN_V \t\t\t\t\t= VK_V,\n\tKN_W \t\t\t\t\t= VK_W,\n\tKN_X \t\t\t\t\t= VK_X,\n\tKN_Y \t\t\t\t\t= VK_Y,\n\tKN_Z \t\t\t\t\t= VK_Z,\n\n\tKN_SHIFT_BIT \t\t= WWKEY_SHIFT_BIT,\n\tKN_CTRL_BIT  \t\t= WWKEY_CTRL_BIT,\n\tKN_ALT_BIT   \t\t= WWKEY_ALT_BIT,\n\tKN_RLSE_BIT  \t\t= WWKEY_RLS_BIT,\n\tKN_BUTTON    \t\t= WWKEY_BTN_BIT,\n} KeyNumType;\n\n\nextern WWKeyboardClass *_Kbd;\n\n#endif\n"
  },
  {
    "path": "REDALERT/KEYFBUFF.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : David R. Dettmer                         *\n;*                                                                         *\n;*                   Start Date : March 3, 1995                            *\n;*                                                                         *\n;*                  Last Update :                                          *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Buffer_Frame_To_Page -- Copies a linear buffer to a virtual viewport  *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;********************** Model & Processor Directives ***********************\n;IDEAL\n;P386\n;MODEL USE32 FLAT\n;jumps\n\n.MODEL FLAT\n;.386\n\n;******************************** Includes *********************************\n;INCLUDE \"gbuffer.inc\"\n;include\t\"profile.inc\"\n\nOPTIMAL_BYTE_COPY\tequ\t14\n\nGraphicViewPort STRUCT \nGVPOffset\t\tDD\t\t?\t\t; offset to virtual viewport\nGVPWidth\t\t\tDD\t\t?\t\t; width of virtual viewport\nGVPHeight\t\tDD\t\t?\t\t; height of virtual viewport\nGVPXAdd\t\t\tDD\t\t?\t\t; x mod to get to next line\nGVPXPos\t\t\tDD\t\t?\t\t; x pos relative to Graphic Buff\nGVPYPos\t\t\tDD\t\t?\t\t; y pos relative to Graphic Buff\nGVPPitch\t\tdd\t\t?\t\t; modulo of graphic view port\nGVPBuffPtr\t\tDD\t\t?\t\t; ptr to associated Graphic Buff\nGraphicViewPort ENDS\n\n;******************************** Equates **********************************\n\nTRUE\tequ\t1\t\t\t; Boolean 'true' value\nFALSE\tequ\t0\t\t\t; Boolean 'false' value\n\n;*=========================================================================*/\n;* The following are defines used to control what functions are linked\t   *\n;* in for Buffer_Frame_To_Page.\t\t\t\t\t\t   *\n;*=========================================================================*/\n;USE_NORMAL\t\tEQU\tTRUE\n;USE_HORZ_REV \t\tEQU\tTRUE\n;USE_VERT_REV \t\tEQU\tTRUE\n;USE_SCALING \t\tEQU\tTRUE\n\n\nFLAG_NORMAL\t\tEQU\t0\nFLAG_TRANS\t\tEQU\t1\nFLAG_GHOST\t\tEQU\t2\nFLAG_FADING\t\tEQU\t4\nFLAG_PREDATOR\t\tEQU\t8\n\nFLAG_MASK\t\tEQU\t0Fh\n\n\nSHAPE_NORMAL \t\tEQU\t0000h\t\t; Standard shape\n;SHAPE_HORZ_REV \t\tEQU\t0001h\t\t; Flipped horizontally\n;SHAPE_VERT_REV \t\tEQU\t0002h\t\t; Flipped vertically\n;SHAPE_SCALING \t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n;SHAPE_VIEWPORT_REL \tEQU\t0010h\t\t; Coords are window-relative\n;SHAPE_WIN_REL \t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER \t\tEQU\t0020h\t\t; Coords are based on shape's center pt\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\nSHAPE_FADING \t\tEQU\t0100h\t\t; Fading effect (VOID * fading_table,\n\t\t\t\t\t\t;   WORD fading_num)\nSHAPE_PREDATOR \t\tEQU\t0200h\t\t; Transparent warping effect\n;SHAPE_COMPACT \t\tEQU\t0400h\t\t; Never use this bit\n;SHAPE_PRIORITY \t\tEQU\t0800h\t\t; Use priority system when drawing\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Shape is drawn ghosted\n;SHAPE_SHADOW\t\tEQU\t2000h\nSHAPE_PARTIAL  \t\tEQU\t4000h\n;SHAPE_COLOR \t\tEQU\t8000h\t\t; Remap the shape's colors\n\t\t\t\t\t\t;   (VOID * color_table)\n\n\n;\n;.......................... Shadow Effect ..................................\n;\nSHADOW_COL\t\tEQU\t00FFh\t; magic number for shadows\n\n;......................... Priority System .................................\n;\nCLEAR_UNUSED_BITS  \tEQU\t0007h\t; and with 0000-0111 to clear\n\t\t\t\t\t;  non-walkable high bit and\n\t\t\t\t\t;  scaling id bits\nNON_WALKABLE_BIT  \tEQU\t0080h\t; and with 1000-0000 to clear all\n\t\t\t\t\t;  but non-walkable bit\n;\n;......................... Predator Effect .................................\n;\n;PRED_MASK\t\tEQU\t0007h\t; mask used for predator pixel puts\nPRED_MASK\t\tEQU\t000Eh\t; mask used for predator pixel puts\n\n\n;---------------------------------------------------------------------------\n;\n; Use a macro to make code a little cleaner.\n; The parameter varname is optional.\n; Syntax to use macro is :\n;  WANT equ expression\n;  USE func [,varname]\n; If the 'varname' is defined, a table declaration is created like:\n;\tGLOBAL\tTableName:DWORD\n; Then, the table entry is created:\n;  If WANT is true, the table entry is created for the given function:\n;\tvarname\tDD\tfunc\n;  If WANT is not TRUE, a Not_Supported entry is put in the table:\n;\tvarname\tDD\tNot_Supported\n; The resulting tables look like:\n;\n;\tGLOBAL\tExampTable:DWORD\n;\tExampTable\tDD\troutine1\n;\t\t\tDD\troutine2\n;\t\t\tDD\troutine3\n;\t\t\t...\n; Thus, each table is an array of function pointers.\n;\n;---------------------------------------------------------------------------\nUSE MACRO  func, varname\n IF WANT\n  varname \tDD\tfunc\n ELSE\n  varname\tDD\tNot_Supported\n ENDIF\nENDM\n\nprologue\tmacro\nendm\n\n\n\nepilogue macro \nendm\n\n\n; IFNB <varname>\n;\tGLOBAL\tvarname:DWORD\n; ENDIF\n\n;---------------------------------------------------------------------------\n\n\n.DATA\n\n;---------------------------------------------------------------------------\n; Predator effect variables\n;---------------------------------------------------------------------------\n; make table for negative offset and use the used space for other variables\n\nBFPredNegTable\tDW\t-1, -3, -2, -5, -2, -4, -3, -1\n\t; 8 words below calculated\n\t\tDW\t0, 0, 0, 0, 0, 0, 0, 0\t; index ffffff00\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff10\nBFPredOffset\tDD\t0, 0, 0, 0\t\t; index ffffff20\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff30\n\t; partially faded predator effect value\nBFPartialPred\tDD\t0, 0, 0, 0\t\t; index ffffff40\nBFPartialCount\tDD\t0, 0, 0, 0\t\t; index ffffff50\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff60\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff70\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff80\n\t\tDD\t0, 0, 0, 0\t\t; index ffffff90\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffa0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffb0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffc0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffd0\n\t\tDD\t0, 0, 0, 0\t\t; index ffffffe0\n\t\tDD\t0, 0, 0, 0\t\t; index fffffff0\nBFPredTable\tDW\t1, 3, 2, 5, 2, 3, 4, 1\n;BFPredTable\tDB\t1, 3, 2, 5, 4, 3, 2, 1\n\n\n\n\n\n\n\t\textern\tC BigShapeBufferStart:dword\n\t\textern\tC UseBigShapeBuffer:dword\n\t\textern\tC TheaterShapeBufferStart:dword\n\t\textern\tC IsTheaterShape:dword\n\t\t;extern\tC Single_Line_Trans_Entry:near\n\t\t;extern\tC Next_Line:near\n\t\textern\tC MMX_Done:near\n\t\textern\tC MMXAvailable:dword\n\t\t;extern\tC EndNewShapeJumpTable:byte\n\t\t;extern\tC NewShapeJumpTable:dword\n\n\n;**********************************************************************************\n;\n; Jump tables for new line header system\n;\n; Each line of shape data now has a header byte which describes the data on the line.\n;\n\n;\n; Header byte control bits\n;\nBLIT_TRANSPARENT\t=1\nBLIT_GHOST\t\t=2\nBLIT_FADING\t\t=4\nBLIT_PREDATOR\t\t=8\nBLIT_SKIP\t\t=16\nBLIT_ALL\t\t=BLIT_TRANSPARENT or BLIT_GHOST or BLIT_FADING or BLIT_PREDATOR or BLIT_SKIP\n\n\nShapeHeaderType\tSTRUCT\n\n\t\tdraw_flags\tdd\t?\n\t\tshape_data\tdd\t?\n\t\tshape_buffer\tdd\t?\n\nShapeHeaderType\tENDS\n\n\n\n;\n; Global definitions for routines that draw a single line of a shape\n;\n\t\t;extern\tShort_Single_Line_Copy:near\n\t\t;extern\tSingle_Line_Trans:near\n\t\t;extern\tSingle_Line_Ghost:near\n\t\t;extern\tSingle_Line_Ghost_Trans:near\n\t\t;extern\tSingle_Line_Fading:near\n\t\t;extern\tSingle_Line_Fading_Trans:near\n\t\t;extern\tSingle_Line_Ghost_Fading:near\n\t\t;extern\tSingle_Line_Ghost_Fading_Trans:near\n\t\t;extern\tSingle_Line_Predator:near\n\t\t;extern\tSingle_Line_Predator_Trans:near\n\t\t;extern\tSingle_Line_Predator_Ghost:near\n\t\t;extern\tSingle_Line_Predator_Ghost_Trans:near\n\t\t;extern\tSingle_Line_Predator_Fading:near\n\t\t;extern\tSingle_Line_Predator_Fading_Trans:near\n\t\t;extern\tSingle_Line_Predator_Ghost_Fading:near\n\t\t;extern\tSingle_Line_Predator_Ghost_Fading_Trans:near\n\t\t;extern\tSingle_Line_Skip:near\n\n\t\t;extern\tSingle_Line_Single_Fade:near\n\t\t;extern\tSingle_Line_Single_Fade_Trans:near\n\n;externdef AllFlagsJumpTable:dword\n;\nexterndef NewShapeJumpTable:dword\nexterndef EndNewShapeJumpTable:byte\nexterndef CriticalFadeRedirections:dword\n;externdef BufferFrameTable:dword\n\n;externdef CriticalFadeRedirections:dword\n;externdef CriticalFadeRedirections:dword\n;externdef CriticalFadeRedirections:dword\n;externdef BF_Copy:far ptr\n;externdef BF_Trans:dword\n;externdef BF_Ghost:dword\n;externdef BF_Ghost_Trans:dword\n;externdef BF_Fading:dword\n;externdef BF_Fading_Trans:dword\n;externdef BF_Ghost_Fading:dword\n;externdef BF_Ghost_Fading_Trans:dword\n;externdef BF_Predator:dword\n;externdef BF_Predator_Trans:dword\n;externdef BF_Predator_Ghost:dword\n;externdef BF_Predator_Ghost_Trans:dword\n;externdef BF_Predator_Fading:dword\n;externdef BF_Predator_Fading_Trans:dword\n;externdef BF_Predator_Ghost_Fading:dword\n;externdef BF_Predator_Ghost_Fading_Trans:dword\n\nexterndef\tC Single_Line_Trans:near\nexterndef\tC Single_Line_Trans_Entry:near\nexterndef\tC Next_Line:near\n\n\n.CODE\n\n\n;---------------------------------------------------------------------------\n; Code Segment Tables:\n; This code uses the USE macro to set up tables of function addresses.\n; The tables have the following format:\n; Tables defined are:\n;\tBufferFrameTable\n;---------------------------------------------------------------------------\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Copy, BufferFrameTable\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Ghost_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Fading_Trans\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading\n\nWANT\tequ \t<TRUE>\nUSE\tBF_Predator_Ghost_Fading_Trans\n\n\n\n.DATA\n\n;NewShapeJumpTable label\tnear ptr\t\tdword\n\n;\n; Jumptable for shape line drawing with no flags set\n;\n\nNewShapeJumpTable\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n;CriticalFadeRedirections label\t\t dword\nCriticalFadeRedirections\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with transparent flags set\n;\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and transparent flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with fading flag set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and transparent flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n;\n; Jumptable for shape line drawing routines with fading, transparent and ghost flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n\n;\n; Jumptable for shape line drawing with predator flag set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with transparent and predator flags set\n;\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with ghost and transparent and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with fading and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and transparent and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Fading\n\t\tdd\tSingle_Line_Fading_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n;\n; Jumptable for shape line drawing routines with fading and ghost and predator flags set\n;\n\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\n\n\n\n\n\n;\n; Jumptable for shape line drawing routines with all flags set\n;\n\nAllFlagsJumpTable label dword\n\t\tdd\tShort_Single_Line_Copy\n\t\tdd\tSingle_Line_Trans\n\t\tdd\tSingle_Line_Ghost\n\t\tdd\tSingle_Line_Ghost_Trans\n\t\tdd\tSingle_Line_Single_Fade\n\t\tdd\tSingle_Line_Single_Fade_Trans\n\t\tdd\tSingle_Line_Ghost_Fading\n\t\tdd\tSingle_Line_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Predator\n\t\tdd\tSingle_Line_Predator_Trans\n\t\tdd\tSingle_Line_Predator_Ghost\n\t\tdd\tSingle_Line_Predator_Ghost_Trans\n\t\tdd\tSingle_Line_Predator_Fading\n\t\tdd\tSingle_Line_Predator_Fading_Trans\n\t\tdd\tSingle_Line_Predator_Ghost_Fading\n\t\tdd\tSingle_Line_Predator_Ghost_Fading_Trans\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\t\tdd\tSingle_Line_Skip\n\n\nEndNewShapeJumpTable\tdb 0\n\n.CODE\n\n\n\n;---------------------------------------------------------------------------\n\n\n\n\n;*********************************************************************************************\n;* Set_Shape_Header -- create the line header bytes for a shape                              *\n;*                                                                                           *\n;* INPUT:\tShape width                                                                  *\n;*              Shape height                                                                 *\n;*              ptr to raw shape data                                                        *\n;*              ptr to shape headers                                                         *\n;*              shape flags                                                                  *\n;*              ptr to translucency table                                                    *\n;*              IsTranslucent                                                                *\n;*                                                                                           *\n;* OUTPUT:      none                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   11/29/95 10:09AM ST : Created.                                                          *\n;*===========================================================================================*\n\n\t\tSetup_Shape_Header proc\tC pixel_width:DWORD, pixel_height:DWORD, src:DWORD, headers:DWORD, flags:DWORD, Translucent:DWORD, IsTranslucent:DWORD\n\n\t\t;ARG\tpixel_width \t:DWORD\t\t; width of rectangle to blit\n\t\t;ARG\tpixel_height\t:DWORD\t\t; height of rectangle to blit\n\t\t;ARG  \tsrc         \t:DWORD\t\t; this is a member function\n\t\t;ARG\theaders\t    \t:DWORD\n\t\t;ARG\tflags\t\t:DWORD\n\t\t;ARG\tTranslucent\t:DWORD\n\t\t;ARG\tIsTranslucent\t:DWORD\n\t\tLOCAL\ttrans_count\t:DWORD\n\n\t\tpushad\n\n\n\t\tmov\tesi,[src]\t\t;ptr to raw shape data\n\t\tmov\tedi,[headers]\t\t;ptr to headers we are going to set up\n\t\tmov\teax,[flags]\n\t\tand\teax,SHAPE_TRANS or SHAPE_FADING or SHAPE_PREDATOR or SHAPE_GHOST\n\t\tmov\t[edi].ShapeHeaderType.draw_flags,eax \t;save old flags in header\n\t\tadd\tedi,size ShapeHeaderType\n\t\tmov\tedx,[pixel_height]\t;number of shape lines to scan\n\nouter_loop:\tmov\tecx,[pixel_width]\t;number of pixels in shape line\n\t\txor\tbl,bl\t\t\t;flag the we dont know anything about this line yet\n\t\tmov\t[trans_count],0\t\t;we havnt scanned any transparent pixels yet\n\n;\n; Scan one shape line to see what kind of data it contains\n;\ninner_loop:\txor\teax,eax\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\n;\n; Check for transparent pixel\n;\n\t\ttest\tal,al\n\t\tjnz\tnot_transp\n\t\ttest\t[flags],SHAPE_TRANS\n\t\tjz\tnot_transp\n\t\tor\tbl,BLIT_TRANSPARENT\t;flag that pixel is transparent\n\t\tinc\t[trans_count]\t\t;keep count of the number of transparent pixels on the line\n\t\tjmp\tend_lp\n\n;\n; Check for predator effect on this line\n;\nnot_transp:\ttest\t[flags],SHAPE_PREDATOR\n\t\tjz\tnot_pred\n\t\tor\tbl,BLIT_PREDATOR\n\n;\n; Check for ghost effects\n;\nnot_pred:\ttest\t[flags],SHAPE_GHOST\n\t\tjz\tnot_ghost\n\t\tpush\tedi\n\t\tmov\tedi,[IsTranslucent]\n\t\tcmp\tbyte ptr [edi+eax],-1\n\t\tpop\tedi\n\t\tjz\tnot_ghost\n\t\tor\tbl,BLIT_GHOST\n\n;\n; Check if fading is required\n;\nnot_ghost:\ttest\t[flags],SHAPE_FADING\n\t\tjz\tend_lp\n\t\tor\tbl,BLIT_FADING\n\nend_lp:       dec\tecx\n\t\tjnz\tinner_loop\n\n\n;\n; Interpret the info we have collected and decide which routine will be\n; used to draw this line\n;\n\t\txor\tbh,bh\n\n\t\ttest\tbl,BLIT_TRANSPARENT\n\t\tjz\tno_transparencies\n\t\tor\tbh,BLIT_TRANSPARENT\n\t\tmov\tecx,[pixel_width]\n\t\tcmp\tecx,[trans_count]\n\t\tjnz\tnot_all_trans\n\n; all pixels in the line were transparent so we dont need to draw it at all\n\t\tmov\tbh,BLIT_SKIP\n\t\tjmp\tgot_line_type\n\nnot_all_trans:\nno_transparencies:\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_PREDATOR\n\t\tor\tbh,al\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_GHOST\n\t\tor\tbh,al\n\t\tmov\tal,bl\n\t\tand\tal,BLIT_FADING\n\t\tor\tbh,al\n\n;\n; Save the line header and do the next line\n;\ngot_line_type:mov\t[edi],bh\n\t\tinc\tedi\n\n\t\tdec\tedx\n\t\tjnz\touter_loop\n\n\n\t\tpopad\n\t\tret\n\nSetup_Shape_Header\tendp\t\n\n\n\n\n;**************************************************************\n;\n; Macro to fetch the header of the next line and jump to the appropriate routine\n;\nnext_line\tmacro\n\n\t\tadd\tedi , [ dest_adjust_width ]\t;add in dest modulo\n\t\tdec\tedx\t\t\t\t;line counter\n\t\tjz\treal_out\t\t\t;return\n\t\tmov\tecx,[save_ecx]\t\t\t;ecx is pixel count\n\t\tmov\teax,[header_pointer]\t\t;ptr to next header byte\n\t\tmov\tal,[eax]\n\t\tinc\t[header_pointer]\n\t\tand\teax,BLIT_ALL\t\t\t;Make sure we dont jump to some spurious address\n\t\t\t\t\t\t\t; if the header is wrong then its better to draw with the wrong\n\t\t\t\t\t\t\t; shape routine than to die\n\t\tshl\teax,2\n\t\tadd\teax,[ShapeJumpTableAddress]\t;get the address to jump to\n\t\tjmp\tdword ptr [eax]\t\t\t;do the jump\n\n\t\tendm\n\n\n\n\n\n\n;***************************************************************************\n;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport\t\t   *\n;*                                                                         *\n;* INPUT:\tWORD\tx_pixel\t\t- x pixel on viewport to copy from *\n;*\t\tWORD\ty_pixel \t- y pixel on viewport to copy from *\n;*\t\tWORD\tpixel_width\t- the width of copy region\t   *\n;*\t\tWORD\tpixel_height\t- the height of copy region\t   *\n;*\t\tBYTE *\tsrc\t\t- buffer to copy from\t\t   *\n;*\t\tVVPC *  dest\t\t- virtual viewport to copy to\t   *\n;*                                                                         *\n;* OUTPUT:      none                                                       *\n;*                                                                         *\n;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *\n;*\t        the boundaries.  In the event that no adjustment is \t   *\n;*\t        possible this routine will abort.  If the size of the \t   *\n;*\t\tregion to copy exceeds the size passed in for the buffer   *\n;*\t\tthe routine will automatically abort.\t\t\t   *\n;*\t\t\t\t\t\t\t\t\t   *\n;* HISTORY:                                                                *\n;*   06/15/1994 PWG : Created.                                             *\n;*=========================================================================*\nBuffer_Frame_To_Page proc C public USES eax ebx ecx edx esi edi x_pixel:DWORD, y_pixel:DWORD, pixel_width:DWORD, pixel_height:DWORD, src:DWORD, dest:DWORD, flags:DWORD\n\n\t;USES\teax,ebx,ecx,edx,esi,edi\n\n\t;*===================================================================\n\t;* define the arguements that our function takes.\n\t;*===================================================================\n\t;ARG\tx_pixel     :DWORD\t\t; x pixel position in source\n\t;ARG\ty_pixel     :DWORD\t\t; y pixel position in source\n\t;ARG\tpixel_width :DWORD\t\t; width of rectangle to blit\n\t;ARG\tpixel_height:DWORD\t\t; height of rectangle to blit\n\t;ARG    \tsrc         :DWORD\t\t; this is a member function\n\t;ARG\tdest        :DWORD\t\t; what are we blitting to\n\n\t;ARG\tflags       :DWORD\t\t; flags passed\n\n\t;*===================================================================\n\t; Define some locals so that we can handle things quickly\n\t;*===================================================================\n\tLOCAL\tIsTranslucent\t\t:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent\t\t:DWORD\t; ptr to the actual translucent table\n\tLOCAL\tFadingTable\t\t:DWORD\t; extracted fading table pointer\n\tLOCAL\tFadingNum\t\t:DWORD\t; get the number of times to fade\n\n\tLOCAL\tStashECX\t\t:DWORD\t; temp variable for ECX register\n\n\tLOCAL\tjflags\t\t\t:DWORD\t; flags used to goto correct buff frame routine\n\tLOCAL\tBufferFrameRout\t\t:DWORD\t; ptr to the buffer frame routine\n\n\tLOCAL\tjmp_loc\t\t\t:DWORD\t; calculated jump location\n\tLOCAL\tloop_cnt\t\t:DWORD\n\n\tLOCAL \tx1_pixel\t\t:DWORD\n\tLOCAL\ty1_pixel\t\t:DWORD\n\tLOCAL\tscr_x\t\t\t:DWORD\n\tLOCAL\tscr_y\t\t\t:DWORD\n\tLOCAL\tdest_adjust_width\t:DWORD\n\tLOCAL\tscr_adjust_width\t:DWORD\n\tLOCAL\theader_pointer\t\t:DWORD\n\tLOCAL\tuse_old_draw\t\t:DWORD\n\tLOCAL\tsave_ecx\t\t:DWORD\n\tLOCAL\tShapeJumpTableAddress\t:DWORD\n\tLOCAL\tshape_buffer_start\t:DWORD\n\n\tprologue\n\tcmp\t[ src ] , 0\n\tjz\treal_out\n\n\t;\n\t; Save the line attributes pointers and\n\t; Modify the src pointer to point to the actual image\n\t;\n\tcmp\t[UseBigShapeBuffer],0\n\tjz\tdo_args\t\t\t;just use the old shape drawing system\n\n\tmov\tedi,[src]\n\tmov\t[header_pointer],edi\n\n\tmov\teax,[BigShapeBufferStart]\n\tcmp\t[edi].ShapeHeaderType.shape_buffer,0\n\tjz\tis_ordinary_shape\n\tmov\teax,[TheaterShapeBufferStart]\nis_ordinary_shape:\n\tmov\t[shape_buffer_start],eax\n\n\tmov\tedi,[edi].ShapeHeaderType.shape_data\n\tadd\tedi,[shape_buffer_start]\n\tmov\t[src],edi\n\tmov\t[use_old_draw],0\n\n\n\t;====================================================================\n\t; Pull off optional arguments:\n\t; EDI is used as an offset from the 'flags' parameter, to point\n\t; to the optional argument currently being processed.\n\t;====================================================================\ndo_args:\n\tmov\tedi , 4\t \t\t\t; optional params start past flags\n\tmov\t[ jflags ] , 0\t\t\t; clear jump flags\n\ncheck_centering:\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_CENTER\t; does this need to be centered?\n\tje\tcheck_trans\t\t\t; if not the skip over this stuff\n\n\tmov\teax , [ pixel_width ]\n\tmov\tebx , [ pixel_height ]\n\tsar\teax , 1\n\tsar\tebx , 1\n\tsub\t[ x_pixel ] , eax\n\tsub\t[ y_pixel ] , ebx\n\ncheck_trans:\n\ttest\t[ flags ] , SHAPE_TRANS\n\tjz\tcheck_ghost\n\n\tor\t[ jflags ] , FLAG_TRANS\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_GHOST: DWORD is_translucent tbl\n\t;--------------------------------------------------------------------\ncheck_ghost:\n\ttest\t[ flags ] , SHAPE_GHOST\t\t; are we ghosting this shape\n\tjz\tcheck_fading\n\n\tmov\teax , [ flags + edi ]\n\tor\t[ jflags ] , FLAG_GHOST\n\tmov\t[ IsTranslucent ] , eax\t\t; save ptr to is_trans. tbl\n\tadd\teax , 0100h\t\t\t; add 256 for first table\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ Translucent ] , eax\t\t; save ptr to translucent tbl\n\n\n\ncheck_fading:\n\t;______________________________________________________________________\n\t; If this is the first time through for this shape then\n\t; set up the shape header\n\t;______________________________________________________________________\n\tpushad\n\n\tcmp\t[UseBigShapeBuffer],0\n\tjz\tnew_shape\n\n\tmov\tedi,[header_pointer]\n\tcmp\t[edi].ShapeHeaderType.draw_flags,-1\n\tjz\tsetup_headers\n\tmov\teax,[flags]\t\t\t\t\t\t\t ;Redo the shape headers if this shape was\n\tand\teax,SHAPE_TRANS or SHAPE_FADING or SHAPE_PREDATOR or SHAPE_GHOST ;initially set up with different flags\n\tcmp\teax,[edi].ShapeHeaderType.draw_flags\n\tjz\tno_header_setup\nnew_shape:\n\tmov\t[use_old_draw],1\n\tjmp\tno_header_setup\n\nsetup_headers:\n\tpush\t[IsTranslucent]\n\tpush\t[Translucent]\n\tpush\t[flags]\n\tpush\t[header_pointer]\n\tpush\t[src]\n\tpush\t[pixel_height]\n\tpush\t[pixel_width]\n\tcall\tSetup_Shape_Header\n\tadd\tesp,7*4\n\tmov\t[ShapeJumpTableAddress], offset AllFlagsJumpTable\n\tjmp\theaders_set\nno_header_setup:\n\n\txor\teax,eax\n\ttest\t[flags],SHAPE_PREDATOR\n\tjz\tnot_shape_predator\n\tor\tal,BLIT_PREDATOR\n\nnot_shape_predator:\n\ttest\t[flags],SHAPE_FADING\n\tjz\tnot_shape_fading\n\tor\tal,BLIT_FADING\n\nnot_shape_fading:\n\n\ttest\t[flags],SHAPE_TRANS\n\tjz\tnot_shape_transparent\n\tor\tal,BLIT_TRANSPARENT\n\nnot_shape_transparent:\n\n\ttest\t[flags],SHAPE_GHOST\n\tjz\tnot_shape_ghost\n\tor\tal,BLIT_GHOST\n\nnot_shape_ghost:\n\n\t \n      \tshl\teax,7\n       \tadd\teax, offset NewShapeJumpTable\n\tmov\t[ShapeJumpTableAddress],eax\n\t;call\tInit_New_Shape_Jump_Table_Address\n\n\nheaders_set:\n\tpopad\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count\n\t;--------------------------------------------------------------------\n\ttest\t[ flags ] , SHAPE_FADING\t; are we fading this shape\n\tjz\tcheck_predator\n\n\tmov\teax , [ flags + edi ]\n\tmov\t[ FadingTable ] , eax\t\t; save address of fading tbl\n\tmov\teax , [ flags + edi + 4 ]\t; get fade num\n\tor\t[ jflags ] , FLAG_FADING\n\tand\teax , 03fh\t\t\t; no need for more than 63\n\tadd\tedi , 8\t\t\t\t; next argument\n\tcmp\teax , 0\t\t\t\t; check if it's 0\n\tjnz\tset_fading\t\t\t; if not, store fade num\n\n\tand\t[ flags ] , NOT SHAPE_FADING\t; otherwise, don't fade\n\nset_fading:\n\tmov\t[ FadingNum ] , eax\n\n\tmov\tebx,[ShapeJumpTableAddress]\n\tmov\tdword ptr [CriticalFadeRedirections-NewShapeJumpTable+ebx],offset Single_Line_Single_Fade\n\tmov\tdword ptr [CriticalFadeRedirections-NewShapeJumpTable+ebx+4],offset Single_Line_Single_Fade_Trans\n\tcmp\teax,1\n\tjz\tsingle_fade\n\tmov\tdword ptr [CriticalFadeRedirections-NewShapeJumpTable+ebx],offset Single_Line_Fading\n\tmov\tdword ptr [CriticalFadeRedirections-NewShapeJumpTable+ebx+4],offset Single_Line_Fading_Trans\n\nsingle_fade:\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PREDATOR: DWORD init_pred_lookup_offset (0-7)\n\t;--------------------------------------------------------------------\ncheck_predator:\n\ttest\t[ flags ] , SHAPE_PREDATOR\t; is predator effect on\n\tjz\tcheck_partial\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tor\t[ jflags ] , FLAG_PREDATOR\n\tshl\teax , 1\n\tcmp\teax , 0\n\tjge\tcheck_range\n\n\tneg\teax\n\tmov\tebx , -1\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\tmov\tbl , al\n\tmov\teax , ebx\t\t\t; will be ffffff00-ffffff07\n\tjmp\tpred_cont\n\ncheck_range:\n\tand\teax , PRED_MASK\t\t\t; keep entries within bounds\n\npred_cont:\n\tadd\tedi , 4\t\t\t\t; next argument\n\tmov\t[ BFPredOffset ] , eax\n\tmov\t[ BFPartialCount ] , 0\t\t; clear the partial count\n\tmov\t[ BFPartialPred ] , 100h\t; init partial to off\n\npred_neg_init:\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\tmov\tebx, 7 * 2\n\npred_loop:\n\tmovzx\teax , [ WORD PTR BFPredNegTable + ebx ]\n\tadd\teax , [esi].GraphicViewPort.GVPWidth\t; add width\n\tadd\teax , [esi].GraphicViewPort.GVPXAdd\t; add x add\n\tadd\teax , [esi].GraphicViewPort.GVPPitch\t; extra pitch of DD surface\tST - 9/29/95 1:08PM\n\tmov\t[ WORD PTR BFPredNegTable + 16 + ebx ] , ax\n\tdec\tebx\n\tdec\tebx\n\tjge\tpred_loop\n\n\t;--------------------------------------------------------------------\n\t; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)\n\t;--------------------------------------------------------------------\ncheck_partial:\n\ttest\t[ flags ] , SHAPE_PARTIAL\t\t; is this a partial pred?\n\tjz\tsetupfunc\n\n\tmov\teax , [ flags + edi ]\t\t; pull the partial value\n\tadd\tedi , 4\t\t\t\t; next argument\n\tand\teax , 0ffh\t\t\t; make sure 0-255\n\tmov\t[ BFPartialPred ] , eax\t\t; store it off\n\nsetupfunc:\n\tmov\tebx , [ jflags ]\t\t; load flags value\n\tand\tebx , FLAG_MASK\t\t\t; clip high bits\n\tadd\tebx , ebx\t\t\t; mult by 4 to get DWORD offset\n\tadd\tebx , ebx\n\tmov\tebx , dword ptr [ BufferFrameTable + ebx ]\t; get table value\n\tmov\tdword ptr [ BufferFrameRout ] , ebx\t\t; store it in the function pointer\n\n; Clip dest Rectangle against source Window boundaries.\n\n\tmov\t[ scr_x ] , 0\n\tmov\t[ scr_y ] , 0\n\tmov  \tesi , [ dest ]\t    ; get ptr to dest\n\txor \tecx , ecx\n\txor \tedx , edx\n\tmov\tedi , [esi].GraphicViewPort.GVPWidth  ; get width into register\n\tmov\tebx , [ x_pixel ]\n\tmov\teax , [ x_pixel ]\n\tadd\tebx , [ pixel_width ]\n\tshld\tecx , eax , 1\n\tmov\t[ x1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\tmov\tedi,[esi].GraphicViewPort.GVPHeight ; get height into register\n\tmov\tebx , [ y_pixel ]\n\tmov\teax , [ y_pixel ]\n\tadd\tebx , [ pixel_height ]\n\tshld\tecx , eax , 1\n\tmov\t[ y1_pixel ] , ebx\n\tinc\tedi\n\tshld\tedx , ebx , 1\n\tsub\teax , edi\n\tsub\tebx , edi\n\tshld\tecx , eax , 1\n\tshld\tedx , ebx , 1\n\n\txor\tcl , 5\n\txor\tdl , 5\n\tmov\tal , cl\n\ttest\tdl , cl\n\tjnz\treal_out\n\n\tor\tal , dl\n\tjz\tdo_blit\n\n\tmov\t[use_old_draw],1\n\ttest\tcl , 1000b\n\tjz\tdest_left_ok\n\n\tmov\teax , [ x_pixel ]\n\tneg\teax\n\tmov\t[ x_pixel ] , 0\n\tmov\t[ scr_x ] , eax\n\ndest_left_ok:\n\ttest\tcl , 0010b\n\tjz\tdest_bottom_ok\n\n\tmov\teax , [ y_pixel ]\n\tneg\teax\n\tmov\t[ y_pixel ] , 0\n\tmov\t[ scr_y ] , eax\n\ndest_bottom_ok:\n\ttest\tdl , 0100b\n\tjz\tdest_right_ok\n\n\tmov\teax , [esi].GraphicViewPort.GVPWidth  ; get width into register\n\tmov\t[ x1_pixel ] , eax\n\ndest_right_ok:\n\ttest\tdl , 0001b\n\tjz\tdo_blit\n\n\tmov\teax , [esi].GraphicViewPort.GVPHeight  ; get width into register\n\tmov\t[ y1_pixel ] , eax\n\ndo_blit:\n\tcld\n\tmov\teax , [esi].GraphicViewPort.GVPXAdd\n\tadd\teax , [esi].GraphicViewPort.GVPPitch\n\tadd\teax , [esi].GraphicViewPort.GVPWidth\n\tmov\tedi , [esi].GraphicViewPort.GVPOffset\n\n\tmov\tecx , eax\n\tmul\t[ y_pixel ]\n\tadd\tedi , [ x_pixel ]\n\tadd\tedi , eax\n\n\tadd\tecx , [ x_pixel ]\n\tsub\tecx , [ x1_pixel ]\n\tmov\t[ dest_adjust_width ] , ecx\n\n\tmov\tesi , [ src ]\n\tmov\teax , [ pixel_width ]\n\tsub\teax , [ x1_pixel ]\n\tadd\teax , [ x_pixel ]\n\tmov\t[ scr_adjust_width ] , eax\n\n\tmov\teax , [ scr_y ]\n\tmul\t[ pixel_width ]\n\tadd\teax , [ scr_x ]\n\tadd\tesi , eax\n\n;\n; If the shape needs to be clipped then we cant handle it with the new header systen\n; so draw it with the old shape drawer\n;\n\tcmp\t[use_old_draw],0\n\tjnz\tuse_old_stuff\n\n\tadd\t[header_pointer],size ShapeHeaderType\n\tmov\tedx,[pixel_height]\n\tmov\tecx,[pixel_width]\n\tmov\teax,[header_pointer]\n\tmov\tal,[eax]\n\tmov\t[save_ecx],ecx\n\tinc\t[header_pointer]\n\tand\teax,BLIT_ALL\n\tshl\teax,2\n\tadd\teax,[ShapeJumpTableAddress]\n\tjmp\tdword ptr [eax]\n\n\nuse_old_stuff:\n\tmov\tedx , [ y1_pixel ]\n\tmov\teax , [ x1_pixel ]\n\n\tsub\tedx , [ y_pixel ]\n\tjle\treal_out\n\n\tsub\teax , [ x_pixel ]\n\tjle\treal_out\n\n\tjmp\t[ BufferFrameRout ]\t; buffer frame to viewport routine\n\nreal_out:\n\n\tcmp\t[MMXAvailable],0\n\tjz\tno_mmx_cleanup\n\tcall\tMMX_Done\n\nno_mmx_cleanup:\n\tepilogue\n\n\tret\n\n\n; ********************************************************************\n; Forward bitblit only\n; the inner loop is so efficient that\n; the optimal consept no longer apply because\n; the optimal byte have to by a number greather than 9 bytes\n; ********************************************************************\n;extern\tBF_Copy:near\n\nBF_Copy:\n\tprologue\n\n\tcmp\teax , 10\n\tjl\tforward_loop_bytes\n\nforward_loop_dword:\n\tmov\tecx , edi\n\tmov\tebx , eax\n\tneg\tecx\n\tand\tecx , 3\n\tsub\tebx , ecx\n\trep\tmovsb\n\tmov\tecx , ebx\n\tshr\tecx , 2\n\trep\tmovsd\n\tmov\tecx , ebx\n\tand\tecx , 3\n\trep\tmovsb\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tforward_loop_dword\n\n\tret\n\nforward_loop_bytes:\n\tmov\tecx , eax\n\trep\tmovsb\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\t\t\t\t\t; decrement the height\n\tjnz\tforward_loop_bytes\n\t\n\tepilogue\n\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;\t\tsegment code page public use32 'code'\t; Need stricter segment alignment\n\t\t\t\t\t\t\t; for pentium optimisations\n\n\n;\n; Expand the 'next_line' macro so we can jump to it\n;\n;\n;  ST - 12/20/2018 3:48PM\nNext_Line::\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Trans::\n\t\tprologue\n\nSingle_Line_Trans_Entry::\n\nslt_mask_map_lp:\t\t\t\t; Pentium pipeline usage\n\t\t\t\t\t\t;Pipe\tCycles\n\t\tmov\tal,[esi]\t\t;U\t1\n\t\tinc\tesi\t\t\t;Vee\t1\n\n\t\ttest\tal,al\t\t\t;U\t1\n\t\tjz\tslt_skip\t\t;Vee\t1/5\n\nslt_not_trans:mov\t[edi],al\t\t;u \t1\n\n\t\tinc\tedi\t\t\t;vee\t1\n\t\tdec\tecx\t\t\t;u\t1\n\n\t\tjnz\tslt_mask_map_lp\t;vee  (maybe)\t1\n\nslt_end_line:\tepilogue\n\t\tnext_line\n\n\t\t;align\t32\n\nslt_skip:\tinc\tedi\n\t\tdec\tecx\n\t\tjz\tslt_skip_end_line\n\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslt_skip2\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\tslt_mask_map_lp\n\n\t\tepilogue\n\t\tnext_line\n\n\t\t;align\t32\n\nslt_skip2:\tinc\tedi\n\t\tdec\tecx\n\t\tjz\tslt_end_line\n\n;\n; If we have hit two transparent pixels in a row then we go into\n; the transparent optimised bit\n;\nslt_round_again:\n\trept\t64\n\t\tmov\tal,[esi]   ;\t;pipe 1\n\t\tinc\tesi\t   ;1\t;pipe 2\n\t\ttest\tal,al\t   ;\t;pipe 1\n\t\tjnz\tslt_not_trans;pipe 2 (not pairable in 1)\n\t\t\t\t   ;2\n\t\tinc\tedi\t   ;\t;pipe 1\n\t\tdec\tecx\t   ;3\t;pipe 2\n\t\tjz\tslt_end_line ;4\t;pipe 1 (not pairable)\n\tendm\t\t\t   ; best case is 4 cycles per iteration\n\t\tjmp\tslt_round_again\n\n\n\nslt_skip_end_line:\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with no transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n; We have to align the destination for cards that dont bankswitch correctly\n; when you write non-aligned data.\n;\n\t\t;align\t32\nLong_Single_Line_Copy:\n\t\tprologue\n\n rept 3\n\t\ttest\tedi,3\n\t\tjz\tLSLC_aligned\n\t\tmovsb\n\t\tdec\tecx\n endm\n\nLSLC_aligned:\n\t\tmov\tebx,ecx\n\n\t\tshr\tecx,2\n\t\trep\tmovsd\n\t\tand\tebx,3\n\t\tjz\tproc_out\n\t\tmovsb\n\t\tdec\tbl\n\t\tjz\tproc_out\n\t\tmovsb\n\t\tdec\tbl\n\t\tjz\tproc_out\n\t\tmovsb\nproc_out:\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single short line with no transparent pixels\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\nShort_Single_Line_Copy:\n\t\tprologue\n\t\tcmp\tecx,16\n\t\tjge\tLong_Single_Line_Copy\n\t\tmov\tebx,ecx\n\t\trep\tmovsb\n\t\tmov\tecx,ebx\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Skip a line of source that is all transparent\n;\n; 11/29/95 10:21AM - ST\n;\n\n\t\t;align\t32\nSingle_Line_Skip:\n\t\tprologue\n\t\tadd\tesi,ecx\n\t\tadd\tedi,ecx\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\nSingle_Line_Ghost:\n\n\t\tprologue\n\t\txor\teax,eax\nslg_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[IsTranslucent]\n\t\tinc\tesi\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslg_store_pixel\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\nslg_store_pixel:\n\t\tmov\t[edi],al\n\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\tslg_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\nSingle_Line_Ghost_Trans:\n\t\tprologue\n\t\txor\teax,eax\n;\t\tcmp\tecx,3\n;\t\tja\tslgt4\n\nslgt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgt_transparent\n\nslgt_not_transparent:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgt_store_pixel\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\nslgt_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\tslgt_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\t\t;align\t32\n\nslgt_transparent:\n\t\tinc\tedi\t\t;1\n\t\tdec\tecx\t\t;2\n\t\tjz\tslgt_out\t;1 (not pairable)\n\nslgt_round_again:\n\trept\t64\n\t\tmov\tal,[esi]   ;\t;pipe 1\n\t\tinc\tesi\t   ;1\t;pipe 2\n\t\ttest\tal,al\t   ;\t;pipe 1\n\t\tjnz\tslgt_not_transparent\t;pipe 2 (not pairable in 1)\n\t\t\t\t   ;2\n\t\tinc\tedi\t   ;\t;pipe 1\n\t\tdec\tecx\t   ;3\t;pipe 2\n\t\tjz\tslgt_out ;4\t;pipe 1 (not pairable)\n\tendm\t\t\t   ; best case is 4 cycles per iteration\n\t\tjmp\tslgt_round_again\n\nslgt_out:\tepilogue\n\t\tnext_line\n\n\n\n;\n; Optimised video memory access version\n;\n\t\t;align \t32\n\nslgt4:        push\tedx\n\t\tmov\tedx,[edi]\n\n\trept\t4\n\tlocal\tslgt4_store1\n\tlocal\tslgt4_trans1\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgt4_trans1\n\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgt4_store1\n\n\t\tand\tebx,0ff00h\n\t\tmov\tal,dl\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[eax+ebx]\n\nslgt4_store1:\tmov\tdl,al\n\nslgt4_trans1:\tror\tedx,8\n\tendm\n\t\tmov\t[edi],edx\n\t\tpop\tedx\n\t\tlea\tedi,[edi+4]\n\t\tlea\tecx,[ecx+0fffffffch]\n\t\tcmp\tecx,3\n\t\tja\tslgt4\n\t\ttest\tecx,ecx\n\t\tjnz\tslgt_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Fading:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tpush\tebp\n\t\tmov\tebp,[FadingNum]\n\t\tpush\tebp\n\nslf_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\n\t\tmov\tebp,[esp]\n\nslf_fade_loop:mov\tal,[ebx+eax]\n\t\tdec\tebp\n\t\tjnz\tslf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslf_loop\n\t\tadd\tesp,4\n\t\tpop\tebp\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Fading_Trans:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tpush\tebp\n\t\tmov\tebp,[FadingNum]\n\t\tpush\tebp\n\nslft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslft_transparent\n\n\t\tmov\tebp,[esp]\n\nslft_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tebp\n\t\tjnz\tslft_fade_loop\n\n\t\tmov\t[edi],al\nslft_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslft_loop\n\t\tadd\tesp,4\n\t\tpop\tebp\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with a single fade level (colour remap)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Single_Fade:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\nslsf_loop:\tmov\tal,[esi]\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslsf_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and a single fade level (colour remap)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Single_Fade_Trans:\n\t\tprologue\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\nslsft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslsft_transparent\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\tslsft_loop\n\t\tepilogue\n\t\tnext_line\n\n\t\t;align\t32\n\nslsft_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjz\tslsft_next_line\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslsft_transparent\n\t\tmov\tal,[ebx+eax]\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\t\tdec\tecx\n\t\tjnz\tslsft_loop\n\nslsft_next_line:\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n\n;*****************************************************************************\n; Draw a single line with ghosting and fading (colour remapping)\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Ghost_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\nSLGF_loop:\txor\teax,eax\n\t\tmov\tal,[esi]\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgf_do_fading\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\nslgf_do_fading:\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslgf_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslgf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tSLGF_loop\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Ghost_Fading_Trans:\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\t\txor\teax,eax\n\n;\t\tcmp\tecx,3\n;\t\tja\tslgft4\n\nSLGFT_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgft_trans_pixel\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgft_do_fading\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\nslgft_do_fading:\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslgft_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslgft_fade_loop\n\n\t\tmov\t[edi],al\nslgft_trans_pixel:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tSLGFT_loop\n\t\tepilogue\n\t\tnext_line\n\n\n\t\t;align\t32\n\nslgft4:\tpush\tedx\n\t\tmov\tedx,[edi]\n\n\trept\t4\n\tlocal\tslgft4_fade\n\tlocal\tslgft4_fade_lp\n\tlocal\tslgft4_trans\n\t\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslgft4_trans\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[eax+ebx]\n\t\tcmp\tbh,-1\n\t\tjz\tslgft4_fade\n\n\t\tand\tebx,0ff00h\n\n\t\tmov\tal,dl\n\t\tadd\tebx,[Translucent]\n\t\tmov\tal,[ebx+eax]\n\nslgft4_fade:\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslgft4_fade_lp:\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslgft4_fade_lp\n\n\t\tmov\tdl,al\n\nslgft4_trans:\tror\tedx,8\n\tendm\n\t\tmov\t[edi],edx\n\t\tpop\tedx\n\t\tlea\tedi,[edi+4]\n\t\tsub\t[StashECX],4\n\t\tjz\tslgft4_out\n\t\tcmp\t[StashECX],3\n\t\tja\tslgft4\n\t\tjmp\tSLGFT_loop\n\nslgft4_out:\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator effect\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator:\n\n\t\tprologue\n\nslp_loop:\tmov\tal,[esi]\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\tor\tbh,bh\n\t\tjnz\tslp_get_pred\n\n\t\tmov\t[BFPartialCount] , ebx\n\t\tjmp\tslp_skip_pixel\n\nslp_get_pred:\txor\tbh , bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount] , ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax, dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\t\tmov\t[edi],al\n\nslp_skip_pixel:\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslp_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels and predator effect\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Trans:\n\n\t\tprologue\n\nslpt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslpt_skip_pixel\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\tor\tbh,bh\n\t\tjnz\tslpt_get_pred\n\n\t\tmov\t[BFPartialCount] , ebx\n\t\tjmp\tslpt_skip_pixel\n\nslpt_get_pred:xor\tbh , bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount] , ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset ] , PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\t\tmov\t[edi],al\n\nslpt_skip_pixel:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslpt_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Ghost:\n\n\t\tprologue\n\nslpg_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\tslpg_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpg_check_ghost\n\nslpg_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax ]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\t\tmov\tal,[edi+eax]\n\nslpg_check_ghost:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\tslpg_store_pixel\n\n\t\txor\teax,eax\n\t\tand\tebx,0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\nslpg_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tesi\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslpg_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, predator and ghosting\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Ghost_Trans:\n\t\tprologue\n\nslpgt_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslpgt_transparent\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\tslpgt_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpgt_check_ghost\n\nslpgt_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax ]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\t\tmov\tal,[edi+eax]\n\nslpgt_check_ghost:\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\tslpgt_store_pixel\n\n\t\txor\teax,eax\n\t\tand\tebx,0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\nslpgt_store_pixel:\n\t\tmov\t[edi],al\nslpgt_transparent:\n\t\tinc\tedi\n\n\t\tdec\tecx\n\t\tjnz\tslpgt_loop\n\n\t\tpop\tecx\n\t\tepilogue\n\t\tnext_line\n\n\n;*****************************************************************************\n; Draw a single line with predator and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\nslpf_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tinc\tesi\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\tslpf_get_pred\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpf_do_fading\n\nslpf_get_pred:xor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tand\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\n\t\tand\teax,0ffffh\n\t\tmov\tal,[eax+edi]\n\nslpf_do_fading:\n\t\tand\teax,255\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslpf_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslpf_fade_loop\n\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tslpf_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, fading and predator\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Fading_Trans:\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\nslpft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslpft_transparent\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh,bh\n\t\tjnz\tslpft_get_pred\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpft_do_fading\n\nslpft_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tand\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\n\t\tand\teax,0ffffh\n\t\tmov\tal,[eax+edi]\n\nslpft_do_fading:\n\t\tand\teax,255\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslpft_fade_loop:\n\t\tmov\tal,[eax+ebx]\n\t\tdec\tecx\n\t\tjnz\tslpft_fade_loop\n\n\t\tmov\t[edi],al\nslpft_transparent:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tslpft_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with predator, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Ghost_Fading:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\nslpgf_loop:\tmov\tal,[esi]\n\t\tmov\tebx,[BFPartialCount]\n\t\tinc\tesi\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh , bh\n\t\tjnz\tslpgf_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpgf_check_ghost\n\nslpgf_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\nslpgf_check_ghost:\n\t\tand\teax,255\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\tslpgf_do_fading\n\n\t\tand\tebx , 0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\nslpgf_do_fading:\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslpgf_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tecx\n\t\tjnz\tslpgf_fade_loop\n\nslpgf_store_pixel:\n\t\tmov\t[edi],al\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tslpgf_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n;*****************************************************************************\n; Draw a single line with transparent pixels, predator, ghosting and fading\n;\n; 11/29/95 10:21AM - ST\n;\n\t\t;align\t32\n\nSingle_Line_Predator_Ghost_Fading_Trans:\n\n\t\tprologue\n\t\tmov\t[StashECX],ecx\n\nslpgft_loop:\tmov\tal,[esi]\n\t\tinc\tesi\n\t\ttest\tal,al\n\t\tjz\tslpgft_transparent\n\n\t\tmov\tebx,[BFPartialCount]\n\t\tadd\tebx,[BFPartialPred]\n\t\ttest\tbh , bh\n\t\tjnz\tslpgft_get_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[BFPartialCount],ebx\n\t\tjmp\tslpgft_check_ghost\n\nslpgft_get_pred:\n\t\txor\tbh,bh\n\t\tmov\teax,[BFPredOffset]\n\t\tmov\t[BFPartialCount],ebx\n\t\tadd\tbyte ptr [BFPredOffset],2\n\t\tmov\teax,dword ptr [BFPredTable+eax]\n\t\tand\tbyte ptr [BFPredOffset],PRED_MASK\n\t\tand\teax,0ffffh\n\n\t\tmov\tal,[edi+eax]\n\nslpgft_check_ghost:\n\t\tand\teax,255\n\t\tmov\tebx,[IsTranslucent]\n\t\tmov\tbh,[ebx+eax]\n\t\tcmp\tbh,0ffh\n\t\tje\tslpgft_do_fading\n\n\t\tand\tebx , 0FF00h\n\n\t\tmov\tal,[edi]\n\t\tadd\tebx,[Translucent]\n\n\t\tmov\tal,[ebx+eax]\n\nslpgft_do_fading:\n\t\txor\teax,eax\n\t\tmov\tebx,[FadingTable]\n\t\tmov\tecx,[FadingNum]\n\nslpgft_fade_loop:\n\t\tmov\tal,[ebx+eax]\n\t\tdec\tecx\n\t\tjnz\tslpgft_fade_loop\n\nslpgft_store_pixel:\n\t\tmov\t[edi],al\nslpgft_transparent:\n\t\tinc\tedi\n\n\t\tdec\t[StashECX]\n\t\tjnz\tslpgft_loop\n\n\t\tepilogue\n\t\tnext_line\n\n\n\n\n;\t\tends\t\t;end of strict alignment segment\n\n;\t       \tcodeseg\n\n\n\n;extern\tBF_Trans:near\n\nBF_Trans:\n\n\tprologue\n; calc the code location to skip to 10 bytes per REPT below!!!!\n\tmov\tecx , eax\n\tand\tecx , 01fh\n\tlea\tecx , [ ecx + ecx * 4 ]\t\t; quick multiply by 5\n\tneg\tecx\n\tshr\teax , 5\n\tlea\tecx , [ trans_reference + ecx * 2 ] ; next multiply by 2\n\tmov\t[ loop_cnt ] , eax\n\tmov\t[ jmp_loc ] , ecx\n\ntrans_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\n; the following code should NOT be changed without changing the calculation\n; above!!!!!!\n\ntrans_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\t\tmov\tbl , [ esi ]\n\t\tinc\tesi\n\t\ttest\tbl , bl\n\t\tjz\ttrans_pixel\n\n\t\tmov\t[ edi ] , bl\n\n\ttrans_pixel:\n\t\tinc\tedi\n\tENDM\n\ntrans_reference:\n\tdec\tecx\n\tjge\ttrans_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\ttrans_loop\n\tepilogue\n\n\tret\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Ghost:near\nBF_Ghost:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx, [offset ghost_reference]\n\tsub\tecx, [offset ghost_line]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ghost_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nghost_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\nghost_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\nghost_reference:\n\tdec\tecx\n\tjge\tghost_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tghost_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Ghost_Trans:near\nBF_Ghost_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset ghost_t_reference ]\n\tsub\tecx, [ offset ghost_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ghost_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nghost_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\nghost_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\nghost_t_reference:\n\tdec\tecx\n\tjge\tghost_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tghost_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Fading:near\nBF_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset fading_reference ]\n\tsub\tecx, [ offset fading_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ fading_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nfading_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\nfading_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\nfading_line:\n\n\tREPT\t32\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\nfading_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tfading_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tfading_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Fading_Trans:near\nBF_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset fading_t_reference ]\n\tsub\tecx, [ offset fading_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ fading_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nfading_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\tjmp\t[ jmp_loc ]\n\nfading_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\nfading_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\nfading_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tfading_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tfading_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Ghost_Fading:near\nBF_Ghost_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset ghost_f_reference ]\n\tsub\tecx, [ offset ghost_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ghost_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nghost_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\nghost_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\nghost_f_line:\n\n\tREPT\t32\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a lucent color?\n\t\tmov\tbh , byte ptr [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the lation table\n\t\t\t\t\t\t\t; ((_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (_color * 256) of the lation equ.\n\t\tmov\tal , byte ptr [ ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\nghost_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tghost_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tghost_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Ghost_Fading_Trans:near\nBF_Ghost_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset ghost_f_t_reference ]\n\tsub\tecx, [ offset ghost_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ ghost_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\nghost_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\nghost_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\nghost_f_t_line:\n\n\tREPT\t32\n\tlocal\ttransp_pixel\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttransp_pixel\n\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , byte ptr [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , byte ptr [ ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttransp_pixel:\n\t\tinc\tedi\n\n\tENDM\n\nghost_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tghost_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tghost_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator:near\nBF_Predator:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_reference ]\n\tsub\tecx, [offset predator_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\npredator_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tskip_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tskip_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n;\t\txor\tbh , bh\n;\t\tmov\teax , [ BFPredValue ]\t; pick up a color offset a pseudo-\n;\t\t\t\t\t\t;  random amount from the current\n;\t\tmov\t[ BFPartialCount ] , ebx\n;\t\tmov\tal , [ edi + eax ]\t;  viewport address\n\n\t\tmov\t[ edi ] , al\n\n\tskip_pixel:\n\t\tinc\tedi\n\n\tENDM\n\npredator_reference:\n\tdec\tecx\n\tjge\tpredator_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Trans:near\nBF_Predator_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_t_reference ]\n\tsub\tecx, [ offset predator_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\npredator_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tstore_pixel\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\npredator_t_reference:\n\tdec\tecx\n\tjge\tpredator_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Ghost:near\nBF_Predator_Ghost:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_g_reference ]\n\tsub\tecx, [ offset predator_g_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_g_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_g_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\npredator_g_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\npredator_g_reference:\n\tdec\tecx\n\tjge\tpredator_g_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_g_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Ghost_Trans:near\nBF_Predator_Ghost_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_g_t_reference ]\n\tsub\tecx, [ offset predator_g_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_g_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_g_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tjmp\t[ jmp_loc ]\n\npredator_g_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tstore_pixel\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\npredator_g_t_reference:\n\tdec\tecx\n\tjge\tpredator_g_t_line\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_g_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Fading:near\nBF_Predator_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_f_reference ]\n\tsub\tecx, [ offset predator_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\npredator_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\npredator_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\npredator_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tpredator_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Fading_Trans:near\nBF_Predator_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_f_t_reference ]\n\tsub\tecx, [ offset predator_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\npredator_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\npredator_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tdo_fading\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\npredator_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tpredator_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Ghost_Fading:near\nBF_Predator_Ghost_Fading:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_g_f_reference ]\n\tsub\tecx, [ offset predator_g_f_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_g_f_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_g_f_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\npredator_g_f_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\npredator_g_f_line:\n\n\tREPT\t32\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tinc\tesi\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\t\tinc\tedi\n\n\tENDM\n\npredator_g_f_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tpredator_g_f_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_g_f_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\n;extern\tBF_Predator_Ghost_Fading_Trans:near\nBF_Predator_Ghost_Fading_Trans:\n\n\tprologue\n\tmov\tebx , eax\t\t\t; width\n\n\t; NOTE: the below calculation assumes a group of instructions is\n\t;\tless than 256 bytes\n\n\t; get length of the 32 groups of instructions\n\n\tlea\tecx , [ offset predator_g_f_t_reference ]\n\tsub\tecx, [ offset predator_g_f_t_line ]\n\n\tshr\tebx , 5\t\t\t\t; width / 32\n\tshr\tecx , 5\t\t\t\t; length of instructions / 32\n\tand\teax , 01fh\t\t\t; mod of width / 32\n\tmul\tcl\t\t\t\t; calc offset to start of group\n\tneg\teax\t\t\t\t; inverse of width\n\tmov\t[ loop_cnt ] , ebx\t\t; save width / 32\n\tlea\tecx , [ predator_g_f_t_reference + eax ]\n\tmov\teax , 0\n\tmov\t[ jmp_loc ] , ecx\n\npredator_g_f_t_loop:\n\tmov\tecx , [ loop_cnt ]\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\tjmp\t[ jmp_loc ]\n\npredator_g_f_t_line_begin:\n\tmov\t[ StashECX ] , ecx\t\t; preserve ecx for later\n\npredator_g_f_t_line:\n\n\tREPT\t32\n\tlocal\ttrans_pixel\n\tlocal\tget_pred\n\tlocal\tcheck_ghost\n\tlocal\tstore_pixel\n\tlocal\tdo_fading\n\tlocal\tfade_loop\n\t\tmov\tal , [ esi ]\n\t\tinc\tesi\n\t\ttest\tal , al\n\t\tjz\ttrans_pixel\n\n\t\tmov\tebx , [ BFPartialCount ]\n\t\tadd\tebx , [ BFPartialPred ]\n\t\tor\tbh , bh\n\t\tjnz\tget_pred\t\t; is this a predator pixel?\n\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tjmp\tcheck_ghost\n\n\tget_pred:\n\t\txor\tbh , bh\n\t\tmov\teax, [ BFPredOffset ]\n\t\tmov\t[ BFPartialCount ] , ebx\n\t\tadd\tBYTE PTR [ BFPredOffset ] , 2\n\t\tmovzx\teax , WORD PTR [ BFPredTable + eax ]\n\t\tand\tBYTE PTR [ BFPredOffset ] , PRED_MASK\n\t\t\t\t\t\t; pick up a color offset a pseudo-\n\t\t\t\t\t\t;  random amount from the current\n\t\tmovzx\teax , BYTE PTR [ edi + eax ]\t;  viewport address\n\n\tcheck_ghost:\n\t\tmov\tebx , [ IsTranslucent ]\t\t; is it a translucent color?\n\t\tmov\tbh , BYTE PTR [ ebx + eax ]\n\t\tcmp\tbh , 0ffh\n\t\tje\tdo_fading\n\n\t\tand\tebx , 0FF00h\t\t\t; clear all of ebx except bh\n\t\t\t\t\t\t\t; we have the index to the translation table\n\t\t\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\t\tmov\tal , [ edi ]\t\t\t; mov pixel at destination to al\n\t\tadd\tebx , [ Translucent ]\t\t; get the ptr to it!\n\t\t\t\t\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\tmov\tal , BYTE PTR [ ebx + eax ]\t; get new pixel in al\n; DRD\t\tjmp\tstore_pixel\n\n\tdo_fading:\n\t\tmov\tebx , [ FadingTable ]\t\t; run color through fading table\n\t\tmov\tecx , [ FadingNum ]\n\n\tfade_loop:\n\t\tmov\tal, byte ptr [ebx + eax]\n\t\tdec\tecx\n\t\tjnz\tfade_loop\n\n\tstore_pixel:\n\t\tmov\t[ edi ] , al\n\n\ttrans_pixel:\n\t\tinc\tedi\n\n\tENDM\n\npredator_g_f_t_reference:\n\tmov\tecx , [ StashECX ]\t\t; restore ecx for main draw loop\n\tdec\tecx\n\tjge\tpredator_g_f_t_line_begin\n\n\tadd\tesi , [ scr_adjust_width ]\n\tadd\tedi , [ dest_adjust_width ]\n\tdec\tedx\n\tjnz\tpredator_g_f_t_loop\n\n\tepilogue\n\tret\n\n\n;********************************************************************\n;********************************************************************\n\nNot_Supported:\n\tret\n\nBuffer_Frame_To_Page\tENDP\t\n\n\nend\n\nexterndef\tC CPUType:byte\n\n\n\n;*********************************************************************************************\n;* Detect_MMX_Availability -- Detect the presence of MMX technology.                         *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      True if MMX technology is available.                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* Note: Based in part on CPUID32.ASM by Intel                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nDetect_MMX_Availability proc C\n\n\t\tlocal\tidflag:byte\n\t\tlocal\tlocal_cputype:byte\n\n;assume processor is at least 386\n;\n;check whether AC bit in eflags can be toggled.\n;If not then processor is 386\n\n\t\tmov\t[idflag],0\n\n\t\tpushfd\t\t\t;get Eflags in EAX\n\t\tpop\teax\n\t\tmov\tecx,eax\t\t;save eflags\n\t\txor\teax,40000h\t;toggle AC bit in eflags\n\t\tpush\teax\t\t;new eflags on stack\n\t\tpopfd\t\t\t;move new value into eflags\n\t\tpushfd\t\t\t;get new eflags back into eax\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;if AC bit not toggled then CPU=386\n\t\tmov\t[local_cputype],3\n\t\tjz\t@@end_get_cpu\t;cpu is 386\n\n\t\tpush\tecx\n\t\tpopfd\t\t\t;restore AC bit in eflags\n\n\n;processor is at least 486\n;\n;Check for ability to set/clear ID flag in EFLAGS\n;ID flag indicates ability of processor to execute the CPUID instruction.\n;486 not guaranteed to have CPUID inst?\n;\n\t\tmov\t[local_cputype],4\n\t\tmov\teax,ecx\t\t;original EFLAGS\n\t\txor\teax,200000h\t;toggle ID bit\n\t\tpush\teax\n\t\tpopfd\n\t\tpushfd\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;check if still toggled\n\t\tjz\t@@end_get_cpu\n\n\n;       Execute CPUID instruction to determine vendor, family,\n;       model and stepping.\n;\n\n\t\tmov\t[idflag],1\t;flag ID is available\n\n\t\txor\teax,eax\n\t\tcpuid\n\n\t\tmov\tdword ptr [VendorID],ebx\n\t\tmov\tdword ptr [VendorID+4],edx\n\t\tmov\tdword ptr [VendorID+8],ecx\n\t\tmov\tdword ptr [VendorID+12],\" \"\n\n\t\tcmp\teax,1\t\t;check if 1 is valid\n\t\tjl\t@@end_get_cpu\t;inp for cpuid inst.\n\n\t\txor\teax,eax\n\t\tinc\teax\n\n\t\tcpuid\t\t;get stepping, model and family\n\n\t\tand     ax,0f00H\n\t\tshr     ax,08H\n\n\t\tmov\t[local_cputype],al\n\n@@end_get_cpu:\tmov\tal,[local_cputype]\n\t\tmov\t[CPUType],al\n\n\n;\n; We have the CPU type in al now.\n; If we arent on at least a pentium then we can assume there is no MMX\n;\n\t\tcmp\tal,5\n\t\tjl\t@@no_mmx\n\n\t\tmov\teax,1\n\t\tcpuid\n\t\ttest\tedx,00800000h\n\t\tjz\t@@no_mmx\n\n;\n; MMX detected - return true\n;\n\t\tmov\teax,1\n\t\tret\n\n\n@@no_mmx:\txor\teax,eax\n\t\tret\n\n\nDetect_MMX_Availability endp\n\n\n\n;*********************************************************************************************\n;* Init_MMX -- Do any special inits required for MMX support                                 *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nInit_MMX\tproc C\n\n\t\tmov\tedi,offset NewShapeJumpTable\n\t\tmov\tecx,offset EndNewShapeJumpTable\n\t\tsub\tecx,edi\n\t\tshr\tecx,2\n\t\tmov\teax,offset Single_Line_Trans\n\t\tmov\tebx,offset MMX_Single_Line_Trans\n\t\tcld\n\n\n@@patch_loop:   repnz\tscasd\n\t\tjnz\t@@done\n\t\tmov\t[edi-4],ebx\n\t\ttest\tecx,ecx\n\t\tjnz\t@@patch_loop\n\n@@done:\t\tret\n\nInit_MMX\tendp\n\n\n\n\n\n\n;*********************************************************************************************\n;* MMX_Done -- Restores floating point capability after MMX usage                            *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nMMX_Done\tproc C\n\n\t\temms\n\t\tret\n\nMMX_Done\tendp\n\n\n\n\n\n\n\n\t\tcode segment page public use32 'code'\t; Need stricter segment alignment\n\t\t\t\t\t\t\t; for pentium optimisations\n\n\n;*********************************************************************************************\n;* MMX_Single_Line_Trans -- draw a single line of transparent pixels using MMX technology    *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tEsi - ptr to source data                                                     *\n;*              Edi - ptr to destination data                                                *\n;*              Ecx - width to draw in bytes                                                 *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\n\t\talign\t16\n\nMMX_Single_Line_Trans proc near\n\n;\n; If we are doing less than 8 bytes then dont use MMX\n;\n\t\tcmp\tecx,8\n\t\tjge\t@@mmx_loop\n\t\tpush\toffset Single_Line_Trans_Entry\n\t\tret\n\n;\n; Use MMX instructions to mask 8 bytes at once\n;\n; Creates a bitmask based on the source bytes equality with zero and then uses this to mask\n; out the source bytes in the destination data. The advatage that MMX gives us is that there is\n; no 'test for zero then jump' required to mask.\n;\n\t\talign\t64\t\t;MMX instructions like 64 byte alignment!\n\n@@mmx_loop:\n\t\tmovq\tmm0,[esi]\t; move 8 bytes of source into mm0\n\t\tpxor\tmm1,mm1\t\t; zero out mm1\n\t\tpcmpeqb mm1,mm0\t\t; compare mm0 with 0. Bits get set in mm1\n\t\tlea\tesi,[esi+8]     ; adjust the source data pointer\n\t\tpand\tmm1,[edi]\t; and in the destination data to throw away the bytes which arent zero in the source\n\t\tsub\tecx,8\t\t; adjust the byte counter\n\t\tpor\tmm1,mm0         ; or in the source with the destination data\n\t\tmovq\t[edi],mm1       ; write back the destination data\n\t\tlea\tedi,[edi+8]\t; adjust the destination pointer\n\n\t\tcmp\tecx,8\n\t\tjg\t@@mmx_loop\n\n;\n; Jump to the approprite code for drawing the end of this line or going to the next one\n;\n\t\tpush\toffset Next_Line\n\t\tjcxz   \t@@next_line\n\t\tpush\toffset Single_Line_Trans_Entry\n@@next_line:\tret\n\n\nMMX_Single_Line_Trans endp\n\n\ncode ends\n\n\t\t.data\n\nCPUType\t\tdb\t0\nVendorID\tdb\t\"Not available\",0,0,0,0,0,0\n\n\n\n\n\n\n\n\n\n\n\nEND\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : KEYFBUFF.ASM                             *\n;*                                                                         *\n;*                   Programmer : Phil W. Gorrow                           *\n;*                                                                         *\n;*                   Start Date : July 16, 1992                            *\n;*                                                                         *\n;*                  Last Update : October 2, 1994   [JLB]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   BUFFER_FRAME_TO_LOGICPAGE --                                          *\n;*   Normal_Draw -- Function that writes a normal pixel line               *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;\tIDEAL\n;\tP386\n;IDEAL_MODE\tEQU\t1\n;\tINCLUDE \"wwlib.i\"\n\n\t;-------------------------------------------------------------------\n\t; Extern all the library variables that this module requires\n\t;-------------------------------------------------------------------\n\n\tEXTRN\tC MaskPage:WORD\n\tEXTRN\tC BackGroundPage:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define all the equates that this module requires\n\t;-------------------------------------------------------------------\n\nWIN_X\t\tEQU\t0\t\t; offset for the x coordinate\nWIN_Y\t\tEQU\t2\t\t; offset for the y coordinate\nWIN_WIDTH\tEQU\t4\t\t; offset for the window width\nWIN_HEIGHT\tEQU\t6\t\t; offset for the window height\nBYTESPERROW\tEQU\t320\t\t; number of bytes per row\n\nFLAG_NORMAL\t\tEQU\t0\t\t; flag for normal draw\n\nFLAG_GHOST\t\tEQU\t1\t\t; This flag enables the ghost\nFLAG_PRIORITY_TRANS\tEQU\t2\t\t; flag for priority and transparent\nFLAG_TRANS\t\tEQU\t4\t\t; flag for transparent draw\nFLAG_PRIORITY\t\tEQU\t8\t\t; flag for priority draw\n\n\t\t\t\t\t\t; fx on the above flags\n\nFLAG_MASK\t\tEQU\t15\t\t; used to and of uneeded bits\n\nSHAPE_NORMAL\t\tEQU\t0000h\t\t; Standard shape.\n;SHAPE_HORZ_REV\t\tEQU\t0001h\t\t; Flipped horizontally.\n;SHAPE_VERT_REV\t\tEQU\t0002h\t\t; Flipped vertically.\n;SHAPE_SCALING\t\tEQU\t0004h\t\t; Scaled (WORD scale_x, WORD scale_y)\n\nSHAPE_WIN_REL\t\tEQU\t0010h\t\t; Coordinates are window relative instead of absolute.\nSHAPE_CENTER\t\tEQU\t0020h\t\t; Coordinates are based on shape's center point.\nSHAPE_TRANS\t\tEQU\t0040h\t\t; has transparency\n\n\n;SHAPE_FADING\t\tEQU\t0100h\t\t; Fading effect active (VOID * fading_table, WORD fading_num).\n;SHAPE_PREDATOR\t\tEQU\t0200h\t\t; Transparent warping effect.\n;SHAPE_COMPACT\t\tEQU\t0400h\t\t; Never use this bit.\nSHAPE_PRIORITY\t\tEQU\t0800h\t\t; Use priority system when drawing.\n\nSHAPE_GHOST\t\tEQU\t1000h\t\t; Transluscent table process.\n;SHAPE_SHADOW\t\tEQU\t2000h\t\t; \n;SHAPE_PARTIAL \t\tEQU\t4000h\t\t; \n;SHAPE_COLOR\t\tEQU\t8000h\t\t; Remap the shape's colors (VOID * color_table).\n\n\n; MBL MOD 12.1.92\n\nCLEAR_NON_WALK_BIT_AND_SCALE_BITS\tEQU\t7\t; Makes it one AND per pixel in Priority_Trans display\nCLEAR_NON_WALK_BIT    \tEQU\t7fh\t; and with 0111-1111 to clear non-walkable high bit\nCLEAR_SCALE_BITS  \tEQU\t87h\t; and with 1000-0111 to clear scaling id bits\nNON_WALKABLE_BIT  \tEQU\t80h\t; and with 1000-0000 to clear all but non-walkable bit\n\n; END MBL MOD\n\n\n\tCODESEG\n\n\t;   1 = GHOST (all odd entrys are prefixed with Ghost_)\n\t;   2 = BLAAAH\n\t;   4 = Trans (prfx)\n\t;   8 = Prior (prfx)\n\n\n;---------------------------------------------------------------------------\n; Define the table of different line draw types\n;---------------------------------------------------------------------------\n\nLineTable\tDW\tWSA_Normal_Draw\t\t\t;0\n\t\tDW\tGhost_Normal_Draw\t\t;1\n\t\tDW\t0\t\t\t\t;2\n\t\tDW\t0\t\t\t\t;3\n\n\t\tDW\tTransparent_Draw\t\t;4\n\t\tDW\tGhost_Transparent_Draw\t\t;5\n\t\tDW\t0\t\t\t\t;6\n\t\tDW\t0\t\t\t\t;7\n\n\t\tDW\tPriority_Draw\t\t\t;8\n\t\tDW\tGhost_Priority_Draw\t\t;9\n\t\tDW\t0\t\t\t\t;10\n\t\tDW\t0\t\t\t\t;11\n\n\t\tDW\tPriority_Transparent_Draw\t;12\n\t\tDW\tGhost_Priority_Transparent_Draw\t;13\n\t\tDW\t0\t\t\t\t;14\n\t\tDW\t0\t\t\t\t;15\n\n\n\n;***************************************************************************\n;* BUFFER_FRAME_TO_LOGICPAGE --                                            *\n;*                                                                         *\n;*                                                                         *\n;*                                                                         *\n;* INPUT:                                                                  *\n;*                                                                         *\n;* OUTPUT:                                                                 *\n;*                                                                         *\n;* WARNINGS:                                                               *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/16/1992 PWG : Created.                                             *\n;*=========================================================================*\n\tPUBLIC\tC Buffer_Frame_To_LogicPage\n\tPROC\tC Buffer_Frame_To_LogicPage FAR USES ax bx ecx dx ds esi es edi\n\n\t;-------------------------------------------------------------------\n\t; Define the arguements that our program takes.\n\t;-------------------------------------------------------------------\n\n\tARG\tx_pixel:WORD\t\t; x pixel position to draw at\n\tARG\ty_pixel:WORD\t\t; y pixel position to draw at\n\tARG\tpixel_w:WORD\t\t; pixel width of draw region\n\tARG\tpixel_h:WORD\t\t; pixel height of draw region\n\tARG\twin:WORD\t\t; window to clip around\n\tARG\tflags:WORD\t\t; flags that this routine will take\n\tARG\tbuffer:DWORD\t\t; pointer to the buffer with data\n\tARG\targs:WORD\n\n\t;-------------------------------------------------------------------\n\t; Define the local variables that our program uses\n\t;-------------------------------------------------------------------\n\n\tLOCAL\tIsTranslucent:DWORD\t; ptr to the is_translucent table\n\tLOCAL\tTranslucent:DWORD\t; ptr to the actual translucent table\n\n\tLOCAL\twin_x1:WORD\t\t; clip window left x pixel position\n\tLOCAL\twin_x2:WORD\t\t; clip window right x pixel position\n\tLOCAL\twin_y1:WORD\t\t; clip window top y pixel position\n\tLOCAL\twin_y2:WORD\t\t; clip window bottom y pixel position\n\tLOCAL\tclipleft:WORD\t\t; number of pixels to clip on left\n\tLOCAL\tclipright:WORD\t\t; number of pixels to clip on right\n\tLOCAL\tnextline:WORD\t\t; offset to the next line\n\tLOCAL\tputmiddle:WORD \t\t; routine to call to put the middle\n\tLOCAL\tmaskpage:WORD\t\t; location of the depth masks\n\tLOCAL   background:WORD\t\t; location of the background data\n\tLOCAL   jflags:WORD\t\t; location of the background data\n\n\tLOCAL\tpriority:BYTE\t\t; the priority level of the back\n\n\tpush\tfs\n\n\txor\tecx,ecx\n\n\t;--------------------------------------------------------------------\n\t; Check to see if we have supplied any GHOST tables.\n\t;--------------------------------------------------------------------\n\tpush\tdi\n\n\tmov\tdi,6\n\tmov\t[jflags],0\n\nghost:\n\ttest\t[flags],SHAPE_GHOST\t; are we ghosting this shape\n\tjz\tshort no_ghost\t; if not then skip and do more\n\n\tor\t[jflags],FLAG_GHOST\n\n\tles\tax,dword ptr [buffer + di]\n\n\t; get the \"are we really translucent?\" table\n\tmov\t[WORD PTR IsTranslucent],ax\n\tmov\t[WORD PTR IsTranslucent + 2],es\n\tadd\tax,0100h\t\t; add to offset for tables\n\n\t; get the \"ok we are translucent!!\" table\n\tmov\t[WORD PTR Translucent],ax\n\tmov\t[WORD PTR Translucent + 2],es\n\n\tadd\tdi,4\n\nno_ghost:\n\n\tpop\tdi\n\n\t;-------------------------------------------------------------------\n\t; See if we need to center the frame\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_CENTER\t; does this need to be centered?\n\tje\tshort no_centering\t; if not the skip over this stuff\n\n\tmov\tax,[pixel_w]\n\tmov\tbx,[pixel_h]\n\tsar\tax,1\n\tsar\tbx,1\n\tsub\t[x_pixel],ax\n\tsub\t[y_pixel],bx\n\nno_centering:\n\tmov\tax,[flags]\n\tand\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tcmp\tax,SHAPE_PRIORITY+SHAPE_TRANS\n\tjne\tshort test_trans\n\n\tor\t[jflags],FLAG_PRIORITY_TRANS\n\tjmp\tshort priority\n\n\t;-------------------------------------------------------------------\n\t; Get the trans information if we need to get it\n\t;-------------------------------------------------------------------\ntest_trans:\n\ttest\t[flags],SHAPE_TRANS\t; does this draw use transparencies?\n\tje\tshort test_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_TRANS\n\ntest_priority:\n\t;-------------------------------------------------------------------\n\t; Get the priority information if we need to get it\n\t;-------------------------------------------------------------------\n\ttest\t[flags],SHAPE_PRIORITY\t; does this draw use priorities?\n\tje\tshort no_priority\t; if not the skip over this junk\n\n\tor\t[jflags],FLAG_PRIORITY\n\npriority:\n\tmov\tax,[BackGroundPage]\t; get the background page from ds\n\tmov\t[background],ax\t\t;    and store it on the stack\n\tmov\tax,[MaskPage]\t\t; get the mask page from ds\n\tmov\t[maskpage],ax\t\t;    and store it on the stack\n\tmov\tax,[WORD PTR buffer + 4]; get the priority level from args\n\tmov\t[priority],al\t\t;    and store it in a local\n\n\t;-------------------------------------------------------------------\n\t; Get the draw routine that we are going to draw with\n\t;-------------------------------------------------------------------\nno_priority:\n;\tmov\tbx,[flags]\t\t; load in the current flags byte\n;\tand\tbx,FLAG_MASK\t\t; prevent lockup on bad value\n\tmov\tbx,[jflags]\t\t; load in the jump table flags\n\tshl\tbx,1\n\tmov\tax,[WORD PTR LineTable + bx]\t; get the offset of the skip table\n\tmov\t[putmiddle],ax\t\t; store off the new offset\n\n\t;-------------------------------------------------------------------\n\t; Get a pointer to the logic page to where we will draw our buffer\n\t;-------------------------------------------------------------------\n\tpush\t[LogicPage]\t\t; push the current logic page\n\tcall\tFAR PTR Get_Page\t; get the physical page address\n\tadd\tsp,2\t\t\t; pull the parameter from the stack\n\tmov\tes,dx\t\t\t; store the address in the dest\n\n\t;--------------------------------------------------------------------\n\t; Point DI to the beginning of the window that we need to look at.\n\t;   that way we can access all of the info through di.\n\t;--------------------------------------------------------------------\n\tmov\tsi,OFFSET WindowList\t; get the offset of the window list\n\tmov\tcl,4\t\t\t; shift 3 times = multiply by 16\n\tmov\tax,[win]\t\t; get the window number we are using\n\tshl\tax,cl\t\t\t; each window is 8 words long\n\tadd\tsi,ax\t\t\t; add that into the offset of window\n\n\t;--------------------------------------------------------------------\n\t; Place all the clipping values on the stack so our function will\n\t; be truly re-entrant and will not need to shadow these values.\n\t;--------------------------------------------------------------------\n\tmov\tcl,3\t\t\t; to convert x to pixel mult by 8\n\tmov\tax,[si + WIN_X]\t\t; get the left clip position\n\tshl\tax,cl\t\t\t; convert to a pixel x position\n\tmov\t[win_x1],ax\t\t; store the left edge of window\n\tmov\t[win_x2],ax\n\n\tmov\tax,[si + WIN_WIDTH]\t; get the width of the window\n\tshl\tax,cl\t\t\t; convert to a pixel width\n\tadd\t[win_x2],ax\t\t; add to get the right window edge\n\n\tmov\tax,[si + WIN_Y]\t\t; get the win y coordinate to clip\n\tmov\t[win_y1],ax\t\t; and save it onto the stack\n\n\tadd\tax,[si + WIN_HEIGHT]\t; calculate the bottom win y coord\n\tmov\t[win_y2],ax\t\t; and save it onto the stack\n\n\ttest\t[flags],SHAPE_WIN_REL\t; is this window relative?\n\tje\tshort get_buffer\t; if not the skip over\n\n\tmov\tax,[win_x1]\t\t; get left edge of window\n\tadd\t[x_pixel],ax\t\t; add to x pixel position\n\tmov\tax,[win_y1]\t\t; get top edge of window\n\tadd\t[y_pixel],ax\t\t; add to y pixel position\n\n\t;--------------------------------------------------------------------\n\t; Get a pointer to the source buffer so we can handle the clipping\n\t;--------------------------------------------------------------------\nget_buffer:\n\tlds\tsi,[buffer]\t\t; get a pointer to the buffer\n\n\t;--------------------------------------------------------------------\n\t; Check the top of our shape and clip any lines that are necessary\n\t;--------------------------------------------------------------------\n\tmov\tax,[y_pixel]\t\t; get the y_pixel draw position\n\tsub\tax,[win_y1]\t\t; subtract out the window y top\n\tjns\tshort check_bottom\t\t;   skip if y below window top\n\tadd\tax,[pixel_h]\t\t; add in the height of the region\n\tjg\tshort clip_top\t\t; if positive then clip top lines\n\njump_exit:\n\tjmp\tproc_exit\t\t\t; otherwise completely clipped\n\nclip_top:\n\txchg\t[pixel_h],ax\n\tsub\tax,[pixel_h]\n\tadd\t[y_pixel],ax\n\tmul\t[pixel_w]\t\t; convert to number of bytes to skip\n\tadd\tsi,ax\t\t\t; skip past the necessary bytes\n\n\t;--------------------------------------------------------------------\n\t; Check the bottom of our shape and clip it if necessary\n\t;--------------------------------------------------------------------\ncheck_bottom:\n\tmov\tax,[win_y2]\t\t; get the bottom y of the window\n\tsub\tax,[y_pixel]\t\t; subtract of the y to draw at\n\tjs\tjump_exit\t\t; if its signed then nothing to draw\n\tjz\tjump_exit\t\t; if its zero then nothing to draw\n\n\tcmp\tax,[pixel_h]\t\t; if more room to draw then height\n\tjae\tshort clip_x_left\t\t;   then go check the left clip\n\tmov\t[pixel_h],ax\t\t; clip all but amount that will fit\n\nclip_x_left:\n\tmov\t[clipleft],0\t\t; clear clip on left of region\n\tmov\tax,[x_pixel]\t\t; get the pixel x of draw region\n\tsub\tax,[win_x1]\t\t; pull out the window coordinate\n\tjns\tshort clip_x_right\n\tneg\tax\t\t\t; negate to get amnt to skip in buf\n\tmov\t[clipleft],ax\t\t; store it in the left clip info\n\tadd\t[x_pixel],ax\t\t; move to the edge of the window\n\tsub\t[pixel_w],ax\t\t; pull it out of the pixel width\n\nclip_x_right:\n\tmov\t[clipright],0\t\t; clear clip on right of region\n\tmov\tax,[win_x2]\t\t; get the window x of clip region\n\tsub\tax,[x_pixel]\t\t; subtract the draw edge of region\n\tjs\tjump_exit\t\t; if its negative then get out\n\tjz\tjump_exit\t\t; if its zero then get out\n\n\tcmp\tax,[pixel_w]\t\t; is space available larger than w\n\tjae\tshort draw_prep\t\t;   if so then go get drawing\n\n\n\txchg\t[pixel_w],ax\t\t; amt to draw in pixel_w (wid in ax)\n\tsub\tax,[pixel_w]\t\t; pull out the amount to draw\n\tmov\t[clipright],ax\t\t; this is the amount to clip on right\n\ndraw_prep:\n\tpush\tsi\t\t\t; save off source pos in buffer\n\tpush\tds\t\t\t;   both offset and segment\n\tmov\tax,@data\n\tmov\tds,ax\n\tmov\tbx,[y_pixel]\n\tshl\tbx,1\t\t\t; shift left by 1 for word table look\n\tlds\tsi,[YTable]\t; get the address of the ytable\n\tmov\tdi,[ds:si+bx]\t\t; look up the multiplied value\n\tpop\tds\t\t\t; restore source pos in buffer\n\tpop\tsi\t\t\t;   both offset and segment\n\n\tadd\tdi,[x_pixel]\t\t; add in the x pixel position\n\tmov\t[nextline],di\t\t; save it off in the next line\n\n \t;--------------------------------------------------------------------\n\t; Now determine the type of the shape and process it in the proper\n\t;   way.\n\t;--------------------------------------------------------------------\n\tmov\tdx,[pixel_h]\n\n\t; Check to see if the WSA is the screen width and there is no\n\t; clipping. In this case, then a special single call to the\n\t; line processing routine is possible.\n\tmov\tax,[clipleft]\n\tadd\tax,[clipright]\n\tjne\tshort top_of_loop\n\tcmp\t[pixel_w],BYTESPERROW\n\tjne\tshort top_of_loop\n\n\t;------------------------------------\n\t; The width of the WSA is the screen width, so just process as\n\t; one large WSA line.\n\tmov\tax,BYTESPERROW\n\timul\tdx\n\tmov\tcx,ax\n\tcall\t[putmiddle]\n\tjmp\tshort proc_exit\n\n\t;------------------------------------\n\t; Process line by line.\ntop_of_loop:\n\tadd\tsi,[clipleft]\t\t; skip whats necessary on left edge\n\tmov\tcx,[pixel_w]\t\t; get the width we need to draw\n\n\t; Copy the source to the destination as appropriate. This routine can\n\t; trash AX, BX, CX, and DI. It must properly modify SI to point one byte past\n\t; the end of the data.\n\tcall\t[putmiddle]\n\n\tadd\tsi,[clipright]\t\t; skip past the left clip\n\tadd\t[nextline],BYTESPERROW\n\tmov\tdi,[nextline]\n\n\tdec\tdx\n\tjnz\ttop_of_loop\n\nproc_exit:\n\tpop\tfs\n\tret\n\tENDP\n\n\n;***************************************************************************\n;* NORMAL_DRAW -- Function that writes a normal pixel line                 *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE WSA_Normal_Draw NEAR\n\n IF 1\n \t; This version is marginally faster than the later version.\n \tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\tret\n\n ELSE\n\n\tshr\tcx,1\t\t\t; convert to words (odd pix in carry)\n\trep\tmovsw\t\t\t; write out the needed words\n\tadc\tcx,0\t\t\t; add the carry into cx\n\trep\tmovsb\t\t\t; write out the odd byte if any\n\tret\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* TRANSPARENT_DRAW -- Function that writes a transparent pixel line       *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   10/02/1994 JLB : Optimized for 250% speed improvement.                *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Transparent_Draw NEAR\n\n IF 1\n\t; Preserve DX since it is used as a scratch register.\n\tpush\tdx\n\nloop:\n\t; Swap DS:SI and ES:DI back in preparation for the REP SCASB\n\t; instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Remember the bytes remaining in order to calculate the position\n\t; of the scan when it stops.\n\tmov\tbx,cx\n\n\t; Scan looking for a non-zero value in the source buffer.\n\txor\tal,al\n\trepe scasb\n\n\t; When the loop ends, if the EQ flag is set then the scanning is\n\t; complete. Jump to the end of the routine in order to fixup the\n\t; pointers.\n\tje\tshort fini\n\n\t; Advance the destination pointer by the amount necessary to match\n\t; the source movement. DS:SI points to where data should be written.\n\tadd\tsi,bx\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tdec\tdi\t\t; SCASB leaves DI one byte too far, fix it.\n\tsub\tsi,cx\n\n\t; Scan for the duration of non-zero pixels. This yields a count which\n\t; is used to copy the source data to the destination. Preserve DI.\n\tmov\tdx,di\n\tmov\tbx,cx\n\trepne scasb\n\tmov\tdi,dx\n\n\t; Set BX to equal the number of bytes to copy from source to dest.\n\tinc\tcx\t\t; SCASB leaves CX one too low, fix it.\n\tsub\tbx,cx\n\n\t; Move the data from ES:DI to DS:SI for BX bytes.\n\txchg\tcx,bx\t\t; Make CX=bytes to move, BX=bytes remaining.\n\n\t; Swap DS:SI and ES:DI in preparation for the REP MOV instruction.\n\txchg\tdi,si\n\tmov\tdx,es\n\tmov\tax,ds\n\tmov\tds,dx\n\tmov\tes,ax\n\n\t; Move the data from source to dest. First try to move double\n\t; words. Then copy the remainder bytes (if any). Putting jumps in\n\t; this section doesn't result in any savings -- oh well.\n\tmov\tax,cx\n\tshr\tcx,2\n\trep movsd\n\tand\tax,0011b\n\tmov\tcx,ax\n\tshr\tcx,1\n\trep movsw\n\tadc\tcx,cx\n\trep movsb\n\n\t; Restore CX with the remaining bytes to process.\n\tmov\tcx,bx\n\n\t; If there are more bytes to process, then loop back.\n\tor\tcx,cx\n\tjne\tshort loop\n\nfini:\n\t; Swap ES:DI and DS:SI back to original orientation.\n\tmov\tax,ds\n\tmov\tbx,es\n\tmov\tes,ax\n\tmov\tds,bx\n\txchg\tdi,si\n\n\t; Restore DX and return.\n\tpop\tdx\n\tret\n\n ELSE\n\nloop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort skip\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\nskip:\n\tinc\tdi\n\tloop\tloop_top\n\tret\n\n ENDIF\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_DRAW -- Function that writes a pixels if they are in front of  *\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\nloop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\nout_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\tloop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they are  *\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\nloop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort write_back\t; if it is go write background\n\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort out_pixel\t; if so then write the pixel\n\nwrite_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\nout_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\tloop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_NORMAL_DRAW -- Function that writes a normal pixel line           *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\n\tPROC\tNOLANGUAGE Ghost_Normal_Draw NEAR\n\nloop_top:\n\tlodsb\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\nnormal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\nskip:\n\tinc\tdi\n\tloop\tloop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_TRANSPARENT_DRAW -- Function that writes a transparent pixel line *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   05/27/1993 MCC : Created.                                             *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Transparent_Draw NEAR\n\nloop_top:\n\tlodsb\n\tor\tal,al\n\tjz\tshort skip\n\n;---\n\t; Ok, find out if the colour is a Translucent colour\n\tpush\tax\n\tpush \tds\n\n\tlds\tbx,[IsTranslucent]\n\tmov\tah,al\t\t\t; preserve real pixel\n\txlat\t\t\t\t; get new al (transluecent pixel\n\txchg\tah,al\t\t\t; get real pixel back into AL just in case\n\tcmp\tah,255\n\tje\tshort normal_pixel\t\t; is it a translucent ?\n\t\t\t\t\t; if we get passed here value in\n\t\t\t\t\t; AH should be 0-15\n\n\t; yes, it is a translucent colour so goto our translucent translation\n\t; table and set up a ptr to the correct table\n\n\tmov\tal,[es:di]\n\t\t\t\t\t; mov pixel at destination to al and we have\n\t\t\t\t\t; the index to the translation table\n\t\t\t\t\t; ((trans_colour * 256) + dest colour)\n\tlds\tbx,[Translucent]\t; get the ptr to it!\n\tadd\tbh,ah\t\t\t; Add the (trans_color * 256) of the translation equ.\n\t\t\t\t\t; XLAT only uses AL so no need to clear AH\n\txlat\t\t\t\t; get new pixel in AL\n\nnormal_pixel:\n\tpop\tds\n\tpop\tbx\n\tmov\tah,bh\n;---\n\n\tmov\t[es:di],al\t\t; store the pixel to the screen\n\nskip:\n\tinc\tdi\n\tloop\tloop_top\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_DRAW -- Function that writes a pixels if they are in fron*\n;*\t\t    the given plate.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\n\nloop_top:\n\tlodsb\t\t\t\t; get the pixel to draw on the screen\n\t\t\t\t\t; get the mask byte for our pixel\n\tmov\tbl,[ds:di]\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort out_pixel\t; if so then write the pixel\n\n\tmov\tal,[fs:di]\t\t; get the pixel to write\nout_pixel:\n\tstosb\t\t\t\t; write the pixel and inc the DI\n\tloop\tloop_top\n\n\tret\n\n\tENDP\n\n\n;***************************************************************************\n;* GHOST_PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they*\n;*\t\t    in front of the given plate.  It also deals with\t   *\n;*\t\t    transparent pixels.\t\t\t\t\t   *\n;*                                                                         *\n;* INPUT:\tcx    - number of pixels to write                          *\n;*\t\tds:si - buffer which holds the pixels to write\t\t   *\n;*\t\tes:di - place to put the pixels we are writing\t\t   *\n;*                                                                         *\n;* OUTPUT:      ds:si - points to next pixel past last pixel read          *\n;*\t\tes:di - points to next pixel past last pixel written\t   *\n;*                                                                         *\n;* WARNINGS:    none                                                       *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/17/1992 PWG : Created.                                             *\n;*   12/01/1992 MBL : Updated to work with latest mask data encoding.      *\n;*   05/27/1993 MCC : Updated to use the new Ghosting fx\t\t   *\n;*   17/01/1993 MCC : Updated for 386, and optimized\t\t\t   *\n;*=========================================================================*\n\tPROC\tNOLANGUAGE Ghost_Priority_Transparent_Draw NEAR\n\n\tmov\tfs,[background]\t\t; get the SEG of the background page\n\tmov\tgs,[maskpage]\t\t; get the SEG of the mask info\n\tmov\tah,[priority]\t\t; keep a copy of priority varible for faster cmp\n\nloop_top:\n\tlodsb\t\t\t\t; get the pixel on the screen\n\tor\tal,al\t\t\t; check to see if al is transparent\n\tje\tshort write_back\t;   if it is go write background\n\tmov\tbl,[gs:di]\t\t; get the mask byte for our pixel\n\t\t\t\t\t; get rid of non-walkable bit and\n\t\t\t\t\t; get rid of scaling id bits\n\tand\tbl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS\n\tcmp\tah,bl\t\t\t; are we more toward the front?\n\tjge\tshort out_pixel\t; if so then write the pixel\nwrite_back:\n\tmov\tal,[fs:di]\t\t; get the pixel to write\nout_pixel:\n\tstosb\t\t\t\t; write the pixel\n\tloop\tloop_top\n\n\tret\n\n\tENDP\n\n\tEND\n\n"
  },
  {
    "path": "REDALERT/LANGUAGE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#ifdef ENGLISH\n#define\tTEXT_ERROR_TIMER\t\t\"Error - Timer system failed to initialise due to system instability. You need to restart Windows.\"\n#define TEXT_SHORT_TITLE                \"Red Alert\"\n#define TEXT_MEMORY_ERROR               \"Error - out of memory.\"\n#define TEXT_ABORT                              \"Abort\"\n#define TEXT_DDRAW_ERROR                \"Error - Unable to allocate primary video buffer - aborting.\"\n#define TEXT_TITLE                              \"Command & Conquer : Red Alert\"\n#define TEXT_VIDEO_ERROR                \"Error - Unable to set the video mode.\"\n#define TEXT_INSUFFICIENT               \"Insufficient Disk Space to run Red Alert.\\n\"\n#define TEXT_MUST_HAVE                  \"You must have %d megabytes of free disk space.\"\n#define TEXT_CRITICALLY_LOW     \"Warning - you are critically low on free disk space for saving games. Do you want to play Red Alert anyway?\"\n#define TEXT_NO_RAM                             \"Insufficient RAM available.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t\t\"\\n\\rIf you have Windows 95 running you should start Red Alert\\r\\nDOS version via the Windows 95 Start Menu.\\n\\rPress any key.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Run SETUP program first.\\n\"\n#define TEXT_NO_MOUSE                   \"Red Alert is unable to detect your mouse driver.\"\n#define TEXT_FILE_ERROR         \"FILE ERROR\"\n#define TEXT_PRESS_KEY                  \"Press any key to retry.\"\n#define TEXT_ESC_KEY                    \"Press <ESC> to exit program.\"\n#define TEXT_TO_EXIT                    \"Press any key to exit program.\"\n#define TEXT_INVALID                    \"Invalid option switch.\\n\"\n#define TEXT_MAP_ERROR                  \"Map Error!\"\n#define TEXT_STOP                               \"Stop\"\n#define TEXT_CONTINUE                   \"Continue\"\n#define TEXT_OPTIONS                    \"Red Alert (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"Parameters:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -DESTNET  = Specify Network Number of destination system\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"              (Syntax: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -SOCKET   = Network Socket ID (0 - 16383)\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -STEALTH  = Hide multiplayer names (\\\"Boss mode\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -MESSAGES = Allow messages from outside this game.\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"\\r\\n\"\n#endif\n\n\n#ifdef GERMAN\n#define TEXT_ERROR_TIMER                \"Fehler - das Timer-System konnte aufgrund einer Instabilitt des Systems nicht initialisiert werden. Bitte starten Sie Windows neu.\"\n#define TEXT_SHORT_TITLE                \"C&C:AR\"\n#define TEXT_MEMORY_ERROR               \"Fehler - Kein Speicher mehr.\"\n#define TEXT_ABORT                      \"Abbrechen\"\n#define TEXT_DDRAW_ERROR                \"Fehler - Kann primren Videopuffer nicht finden - Abbruch.\"\n#define TEXT_TITLE                      \"Command & Conquer : Alarmstufe Rot\"\n#define TEXT_VIDEO_ERROR                \"Fehler - Kann Grafikmodus nicht einstellen.\"\n#define TEXT_INSUFFICIENT               \"Nicht genug Festplattenplatz fr Command & Conquer:AR.\\n\"\n#define TEXT_MUST_HAVE                  \"Sie brauchen %d MByte freien Platz auf der Festplatte.\"\n#define TEXT_CRITICALLY_LOW   \t\t\t \"Nicht genug Festplattenplatz fr Command & Conquer:AR.\\nSie brauchen %d MByte freien Platz auf der Festplatte.\"\n#define TEXT_NO_RAM                     \"Zuwenig Hauptspeicher verfgbar.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t\t\"\\n\\rWenn auf Ihrem Rechner Windows 95 luft,\\n\\rstarten Sie die DOS-Version von Alarmstufe Rot\\n\\rbitte ber das Start-Men von Windows 95.\\n\\rZum Weitermachen beliebige Taste drcken.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Bitte erst das SETUP-Programm starten.\\n\"\n#define TEXT_NO_MOUSE                   \"C&C:AR kann Ihren Maustreiber nicht finden...\"\n#define TEXT_FILE_ERROR       \t\t\t \"DATEIFEHLER\"\n#define TEXT_PRESS_KEY                  \"Beliebige Taste drcken fr erneuten Versuch.\"\n#define TEXT_ESC_KEY                    \"<ESC> drcken, um das Programm zu verlassen.\"\n#define TEXT_TO_EXIT                    \"Beliebige Taste drcken, um das Programm zu verlassen.\"\n#define TEXT_INVALID                    \"Ungltiger Parameter.\\n\"\n#define TEXT_MAP_ERROR                  \"Kartenfehler!\"\n#define TEXT_STOP                       \"Halt\"\n#define TEXT_CONTINUE                   \"Weiter\"\n#define TEXT_OPTIONS                    \"C&C: Alarmstufe Rot (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t \t\t\t\t\t\t\t\t\t \"Parameter:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -DESTNET  = Netzwerkkennung des Zielrechners festlegen\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"              (Syntax: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -SOCKET   = Kennung des Netzwerk-Sockets (0 - 16383)\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -STEALTH  = Namen im Mehrspieler-Modus verstecken (\\\"Boss-Modus\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"  -MESSAGES = Mitteilungen von ausserhalb des Spiels zulassen\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t \"\\r\\n\"\n#endif\n\n\n#ifdef FRENCH\n#define TEXT_ERROR_TIMER                \"Error - L'horloge systme n'a pas pu s'initialiser en raison de l'instabilit du sytme. Vous devez redmarrer Windows.\"\n#define TEXT_SHORT_TITLE                \"Alerte Rouge\"\n#define TEXT_MEMORY_ERROR               \"Erreur - Plus de mmoire.\"\n#define TEXT_ABORT                              \"Interrompre\"\n#define TEXT_DDRAW_ERROR                \" Erreur - Impossible d'allouer le tampon vido principal - Interruption.\"\n#define TEXT_TITLE                              \"Command & Conquer : Alerte Rouge\"\n#define TEXT_VIDEO_ERROR                \" Erreur - Impossible d'tablir le mode vido.\"\n#define TEXT_INSUFFICIENT               \"Espace disque insuffisant pour lancer Command & Conquer.\\n\"\n#define TEXT_MUST_HAVE                  \"Vous devez disposer de %d Mo d'espace disponsible sur le disque dur.\"\n#define TEXT_CRITICALLY_LOW     \"Espace disque insuffisant pour lancer Command & Conquer.\\nVous devez disposer de %d Mo d'espace disponsible sur le disque dur.\"\n#define TEXT_NO_RAM                             \"Mmoire vive (RAM) insuffisante.\\n\"\n#define TEXT_USE_START_MENU\t\t\t\t \"\\n\\rSi vous tes dans Windows 95 vous devez lancer Alerte Rouge\\r\\nDOS  partir du menu Dmarrer de Windows 95.\\n\\rAppuyez sur n'importe quelle touche.\\n\\r\"\n#define TEXT_SETUP_FIRST                \"Lancez d'abord le programme de configuration SETUP.\\n\"\n#define TEXT_NO_MOUSE                   \"Alerte Rouge ne peut pas dtecter votre gestionnaire de souris.\"\n#define TEXT_FILE_ERROR         \"ERREUR DE FICHIER\"\n#define TEXT_PRESS_KEY                  \"Appuyez sur une touche pour recommencer.\"\n#define TEXT_ESC_KEY                    \"Appuyez sur Echap pour quitter le programme.\"\n#define TEXT_TO_EXIT                    \"Appuyez sur une touche pour quitter le programme.\"\n#define TEXT_INVALID                    \"Commande d'option invalide.\\n\"\n#define TEXT_MAP_ERROR                  \"Erreur de carte!\"\n#define TEXT_STOP                               \"Stop\"\n#define TEXT_CONTINUE                   \"Continuer\"\n#define TEXT_OPTIONS                    \"Alerte Rouge (c) 1996, Westwood Studios\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"Paramtres:\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -DESTNET  = Spcifier le numro de rseau du systme de destination\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"              (Syntaxe: DESTNETxx.xx.xx.xx)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -SOCKET   = ID Socket rseau (0 \u0005 16383)\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -STEALTH  = Cacher les noms en mode multijoueurs (\\\"Mode Boss\\\")\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"  -MESSAGES = Autorise les messages extrieurs  ce jeu.\\r\\n\" \\\n\t\t\t\t\t\t\t\t\t\t\"\\r\\n\"\n#endif\n\n"
  },
  {
    "path": "REDALERT/LAYER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LAYER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LAYER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 31, 1994                                                 *\n *                                                                                             *\n *                  Last Update : March 10, 1995 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LayerClass::Sort -- Perform an incremental sort pass on the layer's objects.              *\n *   LayerClass::Sorted_Add -- Adds object in sorted order to layer.                           *\n *   LayerClass::Submit -- Adds an object to a layer list.                                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"layer.h\"\n\n\n/***********************************************************************************************\n * LayerClass::Submit -- Adds an object to a layer list.                                       *\n *                                                                                             *\n *    This routine is used to add an object to the layer list. If the list is full, then the   *\n *    object is not added.                                                                     *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to add.                                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully?                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   05/31/1994 JLB : Allows sorted insert.                                                    *\n *   01/02/1995 JLB : Fixed to work with EMSListOf template.                                   *\n *=============================================================================================*/\nbool LayerClass::Submit(ObjectClass const * object, bool sort)\n{\n\t/*\n\t**\tAdd the object to the layer. Either at the end (if \"sort\" is false) or at the\n\t**\tappropriately sorted position.\n\t*/\n\tif (sort) {\n\t\treturn(Sorted_Add(object));\n\t}\n\treturn(Add((ObjectClass *)object));\n}\n\n\n/***********************************************************************************************\n * LayerClass::Sort -- Handles sorting the objects in the layer.                               *\n *                                                                                             *\n *    This routine is used if the layer objects must be sorted and sorting is to occur now.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Don't call this routine too often since it does take a bit of time to           *\n *             execute. It is a single pass binary sort and thus isn't horribly slow,          *\n *             but it does take some time.                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *   03/10/1995 JLB : Uses comparison operator.                                                *\n *=============================================================================================*/\nvoid LayerClass::Sort(void)\n{\n\tfor (int index = 0; index < Count()-1; index++) {\n\t\tif (*(*this)[index+1] < *(*this)[index]) {\n\t\t\tObjectClass * temp;\n\n\t\t\ttemp = (*this)[index+1];\n\t\t\t(*this)[index+1] = (*this)[index];\n\t\t\t(*this)[index] = temp;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * DynamicVectorClass<T>::Sorted_Add -- Adds object in sorted order to vector.                 *\n *                                                                                             *\n *    Use this routine to add an object to the vector but it will be inserted in sorted        *\n *    order. This depends on the \">\" operator being defined for the vector object.             *\n *                                                                                             *\n * INPUT:   object   -- Reference to the object that will be added to the vector.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added to the vector successfully?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LayerClass::Sorted_Add(ObjectClass const * const object)\n{\n\tif ((unsigned)ActiveCount >= Length()) {\n\t\tif ((IsAllocated || !VectorMax) && GrowthStep > 0) {\n\t\t\tif (!Resize(Length() + GrowthStep)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tFailure to increase the size of the vector is an error condition.\n\t\t\t\t**\tReturn with the error flag.\n\t\t\t\t*/\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIncreasing the size of this vector is not allowed! Bail this\n\t\t\t**\troutine with the error code.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThere is room for the new object now. Add it to the right sorted position.\n\t*/\n\tint index;\n\tfor (index = 0; index < ActiveCount; index++) {\n\t\tif ((*(*this)[index]) > (*object)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tMake room if the insertion spot is not at the end of the vector.\n\t*/\n\tfor (int i = ActiveCount-1; i >= index; i--) {\n\t\t(*this)[i+1] = (*this)[i];\n\t}\n\t(*this)[index] = (ObjectClass *)object;\n\tActiveCount++;\n\treturn(true);\n}\n\n\n"
  },
  {
    "path": "REDALERT/LAYER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LAYER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LAYER.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 31, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 31, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LAYER_H\n#define LAYER_H\n\n#include \"vector.h\"\n\nclass ObjectClass;\n\nclass LayerClass : public DynamicVectorClass<ObjectClass *>\n{\n\tpublic:\n\n\t\t//-----------------------------------------------------------------\n\t\tvoid Sort(void);\n\t\tbool Submit(ObjectClass const * object, bool sort=false);\n\t\tint Sorted_Add(ObjectClass const * const object);\n\n\n\t\tvirtual void Init(void) {Clear();};\n\t\tvirtual void One_Time(void) {};\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/LCW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **    C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *               Project Name : WESTWOOD LIBRARY (PSX)                     *\n *                                                                         *\n *                 File Name : LCWUNCMP.CPP                                *\n *                                                                         *\n *                Programmer : Ian M. Leslie                               *\n *                                                                         *\n *                Start Date : May 17, 1995                                *\n *                                                                         *\n *               Last Update : May 17, 1995    [IML]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n/***************************************************************************\n * LCW_Uncomp -- Decompress an LCW encoded data block.                     *\n *                                                                         *\n * Uncompress data to the following codes in the format b = byte, w = word *\n * n = byte code pulled from compressed data.                              *\n *                                                                         *\n *   Command code, n        |Description                                   *\n * ------------------------------------------------------------------------*\n * n=0xxxyyyy,yyyyyyyy      |short copy back y bytes and run x+3 from dest *\n * n=10xxxxxx,n1,n2,...,nx+1|med length copy the next x+1 bytes from source*\n * n=11xxxxxx,w1            |med copy from dest x+3 bytes from offset w1   *\n * n=11111111,w1,w2         |long copy from dest w1 bytes from offset w2   *\n * n=11111110,w1,b1         |long run of byte b1 for w1 bytes              *\n * n=10000000               |end of data reached                           *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      void * source ptr                                                  *\n *      void * destination ptr                                             *\n *      unsigned long length of uncompressed data                          *\n *                                                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *     unsigned long # of destination bytes written                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *     3rd argument is dummy. It exists to provide cross-platform          *\n *      compatibility. Note therefore that this implementation does not    *\n *      check for corrupt source data by testing the uncompressed length.  *\n *                                                                         *\n * HISTORY:                                                                *\n *    03/20/1995 IML : Created.                                            *\n *=========================================================================*/\nint LCW_Uncomp(void const * source, void * dest, unsigned long )\n{\n\tunsigned char * source_ptr, * dest_ptr, * copy_ptr, op_code, data;\n\tunsigned\t  count, * word_dest_ptr, word_data;\n\n\t/* Copy the source and destination ptrs. */\n\tsource_ptr = (unsigned char*) source;\n\tdest_ptr   = (unsigned char*) dest;\n\n\twhile (1 /*TRUE*/) {\n\n\t\t/* Read in the operation code. */\n\t\top_code = *source_ptr++;\n\n\t\tif (!(op_code & 0x80)) {\n\n\t\t\t/* Do a short copy from destination. */\n\t\t\tcount\t = (op_code >> 4) + 3;\n\t\t\tcopy_ptr = dest_ptr - ((unsigned) *source_ptr++ + (((unsigned) op_code & 0x0f) << 8));\n\n\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t} else {\n\n\t\t\tif (!(op_code & 0x40)) {\n\n\t\t\t\tif (op_code == 0x80) {\n\n\t\t\t\t\t/* Return # of destination bytes written. */\n\t\t\t\t\treturn ((unsigned long) (dest_ptr - (unsigned char*) dest));\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Do a medium copy from source. */\n\t\t\t\t\tcount = op_code & 0x3f;\n\n\t\t\t\t\twhile (count--) *dest_ptr++ = *source_ptr++;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif (op_code == 0xfe) {\n\n\t\t\t\t\t/* Do a long run. */\n\t\t\t\t\tcount = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\tword_data = data = *(source_ptr + 2);\n\t\t\t\t\tword_data  = (word_data << 24) + (word_data << 16) + (word_data << 8) + word_data;\n\t\t\t\t\tsource_ptr += 3;\n\n\t\t\t\t\tcopy_ptr = dest_ptr + 4 - ((unsigned) dest_ptr & 0x3);\n\t\t\t\t\tcount -= (copy_ptr - dest_ptr);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t\tword_dest_ptr = (unsigned*) dest_ptr;\n\n\t\t\t\t\tdest_ptr += (count & 0xfffffffc);\n\n\t\t\t\t\twhile (word_dest_ptr < (unsigned*) dest_ptr) {\n\t\t\t\t\t\t*word_dest_ptr\t\t= word_data;\n\t\t\t\t\t\t*(word_dest_ptr + 1) = word_data;\n\t\t\t\t\t\tword_dest_ptr += 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tcopy_ptr = dest_ptr + (count & 0x3);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (op_code == 0xff) {\n\n\t\t\t\t\t\t/* Do a long copy from destination. */\n\t\t\t\t\t\tcount\t = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *(source_ptr + 2) + ((unsigned) *(source_ptr + 3) << 8);\n\t\t\t\t\t\tsource_ptr += 4;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/* Do a medium copy from destination. */\n\t\t\t\t\t\tcount = (op_code & 0x3f) + 3;\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tsource_ptr += 2;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/LCW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCW_H\n#define LCW_H\n\n\nint LCW_Uncomp(void const * source, void * dest, unsigned long length=0);\n\nextern \"C\" {\nint __cdecl LCW_Comp(void const * source, void * dest, int length);\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/LCWCOMP.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\lcwcomp.asv   5.0   11 Nov 1996 09:40:34   JOE_BOSTIC  $\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Library routine                          *\n;*                                                                         *\n;*                    File Name : COMPRESS.ASM                             *\n;*                                                                         *\n;*                   Programmer : Louis Castle                             *\n;*                                                                         *\n;*                  Last Update : 20 August, 1990   [CY]                   *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*                                                                         *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n;IDEAL\n;P386\n;MODEL USE32 FLAT\n\n.MODEL FLAT\n\n;GLOBAL    C LCW_Comp          :NEAR\nexterndef C LCW_Comp:near\n\n;CODESEG\n.code\n\n; ----------------------------------------------------------------\n;\n; Here are prototypes for the routines defined within this module:\n;\n; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);\n;\n; ----------------------------------------------------------------\n\n\n\n;***********************************************************\n;\n; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)\n;\n; returns the size of the compressed data in bytes\n;\n;*\nLCW_Comp proc C source:DWORD, dest:DWORD, datasize:DWORD\n\n\t;USES ebx,ecx,edx,edi,esi\n\n\t;ARG\tsource:DWORD\n\t;ARG\tdest:DWORD\n\t;ARG\tdatasize:DWORD\n\n\tLOCAL inlen:DWORD\n\tLOCAL a1stdest:DWORD\n\tLOCAL a1stsrc:DWORD\n\tLOCAL lenoff:DWORD\n\tLOCAL ndest:DWORD\n\tLOCAL count:DWORD\n\tLOCAL matchoff:DWORD\n\tLOCAL end_of_data:DWORD\n\n\tpushad\n\n\tcld\n \tmov\tedi,[dest]\n \tmov\tesi,[source]\n \tmov\tedx,[datasize]\t\t; get length of data to compress\n\n;\tmov\tax,ds\n;\tmov\tes,ax\n\n;\n; compress data to the following codes in the format b = byte, w = word\n; n = byte code pulled from compressed data\n;   Bit field of n\t\tcommand\t\tdescription\n; n=0xxxyyyy,yyyyyyyy\t\tshort run\tback y bytes and run x+3\n; n=10xxxxxx,n1,n2,...,nx+1\tmed length\tcopy the next x+1 bytes\n; n=11xxxxxx,w1\t\t\tmed run\t\trun x+3 bytes from offset w1\n; n=11111111,w1,w2\t\tlong run\trun w1 bytes from offset w2\n; n=10000000\t\t\tend\t\tend of data reached\n;\n\tcld\t\t\t; make sure all string commands are forward\n\tmov\tebx,esi\n\tadd\tebx,edx\n\tmov\t[end_of_data],ebx\n\tmov\t[inlen],1\t; set the in-length flag\n\tmov\t[a1stdest],edi\t; save original dest offset for size calc\n\tmov\t[a1stsrc],esi\t; save offset of first byte of data\n\tmov\t[lenoff],edi\t; save the offset of the legth of this len\n\tsub\teax,eax\n\tmov\tal,081h\t\t; the first byte is always a len\n\tstosb\t\t\t; write out a len of 1\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; save it\n_loop:\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,[a1stsrc]\t; get the offset to the first byte of data\n\tmov\t[count],1\t; set the count of run to 0\nsearchloop:\n\tsub\teax,eax\n\tmov\tal,[esi]\t; get the current byte of data\n\tcmp\tal,[esi+64]\n\tjne\tshort notrunlength\n\n\tmov\tebx,edi\n\n\tmov\tedi,esi\n\tmov\tecx,[end_of_data]\n\tsub\tecx,edi\n   \trepe\tscasb\n\tdec\tedi\n\tmov\tecx,edi\n\tsub\tecx,esi\n\tcmp\tecx,65\n\tjb\tshort notlongenough\n\n\tmov\t[DWORD PTR inlen],0\t; clear the in-length flag\n\tmov\tesi,edi\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\n\tmov\tah,al\n\tmov\tal,0FEh\n\tstosb\n\txchg\tecx,eax\n\tstosw\n\tmov\tal,ch\n\tstosb\n\n\tmov\t[ndest],edi\t; save offset of compressed data\n\tmov\tedi,ebx\n\tjmp\tsearchloop\nnotlongenough:\n\tmov\tedi,ebx\nnotrunlength:\n\noploop:\n\tmov\tecx,esi\t\t; get the address of the last byte +1\n\tsub\tecx,edi\t\t; get the total number of bytes left to comp\n\tjz\tshort searchdone\n\n\trepne\tscasb\t\t; look for a match\n\tjne\tshort searchdone\t; if we don't find one we're done\n\n\tmov\tebx,[count]\n\tmov\tah,[esi+ebx-1]\n\tcmp\tah,[edi+ebx-2]\n\n\tjne\toploop\n\n\tmov\tedx,esi\t\t; save this spot for the next search\n\tmov\tebx,edi\t\t; save this spot for the length calc\n\tdec\tedi\t\t; back up one for compare\n\tmov\tecx,[end_of_data]\t\t; get the end of data\n\tsub\tecx,esi\t\t; sub current source for max len\n\n\trepe\tcmpsb\t\t; see how many bytes match\n\n; start of change MH 9-24-91\n\tjne\tshort notend\t; if found mismatch then di - bx = match count\n\n\tinc\tedi\t\t; else cx = 0 and di + 1 - bx = match count\n\nnotend:\n; end of change MH 9-24-91\n\n\tmov\tesi,edx\t\t; restore si\n\tmov\teax,edi\t\t; get the dest\n\tsub\teax,ebx\t\t; sub the start for total bytes that match\n\tmov\tedi,ebx\t\t; restore dest\n\tcmp\teax,[count]\t; see if its better than before\n\tjb\tsearchloop\t; if not keep looking\n\n\tmov\t[count],eax\t; if so keep the count\n\tdec\tebx\t\t; back it up for the actual match offset\n\tmov\t[matchoff],ebx ; save the offset for later\n\tjmp\tsearchloop\t; loop until we searched it all\n\nsearchdone:\n\n\tmov\tecx,[count]\t; get the count of the longest run\n\tmov\tedi,[ndest]\t; get the offset of our compressed data\n\tcmp\tecx,2\t\t; see if its not enough run to matter\n\tjbe\tshort lenin\t\t; if its 0,1, or 2 its too small\n\n\tcmp\tecx,10\t\t; if not, see if it would fit in a short\n\tja\tshort medrun\t; if not, see if its a medium run\n\n\tmov\teax,esi\t\t; if its short get the current address\n\tsub\teax,[matchoff] ; sub the offset of the match\n\tcmp\teax,0FFFh\t; if its less than 12 bits its a short\n\tja\tshort medrun\t; if its not, its a medium\n\nshortrun:\n\tsub\tebx,ebx\n\tmov\tbl,cl\t\t; get the length (3-10)\n\tsub\tbl,3\t\t; sub 3 for a 3 bit number 0-7\n\tshl\tbl,4\t\t; shift it left 4\n\tadd\tah,bl\t\t; add in the length for the high nibble\n\txchg\tah,al\t\t; reverse the bytes for a word store\n\tjmp\tshort srunnxt\t; do the run fixup code\n\nmedrun:\n\tcmp\tecx,64\t\t; see if its a short run\n\tja\tshort longrun\t; if not, oh well at least its long\n\n\tsub\tcl,3\t\t; back down 3 to keep it in 6 bits\n\tor\tcl,0C0h\t\t; the highest bits are always on\n\tmov\tal,cl\t\t; put it in al for the stosb\n\tstosb\t\t\t; store it\n\tjmp\tshort medrunnxt ; do the run fixup code\n\nlenin:\n\tcmp\t[DWORD PTR inlen],0\t; is it doing a length?\n\tjnz\tshort len\t; if so, skip code\n\nlenin1:\n\tmov\t[lenoff],edi\t; save the length code offset\n\tmov\tal,80h\t\t; set the length to 0\n\tstosb\t\t\t; save it\n\nlen:\n\tmov\tebx,[lenoff]\t; get the offset of the length code\n\tcmp\tBYTE PTR [ebx],0BFh\t; see if its maxed out\n\tje\tlenin1\t; if so put out a new len code\n\nstolen:\n\tinc\tBYTE PTR [ebx] ; inc the count code\n\tlodsb\t\t\t; get the byte\n\tstosb\t\t\t; store it\n\tmov\tDWORD PTR [inlen],1\t; we are now in a length so save it\n\tjmp\tshort nxt\t; do the next code\n\nlongrun:\n\tmov\tal,0ffh\t\t; its a long so set a code of FF\n\tstosb\t\t\t; store it\n\n\tmov\teax,[count]\t; send out the count\n\tstosw\t\t\t; store it\nmedrunnxt:\n\tmov\teax,[matchoff] ; get the offset\n\tsub\teax,[a1stsrc]\t; make it relative tot he start of data\nsrunnxt:\n\tstosw\t\t\t; store it\n; this code common to all runs\n\tadd\tesi,[count]\t; add in the length of the run to the source\n\tmov\t[DWORD PTR inlen],0\t; set the in leght flag to false\n\n;=======================================================================\n\nnxt:\n\tcmp\tesi,[end_of_data]\t\t; see if we did the whole pic\n\tjae\tshort _out\t\t; if so, cool! were done\n\n\tjmp\t_loop\n\n_out:\n\tmov\tax,080h\t\t; remember to send an end of data code\n\tstosb\t\t\t; store it\n\tmov\teax,edi\t\t; get the last compressed address\n\tsub\teax,[a1stdest]\t; sub the first for the compressed size\n\n\tpopad\n\tret\n\nLCW_Comp endp\n\n\nEND\n"
  },
  {
    "path": "REDALERT/LCWPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCWPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LCWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LCWPipe::LCWPipe -- Constructor for the LCW processor pipe.                               *\n *   LCWPipe::Put -- Send some data through the LCW processor pipe.                            *\n *   LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lcwpipe.h\"\n#include\t\"lcw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LCWPipe::LCWPipe -- Constructor for the LCW processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LCWPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWPipe::LCWPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWPipe::~LCWPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LCWPipe::Put -- Send some data through the LCW processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LCW processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < ((int)sizeof(BlockHeader)-Counter)) ? slen : ((int)sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tLCW_Uncomp(Buffer, Buffer2);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tint len = LCW_Comp(Buffer, Buffer2, BlockSize);\n\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tint len = LCW_Comp(source, Buffer2, BlockSize);\n\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LCWPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LCW decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tint len = LCW_Comp(Buffer, Buffer2, Counter);\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "REDALERT/LCWPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCWPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCWPIPE_H\n#define LCWPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LCW compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LCWPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLCWPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LCWPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLCW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLCWPipe(LCWPipe & rvalue);\n\t\tLCWPipe & operator = (LCWPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LCWSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCWSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LCWStraw::Get -- Fetch data through the LCW processor.                                    *\n *   LCWStraw::LCWStraw -- Constructor for LCW straw object.                                   *\n *   LCWStraw::~LCWStraw -- Destructor for the LCW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lcwstraw.h\"\n#include\t\"lcw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LCWStraw::LCWStraw -- Constructor for LCW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LCW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWStraw::LCWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LCWStraw::~LCWStraw -- Destructor for the LCW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLCWStraw::~LCWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LCWStraw::Get -- Fetch data through the LCW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LCWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tvoid * ptr = &Buffer[(BlockSize+SafetyMargin) - BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(ptr, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tLCW_Uncomp(ptr, Buffer);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tBlockHeader.CompCount = (unsigned short)LCW_Comp(Buffer, &Buffer2[sizeof(BlockHeader)], BlockHeader.UncompCount);\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/LCWSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCWSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LCWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LCWSTRAW_H\n#define LCWSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LCW compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LCWStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLCWStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LCWStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLCW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLCWStraw(LCWStraw & rvalue);\n\t\tLCWStraw & operator = (LCWStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LCWUNCMP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LCWUNCMP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **    C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *               Project Name : WESTWOOD LIBRARY (PSX)                     *\n *                                                                         *\n *                 File Name : LCWUNCMP.CPP                                *\n *                                                                         *\n *                Programmer : Ian M. Leslie                               *\n *                                                                         *\n *                Start Date : May 17, 1995                                *\n *                                                                         *\n *               Last Update : May 17, 1995    [IML]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\nextern \"C\" {\n\n/***************************************************************************\n * LCW_UNCOMPRESS -- Decompress an LCW encoded data block.                 *\n *                                                                         *\n * Uncompress data to the following codes in the format b = byte, w = word *\n * n = byte code pulled from compressed data.                              *\n *                                                                         *\n * Command code, n        |Description                                     *\n * ------------------------------------------------------------------------*\n * n=0xxxyyyy,yyyyyyyy    |short copy back y bytes and run x+3   from dest *\n * n=10xxxxxx,n1,n2,...,nx+1|med length copy the next x+1 bytes from source*\n * n=11xxxxxx,w1          |med copy from dest x+3 bytes from offset w1     *\n * n=11111111,w1,w2       |long copy from dest w1 bytes from offset w2     *\n * n=11111110,w1,b1       |long run of byte b1 for w1 bytes                *\n * n=10000000             |end of data reached                             *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      void * source ptr                                                  *\n *      void * destination ptr                                             *\n *      unsigned long length of uncompressed data                          *\n *                                                                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *     unsigned long # of destination bytes written                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *     3rd argument is dummy. It exists to provide cross-platform          *\n *      compatibility. Note therefore that this implementation does not    *\n *      check for corrupt source data by testing the uncompressed length.  *\n *                                                                         *\n * HISTORY:                                                                *\n *    03/20/1995 IML : Created.                                            *\n *=========================================================================*/\nunsigned long __cdecl LCW_Uncompress (void * source, void * dest, unsigned long )\n//unsigned long LCW_Uncompress (void * source, void * dest, unsigned long length)\n{\n\tunsigned char * source_ptr, * dest_ptr, * copy_ptr, op_code, data;\n\tunsigned\t  count, * word_dest_ptr, word_data;\n\n\t/* Copy the source and destination ptrs. */\n\tsource_ptr = (unsigned char*) source;\n\tdest_ptr   = (unsigned char*) dest;\n\n\twhile (1 /*TRUE*/) {\n\n\t\t/* Read in the operation code. */\n\t\top_code = *source_ptr++;\n\n\t\tif (!(op_code & 0x80)) {\n\n\t\t\t/* Do a short copy from destination. */\n\t\t\tcount\t = (op_code >> 4) + 3;\n\t\t\tcopy_ptr = dest_ptr - ((unsigned) *source_ptr++ + (((unsigned) op_code & 0x0f) << 8));\n\n\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t} else {\n\n\t\t\tif (!(op_code & 0x40)) {\n\n\t\t\t\tif (op_code == 0x80) {\n\n\t\t\t\t\t/* Return # of destination bytes written. */\n\t\t\t\t\treturn ((unsigned long) (dest_ptr - (unsigned char*) dest));\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/* Do a medium copy from source. */\n\t\t\t\t\tcount = op_code & 0x3f;\n\n\t\t\t\t\twhile (count--) *dest_ptr++ = *source_ptr++;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif (op_code == 0xfe) {\n\n\t\t\t\t\t/* Do a long run. */\n\t\t\t\t\tcount = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\tword_data = data = *(source_ptr + 2);\n\t\t\t\t\tword_data  = (word_data << 24) + (word_data << 16) + (word_data << 8) + word_data;\n\t\t\t\t\tsource_ptr += 3;\n\n\t\t\t\t\tcopy_ptr = dest_ptr + 4 - ((unsigned) dest_ptr & 0x3);\n\t\t\t\t\tcount -= (copy_ptr - dest_ptr);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t\tword_dest_ptr = (unsigned*) dest_ptr;\n\n\t\t\t\t\tdest_ptr += (count & 0xfffffffc);\n\n\t\t\t\t\twhile (word_dest_ptr < (unsigned*) dest_ptr) {\n\t\t\t\t\t\t*word_dest_ptr\t\t= word_data;\n\t\t\t\t\t\t*(word_dest_ptr + 1) = word_data;\n\t\t\t\t\t\tword_dest_ptr += 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tcopy_ptr = dest_ptr + (count & 0x3);\n\t\t\t\t\twhile (dest_ptr < copy_ptr) *dest_ptr++ = data;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (op_code == 0xff) {\n\n\t\t\t\t\t\t/* Do a long copy from destination. */\n\t\t\t\t\t\tcount\t = *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *(source_ptr + 2) + ((unsigned) *(source_ptr + 3) << 8);\n\t\t\t\t\t\tsource_ptr += 4;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/* Do a medium copy from destination. */\n\t\t\t\t\t\tcount = (op_code & 0x3f) + 3;\n\t\t\t\t\t\tcopy_ptr = (unsigned char*) dest + *source_ptr + ((unsigned) *(source_ptr + 1) << 8);\n\t\t\t\t\t\tsource_ptr += 2;\n\n\t\t\t\t\t\twhile (count--) *dest_ptr++ = *copy_ptr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "REDALERT/LED.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\led.h_v   4.42   04 Jul 1996 16:10:40   JOE_BOSTIC  $ */\n\n#ifndef LED_H\n#define LED_H\n\nclass LEDClass\n{\n\tpublic:\n\t\ttypedef enum ControlType {\n\t\t\tLED_NOCHANGE,\t\t\t// Do nothing (just query).\n\t\t\tLED_OFF,\t\t\t\t\t// Turn LED off.\n\t\t\tLED_ON,\t\t\t\t\t// Turn LED on.\n\t\t\tLED_TOGGLE\t\t\t\t// Toggle LED state.\n\t\t} ControlType;\n\n\tprotected:\n\t\tstatic int Shift_Control(ControlType control, char bit);\n\n\tpublic:\n\t\tstatic int Scroll_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x01);};\n\t\tstatic int Caps_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x02);};\n\t\tstatic int Num_Lock(ControlType control=LED_TOGGLE) {return Shift_Control(control, 0x04);};\n\n\tprivate:\n\t\tstatic void Send_To_Keyboard(unsigned char val);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/LINK.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LINK.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINK.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LinkClass::Add -- This object adds itself to the given list                               *\n *   LinkClass::Add_Head -- This gadget makes itself the head of the given list.               *\n *   LinkClass::Add_Tail -- Add myself to the end of the given list.                           *\n *   LinkClass::Get_Next -- Fetches the next object in list.                                   *\n *   LinkClass::Get_Prev -- Fetches previous object in linked list.                            *\n *   LinkClass::Head_Of_List -- Finds the head of the list.                                    *\n *   LinkClass::LinkClass -- Copy constructor for linked list object.                          *\n *   LinkClass::Remove -- Removes the specified object from the list.                          *\n *   LinkClass::Tail_Of_List -- Scans for the object at the end of the list.                   *\n *   LinkClass::Zap -- Forces the link pointers to NULL.                                       *\n *   LinkClass::operator= -- Assignment operator for linked list class object.                 *\n *   LinkClass::~LinkClass -- Default destructor for linked list object.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"link.h\"\n\n\n/***********************************************************************************************\n * LinkClass::LinkClass -- Copy constructor for linked list object.                            *\n *                                                                                             *\n *    This copy constructor, unlike the assignment operator, doesn't have to deal with an      *\n *    already initialized and legal link object to the left of the \"=\". It merely puts the     *\n *    destination object into the same list as the source object.                              *\n *                                                                                             *\n * INPUT:   link  -- Reference to the object on the right of the \"=\".                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass::LinkClass(LinkClass const & link) :\n\tNext(0), Prev(0)\n{\n\t/*\n\t**\tAdd this object to the same list that the copy object\n\t**\tresides in.\n\t*/\n\tAdd((LinkClass &)link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::~LinkClass -- Default destructor for linked list object.                         *\n *                                                                                             *\n *    This default destructor will remove the object from any linked list it may be part of.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass::~LinkClass(void)\n{\n\tRemove();\n}\n\n\n/***********************************************************************************************\n * LinkClass::Zap -- Forces the link pointers to NULL.                                         *\n *                                                                                             *\n *    This routine will \"zap\" out the link pointers. This is usually necessary when the link   *\n *    pointers start in an undefined state, but we KNOW that they aren't pointing to anything  *\n *    valid. In such a case it becomes necessary to zap them so that when the object is added  *\n *    to a list, it will be added correctly.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid LinkClass::Zap(void)\n{\n\tNext = 0;\n\tPrev = 0;\n}\n\n\n/***********************************************************************************************\n * LinkClass::operator= -- Assignment operator for linked list class object.                   *\n *                                                                                             *\n *    The assignment operator makes sure that the previous and next pointers remain valid.     *\n *    Because this class only consists of pointers, the assignment operator doesn't actually   *\n *    transfer any data from the source object. It merely makes the destination object part    *\n *    of the same list as the source object. In essence, this is transferring information      *\n *    but not the actual values.                                                               *\n *                                                                                             *\n *    If the destination object is already part of another list, it is removed from that list  *\n *    before being added to the source object's list. This ensures that either list remains    *\n *    in a valid condition.                                                                    *\n *                                                                                             *\n * INPUT:   link  -- The object to the right of the \"=\" operator.                              *\n *                                                                                             *\n * OUTPUT:  Returns a reference to the rightmost object -- per standard assignment rules.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::operator = (LinkClass const & link)\n{\n\tif (&link == this) return(*this);\n\n\tRemove();\n\tAdd((LinkClass &)link);\n\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Get_Next -- Fetches the next object in list.                                     *\n *                                                                                             *\n *    This routine will return with a pointer to the next object in the list. If there are     *\n *    no more objects, then NULL is returned.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with pointer to next object in list or NULL if at end of list.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Get_Next(void) const\n{\n\treturn(Next);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Get_Prev -- Fetches previous object in linked list.                              *\n *                                                                                             *\n *    Use this routine to get a pointer to the previous object in the linked list. If there    *\n *    are no previous objects (such as at the head of the list), then NULL is returned.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the previous object in the list or NULL if none.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Get_Prev(void) const\n{\n\treturn(Prev);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Head_Of_List -- Finds the head of the list.                                      *\n *                                                                                             *\n *    Use this routine to scan for and return a reference to the object at the head of the     *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Head_Of_List(void)\n{\n\tLinkClass * link = this;\n\twhile (link->Prev) {\n\t\tlink = link->Prev;\n\t\tif (link == this) break;\t\t// Safety check\n\t}\n\treturn(*link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Tail_Of_List -- Scans for the object at the end of the list.                     *\n *                                                                                             *\n *    Use this routine to scan for and return a reference to the object at the end of the      *\n *    list.                                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the end of the list.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Tail_Of_List(void)\n{\n\tLinkClass * link = this;\n\twhile (link->Next) {\n\t\tlink = link->Next;\n\t\tif (link == this) break;\t\t// Safety check\n\t}\n\treturn(*link);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add -- This object adds itself to the given list                                 *\n *                                                                                             *\n *    Use this routine to add a link object to the list, but to be added right after the       *\n *    given link. This allows inserting a link in the middle of the chain. A quite necessary   *\n *    ability if the chain is order dependant (e.g., the gadget system).                       *\n *                                                                                             *\n * INPUT:   list -- gadget object to add this one to                                           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the head of the list.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tSave ptr to next gadget.\n\t*/\n\tptr = list.Next;\n\n\t/*\n\t**\tLink myself in after 'list'.\n\t*/\n\tlist.Next = this;\n\tPrev = &list;\n\n\t/*\n\t**\tLink myself to next gadget, if there is one.\n\t*/\n\tNext = ptr;\n\tif (ptr) {\n\t\tptr->Prev = this;\n\t}\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add_Head -- This gadget makes itself the head of the given list.                 *\n *                                                                                             *\n * INPUT:   list -- the list to make myself the head of                                        *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list. This should be     *\n *          the same object that is passed in.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add_Head(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tGet head of given list.\n\t*/\n\tptr = &list.Head_Of_List();\n\n\t/*\n\t**\tLink myself in front of it.\n\t*/\n\tptr->Prev = this;\n\tNext = ptr;\n\tPrev = NULL;\n\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * LinkClass::Add_Tail -- Add myself to the end of the given list.                             *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  the head of the list                                                               *\n *                                                                                             *\n * WARNINGS:   The previous and next pointers for the added object MUST have been properly     *\n *             initialized for this routine to work correctly.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & LinkClass::Add_Tail(LinkClass & list)\n{\n\tLinkClass * ptr;\n\n\t/*\n\t**\tGet head of given list.\n\t*/\n\tptr = &list.Tail_Of_List();\n\n\t/*\n\t**\tLink myself in front of it.\n\t*/\n\tptr->Next = this;\n\tPrev = ptr;\n\tNext = NULL;\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * LinkClass::Remove -- Removes the specified object from the list.                            *\n *                                                                                             *\n *    This routine will remove the specified object from the list of objects. Because of the   *\n *    previous and next pointers, it is possible to remove an object from the list without     *\n *    knowing the head of the list. To do this, just call Remove() with the parameter of       *\n *    \"this\".                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the new head of list.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass * LinkClass::Remove(void)\n{\n\tLinkClass * head = &Head_Of_List();\n\tLinkClass * tail = &Tail_Of_List();\n\n\tif (Prev) {\n\t\tPrev->Next = Next;\n\t}\n\tif (Next) {\n\t\tNext->Prev = Prev;\n\t}\n\tPrev = 0;\n\tNext = 0;\n\n\tif (head==this) {\n\t\tif (tail==this) {\n\t\t\treturn(0);\n\t\t}\n\t\treturn(&tail->Head_Of_List());\n\t}\n\treturn(head);\n}\n\n\n"
  },
  {
    "path": "REDALERT/LINK.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LINK.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINK.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LINK_H\n#define LINK_H\n\n\n/*\n**\tThis implements a simple linked list. It is possible to add, remove, and traverse the\n**\tlist. Since this is a doubly linked list, it is possible to remove an entry from the\n**\tmiddle of an existing list.\n*/\nclass LinkClass\n{\n\tpublic:\n\t\tLinkClass(NoInitClass const &) {};\n\t\tLinkClass(void) : Next(0), Prev(0) {};\n\t\tvirtual ~LinkClass(void);\n\n\t\tvirtual LinkClass * Get_Next(void) const;\n\t\tvirtual LinkClass * Get_Prev(void) const;\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual LinkClass & Head_Of_List(void);\n\t\tvirtual LinkClass & Tail_Of_List(void);\n\t\tvirtual void Zap(void);\n\t\tvirtual LinkClass * Remove(void);\n\n\t\tLinkClass & operator=(LinkClass const & link);\t\t// Assignment operator.\n\t\tLinkClass(LinkClass const & link);\t\t\t\t\t\t// Copy constructor.\n\n\tprivate:\n\t\t/*\n\t\t**\tPointers to previous and next link objects in chain.\n\t\t*/\n\t\tLinkClass * Next;\n\t\tLinkClass * Prev;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/LINT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LINT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LINT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 03/28/96                                                     *\n *                                                                                             *\n *                  Last Update : March 28, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n// overloading data member (e.g., IsToRedraw)\n//lint -e1516\n\n// function distinguishing error (actually not an error when conversion operators are used).\n//lint -e1053\n\n\n/*\n**\tThe current version of Lint doesn't know how to deal with conversion operators. It\n**\terroneously generates this error message as a result. Unfortunately, we have to throw\n**\tout the baby with the bathwater on this one.\n*/\n//lint -e58 -e56\n\n/*\n**\tHiding a non virtual member function is generally ok.\n*/\n//lint -e1511\n\n/*\n**\tThe warning about not initializing a member during construction is\n**\tvalid. However, C&C takes advantage of this by using the in place\n**\tnew operator during the load game process. Disable the warning, but\n**\tgrudgingly.\n*/\n//lint -e1401\n\n/*\n**\tDisable warning about non virtual base class destructor for these objects.\n*/\n//lint -esym(1509,GraphicBufferClass,GraphicViewPortClass,BufferClass,VideoViewPortClass,GetCDClass)\n//lint -esym(1509,BasicTimerClass,FlyClass,FuseClass,StageClass,FlasherClass,CargoClass,DoorClass)\n//lint -esym(1509,AbstractTypeClass)\n\n/*\n** The \"unusual cast\" warning is the result of derived casting. This is\n** because there is no \"dynamic_cast<>\" implemented in Watcom (version 10.5).\n*/\n//lint -e740 -e571\n\n/*\n**\t\"function not previously declared inline\" is probably not worth noting.\n*/\n//lint -e1727\n\n/*\n**\tAllow sub-integer loss of precision. This will allow assigning ints to\n**\tchars without warning.\n*/\n//lint -e734\n\n/*\n**\tShifting an integer left is always ok.\n*/\n//lint -e701 -e703\n\n/*\n**\tAllow repeated include files. The body of the include file should be\n**\tcoded to ensure that it is processed only once.\n*/\n//lint -e537\n\n/*\n**\tImplicitly converting an enum to an integer is almost always ok.\n*/\n//lint -e641\n\n/*\n**\tIt is possible to have template functions for \"++\" and \"--\" that\n**\tdon't require one of the parameters to be a class object.\n*/\n//lint -e1042\n\n/*\n**\tRedundant declarations are ok. They are a bit harder to maintain,\n**\tbut they facilitate keeping modules less interdependant (include\n**\tfile wise).\n*/\n//lint -e963 -e762 -e763\n\n/*\n**\tNot having a default constructor is ok.\n*/\n//lint -e1712\n\n/*\n**\tPrivate constructors are ok. In fact, they are necessary if the\n**\tclass object must never be instantiated outside of the class\n**\titself.\n*/\n//lint -e1704\n\n/*\n**\tIgnoring the return value from a function is ok. It is very\n**\tcommon for certain side-effect type functions.\n*/\n//lint -e534\n\n/*\n**\tImplicitly converting from a signed to an unsigned parameter (or\n**\tvisa versa) is ok.\n*/\n//lint -e732 -e502 -e713 -e737 -eau\n\n/*\n**\tAllow functions to overload and hide base functions. This is a\n**\ttechnique of inheritance that handles function parameter changes.\n*/\n//lint -e1411\n\n/*\n**\tIf a switch statement doesn't have a case for every value (enums)\n**\tbut it does have a \"default\" case, then don't warn about it.\n*/\n//lint -e788\n\n/*\n**\tIf bitwize arithmetic is performed on compatible enumeration types,\n**\tthen don't complain. Many enums are used in this fashion.\n*/\n//lint -e655 -e656\n\n/*\n**\tIf a data member is not explicitly initialized in the initializer\n**\tlist, this is ok.\n*/\n//lint -e1542\n\n/*\n**\tCalling \"new\" when not part of an assignment operation can be valid. This\n**\tis true if the \"new\" operator has been overloaded and the class keeps\n**\ttrack of itself.\n*/\n//lint -e522\n\n/*\n**\tA class that is zero bytes long is ok. This is how method classes\n**\tusually work.\n*/\n//lint -e1501\n\n/*\n**\tBoolean passed to function is ok.\n*/\n//lint -e730\n\n/*\n**\tSigned/unsigned mix with relational... ignore for now.\n*/\n//lint -e574\n\n"
  },
  {
    "path": "REDALERT/LIST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LIST.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LIST.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 23, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ListClass::Add -- This object adds itself to the given list                               *\n *   ListClass::Add_Head -- This gadget makes itself the head of the given list.               *\n *   ListClass::Add_Item -- Adds a text item (as number) to the list box.                      *\n *   ListClass::Add_Item -- Adds an item to the list box.                                      *\n *   ListClass::Add_Scroll_Bar -- Adds a scroll bar to the list box.                           *\n *   ListClass::Add_Tail -- Add myself to the end of the given list.                           *\n *   ListClass::Bump -- Bumps the list box up/down one \"page\".                                 *\n *   ListClass::Current_Index -- Fetches the current selected index.                           *\n *   ListClass::Current_Item -- Fetches pointer to current item string.                        *\n *   ListClass::Draw_Entry -- Draws a list box text line as indicated.                         *\n *   ListClass::Draw_Me -- Draws the listbox.                                                  *\n *   ListClass::Get_Item -- Fetches an arbitrary item string.                                  *\n *   ListClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                 *\n *   ListClass::Remove -- Removes the specified object from the list.                          *\n *   ListClass::Remove_Item -- Remove specified text from list box.                            *\n *   ListClass::Remove_Scroll_Bar -- Removes the scroll bar if present                         *\n *   ListClass::Set_Selected_Index -- Set the top of the listbox to index specified.           *\n *   ListClass::Set_Tabs -- Sets the tab stop list to be used for text printing.               *\n *   ListClass::Set_View_Index -- Sets the top line for the current list view.                 *\n *   ListClass::Step -- Moves the list view one line in direction specified.                   *\n *   ListClass::Step_Selected_Index -- Change the listbox top line in direction specified.     *\n *   ListClass::~ListClass -- Destructor for list class objects.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***************************************************************************\n * ListClass::ListClass -- class constructor                               *\n *                                                                         *\n * INPUT:            id               button ID                            *\n *                                                                         *\n *                     x,y            upper-left corner, in pixels         *\n *                                                                         *\n *                     w,h            width, height, in pixels             *\n *                                                                         *\n *                     list            ptr to array of char strings to list*\n *                                                                         *\n *                   flags, style   flags for mouse, style of listbox      *\n *                                                                         *\n * OUTPUT:           none.                                                 *\n *                                                                         *\n * WARNINGS:         none.                                                 *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nListClass::ListClass (int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTRELEASE | KEYBOARD, false),\n\tUpGadget(0, up, x+w, y),\n\tDownGadget(0, down, x+w, y+h),\n\tScrollGadget(0, x+w, y, 0, h, true)\n{\n\t/*\n\t**\tSet preliminary values for the slider related gadgets. They don't automatically\n\t**\tappear at this time, but there are some values that can be pre-filled in.\n\t*/\n\tUpGadget.X -= UpGadget.Width;\n\tDownGadget.X -= DownGadget.Width;\n\tDownGadget.Y -= DownGadget.Height;\n\tScrollGadget.X -= max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = Y+UpGadget.Height;\n\tScrollGadget.Height -= UpGadget.Height + DownGadget.Height;\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n\n\t/*\n\t**\tSet the list box to a default state.\n\t*/\n\tTextFlags = flags;\n\tIsScrollActive = false;\n\tTabs = 0;\n\tSelectedIndex = 0;\n\tCurrentTopIndex = 0;\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\tLineHeight = FontHeight+FontYSpacing-1;\n\tLineCount = (h-1) / LineHeight;\n}\n\n\nListClass::ListClass(ListClass const & list) :\n\tControlClass(list),\n\tTextFlags(list.TextFlags),\n\tTabs(list.Tabs),\n\tList(list.List),\n\tLineHeight(list.LineHeight),\n\tLineCount(list.LineCount),\n\tIsScrollActive(list.IsScrollActive),\n\tUpGadget(list.UpGadget),\n\tDownGadget(list.DownGadget),\n\tScrollGadget(list.ScrollGadget),\n\tSelectedIndex(list.SelectedIndex),\n\tCurrentTopIndex(list.CurrentTopIndex)\n{\n\tUpGadget.Make_Peer(*this);\n\tDownGadget.Make_Peer(*this);\n\tScrollGadget.Make_Peer(*this);\n}\n\n\nvoid ListClass::Set_Position(int x, int y)\n{\n\tUpGadget.X = x + Width - UpGadget.Width;\n\tUpGadget.Y = y;\n\tDownGadget.X = x + Width - DownGadget.Width;\n\tDownGadget.Y = y + Height - DownGadget.Height;\n\tScrollGadget.X = x + Width - max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = y + UpGadget.Height;\n\tScrollGadget.Height = Height - (UpGadget.Height + DownGadget.Height);\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n}\n\n\n/***********************************************************************************************\n * ListClass::~ListClass -- Destructor for list class objects.                                 *\n *                                                                                             *\n *    This is the destructor for list objects. It handles removing anything it might have      *\n *    allocated. This is typically the scroll bar.                                             *\n *                                                                                             *\n * INPUT:      none                                                                            *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nListClass::~ListClass(void)\n{\n\tRemove_Scroll_Bar();\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Item -- Adds an item to the list box.                                        *\n *                                                                                             *\n *    This will add the specified string to the list box. The string is added to the end       *\n *    of the list.                                                                             *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to add to the list box.                          *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint ListClass::Add_Item(char const * text)\n{\n\tif (text) {\n\t\tList.Add(text);\n\t\tFlag_To_Redraw();\n\n\t\t/*\n\t\t**\tAdd scroll gadget if the list gets too large to display all of the items\n\t\t**\tat the same time.\n\t\t*/\n\t\tif (List.Count() > LineCount) {\n\t\t\tAdd_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one more entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\t}\n\treturn(List.Count() - 1);\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Item -- Adds a text item (as number) to the list box.                        *\n *                                                                                             *\n *    This will add the text as specified by the text number provided, to the list box.        *\n *    The string is added to the end of the list.                                              *\n *                                                                                             *\n * INPUT:      text  -- The text number for the string to add to the list box.                 *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   Once a string is added to the list box in this fashion, there is no method of   *\n *             retrieving the text number as it relates to any particular index in the list.   *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Add_Item(int text)\n{\n\tif (text != TXT_NONE) {\n\t\tAdd_Item(Text_String(text));\n\t}\n\treturn(List.Count() - 1);\n}\n\n\nvoid ListClass::Remove_Item(int index)\n{\n\tif (index < List.Count()) {\n\t\tList.Delete(index);\n\n\t\t/*\n\t\t**\tIf the list is now small enough to display completely within the list box region,\n\t\t**\tthen delete the slider gadget (if they are present).\n\t\t*/\n\t\tif (List.Count() <= LineCount) {\n\t\t\tRemove_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one less entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the selected entry, select the previous one\n\t\t*/\n\t\tif (SelectedIndex >= List.Count()) {\n\t\t\tSelectedIndex--;\n\t\t\tif (SelectedIndex < 0) {\n\t\t\t\tSelectedIndex = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the top-displayed entry, step up one item\n\t\t*/\n\t\tif (CurrentTopIndex >= List.Count()) {\n\t\t\tCurrentTopIndex--;\n\t\t\tif (CurrentTopIndex < 0)\n\t\t\t\tCurrentTopIndex = 0;\n\t\t\tif (IsScrollActive)\n\t\t\t\tScrollGadget.Step(1);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove_Item -- Remove specified text from list box.                              *\n *                                                                                             *\n *    This routine will remove the specified text string from the list box.                    *\n *                                                                                             *\n * INPUT:      text  -- Pointer to the string to remove.                                       *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   The text pointer passed into this routine MUST be the same text pointer that    *\n *             was used to add the string to the list.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Remove_Item(char const * text)\n{\n\tif (text) {\n\t\tRemove_Item(List.ID(text));\n\t}\n}\n\n\n/***************************************************************************\n * ListClass::Action -- If clicked on, do this!                            *\n *                                                                         *\n * INPUT:            int flags -- combination of mouse flags indicating    *\n *                                  what action to take.                   *\n *                                                                         *\n * OUTPUT:           bool result.                                          *\n *                                                                         *\n * WARNINGS:         none.                                                 *\n *                                                                         *\n * HISTORY:          01/05/1995 MML : Created.                             *\n *=========================================================================*/\nint ListClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tkey = KN_NONE;\n\t\tflags &= (~LEFTRELEASE);\n\t\tControlClass::Action(flags, key);\n\t\treturn(true);\n\t} else {\n\n\t\t/*\n\t\t** Handle keyboard events here.\n\t\t*/\n\t\tif (flags & KEYBOARD) {\n\n\t\t\t/*\n\t\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t\t**\tso that the edit gadget ID number is not returned.\n\t\t\t*/\n\t\t\tif (key == KN_UP) {\n\t\t\t\tStep_Selected_Index(-1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else if (key == KN_DOWN) {\n\t\t\t\tStep_Selected_Index(1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\tindex = index / LineHeight;\n\t\t\tSelectedIndex = CurrentTopIndex + index;\n\t\t\tSelectedIndex = min(SelectedIndex, List.Count()-1);\n\t\t\tif (SelectedIndex == -1) SelectedIndex = 0;\n\t\t}\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * ListClass::Draw_Me -- Draws the listbox.                                                    *\n *                                                                                             *\n *    This routine will render the listbox.                                                    *\n *                                                                                             *\n * INPUT:   forced   -- Should the listbox be redrawn even if it already thinks it doesn't     *\n *                      need to be? This is true when something outside of the gadget system   *\n *                      has trashed the screen.                                                *\n *                                                                                             *\n * OUTPUT:  Was the listbox redrawn?                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tTurn off the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_BOX, true);\n\n\t\t/*\n\t\t**\tDraw List.\n\t\t*/\n\t\tif (List.Count()) {\n\t\t\tfor (int index = 0; index < LineCount; index++)  {\n\t\t\t\tint line = CurrentTopIndex + index;\n\n\t\t\t\tif (List.Count() > line) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrints the text and handles right edge clipping and tabs.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Entry(line, X+1, Y+(LineHeight*index)+1, Width-2, (line == SelectedIndex));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTurn on the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Bump -- Bumps the list box up/down one \"page\".                                   *\n *                                                                                             *\n *    Use this routine to adjust the \"page\" that is being viewed in the list box. The view     *\n *    will move up or down (as specified) one page (screen full) of text strings.              *\n *                                                                                             *\n * INPUT:   up -- Should the adjustment be up?                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Bump(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Step -- Moves the list view one line in direction specified.                     *\n *                                                                                             *\n *    This routine will move the current view \"page\" one line in the direction specified.      *\n *                                                                                             *\n * INPUT:   up -- Should the view be moved upward?                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Step(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Get_Item -- Fetches an arbitrary item string.                                    *\n *                                                                                             *\n *    This routine will fetch an item string from the list box. The item fetched can be any    *\n *    one of the ones in the list.                                                             *\n *                                                                                             *\n * INPUT:   index -- The index to examine and return the text pointer from.                    *\n *                                                                                             *\n * OUTPUT:  Returns with the text pointer to the string at the index position specified.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ListClass::Get_Item(int index) const\n{\n\tif (List.Count() == 0) {\n\t\treturn NULL;\n\t}\n\tindex = min(index, List.Count()-1);\n\treturn(List[index]);\n}\n\n\n/***********************************************************************************************\n * ListClass::Current_Item -- Fetches pointer to current item string.                          *\n *                                                                                             *\n *    This routine will fetch a pointer to the currently selected item's text.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Return with pointer to currently selected text.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ListClass::Current_Item(void) const\n{\n\tif (List.Count() <= SelectedIndex) {\n\t\treturn(0);\n\t}\n\treturn(List[SelectedIndex]);\n}\n\n\n/***********************************************************************************************\n * ListClass::Current_Index -- Fetches the current selected index.                             *\n *                                                                                             *\n *    This routine will fetch the index number for the currently selected line.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the index of the currently selected line. This ranges from zero to    *\n *          the number of items in the list minus one.                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Current_Index(void) const\n{\n\treturn(SelectedIndex);\n}\n\n\n/***********************************************************************************************\n * ListClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                   *\n *                                                                                             *\n *    This routine is called when one of the peer gadgets (the scroll arrows or the slider)    *\n *    was touched in some fashion. This routine will sort out whom and why and then make       *\n *    any necessary adjustments to the list box.                                               *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that affected the peer gadget.                         *\n *                                                                                             *\n *          key      -- The key value at the time of the event.                                *\n *                                                                                             *\n *          whom     -- Which gadget is being touched.                                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == &UpGadget) {\n\t\t\tStep(true);\n\t\t}\n\t\tif (&whom == &DownGadget) {\n\t\t\tStep(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThe slider has changed, so reflect the current list position\n\t**\taccording to the slider setting.\n\t*/\n\tif (&whom == &ScrollGadget) {\n\t\tSet_View_Index(ScrollGadget.Get_Value());\n\t}\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_View_Index -- Sets the top line for the current list view.                   *\n *                                                                                             *\n *    This routine is used to set the line that will be at the top of the list view. This is   *\n *    how the view can be scrolled up and down. This does not affect the currently selected    *\n *    item.                                                                                    *\n *                                                                                             *\n * INPUT:   index -- The line (index) to move to the top of the list view.                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the view actually changed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Set_View_Index(int index)\n{\n\tindex = Bound(index, 0, max(0, List.Count() - LineCount));\n\tif (index != CurrentTopIndex) {\n\t\tCurrentTopIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Scroll_Bar -- Adds a scroll bar to the list box.                             *\n *                                                                                             *\n *    This routine will add a scroll bar (with matching arrows) to the list box. They are      *\n *    added to the right edge and cause the interior of the list box to become narrower.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the scroll bar added?                                                    *\n *                                                                                             *\n * WARNINGS:   The list box becomes narrower when the scroll bar is added.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Add_Scroll_Bar(void)\n{\n\tif (!IsScrollActive) {\n\t\tIsScrollActive = true;\n\n\t\t/*\n\t\t**\tEverything has been created successfully. Flag the list box to be\n\t\t**\tredrawn because it now must be made narrower to accomodate the new\n\t\t**\tslider gadgets.\n\t\t*/\n\t\tFlag_To_Redraw();\n\t\tWidth -= ScrollGadget.Width;\n\n\t\t/*\n\t\t**\tTell the newly created gadgets that they should inform this list box\n\t\t**\twhenever they get touched. In this way, the list box will automatically\n\t\t**\tbe updated under control of the slider buttons.\n\t\t*/\n\t\tUpGadget.Make_Peer(*this);\n\t\tDownGadget.Make_Peer(*this);\n\t\tScrollGadget.Make_Peer(*this);\n\n\t\t/*\n\t\t**\tAdd these newly created gadgets to the same gadget list that the\n\t\t**\tlist box is part of.\n\t\t*/\n\t\tUpGadget.Add(*this);\n\t\tDownGadget.Add(*this);\n\t\tScrollGadget.Add(*this);\n\n\t\t/*\n\t\t**\tMake sure these added gadgets get redrawn at the next opportunity.\n\t\t*/\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\n\t\t/*\n\t\t**\tInform the slider of the size of the window and the current view position.\n\t\t*/\n\t\tScrollGadget.Set_Maximum(List.Count());\n\t\tScrollGadget.Set_Thumb_Size(LineCount);\n\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove_Scroll_Bar -- Removes the scroll bar if present                           *\n *                                                                                             *\n *    Use this routine to remove any attached scroll bar to this list box. If the scroll bar   *\n *    is not present, then no action occurs.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the scroll bar removed?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Remove_Scroll_Bar(void)\n{\n\tif (IsScrollActive) {\n\t\tIsScrollActive = false;\n\t\tWidth += ScrollGadget.Width;\n\t\tScrollGadget.Remove();\n\t\tUpGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_Tabs -- Sets the tab stop list to be used for text printing.                 *\n *                                                                                             *\n *    This sets the tab stop list to be used for text printing. It specifies a series of       *\n *    pixel offsets for each tab stop. The offsets are from the starting pixel position that   *\n *    the text begins at.                                                                      *\n *                                                                                             *\n * INPUT:   tabs  -- Pointer to a list of tab pixel offsets.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only a pointer to the tabs is recorded by the ListClass object. Make sure that  *\n *             the list remains intact for the duration of the existence of this object.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Set_Tabs(int const * tabs)\n{\n\tTabs = tabs;\n}\n\n\n/***********************************************************************************************\n * ListClass::Draw_Entry -- Draws a list box text line as indicated.                           *\n *                                                                                             *\n *    This routine is called by the Draw_Me function when it desired to redraw a particular    *\n *    text line in the list box.                                                               *\n *                                                                                             *\n * INPUT:   index    -- The index of the list entry to draw. This index is based on the        *\n *                      total list and NOT the current visible view page.                      *\n *                                                                                             *\n *          x,y      -- Pixel coordinates for the upper left corner of the text entry.         *\n *                                                                                             *\n *          width    -- The maximum width that the text may draw over. It is expected that     *\n *                      this drawing routine entirely fills this length.                       *\n *                                                                                             *\n *          selected -- bool; Is this a selected (highlighted) listbox entry?                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tTextPrintType flags = TextFlags;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tif (selected) {\n\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, scheme->Shadow);\n\t} else {\n\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t}\n\t}\n\n\tConquer_Clip_Text_Print(List[index], x, y, scheme, TBLACK, flags, width, Tabs);\n\n}\n\n\n/***********************************************************************************************\n * ListClass::Add -- Adds myself to list immediately after given object                        *\n *                                                                                             *\n * Adds the list box to the chain, immediately after the given object.  The order will be:     *\n * - Listbox                                                                                   *\n * - Up arrow (if active)                                                                      *\n * - Down arrow (if active)                                                                    *\n * - Scroll gadget (if active)                                                                 *\n *                                                                                             *                                                                                       *\n * INPUT:   object   -- Pointer to the object to be added right after this one.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the head of the list.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add(list);\n\t\tDownGadget.Add(list);\n\t\tUpGadget.Add(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add(list));\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Head -- Adds myself to head of the given list                                *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object at the head of the list. This should be     *\n *          the same object that is passed in.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add_Head(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add_Head(list);\n\t\tDownGadget.Add_Head(list);\n\t\tUpGadget.Add_Head(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add_Head(list));\n}\n\n\n/***********************************************************************************************\n * ListClass::Add_Tail -- Adds myself to tail of given list                                    *\n *                                                                                             *\n * Adds the list box to the tail of the give chain.  The order will be:                        *\n * - Listbox                                                                                   *\n * - Up arrow (if active)                                                                      *\n * - Down arrow (if active)                                                                    *\n * - Scroll gadget (if active)                                                                 *\n *                                                                                             *\n * INPUT:   list -- list to add myself to                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The previous and next pointers for the added object MUST have been properly     *\n *             initialized for this routine to work correctly.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLinkClass & ListClass::Add_Tail(LinkClass & list)\n{\n\t/*\n\t**\tAdd myself to the list.\n\t*/\n\tControlClass::Add_Tail(list);\n\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tUpGadget.Add_Tail(list);\n\t\tDownGadget.Add_Tail(list);\n\t\tScrollGadget.Add_Tail(list);\n\t}\n\n\treturn(Head_Of_List());\n}\n\n\n/***********************************************************************************************\n * ListClass::Remove -- Removes the specified object from the list.                            *\n *                                                                                             *\n *    This routine will remove the specified object from the list of objects. Because of the   *\n *    previous and next pointers, it is possible to remove an object from the list without     *\n *    knowing the head of the list. To do this, just call Remove() with the parameter of       *\n *    \"this\".                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the new head of list.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nGadgetClass * ListClass::Remove(void)\n{\n\t/*\n\t**\tRemove the scroll bar if it's active\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tUpGadget.Remove();\n\t}\n\n\t/*\n\t**\tRemove myself & return\n\t*/\n\treturn(ControlClass::Remove());\n}\n\n\n/***********************************************************************************************\n * ListClass::Set_Selected_Index -- Set the top of the listbox to index specified.             *\n *                                                                                             *\n *    This routine will set the top line of the listbox to the index value specified.          *\n *                                                                                             *\n * INPUT:   index -- The index to set the top of the listbox to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The requested index may be adjusted to fit within legal parameters.             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *   01/23/1996 JLB : Forces selected index to always be zero for a null list.                 *\n *=============================================================================================*/\nvoid ListClass::Set_Selected_Index(int index)\n{\n   if (index < List.Count()) {\n\t\tSelectedIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (SelectedIndex < CurrentTopIndex) {\n\t\t\tSet_View_Index(SelectedIndex);\n\t\t}\n\t\tif (SelectedIndex >= CurrentTopIndex+LineCount) {\n\t\t\tSet_View_Index(SelectedIndex-(LineCount-1));\n\t\t}\n   } else {\n   \tSelectedIndex = 0;\n   }\n}\n\n\n/***********************************************************************************************\n * ListClass::Step_Selected_Index -- Change the listbox top line in direction specified.       *\n *                                                                                             *\n *    This routine will scroll the top line of the listbox in the direction specified.         *\n *                                                                                             *\n * INPUT:   step  -- The direction (and amount) to adjust the listbox. If negative value, then *\n *                   the top line is scrolled upward.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the original top line index number.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ListClass::Step_Selected_Index(int step)\n{\n\tint old = SelectedIndex;\n\n\tSet_Selected_Index(old + step);\n\treturn(old);\n}\n\n\nvoid ListClass::Flag_To_Redraw(void)\n{\n\tif (IsScrollActive) {\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\t}\n\tControlClass::Flag_To_Redraw();\n}\n\n\nvoid ListClass::Set_Selected_Index(char const * text)\n{\n\tif (text && List.Count() > 0) {\n\t\tfor (int index = 0; index < List.Count(); index++) {\n\t\t\tif (stricmp(List[index], text) == 0) {\n\t\t\t\tSet_Selected_Index(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/LIST.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LIST.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LIST.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LIST_H\n#define LIST_H\n\n#include \"control.h\"\n#include \"shapebtn.h\"\n#include \"slider.h\"\n\n\n/***************************************************************************\n * ListClass -- Like a Windows ListBox structure\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      int x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tUWORD flags -- see enumeration choices\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:     none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t*\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nclass ListClass : public ControlClass\n{\n\tpublic:\n\t\tListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tListClass(ListClass const & list);\n\t\tvirtual ~ListClass(void);\n\n\t\tvirtual int Add_Item(char const * text);\n\t\tvirtual int Add_Item(int text);\n\t\tvirtual int Add_Scroll_Bar(void);\n\t\tvirtual void Bump(int up);\n\t\tvirtual int Count(void) const {return List.Count();};\n\t\tvirtual int Current_Index(void) const;\n\t\tvirtual char const * Current_Item(void) const;\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual char const * Get_Item(int index) const;\n\t\tvirtual int Step_Selected_Index(int forward);\n\t\tvirtual void Flag_To_Redraw(void);\n\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item(char const * text);\n\t\tvirtual void Remove_Item(int);\n\t\tvirtual int  Remove_Scroll_Bar(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(char const * text);\n\t\tvirtual void Set_Tabs(int const * tabs);\n\t\tvirtual int  Set_View_Index(int index);\n\t\tvirtual void Step(int up);\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual GadgetClass * Remove(void);\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n\n\t\t/*\n\t\t**\tThis controls what the text looks like. It uses the basic TPF_ flags that\n\t\t**\tare used to control Fancy_Text_Print().\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tThis is a series of tabstop pixel positions to use when processing any\n\t\t**\t<TAB> characters found in a list box string. The tabs are a series of\n\t\t**\tpixel offsets from the starting pixel position of the text.\n\t\t*/\n\t\tint const *Tabs;\n\n\t\t/*\n\t\t**\tThe actual list of text pointers is maintained by this list manager. The pointers\n\t\t**\tare stored in EMS. The text that is pointed to may also be in EMS.\n\t\t*/\n\t\tDynamicVectorClass<char const *> List;\n\n\t\t/*\n\t\t**\tThis is the total pixel height of a standard line of text. This is greatly\n\t\t**\tinfluenced by the TextFlags value.\n\t\t*/\n\t\tint LineHeight;\n\n\t\t/*\n\t\t**\tThis is the number of text lines that can fit within the list box.\n\t\t*/\n\t\tint LineCount;\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tunsigned IsScrollActive:1;\n\t\tShapeButtonClass UpGadget;\n\t\tShapeButtonClass DownGadget;\n\t\tSliderClass ScrollGadget;\n\n\t\t/*\n\t\t**\tThis is the currently selected index. It is highlighted.\n\t\t*/\n\t\tint SelectedIndex;\n\n\t\t/*\n\t\t**\tThis specifies the line (index) that is at the top of the list box.\n\t\t*/\n\t\tint CurrentTopIndex;\n};\n\n\ntemplate<class T>\nclass TListClass : public ControlClass\n{\n\tpublic:\n\t\tTListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);\n\t\tTListClass(TListClass<T> const & list);\n\t\tvirtual ~TListClass(void);\n\t\tT operator [] (int index) const {return(List[index]);};\n\t\tT & operator [] (int index) {return(List[index]);};\n\n\t\tvirtual int Add_Item(T text);\n\t\tvirtual int Add_Scroll_Bar(void);\n\t\tvirtual void Insert_Item(T item);\n\t\tvirtual void Bump(int up);\n\t\tvirtual int Count(void) const {return List.Count();};\n\t\tvirtual int Current_Index(void) const;\n\t\tvirtual T Current_Item(void) const;\n\t\tvirtual int Draw_Me(int forced);\n\t\tvirtual int Step_Selected_Index(int forward);\n\t\tvirtual void Flag_To_Redraw(void);\n\t\tvirtual T Get_Item(int index) const {return(List[index]);};\n\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\t\tvirtual void Remove_Item(T);\n\t\tvirtual void Remove_Index(int);\n\t\tvirtual int  Remove_Scroll_Bar(void);\n\t\tvirtual void Set_Selected_Index(int index);\n\t\tvirtual void Set_Selected_Index(T item);\n\t\tvirtual void Set_Tabs(int const * tabs);\n\t\tvirtual int  Set_View_Index(int index);\n\t\tvirtual void Step(int up);\n\t\tvirtual void Set_Position(int x, int y);\n\n\t\t/*\n\t\t** These overloaded list routines handle adding/removing the scroll bar\n\t\t** automatically when the list box is added or removed.\n\t\t*/\n\t\tvirtual LinkClass & Add(LinkClass & object);\n\t\tvirtual LinkClass & Add_Tail(LinkClass & object);\n\t\tvirtual LinkClass & Add_Head(LinkClass & object);\n\t\tvirtual GadgetClass * Remove(void);\n\n\tprotected:\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\n\t\t/*\n\t\t**\tThis controls what the text looks like. It uses the basic TPF_ flags that\n\t\t**\tare used to control Fancy_Text_Print().\n\t\t*/\n\t\tTextPrintType TextFlags;\n\n\t\t/*\n\t\t**\tThis is a series of tabstop pixel positions to use when processing any\n\t\t**\t<TAB> characters found in a list box string. The tabs are a series of\n\t\t**\tpixel offsets from the starting pixel position of the text.\n\t\t*/\n\t\tint const * Tabs;\n\n\t\t/*\n\t\t**\tThe actual list of text pointers is maintained by this list manager.\n\t\t*/\n\t\tDynamicVectorClass<T> List;\n\n\t\t/*\n\t\t**\tThis is the total pixel height of a standard line of text. This is greatly\n\t\t**\tinfluenced by the TextFlags value.\n\t\t*/\n\t\tint LineHeight;\n\n\t\t/*\n\t\t**\tThis is the number of text lines that can fit within the list box.\n\t\t*/\n\t\tint LineCount;\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tunsigned IsScrollActive:1;\n\t\tShapeButtonClass UpGadget;\n\t\tShapeButtonClass DownGadget;\n\t\tSliderClass ScrollGadget;\n\n\t\t/*\n\t\t**\tThis is the currently selected index. It is highlighted.\n\t\t*/\n\t\tint SelectedIndex;\n\n\t\t/*\n\t\t**\tThis specifies the line (index) that is at the top of the list box.\n\t\t*/\n\t\tint CurrentTopIndex;\n};\n\ntemplate<class T>\nTListClass<T>::TListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :\n\tControlClass(id, x, y, w, h, LEFTPRESS | LEFTRELEASE | KEYBOARD, false),\n\tUpGadget(0, up, x+w, y),\n\tDownGadget(0, down, x+w, y+h),\n\tScrollGadget(0, x+w, y, 0, h, true),\n\tTextFlags(flags),\n\tTabs(0),\n\tIsScrollActive(false),\n\tSelectedIndex(0),\n\tCurrentTopIndex(0)\n{\n\t/*\n\t**\tSet preliminary values for the slider related gadgets. They don't automatically\n\t**\tappear at this time, but there are some values that can be pre-filled in.\n\t*/\n\tUpGadget.X -= UpGadget.Width;\n\tDownGadget.X -= DownGadget.Width;\n\tDownGadget.Y -= DownGadget.Height;\n\tScrollGadget.X -= max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = Y+UpGadget.Height;\n\tScrollGadget.Height -= UpGadget.Height + DownGadget.Height;\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n\n\t/*\n\t**\tSet the list box to a default state.\n\t*/\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);\n\tLineHeight = FontHeight+FontYSpacing-1;\n\tLineCount = (h-1) / LineHeight;\n}\n\ntemplate<class T>\nTListClass<T>::TListClass(TListClass<T> const & list) :\n\tControlClass(list),\n\tTextFlags(list.TextFlags),\n\tTabs(list.Tabs),\n\tList(list.List),\n\tLineHeight(list.LineHeight),\n\tLineCount(list.LineCount),\n\tIsScrollActive(list.IsScrollActive),\n\tUpGadget(list.UpGadget),\n\tDownGadget(list.DownGadget),\n\tScrollGadget(list.ScrollGadget),\n\tSelectedIndex(list.SelectedIndex),\n\tCurrentTopIndex(list.CurrentTopIndex)\n{\n\tUpGadget.Make_Peer(*this);\n\tDownGadget.Make_Peer(*this);\n\tScrollGadget.Make_Peer(*this);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Position(int x, int y)\n{\n\tUpGadget.X = x + Width - UpGadget.Width;\n\tUpGadget.Y = y;\n\tDownGadget.X = x + Width - DownGadget.Width;\n\tDownGadget.Y = y + Height - DownGadget.Height;\n\tScrollGadget.X = x + Width - max(UpGadget.Width, DownGadget.Width);\n\tScrollGadget.Y = y + UpGadget.Height;\n\tScrollGadget.Height = Height - (UpGadget.Height + DownGadget.Height);\n\tScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);\n}\n\ntemplate<class T>\nTListClass<T>::~TListClass(void)\n{\n\tRemove_Scroll_Bar();\n}\n\ntemplate<class T>\nvoid TListClass<T>::Insert_Item(T item)\n{\n\tif (Current_Index() >= Count()) {\n\t\tList.Add(item);\n\t} else {\n\t\tList.Add(item);\n\n\t\t/*\n\t\t**\tMove all trailing items upward.\n\t\t*/\n\t\tfor (int index = List.Count()-1; index >= Current_Index(); index--) {\n\t\t\tList[index+1] = List[index];\n\t\t}\n\n\t\t/*\n\t\t**\tInsert the new item into the location at the current index.\n\t\t*/\n\t\tList[Current_Index()] = item;\n\t}\n}\n\n\ntemplate<class T>\nint TListClass<T>::Add_Item(T text)\n{\n//\tif (text) {\n\t\tList.Add(text);\n\t\tFlag_To_Redraw();\n\n\t\t/*\n\t\t**\tAdd scroll gadget if the list gets too large to display all of the items\n\t\t**\tat the same time.\n\t\t*/\n\t\tif (List.Count() > LineCount) {\n\t\t\tAdd_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one more entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n//\t}\n\treturn(List.Count() - 1);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Remove_Index(int index)\n{\n\tif ((unsigned)index < List.Count()) {\n\t\tList.Delete(index);\n\n\t\t/*\n\t\t**\tIf the list is now small enough to display completely within the list box region,\n\t\t**\tthen delete the slider gadget (if they are present).\n\t\t*/\n\t\tif (List.Count() <= LineCount) {\n\t\t\tRemove_Scroll_Bar();\n\t\t}\n\n\t\t/*\n\t\t**\tTell the slider that there is one less entry in the list.\n\t\t*/\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Maximum(List.Count());\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the selected entry, select the previous one\n\t\t*/\n\t\tif (SelectedIndex >= List.Count()) {\n\t\t\tSelectedIndex--;\n\t\t\tif (SelectedIndex < 0) {\n\t\t\t\tSelectedIndex = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If we just removed the top-displayed entry, step up one item\n\t\t*/\n\t\tif (CurrentTopIndex >= List.Count()) {\n\t\t\tCurrentTopIndex--;\n\t\t\tif (CurrentTopIndex < 0)\n\t\t\t\tCurrentTopIndex = 0;\n\t\t\tif (IsScrollActive)\n\t\t\t\tScrollGadget.Step(1);\n\t\t}\n\t}\n}\n\ntemplate<class T>\nvoid TListClass<T>::Remove_Item(T text)\n{\n\tRemove_Index(List.ID(text));\n}\n\ntemplate<class T>\nint TListClass<T>::Action(unsigned flags, KeyNumType & key)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tkey = KN_NONE;\n\t\tflags &= (~LEFTRELEASE);\n\t\tControlClass::Action(flags, key);\n\t\treturn(true);\n\t} else {\n\n\t\t/*\n\t\t** Handle keyboard events here.\n\t\t*/\n\t\tif (flags & KEYBOARD) {\n\n\t\t\t/*\n\t\t\t**\tProcess the keyboard character. If indicated, consume this keyboard event\n\t\t\t**\tso that the edit gadget ID number is not returned.\n\t\t\t*/\n\t\t\tif (key == KN_UP) {\n\t\t\t\tStep_Selected_Index(-1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else if (key == KN_DOWN) {\n\t\t\t\tStep_Selected_Index(1);\n\t\t\t\tkey = KN_NONE;\n\t\t\t} else {\n\t\t\t\tflags &= ~KEYBOARD;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tint index = Get_Mouse_Y() - (Y+1);\n\t\t\tindex = index / LineHeight;\n\t\t\tSelectedIndex = CurrentTopIndex + index;\n\t\t\tSelectedIndex = min(SelectedIndex, List.Count()-1);\n\t\t}\n\t}\n\treturn(ControlClass::Action(flags, key));\n}\n\ntemplate<class T>\nint TListClass<T>::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\n\t\t/*\n\t\t**\tTurn off the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t}\n\n\t\tDraw_Box(X, Y, Width, Height, BOXSTYLE_BOX, true);\n\n\t\t/*\n\t\t**\tDraw List.\n\t\t*/\n\t\tif (List.Count()) {\n\t\t\tfor (int index = 0; index < LineCount; index++)  {\n\t\t\t\tint line = CurrentTopIndex + index;\n\n\t\t\t\tif (List.Count() > line) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPrints the text and handles right edge clipping and tabs.\n\t\t\t\t\t*/\n\t\t\t\t\tList[line]->Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);\n//\t\t\t\t\tList[index].Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);\n//\t\t\t\t\tDraw_Entry(line, X+1, Y+(LineHeight*index)+1, Width-2, (line == SelectedIndex));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tTurn on the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Bump(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\ntemplate<class T>\nvoid TListClass<T>::Step(int up)\n{\n\tif (IsScrollActive) {\n\t\tif (ScrollGadget.Step(up)) {\n\t\t\tCurrentTopIndex = ScrollGadget.Get_Value();\n\t\t\tFlag_To_Redraw();\n\t\t}\n\t}\n}\n\n#ifdef NEVER\ntemplate<class T>\nT TListClass<T>::Get_Item(int index) const\n{\n\tindex = min(index, List.Count());\n\treturn(List[index]);\n}\n#endif\n\ntemplate<class T>\nT TListClass<T>::Current_Item(void) const\n{\n\tstatic T _temp;\n\tif (List.Count() <= SelectedIndex) {\n\t\treturn(_temp);\n\t}\n\treturn(List[SelectedIndex]);\n}\n\ntemplate<class T>\nint TListClass<T>::Current_Index(void) const\n{\n\treturn(SelectedIndex);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == &UpGadget) {\n\t\t\tStep(true);\n\t\t}\n\t\tif (&whom == &DownGadget) {\n\t\t\tStep(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tThe slider has changed, so reflect the current list position\n\t**\taccording to the slider setting.\n\t*/\n\tif (&whom == &ScrollGadget) {\n\t\tSet_View_Index(ScrollGadget.Get_Value());\n\t}\n}\n\ntemplate<class T>\nint TListClass<T>::Set_View_Index(int index)\n{\n\tindex = Bound(index, 0, List.Count() - LineCount);\n\tif (index != CurrentTopIndex) {\n\t\tCurrentTopIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (IsScrollActive) {\n\t\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nint TListClass<T>::Add_Scroll_Bar(void)\n{\n\tif (!IsScrollActive) {\n\t\tIsScrollActive = true;\n\n\t\t/*\n\t\t**\tEverything has been created successfully. Flag the list box to be\n\t\t**\tredrawn because it now must be made narrower to accomodate the new\n\t\t**\tslider gadgets.\n\t\t*/\n\t\tFlag_To_Redraw();\n\t\tWidth -= ScrollGadget.Width;\n\n\t\t/*\n\t\t**\tTell the newly created gadgets that they should inform this list box\n\t\t**\twhenever they get touched. In this way, the list box will automatically\n\t\t**\tbe updated under control of the slider buttons.\n\t\t*/\n\t\tUpGadget.Make_Peer(*this);\n\t\tDownGadget.Make_Peer(*this);\n\t\tScrollGadget.Make_Peer(*this);\n\n\t\t/*\n\t\t**\tAdd these newly created gadgets to the same gadget list that the\n\t\t**\tlist box is part of.\n\t\t*/\n\t\tUpGadget.Add(*this);\n\t\tDownGadget.Add(*this);\n\t\tScrollGadget.Add(*this);\n\n\t\t/*\n\t\t**\tMake sure these added gadgets get redrawn at the next opportunity.\n\t\t*/\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\n\t\t/*\n\t\t**\tInform the slider of the size of the window and the current view position.\n\t\t*/\n\t\tScrollGadget.Set_Maximum(List.Count());\n\t\tScrollGadget.Set_Thumb_Size(LineCount);\n\t\tScrollGadget.Set_Value(CurrentTopIndex);\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nint TListClass<T>::Remove_Scroll_Bar(void)\n{\n\tif (IsScrollActive) {\n\t\tIsScrollActive = false;\n\t\tWidth += ScrollGadget.Width;\n\t\tScrollGadget.Remove();\n\t\tUpGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tFlag_To_Redraw();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Tabs(int const * tabs)\n{\n\tTabs = tabs;\n}\n\n#ifdef NEVER\ntemplate<class T>\nvoid TListClass<T>::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tif (TextFlags & TPF_6PT_GRAD) {\n\t\tTextPrintType flags = TextFlags;\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, CC_GREEN_SHADOW);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(List[index], x, y, CC_GREEN, TBLACK, flags, width, Tabs);\n\n\t} else {\n\t\tConquer_Clip_Text_Print(List[index], x, y, (selected ? BLUE : WHITE), TBLACK, TextFlags, width, Tabs);\n\t}\n}\n#endif\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add(list);\n\t\tDownGadget.Add(list);\n\t\tUpGadget.Add(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add(list));\n}\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add_Head(LinkClass & list)\n{\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Add_Head(list);\n\t\tDownGadget.Add_Head(list);\n\t\tUpGadget.Add_Head(list);\n\t}\n\n\t/*\n\t**\tAdd myself to the list, then return.\n\t*/\n\treturn(ControlClass::Add_Head(list));\n}\n\ntemplate<class T>\nLinkClass & TListClass<T>::Add_Tail(LinkClass & list)\n{\n\t/*\n\t**\tAdd myself to the list.\n\t*/\n\tControlClass::Add_Tail(list);\n\n\t/*\n\t**\tAdd the scroll bar gadgets if they're active.\n\t*/\n\tif (IsScrollActive) {\n\t\tUpGadget.Add_Tail(list);\n\t\tDownGadget.Add_Tail(list);\n\t\tScrollGadget.Add_Tail(list);\n\t}\n\n\treturn(Head_Of_List());\n}\n\ntemplate<class T>\nGadgetClass * TListClass<T>::Remove(void)\n{\n\t/*\n\t**\tRemove the scroll bar if it's active\n\t*/\n\tif (IsScrollActive) {\n\t\tScrollGadget.Remove();\n\t\tDownGadget.Remove();\n\t\tUpGadget.Remove();\n\t}\n\n\t/*\n\t**\tRemove myself & return\n\t*/\n\treturn(ControlClass::Remove());\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Selected_Index(int index)\n{\n   if ((unsigned)index < List.Count()) {\n\t\tSelectedIndex = index;\n\t\tFlag_To_Redraw();\n\t\tif (SelectedIndex < CurrentTopIndex) {\n\t\t\tSet_View_Index(SelectedIndex);\n\t\t}\n\t\tif (SelectedIndex >= CurrentTopIndex+LineCount) {\n\t\t\tSet_View_Index(SelectedIndex-(LineCount-1));\n\t\t}\n   }\n}\n\ntemplate<class T>\nint TListClass<T>::Step_Selected_Index(int step)\n{\n\tint old = SelectedIndex;\n\n\tSet_Selected_Index(old + step);\n\treturn(old);\n}\n\ntemplate<class T>\nvoid TListClass<T>::Flag_To_Redraw(void)\n{\n\tif (IsScrollActive) {\n\t\tUpGadget.Flag_To_Redraw();\n\t\tDownGadget.Flag_To_Redraw();\n\t\tScrollGadget.Flag_To_Redraw();\n\t}\n\tControlClass::Flag_To_Redraw();\n}\n\ntemplate<class T>\nvoid TListClass<T>::Set_Selected_Index(T text)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tif (text == Get_Item(index)) {\n\t\t\tSet_Selected_Index(index);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LISTNODE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LISTNODE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LISTNODE.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/16/96                                                     *\n *                                                                                             *\n *                  Last Update : May 16, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LISTNODE_H\n#define LISTNODE_H\n\n#include\t<stddef.h>\n#include\t<assert.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ comittee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n//#pragma warn -inl\n\n/*\n**\tThis is a doubly linked list node. Typical use of this node is to derive\n**\tobjects from this node. The interface class for this node can be used for\n**\tadded convenience.\n*/\nclass GenericList;\nclass GenericNode {\n\tpublic:\n\t\tGenericNode(void) : NextNode(0), PrevNode(0) {}\n\t\t~GenericNode(void) {Unlink();}\n\t\tGenericNode(GenericNode & node) {node.Link(this);}\n\t\tGenericNode & operator = (GenericNode & node) {\n\t\t\tif (&node != this) {\n\t\t\t\tnode.Link(this);\n\t\t\t}\n\t\t\treturn(*this);\n\t\t}\n\n\t\tvoid Unlink(void) {\n\t\t\tif (Is_Valid()) {\n\t\t\t\tPrevNode->NextNode = NextNode;\n\t\t\t\tNextNode->PrevNode = PrevNode;\n\t\t\t\tPrevNode = 0;\n\t\t\t\tNextNode = 0;\n\t\t\t}\n\t\t}\n\n\t\tGenericList * Main_List(void) const {\n\t\t\tGenericNode const * node = this;\n\t\t\twhile (node->PrevNode) {\n\t\t\t\tnode = PrevNode;\n\t\t\t}\n\t\t\treturn((GenericList *)this);\n\t\t}\n\t\tvoid Link(GenericNode * node) {\n\t\t\tassert(node != NULL);\n\t\t\tnode->Unlink();\n\t\t\tnode->NextNode = NextNode;\n\t\t\tnode->PrevNode = this;\n\t\t\tif (NextNode) NextNode->PrevNode = node;\n\t\t\tNextNode = node;\n\t\t}\n\n\t\tGenericNode * Next(void) const {return(NextNode);}\n\t\tGenericNode * Prev(void) const {return(PrevNode);}\n\t\tbool Is_Valid(void) const {return(this != NULL && NextNode != NULL && PrevNode != NULL);}\n\n\tprotected:\n\t\tGenericNode * NextNode;\n\t\tGenericNode * PrevNode;\n};\n\n\n/*\n**\tThis is a generic list handler. It manages N generic nodes. Use the interface class\n**\tto the generic list for added convenience.\n*/\nclass GenericList {\n\tpublic:\n\t\tGenericList(void) {\n\t\t\tFirstNode.Link(&LastNode);\n\t\t}\n\n\t\tGenericNode * First(void) const {return(FirstNode.Next());}\n\t\tGenericNode * Last(void) const {return(LastNode.Prev());}\n\t\tbool Is_Empty(void) const {return(!FirstNode.Next()->Is_Valid());}\n\t\tvoid Add_Head(GenericNode * node) {FirstNode.Link(node);}\n\t\tvoid Add_Tail(GenericNode * node) {LastNode.Prev()->Link(node);}\n\t\tvoid Delete(void) {while (FirstNode.Next()->Is_Valid()) delete FirstNode.Next();}\n\n\tprotected:\n\t\tGenericNode FirstNode;\n\t\tGenericNode LastNode;\n\n\tprivate:\n\t\tGenericList(GenericList & list);\n\t\tGenericList & operator = (GenericList const &);\n};\n\n\n\n/*\n**\tThis node class serves only as an \"interface class\" for the normal node\n**\tobject. In order to use this interface class you absolutely must be sure\n**\tthat the node is the root base object of the \"class T\". If it is true that the\n**\taddress of the node is the same as the address of the \"class T\", then this\n**\tinterface class will work. You can usually ensure this by deriving the\n**\tclass T object from this node.\n*/\ntemplate<class T> class List;\ntemplate<class T>\nclass Node : public GenericNode {\n\tpublic:\n\t\tList<T> * Main_List(void) const {return((List<T> *)GenericNode::Main_List());}\n\t\tT * Next(void) const {return((T *)GenericNode::Next());}\n\t\tT * Prev(void) const {return((T *)GenericNode::Prev());}\n\t\tbool Is_Valid(void) const {return(GenericNode::Is_Valid());}\n};\n\n\n/*\n**\tThis is an \"interface class\" for a list of nodes. The rules for the class T object\n**\tare the same as the requirements required of the node class.\n*/\ntemplate<class T>\nclass List : public GenericList {\n\tpublic:\n\t\tT * First(void) const {return((T*)GenericList::First());}\n\t\tT * Last(void) const {return((T*)GenericList::Last());}\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LOADDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LOADDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOADDLG.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Maria Legg, Joe Bostic, Bill Randolph                        *\n *                                                                                             *\n *                   Start Date : March 19, 1995                                               *\n *                                                                                             *\n *                  Last Update : June 25, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LoadOptionsClass::LoadOptionsClass -- class constructor                                   *\n *   LoadOptionsClass::~LoadOptionsClass -- class destructor                                   *\n *   LoadOptionsClass::Process -- main processing routine                                      *\n *   LoadOptionsClass::Clear_List -- clears the list box & Files arrays                        *\n *   LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                        *\n *   LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                    *\n *   LoadOptionsClass::Compare -- for qsort                                                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <io.h>\t\t\t\t// for unlink\n\n\n/***********************************************************************************************\n * LoadOptionsClass::LoadOptionsClass -- class constructor                                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      style      style for this load/save dialog (LOAD/SAVE/DELETE)                          *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nLoadOptionsClass::LoadOptionsClass(LoadStyleType style)\n{\n\tStyle = style;\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::~LoadOptionsClass -- class destructor                                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nLoadOptionsClass::~LoadOptionsClass()\n{\n\tfor (int i = 0; i < Files.Count(); i++) {\n\t\tdelete Files[i];\n\t}\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Process -- main processing routine                                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      false = User cancelled, true = operation completed                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Process(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint d_dialog_w = 250 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 156 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\t\t\t\t// centered x-coord\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n\tint d_txt8_h = 11 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint x_margin = 16 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_list_w = d_dialog_w - (x_margin * 2);\n\tint d_list_h = 104 * RESFACTOR;\n\tint d_list_x = d_dialog_x + x_margin;\n\tint d_list_y = d_dialog_y + d_margin + d_txt8_h + d_margin;\n\n\tint d_edit_w = d_dialog_w - (x_margin * 2);\n\tint d_edit_h = 13 * RESFACTOR;\n\tint d_edit_x = d_dialog_x + x_margin;\n\tint d_edit_y = d_list_y + d_list_h - (30 * RESFACTOR) + d_margin + d_txt8_h;\n\n#if (GERMAN | FRENCH)\n\tint d_button_w = 50 * RESFACTOR;\n#else\n\tint d_button_w = 40 * RESFACTOR;\n#endif\n\tint d_button_h = 13 * RESFACTOR;\n\tint d_button_x = d_dialog_cx - d_button_w - d_margin;\n\tint d_button_y = d_dialog_y + d_dialog_h - d_button_h - d_margin;\n\n#if defined(GERMAN) || defined(FRENCH)\n\tint d_cancel_w = 60 * RESFACTOR;//BG:40\n#else\n\tint d_cancel_w = 40 * RESFACTOR;\n#endif\n\tint d_cancel_h = 13 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + d_margin;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin;\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_LOAD = 100,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_LIST,\n\t\tBUTTON_EDIT,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t// true = user cancels\n\tint list_ht = d_list_h;\t\t\t\t\t// adjusted list box height\n\n\t/*\n\t**\tOther Variables\n\t*/\n\tint btn_txt;\t\t\t\t\t\t\t\t// text on the 'OK' button\n\tint btn_id;\t\t\t\t\t\t\t\t\t// ID of 'OK' button\n\tint caption;\t\t\t\t\t\t\t\t// dialog caption\n\tint game_idx = 0;\t\t\t\t\t\t\t// index of game to save/load/etc\n\tint game_num = 0;\t\t\t\t\t\t\t// file number of game to load/save/etc\n\tchar game_descr[DESCRIP_MAX] = {0};\t\t\t\t// save-game description\n\tchar fname[_MAX_NAME+_MAX_EXT];\t\t\t\t\t\t\t// for generating filename to delete\n\tint rc;\t\t\t\t\t\t\t\t\t\t// return code\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tswitch (Style) {\n\t\tcase LOAD:\n\t\t\tbtn_txt = TXT_LOAD_BUTTON;\n\t\t\tbtn_id = BUTTON_LOAD;\n\t\t\tcaption = TXT_LOAD_MISSION;\n\t\t\tbreak;\n\n\t\tcase SAVE:\n\t\t\tbtn_txt = TXT_SAVE_BUTTON;\n\t\t\tbtn_id = BUTTON_SAVE;\n\t\t\tcaption = TXT_SAVE_MISSION;\n\t\t\tlist_ht -= 30;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbtn_txt = TXT_DELETE_BUTTON;\n\t\t\tbtn_id = BUTTON_DELETE;\n\t\t\tcaption = TXT_DELETE_MISSION;\n\t\t\tbreak;\n\t}\n\n\tTextButtonClass button (btn_id, btn_txt, TPF_BUTTON, d_button_x, d_button_y, d_button_w);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\n\tListClass listbtn (BUTTON_LIST, d_list_x, d_list_y, d_list_w, list_ht,\n\t\tTPF_6PT_GRAD | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tEditClass editbtn (BUTTON_EDIT, game_descr, sizeof(game_descr)-4, TPF_6PT_GRAD|TPF_NOSHADOW, d_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC);\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tFill_List(&listbtn);\n\n\t/*\n\t**\tDo nothing if list is empty.\n\t*/\n\tif ((Style == LOAD || Style == WWDELETE) && listbtn.Count()==0) {\n\t\tClear_List(&listbtn);\n\t\tWWMessageBox().Process(TXT_NO_SAVES);\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &button;\n\tcancelbtn.Add_Tail(*commands);\n\tlistbtn.Add_Tail(*commands);\n\tif (Style == SAVE) {\n\t\teditbtn.Add_Tail(*commands);\n\t\teditbtn.Set_Focus();\n\t}\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t\tcancel = true;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption(caption, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tif (Style == SAVE) {\n\t\t\t\t\tFancy_Text_Print(TXT_MISSION_DESCRIPTION, d_dialog_cx,\n\t\t\t\t\t\td_edit_y - d_txt8_h, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus if this is the save dialog. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime && Style == SAVE) {\n\t\t\tfirsttime = false;\n\t\t\teditbtn.Set_Focus();\n\t\t\teditbtn.Flag_To_Redraw();\n\t\t}\n\n\t\t/*\n\t\t**\tIf the <RETURN> key was pressed, then default to the appropriate\n\t\t**\taction button according to the style of this dialog box.\n\t\t*/\n\t\tif (input == KN_RETURN || input == (BUTTON_EDIT|KN_BUTTON)) {\n\t\t\tToggleClass * toggle = NULL;\n\t\t\tswitch (Style) {\n\t\t\t\tcase SAVE:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_SAVE|KN_BUTTON);\n\t\t\t\t\tcancelbtn.Turn_Off();\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\ttoggle = (ToggleClass*)commands->Extract_Gadget(BUTTON_SAVE);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->Turn_On();\n//\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase LOAD:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_LOAD|KN_BUTTON);\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\tcancelbtn.Turn_Off();\n\t\t\t\t\ttoggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_LOAD);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WWDELETE:\n\t\t\t\t\tinput = (KeyNumType)(BUTTON_DELETE|KN_BUTTON);\n//\t\t\t\t\tcancelbtn.IsOn = false;\n\t\t\t\t\tcancelbtn.Turn_Off();\n\t\t\t\t\ttoggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_DELETE);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tHide_Mouse();\n\t\t\tcommands->Draw_All(true);\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*\n\t\t\t** Load: if load fails, present a message, and stay in the dialog\n\t\t\t** to allow the user to try another game\n\t\t\t*/\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (Files[game_idx]->Valid) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Start a timer before we load the game\n\t\t\t\t\t*/\n\t\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n//\t\t\t\t\ttimer.Start();\n\t\t\t\t\ttimer = TICKS_PER_SECOND*4;\n\n\t\t\t\t\tWWMessageBox().Process(TXT_LOADING, TXT_NONE);\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\trc = Load_Game(game_num);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure the message says on the screen at least 1 second\n\t\t\t\t\t*/\n\t\t\t\t\twhile (timer > 0) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tKeyboard->Clear();\n\n\t\t\t\t\tif (!rc) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_LOADING_GAME);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSpeak(VOX_LOAD1);\n\t\t\t\t\t\twhile (Is_Speaking()) {\n\t\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tSeenPage.Clear();\n\t\t\t\t\t\tGamePalette.Set();\n//\t\t\t\t\t\tSet_Palette(GamePalette);\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tWWMessageBox().Process(TXT_OBSOLETE_SAVEGAME);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Save: Save the game & exit the dialog\n\t\t\t*/\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tif (!strlen(game_descr)) {\n\t\t\t\t\tWWMessageBox().Process(TXT_MUSTENTER_DESCRIPTION);\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tif (Disk_Space_Available() < SAVE_GAME_DISK_SPACE && game_idx == 0) {\n\t\t\t\t\tWWMessageBox().Process(TXT_SPACE_CANT_SAVE);\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (!Save_Game(game_num, game_descr)) {\n\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_SAVING_GAME);\n\t\t\t\t} else {\n\t\t\t\t\tSpeak(VOX_SAVE1);\n\t\t\t\t\twhile (Is_Speaking()) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tCDTimerClass<SystemTimerClass> timer;\n//\t\t\t\t\ttimer.Start();\n\t\t\t\t\ttimer = TICKS_PER_SECOND*4;\n\n\t\t\t\t\tWWMessageBox().Process(TXT_GAME_WAS_SAVED, TXT_NONE, TXT_NONE);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDelay to let the user read the message\n\t\t\t\t\t*/\n\t\t\t\t\twhile (timer > 0) {\n\t\t\t\t\t\tCall_Back();\n\t\t\t\t\t}\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Delete: delete the file & stay in the dialog, to allow the user\n\t\t\t** to delete multiple files.\n\t\t\t*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tgame_idx = listbtn.Current_Index();\n\t\t\t\tgame_num = Files[game_idx]->Num;\n\t\t\t\tif (WWMessageBox().Process(TXT_DELETE_FILE_QUERY, TXT_YES, TXT_NO)==0) {\n\t\t\t\t\tsprintf(fname, \"SAVEGAME.%03d\", game_num);\n\t\t\t\t\tunlink(fname);\n\t\t\t\t\tClear_List(&listbtn);\n\t\t\t\t\tFill_List(&listbtn);\n\t\t\t\t\tif (listbtn.Count() == 0) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tToggleClass * toggle = (ToggleClass *)commands->Extract_Gadget(BUTTON_DELETE);\n\t\t\t\t\t\tif (toggle != NULL) {\n//\t\t\t\t\t\t\ttoggle->IsOn = false;\n\t\t\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t\t\t\ttoggle->Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** If the user clicks on the list, see if the there is a new current\n\t\t\t** item; if so, and if we're in SAVE mode, copy the list item into\n\t\t\t** the save-game description field.\n\t\t\t*/\n\t\t\tcase (BUTTON_LIST | KN_BUTTON):\n\t\t\t\tif (Style != SAVE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (listbtn.Count() && listbtn.Current_Index() != game_idx) {\n\t\t\t\t\tgame_idx = listbtn.Current_Index();\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Copy the game's description, UNLESS it's the empty slot; if\n\t\t\t\t\t** it is, set the edit buffer to empty.\n\t\t\t\t\t*/\n\t\t\t\t\tif (game_idx != 0) {\n\t\t\t\t\t\tstrcpy(game_descr, listbtn.Get_Item(game_idx));\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tStrip any leading parenthesis off of the description.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (game_descr[0] == '(') {\n\t\t\t\t\t\t\tchar * ptr = strchr(game_descr, ')');\n\t\t\t\t\t\t\tif (ptr != NULL) {\n\t\t\t\t\t\t\t\tstrcpy(game_descr, ptr+1);\n\t\t\t\t\t\t\t\tstrtrim(game_descr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgame_descr[0] = 0;\n\t\t\t\t\t}\n\t\t\t\t\teditbtn.Set_Text(game_descr, 40);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** ESC/Cancel: break\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tClear_List(&listbtn);\n\n\tif (cancel) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Clear_List -- clears the list box & Files arrays                          *\n *                                                                                             *\n * This step is essential, because it frees all the strings allocated for list items.          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nvoid LoadOptionsClass::Clear_List(ListClass * list)\n{\n\t/*\n\t** For every item in the list, free its buffer & remove it from the list.\n\t*/\n\tint j = list->Count();\n\tfor (int i = 0; i < j; i++) {\n\t\tlist->Remove_Item(list->Get_Item(0));\n\t}\n\n\t/*\n\t** Clear the array of game numbers\n\t*/\n\tfor (int i = 0; i < Files.Count(); i++) {\n\t\tdelete Files[i];\n\t}\n\tFiles.Clear();\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   06/25/1995 JLB : Shows which saved games are \"(old)\".                                     *\n *=============================================================================================*/\nvoid LoadOptionsClass::Fill_List(ListClass * list)\n{\n#if(0)\t\t//PG\n\tFileEntryClass * fdata;\t// for adding entries to 'Files'\n\tchar descr[DESCRIP_MAX+32];\n\tunsigned scenario;\t\t\t// scenario #\n\tHousesType house;\t\t\t\t// house\n\tstruct find_t ff;\t\t// for _dos_findfirst\n\tint id;\n\n\t/*\n\t** Make sure the list is empty\n\t*/\n\tClear_List(list);\n\n\t/*\n\t** Add the Empty Slot entry\n\t*/\n\tif (Style == SAVE) {\n\t\tfdata = new FileEntryClass;\n\t\tstrcpy(fdata->Descr, Text_String(TXT_EMPTY_SLOT));\n\t\tfdata->DateTime = 0xffffffff;\t// will always be first\n\t\tFiles.Add(fdata);\n\t}\n\n\t/*\n\t** Find all savegame files\n\t*/\n\tint rc = _dos_findfirst(\"SAVEGAME.*\", _A_NORMAL, &ff);\n\n\twhile (!rc) {\n\n\t\tif (stricmp(ff.name, NET_SAVE_FILE_NAME) != 0) {\n\n\t\t\t/*\n\t\t\t** Extract the game ID from the filename\n\t\t\t*/\n\t\t\tid = Num_From_Ext(ff.name);\n\n\t\t\t/*\n\t\t\t** get the game's info; if success, add it to the list\n\t\t\t*/\n\t\t\tbool ok = Get_Savefile_Info(id, descr, &scenario, &house);\n\n\t\t\tfdata = new FileEntryClass;\n\n\t\t\tfdata->Descr[0] = '\\0';\n\t\t\tif (!ok) {\n\t\t\t\tstrcpy(fdata->Descr, Text_String(TXT_OLD_GAME));\n\t\t\t} else {\n\t\t\t\tif (house == HOUSE_USSR || house == HOUSE_UKRAINE) {\n#ifdef WIN32\n\t\t\t\t\tsprintf(fdata->Descr, \"(%s) \", Text_String(TXT_SOVIET));\n#else\n\t\t\t\t\tsprintf(fdata->Descr, \"(%c) \", *Text_String(TXT_SOVIET));\n#endif\n\t\t\t\t} else {\n#ifdef WIN32\n\t\t\t\t\tsprintf(fdata->Descr, \"(%s) \", Text_String(TXT_ALLIES));\n#else\n\t\t\t\t\tsprintf(fdata->Descr, \"(%c) \", *Text_String(TXT_ALLIES));\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tstrncat(fdata->Descr, descr, (sizeof(fdata->Descr)-strlen(fdata->Descr))-1);\n\t\t\tfdata->Valid = ok;\n\t\t\tfdata->Scenario = scenario;\n\t\t\tfdata->House = house;\n\t\t\tfdata->Num = id;\n\t\t\tfdata->DateTime = (((unsigned long)ff.wr_date) << 16) | (unsigned long)ff.wr_time;\n\t\t\tFiles.Add(fdata);\n\t\t}\n\n\t\t/*\n\t\t** Find the next file\n\t\t*/\n\t\trc = _dos_findnext(&ff);\n\t}\n\n\t/*\n\t** If saving a game, determine a unique file ID for the empty slot\n\t*/\n\tif (Style == SAVE) {\n\t\t/*\n\t\t** Find an un-used number to associate with the Empty Slot by looking in\n\t\t** GameNum for each number from 0 to 'N', where 'N' is the # of entries\n\t\t** in the list; if any number isn't found, use that number; otherwise,\n\t\t** use 'N + 1'.\n\t\t*/\n\t\tfor (int i = 0; i < Files.Count(); i++) {\t\t// i = the # we're searching for\n\t\t\tid = -1;\t\t\t\t\t\t\t\t\t\t\t// mark as 'not found'\n\t\t\tfor (int j = 0; j < Files.Count(); j++) {\t// loop through all game ID's\n\t\t\t\tif (Files[j]->Num==i) {\t\t\t\t\t// if found, mark as found\n\t\t\t\t\tid = j;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (id == -1)\tbreak;\t\t\t\t\t\t\t// if ID not found, use this one\n\t\t}\n\n\t\tFiles[0]->Num = i;\t\t\t\t\t\t\t\t// set the empty slot's ID\n\t}\n\n\t/*\n\t** Now sort the list in order of Date/Time (newest first, oldest last)\n\t*/\n\tqsort((void *)(&Files[0]), Files.Count(), sizeof(class FileEntryClass *), LoadOptionsClass::Compare);\n\n\t/*\n\t** Now add every file's name to the list box\n\t*/\n\tfor (int i = 0; i < Files.Count(); i++) {\n\t\tlist->Add_Item(Files[i]->Descr);\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      fname      filename to parse                                                           *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      File number for this name.                                                             *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Num_From_Ext(char * fname)\n{\n\tchar ext[_MAX_EXT];\n\n\t_splitpath(fname, NULL, NULL, NULL, ext);\n\tint num = atoi(ext + 1);\t\t// skip the '.'\n\treturn(num);\n}\n\n\n/***********************************************************************************************\n * LoadOptionsClass::Compare -- for qsort                                                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      p1,p2      ptrs to elements to compare                                                 *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nint LoadOptionsClass::Compare(const void * p1, const void * p2)\n{\n\tclass FileEntryClass * fe1, * fe2;\n\n\tfe1 = *((class FileEntryClass **)p1);\n\tfe2 = *((class FileEntryClass **)p2);\n\n\tif (fe1->DateTime > fe2->DateTime) return(-1);\n\tif (fe1->DateTime < fe2->DateTime) return(1);\n\treturn(0);\n}\n\n"
  },
  {
    "path": "REDALERT/LOADDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LOADDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                         \t\t\t\t\t\t  *\n *                 Project Name : Command & Conquer                        \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                    File Name : LOADDLG.H \t                              \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Programmer : Maria Legg, Joe Bostic, Bill Randolph     \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Start Date : March 19, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                  Last Update : March 19, 1995\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LOADDLG_H\n#define LOADDLG_H\n\nclass FileEntryClass {\n\tpublic:\n\t\tchar Descr[80];\t\t\t\t// save-game description\n\t\tunsigned Scenario;\t\t\t// scenario #\n\t\tHousesType House;\t\t\t\t// house\n\t\tint Num;\t\t\t\t\t\t\t// save file number (from the extension)\n\t\tunsigned long DateTime;\t\t// date/time stamp of file\n\t\tbool Valid;\t\t\t\t\t\t// Is the scenario valid?\n};\n\nclass LoadOptionsClass\n{\n\tpublic:\n\t\t/*\n\t\t** This defines the style of the dialog\n\t\t*/\n\t\ttypedef enum OperationModeEnum {\n\t\t\tNONE = 0,\n\t\t\tLOAD,\n\t\t\tSAVE,\n\t\t\tWWDELETE\n\t\t} LoadStyleType;\n\n\t\tLoadOptionsClass (LoadStyleType style = LoadOptionsClass::NONE);\n\t\t~LoadOptionsClass ();\n\t\tint Process (void);\n\n\n\tprotected:\n\t\t/*\n\t\t** Internal routines\n\t\t*/\n\t\tvoid Clear_List (ListClass *list);\t\t// clears the list & game # array\n\t\tvoid Fill_List (ListClass *list);\t\t// fills the list & game # array\n\t\tint Num_From_Ext (char *fname);\t\t\t// translates filename to file #\n\t\tstatic int Compare(const void *p1, const void *p2); // for qsort()\n\n\t\t/*\n\t\t** This is the requested style of the dialog\n\t\t*/\n\t\tLoadStyleType Style;\n\n\t\t/*\n\t\t** This is an array of pointers to FileEntryClass objects.  These objects\n\t\t** are allocated on the fly as files are found, and pointers to them are\n\t\t** added to the vector list.  Thus, all the objects must be free'd before\n\t\t** the vector list is cleared.  This list is used for sorting the files\n\t\t** by date/time.\n\t\t*/\n\t\tDynamicVectorClass<FileEntryClass *> Files;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/LOGIC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LOGIC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOGIC.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 27, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LogicClass::AI -- Handles AI logic processing for game objects.                           *\n *   LogicClass::Debug_Dump -- Displays logic class status to the mono screen.                 *\n *   LogicClass::Detach -- Detatch the specified target from the logic system.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"logic.h\"\n#include \t\"vortex.h\"\n\nstatic unsigned FramesPerSecond=0;\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * LogicClass::Debug_Dump -- Displays logic class status to the mono screen.                   *\n *                                                                                             *\n *    This is a debugging support routine. It displays the current state of the logic class    *\n *    to the monochrome monitor. It assumes that it is being called once per second.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once per second.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   01/26/1996 JLB : Prints game time value.                                                  *\n *=============================================================================================*/\nvoid LogicClass::Debug_Dump(MonoClass * mono) const\n{\n\t#define RECORDCOUNT\t40\n\t#define RECORDHEIGHT 21\n\tstatic int _framecounter = 0;\n\n\tstatic bool first = true;\n\tif (first) {\n\t\tfirst = false;\n\tmono->Set_Cursor(0, 0);\n\tmono->Print(Text_String(TXT_DEBUG_STRESS));\n\t}\n\n//mono->Set_Cursor(0,0);mono->Printf(\"%d\", AllowVoice);\n\n\n\t_framecounter++;\n\tmono->Set_Cursor(1, 1);mono->Printf(\"%ld\", (long)Scen.Timer);\n\tmono->Set_Cursor(10, 1);mono->Printf(\"%3d\", FramesPerSecond);\n\tmono->Set_Cursor(1, 3);mono->Printf(\"%02d:%02d:%02d\", Scen.Timer / TICKS_PER_HOUR, (Scen.Timer % TICKS_PER_HOUR)/TICKS_PER_MINUTE, (Scen.Timer % TICKS_PER_MINUTE)/TICKS_PER_SECOND);\n\n\tmono->Set_Cursor(1, 11);mono->Printf(\"%3d\", Units.Count());\n\tmono->Set_Cursor(1, 12);mono->Printf(\"%3d\", Infantry.Count());\n\tmono->Set_Cursor(1, 13);mono->Printf(\"%3d\", Aircraft.Count());\n\tmono->Set_Cursor(1, 14);mono->Printf(\"%3d\", Vessels.Count());\n\tmono->Set_Cursor(1, 15);mono->Printf(\"%3d\", Buildings.Count());\n\tmono->Set_Cursor(1, 16);mono->Printf(\"%3d\", Terrains.Count());\n\tmono->Set_Cursor(1, 17);mono->Printf(\"%3d\", Bullets.Count());\n\tmono->Set_Cursor(1, 18);mono->Printf(\"%3d\", Anims.Count());\n\tmono->Set_Cursor(1, 19);mono->Printf(\"%3d\", Teams.Count());\n\tmono->Set_Cursor(1, 20);mono->Printf(\"%3d\", Triggers.Count());\n\tmono->Set_Cursor(1, 21);mono->Printf(\"%3d\", TriggerTypes.Count());\n\tmono->Set_Cursor(1, 22);mono->Printf(\"%3d\", Factories.Count());\n\n\tSpareTicks = min((long)SpareTicks, (long)TIMER_SECOND);\n\n\t/*\n\t**\tCPU utilization record.\n\t*/\n\tmono->Sub_Window(15, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%3d%%\", ((TIMER_SECOND-SpareTicks)*100) / TIMER_SECOND);\n\n\t/*\n\t**\tUpdate the frame rate log.\n\t*/\n\tmono->Sub_Window(22, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%4d\", FramesPerSecond);\n\n\t/*\n\t**\tUpdate the findpath calc record.\n\t*/\n\tmono->Sub_Window(50, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%4d\", PathCount);\n\tPathCount = 0;\n\n\t/*\n\t**\tUpdate the cell redraw record.\n\t*/\n\tmono->Sub_Window(29, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", CellCount);\n\tCellCount = 0;\n\n\t/*\n\t**\tUpdate the target scan record.\n\t*/\n\tmono->Sub_Window(36, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", TargetScan);\n\tTargetScan = 0;\n\n\t/*\n\t**\tSidebar redraw record.\n\t*/\n\tmono->Sub_Window(43, 1, 6, 11);\n\tmono->Scroll();\n\tmono->Set_Cursor(0, 10);\n\tmono->Printf(\"%5d\", SidebarRedraws);\n\tSidebarRedraws = 0;\n\n\t/*\n\t**\tUpdate the CPU utilization chart.\n\t*/\n\tmono->Sub_Window(15, 13, 63, 10);\n\tmono->Pan(1);\n\tmono->Sub_Window(15, 13, 64, 10);\n\tint graph = RECORDHEIGHT * fixed(TIMER_SECOND-SpareTicks, TIMER_SECOND);\n\tfor (int row = 1; row < RECORDHEIGHT; row += 2) {\n\t\tstatic char _barchar[4] = {' ', 220, 0, 219};\n\t\tchar str[2];\n\t\tint index = 0;\n\n\t\tindex |= (graph >= row) ? 0x01 : 0x00;\n\t\tindex |= (graph >= row+1) ? 0x02: 0x00;\n\n\t\tstr[1] = '\\0';\n\t\tstr[0] = _barchar[index];\n\t\tmono->Text_Print(str, 62, 9-(row/2));\n\t}\n\tmono->Sub_Window();\n\n\n\tSpareTicks = 0;\n\tFramesPerSecond = 0;\n}\n#endif\n\n\n/***********************************************************************************************\n * LogicClass::AI -- Handles AI logic processing for game objects.                             *\n *                                                                                             *\n *    This routine is used to perform the AI processing for all game objects. This includes    *\n *    all houses, factories, objects, and teams.                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/29/1994 JLB : Created.                                                                 *\n *   12/17/1994 JLB : Must perform one complete pass rather than bailing early.                *\n *   12/23/1994 JLB : Ensures that no object gets skipped if it was deleted.                   *\n *=============================================================================================*/\nvoid LogicClass::AI(void)\n{\n\tint index;\n\n\tFramesPerSecond++;\n\n\t/*\n\t** Fading to B&W or color due to the chronosphere is handled here.\n\t*/\n\tScen.Do_Fade_AI();\n\n\t/*\n\t**\tHandle any general timer trigger events.\n\t*/\n\tfor (LogicTriggerID = 0; LogicTriggerID < LogicTriggers.Count(); LogicTriggerID++) {\n\t\tTriggerClass * trig = LogicTriggers[LogicTriggerID];\n\n\t\t/*\n\t\t**\tGlobal changed trigger event might be triggered.\n\t\t*/\n\t\tif (Scen.IsGlobalChanged) {\n\t\t\tif (trig->Spring(TEVENT_GLOBAL_SET)) continue;\n\t\t\tif (trig->Spring(TEVENT_GLOBAL_CLEAR)) continue;\n\t\t}\n\n\t\t/*\n\t\t**\tBridge change event.\n\t\t*/\n\t\tif (Scen.IsBridgeChanged) {\n\t\t\tif (trig->Spring(TEVENT_ALL_BRIDGES_DESTROYED)) continue;\n\t\t}\n\n\t\t/*\n\t\t**\tGeneral time expire trigger events can be sprung without warning.\n\t\t*/\n\t\tif (trig->Spring(TEVENT_TIME)) continue;\n\n\t\t/*\n\t\t**\tThe mission timer expiration trigger event might spring if the timer is active\n\t\t**\tbut at a value of zero.\n\t\t*/\n\t\tif (Scen.MissionTimer.Is_Active() && Scen.MissionTimer == 0) {\n\t\t\tif (trig->Spring(TEVENT_MISSION_TIMER_EXPIRED)) continue;\n\t\t}\n\t}\n\n\tif (Scen.MissionTimer.Is_Active()) {\n\t\tlong secs = Scen.MissionTimer / TICKS_PER_SECOND;\n\t\tlong mins = secs / 60;\n\t\tlong hours = mins / 60;\n\t\tsecs %= 60;\n\t\tmins %= 60;\n\n\t\t/*\n\t\t**\tSpeak mission timer reminders.\n\t\t*/\n\t\tVoxType vox = VOX_NONE;\n\t\tif (Scen.MissionTimer == (1 * TICKS_PER_MINUTE)) vox = VOX_TIME_1;\n\t\tif (Scen.MissionTimer == (2 * TICKS_PER_MINUTE)) vox = VOX_TIME_2;\n\t\tif (Scen.MissionTimer == (3 * TICKS_PER_MINUTE)) vox = VOX_TIME_3;\n\t\tif (Scen.MissionTimer == (4 * TICKS_PER_MINUTE)) vox = VOX_TIME_4;\n\t\tif (Scen.MissionTimer == (5 * TICKS_PER_MINUTE)) vox = VOX_TIME_5;\n\t\tif (Scen.MissionTimer == (10 * TICKS_PER_MINUTE)) vox = VOX_TIME_10;\n\t\tif (Scen.MissionTimer == (20 * TICKS_PER_MINUTE)) vox = VOX_TIME_20;\n\t\tif (Scen.MissionTimer == (30 * TICKS_PER_MINUTE)) vox = VOX_TIME_30;\n\t\tif (Scen.MissionTimer == (40 * TICKS_PER_MINUTE)) vox = VOX_TIME_40;\n\t\tif (vox != VOX_NONE) {\n\t\t\tSpeak(vox);\n\t\t\tMap.FlasherTimer = 7;\n\t\t}\n\t}\n\n\t/*\n\t**\tClean up any status values that were maintained only for logic trigger\n\t**\tpurposes.\n\t*/\n\tif (Scen.MissionTimer.Is_Active() && Scen.MissionTimer == 0) {\n\t\tScen.MissionTimer.Stop();\n\t\tMap.Flag_To_Redraw(true);\t\t\t// Used only to cause tabs to redraw in new state.\n\t}\n\tScen.IsGlobalChanged = false;\n\tScen.IsBridgeChanged = false;\n\t/*\n\t**\tShadow creeping back over time is handled here.\n\t*/\n\tif (Special.IsShadowGrow && Rule.ShroudRate != 0 && Scen.ShroudTimer == 0) {\n\t\tScen.ShroudTimer = TICKS_PER_MINUTE * Rule.ShroudRate;\n\t\t\n\t\t/*\n\t\t** Do this for all players in Client/Server multiplayer. ST - 8/9/2019 10:23AM\n\t\t*/\n\t\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tMap.Encroach_Shadow(PlayerPtr);\n\t\t} else {\n\t\t\tfor (int i=0 ; i<Session.Players.Count() ; i++) {\n\t\t\t\tHouseClass *player_ptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\t\tif (player_ptr && player_ptr->IsHuman) {\n\t\t\t\t\tMap.Encroach_Shadow(player_ptr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t}\n\n\t/*\n\t**\tTeam AI is processed.\n\t*/\n\tfor (index = 0; index < Teams.Count(); index++) {\n\t\tTeams.Ptr(index)->AI();\n\t}\n\n\t/*\n\t** If there's a time quake, handle it here.\n\t*/\n\tif (TimeQuake) {\n\t\tSound_Effect(VOC_KABOOM15);\n\t\tShake_The_Screen(8);\n\t}\n\n\tChronalVortex.AI();\n\t/*\n\t**\tAI for all sentient objects is processed.\n\t*/\n\tfor (index = 0; index < Count(); index++) {\n\t\tObjectClass * obj = (*this)[index];\n\t\tint count = Count();\n\n\t\tBStart(BENCH_AI);\n\t\tobj->AI();\n\t\tBEnd(BENCH_AI);\n\n\t\tif (TimeQuake && obj != NULL && obj->IsActive && !obj->IsInLimbo && obj->Strength) {\n\t\t\tint damage = (int)obj->Class_Of().MaxStrength * Rule.QuakeDamagePercent;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (TimeQuakeCenter) {\n\t\t\t\tif(::Distance(obj->As_Target(),TimeQuakeCenter)/256 < MTankDistance) {\n\t\t\t\t\tswitch(obj->What_Am_I()) {\n\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\tdamage = QuakeInfantryDamage;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\tdamage = QuakeBuildingDamage * (int)obj->Class_Of().MaxStrength;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tdamage = QuakeUnitDamage * (int)obj->Class_Of().MaxStrength;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (damage) {\n\t\t\t\t\t\tobj->Clicked_As_Target(HOUSE_COUNT); // 2019/09/20 JAS - Added record of who clicked on the object, HOUSE_COUNT is used to mark for all houses\n\t\t\t\t\t\tnew AnimClass(ANIM_MINE_EXP1, obj->Center_Coord());\n\t\t\t\t\t}\n\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n\t\t\t}\n#else\n\t\t\tobj->Take_Damage(damage, 0, WARHEAD_AP, 0, true);\n#endif\n\t\t}\n\t\t/*\n\t\t**\tIf the object was destroyed in the process of performing its AI, then\n\t\t**\tadjust the index so that no object gets skipped.\n\t\t*/\n\t\tint count_diff = Count() - count;\n\t\tif (count_diff < 0) {\n\t\t\tindex += count_diff;\n\t\t}\n\t}\n\tHouseClass::Recalc_Attributes();\n\n\t/*\n\t**\tMap related logic is performed.\n\t*/\n\tMap.Logic();\n\n\t/*\n\t**\tFactory processing is performed.\n\t*/\n\tfor (index = 0; index < Factories.Count(); index++) {\n\t\tFactories.Ptr(index)->AI();\n\t}\n\n\t/*\n\t**\tHouse processing is performed.\n\t*/\n#ifdef FIXIT_VERSION_3\n\tif( Session.Type != GAME_NORMAL )\n\t{\n\t\tfor (HousesType house = HOUSE_MULTI1; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr && hptr->IsActive) {\n\t\t\t\thptr->AI();\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr && hptr->IsActive) {\n\t\t\t\thptr->AI();\n\t\t\t}\n\t\t}\n\t}\n#else\t//\tAI() is called redundantly 12 times in multiplayer games here. ajw\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr && hptr->IsActive) {\n\t\t\thptr->AI();\n\t\t}\n\t}\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tif( Session.Type != GAME_NORMAL && Scen.AutoSonarTimer == 0 )\n\t{\n\t\tif( bAutoSonarPulse )\n\t\t{\n\t\t\tMap.Activate_Pulse();\n\t\t\tSound_Effect(VOC_SONAR);\n\t\t\tbAutoSonarPulse = false;\n\t\t}\n#define AUTOSONAR_PERIOD\tTICKS_PER_SECOND * 40;\n\t\tScen.AutoSonarTimer = AUTOSONAR_PERIOD;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * LogicClass::Detach -- Detatch the specified target from the logic system.                   *\n *                                                                                             *\n *    This routine is called when the specified target object is about to be removed from the  *\n *    game system and all references to it must be severed. The only thing that the logic      *\n *    system looks for in this case is to see if the target refers to a trigger and if so,     *\n *    it scans through the trigger list and removes all references to it.                      *\n *                                                                                             *\n * INPUT:   target   -- The target to remove from the sytem.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid LogicClass::Detach(TARGET target, bool )\n{\n\t/*\n\t**\tRemove any triggers from the logic trigger list.\n\t*/\n\tif (Is_Target_Trigger(target)) {\n\t\tfor (int index = 0; index < LogicTriggers.Count(); index++) {\n\t\t\tif (As_Trigger(target) == LogicTriggers[index]) {\n\t\t\t\tLogicTriggers.Delete(index);\n\t\t\t\tindex--;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * LogicClass::Clear_Recently_Created_Bits -- Clear out the indicators that objects were       *\n *                                            recently created                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   8/19/2019 5:47PM ST : Created.                                                            *\n *=============================================================================================*/\nvoid LogicClass::Clear_Recently_Created_Bits(void)\n{\n\tfor (int index = 0; index < Count(); index++) {\n\t\tObjectClass * obj = (*this)[index];\n\t\tobj->IsRecentlyCreated = false;\n\t}\n}"
  },
  {
    "path": "REDALERT/LOGIC.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LOGIC.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LOGIC.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 29, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 29, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef LOGIC_H\n#define LOGIC_H\n\n#include\t\"layer.h\"\n\n/***********************************************************************************************\n**\tGame logic processing is controlled by this class. The graphic and AI logic is handled\n**\tseparately so that on slower machines, the graphic display is least affected.\n*/\nclass LogicClass : public LayerClass\n{\n\tpublic:\n\t\tvoid AI(void);\n\t\tvoid Detach(TARGET target, bool all=true);\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\t\n\t\t/*\n\t\t** Added. ST - 8/19/2019 5:46PM\n\t\t*/\n\t\tvoid Clear_Recently_Created_Bits(void);\n};\n#endif"
  },
  {
    "path": "REDALERT/LZO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _LZO_H\n#define _LZO_H\n\n#include \"lzoconf.h\"\n\nint lzo1x_1_compress ( \tconst lzo_byte *in ,\n\t\t\t\t\t\t\t\tlzo_uint  in_len,\n                         lzo_byte *out,\n\t\t\t\t\t\t\t\tlzo_uint *out_len,\n                         lzo_voidp wrkmem );\n\n\nint lzo1x_decompress\t(  const lzo_byte *in ,\n\t\t\t\t\t\t\t\tlzo_uint  in_len,\n\t\t\t\t\t\t\t\tlzo_byte *out,\n\t\t\t\t\t\t\t\tlzo_uint *out_len,\n                         lzo_voidp );\n\n\n\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZO1X.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* lzo1x.h -- public interface of the LZO1X compression algorithm\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#ifndef __LZO1X_H\n#define __LZO1X_H\n\n#include \"lzoconf.h\"\n\n//#ifdef __cplusplus\n//extern \"C\" {\n//#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n/* Memory required for the wrkmem parameter.\n * When the required size is 0, you can also pass a NULL pointer.\n */\n\n#define LZO1X_MEM_COMPRESS      ((lzo_uint) (16384L * sizeof(lzo_byte *)))\n#define LZO1X_MEM_DECOMPRESS    (0)\n\n\n/* fast decompression */\nLZO_EXTERN(int)\nlzo1x_decompress        ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem /* NOT USED */ );\n\n/* safe decompression with overrun testing */\nLZO_EXTERN(int)\nlzo1x_decompress_x      ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem /* NOT USED */ );\n\n\n/***********************************************************************\n//\n************************************************************************/\n\nLZO_EXTERN(int)\nlzo1x_1_compress        ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem );\n\n\n/***********************************************************************\n// better compression ratio at the cost of more memory and time\n************************************************************************/\n\n#define LZO1X_999_MEM_COMPRESS  ((lzo_uint) (14 * 16384L * sizeof(short)))\n\nLZO_EXTERN(int)\nlzo1x_999_compress      ( const lzo_byte *src, lzo_uint  src_len,\n                                lzo_byte *dst, lzo_uint *dst_len,\n                                lzo_voidp wrkmem );\n\n\n//#ifdef __cplusplus\n//} /* extern \"C\" */\n//#endif\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "REDALERT/LZO1X_C.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* lzo1x_c.c -- standalone LZO1X-1 compressor\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#include \"lzo1x.h\"\n#ifndef NDEBUG\n#define NDEBUG\n#endif\n#include <assert.h>\n#include \"lzo_conf.h\"\n\n#if !defined(LZO1X) && !defined(LZO1Y)\n#  define LZO1X\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#define M1_MAX_OFFSET\t0x0400\n#if defined(LZO1X)\n#define M2_MAX_OFFSET\t0x0800\n#elif defined(LZO1Y)\n#define M2_MAX_OFFSET\t0x0400\n#endif\n#define M3_MAX_OFFSET\t0x4000\n#define M4_MAX_OFFSET\t0xbfff\n\n#define MX_MAX_OFFSET\t(M1_MAX_OFFSET + M2_MAX_OFFSET)\n\n#define M1_MARKER\t\t0\n#define M2_MARKER\t\t64\n#define M3_MARKER\t\t32\n#define M4_MARKER\t\t16\n\n\n#define _DV2(p,shift1,shift2) \\\n\t\t(((( (lzo_uint)(p[2]) << shift1) ^ p[1]) << shift2) ^ p[0])\n#define DVAL_NEXT(dv,p) \\\n\t\tdv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint)(p[2]) << (2*5)))\n#define _DV(p,shift) \t\t_DV2(p,shift,shift)\n#define DVAL_FIRST(dv,p)\tdv = _DV((p),5)\n#define _DINDEX(dv,p)\t\t((40799u * (dv)) >> 5)\n#define DINDEX(dv,p)\t\t(((_DINDEX(dv,p)) & 0x3fff) << 0)\n#define UPDATE_D(dict,cycle,dv,p)\t\tdict[ DINDEX(dv,p) ] = (p)\n#define UPDATE_I(dict,cycle,index,p)\tdict[index] = (p)\n\n\n/***********************************************************************\n// compress a block of data.\n************************************************************************/\n\nstatic int do_compress(const lzo_byte *in , lzo_uint  in_len,\n\tlzo_byte *out, lzo_uint *out_len,\n\tlzo_voidp wrkmem )\n{\n\tregister const lzo_byte *ip;\n\tlzo_uint dv;\n\tlzo_byte *op;\n\tconst lzo_byte * const in_end = in + in_len;\n\tconst lzo_byte * const ip_end = in + in_len - 9 - 4;\n\tconst lzo_byte *ii;\n\tconst lzo_bytepp const dict = (const lzo_bytepp) wrkmem;\n\n\top = out;\n\tip = in;\n\tii = ip;\n\n\tDVAL_FIRST(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\tDVAL_NEXT(dv,ip);  UPDATE_D(dict,cycle,dv,ip); ip++;\n\n\twhile (1) {\n\t\tregister const lzo_byte *m_pos;\n\t\tlzo_uint m_len;\n\t\tlzo_ptrdiff_t m_off;\n\t\tlzo_uint lit;\n\n\t\tlzo_uint dindex = DINDEX(dv,ip);\n\t\tm_pos = dict[dindex];\n\t\tUPDATE_I(dict,cycle,dindex,ip);\n\n\n\t\tif (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) {\n\t\t}\n#if defined(LZO_UNALIGNED_OK_2)\n\t\telse\n\t\t\tif (* (unsigned short *) m_pos != * (unsigned short *) ip)\n#else\n\t\telse\n\t\t\tif (m_pos[0] != ip[0] || m_pos[1] != ip[1])\n#endif\n\t\t{\n\t\t} else {\n\t\t\tif (m_pos[2] == ip[2]) {\n\t\t\t\tlit = ip - ii;\n\t\t\t\tm_pos += 3;\n\t\t\t\tif (m_off <= M2_MAX_OFFSET)\n\t\t\t\t\tgoto match;\n\n\t\t\t\t/* better compression, but slower */\n\t\t\t\tif (lit == 3) {\n\t\t\t\t\tassert(op - 2 > out); op[-2] |= LZO_BYTE(3);\n\t\t\t\t\t*op++ = *ii++; *op++ = *ii++; *op++ = *ii++;\n\t\t\t\t\tgoto code_match;\n\t\t\t\t}\n\n\t\t\t\tif (*m_pos == ip[3]) {\n\t\t\t\t\tgoto match;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* still need a better way for finding M1 matches */\n\t\t\t}\n\t\t}\n\n\n\t/* a literal */\n\t\t++ip;\n\t\tif (ip >= ip_end) {\n\t\t\tbreak;\n\t\t}\n\t\tDVAL_NEXT(dv,ip);\n\t\tcontinue;\n\n\n\t/* a match */\n\nmatch:\n\n\t\t/* store current literal run */\n\t\tif (lit > 0) {\n\t\t\tregister lzo_uint t = lit;\n\n\t\t\tif (t <= 3) {\n\t\t\t\tassert(op - 2 > out);\n\t\t\t\top[-2] |= LZO_BYTE(t);\n\t\t\t} else {\n\t\t\t\tif (t <= 18) {\n\t\t\t\t\t*op++ = LZO_BYTE(t - 3);\n\t\t\t\t} else {\n\t\t\t\t\tregister lzo_uint tt = t - 18;\n\n\t\t\t\t\t*op++ = 0;\n\t\t\t\t\twhile (tt > 255) {\n\t\t\t\t\t\ttt -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(tt > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(tt);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdo {\n\t\t\t\t*op++ = *ii++;\n\t\t\t} while (--t > 0);\n\t\t}\n\n\n\t\t/* code the match */\ncode_match:\n\t\tassert(ii == ip);\n\t\tip += 3;\n\t\tif (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||\n\t\t    *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)\n\t\t{\n\t\t\t--ip;\n\t\t\tm_len = ip - ii;\n\t\t\tassert(m_len >= 3); assert(m_len <= 8);\n\n\t\t\tif (m_off <= M2_MAX_OFFSET) {\n\t\t\t\tm_off -= 1;\n\t\t\t\t*op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));\n\t\t\t\t*op++ = LZO_BYTE(m_off >> 3);\n\t\t\t} else {\n\t\t\t\tif (m_off <= M3_MAX_OFFSET) {\n\t\t\t\t\tm_off -= 1;\n\t\t\t\t\t*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));\n\t\t\t\t\tgoto m3_m4_offset;\n\t\t\t\t} else {\n\t\t\t\t\tm_off -= 0x4000;\n\t\t\t\t\tassert(m_off > 0); assert(m_off <= 0x7fff);\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER |\n\t\t\t\t\t                 ((m_off & 0x4000) >> 11) | (m_len - 2));\n\t\t\t\t\tgoto m3_m4_offset;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst lzo_byte *end;\n\t\t\tend = in_end;\n\t\t\twhile (ip < end && *m_pos == *ip) {\n\t\t\t\tm_pos++;\n\t\t\t\tip++;\n\t\t\t}\n\t\t\tm_len = (ip - ii);\n\t\t\tassert(m_len >= 3);\n\n\t\t\tif (m_off <= M3_MAX_OFFSET) {\n\t\t\t\tm_off -= 1;\n\t\t\t\tif (m_len <= 33) {\n\t\t\t\t\t*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));\n\t\t\t\t} else {\n\t\t\t\t\tm_len -= 33;\n\t\t\t\t\t*op++ = M3_MARKER | 0;\n\t\t\t\t\tgoto m3_m4_len;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm_off -= 0x4000;\n\t\t\t\tassert(m_off > 0); assert(m_off <= 0x7fff);\n\t\t\t\tif (m_len <= 9) {\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER |\n\t\t\t\t\t                 ((m_off & 0x4000) >> 11) | (m_len - 2));\n\t\t\t\t} else {\n\t\t\t\t\tm_len -= 9;\n\t\t\t\t\t*op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));\nm3_m4_len:\n\t\t\t\t\twhile (m_len > 255) {\n\t\t\t\t\t\tm_len -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(m_len > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(m_len);\n\t\t\t\t}\n\t\t\t}\n\nm3_m4_offset:\n\t\t\t*op++ = LZO_BYTE((m_off & 63) << 2);\n\t\t\t*op++ = LZO_BYTE(m_off >> 6);\n\t\t}\n\n\t\tii = ip;\n\t\tif (ip >= ip_end) {\n\t\t\tbreak;\n\t\t}\n\t\tDVAL_FIRST(dv,ip);\n\t}\n\n\t/* store final literal run */\n\tif (in_end - ii > 0) {\n\t\tregister lzo_uint t = in_end - ii;\n\n\t\tif (op == out && t <= 238) {\n\t\t\t*op++ = LZO_BYTE(17 + t);\n\t\t} else {\n\t\t\tif (t <= 3) {\n\t\t\t\top[-2] |= LZO_BYTE(t);\n\t\t\t} else {\n\t\t\t\tif (t <= 18) {\n\t\t\t\t\t*op++ = LZO_BYTE(t - 3);\n\t\t\t\t} else {\n\t\t\t\t\tregister lzo_uint tt = t - 18;\n\n\t\t\t\t\t*op++ = 0;\n\t\t\t\t\twhile (tt > 255) {\n\t\t\t\t\t\ttt -= 255;\n\t\t\t\t\t\t*op++ = 0;\n\t\t\t\t\t}\n\t\t\t\t\tassert(tt > 0);\n\t\t\t\t\t*op++ = LZO_BYTE(tt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdo {\n\t\t\t*op++ = *ii++;\n\t\t} while (--t > 0);\n\t}\n\n\t*out_len = op - out;\n\treturn LZO_E_OK;\n}\n\n\n/***********************************************************************\n// public entry point\n************************************************************************/\n\nint lzo1x_1_compress     ( const lzo_byte *in , lzo_uint  in_len,\n                                 lzo_byte *out, lzo_uint *out_len,\n                                 lzo_voidp wrkmem )\n{\n\tlzo_byte *op = out;\n\tint r = LZO_E_OK;\n\n\tif (in_len <= 0)\n\t\t*out_len = 0;\n\telse if (in_len <= 9 + 4)\n\t{\n\t\t*op++ = LZO_BYTE(17 + in_len);\n\t\tdo *op++ = *in++; while (--in_len > 0);\n\t\t*out_len = op - out;\n\t}\n\telse\n\t\tr = do_compress(in,in_len,out,out_len,wrkmem);\n\n\tif (r == LZO_E_OK)\n\t{\n\t\top = out + *out_len;\n\t\t*op++ = M4_MARKER | 1;\n\t\t*op++ = 0;\n\t\t*op++ = 0;\n\t\t*out_len += 3;\n\t}\n\n\treturn r;\n}\n\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "REDALERT/LZO1X_D.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* lzo1x_d.c -- standalone LZO1X decompressor\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#include \"lzo1x.h\"\n#ifndef NDEBUG\n#define NDEBUG\n#endif\n#include <assert.h>\n\n#if !defined(LZO1X) && !defined(LZO1Y)\n#  define LZO1X\n#endif\n\n#if 1\n#  define TEST_IP\t\t\t\t1\n#else\n#  define TEST_IP\t\t\t\t(ip < ip_end)\n#endif\n\n\n/***********************************************************************\n// decompress a block of data.\n************************************************************************/\n\nint lzo1x_decompress     ( const lzo_byte *in , lzo_uint  in_len,\n                                 lzo_byte *out, lzo_uint *out_len,\n                                 lzo_voidp )\n{\n\tregister lzo_byte *op;\n\tregister const lzo_byte *ip;\n\tregister lzo_uint t;\n\tregister const lzo_byte *m_pos;\n\tconst lzo_byte * const ip_end = in + in_len;\n\n\t*out_len = 0;\n\n\top = out;\n\tip = in;\n\n\tif (*ip > 17)\n\t{\n\t\tt = *ip++ - 17;\n\t\tgoto first_literal_run;\n\t}\n\n\twhile (TEST_IP)\n\t{\n\t\tt = *ip++;\n\t\tif (t >= 16)\n\t\t\tgoto match;\n\t\t/* a literal run */\n\t\tif (t == 0)\n\t\t{\n\t\t\tt = 15;\n\t\t\twhile (*ip == 0)\n\t\t\t\tt += 255, ip++;\n\t\t\tt += *ip++;\n\t\t}\n\t\t/* copy literals */\n\t\t*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;\nfirst_literal_run:\n\t\tdo *op++ = *ip++; while (--t > 0);\n\n\n\t\tt = *ip++;\n\n\t\tif (t >= 16)\n\t\t\tgoto match;\n#if defined(LZO1X)\n\t\tm_pos = op - 1 - 0x800;\n#elif defined(LZO1Y)\n\t\tm_pos = op - 1 - 0x400;\n#endif\n\t\tm_pos -= t >> 2;\n\t\tm_pos -= *ip++ << 2;\n\t\t*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;\n\t\tgoto match_done;\n\n\n\t\t/* handle matches */\n\t\twhile (TEST_IP)\n\t\t{\n\t\t\tif (t < 16)\t\t\t\t\t\t/* a M1 match */\n\t\t\t{\n\t\t\t\tm_pos = op - 1;\n\t\t\t\tm_pos -= t >> 2;\n\t\t\t\tm_pos -= *ip++ << 2;\n\t\t\t\t*op++ = *m_pos++; *op++ = *m_pos++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\nmatch:\n\t\t\t\tif (t >= 64)\t\t\t\t/* a M2 match */\n\t\t\t\t{\n\t\t\t\t\tm_pos = op - 1;\n#if defined(LZO1X)\n\t\t\t\t\tm_pos -= (t >> 2) & 7;\n\t\t\t\t\tm_pos -= *ip++ << 3;\n\t\t\t\t\tt = (t >> 5) - 1;\n#elif defined(LZO1Y)\n\t\t\t\t\tm_pos -= (t >> 2) & 3;\n\t\t\t\t\tm_pos -= *ip++ << 2;\n\t\t\t\t\tt = (t >> 4) - 3;\n#endif\n\t\t\t\t}\n\t\t\t\telse if (t >= 32)\t\t\t/* a M3 match */\n\t\t\t\t{\n\t\t\t\t\tt &= 31;\n\t\t\t\t\tif (t == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tt = 31;\n\t\t\t\t\t\twhile (*ip == 0)\n\t\t\t\t\t\t\tt += 255, ip++;\n\t\t\t\t\t\tt += *ip++;\n\t\t\t\t\t}\n\t\t\t\t\tm_pos = op - 1;\n\t\t\t\t\tm_pos -= *ip++ >> 2;\n\t\t\t\t\tm_pos -= *ip++ << 6;\n\t\t\t\t}\n\t\t\t\telse\t\t\t\t\t\t/* a M4 match */\n\t\t\t\t{\n\t\t\t\t\tm_pos = op;\n\t\t\t\t\tm_pos -= (t & 8) << 11;\n\t\t\t\t\tt &= 7;\n\t\t\t\t\tif (t == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tt = 7;\n\t\t\t\t\t\twhile (*ip == 0)\n\t\t\t\t\t\t\tt += 255, ip++;\n\t\t\t\t\t\tt += *ip++;\n\t\t\t\t\t}\n\t\t\t\t\tm_pos -= *ip++ >> 2;\n\t\t\t\t\tm_pos -= *ip++ << 6;\n\t\t\t\t\tif (m_pos == op)\n\t\t\t\t\t\tgoto eof_found;\n\t\t\t\t\tm_pos -= 0x4000;\n\t\t\t\t}\n\t\t\t\t*op++ = *m_pos++; *op++ = *m_pos++;\n\t\t\t\tdo *op++ = *m_pos++; while (--t > 0);\n\t\t\t}\n\nmatch_done:\n\t\t\tt = ip[-2] & 3;\n\t\t\tif (t == 0)\n\t\t\t\tbreak;\n\t\t\t/* copy literals */\n\t\t\tdo *op++ = *ip++; while (--t > 0);\n\t\t\tt = *ip++;\n\t\t}\n\t}\n\n\t/* ip == ip_end and no EOF code was found */\n\n\t//Unreachable - ST 9/5/96 5:07PM\n\t//*out_len = op - out;\n\t//return (ip == ip_end ? LZO_E_EOF_NOT_FOUND : LZO_E_ERROR);\n\neof_found:\n\tassert(t == 1);\n\t*out_len = op - out;\n\treturn (ip == ip_end ? LZO_E_OK : LZO_E_ERROR);\n}\n\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "REDALERT/LZOCONF.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* lzoconf.h -- configuration for the LZO real-time data compression library\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n#ifndef __LZOCONF_H\n#define __LZOCONF_H\n\n#define LZO_VERSION             0x0200\n#define LZO_VERSION_STRING      \"0.20\"\n#define LZO_VERSION_DATE        \"11 Aug 1996\"\n\n\n#include <limits.h>             /* CHAR_BIT, UINT_MAX, ULONG_MAX */\n#if !defined(CHAR_BIT) || (CHAR_BIT != 8)\n#  error invalid CHAR_BIT\n#endif\n\n//#ifdef __cplusplus\n//extern \"C\" {\n//#endif\n\n\n/***********************************************************************\n// defines\n************************************************************************/\n\n#if defined(__MSDOS__) || defined(MSDOS)\n#  define __LZO_MSDOS\n#  if (UINT_MAX < 0xffffffffL)\n#    define __LZO_MSDOS16 \n#  endif\n#endif\n\n\n/***********************************************************************\n// integral and pointer types\n************************************************************************/\n\n/* Unsigned type with 32 bits or more */\n#if (UINT_MAX >= 0xffffffffL)\n   typedef unsigned int     lzo_uint;\n   typedef int              lzo_int;\n#  define LZO_UINT_MAX      UINT_MAX\n#elif (ULONG_MAX >= 0xffffffffL)\n   typedef unsigned long    lzo_uint;\n   typedef long             lzo_int;\n#  define LZO_UINT_MAX      ULONG_MAX\n#else\n#  error lzo_uint\n#endif\n\n\n/* Memory model that allows to access memory at offsets of lzo_uint.\n * Huge pointers (16 bit MSDOS) are somewhat slow, but they work\n * fine and I really don't care about 16 bit compiler\n * optimizations nowadays.\n */\n#if (LZO_UINT_MAX <= UINT_MAX)\n#  define __LZO_MMODEL\n#elif defined(__LZO_MSDOS16)\n#  define __LZO_MMODEL      huge\n#  define __LZO_ENTRY       __cdecl\n#else\n#  error __LZO_MMODEL\n#endif\n\n\n/* no typedef here because of const-pointer issues */\n#define lzo_byte            unsigned char __LZO_MMODEL\n#define lzo_voidp           void __LZO_MMODEL *\n#define lzo_bytep           unsigned char __LZO_MMODEL *\n#define lzo_uintp           lzo_uint __LZO_MMODEL *\n#define lzo_intp            lzo_int __LZO_MMODEL *\n#define lzo_voidpp          lzo_voidp __LZO_MMODEL * \n#define lzo_bytepp          lzo_bytep __LZO_MMODEL * \n\n\n/* Unsigned type that can store all bits of a lzo_voidp */\ntypedef unsigned long       lzo_ptr_t;\n\n/* Align a pointer on a boundary that is a multiple of 'size' */\n#define LZO_ALIGN(ptr,size) \\\n    ((lzo_voidp) (((lzo_ptr_t)(ptr) + (size)-1) & ~((lzo_ptr_t)((size)-1))))\n\n\n/***********************************************************************\n// function types\n************************************************************************/\n\n//#ifdef __cplusplus\n//#  define LZO_EXTERN_C          extern \"C\"\n//#else\n#  define LZO_EXTERN_C          extern\n//#endif\n\n\n#if !defined(__LZO_ENTRY)       /* calling convention */\n#  define __LZO_ENTRY\n#endif\n#if !defined(__LZO_EXPORT)      /* DLL export (and maybe size) information */\n#  define __LZO_EXPORT\n#endif\n\n#if !defined(LZO_EXTERN)\n#  define LZO_EXTERN(_rettype)  LZO_EXTERN_C _rettype __LZO_ENTRY __LZO_EXPORT\n#endif\n\n\ntypedef int __LZO_ENTRY\n(__LZO_EXPORT *lzo_compress_t)  ( const lzo_byte *src, lzo_uint  src_len,\n                                        lzo_byte *dst, lzo_uint *dst_len,\n                                        lzo_voidp wrkmem );\n\ntypedef int __LZO_ENTRY\n(__LZO_EXPORT *lzo_decompress_t)( const lzo_byte *src, lzo_uint  src_len,\n                                        lzo_byte *dst, lzo_uint *dst_len,\n                                        lzo_voidp wrkmem );\n\n\n/* a progress indicator callback function */\ntypedef void __LZO_ENTRY\n(__LZO_EXPORT *lzo_progress_callback_t)(lzo_uint,lzo_uint);\n\n\n/***********************************************************************\n// error codes and prototypes\n************************************************************************/\n\n/* Error codes for the compression/decompression functions. Negative\n * values are errors, positive values will be used for special but\n * normal events.\n */\n#define LZO_E_OK                    0\n#define LZO_E_ERROR                 (-1)\n#define LZO_E_NOT_COMPRESSIBLE      (-2)    /* not used right now */\n#define LZO_E_EOF_NOT_FOUND         (-3)\n#define LZO_E_INPUT_OVERRUN         (-4)\n#define LZO_E_OUTPUT_OVERRUN        (-5)\n#define LZO_E_LOOKBEHIND_OVERRUN    (-6)\n#define LZO_E_OUT_OF_MEMORY         (-7)    /* not used right now */\n\n\n/* this should be the first function you call. Check the return code ! */\nLZO_EXTERN(int) lzo_init(void);\n\n/* version functions (useful for shared libraries) */\nLZO_EXTERN(unsigned) lzo_version(void);\nLZO_EXTERN(const char *) lzo_version_string(void);\n\n/* string functions */\nLZO_EXTERN(int)\nlzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);\nLZO_EXTERN(lzo_voidp)\nlzo_memset(lzo_voidp _s, int _c, lzo_uint _len);\n\n/* checksum functions */\nLZO_EXTERN(lzo_uint)\nlzo_adler32(lzo_uint _adler, const lzo_byte *_buf, lzo_uint _len);\n\n/* misc. */\nLZO_EXTERN(int) lzo_assert(int _expr);\nLZO_EXTERN(int) _lzo_config_check(void);\n\n\n//#ifdef __cplusplus\n//} /* extern \"C\" */\n//#endif\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n"
  },
  {
    "path": "REDALERT/LZOPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZOPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LZWPipe::LZWPipe -- Constructor for the LZO processor pipe.                               *\n *   LZWPipe::Put -- Send some data through the LZO processor pipe.                            *\n *   LZWPipe::~LZWPipe -- Deconstructor for the LZO pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lzopipe.h\"\n#include\t\"lzo.h\"\n#include\t\"buff.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZOPipe::LZOPipe -- Constructor for the LZO processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LZOPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOPipe::LZOPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LZOPipe::~LZOPipe -- Deconstructor for the LZO pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOPipe::~LZOPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZOPipe::Put -- Send some data through the LZO processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LZO processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < ((int)sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tunsigned int length = sizeof (Buffer2);\n\t\t\t\t\tlzo1x_decompress ((unsigned char*)Buffer, BlockHeader.CompCount, (unsigned char*)Buffer2, &length, NULL);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\t\tchar *dictionary = new char [64*1024];\n\t\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, BlockSize, (unsigned char*)Buffer2, &len, dictionary);\n\t\t\t\tdelete [] dictionary;\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress ((unsigned char*)source, BlockSize, (unsigned char*)Buffer2, &len, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LZOPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LZO decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tunsigned int len = sizeof (Buffer2);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, Counter, (unsigned char *)Buffer2, &len, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "REDALERT/LZOPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZOPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZOPIPE_H\n#define LZOPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LZO compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LZOPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZOPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LZOPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tProbably dont need this anymore as LZO decompresses into a staging buffer.\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZOPipe(LZOPipe & rvalue);\n\t\tLZOPipe & operator = (LZOPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZOSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZOSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZOStraw::Get -- Fetch data through the LZO processor.                                    *\n *   LZOStraw::LZOStraw -- Constructor for LZO straw object.                                   *\n *   LZOStraw::~LZOStraw -- Destructor for the LZO straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzostraw.h\"\n#include\t\"lzo.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZOStraw::LZOStraw -- Constructor for LZO straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZO straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOStraw::LZOStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZOStraw::~LZOStraw -- Destructor for the LZO straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZOStraw::~LZOStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZOStraw::Get -- Fetch data through the LZO processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZOStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tchar *staging_buffer = new char [BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(staging_buffer, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\t\t\tunsigned int length = sizeof(Buffer);\n\t\t\tlzo1x_decompress ((unsigned char*)staging_buffer, BlockHeader.CompCount, (unsigned char*)Buffer, &length, NULL);\n\t\t\tdelete [] staging_buffer;\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tunsigned int length = sizeof (Buffer2) - sizeof (BlockHeader);\n\t\t\tlzo1x_1_compress ((unsigned char*)Buffer, BlockHeader.UncompCount, (unsigned char*)(&Buffer2[sizeof(BlockHeader)]), &length, dictionary);\n\t\t\tBlockHeader.CompCount = (unsigned short)length;\n\t\t\tdelete [] dictionary;\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/LZOSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZoSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZOSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZOSTRAW_H\n#define LZOSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LZO compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LZOStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZOStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LZOStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tProbably dont need this anymore as LZO decompresses into a staging buffer.\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZOStraw(LZOStraw & rvalue);\n\t\tLZOStraw & operator = (LZOStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZO_CONF.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* lzo_conf.h -- main internal configuration file for the the LZO library\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   The LZO library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public\n   License along with the LZO library; see the file COPYING.LIB.\n   If not, write to the Free Software Foundation, Inc.,\n   675 Mass Ave, Cambridge, MA 02139, USA.\n\n   Markus F.X.J. Oberhumer\n   markus.oberhumer@jk.uni-linz.ac.at\n */\n\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the library and is subject\n   to change.\n */\n\n\n#ifndef __LZO_CONF_H\n#define __LZO_CONF_H\n\n#ifndef __LZOCONF_H\n#  include <lzoconf.h>\n#endif\n\n\n/***********************************************************************\n// compiler specific defines\n************************************************************************/\n\n/* need Borland C 4.0 or above because of huge-pointer bugs */\n#if defined(__LZO_MSDOS16) && defined(__TURBOC__)\n#  if (__TURBOC__ < 0x452)\n#    error You need a newer compiler version\n#  endif\n#endif\n\n#if defined(__LZO_MSDOS) || defined(__i386__) || defined(__386__)\n#  if !defined(__LZO_i386)\n#    define __LZO_i386\n#  endif\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#include <stddef.h>\t\t\t/* ptrdiff_t, size_t */\n#include <string.h>\t\t\t/* memcpy, memmove, memcmp, memset */\n\n#if 0 && !defined(assert)\n#  error <assert.h> not included\n#endif\n\n#if defined(__BOUNDS_CHECKING_ON)\n#  include <unchecked.h>\n#else\n#  define BOUNDS_CHECKING_OFF_DURING(stmt)\t\tstmt\n#  define BOUNDS_CHECKING_OFF_IN_EXPR(expr)\t\t(expr)\n#endif\n\n/* ptrdiff_t */\n#if (UINT_MAX >= 0xffffffffL)\n   typedef ptrdiff_t        lzo_ptrdiff_t;\n#else\n   typedef long             lzo_ptrdiff_t;\n#endif\n\n\n#ifdef __cplusplus\n#  define LZO_UNUSED(parm)\n#else\n#  define LZO_UNUSED(parm)\tparm\n#endif\n\n\n#if !defined(__inline__) && !defined(__GNUC__)\n#  if defined(__cplusplus)\n#    define __inline__\t\tinline\n#  else\n#    define __inline__\t\t/* nothing */\n#  endif\n#endif\n\n\n/***********************************************************************\n// compiler and architecture specific stuff\n************************************************************************/\n\n/* Some defines that indicate if memory can be accessed at unaligned\n * addresses. You should also test that this is actually faster if\n * it is allowed by your system.\n */\n\n#if 1 && defined(__LZO_i386)\n#  if !defined(LZO_UNALIGNED_OK_2)\n#    define LZO_UNALIGNED_OK_2\n#  endif\n#  if !defined(LZO_UNALIGNED_OK_4)\n#    define LZO_UNALIGNED_OK_4\n#  endif\n#endif\n\n\n#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4)\n#  if !defined(LZO_UNALIGNED_OK)\n#    define LZO_UNALIGNED_OK\n#  endif\n#endif\n\n\n/* Definitions for byte order, according to significance of bytes, from low\n * addresses to high addresses. The value is what you get by putting '4'\n * in the most significant byte, '3' in the second most significant byte,\n * '2' in the second least significant byte, and '1' in the least\n * significant byte.\n */\n\n#define\tLZO_LITTLE_ENDIAN\t\t1234\n#define\tLZO_BIG_ENDIAN\t\t\t4321\n#define\tLZO_PDP_ENDIAN\t\t\t3412\n\n/* The byte order is only needed if we use LZO_UNALIGNED_OK */\n#if !defined(LZO_BYTE_ORDER)\n#  if defined(__LZO_i386)\n#    define LZO_BYTE_ORDER\t\tLZO_LITTLE_ENDIAN\n#  elif defined(__mc68000__)\n#    define LZO_BYTE_ORDER\t\tLZO_BIG_ENDIAN\n#  elif defined(__BYTE_ORDER)\n#    define LZO_BYTE_ORDER\t\t__BYTE_ORDER\n#  endif\n#endif\n\n#if defined(LZO_UNALIGNED_OK)\n#  if !defined(LZO_BYTE_ORDER)\n#    error LZO_BYTE_ORDER is not defined\n#  elif (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \\\n        (LZO_BYTE_ORDER != LZO_BIG_ENDIAN)\n#    error invalid LZO_BYTE_ORDER\n#  endif\n#endif\n\n\n/***********************************************************************\n// optimization\n************************************************************************/\n\n/* gcc 2.6.3 and gcc 2.7.2 have a bug */\n#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY\n\n/* Help the optimizer with register allocation.\n * Don't activate this macro for a fair comparision with other algorithms.\n */\n#if 1 && defined(NDEBUG) && !defined(__BOUNDS_CHECKING_ON)\n#  if defined(__GNUC__) && defined(__i386__)\n#    if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY)\n#      define LZO_OPTIMIZE_GNUC_i386\n#    endif\n#  endif\n#endif\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#define LZO_BYTE(x)\t\t\t((unsigned char) (x))\n\n#define LZO_MAX(a,b)\t\t((a) >= (b) ? (a) : (b))\n#define LZO_MIN(a,b)\t\t((a) <= (b) ? (a) : (b))\n\n#define lzo_sizeof(x)\t\t((lzo_uint) (sizeof(x)))\n\n#define LZO_HIGH(x)\t\t\t((lzo_uint) (sizeof(x)/sizeof(*(x))))\n\n/* this always fits into 16 bits */\n#define LZO_SIZE(bits)\t\t(1u << (bits))\n#define LZO_MASK(bits)\t\t(LZO_SIZE(bits) - 1)\n\n#define LZO_LSIZE(bits)\t\t(1ul << (bits))\n#define LZO_LMASK(bits)\t\t(LZO_LSIZE(bits) - 1)\n\n#define LZO_USIZE(bits)\t\t((lzo_uint) 1 << (bits))\n#define LZO_UMASK(bits)\t\t(LZO_USIZE(bits) - 1)\n\n\n/***********************************************************************\n// ANSI C preprocessor macros\n************************************************************************/\n\n#define _LZO_STRINGIZE(x)\t\t\t#x\n#define _LZO_MEXPAND(x)\t\t\t\t_LZO_STRINGIZE(x)\n\n/* concatenate */\n#define _LZO_CONCAT2(a,b)\t\t\ta ## b\n#define _LZO_CONCAT3(a,b,c)\t\t\ta ## b ## c\n#define _LZO_CONCAT4(a,b,c,d)\t\ta ## b ## c ## d\n#define _LZO_CONCAT5(a,b,c,d,e)\t\ta ## b ## c ## d ## e\n\n/* expand and concatenate (by using one level of indirection) */\n#define _LZO_ECONCAT2(a,b)\t\t\t_LZO_CONCAT2(a,b)\n#define _LZO_ECONCAT3(a,b,c)\t\t_LZO_CONCAT3(a,b,c)\n#define _LZO_ECONCAT4(a,b,c,d)\t\t_LZO_CONCAT4(a,b,c,d)\n#define _LZO_ECONCAT5(a,b,c,d,e)\t_LZO_CONCAT5(a,b,c,d,e)\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n/* Generate compressed data in a deterministic way.\n * This is fully portable, and compression can be faster as well.\n * A reason NOT to be deterministic is when the block size is\n * very small (e.g. 8kB) or the dictionary is big, because\n * then the initialization of the dictionary becomes a relevant \n * magnitude for compression speed.\n */\n#define LZO_DETERMINISTIC\n\n\n/***********************************************************************\n//\n************************************************************************/\n\n#if 0 \n/* This line causes problems on some architectures */\n#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \\\n\t(BOUNDS_CHECKING_OFF_IN_EXPR( \\\n\t\t(m_off = ip - m_pos) > max_offset ))\n\n#else\n/* This is the safe (but slower) version */\n#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \\\n\t\t(m_pos == NULL || (m_off = ip - m_pos) > max_offset)\n#endif\n\n\n/* m_pos may point anywhere...\n * This marco is probably a good candidate for architecture specific problems.\n * Try casting the pointers to lzo_ptr_t before comparing them.\n */\n#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \\\n\t(BOUNDS_CHECKING_OFF_IN_EXPR( \\\n\t\t(m_pos < in || (m_off = ip - m_pos) <= 0 || m_off > max_offset) ))\n\n\n\n#endif /* already included */\n\n/*\nvi:ts=4\n*/\n\n"
  },
  {
    "path": "REDALERT/LZW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Find_Child_Node -- Find a matching dictionary entry.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include\t\"xstraw.h\"\n#include\t\"xpipe.h\"\n#include\t\"buff.h\"\n#include\t\"lzw.h\"\n\n\nLZWEngine::LZWEngine(void)\n{\n\tReset();\n}\n\n\nvoid LZWEngine::Reset(void)\n{\n\tfor (int i = 0; i < TABLE_SIZE; i++) {\n\t\tdict[i].Make_Unused();\n\t}\n}\n\nint LZWEngine::Compress(Buffer const & input, Buffer const & output)\n{\n\tBufferStraw instraw(input);\n\tBufferPipe outpipe(output);\n\n\tint outcount = 0;\n\tCodeType string_code = END_OF_STREAM;\n\tCodeType next_code = FIRST_CODE;\n\n\tstring_code = 0;\n\tif (instraw.Get(&string_code, sizeof(char)) == 0) {\n\t\tstring_code = END_OF_STREAM;\n\t}\n\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tFetch a character from the source data stream. If exhausted,\n\t\t**\tthen break out of the process loop so that the final code\n\t\t**\tcan be written out.\n\t\t*/\n\t\tunsigned char character;\n\t\tif (instraw.Get(&character, sizeof(character)) == 0) break;\n\n\t\t/*\n\t\t**\tSee if there is a match for the current code and current\n\t\t**\tcharacter. A match indicates that there is already a\n\t\t**\tdictionary entry that fully represents the character\n\t\t**\tsequence.\n\t\t*/\n\t\tint index = Find_Child_Node(string_code, character);\n\n\t\t/*\n\t\t**\tIf a code match was found, then set the current code\n\t\t**\tvalue to this code value that represents the concatenation\n\t\t**\tof the previous code value and the current character.\n\t\t*/\n\t\tif (index != -1 && dict[index].CodeValue != -1) {\n\t\t\tstring_code = dict[index].CodeValue;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSince no exact match was found, then create a new code\n\t\t\t**\tentry that represents the current code and character\n\t\t\t**\tvalue concatenated. This presumes there is room in the\n\t\t\t**\tcode table.\n\t\t\t*/\n\t\t\tif (index != -1 && next_code <= MAX_CODE) {\n\t\t\t\tdict[index] = CodeClass(next_code, string_code, character);\n\t\t\t\tnext_code++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tOutput the code to the compression stream and reset the\n\t\t\t**\tcurrent code value to match the current character. This\n\t\t\t**\thas the effect of clearing out the current character\n\t\t\t**\tsequence scan in preparation for building a new one. It\n\t\t\t**\talso ensures that the character will be written out.\n\t\t\t*/\n\t\t\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\t\t\tstring_code = character;\n\t\t}\n\t}\n\n\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\tif (string_code != END_OF_STREAM) {\n\t\tstring_code = END_OF_STREAM;\n\t\toutcount += outpipe.Put(&string_code, sizeof(string_code));\n\t}\n\n\treturn(outcount);\n}\n\n\nint LZWEngine::Uncompress(Buffer const & input, Buffer const & output)\n{\n\tint outcount = 0;\n\tBufferStraw instraw(input);\n\tBufferPipe outpipe(output);\n\n\tCodeType old_code;\n\tif (instraw.Get(&old_code, sizeof(old_code)) == 0) {\n\t\treturn(outcount);\n\t}\n\n\tunsigned char character = (unsigned char)old_code;\n\toutcount += outpipe.Put(&character, sizeof(character));\n\n\tunsigned int count;\n\tCodeType new_code;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tif (instraw.Get(&new_code, sizeof(new_code)) == 0) break;\n\n\t\tif (new_code == END_OF_STREAM) break;\n\n\t\t/*\n\t\t** This code checks for the CHARACTER+STRING+CHARACTER+STRING+CHARACTER\n\t\t** case which generates an undefined code.  It handles it by decoding\n\t\t** the last code, and adding a single character to the end of the decode string.\n\t\t*/\n\t\tif (new_code >= next_code) {\n\t\t\tdecode_stack[0] = character;\n\t\t\tcount = 1;\n\t\t\tcount += Decode_String(&decode_stack[1], old_code);\n\t\t} else {\n\t\t\tcount = Decode_String(decode_stack, new_code);\n\t\t}\n\n\t\tcharacter = decode_stack[count-1];\n\t\twhile (count > 0) {\n\t\t\t--count;\n\t\t\toutcount += outpipe.Put(&decode_stack[count], sizeof(decode_stack[0]));\n\t\t}\n\n\t\t/*\n\t\t**\tAdd the new code sequence to the dictionary (presuming there is still\n\t\t**\troom).\n\t\t*/\n\t\tif (next_code <= MAX_CODE) {\n\t\t\tdict[next_code] = CodeClass(next_code, old_code, character);\n\t\t\tnext_code++;\n\t\t}\n\t\told_code = new_code;\n\t}\n\n\treturn(outcount);\n}\n\n\nint LZWEngine::Make_LZW_Hash(CodeType code, char character)\n{\n\treturn((((int)(unsigned char)character) << ( BITS - 8 ) ) ^ (int)code);\n}\n\n\nint LZWEngine::Find_Child_Node(CodeType parent_code, char child_character)\n{\n\t/*\n\t**\tFetch the first try index for the code and character.\n\t*/\n\tint hash_index = Make_LZW_Hash(parent_code, child_character);\n\n\t/*\n\t**\tBase the hash-miss-try-again-displacement value on the current\n\t**\tindex. [Shouldn't the value be some large prime number???].\n\t*/\n\tint offset = 1;\n\tif (hash_index != 0) {\n\t\toffset = TABLE_SIZE - hash_index;\n\t}\n\n\t/*\n\t**\tKeep offsetting through the dictionary until an exact match is\n\t**\tfound for the code and character specified.\n\t*/\n\tint initial = hash_index;\n\twhile (!dict[hash_index].Is_Matching(parent_code, child_character)) {\n\n\t\t/*\n\t\t**\tStop searching if an unused index is found since this means that\n\t\t**\ta match doesn't exist in the table at all.\n\t\t*/\n\t\tif (dict[hash_index].Is_Unused()) break;\n\n\t\t/*\n\t\t**\tBump the hash index to another value such that sequential bumps\n\t\t**\twill not result in the same index value until all of the table\n\t\t**\thas been scanned.\n\t\t*/\n\t\thash_index -= offset;\n\t\tif (hash_index < 0) {\n\t\t\thash_index += TABLE_SIZE;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the entire table has been scanned and no match or unused\n\t\t**\tentry was found, then return a special value indicating this\n\t\t**\tcondition.\n\t\t*/\n\t\tif (initial == hash_index) {\n\t\t\thash_index = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(hash_index);\n}\n\n\nint LZWEngine::Decode_String(char * ptr, CodeType code)\n{\n\tint count = 0;\n\twhile (code > 255) {\n\t\t*ptr++ = dict[code].CharValue;\n\t\tcount++;\n\t\tcode = dict[code].ParentCode;\n\t}\n\t*ptr = (char)code;\n\tcount++;\n\treturn(count);\n}\n\n\nint LZW_Uncompress(Buffer const & inbuff, Buffer const & outbuff)\n{\n\tLZWEngine lzw;\n\treturn(lzw.Uncompress(inbuff, outbuff));\n}\n\n\nint LZW_Compress(Buffer const & inbuff, Buffer const & outbuff)\n{\n\tLZWEngine lzw;\n\treturn(lzw.Compress(inbuff, outbuff));\n}\n\n\n\n\n\n#ifdef NEVER\n\n\n/*\n * Constants used throughout the program.  BITS defines how many bits\n * will be in a code.  TABLE_SIZE defines the size of the dictionary\n * table.\n */\n#define BITS                       12\n#define MAX_CODE                   ( ( 1 << BITS ) - 1 )\n#define TABLE_SIZE                 5021\n#define END_OF_STREAM              256\n#define FIRST_CODE                 257\n#define UNUSED                     -1\n\ntypedef unsigned short CodeType;\n\n/*\n * This data structure defines the dictionary.  Each entry in the dictionary\n * has a code value.  This is the code emitted by the compressor.  Each\n * code is actually made up of two pieces:  a parent_code, and a\n * character.  Code values of less than 256 are actually plain\n * text codes.\n */\nstruct CodeClass\n{\n\tCodeType CodeValue;\n\tCodeType ParentCode;\n\tchar CharValue;\n\n\tCodeClass(void) {}\n\tCodeClass(CodeType code, CodeType parent, char c) : CodeValue(code), ParentCode(parent), CharValue(c) {}\n\n\tvoid Make_Unused(void) {CodeValue = UNUSED;}\n\tbool Is_Unused(void) const {return(CodeValue == UNUSED);}\n\tbool Is_Matching(CodeType code, char c) const {return(ParentCode == code && CharValue == c);}\n};\nCodeClass dict[TABLE_SIZE];\n\nchar decode_stack[TABLE_SIZE];\n\ninline int Make_LZW_Hash(CodeType code, char character)\n{\n\treturn((((int)(unsigned char)character) << ( BITS - 8 ) ) ^ (int)code);\n}\n\n\n/***********************************************************************************************\n * Find_Child_Node -- Find a matching dictionary entry.                                        *\n *                                                                                             *\n *    This hashing routine is responsible for finding the table location                       *\n *    for a string/character combination.  The table index is created                          *\n *    by using an exclusive OR combination of the prefix and character.                        *\n *    This code also has to check for collisions, and handles them by                          *\n *    jumping around in the table.                                                             *\n *                                                                                             *\n * INPUT:   parent_code -- The code of the parent string sequence.                             *\n *                                                                                             *\n *          character   -- The current character.                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the index for the matching dictionary entry. If no matching index     *\n *          could be found, then it returns with the index to an unused dictionary entry. If   *\n *          there are also no unused entries in the dictionary, then -1 is returned.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic int Find_Child_Node(CodeType parent_code, char child_character)\n{\n\t/*\n\t**\tFetch the first try index for the code and character.\n\t*/\n\tint hash_index = Make_LZW_Hash(parent_code, child_character);\n\n\t/*\n\t**\tBase the hash-miss-try-again-displacement value on the current\n\t**\tindex. [Shouldn't the value be some large prime number???].\n\t*/\n\tint offset = 1;\n\tif (hash_index != 0) {\n\t\toffset = TABLE_SIZE - hash_index;\n\t}\n\n\t/*\n\t**\tKeep offsetting through the dictionary until an exact match is\n\t**\tfound for the code and character specified.\n\t*/\n\tint initial = hash_index;\n\twhile (!dict[hash_index].Is_Matching(parent_code, child_character)) {\n\n\t\t/*\n\t\t**\tStop searching if an unused index is found since this means that\n\t\t**\ta match doesn't exist in the table at all.\n\t\t*/\n\t\tif (dict[hash_index].Is_Unused()) break;\n\n\t\t/*\n\t\t**\tBump the hash index to another value such that sequential bumps\n\t\t**\twill not result in the same index value until all of the table\n\t\t**\thas been scanned.\n\t\t*/\n\t\thash_index -= offset;\n\t\tif (hash_index < 0) {\n\t\t\thash_index += TABLE_SIZE;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the entire table has been scanned and no match or unused\n\t\t**\tentry was found, then return a special value indicating this\n\t\t**\tcondition.\n\t\t*/\n\t\tif (initial == hash_index) {\n\t\t\thash_index = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(hash_index);\n}\n\n\n/*\n * This routine decodes a string from the dictionary, and stores it\n * in the decode_stack data structure.  It returns a count to the\n * calling program of how many characters were placed in the stack.\n */\nstatic int Decode_String(char * ptr, CodeType code)\n{\n\tint count = 0;\n\twhile (code > 255) {\n\t\t*ptr++ = dict[code].CharValue;\n\t\tcount++;\n\t\tcode = dict[code].ParentCode;\n\t}\n\t*ptr = (char)code;\n\tcount++;\n\treturn(count);\n}\n\n\n/*\n * The compressor is short and simple.  It reads in new symbols one\n * at a time from the input file.  It then  checks to see if the\n * combination of the current symbol and the current code are already\n * defined in the dictionary.  If they are not, they are added to the\n * dictionary, and we start over with a new one symbol code.  If they\n * are, the code for the combination of the code and character becomes\n * our new code.\n */\n\nint LZW_Compress(Buffer & inbuff, Buffer & outbuff)\n{\n\tBufferStraw input(inbuff);\n\tBufferPipe output(outbuff);\n\n\tfor (int i = 0; i < TABLE_SIZE; i++) {\n\t\tdict[i].Make_Unused();\n//\t\tdict[i].code_value = UNUSED;\n\t}\n\n\tint outcount = 0;\n\tCodeType string_code = END_OF_STREAM;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tchar character;\n\n\t\tif (input.Get(&character, sizeof(character)) == 0) break;\n\n\t\tint index = Find_Child_Node(string_code, character);\n\n\t\tif (index == -1) {\n\t\t\tstring_code = character;\n\t\t\toutcount += output.Put(&string_code, sizeof(string_code));\n\t\t} else {\n\n\t\t\tif (dict[index].CodeValue != -1) {\n\t\t\t\tstring_code = dict[ index ].CodeValue;\n\t\t\t} else {\n\t\t\t\tif (next_code <= MAX_CODE) {\n\t\t\t\t\tdict[index] = CodeClass(next_code++, string_code, character);\n\t\t\t\t}\n\t\t\t\toutcount += output.Put(&string_code, sizeof(string_code));\n\t\t\t\tstring_code = character;\n\t\t\t}\n\t\t}\n\t}\n\n\toutcount += output.Put(&string_code, sizeof(string_code));\n\tstring_code = END_OF_STREAM;\n\toutcount += output.Put(&string_code, sizeof(string_code));\n\n\treturn(outcount);\n}\n\n\n/*\n * The file expander operates much like the encoder.  It has to\n * read in codes, the convert the codes to a string of characters.\n * The only catch in the whole operation occurs when the encoder\n * encounters a CHAR+STRING+CHAR+STRING+CHAR sequence.  When this\n * occurs, the encoder outputs a code that is not presently defined\n * in the table.  This is handled as an exception.\n */\nint LZW_Uncompress(Buffer & inbuff, Buffer & outbuff)\n{\n\tint outcount = 0;\n\tBufferStraw input(inbuff);\n\tBufferPipe output(outbuff);\n\n\tCodeType old_code;\n\tif (input.Get(&old_code, sizeof(old_code)) == 0) {\n\t\treturn(outcount);\n\t}\n\n\tchar character = (char)old_code;\n\toutcount += output.Put(&character, sizeof(character));\n\n\tunsigned int count;\n\tCodeType new_code;\n\tCodeType next_code = FIRST_CODE;\n\tfor (;;) {\n\t\tif (input.Get(&new_code, sizeof(new_code)) == 0) break;\n\n\t\t/*\n\t\t** This code checks for the CHARACTER+STRING+CHARACTER+STRING+CHARACTER\n\t\t** case which generates an undefined code.  It handles it by decoding\n\t\t** the last code, and adding a single character to the end of the decode string.\n\t\t*/\n\t\tif (new_code >= next_code) {\n\t\t\tdecode_stack[0] = character;\n\t\t\tcount = 1;\n\t\t\tcount += Decode_String(&decode_stack[1], old_code);\n\t\t} else {\n\t\t\tcount = Decode_String(decode_stack, new_code);\n\t\t}\n\n\t\tcharacter = decode_stack[count-1];\n\t\twhile (count > 0) {\n\t\t\t--count;\n\t\t\toutcount += output.Put(&decode_stack[count], sizeof(decode_stack[0]));\n\t\t}\n\n\t\t/*\n\t\t**\tAdd the new code sequence to the dictionary (presuming there is still\n\t\t**\troom).\n\t\t*/\n\t\tif (next_code <= MAX_CODE) {\n\t\t\tdict[next_code] = CodeClass(next_code, old_code, character);\n\t\t\tnext_code++;\n\t\t}\n\t\told_code = new_code;\n\t}\n\n\treturn(outcount);\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZW.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 08/28/96                                                     *\n *                                                                                             *\n *                  Last Update : August 28, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef _LZW_H\n#define _LZW_H\n\n#include\t\"buff.h\"\n\nclass LZWEngine\n{\n\tpublic:\n\t\tLZWEngine(void);\n\n\t\tint Compress(Buffer const & input, Buffer const & output);\n\t\tint Uncompress(Buffer const & input, Buffer const & output);\n\n\t\tvoid Reset(void);\n\n\tprivate:\n\t\ttypedef short CodeType;\n\t\tstruct CodeClass {\n\t\t\tCodeType CodeValue;\n\t\t\tCodeType ParentCode;\n\t\t\tchar CharValue;\n\n\t\t\tCodeClass(void) {}\n\t\t\tCodeClass(CodeType code, CodeType parent, char c) : CodeValue(code), ParentCode(parent), CharValue(c) {}\n\n\t\t\tenum {UNUSED=-1};\n\t\t\tvoid Make_Unused(void) {CodeValue = UNUSED;}\n\t\t\tbool Is_Unused(void) const {return(CodeValue == UNUSED);}\n\t\t\tbool Is_Matching(CodeType code, char c) const {return(ParentCode == code && CharValue == c);}\n\t\t};\n\n\t\tenum {\n\t\t\tBITS=12,\n\t\t\tMAX_CODE=((1 << BITS ) - 1),\n\t\t\tFIRST_CODE=257,\n\t\t\tEND_OF_STREAM=256,\n\t\t\tTABLE_SIZE=5021\n\t\t};\n\t\tCodeClass dict[TABLE_SIZE];\n\n\t\tchar decode_stack[TABLE_SIZE];\n\n\t\tint Find_Child_Node(CodeType parent_code, char child_character);\n\t\tint Decode_String(char * ptr, CodeType code);\n\t\tstatic int Make_LZW_Hash(CodeType code, char character);\n};\n\n\nint LZW_Compress(Buffer const & inbuff, Buffer const & outbuff);\nint LZW_Uncompress(Buffer const & inbuff, Buffer const & outbuff);\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZWOTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZWOTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWStraw::Get -- Fetch data through the LZW processor.                                    *\n *   LZWStraw::LZWStraw -- Constructor for LZW straw object.                                   *\n *   LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzostraw.h\"\n#include\t\"lzwstraw.h\"\n#include\t\"lzo.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWStraw::LZWStraw -- Constructor for LZW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::LZWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::~LZWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWStraw::Get -- Fetch data through the LZW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tchar *stageing_buffer = new char [BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(staging_buffer, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tlz01x_decompress (ptr, BlockHeader.CompCount, Buffer, sizeof(Buffer), NULL);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tint len = sizeof (Buffer2) - sizeof (BlockHeader);\n\t\t\tchar *dictionary = new char [64*1024];\n\t\t\tlzo1x_1_compress (Buffer, BlockHeader.UncompCount, &Buffer2[sizeof(BlockHeader)], &BlockHeader.CompCount, dictionary);\n\t\t\tdelete [] dictionary;\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/LZWPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZWPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWPipe::Flush -- Flushes any partially accumulated block.                                *\n *   LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                               *\n *   LZWPipe::Put -- Send some data through the LZW processor pipe.                            *\n *   LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                               *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"lzwpipe.h\"\n#include\t\"lzw.h\"\n#include\t\"buff.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                                 *\n *                                                                                             *\n *    This will initialize the LZWPipe object so that it is prepared for compression or        *\n *    decompression as indicated.                                                              *\n *                                                                                             *\n * INPUT:   decrypt  -- Should decompression be performed?                                     *\n *                                                                                             *\n *          blocksize-- The size of the data blocks to process.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWPipe::LZWPipe(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tBuffer2 = new char[BlockSize+SafetyMargin];\n\tBlockHeader.CompCount = 0xFFFF;\n}\n\n\n/***********************************************************************************************\n * LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                                 *\n *                                                                                             *\n *    This will free any buffers it may have allocated.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWPipe::~LZWPipe(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWPipe::Put -- Send some data through the LZW processor pipe.                              *\n *                                                                                             *\n *    This routine will take the data requested and process it (decompression or compression). *\n *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *\n *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be fed to this LZW processor.                   *\n *                                                                                             *\n *          length   -- The number of bytes received.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWPipe::Put(void const * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Pipe::Put(source, slen));\n\t}\n\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tCopy as much as can fit into the buffer from the source data supplied.\n\t*/\n\tif (Control ==  DECOMPRESS) {\n\n\t\twhile (slen > 0) {\n\n\t\t\t/*\n\t\t\t**\tFirst check to see if we are in the block header accumulation phase.\n\t\t\t**\tWhen a whole block header has been accumulated, only then will the regular\n\t\t\t**\tdata processing begin for the block.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\tint len = (slen < ((int)sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tslen -= len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tA whole block header has been accumulated. Store it for safekeeping.\n\t\t\t\t*/\n\t\t\t\tif (Counter == sizeof(BlockHeader)) {\n\t\t\t\t\tmemmove(&BlockHeader, Buffer, sizeof(BlockHeader));\n\t\t\t\t\tCounter = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill the buffer with compressed data until there is enough to make a whole\n\t\t\t**\tdata block.\n\t\t\t*/\n\t\t\tif (slen > 0) {\n\t\t\t\tint len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);\n\n\t\t\t\tmemmove(&Buffer[Counter], source, len);\n\t\t\t\tslen -= len;\n\t\t\t\tsource = ((char *)source) + len;\n\t\t\t\tCounter += len;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf an entire block has been accumulated, then uncompress it and feed it\n\t\t\t\t**\tthrough the pipe.\n\t\t\t\t*/\n\t\t\t\tif (Counter == BlockHeader.CompCount) {\n\t\t\t\t\tLZW_Uncompress(Buffer, Buffer2);\n\t\t\t\t\ttotal += Pipe::Put(Buffer2, BlockHeader.UncompCount);\n\t\t\t\t\tCounter = 0;\n\t\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the buffer already contains some data, then any new data must be stored\n\t\t**\tinto the staging buffer until a full set has been accumulated.\n\t\t*/\n\t\tif (Counter > 0) {\n\t\t\tint tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);\n\t\t\tmemmove(&Buffer[Counter], source, tocopy);\n\t\t\tsource = ((char *)source) + tocopy;\n\t\t\tslen -= tocopy;\n\t\t\tCounter += tocopy;\n\n\t\t\tif (Counter == BlockSize) {\n\t\t\t\tint len = LZW_Compress(::Buffer(Buffer, BlockSize), Buffer2);\n\n\t\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess the source data in whole block chunks until there is insufficient\n\t\t**\tsource data left for a whole data block.\n\t\t*/\n\t\twhile (slen >= BlockSize) {\n\t\t\tint len = LZW_Compress(::Buffer((void*)source, BlockSize), Buffer2);\n\n\t\t\tsource = ((char *)source) + BlockSize;\n\t\t\tslen -= BlockSize;\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)BlockSize;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is any remaining data, then it is stored into the buffer\n\t\t**\tuntil a full data block has been accumulated.\n\t\t*/\n\t\tif (slen > 0) {\n\t\t\tmemmove(Buffer, source, slen);\n\t\t\tCounter = slen;\n\t\t}\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * LZWPipe::Flush -- Flushes any partially accumulated block.                                  *\n *                                                                                             *\n *    This routine is called when any buffered data must be flushed out the pipe. For the      *\n *    compression process, this will generate the sub-sized compressed block. For              *\n *    decompression, this routine should not have any data in the buffer. In such a case, it   *\n *    means that the data source was prematurely truncated. In such a case, just dump the      *\n *    accumulated data through the pipe.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *\n *          the pipe chain.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWPipe::Flush(void)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tIf there is accumulated data, then it must processed.\n\t*/\n\tif (Counter > 0) {\n\t\tif (Control == DECOMPRESS) {\n\n\t\t\t/*\n\t\t\t**\tIf the accumulated data is insufficient to make a block header, then\n\t\t\t**\tthis means the data has been truncated. Just dump the data through\n\t\t\t**\tas if were already decompressed.\n\t\t\t*/\n\t\t\tif (BlockHeader.CompCount == 0xFFFF) {\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tThere appears to be a partial block accumulated in the buffer. It would\n\t\t\t**\tbe disastrous to try to decompress the data since there wouldn't be\n\t\t\t**\tthe special end of data code that LZW decompression needs. In this\n\t\t\t**\tcase, dump the data out as if it were already decompressed.\n\t\t\t*/\n\t\t\tif (Counter > 0) {\n\t\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\t\ttotal += Pipe::Put(Buffer, Counter);\n\t\t\t\tCounter = 0;\n\t\t\t\tBlockHeader.CompCount = 0xFFFF;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA partial block in the compression process is a normal occurrence. Just\n\t\t\t**\tcompress the partial block and output normally.\n\t\t\t*/\n\t\t\tint len = LZW_Compress(::Buffer(Buffer, Counter), Buffer2);\n\n\t\t\tBlockHeader.CompCount = (unsigned short)len;\n\t\t\tBlockHeader.UncompCount = (unsigned short)Counter;\n\t\t\ttotal += Pipe::Put(&BlockHeader, sizeof(BlockHeader));\n\t\t\ttotal += Pipe::Put(Buffer2, len);\n\t\t\tCounter = 0;\n\t\t}\n\t}\n\n\ttotal += Pipe::Flush();\n\treturn(total);\n}\n\n"
  },
  {
    "path": "REDALERT/LZWPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZWPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZWPIPE_H\n#define LZWPIPE_H\n\n#include\t\"pipe.h\"\n\n\n/*\n**\tPerforms LZW compression/decompression on the data stream that is piped through this\n**\tclass. The data is compressed in blocks so of small enough size to be compressed\n**\tquickly and large enough size to get decent compression rates.\n*/\nclass LZWPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZWPipe(CompControl, int blocksize=1024*8);\n\t\tvirtual ~LZWPipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int Put(void const * source, int slen);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLZW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZWPipe(LZWPipe & rvalue);\n\t\tLZWPipe & operator = (LZWPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/LZWSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZWSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   LZWStraw::Get -- Fetch data through the LZW processor.                                    *\n *   LZWStraw::LZWStraw -- Constructor for LZW straw object.                                   *\n *   LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"lzwstraw.h\"\n#include\t\"lzw.h\"\n#include\t<string.h>\n#include\t<assert.h>\n\n\n/***********************************************************************************************\n * LZWStraw::LZWStraw -- Constructor for LZW straw object.                                     *\n *                                                                                             *\n *    This will initialize the LZW straw object. Whether the object is to compress or          *\n *    decompress and the block size to use is specified. The data is compressed in blocks      *\n *    that are sized to be quick to compress and yet still yield good compression ratios.      *\n *                                                                                             *\n * INPUT:   decrypt  -- Should the data be decompressed?                                       *\n *                                                                                             *\n *          blocksize-- The size of the blocks to process.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It takes two buffers of the blocksize specified if compression is to be         *\n *             performed.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::LZWStraw(CompControl control, int blocksize) :\n\t\tControl(control),\n\t\tCounter(0),\n\t\tBuffer(NULL),\n\t\tBuffer2(NULL),\n\t\tBlockSize(blocksize)\n{\n\tSafetyMargin = BlockSize;\n//\tSafetyMargin = BlockSize/128+1;\n\tBuffer = new char[BlockSize+SafetyMargin];\n\tif (control == COMPRESS) {\n\t\tBuffer2 = new char[BlockSize+SafetyMargin];\n\t}\n}\n\n\n/***********************************************************************************************\n * LZWStraw::~LZWStraw -- Destructor for the LZW straw.                                        *\n *                                                                                             *\n *    The destructor will free up the allocated buffers that it allocated in the constructor.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nLZWStraw::~LZWStraw(void)\n{\n\tdelete [] Buffer;\n\tBuffer = NULL;\n\n\tdelete [] Buffer2;\n\tBuffer2 = NULL;\n}\n\n\n/***********************************************************************************************\n * LZWStraw::Get -- Fetch data through the LZW processor.                                      *\n *                                                                                             *\n *    This routine will fetch the data bytes specified. It does this by first accumulating     *\n *    a full block of data and then compressing or decompressing it as indicated. Subsequent   *\n *    requests for data will draw from this buffer of processed data until it is exhausted     *\n *    and another block must be fetched.                                                       *\n *                                                                                             *\n * INPUT:   destbuf  -- Pointer to the buffer to hold the data requested.                      *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. If this number     *\n *          is less than that requested, then this indicates that the data source has been     *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint LZWStraw::Get(void * destbuf, int slen)\n{\n\tassert(Buffer != NULL);\n\n\tint total = 0;\n\n\t/*\n\t**\tVerify parameters for legality.\n\t*/\n\tif (destbuf == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\twhile (slen > 0) {\n\n\t\t/*\n\t\t**\tCopy as much data is requested and available into the desired\n\t\t**\tdestination buffer.\n\t\t*/\n\t\tif (Counter) {\n\t\t\tint len = (slen < Counter) ? slen : Counter;\n\t\t\tif (Control == DECOMPRESS) {\n\t\t\t\tmemmove(destbuf, &Buffer[BlockHeader.UncompCount-Counter], len);\n\t\t\t} else {\n\t\t\t\tmemmove(destbuf, &Buffer2[(BlockHeader.CompCount+sizeof(BlockHeader))-Counter], len);\n\t\t\t}\n\t\t\tdestbuf = ((char *)destbuf) + len;\n\t\t\tslen -= len;\n\t\t\tCounter -= len;\n\t\t\ttotal += len;\n\t\t}\n\t\tif (slen == 0) break;\n\n\t\tif (Control == DECOMPRESS) {\n\t\t\tint incount = Straw::Get(&BlockHeader, sizeof(BlockHeader));\n\t\t\tif (incount != sizeof(BlockHeader)) break;\n\n\t\t\tvoid * ptr = &Buffer[(BlockSize+SafetyMargin) - BlockHeader.CompCount];\n\t\t\tincount = Straw::Get(ptr, BlockHeader.CompCount);\n\t\t\tif (incount != BlockHeader.CompCount) break;\n\n\t\t\tLZW_Uncompress(ptr, Buffer);\n\t\t\tCounter = BlockHeader.UncompCount;\n\t\t} else {\n\t\t\tBlockHeader.UncompCount = (unsigned short)Straw::Get(Buffer, BlockSize);\n\t\t\tif (BlockHeader.UncompCount == 0) break;\n\t\t\tBlockHeader.CompCount = (unsigned short)LZW_Compress(::Buffer(Buffer, BlockHeader.UncompCount), &Buffer2[sizeof(BlockHeader)]);\n\t\t\tmemmove(Buffer2, &BlockHeader, sizeof(BlockHeader));\n\t\t\tCounter = BlockHeader.CompCount+sizeof(BlockHeader);\n\t\t}\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/LZWSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/LZWSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : LZWSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef LZWSTRAW_H\n#define LZWSTRAW_H\n\n\n#include\t\"straw.h\"\n\n/*\n**\tThis class handles LZW compression/decompression to the data stream that is drawn through\n**\tthis class. Note that for compression, two internal buffers are required. For decompression\n**\tonly one buffer is required. This changes the memory footprint of this class depending on\n**\tthe process desired.\n*/\nclass LZWStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CompControl {\n\t\t\tCOMPRESS,\n\t\t\tDECOMPRESS\n\t\t} CompControl;\n\n\t\tLZWStraw(CompControl control, int blocksize=1024*8);\n\t\tvirtual ~LZWStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis tells the pipe if it should be decompressing or compressing the data stream.\n\t\t*/\n\t\tCompControl Control;\n\n\t\t/*\n\t\t**\tThe number of bytes accumulated into the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tPointer to the working buffer that compression/decompression will use.\n\t\t*/\n\t\tchar * Buffer;\n\t\tchar * Buffer2;\n\n\t\t/*\n\t\t**\tThe working block size. Data will be compressed in chunks of this size.\n\t\t*/\n\t\tint BlockSize;\n\n\t\t/*\n\t\t**\tLZW compression requires a safety margin when decompressing over itself. This\n\t\t**\tmargin is only for the worst case situation (very rare).\n\t\t*/\n\t\tint SafetyMargin;\n\n\t\t/*\n\t\t**\tEach block has a header of this format.\n\t\t*/\n\t\tstruct {\n\t\t\tunsigned short CompCount;\t\t// Size of data block (compressed).\n\t\t\tunsigned short UncompCount;\t// Bytes of uncompressed data it represents.\n\t\t} BlockHeader;\n\n\t\tLZWStraw(LZWStraw & rvalue);\n\t\tLZWStraw & operator = (LZWStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/License.txt",
    "content": "Electronic Arts Inc. released only TiberianDawn.dll and RedAlert.dll and their corresponding source code under the GPL V3 below, with additional terms at the bottom.    \n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n\nADDITIONAL TERMS per GNU GPL Section 7\nNo trademark or publicity rights are granted. This license does NOT give you\nany right, title or interest in \"Command & Conquer\" or any other Electronic Arts trademark. You may not distribute any\nmodification of this program using any Electronic Arts trademark or claim any affiliation or association with Electronic Arts Inc.\nor its affiliates or their employees.\n\nAny propagation or conveyance of this program must include this copyright\nnotice and these terms.\n\nIf you convey this program (or any modifications of it) and assume\ncontractual liability for the program to recipients of it, you agree to\nindemnify Electronic Arts for any liability that those contractual\nassumptions impose on Electronic Arts.\n\nYou may not misrepresent the origins of this program; modified versions of\nthe program must be marked as such and not identified as the original program.\n\nThis disclaimer supplements the one included in the General Public License.\nTO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS PROGRAM IS\nPROVIDED TO YOU \"AS IS,\" WITH ALL FAULTS, WITHOUT WARRANTY OF ANY KIND, AND\nYOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF SATISFACTORY QUALITY AND\nPERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS DISCLAIMS ANY AND ALL EXPRESS,\nIMPLIED OR STATUTORY WARRANTIES, INCLUDING IMPLIED WARRANTIES OF\nMERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE,\nNONINFRINGEMENT OF THIRD PARTY RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A\nCOURSE OF DEALING, USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT\nAGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL\nMEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR\nERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE WITH THIRD PARTY SOFTWARE\nOR THAT ANY ERRORS IN THE PROGRAM WILL BE CORRECTED. NO ORAL OR WRITTEN ADVICE\nPROVIDED BY ELECTRONIC ARTS OR ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A\nWARRANTY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON\nIMPLIED WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A\nCONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY NOT APPLY\nTO YOU."
  },
  {
    "path": "REDALERT/MAP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAP.CPP 3     3/14/97 5:15p Joe_b $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAP.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 5, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MapClass::Base_Region -- Finds the owner and base zone for specified cell.                *\n *   MapClass::Cell_Region -- Determines the region from a specified cell number.              *\n *   MapClass::Cell_Threat -- Gets a houses threat value for a cell                            *\n *   MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.     *\n *   MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                *\n *   MapClass::Detach -- Remove specified object from map references.                          *\n *   MapClass::In_Radar -- Is specified cell in the radar map?                                 *\n *   MapClass::Init -- clears all cells                                                        *\n *   MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                  *\n *   MapClass::Logic -- Handles map related logic functions.                                   *\n *   MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.      *\n *   MapClass::One_Time -- Performs special one time initializations for the map.              *\n *   MapClass::Overlap_Down -- computes & marks object's overlap cells                         *\n *   MapClass::Overlap_Up -- Computes & clears object's overlap cells                          *\n *   MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.            *\n *   MapClass::Pick_Up -- Removes specified object from the map.                               *\n *   MapClass::Place_Down -- Places the specified object onto the map.                         *\n *   MapClass::Place_Random_Crate -- Places a crate at random location on map.                 *\n *   MapClass::Read_Binary -- Reads the binary data from the straw specified.                  *\n *   MapClass::Remove_Crate -- Remove a crate from the specified cell.                         *\n *   MapClass::Set_Map_Dimensions -- Initialize the map.                                       *\n *   MapClass::Sight_From -- Mark as visible the cells within a specified radius.              *\n *   MapClass::Validate -- validates every cell on the map                                     *\n *   MapClass::Write_Binary -- Pipes the map template data to the destination specified.       *\n *   MapClass::Zone_Reset -- Resets all zone numbers to match the map.                         *\n *   MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.               *\n *   MapClass::Pick_Random_Location -- Picks a random location on the map.                     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#define\tMCW\tMAP_CELL_W\nint const MapClass::RadiusOffset[] = {\n\t/* 0  */\t0,\n\t/* 1  */\t(-MCW*1)-1,(-MCW*1)+0,(-MCW*1)+1,-1,1,(MCW*1)-1,(MCW*1)+0,(MCW*1)+1,\n\t/* 2  */\t(-MCW*2)-1,(-MCW*2)+0,(-MCW*2)+1,(-MCW*1)-2,(-MCW*1)+2,-2,2,(MCW*1)-2,(MCW*1)+2,(MCW*2)-1,(MCW*2)+0,(MCW*2)+1,\n\t/* 3  */\t(-MCW*3)-1,(-MCW*3)+0,(-MCW*3)+1,(-MCW*2)-2,(-MCW*2)+2,(-MCW*1)-3,(-MCW*1)+3,-3,3,(MCW*1)-3,(MCW*1)+3,(MCW*2)-2,(MCW*2)+2,(MCW*3)-1,(MCW*3)+0,(MCW*3)+1,\n\t/* 4  */\t(-MCW*4)-1,(-MCW*4)+0,(-MCW*4)+1,(-MCW*3)-3,(-MCW*3)-2,(-MCW*3)+2,(-MCW*3)+3,(-MCW*2)-3,(-MCW*2)+3,(-MCW*1)-4,(-MCW*1)+4,-4,4,(MCW*1)-4,(MCW*1)+4,(MCW*2)-3,(MCW*2)+3,(MCW*3)-3,(MCW*3)-2,(MCW*3)+2,(MCW*3)+3,(MCW*4)-1,(MCW*4)+0,(MCW*4)+1,\n\t/* 5  */\t(-MCW*5)-1,(-MCW*5)+0,(-MCW*5)+1,(-MCW*4)-3,(-MCW*4)-2,(-MCW*4)+2,(-MCW*4)+3,(-MCW*3)-4,(-MCW*3)+4,(-MCW*2)-4,(-MCW*2)+4,(-MCW*1)-5,(-MCW*1)+5,-5,5,(MCW*1)-5,(MCW*1)+5,(MCW*2)-4,(MCW*2)+4,(MCW*3)-4,(MCW*3)+4,(MCW*4)-3,(MCW*4)-2,(MCW*4)+2,(MCW*4)+3,(MCW*5)-1,(MCW*5)+0,(MCW*5)+1,\n\t/* 6  */\t(-MCW*6)-1,(-MCW*6)+0,(-MCW*6)+1,(-MCW*5)-3,(-MCW*5)-2,(-MCW*5)+2,(-MCW*5)+3,(-MCW*4)-4,(-MCW*4)+4,(-MCW*3)-5,(-MCW*3)+5,(-MCW*2)-5,(-MCW*2)+5,(-MCW*1)-6,(-MCW*1)+6,-6,6,(MCW*1)-6,(MCW*1)+6,(MCW*2)-5,(MCW*2)+5,(MCW*3)-5,(MCW*3)+5,(MCW*4)-4,(MCW*4)+4,(MCW*5)-3,(MCW*5)-2,(MCW*5)+2,(MCW*5)+3,(MCW*6)-1,(MCW*6)+0,(MCW*6)+1,\n\t/* 7  */\t(-MCW*7)-1,(-MCW*7)+0,(-MCW*7)+1,(-MCW*6)-3,(-MCW*6)-2,(-MCW*6)+2,(-MCW*6)+3,(-MCW*5)-5,(-MCW*5)-4,(-MCW*5)+4,(-MCW*5)+5,(-MCW*4)-5,(-MCW*4)+5,(-MCW*3)-6,(-MCW*3)+6,(-MCW*2)-6,(-MCW*2)+6,(-MCW*1)-7,(-MCW*1)+7,-7,7,(MCW*1)-7,(MCW*1)+7,(MCW*2)-6,(MCW*2)+6,(MCW*3)-6,(MCW*3)+6,(MCW*4)-5,(MCW*4)+5,(MCW*5)-5,(MCW*5)-4,(MCW*5)+4,(MCW*5)+5,(MCW*6)-3,(MCW*6)-2,(MCW*6)+2,(MCW*6)+3,(MCW*7)-1,(MCW*7)+0,(MCW*7)+1,\n\t/* 8  */\t(-MCW*8)-1,(-MCW*8)+0,(-MCW*8)+1,(-MCW*7)-3,(-MCW*7)-2,(-MCW*7)+2,(-MCW*7)+3,(-MCW*6)-5,(-MCW*6)-4,(-MCW*6)+4,(-MCW*6)+5,(-MCW*5)-6,(-MCW*5)+6,(-MCW*4)-6,(-MCW*4)+6,(-MCW*3)-7,(-MCW*3)+7,(-MCW*2)-7,(-MCW*2)+7,(-MCW*1)-8,(-MCW*1)+8,-8,8,(MCW*1)-8,(MCW*1)+8,(MCW*2)-7,(MCW*2)+7,(MCW*3)-7,(MCW*3)+7,(MCW*4)-6,(MCW*4)+6,(MCW*5)-6,(MCW*5)+6,(MCW*6)-5,(MCW*6)-4,(MCW*6)+4,(MCW*6)+5,(MCW*7)-3,(MCW*7)-2,(MCW*7)+2,(MCW*7)+3,(MCW*8)-1,(MCW*8)+0,(MCW*8)+1,\n\t/* 9  */\t(-MCW*9)-1,(-MCW*9)+0,(-MCW*9)+1,(-MCW*8)-3,(-MCW*8)-2,(-MCW*8)+2,(-MCW*8)+3,(-MCW*7)-5,(-MCW*7)-4,(-MCW*7)+4,(-MCW*7)+5,(-MCW*6)-6,(-MCW*6)+6,(-MCW*5)-7,(-MCW*5)+7,(-MCW*4)-7,(-MCW*4)+7,(-MCW*3)-8,(-MCW*3)+8,(-MCW*2)-8,(-MCW*2)+8,(-MCW*1)-9,(-MCW*1)+9,-9,9,(MCW*1)-9,(MCW*1)+9,(MCW*2)-8,(MCW*2)+8,(MCW*3)-8,(MCW*3)+8,(MCW*4)-7,(MCW*4)+7,(MCW*5)-7,(MCW*5)+7,(MCW*6)-6,(MCW*6)+6,(MCW*7)-5,(MCW*7)-4,(MCW*7)+4,(MCW*7)+5,(MCW*8)-3,(MCW*8)-2,(MCW*8)+2,(MCW*8)+3,(MCW*9)-1,(MCW*9)+0,(MCW*9)+1,\n\t/* 10 */\t(-MCW*10)-1,(-MCW*10)+0,(-MCW*10)+1,(-MCW*9)-3,(-MCW*9)-2,(-MCW*9)+2,(-MCW*9)+3,(-MCW*8)-5,(-MCW*8)-4,(-MCW*8)+4,(-MCW*8)+5,(-MCW*7)-7,(-MCW*7)-6,(-MCW*7)+6,(-MCW*7)+7,(-MCW*6)-7,(-MCW*6)+7,(-MCW*5)-8,(-MCW*5)+8,(-MCW*4)-8,(-MCW*4)+8,(-MCW*3)-9,(-MCW*3)+9,(-MCW*2)-9,(-MCW*2)+9,(-MCW*1)-10,(-MCW*1)+10,-10,10,(MCW*1)-10,(MCW*1)+10,(MCW*2)-9,(MCW*2)+9,(MCW*3)-9,(MCW*3)+9,(MCW*4)-8,(MCW*4)+8,(MCW*5)-8,(MCW*5)+8,(MCW*6)-7,(MCW*6)+7,(MCW*7)-7,(MCW*7)-6,(MCW*7)+6,(MCW*7)+7,(MCW*8)-5,(MCW*8)-4,\n\t\t\t(MCW*8)+4,(MCW*8)+5,(MCW*9)-3,(MCW*9)-2,(MCW*9)+2,(MCW*9)+3,(MCW*10)-1,(MCW*10)+0,(MCW*10)+1,\n};\n\nint const MapClass::RadiusCount[11] = {1,9,21,37,61,89,121,161,205,253,309};\n\n\nCellClass * BlubCell;\n\n/***********************************************************************************************\n * MapClass::One_Time -- Performs special one time initializations for the map.                *\n *                                                                                             *\n *    This routine is used by the game initialization function in order to perform any one     *\n *    time initializations required for the map. This includes allocation of the map and       *\n *    setting up its default dimensions.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine MUST be called once and only once.                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/31/1994 JLB : Created.                                                                 *\n *   12/01/1994 BR : Added CellTriggers initialization                                         *\n *=============================================================================================*/\nvoid MapClass::One_Time(void)\n{\n\tGScreenClass::One_Time();\n\n\tXSize = MAP_CELL_W;\n\tYSize = MAP_CELL_H;\n\tSize = XSize * YSize;\n\n\t/*\n\t**\tAllocate the cell array.\n\t*/\n\tAlloc_Cells();\n}\n\n\n/***********************************************************************************************\n * MapClass::Init_Clear -- clears the map & buffers to a known state                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Init_Clear(void)\n{\n\tGScreenClass::Init_Clear();\n\tInit_Cells();\n\tTiberiumScan = 0;\n\tTiberiumGrowthCount = 0;\n\tTiberiumGrowthExcess = 0;\n\tTiberiumSpreadCount = 0;\n\tTiberiumSpreadExcess = 0;\n\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\tCrates[index].Init();\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Alloc_Cells -- allocates the cell array                                           *\n *                                                                                             *\n * This routine should be called at One_Time, and after loading the Map object from a save     *\n * game, but prior to loading the cell objects.                                                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Alloc_Cells(void)\n{\n\t/*\n\t**\tAssume that whatever the contents of the VectorClass are is garbage\n\t**\t(it may have been loaded from a save-game file), so zero it out first.\n\t*/\n\tnew (&Array) VectorClass<CellClass>;\n\tArray.Resize(Size);\n}\n\n\n/***********************************************************************************************\n * MapClass::Free_Cells -- frees the cell array                                                *\n *                                                                                             *\n * This routine is used by the Load_Game routine to free the map's cell array before loading   *\n * the map object from disk; the array is then re-allocated & cleared before the cell objects  *\n * are loaded.                                                                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Free_Cells(void)\n{\n\tArray.Clear();\n}\n\n\n/***********************************************************************************************\n * MapClass::Init_Cells -- Initializes the cell array to a fresh state.                        *\n *                                                                                             *\n * This routine is used by Init_Clear to set the cells to a known state; it's also used by     *\n * the Load_Game routine to init all cells before loading a set of cells from disk, so it      *\n * needs to be called separately from the other Init_xxx() routines.                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/17/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Init_Cells(void)\n{\n\tTotalValue = 0;\n\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tnew (&Array[index]) CellClass;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Set_Map_Dimensions -- Set map dimensions.                                         *\n *                                                                                             *\n *    This routine is used to set the legal limits and position of the                         *\n *    map as it relates to the overall map array. Typically, this is                           *\n *    called by the scenario loading code.                                                     *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y coordinate of the \"upper left\" corner                         *\n *                   of the map.                                                               *\n *                                                                                             *\n *          w,h   -- The width and height of the legal map.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/14/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Set_Map_Dimensions(int x, int y, int w, int h)\n{\n\tMapCellX = x;\n\tMapCellY = y;\n\tMapCellWidth = w;\n\tMapCellHeight = h;\n}\n\n\n/***********************************************************************************************\n * MapClass::Sight_From -- Mark as visible the cells within a specified radius.                *\n *                                                                                             *\n *    This routine is used to reveal the cells around a specific location.                     *\n *    Typically, as a unit moves or is deployed, this routine will be                          *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the sighting originates from.                      *\n *                                                                                             *\n *          sightrange-- The distance in cells that sighting extends.                          *\n *                                                                                             *\n *          incremental-- Is this an incremental sighting. In other                            *\n *                      words, has this function been called before where                      *\n *                      the center coordinate is no more than one cell                         *\n *                      distant from the last time?                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1992 JLB : Created.                                                                 *\n *   03/08/1994 JLB : Updated to use sight table and incremental flag.                         *\n *   05/18/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid MapClass::Sight_From(CELL cell, int sightrange, HouseClass * house, bool incremental)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot sight.\n\t*/\n\tif (!In_Radar(cell)) return;\n\tif (!sightrange || sightrange > 10) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[sightrange];\n\tptr = &RadiusOffset[0];\n\tif (incremental) {\n\t\tif (sightrange > 2) {\n\t\t\tptr += RadiusCount[sightrange-3];\n\t\t\tcount -= RadiusCount[sightrange-3];\n\t\t}\n\t}\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > sightrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tMap the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\t//if (!(*this)[newcell].IsMapped) {  // ST - 8/7/2019 10:31AM\t\t\n\t\tMap.Map_Cell(newcell, house, true, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Shroud_From -- cloak a radius of cells\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    This routine is used to shroud the cells around a specific location.                     *\n *    Typically, as a gap generator refreshes (when Encroach_Shadow() is called) this routine's*\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the shrouding originates from.                     *\n *                                                                                             *\n *          sightrange-- The distance in cells that sighting extends.                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/10/1995 BWG : Created.                                                                 *\n *   08/09/2019  ST : Added house parameter                                                    *\n *=============================================================================================*/\nvoid MapClass::Shroud_From(CELL cell, int sightrange, HouseClass *house)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot sight.\n\t*/\n\tif (!In_Radar(cell)) return;\n\tif (!sightrange || sightrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[sightrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > sightrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tShroud the cell.\n\t\t*/\n\t\tMap.Shroud_Cell(newcell, house);\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Jam_From -- Mark as jammed the cells within a specified radius.                   *\n *                                                                                             *\n *    This routine is used to jam the cells around a specific location.                        *\n *    Typically, as a gap generator structure is created, this routine will be                 *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the jamming originates from.                       *\n *                                                                                             *\n *          jamrange -- The distance in cells that jamming extends.                            *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Jam_From(CELL cell, int jamrange, HouseClass * house)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot jam.\n\t*/\n\tif (!jamrange || jamrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[jamrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > jamrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tJam the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\tMap.Jam_Cell(newcell, house/*KO, false*/);\n\t}\n\n\t/*\n\t** Updated for client/server multiplayer. ST - 8/12/2019 3:25PM\n\t*/\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (!house->IsPlayerControl) {\n\t\t\tMap.Constrained_Look(Cell_Coord(cell), Rule.GapShroudRadius * CELL_LEPTON_W, PlayerPtr);\n\t\t}\n\t\t\n\t} else {\n\t\t\n\t\tfor (int i = 0; i < Session.Players.Count(); i++) {\n\t\t\tHouseClass *player_house = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tif (player_house->IsHuman && player_house != house) {\n\t\t\t\tMap.Constrained_Look(Cell_Coord(cell), Rule.GapShroudRadius * CELL_LEPTON_W, player_house);\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef OBSOLETE\n\t/*\n\t**\tThe objects on the map need to perform a manual look operation if they happen\n\t**\tto have their sight range overlap the gap radius.\n\t*/\n\tif (!house->IsPlayerControl) {\n//\tif (house != PlayerPtr) {\n\n\t\tfor (int index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {\n\t\t\tObjectClass * object = Map.Layer[LAYER_GROUND][index];\n\t\t\tif (object && object->Is_Techno()) {\n\t\t\t\tTechnoClass * tech = ((TechnoClass *)object);\n\n\t\t\t\tif (tech->IsDiscoveredByPlayer &&\n\t\t\t\t\t(tech->Distance(As_Target(cell)) / CELL_LEPTON_W) <= tech->Techno_Type_Class()->SightRange + Rule.GapShroudRadius &&\n\t\t\t\t\t(tech->House->IsPlayerControl ||\n\t\t\t\t\t(tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)))) {\n\n\t\t\t\t\tobject->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t** Here all the player's vehicles will perform a look if they're within\n\t\t** the shadow.\n\t\t*/\n\t\tfor (int index = 0; index < Units.Count(); index++) {\n\t\t\tUnitClass * unit = Units.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass * unit = Infantry.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass * unit = Vessels.Ptr(index);\n\t\t\tif (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {\n\t\t\t\tint dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;\n\t\t\t\tif (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {\n\t\t\t\t\tunit->Look();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n}\n\n\n/***********************************************************************************************\n * MapClass::UnJam_From -- Remove jamming on the cells within a specified radius.              *\n *                                                                                             *\n *    This routine is used to jam the cells around a specific location.                        *\n *    Typically, as a gap generator structure is created, this routine will be                 *\n *    called. Since it deals with MANY cells, it needs to be extremely                         *\n *    fast.                                                                                    *\n *                                                                                             *\n * INPUT:   cell     -- The coordinate that the jamming originates from.                       *\n *                                                                                             *\n *          jamrange -- The distance in cells that jamming extends.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::UnJam_From(CELL cell, int jamrange, HouseClass * house)\n{\n\tint xx;\t\t\t\t// Center cell X coordinate (bounds checking).\n\tint const * ptr;\t// Offset pointer.\n\tint count;\t\t\t// Counter for number of offsets to process.\n\n\t/*\n\t**\tUnits that are off-map cannot jam.\n\t*/\n\tif (!jamrange || jamrange > Rule.GapShroudRadius) return;\n\n\t/*\n\t**\tDetermine logical cell coordinate for center scan point.\n\t*/\n\txx = Cell_X(cell);\n\n\t/*\n\t**\tIncremental scans only scan the outer rings. Full scans\n\t**\tscan all internal cells as well.\n\t*/\n\tcount = RadiusCount[jamrange];\n\tptr = &RadiusOffset[0];\n\n\t/*\n\t**\tProcess all offsets required for the desired scan.\n\t*/\n\twhile (count--) {\n\t\tCELL\tnewcell;\t\t\t// New cell with offset.\n\t\tint\txdiff;\t\t\t// New cell's X coordinate distance from center.\n\n\t\tnewcell = cell + *ptr++;\n\n\t\t/*\n\t\t**\tDetermine if the map edge has been wrapped. If so,\n\t\t**\tthen don't process the cell.\n\t\t*/\n\t\tif ((unsigned)newcell >= MAP_CELL_TOTAL) continue;\n\t\txdiff = Cell_X(newcell) - xx;\n\t\txdiff = ABS(xdiff);\n\t\tif (xdiff > jamrange) continue;\n\t\tif (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;\n\n\t\t/*\n\t\t**\tJam the cell. For incremental scans, then update\n\t\t**\tadjacent cells as well. For full scans, just update\n\t\t**\tthe cell itself.\n\t\t*/\n\t\tMap.UnJam_Cell(newcell, house);\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::In_Radar -- Is specified cell in the radar map?                                   *\n *                                                                                             *\n *    This determines if the specified cell can be within the navigable                        *\n *    bounds of the map. Technically, this means, any cell that can be                         *\n *    scanned by radar. If a cell returns false from this function, then                       *\n *    the player could never move to or pass over this cell.                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine.                                                      *\n *                                                                                             *\n * OUTPUT:  bool; Is this cell possible to be displayed on radar?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/30/1994 JLB : Converted to member function.                                            *\n *   05/01/1994 JLB : Speeded up.                                                              *\n *=============================================================================================*/\nbool MapClass::In_Radar(CELL cell) const\n{\n\t/*\n\t**\tIf the cell value is WAY out of range, then it obviously can't be part of the game\n\t**\tplayfield.\n\t*/\n\tif ((unsigned)cell > MAP_CELL_TOTAL) return(false);\n\n\t/*\n\t**\tIf the cell is off the left or right edge of the playfield, then return the \"not in\n\t**\tradar\" flag.\n\t*/\n\tif ((unsigned)(Cell_X(cell) - MapCellX) >= (unsigned)MapCellWidth) return(false);\n\n\t/*\n\t**\tIf the cell is off the top or bottom edge of the playfield, then return the \"not in\n\t**\tradar\" flag.\n\t*/\n\tif ((unsigned)(Cell_Y(cell) - MapCellY) >= (unsigned)MapCellHeight) return(false);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Place_Down -- Places the specified object onto the map.                           *\n *                                                                                             *\n *    This routine is used to place an object onto the map. It updates the \"occupier\" of the   *\n *    cells that this object covers. The cells are determined from the Occupy_List function    *\n *    provided by the object. Only one cell can have an occupier and this routine is the only  *\n *    place that sets this condition.                                                          *\n *                                                                                             *\n * INPUT:   cell     -- The cell to base object occupation around.                             *\n *                                                                                             *\n *          object   -- The object to place onto the map.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Place_Down(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Occupy_Down(object);\n\t\t\t\t(*this)[newcell].Recalc_Attributes();\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tlist = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Down(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Pick_Up -- Removes specified object from the map.                                 *\n *                                                                                             *\n *    The object specified is removed from the map by this routine. This will remove the       *\n *    occupation flag for all the cells that the object covers. The cells that are covered     *\n *    are determined from the Occupy_List function.                                            *\n *                                                                                             *\n * INPUT:   cell     -- The cell that the object is centered about.                            *\n *                                                                                             *\n *          object   -- Pointer to the object that will be removed.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Pick_Up(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Occupy_Up(object);\n\t\t\t\t(*this)[newcell].Recalc_Attributes();\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tlist = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Up(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overlap_Down -- computes & marks object's overlap cells                           *\n *                                                                                             *\n * This routine is just like Place_Down, but it doesn't mark the cell's Occupier.              *\n * This routine is used to implement MARK_OVERLAP_DOWN, which is useful for changing           *\n * an object's render size, but not its logical size (ie when it's selected or an              *\n * animation is attached to it).                                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell -- The cell to base object overlap around.                                        *\n *    object   -- The object to place onto the map.                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Overlap_Down(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Down(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overlap_Up -- Computes & clears object's overlap cells                            *\n *                                                                                             *\n * This routine is just like Pick_Up, but it doesn't mark the cell's Occupier.                 *\n * This routine is used to implement MARK_OVERLAP_UP, which is useful for changing             *\n * an object's render size, but not its logical size (ie when it's selected or an              *\n * animation is attached to it).                                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell -- The cell to base object overlap around.                                        *\n *    object   -- The object to place onto the map.                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Overlap_Up(CELL cell, ObjectClass * object)\n{\n\tif (!object) return;\n\n\tif (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {\n\t\tshort xlist[32];\n\t\tList_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);\n\t\tshort const * list = xlist;\n\t\twhile (*list != REFRESH_EOL) {\n\t\t\tCELL newcell = cell + *list++;\n\t\t\tif ((unsigned)newcell < MAP_CELL_TOTAL) {\n\t\t\t\t(*this)[newcell].Overlap_Up(object);\n\t\t\t\t(*this)[newcell].Redraw_Objects();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.              *\n *                                                                                             *\n *    This routine will clean up anything necessary with the presumption that the map has      *\n *    been freshly created. Such things to clean up include various tiberium concentrations.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the total credit value of the tiberium on the map.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *   02/13/1995 JLB : Returns total tiberium worth.                                            *\n *   02/15/1995 JLB : Optimal scan.                                                            *\n *=============================================================================================*/\nlong MapClass::Overpass(void)\n{\n\tlong value = 0;\n\n\t/*\n\t**\tSmooth out Tiberium. Cells that are not surrounded by other tiberium\n\t**\twill be reduced in density.\n\t*/\n\tfor (int y = 0; y < MapCellHeight; y++) {\n\t\tfor (int x = 0; x < MapCellWidth; x++) {\n\t\t\tCELL cell = (MapCellY+y) * MAP_CELL_W + (MapCellX+x);\n\t\t\tvalue += (*this)[cell].Tiberium_Adjust(true);\n\t\t\t(*this)[cell].Recalc_Attributes();\n\t\t}\n\t}\n\treturn(value);\n}\n\n\n/***********************************************************************************************\n * MapClass::Write_Binary -- Pipes the map template data to the destination specified.         *\n *                                                                                             *\n *    This stores the template data from the map to the output pipe specified. The template    *\n *    data consists of the template type number and template icon number for every cell on     *\n *    the map. The output is organized in such a way so as to get maximum compression.         *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the output pipe that will receive the map template data.     *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes output to the pipe.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Write_Binary(Pipe & pipe)\n{\n\tint total = 0;\n\n\tLCWPipe comp(LCWPipe::COMPRESS);\n\tcomp.Put_To(&pipe);\n\n\tCellClass * cellptr = &Array[0];\n\tfor (int i = 0; i < MAP_CELL_TOTAL; i++) {\n\t\ttotal += comp.Put(&cellptr->TType, sizeof(cellptr->TType));\n\t\tcellptr++;\n\t}\n\n\tcellptr = &Array[0];\n\tfor (int i = 0; i < MAP_CELL_TOTAL; i++) {\n\t\ttotal += comp.Put(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\tcellptr++;\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * MapClass::Read_Binary -- Reads the binary data from the straw specified.                    *\n *                                                                                             *\n *    This routine will retrieve the map template data from the straw specified.               *\n *                                                                                             *\n * INPUT:   straw -- Reference to the straw that will supply the map template data.            *\n *                                                                                             *\n * OUTPUT:  bool; Was the template data retrieved?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Read_Binary(Straw & straw)\n{\n\tLCWStraw decomp(LCWStraw::DECOMPRESS);\n\tdecomp.Get_From(&straw);\n\n\tCELL cell;\n\tCellClass * cellptr;\n\tswitch (NewINIFormat) {\n\t\tdefault:\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TType, sizeof(cellptr->TType));\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\t\t\tcellptr->Recalc_Attributes();\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t\tcellptr = &Array[0];\n\t\t\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tdecomp.Get(&cellptr->TType, sizeof(cellptr->TType));\n\t\t\t\tdecomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));\n\t\t\t\tcellptr->Recalc_Attributes();\n\t\t\t\tcellptr++;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Logic -- Handles map related logic functions.                                     *\n *                                                                                             *\n *    Manages tiberium growth and spread.                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/11/1995 JLB : Created.                                                                 *\n *   07/09/1995 JLB : Handles two directional scan.                                            *\n *   08/01/1995 JLB : Gives stronger weight to blossom trees.                                  *\n *=============================================================================================*/\nvoid MapClass::Logic(void)\n{\n\tif (Debug_Force_Crash) { *((int *)0) = 1; }\n\t/*\n\t**\tCrate regeneration is handled here.\n\t*/\n\tif (Session.Type != GAME_NORMAL && Session.Options.Goodies) {\n\n\t\t/*\n\t\t**\tFind any crate that has expired and then regenerate it at a new\n\t\t**\tspot.\n\t\t*/\n\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\t\tif (Crates[index].Is_Expired()) {\n\t\t\t\tCrates[index].Remove_It();\n\t\t\t\tPlace_Random_Crate();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tBail early if there is no allowed growth or spread of Tiberium.\n\t*/\n\tif (!Rule.IsTGrowth && !Rule.IsTSpread) return;\n\n\t/*\n\t**\tScan another block of the map in order to accumulate the potential\n\t**\tTiberium cells that can grow or spread.\n\t*/\n\tint subcount = MAP_CELL_TOTAL / (Rule.GrowthRate * TICKS_PER_MINUTE);\n\n\t/*\n\t** Use the Tiberium setting as a multiplier on growth rate. ST - 7/1/2020 3:05PM\n\t*/\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (Session.Options.Tiberium > 1) {\n\t\t\tsubcount *= Session.Options.Tiberium;\n\t\t}\n\t}\t\t \n\n\tsubcount = max(subcount, 1);\n\tint index;\n\tfor (index = TiberiumScan; index < MAP_CELL_TOTAL; index++) {\n\t\tCELL cell = index;\n\t\tif (In_Radar(cell)) {\n\t\t\tCellClass * ptr = &(*this)[cell];\n\n\t\t\t/*\n\t\t\t**\tTiberium cells can grow.\n\t\t\t*/\n\t\t\tif (ptr->Can_Tiberium_Grow()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tEither replace an existing recorded cell value or add the new cell value to\n\t\t\t\t**\tthe list.\n\t\t\t\t*/\n\t\t\t\tif (Random_Pick(0, TiberiumGrowthExcess) <= TiberiumGrowthCount) {\n\t\t\t\t\tif (TiberiumGrowthCount < sizeof(TiberiumGrowth)/sizeof(TiberiumGrowth[0])) {\n\t\t\t\t\t\tTiberiumGrowth[TiberiumGrowthCount++] = cell;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTiberiumGrowth[Random_Pick(0, TiberiumGrowthCount-1)] = cell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTiberiumGrowthExcess++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tHeavy Tiberium growth can spread.\n\t\t\t*/\n\t\t\tif (ptr->Can_Tiberium_Spread()) {\n\t\t\t\t/*\n\t\t\t\t**\tEither replace an existing recorded cell value or add the new cell value to\n\t\t\t\t**\tthe list.\n\t\t\t\t*/\n\t\t\t\tif (Random_Pick(0, TiberiumSpreadExcess) <= TiberiumSpreadCount) {\n\t\t\t\t\tif (TiberiumSpreadCount < ARRAY_SIZE(TiberiumSpread)) {\n\t\t\t\t\t\tTiberiumSpread[TiberiumSpreadCount++] = cell;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTiberiumSpread[Random_Pick(0, TiberiumSpreadCount-1)] = cell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTiberiumSpreadExcess++;\n\t\t\t}\n\t\t}\n\n\t\tsubcount--;\n\t\tif (subcount == 0) break;\n\t}\n\tTiberiumScan = index;\n\n\t/*\n\t**\tWhen the entire map has been processed, proceed with tiberium (ore) growth\n\t**\tand spread action.\n\t*/\n\tif (TiberiumScan >= MAP_CELL_TOTAL) {\n\t\tTiberiumScan = 0;\n\n\t\t/*\n\t\t**\tGrowth logic.\n\t\t*/\n\t\tif (TiberiumGrowthCount) {\n\t\t\tfor (int i = 0; i < TiberiumGrowthCount; i++) {\n\t\t\t\tCELL cell = TiberiumGrowth[i];\n\t\t\t\tCellClass * newcell = &(*this)[cell];\n\t\t\t\tnewcell->Grow_Tiberium();\n\t\t\t}\n\t\t}\n\t\tTiberiumGrowthCount = 0;\n\t\tTiberiumGrowthExcess = 0;\n\n\t\t/*\n\t\t**\tSpread logic.\n\t\t*/\n\t\tif (TiberiumSpreadCount) {\n\t\t\tfor (int i = 0; i < TiberiumSpreadCount; i++) {\n\t\t\t\tMap[TiberiumSpread[i]].Spread_Tiberium();\n\t\t\t}\n\t\t}\n\t\tTiberiumSpreadCount = 0;\n\t\tTiberiumSpreadExcess = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Cell_Region -- Determines the region from a specified cell number.                *\n *                                                                                             *\n *    Use this routine to determine what region a particular cell lies in.                     *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to examine.                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the region that the specified cell occupies.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Cell_Region(CELL cell)\n{\n\treturn((Cell_X(cell) / REGION_WIDTH) + 1) +\t(((Cell_Y(cell) / REGION_HEIGHT) + 1) * MAP_REGION_WIDTH);\n}\n\n\n/***************************************************************************\n * MapClass::Cell_Threat -- Gets a houses threat value for a cell          *\n *                                                                         *\n * INPUT:   CELL        cell    - the cell number to check                 *\n *            HouseType house   - the house to check                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/25/1995 PWG : Created.                                             *\n *=========================================================================*/\nint MapClass::Cell_Threat(CELL cell, HousesType house)\n{\n\tint threat = HouseClass::As_Pointer(house)->Regions[Map.Cell_Region(Map[cell].Cell_Number())].Threat_Value();\n\t//using function for IsVisible so we have different results for different players - JAS 2019/09/30\n\tif (!threat && Map[cell].Is_Visible(house)) {\n\t\tthreat = 1;\n\t}\n\treturn(threat);\n}\n\n\n/***********************************************************************************************\n * MapClass::Place_Random_Crate -- Places a crate at random location on map.                   *\n *                                                                                             *\n *    This routine will place a crate at a random location on the map. This routine will only  *\n *    make a limited number of attempts to place and if unsuccessful, it will not place any.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was a crate successfully placed?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Place_Random_Crate(void)\n{\n\t/*\n\t**\tFind a crate index that is free for assignment. If there are\n\t**\tno free slots, then return with failure to place crate.\n\t*/\n\tint crateindex = 0;\n\tfor (crateindex = 0; crateindex < ARRAY_SIZE(Crates); crateindex++) {\n\t\tif (!Crates[crateindex].Is_Valid()) break;\n\t}\n\tif (crateindex == ARRAY_SIZE(Crates)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tGive a good effort to scan for and place a crate down on the map.\n\t*/\n\tfor (int index = 0; index < 1000; index++) {\n\t\tCELL cell = Map.Pick_Random_Location();\n\n\t\tif (Crates[crateindex].Create_Crate(cell)) {\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Remove_Crate -- Remove a crate from the specified cell.                           *\n *                                                                                             *\n *    This will examine the cell and remove any crates there.                                  *\n *                                                                                             *\n * INPUT:   cell  -- The cell to examine for crates and remove from.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was a crate found at the location specified and was it removed?              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Remove_Crate(CELL cell)\n{\n\tif (Session.Type != GAME_NORMAL) {\n\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n\t\t\tif (Crates[index].Is_Here(cell)) {\n\t\t\t\treturn(Crates[index].Remove_It());\n\t\t\t}\n\t\t}\n\t}\n\n//\tif (Session.Type == GAME_NORMAL) {\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tif (cellptr->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(cellptr->Overlay).IsCrate) {\n\t\t\tcellptr->Overlay = OVERLAY_NONE;\n\t\t\tcellptr->OverlayData = 0;\n\t\t\treturn(true);\n\t\t}\n//\t} else {\n//\t\tfor (int index = 0; index < ARRAY_SIZE(Crates); index++) {\n//\t\t\tif (Crates[index].Is_Here(cell)) {\n//\t\t\t\treturn(Crates[index].Remove_It());\n//\t\t\t}\n//\t\t}\n//\t}\n\treturn(false);\n}\n\n\n/***************************************************************************\n * MapClass::Validate -- validates every cell on the map                   *\n *                                                                         *\n * This is a debugging routine, designed to detect memory trashers that    *\n * alter the map.  This routine is slow, but thorough.                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = map is OK, false = an error was found                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MapClass::Validate(void)\n{\n\tCELL cell;\n\tTemplateType ttype;\n\tunsigned char ticon;\n\tTemplateTypeClass const *tclass;\n\tunsigned char map[13*8];\n\tOverlayType overlay;\n\tSmudgeType smudge;\n\tObjectClass * obj;\n\tLandType land;\n\tint i;\n\nBlubCell = &Array[797];\n\nif (BlubCell->Overlapper[1]) {\n\tobj = BlubCell->Overlapper[1];\n\tif (obj) {\n\t\tif (obj->IsInLimbo)\n\t\tobj = obj;\n\t}\n}\n\n\t/*\n\t**\tCheck every cell on the map, even those that aren't displayed,\n\t**\tin the hopes of detecting a memory trasher.\n\t*/\n\tfor (cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t/*\n\t\t**\tValidate Template & Icon data\n\t\t*/\n\t\tttype = (*this)[cell].TType;\n\t\tticon = (*this)[cell].TIcon;\n\t\tif (ttype >= TEMPLATE_COUNT && ttype != TEMPLATE_NONE)\n\t\t\treturn(false);\n\n\t\t/*\n\t\t**\tTo validate the icon value, we have to get a copy of the template's\n\t\t**\t\"icon map\"; this map will have 0xff's in spots where there is no\n\t\t**\ticon.  If the icon value is out of range or points to an invalid spot,\n\t\t**\treturn an error.\n\t\t*/\n\t\tif (ttype != TEMPLATE_NONE) {\n\t\t\ttclass = &TemplateTypeClass::As_Reference(ttype);\n\t\t\tticon = (*this)[cell].TIcon;\n\t\t\tMem_Copy(Get_Icon_Set_Map(tclass->Get_Image_Data()), map, tclass->Width * tclass->Height);\n\t\t\tif (ticon < 0 || ticon >= (tclass->Width * tclass->Height) || map[ticon]==0xff) {\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Overlay\n\t\t*/\n\t\toverlay = (*this)[cell].Overlay;\n\t\tif (overlay < OVERLAY_NONE || overlay >= OVERLAY_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Smudge\n\t\t*/\n\t\tsmudge = (*this)[cell].Smudge;\n\t\tif (smudge < SMUDGE_NONE || smudge >= SMUDGE_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate LandType\n\t\t*/\n\t\tland = (*this)[cell].Land_Type();\n\t\tif (land < LAND_CLEAR || land >= LAND_COUNT) {\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Occupier\n\t\t*/\n\t\tobj = (*this)[cell].Cell_Occupier();\n\t\tif (obj) {\n\t\t\tif (\n\t\t\t\t((unsigned int)obj & 0xff000000) ||\n\t\t\t\t((unsigned int)obj->Next & 0xff000000) ||\n//\t\t\t\t((unsigned int)obj->Trigger & 0xff000000) ||\n\t\t\t\tobj->IsInLimbo ||\n\t\t\t\t((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {\n\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tValidate Overlappers\n\t\t*/\n\t\tfor (i = 0; i < ARRAY_SIZE((*this)[cell].CellClass::Overlapper); i++) {\n\t\t\tobj = (*this)[cell].Overlapper[i];\n\t\t\tif (obj) {\n\t\t\t\tif (\n\t\t\t\t\t((unsigned int)obj & 0xff000000) ||\n\t\t\t\t\t((unsigned int)obj->Next & 0xff000000) ||\n//\t\t\t\t\t((unsigned int)obj->Trigger & 0xff000000) ||\n\t\t\t\t\tobj->IsInLimbo ||\n\t\t\t\t\t((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {\n\n\t\t\t\t\treturn (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (true);\n}\n\n\n/***********************************************************************************************\n * MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.       *\n *                                                                                             *\n *    This routine is used by the mouse input processing code to find a clickable object       *\n *    close to coordinate specified. This is for targeting as well as selection determination. *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to scan for close object from.                             *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an object that is nearby the specified coordinate.       *\n *                                                                                             *\n * WARNINGS:   There could be a cloaked object at the location, but it won't be considered     *\n *             if it is not owned by the player.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * MapClass::Close_Object(COORDINATE coord) const\n{\n\tObjectClass * object = 0;\n\tint distance = 0;\n\tCELL cell = Coord_Cell(coord);\n\n\t/*\n\t**\tScan through current and adjacent cells, looking for the\n\t**\tclosest object (within reason) to the specified coordinate.\n\t*/\n\tstatic int _offsets[] = {0, -1, 1, -MAP_CELL_W, MAP_CELL_W, MAP_CELL_W-1, MAP_CELL_W+1, -(MAP_CELL_W-1), -(MAP_CELL_W+1)};\n\tfor (int index = 0; index < (sizeof(_offsets) / sizeof(_offsets[0])); index++) {\n\n\t\t/*\n\t\t**\tExamine the cell for close object. Make sure that the cell actually is a\n\t\t**\tlegal one.\n\t\t*/\n\t\tCELL newcell = cell + _offsets[index];\n\t\tif (In_Radar(newcell)) {\n\n\t\t\t/*\n\t\t\t**\tSearch through all objects that occupy this cell and then\n\t\t\t**\tfind the closest object. Check against any previously found object\n\t\t\t**\tto ensure that it is actually closer.\n\t\t\t*/\n\t\t\tObjectClass * o = Array[newcell].Cell_Occupier();\n\t\t\twhile (o != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSpecial case check to ignore cloaked object if not allied with the player.\n\t\t\t\t*/\n\t\t\t\t// Change for client/server multiplayer. ST - 8/7/2019 10:35AM\n\t\t\t\t//if (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) {\n\t\t\t\tif (!o->Is_Techno() || !((TechnoClass *)o)->Is_Cloaked(PlayerPtr)) {\n\t\t\t\t\tint d=-1;\n\t\t\t\t\tif (o->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\td = Distance(coord, Cell_Coord(newcell));\n\t\t\t\t\t\tif (d > 0x00C0) d = -1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\td = Distance(coord, o->Center_Coord());\n\t\t\t\t\t}\n\t\t\t\t\tif (d >= 0 && (!object || d < distance)) {\n\t\t\t\t\t\tdistance = d;\n\t\t\t\t\t\tobject = o;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\to = o->Next;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Handle aircraft selection separately, since they aren't tracked in cells while flying\n\t*/\n\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\tAircraftClass * aircraft = Aircraft.Ptr(index);\n\n\t\tif (aircraft->In_Which_Layer() != LAYER_GROUND) {\n\t\t\tif (!aircraft->Is_Cloaked(PlayerPtr)) {\n\t\t\t\tint d = Distance(coord, Coord_Add(aircraft->Center_Coord(), XY_Coord(0, -aircraft->Height)));\n\t\t\t\tif (d >= 0 && (!object || d < distance)) {\n\t\t\t\t\tdistance = d;\n\t\t\t\t\tobject = aircraft;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tOnly return the object if it is within 1/4 cell distance from the specified\n\t**\tcoordinate.\n\t*/\n\tif (object && distance > 0xC0) {\n\t\tobject = 0;\n\t}\n\treturn(object);\n}\n\n\n/***********************************************************************************************\n * MapClass::Zone_Reset -- Resets all zone numbers to match the map.                           *\n *                                                                                             *\n *    This routine will rescan the map and fill in the zone values for each of the cells.      *\n *    All cells that are contiguous are given the same zone number.                            *\n *                                                                                             *\n * INPUT:   method   -- The method to recalculate the zones upon. If 1 then recalc non         *\n *                      crushable zone. If 2 then recalc crushable zone. If 3, then            *\n *                      recalc both zones.                                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is a time consuming routine. Call it as infrequently as possible. It must  *\n *             be called whenever something that would affect contiguousness occurs. Example:  *\n *             when a bridge is built or destroyed.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Zone_Reset(int method)\n{\n\t/*\n\t**\tZero out all zones to a null state.\n\t*/\n\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tif (method & MZONEF_NORMAL) {\n\t\t\tArray[index].Zones[MZONE_NORMAL] = 0;\n\t\t}\n\t\tif (method & MZONEF_CRUSHER) {\n\t\t\tArray[index].Zones[MZONE_CRUSHER] = 0;\n\t\t}\n\t\tif (method & MZONEF_DESTROYER) {\n\t\t\tArray[index].Zones[MZONE_DESTROYER] = 0;\n\t\t}\n\t\tif (method & MZONEF_WATER) {\n\t\t\tArray[index].Zones[MZONE_WATER] = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tNormal zone recalculation.\n\t*/\n\tif (method & MZONEF_NORMAL) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_NORMAL)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCrushable wall recalculation.\n\t*/\n\tif (method & MZONEF_CRUSHER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_CRUSHER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWall destroyer zone recalculation.\n\t*/\n\tif (method & MZONEF_DESTROYER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_DESTROYER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tWater based zone recalcuation.\n\t*/\n\tif (method & MZONEF_WATER) {\n\t\tint zone = 1;\t\t\t// Starting zone number.\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif (Zone_Span(cell, zone, MZONE_WATER)) {\n\t\t\t\tzone++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.                 *\n *                                                                                             *\n *    This routine is used to fill a zone value into the map. The map is \"flood filled\" from   *\n *    the cell specified. All adjacent (8 connected) and generally passable terrain cells are  *\n *    given the zone number specified. This routine checks for legality before filling         *\n *    occurs. The routine is safe to call even if the legality of the cell is unknown at the   *\n *    time of the call.                                                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to begin filling from.                                           *\n *                                                                                             *\n *          zone  -- The zone number to assign to all adjacent cells.                          *\n *                                                                                             *\n *          check -- The zone type to check against.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of cells marked by this routine.                           *\n *                                                                                             *\n * WARNINGS:   This routine is slow and recursive. Only use when necessary.                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1995 JLB : Created.                                                                 *\n *   10/05/1996 JLB : Examines crushable walls.                                                *\n *=============================================================================================*/\nint MapClass::Zone_Span(CELL cell, int zone, MZoneType check)\n{\n\tint filled = 0;\n\tint xbegin = Cell_X(cell);\n\tint xend = xbegin;\n\tint y = Cell_Y(cell);\n\n\t/*\n\t**\tPerform some preliminary legality checks. If the cell specified\n\t**\tis illegal, then no further processing is necessary.\n\t*/\n\tif (y < MapCellY || y >= MapCellY+MapCellHeight || xbegin < MapCellX || xbegin >= MapCellX+MapCellWidth) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tFind the full extent of the current span by first scanning leftward\n\t**\tuntil a boundary is reached.\n\t*/\n\tfor (; xbegin >= MapCellX; xbegin--) {\n\t\tCellClass * cellptr = &(*this)[XY_Cell(xbegin, y)];\n\t\tif (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {\n\n\t\t\t/*\n\t\t\t**\tSpecial short circuit code to bail from this entire routine if\n\t\t\t**\tit was called for a cell that is not a legal candidate for\n\t\t\t**\tzone marking. This eliminates redundant processing and allows this\n\t\t\t**\troutine to be called for illegal cells without causing an error.\n\t\t\t*/\n\t\t\tif (xbegin == Cell_X(cell)) return(0);\n\n\t\t\t/*\n\t\t\t**\tOtherwise break out of the left scan since a boundary was discovered.\n\t\t\t*/\n\t\t\txbegin++;\n\t\t\tbreak;\n\t\t}\n\t}\n\txbegin = max(xbegin, MapCellX);\n\n\t/*\n\t**\tScan rightward until a boundary is reached. This will then define the\n\t**\textent of the current span.\n\t*/\n\tfor (; xend < MapCellX+MapCellWidth; xend++) {\n\t\tCellClass * cellptr = &(*this)[XY_Cell(xend, y)];\n\t\tif (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {\n\t\t\txend--;\n\t\t\tbreak;\n\t\t}\n\t}\n\txend = min(xend, MapCellX+MapCellWidth-1);\n\n\t/*\n\t**\tAt this point we know the bounds of the current span. Fill in the zone values\n\t**\tfor the entire span.\n\t*/\n\tfor (int x = xbegin; x <= xend; x++) {\n\t\t(*this)[XY_Cell(x, y)].Zones[check] = zone;\n\t\tfilled++;\n\t}\n\n\t/*\n\t**\tNow scan the upper and lower shadow rows. If any of these rows contain\n\t**\tcandidate cells, then recursively call the span process for them. Take\n\t**\tnote that the adjacent span scanning starts one cell wider on each\n\t**\tend of the scan. This is necessary because diagonals are considered\n\t**\tadjacent.\n\t*/\n\tfor (int x = xbegin-1; x <= xend; x++) {\n\t\tfilled += Zone_Span(XY_Cell(x, y-1), zone, check);\n\t\tfilled += Zone_Span(XY_Cell(x, y+1), zone, check);\n\t}\n\treturn(filled);\n}\n\n\n/***********************************************************************************************\n * MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.        *\n *                                                                                             *\n *    This routine is used to find a location that probably will be ok to move to that is      *\n *    located as close as possible to the specified cell. The computer uses this when it has   *\n *    determined the ideal location for an object, but then needs to give a valid movement     *\n *    destination to a unit.                                                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell that scanning should radiate out from.                           *\n *                                                                                             *\n *          zone  -- The zone that must be matched to find a legal location (value of -1 means *\n *                   any zone will do).                                                        *\n *                                                                                             *\n *                                                                                             *\n *          check -- The type of zone to check against. Only valid if a zone value is given.   *\n *                                                                                             *\n *          checkflagged -- Whether the cell's flagged status is checked (used when dropping). *\n *                                                                                             *\n * OUTPUT:  Returns with the cell that is generally clear (legal to move to) that is close     *\n *          to the specified cell.                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType check, bool checkflagged, int locationmod) const\n{\n\tCELL topten[10];\n\tint count = 0;\n\tint xx = Cell_X(cell);\n\tint yy = Cell_Y(cell);\n\n\t/*\n\t**\tDetermine the limits of the scanning in the four directions so that\n\t**\tit won't scan past the edge of the world.\n\t*/\n\tint left = MapCellX;\n\tint right = MapCellX + MapCellWidth - 1;\n\tint top = MapCellY;\n\tint bottom = MapCellY + MapCellHeight - 1;\n\n\t/*\n\t**\tRadiate outward from the specified location, looking for the closest\n\t**\tlocation that is generally clear.\n\t*/\n\tfor (int radius = 0; radius < MAP_CELL_W; radius++) {\n\t\tCELL newcell;\n\t\tCellClass const * cellptr;\n\n\t\t/*\n\t\t**\tScan the top and bottom rows of the \"box\".\n\t\t*/\n\t\tfor (int x = xx-radius; x <= xx+radius; x++) {\n\t\t\tif (x >= left && x <= right) {\n\t\t\t\tint y = yy-radius;\n\t\t\t\tif (y >= top) {\n\t\t\t\t\tnewcell = XY_Cell(x, y);\n\t\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {\n\t\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t\t\ty = yy+radius;\n\t\t\t\tif (y <= bottom) {\n\t\t\t\t\tnewcell = XY_Cell(x, y);\n\t\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {\n\t\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\t\t\t}\n\t\t}\n\n\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t/*\n\t\t**\tScan the left and right columns of the \"box\".\n\t\t*/\n\t\tfor (int y = yy-radius; y <= yy+radius; y++) {\n\t\t\tif (y >= top && y <= bottom) {\n\t\t\t\tint x = xx-radius;\n\t\t\t\tif (x >= left) {\n\t\t\t\t\tnewcell = XY_Cell(x, y);\n\t\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {\n\t\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\n\t\t\t\tx = xx+radius;\n\t\t\t\tif (x <= right) {\n\t\t\t\t\tnewcell = XY_Cell(x, y);\n\t\t\t\t\tcellptr = &Map[newcell];\n\t\t\t\t\tif (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {\n\t\t\t\t\t\ttopten[count++] = newcell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (count == ARRAY_SIZE(topten)) break;\n\t\t\t}\n\t\t}\n\n\t\tif (count > 0) break;\n\t}\n\n\tif (count > 0) {\n\t\treturn(topten[(Frame+locationmod) % count]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MapClass::Base_Region -- Finds the owner and base zone for specified cell.                  *\n *                                                                                             *\n *    This routine is used to determine what base the specified cell is close to and what      *\n *    zone of that base the cell lies in. This routine is particularly useful in letting the   *\n *    computer know when the player targets a destination near a computer's base.              *\n *                                                                                             *\n * INPUT:   cell     -- The cell that is to be checked.                                        *\n *                                                                                             *\n *          house    -- Reference to the house type number. This value will be set if a base   *\n *                      was found nearby the specified cell.                                   *\n *                                                                                             *\n *          zone     -- The zone that the cell is located in IF the cell is near a base.       *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  Was a base near the specified cell found? If not, then the 'house' and 'zone'      *\n *          reference values are left in an undefined state and the return value will be       *\n *          false.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/05/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MapClass::Base_Region(CELL cell, HousesType & house, ZoneType & zone) const\n{\n\tif ((unsigned)cell < MAP_CELL_TOTAL && In_Radar(cell)) {\n\t\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * h = HouseClass::As_Pointer(house);\n\n\t\t\tif (h && h->IsActive && !h->IsDefeated && h->Center) {\n\t\t\t\tzone = h->Which_Zone(cell);\n\t\t\t\tif (zone != ZONE_NONE) {\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                  *\n *                                                                                             *\n *    This routine will destroy the bridge at the location specified.                          *\n *                                                                                             *\n * INPUT:   cell  -- A cell that can uniquely identify the bridge.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the bridge destroyed?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n\n// Need to inform the server of the cell change so it can communicate with the clients - SKY\nextern void On_Update_Map_Cell(int cell_x, int cell_y, const char* template_type_name);\n\nstruct CellUpdateStruct\n{\n\tconst TemplateTypeClass* Type;\n\tCELL Cell;\n};\n\nstatic const int MAX_UPDATES = 8;\n\nstatic void Add_Cell_Update(CellUpdateStruct* updates, int& count, TemplateType type, CELL cell)\n{\n\tnew TemplateClass(type, cell);\n\n\tassert(count < MAX_UPDATES);\n\tif (count < MAX_UPDATES)\n\t{\n\t\tupdates[count].Type = TemplateTypes.Ptr((int)type);\n\t\tupdates[count].Cell = cell;\n\t\tcount++;\n\t}\n}\n\nbool MapClass::Destroy_Bridge_At(CELL cell)\n{\n\tbool destroyed = false;\n\tif (In_Radar(cell) && !Special.IsCaptureTheFlag) {\n\t\tCellClass * cellptr = &(*this)[cell];\n\t\tTemplateType ttype = cellptr->TType;\n\n\t\tCellUpdateStruct cell_updates[MAX_UPDATES];\n\t\tint update_count = 0;\n\n\t\tif (ttype == TEMPLATE_BRIDGE1 || ttype == TEMPLATE_BRIDGE2) {\n\t\t\tint icon = cellptr->TIcon;\n\t\t\tint w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\tint h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\tcell -= icon % w;\n\t\t\tcell -= MAP_CELL_W * (icon / w);\n\n\t\t\tif (ttype == TEMPLATE_BRIDGE1) {\n\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE1H, cell);\n\t\t\t} else {\n\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE2H, cell);\n\t\t\t}\n\n\t\t\tnew AnimClass(ANIM_NAPALM3, Cell_Coord(cell + w/2 + (h/2)*MAP_CELL_W));\n\t\t}\n\n\t\tif (ttype == TEMPLATE_BRIDGE1H || ttype == TEMPLATE_BRIDGE2H) {\n\t\t\tint icon = cellptr->TIcon;\n\t\t\tint bridge_w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\tint bridge_h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\tcell -= icon % bridge_w;\n\t\t\tcell -= MAP_CELL_W * (icon / bridge_w);\n\n\t\t\tif (ttype == TEMPLATE_BRIDGE1H) {\n\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE1D, cell);\n\t\t\t} else {\n\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE2D, cell);\n\t\t\t}\n\n\t\t\tScen.BridgeCount--;\n\t\t\tScen.IsBridgeChanged = true;\n\t\t\tnew AnimClass(ANIM_NAPALM3, Cell_Coord(cell + bridge_w/2 + (bridge_h/2)*MAP_CELL_W));\n\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\n\t\t\t/*\n\t\t\t** Now, loop through all the bridge cells and find anyone standing\n\t\t\t** on a destroyed part (which is now river), and nuke them.\n\t\t\t*/\n\t\t\tCELL cell2 = cell;\n\t\t\tfor (int y = 0; y < bridge_h; y++) {\n\t\t\t\tfor (int x = 0; x < bridge_w; x++) {\n\t\t\t\t\tCellClass * bridge_cell = &(*this)[cell2];\n\t\t\t\t\tif (bridge_cell->TType == ttype) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tAny unit that is firing on the bridge at this location, will stop\n\t\t\t\t\t\t**\tfiring because the bridge has been destroyed.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tDetach_This_From_All(As_Target(cell2), true);\n\n\t\t\t\t\t\tObjectClass * obj = bridge_cell->Cell_Occupier();\n\t\t\t\t\t\twhile (obj != NULL) {\n\t\t\t\t\t\t\tObjectClass * next = obj->Next;\n\t\t\t\t\t\t\tif (obj->Is_Techno()) {\n\t\t\t\t\t\t\t\tint damage = obj->Strength;\n\t\t\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tobj = next;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcell2++;\n\t\t\t\t}\n\t\t\t\tcell2 += MAP_CELL_W - bridge_w;\n\t\t\t}\n\t\t\tShake_The_Screen(3);\n\n\t\t\tdestroyed = true;\n\t\t} else {\n\t\t\t/*\n\t\t\t** All this code is for the multi-part bridges.\n\t\t\t*/\n\t\t\tif (ttype >= TEMPLATE_BRIDGE_1A && ttype <= TEMPLATE_BRIDGE_3E) {\n\t\t\t\tint icon = cellptr->TIcon;\n\t\t\t\tint w = TemplateTypeClass::As_Reference(ttype).Width;\n\t\t\t\tint h = TemplateTypeClass::As_Reference(ttype).Height;\n\n\t\t\t\tcell -= icon % w;\n\t\t\t\tcell -= MAP_CELL_W * (icon / w);\n\t\t\t\tswitch (ttype) {\n\t\t\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_2A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_2B:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\tttype++;\n\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, ttype, cell);\n\t\t\t\t\t\tbreak;\n\t\t \t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we were a middle piece that just got blown up, update the\n\t\t\t\t** adjoining pieces to make sure they're shaped properly.\n\t\t\t\t*/\n\t\t\t\tif (ttype == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t// check the template below us, at x-1, y+1\n\t\t\t\t\tCELL cell2 = cell + (MAP_CELL_W - 1);\n\t\t\t\t\tCellClass * celptr = &(*this)[cell2];\n\t\t\t\t\tif (celptr->TType == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t\t// It was also destroyed.  Update us and it.\n\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell);\n\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell2);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Now check the template above us, at x+1, y-1.\n\t\t\t\t\tcell2 = cell - (MAP_CELL_W - 1);\n\t\t\t\t\tcelptr = &(*this)[cell2];\n\t\t\t\t\tif (celptr->TType == TEMPLATE_BRIDGE_3C) {\n\t\t\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_3D) {\n\t\t\t\t\t\t\t// if we're already one-sided, turn us to all water\n\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell2);\n\t\t\t\t\t}\n\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we're an end bridge piece, update the adjoining piece to\n\t\t\t\t** be the proper shape.\n\t\t\t\t*/\n\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_1C) {\n\t\t\t\t\tScen.BridgeCount--;\n\t\t\t\t\tScen.IsBridgeChanged = true;\n\n\t\t\t\t\t// Point to the template below us, x-1, y+2\n\t\t\t\t\tCELL cell2 = cell + (MAP_CELL_W * 2) - 1;\n\t\t\t\t\tswitch ((*this)[cell2].TType) {\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3D:\n\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_2C) {\n\t\t\t\t\t\t// Point to the template above us, x+2, y-1\n\t\t\t\t\t\tCELL cell2 = cell - (MAP_CELL_W - 2);\n\t\t\t\t\t\tswitch ((*this)[cell2].TType) {\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3A:\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3B:\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3C:\n\t\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell2);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase TEMPLATE_BRIDGE_3E:\n\t\t\t\t\t\t\t\tAdd_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell2);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (cellptr->TType == TEMPLATE_BRIDGE_1C ||\n\t\t\t\t\tcellptr->TType == TEMPLATE_BRIDGE_2C ||\n\t\t\t\t  (cellptr->TType >= TEMPLATE_BRIDGE_3C && cellptr->TType <= TEMPLATE_BRIDGE_3E)) {\n\t\t\t\t\tint x, y, tdata = 0;\n\t\t\t\t\tfor (y = 0; y < h; y++) {\n\t\t\t\t\t\tfor (x = 0; x < w; x++) {\n\t\t\t\t\t\t\tCellClass * ptr = &(*this)[(CELL)(cell + x)];\n\t\t\t\t\t\t\tif (ptr->TType == cellptr->TType || ptr->Land_Type() == LAND_RIVER || ptr->Land_Type() == LAND_WATER) {\n\t\t\t\t\t\t\t\tDetach_This_From_All(As_Target((CELL)(cell+tdata)), true);\n\n\t\t\t\t\t\t\t\tObjectClass * obj = ptr->Cell_Occupier();\n\t\t\t\t\t\t\t\twhile (obj != NULL) {\n\t\t\t\t\t\t\t\t\tObjectClass * next = obj->Next;\n\t\t\t\t\t\t\t\t\tif (obj->Is_Techno()) {\n\t\t\t\t\t\t\t\t\t\tint damage = obj->Strength;\n\t\t\t\t\t\t\t\t\t\tobj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tobj = next;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttdata++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcell += MAP_CELL_W;\n\t\t\t\t\t}\n\t\t\t\t\tMap.Zone_Reset(MZONEF_ALL);\n\t\t\t\t\tdestroyed = true;\n\t\t\t\t}\n\t\t\t\tShake_The_Screen(3);\n\t\t\t}\n\t\t}\n\n\t\tint cell_index = 0;\n\t\tchar cell_name[_MAX_PATH] = { 0 };\n\t\tchar icon_number[32] = { 0 };\n\t\tint icon = 0;\n\t\tvoid *image_data = 0;\n\t\tfor (int i = 0; i < update_count; i++) {\n\t\t\tconst TemplateTypeClass* type = cell_updates[i].Type;\n\t\t\tCELL cell = cell_updates[i].Cell;\n\t\t\tfor (int y = 0; y < type->Height; y++) {\n\t\t\t\tfor (int x = 0; x < type->Width; x++) {\n\t\t\t\t\tCELL newcell = cell + y * MAP_CELL_W + x;\n\t\t\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\t\t\tCellClass * newcellptr = &Map[newcell];\n\t\t\t\t\t\tif (newcellptr->Get_Template_Info(cell_name, icon, image_data)) {\n\t\t\t\t\t\t\titoa(icon, icon_number, 10);\n\t\t\t\t\t\t\tstrncat(cell_name, \"_i\", 32);\n\t\t\t\t\t\t\tstrncat(cell_name, icon_number, 32);\n\t\t\t\t\t\t\tstrncat(cell_name, \".tga\", 32);\n\t\t\t\t\t\t\tOn_Update_Map_Cell(Cell_X(newcell), Cell_Y(newcell), cell_name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(destroyed);\n}\n\n\n/***********************************************************************************************\n * MapClass::Detach -- Remove specified object from map references.                            *\n *                                                                                             *\n *    This routine will take the object (represented by a target value) and remove all         *\n *    references to it from the map. Typically, this is used to remove trigger reference.      *\n *                                                                                             *\n * INPUT:   target   -- The target object to remove from the map.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Detach(TARGET target, bool)\n{\n\t/*\n\t**\tRemove this trigger from the map zone/line tracking list.\n\t*/\n\tif (Is_Target_Trigger(target)) {\n\t\tfor (int index = 0; index < MapTriggers.Count(); index++) {\n\t\t\tif (MapTriggers[index] == As_Trigger(target)) {\n\t\t\t\tMapTriggers.Delete(index);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tLoop through all cells; remove any reference to this trigger\n\t\t*/\n\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\tif ((*this)[cell].Trigger == As_Trigger(target)) {\n\t\t\t\t(*this)[cell].Trigger = NULL;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                    *\n *                                                                                             *\n *    This will examine the entire map and return the number of bridges that are intact. An    *\n *    intact bridge is one that units can travel over.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of intact bridges on the map.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MapClass::Intact_Bridge_Count(void) const\n{\n\t/*\n\t**\tCount all non-destroyed bridges on the map.\n\t*/\n\tint count = 0;\n\tCellClass const * cellptr = &(*this)[(CELL)0];\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tswitch (cellptr->TType) {\n\t\t\tcase TEMPLATE_BRIDGE1:\n\t\t\tcase TEMPLATE_BRIDGE1H:\n\t\t\tcase TEMPLATE_BRIDGE2:\n\t\t\tcase TEMPLATE_BRIDGE2H:\n\t\t\tcase TEMPLATE_BRIDGE_1A:\n\t\t\tcase TEMPLATE_BRIDGE_1B:\n\t\t\t\tif (cellptr->TIcon == 6) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tcellptr++;\n\t}\n\n\treturn(count);\n}\n\n\n/***********************************************************************************************\n * MapClass::Pick_Random_Location -- Picks a random location on the map.                       *\n *                                                                                             *\n *    This routine will pick a random location on the map. It performs no legality checking    *\n *    other than forcing the cell to be on the map proper.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a cell that is within the map.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL MapClass::Pick_Random_Location(void) const\n{\n\tint x = Map.MapCellX + Random_Pick(0, Map.MapCellWidth-1);\n\tint y = Map.MapCellY + Random_Pick(0, Map.MapCellHeight-1);\n\n\treturn(XY_Cell(x, y));\n}\n\n\n#if (1)\n\n/***********************************************************************************************\n * MapClass::Shroud_The_Map -- cover the whole map in darkness (usually from blackout crate)\t  *\n *                                                                                             *\n * INPUT:   House to shroud                                                                    *\n *                                                                                             *\n * OUTPUT:  None\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 BWG : Created.                                                                 *\n *   08/12/2019  ST : Updated for client/server multiplayer                                    *\n *=============================================================================================*/\nvoid MapClass::Shroud_The_Map(HouseClass *house)\n{\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tCellClass * cellptr = &Map[cell];\n\t\tif (cellptr->Is_Mapped(house) || cellptr->Is_Visible(house)) {\n\t\t\t\n\t\t\tcellptr->Redraw_Objects();\n\t\t\t\n\t\t\t/*\n\t\t\t** BG: remove \"ring of darkness\" around edge of map.\n\t\t\t*/\n\t\t\tint x = Cell_X(cell);\n\t\t\tint y = Cell_Y(cell);\n\t\t\tif (x >= Map.MapCellX && x < (Map.MapCellX + Map.MapCellWidth) &&\n\t\t\t\ty >= Map.MapCellY && y < (Map.MapCellY + Map.MapCellHeight)) {\n\t\t\t\tcellptr->Set_Mapped(house, false);\n\t\t\t\tcellptr->Set_Visible(house, false);\n\t\t\t}\n\t\t}\n\t}\n\tfor (int obj_index = 0; obj_index < DisplayClass::Layer[LAYER_GROUND].Count(); obj_index++) {\n\t\tObjectClass * layer_object = DisplayClass::Layer[LAYER_GROUND][obj_index];\n\t\tif (layer_object && layer_object->Is_Techno() && ((TechnoClass *)layer_object)->House == house) {\n\t\t\tlayer_object->Look();\n\t\t}\n\t}\n\tFlag_To_Redraw(true);\n}\n\n\n#else\n\n//\n// Old code for posterity. ST - 8/12/2019 11:34AM\n//\n\n/***********************************************************************************************\n * MapClass::Shroud_The_Map -- cover the whole map in darkness (usually from blackout crate)\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a cell that is within the map.                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/19/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MapClass::Shroud_The_Map(void)\n{\n\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\tCellClass * cellptr = &Map[cell];\n\t\tif (cellptr->IsMapped || cellptr->IsVisible) {\n\t\t\tcellptr->Redraw_Objects();\n\t\t\t/*\n\t\t\t** BG: remove \"ring of darkness\" around edge of map.\n\t\t\t*/\n\t\t\tint x = Cell_X(cell);\n\t\t\tint y = Cell_Y(cell);\n\t\t\tif (x >= Map.MapCellX && x < (Map.MapCellX + Map.MapCellWidth) &&\n\t\t\t\ty >= Map.MapCellY && y < (Map.MapCellY + Map.MapCellHeight)) {\n\t\t\t\tcellptr->IsMapped = false;\n\t\t\t\tcellptr->IsVisible = false;\n\t\t\t}\n\t\t}\n\t}\n\tfor (int obj_index = 0; obj_index < DisplayClass::Layer[LAYER_GROUND].Count(); obj_index++) {\n\t\tObjectClass * layer_object = DisplayClass::Layer[LAYER_GROUND][obj_index];\n\t\tif (layer_object && layer_object->Is_Techno() && ((TechnoClass *)layer_object)->House == PlayerPtr) {\n\t\t\tlayer_object->Look();\n\t\t}\n\t}\n\tFlag_To_Redraw(true);\n}\n#endif"
  },
  {
    "path": "REDALERT/MAP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAP.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAP.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MAP_H\n#define MAP_H\n\n#include\t\"gscreen.h\"\n#include\t\"crate.h\"\n\nclass MapClass: public GScreenClass\n{\n\tpublic:\n\n\t\tMapClass(void) {};\n\t\tMapClass(NoInitClass const & x) : GScreenClass(x), Array(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t// Theater-specific inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Alloc_Cells(void);\t\t\t\t\t\t// Allocates buffers\n\t\tvirtual void Free_Cells(void);\t\t\t\t\t\t\t// Frees buffers\n\t\tvirtual void Init_Cells(void);\t\t\t\t\t\t\t// Frees buffers\n\n\t\t/*--------------------------------------------------------\n\t\t** Main functions that deal with groupings of cells within the map or deals with the cell\n\t\t** as it relates to the map - not what the cell contains.\n\t\t*/\n\t\tCELL Pick_Random_Location(void) const;\n\t\tint Intact_Bridge_Count(void) const;\n\t\tbool Base_Region(CELL cell, HousesType & house, ZoneType & zone) const;\n\t\tCELL Nearby_Location(CELL cell, SpeedType speed, int zone=-1, MZoneType check=MZONE_NORMAL, bool checkflagged=false, int locationmod=0) const;\n\t\tObjectClass * Close_Object(COORDINATE coord) const;\n\t\tvirtual void Detach(ObjectClass * ) {};\n\t\tint Cell_Region(CELL cell);\n\t\tint Cell_Threat(CELL cell, HousesType house);\n\t\tbool In_Radar(CELL cell) const;\n\t\tvoid Sight_From(CELL cell, int sightrange, HouseClass *house, bool incremental=false);\n\t\tvoid Jam_From(CELL cell, int jamrange, HouseClass *house);\n\t\tvoid Shroud_From(CELL cell, int sightrange, HouseClass *house);\n\t\tvoid UnJam_From(CELL cell, int jamrange, HouseClass *house);\n\t\tvoid Place_Down(CELL cell, ObjectClass * object);\n\t\tvoid Pick_Up(CELL cell, ObjectClass * object);\n\t\tvoid Overlap_Down(CELL cell, ObjectClass * object);\n\t\tvoid Overlap_Up(CELL cell, ObjectClass * object);\n\t\tbool Read_Binary(Straw & straw);\n\t\tint Write_Binary(Pipe & pipe);\n\t\tbool Place_Random_Crate(void);\n\t\tbool Remove_Crate(CELL cell);\n\t\tbool Zone_Reset(int method);\n\t\tbool Zone_Cell(CELL cell, int zone);\n\t\tint Zone_Span(CELL cell, int zone, MZoneType check);\n\t\tbool Destroy_Bridge_At(CELL cell);\n\t\tvoid Detach(TARGET target, bool all=true);\n\t\tvoid Shroud_The_Map(HouseClass *house);\n\n\t\tlong Overpass(void);\n\n\t\tvirtual void Logic(void);\n\t\tvirtual void Set_Map_Dimensions(int x, int y, int w, int h);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t** Debug routine\n\t\t*/\n\t\tint Validate(void);\n\n\t\t/*\n\t\t**\tThis is the dimensions and position of the sub section of the global map.\n\t\t**\tIt is this region that appears on the radar map and constrains normal\n\t\t**\tmovement.\n\t\t*/\n\t\tint MapCellX;\n\t\tint MapCellY;\n\t\tint MapCellWidth;\n\t\tint MapCellHeight;\n\n\t\t/*\n\t\t**\tThis is the total value of all harvestable Tiberium on the map.\n\t\t*/\n\t\tlong TotalValue;\n\n\t\tCellClass & operator [] (COORDINATE coord) {return(Array[Coord_Cell(coord)]);};\n\t\tCellClass & operator [] (CELL cell) {return(Array[cell]);};\n\t\tCellClass const & operator [] (COORDINATE coord) const {return(Array[Coord_Cell(coord)]);};\n\t\tCellClass const & operator [] (CELL cell) const {return(Array[cell]);};\n\t\tint ID(CellClass const * ptr) {return(Array.ID(ptr));};\n\t\tint ID(CellClass const & ptr) {return(Array.ID(ptr));};\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis is the array of cell objects.\n\t\t*/\n\t\tVectorClass<CellClass> Array;\n\n\t\t/*\n\t\t**\tThese are the size dimensions of the underlying array of cell objects.\n\t\t**\tThis is the dimensions of the \"map\" that the tactical view is\n\t\t**\trestricted to.\n\t\t*/\n\t\tint\tXSize;\n\t\tint\tYSize;\n\t\tint\tSize;\n\n\t\tstatic int const RadiusCount[11];\n\t\tstatic int const RadiusOffset[];\n\n\t\t/*\n\t\t**\tThis specifies the information for the various crates in the game.\n\t\t*/\n\t\tCrateClass Crates[256];\n\n\tprivate:\n\t\tfriend class CellClass;\n\n\t\t/*\n\t\t**\tTiberium growth potential cells are recorded here.\n\t\t*/\n\t\tCELL TiberiumGrowth[MAP_CELL_W/2];\n\t\tint TiberiumGrowthCount;\n\t\tint TiberiumGrowthExcess;\n\n\t\t/*\n\t\t**\tList of cells that are full enough strength that they could spread\n\t\t**\tTiberium to adjacent cells.\n\t\t*/\n\t\tCELL TiberiumSpread[MAP_CELL_W/2];\n\t\tint TiberiumSpreadCount;\n\t\tint TiberiumSpreadExcess;\n\n\t\t/*\n\t\t**\tThis is the current cell number in the incremental map scan process.\n\t\t*/\n\t\tCELL TiberiumScan;\n\n\t\tenum MapEnum {SCAN_AMOUNT=MAP_CELL_TOTAL};\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[1024];\n\n};\n\n#endif"
  },
  {
    "path": "REDALERT/MAPEDDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDDLG.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : September 4, 1996 [JLB]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Map Editor dialogs & main menu options                                  *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Handle_Triggers -- processes the trigger dialogs        *\n *   MapEditClass::Load_Scenario -- loads a scenario INI file              *\n *   MapEditClass::New_Scenario -- creates a new scenario                  *\n *   MapEditClass::Pick_Scenario -- dialog for choosing scenario           *\n *   MapEditClass::Save_Scenario -- saves current scenario to an INI file  *\n *   MapEditClass::Scenario_Dialog -- scenario global parameters dialog    *\n *   MapEditClass::Select_Trigger -- lets user select a trigger            *\n *   MapEditClass::Size_Map -- lets user set size & location of map        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::New_Scenario -- creates a new scenario                    *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n *   - Prompts user for map size                                           *\n * - Initializes the scenario by calling Clear_Scenario(), which calls     *\n *     everybody's Init() routine                                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = new scenario created, -1 = not                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::New_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n\tHousesType house;\n\n\t/*\n\t**\tForce the house save value to match the player house.\n\t*/\n\tif (PlayerPtr) {\n\t\tswitch (PlayerPtr->Class->House) {\n\t\t\tcase HOUSE_SPAIN:\n\t\t\t\tplayer = SCEN_PLAYER_SPAIN;\n\t\t\t\tbreak;\n\n\t\t\tcase HOUSE_GREECE:\n\t\t\t\tplayer = SCEN_PLAYER_GREECE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tcase HOUSE_USSR:\n\t\t\t\tplayer = SCEN_PLAYER_USSR;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"New Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\tScenarioInit++;\n\n\t/*\n\t**\tBlow away everything\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tCreate houses\n\t*/\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tnew HouseClass(house);\n\t}\n\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_MPLAYER:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_MULTI1);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tLastHouse = HOUSE_MULTI1;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_USSR);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_SPAIN;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_SPAIN);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_GREECE);\n\t\t\tPlayerPtr->IsHuman = true;\n\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tInit the entire map\n\t*/\n//\tInit_Clear();\n\tFill_In_Data();\n\n\t/*\n\t**\tPrompt for map size\n\t*/\n\tSize_Map(-1, -1, 30, 30);\n\n\t/*\n\t**\tSet the Home & Reinforcement Cells to the center of the map\n\t*/\n\tScen.Waypoint[WAYPT_REINF] = XY_Cell(MapCellX + MapCellWidth / 2, MapCellY + MapCellHeight / 2);\n\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + MapCellWidth / 2, MapCellY + MapCellHeight / 2);\n\t(*this)[TacticalCoord].IsWaypoint = 1;\n\tFlag_Cell(Coord_Cell(TacticalCoord));\n\n\tSet_Tactical_Position(Cell_Coord(Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR) - (5 * RESFACTOR)));\n\tScenarioInit--;\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Load_Scenario -- loads a scenario INI file                *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n * - Loads the INI file for that scenario                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0.                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Load_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n\tNodeNameType * who;\t\t\t\t\t\t// node to add to Players\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"Load Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tRead_Scenario_Ini() must be able to set PlayerPtr to the right house:\n\t**\t- Reading the INI will create the house objects\n\t**\t- PlayerPtr must be set before any Techno objects are created\n\t**\t- For GDI or NOD scenarios, PlayerPtr is set by reading the INI;\n\t**\t  but for multiplayer, it's set via the Players vector; so, here we have\n\t**\t  to set various multiplayer variables to fool the Assign_Houses() routine\n\t**\t  into working properly.\n\t*/\n\tif (player == SCEN_PLAYER_MPLAYER) {\n\t\tClear_Vector(&Session.Players);\n\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, Session.Handle);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\tSession.Players.Add (who);\n\n\t\tSession.NumPlayers = 1;\n\t\tLastHouse = HOUSE_MULTI1;\n\t} else {\n#ifdef NEVER\n\tif (ScenPlayer==SCEN_PLAYER_JP) {\n\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_MULTI4);\n\t\tPlayerPtr->IsHuman = true;\n\t\tBase.House = HOUSE_MULTI4;\n\t} else {\n#endif\n\t\tLastHouse = HOUSE_GOOD;\n\t}\n\n\t/*\n\t**\tBlow away everything\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tRead the INI\n\t*/\n\tif (Read_Scenario_INI(Scen.ScenarioName) == 0) {\n\t\tif(Scen.Scenario < 20 && Scen.ScenarioName[2] == 'G'){\n\t            WWMessageBox().Process(\"Please insert Red Alert CD1\");\n\t\t}else if(Scen.Scenario < 20 && Scen.ScenarioName[2] == 'U')\n            \t    WWMessageBox().Process(\"Please insert Red Alert CD2\");\n\t\telse\n\t\t    WWMessageBox().Process(\"Unable to read scenario!\");\n\t\tHidPage.Clear();\n\t\tFlag_To_Redraw(true);\n\t\tRender();\n\t} else {\n\t\tFill_In_Data();\n\t\tGamePalette.Set();\n//\t\tSet_Palette(GamePalette);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Save_Scenario -- saves current scenario to an INI file    *\n *                                                                         *\n * - Prompts user for scenario data (house, scenario #); sets globals      *\n *     PlayerPtr (for house) & Scenario (for scenario #)                   *\n * - Saves the INI file for this scenario                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = error/cancel                                          *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Save_Scenario(void)\n{\n\tint scen_num;\n\tScenarioPlayerType player;\n\tScenarioDirType dir;\n\tScenarioVarType var;\n\n\tDisect_Scenario_Name(Scen.ScenarioName, scen_num, player, dir, var);\n\n\tint rc;\n//\tFILE * fp;\n//\tchar fname[13];\n\n\t/*\n\t**\tPrompt for scenario info\n\t*/\n\trc = Pick_Scenario(\"Save Scenario\", scen_num, player, dir, var);\n\tif (rc != 0) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tWarning if scenario already exists\n\t*/\n//\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n//\tfp = fopen(fname, \"rb\");\n//\tif (fp) {\n//\t\tfclose(fp);\n//\t\trc = WWMessageBox().Process(\"File exists. Replace?\", TXT_YES, TXT_NO);\n//\t\tHidPage.Clear();\n//\t\tFlag_To_Redraw(true);\n//\t\tRender();\n//\t\tif (rc==1) {\n//\t\t\treturn(-1);\n//\t\t}\n//\t}\n\n\t/*\n\t**\tSet parameters\n\t*/\n//\tScen.Scenario = scen_num;\n//\tScen.ScenPlayer = player;\n//\tScen.ScenDir = dir;\n//\tScen.ScenVar = var;\n\tScen.Set_Scenario_Name(scen_num, player, dir, var);\n\n\t/*\n\t**\tPlayer may have changed from GDI to NOD, so change playerptr accordingly\n\t*/\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_USSR);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_SPAIN;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_SPAIN);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tPlayerPtr = HouseClass::As_Pointer(HOUSE_GREECE);\n\t\t\tPlayerPtr->IsHuman = true;\n//\t\t\tBase.House = HOUSE_USSR;\n\t\t\tLastHouse = HOUSE_GOOD;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tWrite the INI\n\t*/\n\tWrite_Scenario_INI(Scen.ScenarioName);\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Pick_Scenario -- dialog for choosing scenario             *\n *                                                                         *\n * Prompts user for:                                                       *\n *   - House (GDI, NOD)                                                    *\n *   - Scenario #                                                          *\n *                                                                         *\n *           Ŀ                          *\n *                       Caption                                         *\n *                                                                       *\n *                    Scenario ___                                       *\n *                     Version ___                                       *\n *                                                                       *\n *                    [East]  [West]                                     *\n *                                                                       *\n *                    [    GDI     ]                                     *\n *                    [    NOD     ]                                     *\n *                    [Multi-Player]                                     *\n *                                                                       *\n *                    [OK]  [Cancel]                                     *\n *                                                                       *\n *                                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      caption      string to use as a title                              *\n *      scen_nump   output: ptr to scenario #                              *\n *      playerp      output: ptr to player type                            *\n *      dirp         output: ptr to direction                              *\n *      varp         output: ptr to variation                              *\n *      multi         1 = allow to change single/multiplayer; 0 = not      *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *   09/04/1996 JLB : Simplified                                           *\n *=========================================================================*/\nint MapEditClass::Pick_Scenario(char const * caption, int & scen_nump, ScenarioPlayerType & playerp, ScenarioDirType & dirp, ScenarioVarType & varp)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 200,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 164,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320 - D_DIALOG_W) / 2),\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = ((200 - D_DIALOG_H) / 2),\t\t\t\t// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_SCEN_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// Scenario # width\n\t\tD_SCEN_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Scenario # height\n\t\tD_SCEN_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// Scenario # x\n\t\tD_SCEN_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,\t// Scenario # y\n\n\t\tD_VARA_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version A width\n\t\tD_VARA_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version A height\n\t\tD_VARA_X = D_DIALOG_CX - (D_VARA_W * 5) / 2,\t\t// Version A x\n\t\tD_VARA_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version A y\n\n\t\tD_VARB_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version B width\n\t\tD_VARB_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version B height\n\t\tD_VARB_X = D_VARA_X + D_VARA_W,\t\t\t\t\t\t// Version B x\n\t\tD_VARB_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version B y\n\n\t\tD_VARC_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version C width\n\t\tD_VARC_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version C height\n\t\tD_VARC_X = D_VARB_X + D_VARB_W,\t\t\t\t\t\t// Version C x\n\t\tD_VARC_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version C y\n\n\t\tD_VARD_W = 13,\t\t\t\t\t\t\t\t\t\t\t\t// Version D width\n\t\tD_VARD_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Version D height\n\t\tD_VARD_X = D_VARC_X + D_VARC_W,\t\t\t\t\t\t// Version D x\n\t\tD_VARD_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t\t// Version D y\n\n\t\tD_VARLOSE_W = 13,\t\t\t\t\t\t\t\t\t\t\t// Version Lose width\n\t\tD_VARLOSE_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Version Lose height\n\t\tD_VARLOSE_X = D_VARD_X + D_VARD_W,\t\t\t\t\t// Version Lose x\n\t\tD_VARLOSE_Y = D_SCEN_Y + D_SCEN_H + D_MARGIN,\t// Version Lose y\n\n\t\tD_EAST_W = 50,\t\t\t\t\t\t\t\t\t\t\t\t// EAST width\n\t\tD_EAST_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// EAST height\n\t\tD_EAST_X = D_DIALOG_CX - D_EAST_W - 5,\t\t\t\t// EAST x\n\t\tD_EAST_Y = D_VARLOSE_Y + D_VARLOSE_H + D_MARGIN,// EAST y\n\n\t\tD_WEST_W = 50,\t\t\t\t\t\t\t\t\t\t\t\t// WEST width\n\t\tD_WEST_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// WEST height\n\t\tD_WEST_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// WEST x\n\t\tD_WEST_Y = D_VARLOSE_Y + D_VARLOSE_H + D_MARGIN,// EAST y\n\n\t\tD_GDI_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// GDI width\n\t\tD_GDI_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// GDI height\n\t\tD_GDI_X = D_DIALOG_CX - (D_GDI_W / 2),\t\t\t\t// GDI x\n\t\tD_GDI_Y = D_EAST_Y + D_EAST_H + D_MARGIN,\t\t\t// GDI y\n\n\t\tD_NOD_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// NOD width\n\t\tD_NOD_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// NOD height\n\t\tD_NOD_X = D_DIALOG_CX - (D_NOD_W / 2),\t\t\t\t// NOD x\n\t\tD_NOD_Y = D_GDI_Y + D_GDI_H,\t\t\t\t\t\t\t// NOD y\n\n\t\tD_NEU_W = 90,\t\t\t\t\t\t\t\t\t\t\t\t// Neutral width\n\t\tD_NEU_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t// Neutral height\n\t\tD_NEU_X = D_DIALOG_CX - (D_NOD_W / 2),\t\t\t\t// Neutral x\n\t\tD_NEU_Y = D_NOD_Y + D_NOD_H,\t\t\t\t\t\t\t// Neutral y\n\n\t\tD_MPLAYER_W = 90,\t\t\t\t\t\t\t\t\t\t\t// Multi-Player width\n\t\tD_MPLAYER_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Multi-Player height\n\t\tD_MPLAYER_X = D_DIALOG_CX - (D_MPLAYER_W / 2),\t// Multi-Player x\n\t\tD_MPLAYER_Y = D_NEU_Y + D_NEU_H,\t\t\t\t\t\t// Multi-Player y\n\n\t\tD_OK_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_CX - D_OK_W - 5,\t\t\t\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - (D_MARGIN+15),\t// OK y\n\n\t\tD_CANCEL_W = 45,\t\t\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_CX + 5,\t\t\t\t\t\t\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - (D_MARGIN+15), // Cancel y\n\n\t};\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_GDI=100,\n\t\tBUTTON_NOD,\n\t\tBUTTON_NEUTRAL,\n\t\tBUTTON_MPLAYER,\n\t\tBUTTON_EAST,\n\t\tBUTTON_WEST,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_SCENARIO,\n\t\tBUTTON_VAR_A,\n\t\tBUTTON_VAR_B,\n\t\tBUTTON_VAR_C,\n\t\tBUTTON_VAR_D,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\n\t/*\n\t**\tOther Variables\n\t*/\n\tchar scen_buf[10]={0};\t\t\t\t\t\t// buffer for editing scenario #\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tEditClass editbtn (BUTTON_SCENARIO, scen_buf, 5, TPF_EFNT|TPF_NOSHADOW, D_SCEN_X, D_SCEN_Y, D_SCEN_W, D_SCEN_H, EditClass::ALPHANUMERIC);\n#else\n\tEditClass editbtn (BUTTON_SCENARIO, scen_buf, 5, TPF_EFNT|TPF_NOSHADOW, D_SCEN_X, D_SCEN_Y, D_SCEN_W, D_SCEN_H, EditClass::NUMERIC);\n#endif\n\n\tTextButtonClass varabtn(BUTTON_VAR_A, \"A\", TPF_EBUTTON, D_VARA_X, D_VARA_Y, D_VARA_W, D_VARA_H);\n\tTextButtonClass varbbtn(BUTTON_VAR_B, \"B\", TPF_EBUTTON, D_VARB_X, D_VARB_Y, D_VARB_W, D_VARB_H);\n\tTextButtonClass varcbtn(BUTTON_VAR_C, \"C\", TPF_EBUTTON, D_VARC_X, D_VARC_Y, D_VARC_W, D_VARC_H);\n\tTextButtonClass vardbtn(BUTTON_VAR_D, \"D\", TPF_EBUTTON, D_VARD_X, D_VARD_Y, D_VARD_W, D_VARD_H);\n\tTextButtonClass gdibtn(BUTTON_GDI, \"North (Spain)\", TPF_EBUTTON, D_GDI_X, D_GDI_Y, D_GDI_W, D_GDI_H);\n\tTextButtonClass nodbtn(BUTTON_NOD, \"South (Greece)\", TPF_EBUTTON, D_NOD_X, D_NOD_Y, D_NOD_W, D_NOD_H);\n\tTextButtonClass neubtn(BUTTON_NEUTRAL, HouseTypeClass::As_Reference(HOUSE_USSR).IniName, TPF_EBUTTON, D_NEU_X, D_NEU_Y, D_NEU_W, D_NEU_H);\n\tTextButtonClass playermbtn(BUTTON_MPLAYER, \"Multiplayer\", TPF_EBUTTON, D_MPLAYER_X, D_MPLAYER_Y, D_MPLAYER_W, D_MPLAYER_H);\n\tTextButtonClass eastbtn(BUTTON_EAST, \"East\", TPF_EBUTTON, D_EAST_X, D_EAST_Y, D_EAST_W, D_EAST_H);\n\tTextButtonClass westbtn(BUTTON_WEST, \"West\", TPF_EBUTTON, D_WEST_X, D_WEST_Y, D_WEST_W, D_WEST_H);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (scen_nump < 100) {\n\t\tsprintf(scen_buf, \"%d\", scen_nump);\t\t// init edit buffer\n\t} else {\n\t\tchar first = scen_nump / 36;\n\t\tchar second = scen_nump % 36;\n\t\tscen_buf[0] = first + 'A';\n//Mono_Printf(\"picking map, scen# = %d, first = %c, second = %d (numeric)\\n\",scen_nump, scen_buf[0],second);Keyboard->Get();Keyboard->Get();\n\t\tif (second < 10) {\n\t\t\tscen_buf[1] = second + '0';\n\t\t} else {\n\t\t\tscen_buf[1] = (second-10) + 'A';\n\t\t}\n\t\tscen_buf[2] = 0;\n\t}\n#else\n\tsprintf(scen_buf, \"%d\", scen_nump);\t\t// init edit buffer\n#endif\n\teditbtn.Set_Text(scen_buf, 5);\n\n\tvarabtn.Turn_Off();\n\tvarbbtn.Turn_Off();\n\tvarcbtn.Turn_Off();\n\tvardbtn.Turn_Off();\n\tswitch (varp) {\n\t\tcase SCEN_VAR_A:\n\t\t\tvarabtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_B:\n\t\t\tvarbbtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_C:\n\t\t\tvarcbtn.Turn_On();\n\t\t\tbreak;\n\n\t\tcase SCEN_VAR_D:\n\t\t\tvardbtn.Turn_On();\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tCreate the button list\n\t*/\n\tcommands = &editbtn;\n\tvarabtn.Add_Tail(*commands);\n\tvarbbtn.Add_Tail(*commands);\n\tvarcbtn.Add_Tail(*commands);\n\tvardbtn.Add_Tail(*commands);\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n\tneubtn.Add_Tail(*commands);\n\tplayermbtn.Add_Tail(*commands);\n\teastbtn.Add_Tail(*commands);\n\twestbtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tInit the button states\n\t*/\n\tgdibtn.Turn_Off();\n\tnodbtn.Turn_Off();\n\tneubtn.Turn_Off();\n\tplayermbtn.Turn_Off();\n\tif (playerp == SCEN_PLAYER_MPLAYER) {\n\t\tplayermbtn.Turn_On();\n\t} else {\n\t\tif (PlayerPtr) {\n\t\t\tswitch (PlayerPtr->Class->House) {\n\t\t\t\tcase HOUSE_SPAIN:\n\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase HOUSE_GREECE:\n\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase HOUSE_USSR:\n\t\t\t\t\tneubtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t} else {\n\t\t\tswitch (Scen.ScenarioName[2]) {\n\t\t\t\tcase 'G':\n\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'U':\n\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'M':\n\t\t\t\t\tplayermbtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\teastbtn.Turn_Off();\n\twestbtn.Turn_Off();\n\tif (dirp == SCEN_DIR_EAST) {\n\t\teastbtn.Turn_On();\n\t} else {\n\t\twestbtn.Turn_On();\n\t}\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tFancy_Text_Print(\"Scenario\", D_DIALOG_CX - 5, D_SCEN_Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_RIGHT | TPF_EFNT | TPF_NOSHADOW);\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tHandle a click on one of the scenario variation group buttons.\n\t\t\t*/\n\t\t\tcase (BUTTON_VAR_A | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_B | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_C | KN_BUTTON):\n\t\t\tcase (BUTTON_VAR_D | KN_BUTTON):\n\t\t\t\tvarabtn.Turn_Off();\n\t\t\t\tvarbbtn.Turn_Off();\n\t\t\t\tvarcbtn.Turn_Off();\n\t\t\t\tvardbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_VAR_A | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_A;\n\t\t\t\t\t\tvarabtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_B | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_B;\n\t\t\t\t\t\tvarbbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_C | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_C;\n\t\t\t\t\t\tvarcbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_VAR_D | KN_BUTTON):\n\t\t\t\t\t\tvarp = SCEN_VAR_D;\n\t\t\t\t\t\tvardbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tHandle a click on the east/west variation group.\n\t\t\t*/\n\t\t\tcase (BUTTON_EAST | KN_BUTTON):\n\t\t\tcase (BUTTON_WEST | KN_BUTTON):\n\t\t\t\twestbtn.Turn_Off();\n\t\t\t\teastbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_EAST | KN_BUTTON):\n\t\t\t\t\t\tdirp = SCEN_DIR_EAST;\n\t\t\t\t\t\teastbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_WEST | KN_BUTTON):\n\t\t\t\t\t\tdirp = SCEN_DIR_WEST;\n\t\t\t\t\t\twestbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\t/*\n\t\t\t**\tHandle a click on one of the player category\n\t\t\t**\tgroup buttons.\n\t\t\t*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\tcase (BUTTON_NEUTRAL | KN_BUTTON):\n\t\t\tcase (BUTTON_MPLAYER | KN_BUTTON):\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tneubtn.Turn_Off();\n\t\t\t\tplayermbtn.Turn_Off();\n\t\t\t\tswitch (input) {\n\t\t\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_SPAIN;\n\t\t\t\t\t\tgdibtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_GREECE;\n\t\t\t\t\t\tnodbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_NEUTRAL | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_USSR;\n\t\t\t\t\t\tneubtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_MPLAYER | KN_BUTTON):\n\t\t\t\t\t\tplayerp = SCEN_PLAYER_MPLAYER;\n\t\t\t\t\t\tplayermbtn.Turn_On();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SCENARIO | KN_BUTTON):\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSave selections & return\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (scen_buf[0] <= '9' && scen_buf[1] <= '9') {\n\t\tscen_nump = atoi(scen_buf);\n\t} else {\n\t\tchar first = scen_buf[0];\n\t\tchar second = scen_buf[1];\n\t\tif (first <= '9') {\n\t\t\tfirst -= '0';\n\t\t} else {\n\t\t\tif (first >= 'a' && first <= 'z') {\n\t\t\t\tfirst -= 'a';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\t\t}\n\t\tif (second <= '9') {\n\t\t\tsecond -= '0';\n\t\t} else {\n\t\t\tif (second >= 'a' && second <= 'z') {\n\t\t\t\tsecond = (second - 'a') + 10;\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\t\t}\n\t\tscen_nump = (first * 36) + second;\n//Mono_Printf(\"Converted to: %d, %d = %d\\n\",first, second, scen_nump);Keyboard->Get();Keyboard->Get();\n\t}\n#else\n\tscen_nump = atoi(scen_buf);\n#endif\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Size_Map -- lets user set size & location of map          *\n *                                                                         *\n * Lets the user select a side of the map and expand/shrink it to the      *\n * desired size, or move the whole map around the available map area.      *\n *                                                                         *\n * The entire available map area is displayed, but the map is limited such *\n * that there's always one blank cell around the map; this lets objects    *\n * properly exit the screen, since they have a blank undisplayed cell to   *\n * exit onto.                                                              *\n *                                                                         *\n *   Ŀ               *\n *                                                                       *\n *     Ŀ   Clear Terrain                           *\n *                             Water                                   *\n *                             Tiberium                                *\n *                             Rock/Wall/Road                          *\n *          (Map Area)         GDI Unit                                *\n *                             NOD Unit                                *\n *                             Neutral Unit                            *\n *                             Terrain Object                          *\n *                             Starting Cell                           *\n *                                                *\n *                                                                       *\n *         X            Y            Width      Height                   *\n *         ##           ##            ##          ##                     *\n *                                                                       *\n *                                                                       *\n *                  [OK]            [Cancel]                             *\n *                                                                       *\n *                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      x,y,w,h:      initial size parameters (-1 = center the thing)      *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Size_Map(int x, int y, int w, int h)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 350,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 225,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = 0,\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = 0,\t\t\t\t// centered y-coord\n//\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_BORD_X1 = D_DIALOG_X + 45,\n//\t\tD_BORD_X1 = D_DIALOG_X + (D_DIALOG_W / 2 - MAP_CELL_W) / 2,\n\t\tD_BORD_Y1 = D_DIALOG_Y + 25,\n\t\tD_BORD_X2 = D_BORD_X1 + MAP_CELL_W + 1,\n\t\tD_BORD_Y2 = D_BORD_Y1 + MAP_CELL_H + 1,\n\n\t\tD_OK_W = 45,\t\t\t\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9,\t\t\t\t\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_X + 45,\t\t\t\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - (D_MARGIN + 10),\t// OK y\n\n\t\tD_CANCEL_W = 45,\t\t\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9,\t\t\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (35 + D_CANCEL_W),\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - (D_MARGIN + 10), // Cancel y\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_OK=100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_MAP,\t\t\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map board, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tRedrawType display;\t\t\t\t\t\t\t// requested redraw level\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tint grabbed = 0;\t\t\t\t\t\t\t\t// 1=TLeft,2=TRight,3=BRight,4=BLeft\n\tint map_x1;\t\t\t\t\t\t\t\t\t\t// map coords x1, pixel coords\n\tint map_x2;\t\t\t\t\t\t\t\t\t\t// map coords x2, pixel coords\n\tint map_y1;\t\t\t\t\t\t\t\t\t\t// map coords y1, pixel coords\n\tint map_y2;\t\t\t\t\t\t\t\t\t\t// map coords y2, pixel coords\n\tint delta1, delta2;\t\t\t\t\t\t\t// mouse-click proximity\n\tint mx,my;\t\t\t\t\t\t\t\t\t\t// last-saved mouse coords\n//\tchar txt[40];\n\tint txt_x,txt_y;\t\t\t\t\t\t\t\t// for displaying text\n//\tunsigned index;\t\t\t\t\t\t\t\t// for drawing map symbology\n\tCELL cell;\t\t\t\t\t\t\t\t\t\t// for drawing map symbology\n\tint color;\t\t\t\t\t\t\t\t\t\t// for drawing map symbology\n\tObjectClass * occupier;\t\t\t\t\t\t// cell's occupier\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\n\n\tTextButtonClass okbtn (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tSet up the actual map area relative to the map's border coords\n\t*/\n\tif (x==-1) {\n\t\tmap_x1 = D_BORD_X1 + (MAP_CELL_W - w) / 2 + 1;\n\t} else {\n\t\tmap_x1 = D_BORD_X1 + x + 1;\n\t}\n\n\tif (y==-1) {\n\t\tmap_y1 = D_BORD_Y1 + (MAP_CELL_H - h) / 2 + 1;\n\t} else {\n\t\tmap_y1 = D_BORD_Y1 + y + 1;\n\t}\n\n\tmap_x2 = map_x1 + w - 1;\n\tmap_y2 = map_y1 + h - 1;\n\n\t/*\n\t**\tBuild the button list\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain processing loop\n\t*/\n\tdisplay = REDRAW_ALL;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tRedraw the background, map border, key, and coord labels\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBackground\n\t\t\t\t*/\n\t\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\t\tDraw_Caption(TXT_SIZE_MAP, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the map border\n\t\t\t\t*/\n\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\tLogicPage->Draw_Rect(D_BORD_X1, D_BORD_Y1, D_BORD_X2, D_BORD_Y2, scheme->Shadow);\n//\t\t\t\t\tfor (index = D_BORD_X1; index < D_BORD_X2;\n//\t\t\t\t\t\tindex += (320/ICON_PIXEL_W)) {\n//\t\t\t\t\t\tLogicPage->Put_Pixel(index, D_BORD_Y1-1, scheme->Shadow);\n//\t\t\t\t\t\tLogicPage->Put_Pixel(index, D_BORD_Y2+1, scheme->Shadow);\n//\t\t\t\t\t}\n//\t\t\t\t\tfor (index = D_BORD_Y1; index < D_BORD_Y2-8;\n//\t\t\t\t\t\tindex += (200/ICON_PIXEL_H)) {\n//\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1-1, index, scheme->Shadow);\n//\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X2+1, index, scheme->Shadow);\n//\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the map \"key\"\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_BORD_X2 + 15;\n\t\t\t\t\ttxt_y = D_BORD_Y1;\n\t\t\t\t\tPlain_Text_Print(\"Clear Terrain\", txt_x, txt_y, GroundColor[LAND_CLEAR], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Water\", txt_x, txt_y, GroundColor[LAND_WATER], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Tiberium\", txt_x, txt_y, GroundColor[LAND_TIBERIUM], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Rock\", txt_x, txt_y, GroundColor[LAND_ROCK], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Wall\", txt_x, txt_y, GroundColor[LAND_WALL], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Beach\", txt_x, txt_y, GroundColor[LAND_BEACH], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Rough\", txt_x, txt_y, GroundColor[LAND_ROUGH], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"River\", txt_x, txt_y, GroundColor[LAND_RIVER], TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"GDI Unit\", txt_x, txt_y, YELLOW, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"Nod Unit\", txt_x, txt_y, RED, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n//\t\t\t\t\ttxt_y += 8;\n//\t\t\t\t\tPlain_Text_Print(\"Neutral Unit\", txt_x, txt_y, PURPLE, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Terrain Object\", txt_x, txt_y, DKGREEN, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\t\t\t\t\ttxt_y += 8;\n\t\t\t\t\tPlain_Text_Print(\"Starting Cell\", txt_x, txt_y, WHITE, TBLACK, TPF_DROPSHADOW | TPF_EFNT);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the coordinate labels\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_DIALOG_X + D_DIALOG_W / 8;\n\t\t\t\t\ttxt_y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - 43;\n\t\t\t\t\tFancy_Text_Print(\"  X\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"  Y\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\" Width\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\" Height\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons\n\t\t\t\t*/\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the map symbology & location\n\t\t\t*/\n\t\t\tif (display >= REDRAW_MAP) {\n\n\t\t\t\tif (LogicPage->Lock()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tErase the map interior\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Fill_Rect(D_BORD_X1 + 1, D_BORD_Y1 + 1, D_BORD_X2 - 1, D_BORD_Y2 - 1, BLACK);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Land map symbols (use color according to Ground[] array).\n\t\t\t\t\t*/\n\t\t\t\t\tfor (cell=0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\toccupier = (*this)[cell].Cell_Occupier();\n\t\t\t\t\t\tif (occupier == NULL) {\n\t\t\t\t\t\t\tcolor = GroundColor[(*this)[cell].Land_Type()];\n\t\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(cell) + 1, D_BORD_Y1 + Cell_Y(cell) + 1, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the actual map location\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Draw_Rect(map_x1, map_y1, map_x2, map_y2, WHITE);\n\t\t\t\t\tswitch (grabbed) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y1, map_x1 + 5, map_y1, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y1, map_x1, map_y1 + 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y1, map_x2 - 5, map_y1, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y1, map_x2, map_y1 + 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y2, map_x2 - 5, map_y2, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x2, map_y2, map_x2, map_y2 - 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y2, map_x1 + 5, map_y2, BLUE);\n\t\t\t\t\t\t\tLogicPage->Draw_Line(map_x1, map_y2, map_x1, map_y2 - 5, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\tLogicPage->Draw_Rect(map_x1, map_y1, map_x2, map_y2, BLUE);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Unit map symbols (Use the radar map color according to\n\t\t\t\t\t**\tthat specified in the house type class object.\n\t\t\t\t\t**\tDKGREEN = terrain object\n\t\t\t\t\t*/\n\t\t\t\t\tfor (cell=0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\t\t\toccupier = (*this)[cell].Cell_Occupier();\n\t\t\t\t\t\tif (occupier) {\n\t\t\t\t\t\t\tcolor = DKGREEN;\n\t\t\t\t\t\t\tif (occupier && occupier->Owner() != HOUSE_NONE) {\n\t\t\t\t\t\t\t\tcolor = ColorRemaps[HouseClass::As_Pointer(occupier->Owner())->RemapColor].Color;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(cell) + 1, D_BORD_Y1 + Cell_Y(cell) + 1, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw Home location\n\t\t\t\t\t*/\n\t\t\t\t\tLogicPage->Put_Pixel(D_BORD_X1 + Cell_X(Scen.Waypoint[WAYPT_HOME]) + 1, D_BORD_Y1 + Cell_Y(Scen.Waypoint[WAYPT_HOME]) + 1, WHITE);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tErase old coordinates\n\t\t\t\t\t*/\n//\t\t\t\t\tLogicPage->Fill_Rect( D_DIALOG_X + 7,\n//\t\t\t\t\t\tD_DIALOG_Y + D_DIALOG_H - D_OK_H - 22,\n//\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W - 7,\n//\t\t\t\t\t\tD_DIALOG_Y + D_DIALOG_H - D_OK_H - 22 + 10, BLACK);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDraw the coordinates\n\t\t\t\t\t*/\n\t\t\t\t\ttxt_x = D_DIALOG_X + D_DIALOG_W / 8;\n\t\t\t\t\ttxt_y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - 32;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_x1 - D_BORD_X1 - 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_y1 - D_BORD_Y1 - 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_x2 - map_x1 + 1);\n\n\t\t\t\t\ttxt_x += (D_DIALOG_W - 20) / 4;\n\t\t\t\t\tFancy_Text_Print(\"%5d\", txt_x, txt_y, GadgetClass::Get_Color_Scheme(), BLACK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, map_y2 - map_y1 + 1);\n\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tNormal button processing: This is done when the mouse button is NOT\n\t\t**\tbeing held down ('grabbed' is 0).\n\t\t*/\n\t\tif (grabbed == 0) {\n\t\t\tswitch (input) {\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\t\tcancel = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tcancel = true;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase KN_LMOUSE:\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab top left\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x1);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y1);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 1;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab top right\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x2);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y1);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 2;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab bottom right\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x2);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y2);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 3;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab bottom left\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 =  abs(Keyboard->MouseQX - map_x1);\n\t\t\t\t\tdelta2 =  abs(Keyboard->MouseQY - map_y2);\n\t\t\t\t\tif (delta1 < 3 && delta2 < 3) {\n\t\t\t\t\t\tgrabbed = 4;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGrab the whole map\n\t\t\t\t\t*/\n\t\t\t\t\tdelta1 = abs(Keyboard->MouseQX - ((map_x1 + map_x2) / 2));\n\t\t\t\t\tdelta2 = abs(Keyboard->MouseQY - ((map_y1 + map_y2) / 2));\n\t\t\t\t\tif (delta1 < (map_x2 - map_x1) / 4 &&\n\t\t\t\t\t\tdelta2 < (map_y2 - map_y1) / 4) {\n\t\t\t\t\t\tgrabbed = 5;\n\t\t\t\t\t\tmx = Keyboard->MouseQX;\n\t\t\t\t\t\tmy = Keyboard->MouseQY;\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tMouse motion processing: This is done while the left mouse button IS\n\t\t\t**\tbeing held down.\n\t\t\t**\t- First, check for the button release; if detected, un-grab\n\t\t\t**\t- Then, handle mouse motion. WWLIB doesn't pass through a KN_MOUSE_MOVE\n\t\t\t**\t  value while the button is being held down, so this case must be\n\t\t\t**\t  trapped as a default.\n\t\t\t*/\n\t\t\tswitch (input) {\n\t\t\t\tcase ((int)KN_LMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\t\tgrabbed = 0;\n\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tdelta1 = Get_Mouse_X() - mx;\n\t\t\t\t\tdelta2 = Get_Mouse_Y() - my;\n\t\t\t\t\tif (delta1==0 && delta2==0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove top left\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==1) {\n\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\tif (map_x1 > map_x2 - 2) {\n\t\t\t\t\t\t\tmap_x1 = map_x2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x1 < D_BORD_X1 + 2) {\n\t\t\t\t\t\t\t\tmap_x1 = D_BORD_X1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\tif (map_y1 > map_y2 - 2) {\n\t\t\t\t\t\t\tmap_y1 = map_y2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y1 < D_BORD_Y1 + 2) {\n\t\t\t\t\t\t\t\tmap_y1 = D_BORD_Y1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove top right\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==2) {\n\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\tif (map_x2 < map_x1 + 2) {\n\t\t\t\t\t\t\tmap_x2 = map_x1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x2 > D_BORD_X2 - 2) {\n\t\t\t\t\t\t\t\tmap_x2 = D_BORD_X2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\tif (map_y1 > map_y2 - 2) {\n\t\t\t\t\t\t\tmap_y1 = map_y2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y1 < D_BORD_Y1 + 2) {\n\t\t\t\t\t\t\t\tmap_y1 = D_BORD_Y1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove bottom right\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==3) {\n\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\tif (map_x2 < map_x1 + 2) {\n\t\t\t\t\t\t\tmap_x2 = map_x1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x2 > D_BORD_X2 - 2) {\n\t\t\t\t\t\t\t\tmap_x2 = D_BORD_X2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\tif (map_y2 < map_y1 + 2) {\n\t\t\t\t\t\t\tmap_y2 = map_y1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y2 > D_BORD_Y2 - 2) {\n\t\t\t\t\t\t\t\tmap_y2 = D_BORD_Y2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove bottom left\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==4) {\n\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\tif (map_x1 > map_x2 - 2) {\n\t\t\t\t\t\t\tmap_x1 = map_x2 - 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_x1 < D_BORD_X1 + 2) {\n\t\t\t\t\t\t\t\tmap_x1 = D_BORD_X1 + 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\tif (map_y2 < map_y1 + 2) {\n\t\t\t\t\t\t\tmap_y2 = map_y1 + 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (map_y2 > D_BORD_Y2 - 2) {\n\t\t\t\t\t\t\t\tmap_y2 = D_BORD_Y2 - 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tMove whole map\n\t\t\t\t\t*/\n\t\t\t\t\tif (grabbed==5) {\n\t\t\t\t\t\tif (map_x1 + delta1 > D_BORD_X1 + 1 && map_x2 + delta1 < D_BORD_X2 - 1) {\n\t\t\t\t\t\t\tmap_x1 += delta1;\n\t\t\t\t\t\t\tmap_x2 += delta1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (map_y1 + delta2 > D_BORD_Y1 + 1 && map_y2 + delta2 < D_BORD_Y2 - 1) {\n\t\t\t\t\t\t\tmap_y1 += delta2;\n\t\t\t\t\t\t\tmap_y2 += delta2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisplay = REDRAW_MAP;\n\t\t\t\t\t\tmx = Get_Mouse_X();\n\t\t\t\t\t\tmy = Get_Mouse_Y();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tSave selections\n\t*/\n\tMapCellX = map_x1 - D_BORD_X1 - 1;\n\tMapCellY = map_y1 - D_BORD_Y1 - 1;\n\tMapCellWidth = map_x2 - map_x1 + 1;\n\tMapCellHeight = map_y2 - map_y1 + 1;\n\n\t/*\n\t**\tClip Home Cell to new map size\n\t*/\n\tif (Cell_X(Scen.Waypoint[WAYPT_HOME]) < MapCellX) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX, Cell_Y(Scen.Waypoint[WAYPT_HOME]));\n\t}\n\n\tif (Cell_X(Scen.Waypoint[WAYPT_HOME]) > MapCellX + MapCellWidth - 1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + MapCellWidth - 1, Cell_Y(Scen.Waypoint[WAYPT_HOME]));\n\t}\n\n\tif (Cell_Y(Scen.Waypoint[WAYPT_HOME]) < MapCellY) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(Cell_X(Scen.Waypoint[WAYPT_HOME]), MapCellY);\n\t}\n\n\tif (Cell_Y(Scen.Waypoint[WAYPT_HOME]) > MapCellY + MapCellHeight - 1) {\n\t\tScen.Waypoint[WAYPT_HOME] = XY_Cell(Cell_X(Scen.Waypoint[WAYPT_HOME]), MapCellY + MapCellHeight - 1);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Scenario_Dialog -- scenario global parameters dialog      *\n *                                                                         *\n *    Edits the house specific and general scenario options.               *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/14/1994 BR : Created.                                              *\n *   02/13/1996 JLB : Revamped to new system.                              *\n *=========================================================================*/\nint MapEditClass::Scenario_Dialog(void)\n{\n\tTheaterType orig_theater = Scen.Theater;\t\t// original theater\n\tHousesType house = PlayerPtr->Class->House;\n\tHousesType newhouse = house;\n\tHouseStaticClass hdata[HOUSE_COUNT];\n\n\t/*\n\t**\tFill in the house data for each house that exists.\n\t*/\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(h);\n\t\tif (hptr) {\n\t\t\thdata[h] = hptr->Control;\n\t\t}\n\t}\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 320 * RESFACTOR,\n\t\tD_DIALOG_H = 200 * RESFACTOR,\n\t\tD_DIALOG_X = ((320 * RESFACTOR - D_DIALOG_W) / 2),\n\t\tD_DIALOG_Y = ((200 * RESFACTOR - D_DIALOG_H) / 2),\n\n\t\tD_OK_W = 45,\n\t\tD_OK_H = 9,\n\t\tD_OK_X = D_DIALOG_X + 15 * RESFACTOR,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 15 * RESFACTOR,\n\n\t\tD_CANCEL_W = 45,\n\t\tD_CANCEL_H = 9,\n\t\tD_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (D_CANCEL_W+15*RESFACTOR),\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - 15*RESFACTOR\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tLIST_THEATER=100,\n\t\tBUTTON_DESCRIPTION,\n\t\tBUTTON_ALLIES,\n\t\tBUTTON_CONTROL,\n\t\tBUTTON_SMARTIES,\n\t\tBUTTON_BASE,\n\t\tBUTTON_NOSPYPLANE,\n\t\tBUTTON_INHERIT,\n\t\tBUTTON_TIMER,\n\t\tBUTTON_THEME,\n\t\tBUTTON_RECORD,\n\t\tBUTTON_EVAC,\n\t\tBUTTON_MONEYTIB,\n\t\tBUTTON_TECH,\n\t\tBUTTON_TRUCKCRATE,\n\t\tBUTTON_ENDOFGAME,\n\t\tBUTTON_SKIPSCORE,\n\t\tBUTTON_ONETIME,\n\t\tBUTTON_NOMAPSEL,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_SOURCE,\n\t\tBUTTON_MAXUNIT,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_BRIEFING,\n\t\tBUTTON_ACTION,\n\t\tBUTTON_WIN,\n\t\tBUTTON_LOSE,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\t/*\n\t**\tTheater choice drop down list.\n\t*/\n\tchar theatertext[45] = \"\";\n\tDropListClass theaterbtn(LIST_THEATER, theatertext, sizeof(theatertext)-1,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+30, 65, 8*5,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (TheaterType t = THEATER_FIRST; t < THEATER_COUNT; t++) {\n\t\ttheaterbtn.Add_Item(Theaters[t].Name);\n\t}\n\ttheaterbtn.Set_Selected_Index(orig_theater);\n\n\tchar description[DESCRIP_MAX] = \"\";\n\tstrcpy(description, Scen.Description);\n\tEditClass desc(BUTTON_DESCRIPTION, description, sizeof(description), TPF_EFNT|TPF_NOSHADOW, theaterbtn.X+theaterbtn.Width+15, theaterbtn.Y, 160);\n\n\t/*\n\t**\tButton that tells if this scenario should inherit buildings from the previous.\n\t*/\n\tCheckBoxClass inherit(BUTTON_INHERIT, theaterbtn.X+theaterbtn.Width+15+250, theaterbtn.Y);\n\tif (Scen.IsToInherit) {\n\t\tinherit.Turn_On();\n\t} else {\n\t\tinherit.Turn_Off();\n\t}\n\n\t/*\n\t**\tRecords scenario disposition into holding slot.\n\t*/\n\tCheckBoxClass record(BUTTON_RECORD, inherit.X, inherit.Y+8);\n\tif (Scen.IsToCarryOver) {\n\t\trecord.Turn_On();\n\t} else {\n\t\trecord.Turn_Off();\n\t}\n\n\t/*\n\t**\tShould Tanya/civilian be automatically evacuated?\n\t*/\n\tCheckBoxClass tanya(BUTTON_EVAC, record.X, record.Y+8);\n\tif (Scen.IsTanyaEvac) {\n\t\ttanya.Turn_On();\n\t} else {\n\t\ttanya.Turn_Off();\n\t}\n\n\t/*\n\t**\tEnd of game with with scenario?\n\t*/\n\tCheckBoxClass endofgame(BUTTON_ENDOFGAME, tanya.X, tanya.Y+8);\n\tif (Scen.IsEndOfGame) {\n\t\tendofgame.Turn_On();\n\t} else {\n\t\tendofgame.Turn_Off();\n\t}\n\n\t/*\n\t**\tTimer inherit logic.\n\t*/\n\tCheckBoxClass timercarry(BUTTON_TIMER, endofgame.X, endofgame.Y+8);\n\tif (Scen.IsInheritTimer) {\n\t\ttimercarry.Turn_On();\n\t} else {\n\t\ttimercarry.Turn_Off();\n\t}\n\n\t/*\n\t**\tDisable spy plane option?\n\t*/\n\tCheckBoxClass nospyplane(BUTTON_NOSPYPLANE, timercarry.X, timercarry.Y+8);\n\tif (Scen.IsNoSpyPlane) {\n\t\tnospyplane.Turn_On();\n\t} else {\n\t\tnospyplane.Turn_Off();\n\t}\n\n\t/*\n\t**\tSkip the score screen?\n\t*/\n\tCheckBoxClass skipscore(BUTTON_SKIPSCORE, nospyplane.X, nospyplane.Y+8);\n\tif (Scen.IsSkipScore) {\n\t\tskipscore.Turn_On();\n\t} else {\n\t\tskipscore.Turn_Off();\n\t}\n\n\t/*\n\t**\tSkip the map selection screen for next mission. Presume goes to\n\t**\tvariation \"B\"?\n\t*/\n\tCheckBoxClass nomapsel(BUTTON_NOMAPSEL, skipscore.X, skipscore.Y+8);\n\tif (Scen.IsNoMapSel) {\n\t\tnomapsel.Turn_On();\n\t} else {\n\t\tnomapsel.Turn_Off();\n\t}\n\n\t/*\n\t**\tReturn to main menu after mission completes?\n\t*/\n\tCheckBoxClass onetime(BUTTON_ONETIME, nomapsel.X, nomapsel.Y+8);\n\tif (Scen.IsOneTimeOnly) {\n\t\tonetime.Turn_On();\n\t} else {\n\t\tonetime.Turn_Off();\n\t}\n\n\t/*\n\t**\tTrucks carry a wood crate?\n\t*/\n\tCheckBoxClass truckcrate(BUTTON_TRUCKCRATE, onetime.X, onetime.Y+8);\n\tif (Scen.IsTruckCrate) {\n\t\ttruckcrate.Turn_On();\n\t} else {\n\t\ttruckcrate.Turn_Off();\n\t}\n\n\t/*\n\t**\tTransfer credits into tiberium storage at scenario start?\n\t*/\n\tCheckBoxClass moneytib(BUTTON_MONEYTIB, truckcrate.X, truckcrate.Y+8);\n\tif (Scen.IsMoneyTiberium) {\n\t\tmoneytib.Turn_On();\n\t} else {\n\t\tmoneytib.Turn_Off();\n\t}\n\n\t/*\n\t**\tIntro movie name.\n\t*/\n\tchar introtext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass intro(BUTTON_INTRO, introtext, sizeof(introtext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\ttheaterbtn.X, theaterbtn.Y+theaterbtn.Height+24, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tintro.Add_Item(\"<none>\");\n\tfor (VQType v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tintro.Add_Item(VQName[v]);\n\t}\n\tintro.Set_Selected_Index((int)Scen.IntroMovie + 1);\n\n\t/*\n\t**\tBriefing movie name.\n\t*/\n\tchar brieftext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass briefing(BUTTON_BRIEFING, brieftext, sizeof(brieftext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tintro.X+intro.Width+10, intro.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tbriefing.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tbriefing.Add_Item(VQName[v]);\n\t}\n\tbriefing.Set_Selected_Index((int)Scen.BriefMovie + 1);\n\n\tchar actiontext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass action(BUTTON_ACTION, actiontext, sizeof(actiontext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tbriefing.X+briefing.Width+10, briefing.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\taction.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\taction.Add_Item(VQName[v]);\n\t}\n\taction.Set_Selected_Index((int)Scen.ActionMovie + 1);\n\n\tchar wintext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass win(BUTTON_WIN, wintext, sizeof(wintext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\taction.X+action.Width+10, action.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\twin.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\twin.Add_Item(VQName[v]);\n\t}\n\twin.Set_Selected_Index((int)Scen.WinMovie + 1);\n\n\tchar losetext[_MAX_FNAME+_MAX_EXT];\n\tDropListClass lose(BUTTON_LOSE, losetext, sizeof(losetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\twin.X+win.Width+10, win.Y, 50, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tlose.Add_Item(\"<none>\");\n\tfor (v = VQ_FIRST; v < VQ_COUNT; v++) {\n\t\tlose.Add_Item(VQName[v]);\n\t}\n\tlose.Set_Selected_Index((int)Scen.LoseMovie + 1);\n\n\t/*\n\t**\tHouse choice list.\n\t*/\n\tListClass housebtn(BUTTON_HOUSE,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+105, 55, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t}\n\thousebtn.Set_Selected_Index(PlayerPtr->Class->House);\n\n\t/*\n\t**\tBase house choice drop down list.\n\t*/\n\tchar basetext[35];\n\tDropListClass basebtn(BUTTON_BASE, basetext, sizeof(basetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tD_DIALOG_X+15*RESFACTOR, D_DIALOG_Y+80, 65, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tbasebtn.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t}\n\tif (Base.House != HOUSE_NONE) {\n\t\tbasebtn.Set_Selected_Index(Base.House);\n\t}\n\n\t/*\n\t**\tOpening scenario theme.\n\t*/\n\tchar themetext[65];\n\tDropListClass themebtn(BUTTON_THEME, themetext, sizeof(themetext),\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tbasebtn.X+basebtn.Width+15*RESFACTOR, basebtn.Y, 85, 7*10,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tthemebtn.Add_Item(\"<none>\");\n\tfor (ThemeType th = THEME_FIRST; th < THEME_COUNT; th++) {\n\t\tthemebtn.Add_Item(Theme.Full_Name(th));\n\t}\n\tif (Scen.TransitTheme != THEME_NONE) {\n\t\tthemebtn.Set_Selected_Index(Scen.TransitTheme+1);\n\t} else {\n\t\tthemebtn.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tBuild level (technology).\n\t*/\n\tSliderClass techlevel(BUTTON_TECH, housebtn.X+housebtn.Width+15, housebtn.Y, 100, 8);\n\ttechlevel.Set_Maximum(16);\n\n\tchar statictechbuff[15];\n\tStaticButtonClass techstatic(0, \"999\", TPF_EFNT|TPF_NOSHADOW, techlevel.X+techlevel.Width-20, techlevel.Y-7);\n\n\t/*\n\t**\tStarting credits.\n\t*/\n\tSliderClass creditbtn(BUTTON_CREDITS, housebtn.X+housebtn.Width+15, techlevel.Y+20, 100, 8);\n\tcreditbtn.Set_Maximum(201);\n\n\tchar staticcreditbuff[15];\n\tStaticButtonClass creditstatic(0, \"999999999\", TPF_EFNT|TPF_NOSHADOW, creditbtn.X+creditbtn.Width-50, creditbtn.Y-7);\n\n\t/*\n\t**\tMaximum unit/infantry slider.\n\t*/\n\tSliderClass maxunit(BUTTON_MAXUNIT, housebtn.X+housebtn.Width+15, creditbtn.Y+20, 100, 8);\n\tmaxunit.Set_Maximum(501);\n\n\tchar staticmaxunitbuff[15];\n\tStaticButtonClass maxunitstatic(0, \"999999\", TPF_EFNT|TPF_NOSHADOW, maxunit.X+maxunit.Width-30, maxunit.Y-7);\n\n\t/*\n\t**\tSource of ground delivery reinforcements.\n\t*/\n\tchar sourcetext[25] = \"\";\n\tListClass sourcebtn(BUTTON_SOURCE,\n\t\thousebtn.X+housebtn.Width+15, maxunit.Y+20, 100, 7*4,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (SourceType source = SOURCE_FIRST; source <= SOURCE_WEST; source++) {\n\t\tsourcebtn.Add_Item(SourceName[source]);\n\t}\n\n\t/*\n\t**\tSmartness lider.\n\t*/\n\tSliderClass smarties(BUTTON_SMARTIES, sourcebtn.X, sourcebtn.Y+sourcebtn.Height+15, 35, 8);\n\tsmarties.Set_Maximum(Rule.MaxIQ+1);\n\n\tchar staticsmartiesbuff[15];\n\tStaticButtonClass smartiesstatic(0, \"9999\", TPF_EFNT|TPF_NOSHADOW, smarties.X+smarties.Width-20, smarties.Y-7);\n\n\t/*\n\t**\tList box of who is allied with whom.\n\t*/\n\tCheckListClass allies(BUTTON_ALLIES,\n\t\ttechlevel.X+techlevel.Width+5, housebtn.Y, 65, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tallies.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t\tif (hdata[house].Allies & (1L << h)) {\n\t\t\tallies.Check_Item(h, true);\n\t\t}\n\t}\n\tallies.Set_Selected_Index(0);\n\n\t/*\n\t**\tList box of who the player can control.\n\t*/\n\tCheckListClass control(BUTTON_CONTROL,\n\t\tallies.X+allies.Width+10, housebtn.Y, 65, 7*10,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tcontrol.Add_Item(HouseTypeClass::As_Reference(h).IniName);\n\t\tif (HouseClass::As_Pointer(h)->IsPlayerControl) {\n\t\t\tcontrol.Check_Item(h, true);\n\t\t}\n\t}\n\tcontrol.Set_Selected_Index(0);\n\n\t/*\n\t**\tCreate the ubiquitous \"ok\" and \"cancel\" buttons.\n\t*/\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\ttheaterbtn.Add_Tail(*commands);\n\tthemebtn.Add_Tail(*commands);\n\thousebtn.Add_Tail(*commands);\n\ttechlevel.Add_Tail(*commands);\n\ttechstatic.Add_Tail(*commands);\n\tsourcebtn.Add_Tail(*commands);\n\tcreditbtn.Add_Tail(*commands);\n\tcreditstatic.Add_Tail(*commands);\n\tmaxunitstatic.Add_Tail(*commands);\n\tmoneytib.Add_Tail(*commands);\n\tsmartiesstatic.Add_Tail(*commands);\n\tallies.Add_Tail(*commands);\n\tcontrol.Add_Tail(*commands);\n\tmaxunit.Add_Tail(*commands);\n\tnospyplane.Add_Tail(*commands);\n\tskipscore.Add_Tail(*commands);\n\tnomapsel.Add_Tail(*commands);\n\tonetime.Add_Tail(*commands);\n\tinherit.Add_Tail(*commands);\n\ttimercarry.Add_Tail(*commands);\n\ttanya.Add_Tail(*commands);\n\trecord.Add_Tail(*commands);\n\ttruckcrate.Add_Tail(*commands);\n\tendofgame.Add_Tail(*commands);\n\tbriefing.Add_Tail(*commands);\n\tintro.Add_Tail(*commands);\n\taction.Add_Tail(*commands);\n\twin.Add_Tail(*commands);\n\tlose.Add_Tail(*commands);\n\tbasebtn.Add_Tail(*commands);\n\tsmarties.Add_Tail(*commands);\n\tdesc.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool housechange = true;\n\tbool display = true;\n\tbool process = true;\n\tbool cancel = false;\t\t// true = user cancels\n\tbool dotext = true;\t\t// display the text.\n\tbool fetch = false;\t\t// Fetch data from dialog into tracking structure.\n\t//Set_Logic_Page(SeenBuff);\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tIf the house changes, then all the gadgets that reflect the settings of the\n\t\t**\thouse should change as well.\n\t\t*/\n\t\tif (housechange) {\n\t\t\tHouseStaticClass * hstatic = &hdata[newhouse];\n\t\t\tcreditbtn.Set_Value(hstatic->InitialCredits/100);\n\t\t\ttechlevel.Set_Value(hstatic->TechLevel);\n\t\t\tsourcebtn.Set_Selected_Index(hstatic->Edge);\n\t\t\tmaxunit.Set_Value(hstatic->MaxUnit + hstatic->MaxInfantry);\n\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\tallies.Check_Item(h, hstatic->Allies & (1L << h));\n\t\t\t}\n\t\t\tsmarties.Set_Value(hstatic->IQ);\n\n\t\t\thouse = newhouse;\n\t\t\thousechange = false;\n\t\t\tdisplay = true;\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background\n\t\t\t*/\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_SCENARIO_OPTIONS, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDisplay the text that doesn't need drawing except when the entire dialog\n\t\t\t**\tneeds to be redrawn.\n\t\t\t*/\n\t\t\tFancy_Text_Print(\"Tech Level =\", techlevel.X, techlevel.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Credits =\", creditbtn.X, creditbtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Unit Max =\", maxunit.X, maxunit.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"IQ =\", smarties.X, smarties.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Prebuild Base:\", basebtn.X, basebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Theater:\", theaterbtn.X, theaterbtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Scenario Name:\", desc.X, desc.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Country:\", housebtn.X, housebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Home Edge:\", sourcebtn.X, sourcebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Allies:\", allies.X, allies.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Plyr Control:\", control.X, control.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Theme:\", themebtn.X, themebtn.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Intro:\", intro.X, intro.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Briefing:\", briefing.X, briefing.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Action:\", action.X, action.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Win:\", win.X, win.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Lose:\", lose.X, lose.Y-7, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Store scenario?\", record.X+10, record.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Inherit stored scenario?\", inherit.X+10, inherit.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Auto evac. Tanya (civilian)?\", tanya.X+10, tanya.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Last mission of game?\", endofgame.X+10, endofgame.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Inherit mission timer from last scenario?\", timercarry.X+10, timercarry.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Disable spy plane?\", nospyplane.X+10, nospyplane.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Skip the score screen?\", skipscore.X+10, skipscore.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"No map selection (force var 'B')?\", nomapsel.X+10, nomapsel.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Return to main menu after scenario finishes?\", onetime.X+10, onetime.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Truck carries wood crate?\", truckcrate.X+10, truckcrate.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(\"Initial money is transferred to silos?\", moneytib.X+10, moneytib.Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_EFNT|TPF_NOSHADOW);\n\n\t\t\ttheaterbtn.Collapse();\n\t\t\tthemebtn.Collapse();\n\t\t\tintro.Collapse();\n\t\t\tbriefing.Collapse();\n\t\t\taction.Collapse();\n\t\t\twin.Collapse();\n\t\t\tlose.Collapse();\n\t\t\tbasebtn.Collapse();\n\t\t\tcommands->Draw_All(true);\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t\tdotext = true;\n\t\t}\n\n\t\t/*\n\t\t**\tDisplay the text of the buttons that could change their text as a\n\t\t**\tresult of slider interaction.\n\t\t*/\n\t\tif (dotext) {\n\t\t\tdotext = false;\n\t\t\tHide_Mouse();\n\n\t\t\tsprintf(statictechbuff, \"%2d\", techlevel.Get_Value());\n\t\t\ttechstatic.Set_Text(statictechbuff);\n\t\t\ttechstatic.Draw_Me();\n\n\t\t\tsprintf(staticcreditbuff, \"$%-7d\", creditbtn.Get_Value() * 100);\n\t\t\tcreditstatic.Set_Text(staticcreditbuff);\n\t\t\tcreditstatic.Draw_Me();\n\n\t\t\tsprintf(staticmaxunitbuff, \"%4d\", maxunit.Get_Value());\n\t\t\tmaxunitstatic.Set_Text(staticmaxunitbuff);\n\t\t\tmaxunitstatic.Draw_Me();\n\n\t\t\tsprintf(staticsmartiesbuff, \"%2d\", smarties.Get_Value());\n\t\t\tsmartiesstatic.Set_Text(staticsmartiesbuff);\n\t\t\tsmartiesstatic.Draw_Me();\n\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase BUTTON_ALLIES|KN_BUTTON:\n\t\t\t\tallies.Check_Item(house, true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_CONTROL|KN_BUTTON:\n\t\t\t\tcontrol.Check_Item(house, true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_THEME|KN_BUTTON:\n\t\t\tcase BUTTON_INTRO|KN_BUTTON:\n\t\t\tcase BUTTON_BRIEFING|KN_BUTTON:\n\t\t\tcase BUTTON_ACTION|KN_BUTTON:\n\t\t\tcase BUTTON_WIN|KN_BUTTON:\n\t\t\tcase BUTTON_LOSE|KN_BUTTON:\n\t\t\tcase BUTTON_BASE|KN_BUTTON:\n\t\t\tcase LIST_THEATER|KN_BUTTON:\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\tintro.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_SMARTIES|KN_BUTTON:\n\t\t\tcase BUTTON_MAXUNIT|KN_BUTTON:\n\t\t\tcase BUTTON_CREDITS|KN_BUTTON:\n\t\t\tcase BUTTON_TECH|KN_BUTTON:\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tdotext = true;\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_HOUSE|KN_BUTTON:\n\t\t\t\tnewhouse = HousesType(housebtn.Current_Index());\n\t\t\t\thousechange = true;\n\t\t\t\tbriefing.Collapse();\n\t\t\t\taction.Collapse();\n\t\t\t\tthemebtn.Collapse();\n\t\t\t\twin.Collapse();\n\t\t\t\tintro.Collapse();\n\t\t\t\tlose.Collapse();\n\t\t\t\tbasebtn.Collapse();\n\t\t\t\ttheaterbtn.Collapse();\n\t\t\t\tfetch = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tfetch = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\n\t\t/*\n\t\t**\tIf the house changes, then all the gadgets that reflect the settings of the\n\t\t**\thouse should change as well.\n\t\t*/\n\t\tif (fetch) {\n\t\t\tfetch = false;\n\t\t\tHouseStaticClass * hstatic = &hdata[house];\n\n\t\t\tBase.House = HousesType(basebtn.Current_Index());\n\t\t\thstatic->InitialCredits = creditbtn.Get_Value() * 100;\n\t\t\thstatic->Edge = SourceType(sourcebtn.Current_Index());\n\t\t\thstatic->TechLevel = techlevel.Get_Value();\n\t\t\thstatic->MaxUnit = maxunit.Get_Value()/2;\n\t\t\thstatic->MaxInfantry = maxunit.Get_Value()/2;\n\t\t\thstatic->IQ = smarties.Get_Value();\n\t\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\t\tif (allies.Is_Checked(h)) {\n\t\t\t\t\thstatic->Allies |= (1L << h);\n\t\t\t\t} else {\n\t\t\t\t\thstatic->Allies &= ~(1L << h);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the map\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\t/*\n\t**\tIf cancel, just return\n\t*/\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tCopy the dialog data back into the appropriate game data locations.\n\t*/\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(h);\n\t\tif (hptr != NULL) {\n\t\t\thptr->Control = hdata[h];\n\t\t\thptr->Allies = hdata[h].Allies;\n\n\t\t\tif (control.Is_Checked(h)) {\n\t\t\t\thptr->IsPlayerControl = true;\n\t\t\t} else {\n\t\t\t\thptr->IsPlayerControl = false;\n\t\t\t}\n\t\t}\n\t}\n\tPlayerPtr->IsPlayerControl = true;\n\tstrncpy(Scen.Description, desc.Get_Text(), sizeof(Scen.Description));\n\tScen.Description[sizeof(Scen.Description)-1] = '\\0';\n\tScen.IntroMovie = VQType(intro.Current_Index()-1);\n\tScen.BriefMovie = VQType(briefing.Current_Index()-1);\n\tScen.ActionMovie = VQType(action.Current_Index()-1);\n\tScen.WinMovie = VQType(win.Current_Index()-1);\n\tScen.LoseMovie = VQType(lose.Current_Index()-1);\n\tScen.IsToInherit = inherit.IsOn;\n\tScen.IsToCarryOver = record.IsOn;\n\tScen.IsTanyaEvac = tanya.IsOn;\n\tScen.IsEndOfGame = endofgame.IsOn;\n\tScen.IsInheritTimer = timercarry.IsOn;\n\tScen.IsNoSpyPlane = nospyplane.IsOn;\n\tScen.IsSkipScore = skipscore.IsOn;\n\tScen.IsNoMapSel = nomapsel.IsOn;\n\tScen.IsOneTimeOnly = onetime.IsOn;\n\tScen.IsTruckCrate = truckcrate.IsOn;\n\tScen.IsMoneyTiberium = moneytib.IsOn;\n\tScen.TransitTheme = ThemeType(themebtn.Current_Index()-1);\n\n\t/*\n\t**\tChange the theater:\n\t**\t- 1st set the Theater global\n\t**\t- scan all cells to check their TType for compatibility with the new\n\t**\t  theater; if not compatible, set TType to TEMPLATE_NONE & TIcon to 0\n\t**\t- Then, re-initialize the TypeClasses for the new Theater\n\t*/\n\tTheaterType theater = TheaterType(theaterbtn.Current_Index());\n\tif (theater != orig_theater) {\n\n\t\tunsigned char theater_mask;\t// template/terrain mask\n\t\tTerrainClass * terrain;\t// cell's terrain pointer\n\n\t\t/*\n\t\t**\tLoop through all cells\n\t\t*/\n\t\tfor (CELL i = 0; i < MAP_CELL_TOTAL; i++) {\n\n\t\t\t/*\n\t\t\t**\tIf this cell has a template icon & that template isn't compatible\n\t\t\t**\twith this theater, set the icon to NONE\n\t\t\t*/\n\t\t\tif ((*this)[i].TType != TEMPLATE_NONE) {\n\t\t\t\ttheater_mask = TemplateTypeClass::As_Reference((*this)[i].TType).Theater;\n\t\t\t\tif ( (theater_mask & (1 << theater))==0) {\n\t\t\t\t\t(*this)[i].TType = TEMPLATE_NONE;\n\t\t\t\t\t(*this)[i].TIcon = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf this cell has terrain in it, and that terrain isn't compatible\n\t\t\t**\twith this theater, delete the terrain object.\n\t\t\t*/\n\t\t\tterrain = (*this)[i].Cell_Terrain();\n\t\t\tif (terrain != NULL) {\n\t\t\t\ttheater_mask = terrain->Class->Theater;\n\t\t\t\tif ( (theater_mask & (1<<theater))==0) {\n\t\t\t\t\tdelete terrain;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Remove any old theater specific uncompressed shapes\n\t\t*/\n#ifdef WIN32\n\t\tReset_Theater_Shapes();\n#endif\t//WIN32\n\t\t/*\n\t\t** Force shapes to reload\n\t\t*/\n\t\tLastTheater = THEATER_NONE;\n\n\t\t/*\n\t\t**\tRe-init the object Type Classes for this theater\n\t\t*/\n\t\tInit_Theater(theater);\n\t\tTerrainTypeClass::Init(theater);\n\t\tTemplateTypeClass::Init(theater);\n\t\tOverlayTypeClass::Init(theater);\n\t\tUnitTypeClass::Init(theater);\n\t\tInfantryTypeClass::Init(theater);\n\t\tBuildingTypeClass::Init(theater);\n\t\tBulletTypeClass::Init(theater);\n\t\tAnimTypeClass::Init(theater);\n\t\tAircraftTypeClass::Init(theater);\n\t\tVesselTypeClass::Init(theater);\n\t\tSmudgeTypeClass::Init(theater);\n\n//\t\tLastTheater = theater;\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * Handle_Triggers -- processes the trigger dialogs                        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Handle_Triggers(void)\n{\n\tint rc;\n\n\t/*\n\t**\tTrigger dialog processing loop:\n\t**\t- Invoke the trigger selection dialog. If a trigger's selected, break\n\t**\t  & return\n\t**\t- If user wants to edit the current trigger, do so\n\t**\t- If user wants to create new trigger, new a TriggerClass & edit it\n\t**\t- If user wants to delete trigger, delete the current trigger\n\t**\t- Keep looping until 'OK'\n\t*/\n\twhile (1) {\n\n\t\t/*\n\t\t**\tSelect trigger\n\t\t*/\n\t\trc = Select_Trigger();\n\n\t\t/*\n\t\t**\t'OK'; break\n\t\t*/\n\t\tif (rc==0) break;\n\n\t\t/*\n\t\t**\t'Edit'\n\t\t*/\n\t\tif (rc==1 && CurTrigger) {\n\t\t\tif (CurTrigger->Edit()) {\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t\tHidPage.Clear();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tRender();\n\t\t}\n\n\t\t/*\n\t\t**\t'New'\n\t\t*/\n\t\tif (rc==2) {\n\n\t\t\t/*\n\t\t\t**\tCreate a new trigger\n\t\t\t*/\n\t\t\tCurTrigger = new TriggerTypeClass();\n\t\t\tif (CurTrigger) {\n\n\t\t\t\t/*\n\t\t\t\t**\tdelete it if user cancels\n\t\t\t\t*/\n\t\t\t\tif (!CurTrigger->Edit()) {\n\t\t\t\t\tdelete CurTrigger;\n\t\t\t\t\tCurTrigger = NULL;\n\t\t\t\t} else {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tUnable to create; issue warning\n\t\t\t\t*/\n\t\t\t\tWWMessageBox().Process(\"No more triggers available.\");\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\t'Delete'\n\t\t*/\n\t\tif (rc==3) {\n\t\t\tif (CurTrigger) {\n\t\t\t\tDetach_This_From_All(CurTrigger->As_Target(), true);\n\t\t\t\tdelete CurTrigger;\n\t\t\t\t//CurTrigger->Remove();\n\t\t\t\tCurTrigger = NULL;\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tLet the CurTrigger global exist if the trigger can be placed on the\n\t**\tground or on a game object.\n\t*/\n\tif (CurTrigger && !(CurTrigger->Attaches_To() & (ATTACH_OBJECT|ATTACH_CELL))) {\n\t\tCurTrigger = NULL;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Trigger -- lets user select a trigger              *\n *                                                                         *\n * CurTrigger can be NULL when this function is called.                    *\n *                                                                         *\n *    Ŀ           *\n *                           Triggers                                    *\n *        Ŀ               *\n *         Name     Event     Action    House   Team  \u0018               *\n *         Name     Event     Action    House   Team  Ĵ               *\n *         Name     Event     Action    House   Team                  *\n *         Name     Event     Action    House   Team                  *\n *                                                                    *\n *                                                                    *\n *                                                    Ĵ               *\n *                                                    \u0019               *\n *                       *\n *                                                                       *\n *          [Edit]        [New]        [Delete]      [OK]                *\n *                                                                       *\n *               *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, 1 = Edit, 2 = New, 3 = Delete                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *   05/07/1996 JLB : Streamlined and sort trigger list.                   *\n *=========================================================================*/\nint MapEditClass::Select_Trigger(void)\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\n\t\tD_DIALOG_H = 250,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\n\t\tD_TXT8_H = 11,\n\t\tD_MARGIN = 35,\n\n\t\tD_LIST_W = (D_DIALOG_W-(D_MARGIN*2))-10,\n\t\tD_LIST_H = D_DIALOG_H-70,\n\t\tD_LIST_X = D_DIALOG_X + (D_DIALOG_W-D_LIST_W)/2,\n\t\tD_LIST_Y = D_DIALOG_Y + 25,\n\n\t\tBUTTON_W = 45,\n\t\tBUTTON_H = 9,\n\n\t\tD_EDIT_W = BUTTON_W,\n\t\tD_EDIT_H = BUTTON_H,\n\t\tD_EDIT_X = D_DIALOG_X + D_DIALOG_W - (((D_EDIT_W+10)*4)+25),\n\t\tD_EDIT_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_EDIT_H,\n\n\t\tD_NEW_W = BUTTON_W,\n\t\tD_NEW_H = BUTTON_H,\n\t\tD_NEW_X = D_EDIT_X + D_EDIT_W + 10,\n\t\tD_NEW_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_NEW_H,\n\n\t\tD_DELETE_W = BUTTON_W,\n\t\tD_DELETE_H = BUTTON_H,\n\t\tD_DELETE_X = D_NEW_X + D_NEW_W + 10,\n\t\tD_DELETE_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_DELETE_H,\n\n\t\tD_OK_W = BUTTON_W,\n\t\tD_OK_H = BUTTON_H,\n\t\tD_OK_X = D_DELETE_X + D_DELETE_W + 10,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_OK_H,\n\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tTRIGGER_LIST=100,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_NEW,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_OK,\n\t};\n\n\t/*\n\t**\tDialog variables:\n\t*/\n\tbool edit_trig = false;\t\t\t\t\t\t// true = user wants to edit\n\tbool new_trig = false;\t\t\t\t\t\t// true = user wants to new\n\tbool del_trig = false;\t\t\t\t\t\t// true = user wants to new\n\tint i;\t\t\t\t\t\t\t\t\t\t\t// loop counter\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\tTListClass<CCPtr<TriggerTypeClass> > triggerlist(TRIGGER_LIST, D_LIST_X, D_LIST_Y, D_LIST_W, D_LIST_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tTextButtonClass editbtn(BUTTON_EDIT, \"Edit\", TPF_EBUTTON, D_EDIT_X, D_EDIT_Y, D_EDIT_W, D_EDIT_H);\n\tTextButtonClass newbtn(BUTTON_NEW, \"New\", TPF_EBUTTON, D_NEW_X, D_NEW_Y, D_NEW_W, D_NEW_H);\n\tTextButtonClass deletebtn(BUTTON_DELETE, \"Delete\", TPF_EBUTTON, D_DELETE_X, D_DELETE_Y, D_DELETE_W, D_DELETE_H);\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tFill in the list box\n\t*/\n\tfor (i = 0; i < TriggerTypes.Count(); i++) {\n\t\ttriggerlist.Add_Item(TriggerTypes.Ptr(i));\n\t}\n\n\tPNBubble_Sort(&triggerlist[0], triggerlist.Count());\n\n\tif (CurTrigger) {\n\t\ttriggerlist.Set_Selected_Index(CurTrigger);\n\t} else {\n\t\ttriggerlist.Set_Selected_Index(0);\n\t}\n\n\t/*\n\t**\tSet CurTrigger if it isn't\n\t*/\n\tif (TriggerTypes.Count()==0) {\n\t\tCurTrigger = NULL;\n\t} else {\n\t\tCurTrigger = triggerlist.Current_Item();\n//\t\tif (!CurTrigger) {\n//\t\t\tCurTrigger = &*triggerlist.Current_Item();\n//\t\t}\n\t}\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &triggerlist;\n\teditbtn.Add_Tail(*commands);\n\tnewbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if requested.\n\t\t*/\n\t\tif (display /*&& LogicPage->Lock()*/) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_TRIGGER_EDITOR, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n//\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (TRIGGER_LIST | KN_BUTTON):\n\t\t\t\tCurTrigger = &*triggerlist.Current_Item();\n//\t\t\t\tCurTrigger = (TriggerTypeClass *)&*triggerlist.Current_Item();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\t\t\t\tif (CurTrigger) {\t\t// only allow if there's one selected\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tedit_trig = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tnew_trig = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tdel_trig = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (edit_trig) return(1);\n\tif (new_trig) return(2);\n\tif (del_trig) return(3);\n\treturn(0);\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MAPEDIT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDIT.CPP 2     3/13/97 2:05p Steve_tall $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDIT.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : October 20, 1994                         *\n *                                                                         *\n *                  Last Update : February 2, 1995   [BR]                  *\n *                                                                         *\n *-------------------------------------------------------------------------*\n *   Map Editor overloaded routines & utility routines                     *\n *-------------------------------------------------------------------------*\n * Map Editor modules:                                                     *\n * (Yes, they're all one huge class.)                                      *\n *      mapedit.cpp:   overloaded routines, utility routines               *\n *      mapeddlg.cpp:   map editor dialogs, most of the main menu options  *\n *      mapedplc.cpp:   object-placing routines                            *\n *      mapedsel.cpp:   object-selection & manipulation routines           *\n *      mapedtm.cpp:   team-editing routines                               *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::AI -- The map editor's main logic                       *\n *   MapEditClass::Read_INI -- overloaded Read_INI function                *\n *   MapEditClass::AI_Menu -- menu of AI options                           *\n *   MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list  *\n *   MapEditClass::Clear_List -- clears the internal chooseable object list*\n *   MapEditClass::Cycle_House -- finds next valid house for object type   *\n *   MapEditClass::Draw_It -- overloaded Redraw routine                    *\n *   MapEditClass::Fatal -- exits with error message                       *\n *   MapEditClass::Main_Menu -- main menu processor for map editor         *\n *   MapEditClass::MapEditClass -- class constructor                       *\n *   MapEditClass::Mouse_Moved -- checks for mouse motion                  *\n *   MapEditClass::One_Time -- one-time initialization                     *\n *   MapEditClass::Verify_House -- sees if given house can own given obj   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n/*\n**\tArray of all missions supported by the map editor\n*/\nMissionType MapEditClass::MapEditMissions[] = {\n\tMISSION_GUARD,\n\tMISSION_STICKY,\n\tMISSION_HARMLESS,\n\tMISSION_HARVEST,\n\tMISSION_GUARD_AREA,\n\tMISSION_RETURN,\n\tMISSION_AMBUSH,\n\tMISSION_HUNT,\n\tMISSION_SLEEP,\n};\n#define NUM_EDIT_MISSIONS (sizeof(MapEditClass::MapEditMissions) / sizeof(MapEditClass::MapEditMissions[0]))\n\n\n/*\n**\tFor menu processing\n*/\nextern int UnknownKey;\t\t\t\t\t// in menus.cpp\n\nchar MapEditClass::HealthBuf[20];\n\n\n/***************************************************************************\n * MapEditClass::MapEditClass -- class constructor                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nMapEditClass::MapEditClass(void)\n{\n\t/*\n\t**\tInit data members.\n\t*/\n//\tScenVar = SCEN_VAR_A;\n\tObjCount = 0;\n\tLastChoice = 0;\n\tLastHouse = HOUSE_GOOD;\n\tGrabbedObject = 0;\n\tfor (int i=0; i < NUM_EDIT_CLASSES; i++) {\n\t\tNumType[i] = 0;\n\t\tTypeOffset[i] = 0;\n\t}\n\tScen.Waypoint[WAYPT_HOME] = 0;\n\tCurrentCell = 0;\n\tCurTeam = NULL;\n\tCurTrigger = NULL;\n\tChanged = 0;\n\tLMouseDown = 0;\n\tBaseBuilding = false;\n//\tBasePercent = 100;\n}\n\n\n/***************************************************************************\n * MapEditClass::One_Time -- one-time initialization                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/02/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::One_Time(void)\n{\n\tMouseClass::One_Time();\n\n\t/*\n\t**\tThe map: a single large \"button\"\n\t*/\n#ifdef WIN32\n\tMapArea = new ControlClass(MAP_AREA, 0, 8, 640-8, 400-8, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);\n#else\n\tMapArea = new ControlClass(MAP_AREA, 0, 8, 312, 192, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);\n#endif\n\n\t/*\n\t**\tHouse buttons\n\t*/\n\tHouseList = new ListClass(POPUP_HOUSELIST, POPUP_HOUSE_X, POPUP_HOUSE_Y, POPUP_HOUSE_W, POPUP_HOUSE_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseList->Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\n\t/*\n\t**\tThe mission list box\n\t*/\n\tMissionList = new ListClass(POPUP_MISSIONLIST,\n\t\tPOPUP_MISSION_X, POPUP_MISSION_Y, POPUP_MISSION_W, POPUP_MISSION_H,\n\t\tTPF_EFNT|TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tfor (int i = 0; i < NUM_EDIT_MISSIONS; i++) {\n\t\tMissionList->Add_Item(MissionClass::Mission_Name(MapEditMissions[i]));\n\t}\n\n\t/*\n\t**\tThe health bar\n\t*/\n\tHealthGauge = new TriColorGaugeClass(POPUP_HEALTHGAUGE,\n\t\tPOPUP_HEALTH_X, POPUP_HEALTH_Y, POPUP_HEALTH_W, POPUP_HEALTH_H);\n\tHealthGauge->Use_Thumb(true);\n\tHealthGauge->Set_Maximum(0x100);\n\tHealthGauge->Set_Red_Limit(0x3f - 1);\n\tHealthGauge->Set_Yellow_Limit(0x7f - 1);\n\n\t/*\n\t**\tThe health text label\n\t*/\n\tHealthBuf[0] = 0;\n\tHealthText = new TextLabelClass(HealthBuf,\n\t\tPOPUP_HEALTH_X + POPUP_HEALTH_W / 2,\n\t\tPOPUP_HEALTH_Y + POPUP_HEALTH_H + 1,\n\t\tGadgetClass::Get_Color_Scheme(),\n\t\tTPF_CENTER | TPF_FULLSHADOW | TPF_EFNT);\n\n\t/*\n\t**\tBuilding attribute buttons.\n\t*/\n\tSellable = new TextButtonClass(POPUP_SELLABLE, TXT_SELLABLE, TPF_EBUTTON, 320-65, 200-25, 60);\n\tRebuildable = new TextButtonClass(POPUP_REBUILDABLE, TXT_REBUILD, TPF_EBUTTON, 320-65, 200-15, 60);\n\n\t/*\n\t**\tThe facing dial\n\t*/\n\tFacingDial = new Dial8Class(POPUP_FACINGDIAL, POPUP_FACEBOX_X,\n\t\tPOPUP_FACEBOX_Y, POPUP_FACEBOX_W, POPUP_FACEBOX_H, (DirType)0);\n\n\t/*\n\t**\tThe base percent-built slider & its label\n\t*/\n\tBaseGauge = new GaugeClass(POPUP_BASEPERCENT, POPUP_BASE_X, POPUP_BASE_Y, POPUP_BASE_W, POPUP_BASE_H);\n\tBaseLabel = new TextLabelClass (\"Base:\", POPUP_BASE_X - 3, POPUP_BASE_Y, GadgetClass::Get_Color_Scheme(),\n\t\tTPF_RIGHT | TPF_NOSHADOW | TPF_EFNT);\n\tBaseGauge->Set_Maximum(100);\n\tBaseGauge->Set_Value(Scen.Percent);\n}\n\n\n/***********************************************************************************************\n * MapeditClass::Init_IO -- Reinitializes the radar map at scenario start.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapEditClass::Init_IO(void)\n{\n\t/*\n\t**\tFor normal game mode, jump to the parent's Init routine.\n\t*/\n\tif (!Debug_Map) {\n\n\t\tMouseClass::Init_IO();\n\n\t} else {\n\n\t\t/*\n\t\t**\tFor editor mode, add the map area to the button input list\n\t\t*/\n\t\tButtons = 0;\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Clear_List -- clears the internal chooseable object list   *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Clear_List(void)\n{\n\t/*\n\t**\tSet # object type ptrs to 0, set NumType for each type to 0\n\t*/\n\tObjCount = 0;\n\tfor (int i = 0; i < NUM_EDIT_CLASSES; i++) {\n\t\tNumType[i] = 0;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list     *\n *                                                                         *\n * Use this routine to add an object to the game object selection list.    *\n * This list is used by the Add_Object function. All items located in the  *\n * list will appear and be chooseable by that function. Make sure to       *\n * clear the list before adding a sequence of items to it. Clearing        *\n * the list is accomplished by the Clear_List() function.                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      object      ptr to ObjectTypeClass to add                          *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      bool: was the object added to the list?  A failure could occur if  *\n *      NULL were passed in or the list is full.                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/04/1994 JLB : Created.                                             *\n *=========================================================================*/\nbool MapEditClass::Add_To_List(ObjectTypeClass const * object)\n{\n\t/*\n\t**\tAdd the object if there's room.\n\t*/\n\tif (object && ObjCount < MAX_EDIT_OBJECTS) {\n\t\tObjects[ObjCount++] = object;\n\n\t\t/*\n\t\t**\tUpdate type counters.\n\t\t*/\n\t\tswitch (object->What_Am_I()) {\n\t\t\tcase RTTI_TEMPLATETYPE:\n\t\t\t\tNumType[0]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_OVERLAYTYPE:\n\t\t\t\tNumType[1]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_SMUDGETYPE:\n\t\t\t\tNumType[2]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_TERRAINTYPE:\n\t\t\t\tNumType[3]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_UNITTYPE:\n\t\t\t\tNumType[4]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_INFANTRYTYPE:\n\t\t\t\tNumType[5]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_VESSELTYPE:\n\t\t\t\tNumType[6]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_BUILDINGTYPE:\n\t\t\t\tNumType[7]++;\n\t\t\t\tbreak;\n\n\t\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\t\tNumType[8]++;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * MapEditClass::AI -- The map editor's main logic                         *\n *                                                                         *\n * This routine overloads the parent's (DisplayClass) AI function.         *\n * It checks for any input specific to map editing, and calls the parent   *\n * AI routine to handle scrolling and other mainstream map stuff.          *\n *                                                                         *\n * If this detects one of its special input keys, it sets 'input' to 0     *\n * before calling the parent AI routine; this prevents input conflict.     *\n *                                                                         *\n * SUPPORTED INPUT:                                                        *\n * General:                                                                *\n *      F2/RMOUSE:            main menu                                    *\n *      F6:                  toggles show-passable mode                    *\n *      HOME:                  go to the Home Cell (scenario's start position)*\n *      SHIFT-HOME:            set the Home Cell to the current TacticalCell*\n *      ESC:                  exits to DOS                                 *\n * Object Placement:                                                       *\n *      INSERT:               go into placement mode                       *\n *      ESC:                  exit placement mode                          *\n *      LEFT/RIGHT:          prev/next placement object                    *\n *      PGUP/PGDN:            prev/next placement category                 *\n *      HOME:                  1st placement object (clear template)       *\n *      h/H:                  toggle house of placement object             *\n *      LMOUSE:               place the placement object                   *\n *      MOUSE MOTION:         \"paint\" with the placement object            *\n * Object selection:                                                       *\n *      LMOUSE:               select & \"grab\" current object               *\n *                           If no object is present where the mouse is    *\n *                           clicked, the current object is de-selected    *\n *                           If the same object is clicked on, it stays    *\n *                           selected. Also displays the object-editing    *\n *                           gadgets.                                      *\n *      LMOUSE RLSE:         release currently-grabbed object              *\n *      MOUSE MOTION:         if an object is grabbed, moves the object    *\n *      SHIFT|ALT|ARROW:      moves object in that direction               *\n *      DELETE               deletes currently-selected object             *\n * Object-editing controls:                                                *\n *      POPUP_GDI:            makes GDI the owner of this object           *\n *      POPUP_NOD:            makes NOD the owner of this object           *\n *      POPUP_MISSIONLIST:   sets that mission for this object             *\n *      POPUP_HEALTHGAUGE:   sets that health value for this object        *\n *      POPUP_FACINGDIAL:      sets the object's facing                    *\n *                                                                         *\n * Changed is set when you:                                                *\n *      - place an object                                                  *\n *      - move a grabbed object                                            *\n *      - delete an object                                                 *\n *      - size the map                                                     *\n *      - create a new scenario                                            *\n *   Changed is cleared when you:                                          *\n *      - Save the scenario                                                *\n *      - Load a scenario                                                  *\n *      - Play the scenario                                                *\n *                                                                         *\n * INPUT:                                                                  *\n *      input      KN_ value, 0 if none                                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::AI(KeyNumType & input, int x, int y)\n{\n\tint rc;\n\tMissionType mission;\n\tint strength;\n\tCELL cell;\n\tint i;\n\tint found;\t\t\t\t\t\t\t\t\t// for removing a waypoint label\n\tint waypt_idx;\t\t\t\t\t\t\t\t// for labelling a waypoint\n\tBaseNodeClass * node;\t\t\t\t\t\t// for removing from an AI Base\n\tHousesType house;\n\tchar wayname[4];\n\n\t/*\n\t**\tTrap 'F2' regardless of whether we're in game or editor mode\n\t*/\n\tif (Debug_Flag) {\n\t\tif ((input == KN_F2 && Session.Type == GAME_NORMAL) || input == (KN_F2 | KN_CTRL_BIT)) {\n\t\t\tScenarioInit = 0;\n\n\t\t\t/*\n\t\t\t** If we're in editor mode & Changed is set, prompt for saving changes\n\t\t\t*/\n\t\t\tif (Debug_Map && Changed) {\n\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\n\t\t\t\t/*\n\t\t\t\t**\tUser wants to save\n\t\t\t\t*/\n\t\t\t\tif (rc == 0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf save cancelled, abort game\n\t\t\t\t\t*/\n\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUser doesn't want to save\n\t\t\t\t\t*/\n\t\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t** If we're in game mode, set Changed to 0 (so if we didn't save our\n\t\t\t\t** changes above, they won't keep coming back to haunt us with continual\n\t\t\t\t** Save Changes? prompts!)\n\t\t\t\t*/\n\t\t\t\tif (!Debug_Map) {\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tBaseGauge->Set_Value(Scen.Percent);\n\t\t\t\tGo_Editor(!Debug_Map);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tFor normal game mode, jump to the parent's AI routine.\n\t*/\n\tif (!Debug_Map) {\n\t\tMouseClass::AI(input, x, y);\n\t\treturn;\n\t}\n\n\t::Frame++;\n\n\t/*\n\t**\tDo special mouse processing if the mouse is over the map\n\t*/\n\tif (Get_Mouse_X() > TacPixelX && Get_Mouse_X() <\n\t\tTacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&\n\t\tGet_Mouse_Y() > TacPixelY && Get_Mouse_Y() <\n\t\tTacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {\n\n\t\t/*\n\t\t**\tWhen the mouse moves over a scrolling edge, ScrollClass changes its\n\t\t**\tshape to the appropriate arrow or NO symbol; it's our job to change it\n\t\t**\tback to normal (or whatever the shape is set to by Set_Default_Mouse())\n\t\t**\twhen it re-enters the map area.\n\t\t*/\n\t\tif (CurTrigger) {\n\t\t\tOverride_Mouse_Shape(MOUSE_CAN_MOVE);\n\t\t} else {\n\t\t\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\t\t}\n\t}\n\n\t/*\n\t**\tSet 'ZoneCell' to track the mouse cursor around over the map.  Do this\n\t**\teven if the map is scrolling.\n\t*/\n\tif (Get_Mouse_X() >= TacPixelX && Get_Mouse_X() <=\n\t\tTacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&\n\t\tGet_Mouse_Y() >= TacPixelY && Get_Mouse_Y() <=\n\t\tTacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {\n\n\t\tcell = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());\n\t\tif (cell != -1) {\n\t\t\tSet_Cursor_Pos(cell);\n\t\t\tif (PendingObject) {\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCheck for mouse motion while left button is down.\n\t*/\n\trc = Mouse_Moved();\n\tif (LMouseDown && rc) {\n\n\t\t/*\n\t\t**\t\"Paint\" mode: place current object, and restart placement\n\t\t*/\n\t\tif (PendingObject) {\n\t\t\tFlag_To_Redraw(true);\n\t\t\tif (Place_Object() == 0) {\n\t\t\t\tChanged = 1;\n\t\t\t\tStart_Placement();\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tMove the currently-grabbed object\n\t\t\t*/\n\t\t\tif (GrabbedObject) {\n\t\t\t\tGrabbedObject->Mark(MARK_CHANGE);\n\t\t\t\tif (Move_Grabbed_Object() == 0) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tTrap special editing keys; if one is detected, set 'input' to 0 to\n\t**\tprevent a conflict with parent's AI().\n\t*/\n\tswitch (input) {\n\t\t/*\n\t\t** F2/RMOUSE = pop up main menu\n\t\t*/\n\t\tcase KN_RMOUSE:\n\n\t\t\t/*\n\t\t\t**\tTurn off placement mode\n\t\t\t*/\n\t\t\tif (PendingObject) {\n\t\t\t\tif (BaseBuilding) {\n\t\t\t\t\tCancel_Base_Building();\n\t\t\t\t} else {\n\t\t\t\t\tCancel_Placement();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tTurn off trigger placement mode\n\t\t\t*/\n\t\t\tif (CurTrigger) {\n\t\t\t\tStop_Trigger_Placement();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tUnselect object & hide popup controls\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tCurrentObject[0]->Unselect();\n\t\t\t\tPopup_Controls();\n\t\t\t}\n\t\t\tMain_Menu();\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tF6 = toggle passable/impassable display\n\t\t*/\n\t\tcase KN_F6:\n\t\t\tDebug_Passable = (Debug_Passable == false);\n\t\t\tHidPage.Clear();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tINSERT = go into object-placement mode\n\t\t*/\n\t\tcase KN_INSERT:\n\t\t\tif (!PendingObject) {\n\t\t\t\t/*\n\t\t\t\t**\tUnselect current object, hide popup controls\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject.Count()) {\n\t\t\t\t\tCurrentObject[0]->Unselect();\n\t\t\t\t\tPopup_Controls();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tGo into placement mode\n\t\t\t\t*/\n\t\t\t\tStart_Placement();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tESC = exit placement mode, or exit to DOS\n\t\t*/\n\t\tcase KN_ESC:\n\n\t\t\t/*\n\t\t\t**\tExit object placement mode\n\t\t\t*/\n\t\t\tif (PendingObject) {\n\t\t\t\tif (BaseBuilding) {\n\t\t\t\t\tCancel_Base_Building();\n\t\t\t\t} else {\n\t\t\t\t\tCancel_Placement();\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tExit trigger placement mode\n\t\t\t\t*/\n\t\t\t\tif (CurTrigger) {\n\t\t\t\t\tStop_Trigger_Placement();\n\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\trc = WWMessageBox().Process(\"Exit Scenario Editor?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUser doesn't want to exit; return to editor\n\t\t\t\t\t*/\n\t\t\t\t\tif (rc==1) {\n\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf changed, prompt for saving\n\t\t\t\t\t*/\n\t\t\t\t\tif (Changed) {\n\t\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUser wants to save\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (rc == 0) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf save cancelled, abort exit\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Prog_End();\n\t\t\tEmergency_Exit(0);\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tLEFT = go to previous placement object\n\t\t*/\n\t\tcase KN_LEFT:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Prev();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tRIGHT = go to next placement object\n\t\t*/\n\t\tcase KN_RIGHT:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Next();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPGUP = go to previous placement category\n\t\t*/\n\t\tcase KN_PGUP:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Prev_Category();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tPGDN = go to next placement category\n\t\t*/\n\t\tcase KN_PGDN:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Next_Category();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHOME = jump to first placement object, or go to Home Cell\n\t\t*/\n\t\tcase KN_HOME:\n\t\t\tif (PendingObject) {\n\t\t\t\tPlace_Home();\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet map position\n\t\t\t\t*/\n\t\t\t\tScenarioInit++;\n\t\t\t\tSet_Tactical_Position(Scen.Waypoint[WAYPT_HOME]);\n\t\t\t\tScenarioInit--;\n\n\t\t\t\t/*\n\t\t\t\t**\tForce map to redraw\n\t\t\t\t*/\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-HOME: set new Home Cell position\n\t\t*/\n\t\tcase ((int)KN_HOME | (int)KN_SHIFT_BIT):\n\t\t\tif (CurrentCell != 0) {\n\n\t\t\t/*\n\t\t\t** Unflag the old Home Cell, if there are no other waypoints\n\t\t\t** pointing to it\n\t\t\t*/\n\t\t\tcell = Scen.Waypoint[WAYPT_HOME];\n\n\t\t\tif (cell != -1) {\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 0; i < WAYPT_COUNT; i++) {\n\t\t\t\t\tif (i != WAYPT_HOME && Scen.Waypoint[i]==cell) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found==0) {\n\t\t\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t\t\t\tFlag_Cell(cell);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Now set the new Home cell\n\t\t\t*/\n//\t\t\tScen.Waypoint[WAYPT_HOME] = Coord_Cell(TacticalCoord);\n//\t\t\t(*this)[TacticalCoord].IsWaypoint = 1;\n//\t\t\tFlag_Cell(Coord_Cell(TacticalCoord));\n\t\t\tScen.Waypoint[WAYPT_HOME] = CurrentCell;\n\t\t\t(*this)[CurrentCell].IsWaypoint = 1;\n\t\t\tFlag_Cell(CurrentCell);\n\n\t\t\tChanged = 1;\n\t\t\tinput = KN_NONE;\n}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-R: set new Reinforcement Cell position.  Don't allow setting\n\t\t**\tthe Reinf. Cell to the same as the Home Cell (for display purposes.)\n\t\t*/\n\t\tcase ((int)KN_R | (int)KN_SHIFT_BIT):\n\t\t\tif (CurrentCell==0 || CurrentCell==Scen.Waypoint[WAYPT_HOME]) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Unflag the old Reinforcement Cell, if there are no other waypoints\n\t\t\t** pointing to it\n\t\t\t*/\n\t\t\tcell = Scen.Waypoint[WAYPT_REINF];\n\n\t\t\tif (cell != -1) {\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 0; i < WAYPT_COUNT; i++) {\n\t\t\t\t\tif (i != WAYPT_REINF && Scen.Waypoint[i]==cell) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found==0) {\n\t\t\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t\t\t\tFlag_Cell(cell);\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t/*\n\t\t\t** Now set the new Reinforcement cell\n\t\t\t*/\n\t\t\tScen.Waypoint[WAYPT_REINF] = CurrentCell;\n\t\t\t(*this)[CurrentCell].IsWaypoint = 1;\n\t\t\tFlag_Cell(CurrentCell);\n\t\t\tChanged = 1;\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tALT-Letter: Label a waypoint cell\n\t\t*/\n\t\tcase ((int)KN_A | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_B | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_C | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_D | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_E | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_F | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_G | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_H | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_I | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_J | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_K | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_L | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_M | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_N | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_O | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_P | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Q | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_R | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_S | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_T | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_U | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_V | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_W | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_X | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Y | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_Z | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0) {\n#ifdef WIN32\n\t\t\t\twaypt_idx = (input & ~KN_ALT_BIT) - KN_A;\n#else\n\t\t\t\twaypt_idx = KN_To_KA(input & 0x00ff) - KA_a;\n#endif\n\t\t\t\tUpdate_Waypoint(waypt_idx);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t** ALT-. : Designate an extended (2-letter) waypoint name\n\t\t*/\n\t\tcase KN_PERIOD:\n\t\tcase ((int)KN_PERIOD | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0 && Get_Waypoint_Name(wayname)) {\n\t\t\t\tint waynm = 0;\n\t\t\t\tif (strlen(wayname)) {\n\t\t\t\t\twayname[0] = toupper(wayname[0]);\n\t\t\t\t\twayname[1] = toupper(wayname[1]);\n\t\t\t\t\tif (wayname[0] >= 'A' && wayname[0] <= 'Z') {\n\t\t\t\t\t\twaynm = wayname[0] - 'A';\n\t\t\t\t\t\tif (wayname[1] >= 'A' && wayname[1] <= 'Z') {\n\t\t\t\t\t\t\twaynm = (waynm+1)*26 + (wayname[1] - 'A');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (waynm < WAYPT_HOME) Update_Waypoint(waynm);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n#ifdef OBSOLETE\n\t\t/*\n\t\t**\tALT-1-4: Designate a cell as a capture-the-flag cell.\n\t\t*/\n\t\tcase ((int)KN_1 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_2 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_3 | (int)KN_ALT_BIT):\n\t\tcase ((int)KN_4 | (int)KN_ALT_BIT):\n\n\t\t\t/*\n\t\t\t**\tIf there's a current cell, place the flag & waypoint there.\n\t\t\t*/\n\t\t\tif (CurrentCell != 0) {\n\t\t\t\twaypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);\n//\t\t\t\twaypt_idx = (KN_To_KA(input & 0xff) - KA_1);\n\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + waypt_idx);\n\t\t\t\tif (HouseClass::As_Pointer(house)) {\n\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Attach(CurrentCell, true);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there's a current object, attach the flag to it and clear the\n\t\t\t\t**\twaypoint.\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject[0] != 0) {\n\t\t\t\t\twaypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);\n\t\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + waypt_idx);\n\t\t\t\t\tif (HouseClass::As_Pointer(house) && CurrentObject[0]->What_Am_I() == RTTI_UNIT) {\n\t\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Attach((UnitClass *)CurrentObject[0], true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n#endif\n\n\t\t/*\n\t\t**\tALT-Space: Remove a waypoint designation\n\t\t*/\n\t\tcase ((int)KN_SPACE | (int)KN_ALT_BIT):\n\t\t\tif (CurrentCell != 0) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through letter waypoints; if this cell is one of them,\n\t\t\t\t**\tclear that waypoint.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0 ; i < WAYPT_HOME; i++) {\n\t\t\t\t\tif (Scen.Waypoint[i]==CurrentCell)\n\t\t\t\t\t\tScen.Waypoint[i] = -1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through flag home values; if this cell is one of them, clear\n\t\t\t\t**\tthat waypoint.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\t\t\t\thouse = (HousesType)(HOUSE_MULTI1 + i);\n\t\t\t\t\tif (HouseClass::As_Pointer(house) &&\n\t\t\t\t\t\tCurrentCell == HouseClass::As_Pointer(house)->FlagHome)\n\t\t\t\t\tHouseClass::As_Pointer(house)->Flag_Remove(As_Target(CurrentCell), true);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there are no more waypoints on this cell, clear the cell's\n\t\t\t\t**\twaypoint designation.\n\t\t\t\t*/\n\t\t\t\tif (Scen.Waypoint[WAYPT_HOME]!=CurrentCell &&\n\t\t\t\t\tScen.Waypoint[WAYPT_REINF]!=CurrentCell)\n\t\t\t\t\t(*this)[CurrentCell].IsWaypoint = 0;\n\t\t\t\tChanged = 1;\n\t\t\t\tFlag_Cell(CurrentCell);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\t'H' = toggle current placement object's house\n\t\t*/\n\t\tcase KN_H:\n\t\tcase ((int)KN_H | (int)KN_SHIFT_BIT):\n\t\t\tif (PendingObject) {\n\t\t\t\tToggle_House();\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tLeft-mouse click:\n\t\t**\tButton DOWN:\n\t\t**\t- Toggle LMouseDown\n\t\t**\t- If we're in placement mode, try to place the current object\n\t\t**\t- If success, re-enter placement mode\n\t\t**\t- Otherwise, try to select an object, and \"grab\" it if there is one\n\t\t**\t- If no object, then select that cell as the \"current\" cell\n\t\t**\tButton UP:\n\t\t**\t- Toggle LMouseDown\n\t\t**\t- release any grabbed object\n\t\t*/\n\t\tcase ((int)MAP_AREA | (int)KN_BUTTON):\n\n\t\t\t/*\n\t\t\t**\tLeft Button DOWN\n\t\t\t*/\n\t\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t\t\t\tLMouseDown = 1;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlacement mode: place an object\n\t\t\t\t*/\n\t\t\t\tif (PendingObject) {\n\t\t\t\t\tif (Place_Object()==0) {\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t\tStart_Placement();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tPlace a trigger\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurTrigger) {\n\t\t\t\t\t\tPlace_Trigger();\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSelect an object or a cell\n\t\t\t\t\t\t**\tCheck for double-click\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (CurrentObject.Count() &&\n\t\t\t\t\t\t\t((TickCount - LastClickTime) < 15)) {\n\t\t\t\t\t\t;\t// stub\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tSingle-click: select object\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Select_Object()==0) {\n\t\t\t\t\t\t\t\tCurrentCell = 0;\n\t\t\t\t\t\t\t\tGrab_Object();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tNo object: select the cell\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tCurrentCell = Click_Cell_Calc(Keyboard->MouseQX, Keyboard->MouseQY);\n\t\t\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\t\t\tRender();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tLastClickTime = TickCount();\n\t\t\t\tinput = KN_NONE;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tLeft Button UP\n\t\t\t\t*/\n\t\t\t\tLMouseDown = 0;\n\t\t\t\tGrabbedObject = 0;\n\t\t\t\tinput = KN_NONE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tSHIFT-ALT-Arrow: move the current object\n\t\t*/\n\t\tcase (int)KN_UP | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_DOWN | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_LEFT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\tcase (int)KN_RIGHT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tCurrentObject[0]->Move(KN_To_Facing(input));\n\t\t\t\tChanged = 1;\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tDELETE: delete currently-selected object\n\t\t*/\n\t\tcase KN_DELETE:\n\n\t\t\t/*\n\t\t\t**\tDelete currently-selected object's trigger, or the object\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDelete trigger\n\t\t\t\t*/\n\t\t\t\tif (CurrentObject[0]->Trigger.Is_Valid()) {\n\t\t\t\t\tCurrentObject[0]->Trigger = NULL;\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t** If the current object is part of the AI's Base, remove it\n\t\t\t\t\t** from the Base's Node list.\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I()==RTTI_BUILDING &&\n\t\t\t\t\t\tBase.Is_Node((BuildingClass *)CurrentObject[0])) {\n\t\t\t\t\t\tnode = Base.Get_Node((BuildingClass *)CurrentObject[0]);\n\t\t\t\t\t\tBase.Nodes.Delete(*node);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDelete current object\n\t\t\t\t\t*/\n\t\t\t\t\tdelete CurrentObject[0];\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tHide the popup controls\n\t\t\t\t\t*/\n\t\t\t\t\tPopup_Controls();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tForce a redraw\n\t\t\t\t*/\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tChanged = 1;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tRemove trigger from current cell\n\t\t\t\t*/\n\t\t\t\tif (CurrentCell) {\n\t\t\t\t\tif ((*this)[CurrentCell].Trigger.Is_Valid()) {\n\t\t\t\t\t\t(*this)[CurrentCell].Trigger = NULL;\n//\t\t\t\t\t\tCellTriggers[CurrentCell] = NULL;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tForce a redraw\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tTAB: select next object on the map\n\t\t*/\n\t\tcase KN_TAB:\n\t\t\tSelect_Next();\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: House Button\n\t\t*/\n\t\tcase POPUP_HOUSELIST|KN_BUTTON:\n\t\t\t/*\n\t\t\t**\tDetermine the house desired by examining the currently\n\t\t\t**\tselected index in the house list gadget.\n\t\t\t*/\n\t\t\thouse = HousesType(((ListClass *)Buttons->Extract_Gadget(POPUP_HOUSELIST))->Current_Index());\n\n\t\t\t/*\n\t\t\t**\tIf that house doesn't own this object, try to transfer it\n\t\t\t*/\n\t\t\tif (CurrentObject[0]->Owner() != house) {\n\t\t\t\tif (Change_House(house)) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n//\t\t\tSet_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);\n\t\t\tHidPage.Clear();\n\t\t\tButtons->Flag_List_To_Redraw();\n\t\t\tFlag_To_Redraw(true);\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n//\t\tcase (POPUP_GDI | KN_BUTTON):\n//\t\tcase (POPUP_NOD | KN_BUTTON):\n//\t\tcase (POPUP_NEUTRAL | KN_BUTTON):\n//\t\tcase (POPUP_MULTI1 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI2 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI3 | KN_BUTTON):\n//\t\tcase (POPUP_MULTI4 | KN_BUTTON):\n//\n//\t\t\t/*\n//\t\t\t**\tConvert input value into a house value; assume HOUSE_GOOD is 0\n//\t\t\t*/\n//\t\t\thouse = (HousesType)( (input & (~KN_BUTTON)) - POPUP_FIRST);\n//\n//\t\t\t/*\n//\t\t\t**\tIf that house doesn't own this object, try to transfer it\n//\t\t\t*/\n//\t\t\tif (CurrentObject[0]->Owner()!=house) {\n//\t\t\t\tif (Change_House(house)) {\n//\t\t\t\t\tChanged = 1;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\tSet_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);\n//\t\t\tHidPage.Clear();\n//\t\t\tFlag_To_Redraw(true);\n//\t\t\tinput = KN_NONE;\n//\t\t\tbreak;\n\n\t\tcase POPUP_SELLABLE|KN_BUTTON:\n\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tBuildingClass * building = (BuildingClass *)CurrentObject[0];\n\n\t\t\t\tif (building->Class->Level != -1) {\n//\t\t\t\tif (building->Class->IsBuildable) {\n\t\t\t\t\tbuilding->IsAllowedToSell = (building->IsAllowedToSell == false);\n\t\t\t\t\tbuilding->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tif (building->IsAllowedToSell) {\n\t\t\t\t\tSellable->Turn_On();\n\t\t\t\t} else {\n\t\t\t\t\tSellable->Turn_Off();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase POPUP_REBUILDABLE|KN_BUTTON:\n\t\t\tif (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\tBuildingClass * building = (BuildingClass *)CurrentObject[0];\n\n\t\t\t\tif (building->Class->Level != -1) {\n//\t\t\t\tif (building->Class->IsBuildable) {\n\t\t\t\t\tbuilding->IsToRebuild = (building->IsToRebuild == false);\n\t\t\t\t\tbuilding->Mark(MARK_CHANGE);\n\t\t\t\t}\n\t\t\t\tif (building->IsToRebuild) {\n\t\t\t\t\tRebuildable->Turn_On();\n\t\t\t\t} else {\n\t\t\t\t\tRebuildable->Turn_Off();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Mission\n\t\t*/\n\t\tcase (POPUP_MISSIONLIST | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\t\t\t\t/*\n\t\t\t\t**\tSet new mission\n\t\t\t\t*/\n\t\t\t\tmission = MapEditMissions[MissionList->Current_Index()];\n\t\t\t\tif (CurrentObject[0]->Get_Mission() != mission) {\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->Set_Mission(mission);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t\tButtons->Flag_List_To_Redraw();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Health\n\t\t*/\n\t\tcase (POPUP_HEALTHGAUGE | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDerive strength from current gauge reading\n\t\t\t\t*/\n\t\t\t\tstrength = CurrentObject[0]->Class_Of().MaxStrength * fixed(HealthGauge->Get_Value(), 256);\n//\t\t\t\tstrength = Fixed_To_Cardinal((unsigned)CurrentObject[0]->Class_Of().MaxStrength, (unsigned)HealthGauge->Get_Value());\n\n\t\t\t\t/*\n\t\t\t\t**\tClip to 1\n\t\t\t\t*/\n\t\t\t\tif (strength <= 0) {\n\t\t\t\t\tstrength = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet new strength\n\t\t\t\t*/\n\t\t\t\tif (strength != CurrentObject[0]->Strength) {\n\t\t\t\t\tCurrentObject[0]->Strength = strength;\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tUpdate text label\n\t\t\t\t*/\n\t\t\t\tsprintf(HealthBuf, \"%d\", strength);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Facing\n\t\t*/\n\t\tcase (POPUP_FACINGDIAL | KN_BUTTON):\n\t\t\tif (CurrentObject[0]->Is_Techno()) {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet new facing\n\t\t\t\t*/\n\t\t\t\tif (FacingDial->Get_Direction() !=\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->PrimaryFacing.Get()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet body's facing\n\t\t\t\t\t*/\n\t\t\t\t\t((TechnoClass *)CurrentObject[0])->PrimaryFacing.Set(FacingDial->Get_Direction());\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tSet turret facing, if there is one\n\t\t\t\t\t*/\n\t\t\t\t\tif (CurrentObject[0]->What_Am_I()==RTTI_UNIT) {\n\t\t\t\t\t\t((UnitClass *)CurrentObject[0])->SecondaryFacing.Set(FacingDial->Get_Direction());\n\t\t\t\t\t}\n\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tObject-Editing button: Facing\n\t\t*/\n\t\tcase (POPUP_BASEPERCENT | KN_BUTTON):\n\t\t\tif (BaseGauge->Get_Value() != Scen.Percent) {\n\t\t\t\tScen.Percent = BaseGauge->Get_Value();\n\t\t\t\tBuild_Base_To(Scen.Percent);\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t}\n\t\t\tinput = KN_NONE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tCall parent's AI routine\n\t*/\n\tMouseClass::AI(input, x, y);\n}\n\n\n/***************************************************************************\n * MapEditClass::Draw_It -- overloaded Redraw routine                      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Draw_It(bool forced)\n{\n\tchar const * label;\n\tchar buf[40];\n\tchar const * tptr;\n\n\tMouseClass::Draw_It(forced);\n\n\tif (!Debug_Map) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tDisplay the total value of all Tiberium on the map.\n\t*/\n\tFancy_Text_Print(\"Tiberium=%ld   \", 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tBLACK, TPF_EFNT | TPF_NOSHADOW, TotalValue);\n\n\t/*\n\t**\tIf there are no object controls displayed, just invoke parent's Redraw\n\t**\tand return.\n\t*/\n\tif (!Buttons) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOtherwise, if 'display' is set, invoke the parent's Redraw to refresh\n\t**\tthe HIDPAGE; then, update the buttons & text labels onto HIDPAGE;\n\t**\tthen invoke the parent's Redraw to blit the HIDPAGE to SEENPAGE.\n\t*/\n\tif (forced) {\n\n\t\t/*\n\t\t**\tUpdate the text labels\n\t\t*/\n\t\tif (CurrentObject.Count()) {\n\t\t\t/*\n\t\t\t**\tDisplay the object's name & ID\n\t\t\t*/\n\t\t\tlabel = Text_String(CurrentObject[0]->Full_Name());\n\t\t\ttptr = label;\n\t\t\tsprintf(buf, \"%s (%d)\", tptr, CurrentObject[0]->As_Target());\n\n\t\t\t/*\n\t\t\t**\tprint the label\n\t\t\t*/\n\t\t\tFancy_Text_Print (buf, 160, 0,\n\t\t\t\t&ColorRemaps[PCOLOR_BROWN], TBLACK,\n\t\t\t\tTPF_CENTER | TPF_NOSHADOW | TPF_EFNT);\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Mouse_Moved -- checks for mouse motion                    *\n *                                                                         *\n * Reports whether the mouse has moved or not. This varies based on the    *\n * type of object currently selected. If there's an infantry object        *\n *   selected, mouse motion counts even within a cell; for all other types,*\n *   mouse motion counts only if the mouse changes cells.                  *\n *                                                                         *\n *   The reason this routine is needed is to prevent Paint-Mode from putting*\n *   gobs of trees and such into the same cell if the mouse moves just     *\n *   a little bit.                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/08/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Mouse_Moved(void)\n{\n\tstatic int old_mx = 0;\n\tstatic int old_my = 0;\n\tstatic CELL old_zonecell = 0;\n\tconst ObjectTypeClass * objtype = NULL;\n\tbool retcode = false;\n\n\t/*\n\t**\tReturn if no motion\n\t*/\n\tif (old_mx == Get_Mouse_X() && old_my == Get_Mouse_Y()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tGet a ptr to ObjectTypeClass\n\t*/\n\tif (PendingObject) {\n\t\tobjtype = PendingObject;\n\t} else {\n\t\tif (GrabbedObject) {\n\t\t\tobjtype = &GrabbedObject->Class_Of();\n\t\t} else {\n\t\t\told_mx = Get_Mouse_X();\n\t\t\told_my = Get_Mouse_Y();\n\t\t\told_zonecell = ZoneCell;\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tInfantry: mouse moved if any motion at all\n\t*/\n\tif (objtype->What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\tretcode = true;\n\t} else {\n\t\t/*\n\t\t**\tOthers: mouse moved only if cell changed\n\t\t*/\n\t\tif (old_zonecell!=ZoneCell) {\n\t\t\tretcode = true;\n\t\t} else {\n\t\t\tretcode = false;\n\t\t}\n\t}\n\n\told_mx = Get_Mouse_X();\n\told_my = Get_Mouse_Y();\n\told_zonecell = ZoneCell;\n\treturn(retcode);\n}\n\n\n/***************************************************************************\n * MapEditClass::Main_Menu -- main menu processor for map editor           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Main_Menu(void)\n{\n\tchar const * _menus[MAX_MAIN_MENU_NUM + 1];\n\tint selection;\t\t\t\t\t\t// option the user picks\n\tbool process;\t\t\t\t\t\t// menu stays up while true\n\tint rc;\n\n\t/*\n\t**\tFill in menu items\n\t*/\n\t_menus[0] = \"New Scenario\";\n\t_menus[1] = \"Load Scenario\";\n\t_menus[2] = \"Save Scenario\";\n\t_menus[3] = \"Size Map\";\n\t_menus[4] = \"Add Game Object\";\n\t_menus[5] = \"Scenario Options\";\n\t_menus[6] = \"AI Options\";\n\t_menus[7] = \"Play Scenario\";\n\t_menus[8] = NULL;\n\n\t/*\n\t**\tMain Menu loop\n\t*/\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\t// display default mouse cursor\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback, to update music\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tInvoke menu\n\t\t*/\n\t\tHide_Mouse();\t\t// Do_Menu assumes the mouse is already hidden\n\t\tselection = Do_Menu(&_menus[0], true);\n\t\tShow_Mouse();\n\t\tif (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess selection\n\t\t*/\n\t\tswitch (selection) {\n\n\t\t\t/*\n\t\t\t**\tNew scenario\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (New_Scenario()==0) {\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tLoad scenario\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Load_Scenario()==0) {\n\t\t\t\t\tScen.CarryOverMoney = 0;\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSave scenario\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tif (Save_Scenario() == 0) {\n\t\t\t\t\tChanged = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tEdit map size\n\t\t\t*/\n\t\t\tcase 3:\n\t\t\t\tif (Size_Map(MapCellX, MapCellY, MapCellWidth, MapCellHeight)==0) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tAdd an object\n\t\t\t*/\n\t\t\tcase 4:\n\t\t\t\tif (Placement_Dialog() == 0) {\n\t\t\t\t\tStart_Placement();\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tScenario options\n\t\t\t*/\n\t\t\tcase 5:\n\t\t\t\tif (Scenario_Dialog() == 0) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOther options\n\t\t\t*/\n\t\t\tcase 6:\n\t\t\t\tAI_Menu();\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTest-drive this scenario\n\t\t\t*/\n\t\t\tcase 7:\n\t\t\t\tif (Changed) {\n\t\t\t\t\trc = WWMessageBox().Process(\"Save Changes?\", TXT_YES, TXT_NO, TXT_CANCEL);\n\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\tRender();\n\t\t\t\t\tif (rc == 2) return;\n\t\t\t\t\tif (rc==0) {\n\t\t\t\t\t\tif (Save_Scenario()!=0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tChanged = 0;\n\t\t\t\tDebug_Map = false;\n\t\t\t\tStart_Scenario(Scen.ScenarioName);\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t**\tRestore the display:\n\t**\t- Clear HIDPAGE to erase any spurious drawing done by the menu system\n\t**\t- Invoke Flag_To_Redraw to tell DisplayClass to re-render the whole screen\n\t**\t- Invoke Redraw() to update the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::AI_Menu -- menu of AI options                             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::AI_Menu(void)\n{\n\tint selection;\t\t\t\t\t\t// option the user picks\n\tbool process;\t\t\t\t\t\t// menu stays up while true\n\tchar const * _menus[MAX_AI_MENU_NUM + 1];\n\n\t/*\n\t**\tFill in menu strings\n\t*/\n\t_menus[0] = \"Pre-Build a Base\";\n\t_menus[1] = \"Edit Triggers\";\n\t_menus[2] = \"Edit Teams\";\n\t_menus[3] = NULL;\n\n\t/*\n\t**\tMain Menu loop\n\t*/\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\t\t// display default mouse cursor\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback, to update music\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tInvoke menu\n\t\t*/\n\t\tHide_Mouse();\t\t// Do_Menu assumes the mouse is already hidden\n\t\tselection = Do_Menu(&_menus[0], true);\n\t\tShow_Mouse();\n\t\tif (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tProcess selection\n\t\t*/\n\t\tswitch (selection) {\n\t\t\t/*\n\t\t\t**\tPre-Build a Base\n\t\t\t*/\n\t\t\tcase 0:\n\t\t\t\tStart_Base_Building();\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTrigger Editing\n\t\t\t*/\n\t\t\tcase 1:\n\t\t\t\tHandle_Triggers();\n\t\t\t\t/*\n\t\t\t\t**\tGo into trigger placement mode\n\t\t\t\t*/\n\t\t\t\tif (CurTrigger) {\n\t\t\t\t\tStart_Trigger_Placement();\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tTeam Editing\n\t\t\t*/\n\t\t\tcase 2:\n\t\t\t\tHandle_Teams(\"Teams\");\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Verify_House -- is this objtype ownable by this house?    *\n *                                                                         *\n * INPUT:                                                                  *\n *      house         house to check                                       *\n *      objtype      ObjectTypeClass to check                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = isn't ownable, 1 = it is                                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Verify_House(HousesType house, ObjectTypeClass const * objtype)\n{\n\t/*\n\t**\tVerify that new house can own this object\n\t*/\n\treturn((objtype->Get_Ownable() & (1 << house)) != 0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cycle_House -- finds next valid house for object type     *\n *                                                                         *\n * INPUT:                                                                  *\n *      objtype      ObjectTypeClass ptr to get house for                  *\n *      curhouse      current house value to start with                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      HousesType that's valid for this object type                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1994 BR : Created.                                              *\n *=========================================================================*/\nHousesType MapEditClass::Cycle_House(HousesType curhouse, ObjectTypeClass const *)\n{\n\tHousesType count;\t\t\t// prevents an infinite loop\n\n\t/*\n\t**\tLoop through all house types, starting with the one after 'curhouse';\n\t**\treturn the first one that's valid\n\t*/\n\tcount = HOUSE_NONE;\n\twhile (1) {\n\n\t\t/*\n\t\t**\tGo to next house\n\t\t*/\n\t\tcurhouse++;\n\t\tif (curhouse == HOUSE_COUNT) {\n\t\t\tcurhouse = HOUSE_FIRST;\n\t\t}\n\n\t\t/*\n\t\t**\tCount # iterations; don't go forever\n\t\t*/\n\t\tcount++;\n\t\tif (count == HOUSE_COUNT) {\n\t\t\tcurhouse = HOUSE_NONE;\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tBreak if this is a valid house\n\t\t*/\n//\t\tif (HouseClass::As_Pointer(curhouse) && Verify_House(curhouse, objtype)) {\n\t\t\tbreak;\n//\t\t}\n\t}\n\n\treturn(curhouse);\n}\n\n\n/***************************************************************************\n * MapEditClass::Fatal -- exits with error message                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      code      tells which message to display; this minimizes the       *\n *               use of character strings in the code.                     *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/12/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Fatal(int txt)\n{\n\t//Prog_End();\n\tprintf(\"%s\\n\", txt);\n\tEmergency_Exit(EXIT_FAILURE);\n}\n\n\nbool MapEditClass::Scroll_Map(DirType facing, int & distance, bool really)\n{\n\tif (Debug_Map) {\n\t\t/*\n\t\t** The popup gadgets require the entire map to be redrawn if we scroll.\n\t\t*/\n\t\tif (really) {\n\t\t\tFlag_To_Redraw(true);\n\t\t}\n\t}\n\treturn(MouseClass::Scroll_Map(facing, distance, really));\n}\n\n\n#ifdef OBSOLETE\nvoid MapEditClass::Flag_To_Redraw(bool complete)\n{\n\tMouseClass::Flag_To_Redraw(complete);\n}\n#endif\n\n\nvoid MapEditClass::Detach(ObjectClass * object)\n{\n\tif (GrabbedObject == object) {\n\t\tGrabbedObject = 0;\n\t}\n}\n\nbool MapEditClass::Get_Waypoint_Name(char wayptname[])\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 100,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 56,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320 - D_DIALOG_W) / 2),\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = ((200 - D_DIALOG_H) / 2),\t\t\t\t// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 7,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_EDIT_W = D_DIALOG_W - (D_MARGIN * 2),\n\t\tD_EDIT_H = 13,\n\t\tD_EDIT_X = D_DIALOG_X + D_MARGIN,\n\t\tD_EDIT_Y = D_DIALOG_Y + 20,\n\n\t\tD_BUTTON_X = D_DIALOG_X + D_MARGIN,\n\t\tD_BUTTON_Y = D_DIALOG_Y + 40,\n\t\tD_BUTTON_W = 40,\n\t\tD_BUTTON_H = 13,\n\n\t\tD_CANCEL_X = D_DIALOG_X + 53,\n\t\tD_CANCEL_Y = D_DIALOG_Y + 40,\n\t\tD_CANCEL_W = 40,\n\t\tD_CANCEL_H = 13,\n\n\t};\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_EDIT,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t// true = user cancels\n\twayptname[0] = 0;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass button (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_BUTTON_X, D_BUTTON_Y, D_BUTTON_W);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W);\n\tEditClass editbtn (BUTTON_EDIT, wayptname, 3, TPF_EFNT|TPF_NOSHADOW, D_EDIT_X, D_EDIT_Y, D_EDIT_W, -1, EditClass::ALPHANUMERIC);\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &button;\n\tcancelbtn.Add_Tail(*commands);\n\teditbtn.Add_Tail(*commands);\n\teditbtn.Set_Focus();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else if (Main_Loop()) {\n\t\t\tprocess = false;\n\t\t\tcancel = true;\n\t\t}\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n//\t\t\t\tDraw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime) {\n\t\t\tfirsttime = false;\n\t\t\teditbtn.Set_Focus();\n\t\t\teditbtn.Flag_To_Redraw();\n\t\t}\n\n\t\t/*\n\t\t**\tIf the <RETURN> key was pressed, then default to the appropriate\n\t\t**\taction button according to the style of this dialog box.\n\t\t*/\n\t\tif (input == KN_RETURN) {\n\t\t\tinput = (KeyNumType)(BUTTON_OK|KN_BUTTON);\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*\n\t\t\t** Load: if load fails, present a message, and stay in the dialog\n\t\t\t** to allow the user to try another game\n\t\t\t*/\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tHide_Mouse();\n\t\t\t\tSeenPage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tprocess = false;\n\t\t\t\tcancel = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** ESC/Cancel: break\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tHide_Mouse();\n\t\t\t\tSeenPage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tMap.Flag_To_Redraw(true);\n\tif (cancel) return(false);\n\n\treturn(true);\n}\n\nvoid MapEditClass::Update_Waypoint(int waypt_idx)\n{\n\tCELL cell;\n\n\t/*\n\t**\tUnflag cell for this waypoint if there is one\n\t*/\n\tcell = Scen.Waypoint[waypt_idx];\n\tif (cell != -1) {\n\t\tif (Scen.Waypoint[WAYPT_HOME] != cell && Scen.Waypoint[WAYPT_REINF] != cell) {\n\t\t\t(*this)[cell].IsWaypoint = 0;\n\t\t}\n\t\tFlag_Cell(cell);\n\t}\n\tScen.Waypoint[waypt_idx] = CurrentCell;\n\t(*this)[CurrentCell].IsWaypoint = 1;\n\tChanged = 1;\n\tFlag_Cell(CurrentCell);\n}\n\n\n/***************************************************************************\n * MapEditClass::Read_INI -- overloaded Read_INI function                  *\n *                                                                         *\n * Overloading this function gives the map editor a chance to initialize   *\n * certain values every time a new INI is read.                            *\n *                                                                         *\n * INPUT:                                                                  *\n *      buffer      INI staging area                                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/16/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Read_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tInvoke parent's Read_INI\n\t*/\n\tMono_Printf(\"We are in Read_INI\\n\");\n\n\tMouseClass::Read_INI(ini);\n\tBaseGauge->Set_Value(Scen.Percent);\n\n\tMono_Clear_Screen();\n\tMono_Printf(\"Scen.Percent = %d\", Scen.Percent);\n\n//\tBaseGauge->Set_Value(Scen.Percent);\n}\n\n\nvoid MapEditClass::Write_INI(CCINIClass & ini)\n{\n\tMouseClass::Write_INI(ini);\n//\tini.Put_Int(\"Basic\", \"Percent\", Scen.Percent);\n}\n\n#endif\n\n#include\t\"mapedsel.cpp\"\n\n"
  },
  {
    "path": "REDALERT/MAPEDIT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDIT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAPEDIT.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 14, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 14, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *\tThis class is derived from the normal display map class. It exists \t\t                    *\n * only to allow editing and adding items to the map.\t\t\t\t\t\t\t\t                    *\n *---------------------------------------------------------------------------------------------*\n * House-setting functions: The editor contains several house maintenance routines:\t\t\t\t  *\n * Verify_House: tells if the given ObjectType can be owned by the given HousesType\t\t\t\t  *\n * Cycle_House: Finds the next valid house for the given ObjectType; used when a new object\t  *\n *              can't be owned by the current editor HousesType.\t\t\t\t\t\t\t\t\t\t  *\n * Change_House: attempts to change the owner of the currently-selected object\t\t\t\t\t  *\n * Toggle_House: cycles the HousesType of a pending placement object\t\t\t\t\t\t\t\t\t  *\n * Set_House_Buttons: sets house buttons in accordance with the given HousesType\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MAPEDIT_H\n#define MAPEDIT_H\n\n#include\t\"function.h\"\n\n/*\n**\tThis is the maximum # of ObjectTypeClasses the editor has to deal with.\n*/\nenum MapEdit1Enum {\n\tMAX_EDIT_OBJECTS =\t\t\t\t// max # of ObjectTypeClasses allowed\n\t\t(int)TEMPLATE_COUNT +\n\t\t(int)OVERLAY_COUNT +\n\t\t(int)SMUDGE_COUNT +\n\t\t(int)TERRAIN_COUNT +\n\t\t(int)UNIT_COUNT +\n\t\t(int)INFANTRY_COUNT +\n\t\t(int)VESSEL_COUNT +\n\t\t(int)STRUCT_COUNT,\n\n\tMAX_TEAM_CLASSES =\t\t\t\t// max # ObjectTypeClasses for a team\n\t\t(int)UNIT_COUNT +\n\t\t(int)INFANTRY_COUNT +\n\t\t(int)AIRCRAFT_COUNT,\n\n//\tNUM_EDIT_MISSIONS = 6,\t\t\t// # missions that can be assigned an object\n\n\tNUM_EDIT_CLASSES = 9,\t\t\t// # different classes (templates, terrain, etc)\n\n\tMAX_MAIN_MENU_NUM = 8,\n\tMAX_MAIN_MENU_LEN = 20,\n\n\tMAX_AI_MENU_NUM = 6,\n\tMAX_AI_MENU_LEN = 20,\n\n\tPOPUP_HOUSE_X=10,\n\tPOPUP_HOUSE_Y=100,\n\tPOPUP_HOUSE_W=60,\n\tPOPUP_HOUSE_H=(190-100),\n\n//\tPOPUP_GDI_W = 50,\n//\tPOPUP_GDI_H = 9,\n//\tPOPUP_GDI_X = 10,\n//\tPOPUP_GDI_Y = 160,\n\n//\tPOPUP_NOD_W = 50,\n//\tPOPUP_NOD_H = 9,\n//\tPOPUP_NOD_X = 10,\n//\tPOPUP_NOD_Y = 169,\n\n//\tPOPUP_NEUTRAL_W = 50,\n//\tPOPUP_NEUTRAL_H = 9,\n//\tPOPUP_NEUTRAL_X = 10,\n//\tPOPUP_NEUTRAL_Y = 178,\n\n//\tPOPUP_MULTI1_W = 25,\n//\tPOPUP_MULTI1_H = 9,\n//\tPOPUP_MULTI1_X = 10,\n//\tPOPUP_MULTI1_Y = 160,\n\n//\tPOPUP_MULTI2_W = 25,\n//\tPOPUP_MULTI2_H = 9,\n//\tPOPUP_MULTI2_X = 35,\n//\tPOPUP_MULTI2_Y = 160,\n\n//\tPOPUP_MULTI3_W = 25,\n//\tPOPUP_MULTI3_H = 9,\n//\tPOPUP_MULTI3_X = 10,\n//\tPOPUP_MULTI3_Y = 169,\n\n//\tPOPUP_MULTI4_W = 25,\n//\tPOPUP_MULTI4_H = 9,\n//\tPOPUP_MULTI4_X = 35,\n//\tPOPUP_MULTI4_Y = 169,\n\n\tPOPUP_MISSION_W = 80,\n\tPOPUP_MISSION_H = 40,\n\tPOPUP_MISSION_X = 70,\n\tPOPUP_MISSION_Y = 150,\n\n\tPOPUP_FACEBOX_W = 30,\n\tPOPUP_FACEBOX_H = 30,\n\tPOPUP_FACEBOX_X = 160,\n\tPOPUP_FACEBOX_Y = 160,\n\n\tPOPUP_HEALTH_W = 50,\n\tPOPUP_HEALTH_H = 10,\n\tPOPUP_HEALTH_X = 200,\n\tPOPUP_HEALTH_Y = 170,\n\n\tPOPUP_BASE_W = 50,\n\tPOPUP_BASE_H = 8,\n\tPOPUP_BASE_X = 300 - 50,\n\tPOPUP_BASE_Y = 0\n};\n\n/*\n**\tThese are the button ID's for the pop-up object-editing gizmos.\n**\tThe house button ID's must be sequential, with a 1-to-1 correspondence to\n**\tthe HousesType values.\n*/\nenum MapEditButtonIDEnum{\n\tPOPUP_SPAIN=500,\n\tPOPUP_FIRST=POPUP_SPAIN,\n\tPOPUP_GREECE,\n\tPOPUP_USSR,\n\tPOPUP_ENGLAND,\n\tPOPUP_ITALY,\n\tPOPUP_GERMANY,\n\tPOPUP_FRANCE,\n\tPOPUP_TURKEY,\n\tPOPUP_HOUSELIST,\t\t\t// House selection list.\n\tPOPUP_SELLABLE,\t\t\t// Allowed to sell.\n\tPOPUP_REBUILDABLE,\t\t// Allowed to rebuild.\n\tPOPUP_MISSIONLIST,\t\t// list box for missions\n\tPOPUP_HEALTHGAUGE,\t\t// health of object\n\tPOPUP_FACINGDIAL,\t\t\t// object's facing\n\tPOPUP_BASEPERCENT,\t\t// Base's percent-built slider\n\tMAP_AREA,\t\t\t\t\t// map as a click-able thingy\n\tBUTTON_FLAG=0x8000\n};\n\n\nclass TeamTypeClass;\n\nclass MapEditClass : public MouseClass\n{\n\t/*\n\t**\tPublic Interface\n\t*/\n\tpublic:\n\n\t\t/*\n\t\t**\tmapedit.cpp\n\t\t*/\n\t\tMapEditClass(void);\n\t\tMapEditClass(NoInitClass const & x) : MouseClass(x) {};\n\t\tbool Get_Waypoint_Name(char wayptname[]);\n\t\tvoid Update_Waypoint(int waypt_index);\n\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time init\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool forced = true);\n\t\tvirtual bool Scroll_Map(DirType facing, int & distance, bool really=true);\n\t\tvirtual void Read_INI(CCINIClass & ini);\n\t\tvirtual void Write_INI(CCINIClass & ini);\n\t\tvirtual void Detach(ObjectClass * object);\n\t\tvoid Detach(TARGET target, bool all=true) {MouseClass::Detach(target, all);}\n\t\tvoid Clear_List(void);\n\t\tbool Add_To_List(ObjectTypeClass const *object);\n\t\tvoid Main_Menu(void);\n\t\tvoid AI_Menu(void);\n\t\tbool Mouse_Moved(void);\n\t\tbool Verify_House(HousesType house, ObjectTypeClass const * objtype);\n\t\tHousesType Cycle_House(HousesType curhouse, ObjectTypeClass const * objtype);\n//\t\tint Trigger_Needs_Team(TriggerClass *trigger);\n\t\tvoid Fatal(int txt);\n\n\t\t/*\n\t\t**\tmapeddlg.cpp\n\t\t*/\n\t\tint New_Scenario(void);\n\t\tint Load_Scenario(void);\n\t\tint Save_Scenario(void);\n\t\tint Pick_Scenario(char const * caption, int & scen_nump, ScenarioPlayerType & playerp, ScenarioDirType & dirp, ScenarioVarType & varp);\n\t\tint Size_Map(int x, int y, int w, int h);\n\t\tint Scenario_Dialog(void);\n\t\tvoid Handle_Triggers(void);\n\t\tint Select_Trigger(void);\n\n\t\t/*\n\t\t**\tmapedplc.cpp\n\t\t*/\n\t\tint Placement_Dialog(void);\n\t\tvoid Start_Placement(void);\n\t\tint Place_Object(void);\n\t\tvoid Cancel_Placement(void);\n\t\tvoid Place_Next(void);\n\t\tvoid Place_Prev(void);\n\t\tvoid Place_Next_Category(void);\n\t\tvoid Place_Prev_Category(void);\n\t\tvoid Place_Home(void);\n\t\tvoid Toggle_House(void);\n\t\tvoid Set_House_Buttons(HousesType house, GadgetClass *btnlist, int base_id);\n\t\tvoid Start_Trigger_Placement(void);\n\t\tvoid Stop_Trigger_Placement(void);\n\t\tvoid Place_Trigger(void);\n\t\tvoid Start_Base_Building(void);\n\t\tvoid Cancel_Base_Building(void);\n\t\tvoid Build_Base_To(int percent);\n\n\t\t/*\n\t\t**\tmapedsel.cpp\n\t\t*/\n\t\tint Select_Object(void);\n\t\tvoid Select_Next(void);\n\t\tvoid Popup_Controls(void);\n\t\tvoid Grab_Object(void);\n\t\tint Move_Grabbed_Object(void);\n\t\tbool Change_House(HousesType newhouse);\n\n\t\t/*\n\t\t**\tmapedtm.cpp\n\t\t*/\n\t\tvoid Draw_Member(TechnoTypeClass const * ptr, int index, int quant, HousesType house);\n\t\tvoid Handle_Teams(char const * caption);\n\t\tint Select_Team(char const * caption);\n\t\tint Team_Members(HousesType house);\n\n\t/*\n\t**\tPrivate Interface\n\t*/\n\tprivate:\n\t\t/*\n\t\t**\tThis is the last-requested variation of a loaded/saved/new scenario.\n\t\t*/\n//\t\tScenarioVarType ScenVar;\n\n\t\t/*\n\t\t**\tArray of all TypeClasses the user can add to the map; cleared by\n\t\t**\tClear_List(), added to by Add_To_List()\n\t\t*/\n\t\tObjectTypeClass const * Objects[MAX_EDIT_OBJECTS];\n\t\tint ObjCount;\t\t\t\t\t\t\t// # of objects in the Objects array\n\n\t\t/*\n\t\t**\tLast-selected object to place, and last-selected house of object\n\t\t*/\n\t\tint LastChoice;\t\t\t\t\t\t// index of item user picked last\n\t\tHousesType LastHouse;\t\t\t\t// house of last item picked\n\n\t\t/*\n\t\t**\tVariables for grabbing/moving objects\n\t\t*/\n\t\tObjectClass * GrabbedObject;\t\t// object \"grabbed\" with mouse\n\t\tCELL GrabOffset;\t\t\t\t\t\t// offset to grabbed obj's upper-left\n\t\tunsigned long LastClickTime;\t\t// time of last LMOUSE click\n\n\t\t/*\n\t\t**\tNumber of each type of object in Objects, so we can switch categories\n\t\t*/\n\t\tint NumType[NUM_EDIT_CLASSES];\t\t// # of each type of class:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 0 = Template\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 1 = Overlay\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 2 = Smudge\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 3 = Terrain\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 4 = Unit\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 5 = Infantry\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 6 = Vessels\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 7 = Building\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 8 = Aircraft\n\n\t\t/*\n\t\t**\tThe offset of each type of object within the Objects[] array\n\t\t*/\n\t\tint TypeOffset[NUM_EDIT_CLASSES];\t// offsets within Objects[]\n\n\t\t/*\n\t\t**\tThe \"current\" trigger for point-and-click trigger setting\n\t\t*/\n\t\tTriggerTypeClass * CurTrigger;\t\t\t\t// current trigger\n\n\t\t/*\n\t\t**\tThe \"current\" team type for editing & associating with a trigger\n\t\t*/\n\t\tTeamTypeClass * CurTeam;\t\t\t\t// current team\n\n\t\t/*\n\t\t**\tBitfields for flags & such\n\t\t*/\n\t\tunsigned Changed : 1;\t\t\t\t\t\t// 1 = changes are unsaved\n\t\tunsigned LMouseDown : 1;\t\t\t\t\t// 1 = left mouse is held down\n\t\tunsigned BaseBuilding : 1;\t\t\t\t// 1 = we're in base-building mode\n\n\t\t/*\n\t\t**\tVariables for pre-building a base\n\t\t*/\n//\t\tint BasePercent;\t\t\t\t\t\t// Percentage the base will be built\n\n\t\t/*\n\t\t**\tVariables for supporting the object-editing controls at screen bottom\n\t\t*/\n\t\tListClass * HouseList;\n\t\tListClass * MissionList;\n\t\tTriColorGaugeClass *HealthGauge;\n\t\tDial8Class *FacingDial;\n\t\tControlClass *MapArea;\n\t\tTextLabelClass *HealthText;\n\t\tTextButtonClass * Sellable;\n\t\tTextButtonClass * Rebuildable;\n\t\tstatic char HealthBuf[20];\n\t\tGaugeClass *BaseGauge;\n\t\tTextLabelClass *BaseLabel;\n\t\tstatic MissionType MapEditMissions[];\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/MAPEDPLC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDPLC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDPLC.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : May 12, 1996 [JLB]                       *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Object-placement routines                                               *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Build_Base_To -- builds the AI base to the given percent*\n *   MapEditClass::Cancel_Base_Building -- stops base-building mode        *\n *   MapEditClass::Cancel_Placement -- cancels placement mode              *\n *   MapEditClass::Place_Home -- homes the placement object                *\n *   MapEditClass::Place_Next -- while placing object, goes to next        *\n *   MapEditClass::Place_Next_Category -- places next object category      *\n *   MapEditClass::Place_Object -- attempts to place the current object    *\n *   MapEditClass::Place_Prev -- while placing object, goes to previous    *\n *   MapEditClass::Place_Prev_Category -- places previous object category  *\n *   MapEditClass::Place_Trigger -- assigns trigger to object or cell      *\n *   MapEditClass::Placement_Dialog -- adds an object to the scenario      *\n *   MapEditClass::Set_House_Buttons -- toggles house buttons for btn list *\n *   MapEditClass::Start_Base_Building -- starts base-building mode        *\n *   MapEditClass::Start_Placement -- enters placement mode                *\n *   MapEditClass::Start_Trigger_Placement -- enters trigger placement mode*\n *   MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode  *\n *   MapEditClass::Toggle_House -- toggles current placement object's house*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::Placement_Dialog -- adds an object to the scenario        *\n *                                                                         *\n * This function sets LastChoice & LastHouse to the values chosen          *\n * by the user. It's up to the caller to call Start_Placement to enter     *\n * placement mode.                                                         *\n *   This routine does not modify PendingObject or PendingHouse.           *\n *                                                                         *\n *  Ŀ                   *\n *     [GDI]  [NOD]  [Neutral]                                           *\n *                                                                       *\n *     Ŀ                                 *\n *                                     [Template]                      *\n *                                     [Overlay ]                      *\n *                                     [Smudge  ]                      *\n *                                     [Terrain ]                      *\n *           (Object picture)          [Unit    ]                      *\n *                                     [Infantry]                      *\n *                                     [Aircraft]                      *\n *                                     [Building]                      *\n *                                                                     *\n *          Ŀ                    *\n *               [<-]  [->]                  (Grid)                    *\n *                                                                     *\n *           [OK]        [Cancel]                                *\n *                     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   10/21/1994 BR : Created.                                              *\n *   12/13/1995 JLB : Fixed house buttons to handle expanded house list.   *\n *   05/12/1996 JLB : Handles hi-res.                                      *\n *=========================================================================*/\nint MapEditClass::Placement_Dialog(void)\n{\n\tHousesType house;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\n\t\tD_DIALOG_H = 180,\n\t\tD_DIALOG_X = 0,\n\t\tD_DIALOG_Y = 0,\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\n\n\t\tD_TXT8_H = 11,\n\t\tD_MARGIN = 7,\n\n\t\tD_PICTURE_W = 152,\t\t\t\t\t// must be divisible by 8!\n\t\tD_PICTURE_H = 105,\n\t\tD_PICTURE_X = D_DIALOG_X + 35,\t\t// must start on a byte boundary!\n\t\tD_PICTURE_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,\n\t\tD_PICTURE_CX = D_PICTURE_X + D_PICTURE_W / 2,\n\n\t\tD_GDI_W = 65,\n\t\tD_GDI_H = 9,\n\t\tD_GDI_X = D_PICTURE_X+D_PICTURE_W+5,\n\t\tD_GDI_Y = D_PICTURE_Y,\n\n\t\tD_LEFT_W = 45,\n\t\tD_LEFT_H = 9,\n\t\tD_LEFT_X = D_PICTURE_CX - 5 - D_LEFT_W,\n\t\tD_LEFT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,\n\n\t\tD_RIGHT_W = 45,\n\t\tD_RIGHT_H = 9,\n\t\tD_RIGHT_X = D_PICTURE_CX + 5,\n\t\tD_RIGHT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,\n\n\t\tD_TEMPLATE_W = 70,\n\t\tD_TEMPLATE_H = 9,\n\t\tD_TEMPLATE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TEMPLATE_W - 30,\n\t\tD_TEMPLATE_Y = D_PICTURE_Y,\n\n\t\tD_OVERLAY_W = 70,\n\t\tD_OVERLAY_H = 9,\n\t\tD_OVERLAY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_OVERLAY_W - 30,\n\t\tD_OVERLAY_Y = D_TEMPLATE_Y + D_TEMPLATE_H,\n\n\t\tD_SMUDGE_W = 70,\n\t\tD_SMUDGE_H = 9,\n\t\tD_SMUDGE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_SMUDGE_W - 30,\n\t\tD_SMUDGE_Y = D_OVERLAY_Y + D_OVERLAY_H,\n\n\t\tD_TERRAIN_W = 70,\n\t\tD_TERRAIN_H = 9,\n\t\tD_TERRAIN_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TERRAIN_W - 30,\n\t\tD_TERRAIN_Y = D_SMUDGE_Y + D_SMUDGE_H,\n\n\t\tD_UNIT_W = 70,\n\t\tD_UNIT_H = 9,\n\t\tD_UNIT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_UNIT_W - 30,\n\t\tD_UNIT_Y = D_TERRAIN_Y + D_TERRAIN_H,\n\n\t\tD_INFANTRY_W = 70,\n\t\tD_INFANTRY_H = 9,\n\t\tD_INFANTRY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_INFANTRY_W - 30,\n\t\tD_INFANTRY_Y = D_UNIT_Y + D_UNIT_H,\n\n\t\tD_AIRCRAFT_W = 70,\n\t\tD_AIRCRAFT_H = 9,\n\t\tD_AIRCRAFT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIRCRAFT_W - 30,\n\t\tD_AIRCRAFT_Y = D_INFANTRY_Y + D_INFANTRY_H,\n\n\t\tD_BUILDING_W = 70,\n\t\tD_BUILDING_H = 9,\n\t\tD_BUILDING_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_BUILDING_W - 30,\n\t\tD_BUILDING_Y = D_AIRCRAFT_Y + D_AIRCRAFT_H,\n\n\t\tD_AIR_W = 70,\n\t\tD_AIR_H = 9,\n\t\tD_AIR_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIR_W - 30,\n\t\tD_AIR_Y = D_BUILDING_Y + D_BUILDING_H,\n\n\t\tD_OK_W = 45,\n\t\tD_OK_H = 9,\n\t\tD_OK_X = D_PICTURE_CX - D_OK_W - 5,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN - 15,\n\n\t\tD_CANCEL_W = 45,\n\t\tD_CANCEL_H = 9,\n\t\tD_CANCEL_X = D_PICTURE_CX + 5,\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN - 15,\n\n\t\tGRIDSIZE = 10,\n\t\tGRIDBLOCK_W = 3,\n\t\tGRIDBLOCK_H = 3,\n\t\tD_GRID_X = D_DIALOG_X + D_DIALOG_W - (GRIDSIZE * GRIDBLOCK_W) - D_MARGIN - 35,\n\t\tD_GRID_Y = D_DIALOG_Y + D_DIALOG_H - (GRIDSIZE * GRIDBLOCK_H) - D_MARGIN - 35,\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_GDI=100,\n\t\tBUTTON_HOUSE,\n\t\tBUTTON_NEXT,\n\t\tBUTTON_PREV,\n\t\tBUTTON_OK,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_TEMPLATE,\n\t\tBUTTON_OVERLAY,\n\t\tBUTTON_SMUDGE,\n\t\tBUTTON_TERRAIN,\n\t\tBUTTON_UNIT,\n\t\tBUTTON_INFANTRY,\n\t\tBUTTON_AIRCRAFT,\n\t\tBUTTON_BUILDING,\n\t\tBUTTON_AIR,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tconst ObjectTypeClass * curobj;\t\t\t// Working object pointer.\n\tint x,y;\t\t\t\t\t\t\t\t\t\t\t// for drawing the grid\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tshort const * occupy;\t\t\t\t\t\t\t// ptr into object's OccupyList\n\tint cell;\t\t\t\t\t\t\t\t\t\t// cell index for parsing OccupyList\n\tint i;\n\tint typeindex;\t\t\t\t\t\t\t\t\t// index of class type\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands;\n\n\tListClass housebtn(BUTTON_HOUSE,\n\t\tD_GDI_X, D_GDI_Y, 60, 8*16,\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\tfor (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\thousebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);\n\t}\n\thouse = HOUSE_FIRST;\n\n\tTextButtonClass nextbtn(BUTTON_NEXT, TXT_RIGHT, TPF_EBUTTON, D_RIGHT_X, D_RIGHT_Y, D_RIGHT_W, D_RIGHT_H);\n\tTextButtonClass prevbtn(BUTTON_PREV, TXT_LEFT, TPF_EBUTTON, D_LEFT_X, D_LEFT_Y, D_LEFT_W, D_LEFT_H);\n\tTextButtonClass okbtn(BUTTON_OK, \"OK\", TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, \"Cancel\", TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\tTextButtonClass templatebtn(BUTTON_TEMPLATE, \"Template\", TPF_EBUTTON, D_TEMPLATE_X, D_TEMPLATE_Y, D_TEMPLATE_W, D_TEMPLATE_H);\n\tTextButtonClass overlaybtn(BUTTON_OVERLAY, \"Overlay\", TPF_EBUTTON, D_OVERLAY_X, D_OVERLAY_Y, D_OVERLAY_W, D_OVERLAY_H);\n\tTextButtonClass smudgebtn(BUTTON_SMUDGE, \"Smudge\", TPF_EBUTTON, D_SMUDGE_X, D_SMUDGE_Y, D_SMUDGE_W, D_SMUDGE_H);\n\tTextButtonClass terrainbtn(BUTTON_TERRAIN, \"Terrain\", TPF_EBUTTON, D_TERRAIN_X, D_TERRAIN_Y, D_TERRAIN_W, D_TERRAIN_H);\n\tTextButtonClass unitbtn(BUTTON_UNIT, \"Unit\", TPF_EBUTTON, D_UNIT_X, D_UNIT_Y, D_UNIT_W, D_UNIT_H);\n\tTextButtonClass infantrybtn(BUTTON_INFANTRY, \"Infantry\", TPF_EBUTTON, D_INFANTRY_X, D_INFANTRY_Y, D_INFANTRY_W, D_INFANTRY_H);\n\tTextButtonClass aircraftbtn(BUTTON_AIRCRAFT, \"Ships\", TPF_EBUTTON, D_AIRCRAFT_X, D_AIRCRAFT_Y, D_AIRCRAFT_W, D_AIRCRAFT_H);\n\tTextButtonClass buildingbtn(BUTTON_BUILDING, \"Building\", TPF_EBUTTON, D_BUILDING_X, D_BUILDING_Y, D_BUILDING_W, D_BUILDING_H);\n\tTextButtonClass airbtn(BUTTON_AIR, \"Aircraft\", TPF_EBUTTON, D_AIR_X, D_AIR_Y, D_AIR_W, D_AIR_H);\n\n\t/*\n\t**\tInitialize addable objects list; we must do this every time in case one\n\t**\tof the object pools has become exhausted; that object won't be available\n\t**\tfor adding.  (Skip aircraft, since they won't be used in the editor.)\n\t*/\n\tClear_List();\n\tTemplateTypeClass::Prep_For_Add();\n\tOverlayTypeClass::Prep_For_Add();\n\tSmudgeTypeClass::Prep_For_Add();\n\tTerrainTypeClass::Prep_For_Add();\n\tUnitTypeClass::Prep_For_Add();\n\tInfantryTypeClass::Prep_For_Add();\n\tVesselTypeClass::Prep_For_Add();\n\tBuildingTypeClass::Prep_For_Add();\n\tAircraftTypeClass::Prep_For_Add();\n\n\t/*\n\t**\tCompute offset of each class type in the Objects array\n\t*/\n\tTypeOffset[0] = 0;\n\tfor (i = 1; i < NUM_EDIT_CLASSES; i++) {\n\t\tTypeOffset[i] = TypeOffset[i-1] + NumType[i-1];\n\t}\n\n\t/*\n\t**\tReturn if no objects to place\n\t*/\n\tif (!ObjCount)  {\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tif (LastChoice >= ObjCount) {\n\t\tLastChoice = 0;\n\t}\n\tcurobj = Objects[LastChoice];\t\t// current object to choose\n\n\tcommands = &nextbtn;\n\thousebtn.Add_Tail(*commands);\n\tprevbtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\ttemplatebtn.Add_Tail(*commands);\n\toverlaybtn.Add_Tail(*commands);\n\tsmudgebtn.Add_Tail(*commands);\n\tterrainbtn.Add_Tail(*commands);\n\tunitbtn.Add_Tail(*commands);\n\tinfantrybtn.Add_Tail(*commands);\n\taircraftbtn.Add_Tail(*commands);\n\tbuildingbtn.Add_Tail(*commands);\n\tairbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMake sure the recorded house selection matches the house list\n\t**\tbox selection.\n\t*/\n\tLastHouse = HousesType(housebtn.Current_Index());\n\n\t/*\n\t**\tMain processing loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_PLACE_OBJECT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t/*\n\t\t\t**\tDisplay the current object:\n\t\t\t**\t- save the current window dimensions\n\t\t\t**\t- adjust the window size to the actual drawable area\n\t\t\t**\t- draw the shape\n\t\t\t**\t- reset the window dimensions\n\t\t\t*/\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWX] = D_PICTURE_X;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWY] = D_PICTURE_Y;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = D_PICTURE_W;\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT] = D_PICTURE_H;\n\t\t\tChange_Window((int)WINDOW_EDITOR);\n\t\t\tDraw_Box(D_PICTURE_X, D_PICTURE_Y, D_PICTURE_W, D_PICTURE_H, BOXSTYLE_DOWN, false);\n\t\t\tcurobj->Display(WinW/2, WinH>>1, WINDOW_EDITOR, LastHouse);\n//\t\t\tcurobj->Display(WinW<<2, WinH>>1, WINDOW_EDITOR, LastHouse);\n\n\t\t\t/*\n\t\t\t**\tErase the grid\n\t\t\t*/\n\t\t\tLogicPage->Fill_Rect(D_GRID_X - GRIDBLOCK_W * 2, D_GRID_Y,\n\t\t\t\tD_GRID_X + GRIDSIZE * GRIDBLOCK_W,\n\t\t\t\tD_GRID_Y + GRIDSIZE * GRIDBLOCK_H, BLACK);\n\n\t\t\t/*\n\t\t\t**\tDraw a box for every cell occupied\n\t\t\t*/\n\t\t\toccupy = curobj->Occupy_List();\n\t\t\twhile ( (*occupy) != REFRESH_EOL) {\n\t\t\t\tcell = (*occupy);\n\t\t\t\toccupy++;\n\t\t\t\tx = D_GRID_X + ((cell % MAP_CELL_W) * GRIDBLOCK_W);\n\t\t\t\ty = D_GRID_Y + ((cell / MAP_CELL_W) * GRIDBLOCK_H);\n\t\t\t\tLogicPage->Fill_Rect(x, y, x + GRIDBLOCK_W - 1, y + GRIDBLOCK_H - 1, scheme->Bright);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the grid itself\n\t\t\t*/\n\t\t\tfor (y = 0; y <= GRIDSIZE; y++) {\n\t\t\t\tfor (x = 0; x <= GRIDSIZE; x++) {\n\t\t\t\t\tLogicPage->Draw_Line(D_GRID_X + x * GRIDBLOCK_W, D_GRID_Y,\n\t\t\t\t\t\tD_GRID_X + x * GRIDBLOCK_W,\n\t\t\t\t\t\tD_GRID_Y + GRIDSIZE * GRIDBLOCK_H, scheme->Shadow);\n\t\t\t\t}\n\t\t\t\tLogicPage->Draw_Line(D_GRID_X, D_GRID_Y + y * GRIDBLOCK_H,\n\t\t\t\t\tD_GRID_X + GRIDSIZE * GRIDBLOCK_W, D_GRID_Y + y * GRIDBLOCK_H,\n\t\t\t\t\tscheme->Shadow);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tPrint the object's label from the class's Full_Name().\n\t\t\t**\tWarning: Text_String returns an EMS pointer, so standard string\n\t\t\t**\tfunctions won't work!\n\t\t\t*/\n\t\t\tFancy_Text_Print (curobj->Full_Name(),\n\t\t\t\tD_PICTURE_CX, D_PICTURE_Y + D_MARGIN, scheme, TBLACK,\n\t\t\t\tTPF_CENTER | TPF_EFNT | TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tRedraw buttons\n\t\t\t**\tFigure out which class category we're in & highlight that button\n\t\t\t**\tThis updates 'typeindex', which is used below, and it also updates\n\t\t\t**\tthe category button states.\n\t\t\t*/\n\t\t\ti = 0;\n\t\t\tfor (typeindex = 0; typeindex < NUM_EDIT_CLASSES; typeindex++) {\n\t\t\t\ti += NumType[typeindex];\n\t\t\t\tif (LastChoice < i) break;\n\t\t\t}\n\t\t\ttemplatebtn.Turn_Off();\n\t\t\toverlaybtn.Turn_Off();\n\t\t\tsmudgebtn.Turn_Off();\n\t\t\tterrainbtn.Turn_Off();\n\t\t\tunitbtn.Turn_Off();\n\t\t\tinfantrybtn.Turn_Off();\n\t\t\taircraftbtn.Turn_Off();\n\t\t\tairbtn.Turn_Off();\n\t\t\tbuildingbtn.Turn_Off();\n\t\t\tswitch (typeindex + BUTTON_TEMPLATE) {\n\t\t\t\tcase BUTTON_TEMPLATE:\n\t\t\t\t\ttemplatebtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_OVERLAY:\n\t\t\t\t\toverlaybtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_SMUDGE:\n\t\t\t\t\tsmudgebtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_TERRAIN:\n\t\t\t\t\tterrainbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_UNIT:\n\t\t\t\t\tunitbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_INFANTRY:\n\t\t\t\t\tinfantrybtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_AIRCRAFT:\n\t\t\t\t\taircraftbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_AIR:\n\t\t\t\t\tairbtn.Turn_On();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BUTTON_BUILDING:\n\t\t\t\t\tbuildingbtn.Turn_On();\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw buttons\n\t\t\t*/\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess user input\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tGDI House\n\t\t\t*/\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\thouse = HousesType(housebtn.Current_Index());\n\n\t\t\t\t/*\n\t\t\t\t**\tSet flags & buttons\n\t\t\t\t*/\n\t\t\t\tLastHouse = house;\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNext in list\n\t\t\t*/\n\t\t\tcase (KN_RIGHT):\n\t\t\tcase (BUTTON_NEXT | KN_BUTTON):\n\t\t\t\t/*\n\t\t\t\t**\tIncrement to next obj\n\t\t\t\t*/\n\t\t\t\tLastChoice++;\n\t\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\t\tLastChoice = 0;\n\t\t\t\t}\n\t\t\t\tcurobj = Objects[LastChoice];\n\n\t\t\t\tnextbtn.Turn_Off();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPrevious in list\n\t\t\t*/\n\t\t\tcase (KN_LEFT):\n\t\t\tcase (BUTTON_PREV | KN_BUTTON):\n\n\t\t\t\t/*\n\t\t\t\t**\tDecrement to prev obj\n\t\t\t\t*/\n\t\t\t\tLastChoice--;\n\t\t\t\tif (LastChoice < 0) {\n\t\t\t\t\tLastChoice = ObjCount-1;\n\t\t\t\t}\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tprevbtn.Turn_Off();\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tSelect a class type\n\t\t\t*/\n\t\t\tcase (BUTTON_TEMPLATE | KN_BUTTON):\n\t\t\tcase (BUTTON_OVERLAY | KN_BUTTON):\n\t\t\tcase (BUTTON_SMUDGE | KN_BUTTON):\n\t\t\tcase (BUTTON_TERRAIN | KN_BUTTON):\n\t\t\tcase (BUTTON_UNIT | KN_BUTTON):\n\t\t\tcase (BUTTON_INFANTRY | KN_BUTTON):\n\t\t\tcase (BUTTON_AIRCRAFT | KN_BUTTON):\n\t\t\tcase (BUTTON_BUILDING | KN_BUTTON):\n\t\t\tcase (BUTTON_AIR | KN_BUTTON):\n\n\t\t\t\t/*\n\t\t\t\t**\tFind index of class\n\t\t\t\t*/\n\t\t\t\ttypeindex = input - (BUTTON_TEMPLATE | KN_BUTTON);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf no objects of that type, do nothing\n\t\t\t\t*/\n\t\t\t\tif (NumType[typeindex]==0) {\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tNext category\n\t\t\t*/\n\t\t\tcase KN_PGDN:\n\t\t\t\ttypeindex++;\n\t\t\t\tif (typeindex==NUM_EDIT_CLASSES) {\n\t\t\t\t\ttypeindex = 0;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tPrevious category\n\t\t\t*/\n\t\t\tcase KN_PGUP:\n\t\t\t\ttypeindex--;\n\t\t\t\tif (typeindex < 0) {\n\t\t\t\t\ttypeindex = NUM_EDIT_CLASSES - 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tLastChoice = TypeOffset[typeindex];\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tJump to 1st choice\n\t\t\t*/\n\t\t\tcase KN_HOME:\n\t\t\t\tLastChoice = 0;\n\n\t\t\t\t/*\n\t\t\t\t**\tSet current object\n\t\t\t\t*/\n\t\t\t\tcurobj = Objects[LastChoice];\n\t\t\t\tdisplay = true;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOK\n\t\t\t*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tcancel = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCancel\n\t\t\t*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (cancel) {\n\t\treturn(-1);\n\t}\n\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Placement -- enters placement mode                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Placement(void)\n{\n\n\t/*\n\t**\tInitialize addable objects list; we must do this every time in case one\n\t**\tof the object pools has become exhausted; that object won't be available\n\t**\tfor adding. These must be added in the same order expected by the\n\t**\tobject selection dialog (same as button order).\n\t*/\n\tClear_List();\n\tTemplateTypeClass::Prep_For_Add();\n\tOverlayTypeClass::Prep_For_Add();\n\tSmudgeTypeClass::Prep_For_Add();\n\tTerrainTypeClass::Prep_For_Add();\n\tUnitTypeClass::Prep_For_Add();\n\tInfantryTypeClass::Prep_For_Add();\n\tVesselTypeClass::Prep_For_Add();\n\tBuildingTypeClass::Prep_For_Add();\n\tAircraftTypeClass::Prep_For_Add();\n\n\t/*\n\t**\tCompute offset of each class type in the Objects array\n\t*/\n\tTypeOffset[0] = 0;\n\tfor (int i = 1; i < NUM_EDIT_CLASSES; i++) {\n\t\tTypeOffset[i] = TypeOffset[i-1] + NumType[i-1];\n\t}\n\n\t/*\n\t**\tCreate the placement object:\n\t**\t- For normal placement mode, use the last-used index into Objects\n\t**\t  (LastChoice), and the last-used house (LastHouse).\n\t**\t- For base-building mode, force the object to be a building, and use the\n\t**\t  House specified in the Base object\n\t*/\n\tif (!BaseBuilding) {\n\t\tif (LastChoice >= ObjCount) {\n\t\t\tLastChoice = ObjCount - 1;\n\t\t}\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));\n\t} else {\n\t\tif (LastChoice < TypeOffset[7]) {\n\t\t\tLastChoice = TypeOffset[7];\n\t\t}\n\t\tif (LastChoice >= ObjCount) {\n\t\t\tLastChoice = ObjCount - 1;\n\t\t}\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse = Base.House;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));\n\t}\n\n\t/*\n\t**\tError if no more objects available\n\t*/\n\tif (!PendingObjectPtr) {\n\t\tWWMessageBox().Process(\"No more objects of this type available.\");\n\t\tHidPage.Clear();\n\t\tFlag_To_Redraw(true);\n\t\tRender();\n\t\tPendingObject = NULL;\n\t\tif (BaseBuilding) {\n\t\t\tCancel_Base_Building();\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSet the placement cursor\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Object -- attempts to place the current object      *\n *                                                                         *\n * Placement of \"real\" objects is simply checked via their Unlimbo routine.*\n * Placement of templates is more complex:                                 *\n * - for every cell in the template's OccupyList, check for objects        *\n *     already in that cell by looking at the cell's OccupyList &          *\n *     OverlapList                                                         *\n * - \"lift\" all the objects in the cell by Mark'ing them                   *\n * - temporarily place the template in that cell                           *\n * - try to Unlimbo all the objects that were in the cell. If any          *\n *     objects fail to Unlimbo onto that template, the template cannot     *\n *     be placed here                                                      *\n *                                                                         *\n * It is assumed that the object being placed is a \"new\" object; the       *\n * object's strength & mission are not set during Unlimbo.                 *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = unable to place                                       *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Place_Object(void)\n{\n\tCELL template_cell;\t\t\t\t\t\t// cell being checked for template\n\tCOORDINATE obj_coord;\t\t\t\t\t\t\t// coord of occupier object\n\tint okflag;\t\t\t\t\t\t\t\t\t// OK to place a template?\n\tshort const * occupy;\t\t\t\t\t\t// ptr into template's OccupyList\n\tObjectClass * occupier;\t\t\t\t\t// occupying object\n\tTemplateType save_ttype;\t\t\t\t// for saving cell's TType\n\tunsigned char save_ticon;\t\t\t\t// for saving cell's TIcon\n//\tBaseNodeClass node;\t\t\t\t\t\t// for adding to an AI Base\n\n\t/*\n\t**\tPlacing a template:\n\t**\t- first lift up any objects in the cell\n\t**\t- place the template, and try to replace the objects; if they won't go\n\t**\t  back, the template can't go there\n\t*/\n\t//ScenarioInit++;\n\tif (PendingObject->What_Am_I() == RTTI_TEMPLATETYPE) {\n\n\t\t/*\n\t\t**\tLoop through all cells this template will occupy\n\t\t*/\n\t\tokflag = true;\n\t\toccupy = PendingObject->Occupy_List();\n\t\twhile ((*occupy) != REFRESH_EOL) {\n\n\t\t\t/*\n\t\t\t**\tCheck this cell for an occupier\n\t\t\t*/\n\t\t\ttemplate_cell = (ZoneCell+ZoneOffset) + (*occupy);\n\t\t\tif ((*this)[template_cell].Cell_Occupier()) {\n\t\t\t\toccupier = (*this)[template_cell].Cell_Occupier();\n\n\t\t\t\t/*\n\t\t\t\t**\tSave object's coordinates\n\t\t\t\t*/\n\t\t\t\tobj_coord = occupier->Coord;\n\n\t\t\t\t/*\n\t\t\t\t**\tPlace the object in limbo\n\t\t\t\t*/\n\t\t\t\toccupier->Mark(MARK_UP);\n\n\t\t\t\t/*\n\t\t\t\t**\tSet the cell's template values\n\t\t\t\t*/\n\t\t\t\tsave_ttype = (*this)[template_cell].TType;\n\t\t\t\tsave_ticon = (*this)[template_cell].TIcon;\n\t\t\t\t(*this)[template_cell].TType =\n\t\t\t\t\t((TemplateTypeClass *)PendingObject)->Type;\n\t\t\t\t(*this)[template_cell].TIcon = Cell_X(*occupy) + Cell_Y(*occupy) *\n\t\t\t\t\t((TemplateTypeClass *)PendingObject)->Width;\n\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\n\t\t\t\t/*\n\t\t\t\t**\tTry to put the object back down\n\t\t\t\t*/\n\t\t\t\tif (occupier->Can_Enter_Cell(Coord_Cell(obj_coord)) != MOVE_OK) {\n\t\t\t\t\tokflag = false;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tPut everything back the way it was\n\t\t\t\t*/\n\t\t\t\t(*this)[template_cell].TType = save_ttype;\n\t\t\t\t(*this)[template_cell].TIcon = save_ticon;\n\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\n\t\t\t\t/*\n\t\t\t\t**\tMajor error if can't replace the object now\n\t\t\t\t*/\n\t\t\t\toccupier->Mark(MARK_DOWN);\n\t\t\t}\n\t\t\toccupy++;\n\t\t}\n\n\t\t/*\n\t\t**\tIf it's still OK after ALL THAT, place the template\n\t\t*/\n\t\tif (okflag) {\n\t\t\tif (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {\n\n\t\t\t\t/*\n\t\t\t\t**\tLoop through all cells occupied by this template, and clear the\n\t\t\t\t**\tsmudge & overlay.\n\t\t\t\t*/\n\t\t\t\toccupy = PendingObject->Occupy_List();\n\t\t\t\twhile ((*occupy) != REFRESH_EOL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tGet cell for this occupy item\n\t\t\t\t\t*/\n\t\t\t\t\ttemplate_cell = (ZoneCell+ZoneOffset) + (*occupy);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tClear smudge & overlay\n\t\t\t\t\t*/\n\t\t\t\t\t(*this)[template_cell].Overlay = OVERLAY_NONE;\n\t\t\t\t\t(*this)[template_cell].OverlayData = 0;\n\t\t\t\t\t(*this)[template_cell].Smudge = SMUDGE_NONE;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tmake adjacent cells recalc attrib's\n\t\t\t\t\t*/\n\t\t\t\t\t(*this)[template_cell].Recalc_Attributes();\n\t\t\t\t\t(*this)[template_cell].Wall_Update();\n\t\t\t\t\t(*this)[template_cell].Concrete_Calc();\n\n\t\t\t\t\toccupy++;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tSet flags etc\n\t\t\t\t*/\n\t\t\t\tPendingObjectPtr = 0;\n\t\t\t\tPendingObject = 0;\n\t\t\t\tPendingHouse = HOUSE_NONE;\n\t\t\t\tSet_Cursor_Shape(0);\n\t\t\t\t//ScenarioInit--;\n\t\t\t\tTotalValue = Overpass();\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFailure to deploy results in a returned failure code.\n\t\t\t*/\n\t\t\t//ScenarioInit--;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t**\tNot OK; return error\n\t\t*/\n\t\t//ScenarioInit--;\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tPlacing infantry: Infantry can go into cell sub-positions, so find the\n\t**\tsub-position closest to the mouse & put him there\n\t*/\n\tif (PendingObject->What_Am_I() == RTTI_INFANTRYTYPE) {\n\n\t\t/*\n\t\t**\tFind cell sub-position\n\t\t*/\n\t\tif (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {\n\t\t\tobj_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));\n\t\t} else {\n\t\t\tobj_coord = NULL;\n\t\t}\n\n\t\t/*\n\t\t**\tNo free spots; don't place the object\n\t\t*/\n\t\tif (obj_coord == NULL) {\n\t\t\t//ScenarioInit--;\n\t\t\treturn(-1);\n\t\t}\n\n\t\t/*\n\t\t**\tUnlimbo the object\n\t\t*/\n\t\tif (PendingObjectPtr->Unlimbo(obj_coord)) {\n\t\t\t((InfantryClass *)PendingObjectPtr)->Set_Occupy_Bit(obj_coord);\n//\t\t\tMap[obj_coord].Flag.Composite |=\n//\t\t\t\t(1 << CellClass::Spot_Index(obj_coord));\n\t\t\tPendingObjectPtr = 0;\n\t\t\tPendingObject = 0;\n\t\t\tPendingHouse = HOUSE_NONE;\n\t\t\tSet_Cursor_Shape(0);\n\t\t\t//ScenarioInit--;\n\t\t\treturn(0);\n\t\t}\n\n\t\t//ScenarioInit--;\n\t\treturn(-1);\n\t}\n\n\t/*\n\t**\tPlacing an object\n\t*/\n\tif (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {\n\n\t\t/*\n\t\t** Update the Tiberium computation if we're placing an overlay\n\t\t*/\n\t\tif (PendingObject->What_Am_I() == RTTI_OVERLAYTYPE &&\n\t\t\t((OverlayTypeClass *)PendingObject)->IsTiberium) {\n\t\t\tTotalValue = Overpass();\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t** If we're building a base, add this building to the base's Node list.\n\t\t*/\n\t\tif (BaseBuilding && PendingObject->What_Am_I() == RTTI_BUILDINGTYPE) {\n//\t\t\tnode.Type = ((BuildingTypeClass *)PendingObject)->Type;\n//\t\t\tnode.Cell = Coord_Cell(PendingObjectPtr->Coord);\n\t\t\tBase.Nodes.Add(BaseNodeClass(((BuildingTypeClass *)PendingObject)->Type, Coord_Cell(PendingObjectPtr->Coord)));\n\t\t}\n\n\t\tPendingObjectPtr = 0;\n\t\tPendingObject = 0;\n\t\tPendingHouse = HOUSE_NONE;\n\t\tSet_Cursor_Shape(0);\n\t\t//ScenarioInit--;\n\t\treturn(0);\n\t}\n\n\treturn(-1);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cancel_Placement -- cancels placement mode                *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Cancel_Placement(void)\n{\n\t/*\n\t**\tDelete the placement object\n\t*/\n\tdelete PendingObjectPtr;\n\tPendingObject = 0;\n\tPendingObjectPtr = 0;\n\tPendingHouse = HOUSE_NONE;\n\n\t/*\n\t**\tRestore cursor shape\n\t*/\n\tSet_Cursor_Shape(0);\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Next -- while placing object, goes to next          *\n *                                                                         *\n * - Deletes the current 'PendingObjectPtr'                                *\n * - Increments LastChoice                                                 *\n * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *\n *   incrementing until it gets it                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Next(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\t\t/*\n\t\t**\tGo to next object in Objects list\n\t\t*/\n\t\tLastChoice++;\n\t\tif (LastChoice == ObjCount) {\n\n\t\t\t/*\n\t\t\t** If we're in normal placement mode, wrap to the 1st object;\n\t\t\t** if we're in base-building mode, wrap to the 1st building\n\t\t\t*/\n\t\t\tif (!BaseBuilding) {\n\t\t\t\tLastChoice = 0;\n\t\t\t} else {\n\t\t\t\tLastChoice = TypeOffset[7];\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Prev -- while placing object, goes to previous      *\n *                                                                         *\n * - Deletes the current 'PendingObjectPtr'                                *\n * - Decrements LastChoice                                                 *\n * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *\n *   decrementing until it gets it                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Prev(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGo to prev object in Objects list\n\t\t*/\n\t\tLastChoice--;\n\n\t\t/*\n\t\t** If we're in normal placement mode, wrap at the 1st object.\n\t\t** If we're building a base, wrap at the 1st building.\n\t\t*/\n\t\tif (!BaseBuilding) {\n\t\t\tif (LastChoice < 0) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t} else {\n\t\t\tif (LastChoice < TypeOffset[7]) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Next_Category -- places next category of object     *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Next_Category(void)\n{\n\tint i;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tGo to next category in Objects list\n\t*/\n\ti = LastChoice;\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti++;\n\t\tif (i == ObjCount) {\n\t\t\ti = 0;\n\t\t}\n\t}\n\tLastChoice = i;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n//\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n//\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n//\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice++;\n\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\tLastChoice = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Prev_Category -- places previous category of object *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Prev_Category(void)\n{\n\tint i;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t**\tGo to prev category in Objects list\n\t*/\n\ti = LastChoice;\n\n\t/*\n\t**\tScan for start of this category\n\t*/\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti--;\n\t\tif (i < 0) {\n\t\t\ti = ObjCount - 1;\n\t\t}\n\t}\n\n\ti--;\n\tif (i < 0) i = ObjCount-1;\n\tLastChoice = i;\n\n\t/*\n\t**\tScan for the previous category\n\t*/\n\twhile (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {\n\t\ti--;\n\t\tif (i < 0) {\n\t\t\ti = ObjCount - 1;\n\t\t}\n\t}\n\n\ti++;\n\tif (i >= ObjCount) i = 0;\n\tLastChoice = i;\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n//\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n//\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n//\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice--;\n\t\t\tif (LastChoice < 0) {\n\t\t\t\tLastChoice = ObjCount - 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Home -- homes the placement object                  *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/03/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Home(void)\n{\n\tdelete PendingObjectPtr;\n\tPendingObjectPtr = NULL;\n\tPendingObject = NULL;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** category for base-building is buildings.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tLoop until we create a valid object\n\t*/\n\tLastChoice = 0;\n\twhile (!PendingObjectPtr) {\n\n\t\t/*\n\t\t**\tGet house for this object type\n\t\t*/\n\t\tif (!Verify_House(LastHouse, Objects[LastChoice])) {\n\t\t\tLastHouse = Cycle_House(LastHouse, Objects[LastChoice]);\n\t\t}\n\n\t\t/*\n\t\t**\tCreate placement object\n\t\t*/\n\t\tPendingObject = Objects[LastChoice];\n\t\tPendingHouse = LastHouse;\n\t\tPendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));\n\n\t\t/*\n\t\t**\tIf this one failed, try the next\n\t\t*/\n\t\tif (!PendingObjectPtr) {\n\t\t\tPendingObject = NULL;\n\t\t\tLastChoice++;\n\t\t\tif (LastChoice == ObjCount) {\n\t\t\t\tLastChoice = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tSet the new cursor shape\n\t*/\n\tSet_Cursor_Pos();\n\tSet_Cursor_Shape(0);\n\tSet_Cursor_Shape(PendingObject->Occupy_List());\n\n\t/*\n\t**\tRedraw the map to erase old leftovers\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n}\n\n\n/***************************************************************************\n * MapEditClass::Toggle_House -- toggles current placement object's house  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Toggle_House(void)\n{\n\tTechnoClass *tp;\n\n\t/*\n\t** Don't allow this command if we're building a base; the only valid\n\t** house for base-building is the one assigned to the base.\n\t*/\n\tif (BaseBuilding) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tOnly techno objects can be owned by a house; return if not a techno\n\t*/\n\tif (!PendingObjectPtr->Is_Techno()) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tSelect the house that will own this object\n\t*/\n\tLastHouse = Cycle_House(PendingObjectPtr->Owner(), PendingObject);\n\n\t/*\n\t**\tChange the house\n\t*/\n\ttp = (TechnoClass *)PendingObjectPtr;\n\ttp->House = HouseClass::As_Pointer(LastHouse);\n\n\t/*\n\t**\tSet house variables to new house\n\t*/\n\tPendingHouse = LastHouse;\n}\n\n\n/***************************************************************************\n * MapEditClass::Set_House_Buttons -- toggles house buttons for btn list   *\n *                                                                         *\n * Looks in the given button list for the given GDI, NOD & Neutral button  *\n * id's. Sets the On/Off state of the buttons based on the given house,    *\n * only if that button is found in the list.                               *\n *                                                                         *\n * INPUT:                                                                  *\n *      house            house to set buttons to                           *\n *      btnlist         ptr to button list to search                       *\n *      base_id         button ID for GDI; assumes other id's are sequential*\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/23/1994 BR : Created.                                              *\n *   01/26/1996 JLB : Uses new house selection list method.                *\n *=========================================================================*/\nvoid MapEditClass::Set_House_Buttons(HousesType house, GadgetClass *, int )\n//void MapEditClass::Set_House_Buttons(HousesType house, GadgetClass * btnlist, int base_id)\n{\n\tHouseList->Set_Selected_Index(house);\n\n#ifdef NEVER\n\tHousesType h;\n\tint id;\n\tTextButtonClass * btn;\n\n\t/*\n\t**\tLoop through all houses, searching the button list for each one.\n\t*/\n\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\n\t\t/*\n\t\t**\tCompute the desired button ID; get a pointer to the button\n\t\t*/\n\t\tid = (int)h + base_id;\n\t\tbtn = (TextButtonClass *)btnlist->Extract_Gadget(id);\n\t\tif (btn) {\n\n\t\t\t/*\n\t\t\t**\tIf this house value is the desired one, turn the button on;\n\t\t\t**\totherwise, turn it off.\n\t\t\t*/\n\t\t\tif (h == house) {\n\t\t\t\tbtn->Turn_On();\n\t\t\t} else {\n\t\t\t\tbtn->Turn_Off();\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Trigger_Placement -- enters trigger placement mode  *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Trigger_Placement(void)\n{\n\tSet_Default_Mouse(MOUSE_CAN_MOVE);\n\tOverride_Mouse_Shape(MOUSE_CAN_MOVE);\n}\n\n\n/***************************************************************************\n * MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Stop_Trigger_Placement(void)\n{\n\tCurTrigger = NULL;\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n}\n\n\n/***************************************************************************\n * MapEditClass::Place_Trigger -- assigns trigger to object or cell        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Place_Trigger(void)\n{\n\tObjectClass * object=NULL;\t\t// Generic object clicked on.\n\tint x,y;\n\tCELL cell;\t\t\t\t\t\t\t\t\t// Cell that was selected.\n\n\t/*\n\t**\tSee if an object was clicked on\n\t*/\n\tx = Keyboard->MouseQX;\n\ty = Keyboard->MouseQY;\n\n\t/*\n\t**\tGet cell for x,y\n\t*/\n\tcell = Click_Cell_Calc(x, y);\n\n\t/*\n\t**\tConvert x,y to offset from cell upper-left\n\t*/\n\tx = (x-TacPixelX) % ICON_PIXEL_W;\n\ty = (y-TacPixelY) % ICON_PIXEL_H;\n\n\t/*\n\t**\tGet object at that x,y\n\t*/\n\tobject = Cell_Object(cell, x, y);\n\n\t/*\n\t**\tAssign trigger to an object\n\t*/\n\tAttachType a1 = CurTrigger->Attaches_To();\n\tif (object && (a1 & ATTACH_OBJECT) != 0) {\n\t\tif (CurTrigger) {\n\t\t\tTriggerClass * tt = Find_Or_Make(CurTrigger);\n\t\t\tif (tt) {\n\t\t\t\tobject->Trigger = tt;\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tAssign trigger to a cell\n\t\t*/\n\t\tif ((a1 & ATTACH_CELL) != 0) {\n\t\t\tif (CurTrigger) {\n\t\t\t\tTriggerClass * tt = Find_Or_Make(CurTrigger);\n\t\t\t\tMap[cell].Trigger = tt;\n\t\t\t}\n//\t\t\tCellTriggers[cell] = CurTrigger;\n\t\t}\n\t}\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Start_Base_Building -- starts base-building mode          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Start_Base_Building(void)\n{\n\t/*\n\t** Fully build the base so the user can edit it\n\t*/\n\tBuild_Base_To(100);\n\n\t/*\n\t** Start placement mode\n\t*/\n\tBaseBuilding = true;\n\tStart_Placement();\n\n\t/*\n\t** Force map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Cancel_Base_Building -- stops base-building mode          *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Cancel_Base_Building(void)\n{\n\t/*\n\t** Build the base to the proper amount\n\t*/\n\tBuild_Base_To(Scen.Percent);\n\n\t/*\n\t** Cancel placement mode\n\t*/\n\tCancel_Placement();\n\tBaseBuilding = false;\n\n\t/*\n\t** Force map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Build_Base_To -- builds the AI base to the given percent  *\n *                                                                         *\n * INPUT:                                                                  *\n *      percent      percentage to build base to                           *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Build_Base_To(int percent)\n{\n\tint i;\n\tint num_buildings;\n\tBuildingTypeClass const * objtype;\n\tBuildingClass * obj;\n\n\t//ScenarioInit++;\n\n\t/*\n\t** Completely dismantle the base, so we start at a known point\n\t*/\n\tfor (i = 0; i < Base.Nodes.Count(); i++) {\n\t\tif (Base.Is_Built(i)) {\n\t\t\tobj = Base.Get_Building(i);\n\t\t\tdelete obj;\n\t\t}\n\t}\n\n\t/*\n\t** Compute number of buildings to build\n\t*/\n\tnum_buildings = (Base.Nodes.Count() * percent) / 100;\n\n\t/*\n\t** Build the base to the desired amount\n\t*/\n\tfor (i = 0; i < num_buildings; i++) {\n\t\t/*\n\t\t** Get a ptr to the type of building to build, create one, and unlimbo it.\n\t\t*/\n\t\tobjtype = &BuildingTypeClass::As_Reference(Base.Nodes[i].Type);\n\t\tobj = (BuildingClass *)objtype->Create_One_Of(HouseClass::As_Pointer(Base.House));\n\n\t\t/*\n\t\t** If unlimbo fails, error out\n\t\t*/\n\t\tScenarioInit++;\n\t\tif (!obj->Unlimbo(Cell_Coord(Base.Nodes[i].Cell))) {\n\t\t\tdelete obj;\n\t\t\tWWMessageBox().Process(\"Unable to build base!\");\n\t\t\tScenarioInit--;\n\t\t\treturn;\n\t\t}\n\t\tScenarioInit--;\n\t}\n\n\t//ScenarioInit--;\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MAPEDSEL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDSEL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDSEL.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : November 18, 1994                        *\n *                                                                         *\n *                  Last Update : April 30, 1996 [JLB]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Object-selection & manipulation routines                                *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Change_House -- changes CurrentObject's house           *\n *   MapEditClass::Grab_Object -- grabs the current object                 *\n *   MapEditClass::Move_Grabbed_Object -- moves the grabbed object         *\n *   MapEditClass::Popup_Controls -- shows/hides the pop-up object controls*\n *   MapEditClass::Select_Next -- selects next object on the map           *\n *   MapEditClass::Select_Object -- selects an object for processing       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * Select_Object -- selects an object for processing                       *\n *                                                                         *\n * INPUT:                                                                  *\n *   none.                                                                 *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   0 = object selected, -1 = none                                        *\n *                                                                         *\n * WARNINGS:                                                               *\n *   none.                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/04/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Select_Object(void)\n{\n\tObjectClass\t* object=NULL;\t\t// Generic object clicked on.\n\tint\t\t\tx,y;\n\tCELL\t\t\tcell;\t\t\t\t\t// Cell that was selected.\n\tint\t\t\trc=0;\n\n\t/*\n\t**\tSee if an object was clicked on\n\t*/\n\tx = Keyboard->MouseQX;\n\ty = Keyboard->MouseQY;\n\n\t/*\n\t**\tGet cell for x,y\n\t*/\n\tcell = Click_Cell_Calc(x, y);\n\n\t/*\n\t**\tConvert x,y to offset from cell upper-left\n\t*/\n\tx = (x-TacPixelX) % ICON_PIXEL_W;\n\ty = (y-TacPixelY) % ICON_PIXEL_H;\n\n\t/*\n\t**\tGet object at that x,y\n\t*/\n\tobject = Cell_Object(cell, x, y);\n\n\t/*\n\t**\tIf no object, unselect the current one\n\t*/\n\tif (!object) {\n\t\tif (CurrentObject.Count()) {\n\n\t\t\t/*\n\t\t\t**\tUnselect all current objects\n\t\t\t*/\n\t\t\tUnselect_All();\n\n\t\t\t/*\n\t\t\t**\tTurn off object controls\n\t\t\t*/\n\t\t\tPopup_Controls();\n\t\t}\n\t\trc = -1;\n\t} else {\n\n\t\t/*\n\t\t**\tSelect object only if it's different\n\t\t*/\n\t\tif (!CurrentObject.Count() || (CurrentObject.Count() && object != CurrentObject[0])) {\n\n\t\t\t/*\n\t\t\t**\tUnselect all current objects\n\t\t\t*/\n\t\t\tUnselect_All();\n\t\t\tobject->Select();\n\n\t\t\t/*\n\t\t\t**\tSet mouse shape back to normal\n\t\t\t*/\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL);\n\t\t\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\t\t\t/*\n\t\t\t**\tShow the popup controls\n\t\t\t*/\n\t\t\tPopup_Controls();\n\t\t}\n\t}\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\n\treturn(rc);\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Next -- selects next object on the map             *\n *                                                                         *\n * INPUT:                                                                  *\n *   none.                                                                 *\n *                                                                         *\n * OUTPUT:                                                                 *\n *   none                                                                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *   none.                                                                 *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Select_Next(void)\n{\n\tObjectClass * obj;\n\tCELL obj_cell;\n\tint smap_w;\t\t\t\t\t\t// screen map width in icons\n\tint smap_h;\t\t\t\t\t\t// screen map height in icons\n\tint cell_x;\t\t\t\t\t\t// cell-x of next object\n\tint cell_y;\t\t\t\t\t\t// cell-y of next object\n\tint tcell_x;\t\t\t\t\t// cell-x of TacticalCell\n\tint tcell_y;\t\t\t\t\t// cell-y of TacticalCell\n\n\t/*\n\t**\tGet next object on the map\n\t*/\n\tobj = Map.Next_Object(CurrentObject[0]);\n\n\tif (obj) {\n\t\t/*\n\t\t**\tUnselect current object if there is one\n\t\t*/\n\t\tUnselect_All();\n\n\t \t/*\n\t\t**\tSelect this object\n\t\t*/\n\t\tobj->Select();\n\t}\n\n\t/*\n\t**\tRestore mouse shape to normal\n\t*/\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\t/*\n\t**\tShow pop-up controls\n\t*/\n\tPopup_Controls();\n\n\t/*\n\t**\tMake sure object is shown on the screen\n\t*/\n\t/*\n\t**\tcompute screen map dimensions\n\t*/\n\tsmap_w = Lepton_To_Cell(TacLeptonWidth);\n\tsmap_h = Lepton_To_Cell(TacLeptonHeight);\n\n\t/*\n\t**\tcompute x,y of object's cell\n\t*/\n\tobj_cell = Coord_Cell(CurrentObject[0]->Coord);\n\tcell_x = Cell_X(obj_cell);\n\tcell_y = Cell_Y(obj_cell);\n\ttcell_x = Coord_XCell(TacticalCoord);\n\ttcell_y = Coord_YCell(TacticalCoord);\n\n\t/*\n\t**\tIf object is off-screen, move map\n\t*/\n\tif (cell_x < tcell_x) {\n\t\ttcell_x = cell_x;\n\t} else {\n\t\tif (cell_x >= tcell_x + smap_w) {\n\t\t\ttcell_x = cell_x - smap_w + 1;\n\t\t}\n\t}\n\n\tif (cell_y < tcell_y) {\n\t\ttcell_y = cell_y;\n\t} else {\n\t\tif (cell_y >= tcell_y + smap_h) {\n\t\t\ttcell_y = cell_y - smap_h + 1;\n\t\t}\n\t}\n\n\tScenarioInit++;\n\tSet_Tactical_Position(XY_Coord(Cell_To_Lepton(tcell_x), Cell_To_Lepton(tcell_y)));\n\tScenarioInit--;\n\n\t/*\n\t**\tForce map to redraw\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n}\n\n\n/***************************************************************************\n * MapEditClass::Popup_Controls -- shows/hides the pop-up object controls  *\n *                                                                         *\n * Call this routine whenever the CurrentObject changes. The routine will  *\n * selectively enable or disable the popup controls based on whether       *\n * CurrentObject is NULL, or if it's a Techno object, or what type of      *\n * Techno object it is.                                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1994 BR : Created.                                              *\n *   04/30/1996 JLB : Revamped for new buttons and stuff.                  *\n *=========================================================================*/\nvoid MapEditClass::Popup_Controls(void)\n{\n\tconst TechnoTypeClass * objtype = NULL;\n\tHousesType owner;\t\t\t\t\t\t\t// object's current owner\n\tint mission_index;\t\t\t\t\t\t// object's current mission\n\tint strength;\t\t\t\t\t\t\t\t// object's 0-255 strength value\n\tint i;\n\n\t/*\n\t**\tRemove all buttons from GScreen's button list (so none of them provide\n\t**\tinput any more); then, destroy the list by Zapping each button.  Then,\n\t**\twe'll have to add at least the MapArea button back to the Input button\n\t**\tlist before we return, plus any other buttons to process input for.  We\n\t**\talways must add MapArea LAST in the list, so it doesn't intercept the\n\t**\tother buttons' input.\n\t*/\n\tRemove_A_Button(*HouseList);\n\tRemove_A_Button(*MissionList);\n\tRemove_A_Button(*HealthGauge);\n\tRemove_A_Button(*HealthText);\n\tRemove_A_Button(*FacingDial);\n\tRemove_A_Button(*BaseGauge);\n\tRemove_A_Button(*BaseLabel);\n\tRemove_A_Button(*MapArea);\n\n\tRemove_A_Button(*Sellable);\n\tRemove_A_Button(*Rebuildable);\n\n\t/*\n\t**\tIf no current object, hide the list\n\t*/\n\tif (!CurrentObject.Count()) {\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf not Techno, no need for editing buttons\n\t*/\n\tif (!CurrentObject[0]->Is_Techno()) {\n\t\tAdd_A_Button(*BaseGauge);\n\t\tAdd_A_Button(*BaseLabel);\n\t\tAdd_A_Button(*MapArea);\n\t\treturn;\n\t}\n\n\tobjtype = (TechnoTypeClass const *)&CurrentObject[0]->Class_Of();\n\n\t/*\n\t**\tGet object's current values\n\t*/\n\towner = CurrentObject[0]->Owner();\n\tmission_index = 0;\n\tfor (i = 0; i < NUM_EDIT_MISSIONS; i++) {\n\t\tif (CurrentObject[0]->Get_Mission() == MapEditMissions[i]) {\n\t\t\tmission_index = i;\n\t\t}\n\t}\n\tstrength = CurrentObject[0]->Health_Ratio()*256;\n\n\tswitch (objtype->What_Am_I()) {\n\t\tcase RTTI_VESSELTYPE:\n\t\tcase RTTI_UNITTYPE:\n\t\tcase RTTI_INFANTRYTYPE:\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\tMissionList->Set_Selected_Index(mission_index);\n\t\t\tHealthGauge->Set_Value(strength);\n\t\t\tsprintf(HealthBuf, \"%d\", CurrentObject[0]->Strength);\n\t\t\tFacingDial->Set_Direction(((TechnoClass *)CurrentObject[0])->PrimaryFacing);\n\n\t\t\t/*\n\t\t\t**\tMake the list.\n\t\t\t*/\n\t\t\tAdd_A_Button(*HealthGauge);\n\t\t\tAdd_A_Button(*HouseList);\n\t\t\tHouseList->Set_Selected_Index(owner);\n\t\t\tAdd_A_Button(*MissionList);\n\t\t\tAdd_A_Button(*HealthText);\n\t\t\tAdd_A_Button(*FacingDial);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\tHealthGauge->Set_Value(strength);\n\t\t\tsprintf(HealthBuf, \"%d\", CurrentObject[0]->Strength);\n\t\t\tAdd_A_Button(*HealthGauge);\n\t\t\tAdd_A_Button(*HouseList);\n\t\t\tHouseList->Set_Selected_Index(owner);\n\t\t\tAdd_A_Button(*HealthText);\n\n\t\t\tAdd_A_Button(*Sellable);\n\t\t\tif (((BuildingClass*)CurrentObject[0])->IsAllowedToSell) {\n\t\t\t\tSellable->Turn_On();\n\t\t\t} else {\n\t\t\t\tSellable->Turn_Off();\n\t\t\t}\n\t\t\tAdd_A_Button(*Rebuildable);\n\t\t\tif (((BuildingClass*)CurrentObject[0])->IsToRebuild) {\n\t\t\t\tRebuildable->Turn_On();\n\t\t\t} else {\n\t\t\t\tRebuildable->Turn_Off();\n\t\t\t}\n\n\t\t\tif (objtype->IsTurretEquipped) {\n\t\t\t\tFacingDial->Set_Direction(((TechnoClass *) CurrentObject[0])->PrimaryFacing);\n\t\t\t\tAdd_A_Button(*FacingDial);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tAdd the map area last, so it's \"underneath\" the other buttons, and won't\n\t**\tintercept input for those buttons.\n\t*/\n\tAdd_A_Button(*BaseGauge);\n\tAdd_A_Button(*BaseLabel);\n\tAdd_A_Button(*MapArea);\n}\n\n\n/***************************************************************************\n * MapEditClass::Grab_Object -- grabs the current object                   *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Grab_Object(void)\n{\n\tCELL cell;\n\n\tif (CurrentObject.Count()) {\n\t\tGrabbedObject = CurrentObject[0];\n\n\t\t/*\n\t\t**\tFind out which cell 'ZoneCell' is in relation to the object's current cell\n\t\t*/\n\t\tcell = Coord_Cell(GrabbedObject->Coord);\n\t\tGrabOffset = cell - ZoneCell;\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Move_Grabbed_Object -- moves the grabbed object           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = object moved, -1 = it didn't                                   *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1994 BR : Created.                                              *\n *=========================================================================*/\nint MapEditClass::Move_Grabbed_Object(void)\n{\n\tCOORDINATE new_coord = 0;\n\tint retval = -1;\n\n\t/*\n\t**\tLift up the object\n\t*/\n\tGrabbedObject->Mark(MARK_UP);\n\n\t/*\n\t**\tIf infantry, use a free spot in this cell\n\t*/\n\tif (GrabbedObject->Is_Infantry()) {\n\n\t\tif (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {\n\t\t\tnew_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));\n\n\t\t\t/*\n\t\t\t**\tClear the occupied bit in this infantry's cell.\n\t\t\t*/\n\t\t\t((InfantryClass *)GrabbedObject)->Clear_Occupy_Bit(GrabbedObject->Coord);\n\t\t} else {\n\t\t\tnew_coord = NULL;\n\t\t}\n\n\t} else {\n\n\t\t/*\n\t\t**\tNon-infantry: use cell's center coordinate\n\t\t*/\n\t\tnew_coord = Cell_Coord(ZoneCell + GrabOffset);\n\n\t\tif (GrabbedObject->What_Am_I() == RTTI_BUILDING ||\n\t\t\tGrabbedObject->What_Am_I() == RTTI_TERRAIN) {\n\n\t\t\tnew_coord = Coord_Whole(new_coord);\n\t\t}\n\n\t\t/*\n\t\t**\tTry to place object at new coordinate\n\t\t*/\n\t\tif (GrabbedObject->Can_Enter_Cell(Coord_Cell(new_coord)) != MOVE_OK) {\n\t\t\tnew_coord = NULL;\n\t\t}\n\t}\n\tif (new_coord != NULL) {\n\n\t\t/*\n\t\t** If this object is part of the AI's Base list, change the coordinate\n\t\t** in the Base's Node list.\n\t\t*/\n\t\tif (GrabbedObject->What_Am_I()==RTTI_BUILDING &&\n\t\t\tBase.Get_Node((BuildingClass *)GrabbedObject))\n\t\t\t\tBase.Get_Node((BuildingClass *)GrabbedObject)->Cell = Coord_Cell(new_coord);\n\n\t\tGrabbedObject->Coord = new_coord;\n\t\tretval = 0;\n\t}\n\tGrabbedObject->Mark(MARK_DOWN);\n\n\t/*\n\t**\tFor infantry, set the bit in its new cell marking that spot as occupied.\n\t*/\n\tif (GrabbedObject->Is_Infantry()) {\n\t\t((InfantryClass *)GrabbedObject)->Set_Occupy_Bit(new_coord);\n\t}\n\n\t/*\n\t**\tRe-select the object, and reset the mouse pointer\n\t*/\n\tSet_Default_Mouse(MOUSE_NORMAL);\n\tOverride_Mouse_Shape(MOUSE_NORMAL);\n\n\tFlag_To_Redraw(true);\n\n\treturn(retval);\n}\n\n\n/***************************************************************************\n * MapEditClass::Change_House -- changes CurrentObject's house             *\n *                                                                         *\n * INPUT:                                                                  *\n *      newhouse      house to change to                                   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      1 = house was changed, 0 = it wasn't                               *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/17/1994 BR : Created.                                              *\n *=========================================================================*/\nbool MapEditClass::Change_House(HousesType newhouse)\n{\n\tTechnoClass *tp;\n\n\t/*\n\t**\tReturn if no current object\n\t*/\n\tif (!CurrentObject.Count()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tOnly techno objects can be owned by a house; return if not a techno\n\t*/\n\tif (!CurrentObject[0]->Is_Techno()) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tYou can't change the house if the object is part of the AI's Base.\n\t*/\n\tif (CurrentObject[0]->What_Am_I()==RTTI_BUILDING && Base.Is_Node((BuildingClass *)CurrentObject[0])) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tVerify that the target house exists\n\t*/\n\tif (HouseClass::As_Pointer(newhouse)==NULL) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tVerify that this is a valid owner\n\t*/\n//\tif (!Verify_House(newhouse, &CurrentObject[0]->Class_Of())) {\n//\t\treturn(false);\n//\t}\n\n\t/*\n\t**\tChange the house\n\t*/\n\ttp = (TechnoClass *)CurrentObject[0];\n\ttp->House = HouseClass::As_Pointer(newhouse);\n\n\ttp->IsOwnedByPlayer = false;\n\tif (tp->House == PlayerPtr) {\n\t\ttp->IsOwnedByPlayer = true;\n\t}\n\n\treturn(true);\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MAPEDTM.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPEDTM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MAPEDTM.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 7, 1994                         *\n *                                                                         *\n *                  Last Update : May 7, 1996 [JLB]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MapEditClass::Draw_Member -- Draws a member of the team dialog box.   *\n *   MapEditClass::Handle_Teams -- main team-dialog-handling function      *\n *   MapEditClass::Select_Team -- user selects a team from a list          *\n *   MapEditClass::Team_Members -- user picks makeup of a team             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n#ifdef SCENARIO_EDITOR\n\n\n/***************************************************************************\n * MapEditClass::Handle_Teams -- main team-dialog-handling function        *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid MapEditClass::Handle_Teams(char const * caption)\n{\n\tint rc;\n\n\t/*\n\t**\tTeam dialog processing loop:\n\t**\t- Invoke the team selection dialog. If a team's selected, break\n\t**\t  & return\n\t**\t- If user wants to edit the current team, do so\n\t**\t- If user wants to create new team, new a TeamTypeClass & edit it\n\t**\t- If user wants to delete team, delete the current team\n\t**\t- Keep looping until 'OK'\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tSelect team\n\t\t*/\n\t\trc = Select_Team(caption);\n\n\t\t/*\n\t\t**\t'OK'; break\n\t\t*/\n\t\tif (rc == 0) {\n\t\t\tbreak;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\t'Edit'\n\t\t\t*/\n\t\t\tif (rc == 1 && CurTeam) {\n\t\t\t\tif (CurTeam->Edit()) {\n\t\t\t\t\tChanged = 1;\n\t\t\t\t}\n\t\t\t\tHidPage.Clear();\n\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\tRender();\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\t'New'\n\t\t\t\t*/\n\t\t\t\tif (rc == 2) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate a new team\n\t\t\t\t\t*/\n\t\t\t\t\tCurTeam = new TeamTypeClass();\n\t\t\t\t\tif (CurTeam) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tdelete it if user cancels\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (!CurTeam->Edit()) {\n\t\t\t\t\t\t\tdelete CurTeam;\n\t\t\t\t\t\t\tCurTeam = NULL;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tChanged = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tUnable to create; issue warning\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tWWMessageBox().Process(\"No more teams available.\");\n\t\t\t\t\t\tHidPage.Clear();\n\t\t\t\t\t\tFlag_To_Redraw(true);\n\t\t\t\t\t\tRender();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t'Delete'\n\t\t\t\t\t*/\n\t\t\t\t\tif (rc==3) {\n\t\t\t\t\t\tif (CurTeam) {\n\t\t\t\t\t\t\tDetach_This_From_All(CurTeam->As_Target(), true);\n\t\t\t\t\t\t\tdelete CurTeam;\n\t\t\t\t\t\t\t//CurTeam->Remove();\n\t\t\t\t\t\t\tCurTeam = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * MapEditClass::Select_Team -- user selects a team from a list            *\n *                                                                         *\n *    Ŀ           *\n *                             Teams                                     *\n *        Ŀ               *\n *         Name     House    Class:Count,Class:Count  \u0018               *\n *         Name     House    Class:Count,Class:Count  Ĵ               *\n *         Name     House    Class:Count,Class:Count                  *\n *         Name     House    Class:Count,Class:Count                  *\n *                                                                    *\n *                                                                    *\n *                                                    Ĵ               *\n *                                                    \u0019               *\n *                       *\n *                                                                       *\n *          [Edit]        [New]        [Delete]      [OK]                *\n *                                                                       *\n *               *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, 1 = Edit, 2 = New, 3 = Delete                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      Uses HIDBUFF.                                                      *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1994 BR : Created.                                              *\n *   05/07/1996 JLB : Streamlined and sorted team list.                    *\n *=========================================================================*/\nint MapEditClass::Select_Team(char const * )\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tenum {\n\t\tD_DIALOG_W = 400,\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 250,\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = 0,\t\t\t\t// centered x-coord\n\t\tD_DIALOG_Y = 0,\t\t\t\t// centered y-coord\n//\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT8_H = 11,\t\t\t\t\t\t\t\t\t\t\t\t// ht of 8-pt text\n\t\tD_MARGIN = 25,\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\t\tD_LIST_W = (D_DIALOG_W-(D_MARGIN*2))-20,\n\t\tD_LIST_X = D_DIALOG_X + (D_DIALOG_W-D_LIST_W)/2,\n\t\tD_LIST_Y = D_DIALOG_Y + 20,\n\t\tD_LIST_H = (D_DIALOG_H-50)-D_LIST_Y,\n\n\t\tBUTTON_W = 45,\n\t\tBUTTON_H = 9,\n\n\t\tD_EDIT_W = BUTTON_W,\n\t\tD_EDIT_H = BUTTON_H,\n\t\tD_EDIT_X = D_DIALOG_X + D_DIALOG_W - (((D_EDIT_W+10)*4)+25),\n\t\tD_EDIT_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_EDIT_H,\n\n\t\tD_NEW_W = BUTTON_W,\n\t\tD_NEW_H = BUTTON_H,\n\t\tD_NEW_X = D_EDIT_X + D_EDIT_W + 10,\n\t\tD_NEW_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_NEW_H,\n\n\t\tD_DELETE_W = BUTTON_W,\n\t\tD_DELETE_H = BUTTON_H,\n\t\tD_DELETE_X = D_NEW_X + D_NEW_W + 10,\n\t\tD_DELETE_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_DELETE_H,\n\n\t\tD_OK_W = BUTTON_W,\n\t\tD_OK_H = BUTTON_H,\n\t\tD_OK_X = D_DELETE_X + D_DELETE_W + 10,\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - 20 - D_OK_H,\n\n\t\tTEAMTXT_LEN = 43,\t\t\t\t// max length of a team entry\n\t};\n\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tTEAM_LIST=100,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_NEW,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_OK,\n\t};\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tbool edit_team = false;\t\t\t\t\t\t// true = user wants to edit\n\tbool new_team = false;\t\t\t\t\t\t// true = user wants to new\n\tbool del_team = false;\t\t\t\t\t\t// true = user wants to new\n\tstatic int tabs[] = {35, 60, 80, 100};\t// list box tab stops\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tButtons\n\t*/\n\tGadgetClass * commands = NULL;\t\t\t\t// the button list\n\n\tTListClass<CCPtr<TeamTypeClass> > teamlist (TEAM_LIST,\n\t\tD_LIST_X, D_LIST_Y, D_LIST_W, D_LIST_H,\n\t\tTPF_EFNT | TPF_NOSHADOW,\n\t\tMFCD::Retrieve(\"EBTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"EBTN-DN.SHP\"));\n\n\tTextButtonClass editbtn (BUTTON_EDIT, \"Edit\", TPF_EBUTTON, D_EDIT_X, D_EDIT_Y, D_EDIT_W);\n\tTextButtonClass newbtn (BUTTON_NEW, \"New\", TPF_EBUTTON, D_NEW_X, D_NEW_Y, D_NEW_W);\n\tTextButtonClass deletebtn (BUTTON_DELETE, \"Delete\", TPF_EBUTTON, D_DELETE_X, D_DELETE_Y, D_DELETE_W);\n\tTextButtonClass okbtn (BUTTON_OK, \"OK\", TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W);\n\n\t/*\n\t**\tInitialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tFill in team names\n\t*/\n\tfor (int index = 0; index < TeamTypes.Count(); index++) {\n\t\tteamlist.Add_Item(TeamTypes.Ptr(index));\n\t}\n\n\tPNBubble_Sort(&teamlist[0], teamlist.Count());\n\n\tif (!CurTeam || !CurTeam->IsActive) CurTeam = NULL;\n\n\tif (CurTeam) {\n\t\tteamlist.Set_Selected_Index(CurTeam);\n\t\tCurTeam = teamlist.Current_Item();\n\t} else {\n\t\tteamlist.Set_Selected_Index(0);\n\t\tif (TeamTypes.Count()) {\n\t\t\tCurTeam = teamlist.Current_Item();\n\t\t}\n\t}\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &teamlist;\n\teditbtn.Add_Tail(*commands);\n\tnewbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tInit tab stops for list\n\t*/\n\tteamlist.Set_Tabs(tabs);\n\n\t/*\n\t**\tMain Processing Loop\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed\n\t\t*/\n\t\tif (display /*&& LogicPage->Lock()*/) {\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_TEAM_EDIT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n//\t\t\tLogicPage->Unlock();\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (TEAM_LIST | KN_BUTTON):\n\t\t\t\tCurTeam = teamlist.Current_Item();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\t\t\t\tif (teamlist.Count()) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tedit_team = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tnew_team = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tdel_team = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (edit_team) return(1);\n\tif (new_team) return(2);\n\tif (del_team) return(3);\n\treturn(0);\n}\n\n\n/***************************************************************************\n * MapEditClass::Team_Members -- user picks makeup of a team               *\n *                                                                         *\n * Team members are rendered in a 24 x 24 area; the Window coordinates     *\n * have to be set to this area when the object's 'Display()' routine is    *\n * called. Thus, the dialog's window coords have to be divisible by        *\n * 24. The height of the dialog is computed based on how many objects      *\n * there are in it.                                                        *\n *                                                                         *\n * 10 pixels are left between rows of objects, so the # of that type of    *\n * object can be displayed underneath the object.                          *\n *                                                                         *\n *  Ŀ                    *\n *                   Team Members                                        *\n *                                                                       *\n *    Ŀ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *    Ĵ                      *\n *                                                           *\n *                          *\n *                 [OK]      [Cancel]                                    *\n *                      *\n *                                                                         *\n * INPUT:                                                                  *\n *      house      house to display objects for                            *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = OK, -1 = cancel                                                *\n *                                                                         *\n * WARNINGS:                                                               *\n *      CurTeam must NOT be NULL when this function is called.             *\n *      This routine uses HIDBUFF for data storage.                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1994 BR : Created.                                              *\n *=========================================================================*/\n//#define TEENSY_WEENSY\n/*\n**\tDialog & button dimensions\n*/\nenum {\n\tD_DIALOG_W = 640,\n\tD_DIALOG_X = 0,\n\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\n\n\tD_TXT6_H = 7,\n\tD_MARGIN = 7,\n\n#ifdef TEENSY_WEENSY\n\tD_PICTURE_W = 32,\n\tD_PICTURE_H = 24,\n#else\n\tD_PICTURE_W = 64,\n\tD_PICTURE_H = 48,\n#endif\n\tD_ROW_H = (D_PICTURE_H + 3),\n\n\tD_OK_W = 50,\n\tD_OK_H = 9,\n\tD_OK_X = D_DIALOG_CX - 5 - D_OK_W,\n\tD_OK_Y = 0,\n\n\tD_CANCEL_W = 50,\n\tD_CANCEL_H = 9,\n\tD_CANCEL_X = D_DIALOG_CX + 5,\n\tD_CANCEL_Y = 0,\n\n};\n\nint MapEditClass::Team_Members(HousesType house)\n{\n\t/*\n\t**\tButton enumerations:\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t**\t(highest enum is the lowest layer). Each section of the map checks\n\t**\tthe requested redraw level to see if it's supposed to draw; if it's\n\t**\t>= its level, it redraws.\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\tRedrawType display;\t\t\t\t\t\t\t// requested redraw level\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tKeyNumType input;\t\t\t\t\t\t\t\t// user input\n\tbool cancel = false;\t\t\t\t\t\t\t// true = user cancels\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tTeam display variables\n\t*/\n\tconst TechnoTypeClass **teamclass;\t\t// array of team classes\n\tint *teamcount;\t\t\t\t\t\t\t\t// array of class counts\n\tint numcols;\t\t\t\t\t\t\t\t\t// # units displayed horizontally\n\tint numrows;\t\t\t\t\t\t\t\t\t// # units displayed vertically\n\n\t/*\n\t**\tDialog dimensions.\n\t*/\n\tint dlg_y;\n\tint dlg_h;\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint msg_y;\t\t\t\t\t\t\t\t\t\t// y-coord for object names\n\n\tint curclass = -1;\t\t\t// current index into 'teamclass'; can be invalid!\n\t\t\t\t\t\t\t\t\t\t// (is based on current mouse position)\n\tint numclasses;\t\t\t\t// current # classes in the team (limited to <=5)\n\tint maxclasses;\t\t\t\t// max # classes available\n\tint i,j;\n\n\t/*\n\t**\tValues for timing when mouse held down.\n\t*/\n\tint lheld = 0;\n\tint rheld = 0;\n\tlong tdelay[3] = {5, 20, 0};\n\tint tindex = 0;\n\tlong heldtime;\n\n\t/*\n\t**\tButtons.\n\t*/\n\tControlClass * commands;\n\n\tTextButtonClass okbtn (BUTTON_OK, TXT_OK, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_CENTER | TPF_EFNT | TPF_NOSHADOW, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\t/*\n\t**\tSet up the team data arrays (ObjectTypeClass pointers & count)\n\t*/\n#ifdef WIN32\n\tteamclass = (const TechnoTypeClass **)SysMemPage.Get_Buffer();\n\tteamcount = (int *)SysMemPage.Get_Buffer() + MAX_TEAM_CLASSES * sizeof (ObjectTypeClass *);\n#else\n\tteamclass = (const TechnoTypeClass **)HidPage.Get_Buffer();\n\tteamcount = (int *)HidPage.Get_Buffer() + MAX_TEAM_CLASSES * sizeof (ObjectTypeClass *);\n#endif\n\n\t/*\n\t**\tFill in the ObjectTypeClass array with all available object type ptrs,\n\t**\tchecking to be sure this house can own the object\n\t*/\n\ti = 0;\n\tfor (InfantryType i_id = INFANTRY_FIRST; i_id < INFANTRY_COUNT; i_id++) {\n\t\tteamclass[i] = &InfantryTypeClass::As_Reference(i_id);\n\t\ti++;\n\t}\n\n\tfor (AircraftType a_id = AIRCRAFT_FIRST; a_id < AIRCRAFT_COUNT; a_id++) {\n\t\tteamclass[i] = &AircraftTypeClass::As_Reference(a_id);\n\t\ti++;\n\t}\n\n\tfor (UnitType u_id = UNIT_FIRST; u_id < UNIT_COUNT; u_id++) {\n\t\tteamclass[i] = &UnitTypeClass::As_Reference(u_id);\n\t\ti++;\n\t}\n\n\tfor (VesselType v_id = VESSEL_FIRST; v_id < VESSEL_COUNT; v_id++) {\n\t\tteamclass[i] = &VesselTypeClass::As_Reference(v_id);\n\t\ti++;\n\t}\n\n\t/*\n\t**\tSave max # classes.\n\t*/\n\tmaxclasses = i;\n\n\t/*\n\t**\tFill in the 'count' array with data from the current team:\n\t**\t- For every class in the current team, find that class type in the\n\t**\t  'teamclass' array & set its count value\n\t*/\n\tfor (j = 0; j < maxclasses; j++) {\n\t\tteamcount[j] = 0;\n\t}\n\n\t/*\n\t**\tLoop through all classes in the team.\n\t*/\n\tfor (i = 0; i < CurTeam->ClassCount; i++) {\n\n\t\t/*\n\t\t**\tFind this class in our array.\n\t\t*/\n\t\tfor (j = 0; j < maxclasses; j++) {\n\n\t\t\t/*\n\t\t\t**\tSet the count; detect a match between the team's class & the\n\t\t\t**\t'teamclass' array entry by comparing the actual pointers; typeid\n\t\t\t**\twon't work because E1 & E2 are the same type class.\n\t\t\t*/\n\t\t\tif (CurTeam->Members[i].Class == teamclass[j]) {\n\t\t\t\tteamcount[j] = CurTeam->Members[i].Quantity;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tnumclasses = CurTeam->ClassCount;\n\n\t/*\n\t**\tSet up the dialog dimensions based on number of classes we have to draw\n\t**\n\t**\tCompute picture rows & cols.\n\t*/\n\tnumcols = (D_DIALOG_W - 16) / D_PICTURE_W;\n\tnumrows = (maxclasses + numcols - 1) / numcols;\n\n\t/*\n\t**\tDialog's height = top margin + label + picture rows + margin + label + margin + btn\n\t*/\n\tdlg_h = 400;\n\tdlg_y = 0;\n\tmsg_y = dlg_y+dlg_h - 26 - 15;\n\n\tokbtn.Y = dlg_y + dlg_h - D_MARGIN - D_OK_H - 15;\n\tcancelbtn.Y = dlg_y + dlg_h - D_MARGIN - D_CANCEL_H - 15;\n\n\t/*\n\t**\tDraw to SeenPage.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tMake sure 'house' is valid.\n\t*/\n//\tif (house!=HOUSE_GOOD && house!=HOUSE_BAD && house != HOUSE_MULTI1 &&\n//\t\thouse != HOUSE_MULTI2 && house != HOUSE_MULTI3 && house != HOUSE_MULTI4 ) {\n//\t\tif (Scen.ScenPlayer == SCEN_PLAYER_MPLAYER) {\n//\t\t\thouse = HOUSE_MULTI1;\n//\t\t} else {\n//\t\t\thouse = HOUSE_GOOD;\n//\t\t}\n//\t}\n\n\t/*\n\t**\tCreate the list.\n\t*/\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDisplay the constant background of this dialog.\n\t\t\t\t*/\n\t\t\t\tDialog_Box(D_DIALOG_X, dlg_y, D_DIALOG_W, dlg_h);\n\t\t\t\tDraw_Caption(TXT_TEAM_MEMBERS, D_DIALOG_X, dlg_y, D_DIALOG_W);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the objects.\n\t\t\t\t*/\n\t\t\t\tfor (i = 0; i < maxclasses; i++) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay the object along with any count value for it.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Member(teamclass[i], i, teamcount[i], house);\n\t\t\t\t}\n\n\t\t\t\tif ((unsigned)curclass < maxclasses) {\n\t\t\t\t\tFancy_Text_Print(teamclass[curclass]->Full_Name(),\n\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W / 2, msg_y,\n\t\t\t\t\t\t&ColorRemaps[PCOLOR_BROWN], TBLACK,\n\t\t\t\t\t\tTPF_CENTER|TPF_EFNT|TPF_NOSHADOW);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\t/*\n\t\t\t**\tMouse buttons set or clear 'held' values\n\t\t\t*/\n\t\t\tcase (KN_LMOUSE):\n\t\t\t\tif (curclass >= 0 && curclass < maxclasses) {\n\t\t\t\t\tlheld = 1;\n\t\t\t\t\ttindex = 2;\n\t\t\t\t\theldtime = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RMOUSE):\n\t\t\t\tif (curclass >= 0 && curclass < maxclasses) {\n\t\t\t\t\trheld = 1;\n\t\t\t\t\ttindex = 2;\n\t\t\t\t\theldtime = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_LMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\tlheld = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase ((int)KN_RMOUSE | (int)KN_RLSE_BIT):\n\t\t\t\trheld = 0;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tOK: save values & return.\n\t\t\t*/\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tCancel: abort & return.\n\t\t\t*/\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tcancel = true;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/*\n\t\t\t\t**\tCompute new 'curclass' based on mouse position.\n\t\t\t\t*/\n\t\t\t\ti = (Get_Mouse_X() - 32 - D_DIALOG_X) / D_PICTURE_W +\n\t\t\t\t\t((Get_Mouse_Y() - (dlg_y+8+11)) / D_ROW_H) * numcols;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf it's changed, update class label.\n\t\t\t\t*/\n\t\t\t\tif (i != curclass) {\n\n\t\t\t\t\tcurclass = i;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tClear out the previously printed name of the item.\n\t\t\t\t\t*/\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tLogicPage->Fill_Rect(D_DIALOG_X + 32, msg_y, D_DIALOG_X + D_DIALOG_W - 64, msg_y + D_TXT6_H, BLACK);\n\n\t\t\t\t\tif ((unsigned)curclass < maxclasses) {\n\t\t\t\t\t\tFancy_Text_Print(teamclass[curclass]->Full_Name(),\n\t\t\t\t\t\t\tD_DIALOG_X + D_DIALOG_W / 2, msg_y, scheme, TBLACK, TPF_CENTER|TPF_EFNT|TPF_NOSHADOW);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tForce buttons to not be held.\n\t\t\t\t\t*/\n\t\t\t\t\tlheld = 0;\n\t\t\t\t\trheld = 0;\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tCheck for a 'held' mouse button; if it's down, and the correct\n\t\t**\tamount of time has gone by, increment/decrement the count for the\n\t\t**\tcurrent class.\n\t\t*/\n\t\tif (lheld) {\n\n\t\t\t/*\n\t\t\t**\tThe first time in, TickCount - heldtime will be larger than\n\t\t\t**\ttdelay[2], so we increment the count immediately; then, we decrement\n\t\t\t**\ttindex to go to the next time delay, which is longer; then, decr.\n\t\t\t**\tagain to go to the 1st time delay which is the shortest.\n\t\t\t*/\n\t\t\tif (TickCount - heldtime > tdelay[tindex]) {\n\t\t\t\theldtime = TickCount;\n\t\t\t\tif (tindex) {\n\t\t\t\t\ttindex--;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDetect addition of a new class.\n\t\t\t\t*/\n\t\t\t\tif (teamcount[curclass]==0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDon't allow more classes than we can handle.\n\t\t\t\t\t*/\n\t\t\t\t\tif (numclasses == TeamTypeClass::MAX_TEAM_CLASSCOUNT) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tnumclasses++;\n\t\t\t\t}\n\t\t\t\tteamcount[curclass]++;\n\n\t\t\t\t/*\n\t\t\t\t**\tUpdate number label.\n\t\t\t\t*/\n\t\t\t\tDraw_Member(teamclass[curclass], curclass, teamcount[curclass], house);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif (rheld) {\n\n\t\t\t\t/*\n\t\t\t\t**\tThe first time in, TickCount - heldtime will be larger than\n\t\t\t\t**\ttdelay[2], so we increment the count immediately; then, we decrement\n\t\t\t\t**\ttindex to go to the next time delay, which is longer; then, decr.\n\t\t\t\t**\tagain to go to the 1st time delay which is the shortest.\n\t\t\t\t*/\n\t\t\t\tif (TickCount - heldtime > tdelay[tindex]) {\n\t\t\t\t\tif (tindex) {\n\t\t\t\t\t\ttindex--;\n\t\t\t\t\t}\n\t\t\t\t\theldtime = TickCount;\n\n\t\t\t\t\tif (teamcount[curclass] > 0) {\n\t\t\t\t\t\tteamcount[curclass]--;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDetect removal of a class.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (teamcount[curclass] == 0) {\n\t\t\t\t\t\t\tnumclasses--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tUpdate number label.\n\t\t\t\t\t*/\n\t\t\t\t\tDraw_Member(teamclass[curclass], curclass, teamcount[curclass], house);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCopy data into team.\n\t*/\n\tif (!cancel) {\n\t\tCurTeam->ClassCount = numclasses;\n\t\ti = 0;\t\t// current team class index\n\t\tfor (j = 0; j < maxclasses; j++) {\n\t\t\tif (teamcount[j] > 0) {\n\t\t\t\tCurTeam->Members[i].Quantity = teamcount[j];\n\t\t\t\tCurTeam->Members[i].Class = teamclass[j];\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tRedraw the display.\n\t*/\n\tHidPage.Clear();\n\tFlag_To_Redraw(true);\n\tRender();\n\n\tif (cancel) return(-1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MapEditClass::Draw_Member -- Draws a member of the team dialog box.                         *\n *                                                                                             *\n *    This routine will display the cameo image of the potential team member. In the corner,   *\n *    it will show the current quantity of this member for the current team being edited.      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the member object type.                                        *\n *                                                                                             *\n *          index -- The index into the team dialog box array of selectable objects. This is   *\n *                   used to determine the correct X and Y offsets to draw.                    *\n *                                                                                             *\n *          quant -- The quantity number to display in the corner of the image.                *\n *                                                                                             *\n *          house -- The owner of this object.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MapEditClass::Draw_Member(TechnoTypeClass const * ptr, int index, int quant, HousesType house)\n{\n\tint numcols = (D_DIALOG_W - 64) / D_PICTURE_W;\n\tint col = index % numcols;\n\tint row = index / numcols;\n\tint dlg_y = 0;\n\tint x = D_DIALOG_X + 32 + col * D_PICTURE_W;\n\tint y = dlg_y + 8 + 13 + row * D_ROW_H;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t**\tChange the window to this box.\n\t*/\n\tWindowList[WINDOW_EDITOR][WINDOWX] = x;\n\tWindowList[WINDOW_EDITOR][WINDOWY] = y;\n\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = D_PICTURE_W;\n\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT] = D_PICTURE_H;\n\tChange_Window((int)WINDOW_EDITOR);\n\n\tHide_Mouse();\n\tDraw_Box(x, y, D_PICTURE_W, D_PICTURE_H, BOXSTYLE_DOWN, true);\n\tptr->Display(WinW/2, WinH>>1, WINDOW_EDITOR, house);\n\tif (quant > 0) {\n\t\tFancy_Text_Print(\"%d\", x+1, y+1, scheme, TBLACK, TPF_8POINT|TPF_DROPSHADOW, quant);\n//\t\tFancy_Text_Print(\"%d\", x+1, y+D_PICTURE_H-8, scheme, TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_DROPSHADOW, quant);\n\t}\n\tShow_Mouse();\n}\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MAPSEL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MAPSEL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MAPSEL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Barry W. Green                                               *\n *                                                                                             *\n *                   Start Date : April 17, 1995                                               *\n *                                                                                             *\n *                  Last Update : April 27, 1995   [BWG]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Bit_It_In -- Pixel fade graphic copy.                                                     *\n *   Map_Selection -- Starts the whole process of selecting next map to go to                  *\n *   Print_Statistics -- Prints statistics on country selected                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\nvoid Cycle_Call_Back_Delay(int time, PaletteClass &pal);\nextern int ControlQ;\n\nint Mouse_Over_Spot(int house, int scenario);\nvoid Set_Mouse(MouseType shape, int &start, int &count, int &delay, int &xspot, int &yspot);\n//VG for ant mission progression\nconst char* antmission[] = {NULL, \"SCA01EA.INI\", \"SCA02EA.INI\", \"SCA03EA.INI\", \"SCA04EA.INI\"};\n\nstruct point {\n\tint x;\n\tint y;\n} const MapCoords[2][14][3] = {\n {\n {{185,123},{ -1, -1},{ -1, -1}},\n {{173,112},{ -1, -1},{ -1, -1}},\n {{196,100},{200,112},{ -1, -1}},\n {{175,113},{ -1, -1},{ -1, -1}},\n {{187, 91},{202, 93},{206,105}},\n {{207,161},{212,172},{ -1, -1}},\n {{172, 92},{ -1, -1},{ -1, -1}},\n {{132,119},{146,125},{ -1, -1}},\n {{199, 73},{205, 86},{ -1, -1}},\n {{236,114},{ -1, -1},{ -1, -1}},\n {{219, 64},{225, 76},{ -1, -1}},\n {{256, 69},{ -1, -1},{ -1, -1}},\n {{262, 77},{ -1, -1},{ -1, -1}},\n {{249, 97},{ -1, -1},{ -1, -1}}\n },\n// Soviet coords\n {\n {{178,105},{ -1, -1},{ -1, -1}},\n {{163,101},{163,113},{ -1, -1}},\n {{160, 89},{ -1, -1},{ -1, -1}},\n {{142,101},{142,117},{ -1, -1}},\n {{212,163},{ -1, -1},{ -1, -1}},\n {{155,133},{171,144},{ -1, -1}},\n {{216,103},{ -1, -1},{ -1, -1}},\n {{132,145},{154,154},{ -1, -1}},\n {{122,117},{ -1, -1},{ -1, -1}},\n {{117,130},{ -1, -1},{ -1, -1}},\n {{ 99,107},{109,146},{ -1, -1}},\n {{134,125},{ -1, -1},{ -1, -1}},\n {{ 32,156},{ 46,171},{ -1, -1}},\n {{108, 97},{ -1, -1},{ -1, -1}}\n }\n};\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif  //WIN32\n\n/***********************************************************************************************\n * Map_Selection -- Starts the whole process of selecting next map to go to                    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/18/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nextern int CopyType;\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif\nchar const * Map_Selection(void)\n{\n\treturn NULL;\n#if (0)//PG\n\tstatic char scenarioname[_MAX_FNAME+_MAX_EXT];\n\n#ifdef FIXIT_ANTS\n\tif (AntsEnabled)  {\n\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\tchar buf[10];\n\t\tsprintf(buf, \"%02d\", Scen.Scenario+1);\n\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\treturn(scenarioname);\n\t}\n\n#endif\n\tchar _filename[]=\"MSAA.WSA\";\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\n\n\t_filename[2] = house ? 'S' : 'A';\n\t_filename[3] = Scen.Scenario + 'A';\n\tPaletteClass mappalette;\n\n\tint scenario = Scen.Scenario;\n\tint selection;\n\tstatic CDTimerClass<SystemTimerClass> timer;\n\tint start = 0;\n\tint count = 0;\n\tint delay = 0;\n\tint xspot = 0;\n\tint yspot = 0;\n\n\tvoid const * appear1 =  MFCD::Retrieve(\"MAPWIPE2.AUD\");\n\tvoid const * bleep11  = MFCD::Retrieve(\"BLEEP11.AUD\");\n\tvoid const * country4 = MFCD::Retrieve(\"MAPWIPE5.AUD\");\n\tvoid const * toney7 =   MFCD::Retrieve(\"TONEY7.AUD\");\n\tvoid const * bleep17  = MFCD::Retrieve(\"BLEEP17.AUD\");\n\n\tvoid const * scold1 =   MFCD::Retrieve(\"TONEY4.AUD\");\n\tvoid const * country1 = MFCD::Retrieve(\"TONEY10.AUD\");\n\n#ifdef WIN32\n\tGraphicBufferClass *pseudoseenbuff = new GraphicBufferClass(320, 200, (void*)NULL);\n#endif\n\n//\tfixed oldvolume = Options.ScoreVolume;\n//\tOptions.Set_Score_Volume(fixed(4, 10));\n\tTheme.Queue_Song(THEME_MAP);\n\n\tvoid *anim = Open_Animation(_filename, NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), mappalette);\n\n\tKeyboard->Clear();\n\tSeenPage.Clear();\n\tmappalette.Set(FADE_PALETTE_FAST, Call_Back);\n\n#ifdef WIN32\n\tpseudoseenbuff->Clear();\n\tAnimate_Frame(anim, *pseudoseenbuff, 1);\n\tfor(int x=0; x<256; x++) memset(&PaletteInterpolationTable[x][0],x,256);\n\tCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , 0);\n#else\n\tHidPage.Clear();\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\n\n\tint frame = 1;\n\tStreamLowImpact = true;\n#ifdef WIN32\n\tPlay_Sample(appear1, 255, Options.Normalize_Volume(170));\n#else\n\tPlay_Sample(appear1, 255, Options.Normalize_Volume(55));\n#endif\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n#ifdef WIN32\n\t\tCopyType = 1;\n\t\tAnimate_Frame(anim, *pseudoseenbuff, frame++);\n\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\tCopyType = 0;\n#else\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n#endif\n\t\tCall_Back_Delay(2);\n\t\tswitch(frame) {\n\t\t\tcase 16:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(bleep11, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(bleep11, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 30:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(country4, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(country4, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 51:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(toney7, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(toney7, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t\tcase 61:\n#ifdef WIN32\n\t\t\t\tPlay_Sample(bleep17, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\tPlay_Sample(bleep17, 255, Options.Normalize_Volume(55));\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tStreamLowImpact = false;\n\tCall_Back();\n\tClose_Animation(anim);\n\tShow_Mouse();\n\tKeyboard->Clear();\n\n\tbool done = 0;\n\tMouseType shape = MOUSE_NORMAL;\n\twhile (!done) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tCopyType = 1;\n\t\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\t\tCopyType = 0;\n\t\t}\n#endif\n\t\tCycle_Call_Back_Delay(1, mappalette);\n\t\tint choice = Mouse_Over_Spot(house, scenario);\n\t\tif (choice == -1) {\n\t\t\tshape = MOUSE_NORMAL;\n\t\t} else {\n\t\t\tshape = MOUSE_CAN_ATTACK;\n\t\t}\n\n\t\tSet_Mouse(shape, start, count, delay, xspot, yspot);\n\t\tif (timer == 0) {\n\t\t\tframe++;\n\t\t\tframe %= count;\n\t\t\ttimer = delay;\n\t\t\tSet_Mouse_Cursor(xspot, yspot, Extract_Shape(MouseClass::MouseShapes, start + frame));\n\t\t}\n\t\tif (Keyboard->Check()) {\n\t\t\tif ((Keyboard->Get() & 0x10FF) == KN_LMOUSE) {\n\t\t\t\tif (choice != -1) {\n\t\t\t\t\tdone = 1;\n\t\t\t\t\tselection = choice;\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(country1, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\t\tPlay_Sample(country1, 255, Options.Normalize_Volume(50));\n#endif\n\t\t\t\t} else {\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(scold1, 255, Options.Normalize_Volume(170));\n#else\n\t\t\t\t\tPlay_Sample(scold1, 255, Options.Normalize_Volume(50));\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tHide_Mouse();\n\n\t/*\n\t** Restore the mouse to normal shape before leaving this routine.\n\t*/\n\tSet_Mouse(MOUSE_NORMAL, start, count, delay, xspot, yspot);\n\tSet_Mouse_Cursor(xspot, yspot, Extract_Shape(MouseClass::MouseShapes, start));\n\n\tKeyboard->Clear();\n//\tBlackPalette.Set(FADE_PALETTE_SLOW, Call_Back);\n//\tSeenPage.Clear();\n\n\tFancy_Text_Print(TXT_STAND_BY, 160 * RESFACTOR, 190 * RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\n\t/*\n\t**\tCreate the new scenario filename from the selection. The filename is\n\t**\tderived from the previous filename but it has the scenario number\n\t**\tincremented and the chosen variation set.\n\t*/\n\n\t//V.G. added so Ant Missions would progress\n\tif(Scen.ScenarioName[2] == 'A'){\n\t   int antnum = Scen.Scenario++;\t\n\t   if(antnum > 4) antnum = 1;\t\n\t   strcpy(scenarioname, antmission[antnum]);\n\t}\n\telse{\n\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\tchar buf[10];\n\t\tsprintf(buf, \"%02d\", Scen.Scenario+1);\n\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\tscenarioname[6] = 'A' + selection;\n\t}\n\tTheme.Fade_Out();\n//\tOptions.Set_Score_Volume(oldvolume);\n\n//\tScen.ScenVar = (ScenarioVarType)selection;\n//Mono_Printf(\"Chose variant %d  \\n\", selection);\n\treturn(scenarioname);\n#endif\n}\n\nint Mouse_Over_Spot(int house, int scenario)\n{\n\tint retval = -1;\n\tfor (int selection = 0; selection < 3 && MapCoords[house][scenario][selection].x != -1; selection++) {\n\t\tint mousex = Get_Mouse_X() / RESFACTOR;\n\t\tint mousey = Get_Mouse_Y() / RESFACTOR;\n\t\tif (mousex >= MapCoords[house][scenario][selection].x &&\n\t\t\t mousey >= MapCoords[house][scenario][selection].y &&\n\t\t\t mousex <= MapCoords[house][scenario][selection].x+11 &&\n\t\t\t mousey <= MapCoords[house][scenario][selection].y+9) {\n\n\t\t\tretval = selection;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(retval);\n}\nvoid Cycle_Call_Back_Delay(int time, PaletteClass &pal)\n{\n\tstatic CDTimerClass<SystemTimerClass> _ftimer;\n\tstatic bool _up = false;\n\tstatic int val = 255;\n\n\twhile(time--) {\n\t\t/*\n\t\t**\tProcess the fading white color.\n\t\t*/\n\t\tif (!_ftimer) {\n\t\t\t_ftimer = TIMER_SECOND/6;\n\n\t\t\t#define\tSTEP_RATE\t20\n\t\t\tif (_up) {\n\t\t\t\tval += STEP_RATE;\n\t\t\t\tif (val > 150) {\n\t\t\t\t\tval = 150;\n\t\t\t\t\t_up = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval -= STEP_RATE;\n\t\t\t\tif (val < 0x20) {\n\t\t\t\t\tval = 0x20;\n\t\t\t\t\t_up = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tSet the pulse color as the proportional value between white and the\n\t\t\t**\tminimum value for pulsing.\n\t\t\t*/\n\t\t\tpal[254] = GamePalette[WHITE];\n\t\t\tpal[254].Adjust(val, BlackColor);\n\n\t\t\tpal.Set();\n\t\t}\n\t\tCall_Back_Delay(1);\n\t}\n}\n\nvoid Set_Mouse(MouseType shape, int &start, int &count, int &delay, int &xspot, int &yspot)\n{\n\tswitch(shape) {\n\t\tcase MOUSE_NORMAL:\n\t\t\tstart = 0;\n\t\t\tcount = 1;\n\t\t\tdelay = 0;\n\t\t\txspot = 0;\n\t\t\tyspot = 0;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstart = 21;\n\t\t\tcount = 8;\n\t\t\tdelay = 4;\n\t\t\txspot = 14;\n\t\t\tyspot = 11;\n\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "REDALERT/MCI.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/****************************************************************************\n*\n* FILE\n*     MCI.cpp\n*\n* DESCRIPTION\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     6/22/98\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include \"mci.h\"\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceCount()\n*\n* DESCRIPTION\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Count - Number of MCI device entries\n*\n****************************************************************************/\n\nunsigned int MCI::GetDeviceCount(void)\n\t{\n\tMCIERROR rc;\n\tMCI_SYSINFO_PARMS sysInfo;\n\tunsigned int count;\n\n\tmemset(&sysInfo, 0, sizeof(sysInfo));\n\tsysInfo.lpstrReturn = (LPSTR)&count;\n\tsysInfo.dwRetSize = sizeof(count);\n\n\trc = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,\n\t\t\tMCI_WAIT | MCI_SYSINFO_QUANTITY, (DWORD)&sysInfo);\n\n\tif (rc)\n\t\treturn 0;\n\n\treturn count;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceName(entry, name)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Entry - Entry number to get name for.\n*     Name  - On return; device entry name\n*\n* RESULT\n*     Success - Success / Failure flag\n*\n****************************************************************************/\n\nbool MCI::GetDeviceName(unsigned int item, char* buffer)\n\t{\n\tMCIERROR rc;\n\tMCI_SYSINFO_PARMS sysInfo;\n\n\t// Get device name\n\tmemset(&sysInfo, 0, sizeof(sysInfo));\n\tsysInfo.lpstrReturn = (LPSTR)buffer;\n\tsysInfo.dwRetSize = 63;\n\tsysInfo.dwNumber = item;\n\n\trc = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,\n\t\t\tMCI_WAIT | MCI_SYSINFO_NAME, (DWORD)&sysInfo);\n\n\tif (rc)\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetProductName(MCIDEVICEID id, char* buffer)\n\t{\n\tMCIERROR rc;\n\tMCI_INFO_PARMS info;\n\n\t// Get device product name\n\tmemset(&info, 0, sizeof(info));\n\tinfo.lpstrReturn = (LPSTR)buffer;\n\tinfo.dwRetSize = 63;\n\n\trc = mciSendCommand(id, MCI_INFO, MCI_WAIT | MCI_INFO_PRODUCT,\n\t\t\t(DWORD)&info);\n\n\tif (rc)\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     OpenDevice(name)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Name - Device name to open\n*\n* RESULT\n*     DeviceID - ID of opened device, 0 if error.\n*\n****************************************************************************/\n\nMCIDEVICEID MCI::OpenDevice(const char* name)\n\t{\n\tMCIERROR rc;\n\tMCI_OPEN_PARMS open;\n\n\tmemset(&open, 0, sizeof(open));\n\topen.lpstrDeviceType = name;\n\n\trc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE, (DWORD)&open);\n\n\tif (rc)\n\t\treturn 0;\n\n\treturn (open.wDeviceID);\n\t}\n\n\nvoid MCI::CloseDevice(MCIDEVICEID id)\n\t{\n\tMCI_GENERIC_PARMS close;\n\n\tclose.dwCallback = (DWORD)NULL;\n\t\n\tif (id)\n\t\tmciSendCommand(id, MCI_CLOSE, MCI_WAIT, (DWORD)&close);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     GetDeviceDescription\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetDeviceDescription(const char* name, MCIDevice* caps)\n\t{\n\tMCIDEVICEID id;\n\tunsigned long result;\n\n\t// Copy the name\n\tstrncpy(caps->name, name, 63);\n\n\tif ((id = OpenDevice(name)) == 0)\n\t\treturn false;\n\n\t// Get device product name\n\tGetProductName(id, caps->description);\n\n\t// Get device type\n\tif (GetCapability(id, MCI_GETDEVCAPS_DEVICE_TYPE, &result))\n\t\tcaps->type = result;\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_EJECT, &result))\n\t\tcaps->canEject = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_PLAY, &result))\n\t\tcaps->canPlay = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_RECORD, &result))\n\t\tcaps->canRecord = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_CAN_SAVE, &result))\n\t\tcaps->canSave = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_COMPOUND_DEVICE, &result))\n\t\tcaps->usesDevElem = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_HAS_AUDIO, &result))\n\t\tcaps->hasAudio = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_HAS_VIDEO, &result))\n\t\tcaps->hasVideo = ((result) ? true : false);\n\n\tif (GetCapability(id, MCI_GETDEVCAPS_USES_FILES, &result))\n\t\tcaps->reqElemFile = ((result) ? true : false);\n\n\tCloseDevice(id);\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCI::GetCapability(MCIDEVICEID id, unsigned long capItem,\n\t\tunsigned long* result)\n\t{\n\tMCIERROR rc;\n\tMCI_GETDEVCAPS_PARMS devCaps;\n\n\tmemset(&devCaps, 0, sizeof(devCaps));\n\tdevCaps.dwItem = capItem;\n\trc = mciSendCommand(id, MCI_GETDEVCAPS, MCI_WAIT|MCI_GETDEVCAPS_ITEM,\n\t\t(DWORD)&devCaps);\n\n\tif (rc)\n\t\treturn false;\n\n\t*result = devCaps.dwReturn;\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nconst char* MCI::GetDeviceTypeName(unsigned long type)\n\t{\n\tstatic struct _DeviceType {unsigned long typeID; const char* typeName;}\n\t\t_deviceTypeNames[] =\n\t\t{\n\t\t\t{MCI_DEVTYPE_ANIMATION, \"Animation\"},\n\t\t\t{MCI_DEVTYPE_CD_AUDIO, \"CD Audio\"},\n\t\t\t{MCI_DEVTYPE_DAT, \"DAT\"},\n\t\t\t{MCI_DEVTYPE_DIGITAL_VIDEO, \"Digital Video\"},\n\t\t\t{MCI_DEVTYPE_OTHER, \"Other\"},\n\t\t\t{MCI_DEVTYPE_OVERLAY, \"Overlay\"},\n\t\t\t{MCI_DEVTYPE_SCANNER, \"Scanner\"},\n\t\t\t{MCI_DEVTYPE_SEQUENCER, \"MIDI Sequencer\"},\n\t\t\t{MCI_DEVTYPE_VCR, \"VCR\"},\n\t\t\t{MCI_DEVTYPE_VIDEODISC, \"VideoDisc\"},\n\t\t\t{MCI_DEVTYPE_WAVEFORM_AUDIO, \"Wave Audio\"},\n\t\t\t{0, NULL},\n\t\t};\n\n\tint i = 0;\n\n\twhile (_deviceTypeNames[i].typeID != 0)\n\t\t{\n\t\tif (_deviceTypeNames[i].typeID == type)\n\t\t\treturn _deviceTypeNames[i].typeName;\n\n\t\ti++;\n\t\t}\n\n\treturn NULL;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     MCIEnumerate(callack, context)\n*\n* DESCRIPTION\n*\n* INPUTS\n*     Callback -\n*     Context  -\n*\n* RESULT\n*     Success - Success / Failure flag\n*\n****************************************************************************/\n\nbool MCI::EnumerateDevices(MCIEnumCB* callback, void* context)\n\t{\n\tDWORD count;\n\tDWORD i;\n\tchar name[64];\n\tMCIDevice device;\n\n\t// Get the number of devices\n\tcount = GetDeviceCount();\n\n\t// Do for each device\n\tfor (i = 1; i <= count; i++)\n\t\t{\n\t\tGetDeviceName(i, name);\n\t\tmemset(&device, 0, sizeof(device));\n\n\t\tif (GetDeviceDescription(name, &device))\n\t\t\t{\n\t\t\tif (!callback(&device, context))\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n#endif // MCIMPEG\n\n"
  },
  {
    "path": "REDALERT/MCI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef _MCI_H_\n#define _MCI_H_\n/****************************************************************************\n*\n* FILE\n*     MCI.H\n*\n* DESCRIPTION\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     6/22/98\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include <windows.h>\n#include <mmsystem.h>\n#include <digitalv.h>\n#include \"watcom.h\"\n\n/* MCIDevice - MCI device capabilities and description\n *\n * name        - Name used to open device.\n * description - Product description\n * type        - Device type\n * canEject    - Can eject media flag\n * canPlay     - Can playback media\n * canRecord   - Can record media\n * canSave     - Can save media\n * usesDevElem - Uses device element\n * hasAudio    - Media supports audio\n * hasVideo    - Media supports video\n * reqElemFile - Requires element file\n */\ntypedef struct _MCIDevice\n\t{\n\tchar name[64];\n\tchar description[64];\n\tunsigned long type;\n\tbool canEject;\n\tbool canPlay;\n\tbool canRecord;\n\tbool canSave;\n\tbool usesDevElem;\n\tbool hasAudio;\n\tbool hasVideo;\n\tbool reqElemFile;\n\t} MCIDevice;\n\n/* MCI enumeration callback definition */\ntypedef bool (MCIEnumCB)(MCIDevice* desc, void*);\n\nclass MCI\n\t{\n\tpublic:\n\t\t// Open MCI device\n\t\tMCIDEVICEID OpenDevice(const char* name);\n\t\tvoid CloseDevice(MCIDEVICEID id);\n\n\t\t// Enumerate devices\n\t\tbool EnumerateDevices(MCIEnumCB* callback, void* context);\n\n\t\t// Get number of MCI devices name in registry or [MCI] section\n\t\t// of system.ini\n\t\tunsigned int GetDeviceCount(void);\n\n\t\t// Get device name from registry or [MCI] section of system.ini\n\t\tbool GetDeviceName(unsigned int item, char* buffer);\n\n\t\t// Get general device description\n\t\tbool GetDeviceDescription(const char* name, MCIDevice* caps);\n\n\t\t// Get type name (IE: Digital Video) from type ID (IE: MCI_DEVTYPE_DIGITAL_VIDEO)\n\t\tconst char* GetDeviceTypeName(unsigned long type);\n\n\t\t// Get device product name\n\t\tbool GetProductName(MCIDEVICEID id, char* buffer);\n\n\t\t// Get device capability\n\t\tbool GetCapability(MCIDEVICEID id, unsigned long capItem,\n\t\t\t\tunsigned long* result);\n\t};\n\n#endif // MCIMPEG\n#endif // _MCI_H_\n"
  },
  {
    "path": "REDALERT/MCIMOVIE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include \"mcimovie.h\"\n#include <memory.h>\n\n/****************************************************************************\n*\n*\tNAME\n*     MCIMovie - Constructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*     HInstance - Application instance handle\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMCIMovie::MCIMovie(HWND mainWindow)\n\t: mMainWindow(mainWindow), mMCIWindow(NULL), mName(NULL), mDeviceID(0)\n\t{\n\tmWidth = mHeight = 0;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     ~MCIMovie - Destructor\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nMCIMovie::~MCIMovie()\n\t{\n\t// Stop any playing movie\n\tClose();\n\n\t// Free name\n\tif (mName != NULL)\n\t\tfree(mName);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Open()\n*\n* DESCRIPTION\n*     Open the media file in preparation for playback.\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Open(const char* name, const char* device)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_RECT_PARMS rectParm;\n\tMCI_BREAK_PARMS breakParm;\n\n\t// Stop any currently playing movie\n\tClose();\n\n\t// Copy the movie name for our use\n\tif (mName != NULL)\n\t\tfree(mName);\n\n\tmName = strdup(name);\n\n\tif (device == NULL)\n\t\tdevice = \"mpegvideo\";\n\t\t\n\t// Setup open parameters\n\tmemset((void*)&mOpenParm, 0, sizeof(mOpenParm));\n\tmOpenParm.dwCallback = NULL;\n\tmOpenParm.lpstrDeviceType = device;\n\tmOpenParm.lpstrElementName = name;\n\n\trc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE |\n\t\tMCI_OPEN_ELEMENT, (DWORD)&mOpenParm);\n\t\t\t\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\t// Set device ID\n\tmDeviceID = mOpenParm.wDeviceID;\n\n\t// Retrieve movie dimensions\n\trectParm.dwCallback = NULL;\n\n\trc = mciSendCommand(mDeviceID, MCI_WHERE, MCI_WAIT | MCI_DGV_WHERE_SOURCE,\n\t\t\t(DWORD)&rectParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\tmWidth = rectParm.rc.right - rectParm.rc.left;\n\tmHeight = rectParm.rc.bottom - rectParm.rc.top;\n\n\t// Set break key to escape\n \tbreakParm.dwCallback = NULL;\n\tbreakParm.nVirtKey = VK_ESCAPE;\n\tbreakParm.hwndBreak = mMainWindow;\n\t\n\trc = mciSendCommand(mDeviceID, MCI_BREAK, MCI_WAIT | MCI_BREAK_HWND |\n\t\tMCI_BREAK_KEY, (DWORD)&breakParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\t}\n\t\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Play - Play the specified movie.\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Play(HWND window)\n\t{\n\tMCIERROR rc;\n\t\n\tif (mDeviceID == 0)\n\t\treturn false;\n\t\t\n\t// Provide window for playback\n\tif (AttachWindow(window))\n\t\t{\n\t\t// Size the video area\n\t\tif (SizeDestination())\n\t\t\t{\n\t\t\t// Start playing\n\t\t\tmemset((void*)&mPlayParm, 0, sizeof(mPlayParm));\n\t\t\tmPlayParm.dwCallback = NULL;\n\n\t\t\trc = mciSendCommand(mDeviceID, MCI_PLAY, MCI_WAIT, (DWORD)&mPlayParm);\n\n\t\t\tif (rc)\n\t\t\t\t{\n\t\t\t\tchar buffer[512];\n\t\t\t\tmciGetErrorString(rc, buffer, 512);\n\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tClose();\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Pause\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Pause(void)\n\t{\n\tif (mDeviceID == 0)\n\t\treturn false;\n\n\tif (mciSendCommand(mDeviceID, MCI_PAUSE, 0, (DWORD)NULL))\n\t\treturn false;\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Stop\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*     Success - Success/Failure flag\n*\n****************************************************************************/\n\nbool MCIMovie::Close(void)\n\t{\n\tMCIERROR rc;\n\t\n\tif (mDeviceID == 0)\n\t\treturn false;\n\n\trc = mciSendCommand(mDeviceID, MCI_CLOSE, 0, (DWORD)NULL);\n\tmDeviceID = 0;\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     SizeDestination\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCIMovie::SizeDestination(void)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_PUT_PARMS putParm;\n\tRECT rect;\n\n\tif (mMCIWindow == NULL)\n\t\treturn false;\n\n\tGetClientRect(mMCIWindow, &rect);\n\tClientToScreen(mMCIWindow, (LPPOINT)&rect);\n\tClientToScreen(mMCIWindow, (LPPOINT)&rect + 1);\n\n\tputParm.dwCallback = NULL;\n\tputParm.rc.left = rect.left;\n\tputParm.rc.top = rect.top;\n\tputParm.rc.right = rect.right;\n\tputParm.rc.bottom = rect.bottom;\n\n\trc = mciSendCommand(mDeviceID, MCI_PUT, MCI_WAIT | MCI_DGV_RECT |\n\t\tMCI_DGV_PUT_DESTINATION, (DWORD)&putParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     AttachWindow\n*\n* DESCRIPTION\n*\n* INPUTS\n*\n* RESULT\n*\n****************************************************************************/\n\nbool MCIMovie::AttachWindow(HWND window)\n\t{\n\tMCIERROR rc;\n\tMCI_DGV_WINDOW_PARMS winParm;\n\n\tmMCIWindow = window;\n\n\tmemset((void*)&winParm, 0, sizeof(winParm));\n\twinParm.dwCallback = NULL;\n\twinParm.hWnd = window;\n\twinParm.nCmdShow = SW_SHOW;\n\n\trc = mciSendCommand(mDeviceID, MCI_WINDOW, MCI_WAIT| MCI_DGV_WINDOW_HWND |\n\t\t\tMCI_DGV_WINDOW_STATE, (DWORD)&winParm);\n\n\tif (rc)\n\t\t{\n\t\tchar buffer[512];\n\t\tmciGetErrorString(rc, buffer, 512);\n\t\treturn false;\n\t\t}\n\n\treturn true;\n\t}\n\n#endif // MCIMPEG\n\n"
  },
  {
    "path": "REDALERT/MCIMOVIE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef _MCIMOVIE_H_\n#define _MCIMOVIE_H_\n\n#include \"function.h\"\n\n#ifdef MCIMPEG\n#include <windows.h>\n#include <windowsx.h>\n#include <mmsystem.h>\n#include <digitalv.h>\n#include \"watcom.h\"\n\nclass MCIMovie\n\t{\n\tpublic:\n\t\tMCIMovie(HWND mainWindow);\n\t\t~MCIMovie();\n\n\t\tbool Open(const char* name, const char* device);\n\t\tbool Play(HWND window);\n\t\tbool Pause(void);\n\t\tbool Close(void);\n\n\t\tLONG GetWidth(void)\n\t\t\t{return ((mDeviceID) ? mWidth : 0);}\n\n\t\tLONG GetHeight(void)\n\t\t\t{return ((mDeviceID) ? mHeight : 0);}\n\n\tprotected:\n\t\tHWND mMainWindow; // Application window\n\t\tHWND mMCIWindow; // Callback window\n\t\tchar *mName;\n\t\tUINT mDeviceID;\n\t\tMCI_OPEN_PARMS mOpenParm;\n\t\tMCI_PLAY_PARMS mPlayParm;\n\n\t\t// Video stream dimension\n\t\tLONG mWidth, mHeight;\n\n\tprivate:\n\t\tbool SizeDestination(void);\n\t\tbool AttachWindow(HWND window);\n\n\t\tstatic int mRegistered;\n\t\tstatic WNDCLASS mWndClass;\n\t\tstatic HINSTANCE mInstance;\n\t};\n\n#endif // MCIMPEG\n#endif // _MCIMOVIE_H_\n"
  },
  {
    "path": "REDALERT/MEMCHECK.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#\n\n                    MemCheck 3.0 Professional for DOS\n\n            Copyright (c) 1990-1994, StratosWare Corporation.  \n                           All rights reserved.\n\n                             1-800-WE-DEBUG\n\n        Note to Developers:\n        --------------------\n        This file should be #included AFTER any other #includes in\n        each source file which is to be memory checked, and BEFORE\n        any code that performs any operations on allocated pointers.\n        If it isn't, MemCheck will not pick up source file and line\n        information for intercepted functions. \n\n        The MCCONFIG.EXE utility distributed with MemCheck 3.0\n        will do this safely and quickly for you.\n\n        Most specifically, this header file MUST NOT come before\n        any prototypes of routines that MemCheck intercepts, like\n        malloc(), free(), strcpy(), and so on.\n\n        The Final Cut:\n        ---------------\n        To ENTIRELY remove MemCheck from your code, just #define\n        the constant \"NOMEMCHECK\", or equivalently, \"NOMC\".\n        \n        This header file will then automatically 'evaporate' all \n        MemCheck 3.0 calls.  This is MUCH PREFERABLE to placing \n        #if-#endif's around the header file's inclusion, as in\n\n                    #ifdef DEBUG        // DON'T DO THIS!\n                    #include <memcheck.h>\n                    #endif\n\n        Using the \"#ifdef DEBUG\" as above doesn't allow the\n        MemCheck header file to evaporate the MemCheck 3.0 API\n        calls you may have placed in your code, like mc_startcheck()\n        and mc_endcheck().  You would then have to surround\n        each MemCheck API call with additional #if-#endif's.\n\n    Modification History\n\n    WHO     WHEN        WHAT\n    KWB     07/28/93    Gussy for beta\n    KWB     09/11/93    Add new placement overload, NEW() C++ stuff\n    KWB     11/08/93    Final QA/QC for initial release\n    KWB     12/02/93    LINT -save added\n    KWB     02/19/94    Fixed function inlining holes, added macros\n                        for underscore func variants under MSC 7+\n    KWB     07/08/94    Added defines for BC extender (_CC_POWERPACK_)\n    KWB     07/09/94    Added special case for STACKTOP, END under PowerPack\n    KWB     08/04/94    Added cdecl modifier to stklen, atopsp etc. decls\n    KWB     08/11/94    Associated _CC32_ with _PROTECTED_ in ccdefs section;\n                        Changed method of determining compiler model,\n                        e.g. _CC_MSC6_ from if == to if >=\n                        Associated DOSX286 with _PROTECTED_ for Phar Lap\n                        Added MC_SET_EXCEPTF, mc_set/get_exceptf()\n    KWB     08/17/94    Added new[] support filtering (_CPP_ANSI20_)\n    KWB     08/18/94    Changed _MCFARCALL to _MCFARGLUE \n    KWB     09/13/94    Added erf_printf as alias for erf_stdout\n    KWB     09/14/94    Added endf_summary\n    KWB     09/21/94    Added MCCRITF and mc_set_critf() & related\n    KWB     10/10/94    Added #if !defined(setmem) etc. for BC DPMI32\n    KWB     10/11/94    Added _CC_BORLANDx_ comp def, 'x' = major ver\n\n*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n\n/* Avoid multiple inclusions */\n#ifndef _MEMCHECK_H_\n#define _MEMCHECK_H_\n\n/* Prevent inclusion in Windows(tm) compilations */\n#if defined(_Windows) || defined(WINDOWS) || defined(_WINDOWS)\n#   if !defined (__DPMI16__) && !defined (__DPMI32__) && !defined (DOSX286)\n#       error DOS version of MemCheck header file #included!\n#   endif\n#endif\n\n/* Shorthand equivalence, V2.0 backwards compatibility... */\n#if defined (NOMC) || defined (NOMEMCHK)\n#   define NOMEMCHECK\n#endif\n\n/*  C++ new interception -- see note later and\n    read the MemCheck 3.0 User's Manual, section\n    \"Integration With C++.\"  Uncommenting the next line\n    and following simple instructions allows seamless\n    transmission of the exact file and line location\n    of new's in your source code.\n*/\n/*  #define NEW_OVERLOADED  */\n\n\n/* *** Backwards compatibility with V2.0 *** */\n\n#define mc_isactive         mc_is_active    /* standardize naming... */\n#define mc_getmode          mc_get_mode\n#define mc_errorstatus      mc_error_flags\n#define mc_verify_memory    mc_check_buffers\n\n#define MC_USEDISK          MC_USING_DISK\n#define MC_USEMEM           MC_USING_MEMORY\n\n\n/* *** Backwards compatibility with V2.1 *** */\n\n#define MCLINENO            MCSL            /* \"MemCheck Source Line\" */\n#define MFUNC               ERF             /* error reporting function */\n\n#define mc_set_msgfunc      mc_set_erf      /* \"Message funcs\" are now    */\n#define mc_get_msgfunc      mc_get_erf      /* universally referred to as */\n#define mc_error_status     mc_error_flags  /* \"error reporting functions\"*/\n\n/*  Maintain source code compatibility with version 2.1.\n    Buffer registration is simplified to\n    just calling \"mc_register\", regardless of model.  \n    Same with buffer checking, e.g. \"mc_check_far\" \n    and \"mc_check_near\" are rolled into \"mc_check\". \n*/\n#define mc_register_near(p,s)   mc_register((void _MCFAR *)(p),s)\n#define mc_register_far(p,s)    mc_register((void _MCFAR *)(p),s)\n#define mc_unregister_near(p)   mc_unregister((void _MCFAR *)(p))\n#define mc_unregister_far(p)    mc_unregister((void _MCFAR *)(p))\n#define mc_check_near(p)        mc_check((void _MCFAR *)(p))\n#define mc_check_far(p)         mc_check((void _MCFAR *)(p))\n\n/*  Error Number Definitions\n    Returned by mc_endcheck() and mc_error_flags().\n    In MemCheck 3.0, there's now a global error number much\n    like the \"errno\" variable in standard C.   \n*/\n#define MCE_NO_ERROR            0       /* it's debugging time & all well */\n#define MCE_NULL_SOURCE         1       /* null source ptr on copy */\n#define MCE_NULL_DEST           2       /* null dest ptr on copy */\n#define MCE_UNDERWRITE          3       /* allocated buf underwritten (front) */\n#define MCE_OVERWRITE           4       /* allocated buf overwritten (end) */\n#define MCE_LEAK                5       /* forgot to free alloc'd memory */\n#define MCE_LEAKAGE             MCE_LEAK\n#define MCE_UNFREED_MEMORY      MCE_LEAK\n#define MCE_NULL_PTR_ASSIGN     6       /* assigned data through null ptr */\n#define MCE_BAD_STACK_PTR       7       /* bad stack pointer */\n#define MCE_STACK_OVERWRITE     8       /* copy trashes stack frame */\n#define MCE_INTERNAL            9       /* internal error msg */\n#define MCE_OVERLAPPING_COPY    10      /* source overlaps dest on copy */\n#define MCE_INVALID_PTR         11      /* bad ptr on free, realloc */\n#define MCE_DEST_OVERWRITE      12      /* copy too big for dest buffer */\n#define MCE_OUT_OF_MEMORY       13      /* out of memory */\n#define MCE_OOM                 MCE_OUT_OF_MEMORY   \n#define MCE_GPF_PTR             14      /* ptr caused GPF */\n\n\n/*  MemCheck Error Flags \n\n    The MemCheck error flag is just an unsigned long \n    (specifically, a MCEFLAGS typedef) with \"sticky\" bits \n    corresponding to the above MCE_... error numbers.  \n    You can use the error flags macro MC_EFLAG(e) to \n    test the global MC_Errno double flag word.\n*/\n/* Returns a long word with the e-th bit set */\n#define MC_EFLAG(e) ( (e) ? ((MCEFLAGS)1 << (e-1)) : (MCEFLAGS)0)\n\n#define EFLAG_NULL_PTR          MC_EFLAG(MCE_NULL_DEST)\n#define EFLAG_BAD_PTR           MC_EFLAG(MCE_UNALLOCED_PTR)\n#define EFLAG_FRONT_MAGIC       MC_EFLAG(MCE_UNDERWRITE)\n#define EFLAG_BACK_MAGIC        MC_EFLAG(MCE_OVERWRITE)\n#define EFLAG_PTRS_NOT_FREED    MC_EFLAG(MCE_LEAK)\n#define EFLAG_TRACK_FILE        0   /*obsolete in 3.0+*/\n#define EFLAG_NULL_ASSIGN       MCE_FLAG(MCE_NULL_PTR_ASSIGN)\n\n/* *** End Compatibility Section *** */\n\n\n/* *** MemCheck Compiler Constant Definitions *** */\n\n/* \n    Compiler            Defines\n    --------            -------\n    Microsoft           _CC_MSC_, _CC_MSC_COMPATIBLE_\n        V8.x            _CC_MSC8_\n        V7.x            _CC_MSC7_\n        V6.x            _CC_MSC6_\n        V5.x            _CC_MSC5_\n    Borland*            _CC_BORLAND_, _CC_BCC_\n        V3.x            _CC_BORLAND3_\n        V4.x            _CC_BORLAND4_\n        PowerPack/16    _CC_POWERPACK_, _CC_POWERPACK16_\n        PowerPack/32    _CC_POWERPACK_, _CC_POWERPACK32_, _CC32_\n    WATCOM              _CC_WATCOM_, _CC_MSC_COMPATIBLE_\n        WAT/386         _CC_WATCOM32_, _CC32_\n\n    * Borland has no good way of determining compiler\n      version.  __BORLANDC__ returns some truly funky\n      hex constant that \"will increase in future versions.\"\n\n    Define              Meaning\n    ------              --------\n    _CC32_ *            32-bit compile\n    _PROTECTED_         16- or 32-bit protected mode compile\n    LCODE               Defined if large code model\n    LDATA               Defined if large data model\n    STACKTOP            Highest stack address (top)\n    STACKEND            Lowest stack address \n    STACKLEN            Stack length (top - end)\n    _CPP_ANSI20_        Compiler supports C++ 2.0, e.g. new[]\n\n    * If _CC32_ is defined, _PROTECTED_ is also defined\n*/\n        \n\n#ifndef _CCDEFS_H_\n#define _CCDEFS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*  NOTE: Microsoft C 5.x users have to \"#define _MSC_VER 500\"\n    at the top of this file.\n*/\n#if defined(_MSC_VER)\n/*\n     _MSC_VER            Microsoft C version; currently defined as 700.\n     M_I86   _M_I86      Member of the I86 processor family.\n     M_I86mM _M_I86mM    Memory model type:\n                         <m>= T            Tiny\n                              S            Small (default)\n                              C            Compact model\n                              M            Medium model\n                              L            Large model\n                              H            Huge model\n                         Identifiers defined by /AT, /AS, /AC, /AM,\n                         /AL, and /AH, respectively.\n     _MSDOS              MS-DOS operating system.\n     _QC                 Microsoft QuickC Compiler.\n     _WINDLL             Windows protected-mode dynamic-link library\n                         is selected with /GD.\n     _WINDOWS            Windows protected-mode is selected with /GA,\n                         /Gn, /GW, /Mq, or /GD.\n*/\n#   define _CC_MSC_\n#   define _CC_MSC_COMPATIBLE_\n\n#   if (_MSC_VER >= 800)\n#       define _CC_MSC8_\n#   elif (_MSC_VER >= 700)\n#       define _CC_MSC7_\n#   elif (_MSC_VER >= 600)\n#       define _CC_MSC6_\n#   elif (_MSC_VER >= 500)  /* see note above */\n#       define _CC_MSC5_\n#   else\n#       error MemCheck.h: unrecognized version of Microsoft compiler!\n#   endif\n\n#elif defined(__BORLANDC__)\n#   define _CC_BORLAND_ /* Borland product */\n#   define _CC_BCC_     /* Borland C compiler */\n\n    /* Major compiler rev */\n#   if (__BORLANDC__ >= 0x0450)\n#       define _CC_BORLAND4_\n#   elif (__BORLANDC__ >= 0x400)\n#       define _CC_BORLAND3_\n#   else\n        /* not needed */\n#   endif\n\n    /* Borland 4.0 PowerPack BCC.EXE defines (-WX):\n            __DPMI16__ _Windows\n\n       With -WXD, -WXDE:\n            __DLL__ __DPMI16__ _Windows\n\n       Borland 4.0 PowerPack BCC21.EXE defines (-WX):\n            __CONSOLE__ __DPMI32__ __FLAT__ __WIN32__ _Windows\n\n       With -WXD:\n            __DLL__ __CONSOLE__ __DPMI32__ __FLAT__ __WIN32__ _Windows\n    */\n#   if defined(__DPMI16__)\n#       define _CC_POWERPACK_\n#       define _CC_POWERPACK16_\n#       define _PROTECTED_\n#   endif\n#   if defined(__DPMI32__)\n#       define _CC_POWERPACK_\n#       define _CC_POWERPACK32_\n#       define _CC32_       /* flat model */\n#   endif\n\n/* Turbo C++ */\n#elif defined(MCTCP)    /* homebrew */\n#   define _CC_BORLAND_ /* Borland product */\n#   define _CC_TCP_     /* Turbo C++ */\n\n#elif defined(__TURBOC__)\n/*\n        __TURBOC__      Gives the current Turbo C version\n                        number, a hexadecimal number.  Version\n                        1.0 id 0x1000; version 1.2 is 0x0102, etc.\n        __TINY__, __SMALL__, __MEDIUM__, \n        __COMPACT__, __LARGE__, __HUGE__\n                        Model defintions \n        __MSDOS__       Signals that we're not yet in the\n                        twenty-first century\n*/\n#   define _CC_BORLAND_ /* Borland C product */\n#   define _CC_TCC_     /* Turbo C/C++ compiler */\n\n\n#elif defined(_INTELC32_)\n/*\n        _INTELC32_      has the value 1.\n        _ARCHITECTURE_  is 386 if the nomod486 pragma is ineffect,\n                        486 otherwise.\n*/\n#   define _CC_INTEL_       /* Intel Code Builder */\n#   define _CC_MSC_COMPATIBLE_\n#   define _CC32_           /* flat model */\n\n#elif defined(__WATCOMC__) \n/*  \n        __WATCOMC__     Used to determine if the WATCOM C\n                        or C/386 compiler is compiling\n        __386__         identifies the target machine as an\n                        Intel 80386 under the WATCOM C/386 compiler\n        MSDOS           Signals that we're not yet in the\n                        twenty-first century\n        __FLAT__, __SMALL__, __MEDIUM__, \n        __COMPACT__, __LARGE__  \n                        Model defintions (flat is default)\n                        Also id's MSC-compatible model defines\n\n        8.5 and later:\n        __WINDOWS__     Identifies 16-bit Windows (\"zw\" or \"zW\" opts)\n        __WINDOWS_386__ 32-bit Microsoft Windows \"zW\" opt \n        __NETWARE_386__ Novell Netware 386, defined by the \n                        Novell/Watcom C \n        __OS2__         IBM OS/2-hosted version of Watcom \n*/\n#   define _CC_WATCOM_      /* Watcom C product */\n#   define _CC_MSC_COMPATIBLE_\n#   ifdef __386__\n#       define _CC32_       /* flat model */\n#       define _CC_WATCOM32_\n#   endif\n\n\n#elif defined(__STDC__)     /* Standard ANSI C */\n#   define _CC_ANSI_\n#   define _CC32_           /* no segmentation via far/near */\n#   define far\n#   define near\n#   define huge\n#   define cdecl\n\n/* Avoids parameter mismatches from _far, etc. */\n#   define _far\n#   define _near\n#   define _huge\n#   define _cdecl\n\n#else       /* UNSUPPORTED / UNRECOGNIZED COMPILER */\n\n#error MemCheck 3.0: unrecognized compiler\n/*\n    If you're using Microsoft C5.1, you must\n    define the constant _MSC_VER, e.g.\n\n    #define _MSC_VER    500\n\n    Place this statement at the top of this\n    header file or in your project header file\n    BEFORE the MemCheck header file is included.\n\n    Microsoft C 5.0 is NOT supported (it's non-ANSI).\n*/\n    \n#endif  /* compiler constant definitions */\n\n/* END of _CC..._ name setups; ripple & alias */\n\n/* Sheer utility & avoidance of !_CC32_ */\n#ifndef _CC32_\n#   define _CC16_   \n#endif\n\n/* 32-bit compilers are always protected mode */\n#ifdef _CC32_\n#ifndef _PROTECTED_\n#   define _PROTECTED_\n#endif\n#endif  /* CC32 */\n\n/* Phar Lap support */\n#ifdef DOSX286\n#ifndef _PROTECTED_\n#   define _PROTECTED_\n#endif\n#endif  /* DOSX286 */\n\n/* C++ 2.0 compliance: _CPP_ANSI20_ */\n#if defined(_CC_BORLAND_)\n    /* Only BC++ 4.x and later, but Borland has\n       seriously mangled version info (__BORLANDC__) */\n#   if defined (__BCPLUSPLUS__)\n#       if (__BCPLUSPLUS__ > 0x0310)    /* after 3.1 */\n#           define _CPP_ANSI20_\n#       endif\n#   elif defined(_CC_POWERPACK_)\n#           define _CPP_ANSI20_\n#   endif\n#elif defined (_CC_MSC_)\n    /* Current release through 8.x doesn't support new[] */\n#elif defined (_CC_WATCOM_)\n#   if (__WATCOMC__ >= 1000)    /* 10.x */\n#           define _CPP_ANSI20_\n#   endif\n#endif\n\n\n/*******************************************************************/\n/*******************************************************************/\n\n/*  *** Code and Data Size Constants *** \n    LCODE not used by this header file.\n    LDATA *is* used, however.\n\n    May be commented out if these constants are already defined.\n*/\n\n/*  #ifndef LCODE   */\n#if defined(M_I86MM) || defined(M_I86LM) || defined(M_I86HM)\n#   define LCODE    1\n#elif defined(__MEDIUM__) || defined(__LARGE__) || defined(__HUGE__)\n#   define LCODE    1\n#endif\n/*  #endif  */\n\n#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#   define LDATA    1\n#elif defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)\n#   define LDATA    1\n#endif\n\n/* Macro \"aliases\" */\n\n#ifndef _LCODE\n#   ifdef LCODE\n#       define _LCODE   LCODE\n#   endif\n#endif\n\n#ifndef _LDATA\n#   ifdef LDATA\n#       define _LDATA   LDATA\n#   endif\n#endif\n\n/*******************************************************************/\n/*******************************************************************/\n\n/* *** Physical Stack Address *** */\n\n#if defined(_CC_BORLAND_)   /* -------------------------- */\n\n    /*\n    BORLAND RTL Notes:\n    ;----------------------------------------------------------------------\n    ; In large data models, the stack is in its own segment.  The stack\n    ; starts at SS:__stklen and grows down to SS:0.\n    ;\n    ; In small data models, the stack is in the DGROUP, and grows down\n    ; to meet the heap.  The end of the heap is marked by ___brklvl.\n    (KWB: Note that the brklvl is adjusted upwards until it meets\n    _stklen...)\n    ;----------------------------------------------------------------------\n    */\n\n#   define STACKSLOP    256\n    extern unsigned cdecl _stklen;\n\n#   if defined(_CC_POWERPACK_)\n#       define  STACKTOP    (mc_stacktop())\n#       define  STACKEND    (mc_stackend())\n#   else /* not P-Pack */\n#   ifdef LDATA\n            /*  Compact, Large, Huge Models ...\n\n                The stack starts at SS:_stklen and\n                grows downward to SS:0\n            */\n#           define  STACKTOP    ((unsigned) _stklen)\n#           define  STACKEND    ((unsigned) 0 + STACKSLOP)\n\n#   else\n        /*  Small, Medium Models ...\n\n            The stack starts at SS:0xFFFE and grows\n            downwards _stklen bytes.\n        */\n#       define  STACKTOP    ((unsigned) 0xFFFE)\n#       define  STACKEND    (STACKTOP - _stklen + STACKSLOP)\n#   endif\n#   endif   /* not PowerPack */\n\n#elif defined (_CC_MSC_)  /* ------------------------------- */\n\n    extern char cdecl end;              /* end of stack */\n    extern unsigned cdecl _atopsp;      /* top of stack */\n\n#   define  STACKTOP    _atopsp\n#   define  STACKSLOP   256\n\n#   ifdef LDATA\n        /* If in far data, stack could be in its own\n            seg. tho not usually. see /FARSTACK */\n#       define  STACKEND    ((unsigned) ((unsigned long)&end) + STACKSLOP)\n#   else\n        /*  If near data, must be in DS; use near ptr */\n#       define  STACKEND    ((unsigned)&end + STACKSLOP)\n#   endif\n\n#elif defined (_CC_WATCOM_)  /* ------------------------------- */\n\n    extern unsigned _STACKLOW;      /* end of stack */\n    extern unsigned _STACKTOP;      /* top of stack */\n\n#   define  STACKTOP    (_STACKTOP)\n#   define  STACKSLOP   256\n\n#   ifdef LDATA\n#       define  STACKEND    ((unsigned) (_STACKLOW + STACKSLOP))\n#   else\n#       define  STACKEND    ((unsigned) (_STACKLOW + STACKSLOP))\n#   endif\n\n#else                   /* Unknown compiler ---------------- */\n\n#error Unknown compiler at __FILE__(__LINE__)\n\n#endif      /* defining stack top, end */\n\n/*******************************************************************/\n/*******************************************************************/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif  /* _ccdefs already #included */\n\n/* End CCDEFS */\n\n\n#if !defined (NULL)     /* pull in stdio.h if not already */\n#   include <stdio.h>\n#endif\n\n/* Backup... sometimes NULL defined in other headers */\n#if !defined (_IOFBF)   /* pull in stdio.h if not already */\n#   include <stdio.h>\n#endif\n\n\n/* *** MemCheck Constants *** */\n\n/*  Standard from MemCheck 3.0 onwards.\n    Access major version and revision\n    via mc_version() and mc_revision() macros.\n*/\n#define _MC_VERSION     0x0300      /* welcome 3.0 the powerful */\n\n#define mc_version()    ((int)((_MC_VERSION & 0xFF00) >> 8))\n#define mc_revision()   ((int)(_MC_VERSION & 0x00FF))\n\n#if defined (_CC32_)    /* 32-bit Intel target */\n#define PRT_FP  \"0x%p\"\n#else\n#define PRT_FP  \"%Fp\"\n#endif\n\n/* *** MCID Macro *** */\n\n/*  Allows later flexibility in assigning mapping...\n    Also makes MCIDs formulaic \n*/\n#define _MCID(f)    (MCID)(__paste(MCID_,f))\n\n/*\n    MemCheck Function ID's (MCID's)\n\n    These are the indices used to retrieve information\n    about specific runtime library calls.\n*/\n/* --- MEMCHECK INTERNAL FUNCTIONS --- */\n\n#define _MCID_FIRST_INTERNAL    0       /* index of first internal func */\n\n#define MCID_mc_startcheck      0\n#define MCID_mc_endcheck        1\n#define MCID_mc_check_buffers   2\n#define MCID_mc_check           3\n#define MCID_mc_register        4\n#define MCID_mc_unregister      5\n#define MCID_mc_set_alignsize   6\n#define MCID_mc_set_checkbytes  7\n#define MCID_mc_nullcheck       8\n#define MCID_mc_breakpoint      9\n#define MCID_mc_debug           10\n#define MCID_mc_set_location    11\n#define MCID_mc_stack_trace     12\n#define MCID_mc_report          13\n\n#define _MCID_LAST_INTERNAL         14  /* Set = to last internal ID */\n\n\n/* ***************   STANDARD C ROUTINES     ******************* */\n\n#define _MCID_FIRST_ANSI        (_MCID_LAST_INTERNAL+1)\n\n#define MCID_calloc             (_MCID_FIRST_ANSI + 0)\n#define MCID_free               (_MCID_FIRST_ANSI + 1)\n#define MCID_malloc             (_MCID_FIRST_ANSI + 2)\n#define MCID_memcpy             (_MCID_FIRST_ANSI + 3)\n#define MCID_memmove            (_MCID_FIRST_ANSI + 4)\n#define MCID_memset             (_MCID_FIRST_ANSI + 5)\n#define MCID_realloc            (_MCID_FIRST_ANSI + 6)\n#define MCID_sprintf            (_MCID_FIRST_ANSI + 7)\n#define MCID_strcat             (_MCID_FIRST_ANSI + 8)\n#define MCID_strcpy             (_MCID_FIRST_ANSI + 9)\n#define MCID_strncat            (_MCID_FIRST_ANSI + 10)\n#define MCID_strncpy            (_MCID_FIRST_ANSI + 11)\n#define MCID_vsprintf           (_MCID_FIRST_ANSI + 12)\n\n#define _MCID_LAST_ANSI     MCID_vsprintf       /* define to last ANSI */\n\n\n/* ***************   MICROSOFT C     ******************* */\n\n#if defined(_CC_MSC_COMPATIBLE_)\n\n#define _MCID_FIRST_MSC     (_MCID_LAST_ANSI + 1)\n\n#   define MCID__expand         (_MCID_FIRST_MSC + 0)\n#   define MCID__ffree          (_MCID_FIRST_MSC + 1)\n#   define MCID__fcalloc        (_MCID_FIRST_MSC + 2)\n#   define MCID__fmalloc        (_MCID_FIRST_MSC + 3)\n#   define MCID__fmsize         (_MCID_FIRST_MSC + 4)\n#   define MCID__frealloc       (_MCID_FIRST_MSC + 5)\n#   define MCID__fexpand        (_MCID_FIRST_MSC + 6)\n#   define MCID__msize          (_MCID_FIRST_MSC + 7)\n\n#   define MCID__fmemmove       (_MCID_FIRST_MSC + 8)\n#   define MCID__fmemcpy        (_MCID_FIRST_MSC + 9)\n#   define MCID__fmemset        (_MCID_FIRST_MSC + 10)\n#   define MCID__fmemccpy       (_MCID_FIRST_MSC + 11)\n#   define MCID__fstrcat        (_MCID_FIRST_MSC + 12)\n#   define MCID__fstrncat       (_MCID_FIRST_MSC + 13)\n#   define MCID__fstrcpy        (_MCID_FIRST_MSC + 14)\n#   define MCID__fstrncpy       (_MCID_FIRST_MSC + 15)\n#   define MCID__fstrdup        (_MCID_FIRST_MSC + 16)\n#   define MCID__fstrset        (_MCID_FIRST_MSC + 17)\n#   define MCID__fstrnset       (_MCID_FIRST_MSC + 18)\n\n#   define MCID__nfree          (_MCID_FIRST_MSC + 19)\n#   define MCID__nmalloc        (_MCID_FIRST_MSC + 20)\n#   define MCID__ncalloc        (_MCID_FIRST_MSC + 21)\n#   define MCID__nrealloc       (_MCID_FIRST_MSC + 22)\n#   define MCID__nexpand        (_MCID_FIRST_MSC + 23)\n#   define MCID__nmsize         (_MCID_FIRST_MSC + 24)\n#   define MCID__nstrdup        (_MCID_FIRST_MSC + 25)\n\n#   define MCID__dos_setvect    (_MCID_FIRST_MSC + 26)\n#   define MCID__getdcwd        (_MCID_FIRST_MSC + 27)\n\n/*  Here starts the Great ANSI Divide.\n    MSC6 and earlier have no underscores;\n    MSC7 and later *have* underscores to emphasize\n        departure from ANSI...\n*/\n#if defined(_CC_MSC_) && !defined (MSC6)    /* not MSC6-compatible */\n\n#   define MCID__getcwd         (_MCID_FIRST_MSC + 28)\n#   define MCID__cgets          (_MCID_FIRST_MSC + 29)\n#   define MCID__halloc         (_MCID_FIRST_MSC + 30)\n#   define MCID__hfree          (_MCID_FIRST_MSC + 31)\n#   define MCID__memccpy        (_MCID_FIRST_MSC + 32)\n#   define MCID__strdup         (_MCID_FIRST_MSC + 33)\n#   define MCID__strnset        (_MCID_FIRST_MSC + 34)\n#   define MCID__strset         (_MCID_FIRST_MSC + 35)\n#   define MCID__swab           (_MCID_FIRST_MSC + 36)\n#   define MCID__tempnam        (_MCID_FIRST_MSC + 37)\n\n#else   /*** MSC6 and before; WATCOM ***/\n\n/* No leading underscores */\n\n#   define MCID_getcwd          (_MCID_FIRST_MSC + 28)\n#   define MCID_cgets           (_MCID_FIRST_MSC + 29)\n#   define MCID_halloc          (_MCID_FIRST_MSC + 30)\n#   define MCID_hfree           (_MCID_FIRST_MSC + 31)\n#   define MCID_memccpy         (_MCID_FIRST_MSC + 32)\n#   define MCID_strdup          (_MCID_FIRST_MSC + 33)\n#   define MCID_strnset         (_MCID_FIRST_MSC + 34)\n#   define MCID_strset          (_MCID_FIRST_MSC + 35)\n#   define MCID_swab            (_MCID_FIRST_MSC + 36)\n#   define MCID_tempnam         (_MCID_FIRST_MSC + 37)\n\n#endif  /* MSC6 ANSI calls */\n\n#   define MCID_new             (_MCID_FIRST_MSC + 38)\n#   define MCID_delete          (_MCID_FIRST_MSC + 39)\n#   define MCID__fullpath       (_MCID_FIRST_MSC + 40)\n\n#endif  /* Microsoft C-compatible calls */\n\n\n/* ***************   BORLAND C     ******************* */\n\n#if defined (_CC_BORLAND_)\n\n#define _MCID_FIRST_BC      (_MCID_LAST_ANSI + 1)\n\n#   define MCID__fmemmove       (_MCID_FIRST_BC + 0)\n#   define MCID__fmemcpy        (_MCID_FIRST_BC + 1)\n#   define MCID__fmemset        (_MCID_FIRST_BC + 2)\n#   define MCID__fmemccpy       (_MCID_FIRST_BC + 3)\n#   define MCID__fstrcat        (_MCID_FIRST_BC + 4)\n#   define MCID__fstrncat       (_MCID_FIRST_BC + 5)\n#   define MCID__fstrcpy        (_MCID_FIRST_BC + 6)\n#   define MCID__fstrncpy       (_MCID_FIRST_BC + 7)\n#   define MCID__fstrdup        (_MCID_FIRST_BC + 8)\n#   define MCID__fstrset        (_MCID_FIRST_BC + 9)\n#   define MCID__fstrnset       (_MCID_FIRST_BC + 10)\n\n#   define MCID__dos_setvect    (_MCID_FIRST_BC + 11)\n#   define MCID__getdcwd        (_MCID_FIRST_BC + 12)\n\n#   define MCID_getcwd          (_MCID_FIRST_BC + 13)\n#   define MCID_cgets           (_MCID_FIRST_BC + 14)\n#   define MCID_memccpy         (_MCID_FIRST_BC + 15)\n#   define MCID_strdup          (_MCID_FIRST_BC + 16)\n#   define MCID_strnset         (_MCID_FIRST_BC + 17)\n#   define MCID_strset          (_MCID_FIRST_BC + 18)\n#   define MCID_swab            (_MCID_FIRST_BC + 19)\n#   define MCID_tempnam         (_MCID_FIRST_BC + 20)\n\n#   define MCID_farmalloc       (_MCID_FIRST_BC + 21)\n#   define MCID_farrealloc      (_MCID_FIRST_BC + 22)\n#   define MCID_farfree         (_MCID_FIRST_BC + 23)\n#   define MCID_farcalloc       (_MCID_FIRST_BC + 24)\n#   define MCID_movmem          (_MCID_FIRST_BC + 25)\n#   define MCID_setmem          (_MCID_FIRST_BC + 26)\n#   define MCID_setvect         (_MCID_FIRST_BC + 27)\n#   define MCID_stpcpy          (_MCID_FIRST_BC + 28)\n#   define MCID__fmovmem        (_MCID_FIRST_BC + 29)\n#   define MCID__fsetmem        (_MCID_FIRST_BC + 30)\n#   define MCID_new             (_MCID_FIRST_BC + 31)\n#   define MCID_delete          (_MCID_FIRST_BC + 32)\n#   define MCID__fullpath       (_MCID_FIRST_BC + 33)\n\n#endif\n\n\n/* \n    'TOUCH' macro so high warning levels don't generate\n    'unreferenced variable' warnings, especially when\n    making Production libraries... All MemCheck code\n    compiles without a whymper.\n*/\n#if defined (_CC_WATCOM_)\n#   define TOUCH(var)   var = var\n#elif defined (_CC_BORLAND4_)\n#   define TOUCH(var)   var = var\n#else\n#   define TOUCH(var)   if (var)\n#endif\n\n\n/* Default log name used by stock erf_logfile() and variants... */\n#define MEMCHECK_LOG    \"MEMCHECK.LOG\"\n\n#define MAX_MEMORY  1000    /* 1000K is more than ever possible */\n\n/* User-Modifiable Defaults */\n\n#define D_CheckByteCt   sizeof(int)     /* word size is default */\n#define D_AlignSize     sizeof(int)     /* align returned memory ptrs */\n\n/*  Number of bytes to copy from null segment (to determine null\n    pointer assignments) \n*/\n#define D_NULLCHECK_BYTES_FAR       16      /* at 0000:0000 (far NULL) */\n#define D_NULLCHECK_BYTES_NEAR      16      /* at   DS:0000 (near NULL) */\n#define MAX_NULLCHECK_BYTES_FAR     1024    /* extent of irupt vect tbl */\n#define MAX_NULLCHECK_BYTES_NEAR    66      /* reserved in DS */\n\n/* Unroll the double-negative */\n/*\n    Debugging code specific to MemCheck can be \n    conditionally compiled by placing it within\n    #if-#endif sections:  (NOTE that this is NOT\n    required when just using API functions)\n\n        #ifdef MEMCHECK\n\n        void _MCCALLBACK trackf_special (int op, MEMRECP memrecp)\n        {\n           (... your custom callback code ...)\n        }\n\n        #endif\n\n    instead of the more arcane\n\n        #ifndef NOMEMCHECK\n        :\n        #endif\n\n    (Both approaches work equally well, however...)\n*/\n#ifndef NOMEMCHECK      /* MemCheck active */\n#define MEMCHECK    \n#endif\n\n\n/* *** Calling Conventions *** */\n\n#if !defined (_CC_ANSI_)\n#define     _MCAPI          pascal      /* MemCheck API functions   */\n#define     _FASTAPI        pascal      /* speed-critical functions */\n#define     _MCCDECL        cdecl       /* MemCheck varargs API     */\n#define     _MCCALLBACK     cdecl       /* callback functions       */\n#define     _MCVAR          cdecl       /* MemCheck global variable */\n#else\n#define     _MCAPI          /* MemCheck API functions   */\n#define     _FASTAPI        /* speed-critical functions */\n#define     _MCCDECL        /* MemCheck varargs API     */\n#define     _MCCALLBACK     /* callback functions       */\n#define     _MCVAR          /* MemCheck global variable */\n#endif\n\n#if !defined(_CC_WATCOM_)\n#   define  _RTL            _MCCDECL    /* RTL calling conv */\n#else\n#   define  _RTL                        /* RTL calling conv */\n\n/*  WATCOM C++ does not currently (2/17/94)\n    accept \"cdecl\" as a modifier on variables...  \n*/\n#   undef _MCVAR\n#   define _MCVAR\n#endif  /* _CC_WATCOM_ */\n\n/*   32-bit compiler-independent stuff */\n#if !defined(_CC32_) \n#define _MCFAR      far\n#define _MCFARCALL  far\n#define _MCNEAR     near\n#define _MCNEARCALL near\n#define _MCHUGE     huge\n#else\n#define _MCFAR  \n#define _MCFARCALL\n#define _MCNEAR\n#define _MCNEARCALL\n#define _MCHUGE \n#endif  /* _CC32_ */\n\n/*\n    MSC declares the following routines as \"far\"... \n    So does Borland.  WATCOM does not; define glue.\n\n        _fstrset        _fstrnset       _fstrcpy \n        _fstrncpy       _fstrcat        _fstrncat\n        _fmemset        _fmemmove       _fmemccpy\n*/\n#if !defined(_CC_WATCOM_)\n#   define _MCFARGLUE   far\n#else\n#   define _MCFARGLUE   \n#endif\n\n\n/*  Microsoft C7 and later will not have\n    have a malloc_mc, only _fmalloc_mc; likewise\n    with free_mc.\n    The RTLMALLOC and RTLFREE macros are used\n    to refer to a generically present back-end malloc\n    and free.\n*/\n#if defined (_CC_MSC_)\n#   if defined (LDATA)\n#       define RTLMALLOC    RTL(_fmalloc)\n#       define RTLFREE      RTL(_ffree)\n#   else\n#       define RTLMALLOC    RTL(_nmalloc)\n#       define RTLFREE      RTL(_nfree)\n#   endif\n#else   /* non-MSC */\n#   define RTLMALLOC    RTL(malloc)\n#   define RTLFREE      RTL(free)\n#endif\n\n\n/*  WATCOM defines its atexit funcs as a \"register\",\n    which causes a param type mismatch.  \n    _ATEXITFUNC calling convention smooths this out.\n*/\n#if defined (_CC_WATCOM_)\n#   define _ATEXITFUNC  \n#else\n#   define _ATEXITFUNC      _MCCDECL\n#endif\n\n\n/*  MemCheck Tracking Mode \n    \n    Returned by mc_get_mode().\n    Indicates whether information on each allocation\n    is being stored in memory or on disk.\n*/\n#define MC_USING_MEMORY     1\n#define MC_USING_DISK       2\n\n\n/* Min, max orders for each node in the B-tree */\n\n#define BT_ORDER_MIN        5\n#define BT_ORDER_MAX        255     /* maximum tree order */\n#define BT_ORDER_DEFAULT    19      /* default tree order */\n\n/*\n    Returned by mc_get_speed().\n    Pass as params to mc_set_speed().\n*/\n#define MC_RUN_NORMAL       1\n#define MC_RUN_FAST         2\n\n/*  For mc_report():\n    \"Flags\" field of the MEMREC structure\n    is set to REPORT_START or REPORT_END\n    to indicate begin and end of report.\n\n    NOTE: If REPORT_START or REPORT_END conflicts\n        with defines in your project, just comment\n        them out and use the MC_... variants instead.\n*/\n#define REPORT_START        (MRFLAGS)0xFE\n#define REPORT_END          (MRFLAGS)0xFD\n\n#define MC_REPORT_START     (MRFLAGS)0xFE   /* alternates in case of conflict */\n#define MC_REPORT_END       (MRFLAGS)0xFD\n\n\n/*\n    Maximum number of breakpoints that\n    can be set via mc_breakpoint().\n*/\n#define MC_MAX_BREAKS       50\n\n\n/*  \"Optype\" parameter on Tracking function callback. */\n#define TRACKF_ADD      1       /* record being added to tree */\n#define TRACKF_DEL      2       /* record being deleted from tree */\n\n/*  Used for the mcflags field of MEMREC to indicate\n    whether file & line are exact or approximate\n*/\n#define MRFLAG_EXACT_LOC        ( (MRFLAGS) 0x01)\n\n/*\n    Set if the values for a MEMREC are already converted\n    to \"user\" values.\n*/\n#define MRFLAG_USER_SPECS       ( (MRFLAGS) 0x02)\n#define MRFLAG_NO_CHECKBYTES    ( (MRFLAGS) 0x04)\n\n/* Alternate name */\n#define mc_message      mc_debug \n\n/*\n    Parameter to mc_check_transfer() that\n    specifies that the given data transfer function cannot\n    have overlapping source & destination.\n    (MCID's are unsigned bytes.)\n*/\n#define MCF_NO_OVERLAP      ((unsigned)0x8000)\n#define NO_OVERLAP(mcid)    ((mcid) | MCF_NO_OVERLAP)\n\n/*  Parameter to mc_check_transfer indicating that\n    the found memory record is not needed */\n#define NO_MEMREC           ((MEMRECP)NULL) \n#define NOMEMREC            NO_MEMREC\n\n/*  Parameter to mc_check_transfer indicating that\n    there is no source pointer operand associated\n    with the data transfer being checked: e.g. memset.  */\n#define NO_SOURCE           ((void _MCFAR *)0xFFFFFFFA)\n\n\n/* *** TYPEDEFS *** */\n\ntypedef char *          MCSF;       /* MemCheck source file */\ntypedef unsigned int    MCSL;       /* MemCheck source line */\ntypedef unsigned char   MCID;       /* MemCheck function ID */\n\ntypedef unsigned long   MCEFLAGS;   /* MemCheck error flags */\ntypedef void _MCFAR *   MCPTR;      /* type of ptr stored in tree */\ntypedef unsigned char   MRFLAGS;    /* flags in MEMRECORD */\ntypedef unsigned long   MCFLAGS;    /* MemCheck settings flags */\n\n/* MemCheck Rocket allocator prototypes */\ntypedef void _MCFAR * (_MCFAR *ROCKETALLOCF)    (size_t);\ntypedef void          (_MCFAR *ROCKETFREEF)     (void _MCFAR *);\n\n#pragma pack(1)\n/* \n    Memory Tracking Structure (MEMREC)\n\n    This is the data structure for buffers being\n    tracked by MemCheck.\n*/\ntypedef struct MemRecord \n    {\n        MCPTR           ptr;            /* heap/registered ptr */\n        MCID            mcid;           /* MemCheck function ID */\n        MRFLAGS         flags;          /* internal MC flags */\n        unsigned long   allocno;        /* cardinality of allocation */\n        unsigned long   size;           /* size of block */\n        MCSF            file;           /* source file */\n        MCSL            line;           /* source line */\n\n    } MEMREC, _MCFAR *MEMRECP;\n\n\n/* *** SETTINGS *** */\n/* These are values that describe the life of a MemCheck run. */\n\ntypedef struct MCSETTINGS { \n    /*\n        Bit Flag                What\n        --- ---------------     -----------------------------------\n        0   MCF_ACTIVE          MemCheck active or off\n        1   MCF_FAST_MODE       Fast mode or normal\n        2   MCF_PROTECTED_MODE  Protected mode or real\n        3   MCF_FAR_NULL_CHECK  Check for far NULL ptr assigns *\n        4   MCF_NEAR_NULL_CHECK Check for far NULL ptr assigns *\n        5   MCF_STANDARD_STACK  Standard stack frame *\n        6   MCF_AUTOINIT        Start up automatically *\n        7   MCF_CLEAR_ON_FREE   Clear buffers when freed \n        8   MCF_DISK_ROCKET     Use DiskRocket options\n        9   MCF_IDX_IN_MEMORY   Use memory only for Rocket indexes *\n                                (only if DiskRocket linked)\n        10  MCF_SOURCE_ONLY     Intercept in source code only \n\n        11 - 31 Reserved\n    */\n    MCFLAGS         Flags;              /* Main settings flags */\n\n    unsigned short  MaxMem;             /* Max mem for tree usage, in K */\n    unsigned short  NearNullBytes;      /* bytes to check in near null */\n    unsigned short  FarNullBytes;       /*  \"    \"    \"    \" far   \"   */\n    unsigned char   CheckByteCt;        /* check byte count */\n    unsigned char   AlignSize;          /* alignment boundary size */\n    char            TrackingDir[36];    /* Rocket stores temp files here */\n\n    } MCSETTINGS, *MCSETTINGSP;\n\n\n/* Random 32-bit .CFG file sentinel */\n#define MC_CFG_FILE_SENTINEL        ( (unsigned long) 0x10F23BC4 )\n\ntypedef struct MCCfgInfo {\n\n    unsigned long   sentinel;           /* always MC_CFG_FILE_SENTINEL */\n    MCSETTINGS      MemCheckSettings;   /* saved by user */\n\n    } MCCFGINFO, *MCCFGINFOP;\n\n\n#ifndef _CC32_\n\n/* 16-bit exception stack */\ntypedef struct {\n\n    unsigned    xRetIP;\n    unsigned    xRetCS;\n    unsigned    xErr;\n    unsigned    xIP;\n    unsigned    xCS;\n    unsigned    xFlags;\n    unsigned    xSP;\n    unsigned    xSS;\n\n    } MCEXCEPTINFO;\n\n#else\n\n/* 32-bit exception stack */\ntypedef struct {\n\n    unsigned long   xRetEIP;\n    unsigned short  xRsvd1;\n    unsigned short  xRetCS;\n    unsigned long   xErr;\n    unsigned long   xEIP;\n    unsigned short  xRsvd2;\n    unsigned short  xCS;\n    unsigned long   xFlags;\n    unsigned long   xESP;\n    unsigned short  xRsvd3;\n    unsigned short  xSS;\n\n    } MCEXCEPTINFO;\n\n#endif  /* _CC32_ */\n\n/* Values for MCCRITSECT.action */\n#define MCCS_ENTER_SECTION  0\n#define MCCS_LEAVE_SECTION  1\n\n#define MCCS_ACTION(pMCCS)  (pMCCS->nAction)\n#define MCCS_ENTER(pMCCS)   ((*(pMCCS->pLocked))++) /* inc flag */\n#define MCCS_LEAVE(pMCCS)   ((*(pMCCS->pLocked))--) /* dec flag */\n\n/* \n    Critical section object - ptr to this passed to crit sect callback \n    WARNING:  access these fields ONLY via the MCCS_...() macros.\n        To do otherwise subjects you to changes in implementation\n        of the underlying coordination of critical section locking.\n*/\ntypedef struct {\n    int             nAction;    /* MCCS_ENTER/LEAVE_SECTION */\n    int *           pLocked;    /* # times entered          */\n    unsigned long   ulRsvd;     /* internal use             */\n    } MCCRITSECT;\n\n#pragma pack()\n\n\n#define MC_FEXIT    ( (MCID) 0xFF )\n\n\n/* Error Reporting Function typedef */\n#ifndef _ERF_DEFINED\n#define _ERF_DEFINED\ntypedef void (_MCCALLBACK *ERF) (char *);\n#endif\n\n\n/* *** Callback Functions *** */\n\n/* Interception callback (on every interception) */\ntypedef void (_MCCALLBACK * GLOBALF) (void);\n\n/* Called whenever nodes added to or deleted from MC database */\ntypedef void (_MCCALLBACK *TRACKF) (int, MEMRECP);\n\n/* User-definable check function to add to transfer checking */\ntypedef void (_MCCALLBACK * CHECKF) (\n                int ,           /* 0 or MCE_... error val for this xfer op */\n                void _MCFAR *,  /* user ptr dest */\n                long            /* bytes to copy to dest */\n            );\n\n/* Funcs called at startup or shutdown */\ntypedef void (_MCCALLBACK *STARTF) (void);\ntypedef void (_MCCALLBACK *ENDF)   (void);\n\n/* Report function type passed to mc_report() */\ntypedef void (_MCCALLBACK *REPORTF) (MEMRECP);\n\n/* Additional heap pointer verification (troubleshoot only) */\ntypedef int (_MCCALLBACK *VERIFYF) (void _MCFAR *);\n\ntypedef void (*MCVOIDFP) (void);\n\n/* Exception handler */\ntypedef void (_MCCALLBACK _MCFAR *MCEXCEPTF) (void);\n\n/* Multitasking enter/exit critical section callback.\n   Specify as param to mc_set_critf() at beginning of program;\n   callback function will be called with MCCS_ENTER_SECTION\n   on entry to MemCheck, or MCCS_LEAVE_SECTION on exit.\n\n   NOT TO BE CONFUSED WITH A MEMCHECK \"GLOBAL\" FUNCTION.\n   Global functions (GLOBALF's) are used to perform any\n   actions on the interception of a runtime function;\n   CRITF's must be used ONLY to serialize access to MemCheck.\n*/\ntypedef void (_MCCALLBACK * MCCRITF) (MCCRITSECT *);\n\n\n/*  Stack Frame Handler \n\n    You can define your own function to \n    record, analyze, or inspect each stack frame\n    when mc_stack_trace() is called.\n\n    You *cannot* modify ANY of the values passed\n    in, as the \"const\" typing indicates.  If you need to\n    modify a value, make a copy.  See the MemCheck 3.0\n    documentation for more details on stack frame handlers.\n*/\n\ntypedef void (_MCFAR _MCCDECL *_SSFRAMEHANDLER ) (\n            short    const ,        /* AX: near/far/error flag   */\n            unsigned short const ,  /* CX: near (default) rtn CS */\n            unsigned short const ,  /* ES: far rtn CS            */\n            unsigned const ,        /* DI: rtn offset from stack */\n            short const             /* DX: frame count           */\n    );\n\n/*  Values for \"flag\" constant parameter to a\n    stack frame handler. \n*/\n#define TRACE_BAD_FRAME     0x00        /* couldn't recognize frame     */\n#define TRACE_FAR_CALL      0x01        /* frame represents a far call  */\n#define TRACE_NEAR_CALL     0x02        /*   \"        \"     \" near  \"   */\n#define TRACE_BAD_CHAIN     0x03        /* frame BP chewed up           */\n#define TRACE_BEGIN         0x80        /* signals begin walk           */\n#define TRACE_END           0x81        /* signals end of walk          */\n\n\n/* MC Settings Structure, \"flags\" member: */\n#define MCF_ACTIVE          (MCFLAGS)(0x01)\n#define MCF_FAST_MODE       (MCFLAGS)(0x02)\n#define MCF_PROTECTED_MODE  (MCFLAGS)(0x04)\n#define MCF_FAR_NULL_CHECK  (MCFLAGS)(0x08)\n#define MCF_NEAR_NULL_CHECK (MCFLAGS)(0x10)\n#define MCF_STANDARD_STACK  (MCFLAGS)(0x20)\n#define MCF_AUTOINIT        (MCFLAGS)(0x40)\n#define MCF_CLEAR_ON_FREE   (MCFLAGS)(0x80)\n#define MCF_DISK_ROCKET     (MCFLAGS)(0x100)\n#define MCF_IDX_IN_MEMORY   (MCFLAGS)(0x200)\n#define MCF_SOURCE_ONLY     (MCFLAGS)(0x400)\n\n\n/* *** Conditional Compilation *** */\n\n/* --------------------------------------------------------------\n    If MEMCHECK is not being `compiled out' (via definition\n    of the constant NOMEMCHECK), include this section...\n-------------------------------------------------------------- */\n\n#if !defined(MEMCHECK)\n\n/* Include Section for `MemCheck Not Active' */\n\n/*  *****************************\n     MemCheck Not Active Section\n    *****************************\n\n    This section completely removes or\n    \"evaporates\" all MemCheck function references\n    from your projects when you compile with\n    NOMEMCHECK #defined.\n\n    There's no need to remove any MemCheck\n    headers or statements from your code\n    to produce a full production version\n    of your application.\n\n                    o\n                   ooo\n                 ooooooo\n                ooooooooo\n               ooooooooooo\n                   ooo\n                   ooo\n                   ooo\n                   ooo\n                                    */\n\n#ifndef MEMCHECK_MODULE\n\n/*  Evaporate all MemCheck 3.0 API\n    statements to do nothing, safely... */\n\n#   define  mc_alloc_count()                0L\n#   define  mc_blocks_allocated()           0L\n#   define  mc_blocks_freed()               0L\n#   define  mc_breakpoint(fi)               0\n#   define  mc_bytes_allocated()            0L\n#   define  mc_bytes_freed()                0L\n#   define  mc_check(p)                     0\n#   define  mc_check_buffers()              0\n#   define  mc_cur_file()                   \"No file\"\n#   define  mc_cur_line()                   0\n#   define  mc_debug(s)\n#   define  mc_debugf(_args)\n#   define  mc_debug_on()\n#   define  mc_debug_off()\n#   define  mc_endcheck()                   (MCEFLAGS)0\n#   define  mc_errno()                      MCE_NO_ERROR\n#   define  mc_error_flags()                (MCEFLAGS)0\n#   define  mc_error_text(e)                \"MemCheck not active\"\n#   define  mc_except_text(e)               \"MemCheck not active\"\n#   define  mc_file()                       \"No file\"\n#   define  mc_find_buffer(p,mr)            0\n#   define  mc_func()                       (MCID)0\n#   define  mc_func_name(mcid)              (\"\")\n#   define  mc_get_erf()                    (ERF)NULL\n#   define  mc_get_mode()                   0\n#   define  mc_get_speed()                  0\n#   define  mc_in_source()                  0\n#   define  mc_is_active()                  0\n#   define  mc_line()                       0\n#   define  mc_load_debugger()\n#   define  mc_location_text()              \"MemCheck not active\"\n#   define  mc_memory_leaked()              0L\n#   define  mc_memrec()                     (MEMRECP)NULL\n#   define  mc_memrec_text()                \"MemCheck not active\"\n#   define  mc_msg_continued()              0\n#   define  mc_nullcheck()                  0\n#   define  mc_null_snapshot() \n#   define  mc_register(p,s)    \n#   define  mc_report(_f)\n#   define  mc_set_alignsize(_s)\n#   define  mc_set_breakfile(_f)\n#   define  mc_set_checkbytes(_cb)\n#   define  mc_set_checkf(_f)               (CHECKF)NULL\n#   define  mc_set_critf(_f)                \n#   define  mc_set_endf(erf)                (ENDF)NULL\n#   define  mc_set_erf(erf)                 (ERF)NULL\n#   define  mc_set_globalf(_f)              (GLOBALF)NULL\n#   define  mc_set_globalexitf(_f)          (GLOBALF)NULL\n#   define  mc_set_speed(_s)\n#   define  mc_set_location()\n#   define  mc_set_trackf(_f)               (TRACKF)NULL\n#   define  mc_set_tracefile(_f)\n#   define  mc_set_tree_order(_q)\n#   define  mc_set_track_dir(_dir)          \n#   define  mc_source_ptr()                 (MCPTR)NULL\n#   define  mc_stack_trace(_memo)           0\n#   define  mc_startcheck(_erf)\n#   define  mc_unregister(p)                \n#   define  mc_set_exceptf(f)   \n#   define  mc_get_exceptf()                ((MCEXCEPTF)NULL)\n\n/* *** Stock error reporting functions *** */\n#   define  erf_default(_msg)\n#   define  erf_standard(_msg)\n#   define  erf_logfile(_msg)\n#   define  erf_log_only(_msg)\n#   define  erf_trace(_msg)\n\n/* Internal Helpers */\n#   define  _direct_output(_s)              \n#   define  _mcsl(_f,_l)\n#   define  _mcsl_delete(_f,_l)\n#   define  _mcsl_new(_f,_l)\n#   define  _mcslx(_f,_l,_s)\n#   define  _mc_set_delflag()\n#   define  _mc_set_location(_f,_l)         \n#   define  _mc_set_newflag()\n\n/* Link-time compileouts */\n#   define  MC_SET_AUTOINIT(_toggle)\n#   define  MC_SET_CHECK_FREQ(_freq)    \n#   define  MC_SET_CHECKF(_f)   \n#   define  MC_SET_CRITF(_f)    \n#   define  MC_SET_ENDF(_f) \n#   define  MC_SET_ENV_VAR(_envvarname)\n#   define  MC_SET_ERF(_f)  \n#   define  MC_SET_GLOBALF(_f)  \n#   define  MC_SET_GLOBALEXITF(_f)  \n#   define  MC_SET_LOGFILE(_logfilename)    \n#   define  MC_SET_PANIC_BUFFERS(_q)\n#   define  MC_SET_SSFH(_f) \n#   define  MC_SET_STARTF(_f)   \n#   define  MC_SET_TRACKF(_f)   \n#   define  MC_SET_VERIFYF(_f)  \n\n/* Back-end direct */\n#define RTL(_f)     _f\n\n/* *** C++ *** */\n#ifdef __cplusplus\n\n#define NEW(_object)        new _object\n#define DELETE(_object)     delete _object\n#define DELETE_ARR(_arr)    delete[] _arr\n\n#define cpp_malloc(_s)      malloc(_s)\n#define cpp_calloc(_n,_s)   calloc(_n,_s)\n#define cpp_free(_p)        free(_p)\n\n/* Borland C++ */\n#define cpp_farmalloc(_s)   farmalloc(_s)\n#define cpp_farfree(_fp)    farfree(_fp)\n\n/* Microsoft C++-compatibles */\n#define cpp__fmalloc(_s)    _fmalloc(_s)\n#define cpp__ffree(_fp)     _ffree(_fp)\n\n#endif  /* C++ */\n\n#endif  /* not MEMCHECK_MODULE */\n\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n#else   /* MEMCHECK is defined */\n\n/* #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# */\n\n#pragma message (\"MemCheck V3.0\")\n\n/*\n    *************************\n     MemCheck Active Section\n    *************************\n\n    The rest of this header file deals with\n    MemCheck's being compiled into an application.\n\n                                                   */\n\n/* Specify that vars and funcs are straight C.. */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/* *** ANSI Location Defines *** */\n\n#define _MC_NO_FILE ((MCSF) 0)      /* just in case... */\n#define _MC_NO_LINE ((MCSL) 0)\n\n\n/*  Allow for the possibility of _MCSF_ being\n    defined to reference a single, static module\n    filename.  This prevents a multiplicity of \n    static filenames getting added to the DGROUP, e.g.\n\n        static char *_thisfile = __FILE__;\n        #define _MCSF_  ((MCSF)thisfile)\n        #include <memcheck.h>\n\n    This is only needed under MSC pre-VC++.\n    Borland has \"-d\" Merge duplicate strings.\n    VC++ has \"/Gf\" Elim duplicate strings.\n*/\n#if !defined (_MCSF_)\n#   ifdef __FILE__\n#      define _MCSF_        (MCSF)__FILE__\n#   else\n#      define _MCSF_        _MC_NO_FILE\n#   endif\n#endif\n\n#ifdef __LINE__\n#   define _MCSL_       (MCSL)__LINE__\n#else\n#   define _MCSL_       _MC_NO_LINE\n#endif\n\n\n/* *** Standard ANSI C Includes *** \n\n    For va_list function call args \n    Inclusion of this header won't change\n    the behavior of host code.\n*/\n#if !defined (va_start)     /* avoid multiple inclusion... */\n#   include <stdarg.h>\n#endif\n\n\n/* *** Compiler-specific includes *** */\n\n/*lint -save -e537 Repeated include files (if necessary) */\n#if defined(_CC_MSC_COMPATIBLE_)\n\n#   if !defined (_INC_MALLOC)   /* C7.x and later optimization */\n#       include <malloc.h>\n#   endif\n\n#   if !defined (_INC_STRING)   /* C7.x and later optimization */\n#       include <string.h>\n#   endif   \n\n#elif defined(_CC_BORLAND_)\n\n#   if !defined (__ALLOC_H)\n#       include <alloc.h>           \n#   endif\n\n/* String functions must be proto'd before pragmas */\n#   if !defined (__STRING_H)\n#       include <string.h>\n#   endif\n\n#endif  /* Compiler-specific includes */\n/*lint -restore */\n\n#if defined (_CC_POWERPACK32_)\nextern void cdecl mcinitfp_startcheck (void);\nextern void cdecl mcexitfp_endcheck (void);\n#pragma startup mcinitfp_startcheck     16\n#pragma exit    mcexitfp_endcheck       16\n#endif\n\n/***************************************/\n/* *** MemCheck 3.0 API Prototypes *** */\n/***************************************/\n\n/* Internal helper macro - proto shorthand */\n#define _LOCP   MCSF,MCSL\n\nextern  unsigned long _MCAPI mc_alloc_count (void);\nextern  unsigned long _MCAPI mc_blocks_allocated (void);\nextern  unsigned long _MCAPI mc_blocks_freed     (void);\nextern  unsigned long _MCAPI mc_bytes_allocated  (void);\nextern  unsigned long _MCAPI mc_bytes_freed      (void);\nextern  int         _MCAPI mc_check (void _MCFAR *);\nextern  int         _MCAPI mc_check_buffers (void);\nextern  MCSF        _MCAPI mc_cur_file (void);\nextern  MCSL        _MCAPI mc_cur_line (void);\nextern  void        _MCCDECL mc_debugv (const char *, ...);\nextern  void        _MCAPI mc_debug (const char *);\nextern  MCEFLAGS    _MCAPI mc_endcheck (void);\nextern  MCEFLAGS    _MCAPI mc_error_flags (void);\nextern  char *      _MCAPI mc_error_text (int);\nextern  int         _MCAPI mc_errno (void);\nextern  char *      _MCAPI mc_except_text (unsigned);\nextern  MCSF        _MCAPI mc_file (void);\nextern  int         _MCAPI mc_find_buffer(void _MCFAR *realptr,MEMRECP memrecp);\nextern  MCID        _MCAPI mc_func (void);\nextern  char *      _MCAPI mc_func_name(MCID);\nextern  ERF         _MCAPI mc_get_erf (void);\nextern  MCEXCEPTF   _MCAPI mc_get_exceptf (void);\nextern  int         _MCAPI mc_get_mode (void);\nextern  int         _MCAPI mc_get_speed (void);\nextern  char *      _MCAPI mc_get_tracefile (void);\nextern  int         _MCAPI mc_in_source (void);\nextern  int         _MCAPI mc_is_active (void);\nextern  MCSL        _MCAPI mc_line (void);\nextern  char *      _MCAPI mc_location_text (void);\n#define  mc_load_debugger()     _asm int 3\nextern  unsigned long _MCAPI mc_memory_leaked (void);\nextern  char *      _MCAPI mc_memrec_text (MEMRECP);\nextern  MEMRECP     _MCAPI mc_memrec (void);\nextern  int         _MCAPI mc_msg_continued (void);\nextern  int         _MCAPI mc_nullcheck (void);\nextern  void        _MCAPI mc_null_snapshot (void);\nextern  void        _MCAPI mc_register (void _MCFAR *, unsigned long);\nextern  void        _MCAPI mc_report (REPORTF);\nextern  void        _MCAPI mc_set_alignsize (unsigned int);\nextern  void        _MCAPI mc_set_breakfile (char *);\nextern  void        _MCAPI mc_set_checkbytes (unsigned int);\nextern  CHECKF      _MCAPI mc_set_checkf (CHECKF);\nextern  void        _MCAPI mc_set_critf (MCCRITF);\nextern  ENDF        _MCAPI mc_set_endf (ENDF);\nextern  ERF         _MCAPI mc_set_erf (ERF);\nextern  MCEXCEPTF   _MCAPI mc_set_exceptf (MCEXCEPTF);\nextern  GLOBALF     _MCAPI mc_set_globalf (GLOBALF);\nextern  GLOBALF     _MCAPI mc_set_globalexitf (GLOBALF);\n#define mc_set_location() _mc_set_location(_MCSF_,_MCSL_)\nextern  MCPTR       _MCAPI mc_source_ptr (void);\nextern  void        _MCAPI mc_set_speed (int);\nextern  void        _MCAPI mc_set_tracefile (char *);\nextern  void        _MCAPI mc_set_track_dir (char *);\nextern  TRACKF      _MCAPI mc_set_trackf (TRACKF);\nextern  void        _MCAPI mc_set_tree_order (int);\nextern  int         _MCAPI mc_stack_trace (char *);\nextern  void        _MCAPI mc_startcheck (_LOCP, ERF);\nextern  void        _ATEXITFUNC mc_endcheck_at_exit (void);\nextern  void        _MCAPI mc_unregister (void _MCFAR *);\n\n/* Debugging versions of the MemCheck library only */\nextern  void _MCAPI mc_debug_on  (void);\nextern  void _MCAPI mc_debug_off (void);\nextern  int _MCCALLBACK mc_search_heap (void _MCFAR *);\n\n/* *** INTERNAL API HELPERS *** */\nextern void _MCAPI   _mc_set_location (_LOCP);\nextern void _FASTAPI _mcsl  (MCSF,MCSL);            /* location run-ahead */\nextern void _FASTAPI _mcslx (MCSF,MCSL,size_t);     /* location run-ahead */\nextern void _FASTAPI _mcsl_new (MCSF,MCSL);         /* location run-ahead */\nextern void _FASTAPI _mcsl_delete (MCSF,MCSL);      /* location run-ahead */\nextern void _FASTAPI _mc_set_newflag (void);        /* new's a'comin'     */\nextern void _FASTAPI _mc_set_delflag (void);        /* delete's a'comin'  */\n\n/* Misc - uses INT 9 to output directly to screen */\n#if !defined (_CC_WATCOM32_)\nextern void _MCCDECL _MCFAR _direct_output (char _MCFAR *);\n#else\n#define _direct_output(s)   printf (\"%s\\n\", s)  /* ALERT */\n#endif\n\n/*\n    mc_breakpoint() is now a MemCheck Tracking function (TRACKF).\n    Tracking functions get called every time\n    MemCheck adds or deletes from its database.\n*/\n#define mc_breakpoint(_f)   \\\n            mc_set_trackf( (mc_set_breakfile (_f), trackf_breakpoint) )\n#define mc_breakpoint_trace(_f) \\\n            mc_set_trackf( (mc_set_tracefile (_f), trackf_breakpoint_trace) )\n\n\n/* *** Advanced-user API extenders *** */\n\n/*  extern  int     _MCAPI mc_find_buffer(void _MCFAR *, MEMRECP);  */\nextern  int     _MCAPI mc_check_transfer(\n                            void _MCFAR *,\n                            void _MCFAR *,\n                            unsigned long,\n                            unsigned,\n                            unsigned,\n                            MEMRECP);\n\n/*  mc_get_settings\n\n    Write your own \"get settings\" routine\n    to override the one shipped with MemCheck.\n    You can hard-wire any settings you like, e.g.\n    always ON for versions of your app shipped to \n    testers/QA stations, etc.\n*/\nextern void _MCCALLBACK mc_get_settings (MCSETTINGS *);\n\n\n/* ***  Callbacks / Functionality Extenders *** \n\n    Function Type           Called...\n    --------------          ------------------------------\n    Error reporting         To handle each MemCheck error message \n    Global Interception     On each MemCheck interception\n    Checking                On every data transfer check\n    Tracking                On every allocation/deallocation\n    Start                   On mc_startcheck or AutoInit\n    End                     At mc_endcheck or MemCheck shutdown\n\n    Refer to your MemCheck 3.0 manual for further details.\n\n    *** STOCK FUNCTIONS *** \n    These functions are available in the MemCheck\n    libraries as \"ready-made\" for your programming \n    pleasure in the categories above.\n*/\n\n/* *** Stock error reporting functions *** */\n\nextern  void    _MCCALLBACK erf_default     (char *);\nextern  void    _MCCALLBACK erf_standard    (char *);\nextern  void    _MCCALLBACK erf_logfile     (char *);\nextern  void    _MCCALLBACK erf_log_only    (char *);\nextern  void    _MCCALLBACK erf_trace       (char *);\nextern  void    _MCCALLBACK erf_trace_all   (char *);\nextern  void    _MCCALLBACK erf_trace_obj   (char *);\nextern  void    _MCCALLBACK erf_stdout      (char *);\nextern  void    _MCCALLBACK erf_stderr      (char *);\nextern  void    _MCCALLBACK erf_find_leaks  (char *);\n\n#define erf_printf  erf_stdout      /* alias*/\n\n/* *** Stock Tracking Functions *** */\n\nextern  void    _MCCALLBACK trackf_default          (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_all              (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_all_2            (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_breakpoint       (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_breakpoint_trace (int, MEMRECP);\nextern  void    _MCCALLBACK trackf_big_alloc        (int, MEMRECP);\n\n/* *** Stock End Functions *** */\n\nextern  void    _MCCALLBACK endf_default    (void); /* does nothing */\nextern  void    _MCCALLBACK endf_info       (void); /* write run info to log */\nextern  void    _MCCALLBACK endf_alert      (void); /* warn if run errs */\nextern  void    _MCCALLBACK endf_summary    (void); /* warn if run errs */\n\n/* *** Stock Start functions *** */\n\nextern  void    _MCCALLBACK startf_default  (void); /* does nothing */\nextern  void    _MCCALLBACK startf_info     (void); /* write options to log */\n\n/* *** Stock Check Functions *** */\n\nextern  void    _MCCALLBACK checkf_default (int,void _MCFAR *,long);\nextern  void    _MCCALLBACK checkf_dataseg (\n    int,            /* 0 or MCE_... error val for this xfer op */\n    void _MCFAR *,  /* user ptr dest */\n    long            /* bytes to copy to dest */\n    );\nextern  void    _MCCALLBACK checkf_verify_heap (int,void _MCFAR *,long);\n                            \n/* *** Stock Global Interception Functions *** */\n\nextern  void        _MCCALLBACK globalf_default       (void); /* does nothing */\nextern  void        _MCCALLBACK globalf_supercheck    (void);\nextern  void        _MCCALLBACK globalf_check_buffers (void);\nextern  void        _MCCALLBACK globalf_heapcheck     (void);\n\n/* *** Stock Report Functions *** */\nextern  void        _MCCALLBACK reportf_default (MEMRECP);\n\n/* *** Stock Exception Handlers *** */\nextern void         _MCCALLBACK _MCFAR exceptf_default (void);\n\n/* *** Stock Stack Frame Handlers *** */\nextern void _MCFAR _MCCDECL ssfh_info (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\nextern void _MCFAR _MCCDECL ssfh_fast (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n                /*  int         const   _flag,      */\n\nextern void _MCFAR _MCCDECL ssfh_standard (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\nextern void _MCFAR _MCCDECL ssfh_debug (\n    short const, unsigned short const, unsigned short const, unsigned const, short const);\n\n/* */\nextern unsigned int _MCAPI mc_stacktop (void);  /* high address */\nextern unsigned int _MCAPI mc_stackend (void);  /* low  address */\n\n\n/*  Function external variables.\n\n    These are used effectively with MemCheck 3.0's AutoInit\n    setting.  Under AutoInit, MemCheck fires itself up automatically\n    on its first interception.  Under these circumstances,\n    there's no chance to have changed any defaults (like the\n    ERF or error reporting function).  These variables provide\n    a link-level method of setting these functions:\n\n        #include <memcheck.h>\n        :\n        // Sets custom erf at link-time\n        MC_SET_ERF (erf_custom_startup);\n        :\n*/\n/* *** GLOBALS *** */\n\nextern  ERF         _MCVAR MC_ERF;          /* error reporting func ptr     */\nextern  CHECKF      _MCVAR MC_CheckF;       /* transfer check func          */\nextern  MCCRITF     _MCVAR MC_CritF;        /* crit section enter/exit */\nextern  GLOBALF     _MCVAR MC_GlobalF;      /* global interception callback */\nextern  GLOBALF     _MCVAR MC_GlobalExitF;  /* called on exit interception */\nextern  TRACKF      _MCVAR MC_TrackF;       /* alloc/dealloc callback       */\nextern  STARTF      _MCVAR MC_StartF;       /* startup callback             */\nextern  ENDF        _MCVAR MC_EndF;         /* shutdown callback            */\n\nextern  VERIFYF     _MCVAR MC_VerifyF;      /* troubleshooting              */\n\nextern  char *      _MCVAR MC_LogFile;      /* log file name used           */\nextern  char        _MCVAR MC_UserAutoInit;\nextern  int         _MCVAR MC_CheckFreq;    /* for globalf_supercheck() et al */\nextern  char *      _MCVAR MC_EnvVar;       /* Env var to detect 'active'   */\nextern  unsigned short _MCVAR MC_DataSeg;   /* DS value                     */\n\nextern  int         _MCVAR MC_MaxTraceDepth;\nextern  char *      _MCVAR MCST_Desc;       /* trace descrip to mc_..trc()  */\n\nextern  MCSETTINGS  _MCVAR MC_DefaultSettings;  /* default settings         */\nextern  MCSETTINGS  _MCVAR MC_Settings;         /* real settings--\n                                                   USE WITH CARE!!!         */\n\nextern  MCVOIDFP    _MCVAR MC_PMMap1;       /* p-mode func in map seg 1     */\n\n/* Protected mode exception handling */\nextern  unsigned char   _MCVAR MC_ExceptList[]; /* exceptions to handle */\nextern  MCEXCEPTINFO    _MCVAR MC_ExceptInfo;   /* in exception */\nextern  MCEXCEPTF       _MCVAR MC_ExceptF;      /* installed hdler */\n\n/* Rocket Guidance Systems */\nextern ROCKETALLOCF _MCVAR  MC_RocketAllocF;\nextern ROCKETFREEF  _MCVAR  MC_RocketFreeF;\nextern unsigned char _MCVAR MC_PanicBufCount;   /* anti-tree failure        */\n\n/*  This char is used to fill freed buffers\n    if the \"ClearOnFree\" option in effect.\n    Default buffer clear char is 0.\n*/\nextern unsigned char _MCVAR MC_FreedBufferFillChar;\n\n/*  Link-time defaults.\n\n    These macros are \"covers\" to insulate you, the developer,\n    from the underlying implementation, as well as to provide\n    such bennies as compiling clean out of your code when\n    NOMEMCHECK or NOMC is defined.  \n    \n    Use instead of accessing vars directly!\n\n    To use, place the following in ONE MODULE e.g. your main module\n    (any *one* module will work fine) after the MemCheck \n    header file has been included:\n\n        #include <memcheck.h>\n        MC_SET_...(params);\n\n    For example, to change the default log file that MemCheck\n    uses at runtime to C:\\MYDEV\\MYPROG.LOG:\n\n        #include <memcheck.h>\n        MC_SET_LOGFILE (\"C:\\\\MYDEV\\\\MPROG.LOG\");\n\n    Most of these macros have runtime function equivalents,\n    such as mc_set_erf() for MC_SET_ERF(), etc.  Notable\n    exceptions to this are the following values that\n    must generally have link-time initializations:\n\n        MC_SET_LOGFILE()\n        MC_SET_AUTOINIT()\n        MC_SET_STARTF()\n*/\n#define MC_SET_AUTOINIT(_toggle)        \\\n            char _MCVAR MC_UserAutoInit = (_toggle);\n#define MC_SET_CHECKF(_f)   \\\n            CHECKF  _MCVAR MC_CheckF    = (_f)\n#define MC_SET_CHECK_FREQ(_freq)        \\\n            int _MCVAR MC_CheckFreq     = (_freq)\n#define MC_SET_CRITF(_f)    \\\n            MCCRITF _MCVAR MC_CritF     = (_f)\n#define MC_SET_ENDF(_f)     \\\n            ENDF    _MCVAR MC_EndF      = (_f)\n#define MC_SET_ENV_VAR(_envvarname)     \\\n            char *  _MCVAR MC_EnvVar    = (_envvarname)\n#define MC_SET_ERF(_f)      \\\n            ERF     _MCVAR MC_ERF       = (_f)\n#define MC_SET_EXCEPTF(_f)      \\\n            MCEXCEPTF   _MCVAR MC_ExceptF = (_f)\n#define MC_SET_GLOBALF(_f)  \\\n            GLOBALF _MCVAR MC_GlobalF   = (_f)\n#define MC_SET_GLOBALEXITF(_f)  \\\n            GLOBALF _MCVAR MC_GlobalExitF = (_f)\n#define MC_SET_LOGFILE(_f)      \\\n            char *  _MCVAR MC_LogFile   = (_f)\n#define MC_SET_PANIC_BUFFERS(_q)        \\\n            unsigned char _MCVAR MC_PanicBufCount = (_q)\n#define MC_SET_SSFH(_f)     \\\n            _SSFRAMEHANDLER _MCVAR near MC_SFrameHandler = (_f)\n#define MC_SET_STARTF(_f)       \\\n            STARTF  _MCVAR MC_StartF    = (_f)\n#define MC_SET_TRACKF(_f)   \\\n            TRACKF  _MCVAR MC_TrackF    = (_f)\n#define MC_SET_VERIFYF(_f)  \\\n            VERIFYF _MCVAR MC_VerifyF   = (_f)\n\n/*  Use the MC_BEGIN_EXCEPTLIST, MC_HANDLE_EXCEPTION,\n    and MC_END_EXCEPTLIST macros to change the exceptions \n    MemCheck handles in protected mode by default.\n\n    Usage (exactly as typed):\n            #include <memcheck.h>\n            :\n            MC_BEGIN_EXCEPTLIST\n                MC_HANDLE_EXCEPTION (0x0)\n                MC_HANDLE_EXCEPTION (0xD)\n            MC_END_EXCEPTLIST\n\n    NOTE:\n    To turn off MemCheck's exception handling completely, use \n\n            MC_SET_EXCEPTF(NULL);\n\n    instead of trying to define an empty EXCEPTLIST...\n*/\n#define MC_BEGIN_EXCEPTLIST     \\\n            unsigned char _MCVAR MC_ExceptList[] = {\n#define MC_HANDLE_EXCEPTION(e)  \\\n                (unsigned char)(e),\n#define MC_END_EXCEPTLIST       \\\n                (unsigned char)0xFF };      /* 0xFF MUST end list */\n\n/* ------------- End MemCheck 3.0 Library Calls --------------- */\n\n/*  Formulaic rogue varargs interceptions;\n    most host-code-compatible method...\n    \"Are you experienced?\"\n\n    \"It is better to be mugged than\n     to live in fear.\" - Anon.\n*/\n#define _VA_DEF(f,r,p)          \\\n        typedef r (_RTL *p_##f) p;  \\\n        extern p_##f _MCAPI _loc_##f (_LOCP);\n\n/* Declare sprintf helper function */\n_VA_DEF(sprintf,int,(char *, const char *, ...))\n\n                               /* * * * * * * * * * * * * * * * * * * * * * *\n    *************************\n          Back-End RTL\n    *************************\n*/\n\n/* *** Back-end functions *** */\n\n/*  Macro to access true back-end RTL.\n    Used internally by the MemCheck API functions. \n*/\n#define __paste(x,y)    x ## y\n#define RTL(func)       __paste(func,_mc)\n\n/*  Macro to encapsulate the declaration of\n    the renamed (zapped) back-end rtl \n*/\n#define _RTLDECL(f,rctype,params) \\\n        extern rctype _RTL RTL(f) params\n\n\n/*  For the conversion that MSC underwent\n    from C 6 to 7, where non-ANSI calls\n    have underbars \n*/\n#if defined (_CC_MSC_) && !defined (MSC6) \n#if (_MSC_VER >= 700)\n#   define _C7A\n#endif\n#endif\n\n#ifdef _C7A\n#define C7ANSI(func)    _##func\n#else\n#define C7ANSI(func)    func\n#endif\n\n#undef _C7A\n\n\n/* ---------------------------------------------- */\n/* These are the renamed (\"zapped\") RTL functions */\n/* ---------------------------------------------- */\n\n/* *** ANSI *** */\n\n_RTLDECL(malloc,    void *,     (size_t));\n_RTLDECL(calloc,    void *,     (size_t, size_t));\n_RTLDECL(realloc,   void *,     (void *, size_t));\n_RTLDECL(free,      void,       (void *));\n_RTLDECL(memcpy,    void *,     (void *,const void *,size_t));\n_RTLDECL(memmove,   void *,     (void *,const void *,size_t));\n_RTLDECL(memset,    void *,     (void *,int,size_t));\n_RTLDECL(strcpy,    char *,     (char *,const char *));\n_RTLDECL(strncpy,   char *,     (char *,const char *,size_t));\n_RTLDECL(strcat,    char *,     (char *,const char *));\n_RTLDECL(strncat,   char *,     (char *,const char *,size_t));\n_RTLDECL(vsprintf,  int,        (char *,const char *,va_list));\n_RTLDECL(sprintf,   int,        (char *,const char *,...));\n\n#if !defined (_CC_ANSI_)\n/* *** MSC *** */\n\n/* WATCOM doesn't support these... */\n#if !defined(_CC32_)\n_RTLDECL(_fmalloc,  void far *, (size_t));\n_RTLDECL(_fcalloc,  void far *, (size_t, size_t));\n_RTLDECL(_ffree,    void,       (void far *));\n_RTLDECL(_fmsize,   size_t,     (void far *));\n#endif\n\n_RTLDECL(_nmalloc,  void _MCNEAR *,(size_t));\n_RTLDECL(_nfree,    void,       (void _MCNEAR *));\n\n/* *** Borland *** */\n\n#if !defined(_CC_POWERPACK32_)  \n_RTLDECL(farmalloc, void _MCFAR *,  (unsigned long));\n_RTLDECL(farcalloc, void _MCFAR *,  (unsigned long, unsigned long));\n_RTLDECL(farfree,   void,           (void _MCFAR *));\n\n/* *** General Porpoise *** */\n\n_RTLDECL(_fmemset,  void far * _MCFARGLUE,  (void far *,int,size_t));\n_RTLDECL(_fmemcpy,  void far * _MCFARGLUE,  (void far *,const void far *,size_t ));\n_RTLDECL(_fstrcpy,  char far * _MCFARGLUE,  (char far *,const void far *));\n#endif  /* not _CC_POWERPACK32_ */\n\n#endif  /* not STDC/ANSI */\n\n/***************************************************************** \n * --------   Function Call Interception Definitions   --------- * \n *****************************************************************/\n\n#ifndef MEMCHECK_MODULE\n\n/*\n    This section targets user's code only\n*/\n\n/* Func interceptors... */\n#define     _INTERCEPT(_f)      (_mcsl(_MCSF_,_MCSL_),_f)\n#define     _VA_INTERCEPT(_f)   (*_loc_##_f(_MCSF_,_MCSL_))\n#define     _SETLOC(_f)         (mc_set_location(),_f)\n\n/* NOTE near _mcsl with #if (_MCC_NEAR_INTERCEPT == 0) */\n\n/*\n    MC_NO_TRANSFER_SIZE is used to eliminate errors or warnings\n    like \"sizeof returns 0\" or \"Not allowed type in sizeof <expr>\".\n    These occur for unsized variables declared like\n\n        extern unsigned char gHelpString[];     \n\n    The optimal solution is to \"size\" the extern, e.g.\n\n        extern unsigned char gHelpString[80];   \n\n    but where this may not be practical, MC_NO_TRANSFER_SIZE may\n    be defined on a module-by-module OR project-wide basis.\n*/\n#ifdef MC_NO_XFER_SIZE      /* beta compat */\n#   define  MC_NO_TRANSFER_SIZE\n#endif\n#ifdef NO_TRANSFER_SIZE     /* alternate */\n#   define  MC_NO_TRANSFER_SIZE\n#endif\n\n#if defined (MC_NO_TRANSFER_SIZE)\n#   define  _INTERCEPTX(_f,_d)  _INTERCEPT(_f)\n#else   /* standard; transmit sizeof dest */\n#   define  _INTERCEPTX(_f,_d)  (_mcslx(_MCSF_,_MCSL_,sizeof(_d)),_f)\n#endif\n\n\n/*  Intrinsic Function Disabling\n\n    It's important to disable function inlining for\n    all intercepted functions.\n*/\n\n#if defined(_CC_MSC_)\n\n/*  Intrinsics (== in-line functions) not permissible\n    since they're implemented as macros...\n*/\n#pragma function(strcat)\n#pragma function(strcpy)\n#pragma function(memcpy)\n#pragma function(memset)\n\n#pragma function(strset)\n\n#if defined(_MSC_VER)\n#if (_MSC_VER >= 700)\n#pragma function(_fmemcpy)\n#pragma function(_fmemset)\n#pragma function(_fstrcat)\n#pragma function(_fstrcpy)\n#pragma function(_fstrset)\n#pragma function(_strset)\n#endif\n#endif /* defined _MSC_VER */\n\n#elif defined(_CC_BORLAND_)\n\n/* Turbo C not like pragmae */\n#if !defined (_CC_TCC_)\n\n/*  Eliminate duplicate strings.\n    This can save a bit of space in large\n    programs particularly, since each call to \n    MemCheck references an otherwise separate\n    copy of the current filename. \n*/\n#pragma option -d\n\n/*  Intrinsics (== in-line functions) not permissible\n    since they're implemented as macros, for one...\n*/\n#pragma intrinsic -strcat\n#pragma intrinsic -strncat\n#pragma intrinsic -strcpy\n#pragma intrinsic -strncpy\n#pragma intrinsic -stpcpy\n#pragma intrinsic -strset\n#pragma intrinsic -strnset\n#pragma intrinsic -memcpy\n#pragma intrinsic -memset\n\n#endif  /* not Turbo C */\n\n/* end Borland compiler intrinsics */\n\n#elif defined (_CC_WATCOM_)\n\n/*  NOTE:  unfortunately, WATCOM C/C++ compilers\n    force inlining of the strcpy() function regardless\n    of whether you want it inlined or not, all the time.\n    So this pragma, while it should ensure that\n    strcpy() is a function call, does not...  :{\n\n    So we take other measures below: see _mcwatcom_strcpy()\n*/\n#pragma function(strcpy)\n\n#pragma function(strcat)\n#pragma function(memcpy)\n#pragma function(memset)\n\n#pragma function(_fmemcpy)\n#pragma function(_fmemset)\n#pragma function(_fstrcat)\n#pragma function(_fstrcpy)\n\n#endif\n\n/* End disable function inlining */\n\n\n/*lint -save -e652 Define of symbol declared previously */\n#if defined (MC_NO_INTERCEPT)\n#define NO_INTERCEPT\n#endif\n\n#if !defined (NO_INTERCEPT)\n\n/* *** ANSI Standard C *** */\n\n#define calloc(n,_sz)       _INTERCEPT(calloc(n,_sz))\n#define malloc(_sz)         _INTERCEPT(malloc(_sz))\n#define realloc(p,s)        _INTERCEPT(realloc(p,s))\n#define free(p)             _INTERCEPT(free(p))\n\n#define memcpy(d,s,n)       _INTERCEPTX(memcpy(d,s,n),d)\n#define memmove(d,s,n)      _INTERCEPTX(memmove(d,s,n),d)\n#define memset(p,c,n)       _INTERCEPTX(memset(p,c,n),p)\n#define strcat(s1,s2)       _INTERCEPTX(strcat(s1,s2),s1)\n#if defined(_CC_WATCOM_)    \n    /* WATCOM forces inlining of strcpy()... see note above */\n#   define strcpy(d,s)      _INTERCEPTX(_mcwatcom_strcpy(d,s),d)\n    extern char * _RTL _mcwatcom_strcpy (char *, const char *);\n#else\n#   define strcpy(d,s)      _INTERCEPTX(strcpy(d,s),d)\n#endif\n#define strncat(s1,s2,n)    _INTERCEPTX(strncat(s1,s2,n),s1)\n#define strncpy(d,s,n)      _INTERCEPTX(strncpy(d,s,n),d)\n#define vsprintf(s,f,a)     _INTERCEPTX(vsprintf(s,f,a),s)\n\n/*  #define sprintf             _VA_INTERCEPT(sprintf)  */\n#ifndef _lint\n#define sprintf             _INTERCEPT(sprintf)\n#endif  \n\n#if defined(_CC_MSC_COMPATIBLE_)    /* *** Microsoft C *** */\n\n#define _expand(_p,_s)      _INTERCEPT(_expand(_p,_s))\n#define _fcalloc(n,_sz)     _INTERCEPT(_fcalloc(n,_sz))\n#define _fexpand(_p,_s)     _INTERCEPT(_fexpand(_p,_s))\n#define _ffree(p)           _INTERCEPT(_ffree(p))\n#define _fmalloc(_sz)       _INTERCEPT(_fmalloc(_sz))\n#define _frealloc(p,s)      _INTERCEPT(_frealloc(p,s))\n#define _fmsize(p)          _INTERCEPT(_fmsize(p))\n#define _msize(p)           _INTERCEPT(_msize(p))\n#define _nfree(p)           _INTERCEPT(_nfree(p))\n#define _nmalloc(_sz)       _INTERCEPT(_nmalloc(_sz))\n#define _nrealloc(p,s)      _INTERCEPT(_nrealloc(p,s))\n#define _ncalloc(n,_sz)     _INTERCEPT(_ncalloc(n,_sz))\n#define _nexpand(_p,_s)     _INTERCEPT(_nexpand(_p,_s))\n#define _nmsize(p)          _INTERCEPT(_nmsize(p))\n#define _nstrdup(s)         _INTERCEPT(_nstrdup(s))\n/*  #define halloc(n,_sz)       _INTERCEPT(halloc(n,_sz))   */\n/*  #define _halloc(n,_sz)      _INTERCEPT(halloc(n,_sz))   */\n/*  #define hfree(p)            _INTERCEPT(hfree(p))    */\n/*  #define _hfree(p)           _INTERCEPT(hfree(p))    */\n\n#define cgets(s)            _INTERCEPTX(cgets(s),s)\n#define _cgets(s)           _INTERCEPTX(_cgets(s),s)\n#define memccpy(d,s,c,n)    _INTERCEPTX(memccpy(d,s,c,n),d)\n#define _memccpy(d,s,c,n)   _INTERCEPTX(_memccpy(d,s,c,n),d)\n#define strdup(s)           _INTERCEPT(strdup(s))\n#define _strdup(s)          _INTERCEPT(_strdup(s))\n#define _strnset(s,c,n)     _INTERCEPTX(_strnset(s,c,n),s)\n#define strnset(s,c,n)      _INTERCEPTX(strnset(s,c,n),s)\n#define strset(s,c)         _INTERCEPTX(strset(s,c),s)\n#define _strset(s,c)        _INTERCEPTX(_strset(s,c),s)\n#define swab(s,d,n)         _INTERCEPTX(swab(s,d,n),d)\n#define _swab(s,d,n)        _INTERCEPTX(_swab(s,d,n),d)\n#define tempnam(d,pfx)      _INTERCEPT(tempnam(d,pfx))\n#define _tempnam(d,pfx)     _INTERCEPT(_tempnam(d,pfx))\n\n#define _fmemcpy(d,s,n)     _INTERCEPTX(_fmemcpy(d,s,n),d)\n#define _fmemmove(d,s,n)    _INTERCEPTX(_fmemmove(d,s,n),d)\n#define _fmemset(d,c,n)     _INTERCEPTX(_fmemset(d,c,n),d)\n#define _fmemccpy(d,s,c,n)  _INTERCEPTX(_fmemccpy(d,s,c,n),d)\n#define _fstrcat(s1,s2)     _INTERCEPTX(_fstrcat(s1,s2),s1)\n#define _fstrcpy(d,s)       _INTERCEPTX(_fstrcpy(d,s),d)\n#define _fstrncat(s1,s2,n)  _INTERCEPTX(_fstrncat(s1,s2,n),s1)\n#define _fstrncpy(d,s,n)    _INTERCEPTX(_fstrncpy(d,s,n),d)\n#define _fstrdup(s)         _INTERCEPT(_fstrdup(s))\n#define _fstrnset(d,c,n)    _INTERCEPTX(_fstrnset(d,c,n),d)\n#define _fstrset(d,c)       _INTERCEPTX(_fstrset(d,c),d)\n\n#define getcwd(d,n)         _INTERCEPTX(getcwd(d,n),d)\n#define _getcwd(d,n)        _INTERCEPTX(getcwd(d,n),d)\n#define _getdcwd(r,d,n)     _INTERCEPTX(_getdcwd(r,d,n),d)\n#define _dos_setvect(_i,_h) _INTERCEPT(_dos_setvect(_i,_h))\n#define _fullpath(b,p,n)    _INTERCEPTX(_fullpath(b,p,n),b)\n\n/* ----- END Microsoft C/C++ interceptions ----- */\n\n#elif defined (_CC_BORLAND_)    /* *** Borland C/C++ *** */\n\n#ifndef _CC_POWERPACK32_\n#define farfree(p)          _INTERCEPT(farfree(p))\n#define farmalloc(s)        _INTERCEPT(farmalloc(s))\n#define farcalloc(n,s)      _INTERCEPT(farcalloc(n,s))\n#define farrealloc(p,s)     _INTERCEPT(farrealloc(p,s))\n#endif  /* not _CC_POWERPACK32_ */\n\n#define cgets(s)            _INTERCEPTX(cgets(s),s)\n#define memccpy(d,s,c,n)    _INTERCEPTX(memccpy(d,s,c,n),d)\n#if !defined(movmem)\n#define movmem(s,d,l)       _INTERCEPTX(movmem(s,d,l),d)\n#endif\n#if !defined(setmem)\n#define setmem(d,c,v)       _INTERCEPTX(setmem(d,c,v),d)\n#endif\n#define setvect(i,v)        _INTERCEPT(setvect(i,v))\n#define stpcpy(d,s)         _INTERCEPTX(stpcpy(d,s),d)\n#define _stpcpy(d,s)        _INTERCEPTX(_stpcpy(d,s),d)\n#define strdup(s)           _INTERCEPT(strdup(s))\n#define strnset(s,c,n)      _INTERCEPTX(strnset(s,c,n),s)\n#define strset(s,c)         _INTERCEPTX(strset(s,c),s)\n#define swab(s,d,n)         _INTERCEPTX(swab(s,d,n),d)\n#define tempnam(d,pfx)      _INTERCEPT(tempnam(d,pfx))\n\n#define getcwd(d,n)         _INTERCEPTX(getcwd(d,n),d)\n#define _getdcwd(r,d,n)     _INTERCEPTX(_getdcwd(r,d,n),d)\n#define _dos_setvect(_i,_h) _INTERCEPT(_dos_setvect(_i,_h))\n\n#ifndef _CC_POWERPACK32_\n#define _fmemcpy(d,s,n)     _INTERCEPTX(_fmemcpy(d,s,n),d)\n#define _fmemmove(d,s,n)    _INTERCEPTX(_fmemmove(d,s,n),d)\n#define _fmemset(d,c,n)     _INTERCEPTX(_fmemset(d,c,n),d)\n#define _fmemccpy(d,s,c,n)  _INTERCEPTX(_fmemccpy(d,s,c,n),d)\n#define _fmovmem(s,d,l)     _INTERCEPTX(_fmovmem(s,d,l),s)\n#define _fsetmem(d,c,v)     _INTERCEPTX(_fsetmem(d,c,v),d)\n#define _fstrcat(s1,s2)     _INTERCEPTX(_fstrcat(s1,s2),s1)\n#define _fstrcpy(d,s)       _INTERCEPTX(_fstrcpy(d,s),d)\n#define _fstrncat(s1,s2,n)  _INTERCEPTX(_fstrncat(s1,s2,n),s1)\n#define _fstrncpy(d,s,n)    _INTERCEPTX(_fstrncpy(d,s,n),d)\n#define _fstrdup(s)         _INTERCEPT(_fstrdup(s))\n#define _fstrnset(d,c,n)    _INTERCEPTX(_fstrnset(d,c,n),d)\n#define _fstrset(d,c)       _INTERCEPTX(_fstrset(d,c),d)\n#endif  /* not _CC_POWERPACK32_ */\n\n/*\n#define freemem(g)          _INTERCEPT(freemem(g))\n#define vsscanf(d,f,a)      _INTERCEPTX(vsscanf(d,f,a),d)\n*/\n\n/* ----- END Borland C/C++ interceptions ----- */\n\n#else\n\n#error Unknown compiler in MemCheck.h\n\n#endif  /* Compiler-specific Function Mapping Section */\n\n/*  Location Transmitters\n\n    You can add any non-intercepted functions to\n    this bunch... Just updates MemCheck's file and line\n    information via mc_set_location(), which is thousands\n    of times faster than anything that does I/O.\n    The only time this section could be a problem is\n    if the header file is included before any other header\n    files which prototype these routines.\n\n    Borland's TD (Turbo Debugger) also has problems here (see note).\n*/\n#ifndef _lint   /* LINT not like */\n\n/*  Borland's Turbo Debugger gets confoosed and executes\n    a `Run' instead of a `Step' when _SETLOC macro is used...\n*/\n#if !defined (_CC_BORLAND_)\n#if 1   /* Change this to '0' to omit this section */\n\n#define printf              _SETLOC(printf)\n\n#define fopen               _SETLOC(fopen)\n#define fprintf             _SETLOC(fprintf)\n#define fread               _SETLOC(fread)\n#define fwrite              _SETLOC(fwrite)\n#define fclose              _SETLOC(fclose)\n\n#define system              _SETLOC(system)\n#define exec                _SETLOC(exec)\n#define spawnl              _SETLOC(spawnl)\n#define spawnlp             _SETLOC(spawnlp)\n#define spawnle             _SETLOC(spawnle)\n#define spawnlpe            _SETLOC(spawnlpe)\n#define spawnv              _SETLOC(spawnv)\n#define spawnvp             _SETLOC(spawnvp)\n#define spawnve             _SETLOC(spawnve)\n#define spawnvpe            _SETLOC(spawnvpe)\n\n#endif  /* end location transmission section */\n#endif  /* not Borland C++ */\n#endif  /* not def _lint */\n\n\n/* ****  THIRD-PARTY MAPPINGS  **** */\n\n/*  Vermont Views V3.xx\n\n    The following code will transmit the exact file\n    and line of any mem_get() and mem_free() calls to\n    MemCheck, so that it can report on the location where\n    these functions are called, instead of the location of\n    the calloc() or free().\n\n    If you've used MCCONFIG to configure the Vermont Views source \n    code, you *must* either NOT include the MemCheck header file \n    in the MEM_GET.C and MEM_FREE.C modules, or, if you do, then\n    #define NO_INTERCEPT beforehand, e.g.\n\n         Module MEM_GET.C ... \n        :\n        #define NO_INTERCEPT\n        #include <memcheck.h>\n        :\n\n    MCCONFIG may be used to configure even the shrouded\n    Vermont Views source code.\n\n    See also: TechNote \"Using MemCheck 3.0 Professional\n        With Vermont Views\", available on the StratosWare\n        BBS (313) 996-2993 as VIEWS.TXT, or by fax.\n*/\n#if defined (VV_SYS)    /* should do the trick */\n#   define mem_get(s)   _INTERCEPT(mem_get(s))\n#   define mem_free(p)  _INTERCEPT(mem_free(p))\n#endif\n\n\n/* ****  APPLICATION-SPECIFIC MAPPINGS  **** */\n\n/*\n    If your application uses allocation \"cover\" routines,\n    MemCheck will by default report errors and leaks by\n    the file and line of the malloc or free within the\n    cover module.  To get MemCheck to report by file and\n    line where the cover function is actually called, follow\n    the instructtions in MemCheck TechNote \"Transmitting File\n    and Line to MemCheck 3.0 Professional Through Cover Functions.\"\n\n    This is where you can place the cover function macros.\n*/\n\n\n/* end APPLICATION-SPECIFIC MAPPINGS */\n\n#endif  /* not NO_INTERCEPT */\n\n/* Calls that xmit source file, line number if called in source */\n/* *** MemCheck API file & line transmittal *** */\n#define mc_startcheck(erf)      mc_startcheck(_MCSF_,_MCSL_,erf)\n#define mc_stack_trace(_memo)   _INTERCEPT(mc_stack_trace(_memo))\n#define mc_debug(s)             _INTERCEPT(mc_debug(s))\n#define mc_debugf(arglist)      mc_debugv arglist\n#define mc_debugv               _mcsl(_MCSF_,_MCSL_),mc_debugv\n#define mc_endcheck()           _INTERCEPT(mc_endcheck())\n#define mc_check_buffers()      _INTERCEPT(mc_check_buffers())\n#define mc_check(p)             _INTERCEPT(mc_check(p))\n#define mc_register(p,s)        _INTERCEPT(mc_register(p,s))\n#define mc_unregister(p)        _INTERCEPT(mc_unregister(p))\n#define mc_nullcheck()          _INTERCEPT(mc_nullcheck())\n#define mc_report(f)            _INTERCEPT(mc_report(f))\n\n/*lint -restore  652 Define of symbol declared prev */\n\n#endif  /* not MEMCHECK_MODULE, function interceptions */\n\n\n/* End \"C\" call wrapper */\n#ifdef __cplusplus\n}\n\n\n/*  C++ MemCheck Class\n\n    This class can be used as an alternative to\n    AutoInit, or to placing the mc_startcheck() and\n    mc_endcheck() calls in your main() program.\n    Just declaring an object of class 'MemCheck'\n    will start MemCheck up;  usually you will place\n    this 'above' any other global or statically declared\n    C++ objects in your main module.\n\n    Here are some examples of starting MemCheck up\n    via object mechanics:\n\n        MemCheck On;\n        MemCheck Active;\n        MemCheck Rules;\n\n    Use your imagination!  Note that if AutoInit is ON,\n    any calls to mc_startcheck() and mc_endcheck() are\n    ignored.\n*/\n#if !defined (NO_INTERCEPT) /* must not have this def'd */\n\n/* This class def causes a warning under MSC if not used */\n#if !defined (_CC_MSC_)\n\nclass MemCheck {\npublic:\n    MemCheck ()  { mc_startcheck (NULL); }\n    ~MemCheck () { mc_endcheck ();       }\n};\n\n#endif\n\n#endif /* NO_INTERCEPT */\n\n\n/* *** For use in new and delete modules only *** */\n/*\n    Replace 'mallocs' with 'cpp_mallocs', etc.\n    In new and delete modules, NO_INTERCEPT should be #defined, e.g.\n\n        #define NO_INTERCEPT\n        #include <memcheck.h>\n        :\n        void * operator new ( size_t size )\n        {\n            if (!size)  size = 1;\n            return (cpp_malloc (size));\n        }\n        etc.\n*/\n#define cpp_malloc(_s)      (_mc_set_newflag(),     malloc(_s))\n#define cpp_calloc(_n,_s)   (_mc_set_newflag(),     calloc(_n,_s))\n#define cpp_free(_p)        (_mc_set_delflag(),     free(_p))\n\n/* Borland C++ */\n#define cpp_farmalloc(_s)   (_mc_set_newflag(),     farmalloc(_s))\n#define cpp_farfree(_fp)    (_mc_set_delflag(),     farfree(_fp))\n\n/* Microsoft C++-compatibles */\n#define cpp__fmalloc(_s)    (_mc_set_newflag(),     _fmalloc(_s))\n#define cpp__ffree(_fp)     (_mc_set_delflag(),     _ffree(_fp))\n\n\n/* C++ */\n#if !defined (NO_INTERCEPT)\n#if !defined (NO_CPP)\n\n/*\n    This method is off by default, because it\n    requires definition of a new operator like:\n\n      void * new (size_t size, char *file, int lineno);\n\n    Such a new operator is included in your SOURCE\\CPP\n    directory. To have this method used for all modules,\n    #define NEW_OVERLOADED at the top of this header file\n    or in your project #include file, BEFORE the MemCheck\n    header file is #included.\n\n    The substitutions for the new operator\n    may not work in all situations.  To disable\n    MemCheck's interception of new on a module-by-\n    module basis by undefining NEW_OVERLOADED.\n*/\n#if defined (NEW_OVERLOADED)\n\n/*  Method 1: Placement Operators\n\n    Use placement operators to trap file and line location transparently\n    on calls to new.  \n    \n    Thanks for this tip to Dan Saks,\n    C and C++ writer, author, teacher, and columnist--buy his books.\n    He came through when no one else had a clue!\n\n    Please consult your manual, MemCheck technotes, \n    or StratosWare Technical Support (1-800-WE-DEBUG)\n    for details on how to configure your project for\n    use with an overloaded new placement operator.\n*/\n\n/* Declare overloaded new with placement operators */\nvoid *operator new (size_t _sz, char *file, int lineno);\n#if defined (_CPP_ANSI20_)\n/*  Array version; only under supporting compilers \n    COMMENT LINE OUT if it causes a compile error.\n*/\nvoid *operator new[] (size_t _sz, char *file, int lineno);\n#endif\n\n#if !defined (_CC_MSC_)\n#define new     new((char *)__FILE__,(int)__LINE__)\n#else\n#define new     new(__FILE__,__LINE__)\n#endif\n\n/*  NOTE:\n    This placement operator interception syntax has been\n    known to cause syntax errors (in VC++ 1.0) for no apparent reason\n    on statements like\n\n            Domain *d = new Domain ();\n\n    Workaround is to change line (sorry!) to equivalent\n\n            Domain *d = new Domain;\n*/\n\n/* Backwards compatibility with the V2.1 C++ macros */\n#ifndef NEW\n#define NEW(_object)         new _object\n#endif\n#ifdef DELETE\n#define DELETE(_object)      delete _object\n#endif\n#define DELETE_ARR(_arr)     delete[] _arr\n\n#else   /* !NEW_OVERLOADED - end of Placement Operator intercept */\n\n/*  New and Delete Interception, Method 2: NEW() and DELETE()\n\n    The NEW() and DELETE() macros may be used to transmit file\n    and line of new and delete.   These macros, which require\n    modification of source code, i.e. \"NEW(object)\" for \"new object\",\n    should probably be used only if the above overloaded new does\n    not work for your code base.\n    \n    Please consult your manual, MemCheck technotes, \n    or StratosWare Technical Support (1-800-WE-DEBUG)\n    for details on how to configure your project for\n    use with NEW() and DELETE().\n\n    If calling, please have your MemCheck serial number handy.\n*/\n#ifndef NEW\n#define NEW(_object)        (_mcsl_new(_MCSF_,_MCSL_),    new _object)\n#endif\n#ifndef DELETE  /* WINNT.H under BC DPMI32 defines DELETE */\n#define DELETE(_object)     (_mcsl_delete(_MCSF_,_MCSL_), delete _object)\n#endif\n#define DELETE_ARR(_arr)    (_mcsl_delete(_MCSF_,_MCSL_), delete[] _arr)\n\n#endif  /* !NEW_OVERLOADED */\n\n#define delete  _mcsl_delete(_MCSF_,_MCSL_), delete\n\n\n/* *** FAILURES *** */\n\n/*  These macros failed in the purpose of\n    intercepting new transparently in some\n    situation or other.\n*/\n\n/* Failed on \" * new expr \" (TV)  */\n/*  #define new (mc_set_location(),0) ? NULL : new  */\n\n/* Failed on \" x = new Object \" (TV) */\n/*  #define new ((mc_set_location(),0) ? NULL : new)    */\n/*  #define new new (mc_set_location(),0) ? NULL :  */\n\n#endif  /* !NO_CPP */\n#endif  /* NO_INTERCEPT */\n#endif  /* cplusplus */\n/******** End C++ ************/\n\n\n#endif      /* End of Section for MEMCHECK Defined */\n\n/* -------------------------------------------------------------------------- */\n\n#endif  /* _MEMCHECK_H_ */\n\n\n/********************************\n * End of MemCheck 3.0 Header *\n ********************************/\n\n"
  },
  {
    "path": "REDALERT/MENUS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MENUS.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MENUS.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Phil W. Gorrow                                               *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : Oct. 24, 1996 Victor Grippi                                  *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Main_Menu -- Menu processing                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#ifdef WIN32\n#include \"ccdde.h\"\n#else\t//WIN32\n#include\t<sys\\timeb.h>\n#endif\n\n/*****************************\n**\tFunction prototypes\n******************************/\n\nPRIVATE int Coordinates_In_Region(int x, int y, int inx1, int iny1, int inx2, int iny2);\nPRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index);\nPRIVATE void Flash_Line(char const *text, int xpix, int ypix, unsigned nfgc, unsigned hfgc, unsigned bgc);\n\nint UnknownKey;\n\nPRIVATE int MenuUpdate=1;\nPRIVATE int MenuSkip;\n\n#ifdef FIXIT_VERSION_3\n#include \"WolStrng.h\"\n#endif\n\n/*=========================================================================*/\n/*\tSELECT_TO_ENTRY:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine converts a selection to the correct string entry. It\t   */\n/*\tdoes this by search through a long bitfield starting at position index\t*/\n/*\tuntil it finds the correct conversion to entries.\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint selection from menu, long the bit field to search, int \t   */\n/*\t\t\t\tthe starting index within the bit field.\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tint the index into the table of entries\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index)\n{\n\tint placement;\n\n\tif (bitfield==0xFFFFFFFFL) \t\t\t\t\t\t\t/* if all bits are set\t*/\n\t\treturn(select);\t\t\t\t\t\t\t\t\t\t/*\t\tthen it as is\t\t*/\n\n\tplacement=0;\t\t\t\t\t\t\t\t\t\t\t\t/* current pos zero\t\t*/\n\twhile (select) {\t\t\t\t\t\t\t\t\t\t\t/* while still ones\t\t*/\n\t\tif (bitfield & (1L<<(placement+index)))\t\t\t/* if this flagged then\t*/\n\t\t\tselect--;\t\t\t\t\t\t\t\t\t\t\t/* decrement counter\t\t*/\n\t\tplacement++;\t\t\t\t\t\t\t\t\t\t\t/* and we moved a place\t*/\n\t}\n\twhile (!(bitfield & (1L<<(placement+index)))) {\n\t\tplacement++;\n\t}\n\n\treturn(placement);\t\t\t\t\t\t\t\t\t\t/* return the position\t*/\n}\n\n\n/*=========================================================================*/\n/*\tFLASH_LINE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine will flash the line at the desired location for the\t\t*/\n/*\tmenu routine. It is way cool awesome!\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tchar *text, int x position on line, int y position, char\t\t   */\n/*\t\t\t\tnormal foreground color, char hilight foreground color, char \t*/\n/*\t\t\t\tbackground color\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE void Flash_Line(char const *text, int xpix, int ypix, unsigned nfgc, unsigned hfgc, unsigned bgc)\n{\n\tint loop;\n\n\tfor (loop=0;loop<3;loop++) {\n\t\tHide_Mouse();\n\t\tPlain_Text_Print(text, xpix, ypix, hfgc, bgc, TPF_8POINT|TPF_DROPSHADOW);\n\t\tDelay(2);\n\t\tPlain_Text_Print(text, xpix, ypix, nfgc, bgc, TPF_8POINT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\n\t\tDelay(2);\n\t}\n}\n\n/*=========================================================================*/\n/*\tCOORDINATES_IN_REGION:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tTest to see if a given pair of coordinates are within the given \t\t*/\n/*\trectangular region.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint x to be tested, int y to be tested, int left x pos,\t\t\t*/\n/*\t\t\t\tint top y pos, int right x pos, int bottom y pos\t\t\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nPRIVATE int Coordinates_In_Region(int x, int y, int inx1, int iny1, int inx2, int iny2)\n{\n\treturn((x>=inx1)&&(x<=inx2)&&(y>=iny1)&&(y<=iny2));\n}\n\n#ifdef NEVER\n/*=========================================================================*/\n/*\tFIND_MENU_ITEMS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine finds the real total items in a menu when certain items\t*/\n/*\tmay be disabled by bit fields and the like. This is done by looping\t\t*/\n/*\tthrough the fields, starting at the position passed in index and \t\t\t*/\n/*\tcounting the number of bits that are set.\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint the maximum number of items possible on the menu, long \t\t*/\n/*\t\t\t\tthe bit field of enabled and disabled items, char the index\t\t*/\n/*\t\t\t\tpoint to start at within the list.\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\tint the total number of items in the menu\t\t\t\t\t\t\t*/\n/*=========================================================================*/\n int Find_Menu_Items(int maxitems, unsigned long field, char index)\n {\n\tint loop,ctr;\n\n\tif (field==0xFFFFFFFFL) \t\t\t\t\t\t\t\t\t\t/* if all bits are set\t*/\n\t\treturn(maxitems);\t\t\t\t\t\t\t\t\t\t/* then maxitems set\t\t*/\n\n\tfor (loop=ctr=0;loop<maxitems;loop++) {\t\t\t/* loop through items\t*/\n\t\tif (field & (1L<<(loop+index))) {\t\t\t\t/* if the bit is set\t\t*/\n\t\t\tctr++;\t\t\t\t\t\t\t\t\t\t\t\t/*\t\tcount the item\t\t*/\n\t\t}\n\t}\n\treturn(ctr);\n}\n#endif\n\n\n/*=========================================================================*/\n/*\tSETUP_EOB_MONITOR_MENU:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\tThis routine sets up the eye of the beholder monitor menu.\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\tint the menu we are using, char *[] the array of text which\t\t*/\n/*\t\t\t\tmakes up the menu commands, long the info field, int the\t\t\t*/\n/*\t\t\t\tindex into the field, int the number of lines to skip.\t\t\t*/\n/*\tRETURNS:\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nvoid Setup_Menu(int menu, char const * text[], unsigned long field, int index, int skip)\n{\n\tint * menuptr,lp;\n\tint menuy,menux,idx,item,num,drawy;\n\n\tmenuptr=&MenuList[menu][0];\t\t\t\t\t\t\t/* get pointer to menu\t*/\n\tmenuy=WinY+menuptr[MENUY];\t\t\t\t\t\t\t\t/* get the absolute \t\t*/\n\tmenux=(WinX+menuptr[MENUX]);\t\t\t\t\t\t/*\t\tcoords of menu\t\t*/\n\titem=Select_To_Entry(menuptr[MSELECTED], field, index);\n\tnum=menuptr[ITEMSHIGH];\n\n\tPlain_Text_Print(0, 0, 0, TBLACK, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n \tHide_Mouse();\n\tfor (lp=0;lp<num;lp++) {\n\t\tidx=Select_To_Entry(lp, field, index);\n\t\tdrawy=menuy+(lp*FontHeight)+(lp*skip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, menuptr[((idx==item) && (MenuUpdate )) ? HILITE : NORMCOL], TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n//\t\tif ((idx==item) && (MenuUpdate ))\n//\t\t\tText_Print(text[idx], menux, drawy, menuptr[HILITE], TBLACK);\n\t}\n\tMenuSkip=skip;\n\tShow_Mouse();\n\tKeyboard->Clear();\n}\n\n\n/*=========================================================================*/\n/*\tCHECK_MENU:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tINPUTS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*\tRETURNS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*/\n/*=========================================================================*/\nint Check_Menu(int menu, char const * text[], char *, long field, int index)\n{\n\tint maxitem,select,key,menuy,menux;\n\tint mx1,mx2,my1,my2,tempy;\n\tint drawy,menuskip,halfskip;\n\tint normcol,litcol,item,newitem,idx;\n\tint * menuptr;\n\n\t//selection++;\t\t\t\t\t\t\t\t\t\t\t\t/* get rid of warning\t*/\n\n\tmenuptr = &MenuList[menu][0];\t\t\t\t\t\t\t/* get pointer to menu\t*/\n\tmaxitem = menuptr[ITEMSHIGH]-1;\t\t\t\t\t\t\t/* find max items\t\t\t*/\n\tnewitem = item = menuptr[MSELECTED]%(maxitem+1);\t/* find selected \t\t\t*/\n\tselect = -1;\t\t\t\t\t\t\t\t\t\t\t\t\t/* no selection made\t\t*/\n\tmenuskip = FontHeight+MenuSkip;\t\t\t\t\t\t\t/* calc new font height\t*/\n\thalfskip = MenuSkip>>1;\t\t\t\t\t\t\t\t\t/* adjustment for menus\t*/\n\n\tmenuy = WinY+menuptr[MENUY];\t\t\t\t\t\t\t\t/* get the absolute \t\t*/\n\tmenux = (WinX+menuptr[MENUX]);\t\t\t\t\t\t/*\t\tcoords of menu\t\t*/\n\tnormcol = menuptr[NORMCOL];\n\tlitcol = menuptr[HILITE];\n\n\t/*\n\t**\tFetch a pending keystroke from the buffer if there is a keystroke\n\t**\tpresent. If no keystroke is pending then simple mouse tracking will\n\t**\tbe done.\n\t*/\n\tkey = 0;\n\tUnknownKey = 0;\n\tif (Keyboard->Check()) {\n#ifdef WIN32\n\t\tkey = (Keyboard->Get() & ~(WWKEY_SHIFT_BIT|WWKEY_ALT_BIT|WWKEY_CTRL_BIT) );\t\t\t/* mask off all but release bit\t*/\n#else\n\t\tkey = (Keyboard->Get()&0x08FF);\t\t\t/* mask off all but release bit\t*/\n#endif\n\t}\n\n\t/*\n\t**\tif we are using the mouse and it is installed, then find the mouse\n\t**\tcoordinates of the menu and if we are not somewhere on the menu get\n\t**\tthe heck outta here. If we are somewhere on the menu, then figure\n\t**\tout the new selected item, and continue forward.\n\t*/\n\tmx1=(WinX)+(menuptr[MENUX]*FontWidth);\t\t/* get menu coords\t\t*/\n\tmy1=(WinY)+(menuptr[MENUY])-halfskip;\t\t\t/*\t\tfrom the menu\t\t*/\n\tmx2=mx1+(menuptr[ITEMWIDTH]*FontWidth)-1;\t\t/*\t\tstructure as\t\t*/\n\tmy2=my1+(menuptr[ITEMSHIGH]*menuskip)-1;\t\t/*\t\tnecessary\t\t\t*/\n\n\t\ttempy=Get_Mouse_Y();\n\t\tif (Coordinates_In_Region(Get_Mouse_X(), tempy, mx1, my1, mx2, my2)&& MenuUpdate) {\n\t\t\tnewitem=(tempy-my1)/menuskip;\n\t\t}\n\n\tswitch (key) {\n\n\t\tcase KN_UP:\t\t\t\t\t\t\t\t\t\t\t\t/* if the key moves up\t*/\n\t\t\tnewitem--;\t\t\t\t\t\t\t\t\t\t\t/* \tnew item up one\t*/\n\t\t\tif (newitem<0) \t\t\t\t\t\t\t\t\t/* if invalid new item\t*/\n\t\t\t\tnewitem=maxitem;\t\t\t\t\t\t\t\t/* put at list bottom\t*/\n\t\t\tbreak;\n\t\tcase KN_DOWN:\t\t\t\t\t\t\t\t\t\t\t/* if key moves down\t\t*/\n\t\t\tnewitem++;\t\t\t\t\t\t\t\t\t\t\t/*\t\tnew item down one\t*/\n\t\t\tif (newitem>maxitem) \t\t\t\t\t\t\t/* if new item past \t\t*/\n\t\t\t\tnewitem=0;\t\t\t\t\t\t\t\t\t\t/*\t\tlist end, clear\t*/\n\t\t\tbreak;\n\t\tcase KN_HOME:\t\t\t\t\t\t\t\t\t\t\t/* if top of list key \t*/\n\t\tcase KN_PGUP:\t\t\t\t\t\t\t\t\t\t\t/*\t\tis selected then\t*/\n\t\t\tnewitem=0;\t\t\t\t\t\t\t\t\t\t\t/*\t\tnew item = top\t\t*/\n\t\t\tbreak;\n\t\tcase KN_END:\t\t\t\t\t\t\t\t\t\t\t/* if bottom of list is\t*/\n\t\tcase KN_PGDN:\t\t\t\t\t\t\t\t\t\t\t/*\t\tselected then\t\t*/\n\t\t\tnewitem=maxitem;\t\t\t\t\t\t\t\t\t/*\t\tnew item = bottom\t*/\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tHandle mouse button press. Set selection and then fall into the\n\t\t**\tnormal menu item select logic.\n\t\t*/\n\t\tcase KN_RMOUSE:\n\t\tcase KN_LMOUSE:\n\t\t\tif (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, mx1, my1, mx2, my2)) {\n\t\t\t\tnewitem = (Keyboard->MouseQY - my1) / menuskip;\n\t\t\t} else {\n\t\t\t\tUnknownKey = key;\t\t\t//\tPass the unprocessed button click back.\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t/*\n\t\t**\tNormal menu item select logic. Will flash line and exit with menu\n\t\t**\tselection number.\n\t\t*/\n\t\tcase KN_RETURN:\t\t\t\t\t\t\t\t\t\t/* if a selection is \t*/\n\t\tcase KN_SPACE:\t\t\t\t\t\t\t\t\t\t\t/*\t\tmade with key\t\t*/\n\t\tcase KN_CENTER:\n\t\t\tselect=newitem;\t\t\t\t\t\t\t\t\t/*\t\tflag it made.\t\t*/\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tWhen no key was pressed or an unknown key was pressed, set the\n\t\t**\tglobal record of the key and exit normally.\n\t\t**\tEXCEPTION:\tIf the key matches the first letter of any of the\n\t\t**\t\t\t\t\tmenu entries, then presume it as a selection of\n\t\t**\t\t\t\t\tthat entry.\n\t\t*/\n\t\tdefault:\n\t\t\tfor (idx = 0; idx < menuptr[ITEMSHIGH]; idx++) {\n\t\t\t\tif (toupper(*(text[Select_To_Entry(idx, field, index)])) == toupper(Keyboard->To_ASCII((KeyNumType)(key&0x0FF)))) {\n\t\t\t\t\tnewitem = select = idx;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUnknownKey = key;\n\t\t\tbreak;\n\t}\n\n\tif (newitem!=item) {\n\t\tHide_Mouse();\n\t\tidx=Select_To_Entry(item, field, index);\n\t\tdrawy=menuy+(item*menuskip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, normcol, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n\t\tidx=Select_To_Entry(newitem, field, index);\n\t\tdrawy=menuy+(newitem*menuskip);\n\t\tPlain_Text_Print(text[idx], menux, drawy, litcol, TBLACK, TPF_8POINT|TPF_DROPSHADOW);\n\t\tShow_Mouse();\t\t\t\t\t\t\t\t\t\t\t\t/* resurrect the mouse\t*/\n\t}\n\n\tif (select!=-1) {\n\t\tidx=Select_To_Entry(select, field, index);\n\t\tHide_Mouse();\t\t\t\t\t\t\t\t\t\t\t\t/* get rid of the mouse\t*/\n\t\tdrawy=menuy+(newitem*menuskip);\n\t\tFlash_Line(text[idx], menux, drawy, normcol, litcol, TBLACK);\n\t\tShow_Mouse();\n\t\tselect=idx;\n\t}\n\n\tmenuptr[MSELECTED]=newitem;\t\t\t\t\t\t\t/* update menu select\t*/\n\n\treturn(select);\n}\n\n\n/***************************************************************************\n * Do_Menu -- Generic menu processor.                                      *\n *                                                                         *\n *    This helper function displays a menu of specified entries and waits  *\n *    for the player to make a selection. If a selection is made, then     *\n *    a whole number (starting at 0) is returned matching the entry        *\n *    selected. If ESC is pressed, then -1 is returned.                    *\n *                                                                         *\n * INPUT:   strings  -- A pointer to an array of pointers to text strings. *\n *                      Each entry in the list will be a menu entry that   *\n *                      can be selected.                                   *\n *                                                                         *\n *          blue     -- Should the special blue color be used to display   *\n *                      the menu?                                          *\n *                                                                         *\n * OUTPUT:  Returns with the cardinal number of the selected menu entry.   *\n *          If ESC was pressed, then -1 is returned.                       *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/16/1994 JLB : Created.                                             *\n *=========================================================================*/\nint Do_Menu(char const ** strings, bool )\n{\n\tint\tcount;\t\t// Number of entries in this menu.\n\tint\tlength;\t\t// The width of the menu (in pixels).\n\tchar\tconst ** ptr;\t\t// Working menu text pointer.\n\tint\tselection;\t// Selection from user.\n\n\tif (!strings) return(-1);\n\tSet_Logic_Page(SeenBuff);\n\tKeyboard->Clear();\n\n\t/*\n\t**\tDetermine the number of entries in this string.\n\t*/\n\tptr = strings;\n\tcount = 0;\n\twhile (*ptr++) {\n\t\tcount++;\n\t}\n\tMenuList[0][ITEMSHIGH] = count;\n\n\t/*\n\t**\tDetermine the width of the menu by finding the length of the\n\t**\tlongest menu entry.\n\t*/\n\tPlain_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_8POINT|TPF_DROPSHADOW);\n\tlength = 0;\n\tptr = strings;\n\twhile (*ptr) {\n\t\tlength = max(length, (int)String_Pixel_Width(*ptr));\n\t\tptr++;\n\t}\n\tlength += 7;\n\tMenuList[0][ITEMWIDTH] = length >> 3;\n\n\t/*\n\t**\tAdjust the window values to match the size of the\n\t**\tspecified menu.\n\t*/\n\tWindowList[WINDOW_MENU][WINDOWWIDTH] = (MenuList[0][ITEMWIDTH] + 2) * 8;\n\tWindowList[WINDOW_MENU][WINDOWX] = (19 - (length >> 4)) * 8;\n\tWindowList[WINDOW_MENU][WINDOWY] = 174 - (unsigned)(MenuList[0][ITEMSHIGH] * (FontHeight+FontYSpacing));\n\tWindowList[WINDOW_MENU][WINDOWHEIGHT] = MenuList[0][ITEMSHIGH] * FontHeight + 5 /*11*/;\n\n\t/*\n\t**\tDisplay the menu.\n\t*/\n\tChange_Window((int)WINDOW_MENU);\n\tShow_Mouse();\n\tWindow_Box(WINDOW_MENU, BOXSTYLE_RAISED);\n\tSetup_Menu(0, strings, 0xFFFFL, 0, 0);\n\n\tKeyboard->Clear();\n\tselection = -1;\n\tUnknownKey = 0;\n\twhile (selection == -1) {\n\t\tCall_Back();\n\t\tselection = Check_Menu(0, strings, NULL, 0xFFL, 0);\n\t\tif (UnknownKey != 0 || UnknownKey == KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) break;\n\t}\n\tKeyboard->Clear();\n\tHide_Mouse();\n\n\tHidPage.Blit(SeenPage);\n//WindowList[WINDOW_MAIN][2] = SeenBuff.Get_Width();//BG\n\tChange_Window((int)WINDOW_MAIN);\n\tMap.Flag_To_Redraw(true);\n\treturn(selection);\n}\n\n\n/***************************************************************************\n * Main_Menu -- Menu processing                                            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tindex of item selected, -1 if time out\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/17/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Main_Menu(unsigned long )\n{\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint\td_dialog_w = 152 * RESFACTOR;\n#ifdef FIXIT_VERSION_3\n\tint\td_dialog_h = 100 * RESFACTOR;\n#else\n//#ifdef WIN32\t//Extra 'Internet' option on WIN32 menu\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\tint\td_dialog_h = 100 * RESFACTOR;\n#else\n//\t#if defined(MPEGMOVIE) // Denzil 6/25/98 - Video settings\n//\tint\td_dialog_h = 100 * RESFACTOR;\n//\t#else\n\tint\td_dialog_h = 80 * RESFACTOR;\n//\t#endif\n#endif\t//WIN32\n#endif\t//FIXIT_VERSION_3\n\tint\td_dialog_x = 85 * RESFACTOR;\n\tint\td_dialog_y = 75 * RESFACTOR;\n\tint\td_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint\td_start_w = 118 * RESFACTOR;\n\tint\td_start_h = 9 * RESFACTOR;\n\tint\td_start_x = 102 * RESFACTOR;\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved button from main menu.\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - no internet play\n\tint\td_internet_w = 118 * RESFACTOR;\n\tint\td_internet_h = 9 * RESFACTOR;\n\tint\td_internet_x = 102 * RESFACTOR;\n#endif\t//WIN32\n#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tint\td_movie_w = 118 * RESFACTOR;\n//\tint\td_movie_h = 9 * RESFACTOR;\n//\tint\td_movie_x = 102 * RESFACTOR;\n//#endif\n\n\tint\td_load_w = 118 * RESFACTOR;\n\tint\td_load_h = 9 * RESFACTOR;\n\tint\td_load_x = 102 * RESFACTOR;\n\n\tint\td_multi_w = 118 * RESFACTOR;\n\tint\td_multi_h = 9 * RESFACTOR;\n\tint\td_multi_x = 102 * RESFACTOR;\n\n\tint\td_intro_w = 118 * RESFACTOR;\n\tint\td_intro_h = 9 * RESFACTOR;\n\tint\td_intro_x = 102 * RESFACTOR;\n\n\tint\td_exit_w = 118 * RESFACTOR;    //changed value to 118 V.Grippi\n\tint\td_exit_h = 9 * RESFACTOR;\n\tint     d_exit_x = 102 *RESFACTOR;   //Added V.Grippi\n\n\tint starty = d_dialog_y + (12 * RESFACTOR);\n\n//#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n//#ifndef FIXIT_VERSION_3\n\tstatic int\tmax_buttons = 7;\n//#else\n//\tstatic int\tmax_buttons = 6;\n//#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tmax_buttons++;\n//#endif\n\t/*\n\t**\tButton enumerations:\n\t*/\n\t//\tEnums in Select_Game() must match order of buttons in Main_Menu().\n#ifdef FIXIT_VERSION_3\n\tenum {\n\t\tBUTTON_EXPAND=100,\t\t\t//\t(CS)\n\t\tBUTTON_EXPAND_AM,\n\t\tBUTTON_START,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_MULTI,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_EXIT,\n\t};\n#else\t//\tFIXIT_VERSION_3\n\tenum {\n\t\tBUTTON_EXPAND=100,\n\t\tBUTTON_START,\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\t\tBUTTON_INTERNET,\n#endif\t//WIN32\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\t\tBUTTON_MOVIE,\n//#endif\n\t\tBUTTON_LOAD,\n\t\tBUTTON_MULTI,\n\t\tBUTTON_INTRO,\n\t\tBUTTON_EXIT,\n\t};\n#endif\t//\tFIXIT_VERSION_3\n\n\t/*\n\t**\tDialog variables:\n\t*/\n#ifdef FIXIT_VERSION_3\n\tbool bExpansionCS = Expansion_CS_Present();\n\tbool bExpansionAM = Expansion_AM_Present();\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tbool expansions = Expansion_CS_Present() | Expansion_AM_Present();\n#else\n\tbool expansions = Expansion_CS_Present();\n#endif\n#endif\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tint retval;\t\t\t\t\t\t\t\t\t\t// return value\n\tint curbutton;\n\tTextButtonClass * buttons[7];\n\tunsigned long starttime;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n#ifdef FIXIT_VERSION_3\n\tint ystep = 14 * RESFACTOR;\n\tif( bExpansionCS )\n\t{\n\t\tif( bExpansionAM )\n\t\t\tystep = 12 * RESFACTOR;\n\t\telse\n\t\t\tystep = 13 * RESFACTOR;\n\t}\n\telse if( bExpansionAM )\n\t\tystep = 13 * RESFACTOR;\n\n\tTextButtonClass expandbtnCS( BUTTON_EXPAND, TXT_WOL_CS_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h );\n\tif( bExpansionCS )\n\t\tstarty += ystep;\n\tTextButtonClass expandbtnAM( BUTTON_EXPAND_AM, TXT_WOL_AM_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h );\n\tif( bExpansionAM )\n\t\tstarty += ystep;\n#else\n\tint ystep = 12 * RESFACTOR;\n\tif (expansions) ystep = 10 * RESFACTOR;\n\t\n\tTextButtonClass expandbtn (BUTTON_EXPAND, TXT_NEW_MISSIONS, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h);\n\tif (expansions) starty += ystep;\n#endif\n\n\tTextButtonClass startbtn(BUTTON_START, TXT_START_NEW_GAME, TPF_BUTTON, d_start_x, starty, d_start_w, d_start_h);\n\tstarty += ystep;\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - no internet play\n\tTextButtonClass internetbutton (BUTTON_INTERNET, TXT_INTERNET, TPF_BUTTON, d_internet_x, starty, d_internet_w, d_internet_h);\n\tstarty += ystep;\n#endif\t//WIN32\n#endif\n\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tTextButtonClass moviebutton(BUTTON_MOVIE, \"Movie Settings\", TPF_BUTTON, d_movie_x, starty, d_movie_w, d_movie_h);\n//\tstarty += ystep;\n//#endif\t//WIN32\n\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_MISSION, TPF_BUTTON, d_load_x, starty, d_load_w, d_load_h);\n\tstarty += ystep;\n\n\tTextButtonClass multibtn(BUTTON_MULTI, TXT_MULTIPLAYER_GAME, TPF_BUTTON, d_multi_x, starty, d_multi_w, d_multi_h);\n\tstarty += ystep;\n\n\tTextButtonClass introbtn(BUTTON_INTRO, TXT_INTRO, TPF_BUTTON, d_intro_x, starty, d_intro_w, d_intro_h);\n\tstarty += ystep;\n\n\tTextButtonClass exitbtn(BUTTON_EXIT, TXT_EXIT_GAME, TPF_BUTTON,\n\t\td_exit_x, starty, d_exit_w, d_exit_h);\n\tstarty += ystep;\n\n\t/*\n\t**\tInitialize\n\t*/\n\tif (RequiredCD != -2) {\n\t\tRequiredCD = -1;\n\t\tForce_CD_Available(RequiredCD);\n\t}\n\tSet_Logic_Page(SeenBuff);\n\tKeyboard->Clear();\n\tstarttime = TickCount;\n\n\t/*\n\t**\tCreate the list\n\t*/\n\tcommands = &startbtn;\n#ifdef FIXIT_VERSION_3\n\tif( bExpansionCS )\n\t\texpandbtnCS.Add_Tail(*commands);\n\tif( bExpansionAM )\n\t\texpandbtnAM.Add_Tail(*commands);\n#else\n\tif (expansions) {\n\t\texpandbtn.Add_Tail(*commands);\n\t}\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No internet play\n\tinternetbutton.Add_Tail(*commands);\n#endif\t//WIN32\n#endif\n//#if defined(MPEGMOVIE) // Denzil 6/26/98 Video settings\n//\tmoviebutton.Add_Tail(*commands);\n//#endif\n\tloadbtn.Add_Tail(*commands);\n\tmultibtn.Add_Tail(*commands);\n\tintrobtn.Add_Tail(*commands);\n\texitbtn.Add_Tail(*commands);\n\n\t/*\n\t**\tFill array of button ptrs\n\t*/\n#ifdef FIXIT_VERSION_3\n\tcurbutton = bExpansionCS ? 0 : ( bExpansionAM ? 1 : 2 );\n\n\tbuttons[0] = &expandbtnCS;\n\tbuttons[1] = &expandbtnAM;\n\tbuttons[2] = &startbtn;\n\tbuttons[3] = &loadbtn;\n\tbuttons[4] = &multibtn;\n\tbuttons[5] = &introbtn;\n\tbuttons[6] = &exitbtn;\n#else\n\tif (expansions) {\n\t\tcurbutton = 0;\n\t} else {\n\t\tcurbutton = 1;\n\t}\n\t\n\tbuttons[0] = &expandbtn;\n\tbuttons[1] = &startbtn;\n\tbuttons[2] = &internetbutton;\n\tbuttons[3] = &loadbtn;\n\tbuttons[4] = &multibtn;\n\tbuttons[5] = &introbtn;\n\tbuttons[6] = &exitbtn;\n#endif\n\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tfixed oldvolume = Options.ScoreVolume;\n\tif (oldvolume == 0) {\n\t\tOptions.Set_Score_Volume(fixed(4, 10), false);\n\t}\n\tTheme.Play_Song(THEME_INTRO);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n#endif\n\n\t\t/*\n\t\t**\tIf timeout expires, bail\n\t\t*/\n//\t\tif (timeout && TickCount - starttime > timeout) {\n//\t\t\tretval = -1;\n//\t\t\tprocess = false;\n//\t\t}\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tLoad the background picture.\n\t\t\t*/\n\t\t\tLoad_Title_Page();\n\t\t\tCCPalette.Set();\n\n\t\t\t/*\n\t\t\t**\tDisplay the title and text overlay for the menu.\n\t\t\t*/\n\t\t\tSet_Logic_Page(HidPage);\n//\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n//\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\tcommands->Draw_All();\n#ifdef FIXIT_VERSION_3\n#if (0)//PG\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(5 * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n#endif\n#else\n#ifndef WIN32\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(8  * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n\n#else\n\t\t\tFancy_Text_Print(\"V%s\", d_dialog_x+d_dialog_w- (18 * RESFACTOR),\n\t\t\t\td_dialog_y+d_dialog_h-(11 * RESFACTOR), GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_EFNT|TPF_NOSHADOW|TPF_RIGHT,\n\t\t\t\tVersion_Name());\n\n#endif\n#endif\n\n\t\t\t/*\n\t\t\t**\tCopy the menu to the visible page.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tHidPage.Blit(SeenPage);\n\t\t\tShow_Mouse();\n\n\t\t\tSet_Logic_Page(SeenBuff);\n\t\t\tdisplay = false;\n\t\t}\n\t\telse {\n\t\t\tif (RunningAsDLL) {\t//PG\n\t\t\t\tretval = -1;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t**\tGet and process player input.\n\t\t*/\n\t\tinput = commands->Input();\n\n#ifndef FIXIT_VERSION_3\n#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - No Internet play\n\t\t/*\n\t\t** Check to see if WChat has told us to start playing an internet game\n\t\t*/\n\t\tif (DDEServer.Get_MPlayer_Game_Info()) {\n\t\t\tretval = BUTTON_INTERNET - BUTTON_EXPAND;\n\t\t\tprocess = false;\n\t\t\tinput = KN_NONE;\n\t\t}\n#endif\t//WIN32\n#endif\n\n\t\t/*\n\t\t**\tIf there is input, then take this opportunity to seed some bits\n\t\t**\tto the cryptographic random number generator.\n\t\t*/\n\t\tif (input != 0) {\n\t\t\t#ifdef WIN32\n\t\t\t\tSYSTEMTIME t;\n\t\t\t\tGetSystemTime(&t);\n\t\t\t\tCryptRandom.Seed_Byte(t.wMilliseconds);\n\t\t\t#else\n\t\t\t\tstruct timeb t;\n\t\t\t\tftime(&t);\n\t\t\t\tCryptRandom.Seed_Byte(t.millitm);\n\t\t\t#endif\n\t\t}\n\n\t\t/*\n\t\t**\tDispatch the input to be processed.\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_EXPAND | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n#ifdef FIXIT_VERSION_3\n\t\t\tcase (BUTTON_EXPAND_AM | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (BUTTON_START | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n#ifndef FIXIT_VERSION_3\n\t\t\t#if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play\n\t\t\tcase (BUTTON_INTERNET | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t\t#endif\t//WIN32\n#endif\n\n//\t\t\t#if defined(MPEGMOVIE)\n//\t\t\tcase (BUTTON_MOVIE | KN_BUTTON):\n//\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n//\t\t\t\tprocess = false;\n//\t\t\tbreak;\n//\t\t\t#endif\n\t\t\t\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_MULTI | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_INTRO | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_EXIT | KN_BUTTON):\n\t\t\t\tretval = (input & 0x7FFF) - BUTTON_EXPAND;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n#if (0)\n\t\t\tcase KN_BACKSPACE:\n\t\t\t\tShow_Who_Was_Responsible ();\n\t\t\t\tdisplay = true;\n\t\t\t\tTheme.Play_Song(THEME_INTRO);\n\t\t\t\tbreak;\n#endif\t//(0)\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tswitch( curbutton )\n\t\t\t\t{\n\t\t\t\tcase -1:\n\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0:\n\t\t\t\t\tif( !bExpansionCS )\n\t\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tif( !bExpansionAM )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( bExpansionCS )\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcurbutton = max_buttons - 1;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#else\n\t\t\t\tif (expansions) {\n\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\tcurbutton = max_buttons-1;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (curbutton < 1) {\n\t\t\t\t\t\tcurbutton = max_buttons-1;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( curbutton == max_buttons )\n\t\t\t\t{\n\t\t\t\t\tif( bExpansionCS )\n\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\telse if( bExpansionAM )\n\t\t\t\t\t\tcurbutton = 1;\n\t\t\t\t\telse\n\t\t\t\t\t\tcurbutton = 2;\n\t\t\t\t}\n\t\t\t\telse if( curbutton == 1 && !bExpansionAM )\n\t\t\t\t\tcurbutton = 2;\n#else\n\t\t\t\tif (curbutton > (max_buttons - 1)) {\n\t\t\t\t\tif (expansions) {\n\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurbutton = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\t\tbuttons[curbutton]->Draw_Me(true);\n\t\t\t\tretval = curbutton;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\n\n\t\t\tcase KN_LMOUSE:\n#if (0)//PG\n\t\t\t\tif (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY,\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t9*RESFACTOR, 10*RESFACTOR,\n\t\t\t\t\t\t\t\t\t\t\t\t\t79*RESFACTOR, 24*RESFACTOR)){\n\t\t\t\t\tShow_Who_Was_Responsible();\n\t\t\t\t\tdisplay = true;\n\t\t\t\t\tTheme.Play_Song(THEME_INTRO);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\n#ifdef FIXIT_ANTS\n\t\t\t#ifdef FIXIT_PATCH_108\n\t\t\tif (Is_Counterstrike_Installed() == true)\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\tif ((Keyboard->Down(KN_LSHIFT) || Keyboard->Down(KN_RSHIFT)) && Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, 260*RESFACTOR, 0, 320*RESFACTOR, 50*RESFACTOR))  {\n\t\t\t\t\tAntsEnabled = true;\n\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\tretval = 2;\t\t//\tTo match SEL_START_NEW_GAME\n#else\n\t\t\t\t\tretval = 1;\n#endif\n\t\t\t\t}\n\t\t\t#ifdef FIXIT_PATCH_108\n\t\t\t}\n\t\t\t#endif\n#endif\n\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tOptions.Set_Score_Volume(oldvolume, false);\n\n\treturn(retval);\n}\n"
  },
  {
    "path": "REDALERT/MESSAGE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#define MESSAGE_NONE             \t0  \t// \n#define MESSAGE_BUILD_WINDTRAP   \t1  \t// You must build a Windtrap\n#define MESSAGE_STRUCT_CONCRETE  \t2  \t// Concrete: Use concrete to\n#define MESSAGE_STRUCT_PALACE    \t3  \t// Palace: This is your\n#define MESSAGE_STRUCT_LIGHT     \t4  \t// Light Factory: The Light\n#define MESSAGE_STRUCT_HEAVY     \t5  \t// Heavy Factory: The Heavy\n#define MESSAGE_STRUCT_HITECH    \t6  \t// Hi-Tech Factory: The\n#define MESSAGE_STRUCT_IX        \t7  \t// House IX: The IX Research\n#define MESSAGE_STRUCT_WOR       \t8  \t// WOR: Wor is used to train\n#define MESSAGE_STRUCT_CONST     \t9  \t// Construction Facility: All\n#define MESSAGE_STRUCT_WINDTRAP  \t10 \t// Windtrap: The windtrap\n#define MESSAGE_STRUCT_BARRACKS  \t11 \t// Barracks: The Barracks is\n#define MESSAGE_STRUCT_STARPORT  \t12 \t// Startport: The Starport is\n#define MESSAGE_STRUCT_REFINERY  \t13 \t// Spice Refinery: The\n#define MESSAGE_STRUCT_REPAIR    \t14 \t// Repair Facility: The Repair\n#define MESSAGE_STRUCT_WALL      \t15 \t// Wall: The wall is used for\n#define MESSAGE_STRUCT_TURRET    \t16 \t// Gun Turret: The cannon\n#define MESSAGE_STRUCT_RTURRET   \t17 \t// Rocket Turret: The\n#define MESSAGE_STRUCT_SILO      \t18 \t// Spice Silo: The Spice silo\n#define MESSAGE_STRUCT_OUTPOST   \t19 \t// Outpost: The Outpost\n#define MESSAGE_NEED_CONCRETE    \t20 \t// There isn't enough open\n#define MESSAGE_SAND             \t21 \t// Sand: This is sand terrain.\n#define MESSAGE_DUNE             \t22 \t// Sand Dunes: These are an\n#define MESSAGE_ROCK             \t23 \t// Rock: This is rock terrain.\n#define MESSAGE_MOUNT            \t24 \t// Mountain: Mountains on\n#define MESSAGE_SPICE            \t25 \t// Spice Field: This is the\n#define MESSAGE_ADJACENT         \t26 \t// Structures must be placed\n#define MESSAGE_SEARCH4SPICE     \t27 \t// Search for spice fields to\n#define MESSAGE_SANDWORM         \t28 \t// Warning: Sandworms\n"
  },
  {
    "path": "REDALERT/MISSION.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MISSION.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MISSION.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : September 14, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MissionClass::AI -- Processes order script.                                               *\n *   MissionClass::Assign_Mission -- Give an order to a unit.                                  *\n *   MissionClass::Commence -- Start script with new order.                                    *\n *   MissionClass::Debug_Dump -- Dumps status values to mono screen.                           *\n *   MissionClass::Get_Mission -- Fetches the mission that this object is acting under.        *\n *   MissionClass::MissionClass -- Default constructor for the mission object type.            *\n *   MissionClass::Mission_???  -- Stub mission functions that do nothing.                     *\n *   MissionClass::Mission_From_Name -- Fetch order pointer from its name.                     *\n *   MissionClass::Mission_Name -- Converts a mission number into an ASCII string.             *\n *   MissionClass::Override_Mission -- temporarily overrides the units mission                 *\n *   MissionClass::Restore_Mission -- Restores overridden mission                              *\n *   MissionClass::Set_Mission -- Sets the mission to the specified value.                     *\n *   MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a te*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * MissionClass::MissionClass -- Default constructor for the mission object type.              *\n *                                                                                             *\n *    This is the default constructor for the mission class object. It sets the mission        *\n *    handler into a default -- do nothing -- state.                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *   03/01/1996 JLB : Uses initializer lists.                                                  *\n *=============================================================================================*/\nMissionClass::MissionClass(RTTIType rtti, int id) :\n\tObjectClass(rtti, id),\n\tMission(MISSION_NONE),\n\tSuspendedMission(MISSION_NONE),\n\tMissionQueue(MISSION_NONE),\n\tStatus(0),\n\tTimer(0)\n{\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_???  -- Stub mission functions that do nothing.                       *\n *                                                                                             *\n *    These are the stub routines that handle the mission logic. They do nothing at this       *\n *    level. Derived classes will override these routine as necessary.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of game frames to delay before calling this mission        *\n *          handler again.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint MissionClass::Mission_Sleep(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Ambush(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Attack(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Capture(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Guard(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Guard_Area(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Harvest(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Hunt(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Move(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Retreat(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Return(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Stop(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Unload(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Enter(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Construction(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Deconstruction(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Repair(void) {return TICKS_PER_SECOND*30;};\nint MissionClass::Mission_Missile(void) {return TICKS_PER_SECOND*30;};\n\n\n/***********************************************************************************************\n * MissionClass::Set_Mission -- Sets the mission to the specified value.                       *\n *                                                                                             *\n *    Use this routine to set the current mission for this object. This routine will blast     *\n *    over the current mission, bypassing the queue method. Call it when the mission needs     *\n *    to be changed immediately.                                                               *\n *                                                                                             *\n * INPUT:   mission  -- The mission to set to.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Set_Mission(MissionType mission)\n{\n\tassert(IsActive);\n\n\tMission = mission;\n\tMissionQueue = MISSION_NONE;\n}\n\n\n/***********************************************************************************************\n * MissionClass::Get_Mission -- Fetches the mission that this object is acting under.          *\n *                                                                                             *\n *    Use this routine to fetch the mission that this object is CURRENTLY acting under. The    *\n *    mission queue may be filled with a imminent mission change, but this routine does not    *\n *    consider that. It only returns the CURRENT mission.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the mission that this unit is currently following.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMissionType MissionClass::Get_Mission(void) const\n{\n\tassert(IsActive);\n\n\treturn(Mission == MISSION_NONE ? MissionQueue : Mission);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * MissionClass::Debug_Dump -- Dumps status values to mono screen.                             *\n *                                                                                             *\n *    This is a debugging function that dumps this class' status to the monochrome screen      *\n *    for review.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(1, 9);mono->Printf(\"%-14s\", MissionClass::Mission_Name(Mission));\n\tmono->Set_Cursor(16, 9);mono->Printf(\"%-12s\", MissionClass::Mission_Name(MissionQueue));\n\tmono->Set_Cursor(1, 7);mono->Printf(\"%3d\", (long)Timer);\n\tmono->Set_Cursor(6, 7);mono->Printf(\"%2d\", Status);\n\n\tObjectClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * MissionClass::AI -- Processes order script.                                                 *\n *                                                                                             *\n *    This routine will process the order script for as much time as                           *\n *    possible or until a script delay is detected. This routine should                        *\n *    be called for every unit once per game loop (if possible).                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   06/25/1995 JLB : Added new missions.                                                      *\n *=============================================================================================*/\nvoid MissionClass::AI(void)\n{\n\tassert(IsActive);\n\n\tObjectClass::AI();\n\n\t/*\n\t**\tIf this is the kind of object that is \"paralyzed with fear\" while it is above\n\t**\tground level (such as when be paradropped), it will perform no mission AI\n\t**\tprocessing.\n\t*/\n\tif ((What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) && Height > 0) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tThis is the script AI equivalent processing.\n\t*/\n\tBStart(BENCH_MISSION);\n\tif (Timer == 0 && Strength > 0) {\n\t\tswitch (Mission) {\n\t\t\tdefault:\n\t\t\t\tTimer = Mission_Sleep();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HARMLESS:\n\t\t\tcase MISSION_SLEEP:\n\t\t\t\tTimer = Mission_Sleep();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_STICKY:\n\t\t\tcase MISSION_GUARD:\n\t\t\t\tTimer = Mission_Guard();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_ENTER:\n\t\t\t\tTimer = Mission_Enter();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_CONSTRUCTION:\n\t\t\t\tTimer = Mission_Construction();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_DECONSTRUCTION:\n\t\t\t\tTimer = Mission_Deconstruction();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_CAPTURE:\n\t\t\tcase MISSION_SABOTAGE:\n\t\t\t\tTimer = Mission_Capture();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_QMOVE:\n\t\t\tcase MISSION_MOVE:\n\t\t\t\tTimer = Mission_Move();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_ATTACK:\n\t\t\t\tTimer = Mission_Attack();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_RETREAT:\n\t\t\t\tTimer = Mission_Retreat();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HARVEST:\n\t\t\t\tTimer = Mission_Harvest();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_GUARD_AREA:\n\t\t\t\tTimer = Mission_Guard_Area();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_RETURN:\n\t\t\t\tTimer = Mission_Return();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_STOP:\n\t\t\t\tTimer = Mission_Stop();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_AMBUSH:\n\t\t\t\tTimer = Mission_Ambush();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_HUNT:\n\t\t\tcase MISSION_RESCUE:\n\t\t\t\tTimer = Mission_Hunt();\n\t\t\t\tbreak;\n\n//\t\t\tcase MISSION_TIMED_HUNT:\n//\t\t\t\tTimer = Mission_Timed_Hunt();\n//\t\t\t\tbreak;\n\n\t\t\tcase MISSION_UNLOAD:\n\t\t\t\tTimer = Mission_Unload();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_REPAIR:\n\t\t\t\tTimer = Mission_Repair();\n\t\t\t\tbreak;\n\n\t\t\tcase MISSION_MISSILE:\n\t\t\t\tTimer = Mission_Missile();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tBEnd(BENCH_MISSION);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Commence -- Start script with new order.                                      *\n *                                                                                             *\n *    This routine will start script processing according to any queued                        *\n *    order it may have. If there is no queued order, then this routine                        *\n *    does nothing. Call this routine whenever the unit is in a good                           *\n *    position to change its order (such as when it is stopped).                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Did the mission actually change?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/23/1994 JLB : Created.                                                                 *\n *   07/14/1994 JLB : Simplified.                                                              *\n *   06/17/1995 JLB : Returns success flag.                                                    *\n *=============================================================================================*/\nbool MissionClass::Commence(void)\n{\n\tassert(IsActive);\n\n\tif (MissionQueue != MISSION_NONE) {\n\t\tMission = MissionQueue;\n\t\tMissionQueue = MISSION_NONE;\n\n\t\t/*\n\t\t**\tForce immediate state machine processing at the first state machine state value.\n\t\t*/\n\t\tTimer = 0;\n\t\tStatus = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Assign_Mission -- Give an order to a unit.                                    *\n *                                                                                             *\n *    This routine will assign the specified mission to the mission queue for this object.     *\n *    The actual mission logic will then be performed at the first available and legal         *\n *    opportunity.                                                                             *\n *                                                                                             *\n * INPUT:   order -- Mission to give the unit.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1991 JLB : Created.                                                                 *\n *   04/15/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid MissionClass::Assign_Mission(MissionType order)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tEnsure that a MISSION_QMOVE is translated into a MISSION_MOVE.\n\t*/\n\tif (order == MISSION_QMOVE) order = MISSION_MOVE;\n\n\tif (order != MISSION_NONE && Mission != order)  {\n\t\tMissionQueue = order;\n\t}\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_From_Name -- Fetch order pointer from its name.                       *\n *                                                                                             *\n *    This routine is used to convert an ASCII order name into the actual                      *\n *    order number it represents. Typically, this is used when processing                      *\n *    a scenario INI file.                                                                     *\n *                                                                                             *\n * INPUT:   name  -- The ASCII order name to process.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual order number that the ASCII name                           *\n *          represents.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   04/22/1994 JLB : Converted to static member function.                                     *\n *=============================================================================================*/\nMissionType MissionClass::Mission_From_Name(char const * name)\n{\n\tMissionType\torder;\n\n\tif (name) {\n\t\tfor (order = MISSION_FIRST; order < MISSION_COUNT; order++) {\n\t\t\tif (stricmp(Missions[order], name) == 0) {\n\t\t\t\treturn(order);\n\t\t\t}\n\t\t}\n\t}\n\treturn(MISSION_NONE);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Mission_Name -- Converts a mission number into an ASCII string.               *\n *                                                                                             *\n *    Use this routine to convert a mission number into the ASCII string that represents       *\n *    it. Typical use of this is when generating an INI file.                                  *\n *                                                                                             *\n * INPUT:   mission  -- The mission number to convert.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the ASCII string that represents the mission type.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * MissionClass::Mission_Name(MissionType mission)\n{\n\tif (mission != MISSION_NONE)  {\n\t\treturn(Missions[mission]);\n\t}\n\treturn(\"None\");\n}\n\n\n/***********************************************************************************************\n * MissionClass::Override_Mission -- temporarily overrides the units mission                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:      MissionType mission - the mission we want to override                           *\n *               TARGET      tarcom  - the new target we want to override                      *\n *               TARGET      navcom  - the new navigation point to override                    *\n *                                                                                             *\n * OUTPUT:      none                                                                           *\n *                                                                                             *\n * WARNINGS:   If a mission is already overridden, the current mission is                      *\n *               just re-assigned.                                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/28/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid MissionClass::Override_Mission(MissionType mission, TARGET, TARGET)\n{\n\tassert(IsActive);\n\n\tif (MissionQueue != MISSION_NONE) {\n\t\tSuspendedMission = MissionQueue;\n\t} else {\n\t\tSuspendedMission = Mission;\n\t}\n\n\tAssign_Mission(mission);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Restore_Mission -- Restores overridden mission                                *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/28/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nbool MissionClass::Restore_Mission(void)\n{\n\tassert(IsActive);\n\n\tif (SuspendedMission != MISSION_NONE) {\n\t\tAssign_Mission(SuspendedMission);\n\t \tSuspendedMission= MISSION_NONE;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a tea *\n *                                                                                             *\n *    Some missions preclude recruitment into a team. This routine will examine the mission    *\n *    specified and if not allowed for a team, it will return false.                           *\n *                                                                                             *\n * INPUT:   mission  -- The mission type to examine.                                           *\n *                                                                                             *\n * OUTPUT:  bool; Is an object following this mission allowed to be recruited into a team?     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool MissionClass::Is_Recruitable_Mission(MissionType mission)\n{\n\tif (mission == MISSION_NONE) {\n\t\treturn(true);\n\t}\n\treturn(MissionControl[mission].IsRecruitable);\n}\n\n\n\nMissionControlClass::MissionControlClass(void) :\n\tMission(MISSION_NONE),\n\tIsNoThreat(false),\n\tIsZombie(false),\n\tIsRecruitable(true),\n\tIsParalyzed(false),\n\tIsRetaliate(true),\n\tIsScatter(true),\n\tRate(\".016\"),\n\tAARate(\".016\")\n{\n}\n\n\nchar const * MissionControlClass::Name(void) const\n{\n\tif (Mission == MISSION_NONE) {\n\t\treturn(\"<none>\");\n\t}\n\treturn(Missions[Mission]);\n}\n\n\n\nbool MissionControlClass::Read_INI(CCINIClass & ini)\n{\n\tif (ini.Is_Present(Name())) {\n\t\tIsNoThreat = ini.Get_Bool(Name(), \"NoThreat\", IsNoThreat);\n\t\tIsZombie = ini.Get_Bool(Name(), \"Zombie\", IsZombie);\n\t\tIsRecruitable = ini.Get_Bool(Name(), \"Recruitable\", IsRecruitable);\n\t\tIsParalyzed = ini.Get_Bool(Name(), \"Paralyzed\", IsParalyzed);\n\t\tIsRetaliate = ini.Get_Bool(Name(), \"Retaliate\", IsRetaliate);\n\t\tIsScatter = ini.Get_Bool(Name(), \"Scatter\", IsScatter);\n\t\tRate = ini.Get_Fixed(Name(), \"Rate\", Rate);\n\t\tAARate = ini.Get_Fixed(Name(), \"AARate\", 0);\n\t\tif (AARate == 0) {\n\t\t\tAARate = Rate;\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n"
  },
  {
    "path": "REDALERT/MISSION.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MISSION.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MISSION.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MISSION_H\n#define MISSION_H\n\n#include \"object.h\"\n#include\t\"monoc.h\"\n\n/****************************************************************************\n**\tThis handles order assignment and tracking. The order is used to guide\n**\toverall AI processing.\n*/\nclass MissionClass : public ObjectClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis the tactical strategy to use. It is used by the unit script. This\n\t\t**\tis a general guide for unit AI processing.\n\t\t*/\n\t\tMissionType Mission;\n\t\tMissionType SuspendedMission;\n\n\t\t/*\n\t\t**\tThe order queue is used for orders that should take effect when the vehicle\n\t\t**\thas reached the center point of a cell. The queued order number is +1 when stored here\n\t\t**\tso that 0 will indicated there is no queued order.\n\t\t*/\n\t\tMissionType MissionQueue;\n\n\t\tint Status;\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tMissionClass(RTTIType rtti, int id);\n\t\tMissionClass(NoInitClass const & x) : ObjectClass(x), Timer(x) {};\n\t\tvirtual ~MissionClass(void) {};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvoid  Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\n\t\tvoid Shorten_Mission_Timer(void) {Timer = 0;}\n\t\tvirtual MissionType Get_Mission(void) const;\n\t\tvirtual void  Assign_Mission(MissionType mission);\n\t\tvirtual bool Commence(void);\n\t\tvirtual void AI(void);\n\n\t\t/*\n\t\t**\tSupport functions.\n\t\t*/\n\t\tvirtual int Mission_Sleep(void);\n\t\tvirtual int Mission_Ambush(void);\n\t\tvirtual int Mission_Attack(void);\n\t\tvirtual int Mission_Capture(void);\n\t\tvirtual int Mission_Guard(void);\n\t\tvirtual int Mission_Guard_Area(void);\n\t\tvirtual int Mission_Harvest(void);\n\t\tvirtual int Mission_Hunt(void);\n//\t\tvirtual int Mission_Timed_Hunt(void);\n\t\tvirtual int Mission_Move(void);\n\t\tvirtual int Mission_Retreat(void);\n\t\tvirtual int Mission_Return(void);\n\t\tvirtual int Mission_Stop(void);\n\t\tvirtual int Mission_Unload(void);\n\t\tvirtual int Mission_Enter(void);\n\t\tvirtual int Mission_Construction(void);\n\t\tvirtual int Mission_Deconstruction(void);\n\t\tvirtual int Mission_Repair(void);\n\t\tvirtual int Mission_Missile(void);\n\t\tvirtual void  Set_Mission(MissionType mission);\n\t\tstatic bool Is_Recruitable_Mission(MissionType mission);\n\n\t\tstatic char const *  Mission_Name(MissionType order);\n\t\tstatic MissionType  Mission_From_Name(char const *name);\n\t\tvirtual void  Override_Mission(MissionType mission, TARGET, TARGET);\n\t\tvirtual bool Restore_Mission(void);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis the thread processing timer. When this value counts down to zero, then\n\t\t**\tmore script processing may occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Timer;\n};\n\n\n/****************************************************************************\n**\tThis is the mission control (pun) that controls how each mission behaves\n**\twhen it comes to interacting with the game world. Example; some\n**\tmissions allow the object to scatter from threats, while others require\n**\tthe object to remain in place. This kind of characteristics are specfied\n**\tby this class.\n*/\nclass MissionControlClass\n{\n\tpublic:\n\t\tMissionControlClass(void);\n\n\t\tbool Read_INI(CCINIClass & ini);\n\t\tint Normal_Delay(void) const {return(TICKS_PER_MINUTE * Rate);}\n\t\tint AA_Delay(void) const {return(TICKS_PER_MINUTE * AARate);}\n\n\t\t/*\n\t\t**\tThis is the mission identifier that this mission represents.\n\t\t*/\n\t\tMissionType Mission;\n\n\t\tchar const * Name(void) const;\n\n\t\t/*\n\t\t**\tIf the object should not be considered a threat when it\n\t\t**\tcomes to target scanning, then this will be true.\n\t\t*/\n\t\tunsigned IsNoThreat:1;\n\n\t\t/*\n\t\t**\tIf objects in this mission should avoid targeting the enemy and\n\t\t**\talso avoid responding to the enemy, then this will be true.\n\t\t*/\n\t\tunsigned IsZombie:1;\n\n\t\t/*\n\t\t**\tAn ojbect that can be recruited into a team must be on a mission\n\t\t**\tof this type.\n\t\t*/\n\t\tunsigned IsRecruitable:1;\n\n\t\t/*\n\t\t**\tIf the object can behave normally except that it cannot\n\t\t**\tmove to another location, then this flag will be true.\n\t\t*/\n\t\tunsigned IsParalyzed:1;\n\n\t\t/*\n\t\t**\tIf an object on this mission is damaged, it is allowed to\n\t\t**\tretaliate?\n\t\t*/\n\t\tunsigned IsRetaliate:1;\n\n\t\t/*\n\t\t**\tIs the object allowed to scatter from immediate threats?\n\t\t*/\n\t\tunsigned IsScatter:1;\n\n\t\t/*\n\t\t**\tThis specifies the time to delay between calls to the mission handler for those cases\n\t\t**\twhere the delay could be indefinate. The exception would be when timing is critical.\n\t\t**\tTypical use of this would be to regulate the delay between mundane mission processing\n\t\t**\tin order to achieve less game overhead.\n\t\t*/\n\t\tfixed Rate;\n\n\t\t/*\n\t\t**\tAnti-Aircraft buildings (and units) in guard or guard area mode will use this override\n\t\t**\tdelay interval instead of the normal \"Rate\" value.\n\t\t*/\n\t\tfixed AARate;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MIXFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MIXFILE.CPP 2     3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MIXFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 12, 1996 [JLB]                                          *\n *                                                                                             *\n *                                                                                             *\n *                  Modified by Vic Grippi for WwXlat Tool 10/14/96                            *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MixFileClass::Cache -- Caches the named mixfile into RAM.                                 *\n *   MixFileClass::Cache -- Loads this particular mixfile's data into RAM.                     *\n *   MixFileClass::Finder -- Finds the mixfile object that matches the name specified.         *\n *   MixFileClass::Free -- Uncaches a cached mixfile.                                          *\n *   MixFileClass::MixFileClass -- Constructor for mixfile object.                             *\n *   MixFileClass::Offset -- Searches in mixfile for matching file and returns offset if found.*\n *   MixFileClass::Retrieve -- Retrieves a pointer to the specified data file.                 *\n *   MixFileClass::~MixFileClass -- Destructor for the mixfile object.                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"buff.h\"\n#include\t\"function.h\"\n#include\t<direct.h>\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\n#include\t<errno.h>\n#include\t<share.h>\n#include\t\"mixfile.h\"\n\n#include\t\"cdfile.h\"\nextern MFCD temp;\n\n//template<class T> int Compare(T const *obj1, T const *obj2) {\n//\tif (*obj1 < *obj2) return(-1);\n//\tif (*obj1 > *obj2) return(1);\n//\treturn(0);\n//};\n\n\n/*\n**\tThis is the pointer to the first mixfile in the list of mixfiles registered\n**\twith the mixfile system.\n*/\ntemplate<class T>\nList<MixFileClass<T> > MixFileClass<T>::List;\n\ntemplate class MixFileClass<CCFileClass>;\n\n/***********************************************************************************************\n * MixFileClass::Free -- Uncaches a cached mixfile.                                            *\n *                                                                                             *\n *    Use this routine to uncache a mixfile that has been cached.                              *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the mixfile that is to be uncached.         *\n *                                                                                             *\n * OUTPUT:  bool; Was the mixfile found and freed?                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Free(char const * filename)\n{\n\tMixFileClass * ptr = Finder(filename);\n\n\tif (ptr) {\n\t\tptr->Free();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::~MixFileClass -- Destructor for the mixfile object.                           *\n *                                                                                             *\n *    This destructor will free all memory allocated by this mixfile and will remove it from   *\n *    the system. A mixfile removed in this fashion must be created anew in order to be        *\n *    subsequent used.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   01/06/1995 JLB : Puts mixfile header table into EMS.                                      *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T>::~MixFileClass(void)\n{\n\t/*\n\t**\tDeallocate any allocated memory.\n\t*/\n\tif (Filename) {\n\t\tfree((char *)Filename);\n\t}\n\tif (Data != NULL && IsAllocated) {\n\t\tdelete [] Data;\n\t\tIsAllocated = false;\n\t}\n\tData = NULL;\n\n\tif (HeaderBuffer != NULL) {\n\t\tdelete [] HeaderBuffer;\n\t\tHeaderBuffer = NULL;\n\t}\n\n\t/*\n\t**\tUnlink this mixfile object from the chain.\n\t*/\n\tUnlink();\n}\n\n\n/***********************************************************************************************\n * MixFileClass::MixFileClass -- Constructor for mixfile object.                               *\n *                                                                                             *\n *    This is the constructor for the mixfile object. It takes a filename and a memory         *\n *    handler object and registers the mixfile object with the system. The index block is      *\n *    allocated and loaded from disk by this routine.                                          *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the mixfile object.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   07/12/1996 JLB : Handles compressed file header.                                          *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T>::MixFileClass(char const * filename, PKey const * key) :\n\tIsDigest(false),\n\tIsEncrypted(false),\n\tIsAllocated(false),\n\tFilename(0),\n\tCount(0),\n\tDataSize(0),\n\tDataStart(0),\n\tHeaderBuffer(0),\n\tData(0)\n{\n\tif (filename == NULL) return;\t// ST - 5/9/2019\n\n\t/*\n\t**\tCheck to see if the file is available. If it isn't, then\n\t**\tno further processing is needed or possible.\n\t*/\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\tProg_End(\"MixFileClass Force_CD_Available failed\", true);\n\t\tif (!RunningAsDLL) {\t//PG\n\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t}\n\t}\n\n\tT file(filename);\t\t// Working file object.\n\tFilename = strdup(file.File_Name());\n\tFileStraw fstraw(file);\n\tPKStraw pstraw(PKStraw::DECRYPT, CryptRandom);\n\tStraw * straw = &fstraw;\n\n\tif (!file.Is_Available()) return;\n\n\t/*\n\t**\tStuctures used to hold the various file headers.\n\t*/\n\tFileHeader fileheader;\n\tstruct {\n\t\tshort First;\t\t// Always zero for extended mixfile format.\n\t\tshort Second;\t\t// Bitfield of extensions to this mixfile.\n\t} alternate;\n\n\t/*\n\t**\tFetch the first bit of the file. From this bit, it is possible to detect\n\t**\twhether this is an extended mixfile format or the plain format. An\n\t**\textended format may have extra options or data layout.\n\t*/\n\tint got = straw->Get(&alternate, sizeof(alternate));\n\n\t/*\n\t**\tDetect if this is an extended mixfile. If so, then see if it is encrypted\n\t**\tand/or has a message digest attached. Otherwise, just retrieve the\n\t**\tplain mixfile header.\n\t*/\n\tif (alternate.First == 0) {\n\t\tIsDigest = ((alternate.Second & 0x01) != 0);\n\t\tIsEncrypted = ((alternate.Second & 0x02) != 0);\n\n\t\tif (IsEncrypted) {\n\t\t\tpstraw.Key(key);\n\t\t\tpstraw.Get_From(&fstraw);\n\t\t\tstraw = &pstraw;\n\t\t}\n\t\tstraw->Get(&fileheader, sizeof(fileheader));\n\n\t} else {\n\t\tmemmove(&fileheader, &alternate, sizeof(alternate));\n\t\tstraw->Get(((char*)&fileheader)+sizeof(alternate), sizeof(fileheader)-sizeof(alternate));\n\t}\n\n\tCount = fileheader.count;\n\tDataSize = fileheader.size;\n//BGMono_Printf(\"Mixfileclass %s DataSize: %08x   \\n\",filename,DataSize);Get_Key();\n\t/*\n\t**\tLoad up the offset control array. If RAM is exhausted, then the mixfile is invalid.\n\t*/\n\tHeaderBuffer = new SubBlock [Count];\n\tif (HeaderBuffer == NULL) return;\n\tstraw->Get(HeaderBuffer, Count * sizeof(SubBlock));\n\n\t/*\n\t**\tThe start of the embedded mixfile data will be at the current file offset.\n\t**\tThis should be true even if the file header has been encrypted because the file\n\t**\theader was cleverly written with just the sufficient number of padding bytes so\n\t**\tthat this condition would be true.\n\t*/\n\tDataStart = file.Seek(0, SEEK_CUR) + file.BiasStart;\n//\tDataStart = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tAttach to list of mixfiles.\n\t*/\n\tList.Add_Tail(this);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Retrieve -- Retrieves a pointer to the specified data file.                   *\n *                                                                                             *\n *    This routine will return with a pointer to the specified data file if the file resides   *\n *    in memory. Otherwise, this routine returns NULL. Use this routine to access a resident   *\n *    file directly rather than going through the process of pseudo disk access. This will     *\n *    save both time and RAM.                                                                  *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename of the data file to retrieve a pointer to.     *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the data file's data. If the file is not in RAM, then    *\n *          NULL is returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid const * MixFileClass<T>::Retrieve(char const * filename)\n{\n\tvoid * ptr = 0;\n\tOffset(filename, &ptr);\n\treturn(ptr);\n};\n\n\n/***********************************************************************************************\n * MixFileClass::Finder -- Finds the mixfile object that matches the name specified.           *\n *                                                                                             *\n *    This routine will scan through all registered mixfiles and return with a pointer to      *\n *    the matching mixfile. If no mixfile could be found that matches the name specified,      *\n *    then NULL is returned.                                                                   *\n *                                                                                             *\n * INPUT:   filename -- Pointer to the filename to search for.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the matching mixfile -- if found.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   06/08/1996 JLB : Only compares filename and extension.                                    *\n *=============================================================================================*/\ntemplate<class T>\nMixFileClass<T> * MixFileClass<T>::Finder(char const * filename)\n{\n\tMixFileClass<T> * ptr = List.First();\n\twhile (ptr->Is_Valid()) {\n\t\tchar path[_MAX_PATH];\n\t\tchar name[_MAX_FNAME];\n\t\tchar ext[_MAX_EXT];\n\n\t\t/*\n\t\t**\tStrip the drive and path (if present) off of the filename\n\t\t**\tin the mixfile list. This enables a simple comparison to the\n\t\t**\tfilename specified. The filename specified won't have a path attached and\n\t\t**\tthe full pathname in the mixfile list WILL have a path attached. Hence, this\n\t\t** stripping of the path is necessary.\n\t\t*/\n\t\t_splitpath(ptr->Filename, NULL, NULL, name, ext);\n\t\t_makepath(path, NULL, NULL, name, ext);\n\n\t\tif (stricmp(path, filename) == 0) {\n\t\t\treturn(ptr);\n\t\t}\n\t\tptr = ptr->Next();\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Cache -- Caches the named mixfile into RAM.                                   *\n *                                                                                             *\n *    This routine will cache the mixfile, specified by name, into RAM.                        *\n *                                                                                             *\n * INPUT:   filename -- The name of the mixfile that should be cached.                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the cache successful?                                                    *\n *                                                                                             *\n * WARNINGS:   This routine could go to disk for a very long time.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Cache(char const * filename, Buffer const * buffer)\n{\n\tMixFileClass<T> * mixer = Finder(filename);\n\n\tif (mixer != NULL) {\n\t\treturn(mixer->Cache(buffer));\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Cache -- Loads this particular mixfile's data into RAM.                       *\n *                                                                                             *\n *    This load the mixfile data into ram for this mixfile object. This is the counterpart     *\n *    to the Free() function.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file load successful?  It could fail if there wasn't enough room     *\n *                to allocate the raw data block.                                              *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk for a potentially very long time.                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *   07/12/1996 JLB : Handles attached message digest.                                         *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Cache(Buffer const * buffer)\n{\n\t/*\n\t**\tIf the mixfile is already cached, then no action needs to be performed.\n\t*/\n\tif (Data != NULL) return(true);\n\n\t/*\n\t**\tIf a buffer was supplied (and it is big enough), then use it as the data block\n\t**\tpointer. Otherwise, the data block must be allocated.\n\t*/\n\tif (buffer != NULL) {\n\t\tif (buffer->Get_Size() == 0 || buffer->Get_Size() >= DataSize) {\n\t\t\tData = buffer->Get_Buffer();\n\t\t}\n\t} else {\n\t\tData = new char [DataSize];\n\t\tIsAllocated = true;\n\t}\n\n\t/*\n\t**\tIf there is a data buffer to fill, then fill it now.\n\t*/\n\tif (Data != NULL) {\n\t\tT file(Filename);\n\n\t\tFileStraw fstraw(file);\n\t\tStraw * straw = &fstraw;\n\n\t\t/*\n\t\t**\tIf a message digest is attached, then link a SHA straw segment to the data\n\t\t**\tstream so that the actual SHA can be compared with the attached one.\n\t\t*/\n\t\tSHAStraw sha;\n\t\tif (IsDigest) {\n\t\t\tsha.Get_From(fstraw);\n\t\t\tstraw = &sha;\n\t\t}\n\n\t\t/*\n\t\t**\tBias the file to the actual start of the data. This is necessary because the\n\t\t**\treal data starts some distance (not so easily determined) from the beginning of\n\t\t**\tthe real file.\n\t\t*/\n\t\tfile.Open(READ);\n\t\tfile.Bias(0);\n\t\tfile.Bias(DataStart);\n\n\t\t/*\n\t\t**\tFetch the whole mixfile data in one step. If the number of bytes retrieved\n\t\t**\tdoes not equal that requested, then this indicates a serious error.\n\t\t*/\n\t\tlong actual = straw->Get(Data, DataSize);\n\t\tif (actual != DataSize) {\n\t\t\tdelete [] Data;\n\t\t\tData = NULL;\n\t\t\tfile.Error(EIO);\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t**\tIf there is a digest attached to this mixfile, then read it in and\n\t\t**\tcompare it to the generated digest. If they don't match, then\n\t\t**\treturn with the \"failure to cache\" error code.\n\t\t*/\n\t\tif (IsDigest) {\n\t\t\tchar digest1[20];\n\t\t\tchar digest2[20];\n\t\t\tsha.Result(digest2);\n\t\t\tfstraw.Get(digest1, sizeof(digest1));\n\t\t\tif (memcmp(digest1, digest2, sizeof(digest1)) != 0) {\n\t\t\t\tdelete [] Data;\n\t\t\t\tData = NULL;\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\n\t\treturn(true);\n\t}\n\tIsAllocated = false;\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Free -- Frees the allocated raw data block (not the index block).             *\n *                                                                                             *\n *    This routine will free the (presumably large) raw data block, but leave the index        *\n *    block intact. By using this in conjunction with the Cache() function, one can maintain   *\n *    tight control of memory usage. If the index block is desired to be freed, then the       *\n *    mixfile object must be deleted.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid MixFileClass<T>::Free(void)\n{\n\tif (Data != NULL && IsAllocated) {\n\t\tdelete [] Data;\n\t}\n\tData = NULL;\n\tIsAllocated = false;\n}\n\n\nint compfunc(void const * ptr1, void const * ptr2)\n{\n\tif (*(long const *)ptr1 < *(long const *)ptr2) return(-1);\n\tif (*(long const *)ptr1 > *(long const *)ptr2) return(1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * MixFileClass::Offset -- Determines the offset of the requested file from the mixfile system.*\n *                                                                                             *\n *    This routine will take the filename specified and search through the mixfile system      *\n *    looking for it. If the file was found, then the mixfile it was found in, the offset      *\n *    from the start of the mixfile, and the size of the embedded file will be returned.       *\n *    Using this method it is possible for the CCFileClass system to process it as a normal    *\n *    file.                                                                                    *\n *                                                                                             *\n * INPUT:   filename    -- The filename to search for.                                         *\n *                                                                                             *\n *          realptr     -- Stores a pointer to the start of the file in memory here. If the    *\n *                         file is not in memory, then NULL is stored here.                    *\n *                                                                                             *\n *          mixfile     -- The pointer to the corresponding mixfile is placed here. If no      *\n *                         mixfile was found that contains the file, then NULL is stored here. *\n *                                                                                             *\n *          offset      -- The starting offset from the beginning of the parent mixfile is     *\n *                         stored here.                                                        *\n *                                                                                             *\n *          size        -- The size of the embedded file is stored here.                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the file found? The file may or may not be resident, but it does exist   *\n *                 and can be opened.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool MixFileClass<T>::Offset(char const * filename, void ** realptr, MixFileClass ** mixfile, long * offset, long * size) \n{\n\tMixFileClass<T> * ptr;\n\n\tif (filename == NULL) {\nassert(filename != NULL);//BG\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCreate the key block that will be used to binary search for the file.\n\t*/\n\t// Can't call strupr on a const string. ST - 5/20/2019\n\t//long crc = Calculate_CRC(strupr((char *)filename), strlen(filename));\n\tchar filename_upper[_MAX_PATH];\n\tstrcpy(filename_upper, filename);\n\tstrupr(filename_upper);\n\tlong crc = Calculate_CRC(strupr(filename_upper), strlen(filename_upper));\n\tSubBlock key;\n\tkey.CRC = crc;\n\n\t/*\n\t**\tSweep through all registered mixfiles, trying to find the file in question.\n\t*/\n\tptr = List.First();\n\twhile (ptr->Is_Valid()) {\n\t\tSubBlock * block;\n\n\t\t/*\n\t\t**\tBinary search for the file in this mixfile. If it is found, then extract the\n\t\t**\tappropriate information and store it in the locations provided and then return.\n\t\t*/\n\t\tblock = (SubBlock *)bsearch(&key, ptr->HeaderBuffer, ptr->Count, sizeof(SubBlock), compfunc);\n\t\tif (block != NULL) {\n\t\t\tif (mixfile != NULL) *mixfile = ptr;\n\t\t\tif (size != NULL) *size = block->Size;\n\t\t\tif (realptr != NULL) *realptr = NULL;\n\t\t\tif (offset != NULL) *offset = block->Offset;\n\t\t\tif (realptr != NULL && ptr->Data != NULL) {\n\t\t\t\t*realptr = (char *)ptr->Data + block->Offset;\n\t\t\t}\n\t\t\tif (ptr->Data == NULL && offset != NULL) {\n\t\t\t\t*offset += ptr->DataStart;\n\t\t\t}\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tAdvance to next mixfile.\n\t\t*/\n\t\tptr = ptr->Next();\n\t}\n\n\t/*\n\t**\tAll the mixfiles have been examined but no match was found. Return with the non success flag.\n\t*/\nassert(1);//BG\n\treturn(false);\n}\n\n\n\n// ST - 12/18/2019 11:36AM\ntemplate<class T>\nvoid MixFileClass<T>::Free_All(void)\n{\n\tMixFileClass<T> * ptr = List.First();\n\twhile (ptr->Is_Valid()) {\n\t\tdelete ptr;\n\t\tptr = List.First();\n\t}\n}\n"
  },
  {
    "path": "REDALERT/MIXFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MIXFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n\n#ifndef MIXFILE_H\n#define MIXFILE_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include\t<stdlib.h>\n#include\t\"listnode.h\"\n#include\t\"pk.h\"\n#include \"buff.h\"\n\ntemplate<class T>\nclass MixFileClass : public Node<MixFileClass<T>>\n{\n\tpublic:\n\t\tchar const * Filename;\t\t\t// Filename of mixfile.\n\n\n\t\tMixFileClass(char const *filename, PKey const * key);\n\t\t~MixFileClass(void);\n\n\t\tstatic bool Free(char const *filename);\n\t\tvoid Free(void);\n\t\tstatic void Free_All(void);\t// ST - 12/18/2019 11:35AM\n\t\tbool Cache(Buffer const * buffer = NULL);\n\t\tstatic bool Cache(char const *filename, Buffer const * buffer=NULL);\n\t\tstatic bool Offset(char const *filename, void ** realptr = 0, MixFileClass ** mixfile = 0, long * offset = 0, long * size = 0);\n\t\tstatic void const * Retrieve(char const *filename);\n\n\t\tstruct SubBlock {\n\t\t\tlong CRC;\t\t\t\t// CRC code for embedded file.\n\t\t\tlong Offset;\t\t\t// Offset from start of data section.\n\t\t\tlong Size;\t\t\t\t// Size of data subfile.\n\n\t\t\tint operator < (SubBlock & two) const {return (CRC < two.CRC);};\n\t\t\tint operator > (SubBlock & two) const {return (CRC > two.CRC);};\n\t\t\tint operator == (SubBlock & two) const {return (CRC == two.CRC);};\n\t\t};\n\n\tprivate:\n\t\tstatic MixFileClass * Finder(char const * filename);\n\t\t//long Offset(long crc, long * size = 0) const;\t// ST - 5/10/2019\n\n\t\t/*\n\t\t**\tIf this mixfile has an attached message digest, then this flag\n\t\t**\twill be true. The digest is checked only when the mixfile is\n\t\t**\tcached.\n\t\t*/\n\t\tunsigned IsDigest:1;\n\n\t\t/*\n\t\t**\tIf the header to this mixfile has been encrypted, then this flag\n\t\t**\twill be true. Although the header of the mixfile may be encrypted,\n\t\t**\tthe attached data files are not.\n\t\t*/\n\t\tunsigned IsEncrypted:1;\n\n\t\t/*\n\t\t**\tIf the cached memory block was allocated by this routine, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsAllocated:1;\n\n\t\t/*\n\t\t**\tThis is the initial file header. It tells how many files are embedded\n\t\t**\twithin this mixfile and the total size of all embedded files.\n\t\t*/\n\t\ttypedef struct {\n\t\t\tshort\tcount;\n\t\t\tlong\tsize;\n\t\t} FileHeader;\n\n\t\t/*\n\t\t**\tThe number of files within the mixfile.\n\t\t*/\n\t\tint Count;\n\n\t\t/*\n\t\t**\tThis is the total size of all the data file embedded within the mixfile.\n\t\t**\tIt does not include the header or digest bytes.\n\t\t*/\n\t\tlong DataSize;\n\n\t\t/*\n\t\t**\tStart of raw data in within the mixfile.\n\t\t*/\n\t\tlong DataStart;\n\n\t\t/*\n\t\t**\tPoints to the file header control block array. Each file in the mixfile will\n\t\t**\thave an entry in this table. The entries are sorted by their (signed) CRC value.\n\t\t*/\n\t\tSubBlock * HeaderBuffer;\n\n\t\t/*\n\t\t**\tIf the mixfile has been cached, then this points to the cached data.\n\t\t*/\n\t\tvoid * Data;\t\t\t\t\t\t// Pointer to raw data.\n\n\t\tstatic List<MixFileClass> List;\n};\n\n#endif"
  },
  {
    "path": "REDALERT/MMX.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S  I N C  **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : MMX.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Steve Tall                               *\n;*                                                                         *\n;*                   Start Date : May 19th, 1996                           *\n;*                                                                         *\n;*                  Last Update : May 19th 1996 [ST]                       *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\n ;\t\tinclude\t<mmx.inc>\n\n\n\t\t.model\tflat\n\t\t;.686\n\n\n\t\texterndef\tC Detect_MMX_Availability:near\n\t\texterndef\tC Single_Line_Trans_Entry:near\n\t\texterndef\tC Next_Line:near\n\t\texterndef\tC Init_MMX:near\n\t\texterndef\tC MMX_Done:near\n\n\t\texterndef\tEndNewShapeJumpTable:byte\n\t\texterndef\tNewShapeJumpTable:dword\n\t\texterndef\tC Single_Line_Trans:near\n\t\texterndef\tMMX_Single_Line_Trans:near\n\n\n\t\t.code\n\nexterndef\tC CPUType:byte\nexterndef\tC VendorID:byte\n\n\n\n;*********************************************************************************************\n;* Detect_MMX_Availability -- Detect the presence of MMX technology.                         *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      True if MMX technology is available.                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* Note: Based in part on CPUID32.ASM by Intel                                               *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nDetect_MMX_Availability proc C\n\n\t\tlocal\tidflag:byte\n\t\tlocal\tlocal_cputype:byte\n\n\t\t; MMX always available now. ST - 1/3/2019 1:31PM\n\t\tmov\t[CPUType], 5\n\t\tmov\teax, 1\n\t\tret\n\n\n;assume processor is at least 386\n;\n;check whether AC bit in eflags can be toggled.\n;If not then processor is 386\n\n\t\tmov\t[idflag],0\n\n\t\tpushfd\t\t\t;get Eflags in EAX\n\t\tpop\teax\n\t\tmov\tecx,eax\t\t;save eflags\n\t\txor\teax,40000h\t;toggle AC bit in eflags\n\t\tpush\teax\t\t;new eflags on stack\n\t\tpopfd\t\t\t;move new value into eflags\n\t\tpushfd\t\t\t;get new eflags back into eax\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;if AC bit not toggled then CPU=386\n\t\tmov\t[local_cputype],3\n\t\tjz\t@@end_get_cpu\t;cpu is 386\n\n\t\tpush\tecx\n\t\tpopfd\t\t\t;restore AC bit in eflags\n\n\n;processor is at least 486\n;\n;Check for ability to set/clear ID flag in EFLAGS\n;ID flag indicates ability of processor to execute the CPUID instruction.\n;486 not guaranteed to have CPUID inst?\n;\n\t\tmov\t[local_cputype],4\n\t\tmov\teax,ecx\t\t;original EFLAGS\n\t\txor\teax,200000h\t;toggle ID bit\n\t\tpush\teax\n\t\tpopfd\n\t\tpushfd\n\t\tpop\teax\n\t\txor\teax,ecx\t\t;check if still toggled\n\t\tjz\t@@end_get_cpu\n\n\n;       Execute CPUID instruction to determine vendor, family,\n;       model and stepping.\n;\n\n\t\tmov\t[idflag],1\t;flag ID is available\n\n\t\txor\teax,eax\n\t\tcpuid\n\n\t\tmov\tdword ptr [VendorID],ebx\n\t\tmov\tdword ptr [VendorID+4],edx\n\t\tmov\tdword ptr [VendorID+8],ecx\n\t\tmov\tdword ptr [VendorID+12],\" \"\n\n\t\tcmp\teax,1\t\t;check if 1 is valid\n\t\tjl\t@@end_get_cpu\t;inp for cpuid inst.\n\n\t\txor\teax,eax\n\t\tinc\teax\n\n\t\tcpuid\t\t;get stepping, model and family\n\n\t\tand     ax,0f00H\n\t\tshr     ax,08H\n\n\t\tmov\t[local_cputype],al\n\n@@end_get_cpu:\tmov\tal,[local_cputype]\n\t\tmov\t[CPUType],al\n\n\n;\n; We have the CPU type in al now.\n; If we arent on at least a pentium then we can assume there is no MMX\n;\n\t\tcmp\tal,5\n\t\tjl\t@@no_mmx\n\n\t\tmov\teax,1\n\t\tcpuid\n\t\ttest\tedx,00800000h\n\t\tjz\t@@no_mmx\n\n;\n; MMX detected - return true\n;\n\t\tmov\teax,1\n\t\tret\n\n\n@@no_mmx:\txor\teax,eax\n\t\tret\n\n\nDetect_MMX_Availability endp\n\n\n\n;*********************************************************************************************\n;* Init_MMX -- Do any special inits required for MMX support                                 *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nInit_MMX\tproc C\n\n\t\tmov\tedi,offset NewShapeJumpTable\n\t\tmov\tecx,offset EndNewShapeJumpTable\n\t\tsub\tecx,edi\n\t\tshr\tecx,2\n\t\tmov\teax,offset Single_Line_Trans\n\t\tmov\tebx,offset MMX_Single_Line_Trans\n\t\tcld\n\n\n@@patch_loop:   repnz\tscasd\n\t\tjnz\t@@done\n\t\tmov\t[edi-4],ebx\n\t\ttest\tecx,ecx\n\t\tjnz\t@@patch_loop\n\n@@done:\t\tret\n\nInit_MMX\tendp\n\n\n\n\n\n\n;*********************************************************************************************\n;* MMX_Done -- Restores floating point capability after MMX usage                            *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tNothing                                                                      *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\nMMX_Done\tproc C\n\n\t\temms\n\t\tret\n\nMMX_Done\tendp\n\n\n\n\n\n\n\n\t\tcode segment page public use32 'code'\t; Need stricter segment alignment\n\t\t\t\t\t\t\t; for pentium optimisations\n\n\n;*********************************************************************************************\n;* MMX_Single_Line_Trans -- draw a single line of transparent pixels using MMX technology    *\n;*                                                                                           *\n;*                                                                                           *\n;* INPUT:\tEsi - ptr to source data                                                     *\n;*              Edi - ptr to destination data                                                *\n;*              Ecx - width to draw in bytes                                                 *\n;*                                                                                           *\n;* OUTPUT:      None                                                                         *\n;*                                                                                           *\n;* Warnings:                                                                                 *\n;*                                                                                           *\n;* HISTORY:                                                                                  *\n;*   05/19/96 ST : Created.                                                                  *\n;*===========================================================================================*\n\n\t\talign\t16\n\nMMX_Single_Line_Trans proc near\n\n;\n; If we are doing less than 8 bytes then dont use MMX\n;\n\t\tcmp\tecx,8\n\t\tjge\t@@mmx_loop\n\t\tpush\toffset Single_Line_Trans_Entry\n\t\tret\n\n;\n; Use MMX instructions to mask 8 bytes at once\n;\n; Creates a bitmask based on the source bytes equality with zero and then uses this to mask\n; out the source bytes in the destination data. The advatage that MMX gives us is that there is\n; no 'test for zero then jump' required to mask.\n;\n\t\talign\t64\t\t;MMX instructions like 64 byte alignment!\n\n@@mmx_loop:\n\t\tmovq\tmm0,[esi]\t; move 8 bytes of source into mm0\n\t\tpxor\tmm1,mm1\t\t; zero out mm1\n\t\tpcmpeqb mm1,mm0\t\t; compare mm0 with 0. Bits get set in mm1\n\t\tlea\tesi,[esi+8]     ; adjust the source data pointer\n\t\tpand\tmm1,[edi]\t; and in the destination data to throw away the bytes which arent zero in the source\n\t\tsub\tecx,8\t\t; adjust the byte counter\n\t\tpor\tmm1,mm0         ; or in the source with the destination data\n\t\tmovq\t[edi],mm1       ; write back the destination data\n\t\tlea\tedi,[edi+8]\t; adjust the destination pointer\n\n\t\tcmp\tecx,8\n\t\tjg\t@@mmx_loop\n\n;\n; Jump to the approprite code for drawing the end of this line or going to the next one\n;\n\t\tpush\toffset Next_Line\n\t\tjcxz   \t@@next_line\n\t\tpush\toffset Single_Line_Trans_Entry\n@@next_line:\tret\n\n\nMMX_Single_Line_Trans endp\n\n\ncode ends\n\n\t\t.data\n\nCPUType\t\tdb\t0\nVendorID\tdb\t\"Not available\",0,0,0,0,0,0\n\n\nend"
  },
  {
    "path": "REDALERT/MONOC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MONOC.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MonoClass::Clear -- Clears the monochrome screen object.                                  *\n *   MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                     *\n *   MonoClass::Fill_Attrib -- Fill a block with specified attribute.                          *\n *   MonoClass::MonoClass -- The default constructor for monochrome screen object.             *\n *   MonoClass::Pan -- Scroll the window right or left.                                        *\n *   MonoClass::Print -- Prints the text string at the current cursor coordinates.             *\n *   MonoClass::Print -- Simple print of text number.                                          *\n *   MonoClass::Printf -- Prints a formatted string to the monochrome screen.                  *\n *   MonoClass::Printf -- Prints formatted text using text string number.                      *\n *   MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.              *\n *   MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.         *\n *   MonoClass::Sub_Window -- Partitions the mono screen into a sub-window.                    *\n *   MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.   *\n *   MonoClass::Text_Print -- Simple text printing from text number.                           *\n *   MonoClass::View -- Brings the mono object to the main display.                            *\n *   MonoClass::operator = -- Handles making one mono object have the same imagery as another. *\n *   MonoClass::~MonoClass -- The default destructor for a monochrome screen object.           *\n *   Mono_Clear_Screen -- Clear the currently visible monochrome page.                         *\n *   Mono_Draw_Rect -- Draws rectangle to monochrome screen.                                   *\n *   Mono_Print -- Prints simple text to monochrome screen.                                    *\n *   Mono_Printf -- Prints formatted text to visible page.                                     *\n *   Mono_Text_Print -- Prints text to location specified.                                     *\n *   Mono_X -- Fetches the X cursor position for current visible mono page.                    *\n *   Mono_Y -- Fetches the Y cursor position for current mono page.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n//#if (0)//PG\n//#include\t\"watcom.h\"\n#include\t\"monoc.h\"\n\n#include\t\"function.h\"\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<dos.h>\n//#include\t<mem.h>\n#include\t<stdarg.h>\n#include\t<string.h>\n\n\n//PG\n//extern void output(short port, short data);\n//#pragma aux output parm [dx] [ax] =\t\t\\\n//\t\t\"out\tdx,al\"\t\t\\\n//\t\t\"inc\tdx\"\t\t\t\\\n//\t\t\"mov\tal,ah\"\t\t\\\n//\t\t\"out\tdx,al\"\n\n\nbool MonoClass::Enabled = 0;\nMonoClass * MonoClass::PageUsage[MonoClass::MAX_MONO_PAGES];\n//MonoClass::MonoPageType * MonoClass::MonoRAM = (MonoClass::MonoPageType *) 0xB0000;\n\n/*\n**\tThese are the IBM linedraw characters.\n*/\nMonoClass::BoxDataType const MonoClass::CharData[MonoClass::COUNT] = {\n\t{0xDA,0xC4,0xBF,0xB3,0xD9,0xC4,0xC0,0xB3},\t// Single line\n\t{0xD5,0xCD,0xB8,0xB3,0xBE,0xCD,0xD4,0xB3},\t// Double horz.\n\t{0xD6,0xC4,0xB7,0xBA,0xBD,0xC4,0xD3,0xBA},\t// Double vert.\n\t{0xC9,0xCD,0xBB,0xBA,0xBC,0xCD,0xC8,0xBA}\t\t// Double horz and vert.\n};\n\n\n#ifdef NEVER\ntemplate<class T>\nT min(T a, T b) {\n\tif (a < b) return(a);\n\treturn(b);\n}\n\ntemplate<class T>\nT max(T a, T b) {\n\tif (a > b) return(a);\n\treturn(b);\n}\n#endif\n\n\n/***********************************************************************************************\n * MonoClass::MonoClass -- The default constructor for monochrome screen object.               *\n *                                                                                             *\n *    This is the constructor for monochrome screen objects. It handles allocating a free      *\n *    monochrome page. If there are no more pages available, then this is a big error. The     *\n *    page allocated may not be the visible one. Call the View function in order to bring      *\n *    it to the displayed page.                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::MonoClass(void) :\n\tX(0),\n\tY(0),\n\tAttrib(NORMAL),\n\tPage(0),\n\tSubX(0),\n\tSubY(0),\n\tSubW(COLUMNS),\n\tSubH(LINES)\n{\n\tint\tindex;\n\n\tfor (index = 0; index < MAX_MONO_PAGES; index++) {\n\t\tif (!PageUsage[index]) {\n\t\t\tPageUsage[index] = this;\n\t\t\tPage = (char)index;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (index == MAX_MONO_PAGES) {\n\t\t// Major error message should pop up here!\n\t\tdelete this;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::~MonoClass -- The default destructor for a monochrome screen object.             *\n *                                                                                             *\n *    This is the default destructor for a monochrome screen object.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass::~MonoClass(void)\n{\n\tPageUsage[Page] = 0;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Pan -- Scroll the window right or left.                                          *\n *                                                                                             *\n *    This routine will scroll the window to the right or left as indicated by the number of   *\n *    rows.                                                                                    *\n *                                                                                             *\n * INPUT:   cols  -- The number of columns to pan the window. Positive numbers pan to the left *\n *                   while negative numbers pan to the right.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Pan(int cols)\n{\n\tif (cols == 0) return;\n\n\tif (abs(cols) >= SubW) {\n\t\tClear();\n\t\treturn;\n\t}\n\n\tCellType cell;\n\tcell.Character = ' ';\n\tcell.Attribute = Attrib;\n\n\tif (cols > 0) {\n\t\tfor (int index = SubY; index < SubY+SubH; index++) {\n\t\t\tmemmove(&Page_Ptr()->Data[index][SubX], &Page_Ptr()->Data[index][SubX+cols], sizeof(CellType)*(SubW-cols));\n\t\t\tfor (int cc = SubX+SubW-cols; cc < SubX+SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[index][cc] = cell;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (int index = SubY; index < SubY+SubH; index++) {\n\t\t\tmemmove(&Page_Ptr()->Data[index][SubX-cols], &Page_Ptr()->Data[index][SubX], sizeof(CellType)*(SubW+cols));\n\t\t\tfor (int cc = SubX; cc < SubX-cols; cc++) {\n\t\t\t\tPage_Ptr()->Data[index][cc] = cell;\n\t\t\t}\n\t\t}\n\t}\n\tSet_Cursor(X-cols, Y);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Sub_Window -- Partitions the mono screen into a sub-window.                      *\n *                                                                                             *\n *    This routine is used to partition the monochrome screen so that only a sub-window will   *\n *    be processed. By using this, a separate rectangle of the screen can be cleared,          *\n *    scrolled, panned, or printed into.                                                       *\n *                                                                                             *\n * INPUT:   x,y   -- The upper left corner of the new sub-window.                              *\n *                                                                                             *\n *          w,h   -- Dimensions of the sub-window specified in characters.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The parameters are clipped as necessary.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Sub_Window(int x, int y, int w, int h)\n{\n\t/*\n\t**\tUndo any sub window adjustments to the cursor position.\n\t*/\n\tX += SubX;\n\tY += SubY;\n\n\t/*\n\t**\tEnsure parameters are legal.\n\t*/\n\tx = min(x, COLUMNS-1);\n\tx = max(x, 0);\n\ty = min(y, LINES-1);\n\ty = max(y, 0);\n\tif (w == -1) w = COLUMNS-x;\n\tif (h == -1) h = LINES-y;\n\n\t/*\n\t**\tAssign the new sub-region.\n\t*/\n\tSubX = x;\n\tSubY = y;\n\tSubW = w;\n\tSubH = h;\n\n\t/*\n\t**\tMove the cursor (if necessary) so that it falls within that region.\n\t*/\n\tint xx = X;\n\tint yy = Y;\n\txx = min(xx, SubX+SubW-1);\n\txx = max(xx, SubX);\n\tyy = min(yy, SubY+SubH-1);\n\tyy = max(yy, SubY);\n\tSet_Cursor(xx-SubX, yy-SubY);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters.                       *\n *                                                                                             *\n *    Use this routine to draw a box to the monochrome screen. The IBM line draw characters    *\n *    are used to give the it a fancy appearance. There are several line draw modes supported. *\n *                                                                                             *\n * INPUT:   x,y      -- The coordinates of the upper left corner of the box.                   *\n *                                                                                             *\n *          w,y      -- The width and height (respectively) to make the box.                   *\n *                                                                                             *\n *          attrib   -- The text attribute to use when drawing the box outline characters.     *\n *                                                                                             *\n *          thick    -- The thickness style to use. Examine the BoxStyleType enum for          *\n *                      elaboration on the supported styles.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The interior of the box is NOT cleared by this routine. It is advised that this *\n *             area be cleared before the box is drawn.                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Draw_Box(int x, int y, int w, int h, MonoAttribute attrib, BoxStyleType thick)\n{\n\tCellType\tcell;\n\tMonoAttribute\toldattrib = Attrib;\n\n\tif (!Enabled || !w || !h) return;\n\n\tx = min(x, SubW);\n\tx = max(x, 0);\n\ty = min(y, SubH);\n\ty = max(y, 0);\n\tw = min(w, SubW-x);\n\tw = max(w, 1);\n\th = min(h, SubH-y);\n\th = max(h, 1);\n\n\tx += SubX;\n\ty += SubY;\n\n\tcell.Attribute = attrib;\n\n\t/*\n\t**\tDraw the horizontal lines.\n\t*/\n\tfor (int xpos = 0; xpos < w-2; xpos++) {\n\t\tcell.Character = CharData[thick].TopEdge;\n\t\tPage_Ptr()->Data[y][x+xpos+1] = cell;\n\t\tcell.Character = CharData[thick].BottomEdge;\n\t\tPage_Ptr()->Data[y+h-1][x+xpos+1] = cell;\n\t}\n\n\t/*\n\t**\tDraw the vertical lines.\n\t*/\n\tfor (int ypos = 0; ypos < h-2; ypos++) {\n\t\tcell.Character = CharData[thick].LeftEdge;\n\t\tPage_Ptr()->Data[y+ypos+1][x] = cell;\n\t\tcell.Character = CharData[thick].RightEdge;\n\t\tPage_Ptr()->Data[y+ypos+1][x+w-1] = cell;\n\t}\n\n\t/*\n\t**\tDraw the four corners.\n\t*/\n\tif (w > 1 && h > 1) {\n\t\tcell.Character = CharData[thick].UpperLeft;\n\t\tPage_Ptr()->Data[y][x] = cell;\n\t\tcell.Character = CharData[thick].UpperRight;\n\t\tPage_Ptr()->Data[y][x+w-1] = cell;\n\t\tcell.Character = CharData[thick].BottomRight;\n\t\tPage_Ptr()->Data[y+h-1][x+w-1] = cell;\n\t\tcell.Character = CharData[thick].BottomLeft;\n\t\tPage_Ptr()->Data[y+h-1][x] = cell;\n\t}\n\n\tAttrib = oldattrib;\n}\n\n\n/***********************************************************************************************\n * MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified.           *\n *                                                                                             *\n *    Use this routine to set the monochrome's cursor position to the coordinates specified.   *\n *    This is the normal way of controlling where the next Print or Printf will output the     *\n *    text to.                                                                                 *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinate to position the monochrome cursor. 0,0 is the upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Set_Cursor(int x, int y)\n{\n\tx = min(x, SubW);\n\tx = max(x, 0);\n\ty = min(y, SubH);\n\ty = max(y, 0);\n\n\tX = x;\n\tY = y;\n#if (0)//PG\n\tif (!Enabled) return;\n\n\t/*\n\t**\tUpdate the visible cursor position only if the this mono page is the currently\n\t**\tvisible one.\n\t*/\n\tint pos = ((y+SubY)*COLUMNS)+(x+SubX);\n\tif (Page == 0) {\n\t\toutput(CONTROL_PORT, (short)(0x0E|(pos&0xFF00)));\n\t\toutput(CONTROL_PORT, (short)(0x0F|(pos<<8)));\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * MonoClass::Clear -- Clears the monochrome screen object.                                    *\n *                                                                                             *\n *    This routine will fill the monochrome screen object with spaces. It is clearing the      *\n *    screen of data, making it free for output. The cursor is positioned at the upper left    *\n *    corner of the screen by this routine.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Clear(void)\n{\n\tif (!Enabled) return;\n\n\tSet_Cursor(0, 0);\n\n\tCellType\tcell;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tfor (int rows = 0; rows < SubH; rows++) {\n\t\tfor (int cols = 0; cols < SubW; cols++) {\n\t\t\tPage_Ptr()->Data[rows+SubX][cols+SubY] = cell;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Fill_Attrib -- Fill a block with specified attribute.                            *\n *                                                                                             *\n *    This routine will give the specified attribute to the characters within the block        *\n *    but will not change the characters themselves. You can use this routine to change the    *\n *    underline, blink, or inverse characteristics of text.                                    *\n *                                                                                             *\n * INPUT:   x,y      -- The upper left coordinate of the region to change.                     *\n *                                                                                             *\n *          w,h      -- The dimensions of the region to change (in characters).                *\n *                                                                                             *\n *          attrib   -- The attribute to fill into the region specified.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Fill_Attrib(int x, int y, int w, int h, MonoAttribute attrib)\n{\n\tif (!w || !h || x >= SubW || h >= SubH || x+w > SubW || y+h > SubH) return;\n\n\tfor (int rows = y; rows < y+h; rows++) {\n\t\tfor (int cols = x; cols < x+w; cols++) {\n\t\t\tPage_Ptr()->Data[rows+SubY][cols+SubX].Attribute = attrib;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines.                *\n *                                                                                             *\n *    Use this routine to scroll the monochrome screen up by the number of lines specified.    *\n *    This routine is typically called by the printing functions so that the monochrome screen *\n *    behaves in the expected manner -- printing at the bottom of the screen scrolls it up     *\n *    to make room for new text.                                                               *\n *                                                                                             *\n * INPUT:   lines -- The number of lines to scroll the monochrome screen.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Scroll(int lines)\n{\n\tif (!Enabled || lines <= 0) return;\n\n\tif (abs(lines) >= SubH) {\n\t\tClear();\n\t\treturn;\n\t}\n\n\tCellType\tcell;\n\tcell.Attribute = Attrib;\n\tcell.Character = ' ';\n\n\tif (lines > 0) {\n\t\tfor (int row = 0; row < SubH-lines; row++) {\n\t\t\tmemmove(&Page_Ptr()->Data[SubY+row][SubX], &Page_Ptr()->Data[SubY+row+1][SubX], SubW*sizeof(CellType));\n\t\t}\n\t\tfor (int frow = SubH-lines; frow < SubH; frow++) {\n\t\t\tfor (int cc = 0; cc < SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[SubY+frow][SubX+cc] = cell;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (int row = SubH-1; row >= -lines; row--) {\n\t\t\tmemmove(&Page_Ptr()->Data[SubY+row][SubX], &Page_Ptr()->Data[SubY+row-1][SubX], SubW*sizeof(CellType));\n\t\t}\n\t\tfor (int frow = 0; frow < -lines; frow++) {\n\t\t\tfor (int cc = 0; cc < SubW; cc++) {\n\t\t\t\tPage_Ptr()->Data[SubY+frow][SubX+cc] = cell;\n\t\t\t}\n\t\t}\n\t}\n\n\tSet_Cursor(X, Y-lines);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints a formatted string to the monochrome screen.                    *\n *                                                                                             *\n *    Use this routine to output a formatted string, using the standard formatting options,    *\n *    to the monochrome screen object's current cursor position.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          ...   -- Any optional parameters to supply in formatting the text.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The total formatted text length must not exceed 255 characters.                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(char const *text, ...)\n{\n\tva_list\tva;\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, text, va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Printf -- Prints formatted text using text string number.                        *\n *                                                                                             *\n *    This routine will take the given text string number and print the formatted text to      *\n *    the monochrome screen.                                                                   *\n *                                                                                             *\n * INPUT:   text  -- The text number to convert into real text (by way of external function).  *\n *                                                                                             *\n *          ...   -- Additional parameters as needed.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Printf(int text, ...)\n{\n\tva_list\tva;\n\n\t/*\n\t**\tThe buffer object is placed at the end of the local variable list\n\t**\tso that if the sprintf happens to spill past the end, it isn't likely\n\t**\tto trash anything (important). The buffer is then manually truncated\n\t**\tto maximum allowed size before being printed.\n\t*/\n\tchar buffer[256];\n\n\tif (!Enabled) return;\n\n\tva_start(va, text);\n\tvsprintf(buffer, Text_String(text), va);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tPrint(buffer);\n\tva_end(va);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Prints the text string at the current cursor coordinates.               *\n *                                                                                             *\n *    Use this routine to output the specified text string at the monochrome object's current  *\n *    text coordinate position.                                                                *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the string to print.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(char const * ptr)\n{\n\tint startcol = X;\n\tchar const * text;\n\tCellType\tcell;\n\n\tif (!ptr || !Enabled) return;\n\n\ttext = ptr;\n\tcell.Attribute = Attrib;\n\twhile (*text) {\n\n\t\tcell.Character = *text;\n\n\t\t/*\n\t\t**\tSometimes the character string is used for cursor control instead\n\t\t**\tof plain text output. Check for this case.\n\t\t*/\n\t\tswitch (cell.Character) {\n\n\t\t\t/*\n\t\t\t**\tThe \"return\" code behaves as it did in the old C library\n\t\t\t**\tmono system. That is, it returns the cursor position to\n\t\t\t**\tthe next line but at the starting column of the print.\n\t\t\t*/\n\t\t\tcase '\\r':\n\t\t\t\tif (Y == SubH-1) {\n\t\t\t\t\tScroll(1);\n\t\t\t\t}\n\t\t\t\tSet_Cursor(startcol, Y+1);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tThe TAB character is not currently handled. Convert it to\n\t\t\t**\ta space instead.\n\t\t\t*/\n\t\t\tcase '\\t':\n\t\t\t\tcell.Character = ' ';\n\t\t\t\t// fall into normal print case.\n\n\t\t\t/*\n\t\t\t**\tAll other characters are output directly and the cursor moves\n\t\t\t**\trightward to match. If the cursor wraps past the right\n\t\t\t**\tedge it is moved to the next now down at left margin. If the\n\t\t\t**\tcursor goes off the bottom of the display, the display is scrolled\n\t\t\t**\tupward a line.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tPage_Ptr()->Data[SubY+Y][SubX+X] = cell;\n\n\t\t\t\tif (X < SubW-1) {\n\t\t\t\t\tSet_Cursor(X+1, Y);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Fall into newline case.\n\n\t\t\t/*\n\t\t\t**\tThe \"newline\" code behaves like the console newline character.\n\t\t\t**\tThat is, it moves the cursor down one line and at the first\n\t\t\t**\tcolumn.\n\t\t\t*/\n\t\t\tcase '\\n':\n\t\t\t\tif (Y == SubH-1) {\n\t\t\t\t\tScroll(1);\n\t\t\t\t}\n\t\t\t\tSet_Cursor(0, Y+1);\n\t\t\t\tbreak;\n\t\t}\n\t\ttext++;\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated.     *\n *                                                                                             *\n *    Use this routine to output text to the monochrome object at the X and Y coordinates      *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to display.                                    *\n *                                                                                             *\n *          x,y   -- The X and Y character coordinates to start the printing at.               *\n *                                                                                             *\n *          attrib-- Optional parameter that specifies what text attribute code to use.        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(char const *text, int x, int y, MonoAttribute attrib)\n{\n\tint\toldx = X;\n\tint\toldy = Y;\n\tMonoAttribute oldattrib = Attrib;\n\n\tX = (char)x;\n\tY = (char)y;\n\tAttrib = attrib;\n\tPrint(text);\n\tAttrib = oldattrib;\n\tSet_Cursor(oldx, oldy);\n}\n\n\n/***********************************************************************************************\n * MonoClass::Text_Print -- Simple text printing from text number.                             *\n *                                                                                             *\n *    This will print the text (represented by the text number) to the location on the         *\n *    monochrome screen specified.                                                             *\n *                                                                                             *\n * INPUT:   text  -- The text number to print (converted to real text by external routine).    *\n *                                                                                             *\n *          x,y   -- The coordinates to begin the printing at.                                 *\n *                                                                                             *\n *          attrib-- The character attribute to use while printing.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Text_Print(int text, int x, int y, MonoAttribute attrib)\n{\n\tint\toldx = X;\n\tint\toldy = Y;\n\tMonoAttribute oldattrib = Attrib;\n\n\tif (text != 0) {\n\t\tX = (char)x;\n\t\tY = (char)y;\n\t\tAttrib = attrib;\n\t\tPrint(Text_String(text));\n\t\tAttrib = oldattrib;\n\t\tSet_Cursor(oldx, oldy);\n\t}\n}\n\n\n/***********************************************************************************************\n * MonoClass::Print -- Simple print of text number.                                            *\n *                                                                                             *\n *    Prints text represented by the text number specified.                                    *\n *                                                                                             *\n * INPUT:   text  -- The text number to print (converted to real text by external routine).    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::Print(int text)\n{\n\tPrint(Text_String(text));\n}\n\n\n/***********************************************************************************************\n * MonoClass::operator = -- Handles making one mono object have the same imagery as another.   *\n *                                                                                             *\n *    The assignment operator will handle copying the imagery from one monochrome object to    *\n *    another. Use this routine in to make two monochrome class objects visually identical.    *\n *                                                                                             *\n * INPUT:   src   -- A reference to the source (right side) monochrome object.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMonoClass & MonoClass::operator = (MonoClass const & src)\n{\n\tmemmove(Page_Ptr(), src.Page_Ptr(), sizeof(MonoPageType));\n\tSet_Cursor(src.X, src.Y);\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * MonoClass::View -- Brings the mono object to the main display.                              *\n *                                                                                             *\n *    Use this routine to display the mono object on the monochrome screen. It is possible     *\n *    that the mono object exists on some background screen memory. Calling this routine will  *\n *    perform the necessary memory swapping to bring the data to the front. The mono object    *\n *    that was currently being viewed is not destroyed by this function. It is merely moved    *\n *    off to some background page. It can be treated normally, except that is just isn't       *\n *    visible.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MonoClass::View(void)\n{\n\tif (Get_Current() == this) return;\n\n\t/*\n\t**\tIf the visible page is already assigned to a real monochrome page\n\t**\tobject, then it must be swapped with the new one.\n\t*/\n\tMonoClass * displace = Get_Current();\n\tif (displace) {\n\t\tfor (int line = 0; line < LINES; line++) {\n\t\t\tfor (int col = 0; col < COLUMNS; col++) {\n\t\t\t\tCellType temp = Page_Ptr()->Data[line][col];\n\t\t\t\tPage_Ptr()->Data[line][col] = Raw_Ptr(0)->Data[line][col];\n\t\t\t\tRaw_Ptr(0)->Data[line][col] = temp;\n\t\t\t}\n\t\t}\n\t\tdisplace->Page = Page;\n\n\t} else {\n\n\t\t/*\n\t\t**\tJust copy the new page over since the display page is not assigned\n\t\t**\tto a real monochrome page object.\n\t\t*/\n\t\tmemmove(Raw_Ptr(0), Page_Ptr(), sizeof(MonoPageType));\n\t}\n\tPageUsage[Page] = displace;\n\tPageUsage[0] = this;\n\tPage = 0;\n\n\tSet_Cursor(X, Y);\n}\n\n\n\n/************************************************************************************\n**\tThis is the set of C wrapper functions that access the MonoClass support routines.\n**\tSince the C interface doesn't have the ability to write to non-visible pages, it\n**\twill just blast the output to whichever mono page is currently visible. If there is\n**\tno mono class object that is visible, then one will be created -- BUT NOT FREED.\n**\tTypically, this is ok, since the C interface will create only one MonoClass object\n**\tand the system supports up to 8.\n*/\nvoid Mono_Set_Cursor(int x, int y)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Set_Cursor(x, y);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Printf -- Prints formatted text to visible page.                                       *\n *                                                                                             *\n *    This routine will print formatted text (with parameters) to the visible monochrome page  *\n *    at whatever the current cursor location is.                                              *\n *                                                                                             *\n * INPUT:   string   -- The string to use as the main text and formatting control string.      *\n *                                                                                             *\n *          ...      -- Any additional parameters required by the formatting string.           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of characters written to the display.                      *\n *                                                                                             *\n * WARNINGS:   The total size of the formatted text must not exceed 256 characters.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_Printf(char const * string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, string, va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n\n/***********************************************************************************************\n * Mono_Clear_Screen -- Clear the currently visible monochrome page.                           *\n *                                                                                             *\n *    This routine will clear the currently visible monochrome page.                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Clear_Screen(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Clear();\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Text_Print -- Prints text to location specified.                                       *\n *                                                                                             *\n *    This routine will print the specified text to the location indicated.                    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text to print.                                             *\n *                                                                                             *\n *          x,y   -- The coordinate to print the text at.                                      *\n *                                                                                             *\n *          attrib-- The attribute to use when printing the text.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Text_Print(void const *text, int x, int y, int attrib)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Text_Print((const char*)text, x, y, (MonoClass::MonoAttribute)attrib);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Draw_Rect -- Draws rectangle to monochrome screen.                                     *\n *                                                                                             *\n *    Use this routine to draw a rectangle to the monochrome screen. The dimensions, attribute,*\n *    and line style are controlled by parameters.                                             *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate of upper left corner of the box to draw.                       *\n *                                                                                             *\n *          w,h   -- The width and height of the box to draw.                                  *\n *                                                                                             *\n *          attrib-- The attribute to use when drawing the box.                                *\n *                                                                                             *\n *          thick -- The line drawing style to use.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Draw_Box(x, y, w, h, (MonoClass::MonoAttribute)attrib, (MonoClass::BoxStyleType)thick);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_Print -- Prints simple text to monochrome screen.                                      *\n *                                                                                             *\n *    This is the non-formatting print to the monochrome screen.                               *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that will be printed.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Mono_Print(void const *text)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\tmono->Print((const char*)text);\n\t}\n}\n\n\n/***********************************************************************************************\n * Mono_X -- Fetches the X cursor position for current visible mono page.                      *\n *                                                                                             *\n *    Use this routine to get the current cursor X position. This only applies to the          *\n *    currently visible monochrome page.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with X position of cursor.                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_X(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * Mono_Y -- Fetches the Y cursor position for current mono page.                              *\n *                                                                                             *\n *    This routine will fetch the current Y cursor position for the monochrome page.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current Y position of the monochrome page.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Mono_Y(void)\n{\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\t\treturn(short)mono->Get_X();\n\t}\n\treturn(0);\n}\n\n\nvoid Mono_Put_Char(char , int )\n{\n}\n\nvoid Mono_Scroll(int )\n{\n}\n\nvoid Mono_View_Page(int )\n{\n}\n\nint Mono_Printf(int string, ...)\n{\n\tva_list\tva;\n\tchar buffer[256];\n\n\tbuffer[0] = '\\0';\n\tif (MonoClass::Is_Enabled()) {\n\t\tMonoClass * mono = MonoClass::Get_Current();\n\t\tif (!mono) {\n\t\t\tmono = new MonoClass();\n\t\t\tmono->View();\n\t\t}\n\n\t\tva_start(va, string);\n\t\tvsprintf(buffer, Text_String(string), va);\n\n\t\tmono->Print(buffer);\n\n\t\tva_end(va);\n\t}\n\treturn((short)strlen(buffer));\n}\n\n//#endif"
  },
  {
    "path": "REDALERT/MONOC.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MONOC.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MONO.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : July 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MONOC_Hx\n#define MONOC_Hx\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\nclass MonoClass {\n\tpublic:\n\t\tenum MonoClassPageEnums {\n\t\t\tCOLUMNS=80,\t\t\t\t\t\t// Number of columns.\n\t\t\tLINES=25,\t\t\t\t\t\t// Number of lines.\n\t\t\tMAX_MONO_PAGES=16\t// Maximum RAM pages on mono card.\n\t\t};\n\n      typedef enum MonoAttribute {\n\t\t\tINVISIBLE=0x00,\t\t\t\t// Black on black.\n\t\t\tUNDERLINE=0x01,\t\t\t\t// Underline.\n\t\t\tBLINKING=0x90,\t\t\t\t\t// Blinking white on black.\n\t\t\tNORMAL=0x02,\t\t\t\t\t// White on black.\n\t\t\tINVERSE=0x70,\t\t\t\t\t// Black on white.\n      } MonoAttribute;\n\n\t\t/*\n\t\t**\tThese are the various box styles that may be used.\n\t\t*/\n\t\ttypedef enum BoxStyleType {\n\t\t\tSINGLE,\t\t\t\t// Single thickness.\n\t\t\tDOUBLE_HORZ,\t\t// Double thick on the horizontal axis.\n\t\t\tDOUBLE_VERT,\t\t// Double thick on the vertical axis.\n\t\t\tDOUBLE,\t\t\t\t// Double thickness.\n\n\t\t\tCOUNT\n\t\t} BoxStyleType;\n\n\t\tMonoClass(void);\n\t\t~MonoClass(void);\n\n\t\tstatic void Enable(void) {Enabled = true;};\n\t\tstatic void Disable(void) {Enabled = false;};\n\t\tstatic bool Is_Enabled(void) {return Enabled;};\n\t\tstatic MonoClass * Get_Current(void) {return PageUsage[0];};\n\n\t\tvoid Sub_Window(int x=0, int y=0, int w=-1, int h=-1);\n\t\tvoid Fill_Attrib(int x, int y, int w, int h, MonoAttribute attrib);\n\t\tvoid Draw_Box(int x, int y, int w, int h, MonoAttribute attrib=NORMAL, BoxStyleType thick=SINGLE);\n\t\tvoid Set_Default_Attribute(MonoAttribute attrib) {Attrib = attrib;};\n\t\tvoid Clear(void);\n\t\tvoid Set_Cursor(int x, int y);\n\t\tvoid Print(char const *text);\n\t\tvoid Print(int text);\n\t\tvoid Printf(char const *text, ...);\n\t\tvoid Printf(int text, ...);\n\t\tvoid Text_Print(char const *text, int x, int y, MonoAttribute attrib=NORMAL);\n\t\tvoid Text_Print(int text, int x, int y, MonoAttribute attrib=NORMAL);\n\t\tvoid View(void);\n\t\tvoid Scroll(int lines=1);\n\t\tvoid Pan(int cols=1);\n\t\tint Get_X(void) const {return X;};\n\t\tint Get_Y(void) const {return Y;};\n\t\tint Get_Width(void) const {return(SubW);};\n\t\tint Get_Height(void) const {return(SubH);};\n\n\t\t/*\n\t\t**\tHandles deep copies for the mono class objects. This performs what is essentially\n\t\t**\ta screen copy.\n\t\t*/\n\t\tMonoClass & operator = (MonoClass const & );\n\n\t\t/*\n\t\t**\tThis merely makes a duplicate of the mono object into a newly created mono\n\t\t**\tobject.\n\t\t*/\n\t\tMonoClass (MonoClass const &);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tCursor coordinate (relative to sub-window).\n\t\t*/\n\t\tint X;\n\t\tint Y;\n\n\t\t/*\n\t\t**\tDefault attribute to use when printing text.\n\t\t*/\n\t\tMonoAttribute Attrib;\n\n\t\t/*\n\t\t**\tThe current physical page that this mono class object refers to.\n\t\t*/\n\t\tint Page;\n\n\t\t/*\n\t\t**\tSub window coordinates.\n\t\t*/\n\t\tint SubX;\n\t\tint SubY;\n\t\tint SubW;\n\t\tint SubH;\n\n\t\t/*\n\t\t**\tPointer to the monochrome RAM.\n\t\t*/\n//\t\tstatic MonoPageType * MonoRAM;\n\n\t\t/*\n\t\t** This the the arrays of characters used for drawing boxes.\n\t\t*/\n\t\t/*\n\t\t**\tThis is a private structure that is used to control which characters\n\t\t**\tare used when a box is drawn. Line drawing on the monochrome screen is\n\t\t**\treally made up of characters. This specifies which characters to use.\n\t\t*/\n\t\tstruct BoxDataType {\n\t\t\tunsigned char\tUpperLeft;\n\t\t\tunsigned char\tTopEdge;\n\t\t\tunsigned char\tUpperRight;\n\t\t\tunsigned char\tRightEdge;\n\t\t\tunsigned char\tBottomRight;\n\t\t\tunsigned char\tBottomEdge;\n\t\t\tunsigned char\tBottomLeft;\n\t\t\tunsigned char\tLeftEdge;\n\t\t};\n\t\tstatic BoxDataType const CharData[4];\n\n\t\t/*\n\t\t**\tEach cell is constructed of the actual character that is displayed and the\n\t\t**\tattribute to use. This character pair is located at every position on the\n\t\t**\tdisplay (80 x 25). Since this cell pair can be represented by a \"short\"\n\t\t**\tinteger, certain speed optimizations are taken in the monochrome drawing\n\t\t**\tcode.\n\t\t*/\n\t\tstruct CellType {\n\t\t\tunsigned char Character;\t// Character to display.\n\t\t\tunsigned char Attribute;\t// Attribute.\n\t\t};\n\n\t\tstruct MonoPageType {\n\t\t\tCellType Data[LINES][COLUMNS];\n\t\t};\n\n\t\t/*\n\t\t**\tThese private constants are used in the various monochrome operations.\n\t\t*/\n\t\tenum MonoClassPortEnums {\n\t\t\tCONTROL_PORT=0x03B4,\t\t\t// CRTC control register.\n\t\t\tDATA_PORT=0x03B5,\t\t\t\t// CRTC data register.\n\t\t\tSIZE_OF_PAGE=(int)LINES*(int)COLUMNS*sizeof(CellType)\t// Entire page size.\n\t\t};\n\n\t\t/*\n\t\t**\tThis array contains pointers to the monochrome objects that are assigned\n\t\t**\tto each of the monochrome pages. As the monochrome pages are made visible,\n\t\t**\tthey can be shuffled around between the actual locations. The first entry\n\t\t**\tin this table is the one that is visible.\n\t\t*/\n\t\tstatic MonoClass * PageUsage[MAX_MONO_PAGES];\n\n\t\t/*\n\t\t**\tFetches pointers to the appropriate mono RAM.\n\t\t*/\n\t\tMonoPageType * Raw_Ptr(int page) const {\n\t\t\treturn &((MonoPageType *)0xB0000)[page];\n\t\t}\n\t\tMonoPageType * Page_Ptr(void) const {\n\t\t\treturn(Raw_Ptr(Page));\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is true, then monochrome output is allowed. It defaults to false\n\t\t**\tso that monochrome output must be explicitly enabled.\n\t\t*/\n\t\tstatic bool Enabled;\n};\n\n#ifndef WIN32\nint Mono_Printf(int string, ...);\n#else\nextern void Mono_Set_Cursor(int x, int y);\nextern int Mono_Printf(int string, ...);\nextern int Mono_Printf(char const * string, ...);\nextern void Mono_Clear_Screen(void);\nextern void Mono_Text_Print(void const *text, int x, int y, int attrib);\nextern void Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick);\nextern void Mono_Print(void const *text);\nextern int Mono_X(void);\nextern int Mono_Y(void);\n#endif\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/MOUSE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MOUSE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MOUSE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : September 21, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MouseClass::AI -- Process player input as it relates to the mouse                         *\n *   MouseClass::Init_Clear -- Sets the mouse system to a known state                          *\n *   MouseClass::MouseClass -- Default constructor for the mouse handler class.                *\n *   MouseClass::Mouse_Small -- Controls the sizing of the mouse.                              *\n *   MouseClass::One_Time -- Performs the one time initialization of the mouse system.         *\n *   MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse.                        *\n *   MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape.    *\n *   MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tThis points to the loaded mouse shapes.\n*/\nvoid const * MouseClass::MouseShapes;\n\n/*\n**\tThis is the timer that controls the mouse animation. It is always at a fixed\n**\trate so it uses the constant system timer.\n*/\nCDTimerClass<SystemTimerClass> MouseClass::Timer = 0;\n\n\n/***********************************************************************************************\n * MouseClass::MouseClass -- Default constructor for the mouse handler class.                  *\n *                                                                                             *\n *    This is the default constructor for the mouse handling class. It merely sets up the      *\n *    mouse system to its default state.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nMouseClass::MouseClass(void) :\n\tIsSmall(false),\n\tCurrentMouseShape(MOUSE_NORMAL),\n\tNormalMouseShape(MOUSE_NORMAL),\n\tFrame(0)\n{\n}\n\n\n/***********************************************************************************************\n * MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified.               *\n *                                                                                             *\n *    This routine is used to inform the display system as to which mouse shape is desired.    *\n *                                                                                             *\n * INPUT:   mouse -- The mouse shape number to set the mouse to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Set_Default_Mouse(MouseType mouse, bool size)\n{\n\tassert((unsigned)mouse < MOUSE_COUNT);\n\n\tNormalMouseShape = mouse;\n\tOverride_Mouse_Shape(mouse, size);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape.      *\n *                                                                                             *\n *    Use this routine to cancel the effects of Override_Mouse_Shape(). It will revert the     *\n *    mouse back to the original shape.                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Revert_Mouse_Shape(void)\n{\n\tOverride_Mouse_Shape(NormalMouseShape, false);\n}\n\n\n/***********************************************************************************************\n * MouseClass::Mouse_Small -- Controls the sizing of the mouse.                                *\n *                                                                                             *\n *    This routine is called to change the mouse sizing override. If the mouse can change      *\n *    size to that specified, then the mouse imagery will be changed. If a change of imagery   *\n *    cannot occur (due to lack of appropriate artwork), then no action will be performed.     *\n *                                                                                             *\n * INPUT:   small -- Should the mouse be made small? If not, then it will be made large.       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Mouse_Small(bool wsmall)\n{\n\tMouseStruct const * control = &MouseControl[CurrentMouseShape];\n\n\tif (IsSmall == wsmall) {\n\t\treturn;\n\t}\n\n\tIsSmall\t= wsmall;\n\n\tif (wsmall) {\n\t\tif (control->SmallFrame != -1) {\n\t\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->SmallFrame + Frame/4));\n\t\t} else {\n\t\t\tSet_Mouse_Cursor(MouseControl[MOUSE_NORMAL].X, MouseControl[MOUSE_NORMAL].Y, Extract_Shape(MouseShapes, MOUSE_NORMAL));\n\t\t}\n\t} else {\n\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->StartFrame + Frame/4));\n\t}\n}\n\n\n/***********************************************************************************************\n * MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse.                          *\n *                                                                                             *\n *    This routine is used to alter the shape of the mouse as needed.                          *\n *    Typical mouse shape change occurs when scrolling the map or                              *\n *    selecting targets.                                                                       *\n *                                                                                             *\n * INPUT:   mouse -- The mouse shape number to use.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the mouse shape changed?                                                 *\n *                                                                                             *\n * WARNINGS:   This is not intended to be used as a means to hide the                          *\n *             mouse. Nor will it work correctly if the mouse shape                            *\n *             file hasn't been loaded.                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/10/1994 JLB : Created.                                                                 *\n *   06/03/1994 JLB : Made into member function.                                               *\n *   12/24/1994 JLB : Added small control parameter.                                           *\n *=============================================================================================*/\n#ifdef WIN32\nvoid Block_Mouse(GraphicBufferClass *buffer);\nvoid Unblock_Mouse(GraphicBufferClass *buffer);\n#endif\n\nbool MouseClass::Override_Mouse_Shape(MouseType mouse, bool wsmall)\n{\n\tassert((unsigned)mouse < MOUSE_COUNT);\n\n\tMouseStruct const * control = &MouseControl[mouse];\n\tstatic bool startup = false;\n\tint baseshp;\n\n\t/*\n\t**\tOnly certain mouse shapes have a small counterpart. If the requested mouse\n\t**\tshape is not one of these, then force the small size override flag to false.\n\t*/\n\tif (control->SmallFrame == -1) {\n\t\twsmall = false;\n\t}\n\n\t/*\n\t**\tIf the mouse shape is going to change, then inform the mouse driver of the\n\t**\tchange.\n\t*/\n\tif (!startup || (MouseShapes && ((mouse != CurrentMouseShape) || (wsmall != IsSmall)))) {\n\t\tstartup = true;\n\n\t\tTimer = control->FrameRate;\n\t\tFrame = 0;\n\n\t\tbaseshp = (wsmall) ? control->SmallFrame : control->StartFrame;\n\t\tif (baseshp == -1) {\n\t\t\tbaseshp = control->StartFrame;\n\t\t}\n\n\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, baseshp));\n\t\tCurrentMouseShape = mouse;\n\t\tIsSmall = wsmall;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * MouseClass::AI -- Process player input as it relates to the mouse                           *\n *                                                                                             *\n *    This routine will is to be called once per game tick and is passed the player keyboard   *\n *    or mouse input code. It processes this code and updates the mouse shape as appropriate.  *\n *                                                                                             *\n * INPUT:   input -- The player input code as returned from Keyboard->Get().                   *\n *                                                                                             *\n *          x,y   -- The mouse coordinate values to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   03/27/1995 JLB : New animation control.                                                   *\n *   05/28/1995 JLB : Moderates animation so is more steady regardless of speed.               *\n *   06/30/1995 JLB : Uses constant timer system.                                              *\n *=============================================================================================*/\nvoid MouseClass::AI(KeyNumType &input, int x, int y)\n{\n\tMouseStruct const * control = &MouseControl[CurrentMouseShape];\n\n\tif (control->FrameRate && Timer == 0) {\n\n\t\tFrame++;\n\t\tFrame %= control->FrameCount;\n\t\tTimer = control->FrameRate;\n\n\t\tif (!IsSmall || control->SmallFrame != -1) {\n\t\t\tint baseframe = (IsSmall) ? control->SmallFrame : control->StartFrame;\n\t\t\tif (baseframe == -1) baseframe = control->StartFrame;\n\t\t\tSet_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, baseframe + Frame));\n\t\t}\n\t}\n\n\tScrollClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * MouseClass::One_Time -- Performs the one time initialization of the mouse system.           *\n *                                                                                             *\n *    Use this routine to load the mouse data file and perform any other necessary one time    *\n *    preparations for the game.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine ONCE.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::One_Time(void)\n{\n\tScrollClass::One_Time();\n\n\t/*\n\t**\tOverride the mouse shape file with the one in the current directory, but only if there\n\t**\tis an override file available.\n\t*/\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"MOUSE.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tMouseShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tMouseShapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t\t}\n\t#else\n\t\tMouseShapes = MFCD::Retrieve(\"MOUSE.SHP\");\n\t#endif\n}\n\n\n/***********************************************************************************************\n * MouseClass::Init_Clear -- Sets the mouse system to a known state                            *\n *                                                                                             *\n *    This routine will reset the mouse handling system. Typically, this routine is called     *\n *    when preparing for the beginning of a new scenario.                                      *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the scenario will take place.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MouseClass::Init_Clear(void)\n{\n\tScrollClass::Init_Clear();\n\tIsSmall = false;\n\tNormalMouseShape = MOUSE_NORMAL;\n}\n\n\n/*\n**\tThis array of structures is used to control the mouse animation\n**\tsequences.\n*/\n//#ifdef WIN32\n//#define\tWD\t45\n//#define\tHT\t36\n//#else\n#define\tWD\t29\n#define\tHT\t23\n//#endif\n\nMouseClass::MouseStruct MouseClass::MouseControl[MOUSE_COUNT] = {\n\t{0, \t1,\t\t0,\t\t80,\t0,\t\t0},\t\t//\tMOUSE_NORMAL\n\t{1, \t1,\t\t0,\t\t-1,\tWD/2,\t0},\t\t//\tMOUSE_N\n\t{2, \t1,\t\t0,\t\t-1,\tWD,\t0},\t\t//\tMOUSE_NE\n\t{3, \t1,\t\t0,\t\t-1,\tWD,\tHT/2},\t//\tMOUSE_E\n\t{4,\t1,\t\t0,\t\t-1,\tWD,\tHT},\t\t//\tMOUSE_SE\n\t{5,\t1,\t\t0,\t\t-1,\tWD/2,\tHT},\t\t//\tMOUSE_S\n\t{6,\t1,\t\t0,\t\t-1,\t0, \tHT},\t\t//\tMOUSE_SW\n\t{7,\t1,\t\t0,\t\t-1,\t0, \tHT/2},\t//\tMOUSE_W\n\t{8,\t1,\t\t0,\t\t-1,\t0, \t0},\t\t//\tMOUSE_NW\n\n\t{124, 1,\t\t0,\t\t-1,\tWD/2,\t0},\t\t//\tMOUSE_NO_N\n\t{125, 1,\t\t0,\t\t-1,\tWD,\t0},\t\t//\tMOUSE_NO_NE\n\t{126, 1,\t\t0,\t\t-1,\tWD,\tHT/2},\t//\tMOUSE_NO_E\n\t{127,\t1,\t\t0,\t\t-1,\tWD,\tHT},\t\t//\tMOUSE_NO_SE\n\t{128,\t1,\t\t0,\t\t-1,\tWD/2,\tHT},\t\t//\tMOUSE_NO_S\n\t{129,\t1,\t\t0,\t\t-1,\t0, \tHT},\t\t//\tMOUSE_NO_SW\n\t{130,\t1,\t\t0,\t\t-1,\t0, \tHT/2},\t//\tMOUSE_NO_W\n\t{131,\t1,\t\t0,\t\t-1,\t0, \t0},\t\t//\tMOUSE_NO_NW\n\n\t{14,\t1,\t\t0,\t\t33,\tWD/2,\tHT/2},\t//\tMOUSE_NO_MOVE\n\t{10,\t4,\t\t4,\t\t29,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_MOVE\n\t{113,\t3,\t\t4,\t\t142,\tWD/2,\tHT/2},\t//\tMOUSE_ENTER\n\t{59,\t9,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_DEPLOY\n\t{15,\t6,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_SELECT\n\t{21,\t8,\t\t4,\t\t134,\tWD/2,\tHT/2},\t//\tMOUSE_CAN_ATTACK\n\t{68,\t12,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_SELL_BACK\n\t{148,\t12,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_SELL_UNIT\n\t{35,\t24,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_REPAIR\n\t{120,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NO_REPAIR\n\t{119,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NO_SELL_BACK\n\t{81,\t1,\t\t0,\t\t145,\tWD/2, HT/2},\t//\tMOUSE_RADAR_CURSOR\n\t{90,\t7,\t\t4,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_NUCLEAR_BOMB\n\t{82,\t8,\t\t2,\t\t213,\tWD/2,\tHT/2},\t//\tMOUSE_AIR_STRIKE\n\t{116,\t3,\t\t4,\t\t121,\tWD/2,\tHT/2},\t//\tMOUSE_DEMOLITIONS\n\t{147,\t1,\t\t0,\t\t146,\tWD/2,\tHT/2},\t//\tMOUSE_AREA_GUARD\n\t{160,\t4,\t\t4,\t\t194,\tWD/2,\tHT/2},\t//\tMOUSE_HEAL\n\t{164,\t3,\t\t4,\t\t167,\tWD/2,\tHT/2},\t//\tMOUSE_DAMAGE\n\t{170,\t24,\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_GREPAIR\n\t{195,\t8,\t\t4,\t\t203,\tWD/2,\tHT/2},\t// MOUSE_STAY_ATTACK\n\t{211,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_DEPLOY\n\t{212,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_ENTER\n\t{213,\t1,\t\t0,\t\t-1,\tWD/2,\tHT/2},\t// MOUSE_NO_REPAIR\n\n\t{97,\t8,\t\t3,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CHRONO_SELECT\n\t{105,\t8,\t\t2,\t\t-1,\tWD/2,\tHT/2},\t//\tMOUSE_CHRONO_DEST\n\n};\n"
  },
  {
    "path": "REDALERT/MOUSE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MOUSE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MOUSE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MOUSE_H\n#define MOUSE_H\n\n#include\t\"stage.h\"\n#include\t\"scroll.h\"\n\nclass MouseClass: public ScrollClass\n{\n\tpublic:\n\t\tMouseClass(void);\n\t\tMouseClass(NoInitClass const & x) : ScrollClass(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual bool Override_Mouse_Shape(MouseType mouse, bool wsmall=false);\n\t\tvirtual void Revert_Mouse_Shape(void);\n\t\tvirtual MouseType Get_Mouse_Shape(void) const {return NormalMouseShape;};\n\t\tvirtual void Mouse_Small(bool wsmall);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual bool Load(Straw & file);\n\t\tvirtual bool Save(Pipe & file) const;\n\n\t\tvirtual void Set_Default_Mouse(MouseType mouse, bool wsmall = false);\n\n\t\t/*\n\t\t**\tThis allows the tactical map input gadget access to change the\n\t\t**\tmouse shapes.\n\t\t*/\n\t\tfriend class TacticalClass;\n\n\t\t/*\n\t\t**\tThis points to the loaded mouse shapes.\n\t\t*/\n\t\tstatic void const * MouseShapes;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis type is used to control the frames and rates of the mouse\n\t\t**\tpointer. Some mouse pointers are actually looping animations.\n\t\t*/\n\t\ttypedef struct MouseStruct\n\t\t{\n\t\t\tint StartFrame;\t\t\t// Starting frame number.\n\t\t\tint FrameCount;\t\t\t// Number of animation frames.\n\t\t\tint FrameRate;\t\t\t\t// Frame delay between changing frames.\n\t\t\tint SmallFrame;\t\t\t// Start frame number for small version (if any).\n\t\t\tint X,Y;\t\t\t\t\t\t// Hotspot X and Y offset.\n\t\t} MouseStruct;\n\n\t\t/*\n\t\t**\tThe control frames and rates for the various mouse pointers are stored\n\t\t**\tin this static array.\n\t\t*/\n\t\tstatic MouseStruct MouseControl[MOUSE_COUNT];\n\n\tpublic:\n\t\t/*\n\t\t**\tIf the small representation of the mouse is active, then this flag is true.\n\t\t*/\n\t\tunsigned IsSmall:1;\n\n\n\tprivate:\n\t\t/*\n\t\t**\tThe mouse shape is controlled by these variables. These\n\t\t**\thold the current mouse shape (so resetting won't be needlessly performed) and\n\t\t**\tthe normal default mouse shape (when arrow shapes are needed).\n\t\t*/\n\t\tMouseType CurrentMouseShape;\n\t\tMouseType NormalMouseShape;\n\n\t\t/*\n\t\t**\tFor animating mouse shapes, this controls the frame and animation rate.\n\t\t*/\n\t\tstatic CDTimerClass<SystemTimerClass> Timer;\n\t\tint Frame;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/MOVIE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef _MPGMOVIE_H_\n#define _MPGMOVIE_H_\n/****************************************************************************\n*\n* FILE\n*     MpgMovie.h\n*\n* DESCRIPTION\n*     Movie playback using DirectShow Multimedia streaming and DirectDraw\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     May 27, 1998\n*\n****************************************************************************/\n\n#include <windows.h>\n#include <ddraw.h>\n\n#ifdef MPGEXPORT\t\t  \n#define DLLCALL __declspec(dllexport)\n#else\n#define DLLCALL __declspec(dllimport)\n#endif\n\ntypedef enum\n\t{\n\tMPGCMD_ERROR = -1,\n\tMPGCMD_INIT = 0,\n\tMPGCMD_CLEANUP,\n\tMPGCMD_PALETTE,\n\tMPGCMD_UPDATE\n\t} MPG_CMD;\n\ntypedef enum\n\t{\n\tMPGRES_QUIT = -1,\n\tMPGRES_CONTINUE = 0,\n\tMPGRES_LOSTFOCUS,\n\t} MPG_RESPONSE;\n\ntypedef MPG_RESPONSE (far __stdcall *LPMPGCALLBACK)(MPG_CMD cmd, LPVOID data, LPVOID user);\n\nextern \"C\"\n\t{\n\tDLLCALL void __stdcall MpgPlay(const char* name, IDirectDraw* dd,\n\t\tIDirectDrawSurface* surface, RECT* dstRect);\n\tDLLCALL void __stdcall MpgPause(void);\n\tDLLCALL void __stdcall MpgResume(void);\n\tDLLCALL void __stdcall MpgSetCallback(LPMPGCALLBACK callback, LPVOID user);\n\t}\n\n#endif // _MPGMOVIE_H_\n"
  },
  {
    "path": "REDALERT/MP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MP.CPP                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   _Byte_Precision -- Determines the number of bytes significant in long integer.            *\n *   memrev -- Reverse the byte order of the buffer specified.                                 *\n *   XMP_Abs -- Perform an absolute value on the specified MP number.                          *\n *   XMP_Add -- Add two MP numbers with a carry option.                                        *\n *   XMP_Add_Int -- Add an integer to an MP number (with carry).                               *\n *   XMP_Compare -- Compare one MP number with another.                                        *\n *   XMP_Count_Bits -- Count the total number of bits (precision) in MP number.                *\n *   XMP_Count_Bytes -- Counts the number of precision bytes in MP number.                     *\n *   XMP_Dec -- Decrement the MP number by one.                                                *\n *   XMP_Decode_ASCII -- Convert ASCII into an MP number.                                      *\n *   XMP_DER_Decode -- Decode a DER number into an MP number.                                  *\n *   XMP_DER_Encode -- Encode a number into a buffer using DER.                                *\n *   XMP_DER_Length_Encode -- Output the length of a DER block.                                *\n *   XMP_Double_Mul -- Double precision MP multiply.                                           *\n *   XMP_Encode -- Encode MP number into buffer as compactly as possible.                      *\n *   XMP_Fermat_Test -- Performs Fermat's Little Theorem on an MP number.                      *\n *   XMP_Hybrid_Mul -- Special hybrid short multiply (with carry).                             *\n *   XMP_Inc -- Increment an MP number by one.                                                 *\n *   XMP_Init -- Initialize an MP number to a starting value.                                  *\n *   XMP_Inverse_A_Mod_B -- Inverts and performs modulus on an MP number.                      *\n *   XMP_Is_Prime -- Determine if the specified MP number is prime.                            *\n *   XMP_Is_Small_Prime -- Determine if MP number is a small prime.                            *\n *   XMP_Mod_Mult -- Perform a multiply - modulus operation.                                   *\n *   XMP_Mod_Mult_Clear -- Remove temporary values from memory.                                *\n *   XMP_Move -- Assign one MP number to another.                                              *\n *   XMP_Neg -- Negate the specified MP number.                                                *\n *   XMP_Not -- Perform bitwise NOT operation on MP number.                                    *\n *   XMP_Prepare_Modulus -- Prepare globals for modulus operation.                             *\n *   XMP_Rabin_Miller_Test -- Performs the Rabin Miller test for primality.                    *\n *   XMP_Randomize -- Generate a random MP number between the boundaries specified.            *\n *   XMP_Randomize -- Generate a random MP number.                                             *\n *   XMP_Reciprocal -- Compute the reciprocal (inverse) of the MP number.                      *\n *   XMP_Rotate_Left -- Rotate specified MP number leftward.                                   *\n *   XMP_Shift_Left_Bits -- Shifts the MP number left by the specified bit count.              *\n *   XMP_Shift_Right_Bits -- Shift the MP number right by specified bit count.                 *\n *   XMP_Signed_Decode -- Decode a number as if it were signed.                                *\n *   XMP_Signed_Div -- Signed divide of one MP number into another.                            *\n *   XMP_Signed_Mult -- A signed multiply between two MP numbers.                              *\n *   XMP_Signed_Mult_Int -- Multiply an MP number by a signed simple integer.                  *\n *   XMP_Significance -- Fetch the precision (bytes) of the MP number.                         *\n *   XMP_Small_Divisors_Test -- Perform the small divisors test on an MP number.               *\n *   XMP_Sub -- Subtract one MP number from another (with borrow).                             *\n *   XMP_Sub_Int -- Subtract an integer from an MP number (with borrow).                       *\n *   XMP_Unsigned_Decode -- Decode a number as if it were unsigned.                            *\n *   XMP_Unsigned_Div -- Unsigned divide of one MP number into another.                        *\n *   XMP_Unsigned_Div_Int -- Perform a short integer divide into an MP number.                 *\n *   XMP_Unsigned_Mult -- Multiply two unsigned MP numbers together.                           *\n *   XMP_Unsigned_Mult_Int -- Multiply an MP number by a simple integer.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t<stdlib.h>\n#include\t<string.h>\n#include\t<ctype.h>\n#include\t<assert.h>\n#include\t<limits.h>\n#include\t\"mp.h\"\n\n\n#ifndef __BORLANDC__\n#define\tmin(a, b)\t(((a) < (b)) ? (a) : (b))\n#define\t_USERENTRY\n#endif\n\n\n/***********************************************************************************************\n * _Byte_Precision -- Determines the number of bytes significant in long integer.              *\n *                                                                                             *\n *    This utility routine will determine the number of precision bytes exist in the long      *\n *    integer specified. There are some optimizations that can occur if the byte precision     *\n *    is known.                                                                                *\n *                                                                                             *\n * INPUT:   value -- The value of the long integer that the byte precision will be calculated  *\n *                   for.                                                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the long integer requires (at a minimum)     *\n *          to cover the precision of the integer. The minimum value will be 1, the maximum    *\n *          will be 4.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic int _Byte_Precision(unsigned long value)\n{\n\tint byte_count;\n\tfor (byte_count = sizeof(value); byte_count; byte_count--) {\n\t\tif (value >> ((byte_count-1)*8)) break;\n\t}\n\treturn(byte_count);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Length_Encode -- Output the length of a DER block.                                  *\n *                                                                                             *\n *    This routine will output the length of the block using Distinguished Encoding Rules.     *\n *    The rest of the block must be filled in as appropriate. For data blocks that are less    *\n *    than 128 bytes long, the header consists of only one byte. Longer buffers lengths        *\n *    can consume up to 5 bytes (depends on magnitude of the length value).                    *\n *                                                                                             *\n * INPUT:   length   -- The length of the data block to be output.                             *\n *                                                                                             *\n *          output   -- Pointer to the memory block that will be set up.                       *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes (header) that was used to store the length        *\n *          value. Subsequent data must be placed after the header.                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_DER_Length_Encode(unsigned long length, unsigned char * output)\n{\n\tassert(output != NULL);\n\n\tint header_length = 0;\n\n\tif (length <= SCHAR_MAX) {\n\t\toutput[header_length++] = (unsigned char)length;\n\t} else {\n\t\toutput[header_length++] = (unsigned char)(_Byte_Precision(length) | 0x80);\n\t\tfor (int byte_counter = _Byte_Precision(length); byte_counter; --byte_counter) {\n\t\t\toutput[header_length++] = (unsigned char)(length >> ((byte_counter-1)*8));\n\t\t}\n\t}\n\treturn(header_length);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Encode -- Encode a number into a buffer using DER.                                  *\n *                                                                                             *\n *    This routine is used to encode a number into a buffer using Distinguished Encoding       *\n *    Rules. The number of bytes used will be, typically, two bytes more than the number of    *\n *    precision bytes in the number.                                                           *\n *                                                                                             *\n * INPUT:   from     -- Pointer to the multi-precision number.                                 *\n *                                                                                             *\n *          output   -- Pointer to the buffer that will hold the DER encoded number.           *\n *                                                                                             *\n *          precision-- The precision of the multi-precision number.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes used in the output buffer.                        *\n *                                                                                             *\n * WARNINGS:   Make sure the buffer is big enough to hold the DER encoded number. For safety   *\n *             make sure it is precision+6 bytes long.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_DER_Encode(digit const * from, unsigned char * output, int precision)\n{\n\tassert(from != NULL);\n\tassert(output != NULL);\n\tassert(precision > 0);\n\n\tunsigned char buffer[MAX_UNIT_PRECISION*sizeof(digit)+1];\n\tint header_count = 0;\n\n\tunsigned number_count = XMP_Encode(buffer, from, precision);\n\n\toutput[header_count++] = 0x02;\n\theader_count += XMP_DER_Length_Encode(number_count, &output[header_count]);\n\tmemcpy(&output[header_count], buffer, number_count);\n\n\treturn(header_count+number_count);\n}\n\n\n/***********************************************************************************************\n * XMP_DER_Decode -- Decode a DER number into an MP number.                                    *\n *                                                                                             *\n *    Use this routine to decode a Distinguished Encoding Rules number into a multi-precision  *\n *    number. This is the counterpart function to the XMP_DER_Encode() function.               *\n *                                                                                             *\n * INPUT:   result      -- The buffer the hold the result MP number.                           *\n *                                                                                             *\n *          input       -- Pointer to the DER encoded number.                                  *\n *                                                                                             *\n *          precision   -- The precision of the MP number. This is the maximum precision the   *\n *                         DER number can be.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_DER_Decode(digit * result, unsigned char const * input, int precision)\n{\n\tassert(result != NULL);\n\tassert(input != NULL);\n\tassert(precision > 0);\n\n\tif (*input++ == 0x02) {\n\t\tunsigned byte_count;\n\n\t\tif ((*input & 0x80) == 0) {\n\t\t\tbyte_count = *input++;\n\t\t} else {\n\t\t\tint length = *input++ & 0x7f;\n\t\t\tif (length > 2) return;\n\t\t\tbyte_count = *input++;\n\t\t\tif (length > 1) byte_count = (byte_count << 8) | *input++;\n\t\t}\n\t\tif (byte_count <= (precision * sizeof(digit))) {\n\t\t\tXMP_Signed_Decode(result, input, byte_count, precision);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Encode -- Encode MP number into buffer.                                                 *\n *                                                                                             *\n *    This routine will encode an multi-precision number into a buffer of specified length.    *\n *    The number of stored in \"big endian\" format with appropriate sign extension.             *\n *                                                                                             *\n * INPUT:   to       -- Pointer to the buffer to place the number.                             *\n *                                                                                             *\n *          tobytes  -- The number of bytes to use in the destination buffer.                  *\n *                                                                                             *\n *          from     -- Pointer to the MP number to be encoded.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes placed into the destination buffer.               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned XMP_Encode(unsigned char * to, unsigned tobytes, digit const * from, int precision)\n{\n\tassert(to != NULL);\n\tassert(from != NULL);\n\tassert(tobytes > 0);\n\tassert(precision > 0);\n\n\tunsigned frombytes = precision * sizeof(digit);\n\tunsigned char filler = (unsigned char)(XMP_Is_Negative(from, precision) ? 0xff : 0);\n\n\tint index;\n\tfor (index = 0; index < (int)(tobytes-frombytes); index++) {\n\t\t*to++ = filler;\n\t}\n\n\tconst unsigned char * fptr = ((const unsigned char *)from) + min(tobytes, frombytes);\n\tfor (index = 0; index < (int)min(tobytes, frombytes); index++) {\n\t\t*to++ = *--fptr;\n\t}\n\n\treturn(tobytes);\n}\n\n\n/***********************************************************************************************\n * XMP_Encode -- Encode MP number into buffer as compactly as possible.                        *\n *                                                                                             *\n *    This routine will encode the MP number into the specified buffer. The number will be     *\n *    encoded using the least number of bytes possible.                                        *\n *                                                                                             *\n * INPUT:   to       -- The buffer to encode the MP number into.                               *\n *                                                                                             *\n *          from     -- Pointer to the MP number to be encoded.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes used in the destination buffer to hold the        *\n *          encoded number.                                                                    *\n *                                                                                             *\n * WARNINGS:   Be sure the destination buffer is big enough to hold the encoded MP number.     *\n *             A safe size would be the precision plus one.                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n//#pragma warning 364 9\nunsigned XMP_Encode(unsigned char * to, digit const * from, int precision)\n{\n\tassert(to != NULL);\n\tassert(from != NULL);\n\tassert(precision > 0);\n\n\tbool is_negative = XMP_Is_Negative(from, precision);\n\tunsigned char filler = (unsigned char)(is_negative ? 0xff : 0);\n\tunsigned char * number_ptr;\n\n\tunsigned char * const end = (unsigned char *)from;\n\tfor (number_ptr = (unsigned char *)end + precision - 1; number_ptr > (unsigned char *)end; number_ptr--) {\n\t\tif (*number_ptr != filler) break;\n\t}\n\n\tunsigned index = 0;\n\tif (((*number_ptr & 0x80) && !is_negative) || (!(*number_ptr & 0x80) && is_negative)) {\n\t\tto[index++] = filler;\n\t}\n\n\tto[index++] = *number_ptr;\n\n\twhile (number_ptr != end) {\n\t\tto[index++] = *--number_ptr;\n\t}\n\treturn(index);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Decode -- Decode a number as if it were signed.                                  *\n *                                                                                             *\n *    Use this routine to convert a coded number back into an MP number. The coded number      *\n *    is presumed to be signed.                                                                *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer that will hold the decoded MP number.            *\n *                                                                                             *\n *          from     -- Pointer to the encoded MP number.                                      *\n *                                                                                             *\n *          frombytes-- The number of bytes consumed by the encoded MP number.                 *\n *                                                                                             *\n *          precision -- The precision of the MP number (maximum) of the result.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that the precision is sufficient to hold the decoded MP number.         *\n *             Otherwise, the result is undefined.                                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Signed_Decode(digit * result, const unsigned char * from, int frombytes, int precision)\n{\n\tassert(result != NULL);\n\tassert(from != NULL);\n\tassert(frombytes > 0);\n\tassert(precision > 0);\n\n\tunsigned char filler = (unsigned char)((*from & 0x80) ? 0xff : 0);\n\n\tint fillcount = precision * sizeof(digit) - frombytes;\n\tunsigned char * dest = (unsigned char *)&result[precision];\n\n\t/*\n\t**\tFill in any excess significant bytes.\n\t*/\n\tint index;\n\tfor (index = 0; index < fillcount; index++) {\n\t\t*--dest = filler;\n\t}\n\n\t/*\n\t**\tMove in the remaining bytes.\n\t*/\n\tfor (index = 0; index < frombytes; index++) {\n\t\t*--dest = *from++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Decode -- Decode a number as if it were unsigned.                              *\n *                                                                                             *\n *    Use this routine to decode a MP number and treat it as if it were unsigned.              *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the result MP number.                    *\n *                                                                                             *\n *          from     -- Pointer to the encoded MP number.                                      *\n *                                                                                             *\n *          frombytes-- The number of bytes in the encoded number.                             *\n *                                                                                             *\n *          precision-- The precision of the result MP number -- maximum precision.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the result MP precision is sufficient to hold the decoded number or     *\n *             else the result is undefined.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Unsigned_Decode(digit * result, const unsigned char * from, int frombytes, int precision)\n{\n\tassert(result != NULL);\n\tassert(from != NULL);\n\tassert(frombytes > 0);\n\tassert(precision > 0);\n\n\tint fillcount = precision * sizeof(digit) - frombytes;\n\tunsigned char * dest = (unsigned char *)&result[precision];\n\n\t/*\n\t**\tFill in any excess significant bytes.\n\t*/\n\tint index;\n\tfor (index = 0; index < fillcount; index++) {\n\t\t*--dest = '\\0';\n\t}\n\n\t/*\n\t**\tMove in the remaining bytes.\n\t*/\n\tfor (index = 0; index < frombytes; index++) {\n\t\t*--dest = *from++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Significance -- Fetch the precision (bytes) of the MP number.                           *\n *                                                                                             *\n *    This routine will return with the precision of the MP number expressed as bytes. The     *\n *    MP number is presumed unsigned.                                                          *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- The precision of the MP number to examine.                             *\n *                                                                                             *\n * OUTPUT:  Returns with the minimum number of bytes consumed by this MP number.               *\n *                                                                                             *\n * WARNINGS:   Passing a signed MP number to this routine will return an artificially greater  *\n *             precision than it really is.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Significance(const digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tnumber += precision;\n\tdo {\n\t\tif (*(--number)) break;\n\t} while (--precision);\n\treturn(precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Inc -- Increment an MP number by one.                                                   *\n *                                                                                             *\n *    This will increment the MP number by one.                                                *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to increment.                                 *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the number wraps around the maximum precision, the results are undefined.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Inc(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tdo {\n\t\tif (++(*number)) break;\n\t\tnumber++;\n\t} while (--precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Dec -- Decrement the MP number by one.                                                  *\n *                                                                                             *\n *    Use this routine to decrement the specified MP number by one.                            *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to decrement.                                 *\n *                                                                                             *\n *          precision-- The precision of the MP number to decrement.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   If the number wraps below zero, the results are undefined.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Dec(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tdo {\n\t\t*number -= 1;\n\t\tif ((*number) != ~(digit)0) break;\n\t\tnumber++;\n\t} while (--precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Neg -- Negate the specified MP number.                                                  *\n *                                                                                             *\n *    This routine will negate (reverse sign) of the specified MP number.                      *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to negate.                                    *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Neg(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tXMP_Not(number, precision);\n\tXMP_Inc(number, precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Abs -- Perform an absolute value on the specified MP number.                            *\n *                                                                                             *\n *    This will perform the absolute value function on the specified MP number. That is, if    *\n *    the MP number is negative, it will be transformed into a positive number. If the number  *\n *    is already positive, then it will be left alone.                                         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to ABS.                                       *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Abs(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tif (XMP_Is_Negative(number, precision)) {\n\t\tXMP_Neg(number, precision);\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Shift_Right_Bits -- Shift the MP number right by specified bit count.                   *\n *                                                                                             *\n *    Use this routine to perform a right shift of the MP number by the number of bits         *\n *    specified.                                                                               *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the shift upon.                    *\n *                                                                                             *\n *          bits     -- The number of bits to shift.                                           *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is an unsigned shift.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Shift_Right_Bits(digit * number, int bits, int precision)\n{\n\tassert(number != NULL);\n\tassert(bits >= 0);\n\tassert(precision > 0);\n\n\tif (bits == 0) return;\t\t\t/* shift zero bits is a no-op */\n\n\t/*\n\t**\tIf the shift is by whole bytes, then the shift operation can\n\t**\tbe performed very quickly.\n\t*/\n\tif (bits == UNITSIZE) {\n\t\tnumber += precision;\n\t\tdigit carry = 0;\n\t\twhile (precision--) {\n\t\t\tnumber--;\n\t\t\tdigit temp = *number;\n\t\t  \t*number = carry;\n\t\t\tcarry = temp;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the number of bits to shift is less than one byte, then the\n\t**\tshift operation is a relatively simple \"ripple\" effect through\n\t**\tthe MP number buffer.\n\t*/\n\tif (bits < UNITSIZE) {\n\t\tnumber += precision;\n\t\tdigit carry = 0;\n\t\tdigit bitmask = (1L << bits) - 1;\n\t\tint unbits = UNITSIZE - bits;\n\n\t\twhile (precision--) {\n\t\t\tnumber--;\n\t\t\tdigit temp = *number & bitmask;\n\t\t\t*number >>= bits;\n\t\t\t*number |= carry << unbits;\n\t\t\tcarry = temp;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGeneral purpose slow right.\n\t*/\n\tint digits_to_shift = bits / UNITSIZE;\n\tint bits_to_shift = bits % UNITSIZE;\n\n\tint index;\n\tfor (index = digits_to_shift; index < (precision-1); index++) {\n\t\t*number = (*(number + digits_to_shift) >> bits_to_shift) | (*(number + (digits_to_shift + 1)) << (UNITSIZE - bits_to_shift));\n\t\tnumber++;\n\t}\n\n\tif (digits_to_shift < precision) {\n\t\t*number = (*(number + digits_to_shift) >> bits_to_shift);\n\t\tnumber++;\n\t}\n\n\tfor (index= 0; index < min(digits_to_shift, precision); index++) {\n\t\t*number++ = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Shift_Left_Bits -- Shifts the MP number left by the specified bit count.                *\n *                                                                                             *\n *    Use this routine to perform a left shift of the specified MP number.                     *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the shift operation on.            *\n *                                                                                             *\n *          bits     -- The number of bits to shift the MP number leftward.                    *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Shift_Left_Bits(digit * number, int bits, int precision)\n{\n\tassert(number != NULL);\n\tassert(bits >= 0);\n\tassert(precision > 0);\n\n\tif (bits == 0) return;\t\t\t/* shift zero bits is a no-op */\n\n\t/*\n\t**\tIf the shift is by whole bytes, then the shift operation can\n\t**\tbe performed very quickly.\n\t*/\n\tif (bits == UNITSIZE) {\n\t\tdigit carry = 0;\n\t\twhile (precision--) {\n\t\t\tdigit temp = *number;\n\t\t\t*number = carry;\n\t\t\tcarry = temp;\n\t\t\tnumber++;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tIf the number of bits to shift is less than one byte, then the\n\t**\tshift operation is a relatively simple \"ripple\" effect through\n\t**\tthe MP number buffer.\n\t*/\n\tif (bits < UNITSIZE) {\n\t\tdigit carry = 0;\n\t\tdigit bitmask = ~(((digit)-1) >> bits);\n\t\tint unbits = UNITSIZE - bits;\t/* shift bits must be <= UNITSIZE */\n\n\t\twhile (precision--) {\n\t\t\tdigit temp = *number & bitmask;\n\t\t\t*number = (*number << bits) | (carry >> unbits);\n\t\t\tcarry = temp;\n\t\t\tnumber++;\n\t\t}\n\t\treturn;\n\t}\n\n\t/*\n\t**\tGeneral purpose slow left;\n\t*/\n\tint digits_to_shift = bits / UNITSIZE;\n\tint bits_to_shift = bits % UNITSIZE;\n\n\tint index;\n\tnumber += precision-1;\n\tfor (index = digits_to_shift; index < (precision-1); index++) {\n\t\t*number = (*(number - digits_to_shift) << bits_to_shift) | (*(number - (digits_to_shift + 1)) >> (UNITSIZE - bits_to_shift));\n\t\tnumber--;\n\t}\n\n\tif (digits_to_shift < precision) {\n\t\t*number = (*(number - digits_to_shift) << bits_to_shift);\n\t\tnumber--;\n\t}\n\n\tfor (index = 0; index < min(digits_to_shift, precision); index++) {\n\t\t*number-- = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Rotate_Left -- Rotate specified MP number leftward.                                     *\n *                                                                                             *\n *    This routine will rotate the MP number to the left by one bit. The rotation passes bits  *\n *    through a \"carry\" bit position. The initial value of this \"carry\" bit is passed to the   *\n *    routine and the final value is returned as the result.                                   *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to perform the left rotate upon.              *\n *                                                                                             *\n *          carry    -- The initial value of the \"carry\" bit.                                  *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the final value of the carry bit. This is the the bit value of the    *\n *          upper most bit of the MP number prior to the rotate operation.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Rotate_Left(digit * number, bool carry, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\twhile (precision--) {\n\t\tbool temp = ((*number & UPPER_MOST_BIT) != 0);\n\t\t*number = (*number << 1);\n\t\tif (carry) *number = *number + 1;\n\t\tcarry = temp;\n\t\tnumber++;\n\t}\n\treturn carry;\n}\n\n\n/***********************************************************************************************\n * XMP_Not -- Perform bitwise NOT operation on MP number.                                      *\n *                                                                                             *\n *    Perform a bitwise NOT operation.                                                         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to operate on.                                *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Not(digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tfor (int index = 0; index < precision; index++) {\n\t\t*number = ~(*number);\n\t\tnumber++;\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Init -- Initialize an MP number to a starting value.                                    *\n *                                                                                             *\n *    This will initialize (assign) a number to an MP number. The initial value is limited     *\n *    to the precision allowed by a DIGIT type.                                                *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to initialize.                                *\n *                                                                                             *\n *          value    -- Initial integer value to assign to the MP number.                      *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Init(digit * number, digit value, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tmemset(number, '\\0', precision * sizeof(digit));\n\t*number = value;\n}\n\n\n/***********************************************************************************************\n * XMP_Count_Bits -- Count the total number of bits (precision) in MP number.                  *\n *                                                                                             *\n *    This routine will count the maximum number of bits used by this MP number. The result    *\n *    could be referred to as the \"bit precision\" of the MP number.                            *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- The (digit) precision of the MP number.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the number of significant bits in the MP number.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned XMP_Count_Bits(const digit * number, int precision)\n{\n\tassert(number != NULL);\n\tassert(precision > 0);\n\n\tint sub_precision = XMP_Significance(number, precision);\n\tif (!sub_precision) return(0);\n\tint total_bit_count = XMP_Digits_To_Bits(sub_precision);\n\tnumber += sub_precision-1;\n\tdigit high_bit_mask = UPPER_MOST_BIT;\n\n\twhile (!((*number) & high_bit_mask)) {\n\t\thigh_bit_mask >>= 1;\n\t\ttotal_bit_count--;\n\t}\n\n\treturn(total_bit_count);\n}\n\n\n/***********************************************************************************************\n * XMP_Count_Bytes -- Counts the number of precision bytes in MP number.                       *\n *                                                                                             *\n *    This routine will scan the MP number and determine the number of bytes needed to         *\n *    represent the MP number. Consider the result the \"byte precision\" of the number.         *\n *                                                                                             *\n * INPUT:   number   -- Pointer to the MP number to examine.                                   *\n *                                                                                             *\n *          precision-- Precision of the MP number.                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes required to represent the precision of the number.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Count_Bytes(const digit * number, int precision)\n{\n\tunsigned char * ptr = (unsigned char *)number;\n\tint count = 0;\n\tfor (unsigned index = 0; index < precision*sizeof(digit); index++) {\n\t\tif (!*ptr) break;\n\t\tcount++;\n\t\tptr++;\n\t}\n\treturn(count);\n}\n\n\n/***********************************************************************************************\n * XMP_Move -- Assign one MP number to another.                                                *\n *                                                                                             *\n *    This will move one MP number over the top of another.                                    *\n *                                                                                             *\n * INPUT:   dest     -- Destination MP number (will get clobbered).                            *\n *                                                                                             *\n *          source   -- Source MP number.                                                      *\n *                                                                                             *\n *          precision-- Precision of both MP numbers.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Both MP numbers must have the same precision.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Move(digit * dest, digit const * source, int precision)\n{\n\tmemcpy(dest, source, precision * sizeof(digit));\n}\n\n\n/***********************************************************************************************\n * XMP_Compare -- Compare one MP number with another.                                          *\n *                                                                                             *\n *    This routine will compare two MP numbers. It will return a value indicating which MP     *\n *    number is greater or if they are equal.                                                  *\n *                                                                                             *\n * INPUT:   left_number -- The left hand MP number.                                            *\n *                                                                                             *\n *          right_number-- The right hand MP number.                                           *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  Returns -1 if the left_number is less than the right_number.                       *\n *          Returns 1 if the left_number is greater than the right number.                     *\n *          Returns 0 if both numbers are identical.                                           *\n *                                                                                             *\n * WARNINGS:   Both numbers must have the same precision.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Compare(const digit * left_number, const digit * right_number, int precision)\n{\n\tleft_number += precision-1;\n\tright_number += precision-1;\n\tdo {\n\t\tif (*left_number < *right_number) return -1;\n\t\tif (*left_number > *right_number) return 1;\n\t\tleft_number--;\n\t\tright_number--;\n\t} while (--precision);\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Add -- Add two MP numbers with a carry option.                                          *\n *                                                                                             *\n *    Use this routine to add one MP number to another. There is an optional \"carry\" value     *\n *    that (when true) will add an additional 1 to the result.                                 *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the MP buffer that will hold the result. This can be the    *\n *                      same value as the left_number or right_number pointers.                *\n *                                                                                             *\n *          left_number -- The left hand MP number.                                            *\n *                                                                                             *\n *          right_number-- The right hand MP number.                                           *\n *                                                                                             *\n *          carry       -- Optional carry flag (typically this will be false).                 *\n *                                                                                             *\n *          precision   -- The precision of the numbers involved.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the carry flag after the addition. If the value is true then an       *\n *          overflow occurred.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Add(digit * result, const digit * left_number, const digit * right_number, bool carry, int precision)\n{\n\twhile (precision--) {\n\t\tdigit term = *left_number + *right_number;\n\t\tdigit final = term + carry;\n\t\tcarry = (term < *left_number || (carry && final == 0));\n\n\t\tright_number++;\n\t\tleft_number++;\n\t\t*result++ = final;\n\t}\n\treturn(carry);\n}\n\n\n/***********************************************************************************************\n * XMP_Add_Int -- Add an integer to an MP number (with carry).                                 *\n *                                                                                             *\n *    This routine will add an integer number to an MP number. There is an optional carry      *\n *    parameter. If the carry flag is true, and additional 1 will be added to the result.      *\n *    This routine is much faster than adding two MP numbers together.                         *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the result MP number. This pointer can be the same as    *\n *                         the left_number parameter.                                          *\n *                                                                                             *\n *          left_number -- Pointer to the left hand MP number.                                 *\n *                                                                                             *\n *          right_number-- The integer number to add to the left hand number.                  *\n *                                                                                             *\n *          carry       -- Input carry flag. If this is true, then an additional one will be   *\n *                         added to the result.                                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the result carry flag. A true value means the addition overflowed.    *\n *                                                                                             *\n * WARNINGS:   All MP numbers must share the same precision. Negative numbers are not          *\n *             supported.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Add_Int(digit * result, const digit * left_number, digit right_number, bool carry, int precision)\n{\n\twhile (precision--) {\n\t\tdigit term = *left_number + right_number;\n\t\tdigit final = term + carry;\n\t\tcarry = (term < *left_number || (carry && final == 0));\n\n\t\tright_number = 0;\n\t\tleft_number++;\n\t\t*result++ = final;\n\t}\n\treturn(carry);\n}\n\n\n/***********************************************************************************************\n * XMP_Sub -- Subtract one MP number from another (with borrow).                               *\n *                                                                                             *\n *    This routine will subtract one MP number from another. There is an optional borrow       *\n *    flag that can be specified.                                                              *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP number that will hold the result. This pointer    *\n *                         can be the same as the left_number or right_number parameters.      *\n *                                                                                             *\n *          left_number -- The left hand number (value will be subtracted from this).          *\n *                                                                                             *\n *          right_number-- The right hand number (the value to subtract from the left number)  *\n *                                                                                             *\n *          borrow      -- The optional borrow flag. If this flag is true, the an extra one    *\n *                         will be subtracted from the result.                                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the borrow result flag. If the value is true, then an underflow       *\n *          occurred during subtraction.                                                       *\n *                                                                                             *\n * WARNINGS:   All MP numbers must share the same precision.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Sub(digit * result, const digit * left_number, const digit * right_number, bool borrow, int precision)\n{\n\tconst unsigned short * left_number_ptr = (const unsigned short *)left_number;\n\tconst unsigned short * right_number_ptr = (const unsigned short *)right_number;\n\tunsigned short * result_ptr = (unsigned short *)result;\n\n\tprecision *= 2;\n\twhile (precision--) {\n\t\tdigit x = (digit) *left_number_ptr - (digit) *right_number_ptr - (digit) borrow;\n\t\tright_number_ptr++;\n\t\tleft_number_ptr++;\n\t\t*result_ptr++ = (unsigned short)x;\n\t\tborrow = (((1L << 16) & x) != 0L);\n\t}\n\treturn (borrow);\n}\n\n\n/***********************************************************************************************\n * XMP_Sub_Int -- Subtract an integer from an MP number (with borrow).                         *\n *                                                                                             *\n *    This will subtract an integer from the specified MP number. There is an optional borrow  *\n *    flag available.                                                                          *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          left_number -- Pointer to the MP number that will be subtracted FROM.              *\n *                                                                                             *\n *          right_number-- The integer to subtract from the left hand number.                  *\n *                                                                                             *\n *          borrow      -- The optional borrow flag. If this value is true, then an extra one  *\n *                         will be subtracted from the result.                                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the borrow flag of the result. If this value is true, then an         *\n *          underflow occurred during subtraction.                                             *\n *                                                                                             *\n * WARNINGS:   The precision must be identical between the MP numbers involved.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Sub_Int(digit * result, const digit * left_number, unsigned short right_number, bool borrow, int precision)\n{\n\tconst unsigned short * left_number_ptr = (const unsigned short *)left_number;\n\tunsigned short * result_ptr = (unsigned short *)result;\n\n\tprecision *= 2;\n\twhile (precision--) {\n\t\tdigit x = (digit) *left_number_ptr - right_number - borrow;\n\t\tleft_number_ptr++;\n\t\t*result_ptr++ = (unsigned short)x;\n\t\tborrow = (((1L << 16) & x) != 0L);\n\n\t\tright_number = 0;\n\t}\n\treturn (borrow);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Mult -- Multiply two unsigned MP numbers together.                             *\n *                                                                                             *\n *    This routine will multiply two MP numbers together. The result will have the sum of the  *\n *    significance of the two.                                                                 *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP buffer that will hold the result.         *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the product will fit within the precision of the result.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/01/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tXMP_Init(prod, 0, precision);\n\n\t/*\n\t**\tMultiplying by zero is always a zero product.\n\t*/\n\tif (XMP_Test_Eq_Int(multiplicand, 0, precision) || XMP_Test_Eq_Int(multiplier, 0, precision)) {\n\t\treturn 0;\n\t}\n\n\tint total_bit_count = XMP_Count_Bits(multiplier, precision);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!sub_precision) return(0);\n\tmultiplier += sub_precision;\n\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(prod, 1, precision);\n\n\t\tif ((*(multiplier-1)) & high_bit_mask) {\n\t\t\tXMP_Add(prod, prod, multiplicand, 0, precision);\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tmultiplier--;\n\t\t}\n\n\t}\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Mult_Int -- Multiply an MP number by a simple integer.                         *\n *                                                                                             *\n *    This is a very fast multiply since the multiplier is just an integer integral.           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number.                                   *\n *                                                                                             *\n *          multiplicand-- Pointer to the MP number that is the multiplicand.                  *\n *                                                                                             *\n *          multiplier  -- The integral integer that is the multiplier.                        *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The multiplier must fit in a signed integer (although it isn't a signed value). *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Mult_Int(digit * prod, const digit * multiplicand, short multiplier, int precision)\n{\n\tconst unsigned short * m2 = (const unsigned short *)multiplicand;\n\tunsigned short * pr = (unsigned short *)prod;\n\tunsigned long carry = 0;\n\tfor (int i = 0; i < precision*2; ++i) {\n\t\tunsigned long p = (((unsigned long)multiplier) * *m2) + carry;;\n\t\t*pr = (unsigned short) p;\n\t\tcarry = p >> 16;\n\t\tm2++;\n\t\tpr++;\n\t}\n\n\t/* Add carry to the next higher word of product / dividend */\n//\t*pr += (unsigned short)carry;\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Mult_Int -- Multiply an MP number by a signed simple integer.                    *\n *                                                                                             *\n *    This will multiply the specified integer with the MP number. It is a much faster         *\n *    multiply than when multiplying two MP numbers.                                           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number.                                   *\n *                                                                                             *\n *          multiplicand-- Pointer to the MP number that serves as the multiplicand.           *\n *                                                                                             *\n *          multiplier  -- The simple integral integer used as the multiplier.                 *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The multiplier must fist within a signed short integer.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Signed_Mult_Int(digit * prod, const digit * multiplicand, signed short multiplier, int precision)\n{\n\tif (XMP_Is_Negative(multiplicand, precision)) {\n\t\tdigit abs_multiplicand[MAX_UNIT_PRECISION];\n\t\tXMP_Move(abs_multiplicand, multiplicand, precision);\n\t\tXMP_Neg(abs_multiplicand, precision);\n\n\t\tif (multiplier < 0) {\n\t\t\tmultiplier = (signed short)-multiplier;\n\n\t\t\tXMP_Unsigned_Mult_Int(prod, abs_multiplicand, multiplier, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult_Int(prod, abs_multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t}\n\t} else {\n\t\tif (multiplier < 0) {\n\t\t\tmultiplier = (signed short)-multiplier;\n\n\t\t\tXMP_Unsigned_Mult_Int(prod, multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult_Int(prod, multiplicand, multiplier, precision);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Mult -- A signed multiply between two MP numbers.                                *\n *                                                                                             *\n *    This routine will perform a multiply between two signed MP numbers.                      *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the product MP number buffer.                            *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is not a very fast routine.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Signed_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tif (XMP_Is_Negative(multiplicand, precision)) {\n\t\tdigit abs_multiplicand[MAX_UNIT_PRECISION];\n\t\tXMP_Move(abs_multiplicand, multiplicand, precision);\n\t\tXMP_Neg(abs_multiplicand, precision);\n\n\t\tif (XMP_Is_Negative(multiplier, precision)) {\n\t\t\tdigit abs_multiplier[MAX_UNIT_PRECISION];\n\t\t\tXMP_Move(abs_multiplier, multiplier, precision);\n\t\t\tXMP_Neg(abs_multiplier, precision);\n\n\t\t\tXMP_Unsigned_Mult(prod, abs_multiplicand, abs_multiplier, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult(prod, abs_multiplicand, multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t}\n\t} else {\n\t\tif (XMP_Is_Negative(multiplier, precision)) {\n\t\t\tdigit abs_multiplier[MAX_UNIT_PRECISION];\n\t\t\tXMP_Move(abs_multiplier, multiplier, precision);\n\t\t\tXMP_Neg(abs_multiplier, precision);\n\n\t\t\tXMP_Unsigned_Mult(prod, multiplicand, abs_multiplier, precision);\n\t\t\tXMP_Neg(prod, precision);\n\t\t} else {\n\t\t\tXMP_Unsigned_Mult(prod, multiplicand, multiplier, precision);\n\t\t}\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Div_Int -- Perform a short integer divide into an MP number.                   *\n *                                                                                             *\n *    This routine performs a fast divide of the specified MP dividend by a simple             *\n *    short integer. The division is an UNSIGNED division however.                             *\n *                                                                                             *\n * INPUT:   quotient    -- Pointer to the MP number buffer where the quotient will go.         *\n *                                                                                             *\n *          dividend    -- Pointer to the MP number that serves as the dividend.               *\n *                                                                                             *\n *          divisor     -- The simple signed short integer that serves as the divisor.         *\n *                                                                                             *\n *          precision   -- The precision that is used by the MP numbers involved.              *\n *                                                                                             *\n * OUTPUT:  Returns with the remainder of the division.                                        *\n *                                                                                             *\n * WARNINGS:   This is an UNSIGNED divide even.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nunsigned short XMP_Unsigned_Div_Int(digit * quotient, digit const * dividend, unsigned short divisor, int precision)\n{\n\tif (!divisor) return 0;\t\t/* zero divisor means divide error */\n\n\tunsigned short remainder = 0;\n\n\tXMP_Init(quotient, 0, precision);\n\n\tint total_bit_count = XMP_Count_Bits(dividend, precision);\n\tint digit_precision = XMP_Bits_To_Digits(total_bit_count);\n\tdigit const * dividend_ptr = dividend + (digit_precision-1);\n\n\tif (!digit_precision) return(0);\n\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\tdigit * quotient_ptr = quotient + (digit_precision-1);\n\n\twhile (total_bit_count--) {\n\t\tremainder <<= 1;\n\n\t\tif ((*dividend_ptr) & high_bit_mask) remainder++;\n\n\t\tif (remainder >= divisor) {\n\t\t\tremainder -= divisor;\n\t\t\t*quotient_ptr |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\t--dividend_ptr;\n\t\t\t--quotient_ptr;\n\t\t}\n\t}\n\n\treturn(remainder);\n}\n\n\n/***********************************************************************************************\n * XMP_Unsigned_Div -- Unsigned divide of one MP number into another.                          *\n *                                                                                             *\n *    This will perform the (dog slow) divide of one MP number into another. Because of the    *\n *    slowness of this routine, both the quotient and the remainder are available as a         *\n *    result of the operation.                                                                 *\n *                                                                                             *\n * INPUT:   remainder   -- Pointer to the MP buffer that will hold the remainder of the divide.*\n *                                                                                             *\n *          quotient    -- Pointer to the MP buffer that will hold the quotient of the divide. *\n *                                                                                             *\n *          dividend    -- The MP dividend (numerator) number.                                 *\n *                                                                                             *\n *          divisor     -- The MP divisor (denominator) number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is very slow.                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Unsigned_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision)\n{\n\t// check for divide by zero.\n\tif (XMP_Test_Eq_Int(divisor, 0, precision)) return(-1);\n\n\tXMP_Init(remainder, 0, precision);\n\tXMP_Init(quotient, 0, precision);\n\n\tint total_bit_count = XMP_Count_Bits(dividend, precision);\n\tint digit_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!digit_precision) return(0);\n\n\tdigit const * dividend_ptr = dividend + (digit_precision-1);\n\tdigit * quotient_ptr = quotient + (digit_precision-1);\n\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(remainder, 1, precision);\n\n\t\tif (((*dividend_ptr) & high_bit_mask) != 0) {\n\t\t\tXMP_Inc(remainder, precision);\n\t\t}\n\n\t\tif (XMP_Compare(remainder, divisor, precision) >= 0) {\n\t\t\tXMP_Sub(remainder, remainder, divisor, 0, precision);\n\t\t\t*quotient_ptr |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tdividend_ptr--;\n\t\t\tquotient_ptr--;\n\t\t}\n\n\t}\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Signed_Div -- Signed divide of one MP number into another.                              *\n *                                                                                             *\n *    This will perform a signed divide (very very slow) of one MP number into another.        *\n *    Because of the slow nature of this routine, both the quotient and the remainder are      *\n *    available as results.                                                                    *\n *                                                                                             *\n * INPUT:   remainder   -- Pointer to the buffer that will hold the remainder of the divide.   *\n *                                                                                             *\n *          quotient    -- Pointer to the buffer that will hold the quotient of the divide.    *\n *                                                                                             *\n *          dividend    -- The dividend (numerator) MP number.                                 *\n *                                                                                             *\n *          divisor     -- The divisor (denominator) MP number.                                *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is very very slow.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Signed_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision)\n{\n\tbool negative = false;\n\n\tdigit scratch_dividend[MAX_UNIT_PRECISION];\n\tXMP_Move(scratch_dividend, dividend, precision);\n\n\tdigit scratch_divisor[MAX_UNIT_PRECISION];\n\tXMP_Move(scratch_divisor, divisor, precision);\n\n\tif (XMP_Is_Negative(scratch_dividend, precision)) {\n\t\tXMP_Neg(scratch_dividend, precision);\n\t\tnegative = !negative;\n\t}\n\n\tif (XMP_Is_Negative(scratch_divisor, precision)) {\n\t\tXMP_Neg(scratch_divisor, precision);\n\t\tnegative = !negative;\n\t}\n\n\tXMP_Unsigned_Div(remainder, quotient, scratch_dividend, scratch_divisor, precision);\n\n\tif (negative) {\n\t\tXMP_Neg(quotient, precision);\n\t\tif (!XMP_Test_Eq_Int(remainder, 0, precision)) {\n\t\t\tXMP_Dec(quotient, precision);\n\t\t\tXMP_Neg(remainder, precision);\n\t\t\tXMP_Add(remainder, remainder, scratch_divisor, 0, precision);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Inverse_A_Mod_B -- Inverts and performs modulus on an MP number.                        *\n *                                                                                             *\n *    This is a utility routine that will perform an inverse on the MP number and then         *\n *    perform a modulus of that number by another MP number. There are some algorithms that    *\n *    require this process.                                                                    *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          number      -- The MP number that will be inverted then modulo-ized.               *\n *                                                                                             *\n *          modulus     -- The MP number to modulus the first number by.                       *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Inverse_A_Mod_B(digit * result, digit const * number, digit const * modulus, int precision)\n{\n\tdigit g[3][MAX_UNIT_PRECISION];\n\tXMP_Move(g[0], modulus, precision);\n\tXMP_Move(g[1], number, precision);\n\n\tdigit v[3][MAX_UNIT_PRECISION];\n\tXMP_Init(v[0], 0, precision);\n\tXMP_Init(v[1], 1, precision);\n\n\tdigit y[MAX_UNIT_PRECISION];\n\n\tint i;\n\tfor (i = 1; !XMP_Test_Eq_Int(g[i%3], 0, precision); i++) {\n\t\tXMP_Unsigned_Div(g[(i+1)%3], y, g[(i-1)%3], g[i%3], precision);\n\n\t\tXMP_Unsigned_Mult(result, v[i%3], y, precision);\n\t\tXMP_Sub(v[(i+1)%3], v[(i-1)%3], result, 0, precision);\n\t}\n\n\tif (XMP_Is_Negative(v[(i-1)%3], precision)) {\n\t\tXMP_Add(v[(i-1)%3], v[(i-1)%3], modulus, 0, precision);\n\t}\n\n\tXMP_Move(result, v[(i-1)%3], precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Reciprocal -- Compute the reciprocal (inverse) of the MP number.                        *\n *                                                                                             *\n *    Use this routine to determine the inverse of the specified MP number. The inverse is     *\n *    defined as 1/number.                                                                     *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the result MP number buffer.                                *\n *                                                                                             *\n *          number   -- The number to be inverted.                                             *\n *                                                                                             *\n *          precision-- The precision of the MP number.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Reciprocal(digit * quotient, const digit * divisor, int precision)\n{\n\tdigit remainder[MAX_UNIT_PRECISION];\n\n\tif (XMP_Test_Eq_Int(divisor, 0, precision)) return -1;\t\t/* zero divisor means divide error */\n\n\tXMP_Init(remainder, 0, precision);\n\tXMP_Init(quotient, 0, precision);\n\n\t/* normalize and compute number of bits in quotient first */\n\tunsigned total_bit_count = XMP_Count_Bits(divisor, precision);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count + 1);\t/* bitmask within a single digit */\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count + 1);\n\n\tXMP_Set_Bit(remainder, total_bit_count - 1);\n\n\t/* rescale quotient to precision of divisor bits */\n\tquotient += sub_precision-1;\n\n\twhile (total_bit_count--) {\n\t\tXMP_Shift_Left_Bits(remainder, 1, precision);\n\t\tif (XMP_Compare(remainder, divisor, precision) >= 0) {\n\t\t\tXMP_Sub(remainder, remainder, divisor, 0, precision);\n\t\t\t*quotient |= high_bit_mask;\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\tquotient--;\n\t\t}\n\t}\n\n\tXMP_Init(remainder, 0, precision);\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Decode_ASCII -- Convert ASCII into an MP number.                                        *\n *                                                                                             *\n *    This routine will convert a supplied ASCII string into an MP number.                     *\n *                                                                                             *\n * INPUT:   str      -- Pointer to the ASCII string that will be converted.                    *\n *                                                                                             *\n *          mpn      -- Pointer to the MP number buffer that will be initialized.              *\n *                                                                                             *\n *          precision -- The precision of the MP number.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Decode_ASCII(char const * str, digit * mpn, int precision)\n{\n\t/*\n\t**\tInitialize the multiprecision number to zero. From this point\n\t**\tonward, this object can be manipulated as a regular number.\n\t**\tThis is, in fact, what is done as the ascii string is parsed\n\t**\tinto a working number.\n\t*/\n\tXMP_Init(mpn, 0, precision);\n\n\t/*\n\t**\tNo string or zero length is considered '0'.\n\t*/\n\tif (!str) return;\n\tint i = strlen(str);\n\tif (i == 0) return;\n\n\tunsigned short radix;\t\t/* base 2-16 */\n\tswitch (toupper(str[i-1])) {\t\t/* classify radix select suffix character */\n\t\tcase '.':\n\t\t\tradix = 10;\n\t\t\tbreak;\n\n\t\tcase 'H':\n\t\t\tradix = 16;\n\t\t\tbreak;\n\n\t\tcase 'O':\n\t\t\tradix = 8;\n\t\t\tbreak;\n\n\t\tcase 'B':\t\t\t/* caution! 'b' is a hex digit! */\n\t\t\tradix = 2;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tradix = 10;\n\t\t\tbreak;\n\t}\n\n\tbool minus = (*str == '-');\n\tif (minus) str++;\n\n\tdigit c;\n\twhile ((c = (unsigned char)*str++) != 0) {\n\t\tif (c == ',') continue;\t\t/* allow commas in number */\n\n\t\t/*\n\t\t**\tIf not a hexadecimal (highest base) digit then it is\n\t\t**\tclearly the end of the processable string. Bail out\n\t\t**\tof the scan loop.\n\t\t*/\n\t\tif (!isxdigit((char)c)) break;\n\n\t\t/*\n\t\t**\tConvert the character into an integer number 0 through 15.\n\t\t*/\n\t\tif (isdigit((char)c)) {\n\t\t\tc -= '0';\n\t\t} else {\n\t\t\tc = (unsigned char)(toupper((char)c) - 'A') + 10;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the integer digit is greater than the radix, then we\n\t\t**\tknow that further processing should stop. This is the\n\t\t**\tend of the number string.\n\t\t*/\n\t\tif (c >= radix) break;\t\t/* scan terminated by any non-digit */\n\n\n\t\tXMP_Unsigned_Mult_Int(mpn, mpn, radix, precision);\n\t\tXMP_Add_Int(mpn, mpn, c, 0, precision);\n\t}\n\tif (minus) {\n\t\tXMP_Neg(mpn, precision);\n\t}\n}\n\n\n/***********************************************************************************************\n * XMP_Hybrid_Mul -- Special hybrid short multiply (with carry).                               *\n *                                                                                             *\n *    Multiply the single-word multiplier times the multiprecision integer                     *\n *    in multiplicand, accumulating result in prod.  The resulting                             *\n *    multiprecision prod will be 1 word longer than the multiplicand.                         *\n *    multiplicand is double precision words long.  We add into prod, so caller                *\n *    should zero it out first.  For best results, this time-critical                          *\n *    function should be implemented in assembly.                                              *\n *    NOTE:  Unlike other functions in the multiprecision arithmetic                           *\n *    library, both multiplicand and prod are pointing at the LSB,                             *\n *    regardless of byte order of the machine.  On an 80x86, this makes                        *\n *    no difference.  But if this assembly function is implemented                             *\n *    on a 680x0, it becomes important.                                                        *\n *                                                                                             *\n *    Note that this has been modified from the previous version to allow                      *\n *    better support for Smith's modmult:                                                      *\n *         The final carry bit is added to the existing product                                *\n *         array, rather than simply stored.                                                   *\n *                                                                                             *\n * INPUT:   prod     -- Pointer to the product MP number buffer.                               *\n *                                                                                             *\n *          multiplicand   -- Pointer to the multiplicand MP number.                           *\n *                                                                                             *\n *          multiplier  -- The short integer used as the multiplier.                           *\n *                                                                                             *\n *          precision   -- The precision of the MP number used.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The carry (if any) is added into the integer one beyond the end of the          *\n *             product buffer.                                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Hybrid_Mul(unsigned short * prod, unsigned short * multiplicand, unsigned short multiplier, int precision)\n{\n\tunsigned long carry = 0;\n\tfor (int i = 0; i < precision; ++i) {\n\t\tunsigned long p = (unsigned long)multiplier * *multiplicand++;\n\t\tp += *prod + carry;\n\t\t*prod++ = (unsigned short) p;\n\t\tcarry = p >> 16;\n\t}\n\n\t/* Add carry to the next higher word of product / dividend */\n\t*prod += (unsigned short) carry;\n}\n\n\n/***********************************************************************************************\n * XMP_Double_Mul -- Double precision MP multiply.                                             *\n *                                                                                             *\n *    This will perform a double precision multiply of MP numbers. This means that the product *\n *    will be twice the precision of the components.                                           *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the result buffer. This buffer must be able to hold      *\n *                         double the precision specified.                                     *\n *                                                                                             *\n *          multiplicand-- Pointer to the multiplicand MP number.                              *\n *                                                                                             *\n *          multiplier  -- Pointer to the multiplier number.                                   *\n *                                                                                             *\n *          precision   -- The precision of the two component MP numbers.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure the product buffer can hold a double precision number.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Double_Mul(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\t/*\n\t**\tClear out the double precision product buffer.\n\t*/\n\tXMP_Init(prod, 0, precision*2);\n\n\tconst unsigned short * multiplier_ptr = (const unsigned short *) multiplier;\n\tunsigned short * product_ptr = (unsigned short *) prod;\n\n\t// Multiply multiplicand by each word in multiplier, accumulating prod.\n\tfor (int i = 0; i < precision*2; ++i) {\n\t\tXMP_Hybrid_Mul(product_ptr++, (unsigned short *)multiplicand, *multiplier_ptr++, precision*2);\n\t}\n}\n\n\n\nstatic int _modulus_shift;\t\t\t\t\t\t\t\t\t// number of bits for recip scaling\nstatic unsigned short _reciprical_high_digit;\t\t// MSdigit of scaled recip\nstatic unsigned short _reciprical_low_digit;\t\t\t// LSdigit of scaled recip\n\nstatic int _modulus_sub_precision;\t\t\t\t\t\t//\tlength of modulus in MULTUNITs\nstatic int _modulus_bit_count;\t\t\t\t\t\t\t//\tnumber of modulus significant bits\nstatic digit _scratch_modulus[MAX_UNIT_PRECISION];\t// modulus\n\n// The double precision modulus staging buffer.\nstatic digit _double_staging_number[MAX_UNIT_PRECISION * 2 + 2];\n\n// most significant digits of modulus.\nstatic digit _mod_quotient[4];\nstatic digit _mod_divisor[4];\n\n\n/***********************************************************************************************\n * XMP_Prepare_Modulus -- Prepare globals for modulus operation.                               *\n *                                                                                             *\n *    Calculate the reciprocal of modulus with a precision of two MULTUNITs.                   *\n *    Assumes that precision has already been adjusted to the                                  *\n *    size of the modulus, plus SLOP_BITS.                                                     *\n *                                                                                             *\n *    Note: This routine was designed to work with large values and                            *\n *    doesn't have the necessary testing or handling to work with a                            *\n *    modulus having less than three significant digits.  For such cases,                      *\n *    the separate multiply and modulus routines can be used.                                  *\n *                                                                                             *\n * INPUT:   modulus  -- Pointer to the modulus number.                                         *\n *                                                                                             *\n *          precision-- The precision of the modulus number.                                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Prepare_Modulus(const digit * n_modulus, int precision)\n{\n\tXMP_Move(_scratch_modulus, n_modulus, precision);\n\n\t_modulus_bit_count = XMP_Count_Bits(_scratch_modulus, precision);\n\t_modulus_sub_precision = (_modulus_bit_count + 16 - 1) / 16;\n\n\t/*\n\t**\tKeep 2*16 bits in _mod_divisor.\n\t** This will (normally) result in a reciprocal of 2*16+1 bits.\n\t*/\n\tint sub_precision = XMP_Significance(_scratch_modulus, precision);\t// significant digits in modulus\n\tXMP_Move(_mod_divisor, &_scratch_modulus[sub_precision-2], 2);\n\t_modulus_shift = XMP_Count_Bits(_mod_divisor, 2) - 2 * 16;\n\tXMP_Shift_Right_Bits(_mod_divisor, _modulus_shift, 2);\n\n\tXMP_Reciprocal(_mod_quotient, _mod_divisor, 2);\n\tXMP_Shift_Right_Bits(_mod_quotient, 1, 2);\n\n\t/* Reduce to:   0 < _modulus_shift <= 16 */\n\t_modulus_shift = ((_modulus_shift + (16 - 1)) % 16) + 1;\n\n\t/* round up */\n\tXMP_Inc(_mod_quotient, 2);\n\tif (XMP_Count_Bits(_mod_quotient, 2) > 2 * 16) {\n\t\tXMP_Shift_Right_Bits(_mod_quotient, 1, 2);\n\t\t_modulus_shift--;\t\t/* now  0 <= _modulus_shift <= 16 */\n\t}\n\tunsigned short * mpm = (unsigned short *) _mod_quotient;\n\t_reciprical_low_digit = *mpm++;\n\t_reciprical_high_digit = *mpm;\n\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * XMP_Mod_Mult -- Perform a multiply - modulus operation.                                     *\n *                                                                                             *\n *    This routine will combine a multiply and a modulus operation. This takes advantage of    *\n *    a tremendous speed advantage possible if these two processes are combined rather than    *\n *    being performed separately.                                                              *\n *                                                                                             *\n * INPUT:   prod        -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          multiplicand-- The number to multiply.                                             *\n *                                                                                             *\n *          multiplier  -- The number to multiply by.                                          *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The modulus must already have been prepared by the routine XMP_Prepare_Modulus. *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint XMP_Mod_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision)\n{\n\tXMP_Double_Mul(_double_staging_number, multiplicand, multiplier, precision);\n\n\tint double_precision = precision * 2 + 1;\n\n\t_double_staging_number[double_precision - 1] = 0;\t/* leading 0 digit */\n\n\t/*\n\t**\tWe now start working with MULTUNITs.\n\t**\tDetermine the most significant MULTUNIT of the product so we don't\n\t**\thave to process leading zeros in our divide loop.\n\t*/\n\tint dmi = XMP_Significance(_double_staging_number, double_precision) * 2;\t//\tnumber of significant MULTUNITs in product\n\n\tif (dmi >= _modulus_sub_precision) {\n\n\t\t/* Make dividend negative.  This allows the use of mp_single_mul to\n\t\t** \"subtract\" the product of the modulus and the trial divisor\n\t\t** by actually adding to a negative dividend.\n\t\t** The one's complement of the dividend is used, since it causes\n\t\t** a zero value to be represented as all ones.  This facilitates\n\t\t** testing the result for possible overflow, since a sign bit\n\t\t** indicates that no adjustment is necessary, and we should not\n\t\t** attempt to adjust if the result of the addition is zero.\n\t\t*/\n\t\tXMP_Inc(_double_staging_number, double_precision);\n\t\tXMP_Neg(_double_staging_number, double_precision);\n\n\t\tint nqd = dmi + 1 - _modulus_sub_precision; \t// number of quotient digits remaining to be generated\n\n\t\t/* Set msb, lsb, and normal ptrs of dividend */\n\t\tunsigned short * dmph = ((unsigned short *)_double_staging_number) + dmi + 1;\t// points to one higher than precision would indicate\n\t\tunsigned short * dmpl = dmph - _modulus_sub_precision;\n\n\t\t/*\n\t\t** Divide loop.\n\t\t** Each iteration computes the next quotient MULTUNIT digit, then\n\t\t** multiplies the divisor (modulus) by the quotient digit and adds\n\t\t** it to the one's complement of the dividend (equivalent to\n\t\t** subtracting).  If the product was greater than the remaining dividend,\n\t\t** we get a non-negative result, in which case we subtract off the\n\t\t** modulus to get the proper negative remainder.\n\t\t*/\n\t\tfor (; nqd; nqd--) {\n\t\t\t--dmph;\n\t\t\t--dmpl;\n\n\t\t\tunsigned short q = mp_quo_digit(dmph);\t// trial quotient digit\n\t\t\tif (q > 0) {\n\t\t\t\tXMP_Hybrid_Mul(dmpl, (unsigned short *)_scratch_modulus, q, precision*2);\n\n\t\t\t\t/* Perform correction if q too large.\n\t\t\t\t**  This rarely occurs.\n\t\t\t\t*/\n\t\t\t\tif (!(*dmph & SEMI_UPPER_MOST_BIT)) {\n\t\t\t\t\tunsigned short * dmp = dmpl;\n\t\t\t\t\tif (XMP_Sub((unsigned long *)dmp, (unsigned long *)dmp, _scratch_modulus, false, precision)) {\n\t\t\t\t\t\t(*dmph)--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* d contains the one's complement of the remainder. */\n\t\tXMP_Neg(_double_staging_number, precision);\n\t\tXMP_Dec(_double_staging_number, precision);\n\t}\n\n\tXMP_Move(prod, _double_staging_number, precision);\n\treturn (0);\n}\n\n\n/***********************************************************************************************\n * XMP_Mod_Mult_Clear -- Remove temporary values from memory.                                  *\n *                                                                                             *\n *    Smith's mp_modmult function leaves some internal arrays in memory,                       *\n *    so we have to call modmult_burn() at the end of mp_exponent_mod.                         *\n *    This is so that no cryptographically sensitive data is left in memory                    *\n *    after the program exits.                                                                 *\n *                                                                                             *\n * INPUT:   precision   -- The precision of the numbers involved.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Mod_Mult_Clear(int precision)\n{\n\tXMP_Init(_scratch_modulus, 0, precision);\n\tXMP_Init(_double_staging_number, 0, precision);\n\tXMP_Init(_mod_quotient, 0, ARRAY_SIZE(_mod_quotient));\n\tXMP_Init(_mod_divisor, 0, ARRAY_SIZE(_mod_divisor));\n\t_modulus_shift = _modulus_bit_count = 0;\n\t_reciprical_high_digit = _reciprical_low_digit = 0;\n\t_modulus_sub_precision = /*mutemp =*/ 0;\n}\n\n\n/*\n** The function mp_quo_digit is the heart of Smith's modulo reduction,\n** which uses a form of long division.  It computes a trial quotient\n** \"digit\" (MULTUNIT-sized digit) by multiplying the three most\n** significant MULTUNITs of the dividend by the two most significant\n** MULTUNITs of the reciprocal of the modulus.  Note that this function\n** requires that 16 * 2 <= sizeof(unsigned long).\n**\n** An important part of this technique is that the quotient never be\n** too small, although it may occasionally be too large.  This was\n** done to eliminate the need to check and correct for a remainder\n** exceeding the divisor.       It is easier to check for a negative\n** remainder.  The following technique rarely needs correction for\n** MULTUNITs of at least 16 bits.\n**\n** The following routine has two implementations:\n**\n** Parameter: dividend - points to the most significant MULTUNIT\n**      of the dividend.  Note that dividend actually contains the\n**      one's complement of the actual dividend value (see comments for\n**      XMP_Mod_Mult).\n**\n**  Return: the trial quotient digit resulting from dividing the first\n**      three MULTUNITs at dividend by the upper two MULTUNITs of the\n**      modulus.\n*/\nunsigned short mp_quo_digit(unsigned short * dividend)\n{\n\tunsigned long q, q0, q1, q2;\n\n\t/*\n\t* Compute the least significant product group.\n\t* The last terms of q1 and q2 perform upward rounding, which is\n\t* needed to guarantee that the result not be too small.\n\t*/\n\tq1 = (dividend[-2] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit + _reciprical_high_digit;\n\tq2 = (dividend[-1] ^ SEMI_MASK) * (unsigned long) _reciprical_low_digit + (1L << 16);\n\tq0 = (q1 >> 1) + (q2 >> 1) + 1;\n\n\t/*      Compute the middle significant product group.   */\n\tq1 = (dividend[-1] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit;\n\tq2 = (dividend[0] ^ SEMI_MASK) * (unsigned long) _reciprical_low_digit;\n\tq = (q0 >> 16) + (q1 >> 1) + (q2 >> 1) + 1;\n\n\t/*      Compute the most significant term and add in the others */\n\tq = (q >> (16 - 2)) + (((dividend[0] ^ SEMI_MASK) * (unsigned long) _reciprical_high_digit) << 1);\n\tq >>= _modulus_shift;\n\n\t/*      Prevent overflow and then wipe out the intermediate results. */\n\treturn (unsigned short) min(q, (unsigned long)(1L << 16) - 1);\n}\n\n\n/*\n** Russian peasant combined exponentiation/modulo algorithm.\n** Calls modmult instead of mult.\n** Computes:  expout = (expin**exponent) mod modulus\n** WARNING: All the arguments must be less than the modulus!\n*/\nint xmp_exponent_mod(digit * expout, const digit * expin, const digit * exponent_ptr, const digit * modulus, int precision)\n{\n\tdigit product[MAX_UNIT_PRECISION];\n\n\tXMP_Init(expout, 1, precision);\n\tif (XMP_Test_Eq_Int(exponent_ptr, 0, precision)) {\n\t\tif (XMP_Test_Eq_Int(expin, 0, precision)) {\n\t\t\treturn -1;\t\t/* 0 to the 0th power means return error */\n\t\t}\n\t\treturn 0;\t\t/* otherwise, zero exponent means expout is 1 */\n\t}\n\n\tif (XMP_Test_Eq_Int(modulus, 0, precision)) {\n\t\treturn -2;\t\t/* zero modulus means error */\n\t}\n\n\tif (XMP_Compare(expin, modulus, precision) >= 0) {\n\t\treturn -3;\t\t/* if expin >= modulus, return error */\n\t}\n\n\tif (XMP_Compare(exponent_ptr, modulus, precision) >= 0) {\n\t\treturn -4;\t\t/* if exponent >= modulus, return error */\n\t}\n\n\t/* set smallest optimum precision for this modulus */\n\tint limited_precision = XMP_Significance(modulus, precision);\n\n\tif (XMP_Prepare_Modulus(modulus, limited_precision)) {\n\t\treturn -5;\t\t/* unstageable modulus (STEWART algorithm) */\n\t}\n\n\t/* normalize and compute number of bits in exponent first */\n//\tint exp_precision = XMP_Significance(exponent_ptr, limited_precision);\n//\tif (!exp_precision) return(0);\n//\tint bits = XMP_Digits_To_Bits(exp_precision);\n//\texponent_ptr += (exp_precision-1);\n//\tdigit high_bit_mask = UPPER_MOST_BIT;\n//\twhile (! ((*exponent_ptr) & high_bit_mask)) {\n//\t\thigh_bit_mask >>= 1;\n//\t\tbits--;\n//\t}\n\n\tint total_bit_count = XMP_Count_Bits(exponent_ptr, limited_precision);\n\tint sub_precision = XMP_Bits_To_Digits(total_bit_count);\n\tif (!sub_precision) return(0);\n\tdigit high_bit_mask = XMP_Bits_To_Mask(total_bit_count);\n\texponent_ptr += (sub_precision-1);\n\n\t/* We can \"optimize out\" the first modsquare and modmult: */\n\ttotal_bit_count--;\t\t\t/* We know for sure at this point that bits>0 */\n\n\tXMP_Move(expout, expin, limited_precision);\n\n\thigh_bit_mask >>= 1;\n\tif (!high_bit_mask) {\n\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\texponent_ptr--;\n\t}\n\n\twhile (total_bit_count--) {\n\t\tXMP_Mod_Mult(product, expout, expout, limited_precision);\n\n\t\tif (((*exponent_ptr) & high_bit_mask)) {\n\t\t\tXMP_Mod_Mult(expout, product, expin, limited_precision);\n\t\t} else {\n\t\t\tXMP_Move(expout, product, limited_precision);\n\t\t}\n\n\t\thigh_bit_mask >>= 1;\n\t\tif (!high_bit_mask) {\n\t\t\thigh_bit_mask = UPPER_MOST_BIT;\n\t\t\texponent_ptr--;\n\t\t}\n\n\t}\n\n\tXMP_Init(product, 0, limited_precision);\n\tXMP_Mod_Mult_Clear(limited_precision);\t\t/* ask mp_modmult to also burn its own evidence */\n\n\treturn 0;\n}\n\n\n/***********************************************************************************************\n * memrev -- Reverse the byte order of the buffer specified.                                   *\n *                                                                                             *\n *    This routine will reverse the byte order in the buffer specified.                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will be reversed.                           *\n *                                                                                             *\n *          length   -- The length of the buffer.                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid memrev(char * buffer, size_t length)\n{\n\tchar * r2 = &(buffer[length - 1]);\n\twhile (buffer < r2) {\n\t\tchar b = *buffer;\n\t\t*buffer++ = *r2;\n\t\t*r2-- = b;\n\t}\n}\n\n\nint _USERENTRY pfunc(const void * pkey, const void * base)\n{\n\tif (*(unsigned short *)pkey < *(unsigned short *)base) return(-1);\n\tif (*(unsigned short *)pkey > *(unsigned short *)base) return(1);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * XMP_Is_Small_Prime -- Determine if MP number is a small prime.                              *\n *                                                                                             *\n *    This routine will compare the MP number against all known small prime numbers. It will   *\n *    return true if a match was found.                                                        *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to MP number that is to be tested.                          *\n *                                                                                             *\n *          precision   -- The precision of the MP number specified.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the MP number a member of the small prime community?                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Is_Small_Prime(const digit * candidate, int precision)\n{\n\t/*\n\t**\tIf the number is too large for comparison to the known small primes table, then\n\t**\tbail immediately.\n\t*/\n\tif (XMP_Significance(candidate, precision) > 1) return(false);\n\tif (*candidate > primeTable[ARRAY_SIZE(primeTable)-1]) return false;\n\n\tunsigned long * ptr = (unsigned long *)bsearch(&candidate, &primeTable[0], ARRAY_SIZE(primeTable), sizeof(primeTable[0]), pfunc);\n\treturn(ptr != NULL);\n}\n\n\n/***********************************************************************************************\n * XMP_Small_Divisors_Test -- Perform the small divisors test on an MP number.                 *\n *                                                                                             *\n *    This test for primality will divide an MP number by the set of small primes. If any of   *\n *    these numbers divides evenly into the candidate number, then it is known that the        *\n *    candidate is NOT prime.                                                                  *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to the MP number that is to be tested.                      *\n *                                                                                             *\n *          precision   -- The precision of the MP number/                                     *\n *                                                                                             *\n * OUTPUT:  bool; Did the MP number pass the small divisors test?                              *\n *                                                                                             *\n * WARNINGS:   If the MP number passes, it doesn't mean that it is prime, just that is hasn't  *\n *             yet been proven to be not prime.                                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Small_Divisors_Test(const digit * candidate, int precision)\n{\n\tdigit quotient[MAX_UNIT_PRECISION];\n\n\tfor (unsigned i = 0; i < ARRAY_SIZE(primeTable); i++) {\n\t\tif (XMP_Unsigned_Div_Int(quotient, candidate, primeTable[i], precision) == 0) return(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * XMP_Fermat_Test -- Performs Fermat's Little Theorem on an MP number.                        *\n *                                                                                             *\n *    This is a more expensive but thorough test for primality. The aggressiveness of this     *\n *    test can be controlled by the number of rounds specified. Four rounds is usually         *\n *    sufficient.                                                                              *\n *                                                                                             *\n * INPUT:   candidate   -- Pointer to the candidate MP number that is to be tested.            *\n *                                                                                             *\n *          rounds      -- The number of rounds to test the MP number (keep it small).         *\n *                                                                                             *\n *          precision   -- The precision of the MP number.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime. A FALSE means that it is not      *\n *                prime. A TRUE means that it might be prime.                                  *\n *                                                                                             *\n * WARNINGS:   This takes a bit of time. The time it takes is directly controlled by the       *\n *             number of rounds specified. Keep the number of rounds as small as possible.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Fermat_Test(const digit * candidate_prime, unsigned rounds, int precision)\n{\n\tassert(rounds < ARRAY_SIZE(primeTable));\n\n\tdigit term[MAX_UNIT_PRECISION];\n\tXMP_Move(term, candidate_prime, precision);\n\tXMP_Dec(term, precision);\n\n\tfor (unsigned i = 0; i < rounds; i++) {\n\t\t// if ((x**(p-1)) mod p) != 1, then p is not prime\n\t\tdigit result[MAX_UNIT_PRECISION];\n\n\t\tdigit small_prime[MAX_UNIT_PRECISION];\n\t\tXMP_Init(small_prime, primeTable[i], precision);\n\n\t\txmp_exponent_mod(result, small_prime, term, candidate_prime, precision);\n\n\t\tif (!XMP_Test_Eq_Int(result, 1, precision)) return(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * XMP_Rabin_Miller_Test -- Performs the Rabin Miller test for primality.                      *\n *                                                                                             *\n *    This test for primality is even more expensive the Fermat's Little Theorem. It doesn't   *\n *    prove that a number is prime, but it can prove that it is not prime.                     *\n *                                                                                             *\n * INPUT:   rng      -- Reference to to a random number generator.                             *\n *                                                                                             *\n *          candidate-- Pointer to the candidate MP number that is to be tested.               *\n *                                                                                             *\n *          rounds   -- The number of test rounds to perform.                                  *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime? A FALSE means that the number is  *\n *          not prime. A TRUE means that it might be.                                          *\n *                                                                                             *\n * WARNINGS:   This routine takes a long time. Use as few rounds as possible.                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Rabin_Miller_Test(Straw & rng, digit const * w, int rounds, int precision)\n{\n\tdigit wminus1[MAX_UNIT_PRECISION];\n\tXMP_Sub_Int(wminus1, w, 1, 0, precision);\n\n\tunsigned maxbitprecision = precision * sizeof(digit) * 8;\n\tunsigned a;\n\tfor (a = 0; a < maxbitprecision; a++) {\n\t\tif (XMP_Test_Bit(wminus1, a)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdigit m[MAX_UNIT_PRECISION];\n\tXMP_Move(m, wminus1, precision);\n\tXMP_Shift_Right_Bits(wminus1, a, precision);\n\n\tfor (int i = 0; i < rounds; i++) {\n\t\tdigit b[MAX_UNIT_PRECISION];\n\t\tdigit temp[MAX_UNIT_PRECISION];\n\t\tXMP_Init(temp, 2, precision);\n\t\tXMP_Randomize(b, rng, temp, wminus1, precision);\n\n\t\tdigit z[MAX_UNIT_PRECISION];\n\t\txmp_exponent_mod(z, b, m, w, precision);\n\n\t\tif (XMP_Test_Eq_Int(z, 1, precision) || XMP_Compare(z, wminus1, precision) == 0) {\n\t\t\tcontinue;   // passes this round\n\t\t}\n\n\t\tint j;\n\t\tfor (j = 1; j < (int)a; j++) {\n\t\t\tdigit t2[MAX_UNIT_PRECISION];\n\t\t\txmp_exponent_mod(t2, z, temp, w, precision);\n\n\t\t\tif (XMP_Compare(t2, wminus1, precision) == 0) {\n\t\t\t\tbreak;  // passed this round\n\t\t\t}\n\t\t\tif (XMP_Test_Eq_Int(z, 1, precision)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (j == a) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n\n/***********************************************************************************************\n * XMP_Randomize -- Generate a random MP number.                                               *\n *                                                                                             *\n *    This routine will generate a random MP number with the number of bits precision          *\n *    specified. This is the starting point for generating large random prime numbers. It is   *\n *    very important that the random number generated is truly random.                         *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer that will hold the MP number.                    *\n *                                                                                             *\n *          rng      -- Reference to a random number generator.                                *\n *                                                                                             *\n *          total_bits-- The number of bits precision that the MP number must have.            *\n *                                                                                             *\n *          precision-- The precision of the MP number to be generated (maximum)               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Randomize(digit * result, Straw & rng, int total_bits, int precision)\n{\n\tassert(XMP_Bits_To_Digits(total_bits) <= MAX_UNIT_PRECISION);\n\n\ttotal_bits = min(total_bits, precision * 32);\n\n\tunsigned nbytes = total_bits/8 + 1;\n\n\tXMP_Init(result, 0, precision);\n\trng.Get(result, nbytes);\n\n\t((unsigned char *)result)[nbytes-1] &= (unsigned char)(~((~0) << (total_bits % 8)));\n}\n\n\n/***********************************************************************************************\n * XMP_Randomize -- Generate a random MP number between the boundaries specified.              *\n *                                                                                             *\n *    This routine will generate a random MP number but it will be bounded by the minimum      *\n *    and maximum MP numbers specified.                                                        *\n *                                                                                             *\n * INPUT:   result      -- Pointer to the MP buffer that will hold the result.                 *\n *                                                                                             *\n *          rng         -- Reference to a random number generator to use.                      *\n *                                                                                             *\n *          minval      -- Minimum value allowed.                                              *\n *                                                                                             *\n *          maxval      -- Maximum value allowed.                                              *\n *                                                                                             *\n *          precision   -- The precision of the MP numbers involved.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid XMP_Randomize(digit * result, Straw & rng, digit const * minval, digit const * maxval, int precision)\n{\n\tdigit range[MAX_UNIT_PRECISION];\n\tXMP_Sub(range, maxval, minval, 0, precision);\n\tunsigned int bit_count = XMP_Count_Bits(range, precision);\n\tdo\t{\n\t\tXMP_Randomize(result, rng, bit_count, precision);\n\t} while (XMP_Compare(result, range, precision) > 0);\n\n\tXMP_Add(result, result, minval, 0, precision);\n}\n\n\n/***********************************************************************************************\n * XMP_Is_Prime -- Determine if the specified MP number is prime.                              *\n *                                                                                             *\n *    This routine will perform some checks to try and determine if the specified MP number    *\n *    is a prime number. The result of this test is not 100% conclusive, but it is pretty      *\n *    darn close.                                                                              *\n *                                                                                             *\n * INPUT:   prime    -- Pointer to a candidate number to test for primality.                   *\n *                                                                                             *\n *          precision-- The precision of the MP number specified.                              *\n *                                                                                             *\n * OUTPUT:  bool; Was the number not proven to be not prime? If FALSE, then the number is      *\n *          not prime. If TRUE, then it might be.                                              *\n *                                                                                             *\n * WARNINGS:   This can take a very very very very very long time. Especially for the larger   *\n *             numbers.                                                                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool XMP_Is_Prime(digit const * prime, int precision)\n{\n\t/*\n\t**\tEven numbers are ALWAYS not prime.\n\t*/\n\tif (!(*prime & 0x01)) return(false);\n\n\t/*\n\t**\tCompare the prime number against the exhaustive list of prime\n\t**\tnumbers below 14 bits in size. If it finds a match, then\n\t**\tthe number is a known prime.\n\t*/\n\tif (XMP_Is_Small_Prime(prime, precision)) return(true);\n\n\t/*\n\t**\tPerform the small divisors test. This is not exhaustive, but\n\t**\twill weed out a large percentage of non-prime numbers.\n\t*/\n\tif (!XMP_Small_Divisors_Test(prime, precision)) return(false);\n\n\t/*\n\t**\tPerform Fermat's Little Theorum on the candidate prime. Run\n\t**\tthe theorum for several rounds to ensure a high degree of\n\t**\tconfidence.\n\t*/\n\tif (!XMP_Fermat_Test(prime, 2, precision)) return(false);\n\n\t/*\n\t**\tIf all of the above tests have not confirmed primality nor\n\t**\tconfirmed non-primality, presume that the number must be prime.\n\t*/\n\treturn(true);\n}\n\n\n/*\n**\tComplete list of all prime numbers that are less than 32719 (inclusive).\n*/\nunsigned short primeTable[3511] = {\n\t0x0002,0x0003,0x0005,0x0007,0x000B,0x000D,0x0011,0x0013,0x0017,0x001D,0x001F,0x0025,0x0029,0x002B,0x002F,0x0035,\n\t0x003B,0x003D,0x0043,0x0047,0x0049,0x004F,0x0053,0x0059,0x0061,0x0065,0x0067,0x006B,0x006D,0x0071,0x007F,0x0083,\n\t0x0089,0x008B,0x0095,0x0097,0x009D,0x00A3,0x00A7,0x00AD,0x00B3,0x00B5,0x00BF,0x00C1,0x00C5,0x00C7,0x00D3,0x00DF,\n\t0x00E3,0x00E5,0x00E9,0x00EF,0x00F1,0x00FB,0x0101,0x0107,0x010D,0x010F,0x0115,0x0119,0x011B,0x0125,0x0133,0x0137,\n\t0x0139,0x013D,0x014B,0x0151,0x015B,0x015D,0x0161,0x0167,0x016F,0x0175,0x017B,0x017F,0x0185,0x018D,0x0191,0x0199,\n\t0x01A3,0x01A5,0x01AF,0x01B1,0x01B7,0x01BB,0x01C1,0x01C9,0x01CD,0x01CF,0x01D3,0x01DF,0x01E7,0x01EB,0x01F3,0x01F7,\n\t0x01FD,0x0209,0x020B,0x021D,0x0223,0x022D,0x0233,0x0239,0x023B,0x0241,0x024B,0x0251,0x0257,0x0259,0x025F,0x0265,\n\t0x0269,0x026B,0x0277,0x0281,0x0283,0x0287,0x028D,0x0293,0x0295,0x02A1,0x02A5,0x02AB,0x02B3,0x02BD,0x02C5,0x02CF,\n\t0x02D7,0x02DD,0x02E3,0x02E7,0x02EF,0x02F5,0x02F9,0x0301,0x0305,0x0313,0x031D,0x0329,0x032B,0x0335,0x0337,0x033B,\n\t0x033D,0x0347,0x0355,0x0359,0x035B,0x035F,0x036D,0x0371,0x0373,0x0377,0x038B,0x038F,0x0397,0x03A1,0x03A9,0x03AD,\n\t0x03B3,0x03B9,0x03C7,0x03CB,0x03D1,0x03D7,0x03DF,0x03E5,0x03F1,0x03F5,0x03FB,0x03FD,0x0407,0x0409,0x040F,0x0419,\n\t0x041B,0x0425,0x0427,0x042D,0x043F,0x0443,0x0445,0x0449,0x044F,0x0455,0x045D,0x0463,0x0469,0x047F,0x0481,0x048B,\n\t0x0493,0x049D,0x04A3,0x04A9,0x04B1,0x04BD,0x04C1,0x04C7,0x04CD,0x04CF,0x04D5,0x04E1,0x04EB,0x04FD,0x04FF,0x0503,\n\t0x0509,0x050B,0x0511,0x0515,0x0517,0x051B,0x0527,0x0529,0x052F,0x0551,0x0557,0x055D,0x0565,0x0577,0x0581,0x058F,\n\t0x0593,0x0595,0x0599,0x059F,0x05A7,0x05AB,0x05AD,0x05B3,0x05BF,0x05C9,0x05CB,0x05CF,0x05D1,0x05D5,0x05DB,0x05E7,\n\t0x05F3,0x05FB,0x0607,0x060D,0x0611,0x0617,0x061F,0x0623,0x062B,0x062F,0x063D,0x0641,0x0647,0x0649,0x064D,0x0653,\n\t0x0655,0x065B,0x0665,0x0679,0x067F,0x0683,0x0685,0x069D,0x06A1,0x06A3,0x06AD,0x06B9,0x06BB,0x06C5,0x06CD,0x06D3,\n\t0x06D9,0x06DF,0x06F1,0x06F7,0x06FB,0x06FD,0x0709,0x0713,0x071F,0x0727,0x0737,0x0745,0x074B,0x074F,0x0751,0x0755,\n\t0x0757,0x0761,0x076D,0x0773,0x0779,0x078B,0x078D,0x079D,0x079F,0x07B5,0x07BB,0x07C3,0x07C9,0x07CD,0x07CF,0x07D3,\n\t0x07DB,0x07E1,0x07EB,0x07ED,0x07F7,0x0805,0x080F,0x0815,0x0821,0x0823,0x0827,0x0829,0x0833,0x083F,0x0841,0x0851,\n\t0x0853,0x0859,0x085D,0x085F,0x0869,0x0871,0x0883,0x089B,0x089F,0x08A5,0x08AD,0x08BD,0x08BF,0x08C3,0x08CB,0x08DB,\n\t0x08DD,0x08E1,0x08E9,0x08EF,0x08F5,0x08F9,0x0905,0x0907,0x091D,0x0923,0x0925,0x092B,0x092F,0x0935,0x0943,0x0949,\n\t0x094D,0x094F,0x0955,0x0959,0x095F,0x096B,0x0971,0x0977,0x0985,0x0989,0x098F,0x099B,0x09A3,0x09A9,0x09AD,0x09C7,\n\t0x09D9,0x09E3,0x09EB,0x09EF,0x09F5,0x09F7,0x09FD,0x0A13,0x0A1F,0x0A21,0x0A31,0x0A39,0x0A3D,0x0A49,0x0A57,0x0A61,\n\t0x0A63,0x0A67,0x0A6F,0x0A75,0x0A7B,0x0A7F,0x0A81,0x0A85,0x0A8B,0x0A93,0x0A97,0x0A99,0x0A9F,0x0AA9,0x0AAB,0x0AB5,\n\t0x0ABD,0x0AC1,0x0ACF,0x0AD9,0x0AE5,0x0AE7,0x0AED,0x0AF1,0x0AF3,0x0B03,0x0B11,0x0B15,0x0B1B,0x0B23,0x0B29,0x0B2D,\n\t0x0B3F,0x0B47,0x0B51,0x0B57,0x0B5D,0x0B65,0x0B6F,0x0B7B,0x0B89,0x0B8D,0x0B93,0x0B99,0x0B9B,0x0BB7,0x0BB9,0x0BC3,\n\t0x0BCB,0x0BCF,0x0BDD,0x0BE1,0x0BE9,0x0BF5,0x0BFB,0x0C07,0x0C0B,0x0C11,0x0C25,0x0C2F,0x0C31,0x0C41,0x0C5B,0x0C5F,\n\t0x0C61,0x0C6D,0x0C73,0x0C77,0x0C83,0x0C89,0x0C91,0x0C95,0x0C9D,0x0CB3,0x0CB5,0x0CB9,0x0CBB,0x0CC7,0x0CE3,0x0CE5,\n\t0x0CEB,0x0CF1,0x0CF7,0x0CFB,0x0D01,0x0D03,0x0D0F,0x0D13,0x0D1F,0x0D21,0x0D2B,0x0D2D,0x0D3D,0x0D3F,0x0D4F,0x0D55,\n\t0x0D69,0x0D79,0x0D81,0x0D85,0x0D87,0x0D8B,0x0D8D,0x0DA3,0x0DAB,0x0DB7,0x0DBD,0x0DC7,0x0DC9,0x0DCD,0x0DD3,0x0DD5,\n\t0x0DDB,0x0DE5,0x0DE7,0x0DF3,0x0DFD,0x0DFF,0x0E09,0x0E17,0x0E1D,0x0E21,0x0E27,0x0E2F,0x0E35,0x0E3B,0x0E4B,0x0E57,\n\t0x0E59,0x0E5D,0x0E6B,0x0E71,0x0E75,0x0E7D,0x0E87,0x0E8F,0x0E95,0x0E9B,0x0EB1,0x0EB7,0x0EB9,0x0EC3,0x0ED1,0x0ED5,\n\t0x0EDB,0x0EED,0x0EEF,0x0EF9,0x0F07,0x0F0B,0x0F0D,0x0F17,0x0F25,0x0F29,0x0F31,0x0F43,0x0F47,0x0F4D,0x0F4F,0x0F53,\n\t0x0F59,0x0F5B,0x0F67,0x0F6B,0x0F7F,0x0F95,0x0FA1,0x0FA3,0x0FA7,0x0FAD,0x0FB3,0x0FB5,0x0FBB,0x0FD1,0x0FD3,0x0FD9,\n\t0x0FE9,0x0FEF,0x0FFB,0x0FFD,0x1003,0x100F,0x101F,0x1021,0x1025,0x102B,0x1039,0x103D,0x103F,0x1051,0x1069,0x1073,\n\t0x1079,0x107B,0x1085,0x1087,0x1091,0x1093,0x109D,0x10A3,0x10A5,0x10AF,0x10B1,0x10BB,0x10C1,0x10C9,0x10E7,0x10F1,\n\t0x10F3,0x10FD,0x1105,0x110B,0x1115,0x1127,0x112D,0x1139,0x1145,0x1147,0x1159,0x115F,0x1163,0x1169,0x116F,0x1181,\n\t0x1183,0x118D,0x119B,0x11A1,0x11A5,0x11A7,0x11AB,0x11C3,0x11C5,0x11D1,0x11D7,0x11E7,0x11EF,0x11F5,0x11FB,0x120D,\n\t0x121D,0x121F,0x1223,0x1229,0x122B,0x1231,0x1237,0x1241,0x1247,0x1253,0x125F,0x1271,0x1273,0x1279,0x127D,0x128F,\n\t0x1297,0x12AF,0x12B3,0x12B5,0x12B9,0x12BF,0x12C1,0x12CD,0x12D1,0x12DF,0x12FD,0x1307,0x130D,0x1319,0x1327,0x132D,\n\t0x1337,0x1343,0x1345,0x1349,0x134F,0x1357,0x135D,0x1367,0x1369,0x136D,0x137B,0x1381,0x1387,0x138B,0x1391,0x1393,\n\t0x139D,0x139F,0x13AF,0x13BB,0x13C3,0x13D5,0x13D9,0x13DF,0x13EB,0x13ED,0x13F3,0x13F9,0x13FF,0x141B,0x1421,0x142F,\n\t0x1433,0x143B,0x1445,0x144D,0x1459,0x146B,0x146F,0x1471,0x1475,0x148D,0x1499,0x149F,0x14A1,0x14B1,0x14B7,0x14BD,\n\t0x14CB,0x14D5,0x14E3,0x14E7,0x1505,0x150B,0x1511,0x1517,0x151F,0x1525,0x1529,0x152B,0x1537,0x153D,0x1541,0x1543,\n\t0x1549,0x155F,0x1565,0x1567,0x156B,0x157D,0x157F,0x1583,0x158F,0x1591,0x1597,0x159B,0x15B5,0x15BB,0x15C1,0x15C5,\n\t0x15CD,0x15D7,0x15F7,0x1607,0x1609,0x160F,0x1613,0x1615,0x1619,0x161B,0x1625,0x1633,0x1639,0x163D,0x1645,0x164F,\n\t0x1655,0x1669,0x166D,0x166F,0x1675,0x1693,0x1697,0x169F,0x16A9,0x16AF,0x16B5,0x16BD,0x16C3,0x16CF,0x16D3,0x16D9,\n\t0x16DB,0x16E1,0x16E5,0x16EB,0x16ED,0x16F7,0x16F9,0x1709,0x170F,0x1723,0x1727,0x1733,0x1741,0x175D,0x1763,0x1777,\n\t0x177B,0x178D,0x1795,0x179B,0x179F,0x17A5,0x17B3,0x17B9,0x17BF,0x17C9,0x17CB,0x17D5,0x17E1,0x17E9,0x17F3,0x17F5,\n\t0x17FF,0x1807,0x1813,0x181D,0x1835,0x1837,0x183B,0x1843,0x1849,0x184D,0x1855,0x1867,0x1871,0x1877,0x187D,0x187F,\n\t0x1885,0x188F,0x189B,0x189D,0x18A7,0x18AD,0x18B3,0x18B9,0x18C1,0x18C7,0x18D1,0x18D7,0x18D9,0x18DF,0x18E5,0x18EB,\n\t0x18F5,0x18FD,0x1915,0x191B,0x1931,0x1933,0x1945,0x1949,0x1951,0x195B,0x1979,0x1981,0x1993,0x1997,0x1999,0x19A3,\n\t0x19A9,0x19AB,0x19B1,0x19B5,0x19C7,0x19CF,0x19DB,0x19ED,0x19FD,0x1A03,0x1A05,0x1A11,0x1A17,0x1A21,0x1A23,0x1A2D,\n\t0x1A2F,0x1A35,0x1A3F,0x1A4D,0x1A51,0x1A69,0x1A6B,0x1A7B,0x1A7D,0x1A87,0x1A89,0x1A93,0x1AA7,0x1AAB,0x1AAD,0x1AB1,\n\t0x1AB9,0x1AC9,0x1ACF,0x1AD5,0x1AD7,0x1AE3,0x1AF3,0x1AFB,0x1AFF,0x1B05,0x1B23,0x1B25,0x1B2F,0x1B31,0x1B37,0x1B3B,\n\t0x1B41,0x1B47,0x1B4F,0x1B55,0x1B59,0x1B65,0x1B6B,0x1B73,0x1B7F,0x1B83,0x1B91,0x1B9D,0x1BA7,0x1BBF,0x1BC5,0x1BD1,\n\t0x1BD7,0x1BD9,0x1BEF,0x1BF7,0x1C09,0x1C13,0x1C19,0x1C27,0x1C2B,0x1C2D,0x1C33,0x1C3D,0x1C45,0x1C4B,0x1C4F,0x1C55,\n\t0x1C73,0x1C81,0x1C8B,0x1C8D,0x1C99,0x1CA3,0x1CA5,0x1CB5,0x1CB7,0x1CC9,0x1CE1,0x1CF3,0x1CF9,0x1D09,0x1D1B,0x1D21,\n\t0x1D23,0x1D35,0x1D39,0x1D3F,0x1D41,0x1D4B,0x1D53,0x1D5D,0x1D63,0x1D69,0x1D71,0x1D75,0x1D7B,0x1D7D,0x1D87,0x1D89,\n\t0x1D95,0x1D99,0x1D9F,0x1DA5,0x1DA7,0x1DB3,0x1DB7,0x1DC5,0x1DD7,0x1DDB,0x1DE1,0x1DF5,0x1DF9,0x1E01,0x1E07,0x1E0B,\n\t0x1E13,0x1E17,0x1E25,0x1E2B,0x1E2F,0x1E3D,0x1E49,0x1E4D,0x1E4F,0x1E6D,0x1E71,0x1E89,0x1E8F,0x1E95,0x1EA1,0x1EAD,\n\t0x1EBB,0x1EC1,0x1EC5,0x1EC7,0x1ECB,0x1EDD,0x1EE3,0x1EEF,0x1EF7,0x1EFD,0x1F01,0x1F0D,0x1F0F,0x1F1B,0x1F39,0x1F49,\n\t0x1F4B,0x1F51,0x1F67,0x1F75,0x1F7B,0x1F85,0x1F91,0x1F97,0x1F99,0x1F9D,0x1FA5,0x1FAF,0x1FB5,0x1FBB,0x1FD3,0x1FE1,\n\t0x1FE7,0x1FEB,0x1FF3,0x1FFF,0x2011,0x201B,0x201D,0x2027,0x2029,0x202D,0x2033,0x2047,0x204D,0x2051,0x205F,0x2063,\n\t0x2065,0x2069,0x2077,0x207D,0x2089,0x20A1,0x20AB,0x20B1,0x20B9,0x20C3,0x20C5,0x20E3,0x20E7,0x20ED,0x20EF,0x20FB,\n\t0x20FF,0x210D,0x2113,0x2135,0x2141,0x2149,0x214F,0x2159,0x215B,0x215F,0x2173,0x217D,0x2185,0x2195,0x2197,0x21A1,\n\t0x21AF,0x21B3,0x21B5,0x21C1,0x21C7,0x21D7,0x21DD,0x21E5,0x21E9,0x21F1,0x21F5,0x21FB,0x2203,0x2209,0x220F,0x221B,\n\t0x2221,0x2225,0x222B,0x2231,0x2239,0x224B,0x224F,0x2263,0x2267,0x2273,0x2275,0x227F,0x2285,0x2287,0x2291,0x229D,\n\t0x229F,0x22A3,0x22B7,0x22BD,0x22DB,0x22E1,0x22E5,0x22ED,0x22F7,0x2303,0x2309,0x230B,0x2327,0x2329,0x232F,0x2333,\n\t0x2335,0x2345,0x2351,0x2353,0x2359,0x2363,0x236B,0x2383,0x238F,0x2395,0x23A7,0x23AD,0x23B1,0x23BF,0x23C5,0x23C9,\n\t0x23D5,0x23DD,0x23E3,0x23EF,0x23F3,0x23F9,0x2405,0x240B,0x2417,0x2419,0x2429,0x243D,0x2441,0x2443,0x244D,0x245F,\n\t0x2467,0x246B,0x2479,0x247D,0x247F,0x2485,0x249B,0x24A1,0x24AF,0x24B5,0x24BB,0x24C5,0x24CB,0x24CD,0x24D7,0x24D9,\n\t0x24DD,0x24DF,0x24F5,0x24F7,0x24FB,0x2501,0x2507,0x2513,0x2519,0x2527,0x2531,0x253D,0x2543,0x254B,0x254F,0x2573,\n\t0x2581,0x258D,0x2593,0x2597,0x259D,0x259F,0x25AB,0x25B1,0x25BD,0x25CD,0x25CF,0x25D9,0x25E1,0x25F7,0x25F9,0x2605,\n\t0x260B,0x260F,0x2615,0x2627,0x2629,0x2635,0x263B,0x263F,0x264B,0x2653,0x2659,0x2665,0x2669,0x266F,0x267B,0x2681,\n\t0x2683,0x268F,0x269B,0x269F,0x26AD,0x26B3,0x26C3,0x26C9,0x26CB,0x26D5,0x26DD,0x26EF,0x26F5,0x2717,0x2719,0x2735,\n\t0x2737,0x274D,0x2753,0x2755,0x275F,0x276B,0x276D,0x2773,0x2777,0x277F,0x2795,0x279B,0x279D,0x27A7,0x27AF,0x27B3,\n\t0x27B9,0x27C1,0x27C5,0x27D1,0x27E3,0x27EF,0x2803,0x2807,0x280D,0x2813,0x281B,0x281F,0x2821,0x2831,0x283D,0x283F,\n\t0x2849,0x2851,0x285B,0x285D,0x2861,0x2867,0x2875,0x2881,0x2897,0x289F,0x28BB,0x28BD,0x28C1,0x28D5,0x28D9,0x28DB,\n\t0x28DF,0x28ED,0x28F7,0x2903,0x2905,0x2911,0x2921,0x2923,0x293F,0x2947,0x295D,0x2965,0x2969,0x296F,0x2975,0x2983,\n\t0x2987,0x298F,0x299B,0x29A1,0x29A7,0x29AB,0x29BF,0x29C3,0x29D5,0x29D7,0x29E3,0x29E9,0x29ED,0x29F3,0x2A01,0x2A13,\n\t0x2A1D,0x2A25,0x2A2F,0x2A4F,0x2A55,0x2A5F,0x2A65,0x2A6B,0x2A6D,0x2A73,0x2A83,0x2A89,0x2A8B,0x2A97,0x2A9D,0x2AB9,\n\t0x2ABB,0x2AC5,0x2ACD,0x2ADD,0x2AE3,0x2AEB,0x2AF1,0x2AFB,0x2B13,0x2B27,0x2B31,0x2B33,0x2B3D,0x2B3F,0x2B4B,0x2B4F,\n\t0x2B55,0x2B69,0x2B6D,0x2B6F,0x2B7B,0x2B8D,0x2B97,0x2B99,0x2BA3,0x2BA5,0x2BA9,0x2BBD,0x2BCD,0x2BE7,0x2BEB,0x2BF3,\n\t0x2BF9,0x2BFD,0x2C09,0x2C0F,0x2C17,0x2C23,0x2C2F,0x2C35,0x2C39,0x2C41,0x2C57,0x2C59,0x2C69,0x2C77,0x2C81,0x2C87,\n\t0x2C93,0x2C9F,0x2CAD,0x2CB3,0x2CB7,0x2CCB,0x2CCF,0x2CDB,0x2CE1,0x2CE3,0x2CE9,0x2CEF,0x2CFF,0x2D07,0x2D1D,0x2D1F,\n\t0x2D3B,0x2D43,0x2D49,0x2D4D,0x2D61,0x2D65,0x2D71,0x2D89,0x2D9D,0x2DA1,0x2DA9,0x2DB3,0x2DB5,0x2DC5,0x2DC7,0x2DD3,\n\t0x2DDF,0x2E01,0x2E03,0x2E07,0x2E0D,0x2E19,0x2E1F,0x2E25,0x2E2D,0x2E33,0x2E37,0x2E39,0x2E3F,0x2E57,0x2E5B,0x2E6F,\n\t0x2E79,0x2E7F,0x2E85,0x2E93,0x2E97,0x2E9D,0x2EA3,0x2EA5,0x2EB1,0x2EB7,0x2EC1,0x2EC3,0x2ECD,0x2ED3,0x2EE7,0x2EEB,\n\t0x2F05,0x2F09,0x2F0B,0x2F11,0x2F27,0x2F29,0x2F41,0x2F45,0x2F4B,0x2F4D,0x2F51,0x2F57,0x2F6F,0x2F75,0x2F7D,0x2F81,\n\t0x2F83,0x2FA5,0x2FAB,0x2FB3,0x2FC3,0x2FCF,0x2FD1,0x2FDB,0x2FDD,0x2FE7,0x2FED,0x2FF5,0x2FF9,0x3001,0x300D,0x3023,\n\t0x3029,0x3037,0x303B,0x3055,0x3059,0x305B,0x3067,0x3071,0x3079,0x307D,0x3085,0x3091,0x3095,0x30A3,0x30A9,0x30B9,\n\t0x30BF,0x30C7,0x30CB,0x30D1,0x30D7,0x30DF,0x30E5,0x30EF,0x30FB,0x30FD,0x3103,0x3109,0x3119,0x3121,0x3127,0x312D,\n\t0x3139,0x3143,0x3145,0x314B,0x315D,0x3161,0x3167,0x316D,0x3173,0x317F,0x3191,0x3199,0x319F,0x31A9,0x31B1,0x31C3,\n\t0x31C7,0x31D5,0x31DB,0x31ED,0x31F7,0x31FF,0x3209,0x3215,0x3217,0x321D,0x3229,0x3235,0x3259,0x325D,0x3263,0x326B,\n\t0x326F,0x3275,0x3277,0x327B,0x328D,0x3299,0x329F,0x32A7,0x32AD,0x32B3,0x32B7,0x32C9,0x32CB,0x32CF,0x32D1,0x32E9,\n\t0x32ED,0x32F3,0x32F9,0x3307,0x3325,0x332B,0x332F,0x3335,0x3341,0x3347,0x335B,0x335F,0x3367,0x336B,0x3373,0x3379,\n\t0x337F,0x3383,0x33A1,0x33A3,0x33AD,0x33B9,0x33C1,0x33CB,0x33D3,0x33EB,0x33F1,0x33FD,0x3401,0x340F,0x3413,0x3419,\n\t0x341B,0x3437,0x3445,0x3455,0x3457,0x3463,0x3469,0x346D,0x3481,0x348B,0x3491,0x3497,0x349D,0x34A5,0x34AF,0x34BB,\n\t0x34C9,0x34D3,0x34E1,0x34F1,0x34FF,0x3509,0x3517,0x351D,0x352D,0x3533,0x353B,0x3541,0x3551,0x3565,0x356F,0x3571,\n\t0x3577,0x357B,0x357D,0x3581,0x358D,0x358F,0x3599,0x359B,0x35A1,0x35B7,0x35BD,0x35BF,0x35C3,0x35D5,0x35DD,0x35E7,\n\t0x35EF,0x3605,0x3607,0x3611,0x3623,0x3631,0x3635,0x3637,0x363B,0x364D,0x364F,0x3653,0x3659,0x3661,0x366B,0x366D,\n\t0x368B,0x368F,0x36AD,0x36AF,0x36B9,0x36BB,0x36CD,0x36D1,0x36E3,0x36E9,0x36F7,0x3701,0x3703,0x3707,0x371B,0x373F,\n\t0x3745,0x3749,0x374F,0x375D,0x3761,0x3775,0x377F,0x378D,0x37A3,0x37A9,0x37AB,0x37C9,0x37D5,0x37DF,0x37F1,0x37F3,\n\t0x37F7,0x3805,0x380B,0x3821,0x3833,0x3835,0x3841,0x3847,0x384B,0x3853,0x3857,0x385F,0x3865,0x386F,0x3871,0x387D,\n\t0x388F,0x3899,0x38A7,0x38B7,0x38C5,0x38C9,0x38CF,0x38D5,0x38D7,0x38DD,0x38E1,0x38E3,0x38FF,0x3901,0x391D,0x3923,\n\t0x3925,0x3929,0x392F,0x393D,0x3941,0x394D,0x395B,0x396B,0x3979,0x397D,0x3983,0x398B,0x3991,0x3995,0x399B,0x39A1,\n\t0x39A7,0x39AF,0x39B3,0x39BB,0x39BF,0x39CD,0x39DD,0x39E5,0x39EB,0x39EF,0x39FB,0x3A03,0x3A13,0x3A15,0x3A1F,0x3A27,\n\t0x3A2B,0x3A31,0x3A4B,0x3A51,0x3A5B,0x3A63,0x3A67,0x3A6D,0x3A79,0x3A87,0x3AA5,0x3AA9,0x3AB7,0x3ACD,0x3AD5,0x3AE1,\n\t0x3AE5,0x3AEB,0x3AF3,0x3AFD,0x3B03,0x3B11,0x3B1B,0x3B21,0x3B23,0x3B2D,0x3B39,0x3B45,0x3B53,0x3B59,0x3B5F,0x3B71,\n\t0x3B7B,0x3B81,0x3B89,0x3B9B,0x3B9F,0x3BA5,0x3BA7,0x3BAD,0x3BB7,0x3BB9,0x3BC3,0x3BCB,0x3BD1,0x3BD7,0x3BE1,0x3BE3,\n\t0x3BF5,0x3BFF,0x3C01,0x3C0D,0x3C11,0x3C17,0x3C1F,0x3C29,0x3C35,0x3C43,0x3C4F,0x3C53,0x3C5B,0x3C65,0x3C6B,0x3C71,\n\t0x3C85,0x3C89,0x3C97,0x3CA7,0x3CB5,0x3CBF,0x3CC7,0x3CD1,0x3CDD,0x3CDF,0x3CF1,0x3CF7,0x3D03,0x3D0D,0x3D19,0x3D1B,\n\t0x3D1F,0x3D21,0x3D2D,0x3D33,0x3D37,0x3D3F,0x3D43,0x3D6F,0x3D73,0x3D75,0x3D79,0x3D7B,0x3D85,0x3D91,0x3D97,0x3D9D,\n\t0x3DAB,0x3DAF,0x3DB5,0x3DBB,0x3DC1,0x3DC9,0x3DCF,0x3DF3,0x3E05,0x3E09,0x3E0F,0x3E11,0x3E1D,0x3E23,0x3E29,0x3E2F,\n\t0x3E33,0x3E41,0x3E57,0x3E63,0x3E65,0x3E77,0x3E81,0x3E87,0x3EA1,0x3EB9,0x3EBD,0x3EBF,0x3EC3,0x3EC5,0x3EC9,0x3ED7,\n\t0x3EDB,0x3EE1,0x3EE7,0x3EEF,0x3EFF,0x3F0B,0x3F0D,0x3F37,0x3F3B,0x3F3D,0x3F41,0x3F59,0x3F5F,0x3F65,0x3F67,0x3F79,\n\t0x3F7D,0x3F8B,0x3F91,0x3FAD,0x3FBF,0x3FCD,0x3FD3,0x3FDD,0x3FE9,0x3FEB,0x3FF1,0x3FFD,0x401B,0x4021,0x4025,0x402B,\n\t0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9,0x40B1,0x40B7,0x40BD,0x40DB,\n\t0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B,0x413F,0x4159,0x4165,0x416B,\n\t0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9,0x4205,0x4207,0x4219,0x421F,\n\t0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285,0x4289,0x4291,0x4297,0x429D,\n\t0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327,0x4333,0x4337,0x4339,0x434F,\n\t0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF,0x43E1,0x43E7,0x43EB,0x43ED,\n\t0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451,0x4453,0x4459,0x4465,0x446F,\n\t0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9,0x44FB,0x4505,0x4511,0x4513,\n\t0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3,0x45AD,0x45AF,0x45BB,0x45C7,\n\t0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633,0x4639,0x463D,0x4643,0x4645,\n\t0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9,0x46CF,0x46D3,0x46D5,0x46DF,\n\t0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D,0x4751,0x475D,0x476F,0x4771,\n\t0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1,0x47ED,0x47FB,0x4801,0x4807,\n\t0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D,0x4879,0x4897,0x489B,0x48A1,\n\t0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D,0x4945,0x4955,0x4963,0x4969,\n\t0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F,0x4A1D,0x4A23,0x4A39,0x4A41,\n\t0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5,0x4AD5,0x4ADB,0x4AED,0x4AEF,\n\t0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65,0x4B6D,0x4B77,0x4B85,0x4BAD,\n\t0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1,0x4BF7,0x4C01,0x4C07,0x4C0D,\n\t0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73,0x4C79,0x4C7F,0x4C8D,0x4C93,\n\t0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29,0x4D2F,0x4D33,0x4D41,0x4D51,\n\t0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF,0x4DD7,0x4DE1,0x4DED,0x4DF9,\n\t0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53,0x4E5F,0x4E67,0x4E79,0x4E85,\n\t0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7,0x4EE9,0x4EFB,0x4F07,0x4F09,\n\t0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85,0x4F87,0x4F91,0x4FA5,0x4FA9,\n\t0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029,0x5035,0x503F,0x5045,0x5047,\n\t0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED,0x50EF,0x50FB,0x5107,0x510B,\n\t0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F,0x5197,0x51A1,0x51A3,0x51A7,\n\t0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219,0x521B,0x521F,0x5227,0x5243,\n\t0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1,0x52BB,0x52C3,0x52C7,0x52C9,\n\t0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D,0x5363,0x5381,0x5383,0x5387,\n\t0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB,0x53FF,0x540D,0x5411,0x5413,\n\t0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D,0x5471,0x548F,0x5491,0x549D,\n\t0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B,0x5527,0x552B,0x5539,0x553D,\n\t0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7,0x55C9,0x55D9,0x55E7,0x55ED,\n\t0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B,0x564D,0x565D,0x565F,0x566B,\n\t0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3,0x56FF,0x5701,0x5705,0x5707,\n\t0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789,0x57A1,0x57A9,0x57AF,0x57B5,\n\t0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D,0x5855,0x585B,0x585D,0x586D,\n\t0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7,0x58D3,0x58D5,0x58DF,0x58F1,\n\t0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975,0x597B,0x5989,0x5999,0x599F,\n\t0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01,0x5A0D,0x5A11,0x5A13,0x5A17,\n\t0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D,0x5AA1,0x5AA3,0x5AA9,0x5ABB,\n\t0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D,0x5B49,0x5B4B,0x5B67,0x5B79,\n\t0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09,0x5C0B,0x5C0F,0x5C1D,0x5C29,\n\t0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87,0x5C89,0x5CA7,0x5CBD,0x5CBF,\n\t0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19,0x5D31,0x5D3D,0x5D41,0x5D47,\n\t0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9,0x5DC1,0x5DC7,0x5DD3,0x5DD7,\n\t0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D,0x5E31,0x5E39,0x5E45,0x5E49,\n\t0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9,0x5EFD,0x5F09,0x5F11,0x5F27,\n\t0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99,0x5FA1,0x5FB3,0x5FBD,0x5FC5,\n\t0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065,0x606B,0x6073,0x6079,0x6085,\n\t0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113,0x611B,0x612D,0x6139,0x614B,\n\t0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7,0x61C9,0x61CD,0x61E1,0x61F1,\n\t0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F,0x6265,0x6283,0x628D,0x6295,\n\t0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305,0x630D,0x6317,0x631D,0x632F,\n\t0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1,0x63C5,0x63D9,0x63E9,0x63EB,\n\t0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449,0x644F,0x645D,0x6467,0x6475,\n\t0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7,0x64F9,0x650B,0x6511,0x6521,\n\t0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F,0x6593,0x65A1,0x65A5,0x65AD,\n\t0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B,0x6641,0x6647,0x664D,0x665B,\n\t0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD,0x66D1,0x66E3,0x66EB,0x66F5,\n\t0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F,0x6779,0x6781,0x6785,0x6791,\n\t0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839,0x683B,0x683F,0x6845,0x684B,\n\t0x684D,0x6857,0x6859,0x685D,0x6863,0x6869,0x686B,0x6871,0x6887,0x6899,0x689F,0x68B1,0x68BD,0x68C5,0x68D1,0x68D7,\n\t0x68E1,0x68ED,0x68EF,0x68FF,0x6901,0x690B,0x690D,0x6917,0x6929,0x692F,0x6943,0x6947,0x6949,0x694F,0x6965,0x696B,\n\t0x6971,0x6983,0x6989,0x6997,0x69A3,0x69B3,0x69B5,0x69BB,0x69C1,0x69C5,0x69D3,0x69DF,0x69E3,0x69E5,0x69F7,0x6A07,\n\t0x6A2B,0x6A37,0x6A3D,0x6A4B,0x6A67,0x6A69,0x6A75,0x6A7B,0x6A87,0x6A8D,0x6A91,0x6A93,0x6AA3,0x6AC1,0x6AC9,0x6AE1,\n\t0x6AE7,0x6B05,0x6B0F,0x6B11,0x6B23,0x6B27,0x6B2D,0x6B39,0x6B41,0x6B57,0x6B59,0x6B5F,0x6B75,0x6B87,0x6B89,0x6B93,\n\t0x6B95,0x6B9F,0x6BBD,0x6BBF,0x6BDB,0x6BE1,0x6BEF,0x6BFF,0x6C05,0x6C19,0x6C29,0x6C2B,0x6C31,0x6C35,0x6C55,0x6C59,\n\t0x6C5B,0x6C5F,0x6C65,0x6C67,0x6C73,0x6C77,0x6C7D,0x6C83,0x6C8F,0x6C91,0x6C97,0x6C9B,0x6CA1,0x6CA9,0x6CAF,0x6CB3,\n\t0x6CC7,0x6CCB,0x6CEB,0x6CF5,0x6CFD,0x6D0D,0x6D0F,0x6D25,0x6D27,0x6D2B,0x6D31,0x6D39,0x6D3F,0x6D4F,0x6D5D,0x6D61,\n\t0x6D73,0x6D7B,0x6D7F,0x6D93,0x6D99,0x6DA5,0x6DB1,0x6DB7,0x6DC1,0x6DC3,0x6DCD,0x6DCF,0x6DDB,0x6DF7,0x6E03,0x6E15,\n\t0x6E17,0x6E29,0x6E33,0x6E3B,0x6E45,0x6E75,0x6E77,0x6E7B,0x6E81,0x6E89,0x6E93,0x6E95,0x6E9F,0x6EBD,0x6EBF,0x6EE3,\n\t0x6EE9,0x6EF3,0x6EF9,0x6EFB,0x6F0D,0x6F11,0x6F17,0x6F1F,0x6F2F,0x6F3D,0x6F4D,0x6F53,0x6F61,0x6F65,0x6F79,0x6F7D,\n\t0x6F83,0x6F85,0x6F8F,0x6F9B,0x6F9D,0x6FA3,0x6FAF,0x6FB5,0x6FBB,0x6FBF,0x6FCB,0x6FCD,0x6FD3,0x6FD7,0x6FE3,0x6FE9,\n\t0x6FF1,0x6FF5,0x6FF7,0x6FFD,0x700F,0x7019,0x701F,0x7027,0x7033,0x7039,0x704F,0x7051,0x7057,0x7063,0x7075,0x7079,\n\t0x7087,0x708D,0x7091,0x70A5,0x70AB,0x70BB,0x70C3,0x70C7,0x70CF,0x70E5,0x70ED,0x70F9,0x70FF,0x7105,0x7115,0x7121,\n\t0x7133,0x7151,0x7159,0x715D,0x715F,0x7163,0x7169,0x7183,0x7187,0x7195,0x71AD,0x71C3,0x71C9,0x71CB,0x71D1,0x71DB,\n\t0x71E1,0x71EF,0x71F5,0x71FB,0x7207,0x7211,0x7217,0x7219,0x7225,0x722F,0x723B,0x7243,0x7255,0x7267,0x7271,0x7277,\n\t0x727F,0x728F,0x7295,0x729B,0x72A3,0x72B3,0x72C7,0x72CB,0x72CD,0x72D7,0x72D9,0x72E3,0x72EF,0x72F5,0x72FD,0x7303,\n\t0x730D,0x7321,0x732B,0x733D,0x7357,0x735B,0x7361,0x737F,0x7381,0x7385,0x738D,0x7393,0x739F,0x73AB,0x73BD,0x73C1,\n\t0x73C9,0x73DF,0x73E5,0x73E7,0x73F3,0x7415,0x741B,0x742D,0x7439,0x743F,0x7441,0x745D,0x746B,0x747B,0x7489,0x748D,\n\t0x749B,0x74A7,0x74AB,0x74B1,0x74B7,0x74B9,0x74DD,0x74E1,0x74E7,0x74FB,0x7507,0x751F,0x7525,0x753B,0x753D,0x754D,\n\t0x755F,0x756B,0x7577,0x7589,0x758B,0x7591,0x7597,0x759D,0x75A1,0x75A7,0x75B5,0x75B9,0x75BB,0x75D1,0x75D9,0x75E5,\n\t0x75EB,0x75F5,0x75FB,0x7603,0x760F,0x7621,0x762D,0x7633,0x763D,0x763F,0x7655,0x7663,0x7669,0x766F,0x7673,0x7685,\n\t0x768B,0x769F,0x76B5,0x76B7,0x76C3,0x76DB,0x76DF,0x76F1,0x7703,0x7705,0x771B,0x771D,0x7721,0x772D,0x7735,0x7741,\n\t0x774B,0x7759,0x775D,0x775F,0x7771,0x7781,0x77A7,0x77AD,0x77B3,0x77B9,0x77C5,0x77CF,0x77D5,0x77E1,0x77E9,0x77EF,\n\t0x77F3,0x77F9,0x7807,0x7825,0x782B,0x7835,0x783D,0x7853,0x7859,0x7861,0x786D,0x7877,0x7879,0x7883,0x7885,0x788B,\n\t0x7895,0x7897,0x78A1,0x78AD,0x78BF,0x78D3,0x78D9,0x78DD,0x78E5,0x78FB,0x7901,0x7907,0x7925,0x792B,0x7939,0x793F,\n\t0x794B,0x7957,0x795D,0x7967,0x7969,0x7973,0x7991,0x7993,0x79A3,0x79AB,0x79AF,0x79B1,0x79B7,0x79C9,0x79CD,0x79CF,\n\t0x79D5,0x79D9,0x79F3,0x79F7,0x79FF,0x7A05,0x7A0F,0x7A11,0x7A15,0x7A1B,0x7A23,0x7A27,0x7A2D,0x7A4B,0x7A57,0x7A59,\n\t0x7A5F,0x7A65,0x7A69,0x7A7D,0x7A93,0x7A9B,0x7A9F,0x7AA1,0x7AA5,0x7AED,0x7AF5,0x7AF9,0x7B01,0x7B17,0x7B19,0x7B1D,\n\t0x7B2B,0x7B35,0x7B37,0x7B3B,0x7B4F,0x7B55,0x7B5F,0x7B71,0x7B77,0x7B8B,0x7B9B,0x7BA1,0x7BA9,0x7BAF,0x7BB3,0x7BC7,\n\t0x7BD3,0x7BE9,0x7BEB,0x7BEF,0x7BF1,0x7BFD,0x7C07,0x7C19,0x7C1B,0x7C31,0x7C37,0x7C49,0x7C67,0x7C69,0x7C73,0x7C81,\n\t0x7C8B,0x7C93,0x7CA3,0x7CD5,0x7CDB,0x7CE5,0x7CED,0x7CF7,0x7D03,0x7D09,0x7D1B,0x7D1D,0x7D33,0x7D39,0x7D3B,0x7D3F,\n\t0x7D45,0x7D4D,0x7D53,0x7D59,0x7D63,0x7D75,0x7D77,0x7D8D,0x7D8F,0x7D9F,0x7DAD,0x7DB7,0x7DBD,0x7DBF,0x7DCB,0x7DD5,\n\t0x7DE9,0x7DED,0x7DFB,0x7E01,0x7E05,0x7E29,0x7E2B,0x7E2F,0x7E35,0x7E41,0x7E43,0x7E47,0x7E55,0x7E61,0x7E67,0x7E6B,\n\t0x7E71,0x7E73,0x7E79,0x7E7D,0x7E91,0x7E9B,0x7E9D,0x7EA7,0x7EAD,0x7EB9,0x7EBB,0x7ED3,0x7EDF,0x7EEB,0x7EF1,0x7EF7,\n\t0x7EFB,0x7F13,0x7F15,0x7F19,0x7F31,0x7F33,0x7F39,0x7F3D,0x7F43,0x7F4B,0x7F5B,0x7F61,0x7F63,0x7F6D,0x7F79,0x7F87,\n\t0x7F8D,0x7FAF,0x7FB5,0x7FC3,0x7FC9,0x7FCD,0x7FCF\n};\n"
  },
  {
    "path": "REDALERT/MP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MP.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O                 ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MP.H                                                         *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MP_H\n#define MP_H\n\n//lint -e740 -e534 -e537 -e760\n\n//lint -d_LINT=1\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#include\t\"straw.h\"\n#include\t<stdlib.h>\n\nextern unsigned short primeTable[3511];\n\n\n#define\tdigit\tunsigned long\n#define\tsigneddigit\tsigned long\n#define\tLOG_UNITSIZE\t\t\t5\n#define\tUNITSIZE\t\t\t\t\t32\n#define\tUPPER_MOST_BIT\t\t\t0x80000000L\n#define\tSEMI_UPPER_MOST_BIT\t0x8000\n#define\tSEMI_MASK\t\t\t\t((unsigned short)~0)\n#define\tMAX_BIT_PRECISION\t\t2048\n#define\tMAX_UNIT_PRECISION\t(MAX_BIT_PRECISION/UNITSIZE)\n#ifndef ARRAY_SIZE\n#define ARRAY_SIZE(a)\t(sizeof(a)/sizeof(a[0]))\n#endif\n\n\nint XMP_Significance(const digit * r, int precision);\nvoid XMP_Inc(digit * r, int precision);\nvoid XMP_Dec(digit * r, int precision);\nvoid XMP_Neg(digit * r, int precision);\nvoid XMP_Abs(digit * r, int precision);\nvoid XMP_Shift_Right_Bits(digit * r1, int bits, int precision);\nvoid XMP_Shift_Left_Bits(digit * r1, int bits, int precision);\nbool XMP_Rotate_Left(digit * r1, bool carry, int precision);\nvoid XMP_Not(digit * digit_ptr, int precision);\nvoid XMP_Init(digit * r, digit value, int precision);\nunsigned XMP_Count_Bits(const digit * r, int precision);\nint XMP_Count_Bytes(const digit * r, int precision);\nvoid XMP_Move(digit * dest, digit const * source, int precision);\nint XMP_Compare(const digit * r1, const digit * r2, int precision);\nbool XMP_Add(digit * result, const digit * r1, const digit * r2, bool carry, int precision);\nbool XMP_Add_Int(digit * result, const digit * r1, digit r2, bool carry, int precision);\nbool XMP_Sub(digit * result, const digit * r1, const digit * r2, bool borrow, int precision);\nbool XMP_Sub_Int(digit * result, const digit * r1, unsigned short r2, bool borrow, int precision);\nint XMP_Unsigned_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nint XMP_Unsigned_Mult_Int(digit * prod, const digit * multiplicand, short multiplier, int precision);\nint XMP_Signed_Mult_Int(digit * prod, const digit * multiplicand, signed short multiplier, int precision);\nint XMP_Signed_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nunsigned short XMP_Unsigned_Div_Int(digit * quotient, digit const * dividend, unsigned short divisor, int precision);\nint XMP_Unsigned_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);\nvoid XMP_Signed_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);\nint XMP_Reciprocal(digit * quotient, const digit * divisor, int precision);\nvoid XMP_Decode_ASCII(char const * str, digit * mpn, int precision);\nvoid xmp_single_mul(unsigned short * prod, unsigned short * multiplicand, unsigned short multiplier, int precision);\nvoid XMP_Double_Mul(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nint xmp_stage_modulus(const digit * n_modulus, int precision);\nint XMP_Mod_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);\nvoid XMP_Mod_Mult_Clear(int precision);\nunsigned short mp_quo_digit(unsigned short * dividend);\nint xmp_exponent_mod(digit * expout, const digit * expin, const digit * exponent_ptr, const digit * modulus, int precision);\nbool XMP_Is_Small_Prime(const digit * candidate, int precision);\nbool XMP_Small_Divisors_Test(const digit * candidate, int precision);\nbool XMP_Fermat_Test(const digit * candidate_prime, unsigned rounds, int precision);\nvoid XMP_Inverse_A_Mod_B(digit * result, digit const * number, digit const * modulus, int precision);\nvoid XMP_Signed_Decode(digit * result, const unsigned char * from, int frombytes, int precision);\nvoid XMP_Unsigned_Decode(digit * result, const unsigned char * from, int frombytes, int precision);\nunsigned XMP_Encode(unsigned char * to, digit const * from, int precision);\nunsigned XMP_Encode(unsigned char * to, unsigned tobytes, digit const * from, int precision);\nvoid XMP_Randomize(digit * result, Straw & rng, int nbits, int precision);\nvoid XMP_Randomize(digit * result, Straw & rng, digit const * min, digit const * max, int precision);\nbool XMP_Is_Prime(digit const * prime, int precision);\nbool XMP_Rabin_Miller_Test(Straw & rng, digit const * w, int rounds, int precision);\nint XMP_DER_Length_Encode(unsigned long length, unsigned char * output);\nint XMP_DER_Encode(digit const * from, unsigned char * output, int precision);\nvoid XMP_DER_Decode(digit * result, unsigned char const * input, int precision);\n\n\n\ninline int XMP_Digits_To_Bits(int digits)\n{\n\treturn(digits << LOG_UNITSIZE);\n}\n\n\ninline int XMP_Bits_To_Digits(int bits)\n{\n\treturn ((bits + (UNITSIZE-1)) / UNITSIZE);\n}\n\n\ninline digit XMP_Bits_To_Mask(int bits)\n{\n\tif (!bits) return(0);\n\treturn(1 << ((bits-1) % UNITSIZE));\n}\n\n\ninline bool XMP_Is_Negative(const digit * r, int precision)\n{\n\treturn((signeddigit) *(r + (precision-1)) < 0);\n}\n\n\ninline bool XMP_Test_Eq_Int(digit const * r, int i, int p)\n{\n\treturn( (*r == i ) && XMP_Significance(r,p) <= 1 );\n}\n\n\ninline void XMP_Set_Bit(digit * r, unsigned bit)\n{\n\tr[bit >> LOG_UNITSIZE] |= ((digit)1 << (bit & (UNITSIZE-1)));\n}\n\ninline bool XMP_Test_Bit(const digit * r, unsigned bit)\n{\n\treturn (r[bit >> LOG_UNITSIZE] & ((digit)1 << (bit & (UNITSIZE-1))));\n}\n\n\n\n// Misc functions.\nvoid memrev(char * buffer, size_t length);\n\n#endif\n"
  },
  {
    "path": "REDALERT/MPGSET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/****************************************************************************\n*\n* FILE\n*     MpgSet.cpp\n*\n* DESCRIPTION\n*     Mpeg movie settings manager\n*\n* PROGRAMMER\n*     Denzil E. Long, Jr.\n*\n* DATE\n*     June 30, 1998\n*\n****************************************************************************/\n\n#include \"function.h\"\n\n#ifdef DVD\n#include \"mpgset.h\"\n\n#ifdef MCIMPEG\nbool EnumMCI(MCIDevice* desc, void* context);\n#endif\n\n/****************************************************************************\n*\n* NAME\n*     MPGSettings(DeviceName)\n*\n* DESCRIPTION\n*     Default constructor\n*\n* INPUTS\n*     DeviceName - Initial device to use for MPG playback (NULL = DXMedia)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMPGSettings::MPGSettings(const char* deviceName)\n\t: mDeviceName(NULL)\n\t{\n\tSetDeviceName(deviceName);\n\n\t#ifdef MCIMPEG\n\tint count = mMCI.GetDeviceCount();\n\n\tmMCIDevices = NULL;\n\tmCount = 0;\n\t\n\tif (count)\n\t\t{\n\t\tmMCIDevices = new MCIDevice[count];\n\t\t\n\t\tif (mMCIDevices)\n\t\t\t{\n\t\t\tmMCI.EnumerateDevices(EnumMCI, this);\n\t\t\t}\n\t\t}\n\t#endif\n\t}\n\n\nMPGSettings::MPGSettings(FileClass& file)\n\t: mDeviceName(NULL)\n\t{\n\tINIClass ini;\n\tchar buffer[256];\n\tchar* device = NULL;\n\n\t#ifdef MCIMPEG\n\tint count = mMCI.GetDeviceCount();\n\n\tmMCIDevices = NULL;\n\tmCount = 0;\n\t\n\t// Enumerate all the MCI devices that can play a movie\n\tif (count)\n\t\t{\n\t\tmMCIDevices = new MCIDevice[count];\n\n\t\tif (mMCIDevices)\n\t\t\t{\n\t\t\tmMCI.EnumerateDevices(EnumMCI, this);\n\t\t\t}\n\t\t}\n\n\t#endif\n\t\n\t// Retrieve the user specified device from the config file\n\tbuffer[0] = '\\0';\n\n\tif (ini.Load(file))\n\t\t{\n\t\tini.Get_String(\"MovieSettings\", \"Device\", \"Default\", buffer, sizeof(buffer));\n\t\t}\n\n\t// If there is a specification in the config and it isn't the default\n\tif ((strlen(buffer) != 0) && (stricmp(buffer, \"Default\") != 0))\n\t\t{\n\t\t#ifdef MCIMPEG\n\t\t// Search for selection\n\t\tfor (int i = 0; i < mCount; i++)\n\t\t\t{\n\t\t\tif (stricmp(buffer, mMCIDevices[i].name) == 0)\n\t\t\t\t{\n\t\t\t\tdevice = mMCIDevices[i].name;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\t\t}\n\n\tSetDeviceName(device);\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     ~MPGSettings\n*\n* DESCRIPTION\n*     Destructor\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nMPGSettings::~MPGSettings(void)\n\t{\n\tif (mDeviceName)\n\t\tfree(mDeviceName);\n\t\t\n\t#ifdef MCIMPEG\n\tif (mMCIDevices)\n\t\tdelete[] mMCIDevices;\n\t#endif\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     SetDeviceName(DeviceName)\n*\n* DESCRIPTION\n*     Change current device used for mpeg playback\n*\n* INPUTS\n*     DeviceName - Device name type (IE: mpegvideo)\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid MPGSettings::SetDeviceName(const char* deviceName)\n\t{\n\tif (mDeviceName)\n\t\tfree(mDeviceName);\n\n\tmDeviceName = NULL;\n\n\tif (deviceName)\n\t\tmDeviceName = strdup(deviceName);\n\t}\n\n\nbool MPGSettings::Save(FileClass& file)\n\t{\n\tINIClass ini;\n\n\tif (ini.Load(file))\n\t\t{\n\t\tconst char* device = GetDeviceName();\n\t\t\n\t\tif (device)\n\t\t\t{\n\t\t\tini.Put_String(\"MovieSettings\", \"Device\", device);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tini.Put_String(\"MovieSettings\", \"Device\", \"Default\");\n\t\t\t}\n\t\t\t\n\t\tini.Save(file);\n\t\treturn true;\n\t\t}\n\n\treturn false;\n\t}\n\n\n/****************************************************************************\n*\n* NAME\n*     Dialog()\n*\n* DESCRIPTION\n*     Mpeg playback settings dialog\n*\n* INPUTS\n*     NONE\n*\n* RESULT\n*     NONE\n*\n****************************************************************************/\n\nvoid MPGSettings::Dialog(void)\n\t{\n\t//\tDialog & button dimensions\n\tint d_dialog_w = 200 *RESFACTOR;\n\tint d_dialog_h = 100 *RESFACTOR;\n\tint d_dialog_x = (((320*RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = 70 * RESFACTOR;\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint d_txt6_h = 7 *RESFACTOR;\n\tint d_margin = 7 *RESFACTOR;\n\n\tint d_okay_w = 40 *RESFACTOR;\n\tint d_okay_h = 9 *RESFACTOR;\n\tint d_okay_x = d_dialog_x + d_margin + 20;\n\tint d_okay_y = ((d_dialog_y + d_dialog_h) - (d_okay_h + 20));\n\n\tint d_test_w = 40 *RESFACTOR;\n\tint d_test_h = 9 *RESFACTOR;\n\tint d_test_x = (d_dialog_cx - (d_test_w / 2));\n\tint d_test_y = ((d_dialog_y + d_dialog_h) - (d_test_h + 20));\n\n\tint d_cancel_w = 40 *RESFACTOR;\n\tint d_cancel_h = 9 *RESFACTOR;\n\tint d_cancel_x = ((d_dialog_x + d_dialog_w) - (d_cancel_w + d_margin + 20));\n\tint d_cancel_y = ((d_dialog_y + d_dialog_h) - (d_cancel_h + 20));\n\n\tint d_method_w = 165 * RESFACTOR;\n\tint d_method_h = 50 * RESFACTOR;\n\tint d_method_x = (d_dialog_cx - (d_method_w / 2));\n\tint d_method_y = (d_dialog_y + 40);\n\n\t//\tButton enumerations:\n\tenum\n\t\t{\n\t\tBUTTON_OKAY = 100,\n\t\tBUTTON_TEST,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_METHOD,\n\t\tNUM_OF_BUTTONS = 4,\n\t\t};\n\n\tint num_of_buttons = NUM_OF_BUTTONS;\n\t\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\ttypedef enum\n\t\t{\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map bord, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t\t} RedrawType;\n\n\t//\tDialog variables:\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\tRedrawType display;\t\t\t\t\t\t\t// true = re-draw everything\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\tint i;\n\tchar* origDevice = NULL;\n\n\t//\tButtons\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\tTextButtonClass okaybtn(BUTTON_OKAY, TXT_OK, TPF_BUTTON,\n\t\td_okay_x, d_okay_y, d_okay_w, d_okay_h);\n\n\tTextButtonClass testbtn(BUTTON_TEST, \"Test\", TPF_BUTTON,\n\t\td_test_x, d_test_y, d_test_w, d_test_h);\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\tListClass method(BUTTON_METHOD, d_method_x, d_method_y, d_method_w,\n\t\td_method_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\t\t\n\t//\tInitialize\n\tSet_Logic_Page(SeenBuff);\n\t\n\t//\tCreate the list\n\tcommands = &okaybtn;\n\ttestbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tmethod.Add_Tail(*commands);\n\n\t//\tFill array of button ptrs\n\tcurbutton = 0;\n\tbuttons[0] = &okaybtn;\n\tbuttons[1] = &testbtn;\n\tbuttons[2] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\t// Add device to device control\n\tmethod.Add_Item(\"DirectX Media (Default)\");\n\n\t#ifdef MCIMPEG\n\tfor (i = 0; i < mCount; i++)\n\t\t{\n\t\tif (mMCIDevices[i].description != NULL)\n\t\t\t{\n\t\t\tmethod.Add_Item(mMCIDevices[i].description);\n\t\t\t}\n\t\t}\n\t#endif\n\t\n\tmethod.Set_Selected_Index(0);\n\t\n\t#ifdef MCIMPEG\n\t// Search for current selection\n\tif (GetDeviceName())\n\t\t{\n\t\tfor (i = 0; i < mCount; i++)\n\t\t\t{\n\t\t\tif (stricmp(GetDeviceName(), mMCIDevices[i].name) == 0)\n\t\t\t\t{\n\t\t\t\tmethod.Set_Selected_Index(i + 1);\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t#endif\n\t\n\t// Save original device selection\n\tif (GetDeviceName())\n\t\torigDevice = strdup(GetDeviceName());\n\t\t\t\t\t\t\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\t\n\twhile (process)\n\t\t{\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored)\n\t\t\t{\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t#endif\n\n\t\t//\tInvoke game callback\n\t\tCall_Back();\n\n\t\t//\tRefresh display if needed\n\t\tif (display)\n\t\t\t{\n\t\t\tHide_Mouse();\n\t\t\t\n\t\t\tif (display >= REDRAW_BACKGROUND)\n\t\t\t\t{\n\t\t\t\t//\tRefresh the backdrop\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\t//\tDraw the background\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption(\"Movie Settings\", d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t\t}\n\n\t\t\t//\tRedraw buttons\n\t\t\tif (display >= REDRAW_BUTTONS)\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t\t\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t\t}\n\n\t\t//\tGet user input\n\t\tinput = commands->Input();\n\n\t\t//\tProcess input\n\t\tswitch (input)\n\t\t\t{\n\t\t\tcase (BUTTON_OKAY | KN_BUTTON):\n\t\t\t\tselection = BUTTON_OKAY;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase (BUTTON_TEST | KN_BUTTON):\n\t\t\t\tselection = BUTTON_TEST;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\t\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (num_of_buttons - 1);\n\t\t\t\t\t\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\t\n\t\t\t\tif (curbutton > (num_of_buttons - 1))\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tselection = curbutton + BUTTON_OKAY;\n\t\t\t\tpressed = true;\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n\n\t\tif (pressed)\n\t\t\t{\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\tcurbutton = selection - BUTTON_OKAY;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection)\n\t\t\t\t{\n\t\t\t\tcase (BUTTON_TEST):\n\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\n\t\t\t\t\tif (method.Current_Index() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tSetDeviceName(NULL);\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\ti = method.Current_Index();\n\t\t\t\t\t\t#ifdef MCIMPEG\n\t\t\t\t\t\tSetDeviceName(mMCIDevices[i - 1].name);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\tTheme.Fade_Out();\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tVisiblePage.Clear();\n\t\t\t\t\t//PlayMpegMovie(\"acrop\");\t//PG\n\t\t\t\t\tKeyboard->Clear();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t\tTheme.Queue_Song(THEME_CRUS);\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\tbuttons[0]->Turn_On();\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_OKAY):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\t\n\t\t\t\t\tif (method.Current_Index() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tSetDeviceName(NULL);\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\ti = method.Current_Index();\n\t\t\t\t\t\t#ifdef MCIMPEG\n\t\t\t\t\t\tSetDeviceName(mMCIDevices[i - 1].name);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\t{\n\t\t\t\t\tRawFileClass file(CONFIG_FILE_NAME);\n\t\t\t\t\tSave(file);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tSetDeviceName(origDevice);\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\tif (origDevice)\n\t\tfree(origDevice);\n\t}\n\n\n#ifdef MCIMPEG\n/****************************************************************************\n*\n* NAME\n*     EnumMCI(DeviceDesc, Context)\n*\n* DESCRIPTION\n*     MCI device enumeration callback\n*\n* INPUTS\n*     DeviceDesc - MCI device description\n*     Context    - User defined context variable\n*\n* RESULT\n*     Continue - Continue with next device flag\n*\n****************************************************************************/\n\nbool EnumMCI(MCIDevice* desc, void* context)\n\t{\n\tMPGSettings* mpgset = (MPGSettings*)context;\n\n\t// Digital video device type?\n\tif (desc->type == MCI_DEVTYPE_DIGITAL_VIDEO)\n\t\t{\n\t\tif (MciMovie)\n\t\t\t{\n\t\t\tCCFileClass file;\n\t\t\tconst char* filename;\n\n\t\t\tfilename = file.Set_Name(\"movies\\\\acrop.mpg\");\n\t\n\t\t\tif (!file.Is_Available())\n\t\t\t\t{\n\t\t\t\tchar buffer[256];\n\t\t\t\tsprintf(buffer, \"Couldn't test MCI device %s\\n\", desc->name);\n\t\t\t\tVisiblePage.Clear();\n\t\t\t\tGamePalette.Set();\n\t\t\t\tShow_Mouse();\n\t\t\t\tWWMessageBox().Process(buffer);\n\t\t\t\tHide_Mouse();\n\t\t\t\tVisiblePage.Clear();\n\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\n\t\t\tif (MciMovie->Open(filename, desc->name))\n\t\t\t\t{\n\t\t\t\tMciMovie->Close();\n\t\t\t\tmemcpy((void*)&mpgset->mMCIDevices[mpgset->mCount], (void*)desc,\n\t\t\t\t\tsizeof(MCIDevice));\n\t\t\t\tmpgset->mCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn true;\n\t}\n#endif\n#endif\n"
  },
  {
    "path": "REDALERT/MPGSET.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef _MPGSETTINGS_H_\n#define _MPGSETTINGS_H_\n\n#include \"function.h\"\n\n#ifdef DVD\n#include \"mci.h\"\n#include \"rawfile.h\"\n\nclass MPGSettings\n\t{\n\tpublic:\n\t\tMPGSettings(const char* deviceName);\n\t\tMPGSettings(FileClass& file);\n\t\tvirtual ~MPGSettings(void);\n\n\t\tvoid SetDeviceName(const char* device);\n\t\tconst char* GetDeviceName(void) const\n\t\t\t{return mDeviceName;}\n\t\tbool Save(FileClass& file);\n\t\tvoid Dialog(void);\n\n\t\tchar* mDeviceName;\n\n\t\t#ifdef MCIMPEG\n\t\tMCI mMCI;\n\t\tunsigned int mCount;\n\t\tMCIDevice* mMCIDevices;\n\t\t#endif\n\t};\n\n#endif // DVD\n#endif // _MPGSETTINGS_H_\n"
  },
  {
    "path": "REDALERT/MPLAYER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MPLAYER.CPP 3     3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPLAYER.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Bill Randolph                                                *\n *                                                                                             *\n *                   Start Date : April 14, 1995                                               *\n *                                                                                             *\n *                  Last Update : November 30, 1995 [BRR]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                *\n *   Clear_Listbox -- clears the given list box                                                *\n *   Clear_Vector -- clears the given NodeNameType vector                                      *\n *   Computer_Message -- \"sends\" a message from the computer                                   *\n *   Garble_Message -- \"garbles\" a message                                                     *\n *   Surrender_Dialog -- Prompts user for surrendering                                         *\n *   Abort_Dialog -- Prompts user for confirmation on aborting the mission\t\t\t\t\t\t\t  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\nextern bool Is_Mission_Counterstrike (char *file_name);\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#endif\n\n/***********************************************************************************************\n * Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      GAME_NORMAL, GAME_MODEM, etc.                                                          *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nGameType Select_MPlayer_Game (void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 190 *RESFACTOR;\n#ifdef WOLAPI_INTEGRATION\n\tint d_dialog_h = 89 * RESFACTOR;\t\t\t//\tajw\n\tint\td_dialog_y = (((255 * RESFACTOR) - d_dialog_h) / 2);\n#else\n\tint d_dialog_h = 78 *RESFACTOR;\n\tint d_dialog_y = 90 * RESFACTOR;\n#endif\n\tint d_dialog_x = (((320*RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\n\n\tint d_txt6_h = 7 *RESFACTOR;\n\tint d_margin = 7 *RESFACTOR;\n\n\tint d_modemserial_w = 80 *RESFACTOR;\n\tint d_modemserial_h = 9 *RESFACTOR;\n\tint d_modemserial_x = d_dialog_cx - d_modemserial_w / 2;\n\tint d_modemserial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;\n\n\tint d_skirmish_w = 80 *RESFACTOR;\n\tint d_skirmish_h = 9 *RESFACTOR;\n\tint d_skirmish_x = d_dialog_cx - d_skirmish_w / 2;\n\tint d_skirmish_y = d_modemserial_y + d_modemserial_h + 2*RESFACTOR;\n\n\tint d_ipx_w = 80 *RESFACTOR;\n\tint d_ipx_h = 9 *RESFACTOR;\n\tint d_ipx_x = d_dialog_cx - d_ipx_w / 2;\n\tint d_ipx_y = d_skirmish_y + d_skirmish_h + 2*RESFACTOR;\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tajw 7/2/98 - added button\n\tint d_wol_w = 80 * RESFACTOR;\n\tint d_wol_h = 9 * RESFACTOR;\n\tint d_wol_x = d_dialog_cx - d_wol_w / 2;\n\tint d_wol_y = d_ipx_y + d_ipx_h + 2*RESFACTOR;\n#endif\n\n\tint d_cancel_w = 60 *RESFACTOR;\n\tint d_cancel_h = 9 *RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n#ifdef WOLAPI_INTEGRATION\n\tint d_cancel_y = d_wol_y + d_wol_h + d_margin;\n#else\n\tint d_cancel_y = d_ipx_y + d_ipx_h + d_margin;\n#endif\n\n\t#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n\t#endif\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations:\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_MODEMSERIAL = 100,\n\t\tBUTTON_SKIRMISH,\n\t\tBUTTON_IPX,\n#ifdef WOLAPI_INTEGRATION\n\t\tBUTTON_WOL,\t\t\t\t//\tajw\n#endif\n\t\tBUTTON_CANCEL,\n\n#ifdef WOLAPI_INTEGRATION\n\t\tNUM_OF_BUTTONS = 5,\t\t//\tajw\n#else\n\t\tNUM_OF_BUTTONS = 4,\n#endif\n\t};\n\n\tint num_of_buttons = NUM_OF_BUTTONS - (Ipx.Is_IPX() ? 0 : 1);\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\t\t// includes map interior & coord values\n\t\tREDRAW_BACKGROUND,\t// includes box, map bord, key, coord labels, btns\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables:\n\t//------------------------------------------------------------------------\n\tKeyNumType input;\t\t\t\t\t\t\t\t// input from user\n\tbool process;\t\t\t\t\t\t\t\t\t// loop while true\n\tRedrawType display;\t\t\t\t\t\t\t// true = re-draw everything\n\tGameType retval;\t\t\t\t\t\t\t\t// return value\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[NUM_OF_BUTTONS];\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t\t\t// the button list\n\n\n\t//------------------------------------------------------------------------\n\t// If IPX not active then do only the modem serial dialog\n\t//------------------------------------------------------------------------\n//\tif ( !Ipx.Is_IPX() ) {\n//\t\treturn( Select_Serial_Dialog() );\n//\t}\n\n\n\tTextButtonClass modemserialbtn (BUTTON_MODEMSERIAL, TXT_MODEM_SERIAL, TPF_BUTTON,\n\t\td_modemserial_x, d_modemserial_y, d_modemserial_w, d_modemserial_h);\n\n\tTextButtonClass skirmishbtn (BUTTON_SKIRMISH, TXT_SKIRMISH, TPF_BUTTON,\n\t\td_skirmish_x, d_skirmish_y, d_skirmish_w, d_skirmish_h);\n\n\tTextButtonClass ipxbtn (BUTTON_IPX, TXT_NETWORK, TPF_BUTTON,\n\t\td_ipx_x, d_ipx_y, d_ipx_w, d_ipx_h);\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tajw\n\tTextButtonClass wolbtn(BUTTON_WOL, TXT_WOL_INTERNETBUTTON, TPF_BUTTON,\n\t\td_wol_x, d_wol_y, d_wol_w, d_wol_h);\n#endif\n\n\tif(!Ipx.Is_IPX()) {\n\t\td_cancel_y = d_ipx_y;\n\t\td_dialog_h -= d_cancel_h;\n\t}\n\n\tTextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n#endif\n\t//------------------------------------------------------------------------\n\t//\tCreate the list\n\t//------------------------------------------------------------------------\n\tcommands = &modemserialbtn;\n\tskirmishbtn.Add_Tail(*commands);\n\tif(Ipx.Is_IPX()) {\n\t\tipxbtn.Add_Tail(*commands);\n\t}\n#ifdef WOLAPI_INTEGRATION\n\twolbtn.Add_Tail(*commands);\t\t\t//\tajw\n#endif\n\tcancelbtn.Add_Tail(*commands);\n\n\t//------------------------------------------------------------------------\n\t//\tFill array of button ptrs\n\t//------------------------------------------------------------------------\n\tcurbutton = 0;\n\tbuttons[0] = &modemserialbtn;\n\tbuttons[1] = &skirmishbtn;\n\tif(Ipx.Is_IPX()) {\n\t\tbuttons[2] = &ipxbtn;\n#ifdef WOLAPI_INTEGRATION\n\t\tbuttons[3] = &wolbtn;\t\t\t//\tajw\n\t\tbuttons[4] = &cancelbtn;\n#else\n\t\tbuttons[3] = &cancelbtn;\n#endif\n\t} else {\n#ifdef WOLAPI_INTEGRATION\n\t\tbuttons[2] = &wolbtn;\t\t\t//\tajw\n\t\tbuttons[3] = &cancelbtn;\n#else\n\t\tbuttons[2] = &cancelbtn;\n#endif\n\t}\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\twhile (process) {\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t}\n\t\t\t#endif\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRefresh the backdrop\n\t\t\t\t//...............................................................\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDraw the background\n\t\t\t\t//...............................................................\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption (TXT_SELECT_MPLAYER_GAME, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_MODEMSERIAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_MODEMSERIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SKIRMISH | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SKIRMISH;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_IPX | KN_BUTTON):\n\t\t\t\tselection = BUTTON_IPX;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tcase (BUTTON_WOL | KN_BUTTON):\t\t\t//\tajw\n\t\t\t\tselection = BUTTON_WOL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_UP:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (num_of_buttons - 1);\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_DOWN:\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (num_of_buttons - 1) )\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase KN_RETURN:\n\t\t\t\tselection = curbutton + BUTTON_MODEMSERIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\n\t\t\t//..................................................................\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\t//..................................................................\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tcurbutton = selection - BUTTON_MODEMSERIAL;\n\t\t\tif(selection == BUTTON_CANCEL && !Ipx.Is_IPX()) curbutton--;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_MODEMSERIAL):\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Pop up the modem/serial/com port dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tretval = Select_Serial_Dialog();\n\n\t\t\t\t\tif (retval != GAME_NORMAL) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SKIRMISH):\n\t\t\t\t\tSession.Type = GAME_SKIRMISH;\n#if (0) //PG\n\t\t\t\t\tif (Com_Scenario_Dialog(true)) {\n\t\t\t\t\t\tretval = GAME_SKIRMISH;\n\t\t\t\t\t\tprocess = false;\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tbAftermathMultiplayer = Is_Aftermath_Installed();\n\t\t\t\t\t\t//\tajw I'll bet this was needed before also...\n\t\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_IPX):\n\t\t\t\t\tretval = GAME_IPX;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tcase (BUTTON_WOL):\t\t\t\t//\tajw\n\t\t\t\t\tretval = GAME_INTERNET;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tretval = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\n\treturn(retval);\n\n}\t/* end of Select_MPlayer_Game */\n\n\n/***************************************************************************\n * Clear_Listbox -- clears the given list box                              *\n *                                                                         *\n * This routine assumes the items in the given list box are character\t\t*\n * buffers; it deletes each item in the list, then clears the list.\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\t\tptr to listbox\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Clear_Listbox(ListClass * list)\n{\n\tchar * item;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list box\n\t//------------------------------------------------------------------------\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\tlist->Flag_To_Redraw();\n\n}\t// end of Clear_Listbox\n\n\n/***************************************************************************\n * Clear_Vector -- clears the given NodeNameType vector                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tvector\t\tptr to vector to clear\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Clear_Vector(DynamicVectorClass <NodeNameType *> * vector)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the 'Players' Vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < vector->Count(); i++) {\n\t\tdelete (*vector)[i];\n\t}\n\tvector->Clear();\n\n}\t// end of Clear_Vector\n\n\n/***************************************************************************\n * Computer_Message -- \"sends\" a message from the computer                 *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Computer_Message(void)\n{\n#ifdef NEVER\n\tint color;\n\tHousesType house;\n\tHouseClass * ptr;\n\n\t//------------------------------------------------------------------------\n\t//\tFind the computer house that the message will be from\n\t//------------------------------------------------------------------------\n\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\t\tptr = HouseClass::As_Pointer(house);\n\n\t\tif (!ptr || ptr->IsHuman || ptr->IsDefeated) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDecode this house's color\n\t\t//.....................................................................\n\t\tcolor = ptr->RemapColor;\n\n\t\t//.....................................................................\n\t\t//\tWe now have a 1/4 chance of echoing one of the human players'\n\t\t// messages back.\n\t\t//.....................................................................\n\t\tif (Percent_Chance(25)) {\n\n\t\t\t//..................................................................\n\t\t\t//\tNow we have a 1/3 chance of garbling the human message.\n\t\t\t//..................................................................\n\t\t\tif (Percent_Chance(33)) {\n\t\t\t\tGarble_Message(Session.LastMessage);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tOnly add the message if there is one to add.\n\t\t\t//..................................................................\n\t\t\tif (strlen(Session.LastMessage)) {\n\t\t\t\tSession.Messages.Add_Message(Text_String(TXT_COMPUTER), 0,\n\t\t\t\t\tSession.LastMessage,\n\t\t\t\t\tcolor, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tSession.Messages.Add_Message(Text_String(TXT_COMPUTER), 0,\n\t\t\t\tText_String(TXT_COMP_MSG1 + Random_Pick(0, 12)),\n\t\t\t\tcolor, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\t}\n\n\t\treturn;\n\t}\n#endif\n}\t/* end of Computer_Message */\n\n\n#ifdef NEVER\n/***************************************************************************\n * Garble_Message -- \"garbles\" a message                                   *\n *                                                                         *\n * INPUT:                                                                  *\n *      buf      buffer to garble; stores output message                   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Garble_Message(char * buf)\n{\n\tchar txt[80];\n\tchar punct[20];\t\t// for punctuation\n\tchar * p;\t\t\t\t\t// working ptr\n\tint numwords;\t\t\t// # words in the phrase\n\tchar * words[40];\t\t// ptrs to various words in the phrase\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tPull off any trailing punctuation\n\t//------------------------------------------------------------------------\n\tp = buf + strlen(buf) - 1;\n\twhile (1) {\n\t\tif (p < buf)\n\t\t\tbreak;\n\t\tif (p[0]=='!' || p[0]=='.' || p[0]=='?') {\n\t\t\tp--;\n\t\t}\n\t\telse {\n\t\t\tp++;\n\t\t\tbreak;\n\t\t}\n\t\tif (strlen(p) >= (sizeof(punct) - 1) ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tstrcpy (punct, p);\n\tp[0] = 0;\n\n\tfor (i = 0; i < 40; i++) {\n\t\twords[i] = NULL;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCopy the original buffer\n\t//------------------------------------------------------------------------\n\tstrcpy(txt, buf);\n\n\t//------------------------------------------------------------------------\n\t//\tSplit it up into words\n\t//------------------------------------------------------------------------\n\tp = strtok (txt, \" \");\n\tnumwords = 0;\n\twhile (p) {\n\t\twords[numwords] = p;\n\t\tnumwords++;\n\t\tp = strtok (NULL, \" \");\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNow randomly put the words back.  Don't use the real random-number\n\t//\tgenerator, since different machines will have different LastMessage's,\n\t//\tand will go out of sync.\n\t//------------------------------------------------------------------------\n\tbuf[0] = 0;\n\tfor (i = 0; i < numwords; i++) {\n\t\tj = Sim_IRandom(0, numwords);\n\t\tif (words[j] == NULL) {\t\t// this word has been used already\n\t\t\ti--;\n\t\t\tcontinue;\n\t\t}\n\t\tstrcat(buf, words[j]);\n\t\twords[j] = NULL;\n\t\tif (i < numwords-1)\n\t\t\tstrcat(buf, \" \");\n\t}\n\tstrcat(buf, punct);\n\n}\t/* end of Garble_Message */\n#endif\n\n\n/***************************************************************************\n * Surrender_Dialog -- Prompts user for surrendering                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = user cancels, 1 = user wants to surrender.                     *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 BRR : Created.                                             *\n *=========================================================================*/\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(int text)\n{\n\treturn Surrender_Dialog( Text_String( text ) );\n}\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\nint Surrender_Dialog(const char* text)\n#else\nint Surrender_Dialog(int text)\n#endif\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tD_DIALOG_W = 240*RESFACTOR,\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 63*RESFACTOR,\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320*RESFACTOR - D_DIALOG_W) / 2),// centered x-coord\n\t\tD_DIALOG_Y = ((200*RESFACTOR - D_DIALOG_H) / 2),// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT6_H = 7*RESFACTOR,\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tD_MARGIN = 5*RESFACTOR,\t\t\t\t\t\t\t\t\t// margin width/height\n\t\tD_TOPMARGIN = 20*RESFACTOR,\t\t\t\t\t\t\t// top margin\n\n\t\tD_OK_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// OK width\n\t\tD_OK_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// OK height\n\t\tD_OK_X = D_DIALOG_CX - D_OK_W - 5*RESFACTOR,\t\t// OK x\n\t\tD_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN*2,\t// OK y\n\n\t\tD_CANCEL_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_CANCEL_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_CANCEL_X = D_DIALOG_CX + 5*RESFACTOR,\t\t\t// Cancel x\n\t\tD_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN*2, // Cancel y\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);\n\n\tint curbutton;\n\tTextButtonClass * buttons[2];\n\tcurbutton = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the button list\n\t//------------------------------------------------------------------------\n\tcommands = &okbtn;\n\tcancelbtn.Add_Tail(*commands);\n\n\tbuttons[0] = &okbtn;\n\tbuttons[1] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tint retcode = 0;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tif (Session.Type != GAME_SKIRMISH) {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\t//..................................................................\n\t\t\t//\tDisplay the dialog box\n\t\t\t//..................................................................\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_NONE, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t//...............................................................\n\t\t\t//\tDraw the captions\n\t\t\t//...............................................................\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\tFancy_Text_Print(text,\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n#else\n\t\t\tFancy_Text_Print(Text_String(text),\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n#endif\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw the buttons\n\t\t\t//..................................................................\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tKeyNumType input = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tretcode = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tif (curbutton == 0) {\n\t\t\t\t\tretcode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > 1) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = 1;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw the display\n\t//------------------------------------------------------------------------\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n\n\treturn (retcode);\n}\n\n\n/***************************************************************************\n * Abort_Dialog -- Prompts user for confirmation on aborting the mission\t*\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      1 = user confirms abort, 0 = user cancels\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   07/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Abort_Dialog(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tD_DIALOG_W = 170*RESFACTOR,\t\t\t\t\t\t\t// dialog width\n\t\tD_DIALOG_H = 63*RESFACTOR,\t\t\t\t\t\t\t\t// dialog height\n\t\tD_DIALOG_X = ((320*RESFACTOR - D_DIALOG_W) / 2),// centered x-coord\n\t\tD_DIALOG_Y = ((200*RESFACTOR - D_DIALOG_H) / 2),// centered y-coord\n\t\tD_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),\t\t// coord of x-center\n\n\t\tD_TXT6_H = 7*RESFACTOR,\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tD_MARGIN = 5*RESFACTOR,\t\t\t\t\t\t\t\t\t// margin width/height\n\t\tD_TOPMARGIN = 20*RESFACTOR,\t\t\t\t\t\t\t// top margin\n\n\t\tD_YES_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// YES width\n\t\tD_YES_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// YES height\n\t\tD_YES_X = D_DIALOG_CX - D_YES_W - 5*RESFACTOR,\t// YES x\n\t\tD_YES_Y = D_DIALOG_Y + D_DIALOG_H - D_YES_H - D_MARGIN*2,\t// YES y\n\n\t\tD_NO_W = 45*RESFACTOR,\t\t\t\t\t\t\t\t\t// Cancel width\n\t\tD_NO_H = 9*RESFACTOR,\t\t\t\t\t\t\t\t\t// Cancel height\n\t\tD_NO_X = D_DIALOG_CX + 5*RESFACTOR,\t\t\t\t\t// Cancel x\n\t\tD_NO_Y = D_DIALOG_Y + D_DIALOG_H - D_NO_H - D_MARGIN*2, // Cancel y\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButton enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_YES = 100,\n\t\tBUTTON_NO,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tControlClass * commands = NULL;\t\t// the button list\n\n\tTextButtonClass yesbtn(BUTTON_YES, TXT_YES, TPF_BUTTON, D_YES_X, D_YES_Y, D_YES_W, D_YES_H);\n\n\tTextButtonClass nobtn(BUTTON_NO, TXT_NO, TPF_BUTTON, D_NO_X, D_NO_Y, D_NO_W, D_NO_H);\n\n\tint curbutton;\n\tTextButtonClass * buttons[2];\n\tcurbutton = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize\n\t//------------------------------------------------------------------------\n\tSet_Logic_Page(SeenBuff);\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the button list\n\t//------------------------------------------------------------------------\n\tcommands = &yesbtn;\n\tnobtn.Add_Tail(*commands);\n\n\tbuttons[0] = &yesbtn;\n\tbuttons[1] = &nobtn;\n\tbuttons[curbutton]->Turn_On();\n\n\t//------------------------------------------------------------------------\n\t//\tMain Processing Loop\n\t//------------------------------------------------------------------------\n\tint retcode = 0;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t//.....................................................................\n\t\t//\tInvoke game callback\n\t\t//.....................................................................\n\t\tif (Session.Type != GAME_SKIRMISH) {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\t//..................................................................\n\t\t\t//\tDisplay the dialog box\n\t\t\t//..................................................................\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);\n\t\t\tDraw_Caption(TXT_NONE, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);\n\n\t\t\t//...............................................................\n\t\t\t//\tDraw the captions\n\t\t\t//...............................................................\n\t\t\tFancy_Text_Print(Text_String(TXT_CONFIRM_EXIT),\n\t\t\t\tD_DIALOG_CX, D_DIALOG_Y + D_TOPMARGIN,\n\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\tTPF_CENTER | TPF_TEXT);\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw the buttons\n\t\t\t//..................................................................\n\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tKeyNumType input = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_YES | KN_BUTTON):\n\t\t\t\tretcode = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NO | KN_BUTTON):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tif (curbutton == 0) {\n\t\t\t\t\tretcode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\t\tretcode = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RIGHT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > 1) {\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_LEFT):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\tcurbutton = 1;\n\t\t\t\t}\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw the display\n\t//------------------------------------------------------------------------\n\tHidPage.Clear();\n\tMap.Flag_To_Redraw(true);\n\tMap.Render();\n\n\treturn (retcode);\n}\n\n\n#if(TEN)\n/***************************************************************************\n * Read_TEN_Game_Options -- reads multiplayer game options from disk       *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Read_TEN_Game_Options(void)\n{\n\tINIClass ini;\n\tif (!ini.Load(RawFileClass(Session.OptionsFile))) {\n\t\treturn (0);\n\t}\n\n\tini.Get_String(\"Options\", \"Handle\", \"Noname\",  Session.Handle,\n\t\tsizeof(Session.Handle));\n\tif (Session.TenPlayerID == -1) {\n\t\treturn (0);\n\t}\n\tSession.ColorIdx = (PlayerColorType)Session.TenPlayerID;\n\tSession.House = (HousesType)\n\t\t((int)HOUSE_USSR + ini.Get_Int(\"Options\", \"Side\", 0));\n\tSession.Options.Credits = ini.Get_Int(\"Options\", \"Credits\", 3000);\n\tSession.Options.Bases = ini.Get_Int(\"Options\", \"Bases\", 1);\n\tSession.Options.Tiberium = ini.Get_Int(\"Options\", \"Tiberium\", 1);\n\tSession.Options.Goodies = ini.Get_Int(\"Options\", \"Crates\", 1);\n\tSpecial.IsShadowGrow = ini.Get_Int (\"Options\", \"Shadow\", 0);\n\tBuildLevel = ini.Get_Int(\"Options\", \"BuildLevel\", 3);\n\tSession.Options.UnitCount = ini.Get_Int(\"Options\", \"UnitCount\", 5);\n\tSeed = ini.Get_Int(\"Options\", \"Seed\", 0);\n\tSpecial.IsCaptureTheFlag = ini.Get_Int(\"Options\", \"CapFlag\", 0);\n\tSession.Options.AIPlayers = ini.Get_Int(\"Options\", \"AI\", 0);\n\tSession.NumPlayers = ini.Get_Int(\"Options\", \"Players\", 2);\n\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tini.Get_String(\"Options\", \"Scenario\", \"Black Acres\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(),\n\t\t\tSession.Options.ScenarioDescription) ) {\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tstrcpy(Session.ScenarioFileName, Session.Scenarios[i]->Get_Filename());\n\t\t\tstrcpy(Scen.ScenarioName, Session.Scenarios[i]->Get_Filename());\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (Session.Options.ScenarioIndex == -1) {\n\t\tWWMessageBox().Process(\"Scenario not found!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\tOptions.GameSpeed = 0;\n\n\tSession.MaxAhead = ini.Get_Int(\"Timing\", \"MaxAhead\", 9);\n\tSession.FrameSendRate = ini.Get_Int(\"Timing\", \"SendRate\", 3);\n\tSession.NetResponseTime = ini.Get_Int(\"Timing\",\"Latency\",600);\n\n\treturn (1);\n}\n#endif\t// TEN\n\n\n#if(MPATH)\n/***************************************************************************\n * Read_MPATH_Game_Options -- reads multiplayer game options from disk     *\n *                                                                         *\n * This routine is used for multiplayer games which read the game options\t*\n * from disk, rather than through a connection dialog.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   01/11/1996 BRR : Created.                                             *\n *=========================================================================*/\nint Read_MPATH_Game_Options(void)\n{\n\tINIClass ini;\n\tif (!ini.Load(RawFileClass(Session.OptionsFile))) {\n\t\treturn (0);\n\t}\n\n\tini.Get_String(\"Options\", \"Handle\", \"Noname\",  Session.Handle,\n\t\tsizeof(Session.Handle));\n\tSession.ColorIdx = (PlayerColorType)ini.Get_Int(\"Options\", \"Color\", 0);\n\tSession.House = (HousesType)\n\t\t((int)HOUSE_USSR + ini.Get_Int(\"Options\", \"Side\", 0));\n\tSession.Options.Credits = ini.Get_Int(\"Options\", \"Credits\", 3000);\n\tSession.Options.Bases = ini.Get_Int(\"Options\", \"Bases\", 1);\n\tSession.Options.Tiberium = ini.Get_Int(\"Options\", \"Tiberium\", 1);\n\tSession.Options.Goodies = ini.Get_Int(\"Options\", \"Crates\", 1);\n\tSpecial.IsShadowGrow = ini.Get_Int (\"Options\", \"Shadow\", 0);\n\tBuildLevel = ini.Get_Int(\"Options\", \"BuildLevel\", 3);\n\tSession.Options.UnitCount = ini.Get_Int(\"Options\", \"UnitCount\", 5);\n\tSeed = ini.Get_Int(\"Options\", \"Seed\", 0);\n\tSpecial.IsCaptureTheFlag = ini.Get_Int(\"Options\", \"CapFlag\", 0);\n\tSession.Options.AIPlayers = ini.Get_Int(\"Options\", \"AI\", 0);\n\n\tif (Session.Options.AIPlayers){\n\t\tSession.Options.Ghosts = 1;\n\t}\n\n\tif (Session.Options.Tiberium) {\n\t\tSpecial.IsTGrowth = 1;\n\t\tSpecial.IsTSpread = 1;\n\t} else {\n\t\tSpecial.IsTGrowth = 0;\n\t\tSpecial.IsTSpread = 0;\n\t}\n\n\t/*\n\t** Read the scenario name from the .INI and try to match it with a scenario file in our list.\n\t*/\n\tini.Get_String(\"Options\", \"Scenario\", \"Black Acres\",\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\n\tSession.Options.ScenarioIndex = -1;\n\tfor (int i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tif (!strcmp (Session.Scenarios[i]->Description(),\n\t\t\tSession.Options.ScenarioDescription) ) {\n\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\tstrcpy(Session.ScenarioFileName, Session.Scenarios[i]->Get_Filename());\n\t\t\tstrcpy(Scen.ScenarioName, Session.Scenarios[i]->Get_Filename());\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (Session.Options.ScenarioIndex == -1) {\n\t\tWWMessageBox().Process(\"Scenario not found!\");\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n\tOptions.GameSpeed = 0;\n\n\tSession.MaxAhead = ini.Get_Int(\"Timing\", \"MaxAhead\", 9);\n\tSession.FrameSendRate = ini.Get_Int(\"Timing\", \"SendRate\", 3);\n\tSession.NetResponseTime = ini.Get_Int(\"Timing\",\"Latency\",600);\n\n\treturn (1);\n}\n#endif\t// MPATH\n\n/************************** end of mplayer.cpp *****************************/\n"
  },
  {
    "path": "REDALERT/MPLIB.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#include \"types.h\"\n#include \"mgenord.h\"\n#include \"magic.h\"\n#include \"rtq.h\"\n#include <mem.h>\n#include <i86.h>\n#include <assert.h>\n#include \"mplib.h\"\n\n#define CHUNNEL_INT 0x48\n\ntypedef union REGS REGISTERS;\n\nvoid\nYield(void)\n{\n   REGISTERS   regs;\n\n   regs.w.ax = 0x1680;\n   int386(0x2f, &regs, &regs);\n}\n\nvoid\nPostWindowsMessage(void)\n{\n   REGISTERS regs;\n\n   regs.x.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = 0;\n   regs.x.ecx = 0;\n   int386(CHUNNEL_INT, &regs, &regs);\n}\n\nint MGenGetQueueCtr(int qNo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qNo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nRTQ_NODE *MGenMoveTo(int qFrom, int qTo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qFrom;\n   regs.x.ecx = qTo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nRTQ_NODE *MGenGetNode(int q)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = q;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nRTQ_NODE *MGenGetMasterNode(unsigned *size)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   int386(CHUNNEL_INT, &regs, &regs);\n   *size = regs.x.ecx;\n\n   return (RTQ_NODE *) regs.x.eax;\n}\n\nint MGenFlushNodes(int qFrom, int qTo)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = qFrom;\n   regs.x.ecx = qTo;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nint MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID;\n   regs.x.ebx = lowerOrderBits;\n   regs.x.ecx = upperOrderBits;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\nint MGenSanityCheck(void)\n{\n   REGISTERS   regs;\n\n   regs.x.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID;\n   int386(CHUNNEL_INT, &regs, &regs);\n\n   return regs.x.eax;\n}\n\u001a"
  },
  {
    "path": "REDALERT/MPMGRD.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#include \"mpmgrd.h\"\n\nextern \"C\" {\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include \"types.h\"\n#include \"rtq.h\"\n#include \"services.h\"\n}\n#include \"mplib.h\"\n#include \"mplpc.h\"\n\n\n#define     STATUS_OK    1\n#define     STATUS_BAD   0\n\n#define     BROADCAST_ADDR    0\n\ntypedef struct {\n   DWORD      address;\n   char       Data[1];\n} packet;\n\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\n#define     FREEQUEUE            0\n#define     DOSWORKQUEUE         1\n#define     WINWORKQUEUE         2\n#define     WINSENDQUEUE         3\n#define     DOSPENDINGQUEUE      4\n#define     WINWORKQUEUE2        5\n\n// 6, 7, 8, taken up by LPC services\n\n#define     GDOSWORKQUEUE        14\n#define     GWINWORKQUEUE        15\n#define     GWINSENDQUEUE        16\n#define     GDOSPENDINGQUEUE     17\n#define     GWINWORKQUEUE2       18\n\nMPlayerManClass::MPlayerManClass(void) : ConnManClass()\n{\n   unsigned  size;\n\n   MGenGetMasterNode(&size);\n   if (size != sizeof(RTQ_NODE)) {\n      exit(-234);\n   }\n   _myAddr = LPCGetMPAddr();\n   _nConnections = 0;\n\n   for (int i = 0; i < CONNECT_MAX; i++) {\n      _Connections[i] = 0;\n      strcpy(_Names[i], \"\");\n   }\n}\n\n// here's what we do to get private & broadcasts over the same chunnel\n// we package up an extra dword at the beginning to indicate the address\n\nint\nMPlayerManClass::Send_Private_Message(void *buf,\n                                      int buflen,\n                                      int /* ack_req */,\n                                      int conn_id)\n{\n   RTQ_NODE *n;\n\tint idx = Connection_Index(conn_id);\n\n\tif (_nConnections == 0) {\n\t\treturn (STATUS_OK);\n\t}\n\n   while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);\n\n   packet *p = (packet *) n->rtqDatum;\n\n   if (conn_id == CONNECTION_NONE) {\n      p->address = BROADCAST_ADDR;\n   } else {\n      p->address = _Connections[idx];\n   }\n\n   memcpy(p->Data, buf, buflen);\n   n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));\n\n   MGenMoveTo(DOSWORKQUEUE, WINSENDQUEUE);\n   PostWindowsMessage();\n   Yield();\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Get_Private_Message(void *buf, int *buflen,\n                                     int *conn_id)\n{\n   RTQ_NODE *n;\n\tint i;\n\n   if ((n = MGenMoveTo(DOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {\n      *buflen = 0;\n      return 0;\n   }\n\n   packet *p = (packet *) n->rtqDatum;\n\n   int lentocpy = n->rtqUpCtr - sizeof(DWORD);\n\n   *conn_id = CONNECTION_NONE;\n\tfor (i = 0; i < _nConnections; i++) {\n\t\tif (p->address == _Connections[i]) {\n\t\t\t(*conn_id) = _ID[i];\n\t\t\tbreak;\n\t\t}\n\t}\n\n   memcpy(buf, p->Data, lentocpy);\n\n   *buflen = lentocpy;\n\n   MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Send_Global_Message(void *buf, int buflen, int /*ack_req*/,\n   int address)\n{\n   RTQ_NODE *n;\n\n   while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);\n\n   packet *p = (packet *) n->rtqDatum;\n\n   if (address == 0) {\n      p->address = BROADCAST_ADDR;\n   } else {\n      p->address = address;\n   }\n\n   memcpy(p->Data, buf, buflen);\n   n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));\n\n   MGenMoveTo(DOSWORKQUEUE, GWINSENDQUEUE);\n   PostWindowsMessage();\n   Yield();\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Get_Global_Message(void *buf, int *buflen, int *address)\n{\n   RTQ_NODE *n;\n\n   if ((n = MGenMoveTo(GDOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {\n      *buflen = 0;\n      return 0;\n   }\n\n   packet *p = (packet *) n->rtqDatum;\n\n   int lentocpy = n->rtqUpCtr - sizeof(DWORD);\n\n   if (address) {\n      if (p->address == BROADCAST_ADDR) {\n         *address = 0;\n      } else {\n         *address = p->address;\n      }\n   }\n\n   memcpy(buf, p->Data, lentocpy);\n\n   *buflen = lentocpy;\n\n   MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);\n\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Service(void)\n{\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Create_Connection(int id, char *name, int address)\n{\n   _Connections[_nConnections] = address;\n\t_ID[_nConnections] = id;\n   strcpy(_Names[_nConnections], name);\n   _nConnections++;\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Delete_Connection(int id)\n{\n\tint i;\n\tint idx = Connection_Index(id);\n\tif (idx == -1)\n\t\treturn 0;\n\n\tfor (i = idx; i < _nConnections - 1; i++) {\n\t\t_Connections[i] = _Connections[i+1];\n\t\t_ID[i] = _ID[i+1];\n\t\tstrcpy (_Names[i], _Names[i+1]);\n\t}\n   _nConnections--;\n   return STATUS_OK;\n}\n\nchar *\nMPlayerManClass::Connection_Name(int id)\n{\n\tint idx = Connection_Index(id);\n\tif (idx==-1) {\n\t\treturn (NULL);\n\t}\n\n   return _Names[idx];\n}\n\nint\nMPlayerManClass::Connection_Address(int id)\n{\n\tint idx = Connection_Index(id);\n\tif (idx==-1) {\n\t\treturn (0);\n\t}\n\n   return _Connections[idx];\n}\n\nint\nMPlayerManClass::Num_Connections(void)\n{\n   return _nConnections;\n}\n\nint\nMPlayerManClass::Connection_ID(int index)\n{\n   return _ID[index];\n}\n\nint\nMPlayerManClass::Connection_Index(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < _nConnections; i++) {\n\t\tif (_ID[i] == id) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n   return -1;\n}\n\nint\nMPlayerManClass::Global_Num_Send(void)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Global_Num_Receive(void)\n{\n   return MGenGetQueueCtr(GDOSPENDINGQUEUE);\n}\n\nint\nMPlayerManClass::Private_Num_Send(int /*id*/)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Private_Num_Receive(int /*id*/)\n{\n   return MGenGetQueueCtr(DOSPENDINGQUEUE);\n}\n\nvoid\nMPlayerManClass::Reset_Response_Time(void)\n{\n   // unsupported\n}\n\nunsigned long\nMPlayerManClass::Response_Time(void)\n{\n   return (160 * 60) / 1000;   // 160 microseconds one way (9 ticks)\n}\n\nvoid\nMPlayerManClass::Set_Timing(unsigned long /*retrydelta*/,\n                            unsigned long /*maxretries*/,\n                            unsigned long /*timeout*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Configure_Debug(int /*index*/, int /*type_offset*/,\n                                 int /*type_size*/, char ** /*names*/,\n                                 int /*namestart*/, int /*namecount*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)\n{\n   // unsupported\n}\n\nint\nMPlayerManClass::Init(void)\n{\n   return STATUS_OK;\n}\n\nint MPlayerManClass::Find_Num_Connections(void)\n{\n\tTGAMEDEF game_def;\n\tint sz = sizeof(game_def);\n\n\tGetGameDef(&game_def, &sz);\n\n\treturn (game_def.numPlayers - 1);\n\n}\n\n\nvoid MPlayerManClass::Flush_All(void)\n{\n\tMGenFlushNodes(DOSPENDINGQUEUE, FREEQUEUE);\n\tMGenFlushNodes(GDOSPENDINGQUEUE, FREEQUEUE);\n}\n\n"
  },
  {
    "path": "REDALERT/MPMGRD.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef mpmgr_h\n#define mpmgr_h\n\n#include \"connmgr.h\"\n\n// maximum number of connections\n#define CONNECT_MAX    7\n#define MAX_NAME_LEN   128\n\nclass MPlayerManClass : public ConnManClass {\npublic:\n   MPlayerManClass(void);\n\n   // queues up incoming packets appropriately\n   int   Service(void);\n\n   // initialization\n   int   Init(void);\n\tint Find_Num_Connections(void);\n\tvoid Flush_All(void);\n\n   // send/receive data\n   int  Send_Private_Message(void *buf, int buflen, int ack_req = 1, int conn_id = CONNECTION_NONE);\n   int  Get_Private_Message(void *buf, int *buflen, int *conn_id);\n\n   int  Send_Global_Message(void *buf, int buflen, int ack_req = 0, int address = 0);\n   int  Get_Global_Message(void *buf, int *buflen, int *address = 0);\n\n   // manage connections\n   int  Num_Connections(void);\n   int  Connection_ID(int index);\n   int  Connection_Index(int id);\n   int  Create_Connection(int id, char *name, int address);\n   int  Delete_Connection(int id);\n   char *Connection_Name(int id);\n   int  Connection_Address(int id);\n\n   // queueing routines\n\n   int Global_Num_Send(void);\n   int Global_Num_Receive(void);\n   int Private_Num_Send(int id = CONNECTION_NONE);\n   int Private_Num_Receive(int id = CONNECTION_NONE);\n\n   // timing magnagement\n   void Reset_Response_Time(void);\n   unsigned long Response_Time(void);\n   void Set_Timing(unsigned long retrydelta, unsigned long maxretries, unsigned long timeout);\n\n   // debug\n   void Configure_Debug(int index, int type_offset, int type_size, char **names, int namestart,\n      int namecount);\n   void Mono_Debug_Print(int index, int refresh);\n\nprivate:\n   int  _myAddr;\n   int  _Connections[CONNECT_MAX];\n\tint  _ID[CONNECT_MAX];\n   char _Names[CONNECT_MAX][MAX_NAME_LEN];\n   int  _nConnections;\n};\n\n#endif // mpmgr_h\n\n\u001a"
  },
  {
    "path": "REDALERT/MPMGRW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#if (0)//PG\n#ifndef MP_LOAD_DLL_DYNAMICALLY\n#define MP_LOAD_DLL_DYNAMICALLY\n#endif\n\n#include \"mpmgrw.h\"\n\nextern \"C\" {\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n}\n\n#include <windows.h>\n\n#define     STATUS_OK    1\n#define     STATUS_BAD   0\n\n#define     BROADCAST_ADDR    0\n\n#define PRIVATE 0\n#define PUBLIC  1\n\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\ntypedef void __cdecl (*MPlayerInit_Type)(void);\ntypedef void __cdecl (*MPlayerDestroy_Type)(void);\ntypedef int __cdecl (*Send_Private_Message_Type)(void *buf,\n\t\t\t\t\t int buflen,\n                     int ack_req,\n                     int conn_id);\ntypedef int __cdecl\t(*Get_Private_Message_Type)(void *buf, int *buflen,\n                    int *conn_id);\ntypedef int __cdecl (*Send_Global_Message_Type)(void *buf, int buflen, int ack_req,\n   int addr);\ntypedef int __cdecl (*Get_Global_Message_Type)(void *buf, int *buflen, int *address);\t\t\ntypedef int __cdecl (*Create_Connection_Type)(int id, char *name, int address);\t\t\ntypedef int __cdecl (*Delete_Connection_Type)(int id);\t\t\ntypedef char * __cdecl (*Connection_Name_Type)(int id);\t\t\t\ntypedef int __cdecl\t(*Connection_Address_Type)(int id);\t\t\ntypedef int __cdecl\t(*Num_Connections_Type)(void);\t\t\t\ntypedef int __cdecl (*Connection_ID_Type)(int id);\t\t\t\ntypedef int __cdecl (*Connection_Index_Type)(int id);\ntypedef int __cdecl\t(*Init_Type)(void);\t\t\t\t\t\ntypedef int __cdecl (*Find_Num_Connections_Type)(void);\n\nMPlayerInit_Type MPlayerManCreate;\nMPlayerDestroy_Type MPlayerManDestroy;\nSend_Private_Message_Type Send_Private_Message_DLL;\nGet_Private_Message_Type Get_Private_Message_DLL;\nSend_Global_Message_Type Send_Global_Message_DLL;\nGet_Global_Message_Type Get_Global_Message_DLL;\nCreate_Connection_Type Create_Connection_DLL;\nDelete_Connection_Type Delete_Connection_DLL;\nConnection_Name_Type Connection_Name_DLL;\nConnection_Address_Type Connection_Address_DLL;\nNum_Connections_Type Num_Connections_DLL;\nConnection_ID_Type Connection_ID_DLL;\nConnection_Index_Type Connection_Index_DLL;\nInit_Type Init_DLL;\nFind_Num_Connections_Type Find_Num_Connections_DLL;\n\n\nFARPROC MPGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {\n        FARPROC ret=GetProcAddress(hModule, lpProcName);\n        if (!ret) {\n                char msg[255];\n                sprintf(msg, \"Unable to load function %s from %s\",\n\t\t\t\t\t\tlpProcName, \"RA95MP.DLL\");\n                MessageBox(0, msg, \"Warning\", MB_OK);\n        }\n        return ret;\n}\n\nMPlayerManClass::MPlayerManClass(void) : ConnManClass()\n{\n\tHMODULE lib;\n\n\tlib = LoadLibrary(\"ra95mp.dll\");\n\tif (lib != 0) {\n\t\tMPlayerManCreate = (MPlayerInit_Type) MPGetProcAddress(lib,\n\t\t\t\"MPlayerManCreate\");\n\t\tMPlayerManDestroy = (MPlayerDestroy_Type) MPGetProcAddress(lib,\n\t\t\t\"MPlayerManDestroy\");\n\t\tSend_Private_Message_DLL = (Send_Private_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Send_Private_Message\");\n\t\tGet_Private_Message_DLL = (Get_Private_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Get_Private_Message\");\n\t\tSend_Global_Message_DLL = (Send_Global_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Send_Global_Message\");\n\t\tGet_Global_Message_DLL = (Get_Global_Message_Type) MPGetProcAddress(lib,\n\t\t\t\"Get_Global_Message\");\n\t\tCreate_Connection_DLL = (Create_Connection_Type) MPGetProcAddress(lib,\n\t\t\t\"Create_Connection\");\n\t\tDelete_Connection_DLL = (Delete_Connection_Type) MPGetProcAddress(lib,\n\t\t\t\"Delete_Connection\");\n\t\tConnection_Name_DLL = (Connection_Name_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Name\");\n\t\tConnection_Address_DLL = (Connection_Address_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Address\");\n\t\tNum_Connections_DLL = (Num_Connections_Type) MPGetProcAddress(lib,\n\t\t\t\"Num_Connections\");\n\t\tConnection_ID_DLL = (Connection_ID_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_ID\");\n\t\tConnection_Index_DLL = (Connection_Index_Type) MPGetProcAddress(lib,\n\t\t\t\"Connection_Index\");\n\t\tInit_DLL = (Init_Type) MPGetProcAddress(lib,\n\t\t\t\"Init\");\n\t\tFind_Num_Connections_DLL = (Find_Num_Connections_Type) MPGetProcAddress(lib,\n\t\t\t\"Find_Num_Connections\");\n\t} else {\n       MessageBox(0, \"RA95MP.DLL not found!\", \"Warning\", MB_OK);\n\t\t exit(0);\n\t}\n\t\n\tif (MPlayerManCreate != 0) {\n\t\tMPlayerManCreate();\n\t}\n}\n\nMPlayerManClass::~MPlayerManClass()\n{\n\tMPlayerManDestroy();\n}\n\n// here's what we do to get private & broadcasts over the same chunnel\n// we package up an extra dword at the beginning to indicate the address\n\nint\nMPlayerManClass::Send_Private_Message(void *buf,\n                                      int buflen,\n                                      int ack_req,\n                                      int conn_id)\n{\n\treturn Send_Private_Message_DLL(buf, buflen, ack_req, conn_id);\n}\n\nint\nMPlayerManClass::Get_Private_Message(void *buf, int *buflen,\n                                     int *conn_id)\n{\n\treturn Get_Private_Message_DLL(buf, buflen, conn_id);\n}\n\nint\nMPlayerManClass::Send_Global_Message(void *buf, int buflen, int ack_req,\n   int addr)\n{\n \treturn Send_Global_Message_DLL(buf, buflen, ack_req, addr);\n}\n\nint\nMPlayerManClass::Get_Global_Message(void *buf, int *buflen, int *address)\n{\n\treturn Get_Global_Message_DLL(buf, buflen, address);\n}\n\nint\nMPlayerManClass::Service(void)\n{\n   return STATUS_OK;\n}\n\nint\nMPlayerManClass::Create_Connection(int id, char *name, int address)\n{\n\treturn Create_Connection_DLL(id, name, address);\n}\n\nint\nMPlayerManClass::Delete_Connection(int id)\n{\n\treturn Delete_Connection_DLL(id);\n}\n\nchar *\nMPlayerManClass::Connection_Name(int id)\n{\n\treturn Connection_Name_DLL(id);\n}\n\nint\nMPlayerManClass::Connection_Address(int id)\n{\n\treturn Connection_Address_DLL(id);\n}\n\nint\nMPlayerManClass::Num_Connections(void)\n{\n   return Num_Connections_DLL();\n}\n\nint\nMPlayerManClass::Connection_ID(int index)\n{\n   return Connection_ID_DLL(index);\n}\n\nint\nMPlayerManClass::Connection_Index(int id)\n{\n\treturn Connection_Index_DLL(id);\n}\n\nint\nMPlayerManClass::Global_Num_Send(void)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Global_Num_Receive(void)\n{\n\treturn 0;\n//   return MGenGetQueueCtr(GDOSPENDINGQUEUE);\n}\n\nint\nMPlayerManClass::Private_Num_Send(int /*id*/)\n{\n   return 0;\n}\n\nint\nMPlayerManClass::Private_Num_Receive(int /*id*/)\n{\n   return 0;\n}\n\nvoid\nMPlayerManClass::Reset_Response_Time(void)\n{\n   // unsupported\n}\n\nunsigned long\nMPlayerManClass::Response_Time(void)\n{\n   return (160 * 60) / 1000;   // 160 microseconds one way (9 ticks)\n}\n\nvoid\nMPlayerManClass::Set_Timing(unsigned long /*retrydelta*/,\n                            unsigned long /*maxretries*/,\n                            unsigned long /*timeout*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Configure_Debug(int /*index*/, int /*type_offset*/,\n                                 int /*type_size*/, char ** /*names*/,\n                                 int /*namestart*/, int /*namecount*/)\n{\n   // unsupported\n}\n\nvoid\nMPlayerManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)\n{\n   // unsupported\n}\n\nint\nMPlayerManClass::Init(void)\n{\n\treturn Init_DLL();\n}\n\nint MPlayerManClass::Find_Num_Connections(void)\n{\n\treturn Find_Num_Connections_DLL();\n}\n\n\nvoid MPlayerManClass::Flush_All(void)\n{\n}\n\n#endif"
  },
  {
    "path": "REDALERT/MPMGRW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifndef mpmgr_h\n#define mpmgr_h\n\n#include \"connmgr.h\"\n#include \"mplayer.h\"\n#include <windows.h>\n\n// maximum number of connections\n#define CONNECT_MAX    7\n#define MAX_NAME_LEN   128\n\nclass MPlayerManClass : public ConnManClass {\npublic:\n   MPlayerManClass(void);\n\t~MPlayerManClass(void);\n\n   // queues up incoming packets appropriately\n   int   Service(void);\n\n   // initialization\n   int   Init(void);\n\tint Find_Num_Connections(void);\n\tvoid Flush_All(void);\n\n   // send/receive data\n   int  Send_Private_Message(void *buf, int buflen, int ack_req = 1, int conn_id = CONNECTION_NONE);\n   int  Get_Private_Message(void *buf, int *buflen, int *conn_id);\n\n   int  Send_Global_Message(void *buf, int buflen, int ack_req = 0, int address = 0);\n   int  Get_Global_Message(void *buf, int *buflen, int *address = 0);\n\n   // manage connections\n   int  Num_Connections(void);\n   int  Connection_ID(int index);\n   int  Connection_Index(int id);\n   int  Create_Connection(int id, char *name, int address);\n   int  Delete_Connection(int id);\n   char *Connection_Name(int id);\n   int  Connection_Address(int id);\n\n   // queueing routines\n\n   int Global_Num_Send(void);\n   int Global_Num_Receive(void);\n   int Private_Num_Send(int id = CONNECTION_NONE);\n   int Private_Num_Receive(int id = CONNECTION_NONE);\n\n   // timing magnagement\n   void Reset_Response_Time(void);\n   unsigned long Response_Time(void);\n   void Set_Timing(unsigned long retrydelta, unsigned long maxretries, unsigned long timeout);\n\n   // debug\n   void Configure_Debug(int index, int type_offset, int type_size, char **names, int namestart,\n      int namecount);\n   void Mono_Debug_Print(int index, int refresh);\n\nprivate:\n  //HGULP _gulp;\n  //HGULP _pgulp;\n  //GAMEDEF _gameDef;\n   //int  _myAddr;\n   //int  _Connections[CONNECT_MAX];\n\t//int  _ID[CONNECT_MAX];\n   //char _Names[CONNECT_MAX][MAX_NAME_LEN];\n   //int  _nConnections;\n};\n\n#endif // mpmgr_h\n\n"
  },
  {
    "path": "REDALERT/MPU.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MPU.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPU.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/17/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"mpu.h\"\n\n\n#ifdef __BORLANDC__\nunsigned long __cdecl Get_CPU_Clock(unsigned long & high)\n{\n\t__asm db 0fh,031h\n\t__asm mov [high],edx\n\treturn(_EAX);\n}\n#endif\n"
  },
  {
    "path": "REDALERT/MPU.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MPU.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : MPU.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/15/96                                                     *\n *                                                                                             *\n *                  Last Update : July 17, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_CPU_Clock -- Fetches the current CPU clock time.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MPU_H\n#define MPU_H\n\n\n/***********************************************************************************************\n * Get_CPU_Clock -- Fetches the current CPU clock time.                                        *\n *                                                                                             *\n *    This routine will return the internal Pentium clock accumulator. This accumulator is     *\n *    incremented every clock tick. Since this clock value can get very very large, the value  *\n *    returned is in 64 bits. The low half is returned directly, the high half is stored in    *\n *    location specified.                                                                      *\n *                                                                                             *\n * INPUT:   high  -- Reference to the high value of the 64 bit clock number.                   *\n *                                                                                             *\n * OUTPUT:  Returns with the low half of the CPU clock value.                                  *\n *                                                                                             *\n * WARNINGS:   This instruction is only available on Pentium or later processors.              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#if (0)\nunsigned long Get_CPU_Clock(unsigned long & high);\n#ifndef __BORLANDC__\n#pragma aux Get_CPU_Clock parm [esi] \\\n\tmodify [edx] \\\n\tvalue [eax] = \\\n\t\"db 0fh,031h\" \\\n\t\"mov [esi],edx\"\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/MSGBOX.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MSGBOX.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : August 24, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWMessageBox::Process -- Handles all the options graphic interface.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"msgbox.h\"\n#include \"gadget.h\"\n\n\n#ifdef FIXIT_VERSION_3\nbool cancel_current_msgbox = false;\n#endif\n\n/***********************************************************************************************\n * WWMessageBox::Process -- pops up a message with yes/no, etc                                 *\n *                                                                                             *\n * This function displays a dialog box with a one-line message, and                            *\n * up to two buttons. The 2nd button is optional. The buttons default                          *\n * to \"OK\" and nothing, respectively. The hotkeys for the buttons are                          *\n * RETURN and ESCAPE.                                                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/08/1994 BR : Created.                                                                  *\n *   05/18/1995 JLB : Uses new font and dialog style.                                          *\n *   08/24/1995 JLB : Handles three buttons.                                                   *\n *=============================================================================================*/\n#define\tBUTTON_1\t\t1\n#define\tBUTTON_2\t\t2\n#define\tBUTTON_3\t\t3\n#define\tBUTTON_FLAG\t0x8000\nint WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2txt, const char * b3txt, bool preserve)\n{\n#define BUFFSIZE (511)\n\tchar buffer[BUFFSIZE];\n\tint retval;\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[3];\n\tvoid * back;\n\tBOOL display;\t\t\t\t\t\t\t\t\t// display level\n\tint  realval[5];\n\n#ifndef WIN32\n\tint\tpreservex,preservey,preservew,preserveh;\n#endif\n\n\t#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n\t#endif\n\n\tif (b1txt != NULL && *b1txt == '\\0') b1txt = NULL;\n\tif (b2txt != NULL && *b2txt == '\\0') b2txt = NULL;\n\tif (b3txt != NULL && *b3txt == '\\0') b3txt = NULL;\n\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint numbuttons = 0;\n\tif (b1txt != NULL) {\n\n\t\t/*\n\t\t**\tBuild the button list.\n\t\t*/\n\t\tbheight = FontHeight + FontYSpacing + (2 * RESFACTOR);\n\t\tbwidth = max((String_Pixel_Width(b1txt) + (8 * RESFACTOR)), (30 * RESFACTOR));\n\n\t\tif (b2txt != NULL) {\n\t\t\tnumbuttons = 2;\n\t\t\tbwidth = max(((int)String_Pixel_Width( b2txt ) + (8 * RESFACTOR)), bwidth);\n\n\t\t\tif (b3txt != NULL) {\n\t\t\t\tnumbuttons = 3;\n\t\t\t}\n\n\t\t} else {\n\t\t\tnumbuttons = 1;\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tstrncpy(buffer, msg, BUFFSIZE-1);\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tint width;\n\tint height;\n\tint lines = Format_Window_String(buffer, 255 * RESFACTOR, width, height);\n\tTextPrintType tpf = TPF_TEXT;\n\n\twidth = max(width, (90 * RESFACTOR));\n\twidth += 40 * RESFACTOR;\n\theight += (numbuttons == 0) ? (40 * RESFACTOR) : (60 * RESFACTOR);\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\tint printx = x + (20 * RESFACTOR);\n\n\t/*\n\t**\tSpecial hack to center a one line dialog box text.\n\t*/\n\tif (lines == 1) {\n\t\tprintx = x + width/2;\n\t\ttpf = tpf | TPF_CENTER;\n\t}\n\n\t/*\n\t**\tOther inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\t#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n\t#endif\n\n\t/*\n\t**\tInitialize the button structures. All are initialized, even though one (or none) may\n\t**\tactually be added to the button list.\n\t*/\n\t//DOS BUILD GERMAN BUTTONS NEED TO ONE ON TOP OF THE OTHER  VG 11/6/96\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tCenter button.\n\t*/\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);\n\n\t/*\n\t**\tRight button.\n\t*/\n\tTextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON, 0, y + height - (bheight + (15 * RESFACTOR)));\n\tbutton3.X = x + ((width - button3.Width) >> 1);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tmemset(buttons, '\\0', sizeof(buttons));\n\tif (numbuttons > 0) {\n\t\tbuttonlist = &button1;\n\t\tbuttons[0] = &button1;\n\t\trealval[0] = BUTTON_1;\n\t\tif (numbuttons > 2) {\n\t\t\tbutton3.Add(*buttonlist);\n\t\t\tbuttons[1] = &button3;\n\t\t\trealval[1] = BUTTON_3;\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[2] = &button2;\n\t\t\trealval[2] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t} else {\n\t\t\tif (numbuttons == 2) {\n\t\t\t\tbutton2.Add(*buttonlist);\n\t\t\t\tbuttons[1] = &button2;\n\t\t\t\trealval[1] = BUTTON_2;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the dialog.\n\t*/\n\tHide_Mouse();\n\tif (preserve) {\n#ifndef WIN32\n\tpreservex = max(0, x-4);\n\tpreservey = max(0, y-4);\n\tpreservew = min(width+8, 320-preservex);\n\tpreserveh = min(height+8, 200-preservey);\n\tback = new char[preservew * preserveh];\n\tSeenBuff.To_Buffer(preservex, preservey, preservew, preserveh, back, preservew * preserveh);\n#else\n\t\tback = new char[width * height];\n\t\tSeenBuff.To_Buffer(x, y, width, height, back, width * height);\n#endif\n\t}\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(Caption, x, y, width);\n\n\t/*\n\t**\tDraw the body of the message.\n\t*/\n\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t/*\n\t**\tRedraw the buttons.\n\t*/\n\tif (buttonlist) {\n\t\tbuttonlist->Draw_All();\n\t}\n\tShow_Mouse();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tif (buttonlist) {\n\t\tprocess = true;\n\t\tpressed = false;\n\t\twhile (process) {\n\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = true;\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif (display) {\n\t\t\t\tdisplay = false;\n\n\t\t\t\tHide_Mouse();\n\t\t\t\tDialog_Box(x, y, width, height);\n\t\t\t\tDraw_Caption(Caption, x, y, width);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the body of the message.\n\t\t\t\t*/\n\t\t\t\tFancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons.\n\t\t\t\t*/\n\t\t\t\tif (buttonlist) {\n\t\t\t\t\tbuttonlist->Draw_All();\n\t\t\t\t}\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInvoke game callback.\n\t\t\t*/\n\t\t\tCall_Back();\n\n\t\t\t/*\n\t\t\t**\tFetch and process input.\n\t\t\t*/\n\t\t\tKeyNumType input = buttonlist->Input();\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tI really hate to do this, but...      ajw\n\t\t\tif( cancel_current_msgbox )\n\t\t\t{\n\t\t\t\tcancel_current_msgbox = false;\n\t\t\t\tinput = KN_ESC;\n\t\t\t}\n#endif\n\t\t\tswitch (input) {\n\t\t\t\tcase (KN_ESC):\n\t\t\t\t\tselection = realval[numbuttons-1];\n\t\t\t\t\tpressed = true;\n\n#ifdef NEVER\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_1|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[0];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_2|BUTTON_FLAG):\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t}\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_3|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[1];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_LEFT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton--;\n\t\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\t\tcurbutton = numbuttons - 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RIGHT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton++;\n\t\t\t\t\t\tif (curbutton > (numbuttons - 1) ) {\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\t\tselection = realval[curbutton];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck 'input' to see if it's the 1st char of button text\n\t\t\t\t*/\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (pressed) {\n\n\t\t\t\tTextButtonClass * toggle;\n\t\t\t\t/*\n\t\t\t\t**\tTurn all the buttons off.\n\t\t\t\t*/\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_1);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_2);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\t\t\t\ttoggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_3);\n\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\ttoggle->Turn_Off();\n\t\t\t\t\ttoggle->IsPressed = false;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tTurn on and depress the button that was selected.\n\t\t\t\t*/\n\t\t\t\tif (selection == BUTTON_1 || selection == BUTTON_2 || selection == BUTTON_3) {\n\t\t\t\t\tTextButtonClass * toggle = (TextButtonClass *)buttonlist->Extract_Gadget(selection);\n\t\t\t\t\tif (toggle != NULL) {\n\t\t\t\t\t\ttoggle->Turn_On();\n//\t\t\t\t\t\ttoggle->IsOn = true;\n\t\t\t\t\t\ttoggle->IsPressed = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tHide_Mouse();\n\t\t\t\tbuttonlist->Draw_All(true);\n\t\t\t\tShow_Mouse();\n\n\t\t\t\tswitch (selection) {\n\t\t\t\t\tcase (BUTTON_1):\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_2):\n\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase BUTTON_3:\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tKeyboard->Clear();\n\t}\n\n\t/*\n\t**\tRestore the screen if necessary.\n\t*/\n\tif (preserve) {\n\t\tHide_Mouse();\n\t\tif (SeenBuff.Lock()) {\n\t\t\t#ifdef WIN32\n\t\t\t\tBuffer_To_Page(x, y, width, height, back, &SeenBuff);\n\t\t\t#else\n\t\t\t\tMCGA_Buffer_To_Page(preservex, preservey, preservew, preserveh, back, &SeenBuff);\n\t\t\t#endif\n\t\t}\n\t\tSeenBuff.Unlock();\n\n\t\tdelete[] back;\n\t\tback = NULL;\n\t\tShow_Mouse();\n\t}\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- this one takes integer text arguments                              *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      msg         message to display                                                         *\n *      b1txt         text for 1st button                                                      *\n *      b2txt         text for 2nd button; NULL = no 2nd button                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      # of button selected (0 = 1st)                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      'msg' text must be <= 38 chars                                                         *\n *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/12/1994 BR : Created.                                                                  *\n *   06/18/1995 JLB : Simplified.                                                              *\n *=============================================================================================*/\nint WWMessageBox::Process(int msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(Text_String(msg), b1txt, b2txt, b3txt, preserve));\n}\n\n\n/***********************************************************************************************\n * WWMessageBox::Process -- Displays message box.                                              *\n *                                                                                             *\n *    This routine will display a message box and wait for player input. It varies from the    *\n *    other message box functions only in the type of parameters it takes.                     *\n *                                                                                             *\n * INPUT:   msg   -- Pointer to text string for the message itself.                            *\n *                                                                                             *\n *          b1txt -- Text number for the \"ok\" button.                                          *\n *                                                                                             *\n *          b2txt -- Text number for the \"cancel\" button.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the button selected. \"true\" if \"OK\" was pressed, and \"false\" if       *\n *          \"CANCEL\" was pressed.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWMessageBox::Process(char const * msg, int b1txt, int b2txt, int b3txt, bool preserve)\n{\n\treturn(Process(msg, Text_String(b1txt), Text_String(b2txt), Text_String(b3txt), preserve));\n}\n"
  },
  {
    "path": "REDALERT/MSGBOX.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MSGBOX.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MSGBOX_H\n#define MSGBOX_H\n\n#include\t\"jshell.h\"\n\nclass WWMessageBox\n{\n\t\tint Caption;\n\n\tpublic:\n\t\tWWMessageBox(int caption=TXT_NONE) {Caption = caption;};\n\t\tint Process(const char *msg, const char *b1txt, const char *b2txt=NULL, const char *b3txt=NULL, bool preserve=false);\n\t\tint Process(int msg, int b1txt=TXT_OK, int b2txt=TXT_NONE, int b3txt=TXT_NONE, bool preserve=false);\n\t\tint Process(char const *msg, int b1txt=TXT_OK, int b2txt=TXT_NONE, int b3txt=TXT_NONE, bool preserve=false);\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/MSGLIST.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MSGLIST.CPP 2     3/04/97 2:52p Joe_bostic $ */\n/***************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MSGLIST.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 05/22/95                                 *\n *                                                                         *\n *                  Last Update : March 4, 1997 [JLB]                      *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   MessageListClass::MessageListClass -- constructor                     *\n *   MessageListClass::~MessageListClass -- destructor                     *\n *   MessageListClass::Init -- Inits message system, sets options          *\n *   MessageListClass::Add_Message -- displays the given message           *\n *   MessageListClass::Get_Message -- retrieves given message              *\n *   MessageListClass::Get_Label -- retrieves given text label\t\t\t\t\t*\n *   MessageListClass::Concat_Message -- concats the given message         *\n *   MessageListClass::Add_Edit -- Adds editable string to message list    *\n *   MessageListClass::Remove_Edit -- removes the edit field               *\n *   MessageListClass::Get_Edit_Buf -- gets edit buffer                    *\n *   MessageListClass::Set_Edit_Color -- sets color of edit gizmo          *\n *   MessageListClass::Manage -- Manages multiplayer messages              *\n *   MessageListClass::Input -- Handles input for sending messages         *\n *   MessageListClass::Draw -- Draws the messages                          *\n *   MessageListClass::Num_Messages -- returns # messages in the list      *\n *   MessageListClass::Set_Width -- sets allowable width of messages       *\n *   MessageListClass::Trim_Message -- trims chars off start of message    *\n *   MessageListClass::Compute_Y -- recomputes y-coord for all messages    *\n *   MessageListClass::Reset -- Reset so no messages are visible.          * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n\n/**************************** Globals **************************************/\n\n\n/***************************************************************************\n * MessageListClass::MessageListClass -- constructor                       *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\tcoord of upper-left of top message                    \t*\n *    max_msg\t\tmax messages allowed, including edit message          \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nMessageListClass::MessageListClass(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Init all data members\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tMessageX = 0;\n\tMessageY = 0;\n\tMaxMessages = 0;\n\tMaxChars = 0;\n\tHeight = 0;\n\n\tEnableOverflow = 0;\n\tAdjustEdit = 0;\n\tIsEdit = 0;\n\tEditX = 0;\n\tEditY = 0;\n\tEditLabel = 0;\n\tEditBuf[0] = 0;\n\tOverflowBuf[0] = 0;\n\tEditCurPos = 0;\n\tEditInitPos = 0;\n\tCursorChar = 0;\n\tOverflowStart = 0;\n\tOverflowEnd = 0;\n\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tBufferAvail[i] = 1;\n\t}\n\n}\t// end of MessageListClass\n\n\n/***************************************************************************\n * MessageListClass::~MessageListClass -- destructor                       *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\tcoord of upper-left of top message                     \t*\n *    max_msg\t\tmax messages allowed, including edit message          \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nMessageListClass::~MessageListClass()\n{\n\tInit(0,0,0,0,0,0,0,0,0,0);\n\n}\t// end of ~MessageListClass\n\n\n/***************************************************************************\n * MessageListClass::Init -- Inits message system, sets options            *\n *                                                                         *\n * INPUT:                                                                  *\n *    x,y\t\t\t\tcoord of upper-left of top message                    *\n *    max_msg\t\t\tmax messages allowed, NOT including edit message      *\n *    maxchars\t\t\tmax # characters allowed per message                \t*\n *\t\theight\t\t\tpixel height of a line of text\t\t\t\t\t\t\t\t*\n *\t\tedit_x\t\t\tx-coord of edit field; -1 = put at the top of the\t\t*\n *\t\t\t\t\t\t\tother messages\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit_y\t\t\ty-coord of edit field; -1 = put at the top of the\t\t*\n *\t\t\t\t\t\t\tother messages\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\toverflow_on\t\ttrue = enable the overflow typing feature\t\t\t\t\t*\n *\t\tover_start\t\tstart index for overflow processing\t\t\t\t\t\t\t*\n *\t\tover_end\t\t\tend index for overflow processing\t\t\t\t\t\t\t*\n *     width          pixel width of message buffer                         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Init(int x, int y, int max_msg, int maxchars,\n\tint height, int edit_x, int edit_y, int overflow_on, int over_start,\n\tint over_end, int width)\n{\n\tTextLabelClass * txtlabel;\n\tint i;\n\n\tWidth = width;\n\n\t//------------------------------------------------------------------------\n\t//\tRemove every entry in the list\n\t//------------------------------------------------------------------------\n\ttxtlabel = MessageList;\n\twhile (txtlabel) {\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tdelete txtlabel;\n\t\ttxtlabel = MessageList;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMark all buffers as available\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tBufferAvail[i] = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the editable message\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tdelete EditLabel;\n\t\tEditLabel = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tMessageX = x;\n\tMessageY = y;\n\n\tMaxMessages = max_msg;\n\tif (MaxMessages > MAX_NUM_MESSAGES)\n\t\tMaxMessages = MAX_NUM_MESSAGES;\n\n\tMaxChars = maxchars;\n\tif (MaxChars > MAX_MESSAGE_LENGTH)\n\t\tMaxChars = MAX_MESSAGE_LENGTH;\n\n\tHeight = height;\n\n\t//------------------------------------------------------------------------\n\t// Init the edit field variables.  If edit_x or edit_y is -1, place the\n\t// edit field above the other messages; otherwise, place it at the desired\n\t// coords.\n\t//------------------------------------------------------------------------\n\tEnableOverflow = overflow_on;\n\tIsEdit = 0;\n\tif (edit_x == -1 || edit_y == -1) {\n\t\tAdjustEdit = 1;\n\t\tEditX = x;\n\t\tEditY = y;\n\t}\n\telse {\n\t\tAdjustEdit = 0;\n\t\tEditX = edit_x;\n\t\tEditY = edit_y;\n\t}\n\tEditLabel = 0;\n\tEditBuf[0] = 0;\n\tOverflowBuf[0] = 0;\n\tEditCurPos = 0;\n\tEditInitPos = 0;\n\tCursorChar = 0;\n\n\t//------------------------------------------------------------------------\n\t// Init the overflow processing indices\n\t//------------------------------------------------------------------------\n\tOverflowStart = over_start;\n\tOverflowEnd = over_end;\n\tif (OverflowEnd >= MaxChars) {\n\t\tOverflowEnd = MaxChars - 1;\n\t}\n\tif (OverflowStart >= OverflowEnd) {\n\t\tOverflowStart = OverflowEnd - 1;\n\t}\n\n}\t// end of Init\n\n\n/*********************************************************************************************** \n * MessageListClass::Reset -- Reset so no messages are visible.                                * \n *                                                                                             * \n *    This routine will reset the message list tracker so that any displayed messages are      * \n *    cleared.                                                                                 * \n *                                                                                             * \n * INPUT:   none                                                                               * \n *                                                                                             * \n * OUTPUT:  none                                                                               * \n *                                                                                             * \n * WARNINGS:   none                                                                            * \n *                                                                                             * \n * HISTORY:                                                                                    * \n *   03/04/1997 JLB : Created.                                                                 * \n *=============================================================================================*/\nvoid MessageListClass::Reset(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tRemove every entry in the list\n\t//------------------------------------------------------------------------\n\tTextLabelClass * txtlabel = MessageList;\n\twhile (txtlabel) {\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tdelete txtlabel;\n\t\ttxtlabel = MessageList;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMark all buffers as available\n\t//------------------------------------------------------------------------\n\tfor (int index = 0; index < MAX_NUM_MESSAGES; index++) {\n\t\tBufferAvail[index] = 1;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the editable message\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tdelete EditLabel;\n\t\tEditLabel = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit variables\n\t//------------------------------------------------------------------------\n\tMessageList = 0;\n\tEditLabel = 0;\n\tIsEdit = 0;\n}\n\nextern void On_Message(const char* message, float timeout_seconds, long long message_id);\n\n/***************************************************************************\n * MessageListClass::Add_Message -- displays the given message             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\t\tname of sender, NULL = none\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\t\tnumerical ID for this message\t\t\t\t\t\t\t\t\t\t*\n *    txt         text to display                                        \t*\n *    color       color to draw text in                                \t\t*\n *    style       style to use                                         \t\t*\n *    timeout     # of ticks the thing is supposed to last (-1 = forever)\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to new TextLabelClass object.                                  \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *   10/16/1996 JLB : Audio feedback added.                                *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Add_Message(char const * name, int id, char const * txt,\n\tPlayerColorType color, TextPrintType style, int timeout)\n{\n\tTextLabelClass * txtlabel = NULL;\n\tchar message[MAX_MESSAGE_LENGTH + 30];\n\n\t//------------------------------------------------------------------------\n\t// Combine the name & message text, if there's a name given\n\t//------------------------------------------------------------------------\n\tif (name) {\n\t\tsprintf(message, \"%s:%s\", name, txt);\n\t\tid = -1;\n\t} else {\n\t\tstrcpy(message, txt);\n\t}\n\n#if (0)\n\n\tint i;\n\tint found;\n\tchar temp[MAX_MESSAGE_LENGTH + 30];\n\tint print_this_pass;\n\tchar save = 0;\n\tint mess_start;\n\n\t//------------------------------------------------------------------------\n\t//\tCheck that printing this wont overrun the width of the print area on screen\n\t//------------------------------------------------------------------------\n\n\tprint_this_pass = 0;\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[color], TBLACK, style);\n\tint wid = String_Pixel_Width(message);\n\tif (wid >= Width-8) {\n\t\t//------------------------------------------------------------------------\n\t\t//\tBugger. Its too long. Loop through and find out how many chars we can print\n\t\t//------------------------------------------------------------------------\n\t\tif (name) {\n\t\t\tsprintf (temp, \"%s:\", name);\n\t\t\tmess_start = strlen (name)+1;\n\t\t} else {\n\t\t\tmess_start = 0;\n\t\t}\n\t\tfor (int i=1 ; i<(int)strlen(txt) ; i++) {\n\t\t\tstrncpy (&temp[mess_start], txt, i);\n\t\t\ttemp [mess_start + i] = 0;\n\t\t\twid = String_Pixel_Width(temp);\n\t\t\tif (wid >= Width-8) {\n\t\t\t\tprint_this_pass = mess_start + i-1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//------------------------------------------------------------------------\n\t\t//\tPrematurely terminate the string so it doesn't all print.\n\t\t// We will re-enter at the end to print the rest.\n\t\t//------------------------------------------------------------------------\n\t\tif (print_this_pass) {\n\t\t\tsave = message [print_this_pass];\n\t\t\tmessage [print_this_pass] = 0;\n\t\t}\n\t}\n\n\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the top-most message if we're about to exceed the max allowed\n\t//------------------------------------------------------------------------\n\tif ( (MaxMessages > 0) && ((Num_Messages() + 1) > MaxMessages)) {\n\t\ttxtlabel = MessageList;\n\n\t\tif (txtlabel==NULL)\n\t\t\treturn(NULL);\n\n\t\t//.....................................................................\n\t\t//\tRemove this message from the list; mark its buffer as being available.\n\t\t//.....................................................................\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\tif (txtlabel->Text == MessageBuffers[i])\n\t\t\t\tBufferAvail[i] = 1;\n\t\t}\n\t\tdelete txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tCreate the message\n\t//------------------------------------------------------------------------\n\ttxtlabel = new TextLabelClass (message, MessageX, MessageY,\n\t\t&ColorRemaps[color], style);\n\tif (timeout==-1) {\n\t\ttxtlabel->UserData1 = 0;\n\t}\n\telse {\n\t\ttxtlabel->UserData1 = TickCount + timeout;\n\t}\n\ttxtlabel->UserData2 = id;\n\n\t//------------------------------------------------------------------------\n\t//\tFind a buffer to store our message in; if there are none, don't add the\n\t//\tmessage.\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\tif (BufferAvail[i]) {\n\t\t\tBufferAvail[i] = 0;\n\t\t\tmemset (MessageBuffers[i],0,MAX_MESSAGE_LENGTH + 30);\n\t\t\tstrcpy (MessageBuffers[i],message);\n\t\t\ttxtlabel->Text = MessageBuffers[i];\n\t\t\tfound = 1;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!found) {\n\t\tdelete txtlabel;\n\t\treturn (NULL);\n\t}\n\n#endif\n\n\tOn_Message(message, timeout * 60.0f / TICKS_PER_MINUTE, id);\n\t//Sound_Effect(VOC_INCOMING_MESSAGE);\n\n#if (0)\n\n\t//------------------------------------------------------------------------\n\t//\tAttach the message to our list\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\ttxtlabel->Add_Tail (*MessageList);\n\t}\n\telse {\n\t\tMessageList = txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRecompute all messages' y-coordinate values\n\t//------------------------------------------------------------------------\n\tCompute_Y();\n\n\t//------------------------------------------------------------------------\n\t//\tIf we terminated the string before the end then we need to reenter to\n\t// add a new message with the rest of the string.\n\t//------------------------------------------------------------------------\n\tif (save) {\n\t\tmessage [print_this_pass] = save;\n\t\tAdd_Message (name, id, &message [print_this_pass], color, style, timeout);\n\t}\n\n#endif\n\n\treturn(txtlabel);\n\n}\t// end of Add_Message\n\n\n/***************************************************************************\n * MessageListClass::Get_Message -- retrieves given message                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tID of message to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to message text, NULL if not found\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar * MessageListClass::Get_Message(int id)\n{\n\tTextLabelClass * gadg;\n\n\t//------------------------------------------------------------------------\n\t// Scan the message list, searching for the given ID\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tif (gadg->UserData2 == id) {\n\t\t\t\treturn (gadg->Text);\n\t\t\t}\n\t\t\tgadg = (TextLabelClass *)gadg->Get_Next();\n\t\t}\n\t}\n\n\treturn (NULL);\n\n}\t// end of Get_Message\n\n\n/***************************************************************************\n * MessageListClass::Get_Label -- retrieves given text label\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tid\t\t\tID of message to get\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tptr to message text, NULL if not found\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Get_Label(int id)\n{\n\tTextLabelClass * gadg;\n\n\t//------------------------------------------------------------------------\n\t// Scan the message list, searching for the given ID\n\t//------------------------------------------------------------------------\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tif (gadg->UserData2 == id) {\n\t\t\t\treturn (gadg);\n\t\t\t}\n\t\t\tgadg = (TextLabelClass *)gadg->Get_Next();\n\t\t}\n\t}\n\n\treturn (NULL);\n\n}\t// end of Get_Label\n\n\n/***************************************************************************\n * MessageListClass::Concat_Message -- concats the given message           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\t\tname of sender; NULL = none\t\t\t\t\t\t\t\t\t\t*\n *\t\tid\t\t\t\tID of message to concatenate to\t\t\t\t\t\t\t\t\t*\n *\t\ttxt\t\t\ttext to concatenate onto existing message\t\t\t\t\t\t*\n *\t\ttimeout\t\tnew timeout for message\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error (id or name not found)\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tIf the required message doesn't exist, this routine does nothing.\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Concat_Message(char const * name, int id, char const * txt, int timeout)\n{\n\tint min_chars;\n\tint max_chars;\n\tchar * msg;\n\tTextLabelClass * tlabel;\n\tint found;\n\n\t//------------------------------------------------------------------------\n\t// If no name is given, or the concatenation feature is turned off,\n\t// don't concatenate the message\n\t//------------------------------------------------------------------------\n\tif (!name || !EnableOverflow) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Scan through all active messages, searching for one with a matching\n\t// name & ID\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\tif (MessageList) {\n\t\ttlabel = MessageList;\n\t\twhile (tlabel) {\n\t\t\tif (tlabel->UserData2 == id &&\n\t\t\t\t!memcmp(tlabel->Text,name,strlen(name))) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ttlabel = (TextLabelClass *)tlabel->Get_Next();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// name and ID not found; return\n\t//------------------------------------------------------------------------\n\tif (!found) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// set a pointer to the text string, plus the name and colon\n\t//------------------------------------------------------------------------\n\tmsg = tlabel->Text + strlen(name) + 1;\n\n\t//------------------------------------------------------------------------\n\t// If there's room enough in the message, just add the given string\n\t//------------------------------------------------------------------------\n\tif ( (int)(strlen(msg) + strlen(txt)) < MaxChars) {\n\n\t\t//---------------------------------------------------------------------\n\t\t// We need to trim the message if there is no room to draw it\n\t\t//---------------------------------------------------------------------\n\t\tchar *concat_test = new char [MaxChars+1];\n\t\tFancy_Text_Print(TXT_NONE, 0, 0, tlabel->Color, TBLACK, tlabel->Style);\n\t\tint name_width = String_Pixel_Width(tlabel->Text) - String_Pixel_Width(msg);\n\t\tint width;\n\n\t\tstrcpy (concat_test, msg);\n\t\tstrcat (concat_test, txt);\n\t\twidth = String_Pixel_Width(concat_test) + name_width;\n\t\tmin_chars = 10;\n\n\t\twhile (width >= Width-8){\n\n\t\t\tmax_chars = strlen (msg);\n\t\t\tif (max_chars < min_chars) {\n\t\t\t\tmax_chars = min_chars;\n\t\t\t}\n\n\t\t\tTrim_Message (NULL, msg, min_chars, max_chars, 0);\n\n\t\t\tstrcpy (concat_test, msg);\n\t\t\tstrcat (concat_test, txt);\n\n\t\t\twidth = String_Pixel_Width(concat_test) + name_width;\n\t\t};\n\n\t\tdelete [] concat_test;\n\n\t\tstrcat (msg,txt);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Otherwise, trim off some characters from the beginning of the\n\t// message.  Trim off at least enough to leave room for the new text.\n\t// Trim from left to right to remove the minimum required text.\n\t//------------------------------------------------------------------------\n\telse {\n\t\tmin_chars = (strlen(msg) + strlen(txt)) - MaxChars;\n\t\tmax_chars = strlen(msg);\n\t\tif (max_chars < min_chars) {\n\t\t\tmax_chars = min_chars;\n\t\t}\n\t\tTrim_Message (NULL, msg, min_chars, max_chars, 0);\n\t\tstrcat (msg, txt);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Set the new timeout value for the message\n\t//------------------------------------------------------------------------\n\tif (timeout==-1) {\n\t\ttlabel->UserData1 = 0;\n\t}\n\telse {\n\t\ttlabel->UserData1 = TickCount + timeout;\n\t}\n\n\treturn (1);\n\n}\t// end of Concat_Message\n\n\n\n/***********************************************************************************************\n * MessageListClass::Set_Edit_Focus -- Give the gadget system focus to the edit box            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/19/96 4:41PM ST : Created                                                             *\n *=============================================================================================*/\nvoid MessageListClass::Set_Edit_Focus (void)\n{\n\tif (IsEdit) EditLabel->Set_Focus();\n}\n\n\n/***********************************************************************************************\n * MessageListClass::Has_Edit_Focus -- Find out if the edit box has the input focus            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    10/19/96 4:41PM ST : Created                                                             *\n *=============================================================================================*/\nbool MessageListClass::Has_Edit_Focus (void)\n{\n\tif (IsEdit){\n\t\treturn (EditLabel->Has_Focus());\n\t}else{\n\t\treturn(false);\n\t}\n}\n\n\n\n/***************************************************************************\n * MessageListClass::Add_Edit -- Adds editable string to message list      *\n *                                                                         *\n * INPUT:                                                                  *\n *    color\t\t\tcolor of edit message                                \t\t*\n *    style\t\t\tstyle of edit message                                \t\t*\n *    to\t\t\t\tstring: who to send to; NULL = none\t\t\t\t\t\t\t\t*\n *\t\tcursor\t\tcharacter to use as a cursor; 0 = none\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to new TextLabelClass                                          \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nTextLabelClass * MessageListClass::Add_Edit(PlayerColorType color,\n\tTextPrintType style, char * to, char cursor, int width)\n{\n\tint i;\n\tTextLabelClass * txtlabel;\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if we're already in \"edit\" mode\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tEditLabel->Set_Focus();\n\t\treturn(NULL);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRemove the top-most message if we're about to exceed the max allowed\n\t//------------------------------------------------------------------------\n\tif (AdjustEdit && ((Num_Messages() + 1) > MaxMessages)) {\n\t\ttxtlabel = MessageList;\n\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\tif (txtlabel->Text == MessageBuffers[i])\n\t\t\t\tBufferAvail[i] = 1;\n\t\t}\n\t\tdelete txtlabel;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If no 'to' field was passed in, ignore it\n\t//------------------------------------------------------------------------\n\tif (!to) {\n\t\tto = \"\";\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Set the cursor character\n\t//------------------------------------------------------------------------\n\tCursorChar = cursor;\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize the buffer positions; create a new text label object\n\t//------------------------------------------------------------------------\n\tmemset (EditBuf, 0, sizeof(EditBuf));\n\tstrcpy (EditBuf, to);\n\tOverflowBuf[0] = 0;\n\tEditCurPos = EditInitPos = strlen(to);\n\tEditLabel = new TextLabelClass (EditBuf, EditX, EditY,\n\t\t&ColorRemaps[color], style);\n\n\tWidth = width;\n\n\tif (EditLabel) {\n\t\tIsEdit = 1;\n\t\tEditLabel->Set_Focus();\n\t}\n\telse {\n\t\tIsEdit = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If the edit field appears over the message list, recompute the y-value\n\t// for all messages.  Also, adjust MaxMessages down by one, since there\n\t// is now one less slot available.\n\t//------------------------------------------------------------------------\n\tif (AdjustEdit) {\n\t\tCompute_Y();\n\t\tMaxMessages--;\n\t}\n\n\treturn(EditLabel);\n\n}\t// end of Add_Edit\n\n\n/***************************************************************************\n * MessageListClass::Remove_Edit -- removes the edit field                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/06/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Remove_Edit(void)\n{\n\t//------------------------------------------------------------------------\n\t// If the edit field is active, delete it\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\t\tIsEdit = 0;\n\t\tdelete EditLabel;\n\n\t\t//.....................................................................\n\t\t// If the edit field appears over the message list, recompute the\n\t\t// y-value for all messages.  Adjust MaxMessages back up, since there\n\t\t// is now a new available slot.\n\t\t//.....................................................................\n\t\tif (AdjustEdit) {\n\t\t\tCompute_Y();\n\t\t\tMaxMessages++;\n\t\t}\n\t}\n\n}\t// end if Remove_Edit\n\n\n/***************************************************************************\n * MessageListClass::Get_Edit_Buf -- gets edit buffer                      *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    ptr to edit buffer, minus the \"To:\" header                         \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nchar * MessageListClass::Get_Edit_Buf(void)\n{\n\treturn(EditBuf + EditInitPos);\n\n}\t// end of Get_Edit_Buf\n\n\n/***************************************************************************\n * MessageListClass::Set_Edit_Color -- sets color of edit gizmo            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcolor\t\tcolor to set edit label to\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Set_Edit_Color(PlayerColorType color)\n{\n\tif (IsEdit) {\n\t\tEditLabel->Color = &ColorRemaps[color];\n\t}\n\n}\t// end of Set_Edit_Color\n\n\n/***************************************************************************\n * MessageListClass::Manage -- Manages multiplayer messages                *\n *                                                                         *\n * If this routine returns TRUE, the caller should update the display.     *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    0 = no change has occurred, 1 = changed                            \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Manage (void)\n{\n\tTextLabelClass * txtlabel;\n\tTextLabelClass * next;\n\tint changed = 0;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tLoop through all messages\n\t//------------------------------------------------------------------------\n\ttxtlabel = MessageList;\n\twhile (txtlabel) {\n\n\t\t//.....................................................................\n\t\t//\tIf this message's time is up, remove it from the list\n\t\t//.....................................................................\n\t\tif (txtlabel->UserData1 != 0 && TickCount > txtlabel->UserData1) {\n\n\t\t\t//..................................................................\n\t\t\t//\tSave the next ptr in the list; remove this entry\n\t\t\t//..................................................................\n\t\t\tnext = (TextLabelClass *)txtlabel->Get_Next();\n\t\t\tMessageList = (TextLabelClass *)txtlabel->Remove();\n\t\t\tfor (i = 0; i < MAX_NUM_MESSAGES; i++) {\n\t\t\t\tif (txtlabel->Text == MessageBuffers[i]) {\n\t\t\t\t\tBufferAvail[i] = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdelete txtlabel;\n\t\t\tchanged = 1;\n\t\t\ttxtlabel = next;\n\t\t}\n\t\telse {\n\t\t\ttxtlabel = (TextLabelClass *)txtlabel->Get_Next();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf a changed has been made, recompute the y-coord of all messages\n\t//------------------------------------------------------------------------\n\tif (changed) {\n\t\tCompute_Y();\n\t}\n\n\treturn(changed);\n\n}\t// end of Manage\n\n\n/***************************************************************************\n * MessageListClass::Input -- Handles input for sending messages           *\n *                                                                         *\n * INPUT:                                                                  *\n *    input         key value to process                                 \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    1 = caller should redraw the message list (no need to complete     \t*\n *        refresh, though)                                                 *\n *    2 = caller should completely refresh the display.                  \t*\n *    3 = caller should send the edit message.                           \t*\n *        (sets 'input' to 0 if it processes it.)                          *\n *\t\t4 = caller should send the Overflow buffer\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Input(KeyNumType &input)\n{\n\tKeyASCIIType ascii;\n\tint retcode = 0;\n\tint numchars;\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if nothing to do.\n\t//------------------------------------------------------------------------\n\tif (input == KN_NONE) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLeave mouse events alone.\n\t//------------------------------------------------------------------------\n\tif ( (input & (~KN_RLSE_BIT))==KN_LMOUSE ||\n\t\t(input & (~KN_RLSE_BIT))==KN_RMOUSE) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're in 'edit mode', handle keys\n\t//------------------------------------------------------------------------\n\tif (IsEdit) {\n\n\n\t\tascii = (KeyASCIIType)(Keyboard->To_ASCII(input) & 0x00ff);\n\n#ifdef WIN32\n\t\t/*\n\t\t** Allow numeric keypad presses to map to ascii numbers\n\t\t*/\n\t\tif ((input & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {\n\n\t\t\tinput = (KeyNumType)(input & ~WWKEY_VK_BIT);\n\n\t\t} else {\n\t\t\t/*\n\t\t\t** Filter out all special keys except return, escape and backspace\n\t\t\t*/\n\t\t\tif ((!(input & WWKEY_VK_BIT) && !(input & KN_BUTTON)\n\t\t\t\t\t&& ascii >= ' ' && ascii <= 127)\n\t\t\t\t|| (input & 0xff)== (KN_RETURN & 0xff)\n\t\t\t\t|| (input & 0xff)== (KN_BACKSPACE & 0xff)\n\t\t\t\t|| (input & 0xff)== (KN_ESC & 0xff) ) {\n\n\t\t\t\t//ascii = (KeyASCIIType)(Keyboard->To_ASCII(input));\n\t\t\t} else {\n\t\t\t\tinput = KN_NONE;\n\t\t\t\treturn (0);\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\n\n\t\tswitch (ascii) {\n\t\t\t//..................................................................\n\t\t\t//\tESC = abort message\n\t\t\t//..................................................................\n\t\t\tcase KA_ESC & 0xff:\n\t\t\t\tRemove_Edit();\n\t\t\t\tretcode = 2;\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tRETURN = send the message.\n\t\t\t// Add a space to the end, in case another message gets concatenated\n\t\t\t// onto this one after we send it; then, they won't be mushed\n\t\t\t// together.\n\t\t\t//..................................................................\n\t\t\tcase KA_RETURN & 0xff:\n\t\t\t\tif (EditCurPos == EditInitPos) {\n\t\t\t\t\tretcode = 0;\n\t\t\t\t\tinput = KN_NONE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {\n\t\t\t\t\tEditBuf[EditCurPos] = ' ';\n\t\t\t\t\tEditCurPos++;\n\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t}\n\t\t\t\tRemove_Edit();\n\t\t\t\tretcode = 3;\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tBACKSPACE = remove a character\n\t\t\t//..................................................................\n\t\t\tcase KA_BACKSPACE & 0xff:\n\t\t\t\tif (EditCurPos > EditInitPos) {\n\t\t\t\t\tEditCurPos--;\n\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\tretcode = 2;\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tEditLabel->Set_Focus();\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// default: add a character.  Reserve the last buffer position for\n\t\t\t// null.  (EditCurPos - EditInitPos) is the buffer index # of the\n\t\t\t// next character, after the \"To:\" prefix.\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tEditLabel->Set_Focus();\n\t\t\t\tbool overflowed = false;\n\t\t\t\tif (ascii >= ' ' && ascii <= 127) {\n\t\t\t\t\tif ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {\n\n\t\t\t\t\t\tEditBuf[EditCurPos] = ascii;\n\t\t\t\t\t\tEditCurPos++;\n\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\tretcode = 1;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Verify that the additional character would not overrun the on screen edit box.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, EditLabel->Color, TBLACK, EditLabel->Style);\n\t\t\t\t\t\tint width = String_Pixel_Width(EditBuf);\n\t\t\t\t\t\tif (width >= Width-10) {\n\t\t\t\t\t\t\toverflowed = true;\n\t\t\t\t\t\t\tEditCurPos--;\n\t\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\t\tretcode = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If there's no room in the buffer, and overflow is enabled,\n\t\t\t\t\t// trim the extra characters off (from right to left, to\n\t\t\t\t\t// remove the max possible characters), and then add the new\n\t\t\t\t\t// character in.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\toverflowed = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (/*BGEnableOverflow &&*/ overflowed) {\n\t\t\t\t\t\tnumchars = Trim_Message (OverflowBuf, EditBuf + EditInitPos,\n\t\t\t\t\t\t\tOverflowStart,OverflowEnd, 1);\n\t\t\t\t\t\tEditCurPos -= numchars;\n\t\t\t\t\t\tEditBuf[EditCurPos] = ascii;\n\t\t\t\t\t\tEditCurPos++;\n\t\t\t\t\t\tEditBuf[EditCurPos] = 0;\n\t\t\t\t\t\tretcode = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinput = KN_NONE;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(retcode);\n\n}\t// end of Input\n\n\n/***************************************************************************\n * MessageListClass::Draw -- draws messages                                *\n *                                                                         *\n * INPUT:                                                                  *\n *    none                                                               \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Draw(void)\n{\n\tchar txt[2] = {0,0};\n\n\tif (IsEdit) {\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\t\tEditLabel->Draw_Me(true);\n\n\t\tif (CursorChar && (EditCurPos - EditInitPos) < (MaxChars - 1) && EditLabel->Has_Focus()) {\n\t\t\ttxt[0] = CursorChar;\n\t\t\tFancy_Text_Print(txt,\n\t\t\t\tEditLabel->X + String_Pixel_Width(EditLabel->Text),\n\t\t\t\tEditLabel->Y,\n\t\t\t\tEditLabel->Color,\n\t\t\t\tTBLACK,\n\t\t\t\tEditLabel->Style);\n\t\t}\n\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\t}\n\tif (MessageList) {\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tHide_Mouse();\n\t\t}\n\t\tMessageList->Draw_All();\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tShow_Mouse();\n\t\t}\n\t}\n\n}\t// end of Draw\n\n\n/***************************************************************************\n * MessageListClass::Num_Messages -- returns # messages in the list        *\n *                                                                         *\n * INPUT:                                                                  *\n *    none.                                                              \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    # of messages, including the edit field if it's above the messages\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Num_Messages(void)\n{\n\tGadgetClass * gadg;\n\tint num;\n\n\tnum = 0;\n\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tnum++;\n\t\t\tgadg = gadg->Get_Next();\n\t\t}\n\t}\n\n\tif (IsEdit && AdjustEdit) {\n\t\tnum++;\n\t}\n\n\treturn (num);\n\n}\t// end of Num_Messages\n\n\n/***************************************************************************\n * MessageListClass::Set_Width -- sets allowable width of messages         *\n *                                                                         *\n * INPUT:                                                                  *\n *    width      pixel width                                             \t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *    none.                                                              \t*\n *                                                                         *\n * WARNINGS:                                                               *\n *    none.                                                              \t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/26/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Set_Width(int width)\n{\n\tGadgetClass * gadg;\n\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\t((TextLabelClass *)gadg)->PixWidth = width;\n\t\t\tgadg = gadg->Get_Next();\n\t\t}\n\t}\n\n\tif (IsEdit) {\n\t\tEditLabel->PixWidth = width;\n\t}\n\n}\t// end of Set_Width\n\n\n/***************************************************************************\n * MessageListClass::Trim_Message -- trims chars off start of message      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tdest\t\t\t\tbuffer to store removed characters in; NULL = none\t\t*\n *\t\tsrc\t\t\t\ttext buffer to trim\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmin_chars\t\tmin # chars that must be trimmed off\t\t\t\t\t\t*\n *\t\tmax_chars\t\tmax # chars allowed to trim\t\t\t\t\t\t\t\t\t*\n *\t\tscandir\t\t\t0 = left-to-right, 1 = right-to-left\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# characters removed\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nint MessageListClass::Trim_Message(char * dest, char * src, int min_chars,\n\tint max_chars, int scandir)\n{\n\tint i;\n\tint len;\n\tint found;\n\n\t//------------------------------------------------------------------------\n\t// validate parameters\n\t//------------------------------------------------------------------------\n\tif (min_chars <= 0) {\n\t\treturn(0);\n\t}\n\n\tlen = strlen (src);\n\tif (max_chars > len) {\n\t\tmax_chars = len;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// find 1st available white space; if there is none, just trim off\n\t// 'min_chars' characters.  'i' will be the number of chars to trim.\n\t// The chars removed will include the white space.\n\t//------------------------------------------------------------------------\n\tfound = 0;\n\t//........................................................................\n\t// scan from left to right\n\t//........................................................................\n\tif (scandir == 0) {\n\t\tfor (i = min_chars; i <= max_chars; i++) {\n\t\t\tif (isspace(src[i - 1])) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t//........................................................................\n\t// scan from right to left\n\t//........................................................................\n\telse {\n\t\tfor (i = max_chars; i >= min_chars; i--) {\n\t\t\tif (isspace(src[i - 1])) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t//........................................................................\n\t// If no whitespace was found, just set 'i' to the min # characters\n\t//........................................................................\n\tif (!found) {\n\t\ti = min_chars;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Save trimmed characters in the dest buffer, if there is one\n\t//------------------------------------------------------------------------\n\tif (dest) {\n\t\tmemcpy (dest, src, i);\n\t\tdest[i] ='\\0';\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Shift characters over in the source buffer\n\t//------------------------------------------------------------------------\n\tmemmove (src, src + i, len - i + 1);\n\n\treturn (i);\n\n}\t// end of Trim_Message\n\n\n/***************************************************************************\n * MessageListClass::Compute_Y -- recomputes y-coord for all messages      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MessageListClass::Compute_Y(void)\n{\n\tGadgetClass * gadg;\n\tint y;\n\n\t//------------------------------------------------------------------------\n\t// If the editable message is attached to the message list, 'AdjustEdit'\n\t// will be set; so, adjust all y-values downward one line.  Otherwise,\n\t// the editable message has its own screen coordinates.\n\t//------------------------------------------------------------------------\n\tif (IsEdit && AdjustEdit) {\n\t\ty = MessageY + Height;\n\t}\n\telse {\n\t\ty = MessageY;\n\t}\n\tif (MessageList) {\n\t\tgadg = MessageList;\n\t\twhile (gadg) {\n\t\t\tgadg->Y = y;\n\t\t\tgadg = gadg->Get_Next();\n\t\t\ty += Height;\n\t\t}\n\t}\n\n}\t// end of Compute_Y\n\n\n/*************************** end of msglist.cpp ****************************/\n"
  },
  {
    "path": "REDALERT/MSGLIST.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/MSGLIST.H 2     3/04/97 2:53p Joe_bostic $ */\n/***************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : MSGLIST.H                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 05/22/95                                 *\n *                                                                         *\n *                  Last Update : May 22, 1995 [BRR]                       *\n *                                                                         *\n * Initializing:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Init(), giving it the coords of the upper-left corner to display\t*\n *   the messages, the coordinates to display the editable message, max # \t*\n *   messages allowed, max # chars per message, and the pixel height of \t*\n *   the font.  MaxChars should be less than or equal to the define \t\t\t*\n *   MAX_MESSAGE_LENGTH.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tDisplaying a message:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Add_Message(); the buffer you pass in is copied into a static\t\t*\n *   buffer in this class.  Each message is given a timeout; after this\t\t*\n *   time, the message is removed from the displayed list.\t\t\t\t\t\t*\n *   Each message also has a 2-byte ID, which can be used to identify the\n *   sender.\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Editing a message:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Call Add_Edit(), giving it the color & style to print in.  An \t\t\t*\n *   optional \"To xxx\" prefix is allowed.  The edit message can appear in \t*\n *   the message list itself (it's placed first), or at a separate screen \t*\n *   location, depending on the values passed to Init().\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tUpdating messages:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   The Input() routine passes new keys to the editable message; this \t\t*\n *   routine's return code tells the app whether to redraw the messages,\t*\n *   and whether to send it the edit message.  As the user types \t\t\t\t*\n *   characters into the edit field, if he overflows the max storage\t\t\t*\n *   for the edit field, the field is parsed & the first few words \t\t\t*\n *   removed; these words are put into the Overflow buffer, and the app\t\t*\n *   is told so; the app should send this buffer across to the destination.*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - MessageList is a gadget list of all current messages\t\t\t\t\t\t*\n * - MessageX & Y are the upper left corner of the 1st message\t\t\t\t\t*\n * - MaxMessages is the max # of messages allowed, including the editable \t*\n *   message; 0 = no limit.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - MaxChars is the max # of chars allowed per message\t\t\t\t\t\t\t*\n * - Height is the pixel height of a single line\t\t\t\t\t\t\t\t\t*\n * - EditLabel points to the textmessage gadget for the current editable\t*\n *   field.  EditBuf points to the char buffer being edited.  EditInitPos\t*\n *   & EditCurPos define buffer index positions.\t\t\t\t\t\t\t\t\t*\n * - EditSendAddress is the IPX Address to send the message to when RETURN\t*\n *   is pressed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * The low word in the UserData field in the TextLabelClass tells what the *\n * timeout for each message is (0 = none); the high byte of the UserData\t*\n * field is used for the text message ID.\t\t\t\t\t\t\t\t\t\t\t\t*\n * When a message's timeout expires, it's deleted.  When a new message\t\t*\n * is added, the top message is deleted if MPlayerMaxMessages is exceeded.\t*\n *                                                                         *\n * The Edit-able message is never deleted until ESC or RETURN is pressed.\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef MSGLIST_H\n#define MSGLIST_H\n\n//***************************************************************************\n// Defines\n//***************************************************************************\n//---------------------------------------------------------------------------\n//\tMax length of inter-player message buffers.  Messages.Init() should specify\n// a value <= this.  For editing messages, the \"to\" field length is added to\n// this length to generate the entire editable message length.  For displayed\n// messages, a \"From\" prefix length should be added to this value to generate\n// the entire max displayable message length.\n//---------------------------------------------------------------------------\n#define\tMAX_MESSAGE_LENGTH\t\t120\n\n//---------------------------------------------------------------------------\n// Max # of allowed messages at one time\n//---------------------------------------------------------------------------\n#define\tMAX_NUM_MESSAGES\t\t\t14\n\n//***************************************************************************\n// Forward declarations\n//***************************************************************************\nclass TextLabelClass;\n\n//***************************************************************************\n// Class declaration\n//***************************************************************************\nclass MessageListClass {\n\tpublic:\n\t\t//.....................................................................\n\t\t// Constructor/Destructor\n\t\t//.....................................................................\n\t\tMessageListClass (void);\n\t\t~MessageListClass ();\n\n\t\t//.....................................................................\n\t\t// Initialization\n\t\t//.....................................................................\n\t\tvoid Reset(void);\n\t\tvoid Init (int x, int y, int max_msg, int maxchars, int height,\n\t\t\tint edit_x, int edit_y, int overflow_on, int over_start,\n\t\t\tint over_end, int width = 640);\n\t\tTextLabelClass * Add_Message (char const * name, int id, char const * txt,\n\t\t\tPlayerColorType color, TextPrintType style, int timeout);\n\t\tint Concat_Message (char const * name, int id, char const * txt, int timeout);\n\n\t\t//.....................................................................\n\t\t// Message access utility routines\n\t\t//.....................................................................\n\t\tchar * Get_Message (int id);\n\t\tTextLabelClass * Get_Label (int id);\n\n\t\t//.....................................................................\n\t\t// Message-editing support routines\n\t\t//.....................................................................\n\t\tTextLabelClass * Add_Edit(PlayerColorType color, TextPrintType style,\n\t\t\tchar *to, char cursor = 0, int width = 640);\n\t\tvoid Remove_Edit (void);\n\t\tchar * Get_Edit_Buf (void);\n\t\tchar * Get_Overflow_Buf (void) {return (OverflowBuf);}\n\t\tvoid Clear_Overflow_Buf (void) {OverflowBuf[0] = 0;}\n\t\tint Is_Edit(void) {return (IsEdit);}\n\t\tvoid Set_Edit_Color(PlayerColorType color);\n\n\t\t//.....................................................................\n\t\t// Maintenance routines\n\t\t//.....................................................................\n\t\tint Manage (void);\n\t\tint Input (KeyNumType &input);\n\t\tvoid Draw(void);\n\t\tint Num_Messages(void);\n\t\tvoid Set_Width(int width);\n\t\tvoid Set_Edit_Focus(void);\n\t\tbool Has_Edit_Focus(void);\n\n\tprivate:\n\n\t\t//.....................................................................\n\t\t// Message parsing\n\t\t//.....................................................................\n\t\tint Trim_Message(char *dest, char *src, int min_chars, int max_chars,\n\t\t\tint scandir);\n\n\t\t//.....................................................................\n\t\t// Compute the y-coord of the message list\n\t\t//.....................................................................\n\t\tvoid Compute_Y(void);\n\n\t\t//.....................................................................\n\t\t// Private Data\n\t\t//.....................................................................\n\t\tTextLabelClass * MessageList;\t\t\t\t// list of messages\n\t\tint MessageX;\t\t\t\t\t\t\t\t\t// x-coord of upper-left\n\t\tint MessageY;\t\t\t\t\t\t\t\t\t// y-coord of upper-left\n\t\tint MaxMessages;\t\t\t\t\t\t\t\t// max messages allowed\n\t\tint MaxChars;\t\t\t\t\t\t\t\t\t// max allowed chars per message\n\t\tint Height;\t\t\t\t\t\t\t\t\t\t// height in pixels\n\n\t\t//.....................................................................\n\t\t// Data for the edit field: the edit field will either appear at\n\t\t// exact coordinates specified by the application, or it will appear\n\t\t// vertically above the other messages.\n\t\t//.....................................................................\n\t\tunsigned EnableOverflow\t: 1;\t\t\t\t\t// 1 = enable overflow feature\n\t\tunsigned IsEdit\t\t\t\t: 1;\t\t\t\t\t// 1 = there's an edit field\n\t\tunsigned AdjustEdit\t\t\t: 1;\t\t\t\t\t// 1 = edit field appears over msgs\n\t\tint EditX;\t\t\t\t\t\t\t\t\t\t// x-coord of edit field\n\t\tint EditY;\t\t\t\t\t\t\t\t\t\t// y-coord of edit field\n\t\tTextLabelClass *EditLabel;\t\t\t\t\t// ptr to current edit label\n\t\tchar EditBuf[MAX_MESSAGE_LENGTH + 30];\t// buffer for editable message\n\t\tchar OverflowBuf[MAX_MESSAGE_LENGTH + 30];\t// overflow area\n\t\tint EditCurPos;\t\t\t\t\t\t\t\t// current edit position\n\t\tint EditInitPos;\t\t\t\t\t\t\t\t// initial edit position\n\t\tchar CursorChar;\t\t\t\t\t\t\t\t// character to use a cursor\n\t\tint OverflowStart;\t\t\t\t\t\t\t// 1st index for overflow trimming\n\t\tint OverflowEnd;\t\t\t\t\t\t\t\t// last index for overflow trimming\n\t\tint Width;\t\t\t\t\t\t\t\t\t\t// Maximum width in pixels of editable string\n\n\t\t//.....................................................................\n\t\t// Buffers provided for messages.  They must be long enough for\n\t\t// both the message, and for the \"To\" prefix on edited messages, or\n\t\t// the \"Name:\" prefix on received messages.\n\t\t//.....................................................................\n\t\tchar MessageBuffers[MAX_NUM_MESSAGES][MAX_MESSAGE_LENGTH + 30];\n\t\tchar BufferAvail[MAX_NUM_MESSAGES];\n};\n\n#endif\n/**************************** end of msglist.h *****************************/\n\n"
  },
  {
    "path": "REDALERT/MiscAsm.cpp",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/*\n** \n**   Misc. assembly code moved from headers\n** \n** \n** \n** \n** \n*/\n\n#include \"FUNCTION.H\"\n\n\n\nextern \"C\" void __cdecl Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy)\n{\n\tmemcpy(dest, source, bytes_to_copy);\n}\t\t\t  \n\n\n/***********************************************************************************************\n * Distance -- Determines the lepton distance between two coordinates.                         *\n *                                                                                             *\n *    This routine is used to determine the distance between two coordinates. It uses the      *\n *    Dragon Strike method of distance determination and thus it is very fast.                 *\n *                                                                                             *\n * INPUT:   coord1   -- First coordinate.                                                      *\n *                                                                                             *\n *          coord2   -- Second coordinate.                                                     *\n *                                                                                             *\n * OUTPUT:  Returns the lepton distance between the two coordinates.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Distance_Coord(COORDINATE coord1, COORDINATE coord2)\n{\n\t__asm {\n\t\tmov\teax,[coord1]\n\t\tmov\tebx,[coord2]\n\t\tmov\tdx,ax\t\t\t\n\t\tsub\tdx,bx\t\t\t\n\t\tjg\tokx\t\t\t\t\n\t\tneg\tdx\t\t\t\t\n\t\tokx:\t\t\t\t\t\n\t\tshr\teax,16\t\t\t\n\t\tshr\tebx,16\t\t\t\n\t\tsub\tax,bx\t\t\t\n\t\tjg\toky\t\t\t\t\n\t\tneg\tax\t\t\t\t\noky:\t\t\t\t\t\n\t\tcmp\tax,dx\t\t\t\n\t\tjg\tok\t\t\t\t\n\t\txchg\tax,dx\t\t\t\nok:\t\t\t\t\t\t\n\t\tshr\tdx,1\t\t\t\t\n\t\tadd\tax,dx\n\t}\n}\t\t\t  \n\n\n\n\n/*\n;***************************************************************************\n;* DESIRED_FACING16 -- Converts coordinates into a facing number.          *\n;*                                                                         *\n;*      This converts coordinates into a desired facing number that ranges *\n;*      from 0 to 15 (0 equals North and going clockwise).                 *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0 to 255 but       *\n;*              accurate to 22.5 degree increments.                        *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/14/1991 JLB : Created.                                             *\n;*=========================================================================*\n*/\n\nlong __cdecl Desired_Facing16(long x1, long y1, long x2, long y2)\n{\n\tstatic const char _new_facing16[] = {\n\t\t3, 2, 4,-1, 1, 2,0,-1,\n\t\t13,14,12,-1,15,14,0,-1,\n\t\t5, 6, 4,-1, 7, 6,8,-1,\n\t\t11,10,12,-1, 9,10,8,-1\n\t};\n\n\t\n\t__asm {\t\t  \n\t\txor\tebx,ebx\t\t\t//; Index byte (built).\n\n\t\t//; Determine Y axis difference.\n\t\tmov\tedx,[y1]\n\t\tmov\tecx,[y2]\n\t\tsub\tedx,ecx\t\t\t//; DX = Y axis (signed).\n\t\tjns\tshort absy\n\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\tneg\tedx\t\t\t//; ABS(y)\nabsy:\n\n\t\t//; Determine X axis difference.\n\t\tshl\tebx,1\n\t\tmov\teax,[x1]\n\t\tmov\tecx,[x2]\n\t\tsub\tecx,eax\t\t\t//; CX = X axis (signed).\n\t\tjns\tshort absx\n\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\tneg\tecx\t\t\t//; ABS(x)\nabsx:\n\n\t\t//; Determine the greater axis.\n\t\tcmp\tecx,edx\n\t\tjb\tshort dxisbig\n\t\txchg\tecx,edx\ndxisbig:\n\t\trcl\tebx,1\t\t\t//; Y > X flag bit.\n\n\t\t//; Determine the closeness or farness of lesser axis.\n\t\tmov\teax,edx\n\t\tinc\teax\t\t\t//; Round up.\n\t\tshr\teax,1\n\t\tinc\teax\t\t\t//; Round up.\n\t\tshr\teax,1\t\t\t//; 1/4 of greater axis.\n\n\t\tcmp\tecx,eax\n\t\trcl\tebx,1\t\t\t//; Very close to major axis bit.\n\n\t\tsub\tedx,eax\n\t\tcmp\tedx,ecx\n\t\trcl\tebx,1\t\t\t//; Very far from major axis bit.\n\n\t\txor\teax,eax\n\t\tmov\tal,[_new_facing16+ebx]\n\n\t\t//; Normalize to 0..FF range.\n\t\tshl\teax,4\n\n//\t\tret\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/*\n;***************************************************************************\n;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution.        *\n;*                                                                         *\n;*    This is a desired facing algorithm that has a resolution of 0        *\n;*    through 255.                                                         *\n;*                                                                         *\n;* INPUT:   srcx,srcy   -- Source coordinate.                              *\n;*                                                                         *\n;*          dstx,dsty   -- Destination coordinate.                         *\n;*                                                                         *\n;* OUTPUT:  Returns with the desired facing to face the destination        *\n;*          coordinate from the position of the source coordinate.  North  *\n;*          is 0, East is 64, etc.                                         *\n;*                                                                         *\n;* WARNINGS:   This routine is slower than the other forms of desired      *\n;*             facing calculation.  Use this routine when accuracy is      *\n;*             required.                                                   *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   12/24/1991 JLB : Adapted.                                             *\n;*=========================================================================*/\n\nint __cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)\n{\n\t\n\t__asm {\n\t\t\txor\tebx,ebx\t\t\t//; Facing number.\n\n\t\t\t////; Determine absolute X delta and left/right direction.\n\t\t\tmov\tecx,[dstx]\n\t\t\tsub\tecx,[srcx]\n\t\t\tjge\tshort xnotneg\n\t\t\tneg\tecx\n\t\t\tmov\tebx,11000000b\t\t//; Set bit 7 and 6 for leftward.\nxnotneg:\n\n\t\t\t//; Determine absolute Y delta and top/bottom direction.\n\t\t\tmov\teax,[srcy]\n\t\t\tsub\teax,[dsty]\n\t\t\tjge\tshort ynotneg\n\t\t\txor\tebx,01000000b\t\t//; Complement bit 6 for downward.\n\t\t\tneg\teax\nynotneg:\n\n\t\t\t//; Set DX=64 for quadrants 0 and 2.\n\t\t\tmov\tedx,ebx\n\t\t\tand\tedx,01000000b\n\t\t\txor\tedx,01000000b\n\n\t\t\t//; Determine if the direction is closer to the Y axis and make sure that\n\t\t\t//; CX holds the larger of the two deltas.  This is in preparation for the\n\t\t\t//; divide.\n\t\t\tcmp\teax,ecx\n\t\t\tjb\tshort gotaxis\n\t\t\txchg\teax,ecx\n\t\t\txor\tedx,01000000b\t\t//; Closer to Y axis so make DX=64 for quad 0 and 2.\ngotaxis:\n\n\t\t\t//; If closer to the X axis then add 64 for quadrants 0 and 2.  If\n\t\t\t//; closer to the Y axis then add 64 for quadrants 1 and 3.  Determined\n\t\t\t//; add value is in DX and save on stack.\n\t\t\tpush\tedx\n\n\t\t\t//; Make sure that the division won't overflow.  Reduce precision until\n\t\t\t//; the larger number is less than 256 if it appears that an overflow\n\t\t\t//; will occur.  If the high byte of the divisor is not zero, then this\n\t\t\t//; guarantees no overflow, so just abort shift operation.\n\t\t\ttest\teax,0FFFFFF00h\n\t\t\tjnz\tshort nooverflow\nagain:\n\t\t\ttest\tecx,0FFFFFF00h\n\t\t\tjz\tshort nooverflow\n\t\t\tshr\tecx,1\n\t\t\tshr\teax,1\n\t\t\tjmp\tshort again\nnooverflow:\n\n\t\t\t//; Make sure that the division won't underflow (divide by zero).  If\n\t\t\t//; this would occur, then set the quotient to $FF and skip divide.\n\t\t\tor\tecx,ecx\n\t\t\tjnz\tshort nounderflow\n\t\t\tmov\teax,0FFFFFFFFh\n\t\t\tjmp\tshort divcomplete\n\n\t\t\t//; Derive a pseudo angle number for the octant.  The angle is based\n\t\t\t//; on $00 = angle matches long axis, $00 = angle matches $FF degrees.\nnounderflow:\n\t\t\txor\tedx,edx\n\t\t\tshld\tedx,eax,8\t//; shift high byte of eax into dl\n\t\t\tshl\teax,8\n\t\t\tdiv\tecx\ndivcomplete:\n\n\t\t\t//; Integrate the 5 most significant bits into the angle index.  If DX\n\t\t\t//; is not zero, then it is 64.  This means that the dividend must be negated\n\t\t\t//; before it is added into the final angle value.\n\t\t\tshr\teax,3\n\t\t\tpop\tedx\n\t\t\tor\tedx,edx\n\t\t\tje\tshort noneg\n\t\t\tdec\tedx\n\t\t\tneg\teax\nnoneg:\n\t\t\tadd\teax,edx\n\t\t\tadd\teax,ebx\n\t\t\tand\teax,0FFH\n//\t\t\tret\n\t}\n}\t\t \n\n\n\n\n\n\n\n\n\n\n\n\n/*\n\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING8.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing8 -- Determines facing to reach a position.             *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Desired_Facing8\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 8 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 3 = Is y2 < y1?\n; bit 2 = Is x2 < x1?\n; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 0 = Is the facing closer to a major axis?\n//NewFacing8\tDB\t1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4\n\n//\tCODESEG\n*/\n\n/*\n;***************************************************************************\n;* DESIRED_FACING8 -- Determines facing to reach a position.               *\n;*                                                                         *\n;*    This routine will return with the most desirable facing to reach     *\n;*    one position from another.  It is accurate to a resolution of 0 to   *\n;*    7.                                                                   *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0..255 with an     *\n;*              accuracy of 32 degree increments.                          *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   07/15/1991 JLB : Documented.                                          *\n;*   08/08/1991 JLB : Same position check.                                 *\n;*   08/14/1991 JLB : New algorithm                                        *\n;*   02/06/1995 BWG : Convert to 32-bit                                    *\n;*=========================================================================*\n*/\nint __cdecl Desired_Facing8(long x1, long y1, long x2, long y2)\n{\n\t\n\tstatic const char _new_facing8[] = {1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4};\n\t\n\t__asm {\n\t\t\n\t\txor\tebx,ebx\t\t\t//; Index byte (built).\n\n\t\t//; Determine Y axis difference.\n\t\tmov\tedx,[y1]\n\t\tmov\tecx,[y2]\n\t\tsub\tedx,ecx\t\t\t//; DX = Y axis (signed).\n\t\tjns\tshort absy\n\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\tneg\tedx\t\t\t//; ABS(y)\nabsy:\n\n\t\t//; Determine X axis difference.\n\t\tshl\tebx,1\n\t\tmov\teax,[x1]\n\t\tmov\tecx,[x2]\n\t\tsub\tecx,eax\t\t\t//; CX = X axis (signed).\n\t\tjns\tshort absx\n\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\tneg\tecx\t\t\t//; ABS(x)\nabsx:\n\n\t\t//; Determine the greater axis.\n\t\tcmp\tecx,edx\n\t\tjb\tshort dxisbig\n\t\txchg\tecx,edx\ndxisbig:\n\t\trcl\tebx,1\t\t\t//; Y > X flag bit.\n\n\t\t//; Determine the closeness or farness of lesser axis.\n\t\tmov\teax,edx\n\t\tinc\teax\t\t\t//; Round up.\n\t\tshr\teax,1\n\n\t\tcmp\tecx,eax\n\t\trcl\tebx,1\t\t\t//; Close to major axis bit.\n\n\t\txor\teax,eax\n\t\tmov\tal,[_new_facing8+ebx]\n\n\t\t//; Normalize to 0..FF range.\n\t\tshl\teax,5\n\n//\t\tret\n\n\t}\n\t\n}\n\n\n\n#if (0)\n\n/*\n\t; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/REDALERT/MiscAsm.cpp#139 $\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Support Library                          *\n;*                                                                         *\n;*                    File Name : FACING16.ASM                             *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : May 8, 1991                              *\n;*                                                                         *\n;*                  Last Update : February 6, 1995  [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   Desired_Facing16 -- Converts coordinates into a facing number.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\t C Desired_Facing16\t:NEAR\n;\tINCLUDE\t\"wwlib.i\"\n\n\tDATASEG\n\n; 16 direction desired facing lookup table.  Build the index according\n; to the following bits:\n;\n; bit 4 = Is y2 < y1?\n; bit 3 = Is x2 < x1?\n; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)?\n; bit 1 = Is the lesser absolute difference very close to zero?\n; bit 0 = Is the lesser absolute difference very close to the greater dist?\nNewFacing16\tDB\t 3, 2, 4,-1, 1, 2,0,-1\n\t\tDB\t13,14,12,-1,15,14,0,-1\n\t\tDB\t 5, 6, 4,-1, 7, 6,8,-1\n\t\tDB\t11,10,12,-1, 9,10,8,-1\n\n\tCODESEG\n\n;***************************************************************************\n;* DESIRED_FACING16 -- Converts coordinates into a facing number.          *\n;*                                                                         *\n;*      This converts coordinates into a desired facing number that ranges *\n;*      from 0 to 15 (0 equals North and going clockwise).                 *\n;*                                                                         *\n;* INPUT:       x1,y1   -- Position of origin point.                       *\n;*                                                                         *\n;*              x2,y2   -- Position of target.                             *\n;*                                                                         *\n;* OUTPUT:      Returns desired facing as a number from 0 to 255 but       *\n;*              accurate to 22.5 degree increments.                        *\n;*                                                                         *\n;* WARNINGS:    If the two coordinates are the same, then -1 will be       *\n;*              returned.  It is up to you to handle this case.            *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   08/14/1991 JLB : Created.                                             *\n;*=========================================================================*\n*/\nlong __cdecl Desired_Facing16(long x1, long y1, long x2, long y2)\n{\n\t\n\t__asm {\n\t\t\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t\t\t; Determine Y axis difference.\n\t\t\tmov\tedx,[y1]\n\t\t\tmov\tecx,[y2]\n\t\t\tsub\tedx,ecx\t\t\t//; DX = Y axis (signed).\n\t\t\tjns\tshort absy\n\t\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\t\tneg\tedx\t\t\t//; ABS(y)\nabsy:\n\n\t\t\t//; Determine X axis difference.\n\t\t\tshl\tebx,1\n\t\t\tmov\teax,[x1]\n\t\t\tmov\tecx,[x2]\n\t\t\tsub\tecx,eax\t\t\t//; CX = X axis (signed).\n\t\t\tjns\tshort absx\n\t\t\tinc\tebx\t\t\t//; Set the signed bit.\n\t\t\tneg\tecx\t\t\t//; ABS(x)\nabsx:\n\n\t\t\t//; Determine the greater axis.\n\t\t\tcmp\tecx,edx\n\t\t\tjb\tshort dxisbig\n\t\t\txchg\tecx,edx\ndxisbig:\n\t\t\trcl\tebx,1\t\t\t//; Y > X flag bit.\n\n\t\t\t//; Determine the closeness or farness of lesser axis.\n\t\t\tmov\teax,edx\n\t\t\tinc\teax\t\t\t//; Round up.\n\t\t\tshr\teax,1\n\t\t\tinc\teax\t\t\t//; Round up.\n\t\t\tshr\teax,1\t\t\t//; 1/4 of greater axis.\n\n\t\t\tcmp\tecx,eax\n\t\t\trcl\tebx,1\t\t\t//; Very close to major axis bit.\n\n\t\t\tsub\tedx,eax\n\t\t\tcmp\tedx,ecx\n\t\t\trcl\tebx,1\t\t\t//; Very far from major axis bit.\n\n\t\t\txor\teax,eax\n\t\t\tmov\tal,[NewFacing16+ebx]\n\n\t\t\t//; Normalize to 0..FF range.\n\t\t\tshl\teax,4\n\n//\t\t\tret\n\t}\n}\n\t\t\n\t\n\t\t\t  \n\t\n#if (0)\n\tPROC\tDesired_Facing16 C near\n\tUSES\tebx, ecx, edx\n\n\tARG\tx1:DWORD\n\tARG\ty1:DWORD\n\tARG\tx2:DWORD\n\tARG\ty2:DWORD\n\n\txor\tebx,ebx\t\t\t; Index byte (built).\n\n\t; Determine Y axis difference.\n\tmov\tedx,[y1]\n\tmov\tecx,[y2]\n\tsub\tedx,ecx\t\t\t; DX = Y axis (signed).\n\tjns\tshort ??absy\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tedx\t\t\t; ABS(y)\n??absy:\n\n\t; Determine X axis difference.\n\tshl\tebx,1\n\tmov\teax,[x1]\n\tmov\tecx,[x2]\n\tsub\tecx,eax\t\t\t; CX = X axis (signed).\n\tjns\tshort ??absx\n\tinc\tebx\t\t\t; Set the signed bit.\n\tneg\tecx\t\t\t; ABS(x)\n??absx:\n\n\t; Determine the greater axis.\n\tcmp\tecx,edx\n\tjb\tshort ??dxisbig\n\txchg\tecx,edx\n??dxisbig:\n\trcl\tebx,1\t\t\t; Y > X flag bit.\n\n\t; Determine the closeness or farness of lesser axis.\n\tmov\teax,edx\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\n\tinc\teax\t\t\t; Round up.\n\tshr\teax,1\t\t\t; 1/4 of greater axis.\n\n\tcmp\tecx,eax\n\trcl\tebx,1\t\t\t; Very close to major axis bit.\n\n\tsub\tedx,eax\n\tcmp\tedx,ecx\n\trcl\tebx,1\t\t\t; Very far from major axis bit.\n\n\txor\teax,eax\n\tmov\tal,[NewFacing16+ebx]\n\n\t; Normalize to 0..FF range.\n\tshl\teax,4\n\n\tret\n\n\tENDP\tDesired_Facing16\n\n\tEND\n#endif\n#endif\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/*\n;***********************************************************************************************\n;* Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number.                   *\n;*                                                                                             *\n;*    This utility function will convert cardinal numbers into a fixed point fraction. The     *\n;*    use of fixed point numbers occurs throughout the product -- since it is a convenient     *\n;*    tool. The fixed point number is based on the formula:                                    *\n;*                                                                                             *\n;*       result = cardinal / base                                                              *\n;*                                                                                             *\n;*    The accuracy of the fixed point number is limited to 1/65536 as the lowest and up to     *\n;*    65536 as the largest.                                                                    *\n;*                                                                                             *\n;* INPUT:   base     -- The key number to base the fraction about.                             *\n;*                                                                                             *\n;*          cardinal -- The other number (hey -- what do you call it?)                         *\n;*                                                                                             *\n;* OUTPUT:  Returns with the fixed point number of the \"cardinal\" parameter as it relates      *\n;*          to the \"base\" parameter.                                                           *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n\nunsigned int __cdecl Cardinal_To_Fixed(unsigned base, unsigned cardinal)\n{\n\t__asm {\n\t\t\n\t\t\t\tmov\teax, 0FFFFFFFFh\t//; establish default return value\n\n\t\t\t\tmov\tebx,[base]\n\t\t\t\tor\t\tebx, ebx\n\t\t\t\tjz\t\tretneg1\t\t//; if base==0, return 4294967295\n\n\t\t\t\tmov\teax,[cardinal]\t\t//; otherwise, return (cardinal*65536)/base\n\t\t\t\tshl\teax,16\n\t\t\t\txor\tedx,edx\n\t\t\t\tdiv\tebx\n\nretneg1:\n\t\t\t\t//ret\n\n\t\t  \n\t}\t\n}\n\n#if (0)\n\tPROC\tCardinal_To_Fixed C near\n\tUSES\tebx, edx\n\n\tARG\tbase:DWORD\n\tARG\tcardinal:DWORD\n\n\tmov\teax,0FFFFh\t\t; establish default return value\n\n\tmov\tebx,[base]\n\tor\tebx,ebx\n\tjz\tnear ??retneg1\t\t; if base==0, return 65535\n\n\tmov\teax,[cardinal]\t\t; otherwise, return (cardinal*256)/base\n\tshl\teax,8\n\txor\tedx,edx\n\tdiv\tebx\n\n??retneg1:\n\tret\n\n\tENDP\tCardinal_To_Fixed\n#endif\n\n/*\n;***********************************************************************************************\n;* Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number.                  *\n;*                                                                                             *\n;*    Use this routine to convert a fixed point number into a cardinal number.                 *\n;*                                                                                             *\n;* INPUT:   base     -- The base number that the original fixed point number was created from. *\n;*                                                                                             *\n;*          fixed    -- The fixed point number to convert.                                     *\n;*                                                                                             *\n;* OUTPUT:  Returns with the reconverted number.                                               *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   02/17/1995 BWG : Created.                                                                 *\n;*=============================================================================================*/\n\nunsigned int __cdecl Fixed_To_Cardinal(unsigned base, unsigned fixed)\n{\n//\tPROC\tFixed_To_Cardinal C near\n//\tUSES\tedx\n\n//\tARG\tbase:DWORD\n//\tARG\tfixed:DWORD\n\n\t__asm {\n\t\tmov\teax,[base]\n\t\tmul\t[fixed]\n\t\tadd\teax,08000h\t\t//; eax = (base * fixed) + 0x8000\n\n\t\tshr\teax,16\t\t\t//; return eax/65536\n\t\t//ret\n\t}\n\n\n#if (0)\n\tmov\teax,[base]\n\tmul\t[fixed]\n\tadd\teax,080h\t\t; eax = (base * fixed) + 0x80\n\n\ttest\teax,0FF000000h\t\t; if high byte set, return FFFF\n\tjnz\t??rneg1\n\tshr\teax,8\t\t\t; else, return eax/256\n\tret\n??rneg1\t:\n\tmov\teax,0FFFFh\t\t; establish default return value\n\tret\n\n\tENDP\tFixed_To_Cardinal\n\n\tEND\n#endif\n\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid __cdecl Set_Bit(void * array, int bit, int value)\n{\n\t__asm {\n\t\tmov\tecx, [bit]\n\t\tmov\teax, [value]\n\t\tmov\tesi, [array]\n\t\tmov\tebx,ecx\t\t\t\t\t\n\t\tshr\tebx,5\t\t\t\t\t\n\t\tand\tecx,01Fh\t\t\t\t\n\t\tbtr\t[esi+ebx*4],ecx\t\t\n\t\tor\teax,eax\t\t\t\t\t\n\t\tjz\tok\t\t\t\t\t\t\n\t\tbts\t[esi+ebx*4],ecx\t\t\nok:\n\t}\n}\n\n\nint __cdecl Get_Bit(void const * array, int bit)\n{\n\t__asm {\n\t\tmov\teax, [bit]\n\t\tmov\tesi, [array]\n\t\tmov\tebx,eax\t\t\t\t\t\n\t\tshr\tebx,5\t\t\t\t\t\n\t\tand\teax,01Fh\t\t\t\t\n\t\tbt\t[esi+ebx*4],eax\t\t\n\t\tsetc\tal\n\t}\n}\n\nint __cdecl First_True_Bit(void const * array)\n{\n\t__asm {\n\t\tmov\tesi, [array]\n\t\tmov\teax,-32\t\t\t\t\t\nagain:\t\t\t\t\t\t\t\n\t\tadd\teax,32\t\t\t\t\t\n\t\tmov\tebx,[esi]\t\t\t\t\n\t\tadd\tesi,4\t\t\t\t\t\n\t\tbsf\tebx,ebx\t\t\t\t\t\n\t\tjz\tagain\t\t\t\t\t\n\t\tadd\teax,ebx\n\t}\n}\n\n\nint __cdecl First_False_Bit(void const * array)\n{\n\t__asm {\n\t\t\n\t\tmov\tesi, [array]\n\t\tmov\teax,-32\t\t\t\t\t\nagain:\t\t\t\t\t\t\t\n\t\tadd\teax,32\t\t\t\t\t\n\t\tmov\tebx,[esi]\t\t\t\t\n\t\tnot\tebx\t\t\t\t\t\t\n\t\tadd\tesi,4\t\t\t\t\t\n\t\tbsf\tebx,ebx\t\t\t\t\t\n\t\tjz\tagain\t\t\t\t\t\n\t\tadd\teax,ebx\n\t}\n}\n\nint __cdecl Bound(int original, int min, int max)\n{\t\t\n\t__asm {\n\t\tmov\teax,[original]\n\t\tmov\tebx,[min]\n\t\tmov\tecx,[max]\n\t\tcmp\tebx,ecx\t\t\t\t\t\n\t\tjl\tokorder\t\t\t\t\t\n\t\txchg\tebx,ecx\t\t\t\t\t\nokorder: cmp\teax,ebx\t\t\n\t\tjg\tokmin\t\t\t\t\t\n\t\tmov\teax,ebx\t\t\t\t\t\nokmin: cmp\teax,ecx\t\t\t\n\t\tjl\tokmax\t\t\t\t\t\n\t\tmov\teax,ecx\t\t\t\t\t\nokmax:\n\t}\n}\n\n\n\n\n\n\n\n/*\n\nCELL __cdecl Coord_Cell(COORDINATE coord)\n{\n\t__asm {\n\t\tmov\teax, coord\n\t\tmov\tebx,eax\n\t\tshr\teax,010h\n\t\txor\tal,al\n\t\tshr\teax,2\n\t\tor\t\tal,bh\n\t}\n\n}\n\n\n\n*/\n\n\n\n\n\n/*\n;***********************************************************\n; SHAKE_SCREEN\n;\n; VOID Shake_Screen(int shakes);\n;\n; This routine shakes the screen the number of times indicated.\n;\n; Bounds Checking: None\n;\n;*\n*/ \nvoid __cdecl Shake_Screen(int shakes)\n{\n\t// PG_TO_FIX\t\n\t// Need a different solution for shaking the screen\n\tshakes;\n}\n\n\n\n#if (0)\nGLOBAL\tC Shake_Screen\t:NEAR\n\n\tCODESEG\n\n;***********************************************************\n; SHAKE_SCREEN\n;\n; VOID Shake_Screen(int shakes);\n;\n; This routine shakes the screen the number of times indicated.\n;\n; Bounds Checking: None\n;\n;*\n\tPROC\tShake_Screen C near\n\tUSES\tecx, edx\n\n\tARG\tshakes:DWORD\n ret\n\n\tmov\tecx,[shakes]\n\n;;; push es\n;;; mov ax,40h\n;;; mov es,ax\n;;; mov dx,[es:63h]\n;;; pop es\n\tmov\teax,[0463h]\t\t; get CRTC I/O port\n\tmov\tdx,ax\n\tadd\tdl,6\t\t\t; video status port\n\n??top_loop:\n\n??start_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace\n\n??end_retrace:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,01\t\t\t; top word of start address\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,040h\t\t\t; bottom word = 40 (140h)\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n??start_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace2\n\n??end_retrace2:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace2\n\n??start_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjz\t??start_retrace3\n\n??end_retrace3:\n\tin\tal,dx\n\ttest\tal,8\n\tjnz\t??end_retrace3\n\n\tcli\n\tsub\tdl,6\t\t\t; dx = 3B4H or 3D4H\n\n\tmov\tah,0\n\tmov\tal,0Ch\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\tdec\tdx\n\n\tmov\tah,0\n\tinc\tal\n\tout\tdx,al\n\txchg\tah,al\n\tinc\tdx\n\tout\tdx,al\n\txchg\tah,al\n\n\tsti\n\tadd\tdl,5\n\n\tloop\t??top_loop\n\n\tret\n\n\tENDP\tShake_Screen\n\n;***********************************************************\n\n\tEND\n\n#endif\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/*\n\n;***************************************************************************\n;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.  *\n;*                                                                         *\n;*    This routine is used to build a special fading table for C&C.  There *\n;*    are certain colors that get faded to and cannot be faded again.      *\n;*    With this rule, it is possible to draw a shadow multiple times and   *\n;*    not have it get any lighter or darker.                               *\n;*                                                                         *\n;* INPUT:   palette  -- Pointer to the 768 byte IBM palette to build from. *\n;*                                                                         *\n;*          dest     -- Pointer to the 256 byte remap table.               *\n;*                                                                         *\n;*          color    -- Color index of the color to \"fade to\".             *\n;*                                                                         *\n;*          frac     -- The fraction to fade to the specified color        *\n;*                                                                         *\n;* OUTPUT:  Returns with pointer to the remap table.                       *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*/\n\nvoid * __cdecl Conquer_Build_Fading_Table(void const *palette, void *dest, int color, int frac)\n{\t\n\t/*\n\tglobal C\tConquer_Build_Fading_Table : NEAR\n\tPROC\tConquer_Build_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\t\nALLOWED_COUNT\tEQU\t16\nALLOWED_START\tEQU\t256-ALLOWED_COUNT\n\t*/\n\n#define\tALLOWED_COUNT\t16\n#define\tALLOWED_START\t256-ALLOWED_COUNT\n\n\tint matchvalue = 0;\t//:DWORD\t; Last recorded match value.\n\tunsigned char targetred = 0;\t\t//BYTE\t\t; Target gun red.\n\tunsigned char targetgreen = 0;\t//BYTE\t\t; Target gun green.\n\tunsigned char targetblue = 0;\t\t//BYTE\t\t; Target gun blue.\n\tunsigned char idealred = 0;\t\t//BYTE\t\n\tunsigned char idealgreen = 0;\t\t//BYTE\t\n\tunsigned char idealblue = 0;\t\t//BYTE\t\n\tunsigned char matchcolor = 0;\t\t//:BYTE\t\t; Tentative match color.\n\n\t__asm {\n\t\n\t\t\tcld\n\n\t\t\t; If the source palette is NULL, then just return with current fading table pointer.\n\t\t\tcmp\t[palette],0\n\t\t\tje\tfini1\n\t\t\tcmp\t[dest],0\n\t\t\tje\tfini1\n\n\t\t\t; Fractions above 255 become 255.\n\t\t\tmov\teax,[frac]\n\t\t\tcmp\teax,0100h\n\t\t\tjb\tshort ok\n\t\t\tmov\t[frac],0FFh\n\t\tok:\n\n\t\t\t; Record the target gun values.\n\t\t\tmov\tesi,[palette]\n\t\t\tmov\tebx,[color]\n\t\t\tadd\tesi,ebx\n\t\t\tadd\tesi,ebx\n\t\t\tadd\tesi,ebx\n\t\t\tlodsb\n\t\t\tmov\t[targetred],al\n\t\t\tlodsb\n\t\t\tmov\t[targetgreen],al\n\t\t\tlodsb\n\t\t\tmov\t[targetblue],al\n\n\t\t\t; Main loop.\n\t\t\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t\t\t; Transparent black never gets remapped.\n\t\t\tmov\tedi,[dest]\n\t\t\tmov\t[edi],bl\n\t\t\tinc\tedi\n\n\t\t\t; EBX = source palette logical number (1..255).\n\t\t\t; EDI = running pointer into dest remap table.\n\t\tmainloop:\n\t\t\tinc\tebx\n\t\t\tmov\tesi,[palette]\n\t\t\tadd\tesi,ebx\n\t\t\tadd\tesi,ebx\n\t\t\tadd\tesi,ebx\n\n\t\t\tmov\tedx,[frac]\n\t\t\tshr\tedx,1\n\t\t\t; new = orig - ((orig-target) * fraction);\n\n\t\t\tlodsb\t\t\t\t; orig\n\t\t\tmov\tdh,al\t\t\t; preserve it for later.\n\t\t\tsub\tal,[targetred]\t\t; al = (orig-target)\n\t\t\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\t\t\tshl\teax,1\n\t\t\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\t\t\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\t\t\tlodsb\t\t\t\t; orig\n\t\t\tmov\tdh,al\t\t\t; preserve it for later.\n\t\t\tsub\tal,[targetgreen]\t; al = (orig-target)\n\t\t\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\t\t\tshl\teax,1\n\t\t\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\t\t\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\t\t\tlodsb\t\t\t\t; orig\n\t\t\tmov\tdh,al\t\t\t; preserve it for later.\n\t\t\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\t\t\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\t\t\tshl\teax,1\n\t\t\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\t\t\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t\t\t; Sweep through a limited set of existing colors to find the closest\n\t\t\t; matching color.\n\n\t\t\tmov\teax,[color]\n\t\t\tmov\t[matchcolor],al\t\t; Default color (self).\n\t\t\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\t\t\tmov\tecx,ALLOWED_COUNT\n\n\t\t\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\t\t\tadd\tesi,(ALLOWED_START)*3\n\n\t\t\t; BH = color index.\n\t\t\tmov\tbh,ALLOWED_START\n\t\tinnerloop:\n\n\t\t\txor\tedx,edx\t\t\t; Comparison value starts null.\n\n\t\t\t; Build the comparison value based on the sum of the differences of the color\n\t\t\t; guns squared.\n\t\t\tlodsb\n\t\t\tsub\tal,[idealred]\n\t\t\tmov\tah,al\n\t\t\timul\tah\n\t\t\tadd\tedx,eax\n\n\t\t\tlodsb\n\t\t\tsub\tal,[idealgreen]\n\t\t\tmov\tah,al\n\t\t\timul\tah\n\t\t\tadd\tedx,eax\n\n\t\t\tlodsb\n\t\t\tsub\tal,[idealblue]\n\t\t\tmov\tah,al\n\t\t\timul\tah\n\t\t\tadd\tedx,eax\n\t\t\tjz\tshort perfect\t\t; If perfect match found then quit early.\n\n\t\t\tcmp\tedx,[matchvalue]\n\t\t\tjae\tshort notclose\n\t\t\tmov\t[matchvalue],edx\t; Record new possible color.\n\t\t\tmov\t[matchcolor],bh\n\t\tnotclose:\n\t\t\tinc\tbh\t\t\t; Checking color index.\n\t\t\tloop\tinnerloop\n\t\t\tmov\tbh,[matchcolor]\n\t\tperfect:\n\t\t\tmov\t[matchcolor],bh\n\t\t\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t\t\t; When the loop exits, we have found the closest match.\n\t\t\tmov\tal,[matchcolor]\n\t\t\tstosb\n\t\t\tcmp\tebx,ALLOWED_START-1\n\t\t\tjne\tmainloop\n\n\t\t\t; Fill the remainder of the remap table with values\n\t\t\t; that will remap the color to itself.\n\t\t\tmov\tecx,ALLOWED_COUNT\n\t\tfillerloop:\n\t\t\tinc\tbl\n\t\t\tmov\tal,bl\n\t\t\tstosb\n\t\t\tloop\tfillerloop\n\n\t\tfini1:\n\t\t\tmov\tesi,[dest]\n\t\t\tmov\teax,esi\n\t\t\t\n\t\t\t//ret\n\t}\n}\n\n\n\n\n\n\nextern \"C\" long __cdecl Reverse_Long(long number)\n{\n\t__asm {\n\t\tmov\teax,dword ptr [number]\n\t\txchg\tal,ah\n\t\tror\teax,16\n\t\txchg\tal,ah\n\t}\n}\n\n\nextern \"C\" short __cdecl Reverse_Short(short number)\n{\n\t__asm {\n\t\tmov\tax,[number]\n\t\txchg\tah,al\n\t}\n}\t\n\n\n\nextern \"C\" long __cdecl Swap_Long(long number)\n{\n\t__asm {\n\t\tmov\teax,dword ptr [number]\n\t\tror\teax,16\n\t}\n}\n\n\n\n\n\n\n\n\n/*\n\n\n\n;***************************************************************************\n;* strtrim -- Remove the trailing white space from a string.               *\n;*                                                                         *\n;*    Use this routine to remove white space characters from the beginning *\n;*    and end of the string.        The string is modified in place by     *\n;*    this routine.                                                        *\n;*                                                                         *\n;* INPUT:   buffer   -- Pointer to the string to modify.                   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl strtrim(BYTE *buffer);\n\tglobal C\tstrtrim :NEAR\n\tPROC\tstrtrim C near\n\tUSES\tax, edi, esi\n\n\tARG\tbuffer:DWORD\t\t; Pointer to string to modify.\n*/\nvoid __cdecl strtrim(char *buffer)\n{\n\t__asm {\t\t  \n\t\t\tcmp\t[buffer],0\n\t\t\tje\tshort fini\n\n\t\t\t; Prepare for string scanning by loading pointers.\n\t\t\tcld\n\t\t\tmov\tesi,[buffer]\n\t\t\tmov\tedi,esi\n\n\t\t\t; Strip white space from the start of the string.\n\t\tlooper:\n\t\t\tlodsb\n\t\t\tcmp\tal,20h\t\t\t; Space\n\t\t\tje\tshort looper\n\t\t\tcmp\tal,9\t\t\t; TAB\n\t\t\tje\tshort looper\n\t\t\tstosb\n\n\t\t\t; Copy the rest of the string.\n\t\tgruntloop:\n\t\t\tlodsb\n\t\t\tstosb\n\t\t\tor\tal,al\n\t\t\tjnz\tshort gruntloop\n\t\t\tdec\tedi\n\t\t\t; Strip the white space from the end of the string.\n\t\tlooper2:\n\t\t\tmov\t[edi],al\n\t\t\tdec\tedi\n\t\t\tmov\tah,[edi]\n\t\t\tcmp\tah,20h\n\t\t\tje\tshort looper2\n\t\t\tcmp\tah,9\n\t\t\tje\tshort looper2\n\n\t\tfini:\n\t\t\t//ret\n\t}\n}\n\n\n/*\n;***************************************************************************\n;* Fat_Put_Pixel -- Draws a fat pixel.                                     *\n;*                                                                         *\n;*    Use this routine to draw a \"pixel\" that is bigger than 1 pixel       *\n;*    across.  This routine is faster than drawing a similar small shape   *\n;*    and faster than calling Fill_Rect.                                   *\n;*                                                                         *\n;* INPUT:   x,y       -- Screen coordinates to draw the pixel's upper      *\n;*                       left corner.                                      *\n;*                                                                         *\n;*          color     -- The color to render the pixel in.                 *\n;*                                                                         *\n;*          size      -- The number of pixels width of the big \"pixel\".    *\n;*                                                                         *\n;*          page      -- The pointer to a GraphicBuffer class or something *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/17/1994 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)\n\tglobal C\tFat_Put_Pixel:NEAR\n\tPROC\tFat_Put_Pixel C near\n\tUSES\teax, ebx, ecx, edx, edi, esi\n\n\tARG\tx:DWORD\t\t; X coordinate of upper left pixel corner.\n\tARG\ty:DWORD\t\t; Y coordinate of upper left pixel corner.\n\tARG\tcolor:DWORD\t; Color to use for the \"pixel\".\n\tARG\tsiz:DWORD\t; Size of \"pixel\" to plot (square).\n\tARG\tgpage:DWORD\t; graphic page address to plot onto\n*/\n\nvoid __cdecl Fat_Put_Pixel(int x, int y, int color, int siz, GraphicViewPortClass &gpage)\n{\n\t__asm {\n\t\t\t\t  \n\t\t\tcmp\t[siz],0\n\t\t\tje\tshort exit_label\n\n\t\t\t; Set EDI to point to start of logical page memory.\n\t\t\t;*===================================================================\n\t\t\t; Get the viewport information and put bytes per row in ecx\n\t\t\t;*===================================================================\n\t\t\tmov\tebx,[gpage]\t\t\t\t; get a pointer to viewport\n\t\t\tmov\tedi,[ebx]GraphicViewPortClass.Offset\t; get the correct offset\n\n\t\t\t; Verify the the Y pixel offset is legal.\n\t\t\tmov\teax,[y]\n\t\t\tcmp\teax,[ebx]GraphicViewPortClass.Height\t;YPIXEL_MAX\n\t\t\tjae\tshort exit_label\n\t\t\tmov\tecx,[ebx]GraphicViewPortClass.Width\n\t\t\tadd\tecx,[ebx]GraphicViewPortClass.XAdd\n\t\t\tadd\tecx,[ebx]GraphicViewPortClass.Pitch\n\t\t\tmul\tecx\n\t\t\tadd\tedi,eax\n\n\t\t\t; Verify the the X pixel offset is legal.\n\t\n\t\t\tmov\tedx,[ebx]GraphicViewPortClass.Width\n\t\t\tcmp\tedx,[x]\n\t\t\tmov\tedx,ecx\n\t\t\tjbe\tshort exit_label\n\t\t\tadd\tedi,[x]\n\n\t\t\t; Write the pixel to the screen.\n\t\t\tmov\tebx,[siz]\t\t; Copy of pixel size.\n\t\t\tsub\tedx,ebx\t\t\t; Modulo to reach start of next row.\n\t\t\tmov\teax,[color]\n\t\tagain:\n\t\t\tmov\tecx,ebx\n\t\t\trep stosb\n\t\t\tadd\tedi,edx\t\t\t; EDI points to start of next row.\n\t\t\tdec\t[siz]\n\t\t\tjnz\tshort again\n\n\t\texit_label:\n\t\t\t//ret\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n/*\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Westwood Library                         *\n;*                                                                         *\n;*                    File Name : CRC.ASM                                  *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : June 12, 1992                            *\n;*                                                                         *\n;*                  Last Update : February 10, 1995 [BWG]                  *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nGLOBAL\tC Calculate_CRC\t:NEAR\n\n\tCODESEG\n*/\n/*\nextern \"C\" long __cdecl Calculate_CRC(void *buffer, long length)\n{\n\tunsigned long crc;\n\n\tunsigned long local_length = (unsigned long) length;\n\n\t__asm {\n\t\t\t; Load pointer to data block.\n\t\t\tmov\t[crc],0\n\t\t\tpushad\n\t\t\tmov\tesi,[buffer]\n\t\t\tcld\n\n\t\t\t; Clear CRC to default (NULL) value.\n\t\t\txor\tebx,ebx\n\n\t\t\t//; Fetch the length of the data block to CRC.\n\t\t\t\n\t\t\tmov\tecx,[local_length]\n\n\t\t\tjecxz\tshort fini\n\n\t\t\t; Prepare the length counters.\n\t\t\tmov\tedx,ecx\n\t\t\tand\tdl,011b\n\t\t\tshr\tecx,2\n\n\t\t\t; Perform the bulk of the CRC scanning.\n\t\t\tjecxz\tshort remainder2\n\t\taccumloop:\n\t\t\tlodsd\n\t\t\trol\tebx,1\n\t\t\tadd\tebx,eax\n\t\t\tloop\taccumloop\n\n\t\t\t; Handle the remainder bytes.\n\t\tremainder2:\n\t\t\tor\tdl,dl\n\t\t\tjz\tshort fini\n\t\t\tmov\tecx,edx\n\t\t\txor\teax,eax\n\n\t\t\tand \tecx,0FFFFh\n\t\t\tpush\tecx\n\t\tnextbyte:\n\t\t\tlodsb\n\t\t\tror\teax,8\n\t\t\tloop\tnextbyte\n\t\t\tpop\tecx\n\t\t\tneg\tecx\n\t\t\tadd\tecx,4\n\t\t\tshl\tecx,3\n\t\t\tror\teax,cl\n\n\t\t;nextbyte:\n\t\t;\tshl\teax,8\n\t\t;\tlodsb\n\t\t;\tloop\tnextbyte\n\t\t\trol\tebx,1\n\t\t\tadd\tebx,eax\n\n\t\tfini:\n\t\t\tmov\t[crc],ebx\n\t\t\tpopad\n\t\t\tmov\teax,[crc]\n\t\t\t//ret\n\t}\n}\n\n\n*/\n\n\n\nextern \"C\" void __cdecl Set_Palette_Range(void *palette)\n{\n\tif (palette == NULL) {\n\t\treturn;\n\t}\n\n\tmemcpy(CurrentPalette, palette, 768);\n\tSet_DD_Palette(palette);\n}"
  },
  {
    "path": "REDALERT/NETDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/NETDLG.CPP 13    10/13/97 2:20p Steve_t $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                         \t\t\t\t\t\t  *\n *                 Project Name : Command & Conquer                        \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                    File Name : NETDLG.CPP                               \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Programmer : Bill Randolph                            \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                   Start Date : January 23, 1995                         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                  Last Update : December 12, 1995 [BRR]                  \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n *                                                                         \t\t\t\t\t\t  *\n * These routines establish & maintain peer-to-peer connections between this system\t\t\t\t  *\n * and all others in the game.  Each system finds out the IPX address of the others,\t\t\t  *\n * and forms a direct connection (IPXConnectionClass) to that system.  Systems are\t\t\t\t  *\n * found out via broadcast queries.  Every system broadcasts its queries, and every\t\t\t\t  *\n * system replies to queries it receives.  At the point when the game owner signals\t\t\t\t  *\n * 'OK', every system must know about all the other systems in the game.\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * How Bridges are handled:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * Currently, bridges are handled by specifying the destination IPX address of the\t\t\t\t  *\n * \"server\" (game owner's system) on the command-line.  This address is used to\t\t\t\t\t  *\n * derive a broadcast address to that destination network, and this system's queries\t\t\t  *\n * are broadcast over its network & the server's network; replies to the queries come\t\t\t  *\n * with each system's IPX address attached, so once we have the address, we can form\t\t\t  *\n * a connection with any system on the bridged net.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The flaw in this plan is that we can only cross one bridge.  If there are 3 nets\t\t\t\t  *\n * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts\t\t\t  *\n * will reach nets A & B, but not C.  The way to circumvent this (if it becomes a problem)\t  *\n * would be to have the server tell us what other systems are in its game, not each\t\t\t\t  *\n * individual player's system.  Thus, each system would find out about all the other systems\t  *\n * by interacting with the game's owner system (this would be more involved than what\t\t\t  *\n * I'm doing here).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Here's a list of all the different packets sent over the Global Channel:\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_QUERY_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t(no other data)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_ANSWER_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tgame owner's name\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tGameInfo:\t\t\tgame's version & open state\t\t\t\t\t\t\t\t\t  *\n *\tNET_QUERY_PLAYER\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of game we want players to respond for\t\t\t\t  *\n *\tNET_ANSWER_PLAYER\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tplayer's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tinfo about player\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * NET_CHAT_ANNOUNCE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tChat:\t\t\t\t\tunique id of the local node, so I can tell\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\tif this chat announcement is from myself\t\t\t\t\t  *\n *\tNET_QUERY_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of player wanting to join\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tplayer's requested house, color, & version range\t\t  *\n *\tNET_CONFIRM_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tPlayerInfo:\t\t\tapproves player's house & color\t\t\t\t\t\t\t\t  *\n *\tNET_REJECT_JOIN\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tReject.Why:\t\t\ttells why we got rejected\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_GAME_OPTIONS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tScenarioInfo:\t\tinfo about scenario\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_SIGN_OFF\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tName:\t\t\t\t\tname of player signing off\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_PING\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t(no other data)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\tNET_GO\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\tDelay:            value of one-way response time, in frames               *\n * \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                              \t\t\t\t\t\t  *\n *   Init_Network -- initializes network stuff                             \t\t\t\t\t\t  *\n *   Shutdown_Network -- shuts down network stuff                          \t\t\t\t\t\t  *\n *   Process_Global_Packet -- responds to remote queries                   \t\t\t\t\t\t  *\n *   Destroy_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Remote_Connect -- handles connecting this user to others              \t\t\t\t\t\t  *\n *   Net_Join_Dialog -- lets user join an existing game, or start a new one\t\t\t\t\t\t  *\n *   Request_To_Join -- Sends a JOIN request packet to game owner           \t \t\t\t\t\t  *\n *   Unjoin_Game -- Cancels joining a game                                                     *\n *   Send_Join_Queries -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Get_Join_Responses -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t  *\n *   Net_New_Dialog -- lets user start a new game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *   Get_NewGame_Responses -- processes packets for New Game dialog                            *\n *   Compute_Name_CRC -- computes CRC from char string                                         *\n *   Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n//\tWarning - Most disgusting cpp file of all time. ajw\n\n#include \"function.h\"\n\n//PG Stubs\nvoid Destroy_Connection(int, int) {}\nbool Process_Global_Packet(GlobalPacketType *, IPXAddressClass *) { return false; }\nbool Client_Remote_Connect(void) { return false; }\nbool Server_Remote_Connect(void) { return false; }\nbool Init_Network(void) { return false; }\nbool Remote_Connect(void) { return false; }\n\n#if (0)\t\t//PG\n\n\n#ifdef WIN32\n#ifdef WINSOCK_IPX\n#include\t\"WSProto.h\"\n#else\t//WINSOCK_IPX\n#include \"tcpip.h\"\n#endif\t//WINSOCK_IPX\n#include \"ccdde.h\"\n#else\t//WIN32\n#include \"fakesock.h\"\n#endif\t//WIN32\n\n#include <time.h>\n//#include <dos.h>\n\n//#include \"WolDebug.h\"\n\n#define SHOW_MONO\t\t0\n//#define OLDWAY\t\t\t1\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Connexion En Cours...\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_CONNECTING)\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_126x126 (char *file_name);\nbool Is_Mission_Aftermath (char *file_name);\nbool Is_Mission_Counterstrike (char *file_name);\nbool bSpecialAftermathScenario( const char* szScenarioDescription );\n#endif\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName );\n#endif\n#ifdef WOLAPI_INTEGRATION\n#include \"WolStrng.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n#include \"COORDA.h\"\n\n//---------------------------------------------------------------------------\n//\tThe possible states of the join-game dialog\n//---------------------------------------------------------------------------\ntypedef enum {\n\tJOIN_REJECTED = -1,\t\t// we've been rejected\n\tJOIN_NOTHING,\t\t\t\t// we're not trying to join a game\n\tJOIN_WAIT_CONFIRM,\t\t// we're asking to join, & waiting for confirmation\n\tJOIN_CONFIRMED,\t\t\t// we've been confirmed\n\tJOIN_GAME_START,\t\t\t// the game we've joined is starting\n\tJOIN_GAME_START_LOAD,\t// the game we've joined is starting; load saved game\n} JoinStateType;\n\n//---------------------------------------------------------------------------\n//\tThe possible return codes from Get_Join_Responses()\n//---------------------------------------------------------------------------\ntypedef enum {\n\tEV_NONE,\t\t\t\t\t\t\t// nothing happened\n\tEV_STATE_CHANGE,\t\t\t\t// Join dialog is in a new state\n\tEV_NEW_GAME,\t\t\t\t\t// a new game formed, or is now open\n\tEV_NEW_PLAYER,\t\t\t\t\t// a new player was detected\n\tEV_PLAYER_SIGNOFF,\t\t\t// a player has signed off\n\tEV_GAME_SIGNOFF,\t\t\t\t// a gamed owner has signed off\n\tEV_GAME_OPTIONS,\t\t\t\t// a game options packet was received\n\tEV_MESSAGE,\t\t\t\t\t\t// a message was received\n} JoinEventType;\n\n\n//---------------------------------------------------------------------------\n//\tThe possible reasons we're rejected from joining a game\n//---------------------------------------------------------------------------\ntypedef enum {\n\tREJECT_DUPLICATE_NAME,\t\t// player's name is a duplicate\n\tREJECT_GAME_FULL,\t\t\t\t// game is full\n\tREJECT_VERSION_TOO_OLD,\t\t// joiner's version is too old\n\tREJECT_VERSION_TOO_NEW,\t\t// joiner's version is too new\n\tREJECT_BY_OWNER,\t\t\t\t// game owner clicked \"reject\"\n\tREJECT_DISBANDED,\t\t\t\t// game was disbanded\n\tREJECT_MISMATCH,\t\t\t\t// \"rules.ini\" file mismatch.\n} RejectType;\n\n#ifdef ENGLISH\nchar const *EngMisStr[] = {\n\t\"Coastal Influence (Med)\",\n\t\"Middle Mayhem (Sm)\",\n\t\"Equal Opportunity (Sm)\",\n\t\"Marooned II (Med)\",\n\t\"Keep off the Grass (Sm)\",\n\t\"Isle of Fury (Lg)\",\n\t\"Ivory Wastelands (Sm)\",\n\t\"Shallow Grave (Med)\",\n\t\"North By Northwest (Lg)\",\n\t\"First Come, First Serve (Sm)\",\n\t\"Island Hoppers (Sm)\",\n\t\"Raraku (Lg)\",\n\t\"Central Conflict (Lg)\",\n\t\"Combat Alley (Med)\",\n\t\"Island Wars (Lg)\",\n\t\"Desolation (Lg)\",\n\t\"No Escape (Med)\",\n\t\"No Man's Land (Med)\",\n\t\"Normandy (Med)\",\n\t\"Pond Skirmish (Med)\",\n\t\"Ridge War (Med)\",\n\t\"A Path Beyond (Lg)\",\n\t\"Dugout Isle (Med)\",\n\t\"Treasure Isle (Med)\",\n\n\t\"Africa (Lg)\",\n\t\"Alaska Anarchy (Lg)\",\n\t\"All that Glitters... (Lg)\",\n\t\"Apre's Peace (Lg)\",\n\t\"Antartica (Lg)\",\n\t\"Armourgarden (Lg)\",\n\t\"Austraila (Med)\",\n\t\"Barrier to Entry (Lg)\",\n\t\"Bavarian Blast (Med)\",\n\t\"Be Shore (Med)\",\n\t\"Bearing Straits (Med)\",\n\t\"Blow Holes (Lg)\",\n\t\"Bonsai (Sm)\",\n\t\"Brother Stalin (Lg)\",\n\t\"Bullseye (Lg)\",\n\t\"C&C (Med)\",\n\t\"Camos Canyon (Med)\",\n\t\"Camos Coves (Lg)\",\n\t\"Camos Cross (Lg)\",\n\t\"Camos Crossing (Sm)\",\n\t\"Central Arena (Lg)\",\n\t\"Canyon River (Med)\",\n\t\"Crossroads (Sm)\",\n\t\"Czech Mate (Lg)\",\n\t\"Dday (Med)\",\n\t\"Disaster Central (Lg)\",\n\t\"Docklands (Med)\",\n\t\"East Coast (Med)\",\n\t\"Eastern Seaboard (Lg)\",\n\t\"Finger Lake (Lg)\",\n\t\"Fjords (Med)\",\n\t\"Floodlands (Lg)\",\n\t\"Forest under fire (Lg)\",\n\t\"Four Corners (Lg)\",\n\t\"Frostbit Fjords (Lg)\",\n\t\"Glenboig (Sm)\",\n\t\"Hell Frozen Over (Lg)\",\n\t\"India (Lg)\",\n\t\"Indirect Fire (Lg)\",\n\t\"Island Wars II (Lg)\",\n\t\"Italy (Lg)\",\n\t\"Kabalo (Lg)\",\n\t\"King of the Hills (Lg)\",\n\t\"Lake Divide (Med)\",\n\t\"Lakelands (Lg)\",\n\t\"Land Ladder (Lg)\",\n\t\"Lotsa Lakes (Lg)\",\n\t\"Lunar Battlefield (Lg Special)\",\n\t\"Malibu Fields (Med)\",\n\t\"Marshland (Med)\",\n\t\"MyLai Delta (Med)\",\n\t\"Natural Harbor (Med)\",\n\t\"No Way Out (Lg)\",\n\t\"Normandy Landing (Lg)\",\n\t\"Ore Wars (Med)\",\n\t\"Oz (Lg)\",\n\t\"Pilgrim Fathers II (Lg)\",\n\t\"Pip's Ice Tea (Med)\",\n\t\"Polar Panic (Lg)\",\n\t\"Ponds (Med)\",\n\t\"Putney (Lg)\",\n\t\"Return to Zion (Lg)\",\n\t\"Ring of Land (Lg)\",\n\t\"River Basin (Lg)\",\n\t\"River Delta (Med)\",\n\t\"River Islands (Med)\",\n\t\"River Maze (Sm)\",\n\t\"Rivers (Sm)\",\n\t\"Run the Gauntlet (Med)\",\n\t\"Scappa Flow (Lg)\",\n\t\"Siberian Slaughter (Lg)\",\n\t\"Sleepy Valley (Sm)\",\n\t\"Snake River (Lg)\",\n\t\"Snow Wars (Lg)\",\n\t\"Snowball fight (Lg)\",\n\t\"Snowy Island (Lg)\",\n\t\"So Near So Far (Sm)\",\n\t\"South America (Lg)\",\n\t\"Spring Line (Lg)\",\n\t\"Star (Lg)\",\n\t\"Straighter & Narrower (Sm)\",\n\t\"TerrainSpotting (Sm)\",\n\t\"The Bay (Lg)\",\n\t\"The Garden (Lg)\",\n\t\"The Great Lakes (Med)\",\n\t\"The Ice Arena (Lg)\",\n\t\"The Lake District (Lg)\",\n\t\"The Linked lands (Lg)\",\n\t\"The Mississippi (Med)\",\n\t\"The Sticky Bit (Lg)\",\n\t\"The Valley (Med)\",\n\t\"The Woods Today (Lg)\",\n\t\"Things to Come (Lg)\",\n\t\"Tiger Core (Sm)\",\n\t\"To the Core (Sm)\",\n\t\"Tournament Hills (Lg)\",\n\t\"Tropical Storm (Med)\",\n\t\"Tundra Trouble (Lg)\",\n\t\"Uk (Med)\",\n\t\"Undiscovered Country (Sm)\",\n\t\"United States (Med)\",\n\t\"Volcano (Sm)\",\n\t\"Wastelands (Lg)\",\n\t\"Water Works (Sm)\",\n\t\"World Map (Med)\",\n\t\"Zambezi (Lg)\",\n\n\t\"A Pattern of Islands (Lg 8 players)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\n\t\"Around the Rim (Sm 4 players)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\n\t\"Artic Wasteland (Mega 8 players)\",\n\t\"Badajoz (Med 4 players)\",\n\t\"Baptism of Fire (Lg 6 players)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\n\t\"Blue Lakes (Lg 8 players)\",\n\t\"Booby Traps (Mega 8 players)\",\n\t\"Bridgehead (Lg 6 players)\",\n\t\"Butterfly Bay (Lg 6 players)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",\n\t\"Circles of Death (Mega 8 players)\",\n\t\"Cold Front (Med 6 players)\",\n\t\"Cold Pass (Med 4 players)\",\n\t\"Combat Zones (Mega 8 players)\",\n\t\"Conflict Cove (Sm 4 players)\",\n\t\"Culloden Moor (Med 8 players)\",\n\t\"Damnation Alley (Mega 8 players)\",\n\t\"Death Valley (Mega 8 players)\",\n\t\"Deep Six (Mega 8 players)\",\n\t\"Destruction Derby (Mega 8 players)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\n\t\"Elysium (Sm 4 players)\",\n\t\"Equal Shares (Lg 4 players)\",\n\t\"Frost Bitten (Mega 8 players)\",\n\t\"Frozen Valley (Med 6 players)\",\n\t\"Gettysburg (Sm 4 players)\",\n\t\"Glacial Valley (Sm 4 players)\",\n\t\"Gold Coast (Med 6 players)\",\n\t\"Gold Rush (Lg 4 players)\",\n\t\"Habitat (Lg 4 players)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\n\t\"Hamburger Hill (Mega 8 players)\",\n\t\"Hastings (Sm 4 players)\",\n\t\"Hell's Pass (Med 6 players)\",\n\t\"Holy Grounds (Mega 8 players)\",\n\t\"Ice Bergs (Med 6 players)\",\n\t\"Ice Station (Lg 6 players)\",\n\t\"Ice Queen (Lg 4 players)\",\n\t\"In the Sun (Med 6 players)\",\n\t\"Innocents? (Mega 8 players)\",\n\t\"Islands (Med 8 players)\",\n\t\"Island Plateau (Lg 4 players)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\n\t\"Kananga (Med 6 players)\",\n\t\"King of the Hills Extreme (Mega 8 players)\",\n\t\"Lake Land (Lg 8 players)\",\n\t\"Land Locked (Lg 8 players)\",\n\t\"Lanes (Med 8 players)\",\n\t\"Leipzip (Sm 4 players)\",\n\t\"Meander (Lg 8 players)\",\n\t\"Mekong (Med 8 players)\",\n\t\"Middle Ground (Med 8 players)\",\n\t\"Naval Conquests (Mega 8 players)\",\n\t\"On your Marks (Med 4 players)\",\n\t\"Open Warfare (Mega 8 players)\",\n\t\"Ore Gardens (Lg 8 players)\",\n\t\"Potholes (Mega 8 players)\",\n\t\"Puddles (Med 4 players)\",\n\t\"Random Violence (Mega 8 players)\",\n\t\"Revenge (Med 8 players)\",\n\t\"Rias (Med 8 players)\",\n\t\"River Crossing (Sm 4 players)\",\n\t\"River Rampage (Mega 8 players)\",\n\t\"River Rapids (Lg 6 players)\",\n\t\"Rivers Wild (Mega 8 players)\",\n\t\"Rorkes Drift (Lg 4 players)\",\n\t\"Seaside (Med 4 players)\",\n\t\"Shades (Med 8 players)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\n\t\"Snow Garden (Sm 2 players)\",\n\t\"Stalingrad (Sm 4 players)\",\n\t\"Sticks & Stones (Med 4 players)\",\n\t\"Strathearn Valley (Lg 6 players)\",\n\t\"Super Bridgehead (Mega 8 players)\",\n\t\"Super Mekong (Mega 8 players)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\n\t\"Switch (Med 4 players)\",\n\t\"The Berg (Mega 8 players)\",\n\t\"The Boyne (Med 4 players)\",\n\t\"The Bulge (Sm 4 players)\",\n\t\"The Cauldron (Lg 6 players)\",\n\t\"The Finger (Lg 6 players)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\n\t\"The Keyes (Med 6 players)\",\n\t\"The Lakes (Med 8 players)\",\n\t\"The Neck (Med 6 players)\",\n\t\"The Web (Lg 6 players)\",\n\t\"To the Core (Lg 4 players)\",\n\t\"Trafalgar (Lg 4 players)\",\n\t\"Twin Rivers (Sm 4 players)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\n\t\"Waterfalls (Lg 8 players)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\n\t\"Water Werks (Mega 8 players)\",\n\t\"Warlord's Lake (Sm 4 players)\",\n\t\"Zama (Sm 4 players)\",\n\n\tNULL\n};\n#endif\n\n#ifdef GERMAN\nchar const *EngMisStr[] = {\n\n\t\"A Path Beyond (Lg)\",\t\t\t\t\t\"Weg ins Jenseits (Gr)\",\n\t\"Central Conflict (Lg)\",\t\t\t\t\"Der zentrale Konflikt (Gr)\",\n\t\"Coastal Influence (Med)\",\t\t\t\t\"Sturm an der Kste (Mit)\",\n\t\"Combat Alley (Med)\",\t\t\t\t\t\"Boulevard der Schlachten (Mit)\",\n\t\"Desolation (Lg)\",\t\t\t\t\t\t\"Verwstung (Gr)\",\n\t\"Dugout Isle (Med)\",\t\t\t\t\t\t\"Buddelschiff (Mit)\",\n\t\"Equal Opportunity (Sm)\",\t\t\t\t\"Gleiche Chancen (Kl)\",\n\t\"First Come, First Serve (Sm)\",\t\t\"Wer zuerst kommt... (Kl)\",\n\t\"Island Hoppers (Sm)\",\t\t\t\t\t\"Inselspringen (Kl)\",\n\t\"Island Wars (Lg)\",\t\t\t\t\t\t\"Der Krieg der Eilande (Gr)\",\n\t\"Isle of Fury (Lg)\",\t\t\t\t\t\t\"Insel des Zorns (Gr)\",\n\t\"Ivory Wastelands (Sm)\",\t\t\t\t\"Elfenbeinwste (Kl)\",\n\t\"Keep off the Grass (Sm)\",\t\t\t\t\"Rasen betreten verboten (Kl)\",\n\t\"Marooned II (Med)\",\t\t\t\t\t\t\"Gestrandet (Mit)\",\n\t\"Middle Mayhem (Sm)\",\t\t\t\t\t\"Mittelsmann (Kl)\",\n\t\"No Escape (Med)\",\t\t\t\t\t\t\"Kein Entrinnen (Mit)\",\n\t\"No Man's Land (Med)\",\t\t\t\t\t\"Niemandsland (Mit)\",\n\t\"Normandy (Med)\",\t\t\t\t\t\t\t\"Normandie (Mit)\",\n\t\"North By Northwest (Lg)\",\t\t\t\t\"Nord auf Nordwest (Gr)\",\n\t\"Pond Skirmish (Med)\",\t\t\t\t\t\"Teichgeplnkel (Mit)\",\n\t\"Raraku (Lg)\",\t\t\t\t\t\t\t\t\"Raraku (Gr)\",\n\t\"Ridge War (Med)\",\t\t\t\t\t\t\"Das Tal der Cyborgs (Mit)\",\n\t\"Shallow Grave (Med)\",\t\t\t\t\t\"Ein enges Grab (Mit)\",\n\t\"Treasure Isle (Med)\",\t\t\t\t\t\"Die Schatzinsel (Mit)\",\n\n\t\"Africa (Lg)\",\t\t\t\t\t\t\t\t\"Afrika (Gr)\",\n\t\"Alaska Anarchy (Lg)\",\t\t\t\t\t\"Anarchie in Alaska (Gr)\",\n\t\"All that Glitters... (Lg)\",\t\t\t\"Alles was glnzt... (Gr)\",\n\t\"Apre's Peace (Lg)\",\t\t\t\t\t\t\"Apres Frieden (Gr)\",\n\t\"Antartica (Lg)\",\t\t\t\t\t\t\t\"Antarktica (Gr)\",\n\t\"Armourgarden (Lg)\",\t\t\t\t\t\t\"Garten der Panzer (Gr)\",\n\t\"Austraila (Med)\",\t\t\t\t\t\t\"Koalaland (Mit)\",\n\t\"Barrier to Entry (Lg)\",\t\t\t\t\"Zutritt verboten (Gr)\",\n\t\"Bavarian Blast (Med)\",\t\t\t\t\t\"Bayrische Blasmusik (Mit)\",\n\t\"Be Shore (Med)\",\t\t\t\t\t\t\t\"Strandlufer (Mit)\",\n\t\"Bearing Straits (Med)\",\t\t\t\t\"Die Heringstrasse (Mit)\",\n\t\"Blow Holes (Lg)\",\t\t\t\t\t\t\"Lcheriger Kse (Gr)\",\n\t\"Bonsai (Sm)\",\t\t\t\t\t\t\t\t\"Bonsai (Kl)\",\n\t\"Brother Stalin (Lg)\",\t\t\t\t\t\"Brderchen Stalin (Gr)\",\n\t\"Bullseye (Lg)\",\t\t\t\t\t\t\t\"Bullseye (Gr)\",\n\t\"C&C (Med)\",\t\t\t\t\t\t\t\t\"C&C (Mit)\",\n\t\"Camos Canyon (Med)\",\t\t\t\t\t\"Camos-Canyon (Mit)\",\n\t\"Camos Coves (Lg)\",\t\t\t\t\t\t\"Camos-Grotte (Gr)\",\n\t\"Camos Cross (Lg)\",\t\t\t\t\t\t\"Camos-Kreuz (Gr)\",\n\t\"Camos Crossing (Sm)\",\t\t\t\t\t\"Camos-Kreuzweg (Kl)\",\n\t\"Central Arena (Lg)\",\t\t\t\t\t\"Spielplatz des Teufels (Gr)\",\n\t\"Canyon River (Med)\",\t\t\t\t\t\"Canyonfluss (Mit)\",\n\t\"Crossroads (Sm)\",\t\t\t\t\t\t\"Kreuzung (Kl)\",\n\t\"Czech Mate (Lg)\",\t\t\t\t\t\t\"Tschechische Erffnung (Gr)\",\n\t\"Dday (Med)\",\t\t\t\t\t\t\t\t\"D-Day (Mit)\",\n\t\"Disaster Central (Lg)\",\t\t\t\t\"Endstation Schweinebucht (Gr)\",\n\t\"Docklands (Med)\",\t\t\t\t\t\t\"Docklands (Mit)\",\n\t\"East Coast (Med)\",\t\t\t\t\t\t\"Ostkste (Mit)\",\n\t\"Eastern Seaboard (Lg)\",\t\t\t\t\"Die Passage nach Osten (Gr)\",\n\t\"Finger Lake (Lg)\",\t\t\t\t\t\t\"Fingersee (Gr)\",\n\t\"Fjords (Med)\",\t\t\t\t\t\t\t\"Fjorde (Mit)\",\n\t\"Floodlands (Lg)\",\t\t\t\t\t\t\"Land unter! (Gr)\",\n\t\"Forest under fire (Lg)\",\t\t   \t\"Waldsterben im Feuer (Gr)\",\n\t\"Four Corners (Lg)\",\t\t\t\t\t\t\"Viereck (Gr)\",\n\t\"Frostbit Fjords (Lg)\",\t\t\t\t\t\"Frostbeulenfjord (Gr)\",\n\t\"Glenboig (Sm)\",\t\t\t\t\t\t\t\"Glenboig (Kl)\",\n\t\"Hell Frozen Over (Lg)\",\t\t\t\t\"Winter in der Hlle (Gr)\",\n\t\"India (Lg)\",\t\t\t\t\t\t\t\t\"Indien (Gr)\",\n\t\"Indirect Fire (Lg)\",\t\t\t\t\t\"Indirekter Beschuss (Gr)\",\n\t\"Island Wars II (Lg)\",\t\t\t\t\t\"Krieg der Inseln (Gr)\",\n\t\"Italy (Lg)\",\t\t\t\t\t\t\t\t\"Italien (Gr)\",\n\t\"Kabalo (Lg)\",\t\t\t\t\t\t\t\t\"Kabalo (Gr)\",\n\t\"King of the Hills (Lg)\",\t\t\t\t\"Knig des Maulwurfshgels (Gr)\",\n\t\"Lake Divide (Med)\",\t\t\t\t\t\t\"Wasserscheide (Mit)\",\n\t\"Lakelands (Lg)\",\t\t\t\t\t\t\t\"Seenplatte (Gr)\",\n\t\"Land Ladder (Lg)\",\t\t\t\t\t\t\"Das Leiterspiel (Gr)\",\n\t\"Lotsa Lakes (Lg)\",\t\t\t\t\t\t\"Mehr Seen (Gr)\",\n\t\"Lunar Battlefield (Lg Special)\",\t\"Schlachtfeld Mond (Gr Spezial)\",\n\t\"Malibu Fields (Med)\",\t\t\t\t\t\"Malibu (Mit)\",\n\t\"Marshland (Med)\",\t\t\t\t\t\t\"Schlammschlacht (Mit)\",\n\t\"MyLai Delta (Med)\",\t\t\t\t\t\t\"Das Delta von My Lai (Mit)\",\n\t\"Natural Harbor (Med)\",\t\t\t\t\t\"Natrlicher Hafen (Mit)\",\n\t\"No Way Out (Lg)\",\t\t\t\t\t\t\"Kein Entkommen (Gr)\",\n\t\"Normandy Landing (Lg)\",\t\t\t\t\"Landung in der Normandie (Gr)\",\n\t\"Ore Wars (Med)\",\t\t\t\t\t\t\t\"Die Erz-Kriege (Mit)\",\n\t\"Oz (Lg)\",\t\t\t\t\t\t\t\t\t\"Das Land Oz (Gr)\",\n\t\"Pilgrim Fathers II (Lg)\",\t\t\t\t\"Die Grndervter (Gr)\",\n\t\"Pip's Ice Tea (Med)\",\t\t\t\t\t\"Pips Eistee (Mit)\",\n\t\"Polar Panic (Lg)\",\t\t\t\t\t\t\"Panik am Pol (Gr)\",\n\t\"Ponds (Med)\",\t\t\t\t\t\t\t\t\"Tmpelspringer (Mit)\",\n\t\"Putney (Lg)\",\t\t\t\t\t\t\t\t\"Putney (Gr)\",\n\t\"Return to Zion (Lg)\",\t\t\t\t\t\"Rckkehr nach Zion (Gr)\",\n\t\"Ring of Land (Lg)\",\t\t\t\t\t\t\"Der Landring (Gr)\",\n\t\"River Basin (Lg)\",\t\t\t\t\t\t\"Flusslauf (Gr)\",\n\t\"River Delta (Med)\",\t\t\t\t\t\t\"Flussdelta (Mit)\",\n\t\"River Islands (Med)\",\t\t\t\t\t\"Flussinsel (Mit)\",\n\t\"River Maze (Sm)\",\t\t\t\t\t\t\"Flussgewirr (Kl)\",\n\t\"Rivers (Sm)\",\t\t\t\t\t\t\t\t\"Flsse (Kl)\",\n\t\"Run the Gauntlet (Med)\",\t\t\t\t\"Spiessrutenlauf (Mit)\",\n\t\"Scappa Flow (Lg)\",\t\t\t\t\t\t\"Scapa Flow (Gr)\",\n\t\"Siberian Slaughter (Lg)\",\t\t\t\t\"Sibirisches Gemetzel (Gr)\",\n\t\"Sleepy Valley (Sm)\",\t\t\t\t\t\"Tal der Ahnungslosen (Kl)\",\n\t\"Snake River (Lg)\",\t\t\t\t\t\t\"Am Schlangenfluss (Gr)\",\n\t\"Snow Wars (Lg)\",\t\t\t\t\t\t\t\"Krieg der Flocken (Gr)\",\n\t\"Snowball fight (Lg)\",\t\t\t\t\t\"Schneeballschlacht (Gr)\",\n\t\"Snowy Island (Lg)\",\t\t\t\t\t\t\"Schneeinsel (Gr)\",\n\t\"So Near So Far (Sm)\",\t\t\t\t\t\"So nah und doch so fern (Kl)\",\n\t\"South America (Lg)\",\t\t\t\t\t\"Sdamerika (Gr)\",\n\t\"Spring Line (Lg)\",\t\t\t\t\t\t\"Frhlingsgefhle (Gr)\",\n\t\"Star (Lg)\",\t\t\t\t\t\t\t\t\"Stern (Gr)\",\n\t\"Straighter & Narrower (Sm)\",\t\t\t\"Enger & schmaler (Kl)\",\n\t\"TerrainSpotting (Sm)\",\t\t\t\t\t\"TerrainSpotting (Kl)\",\n\t\"The Bay (Lg)\",\t\t\t\t\t\t\t\"Die Bucht (Gr)\",\n\t\"The Garden (Lg)\",\t\t\t\t\t\t\"Der Garten (Gr)\",\n\t\"The Great Lakes (Med)\",\t\t\t\t\"Die Grossen Seen (Mit)\",\n\t\"The Ice Arena (Lg)\",\t\t\t\t\t\"Eisarena (Gr)\",\n\t\"The Lake District (Lg)\",\t\t\t\t\"Kalte Seenplatte (Gr)\",\n\t\"The Linked lands (Lg)\",\t\t\t\t\"Die verbundenen Lnder (Gr)\",\n\t\"The Mississippi (Med)\",\t\t\t\t\"Grsse von Tom Sawyer (Mit)\",\n\t\"The Sticky Bit (Lg)\",\t\t\t\t\t\"Der klebrige Teil (Gr)\",\n\t\"The Valley (Med)\",\t\t\t\t\t\t\"Das Tal (Mit)\",\n\t\"The Woods Today (Lg)\",\t\t\t\t\t\"Waldlufer (Gr)\",\n\t\"Things to Come (Lg)\",\t\t\t\t\t\"Was die Zukunft bringt (Gr)\",\n\t\"Tiger Core (Sm)\",\t\t\t\t\t\t\"Das Herz des Tigers (Kl)\",\n\t\"To the Core (Sm)\",\t\t\t\t\t\t\"Mitten ins Herz (Kl)\",\n\t\"Tournament Hills (Lg)\",\t\t\t\t\"Hgel der Entscheidung (Gr)\",\n\t\"Tropical Storm (Med)\",\t\t\t\t\t\"Tropenstrme (Mit)\",\n\t\"Tundra Trouble (Lg)\",\t\t\t\t\t\"Tauziehen in der Tundra (Gr)\",\n\t\"Uk (Med)\",\t\t\t\t\t\t\t\t\t\"GB (Mit)\",\n\t\"Undiscovered Country (Sm)\",\t\t\t\"Unentdecktes Land (Kl)\",\n\t\"United States (Med)\",\t\t\t\t\t\"US (Mit)\",\n\t\"Volcano (Sm)\",\t\t\t\t\t\t\t\"Vulkan (Kl)\",\n\t\"Wastelands (Lg)\",\t\t\t\t\t\t\"Wstenei (Gr)\",\n\t\"Water Works (Sm)\",\t\t\t\t\t\t\"Wasserwerke (Kl)\",\n\t\"World Map (Med)\",\t\t\t\t\t\t\"Weltkarte (Kl)\",\n\t\"Zambezi (Lg)\",\t\t\t\t\t\t\t\"Sambesi (Gr)\",\n\n//#if 0\n\t\"A Pattern of Islands (Lg 8 players)\",  \t\t \"Inselmuster (gross, 8 Spieler)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\t\t \"Arenatal (sehr gross, 8 Spieler)\",\n\t\"Around the Rim (Sm 4 players)\",\t\t\t\t\t \"Um die Kante (klein, 4 Spieler)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\t\t\t\t\t \"Asche zu Asche (gross, 6 Spieler)\",\n\t\"Artic Wasteland (Mega 8 players)\",\t\t\t\t \"Arktische Wste (sehr gross, 8 Spieler)\",\n\t\"Badajoz (Med 4 players)\",\t\t\t\t\t\t\t \"Badjoz (mittelgross, 4 Spieler)\",\n\t\"Baptism of Fire (Lg 6 players)\",\t\t\t\t \"Feuertaufe (gross, 6 Spieler)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\t\t\t \"Grosser Fisch im kleinen Teich (gross, 6 Spieler)\",\n\t\"Blue Lakes (Lg 8 players)\",\t\t\t\t\t\t \"Die blauen Seen (gross, 8 Spieler)\",\n\t\"Booby Traps (Mega 8 players)\",\t\t\t\t\t \"Vorsicht, Falle! (sehr gross, 8 Spieler)\",\n\t\"Bridgehead (Lg 6 players)\",\t\t\t\t\t\t \"Brckenkopf im Niemandsland (gross, 6 Spieler)\",\n\t\"Butterfly Bay (Lg 6 players)\",\t\t\t\t\t \"Schmetterlingsbucht (gross, 6 Spieler)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",  \"Zentraler Konflikt fr Knner (sehr gross, 8 Spieler)\",\n\t\"Circles of Death (Mega 8 players)\",\t\t\t \"Todeskreise (sehr gross, 8 Spieler)\",\n\t\"Cold Front (Med 6 players)\",\t\t\t\t\t\t \"Kaltfront ( mittelgross, 6 Spieler)\",\n\t\"Cold Pass (Med 4 players)\",\t\t\t\t\t\t \"Cooler Pass (mittelgross, 4 Spieler)\",\n\t\"Combat Zones (Mega 8 players)\",\t\t\t\t\t \"Kampfgebiete (sehr gross, 8 Spieler)\",\n\t\"Conflict Cove (Sm 4 players)\",\t\t\t\t\t \"Hhlenkonflikt (klein, 4 Spieler)\",\n\t\"Culloden Moor (Med 8 players)\",\t\t\t\t\t \"Culloden-Moor (mittelgross, 8 Spieler)\",\n\t\"Damnation Alley (Mega 8 players)\",\t\t\t\t \"Strasse der Verdammten (sehr gross, 8 Spieler)\",\n\t\"Death Valley (Mega 8 players)\",\t\t\t\t\t \"Tal des Todes (sehr gross, 8 Spieler)\",\n\t\"Deep Six (Mega 8 players)\",\t\t\t\t\t\t \"Tiefe Sechs (sehr gross, 8 Spieler)\",\n\t\"Destruction Derby (Mega 8 players)\",\t\t\t \"Destruction Derby (sehr gross, 8 Spieler)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\t \"Vergngliche Diamanten (sehr gross, 8 Spieler)\",\n\t\"Elysium (Sm 4 players)\",\t\t\t\t\t\t\t \"Elysium (klein, 4 Spieler)\",\n\t\"Equal Shares (Lg 4 players)\",\t\t\t\t\t \"Gleiche Anteile (gross, 4 Spieler)\",\n\t\"Frost Bitten (Mega 8 players)\",\t\t\t\t\t \"Frostbrand (sehr gross, 8 Spieler)\",\n\t\"Frozen Valley (Med 6 players)\",\t\t\t\t\t \"Eisiges Tal (mittelgross, 6 Spieler)\",\n\t\"Gettysburg (Sm 4 players)\",\t\t\t\t\t\t \"Gettysburg (klein, 4 Spieler)\",\n\t\"Glacial Valley (Sm 4 players)\",\t\t\t\t\t \"Gletschertal (klein, 4 Spieler)\",\n\t\"Gold Coast (Med 6 players)\",\t\t\t\t\t\t \"Goldkste (mittelgross, 6 Spieler)\",\n\t\"Gold Rush (Lg 4 players)\",\t\t\t\t\t\t \"Goldrausch (gross, 4 Spieler)\",\n\t\"Habitat (Lg 4 players)\",\t\t\t\t\t\t\t \"Habitat (gross, 4 Spieler)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\t\t\t\t \"Frostschutz fr die Hlle (klein, 4 Spieler)\",\n\t\"Hamburger Hill (Mega 8 players)\",\t\t\t\t \"Hamburger Hill (sehr gross, 8 Spieler)\",\n\t\"Hastings (Sm 4 players)\",\t\t\t\t\t\t\t \"Hastings (klein, 4 Spieler)\",\n\t\"Hell's Pass (Med 6 players)\",\t\t\t\t\t \"Hllenpass (mittelgross, 6 Spieler)\",\n\t\"Holy Grounds (Mega 8 players)\",\t\t\t\t\t \"Heiliger Boden (sehr gross, 8 Spieler)\",\n\t\"Ice Bergs (Med 6 players)\",\t\t\t\t\t\t \"Eisberge (mittelgross, 6 Spieler)\",\n\t\"Ice Station (Lg 6 players)\",\t\t\t\t\t\t \"Eisstation  (gross, 6 Spieler)\",\n\t\"Ice Queen (Lg 4 players)\",\t\t\t\t\t\t \"Eisknigin (gross, 4 Spieler)\",\n\t\"In the Sun (Med 6 players)\",\t\t\t\t\t\t \"Unter der Sonne (mittelgross, 6 Spieler)\",\n\t\"Innocents? (Mega 8 players)\",\t\t\t\t\t \"Unschuldig? Wer? (sehr gross, 8 Spieler)\",\n\t\"Islands (Med 8 players)\",\t\t\t\t\t\t\t \"Inseln im Nebel (mittelgross, 8 Spieler)\",\n\t\"Island Plateau (Lg 4 players)\",\t\t\t\t\t \"Inselplateau (gross, 4 Spieler)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\t\t \"Extremes Inselspringen (sehr gross, 8 Spieler)\",\n\t\"Kananga (Med 6 players)\",\t\t\t\t\t\t\t \"Kananga (mittelgross, 6 Spieler)\",\n\t\"King of the Hills Extreme (Mega 8 players)\", \"Knig des Maulwurfshgels (sehr gross, 8 Spieler)\",\n\t\"Lake Land (Lg 8 players)\",\t\t\t\t\t\t \"Seenland (gross, 8 Spieler)\",\n\t\"Land Locked (Lg 8 players)\",\t\t\t\t\t\t \"Das Verschlossene Land (gross, 8 Spieler)\",\n\t\"Lanes (Med 8 players)\",\t\t\t\t\t\t\t \"Gassenjungen (mittelgross, 8 Spieler)\",\n\t\"Leipzip (Sm 4 players)\",\t\t\t\t\t\t\t \"Leipzig (klein, 4 Spieler)\",\n\t\"Meander (Lg 8 players)\",\t\t\t\t\t\t\t \"Mander (gross, 8 Spieler)\",\n\t\"Mekong (Med 8 players)\",\t\t\t\t\t\t\t \"Mekong (mittelgross, 8 Spieler)\",\n\t\"Middle Ground (Med 8 players)\",\t\t\t\t\t \"Mittelsmann (mittelgross, 8 Spieler)\",\n\t\"Naval Conquests (Mega 8 players)\",\t\t\t\t \"Kommt zur Marine, haben sie gesagt (sehr gross, 8 Spieler)\",\n\t\"On your Marks (Med 4 players)\",\t\t\t\t\t \"Auf die Pltze (mittelgross, 4 Spieler)\",\n\t\"Open Warfare (Mega 8 players)\",\t\t\t\t\t \"Offener Schlagabtausch (sehr gross, 8 Spieler)\",\n\t\"Ore Gardens (Lg 8 players)\",\t\t\t\t\t\t \"Erzparadies (gross, 8 Spieler)\",\n\t\"Potholes (Mega 8 players)\",\t\t\t\t\t\t \"Schlaglcher (sehr gross, 8 Spieler)\",\n\t\"Puddles (Med 4 players)\",\t\t\t\t\t\t\t \"Pftzen (mittelgross, 4 Spieler)\",\n\t\"Random Violence (Mega 8 players)\",\t\t\t\t \"Unberechenbare Gewalt (sehr gross, 8 Spieler)\",\n\t\"Revenge (Med 8 players)\",\t\t\t\t\t\t\t \"Rache (mittelgross, 8 Spieler)\",\n\t\"Rias (Med 8 players)\",\t\t\t\t\t\t\t\t \"Kabul (mittelgross, 8 Spieler)\",\n\t\"River Crossing (Sm 4 players)\",\t\t\t\t\t \"Die Furt (klein, 4 Spieler)\",\n\t\"River Rampage (Mega 8 players)\",\t\t\t\t \"Flussfahrt (sehr gross, 8 Spieler)\",\n\t\"River Rapids (Lg 6 players)\",\t\t\t\t\t \"Stromschnellen (gross, 6 Spieler)\",\n\t\"Rivers Wild (Mega 8 players)\",\t\t\t\t\t \"Wildwasser (sehr gross, 8 Spieler)\",\n\t\"Rorkes Drift (Lg 4 players)\",\t\t\t\t\t \"Rorkes Drift (gross, 4 Spieler)\",\n\t\"Seaside (Med 4 players)\",\t\t\t\t\t\t\t \"Strandleben (mittelgross, 4 Spieler)\",\n\t\"Shades (Med 8 players)\",\t\t\t\t\t\t\t \"Schattenreich (mittelgross, 8 Spieler)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\t\t\t\t \"Schmugglerhhle (gross, 6 Spieler)\",\n\t\"Snow Garden (Sm 2 players)\",\t\t\t\t\t\t \"Schneegestber (klein, 2 Spieler)\",\n\t\"Stalingrad (Sm 4 players)\",\t\t\t\t\t\t \"Stalingrad (klein, 4 Spieler)\",\n\t\"Sticks & Stones (Med 4 players)\",\t\t\t\t \"Holz und Steine (mittelgross, 4 Spieler)\",\n\t\"Strathearn Valley (Lg 6 players)\",\t\t\t\t \"Das Tal von Strathearn (gross, 6 Spieler)\",\n\t\"Super Bridgehead (Mega 8 players)\",\t\t\t \"Super-Brckenkopf (sehr gross, 8 Spieler)\",\n\t\"Super Mekong (Mega 8 players)\",\t\t\t\t\t \"Super-Mekong (sehr gross, 8 Spieler)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\t\t\t \"Super-Erzparadies (sehr gross, 8 Spieler)\",\n\t\"Switch (Med 4 players)\",\t\t\t\t\t\t\t \"Schalter (mittelgross, 4 Spieler)\",\n\t\"The Berg (Mega 8 players)\",\t\t\t\t\t\t \"Der Berg (sehr gross, 8 Spieler)\",\n\t\"The Boyne (Med 4 players)\",\t\t\t\t\t\t \"Boyne (mittelgross, 4 Spieler)\",\n\t\"The Bulge (Sm 4 players)\",\t\t\t\t\t\t \"Die Wlbung (klein, 4 Spieler)\",\n\t\"The Cauldron (Lg 6 players)\",\t\t\t\t\t \"Der Kessel (gross, 6 Spieler)\",\n\t\"The Finger (Lg 6 players)\",\t\t\t\t\t\t \"Der Finger (gross, 6 Spieler)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\t\t \"Die Hgel haben Augen (sehr gross, 8 Spieler)\",\n\t\"The Keyes (Med 6 players)\",\t\t\t\t\t\t \"Ein Sumpf (mittelgross, 6 Spieler)\",\n\t\"The Lakes (Med 8 players)\",\t\t\t\t\t\t \"Die Seen (mittelgross, 8 Spieler)\",\n\t\"The Neck (Med 6 players)\",\t\t\t\t\t\t \"Der Hals (mittelgross, 6 Spieler)\",\n\t\"The Web (Lg 6 players)\",\t\t\t\t\t\t\t \"Das Netz (gross, 6 Spieler)\",\n\t\"To the Core (Lg 4 players)\",\t\t\t\t\t\t \"Mitten ins Herz (gross, 4 Spieler)\",\n\t\"Trafalgar (Lg 4 players)\",\t\t\t\t\t\t \"Trafalgar (gross, 4 Spieler)\",\n\t\"Twin Rivers (Sm 4 players)\",\t\t\t\t\t\t \"Zwillingsstrme (klein, 4 Spieler)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\t\t\t\t\t \"Die Umtumbo-Schlucht (gross, 4 Spieler)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\t \"Vorsicht, Lebensgefahr (sehr gross, 8 Spieler)\",\n\t\"Waterfalls (Lg 8 players)\",\t\t\t\t\t\t \"Wasserfall (gross, 8 Spieler)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\t\t\t \"Zu Besuch in Waterloo (gross, 6 Spieler)\",\n\t\"Water Werks (Mega 8 players)\",\t\t\t\t\t \"Wasserwerk (sehr gross, 8 Spieler)\",\n\t\"Warlord's Lake (Sm 4 players)\",\t\t\t\t\t \"Der See des Kriegsgottes (klein, 4 Spieler)\",\n\t\"Zama (Sm 4 players)\",\t\t\t\t\t\t\t\t \"Zama (klein, 4 Spieler)\",\n//#endif\n        NULL\n};\n#endif\n#ifdef FRENCH\nchar const *EngMisStr[] = {\n\n\t\"A Path Beyond (Lg)\",\t\t\t\t\t\"Le Passage (Max)\",\n\t\"Central Conflict (Lg)\",\t\t\t\t\"Conflit Central (Max)\",\n\t\"Coastal Influence (Med)\",\t\t\t\t\"Le Chant des Canons (Moy)\",\n\t\"Combat Alley (Med)\",\t\t\t\t\t\"Aux Armes! (Moy)\",\n\t\"Desolation (Lg)\",\t\t\t\t\t\t\"Dsolation (Max)\",\n\t\"Dugout Isle (Med)\",\t\t\t\t\t\t\"L'Ile Maudite (Moy)\",\n\t\"Equal Opportunity (Sm)\",\t\t\t\t\"A Chances Egales (Min)\",\n\t\"First Come, First Serve (Sm)\",\t\t\"La Loi du Plus Fort (Min)\",\n\t\"Island Hoppers (Sm)\",\t\t\t\t\t\"D'une Ile  l'autre (Min)\",\n\t\"Island Wars (Lg)\",\t\t\t\t\t\t\"Guerres Insulaires (Max)\",\n\t\"Isle of Fury (Lg)\",\t\t\t\t\t\t\"L'Ile de la Furie(Max)\",\n\t\"Ivory Wastelands (Sm)\",\t\t\t\t\"Terres d'Ivoire (Min)\",\n\t\"Keep off the Grass (Sm)\",\t\t\t\t\"Hors de mon Chemin (Min)\",\n\t\"Marooned II (Med)\",\t\t\t\t\t\t\"Isolement II (Moy)\",\n\t\"Middle Mayhem (Sm)\",\t\t\t\t\t\"Chaos Interne (Min)\",\n\t\"No Escape (Med)\",\t\t\t\t\t\t\"Le Pige (Moy)\",\n\t\"No Man's Land (Med)\",\t\t\t\t\t\"No Man's Land (Moy)\",\n\t\"Normandy (Med)\",\t\t\t\t\t\t\t\"Normandie (Moy)\",\n\t\"North By Northwest (Lg)\",\t\t\t\t\"Nord, Nord-Ouest (Max)\",\n\t\"Pond Skirmish (Med)\",\t\t\t\t\t\"Bain de Sang (Moy)\",\n\t\"Raraku (Lg)\",\t\t\t\t\t\t\t\t\"Raraku (Max)\",\n\t\"Ridge War (Med)\",\t\t\t\t\t\t\"Guerre au Sommet (Moy)\",\n\t\"Shallow Grave (Med)\",\t\t\t\t\t\"La Saveur de la Mort (Moy)\",\n\t\"Treasure Isle (Med)\",\t\t\t\t\t\"L'Ile au Trsor (Moy)\",\n\n\t\"Africa (Lg)\",\t\t\t\t\t\t\t\t\"Afrique (Max)\",\n\t\"Alaska Anarchy (Lg)\",\t\t\t\t\t\"Anarchie en Alaska (Max)\",\n\t\"All that Glitters... (Lg)\",\t\t\t\"Tout ce qui brille... (Max)\",\n\t\"Apre's Peace (Lg)\",\t\t\t\t\t\t\"Une Paix Durement Ngocie... (Max)\",\n\t\"Antartica (Lg)\",\t\t\t\t\t\t\t\"Antarctique (Max)\",\n\t\"Armourgarden (Lg)\",\t\t\t\t\t\t\"La Guerre des Blinds (Max)\",\n\t\"Austraila (Med)\",\t\t\t\t\t\t\"Australie (Moy)\",\n\t\"Barrier to Entry (Lg)\",\t\t\t\t\"Barrire  l'Entre (Max)\",\n\t\"Bavarian Blast (Med)\",\t\t\t\t\t\"Tonnerre Bavarois (Moy)\",\n\t\"Be Shore (Med)\",\t\t\t\t\t\t\t\"Plages Menaces (Moy)\",\n\t\"Bearing Straits (Med)\",\t\t\t\t\"Droit Devant ! (Moy)\",\n\t\"Blow Holes (Lg)\",\t\t\t\t\t\t\"Cratres (Max)\",\n\t\"Bonsai (Sm)\",\t\t\t\t\t\t\t\t\"Bonsa (Min)\",\n\t\"Brother Stalin (Lg)\",\t\t\t\t\t\"Frre Staline (Max)\",\n\t\"Bullseye (Lg)\",\t\t\t\t\t\t\t\"L'oeil du Taureau (Max)\",\n\t\"C&C (Med)\",\t\t\t\t\t\t\t\t\"C&C (Moy)\",\n\t\"Camos Canyon (Med)\",\t\t\t\t\t\"Le Canyon (Moy)\",\n\t\"Camos Coves (Lg)\",\t\t\t\t\t\t\"Criques (Max)\",\n\t\"Camos Cross (Lg)\",\t\t\t\t\t\t\"La Croix de Guerre (Max)\",\n\t\"Camos Crossing (Sm)\",\t\t\t\t\t\"La Croise des Chemins (Min)\",\n\t\"Central Arena (Lg)\",\t\t\t\t\t\"L'Arne Diabolique (Max)\",\n\t\"Canyon River (Med)\",\t\t\t\t\t\"Au Milieu Coule Une Rivire (Moy)\",\n\t\"Crossroads (Sm)\",\t\t\t\t\t\t\"Carrefours (Min)\",\n\t\"Czech Mate (Lg)\",\t\t\t\t\t\t\"Tchque et Mat (Max)\",\n\t\"Dday (Med)\",\t\t\t\t\t\t\t\t\"Le Jour J (Moy)\",\n\t\"Disaster Central (Lg)\",\t\t\t\t\"Dsastre Central (Max)\",\n\t\"Docklands (Med)\",\t\t\t\t\t\t\"L'Enfer des Docks (Moy)\",\n\t\"East Coast (Med)\",\t\t\t\t\t\t\"Cte Est (Moy)\",\n\t\"Eastern Seaboard (Lg)\",\t\t\t\t\"Rivages de l'Est (Max)\",\n\t\"Finger Lake (Lg)\",\t\t\t\t\t\t\"Le Lac de tous les Dangers (Max)\",\n\t\"Fjords (Med)\",\t\t\t\t\t\t\t\"Fjords (Moy)\",\n\t\"Floodlands (Lg)\",\t\t\t\t\t\t\"Campagne Lacustre (Max)\",\n\t\"Forest under fire (Lg)\",\t\t\t\t\"Fort en flammes (Max)\",\n\t\"Four Corners (Lg)\",\t\t\t\t\t\t\"4 Coins (Max)\",\n\t\"Frostbit Fjords (Lg)\",\t\t\t\t\t\"Fjords Gels (Max)\",\n\t\"Glenboig (Sm)\",\t\t\t\t\t\t\t\"Glenboig (Min)\",\n\t\"Hell Frozen Over (Lg)\",\t\t\t\t\"Enfer de Glace Max)\",\n\t\"India (Lg)\",\t\t\t\t\t\t\t\t\"Inde (Max)\",\n\t\"Indirect Fire (Lg)\",\t\t\t\t\t\"Attaque Indirecte (Max)\",\n\t\"Island Wars II (Lg)\",\t\t\t\t\t\"Guerres Insulaires II (Max)\",\n\t\"Italy (Lg)\",\t\t\t\t\t\t\t\t\"Italie (Max)\",\n\t\"Kabalo (Lg)\",\t\t\t\t\t\t\t\t\"Kabalo (Max)\",\n\t\"King of the Hills (Lg)\",\t\t\t\t\"Le Roi des Montagnes (Max)\",\n\t\"Lake Divide (Med)\",\t\t\t\t\t\t\"La Guerre du Lac (Moy)\",\n\t\"Lakelands (Lg)\",\t\t\t\t\t\t\t\"Terres Submerges (Max)\",\n\t\"Land Ladder (Lg)\",\t\t\t\t\t\t\"Jusqu'au Sommet (Max)\",\n\t\"Lotsa Lakes (Lg)\",\t\t\t\t\t\t\"Terres de Lacs (Max)\",\n\t\"Lunar Battlefield (Lg Special)\",\t\"Combat Lunaire (Max Spcial)\",\n\t\"Malibu Fields (Med)\",\t\t\t\t\t\"Les Champs de Malibu (Moy)\",\n\t\"Marshland (Med)\",\t\t\t\t\t\t\"Marcages (Moy)\",\n\t\"MyLai Delta (Med)\",\t\t\t\t\t\t\"Le Delta Mylai (Moy)\",\n\t\"Natural Harbor (Med)\",\t\t\t\t\t\"Port Naturel (Moy)\",\n\t\"No Way Out (Lg)\",\t\t\t\t\t\t\"Sans Issue (Max)\",\n\t\"Normandy Landing (Lg)\",\t\t\t\t\"Le Dbarquement (Max)\",\n\t\"Ore Wars (Med)\",\t\t\t\t\t\t\t\"La Guerre du Minerai (Moy)\",\n\t\"Oz (Lg)\",\t\t\t\t\t\t\t\t\t\"Oz (Max)\",\n\t\"Pilgrim Fathers II (Lg)\",\t\t\t\t\"Les Plerins 2 (Max)\",\n\t\"Pip's Ice Tea (Med)\",\t\t\t\t\t\"Les Tranches de Glace (Moy)\",\n\t\"Polar Panic (Lg)\",\t\t\t\t\t\t\"Panique Polaire (Max)\",\n\t\"Ponds (Med)\",\t\t\t\t\t\t\t\t\"Les Etangs (Moy)\",\n\t\"Putney (Lg)\",\t\t\t\t\t\t\t\t\"La Meilleure Dfense... (Max)\",\n\t\"Return to Zion (Lg)\",\t\t\t\t\t\"Retour  Sion (Max)\",\n\t\"Ring of Land (Lg)\",\t\t\t\t\t\t\"Le Cycle Infernal (Max)\",\n\t\"River Basin (Lg)\",\t\t\t\t\t\t\"Confrontation Navale (Max)\",\n\t\"River Delta (Med)\",\t\t\t\t\t\t\"Le Delta (Moy)\",\n\t\"River Islands (Med)\",\t\t\t\t\t\"Ctes  Surveiller de Prs (Moy)\",\n\t\"River Maze (Sm)\",\t\t\t\t\t\t\"Labyrinthe Fluvial (Min)\",\n\t\"Rivers (Sm)\",\t\t\t\t\t\t\t\t\"Rivires (Min)\",\n\t\"Run the Gauntlet (Med)\",\t\t\t\t\"Relevons le Dfi ! (Moy)\",\n\t\"Scappa Flow (Lg)\",\t\t\t\t\t\t\"Combats Sanglants (Max)\",\n\t\"Siberian Slaughter (Lg)\",\t\t\t\t\"Carnage Sibrien (Max)\",\n\t\"Sleepy Valley (Sm)\",\t\t\t\t\t\"La Valle Endormie (Min)\",\n\t\"Snake River (Lg)\",\t\t\t\t\t\t\"La Rivire aux Serpents (Max)\",\n\t\"Snow Wars (Lg)\",\t\t\t\t\t\t\t\"Guerres de Neige (Max)\",\n\t\"Snowball fight (Lg)\",\t\t\t\t\t\"Bataille de Boules de Neige (Max)\",\n\t\"Snowy Island (Lg)\",\t\t\t\t\t\t\"L'Ile sous la Neige (Max)\",\n\t\"So Near So Far (Sm)\",\t\t\t\t\t\"Si Loin, Si Proche (Min)\",\n\t\"South America (Lg)\",\t\t\t\t\t\"Amrique du Sud (Max)\",\n\t\"Spring Line (Lg)\",\t\t\t\t\t\t\"Ligne de Front (Max)\",\n\t\"Star (Lg)\",\t\t\t\t\t\t\t\t\"Etoile (Max)\",\n\t\"Straighter & Narrower (Sm)\",\t\t\t\"L'Entonnoir (Min)\",\n\t\"TerrainSpotting (Sm)\",\t\t\t\t\t\"TerrainSpotting (Min)\",\n\t\"The Bay (Lg)\",\t\t\t\t\t\t\t\"La Baie (Max)\",\n\t\"The Garden (Lg)\",\t\t\t\t\t\t\"Le Jardin (Max)\",\n\t\"The Great Lakes (Med)\",\t\t\t\t\"Les Grands Lacs (Moy)\",\n\t\"The Ice Arena (Lg)\",\t\t\t\t\t\"L'Arne de Glace (Max)\",\n\t\"The Lake District (Lg)\",\t\t\t\t\"Un Lac Imprenable (Max)\",\n\t\"The Linked lands (Lg)\",\t\t\t\t\"Passages  Gu (Max)\",\n\t\"The Mississippi (Med)\",\t\t\t\t\"Mississippi (Moy)\",\n\t\"The Sticky Bit (Lg)\",\t\t\t\t\t\"Marasme (Max)\",\n\t\"The Valley (Med)\",\t\t\t\t\t\t\"La Valle (Moy)\",\n\t\"The Woods Today (Lg)\",\t\t\t\t\t\"Aujoud'hui: la Mort ! (Max)\",\n\t\"Things to Come (Lg)\",\t\t\t\t\t\"Dnouement Incertain (Max)\",\n\t\"Tiger Core (Sm)\",\t\t\t\t\t\t\"Le Coeur du Tigre (Min)\",\n\t\"To the Core (Sm)\",\t\t\t\t\t\t\"Le Coeur du Conflit (Min)\",\n\t\"Tournament Hills (Lg)\",\t\t\t\t\"Combat en Altitude (Max)\",\n\t\"Tropical Storm (Med)\",\t\t\t\t\t\"Ouragan Tropical (Moy)\",\n\t\"Tundra Trouble (Lg)\",\t\t\t\t\t\"La Toundra (Max)\",\n\t\"Uk (Med)\",\t\t\t\t\t\t\t\t\t\"Royaume Uni (Moy)\",\n\t\"Undiscovered Country (Sm)\",\t\t\t\"Terre Inconnue (Min)\",\n\t\"United States (Med)\",\t\t\t\t\t\"Etats Unis (Moy)\",\n\t\"Volcano (Sm)\",\t\t\t\t\t\t\t\"Le Volcan (Min)\",\n\t\"Wastelands (Lg)\",\t\t\t\t\t\t\"Terres Dsoles (Max)\",\n\t\"Water Works (Sm)\",\t\t\t\t\t\t\"Jeux d'Eau (Min)\",\n\t\"World Map (Med)\",\t\t\t\t\t\t\"Carte du Monde (Moy)\",\n\t\"Zambezi (Lg)\",\t\t\t\t\t\t\t\"Zambze (Max)\",\n//#if 0\n\t\"A Pattern of Islands (Lg 8 players)\",\t\t\t \"Archipel (Max. 8 joueurs)\",\n\t\"Arena Valley Extreme (Mega 8 players)\",\t\t \"La Valle de l'arne (XL 8 joueurs)\",\n\t\"Around the Rim (Sm 4 players)\",\t\t\t\t\t \"Autour de la crte (Min. 4 joueurs)\",\n\t\"Ashes to Ashes (Lg 6 players)\",\t\t\t\t\t \"Rduit en cendres (Max. 6 joueurs)\",\n\t\"Artic Wasteland (Mega 8 players)\",\t\t\t\t \"Dsolation arctique (XL 8 joueurs)\",\n\t\"Badajoz (Med 4 players)\",\t\t\t\t\t\t\t \"Badjoz (Moy. 4 joueurs)\",\n\t\"Baptism of Fire (Lg 6 players)\",\t\t\t\t \"Baptme du feu (Max. 6 joueurs)\",\n\t\"Big Fish, Small Pond (Lg 6 players)\",\t\t\t \"Gros poisson, Min. Mare (Max. 6 joueurs)\",\n\t\"Blue Lakes (Lg 8 players)\",\t\t\t\t\t\t \"Lacs bleus (Max. 8 joueurs)\",\n\t\"Booby Traps (Mega 8 players)\",\t\t\t\t\t \"Piges (XL 8 joueurs)\",\n\t\"Bridgehead (Lg 6 players)\",\t\t\t\t\t\t \"Tte de pont (Max. 6 joueurs)\",\n\t\"Butterfly Bay (Lg 6 players)\",\t\t\t\t\t \"La baie du papillon (Max. 6 joueurs)\",\n\t\"Central Conflict Extreme (Mega 8 players)\",\t \"Conflit central extrme (XL 8 joueurs)\",\n\t\"Circles of Death (Mega 8 players)\",\t\t\t \"Les cercles de la mort (XL 8 joueurs)\",\n\t\"Cold Front (Med 6 players)\",\t\t\t\t\t\t \"Front froid ( Moy. 6 joueurs)\",\n\t\"Cold Pass (Med 4 players)\",\t\t\t\t\t\t \"La Passe Glace (Moy. 4 joueurs)\",\n\t\"Combat Zones (Mega 8 players)\",\t\t\t\t\t \"Zones de combat (XL 8 joueurs)\",\n\t\"Conflict Cove (Sm 4 players)\",\t\t\t\t\t \"La Crique du conflit (Min. 4 joueurs)\",\n\t\"Culloden Moor (Med 8 players)\",\t\t\t\t\t \"La Lande de Culloden (Moy. 8 joueurs)\",\n\t\"Damnation Alley (Mega 8 players)\",\t\t\t\t \"Le chemin de la damnation (XL 8 joueurs)\",\n\t\"Death Valley (Mega 8 players)\",\t\t\t\t\t \"La valle de la mort (XL 8 joueurs)\",\n\t\"Deep Six (Mega 8 players)\",\t\t\t\t\t\t \"Six de profondeur (XL 8 joueurs)\",\n\t\"Destruction Derby (Mega 8 players)\",\t\t\t \"Stock car (XL 8 joueurs)\",\n\t\"Diamonds Aren't Forever (Mega 8 players)\",\t \"Les diamants ne sont pas ternels (XL 8 joueurs)\",\n\t\"Elysium (Sm 4 players)\",\t\t\t\t\t\t\t \"Elyse (Min. 4 joueurs)\",\n\t\"Equal Shares (Lg 4 players)\",\t\t\t\t\t \"Parts gales (Max. 4 joueurs)\",\n\t\"Frost Bitten (Mega 8 players)\",\t\t\t\t\t \"Engelures (XL 8 joueurs)\",\n\t\"Frozen Valley (Med 6 players)\",\t\t\t\t\t \"La Valle glace (Moy. 6 joueurs)\",\n\t\"Gettysburg (Sm 4 players)\",\t\t\t\t\t\t \"Gettysburg (Min. 4 joueurs)\",\n\t\"Glacial Valley (Sm 4 players)\",\t\t\t\t\t \"Valle de glace (Min. 4 joueurs)\",\n\t\"Gold Coast (Med 6 players)\",\t\t\t\t\t\t \"La cte dore (Moy. 6 joueurs)\",\n\t\"Gold Rush (Lg 4 players)\",\t\t\t\t\t\t \"La rue vers l'or (Max. 4 joueurs)\",\n\t\"Habitat (Lg 4 players)\",\t\t\t\t\t\t\t \"Habitat (Max. 4 joueurs)\",\n\t\"Hades Frozen Over (Sm 4 players)\",\t\t\t\t \"Les enfers glacs (Min. 4 joueurs)\",\n\t\"Hamburger Hill (Mega 8 players)\",\t\t\t\t \"Hamburger Hill (XL 8 joueurs)\",\n\t\"Hastings (Sm 4 players)\",\t\t\t\t\t\t\t \"Hastings (Min. 4 joueurs)\",\n\t\"Hell's Pass (Med 6 players)\",\t\t\t\t\t \"La route de l'enfer (Moy. 6 joueurs)\",\n\t\"Holy Grounds (Mega 8 players)\",\t\t\t\t\t \"Terres saintes (XL 8 joueurs)\",\n\t\"Ice Bergs (Med 6 players)\",\t\t\t\t\t\t \"Icebergs (Moy. 6 joueurs)\",\n\t\"Ice Station (Lg 6 players)\",\t\t\t\t\t\t \"Station glace (Max. 6 joueurs)\",\n\t\"Ice Queen (Lg 4 players)\",\t\t\t\t\t\t \"Reine des glaces (Max. 4 joueurs)\",\n\t\"In the Sun (Med 6 players)\",\t\t\t\t\t\t \"Sous le soleil (Moy. 6 joueurs)\",\n\t\"Innocents? (Mega 8 players)\",\t\t\t\t\t \"Innocents ? (XL 8 joueurs)\",\n\t\"Islands (Med 8 players)\",\t\t\t\t\t\t\t \"Iles (Moy. 8 joueurs)\",\n\t\"Island Plateau (Lg 4 players)\",\t\t\t\t\t \"Plateau des les (Max. 4 joueurs)\",\n\t\"Island Wars Extreme (Mega 8 players)\",\t\t \"Guerres insulaires extrme (XL 8 joueurs)\",\n\t\"Kananga (Med 6 players)\",\t\t\t\t\t\t\t \"Kananga (Moy. 6 joueurs)\",\n\t\"King of the Hills Extreme (Mega 8 players)\", \"Roi des collines extrme (XL 8 joueurs)\",\n\t\"Lake Land (Lg 8 players)\",\t\t\t\t\t\t \"Paysage lacustre (Max. 8 joueurs)\",\n\t\"Land Locked (Lg 8 players)\",\t\t\t\t\t\t \"Enclave (Max. 8 joueurs)\",\n\t\"Lanes (Med 8 players)\",\t\t\t\t\t\t\t \"Le parcours du combattant (Moy. 8 joueurs)\",\n\t\"Leipzip (Sm 4 players)\",\t\t\t\t\t\t\t \"Leipzig (Min. 4 joueurs)\",\n\t\"Meander (Lg 8 players)\",\t\t\t\t\t\t\t \"Mandre (Max. 8 joueurs)\",\n\t\"Mekong (Med 8 players)\",\t\t\t\t\t\t\t \"Mkong (Moy. 8 joueurs)\",\n\t\"Middle Ground (Med 8 players)\",\t\t\t\t\t \"Plateau mdian (Moy. 8 joueurs)\",\n\t\"Naval Conquests (Mega 8 players)\",\t\t\t\t \"Conqutes navales (XL 8 joueurs)\",\n\t\"On your Marks (Med 4 players)\",\t\t\t\t\t \"A vos marques (Moy. 4 joueurs)\",\n\t\"Open Warfare (Mega 8 players)\",\t\t\t\t\t \"Guerre ouverte (XL 8 joueurs)\",\n\t\"Ore Gardens (Lg 8 players)\",\t\t\t\t\t\t \"Jardins de minerai (Max. 8 joueurs)\",\n\t\"Potholes (Mega 8 players)\",\t\t\t\t\t\t \"Nids de poules (XL 8 joueurs)\",\n\t\"Puddles (Med 4 players)\",\t\t\t\t\t\t\t \"Flaques (Moy. 4 joueurs)\",\n\t\"Random Violence (Mega 8 players)\",\t\t\t\t \"Violence alatoire (XL 8 joueurs)\",\n\t\"Revenge (Med 8 players)\",\t\t\t\t\t\t\t \"Vengeance (Moy. 8 joueurs)\",\n\t\"Rias (Med 8 players)\",\t\t\t\t\t\t\t\t \"Rias (Moy. 8 joueurs)\",\n\t\"River Crossing (Sm 4 players)\",\t\t\t\t\t \"Passage  gu (Min. 4 joueurs)\",\n\t\"River Rampage (Mega 8 players)\",\t\t\t\t \"Rivire dchane (XL 8 joueurs)\",\n\t\"River Rapids (Lg 6 players)\",\t\t\t\t\t \"Rapides (Max. 6 joueurs)\",\n\t\"Rivers Wild (Mega 8 players)\",\t\t\t\t\t \"Rivires sauvages (XL 8 joueurs)\",\n\t\"Rorkes Drift (Lg 4 players)\",\t\t\t\t\t \"L'Exode de Rorkes (Max. 4 joueurs)\",\n\t\"Seaside (Med 4 players)\",\t\t\t\t\t\t\t \"Cte (Moy. 4 joueurs)\",\n\t\"Shades (Med 8 players)\",\t\t\t\t\t\t\t \"Ombres (Moy. 8 joueurs)\",\n\t\"Smuggler's Cove (Lg 6 players)\",\t\t\t\t \"La Crique du contrebandier (Max. 6 joueurs)\",\n\t\"Snow Garden (Sm 2 players)\",\t\t\t\t\t\t \"Jardin de neige (Min. 2 joueurs)\",\n\t\"Stalingrad (Sm 4 players)\",\t\t\t\t\t\t \"Stalingrad (Min. 4 joueurs)\",\n\t\"Sticks & Stones (Med 4 players)\",\t\t\t\t \"Bton & Roches (Moy. 4 joueurs)\",\n\t\"Strathearn Valley (Lg 6 players)\",\t\t\t\t \"La Valle de Strathearn (Max. 6 joueurs)\",\n\t\"Super Bridgehead (Mega 8 players)\",\t\t\t \"Super tte de pont (XL 8 joueurs)\",\n\t\"Super Mekong (Mega 8 players)\",\t\t\t\t\t \"Super Mkong (XL 8 joueurs)\",\n\t\"Super Ore Gardens (Mega 8 players)\",\t\t\t \"Super jardin de minerai (XL 8 joueurs)\",\n\t\"Switch (Med 4 players)\",\t\t\t\t\t\t\t \"Permutation (Moy. 4 joueurs)\",\n\t\"The Berg (Mega 8 players)\",\t\t\t\t\t\t \"Le Berg (XL 8 joueurs)\",\n\t\"The Boyne (Med 4 players)\",\t\t\t\t\t\t \"Le Boyne (Moy. 4 joueurs)\",\n\t\"The Bulge (Sm 4 players)\",\t\t\t\t\t\t \"Le bombement (Min. 4 joueurs)\",\n\t\"The Cauldron (Lg 6 players)\",\t\t\t\t\t \"Le chaudron (Max. 6 joueurs)\",\n\t\"The Finger (Lg 6 players)\",\t\t\t\t\t\t \"Le doigt (Max. 6 joueurs)\",\n\t\"The Hills Have Eyes (Mega 8 players)\",\t\t \"Les collines ont des yeux (XL 8 joueurs)\",\n\t\"The Keyes (Med 6 players)\",\t\t\t\t\t\t \"Les Keyes (Moy. 6 joueurs)\",\n\t\"The Lakes (Med 8 players)\",\t\t\t\t\t\t \"Les lacs (Moy. 8 joueurs)\",\n\t\"The Neck (Med 6 players)\",\t\t\t\t\t\t \"Le goulot (Moy. 6 joueurs)\",\n\t\"The Web (Lg 6 players)\",\t\t\t\t\t\t\t \"La toile (Max. 6 joueurs)\",\n\t\"To the Core (Lg 4 players)\",\t\t\t\t\t\t \"Jusqu'au cour (Max. 4 joueurs)\",\n\t\"Trafalgar (Lg 4 players)\",\t\t\t\t\t\t \"Trafalgar (Max. 4 joueurs)\",\n\t\"Twin Rivers (Sm 4 players)\",\t\t\t\t\t\t \"Les deux rivires (Min. 4 joueurs)\",\n\t\"Umtumbo Gorge (Lg 4 players)\",\t\t\t\t\t \"La Gorge de Umtumbo (Max. 4 joueurs)\",\n\t\"Watch Your Step Extreme (Mega 8 players)\",\t \"Pas--pas extrme (XL 8 joueurs)\",\n\t\"Waterfalls (Lg 8 players)\",\t\t\t\t\t\t \"Chutes d'eau (Max. 8 joueurs)\",\n\t\"Waterloo Revisited (Lg 6 players)\",\t\t\t \"Waterloo II (Max. 6 joueurs)\",\n\t\"Water Werks (Mega 8 players)\",\t\t\t\t\t \"Jeux d'eau (XL 8 joueurs)\",\n\t\"Warlord's Lake (Sm 4 players)\",\t\t\t\t\t \"Le lac du guerrier (Min. 4 joueurs)\",\n\t\"Zama (Sm 4 players)\",\t\t\t\t\t\t\t\t \"Zama (Min. 4 joueurs)\",\n//#endif\n\tNULL\n};\n#endif\n\n\n/*\n******************************** Prototypes *********************************\n*/\nstatic int Net_Join_Dialog(void);\nstatic int Request_To_Join (char *playername, int join_index,\n\tHousesType house, PlayerColorType color);\nstatic void Unjoin_Game(char *namebuf,JoinStateType joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int game_index,\n\tint goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,\n\tint msg_len);\nstatic void Send_Join_Queries(int curgame, JoinStateType joinstate,\n\tint gamenow, int playernow, int chatnow, char *myname, int init = 0);\nstatic JoinEventType Get_Join_Responses(JoinStateType *joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int join_index,\n\tchar *my_name, RejectType *why);\nstatic int Net_New_Dialog(void);\nstatic JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,\n\tint *color_used);\nvoid Start_WWChat(ColorListClass *playerlist);\nint Update_WWChat(void);\n\n\n#define PCOLOR_BROWN\tPCOLOR_GREY\n\n\n/***********************************************************************************************\n * Init_Network -- initializes network stuff                               \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = Initialization OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Init_Network (void)\n{\n\tNetNumType net;\n\tNetNodeType node;\n#ifdef WINSOCK_IPX\n\tassert ( PacketTransport != NULL );\n#endif\t//WINSOCK_IPX\n\n\t//------------------------------------------------------------------------\n\t//\tThis call allocates all necessary queue buffers, allocates Real-mode\n\t//\tmemory, and commands IPX to start listening on the Global Channel.\n\t//------------------------------------------------------------------------\n\tif (!Ipx.Init()) {\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSet up the IPX manager to cross a bridge\n\t//------------------------------------------------------------------------\n\tif (Session.Type != GAME_INTERNET) {\n\t\tif (Session.IsBridge) {\n\t\t\tSession.BridgeNet.Get_Address(net,node);\n\t\t\tIpx.Set_Bridge(net);\n\t\t}\n\t}\n\n\treturn(true);\n\n}\t/* end of Init_Network */\n\n\n/***********************************************************************************************\n * Shutdown_Network -- shuts down network stuff                            \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Shutdown_Network (void)\n{\n//\n// Note: The thought behind this section of code was that if the program\n// terminates early, without an EventClass::EXIT event, it still needs to\n// tell the other systems that it's gone, so it would send a SIGN_OFF packet.\n// BUT, this causes a sync bug if the systems are running slow and this system\n// is running ahead of the others; it will send the NET_SIGN_OFF >>before<<\n// the other system execute their EventClass::EXIT event, and the other systems\n// will kill the connection at some random Frame # & turn my stuff over to\n// the computer possibly at different times.\n// BRR, 10/29/96\n//\n#if 0\n\t//------------------------------------------------------------------------\n\t// If the Players vector contains at least one name, send a sign-off\n\t// packet.  If 'Players' is empty, I have no name, so there's no point\n\t// in sending a sign-off.\n\t//------------------------------------------------------------------------\n\tif (Session.Players.Count()) {\n\t\t//.....................................................................\n\t\t// Build a sign-off packet & send it\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\tstrcpy (Session.GPacket.Name, Session.Players[0]->Name);\n\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t0, NULL);\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t0, NULL);\n\n\t\tif (Session.IsBridge\t&& !Winsock.Get_Connected()) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,\n\t\t\t\t&Session.BridgeNet);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,\n\t\t\t\t&Session.BridgeNet);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait for the packets to finish going out (or the Global Channel\n\t\t// times out)\n\t\t//.....................................................................\n\t\tfor (;;) {\n\t\t\tif (Ipx.Global_Num_Send()==0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tIpx.Service();\n\t\t}\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tIf I was in a game, I'm not now, so clear the game name\n\t//------------------------------------------------------------------------\n\tSession.GameName[0] = 0;\n\n}\t/* end of Shutdown_Network */\n\n\n/***********************************************************************************************\n * Process_Global_Packet -- responds to remote queries                     \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The only commands from other systems this routine responds to are NET_QUERY_GAME\t\t\t\t  *\n * and NET_QUERY_PLAYER.  The other commands are too context-specific to be able\t\t\t\t\t  *\n * to handle here, such as joining the game or signing off; but this routine handles\t\t\t  *\n * the majority of the program's needs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tpacket\t\tptr to packet to process\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\taddress\t\tsource address of sender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = packet was processed, false = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tSession.GameName must have been filled in before this function can be called.\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/15/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)\n{\n\tGlobalPacketType mypacket;\n\n\t//------------------------------------------------------------------------\n\t// If our Players vector is empty, just return.\n\t//------------------------------------------------------------------------\n\tif (Session.Players.Count()==0) {\n\t\treturn (true);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAnother system asking what game this is\n\t//------------------------------------------------------------------------\n\tif (packet->Command==NET_QUERY_GAME && Session.NetStealth==0) {\n\n\t\t//.....................................................................\n\t\t//\tIf the game is closed, let every player respond, and let the sender of\n\t\t//\tthe query sort it all out.  This way, if the game's host exits the game,\n\t\t//\tthe game still shows up on other players' dialogs.\n\t\t//\tIf the game is open, only the game owner may respond.\n\t\t//.....................................................................\n\t\tif (strlen(Session.GameName) > 0 && ((!Session.NetOpen) ||\n\t\t\t(Session.NetOpen &&\n\t\t\t\t!strcmp(Session.Players[0]->Name,Session.GameName)))) {\n\n\t\t\tmemset (&mypacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tmypacket.Command = NET_ANSWER_GAME;\n\t\t\tstrcpy(mypacket.Name, Session.GameName);\n\t\t\tmypacket.GameInfo.IsOpen = Session.NetOpen;\n\n\t\t\tIpx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,\n\t\t\t\taddress);\n\t\t}\n\t\treturn(true);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tAnother system asking what player I am\n\t//------------------------------------------------------------------------\n\telse if (packet->Command==NET_QUERY_PLAYER &&\n\t\t!strcmp (packet->Name, Session.GameName) &&\n\t\t\t(strlen(Session.GameName) > 0) && Session.NetStealth==0) {\n\n\t\tmemset (&mypacket, 0, sizeof(GlobalPacketType));\t\t// changed DRD 9/26\n\n\t\tmypacket.Command = NET_ANSWER_PLAYER;\n\t\tstrcpy(mypacket.Name, Session.Players[0]->Name);\n\t\tmypacket.PlayerInfo.House = Session.House;\n\t\tmypacket.PlayerInfo.Color = Session.ColorIdx;\n\t\tmypacket.PlayerInfo.NameCRC = Compute_Name_CRC(Session.GameName);\n\n\t\tIpx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);\n\t\treturn(true);\n\t}\n\n\treturn(false);\n\n}\t/* end of Process_Global_Packet */\n\n\n/***********************************************************************************************\n * Destroy_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Call this routine when a connection goes bad, or another player signs off.\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tid\t\t\tconnection ID to destroy; this should be the HousesType of the player\t\t\t  *\n *             on this connection\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\terror\t\t0 = user signed off; 1 = connection error; otherwise, no error is shown.\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   04/22/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Destroy_Connection(int id, int error)\n{\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"Destroying connection for house %d (%s)\\n\",\n\t\t\tid,HouseClass::As_Pointer((HousesType)id)->IniName);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDo nothing if the house isn't human.\n\t//------------------------------------------------------------------------\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t//------------------------------------------------------------------------\n\t//\tCreate a message to display to the user\n\t//------------------------------------------------------------------------\n\ttxt[0] = '\\0';\n\tif (error==1) {\n\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName);\n\t} else if (error==0) {\n\t\tsprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName);\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL,0, txt, housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Remove this player from the Players vector\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDelete the IPX connection\n\t//------------------------------------------------------------------------\n\tIpx.Delete_Connection(id);\n\n\t//------------------------------------------------------------------------\n\t//\tTurn the player's house over to the computer's AI\n\t//------------------------------------------------------------------------\n\thousep->IsHuman = false;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're the last player left, tell the user.\n\t//------------------------------------------------------------------------\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n}\t/* end of Destroy_Connection */\n\n\n/***********************************************************************************************\n * Remote_Connect -- handles connecting this user to others                \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = connections established; false = not\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nbool Remote_Connect(void)\n{\n\tint rc;\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit my game name to 0-length, since I haven't joined any game yet.\n\t//------------------------------------------------------------------------\n\tSession.GameName[0] = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tKeep looping until something useful happens.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\t\t//.....................................................................\n\t\t//\tPop up the network Join/New dialog\n\t\t//.....................................................................\n\t\trc = Net_Join_Dialog();\n\n\t\t//.....................................................................\n\t\t//\t-1 = user selected Cancel\n\t\t//.....................................................................\n\t\tif (rc==-1) {\n\t\t\tSession.NetStealth = stealth;\n\t\t\tSession.NetOpen = 0;\n\t\t\treturn(false);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\t0 = user has joined an existing game; save values & return\n\t\t//.....................................................................\n\t\telse if (rc==0) {\n\t\t\tSession.Write_MultiPlayer_Settings ();\n\t\t\tSession.NetStealth = stealth;\n\t\t\tSession.NetOpen = 0;\n\n\t\t\treturn(true);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\t1 = user requests New Network Game\n\t\t//.....................................................................\n\t\telse if (rc==1) {\n\t\t\t//..................................................................\n\t\t\t//\tPop up the New Network Game dialog; if user selects OK, return\n\t\t\t//\t'true'; otherwise, return to the Join Dialog.\n\t\t\t//..................................................................\n\t\t\tif (Net_New_Dialog()) {\n\t\t\t\tSession.Write_MultiPlayer_Settings ();\n\t\t\t\tSession.NetStealth = stealth;\n\t\t\t\tSession.NetOpen = 0;\n\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n\n}\t/* end of Remote_Connect */\n\n\n\n/***********************************************************************************************\n * Net_Join_Dialog -- lets user join an existing game or start a new one                       *\n *                                                                                             *\n * This dialog displays an edit field for the player's name, and a list of all non-stealth-    *\n * mode games.  Clicking once on a game name displays a list of who's in that game.  Clicking  *\n * \"New\" takes the user to the Net_New dialog, where he waits for other users to join his      *\n * game.  All other input is done through this dialog.                                         *\n *                                                                                             *\n * The dialog has several \"states\":                                                            *\n *                                                                                             *\n *   1) Initially, it waits for the user to fill in his/her name and then to select Join or    *\n *      New; if New is selected, this dialog is exited.                                        *\n *                                                                                             *\n *   2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*\n *      The join request is transmitted to the game's owner, and the message \"Waiting for      *\n *      Confirmation\" is displayed, until a confirmation or denial is received from the game's *\n *      owner.  The user may click Cancel at this point to cancel the join request.            *\n *      (Once Join is selected, the name editing field is disabled, and becomes a display-only *\n *      field.  If cancel is selected, it reappears as an edit field.) The user can still click*\n *      around & see who's in which games.                                                     *\n *                                                                                             *\n *   3) If the join request is denied, the dialog re-initializes to its pre-join state; the    *\n *      Join & New buttons reappear, & the Name field is available again.                      *\n *                                                                                             *\n *   4) If join confirmation is obtained, the message changes to show all the current game\t  *\n *      settings.  The user cannot click around & look at other games any more.\t\t\t\t\t  *\n *                                                                                             *\n * Any game running in Stealth mode won't show up on this dialog.                              *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * The 'Chat' vector contains the address of everyone who sends me a chat announcement.\t\t  *\n * The address field is used to send everyone my outgoing messages.  The LastTime\t\t\t\t  *\n * field is used as a timeout; if enough time goes by & we don't hear from this node,\t\t\t  *\n * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat.  If we don't hear\t\t\t\t  *\n * from him after that, we remove him from our list.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      -1 = cancel, 0 = OK, 1 = New net game requested                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Join_Dialog(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\t\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tint d_dialog_h = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\t\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\t\tint d_txt6_h = 6 *RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tint d_margin1 = 17 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\t\tint d_margin2 = 7 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\t\tint d_name_w = 70 *RESFACTOR;\n\t\tint d_name_h = 9 *RESFACTOR;\n\t\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\t\tint d_name_y = d_dialog_y + d_margin2 + d_txt6_h + (2*RESFACTOR);\n\n#ifdef OLDWAY\n\t\tint d_gdi_w = 40 *RESFACTOR;\n\t\tint d_gdi_h = 9 *RESFACTOR;\n\t\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\t\tint d_gdi_y = d_name_y;\n\n\t\tint d_nod_w = 40 *RESFACTOR;\n\t\tint d_nod_h = 9 *RESFACTOR;\n\t\tint d_nod_x = d_dialog_cx;\n\t\tint d_nod_y = d_name_y;\n#else\n\t\tint d_house_w = 60 *RESFACTOR;\n\t\tint d_house_h = (8 * 5 *RESFACTOR);\n\t\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\t\tint d_house_y = d_name_y;\n#endif\n\n\t\tint d_color_w = 10 *RESFACTOR;\n\t\tint d_color_h = 9 *RESFACTOR;\n\t\tint d_color_y = d_name_y;\n\t\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\n\t\tint d_gamelist_w = 155 *RESFACTOR;\n\t\tint d_gamelist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\tint d_gamelist_x = d_dialog_x + d_margin1 - 2*RESFACTOR;\n\t\tint d_gamelist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n//BG\t\tint d_playerlist_w = 113 *RESFACTOR;\n\tint d_playerlist_w = 118 *RESFACTOR;\n\t\tint d_playerlist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\tint d_playerlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_playerlist_w - 2*RESFACTOR);\n\t\tint d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n\t\tint d_count_w = 25 *RESFACTOR;\n\t\tint d_count_h = d_txt6_h;\n\t\tint d_count_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_count_y = d_gamelist_y + d_gamelist_h + d_margin2;\n\n\t\tint d_level_w = 25 *RESFACTOR;\n\t\tint d_level_h = d_txt6_h;\n\t\tint d_level_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_level_y = d_count_y + d_count_h;\n\n\t\tint d_credits_w = 25 *RESFACTOR;\n\t\tint d_credits_h = d_txt6_h;\n\t\tint d_credits_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_credits_y = d_level_y + d_level_h;\n\n\t\tint d_aiplayers_w = 25 *RESFACTOR;\n\t\tint d_aiplayers_h = d_txt6_h;\n\t\tint d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2);\n\t\tint d_aiplayers_y = d_credits_y + d_level_h;\n\n\t\tint d_options_w = d_playerlist_w;\n\t\tint d_options_h = ((5 * 6) + 4) *RESFACTOR;\n\t\tint d_options_x = d_playerlist_x;\n\t\tint d_options_y = d_playerlist_y + d_playerlist_h + d_margin2 - (2*RESFACTOR);\n\n\t\tint d_message1_w = d_dialog_w - (d_margin1 * 2) + 4*RESFACTOR;\n\t\tint d_message1_h = (14 * d_txt6_h) +3*RESFACTOR;\n\t\tint d_message1_x = d_dialog_x + (d_dialog_w-d_message1_w)/2;\n\t\tint d_message1_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message1_h);\n\n\t\tint d_message2_w = d_message1_w;\n\t\tint d_message2_h = (8 * d_txt6_h) + 3*RESFACTOR;\n\t\tint d_message2_x = d_message1_x;\n\t\tint d_message2_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message2_h);\n\n#ifdef FRENCH              //VG2\n\t\tint d_join_w = 60 *RESFACTOR;\n#else\n\t\tint d_join_w = 40 *RESFACTOR;\n#endif\n\t\tint d_join_h = 9 *RESFACTOR;\n\t\tint d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);\n\t\tint d_join_y = d_dialog_y + d_dialog_h - d_join_h - 8*RESFACTOR;\n\n\t\tint d_cancel_w = 50 *RESFACTOR;\n\t\tint d_cancel_h = 9 *RESFACTOR;\n\t\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\t\tint d_cancel_y = d_join_y;\n\n#ifdef FRENCH\n\t\tint d_new_w = 60 *RESFACTOR;\n#else\n\t\tint d_new_w = 40 *RESFACTOR;\n#endif\n\t\tint d_new_h = 9 *RESFACTOR;\n\t\tint d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);\n\t\tint d_new_y = d_join_y;\n\n\t\tint d_send_w = d_message1_w;\n\t\tint d_send_h = 9 *RESFACTOR;\n\t\tint d_send_x = d_message1_x;\n\t\tint d_send_y = d_message1_y + d_message1_h;\n\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\n\t\tBUTTON_HOUSE,\n#endif\n\t\tBUTTON_GAMELIST,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_JOIN,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_NEW,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AI_PLAYERS,\n\t\tBUTTON_OPTIONS,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7),\n\t\t\t\t\t\t\t};\n\tchar housetext[25] = \"\";\t\t\t\t// buffer for house droplist\n\tint isdropped = 0;\n\n\tJoinStateType joinstate = JOIN_NOTHING;\t// current \"state\" of this dialog\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint playertabs[] = {71 *RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tint game_index = -1;\t\t\t\t\t\t// index of currently-selected game\n\tint join_index = -1;\t\t\t\t\t\t// index of game we're joining\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tJoinEventType event;\t\t\t\t\t\t// event from incoming packet\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tchar txt[128];\n\tchar const *p;\n\tint parms_received = 0;\t\t\t\t\t// 1 = game options received\n\tint found;\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tRejectType why;\t\t\t\t\t\t\t// reason for rejection\n\tTTimerClass<SystemTimerClass> lastclick_timer;\t\t\t// time b/w send periods\n\tint lastclick_idx = 0;\t\t\t\t\t// index of item last clicked on\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\n\tchar * item;\n\tunsigned long starttime;\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load saved game\n\tint goto_lobby;\n\tbool messages_have_focus = true;\t\t// Gadget focus starts on the message system\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT,\n\t\td_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w);\n#else\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\n\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\tTextButtonClass newbtn(BUTTON_NEW, TXT_NEW, TPF_BUTTON, d_new_x, d_new_y, d_new_w);\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tGaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tStaticButtonClass descrip(0, \"\", TPF_CENTER|TPF_TEXT, d_dialog_x + 16*RESFACTOR, d_name_y, d_dialog_w - 32*RESFACTOR, d_txt6_h+1);\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);\n\tStaticButtonClass staticcredits(0, \"          \", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);\n\tStaticButtonClass staticaiplayers(0, \"     \", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tif (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {\n\t\tname_edt.Set_Color(&ColorRemaps[PCOLOR_REALLY_BLUE]);\n\t} else {\n\t\tname_edt.Set_Color(&ColorRemaps[Session.ColorIdx]);\n\t}\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(1);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Rule.IsMPBasesOn);\n\toptionlist.Check_Item(1, Rule.IsMPTiberiumGrow);\n\toptionlist.Check_Item(2, Rule.IsMPCrates);\n\toptionlist.Check_Item(3, Rule.IsMPCaptureTheFlag);\n\toptionlist.Check_Item(4, Rule.IsMPShadowGrow);\n\n\t//........................................................................\n\t// House buttons\n\t//........................................................................\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n//\tfor (HousesType house = HOUSE_FIRST; house <= HOUSE_TURKEY; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\n\n\t//........................................................................\n\t// Option gauges\n\t//........................................................................\n\tcountgauge.Use_Thumb(0);\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Use_Thumb(0);\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Use_Thumb(0);\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\taiplayersgauge.Use_Thumb(0);\n\taiplayersgauge.Set_Maximum(Session.Options.AIPlayers);\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_TEXT);\n\n\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\tSession.WWChat = 0;\n\n\tlastclick_timer = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of games, players, and the chat list\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Games);\n\tClear_Vector(&Session.Players);\n\tClear_Vector(&Session.Chat);\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the Chat vector\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, namebuf);\n\twho->Chat.LastTime = 0;\n\twho->Chat.LastChance = 0;\n\twho->Chat.Color = Session.GPacket.Chat.Color;\n\tSession.Chat.Add (who);\n\n\t//------------------------------------------------------------------------\n\t// Create the \"Lobby\" game name on the games list, and create a bogus\n\t// node for the gamelist, so Games[i] will always match gamelist[i]\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, \"\");\n\twho->Game.IsOpen = 0;\n\twho->Game.LastTime = 0;\n\tSession.Games.Add (who);\n\titem = new char [MPLAYER_NAME_MAX];\n\tstrcpy(item, Text_String(TXT_LOBBY));\n\tgamelist.Add_Item(item);\n\tgamelist.Set_Selected_Index(0);\n\tgame_index = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tSend game-name query & chat announcement; also, initialize timers.\n\t//------------------------------------------------------------------------\n\tSend_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tInit Mono Output\n\t//------------------------------------------------------------------------\n\t#if(SHOW_MONO)\n \tIpx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13);\n\tIpx.Mono_Debug_Print(-1,1);\n\t#endif\n#ifdef WIN32\n//char *fred;\n#endif\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\tmessages_have_focus = false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tmessages_have_focus = true;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Collapse the country list if we are going to redraw the game list\n\t\t*/\n\t\tif (gamelist.Is_To_Redraw() && housebtn.IsDropped) {\n\t\t\thousebtn.Collapse();\n\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// For game-browsing, label the name, side, & color buttons:\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate < JOIN_CONFIRMED) {\n\t\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n#ifdef OLDWAY\n\t\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON,\n\t\t\t\t\t\td_gdi_x + d_gdi_w,\n\t\t\t\t\t\td_gdi_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON,\n\t\t\t\t\t\td_house_x + (d_house_w / 2),\n\t\t\t\t\t\td_house_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n#endif\n\n\t\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON,\n\t\t\t\t\t\td_dialog_x + ((d_dialog_w / 4) * 3),\n\t\t\t\t\t\td_color_y - d_txt6_h,\n\t\t\t\t\t\tscheme, TBLACK,\n\t\t\t\t\t\tTPF_CENTER | TPF_TEXT);\n\t\t\t\t} else {\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t// If we're joined to a game, just print the player's name & side.\n\t\t\t\t\t//...............................................................\n#ifdef OLDWAY\n\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\tsprintf (txt, Text_String(TXT_S_PLAYING_S), namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\tFancy_Text_Print(txt,d_dialog_cx, d_dialog_y + d_margin2 + (1*RESFACTOR),\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx],\n\t\t\t\t\t\tTBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRebuild the button list\n\t\t\t\t//...............................................................\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tgamelist.Zap();\n\t\t\t\tplayerlist.Zap();\n#ifdef OLDWAY\n\t\t\t\tgdibtn.Zap();\n\t\t\t\tnodbtn.Zap();\n#else\n\t\t\t\thousebtn.Zap();\n#endif\n\t\t\t\tname_edt.Zap();\n\t\t\t\tjoinbtn.Zap();\n\t\t\t\tnewbtn.Zap();\n\t\t\t\tcountgauge.Zap();\n\t\t\t\tlevelgauge.Zap();\n\t\t\t\tcreditsgauge.Zap();\n\t\t\t\taiplayersgauge.Zap();\n\t\t\t\tstaticcount.Zap();\n\t\t\t\tstaticlevel.Zap();\n\t\t\t\tstaticcredits.Zap();\n\t\t\t\tstaticaiplayers.Zap();\n\n\t\t\t\tcommands = &cancelbtn;\n\t\t\t\tgamelist.Add_Tail(*commands);\n\t\t\t\tplayerlist.Add_Tail(*commands);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tOnly add the name edit field, the House, Join & New buttons if\n\t\t\t\t//\twe're doing nothing, or we've just been rejected.\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate < JOIN_CONFIRMED) {\n#ifdef OLDWAY\n\t\t\t\t\tgdibtn.Add_Tail(*commands);\n\t\t\t\t\tnodbtn.Add_Tail(*commands);\n#else\n\t\t\t\t\thousebtn.Add_Tail(*commands);\n#endif\n\t\t\t\t\tname_edt.Add_Tail(*commands);\n\t\t\t\t\tjoinbtn.Add_Tail(*commands);\n\t\t\t\t\tnewbtn.Add_Tail(*commands);\n\t\t\t\t} else {\n\t\t\t\t\tcountgauge.Add_Tail(*commands);\n\t\t\t\t\tlevelgauge.Add_Tail(*commands);\n\t\t\t\t\tcreditsgauge.Add_Tail(*commands);\n\t\t\t\t\taiplayersgauge.Add_Tail(*commands);\n\t\t\t\t\tstaticcount.Add_Tail(*commands);\n\t\t\t\t\tstaticlevel.Add_Tail(*commands);\n\t\t\t\t\tstaticcredits.Add_Tail(*commands);\n\t\t\t\t\tstaticaiplayers.Add_Tail(*commands);\n\t\t\t\t\toptionlist.Add_Tail(*commands);\n\t\t\t\t\tdescrip.Add_Tail(*commands);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t\t}\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the color boxes\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_COLORS && joinstate < JOIN_CONFIRMED) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,\n\t\t\t\t\t\tcbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Draw the message system; erase old messages first\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\tDraw_Box(d_message2_x, d_message2_y, d_message2_w, d_message2_h, BOXSTYLE_BOX, true);\n\t\t\t\t} else {\n\t\t\t\t\tDraw_Box(d_message1_x, d_message1_y, d_message1_w, d_message1_h, BOXSTYLE_BOX, true);\n\t\t\t\t}\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Redraw the game options\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS && parms_received && joinstate >= JOIN_CONFIRMED) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Scenario title\n\t\t\t\t//...............................................................\n//\t\t\t\tLogicPage->Fill_Rect(d_dialog_x + 16 *RESFACTOR, d_name_y, d_dialog_x + d_dialog_w - 16 *RESFACTOR, d_name_y + d_txt6_h, BLACK);\n\n\t\t\t\tp = Text_String(TXT_SCENARIO_COLON);\n\t\t\t\tif (Session.Options.ScenarioDescription[0]) {\n\n\t\t\t\t\t// EW - Scenario language translation goes here!!!!!!!! VG\n\t\t\t\t\tint ii;\n\t\t\t\t\tfor (ii = 0; EngMisStr[ii] != NULL;  ii++) {\n\t\t\t\t\t\tif (!strcmp(Session.Options.ScenarioDescription, EngMisStr[ii])) {\n\t\t\t\t\t\t\t#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, EngMisStr[ii+1]);\n\t\t\t\t\t\t\t#else\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (EngMisStr[ii] == NULL) {\n\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t}\n\t\t\t\t\tdescrip.Set_Text(txt);\n\n//\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n//\t\t\t\t\tdescrip.Set_Text(txt);\n//\t\t\t\t\tFancy_Text_Print(\"%s %s\", d_dialog_cx, d_name_y, scheme, BLACK, TPF_TEXT | TPF_CENTER, p, Session.Options.ScenarioDescription);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"%s %s\", p, Text_String(TXT_NOT_FOUND));\n\t\t\t\t\tdescrip.Set_Text(txt);\n//\t\t\t\t\tFancy_Text_Print(\"%s %s\", d_dialog_cx, d_name_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER, p, Text_String(TXT_NOT_FOUND));\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Unit count, tech level, credits, ai players\n\t\t\t\t//...............................................................\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, d_count_x + d_count_w + 35 *RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2 *RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.UnitCount);\n\t\t\t\tstaticcount.Set_Text(txt);\n\t\t\t\tstaticcount.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2 *RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(txt,\"%d\",BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(txt);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 2 *RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2 *RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(txt);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_credits_x + d_credits_w + 2 *RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.AIPlayers);\n\t\t\t\tstaticaiplayers.Set_Text(txt);\n\t\t\t\tstaticaiplayers.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2 *RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\tif (input & KN_BUTTON) {\n\t\t\thousebtn.Collapse();\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t// Mouse Click:\n\t\t\t// If we're joined to a game, display an error if the user tries to\n\t\t\t// modify a read-only control.\n\t\t\t// If user clicks on a color button:\n\t\t\t//\t- If we've joined a game, don't allow a new color selection\n\t\t\t//\t- otherwise, select that color\n\t\t\t// - Change the color of the user's name & message field to match\n\t\t\t//   the newly-selected color.\n\t\t\t//..................................................................\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (joinstate > JOIN_NOTHING) {\n\t\t\t\t\tif ( (Get_Mouse_X() >= d_count_x &&\n\t\t\t\t\t\tGet_Mouse_X() <= d_count_x + d_count_w &&\n\t\t\t\t\t\tGet_Mouse_Y() >= d_count_y &&\n\t\t\t\t\t\tGet_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) ||\n\t\t\t\t\t\t(Get_Mouse_X() >= d_options_x &&\n\t\t\t\t\t\tGet_Mouse_X() <= d_options_x + d_options_w &&\n\t\t\t\t\t\tGet_Mouse_Y() >= d_options_y &&\n\t\t\t\t\t\tGet_Mouse_Y() <= d_options_y + d_options_h) ) {\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\t\t\t\t\t\tSession.PrefColor = (PlayerColorType)\n\t\t\t\t\t\t\t((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\n\t\t\t\t\t\tif (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {\n\t\t\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[PCOLOR_REALLY_BLUE]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\n\t\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx);\n\n\t\t\t\t\t\tdisplay = REDRAW_COLORS;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser clicks on the game list:\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_GAMELIST | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t// Handle a double-click\n\t\t\t\t//...............................................................\n\t\t\t\tif (lastclick_timer < 30 && gamelist.Current_Index() == lastclick_idx) {\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're in a game, & the item clicked on is a different\n\t\t\t\t\t// game, un-join the game we're in.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif ((joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) &&\n\t\t\t\t\t\tlastclick_idx != game_index) {\n\t\t\t\t\t\tif (gamelist.Current_Index() == 0) {\n\t\t\t\t\t\t\tgoto_lobby = 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgoto_lobby = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\t\tgame_index, goto_lobby, d_message1_x, d_message1_y, d_txt6_h,\n\t\t\t\t\t\t\td_send_x, d_send_y, MAX_MESSAGE_LENGTH);\n\t\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Clear the Player vector & the player list box, since\n\t\t\t\t\t\t// our game_index has changed.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t}\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we clicked on another game, join that game.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate != JOIN_CONFIRMED &&\n\t\t\t\t\t\tjoinstate != JOIN_WAIT_CONFIRM && lastclick_idx > 0) {\n\t\t\t\t\t\tgamelist.Set_Selected_Index(lastclick_idx);\n\t\t\t\t\t\tgame_index = lastclick_idx;\n\t\t\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\tstrcpy (Session.Handle,namebuf);\n#ifndef OLDWAY\n\t\t\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\t\t\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\t\t\tparms_received = 0;\n\t\t\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Otherwise, we must have joined the lobby\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (game_index == 0) {\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\t\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\t\t\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t TPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t\t\t\tSession.WWChat = 0;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t//...............................................................\n\t\t\t\t// Handle a single-click\n\t\t\t\t//...............................................................\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If no double-click occurred, set the last-clicked index\n\t\t\t\t\t// & double-click timer.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tlastclick_timer = 0;\n\t\t\t\t\tlastclick_idx = gamelist.Current_Index();\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf we've joined a game, don't allow the selected item to\n\t\t\t\t\t// change\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) {\n\t\t\t\t\t\tgamelist.Set_Selected_Index(game_index);\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're not in a game, and the user clicks on a different\n\t\t\t\t\t// entry, clear the player list & send a player query;\n\t\t\t\t\t// init the click timer, to detect a double-click of this item.\n\t\t\t\t\t//............................................................\n\t\t\t\t\telse if (gamelist.Current_Index() != game_index) {\n\n\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t//..................................................................\n\t\t\t//\tHouse Buttons: set the player's desired House\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tbreak;\n#else\n#endif\n\n\t\t\t//..................................................................\n\t\t\t//\tJOIN: send a join request packet & switch to waiting-for-\n\t\t\t// confirmation mode.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_JOIN | KN_BUTTON):\n\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\tstrcpy (Session.Handle,namebuf);\n#ifndef OLDWAY\n\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\tparms_received = 0;\n\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t} else {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// ESC / CANCEL: send a SIGN_OFF\n\t\t\t// - If we're part of a game, stay in this dialog; otherwise, exit\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf we're joined to a game, make extra sure the other players in\n\t\t\t\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t\t\t\t//\tpacket.  Don't send this to myself (index 0).\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\tgame_index, 1, d_message1_x, d_message1_y, d_txt6_h, d_send_x,\n\t\t\t\t\t\td_send_y, MAX_MESSAGE_LENGTH);\n\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t} else {\n\t\t\t\t//...............................................................\n\t\t\t\t// If I'm not joined to a game, send a SIGN_OFF to all players\n\t\t\t\t// in my Chat vector (but not to myself, index 0)\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\tstrcpy(Session.GPacket.Name,namebuf);\n\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tNow broadcast a SIGN_OFF just to be thorough\n\t\t\t\t\t//............................................................\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// exit the dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tNEW: bail out with return code 1\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_NEW | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tForce user to enter a name\n\t\t\t\t//...............................................................\n\t\t\t\tif (strlen(namebuf)==0) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tEnsure name is unique\n\t\t\t\t//...............................................................\n\t\t\t\tfound = 0;\n\t\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\t\tif (!stricmp(Session.Games[i]->Name, namebuf)) {\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAMENAME_MUSTBE_UNIQUE), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tSave player & game name\n\t\t\t\t//...............................................................\n\t\t\t\tstrcpy(Session.Handle,namebuf);\n\t\t\t\tstrcpy(Session.GameName,namebuf);\n#ifndef OLDWAY\n\t\t\t\tSession.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);\n#endif\n\n\t\t\t\tname_edt.Clear_Focus();\n\t\t\t\tname_edt.Flag_To_Redraw();\n\n\t\t\t\trc = 1;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tService keyboard input for any message being edited.\n\t\t\t\t//...............................................................\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t// (We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t// Rather than setting 'display', which would redraw all msgs,\n\t\t\t\t// we only need to erase & redraw the edit box here.\n\t\t\t\t//...............................................................\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 3, it means send the current message.\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\t\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\t\tSession.GPacket.Message.NameCRC =\n\t\t\t\t\t\tCompute_Name_CRC(Session.GameName);\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf we're joined in a game, send the message to every player\n\t\t\t\t\t// in our player list.  Skip the local system (index 0).\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &(Session.Players[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Otherwise, send the message to all players in our chat list.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Obfuscate(Session.GPacket.Message.Buf) == 0x72A47EF6) {\n\t\t\t\t\t\t\tSession.WWChat = 1;\n\t\t\t\t\t\t\tClear_Listbox (&playerlist);\n\t\t\t\t\t\t\tStart_WWChat(&playerlist);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tAdd the message to our own list, since we're not in the\n\t\t\t\t\t// player list on this dialog.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n#ifdef OBSOLETE\n\t\t\t\t//\n\t\t\t\t// This is for the old drop-down list of houses, not used any more.\n\t\t\t\t//\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\tisdropped = 1;\n\t\t\t\t} else if (isdropped) {\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n#endif\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tResend our query packets\n\t\t//.....................................................................\n\t\tSend_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\tevent = Get_Join_Responses(&joinstate, &gamelist, &playerlist,\n\t\t\tjoin_index, namebuf, &why);\n\n\t\t//.....................................................................\n\t\t//\tIf we've changed state, redraw everything; if we're starting the game,\n\t\t//\tbreak out of the loop.  If we've just joined, send out a player query\n\t\t//\tso I'll get added to the list instantly.\n\t\t//.....................................................................\n\t\tif (event == EV_STATE_CHANGE) {\n\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\tif (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {\n\t\t\t\tif (joinstate==JOIN_GAME_START_LOAD) {\n\t\t\t\t\tload_game = 1;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t**\n\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t**\n\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t**\n\t\t\t\t*/\n\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n\t\t\t\tbool ready_packet_was_sent = false;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\t/*\n\t\t\t\t** If the scenario that the host wants to play doesn't exist locally then we\n\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t*/\n\t\t\t\tIpx.Set_Timing (25, (unsigned long) -1, 1000);\n\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t \t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n\n\t\t\t\t\t/*\n\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( !ready_packet_was_sent ){\n\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t1, &Session.HostAddress);\n\n\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t}\n\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t/*\n\t\t\t\t\t** Oh dear. Thats a scenario I don't have. Request that the host sends the\n\t\t\t\t\t**\tscenario to me provided it's not an official scenario.\n\t\t\t\t\t**\n\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t*/\n\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t} else {\n#endif\n\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\n\t\t\t\tIpx.Set_Timing (30, (unsigned long) -1, 600);\n\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\t\t\t\trc = 0;\n\t\t\t\tprocess = false;\n\n\t\t\t} else if (joinstate==JOIN_CONFIRMED) {\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we're newly-confirmed, add myself to the Players list, and\n\t\t\t// immediately send out a player query\n\t\t\t//..................................................................\n\t\t\t\t//...............................................................\n\t\t\t\t//\tClear the player list, then add myself to the list.\n\t\t\t\t//...............................................................\n\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\n\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, namebuf);\n\t\t\t\twho->Player.House = Session.House;\n\t\t\t\twho->Player.Color = Session.ColorIdx;\n\t\t\t\tSession.Players.Add (who);\n\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Re-init the message system to its new smaller size\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Messages.Init (d_message2_x + 1 *RESFACTOR, d_message2_y + 1 *RESFACTOR, 8,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\t\t\t} else if (joinstate==JOIN_REJECTED) {\n\t\t\t//..................................................................\n\t\t\t//\tIf we've been rejected, clear any messages we may have been\n\t\t\t// typing, add a message stating why we were rejected, and send a\n\t\t\t// chat announcement.\n\t\t\t//..................................................................\n\t\t\t\tSession.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message2_w);\n\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message2_w);\n\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_REQUEST_DENIED), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\n\t\t\t\titem = NULL;\n\t\t\t\tif (why==REJECT_DUPLICATE_NAME) {\n\t\t\t\t\titem = (char *)Text_String(TXT_NAME_MUSTBE_UNIQUE);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_GAME_FULL) {\n\t\t\t\t\titem = (char *)Text_String(TXT_GAME_FULL);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_VERSION_TOO_OLD) {\n\t\t\t\t\titem = (char *)Text_String(TXT_YOURGAME_OUTDATED);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_VERSION_TOO_NEW) {\n\t\t\t\t\titem = (char *)Text_String(TXT_DESTGAME_OUTDATED);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_MISMATCH) {\n\t\t\t\t\titem = (char *)Text_String(TXT_MISMATCH);\n\t\t\t\t}\n\t\t\t\telse if (why==REJECT_DISBANDED) {\n\t\t\t\t\titem = (char *)Text_String(TXT_GAME_CANCELLED);\n\t\t\t\t}\n\t\t\t\tif (item) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, item, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t}\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t}\n\t\t} else if (event == EV_GAME_OPTIONS) {\n\t\t//.....................................................................\n\t\t//\tIf the game options have changed, print them.\n\t\t//.....................................................................\n\t\t\tcountgauge.Set_Maximum(\n\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\tlevelgauge.Set_Value(BuildLevel - 1);\n\t\t\tcreditsgauge.Set_Value(Session.Options.Credits);\n\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t} else {\n\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t}\n\t\t\toptionlist.Check_Item(0,Session.Options.Bases);\n\t\t\toptionlist.Check_Item(1,Session.Options.Tiberium);\n\t\t\toptionlist.Check_Item(2,Session.Options.Goodies);\n\t\t\toptionlist.Check_Item(3,Special.IsCaptureTheFlag);\n\t\t\toptionlist.Check_Item(4,Special.IsShadowGrow);\n\t\t\toptionlist.Flag_To_Redraw();\n\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\tparms_received = 1;\n\t\t\tdisplay = REDRAW_PARMS;\n\t\t} else if (event == EV_MESSAGE) {\n\t\t//.....................................................................\n\t\t//\tDraw an incoming message\n\t\t//.....................................................................\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t} else if (event == EV_NEW_GAME) {\n\t\t//.....................................................................\n\t\t// If a new game has formed, or an existing game has changed state\n\t\t// (from open to closed or closed to open), redraw the message system.\n\t\t//.....................................................................\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t} else if (event == EV_NEW_PLAYER || event == EV_PLAYER_SIGNOFF) {\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tif (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {\n\t\t\t\taiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());\n\t\t\t}\n\t\t} else if (event == EV_GAME_SIGNOFF) {\n\n\t\t//.....................................................................\n\t\t// EV_GAME_SIGNOFF:\n\t\t//\tA game before the one I've selected is gone, so we have a new index\n\t\t// now. 'game_index' must be kept set to the currently-selected list\n\t\t// item, so we send out queries for the currently-selected game.  It's\n\t\t// therefore imperative that we detect any changes to the game list.\n\t\t// If we're joined in a game, we must decrement our game_index to keep\n\t\t// it aligned with the game we're joined to.\n\t\t//.....................................................................\n\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\tgame_index--;\n\t\t\t\tjoin_index--;\n\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t} else {\n\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\tif (process) {\n\t\t\t//.....................................................................\n\t\t\t//\tClean out the Game List; if an old entry is found:\n\t\t\t//\t- Remove it\n\t\t\t//\t- Clear the player list\n\t\t\t//\t- Send queries for the new selected game, if there is one\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Games[i]->Game.LastTime > 400) {\n\n\t\t\t\t\tdelete Session.Games[i];\n\t\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\n\t\t\t\t\titem = (char *)(gamelist.Get_Item (i));\n\t\t\t\t\tgamelist.Remove_Item (item);\n\t\t\t\t\tdelete [] item;\n\n\t\t\t\t\tgamelist.Flag_To_Redraw();\n\n\t\t\t\t\tif (i <= game_index) {\n\t\t\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\t\t\tgame_index--;\n\t\t\t\t\t\t\tjoin_index--;\n\t\t\t\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// If I've changed my name or color, make sure those changes go into\n\t\t\t// the Chat vector.\n\t\t\t//.....................................................................\n\t\t\tstrcpy(Session.Chat[0]->Name, namebuf);\n\t\t\tSession.Chat[0]->Chat.Color = Session.ColorIdx;\n\t\t\tif (Session.Chat[0]->Chat.Color == PCOLOR_DIALOG_BLUE) {\n\t\t\t\t Session.Chat[0]->Chat.Color = PCOLOR_REALLY_BLUE;\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// Clean out the chat vector.  If we find a node that we haven't heard\n\t\t\t// from in 6 seconds, delete that node.\n\t\t\t// If we haven't heard from a node in 5 seconds, send him a request\n\t\t\t// for a chat announcement; he then has 1 second to reply.\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Chat[i]->Chat.LastTime > 360) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t} else if (TickCount - Session.Chat[i]->Chat.LastTime > 300 &&\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance == 0) {\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Name[0] = 0;\n\t\t\t\t\tSession.GPacket.Command = NET_CHAT_REQUEST;\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &(Session.Chat[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//.....................................................................\n\t\t\t// Manage the Lobby list:\n\t\t\t// If the user has selected the 1st Game (\"Lobby\"), the names of all\n\t\t\t// users in the Chat area show up in the Players list box.\n\t\t\t// Users can be changing their names and their colors at any time, so\n\t\t\t// we scan the Chat list each time to see if anything's changed; if\n\t\t\t// so, we redraw the player list.\n\t\t\t// (If WWChat is on, the Chat list is ignored, and the playerlist\n\t\t\t// contains custom names.)\n\t\t\t//.....................................................................\n\t\t\tif (game_index == 0) {\n\t\t\t\tif (!Session.WWChat) {\n\t\t\t\t\twhile (Session.Chat.Count() > playerlist.Count()) {\n\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX];\n\t\t\t\t\t\titem[0] = 0;\n\t\t\t\t\t\tplayerlist.Add_Item(item);\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\twhile (playerlist.Count() > Session.Chat.Count()) {\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n\t\t\t\t\t\tplayerlist.Remove_Item(item);\n\t\t\t\t\t\tdelete [] item;\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tfor (i = 0; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tif (stricmp(Session.Chat[i]->Name,playerlist.Get_Item(i)) ||\n\t\t\t\t\t\t\t&ColorRemaps[ (Session.Chat[i]->Chat.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.Chat[i]->Chat.Color] !=\n\t\t\t\t\t\t\tplayerlist.Colors[i]) {\n\n\t\t\t\t\t\t\tplayerlist.Colors[i] =\n\t\t\t\t\t\t\t\t&ColorRemaps[Session.Chat[i]->Chat.Color];\n\t\t\t\t\t\t\tif (playerlist.Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {\n\t\t\t\t\t\t\t\tplayerlist.Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstrcpy((char *)playerlist.Get_Item(i), Session.Chat[i]->Name);\n\t\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (stricmp(Session.Chat[0]->Name,playerlist.Get_Item(0)) ||\n\t\t\t\t\t\t&ColorRemaps[Session.Chat[0]->Chat.Color] !=\n\t\t\t\t\t\t\tplayerlist.Colors[0]) {\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[Session.Chat[0]->Chat.Color];\n\t\t\t\t\t\tstrcpy((char *)playerlist.Get_Item(0), Session.Chat[0]->Name);\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tif (Update_WWChat()) {\n\t\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t}\t// end of while\n\n\n\t//------------------------------------------------------------------------\n\t//\tEstablish connections with all other players.\n\t//------------------------------------------------------------------------\n\tif (rc == 0) {\n\t\t//.....................................................................\n\t\t//\tIf the other guys are playing a scenario I don't have (sniff), I can't\n\t\t//\tplay.  Try to bail gracefully.\n\t\t//.....................................................................\n\t\tif (Session.Options.ScenarioIndex==-1) {\n\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\n\t\t\t//..................................................................\n\t\t\t// Don't send myself the message.\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\trc = -1;\n\n\t\t} else {\n\n\t\t//---------------------------------------------------------------------\n\t\t// Prepare to load the scenario.\n\t\t//---------------------------------------------------------------------\n\t\t\t//..................................................................\n\t\t\t//\tSet the number of players in this game, and the scenario number.\n\t\t\t//..................................................................\n\t\t\tSession.NumPlayers = Session.Players.Count();\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t\t// he'll be waiting the whole time we load MIX files.\n\t\t//.....................................................................\n\t\ti = max(Ipx.Global_Response_Time() * 2, 60);\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < (unsigned)i) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n//\tIpx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n//\t\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games & Players vectors.\n\t//------------------------------------------------------------------------\n\tClear_Listbox(&gamelist);\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t// Remove the chat edit box\n\t//------------------------------------------------------------------------\n\tSession.Messages.Remove_Edit();\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t//------------------------------------------------------------------------\n\t// Load a game if the game owner told us to\n\t//------------------------------------------------------------------------\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = -1;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players & Games vectors if we're not joined to a game.\n\t// Clear the Chat vector regardless.\n\t//------------------------------------------------------------------------\n\tif (rc != 0) {\n\t\tClear_Vector(&Session.Games);\n\t\tClear_Vector(&Session.Players);\n\t}\n\tClear_Vector(&Session.Chat);\n\n\treturn(rc);\n\n}\t/* end of Net_Join_Dialog */\n\n\n/***************************************************************************\n * Request_To_Join -- Sends a JOIN request packet to game owner            *\n *                                                                         *\n * Regardless of the return code, the Join Dialog will need to be redrawn\t*\n * after calling this routine.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tplayername\t\tplayer's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tjoin_index\t\tindex of game we're joining\t\t\t\t\t\t\t\t\t*\n *\t\thouse\t\t\t\trequested house\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tcolor\t\t\t\trequested color\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = Packet sent, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *=========================================================================*/\nstatic int Request_To_Join (char *playername, int join_index,\n\tHousesType house, PlayerColorType color)\n{\n\t//------------------------------------------------------------------------\n\t//\tValidate join_index\n\t//------------------------------------------------------------------------\n\tif (join_index < 1) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_MUST_SELECT_GAME), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\tif ( (Session.Games.Count()<=1) || join_index > Session.Games.Count()) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NOTHING_TO_JOIN), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tForce user to enter a name\n\t//------------------------------------------------------------------------\n\tif (strlen(playername)==0) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn(false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tThe game must be open\n\t//------------------------------------------------------------------------\n\tif (!Session.Games[join_index]->Game.IsOpen) {\n\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAME_IS_CLOSED), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\tSound_Effect(VOC_SYS_ERROR);\n\t\treturn (false);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend packet to game's owner\n\t//------------------------------------------------------------------------\n\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\tSession.GPacket.Command = NET_QUERY_JOIN;\n\tstrcpy (Session.GPacket.Name, playername);\n\tSession.GPacket.PlayerInfo.House = house;\n\tSession.GPacket.PlayerInfo.Color = color;\n#ifdef FIXIT_VERSION_3\n\t//\tGuest sends host his version.\n\t//\tAdded to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.\n\tif( Is_Aftermath_Installed() )\n\t{\n//\t\tdebugprint( \"Guest tells host 'I have Aftermath'\\n\" );\n\t\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version() |  0x80000000;\n\t}\n\telse\n\t{\n//\t\tdebugprint( \"Guest tells host 'I don't have Aftermath'\\n\" );\n\t\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();\n\t}\n#else\n\tSession.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();\n#endif\n\tSession.GPacket.PlayerInfo.MaxVersion = VerNum.Max_Version();\n\tSession.GPacket.PlayerInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\n\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t&(Session.Games[join_index]->Address));\n\n\treturn(true);\n\n}\t/* end of Request_To_Join */\n\n\n/***************************************************************************\n * Unjoin_Game -- Cancels joining a game                                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnamebuf\t\t\tcurrent player name\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tjoinstate\t\tcurrent join state\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tgamelist\t\t\tListBox of game names\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tplayerlist\t\tListBox of player names\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tgame_index\t\tindex in 'gamelist' of game we're leaving\t\t\t\t\t*\n *\t\tgoto_lobby\t\ttrue = we're going to the lobby\t\t\t\t\t\t\t\t*\n *\t\tmsg_x\t\t\t\tmessage system x-coord\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_y\t\t\t\tmessage system y-coord\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_h\t\t\t\tmessage system char height\t\t\t\t\t\t\t\t\t\t*\n *\t\tsend_x\t\t\tmessage system send x-coord\t\t\t\t\t\t\t\t\t*\n *\t\tsend_y\t\t\tmessage system send y-coord\t\t\t\t\t\t\t\t\t*\n *\t\tmsg_len\t\t\tmessage system max msg length\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/12/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Unjoin_Game(char *namebuf,JoinStateType joinstate,\n\tListClass *gamelist, ColorListClass *playerlist, int game_index,\n\tint goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,\n\tint msg_len)\n{\n\tint i;\n\tchar *item;\n\n\t//------------------------------------------------------------------------\n\t// Fill in a SIGN_OFF packet\n\t//------------------------------------------------------------------------\n\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\tSession.GPacket.Command = NET_SIGN_OFF;\n\tstrcpy(Session.GPacket.Name,namebuf);\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're joined to a game, make extra sure the other players in\n\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t//\tpacket.  Don't send this to myself (index 0).\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t\t&(Session.Players[i]->Address));\n\t\tIpx.Service();\n\t}\n\n\tif (joinstate == JOIN_WAIT_CONFIRM || joinstate == JOIN_CONFIRMED) {\n\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,\n\t\t\t&(Session.Games[game_index]->Address));\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Re-init the message system to its new larger size\n\t//------------------------------------------------------------------------\n\tSession.Messages.Init (msg_x + 1, msg_y + 1, 14,\n\t\tmsg_len, msg_h, send_x + 1, send_y + 1, 1,\n\t\t20, msg_len - 5);\n\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_');\n\n\t//------------------------------------------------------------------------\n\t// Remove myself from the player list, and reset my game name\n\t//------------------------------------------------------------------------\n\tif (playerlist->Count()) {\n\t\titem = (char *)(playerlist->Get_Item(0));\n\t\tplayerlist->Remove_Item(item);\n\t\tdelete [] item;\n\t\tplayerlist->Flag_To_Redraw();\n\t}\n\n\tif (Session.Players.Count() > 0) {\n\t\tdelete Session.Players[0];\n\t\tSession.Players.Delete(Session.Players[0]);\n\t}\n\n\tSession.GameName[0] = 0;\n\n\t//------------------------------------------------------------------------\n\t// Highlight \"Lobby\" on the Game list, Announce I'm ready to chat\n\t//------------------------------------------------------------------------\n\tif (goto_lobby) {\n\t\tgamelist->Set_Selected_Index(0);\n\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\t}\n\n}\t// end of Unjoin_Game\n\n\n/***********************************************************************************************\n * Send_Join_Queries -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine [re]sends the queries related to the Join Dialog:\t\t\t\t\t\t\t\t\t\t  *\n * - NET_QUERY_GAME\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * - NET_QUERY_PLAYER for the game currently selected (if there is one)\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n * The queries are \"staggered\" in time so they aren't all sent at once; otherwise, we'd\t\t  *\n * be inundated with reply packets & we'd miss some (even though the replies will require\t\t  *\n * ACK's).\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tcurgame\t\tindex of currently-selected game; -1 = none\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tjoinstate\tour current joinstate\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tgamenow\t\tif 1, will immediately send the game query\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tplayernow\tif 1, will immediately send the player query for currently-selected game\t  *\n *\t\tchatnow\t\tif 1, will immediately send the chat announcement\t\t\t\t\t\t\t\t\t  *\n *\t\tmyname\t\tuser's name\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tinit\t\t\tinitialize the timers\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *   04/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Send_Join_Queries(int curgame, JoinStateType joinstate,\n\tint gamenow, int playernow, int chatnow, char *myname, int init)\n{\n\t//........................................................................\n\t// These values control the timeouts for sending various types of packets;\n\t// they're designed such that they'll rarely occur simultaneously.\n\t//........................................................................\n\tenum {\n\t\tGAME_QUERY_TIME = 120,\n\t\tPLAYER_QUERY_TIME = 35,\n\t\tCHAT_ANNOUNCE_TIME = 83,\n\t};\n\tstatic CDTimerClass<SystemTimerClass> game_timer;\t\t// time between NET_QUERY_GAME's\n\tstatic CDTimerClass<SystemTimerClass> player_timer;\t// time between NET_QUERY_PLAYERS's\n\tstatic CDTimerClass<SystemTimerClass> chat_timer;\t\t// time between NET_CHAT_ANNOUNCE's\n\n\n\t//------------------------------------------------------------------------\n\t// Initialize timers\n\t//------------------------------------------------------------------------\n\tif (init) {\n\t\tgame_timer = GAME_QUERY_TIME;\n\t\tplayer_timer = PLAYER_QUERY_TIME;\n\t\tchat_timer = CHAT_ANNOUNCE_TIME;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the game-name query if the time has expired, or we're told to do\n\t//\tit right now\n\t//------------------------------------------------------------------------\n\tif (!game_timer || gamenow) {\n\n\t\tgame_timer = GAME_QUERY_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_QUERY_GAME;\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\t//.....................................................................\n\t\t//\tIf the user specified a remote server address, broadcast over that\n\t\t//\tnetwork, too.\n\t\t//.....................................................................\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSend the player query for the game currently clicked on, if the time has\n\t//\texpired and there is a currently-selected game, or we're told to do it\n\t//\tright now\n\t//------------------------------------------------------------------------\n\tif ( ((curgame > 0) && (curgame < Session.Games.Count()) &&\n\t\t!player_timer) || playernow) {\n\n\t\tplayer_timer = PLAYER_QUERY_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_QUERY_PLAYER;\n\t\tstrcpy (Session.GPacket.Name, Session.Games[curgame]->Name);\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\t//.....................................................................\n\t\t//\tIf the user specified a remote server address, broadcast over that\n\t\t//\tnetwork, too.\n\t\t//.....................................................................\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Send the chat announcement\n\t//------------------------------------------------------------------------\n\tif ((!chat_timer && joinstate!=JOIN_CONFIRMED) || chatnow) {\n\n\t\tchat_timer = CHAT_ANNOUNCE_TIME;\n\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\tSession.GPacket.Command = NET_CHAT_ANNOUNCE;\n\t\tstrcpy (Session.GPacket.Name, myname);\n\t\tSession.GPacket.Chat.ID = Session.UniqueID;\n\t\tSession.GPacket.Chat.Color = Session.ColorIdx;\n\n\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\tsizeof(GlobalPacketType), 0, NULL);\n\n\t\tif (Session.IsBridge) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t}\n\t}\n\n}\t/* end of Send_Join_Queries */\n\n\n/***********************************************************************************************\n * Get_Join_Responses -- sends queries for the Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine polls the Global Channel to see if there are any incoming packets;\t\t\t\t  *\n * if so, it processes them.  This routine can change the state of the Join Dialog, or\t\t\t  *\n * the contents of the list boxes, based on what the packet is.\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The list boxes are passed in as pointers; they can't be made globals, because they\t\t\t  *\n * can't be constructed, because they require shape pointers to the arrow buttons, and\t\t\t  *\n * the mix files won't have been initialized when the global variables' constructors are\t\t  *\n * called.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * This routine sets the globals \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.House\t\t\t\t\t(from NET_CONFIRM_JOIN)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.ColorIdx\t\t\t\t(from NET_CONFIRM_JOIN)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Bases\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Tiberium\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Goodies\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tSession.Options.Ghosts\t\t(from NET_GAME_OPTIONS)\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tScenarioIdx\t\t\t\t(from NET_GAME_OPTIONS; -1 = scenario not found)\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tjoinstate\t\tcurrent state of Join Dialog\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tgamelist\t\t\tlist box containing game names\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tplayerlist\t\tlist box containing player names for the currently-selected game\t\t\t  *\n *\t\tjoin_index\t\tindex of the game we've joined or are asking to join\t\t\t\t\t\t\t  *\n *\t\tmy_name\t\t\tname of local system\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\twhy\t\t\t\tptr: filled in with reason for rejection from a game\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tEvent that occurred\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *   04/15/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,\n\tColorListClass *playerlist, int join_index, char *my_name, RejectType *why)\n{\n\tint rc;\n\tchar * item;\t\t\t\t\t\t// general-purpose string\n\tNodeNameType *who;\t\t\t\t// node to add to Games or Players\n\tint i;\n\tint found;\n\tJoinEventType retcode = EV_NONE;\n\tchar txt[80];\n\n\t//------------------------------------------------------------------------\n\t//\tIf there is no incoming packet, just return\n\t//------------------------------------------------------------------------\n\trc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.GAddress, &Session.GProductID);\n\tif (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0)\n\t\treturn(EV_NONE);\n\n\t//------------------------------------------------------------------------\n\t//\tIf we're joined in a game, handle the packet in a standard way; otherwise,\n\t//\tdon't answer standard queries.\n\t//------------------------------------------------------------------------\n\tif ( (*joinstate)==JOIN_CONFIRMED &&\n\t\tProcess_Global_Packet(&Session.GPacket,&Session.GAddress)!=0) {\n\t\treturn(EV_NONE);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_ANSWER_GAME:  Another system is answering our GAME query, so add that\n\t//\tsystem to our list box if it's new.\n\t//------------------------------------------------------------------------\n\tif (Session.GPacket.Command==NET_ANSWER_GAME) {\n\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique\n\t\t//.....................................................................\n\t\tretcode = EV_NONE;\n\t\tfound = 0;\n\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\tif (!strcmp(Session.Games[i]->Name, Session.GPacket.Name)) {\n\t\t\t\tfound = 1;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf name was found, update the node's time stamp & IsOpen flag.\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Games[i]->Game.LastTime = TickCount;\n\t\t\t\tif (Session.Games[i]->Game.IsOpen != Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\t\titem = (char *)gamelist->Get_Item(i);\n\t\t\t\t\tif (Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),\n\t\t\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),\n\t\t\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\t\t}\n\t\t\t\t\tSession.Games[i]->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;\n\t\t\t\t\tgamelist->Flag_To_Redraw();\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf this game has gone from closed to open, copy the\n\t\t\t\t\t// responder's address into our Game slot, since the guy\n\t\t\t\t\t// responding to this must be game owner.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (Session.Games[i]->Game.IsOpen) {\n\t\t\t\t\t\tSession.Games[i]->Address = Session.GAddress;\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// If we're in chat mode, print a message that the state of\n\t\t\t\t\t// this game has changed.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (*joinstate < JOIN_CONFIRMED) {\n\t\t\t\t\t\tif (Session.Games[i]->Game.IsOpen) {\n\t\t\t\t\t\t\tsprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),\n\t\t\t\t\t\t\t\tSession.Games[Session.Games.Count()-1]->Name);\n\t\t\t\t\t\t\tSound_Effect(VOC_GAME_FORMING);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsprintf(txt,Text_String(TXT_GAME_NOW_IN_PROGRESS),\n\t\t\t\t\t\t\t\tSession.Games[Session.Games.Count()-1]->Name);\n\t\t\t\t\t\t\tSound_Effect(VOC_GAME_CLOSED);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tretcode = EV_NEW_GAME;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tname not found (or addresses are different); add it to 'Games'\n\t\t//.....................................................................\n\t\tif (found==0) {\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate a new node structure, fill it in, add it to 'Games'\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;\n\t\t\twho->Game.LastTime = TickCount;\n\t\t\tSession.Games.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate a string for \"xxx's Game\", leaving room for brackets around\n\t\t\t//\tthe string if it's a closed game\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\tif (Session.GPacket.GameInfo.IsOpen) {\n\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),Session.GPacket.Name);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),\n\t\t\t\t\tSession.GPacket.Name);\n\t\t\t}\n\t\t\tgamelist->Add_Item(item);\n\n\t\t\t//..................................................................\n\t\t\t// If this player's in the Chat vector, remove him from there\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// If this game is open, display a message stating that it's\n\t\t\t// now available.\n\t\t\t//..................................................................\n\t\t\tif (Session.GPacket.GameInfo.IsOpen && (*joinstate) < JOIN_CONFIRMED) {\n\t\t\t\tsprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),\n\t\t\t\t\tSession.GPacket.Name);\n\t\t\t\tSession.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\tSound_Effect(VOC_GAME_FORMING);\n\t\t\t}\n\n\t\t\tretcode = EV_NEW_GAME;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add\n\t// it to our player list box & the Player Vector if it's new\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_ANSWER_PLAYER) {\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique\n\t\t//.....................................................................\n\t\tretcode = EV_NONE;\n\t\tfound = 0;\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tIf the address is already present, re-copy their name, color &\n\t\t\t//\thouse into the existing entry, in case they've changed it without\n\t\t\t//\tour knowledge; set the 'found' flag so we won't create a new entry.\n\t\t\t//..................................................................\n\t\t\tif (Session.Players[i]->Address==Session.GAddress) {\n\t\t\t\tstrcpy(Session.Players[i]->Name, Session.GPacket.Name);\n\t\t\t\tSession.Players[i]->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\t\tSession.Players[i]->Player.Color = Session.GPacket.PlayerInfo.Color;\n\n\t\t\t\tplayerlist->Colors[i] =\n\t\t\t\t\t&ColorRemaps[Session.GPacket.PlayerInfo.Color];\n\n\t\t\t\tif (playerlist->Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {\n\t\t\t\t\tplayerlist->Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];\n\t\t\t\t}\n\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDon't add this player if he's not part of the game that's selected.\n\t\t//.....................................................................\n\t\ti = gamelist->Current_Index();\n\t\tif (Session.Games.Count() && Session.GPacket.PlayerInfo.NameCRC !=\n\t\t\tCompute_Name_CRC(Session.Games[i]->Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tDon't add this player if it's myself.  (We must check the name\n\t\t// since the address of myself in 'Players' won't be valid.)\n\t\t//.....................................................................\n\t\tif (!strcmp (my_name,Session.GPacket.Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tname not found, or address didn't match; add to player list box\n\t\t// & Players Vector\n\t\t//.....................................................................\n\t\tif (found==0) {\n\t\t\t//..................................................................\n\t\t\t//\tCreate & add a node to the Vector\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\twho->Player.Color = Session.GPacket.PlayerInfo.Color;\n\t\t\tSession.Players.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tCreate & add a string to the list box\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\tif (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_ALLIES));\n\t\t\t} else {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_SOVIET));\n\t\t\t}\n#else\t//OLDWAY\n\t\t\tsprintf (item, \"%s\\t%s\", Session.GPacket.Name, Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);\n\n\t\t\t//..................................................................\n\t\t\t// If this player's in the Chat vector, remove him from there\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tdelete Session.Chat[i];\n\t\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// If this player has joined our game, play a special sound.\n\t\t\t//..................................................................\n\t\t\tif ((*joinstate)>=JOIN_CONFIRMED) {\n\t\t\t\tSound_Effect(VOC_PLAYER_JOINED);\n\t\t\t}\n\n\t\t\tretcode = EV_NEW_PLAYER;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us\n\t// as being confirmed, and start answering queries from other systems\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CONFIRM_JOIN) {\n\t\tif ( (*joinstate) != JOIN_CONFIRMED) {\n\t\t\tstrcpy (Session.GameName, Session.GPacket.Name);\n\t\t\tSession.House = Session.GPacket.PlayerInfo.House;\n\t\t\tSession.ColorIdx = Session.GPacket.PlayerInfo.Color;\n\n\t\t\t(*joinstate) = JOIN_CONFIRMED;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_REJECT_JOIN: The game owner has turned down our JOIN query; restore\n\t//\tthe dialog state to its first pop-up state.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_REJECT_JOIN) {\n\t\t//.....................................................................\n\t\t// If we're confirmed in a game, broadcast a sign-off to tell all other\n\t\t// systems that I'm no longer a part of any game; this way, I'll be\n\t\t// properly removed from their dialogs.\n\t\t//.....................................................................\n\t\tif ( (*joinstate) == JOIN_CONFIRMED) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name,my_name);\n\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\tSession.GameName[0] = 0;\n\n\t\t\t//..................................................................\n\t\t\t// remove myself from the player list\n\t\t\t//..................................................................\n\t\t\titem = (char *)(playerlist->Get_Item(0));\n\t\t\tplayerlist->Remove_Item(item);\n\t\t\tdelete [] item;\n\t\t\tplayerlist->Flag_To_Redraw();\n\n\t\t\tdelete Session.Players[0];\n\t\t\tSession.Players.Delete(Session.Players[0]);\n\n\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\t(*why) = REJECT_BY_OWNER;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t\t//.....................................................................\n\t\t// If we're waiting for confirmation & got rejected, tell the user why\n\t\t//.....................................................................\n\t\telse if ((*joinstate) == JOIN_WAIT_CONFIRM) {\n\t\t\t(*why) = (RejectType)Session.GPacket.Reject.Why;\n\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_GAME_OPTIONS: The game owner has changed the game options & is\n\t// sending us the new values.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_GAME_OPTIONS) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED || (*joinstate)==JOIN_WAIT_CONFIRM) {\n\t\t\tSession.Options.Credits = Session.GPacket.ScenarioInfo.Credits;\n\t\t\tSession.Options.Bases = Session.GPacket.ScenarioInfo.IsBases;\n\t\t\tSession.Options.Tiberium = Session.GPacket.ScenarioInfo.IsTiberium;\n\t\t\tSession.Options.Goodies = Session.GPacket.ScenarioInfo.IsGoodies;\n//\t\t\tSession.Options.Ghosts = Session.GPacket.ScenarioInfo.IsGhosties;\n\t\t\tSession.Options.AIPlayers = Session.GPacket.ScenarioInfo.AIPlayers;\n\t\t\tBuildLevel = Session.GPacket.ScenarioInfo.BuildLevel;\n\t\t\tSession.Options.UnitCount = Session.GPacket.ScenarioInfo.UnitCount;\n\t\t\tSeed = Session.GPacket.ScenarioInfo.Seed;\n\t\t\tSpecial = Session.GPacket.ScenarioInfo.Special;\n\t\t\tOptions.GameSpeed = Session.GPacket.ScenarioInfo.GameSpeed;\n\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tGuest receives game version number from host.\n\t\t\t//\tAdded to the transmitted version number is a bit indicating presence of Aftermath expansion.\n\t\t\tunsigned long lVersion = Session.GPacket.ScenarioInfo.Version & ~0x80000000;\t//\tActual version number.\n\t\t\tSession.CommProtocol = VerNum.Version_Protocol( lVersion );\n\t\t\tbAftermathMultiplayer = Session.GPacket.ScenarioInfo.Version & 0x80000000;\n//\t\t\tif( bAftermathMultiplayer )\n//\t\t\t\tdebugprint( \"Guest hears host say 'This is an Aftermath game'\\n\" );\n//\t\t\telse\n//\t\t\t\tdebugprint( \"Guest hears host say 'This is NOT an Aftermath game'\\n\" );\n#else\n\t\t\tSession.CommProtocol = VerNum.Version_Protocol(Session.GPacket.ScenarioInfo.Version);\n\t\t\tPlayingAgainstVersion = Session.GPacket.ScenarioInfo.Version;\n#endif\n\n\t\t\tif (Session.Options.Tiberium) {\n\t\t\t\tSpecial.IsTGrowth = 1;\n\t\t\t\tRule.IsTGrowth = 1;\n\t\t\t\tSpecial.IsTSpread = 1;\n\t\t\t\tRule.IsTSpread = 1;\n\t\t\t} else {\n\t\t\t\tSpecial.IsTGrowth = 0;\n\t\t\t\tRule.IsTGrowth = 0;\n\t\t\t\tSpecial.IsTSpread = 0;\n\t\t\t\tRule.IsTSpread = 0;\n\t\t\t}\n\n\t\t\t/*...............................................................\n\t\t\tCopy the information about the scenario that the host wants to\n\t\t\tplay so ee can request this scenario from the host if we don't\n\t\t\thave it locally.\n\t\t\t...............................................................*/\n\t\t\tstrcpy (Session.Options.ScenarioDescription, Session.GPacket.ScenarioInfo.Scenario);\n\t\t\tstrcpy (Session.ScenarioFileName, Session.GPacket.ScenarioInfo.ShortFileName);\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstrncpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest, sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n#else\n\t\t\tstrcpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest);\n#endif\n\t\t\tSession.ScenarioIsOfficial = Session.GPacket.ScenarioInfo.OfficialScenario;\n\t\t\tSession.ScenarioFileLength = Session.GPacket.ScenarioInfo.FileLength;\n\n\t\t\tretcode = EV_GAME_OPTIONS;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_SIGN_OFF: Another system is signing off: search for that system in\n\t//\tboth the game list & player list, & remove it if found\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_SIGN_OFF) {\n\t\t//.....................................................................\n\t\t//\tRemove this name from the list of games\n\t\t//.....................................................................\n\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\tif (!strcmp(Session.Games[i]->Name, Session.GPacket.Name) &&\n\t\t\t\tSession.Games[i]->Address==Session.GAddress) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf the system signing off is the currently-selected list\n\t\t\t\t//\titem, clear the player list since that game is no longer\n\t\t\t\t//\tforming.\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==gamelist->Current_Index()) {\n\t\t\t\t\tClear_Listbox (playerlist);\n\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf the system signing off was the owner of our game, mark\n\t\t\t\t//\tourselves as rejected\n\t\t\t\t//...............................................................\n\t\t\t\tif ( (*joinstate) > JOIN_NOTHING && i==join_index) {\n\t\t\t\t\t(*joinstate) = JOIN_REJECTED;\n\t\t\t\t\tretcode = EV_STATE_CHANGE;\n\t\t\t\t\t(*why) = REJECT_DISBANDED;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tSet my return code\n\t\t\t\t//...............................................................\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tif (i <= gamelist->Current_Index()) {\n\t\t\t\t\t\tretcode = EV_GAME_SIGNOFF;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRemove game name from game list\n\t\t\t\t//...............................................................\n\t\t\t\tdelete Session.Games[i];\n\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\t\t\t\titem = (char *)(gamelist->Get_Item (i));\n\t\t\t\tgamelist->Remove_Item (item);\n\t\t\t\tdelete [] item;\n\t\t\t\tgamelist->Flag_To_Redraw();\n\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRemove this name from the list of players\n\t\t//.....................................................................\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (Session.Players[i]->Address==Session.GAddress) {\n\t\t\t\titem = (char *)(playerlist->Get_Item(i));\n\t\t\t\tplayerlist->Remove_Item(item);\n\t\t\t\tdelete [] item;\n\n\t\t\t\tdelete Session.Players[i];\n\t\t\t\tSession.Players.Delete(Session.Players[i]);\n\n\t\t\t\tplayerlist->Flag_To_Redraw();\n\n\t\t\t\t//...............................................................\n\t\t\t\t// If this player has left our game, play a special sound.\n\t\t\t\t//...............................................................\n\t\t\t\tif ((*joinstate)>=JOIN_CONFIRMED) {\n\t\t\t\t\tSound_Effect(VOC_PLAYER_LEFT);\n\t\t\t\t}\n\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRemove this name from the chat list\n\t\t//.....................................................................\n\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\n\t\t\t\tdelete Session.Chat[i];\n\t\t\t\tSession.Chat.Delete(Session.Chat[i]);\n\n\t\t\t\tif (retcode == EV_NONE) {\n\t\t\t\t\tretcode = EV_PLAYER_SIGNOFF;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_GO: The game's owner is signalling us to start playing.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_GO) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tSession.MaxAhead = Session.GPacket.ResponseTime.OneWay;\n\t\t\t(*joinstate) = JOIN_GAME_START;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t\tSession.HostAddress = Session.GAddress;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_LOADGAME: The game's owner is signalling us to start playing.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_LOADGAME) {\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tSession.MaxAhead = Session.GPacket.ResponseTime.OneWay;\n\t\t\t(*joinstate) = JOIN_GAME_START_LOAD;\n\t\t\tretcode = EV_STATE_CHANGE;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_CHAT_ANNOUNCE: Someone is ready to chat; add them to our list, if\n\t// they aren't already on it, and it's not myself.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CHAT_ANNOUNCE) {\n\t\tfound = 0;\n\t\t//.....................................................................\n\t\t// If this packet is from myself, don't add it to the list\n\t\t//.....................................................................\n\t\tif (Session.GPacket.Chat.ID == Session.UniqueID) {\n\t\t\tfound = 1;\n\t\t}\n\t\t//.....................................................................\n\t\t// Otherwise, see if we already have this address stored in our list\n\t\t// If so, update that node's time values & name (in case the user\n\t\t// changed it), and return.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tfor (i = 0; i < Session.Chat.Count(); i++) {\n\t\t\t\tif (Session.Chat[i]->Address==Session.GAddress) {\n\t\t\t\t\tstrcpy (Session.Chat[i]->Name, Session.GPacket.Name);\n\t\t\t\t\tSession.Chat[i]->Chat.LastTime = TickCount;\n\t\t\t\t\tSession.Chat[i]->Chat.LastChance = 0;\n\t\t\t\t\tSession.Chat[i]->Chat.Color = Session.GPacket.Chat.Color;\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// Add a new node to the list\n\t\t//.....................................................................\n\t\tif (!found) {\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy (who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Chat.LastTime = TickCount;\n\t\t\twho->Chat.LastChance = 0;\n\t\t\twho->Chat.Color = Session.GPacket.Chat.Color;\n\t\t\tSession.Chat.Add (who);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_CHAT_REQUEST: Someone is requesting a CHAT_ANNOUNCE from us; send\n\t// one to him directly.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_CHAT_REQUEST) {\n\t\tif ((*joinstate) != JOIN_WAIT_CONFIRM && (*joinstate) != JOIN_CONFIRMED) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_CHAT_ANNOUNCE;\n\t\t\tstrcpy(Session.GPacket.Name, my_name);\n\t\t\tSession.GPacket.Chat.ID = Session.UniqueID;\n\t\t\tSession.GPacket.Chat.Color = Session.ColorIdx;\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\tsizeof(GlobalPacketType), 1, &Session.GAddress);\n\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// NET_MESSAGE: Someone is sending us a message\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_MESSAGE) {\n\t\t//.....................................................................\n\t\t// If we're in a game, the sender must be in our game.\n\t\t//.....................................................................\n\t\tif ( (*joinstate)==JOIN_CONFIRMED) {\n\t\t\tif (Session.GPacket.Message.NameCRC ==\n\t\t\t\tCompute_Name_CRC(Session.GameName)) {\n\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// Otherwise, we're in the chat room; display any old message.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\tSession.GPacket.Message.Color,\n\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\tTPF_TEXT, -1);\n\t\t}\n\n\t\tretcode = EV_MESSAGE;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_PING: Someone is pinging me to get a response time measure (will only\n\t//\thappen after I've joined a game).  Do nothing; the IPX Manager will handle\n\t//\tsending an ACK, and updating the response time measurements.\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_PING) {\n\t\tretcode = EV_NONE;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDefault case: nothing happened.  (This case will be hit every time I\n\t//\treceive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)\n\t//------------------------------------------------------------------------\n\telse {\n\t\tretcode = EV_NONE;\n\t}\n\n\treturn(retcode);\n\n}\t/* end of Get_Join_Responses */\n\n\n/***********************************************************************************************\n * Net_New_Dialog -- lets user start a new game                                                *\n *                                                                                             *\n * This dialog shows a list of who's requesting to join this game, and lets                    *\n * the game initiator selectively approve each user.                                           *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = cancel                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      Session.GameName must contain this player's name.                                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_New_Dialog(void)\n{\n\treturn 0;\t//PG\n#if (0)\n\ttypedef enum {\n\t\tNUM_MESSAGES = 10\n\t} NumMessagesType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 320 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6*RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n//BG\tint d_playerlist_w = 118*RESFACTOR;\n\tint d_playerlist_w = 124*RESFACTOR;\n\tint d_playerlist_h = (6 * d_txt6_h) + 3*RESFACTOR;\t\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR;\n\tint d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR;\n\n\tint d_scenariolist_w = 162*RESFACTOR;\n\tint d_scenariolist_h = (6 * d_txt6_h) + 3*RESFACTOR;\t\t// 6 rows high\n\tint d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - (5*RESFACTOR);\n\tint d_scenariolist_y = d_playerlist_y;\n\n\tint d_reject_w = 55*RESFACTOR;\n\tint d_reject_h = 9*RESFACTOR;\n\tint d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);\n\tint d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;\n\n\tint d_count_w = 25*RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t\t// (fudged)\n\tint d_count_y = d_reject_y + d_reject_h /*KO+ d_margin2*/;\n\n\tint d_level_w = 25*RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t\t// (fudged)\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25*RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25*RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 106*RESFACTOR;\n\tint d_options_h = ((5 * 6) + 4)*RESFACTOR;\n\tint d_options_x = d_scenariolist_x + ((d_scenariolist_w - d_options_w) / 2);\n\tint d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (NUM_MESSAGES * d_txt6_h) + 3*RESFACTOR;\t// 10 rows high\n\tint d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message_h);\n//\tint d_message_y = d_options_y + d_options_h + d_margin1;\n\n\tint d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_send_h = 9*RESFACTOR;\n\tint d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_ok_w = 50*RESFACTOR;\n\tint d_ok_h = 9*RESFACTOR;\n\tint d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR;\n\n\tint d_cancel_w = 50*RESFACTOR;\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR;\n\n\tint d_load_w = 50*RESFACTOR;\n\tint d_load_h = 9*RESFACTOR;\n\tint d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);\n\tint d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_PLAYERLIST = 100,\n\t\tBUTTON_SCENARIOLIST,\n\t\tBUTTON_REJECT,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AIPLAYERS,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_OK,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\n\tlong ok_timer = 0;\t\t\t\t\t\t// for timing OK button\n\tint index;\t\t\t\t\t\t\t\t\t// index for rejecting a player\n\tint rc;\n\tint i,j;\n\tchar *item;\n\tint tabs[] = {77*RESFACTOR};\t\t\t// tabs for player list box\n\tint optiontabs[] = {8*RESFACTOR};\t// tabs for option list box\n\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tlong ping_timer = 0;\t\t\t\t\t\t// for sending Ping packets\n\n\tint color_used[MAX_MPLAYER_COLORS];\t// 1 = color has been used\n\tchar txt[80];\n\tJoinEventType whahoppa;\t\t\t\t\t// event generated by received packets\n\tstatic int first_time = 1;\t\t\t\t// 1 = 1st time this dialog is run\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load a saved game\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t//------------------------------------------------------------------------\n\t// Buttons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y);\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tGaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR);\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, 60*RESFACTOR);\n\n\tStaticButtonClass staticunit(0, \"    \", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);\n\tStaticButtonClass staticlevel(0, \"    \", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);\n\tStaticButtonClass staticaiplayers(0, \"   \", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);\n\n\t//------------------------------------------------------------------------\n\t//\tBuild the button list\n\t//------------------------------------------------------------------------\n\tcommands = &playerlist;\n\tscenariolist.Add_Tail(*commands);\n\trejectbtn.Add_Tail(*commands);\n\tstaticunit.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticaiplayers.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n\tokbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tif (loadfile.Is_Available()) {\n#ifdef FIXIT_MULTI_SAVE\n//\t\tloadbtn.Add_Tail(*commands);\n#endif\n\t} else {\n\t\tcancelbtn.X = loadbtn.X;\n\t}\n\tplayerlist.Set_Tabs(tabs);\n\n\t//------------------------------------------------------------------------\n\t//\tInit dialog values, only the first time through\n\t//------------------------------------------------------------------------\n\tSpecial.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;\n\tif (first_time) {\n\t\tSession.Options.Credits = Rule.MPDefaultMoney;\t\t\t// init credits & credit buffer\n\t\tSession.Options.Bases = Rule.IsMPBasesOn;\t\t\t\t\t// init scenario parameters\n\t\tSession.Options.Tiberium = Rule.IsMPTiberiumGrow;\n\t\tSession.Options.Goodies = Rule.IsMPCrates;\n\t\tSession.Options.AIPlayers = 0;\n\t\tSession.Options.UnitCount =\n\t\t\t(SessionClass::CountMax[Session.Options.Bases] +\n\t\t\tSessionClass::CountMin[Session.Options.Bases]) / 2;\n\t\tfirst_time = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit button states\n\t//------------------------------------------------------------------------\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(0);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\t//------------------------------------------------------------------------\n\t//\tInit other scenario parameters\n\t//------------------------------------------------------------------------\n\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\tRule.IsTGrowth = Session.Options.Tiberium;\n\tSpecial.IsTSpread = Session.Options.Tiberium;\n\tRule.IsTSpread = Session.Options.Tiberium;\n\ttransmit = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit scenario description list box\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tfor (j = 0; EngMisStr[j] != NULL;  j++) {\n\t\t\tif (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed).\n\t\t\t\t//\tAdd mission if it's available to us.\n\t\t\t\tif( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\tscenariolist.Add_Item(EngMisStr[j+1]);\n#else\n\t\t\t\t\tscenariolist.Add_Item(EngMisStr[j]);\n#endif\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ( EngMisStr[j] == NULL) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed). Added officialness check.\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !Session.Scenarios[i]->Get_Official() ||\n\t\t\t\t!( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n\t\t\t{\n\t\t\t\tscenariolist.Add_Item(Session.Scenarios[i]->Description());\n\t\t\t}\n\t\t}\n\t}\n\n\tSession.Options.ScenarioIndex = 0;\t// 1st scenario is selected\n#ifdef FIXIT_VERSION_3\n\tbAftermathMultiplayer = Is_Aftermath_Installed();\n//\tdebugprint( \"Host decides that, initially, bAftermathMultiplayer is %i\\n\", bAftermathMultiplayer );\n#else\n\tPlayingAgainstVersion = VerNum.Version_Number();\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tInit player color-used flags\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\tcolor_used[i] = 0;\t\t\t\t\t\t\t// init all colors to available\n\t}\n\tcolor_used[Session.ColorIdx] = 1;\t\t\t// set my color to used\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);\n\n\t//------------------------------------------------------------------------\n\t//\tInit random-number generator, & create a seed to be used for all random\n\t//\tnumbers from here on out\n\t//------------------------------------------------------------------------\n\tsrand(time(NULL));\n\tSeed = rand();\n\n\t//------------------------------------------------------------------------\n\t//\tInit the message display system\n\t//------------------------------------------------------------------------\n\tSession.Messages.Init(d_message_x + 1*RESFACTOR, d_message_y + 1*RESFACTOR, NUM_MESSAGES,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1*RESFACTOR, d_send_y + 1*RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t//------------------------------------------------------------------------\n\t//\tInit the version-clipping system\n\t//------------------------------------------------------------------------\n\tVerNum.Init_Clipping();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of players\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Players);\n\n\t//------------------------------------------------------------------------\n\t//\tAdd myself to the list, and to the Players vector.\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t} else {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\t\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist.Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//\n\t// Now init the max range of the AI players slider.\n\t//\n\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tFancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\n\t\t\t\t/*\n\t\t\t\t** Zap, Zap, Zap\n\t\t\t\t*/\n\t\t\t\tplayerlist.Zap();\n\t\t\t\tscenariolist.Zap();\n\t\t\t\trejectbtn.Zap();\n\t\t\t\tstaticunit.Zap();\n\t\t\t\tstaticlevel.Zap();\n\t\t\t\tstaticcredits.Zap();\n\t\t\t\tstaticaiplayers.Zap();\n\t\t\t\tcountgauge.Zap();\n\t\t\t\tcreditsgauge.Zap();\n\t\t\t\taiplayersgauge.Zap();\n\t\t\t\tlevelgauge.Zap();\n\t\t\t\toptionlist.Zap();\n\t\t\t\tokbtn.Zap();\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tloadbtn.Zap();\n\n\n\t\t\t\t/*\n\t\t\t\t** Hack hack, hack\n\t\t\t\t*/\n\t\t\t\tcommands = &playerlist;\n\t\t\t\tscenariolist.Add_Tail(*commands);\n\t\t\t\trejectbtn.Add_Tail(*commands);\n\t\t\t\tstaticunit.Add_Tail(*commands);\n\t\t\t\tstaticlevel.Add_Tail(*commands);\n\t\t\t\tstaticcredits.Add_Tail(*commands);\n\t\t\t\tstaticaiplayers.Add_Tail(*commands);\n\t\t\t\tcountgauge.Add_Tail(*commands);\n\t\t\t\tcreditsgauge.Add_Tail(*commands);\n\t\t\t\taiplayersgauge.Add_Tail(*commands);\n\t\t\t\tlevelgauge.Add_Tail(*commands);\n\t\t\t\toptionlist.Add_Tail(*commands);\n\t\t\t\tokbtn.Add_Tail(*commands);\n\t\t\t\tcancelbtn.Add_Tail(*commands);\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( loadfile.Is_Available() ) {\n#else\n\t\t\t\tif (loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) {\n#endif\n#ifdef FIXIT_MULTI_SAVE\n\t\t\t\t\tloadbtn.Add_Tail(*commands);\n#endif\n\t\t\t\t}\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tDraw the messages:\n\t\t\t//\t- Erase an old message first\n\t\t\t//\t- If we're in a game, print the game options (if they've been\n\t\t\t//\t  received)\n\t\t\t//\t- If we've been rejected from a game, print that message\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Update game parameter labels\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS) {\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2*RESFACTOR, d_count_y, d_count_x + d_count_w + 35*RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.UnitCount);\n\t\t\t\tstaticunit.Set_Text(txt);\n\t\t\t\tstaticunit.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_count_x + d_count_w + 2*RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(txt,\"%d\",BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(txt, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(txt);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 2*RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(txt);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(txt,\"%d\",Session.Options.AIPlayers);\n\t\t\t\tstaticaiplayers.Set_Text(txt);\n\t\t\t\tstaticaiplayers.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t//\tNew Scenario selected.\n\t\t\t//..................................................................\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable as downloads. ajw\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex)\n\t\t\t\t{\n\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\ttransmit = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#else\t//\tFIXIT_VERSION_3\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n#else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t}else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#endif\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t\ttransmit = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\t//\tFIXIT_VERSION_3\n\n\t\t\t//..................................................................\n\t\t\t//\tReject the currently-selected player (don't allow rejecting myself,\n\t\t\t//\twho will be the first entry in the list)\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_REJECT | KN_BUTTON):\n\t\t\t\tindex = playerlist.Current_Index();\n\n\t\t\t\tif (index == 0) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t(char *)Text_String(TXT_CANT_REJECT_SELF), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else if (index < 0 || index >= playerlist.Count()) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t(char *)Text_String(TXT_SELECT_PLAYER_REJECT),\n\t\t\t\t\t\tPCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[index]->Address));\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts max # units\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_COUNT | KN_BUTTON):\n\t\t\t\tSession.Options.UnitCount = countgauge.Get_Value() +\n\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases];\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts build level\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_LEVEL | KN_BUTTON):\n\t\t\t\tBuildLevel = levelgauge.Get_Value() + 1;\n\t\t\t\tif (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)\t// if it's pegged, max it out\n\t\t\t\t\tBuildLevel = MPLAYER_BUILD_LEVEL_MAX;\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser edits the credits value; retransmit new game options\n\t\t\t// Round the credits to the nearest 500.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_CREDITS | KN_BUTTON):\n\t\t\t\tSession.Options.Credits = creditsgauge.Get_Value();\n\t\t\t\tSession.Options.Credits =\n\t\t\t\t\t((Session.Options.Credits + 250) / 500) * 500;\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts # of AI players\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_AIPLAYERS | KN_BUTTON):\n\t\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t\t}\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Toggle-able options:\n\t\t\t// If 'Bases' gets toggled, we have to change the range of the\n\t\t\t// UnitCount slider.\n\t\t\t// Also, if Tiberium gets toggled, we have to set the flags\n\t\t\t// in SpecialClass.\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_OPTIONS | KN_BUTTON):\n\t\t\t\tif (Special.IsCaptureTheFlag != optionlist.Is_Checked(3) && !Special.IsCaptureTheFlag) {\n\t\t\t\t\toptionlist.Check_Item(0, true);\n\t\t\t\t}\n\t\t\t\tif (Session.Options.Bases != (optionlist.Is_Checked(0) ? 1 : 0)) {\n\t\t\t\t\tSession.Options.Bases = (optionlist.Is_Checked(0) ? 1 : 0);\n\t\t\t\t\tif (Session.Options.Bases) {\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[1] -\n\t\t\t\t\t\t\tSessionClass::CountMin[1],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[0]-SessionClass::CountMin[0],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount-SessionClass::CountMin[0])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\toptionlist.Check_Item(3, false);\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[0] -\n\t\t\t\t\t\t\tSessionClass::CountMin[0],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[1]-SessionClass::CountMin[1],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount - SessionClass::CountMin[1])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[0];\n\t\t\t\t\t}\n\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t}\n\t\t\t\tSession.Options.Tiberium = optionlist.Is_Checked(1);\n\t\t\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tSpecial.IsTSpread = Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\t\t\tSession.Options.Goodies = optionlist.Is_Checked(2);\n\t\t\t\tSpecial.IsCaptureTheFlag = optionlist.Is_Checked(3);\n\t\t\t\tSpecial.IsShadowGrow = optionlist.Is_Checked(4);\n\n\t\t\t\ttransmit = 1;\n\t\t\t\tdisplay = REDRAW_PARMS;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tOK: exit loop with TRUE status\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf a new player has joined in the last second, don't allow\n\t\t\t\t//\tan OK; force a wait longer than 1 second (to give all players\n\t\t\t\t//\ta chance to know about this new guy)\n\t\t\t\t//...............................................................\n\t\t\t\ti = max(Ipx.Global_Response_Time() * 2, 60);\n\t\t\t\twhile ((int)TickCount - ok_timer < i) {\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf there are at least 2 players, go ahead & play; error otherwise\n\t\t\t\t//...............................................................\n\t\t\t\tif (Session.Players.Count() > 1 ) {\n//\t\t\t\tif (Session.Players.Count() + Session.Options.AIPlayers > 1 ) {\n\t\t\t\t\trc = TRUE;\n\t\t\t\t\tprocess = FALSE;\n\t\t\t\t} else {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_ONE), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tif (input==(BUTTON_LOAD | KN_BUTTON)) {\n\t\t\t\t\tload_game = 1;\n\t\t\t\t} else {\n\t\t\t\t\tload_game = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over my network\n\t\t\t\t//...............................................................\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over a bridged network if there is one\n\t\t\t\t//...............................................................\n\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tAnd now, just be absolutely sure, send my sign-off to each\n\t\t\t\t//\tplayer in my game.  (If there's a bridge between us, the other\n\t\t\t\t//\tplayer will have specified my address, so he can cross the\n\t\t\t\t//\tbridge; but I may not have specified a bridge address, so the\n\t\t\t\t//\tonly way I have of crossing the bridge is to send a packet\n\t\t\t\t//\tdirectly to him.)\n\t\t\t\t// Don't send this message to myself.\n\t\t\t\t//...............................................................\n\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\t\t\t\tSession.GameName[0] = 0;\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRe-draw the messages & service keyboard input for any message\n\t\t\t\t//\tbeing edited.\n\t\t\t\t//...............................................................\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t//...............................................................\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\t// (erase the cursor)\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t//...............................................................\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\t// (erase the cursor)\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t//...............................................................\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_MESSAGE;\n\t\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (Session.GPacket.Message.Buf,\n\t\t\t\t\t\t\tSession.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\t\t\t\t\tSession.GPacket.Message.Color = Session.ColorIdx;\n\t\t\t\t\tSession.GPacket.Message.NameCRC =\n\t\t\t\t\t\tCompute_Name_CRC(Session.GameName);\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tSend the message to every player in our player list, except\n\t\t\t\t\t// myself.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tAdd the message to our own list, since we're not in the\n\t\t\t\t\t// player list on this dialog.\n\t\t\t\t\t// If there's no message with this ID already displayed, just\n\t\t\t\t\t// add a new message; if there is one, concatenate it.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\t\t\t\tSession.GPacket.Message.Buf,\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n#ifndef FIXIT_VERSION_3\n\t\tint oldversion = PlayingAgainstVersion;\n#endif\n\t\twhahoppa = Get_NewGame_Responses(&playerlist, color_used);\n\t\tif (whahoppa == EV_NEW_PLAYER) {\n\t\t\tok_timer = TickCount;\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n \t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n \t\t\t}\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable for download, regardless of if CS scen. or 126x126 scen.\n\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n#else\t//\tFIXIT_VERSION_3\n\t\t\t\tif (oldversion == PlayingAgainstVersion){\n\t\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\t}else{\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If a CS scenario was selected and we now have a red alert only player\n\t\t\t\t\t** in the mix then deselect the cs scenario.\n\t\t\t\t\t*/\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n\t#else\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n\t#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (0);\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t}\n\t#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t/*\n\t\t\t\t\t** If an AM mega scenario was selected and we now have a non-AM\n\t\t\t\t\t** player in the mix then deselect the mega scenario.\n\t\t\t\t\t*/\n\t\t\t\t\tif (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (0);\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t}\n\t#endif\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n#endif\t//\tFIXIT_VERSION_3\n\n\t\t\ttransmit = 1;\n\t\t} else if (whahoppa == EV_MESSAGE) {\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t} else if (whahoppa == EV_PLAYER_SIGNOFF) {\n\t\t\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());\n\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\tif (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();\n \t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\t\t\t\tdisplay = REDRAW_PARMS;\n \t\t\t}\n\t\t\ttransmit = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t// Don't send it to myself.\n\t\t//.....................................................................\n\t\tif (transmit) {\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_GAME_OPTIONS;\n\n\t\t\t\t/*\n\t\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t\t** or request a download if it doesnt exist\n\t\t\t\t*/\n\t\t\t\tstrcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\t\t\t\tSession.GPacket.ScenarioInfo.FileLength = file.Size();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tstrcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\t\tstrncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\t\tstrncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n\t\t\t\tSession.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\n\t\t\t\tSession.GPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\t\tSession.GPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\t\tSession.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\t\tSession.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\t\tSession.GPacket.ScenarioInfo.Seed = Seed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Special = Special;\n\t\t\t\tSession.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\t\t\t\t//\tHost encodes whether or not this is an Aftermath game in the highest bit.\n\t\t\t\tif( bAftermathMultiplayer )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host tells guests 'This is an Aftermath game'\\n\" );\n\t\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version() | 0x80000000;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host tells guests 'This is NOT an Aftermath game'\\n\" );\n\t\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\t\t\t\t}\n#else\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n#endif\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\ttransmit = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tPing every player in my game, to force the Global Channel to measure\n\t\t//\tthe connection response time.  Don't ping myself (index 0).\n\t\t//.....................................................................\n\t\tif (TickCount - ping_timer > 15) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_PING;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tping_timer = TickCount;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrepare to load the scenario\n\t//------------------------------------------------------------------------\n\tif (rc) {\n\t\t//.....................................................................\n\t\t//\tSet the player count & scenario number\n\t\t//.....................................................................\n\t\tSession.NumPlayers = Session.Players.Count();\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t//.....................................................................\n\t\t//\tCompute frame delay value for packet transmissions:\n\t\t//\t- Divide global channel's response time by 8 (2 to convert to 1-way\n\t\t//\t  value, 4 more to convert from ticks to frames)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tSession.MaxAhead = max( ((((Ipx.Global_Response_Time() / 8) +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t}\n\t\telse {\n\t\t\tSession.MaxAhead = max( (Ipx.Global_Response_Time() / 8),\n\t\t\t\t\t\t\t\t\t\t  NETWORK_MIN_MAX_AHEAD );\n\t\t}\n\n\t\tIpx.Set_Timing (25, (unsigned long) -1, 1000);\n\n\t\t//.....................................................................\n\t\t//\tSend all players the NET_GO packet.  Wait until all ACK's have been\n\t\t//\treceived.\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tif (load_game)\n\t\t\tSession.GPacket.Command = NET_LOADGAME;\n\t\telse\n\t\t\tSession.GPacket.Command = NET_GO;\n\t\tSession.GPacket.ResponseTime.OneWay = Session.MaxAhead;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t}\n\t\t//.....................................................................\n\t\t//\tWait for all the ACK's to come in.\n\t\t//.....................................................................\n\t\twhile (Ipx.Global_Num_Send() > 0) {\n\t\t\tIpx.Service();\n\t\t}\n\n\t\t/*\n\t\t** Wait for the go responses from each player in case someone needs the scenario\n\t\t** file to be sent.\n\t\t*/\n\t\tint responses[20];\t\t//In big trub if more than 20 players\n\t\tmemset (responses, 0, sizeof (responses));\n\t\tint num_responses = 0;\n\t\tbool send_scenario = false;\n#ifdef WIN32\n\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\");\n#endif\n\t\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\t\tresponse_timer = 60*10;\t\t// Wait for 10 seconds. If we dont hear by then assume someone crashed\n\n\t\tdo\t{\n\t\t\tIpx.Service();\n\t\t\tint retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t\t\t&Session.GAddress, &Session.GProductID);\n\t\t\tif (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\t\tif (Session.Players[i]->Address == Session.GAddress) {\n\t\t\t\t\t\tif (!responses[i]) {\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_REQ_SCENARIO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tsend_scenario = true;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_READY_TO_GO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( num_responses < Session.Players.Count()-1 && response_timer );\n\n#ifdef FIXIT_VERSION_3\n\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t{\n\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t}\n#endif\n\n\t\t/*\n\t\t** If one of the machines requested that the scenario be sent then send it.\n\t\t*/\n\t\tif (send_scenario) {\n\t\t\tmemset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));\n\t\t\tSession.RequestCount = 0;\n\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\tif (responses[i] == NET_REQ_SCENARIO) {\n\t\t\t\t\tSession.ScenarioRequests[Session.RequestCount++] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSend_Remote_File (Scen.ScenarioName, 1);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, Ipx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games or Players vectors.\n\t//------------------------------------------------------------------------\n\twhile (scenariolist.Count()) {\n\t\tscenariolist.Remove_Item(scenariolist.Get_Item(0));\n\t}\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t// Remove the chat edit box\n\t//------------------------------------------------------------------------\n\tSession.Messages.Remove_Edit();\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), SysMemPage, SysMemPage, CCPalette);\n//\tSysMemPage.Scale(SeenPage);\n//#else\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), HidPage, HidPage, CCPalette);\n//\tHidPage.Blit(SeenPage);\n//#endif\t//WIN32\n\tShow_Mouse();\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players vector if we're not starting a game.\n\t//------------------------------------------------------------------------\n\tif (!rc) {\n\t\tClear_Vector(&Session.Players);\n\t}\n\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\n\treturn(rc);\n#endif\n}\t/* end of Net_New_Dialog */\n\n\n/***************************************************************************\n * Get_NewGame_Responses -- processes packets for New Game dialog          *\n *                                                                         *\n * This routine can modify the contents of the given list box, as well\t\t*\n * as the contents of the Players Vector global.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tplayerlist\t\tlist of players in this game\t\t\t\t\t\t\t\t\t*\n *\t\tcolor_used\t\tarray of color-used flags\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tEV_NONE = nothing happened\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tEV_NEW_PLAYER = a new player has joined; false otherwise\t\t\t\t\t*\n *\t\tEV_PLAYER_SIGNOFF = a player has left\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tEV_MESSAGE = a message was received\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,\n\tint *color_used)\n{\n\tint rc;\n\tchar * item;\t\t\t\t\t\t// general-purpose string\n\tNodeNameType *who;\t\t\t\t// node to add to Players Vector\n\tint i;\n\tint found;\n\tJoinEventType retval = EV_NONE;\n\tint resend;\n\tunsigned long version;\t\t\t// version # to use\n\n\t//------------------------------------------------------------------------\n\t//\tIf there is no incoming packet, just return\n\t//------------------------------------------------------------------------\n\trc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t&Session.GAddress, &Session.GProductID);\n\tif (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\t\treturn(EV_NONE);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTry to handle the packet in a standard way\n\t//------------------------------------------------------------------------\n\tif (Process_Global_Packet(&Session.GPacket,&Session.GAddress) != 0) {\n\t\treturn(EV_NONE);\n\t} else if (Session.GPacket.Command==NET_QUERY_JOIN) {\n\t//------------------------------------------------------------------------\n\t//\tNET_QUERY_JOIN:\n\t//------------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t//\tSee if this name is unique:\n\t\t//\t- If the name matches, but the address is different, reject this player\n\t\t//\t- If the name & address match, this packet must be a re-send of a\n\t\t//\t  previous request; in this case, do nothing.  The other player must have\n\t\t//\t  received my CONFIRM_JOIN packet (since it was sent with an ACK\n\t\t//\t  required), so we can ignore this resend.\n\t\t//.....................................................................\n\t\tfound = 0;\n\t\tresend = 0;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tif (!strcmp(Session.Players[i]->Name,Session.GPacket.Name)) {\n\t\t\t\tif (Session.Players[i]->Address != Session.GAddress) {\n\t\t\t\t\tfound = 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tresend = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// If his name is the same as mine, treat it like a duplicate name\n\t\t//.....................................................................\n\t\tif (!strcmp (Session.Players[0]->Name, Session.GPacket.Name)) {\n\t\t\tfound = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tReject if name is a duplicate\n\t\t//.....................................................................\n\t\tif (found) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_DUPLICATE_NAME;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tReject if there are too many players\n\t\t//.....................................................................\n\t\telse if ( (Session.Players.Count() >= Session.MaxPlayers) && !resend) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_GAME_FULL;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t/*\n\t\t**\tDon't allow joining if the rules.ini file doesn't appear to match.\n\t\t*/\n\t\telse if (Session.GPacket.PlayerInfo.CheatCheck != RuleINI.Get_Unique_ID() && !resend) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\tSession.GPacket.Reject.Why = (int)REJECT_MISMATCH;\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1, &Session.GAddress);\n\t\t\treturn(EV_NONE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf this packet is NOT a resend, accept the player.  Grant him the\n\t\t//\trequested color if possible.\n\t\t//.....................................................................\n\t\telse if (!resend) {\n\t\t\t//..................................................................\n\t\t\t//\tCheck the player's version range against our own, to see if\n\t\t\t// there's an overlap region\n\t\t\t//..................................................................\n#ifdef FIXIT_VERSION_3\n\t\t\t//\tAdded to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.\n\t\t\tbool bGuestHasAftermath = Session.GPacket.PlayerInfo.MinVersion & 0x80000000;\n\t\t\tif( bGuestHasAftermath )\n//\t\t\t\tdebugprint( \"Host hears guest say 'I have Aftermath'\\n\" );\n\t\t\t\t;\n\t\t\telse\n\t\t\t{\n//\t\t\t\tdebugprint( \"Host hears guest say 'I don't have Aftermath'\\n\" );\n\t\t\t\tif( bAftermathMultiplayer )\n\t\t\t\t{\n//\t\t\t\t\tdebugprint( \"Host decides this is no longer an Aftermath game!\\n\" );\n\t\t\t\t\tbAftermathMultiplayer = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSession.GPacket.PlayerInfo.MinVersion &= ~0x80000000;\t\t//\tStrip special bit.\n#endif\n\t\t\tversion = VerNum.Clip_Version (Session.GPacket.PlayerInfo.MinVersion,\n\t\t\t\tSession.GPacket.PlayerInfo.MaxVersion);\n\n#ifndef FIXIT_VERSION_3\n\t\t\tPlayingAgainstVersion = version;\n#endif\n\n// TCTCTC save off version number\n\n\t\t\t//..................................................................\n\t\t\t// Reject player if his version is too old\n\t\t\t//..................................................................\n\t\t\tif (version == 0) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\t\tSession.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_OLD;\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &Session.GAddress);\n\t\t\t\treturn(EV_NONE);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Reject player if his version is too new\n\t\t\t//..................................................................\n\t\t\telse if (version == 0xffffffff) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\tSession.GPacket.Command = NET_REJECT_JOIN;\n\t\t\t\tSession.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_NEW;\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &Session.GAddress);\n\t\t\t\treturn(EV_NONE);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// If the player is accepted, our mutually-accepted version may be\n\t\t\t// different; set the CommProtocol accordingly.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tAdd node to the Vector list\n\t\t\t//..................................................................\n\t\t\twho = new NodeNameType;\n\t\t\tstrcpy(who->Name, Session.GPacket.Name);\n\t\t\twho->Address = Session.GAddress;\n\t\t\twho->Player.House = Session.GPacket.PlayerInfo.House;\n\t\t\tSession.Players.Add (who);\n\n\t\t\t//..................................................................\n\t\t\t//\tSet player's color; if requested color isn't used, give it to him;\n\t\t\t//\totherwise, give him the 1st available color.  Mark the color we\n\t\t\t//\tgive him as used.\n\t\t\t//..................................................................\n\t\t\tif (color_used[Session.GPacket.PlayerInfo.Color] == 0) {\n\t\t\t\twho->Player.Color = Session.GPacket.PlayerInfo.Color;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tif (color_used[i]==0) {\n\t\t\t\t\t\twho->Player.Color = (PlayerColorType)i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcolor_used[who->Player.Color] = 1;\n\n\t\t\t//..................................................................\n\t\t\t//\tAdd player name to the list box\n\t\t\t//..................................................................\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\t\t\tif (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_ALLIES));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsprintf(item,\"%s\\t%s\",Session.GPacket.Name, Text_String(TXT_SOVIET));\n\t\t\t}\n#else\t//OLDWAY\n\t\t\tsprintf (item, \"%s\\t%s\", Session.GPacket.Name,\n\t\t\t\t\t\tText_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);\n\n\t\t\t//..................................................................\n\t\t\t//\tSend a confirmation packet\n\t\t\t//..................................................................\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_CONFIRM_JOIN;\n\t\t\tstrcpy(Session.GPacket.Name,Session.Handle);\n\t\t\tSession.GPacket.PlayerInfo.House = who->Player.House;\n\t\t\tSession.GPacket.PlayerInfo.Color = who->Player.Color;\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &Session.GAddress);\n\n\t\t\t//..................................................................\n\t\t\t// Play a special sound.\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_PLAYER_JOINED);\n\n\t\t\tretval = EV_NEW_PLAYER;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_SIGN_OFF: Another system is signing off: search for that system in\n\t//\tthe player list, & remove it if found\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_SIGN_OFF) {\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t\t//..................................................................\n\t\t\t//\tName found; remove it\n\t\t\t//..................................................................\n\t\t\tif (!strcmp (Session.Players[i]->Name, Session.GPacket.Name) &&\n\t\t\t\tSession.Players[i]->Address==Session.GAddress) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRemove from the list box\n\t\t\t\t//...............................................................\n\t\t\t\titem = (char *)(playerlist->Get_Item(i));\n\t\t\t\tplayerlist->Remove_Item(item);\n\t\t\t\tplayerlist->Flag_To_Redraw();\n\t\t\t\tdelete [] item;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tMark his color as available\n\t\t\t\t//...............................................................\n\t\t\t\tcolor_used[Session.Players[i]->Player.Color] = 0;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDelete from the Vector list\n\t\t\t\t//...............................................................\n\t\t\t\tdelete Session.Players[i];\n\t\t\t\tSession.Players.Delete(Session.Players[i]);\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Play a special sound.\n\t\t\t\t//...............................................................\n\t\t\t\tSound_Effect(VOC_PLAYER_LEFT);\n\n\t\t\t\tretval = EV_PLAYER_SIGNOFF;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tNET_MESSAGE: Someone is sending us a message\n\t//------------------------------------------------------------------------\n\telse if (Session.GPacket.Command==NET_MESSAGE) {\n\t\tSession.Messages.Add_Message (Session.GPacket.Name,\n\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\tSession.GPacket.Message.Buf,\n\t\t\t(Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,\n\t\t\tTPF_TEXT, -1);\n\n\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\n\t\tretval = EV_MESSAGE;\n\t}\n\n\treturn(retval);\n\n}\t/* end of Get_NewGame_Responses */\n\n\n/***************************************************************************\n * Compute_Name_CRC -- computes CRC from char string                       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tname\t\tstring to create CRC for\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tCRC\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long Compute_Name_CRC(char *name)\n{\n\tchar buf[80];\n\tunsigned long crc = 0L;\n\tint i;\n\n\tstrcpy (buf, name);\n\tstrupr (buf);\n\n\tfor (i = 0; i < (int)strlen(buf); i++) {\n\t\tAdd_CRC (&crc, (unsigned long)buf[i]);\n\t}\n\n\treturn (crc);\n\n}\t/* end of Compute_Name_CRC */\n\n\n/***************************************************************************\n * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\treconn\t\t\t1 = reconnect, 0 = waiting for first-time connection\t*\n *\t\tfresh\t\t\t\t1 = draw from scratch, 0 = only update time counter\t*\n *\t\toldest_index\tIPX connection index of oldest connection \t\t\t\t*\n *\t\t\t\t\t\t\t(only used for reconnection)\t\t\t\t\t\t\t\t\t*\n *\t\ttimeval\t\t\tvalue to print in the countdown field\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/08/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,\n\tunsigned long timeval)\n{\n\treconn; fresh; oldest_index; timeval;\n#if (0)//PG\n\tstatic int x,y,w,h;\n\tint id;\n\tchar buf1[40] = {0};\n\tchar buf2[40] = {0};\n\tchar const *buf3 = \"\";\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\n\tint d_margin = 5 * RESFACTOR;\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n#ifdef WIN32\n\t/*\n\t** If we have just received input focus again after running in the background then\n\t** we need to redraw.\n\t*/\n\tif (AllSurfaces.SurfacesRestored) {\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\tfresh = true;\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tDraw the dialog from scratch\n\t//------------------------------------------------------------------------\n\tif (fresh) {\n\t\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tswitch ( Session.Type) {\n\t\t\tcase GAME_IPX:\n\t\t\tcase GAME_INTERNET:\n\t\t\tcase GAME_MODEM:\n\t\t\tcase GAME_NULL_MODEM:\n\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = Ipx.Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tIpx.Connection_Name(id));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#if(TEN)\n\t\t\tcase GAME_TEN:\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = Ten->Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tTen->Connection_Name(id));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\tcase GAME_MPATH:\n\t\t\t\tif (reconn) {\n\t\t\t\t\tid = MPath->Connection_ID(oldest_index);\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_RECONNECTING_TO),\n\t\t\t\t\t\tMPath->Connection_Name(id));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));\n\t\t\t\t}\n#endif\t// MPATH\n\t\t}\n\n\t\tsprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);\n\t\tbuf3 = Text_String(TXT_PRESS_ESC);\n\n\t\tw = max(String_Pixel_Width(buf1),String_Pixel_Width(buf2));\n\n#ifdef FIXIT_VERSION_3\n\t\tchar szNewCancelMessage[ 300 ];\n\t\tsprintf( szNewCancelMessage, \"%s%s\", buf3, TXT_WOL_CANCELMEANSFORFEIT );\n\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t{\n\t\t\tw = max(String_Pixel_Width(szNewCancelMessage), w);\t// * RESFACTOR;\t\twhy was it ever multiplied by this!!!?\n\t\t\tw += (d_margin * 12);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tw = max(String_Pixel_Width(buf3), w) * RESFACTOR;\n\t\t\tw += (d_margin * 5);\n\t\t}\n#else\n\t\tw = max(String_Pixel_Width(buf3), w) * RESFACTOR;\n\t\tw += (d_margin * 5);\n#endif\n\n\t\th = (d_txt6_h * 3) + (d_margin * 6);\n\t\tx = 160*RESFACTOR - (w / 2);\n\t\ty = 100*RESFACTOR - (h / 2);\n\n\t\tHide_Mouse();\n\t\tSet_Logic_Page(SeenBuff);\n\t\tDialog_Box(x, y, w, h);\n\n\t\tFancy_Text_Print (buf1, 160*RESFACTOR, y + (d_margin * 2), scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tFancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n#ifdef FIXIT_VERSION_3\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t\tFancy_Text_Print (szNewCancelMessage, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\telse\n\t\t\tFancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\tFancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\n\t\tShow_Mouse();\n\t}\n\t//------------------------------------------------------------------------\n\t//\tJust update the timeout value on the dialog\n\t//------------------------------------------------------------------------\n\telse {\n\t\tHide_Mouse();\n\t\tSet_Logic_Page(SeenBuff);\n\n\t\tsprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);\n\n\t\tint fillx = 160*RESFACTOR - (String_Pixel_Width (buf2) / 2) -6;\n\t\tLogicPage->Fill_Rect (fillx, y + (d_margin * 2) + d_txt6_h + d_margin,\n\t\t\t\t\t\t\t\t\tfillx + String_Pixel_Width (buf2) + 12,\n\t\t\t\t\t\t\t\t\ty + (d_margin * 2) + d_txt6_h + d_margin + d_txt6_h +1*RESFACTOR,\n\t\t\t\t\t\t\t\t\tBLACK);\n\n\t\tFancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, BLACK, TPF_CENTER | TPF_TEXT);\n\n\t\tShow_Mouse();\n\t}\n#endif\n}\t/* end of Net_Reconnect_Dialog */\n\n#define\tMAX_CHAT_NAME\t\t12\n#define\tMAX_CHAT_PHRASE\t45\n\nstruct WWPerson {\n\tchar Name[MAX_CHAT_NAME];\n\tchar Phrase[MAX_CHAT_PHRASE];\n\tPlayerColorType Color;\n\tunsigned long LastTime;\n};\n\nstruct WWPerson WWPersons[] = {\n\t{ {66,105,108,108,32,82,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,105,115,110,39,116,32,116,104,105,115,32,99,111,111,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,82,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,119,97,110,116,32,115,111,109,101,32,115,101,97,102,111,111,100,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,97,114,114,121,32,71,0,0,0,0,0,},\n\t  {71,114,101,97,116,46,32,74,117,115,116,32,103,114,101,97,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,97,114,114,121,32,71,0,0,0,0,0,},\n\t  {87,111,110,100,101,114,102,117,108,46,32,80,101,114,102,101,99,116,44,32,105,110,32,102,97,99,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,80,0,0,0,0,0,0,},\n\t  {89,111,117,32,99,97,108,108,32,116,104,105,115,32,65,73,63,32,32,83,104,101,101,115,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,108,108,32,80,0,0,0,0,0,0,},\n\t  {66,105,108,108,115,32,114,117,108,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {84,97,107,101,32,116,104,105,115,32,111,117,116,44,32,110,111,119,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {87,104,121,32,99,97,110,39,116,32,121,111,117,32,102,105,116,32,97,110,121,32,109,111,114,101,32,108,101,116,116,101,114,115,32,111,110,32,116,104,101,32,108,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {69,100,44,32,73,32,119,97,110,116,32,116,111,32,116,97,108,107,32,116,111,32,121,111,117,32,97,98,111,117,116,32,116,104,105,115,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,101,116,116,32,83,0,0,0,0,0,},\n\t  {69,100,44,32,99,111,109,101,32,116,111,32,109,121,32,111,102,102,105,99,101,44,32,110,111,119,33,32,32,91,99,114,97,99,107,33,93,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,115,116,97,112,108,101,114,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,116,104,101,115,97,117,114,117,115,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,101,110,105,110,97,32,70,0,0,0,0,},\n\t  {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,112,101,110,99,105,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,108,111,32,66,0,0,0,0,0,0,},\n\t  {72,101,121,32,83,116,101,118,101,44,32,99,97,110,32,119,101,32,109,101,101,116,32,105,110,32,121,111,117,114,32,111,102,102,105,99,101,63,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,108,111,32,66,0,0,0,0,0,0,},\n\t  {83,116,101,118,101,44,32,105,116,39,108,108,32,111,110,108,121,32,116,97,107,101,32,97,32,109,105,110,117,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,111,98,32,83,0,0,0,0,0,0,0,},\n\t  {77,105,108,111,44,32,100,105,97,108,32,50,52,57,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,119,105,116,104,32,97,110,32,69,45,76,45,83,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,115,98,97,114,102,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,108,115,98,101,116,104,32,87,0,0,0,},\n\t  {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,102,98,117,116,116,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,97,114,101,110,32,71,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,115,111,111,111,32,119,101,105,114,100,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,97,114,101,110,32,71,0,0,0,0,0,},\n\t  {68,117,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,104,105,108,32,71,0,0,0,0,0,0,},\n\t  {72,101,121,44,32,105,116,32,119,111,114,107,101,100,32,111,110,32,109,121,32,99,111,109,112,117,116,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,104,105,108,32,71,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,116,104,105,110,103,32,105,115,32,99,108,101,97,114,108,121,32,97,32,119,97,115,116,101,32,111,102,32,109,101,109,111,114,121,46,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,66,0,0,0,0,0,0,0,},\n\t  {72,109,109,44,32,73,32,115,101,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,66,0,0,0,0,0,0,0,},\n\t  {65,104,104,44,32,121,101,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,114,105,97,32,68,77,77,76,0,0,},\n\t  {78,111,116,32,97,110,111,116,104,101,114,32,105,110,115,116,97,108,108,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,114,105,97,32,68,77,77,76,0,0,},\n\t  {72,65,32,72,65,32,72,65,32,72,65,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,114,101,97,108,108,121,32,99,111,111,108,33,32,32,71,111,115,104,32,103,117,121,115,33,32,32,87,111,119,33,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,0,0,0,0,0,0,},\n\t  {87,111,119,33,32,32,89,111,117,32,103,117,121,115,32,97,114,101,32,116,104,101,32,103,114,101,97,116,101,115,116,33,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,71,0,0,0,0,0,0,},\n\t  {71,114,97,121,102,105,115,104,32,102,111,114,32,108,117,110,99,104,32,97,103,97,105,110,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,71,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,108,97,109,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,108,101,110,110,32,83,0,0,0,0,0,},\n\t  {84,104,105,115,32,116,104,105,110,103,39,115,32,98,117,103,103,101,100,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,108,101,110,110,32,83,0,0,0,0,0,},\n\t  {83,104,105,112,32,105,116,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,116,101,118,101,32,87,0,0,0,0,0,},\n\t  {79,75,32,101,118,101,114,121,111,110,101,44,32,111,117,116,32,111,102,32,109,121,32,111,102,102,105,99,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,100,32,68,0,0,0,0,0,0,0,0,},\n\t  {65,32,103,111,111,100,32,99,104,97,116,32,112,114,111,103,114,97,109,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,100,32,68,0,0,0,0,0,0,0,0,},\n\t  {65,32,103,111,111,100,32,110,105,110,106,97,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,107,32,89,0,0,0,0,0,0,},\n\t  {73,32,119,101,97,114,32,100,101,115,105,103,110,101,114,32,106,101,97,110,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,107,32,89,0,0,0,0,0,0,},\n\t  {72,101,121,32,66,105,108,108,44,32,116,104,105,115,32,116,104,105,110,103,32,107,101,101,112,115,32,99,114,97,25,26,24,104,105,110,103,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,70,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,98,101,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,70,0,0,0,0,0,0,},\n\t  {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,119,111,114,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,105,99,107,32,78,0,0,0,0,0,0,},\n\t  {83,111,117,110,100,115,32,108,105,107,101,32,97,32,100,114,105,118,101,114,32,112,114,111,98,108,101,109,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,99,111,116,116,32,66,0,0,0,0,0,},\n\t  {73,32,110,101,101,100,32,116,104,105,115,32,102,111,114,32,76,79,76,50,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {83,116,101,118,101,32,84,0,0,0,0,0,},\n\t  {84,104,105,115,32,115,101,101,109,115,32,114,97,116,104,101,114,32,115,105,108,108,121,44,32,97,99,116,117,97,108,108,121,46,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,97,117,108,32,77,0,0,0,0,0,0,},\n\t  {78,111,32,46,46,46,46,32,32,87,32,65,32,89,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {82,105,99,107,32,80,0,0,0,0,0,0,},\n\t  {65,72,32,72,65,32,72,65,32,72,65,33,33,32,32,72,65,72,65,33,33,32,32,65,72,72,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,75,0,0,0,0,0,0,0,},\n\t  {83,116,97,108,105,110,32,107,105,108,108,101,100,32,109,121,32,102,97,116,104,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,101,32,75,0,0,0,0,0,0,0,},\n\t  {73,32,104,111,112,101,32,121,111,117,39,114,101,32,112,114,111,117,100,32,111,102,32,121,111,117,114,115,101,108,102,44,32,66,105,108,108,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,105,103,32,87,105,108,108,121,0,0,0,},\n\t  {65,110,121,98,111,100,121,32,102,101,114,32,97,32,115,112,105,116,116,105,110,39,32,99,111,110,116,101,115,116,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {69,114,105,99,32,87,0,0,0,0,0,0,},\n\t  {75,97,114,97,116,101,32,105,115,32,103,111,111,100,32,98,117,116,32,121,111,117,32,117,115,101,32,105,116,32,102,111,114,32,101,118,105,108,33,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {84,101,100,32,77,0,0,0,0,0,0,0,},\n\t  {72,97,46,32,32,70,117,110,110,121,46,32,32,84,104,105,115,32,105,115,32,102,117,110,110,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,97,109,111,110,32,82,0,0,0,0,0,},\n\t  {73,32,98,108,97,109,101,32,116,104,101,32,70,114,101,110,99,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,119,105,103,104,116,32,79,0,0,0,0,},\n\t  {79,104,44,32,109,97,110,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,105,97,32,72,0,0,0,0,0,0,0,},\n\t  {73,111,110,32,99,97,110,110,111,110,32,114,101,97,100,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,105,97,32,72,0,0,0,0,0,0,0,},\n\t  {83,101,108,101,99,116,32,116,97,114,103,101,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {66,114,117,99,101,32,74,0,0,0,0,0,},\n\t  {73,32,97,109,32,116,104,101,32,71,101,110,105,101,32,111,102,32,116,104,101,32,108,97,109,112,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {76,97,117,114,97,32,87,0,0,0,0,0,},\n\t  {71,111,32,97,119,97,121,44,32,66,105,108,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,97,118,105,100,32,68,0,0,0,0,0,},\n\t  {72,109,109,109,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,105,107,101,32,76,105,0,0,0,0,0,},\n\t  {67,97,108,108,32,109,101,32,78,97,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {68,101,110,122,105,108,32,76,0,0,0,0,},\n\t  {84,104,105,115,32,119,111,117,108,100,32,98,101,32,98,101,116,116,101,114,32,111,110,32,116,104,101,32,77,97,99,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {71,114,101,103,32,72,0,0,0,0,0,0,},\n\t  {66,117,116,32,100,111,101,115,32,105,116,32,102,105,116,32,105,110,116,111,32,50,32,77,66,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,110,97,116,104,97,110,32,76,0,0,},\n\t  {73,32,116,104,105,110,107,32,73,32,110,101,101,100,32,97,32,104,97,105,114,99,117,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {65,100,97,109,32,73,0,0,0,0,0,0,},\n\t  {87,104,97,116,101,118,101,114,46,32,32,66,101,101,102,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {75,117,114,116,32,79,0,0,0,0,0,0,},\n\t  {70,105,120,32,105,116,32,121,111,117,114,115,101,108,102,46,32,32,73,39,109,32,98,117,115,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,111,115,101,112,104,32,72,0,0,0,0,},\n\t  {60,73,99,121,32,103,108,97,114,101,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {77,97,116,116,32,72,0,0,0,0,0,0,},\n\t  {73,39,109,32,110,101,118,101,114,32,103,111,111,100,32,119,105,116,104,32,99,108,101,118,101,114,32,111,110,32,116,104,101,32,115,112,111,116,46,46,46,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {67,104,114,105,115,32,82,0,0,0,0,0,},\n\t  {73,32,108,111,118,101,32,109,121,32,106,111,98,46,32,32,89,101,97,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {80,97,116,32,67,0,0,0,0,0,0,0,},\n\t  {73,39,109,32,97,32,112,114,111,102,101,115,115,105,111,110,97,108,32,121,111,100,101,108,108,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {73,97,110,32,76,0,0,0,0,0,0,0,},\n\t  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n\t{ {74,97,99,107,32,77,0,0,0,0,0,0,},\n\t  {73,32,108,105,118,101,32,97,98,111,117,116,32,97,32,98,108,111,99,107,32,102,114,111,109,32,116,104,101,32,112,114,111,112,111,115,101,100,32,115,105,116,101,46,0,},PCOLOR_GREEN,0},\n\t{ {74,101,102,102,32,66,0,0,0,0,0,0,},\n\t  {84,104,101,121,32,97,108,108,32,108,111,111,107,32,108,105,107,101,32,97,110,116,115,32,102,114,111,109,32,117,112,32,104,101,114,101,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},\n};\n\nCDTimerClass<SystemTimerClass> wwperson_timer;\n\nvoid Start_WWChat(ColorListClass *playerlist)\n{\n\tchar *item;\n\tint i;\n\tHousesType house;\n\n\t//------------------------------------------------------------------------\n\t// Ensure a different sequence each time\n\t//------------------------------------------------------------------------\n\tScen.RandomNumber = rand();\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the player list\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t}\n\telse {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist->Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t//------------------------------------------------------------------------\n\t// Add everyone else to the list\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < sizeof(WWPersons) / sizeof(struct WWPerson); i++) {\n\t\t//.....................................................................\n\t\t// Add the 1st entry to the list no matter what; for entries after the\n\t\t// 1st, only add the name if it's different from the previous name.\n\t\t//.....................................................................\n\t\tif (i==0 || strcmp(WWPersons[i].Name, WWPersons[i-1].Name)) {\n\t\t\tWWPersons[i].Color = (PlayerColorType)(Random_Pick(0,(int)(PCOLOR_LAST - 1)));\n\t\t\tif (Percent_Chance(50)) {\n\t\t\t\thouse = HOUSE_GREECE;\n\t\t\t} else {\n\t\t\t\thouse = HOUSE_USSR;\n\t\t\t}\n//\t\t\thouse = (HousesType)Random_Pick((int)HOUSE_GOOD,(int)HOUSE_BAD);\n\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\tif (house != HOUSE_USSR && house != HOUSE_UKRAINE) {\n\t\t\t\tsprintf(item,\"%s\\t%s\", WWPersons[i].Name, Text_String(TXT_ALLIES));\n\t\t\t} else {\n\t\t\t\tsprintf(item,\"%s\\t%s\", WWPersons[i].Name, Text_String(TXT_SOVIET));\n\t\t\t}\n\t\t\tplayerlist->Add_Item(item,\n\t\t\t\t(WWPersons[i].Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[WWPersons[i].Color]);\n\t\t}\n\t\t//.....................................................................\n\t\t// If this entry's name is the same as the previous, copy the color\n\t\t// value from the previous entry.\n\t\t//.....................................................................\n\t\telse if (i > 0) {\n\t\t\tWWPersons[i].Color = WWPersons[i-1].Color;\n\t\t}\n\n\t}\n\n\t//wwperson_timer = 240;\n\twwperson_timer = Random_Pick(90,360);\n\n}\t// end of Start_WWChat\n\n\nint Update_WWChat(void)\n{\n\tint i;\n\tint j;\n\n\t//------------------------------------------------------------------------\n\t// Do nothing if it's too soon.\n\t//------------------------------------------------------------------------\n\tif (wwperson_timer > 0) {\n\t\treturn(0);\n\t}\n\n\t//wwperson_timer = 240;\n\twwperson_timer = Random_Pick(90,360);\n\n\t//------------------------------------------------------------------------\n\t// Even after the timer's gone off, there's only a 1/8 chance we'll\n\t// print a message.\n\t//------------------------------------------------------------------------\n\tif (Percent_Chance(12)) {\n\t\treturn(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Randomly select a message to \"send\"; ensure we pick a message that\n\t// hasn't been recently displayed.\n\t//------------------------------------------------------------------------\n\tj = sizeof(WWPersons) / sizeof(struct WWPerson);\n\ti = Random_Pick (0, j - 1);\n\tif ((TickCount - WWPersons[i].LastTime) < 1800 &&\n\t\tWWPersons[i].LastTime != 0) {\n\t\treturn(0);\n\t}\n\n\tSession.Messages.Add_Message (WWPersons[i].Name,\n\t\t0,\n\t\tWWPersons[i].Phrase, WWPersons[i].Color,\n\t\tTPF_TEXT, -1);\n\tWWPersons[i].LastTime = TickCount;\n\n\treturn (1);\n\n}\t// end of Update_WWChat\n\n\n#if(0)\n/*****************************************************************************/\nvoid Start_Logging(void)\n{\n\tFILE *fp;\n\tstatic char *ColorNames[6] = {\n\t\t\"Yellow\",\n\t\t\"Red\",\n\t\t\"BlueGreen\",\n\t\t\"Orange\",\n\t\t\"Green\",\n\t\t\"Blue\",\n\t};\n\tint i;\n\tint id;\n\tHousesType house;\n\tchar *housenames[] = {\n\t\t\"ALLIES\",\n\t\t\"SOVIET\",\n\t\t\"Neutral\",\n\t\t\"Special\",\n\t\t\"Multi1\",\n\t\t\"Multi2\",\n\t\t\"Multi3\",\n\t\t\"Multi4\",\n\t\t};\n\ttime_t t;\n\n\tfp = fopen(\"NETPLAY.LOG\",\"at\");\n\tif (!fp)\n\t\treturn;\n\n\t/*\n\t**\tPrint game header\n\t*/\n\tt = time(NULL);\n\tfprintf (fp,\"==============================================================\\n\");\n\tfprintf (fp,\"Date:            %s\",ctime(&t));\n\tfprintf (fp,\"Scenario:        %s\\n\",\n\t\tSession.Scenarios[Session.Options.ScenarioIndex].Description());\n\tfprintf (fp,\"Total # players: %d\\n\",Session.NumPlayers);\n\tfprintf (fp,\"==============================================================\\n\");\n\n\t/*\n\t**\tPrint connection info\n\t*/\n\n\t/*\n\t**\tPrint player data\n\t*/\n\tfprintf(fp,\"Local Player:\\n\");\n\tfprintf (fp,\"             Name:%s\\n\", Session.Handle);\n\tfprintf (fp,\"            Color:%s\\n\", ColorNames[Session.ColorIdx]);\n\tfprintf (fp,\"            House:%s\\n\", housenames[Session.House]);\n\tfprintf (fp,\"\\n\");\n\n\tfor (i = 0; i < Ipx.Num_Connections(); i++) {\n\t\tid = Ipx.Connection_ID(i);\n\t\thouse = (HouseClass)id;\n\t\tfprintf(fp,\"Connection %d:\\n\",i);\n\t\tfprintf (fp,\"             Name:%s\\n\", Ipx.Connection_Name(id));\n\t\tfprintf (fp,\"            Color:%s\\n\",\n\t\t\tColorNames[HouseClass::As_Pointer(house)->RemapColor);\n\t\tfprintf (fp,\"            House:%s\\n\", housenames[house]);\n\t\tfprintf (fp,\"\\n\");\n\t}\n\n\t/*\n\t**\tPrint game options\n\t*/\n\tfprintf(fp,\"Game Options:\\n\");\n\tfprintf(fp,\"             Bases:%d\\n\",Session.Options.Bases);\n\tfprintf(fp,\"           Credits:%d\\n\",Session.Options.Credits);\n\tfprintf(fp,\"          Tiberium:%d\\n\",Session.Options.Tiberium);\n\tfprintf(fp,\"            Crates:%d\\n\",Session.Options.Goodies);\n\tfprintf(fp,\"        AI Players:%d\\n\",Session.Options.AIPlayers);\n\tfprintf(fp,\"       Build Level:%d\\n\",BuildLevel);\n\tfprintf(fp,\"        Unit Count:%d\\n\",Session.Options.UnitCount);\n\tfprintf(fp,\"              Seed:%d\\n\",Seed);\n\tfprintf (fp,\"\\n\");\n\n\tfclose(fp);\n\n}\t/* end of Start_Logging */\n\n\nvoid Log_Message(char *msg)\n{\n\tFILE *fp;\n\n\tfp = fopen(\"NETPLAY.LOG\",\"at\");\n\tif (!fp)\n\t\treturn;\n\n\tfprintf(fp,\"%s (Frame:%d)\\n\",msg,Frame);\n\tfclose(fp);\n\tflushall();\n\n}\t/* end of Log_Message */\n#endif\n\n\n\n\n\n#ifndef WOLAPI_INTEGRATION\t\t\t//\tRest of file ifdeffed out.\n\n\n\n\n\nextern bool Spawn_WChat(bool can_launch);\n\n/***********************************************************************************************\n * Net_Fake_New_Dialog -- lets user start a new game                                           *\n *                                                                                             *\n * This dialog shows a list of who's requesting to join this game, and lets                    *\n * the game initiator selectively approve each user.                                           *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Ŀ                                           *\n *                  New Network Game                                                         *\n *                                                                                           *\n *         Players               Scenario                                                    *\n *     Ŀ   Ŀ                                            *\n *      Boffo       .    Green Acres      .                                            *\n *      Bozo        Ĵ    Brown Sewers     Ĵ                                            *\n *      Bonzo                 ...                                                      *\n *                  Ĵ                     Ĵ                                            *\n *                  .                     .                                            *\n *                                                    *\n *         [Reject]             Count:--- ##                                                 *\n *                              Level:--- ##                                                 *\n *                                                                                           *\n *                   Credits: _____                                                          *\n *           [  Bases   ]   [   Crates   ]                                                   *\n *           [ Tiberium ]   [ AI Players ]                                                   *\n *      Ŀ                                              *\n *                                                                                         *\n *                                                                                         *\n *                                                    *\n *      Ŀ                                              *\n *                                                    *\n *                  [OK]    [Cancel]                                                         *\n *                                               *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = cancel                                                         *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      Session.GameName must contain this player's name.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Fake_New_Dialog(void)\n{\n#ifdef WIN32\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\tint d_dialog_w = 120 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 80 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6*RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_playerlist_w = 118*RESFACTOR;\n\tint d_playerlist_h = ((6 * 6) + 3)*RESFACTOR;\t\t\t// 6 rows high\n\t//int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1;\n\tint d_playerlist_x = 500*RESFACTOR;\n\tint d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_PLAYERLIST = 100,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\n\tlong ok_timer = 0;\t\t\t\t\t\t// for timing OK button\n\tint rc;\n\tint i;\n\tchar *item;\n\tint tabs[] = {77};\t\t\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for option list box\n\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tlong ping_timer = 0;\t\t\t\t\t\t// for sending Ping packets\n\n\tint color_used[MAX_MPLAYER_COLORS];\t// 1 = color has been used\n\tJoinEventType whahoppa;\t\t\t\t\t// event generated by received packets\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load a saved game\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint\twidth;\n\tint\theight;\n\n\tbool\tplayer_joined = false;\n\tCountDownTimerClass join_timer;\n\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\n\t//------------------------------------------------------------------------\n\t// Buttons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST,\n\t\td_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,\n\t\tTPF_TEXT,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//------------------------------------------------------------------------\n\t//\tBuild the button list\n\t//------------------------------------------------------------------------\n\tcommands = &playerlist;\n\tcancelbtn.Add_Tail(*commands);\n\tplayerlist.Set_Tabs(tabs);\n\n\t//------------------------------------------------------------------------\n\t//\tInit other scenario parameters\n\t//------------------------------------------------------------------------\n\tRule.IsTGrowth = Special.IsTGrowth;\n\tSpecial.IsTSpread = Session.Options.Tiberium;\n\tRule.IsTSpread = Special.IsTSpread;\n\ttransmit = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInit player color-used flags\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\tcolor_used[i] = 0;\t\t\t\t\t\t\t// init all colors to available\n\t}\n\tcolor_used[Session.ColorIdx] = 1;\t\t\t// set my color to used\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);\n\n\t//------------------------------------------------------------------------\n\t//\tInit random-number generator, & create a seed to be used for all random\n\t//\tnumbers from here on out\n\t//------------------------------------------------------------------------\n//\trandomize();\n\tSeed = rand();\n\n\t//------------------------------------------------------------------------\n\t//\tInit the version-clipping system\n\t//------------------------------------------------------------------------\n\tVerNum.Init_Clipping();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of players\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Players);\n\t//------------------------------------------------------------------------\n\t//\tAdd myself to the list, and to the Players vector.\n\t//------------------------------------------------------------------------\n\titem = new char [MPLAYER_NAME_MAX + 64];\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_ALLIES));\n\t}\n\telse {\n\t\tsprintf(item,\"%s\\t%s\",Session.Handle, Text_String(TXT_SOVIET));\n\t}\n#else\t//OLDWAY\n\tsprintf (item, \"%s\\t%s\", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\tplayerlist.Add_Item(item,\n\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\n\t/*\n\t** Process the message loop until we are in focus.\n\t*/\n\tCDTimerClass<SystemTimerClass> focus_timer;\t\t// Timer to allow a wait after client joins\n\tfocus_timer = 5*60;\n\n\tWWDebugString (\"RA95 - About to enter wait for focus loop.\\n\");\n\tSetForegroundWindow ( MainWindow );\n\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\n\tif (!GameInFocus) {\n\t\tdo {\n\t\t\tKeyboard->Check();\n\t\t\tif (!focus_timer){\n\t\t\t\tWWDebugString (\"RA95 - Calling SetForgroundWindow.\\n\");\n\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\tWWDebugString (\"RA95 - Calling ShowWindow.\\n\");\n\t\t\t\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tfocus_timer = 5*60;\n\t\t\t}\n\t\t}while (!GameInFocus);\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t}\n\n\twho = new NodeNameType;\n\tstrcpy(who->Name, Session.Handle);\n\twho->Player.House = Session.House;\n\twho->Player.Color = Session.ColorIdx;\n\tSession.Players.Add (who);\n\n\tif (LogicPage != &SeenBuff && LogicPage!= &HidPage) {\n\t\tSet_Logic_Page (SeenBuff);\n\t}\n\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tIpx.Mono_Debug_Print(-1,0);\n\t\t#endif\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\t//GamePalette.Set();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tBroadcast my sign-off over my network\n\t\t\t\t//...............................................................\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tAnd now, just be absolutely sure, send my sign-off to each\n\t\t\t\t//\tplayer in my game.  (If there's a bridge between us, the other\n\t\t\t\t//\tplayer will have specified my address, so he can cross the\n\t\t\t\t//\tbridge; but I may not have specified a bridge address, so the\n\t\t\t\t//\tonly way I have of crossing the bridge is to send a packet\n\t\t\t\t//\tdirectly to him.)\n\t\t\t\t// Don't send this message to myself.\n\t\t\t\t//...............................................................\n\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));\n\t\t\t\t\tIpx.Service();\n\t\t\t\t}\n\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\t\t\t\tSession.GameName[0] = 0;\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tSend_Data_To_DDE_Server (\"Hello\", strlen(\"Hello\"), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\tSpawn_WChat(false);\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tDefault: manage the inter-player messages\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (Session.Players.Count() > 1) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Wait for several secs after receiving request to join before sending\n\t\t\t\t\t** start game packet\n\t\t\t\t\t*/\n\t\t\t\t\tif (!player_joined) {\n\t\t\t\t\t\tplayer_joined = true;\n\t\t\t\t\t\tjoin_timer.Set (3*60, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (join_timer.Time()) break;\n\t\t\t\t\t}\n\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t//\tIf a new player has joined in the last second, don't allow\n\t\t\t\t\t//\tan OK; force a wait longer than 1 second (to give all players\n\t\t\t\t\t//\ta chance to know about this new guy)\n\t\t\t\t\t//...............................................................\n\t\t\t\t\ti = MAX((int)Ipx.Global_Response_Time() * 2, 60*2);\n\t\t\t\t\twhile ((int)TickCount - ok_timer < i) {\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//...............................................................\n\t\t\t\t\t//\tIf there are at least 2 players, go ahead & play; error otherwise\n\t\t\t\t\t//...............................................................\n\t\t\t\t\tif (Session.Solo || Session.Players.Count() > 1 || Session.Options.Ghosts) {\n\t\t\t\t\t\trc = TRUE;\n\t\t\t\t\t\tprocess = FALSE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tWWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t}\n\t\t\t\t\t//if (input==(BUTTON_LOAD | KN_BUTTON))\n\t\t\t\t\t//\tload_game = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\twhahoppa = Get_NewGame_Responses(&playerlist, color_used);\n\t\tif (whahoppa == EV_NEW_PLAYER) {\n\t\t\tok_timer = TickCount;\n\t\t\ttransmit = 1;\n\t\t}\n\t\telse if (whahoppa == EV_MESSAGE) {\n\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t// Don't send it to myself.\n\t\t//.....................................................................\n\t\tif (transmit) {\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\tSession.GPacket.Command = NET_GAME_OPTIONS;\n\t\t\t\t/*\n\t\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t\t** or request a download if it doesnt exist\n\t\t\t\t*/\n\t\t\t\tstrcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t\t\t//\tajw - I don't understand why this check is done here and not later.\n\t\t\t\tif ( !file.Is_Available() ) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t**\n\t\t\t\t\t** The only time the file can be unavailable is if its a counterstrike\n\t\t\t\t\t** mission and the CS CD is not in the drive so\n\t\t\t\t\t** make sure the counterstrike CD is in the drive.\n\t\t\t\t\t**\n\t\t\t\t\t** If Counterstrike is installed and\n\t\t\t\t\t** the file name matches a counterstrike map then force the CD\n\t\t\t\t\t** to be there.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\tif ( Expansion_CS_Present() || Expansion_AM_Present() ) {\n\t\t\t\t\t\tif ( toupper (Session.ScenarioFileName [2]) == 'M' ){\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName) && index!=2 && index!=3) {\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName) && index!=3) {\n\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\tif ( Expansion_CS_Present() ) {\n\t\t\t\t\t\tif ( toupper (Session.ScenarioFileName [2]) == 'M' ){\n\t\t\t\t\t\t\tint scen_num;\n\t\t\t\t\t\t\tsscanf ( Session.ScenarioFileName, \"SCM%02d\", &scen_num );\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\t\t\tif ( scen_num>24 && Get_CD_Index(current_drive, 1*60) != 2){\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** See if that file is available now. Its fatal if it isnt.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( !file.Is_Available() ) {\n\n\t\t\t\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\t\tstrcpy (Session.GPacket.Name, Session.Handle);\n\n\t\t\t\t\t\t//..................................................................\n\t\t\t\t\t\t// Don't send myself the message.\n\t\t\t\t\t\t//..................................................................\n\t\t\t\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t0, NULL);\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t0, NULL);\n\n\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t\tClear_Listbox(&playerlist);\n\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\t//\tRestore screen\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t\t\tShow_Mouse();\n\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\t// Clear the Players vector if we're not starting a game.\n\t\t\t\t\t\t//------------------------------------------------------------------------\n\t\t\t\t\t\tClear_Vector(&Session.Players);\n\t\t\t\t\t\treturn (false);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tSession.GPacket.ScenarioInfo.FileLength = file.Size();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\tstrcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\t\tstrncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\t\tstrncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));\n\t\t\t\tSession.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\n\t\t\t\tSession.GPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\t\tSession.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\t\t//Session.GPacket.ScenarioInfo.IsGhosties = Session.Options.Ghosts;\n\t\t\t\tSession.GPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\t\tSession.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\t\tSession.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\t\tSession.GPacket.ScenarioInfo.Seed = Seed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Special = Special;\n\t\t\t\tSession.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n\t\t\t\tSession.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();\n\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t\ttransmit = 0;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tPing every player in my game, to force the Global Channel to measure\n\t\t//\tthe connection response time.  Don't ping myself (index 0).\n\t\t//.....................................................................\n\t\tif (TickCount - ping_timer > 15) {\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\tSession.GPacket.Command = NET_PING;\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t\t}\n\t\t\tping_timer = TickCount;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tPrepare to load the scenario\n\t//------------------------------------------------------------------------\n\tif (rc) {\n\t\t//.....................................................................\n\t\t//\tSet the player count & scenario number\n\t\t//.....................................................................\n\t\tSession.NumPlayers = Session.Players.Count();\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t//.....................................................................\n\t\t//\tCompute frame delay value for packet transmissions:\n\t\t//\t- Divide global channel's response time by 8 (2 to convert to 1-way\n\t\t//\t  value, 4 more to convert from ticks to frames)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tSession.MaxAhead = MAX( ((((Ipx.Global_Response_Time() / 8) +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t}\n\t\telse {\n\t\t\tSession.MaxAhead = MAX( ((int)Ipx.Global_Response_Time() / 8),\n\t\t\t\t\t\t\t\t\t\t  NETWORK_MIN_MAX_AHEAD );\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSend all players the NET_GO packet.  Wait until all ACK's have been\n\t\t//\treceived.\n\t\t//.....................................................................\n\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\tif (load_game)\n\t\t\tSession.GPacket.Command = NET_LOADGAME;\n\t\telse\n\t\t\tSession.GPacket.Command = NET_GO;\n\t\tSession.GPacket.ResponseTime.OneWay = Session.MaxAhead;\n\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[i]->Address) );\n\t\t}\n\t\t//.....................................................................\n\t\t//\tWait for all the ACK's to come in.\n\t\t//.....................................................................\n\t\twhile (Ipx.Global_Num_Send() > 0) {\n\t\t\tIpx.Service();\n\t\t}\n\n\n\t\t/*\n\t\t** Wait for the go responses from each player in case someone needs the scenario\n\t\t** file to be sent.\n\t\t*/\n\t\tint responses[20];\t\t//In big trub if more than 20 players\n\t\tmemset (responses, 0, sizeof (responses));\n\t\tint num_responses = 0;\n\t\tbool send_scenario = false;\n\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\\n\");\n\n\t\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\t\tresponse_timer = 60*30;\t\t// Wait for 30 seconds. If we dont hear by then assume someone crashed\n\n\t\tdo\t{\n\t\t\tIpx.Service();\n\t\t\tint retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,\n\t\t\t\t&Session.GAddress, &Session.GProductID);\n\t\t\tif (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {\n\n\t\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\t\tif (Session.Players[i]->Address == Session.GAddress) {\n\t\t\t\t\t\tif (!responses[i]) {\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_REQ_SCENARIO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tsend_scenario = true;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Session.GPacket.Command == NET_READY_TO_GO) {\n\t\t\t\t\t\t\t\tresponses[i] = Session.GPacket.Command;\n\t\t\t\t\t\t\t\tnum_responses++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( num_responses < Session.Players.Count()-1 && response_timer );\n\n\t\tWWDebugString (\"RA95 - Exited response wait loop.\\n\");\n\n\t\t/*\n\t\t** If one of the machines requested that the scenario be sent then send it.\n\t\t*/\n\t\tif (send_scenario) {\n\t\t\tmemset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));\n\t\t\tSession.RequestCount = 0;\n\t\t\tfor ( i=1 ; i<Session.Players.Count() ; i++ ) {\n\t\t\t\tif (responses[i] == NET_REQ_SCENARIO) {\n\t\t\t\t\tSession.ScenarioRequests[Session.RequestCount++] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSend_Remote_File (Scen.ScenarioName, 1);\n\t\t}\n\n\t}\n\n\t//.....................................................................\n\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t// he'll be waiting the whole time we load MIX files.\n\t//.....................................................................\n\ti = MAX((int)Ipx.Global_Response_Time() * 2, 60*2);\n\tint starttime = TickCount;\n\twhile ((int)TickCount - starttime < i) {\n\t\tIpx.Service();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n\t//\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players vector if we're not starting a game.\n\t//------------------------------------------------------------------------\n\tif (!rc) {\n\t\tClear_Vector(&Session.Players);\n\t}\n\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\n\treturn(rc);\n\n#else\t//WIN32\n\n\treturn (0);\n\n#endif\t//WIN32\n}\t/* end of Net_Fake_New_Dialog */\n\n\n\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Net_Join_Dialog -- lets user join an existing game or start a new one                       *\n *                                                                                             *\n * This dialog displays an edit field for the player's name, and a list of all non-stealth-    *\n * mode games.  Clicking once on a game name displays a list of who's in that game.  Clicking  *\n * \"New\" takes the user to the Net_New dialog, where he waits for other users to join his      *\n * game.  All other input is done through this dialog.                                         *\n *                                                                                             *\n * The dialog has several \"states\":                                                            *\n *                                                                                             *\n *   1) Initially, it waits for the user to fill in his/her name and then to select Join or    *\n *      New; if New is selected, this dialog is exited.                                        *\n *                                                                                             *\n *   2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*\n *      The join request is transmitted to the game's owner, and the message \"Waiting for      *\n *      Confirmation\" is displayed, until a confirmation or denial is received from the game's *\n *      owner.  The user may click Cancel at this point to cancel the join request.            *\n *      (Once Join is selected, the name editing field is disabled, and becomes a display-only *\n *      field.  If cancel is selected, it reappears as an edit field.) The user can still click*\n *      around & see who's in which games.                                                     *\n *                                                                                             *\n *   3) If the join request is denied, the dialog re-initializes to its pre-join state; the    *\n *      Join & New buttons reappear, & the Name field is available again.                      *\n *                                                                                             *\n *   4) If join confirmation is obtained, the message changes to show all the current game\t  *\n *      settings.  The user cannot click around & look at other games any more.\t\t\t\t\t  *\n *                                                                                             *\n * Any game running in Stealth mode won't show up on this dialog.                              *\n *                                                                                             *\n * The 'Players' vector matches one-for-one the contents of the list box.  The local system\t  *\n * is always listed first; the IPX Address of the local system will NOT be valid in the\t\t  *\n * Players vector.  The Games & Players vectors should be left filled in even after this\t\t  *\n * routine is exited; their contents are used to form connections to the other players,\t\t  *\n * after the scenario has been loaded.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * The 'Chat' vector contains the address of everyone who sends me a chat announcement.\t\t  *\n * The address field is used to send everyone my outgoing messages.  The LastTime\t\t\t\t  *\n * field is used as a timeout; if enough time goes by & we don't hear from this node,\t\t\t  *\n * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat.  If we don't hear\t\t\t\t  *\n * from him after that, we remove him from our list.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    Ŀ                                    *\n *                     Network Games                                                         *\n *                                                                                           *\n *                  Your Name: ____________                                                  *\n *                      House: [GDI] [NOD]                                                   *\n *              Desired Color: [ ][ ][ ][ ]                                                  *\n *                                                                                           *\n *                Games                 Players                                              *\n *     Ŀ Ŀ                                     *\n *     (Bill's Game         ).  Peter Parker GDI .                                     *\n *      Peter Parker's Game  Ĵ  Mary Jane    GDI Ĵ                                     *\n *     (Magnum PI's Game    )   JJ Jameson   NOD                                       *\n *                           Ĵ                   Ĵ                                     *\n *                           .                   .                                     *\n *                                           *\n *               Scenario: Big Long Description                                              *\n *                    Starting Credits: xxxx                                                 *\n *              Count: ---          Level: ---                                               *\n *              Bases: ON          Crates: ON                                                *\n *           Tiberium: ON      AI Players: ON                                                *\n *                                                                                           *\n *      Ŀ                                      *\n *                                                                                         *\n *                                                                                         *\n *                                            *\n *      Ŀ                                      *\n *                                            *\n *                [Join]  [Cancel]    [New]                                                  *\n *                                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      -1 = cancel, 0 = OK, 1 = New net game requested                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *=============================================================================================*/\nstatic int Net_Fake_Join_Dialog(void)\n{\n\n#ifdef WIN32\n\t//------------------------------------------------------------------------\n\t//\tDialog & button dimensions\n\t//------------------------------------------------------------------------\n\t\tint d_dialog_w = 120 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\t\tint d_dialog_h = 80 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\t\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\t\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\t\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\t\tint d_txt6_h = 6 *RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\t\tint d_margin1 = 5 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// large margin\n\t\tint d_margin2 = 7 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// small margin\n\n\t\tint d_gamelist_w = 160 *RESFACTOR;\n\t\tint d_gamelist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n//\t\tint d_gamelist_x = d_dialog_x + d_margin1 + d_margin1;\n\t\tint d_gamelist_x = 500*RESFACTOR;\t//d_dialog_x + d_margin1 + d_margin1;\n\t\tint d_gamelist_y = 50 + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n\t\tint d_playerlist_w = 118 *RESFACTOR;\n\t\tint d_playerlist_h = ((6 * 6) + 3) *RESFACTOR;\t\t// 6 rows high\n\t\t//int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w;\n\t\tint d_playerlist_x = 500*RESFACTOR;\n\t\tint d_playerlist_y = 50+ d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\t//------------------------------------------------------------------------\n\t//\tButton Enumerations\n\t//------------------------------------------------------------------------\n\tenum {\n\t\tBUTTON_GAMELIST = 100,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t//------------------------------------------------------------------------\n\t//\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t//------------------------------------------------------------------------\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t//------------------------------------------------------------------------\n\t//\tDialog variables\n\t//------------------------------------------------------------------------\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar housetext[25] = \"\";\t\t\t\t// buffer for house droplist\n\tint isdropped = 0;\n\n\tJoinStateType joinstate = JOIN_NOTHING;\t// current \"state\" of this dialog\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint playertabs[] = {77 *RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tint game_index = -1;\t\t\t\t\t\t// index of currently-selected game\n\tint join_index = -1;\t\t\t\t\t\t// index of game we're joining\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tJoinEventType event;\t\t\t\t\t\t// event from incoming packet\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tint parms_received = 0;\t\t\t\t\t// 1 = game options received\n\tNodeNameType *who;\t\t\t\t\t\t// node to add to Players\n\tRejectType why;\t\t\t\t\t\t\t// reason for rejection\n\tTTimerClass<SystemTimerClass> lastclick_timer;\t\t\t// time b/w send periods\n\tint lastclick_idx = 0;\t\t\t\t\t// index of item last clicked on\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tint ready_to_go = 0;\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\tint\twidth;\n\tint\theight;\n\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);\n\tchar * item;\n\tunsigned long starttime;\n\tint load_game = 0;\t\t\t\t\t\t// 1 = load saved game\n\n\t//------------------------------------------------------------------------\n\t//\tButtons\n\t//------------------------------------------------------------------------\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n//#if (GERMAN | FRENCH)\n//\t\td_cancel_x, d_cancel_y);\n//#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n//#endif\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK,\n\t\tTPF_CENTER | TPF_TEXT);\n\n\tlastclick_timer = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the list of games, players, and the chat list\n\t//------------------------------------------------------------------------\n\tClear_Vector(&Session.Games);\n\tClear_Vector(&Session.Players);\n\tClear_Vector(&Session.Chat);\n\n\t//------------------------------------------------------------------------\n\t// Add myself to the Chat vector\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, namebuf);\n\twho->Chat.LastTime = 0;\n\twho->Chat.LastChance = 0;\n\twho->Chat.Color = Session.GPacket.Chat.Color;\n\tSession.Chat.Add (who);\n\n\t//------------------------------------------------------------------------\n\t// Create the \"Lobby\" game name on the games list, and create a bogus\n\t// node for the gamelist, so Games[i] will always match gamelist[i]\n\t//------------------------------------------------------------------------\n\twho = new NodeNameType;\n\tstrcpy(who->Name, \"\");\n\twho->Game.IsOpen = 0;\n\twho->Game.LastTime = 0;\n\tSession.Games.Add (who);\n\titem = new char [MPLAYER_NAME_MAX];\n\tstrcpy(item, Text_String(TXT_LOBBY));\n\tgamelist.Add_Item(item);\n\tgamelist.Set_Selected_Index(0);\n\tgame_index = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tSend game-name query & chat announcement; also, initialize timers.\n\t//------------------------------------------------------------------------\n\tSend_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);\n\n\t/*\n\t** Process the message loop until we are in focus.\n\t*/\n\tCDTimerClass<SystemTimerClass> focus_timer;\t\t// Timer to allow a wait after client joins\n\tfocus_timer = 5*60;\n\n\tWWDebugString (\"RA95 - About to enter wait for focus loop.\\n\");\n\tSetForegroundWindow ( MainWindow );\n\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\n\tif (!GameInFocus) {\n\t\tdo {\n\t\t\tKeyboard->Check();\n\t\t\tif (!focus_timer){\n\t\t\t\tWWDebugString (\"RA95 - Calling SetForgroundWindow.\\n\");\n\t\t\t\tSetForegroundWindow ( MainWindow );\n\t\t\t\tWWDebugString (\"RA95 - Calling ShowWindow.\\n\");\n\t\t\t\tShowWindow ( MainWindow, SW_SHOWMAXIMIZED );\n\t\t\t\tfocus_timer = 5*60;\n\t\t\t}\n\t\t}while (!GameInFocus);\n\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t}\n\n\tif (LogicPage != &SeenBuff && LogicPage!= &HidPage) {\n\t\tSet_Logic_Page (SeenBuff);\n\t}\n\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\t//GamePalette.Set();\n\n\t//------------------------------------------------------------------------\n\t//\tProcessing loop\n\t//------------------------------------------------------------------------\n\twhile (process) {\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t//.....................................................................\n\t\t//\tRefresh display if needed\n\t\t//.....................................................................\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw backgound & dialog box\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\t//GamePalette.Set();\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tDialog & Field labels\n\t\t\t\t//...............................................................\n\t\t\t\tFancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tRebuild the button list\n\t\t\t\t//...............................................................\n\t\t\t\tcancelbtn.Zap();\n\t\t\t\tgamelist.Zap();\n\t\t\t\tplayerlist.Zap();\n\n\t\t\t\tcommands = &cancelbtn;\n\t\t\t\tgamelist.Add_Tail(*commands);\n\t\t\t\tplayerlist.Add_Tail(*commands);\n\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tRedraw buttons\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tGet user input\n\t\t//.....................................................................\n\t\tinput = commands->Input();\n\n\t\t//.....................................................................\n\t\t//\tProcess input\n\t\t//.....................................................................\n\t\tswitch (input) {\n\n\t\t\t//..................................................................\n\t\t\t// ESC / CANCEL: send a SIGN_OFF\n\t\t\t// - If we're part of a game, stay in this dialog; otherwise, exit\n\t\t\t//..................................................................\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t//...............................................................\n\t\t\t\t//\tIf we're joined to a game, make extra sure the other players in\n\t\t\t\t//\tthat game know I'm exiting; send my SIGN_OFF as an ack-required\n\t\t\t\t//\tpacket.  Don't send this to myself (index 0).\n\t\t\t\t//...............................................................\n\t\t\t\tif (joinstate == JOIN_CONFIRMED) {\n\t\t\t\t\tUnjoin_Game(namebuf, joinstate, &gamelist, &playerlist,\n\t\t\t\t\t\tgame_index, 1, 0, 0, d_txt6_h, 0,\n\t\t\t\t\t\t0, MAX_MESSAGE_LENGTH);\n\t\t\t\t\tjoinstate = JOIN_NOTHING;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// If I'm not joined to a game, send a SIGN_OFF to all players\n\t\t\t\t// in my Chat vector (but not to myself, index 0)\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\t\t\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\t\t\tstrcpy(Session.GPacket.Name,namebuf);\n\t\t\t\t\tfor (i = 1; i < Session.Chat.Count(); i++) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType),\n\t\t\t\t\t\t\t1, &(Session.Chat[i]->Address));\n\t\t\t\t\t\tIpx.Service();\n\t\t\t\t\t}\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tNow broadcast a SIGN_OFF just to be thorough\n\t\t\t\t\t//............................................................\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\tsizeof (GlobalPacketType), 0, NULL);\n\t\t\t\t\tif (Session.IsBridge) {\n\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\t\t\tsizeof(GlobalPacketType), 0, &Session.BridgeNet);\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// exit the dialog\n\t\t\t\t\t//............................................................\n\t\t\t\t\tSend_Data_To_DDE_Server (\"Hello\", strlen(\"Hello\"), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\t\tGameStatisticsPacketSent = false;\n\t\t\t\t\tSpawn_WChat(false);\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = -1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\n\t\t\t//..................................................................\n\t\t\t//\tJOIN: send a join request packet & switch to waiting-for-\n\t\t\t// confirmation mode.\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\tif (joinstate == JOIN_NOTHING && gamelist.Count() >1 ) {\n\t\t\t\t\tgamelist.Set_Selected_Index(1);\t//lastclick_idx);\n\t\t\t\t\tgame_index = 1;\n\t\t\t\t\tstrcpy (Session.Handle,namebuf);\n\t\t\t\t\t//Session.House = (HousesType)housebtn.Current_Index();\n\t\t\t\t\tjoin_index = gamelist.Current_Index();\n\t\t\t\t\tparms_received = 0;\n\t\t\t\t\tif (Request_To_Join (namebuf, join_index, Session.House,\n\t\t\t\t\t\tSession.ColorIdx)) {\n\t\t\t\t\t\tjoinstate = JOIN_WAIT_CONFIRM;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tResend our query packets\n\t\t//.....................................................................\n\t\tSend_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);\n\n\t\t//.....................................................................\n\t\t//\tProcess incoming packets\n\t\t//.....................................................................\n\t\tevent = Get_Join_Responses(&joinstate, &gamelist, &playerlist,\n\t\t\tjoin_index, namebuf, &why);\n\n\t\t//.....................................................................\n\t\t//\tIf we've changed state, redraw everything; if we're starting the game,\n\t\t//\tbreak out of the loop.  If we've just joined, send out a player query\n\t\t//\tso I'll get added to the list instantly.\n\t\t//.....................................................................\n\t\tif (event == EV_STATE_CHANGE) {\n\t\t\tdisplay = REDRAW_ALL;\n\t\t\tif (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {\n\t\t\t\tif (joinstate==JOIN_GAME_START_LOAD) load_game = 1;\n\n\t\t\t\tbool ready_packet_was_sent = false;\n\n\t\t\t\tif (!load_game){\n\t\t\t\t\t/*\n\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t**\n\t\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t\t**\n\t\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n\t\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tCCFileClass testfile ( Session.ScenarioFileName );\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** See if that scenario is available now. Its pretty fatal if it isnt.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t\t\t\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\t\t\t\t\t\t\t\tif (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){\n\t\t\t\t\t\t\t\t\t\tSession.Options.ScenarioIndex = i;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\t/*\n\t\t\t\t\t** If the scenario that the host wants to play doesnt exist locally then we\n\t\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t \t\t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif ( !ready_packet_was_sent ){\n\t\t\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Oh dear. Thats a scenario I dont have. Request that the host sends the\n\t\t\t\t\t\t**\tscenario to me provided its not an official Westwood scenario.\n\t\t\t\t\t\t**\n\t\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\t\tSession.Options.ScenarioIndex = -1;\n\t\t\t\t\t\t} else {\n#endif\n\t\t\t\t\t\t\tSession.Options.ScenarioIndex = 1;\t\t//We dont care what it\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//is as long as it isnt -1\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\t\tbreak;\n#endif\n\n\t\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure we respond to the host in a load game\n\t\t\t\t\t*/\n\t\t\t\t\tmemset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));\n\t\t\t\t\tSession.GPacket.Command = NET_READY_TO_GO;\n\t\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t\t\t1, &Session.HostAddress);\n\t\t\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);\n\t\t\t\t}\n\n\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\n\t\t\t\trc = 0;\n\t\t\t\tprocess = false;\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we're newly-confirmed, add myself to the Players list, and\n\t\t\t// immediately send out a player query\n\t\t\t//..................................................................\n\t\t\telse if (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t//...............................................................\n\t\t\t\t//\tClear the player list, then add myself to the list.\n\t\t\t\t//...............................................................\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\n\t\t\t\titem = new char [MPLAYER_NAME_MAX + 12];\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf, Text_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);\n\n\t\t\t\twho = new NodeNameType;\n\t\t\t\tstrcpy(who->Name, namebuf);\n\t\t\t\twho->Player.House = Session.House;\n\t\t\t\twho->Player.Color = Session.ColorIdx;\n\t\t\t\tSession.Players.Add (who);\n\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n#if (0)\n\t\t\t\t//...............................................................\n\t\t\t\t// Re-init the message system to its new smaller size\n\t\t\t\t//...............................................................\n\t\t\t\tSession.Messages.Init (0,0, 8,\n\t\t\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, 0, 0, 1,\n\t\t\t\t\t20, MAX_MESSAGE_LENGTH - 5);\n\t\t\t\tSession.Messages.Add_Edit(Session.ColorIdx, TPF_TEXT | TPF_BRIGHT_COLOR, NULL, '_');\n#endif\t//(0)\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tIf we've been rejected, clear any messages we may have been\n\t\t\t// typing, add a message stating why we were rejected, and send a\n\t\t\t// chat announcement.\n\t\t\t//..................................................................\n\t\t\telse if (joinstate==JOIN_REJECTED) {\n\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);\n\n\t\t\t}\n\t\t}\t// end of state change\n\n\t\t//.....................................................................\n\t\t//\tIf the game options have changed, print them.\n\t\t//.....................................................................\n\t\telse if (event == EV_GAME_OPTIONS) {\n\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\tparms_received = 1;\n\t\t\tdisplay = REDRAW_PARMS;\n\t\t}\n\n\n\t\t//.....................................................................\n\t\t// EV_GAME_SIGNOFF:\n\t\t//\tA game before the one I've selected is gone, so we have a new index\n\t\t// now. 'game_index' must be kept set to the currently-selected list\n\t\t// item, so we send out queries for the currently-selected game.  It's\n\t\t// therefore imperative that we detect any changes to the game list.\n\t\t// If we're joined in a game, we must decrement our game_index to keep\n\t\t// it aligned with the game we're joined to.\n\t\t//.....................................................................\n\t\telse if (event == EV_GAME_SIGNOFF) {\n\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\tgame_index--;\n\t\t\t\tjoin_index--;\n\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tService the Ipx connections\n\t\t//.....................................................................\n\t\tIpx.Service();\n\n\t\tif (process) {\n\t\t\t//.....................................................................\n\t\t\t//\tClean out the Game List; if an old entry is found:\n\t\t\t//\t- Remove it\n\t\t\t//\t- Clear the player list\n\t\t\t//\t- Send queries for the new selected game, if there is one\n\t\t\t//.....................................................................\n\t\t\tfor (i = 1; i < Session.Games.Count(); i++) {\n\t\t\t\tif (TickCount - Session.Games[i]->Game.LastTime > 400) {\n\n\t\t\t\t\tdelete Session.Games[i];\n\t\t\t\t\tSession.Games.Delete(Session.Games[i]);\n\n\t\t\t\t\titem = (char *)(gamelist.Get_Item (i));\n\t\t\t\t\tgamelist.Remove_Item (item);\n\t\t\t\t\tdelete [] item;\n\n\t\t\t\t\tif (i <= game_index) {\n\t\t\t\t\t\tif (joinstate==JOIN_CONFIRMED) {\n\t\t\t\t\t\t\tgame_index--;\n\t\t\t\t\t\t\tjoin_index--;\n\t\t\t\t\t\t\tgamelist.Set_Selected_Index(join_index);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\t\tClear_Listbox(&playerlist);\n\t\t\t\t\t\t\tClear_Vector (&Session.Players);\n\t\t\t\t\t\t\tgame_index = gamelist.Current_Index();\n\t\t\t\t\t\t\tSend_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#if (0)\n\t\t/*\n\t\t** If we were flagged to start the game and we recognise both players then quit the loop\n\t\t*/\n\t\tif (ready_to_go && Session.Players.Count() == 2) {\n\t\t\trc = 0;\n\t\t\tprocess = false;\n\t\t}\n#endif\t//(0)\n\n\t\t//.....................................................................\n\t\t//\tService the sounds & score; GameActive must be false at this point,\n\t\t//\tso Call_Back() doesn't intercept global messages from me!\n\t\t//.....................................................................\n\t\tCall_Back();\n\n\t}\t// end of while\n\n\n\t//------------------------------------------------------------------------\n\t//\tEstablish connections with all other players.\n\t//------------------------------------------------------------------------\n\tif (rc == 0) {\n\t\t//.....................................................................\n\t\t//\tIf the other guys are playing a scenario I don't have (sniff), I can't\n\t\t//\tplay.  Try to bail gracefully.\n\t\t//.....................................................................\n\t\tif (Session.Options.ScenarioIndex==-1) {\n\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\n\t\t\tmemset (&Session.GPacket, 0, sizeof(GlobalPacketType));\n\n\t\t\tSession.GPacket.Command = NET_SIGN_OFF;\n\t\t\tstrcpy (Session.GPacket.Name, namebuf);\n\n\t\t\t//..................................................................\n\t\t\t// Don't send myself the message.\n\t\t\t//..................................................................\n\t\t\tfor (i = 1; i < Session.Players.Count(); i++) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket,\n\t\t\t\t\tsizeof(GlobalPacketType), 1,\n\t\t\t\t\t&(Session.Players[i]->Address));\n\t\t\t\tIpx.Service();\n\t\t\t}\n\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),\n\t\t\t\t0, NULL);\n\n\t\t\tif (Session.IsBridge) {\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t\tIpx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),\n\t\t\t\t\t0, &Session.BridgeNet);\n\t\t\t}\n\n\t\t\twhile (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;\n\n\t\t\trc = -1;\n\n\t\t}\n\t\t//---------------------------------------------------------------------\n\t\t// Prepare to load the scenario.\n\t\t//---------------------------------------------------------------------\n\t\telse {\n\t\t\t//..................................................................\n\t\t\t//\tSet the number of players in this game, and the scenario number.\n\t\t\t//..................................................................\n\t\t\tSession.NumPlayers = Session.Players.Count();\n///*\n//**\tHack to fake a scenario name as if it had been sent over the connection.\n//*/\n//sprintf(Scen.ScenarioName, \"SCM%02dEA.INI\", Session.Options.ScenarioIndex+1);\n\n//\t\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tWait a while, polling the IPX service routines, to give our ACK\n\t\t//\ta chance to get to the other system.  If he doesn't get our ACK,\n\t\t// he'll be waiting the whole time we load MIX files.\n\t\t//.....................................................................\n\t\ti = MAX((int)Ipx.Global_Response_Time() * 2, 60*2);\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < (unsigned)i) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing values, using previous response times as a measure\n\t//\tof what our retry delta & timeout should be.\n\t//------------------------------------------------------------------------\n\t//Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,\n\t//\tIpx.Global_Response_Time() * 4);\n\tIpx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));\n\n\t//------------------------------------------------------------------------\n\t//\tClear all lists, but NOT the Games & Players vectors.\n\t//------------------------------------------------------------------------\n\tClear_Listbox(&gamelist);\n\tClear_Listbox(&playerlist);\n\n\t//------------------------------------------------------------------------\n\t//\tRestore screen\n\t//------------------------------------------------------------------------\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\t//------------------------------------------------------------------------\n\t// Load a game if the game owner told us to\n\t//------------------------------------------------------------------------\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = -1;\n\t\t}\n\t\tFrame++;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Clear the Players & Games vectors if we're not joined to a game.\n\t// Clear the Chat vector regardless.\n\t//------------------------------------------------------------------------\n\tif (rc != 0) {\n\t\tClear_Vector(&Session.Games);\n\t\tClear_Vector(&Session.Players);\n\t}\n\tClear_Vector(&Session.Chat);\n\n\treturn(rc);\n\n#else\t//WIN32\n\n\treturn (0);\n\n#endif\t//WIN32\n\n}\t/* end of Net_Join_Dialog */\n\n\n\n\n\n\n\n\n\n\nbool Server_Remote_Connect(void)\n{\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tRead in last multiplayer game settings from the .INI file\n\t//------------------------------------------------------------------------\n\tif (!Net_Fake_New_Dialog()) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t\treturn (false);\n\t}\n\n\tSession.NetOpen = 0;\n\tSession.NetStealth = stealth;\n\tSession.Write_MultiPlayer_Settings ();\n\treturn (true);\n\n}\t/* end of Server_Remote_Connect */\n\n\n\n\n\n\n\nbool Client_Remote_Connect(void)\n{\n\tint rc;\n\tint stealth;\t\t\t\t// original state of Session.NetStealth flag\n\n\t//------------------------------------------------------------------------\n\t//\tInit network timing parameters; these values should work for both a\n\t// \"real\" network, and a simulated modem network (ie Kali)\n\t//------------------------------------------------------------------------\n\tIpx.Set_Timing (\t30, \t\t// retry 2 times per second\n\t\t\t\t\t\t\t-1, \t\t// ignore max retries\n\t\t\t\t\t\t\t600);\t\t// give up after 10 seconds\n\n\t//------------------------------------------------------------------------\n\t//\tSave the original value of the NetStealth flag, so we can turn stealth\n\t//\toff for now (during this portion of the dialogs, we must show ourselves)\n\t//------------------------------------------------------------------------\n\tstealth = Session.NetStealth;\n\tSession.NetStealth = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tThe game is now \"open\" for joining.  Close it as soon as we exit this\n\t//\troutine.\n\t//------------------------------------------------------------------------\n\tSession.NetOpen = 1;\n\n\t//------------------------------------------------------------------------\n\t//\tRead in last multiplayer game settings from the .INI file\n\t//------------------------------------------------------------------------\n\trc = Net_Fake_Join_Dialog();\n\tSession.Write_MultiPlayer_Settings ();\n\n\tSession.NetStealth = stealth;\n\tSession.NetOpen = 0;\n\n\tif (rc == -1) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n\n}\t/* end of Client_Remote_Connect */\n\n\n\n/*************************** end of netdlg.cpp *****************************/\n\n#endif\t//#ifndef WOLAPI_INTEGRATION\n#endif"
  },
  {
    "path": "REDALERT/NOSEQCON.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\noseqcon.cpv   1.10   01 Mar 1996 18:08:30   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NonSequencedConnClass::NonSequencedConnClass -- class constructor     *\n *   NonSequencedConnClass::~NonSequencedConnClass -- class destructor     *\n *   NonSequencedConnClass::Init -- Initializes connection queue to empty\t*\n *   NonSequencedConnClass::Send_Packet -- adds a packet to the send queue\t*\n *   NonSequencedConnClass::Receive_Packet -- adds packet to receive queue\t*\n *   NonSequencedConnClass::Get_Packet -- gets a packet from receive queue\t*\n *   NonSequencedConnClass::Service_Send_Queue -- services the send queue\t*\n *   NonSequencedConnClass::Service_Receive_Queue -- services recieve queue*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"NOSEQCON.H\"\n\n\n/***************************************************************************\n * NonSequencedConnClass::NonSequencedConnClass -- class constructor       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the recieve queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNonSequencedConnClass::NonSequencedConnClass (int numsend, int numreceive, \n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout) :\n\tConnectionClass (maxlen, magicnum, retry_delta, max_retries, timeout)\n{\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (which will\n\tbe placed there by the Connection Manager), and outgoing packets (which\n\tare placed there by this class when it \"sends\" a packet).\n\t------------------------------------------------------------------------*/\n\tQueue = new CommBufferClass (numsend, numreceive, MaxPacketLen);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::~NonSequencedConnClass -- class destructor       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNonSequencedConnClass::~NonSequencedConnClass ()\n{\n\tdelete Queue;\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Init -- Initializes connection queue to empty\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid NonSequencedConnClass::Init (void)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\tLastSeqID = 0xffffffff;\n\tLastReadID = 0xffffffff;\n\n\tQueue->Init();\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Send_Packet -- adds a packet to the send queue\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\ttrue = ACK is required for this packet; false = isn't\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*........................................................................\n\tSet the magic # for the packet\n\t........................................................................*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*........................................................................\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t........................................................................*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t} else {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*........................................................................\n\tNow build the packet\n\t........................................................................*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*........................................................................\n\tAdd it to the queue.\n\t........................................................................*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType))) {\n\t\tif (ack_req) {\n// Smart_Printf( \"Packet ack Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\t\tNumSendAck++;\n\t\t} else {\n// Smart_Printf( \"Packet noack Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(true);\n\t} else {\n// Smart_Printf( \"Packet not Queued ID %d \\n\", ((CommHeaderType *)PacketBuf)->PacketID );\n\t\treturn(false);\n\t}\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t\t\t\t// ptr to packet header\n\tSendQueueType *send_entry;\t\t\t\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t\t\t\t// ptr to recv entry header\n\tCommHeaderType *entry_data;\t\t\t\t\t\t// ptr to queue entry data\n\tCommHeaderType ackpacket;\t\t\t\t\t\t\t// ACK packet to send\n\tint i;\n\tint save_packet = 1;\t\t\t\t\t\t\t\t\t// 0 = this is a resend\n\tint found;\n\n\t/*\n\t--------------------------- Check the magic # ----------------------------\n\t*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber != MagicNum) {\n// Smart_Printf( \"Bad Magic Number\\n\" );\n\t\treturn(false);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming ACK\n\t------------------------------------------------------------------------*/\n\tif (packet->Code == PACKET_ACK) {\n\n\t\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t\t/*\n\t\t\t....................... Get queue entry ptr ........................\n\t\t\t*/\n\t\t\tsend_entry = Queue->Get_Send(i);\n\t\t\t/*\n\t\t\t............... If ptr is valid, get ptr to its data ...............\n\t\t\t*/\n\t\t\tif (send_entry != NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\t/*\n\t\t\t\t.............. If ACK is for this entry, mark it ................\n\t\t\t\t*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID && \n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Received ACK for %d \\n\", packet->PacketID );\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n//{\n//\t\tif (i == Queue->Num_Send() ) {\n// Smart_Printf( \"Received bad ACK for %d \\n\", packet->PacketID );\n//\t\t}\n//}\n\n\t\treturn(true);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_NOACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_NOACK) {\n\t\t/*---------------------------------------------------------------------\n\t\tIf there's only one slot left, don't tie up the queue with this packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n// Smart_Printf( \"Only one slot left don't tie up with DATA NOACK packet %d \\n\", packet->PacketID );\n\t\t\t\treturn(false);\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tError if we can't queue the packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (!Queue->Queue_Receive (buf, buflen)) {\n// Smart_Printf( \"Can't Queue the packet %d \\n\", packet->PacketID );\n\t\t\treturn(false);\n\t\t}\n\n// Smart_Printf( \"Queued DATA NOACK for %d \\n\", packet->PacketID );\n\t\tNumRecNoAck++;\n\n\t\treturn(true);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tHandle an incoming PACKET_DATA_ACK packet\n\t------------------------------------------------------------------------*/\n\telse if (packet->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Looking at ID %d, LastSeqID=%d \\n\", packet->PacketID, LastSeqID );\n\t\t/*....................................................................\n\t\tIf this is a packet requires an ACK, and it's ID is older than our\n\t\t\"oldest\" ID, we know it's a resend; send an ACK, but don't queue it\n\t\t....................................................................*/\n\t\tif (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {\n// Smart_Printf( \"Older than oldest\\n\" );\n\t\t\tsave_packet = 0;\n\t\t}\n\t\t/*....................................................................\n\t\tOtherwise, scan the queue for this entry; if it's found, it's a\n\t\tresend, so don't save it.\n\t\t....................................................................*/\n\t\telse {\n\t\t\tsave_packet = 1;\n\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\t\t\trec_entry = Queue->Get_Receive(i);\n\t\t\t\tif (rec_entry) {\n\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\t\t\t\t\t/*...........................................................\n\t\t\t\t\tPacket is found; it's a resend\n\t\t\t\t\t...........................................................*/\n\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\tentry_data->PacketID == packet->PacketID) {\n// Smart_Printf( \"It's a resend\\n\" );\n\t\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t/* end of scan for resend */\n\n\t\t/*---------------------------------------------------------------------\n\t\tQueue the packet & update our LastSeqID value.\n\t\t---------------------------------------------------------------------*/\n\t\tif (save_packet) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tIf there's only one slot left, make sure we only put a packet in it if\n\t\t\tthis packet will let us increment our LastSeqID; otherwise, we'll get\n\t\t\tstuck, forever unable to increment LastSeqID.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {\n\t\t\t\tif (packet->PacketID != (LastSeqID + 1) ) {\n// Smart_Printf( \"One slot left not what we looking for max=%d,num=%d \\n\",\n//\tQueue->Max_Receive(), Queue->Num_Receive() );\n\t\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tIf we can't queue the packet, return; don't send an ACK.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (!Queue->Queue_Receive (buf, buflen)) {\n// Smart_Printf( \"unable to queue packet\\n\" );\n\t\t\t\treturn(0);\n\t\t\t}\n\n\t\t\tNumRecAck++;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUpdate our LastSeqID value if we can.  Anything less than LastSeqID\n\t\t\twe'll know is a resend.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tif (packet->PacketID == (LastSeqID + 1)) {\n\t\t\t\tLastSeqID = packet->PacketID;\n\t\t\t\t/*............................................................\n\t\t\t\tNow that we have a new 'LastSeqID', search our Queue to see if\n\t\t\t\tthe next ID is there; if so, keep checking for the next one;\n\t\t\t\tbreak only when the next one isn't found.  This forces \n\t\t\t\tLastSeqID to be the largest possible value.\n\t\t\t\t............................................................*/\n\t\t\t\tdo {\n\t\t\t\t\tfound = 0;\n\t\t\t\t\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\t\t\t\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t\t\t\t\t/*......................................................\n\t\t\t\t\t\t\tEntry is found\n\t\t\t\t\t\t\t......................................................*/\n\t\t\t\t\t\t\tif (entry_data->Code == PACKET_DATA_ACK &&\n\t\t\t\t\t\t\t\tentry_data->PacketID == (LastSeqID + 1)) {\n\n\t\t\t\t\t\t\t\tLastSeqID = entry_data->PacketID;\n\t\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} while (found);\n\t\t\t}\n\t\t}\t/* end of save packet */\n\n\t\t/*---------------------------------------------------------------------\n\t\tSend an ACK, regardless of whether this was a resend or not.\n\t\t---------------------------------------------------------------------*/\n\t\tackpacket.MagicNumber = Magic_Num();\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet->PacketID;\n// Smart_Printf( \"Sending ACK for %d \\n\", packet->PacketID );\n\t\tSend ((char *)&ackpacket, sizeof(CommHeaderType));\n\n\t\treturn(true);\n\n\t} else {\n// Smart_Printf( \"invalid packet type %d \\n\", packet->Code );\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Get_Packet -- gets a packet from receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\tCommHeaderType *entry_data;\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tEnsure that we read the packets in order.  LastReadID is the ID of the\n\tlast PACKET_DATA_ACK packet we read.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\t/*.....................................................................\n\t\tOnly read this entry if it hasn't been yet\n\t\t.....................................................................*/\n\t\tif (rec_entry && rec_entry->IsRead==0) {\n\n\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_ACK packet, its ID must be one greater than\n\t\t\tthe last one we read.\n\t\t\t..................................................................*/\n\t\t\tif ( (entry_data->Code == PACKET_DATA_ACK) &&\n\t\t\t\t(entry_data->PacketID == (LastReadID + 1))) {\n\n\t\t\t\tLastReadID = entry_data->PacketID;\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\t/*..................................................................\n\t\t\tIf this is a DATA_NOACK packet, who cares what the ID is?\n\t\t\t..................................................................*/\n\t\t\telse if (entry_data->Code == PACKET_DATA_NOACK) {\n\n\t\t\t\trec_entry->IsRead = 1;\n\n\t\t\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\t\t\tif (packetlen > 0) {\n\t\t\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t\t\t}\n\t\t\t\t(*buflen) = packetlen;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Service_Send_Queue -- services the send queue\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Service_Send_Queue (void)\n{\n\tint i;\n\tint num_entries;\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\tint bad_conn = 0;\n\n\t/*------------------------------------------------------------------------\n\tRemove any ACK'd packets from the queue\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Send(); i++) {\n\t\t/*\n\t\t------------------------- Get this queue entry ------------------------\n\t\t*/\n\t\tsend_entry = Queue->Get_Send(i);\n\t\t/*\n\t\t---------------- If ACK has been received, unqueue it -----------------\n\t\t*/\n\t\tif (send_entry->IsACK) {\n\t\t\t/*\n\t\t\t................ Update this queue's response time .................\n\t\t\t*/\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t\t}\n\t\t\t/*\n\t\t\t....................... unqueue the packet .........................\n\t\t\t*/\n\t\t\tQueue->UnQueue_Send(NULL,NULL,i);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tLoop through all entries in the Send queue.  [Re]Send any entries that\n\tneed it.\n\t------------------------------------------------------------------------*/\n\tnum_entries = Queue->Num_Send();\n\n\tfor (i = 0; i < num_entries; i++) {\n\t\tsend_entry = Queue->Get_Send(i);\n\n\t\tif (send_entry->IsACK) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\t\t\t/*\n\t\t\t......................... Send the message .........................\n\t\t\t*/\n#if(0)\n{\n\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (send_entry->SendCount) {\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n// Smart_Printf( \"Resending DATA NOACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t} else {\n\t\t\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Resending DATA ACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} else {\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n// Smart_Printf( \"Sending DATA NOACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t} else {\n\t\t\t\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n// Smart_Printf( \"Sending DATA ACK for %d \\n\", packet_hdr->PacketID );\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t}\n}\n#endif\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen);\n\n\t\t\t/*\n\t\t\t....................... Fill in Time fields ........................\n\t\t\t*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*\n\t\t\t......................... Update SendCount .........................\n\t\t\t*/\n\t\t\tsend_entry->SendCount++;\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {\n// Smart_Printf( \"Max Retries!!! %d !!! \\n\", MaxRetries );\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\n\t\t\tif (Timeout != -1 &&\n\t\t\t\t(send_entry->LastTime - send_entry->FirstTime) > Timeout) {\n// Smart_Printf( \"Timed out!!! Time %d, Timeout %d, buflen %d !!! \\n\",\n//\t(send_entry->LastTime - send_entry->FirstTime), Timeout,\n//\tsend_entry->BufLen );\n\t\t\t\tbad_conn = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the connection is going bad, return an error\n\t------------------------------------------------------------------------*/\n\tif (bad_conn) {\n// Smart_Printf( \"Connection going bad!!! \\n\" );\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***************************************************************************\n * NonSequencedConnClass::Service_Receive_Queue -- services recieve queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NonSequencedConnClass::Service_Receive_Queue (void)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tint i;\n\n\t/*------------------------------------------------------------------------\n\tRemove all dead packets.  \n\tPACKET_DATA_NOACK: if it's been read, throw it away.\n\tPACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,\n\tthrow it away.\n\t------------------------------------------------------------------------*/\n\tfor (i = 0; i < Queue->Num_Receive(); i++) {\n\t\trec_entry = Queue->Get_Receive(i);\n\n\t\tif (rec_entry->IsRead) {\n\t\t\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\n\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i);\n\t\t\t\ti--;\n\t\t\t} else {\n\t\t\t\tif (packet_hdr->PacketID < LastSeqID) {\n\t\t\t\t\tQueue->UnQueue_Receive(NULL,NULL,i);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n"
  },
  {
    "path": "REDALERT/NOSEQCON.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\noseqcon.h_v   1.13   01 Mar 1996 17:32:42   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NOSEQCON.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class provides a \"Non-Sequenced\" ACK/Retry approach to packet\t\t*\n * transmission.  It sends out as many packets as are in the queue, whose\t*\n * resend delta times have expired; and it ACK's any packets its received\t*\n * who haven't been ACK'd yet.  Thus, order of delivery is NOT guaranteed;\t*\n * however, the performance is better than the Sequenced approach.\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tA derived class must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NONSEQCONN_H\n#define NONSEQCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n#include \"combuf.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NonSequencedConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tNonSequencedConnClass (int numsend, int numrecieve, int maxlen, \n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout);\n\t\tvirtual ~NonSequencedConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int *buflen);\n\n\t\t/*.....................................................................\n\t\tThe packet \"queue\"; this non-sequenced version isn't really much of\n\t\ta queue, but more of a repository.\n\t\t.....................................................................*/\n\t\tCommBufferClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue (void);\n\t\tvirtual int Service_Receive_Queue (void);\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK, \n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the last consecutively-received packet; anything older \n\t\tthan this, we know is a resend.  Anything newer than this MUST be lying \n\t\taround in the Queue for us to detect it as a resend.\n\t\t.....................................................................*/\n\t\tunsigned long LastSeqID;\n\n\t\t/*.....................................................................\n\t\tThis is the ID of the PACKET_DATA_ACK packet we read last; it ensures\n\t\tthat the application reads that type of packet in order.\n\t\t.....................................................................*/\n\t\tunsigned long LastReadID;\n};\n\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/NULLCONN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/NULLCONN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLCONN.CPP                             *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : April 5, 1995\t\t                        *\n *                                                                         *\n *                  Last Update : April 20, 1995   [DRD]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NullModemConnClass::NullModemConnClass -- class constructor           *\n *   NullModemConnClass::~NullModemConnClass -- class destructor           *\n *   NullModemConnClass::Init -- hardware-dependent initialization\t\t\t*\n *   NullModemConnClass::Send -- hardware-dependent packet sending\t\t\t*\n *   NullModemConnClass::Compute_CRC -- computes CRC for given buffer\t\t*\n *   NullModemConnClass::Packet_Overhead_Size -- number of extra bytes     *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#ifdef WIN32\n#include \"wincomm.h\"\n#endif\t//WIN32\n#include <stdio.h>\n//#include <mem.h>\n#include \"nullconn.h\"\n\n\n/***************************************************************************\n * NullModemConnClass::NullModemConnClass -- class constructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # send queue entries\t\t\t\t\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # send receive entries\t\t\t\t\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of application's packets\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tapplication-defined magic # for the packets\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemConnClass::NullModemConnClass (int numsend, int numreceive,\n\tint maxlen, unsigned short magicnum) :\n\tConnectionClass (numsend, numreceive, maxlen, magicnum,\n\t\t60, \t\t\t// Retry Delta Time\n\t\t-1, \t\t\t// Max Retries (-1 means ignore this timeout parameter)\n\t\t1200)\t\t\t// Timeout: 20 seconds\n{\n\t/*------------------------------------------------------------------------\n\tPre-set the port value to NULL, so Send won't send until we've been Init'd\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tPortHandle = NULL;\n#else\t//WIN32\n\tPort = NULL;\n#endif\t//WIN32\n\t/*------------------------------------------------------------------------\n\tAllocate the Send Buffer; the parent constructor has set MaxPacketLen,\n\tso we can use it in our computation.\n\t------------------------------------------------------------------------*/\n\tSendBuf = new char [ Actual_Max_Packet() ];\n\n}\t/* end of NullModemConnClass */\n\n\n/***************************************************************************\n * NullModemConnClass::~NullModemConnClass -- class destructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemConnClass::~NullModemConnClass ()\n{\n\tdelete [] SendBuf;\n\n}\t/* end of ~NullModemConnClass */\n\n\n/***************************************************************************\n * NullModemConnClass::Init -- hardware-dependent initialization\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tport\t\tGreenLeaf port handle\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\n#ifdef WIN32\nvoid NullModemConnClass::Init (HANDLE port_handle)\n{\n\tConnectionClass::Init();\n\tPortHandle = port_handle;\n}\n#else\t//WIN32\nvoid NullModemConnClass::Init (PORT *port)\n{\n\tConnectionClass::Init();\n\tPort = port;\n}\t/* end of Init */\n#endif\t//WIN32\n\n/***************************************************************************\n * NullModemConnClass::Send -- hardware-dependent packet sending\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer to send\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textrabuf\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *\t\textralen\t\t(not used by this class)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemConnClass::Send (char *buf, int buflen, void *, int )\n{\n\treturn 0;\n#if (0)//PG\n\tint *ibuf;\n\tSerialHeaderType *header;\n\tunsigned long sendlen;\n\n\t/*------------------------------------------------------------------------\n\tError if we haven't been properly initialized\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tif ( PortHandle == NULL ) return(false);\n\n#else\t//WIN32\n\tint status;\n\tif ( Port == NULL ) {\n\t\treturn(0);\n\t}\n#endif\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tPackage the data into the Send Buffer\n\t------------------------------------------------------------------------*/\n\theader = (SerialHeaderType *) SendBuf;\n\theader->MagicNumber\t= PACKET_SERIAL_START;\n\theader->Length\t\t\t= (short) buflen;\n\theader->MagicNumber2\t= PACKET_SERIAL_VERIFY;\n\n\tsendlen = sizeof( SerialHeaderType );\n\tmemcpy (SendBuf + sendlen, buf, buflen);\n\tsendlen += buflen;\n\tibuf = (int *)(SendBuf + sendlen);\n\t*ibuf = Compute_CRC( buf, buflen );\n\tsendlen += sizeof( int );\n\n\t*(SendBuf + sendlen) = '\\r';\n\tsendlen += 1;\n\n\t/*------------------------------------------------------------------------\n\tSend the data\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\t\tSerialPort->Write_To_Serial_Port((unsigned char *)SendBuf, (int)sendlen );\n\t\treturn (true);\n\n#else\t//WIN32\n\tstatus = WriteBuffer( Port, SendBuf, sendlen );\n\tif ( status == ASSUCCESS ) {\n\t\treturn(1);\n\t}\n\telse {\n\t\treturn(0);\n\t}\n#endif\t//WIN32\n#endif//PG\n}\t/* end of Send */\n\n\n/***************************************************************************\n * NullModemConnClass::Compute_CRC -- computes CRC for given buffer\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to compute CRC for\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tlength of buffer in bytes\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemConnClass::Compute_CRC (char *buf, int buflen)\n{\n\tunsigned int sum, hibit;\n\n\tsum = 0;\n\tfor (int i = 0; i < buflen; i++) {\n\t\tif ( sum & 0x80000000 ) {\t\t// check hi bit to rotate into low bit\n\t\t\thibit = 1;\n\t\t}\n\t\telse {\n\t\t\thibit = 0;\n\t\t}\n\n\t\tsum <<= 1;\n\t\tsum += (hibit + (unsigned char)buf[i]);\n\t}\n\n\treturn((int)sum);\n\n}\t/* end of Compute_CRC */\n\n\n/***************************************************************************\n * NullModemConnClass::Packet_Overhead_Size -- number of extra bytes       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnumber of bytes used for communications only.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/20/1995 DRD : Created.                                             *\n *=========================================================================*/\nint NullModemConnClass::Packet_Overhead_Size ( void )\n{\n\t/*------------------------------------------------------------------------\n\tshort for Null Modem Magic Number\n\tshort for Null Modem length of packet\n\tint for Null Modem CRC check\n\tCommHeaderType for Queued packets\n\t------------------------------------------------------------------------*/\n\treturn( (PACKET_SERIAL_OVERHEAD_SIZE + sizeof(CommHeaderType)) );\n\n}\t/* end of Packet_Overhead_Size */\n\n/************************** end of nullconn.cpp ****************************/\n"
  },
  {
    "path": "REDALERT/NULLCONN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/NULLCONN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLCONN.H                               *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Class for a NULL-Modem connection.  It inherits\t*\n * a Queue, PacketBuf, timeout variables from ConnectionClass.  It \t\t\t*\n * inherits its Send_/Receive_/Get_Packet functions, and the non-sequenced\t*\n * ACK/Retry logic in Service_Send_Queue & Service_Receive_Queue from\t\t*\n * ConnectionClass.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NULLCONN_H\n#define NULLCONN_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"connect.h\"\n//#include \"commlib.h\"\n\n/*\n********************************** Defines **********************************\n*/\n#define\tPACKET_SERIAL_START\t\t\t\t0xDABD\n#define\tPACKET_SERIAL_VERIFY\t\t\t\t0xDEAF\n\n#define\tPACKET_SERIAL_OVERHEAD_SIZE\t(sizeof( SerialHeaderType ) + sizeof( SerialCRCType ))\n\ntypedef struct {\n\tunsigned short MagicNumber;\n\tunsigned short Length;\n\tunsigned short MagicNumber2;\n} SerialHeaderType;\n\ntypedef struct {\n\tint SerialCRC;\n} SerialCRCType;\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NullModemConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tNullModemConnClass (int numsend, int numrecieve, int maxlen,\n\t\t\tunsigned short magicnum);\n\t\tvirtual ~NullModemConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n#ifdef WIN32\n\t\tvoid Init (HANDLE port_handle);\n#else\t//WIN32\n\t\tvoid Init (PORT *port);\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tUtility routines.\n\t\t.....................................................................*/\n\t\tunsigned long Actual_Max_Packet (void) { return (MaxPacketLen +\n\t\t\t(sizeof(SerialHeaderType)) + sizeof(int) + sizeof (char)); }\n\n\t\t/*.....................................................................\n\t\tThis routine computes a CRC value for the given buffer.\n\t\t.....................................................................*/\n\t\tstatic int Compute_CRC(char *buf, int buflen);\n\n\t\t/*.....................................................................\n\t\tThis routine returns the number of bytes extra added the packet\n\t\tfor communication.\n\t\t.....................................................................*/\n\t\tstatic int Packet_Overhead_Size( void );\n\n\t/*\n\t--------------------------- Private Interface ----------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tThis routine actually performs a hardware-dependent data send.\n\t\t.....................................................................*/\n\t\tvirtual int Send (char *buf, int buflen, void *extrabuf, int extralen);\n#ifdef WIN32\n\t\t/*\n\t\t** This is the winsoze port handle\n\t\t*/\n\t\tHANDLE PortHandle;\n#else\t//WIN32\n\t\t/*.....................................................................\n\t\tThis is the PORT value used by the GreenLeaf calls.\n\t\t.....................................................................*/\n\t\tPORT *Port;\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tThis buffer is a staging area for data sent out; it includes the\n\t\tpacket sent by the parent class (which includes the application's\n\t\tpacket, plus the CommHeaderType header), plus:\n\t\t- 2-byte buffer start ID\n\t\t- 2-byte length\n\t\t- 4-byte CRC value (at the end of the buffer)\n\t\tThis is the actual packet that gets sent across the serial line.\n\t\t.....................................................................*/\n\t\tchar *SendBuf;\n};\n\n#endif\n\n/************************** end of nullconn.h ******************************/\n\n"
  },
  {
    "path": "REDALERT/NULLDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/NULLDLG.CPP 14    3/17/97 1:05a Steve_tall $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLDLG.CPP                              *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 04/29/95                                 *\n *                                                                         *\n *                  Last Update : Jan. 21, 1997 [V.Grippi]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   Build_InitString_Listbox -- [re]builds the initstring entry listbox   *\n *   Build_Phone_Listbox -- [re]builds the phone entry listbox             *\n *   Com_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t*\n *   Com_Settings_Dialog -- Lets user select serial port settings          *\n *   Destroy_Null_Connection -- destroys the given connection\t\t\t\t\t*\n *   Edit_Phone_Dialog -- lets user edit a phone book entry                *\n *   Init_Null_Modem -- Initializes Null Modem communications              *\n *   Init_String_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Phone_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Phone_Dialog -- Lets user edit phone directory & dial                 *\n *   Reconnect_Null_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t*\n *   Select_Serial_Dialog -- Serial Communications menu dialog             *\n *   Shutdown_Modem -- Shuts down modem/null-modem communications          *\n *   Test_Null_Modem -- Null-Modem test routine                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n//PG\nGameType Select_Serial_Dialog(void) { return GAME_NORMAL; }\n\n\n\n\n\n#if (0)//PG\n#ifdef FIXIT_RANDOM_GAME\n#include \"time.h\"\n#endif\n#ifdef WIN32\n#include \"wincomm.h\"\n#include \"modemreg.h\"\nModemRegistryEntryClass *ModemRegistry = NULL;\t\t//Ptr to modem registry data\n#endif\t//WIN32\n#include \"COORDA.h\"\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_126x126 (char *file_name);\nextern bool Is_Mission_Counterstrike (char *file_name);\nextern bool Is_Mission_Aftermath( char* file_name );\n#endif\n\n//#include \"WolDebug.h\"\n\n//\n// how much time (ticks) to go by before thinking other system\n// is not responding.\n//\n#define PACKET_SENDING_TIMEOUT\t1800\n#define PACKET_CANCEL_TIMEOUT\t\t900\n\n//extern char const *ForMisStr[];\nextern char const *EngMisStr[];\n\n\n//\n// how much time (ticks) to go by before sending another packet\n// of game options or serial connect.\n//\n#define PACKET_RETRANS_TIME\t30\n#define PACKET_REDRAW_TIME\t\t60\n\nstatic int Reconnect_Null_Modem( void );\nstatic int Com_Settings_Dialog( SerialSettingsType *settings );\nstatic int Phone_Dialog (void);\nstatic void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index);\nstatic int Init_String_Compare (const void *p1, const void *p2);\nstatic void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf);\nstatic int Phone_Compare (const void *p1, const void *p2);\nstatic int Edit_Phone_Dialog (PhoneEntryClass *phone);\nstatic bool Dial_Modem( SerialSettingsType *settings, bool reconnect );\nstatic bool Answer_Modem( SerialSettingsType *settings, bool reconnect );\nstatic void Modem_Echo( char c );\n\nvoid Smart_Printf( char *format, ... );\nvoid Hex_Dump_Data( char *buffer, int length );\nvoid itoh( int i, char *s);\n\n\nstatic SerialPacketType SendPacket;\nstatic SerialPacketType ReceivePacket;\nchar TheirName[MPLAYER_NAME_MAX];\nPlayerColorType TheirColor;\nHousesType TheirHouse;\nstatic char DialString[ CWAITSTRBUF_MAX + PhoneEntryClass::PHONE_MAX_NUM - 1 ];\nstatic SerialSettingsType *DialSettings;\n\n#ifdef FIXIT_VERSION_3\nbool Force_Scenario_Available( const char* szName );\nbool bSpecialAftermathScenario( const char* szScenarioDescription );\n#endif\n\n#define PCOLOR_BROWN\tPCOLOR_GREY\n\n\n#define SHOW_MONO\t0\n\n/***************************************************************************\n * Init_Null_Modem -- Initializes Null Modem communications                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *   8/2/96      ST : Win32 support added                                  *\n *=========================================================================*/\nint Init_Null_Modem( SerialSettingsType *settings )\n{\n\n#ifdef WIN32\n\tif ( NullModem.Init( settings->Port, settings->IRQ,\n\t\t\t\t\t\t\t\tsettings->ModemName,\n\t\t\t\t\t\t\t\tsettings->Baud, 0,  8, 1,\n\t\t\t\t\t\t\t\tsettings->HardwareFlowControl ) ) {\n\t\treturn (true);\n\t} else {\n\t\treturn (false);\n\t}\n\n#else\t//WIN32\n\tif ( NullModem.Init( settings->Port, settings->IRQ,\n\t\t\t\t\t\t\t\tsettings->ModemName,\n\t\t\t\t\t\t\t\tsettings->Baud, 'N',  8, 1,\n\t\t\t\t\t\t\t\tsettings->HardwareFlowControl) ) {\n\t\tNullModem.Change_IRQ_Priority( settings->IRQ );\n\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n#endif\t//WIN32\n}\n\n\n/***************************************************************************\n * Shutdown_Modem -- Shuts down modem/null-modem communications            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Shutdown_Modem( void )\n{\n\tif (!Session.Play) {\n\t\tif (Session.Type == GAME_MODEM) {\n\t\t\tNullModem.Hangup_Modem();\n\t\t}\n\t}\n\n\tNullModem.Change_IRQ_Priority( 0 );\t\t// reset priority of interrupts\n\n\t//\n\t// close port\n\t//\n\tNullModem.Shutdown();\n}\n\n\n/***************************************************************************\n * Modem_Signoff -- sends EXIT event\t\t\t\t\t\t\t\t\t\t         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/03/1995 DRD : Created.                                             *\n *=========================================================================*/\nvoid Modem_Signoff( void )\n{\n\tunsigned long starttime;\n\tEventClass event;\n\n\tif (!Session.Play) {\n\t\t/*\n\t\t** Send a sign-off packet\n\t\t*/\n\t\tmemset (&event, 0, sizeof(EventClass));\n\t\tevent.Type = EventClass::EXIT;\n\t\tNullModem.Send_Message (&event,sizeof(EventClass),0);\n\t\tNullModem.Send_Message (&event,sizeof(EventClass),0);\n\n\t\tstarttime = TickCount;\n\t\twhile ( (TickCount - starttime) < 30) {\n\t\t\tNullModem.Service();\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * Test_Null_Modem -- Null-Modem test routine                              *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      0 = failure to connect; 1 = I'm the game owner, 2 = I'm not        *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *   8/2/96      ST : Win32 support added                                  *\n *=========================================================================*/\nint Test_Null_Modem( void )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Dialog variables\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\n\tint retval;\n\tunsigned long starttime;\n\tint packetlen;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tstrcpy( buffer, Text_String( TXT_WAITING_CONNECT ) );\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 50 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tprocess = true;\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &cancelbtn;\n\n\tcommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Draw the dialog\n\t*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, x + 20 * RESFACTOR, y + 25 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\tcommands->Draw_All();\n\twhile (Get_Mouse_State() > 0) Show_Mouse();\n\n#ifdef WIN32\n\t/*\n\t** This is supposed to be a direct connection so hang up any modem on this port\n\t** just to annoy British Telecom\n\t*/\n\t/*\n\t** Go into break mode\n\t*/\n\tSetCommBreak(SerialPort->Get_Port_Handle());\n\n\t/*\n\t** Send hangup command\n\t*/\n\tSerialPort->Write_To_Serial_Port ((unsigned char*)\"ATH\\r\", strlen(\"ATH\\r\"));\n\tCountDownTimerClass time;\n\ttime.Set(2*60);\n\twhile (time.Time()) {}\n\n\t/*\n\t** Back out of break mode\n\t*/\n\tClearCommBreak(SerialPort->Get_Port_Handle());\n\n\t/*\n\t** Drop DTR as well - just in case the modem still hasnt got the message\n\t*/\n\tEscapeCommFunction(SerialPort->Get_Port_Handle(), CLRDTR);\n#endif\t//WIN32\n\n\n\t/*\n\t** Check for a packet.  If we detect one, the other system has already been\n\t** started.  Wait 1/2 sec for him to receive my ACK, then exit with success.\n\t** Note: The initial time must be a little longer than the resend delay.\n\t** \tJust in case we just missed the packet.\n\t*/\n\tstarttime = TickCount;\n\twhile ( TickCount - starttime < 80) {\n\t\tNullModem.Service();\n\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\tNullModem.Service();\n\t\t\t\tprocess = false;\n\t\t\t\tretval = 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Send a packet across.  As long as Num_Send() is non-zero, the other system\n\t** hasn't received it yet.\n\t*/\n\tif (process) {\n\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t//\n\t\t// put time from start of game for determining the host in case of tie.\n\t\t//\n\t\tSendPacket.ScenarioInfo.Seed = TickCount;\n\t\tSendPacket.ID = (int) buffer;\t\t// address of buffer for more uniqueness.\n\n\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\tstarttime = TickCount;\n\t\twhile (TickCount - starttime < 80) {\n\t\t\tNullModem.Service();\n\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\t\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t//\n\t\t\t\t\t// whoever has the highest time is the host\n\t\t\t\t\t//\n\t\t\t\t\tif (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t} else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tif (ReceivePacket.ID > SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// if they are equal then it's a loopback cable or a modem\n\t\t\t\t\t\t//\n\t\t\t\t\t\t} else if (ReceivePacket.ID == SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tstarttime = TickCount;\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tcommands->Draw_All();\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretval = 0;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t/*\n\t\t** Service the connection.\n\t\t*/\n\t\tNullModem.Service();\n\t\tif (NullModem.Num_Send() == 0) {\n\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\t\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\twhile (TickCount - starttime < 30)\n\t\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t//\n\t\t\t\t\t// whoever has the highest time is the host\n\t\t\t\t\t//\n\t\t\t\t\tif (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tretval = 2;\n\n\t\t\t\t\t} else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) {\n\t\t\t\t\t\tif (ReceivePacket.ID > SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 2;\n\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// if they are equal then it's a loopback cable or a modem\n\t\t\t\t\t\t//\n\t\t\t\t\t\t} else if (ReceivePacket.ID == SendPacket.ID) {\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\tretval = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tretval = 0;\n\t\t\t\t\tprocess = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tretval = 1;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (TickCount - starttime > 3600) {\t\t// only wait 1 minute\n\t\t\tretval = 0;\n\t\t\tprocess = false;\n\t\t}\n\t}\t/* end of while */\n\n\treturn( retval );\n\n}\n\n\n/***************************************************************************\n * Reconnect_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = failure to connect; 1 = connect OK\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nint Reconnect_Modem( void )\n{\n\tint status;\n\tint modemstatus;\n\n\n\tswitch (Session.ModemType) {\n\t\tcase (MODEM_NULL_HOST):\n\t\tcase (MODEM_NULL_JOIN):\n\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\tbreak;\n\n\t\tcase (MODEM_DIALER):\n\t\t\tmodemstatus = NullModem.Get_Modem_Status();\n\t\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\t} else {\n\t\t\t\tstatus = Dial_Modem( DialSettings, true );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase (MODEM_ANSWERER):\n\t\t\tmodemstatus = NullModem.Get_Modem_Status();\n\t\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\t\tstatus = Reconnect_Null_Modem();\n\t\t\t} else {\n\t\t\t\tstatus = Answer_Modem( DialSettings, true );\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn( status );\n}\n\n\n/***************************************************************************\n * Reconnect_Null_Modem -- allows user to reconnect\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = failure to connect; 1 = connect OK\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Reconnect_Null_Modem( void )\n{\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Dialog variables\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint retval;\n\tunsigned long starttime;\n\tunsigned long lastmsgtime;\n\tint packetlen;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tstrcpy( buffer, Text_String( TXT_NULL_CONNERR_CHECK_CABLES ) );\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 50 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2*RESFACTOR) - 10 * RESFACTOR);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tprocess = true;\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &cancelbtn;\n\n\tcommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Draw the dialog\n\t*/\n\tHide_Mouse();\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\tcommands->Draw_All();\n\tShow_Mouse();\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\tstarttime = lastmsgtime = TickCount;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tcommands->Draw_All();\n\t\t}\n#endif\t//WIN32\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tretval = false;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t/*\n\t\t** Service the connection.\n\t\t*/\n\t\tNullModem.Service();\n\n\t\t/*\n\t\t** Resend our message if it's time\n\t\t*/\n\t\tif (TickCount - starttime > PACKET_RETRANS_TIME) {\n\t\t\tstarttime = TickCount;\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t}\n\n\t\t/*\n\t\t** Check for an incoming message\n\t\t*/\n\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\n\t\t\tif (ReceivePacket.Command == SERIAL_CONNECT) {\n\n\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\tif (ReceivePacket.ID == Session.ColorIdx) {\n\t\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\t\t\tretval = false;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** OK, we got our message; now we have to make certain the other\n\t\t\t\t** guy gets his, so send him one with an ACK required.\n\t\t\t\t*/\n\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\tSendPacket.Command = SERIAL_CONNECT;\n\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile (TickCount - starttime < 60)\n\t\t\t\t\tNullModem.Service();\n\t\t\t\tretval = true;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// timeout if we do not get any packets\n\t\t//\n\t\tif (TickCount - lastmsgtime > PACKET_CANCEL_TIMEOUT) {\n\t\t\tretval = false;\n\t\t\tprocess = false;\n\t\t}\n\n\t}\t/* end of while */\n\n\treturn( retval );\n\n}\n\n\n/***********************************************************************************************\n * Destroy_Null_Connection -- destroys the given connection\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * Call this routine when a connection goes bad, or another player signs off.\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tid\t\t\tconnection ID to destroy; this should be the HousesType of the player being\t  *\n *             \"destroyed\".\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\terror\t\t0 = user signed off; 1 = connection error\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   07/31/1995 DRD : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid Destroy_Null_Connection(int id, int error)\n{\n\tint i;\n\tHouseClass *housep;\n\tchar txt[80];\n\n\n\tif ( Session.NumPlayers == 1 ) {\n\t\treturn;\n\t}\n\n\t/*\n\t**\tDo nothing if the house isn't human.\n\t*/\n\thousep = HouseClass::As_Pointer((HousesType)id);\n\tif (!housep || !housep->IsHuman)\n\t\treturn;\n\n\t/*\n\t**\tCreate a message to display to the user\n\t*/\n\ttxt[0] = '\\0';\n\tswitch (error) {\n\t\tcase 1:\n\t\t\tsprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName);\n\t\t\tbreak;\n\n\t\tcase 0:\n\t\t\tsprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName);\n\t\t\tbreak;\n\n\t\tcase -1:\n\t\t\tNullModem.Delete_Connection();\n\t\t\tbreak;\n\t}\n\n\tif (strlen(txt)) {\n\t\tSession.Messages.Add_Message (NULL, 0, txt,\n\t\t\t(housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n\t/*\n\t** Remove this player from the Players vector\n\t*/\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (!stricmp(Session.Players[i]->Name,housep->IniName)) {\n\t\t\tdelete Session.Players[i];\n\t\t\tSession.Players.Delete(Session.Players[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tTurn the player's house over to the computer's AI\n\t*/\n\thousep->IsHuman = false;\n//\thousep->Smartness = IQ_MENSA;\n\thousep->IQ = Rule.MaxIQ;\n\tstrcpy (housep->IniName,Text_String(TXT_COMPUTER));\n\n\tSession.NumPlayers--;\n\n\t/*\n\t**\tIf we're the last player left, tell the user.\n\t*/\n\tif (Session.NumPlayers == 1) {\n\t\tsprintf(txt,\"%s\",Text_String(TXT_JUST_YOU_AND_ME));\n\t\tSession.Messages.Add_Message (NULL, 0, txt,\n\t\t\t(housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor,\n\t\t\tTPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);\n\t\tMap.Flag_To_Redraw(false);\n\t}\n\n}\n\n\n/***************************************************************************\n * Select_Serial_Dialog -- Serial Communications menu dialog               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tGAME_MODEM\t\t\t\tuser wants to play a modem game\t\t\t\t\t\t*\n *\t\tGAME_NULL_MODEM\t\tuser wants to play a null-modem game\t\t\t\t*\n *\t\tGAME_NORMAL\t\t\t\tuser hit Cancel\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nGameType Select_Serial_Dialog( void )\n{\n\tint rc;\n//\tint value, i;\n\tint com = -1, baud = -1;\n\tint error = 0;\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 160 * RESFACTOR;\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 94 * RESFACTOR;\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t// dialog x-coord\n\tint d_dialog_y = 80*RESFACTOR;\n//\tint d_dialog_y = ((136 * RESFACTOR - d_dialog_h) / 2);\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_dial_w = 90 * RESFACTOR;\n\tint d_dial_h = 9 * RESFACTOR;\n\tint d_dial_x = d_dialog_cx - d_dial_w / 2;\n\tint d_dial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;\n\n\tint d_answer_w = 90 * RESFACTOR;\n\tint d_answer_h = 9 * RESFACTOR;\n\tint d_answer_x = d_dialog_cx - d_answer_w / 2;\n\tint d_answer_y = d_dial_y + d_dial_h + 2;\n\n\tint d_nullmodem_w = 90 * RESFACTOR;\n\tint d_nullmodem_h = 9 * RESFACTOR;\n\tint d_nullmodem_x = d_dialog_cx - d_nullmodem_w / 2;\n\tint d_nullmodem_y = d_answer_y + d_answer_h + 2;\n\n\tint d_settings_w = 90 * RESFACTOR;\n\tint d_settings_h = 9 * RESFACTOR;\n\tint d_settings_x = d_dialog_cx - d_settings_w / 2;\n\tint d_settings_y = d_nullmodem_y + d_nullmodem_h + 2;\n\n\tint d_cancel_w = 50 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_settings_y + d_settings_h + d_margin;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_DIAL = 100,\n\t\tBUTTON_ANSWER,\n\t\tBUTTON_NULLMODEM,\n\t\tBUTTON_SETTINGS,\n\t\tBUTTON_CANCEL,\n\n\t\tNUM_OF_BUTTONS = 5,\n\t};\n\n\t/*\n\t** Redraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t** Dialog variables\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tint tabs[] = {77*RESFACTOR};\t\t\t\t// tabs for player list box\n\tGameType retval;\t\t\t\t\t\t\t// return value\n\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass *buttons[NUM_OF_BUTTONS];\n\n\tSerialSettingsType *settings;\n\tbool selectsettings = false;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL_MODEM, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h);\n\tTextButtonClass answerbtn(BUTTON_ANSWER, TXT_ANSWER_MODEM, TPF_BUTTON, d_answer_x, d_answer_y, d_answer_w, d_answer_h);\n\tTextButtonClass nullmodembtn(BUTTON_NULLMODEM, TXT_NULL_MODEM, TPF_BUTTON, d_nullmodem_x, d_nullmodem_y, d_nullmodem_w, d_nullmodem_h);\n\tTextButtonClass settingsbtn(BUTTON_SETTINGS, TXT_SETTINGS, TPF_BUTTON, d_settings_x, d_settings_y, d_settings_w, d_settings_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t/*\n\t** Initialize\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\tif (Session.SerialDefaults.Port == 0 ||\n\t\tSession.SerialDefaults.IRQ == -1 ||\n\t\tSession.SerialDefaults.Baud == -1) {\n\t\tselectsettings = true;\n\n\t} else if ( NullModem.Detect_Port( &Session.SerialDefaults ) != PORT_VALID ) {\n\t\tselectsettings = true;\n\t}\n\n\t/*\n\t** Create the list\n\t*/\n\tcommands = &dialbtn;\n\tanswerbtn.Add_Tail(*commands);\n\tnullmodembtn.Add_Tail(*commands);\n\tsettingsbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t** Fill array of button ptrs\n\t*/\n\tcurbutton = 0;\n\tbuttons[0] = &dialbtn;\n\tbuttons[1] = &answerbtn;\n\tbuttons[2] = &nullmodembtn;\n\tbuttons[3] = &settingsbtn;\n\tbuttons[4] = &cancelbtn;\n\tbuttons[curbutton]->Turn_On();\n\n\tKeyboard->Clear();\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t/*\n\t** Main Processing Loop\n\t*/\n\tdisplay = REDRAW_ALL;\n\tprocess = true;\n\tpressed = false;\n\twhile (process) {\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Refresh display if needed\n\t\t*/\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\t/*\n\t\t\t\t** Refresh the backdrop\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t/*\n\t\t\t\t** Draw the background\n\t\t\t\t*/\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\t/*\n\t\t\t\t** Draw the labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_SELECT_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t}\n\t\t\tcommands->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_DIAL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_DIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_ANSWER | KN_BUTTON):\n\t\t\t\tselection = BUTTON_ANSWER;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NULLMODEM | KN_BUTTON):\n\t\t\t\tselection = BUTTON_NULLMODEM;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_SETTINGS | KN_BUTTON):\n\t\t\t\tselection = BUTTON_SETTINGS;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tselection = BUTTON_CANCEL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_UP):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton--;\n\t\t\t\tif (curbutton < 0)\n\t\t\t\t\tcurbutton = (NUM_OF_BUTTONS - 1);\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_DOWN):\n\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tcurbutton++;\n\t\t\t\tif (curbutton > (NUM_OF_BUTTONS - 1) )\n\t\t\t\t\tcurbutton = 0;\n\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tselection = curbutton + BUTTON_DIAL;\n\t\t\t\tpressed = true;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pressed) {\n\t\t\t//\n\t\t\t// to make sure the selection is correct in case they used the mouse\n\t\t\t//\n\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\tcurbutton = selection - BUTTON_DIAL;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\tbuttons[curbutton]->IsPressed = true;\n\t\t\tbuttons[curbutton]->Draw_Me(true);\n\n\t\t\tswitch (selection) {\n\t\t\t\tcase (BUTTON_DIAL):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Remote-connect\n\t\t\t\t\t*/\n\t\t\t\t\t} else if ( Phone_Dialog() ) {\n\t\t\t\t\t\tif (Session.PhoneBook[Session.CurPhoneIdx]->Settings.Port == 0) {\n\t\t\t\t\t\t\tsettings = &Session.SerialDefaults;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsettings = &(Session.PhoneBook[Session.CurPhoneIdx]->Settings);\n\t\t\t\t\t\t}\n#ifdef WIN32\n\t\t\t\t\t\tif (SerialPort) {\n\t\t\t\t\t\t\tdelete SerialPort;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSerialPort = new WinModemClass;\n#endif\t//WIN32\n\t\t\t\t\t\tif ( Init_Null_Modem( settings ) ) {\n\n\t\t\t\t\t\t\tif (settings->CallWaitStringIndex == CALL_WAIT_CUSTOM) {\n\t\t\t\t\t\t\t\tstrcpy( DialString, settings->CallWaitString );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstrcpy( DialString,\n\t\t\t\t\t\t\t\t\tSession.CallWaitStrings[ settings->CallWaitStringIndex ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstrcat( DialString, Session.PhoneBook[ Session.CurPhoneIdx ]->Number );\n\n\t\t\t\t\t\t\tif ( Dial_Modem( settings, false ) ) {\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_DIALER;\n\t\t\t\t\t\t\t\tif ( Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n  \t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_ANSWER):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Remote-connect\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tsettings = &Session.SerialDefaults;\n#ifdef WIN32\n\t\t\t\t\t\tif (SerialPort) {\n\t\t\t\t\t\t\tdelete SerialPort;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSerialPort = new WinModemClass;\n#endif\t//WIN32\n\t\t\t\t\t\tif ( Init_Null_Modem( settings ) ) {\n\t\t\t\t\t\t\tif ( Answer_Modem( settings, false ) ) {\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_ANSWERER;\n\t\t\t\t\t\t\t\tif ( Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_NULLMODEM):\n\n\t\t\t\t\tif (selectsettings) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Otherwise, remote-connect; save values if we're recording\n\t\t\t\t\t*/\n\t\t\t\t\t} else if ( Init_Null_Modem( &Session.SerialDefaults ) ) {\n\t\t\t\t\t\trc = Test_Null_Modem();\n\t\t\t\t\t\tswitch (rc) {\n\t\t\t\t\t\t\tcase (1):\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_NULL_HOST;\n\t\t\t\t\t\t\t\tif ( Com_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_NULL_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase (2):\n\t\t\t\t\t\t\t\tSession.ModemType = MODEM_NULL_JOIN;\n\t\t\t\t\t\t\t\tif ( Com_Show_Scenario_Dialog() ) {\n\t\t\t\t\t\t\t\t\tretval = GAME_NULL_MODEM;\n\t\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase (3):\n\t\t\t\t\t\t\t\tWWMessageBox().Process( TXT_MODEM_OR_LOOPBACK );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (process) {\t\t// restore to default\n\t\t\t\t\t\t\tNullModem.Change_IRQ_Priority( 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_SELECT_SETTINGS);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (process) {\n\t\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_SETTINGS):\n\t\t\t\t\tif ( Com_Settings_Dialog( &Session.SerialDefaults ) ) {\n\t\t\t\t\t\tSession.Write_MultiPlayer_Settings ();\n\n\t\t\t\t\t\tselectsettings = true;\n\n\t\t\t\t\t\tif (Session.SerialDefaults.Port != 0 &&\n\t\t\t\t\t\t\tSession.SerialDefaults.IRQ != -1 &&\n\t\t\t\t\t\t\tSession.SerialDefaults.Baud != -1) {\n\t\t\t\t\t\t\tif ( NullModem.Detect_Port( &Session.SerialDefaults ) == PORT_VALID) {\n\t\t\t\t\t\t\t\tselectsettings = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbuttons[curbutton]->IsPressed = false;\n\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_CANCEL):\n\t\t\t\t\tretval = GAME_NORMAL;\n\t\t\t\t\tprocess = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpressed = false;\n\t\t}\n\t}\t/* end of while */\n\n\treturn( retval );\n}\n\n\n\n\n\n\n#ifdef WIN32\n/***********************************************************************************************\n * Advanced_Modem_Settings -- Allows to user to set additional modem settings                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    current settings                                                                  *\n *                                                                                             *\n * OUTPUT:   modified settings                                                                 *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    12/16/96 2:29PM ST : Created                                                             *\n *=============================================================================================*/\nAdvanced_Modem_Settings (SerialSettingsType *settings)\n{\n\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n#if (FRENCH | GERMAN)\n\tint d_dialog_w = 440;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#else\n\tint d_dialog_w = 340;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog width\n#endif\n\n\tint d_dialog_h = 200;\t\t\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = 320 - d_dialog_w/2;\t\t\t\t\t\t\t\t// dialog x-coord\n\tint d_dialog_y = 200 - d_dialog_h/ 4;\t\t\t\t\t\t\t\t// dialog y-coord\n\n\n\tint d_compression_w = 50;\n\tint d_compression_h = 18;\n\tint d_compression_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_compression_y = d_dialog_y + 40;\n\n\tint d_errorcorrection_w = 50;\n\tint d_errorcorrection_h = 18;\n\tint d_errorcorrection_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_errorcorrection_y = d_dialog_y + 65;\n\n\tint d_hardwareflowcontrol_w = 50;\n\tint d_hardwareflowcontrol_h = 18;\n\tint d_hardwareflowcontrol_x = d_dialog_x + d_dialog_w/2 +40;\n\tint d_hardwareflowcontrol_y = d_dialog_y + 90;\n\n\tint d_default_w = 100;\n\tint d_default_h = 18;\n\tint d_default_x = d_dialog_x + d_dialog_w / 2 - d_default_w / 2;\n\tint d_default_y = d_dialog_y + d_dialog_h - 70;\n\n\tint d_ok_w = 100;\n\tint d_ok_h = 18;\n\tint d_ok_x = d_dialog_x + d_dialog_w/2 - d_ok_w / 2;\n\tint d_ok_y = d_dialog_y + d_dialog_h - 40;\n\n\tenum {\n\t\tBUTTON_COMPRESSION = 100,\n\t\tBUTTON_ERROR_CORRECTION,\n\t\tBUTTON_HARDWARE_FLOW_CONTROL,\n\t\tBUTTON_DEFAULT,\n\t\tBUTTON_OK,\n\t};\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND,\n\t} RedrawType;\n\n\t/*\n\t** Yes/No strings\n\t*/\n\tchar compress_text [16];\n\tchar correction_text [16];\n\tchar flowcontrol_text[16];\n\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*\n\t** Initialise the button text\n\t*/\n\tstrcpy (compress_text, settings->Compression ? Text_String (TXT_ON) : Text_String (TXT_OFF) );\n\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\n\t/*\n\t** Create the buttons\n\t*/\n\tTextButtonClass compressionbutton(BUTTON_COMPRESSION, compress_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_compression_x, d_compression_y, d_compression_w, d_compression_h);\n\n\tTextButtonClass errorcorrectionbutton(BUTTON_ERROR_CORRECTION, correction_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_errorcorrection_x, d_errorcorrection_y, d_errorcorrection_w, d_errorcorrection_h);\n\n\tTextButtonClass hardwareflowcontrolbutton(BUTTON_HARDWARE_FLOW_CONTROL, flowcontrol_text,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_hardwareflowcontrol_x, d_hardwareflowcontrol_y, d_hardwareflowcontrol_w, d_hardwareflowcontrol_h);\n\n\tTextButtonClass defaultbutton(BUTTON_DEFAULT, TXT_DEFAULT,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_default_x, d_default_y, d_default_w, d_default_h);\n\n\tTextButtonClass okbutton(BUTTON_OK, TXT_OK,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n\t\td_ok_x, d_ok_y, d_ok_w, d_ok_h);\n\n\n\t/*\n\t** Misc. variables.\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tBOOL process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\n\n\tcommands = &okbutton;\n\tdefaultbutton.Add_Tail(*commands);\n\tcompressionbutton.Add_Tail(*commands);\n\terrorcorrectionbutton.Add_Tail(*commands);\n\thardwareflowcontrolbutton.Add_Tail(*commands);\n\n\n\t/*\n\t** Main process loop\n\t*/\n\twhile (process) {\n\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored){\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay=REDRAW_ALL;\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption (TXT_MODEM_INITIALISATION, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print( TXT_DATA_COMPRESSION,\n\t\t\t\t\td_compression_x - 26, d_compression_y + 2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tFancy_Text_Print( TXT_ERROR_CORRECTION,\n\t\t\t\t\td_errorcorrection_x - 26, d_errorcorrection_y +2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t\tFancy_Text_Print( TXT_HARDWARE_FLOW_CONTROL,\n\t\t\t\t\td_hardwareflowcontrol_x -26, d_hardwareflowcontrol_y +2,\n\t\t\t\t\tscheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcompressionbutton.Flag_To_Redraw();\n\t\t\t\terrorcorrectionbutton.Flag_To_Redraw();\n\t\t\t\thardwareflowcontrolbutton.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_COMPRESSION | KN_BUTTON):\n\t\t\t\tsettings->Compression = settings->Compression ^ 1;\n\t\t\t\tstrcpy (compress_text, settings->Compression ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_ERROR_CORRECTION | KN_BUTTON):\n\t\t\t\tsettings->ErrorCorrection = settings->ErrorCorrection ^ 1;\n\t\t\t\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_HARDWARE_FLOW_CONTROL | KN_BUTTON):\n\t\t\t\tsettings->HardwareFlowControl = settings->HardwareFlowControl ^ 1;\n\t\t\t\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_DEFAULT | KN_BUTTON):\n\t\t\t\tsettings->Compression = false;\n\t\t\t\tsettings->ErrorCorrection = false;\n\t\t\t\tsettings->HardwareFlowControl = true;\n\n\t\t\t\tstrcpy (compress_text, settings->Compression ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tstrcpy (correction_text, settings->ErrorCorrection ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tstrcpy (flowcontrol_text, settings->HardwareFlowControl ?\n\t\t\t\t\t\t\t\t\t\tText_String (TXT_ON) : Text_String (TXT_OFF) );\n\n\t\t\t\tif (display < REDRAW_BUTTONS)\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n#endif\t//WIN32\n\n\n\n/***************************************************************************\n * Com_Settings_Dialog -- Lets user select serial port settings            *\n *                                                                         *\n *  Ŀ               *\n *                      Settings                                         *\n *                                                                       *\n *       Port:____       IRQ:__        Baud:______                       *\n *    Ŀ  Ŀ  Ŀ                     *\n *                                                                 *\n *                                                                 *\n *                                                                 *\n *                                                                 *\n *                             *\n *                                                                       *\n *     Initialization:        [Add]   [Delete]                           *\n *      _____________________________                                    *\n *     Ŀ                    *\n *                                                                     *\n *                                                                     *\n *                                                                     *\n *                         *\n *                                                                       *\n *     Call Waiting:                                                     *\n *      _______________                                                  *\n *     Ŀ          [Tone Dialing]                       *\n *                                                                     *\n *                                [Pulse Dialing]                      *\n *                                                                     *\n *                                                    *\n *                                                                       *\n *                     [OK]   [Cancel]                                   *\n *                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettingsType structure\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = Cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Com_Settings_Dialog( SerialSettingsType *settings )\n{\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_portlist_w = 80 * RESFACTOR + 80*(RESFACTOR-1);\t//Port list wider in hires\n\tint d_portlist_h = 33 * RESFACTOR;\n\tint d_portlist_x = d_dialog_x + (d_dialog_w / 6) - (d_portlist_w / 2);\n#ifdef WIN32\n \td_portlist_x = 0x45;\n#endif\n\tint d_portlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 * RESFACTOR;\n\n#ifdef WIN32\n\tint d_port_w = d_portlist_w;\n\tint d_port_x = 0x45;\n#else\n\tint d_port_w = (5 * 6 * RESFACTOR) + 3 * RESFACTOR;\n\n//\tint d_port_x = d_portlist_x + 29 * RESFACTOR;\n#ifdef FRENCH  //VG2\n\tint d_port_x = (d_portlist_x + 29 * RESFACTOR) + 5;\n#else\n\tint d_port_x = d_portlist_x + 29 * RESFACTOR;\n#endif\n\n#endif\t//WIN32\n\tint d_port_h = 9 * RESFACTOR;\n\tint d_port_y = d_portlist_y - d_margin - d_txt6_h;\n\n\tint d_irqlist_w = 80 * RESFACTOR;\n\tint d_irqlist_h = 33 * RESFACTOR;\n\tint d_irqlist_x = d_dialog_x + (d_dialog_w / 2) - (d_irqlist_w / 2);\n\tint d_irqlist_y = d_portlist_y;\n\n\tint d_irq_w = ((IRQBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_irq_h = 9 * RESFACTOR;\n\tint d_irq_x = d_irqlist_x + 25 * RESFACTOR;\n\tint d_irq_y = d_irqlist_y - d_margin - d_txt6_h;\n\n\tint d_baudlist_w = 80 * RESFACTOR;\n\tint d_baudlist_h = 33 * RESFACTOR;\n\tint d_baudlist_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_baudlist_w / 2);\n#ifdef WIN32\n d_baudlist_x -= 32;\n#endif\n\tint d_baudlist_y = d_irqlist_y;\n\n\tint d_baud_w = ((BAUDBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_baud_h = 9 * RESFACTOR;\n\tint d_baud_x = d_baudlist_x + 29 * RESFACTOR;\n\tint d_baud_y = d_baudlist_y - d_margin - d_txt6_h;\n\n\tint d_initstrlist_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 8 * RESFACTOR + 3 * RESFACTOR;\n\tint d_initstrlist_h = 21 * RESFACTOR;\n\tint d_initstrlist_x = d_dialog_cx - (d_initstrlist_w / 2);\n\tint d_initstrlist_y = d_portlist_y + d_portlist_h + ((d_margin + d_txt6_h) * 2) + d_margin + 4;\n\n\tint d_initstr_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR;\n\tint d_initstr_h = 9 * RESFACTOR;\n\tint d_initstr_x = d_initstrlist_x;\n\tint d_initstr_y = d_initstrlist_y - d_margin - d_txt6_h;\n\n\tint d_add_w = 45 * RESFACTOR;\n#ifdef FRENCH\n\tint d_add_x = d_dialog_cx - (d_add_w / 2);\n#else\n\tint d_add_x = (d_dialog_cx - (d_add_w / 2)) + 30;\n#endif\n\tint d_add_h = 9 * RESFACTOR;\n\tint d_add_y = d_initstr_y - d_add_h - 3 * RESFACTOR;\n\n\tint d_delete_w = 45 * RESFACTOR;\n#ifdef FRENCH\n\tint d_delete_x = (d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2)) + 10;\n#else\n\tint d_delete_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2);\n#endif\n\tint d_delete_h = 9 * RESFACTOR;\n\tint d_delete_y = d_initstr_y - d_add_h - 3 * RESFACTOR;\n\n\tint d_cwaitstrlist_w = (((CWAITSTRBUF_MAX - 1) + 9) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_cwaitstrlist_h = 27 * RESFACTOR;\n\tint d_cwaitstrlist_x = d_initstrlist_x;\n\tint d_cwaitstrlist_y = d_initstrlist_y + d_initstrlist_h + ((d_margin + d_txt6_h) * 2) + 2;\n\n\tint d_cwaitstr_w = ((CWAITSTRBUF_MAX - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_cwaitstr_h = 9 * RESFACTOR;\n\tint d_cwaitstr_x = d_cwaitstrlist_x;\n\tint d_cwaitstr_y = d_cwaitstrlist_y - d_margin - d_txt6_h;\n\n\tint d_tone_w = 80 * RESFACTOR;\n\tint d_tone_h = 9 * RESFACTOR;\n\tint d_tone_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_tone_w / 2);\n\tint d_tone_y = d_cwaitstrlist_y;\n\n\tint d_pulse_w = 80 * RESFACTOR;\n\tint d_pulse_h = 9 * RESFACTOR;\n\tint d_pulse_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_pulse_w / 2);\n\tint d_pulse_y = d_tone_y + d_tone_h + d_margin;\n\n#ifdef FRENCH\n\tint d_save_w = 80 * RESFACTOR;\n#else\n\tint d_save_w = 40 * RESFACTOR;\n#endif\n\tint d_save_h = 9 * RESFACTOR;\n\tint d_save_x = d_dialog_x + (d_dialog_w / 5) - (d_save_w / 2);\n\tint d_save_y = d_dialog_y + d_dialog_h - d_save_h - d_margin - 4*RESFACTOR;\n\n\tint d_cancel_w = 50 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_x + ((d_dialog_w * 4) / 5) - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin - 4*RESFACTOR;\n\n#if (GERMAN | FRENCH)\n\tint d_advanced_w = 50*RESFACTOR;\n#else\n\tint d_advanced_w = 40*RESFACTOR;\n#endif\n\tint d_advanced_h = 9*RESFACTOR;\n\tint d_advanced_x = d_dialog_x + ((d_dialog_w) / 2) - (d_advanced_w / 2);\n\tint d_advanced_y = d_dialog_y + d_dialog_h - d_advanced_h - d_margin - 4 *RESFACTOR;\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_PORT = 100,\n\t\tBUTTON_PORTLIST,\n\t\tBUTTON_IRQ,\n\t\tBUTTON_IRQLIST,\n\t\tBUTTON_BAUD,\n\t\tBUTTON_BAUDLIST,\n\t\tBUTTON_INITSTR,\n\t\tBUTTON_INITSTRLIST,\n\t\tBUTTON_ADD,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_CWAITSTR,\n\t\tBUTTON_CWAITSTRLIST,\n\t\tBUTTON_TONE,\n\t\tBUTTON_PULSE,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_ADVANCED,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*\n\t** Redraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\tstatic char *portname[4] = {\n\t\t\"COM1 - 3F8\",\n\t\t\"COM2 - 2F8\",\n\t\t\"COM3 - 3E8\",\n\t\t\"COM4 - 2E8\",\n\t};\n\n\tstatic char custom_port[10 + MODEM_NAME_MAX] = {\"CUSTOM - ????\"};\n\n\n\n#ifndef WIN32\t\t// No IRQ dialog in Win version\n\tstatic char *irqname[5] = {\n\t\t\"2 / 9\",\n\t\t\"3 - [COM2 & 4]\",\n\t\t\"4 - [COM1 & 3]\",\n\t\t\"5\",\n\t\t\"CUSTOM - ??\"\n\t};\n\n\tstatic int _irqidx[4] = {\n\t\t2,\n\t\t1,\n\t\t2,\n\t\t1\n\t};\n\n#endif\t//WIN32\n\n#ifdef WIN32\n\tstatic char *baudname[5] = {\n\t\t\"14400\",\n\t\t\"19200\",\n\t\t\"28800\",\n\t\t\"38400\",\n\t\t\"57600\",\n\t};\n\n\tstatic char modemnames[10][MODEM_NAME_MAX];\n\n#else\t//WIN32\n\tstatic char *baudname[5] = {\n\t\t\"9600\",\n\t\t\"14400\",\n\t\t\"19200\",\n\t\t\"28800\",\n\t\t\"38400\"\n\t};\n#endif\t//WIN32\n\t/*\n\t** Dialog variables\n\t*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\tchar * item;\t\t\t\t\t\t\t\t// general-purpose string\n\tchar * temp;\t\t\t\t\t\t\t\t// general-purpose string\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tchar portbuf[ PORTBUF_MAX ] = {0};\t// buffer for port\n\tchar irqbuf[ IRQBUF_MAX ] = {0};\t\t// buffer for irq\n\tchar baudbuf[ BAUDBUF_MAX ] = {0};\t// buffer for baud\n\tchar initstrbuf[ INITSTRBUF_MAX ] = {0};\t\t// buffer for init string\n\tchar cwaitstrbuf[ CWAITSTRBUF_MAX ] = {0};\t// buffer for call waiting string\n\n\tint port_index = 1;\t// index of currently-selected port (default = com2)\n\tint port_custom_index = 4;\t//index of custom entry in port list\n\tint irq_index = 1;\t// index of currently-selected irq (default = 3)\n\tint baud_index = 1;\t// index of currently-selected baud (default = 19200)\n\tint initstr_index = 0;\t// index of currently-selected modem init (default = \"ATZ\")\n\tint cwaitstr_index = CALL_WAIT_CUSTOM;\t// index of currently-selected call waiting (default = \"\")\n\tint rc = 0;\t\t\t\t\t\t\t\t\t// -1 = user cancelled, 1 = New\n\tint i;\t\t\t\t\t\t\t\t\t\t// loop counter\n\tint pos;\n\tint len;\n\tbool firsttime = true;\n\tSerialSettingsType tempsettings;\n\tDetectPortType dpstatus;\n\n\t/*\n\t** Buttons\n\t*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass port_edt (BUTTON_PORT, portbuf, PORTBUF_MAX,\n\t\tTPF_TEXT, d_port_x, d_port_y, d_port_w, d_port_h, EditClass::ALPHANUMERIC);\n\n\tListClass portlist(BUTTON_PORTLIST, d_portlist_x, d_portlist_y, d_portlist_w, d_portlist_h,\n\t\tTPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#ifndef WIN32\n\tEditClass irq_edt (BUTTON_IRQ, irqbuf, IRQBUF_MAX, TPF_TEXT, d_irq_x, d_irq_y, d_irq_w, d_irq_h, EditClass::NUMERIC);\n\n\tListClass irqlist(BUTTON_IRQLIST, d_irqlist_x, d_irqlist_y, d_irqlist_w, d_irqlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\t//WIN32\n\n\tEditClass baud_edt (BUTTON_BAUD, baudbuf, BAUDBUF_MAX, TPF_TEXT, d_baud_x, d_baud_y, d_baud_w, d_baud_h, EditClass::NUMERIC);\n\tListClass baudlist(BUTTON_BAUDLIST, d_baudlist_x, d_baudlist_y, d_baudlist_w, d_baudlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tEditClass initstr_edt (BUTTON_INITSTR, initstrbuf, INITSTRBUF_MAX, TPF_TEXT, d_initstr_x, d_initstr_y, d_initstr_w, d_initstr_h, EditClass::ALPHANUMERIC);\n\tListClass initstrlist(BUTTON_INITSTRLIST, d_initstrlist_x, d_initstrlist_y, d_initstrlist_w, d_initstrlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h);\n\tTextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h);\n\tEditClass cwaitstr_edt (BUTTON_CWAITSTR, cwaitstrbuf, CWAITSTRBUF_MAX, TPF_TEXT, d_cwaitstr_x, d_cwaitstr_y, d_cwaitstr_w, d_cwaitstr_h, EditClass::ALPHANUMERIC);\n\tListClass cwaitstrlist(BUTTON_CWAITSTRLIST, d_cwaitstrlist_x, d_cwaitstrlist_y, d_cwaitstrlist_w, d_cwaitstrlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass tonebtn(BUTTON_TONE, TXT_TONE_BUTTON, TPF_BUTTON, d_tone_x, d_tone_y, d_tone_w, d_tone_h);\n\tTextButtonClass pulsebtn(BUTTON_PULSE, TXT_PULSE_BUTTON, TPF_BUTTON, d_pulse_x, d_pulse_y, d_pulse_w, d_pulse_h);\n\tTextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#ifdef WIN32\n\tTextButtonClass advancedbutton(BUTTON_ADVANCED, TXT_ADVANCED, TPF_BUTTON, d_advanced_x, d_advanced_y, d_advanced_w, d_advanced_h);\n#endif\t//WIN32\n\t/*\n\t** Various Inits\n\t*/\n\tmemcpy( &tempsettings, settings, sizeof(SerialSettingsType) );\n\n\tif (tempsettings.Port == 0) {\n\t\ttempsettings.Port = 0x2f8;\n\t}\n\n\tif (tempsettings.IRQ == -1) {\n\t\ttempsettings.IRQ = 3;\n\t}\n\n\tif (tempsettings.Baud == -1) {\n#ifdef WIN32\n\t\ttempsettings.Baud = 19200;\n#else\t//WIN32\n\t\ttempsettings.Baud = 9600;\n#endif\t//WIN32\n\t}\n\n\n\t/*\n\t** Set the current indices\n\t*/\n#ifndef WIN32\n\tswitch ( tempsettings.IRQ ) {\n\t\tcase ( 2 ):\n\t\t\tirq_index = 0;\n\t\t\tstrcpy (irqbuf, \"2\");\n\t\t\tbreak;\n\n\t\tcase ( 3 ):\n\t\t\tirq_index = 1;\n\t\t\tstrcpy (irqbuf, \"3\");\n\t\t\tbreak;\n\n\t\tcase ( 4 ):\n\t\t\tirq_index = 2;\n\t\t\tstrcpy (irqbuf, \"4\");\n\t\t\tbreak;\n\n\t\tcase ( 5 ):\n\t\t\tirq_index = 3;\n\t\t\tstrcpy (irqbuf, \"5\");\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tirq_index = 4;\n\t\t\tsprintf (irqbuf, \"%d\", tempsettings.IRQ);\n\t\t\ttemp = strchr( irqname[4], '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - irqname[4]) + 2;\n\t\t\t\tlen = strlen( irqbuf );\n\t\t\t\tstrncpy( irqname[4] + pos, irqbuf, len );\n\t\t\t\t*(irqname[4] + pos + len) = 0;\n\t\t\t}\n\t\t\tbreak;\n\t}\n#endif\t//WIN32\n\n#ifdef WIN32\n\tif (tempsettings.Baud == 14400) {\n\t\tbaud_index = 0;\n\t} else if (tempsettings.Baud == 19200) {\n\t\tbaud_index = 1;\n\t} else if (tempsettings.Baud == 28800) {\n\t\tbaud_index = 2;\n\t} else if (tempsettings.Baud == 38400) {\n\t\tbaud_index = 3;\n\t} else {\n\t\tbaud_index = 4;\n\t}\n#else\t//WIN32\n\tif (tempsettings.Baud == 9600) {\n\t\tbaud_index = 0;\n\t} else if (tempsettings.Baud == 14400) {\n\t\tbaud_index = 1;\n\t} else if (tempsettings.Baud == 19200) {\n\t\tbaud_index = 2;\n\t} else if (tempsettings.Baud == 28800) {\n\t\tbaud_index = 3;\n\t} else {\n\t\tbaud_index = 4;\n\t}\n#endif\t//WIN32\n\tsprintf (baudbuf, \"%d\", tempsettings.Baud);\n\n\t/*\n\t** Set up the port list box & edit box\n\t*/\n\tfor (i = 0; i < 4; i++) {\n\t\tportlist.Add_Item( portname[ i ] );\n\t}\n\n#ifdef WIN32\n\t/*\n\t** Loop through the first 10 possible modem entries in the registry. Frankly, its just\n\t** tough luck if the user has more than 10 modems attached!\n\t*/\n\tif (ModemRegistry) {\n\t\tdelete ModemRegistry;\n\t}\n\tint modems_found = 0;\n\tfor (i=0 ; i<10 ; i++) {\n\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\tif (ModemRegistry->Get_Modem_Name()) {\n\t\t\tstrncpy (modemnames[modems_found], ModemRegistry->Get_Modem_Name(), MODEM_NAME_MAX);\n\t\t\tportlist.Add_Item( modemnames [modems_found++] );\n\t\t\tport_custom_index ++;\n\t\t}\n\t\tdelete ModemRegistry;\n\t}\n\tModemRegistry = NULL;\n\n#endif\t//WIN32\n\n\tportlist.Add_Item ( custom_port );\n\n\n\t/*\n\t** Work out the current port index\n\t*/\n\tport_index = -1;\n#ifdef WIN32\n\tif (tempsettings.ModemName[0]) {\n\t\tfor ( i=0 ; i<port_custom_index ; i++) {\n\t\t\tif (!stricmp (portlist.Get_Item(i), tempsettings.ModemName)) {\n\t\t\t\tport_index = i;\n\t\t\t\tstrcpy (portbuf, tempsettings.ModemName);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** The modem name specified wasnt in the registry so add it as a custom entry\n\t\t*/\n\t\tif (port_index == -1) {\n\t\t\ttemp = strchr( custom_port, '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - custom_port) + 2;\n\t\t\t\tlen = strlen( tempsettings.ModemName );\n\t\t\t\tstrncpy( custom_port + pos, tempsettings.ModemName, len );\n\t\t\t\t*(custom_port + pos + len) = 0;\n\t\t\t\tstrcpy (portbuf, tempsettings.ModemName);\n\t\t\t\tport_index = port_custom_index;\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\tif (port_index == -1) {\n\t\tswitch ( tempsettings.Port ) {\n\t\t\tcase ( 0x3f8 ):\n\t\t\t\tport_index = 0;\n\t\t\t\tstrcpy (portbuf, \"COM1\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x2f8 ):\n\t\t\t\tport_index = 1;\n\t\t\t\tstrcpy (portbuf, \"COM2\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x3e8 ):\n\t\t\t\tport_index = 2;\n\t\t\t\tstrcpy (portbuf, \"COM3\");\n\t\t\t\tbreak;\n\n\t\t\tcase ( 0x2e8 ):\n\t\t\t\tport_index = 3;\n\t\t\t\tstrcpy (portbuf, \"COM4\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tport_index = port_custom_index;\n\t\t\t\tsprintf (portbuf, \"%x\", tempsettings.Port);\n\t\t\t\ttemp = strchr( custom_port, '-' );\n\t\t\t\tif ( temp ) {\n\t\t\t\t\tpos = (int)(temp - custom_port) + 2;\n\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\tstrncpy( custom_port + pos, portbuf, len );\n\t\t\t\t\t*(custom_port + pos + len) = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tportlist.Set_Selected_Index( port_index );\n\n\n\n\t/*\n\t** Set up the port edit box\n\t*/\n\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n#ifndef WIN32\n\t/*\n\t** Set up the IRQ list box & edit box\n\t*/\n\tfor (i = 0; i < 5; i++) {\n\t\tirqlist.Add_Item( irqname[ i ] );\n\t}\n\n\tirqlist.Set_Selected_Index( irq_index );\n\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n#endif\t//WIN32\n\t/*\n\t** Set up the baud rate list box & edit box\n\t*/\n\tfor (i = 0; i < 5; i++) {\n\t\tbaudlist.Add_Item( baudname[ i ] );\n\t}\n\n\tbaudlist.Set_Selected_Index( baud_index );\n\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\n\tinitstr_index = tempsettings.InitStringIndex;\n\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf, &initstr_index);\n\n\t/*\n\t** Set up the cwait rate list box & edit box\n\t*/\n\tcwaitstr_index = tempsettings.CallWaitStringIndex;\n\tfor (i = 0; i < CALL_WAIT_STRINGS_NUM; i++) {\n\t\tif ( i == CALL_WAIT_CUSTOM ) {\n\t\t\titem = Session.CallWaitStrings[ i ];\n\t\t\ttemp = strchr( item, '-' );\n\t\t\tif ( temp ) {\n\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\tlen = strlen( tempsettings.CallWaitString );\n\t\t\t\tstrncpy( item + pos, tempsettings.CallWaitString, len );\n\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\tif (i == cwaitstr_index) {\n\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (i == cwaitstr_index) {\n\t\t\tstrncpy( cwaitstrbuf, Session.CallWaitStrings[ i ], CWAITSTRBUF_MAX );\n\t\t}\n\t\tcwaitstrlist.Add_Item( Session.CallWaitStrings[ i ] );\n\t}\n\n\tcwaitstrlist.Set_Selected_Index( cwaitstr_index );\n\tcwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );\n\n\t/*\n\t** Build the button list\n\t*/\n\tcommands = &cancelbtn;\n\tport_edt.Add_Tail(*commands);\n\tportlist.Add_Tail(*commands);\n#ifndef WIN32\n\tirq_edt.Add_Tail(*commands);\n\tirqlist.Add_Tail(*commands);\n#endif\t//WIN32\n\tbaud_edt.Add_Tail(*commands);\n\tbaudlist.Add_Tail(*commands);\n\tinitstr_edt.Add_Tail(*commands);\n\tinitstrlist.Add_Tail(*commands);\n\taddbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tcwaitstr_edt.Add_Tail(*commands);\n\tcwaitstrlist.Add_Tail(*commands);\n\ttonebtn.Add_Tail(*commands);\n\tpulsebtn.Add_Tail(*commands);\n\tsavebtn.Add_Tail(*commands);\n#ifdef WIN32\n\tadvancedbutton.Add_Tail(*commands);\n#endif\t//WIN32\n\n\tif (tempsettings.DialMethod == DIAL_TOUCH_TONE) {\n\t\ttonebtn.Turn_On();\n\t} else {\n\t\tpulsebtn.Turn_On();\n\t}\n\n\t/*\n\t** Processing loop\n\t*/\n\twhile (process) {\n\t\t/*\n\t\t** Invoke game callback\n\t\t*/\n\t\tCall_Back();\n\n\t\t/*\n\t\t** Dont allow editing of non-custom ports to fix the problem of the cursor appearing\n\t\t** outside the edit box.\n\t\t*/\n\t\tif (port_index == port_custom_index) {\n\t\t\tport_edt.Set_Read_Only(false);\n\t\t}else{\n\t\t\tport_edt.Set_Read_Only(true);\n\t\t}\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\t\t/*\n\t\t** Refresh display if needed\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t** Redraw backgound & dialog box\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption(TXT_SETTINGS, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(TXT_PORT_COLON, d_port_x - 3 * RESFACTOR, d_port_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n#ifndef WIN32\n\t\t\t\tFancy_Text_Print(TXT_IRQ_COLON, d_irq_x - 3 * RESFACTOR, d_irq_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n#endif\t//WIN32\n\t\t\t\tFancy_Text_Print(TXT_BAUD_COLON, d_baud_x - 3 * RESFACTOR, d_baud_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_INIT_STRING, d_initstr_x, d_initstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t\tFancy_Text_Print(TXT_CWAIT_STRING, d_cwaitstr_x, d_cwaitstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Redraw buttons\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcancelbtn.Flag_To_Redraw();\n\t\t\t\tport_edt.Flag_To_Redraw();\n\t\t\t\tportlist.Flag_To_Redraw();\n#ifndef WIN32\n\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\tirqlist.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\tbaud_edt.Flag_To_Redraw();\n\t\t\t\tbaudlist.Flag_To_Redraw();\n#ifdef WIN32\n\t\t\t\tadvancedbutton.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tinitstrlist.Flag_To_Redraw();\n\t\t\t\taddbtn.Flag_To_Redraw();\n\t\t\t\tdeletebtn.Flag_To_Redraw();\n\t\t\t\tcwaitstr_edt.Flag_To_Redraw();\n\t\t\t\tcwaitstrlist.Flag_To_Redraw();\n\t\t\t\ttonebtn.Flag_To_Redraw();\n\t\t\t\tpulsebtn.Flag_To_Redraw();\n\t\t\t\tsavebtn.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t** Get user input\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\tif ( firsttime ) {\n//\t\t\tport_edt.Set_Focus();\n\t\t\tport_edt.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t** Process input\n\t\t*/\n\t\tswitch (input) {\n\n#ifdef WIN32\n\t\t\tcase (BUTTON_ADVANCED | KN_BUTTON):\n\t\t\t\tAdvanced_Modem_Settings (&tempsettings);\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n#endif\t//WIN32\n\n\t\t\tcase (BUTTON_PORT | KN_BUTTON):\n\t\t\t\titem = (char *)portlist.Current_Item();\n\t\t\t\tif (port_index < 4) {\n\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\tstrncpy( portbuf, item, PORTBUF_MAX );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( portbuf, item, pos );\n\t\t\t\t\t\tportbuf[pos] = 0;\n\t\t\t\t\t}\n\t\t\t\t\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n\t\t\t\t\tport_edt.Flag_To_Redraw();\n#ifndef WIN32\n\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\tirq_edt.Flag_To_Redraw();\n#endif\t//WIN32\n\t\t\t\t} else {\n\t\t\t\t\tstrupr( portbuf );\n\t\t\t\t\tif ( stricmp(portbuf, \"3F8\") == 0 ) {\n\t\t\t\t\t\tport_index = 0;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM1\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"2F8\") == 0 ) {\n\t\t\t\t\t\tport_index = 1;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM2\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"3E8\") == 0 ) {\n\t\t\t\t\t\tport_index = 2;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM3\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( stricmp(portbuf, \"2E8\") == 0 ) {\n\t\t\t\t\t\tport_index = 3;\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\t\t\t\t\t\tstrcpy (portbuf, \"COM4\");\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t} else if ( strncmp(portbuf, \"COM\", 3) == 0 ) {\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\n\t\t\t\t\t\tswitch ( (portbuf[3] - '0') ) {\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tport_index = 0;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tport_index = 1;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tport_index = 2;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tport_index = 3;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n#ifdef WIN32\n\t\t\t\t\t\t\t\tif (portbuf[3] <= '9' && portbuf[3] >'0') {\n\t\t\t\t\t\t\t\t\tportbuf[4] = 0;\n\t\t\t\t\t\t\t\t\tport_index = port_custom_index;\n\t\t\t\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\t\t\t\t\t\tstrncpy( item + pos, portbuf, len );\n\t\t\t\t\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\t\t\t\t\tWWMessageBox().Process( TXT_INVALID_PORT_ADDRESS );\n\t\t\t\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tportlist.Set_Selected_Index( port_index );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tlen = strlen( portbuf );\n\t\t\t\t\t\t\tstrncpy( item + pos, portbuf, len );\n\t\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#ifndef WIN32\n\t\t\t\t\tif (display == REDRAW_BUTTONS) {\n\t\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_PORTLIST | KN_BUTTON):\n\t\t\t\tif (portlist.Current_Index() != port_index) {\n\t\t\t\t\tport_index = portlist.Current_Index();\n\t\t\t\t\titem = (char *)portlist.Current_Item();\n\t\t\t\t\tif (port_index < 4) {\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( portbuf, item, pos );\n\t\t\t\t\t\tportbuf[pos] = 0;\n\t\t\t\t\t\tport_edt.Clear_Focus();\n\n\t\t\t\t\t\t// auto select the irq for port\n#ifndef WIN32\n\t\t\t\t\t\tirq_index = _irqidx[ port_index ];\n\t\t\t\t\t\tirqlist.Set_Selected_Index( irq_index );\n\t\t\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, 2 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Clear_Focus();\n#endif\t//WIN32\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (port_index == port_custom_index) {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** This is the custom entry\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\t\tif ( *(item + pos) == '?' ) {\n\t\t\t\t\t\t\t\t\tportbuf[0] = 0;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstrncpy( portbuf, item + pos, PORTBUF_MAX );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Must be a modem name entry so just copy iy\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrncpy (portbuf, item, PORTBUF_MAX);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tport_edt.Set_Text( portbuf, PORTBUF_MAX );\n\t\t\t\t} else if (port_index < port_custom_index) {\n\t\t\t\t\tport_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tport_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n#ifndef WIN32\n\t\t\tcase (BUTTON_IRQ | KN_BUTTON):\n\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\tif (irq_index < 4) {\n\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\tstrncpy( irqbuf, item, IRQBUF_MAX );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t}\n\t\t\t\t\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n\t\t\t\t\tirq_edt.Flag_To_Redraw();\n\t\t\t\t} else {\n\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\tlen = strlen( irqbuf );\n\t\t\t\t\t\tstrncpy( item + pos, irqbuf, len );\n\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbaud_edt.Set_Focus();\n\t\t\t\tbaud_edt.Flag_To_Redraw();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_IRQLIST | KN_BUTTON):\n\t\t\t\tif (irqlist.Current_Index() != irq_index) {\n\t\t\t\t\tirq_index = irqlist.Current_Index();\n\t\t\t\t\titem = (char *)irqlist.Current_Item();\n\t\t\t\t\tif (irq_index < 4) {\n\t\t\t\t\t\ttemp = strchr( item, ' ' );\n\t\t\t\t\t\tif ( !temp ) {\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, IRQBUF_MAX );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpos = (int)(temp - item);\n\t\t\t\t\t\t\tstrncpy( irqbuf, item, pos );\n\t\t\t\t\t\t\tirqbuf[pos] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Clear_Focus();\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tif ( *(item + pos) == '?' ) {\n\t\t\t\t\t\t\t\tirqbuf[0] = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstrncpy( irqbuf, item + pos, IRQBUF_MAX );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t\t}\n\t\t\t\t\tirq_edt.Set_Text( irqbuf, IRQBUF_MAX );\n\t\t\t\t} else if (irq_index < 4) {\n\t\t\t\t\tirq_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tirq_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n#endif\t//WIN32\n\t\t\tcase (BUTTON_BAUD | KN_BUTTON):\n\t\t\t\titem = (char *)baudlist.Current_Item();\n\t\t\t\tstrncpy( baudbuf, item, BAUDBUF_MAX );\n\t\t\t\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_BAUDLIST | KN_BUTTON):\n\t\t\t\tif (baudlist.Current_Index() != baud_index) {\n\t\t\t\t\tbaud_index = baudlist.Current_Index();\n\t\t\t\t\titem = (char *)baudlist.Current_Item();\n\t\t\t\t\tstrncpy( baudbuf, item, BAUDBUF_MAX );\n\t\t\t\t\tbaud_edt.Set_Text( baudbuf, BAUDBUF_MAX );\n\t\t\t\t\tbaud_edt.Clear_Focus();\n\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#if 0\n\t\t\tcase (BUTTON_INITSTR | KN_BUTTON):\n\t\t\t\tstrupr( initstrbuf );\n\t\t\t\tstrncpy( Session.InitStrings[ initstr_index ], initstrbuf, INITSTRBUF_MAX );\n\t\t\t\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t&initstr_index);\n\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\tcwaitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n#endif\n\n\t\t\tcase (BUTTON_INITSTRLIST | KN_BUTTON):\n\t\t\t\tif (initstrlist.Current_Index() != initstr_index) {\n\t\t\t\t\tinitstr_index = initstrlist.Current_Index();\n\t\t\t\t\titem = (char *)initstrlist.Current_Item();\n\t\t\t\t\tstrncpy( initstrbuf, item, INITSTRBUF_MAX );\n\t\t\t\t\tinitstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );\n\t\t\t\t}\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t** Add a new InitString entry\n\t\t\t*/\n\t\t\tcase (BUTTON_ADD | KN_BUTTON):\n\n\t\t\t\titem = new char[ INITSTRBUF_MAX ];\n\t\t\t\tmemset (item, 0, INITSTRBUF_MAX);\n\n\t\t\t\tstrupr ( initstrbuf );\n\t\t\t\tstrncpy ( item, initstrbuf, INITSTRBUF_MAX-1 );\n\n\t\t\t\tSession.InitStrings.Add ( item );\n\t\t\t\tBuild_Init_String_Listbox (&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t&initstr_index);\n\t\t\t\t/*............................................................\n\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t............................................................*/\n\t\t\t\tfor (i = 0; i < Session.InitStrings.Count(); i++) {\n\t\t\t\t\tif (item == Session.InitStrings[i]) {\n\t\t\t\t\t\tinitstr_index = i;\n\t\t\t\t\t\tstrcpy( initstrbuf, Session.InitStrings[ initstr_index ] );\n\t\t\t\t\t\tinitstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );\n\t\t\t\t\t\tinitstrlist.Set_Selected_Index( initstr_index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinitstr_edt.Set_Focus();\n\t\t\t\tinitstr_edt.Flag_To_Redraw();\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDelete the current InitString entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\n\t\t\t\tif ( Session.InitStrings.Count() && initstr_index != -1) {\n\t\t\t\t\tSession.InitStrings.Delete( initstr_index );\n\t\t\t\t\tBuild_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,\n\t\t\t\t\t\t&initstr_index);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CWAITSTR | KN_BUTTON):\n\t\t\t\titem = (char *)cwaitstrlist.Current_Item();\n\t\t\t\tif (cwaitstr_index < 3) {\n\t\t\t\t} else {\n\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\tlen = strlen( cwaitstrbuf );\n\t\t\t\t\t\tstrncpy( item + pos, cwaitstrbuf, len );\n\t\t\t\t\t\t*(item + pos + len) = 0;\n\t\t\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_CWAITSTRLIST | KN_BUTTON):\n\t\t\t\tif (cwaitstrlist.Current_Index() != cwaitstr_index) {\n\t\t\t\t\tcwaitstr_index = cwaitstrlist.Current_Index();\n\t\t\t\t\titem = (char *)cwaitstrlist.Current_Item();\n\t\t\t\t\tif (cwaitstr_index < 3) {\n\t\t\t\t\t\tstrncpy( cwaitstrbuf, item, CWAITSTRBUF_MAX );\n\t\t\t\t\t\tcwaitstr_edt.Clear_Focus();\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\t\t}\n\t\t\t\t\tcwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );\n\t\t\t\t} else if (cwaitstr_index < 3) {\n\t\t\t\t\tcwaitstr_edt.Clear_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tcwaitstr_edt.Set_Focus();\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_BUTTONS;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_TONE | KN_BUTTON):\n\t\t\t\ttempsettings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\ttonebtn.Turn_On();\n\t\t\t\tpulsebtn.Turn_Off();\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_PULSE | KN_BUTTON):\n\t\t\t\ttempsettings.DialMethod = DIAL_PULSE;\n\t\t\t\ttonebtn.Turn_Off();\n\t\t\t\tpulsebtn.Turn_On();\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tSAVE: save the com settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tswitch (port_index) {\n\t\t\t\t\tcase ( 0 ):\n\t\t\t\t\t\ttempsettings.Port = 0x3f8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 1 ):\n\t\t\t\t\t\ttempsettings.Port = 0x2f8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 2 ):\n\t\t\t\t\t\ttempsettings.Port = 0x3e8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 3 ):\n\t\t\t\t\t\ttempsettings.Port = 0x2e8;\n\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (port_index == port_custom_index) {\n#ifdef WIN32\n\t\t\t\t\t\t\tstrncpy ( tempsettings.ModemName, portbuf, MODEM_NAME_MAX );\n\t\t\t\t\t\t\ttempsettings.Port = 1;\n#else\t//WIN32\n\t\t\t\t\t\t\tsscanf( portbuf, \"%x\", &tempsettings.Port );\n\t\t\t\t\t\t\ttempsettings.ModemName[0] = 0;\n#endif\t//WIN32\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Must be a modem name index\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tstrcpy (tempsettings.ModemName, portlist.Current_Item());\n\t\t\t\t\t\t\ttempsettings.Port = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\n#ifndef WIN32\n\t\t\t\tswitch (irq_index) {\n\t\t\t\t\tcase ( 0 ):\n\t\t\t\t\t\ttempsettings.IRQ = 2;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 1 ):\n\t\t\t\t\t\ttempsettings.IRQ = 3;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 2 ):\n\t\t\t\t\t\ttempsettings.IRQ = 4;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase ( 3 ):\n\t\t\t\t\t\ttempsettings.IRQ = 5;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsscanf( irqbuf, \"%d\", &tempsettings.IRQ );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\t//WIN32\n\t\t\t\tsscanf( baudbuf, \"%d\", &tempsettings.Baud );\n\n\t\t\t\ttempsettings.InitStringIndex = initstr_index;\n\t\t\t\ttempsettings.CallWaitStringIndex = cwaitstr_index;\n\n\t\t\t\titem = Session.CallWaitStrings[ CALL_WAIT_CUSTOM ];\n\t\t\t\ttemp = strchr( item, '-' );\n\t\t\t\tif ( temp ) {\n\t\t\t\t\tpos = (int)(temp - item) + 2;\n\t\t\t\t\tstrncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );\n\t\t\t\t} else {\n\t\t\t\t\tcwaitstrbuf[ 0 ] = 0;\n\t\t\t\t}\n\n\t\t\t\tstrncpy( tempsettings.CallWaitString, cwaitstrbuf, CWAITSTRBUF_MAX );\n\n\t\t\t\tdpstatus = NullModem.Detect_Port( &tempsettings );\n\n\t\t\t\tif (dpstatus == PORT_VALID) {\n\t\t\t\t\tprocess = false;\n\t\t\t\t\trc = true;\n\n\t\t\t\t} else if (dpstatus == PORT_INVALID) {\n#ifdef WIN32\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_TO_OPEN_PORT );\n#else\t//WIN32\n\t\t\t\t\tWWMessageBox().Process( TXT_INVALID_SETTINGS );\n#endif\t//WIN32\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\n\t\t\t\t} else if (dpstatus == PORT_IRQ_INUSE) {\n\t\t\t\t\tWWMessageBox().Process( TXT_IRQ_ALREADY_IN_USE );\n\t\t\t\t\tfirsttime = true;\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave values into the Settings structure\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tmemcpy( settings, &tempsettings, sizeof(SerialSettingsType) );\n\t}\n\n\treturn(rc);\n\n}\t/* end of Com_Settings_Dialog */\n\n\n/***************************************************************************\n * Build_Init_String_Listbox -- [re]builds the initstring listbox          *\n *                                                                         *\n * This routine rebuilds the initstring list box from scratch; it also\t\t*\n * updates the contents of the initstring edit field.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\tptr to list box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit\t\tptr to edit box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuf\t\tptr to buffer for initstring\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index)\n{\n\tint i, curidx;\n\tchar *item;\n\n\n\tcuridx = *index;\n\n\t/*........................................................................\n\tClear the list\n\t........................................................................*/\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\t/*\n\t** Now sort the init string list by name then number\n\t*/\n\tqsort ((void *)(&Session.InitStrings[0]), Session.InitStrings.Count(), sizeof(char *), Init_String_Compare);\n\n\t/*........................................................................\n\tBuild the list\n\t........................................................................*/\n\tfor (i = 0; i < Session.InitStrings.Count(); i++) {\n\t\titem = new char[ INITSTRBUF_MAX ];\n\t\tstrcpy( item, Session.InitStrings[i] );\n\t\tlist->Add_Item(item);\n\t}\n\tlist->Flag_To_Redraw();\n\n\t/*........................................................................\n\tInit the current phone book index\n\t........................................................................*/\n\tif (list->Count() == 0 || curidx < -1) {\n\t\tcuridx = -1;\n\t} else if (curidx >= list->Count() ) {\n\t\tcuridx = 0;\n\t}\n\n\t/*........................................................................\n\tFill in initstring edit buffer\n\t........................................................................*/\n\tif (curidx > -1) {\n\t\tstrcpy (buf, Session.InitStrings[ curidx ]);\n\t\tedit->Set_Text (buf, INITSTRBUF_MAX );\n\t\tlist->Set_Selected_Index( curidx );\n\t}\n\n\t*index = curidx;\n}\n\n\n/***************************************************************************\n * Init_String_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tp1,p2\t\tptrs to elements to compare\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/08/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Init_String_Compare (const void *p1, const void *p2)\n{\n\treturn( strcmp( *((char **)p1), *((char **)p2) ) );\n}\n\n\n/***********************************************************************************************\n * Com_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = success, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.\n *   01/21/97 V.Grippi added check for CS before sending scenario file                                             \t\t\t\t\t\t  *\n *=============================================================================================*/\nint Com_Scenario_Dialog(bool skirmish)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = 70 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\tint d_name_y = d_dialog_y + d_margin2 + d_txt6_h + 1 * RESFACTOR;\n\n#ifdef OLDWAY\n\tint d_gdi_w = 40 * RESFACTOR;\n\tint d_gdi_h = 9 * RESFACTOR;\n\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\tint d_gdi_y = d_name_y;\n\n\tint d_nod_w = 40 * RESFACTOR;\n\tint d_nod_h = 9 * RESFACTOR;\n\tint d_nod_x = d_dialog_cx;\n\tint d_nod_y = d_name_y;\n#else\n\tint d_house_w = 60 *RESFACTOR;\n\tint d_house_h = (8 * 5 *RESFACTOR);\n\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\tint d_house_y = d_name_y;\n#endif\n\n\tint d_color_w = 10 * RESFACTOR;\n\tint d_color_h = 9 * RESFACTOR;\n\tint d_color_y = d_name_y;\n\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\n\tint d_playerlist_w = 118 * RESFACTOR;\n\tint d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR;\n\tint d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h*/;\n\n\tint d_scenariolist_w = 162 * RESFACTOR;\n\tint d_scenariolist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\n\tif (skirmish) {\n\t\td_scenariolist_h *= 2;\n\t}\n\n\n\tint d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - 5*RESFACTOR;\n\tint d_scenariolist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR;\n\n\tif (skirmish) {\n\t\td_scenariolist_x = d_dialog_x + (d_dialog_w-d_scenariolist_w)/2;\n\t}\n\n\tint d_count_w = 25 * RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t\t// (fudged)\n\tint d_count_y = d_playerlist_y + d_playerlist_h + (d_margin1 * 2) - 2 * RESFACTOR;\n\n\tif (skirmish) {\n\t\td_count_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR;\n\t}\n\n\tint d_level_w = 25 * RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t\t// (fudged)\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25 * RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR;\t// (fudged)\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25*RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR;\t// (fudged)\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 106 * RESFACTOR;\n\tint d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR;\n\tint d_options_x = d_dialog_x + d_dialog_w - 149 * RESFACTOR;\n\tint d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (8 * d_txt6_h) + 3 * RESFACTOR;\t\t// 4 rows high\n\tint d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_options_y + d_options_h + 2*RESFACTOR;\n\n\tint d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_send_h = 9 * RESFACTOR;\n\tint d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_ok_w = 45 * RESFACTOR;\n\tint d_ok_h = 9 * RESFACTOR;\n\tint d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);\n\tint d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - RESFACTOR*6;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - RESFACTOR*6;\n\n\tint d_load_w = 45 * RESFACTOR;\n\tint d_load_h = 9 * RESFACTOR;\n\tint d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);\n\tint d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - RESFACTOR*6;\n\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\n\t\tBUTTON_HOUSE,\n#endif\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AIPLAYERS,\n\t\tBUTTON_OPTIONS,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_SCENARIOLIST,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_OK,\n\t\tBUTTON_LOAD,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_DIFFICULTY,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tint playertabs[] = {77*RESFACTOR};\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for player list box\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n\tbool transmit;\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7)\n\t\t\t\t\t\t\t};\n\tbool parms_received = false;\t\t\t\t\t// 1 = game options received\n\tbool changed = false;\t\t\t\t\t\t\t// 1 = user has changed an option\n\n\tint rc;\n\tint recsignedoff = false;\n\tint i;\n\tunsigned long version;\n\tunsigned long starttime;\n\tunsigned long timingtime;\n\tunsigned long lastmsgtime;\n\tunsigned long lastredrawtime;\n\tunsigned long transmittime = 0;\n\tunsigned long theirresponsetime;\n\tint packetlen;\n\tstatic bool first_time = true;\n\tbool oppscorescreen = false;\n\tbool gameoptions = Session.Type == GAME_SKIRMISH;\n\tEventClass *event;\t\t\t\t\t// event ptr\n\tunsigned long msg_timeout = 1200;\t// init to 20 seconds\n\n\tCCFileClass loadfile (\"SAVEGAME.NET\");\n\tbool load_game = false;\t\t\t\t\t// 1 = load a saved game\n\tNodeNameType *who;\t\t\t\t\t// node to add to Players\n\tchar *item;\t\t\t\t\t\t\t\t// for filling in lists\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tbool messages_have_focus = true;\t\t// Gadget focus starts on the message system\n\n\tSet_Logic_Page(SeenBuff);\n\n\tCDTimerClass<SystemTimerClass> kludge_timer;\t\t// Timer to allow a wait after client joins\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// game before game can start\n\tbool ok_button_added = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass * commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h);\n#else\n\tchar housetext[25] = \"\";\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\n\tchar staticcountbuff[35];\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y);\n\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\n\tchar staticlevelbuff[35];\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y);\n\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\n\tchar staticcreditsbuff[35];\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y);\n\n\tGaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\n\tchar staticaibuff[35];\n\tStaticButtonClass staticai(0, \"     \", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y);\n\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w, d_ok_h);\n\tTextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, d_load_w, d_load_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\tSliderClass difficulty(BUTTON_DIFFICULTY, d_name_x, optionlist.Y + optionlist.Height + d_margin1 + d_margin1, d_dialog_w - (d_name_x-d_dialog_x)*2, 8*RESFACTOR, true);\n\tif (Rule.IsFineDifficulty) {\n\t\tdifficulty.Set_Maximum(5);\n\t\tdifficulty.Set_Value(2);\n\t} else {\n\t\tdifficulty.Set_Maximum(3);\n\t\tdifficulty.Set_Value(1);\n\t}\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &name_edt;\n\tstaticcount.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticai.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tif (!skirmish) {\n\t\tplayerlist.Add_Tail(*commands);\n\t} else {\n\t\tdifficulty.Add_Tail(*commands);\n\t}\n\tscenariolist.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n\tif (Session.Type == GAME_SKIRMISH){\n\t\tokbtn.Add_Tail(*commands);\n\t}\n\tcancelbtn.Add_Tail(*commands);\n\tif (!skirmish && loadfile.Is_Available()) {\n#ifdef FIXIT_MULTI_SAVE\n\t\t//Load button added only when other player has arrived\n\t\t//loadbtn.Add_Tail(*commands);\n#endif\n\t} else {\n\t\tcancelbtn.X = loadbtn.X;\n\t}\n#ifdef OLDWAY\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n#else\n\thousebtn.Add_Tail(*commands);\n#endif\n\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tInit player name & house\n\t........................................................................*/\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\n\n\t/*........................................................................\n\tInit scenario values, only the first time through\n\t........................................................................*/\n\tSpecial.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;\n\tif (first_time) {\n\t\tSession.Options.Credits = Rule.MPDefaultMoney;\t// init credits & credit buffer\n\t\tSession.Options.Bases = Rule.IsMPBasesOn;\t\t\t// init scenario parameters\n\t\tSession.Options.Tiberium = Rule.IsMPTiberiumGrow;\n\t\tSession.Options.Goodies = Rule.IsMPCrates;\n\t\tSession.Options.AIPlayers = 0;\n\t\tSpecial.IsShadowGrow = Rule.IsMPShadowGrow;\n\t\tSession.Options.UnitCount = (SessionClass::CountMax[Session.Options.Bases] + SessionClass::CountMin[Session.Options.Bases]) / 2;\n\t\tfirst_time = false;\n\t}\n\n\t/*........................................................................\n\tInit button states\n\t........................................................................*/\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(0);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\tif (!skirmish) {\n\t\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\t}\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsShadowGrow);\n\tif (!skirmish) {\n\t\toptionlist.Check_Item(4, Special.IsCaptureTheFlag);\n\t}\n\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\tint maxp = Rule.MaxPlayers - 2;\n//\tint maxp = Rule.MaxPlayers - (skirmish ? 1 : 2);\n\taiplayersgauge.Set_Maximum(maxp);\n\n\tif (skirmish) {\n\t\tif ( Session.Options.AIPlayers > 7 ) {\n\t\t\tSession.Options.AIPlayers = 7;\n\t\t}\n\t\tSession.Options.AIPlayers = max(Session.Options.AIPlayers, 1);\n\t}else{\n\t\tif ( Session.Options.AIPlayers > 6 ) {\n\t\t\tSession.Options.AIPlayers = 6;\n\t\t}\n\t}\n\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0));\n\n\t/*........................................................................\n\tInit other scenario parameters\n\t........................................................................*/\n\tSpecial.IsTGrowth = //Session.Options.Tiberium;\n\t\tRule.IsTGrowth = //Session.Options.Tiberium;\n\t\t\tSpecial.IsTSpread = //Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\ttransmit = true;\n\n\t/*........................................................................\n\tClear the Players vector\n\t........................................................................*/\n\tClear_Vector(&Session.Players);\n\n\t/*........................................................................\n\tInit scenario description list box\n\t........................................................................*/\n\tfor (i = 0; i < Session.Scenarios.Count(); i++) {\n\t\tfor (int j = 0; EngMisStr[j] != NULL;  j++) {\n\t\t\tif (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed).\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\tscenariolist.Add_Item(EngMisStr[j+1]);\n#else\n\t\t\t\tscenariolist.Add_Item(EngMisStr[j]);\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (EngMisStr[j] == NULL) {\n#ifdef FIXIT_CSII\t//\tajw Added Aftermath installed checks (before, it was assumed). Added officialness check.\n\t\t\t//\tAdd mission if it's available to us.\n\t\t\tif( !Session.Scenarios[i]->Get_Official() ||\n\t\t\t\t!( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||\n\t\t\t\t\t( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )\n#endif\n\t\t\tscenariolist.Add_Item(Session.Scenarios[i]->Description());\n\t\t}\n\t}\n\n\tSession.Options.ScenarioIndex = 0;\t\t// 1st scenario is selected\n\n\t/*........................................................................\n\tInit random-number generator, & create a seed to be used for all random\n\tnumbers from here on out\n\t........................................................................*/\n#ifdef FIXIT_RANDOM_GAME\n\tsrand(time(NULL));\n\tSeed = rand();\n#else\n//\trandomize();\n//\tSeed = rand();\n#endif\n\n\t/*........................................................................\n\tInit the message display system\n\t........................................................................*/\n\tif (!skirmish) {\n\t\tSession.Messages.Init (d_message_x + 1, d_message_y + 1, 8,\n\t\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1, d_send_y + 1, 1,\n\t\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\t\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\t}\n\n\t/*........................................................................\n\tInit version number clipping system\n\t........................................................................*/\n\tVerNum.Init_Clipping();\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\n\n\textern char ModemRXString[];\n\n\tif (strlen(ModemRXString) > 36)\n\t\tModemRXString[36] = 0;\n\n\tif (strlen(ModemRXString) > 0)\n\t\tSession.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN,\n\t\t\tTPF_TEXT, -1);\n\n\tModemRXString[0] = '\\0';\n\n\t/*\n\t---------------------------- Init Mono Output ----------------------------\n\t*/\n\t#if(SHOW_MONO)\n\tif (!skirmish) {\n\t\tNullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),\n\t\t\tSerialPacketNames, 100, 8);\n\t\tNullModem.Mono_Debug_Print(1);\n\t}\n\t#endif\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tif (!skirmish) {\n\t\tNullModem.Reset_Response_Time();\t\t// clear response time\n\t}\n\ttheirresponsetime = 10000;\t\t\t\t// initialize to an invalid value\n\ttimingtime = lastmsgtime = lastredrawtime = TickCount;\n\n\n\t/*\n\t** Those easily offended should avert their eyes from the following line. And whatever\n\t** you do, dont search for 'goto'.\n\t*/\noh_dear_its_a_label:\n\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tif (!skirmish) {\n\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t}\n\t\t#endif\n\n\t\tif (!skirmish){\n\t\t\tif (!ok_button_added && gameoptions && kludge_timer == 0){\n\t\t\t\tokbtn.Add_Tail(*commands);\n\t\t\t\tok_button_added = true;\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( loadfile.Is_Available() )\n\t\t\t\t{\n\t\t\t\t\tloadbtn.Add_Tail( *commands );\n\t\t\t\t}\n#else\n#ifdef FIXIT_MULTI_SAVE\n\t\t\t\tif ( loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) {\n\t\t\t\t\tloadbtn.Add_Tail ( *commands );\n\t\t\t\t}\n#endif\n#endif\n\t\t\t\tif (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (!skirmish) {\n\t\t\tif (messages_have_focus) {\n\t\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tmessages_have_focus = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\t\tmessages_have_focus = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE)\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#ifdef OLDWAY\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t} else {\n\t\t\t\t\tFancy_Text_Print(TXT_EASY, difficulty.X, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_TEXT);\n\t\t\t\t\tFancy_Text_Print(TXT_HARD, difficulty.X + difficulty.Width, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_RIGHT|TPF_TEXT);\n\t\t\t\t\tFancy_Text_Print(TXT_NORMAL, difficulty.X + difficulty.Width/2, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_CENTER|TPF_TEXT);\n\t\t\t\t}\n\t\t\t\tFancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_COUNT, d_count_x - 2, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_LEVEL, d_level_x - 2, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the color boxes\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_COLORS) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,\n\t\t\t\t\t\tcbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the message system; erase old messages first\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_MESSAGE && !skirmish) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Update game parameter labels\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS) {\n\n//\t\t\t\tLogicPage->Fill_Rect(d_count_x + d_count_w + 2, d_count_y, d_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);\n\n\t\t\t\tsprintf(staticcountbuff, \"%d\", Session.Options.UnitCount);\n\t\t\t\tstaticcount.Set_Text(staticcountbuff);\n\t\t\t\tstaticcount.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d \", d_count_x + d_count_w + 3 * RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT, Session.Options.UnitCount);\n\n\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\tsprintf(staticlevelbuff, \"%d \", BuildLevel);\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(staticlevelbuff, \"**\");\n\t\t\t\t}\n\t\t\t\tstaticlevel.Set_Text(staticlevelbuff);\n\t\t\t\tstaticlevel.Draw_Me();\n//\t\t\t\tFancy_Text_Print(txt, d_level_x + d_level_w + 3 * RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);\n\n\t\t\t\tsprintf(staticcreditsbuff, \"%d\", Session.Options.Credits);\n\t\t\t\tstaticcredits.Set_Text(staticcreditsbuff);\n\t\t\t\tstaticcredits.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d\", d_credits_x + d_credits_w + 2 * RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT, Session.Options.Credits);\n\n\t\t\t\tsprintf(staticaibuff, \"%d\", Session.Options.AIPlayers);\n\t\t\t\tstaticai.Set_Text(staticaibuff);\n\t\t\t\tstaticai.Draw_Me();\n//\t\t\t\tFancy_Text_Print(\"%d\", d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT, Session.Options.AIPlayers);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t\tcommands->Draw_All();\n\t\t\t}\n\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tmessages_have_focus = Session.Messages.Has_Edit_Focus();\n\t\tbool droplist_is_dropped = housebtn.IsDropped;\n\t\tinput = commands->Input();\n\n\t\t/*\n\t\t** Sort out the input focus between the name edit box and the message system\n\t\t*/\n\t\tif (!skirmish) {\n\t\t\tif (messages_have_focus) {\n\t\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t\t} else {\n\t\t\t\t\tmessages_have_focus = false;\n\t\t\t\t\tdisplay = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Redraw everything if the droplist collapsed\n\t\t*/\n\t\tif (droplist_is_dropped && !housebtn.IsDropped) {\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\tif (input & KN_BUTTON) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser clicks on a color button\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\n\t\t\t\t\tSession.PrefColor = (PlayerColorType)((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\n\t\t\t\t\tname_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx);\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser edits the name field; retransmit new game options\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t/*------------------------------------------------------------------\n\t\t\tHouse Buttons: set the player's desired House\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#else\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\tSession.House = HousesType(housebtn.Current_Index()+HOUSE_USSR);\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tNew Scenario selected.\n\t\t\t------------------------------------------------------------------*/\n#ifdef FIXIT_VERSION_3\t\t//\tAll scenarios now allowable as downloads. ajw\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex)\n\t\t\t\t{\n\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n#else\t//\tFIXIT_VERSION_3\t\tWhoever duplicated Netdlg into Nulldlg should be shot. Wasn't it enough?\n\n\t\t\t\tAbandon all hope ye who hit enter here.\n\n\t\t\tcase (BUTTON_SCENARIOLIST | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tif (scenariolist.Current_Index() != Session.Options.ScenarioIndex) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\tif ( !skirmish && (PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&\n#else\n\t\t\t\t\tif ( !skirmish && PlayingAgainstVersion < VERSION_RED_ALERT_107 &&\n#endif\n\t\t\t\t\t\t\t\tSession.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\t\t} else\n\t\t\t\t\tif ( !skirmish && PlayingAgainstVersion < VERSION_AFTERMATH_CS &&\n\t\t\t\t\t\t\tIs_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){\n\t\t\t\t\t\tscenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);\n\t\t\t\t\t\tSession.Messages.Add_Message(NULL, 0,\n\t\t\t\t\t\t\t(char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n#endif\n\t\t\t\t\t}else{\n\t\t\t\t\t\tSession.Options.ScenarioIndex = scenariolist.Current_Index();\n\t\t\t\t\t\ttransmit = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\ttransmit = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts max # units\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_COUNT | KN_BUTTON):\n\t\t\t\tSession.Options.UnitCount = countgauge.Get_Value() + SessionClass::CountMin[Session.Options.Bases];\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts build level\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_LEVEL | KN_BUTTON):\n\t\t\t\tBuildLevel = levelgauge.Get_Value() + 1;\n\t\t\t\tif (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)\t// if it's pegged, max it out\n\t\t\t\t\tBuildLevel = MPLAYER_BUILD_LEVEL_MAX;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser adjusts max # units\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_CREDITS | KN_BUTTON):\n\t\t\t\tSession.Options.Credits = creditsgauge.Get_Value();\n\t\t\t\tSession.Options.Credits = ((Session.Options.Credits + 250) / 500) * 500;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t//\tUser adjusts # of AI players\n\t\t\t//..................................................................\n\t\t\tcase (BUTTON_AIPLAYERS | KN_BUTTON):\n\t\t\t\t{\n\t\t\t\t\tSession.Options.AIPlayers = aiplayersgauge.Get_Value();\n\t\t\t\t\tint humans = 2;\t\t\t// Two humans.\n\t\t\t\t\tif (skirmish) {\n\t\t\t\t\t\tSession.Options.AIPlayers += 1;\t// Always one forced AI player.\n\t\t\t\t\t\thumans = 1;\t\t\t// One human.\n\t//\t\t\t\t\t\tif (Session.Options.AIPlayers == 0) {\n\t//\t\t\t\t\t\t\tSession.Options.AIPlayers = 1;\n\t//\t\t\t\t\t\t\taiplayersgauge.Set_Value(0);\n\t//\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (Session.Options.AIPlayers+humans >= Rule.MaxPlayers) {\t// if it's pegged, max it out\n\t\t\t\t\t\tSession.Options.AIPlayers = Rule.MaxPlayers - humans;\n\t\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0));\n\t\t\t\t\t}\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t// Toggle-able options:\n\t\t\t// If 'Bases' gets toggled, we have to change the range of the\n\t\t\t// UnitCount slider.\n\t\t\t// Also, if Tiberium gets toggled, we have to set the flags\n\t\t\t// in SpecialClass.\n\t\t\t//------------------------------------------------------------------\n\t\t\tcase (BUTTON_OPTIONS | KN_BUTTON):\n\t\t\t\tif (!skirmish && Special.IsCaptureTheFlag != optionlist.Is_Checked(4) && !Special.IsCaptureTheFlag) {\n\t\t\t\t\toptionlist.Check_Item(0, true);\n\t\t\t\t}\n\t\t\t\tif (Session.Options.Bases != optionlist.Is_Checked(0)) {\n\t\t\t\t\tSession.Options.Bases = optionlist.Is_Checked(0);\n\t\t\t\t\tif (Session.Options.Bases) {\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[1] -\n\t\t\t\t\t\t\tSessionClass::CountMin[1],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[0]-SessionClass::CountMin[0],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount-SessionClass::CountMin[0])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!skirmish) optionlist.Check_Item(4, false);\n\t\t\t\t\t\tSession.Options.UnitCount = Fixed_To_Cardinal (\n\t\t\t\t\t\t\tSessionClass::CountMax[0] -\n\t\t\t\t\t\t\tSessionClass::CountMin[0],\n\t\t\t\t\t\t\tCardinal_To_Fixed(\n\t\t\t\t\t\t\t\tSessionClass::CountMax[1]-SessionClass::CountMin[1],\n\t\t\t\t\t\t\t\tSession.Options.UnitCount - SessionClass::CountMin[1])) +\n\t\t\t\t\t\t\tSessionClass::CountMin[0];\n\t\t\t\t\t}\n\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t}\n\t\t\t\tSession.Options.Tiberium = optionlist.Is_Checked(1);\n\t\t\t\tSpecial.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tRule.IsTGrowth = Session.Options.Tiberium;\n\t\t\t\tSpecial.IsTSpread = Session.Options.Tiberium;\n\t\t\t\tRule.IsTSpread = Session.Options.Tiberium;\n\n\t\t\t\tSession.Options.Goodies = optionlist.Is_Checked(2);\n\t\t\t\tSpecial.IsShadowGrow = optionlist.Is_Checked(3);\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tSpecial.IsCaptureTheFlag = optionlist.Is_Checked(4);\n\t\t\t\t}\n\n\t\t\t\ttransmit = true;\n\t\t\t\tif (display < REDRAW_PARMS) display = REDRAW_PARMS;\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tOK: exit loop with true status\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_LOAD | KN_BUTTON):\n\t\t\tcase (BUTTON_OK | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\t// make sure we got a game options packet from the other player\n\t\t\t\t//\n\t\t\t\tif (gameoptions) {\n\t\t\t\t\trc = true;\n\t\t\t\t\tprocess = false;\n\n\t\t\t\t\t// force transmitting of game options packet one last time\n\n\t\t\t\t\ttransmit = true;\n\t\t\t\t\ttransmittime = 0;\n\t\t\t\t} else {\n\t\t\t\t\tWWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);\n\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t}\n\t\t\t\tif (input==(BUTTON_LOAD | KN_BUTTON))\n\t\t\t\t\tload_game = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDefault: manage the inter-player messages\n\t\t\t------------------------------------------------------------------*/\n\t\t\tdefault:\n\t\t\t\tif (!skirmish) {\n\t\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tService keyboard input for any message being edited.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t\t(We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\tif (i==1) {\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t} else if (i==2) {\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\t\tRather than setting 'display', which would redraw all msgs,\n\t\t\t\t\twe only need to erase & redraw the edit box here.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tHide_Mouse();\n\t\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);\n\t\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\t\tShow_Mouse();\n\t\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\t\t\tSendPacket.Command = SERIAL_MESSAGE;\n\t\t\t\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*..................................................................\n\t\t\t\t\t\tSend the message\n\t\t\t\t\t\t..................................................................*/\n\t\t\t\t\t\tif (!skirmish) {\n\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/*..................................................................\n\t\t\t\t\t\tAdd the message to our own screen\n\t\t\t\t\t\t..................................................................*/\n\t\t\t\t\t\tSession.Messages.Add_Message (SendPacket.Name, SendPacket.ID,\n\t\t\t\t\t\t\tSendPacket.Message.Message,\n\t\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t}\t/* end of send message */\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tDetect editing of the name buffer, transmit new values to players\n\t\t---------------------------------------------------------------------*/\n\t\tif (strcmp (namebuf, Session.Handle)) {\n\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\ttransmit = true;\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tIf our Transmit flag is set, we need to send out a game option packet.\n\t\tThis message requires an ACK.  The first time through the loop, transmit\n\t\tshould be set, so we send out our default options; we'll then send\n\t\tany changes we make to the defaults.\n\t\t---------------------------------------------------------------------*/\n\t\tif (skirmish) {\n\t\t\ttransmit = false;\n\t\t}\n\n\t\tif (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_GAME_OPTIONS;\n\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\tSendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\t\t\tSendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version();\n\t\t\tSendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version();\n\t\t\tSendPacket.ScenarioInfo.House = Session.House;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\n\t\t\tSendPacket.ScenarioInfo.Credits = Session.Options.Credits;\n\t\t\tSendPacket.ScenarioInfo.IsBases = Session.Options.Bases;\n\t\t\tSendPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;\n\t\t\tSendPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;\n\t\t\tSendPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;\n\t\t\tSendPacket.ScenarioInfo.BuildLevel = BuildLevel;\n\t\t\tSendPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;\n\t\t\tSendPacket.ScenarioInfo.Seed = Seed;\n\t\t\tSendPacket.ScenarioInfo.Special = Special;\n\t\t\tSendPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\t/*\n\t\t\t** Set up the scenario info so the remote player can match the scenario on his machine\n\t\t\t** or request a download if it doesnt exist\n\t\t\t*/\n\t\t\tstrcpy (SendPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());\n\t\t\tCCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t\tSendPacket.ScenarioInfo.FileLength = file.Size();\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstrcpy( SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );\n#else\n\t\t\tstrncpy (SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(SendPacket.ScenarioInfo.ShortFileName));\n#endif\n\t\t\tstrncpy ((char*)SendPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof SendPacket.ScenarioInfo.FileDigest);\n\t\t\tSendPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\ttransmittime = TickCount;\n\t\t\ttransmit = false;\n\n\t\t\t//..................................................................\n\t\t\t// Keep the player list up to date\n\t\t\t//..................................................................\n\t\t\tif (playerlist.Count()) {\n\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef OLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Play a little sound effect\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t}\n\n\t\t//\n\t\t// send a timing packet if enough time has gone by.\n\t\t//\n\t\tif (!skirmish &&  (TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_TIMING;\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t\ttimingtime = TickCount;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tCheck for an incoming message\n\t\t---------------------------------------------------------------------*/\n\t\tif (!skirmish && NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\t\t\tmsg_timeout = 600;\t\t// reset timeout value to 10 seconds\n\t\t\t\t\t\t\t\t\t\t\t// (only the 1st time through is 20 seconds)\n\n\t\t\t// are we getting our own packets back??\n\n\t\t\tif (ReceivePacket.Command >= SERIAL_CONNECT &&\n\t\t\t\tReceivePacket.Command < SERIAL_LAST_COMMAND &&\n\t\t\t\tReceivePacket.Command != SERIAL_MESSAGE &&\n\t\t\t\tReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\n\t\t\t\t// to skip the other system not responding msg\n\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\n\t\t\t\t// say we did receive sign off to keep from sending one\n\t\t\t\trecsignedoff = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tevent = (EventClass *)&ReceivePacket;\n\t\t\tif (event->Type <= EventClass::FRAMEINFO) {\n\t\t\t\tif ( (TickCount - lastredrawtime) > PACKET_REDRAW_TIME) {\n\t\t\t\t\tlastredrawtime = TickCount;\n\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tparms_received = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( ReceivePacket.Command ) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tSign-off: Give the other machine time to receive my ACK, display a\n\t\t\t\t\tmessage, and exit.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_SIGN_OFF):\n\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\twhile (TickCount - starttime < 60)\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\tWWMessageBox().Process(TXT_USER_SIGNED_OFF);\n\n\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = false;\n\t\t\t\t\t\trecsignedoff = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGame Options:  Store the other machine's name, color & house;\n\t\t\t\t\tIf they've picked the same color as myself, re-transmit my settings\n\t\t\t\t\tto force him to choose a different color.  (Com_Show_Scenario_Dialog\n\t\t\t\t\tis responsible for ensuring the colors are different.)\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_GAME_OPTIONS):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tgameoptions = true;\n\t\t\t\t\t\tkludge_timer = 2*60;\n\t\t\t\t\t\tstrcpy (TheirName, ReceivePacket.Name);\n\t\t\t\t\t\tTheirColor = ReceivePacket.ScenarioInfo.Color;\n\t\t\t\t\t\tTheirHouse = ReceivePacket.ScenarioInfo.House;\n\t\t\t\t\t\ttransmit = true;\n\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// \"Clip\" the other system's version range to our own\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tversion = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion,\n\t\t\t\t\t\t\tReceivePacket.ScenarioInfo.MaxVersion);\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0, the other\n\t\t\t\t\t\t// system's range is too low for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tif (version == 0) {\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_DESTGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else if (version == 0xffffffff) {\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0xffffffff,\n\t\t\t\t\t\t// the other system's range is too high for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_YOURGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tif (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) {\n\t\t\t\t\t\t\t\tWWMessageBox().Process (TXT_MISMATCH);\n\n\t\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\trc = false;\n\n\t\t\t\t\t\t\t} else {\n\n\n\t\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t\t// Otherwise, 'version' is the highest version we have in\n\t\t\t\t\t\t\t\t// common; look up the protocol that goes with this version.\n\t\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tPlayingAgainstVersion = version;\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf this is the first game-options packet we've received,\n\t\t\t\t\t\tinit the game & player lists\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (playerlist.Count()==0) {\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Add two strings to the player list\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[Session.ColorIdx]);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[TheirColor]);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Ensure the player list has the latest, greatest copy of\n\t\t\t\t\t\t// our names & colors.  Do this every time we receive an\n\t\t\t\t\t\t// options packet.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef OLDWAY\n\t\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(1);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (TheirHouse==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : TheirColor];\n\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Play a little sound effect\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tIncoming message: add to our list\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_MESSAGE):\n\t\t\t\t\t\toppscorescreen = false;\n\n\t\t\t\t\t\tSession.Messages.Add_Message (ReceivePacket.Name,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tReceivePacket.Message.Message,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// get their response time\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_TIMING):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\ttheirresponsetime = ReceivePacket.ScenarioInfo.ResponseTime;\n\n\t\t\t\t\t\tif ( !gameoptions ) {\n\n\t\t\t\t\t\t\t// retransmit of game options packet again\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// print msg waiting for opponent\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_SCORE_SCREEN):\n\t\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we haven't received a msg for 10 seconds exit\n\n\t\tif (!skirmish && (TickCount - lastmsgtime) > msg_timeout) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\tprocess = false;\n\t\t\trc = false;\n\n\t\t\t// say we did receive sign off to keep from sending one\n\t\t\trecsignedoff = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tService the connection\n\t\t---------------------------------------------------------------------*/\n\t\tif (!skirmish) {\n\t\t\tNullModem.Service();\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tPrepare to load the scenario\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tSession.NumPlayers = skirmish ? 1 : 2;\n\n\t\tScen.Scenario = Session.Options.ScenarioIndex;\n\t\tstrcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());\n\n\t\t/*.....................................................................\n\t\tAdd both players to the Players vector; the local system is always\n\t\tindex 0.\n\t\t.....................................................................*/\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, namebuf);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\t/*\n\t\t**\tFetch the difficulty setting when in skirmish mode.\n\t\t*/\n\t\tif (skirmish) {\n\t\t\tint diff = difficulty.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2);\n\t\t\tswitch (diff) {\n\t\t\t\tcase 0:\n\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\tScen.Difficulty = DIFF_EASY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\t\t\t\t\tScen.CDifficulty = DIFF_HARD;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\t\t\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 3:\n\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 4:\n\t\t\t\t\tScen.CDifficulty = DIFF_EASY;\n\t\t\t\t\tScen.Difficulty = DIFF_HARD;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tScen.CDifficulty = DIFF_NORMAL;\n\t\t\tScen.Difficulty = DIFF_NORMAL;\n\t\t}\n\n\t\tif (!skirmish) {\n\t\t\twho = new NodeNameType;\n\n\t\t\t#ifdef FIXIT_MODEM_LOAD_CRASH\n\t\t\t/* If the names of the players are the same then we MUST force them\n\t\t\t * be be unique. This is necessary to prevent a crash after loading\n\t\t\t * a modem save game.\n\t\t\t */\n\t\t\tif (strcmp(TheirName, namebuf) == 0)\n\t\t\t\t{\n\t\t\t\tif (strlen(TheirName) == (MPLAYER_NAME_MAX - 1))\n\t\t\t\t\t{\n\t\t\t\t\tTheirName[MPLAYER_NAME_MAX - 1] = '\\0';\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tstrcat(TheirName, \"2\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\tstrcpy(who->Name, TheirName);\n\t\t\twho->Player.House = TheirHouse;\n\t\t\twho->Player.Color = TheirColor;\n\t\t\twho->Player.ProcessTime = -1;\n\t\t\tSession.Players.Add (who);\n\t\t}\n\n\t\t/*.....................................................................\n\t\tSend all players a GO packet.\n\t\t.....................................................................*/\n\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\tif (load_game) {\n\t\t\tSendPacket.Command = SERIAL_LOADGAME;\n\t\t} else {\n\t\t\tSendPacket.Command = SERIAL_GO;\n\t\t}\n\n\t\tif (!skirmish) {\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tif ( theirresponsetime == 10000 ) {\n\t\t\t\t;\n\t\t\t} else if (SendPacket.ScenarioInfo.ResponseTime < theirresponsetime) {\n\t\t\t\tSendPacket.ScenarioInfo.ResponseTime = theirresponsetime;\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// calculated one way delay for a packet and overall delay to execute\n\t\t// a packet\n\t\t//\n\t\tif (!skirmish) {\n\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\tSession.MaxAhead = max( ((((SendPacket.ScenarioInfo.ResponseTime / 8) +\n\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2)\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tSession.MaxAhead = max( (SendPacket.ScenarioInfo.ResponseTime / 8),\n\t\t\t\t\t\t\t\t\t\t\t  MODEM_MIN_MAX_AHEAD );\n\t\t\t}\n\t\t}\n\t\tSendPacket.ID = Session.ModemType;\n\n\t\tif (!skirmish) {\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\tstarttime = TickCount;\n\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t#if(SHOW_MONO)\n\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t#endif\n\n\t\t\t\tNullModem.Service();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Wait for the go response. This will be either a 'GO' reply, a\n\t\t\t** request for the scenario to be sent or a reply to say that the scenario\n\t\t\t** cant be played.\n\t\t\t*/\n#ifdef WIN32\n\t\t\tWWDebugString (\"RA95 - About to wait for 'GO' response.\\n\");\n#endif\n\t\t\tdo {\n\t\t\t\tNullModem.Service();\n\n\t\t\t\tif (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {\n\n#ifdef FIXIT_VERSION_3\n \t\t\t\t\tif (ReceivePacket.Command == SERIAL_READY_TO_GO)\n\t\t\t\t\t{\n\t\t\t\t\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#else\n \t\t\t\t\tif (ReceivePacket.Command == SERIAL_READY_TO_GO) break;\n#endif\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_NO_SCENARIO) {\n\t\t\t\t\t\tWWMessageBox().Process(TXT_NO_EXPANSION_SCENARIO, TXT_CANCEL);\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** We have to recover from this somehow so....\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tprocess = true;\n\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\tgoto oh_dear_its_a_label;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_REQ_SCENARIO) {\n#ifdef WIN32\n\t\t\t\t\t\tWWDebugString (\"RA95 - About to call 'Send_Remote_File'.\\n\");\n\n#endif\n\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\tif( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif( !Force_Scenario_Available( Scen.ScenarioName ) )\n\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t}\n#endif\n\n\t\t\t\t\t\tSend_Remote_File (Scen.ScenarioName, 0);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} while ( !Keyboard->Check() );\n\n\t\t// clear queue to keep from doing any resends\n\t\t\tNullModem.Init_Send_Queue();\n\t\t}\n\n\t} else {\n\t\tif ( !recsignedoff ) {\n\t\t\t/*.....................................................................\n\t\t\tBroadcast my sign-off over my network\n\t\t\t.....................................................................*/\n\t\t\tif (!skirmish) {\n\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\tSendPacket.Command = SERIAL_SIGN_OFF;\n\t\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\t\t// use Color for ID\n\t\t\t\tSendPacket.ID = Session.ModemType;\n\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\t\tstarttime = TickCount;\n\t\t\t\twhile ( (NullModem.Num_Send()\n\t\t\t\t\t&& ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) )\n\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t#if(SHOW_MONO)\n\t\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t\t#endif\n\n\t\t\t\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\n\t\t\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\t\t\tif (ReceivePacket.Command == SERIAL_SIGN_OFF\n\t\t\t\t\t\t\t&& ReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\t\t\t\t// exit while\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tNullModem.Service();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!skirmish) Shutdown_Modem();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear all lists\n\t------------------------------------------------------------------------*/\n\twhile (scenariolist.Count()) {\n\t\tscenariolist.Remove_Item(scenariolist.Get_Item(0));\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClean up the list boxes\n\t------------------------------------------------------------------------*/\n\twhile (playerlist.Count()>0) {\n\t\titem = (char *)playerlist.Get_Item(0);\n\t\tdelete [] item;\n\t\tplayerlist.Remove_Item(item);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tRemove the chat edit box\n\t------------------------------------------------------------------------*/\n\tSession.Messages.Remove_Edit();\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave any changes made to our options\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings();\n\t}\n\n\tif (load_game && !skirmish) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\treturn(rc);\n}\n\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * Find_Local_Scenario -- finds the file name of the scenario with matching attributes         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to Scenario description                                                       *\n *           ptr to Scenario filename to fix up                                                *\n *           length of file for trivial rejection of scenario files                            *\n *           ptr to digest. Digests must match.                                                *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:   true if scenario is available locally                                             *\n *                                                                                             *\n * WARNINGS: We need to reject files that don't match exactly because scenarios with the same  *\n *           description can exist on both machines but have different contents. For example   *\n *           there will be lots of scenarios called 'my map' and 'aaaaaa'.          \t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/23/96 12:36PM ST : Created                                                             *\n *=============================================================================================*/\nbool Find_Local_Scenario (char *description, char *filename, unsigned int length, char *digest, bool official)\n{\n//FILE *fp;\n//fp = fopen(\"findscen.txt\",\"wt\");\n//debugprint(\"looking for local scenario: description = %s, name=%s, length=%d, digest=%s, official=%d\\n\", description, filename, length, digest, official);\n\n\tchar digest_buffer[32];\n\t/*\n\t** Scan through the scenario list looking for scenarios with matching descriptions.\n\t*/\n\tfor (int index = 0; index < Session.Scenarios.Count(); index++) {\n\n//debugprint( \"Checking against scenario: %s\\n\", Session.Scenarios[index]->Description());\n\t\tif (!strcmp (Session.Scenarios[index]->Description(), description)) {\n//debugprint(\"found matching description.\\n\");\n\t\t\tCCFileClass file (Session.Scenarios[index]->Get_Filename());\n\n\t\t\t/*\n\t\t\t** Possible rejection on the basis of availability.\n\t\t\t*/\n\t\t\tif (file.Is_Available()) {\n//debugprint(\"file is available.\\n\");\n\t\t\t\t/*\n\t\t\t\t** Possible rejection on the basis of size.\n\t\t\t\t*/\n\t\t\t\tif (file.Size() == length) {\n//debugprint(\"length matches.\\n\");\n\t\t\t\t\t/*\n\t\t\t\t\t** We don't know the digest for 'official' scenarios so assume its correct\n\t\t\t\t\t*/\n\t\t\t\t\tif (!official) {\n//debugprint(\"!official.\\n\");\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Possible rejection on the basis of digest\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tINIClass ini;\n\t\t\t\t\t\tini.Load(file);\n\t\t\t\t\t\tini.Get_String (\"Digest\", \"1\", \"No digest here mate. Nope.\", digest_buffer, sizeof (digest_buffer) );\n\t\t\t\t\t}\n//debugprint(\"digest = %s, digest_buffer = %s.\\n\", digest, digest_buffer);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98. But don't know why this happens. Because of autodownload?\n\t\t\t\t\t/*\n\t\t\t\t\t** If this is an aftermath scenario then ignore the digest and return success.\n\t\t\t\t\t*/\n\t\t\t\t\tif ( Is_Mission_Aftermath ((char*)Session.Scenarios[index]->Get_Filename()) ) {\n//debugprint(\"a 1match!\\n\");\n\t\t\t\t\t\tstrcpy (filename, Session.Scenarios[index]->Get_Filename());\n\t\t\t\t\t\treturn (true);\n\t\t\t\t\t}\n#endif\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This must be the same scenario. Copy the name and return true.\n\t\t\t\t\t*/\n\t\t\t\t\tif (official || !strcmp (digest, digest_buffer)) {\n//debugprint(\"a match!\\n\");\n\t\t\t\t\t\tstrcpy (filename, Session.Scenarios[index]->Get_Filename());\n\t\t\t\t\t\treturn (true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n//\t\t\telse\n//\t\t\t\tdebugprint(\"file not available '%s'.\\n\", Session.Scenarios[index]->Get_Filename());\n\n\t\t}\n\t}\n//debugprint(\"failed match.\\n\");\n\t/*\n\t** Couldnt find the scenario locally. Return failure.\n\t*/\n\treturn (false);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Com_Show_Scenario_Dialog -- Serial game scenario selection dialog\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * The 'Players' vector is filled in by this routine, when the game starts; this\t\t\t\t\t  *\n * is for the Assign_Houses routine, which expects this vector to contain all\t\t\t\t\t\t  *\n * players' names & houses & colors.  Other than that, the Players vector, Games\t\t\t\t\t  *\n * vector, and Chat vector aren't used at all by this routine.  The Game & Players\t\t\t\t  *\n * list boxes are filled in manually in the processing loop.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n *    Ŀ                      \t  *\n *                            Serial Game                                                \t  *\n *                                                                                      \t  *\n *                       Your Name: __________                         \t\t\t\t\t\t\t  *\n *                           House: [GDI] [NOD]                   \t\t\t\t\t\t\t\t\t  *\n *                   Desired Color: [ ][ ][ ][ ]                   \t   \t\t\t\t\t\t  *\n *                                                                                    \t \t  *\n *                         Opponent: Name                                             \t \t  *\n *                         Scenario: Description                     \t\t\t\t\t\t\t\t  *\n *                          Credits: xxxx                            \t\t\t\t\t\t\t\t  *\n *                            Bases: ON                                              \t \t  *\n *                           Crates: ON                                              \t \t  *\n *                         Tiberium: ON                                              \t \t  *\n *                           Ghosts: ON                                              \t \t  *\n *                                                                                   \t \t  *\n *                             [Cancel]                                               \t \t  *\n *                                                                                   \t \t  *\n *       Ŀ                      \t \t  *\n *                                                                                 \t \t  *\n *                                                                                 \t \t  *\n *                             \t \t  *\n *                           [Send Message]                                          \t \t  *\n *                          \t  *\n *                                                                         \t\t\t\t\t\t  *\n * INPUT:                                                                  \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * OUTPUT:                                                                 \t\t\t\t\t\t  *\n *\t\ttrue = success, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * WARNINGS:                                                               \t\t\t\t\t\t  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         \t\t\t\t\t\t  *\n * HISTORY:                                                                \t\t\t\t\t\t  *\n *   02/14/1995 BR : Created.                                              \t\t\t\t\t\t  *\n *=============================================================================================*/\nint Com_Show_Scenario_Dialog(void)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 320 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 200 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 6 * RESFACTOR+1;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin1 = 5 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_margin2 = 2 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = 70 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);\n\tint d_name_y = d_dialog_y + d_margin1 + d_margin2 + d_txt6_h + 1*RESFACTOR;\n\n#ifdef OLDWAY\n\tint d_gdi_w = 40 * RESFACTOR;\n\tint d_gdi_h = 9 * RESFACTOR;\n\tint d_gdi_x = d_dialog_cx - d_gdi_w;\n\tint d_gdi_y = d_name_y;\n\n\tint d_nod_w = 40 * RESFACTOR;\n\tint d_nod_h = 9 * RESFACTOR;\n\tint d_nod_x = d_dialog_cx;\n\tint d_nod_y = d_name_y;\n\n#else\t//OLDWAY\n\n\tint d_house_w = 60 *RESFACTOR;\n\tint d_house_h = (8 * 5 *RESFACTOR);\n\tint d_house_x = d_dialog_cx - (d_house_w / 2);\n\tint d_house_y = d_name_y;\n\n#endif\t//OLDWAY\n\n\tint d_color_w = 10 * RESFACTOR;\n\tint d_color_h = 9 * RESFACTOR;\n\tint d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);\n\tint d_color_y = d_name_y;\n\n\tint d_scenario_y = d_name_y + d_name_h + d_margin2;\n\n\tint d_gamelist_w = 160 * RESFACTOR;\n\tint d_gamelist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\tint d_gamelist_x = d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_gamelist_y = d_scenario_y + d_txt6_h + d_margin2 + d_txt6_h + d_margin2;\n\n//BG\tint d_playerlist_w = 112 * RESFACTOR;\n\tint d_playerlist_w = 118 * RESFACTOR;\n\tint d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR;\t\t// 6 rows high\n\tint d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w - 5*RESFACTOR;\n\tint d_playerlist_y = d_gamelist_y;\n\n\tint d_count_w = 25 * RESFACTOR;\n\tint d_count_h = d_txt6_h;\n\tint d_count_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_count_y = d_gamelist_y + d_gamelist_h + (d_margin1 * 2) - d_margin2;\n\n\tint d_level_w = 25 * RESFACTOR;\n\tint d_level_h = d_txt6_h;\n\tint d_level_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_level_y = d_count_y + d_count_h;\n\n\tint d_credits_w = 25 * RESFACTOR;\n\tint d_credits_h = d_txt6_h;\n\tint d_credits_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_credits_y = d_level_y + d_level_h;\n\n\tint d_aiplayers_w = 25 * RESFACTOR;\n\tint d_aiplayers_h = d_txt6_h;\n\tint d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2);\n\tint d_aiplayers_y = d_credits_y + d_credits_h;\n\n\tint d_options_w = 112 * RESFACTOR;\n\tint d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR;\n\tint d_options_x = d_playerlist_x;\n\tint d_options_y = d_playerlist_y + d_playerlist_h + d_margin1 - d_margin2;\n\n\tint d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;\n\tint d_message_h = (7 * d_txt6_h) + 3 * RESFACTOR;\t\t// 7 rows high\n\tint d_message_x = d_gamelist_x;//d_dialog_x + d_margin1 + 10*RESFACTOR;\n\tint d_message_y = d_options_y + d_options_h + d_margin2/*KO + d_margin1*/;\n\n\tint d_send_w = d_message_w;\n\tint d_send_h = 9 * RESFACTOR;\n\tint d_send_x = d_message_x;\n\tint d_send_y = d_message_y + d_message_h;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - (d_cancel_w / 2);\n\tint d_cancel_y = d_send_y + d_send_h/*KO + d_margin2*/;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n#ifdef OLDWAY\n\t\tBUTTON_GDI,\n\t\tBUTTON_NOD,\n#else\t//OLDWAY\n\t\tBUTTON_HOUSE,\n#endif\t//OLDWAY\n\t\tBUTTON_GAMELIST,\n\t\tBUTTON_PLAYERLIST,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_COUNT,\n\t\tBUTTON_LEVEL,\n\t\tBUTTON_CREDITS,\n\t\tBUTTON_AI_PLAYERS,\n\t\tBUTTON_OPTIONS,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PARMS,\n\t\tREDRAW_MESSAGE,\n\t\tREDRAW_COLORS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tint cbox_x[] = {\n\t\t\t\t\t\t\td_color_x,\n\t\t\t\t\t\t\td_color_x + d_color_w,\n\t\t\t\t\t\t\td_color_x + (d_color_w * 2),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 3),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 4),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 5),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 6),\n\t\t\t\t\t\t\td_color_x + (d_color_w * 7)\n\t\t\t\t\t\t\t};\n\n\tchar namebuf[MPLAYER_NAME_MAX] = {0};\t\t// buffer for player's name\n//BG\tint playertabs[] = {77};\t\t\t\t// tabs for player list box\n\tint playertabs[] = {71*RESFACTOR};\t\t\t\t// tabs for player list box\n\tint optiontabs[] = {8};\t\t\t\t\t// tabs for options list box\n\tbool transmit;\t\t\t\t\t\t\t\t\t\t// 1 = re-transmit new game options\n\tbool first;\t\t\t\t\t\t\t\t\t\t\t// 1 = no packets received yet\n\tbool parms_received = false;\t\t\t\t\t// 1 = game options received\n\tbool changed = false;\t\t\t\t\t\t\t// 1 = user has changed an option\n\n\tint rc;\n\tint recsignedoff = 0;\n\tint i;\n\tunsigned long version;\n\tchar txt[80];\n\tunsigned long starttime;\n\tunsigned long timingtime;\n\tunsigned long lastmsgtime;\n\tunsigned long lastredrawtime;\n\tunsigned long transmittime = 0;\n\tint packetlen;\n\tbool oppscorescreen = false;\n\tbool gameoptions = false;\n\tEventClass *event;\t\t\t\t\t// event ptr\n\tunsigned long msg_timeout = 1200;\t// init to 20 seconds\n\tbool load_game = false;\t\t\t\t\t// 1 = load saved game\n\tNodeNameType *who;\t\t\t\t\t// node to add to Players\n\tchar *item;\t\t\t\t\t\t\t\t// for filling in lists\n\tchar *p;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tSession.Options.ScenarioDescription[0] = 0;\t//Flag that we dont know the scenario name yet\n\tbool messages_have_focus = true;\n\tbool ready_packet_was_sent = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n#ifdef OLDWAY\n\tTextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);\n\tTextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h);\n#else\t//OLDWAY\n\tchar housetext[25] = \"\";\n\tFancy_Text_Print(\"\", 0, 0, 0, 0, TPF_TEXT);\n\tDropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),\n\t\tTPF_TEXT,\n\t\td_house_x, d_house_y, d_house_w, d_house_h,\n\t\tMFCD::Retrieve(\"BTN-UP.SHP\"),\n\t\tMFCD::Retrieve(\"BTN-DN.SHP\"));\n#endif\t//OLDWAY\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);\n\tListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\tGaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);\n\tchar staticcountbuff[35];\n\tStaticButtonClass staticcount(0, \"     \", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y);\n\n\tGaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);\n\tchar staticlevelbuff[35];\n\tStaticButtonClass staticlevel(0, \"     \", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y);\n\n\tGaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);\n\tchar staticcreditsbuff[35];\n\tStaticButtonClass staticcredits(0, \"         \", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y);\n\n\tGaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);\n\tchar staticaibuff[35];\n\tStaticButtonClass staticai(0, \"     \", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y);\n\n\tCheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &name_edt;\n\tstaticcount.Add_Tail(*commands);\n\tstaticcredits.Add_Tail(*commands);\n\tstaticai.Add_Tail(*commands);\n\tstaticlevel.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tgamelist.Add_Tail(*commands);\n\tplayerlist.Add_Tail(*commands);\n\tcountgauge.Add_Tail(*commands);\n\tlevelgauge.Add_Tail(*commands);\n\tcreditsgauge.Add_Tail(*commands);\n\taiplayersgauge.Add_Tail(*commands);\n\toptionlist.Add_Tail(*commands);\n#ifdef OLDWAY\n\tgdibtn.Add_Tail(*commands);\n\tnodbtn.Add_Tail(*commands);\n#else\t//OLDWAY\n\thousebtn.Add_Tail(*commands);\n#endif\t//OLDWAY\n\n\n\t//------------------------------------------------------------------------\n\t//\tInit the button states\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Name & Color\n\t//........................................................................\n\tSession.ColorIdx = Session.PrefColor;\t\t\t// init my preferred color\n\tstrcpy (namebuf, Session.Handle);\t\t\t\t// set my name\n\tname_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);\n\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\n\t//........................................................................\n\t// List boxes\n\t//........................................................................\n\tplayerlist.Set_Tabs(playertabs);\n\tplayerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);\n\n\toptionlist.Set_Tabs(optiontabs);\n\toptionlist.Set_Read_Only(1);\n\n\toptionlist.Add_Item(Text_String(TXT_BASES));\n\toptionlist.Add_Item(Text_String(TXT_ORE_SPREADS));\n\toptionlist.Add_Item(Text_String(TXT_CRATES));\n\toptionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));\n\toptionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));\n\n\toptionlist.Check_Item(0, Session.Options.Bases);\n\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\toptionlist.Check_Item(2, Session.Options.Goodies);\n\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\n\t//........................................................................\n\t// House buttons\n\t//........................................................................\n#ifdef OLDWAY\n\tif (Session.House==HOUSE_GOOD) {\n\t\tgdibtn.Turn_On();\n\t} else {\n\t\tnodbtn.Turn_On();\n\t}\n#else\t//OLDWAY\n\tfor (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {\n\t\thousebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));\n\t}\n\thousebtn.Set_Selected_Index(Session.House - HOUSE_USSR);\n\thousebtn.Set_Read_Only (true);\n#endif\t//OLDWAY\n\n\t//........................................................................\n\t// Option gauges\n\t//........................................................................\n\tcountgauge.Use_Thumb(0);\n\tcountgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);\n\tcountgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);\n\n\tlevelgauge.Use_Thumb(0);\n\tlevelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);\n\tlevelgauge.Set_Value(BuildLevel - 1);\n\n\tcreditsgauge.Use_Thumb(0);\n\tcreditsgauge.Set_Maximum(Rule.MPMaxMoney);\n\tcreditsgauge.Set_Value(Session.Options.Credits);\n\n\taiplayersgauge.Use_Thumb(0);\n\taiplayersgauge.Set_Maximum(Rule.MaxPlayers-2);\n\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\tFancy_Text_Print(\"\", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\ttransmit = true;\n\tfirst = true;\n\n\t/*........................................................................\n\tClear the Players vector\n\t........................................................................*/\n\tClear_Vector(&Session.Players);\n\n\t/*........................................................................\n\tInit the message display system\n\t........................................................................*/\n\tSession.Messages.Init (d_message_x + 1, d_message_y + 1, 7,\n\t\tMAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 * RESFACTOR, d_send_y + 1 * RESFACTOR, 1,\n\t\t20, MAX_MESSAGE_LENGTH - 5, d_message_w);\n\tSession.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\tSession.WWChat = 0;\n\n\t/*........................................................................\n\tInit version number clipping system\n\t........................................................................*/\n\tVerNum.Init_Clipping();\n\tLoad_Title_Page(true);\n\tCCPalette.Set();\n\n\textern char ModemRXString[];\n\n\tif (strlen(ModemRXString) > 36)\n\t\tModemRXString[36] = 0;\n\n\tif (strlen(ModemRXString) > 0)\n\t\tSession.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN,\n\t\t\tTPF_TEXT, -1);\n\n\tModemRXString[0] = '\\0';\n\n\t/*\n\t---------------------------- Init Mono Output ----------------------------\n\t*/\n\t#if(SHOW_MONO)\n\tNullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),\n\t\tSerialPacketNames, 100, 8);\n\tNullModem.Mono_Debug_Print(1);\n\t#endif\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tNullModem.Reset_Response_Time();\t\t// clear response time\n\ttimingtime = lastmsgtime = lastredrawtime = TickCount;\n\n\tbool process = true;\t\t\t\t\t\t// process while true\n\twhile (process) {\n\t\t#if(SHOW_MONO)\n\t\tNullModem.Mono_Debug_Print(0);\n\t\t#endif\n\n\t\t/*\n\t\t** Kludge to make sure we redraw the message input line when it loses focus.\n\t\t** If we dont do this then the cursor doesnt disappear.\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (name_edt.Has_Focus()) {\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\tmessages_have_focus = false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tmessages_have_focus = true;\n\t\t\t\tif (display < REDRAW_MESSAGE)\tdisplay = REDRAW_MESSAGE;\n\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tif (housebtn.IsDropped) {\n\t\t\t\thousebtn.Collapse();\n\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t}\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#ifdef OLDWAY\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#else\n\t\t\t\tFancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n#endif\n\t\t\t\tFancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\tFancy_Text_Print (TXT_COUNT, d_count_x - 2 * RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_LEVEL, d_level_x - 2 * RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_CREDITS_COLON, d_credits_x - 2 * RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\t\t\t\tFancy_Text_Print (TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);\n\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the color boxes\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_COLORS) {\n\t\t\t\tfor (i = 0; i < MAX_MPLAYER_COLORS; i++) {\n\t\t\t\t\tLogicPage->Fill_Rect (cbox_x[i] + 1 * RESFACTOR, d_color_y + 1 * RESFACTOR,\n\t\t\t\t\t\tcbox_x[i] + 1 * RESFACTOR + d_color_w - 2 * RESFACTOR, d_color_y + 1 * RESFACTOR + d_color_h - 2 * RESFACTOR,\n\t\t\t\t\t\tColorRemaps[i].Box);\n//\t\t\t\t\t\t(i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);\n\n\t\t\t\t\tif (i == Session.ColorIdx) {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,\n\t\t\t\t\t\t\tBOXSTYLE_DOWN, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDraw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,\n\t\t\t\t\t\t\tBOXSTYLE_RAISED, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*..................................................................\n\t\t\tDraw the message system; erase old messages first\n\t\t\t..................................................................*/\n\t\t\tif (display >= REDRAW_MESSAGE) {\n\t\t\t\tDraw_Box(d_message_x, d_message_y, d_message_w, d_message_h,\n\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\tSession.Messages.Draw();\n\n\t\t\t//..................................................................\n\t\t\t// Redraw the game options\n\t\t\t//..................................................................\n\t\t\tif (display >= REDRAW_PARMS && parms_received) {\n\t\t\t\t\tif (oppscorescreen) {\n\t\t\t\t\t\tsprintf(txt,\"%s\",Text_String(TXT_WAITING_FOR_OPPONENT));\n\n\t\t\t\t\t\tint txtwidth = String_Pixel_Width( txt );\n\n\t\t\t\t\t\tFancy_Text_Print(txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_CENTER | TPF_TEXT);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*............................................................\n\t\t\t\t\t\tScenario description\n\t\t\t\t\t\t............................................................*/\n\t\t\t\t\t\t//LogicPage->Fill_Rect(d_dialog_x + 16*RESFACTOR, d_scenario_y,\n\t\t\t\t\t\t//\td_dialog_x + d_dialog_w - 16*RESFACTOR, d_scenario_y + d_txt6_h, BLACK);\n\n\t\t\t\t\t\tp = (char *)Text_String(TXT_SCENARIO_COLON);\n\t\t\t\t\t\tif (Session.Options.ScenarioDescription[0]) {\n//\t\t\t\t\t\t\tsprintf(txt,\"%s %s\",p, Session.Options.ScenarioDescription);\n//\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\n\t\t\t\t\t\t\t// EW - Scenario language translation goes here!!!!!!!! VG\n\t\t\t\t\t\t\tfor (i = 0; EngMisStr[i] != NULL;  i++) {\n\t\t\t\t\t\t\t\tif (!strcmp(Session.Options.ScenarioDescription, EngMisStr[i])) {\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, EngMisStr[i+1]);\n#else\n\t\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n#endif\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (EngMisStr[i] == NULL) {\n\t\t\t\t\t\t\t\tsprintf(txt, \"%s %s\", p, Session.Options.ScenarioDescription);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER);\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(txt,\"%s %s\",p,Text_String(TXT_NOT_FOUND));\n\n\t\t\t\t\t\t\tFancy_Text_Print (txt, d_dialog_cx, d_scenario_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Unit count, tech level, credits\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t//LogicPage->Fill_Rect(d_count_x + d_count_w + 2 * RESFACTOR, d_count_y,\n\t\t\t\t\t\t//\td_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR,\n\t\t\t\t\t\t//\tBLACK);\n\n\t\t\t\t\t\tsprintf(staticcountbuff, \"%d\", Session.Options.UnitCount);\n\t\t\t\t\t\tstaticcount.Set_Text(staticcountbuff);\n\t\t\t\t\t\tstaticcount.Draw_Me();\n\t\t\t\t\t\tif (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {\n\t\t\t\t\t\t\tsprintf(staticlevelbuff, \"%d \", BuildLevel);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(staticlevelbuff, \"**\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstaticlevel.Set_Text(staticlevelbuff);\n\t\t\t\t\t\tstaticlevel.Draw_Me();\n\n\t\t\t\t\t\tsprintf(staticcreditsbuff, \"%d\", Session.Options.Credits);\n\t\t\t\t\t\tstaticcredits.Set_Text(staticcreditsbuff);\n\t\t\t\t\t\tstaticcredits.Draw_Me();\n\n\t\t\t\t\t\tsprintf(staticaibuff, \"%d\", Session.Options.AIPlayers);\n\t\t\t\t\t\tstaticai.Set_Text(staticaibuff);\n\t\t\t\t\t\tstaticai.Draw_Me();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tmessages_have_focus = Session.Messages.Has_Edit_Focus();\n\t\tbool droplist_is_dropped = housebtn.IsDropped;\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t** Sort out the input focus between the name edit box and the message system\n\t\t*/\n\t\tif (messages_have_focus) {\n\t\t\tif (!name_edt.Has_Focus()) {\n\t\t\t\tSession.Messages.Set_Edit_Focus();\n\t\t\t} else {\n\t\t\t\tmessages_have_focus = false;\n\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Redraw everything if the droplist collapsed\n\t\t*/\n\t\tif (droplist_is_dropped && !housebtn.IsDropped) {\n\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser clicks on a color button\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase KN_LMOUSE:\n\t\t\t\tif (Keyboard->MouseQX > cbox_x[0] &&\n\t\t\t\t\tKeyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&\n\t\t\t\t\tKeyboard->MouseQY > d_color_y &&\n\t\t\t\t\tKeyboard->MouseQY < (d_color_y + d_color_h)) {\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tCompute my preferred color as the one I clicked on.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tSession.PrefColor = (PlayerColorType)\n\t\t\t\t\t\t\t((Keyboard->MouseQX - cbox_x[0]) / d_color_w);\n\t\t\t\t\t\tchanged = true;\n\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf 'TheirColor' is set to the other player's color, make\n\t\t\t\t\t\tsure we can't pick that color.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (parms_received) {\n\t\t\t\t\t\t\tif (Session.PrefColor == TheirColor)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSession.ColorIdx = Session.PrefColor;\n\n\t\t\t\t\t\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\tSession.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx);\n\t\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\t\t\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t\t}\n\t\t\t\t} else if ( (Get_Mouse_X() >= d_count_x &&\n\t\t\t\t\tGet_Mouse_X() <= d_count_x + d_count_w &&\n\t\t\t\t\tGet_Mouse_Y() >= d_count_y &&\n\t\t\t\t\tGet_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) ||\n\t\t\t\t\t(Get_Mouse_X() >= d_options_x &&\n\t\t\t\t\tGet_Mouse_X() <= d_options_x + d_options_w &&\n\t\t\t\t\tGet_Mouse_Y() >= d_options_y &&\n\t\t\t\t\tGet_Mouse_Y() <= d_options_y + d_options_h) ) {\n\t\t\t\t\tSession.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);\n\t\t\t\t\tSound_Effect(VOC_SYS_ERROR);\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n#ifdef OLDWAY\n\t\t\t/*------------------------------------------------------------------\n\t\t\tHouse Buttons: set the player's desired House\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_GDI | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_GOOD;\n\t\t\t\tgdibtn.Turn_On();\n\t\t\t\tnodbtn.Turn_Off();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n\n\t\t\tcase (BUTTON_NOD | KN_BUTTON):\n\t\t\t\tSession.House = HOUSE_BAD;\n\t\t\t\tgdibtn.Turn_Off();\n\t\t\t\tnodbtn.Turn_On();\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tbreak;\n#else\t//OLDWAY\n\t\t\tcase (BUTTON_HOUSE | KN_BUTTON):\n\t\t\t\tSession.House = HousesType(housebtn.Current_Index()+HOUSE_USSR);\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\t//display = REDRAW_BACKGROUND;\n\t\t\t\tbreak;\n#endif\t//OLDWAY\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUser edits the name value; retransmit\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t}\n\t\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\t\ttransmit = true;\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: send a SIGN_OFF, bail out with error code\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDefault: manage the inter-player messages\n\t\t\t------------------------------------------------------------------*/\n\t\t\tdefault:\n\t\t\t\tif (Session.Messages.Manage()) {\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t}\n\n\t\t\t\t/*...............................................................\n\t\t\t\tService keyboard input for any message being edited.\n\t\t\t\t...............................................................*/\n\t\t\t\ti = Session.Messages.Input(input);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'Input' returned 1, it means refresh the message display.\n\t\t\t\t(We have to redraw the edit line, to erase the cursor.)\n\t\t\t\t...............................................................*/\n\t\t\t\tif (i==1) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==2) {\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'Input' returned 2, it means redraw the message display.\n\t\t\t\tRather than setting 'display', which would redraw all msgs,\n\t\t\t\twe only need to erase & redraw the edit box here.\n\t\t\t\t...............................................................*/\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tDraw_Box(d_send_x, d_send_y, d_send_w, d_send_h,\n\t\t\t\t\t\tBOXSTYLE_BOX, true);\n\t\t\t\t\tSession.Messages.Draw();\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t} else if (i==3 || i==4) {\n\t\t\t\t/*...............................................................\n\t\t\t\tIf 'input' returned 3, it means send the current message.\n\t\t\t\t...............................................................*/\n\t\t\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\t\t\tSendPacket.Command = SERIAL_MESSAGE;\n\t\t\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\t\t\tSendPacket.ID = Session.ColorIdx;\n\t\t\t\t\tif (i==3) {\n\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf());\n\t\t\t\t\t\tSession.Messages.Clear_Overflow_Buf();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tSend the message\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\t\t\t\t\tNullModem.Service();\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tAdd the message to our own screen\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tSession.Messages.Add_Message (SendPacket.Name, SendPacket.ID,\n\t\t\t\t\t\tSendPacket.Message.Message,\n\t\t\t\t\t\t(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, -1);\n\t\t\t\t\tSession.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx,\n\t\t\t\t\t\tTPF_TEXT, NULL, '_', d_message_w);\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tDetect editing of the name buffer, transmit new values to players\n\t\t---------------------------------------------------------------------*/\n\t\tif (strcmp (namebuf, Session.Handle)) {\n\t\t\tstrcpy (Session.Handle, namebuf);\n\t\t\ttransmit = true;\n\t\t\tchanged = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tIf our Transmit flag is set, we need to send out a game option packet\n\t\t---------------------------------------------------------------------*/\n\t\tif (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_GAME_OPTIONS;\n\t\t\tstrcpy (SendPacket.Name, namebuf);\n\t\t\tSendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID();\n\t\t\tSendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version();\n\t\t\tSendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version();\n\t\t\tSendPacket.ScenarioInfo.House = Session.House;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\ttransmittime = TickCount;\n\t\t\ttransmit = false;\n\n\t\t\t//..................................................................\n\t\t\t// Keep the player list up to date\n\t\t\t//..................................................................\n\t\t\tif (playerlist.Count()) {\n\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef\tOLDWAY\n\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t} else {\n\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\t\t\t\tplayerlist.Flag_To_Redraw();\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// Play a little sound effect\n\t\t\t//..................................................................\n\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\t\t}\n\n\t\t//\n\t\t// send a timing packet if enough time has gone by.\n\t\t//\n\t\tif ((TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_TIMING;\n\t\t\tSendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\tSendPacket.ID = Session.ModemType;\n\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);\n\t\t\ttimingtime = TickCount;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tCheck for an incoming message\n\t\t---------------------------------------------------------------------*/\n\t\tif (NullModem.Get_Message(&ReceivePacket, &packetlen) > 0) {\n\n\t\t\tlastmsgtime = TickCount;\n\n\t\t\tmsg_timeout = 600;\n\n\t\t\t// are we getting our own packets back??\n\n\t\t\tif (ReceivePacket.Command >= SERIAL_CONNECT &&\n\t\t\t\tReceivePacket.Command < SERIAL_LAST_COMMAND &&\n\t\t\t\tReceivePacket.Command != SERIAL_MESSAGE &&\n\t\t\t\tReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\n\t\t\t\t// to skip the other system not responding msg\n\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\n\t\t\t\t// say we did receive sign off to keep from sending one\n\t\t\t\trecsignedoff = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tevent = (EventClass *)&ReceivePacket;\n\t\t\tif (event->Type <= EventClass::FRAMEINFO) {\n\t\t\t\tif ( (TickCount - lastredrawtime) > PACKET_REDRAW_TIME) {\n\t\t\t\t\tlastredrawtime = TickCount;\n\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\tparms_received = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( ReceivePacket.Command ) {\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tOther system signs off:  Give it time to receive my ACK, then show\n\t\t\t\t\ta message.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_SIGN_OFF):\n\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\twhile ( (TickCount - starttime) < 60)\n\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\tWWMessageBox().Process(TXT_USER_SIGNED_OFF);\n\n\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = false;\n\t\t\t\t\t\trecsignedoff = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGame Options: Store all options; check my color & game version.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_GAME_OPTIONS):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tgameoptions = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\n\t\t\t\t\t\tstrcpy (TheirName, ReceivePacket.Name);\n\t\t\t\t\t\tTheirColor = ReceivePacket.ScenarioInfo.Color;\n\t\t\t\t\t\tTheirHouse = ReceivePacket.ScenarioInfo.House;\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tMake sure I don't have the same color as the other guy.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tif (Session.ColorIdx == TheirColor) {\n\n\t\t\t\t\t\t\t// force transmitting of game options packet\n\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t\ttransmittime = 0;\n\n\t\t\t\t\t\t\tSession.ColorIdx = (PlayerColorType)(TheirColor + 1);\n\t\t\t\t\t\t\tif (Session.ColorIdx >= 6) {\n\t\t\t\t\t\t\t\tSession.ColorIdx = PCOLOR_FIRST;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tname_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t\tname_edt.Flag_To_Redraw();\n\t\t\t\t\t\t\tif (display < REDRAW_COLORS) display = REDRAW_COLORS;\n\t\t\t\t\t\t\tif (housebtn.IsDropped) {\n\t\t\t\t\t\t\t\thousebtn.Collapse();\n\t\t\t\t\t\t\t\tdisplay = REDRAW_BACKGROUND;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tSave scenario settings.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tSession.Options.Credits = ReceivePacket.ScenarioInfo.Credits;\n\t\t\t\t\t\tSession.Options.Bases = ReceivePacket.ScenarioInfo.IsBases;\n\t\t\t\t\t\tSession.Options.Tiberium = ReceivePacket.ScenarioInfo.IsTiberium;\n\t\t\t\t\t\tSession.Options.Goodies = ReceivePacket.ScenarioInfo.IsGoodies;\n\t\t\t\t\t\tSession.Options.AIPlayers = ReceivePacket.ScenarioInfo.AIPlayers;\n\t\t\t\t\t\tBuildLevel = ReceivePacket.ScenarioInfo.BuildLevel;\n\t\t\t\t\t\tSession.Options.UnitCount = ReceivePacket.ScenarioInfo.UnitCount;\n\t\t\t\t\t\tSeed = ReceivePacket.ScenarioInfo.Seed;\n\t\t\t\t\t\tSpecial = ReceivePacket.ScenarioInfo.Special;\n\t\t\t\t\t\tOptions.GameSpeed = ReceivePacket.ScenarioInfo.GameSpeed;\n\n\t\t\t\t\t\tif (Session.Options.Tiberium) {\n\t\t\t\t\t\t\tSpecial.IsTGrowth = true;\n\t\t\t\t\t\t\tRule.IsTGrowth = true;\n\t\t\t\t\t\t\tSpecial.IsTSpread = true;\n\t\t\t\t\t\t\tRule.IsTSpread = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSpecial.IsTGrowth = false;\n\t\t\t\t\t\t\tRule.IsTGrowth = false;\n\t\t\t\t\t\t\tSpecial.IsTSpread = false;\n\t\t\t\t\t\t\tRule.IsTSpread = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Adjust the gauges\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tcountgauge.Set_Maximum(\n\t\t\t\t\t\t\tSessionClass::CountMax[Session.Options.Bases] -\n\t\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\t\tcountgauge.Set_Value(Session.Options.UnitCount -\n\t\t\t\t\t\t\tSessionClass::CountMin[Session.Options.Bases]);\n\t\t\t\t\t\tlevelgauge.Set_Value(BuildLevel - 1);\n\t\t\t\t\t\tcreditsgauge.Set_Value(Session.Options.Credits);\n\t\t\t\t\t\taiplayersgauge.Set_Value(Session.Options.AIPlayers);\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Update the options list box\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\toptionlist.Check_Item(0, Session.Options.Bases);\n\t\t\t\t\t\toptionlist.Check_Item(1, Session.Options.Tiberium);\n\t\t\t\t\t\toptionlist.Check_Item(2, Session.Options.Goodies);\n\t\t\t\t\t\toptionlist.Check_Item(3, Special.IsCaptureTheFlag);\n\t\t\t\t\t\toptionlist.Check_Item(4, Special.IsShadowGrow);\n\t\t\t\t\t\toptionlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** If the scenario name changed then we need to redraw the whole lot.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (strcmp (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario)) {\n\t\t\t\t\t\t\tif (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*...............................................................\n\t\t\t\t\t\tCopy the information about the scenario that the host wants to\n\t\t\t\t\t\tplay so ee can request this scenario from the host if we don't\n\t\t\t\t\t\thave it locally.\n\t\t\t\t\t\t...............................................................*/\n\t\t\t\t\t\tstrcpy (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario);\n\t\t\t\t\t\tstrcpy (Session.ScenarioFileName, ReceivePacket.ScenarioInfo.ShortFileName);\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\t\tstrncpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest, sizeof( ReceivePacket.ScenarioInfo.FileDigest ));\n#else\n\t\t\t\t\t\tstrcpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest);\n#endif\n\t\t\t\t\t\tSession.ScenarioIsOfficial = ReceivePacket.ScenarioInfo.OfficialScenario;\n\t\t\t\t\t\tSession.ScenarioFileLength = ReceivePacket.ScenarioInfo.FileLength;\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// \"Clip\" the other system's version range to our own\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tversion = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion,\n\t\t\t\t\t\t\tReceivePacket.ScenarioInfo.MaxVersion);\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// If the greatest-common-version comes back 0, the other\n\t\t\t\t\t\t// system's range is too low for ours\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\tif (version == 0) {\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_DESTGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t} else if (version == 0xffffffff) {\n\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\t// If the greatest-common-version comes back 0xffffffff,\n\t\t\t\t\t\t\t// the other system's range is too high for ours\n\t\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t\tWWMessageBox().Process (TXT_YOURGAME_OUTDATED);\n\n\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\t// Otherwise, 'version' is the highest version we have in\n\t\t\t\t\t\t// common; look up the protocol that goes with this version.\n\t\t\t\t\t\t// ........................................................\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\tif (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) {\n\t\t\t\t\t\t\t\tWWMessageBox().Process(TXT_MISMATCH);\n\n\t\t\t\t\t\t\t\t// to skip the other system not responding msg\n\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\n\t\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tSession.CommProtocol = VerNum.Version_Protocol(version);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\tPlayingAgainstVersion = version;\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*.........................................................\n\t\t\t\t\t\tIf this is the first game-options packet we've received,\n\t\t\t\t\t\tinit the game & player lists, then transmit our options\n\t\t\t\t\t\tto him.\n\t\t\t\t\t\t.........................................................*/\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Add a string to the game list, and two to the player\n\t\t\t\t\t\t\t// list\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\n\t\t\t\t\t\t\tgamelist.Add_Item(item);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx]);\n\t\t\t\t\t\t\titem = new char [MPLAYER_NAME_MAX + 64];\t//Need room to display country name\n\t\t\t\t\t\t\tplayerlist.Add_Item(item,\n\t\t\t\t\t\t\t\t&ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor]);\n\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\ttransmit = true;\n\t\t\t\t\t\t\ttransmittime = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Ensure the game list & player list have the latest,\n\t\t\t\t\t\t// greatest copy of our names & colors.  Do this every time\n\t\t\t\t\t\t// we receive an options packet.\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\titem = (char *)gamelist.Get_Item(0);\n\t\t\t\t\t\tsprintf(item,Text_String(TXT_THATGUYS_GAME),\n\t\t\t\t\t\t\tTheirName);\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(0);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (Session.House==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",namebuf,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));\n\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : Session.ColorIdx];\n\n\t\t\t\t\t\titem = (char *)playerlist.Get_Item(1);\n#ifdef\tOLDWAY\n\t\t\t\t\t\tif (TheirHouse==HOUSE_GOOD) {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_ALLIES));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsprintf(item,\"%s\\t%s\",TheirName,\n\t\t\t\t\t\t\t\tText_String(TXT_SOVIET));\n\t\t\t\t\t\t}\n#else\t//OLDWAY\n\t\t\t\t\t\tsprintf (item, \"%s\\t%s\", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name()));\n#endif\t//OLDWAY\n\t\t\t\t\t\tplayerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor];\n\n\t\t\t\t\t\tgamelist.Flag_To_Redraw();\n\t\t\t\t\t\tplayerlist.Flag_To_Redraw();\n\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\t// Play a little sound effect\n\t\t\t\t\t\t//.........................................................\n\t\t\t\t\t\tSound_Effect(VOC_OPTIONS_CHANGED);\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tGO: Exit this routine with a success code.\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_LOADGAME):\n\t\t\t\t\t\tload_game = true;\n\t\t\t\t\tcase (SERIAL_GO):\n\n\t\t\t\t\t\tready_packet_was_sent = false;\n\n\t\t\t\t\t\tif (!load_game){\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Special new kludge for counterstrike.\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t** Find local scenario will fail to match a counterstrike mission\n\t\t\t\t\t\t\t** unless the CS CD is in the drive. So....\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t** If Counterstrike is installed and this is an official map and\n\t\t\t\t\t\t\t** the file name matches a counterstrike map then tell the host\n\t\t\t\t\t\t\t** that I have the scenario so he can continue while we make\n\t\t\t\t\t\t\t** sure the local user has the Counterstrike CD in the drive.\n\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t//\tThis is duplicated for Aftermath scenarios. ajw\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\tif (Session.ScenarioIsOfficial &&\n\t\t\t\t\t\t\t\t( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||\n\t\t\t\t\t\t\t\t  (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {\n#else\n\t\t\t\t\t\t\tif ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {\n#endif\n\n\t\t\t\t\t\t\t\tCCFileClass check_file ( Session.ScenarioFileName );\n\t\t\t\t\t\t\t\tif ( !check_file.Is_Available() ) {\n\n\t\t\t\t\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\t\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\t\t\t\t\tbool needcd = false;\n\t\t\t\t\t\t\t\t\tif (Is_Mission_Counterstrike(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\t\t\tif (index != 2 && index != 3) {\n\t\t\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (Is_Mission_Aftermath(Session.ScenarioFileName)) {\n\t\t\t\t\t\t\t\t\t\tif (index != 3) {\n\t\t\t\t\t\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t\t\t\t\t\t\tneedcd = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (needcd) {\n#else\n\t\t\t\t\t\t\t\t\tif ( Get_CD_Index(current_drive, 1*60) != 2 ){\n\t\t\t\t\t\t\t\t\t\tRequiredCD = 2;\n#endif\n\t#ifdef WIN32\n\t\t\t\t\t\t\t\t\t\tWWDebugString (\"RA95 - Counterstrike CD is not in drive\\n\");\n\t#endif\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** We should have the scenario but the wrong disk is in.\n\t\t\t\t\t\t\t\t\t\t** Tell the host that I am ready to go anyway.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\n\t\t\t\t\t\t\t\t\t\tstarttime = TickCount;\n\t\t\t\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tready_packet_was_sent = true;\n\n\t\t\t\t\t\t\t\t\t\tif (!Force_CD_Available (RequiredCD)){\n\t\t\t\t\t\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t\t\t\t\t\t\t\t** list.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tSession.Read_Scenario_Descriptions();\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Make sure we dont time out because of the disk swap\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** If the scenario that the host wants to play doesnt exist locally then we\n\t\t\t\t\t\t\t**\tneed to request that it is sent. If we can identify the scenario locally then\n\t\t\t\t\t\t\t**\twe need to fix up the file name so we load the right one.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (Find_Local_Scenario (Session.Options.ScenarioDescription,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileName,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioFileLength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioDigest,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSession.ScenarioIsOfficial)) {\n\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** We have the scenario. Tell the host that I am ready to go.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (!ready_packet_was_sent) {\n\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\t\t\tstarttime = TickCount;\n\n\t\t\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n#ifndef FIXIT_VERSION_3\t\t\t//\tRemoved restriction on downloading official maps.\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t** Oh dear. Thats a scenario I dont have. Request that the host sends the\n\t\t\t\t\t\t\t\t**\tscenario to me provided it isnt an official Westwood scenario.\n\t\t\t\t\t\t\t\t**\n\t\t\t\t\t\t\t\t** If the file is received OK then we will get a true return value and the\n\t\t\t\t\t\t\t\t** actual file name to load will be in Session.ScenarioFileName\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (Session.ScenarioIsOfficial) {\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t** We dont have the scenario and we dont want to request that it gets\n\t\t\t\t\t\t\t\t\t** sent because its an official one.\n\t\t\t\t\t\t\t\t\t** Print up a message saying we cant play this scenario and reply to the\n\t\t\t\t\t\t\t\t\t** host, telling him to select another.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\t\t\tSendPacket.Command = SERIAL_NO_SCENARIO;\n\t\t\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t\t\tWWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);\n\t\t\t\t\t\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else {\n#endif\n#ifdef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t\tif( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )\n\t\t\t\t\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t\t\t\t\t\tif (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 0)) {\n\t\t\t\t\t\t\t\t\t\trc = false;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t** Make sure we dont time-out because of the download\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tlastmsgtime = TickCount;\n\t\t\t\t\t\t\t\t\t}\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Make sure we respond to the host in a load game\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tmemset ((void*)&SendPacket, 0, sizeof (SendPacket));\n\t\t\t\t\t\t\tSendPacket.Command = SERIAL_READY_TO_GO;\n\t\t\t\t\t\t\tNullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1);\n\t\t\t\t\t\t\t\tstarttime = TickCount;\n\n\t\t\t\t\t\t\twhile ( ( NullModem.Num_Send()\n\t\t\t\t\t\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t\t\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t\t\t\t\tNullModem.Service();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Fall through here...\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tstrcpy (Scen.ScenarioName, Session.ScenarioFileName);\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// calculated one way delay for a packet and overall delay\n\t\t\t\t\t\t// to execute a packet\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\t\t\t\tSession.MaxAhead = max( ((((ReceivePacket.ScenarioInfo.ResponseTime / 8) +\n\t\t\t\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSession.MaxAhead = max( (ReceivePacket.ScenarioInfo.ResponseTime / 8),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  MODEM_MIN_MAX_AHEAD );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\trc = true;\n\t\t\t\t\t\tif (ReceivePacket.Command == SERIAL_LOADGAME)\n\t\t\t\t\t\t\tload_game = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/*..................................................................\n\t\t\t\t\tIncoming message: add to our list\n\t\t\t\t\t..................................................................*/\n\t\t\t\t\tcase (SERIAL_MESSAGE):\n\t\t\t\t\t\toppscorescreen = false;\n\n\t\t\t\t\t\tSession.Messages.Add_Message (ReceivePacket.Name,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tReceivePacket.Message.Message,\n\t\t\t\t\t\t\t((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID,\n\t\t\t\t\t\t\tTPF_TEXT, -1);\n\n\t\t\t\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// throw away timing packet\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_TIMING):\n\t\t\t\t\t\toppscorescreen = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t//\n\t\t\t\t\t// print msg waiting for opponent\n\t\t\t\t\t//\n\t\t\t\t\tcase (SERIAL_SCORE_SCREEN):\n\t\t\t\t\t\toppscorescreen = true;\n\t\t\t\t\t\tif (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;\n\t\t\t\t\t\tparms_received = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we haven't received a msg for 10 seconds exit\n\n\t\tif ((TickCount - lastmsgtime) > msg_timeout) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\tprocess = false;\n\t\t\trc = false;\n\n\t\t\t// say we did receive sign off to keep from sending one\n\t\t\trecsignedoff = true;\n\t\t}\n\n\t\t/*---------------------------------------------------------------------\n\t\tService the connection\n\t\t---------------------------------------------------------------------*/\n\t\tNullModem.Service();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tPrepare to load the scenario\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tSession.NumPlayers = 2;\n\n\t\t/*.....................................................................\n\t\tAdd both players to the Players vector; the local system is always\n\t\tindex 0.\n\t\t.....................................................................*/\n\t\twho = new NodeNameType;\n\n\t\t#ifdef FIXIT_MODEM_LOAD_CRASH\n\t\t/* If the names of the players are the same then we MUST force them\n\t\t * be be unique. This is necessary to prevent a crash after loading\n\t\t * a modem save game.\n\t\t */\n\t\tif (strcmp(TheirName, namebuf) == 0)\n\t\t\t{\n\t\t\tif (strlen(TheirName) == (MPLAYER_NAME_MAX - 1))\n\t\t\t\t{\n\t\t\t\tnamebuf[MPLAYER_NAME_MAX - 1] = '\\0';\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstrcat(namebuf, \"2\");\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\n\t\tstrcpy(who->Name, namebuf);\n\t\twho->Player.House = Session.House;\n\t\twho->Player.Color = Session.ColorIdx;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\twho = new NodeNameType;\n\t\tstrcpy(who->Name, TheirName);\n\t\twho->Player.House = TheirHouse;\n\t\twho->Player.Color = TheirColor;\n\t\twho->Player.ProcessTime = -1;\n\t\tSession.Players.Add (who);\n\n\t\tstarttime = TickCount;\n\t\twhile ( ( NullModem.Num_Send()\n\t\t\t&& ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) )\n\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t#if(SHOW_MONO)\n\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t#endif\n\n\t\t\tNullModem.Service();\n\t\t}\n\n\t\t// clear queue to keep from doing any resends\n\t\tNullModem.Init_Send_Queue();\n\n\t} else {\n\t\tif ( !recsignedoff ) {\n\t\t\t/*.....................................................................\n\t\t\tBroadcast my sign-off over my network\n\t\t\t.....................................................................*/\n\t\t\tmemset (&SendPacket, 0, sizeof(SerialPacketType));\n\t\t\tSendPacket.Command = SERIAL_SIGN_OFF;\n\t\t\tSendPacket.ScenarioInfo.Color = Session.ColorIdx;\t\t// use Color for ID\n\t\t\tSendPacket.ID = Session.ModemType;\n\t\t\tNullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);\n\n\t\t\tstarttime = TickCount;\n\t\t\twhile ( (NullModem.Num_Send()\n\t\t\t\t&& ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) )\n\t\t\t\t|| ((TickCount - starttime) < 60) ) {\n\t\t\t\t#if(SHOW_MONO)\n\t\t\t\tNullModem.Mono_Debug_Print(0);\n\t\t\t\t#endif\n\n\t\t\t\tif ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {\n\n\t\t\t\t\t// are we getting our own packets back??\n\n\t\t\t\t\tif (ReceivePacket.Command == SERIAL_SIGN_OFF\n\t\t\t\t\t\t&& ReceivePacket.ID == Session.ModemType) {\n\n\t\t\t\t\t\t// exit while\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tNullModem.Service();\n\t\t\t}\n\t\t}\n\n\t\tShutdown_Modem();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClean up the list boxes\n\t------------------------------------------------------------------------*/\n//\twhile (optionlist.Count()>0) {\n//\t\titem = (char *)optionlist.Get_Item(0);\n//\t\tdelete [] item;\n//\t\toptionlist.Remove_Item(item);\n//\t}\n\twhile (gamelist.Count()>0) {\n\t\titem = (char *)gamelist.Get_Item(0);\n\t\tdelete [] item;\n\t\tgamelist.Remove_Item(item);\n\t}\n\twhile (playerlist.Count()>0) {\n\t\titem = (char *)playerlist.Get_Item(0);\n\t\tdelete [] item;\n\t\tplayerlist.Remove_Item(item);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tRemove the chat edit box\n\t------------------------------------------------------------------------*/\n\tSession.Messages.Remove_Edit();\n\n\t/*------------------------------------------------------------------------\n\tRestore screen\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tLoad_Title_Page(true);\n//#ifdef WIN32\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), SysMemPage, SysMemPage, CCPalette);\n//\tSysMemPage.Scale(SeenPage);\n//#else\n//\tLoad_Uncompress(CCFileClass(\"TITLE.CPS\"), HidPage, HidPage, CCPalette);\n//\tHidPage.Blit(SeenPage);\n//#endif\n\tShow_Mouse();\n\n\t/*------------------------------------------------------------------------\n\tSave any changes made to our options\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t}\n\n\tif (load_game) {\n\t\tif (!Load_Game (-1)) {\n\t\t\tWWMessageBox().Process (TXT_ERROR_LOADING_GAME);\n\t\t\trc = false;\n\t\t}\n\t\tFrame++;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Com_Show_Scenario_Dialog */\n\n\n/***************************************************************************\n * Phone_Dialog -- Lets user edit phone directory & dial                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = dial the current phone book entry, false = cancel.\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tSerial options must have been read from CC.INI.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Phone_Dialog (void)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 280 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 160 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((200 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_phonelist_w = 248 * RESFACTOR;\n\tint d_phonelist_h = 87 * RESFACTOR;\n\tint d_phonelist_x = d_dialog_cx - (d_phonelist_w / 2);\n\tint d_phonelist_y = d_dialog_y + d_margin + d_txt6_h + 11 * RESFACTOR;\n\n\tint d_add_w = 45 * RESFACTOR;\n\tint d_add_h = 9 * RESFACTOR;\n\tint d_add_x = d_dialog_cx - (d_add_w / 2) - d_margin - d_add_w;\n\tint d_add_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_edit_w = 45 * RESFACTOR;\n\tint d_edit_h = 9 * RESFACTOR;\n\tint d_edit_x = d_dialog_cx - (d_edit_w / 2);\n\tint d_edit_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_delete_w = 45 * RESFACTOR;\n\tint d_delete_h = 9 * RESFACTOR;\n\tint d_delete_x = d_dialog_cx + (d_delete_w / 2) + d_margin;\n\tint d_delete_y = d_phonelist_y + d_phonelist_h + d_margin;\n\n\tint d_numedit_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_numedit_h = 9 * RESFACTOR;\n\tint d_numedit_x = d_dialog_cx - (d_numedit_w / 2);\n\tint d_numedit_y = d_add_y + d_add_h + d_margin;\n\n\tint d_dial_w = 45 * RESFACTOR;\n\tint d_dial_h = 9 * RESFACTOR;\n\tint d_dial_x = d_dialog_cx - (d_numedit_w / 2) - d_margin - d_dial_w;\n\tint d_dial_y = d_add_y + d_add_h + d_margin;\n\n\tint d_cancel_w = 45 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + (d_numedit_w / 2) + d_margin;\n\tint d_cancel_y = d_add_y + d_add_h + d_margin;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_PHONELIST = 100,\n\t\tBUTTON_ADD,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_DELETE,\n\t\tBUTTON_DIAL,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_NUMEDIT,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n\tKeyNumType input;\n\n\tchar phone_num[ PhoneEntryClass::PHONE_MAX_NUM ] = { 0 }; // buffer for editing phone #\n\tint rc;\n\tint i;\n\tint tabs[] = {123*RESFACTOR, 207*RESFACTOR};\t\t\t\t// tabs for list box\n\tchar *item;\t\t\t\t\t\t\t\t\t// for removing items from list box\n\tPhoneEntryClass *p_entry;\t\t\t\t// for creating / editing phonebook entries\n\tbool changed = false;\t\t\t\t\t// 1 = save changes to INI file\n\tbool firsttime = false;\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tListClass phonelist(BUTTON_PHONELIST, d_phonelist_x, d_phonelist_y, d_phonelist_w, d_phonelist_h, TPF_TEXT, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"));\n\tTextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h);\n\tTextButtonClass editbtn(BUTTON_EDIT, TXT_EDIT, TPF_BUTTON, d_edit_x, d_edit_y, d_edit_w, d_edit_h);\n\tTextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h);\n\tTextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\tEditClass numedit (BUTTON_NUMEDIT, phone_num, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, d_numedit_x, d_numedit_y, d_numedit_w, d_numedit_h, EditClass::ALPHANUMERIC);\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &phonelist;\n\taddbtn.Add_Tail(*commands);\n\teditbtn.Add_Tail(*commands);\n\tdeletebtn.Add_Tail(*commands);\n\tdialbtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\tnumedit.Add_Tail(*commands);\n\tdialbtn.Turn_On();\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tFill in the phone directory list box\n\t........................................................................*/\n\tphonelist.Set_Tabs(tabs);\n\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\n\tif (Session.CurPhoneIdx == -1) {\n\t\tfirsttime = true;\n\t}\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\twhile (process) {\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t// init font variables\n\n\t\t\t\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_CENTER | TPF_TEXT);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption (TXT_PHONE_LIST, d_dialog_x, d_dialog_y, d_dialog_w);\n\t\t\t\tphonelist.Draw_Me (true);\n\t\t\t}\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\taddbtn.Flag_To_Redraw();\n\t\t\t\teditbtn.Flag_To_Redraw();\n\t\t\t\tdeletebtn.Flag_To_Redraw();\n\t\t\t\tdialbtn.Flag_To_Redraw();\n\t\t\t\tcancelbtn.Flag_To_Redraw();\n\t\t\t\tnumedit.Flag_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tinput = commands->Input();\n\n\t\tif ( firsttime ) {\n\t\t\tnumedit.Set_Focus();\n\t\t\tnumedit.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\t/*------------------------------------------------------------------\n\t\t\tNew phone listing selected.\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_PHONELIST | KN_BUTTON):\n\t\t\t\t/*...............................................................\n\t\t\t\tDetect a change in the selected item; update CurPhoneIdx, and\n\t\t\t\tthe edit box buffer.\n\t\t\t\t...............................................................*/\n\t\t\t\t#ifdef FIXIT_PHONELIST_CRASH\n\t\t\t\tif (Session.CurPhoneIdx != -1) {\n\t\t\t\t#endif\n\t\t\t\t\tif (phonelist.Current_Index() != Session.CurPhoneIdx) {\n\t\t\t\t\t\tSession.CurPhoneIdx = phonelist.Current_Index();\n\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t#ifdef FIXIT_PHONELIST_CRASH\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tAdd a new entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_ADD | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tAllocate a new phone book entry\n\t\t\t\t...............................................................*/\n\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\tp_entry->Name[0] = 0;\n\t\t\t\tp_entry->Number[0] = 0;\n\t\t\t\tp_entry->Settings.Port = 0;\n\t\t\t\tp_entry->Settings.IRQ = -1;\n\t\t\t\tp_entry->Settings.Baud = -1;\n\t\t\t\tp_entry->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\tp_entry->Settings.InitStringIndex = 0;\n\t\t\t\tp_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t\tp_entry->Settings.CallWaitString[0] = 0;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tInvoke the entry editor; if user clicks Save, add the new entry\n\t\t\t\tto the list, and rebuild the list box.\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( Edit_Phone_Dialog( p_entry ) ) {\n\t\t\t\t\tSession.PhoneBook.Add (p_entry);\n\t\t\t\t\tBuild_Phone_Listbox( &phonelist, &numedit, phone_num );\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (p_entry == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\t\tphonelist.Set_Selected_Index( Session.CurPhoneIdx );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t} else {\n\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf the user clicked Cancel, delete the entry & keep looping.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\tdelete p_entry;\n\t\t\t\t}\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tEdit the current entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_EDIT | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDo nothing if no entry is selected.\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx==-1)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tAllocate a new entry & copy the currently-selected entry into it\n\t\t\t\t...............................................................*/\n\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\t(*p_entry) = (*Session.PhoneBook[Session.CurPhoneIdx]);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tPass the new entry to the entry editor; if the user selects OK,\n\t\t\t\tcopy the data back into our phone book.  Rebuild the list so\n\t\t\t\tthe changes show up in the list box.\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( Edit_Phone_Dialog( p_entry ) ) {\n\t\t\t\t\t(*Session.PhoneBook[Session.CurPhoneIdx]) = (*p_entry);\n\t\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (Session.PhoneBook[Session.CurPhoneIdx] == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t\tstrcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\t\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t\t\t\tphonelist.Set_Selected_Index( Session.CurPhoneIdx );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t\tdelete p_entry;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDelete the current entry\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DELETE | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDo nothing if no entry is selected.\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx == -1)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDelete the current item & rebuild the phone listbox\n\t\t\t\t...............................................................*/\n\t\t\t\tSession.PhoneBook.Delete (Session.CurPhoneIdx);\n\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\n\t\t\t\tif (Session.CurPhoneIdx == -1) {\n\t\t\t\t\t*phone_num = 0;\n\t\t\t\t\tnumedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );\n\t\t\t\t}\n\t\t\t\tchanged = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tDial the current number\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\t\tdialbtn.IsPressed = true;\n\t\t\t\tdialbtn.Draw_Me(true);\n\t\t\t\t// fall thru\n\n\t\t\tcase (BUTTON_DIAL | KN_BUTTON):\n\n\t\t\t\t/*...............................................................\n\t\t\t\tIf no item is selected, just dial the number in the phone #\n\t\t\t\tedit box:\n\t\t\t\t- Create a new phone entry\n\t\t\t\t- Copy the phone number into it\n\t\t\t\t- Set settings to defaults\n\t\t\t\t...............................................................*/\n\t\t\t\tif (Session.CurPhoneIdx == -1 ||\n\t\t\t\t\tstrcmp( Session.PhoneBook[Session.CurPhoneIdx]->Number, phone_num) ) {\n\n\t\t\t\t\tif ( strlen(phone_num) == 0) {\t// do not dial\n\t\t\t\t\t\tdialbtn.IsPressed = true;\n\t\t\t\t\t\tdialbtn.Flag_To_Redraw();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tp_entry = new PhoneEntryClass();\n\t\t\t\t\tstrcpy( p_entry->Name, \"NONAME\" );\n\t\t\t\t\tstrcpy( p_entry->Number, phone_num);\n\t\t\t\t\tp_entry->Settings.Port = 0;\n\t\t\t\t\tp_entry->Settings.IRQ = -1;\n\t\t\t\t\tp_entry->Settings.Baud = -1;\n\t\t\t\t\tp_entry->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\t\tp_entry->Settings.InitStringIndex = 0;\n\t\t\t\t\tp_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t\t\tp_entry->Settings.CallWaitString[0] = 0;\n\n\t\t\t\t\tSession.PhoneBook.Add (p_entry);\n\t\t\t\t\tBuild_Phone_Listbox(&phonelist, &numedit, phone_num);\n\t\t\t\t\t/*............................................................\n\t\t\t\t\tSet the current listbox index to the newly-added item.\n\t\t\t\t\t............................................................*/\n\t\t\t\t\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\t\t\t\t\tif (p_entry == Session.PhoneBook[i]) {\n\t\t\t\t\t\t\tSession.CurPhoneIdx = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\n\t\t\t\tprocess = false;\n\t\t\t\trc = true;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: bail out\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tSave any changes we've made to the phone list or settings\n\t------------------------------------------------------------------------*/\n\tif (changed) {\n\t\tSession.Write_MultiPlayer_Settings ();\n\t}\n\n\t/*------------------------------------------------------------------------\n\tClear the list box\n\t------------------------------------------------------------------------*/\n\twhile (phonelist.Count()) {\n\t\titem = (char *)phonelist.Get_Item(0);\n\t\tphonelist.Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\treturn(rc);\n\n}\t/* end of Phone_Dialog */\n\n\n/***************************************************************************\n * Build_Phone_Listbox -- [re]builds the phone entry listbox               *\n *                                                                         *\n * This routine rebuilds the phone list box from scratch; it also updates\t*\n * the contents of the phone # edit field.\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tlist\t\tptr to list box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tedit\t\tptr to edit box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuf\t\tptr to buffer for phone #\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf)\n{\n\tint i;\n\tchar *item;\n\tchar phonename[21];\n\tchar phonenum[15];\n\n\t/*........................................................................\n\tClear the list\n\t........................................................................*/\n\twhile (list->Count()) {\n\t\titem = (char *)(list->Get_Item(0));\n\t\tlist->Remove_Item(item);\n\t\tdelete [] item;\n\t}\n\n\t/*\n\t** Now sort the phone list by name then number\n\t*/\n\tqsort ((void *)(&Session.PhoneBook[0]), Session.PhoneBook.Count(), sizeof(class PhoneEntryClass *), Phone_Compare);\n\n\t/*........................................................................\n\tBuild the list\n\t........................................................................*/\n\tfor (i = 0; i < Session.PhoneBook.Count(); i++) {\n\t\titem = new char[80];\n\t\tif ( !(strlen( Session.PhoneBook[i]->Name )) ) {\n\t\t\tstrcpy( phonename, \" \" );\n\t\t} else {\n\t\t\tstrncpy( phonename, Session.PhoneBook[i]->Name, 20 );\n\t\t\tphonename[21] = 0;\n\t\t}\n\n\t\tif ( !(strlen( Session.PhoneBook[i]->Number )) ) {\n\t\t\tstrcpy( phonenum, \" \" );\n\t\t} else {\n\t\t\tif ( strlen( Session.PhoneBook[i]->Number ) < 14) {\n\t\t\t\tstrcpy( phonenum, Session.PhoneBook[i]->Number );\n\t\t\t} else {\n\t\t\t\tstrncpy( phonenum, Session.PhoneBook[i]->Number, 12 );\n\t\t\t\tphonenum[12] = 0;\n\t\t\t\tstrcat( phonenum, \"...\" );\n\t\t\t}\n\t\t}\n\n\t\tif (Session.PhoneBook[i]->Settings.Baud != -1) {\n\t\t\tsprintf(item,\"%s\\t%s\\t%d\", phonename, phonenum,\n\t\t\t\tSession.PhoneBook[i]->Settings.Baud);\n\t\t} else {\n\t\t\tsprintf(item,\"%s\\t%s\\t[%s]\", phonename, phonenum,\n\t\t\t\tText_String(TXT_DEFAULT));\n\t\t}\n\t\tlist->Add_Item(item);\n\t}\n\tlist->Flag_To_Redraw();\n\n\t/*........................................................................\n\tInit the current phone book index\n\t........................................................................*/\n\tif (list->Count() == 0 || Session.CurPhoneIdx < -1) {\n\t\tSession.CurPhoneIdx = -1;\n\t} else {\n\t\tif (Session.CurPhoneIdx >= list->Count() ) {\n\t\t\tSession.CurPhoneIdx = 0;\n\t\t}\n\t}\n\n\t/*........................................................................\n\tFill in phone number edit buffer\n\t........................................................................*/\n\tif (Session.CurPhoneIdx > -1) {\n\t\tstrcpy (buf, Session.PhoneBook[Session.CurPhoneIdx]->Number);\n\t\tedit->Set_Text (buf, PhoneEntryClass::PHONE_MAX_NUM );\n\t\tlist->Set_Selected_Index( Session.CurPhoneIdx );\n\t}\n}\n\n\n/***************************************************************************\n * Phone_Compare -- for qsort\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tp1,p2\t\tptrs to elements to compare\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nstatic int Phone_Compare (const void *p1, const void *p2)\n{\n\tclass PhoneEntryClass *pe1,*pe2;\n\tint result;\n\n\tpe1 = *((class PhoneEntryClass **)p1);\n\tpe2 = *((class PhoneEntryClass **)p2);\n\n\tresult = strcmp( pe1->Name, pe2->Name );\n\n\t// if strings are equal then check the phone number\n\n\tif ( !result ) {\n\t\tresult = strcmp( pe1->Number, pe2->Number );\n\t}\n\n\treturn(result);\n}\n\n\n/***************************************************************************\n * Edit_Phone_Dialog -- lets user edit a phone book entry                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tphone\t\tentry to edit\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = cancel\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   04/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Edit_Phone_Dialog (PhoneEntryClass *phone)\n{\n\t/*........................................................................\n\tDialog & button dimensions\n\t........................................................................*/\n\tint d_dialog_w = 230 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 110 * RESFACTOR;\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2);\t\t// dialog x-coord\n\tint d_dialog_y = ((136 * RESFACTOR - d_dialog_h) / 2);\t\t// dialog y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_txt6_h = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// ht of 6-pt text\n\tint d_margin = 7 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t// margin width/height\n\n\tint d_name_w = ( (PhoneEntryClass::PHONE_MAX_NAME - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_name_h = 9 * RESFACTOR;\n\tint d_name_x = d_dialog_x + (((d_dialog_w - d_name_w) * 3) / 4) - 5 * RESFACTOR;\n\tint d_name_y = d_dialog_y + 25 * RESFACTOR;\n\n\tint d_number_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) * RESFACTOR + 3 * RESFACTOR;\n\tint d_number_h = 9 * RESFACTOR;\n\tint d_number_x = d_dialog_x + (((d_dialog_w - d_number_w) * 3) / 4) - 5 * RESFACTOR;\n\tint d_number_y = d_name_y + d_name_h + d_margin;\n\n\tint d_default_w = 130 * RESFACTOR;\n\tint d_default_h = 9 * RESFACTOR;\n\tint d_default_x = d_dialog_cx - (d_default_w / 2);\n\tint d_default_y = d_number_y + d_number_h + d_margin;\n\n\tint d_custom_w = 130 * RESFACTOR;\n\tint d_custom_h = 9 * RESFACTOR;\n\tint d_custom_x = d_dialog_cx - (d_default_w / 2);\n\tint d_custom_y = d_default_y + d_default_h + d_margin;\n\n\tint d_save_w = 55 * RESFACTOR;\n\tint d_save_h = 9 * RESFACTOR;\n\tint d_save_x = d_dialog_cx - d_margin - d_save_w;\n\tint d_save_y = d_dialog_y + d_dialog_h - d_margin - d_save_h - 5*RESFACTOR;\n\n\tint d_cancel_w = 55 * RESFACTOR;\n\tint d_cancel_h = 9 * RESFACTOR;\n\tint d_cancel_x = d_dialog_cx + d_margin;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - d_margin - d_cancel_h - 5*RESFACTOR;\n\n\t/*........................................................................\n\tButton Enumerations\n\t........................................................................*/\n\tenum {\n\t\tBUTTON_NAME = 100,\n\t\tBUTTON_NUMBER,\n\t\tBUTTON_DEFAULT,\n\t\tBUTTON_CUSTOM,\n\t\tBUTTON_SAVE,\n\t\tBUTTON_CANCEL,\n\t};\n\n\t/*........................................................................\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t........................................................................*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*........................................................................\n\tDialog variables\n\t........................................................................*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\n\tchar namebuf[PhoneEntryClass::PHONE_MAX_NAME] = { 0 };\t// buffer for editing name\n\tchar numbuf[PhoneEntryClass::PHONE_MAX_NUM] = { 0 };\t\t// buffer for editing phone #\n\tint rc;\n\tSerialSettingsType settings;\n\tbool custom = false;\n\tbool firsttime = true;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\t/*........................................................................\n\tButtons\n\t........................................................................*/\n\tGadgetClass *commands;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tEditClass nameedit(BUTTON_NAME, namebuf, PhoneEntryClass::PHONE_MAX_NAME, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);\n\tEditClass numedit(BUTTON_NUMBER, numbuf, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, d_number_x, d_number_y, d_number_w, d_number_h, EditClass::ALPHANUMERIC);\n\tTextButtonClass defaultbtn(BUTTON_DEFAULT, TXT_DEFAULT_SETTINGS, TPF_BUTTON, d_default_x, d_default_y, d_default_w, d_default_h);\n\tTextButtonClass custombtn(BUTTON_CUSTOM, TXT_CUSTOM_SETTINGS, TPF_BUTTON, d_custom_x, d_custom_y, d_custom_w, d_custom_h);\n\tTextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h);\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n\n\t/*\n\t------------------------- Build the button list --------------------------\n\t*/\n\tcommands = &nameedit;\n\tnumedit.Add_Tail(*commands);\n\tdefaultbtn.Add_Tail(*commands);\n\tcustombtn.Add_Tail(*commands);\n\tsavebtn.Add_Tail(*commands);\n\tcancelbtn.Add_Tail(*commands);\n\n\t/*\n\t----------------------------- Various Inits ------------------------------\n\t*/\n\t/*........................................................................\n\tInit the settings; if the phone entry is set to use defaults, init our\n\tsettings to sensible values (in case we invoke the setting editor);\n\totherwise, copy the entry's settings.\n\t........................................................................*/\n\tif (phone->Settings.Port == 0 || phone->Settings.IRQ == -1 ||\n\t\tphone->Settings.Baud == -1) {\n\t\tsettings = Session.SerialDefaults;\n\t\tdefaultbtn.Turn_On();\n\t\tcustom = false;\n\t} else {\n\t\tsettings = phone->Settings;\n\t\tcustombtn.Turn_On();\n\t\tcustom = true;\n\t}\n\n\tstrcpy (namebuf, phone->Name);\n\tnameedit.Set_Text (namebuf, PhoneEntryClass::PHONE_MAX_NAME);\n\n\tstrcpy (numbuf, phone->Number);\n\tnumedit.Set_Text (numbuf, PhoneEntryClass::PHONE_MAX_NUM);\n\n\t/*\n\t---------------------------- Processing loop -----------------------------\n\t*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n\twhile (process) {\n\t\t/*\n\t\t........................ Invoke game callback .........................\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t...................... Refresh display if needed ......................\n\t\t*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\t/*\n\t\t\t.................. Redraw backgound & dialog box ...................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tCCPalette.Set();\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tDraw_Caption (TXT_PHONE_LISTING, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDialog & Field labels\n\t\t\t\t...............................................................*/\n\t\t\t\tFancy_Text_Print (TXT_NAME_COLON, d_name_x - 5 * RESFACTOR, d_name_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\t\t\t\tFancy_Text_Print (TXT_NUMBER_COLON, d_number_x - 5 * RESFACTOR, d_number_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT);\n\t\t\t}\n\t\t\t/*\n\t\t\t.......................... Redraw buttons ..........................\n\t\t\t*/\n\t\t\tif (display >= REDRAW_BUTTONS) {\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\t\t/*\n\t\t........................... Get user input ............................\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\tif ( firsttime ) {\n\t\t\tnameedit.Set_Focus();\n\t\t\tnameedit.Flag_To_Redraw();\n\t\t\tinput = commands->Input();\n\t\t\tfirsttime = false;\n\t\t}\n\n\t\t/*\n\t\t---------------------------- Process input ----------------------------\n\t\t*/\n\t\tswitch (input) {\n\t\t\tcase (BUTTON_NAME | KN_BUTTON):\n\t\t\t\tnumedit.Set_Focus();\n\t\t\t\tnumedit.Flag_To_Redraw();\n\t\t\t\tbreak;\n\n//\t\t\tcase (BUTTON_NUMBER | KN_BUTTON):\n//\t\t\t\tnameedit.Clear_Focus();\n//\t\t\t\tnameedit.Flag_To_Redraw();\n//\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUse Default Serial Settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_DEFAULT | KN_BUTTON):\n\t\t\t\tcustombtn.Turn_Off();\n\t\t\t\tdefaultbtn.Turn_On();\n\t\t\t\tcustom = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tUse Custom Serial Settings\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (BUTTON_CUSTOM | KN_BUTTON):\n\t\t\t\tif (Com_Settings_Dialog (&settings)) {\n\t\t\t\t\tcustombtn.Turn_On();\n\t\t\t\t\tdefaultbtn.Turn_Off();\n\t\t\t\t}\n\t\t\t\tcustom = true;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tCANCEL: bail out\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = false;\n\t\t\t\tbreak;\n\n\t\t\t/*------------------------------------------------------------------\n\t\t\tSave: save changes\n\t\t\t------------------------------------------------------------------*/\n\t\t\tcase (KN_RETURN):\n\t\t\tcase (BUTTON_SAVE | KN_BUTTON):\n\t\t\t\tprocess = false;\n\t\t\t\trc = true;\n\t\t\t\tbreak;\n\t\t}\n\n\t}\t/* end of while */\n\n\t/*------------------------------------------------------------------------\n\tIf 'Save', save all current settings\n\t------------------------------------------------------------------------*/\n\tif (rc) {\n\t\tstrcpy( phone->Name, strupr( namebuf ) );\n\n\t\t// if nothing was entered then make if NONAME\n\n\t\tif ( !(phone->Name[0]) ) {\n\t\t\tstrcpy( phone->Name, \"NONAME\" );\n\t\t}\n\n\t\tstrcpy( phone->Number, strupr( numbuf ) );\n\n\t\tif (custom) {\n\t\t\tphone->Settings = settings;\n\t\t} else {\n\t\t\tphone->Settings.Port = 0;\n\t\t\tphone->Settings.IRQ = -1;\n\t\t\tphone->Settings.Baud = -1;\n\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\tphone->Settings.InitStringIndex = 0;\n\t\t\tphone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\tphone->Settings.CallWaitString[0] = 0;\n\t\t}\n\t}\n\n\treturn(rc);\n\n\n}\t/* end of Edit_Phone_Dialog */\n\n\nstatic bool Dial_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\tbool connected = false;\n\tDialStatusType dialstatus;\n\tint modemstatus;\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\t// save for later to reconnect\n\n\tDialSettings = settings;\n\n\tmodemstatus = NullModem.Get_Modem_Status();\n\tif (reconnect) {\n\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\tconnected = true;\n\t\t\tSession.ModemService = true;\n\t\t\treturn( connected );\n\t\t}\n\t} else if ( (modemstatus & CD_SET) ) {\n\t\tNullModem.Hangup_Modem();\n\t\tSession.ModemService = false;\n\t}\n\n\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\n\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\tif ( !modemstatus ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n//#ifndef WIN32\n\t\t/*\n\t\t** If our first attempt to detect the modem failed, and we're at\n\t\t** 14400 or 28800, bump up to the next baud rate & try again.\n\t\t*/\n\t\tswitch (settings->Baud) {\n\t\t\tcase 14400:\n\t\t\t\tsettings->Baud = 19200;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 28800:\n\t\t\t\tsettings->Baud = 38400;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\tSession.ModemService = true;\n\t\t\t\treturn( connected );\n\n\t\t}\n//#else\t//WIN32\n//\t\tSession.ModemService = true;\n//\t\treturn( connected );\n//#endif\t//WIN32\n\n\n\t} else if ( modemstatus == -1 ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n\t\tWWMessageBox().Process( TXT_ERROR_IN_INITSTRING );\n//\t\tWWMessageBox().Process( \"Error in the InitString.\" );\n\t\tSession.ModemService = true;\n\t\treturn( connected );\n\t}\n\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\n\t/*\n\t** Completely disable audio. This is required for MWave devices like those\n\t** found in the IBM Aptiva.\n\t*/\n\tThemeType old_theme = THEME_NONE;\n\tif (SoundOn){\n\t\told_theme = Theme.What_Is_Playing();\n\t\tTheme.Stop();\n\t\tCountDownTimerClass wait;\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSound_End();\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSoundOn = 0;\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tdialstatus = NullModem.Dial_Modem( DialString, settings->DialMethod, reconnect );\n\n\tif (reconnect) {\n\t\t/*\n\t\t--------------------------- Redraw the display ---------------------------\n\t\t*/\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n\n\tswitch ( dialstatus ) {\n\t\tcase DIAL_CONNECTED:\n\t\t\tconnected = true;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_CARRIER:\n\t\t\tWWMessageBox().Process(TXT_NO_CARRIER);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_BUSY:\n\t\t\tWWMessageBox().Process(TXT_LINE_BUSY);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_ERROR:\n\t\t\tWWMessageBox().Process(TXT_NUMBER_INVALID);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_DIAL_TONE:\n\t\t\tWWMessageBox().Process(TXT_NO_DIAL_TONE);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_CANCELED:\n\t\t\tNullModem.Hangup_Modem();\n\t\t\tSession.ModemService = false;\n\t\t\tWWMessageBox().Process(TXT_DIALING_CANCELED);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\t}\n\n\tNullModem.Remove_Modem_Echo();\n\tNullModem.Print_EchoBuf();\n\tNullModem.Reset_EchoBuf();\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Restore audio capability\n\t*/\n\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n\tif (SoundOn){\n\t\tTheme.Play_Song (old_theme);\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tSession.ModemService = true;\n\treturn( connected );\n\n}\t/* end of Dial_Modem */\n\n\nstatic bool Answer_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\tbool connected = false;\n\tDialStatusType dialstatus;\n\tint modemstatus;\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\t// save for later to reconnect\n\n\tDialSettings = settings;\n\n\tmodemstatus = NullModem.Get_Modem_Status();\n\tif (reconnect) {\n\t\tif ( (modemstatus & CD_SET) ) {\n\t\t\tconnected = true;\n\t\t\tSession.ModemService = true;\n\t\t\treturn( connected );\n\t\t}\n\t} else if ( (modemstatus & CD_SET) ) {\n\t\tNullModem.Hangup_Modem();\n\t\tSession.ModemService = false;\n\t}\n\n\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\n\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\tif ( !modemstatus ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n//#ifndef WIN32\n\t\t/*\n\t\t** If our first attempt to detect the modem failed, and we're at\n\t\t** 14400 or 28800, bump up to the next baud rate & try again.\n\t\t*/\n\t\tswitch (settings->Baud) {\n\t\t\tcase 14400:\n\t\t\t\tsettings->Baud = 19200;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 28800:\n\t\t\t\tsettings->Baud = 38400;\n\t\t\t\tShutdown_Modem();\n\t\t\t\tInit_Null_Modem(settings);\n\t\t\t\tNullModem.Setup_Modem_Echo( Modem_Echo );\n\t\t\t\tmodemstatus = NullModem.Detect_Modem( settings, reconnect );\n\t\t\t\tif ( !modemstatus ) {\n\t\t\t\t\tNullModem.Remove_Modem_Echo();\n\t\t\t\t\tNullModem.Print_EchoBuf();\n\t\t\t\t\tNullModem.Reset_EchoBuf();\n\t\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\t\tSession.ModemService = true;\n\t\t\t\t\treturn( connected );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tWWMessageBox().Process( TXT_UNABLE_FIND_MODEM );\n\t\t\t\tSession.ModemService = true;\n\t\t\t\treturn( connected );\n\n\t\t}\n//#else\t//WIN32\n//\t\tSession.ModemService = true;\n//\t\treturn( connected );\n//#endif\t//WIN32\n\t} else if ( modemstatus == -1 ) {\n\t\tNullModem.Remove_Modem_Echo();\n\t\tNullModem.Print_EchoBuf();\n\t\tNullModem.Reset_EchoBuf();\n\t\tWWMessageBox().Process( TXT_ERROR_IN_INITSTRING );\n\t\tSession.ModemService = true;\n\t\treturn( connected );\n\t}\n\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Completely disable audio. This is required for some MWave devices like those\n\t** found in the IBM Aptiva.\n\t*/\n\tThemeType old_theme = THEME_NONE;\n\tif (SoundOn){\n\t\told_theme = Theme.What_Is_Playing();\n\t\tTheme.Stop();\n\t\tCountDownTimerClass wait;\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSound_End();\n\t\tCall_Back();\n\t\twait.Set (60,true);\n\t\twhile ( wait.Time() ) {\n\t\t\tCall_Back();\n\t\t}\n\t\tSoundOn = 0;\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tdialstatus = NullModem.Answer_Modem( reconnect );\n\n\tswitch ( dialstatus ) {\n\t\tcase DIAL_CONNECTED:\n\t\t\tconnected = true;\n\t\t\tbreak;\n\n\t\tcase DIAL_NO_CARRIER:\n\t\t\tWWMessageBox().Process(TXT_NO_CARRIER);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n//\t\tcase DIAL_BUSY:\n//\t\t\tWWMessageBox().Process(TXT_LINE_BUSY);\n//\t\t\tconnected = false;\n//\t\t\tbreak;\n\n\t\tcase DIAL_ERROR:\n\t\t\tWWMessageBox().Process(TXT_NUMBER_INVALID);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\n\t\tcase DIAL_CANCELED:\n\t\t\tWWMessageBox().Process(TXT_ANSWERING_CANCELED);\n\t\t\tconnected = false;\n\t\t\tbreak;\n\t}\n\n\tNullModem.Remove_Modem_Echo();\n\tNullModem.Print_EchoBuf();\n\tNullModem.Reset_EchoBuf();\n\n#ifdef WIN32\n#ifdef FIXIT_APTIVA_MODEM\n\t/*\n\t** Restore audio capability\n\t*/\n\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n\tif (SoundOn){\n\t\tTheme.Play_Song (old_theme);\n\t}\n#endif\t//FIXIT_APTIVA_MODEM\n#endif\t//WIN32\n\n\tSession.ModemService = true;\n\treturn( connected );\n\n}\t/* end of Answer_Modem */\n\n\nstatic void Modem_Echo( char c )\n{\n\tif (NullModem.EchoCount < (NullModem.EchoSize - 1) ) {\n\t\t*(NullModem.EchoBuf + NullModem.EchoCount) = c;\n\t\t*(NullModem.EchoBuf + NullModem.EchoCount + 1) = 0;\n\t\tNullModem.EchoCount++;\n\t}\n\n}\t/* end of Modem_Echo */\n\n\nvoid Smart_Printf( char *format, ... )\n{\n\tva_list arglist;\n\tchar buf[501];\n\n\n\tva_start(arglist,format);\n\tvsprintf(buf,format,arglist);\n\tva_end(arglist);\n\n\tif (Debug_Smart_Print) {\n\t\tif (MonoClass::Is_Enabled()) {\n\t\t\tMono_Printf(\"%s\",buf);\n\t\t} else {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t} else {\n\t\tif (Debug_Heap_Dump) {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t\tif (Debug_Modem_Dump) {\n\t\t\tprintf(\"%s\",buf);\n\t\t}\n\t}\n}\n\n\nvoid Hex_Dump_Data( char *buffer, int length )\n{\n\tint i;\n\tint offset = 0;\n\tchar buff[10];\n\tchar ptr[16];\n\tchar c;\n\n\n\twhile (length >= 16) {\n\t\tmemcpy( ptr, (buffer + offset), 16);\n\n\t\tSmart_Printf(\"%05lX  \", offset);\n\n\t\tfor (i = 0; i < 16; i++) {\n\n\t\t\tc = ptr[i];\n\t\t\titoh(c, buff);\n\n\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\tSmart_Printf(\" \");\n\t\t\t}\n\n\t\t\tSmart_Printf(\"%s \", buff);\n\t\t}\n\n\t\tSmart_Printf(\"  \");\n\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tc = ptr[i];\n\n\t\t\tif (c && ((c < 7) || (c > 11)) && (c != 13)) {\n\t\t\t\tSmart_Printf(\"%c\", c);\n\t\t\t} else {\n\t\t\t\tSmart_Printf(\".\");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"\\n\");\n\n\t\toffset += 16;\n\t\tlength -= 16;\n\t}\n\n\tif (length) {\n\t\tmemcpy( ptr, (buffer + offset), 16);\n\n\t\tSmart_Printf(\"%05lX  \", offset);\n\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tif (i < length) {\n\t\t\t\tc = ptr[i];\n\t\t\t\titoh(c, buff);\n\t\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\t\tSmart_Printf(\" \");\n\t\t\t\t}\n\t\t\t\tSmart_Printf(\"%s \", buff);\n\t\t\t} else {\n\t\t\t\tif (!(i & 0x3) && i) {\n\t\t\t\t\tSmart_Printf(\"  \");\n\t\t\t\t}\n\t\t\t\tSmart_Printf(\"   \");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"  \");\n\n\t\tfor (i = 0; i < length; i++) {\n\n\t\t\tc = ptr[i];\n\n\t\t\tif (c && ((c < 7) || (c > 11)) && (c != 13)) {\n\t\t\t\tSmart_Printf(\"%c\", c);\n\t\t\t} else {\n\t\t\t\tSmart_Printf(\".\");\n\t\t\t}\n\t\t}\n\n\t\tSmart_Printf(\"\\n\");\n\t}\n\n}\t/* end of Hex_Dump_Data */\n\n\nvoid itoh( int i, char *s)\n{\n\n\tint nibble, loop;\n\n//\t*s++ = '0';\n//\t*s++ = 'x';\n\n\tif (i == 0) {\n\t\t*s++ = '0';\n\t\t*s++ = '0';\n\t} else {\n\t\tfor (loop = 1; loop >= 0; loop--) {\n\t\t\tnibble = (i >> (loop << 2)) & 0x000F;\n\n\t\t\t/* decimal range */\n\t\t\tif (nibble < 10) {\n\t\t\t\t*s++ = '0' + nibble;\n\t\t\t} else {\n\t\t\t\t*s++ = 'A' + (nibble - 10);\n\t\t\t}\n\t\t}\n\t}\n\t*s = 0;\t\t\t\t\t\t\t/* null terminate it */\n}\n\nvoid Log_Start_Time( char *string )\n{\n//\tLogDump_Print = true;\n\n\tLogLevel = 0;\n\tLogLevelTime[ LogLevel ] = LogLastTime = TickCount;\n\n\tSmart_Printf( \"start tick=%d, %s \\n\", LogLastTime, string );\n}\n\n\nvoid Log_End_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\twhile (LogLevel >= 0) {\n\t\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t\t//\n\t\t\t// put one space for each level as indenting\n\t\t\t//\n\t\t\ti = 0;\n\t\t\twhile (i++ < LogLevel) {\n\t\t\t\tSmart_Printf( \" \" );\n\t\t\t}\n\t\t} else {\n\t\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t\t}\n\n\t\tticks = currtime - LogLevelTime[ LogLevel-- ];\n\t\tSmart_Printf( \"end tick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\t}\n\n\tLogDump_Print = false;\n}\n\n\nvoid Log_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLastTime;\n\n\tSmart_Printf( \"tick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tLogLastTime = currtime;\n}\n\n\nvoid Log_Start_Nest_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLastTime;\n\tSmart_Printf( \"start ntick=%d, ticks=%d, tsecs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tif (LogLevel >= (MAX_LOG_LEVEL - 1) ) {\n\t\tSmart_Printf( \"Could not start another nesting Maxed at %d,%d!-! \\n\",\n\t\t\tLogLevel, (MAX_LOG_LEVEL - 1) );\n\t} else {\n\t\tLogLevelTime[ ++LogLevel ] = currtime;\n\t}\n\n\tLogLastTime = currtime;\n}\n\n\nvoid Log_End_Nest_Time( char *string )\n{\n\tint i;\n\tunsigned long currtime;\n\tunsigned long ticks;\n\n\n\tcurrtime = TickCount;\n\n\tif (LogLevel <= 0) {\n\t\tSmart_Printf( \"Could not end another nesting Mined at %d,%d!-! \\n\",\n\t\t\tLogLevel, 0 );\n\t\tLogLevel = 0;\n\t}\n\n\tif (LogLevel < MAX_LOG_LEVEL) {\n\t\t//\n\t\t// put one space for each level as indenting\n\t\t//\n\t\ti = 0;\n\t\twhile (i++ < LogLevel) {\n\t\t\tSmart_Printf( \" \" );\n\t\t}\n\t} else {\n\t\tSmart_Printf( \"LogLevel %d too large!-! \\n\", LogLevel);\n\t\tLogLevel = MAX_LOG_LEVEL - 1;\n\t}\n\n\tticks = currtime - LogLevelTime[ LogLevel ];\n\tSmart_Printf( \"end ntick=%d, ticks=%d, secs=%d, %s \\n\",\n\t\tcurrtime, ticks, ((ticks * 10) / 60), string );\n\n\tif (LogLevel) {\n\t\tLogLevel--;\n\t}\n\n\tLogLastTime = currtime;\n}\n\n#endif"
  },
  {
    "path": "REDALERT/NULLMGR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/NULLMGR.CPP 2     3/07/97 6:40p Steve_tall $ */\n/***************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : NULLMGR.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : April 5, 1995       \t \t\t\t\t\t\t*\n *                                                                         *\n *                  Last Update : May 1, 1995 [BRR]                        *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   NullModemClass::NullModemClass -- class constructor                   *\n *   NullModemClass::~NullModemClass -- class destructor                   *\n *   NullModemClass::Init -- initialization\t\t\t\t\t\t\t\t\t\t\t*\n *   NullModemClass::Send_Message -- sends a message\t\t\t\t\t\t\t\t*\n *   NullModemClass::Get_Message -- polls the Queue for a message\t\t\t\t*\n *   NullModemClass::Service -- main polling routine\t\t\t\t\t\t\t\t*\n *   NullModemClass::Num_Send -- Returns # of unACK'd send entries\t\t\t*\n *   NullModemClass::Num_Receive -- Returns # entries in the receive queue *\n *   NullModemClass::Response_Time -- Returns Queue's avg response time    *\n *   NullModemClass::Reset_Response_Time -- Resets response time computatio*\n *   NullModemClass::Oldest_Send -- Returns ptr to oldest unACK'd send buf *\n *   NullModemClass::Detect_Modem -- Detects and initializes the modem     *\n *   NullModemClass::Dial_Modem -- dials a number passed                   *\n *   NullModemClass::Answer_Modem -- waits for call and answers            *\n *   NullModemClass::Hangup_Modem -- hangs up the modem                    *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0)//PG\n#include \"function.h\"\n#ifdef WIN32\n#include \"wincomm.h\"\n#include \"modemreg.h\"\nextern ModemRegistryEntryClass *ModemRegistry;\n#endif\t//WIN32\n#include \"i86.h\"\n\n\n// Turn off \"expression is not meaningful\".\n#pragma warning 628 9\n\n\n// the following line was taken from Greenleaf's <ibmkeys.h> <asciidef.h>\n// because of other define conflicts\n\n#define ESC\t\t         27\n#define NOKEY           0xffff\n#define INIT_COMMAND_RETRIES\t2\n\n// this time is in milliseconds\n\n#define DEFAULT_TIMEOUT\t\t\t1500\n\n//\n// the following is for a fix around a greenleaf bug\n// where they do not check for the value of abortkey\n// to determine whether or not they call the abort modem function.\n//\nextern \"C\" {\n\textern void (*_AbortModemFunctionPtr)(int);\n}\n\nstatic void (*NullModemClass::OrigAbortModemFunc)(int);\n\nstatic KeyNumType NullModemClass::Input;\nstatic GadgetClass *NullModemClass::Commands;\t\t// button list\n\n/*\n** Ugly hack: this string stores the string received from the modem\n*/\nchar ModemRXString[80];\n\n\n/***************************************************************************\n * NullModemClass::NullModemClass -- class constructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\t# desired entries for the send queue\t\t\t\t\t\t*\n *\t\tnumreceive\t\t# desired entries for the receive queue\t\t\t\t\t*\n *\t\tmaxlen\t\t\tapplication's max packet length\t\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tapplication-specific magic # (so we don't \t\t\t\t*\n *\t\t\t\t\t\t\taccidentally end up talking to another one of our own\t*\n *\t\t\t\t\t\t\tproducts using the same protocol)\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemClass::NullModemClass (int numsend, int numreceive, int maxlen,\n\tunsigned short magicnum) : ConnManClass()\n{\n\t/*------------------------------------------------------------------------\n\tInit Port to NULL; we haven't opened Greenleaf yet.\n\t------------------------------------------------------------------------*/\n#ifdef WIN32\n\tPortHandle = NULL;\n#else\t//WIN32\n\tPort = NULL;\n#endif\t//WIN32\n\n\tConnection = NULL;\n\n\tNumSend = numsend;\n\tNumReceive = numreceive;\n\tMaxLen = maxlen;\n\tMagicNum = magicnum;\n\n\tRXBuf = 0;\n\tBuildBuf = 0;\n\n\tEchoSize = 500;\n\tEchoBuf = 0;\n\n\tOldIRQPri = -1;\n\n\tModemVerboseOn = false;\t\t\t\t\t// default true\n\tModemEchoOn = false;\t\t\t\t\t\t// default true\n\tModemWaitCarrier = 50000;\t\t\t\t// default 50 * 1000ms = 50 secs\n\tModemCarrierDetect = 600;\t\t\t\t// default 6  * 100ms  = .6 secs\n\tModemCarrierLoss = 1400;\t\t\t\t// default 14 * 100ms  = 1.4 secs\n\tModemHangupDelay = 20000;\t\t\t\t// default 20 * 1000ms = 20 secs\n\tModemGuardTime = 1000;\t\t\t\t\t// default 50 * 20ms   = 1 sec\n\tModemEscapeCode = '+';\t\t\t\t\t// default ASCII 43\n\n\tSendOverflows = 0;\n\tReceiveOverflows = 0;\n\tCRCErrors = 0;\n\n\tNumConnections = 0;\n\n\t/*------------------------------------------------------------------------\n\tInit timing parameters\n\t------------------------------------------------------------------------*/\n\tRetryDelta = 60;\t\t// 60 ticks between retries\n\tMaxRetries = -1;\t\t// disregard # retries\n\tTimeout = 1200;\t\t// report bad connection after 20 seconds\n\n}\t/* end of NullModemClass */\n\n\n/***************************************************************************\n * NullModemClass::~NullModemClass -- class destructor                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nNullModemClass::~NullModemClass ()\n{\n\tDelete_Connection();\n\n}\t/* end of ~NullModemClass */\n\n\n/***************************************************************************\n * NullModemClass::Init -- initialization\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tport\t\t\t\taddress  \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tirq\t\t\t\t2-15     \t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *     dev_name\t\t\tname of communications device (win32 only)           *\n *\t\tbaud\t\t\t\t300, 1200, 9600, etc\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tparity\t\t\t'O' (odd), 'E' (even), 'N' (none), 'S' (space),\t\t  *\n *\t\t\t\t\t\t\t'M' (mark)\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\twordlength\t\t5, 6, 7, or 8\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tstopbits\t\t\t1 or 2\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *   10/9/1996  ST : Modified to take device name in win32                 *\n *=========================================================================*/\nint NullModemClass::Init (int port, int irq, char *dev_name, int baud, char parity, int wordlen, int stopbits, int flowcontrol)\n{\n\tint com;\n\n#ifdef WIN32\n\n\t/*\n\t** Get rid of the 'no reference to' warning\n\t*/\n\tirq = irq;\n\n\t/*\n\t** Make sure the port is closed before we start\n\t*/\n\tif (PortHandle) {\n\t\tCloseHandle (PortHandle);\n\t\tPortHandle = NULL;\n\t}\n\n\tif (!Connection) {\n\n#else\t//WIN32\n\n\tint irqnum;\n\tint address;\n\tint status;\n\n\t/*\n\t** Get rid of the 'no reference to' warning\n\t*/\n\tdev_name = dev_name;\n\n\tif (Port) {\n\t\tPortClose(Port);\n\t\tPort = NULL;\n\t}else {\n\n#endif\t//WIN32\n\n\t/*------------------------------------------------------------------------\n\tInit our Connection\n\t------------------------------------------------------------------------*/\n\t\tConnection = new NullModemConnClass (NumSend, NumReceive, MaxLen,\n\t\t\tMagicNum);\n\n\t\tConnection->Set_Retry_Delta (RetryDelta);\n\t\tConnection->Set_Max_Retries (MaxRetries);\n\t\tConnection->Set_TimeOut (Timeout);\n\n\t\t/*---------------------------------------------------------------------\n\t\tAllocate our packet parsing buffer; make it the same # of packets as the\n\t\t# of receive queue entries the application has requested.  Use the\n\t\t\"Actual\" maximum packet size, given from the connection; this allows for\n\t\tboth headers that get added to the packet.\n\t\t---------------------------------------------------------------------*/\n\t\tRXSize = Connection->Actual_Max_Packet() * NumReceive;\n\t\tRXBuf = new char [RXSize];\n\n\t\tBuildBuf = new char [MaxLen];\n\n\t\tEchoBuf = new char [ EchoSize ];\n\t}\n\n\tRXCount = 0;\n\tEchoCount = 0;\n\n\n\t/*------------------------------------------------------------------------\n\tThis call allocates all necessary queue buffers\n\t------------------------------------------------------------------------*/\n\tswitch (port) {\n\t\tcase 0x3f8:\n\t\t\tcom = COM1;\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tcom = COM2;\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tcom = COM3;\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tcom = COM4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcom = COM5;\n\t\t\tbreak;\n\t}\n\n#ifdef WIN32\n\tint\ti;\n\n\t/*\n\t** Create a new modem class for our com port\n\t*/\n\tif (!SerialPort) {\n\t\tSerialPort = new WinModemClass;\n\t}\n\n\t/*\n\t** Shift up the baud rate to sensible values\n\t*/\n//\tif (baud == 14400) baud = 19200;\n//\tif (baud == 28800) baud = 38400;\n\n\tstatic char com_ids[9][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\",\n\t\t\"COM9\"\n\t};\n\n\tchar *device;\n\n\tswitch ( port ) {\n\n\t\tcase 0x3f8:\n\t\t\tdevice = com_ids[0];\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tdevice = com_ids[1];\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tdevice = com_ids[2];\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tdevice = com_ids[3];\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\t/*\n\t\t\t** 1 is a special value. It means use the device name not the port address.\n\t\t\t*/\n\t\t\tdevice = dev_name;\n\n\t\t\t/*\n\t\t\t** If we can match a registry entry with the device name then use that, otherwise use\n\t\t\t** the device name directly to open the port with.\n\t\t\t*/\n\t\t\tif (ModemRegistry){\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tfor ( i=0 ; i<10 ; i++ ){\n\t\t\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\t\t\tif (ModemRegistry->Get_Modem_Name()){\n\t\t\t\t\tif (!strcmp (dev_name, ModemRegistry->Get_Modem_Name() )){\n\t\t\t\t\t\tdevice = ModemRegistry->Get_Modem_Device_Name();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tdevice = NULL;\n\t}\n\n\n\n\t/*\n\t** Open the com port\n\t*/\n\tPortHandle = SerialPort->Serial_Port_Open (device, baud, parity, wordlen, stopbits, flowcontrol);\n\tif (PortHandle == INVALID_HANDLE_VALUE) {\n\t\tShutdown();\n\t\treturn(false);\n\t}\n\n\tConnection->Init (PortHandle);\n\n#else\t//WIN32\n\n\tstatus = FastGetPortHardware( com, &irqnum, &address );\n\tif (status == ASSUCCESS) {\n\t\tif (port != address || irq != irqnum) {\n\n\t\t\tstatus = FastSetPortHardware( com, irq, port );\n\n\t\t\tif (status < ASSUCCESS) {\n\t\t\t\tMono_Printf( \"Unable to set Com port status %d\\n\", status );\n\t\t\t\tMono_Printf( \"Com port number %d with address %x, irq %d\\n\",\n\t\t\t\t\tcom + 1, port, irq );\n\t\t\t} else {\n\t\t\t\tMono_Printf( \"Changed Com port number %d to address %x, irq %d\\n\",\n\t\t\t\t\tcom + 1, port, irq );\n\t\t\t}\n\t\t} else {\n\t\t\tMono_Printf( \"No changes to Com port number %d with address %x, irq %d\\n\",\n\t\t\t\tcom + 1, port, irq );\n\t\t}\n\t} else {\n\t\tMono_Printf( \"Com port number %d\\n\", com + 1 );\n\t}\n\n\tif (status != ASSUCCESS) {\n\t\tDelete_Connection();\n\t\treturn(false);\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Greenleaf port\n\t------------------------------------------------------------------------*/\n\tPort = PortOpenGreenleafFast (com, baud, parity, wordlen, stopbits);\n\n\tif (Port->status != ASSUCCESS) {\n\t\tShutdown();\n\t\treturn(false);\n\t}\n\n//\tUseRtsCts( Port, 1 );\t\t\t// use RTS CTS hardware flow control\n\n\t/*------------------------------------------------------------------------\n\tInit the Connection\n\t------------------------------------------------------------------------*/\n\tConnection->Init(Port);\n\t//because Watcom is so stupid\n\tflowcontrol = flowcontrol;\n\n#endif\t//WIN32\n\n\tNumConnections = 1;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * NMC::Num_Connections -- returns NumConnections member                                       *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   NumConnections                                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:44AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Num_Connections( void )\n{\n\treturn(NumConnections);\n}\n\n\n/***********************************************************************************************\n * NMC::Delete_Connection -- removes the connection                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:44AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Delete_Connection( void )\n{\n\tif (Connection) {\n\t\tdelete Connection;\n\t\tConnection = NULL;\n\t}\n\n\tif (RXBuf) {\n\t\tdelete [] RXBuf;\n\t\tRXBuf = NULL;\n\t}\n\n\tif (BuildBuf) {\n\t\tdelete [] BuildBuf;\n\t\tBuildBuf = NULL;\n\t}\n\n\tif (EchoBuf) {\n\t\tdelete [] EchoBuf;\n\t\tEchoBuf = NULL;\n\t}\n\n\tNumConnections = 0;\n\n\treturn( true );\n}\t/* end of Delete_Connection */\n\n\n\n/***********************************************************************************************\n * NMC::Init_Send_Queue -- Initialises the connections send queue                              *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   true                                                                              *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:46AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nint NullModemClass::Init_Send_Queue( void )\n{\n\n\t/*------------------------------------------------------------------------\n\tInit the send queue\n\t------------------------------------------------------------------------*/\n\tif ( Connection ) {\n\t\tConnection->Queue->Init_Send_Queue();\n\t}\n\n\treturn(true);\n}\n\n\n\n/***********************************************************************************************\n * NMC::Detect_Port -- Checks that the specified com port exists                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to SerialSettingsType                                                         *\n *                                                                                             *\n * OUTPUT:   true if port is valid                                                             *\n *                                                                                             *\n * WARNINGS: Win32 version always returns true as win95 shouldnt allow us to open the          *\n *           port if it doesnt exist or is in use by the mouse                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:47AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nDetectPortType NullModemClass::Detect_Port( SerialSettingsType *settings )\n{\n\n#ifdef WIN32\n\n\tstatic char com_ids[9][5]={\n\t\t\"COM1\",\n\t\t\"COM2\",\n\t\t\"COM3\",\n\t\t\"COM4\",\n\t\t\"COM5\",\n\t\t\"COM6\",\n\t\t\"COM7\",\n\t\t\"COM8\",\n\t\t\"COM9\"\n\t};\n\n\tint\ti;\n\n\t/*\n\t** Create a new modem class for our com port\n\t*/\n\tif (!SerialPort) {\n\t\tSerialPort = new WinModemClass;\n\t}else{\n\t\tSerialPort->Serial_Port_Close();\n\t}\n\n\t/*\n\t** Shift up the baud rate to sensible values\n\t*/\n\tint baud = settings->Baud;\n//\tif (baud == 14400) baud = 19200;\n//\tif (baud == 28800) baud = 38400;\n\n\n\t/*\n\t** Translate the port address into a usable device name\n\t*/\n\tchar *device;\n\n\tswitch ( settings->Port ) {\n\n\t\tcase 0x3f8:\n\t\t\tdevice = com_ids[0];\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tdevice = com_ids[1];\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tdevice = com_ids[2];\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tdevice = com_ids[3];\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\t/*\n\t\t\t** 1 is a special value. It means use the device name not the port address.\n\t\t\t*/\n\t\t\tdevice = settings->ModemName;\n\n\t\t\t/*\n\t\t\t** If we can match a registry entry with the device name then use that, otherwise use\n\t\t\t** the device name directly to open the port with.\n\t\t\t*/\n\t\t\tif (ModemRegistry){\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tfor ( i=0 ; i<10 ; i++){\n\t\t\t\tModemRegistry = new ModemRegistryEntryClass (i);\n\t\t\t\tif (ModemRegistry->Get_Modem_Name()){\n\t\t\t\t\tif (!strcmp (device, ModemRegistry->Get_Modem_Name() )){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Got a match. Break out leaving the registry info intact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tdevice = ModemRegistry->Get_Modem_Device_Name();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete ModemRegistry;\n\t\t\t\tModemRegistry = NULL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn (PORT_INVALID);\n\t}\n\n\t/*\n\t** Open the com port\n\t*/\n\tHANDLE porthandle = SerialPort->Serial_Port_Open (device, baud, 0, 8, 1, settings->HardwareFlowControl);\n\n\tif (porthandle == INVALID_HANDLE_VALUE){\n\t\treturn (PORT_INVALID);\n\t}\n\n\tSerialPort->Serial_Port_Close();\n\treturn (PORT_VALID);\n\n\n\n#else\t//WIN32\n\n\tunion REGS\t\tregs ;\n\tint com;\n\tint irqnum;\n\tint address;\n\tint status;\n\n\n\t// shutdown previous port\n\n\tShutdown();\n\n\tif (settings->IRQ > 0xf) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\t//\n\t// check if the IRQ is the same as the mouse\n\t// call mouse func to get mouse IRQ number\n\t//\n\n\tregs.x.eax = 0x0024;\n\tint386( 0x33, &regs, &regs );\n\n\t//\n\t// check for error\n\t//\n\tif (regs.w.ax != 0xffff) {\n\t\t//\n\t\t// is the mouse IRQ the same as that they selected\n\t\t//\n\t\tif (regs.h.cl == 0) {\t// PS/2 IRQ 0xc\n\t\t\tif (settings->IRQ == 0xc) {\n\t\t\t\treturn( PORT_IRQ_INUSE );\n\t\t\t}\n\t\t} else if (regs.h.cl == (unsigned char)(settings->IRQ)) {\n\t\t\treturn( PORT_IRQ_INUSE );\n\t\t}\n\t}\n\n\tif (settings->IRQ < 2\t\t\t\t\t// 0 timer, 1 keyboard\n\t\t|| settings->IRQ == 6\t\t\t\t// floppy disk\n\t\t|| settings->IRQ == 8\t\t\t\t// CMOS real-time clock\n\t\t|| settings->IRQ == 0xd\t\t\t\t// math coprocessor error\n\t\t|| settings->IRQ == 0xe) {\t\t\t// hard disk\n\t\treturn( PORT_IRQ_INUSE );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tThis call allocates all necessary queue buffers\n\t------------------------------------------------------------------------*/\n\tswitch ( settings->Port ) {\n\t\tcase 0x3f8:\n\t\t\tcom = COM1;\n\t\t\tbreak;\n\n\t\tcase 0x2f8:\n\t\t\tcom = COM2;\n\t\t\tbreak;\n\n\t\tcase 0x3e8:\n\t\t\tcom = COM3;\n\t\t\tbreak;\n\n\t\tcase 0x2e8:\n\t\t\tcom = COM4;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcom = COM5;\n\t\t\tbreak;\n\t}\n\n\tstatus = FastGetPortHardware( com, &irqnum, &address );\n\tif (status == ASSUCCESS) {\n\t\tif (settings->Port != address || settings->IRQ != irqnum) {\n\t\t\tstatus = FastSetPortHardware( com, settings->IRQ, settings->Port );\n\t\t}\n\t}\n\n\tif (status != ASSUCCESS) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tOpen the Greenleaf port\n\t------------------------------------------------------------------------*/\n\tPort = PortOpenGreenleafFast (com, settings->Baud, 'N', 8, 1);\n\n\tstatus = Port->status;\n\n\tPortClose(Port);\n\tPort = NULL;\n\n\tif (status == ASIRQINUSE) {\n\t\treturn( PORT_IRQ_INUSE );\n\t} else if (status != ASSUCCESS) {\n\t\treturn( PORT_INVALID );\n\t}\n\n\treturn( PORT_VALID );\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * NullModemClass::ShutDown -- Closes serial port and removes the connection                   *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 11:43AM ST : Documented / Win32 support                                           *\n *=============================================================================================*/\nvoid NullModemClass::Shutdown ( void )\n{\n\n#ifdef WIN32\n\n\tif (PortHandle && SerialPort) {\n\t\tSerialPort->Serial_Port_Close();\n\t\tdelete SerialPort;\n\t\tSerialPort = NULL;\n\t\tPortHandle = NULL;\n\t\tDelete_Connection();\n\t}\n\n#else\t//WIN32\n\tif (Port) {\n\t\tPortClose(Port);\n\t\tPort = NULL;\n\t\tDelete_Connection();\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Shutdown */\n\n\n/***************************************************************************\n * NullModemClass::Set_Timing -- sets timing for all connections\t\t\t\t*\n *                                                                         *\n * This will set the timing parameters.  This allows an application to\t\t*\n * measure the Response_Time while running, and adjust timing accordingly.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tretrydelta\tvalue to set for retry delta \t\t\t\t\t\t\t\t\t\t*\n *\t\tmaxretries\tvalue to set for max # retries\t\t\t\t\t\t\t\t\t*\n *\t\ttimeout\t\tvalue to set for connection timeout\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/07/1995 DRD : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Set_Timing (unsigned long retrydelta,\n\tunsigned long maxretries, unsigned long timeout)\n{\n\tRetryDelta = retrydelta;\n\tMaxRetries = maxretries;\n\tTimeout = timeout;\n\n\tConnection->Set_Retry_Delta (RetryDelta);\n\tConnection->Set_Max_Retries (MaxRetries);\n\tConnection->Set_TimeOut (Timeout);\n\n}\t/* end of Set_Timing */\n\n\n/***************************************************************************\n * NullModemClass::Send_Message -- sends a message\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * For clarity's sake, here's what happens to the buffer passed in:\t\t\t*\n * - It gets passed to the Connection's Send_Packet() routine\t\t\t\t\t*\n * - The CommHeaderType header gets tacked onto it\t\t\t\t\t\t\t\t\t*\n * - The resulting buffer gets added to the Connection's Send Queue\t\t\t*\n * - When Service() determines that it needs to send the data, it\t\t\t\t*\n *   copies the entire packet (CommHeaderType and all) into its local \t\t*\n *   SendBuf, adds the packet start ID, length, and CRC, then sends it out.*\n *                                                                         *\n * The ack_req argument will almost always be '1' (the default).  The only\t*\n * reason to use 0 is if you don't know whether the other system is\t\t\t*\n * ready or not, so you have to periodically send out a query packet,\t\t*\n * and wait for a response.  (Using the connection's built-in retry\t\t\t*\n * system would just blast out useless data if the other system isn't\t\t*\n * even there.)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\t1 = ACK is required; 0 = not\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK; 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemClass::Send_Message (void *buf, int buflen, int ack_req)\n{\n\tint rc;\n\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\n\trc = Connection->Send_Packet(buf,buflen,ack_req);\n\tif (!rc)\n\t\tSendOverflows++;\n\n\treturn(rc);\n\n}\t/* end of Send_Message */\n\n\n/***************************************************************************\n * NullModemClass::Get_Message -- polls the Queue for a message\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to store message in\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tptr filled in with length of message\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = message was received; 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint NullModemClass::Get_Message (void *buf, int *buflen)\n{\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\treturn( Connection->Get_Packet( buf, buflen ) );\n}\n\n\n/***************************************************************************\n * NullModemClass::Service -- main polling routine\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = connection has gone bad\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *   8/2/96     ST : Win32 support                                         *\n *=========================================================================*/\nint NullModemClass::Service (void)\n{\n\tint pos;\t\t\t\t// current position in RXBuf\n\tint i;\t\t\t\t// loop counter\n\tunsigned short length;\n\tSerialHeaderType *header;\t// decoded packet start, length\n\tSerialCRCType *crc;\t\t\t// decoded packet CRC\n\tchar moredata = 0;\n\n\tif (NumConnections == 0) {\n\t\treturn( false );\n\t}\n\n#ifdef WIN32\n\n\tRXCount += SerialPort->Read_From_Serial_Port((unsigned char*)(RXBuf + RXCount), int(RXSize - RXCount) );\n\n#else\t//WIN32\n\n\tint status;\n\tstatic unsigned long last_time = 0;\n\n\t/*------------------------------------------------------------------------\n\tFirst, copy all the bytes we can from the Greenleaf RX buffer to our\n\town buffer.\n\t(For Win95, only call GetLineStatus() 60 times a second at most.\n\tOtherwise, we don't receive any packets!)\n\t------------------------------------------------------------------------*/\n\tif ( (TickCount - last_time) > 0) {\n\t\tif ( GetLineStatus( Port ) ) {\n\t\t\tMono_Set_Cursor(0,0);\n\t\t\tClearLineStatus( Port );\n\t\t}\n\t\tlast_time = TickCount;\n\t}\n\n\tstatus = SpaceUsedInRXBuffer( Port );\n\n\tif ( status < ASSUCCESS) {\n//\t\tSmart_Printf( \"SpaceUsedInRXBuffer status = %d, port status = %d \\n\", status, Port->status );\n\n\t\tif ( Port->status < ASSUCCESS ) {\n\t\t\tClearError( Port );\n\t\t}\n\n\t} else if (status > 0) {\n\t\tstatus = ReadBuffer( Port, RXBuf + RXCount, RXSize - RXCount );\n\n#if (CONN_DEBUG)\n\t\tprintf( \"ReadBuffer status = %d, port status = %d, count = %d \\n\", status, Port->status, Port->count );\n#endif\n//\t\t\tSmart_Printf( \"ReadBuffer status = %d, port status = %d, count = %d \\n\", status, Port->status, Port->count );\n\t\tif (status < ASSUCCESS && status != ASBUFREMPTY) {\n//\t\t\t\tSmart_Printf( \"ReadBuffer ERRRRRRORRRRRR! \\n\" );\n\t\t} else {\n\t\t\tmoredata = 1;\n\t\t}\n\n\t\tif ( Port->status < ASSUCCESS ) {\n\t\t\tClearError( Port );\n\t\t}\n\n\t\tRXCount += Port->count;\n\t}\n\n\n#endif\t//WIN32\n\n\t// minimum packet size\n\n\tif ( RXCount < (PACKET_SERIAL_OVERHEAD_SIZE + 1) ) {\n\t\treturn( Connection->Service() );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow scan the buffer for the start of a packet.\n\t------------------------------------------------------------------------*/\n\tpos = -1;\n\tfor (i = 0; i <= RXCount - sizeof( short ); i++) {\n\t\tif ( *((unsigned short *)(RXBuf + i)) == PACKET_SERIAL_START ) {\n\t\t\tpos = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNo start code was found; throw away all bytes except the last few, and\n\treturn.\n\t------------------------------------------------------------------------*/\n\tif (pos==-1) {\n// Smart_Printf( \"No magic number found \\n\" );\n\t\t/*.....................................................................\n\t\tmove the remaining, un-checked bytes to the start of the buffer\n\t\t.....................................................................*/\n\t\tmemmove (RXBuf, RXBuf + i, sizeof( short ) - 1);\n\t\tRXCount = sizeof( short ) - 1;\n\t\treturn( Connection->Service() );\n\t}\n\n\t/*------------------------------------------------------------------------\n\tCheck to see if there are enough bytes for the header to be decoded\n\t------------------------------------------------------------------------*/\n\tif ( (RXCount - pos) < sizeof( SerialHeaderType ) ) {\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tA start code was found; check the packet's length & CRC\n\t------------------------------------------------------------------------*/\n\theader = (SerialHeaderType *)(RXBuf + pos);\n\n\t/*------------------------------------------------------------------------\n\tIf we lost a byte in the length, we may end up waiting a very long time\n\tfor the buffer to get to the right length; check the verify value to\n\tmake sure this didn't happen.\n\t------------------------------------------------------------------------*/\n\tif ( header->MagicNumber2 != PACKET_SERIAL_VERIFY ) {\n// Smart_Printf( \"Verify failed\\n\");\n//\t\tHex_Dump_Data( (RXBuf + pos), PACKET_SERIAL_OVERHEAD_SIZE );\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\tlength = header->Length;\n\n\t/*------------------------------------------------------------------------\n\tSpecial case: if the length comes out too long for us to process:\n\t- Assume the packet is bad\n\t- Throw away the bogus packet-start code\n\t- Return;  we'll search for another packet-start code next time.\n\t------------------------------------------------------------------------*/\n\tif (length > MaxLen) {\n#if (CONN_DEBUG)\n\t\tprintf( \"length too lonnng\\n\" );\n#endif\n// Smart_Printf( \"length too lonnng %d, max %d \\n\", length, MaxLen );\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tIf the entire packet isn't stored in our buffer, copy the remaining bytes\n\tto the front of the buffer & return.\n\t------------------------------------------------------------------------*/\n\tif ( (pos + length + PACKET_SERIAL_OVERHEAD_SIZE) > RXCount) {\n\n\t\tif ( moredata ) {\n// Smart_Printf( \"waiting for more data %d, pos = %d \\n\", ((length + PACKET_SERIAL_OVERHEAD_SIZE) - (RXCount - pos)), pos );\n\t\t}\n\n\t\tif (pos) {\n\t\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\t\tRXCount -= pos;\n\t\t}\n\t\treturn(Connection->Service());\n\t}\n\n\t/*------------------------------------------------------------------------\n\tNow grab the CRC value in the packet, & compare it to the CRC value\n\tcomputed from the actual data.  If they don't match, throw away the bogus\n\tstart-code, move the rest to the front of the buffer, & return.\n\tWe'll continue parsing this data when we're called next time.\n\t------------------------------------------------------------------------*/\n\tcrc = (SerialCRCType *)(RXBuf + pos + sizeof( SerialHeaderType ) + length);\n\tif (NullModemConnClass::Compute_CRC(RXBuf + pos +\n\t\tsizeof( SerialHeaderType ), length) != crc->SerialCRC) {\n\n\t\tCRCErrors++;\n\n#if (CONN_DEBUG)\n\t\tprintf( \"CRC check failed\\n\" );\n#endif\n// Smart_Printf( \"CRC check failed for packet of length %d \\n\", length );\n\n//\t\tif (length < 100) {\n//\t\t\tHex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );\n//\t\t}\n\n\t\tpos += sizeof ( short );\t\t// throw away the bogus start code\n\t\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\t\tRXCount -= pos;\n\t\treturn(Connection->Service());\n\t}\n\n#if(0)\n// Mono_Printf( \"received %d bytes \\n\", sendlen );\n Debug_Modem_Dump = true;\n Smart_Printf( \"Received tick=%d, Protocol=%d \\n\",  TickCount, Session.CommProtocol );\n Hex_Dump_Data( (RXBuf + pos), (sizeof( SerialHeaderType) + length) );\n Debug_Modem_Dump = false;\n#endif\n\n\t/*------------------------------------------------------------------------\n\tGive the new packet to the Connection to process.\n\t------------------------------------------------------------------------*/\n\tif (!Connection->Receive_Packet(RXBuf + pos + sizeof( SerialHeaderType ), length)) {\n\t\tReceiveOverflows++;\n// Smart_Printf( \"Received overflows %d \\n\", ReceiveOverflows );\n\t}\n\n#if(0)\n\telse {\n// Mono_Printf( \"added packet \\n\", sendlen );\n Debug_Modem_Dump = true;\n Smart_Printf( \"Received Packet \\n\" );\n Debug_Modem_Dump = false;\n\t}\n#endif\n\n#if (0)\n\tHex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );\n#endif\n\n\t/*------------------------------------------------------------------------\n\tMove all data past this packet to the front of the buffer.\n\t------------------------------------------------------------------------*/\n\tpos += (PACKET_SERIAL_OVERHEAD_SIZE + length);\n\tmemmove (RXBuf, RXBuf + pos, RXCount - pos);\n\tRXCount -= pos;\n\n\t/*------------------------------------------------------------------------\n\tNow, service the connection's Queue's; this will handle ACK & Retries.\n\t------------------------------------------------------------------------*/\n\treturn(Connection->Service());\n\n}\t/* end of Service */\n\n\n/***************************************************************************\n * NullModemClass::Num_Send -- Returns # of unACK'd send entries\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nint NullModemClass::Num_Send(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Num_Send() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Num_Send */\n\n\n/***************************************************************************\n * NullModemClass::Num_Receive -- Returns # entries in the receive queue   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nint NullModemClass::Num_Receive(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Num_Receive() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Num_Receive */\n\n\n/***************************************************************************\n * NullModemClass::Response_Time -- Returns Queue's avg response time      *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long NullModemClass::Response_Time(void)\n{\n\tif (Connection)\n\t\treturn( Connection->Queue->Avg_Response_Time() );\n\telse\n\t\treturn (0);\n\n}\t/* end of Response_Time */\n\n\n/***************************************************************************\n * NullModemClass::Reset_Response_Time -- Resets response time computation *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Reset_Response_Time(void)\n{\n\tif (Connection)\n\t\tConnection->Queue->Reset_Response_Time();\n\n}\t/* end of Reset_Response_Time */\n\n\n/***************************************************************************\n * Oldest_Send -- Returns ptr to oldest unACK'd send buffer                *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid * NullModemClass::Oldest_Send(void)\n{\n\tint i;\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tCommHeaderType *packet;\n\tvoid *buf = NULL;\n\n\tfor (i = 0; i < Connection->Queue->Num_Send(); i++) {\n\t\tsend_entry = Connection->Queue->Get_Send(i);\n\t\tif (send_entry) {\n\t\t\tpacket = (CommHeaderType *)send_entry->Buffer;\n\t\t\tif (packet->Code == ConnectionClass::PACKET_DATA_ACK && send_entry->IsACK == 0) {\n\t\t\t\tbuf = send_entry->Buffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(buf);\n\n}\t/* end of Oldest_Send */\n\n\n/***************************************************************************\n * NullModemClass::Configure_Debug -- sets up special debug values         *\n *                                                                         *\n * Mono_Debug_Print2() can look into a packet to pull out a particular\t\t*\n * ID, and can print both that ID and a string corresponding to\t\t\t\t*\n * that ID.  This routine configures these values so it can find\t\t\t\t*\n * and decode the ID.  This ID is used in addition to the normal\t\t\t\t*\n * CommHeaderType values.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t(not used)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttype_offset\t\tID's byte offset into packet\t\t\t\t\t\t\t\t\t*\n *\t\ttype_size\t\tsize of ID, in bytes; 0 if none\t\t\t\t\t\t\t\t*\n *\t\tnames\t\t\t\tptr to array of names; use ID as an index into this\t*\n *\t\tnamestart\t\tnumerical start of the 1st name value\t\t\t\t\t\t*\n *\t\tnamecount\t\t# in the names array; 0 if none.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tNames shouldn't be longer than 12 characters.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/31/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Configure_Debug(int, int type_offset, int type_size,\n\tchar **names, int namestart, int namecount)\n{\n\tif (Connection)\n\t\tConnection->Queue->Configure_Debug (type_offset, type_size, names,\n\t\t\tnamestart, namecount);\n}\n\n#ifdef CHEAT_KEYS\n/***************************************************************************\n * Mono_Debug_Print -- Debug output routine                                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tindex\t\t\t(not used)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\trefresh\t\t1 = clear screen & completely refresh\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid NullModemClass::Mono_Debug_Print(int,int refresh)\n{\n\tif (!Connection)\n\t\treturn;\n\n\tConnection->Queue->Mono_Debug_Print (refresh);\n\n\tif (refresh) {\n\t\tMono_Set_Cursor (31,1);\n\t\tMono_Printf (\"Serial Port Queues\");\n\n\t\tMono_Set_Cursor (9,2);\n\t\tMono_Printf (\"Average Response Time:\");\n\n\t\tMono_Set_Cursor (20,3);\n\t\tMono_Printf (\"CRC Errors:\");\n\n\t\tMono_Set_Cursor (43,2);\n\t\tMono_Printf (\"Send Overflows:\");\n\n\t\tMono_Set_Cursor (40,3);\n\t\tMono_Printf (\"Receive Overflows:\");\n\t}\n\n\tMono_Set_Cursor (32,2);\n\tMono_Printf (\"%d  \", Connection->Queue->Avg_Response_Time());\n\n\tMono_Set_Cursor (32,3);\n\tMono_Printf (\"%d  \", CRCErrors);\n\n\tMono_Set_Cursor (59,2);\n\tMono_Printf (\"%d  \", SendOverflows);\n\n\tMono_Set_Cursor (59,3);\n\tMono_Printf (\"%d  \", ReceiveOverflows);\n\n\tMono_Set_Cursor (2,5);\n\tMono_Printf (\"%d  \", Num_Send());\n\n\tMono_Set_Cursor (41,5);\n\tMono_Printf (\"%d  \", Num_Receive());\n\n}\t/* end of Mono_Debug_Print */\n#endif\n\n\n/***************************************************************************\n * NullModemClass::Detect_Modem -- Detects and initializes the modem       *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettings structure     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t-1\t\t\t\tinit string invalid\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t0\t\t\t\tno modem found\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t1\t\t\t\tmodem found\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Added Win32 support                                  *\n *=========================================================================*/\nint NullModemClass::Detect_Modem( SerialSettingsType *settings, bool reconnect )\n{\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tint status;\n\tint error_count = 0;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\t/*\n\t** Get resolution factor\n\t*/\n//\tint\tfactor = SeenBuff.Get_Width()/320;\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tstrcpy( buffer, Text_String( TXT_INITIALIZING_MODEM ) );\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tint lines = Format_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 40 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*------------------------------------------------------------------------\n\tDraw the dialog\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tif ( !reconnect ) {\n\t\tLoad_Title_Page(true);\n\t}\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tif (lines == 1) {\n\t\tFancy_Text_Print(buffer, x + width/2, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT|TPF_CENTER);\n\t} else {\n\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\t}\n\n\tShow_Mouse();\n\n\n\tHMWaitForOK( 0, NULL );\n\n\n\t/*\n\t** OK, lets not mess about any more. Just turn on echo, verbose, and result codes\n\t** before we even begin. At least this way when we get an error later on we have already\n\t** removed all the steps we use to try and recover.\n\t** The timeouts need to be quite small in case the modem is turned off.\n\t*/\n\n\t/*\n\t** Turn on result codes.\n\t*/\n\tSend_Modem_Command ( \"ATQ0\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\t/*\n\t** Make result codes verbose.\n\t*/\n\tSend_Modem_Command ( \"ATV1\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\t/*\n\t** Turn on echo.\n\t*/\n\tSend_Modem_Command ( \"ATE1\", '\\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);\n\n\tModemVerboseOn = true;\n\tModemEchoOn = true;\n\n\n\n\n\n\t/*\n\t** Try sending a plain old AT command to the modem. Now that we have theoretically\n\t** turned on verbose result codes we should get an 'OK' back.\n\t**\n\t*/\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 2 );\n\n\tif (status < ASSUCCESS) {\n#ifdef FIXIT_MULTI_SAVE\n\t\treturn(false);\n#else\n\t\tif (WWMessageBox().Process(TXT_ERROR_NO_RESP, TXT_IGNORE, TXT_CANCEL)) return( false );\n\t\terror_count++;\n#endif\n\t}\n\n\t/*\n\t** Send the user supplied modem init string\n\t*/\n\tif (settings->InitStringIndex == -1) {\n\t\tstatus = Send_Modem_Command( \"\", '\\r', buffer, 81, 300, 1 );\n\t} else {\n\t\t/*\n\t\t** Split up the init string into seperate strings if it contains one or more '|' characters.\n\t\t** This character acts as a carriage return/pause.\n\t\t*/\n\t\tchar *istr = new char [2 + strlen( Session.InitStrings [settings->InitStringIndex] )];\n\t\tchar *tokenptr;\n\t\tstrcpy (istr, Session.InitStrings [settings->InitStringIndex] );\n\n\t\t/*\n\t\t** Tokenise the string and send it in chunks\n\t\t*/\n\t\ttokenptr = strtok ( istr, \"|\" );\n\t\twhile ( tokenptr ) {\n\n\t\t\tstatus = Send_Modem_Command( tokenptr, '\\r', buffer, 81, 3000, 1 );\n\t\t\t/*\n\t\t\t** Handle error case.\n\t\t\t*/\n\t\t\tif (status < ASSUCCESS) {\n\t\t\t\tif (WWMessageBox().Process(TXT_ERROR_NO_INIT, TXT_IGNORE, TXT_CANCEL)) {\n\t\t\t\t\tdelete istr;\n\t\t\t\t\treturn( false );\n\t\t\t\t}\n#ifdef WIN32\n\t\t\t\terror_count++;\n#endif\t//WIN32\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\ttokenptr = strtok ( NULL, \"|\");\n\n\t\t}\n\t}\n\n#ifdef WIN32\n\n\tif (settings->Port == 1 && ModemRegistry) {\n\t\t/*\n\t\t** Send the init strings from the registry if available\n\t\t*/\n\t\tchar send_string[256] = {\"AT\"};\n\n\t\t/*\n\t\t** Send the init string for hardware flow control\n\t\t*/\n\t\tif (settings->HardwareFlowControl){\n\t\t\tif (ModemRegistry->Get_Modem_Hardware_Flow_Control()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Hardware_Flow_Control());\n\t\t\t\tstatus = Send_Modem_Command (send_string, '\\r', buffer, 81, 300, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t** Send the init string for no flow control\n\t\t\t*/\n\t\t\tif (ModemRegistry->Get_Modem_No_Flow_Control()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_No_Flow_Control());\n\t\t\t\tstatus = Send_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Send the string for data compresseion\n\t\t*/\n\t\tif (settings->Compression){\n\n\t\t\tif (ModemRegistry->Get_Modem_Compression_Enable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Enable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\n\t\t\tif (ModemRegistry->Get_Modem_Compression_Disable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Disable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t/*\n\t\t** Send the string for error correction\n\t\t*/\n\t\tif (settings->ErrorCorrection){\n\n\t\t\tif (ModemRegistry->Get_Modem_Error_Correction_Enable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Enable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif (ModemRegistry->Get_Modem_Error_Correction_Disable()) {\n\t\t\t\tstrcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Disable());\n\t\t\t\tSend_Modem_Command (send_string, '\\r', buffer, 81, DEFAULT_TIMEOUT, 1);\n\t\t\t\tif (status != MODEM_CMD_OK && status != MODEM_CMD_0) {\n\t\t\t\t\tif (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n#endif\t//WIN32\n\n\n\t/*\n\t** We require that auto-answer be disabled so turn it off now.\n\t*/\n\tstatus = Send_Modem_Command( \"ATS0=0\", '\\r', buffer, 81, DEFAULT_TIMEOUT, INIT_COMMAND_RETRIES );\n\tif (status != MODEM_CMD_OK) {\n\t\tif (WWMessageBox().Process(TXT_ERROR_NO_DISABLE, TXT_IGNORE, TXT_CANCEL)) return( false );\n\t\terror_count++;\n\t}\n\n\t/*\n\t** If we had an unreasonable number of ignored errors then return failure\n\t*/\n\tif (error_count >= 3) {\n\t\tWWMessageBox().Process(TXT_ERROR_TOO_MANY, TXT_OK);\n\t\treturn (false);\n\t}\n\n\treturn( true );\n}\n\n\n/***************************************************************************\n * NullModemClass::Dial_Modem -- dials a number passed                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tsettings\t\tptr to SerialSettings structure     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tDialStatus\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Win32 support                                        *\n *=========================================================================*/\nDialStatusType NullModemClass::Dial_Modem( char *string, DialMethodType method, bool reconnect )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor = SeenBuff.Get_Width()/320;\n\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*------------------------------------------------------------------------\n\tDialog variables\n\t------------------------------------------------------------------------*/\n\tbool process = true;\t\t\t\t\t\t// process while true\n#ifndef WIN32\n\tint status;\n#endif\t//WIN32\n\tint delay;\n\tDialStatusType dialstatus;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tchar buffer[80*3];\n\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tif (reconnect) {\n\t\tstrcpy( buffer, Text_String( TXT_MODEM_CONNERR_REDIALING ) );\n\t} else {\n\t\tstrcpy( buffer, Text_String( TXT_DIALING ) );\n\t}\n\n\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT);\n\tFormat_Window_String(buffer, SeenBuff.Get_Height(), width, height);\n\n\tint text_width = width;\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*------------------------------------------------------------------------\n\tCreate the list\n\t------------------------------------------------------------------------*/\n\tCommands = &cancelbtn;\n\n\tCommands->Flag_List_To_Redraw();\n\n\t/*------------------------------------------------------------------------\n\tDraw the dialog\n\t------------------------------------------------------------------------*/\n\tHide_Mouse();\n\tif ( !reconnect ) {\n\t\tLoad_Title_Page(true);\n\t}\n\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(TXT_NONE, x, y, width);\n\n\tFancy_Text_Print(buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 *RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\n\tCommands->Draw_All();\n\tShow_Mouse();\n\n\t/*\n\t** Start waiting for connection response\n\t*/\n#ifdef WIN32\n\tSerialPort->Set_Modem_Dial_Type((WinCommDialMethodType) method);\n\t/*\n\t** Clear out any old modem results that might be hanging around\n\t*/\n\tSerialPort->Get_Modem_Result(60, buffer, 81);\n\t/*\n\t** Dial that sucker\n\t*/\n\tSerialPort->Dial_Modem(string);\n\n#else\t//WIN32\n\tHMSetDialingMethod( Port, (int)method );\n\tstatus = HMDial( Port, string );\n\n#endif\t//WIN32\n\n\n\t/*\n\t** Sets up the ability to abort modem commands when any input is in the\n\t** Keyboard buffer.  This also calls the game CallBack().\n\t*/\n\tSetup_Abort_Modem();\n\n\t/*------------------------------------------------------------------------\n\tMain Processing Loop\n\t------------------------------------------------------------------------*/\n\tprocess = true;\n\tdelay = ModemWaitCarrier;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tCommands->Draw_All();\n\t\t}\n\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tProcess input\n\t\t.....................................................................*/\n\t\tswitch (Input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tdialstatus = DIAL_CANCELED;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (process) {\n\t\t\tif ( strncmp( buffer, \"CON\", 3 ) == 0 ) {\n\t\t\t\tmemset (ModemRXString, 0, 80);\n\t\t\t\tstrncpy (ModemRXString, buffer, 79);\n\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"BUSY\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_BUSY;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"NO C\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_CARRIER;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"NO D\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_DIAL_TONE;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( buffer, \"ERRO\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (delay <= 0) {\n\t\t\tprocess = false;\n\t\t}\n\t}\n\n\tRemove_Abort_Modem();\n\n\treturn( dialstatus );\n\n}\t/* end of Dial_Modem */\n\n\n/***************************************************************************\n * NullModemClass::Answer_Modem -- waits for call and answers              *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\treconnect\twhether this is to reconnect\t\t     \t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tDialStatus\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96      ST : Added Win32 support                                  *\n *=========================================================================*/\nDialStatusType NullModemClass::Answer_Modem( bool reconnect )\n{\n\t/*\n\t** Get the resolution factor\n\t*/\n//\tint factor \t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\t/*------------------------------------------------------------------------\n\tButton Enumerations\n\t------------------------------------------------------------------------*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*------------------------------------------------------------------------\n\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t------------------------------------------------------------------------*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*------------------------------------------------------------------------\n\tDialog variables\n\t------------------------------------------------------------------------*/\n\tRedrawType display = REDRAW_ALL;\t\t// redraw level\n\tbool process = true;\t\t\t\t\t\t// process while true\n#ifndef WIN32\n\tint status;\n#endif\t//WIN32\n\tint delay;\n\tDialStatusType dialstatus;\n\tbool ring = false;\n\n\tint x,y,width,height;\t\t\t\t\t// dialog dimensions\n\tint text_width;\n\tchar text_buffer[80*3];\n\tchar comm_buffer[80*3];\n\n\t/*------------------------------------------------------------------------\n\tDetermine the dimensions of the text to be used for the dialog box.\n\tThese dimensions will control how the dialog box looks.\n\t------------------------------------------------------------------------*/\n\tif (reconnect) {\n\t\tstrcpy( text_buffer, Text_String( TXT_MODEM_CONNERR_WAITING ) );\n\t} else {\n\t\tstrcpy( text_buffer, Text_String( TXT_WAITING_FOR_CALL ) );\n\t}\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);\n\tFormat_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);\n\n\ttext_width = width;\n\twidth = max(width, 90 * RESFACTOR);\n\twidth += 40 * RESFACTOR;\n\theight += 60 * RESFACTOR;\n\n\tx = (SeenBuff.Get_Width() - width) / 2;\n\ty = (SeenBuff.Get_Height() - height) / 2;\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,\n\t\tx + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1),\n\t\ty + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR);\n\n\t/*------------------------------------------------------------------------\n\tInitialize\n\t------------------------------------------------------------------------*/\n\tSet_Logic_Page(SeenBuff);\n\tLoad_Title_Page(true);\n\n\tInput = KN_NONE;\n\n\t/*------------------------------------------------------------------------\n\tCreate the list\n\t------------------------------------------------------------------------*/\n\tCommands = &cancelbtn;\n\n\tCommands->Flag_List_To_Redraw();\n\n\t/*\n\t** Sets up the ability to abort modem commands when any input is in the\n\t** Keyboard buffer.  This also calls the game CallBack() and Input().\n\t*/\n\tSetup_Abort_Modem();\n\n\t/*------------------------------------------------------------------------\n\tMain Processing Loop\n\t------------------------------------------------------------------------*/\n\tprocess = true;\n\tdelay = 60000;\n\twhile (process) {\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay=REDRAW_ALL;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*.....................................................................\n\t\tRefresh display if needed\n\t\t.....................................................................*/\n\t\tif (display) {\n\t\t\tHide_Mouse();\n\t\t\tif (display >= REDRAW_BACKGROUND) {\n\t\t\t\t/*...............................................................\n\t\t\t\tRefresh the backdrop\n\t\t\t\t...............................................................*/\n\t\t\t\tif ( !reconnect ) {\n\t\t\t\t\tLoad_Title_Page(true);\n\t\t\t\t}\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDraw the background\n\t\t\t\t...............................................................*/\n\t\t\t\tDialog_Box(x, y, width, height);\n\n\t\t\t\t/*...............................................................\n\t\t\t\tDraw the labels\n\t\t\t\t...............................................................*/\n\t\t\t\tDraw_Caption(TXT_NONE, x, y, width);\n\n\t\t\t\tFancy_Text_Print(text_buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 * RESFACTOR,\n\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT);\n\n\t\t\t\tCommands->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, comm_buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, comm_buffer, 81 );\n#endif\t//WIN32\n\n\n\t\t/*.....................................................................\n\t\tProcess input\n\t\t.....................................................................*/\n\t\tif (!Input) Input = Commands->Input();\n\t\tswitch (Input) {\n\t\t\tcase (KN_ESC):\n\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\tdialstatus = DIAL_CANCELED;\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (process) {\n\t\t\tif ( strncmp( comm_buffer, \"RING\", 4 ) == 0 ) {\n\n\t\t\t\tstrcpy( text_buffer, Text_String( TXT_ANSWERING ) );\n\n\t\t\t\tFancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT);\n\t\t\t\tFormat_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);\n\n\t\t\t\ttext_width = width;\n\t\t\t\twidth = max(width, 90 * RESFACTOR);\n\t\t\t\twidth += 40 * RESFACTOR;\n\t\t\t\theight += 60 * RESFACTOR;\n\n\t\t\t\tx = (SeenBuff.Get_Width() - width) / 2;\n\t\t\t\ty = (SeenBuff.Get_Height() - height) / 2;\n\n#ifdef WIN32\n\t\t\t\tSerialPort->Write_To_Serial_Port ((unsigned char*)\"ATA\\r\", strlen(\"ATA\\r\"));\n#else\t//WIN32\n\t\t\t\tPortKillTime( Port, 100 );\n\t\t\t\tHMWaitForOK( 0, NULL );\n\t\t\t\tstatus = HMAnswer( Port );\n#endif\t//WIN32\n\n\t\t\t\tring = true;\n\t\t\t\tdelay = ModemWaitCarrier;\n\t\t\t\tdisplay = REDRAW_ALL;\n\t\t\t} else if ( strncmp( comm_buffer, \"CON\", 3 ) == 0 ) {\n\t\t\t\tmemset (ModemRXString, 0, 80);\n\t\t\t\tstrncpy (ModemRXString, comm_buffer, 79);\n\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"BUSY\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_BUSY;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"NO C\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_NO_CARRIER;\n\t\t\t\tprocess = false;\n\t\t\t} else if ( strncmp( comm_buffer, \"ERRO\", 4 ) == 0 ) {\n\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\tWWMessageBox().Process(TXT_ERROR_ERROR, TXT_OK);\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n#ifdef WIN32\n\n\t\tif (delay <= 0) {\n\t\t\tif (ring) {\n\t\t\t\tif (SerialPort->Get_Modem_Status() & CD_SET) {\n\t\t\t\t\tsprintf(ModemRXString, \"%s\", \"Connected\");\n\t\t\t\t\tdialstatus = DIAL_CONNECTED;\n\t\t\t\t} else {\n\t\t\t\t\tdialstatus = DIAL_ERROR;\n\t\t\t\t\tWWMessageBox().Process(TXT_ERROR_TIMEOUT, TXT_OK);\n\t\t\t\t}\n\t\t\t\tprocess = false;\n\t\t\t} else {\n\t\t\t\tdelay = 60000;\n\t\t\t}\n\t\t}\n#else\t//WIN32\n\n\t\tif (delay <= 0) {\n\t\t\tif (ring) {\n\t\t\t\tprocess = false;\n\t\t\t} else {\n\t\t\t\tdelay = 60000;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\n\t}\n\n\tRemove_Abort_Modem();\n\n\treturn( dialstatus );\n\n}\t/* end of Answer_Modem */\n\n\n/***************************************************************************\n * NullModemClass::Hangup_Modem -- hangs up the modem                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tstatus\t\tsuccessful or not\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 DRD : Created.                                             *\n *   8/2/96         : Added Win32 support                                  *\n *=========================================================================*/\nbool NullModemClass::Hangup_Modem( void )\n{\n\tint status;\n\tint delay;\n\tchar buffer[81];\n\tchar escape[4];\n\n\t/*\n\t**\tTurn modem servicing off in the callback routine.\n\t*/\n\tSession.ModemService = false;\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( true );\n\t}\n\n\t/*\n\t** Toggle DTR low then high\n\t*/\n#ifdef WIN32\n\tSerialPort->Set_Serial_DTR(FALSE);\n\tDelay(3200/60);\n\tSerialPort->Set_Serial_DTR(TRUE);\n#else\t//WIN32\n\n\tSetDtr( Port, 0 );\n\tPortKillTime( Port, 3200 );\n\tSetDtr( Port, 1 );\n#endif\t//WIN32\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( true );\n\t}\n\n\tdelay = ModemGuardTime;\n\twhile ( delay > 0 ) {\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\t}\n\n\t/*\n\t** Send modem break commmand\n\t*/\n\tescape[0] = ModemEscapeCode;\n\tescape[1] = ModemEscapeCode;\n\tescape[2] = ModemEscapeCode;\n\tescape[3] = 0;\n\n#ifdef WIN32\n\tSerialPort->Write_To_Serial_Port((unsigned char*)escape, 3);\n#else\t//WIN32\n\tstatus = HMSendStringNoWait( Port, escape, -1 );\n#endif\t//WIN32\n\n\n\tdelay = ModemGuardTime;\n\twhile ( delay > 0 ) {\n#ifdef WIN32\n\t\tdelay = SerialPort->Get_Modem_Result(delay, buffer, 81);\n#else\t//WIN32\n\t\tdelay = HMInputLine( Port, delay, buffer, 81 );\n#endif\t//WIN32\n\n\t\tif ( strncmp( buffer, \"OK\", 2 ) == 0 ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t** Send the hangup command\n\t*/\n\tstatus = Send_Modem_Command( \"ATH\", '\\r', buffer, 81, ModemHangupDelay, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t} else {\n\t\tSession.ModemService = true;\n\t\treturn( false );\n\t}\n\n\t/*\n\t** Send spurious ATZ command for no apparent reason\n\t*/\n\tstatus = Send_Modem_Command( \"ATZ\", '\\r', buffer, 81, 5000, 1 );\n\n\tif (status != MODEM_CMD_OK) {\n\t\tSession.ModemService = true;\n\t\treturn( false );\n\t}\n\n\tSession.ModemService = true;\n\treturn( true );\n\n}\t/* end of Hangup_Modem */\n\n\n/***********************************************************************************************\n * NMC::Setup_Modem_Echo -- Sets the echo callback function pointer                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Ptr to callback function                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:48PM ST : Documented and added WIn32 support                                   *\n *=============================================================================================*/\nvoid NullModemClass::Setup_Modem_Echo( void ( *func )( char c) )\n{\n#ifdef WIN32\n\tSerialPort->Set_Echo_Function(func);\n#else\t//WIN32\n\tHMSetUpEchoRoutine( func );\n#endif\t//WIN32\n\n}\t/* end of Setup_Modem_Echo */\n\n\n/***********************************************************************************************\n * NMC::Remove_Modem_Echo -- Set the echo function callback pointer to null                    *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:50PM ST : Documented / Win32 support added                                     *\n *=============================================================================================*/\nvoid NullModemClass::Remove_Modem_Echo( void )\n{\n//\tSmart_Printf( \"Remove Echo modem code\\n\" );\n\tHMSetUpEchoRoutine( NULL );\n\n}\t/* end of Remove_Modem_Echo */\n\n\n\n/***********************************************************************************************\n * NMC::Print_EchoBuf -- Print out the contents of the echo buffer                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:51PM ST : Documented                                                           *\n *=============================================================================================*/\nvoid NullModemClass::Print_EchoBuf( void )\n{\n\tfor (int i = 0; i < strlen(NullModem.EchoBuf); i++) {\n\t\tif (NullModem.EchoBuf[i] == '\\r') {\n\t\t\tNullModem.EchoBuf[i] = 1;\n\t\t} else {\n\t\t\tif (NullModem.EchoBuf[i] == '\\n') {\n\t\t\t\tNullModem.EchoBuf[i] = 2;\n\t\t\t}\n\t\t}\n\t}\n//\tSmart_Printf( \"Echo buffer length %d (%s)\\n\", NullModem.EchoCount, NullModem.EchoBuf );\n}\n\n\n\n/***********************************************************************************************\n * NMC::Reset_EchoBuf -- Empties the echo buffer                                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:51PM ST : Documented                                                           *\n *=============================================================================================*/\nvoid NullModemClass::Reset_EchoBuf( void )\n{\n\t*EchoBuf = 0;\n\tEchoCount = 0;\n}\n\n\n/***********************************************************************************************\n * NMC::Abort_Modem -- Checks for user input so that modem operations can be aborted           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   ASUSERABORT if abort key pressed. ASSUCESS otherwise.                             *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 12:52PM ST : Documented                                                           *\n *=============================================================================================*/\nint NullModemClass::Abort_Modem( PORT * )\n{\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t};\n\n\t/*\n\t** Invoke game callback\n\t*/\n\tCall_Back();\n\n\t/*\n\t** Get user input\n\t*/\n\tInput = Commands->Input();\n\n\tswitch ( Input ) {\n\t\tcase (KN_ESC):\n\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\treturn( ASUSERABORT );\n\t}\n\n\treturn( ASSUCCESS );\n\n}\t/* end of Abort_Modem */\n\n\n/***********************************************************************************************\n * NMC::Setup_Abort_Modem -- sets the modem abort function pointer                             *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 2:59PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nvoid NullModemClass::Setup_Abort_Modem( void )\n{\n\n#ifdef WIN32\n\n\tSerialPort->Set_Abort_Function((int(*)(void))Abort_Modem);\n\n#else\t//WIN32\n\t/*\n\t** save off original abort modem function to later restore\n\t*/\n\tOrigAbortModemFunc = _AbortModemFunctionPtr;\n\tHMSetUpAbortKey( ESC );\n\tSetAbortModemFunctionPtr( Abort_Modem );\n#endif\t//WIN32\n\n}\t/* end of Setup_Abort_Modem */\n\n\n/***********************************************************************************************\n * NMC::Remove_Abort_Modem -- Removes the modem abort function pointer                         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:01PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nvoid NullModemClass::Remove_Abort_Modem( void )\n{\n\n#ifdef WIN32\n\tSerialPort->Set_Abort_Function(NULL);\n\n#else\t//WIN32\n\n\tHMSetUpAbortKey( NOKEY );\n\n\t/*\n\t** Restore the original abort modem function\n\t*/\n\t_AbortModemFunctionPtr = OrigAbortModemFunc;\n#endif\t//WIN32\n\n}\t/* end of Remove_Abort_Modem */\n\n\n\n/***********************************************************************************************\n * NMC::Change_IRQ_Priority -- Increases the priority of the serial interrupt                  *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Interrupt request number                                                          *\n *                                                                                             *\n * OUTPUT:   ASSUCCESS if changed                                                              *\n *                                                                                             *\n * WARNINGS: The Win32 version of this function does nothing.                                  *\n *           Priorities are controlled by windoze                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:03PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Change_IRQ_Priority( int irq )\n{\n#ifdef WIN32\n\n\tirq = irq;\n\treturn ( ASSUCCESS );\n\n#else\t//WIN32\n\n\tif (irq != OldIRQPri) {\n\t\tOldIRQPri = irq;\n\t\treturn( Change8259Priority( irq ) );\n\t} else {\n\t\treturn( ASSUCCESS );\n\t}\n\n#endif\t//WIN32\n\n}\t/* end of Change_IRQ_Priority */\n\n\n\n/***********************************************************************************************\n * NMC::Get_Modem_Status -- returns status of modem control bits                               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Modem status                                                                      *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:06PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Get_Modem_Status( void )\n{\n\tint modemstatus;\n\tint status;\n\tchar buffer[81];\n\n#ifdef WIN32\n\tmodemstatus = SerialPort->Get_Modem_Status();\n#else\t//WIN32\n\tmodemstatus = GetModemStatus( Port );\n#endif\t//WIN32\n\n\tstatus = Send_Modem_Command( \"AT\", '\\r', buffer, 81, DEFAULT_TIMEOUT, 1 );\n\n\tif (status == MODEM_CMD_OK) {\n\t\tmodemstatus &= (~CD_SET);\n\t}\n\n\treturn( modemstatus );\n\n}\t/* end of Get_Modem_Status */\n\n\n/***********************************************************************************************\n * NMC::Send_Modem_Command -- Sends an 'AT' command to the modem and gets the response         *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    command to send to modem. e.g. 'ATZ'                                              *\n *           terminator byte for command string                                                *\n *           buffer to put modem response into                                                 *\n *           length of above buffer                                                            *\n *           delay to wait for response                                                        *\n *           number of times to retry when modem doesnt respond                                *\n *                                                                                             *\n * OUTPUT:   input delay less the time it took the modem to respond                            *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:09PM ST : Documented / Win32 support added                                      *\n *=============================================================================================*/\nint NullModemClass::Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries )\n{\n\n#ifdef WIN32\n\treturn (SerialPort->Send_Command_To_Modem(command, terminator, buffer, buflen, delay, retries));\n#else\t//WIN32\n\n\tint status, tmpdelay, retry;\n\tchar tempbuf[81];\n\n\n\t*buffer = 0;\n\n\tfor ( retry = 0; retry < retries; retry++ ) {\n\n\t\tPortKillTime( Port, 100 );\n\n\t\tstatus = HMSendStringNoWait( Port, command, terminator );\n\n\n\t\tif (status < ASSUCCESS) {\n\t\t\treturn( status );\n\t\t}\n\n\t\ttmpdelay = delay;\n\t\twhile ( tmpdelay > 0 ) {\n\n\t\t\ttmpdelay = HMInputLine( Port, tmpdelay, tempbuf, 81 );\n\n\t\t\tif ( strcmp( tempbuf, \"OK\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_OK );\n\t\t\t} else if ( strcmp( tempbuf, \"0\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_0 );\n\t\t\t} else if ( strcmp( tempbuf, \"ERROR\" ) == 0 ) {\n\t\t\t\treturn( MODEM_CMD_ERROR );\n\t\t\t} else if ( tempbuf[0] != 0 ) {\n\t\t\t\tstrncpy( buffer, tempbuf, buflen );\n\t\t\t}\n\t\t}\n\n\t\tPortKillTime( Port, 100 );\n\n\t\t/*\n\t\t**\tSend and extra return to help clear out any problems with the modem (if any).\n\t\t*/\n\t\tHMWaitForOK( 300, NULL );\n\t\tstatus = HMSendString( Port, \"\" );\n\t\tHMWaitForOK( 0, NULL );\n\t}\n\n\treturn( tmpdelay );\n\n#endif\t//WIN32\n}\n\n\n/***********************************************************************************************\n * NMC::Verify_And_Convert_To_Int -- converts a text string of numbers to an int               *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer                                                                     *\n *                                                                                             *\n * OUTPUT:   value of text number in buffer                                                    *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/2/96 3:13PM ST : Documented                                                            *\n *=============================================================================================*/\nint NullModemClass::Verify_And_Convert_To_Int( char *buffer )\n{\n\tint value = 0;\n\tint len = strlen(buffer);\n\n\n\tfor (int i = 0; i < len; i++) {\n\t\tif ( !isdigit( *(buffer + i) ) ) {\n\t\t\tvalue = -1;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (value == 0) {\n\t\tvalue = atoi( buffer );\n\t}\n\n\treturn( value );\n\n}\t/* end of Verify_And_Convert_To_Int */\n\n/*************************** end of nullmgr.cpp ****************************/\n\n#endif"
  },
  {
    "path": "REDALERT/NULLMGR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/NULLMGR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : CONNECT.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 3, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This is the Connection Manager for a NULL-Modem connection.\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NULLMODEM_H\n#define NULLMODEM_H\n\n\n/*\n********************************* Includes **********************************\n*/\n#include \"nullconn.h\"\n#include \"connmgr.h\"\n#include \"commlib.h\"\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass NullModemClass : public ConnManClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\tenum SendModemEnum {\n\t\t\tMODEM_CMD_TIMEOUT = 0,\n\t\t\tMODEM_CMD_OK,\n\t\t\tMODEM_CMD_0,\n\t\t\tMODEM_CMD_ERROR\n\t\t};\n\n\t\tchar *BuildBuf;\n\t\tint MaxLen;\n\n\t\tchar *EchoBuf;\n\t\tint EchoSize;\n\t\tint EchoCount;\n\n\t\tint OldIRQPri;\n\n\t\tint ModemVerboseOn;\n\t\tint ModemEchoOn;\n\t\tint ModemWaitCarrier;\n\t\tint ModemCarrierDetect;\n\t\tint ModemCarrierLoss;\n\t\tint ModemHangupDelay;\n\t\tint ModemGuardTime;\n\t\tchar ModemEscapeCode;\n\n\t\tstatic void (*OrigAbortModemFunc)(int);\n\t\tstatic KeyNumType Input;\n\t\tstatic GadgetClass *Commands;\t\t\t\t\t\t\t// button list\n\n\t\t/*\n\t\t**\tConstructor/destructor.\n\t\t*/\n\t\tNullModemClass (int numsend, int numreceive, int maxlen, unsigned short magicnum);\n\t\tvirtual ~NullModemClass ();\n\n\t\t/*\n\t\t**\tThis is the main initialization routine.\n\t\t*/\n\t\tint Init( int port, int irq, char *dev_name, int baud, char parity, int wordlength, int stopbits, int flowcontrol );\n\t\tint Delete_Connection( void );\n\t\tvirtual int Num_Connections(void);\n\t\tvirtual int Connection_ID(int ) {return (0);}\n\t\tvirtual int Connection_Index(int ) {return (0);}\n\t\tint Init_Send_Queue( void );\n\t\tvoid Shutdown( void );\n\n\t\tvirtual void Set_Timing (unsigned long retrydelta,\n\t\t\tunsigned long maxretries, unsigned long timeout);\n\n\t\t/*\n\t\t**\tThis is how the application sends & receives messages.\n\t\t*/\n\t\tint Send_Message (void *buf, int buflen, int ack_req = 1);\n\t\tint Get_Message (void *buf, int *buflen);\n\n\t\t/*\n\t\t** These are for compatibility\n\t\t*/\n\t\tvirtual int Send_Private_Message (void *buf, int buflen,\n\t\t\tint ack_req = 1, int = CONNECTION_NONE)\n\t\t\t{return (Send_Message(buf,buflen,ack_req));}\n\t\tvirtual int Get_Private_Message (void *buf, int *buflen, int *)\n\t\t\t{return (Get_Message(buf,buflen));}\n\n\t\t/*\n\t\t**\tThe main polling routine; should be called as often as possible.\n\t\t*/\n\t\tvirtual int Service (void);\n\n\t\t/*\n\t\t**\tQueue utility routines.  The application can determine how many\n\t\t**\tmessages are in the send/receive queues, and the queue's average\n\t\t**\tresponse time (in clock ticks).\n\t\t*/\n\t\tint Num_Send(void);\n\t\tint Num_Receive(void);\n\t\tvirtual unsigned long Response_Time(void);\n\t\tvirtual void Reset_Response_Time(void);\n\t\tvoid * Oldest_Send(void);\n\t\tvirtual void Configure_Debug(int index, int type_offset, int type_size,\n\t\t\tchar **names, int namestart, int namecount);\n#ifdef CHEAT_KEYS\n\t\tvirtual void Mono_Debug_Print(int index, int refresh = 0);\n#endif\n\n\t\t/*\n\t\t** These are for compatibility\n\t\t*/\n\t\tvirtual int Global_Num_Send(void) {return (Num_Send());}\n\t\tvirtual int Global_Num_Receive(void) {return (Num_Receive());}\n\t\tvirtual int Private_Num_Send(int = CONNECTION_NONE)\n\t\t\t{return (Num_Send());}\n\t\tvirtual int Private_Num_Receive(int = CONNECTION_NONE)\n\t\t\t{return (Num_Receive());}\n\n\t\tDetectPortType Detect_Port( SerialSettingsType *settings );\n\t\tint Detect_Modem( SerialSettingsType *settings, int reconnect = 0 );\n\t\tDialStatusType Dial_Modem(char *string, DialMethodType method, int reconnect = 0);\n\t\tDialStatusType Answer_Modem(int reconnect = 0);\n\t\tint Hangup_Modem(void);\n\t\tvoid Setup_Modem_Echo(void (*func)(char c));\n\t\tvoid Remove_Modem_Echo(void);\n\t\tvoid Print_EchoBuf(void);\n\t\tvoid Reset_EchoBuf(void);\n\t\tstatic int Abort_Modem(PORT *);\n\t\tvoid Setup_Abort_Modem(void);\n\t\tvoid Remove_Abort_Modem(void);\n\n\t\tint Change_IRQ_Priority(int irq);\n\t\tint Get_Modem_Status(void);\n\t\tint Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries );\n\t\tint Verify_And_Convert_To_Int( char *buffer );\n\n\t/*\n\t**\tPrivate Interface.\n\t*/\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a pointer to the NULL-Modem Connection object.\n\t\t*/\n\t\tNullModemConnClass *Connection;\n\t\tint NumConnections;\t\t\t\t\t\t// # connection objects in use\n\n#ifdef WIN32\n\t\t/*\n\t\t** This is the Win95 port handle\n\t\t*/\n\t\tHANDLE\tPortHandle;\n#else\t//WIN32\n\t\t/*\n\t\t**\tThis is the Greenleaf port handle.\n\t\t*/\n\t\tPORT *Port;\n#endif\t//WIN32\n\n\t\tint NumSend;\n\t\tint NumReceive;\n\t\tunsigned short MagicNum;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for parsing incoming packets.\n\t\t**\tRXSize is the allocated size of the RX buffer.\n\t\t**\tRXCount is the # of characters we currently have in our buffer.\n\t\t*/\n\t\tchar *RXBuf;\n\t\tint RXSize;\n\t\tint RXCount;\n\n\t\t/*.....................................................................\n\t\tTiming parameters for all connections\n\t\t.....................................................................*/\n\t\tunsigned long RetryDelta;\n\t\tunsigned long MaxRetries;\n\t\tunsigned long Timeout;\n\n\t\t/*\n\t\t**\tVarious Statistics\n\t\t*/\n\t\tint SendOverflows;\n\t\tint ReceiveOverflows;\n\t\tint CRCErrors;\n};\n\n#endif\n\n/*************************** end of nullmgr.h ******************************/\n"
  },
  {
    "path": "REDALERT/OBJECT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OBJECT.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OBJECT.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 6, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ObjectClass::AI -- Handles generic object AI processing.                                  *\n *   ObjectClass::Active_Click_With -- Dispatches action on the object specified.              *\n *   ObjectClass::Active_Click_With -- Dispatches action on the specified cell.                *\n *   ObjectClass::Attach_Trigger -- Attach specified trigger to object.                        *\n *   ObjectClass::Can_Demolish -- Queries whether this object can be sold back.                *\n *   ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission?        *\n *   ObjectClass::Can_Player_Move -- Can the player give this object a movement mission?       *\n *   ObjectClass::Can_Repair -- Queries whether this object can be repaired.                   *\n *   ObjectClass::Catch_Fire -- Called when animation is attached to this object.              *\n *   ObjectClass::Center_Coord -- Fetches the center coordinate for the object.                *\n *   ObjectClass::Clicked_As_Target -- Triggers target selection animation.                    *\n *   ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor.       *\n *   ObjectClass::Detach -- Detach the specified target from this object.                      *\n *   ObjectClass::Detach_All -- Removes the object from all tracking systems.                  *\n *   ObjectClass::Do_Shimmer -- Shimmers this object if it is cloaked.                         *\n *   ObjectClass::Docking_Coord -- Fetches the coordinate to dock at this object.              *\n *   ObjectClass::Exit_Coord -- Return with the exit coordinate for this object.               *\n *   ObjectClass::Exit_Object -- Causes the specified object to leave this object.             *\n *   ObjectClass::Fire_Coord -- Fetches the coordinate a projectile will launch from.          *\n *   ObjectClass::Fire_Out -- Informs object that attached animation has finished.             *\n *   ObjectClass::Get_Mission -- Fetches the current mission of this object.                   *\n *   ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object.     *\n *   ObjectClass::Hidden -- Called when this object becomes hidden from the player.            *\n *   ObjectClass::In_Range -- Determines if the coordinate is within weapon range.             *\n *   ObjectClass::In_Which_Layer -- Fetches what layer this object is located in.              *\n *   ObjectClass::Init -- Initializes the basic object system.                                 *\n *   ObjectClass::Limbo -- Brings the object into a state of limbo.                            *\n *   ObjectClass::Look -- Called when this object needs to reveal terrain.                     *\n *   ObjectClass::Mark -- Handles basic marking logic.                                         *\n *   ObjectClass::Mark_For_Redraw -- Marks object and system for redraw.                       *\n *   ObjectClass::Move -- Moves (by force) the object in the desired direction.                *\n *   ObjectClass::Name -- Fetches the identification name of this object.                      *\n *   ObjectClass::ObjectClass -- Default constructor for objects.                              *\n *   ObjectClass::Paradrop -- Unlimbos object in paradrop mode.                                *\n *   ObjectClass::Passive_Click_With -- Right mouse button click process.                      *\n *   ObjectClass::Receive_Message -- Processes an incoming radio message.                      *\n *   ObjectClass::Record_The_Kill -- Records this object as killed by the specified object.    *\n *   ObjectClass::Render -- Displays the object onto the map.                                  *\n *   ObjectClass::Render_Coord -- Fetches the coordinate to draw this object at.               *\n *   ObjectClass::Repair -- Handles object repair control.                                     *\n *   ObjectClass::Revealed -- Reveals this object to the house specified.                      *\n *   ObjectClass::Scatter -- Tries to scatter this object.                                     *\n *   ObjectClass::Select -- Try to make this object the \"selected\" object.                     *\n *   ObjectClass::Sell_Back -- Sells the object -- if possible.                                *\n *   ObjectClass::Sort_Y -- Returns the coordinate used for display order sorting.             *\n *   ObjectClass::Take_Damage -- Applies damage to the object.                                 *\n *   ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target.           *\n *   ObjectClass::Unlimbo -- Brings the object into the game system.                           *\n *   ObjectClass::Unselect -- This will un-select the object if it was selected.               *\n *   ObjectClass::Value -- Fetches the target value of this object.                            *\n *   ObjectClass::Weapon_Range -- Returns the weapon range for the weapon specified.           *\n *   ObjectClass::What_Action -- Determines what action to perform on specified object.        *\n *   ObjectClass::What_Action -- Returns with the action to perform for this object.           *\n *   ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit.                            *\n *   ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels.               *\n *   ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type.    *\n *   ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object.            *\n *   ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects.     *\n *   ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object.           *\n *   ObjectTypeClass::One_Time -- Handles one time processing for object types.                *\n *   ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list.              *\n *   ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object.              *\n *   ObjectTypeClass::Who_Can_Build_Me -- Determine what building can build this object type.  *\n *   ObjectTypeClass::Who_Can_Build_Me -- Finds the factory building that can build this object*\n *   ObjectClass::Get_Image_Data -- Fetches the image data to use for this object.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n\n/*\n**\tSelected objects have a special marking box around them. This is the shapes that are\n**\tused for this purpose.\n*/\nvoid const * ObjectTypeClass::SelectShapes = 0;\n\nvoid const * ObjectTypeClass::PipShapes = 0;\n\n\n\n/***********************************************************************************************\n * ObjectClass::ObjectClass -- Default constructor for objects.                                *\n *                                                                                             *\n *    This is the default constructor for objects. It is called as an inherent part of the     *\n *    construction process for all the normal game objects instantiated. It serves merely to   *\n *    initialize the object values to a common (default) state.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Objects always start in a state of limbo. They must be Unlimbo()ed before they  *\n *             can be used.                                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass::ObjectClass(RTTIType rtti, int id) :\n\tAbstractClass(rtti, id),\n\tIsDown(false),\n\tIsToDamage(false),\n\tIsToDisplay(false),\n\tIsInLimbo(true),\n\tIsSelected(false),\n\tIsAnimAttached(false),\n\tIsFalling(false),\n\tRiser(0),\n\tNext(0),\n\tTrigger(NULL),\n\tStrength(255),\n\tIsSelectedMask(0)\t\t// Mask showing who has selected this object\n{\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Image_Data -- Fetches the image data to use for this object.               *\n *                                                                                             *\n *    This routine will return with a pointer to the image data that should be used when       *\n *    this object is drawn.                                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the shape data for this object.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * ObjectClass::Get_Image_Data(void) const\n{\n\treturn(Class_Of().Get_Image_Data());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Name -- Fetches the identification name of this object.                        *\n *                                                                                             *\n *    This routine will return a pointer to the identifier name for this object. This name     *\n *    is usually short and is used in the INI files to identify this object.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the text identifier name of this object.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * ObjectClass::Name(void) const\n{\n\treturn(Class_Of().Name());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Exit_Coord -- Return with the exit coordinate for this object.                 *\n *                                                                                             *\n *    Ths exit coordinate is the location that a piggy back or newly produced object will      *\n *    appear at when it exits this object. Transports and factory buildings will utilize this  *\n *    routine.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that an object will appear at when exiting this        *\n *          object.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Exit_Coord(void) const\n{\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::AI -- Handles generic object AI processing.                                    *\n *                                                                                             *\n *    This routine is used to handle the AI processing that occurs for all object types.       *\n *    Typically, this isn't much, but there is the concept of falling that all objects can     *\n *    be subjected to (e.g., grenades).                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::AI(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t/*\n\t**\tFalling logic is handled here.\n\t*/\n\tif (IsFalling) {\n\t\tLayerType layer = In_Which_Layer();\n\n\t\tHeight += Riser;\n\t\tif (Height <= 0) {\n\t\t\tHeight = 0;\n\t\t\tIsFalling = false;\n\t\t\tPer_Cell_Process(PCP_END);\n\n\t\t\tShorten_Attached_Anims(this);\n\t\t}\n\t\tif (IsAnimAttached) {\n\t\t\tRiser -= 1;\n\t\t\tRiser = max(Riser, -3);\n\t\t} else {\n\t\t\tRiser -= Rule.Gravity;\n//\t\t\tRiser -= GRAVITY;\n\t\t\tRiser = max(Riser, -100);\n\t\t}\n\n\t\tif (layer != In_Which_Layer()) {\n\t\t\tMap.Remove(this, layer);\n\t\t\tMap.Submit(this, In_Which_Layer());\n\n\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\t\tMap.Place_Down(Coord_Cell(Center_Coord()), this);\n\t\t\t\t} else {\n\t\t\t\t\tMap.Pick_Up(Coord_Cell(Center_Coord()), this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::What_Action -- Determines what action to perform on specified object.          *\n *                                                                                             *\n *    This routine will return that action that this object could perform if the mouse were    *\n *    clicked over the object specified.                                                       *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object to check this object against when determining    *\n *                      the action to perform.                                                 *\n *                                                                                             *\n * OUTPUT:  It returns that action that will be performed if the mouse were clicked over the   *\n *          object. Since non-derived objects cannot do anything, and cannot even be           *\n *          instantiated, this routine will always return ACTION_NONE.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType ObjectClass::What_Action(ObjectClass const *) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::What_Action -- Returns with the action to perform for this object.             *\n *                                                                                             *\n *    This routine is called when information on a potential action if the mouse were clicked  *\n *    on the cell specified. This routine merely serves as a virtual placeholder so that       *\n *    object types that can actually perform some action will override this routine to provide *\n *    true functionality.                                                                      *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the mouse is over and might be clicked on.                  *\n *                                                                                             *\n * OUTPUT:  Returns with the action that this object would try to perform if the mouse were    *\n *          clicked. Since objects at this level have no ability to do anything, this routine  *\n *          will always returns ACTION_NONE unless it is overridden.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nActionType ObjectClass::What_Action(CELL) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(ACTION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::In_Which_Layer -- Fetches what layer this object is located in.                *\n *                                                                                             *\n *    The default layer for object location is the LAYER_GROUND. Aircraft will override this   *\n *    routine and make adjustments as necessary according to the aircraft's altitude.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the layer that this object is located in.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nLayerType ObjectClass::In_Which_Layer(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (Height < (FLIGHT_LEVEL - (FLIGHT_LEVEL/3))) {\n\t\treturn(LAYER_GROUND);\n\t}\n\treturn(LAYER_TOP);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object.       *\n *                                                                                             *\n *    This routine will return the ownable bits for this object. Objects at this level can't   *\n *    really be owned by anyone, but return the full spectrum of legality just to be safe.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the ownable flags (as a combined bitfield) for this object.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Get_Ownable(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Repair -- Queries whether this object can be repaired.                     *\n *                                                                                             *\n *    Most objects cannot be repaired. This routine defaults to returning \"false\", but is      *\n *    overridden by derived functions defined by object types that can support repair.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be repaired?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Repair(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Demolish -- Queries whether this object can be sold back.                  *\n *                                                                                             *\n *    This routine is used to determine if this object can be sold. Most objects cannot be     *\n *    but for those objects that can, this routine will be overridden as necessary.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be sold back? Typically, the answer is no.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Demolish(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\nbool ObjectClass::Can_Demolish_Unit(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\nbool ObjectClass::Can_Capture(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission?          *\n *                                                                                             *\n *    This routine is used to determine if attacking is an option under player control with    *\n *    respect to this unit. This routine will be overridden as necessary for those objects     *\n *    that have the ability to attack.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be given an attack order by the player?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Player_Fire(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Can_Player_Move -- Can the player give this object a movement mission?         *\n *                                                                                             *\n *    This routine is used to determine if the player has the ability to command this object   *\n *    with a movement mission. This routine will be overridden as necessary to support this    *\n *    ability.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Can this object be given a movement mission by the player?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Can_Player_Move(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target.             *\n *                                                                                             *\n *    When the coordinate to use when firing at this object is needed, this routine will       *\n *    provide it. Normal objects just use the center of the object for this, but there are     *\n *    some more sophisticated objects that are not fired upon the center.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate to fire at if this object is a target.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Target_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord_Add(XY_Coord(0, -Height), Center_Coord()));\n//\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Center_Coord -- Fetches the center coordinate for the object.                  *\n *                                                                                             *\n *    This routine will return the center coordinate for the object. The center coordinate is  *\n *    typically the coordinate recorded in the object structure. Exceptions to this include    *\n *    the trees and other terrain elements.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate that is considered the center point of this object.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Center_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Render_Coord -- Fetches the coordinate to draw this object at.                 *\n *                                                                                             *\n *    This routine will return the coordinate to base the drawing of this object's graphic     *\n *    at. This is adjusted according to the nature of the graphic associated with this         *\n *    object.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the coordinate to draw the graphic of this object at.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Render_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Docking_Coord -- Fetches the coordinate to dock at this object.                *\n *                                                                                             *\n *    This routine returns the coordinate that a potential docking object should home in on.   *\n *    Typically, this the center of the object, but in certain cases it is adjusted off center *\n *    according to the object type. An example of this would be the airfield.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that a docking object should head for.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Docking_Coord(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Center_Coord());\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Sort_Y -- Returns the coordinate used for display order sorting.               *\n *                                                                                             *\n *    This routine will return the value to be used for object sorting. The sorting ensures    *\n *    that the object are rendered from a top to bottom order. Certain object use a sorting    *\n *    value different from their center coordinate. This is true if the object \"touches the    *\n *    ground\" at a point that is different from the object's center point.                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the value to use as the Y sorting value.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE ObjectClass::Sort_Y(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Fire_Coord -- Fetches the coordinate a projectile will launch from.            *\n *                                                                                             *\n *    For those objects that fire, the coordinate that the projectile it launches will appear  *\n *    at the location specified by the return value from this function.                        *\n *                                                                                             *\n * INPUT:   which -- Which weapon to consider when determining fire coordinate?                *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the coordinate that a launched projectile will appear at if this      *\n *          object were to fire the weapon specified.                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nFireDataType ObjectClass::Fire_Data(int which) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn{Fire_Coord(which),0};\n}\n\nCOORDINATE ObjectClass::Fire_Coord(int ) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(Coord);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Record_The_Kill -- Records this object as killed by the specified object.      *\n *                                                                                             *\n *    This routine is called when this object is killed. If the source of the death is known,  *\n *    then a pointer to the responsible object is provided as a parameter.                     *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the cause of this unit's death.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Record_The_Kill(TechnoClass * )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Do_Shimmer -- Shimmers this object if it is cloaked.                           *\n *                                                                                             *\n *    When an object is cloaked, there are several conditions that would cause it to shimmer   *\n *    and thus reveal itself. When such a condition arrises, this function is called. If the   *\n *    object is cloaked, then it will shimmer. At this derivation level, cloaking is           *\n *    undefined. Objects that can cloak will override this function as necessary.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Do_Shimmer(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Exit_Object -- Causes the specified object to leave this object.               *\n *                                                                                             *\n *    This routine is called, typically, by a transport building type that requires an object  *\n *    to leave it. This routine will place the object at a suitable location or return         *\n *    a value indicating why not.                                                              *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that wishes to leave this object.                *\n *                                                                                             *\n * OUTPUT:  Returns the success value of the attempt:                                          *\n *             0: Object could not be placed -- ever                                           *\n *             1: Object placement is temporarily delayed -- try again later.                  *\n *             2: Object placement proceeded normally                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Exit_Object(TechnoClass *)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Hidden -- Called when this object becomes hidden from the player.              *\n *                                                                                             *\n *    This routine is called when the object becomes hidden from the player. It can result in  *\n *    lost targeting and tracking abilities with respect to the hidden object.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Hidden(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Look -- Called when this object needs to reveal terrain.                       *\n *                                                                                             *\n *    This routine is called when the object needs to look around the terrain. For player      *\n *    owned objects, the terrain is revealed. For non-player objects, not effect occurs.       *\n *                                                                                             *\n * INPUT:   incremental -- If true, then the looking algorithm will only examine the edges     *\n *                         of the sight range. This is more efficient and work well if the     *\n *                         object has only moved one cell since the last time it has performed *\n *                         the look operation.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This can be a time consuming operation. Call only when necessary.               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Look(bool )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Active_Click_With -- Dispatches action on the object specified.                *\n *                                                                                             *\n *    This routine is called when this object is selected and the mouse was clicked on the     *\n *    tactical map. An action is required from the object. The object that the mouse was       *\n *    over and the tentative action to perform are provided as parameters.                     *\n *                                                                                             *\n * INPUT:   action   -- The requested action to perform with the object specified.             *\n *                                                                                             *\n *          object   -- The object that the action should be performed on. This object is      *\n *                      what the mouse was over when the click occurred.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Active_Click_With(ActionType , ObjectClass *)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Active_Click_With -- Dispatches action on the specified cell.                  *\n *                                                                                             *\n *    This routine will dispatch the action requested upon the cell specified. It is called    *\n *    when the mouse is clicked over a cell while this object is selected.                     *\n *                                                                                             *\n * INPUT:   action   -- The action to perform.                                                 *\n *                                                                                             *\n *          cell     -- The location (cell) to perform this action upon.                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Active_Click_With(ActionType , CELL )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Clicked_As_Target -- Triggers target selection animation.                      *\n *                                                                                             *\n *    This routine is called when this object is the target of some player click action.       *\n *    For more sophisticated object, this will trigger the object to begin flashing a few      *\n *    times. At this level, no action is performed.                                            *\n *                                                                                             *\n * INPUT:   flashes  -- The requested number of times to flash this object.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Clicked_As_Target(HousesType house, int) // 2019/09/20 JAS - Added record of who clicked on the object\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::In_Range -- Determines if the coordinate is within weapon range.               *\n *                                                                                             *\n *    This routine will determine if the specified coordinate is within weapon range.          *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to check to see if it is within weapon range.              *\n *                                                                                             *\n *          which -- The weapon to check against.                                              *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  bool; Is the specified coordinate within weapon range for the weapon type          *\n *                specified?                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::In_Range(COORDINATE , int) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Weapon_Range -- Returns the weapon range for the weapon specified.             *\n *                                                                                             *\n *    This routine will return the weapon range according to the type of weapon specified.     *\n *                                                                                             *\n * INPUT:   which -- The weapon to fetch the range from.                                       *\n *                   0: primary weapon                                                         *\n *                   1: secondary weapon                                                       *\n *                                                                                             *\n * OUTPUT:  Returns with the range (in leptons) of the weapon specified.                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Weapon_Range(int) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Scatter -- Tries to scatter this object.                                       *\n *                                                                                             *\n *    This routine is used when the object should scatter from its current location. It        *\n *    applies to units that have the ability to move.                                          *\n *                                                                                             *\n * INPUT:   coord -- The source of the threat that is causing the scatter.                     *\n *                                                                                             *\n *          forced-- Whether this scatter attempt is serious and scattering should occur       *\n *                   regardless of what is doing now.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This may or may not cause the object to scatter. It is merely a request to the  *\n *             object that it would be good if it were to scatter.                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Scatter(COORDINATE , bool, bool)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Catch_Fire -- Called when animation is attached to this object.                *\n *                                                                                             *\n *    This routine is called when an animation is attached to this object. It might be a       *\n *    fire animation (hence the name), but it might also be smoke or any other animation       *\n *    as well.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object caught on fire by this routine? Actually, this is really      *\n *                the answer to this question; \"Is this animation attaching to this object     *\n *                that doesn't already have an animation attached?\"                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Catch_Fire(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn false;\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Fire_Out -- Informs object that attached animation has finished.               *\n *                                                                                             *\n *    This routine is called if there is an attached animation on this object and that         *\n *    animation has finished. Typically, this is necessary for when trees are on fire.         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Fire_Out(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Value -- Fetches the target value of this object.                              *\n *                                                                                             *\n *    This routine will return the target value of this object. The higher the number, the     *\n *    better the object will be as a target. This routine is called when searching for         *\n *    targets. Generic objects have no target potential, and this routine returns zero to      *\n *    reflect that. Other object types will override this routine to return the appropriate    *\n *    target value.                                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the value of this object as a target. Higher values mean better       *\n *          target.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectClass::Value(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Get_Mission -- Fetches the current mission of this object.                     *\n *                                                                                             *\n *    Generic objects don't have a mission, so this routine will just return MISSION_NONE.     *\n *    However, techno objects do have a mission and this routine is overloaded to handle       *\n *    those objects in order to return the correct mission value.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current mission being followed by this object.                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nMissionType ObjectClass::Get_Mission(void) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(MISSION_NONE);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Repair -- Handles object repair control.                                       *\n *                                                                                             *\n *    This routine will control object repair mode. At the object level, no repair is          *\n *    possible, so it is expected that any object that can repair will override this function  *\n *    as necessary.                                                                            *\n *                                                                                             *\n * INPUT:   control  -- The repair control parameter.                                          *\n *                      0  = turn repair off                                                   *\n *                      1  = turn repair on                                                    *\n *                      -1 = toggle repair state                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Repair(int )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Sell_Back -- Sells the object -- if possible.                                  *\n *                                                                                             *\n *    This routine is called to sell back the object. Override this routine for the more       *\n *    sophisticated objects that can actually be sold back. Normal objects can't be sold and   *\n *    this routine does nothing as a consequence.                                              *\n *                                                                                             *\n * INPUT:   control  -- How to control the sell state of this object.                          *\n *                      0  = stop selling.                                                     *\n *                      1  = start selling.                                                    *\n *                      -1 = toggle selling state.                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Sell_Back(int )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Move -- Moves (by force) the object in the desired direction.                  *\n *                                                                                             *\n *    This routine will instantly move the object one cell in the specified direction. It      *\n *    moves the object by force. This is typically ONLY used by the scenario editor            *\n *    process.                                                                                 *\n *                                                                                             *\n * INPUT:   facing   -- The direction to move the object.                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Naturally, this can cause illegal placement situations -- use with caution.     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Move(FacingType facing)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tCOORDINATE\tcoord;\n\n\tMark(MARK_UP);\n\tcoord = Adjacent_Cell(Coord, facing);\n\tif (Can_Enter_Cell(Coord_Cell(coord)) == MOVE_OK) {\n\t\tCoord = coord;\n\t}\n\tMark(MARK_DOWN);\n}\n\n\n// Object selection list is switched with player context for GlyphX. ST - 4/17/2019 9:42AM\nextern void Logic_Switch_Player_Context(ObjectClass *object);\n\n/***********************************************************************************************\n * ObjectClass::Unselect -- This will un-select the object if it was selected.                 *\n *                                                                                             *\n *    This routine brings a currently selected object into an unselected state. This is        *\n *    needed when another object becomes selected as well as if the object is destroyed.       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Unselect(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t//if (IsSelected) { \n\t// Updated to function for multiplayer - 6/26/2019 JAS\n\tif (Is_Selected_By_Player()) {\n\t\t\n\t\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_UP);\n\t\t\n\t\tIsSelected = false;\n\t\t\n\t\t// Updated to function for multiplayer - 6/26/2019 JAS\n\t\tSet_Unselected_By_Player();\n\t\t\n\t\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_DOWN);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Unselect_All_Players --\tThis will un-select the object if it was selected    *\n *\t\t\t\t\t\t\t\t\t\t\tfrom all players\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n *    This routine brings a currently selected object into an unselected state for all players.*\n *\t\tThis is needed when  the object is destroyed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/2019 JAS : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Unselect_All_Players(void)\n{\n\tCurrentObject.Delete_All(this);\n\n\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\tMark(MARK_OVERLAP_UP);\n\t}\n\n\tIsSelected = false;\n\tIsSelectedMask = 0;\n\n\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n}\n\n/***********************************************************************************************\n * ObjectClass::Unselect_All_Players_Except_Owner --\tThis will un-select the object if it was *\n *\t\t\t\t\t\t\t\t\t\t\tselected for all players except for the object's owner\t\t  *\n *                                                                                             *\n *    This routine brings a currently selected object into an unselected state for all players.*\n *\t\tThis is needed when the object cloaks.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/28/2019 JAS : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Unselect_All_Players_Except_Owner(void)\n{\n\tCurrentObject.Delete_All_Except(this, Owner());\n\n\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\tMark(MARK_OVERLAP_UP);\n\t}\n\n\tint owner_mask = 1 << Owner();\n\tif (IsSelectedMask & owner_mask)\n\t{\n\t\tIsSelected = true;\n\t\tIsSelectedMask = owner_mask;\n\t}\n\telse\n\t{\n\t\tIsSelected = false;\n\t\tIsSelectedMask = 0;\n\t}\n\n\tif (In_Which_Layer() == LAYER_GROUND) {\n\t\tMark(MARK_OVERLAP_DOWN);\n\t}\n}\n\n/***********************************************************************************************\n * ObjectClass::Select -- Try to make this object the \"selected\" object.                       *\n *                                                                                             *\n *    This routine is used to make this object into the one that is \"selected\". A selected     *\n *    object usually displays a floating bar graph and is available to be given orders from    *\n *    the player's I/O.                                                                        *\n *                                                                                             *\n * INPUT:   allow_mixed -- Allow a mix of player and non-player controlled units?              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *   06/12/1995 JLB : Cannot select a loaner object.                                           *\n *   07/23/1995 JLB : Adds to head or tail depending on leader type flag.                      *\n *=============================================================================================*/\nbool ObjectClass::Select(bool allow_mixed)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t//if (!Debug_Map && (IsSelected || !Class_Of().IsSelectable)) {\n\t//\treturn(false);\n\t//}\n\t// Updated to function for multiplayer - 6/26/2019 JAS\n\tif (!Debug_Map && (Is_Selected_By_Player() || !Class_Of().IsSelectable)) {\n\t\treturn(false);\n\t}\n\n\tif (!Debug_Map && Can_Player_Move() && Is_Techno() && ((TechnoClass *)this)->IsALoaner) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tDon't allow selection if the object is still in the air.\n\t*/\n\tif (Height > 0 && (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL || What_Am_I() == RTTI_INFANTRY)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tDon't allow selection of object when in building placement mode.\n\t*/\n\tif (Map.PendingObject) {\n\t\treturn(false);\n\t}\n\n\tif (!allow_mixed) {\n\t\t/*\n\t\t**\tIf selecting an object of a different house than the player's, make sure that\n\t\t**\tthe entire selection list is cleared.\n\t\t*/\n\t\tfor (int i = 0; i < CurrentObject.Count(); i++) {\n\t\t\tHouseClass * tryhptr = HouseClass::As_Pointer(Owner());\n\t\t\tHouseClass * oldhptr = HouseClass::As_Pointer(CurrentObject[i]->Owner());\n\t//\t\tif (Owner() != CurrentObject[0]->Owner() || CurrentObject[0]->Owner() != PlayerPtr->Class->House) {\n\t\t\tif (oldhptr->IsPlayerControl != tryhptr->IsPlayerControl) {\n\t\t\t\tUnselect_All();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_UP);\n\n\t//IsSelected = true;\n\t// Updated to function for multiplayer - 6/26/2019 JAS\n\tSet_Selected_By_Player();\n\t\n\tif (In_Which_Layer() == LAYER_GROUND) Mark(MARK_OVERLAP_DOWN);\n\t\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Render -- Displays the object onto the map.                                    *\n *                                                                                             *\n *    This routine will determine the location of the object and if it is roughly on the       *\n *    visible screen, it will display it. Not displaying objects that are not on the screen    *\n *    will save valuable time.                                                                 *\n *                                                                                             *\n * INPUT:   bool; Should the render be forced regardless of whether the object is flagged to   *\n *                be redrawn?                                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the draw code called for this object?                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/19/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Render(bool forced) const\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tint\tx, y;\n\tCOORDINATE coord = Render_Coord();\n\tCELL cell = Coord_Cell(coord);\n\n\tif (Debug_Map || Debug_Unshroud || ((forced || IsToDisplay) && IsDown && !IsInLimbo)) {\n\t\tconst_cast<ObjectClass*>(this)->IsToDisplay = false;\t\t// added const_cast ST - 5/9/2019\n\n\t\tif (Map.Coord_To_Pixel(coord, x, y)) {\n\n\t\t\t/*\n\t\t\t**\tDraw the object itself\n\t\t\t*/\n\t\t\tDraw_It(x, y, WINDOW_TACTICAL);\n\n#ifdef SCENARIO_EDITOR\n\t\t\t/*\n\t\t\t**\tDraw the trigger attached to the object. Draw_It is window-\n\t\t\t**\trelative, so add the window's x-coord to 'x'.\n\t\t\t*/\n\t\t\tif (Debug_Map && Trigger.Is_Valid()) {\n\t\t\t\tFancy_Text_Print(Trigger->Class->IniName,\n\t\t\t\t\tx + (WinX), y,\n\t\t\t\t\t&ColorRemaps[PCOLOR_RED], TBLACK,\n\t\t\t\t\tTPF_CENTER | TPF_NOSHADOW | TPF_6POINT);\n\t\t\t}\n#endif\n\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor.         *\n *                                                                                             *\n *    This routine is used to display the current status of the object class to the mono       *\n *    monitor.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Debug_Dump(MonoClass * mono) const\n{\n\tmono->Set_Cursor(1, 1);mono->Printf(\"%-18.18s\", Text_String(Full_Name()));\n\tif (Next != NULL) {\n\t\tmono->Set_Cursor(20, 5);mono->Printf(\"%08X\", Next->As_Target());\n\t}\n\tif (Trigger.Is_Valid()) {\n\t\tmono->Text_Print(Trigger->Class->IniName, 11, 3);\n\t}\n\tmono->Set_Cursor(34, 1);mono->Printf(\"%3d\", Strength);\n\n\tmono->Fill_Attrib(1, 13, 12, 1, IsDown ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 14, 12, 1, IsToDamage ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 15, 12, 1, IsToDisplay ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(1, 16, 12, 1, IsInLimbo ? MonoClass::INVERSE : MonoClass::NORMAL);\n\t// Updated to function for multiplayer - 6/26/2019 JAS\n\tmono->Fill_Attrib(1, 17, 12, 1, Is_Selected_By_Player() ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Fill_Attrib(14, 13, 12, 1, IsAnimAttached ? MonoClass::INVERSE : MonoClass::NORMAL);\n\tmono->Set_Cursor(23, 14);mono->Printf(\"%d\", Riser);\n\tmono->Fill_Attrib(14, 12, 14, 1, IsFalling ? MonoClass::INVERSE : MonoClass::NORMAL);\n\n\tAbstractClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * ObjectClass::Mark_For_Redraw -- Marks object and system for redraw.                         *\n *                                                                                             *\n *    This routine will mark the object and inform the display system                          *\n *    that appropriate rendering is needed. Whenever it is determined                          *\n *    that an object needs to be redrawn, call this routine.                                   *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   This is a subordinate function to the function Mark(). If an object needs to    *\n *             be redrawn it is probably better to call the function Mark(MARK_CHANGE) rather  *\n *             than this function. This function does not inform the map system that           *\n *             overlapping objects are to be redrawn and thus unless you are really sure that  *\n *             this routine should be called, don't.                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Flags map and flags unit only.                                           *\n *=============================================================================================*/\nvoid ObjectClass::Mark_For_Redraw(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (!IsToDisplay) {\n\t\tIsToDisplay = true;\n\n\t\t/*\n\t\t**\tThis tells the map rendering logic to \"go through the motions\" and call the\n\t\t**\trendering function. In the rendering function, it will sort out what gets\n\t\t**\trendered and what doesn't.\n\t\t*/\n\t\tMap.Flag_To_Redraw(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Limbo -- Brings the object into a state of limbo.                              *\n *                                                                                             *\n *    An object brought into a state of limbo by this routine can be safely deleted. This      *\n *    routine will remove the object from all game lists and tracking systems. It is called    *\n *    prior to deleting the object or placing the object \"on ice\".                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully placed in limbo?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Limbo(void)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (GameActive && !IsInLimbo) {\n\n\t\t//Unselect();\n\t\t// Updated to function for multiplayer - 6/26/2019 JAS\n\t\tUnselect_All_Players();\n\n\t\tDetach_All();\n\t\tMark(MARK_UP);\n\n\t\t/*\n\t\t**\tRemove the object from the appropriate display list.\n\t\t*/\n\t\tMap.Remove(this, In_Which_Layer());\n\n\t\t/*\n\t\t**\tRemove the object from the logic processing list.\n\t\t*/\n\t\tif (Class_Of().IsSentient) {\n\t\t\tLogic.Delete(this);\n\t\t}\n\n\t\tHidden();\n\t\tIsInLimbo = true;\n\t\tIsToDisplay = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Unlimbo -- Brings the object into the game system.                             *\n *                                                                                             *\n *    This routine will place the object into the game tracking and display systems. It is     *\n *    called as a consequence of creating the object. Every game object must be unlimboed at   *\n *    some point.                                                                              *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to place the object into the game system.                  *\n *                                                                                             *\n *          dir (optional) -- initial facing direction for this object                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the game object successfully unlimboed?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Sets object strength.                                                    *\n *=============================================================================================*/\nbool ObjectClass::Unlimbo(COORDINATE coord, DirType )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\tif (GameActive && IsInLimbo && !IsDown) {\n\t\tif (ScenarioInit || Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {\n\t\t\tIsInLimbo = false;\n\t\t\tIsToDisplay = false;\n\t\t\tCoord = Class_Of().Coord_Fixup(coord);\n\n\t\t\tif (Mark(MARK_DOWN)) {\n\t\t\t\tif (IsActive) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdd the object to the appropriate map layer. This layer is used\n\t\t\t\t\t**\tfor rendering purposes.\n\t\t\t\t\t*/\n\t\t\t\t\tif (In_Which_Layer() != LAYER_NONE) {\n\t\t\t\t\t\tMap.Submit(this, In_Which_Layer());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Class_Of().IsSentient) {\n\t\t\t\t\t\tLogic.Submit(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Detach -- Detach the specified target from this object.                        *\n *                                                                                             *\n *    This routine is called when the object (as specified) is to be removed from the game     *\n *    engine and thus, all references to it must be severed. Typically, the only thing         *\n *    checked for at this level is the attached trigger.                                       *\n *                                                                                             *\n * INPUT:   target   -- The target that will be removed from the game system.                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Detach(TARGET target, bool )\n{\n\tif (Trigger.Is_Valid() && Is_Target_Trigger(target) && Trigger->As_Target() == target) {\n\t\tAttach_Trigger(NULL);\n\t}\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Detach_All -- Removes the object from all tracking systems.                    *\n *                                                                                             *\n *    This routine will take the object and see that it is removed from all miscellaneous      *\n *    tracking systems in the game. This operation is vital when deleting an object. It is     *\n *    necessary so that when the object is removed from the game, existing game objects won't  *\n *    be referencing a now invalid game object. This typically affects the targeting           *\n *    and navigation computers of other game objects.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Detach_All(bool all)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\t/*\n\t**\tUnselect this object if it was selected.\n\t*/\n\t//if (all || Owner() != PlayerPtr->Class->House) {\n\t//\tUnselect();\n\t//}\n\n\t//Added some error handling incase there was an issue removing the object - JAS 6/28/2019\n\tif (all) {\n\t\t//Unselect();\n\t\t// Updated to function for multiplayer - 6/28/2019 JAS\n\t\tUnselect_All_Players();\n\t}\n\telse\n\t{\n\t\tUnselect_All_Players_Except_Owner();\n\t}\n\t//End of change - JAS 6/28/2019\n\n\tMap.Detach(this);\n\n\t/*\n\t**\tRemove from targeting computers.\n\t*/\n\tDetach_This_From_All(As_Target(), all);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Receive_Message -- Processes an incoming radio message.                        *\n *                                                                                             *\n *    Any radio message received that applies to objects in general are handled by this        *\n *    routine. Typically, this is the \"redraw\" message, which occurs when another object is    *\n *    loading or unloading and thus overlapping.                                               *\n *                                                                                             *\n * INPUT:   message  -- The message received.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the appropriate radio response. If the message was recognized, then   *\n *          RADIO_ROGER is returned, otherwise, just RADIO_STATIC is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType ObjectClass::Receive_Message(RadioClass *, RadioMessageType message, long & )\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tswitch (message) {\n\n\t\t/*\n\t\t**\tThis message serves as a rendering convenience. It lets the system\n\t\t**\tknow that there might be a visual conflict and the unit in radio\n\t\t**\tcontact should be redrawn. This typically occurs when a vehicle\n\t\t**\tis being unloaded from a hover lander.\n\t\t*/\n\t\tcase RADIO_REDRAW:\n\t\t\tMark(MARK_CHANGE);\n\t\t\treturn(RADIO_ROGER);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(RADIO_STATIC);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Take_Damage -- Applies damage to the object.                                   *\n *                                                                                             *\n *    This routine applies damage to the object according to the damage parameters. It handles *\n *    reducing the strength of the object and also returns the result of that damage. The      *\n *    result value can be examined to determine if the object was destroyed, greatly damaged,  *\n *    or other results.                                                                        *\n *                                                                                             *\n * INPUT:   damage   -- Reference to the damage number to apply. This number will be adjusted  *\n *                      according to defensive armor and distance. Examine this value after    *\n *                      the call to determine the actual amount of damage applied.             *\n *                                                                                             *\n *          distance -- The distance (in leptons) from the center of the damage causing        *\n *                      explosion to the object itself.                                        *\n *                                                                                             *\n *          warhead  -- The warhead type that is causing the damage.                           *\n *                                                                                             *\n *          source   -- The perpetrator of this damage.                                        *\n *                                                                                             *\n *          forced   -- Is the damage forced upon the object regardless of whether it          *\n *                      is normally immune?                                                    *\n *                                                                                             *\n * OUTPUT:  Returns the ResultType that indicates what the affect of the damage was.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/29/1994 JLB : Created.                                                                 *\n *   12/27/1994 JLB : Trigger event processing for attacked or destroyed.                      *\n *   01/01/1995 JLB : Reduces damage greatly depending on range.                               *\n *=============================================================================================*/\nResultType ObjectClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tResultType result = RESULT_NONE;\n\tint oldstrength = Strength;\n\n\tif (oldstrength && damage != 0 && (forced || !Class_Of().IsImmune)) {\n\t\tint maxstrength = Class_Of().MaxStrength;\n\n\t\t/*\n\t\t**\tModify damage based on the warhead type and the armor of the object. This results\n\t\t**\tin a reduced damage value, but never below 1 damage point.  Unless\n\t\t** it's forced damage, in which case we want full damage.\n\t\t*/\n\t\tif (!forced /*&& damage > 0*/) {\n\t\t\tdamage = Modify_Damage(damage, warhead, Class_Of().Armor, distance);\n\n\t\t\t/*\n\t\t\t**\tSpecial hack to ensure that dogs only do damage to intended victim and no\n\t\t\t**\tdamage to others.\n\t\t\t*/\n\t\t\tif (source && source->What_Am_I() == RTTI_INFANTRY && ((InfantryClass *)source)->Class->IsDog) {\n\t\t\t\tif (source->TarCom == As_Target()) {\n\t\t\t\t\tdamage = Strength;\n\t\t\t\t} else {\n\t\t\t\t\tdamage = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (damage == 0) return(RESULT_NONE);\n\n\t\t/*\n\t\t** Are we healing/repairing?  If so, add strength, but in\n\t\t** any case, return that no damage was done.\n\t\t*/\n\t\tif (damage < 0) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_AIRCRAFT) {\n#else\n\t\t\tif (What_Am_I() == RTTI_INFANTRY) {\n#endif\n\t\t\t\tClicked_As_Target(PlayerPtr->Class->House, 7); // 2019/09/20 JAS - Added record of who clicked on the object\n\t\t\t\tStrength -= damage;\n\t\t\t\tif (Strength > maxstrength) {\n\t\t\t\t\tStrength = maxstrength;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn(RESULT_NONE);\n\t\t}\n\n\t\t/*\n\t\t**\tAt this point, we KNOW that at least light damage has occurred.\n\t\t*/\n\t\tresult = RESULT_LIGHT;\n\n\t\t/*\n\t\t**\tA non-fatal blow has occurred. Check to see if the object transitioned to below\n\t\t**\thalf strength or if it is now down to one hit point.\n\t\t*/\n\t\tif (oldstrength > damage) {\n\n\t\t\tif (oldstrength >= (maxstrength >> 1) && (oldstrength-damage) < (maxstrength >> 1)) {\n\t\t\t\tresult = RESULT_HALF;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tWhen an object is damaged to destruction, it will instead stop at one\n\t\t\t**\tdamage point. This will prolong the damage state as well as\n\t\t\t**\tgive greater satisfaction when it is finally destroyed.\n\t\t\t*/\n\t\t\tdamage = oldstrength;\n\t\t}\n\n\t\t/*\n\t\t**\tApply the damage to the object.\n\t\t*/\n\t\tStrength = oldstrength - damage;\n\n\t\t/*\n\t\t**\tCheck to see if the object is majorly damaged or destroyed.\n\t\t*/\n\t\tswitch (Strength) {\n\t\t\tcase 0:\n\t\t\t\tRecord_The_Kill(source);\n\t\t\t\tresult = RESULT_DESTROYED;\n\t\t\t\tif (this->Is_Techno()) {\n\t\t\t\t\tif (this == ::As_Object(((TechnoClass *)this)->House->UnitToTeleport)) ((TechnoClass *)this)->House->UnitToTeleport = 0;\n\t\t\t\t}\n\t\t\t\tDetach_All();\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\tresult = RESULT_MAJOR;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tHandle any trigger event associated with this object.\n\t\t*/\n\t\tif (source && Trigger.Is_Valid() && result != RESULT_DESTROYED) {\n\t\t\tTrigger->Spring(TEVENT_ATTACKED, this);\n\t\t}\n\n\t\t/*\n\t\t**\tIf any damage was assessed and this object is selected, then flag\n\t\t**\tthe object to be redrawn so that the health bar will be updated.\n\t\t*/\n\t\t//if (result != RESULT_NONE && IsSelected) {\n\t\t// Updated to function for multiplayer - 6/26/2019 JAS\n\t\tif (result != RESULT_NONE && Is_Selected_By_Player()) {\t\t\t\n\t\t\tMark(MARK_CHANGE);\n\t\t}\n\t}\n\n\t/*\n\t**\tReturn with the result of the damage taken.\n\t*/\n\treturn(result);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Mark -- Handles basic marking logic.                                           *\n *                                                                                             *\n *    This routine handles the base logic for marking an object up or down on the map. It      *\n *    manages the IsDown flag as well as flagging the object to be redrawn if necessary.       *\n *    Whenever an object is to be marked, it should call this base class function first. If    *\n *    this function returns true, then the higher level function should proceed with its own   *\n *    logic.                                                                                   *\n *                                                                                             *\n * INPUT:   mark  -- The marking method to use for this object. It can be either MARK_DOWN,    *\n *                   MARK_UP, or MARK_CHANGE.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the object marked successfully?                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Mark(MarkType mark)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tif (!IsInLimbo && IsActive) {\n\n\t\t/*\n\t\t**\tA mark for change is always successful UNLESS the object\n\t\t**\tis not placed down or has already been flagged as changed\n\t\t**\tthis game frame.\n\t\t*/\n\t\tif (mark == MARK_CHANGE || mark == MARK_CHANGE_REDRAW) {\n\t\t\tif (IsToDisplay && mark != MARK_CHANGE_REDRAW) return(false);\n\t\t\tif (IsDown) {\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\treturn(false);\n\t\t}\n\n\t\t/*\n\t\t** Handle adding or removing the object in the cells' overlap lists\n\t\t*/\n\t\tif (mark == MARK_OVERLAP_UP) {\n\t\t\tif (IsDown == true) {\n\t\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\t\t}\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t\tif (mark == MARK_OVERLAP_DOWN) {\n\t\t\tif (IsDown == true) {\n\t\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\t\tMap.Overlap_Down(Coord_Cell(Coord), this);\n\t\t\t\t}\n\t\t\t\tMark_For_Redraw();\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** It is important to know whether the object is a techno class\n\t\t** or not to see if we have to adjust the regional threat ratings\n\t\t*/\n\t\tint threat = 0;\n\t\tHousesType house = HOUSE_NONE;\n\t\tCELL cell = 0;\n\t\tTechnoClass * tech;\n\t\tif (Is_Techno()) {\n\t\t\ttech \t = (TechnoClass *)this;\n\t\t\tthreat = tech->Risk();\n\t\t\thouse  = tech->Owner();\n\t\t\tcell   = Coord_Cell(Coord);\n\t\t} else {\n\t\t\ttech = NULL;\n\t\t}\n\n\t\t/*\n\t\t**\tMarking down is only successful if the object isn't already\n\t\t**\tplaced down.\n\t\t*/\n\t\tif (mark == MARK_DOWN && !IsDown) {\n\t\t\tif (tech && Session.Type == GAME_NORMAL && In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\tMap[cell].Adjust_Threat(house, threat);\n\t\t\t}\n\t\t\tIsDown = true;\n\t\t\tMark_For_Redraw();\n\t\t\treturn(true);\n\t\t}\n\n\t\t/*\n\t\t**\tLifting up is only successful if the object isn't already\n\t\t**\tlifted up from the map.\n\t\t*/\n\t\tif (mark == MARK_UP && IsDown) {\n\t\t\tif (tech && Session.Type == GAME_NORMAL && In_Which_Layer() == LAYER_GROUND) {\n\t\t\t\tMap[cell].Adjust_Threat(house, -threat);\n\t\t\t}\n\t\t\tif (Class_Of().IsFootprint) {\n\t\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\t}\n\t\t\tIsDown = false;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Init -- Initializes the basic object system.                                   *\n *                                                                                             *\n *    This routine should be called when the basic object system needs to be initialized. This *\n *    occurs when the scenario is about to be loaded.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectClass::Init(void)\n{\n\tCurrentObject.Clear_All();\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Revealed -- Reveals this object to the house specified.                        *\n *                                                                                             *\n *    This routine is called when this object gets revealed to the house specified.            *\n *                                                                                             *\n * INPUT:   house -- Pointer to the house that this object is being revealed to.               *\n *                                                                                             *\n * OUTPUT:  Was this object revealed for the first time to this house? Generic objects always  *\n *          return true unless an invalid house pointer was specified.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Revealed(HouseClass * house)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\treturn(house != NULL);\n}\n\n\n\n\n/***********************************************************************************************\n * ObjectClass::Set_Selected_By_Player -- Set this object as selected by the given player or   *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\tthe default player.\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   Player pointer                                                                     *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   6/25/2019 - JAS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid ObjectClass::Set_Selected_By_Player(HouseClass *player)\n{\n\tif (!player || !player->Class) {\n\t\tplayer = PlayerPtr;\n\t}\n\n\tHousesType house = player->Class->House;\n\tif (((TechnoTypeClass const &)Class_Of()).IsLeader) {\n\t\tCurrentObject.Add_Head(house, this);\n\t}\n\telse {\n\t\tCurrentObject.Add(house, this);\n\t}\n\n\tint shift = (int)house;\n\tIsSelectedMask |= (1 << shift);\n\n\tif (Session.Type == GAME_NORMAL && player == PlayerPtr) {\n\t\tIsSelected = true;\n\t}\n}\n\n/***********************************************************************************************\n * ObjectClass::Set_Unselected_By_Player -- Set this object as unselected by the given player  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\torthe default player.\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:   Player pointer                                                                     *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   6/25/2019 - JAS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=============================================================================================*/\nvoid ObjectClass::Set_Unselected_By_Player(HouseClass *player)\n{\n\tif (!player || !player->Class) {\n\t\tplayer = PlayerPtr;\n\t}\n\n\tHousesType house = player->Class->House;\n\tCurrentObject.Delete(house, this);\n\n\tint shift = (int)house;\n\tIsSelectedMask &= ~(1 << shift);\n\n\tif (Session.Type == GAME_NORMAL && player == PlayerPtr) {\n\t\tIsSelected = false;\n\t}\n}\n\n/***********************************************************************************************\n * ObjectClass::Is_Selected_By_Player -- Has this object been selected by the given player\t  *\n *                                                                                             *\n * INPUT:   Player pointer                                                                     *\n *                                                                                             *\n * OUTPUT:  True if selected by that player                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   6/25/2019\t- JAS \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *=============================================================================================*/\nbool ObjectClass::Is_Selected_By_Player(HouseClass *player) const\n{\n\tif (player && player->Class) {\n\t\tint shift = (int)player->Class->House;\n\t\treturn (IsSelectedMask & (1 << shift)) ? true : false;\n\t}\n\telse {\n\t\tint shift = (int)PlayerPtr->Class->House;\n\t\treturn (IsSelectedMask & (1 << shift)) ? true : false;\n\t}\n\treturn false;\n}\n\n\n\n\n/***********************************************************************************************\n * ObjectClass::Paradrop -- Unlimbos object in paradrop mode.                                  *\n *                                                                                             *\n *    Call this routine as a replacement for Unlimbo() if the object is to be paradropped onto *\n *    the playing field.                                                                       *\n *                                                                                             *\n * INPUT:   coord -- The desired landing coordinate to give the dropping unit.                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully unlimboed and has begun paradropping?            *\n *                                                                                             *\n * WARNINGS:   The unit may not be successful in paradropping if the desired destination       *\n *             location cannot be occupied by the object.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Paradrop(COORDINATE coord)\n{\n\tassert(this != 0);\n\tassert(IsActive);\n\n\tHeight = FLIGHT_LEVEL;\n\tIsFalling = true;\n\tif (Unlimbo(coord, DIR_S)) {\n\t\tAnimClass * anim = NULL;\n\n\t\tif (What_Am_I() == RTTI_BULLET) {\n\t\t\tanim = new AnimClass(ANIM_PARA_BOMB, Coord_Move(Center_Coord(), DIR_N, 0x0030 + Height));\n\t\t} else {\n\t\t\tanim = new AnimClass(ANIM_PARACHUTE, Coord_Move(Center_Coord(), DIR_N, 0x0030 + Height));\n\t\t}\n\n\t\t/*\n\t\t**\tIf the animation was created, then attach it to this object.\n\t\t*/\n\t\tif (anim != NULL) {\n\t\t\tanim->Attach_To(this);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * ObjectClass::Attach_Trigger -- Attach specified trigger to object.                          *\n *                                                                                             *\n *    This routine is used to attach the specified trigger to the object.                      *\n *                                                                                             *\n * INPUT:   trigger  -- Pointer to the trigger to attach. If any existing trigger is desired   *\n *                      to be detached, then pass NULL to this routine.                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the trigger attached?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ObjectClass::Attach_Trigger(TriggerClass * trigger)\n{\n\tif (Trigger.Is_Valid()) {\n\t\tTriggerClass * tptr = Trigger;\n\t\ttptr->AttachCount--;\n\t\tTrigger = NULL;\n\t}\n\n\tif (trigger) {\n\t\tTrigger = trigger;\n\t\ttrigger->AttachCount++;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n// These can't be made inline (for various reasons).\nshort const * ObjectClass::Occupy_List(bool placement) const {return(Class_Of().Occupy_List(placement));};\nshort const * ObjectClass::Overlap_List(bool ) const {return(Class_Of().Overlap_List());};\nBuildingClass * ObjectClass::Who_Can_Build_Me(bool intheory, bool legal) const {return(Class_Of().Who_Can_Build_Me(intheory, legal, Owner()));};\nfixed ObjectClass::Health_Ratio(void) const {return(fixed(Strength, Class_Of().MaxStrength));};\nint ObjectClass::Full_Name(void) const {return Class_Of().Full_Name();};\n\n\n//**********************************************************************************************\n// MODULE SEPARATION -- ObjectTypeClass member functions follow.\n//**********************************************************************************************\n\n\n/***********************************************************************************************\n * ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects.       *\n *                                                                                             *\n *    This is the base constructor that is used when constructing the object type classes.     *\n *    Every tangible game piece type calls this constructor for the ObjectTypeClass. This      *\n *    class holds static information that is common to objects in general.                     *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/23/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectTypeClass::ObjectTypeClass(\n\t\t\t\t\t\tRTTIType rtti,\n\t\t\t\t\t\tint id,\n\t\t\t\t\t\tbool is_sentient,\n\t\t\t\t\t\tbool is_stealthy,\n\t\t\t\t\t\tbool is_selectable,\n\t\t\t\t\t\tbool is_legal_target,\n\t\t\t\t\t\tbool is_insignificant,\n\t\t\t\t\t\tbool is_immune,\n\t\t\t\t\t\tbool is_footprint,\n\t\t\t\t\t\tint name,\n\t\t\t\t\t\tchar const * ini) :\n\tAbstractTypeClass(rtti, id, name, ini),\n\tIsCrushable(false),\n\tIsStealthy(is_stealthy),\n\tIsSelectable(is_selectable),\n\tIsLegalTarget(is_legal_target),\n\tIsInsignificant(is_insignificant),\n\tIsImmune(is_immune),\n\tIsSentient(is_sentient),\n\tIsFootprint(is_footprint),\n\tArmor(ARMOR_NONE),\n\tMaxStrength(0),\n\tImageData(0),\n\tRadarIcon(0)\n{\n\t/*\n\t** Init the DimensionData rect. Not sure how this was ever working before without being allocated. It was just trashing\n\t** memory later on when the pointer was being dereferenced and written to without being initialized. ST - 8/14/2019 3:15PM\n\t*/\n\tDimensionData = NULL;\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object.              *\n *                                                                                             *\n *    This routine will return the maximum number of pips that can be displayed for this       *\n *    object. When dealing with generic objects, this value is always zero.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of pip boxes (empty or otherwise) to display.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Max_Pips(void) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels.                 *\n *                                                                                             *\n *    This routine will fetch the dimensions of this object expressed as pixels width and      *\n *    pixels height. This information can be used to intelligently update the clipping         *\n *    rectangles.                                                                              *\n *                                                                                             *\n * INPUT:   width    -- Reference to the width variable that will be filled in.                *\n *                                                                                             *\n *          height   -- Reference to the height variable that will be filled in.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectTypeClass::Dimensions(int &width, int &height) const\n{\n\twidth = 10;\n\theight = 10;\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit.                              *\n *                                                                                             *\n *    This routine will return the cost to purchase this unit. This routine is expected to be  *\n *    overridden by the objects that can actually be purchased. All other object types can     *\n *    simply return zero since this value won't be used.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the cost of the object.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Cost_Of(void) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object.                *\n *                                                                                             *\n *    This routine will fetch the time in takes to construct this object. Objects that can     *\n *    be constructed will override this routine in order to return a useful value.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the time units (arbitrary) that it takes to construct this object.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ObjectTypeClass::Time_To_Build(HousesType ) const\n{\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type.      *\n *                                                                                             *\n *    This routine will return with the cameo data pointer for this object type. It is         *\n *    expected that objects that can appear on the sidebar will override this routine in order *\n *    to provide proper cameo data pointer.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cameo shape data.                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid const * ObjectTypeClass::Get_Cameo_Data(void) const\n{\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object.             *\n *                                                                                             *\n *    This routine returns a pointer to a simple occupation list for this object. Since at     *\n *    this tier of the object class chain, the exact shape of the object is indeterminate,     *\n *    this function merely returns a single cell occupation list. This actually works for      *\n *    most vehicles.                                                                           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to a simple occupation list.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * ObjectTypeClass::Occupy_List(bool) const\n{\n\tstatic short const _list[] = {0, REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list.                *\n *                                                                                             *\n *    This function returns a pointer to an overlap list for the object. An overlap list is    *\n *    the offsets from the object's cell to get the cells the imagery overlaps, but is object  *\n *    is not considered to occupy. Since at this stage, the overlap information is not         *\n *    available, this function merely returns a pointer to an empty list.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the generic overlap list.                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * ObjectTypeClass::Overlap_List(void) const\n{\n\tstatic short const _list[] = {REFRESH_EOL};\n\treturn(_list);\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::One_Time -- Handles one time processing for object types.                  *\n *                                                                                             *\n *    This routine is used to handle the once per game processing required for object types.   *\n *    This consists of loading any data and initializing any data tables the game requires.    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine goes to disk.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ObjectTypeClass::One_Time(void)\n{\n\tSelectShapes = MFCD::Retrieve(\"SELECT.SHP\");\n\n\t#ifndef NDEBUG\n\t\tRawFileClass file(\"PIPS.SHP\");\n\t\tif (file.Is_Available()) {\n\t\t\tPipShapes = Load_Alloc_Data(file);\n\t\t} else {\n\t\t\tPipShapes = MFCD::Retrieve(\"PIPS.SHP\");\n\t\t}\n\t#else\n\t\tPipShapes = MFCD::Retrieve(\"PIPS.SHP\");\n\t#endif\n}\n\n\n/***********************************************************************************************\n * ObjectTypeClass::Who_Can_Build_Me -- Determine what building can build this object type.    *\n *                                                                                             *\n *    This routine will scan through all available factory buildings and determine which       *\n *    is capable of building this object type. The scan can be controlled to scan for only     *\n *    factory buildings that are free to produce now or those that could produce this          *\n *    object type if conditions permit.                                                        *\n *                                                                                             *\n * INPUT:   intheory -- Should the general (when conditions permit) case be examined to see    *\n *                      if a building could build this object type \"in theory\" even though it  *\n *                      might currently be otherwise occupied?                                 *\n *                                                                                             *\n *          legal    -- Check for building prerequisite and technology level rules? Usually    *\n *                      this would be 'true' for human controlled requests and 'false' for     *\n *                      the computer. This is because the computer is usually not under        *\n *                      the normal restrictions that the player is under.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building that can produce the object of this         *\n *          type. If no suitable factory building could be found, then NULL is returned.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass * ObjectTypeClass::Who_Can_Build_Me(bool intheory, bool legal, HousesType house) const\n{\n\tBuildingClass * anybuilding = NULL;\n\n\tif (!intheory && What_Am_I() == RTTI_AIRCRAFTTYPE && ((AircraftTypeClass*)this)->IsFixedWing) {\n\t\tint num_builders = 0, num_fixed_wings = 0;\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\tassert(building != NULL);\n\n\t\t\tif (\t!building->IsInLimbo &&\n\t\t\t\t\tbuilding->House->Class->House == house &&\n\t\t\t\t\tbuilding->Class->ToBuild == RTTI &&\n\t\t\t\t\tbuilding->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION &&\n\t\t\t\t\t((1L << building->ActLike) & Get_Ownable()) &&\n\t\t\t\t\t(!legal || building->House->Can_Build(this, building->ActLike))) {\n\t\t\t\tnum_builders++;\n\t\t\t}\n\t\t}\n\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass * aircraft = Aircraft.Ptr(index);\n\t\t\tassert(aircraft != NULL);\n\n\t\t\tif (\t!aircraft->IsInLimbo &&\n\t\t\t\t\taircraft->House->Class->House == house &&\n\t\t\t\t\taircraft->Class->IsFixedWing) {\n\t\t\t\tnum_fixed_wings++;\n\t\t\t}\n\t\t}\n\t\tif (num_fixed_wings >= num_builders) {\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\tassert(building != NULL);\n\n\t\tif (\t!building->IsInLimbo &&\n\t\t\t\tbuilding->House->Class->House == house &&\n\t\t\t\tbuilding->Class->ToBuild == RTTI &&\n\t\t\t\tbuilding->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION &&\n\t\t\t\t((1L << building->ActLike) & Get_Ownable()) &&\n\t\t\t\t(!legal || building->House->Can_Build(this, building->ActLike)) &&\n\t\t\t\t(intheory || !building->In_Radio_Contact())) {\n\n\t\t\t// BG: Hack so only kennels can build dogs, and no other, and barracks can\n\t\t\t//     only build humans and no other.\n\t\t\tif (What_Am_I() == RTTI_INFANTRYTYPE) {\n\t\t\t\tInfantryTypeClass * me = (InfantryTypeClass *)this;\n\t\t\t\tif (me->IsDog) {\n\t\t\t\t\tif (*building == STRUCT_KENNEL) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (*building != STRUCT_KENNEL) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tHACK ALERT: Helipads can build aircraft and airstrips can build\n\t\t\t\t**\tfixed wing craft only.\n\t\t\t\t*/\n\t\t\t\tif (What_Am_I() == RTTI_AIRCRAFTTYPE) {\n\t\t\t\t\tAircraftTypeClass * air = (AircraftTypeClass *)this;\n\t\t\t\t\tif ((*building == STRUCT_HELIPAD && !air->IsFixedWing) || (*building == STRUCT_AIRSTRIP && air->IsFixedWing)) {\n\t\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\t\tanybuilding = building;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tif (building->IsLeader) return(building);\n\t\t\t\t\tanybuilding = building;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(anybuilding);\n}"
  },
  {
    "path": "REDALERT/OBJECT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OBJECT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OBJECT.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 29, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 29, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OBJECT_H\n#define OBJECT_H\n\n#include\t\"abstract.h\"\n\nclass ObjectClass;\nclass TechnoClass;\nclass ObjectTypeClass;\nclass HouseClass;\nclass BuildingClass;\nclass RadioClass;\nclass TriggerClass;\n\n\n/**********************************************************************\n**\tEvery game object (that can exist on the map) is ultimately derived from this object\n**\tclass. It holds the common information between all objects. This is primarily the\n**\tobject unique ID number and its location in the world. All common operations between\n**\tgame objects are represented by virtual functions in this class.\n*/\nclass ObjectClass : public AbstractClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThe object can be in one of two states -- placed down on the map, or not. If the\n\t\t**\tobject is placed down on the map, then this flag will be true.\n\t\t*/\n\t\tunsigned IsDown:1;\n\n\t\t/*\n\t\t**\tThis is a support flag that is only used while building a list of objects to\n\t\t**\tbe damaged by a proximity affect (explosion). When this flag is set, this object\n\t\t**\twill not be added to the list of units to damage. When damage is applied to the\n\t\t**\tobject, this flag is cleared again. This process ensures that an object is never\n\t\t**\tsubject to \"double jeopardy\".\n\t\t*/\n\t\tunsigned IsToDamage:1;\n\n\t\t/*\n\t\t**\tIs this object flagged to be displayed during the next rendering process?  This\n\t\t**\tflag could be set by many different circumstances. It is automatically cleared\n\t\t**\twhen the object is rerendered.\n\t\t*/\n\t\tunsigned IsToDisplay:1;\n\n\t\t/*\n\t\t**\tAn object in the game may be valid yet held in a state of \"limbo\". Units are in such\n\t\t**\ta state if they are being transported or are otherwise \"inside\" another unit. They can\n\t\t**\talso be in limbo if they have been created but are being held until the proper time\n\t\t**\tfor delivery.\n\t\t*/\n\t\tunsigned IsInLimbo:1;\n\n\t\t/*\n\t\t**\tWhen an object is \"selected\" it is given a floating bar graph or other graphic imagery\n\t\t**\tto display this fact. When the player performs I/O, the actions may have a direct\n\t\t**\tbearing on the actions of the currently selected object. For quick checking purposes,\n\t\t**\tif this object is the one that is \"selected\", this flag will be true.\n\t\t*/\n\t\tunsigned IsSelected:1;\n\n\t\t//Added a mask instead of bool for selecting players. This is because we must now support multiplayer.\n\t\t// - 6/26/2019\n\t\t// Needs more than 16 bits since RA has more than 16 factions. ST - 8/14/2019 12:15PM\n\t\tunsigned int IsSelectedMask;\n\n\t\t/*\n\t\t**\tIf an animation is attached to this object, then this flag will be true.\n\t\t*/\n\t\tunsigned IsAnimAttached:1;\n\n\t\t/*\n\t\t**\tIf this object should process falling logic, then this flag will be true. Such\n\t\t**\tobjects might be ballistic projectiles, grenades, or parachuters.\n\t\t*/\n\t\tunsigned IsFalling:1;\n\t\tint Riser;\n\n\t\t/*\n\t\t**\tSeveral objects could exist in the same cell list. This is a pointer to the\n\t\t**\tnext object in the cell list. The objects in this list are not in any\n\t\t**\tsignificant order.\n\t\t*/\n\t\tSmartPtr<ObjectClass> Next;\n\n\t\t/*\n\t\t** Every object can be assigned a trigger; the same trigger can be assigned\n\t\t** to multiple objects.\n\t\t*/\n\t\tCCPtr<TriggerClass> Trigger;\n\n\t\t/*\n\t\t**\tThis is the current strength of this object.\n\t\t*/\n\t\tshort Strength;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[16];\n\n\t\t/*-----------------------------------------------------------------------------------\n\t\t**\tConstructor & destructors.\n\t\t*/\n\t\tObjectClass(RTTIType rtti, int id);\n\t\tObjectClass(NoInitClass const & x) : AbstractClass(x), Next(x), Trigger(x) {};\n\t\tvirtual ~ObjectClass(void) {Next = 0;};\n\t\tint operator < (ObjectClass const & object) const {return Sort_Y() < object.Sort_Y();};\n\t\tint operator > (ObjectClass const & object) const {return Sort_Y() > object.Sort_Y();};\n\n\t\t/*\n\t\t**\tObject selection control.\n\t\t*/\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tQuery functions.\n\t\t*/\n\t\tvirtual bool Is_Players_Army(void) const {return(false);}\n\t\tvirtual void const * Get_Image_Data(void) const;\n\t\tvirtual ActionType What_Action(ObjectClass const *) const;\n\t\tvirtual ActionType What_Action(CELL) const;\n\t\tvirtual LayerType In_Which_Layer(void) const;\n\t\tbool Is_Infantry(void) const {return(RTTI == RTTI_INFANTRY);};\n\t\tbool Is_Foot(void) const {return(RTTI == RTTI_INFANTRY || RTTI == RTTI_UNIT || RTTI == RTTI_VESSEL || RTTI == RTTI_AIRCRAFT);};\n\t\tbool Is_Techno(void) const {return(RTTI == RTTI_BUILDING || RTTI == RTTI_UNIT || RTTI == RTTI_INFANTRY || RTTI == RTTI_VESSEL || RTTI == RTTI_AIRCRAFT);};\n\t\tvirtual int Get_Ownable(void) const;\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const = 0;\n\t\tvirtual char const * Name(void) const;\n\t\tvirtual int Full_Name(void) const;\n\t\tvirtual bool Can_Repair(void) const;\n\t\tvirtual bool Can_Demolish(void) const;\n\t\tvirtual bool Can_Demolish_Unit(void) const;\n\t\tvirtual bool Can_Capture(void) const;\n\t\tvirtual bool Can_Player_Fire(void) const;\n\t\tvirtual bool Can_Player_Move(void) const;\n\n\t\t/*\n\t\t**\tCoordinate inquiry functions. These are used for both display and\n\t\t**\tcombat purposes.\n\t\t*/\n\t\tvirtual COORDINATE Docking_Coord(void) const;\n\t\tvirtual COORDINATE Target_Coord(void) const;\n\t\tvirtual COORDINATE Center_Coord(void) const;\n\t\tvirtual COORDINATE Render_Coord(void) const;\n\t\tvirtual COORDINATE Sort_Y(void) const;\n\t\tvirtual FireDataType Fire_Data(int which) const;\n\t\tvirtual COORDINATE Fire_Coord(int which) const;\n\t\tvirtual COORDINATE Exit_Coord(void) const;\n\n\t\t/*\n\t\t**\tObject entry and exit from the game system.\n\t\t*/\n\t\tvirtual bool Limbo(void);\n\t\tvirtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);\n\t\tvirtual void Detach(TARGET target, bool all=true);\n\t\tvirtual void Detach_All(bool all=true);\n\t\tvirtual void Record_The_Kill(TechnoClass * );\n\t\tvirtual bool Paradrop(COORDINATE coord);\n\t\tbool Attach_Trigger(TriggerClass * trigger);\n\n\t\t/*\n\t\t**\tDisplay and rendering support functionality. Supports imagery and how\n\t\t**\tobject interacts with the map and thus indirectly controls rendering.\n\t\t*/\n\t\tvirtual void Do_Shimmer(void);\n\t\tvirtual int Exit_Object(TechnoClass *);\n\t\tvirtual bool Render(bool forced) const;\n\t\tvirtual short const * Occupy_List(bool placement=false) const;\n\t\tvirtual short const * Overlap_List(bool redraw=false) const;\n\t\tvirtual fixed Health_Ratio(void) const;\n\t\tvirtual void Draw_It(int x, int y, WindowNumberType ) const = 0;\n\t\tvirtual void Hidden(void);\n\t\tvirtual void Look(bool incremental=false);\n\t\tvirtual bool Mark(MarkType=MARK_CHANGE);\n\n\tprivate:\n\t\tvirtual void Mark_For_Redraw(void);\n\n\tpublic:\n\n\t\t/*\n\t\t**\tUser I/O.\n\t\t*/\n\t\tvirtual void Active_Click_With(ActionType , ObjectClass *);\n\t\tvirtual void Active_Click_With(ActionType , CELL );\n\t\tvirtual void Clicked_As_Target(HousesType house, int = 7); // 2019/09/20 JAS - Added record of who clicked on the object\n\t\tvirtual bool Select(bool allow_mixed = false);\n\t\tvirtual void Unselect(void);\n\n\t\t//These selection functions were added to handle the fact that we now need to support \n\t\t//client-server multiplayer. - JAS 6/26/2019\n\t\tvirtual void Unselect_All_Players(void);\n\t\tvirtual void Unselect_All_Players_Except_Owner(void);\n\t\tvirtual bool Is_Selected_By_Player(HouseClass *player = NULL) const;\n\t\tvirtual void Set_Selected_By_Player(HouseClass *player = NULL);\n\t\tvirtual void Set_Unselected_By_Player(HouseClass *player = NULL);\n\n\t\t/*\n\t\t**\tCombat related.\n\t\t*/\n\t\tvirtual bool In_Range(COORDINATE , int=0) const;\n\t\tvirtual int Weapon_Range(int =0) const;\n\t\tvirtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);\n\t\tvirtual void Scatter(COORDINATE , bool forced=false, bool nokidding=false);\n\t\tvirtual bool Catch_Fire(void);\n\t\tvirtual void Fire_Out(void);\n\t\tvirtual int Value(void) const;\n\t\tvirtual MissionType Get_Mission(void) const;\n\n\t\t/*\n\t\t**\tAI.\n\t\t*/\n\t\tvirtual void Per_Cell_Process(PCPType) {}\n\t\tvirtual BuildingClass * Who_Can_Build_Me(bool intheory, bool legal) const;\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual bool Revealed(HouseClass * house);\n\t\tvirtual void Repair(int );\n\t\tvirtual void Sell_Back(int );\n\t\tvirtual void AI(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n\n\t\t/*\n\t\t**\tScenario and debug support.\n\t\t*/\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvirtual void Move(FacingType);\n\n\t\tenum {FLIGHT_LEVEL=256};\n\n};\n\n#endif"
  },
  {
    "path": "REDALERT/OCIDL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* this ALWAYS GENERATED file contains the definitions for the interfaces */\n\n\n/* File created by MIDL compiler version 3.00.39 */\n/* at Sat Jul 13 21:56:58 1996\n */\n/* Compiler settings for c:\\oa\\src\\idl\\ocidl.idl:\n    Oic (OptLev=i1), W1, Zp8, env=Win32, ms_ext, c_ext\n    error checks: allocation ref bounds_check enum stub_data \n*/\n//@@MIDL_FILE_HEADING(  )\n#include \"rpc.h\"\n#include \"rpcndr.h\"\n#ifndef COM_NO_WINDOWS_H\n#include \"windows.h\"\n#include \"ole2.h\"\n#endif /*COM_NO_WINDOWS_H*/\n\n#ifndef __ocidl_h__\n#define __ocidl_h__\n\n#ifdef __cplusplus\nextern \"C\"{\n#endif \n\n/* Forward Declarations */ \n\n#ifndef __IEnumConnections_FWD_DEFINED__\n#define __IEnumConnections_FWD_DEFINED__\ntypedef interface IEnumConnections IEnumConnections;\n#endif \t/* __IEnumConnections_FWD_DEFINED__ */\n\n\n#ifndef __IConnectionPoint_FWD_DEFINED__\n#define __IConnectionPoint_FWD_DEFINED__\ntypedef interface IConnectionPoint IConnectionPoint;\n#endif \t/* __IConnectionPoint_FWD_DEFINED__ */\n\n\n#ifndef __IEnumConnectionPoints_FWD_DEFINED__\n#define __IEnumConnectionPoints_FWD_DEFINED__\ntypedef interface IEnumConnectionPoints IEnumConnectionPoints;\n#endif \t/* __IEnumConnectionPoints_FWD_DEFINED__ */\n\n\n#ifndef __IConnectionPointContainer_FWD_DEFINED__\n#define __IConnectionPointContainer_FWD_DEFINED__\ntypedef interface IConnectionPointContainer IConnectionPointContainer;\n#endif \t/* __IConnectionPointContainer_FWD_DEFINED__ */\n\n\n#ifndef __IClassFactory2_FWD_DEFINED__\n#define __IClassFactory2_FWD_DEFINED__\ntypedef interface IClassFactory2 IClassFactory2;\n#endif \t/* __IClassFactory2_FWD_DEFINED__ */\n\n\n#ifndef __IProvideClassInfo_FWD_DEFINED__\n#define __IProvideClassInfo_FWD_DEFINED__\ntypedef interface IProvideClassInfo IProvideClassInfo;\n#endif \t/* __IProvideClassInfo_FWD_DEFINED__ */\n\n\n#ifndef __IProvideClassInfo2_FWD_DEFINED__\n#define __IProvideClassInfo2_FWD_DEFINED__\ntypedef interface IProvideClassInfo2 IProvideClassInfo2;\n#endif \t/* __IProvideClassInfo2_FWD_DEFINED__ */\n\n\n#ifndef __IOleControl_FWD_DEFINED__\n#define __IOleControl_FWD_DEFINED__\ntypedef interface IOleControl IOleControl;\n#endif \t/* __IOleControl_FWD_DEFINED__ */\n\n\n#ifndef __IOleControlSite_FWD_DEFINED__\n#define __IOleControlSite_FWD_DEFINED__\ntypedef interface IOleControlSite IOleControlSite;\n#endif \t/* __IOleControlSite_FWD_DEFINED__ */\n\n\n#ifndef __IPropertyPage_FWD_DEFINED__\n#define __IPropertyPage_FWD_DEFINED__\ntypedef interface IPropertyPage IPropertyPage;\n#endif \t/* __IPropertyPage_FWD_DEFINED__ */\n\n\n#ifndef __IPropertyPage2_FWD_DEFINED__\n#define __IPropertyPage2_FWD_DEFINED__\ntypedef interface IPropertyPage2 IPropertyPage2;\n#endif \t/* __IPropertyPage2_FWD_DEFINED__ */\n\n\n#ifndef __IPropertyPageSite_FWD_DEFINED__\n#define __IPropertyPageSite_FWD_DEFINED__\ntypedef interface IPropertyPageSite IPropertyPageSite;\n#endif \t/* __IPropertyPageSite_FWD_DEFINED__ */\n\n\n#ifndef __IPropertyNotifySink_FWD_DEFINED__\n#define __IPropertyNotifySink_FWD_DEFINED__\ntypedef interface IPropertyNotifySink IPropertyNotifySink;\n#endif \t/* __IPropertyNotifySink_FWD_DEFINED__ */\n\n\n#ifndef __ISpecifyPropertyPages_FWD_DEFINED__\n#define __ISpecifyPropertyPages_FWD_DEFINED__\ntypedef interface ISpecifyPropertyPages ISpecifyPropertyPages;\n#endif \t/* __ISpecifyPropertyPages_FWD_DEFINED__ */\n\n\n#ifndef __IPersistMemory_FWD_DEFINED__\n#define __IPersistMemory_FWD_DEFINED__\ntypedef interface IPersistMemory IPersistMemory;\n#endif \t/* __IPersistMemory_FWD_DEFINED__ */\n\n\n#ifndef __IPersistStreamInit_FWD_DEFINED__\n#define __IPersistStreamInit_FWD_DEFINED__\ntypedef interface IPersistStreamInit IPersistStreamInit;\n#endif \t/* __IPersistStreamInit_FWD_DEFINED__ */\n\n\n#ifndef __IPersistPropertyBag_FWD_DEFINED__\n#define __IPersistPropertyBag_FWD_DEFINED__\ntypedef interface IPersistPropertyBag IPersistPropertyBag;\n#endif \t/* __IPersistPropertyBag_FWD_DEFINED__ */\n\n\n#ifndef __ISimpleFrameSite_FWD_DEFINED__\n#define __ISimpleFrameSite_FWD_DEFINED__\ntypedef interface ISimpleFrameSite ISimpleFrameSite;\n#endif \t/* __ISimpleFrameSite_FWD_DEFINED__ */\n\n\n#ifndef __IFont_FWD_DEFINED__\n#define __IFont_FWD_DEFINED__\ntypedef interface IFont IFont;\n#endif \t/* __IFont_FWD_DEFINED__ */\n\n\n#ifndef __IPicture_FWD_DEFINED__\n#define __IPicture_FWD_DEFINED__\ntypedef interface IPicture IPicture;\n#endif \t/* __IPicture_FWD_DEFINED__ */\n\n\n#ifndef __IFontDisp_FWD_DEFINED__\n#define __IFontDisp_FWD_DEFINED__\ntypedef interface IFontDisp IFontDisp;\n#endif \t/* __IFontDisp_FWD_DEFINED__ */\n\n\n#ifndef __IPictureDisp_FWD_DEFINED__\n#define __IPictureDisp_FWD_DEFINED__\ntypedef interface IPictureDisp IPictureDisp;\n#endif \t/* __IPictureDisp_FWD_DEFINED__ */\n\n\n#ifndef __IAdviseSinkEx_FWD_DEFINED__\n#define __IAdviseSinkEx_FWD_DEFINED__\ntypedef interface IAdviseSinkEx IAdviseSinkEx;\n#endif \t/* __IAdviseSinkEx_FWD_DEFINED__ */\n\n\n#ifndef __IOleInPlaceObjectWindowless_FWD_DEFINED__\n#define __IOleInPlaceObjectWindowless_FWD_DEFINED__\ntypedef interface IOleInPlaceObjectWindowless IOleInPlaceObjectWindowless;\n#endif \t/* __IOleInPlaceObjectWindowless_FWD_DEFINED__ */\n\n\n#ifndef __IOleInPlaceSiteEx_FWD_DEFINED__\n#define __IOleInPlaceSiteEx_FWD_DEFINED__\ntypedef interface IOleInPlaceSiteEx IOleInPlaceSiteEx;\n#endif \t/* __IOleInPlaceSiteEx_FWD_DEFINED__ */\n\n\n#ifndef __IOleInPlaceSiteWindowless_FWD_DEFINED__\n#define __IOleInPlaceSiteWindowless_FWD_DEFINED__\ntypedef interface IOleInPlaceSiteWindowless IOleInPlaceSiteWindowless;\n#endif \t/* __IOleInPlaceSiteWindowless_FWD_DEFINED__ */\n\n\n#ifndef __IViewObjectEx_FWD_DEFINED__\n#define __IViewObjectEx_FWD_DEFINED__\ntypedef interface IViewObjectEx IViewObjectEx;\n#endif \t/* __IViewObjectEx_FWD_DEFINED__ */\n\n\n#ifndef __IOleUndoUnit_FWD_DEFINED__\n#define __IOleUndoUnit_FWD_DEFINED__\ntypedef interface IOleUndoUnit IOleUndoUnit;\n#endif \t/* __IOleUndoUnit_FWD_DEFINED__ */\n\n\n#ifndef __IOleParentUndoUnit_FWD_DEFINED__\n#define __IOleParentUndoUnit_FWD_DEFINED__\ntypedef interface IOleParentUndoUnit IOleParentUndoUnit;\n#endif \t/* __IOleParentUndoUnit_FWD_DEFINED__ */\n\n\n#ifndef __IEnumOleUndoUnits_FWD_DEFINED__\n#define __IEnumOleUndoUnits_FWD_DEFINED__\ntypedef interface IEnumOleUndoUnits IEnumOleUndoUnits;\n#endif \t/* __IEnumOleUndoUnits_FWD_DEFINED__ */\n\n\n#ifndef __IOleUndoManager_FWD_DEFINED__\n#define __IOleUndoManager_FWD_DEFINED__\ntypedef interface IOleUndoManager IOleUndoManager;\n#endif \t/* __IOleUndoManager_FWD_DEFINED__ */\n\n\n#ifndef __IQuickActivate_FWD_DEFINED__\n#define __IQuickActivate_FWD_DEFINED__\ntypedef interface IQuickActivate IQuickActivate;\n#endif \t/* __IQuickActivate_FWD_DEFINED__ */\n\n\n#ifndef __IPointerInactive_FWD_DEFINED__\n#define __IPointerInactive_FWD_DEFINED__\ntypedef interface IPointerInactive IPointerInactive;\n#endif \t/* __IPointerInactive_FWD_DEFINED__ */\n\n\n#ifndef __IObjectWithSite_FWD_DEFINED__\n#define __IObjectWithSite_FWD_DEFINED__\ntypedef interface IObjectWithSite IObjectWithSite;\n#endif \t/* __IObjectWithSite_FWD_DEFINED__ */\n\n\n#ifndef __IErrorLog_FWD_DEFINED__\n#define __IErrorLog_FWD_DEFINED__\ntypedef interface IErrorLog IErrorLog;\n#endif \t/* __IErrorLog_FWD_DEFINED__ */\n\n\n#ifndef __IPropertyBag_FWD_DEFINED__\n#define __IPropertyBag_FWD_DEFINED__\ntypedef interface IPropertyBag IPropertyBag;\n#endif \t/* __IPropertyBag_FWD_DEFINED__ */\n\n\n#ifndef __IPerPropertyBrowsing_FWD_DEFINED__\n#define __IPerPropertyBrowsing_FWD_DEFINED__\ntypedef interface IPerPropertyBrowsing IPerPropertyBrowsing;\n#endif \t/* __IPerPropertyBrowsing_FWD_DEFINED__ */\n\n\n/* header files for imported files */\n#include \"oleidl.h\"\n#include \"oaidl.h\"\n\nvoid __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);\nvoid __RPC_USER MIDL_user_free( void __RPC_FAR * ); \n\n/****************************************\n * Generated header for interface: __MIDL__intf_0000\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [local] */ \n\n\n//+-------------------------------------------------------------------------\n//\n//  Microsoft Windows\n//  Copyright (C) Microsoft Corporation, 1993 - 1996.\n//\n//--------------------------------------------------------------------------\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nextern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_c_ifspec;\nextern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_s_ifspec;\n\n#ifndef __IOleControlTypes_INTERFACE_DEFINED__\n#define __IOleControlTypes_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleControlTypes\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [auto_handle][unique][version] */ \n\n\ntypedef /* [v1_enum] */ \nenum tagUASFLAGS\n    {\tUAS_NORMAL\t= 0,\n\tUAS_BLOCKED\t= 0x1,\n\tUAS_NOPARENTENABLE\t= 0x2,\n\tUAS_MASK\t= 0x3\n    }\tUASFLAGS;\n\n/* State values for the DISPID_READYSTATE property */\ntypedef /* [v1_enum] */ \nenum tagREADYSTATE\n    {\tREADYSTATE_UNINITIALIZED\t= 0,\n\tREADYSTATE_LOADING\t= 1,\n\tREADYSTATE_LOADED\t= 2,\n\tREADYSTATE_INTERACTIVE\t= 3,\n\tREADYSTATE_COMPLETE\t= 4\n    }\tREADYSTATE;\n\ntypedef /* [represent_as] */ struct  tagUserHWND\n    {\n    wireHWND pRemHwnd;\n    }\tUserHWND;\n\ntypedef /* [represent_as] */ struct tagUserHWND UserHACCEL;\n\ntypedef /* [represent_as] */ struct tagUserHWND UserHDC;\n\ntypedef /* [represent_as] */ struct tagUserHWND UserHFONT;\n\ntypedef /* [represent_as] */ struct  tagUserMSG\n    {\n    wireHWND pRemHwnd;\n    UINT message;\n    WPARAM wParam;\n    LPARAM lParam;\n    DWORD time;\n    POINT pt;\n    }\tUserMSG;\n\ntypedef /* [represent_as] */ struct  tagUserBSTR\n    {\n    wireBSTR pBstrBlob;\n    }\tUserBSTR;\n\ntypedef struct  tagVARIANT_BLOB\n    {\n    DWORD clSize;\n    DWORD rpcReserved;\n    /* [size_is] */ ULONGLONG ahData[ 1 ];\n    }\t__RPC_FAR *wireVARIANT_BLOB;\n\ntypedef /* [represent_as] */ struct  tagUserVARIANT\n    {\n    wireVARIANT_BLOB pVarBlob;\n    }\tUserVARIANT;\n\ntypedef /* [represent_as] */ struct  tagUserEXCEPINFO\n    {\n    WORD wCode;\n    WORD wReserved;\n    wireBSTR bstrSource;\n    wireBSTR bstrDescription;\n    wireBSTR bstrHelpFile;\n    DWORD dwHelpContext;\n    ULONG pvReserved;\n    ULONG pfnDeferredFillIn;\n    SCODE scode;\n    }\tUserEXCEPINFO;\n\n\n\nextern RPC_IF_HANDLE IOleControlTypes_v1_0_c_ifspec;\nextern RPC_IF_HANDLE IOleControlTypes_v1_0_s_ifspec;\n#endif /* __IOleControlTypes_INTERFACE_DEFINED__ */\n\n#ifndef __IEnumConnections_INTERFACE_DEFINED__\n#define __IEnumConnections_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IEnumConnections\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IEnumConnections __RPC_FAR *PENUMCONNECTIONS;\n\ntypedef IEnumConnections __RPC_FAR *LPENUMCONNECTIONS;\n\ntypedef struct  tagCONNECTDATA\n    {\n    IUnknown __RPC_FAR *pUnk;\n    DWORD dwCookie;\n    }\tCONNECTDATA;\n\ntypedef struct tagCONNECTDATA __RPC_FAR *PCONNECTDATA;\n\ntypedef struct tagCONNECTDATA __RPC_FAR *LPCONNECTDATA;\n\n\nEXTERN_C const IID IID_IEnumConnections;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IEnumConnections : public IUnknown\n    {\n    public:\n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( \n            /* [in] */ ULONG cConnections,\n            /* [length_is][size_is][out] */ LPCONNECTDATA rgcd,\n            /* [out] */ ULONG __RPC_FAR *pcFetched) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Skip( \n            /* [in] */ ULONG cConnections) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Clone( \n            /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IEnumConnectionsVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IEnumConnections __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IEnumConnections __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IEnumConnections __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( \n            IEnumConnections __RPC_FAR * This,\n            /* [in] */ ULONG cConnections,\n            /* [length_is][size_is][out] */ LPCONNECTDATA rgcd,\n            /* [out] */ ULONG __RPC_FAR *pcFetched);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( \n            IEnumConnections __RPC_FAR * This,\n            /* [in] */ ULONG cConnections);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( \n            IEnumConnections __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( \n            IEnumConnections __RPC_FAR * This,\n            /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        END_INTERFACE\n    } IEnumConnectionsVtbl;\n\n    interface IEnumConnections\n    {\n        CONST_VTBL struct IEnumConnectionsVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IEnumConnections_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IEnumConnections_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IEnumConnections_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IEnumConnections_Next(This,cConnections,rgcd,pcFetched)\t\\\n    (This)->lpVtbl -> Next(This,cConnections,rgcd,pcFetched)\n\n#define IEnumConnections_Skip(This,cConnections)\t\\\n    (This)->lpVtbl -> Skip(This,cConnections)\n\n#define IEnumConnections_Reset(This)\t\\\n    (This)->lpVtbl -> Reset(This)\n\n#define IEnumConnections_Clone(This,ppEnum)\t\\\n    (This)->lpVtbl -> Clone(This,ppEnum)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumConnections_RemoteNext_Proxy( \n    IEnumConnections __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTDATA rgcd,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n\nvoid __RPC_STUB IEnumConnections_RemoteNext_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnections_Skip_Proxy( \n    IEnumConnections __RPC_FAR * This,\n    /* [in] */ ULONG cConnections);\n\n\nvoid __RPC_STUB IEnumConnections_Skip_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnections_Reset_Proxy( \n    IEnumConnections __RPC_FAR * This);\n\n\nvoid __RPC_STUB IEnumConnections_Reset_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnections_Clone_Proxy( \n    IEnumConnections __RPC_FAR * This,\n    /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IEnumConnections_Clone_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IEnumConnections_INTERFACE_DEFINED__ */\n\n\n#ifndef __IConnectionPoint_INTERFACE_DEFINED__\n#define __IConnectionPoint_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IConnectionPoint\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IConnectionPoint __RPC_FAR *PCONNECTIONPOINT;\n\ntypedef IConnectionPoint __RPC_FAR *LPCONNECTIONPOINT;\n\n\nEXTERN_C const IID IID_IConnectionPoint;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IConnectionPoint : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetConnectionInterface( \n            /* [out] */ IID __RPC_FAR *pIID) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetConnectionPointContainer( \n            /* [out] */ IConnectionPointContainer __RPC_FAR *__RPC_FAR *ppCPC) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Advise( \n            /* [in] */ IUnknown __RPC_FAR *pUnkSink,\n            /* [out] */ DWORD __RPC_FAR *pdwCookie) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Unadvise( \n            /* [in] */ DWORD dwCookie) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE EnumConnections( \n            /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IConnectionPointVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IConnectionPoint __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IConnectionPoint __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetConnectionInterface )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [out] */ IID __RPC_FAR *pIID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetConnectionPointContainer )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [out] */ IConnectionPointContainer __RPC_FAR *__RPC_FAR *ppCPC);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Advise )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [in] */ IUnknown __RPC_FAR *pUnkSink,\n            /* [out] */ DWORD __RPC_FAR *pdwCookie);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Unadvise )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [in] */ DWORD dwCookie);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumConnections )( \n            IConnectionPoint __RPC_FAR * This,\n            /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        END_INTERFACE\n    } IConnectionPointVtbl;\n\n    interface IConnectionPoint\n    {\n        CONST_VTBL struct IConnectionPointVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IConnectionPoint_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IConnectionPoint_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IConnectionPoint_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IConnectionPoint_GetConnectionInterface(This,pIID)\t\\\n    (This)->lpVtbl -> GetConnectionInterface(This,pIID)\n\n#define IConnectionPoint_GetConnectionPointContainer(This,ppCPC)\t\\\n    (This)->lpVtbl -> GetConnectionPointContainer(This,ppCPC)\n\n#define IConnectionPoint_Advise(This,pUnkSink,pdwCookie)\t\\\n    (This)->lpVtbl -> Advise(This,pUnkSink,pdwCookie)\n\n#define IConnectionPoint_Unadvise(This,dwCookie)\t\\\n    (This)->lpVtbl -> Unadvise(This,dwCookie)\n\n#define IConnectionPoint_EnumConnections(This,ppEnum)\t\\\n    (This)->lpVtbl -> EnumConnections(This,ppEnum)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPoint_GetConnectionInterface_Proxy( \n    IConnectionPoint __RPC_FAR * This,\n    /* [out] */ IID __RPC_FAR *pIID);\n\n\nvoid __RPC_STUB IConnectionPoint_GetConnectionInterface_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPoint_GetConnectionPointContainer_Proxy( \n    IConnectionPoint __RPC_FAR * This,\n    /* [out] */ IConnectionPointContainer __RPC_FAR *__RPC_FAR *ppCPC);\n\n\nvoid __RPC_STUB IConnectionPoint_GetConnectionPointContainer_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPoint_Advise_Proxy( \n    IConnectionPoint __RPC_FAR * This,\n    /* [in] */ IUnknown __RPC_FAR *pUnkSink,\n    /* [out] */ DWORD __RPC_FAR *pdwCookie);\n\n\nvoid __RPC_STUB IConnectionPoint_Advise_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPoint_Unadvise_Proxy( \n    IConnectionPoint __RPC_FAR * This,\n    /* [in] */ DWORD dwCookie);\n\n\nvoid __RPC_STUB IConnectionPoint_Unadvise_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPoint_EnumConnections_Proxy( \n    IConnectionPoint __RPC_FAR * This,\n    /* [out] */ IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IConnectionPoint_EnumConnections_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IConnectionPoint_INTERFACE_DEFINED__ */\n\n\n#ifndef __IEnumConnectionPoints_INTERFACE_DEFINED__\n#define __IEnumConnectionPoints_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IEnumConnectionPoints\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IEnumConnectionPoints __RPC_FAR *PENUMCONNECTIONPOINTS;\n\ntypedef IEnumConnectionPoints __RPC_FAR *LPENUMCONNECTIONPOINTS;\n\n\nEXTERN_C const IID IID_IEnumConnectionPoints;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IEnumConnectionPoints : public IUnknown\n    {\n    public:\n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( \n            /* [in] */ ULONG cConnections,\n            /* [length_is][size_is][out] */ LPCONNECTIONPOINT __RPC_FAR *ppCP,\n            /* [out] */ ULONG __RPC_FAR *pcFetched) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Skip( \n            /* [in] */ ULONG cConnections) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Clone( \n            /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IEnumConnectionPointsVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IEnumConnectionPoints __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IEnumConnectionPoints __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IEnumConnectionPoints __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( \n            IEnumConnectionPoints __RPC_FAR * This,\n            /* [in] */ ULONG cConnections,\n            /* [length_is][size_is][out] */ LPCONNECTIONPOINT __RPC_FAR *ppCP,\n            /* [out] */ ULONG __RPC_FAR *pcFetched);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( \n            IEnumConnectionPoints __RPC_FAR * This,\n            /* [in] */ ULONG cConnections);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( \n            IEnumConnectionPoints __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( \n            IEnumConnectionPoints __RPC_FAR * This,\n            /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        END_INTERFACE\n    } IEnumConnectionPointsVtbl;\n\n    interface IEnumConnectionPoints\n    {\n        CONST_VTBL struct IEnumConnectionPointsVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IEnumConnectionPoints_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IEnumConnectionPoints_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IEnumConnectionPoints_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IEnumConnectionPoints_Next(This,cConnections,ppCP,pcFetched)\t\\\n    (This)->lpVtbl -> Next(This,cConnections,ppCP,pcFetched)\n\n#define IEnumConnectionPoints_Skip(This,cConnections)\t\\\n    (This)->lpVtbl -> Skip(This,cConnections)\n\n#define IEnumConnectionPoints_Reset(This)\t\\\n    (This)->lpVtbl -> Reset(This)\n\n#define IEnumConnectionPoints_Clone(This,ppEnum)\t\\\n    (This)->lpVtbl -> Clone(This,ppEnum)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumConnectionPoints_RemoteNext_Proxy( \n    IEnumConnectionPoints __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTIONPOINT __RPC_FAR *ppCP,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n\nvoid __RPC_STUB IEnumConnectionPoints_RemoteNext_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Skip_Proxy( \n    IEnumConnectionPoints __RPC_FAR * This,\n    /* [in] */ ULONG cConnections);\n\n\nvoid __RPC_STUB IEnumConnectionPoints_Skip_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Reset_Proxy( \n    IEnumConnectionPoints __RPC_FAR * This);\n\n\nvoid __RPC_STUB IEnumConnectionPoints_Reset_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Clone_Proxy( \n    IEnumConnectionPoints __RPC_FAR * This,\n    /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IEnumConnectionPoints_Clone_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IEnumConnectionPoints_INTERFACE_DEFINED__ */\n\n\n#ifndef __IConnectionPointContainer_INTERFACE_DEFINED__\n#define __IConnectionPointContainer_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IConnectionPointContainer\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IConnectionPointContainer __RPC_FAR *PCONNECTIONPOINTCONTAINER;\n\ntypedef IConnectionPointContainer __RPC_FAR *LPCONNECTIONPOINTCONTAINER;\n\n\nEXTERN_C const IID IID_IConnectionPointContainer;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IConnectionPointContainer : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE EnumConnectionPoints( \n            /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE FindConnectionPoint( \n            /* [in] */ REFIID riid,\n            /* [out] */ IConnectionPoint __RPC_FAR *__RPC_FAR *ppCP) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IConnectionPointContainerVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IConnectionPointContainer __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IConnectionPointContainer __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IConnectionPointContainer __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumConnectionPoints )( \n            IConnectionPointContainer __RPC_FAR * This,\n            /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FindConnectionPoint )( \n            IConnectionPointContainer __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [out] */ IConnectionPoint __RPC_FAR *__RPC_FAR *ppCP);\n        \n        END_INTERFACE\n    } IConnectionPointContainerVtbl;\n\n    interface IConnectionPointContainer\n    {\n        CONST_VTBL struct IConnectionPointContainerVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IConnectionPointContainer_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IConnectionPointContainer_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IConnectionPointContainer_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IConnectionPointContainer_EnumConnectionPoints(This,ppEnum)\t\\\n    (This)->lpVtbl -> EnumConnectionPoints(This,ppEnum)\n\n#define IConnectionPointContainer_FindConnectionPoint(This,riid,ppCP)\t\\\n    (This)->lpVtbl -> FindConnectionPoint(This,riid,ppCP)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPointContainer_EnumConnectionPoints_Proxy( \n    IConnectionPointContainer __RPC_FAR * This,\n    /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IConnectionPointContainer_EnumConnectionPoints_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IConnectionPointContainer_FindConnectionPoint_Proxy( \n    IConnectionPointContainer __RPC_FAR * This,\n    /* [in] */ REFIID riid,\n    /* [out] */ IConnectionPoint __RPC_FAR *__RPC_FAR *ppCP);\n\n\nvoid __RPC_STUB IConnectionPointContainer_FindConnectionPoint_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IConnectionPointContainer_INTERFACE_DEFINED__ */\n\n\n#ifndef __IClassFactory2_INTERFACE_DEFINED__\n#define __IClassFactory2_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IClassFactory2\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IClassFactory2 __RPC_FAR *LPCLASSFACTORY2;\n\ntypedef struct  tagLICINFO\n    {\n    LONG cbLicInfo;\n    BOOL fRuntimeKeyAvail;\n    BOOL fLicVerified;\n    }\tLICINFO;\n\ntypedef struct tagLICINFO __RPC_FAR *LPLICINFO;\n\n\nEXTERN_C const IID IID_IClassFactory2;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IClassFactory2 : public IClassFactory\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetLicInfo( \n            /* [out] */ LICINFO __RPC_FAR *pLicInfo) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE RequestLicKey( \n            /* [in] */ DWORD dwReserved,\n            /* [out] */ BSTR __RPC_FAR *pBstrKey) = 0;\n        \n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstanceLic( \n            /* [in] */ IUnknown __RPC_FAR *pUnkOuter,\n            /* [in] */ IUnknown __RPC_FAR *pUnkReserved,\n            /* [in] */ REFIID riid,\n            /* [in] */ BSTR bstrKey,\n            /* [iid_is][out] */ PVOID __RPC_FAR *ppvObj) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IClassFactory2Vtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IClassFactory2 __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IClassFactory2 __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateInstance )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LockServer )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [in] */ BOOL fLock);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetLicInfo )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [out] */ LICINFO __RPC_FAR *pLicInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestLicKey )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [in] */ DWORD dwReserved,\n            /* [out] */ BSTR __RPC_FAR *pBstrKey);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateInstanceLic )( \n            IClassFactory2 __RPC_FAR * This,\n            /* [in] */ IUnknown __RPC_FAR *pUnkOuter,\n            /* [in] */ IUnknown __RPC_FAR *pUnkReserved,\n            /* [in] */ REFIID riid,\n            /* [in] */ BSTR bstrKey,\n            /* [iid_is][out] */ PVOID __RPC_FAR *ppvObj);\n        \n        END_INTERFACE\n    } IClassFactory2Vtbl;\n\n    interface IClassFactory2\n    {\n        CONST_VTBL struct IClassFactory2Vtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IClassFactory2_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IClassFactory2_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IClassFactory2_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IClassFactory2_CreateInstance(This,pUnkOuter,riid,ppvObject)\t\\\n    (This)->lpVtbl -> CreateInstance(This,pUnkOuter,riid,ppvObject)\n\n#define IClassFactory2_LockServer(This,fLock)\t\\\n    (This)->lpVtbl -> LockServer(This,fLock)\n\n\n#define IClassFactory2_GetLicInfo(This,pLicInfo)\t\\\n    (This)->lpVtbl -> GetLicInfo(This,pLicInfo)\n\n#define IClassFactory2_RequestLicKey(This,dwReserved,pBstrKey)\t\\\n    (This)->lpVtbl -> RequestLicKey(This,dwReserved,pBstrKey)\n\n#define IClassFactory2_CreateInstanceLic(This,pUnkOuter,pUnkReserved,riid,bstrKey,ppvObj)\t\\\n    (This)->lpVtbl -> CreateInstanceLic(This,pUnkOuter,pUnkReserved,riid,bstrKey,ppvObj)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IClassFactory2_GetLicInfo_Proxy( \n    IClassFactory2 __RPC_FAR * This,\n    /* [out] */ LICINFO __RPC_FAR *pLicInfo);\n\n\nvoid __RPC_STUB IClassFactory2_GetLicInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IClassFactory2_RequestLicKey_Proxy( \n    IClassFactory2 __RPC_FAR * This,\n    /* [in] */ DWORD dwReserved,\n    /* [out] */ BSTR __RPC_FAR *pBstrKey);\n\n\nvoid __RPC_STUB IClassFactory2_RequestLicKey_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IClassFactory2_RemoteCreateInstanceLic_Proxy( \n    IClassFactory2 __RPC_FAR * This,\n    /* [in] */ REFIID riid,\n    /* [in] */ BSTR bstrKey,\n    /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObj);\n\n\nvoid __RPC_STUB IClassFactory2_RemoteCreateInstanceLic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IClassFactory2_INTERFACE_DEFINED__ */\n\n\n#ifndef __IProvideClassInfo_INTERFACE_DEFINED__\n#define __IProvideClassInfo_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IProvideClassInfo\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IProvideClassInfo __RPC_FAR *LPPROVIDECLASSINFO;\n\n\nEXTERN_C const IID IID_IProvideClassInfo;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IProvideClassInfo : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetClassInfo( \n            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTI) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IProvideClassInfoVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IProvideClassInfo __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IProvideClassInfo __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IProvideClassInfo __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassInfo )( \n            IProvideClassInfo __RPC_FAR * This,\n            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTI);\n        \n        END_INTERFACE\n    } IProvideClassInfoVtbl;\n\n    interface IProvideClassInfo\n    {\n        CONST_VTBL struct IProvideClassInfoVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IProvideClassInfo_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IProvideClassInfo_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IProvideClassInfo_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IProvideClassInfo_GetClassInfo(This,ppTI)\t\\\n    (This)->lpVtbl -> GetClassInfo(This,ppTI)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IProvideClassInfo_GetClassInfo_Proxy( \n    IProvideClassInfo __RPC_FAR * This,\n    /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTI);\n\n\nvoid __RPC_STUB IProvideClassInfo_GetClassInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IProvideClassInfo_INTERFACE_DEFINED__ */\n\n\n#ifndef __IProvideClassInfo2_INTERFACE_DEFINED__\n#define __IProvideClassInfo2_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IProvideClassInfo2\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IProvideClassInfo2 __RPC_FAR *LPPROVIDECLASSINFO2;\n\ntypedef \nenum tagGUIDKIND\n    {\tGUIDKIND_DEFAULT_SOURCE_DISP_IID\t= 1\n    }\tGUIDKIND;\n\n\nEXTERN_C const IID IID_IProvideClassInfo2;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IProvideClassInfo2 : public IProvideClassInfo\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetGUID( \n            /* [in] */ DWORD dwGuidKind,\n            /* [out] */ GUID __RPC_FAR *pGUID) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IProvideClassInfo2Vtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IProvideClassInfo2 __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IProvideClassInfo2 __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IProvideClassInfo2 __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassInfo )( \n            IProvideClassInfo2 __RPC_FAR * This,\n            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTI);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetGUID )( \n            IProvideClassInfo2 __RPC_FAR * This,\n            /* [in] */ DWORD dwGuidKind,\n            /* [out] */ GUID __RPC_FAR *pGUID);\n        \n        END_INTERFACE\n    } IProvideClassInfo2Vtbl;\n\n    interface IProvideClassInfo2\n    {\n        CONST_VTBL struct IProvideClassInfo2Vtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IProvideClassInfo2_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IProvideClassInfo2_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IProvideClassInfo2_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IProvideClassInfo2_GetClassInfo(This,ppTI)\t\\\n    (This)->lpVtbl -> GetClassInfo(This,ppTI)\n\n\n#define IProvideClassInfo2_GetGUID(This,dwGuidKind,pGUID)\t\\\n    (This)->lpVtbl -> GetGUID(This,dwGuidKind,pGUID)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IProvideClassInfo2_GetGUID_Proxy( \n    IProvideClassInfo2 __RPC_FAR * This,\n    /* [in] */ DWORD dwGuidKind,\n    /* [out] */ GUID __RPC_FAR *pGUID);\n\n\nvoid __RPC_STUB IProvideClassInfo2_GetGUID_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IProvideClassInfo2_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleControl_INTERFACE_DEFINED__\n#define __IOleControl_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleControl\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IOleControl __RPC_FAR *LPOLECONTROL;\n\ntypedef struct  tagCONTROLINFO\n    {\n    ULONG cb;\n    HACCEL hAccel;\n    USHORT cAccel;\n    DWORD dwFlags;\n    }\tCONTROLINFO;\n\ntypedef struct tagCONTROLINFO __RPC_FAR *LPCONTROLINFO;\n\ntypedef \nenum tagCTRLINFO\n    {\tCTRLINFO_EATS_RETURN\t= 1,\n\tCTRLINFO_EATS_ESCAPE\t= 2\n    }\tCTRLINFO;\n\n\nEXTERN_C const IID IID_IOleControl;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleControl : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetControlInfo( \n            /* [out] */ CONTROLINFO __RPC_FAR *pCI) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnMnemonic( \n            /* [in] */ MSG __RPC_FAR *pMsg) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnAmbientPropertyChange( \n            /* [in] */ DISPID dispID) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE FreezeEvents( \n            /* [in] */ BOOL bFreeze) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleControlVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleControl __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleControl __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleControl __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetControlInfo )( \n            IOleControl __RPC_FAR * This,\n            /* [out] */ CONTROLINFO __RPC_FAR *pCI);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnMnemonic )( \n            IOleControl __RPC_FAR * This,\n            /* [in] */ MSG __RPC_FAR *pMsg);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnAmbientPropertyChange )( \n            IOleControl __RPC_FAR * This,\n            /* [in] */ DISPID dispID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FreezeEvents )( \n            IOleControl __RPC_FAR * This,\n            /* [in] */ BOOL bFreeze);\n        \n        END_INTERFACE\n    } IOleControlVtbl;\n\n    interface IOleControl\n    {\n        CONST_VTBL struct IOleControlVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleControl_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleControl_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleControl_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleControl_GetControlInfo(This,pCI)\t\\\n    (This)->lpVtbl -> GetControlInfo(This,pCI)\n\n#define IOleControl_OnMnemonic(This,pMsg)\t\\\n    (This)->lpVtbl -> OnMnemonic(This,pMsg)\n\n#define IOleControl_OnAmbientPropertyChange(This,dispID)\t\\\n    (This)->lpVtbl -> OnAmbientPropertyChange(This,dispID)\n\n#define IOleControl_FreezeEvents(This,bFreeze)\t\\\n    (This)->lpVtbl -> FreezeEvents(This,bFreeze)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleControl_GetControlInfo_Proxy( \n    IOleControl __RPC_FAR * This,\n    /* [out] */ CONTROLINFO __RPC_FAR *pCI);\n\n\nvoid __RPC_STUB IOleControl_GetControlInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControl_OnMnemonic_Proxy( \n    IOleControl __RPC_FAR * This,\n    /* [in] */ MSG __RPC_FAR *pMsg);\n\n\nvoid __RPC_STUB IOleControl_OnMnemonic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControl_OnAmbientPropertyChange_Proxy( \n    IOleControl __RPC_FAR * This,\n    /* [in] */ DISPID dispID);\n\n\nvoid __RPC_STUB IOleControl_OnAmbientPropertyChange_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControl_FreezeEvents_Proxy( \n    IOleControl __RPC_FAR * This,\n    /* [in] */ BOOL bFreeze);\n\n\nvoid __RPC_STUB IOleControl_FreezeEvents_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleControl_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleControlSite_INTERFACE_DEFINED__\n#define __IOleControlSite_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleControlSite\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IOleControlSite __RPC_FAR *LPOLECONTROLSITE;\n\ntypedef struct  tagPOINTF\n    {\n    FLOAT x;\n    FLOAT y;\n    }\tPOINTF;\n\ntypedef struct tagPOINTF __RPC_FAR *LPPOINTF;\n\ntypedef \nenum tagXFORMCOORDS\n    {\tXFORMCOORDS_POSITION\t= 0x1,\n\tXFORMCOORDS_SIZE\t= 0x2,\n\tXFORMCOORDS_HIMETRICTOCONTAINER\t= 0x4,\n\tXFORMCOORDS_CONTAINERTOHIMETRIC\t= 0x8\n    }\tXFORMCOORDS;\n\n\nEXTERN_C const IID IID_IOleControlSite;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleControlSite : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE OnControlInfoChanged( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE LockInPlaceActive( \n            /* [in] */ BOOL fLock) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetExtendedControl( \n            /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE TransformCoords( \n            /* [out][in] */ POINTL __RPC_FAR *pPtlHimetric,\n            /* [out][in] */ POINTF __RPC_FAR *pPtfContainer,\n            /* [in] */ DWORD dwFlags) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( \n            /* [in] */ MSG __RPC_FAR *pMsg,\n            /* [in] */ DWORD grfModifiers) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnFocus( \n            /* [in] */ BOOL fGotFocus) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE ShowPropertyFrame( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleControlSiteVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleControlSite __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleControlSite __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleControlSite __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnControlInfoChanged )( \n            IOleControlSite __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LockInPlaceActive )( \n            IOleControlSite __RPC_FAR * This,\n            /* [in] */ BOOL fLock);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetExtendedControl )( \n            IOleControlSite __RPC_FAR * This,\n            /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *TransformCoords )( \n            IOleControlSite __RPC_FAR * This,\n            /* [out][in] */ POINTL __RPC_FAR *pPtlHimetric,\n            /* [out][in] */ POINTF __RPC_FAR *pPtfContainer,\n            /* [in] */ DWORD dwFlags);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *TranslateAccelerator )( \n            IOleControlSite __RPC_FAR * This,\n            /* [in] */ MSG __RPC_FAR *pMsg,\n            /* [in] */ DWORD grfModifiers);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnFocus )( \n            IOleControlSite __RPC_FAR * This,\n            /* [in] */ BOOL fGotFocus);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ShowPropertyFrame )( \n            IOleControlSite __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IOleControlSiteVtbl;\n\n    interface IOleControlSite\n    {\n        CONST_VTBL struct IOleControlSiteVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleControlSite_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleControlSite_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleControlSite_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleControlSite_OnControlInfoChanged(This)\t\\\n    (This)->lpVtbl -> OnControlInfoChanged(This)\n\n#define IOleControlSite_LockInPlaceActive(This,fLock)\t\\\n    (This)->lpVtbl -> LockInPlaceActive(This,fLock)\n\n#define IOleControlSite_GetExtendedControl(This,ppDisp)\t\\\n    (This)->lpVtbl -> GetExtendedControl(This,ppDisp)\n\n#define IOleControlSite_TransformCoords(This,pPtlHimetric,pPtfContainer,dwFlags)\t\\\n    (This)->lpVtbl -> TransformCoords(This,pPtlHimetric,pPtfContainer,dwFlags)\n\n#define IOleControlSite_TranslateAccelerator(This,pMsg,grfModifiers)\t\\\n    (This)->lpVtbl -> TranslateAccelerator(This,pMsg,grfModifiers)\n\n#define IOleControlSite_OnFocus(This,fGotFocus)\t\\\n    (This)->lpVtbl -> OnFocus(This,fGotFocus)\n\n#define IOleControlSite_ShowPropertyFrame(This)\t\\\n    (This)->lpVtbl -> ShowPropertyFrame(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_OnControlInfoChanged_Proxy( \n    IOleControlSite __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleControlSite_OnControlInfoChanged_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_LockInPlaceActive_Proxy( \n    IOleControlSite __RPC_FAR * This,\n    /* [in] */ BOOL fLock);\n\n\nvoid __RPC_STUB IOleControlSite_LockInPlaceActive_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_GetExtendedControl_Proxy( \n    IOleControlSite __RPC_FAR * This,\n    /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp);\n\n\nvoid __RPC_STUB IOleControlSite_GetExtendedControl_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_TransformCoords_Proxy( \n    IOleControlSite __RPC_FAR * This,\n    /* [out][in] */ POINTL __RPC_FAR *pPtlHimetric,\n    /* [out][in] */ POINTF __RPC_FAR *pPtfContainer,\n    /* [in] */ DWORD dwFlags);\n\n\nvoid __RPC_STUB IOleControlSite_TransformCoords_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_TranslateAccelerator_Proxy( \n    IOleControlSite __RPC_FAR * This,\n    /* [in] */ MSG __RPC_FAR *pMsg,\n    /* [in] */ DWORD grfModifiers);\n\n\nvoid __RPC_STUB IOleControlSite_TranslateAccelerator_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_OnFocus_Proxy( \n    IOleControlSite __RPC_FAR * This,\n    /* [in] */ BOOL fGotFocus);\n\n\nvoid __RPC_STUB IOleControlSite_OnFocus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleControlSite_ShowPropertyFrame_Proxy( \n    IOleControlSite __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleControlSite_ShowPropertyFrame_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleControlSite_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPropertyPage_INTERFACE_DEFINED__\n#define __IPropertyPage_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPropertyPage\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPropertyPage __RPC_FAR *LPPROPERTYPAGE;\n\ntypedef struct  tagPROPPAGEINFO\n    {\n    ULONG cb;\n    LPOLESTR pszTitle;\n    SIZE size;\n    LPOLESTR pszDocString;\n    LPOLESTR pszHelpFile;\n    DWORD dwHelpContext;\n    }\tPROPPAGEINFO;\n\ntypedef struct tagPROPPAGEINFO __RPC_FAR *LPPROPPAGEINFO;\n\n\nEXTERN_C const IID IID_IPropertyPage;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPropertyPage : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE SetPageSite( \n            /* [in] */ IPropertyPageSite __RPC_FAR *pPageSite) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Activate( \n            /* [in] */ HWND hWndParent,\n            /* [in] */ LPCRECT pRect,\n            /* [in] */ BOOL bModal) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Deactivate( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetPageInfo( \n            /* [out] */ PROPPAGEINFO __RPC_FAR *pPageInfo) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetObjects( \n            /* [in] */ ULONG cObjects,\n            /* [size_is][in] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Show( \n            /* [in] */ UINT nCmdShow) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Move( \n            /* [in] */ LPCRECT pRect) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE IsPageDirty( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Apply( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Help( \n            /* [in] */ LPCOLESTR pszHelpDir) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( \n            /* [in] */ MSG __RPC_FAR *pMsg) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPropertyPageVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPropertyPage __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPropertyPage __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetPageSite )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ IPropertyPageSite __RPC_FAR *pPageSite);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Activate )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ HWND hWndParent,\n            /* [in] */ LPCRECT pRect,\n            /* [in] */ BOOL bModal);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Deactivate )( \n            IPropertyPage __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPageInfo )( \n            IPropertyPage __RPC_FAR * This,\n            /* [out] */ PROPPAGEINFO __RPC_FAR *pPageInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetObjects )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ ULONG cObjects,\n            /* [size_is][in] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Show )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ UINT nCmdShow);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Move )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ LPCRECT pRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsPageDirty )( \n            IPropertyPage __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Apply )( \n            IPropertyPage __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Help )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ LPCOLESTR pszHelpDir);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *TranslateAccelerator )( \n            IPropertyPage __RPC_FAR * This,\n            /* [in] */ MSG __RPC_FAR *pMsg);\n        \n        END_INTERFACE\n    } IPropertyPageVtbl;\n\n    interface IPropertyPage\n    {\n        CONST_VTBL struct IPropertyPageVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPropertyPage_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPropertyPage_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPropertyPage_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPropertyPage_SetPageSite(This,pPageSite)\t\\\n    (This)->lpVtbl -> SetPageSite(This,pPageSite)\n\n#define IPropertyPage_Activate(This,hWndParent,pRect,bModal)\t\\\n    (This)->lpVtbl -> Activate(This,hWndParent,pRect,bModal)\n\n#define IPropertyPage_Deactivate(This)\t\\\n    (This)->lpVtbl -> Deactivate(This)\n\n#define IPropertyPage_GetPageInfo(This,pPageInfo)\t\\\n    (This)->lpVtbl -> GetPageInfo(This,pPageInfo)\n\n#define IPropertyPage_SetObjects(This,cObjects,ppUnk)\t\\\n    (This)->lpVtbl -> SetObjects(This,cObjects,ppUnk)\n\n#define IPropertyPage_Show(This,nCmdShow)\t\\\n    (This)->lpVtbl -> Show(This,nCmdShow)\n\n#define IPropertyPage_Move(This,pRect)\t\\\n    (This)->lpVtbl -> Move(This,pRect)\n\n#define IPropertyPage_IsPageDirty(This)\t\\\n    (This)->lpVtbl -> IsPageDirty(This)\n\n#define IPropertyPage_Apply(This)\t\\\n    (This)->lpVtbl -> Apply(This)\n\n#define IPropertyPage_Help(This,pszHelpDir)\t\\\n    (This)->lpVtbl -> Help(This,pszHelpDir)\n\n#define IPropertyPage_TranslateAccelerator(This,pMsg)\t\\\n    (This)->lpVtbl -> TranslateAccelerator(This,pMsg)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_SetPageSite_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ IPropertyPageSite __RPC_FAR *pPageSite);\n\n\nvoid __RPC_STUB IPropertyPage_SetPageSite_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Activate_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ HWND hWndParent,\n    /* [in] */ LPCRECT pRect,\n    /* [in] */ BOOL bModal);\n\n\nvoid __RPC_STUB IPropertyPage_Activate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Deactivate_Proxy( \n    IPropertyPage __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPropertyPage_Deactivate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_GetPageInfo_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [out] */ PROPPAGEINFO __RPC_FAR *pPageInfo);\n\n\nvoid __RPC_STUB IPropertyPage_GetPageInfo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_SetObjects_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ ULONG cObjects,\n    /* [size_is][in] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk);\n\n\nvoid __RPC_STUB IPropertyPage_SetObjects_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Show_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ UINT nCmdShow);\n\n\nvoid __RPC_STUB IPropertyPage_Show_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Move_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ LPCRECT pRect);\n\n\nvoid __RPC_STUB IPropertyPage_Move_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_IsPageDirty_Proxy( \n    IPropertyPage __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPropertyPage_IsPageDirty_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Apply_Proxy( \n    IPropertyPage __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPropertyPage_Apply_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_Help_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszHelpDir);\n\n\nvoid __RPC_STUB IPropertyPage_Help_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage_TranslateAccelerator_Proxy( \n    IPropertyPage __RPC_FAR * This,\n    /* [in] */ MSG __RPC_FAR *pMsg);\n\n\nvoid __RPC_STUB IPropertyPage_TranslateAccelerator_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPropertyPage_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPropertyPage2_INTERFACE_DEFINED__\n#define __IPropertyPage2_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPropertyPage2\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPropertyPage2 __RPC_FAR *LPPROPERTYPAGE2;\n\n\nEXTERN_C const IID IID_IPropertyPage2;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPropertyPage2 : public IPropertyPage\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE EditProperty( \n            /* [in] */ DISPID dispID) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPropertyPage2Vtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPropertyPage2 __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPropertyPage2 __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetPageSite )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ IPropertyPageSite __RPC_FAR *pPageSite);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Activate )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ HWND hWndParent,\n            /* [in] */ LPCRECT pRect,\n            /* [in] */ BOOL bModal);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Deactivate )( \n            IPropertyPage2 __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPageInfo )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [out] */ PROPPAGEINFO __RPC_FAR *pPageInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetObjects )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ ULONG cObjects,\n            /* [size_is][in] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Show )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ UINT nCmdShow);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Move )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ LPCRECT pRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsPageDirty )( \n            IPropertyPage2 __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Apply )( \n            IPropertyPage2 __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Help )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ LPCOLESTR pszHelpDir);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *TranslateAccelerator )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ MSG __RPC_FAR *pMsg);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EditProperty )( \n            IPropertyPage2 __RPC_FAR * This,\n            /* [in] */ DISPID dispID);\n        \n        END_INTERFACE\n    } IPropertyPage2Vtbl;\n\n    interface IPropertyPage2\n    {\n        CONST_VTBL struct IPropertyPage2Vtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPropertyPage2_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPropertyPage2_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPropertyPage2_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPropertyPage2_SetPageSite(This,pPageSite)\t\\\n    (This)->lpVtbl -> SetPageSite(This,pPageSite)\n\n#define IPropertyPage2_Activate(This,hWndParent,pRect,bModal)\t\\\n    (This)->lpVtbl -> Activate(This,hWndParent,pRect,bModal)\n\n#define IPropertyPage2_Deactivate(This)\t\\\n    (This)->lpVtbl -> Deactivate(This)\n\n#define IPropertyPage2_GetPageInfo(This,pPageInfo)\t\\\n    (This)->lpVtbl -> GetPageInfo(This,pPageInfo)\n\n#define IPropertyPage2_SetObjects(This,cObjects,ppUnk)\t\\\n    (This)->lpVtbl -> SetObjects(This,cObjects,ppUnk)\n\n#define IPropertyPage2_Show(This,nCmdShow)\t\\\n    (This)->lpVtbl -> Show(This,nCmdShow)\n\n#define IPropertyPage2_Move(This,pRect)\t\\\n    (This)->lpVtbl -> Move(This,pRect)\n\n#define IPropertyPage2_IsPageDirty(This)\t\\\n    (This)->lpVtbl -> IsPageDirty(This)\n\n#define IPropertyPage2_Apply(This)\t\\\n    (This)->lpVtbl -> Apply(This)\n\n#define IPropertyPage2_Help(This,pszHelpDir)\t\\\n    (This)->lpVtbl -> Help(This,pszHelpDir)\n\n#define IPropertyPage2_TranslateAccelerator(This,pMsg)\t\\\n    (This)->lpVtbl -> TranslateAccelerator(This,pMsg)\n\n\n#define IPropertyPage2_EditProperty(This,dispID)\t\\\n    (This)->lpVtbl -> EditProperty(This,dispID)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPage2_EditProperty_Proxy( \n    IPropertyPage2 __RPC_FAR * This,\n    /* [in] */ DISPID dispID);\n\n\nvoid __RPC_STUB IPropertyPage2_EditProperty_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPropertyPage2_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPropertyPageSite_INTERFACE_DEFINED__\n#define __IPropertyPageSite_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPropertyPageSite\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPropertyPageSite __RPC_FAR *LPPROPERTYPAGESITE;\n\ntypedef \nenum tagPROPPAGESTATUS\n    {\tPROPPAGESTATUS_DIRTY\t= 0x1,\n\tPROPPAGESTATUS_VALIDATE\t= 0x2,\n\tPROPPAGESTATUS_CLEAN\t= 0x4\n    }\tPROPPAGESTATUS;\n\n\nEXTERN_C const IID IID_IPropertyPageSite;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPropertyPageSite : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE OnStatusChange( \n            /* [in] */ DWORD dwFlags) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetLocaleID( \n            /* [out] */ LCID __RPC_FAR *pLocaleID) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetPageContainer( \n            /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( \n            /* [in] */ MSG __RPC_FAR *pMsg) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPropertyPageSiteVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPropertyPageSite __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPropertyPageSite __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPropertyPageSite __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnStatusChange )( \n            IPropertyPageSite __RPC_FAR * This,\n            /* [in] */ DWORD dwFlags);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetLocaleID )( \n            IPropertyPageSite __RPC_FAR * This,\n            /* [out] */ LCID __RPC_FAR *pLocaleID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPageContainer )( \n            IPropertyPageSite __RPC_FAR * This,\n            /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *TranslateAccelerator )( \n            IPropertyPageSite __RPC_FAR * This,\n            /* [in] */ MSG __RPC_FAR *pMsg);\n        \n        END_INTERFACE\n    } IPropertyPageSiteVtbl;\n\n    interface IPropertyPageSite\n    {\n        CONST_VTBL struct IPropertyPageSiteVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPropertyPageSite_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPropertyPageSite_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPropertyPageSite_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPropertyPageSite_OnStatusChange(This,dwFlags)\t\\\n    (This)->lpVtbl -> OnStatusChange(This,dwFlags)\n\n#define IPropertyPageSite_GetLocaleID(This,pLocaleID)\t\\\n    (This)->lpVtbl -> GetLocaleID(This,pLocaleID)\n\n#define IPropertyPageSite_GetPageContainer(This,ppUnk)\t\\\n    (This)->lpVtbl -> GetPageContainer(This,ppUnk)\n\n#define IPropertyPageSite_TranslateAccelerator(This,pMsg)\t\\\n    (This)->lpVtbl -> TranslateAccelerator(This,pMsg)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPageSite_OnStatusChange_Proxy( \n    IPropertyPageSite __RPC_FAR * This,\n    /* [in] */ DWORD dwFlags);\n\n\nvoid __RPC_STUB IPropertyPageSite_OnStatusChange_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPageSite_GetLocaleID_Proxy( \n    IPropertyPageSite __RPC_FAR * This,\n    /* [out] */ LCID __RPC_FAR *pLocaleID);\n\n\nvoid __RPC_STUB IPropertyPageSite_GetLocaleID_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPageSite_GetPageContainer_Proxy( \n    IPropertyPageSite __RPC_FAR * This,\n    /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk);\n\n\nvoid __RPC_STUB IPropertyPageSite_GetPageContainer_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyPageSite_TranslateAccelerator_Proxy( \n    IPropertyPageSite __RPC_FAR * This,\n    /* [in] */ MSG __RPC_FAR *pMsg);\n\n\nvoid __RPC_STUB IPropertyPageSite_TranslateAccelerator_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPropertyPageSite_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPropertyNotifySink_INTERFACE_DEFINED__\n#define __IPropertyNotifySink_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPropertyNotifySink\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPropertyNotifySink __RPC_FAR *LPPROPERTYNOTIFYSINK;\n\n\nEXTERN_C const IID IID_IPropertyNotifySink;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPropertyNotifySink : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE OnChanged( \n            /* [in] */ DISPID dispID) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnRequestEdit( \n            /* [in] */ DISPID dispID) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPropertyNotifySinkVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPropertyNotifySink __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPropertyNotifySink __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPropertyNotifySink __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnChanged )( \n            IPropertyNotifySink __RPC_FAR * This,\n            /* [in] */ DISPID dispID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnRequestEdit )( \n            IPropertyNotifySink __RPC_FAR * This,\n            /* [in] */ DISPID dispID);\n        \n        END_INTERFACE\n    } IPropertyNotifySinkVtbl;\n\n    interface IPropertyNotifySink\n    {\n        CONST_VTBL struct IPropertyNotifySinkVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPropertyNotifySink_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPropertyNotifySink_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPropertyNotifySink_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPropertyNotifySink_OnChanged(This,dispID)\t\\\n    (This)->lpVtbl -> OnChanged(This,dispID)\n\n#define IPropertyNotifySink_OnRequestEdit(This,dispID)\t\\\n    (This)->lpVtbl -> OnRequestEdit(This,dispID)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPropertyNotifySink_OnChanged_Proxy( \n    IPropertyNotifySink __RPC_FAR * This,\n    /* [in] */ DISPID dispID);\n\n\nvoid __RPC_STUB IPropertyNotifySink_OnChanged_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyNotifySink_OnRequestEdit_Proxy( \n    IPropertyNotifySink __RPC_FAR * This,\n    /* [in] */ DISPID dispID);\n\n\nvoid __RPC_STUB IPropertyNotifySink_OnRequestEdit_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPropertyNotifySink_INTERFACE_DEFINED__ */\n\n\n#ifndef __ISpecifyPropertyPages_INTERFACE_DEFINED__\n#define __ISpecifyPropertyPages_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: ISpecifyPropertyPages\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef ISpecifyPropertyPages __RPC_FAR *LPSPECIFYPROPERTYPAGES;\n\ntypedef struct  tagCAUUID\n    {\n    ULONG cElems;\n    /* [size_is] */ GUID __RPC_FAR *pElems;\n    }\tCAUUID;\n\ntypedef struct tagCAUUID __RPC_FAR *LPCAUUID;\n\n\nEXTERN_C const IID IID_ISpecifyPropertyPages;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface ISpecifyPropertyPages : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetPages( \n            /* [out] */ CAUUID __RPC_FAR *pPages) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct ISpecifyPropertyPagesVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            ISpecifyPropertyPages __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            ISpecifyPropertyPages __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            ISpecifyPropertyPages __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPages )( \n            ISpecifyPropertyPages __RPC_FAR * This,\n            /* [out] */ CAUUID __RPC_FAR *pPages);\n        \n        END_INTERFACE\n    } ISpecifyPropertyPagesVtbl;\n\n    interface ISpecifyPropertyPages\n    {\n        CONST_VTBL struct ISpecifyPropertyPagesVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define ISpecifyPropertyPages_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define ISpecifyPropertyPages_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define ISpecifyPropertyPages_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define ISpecifyPropertyPages_GetPages(This,pPages)\t\\\n    (This)->lpVtbl -> GetPages(This,pPages)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE ISpecifyPropertyPages_GetPages_Proxy( \n    ISpecifyPropertyPages __RPC_FAR * This,\n    /* [out] */ CAUUID __RPC_FAR *pPages);\n\n\nvoid __RPC_STUB ISpecifyPropertyPages_GetPages_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __ISpecifyPropertyPages_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPersistMemory_INTERFACE_DEFINED__\n#define __IPersistMemory_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPersistMemory\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPersistMemory __RPC_FAR *LPPERSISTMEMORY;\n\n\nEXTERN_C const IID IID_IPersistMemory;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPersistMemory : public IPersist\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE IsDirty( void) = 0;\n        \n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Load( \n            /* [size_is][in] */ LPVOID pMem,\n            /* [in] */ ULONG cbSize) = 0;\n        \n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Save( \n            /* [size_is][in] */ LPVOID pMem,\n            /* [in] */ BOOL fClearDirty,\n            /* [in] */ ULONG cbSize) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetSizeMax( \n            /* [out] */ ULONG __RPC_FAR *pCbSize) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE InitNew( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPersistMemoryVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPersistMemory __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPersistMemory __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPersistMemory __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassID )( \n            IPersistMemory __RPC_FAR * This,\n            /* [out] */ CLSID __RPC_FAR *pClassID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsDirty )( \n            IPersistMemory __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Load )( \n            IPersistMemory __RPC_FAR * This,\n            /* [size_is][in] */ LPVOID pMem,\n            /* [in] */ ULONG cbSize);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Save )( \n            IPersistMemory __RPC_FAR * This,\n            /* [size_is][in] */ LPVOID pMem,\n            /* [in] */ BOOL fClearDirty,\n            /* [in] */ ULONG cbSize);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetSizeMax )( \n            IPersistMemory __RPC_FAR * This,\n            /* [out] */ ULONG __RPC_FAR *pCbSize);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InitNew )( \n            IPersistMemory __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IPersistMemoryVtbl;\n\n    interface IPersistMemory\n    {\n        CONST_VTBL struct IPersistMemoryVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPersistMemory_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPersistMemory_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPersistMemory_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPersistMemory_GetClassID(This,pClassID)\t\\\n    (This)->lpVtbl -> GetClassID(This,pClassID)\n\n\n#define IPersistMemory_IsDirty(This)\t\\\n    (This)->lpVtbl -> IsDirty(This)\n\n#define IPersistMemory_Load(This,pMem,cbSize)\t\\\n    (This)->lpVtbl -> Load(This,pMem,cbSize)\n\n#define IPersistMemory_Save(This,pMem,fClearDirty,cbSize)\t\\\n    (This)->lpVtbl -> Save(This,pMem,fClearDirty,cbSize)\n\n#define IPersistMemory_GetSizeMax(This,pCbSize)\t\\\n    (This)->lpVtbl -> GetSizeMax(This,pCbSize)\n\n#define IPersistMemory_InitNew(This)\t\\\n    (This)->lpVtbl -> InitNew(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPersistMemory_IsDirty_Proxy( \n    IPersistMemory __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPersistMemory_IsDirty_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPersistMemory_RemoteLoad_Proxy( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ BYTE __RPC_FAR *pMem,\n    /* [in] */ ULONG cbSize);\n\n\nvoid __RPC_STUB IPersistMemory_RemoteLoad_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPersistMemory_RemoteSave_Proxy( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ BYTE __RPC_FAR *pMem,\n    /* [in] */ BOOL fClearDirty,\n    /* [in] */ ULONG cbSize);\n\n\nvoid __RPC_STUB IPersistMemory_RemoteSave_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistMemory_GetSizeMax_Proxy( \n    IPersistMemory __RPC_FAR * This,\n    /* [out] */ ULONG __RPC_FAR *pCbSize);\n\n\nvoid __RPC_STUB IPersistMemory_GetSizeMax_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistMemory_InitNew_Proxy( \n    IPersistMemory __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPersistMemory_InitNew_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPersistMemory_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPersistStreamInit_INTERFACE_DEFINED__\n#define __IPersistStreamInit_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPersistStreamInit\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPersistStreamInit __RPC_FAR *LPPERSISTSTREAMINIT;\n\n\nEXTERN_C const IID IID_IPersistStreamInit;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPersistStreamInit : public IPersist\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE IsDirty( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Load( \n            /* [in] */ LPSTREAM pStm) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Save( \n            /* [in] */ LPSTREAM pStm,\n            /* [in] */ BOOL fClearDirty) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetSizeMax( \n            /* [out] */ ULARGE_INTEGER __RPC_FAR *pCbSize) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE InitNew( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPersistStreamInitVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPersistStreamInit __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPersistStreamInit __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPersistStreamInit __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassID )( \n            IPersistStreamInit __RPC_FAR * This,\n            /* [out] */ CLSID __RPC_FAR *pClassID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsDirty )( \n            IPersistStreamInit __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Load )( \n            IPersistStreamInit __RPC_FAR * This,\n            /* [in] */ LPSTREAM pStm);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Save )( \n            IPersistStreamInit __RPC_FAR * This,\n            /* [in] */ LPSTREAM pStm,\n            /* [in] */ BOOL fClearDirty);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetSizeMax )( \n            IPersistStreamInit __RPC_FAR * This,\n            /* [out] */ ULARGE_INTEGER __RPC_FAR *pCbSize);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InitNew )( \n            IPersistStreamInit __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IPersistStreamInitVtbl;\n\n    interface IPersistStreamInit\n    {\n        CONST_VTBL struct IPersistStreamInitVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPersistStreamInit_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPersistStreamInit_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPersistStreamInit_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPersistStreamInit_GetClassID(This,pClassID)\t\\\n    (This)->lpVtbl -> GetClassID(This,pClassID)\n\n\n#define IPersistStreamInit_IsDirty(This)\t\\\n    (This)->lpVtbl -> IsDirty(This)\n\n#define IPersistStreamInit_Load(This,pStm)\t\\\n    (This)->lpVtbl -> Load(This,pStm)\n\n#define IPersistStreamInit_Save(This,pStm,fClearDirty)\t\\\n    (This)->lpVtbl -> Save(This,pStm,fClearDirty)\n\n#define IPersistStreamInit_GetSizeMax(This,pCbSize)\t\\\n    (This)->lpVtbl -> GetSizeMax(This,pCbSize)\n\n#define IPersistStreamInit_InitNew(This)\t\\\n    (This)->lpVtbl -> InitNew(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPersistStreamInit_IsDirty_Proxy( \n    IPersistStreamInit __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPersistStreamInit_IsDirty_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistStreamInit_Load_Proxy( \n    IPersistStreamInit __RPC_FAR * This,\n    /* [in] */ LPSTREAM pStm);\n\n\nvoid __RPC_STUB IPersistStreamInit_Load_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistStreamInit_Save_Proxy( \n    IPersistStreamInit __RPC_FAR * This,\n    /* [in] */ LPSTREAM pStm,\n    /* [in] */ BOOL fClearDirty);\n\n\nvoid __RPC_STUB IPersistStreamInit_Save_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistStreamInit_GetSizeMax_Proxy( \n    IPersistStreamInit __RPC_FAR * This,\n    /* [out] */ ULARGE_INTEGER __RPC_FAR *pCbSize);\n\n\nvoid __RPC_STUB IPersistStreamInit_GetSizeMax_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistStreamInit_InitNew_Proxy( \n    IPersistStreamInit __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPersistStreamInit_InitNew_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPersistStreamInit_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPersistPropertyBag_INTERFACE_DEFINED__\n#define __IPersistPropertyBag_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPersistPropertyBag\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPersistPropertyBag __RPC_FAR *LPPERSISTPROPERTYBAG;\n\n\nEXTERN_C const IID IID_IPersistPropertyBag;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPersistPropertyBag : public IPersist\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE InitNew( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Load( \n            /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n            /* [in] */ IErrorLog __RPC_FAR *pErrorLog) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Save( \n            /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n            /* [in] */ BOOL fClearDirty,\n            /* [in] */ BOOL fSaveAllProperties) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPersistPropertyBagVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPersistPropertyBag __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPersistPropertyBag __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPersistPropertyBag __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassID )( \n            IPersistPropertyBag __RPC_FAR * This,\n            /* [out] */ CLSID __RPC_FAR *pClassID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InitNew )( \n            IPersistPropertyBag __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Load )( \n            IPersistPropertyBag __RPC_FAR * This,\n            /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n            /* [in] */ IErrorLog __RPC_FAR *pErrorLog);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Save )( \n            IPersistPropertyBag __RPC_FAR * This,\n            /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n            /* [in] */ BOOL fClearDirty,\n            /* [in] */ BOOL fSaveAllProperties);\n        \n        END_INTERFACE\n    } IPersistPropertyBagVtbl;\n\n    interface IPersistPropertyBag\n    {\n        CONST_VTBL struct IPersistPropertyBagVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPersistPropertyBag_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPersistPropertyBag_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPersistPropertyBag_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPersistPropertyBag_GetClassID(This,pClassID)\t\\\n    (This)->lpVtbl -> GetClassID(This,pClassID)\n\n\n#define IPersistPropertyBag_InitNew(This)\t\\\n    (This)->lpVtbl -> InitNew(This)\n\n#define IPersistPropertyBag_Load(This,pPropBag,pErrorLog)\t\\\n    (This)->lpVtbl -> Load(This,pPropBag,pErrorLog)\n\n#define IPersistPropertyBag_Save(This,pPropBag,fClearDirty,fSaveAllProperties)\t\\\n    (This)->lpVtbl -> Save(This,pPropBag,fClearDirty,fSaveAllProperties)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPersistPropertyBag_InitNew_Proxy( \n    IPersistPropertyBag __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPersistPropertyBag_InitNew_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistPropertyBag_Load_Proxy( \n    IPersistPropertyBag __RPC_FAR * This,\n    /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n    /* [in] */ IErrorLog __RPC_FAR *pErrorLog);\n\n\nvoid __RPC_STUB IPersistPropertyBag_Load_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPersistPropertyBag_Save_Proxy( \n    IPersistPropertyBag __RPC_FAR * This,\n    /* [in] */ IPropertyBag __RPC_FAR *pPropBag,\n    /* [in] */ BOOL fClearDirty,\n    /* [in] */ BOOL fSaveAllProperties);\n\n\nvoid __RPC_STUB IPersistPropertyBag_Save_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPersistPropertyBag_INTERFACE_DEFINED__ */\n\n\n#ifndef __ISimpleFrameSite_INTERFACE_DEFINED__\n#define __ISimpleFrameSite_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: ISimpleFrameSite\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef ISimpleFrameSite __RPC_FAR *LPSIMPLEFRAMESITE;\n\n\nEXTERN_C const IID IID_ISimpleFrameSite;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface ISimpleFrameSite : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE PreMessageFilter( \n            /* [in] */ HWND hWnd,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wp,\n            /* [in] */ LPARAM lp,\n            /* [out] */ LRESULT __RPC_FAR *plResult,\n            /* [out] */ DWORD __RPC_FAR *pdwCookie) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE PostMessageFilter( \n            /* [in] */ HWND hWnd,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wp,\n            /* [in] */ LPARAM lp,\n            /* [out] */ LRESULT __RPC_FAR *plResult,\n            /* [in] */ DWORD dwCookie) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct ISimpleFrameSiteVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            ISimpleFrameSite __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            ISimpleFrameSite __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            ISimpleFrameSite __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PreMessageFilter )( \n            ISimpleFrameSite __RPC_FAR * This,\n            /* [in] */ HWND hWnd,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wp,\n            /* [in] */ LPARAM lp,\n            /* [out] */ LRESULT __RPC_FAR *plResult,\n            /* [out] */ DWORD __RPC_FAR *pdwCookie);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PostMessageFilter )( \n            ISimpleFrameSite __RPC_FAR * This,\n            /* [in] */ HWND hWnd,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wp,\n            /* [in] */ LPARAM lp,\n            /* [out] */ LRESULT __RPC_FAR *plResult,\n            /* [in] */ DWORD dwCookie);\n        \n        END_INTERFACE\n    } ISimpleFrameSiteVtbl;\n\n    interface ISimpleFrameSite\n    {\n        CONST_VTBL struct ISimpleFrameSiteVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define ISimpleFrameSite_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define ISimpleFrameSite_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define ISimpleFrameSite_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define ISimpleFrameSite_PreMessageFilter(This,hWnd,msg,wp,lp,plResult,pdwCookie)\t\\\n    (This)->lpVtbl -> PreMessageFilter(This,hWnd,msg,wp,lp,plResult,pdwCookie)\n\n#define ISimpleFrameSite_PostMessageFilter(This,hWnd,msg,wp,lp,plResult,dwCookie)\t\\\n    (This)->lpVtbl -> PostMessageFilter(This,hWnd,msg,wp,lp,plResult,dwCookie)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE ISimpleFrameSite_PreMessageFilter_Proxy( \n    ISimpleFrameSite __RPC_FAR * This,\n    /* [in] */ HWND hWnd,\n    /* [in] */ UINT msg,\n    /* [in] */ WPARAM wp,\n    /* [in] */ LPARAM lp,\n    /* [out] */ LRESULT __RPC_FAR *plResult,\n    /* [out] */ DWORD __RPC_FAR *pdwCookie);\n\n\nvoid __RPC_STUB ISimpleFrameSite_PreMessageFilter_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE ISimpleFrameSite_PostMessageFilter_Proxy( \n    ISimpleFrameSite __RPC_FAR * This,\n    /* [in] */ HWND hWnd,\n    /* [in] */ UINT msg,\n    /* [in] */ WPARAM wp,\n    /* [in] */ LPARAM lp,\n    /* [out] */ LRESULT __RPC_FAR *plResult,\n    /* [in] */ DWORD dwCookie);\n\n\nvoid __RPC_STUB ISimpleFrameSite_PostMessageFilter_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __ISimpleFrameSite_INTERFACE_DEFINED__ */\n\n\n#ifndef __IFont_INTERFACE_DEFINED__\n#define __IFont_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IFont\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IFont __RPC_FAR *LPFONT;\n\n#if defined(_WIN32) && !defined(OLE2ANSI)\ntypedef TEXTMETRICW TEXTMETRICOLE;\n\n#else\ntypedef TEXTMETRIC TEXTMETRICOLE;\n#endif\ntypedef TEXTMETRICOLE __RPC_FAR *LPTEXTMETRICOLE;\n\n\nEXTERN_C const IID IID_IFont;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IFont : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE get_Name( \n            /* [out] */ BSTR __RPC_FAR *pName) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Name( \n            /* [in] */ BSTR name) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Size( \n            /* [out] */ CY __RPC_FAR *pSize) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Size( \n            /* [in] */ CY size) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Bold( \n            /* [out] */ BOOL __RPC_FAR *pBold) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Bold( \n            /* [in] */ BOOL bold) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Italic( \n            /* [out] */ BOOL __RPC_FAR *pItalic) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Italic( \n            /* [in] */ BOOL italic) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Underline( \n            /* [out] */ BOOL __RPC_FAR *pUnderline) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Underline( \n            /* [in] */ BOOL underline) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Strikethrough( \n            /* [out] */ BOOL __RPC_FAR *pStrikethrough) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Strikethrough( \n            /* [in] */ BOOL strikethrough) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Weight( \n            /* [out] */ SHORT __RPC_FAR *pWeight) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Weight( \n            /* [in] */ SHORT weight) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Charset( \n            /* [out] */ SHORT __RPC_FAR *pCharset) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_Charset( \n            /* [in] */ SHORT charset) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_hFont( \n            /* [out] */ HFONT __RPC_FAR *phFont) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Clone( \n            /* [out] */ IFont __RPC_FAR *__RPC_FAR *ppFont) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE IsEqual( \n            /* [in] */ IFont __RPC_FAR *pFontOther) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetRatio( \n            /* [in] */ LONG cyLogical,\n            /* [in] */ LONG cyHimetric) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE QueryTextMetrics( \n            /* [out] */ TEXTMETRICOLE __RPC_FAR *pTM) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE AddRefHfont( \n            /* [in] */ HFONT hFont) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE ReleaseHfont( \n            /* [in] */ HFONT hFont) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetHdc( \n            /* [in] */ HDC hDC) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IFontVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IFont __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IFont __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IFont __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Name )( \n            IFont __RPC_FAR * This,\n            /* [out] */ BSTR __RPC_FAR *pName);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Name )( \n            IFont __RPC_FAR * This,\n            /* [in] */ BSTR name);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Size )( \n            IFont __RPC_FAR * This,\n            /* [out] */ CY __RPC_FAR *pSize);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Size )( \n            IFont __RPC_FAR * This,\n            /* [in] */ CY size);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Bold )( \n            IFont __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pBold);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Bold )( \n            IFont __RPC_FAR * This,\n            /* [in] */ BOOL bold);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Italic )( \n            IFont __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pItalic);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Italic )( \n            IFont __RPC_FAR * This,\n            /* [in] */ BOOL italic);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Underline )( \n            IFont __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pUnderline);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Underline )( \n            IFont __RPC_FAR * This,\n            /* [in] */ BOOL underline);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Strikethrough )( \n            IFont __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pStrikethrough);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Strikethrough )( \n            IFont __RPC_FAR * This,\n            /* [in] */ BOOL strikethrough);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Weight )( \n            IFont __RPC_FAR * This,\n            /* [out] */ SHORT __RPC_FAR *pWeight);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Weight )( \n            IFont __RPC_FAR * This,\n            /* [in] */ SHORT weight);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Charset )( \n            IFont __RPC_FAR * This,\n            /* [out] */ SHORT __RPC_FAR *pCharset);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Charset )( \n            IFont __RPC_FAR * This,\n            /* [in] */ SHORT charset);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_hFont )( \n            IFont __RPC_FAR * This,\n            /* [out] */ HFONT __RPC_FAR *phFont);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( \n            IFont __RPC_FAR * This,\n            /* [out] */ IFont __RPC_FAR *__RPC_FAR *ppFont);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsEqual )( \n            IFont __RPC_FAR * This,\n            /* [in] */ IFont __RPC_FAR *pFontOther);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetRatio )( \n            IFont __RPC_FAR * This,\n            /* [in] */ LONG cyLogical,\n            /* [in] */ LONG cyHimetric);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryTextMetrics )( \n            IFont __RPC_FAR * This,\n            /* [out] */ TEXTMETRICOLE __RPC_FAR *pTM);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddRefHfont )( \n            IFont __RPC_FAR * This,\n            /* [in] */ HFONT hFont);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReleaseHfont )( \n            IFont __RPC_FAR * This,\n            /* [in] */ HFONT hFont);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetHdc )( \n            IFont __RPC_FAR * This,\n            /* [in] */ HDC hDC);\n        \n        END_INTERFACE\n    } IFontVtbl;\n\n    interface IFont\n    {\n        CONST_VTBL struct IFontVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IFont_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IFont_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IFont_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IFont_get_Name(This,pName)\t\\\n    (This)->lpVtbl -> get_Name(This,pName)\n\n#define IFont_put_Name(This,name)\t\\\n    (This)->lpVtbl -> put_Name(This,name)\n\n#define IFont_get_Size(This,pSize)\t\\\n    (This)->lpVtbl -> get_Size(This,pSize)\n\n#define IFont_put_Size(This,size)\t\\\n    (This)->lpVtbl -> put_Size(This,size)\n\n#define IFont_get_Bold(This,pBold)\t\\\n    (This)->lpVtbl -> get_Bold(This,pBold)\n\n#define IFont_put_Bold(This,bold)\t\\\n    (This)->lpVtbl -> put_Bold(This,bold)\n\n#define IFont_get_Italic(This,pItalic)\t\\\n    (This)->lpVtbl -> get_Italic(This,pItalic)\n\n#define IFont_put_Italic(This,italic)\t\\\n    (This)->lpVtbl -> put_Italic(This,italic)\n\n#define IFont_get_Underline(This,pUnderline)\t\\\n    (This)->lpVtbl -> get_Underline(This,pUnderline)\n\n#define IFont_put_Underline(This,underline)\t\\\n    (This)->lpVtbl -> put_Underline(This,underline)\n\n#define IFont_get_Strikethrough(This,pStrikethrough)\t\\\n    (This)->lpVtbl -> get_Strikethrough(This,pStrikethrough)\n\n#define IFont_put_Strikethrough(This,strikethrough)\t\\\n    (This)->lpVtbl -> put_Strikethrough(This,strikethrough)\n\n#define IFont_get_Weight(This,pWeight)\t\\\n    (This)->lpVtbl -> get_Weight(This,pWeight)\n\n#define IFont_put_Weight(This,weight)\t\\\n    (This)->lpVtbl -> put_Weight(This,weight)\n\n#define IFont_get_Charset(This,pCharset)\t\\\n    (This)->lpVtbl -> get_Charset(This,pCharset)\n\n#define IFont_put_Charset(This,charset)\t\\\n    (This)->lpVtbl -> put_Charset(This,charset)\n\n#define IFont_get_hFont(This,phFont)\t\\\n    (This)->lpVtbl -> get_hFont(This,phFont)\n\n#define IFont_Clone(This,ppFont)\t\\\n    (This)->lpVtbl -> Clone(This,ppFont)\n\n#define IFont_IsEqual(This,pFontOther)\t\\\n    (This)->lpVtbl -> IsEqual(This,pFontOther)\n\n#define IFont_SetRatio(This,cyLogical,cyHimetric)\t\\\n    (This)->lpVtbl -> SetRatio(This,cyLogical,cyHimetric)\n\n#define IFont_QueryTextMetrics(This,pTM)\t\\\n    (This)->lpVtbl -> QueryTextMetrics(This,pTM)\n\n#define IFont_AddRefHfont(This,hFont)\t\\\n    (This)->lpVtbl -> AddRefHfont(This,hFont)\n\n#define IFont_ReleaseHfont(This,hFont)\t\\\n    (This)->lpVtbl -> ReleaseHfont(This,hFont)\n\n#define IFont_SetHdc(This,hDC)\t\\\n    (This)->lpVtbl -> SetHdc(This,hDC)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Name_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ BSTR __RPC_FAR *pName);\n\n\nvoid __RPC_STUB IFont_get_Name_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Name_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ BSTR name);\n\n\nvoid __RPC_STUB IFont_put_Name_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Size_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ CY __RPC_FAR *pSize);\n\n\nvoid __RPC_STUB IFont_get_Size_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Size_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ CY size);\n\n\nvoid __RPC_STUB IFont_put_Size_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Bold_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pBold);\n\n\nvoid __RPC_STUB IFont_get_Bold_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Bold_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ BOOL bold);\n\n\nvoid __RPC_STUB IFont_put_Bold_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Italic_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pItalic);\n\n\nvoid __RPC_STUB IFont_get_Italic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Italic_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ BOOL italic);\n\n\nvoid __RPC_STUB IFont_put_Italic_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Underline_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pUnderline);\n\n\nvoid __RPC_STUB IFont_get_Underline_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Underline_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ BOOL underline);\n\n\nvoid __RPC_STUB IFont_put_Underline_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Strikethrough_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pStrikethrough);\n\n\nvoid __RPC_STUB IFont_get_Strikethrough_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Strikethrough_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ BOOL strikethrough);\n\n\nvoid __RPC_STUB IFont_put_Strikethrough_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Weight_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ SHORT __RPC_FAR *pWeight);\n\n\nvoid __RPC_STUB IFont_get_Weight_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Weight_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ SHORT weight);\n\n\nvoid __RPC_STUB IFont_put_Weight_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_Charset_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ SHORT __RPC_FAR *pCharset);\n\n\nvoid __RPC_STUB IFont_get_Charset_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_put_Charset_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ SHORT charset);\n\n\nvoid __RPC_STUB IFont_put_Charset_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_get_hFont_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ HFONT __RPC_FAR *phFont);\n\n\nvoid __RPC_STUB IFont_get_hFont_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_Clone_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ IFont __RPC_FAR *__RPC_FAR *ppFont);\n\n\nvoid __RPC_STUB IFont_Clone_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_IsEqual_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ IFont __RPC_FAR *pFontOther);\n\n\nvoid __RPC_STUB IFont_IsEqual_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_SetRatio_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ LONG cyLogical,\n    /* [in] */ LONG cyHimetric);\n\n\nvoid __RPC_STUB IFont_SetRatio_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_QueryTextMetrics_Proxy( \n    IFont __RPC_FAR * This,\n    /* [out] */ TEXTMETRICOLE __RPC_FAR *pTM);\n\n\nvoid __RPC_STUB IFont_QueryTextMetrics_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_AddRefHfont_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ HFONT hFont);\n\n\nvoid __RPC_STUB IFont_AddRefHfont_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_ReleaseHfont_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ HFONT hFont);\n\n\nvoid __RPC_STUB IFont_ReleaseHfont_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IFont_SetHdc_Proxy( \n    IFont __RPC_FAR * This,\n    /* [in] */ HDC hDC);\n\n\nvoid __RPC_STUB IFont_SetHdc_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IFont_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPicture_INTERFACE_DEFINED__\n#define __IPicture_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPicture\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPicture __RPC_FAR *LPPICTURE;\n\ntypedef \nenum tagPictureAttributes\n    {\tPICTURE_SCALABLE\t= 0x1,\n\tPICTURE_TRANSPARENT\t= 0x2\n    }\tPICTUREATTRIBUTES;\n\ntypedef UINT OLE_HANDLE;\n\ntypedef LONG OLE_XPOS_HIMETRIC;\n\ntypedef LONG OLE_YPOS_HIMETRIC;\n\ntypedef LONG OLE_XSIZE_HIMETRIC;\n\ntypedef LONG OLE_YSIZE_HIMETRIC;\n\n\nEXTERN_C const IID IID_IPicture;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPicture : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE get_Handle( \n            /* [out] */ OLE_HANDLE __RPC_FAR *pHandle) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_hPal( \n            /* [out] */ OLE_HANDLE __RPC_FAR *phPal) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Type( \n            /* [out] */ SHORT __RPC_FAR *pType) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Width( \n            /* [out] */ OLE_XSIZE_HIMETRIC __RPC_FAR *pWidth) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Height( \n            /* [out] */ OLE_YSIZE_HIMETRIC __RPC_FAR *pHeight) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Render( \n            /* [in] */ HDC hDC,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ LONG cx,\n            /* [in] */ LONG cy,\n            /* [in] */ OLE_XPOS_HIMETRIC xSrc,\n            /* [in] */ OLE_YPOS_HIMETRIC ySrc,\n            /* [in] */ OLE_XSIZE_HIMETRIC cxSrc,\n            /* [in] */ OLE_YSIZE_HIMETRIC cySrc,\n            /* [in] */ LPCRECT pRcWBounds) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE set_hPal( \n            /* [in] */ OLE_HANDLE hPal) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_CurDC( \n            /* [out] */ HDC __RPC_FAR *phDC) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SelectPicture( \n            /* [in] */ HDC hDCIn,\n            /* [out] */ HDC __RPC_FAR *phDCOut,\n            /* [out] */ OLE_HANDLE __RPC_FAR *phBmpOut) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_KeepOriginalFormat( \n            /* [out] */ BOOL __RPC_FAR *pKeep) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE put_KeepOriginalFormat( \n            /* [in] */ BOOL keep) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE PictureChanged( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SaveAsFile( \n            /* [in] */ LPSTREAM pStream,\n            /* [in] */ BOOL fSaveMemCopy,\n            /* [out] */ LONG __RPC_FAR *pCbSize) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE get_Attributes( \n            /* [out] */ DWORD __RPC_FAR *pDwAttr) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPictureVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPicture __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPicture __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Handle )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ OLE_HANDLE __RPC_FAR *pHandle);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_hPal )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ OLE_HANDLE __RPC_FAR *phPal);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Type )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ SHORT __RPC_FAR *pType);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Width )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ OLE_XSIZE_HIMETRIC __RPC_FAR *pWidth);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Height )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ OLE_YSIZE_HIMETRIC __RPC_FAR *pHeight);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Render )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ HDC hDC,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ LONG cx,\n            /* [in] */ LONG cy,\n            /* [in] */ OLE_XPOS_HIMETRIC xSrc,\n            /* [in] */ OLE_YPOS_HIMETRIC ySrc,\n            /* [in] */ OLE_XSIZE_HIMETRIC cxSrc,\n            /* [in] */ OLE_YSIZE_HIMETRIC cySrc,\n            /* [in] */ LPCRECT pRcWBounds);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *set_hPal )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ OLE_HANDLE hPal);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_CurDC )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ HDC __RPC_FAR *phDC);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SelectPicture )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ HDC hDCIn,\n            /* [out] */ HDC __RPC_FAR *phDCOut,\n            /* [out] */ OLE_HANDLE __RPC_FAR *phBmpOut);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_KeepOriginalFormat )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pKeep);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_KeepOriginalFormat )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ BOOL keep);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *PictureChanged )( \n            IPicture __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SaveAsFile )( \n            IPicture __RPC_FAR * This,\n            /* [in] */ LPSTREAM pStream,\n            /* [in] */ BOOL fSaveMemCopy,\n            /* [out] */ LONG __RPC_FAR *pCbSize);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Attributes )( \n            IPicture __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pDwAttr);\n        \n        END_INTERFACE\n    } IPictureVtbl;\n\n    interface IPicture\n    {\n        CONST_VTBL struct IPictureVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPicture_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPicture_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPicture_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPicture_get_Handle(This,pHandle)\t\\\n    (This)->lpVtbl -> get_Handle(This,pHandle)\n\n#define IPicture_get_hPal(This,phPal)\t\\\n    (This)->lpVtbl -> get_hPal(This,phPal)\n\n#define IPicture_get_Type(This,pType)\t\\\n    (This)->lpVtbl -> get_Type(This,pType)\n\n#define IPicture_get_Width(This,pWidth)\t\\\n    (This)->lpVtbl -> get_Width(This,pWidth)\n\n#define IPicture_get_Height(This,pHeight)\t\\\n    (This)->lpVtbl -> get_Height(This,pHeight)\n\n#define IPicture_Render(This,hDC,x,y,cx,cy,xSrc,ySrc,cxSrc,cySrc,pRcWBounds)\t\\\n    (This)->lpVtbl -> Render(This,hDC,x,y,cx,cy,xSrc,ySrc,cxSrc,cySrc,pRcWBounds)\n\n#define IPicture_set_hPal(This,hPal)\t\\\n    (This)->lpVtbl -> set_hPal(This,hPal)\n\n#define IPicture_get_CurDC(This,phDC)\t\\\n    (This)->lpVtbl -> get_CurDC(This,phDC)\n\n#define IPicture_SelectPicture(This,hDCIn,phDCOut,phBmpOut)\t\\\n    (This)->lpVtbl -> SelectPicture(This,hDCIn,phDCOut,phBmpOut)\n\n#define IPicture_get_KeepOriginalFormat(This,pKeep)\t\\\n    (This)->lpVtbl -> get_KeepOriginalFormat(This,pKeep)\n\n#define IPicture_put_KeepOriginalFormat(This,keep)\t\\\n    (This)->lpVtbl -> put_KeepOriginalFormat(This,keep)\n\n#define IPicture_PictureChanged(This)\t\\\n    (This)->lpVtbl -> PictureChanged(This)\n\n#define IPicture_SaveAsFile(This,pStream,fSaveMemCopy,pCbSize)\t\\\n    (This)->lpVtbl -> SaveAsFile(This,pStream,fSaveMemCopy,pCbSize)\n\n#define IPicture_get_Attributes(This,pDwAttr)\t\\\n    (This)->lpVtbl -> get_Attributes(This,pDwAttr)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_Handle_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ OLE_HANDLE __RPC_FAR *pHandle);\n\n\nvoid __RPC_STUB IPicture_get_Handle_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_hPal_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ OLE_HANDLE __RPC_FAR *phPal);\n\n\nvoid __RPC_STUB IPicture_get_hPal_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_Type_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ SHORT __RPC_FAR *pType);\n\n\nvoid __RPC_STUB IPicture_get_Type_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_Width_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ OLE_XSIZE_HIMETRIC __RPC_FAR *pWidth);\n\n\nvoid __RPC_STUB IPicture_get_Width_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_Height_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ OLE_YSIZE_HIMETRIC __RPC_FAR *pHeight);\n\n\nvoid __RPC_STUB IPicture_get_Height_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_Render_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [in] */ HDC hDC,\n    /* [in] */ LONG x,\n    /* [in] */ LONG y,\n    /* [in] */ LONG cx,\n    /* [in] */ LONG cy,\n    /* [in] */ OLE_XPOS_HIMETRIC xSrc,\n    /* [in] */ OLE_YPOS_HIMETRIC ySrc,\n    /* [in] */ OLE_XSIZE_HIMETRIC cxSrc,\n    /* [in] */ OLE_YSIZE_HIMETRIC cySrc,\n    /* [in] */ LPCRECT pRcWBounds);\n\n\nvoid __RPC_STUB IPicture_Render_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_set_hPal_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [in] */ OLE_HANDLE hPal);\n\n\nvoid __RPC_STUB IPicture_set_hPal_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_CurDC_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ HDC __RPC_FAR *phDC);\n\n\nvoid __RPC_STUB IPicture_get_CurDC_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_SelectPicture_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [in] */ HDC hDCIn,\n    /* [out] */ HDC __RPC_FAR *phDCOut,\n    /* [out] */ OLE_HANDLE __RPC_FAR *phBmpOut);\n\n\nvoid __RPC_STUB IPicture_SelectPicture_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_KeepOriginalFormat_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pKeep);\n\n\nvoid __RPC_STUB IPicture_get_KeepOriginalFormat_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_put_KeepOriginalFormat_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [in] */ BOOL keep);\n\n\nvoid __RPC_STUB IPicture_put_KeepOriginalFormat_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_PictureChanged_Proxy( \n    IPicture __RPC_FAR * This);\n\n\nvoid __RPC_STUB IPicture_PictureChanged_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_SaveAsFile_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [in] */ LPSTREAM pStream,\n    /* [in] */ BOOL fSaveMemCopy,\n    /* [out] */ LONG __RPC_FAR *pCbSize);\n\n\nvoid __RPC_STUB IPicture_SaveAsFile_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPicture_get_Attributes_Proxy( \n    IPicture __RPC_FAR * This,\n    /* [out] */ DWORD __RPC_FAR *pDwAttr);\n\n\nvoid __RPC_STUB IPicture_get_Attributes_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPicture_INTERFACE_DEFINED__ */\n\n\n#ifndef __IFontDisp_INTERFACE_DEFINED__\n#define __IFontDisp_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IFontDisp\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IFontDisp __RPC_FAR *LPFONTDISP;\n\n\nEXTERN_C const IID IID_IFontDisp;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IFontDisp : public IDispatch\n    {\n    public:\n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IFontDispVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IFontDisp __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IFontDisp __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IFontDisp __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )( \n            IFontDisp __RPC_FAR * This,\n            /* [out] */ UINT __RPC_FAR *pctinfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )( \n            IFontDisp __RPC_FAR * This,\n            /* [in] */ UINT iTInfo,\n            /* [in] */ LCID lcid,\n            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )( \n            IFontDisp __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,\n            /* [in] */ UINT cNames,\n            /* [in] */ LCID lcid,\n            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )( \n            IFontDisp __RPC_FAR * This,\n            /* [in] */ DISPID dispIdMember,\n            /* [in] */ REFIID riid,\n            /* [in] */ LCID lcid,\n            /* [in] */ WORD wFlags,\n            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,\n            /* [out] */ VARIANT __RPC_FAR *pVarResult,\n            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,\n            /* [out] */ UINT __RPC_FAR *puArgErr);\n        \n        END_INTERFACE\n    } IFontDispVtbl;\n\n    interface IFontDisp\n    {\n        CONST_VTBL struct IFontDispVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IFontDisp_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IFontDisp_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IFontDisp_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IFontDisp_GetTypeInfoCount(This,pctinfo)\t\\\n    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\n\n#define IFontDisp_GetTypeInfo(This,iTInfo,lcid,ppTInfo)\t\\\n    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\n\n#define IFontDisp_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\t\\\n    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\n\n#define IFontDisp_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\t\\\n    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\n\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n\n#endif \t/* __IFontDisp_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPictureDisp_INTERFACE_DEFINED__\n#define __IPictureDisp_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPictureDisp\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPictureDisp __RPC_FAR *LPPICTUREDISP;\n\n\nEXTERN_C const IID IID_IPictureDisp;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPictureDisp : public IDispatch\n    {\n    public:\n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPictureDispVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPictureDisp __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPictureDisp __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPictureDisp __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )( \n            IPictureDisp __RPC_FAR * This,\n            /* [out] */ UINT __RPC_FAR *pctinfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )( \n            IPictureDisp __RPC_FAR * This,\n            /* [in] */ UINT iTInfo,\n            /* [in] */ LCID lcid,\n            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )( \n            IPictureDisp __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,\n            /* [in] */ UINT cNames,\n            /* [in] */ LCID lcid,\n            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )( \n            IPictureDisp __RPC_FAR * This,\n            /* [in] */ DISPID dispIdMember,\n            /* [in] */ REFIID riid,\n            /* [in] */ LCID lcid,\n            /* [in] */ WORD wFlags,\n            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,\n            /* [out] */ VARIANT __RPC_FAR *pVarResult,\n            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,\n            /* [out] */ UINT __RPC_FAR *puArgErr);\n        \n        END_INTERFACE\n    } IPictureDispVtbl;\n\n    interface IPictureDisp\n    {\n        CONST_VTBL struct IPictureDispVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPictureDisp_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPictureDisp_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPictureDisp_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPictureDisp_GetTypeInfoCount(This,pctinfo)\t\\\n    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\n\n#define IPictureDisp_GetTypeInfo(This,iTInfo,lcid,ppTInfo)\t\\\n    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\n\n#define IPictureDisp_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\t\\\n    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\n\n#define IPictureDisp_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\t\\\n    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\n\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n\n#endif \t/* __IPictureDisp_INTERFACE_DEFINED__ */\n\n\n#ifndef __IAdviseSinkEx_INTERFACE_DEFINED__\n#define __IAdviseSinkEx_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IAdviseSinkEx\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IAdviseSinkEx __RPC_FAR *LPADVISESINKEX;\n\n\nEXTERN_C const IID IID_IAdviseSinkEx;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IAdviseSinkEx : public IAdviseSink\n    {\n    public:\n        virtual /* [local] */ void STDMETHODCALLTYPE OnViewStatusChange( \n            /* [in] */ DWORD dwViewStatus) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IAdviseSinkExVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IAdviseSinkEx __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IAdviseSinkEx __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IAdviseSinkEx __RPC_FAR * This);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnDataChange )( \n            IAdviseSinkEx __RPC_FAR * This,\n            /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,\n            /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnViewChange )( \n            IAdviseSinkEx __RPC_FAR * This,\n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LONG lindex);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnRename )( \n            IAdviseSinkEx __RPC_FAR * This,\n            /* [in] */ IMoniker __RPC_FAR *pmk);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnSave )( \n            IAdviseSinkEx __RPC_FAR * This);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnClose )( \n            IAdviseSinkEx __RPC_FAR * This);\n        \n        /* [local] */ void ( STDMETHODCALLTYPE __RPC_FAR *OnViewStatusChange )( \n            IAdviseSinkEx __RPC_FAR * This,\n            /* [in] */ DWORD dwViewStatus);\n        \n        END_INTERFACE\n    } IAdviseSinkExVtbl;\n\n    interface IAdviseSinkEx\n    {\n        CONST_VTBL struct IAdviseSinkExVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IAdviseSinkEx_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IAdviseSinkEx_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IAdviseSinkEx_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IAdviseSinkEx_OnDataChange(This,pFormatetc,pStgmed)\t\\\n    (This)->lpVtbl -> OnDataChange(This,pFormatetc,pStgmed)\n\n#define IAdviseSinkEx_OnViewChange(This,dwAspect,lindex)\t\\\n    (This)->lpVtbl -> OnViewChange(This,dwAspect,lindex)\n\n#define IAdviseSinkEx_OnRename(This,pmk)\t\\\n    (This)->lpVtbl -> OnRename(This,pmk)\n\n#define IAdviseSinkEx_OnSave(This)\t\\\n    (This)->lpVtbl -> OnSave(This)\n\n#define IAdviseSinkEx_OnClose(This)\t\\\n    (This)->lpVtbl -> OnClose(This)\n\n\n#define IAdviseSinkEx_OnViewStatusChange(This,dwViewStatus)\t\\\n    (This)->lpVtbl -> OnViewStatusChange(This,dwViewStatus)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [async][call_as] */ void STDMETHODCALLTYPE IAdviseSinkEx_RemoteOnViewStatusChange_Proxy( \n    IAdviseSinkEx __RPC_FAR * This,\n    /* [in] */ DWORD dwViewStatus);\n\n\nvoid __RPC_STUB IAdviseSinkEx_RemoteOnViewStatusChange_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IAdviseSinkEx_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleInPlaceObjectWindowless_INTERFACE_DEFINED__\n#define __IOleInPlaceObjectWindowless_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleInPlaceObjectWindowless\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object][local] */ \n\n\ntypedef IOleInPlaceObjectWindowless __RPC_FAR *LPOLEINPLACEOBJECTWINDOWLESS;\n\n\nEXTERN_C const IID IID_IOleInPlaceObjectWindowless;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleInPlaceObjectWindowless : public IOleInPlaceObject\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE OnWindowMessage( \n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wParam,\n            /* [in] */ LPARAM lParam,\n            /* [out] */ LRESULT __RPC_FAR *plResult) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetDropTarget( \n            /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleInPlaceObjectWindowlessVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This);\n        \n        /* [input_sync] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetWindow )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [out] */ HWND __RPC_FAR *phwnd);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ContextSensitiveHelp )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fEnterMode);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InPlaceDeactivate )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UIDeactivate )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This);\n        \n        /* [input_sync] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetObjectRects )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [in] */ LPCRECT lprcPosRect,\n            /* [in] */ LPCRECT lprcClipRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReactivateAndUndo )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnWindowMessage )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wParam,\n            /* [in] */ LPARAM lParam,\n            /* [out] */ LRESULT __RPC_FAR *plResult);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDropTarget )( \n            IOleInPlaceObjectWindowless __RPC_FAR * This,\n            /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);\n        \n        END_INTERFACE\n    } IOleInPlaceObjectWindowlessVtbl;\n\n    interface IOleInPlaceObjectWindowless\n    {\n        CONST_VTBL struct IOleInPlaceObjectWindowlessVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleInPlaceObjectWindowless_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleInPlaceObjectWindowless_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleInPlaceObjectWindowless_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleInPlaceObjectWindowless_GetWindow(This,phwnd)\t\\\n    (This)->lpVtbl -> GetWindow(This,phwnd)\n\n#define IOleInPlaceObjectWindowless_ContextSensitiveHelp(This,fEnterMode)\t\\\n    (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)\n\n\n#define IOleInPlaceObjectWindowless_InPlaceDeactivate(This)\t\\\n    (This)->lpVtbl -> InPlaceDeactivate(This)\n\n#define IOleInPlaceObjectWindowless_UIDeactivate(This)\t\\\n    (This)->lpVtbl -> UIDeactivate(This)\n\n#define IOleInPlaceObjectWindowless_SetObjectRects(This,lprcPosRect,lprcClipRect)\t\\\n    (This)->lpVtbl -> SetObjectRects(This,lprcPosRect,lprcClipRect)\n\n#define IOleInPlaceObjectWindowless_ReactivateAndUndo(This)\t\\\n    (This)->lpVtbl -> ReactivateAndUndo(This)\n\n\n#define IOleInPlaceObjectWindowless_OnWindowMessage(This,msg,wParam,lParam,plResult)\t\\\n    (This)->lpVtbl -> OnWindowMessage(This,msg,wParam,lParam,plResult)\n\n#define IOleInPlaceObjectWindowless_GetDropTarget(This,ppDropTarget)\t\\\n    (This)->lpVtbl -> GetDropTarget(This,ppDropTarget)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceObjectWindowless_OnWindowMessage_Proxy( \n    IOleInPlaceObjectWindowless __RPC_FAR * This,\n    /* [in] */ UINT msg,\n    /* [in] */ WPARAM wParam,\n    /* [in] */ LPARAM lParam,\n    /* [out] */ LRESULT __RPC_FAR *plResult);\n\n\nvoid __RPC_STUB IOleInPlaceObjectWindowless_OnWindowMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceObjectWindowless_GetDropTarget_Proxy( \n    IOleInPlaceObjectWindowless __RPC_FAR * This,\n    /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);\n\n\nvoid __RPC_STUB IOleInPlaceObjectWindowless_GetDropTarget_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleInPlaceObjectWindowless_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleInPlaceSiteEx_INTERFACE_DEFINED__\n#define __IOleInPlaceSiteEx_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleInPlaceSiteEx\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IOleInPlaceSiteEx __RPC_FAR *LPOLEINPLACESITEEX;\n\ntypedef /* [v1_enum] */ \nenum tagACTIVATEFLAGS\n    {\tACTIVATE_WINDOWLESS\t= 1\n    }\tACTIVATEFLAGS;\n\n\nEXTERN_C const IID IID_IOleInPlaceSiteEx;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleInPlaceSiteEx : public IOleInPlaceSite\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx( \n            /* [out] */ BOOL __RPC_FAR *pfNoRedraw,\n            /* [in] */ DWORD dwFlags) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx( \n            /* [in] */ BOOL fNoRedraw) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE RequestUIActivate( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleInPlaceSiteExVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        /* [input_sync] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetWindow )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [out] */ HWND __RPC_FAR *phwnd);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ContextSensitiveHelp )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ BOOL fEnterMode);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CanInPlaceActivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceActivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUIActivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetWindowContext )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,\n            /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,\n            /* [out] */ LPRECT lprcPosRect,\n            /* [out] */ LPRECT lprcClipRect,\n            /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Scroll )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ SIZE scrollExtant);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUIDeactivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ BOOL fUndoable);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceDeactivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DiscardUndoState )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DeactivateAndUndo )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPosRectChange )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ LPCRECT lprcPosRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceActivateEx )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pfNoRedraw,\n            /* [in] */ DWORD dwFlags);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceDeactivateEx )( \n            IOleInPlaceSiteEx __RPC_FAR * This,\n            /* [in] */ BOOL fNoRedraw);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUIActivate )( \n            IOleInPlaceSiteEx __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IOleInPlaceSiteExVtbl;\n\n    interface IOleInPlaceSiteEx\n    {\n        CONST_VTBL struct IOleInPlaceSiteExVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleInPlaceSiteEx_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleInPlaceSiteEx_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleInPlaceSiteEx_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleInPlaceSiteEx_GetWindow(This,phwnd)\t\\\n    (This)->lpVtbl -> GetWindow(This,phwnd)\n\n#define IOleInPlaceSiteEx_ContextSensitiveHelp(This,fEnterMode)\t\\\n    (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)\n\n\n#define IOleInPlaceSiteEx_CanInPlaceActivate(This)\t\\\n    (This)->lpVtbl -> CanInPlaceActivate(This)\n\n#define IOleInPlaceSiteEx_OnInPlaceActivate(This)\t\\\n    (This)->lpVtbl -> OnInPlaceActivate(This)\n\n#define IOleInPlaceSiteEx_OnUIActivate(This)\t\\\n    (This)->lpVtbl -> OnUIActivate(This)\n\n#define IOleInPlaceSiteEx_GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo)\t\\\n    (This)->lpVtbl -> GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo)\n\n#define IOleInPlaceSiteEx_Scroll(This,scrollExtant)\t\\\n    (This)->lpVtbl -> Scroll(This,scrollExtant)\n\n#define IOleInPlaceSiteEx_OnUIDeactivate(This,fUndoable)\t\\\n    (This)->lpVtbl -> OnUIDeactivate(This,fUndoable)\n\n#define IOleInPlaceSiteEx_OnInPlaceDeactivate(This)\t\\\n    (This)->lpVtbl -> OnInPlaceDeactivate(This)\n\n#define IOleInPlaceSiteEx_DiscardUndoState(This)\t\\\n    (This)->lpVtbl -> DiscardUndoState(This)\n\n#define IOleInPlaceSiteEx_DeactivateAndUndo(This)\t\\\n    (This)->lpVtbl -> DeactivateAndUndo(This)\n\n#define IOleInPlaceSiteEx_OnPosRectChange(This,lprcPosRect)\t\\\n    (This)->lpVtbl -> OnPosRectChange(This,lprcPosRect)\n\n\n#define IOleInPlaceSiteEx_OnInPlaceActivateEx(This,pfNoRedraw,dwFlags)\t\\\n    (This)->lpVtbl -> OnInPlaceActivateEx(This,pfNoRedraw,dwFlags)\n\n#define IOleInPlaceSiteEx_OnInPlaceDeactivateEx(This,fNoRedraw)\t\\\n    (This)->lpVtbl -> OnInPlaceDeactivateEx(This,fNoRedraw)\n\n#define IOleInPlaceSiteEx_RequestUIActivate(This)\t\\\n    (This)->lpVtbl -> RequestUIActivate(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteEx_OnInPlaceActivateEx_Proxy( \n    IOleInPlaceSiteEx __RPC_FAR * This,\n    /* [out] */ BOOL __RPC_FAR *pfNoRedraw,\n    /* [in] */ DWORD dwFlags);\n\n\nvoid __RPC_STUB IOleInPlaceSiteEx_OnInPlaceActivateEx_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteEx_OnInPlaceDeactivateEx_Proxy( \n    IOleInPlaceSiteEx __RPC_FAR * This,\n    /* [in] */ BOOL fNoRedraw);\n\n\nvoid __RPC_STUB IOleInPlaceSiteEx_OnInPlaceDeactivateEx_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteEx_RequestUIActivate_Proxy( \n    IOleInPlaceSiteEx __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleInPlaceSiteEx_RequestUIActivate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleInPlaceSiteEx_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleInPlaceSiteWindowless_INTERFACE_DEFINED__\n#define __IOleInPlaceSiteWindowless_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleInPlaceSiteWindowless\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object][local] */ \n\n\ntypedef IOleInPlaceSiteWindowless __RPC_FAR *LPOLEINPLACESITEWINDOWLESS;\n\ntypedef /* [v1_enum] */ \nenum tagOLEDCFLAGS\n    {\tOLEDC_NODRAW\t= 0x1,\n\tOLEDC_PAINTBKGND\t= 0x2,\n\tOLEDC_OFFSCREEN\t= 0x4\n    }\tOLEDCFLAGS;\n\n\nEXTERN_C const IID IID_IOleInPlaceSiteWindowless;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleInPlaceSiteWindowless : public IOleInPlaceSiteEx\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE CanWindowlessActivate( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetCapture( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetCapture( \n            /* [in] */ BOOL fCapture) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetFocus( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetFocus( \n            /* [in] */ BOOL fFocus) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetDC( \n            /* [in] */ LPCRECT pRect,\n            /* [in] */ DWORD grfFlags,\n            /* [out] */ HDC __RPC_FAR *phDC) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE ReleaseDC( \n            /* [in] */ HDC hDC) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE InvalidateRect( \n            /* [in] */ LPCRECT pRect,\n            /* [in] */ BOOL fErase) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE InvalidateRgn( \n            /* [in] */ HRGN hRGN,\n            /* [in] */ BOOL fErase) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE ScrollRect( \n            /* [in] */ INT dx,\n            /* [in] */ INT dy,\n            /* [in] */ LPCRECT pRectScroll,\n            /* [in] */ LPCRECT pRectClip) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE AdjustRect( \n            /* [out][in] */ LPRECT prc) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnDefWindowMessage( \n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wParam,\n            /* [in] */ LPARAM lParam,\n            /* [out] */ LRESULT __RPC_FAR *plResult) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleInPlaceSiteWindowlessVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        /* [input_sync] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetWindow )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [out] */ HWND __RPC_FAR *phwnd);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ContextSensitiveHelp )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fEnterMode);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CanInPlaceActivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceActivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUIActivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetWindowContext )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,\n            /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,\n            /* [out] */ LPRECT lprcPosRect,\n            /* [out] */ LPRECT lprcClipRect,\n            /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Scroll )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ SIZE scrollExtant);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnUIDeactivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fUndoable);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceDeactivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DiscardUndoState )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DeactivateAndUndo )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnPosRectChange )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ LPCRECT lprcPosRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceActivateEx )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [out] */ BOOL __RPC_FAR *pfNoRedraw,\n            /* [in] */ DWORD dwFlags);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInPlaceDeactivateEx )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fNoRedraw);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RequestUIActivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CanWindowlessActivate )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCapture )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetCapture )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fCapture);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetFocus )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetFocus )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ BOOL fFocus);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDC )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ LPCRECT pRect,\n            /* [in] */ DWORD grfFlags,\n            /* [out] */ HDC __RPC_FAR *phDC);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReleaseDC )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ HDC hDC);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InvalidateRect )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ LPCRECT pRect,\n            /* [in] */ BOOL fErase);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *InvalidateRgn )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ HRGN hRGN,\n            /* [in] */ BOOL fErase);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ScrollRect )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ INT dx,\n            /* [in] */ INT dy,\n            /* [in] */ LPCRECT pRectScroll,\n            /* [in] */ LPCRECT pRectClip);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AdjustRect )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [out][in] */ LPRECT prc);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnDefWindowMessage )( \n            IOleInPlaceSiteWindowless __RPC_FAR * This,\n            /* [in] */ UINT msg,\n            /* [in] */ WPARAM wParam,\n            /* [in] */ LPARAM lParam,\n            /* [out] */ LRESULT __RPC_FAR *plResult);\n        \n        END_INTERFACE\n    } IOleInPlaceSiteWindowlessVtbl;\n\n    interface IOleInPlaceSiteWindowless\n    {\n        CONST_VTBL struct IOleInPlaceSiteWindowlessVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleInPlaceSiteWindowless_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleInPlaceSiteWindowless_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleInPlaceSiteWindowless_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleInPlaceSiteWindowless_GetWindow(This,phwnd)\t\\\n    (This)->lpVtbl -> GetWindow(This,phwnd)\n\n#define IOleInPlaceSiteWindowless_ContextSensitiveHelp(This,fEnterMode)\t\\\n    (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)\n\n\n#define IOleInPlaceSiteWindowless_CanInPlaceActivate(This)\t\\\n    (This)->lpVtbl -> CanInPlaceActivate(This)\n\n#define IOleInPlaceSiteWindowless_OnInPlaceActivate(This)\t\\\n    (This)->lpVtbl -> OnInPlaceActivate(This)\n\n#define IOleInPlaceSiteWindowless_OnUIActivate(This)\t\\\n    (This)->lpVtbl -> OnUIActivate(This)\n\n#define IOleInPlaceSiteWindowless_GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo)\t\\\n    (This)->lpVtbl -> GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo)\n\n#define IOleInPlaceSiteWindowless_Scroll(This,scrollExtant)\t\\\n    (This)->lpVtbl -> Scroll(This,scrollExtant)\n\n#define IOleInPlaceSiteWindowless_OnUIDeactivate(This,fUndoable)\t\\\n    (This)->lpVtbl -> OnUIDeactivate(This,fUndoable)\n\n#define IOleInPlaceSiteWindowless_OnInPlaceDeactivate(This)\t\\\n    (This)->lpVtbl -> OnInPlaceDeactivate(This)\n\n#define IOleInPlaceSiteWindowless_DiscardUndoState(This)\t\\\n    (This)->lpVtbl -> DiscardUndoState(This)\n\n#define IOleInPlaceSiteWindowless_DeactivateAndUndo(This)\t\\\n    (This)->lpVtbl -> DeactivateAndUndo(This)\n\n#define IOleInPlaceSiteWindowless_OnPosRectChange(This,lprcPosRect)\t\\\n    (This)->lpVtbl -> OnPosRectChange(This,lprcPosRect)\n\n\n#define IOleInPlaceSiteWindowless_OnInPlaceActivateEx(This,pfNoRedraw,dwFlags)\t\\\n    (This)->lpVtbl -> OnInPlaceActivateEx(This,pfNoRedraw,dwFlags)\n\n#define IOleInPlaceSiteWindowless_OnInPlaceDeactivateEx(This,fNoRedraw)\t\\\n    (This)->lpVtbl -> OnInPlaceDeactivateEx(This,fNoRedraw)\n\n#define IOleInPlaceSiteWindowless_RequestUIActivate(This)\t\\\n    (This)->lpVtbl -> RequestUIActivate(This)\n\n\n#define IOleInPlaceSiteWindowless_CanWindowlessActivate(This)\t\\\n    (This)->lpVtbl -> CanWindowlessActivate(This)\n\n#define IOleInPlaceSiteWindowless_GetCapture(This)\t\\\n    (This)->lpVtbl -> GetCapture(This)\n\n#define IOleInPlaceSiteWindowless_SetCapture(This,fCapture)\t\\\n    (This)->lpVtbl -> SetCapture(This,fCapture)\n\n#define IOleInPlaceSiteWindowless_GetFocus(This)\t\\\n    (This)->lpVtbl -> GetFocus(This)\n\n#define IOleInPlaceSiteWindowless_SetFocus(This,fFocus)\t\\\n    (This)->lpVtbl -> SetFocus(This,fFocus)\n\n#define IOleInPlaceSiteWindowless_GetDC(This,pRect,grfFlags,phDC)\t\\\n    (This)->lpVtbl -> GetDC(This,pRect,grfFlags,phDC)\n\n#define IOleInPlaceSiteWindowless_ReleaseDC(This,hDC)\t\\\n    (This)->lpVtbl -> ReleaseDC(This,hDC)\n\n#define IOleInPlaceSiteWindowless_InvalidateRect(This,pRect,fErase)\t\\\n    (This)->lpVtbl -> InvalidateRect(This,pRect,fErase)\n\n#define IOleInPlaceSiteWindowless_InvalidateRgn(This,hRGN,fErase)\t\\\n    (This)->lpVtbl -> InvalidateRgn(This,hRGN,fErase)\n\n#define IOleInPlaceSiteWindowless_ScrollRect(This,dx,dy,pRectScroll,pRectClip)\t\\\n    (This)->lpVtbl -> ScrollRect(This,dx,dy,pRectScroll,pRectClip)\n\n#define IOleInPlaceSiteWindowless_AdjustRect(This,prc)\t\\\n    (This)->lpVtbl -> AdjustRect(This,prc)\n\n#define IOleInPlaceSiteWindowless_OnDefWindowMessage(This,msg,wParam,lParam,plResult)\t\\\n    (This)->lpVtbl -> OnDefWindowMessage(This,msg,wParam,lParam,plResult)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_CanWindowlessActivate_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_CanWindowlessActivate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_GetCapture_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_GetCapture_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_SetCapture_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ BOOL fCapture);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_SetCapture_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_GetFocus_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_GetFocus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_SetFocus_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ BOOL fFocus);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_SetFocus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_GetDC_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ LPCRECT pRect,\n    /* [in] */ DWORD grfFlags,\n    /* [out] */ HDC __RPC_FAR *phDC);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_GetDC_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_ReleaseDC_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ HDC hDC);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_ReleaseDC_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_InvalidateRect_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ LPCRECT pRect,\n    /* [in] */ BOOL fErase);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_InvalidateRect_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_InvalidateRgn_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ HRGN hRGN,\n    /* [in] */ BOOL fErase);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_InvalidateRgn_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_ScrollRect_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ INT dx,\n    /* [in] */ INT dy,\n    /* [in] */ LPCRECT pRectScroll,\n    /* [in] */ LPCRECT pRectClip);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_ScrollRect_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_AdjustRect_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [out][in] */ LPRECT prc);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_AdjustRect_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleInPlaceSiteWindowless_OnDefWindowMessage_Proxy( \n    IOleInPlaceSiteWindowless __RPC_FAR * This,\n    /* [in] */ UINT msg,\n    /* [in] */ WPARAM wParam,\n    /* [in] */ LPARAM lParam,\n    /* [out] */ LRESULT __RPC_FAR *plResult);\n\n\nvoid __RPC_STUB IOleInPlaceSiteWindowless_OnDefWindowMessage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleInPlaceSiteWindowless_INTERFACE_DEFINED__ */\n\n\n#ifndef __IViewObjectEx_INTERFACE_DEFINED__\n#define __IViewObjectEx_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IViewObjectEx\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object][local] */ \n\n\ntypedef IViewObjectEx __RPC_FAR *LPVIEWOBJECTEX;\n\ntypedef /* [v1_enum] */ \nenum tagVIEWSTATUS\n    {\tVIEWSTATUS_OPAQUE\t= 1,\n\tVIEWSTATUS_SOLIDBKGND\t= 2,\n\tVIEWSTATUS_DVASPECTOPAQUE\t= 4,\n\tVIEWSTATUS_DVASPECTTRANSPARENT\t= 8\n    }\tVIEWSTATUS;\n\ntypedef /* [v1_enum] */ \nenum tagHITRESULT\n    {\tHITRESULT_OUTSIDE\t= 0,\n\tHITRESULT_TRANSPARENT\t= 1,\n\tHITRESULT_CLOSE\t= 2,\n\tHITRESULT_HIT\t= 3\n    }\tHITRESULT;\n\ntypedef /* [v1_enum] */ \nenum tagDVASPECT2\n    {\tDVASPECT_OPAQUE\t= 16,\n\tDVASPECT_TRANSPARENT\t= 32\n    }\tDVASPECT2;\n\ntypedef struct  tagExtentInfo\n    {\n    ULONG cb;\n    DWORD dwExtentMode;\n    SIZEL sizelProposed;\n    }\tDVEXTENTINFO;\n\ntypedef /* [v1_enum] */ \nenum tagExtentMode\n    {\tDVEXTENT_CONTENT\t= 0,\n\tDVEXTENT_INTEGRAL\t= DVEXTENT_CONTENT + 1\n    }\tDVEXTENTMODE;\n\ntypedef /* [v1_enum] */ \nenum tagAspectInfoFlag\n    {\tDVASPECTINFOFLAG_CANOPTIMIZE\t= 1\n    }\tDVASPECTINFOFLAG;\n\ntypedef struct  tagAspectInfo\n    {\n    ULONG cb;\n    DWORD dwFlags;\n    }\tDVASPECTINFO;\n\n\nEXTERN_C const IID IID_IViewObjectEx;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IViewObjectEx : public IViewObject2\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetRect( \n            /* [in] */ DWORD dwAspect,\n            /* [out] */ LPRECTL pRect) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetViewStatus( \n            /* [out] */ DWORD __RPC_FAR *pdwStatus) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE QueryHitPoint( \n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ POINT ptlLoc,\n            /* [in] */ LONG lCloseHint,\n            /* [out] */ DWORD __RPC_FAR *pHitResult) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE QueryHitRect( \n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LPCRECT pRectLoc,\n            /* [in] */ LONG lCloseHint,\n            /* [out] */ DWORD __RPC_FAR *pHitResult) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetNaturalExtent( \n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LONG lindex,\n            /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n            /* [in] */ HDC hicTargetDev,\n            /* [in] */ DVEXTENTINFO __RPC_FAR *pExtentInfo,\n            /* [out] */ LPSIZEL pSizel) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IViewObjectExVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IViewObjectEx __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IViewObjectEx __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Draw )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwDrawAspect,\n            /* [in] */ LONG lindex,\n            /* [unique][in] */ void __RPC_FAR *pvAspect,\n            /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n            /* [in] */ HDC hdcTargetDev,\n            /* [in] */ HDC hdcDraw,\n            /* [in] */ LPCRECTL lprcBounds,\n            /* [unique][in] */ LPCRECTL lprcWBounds,\n            /* [in] */ BOOL ( STDMETHODCALLTYPE __RPC_FAR *pfnContinue )( \n                DWORD dwContinue),\n            /* [in] */ DWORD dwContinue);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetColorSet )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwDrawAspect,\n            /* [in] */ LONG lindex,\n            /* [unique][in] */ void __RPC_FAR *pvAspect,\n            /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n            /* [in] */ HDC hicTargetDev,\n            /* [out] */ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwDrawAspect,\n            /* [in] */ LONG lindex,\n            /* [unique][in] */ void __RPC_FAR *pvAspect,\n            /* [out] */ DWORD __RPC_FAR *pdwFreeze);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Unfreeze )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwFreeze);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetAdvise )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD aspects,\n            /* [in] */ DWORD advf,\n            /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetAdvise )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pAspects,\n            /* [out] */ DWORD __RPC_FAR *pAdvf,\n            /* [out] */ IAdviseSink __RPC_FAR *__RPC_FAR *ppAdvSink);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetExtent )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwDrawAspect,\n            /* [in] */ LONG lindex,\n            /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n            /* [out] */ LPSIZEL lpsizel);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRect )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwAspect,\n            /* [out] */ LPRECTL pRect);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetViewStatus )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pdwStatus);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryHitPoint )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ POINT ptlLoc,\n            /* [in] */ LONG lCloseHint,\n            /* [out] */ DWORD __RPC_FAR *pHitResult);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryHitRect )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LPCRECT pRectLoc,\n            /* [in] */ LONG lCloseHint,\n            /* [out] */ DWORD __RPC_FAR *pHitResult);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetNaturalExtent )( \n            IViewObjectEx __RPC_FAR * This,\n            /* [in] */ DWORD dwAspect,\n            /* [in] */ LONG lindex,\n            /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n            /* [in] */ HDC hicTargetDev,\n            /* [in] */ DVEXTENTINFO __RPC_FAR *pExtentInfo,\n            /* [out] */ LPSIZEL pSizel);\n        \n        END_INTERFACE\n    } IViewObjectExVtbl;\n\n    interface IViewObjectEx\n    {\n        CONST_VTBL struct IViewObjectExVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IViewObjectEx_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IViewObjectEx_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IViewObjectEx_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IViewObjectEx_Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue)\t\\\n    (This)->lpVtbl -> Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue)\n\n#define IViewObjectEx_GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet)\t\\\n    (This)->lpVtbl -> GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet)\n\n#define IViewObjectEx_Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze)\t\\\n    (This)->lpVtbl -> Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze)\n\n#define IViewObjectEx_Unfreeze(This,dwFreeze)\t\\\n    (This)->lpVtbl -> Unfreeze(This,dwFreeze)\n\n#define IViewObjectEx_SetAdvise(This,aspects,advf,pAdvSink)\t\\\n    (This)->lpVtbl -> SetAdvise(This,aspects,advf,pAdvSink)\n\n#define IViewObjectEx_GetAdvise(This,pAspects,pAdvf,ppAdvSink)\t\\\n    (This)->lpVtbl -> GetAdvise(This,pAspects,pAdvf,ppAdvSink)\n\n\n#define IViewObjectEx_GetExtent(This,dwDrawAspect,lindex,ptd,lpsizel)\t\\\n    (This)->lpVtbl -> GetExtent(This,dwDrawAspect,lindex,ptd,lpsizel)\n\n\n#define IViewObjectEx_GetRect(This,dwAspect,pRect)\t\\\n    (This)->lpVtbl -> GetRect(This,dwAspect,pRect)\n\n#define IViewObjectEx_GetViewStatus(This,pdwStatus)\t\\\n    (This)->lpVtbl -> GetViewStatus(This,pdwStatus)\n\n#define IViewObjectEx_QueryHitPoint(This,dwAspect,pRectBounds,ptlLoc,lCloseHint,pHitResult)\t\\\n    (This)->lpVtbl -> QueryHitPoint(This,dwAspect,pRectBounds,ptlLoc,lCloseHint,pHitResult)\n\n#define IViewObjectEx_QueryHitRect(This,dwAspect,pRectBounds,pRectLoc,lCloseHint,pHitResult)\t\\\n    (This)->lpVtbl -> QueryHitRect(This,dwAspect,pRectBounds,pRectLoc,lCloseHint,pHitResult)\n\n#define IViewObjectEx_GetNaturalExtent(This,dwAspect,lindex,ptd,hicTargetDev,pExtentInfo,pSizel)\t\\\n    (This)->lpVtbl -> GetNaturalExtent(This,dwAspect,lindex,ptd,hicTargetDev,pExtentInfo,pSizel)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IViewObjectEx_GetRect_Proxy( \n    IViewObjectEx __RPC_FAR * This,\n    /* [in] */ DWORD dwAspect,\n    /* [out] */ LPRECTL pRect);\n\n\nvoid __RPC_STUB IViewObjectEx_GetRect_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IViewObjectEx_GetViewStatus_Proxy( \n    IViewObjectEx __RPC_FAR * This,\n    /* [out] */ DWORD __RPC_FAR *pdwStatus);\n\n\nvoid __RPC_STUB IViewObjectEx_GetViewStatus_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IViewObjectEx_QueryHitPoint_Proxy( \n    IViewObjectEx __RPC_FAR * This,\n    /* [in] */ DWORD dwAspect,\n    /* [in] */ LPCRECT pRectBounds,\n    /* [in] */ POINT ptlLoc,\n    /* [in] */ LONG lCloseHint,\n    /* [out] */ DWORD __RPC_FAR *pHitResult);\n\n\nvoid __RPC_STUB IViewObjectEx_QueryHitPoint_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IViewObjectEx_QueryHitRect_Proxy( \n    IViewObjectEx __RPC_FAR * This,\n    /* [in] */ DWORD dwAspect,\n    /* [in] */ LPCRECT pRectBounds,\n    /* [in] */ LPCRECT pRectLoc,\n    /* [in] */ LONG lCloseHint,\n    /* [out] */ DWORD __RPC_FAR *pHitResult);\n\n\nvoid __RPC_STUB IViewObjectEx_QueryHitRect_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IViewObjectEx_GetNaturalExtent_Proxy( \n    IViewObjectEx __RPC_FAR * This,\n    /* [in] */ DWORD dwAspect,\n    /* [in] */ LONG lindex,\n    /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,\n    /* [in] */ HDC hicTargetDev,\n    /* [in] */ DVEXTENTINFO __RPC_FAR *pExtentInfo,\n    /* [out] */ LPSIZEL pSizel);\n\n\nvoid __RPC_STUB IViewObjectEx_GetNaturalExtent_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IViewObjectEx_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleUndoUnit_INTERFACE_DEFINED__\n#define __IOleUndoUnit_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleUndoUnit\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IOleUndoUnit __RPC_FAR *LPOLEUNDOUNIT;\n\n\nEXTERN_C const IID IID_IOleUndoUnit;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleUndoUnit : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE Do( \n            /* [in] */ IOleUndoManager __RPC_FAR *pUndoManager) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetDescription( \n            /* [out] */ BSTR __RPC_FAR *pBstr) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetUnitType( \n            /* [out] */ CLSID __RPC_FAR *pClsid,\n            /* [out] */ LONG __RPC_FAR *plID) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnNextAdd( void) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleUndoUnitVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleUndoUnit __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleUndoUnit __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleUndoUnit __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Do )( \n            IOleUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleUndoManager __RPC_FAR *pUndoManager);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDescription )( \n            IOleUndoUnit __RPC_FAR * This,\n            /* [out] */ BSTR __RPC_FAR *pBstr);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetUnitType )( \n            IOleUndoUnit __RPC_FAR * This,\n            /* [out] */ CLSID __RPC_FAR *pClsid,\n            /* [out] */ LONG __RPC_FAR *plID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnNextAdd )( \n            IOleUndoUnit __RPC_FAR * This);\n        \n        END_INTERFACE\n    } IOleUndoUnitVtbl;\n\n    interface IOleUndoUnit\n    {\n        CONST_VTBL struct IOleUndoUnitVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleUndoUnit_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleUndoUnit_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleUndoUnit_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleUndoUnit_Do(This,pUndoManager)\t\\\n    (This)->lpVtbl -> Do(This,pUndoManager)\n\n#define IOleUndoUnit_GetDescription(This,pBstr)\t\\\n    (This)->lpVtbl -> GetDescription(This,pBstr)\n\n#define IOleUndoUnit_GetUnitType(This,pClsid,plID)\t\\\n    (This)->lpVtbl -> GetUnitType(This,pClsid,plID)\n\n#define IOleUndoUnit_OnNextAdd(This)\t\\\n    (This)->lpVtbl -> OnNextAdd(This)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoUnit_Do_Proxy( \n    IOleUndoUnit __RPC_FAR * This,\n    /* [in] */ IOleUndoManager __RPC_FAR *pUndoManager);\n\n\nvoid __RPC_STUB IOleUndoUnit_Do_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoUnit_GetDescription_Proxy( \n    IOleUndoUnit __RPC_FAR * This,\n    /* [out] */ BSTR __RPC_FAR *pBstr);\n\n\nvoid __RPC_STUB IOleUndoUnit_GetDescription_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoUnit_GetUnitType_Proxy( \n    IOleUndoUnit __RPC_FAR * This,\n    /* [out] */ CLSID __RPC_FAR *pClsid,\n    /* [out] */ LONG __RPC_FAR *plID);\n\n\nvoid __RPC_STUB IOleUndoUnit_GetUnitType_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoUnit_OnNextAdd_Proxy( \n    IOleUndoUnit __RPC_FAR * This);\n\n\nvoid __RPC_STUB IOleUndoUnit_OnNextAdd_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleUndoUnit_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleParentUndoUnit_INTERFACE_DEFINED__\n#define __IOleParentUndoUnit_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleParentUndoUnit\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IOleParentUndoUnit __RPC_FAR *LPOLEPARENTUNDOUNIT;\n\n\nEXTERN_C const IID IID_IOleParentUndoUnit;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleParentUndoUnit : public IOleUndoUnit\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE Open( \n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Close( \n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n            /* [in] */ BOOL fCommit) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Add( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE FindUnit( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetParentState( \n            /* [out] */ DWORD __RPC_FAR *pdwState) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleParentUndoUnitVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleParentUndoUnit __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleParentUndoUnit __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Do )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleUndoManager __RPC_FAR *pUndoManager);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDescription )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [out] */ BSTR __RPC_FAR *pBstr);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetUnitType )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [out] */ CLSID __RPC_FAR *pClsid,\n            /* [out] */ LONG __RPC_FAR *plID);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnNextAdd )( \n            IOleParentUndoUnit __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Open )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Close )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n            /* [in] */ BOOL fCommit);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Add )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FindUnit )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetParentState )( \n            IOleParentUndoUnit __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pdwState);\n        \n        END_INTERFACE\n    } IOleParentUndoUnitVtbl;\n\n    interface IOleParentUndoUnit\n    {\n        CONST_VTBL struct IOleParentUndoUnitVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleParentUndoUnit_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleParentUndoUnit_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleParentUndoUnit_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleParentUndoUnit_Do(This,pUndoManager)\t\\\n    (This)->lpVtbl -> Do(This,pUndoManager)\n\n#define IOleParentUndoUnit_GetDescription(This,pBstr)\t\\\n    (This)->lpVtbl -> GetDescription(This,pBstr)\n\n#define IOleParentUndoUnit_GetUnitType(This,pClsid,plID)\t\\\n    (This)->lpVtbl -> GetUnitType(This,pClsid,plID)\n\n#define IOleParentUndoUnit_OnNextAdd(This)\t\\\n    (This)->lpVtbl -> OnNextAdd(This)\n\n\n#define IOleParentUndoUnit_Open(This,pPUU)\t\\\n    (This)->lpVtbl -> Open(This,pPUU)\n\n#define IOleParentUndoUnit_Close(This,pPUU,fCommit)\t\\\n    (This)->lpVtbl -> Close(This,pPUU,fCommit)\n\n#define IOleParentUndoUnit_Add(This,pUU)\t\\\n    (This)->lpVtbl -> Add(This,pUU)\n\n#define IOleParentUndoUnit_FindUnit(This,pUU)\t\\\n    (This)->lpVtbl -> FindUnit(This,pUU)\n\n#define IOleParentUndoUnit_GetParentState(This,pdwState)\t\\\n    (This)->lpVtbl -> GetParentState(This,pdwState)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleParentUndoUnit_Open_Proxy( \n    IOleParentUndoUnit __RPC_FAR * This,\n    /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU);\n\n\nvoid __RPC_STUB IOleParentUndoUnit_Open_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleParentUndoUnit_Close_Proxy( \n    IOleParentUndoUnit __RPC_FAR * This,\n    /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n    /* [in] */ BOOL fCommit);\n\n\nvoid __RPC_STUB IOleParentUndoUnit_Close_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleParentUndoUnit_Add_Proxy( \n    IOleParentUndoUnit __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleParentUndoUnit_Add_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleParentUndoUnit_FindUnit_Proxy( \n    IOleParentUndoUnit __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleParentUndoUnit_FindUnit_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleParentUndoUnit_GetParentState_Proxy( \n    IOleParentUndoUnit __RPC_FAR * This,\n    /* [out] */ DWORD __RPC_FAR *pdwState);\n\n\nvoid __RPC_STUB IOleParentUndoUnit_GetParentState_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleParentUndoUnit_INTERFACE_DEFINED__ */\n\n\n#ifndef __IEnumOleUndoUnits_INTERFACE_DEFINED__\n#define __IEnumOleUndoUnits_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IEnumOleUndoUnits\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IEnumOleUndoUnits __RPC_FAR *LPENUMOLEUNDOUNITS;\n\n\nEXTERN_C const IID IID_IEnumOleUndoUnits;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IEnumOleUndoUnits : public IUnknown\n    {\n    public:\n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( \n            /* [in] */ ULONG cElt,\n            /* [length_is][size_is][out] */ IOleUndoUnit __RPC_FAR *__RPC_FAR *rgElt,\n            /* [out] */ ULONG __RPC_FAR *pcEltFetched) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Skip( \n            /* [in] */ ULONG cElt) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Clone( \n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IEnumOleUndoUnitsVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IEnumOleUndoUnits __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IEnumOleUndoUnits __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IEnumOleUndoUnits __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( \n            IEnumOleUndoUnits __RPC_FAR * This,\n            /* [in] */ ULONG cElt,\n            /* [length_is][size_is][out] */ IOleUndoUnit __RPC_FAR *__RPC_FAR *rgElt,\n            /* [out] */ ULONG __RPC_FAR *pcEltFetched);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( \n            IEnumOleUndoUnits __RPC_FAR * This,\n            /* [in] */ ULONG cElt);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( \n            IEnumOleUndoUnits __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( \n            IEnumOleUndoUnits __RPC_FAR * This,\n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        END_INTERFACE\n    } IEnumOleUndoUnitsVtbl;\n\n    interface IEnumOleUndoUnits\n    {\n        CONST_VTBL struct IEnumOleUndoUnitsVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IEnumOleUndoUnits_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IEnumOleUndoUnits_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IEnumOleUndoUnits_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IEnumOleUndoUnits_Next(This,cElt,rgElt,pcEltFetched)\t\\\n    (This)->lpVtbl -> Next(This,cElt,rgElt,pcEltFetched)\n\n#define IEnumOleUndoUnits_Skip(This,cElt)\t\\\n    (This)->lpVtbl -> Skip(This,cElt)\n\n#define IEnumOleUndoUnits_Reset(This)\t\\\n    (This)->lpVtbl -> Reset(This)\n\n#define IEnumOleUndoUnits_Clone(This,ppEnum)\t\\\n    (This)->lpVtbl -> Clone(This,ppEnum)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_RemoteNext_Proxy( \n    IEnumOleUndoUnits __RPC_FAR * This,\n    /* [in] */ ULONG cElt,\n    /* [length_is][size_is][out] */ IOleUndoUnit __RPC_FAR *__RPC_FAR *rgElt,\n    /* [out] */ ULONG __RPC_FAR *pcEltFetched);\n\n\nvoid __RPC_STUB IEnumOleUndoUnits_RemoteNext_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_Skip_Proxy( \n    IEnumOleUndoUnits __RPC_FAR * This,\n    /* [in] */ ULONG cElt);\n\n\nvoid __RPC_STUB IEnumOleUndoUnits_Skip_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_Reset_Proxy( \n    IEnumOleUndoUnits __RPC_FAR * This);\n\n\nvoid __RPC_STUB IEnumOleUndoUnits_Reset_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_Clone_Proxy( \n    IEnumOleUndoUnits __RPC_FAR * This,\n    /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IEnumOleUndoUnits_Clone_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IEnumOleUndoUnits_INTERFACE_DEFINED__ */\n\n\n#ifndef __IOleUndoManager_INTERFACE_DEFINED__\n#define __IOleUndoManager_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IOleUndoManager\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\n#define SID_SOleUndoManager IID_IOleUndoManager;\ntypedef IOleUndoManager __RPC_FAR *LPOLEUNDOMANAGER;\n\n\nEXTERN_C const IID IID_IOleUndoManager;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IOleUndoManager : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE Open( \n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Close( \n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n            /* [in] */ BOOL fCommit) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Add( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetOpenParentState( \n            /* [out] */ DWORD __RPC_FAR *pdwState) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE DiscardFrom( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE UndoTo( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE RedoTo( \n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE EnumUndoable( \n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE EnumRedoable( \n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetLastUndoDescription( \n            /* [out] */ BSTR __RPC_FAR *pBstr) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetLastRedoDescription( \n            /* [out] */ BSTR __RPC_FAR *pBstr) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Enable( \n            /* [in] */ BOOL fEnable) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IOleUndoManagerVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IOleUndoManager __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IOleUndoManager __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Open )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Close )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n            /* [in] */ BOOL fCommit);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Add )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetOpenParentState )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pdwState);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DiscardFrom )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UndoTo )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RedoTo )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumUndoable )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumRedoable )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetLastUndoDescription )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [out] */ BSTR __RPC_FAR *pBstr);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetLastRedoDescription )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [out] */ BSTR __RPC_FAR *pBstr);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Enable )( \n            IOleUndoManager __RPC_FAR * This,\n            /* [in] */ BOOL fEnable);\n        \n        END_INTERFACE\n    } IOleUndoManagerVtbl;\n\n    interface IOleUndoManager\n    {\n        CONST_VTBL struct IOleUndoManagerVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IOleUndoManager_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IOleUndoManager_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IOleUndoManager_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IOleUndoManager_Open(This,pPUU)\t\\\n    (This)->lpVtbl -> Open(This,pPUU)\n\n#define IOleUndoManager_Close(This,pPUU,fCommit)\t\\\n    (This)->lpVtbl -> Close(This,pPUU,fCommit)\n\n#define IOleUndoManager_Add(This,pUU)\t\\\n    (This)->lpVtbl -> Add(This,pUU)\n\n#define IOleUndoManager_GetOpenParentState(This,pdwState)\t\\\n    (This)->lpVtbl -> GetOpenParentState(This,pdwState)\n\n#define IOleUndoManager_DiscardFrom(This,pUU)\t\\\n    (This)->lpVtbl -> DiscardFrom(This,pUU)\n\n#define IOleUndoManager_UndoTo(This,pUU)\t\\\n    (This)->lpVtbl -> UndoTo(This,pUU)\n\n#define IOleUndoManager_RedoTo(This,pUU)\t\\\n    (This)->lpVtbl -> RedoTo(This,pUU)\n\n#define IOleUndoManager_EnumUndoable(This,ppEnum)\t\\\n    (This)->lpVtbl -> EnumUndoable(This,ppEnum)\n\n#define IOleUndoManager_EnumRedoable(This,ppEnum)\t\\\n    (This)->lpVtbl -> EnumRedoable(This,ppEnum)\n\n#define IOleUndoManager_GetLastUndoDescription(This,pBstr)\t\\\n    (This)->lpVtbl -> GetLastUndoDescription(This,pBstr)\n\n#define IOleUndoManager_GetLastRedoDescription(This,pBstr)\t\\\n    (This)->lpVtbl -> GetLastRedoDescription(This,pBstr)\n\n#define IOleUndoManager_Enable(This,fEnable)\t\\\n    (This)->lpVtbl -> Enable(This,fEnable)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_Open_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU);\n\n\nvoid __RPC_STUB IOleUndoManager_Open_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_Close_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleParentUndoUnit __RPC_FAR *pPUU,\n    /* [in] */ BOOL fCommit);\n\n\nvoid __RPC_STUB IOleUndoManager_Close_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_Add_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleUndoManager_Add_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_GetOpenParentState_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [out] */ DWORD __RPC_FAR *pdwState);\n\n\nvoid __RPC_STUB IOleUndoManager_GetOpenParentState_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_DiscardFrom_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleUndoManager_DiscardFrom_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_UndoTo_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleUndoManager_UndoTo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_RedoTo_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ IOleUndoUnit __RPC_FAR *pUU);\n\n\nvoid __RPC_STUB IOleUndoManager_RedoTo_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_EnumUndoable_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IOleUndoManager_EnumUndoable_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_EnumRedoable_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [out] */ IEnumOleUndoUnits __RPC_FAR *__RPC_FAR *ppEnum);\n\n\nvoid __RPC_STUB IOleUndoManager_EnumRedoable_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_GetLastUndoDescription_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [out] */ BSTR __RPC_FAR *pBstr);\n\n\nvoid __RPC_STUB IOleUndoManager_GetLastUndoDescription_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_GetLastRedoDescription_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [out] */ BSTR __RPC_FAR *pBstr);\n\n\nvoid __RPC_STUB IOleUndoManager_GetLastRedoDescription_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IOleUndoManager_Enable_Proxy( \n    IOleUndoManager __RPC_FAR * This,\n    /* [in] */ BOOL fEnable);\n\n\nvoid __RPC_STUB IOleUndoManager_Enable_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IOleUndoManager_INTERFACE_DEFINED__ */\n\n\n#ifndef __IQuickActivate_INTERFACE_DEFINED__\n#define __IQuickActivate_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IQuickActivate\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object][local] */ \n\n\ntypedef IQuickActivate __RPC_FAR *LPQUICKACTIVATE;\n\ntypedef /* [v1_enum] */ \nenum tagQACONTAINERFLAGS\n    {\tQACONTAINER_SHOWHATCHING\t= 0x1,\n\tQACONTAINER_SHOWGRABHANDLES\t= 0x2,\n\tQACONTAINER_USERMODE\t= 0x4,\n\tQACONTAINER_DISPLAYASDEFAULT\t= 0x8,\n\tQACONTAINER_UIDEAD\t= 0x10,\n\tQACONTAINER_AUTOCLIP\t= 0x20,\n\tQACONTAINER_MESSAGEREFLECT\t= 0x40,\n\tQACONTAINER_SUPPORTSMNEMONICS\t= 0x80\n    }\tQACONTAINERFLAGS;\n\ntypedef DWORD OLE_COLOR;\n\ntypedef struct  tagQACONTAINER\n    {\n    ULONG cbSize;\n    IOleClientSite __RPC_FAR *pClientSite;\n    IAdviseSinkEx __RPC_FAR *pAdviseSink;\n    IPropertyNotifySink __RPC_FAR *pPropertyNotifySink;\n    IUnknown __RPC_FAR *pUnkEventSink;\n    DWORD dwAmbientFlags;\n    OLE_COLOR colorFore;\n    OLE_COLOR colorBack;\n    IFont __RPC_FAR *pFont;\n    IOleUndoManager __RPC_FAR *pUndoMgr;\n    DWORD dwAppearance;\n    LONG lcid;\n    HPALETTE hpal;\n    struct IBindHost __RPC_FAR *pBindHost;\n    }\tQACONTAINER;\n\ntypedef struct  tagQACONTROL\n    {\n    ULONG cbSize;\n    DWORD dwMiscStatus;\n    DWORD dwViewStatus;\n    DWORD dwEventCookie;\n    DWORD dwPropNotifyCookie;\n    DWORD dwPointerActivationPolicy;\n    }\tQACONTROL;\n\n\nEXTERN_C const IID IID_IQuickActivate;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IQuickActivate : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE QuickActivate( \n            /* [in] */ QACONTAINER __RPC_FAR *pQaContainer,\n            /* [out] */ QACONTROL __RPC_FAR *pQaControl) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE SetContentExtent( \n            LPSIZEL pSizel) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetContentExtent( \n            LPSIZEL pSizel) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IQuickActivateVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IQuickActivate __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IQuickActivate __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IQuickActivate __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QuickActivate )( \n            IQuickActivate __RPC_FAR * This,\n            /* [in] */ QACONTAINER __RPC_FAR *pQaContainer,\n            /* [out] */ QACONTROL __RPC_FAR *pQaControl);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContentExtent )( \n            IQuickActivate __RPC_FAR * This,\n            LPSIZEL pSizel);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContentExtent )( \n            IQuickActivate __RPC_FAR * This,\n            LPSIZEL pSizel);\n        \n        END_INTERFACE\n    } IQuickActivateVtbl;\n\n    interface IQuickActivate\n    {\n        CONST_VTBL struct IQuickActivateVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IQuickActivate_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IQuickActivate_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IQuickActivate_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IQuickActivate_QuickActivate(This,pQaContainer,pQaControl)\t\\\n    (This)->lpVtbl -> QuickActivate(This,pQaContainer,pQaControl)\n\n#define IQuickActivate_SetContentExtent(This,pSizel)\t\\\n    (This)->lpVtbl -> SetContentExtent(This,pSizel)\n\n#define IQuickActivate_GetContentExtent(This,pSizel)\t\\\n    (This)->lpVtbl -> GetContentExtent(This,pSizel)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IQuickActivate_QuickActivate_Proxy( \n    IQuickActivate __RPC_FAR * This,\n    /* [in] */ QACONTAINER __RPC_FAR *pQaContainer,\n    /* [out] */ QACONTROL __RPC_FAR *pQaControl);\n\n\nvoid __RPC_STUB IQuickActivate_QuickActivate_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IQuickActivate_SetContentExtent_Proxy( \n    IQuickActivate __RPC_FAR * This,\n    LPSIZEL pSizel);\n\n\nvoid __RPC_STUB IQuickActivate_SetContentExtent_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IQuickActivate_GetContentExtent_Proxy( \n    IQuickActivate __RPC_FAR * This,\n    LPSIZEL pSizel);\n\n\nvoid __RPC_STUB IQuickActivate_GetContentExtent_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IQuickActivate_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPointerInactive_INTERFACE_DEFINED__\n#define __IPointerInactive_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPointerInactive\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [uuid][unique][object] */ \n\n\ntypedef IPointerInactive __RPC_FAR *LPPOINTERINACTIVE;\n\ntypedef /* [v1_enum] */ \nenum tagPOINTERINACTIVE\n    {\tPOINTERINACTIVE_ACTIVATEONENTRY\t= 1,\n\tPOINTERINACTIVE_DEACTIVATEONLEAVE\t= 2,\n\tPOINTERINACTIVE_ACTIVATEONDRAG\t= 4\n    }\tPOINTERINACTIVE;\n\n\nEXTERN_C const IID IID_IPointerInactive;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPointerInactive : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetActivationPolicy( \n            /* [out] */ DWORD __RPC_FAR *pdwPolicy) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnInactiveMouseMove( \n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ DWORD grfKeyState) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE OnInactiveSetCursor( \n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ DWORD dwMouseMsg,\n            /* [in] */ BOOL fSetAlways) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPointerInactiveVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPointerInactive __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPointerInactive __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPointerInactive __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetActivationPolicy )( \n            IPointerInactive __RPC_FAR * This,\n            /* [out] */ DWORD __RPC_FAR *pdwPolicy);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInactiveMouseMove )( \n            IPointerInactive __RPC_FAR * This,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ DWORD grfKeyState);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *OnInactiveSetCursor )( \n            IPointerInactive __RPC_FAR * This,\n            /* [in] */ LPCRECT pRectBounds,\n            /* [in] */ LONG x,\n            /* [in] */ LONG y,\n            /* [in] */ DWORD dwMouseMsg,\n            /* [in] */ BOOL fSetAlways);\n        \n        END_INTERFACE\n    } IPointerInactiveVtbl;\n\n    interface IPointerInactive\n    {\n        CONST_VTBL struct IPointerInactiveVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPointerInactive_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPointerInactive_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPointerInactive_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPointerInactive_GetActivationPolicy(This,pdwPolicy)\t\\\n    (This)->lpVtbl -> GetActivationPolicy(This,pdwPolicy)\n\n#define IPointerInactive_OnInactiveMouseMove(This,pRectBounds,x,y,grfKeyState)\t\\\n    (This)->lpVtbl -> OnInactiveMouseMove(This,pRectBounds,x,y,grfKeyState)\n\n#define IPointerInactive_OnInactiveSetCursor(This,pRectBounds,x,y,dwMouseMsg,fSetAlways)\t\\\n    (This)->lpVtbl -> OnInactiveSetCursor(This,pRectBounds,x,y,dwMouseMsg,fSetAlways)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPointerInactive_GetActivationPolicy_Proxy( \n    IPointerInactive __RPC_FAR * This,\n    /* [out] */ DWORD __RPC_FAR *pdwPolicy);\n\n\nvoid __RPC_STUB IPointerInactive_GetActivationPolicy_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPointerInactive_OnInactiveMouseMove_Proxy( \n    IPointerInactive __RPC_FAR * This,\n    /* [in] */ LPCRECT pRectBounds,\n    /* [in] */ LONG x,\n    /* [in] */ LONG y,\n    /* [in] */ DWORD grfKeyState);\n\n\nvoid __RPC_STUB IPointerInactive_OnInactiveMouseMove_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPointerInactive_OnInactiveSetCursor_Proxy( \n    IPointerInactive __RPC_FAR * This,\n    /* [in] */ LPCRECT pRectBounds,\n    /* [in] */ LONG x,\n    /* [in] */ LONG y,\n    /* [in] */ DWORD dwMouseMsg,\n    /* [in] */ BOOL fSetAlways);\n\n\nvoid __RPC_STUB IPointerInactive_OnInactiveSetCursor_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPointerInactive_INTERFACE_DEFINED__ */\n\n\n#ifndef __IObjectWithSite_INTERFACE_DEFINED__\n#define __IObjectWithSite_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IObjectWithSite\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IObjectWithSite __RPC_FAR *LPOBJECTWITHSITE;\n\n\nEXTERN_C const IID IID_IObjectWithSite;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IObjectWithSite : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE SetSite( \n            /* [in] */ IUnknown __RPC_FAR *pUnkSite) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetSite( \n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvSite) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IObjectWithSiteVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IObjectWithSite __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IObjectWithSite __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IObjectWithSite __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetSite )( \n            IObjectWithSite __RPC_FAR * This,\n            /* [in] */ IUnknown __RPC_FAR *pUnkSite);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetSite )( \n            IObjectWithSite __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvSite);\n        \n        END_INTERFACE\n    } IObjectWithSiteVtbl;\n\n    interface IObjectWithSite\n    {\n        CONST_VTBL struct IObjectWithSiteVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IObjectWithSite_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IObjectWithSite_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IObjectWithSite_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IObjectWithSite_SetSite(This,pUnkSite)\t\\\n    (This)->lpVtbl -> SetSite(This,pUnkSite)\n\n#define IObjectWithSite_GetSite(This,riid,ppvSite)\t\\\n    (This)->lpVtbl -> GetSite(This,riid,ppvSite)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IObjectWithSite_SetSite_Proxy( \n    IObjectWithSite __RPC_FAR * This,\n    /* [in] */ IUnknown __RPC_FAR *pUnkSite);\n\n\nvoid __RPC_STUB IObjectWithSite_SetSite_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IObjectWithSite_GetSite_Proxy( \n    IObjectWithSite __RPC_FAR * This,\n    /* [in] */ REFIID riid,\n    /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvSite);\n\n\nvoid __RPC_STUB IObjectWithSite_GetSite_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IObjectWithSite_INTERFACE_DEFINED__ */\n\n\n#ifndef __IErrorLog_INTERFACE_DEFINED__\n#define __IErrorLog_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IErrorLog\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IErrorLog __RPC_FAR *LPERRORLOG;\n\n\nEXTERN_C const IID IID_IErrorLog;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IErrorLog : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE AddError( \n            /* [in] */ LPCOLESTR pszPropName,\n            /* [in] */ EXCEPINFO __RPC_FAR *pExcepInfo) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IErrorLogVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IErrorLog __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IErrorLog __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IErrorLog __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddError )( \n            IErrorLog __RPC_FAR * This,\n            /* [in] */ LPCOLESTR pszPropName,\n            /* [in] */ EXCEPINFO __RPC_FAR *pExcepInfo);\n        \n        END_INTERFACE\n    } IErrorLogVtbl;\n\n    interface IErrorLog\n    {\n        CONST_VTBL struct IErrorLogVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IErrorLog_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IErrorLog_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IErrorLog_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IErrorLog_AddError(This,pszPropName,pExcepInfo)\t\\\n    (This)->lpVtbl -> AddError(This,pszPropName,pExcepInfo)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IErrorLog_AddError_Proxy( \n    IErrorLog __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszPropName,\n    /* [in] */ EXCEPINFO __RPC_FAR *pExcepInfo);\n\n\nvoid __RPC_STUB IErrorLog_AddError_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IErrorLog_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPropertyBag_INTERFACE_DEFINED__\n#define __IPropertyBag_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPropertyBag\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPropertyBag __RPC_FAR *LPPROPERTYBAG;\n\n\nEXTERN_C const IID IID_IPropertyBag;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPropertyBag : public IUnknown\n    {\n    public:\n        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( \n            /* [in] */ LPCOLESTR pszPropName,\n            /* [out][in] */ VARIANT __RPC_FAR *pVar,\n            /* [in] */ IErrorLog __RPC_FAR *pErrorLog) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE Write( \n            /* [in] */ LPCOLESTR pszPropName,\n            /* [in] */ VARIANT __RPC_FAR *pVar) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPropertyBagVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPropertyBag __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPropertyBag __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPropertyBag __RPC_FAR * This);\n        \n        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Read )( \n            IPropertyBag __RPC_FAR * This,\n            /* [in] */ LPCOLESTR pszPropName,\n            /* [out][in] */ VARIANT __RPC_FAR *pVar,\n            /* [in] */ IErrorLog __RPC_FAR *pErrorLog);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Write )( \n            IPropertyBag __RPC_FAR * This,\n            /* [in] */ LPCOLESTR pszPropName,\n            /* [in] */ VARIANT __RPC_FAR *pVar);\n        \n        END_INTERFACE\n    } IPropertyBagVtbl;\n\n    interface IPropertyBag\n    {\n        CONST_VTBL struct IPropertyBagVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPropertyBag_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPropertyBag_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPropertyBag_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPropertyBag_Read(This,pszPropName,pVar,pErrorLog)\t\\\n    (This)->lpVtbl -> Read(This,pszPropName,pVar,pErrorLog)\n\n#define IPropertyBag_Write(This,pszPropName,pVar)\t\\\n    (This)->lpVtbl -> Write(This,pszPropName,pVar)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPropertyBag_RemoteRead_Proxy( \n    IPropertyBag __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszPropName,\n    /* [out] */ VARIANT __RPC_FAR *pVar,\n    /* [in] */ IErrorLog __RPC_FAR *pErrorLog,\n    /* [in] */ DWORD varType,\n    /* [in] */ IUnknown __RPC_FAR *pUnkObj);\n\n\nvoid __RPC_STUB IPropertyBag_RemoteRead_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPropertyBag_Write_Proxy( \n    IPropertyBag __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszPropName,\n    /* [in] */ VARIANT __RPC_FAR *pVar);\n\n\nvoid __RPC_STUB IPropertyBag_Write_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPropertyBag_INTERFACE_DEFINED__ */\n\n\n#ifndef __IPerPropertyBrowsing_INTERFACE_DEFINED__\n#define __IPerPropertyBrowsing_INTERFACE_DEFINED__\n\n/****************************************\n * Generated header for interface: IPerPropertyBrowsing\n * at Sat Jul 13 21:56:58 1996\n * using MIDL 3.00.39\n ****************************************/\n/* [unique][uuid][object] */ \n\n\ntypedef IPerPropertyBrowsing __RPC_FAR *LPPERPROPERTYBROWSING;\n\ntypedef struct  tagCALPOLESTR\n    {\n    ULONG cElems;\n    /* [size_is] */ LPOLESTR __RPC_FAR *pElems;\n    }\tCALPOLESTR;\n\ntypedef struct tagCALPOLESTR __RPC_FAR *LPCALPOLESTR;\n\ntypedef struct  tagCADWORD\n    {\n    ULONG cElems;\n    /* [size_is] */ DWORD __RPC_FAR *pElems;\n    }\tCADWORD;\n\ntypedef struct tagCADWORD __RPC_FAR *LPCADWORD;\n\n\nEXTERN_C const IID IID_IPerPropertyBrowsing;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n    \n    interface IPerPropertyBrowsing : public IUnknown\n    {\n    public:\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayString( \n            /* [in] */ DISPID dispID,\n            /* [out] */ BSTR __RPC_FAR *pBstr) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE MapPropertyToPage( \n            /* [in] */ DISPID dispID,\n            /* [out] */ CLSID __RPC_FAR *pClsid) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetPredefinedStrings( \n            /* [in] */ DISPID dispID,\n            /* [out] */ CALPOLESTR __RPC_FAR *pCaStringsOut,\n            /* [out] */ CADWORD __RPC_FAR *pCaCookiesOut) = 0;\n        \n        virtual HRESULT STDMETHODCALLTYPE GetPredefinedValue( \n            /* [in] */ DISPID dispID,\n            /* [in] */ DWORD dwCookie,\n            /* [out] */ VARIANT __RPC_FAR *pVarOut) = 0;\n        \n    };\n    \n#else \t/* C style interface */\n\n    typedef struct IPerPropertyBrowsingVtbl\n    {\n        BEGIN_INTERFACE\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( \n            IPerPropertyBrowsing __RPC_FAR * This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( \n            IPerPropertyBrowsing __RPC_FAR * This);\n        \n        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( \n            IPerPropertyBrowsing __RPC_FAR * This);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDisplayString )( \n            IPerPropertyBrowsing __RPC_FAR * This,\n            /* [in] */ DISPID dispID,\n            /* [out] */ BSTR __RPC_FAR *pBstr);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MapPropertyToPage )( \n            IPerPropertyBrowsing __RPC_FAR * This,\n            /* [in] */ DISPID dispID,\n            /* [out] */ CLSID __RPC_FAR *pClsid);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPredefinedStrings )( \n            IPerPropertyBrowsing __RPC_FAR * This,\n            /* [in] */ DISPID dispID,\n            /* [out] */ CALPOLESTR __RPC_FAR *pCaStringsOut,\n            /* [out] */ CADWORD __RPC_FAR *pCaCookiesOut);\n        \n        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetPredefinedValue )( \n            IPerPropertyBrowsing __RPC_FAR * This,\n            /* [in] */ DISPID dispID,\n            /* [in] */ DWORD dwCookie,\n            /* [out] */ VARIANT __RPC_FAR *pVarOut);\n        \n        END_INTERFACE\n    } IPerPropertyBrowsingVtbl;\n\n    interface IPerPropertyBrowsing\n    {\n        CONST_VTBL struct IPerPropertyBrowsingVtbl __RPC_FAR *lpVtbl;\n    };\n\n    \n\n#ifdef COBJMACROS\n\n\n#define IPerPropertyBrowsing_QueryInterface(This,riid,ppvObject)\t\\\n    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\n\n#define IPerPropertyBrowsing_AddRef(This)\t\\\n    (This)->lpVtbl -> AddRef(This)\n\n#define IPerPropertyBrowsing_Release(This)\t\\\n    (This)->lpVtbl -> Release(This)\n\n\n#define IPerPropertyBrowsing_GetDisplayString(This,dispID,pBstr)\t\\\n    (This)->lpVtbl -> GetDisplayString(This,dispID,pBstr)\n\n#define IPerPropertyBrowsing_MapPropertyToPage(This,dispID,pClsid)\t\\\n    (This)->lpVtbl -> MapPropertyToPage(This,dispID,pClsid)\n\n#define IPerPropertyBrowsing_GetPredefinedStrings(This,dispID,pCaStringsOut,pCaCookiesOut)\t\\\n    (This)->lpVtbl -> GetPredefinedStrings(This,dispID,pCaStringsOut,pCaCookiesOut)\n\n#define IPerPropertyBrowsing_GetPredefinedValue(This,dispID,dwCookie,pVarOut)\t\\\n    (This)->lpVtbl -> GetPredefinedValue(This,dispID,dwCookie,pVarOut)\n\n#endif /* COBJMACROS */\n\n\n#endif \t/* C style interface */\n\n\n\nHRESULT STDMETHODCALLTYPE IPerPropertyBrowsing_GetDisplayString_Proxy( \n    IPerPropertyBrowsing __RPC_FAR * This,\n    /* [in] */ DISPID dispID,\n    /* [out] */ BSTR __RPC_FAR *pBstr);\n\n\nvoid __RPC_STUB IPerPropertyBrowsing_GetDisplayString_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPerPropertyBrowsing_MapPropertyToPage_Proxy( \n    IPerPropertyBrowsing __RPC_FAR * This,\n    /* [in] */ DISPID dispID,\n    /* [out] */ CLSID __RPC_FAR *pClsid);\n\n\nvoid __RPC_STUB IPerPropertyBrowsing_MapPropertyToPage_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPerPropertyBrowsing_GetPredefinedStrings_Proxy( \n    IPerPropertyBrowsing __RPC_FAR * This,\n    /* [in] */ DISPID dispID,\n    /* [out] */ CALPOLESTR __RPC_FAR *pCaStringsOut,\n    /* [out] */ CADWORD __RPC_FAR *pCaCookiesOut);\n\n\nvoid __RPC_STUB IPerPropertyBrowsing_GetPredefinedStrings_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\nHRESULT STDMETHODCALLTYPE IPerPropertyBrowsing_GetPredefinedValue_Proxy( \n    IPerPropertyBrowsing __RPC_FAR * This,\n    /* [in] */ DISPID dispID,\n    /* [in] */ DWORD dwCookie,\n    /* [out] */ VARIANT __RPC_FAR *pVarOut);\n\n\nvoid __RPC_STUB IPerPropertyBrowsing_GetPredefinedValue_Stub(\n    IRpcStubBuffer *This,\n    IRpcChannelBuffer *_pRpcChannelBuffer,\n    PRPC_MESSAGE _pRpcMessage,\n    DWORD *_pdwStubPhase);\n\n\n\n#endif \t/* __IPerPropertyBrowsing_INTERFACE_DEFINED__ */\n\n\n/* Additional Prototypes for ALL interfaces */\n\n\nvoid __RPC_USER UserHWND_from_local( HWND __RPC_FAR *, UserHWND __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserHWND_to_local( UserHWND __RPC_FAR *, HWND __RPC_FAR * );\n void __RPC_USER UserHWND_free_inst( UserHWND __RPC_FAR * );\nvoid __RPC_USER UserHWND_free_local( HWND __RPC_FAR * );\n\nvoid __RPC_USER UserHACCEL_from_local( HACCEL __RPC_FAR *, UserHACCEL __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserHACCEL_to_local( UserHACCEL __RPC_FAR *, HACCEL __RPC_FAR * );\n void __RPC_USER UserHACCEL_free_inst( UserHACCEL __RPC_FAR * );\nvoid __RPC_USER UserHACCEL_free_local( HACCEL __RPC_FAR * );\n\nvoid __RPC_USER UserHDC_from_local( HDC __RPC_FAR *, UserHDC __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserHDC_to_local( UserHDC __RPC_FAR *, HDC __RPC_FAR * );\n void __RPC_USER UserHDC_free_inst( UserHDC __RPC_FAR * );\nvoid __RPC_USER UserHDC_free_local( HDC __RPC_FAR * );\n\nvoid __RPC_USER UserHFONT_from_local( HFONT __RPC_FAR *, UserHFONT __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserHFONT_to_local( UserHFONT __RPC_FAR *, HFONT __RPC_FAR * );\n void __RPC_USER UserHFONT_free_inst( UserHFONT __RPC_FAR * );\nvoid __RPC_USER UserHFONT_free_local( HFONT __RPC_FAR * );\n\nvoid __RPC_USER UserMSG_from_local( MSG __RPC_FAR *, UserMSG __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserMSG_to_local( UserMSG __RPC_FAR *, MSG __RPC_FAR * );\n void __RPC_USER UserMSG_free_inst( UserMSG __RPC_FAR * );\nvoid __RPC_USER UserMSG_free_local( MSG __RPC_FAR * );\n\nvoid __RPC_USER UserBSTR_from_local( BSTR __RPC_FAR *, UserBSTR __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserBSTR_to_local( UserBSTR __RPC_FAR *, BSTR __RPC_FAR * );\n void __RPC_USER UserBSTR_free_inst( UserBSTR __RPC_FAR * );\nvoid __RPC_USER UserBSTR_free_local( BSTR __RPC_FAR * );\n\nvoid __RPC_USER UserVARIANT_from_local( VARIANT __RPC_FAR *, UserVARIANT __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserVARIANT_to_local( UserVARIANT __RPC_FAR *, VARIANT __RPC_FAR * );\n void __RPC_USER UserVARIANT_free_inst( UserVARIANT __RPC_FAR * );\nvoid __RPC_USER UserVARIANT_free_local( VARIANT __RPC_FAR * );\n\nvoid __RPC_USER UserEXCEPINFO_from_local( EXCEPINFO __RPC_FAR *, UserEXCEPINFO __RPC_FAR * __RPC_FAR * );\nvoid __RPC_USER UserEXCEPINFO_to_local( UserEXCEPINFO __RPC_FAR *, EXCEPINFO __RPC_FAR * );\n void __RPC_USER UserEXCEPINFO_free_inst( UserEXCEPINFO __RPC_FAR * );\nvoid __RPC_USER UserEXCEPINFO_free_local( EXCEPINFO __RPC_FAR * );\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IEnumConnections_Next_Proxy( \n    IEnumConnections __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTDATA rgcd,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumConnections_Next_Stub( \n    IEnumConnections __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTDATA rgcd,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Next_Proxy( \n    IEnumConnectionPoints __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTIONPOINT __RPC_FAR *ppCP,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Next_Stub( \n    IEnumConnectionPoints __RPC_FAR * This,\n    /* [in] */ ULONG cConnections,\n    /* [length_is][size_is][out] */ LPCONNECTIONPOINT __RPC_FAR *ppCP,\n    /* [out] */ ULONG __RPC_FAR *pcFetched);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IClassFactory2_CreateInstanceLic_Proxy( \n    IClassFactory2 __RPC_FAR * This,\n    /* [in] */ IUnknown __RPC_FAR *pUnkOuter,\n    /* [in] */ IUnknown __RPC_FAR *pUnkReserved,\n    /* [in] */ REFIID riid,\n    /* [in] */ BSTR bstrKey,\n    /* [iid_is][out] */ PVOID __RPC_FAR *ppvObj);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IClassFactory2_CreateInstanceLic_Stub( \n    IClassFactory2 __RPC_FAR * This,\n    /* [in] */ REFIID riid,\n    /* [in] */ BSTR bstrKey,\n    /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObj);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IPersistMemory_Load_Proxy( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ LPVOID pMem,\n    /* [in] */ ULONG cbSize);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPersistMemory_Load_Stub( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ BYTE __RPC_FAR *pMem,\n    /* [in] */ ULONG cbSize);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IPersistMemory_Save_Proxy( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ LPVOID pMem,\n    /* [in] */ BOOL fClearDirty,\n    /* [in] */ ULONG cbSize);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPersistMemory_Save_Stub( \n    IPersistMemory __RPC_FAR * This,\n    /* [size_is][in] */ BYTE __RPC_FAR *pMem,\n    /* [in] */ BOOL fClearDirty,\n    /* [in] */ ULONG cbSize);\n\n/* [local] */ void STDMETHODCALLTYPE IAdviseSinkEx_OnViewStatusChange_Proxy( \n    IAdviseSinkEx __RPC_FAR * This,\n    /* [in] */ DWORD dwViewStatus);\n\n\n/* [async][call_as] */ void STDMETHODCALLTYPE IAdviseSinkEx_OnViewStatusChange_Stub( \n    IAdviseSinkEx __RPC_FAR * This,\n    /* [in] */ DWORD dwViewStatus);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_Next_Proxy( \n    IEnumOleUndoUnits __RPC_FAR * This,\n    /* [in] */ ULONG cElt,\n    /* [length_is][size_is][out] */ IOleUndoUnit __RPC_FAR *__RPC_FAR *rgElt,\n    /* [out] */ ULONG __RPC_FAR *pcEltFetched);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IEnumOleUndoUnits_Next_Stub( \n    IEnumOleUndoUnits __RPC_FAR * This,\n    /* [in] */ ULONG cElt,\n    /* [length_is][size_is][out] */ IOleUndoUnit __RPC_FAR *__RPC_FAR *rgElt,\n    /* [out] */ ULONG __RPC_FAR *pcEltFetched);\n\n/* [local] */ HRESULT STDMETHODCALLTYPE IPropertyBag_Read_Proxy( \n    IPropertyBag __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszPropName,\n    /* [out][in] */ VARIANT __RPC_FAR *pVar,\n    /* [in] */ IErrorLog __RPC_FAR *pErrorLog);\n\n\n/* [call_as] */ HRESULT STDMETHODCALLTYPE IPropertyBag_Read_Stub( \n    IPropertyBag __RPC_FAR * This,\n    /* [in] */ LPCOLESTR pszPropName,\n    /* [out] */ VARIANT __RPC_FAR *pVar,\n    /* [in] */ IErrorLog __RPC_FAR *pErrorLog,\n    /* [in] */ DWORD varType,\n    /* [in] */ IUnknown __RPC_FAR *pUnkObj);\n\n\n\n/* end of Additional Prototypes */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/ODATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ODATA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ODATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 16, 1994                                                 *\n *                                                                                             *\n *                  Last Update : August 14, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OverlayTypeClass::As_Reference -- Fetch a reference to the overlay type specified.        *\n *   OverlayTypeClass::Coord_Fixup -- Adjust the coord to be legal for assignment.             *\n *   OverlayTypeClass::Create_And_Place -- Creates and places a overlay object on the map.     *\n *   OverlayTypeClass::Create_One_Of -- Creates an object of this overlay type.                *\n *   OverlayTypeClass::Display -- Displays a generic representation of overlay.                *\n *   OverlayTypeClass::Draw_It -- Draws the overlay image at location specified.               *\n *   OverlayTypeClass::From_Name -- Determine overlay from ASCII name.                         *\n *   OverlayTypeClass::Init -- Initialize the overlay graphic data per theater.                *\n *   OverlayTypeClass::Init_Heap -- Initialize the overlay type class heap.                    *\n *   OverlayTypeClass::Occupy_List -- Determines occupation list.                              *\n *   OverlayTypeClass::One_Time -- Loads all the necessary general overlay shape data.         *\n *   OverlayTypeClass::OverlayTypeClass -- Constructor for overlay type objects.               *\n *   OverlayTypeClass::Prep_For_Add -- Prepares to add overlay to scenario.                    *\n *   OverlayTypeClass::Radar_Icon -- Gets a pointer to the radar icons                         *\n *   OverlayTypeClass::operator delete -- Returns an overlay type object back to the pool.     *\n *   OverlayTypeClass::operator new -- Allocate an overlay type class object from pool.        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\n\nstatic OverlayTypeClass const Sandbag(\n\tOVERLAY_SANDBAG_WALL,\t// Overlay type number.\n\t\"SBAG\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_SANDBAG_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t20,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Cyclone(\n\tOVERLAY_CYCLONE_WALL,\t// Overlay type number.\n\t\"CYCL\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CYCLONE_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t10,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Brick(\n\tOVERLAY_BRICK_WALL,\t\t// Overlay type number.\n\t\"BRIK\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_BRICK_WALL,\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t3,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t70,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\ttrue,\t\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Barbwire(\n\tOVERLAY_BARBWIRE_WALL,\t// Overlay type number.\n\t\"BARB\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_BARBWIRE_WALL,\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Wood(\n\tOVERLAY_WOOD_WALL,\t\t// Overlay type number.\n\t\"WOOD\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_WOOD_WALL,\t\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t1,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\ttrue,\t\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Fence(\n\tOVERLAY_FENCE,\t// Overlay type number.\n\t\"FENC\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_FENCE,\t\t\t\t\t// Full name of overlay.\n\tLAND_WALL,\t\t\t\t\t// What kind of ground is it?\n\t2,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t10,\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\ttrue,\t\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\ttrue,\t\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\n\nstatic OverlayTypeClass const Gold1(\n\tOVERLAY_GOLD1,\t\t\t\t// Overlay type number.\n\t\"GOLD01\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold2(\n\tOVERLAY_GOLD2,\t\t\t\t// Overlay type number.\n\t\"GOLD02\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold3(\n\tOVERLAY_GOLD3,\t\t\t\t// Overlay type number.\n\t\"GOLD03\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gold4(\n\tOVERLAY_GOLD4,\t\t\t\t// Overlay type number.\n\t\"GOLD04\",\t\t\t\t\t// INI name of overlay.\n\tTXT_GOLD,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\n\nstatic OverlayTypeClass const Gems1(\n\tOVERLAY_GEMS1,\t\t\t\t// Overlay type number.\n\t\"GEM01\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems2(\n\tOVERLAY_GEMS2,\t\t\t\t// Overlay type number.\n\t\"GEM02\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems3(\n\tOVERLAY_GEMS3,\t\t\t\t// Overlay type number.\n\t\"GEM03\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const Gems4(\n\tOVERLAY_GEMS4,\t\t\t\t// Overlay type number.\n\t\"GEM04\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_GEMS,\t\t\t\t\t// Full name of overlay.\n\tLAND_TIBERIUM,\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\ttrue,\t\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V12(\n\tOVERLAY_V12,\t\t\t\t// Overlay type number.\n\t\"V12\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV12,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V13(\n\tOVERLAY_V13,\t\t\t\t// Overlay type number.\n\t\"V13\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV13,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V14(\n\tOVERLAY_V14,\t\t\t\t// Overlay type number.\n\t\"V14\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV14,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V15(\n\tOVERLAY_V15,\t\t\t\t// Overlay type number.\n\t\"V15\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV15,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V16(\n\tOVERLAY_V16,\t\t\t\t// Overlay type number.\n\t\"V16\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV16,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V17(\n\tOVERLAY_V17,\t\t\t\t// Overlay type number.\n\t\"V17\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV17,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const V18(\n\tOVERLAY_V18,\t\t\t\t// Overlay type number.\n\t\"V18\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_CIV18,\t\t\t\t\t// Full name of overlay.\n\tLAND_ROCK,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\ttrue,\t\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\ttrue,\t\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const FlagSpot(\n\tOVERLAY_FLAG_SPOT,\t\t// Overlay type number.\n\t\"FPLS\",\t\t\t\t\t\t// INI name of overlay.\n\tTXT_FLAG_SPOT,\t\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\ttrue,\t\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\tfalse\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const WoodCrate(\n\tOVERLAY_WOOD_CRATE,\t\t// Overlay type number.\n\t\"WCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_WOOD_CRATE,\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const WaterCrate(\n\tOVERLAY_WATER_CRATE,\t\t// Overlay type number.\n\t\"WWCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_WATER_CRATE,\t\t\t// Full name of overlay.\n\tLAND_WATER,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\nstatic OverlayTypeClass const SteelCrate(\n\tOVERLAY_STEEL_CRATE,\t\t// Overlay type number.\n\t\"SCRATE\",\t\t\t\t\t// INI name of overlay.\n\tTXT_STEEL_CRATE,\t\t\t// Full name of overlay.\n\tLAND_CLEAR,\t\t\t\t\t// What kind of ground is it?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage levels?\n\t0,\t\t\t\t\t\t\t\t// If this is a wall, how many damage points can it take per level?\n\tfalse,\t\t\t\t\t\t// Visible on the radar map?\n\tfalse,\t\t\t\t\t\t// Is it a wooden overlay (affected by fire)?\n\tfalse,\t\t\t\t\t\t// Targetable as a destroyable overlay?\n\tfalse,\t\t\t\t\t\t// Crushable by tracked vehicle?\n\tfalse,\t\t\t\t\t\t// Is this harvestable Tiberium?\n\tfalse,\t\t\t\t\t\t// Stops low level bullets in flight?\n\tfalse,\t\t\t\t\t\t// Theater specific art?\n\tfalse,\t\t\t\t\t\t// Is this a wall type?\n\ttrue\t\t\t\t\t\t\t// Is this a crate?\n);\n\n\n/***********************************************************************************************\n * OverlayTypeClass::OverlayTypeClass -- Constructor for overlay type objects.                 *\n *                                                                                             *\n *    This is the constructor for the overlay types.                                           *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayTypeClass::OverlayTypeClass(\n\tOverlayType iconset,\n\tchar const * ininame,\n\tint fullname,\n\tLandType ground,\n\tint  damagelevels,\n\tint  damagepoints,\n\tbool isradarvisible,\n\tbool iswooden,\n\tbool istarget,\n\tbool iscrushable,\n\tbool istiberium,\n\tbool high,\n\tbool theater,\n\tbool walltype,\n\tbool iscrate) :\n\t\tObjectTypeClass(RTTI_OVERLAYTYPE,\n\t\t\t\t\t\t\tint(iconset),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tistarget,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfullname,\n\t\t\t\t\t\t\tininame),\n\tType(iconset),\n\tLand(ground),\n\tDamageLevels(damagelevels),\n\tDamagePoints(damagepoints),\n\tIsTheater(theater),\n\tIsWall(walltype),\n\tIsHigh(high),\n\tIsTiberium(istiberium),\n\tIsWooden(iswooden),\n\tIsCrate(iscrate),\n\tIsRadarVisible(isradarvisible)\n{\n\tIsCrushable = iscrushable;\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::operator new -- Allocate an overlay type class object from pool.          *\n *                                                                                             *\n *    This will allocate an overlay type class object from the special memory pool that is     *\n *    for that purpose.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlay type class object allocated. If there is     *\n *          insufficient memory to fulfill the request, then NULL is returned.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * OverlayTypeClass::operator new(size_t)\n{\n\treturn(OverlayTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::operator delete -- Returns an overlay type object back to the pool.       *\n *                                                                                             *\n *    This will return a previously allcoated overaly type object to the special memory        *\n *    pool that it was allocated from.                                                         *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the overlay type class object to return the memory pool.    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::operator delete(void * pointer)\n{\n\tOverlayTypes.Free((OverlayTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Init_Heap -- Initialize the overlay type class heap.                      *\n *                                                                                             *\n *    This will initialize the overlay type heap by pre-allocated all overlay types known      *\n *    to exist.                                                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   It should be called once and before the rules.ini file is processed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese overlay type class objects must be allocated in the exact order that they\n\t**\tare specified in the OverlayType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew OverlayTypeClass(Sandbag);\t\t//\tOVERLAY_SANDBAG_WALL\n\tnew OverlayTypeClass(Cyclone);\t\t//\tOVERLAY_CYCLONE_WALL\n\tnew OverlayTypeClass(Brick);\t\t\t//\tOVERLAY_BRICK_WALL\n\tnew OverlayTypeClass(Barbwire);\t\t//\tOVERLAY_BARBWIRE_WALL\n\tnew OverlayTypeClass(Wood);\t\t\t//\tOVERLAY_WOOD_WALL\n\tnew OverlayTypeClass(Gold1);\t\t\t// OVERLAY_GOLD1\n\tnew OverlayTypeClass(Gold2);\t\t\t// OVERLAY_GOLD2\n\tnew OverlayTypeClass(Gold3);\t\t\t// OVERLAY_GOLD3\n\tnew OverlayTypeClass(Gold4);\t\t\t// OVERLAY_GOLD4\n\tnew OverlayTypeClass(Gems1);\t\t\t// OVERLAY_GEMS1\n\tnew OverlayTypeClass(Gems2);\t\t\t// OVERLAY_GEMS2\n\tnew OverlayTypeClass(Gems3);\t\t\t// OVERLAY_GEMS3\n\tnew OverlayTypeClass(Gems4);\t\t\t// OVERLAY_GEMS4\n\tnew OverlayTypeClass(V12);\t\t\t\t//\tOVERLAY_V12\n\tnew OverlayTypeClass(V13);\t\t\t\t//\tOVERLAY_V13\n\tnew OverlayTypeClass(V14);\t\t\t\t//\tOVERLAY_V14\n\tnew OverlayTypeClass(V15);\t\t\t\t//\tOVERLAY_V15\n\tnew OverlayTypeClass(V16);\t\t\t\t//\tOVERLAY_V16\n\tnew OverlayTypeClass(V17);\t\t\t\t//\tOVERLAY_V17\n\tnew OverlayTypeClass(V18);\t\t\t\t//\tOVERLAY_V18\n\tnew OverlayTypeClass(FlagSpot);\t\t//\tOVERLAY_FLAG_SPOT\n\tnew OverlayTypeClass(WoodCrate);\t\t// OVERLAY_WOOD_CRATE\n\tnew OverlayTypeClass(SteelCrate);\t// OVERLAY_STEEL_CRATE\n\tnew OverlayTypeClass(Fence);\t\t\t// OVERLAY_FENCE\n\tnew OverlayTypeClass(WaterCrate);\t// OVERLAY_WATER_CRATE\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::One_Time -- Loads all the necessary general overlay shape data.           *\n *                                                                                             *\n *    This routine should be called once when the game first starts. It will establish         *\n *    pointers to the graphic data of the overlay objects.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::From_Name -- Determine overlay from ASCII name.                           *\n *                                                                                             *\n *    This routine is used to determine the overlay number given only                          *\n *    an ASCII representation. The scenario loader uses this routine                           *\n *    to construct the map from the INI control file.                                          *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the ASCII name of the overlay.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the overlay number. If the name had no match,                         *\n *          then returns with OVERLAY_NONE.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayType OverlayTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(OVERLAY_NONE);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Occupy_List -- Determines occupation list.                                *\n *                                                                                             *\n *    This routine is used to examine the overlay map and build an                             *\n *    occupation list. This list is used to render a overlay cursor as                         *\n *    well as placement of icon numbers.                                                       *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the overlay occupation list.                             *\n *                                                                                             *\n * WARNINGS:   The return pointer is valid only until the next time that                       *\n *             this routine is called.                                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * OverlayTypeClass::Occupy_List(bool) const\n{\n\tstatic short _simple[] = {0, REFRESH_EOL};\n\n\treturn(_simple);\n}\n\n\n/***************************************************************************\n * OverlayTypeClass::Radar_Icon -- Gets a pointer to the radar icons       *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 PWG : Created.                                             *\n *=========================================================================*/\nunsigned char * OverlayTypeClass::Radar_Icon(int data) const\n{\n\tunsigned char * icon = (unsigned char *)Get_Radar_Data();\t\t// Get pointer to radar icons\n\tif (icon != NULL) icon += (data * 9) + 2;\t\t\t// move icon ptr to correct icon\n\treturn(icon);\t\t\t\t\t\t\t\t\t\t\t// Return the correct icon\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * OverlayTypeClass::Display -- Displays a generic representation of overlay.                  *\n *                                                                                             *\n *    This routine is used to display a generic view of the overlay                            *\n *    object. This is necessary for selection in the scenario editor.                          *\n *                                                                                             *\n * INPUT:   x,y   -- The coordinates to center the display about.                              *\n *                                                                                             *\n *          window-- The window to base the coordinates upon.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/23/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tif (Get_Image_Data() != NULL) {\n\t\tint frame = 0;\n\n\t\tif (IsTiberium) {\n\t\t\tframe = 7;\n\t\t}\n\t\tif (Type == OVERLAY_GEMS1 || Type == OVERLAY_GEMS2 || Type == OVERLAY_GEMS3 || Type == OVERLAY_GEMS4) {\n\t\t\tframe = 2;\n\t\t}\n\n\t\tIsTheaterShape = IsTheater;\n\t\tCC_Draw_Shape(Get_Image_Data(), frame, x, y, window, SHAPE_NORMAL|SHAPE_CENTER|SHAPE_WIN_REL);\n\t\tIsTheaterShape = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Prep_For_Add -- Prepares to add overlay to scenario.                      *\n *                                                                                             *\n *    This routine prepares a list of overlay objects so that the                              *\n *    scenario editor can use this list to display a dialog box. The                           *\n *    selection of a overlay object will allow its placement upon the                          *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1994 JLB : Created                                                                  *\n *=============================================================================================*/\nvoid OverlayTypeClass::Prep_For_Add(void)\n{\n\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\tOverlayTypeClass const & overlay = As_Reference(index);\n\t\tif (overlay.Get_Image_Data() != NULL &&\n\t\t\t!overlay.IsWall &&\n\t\t\t(!overlay.IsTiberium || index == OVERLAY_GOLD1 || index == OVERLAY_GEMS1)) {\n\n\t\t\tMap.Add_To_List(&overlay);\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Create_And_Place -- Creates and places a overlay object on the map.       *\n *                                                                                             *\n *    This support routine is used by the scenario editor to add a overlay object to the map   *\n *    and to the game.                                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the overlay object.                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay object placed successfully?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool OverlayTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new OverlayClass(Type, cell)) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Create_One_Of -- Creates an object of this overlay type.                  *\n *                                                                                             *\n *    This routine will create an object of this type. For certain overlay objects, such       *\n *    as walls, it is actually created as a building. The \"building\" wall is converted into    *\n *    a overlay at the moment of placing down on the map.                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the appropriate object for this overlay type.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * OverlayTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new OverlayClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Draw_It -- Draws the overlay image at location specified.                 *\n *                                                                                             *\n *    This routine will draw the overlay shape at the coordinates specified. It is presumed    *\n *    that all the underlying layers have already been rendered by the time this routine is    *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   x, y  -- Coordinate (upper left) of cell where overlay image is to be drawn.       *\n *                                                                                             *\n *          data  -- Cell specific data that controls the imagery of the overlay.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Draw_It(int x, int y, int data) const\n{\n\tIsTheaterShape = IsTheater;\n\tCC_Draw_Shape(Get_Image_Data(), data, Map.TacPixelX+x+(CELL_PIXEL_W>>1), Map.TacPixelY+y+(CELL_PIXEL_H>>1), WINDOW_MAIN, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, Map.UnitShadow);\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Init -- Initialize the overlay graphic data per theater.                  *\n *                                                                                             *\n *    This routine will update the overlay graphic data according to the theater specified.    *\n *    It is typically called when the scenario is first loaded (theater change).               *\n *                                                                                             *\n * INPUT:   theater  -- The theater to load specific data for.                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\n\t\tfor (OverlayType index = OVERLAY_FIRST; index < OVERLAY_COUNT; index++) {\n\t\t\tOverlayTypeClass & overlay = As_Reference(index);\n\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed iconset name.\n\n\t\t\tif (overlay.IsTheater) {\n\t\t\t\t_makepath(fullname, NULL, NULL, overlay.IniName, Theaters[theater].Suffix);\n\t\t\t} else {\n\t\t\t\t_makepath(fullname, NULL, NULL, overlay.IniName, \".SHP\");\n\t\t\t}\n\t\t\toverlay.ImageData = MFCD::Retrieve(fullname);\n\n\t\t\tIsTheaterShape = overlay.IsTheater;\t\t//Tell Build_Frame if this is a theater specific shape\n\t\t\tif (overlay.RadarIcon != NULL) delete[] (char *)overlay.RadarIcon;\n\t\t\toverlay.RadarIcon = Get_Radar_Icon(overlay.Get_Image_Data(), 0, -1, 3);\n\t\t\tIsTheaterShape = false;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::As_Reference -- Fetch a reference to the overlay type specified.          *\n *                                                                                             *\n *    Use this routine to get a reference that corresponds to the overlay type.                *\n *                                                                                             *\n * INPUT:   type  -- The overlay type to fetch a reference to.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the overlay type specified.                            *\n *                                                                                             *\n * WARNINGS:   Be sure that the overlay type specified is legal. Illegal type value will       *\n *             result in undefined behavior.                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayTypeClass & OverlayTypeClass::As_Reference(OverlayType type)\n{\n\treturn(*OverlayTypes.Ptr(type));\n}\n\n\n/***********************************************************************************************\n * OverlayTypeClass::Coord_Fixup -- Adjust the coord to be legal for assignment.               *\n *                                                                                             *\n *    This will adjust the coordinate specified so that it will be of legal format to          *\n *    assign as the coordinate of an overlay. Overlays are always relative to the upper left   *\n *    corner of the cell, so this routine drops the fractional cell components.                *\n *                                                                                             *\n * INPUT:   coord -- The coordinate to fixup to be legal for assignment.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a properly fixed up coordinate.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE OverlayTypeClass::Coord_Fixup(COORDINATE coord) const\n{\n\treturn Coord_Whole(coord);\n}\n"
  },
  {
    "path": "REDALERT/OPTIONS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OPTIONS.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OptionsClass::Adjust_Palette -- Adjusts the palette according to the settings specified.  *\n *   OptionsClass::Fixup_Palette -- Adjusts the real palette to match the palette sliders.     *\n *   OptionsClass::Get_Brightness -- Fetches the current brightness setting.                   *\n *   OptionsClass::Get_Contrast -- Gets the current contrast setting.                          *\n *   OptionsClass::Get_Game_Speed -- Fetches the current game speed setting.                   *\n *   OptionsClass::Get_Saturation -- Fetches the current color setting.                        *\n *   OptionsClass::Get_Scroll_Rate -- Fetches the current scroll rate setting.                 *\n *   OptionsClass::Get_Tint -- Fetches the current tint setting.                               *\n *   OptionsClass::Load_Settings -- reads options settings from the INI file                   *\n *   OptionsClass::Normalize_Delay -- Normalizes delay factor to keep rate constant.           *\n *   OptionsClass::Normalize_Volume -- Convert to a real volume value.                         *\n *   OptionsClass::One_Time -- This performs any one time initialization for the options class.*\n *   OptionsClass::OptionsClass -- The default constructor for the options class.              *\n *   OptionsClass::Process -- Handles all the options graphic interface.                       *\n *   OptionsClass::Save_Settings -- writes options settings to the INI file                    *\n *   OptionsClass::Set -- Sets options based on current settings                               *\n *   OptionsClass::Set_Brightness -- Sets the brightness level to that specified.              *\n *   OptionsClass::Set_Contrast -- Sets the contrast to the value specified.                   *\n *   OptionsClass::Set_Game_Speed -- Sets the game speed as specified.                         *\n *   OptionsClass::Set_Repeat -- Controls the score repeat option.                             *\n *   OptionsClass::Set_Saturation -- Sets the color to the value specified.                    *\n *   OptionsClass::Set_Score_Volume -- Sets the global score volume to that specified.         *\n *   OptionsClass::Set_Scroll_Rate -- Sets the scroll rate as specified.                       *\n *   OptionsClass::Set_Shuffle -- Controls the play shuffle setting.                           *\n *   OptionsClass::Set_Sound_Volume -- Sets the sound effects volume level.                    *\n *   OptionsClass::Set_Tint -- Sets the tint setting.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"options.h\"\n\n\n#ifdef WIN32\nchar const * const OptionsClass::HotkeyName = \"WinHotkeys\";\n#else\nchar const * const OptionsClass::HotkeyName = \"DOSHotkeys\";\n#endif\n\n\n/***********************************************************************************************\n * OptionsClass::OptionsClass -- The default constructor for the options class.                *\n *                                                                                             *\n *    This is the constructor for the options class. It handles setting up all the globals     *\n *    necessary for the options. This includes setting them to their default state.            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOptionsClass::OptionsClass(void) :\n\tGameSpeed(3),\n\tScrollRate(3),\n#ifdef WIN32\n\tVolume(\".40\"),\t\t\t// was .295\n\tScoreVolume(\".25\"),\n#ifdef FIXIT_VERSION_3\n\tMultiScoreVolume(\"0\"),\n#endif\n#else\n\tVolume(\".8\"),\n\tScoreVolume(\".6\"),\n#endif\n\tBrightness(fixed::_1_2),\n\tTint(fixed::_1_2),\n\tSaturation(fixed::_1_2),\n\tContrast(fixed::_1_2),\n\tAutoScroll(true),\n\tIsScoreRepeat(false),\n\tIsScoreShuffle(false),\n\tIsPaletteScroll(true),\n\n\tKeyForceMove1(KN_LALT),\n\tKeyForceMove2(KN_RALT),\n\tKeyForceAttack1(KN_LCTRL),\n\tKeyForceAttack2(KN_RCTRL),\n\tKeySelect1(KN_LSHIFT),\n\tKeySelect2(KN_RSHIFT),\n\tKeyScatter(KN_X),\n\tKeyStop(KN_S),\n\tKeyGuard(KN_G),\n\tKeyNext(KN_N),\n\tKeyPrevious(KN_B),\n\tKeyFormation(KN_F),\n\tKeyHome1(KN_HOME),\n\tKeyHome2(KN_E_HOME),\n\tKeyBase(KN_H),\n\tKeyResign(KN_R),\n\tKeyAlliance(KN_A),\n\tKeyBookmark1(KN_F9),\n\tKeyBookmark2(KN_F10),\n\tKeyBookmark3(KN_F11),\n\tKeyBookmark4(KN_F12),\n\tKeySelectView(KN_E),\n\tKeyRepair(KN_T),\n\tKeyRepairOn(KN_NONE),\n\tKeyRepairOff(KN_NONE),\n\tKeySell(KN_Y),\n\tKeySellOn(KN_NONE),\n\tKeySellOff(KN_NONE),\n\tKeyMap(KN_U),\n\tKeySidebarUp(KN_UP),\n\tKeySidebarDown(KN_DOWN),\n\tKeyOption1(KN_ESC),\n\tKeyOption2(KN_SPACE),\n\tKeyScrollLeft(KN_NONE),\n\tKeyScrollRight(KN_NONE),\n\tKeyScrollUp(KN_NONE),\n\tKeyScrollDown(KN_NONE),\n\tKeyQueueMove1(KN_Q),\n\tKeyQueueMove2(KN_Q),\n\tKeyTeam1(KN_1),\n\tKeyTeam2(KN_2),\n\tKeyTeam3(KN_3),\n\tKeyTeam4(KN_4),\n\tKeyTeam5(KN_5),\n\tKeyTeam6(KN_6),\n\tKeyTeam7(KN_7),\n\tKeyTeam8(KN_8),\n\tKeyTeam9(KN_9),\n\tKeyTeam10(KN_0)\n{\n}\n\n\n/***********************************************************************************************\n * OptionsClass::One_Time -- This performs any one time initialization for the options class.  *\n *                                                                                             *\n *    This routine should be called only once and it will perform any initializations for the  *\n *    options class that is needed. This may include things like file loading and memory       *\n *    allocation.                                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once.                                                    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::One_Time(void)\n{\n\tSet_Score_Vol(ScoreVolume * 256);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Process -- Handles all the options graphic interface.                         *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Process(void)\n{\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Shuffle -- Controls the play shuffle setting.                             *\n *                                                                                             *\n *    This routine will control the score shuffle flag. The setting to use is provided as      *\n *    a parameter. When shuffling is on, the score play order is scrambled.                    *\n *                                                                                             *\n * INPUT:   on -- Should the shuffle option be activated?                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Shuffle(int on)\n{\n\tIsScoreShuffle = on;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Repeat -- Controls the score repeat option.                               *\n *                                                                                             *\n *    This routine is used to control whether scores repeat or not. The setting to use for     *\n *    the repeat flag is provided as a parameter.                                              *\n *                                                                                             *\n * INPUT:   on -- Should the scores repeat?                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Repeat(int on)\n{\n\tIsScoreRepeat = on;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Score_Volume -- Sets the global score volume to that specified.           *\n *                                                                                             *\n *    This routine will set the global score volume to the value specified. The value ranges   *\n *    from zero to 255.                                                                        *\n *                                                                                             *\n * INPUT:   volume   -- The new volume setting to use for scores.                              *\n *                                                                                             *\n *          feedback -- Should a feedback sound effect be generated?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Score_Volume(fixed volume, bool feedback)\n{\n\tScoreVolume = Sub_Saturate(volume, 1);\n\tSet_Score_Vol(ScoreVolume * 256);\n\tif (feedback && !Theme.Still_Playing()) {\n\t\tSound_Effect(VOC_BEEP, ScoreVolume);\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Sound_Volume -- Sets the sound effects volume level.                      *\n *                                                                                             *\n *    This routine will set the sound effect volume level as indicated. It can generate a      *\n *    sound effect for feedback purposes if desired. The volume setting can range from zero    *\n *    to 255. The value of 255 is the loudest.                                                 *\n *                                                                                             *\n * INPUT:   volume   -- The volume setting to use for the new value. 0 to 255.                 *\n *                                                                                             *\n *          feedback -- Should a feedback sound effect be generated?                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Sound_Volume(fixed volume, bool feedback)\n{\n\tVolume = Sub_Saturate(volume, 1);\n\tif (feedback) {\n\t\tSound_Effect(VOC_BEEP);\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Brightness -- Sets the brightness level to that specified.                *\n *                                                                                             *\n *    This routine will set the current brightness level to the value specified. This value    *\n *    can range from zero to 255, with 128 being the normal (default) brightness level.        *\n *                                                                                             *\n * INPUT:   brightness  -- The brightness level to set as current.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Brightness(fixed brightness)\n{\n\tBrightness = fixed::_1_4 + (fixed::_1_2 * brightness);\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Brightness -- Fetches the current brightness setting.                     *\n *                                                                                             *\n *    This routine will fetch the current setting for the brightness level. The value ranges   *\n *    from zero to 255, with 128 being the normal (default) value.                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current brightness setting.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Brightness(void) const\n{\n\treturn((Brightness - fixed::_1_4) / fixed::_1_2);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Saturation -- Sets the color to the value specified.                      *\n *                                                                                             *\n *    This routine will set the color value to that specified. The value specified can range   *\n *    from zero to 255. The value of 128 is the normal default color setting.                  *\n *                                                                                             *\n * INPUT:   color -- The new color value to set as current.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Saturation(fixed color)\n{\n\tSaturation = color;\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Saturation -- Fetches the current color setting.                          *\n *                                                                                             *\n *    This routine will fetch the current color setting. This value ranges from zero to        *\n *    255.                                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current color setting. The value of 128 is the normal (default)   *\n *          color setting.                                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Saturation(void) const\n{\n\treturn(Saturation);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Contrast -- Sets the contrast to the value specified.                     *\n *                                                                                             *\n *    This routine will set the contrast to the setting specified. This setting ranges from    *\n *    zero to 255. The value o 128 is the normal default value.                                *\n *                                                                                             *\n * INPUT:   contrast -- The contrast setting to make as the current setting.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Contrast(fixed contrast)\n{\n\tContrast = fixed::_1_4 + (fixed::_1_2 * contrast);\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Contrast -- Gets the current contrast setting.                            *\n *                                                                                             *\n *    This routine will get the current contrast setting. The value returned is in the range   *\n *    of zero to 255.                                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the current contrast setting. A setting of 128 is the normal default value.*\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Contrast(void) const\n{\n\treturn((Contrast - fixed::_1_4) / fixed::_1_2);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set_Tint -- Sets the tint setting.                                            *\n *                                                                                             *\n *    This routine will change the current tint setting according to the value specified.      *\n *                                                                                             *\n * INPUT:   tint  -- The desired tint setting. This value ranges from zero to 255.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The value of 128 is the default (normal) tint setting.                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set_Tint(fixed tint)\n{\n\tTint = tint;\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tInGamePalette.Set();\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Get_Tint -- Fetches the current tint setting.                                 *\n *                                                                                             *\n *    This fetches the current tint setting. The value is returned as a number between         *\n *    zero and 255. This has been adjusted for the valid range allowed.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current tint setting. Normal tint setting is 128.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nfixed OptionsClass::Get_Tint(void) const\n{\n\treturn(Tint);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Adjust_Palette -- Adjusts the palette according to the settings specified.    *\n *                                                                                             *\n *    This routine is used to adjust the palette according to the settings provided. It is     *\n *    used by the options class to monkey with the palette.                                    *\n *                                                                                             *\n * INPUT:   oldpal      -- Pointer to the original (unmodified) palette.                       *\n *                                                                                             *\n *          newpal      -- The new palette to create according to the settings provided.       *\n *                                                                                             *\n *          brightness  -- The brightness level (0..255).                                      *\n *                                                                                             *\n *          color       -- The color level (0..255).                                           *\n *                                                                                             *\n *          tint        -- The tint (hue) level (0..255).                                      *\n *                                                                                             *\n *          contrast    -- The contrast level (0..255).                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/21/1994 JLB : Created.                                                                 *\n *   12/02/1995 JLB : Uses palette class objects.                                              *\n *=============================================================================================*/\nvoid OptionsClass::Adjust_Palette(PaletteClass const & oldpal, PaletteClass & newpal, fixed brightness, fixed color, fixed tint, fixed contrast) const\n{\n\t//if (!oldpal || !newpal) return;\tCan't be NULL... ST - 5/9/2019\n\n\t/*\n\t**\tAdjust for palette.\n\t*/\n\tfor (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {\n\t\tif (index == CC_MOUSE_COLOR) {\n\t\t\tnewpal[index] = oldpal[index];\n\t\t} else {\n\t\t\t/*\n\t\t\t**\tConvert the working palette entry into an HSV format for\n\t\t\t**\tmanipulation.\n\t\t\t*/\n\t\t\tHSVClass hsv = oldpal[index];\n\n\t\t\t/*\n\t\t\t**\tAdjust contrast by moving the value toward the center according to the\n\t\t\t**\tpercentage indicated.\n\t\t\t*/\n\t\t\tint temp;\n\t\t\ttemp = (hsv.Value_Component() * (brightness * 256)) / 0x80;\t\t// Brightness\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint v = temp;\n\t\t\ttemp = (((((int)v) - 0x80) * (contrast * 256)) / 0x80) + 0x80;\t// Contrast\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tv = temp;\n\t\t\ttemp = (hsv.Saturation_Component() * (color * 256)) / 0x80;\t\t// Color\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint s = temp;\n\t\t\ttemp = (hsv.Hue_Component() * (tint * 256)) / 0x80;\t\t\t\t\t// Tint\n\t\t\ttemp = Bound(temp, 0, 0xFF);\n\t\t\tint h = temp;\n\n\t\t\t/*\n\t\t\t**\tReplace the working palette entry according to the newly calculated\n\t\t\t**\thue, saturation, and value.\n\t\t\t*/\n\t\t\tnewpal[index] = HSVClass(h, s, v);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Load_Settings -- reads options settings from the INI file                     *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   07/03/1996 JLB : Reworked to use new INI handler.                                         *\n *   07/30/1996 JLB : Handles hotkeys.                                                         *\n *=============================================================================================*/\nvoid OptionsClass::Load_Settings(void)\n{\n\t/*\n\t**\tCreate filename and read the file.\n\t*/\n\tCCFileClass file(CONFIG_FILE_NAME);\n\tINIClass ini;\n\tini.Load(file);\n\n\t/*\n\t**\tRead in the Options values\n\t*/\n\tstatic char const * const OPTIONS = \"Options\";\n\tGameSpeed = ini.Get_Int(OPTIONS, \"GameSpeed\", GameSpeed);\n\tScrollRate = ini.Get_Int(OPTIONS, \"ScrollRate\", ScrollRate);\n\tSet_Brightness(ini.Get_Fixed(OPTIONS, \"Brightness\", Brightness));\n\tSet_Sound_Volume(ini.Get_Fixed(OPTIONS, \"Volume\", Volume), false);\n\tSet_Score_Volume(ini.Get_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume), false);\n#ifdef FIXIT_VERSION_3\n\tMultiScoreVolume = ini.Get_Fixed(OPTIONS, \"MultiplayerScoreVolume\", MultiScoreVolume);\n#endif\n\tSet_Contrast(ini.Get_Fixed(OPTIONS, \"Contrast\", Contrast));\n\tSet_Saturation(ini.Get_Fixed(OPTIONS, \"Color\", Saturation));\n\tSet_Tint(ini.Get_Fixed(OPTIONS, \"Tint\", Tint));\n\tAutoScroll = ini.Get_Bool(OPTIONS, \"AutoScroll\", AutoScroll);\n\tSet_Repeat(ini.Get_Bool(OPTIONS, \"IsScoreRepeat\", IsScoreRepeat));\n\tSet_Shuffle(ini.Get_Bool(OPTIONS, \"IsScoreShuffle\", IsScoreShuffle));\n\tSlowPalette = ini.Get_Bool(OPTIONS, \"SlowPalette\", SlowPalette);\n\tIsPaletteScroll = ini.Get_Bool(OPTIONS, \"PaletteScroll\", IsPaletteScroll);\n\n\tKeyForceMove1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceMove1\", KeyForceMove1);\n\tKeyForceMove2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceMove2\", KeyForceMove2);\n\tKeyForceAttack1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceAttack1\", KeyForceAttack1);\n\tKeyForceAttack2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyForceAttack2\", KeyForceAttack2);\n\tKeySelect1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelect1\", KeySelect1);\n\tKeySelect2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelect2\", KeySelect2);\n\tKeyScatter = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScatter\", KeyScatter);\n\tKeyStop = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyStop\", KeyStop);\n\tKeyGuard = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyGuard\", KeyGuard);\n\tKeyNext = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyNext\", KeyNext);\n\tKeyPrevious = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyPrevious\", KeyPrevious);\n\tKeyFormation = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyFormation\", KeyFormation);\n\tKeyHome1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyHome1\", KeyHome1);\n\tKeyHome2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyHome2\", KeyHome2);\n\tKeyBase = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBase\", KeyBase);\n\tKeyResign = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyResign\", KeyResign);\n\tKeyAlliance = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyAlliance\", KeyAlliance);\n\tKeyBookmark1 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark1\", KeyBookmark1);\n\tKeyBookmark2 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark2\", KeyBookmark2);\n\tKeyBookmark3 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark3\", KeyBookmark3);\n\tKeyBookmark4 = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyBookmark4\", KeyBookmark4);\n\tKeySelectView =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySelectView\", KeySelectView);\n\tKeyRepair =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairToggle\", KeyRepair);\n\tKeyRepairOn = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairOn\", KeyRepairOn);\n\tKeyRepairOff = (KeyNumType)ini.Get_Int(HotkeyName, \"KeyRepairOff\", KeyRepairOff);\n\tKeySell =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellToggle\", KeySell);\n\tKeySellOn = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellOn\", KeySellOn);\n\tKeySellOff = (KeyNumType)ini.Get_Int(HotkeyName, \"KeySellOff\", KeySellOff);\n\tKeyMap =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyMapToggle\", KeyMap);\n\tKeySidebarUp =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySidebarUp\", KeySidebarUp);\n\tKeySidebarDown =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeySidebarDown\", KeySidebarDown);\n\tKeyOption1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyOption1\", KeyOption1);\n\tKeyOption2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyOption2\", KeyOption2);\n\tKeyScrollLeft =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollLeft\", KeyScrollLeft);\n\tKeyScrollRight =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollRight\", KeyScrollRight);\n\tKeyScrollUp =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollUp\", KeyScrollUp);\n\tKeyScrollDown =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyScrollDown\", KeyScrollDown);\n\tKeyQueueMove1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyQueueMove1\", KeyQueueMove1);\n\tKeyQueueMove2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyQueueMove2\", KeyQueueMove2);\n\tKeyTeam1 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam1\", KeyTeam1);\n\tKeyTeam2 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam2\", KeyTeam2);\n\tKeyTeam3 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam3\", KeyTeam3);\n\tKeyTeam4 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam4\", KeyTeam4);\n\tKeyTeam5 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam5\", KeyTeam5);\n\tKeyTeam6 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam6\", KeyTeam6);\n\tKeyTeam7 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam7\", KeyTeam7);\n\tKeyTeam8 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam8\", KeyTeam8);\n\tKeyTeam9 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam9\", KeyTeam9);\n\tKeyTeam10 =  (KeyNumType)ini.Get_Int(HotkeyName, \"KeyTeam10\", KeyTeam10);\n\n\n#ifdef WIN32\n\tKeyForceMove1 = (KeyNumType)(KeyForceMove1 & ~WWKEY_VK_BIT);\n\tKeyForceMove2 = (KeyNumType)(KeyForceMove2 & ~WWKEY_VK_BIT);\n\tKeyForceAttack1 = (KeyNumType)(KeyForceAttack1 & ~WWKEY_VK_BIT);\n\tKeyForceAttack2 = (KeyNumType)(KeyForceAttack2 & ~WWKEY_VK_BIT);\n\tKeySelect1 = (KeyNumType)(KeySelect1 & ~WWKEY_VK_BIT);\n\tKeySelect2 = (KeyNumType)(KeySelect2 & ~WWKEY_VK_BIT);\n\tKeyScatter = (KeyNumType)(KeyScatter & ~WWKEY_VK_BIT);\n\tKeyStop = (KeyNumType)(KeyStop & ~WWKEY_VK_BIT);\n\tKeyGuard = (KeyNumType)(KeyGuard & ~WWKEY_VK_BIT);\n\tKeyNext = (KeyNumType)(KeyNext & ~WWKEY_VK_BIT);\n\tKeyPrevious = (KeyNumType)(KeyPrevious & ~WWKEY_VK_BIT);\n\tKeyFormation = (KeyNumType)(KeyFormation & ~WWKEY_VK_BIT);\n\tKeyHome1 = (KeyNumType)(KeyHome1 & ~WWKEY_VK_BIT);\n\tKeyHome2 = (KeyNumType)(KeyHome2 & ~WWKEY_VK_BIT);\n\tKeyBase = (KeyNumType)(KeyBase & ~WWKEY_VK_BIT);\n\tKeyResign = (KeyNumType)(KeyResign & ~WWKEY_VK_BIT);\n\tKeyAlliance = (KeyNumType)(KeyAlliance & ~WWKEY_VK_BIT);\n\tKeyBookmark1 = (KeyNumType)(KeyBookmark1 & ~WWKEY_VK_BIT);\n\tKeyBookmark2 = (KeyNumType)(KeyBookmark2 & ~WWKEY_VK_BIT);\n\tKeyBookmark3 = (KeyNumType)(KeyBookmark3 & ~WWKEY_VK_BIT);\n\tKeyBookmark4 = (KeyNumType)(KeyBookmark4 & ~WWKEY_VK_BIT);\n\tKeySelectView = (KeyNumType)(KeySelectView & ~WWKEY_VK_BIT);\n\tKeyRepair = (KeyNumType)(KeyRepair & ~WWKEY_VK_BIT);\n\tKeyRepairOn = (KeyNumType)(KeyRepairOn & ~WWKEY_VK_BIT);\n\tKeyRepairOff = (KeyNumType)(KeyRepairOff & ~WWKEY_VK_BIT);\n\tKeySell = (KeyNumType)(KeySell & ~WWKEY_VK_BIT);\n\tKeySellOn = (KeyNumType)(KeySellOn & ~WWKEY_VK_BIT);\n\tKeySellOff = (KeyNumType)(KeySellOff & ~WWKEY_VK_BIT);\n\tKeyMap = (KeyNumType)(KeyMap & ~WWKEY_VK_BIT);\n\tKeySidebarUp = (KeyNumType)(KeySidebarUp & ~WWKEY_VK_BIT);\n\tKeySidebarDown = (KeyNumType)(KeySidebarDown & ~WWKEY_VK_BIT);\n\tKeyOption1 = (KeyNumType)(KeyOption1 & ~WWKEY_VK_BIT);\n\tKeyOption2 = (KeyNumType)(KeyOption2 & ~WWKEY_VK_BIT);\n\tKeyScrollLeft = (KeyNumType)(KeyScrollLeft & ~WWKEY_VK_BIT);\n\tKeyScrollRight = (KeyNumType)(KeyScrollRight & ~WWKEY_VK_BIT);\n\tKeyScrollUp = (KeyNumType)(KeyScrollUp & ~WWKEY_VK_BIT);\n\tKeyScrollDown = (KeyNumType)(KeyScrollDown & ~WWKEY_VK_BIT);\n\tKeyQueueMove1 = (KeyNumType)(KeyQueueMove1 & ~WWKEY_VK_BIT);\n\tKeyQueueMove2 = (KeyNumType)(KeyQueueMove2 & ~WWKEY_VK_BIT);\n\tKeyTeam1 = (KeyNumType)(KeyTeam1 & ~WWKEY_VK_BIT);\n\tKeyTeam2 = (KeyNumType)(KeyTeam2 & ~WWKEY_VK_BIT);\n\tKeyTeam3 = (KeyNumType)(KeyTeam3 & ~WWKEY_VK_BIT);\n\tKeyTeam4 = (KeyNumType)(KeyTeam4 & ~WWKEY_VK_BIT);\n\tKeyTeam5 = (KeyNumType)(KeyTeam5 & ~WWKEY_VK_BIT);\n\tKeyTeam6 = (KeyNumType)(KeyTeam6 & ~WWKEY_VK_BIT);\n\tKeyTeam7 = (KeyNumType)(KeyTeam7 & ~WWKEY_VK_BIT);\n\tKeyTeam8 = (KeyNumType)(KeyTeam8 & ~WWKEY_VK_BIT);\n\tKeyTeam9 = (KeyNumType)(KeyTeam9 & ~WWKEY_VK_BIT);\n\tKeyTeam10 = (KeyNumType)(KeyTeam10 & ~WWKEY_VK_BIT);\n#endif\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Save_Settings -- writes options settings to the INI file                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/14/1995 BR : Created.                                                                  *\n *   07/03/1996 JLB : Revamped and tightened up.                                               *\n *   07/30/1996 JLB : Handles hotkeys.                                                         *\n *=============================================================================================*/\nvoid OptionsClass::Save_Settings (void)\n{\n\tCCFileClass file(CONFIG_FILE_NAME);\n\tINIClass ini;\n\n\t/*\n\t**\tLoad any existing options file because it may contain entries that won't be\n\t**\texplicitly written out by this routine. By preloading the database, these entries\n\t**\twill be carried over.\n\t*/\n\tif (file.Is_Available()) {\n\t\tini.Load(file);\n\t}\n\n\t/*\n\t**\tSave Options settings\n\t*/\n\tstatic char const * const OPTIONS = \"Options\";\n\tini.Put_Int(OPTIONS, \"GameSpeed\", GameSpeed);\n\tini.Put_Int(OPTIONS, \"ScrollRate\", ScrollRate);\n\tini.Put_Fixed(OPTIONS, \"Brightness\", Brightness);\n\tini.Put_Fixed(OPTIONS, \"Volume\", Volume);\n#ifdef FIXIT_VERSION_3\n\tif( Session.Type == GAME_NORMAL )\t\t//\tSave only when non-multiplayer.\n\t\tini.Put_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume);\n#else\n\tini.Put_Fixed(OPTIONS, \"ScoreVolume\", ScoreVolume);\n#endif\n#ifdef FIXIT_VERSION_3\n\tini.Put_Fixed(OPTIONS, \"MultiplayerScoreVolume\", MultiScoreVolume);\n#endif\n\tini.Put_Fixed(OPTIONS, \"Contrast\", Contrast);\n\tini.Put_Fixed(OPTIONS, \"Color\", Saturation);\n\tini.Put_Fixed(OPTIONS, \"Tint\", Tint);\n\tini.Put_Bool(OPTIONS, \"AutoScroll\", AutoScroll);\n\tini.Put_Bool(OPTIONS, \"IsScoreRepeat\", IsScoreRepeat);\n\tini.Put_Bool(OPTIONS, \"IsScoreShuffle\", IsScoreShuffle);\n\tini.Put_Bool(OPTIONS, \"PaletteScroll\", IsPaletteScroll);\n\n\tini.Put_Int(HotkeyName, \"KeyForceMove1\", KeyForceMove1);\n\tini.Put_Int(HotkeyName, \"KeyForceMove2\", KeyForceMove2);\n\tini.Put_Int(HotkeyName, \"KeyForceAttack1\", KeyForceAttack1);\n\tini.Put_Int(HotkeyName, \"KeyForceAttack2\", KeyForceAttack2);\n\tini.Put_Int(HotkeyName, \"KeySelect1\", KeySelect1);\n\tini.Put_Int(HotkeyName, \"KeySelect2\", KeySelect2);\n\tini.Put_Int(HotkeyName, \"KeyScatter\", KeyScatter);\n\tini.Put_Int(HotkeyName, \"KeyStop\", KeyStop);\n\tini.Put_Int(HotkeyName, \"KeyGuard\", KeyGuard);\n\tini.Put_Int(HotkeyName, \"KeyNext\", KeyNext);\n\tini.Put_Int(HotkeyName, \"KeyPrevious\", KeyPrevious);\n\tini.Put_Int(HotkeyName, \"KeyFormation\", KeyFormation);\n\tini.Put_Int(HotkeyName, \"KeyHome1\", KeyHome1);\n\tini.Put_Int(HotkeyName, \"KeyHome2\", KeyHome2);\n\tini.Put_Int(HotkeyName, \"KeyBase\", KeyBase);\n\tini.Put_Int(HotkeyName, \"KeyResign\", KeyResign);\n\tini.Put_Int(HotkeyName, \"KeyAlliance\", KeyAlliance);\n\tini.Put_Int(HotkeyName, \"KeyBookmark1\", KeyBookmark1);\n\tini.Put_Int(HotkeyName, \"KeyBookmark2\", KeyBookmark2);\n\tini.Put_Int(HotkeyName, \"KeyBookmark3\", KeyBookmark3);\n\tini.Put_Int(HotkeyName, \"KeyBookmark4\", KeyBookmark4);\n\tini.Put_Int(HotkeyName, \"KeySelectView\", KeySelectView);\n\tini.Put_Int(HotkeyName, \"KeyRepairToggle\", KeyRepair);\n\tini.Put_Int(HotkeyName, \"KeyRepairOn\", KeyRepairOn);\n\tini.Put_Int(HotkeyName, \"KeyRepairOff\", KeyRepairOff);\n\tini.Put_Int(HotkeyName, \"KeySellToggle\", KeySell);\n\tini.Put_Int(HotkeyName, \"KeySellOn\", KeySellOn);\n\tini.Put_Int(HotkeyName, \"KeySellOff\", KeySellOff);\n\tini.Put_Int(HotkeyName, \"KeyMapToggle\", KeyMap);\n\tini.Put_Int(HotkeyName, \"KeySidebarUp\", KeySidebarUp);\n\tini.Put_Int(HotkeyName, \"KeySidebarDown\", KeySidebarDown);\n\tini.Put_Int(HotkeyName, \"KeyOption1\", KeyOption1);\n\tini.Put_Int(HotkeyName, \"KeyOption2\", KeyOption2);\n\tini.Put_Int(HotkeyName, \"KeyScrollLeft\", KeyScrollLeft);\n\tini.Put_Int(HotkeyName, \"KeyScrollRight\", KeyScrollRight);\n\tini.Put_Int(HotkeyName, \"KeyScrollUp\", KeyScrollUp);\n\tini.Put_Int(HotkeyName, \"KeyScrollDown\", KeyScrollDown);\n\tini.Put_Int(HotkeyName, \"KeyQueueMove1\", KeyQueueMove1);\n\tini.Put_Int(HotkeyName, \"KeyQueueMove2\", KeyQueueMove2);\n\tini.Put_Int(HotkeyName, \"KeyTeam1\", KeyTeam1);\n\tini.Put_Int(HotkeyName, \"KeyTeam2\", KeyTeam2);\n\tini.Put_Int(HotkeyName, \"KeyTeam3\", KeyTeam3);\n\tini.Put_Int(HotkeyName, \"KeyTeam4\", KeyTeam4);\n\tini.Put_Int(HotkeyName, \"KeyTeam5\", KeyTeam5);\n\tini.Put_Int(HotkeyName, \"KeyTeam6\", KeyTeam6);\n\tini.Put_Int(HotkeyName, \"KeyTeam7\", KeyTeam7);\n\tini.Put_Int(HotkeyName, \"KeyTeam8\", KeyTeam8);\n\tini.Put_Int(HotkeyName, \"KeyTeam9\", KeyTeam9);\n\tini.Put_Int(HotkeyName, \"KeyTeam10\", KeyTeam10);\n\n\t/*\n\t**\tWrite the INI data out to a file.\n\t*/\n\tini.Save(file);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Set -- Sets options based on current settings                                 *\n *                                                                                             *\n * Use this routine to adjust the palette or sound settings after a fresh scenario load.       *\n * It assumes the values needed are already loaded into OptionsClass.                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Set(void)\n{\n\tSet_Brightness(Brightness);\n\tSet_Contrast(Contrast);\n\tSet_Saturation(Saturation);\n\tSet_Tint(Tint);\n\tSet_Sound_Volume(Volume, false);\n\tSet_Score_Volume(ScoreVolume, false);\n\tSet_Repeat(IsScoreRepeat);\n\tSet_Shuffle(IsScoreShuffle);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Normalize_Delay -- Normalizes delay factor to keep rate constant.             *\n *                                                                                             *\n *    This routine is used to adjust delay factors that MUST be synchronized on all machines   *\n *    but should maintain a speed as close to constant as possible. Building animations are    *\n *    a good example of this.                                                                  *\n *                                                                                             *\n * INPUT:   delay -- The normal delay factor.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the delay to use that has been modified so that a reasonably constant *\n *          rate will result.                                                                  *\n *                                                                                             *\n * WARNINGS:   This calculation is crude due to the coarse resolution that a 1/15 second timer *\n *             allows.                                                                         *\n *                                                                                             *\n *             Use of this routine ASSUMES that the GameSpeed is synchronized on all machines. *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/18/1995 JLB : Created.                                                                 *\n *   06/30/1995 JLB : Handles low values in a more consistent manner.                          *\n *=============================================================================================*/\nint OptionsClass::Normalize_Delay(int delay) const\n{\n\tstatic int _adjust[][8] = {\n\t\t{2,2,1,1,1,1,1,1},\n\t\t{3,3,3,2,2,2,1,1},\n\t\t{5,4,4,3,3,2,2,1},\n\t\t{7,6,5,4,4,4,3,2}\n\t};\n\tif (delay) {\n\t\tif (delay < 5) {\n\t\t\tdelay = _adjust[delay-1][GameSpeed];\n\t\t} else {\n\t\t\tdelay = ((delay * 8) / (GameSpeed+1));\n\t\t}\n\t}\n\treturn(delay);\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Fixup_Palette -- Adjusts the real palette to match the palette sliders.       *\n *                                                                                             *\n *    This routine is used to adjust the real palette to match the values for the palette      *\n *    control. The adjusted palette is placed into the palette buffer specified.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The palette is not actually set by this routine.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OptionsClass::Fixup_Palette(void) const\n{\n\tAdjust_Palette(OriginalPalette, InGamePalette, Brightness, Saturation, Tint, Contrast);\n\tCCPalette = InGamePalette;\n}\n\n\n/***********************************************************************************************\n * OptionsClass::Normalize_Volume -- Convert to a real volume value.                           *\n *                                                                                             *\n *    This routine will take a relative volume value and convert it to the real volume value   *\n *    to use. This allows all the game volumes to be corrected to the correct global volume.   *\n *                                                                                             *\n * INPUT:   volume   -- Requested volume level.                                                *\n *                                                                                             *\n * OUTPUT:  Returns with the actual volume level to use.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint OptionsClass::Normalize_Volume(int volume) const\n{\n\treturn(volume * Volume);\n}\n"
  },
  {
    "path": "REDALERT/OPTIONS.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OPTIONS.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OPTIONS_H\n#define OPTIONS_H\n\nclass OptionsClass {\n\tpublic:\n\t\tenum {\n\t\t\tMAX_SCROLL_SETTING=7,\n\t\t\tMAX_SPEED_SETTING=7\n\t\t};\n\n\t\tOptionsClass(void);\n\n\t\tvoid One_Time(void);\n\t\tvoid Process(void);\n\n\t\tvoid Fixup_Palette(void) const;\n\t\tvoid Set_Shuffle(int on);\n\t\tvoid Set_Repeat(int on);\n\t\tvoid Set_Score_Volume(fixed volume, bool feedback);\n\t\tvoid Set_Sound_Volume(fixed volume, bool feedback);\n\t\tvoid Set_Brightness(fixed brightness);\n\t\tfixed Get_Brightness(void) const;\n\t\tvoid Set_Saturation(fixed color);\n\t\tfixed Get_Saturation(void) const;\n\t\tvoid Set_Contrast(fixed contrast);\n\t\tfixed Get_Contrast(void) const;\n\t\tvoid Set_Tint(fixed tint);\n\t\tfixed Get_Tint(void) const;\n\t\tint Normalize_Delay(int delay) const;\n\t\tint Normalize_Volume(int volume) const;\n\n\t\t/*\n\t\t** File I/O routines\n\t\t*/\n\t\tvoid Load_Settings(void);\n\t\tvoid Save_Settings(void);\n\n\t\tvoid Set(void);\n\n\t\t/*\n\t\t**\tThis is actually the delay between game frames expressed as 1/60 of\n\t\t**\ta second. The default value is 4 (1/15 second).\n\t\t*/\n\t\tunsigned int GameSpeed;\n\n\t\tint ScrollRate;\t\t// Distance to scroll.\n\t\tfixed Volume;\t\t\t// Volume for sound effects.\n\t\tfixed ScoreVolume;\t// Volume for scores.\n#ifdef FIXIT_VERSION_3\n\t\tfixed MultiScoreVolume;\t\t//\tVolume for scores during multiplayer games.\n#endif\n\t\tfixed Brightness;\t\t// Brightness.\n\t\tfixed Tint;\t\t\t\t// Hue\n\t\tfixed Saturation;\t\t// Saturation\n\t\tfixed Contrast;\t\t// Value\n\t\tunsigned AutoScroll:1;\t\t// Does map autoscroll?\n\t\tunsigned IsScoreRepeat:1;\t// Score should repeat?\n\t\tunsigned IsScoreShuffle:1;\t// Score list should shuffle?\n\t\tunsigned IsPaletteScroll:1;// Allow palette scrolling?\n\n\t\t/*\n\t\t**\tThese are the hotkeys used for keyboard control.\n\t\t*/\n\t\tKeyNumType KeyForceMove1;\n\t\tKeyNumType KeyForceMove2;\n\t\tKeyNumType KeyForceAttack1;\n\t\tKeyNumType KeyForceAttack2;\n\t\tKeyNumType KeySelect1;\n\t\tKeyNumType KeySelect2;\n\t\tKeyNumType KeyScatter;\n\t\tKeyNumType KeyStop;\n\t\tKeyNumType KeyGuard;\n\t\tKeyNumType KeyNext;\n\t\tKeyNumType KeyPrevious;\n\t\tKeyNumType KeyFormation;\n\t\tKeyNumType KeyHome1;\n\t\tKeyNumType KeyHome2;\n\t\tKeyNumType KeyBase;\n\t\tKeyNumType KeyResign;\n\t\tKeyNumType KeyAlliance;\n\t\tKeyNumType KeyBookmark1;\n\t\tKeyNumType KeyBookmark2;\n\t\tKeyNumType KeyBookmark3;\n\t\tKeyNumType KeyBookmark4;\n\t\tKeyNumType KeySelectView;\n\t\tKeyNumType KeyRepair;\n\t\tKeyNumType KeyRepairOn;\n\t\tKeyNumType KeyRepairOff;\n\t\tKeyNumType KeySell;\n\t\tKeyNumType KeySellOn;\n\t\tKeyNumType KeySellOff;\n\t\tKeyNumType KeyMap;\n\t\tKeyNumType KeySidebarUp;\n\t\tKeyNumType KeySidebarDown;\n\t\tKeyNumType KeyOption1;\n\t\tKeyNumType KeyOption2;\n\t\tKeyNumType KeyScrollLeft;\n\t\tKeyNumType KeyScrollRight;\n\t\tKeyNumType KeyScrollUp;\n\t\tKeyNumType KeyScrollDown;\n\t\tKeyNumType KeyQueueMove1;\n\t\tKeyNumType KeyQueueMove2;\n\t\tKeyNumType KeyTeam1;\n\t\tKeyNumType KeyTeam2;\n\t\tKeyNumType KeyTeam3;\n\t\tKeyNumType KeyTeam4;\n\t\tKeyNumType KeyTeam5;\n\t\tKeyNumType KeyTeam6;\n\t\tKeyNumType KeyTeam7;\n\t\tKeyNumType KeyTeam8;\n\t\tKeyNumType KeyTeam9;\n\t\tKeyNumType KeyTeam10;\n\n\t\tvoid Adjust_Palette(PaletteClass const & oldpal, PaletteClass & newpal, fixed brightness, fixed color, fixed tint, fixed contrast) const;\n\tprotected:\n\n\tprivate:\n\n\t\tstatic char const * const HotkeyName;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/OVERLAY.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OVERLAY.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OVERLAY.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 24, 1995 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   OverlayClass::Read_INI -- Reads the overlay data from an INI file.                        *\n *   OverlayClass::Init -- Resets the overlay object system.                                   *\n *   OverlayClass::Mark -- Marks the overlay down on the map.                                  *\n *   OverlayClass::OverlayClass -- Overlay object constructor.                                 *\n *   OverlayClass::delete -- Returns a overlay object to the pool.                             *\n *   OverlayClass::new -- Allocates a overlay object from pool                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"overlay.h\"\n\n\nHousesType OverlayClass::ToOwn = HOUSE_NONE;\n\n\n\n/***********************************************************************************************\n * OverlayClass::Init -- Resets the overlay object system.                                     *\n *                                                                                             *\n *    This routine resets the overlay object system. It is called                              *\n *    prior to loading a new scenario.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayClass::Init(void)\n{\n\tOverlays.Free_All();\n}\n\n\n/***********************************************************************************************\n * OverlayClass::new -- Allocates a overlay object from pool                                   *\n *                                                                                             *\n *    This routine is used to allocate a overlay object from the                               *\n *    overlay object pool.                                                                     *\n *                                                                                             *\n * INPUT:   size  -- The size of a overlay object (not used).                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to an available overlay object.                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * OverlayClass::operator new(size_t )\n{\n\tvoid * ptr = Overlays.Allocate();\n\tif (ptr) {\n\t\t((OverlayClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::delete -- Returns a overlay object to the pool.                               *\n *                                                                                             *\n *    This routine will return a overlay object to the overlay object                          *\n *    pool. A overlay so returned is available for allocation again.                           *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the object to be returned.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid OverlayClass::operator delete(void * ptr)\n{\n\tif (ptr) {\n\t\t((OverlayClass *)ptr)->IsActive = false;\n\t}\n\tOverlays.Free((OverlayClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::OverlayClass -- Overlay object constructor.                                   *\n *                                                                                             *\n *    This is the constructor for a overlay object.                                            *\n *                                                                                             *\n * INPUT:   type  -- The overlay object this is to become.                                     *\n *                                                                                             *\n *          pos   -- The position on the map to place the object.                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nOverlayClass::OverlayClass(OverlayType type, CELL pos, HousesType house) :\n\tObjectClass(RTTI_OVERLAY, Overlays.ID(this)),\n\tClass(OverlayTypes.Ptr((int)type))\n{\n\tif (pos != -1) {\n\t\tToOwn = house;\n\t\tUnlimbo(Cell_Coord(pos));\n\t\tToOwn = HOUSE_NONE;\n\t}\n}\n\n\n/***********************************************************************************************\n * OverlayClass::Mark -- Marks the overlay down on the map.                                    *\n *                                                                                             *\n *    This routine will place the overlay onto the map. The overlay object is deleted by this  *\n *    operation. The map is updated to reflect the presence of the overlay.                    *\n *                                                                                             *\n * INPUT:   mark  -- The type of marking to perform. Only MARK_DOWN is supported.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the overlay successfully marked? Failure occurs if it is not being       *\n *                marked down.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/24/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Checks low level legality before proceeding.                             *\n *=============================================================================================*/\nbool OverlayClass::Mark(MarkType mark)\n{\n\tassert(Overlays.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (mark == MARK_DOWN) {\n\t\t\tCELL\tcell = Coord_Cell(Coord);\n\t\t\tCellClass * cellptr = &Map[cell];\n\n\t\t\t/*\n\t\t\t**\tWalls have special logic when they are marked down.\n\t\t\t*/\n\t\t\tif (Class->IsWall) {\n\t\t\t\tif (cellptr->Is_Clear_To_Build()) {\n\t\t\t\t\tcellptr->Overlay = Class->Type;\n\t\t\t\t\tcellptr->OverlayData = 0;\n\t\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t\t\tcellptr->Wall_Update();\n\t\t\t\t\tMap.Zone_Reset(Class->IsCrushable ? MZONE_NORMAL : MZONE_NORMAL|MZONE_CRUSHER);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFlag ownership of the cell if the 'global' ownership flag indicates that this\n\t\t\t\t\t**\tis necessary for the overlay.\n\t\t\t\t\t*/\n\t\t\t\t\tif (ToOwn != HOUSE_NONE) {\n\t\t\t\t\t\tcellptr->Owner = ToOwn;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tdelete this;\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\tbool clear = false;\n\t\t\t\tif (!ScenarioInit) {\n\t\t\t\t\tif (Class->Type == OVERLAY_WATER_CRATE) {\n\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_FLOAT, false, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Class->Type == OVERLAY_STEEL_CRATE || Class->Type == OVERLAY_WOOD_CRATE) {\n\t\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_TRACK, false, false);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tclear = cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tclear = true;\n\t\t\t\t}\n\n\t\t\t\tif ((ScenarioInit || cellptr->Overlay == OVERLAY_NONE) && clear) {\n\n\t\t\t\t\tcellptr->Overlay = Class->Type;\n\t\t\t\t\tcellptr->OverlayData = 0;\n\n\t\t\t\t\tcellptr->Redraw_Objects();\n\t\t\t\t\tif (Class->Land == LAND_TIBERIUM) {\n\t\t\t\t\t\tcellptr->OverlayData = 1;\n\t\t\t\t\t\tcellptr->Tiberium_Adjust();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\t*****  Is this really needed?\n\t\t\t*/\n\t\t\tcellptr->Recalc_Attributes();\n\n\t\t\t/*\n\t\t\t**\tRemove the overlay and make sure the system thinks it was never placed down!\n\t\t\t*/\n\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\tIsDown = false;\n\t\t\tIsInLimbo = true;\n\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * OverlayClass::Read_INI -- Reads the overlay data from an INI file.                          *\n *                                                                                             *\n *    This routine is used to load a scenario's overlay data. The overlay objects are read     *\n *    from the INI file and then created on the map.                                           *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI file staging buffer.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Requires that all the buildings be placed first, so the scan for assigning wall *\n *             ownership to the nearest building will work.                                    *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   07/24/1995 JLB : Specifically forbid manual crates in multiplayer scenarios.              *\n *=============================================================================================*/\nvoid OverlayClass::Read_INI(CCINIClass & ini)\n{\n\tif (NewINIFormat > 1) {\n\t\tint len = ini.Get_UUBlock(\"OverlayPack\", _staging_buffer, sizeof(_staging_buffer));\n\n\t\tif (len > 0) {\n\t\t\tBufferStraw bpipe(_staging_buffer, len);\n\t\t\tLCWStraw uncomp(LCWStraw::DECOMPRESS);\n\t\t\tuncomp.Get_From(&bpipe);\n\n\t\t\tfor (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {\n\t\t\t\tOverlayType classid;\n\n\t\t\t\tuncomp.Get(&classid, sizeof(classid));\n\n\t\t\t\tif (classid != OVERLAY_NONE) {\n\n\t\t\t\t\tif (Session.Type == GAME_NORMAL || !OverlayTypeClass::As_Reference(classid).IsCrate) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tDon't allow placement of overlays on the top or bottom rows of\n\t\t\t\t\t\t**\tthe map.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (cell >= MAP_CELL_W && cell <= MAP_CELL_TOTAL - MAP_CELL_W) {\n\t\t\t\t\t\t\tnew OverlayClass(classid, cell);\n\n\t\t\t\t\t\t\t// Assign house ownership to cells with walls in 'em.\n\t\t\t\t\t\t\tif (OverlayTypeClass::As_Reference(classid).IsWall) {\n\t\t\t\t\t\t\t\tHousesType owner = HOUSE_NONE;\n\t\t\t\t\t\t\t\tint distance = 0x7FFFFFFF;\n\t\t\t\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\t\t\t\t\t\t\tint newdist = ::Distance(building->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\t\t\t\t\tif (newdist < distance) {\n\t\t\t\t\t\t\t\t\t\tdistance = newdist;\n\t\t\t\t\t\t\t\t\t\towner = building->Owner();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tMap[cell].Owner = owner;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (NewINIFormat < 2 || ini.Is_Present(\"Overlay\")) {\n\t\tint len = ini.Entry_Count(INI_Name());\n\t\tfor (int index = 0; index < len; index++) {\n\t\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\t\tCELL cell = atoi(entry);\n\t\t\tOverlayType classid = ini.Get_OverlayType(INI_Name(), entry, OVERLAY_NONE);\n\n\t\t\t/*\n\t\t\t**\tDon't allow placement of crates in the multiplayer scenarios.\n\t\t\t*/\n\t\t\tif (classid != OVERLAY_NONE && (Session.Type == GAME_NORMAL || !OverlayTypeClass::As_Reference(classid).IsCrate)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tDon't allow placement of overlays on the top or bottom rows of\n\t\t\t\t**\tthe map.\n\t\t\t\t*/\n\t\t\t\tif (cell >= MAP_CELL_W && cell <= MAP_CELL_TOTAL - MAP_CELL_W) {\n\t\t\t\t\tnew OverlayClass(classid, cell);\n\n\t\t\t\t\t// Assign house ownership to cells with walls in 'em.\n\t\t\t\t\tif (OverlayTypeClass::As_Reference(classid).IsWall) {\n\t\t\t\t\t\tHousesType owner = HOUSE_NONE;\n\t\t\t\t\t\tint distance = 0x7FFFFFFF;\n\t\t\t\t\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\t\t\t\t\tBuildingClass * building = Buildings.Ptr(index);\n\t\t\t\t\t\t\tint newdist = ::Distance(building->Center_Coord(), Cell_Coord(cell));\n\t\t\t\t\t\t\tif (newdist < distance) {\n\t\t\t\t\t\t\t\tdistance = newdist;\n\t\t\t\t\t\t\t\towner = building->Owner();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tMap[cell].Owner = owner;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid OverlayClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing unit data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\tini.Clear(\"OverlayPack\");\n\n\tBufferPipe bpipe(_staging_buffer, sizeof(_staging_buffer));\n\tLCWPipe comppipe(LCWPipe::COMPRESS);\n\n\tcomppipe.Put_To(&bpipe);\n\n\tint total = 0;\n\tCellClass * cellptr = &Map[(CELL)0];\n\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\ttotal += comppipe.Put(&cellptr->Overlay, sizeof(cellptr->Overlay));\n\t\tcellptr++;\n\t}\n\tif (total) {\n\t\tini.Put_UUBlock(\"OverlayPack\", _staging_buffer, total);\n\t}\n\n//\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n//\t\tCellClass * cellptr = &Map[index];\n//\t\tif (cellptr->Overlay != OVERLAY_NONE) {\n//\t\t\tchar\tuname[10];\n//\t\t\tsprintf(uname, \"%d\", index);\n//\t\t\tini.Put_Overlay(INI_Name(), uname, cellptr->Overlay);\n//\t\t}\n//\t}\n}"
  },
  {
    "path": "REDALERT/OVERLAY.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/OVERLAY.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OVERLAY.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 17, 1994                                                 *\n *                                                                                             *\n *                  Last Update : May 17, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef OVERLAY_H\n#define OVERLAY_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n/******************************************************************************\n**\tThis class controls the overlay object. Overlay objects function congruously\n**\tto carpet on a floor. They have no depth, but merely control the icon to be rendered\n**\tas the cell's bottom most layer.\n*/\nclass OverlayClass : public ObjectClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the overlay object's class.\n\t\t*/\n\t\tCCPtr<OverlayTypeClass> Class;\n\n\t\t/*-------------------------------------------------------------------\n\t\t**\tConstructors and destructors.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tOverlayClass(OverlayType type, CELL pos=-1, HousesType = HOUSE_NONE);\n\t\tOverlayClass(NoInitClass const & x) : ObjectClass(x), Class(x) {};\n\t\tvirtual ~OverlayClass(void) {if (GameActive) OverlayClass::Limbo();Class=0;};\n\t\toperator OverlayType(void) const {return Class->Type;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"OVERLAY\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\t/*\n\t\t**\tVirtual support functionality.\n\t\t*/\n\t\tvirtual bool Mark(MarkType);\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual void Draw_It(int , int , WindowNumberType ) const {};\n\n\tprivate:\n\t\t/*\n\t\t**\tThis is used to control the marking process of the overlay. If this is\n\t\t**\tset to a valid house number, then the cell that the overlay is marked down\n\t\t**\tupon will be flagged as being owned by the specified house.\n\t\t*/\n\t\tstatic HousesType ToOwn;\n\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[8];\n};\n\n#endif"
  },
  {
    "path": "REDALERT/PACKET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : PACKET.CPP                               *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/22/96                                 *\n *                                                                         *\n *                  Last Update : April 24, 1996 [PWG]                     *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n *   *PacketClass::Find_Field -- Finds a field if it exists in the packets *\n *   Get_Field -- Find specified name and returns data                     *\n *   PacketClass::~PacketClass -- destroys a packet class be freeing list  *\n *   PacketClass::Add_Field -- Adds a FieldClass entry to head of packet li*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0) //PG\n\n#include <stdlib.h>\n#include <mem.h>\n#include <string.h>\n\nenum {false=0,true=1};\ntypedef int bool;\n\n#include \"packet.h\"\n\n\n/**************************************************************************\n * PACKETCLASS::~PACKETCLASS -- destroys a packet class be freeing list   *\n *                                                                        *\n * INPUT:\t\tnone                                                       *\n *                                                                        *\n * OUTPUT:     none\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/24/1996 PWG : Created.                                            *\n *========================================================================*/\nPacketClass::~PacketClass(void)\n{\n\tFieldClass *current;\n\tFieldClass *next;\n\t//\n\t// Loop through the entire field list and delete each entry.\n\t//\n\tfor (current = Head; current; current = next) {\n\t\tnext = current->Next;\n\t\tdelete current;\n\t}\n}\n\n\n/**************************************************************************\n * PACKETCLASS::ADD_FIELD -- Adds a FieldClass entry to head of packet li *\n *                                                                        *\n * INPUT:\t\tFieldClass * - a properly constructed field class entry.\t  *\n *                                                                        *\n * OUTPUT:     none                                                       *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/24/1996 PWG : Created.                                            *\n *========================================================================*/\nvoid PacketClass::Add_Field(FieldClass *field)\n{\n\tfield->Next = Head;\n\tHead = field;\n}\n\n/**************************************************************************\n * PACKETCLASS::PACKETCLASS -- Creates a Packet object from a COMMS packe *\n *                                                                        *\n * INPUT:                                                                 *\n *                                                                        *\n * OUTPUT:                                                                *\n *                                                                        *\n * WARNINGS:                                                              *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nPacketClass::PacketClass(char *curbuf)\n{\n\tint remaining_size;\n\t//\n\t// Pull the size and packet ID out of the linear packet stream.\n\t//\n\tSize = *(unsigned short *)curbuf;\n\tcurbuf += sizeof (unsigned short);\n\tSize = ntohs(Size);\n\tID\t  = *(short *)curbuf;\n\tcurbuf += sizeof (short);\n\tID   = ntohs(ID);\n\tHead = NULL;\n\n\t//\n\t// Calculate the remaining size so that we can loop through the\n\t//   packets and extract them.\n\t//\n\tremaining_size = Size - 4;\n\n\t//\n\t// Loop through the linear packet until we run out of room and\n\t// create a field for each.\n\t//\n\twhile (remaining_size > 0) {\n\t\tFieldClass *field = new FieldClass;\n\n\t\t//\n\t\t// Copy the adjusted header into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(field, curbuf, FIELD_HEADER_SIZE);\n\t\tcurbuf += FIELD_HEADER_SIZE;\n\t\tremaining_size   -= FIELD_HEADER_SIZE;\n\n\t\t//\n\t\t// Copy the data into the buffer\n\t\t//\n\t\tint size\t\t\t= ntohs(field->Size);\n\t\tfield->Data\t\t= new char[size];\n\t\tmemcpy(field->Data, curbuf, size);\n\t\tcurbuf\t\t\t+= size;\n\t\tremaining_size\t-= size;\n\t\t//\n\t\t// Make sure we allow for the pad bytes.\n\t\t//\n\t\tint pad = (4 - (ntohs(field->Size) & 3)) & 3;\n\t\tcurbuf += pad;\n\t\tremaining_size   -= pad;\n\n\t\t//\n\t\t// Convert the field back to the host format\n\t\t//\n\t\tfield->Net_To_Host();\n\n\t\t//\n\t\t// Finally add the field to the field list in the packet\n\t\t// structure.\n\t\t//\n\t\tAdd_Field(field);\n\t}\n}\n\n/**************************************************************************\n * CREATE_COMMS_PACKET -- Walks field list creating a packet              *\n *                                                                        *\n * INPUT:\t\tshort - the id of the packet so the server can identify it *\n *\t\t\t\t\tunsigned short & - the size of the packet returned here    *\n *                                                                        *\n * OUTPUT:     void * pointer to the linear packet data                   *\n *                                                                        *\n * WARNINGS: \tThis routine allocates memory that the user is responsible *\n *  \t\t\t\tfor freeing.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/22/1996 PWG : Created.                                            *\n *========================================================================*/\nchar *PacketClass::Create_Comms_Packet(int &size)\n{\n\tFieldClass *current;\n\n\t//\n\t// Size starts at four because that is the size of the packet header.\n\t//\n\tsize = 4;\n\n\t//\n\t// Take a quick spin through and calculate the size of the packet we\n\t//   are building.\n\t//\n\tfor (current = Head; current; current=current->Next) {\n\t\tsize += (unsigned short)FIELD_HEADER_SIZE;\t\t\t// add in packet header size\n\t\tsize += current->Size;\t\t\t\t// add in data size\n\t\tsize += (4 - (size & 3)) & 3; \t// add in pad value to dword align next packet\n\t}\n\n\t//\n\t// Now that we know the size allocate a buffer big enough to hold the\n\t// packet.\n\t//\n\tchar *retval = new char[size];\n\tchar *curbuf = retval;\n\n\t//\n\t// write the size into the packet header\n\t//\n\t*(unsigned short *)curbuf = (unsigned short)htons((unsigned short)size);\n\tcurbuf += sizeof (unsigned short);\n\t*(short *)curbuf = htons(ID);\n\tcurbuf += sizeof (short);\n\n\t//\n\t// Ok now that the actual header information has been written we need to write out\n\t// field information.\n\t//\n\tfor (current = Head; current; current = current->Next) {\n\t\t//\n\t\t// Temporarily convert the packet to net format (this saves alot of\n\t\t//   effort, and seems safe...)\n\t\t//\n\t\tcurrent->Host_To_Net();\n\n\t\t//\n\t\t// Copy the adjusted header into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(curbuf, current, FIELD_HEADER_SIZE);\n\t\tcurbuf += FIELD_HEADER_SIZE;\n\n\t\t//\n\t\t// Copy the data into the buffer and then advance the buffer\n\t\t//\n\t\tmemcpy(curbuf, current->Data, ntohs(current->Size));\n\t\tcurbuf += ntohs(current->Size);\n\n\t\t//\n\t\t// Finally take care of any pad bytes by setting them to 0\n\t\t//\n\t\tint pad = (4 - (ntohs(current->Size) & 3)) & 3;\n\n\t\t//\n\t\t//\tIf there is any pad left over, make sure you memset it\n\t\t// to zeros, so it looks like a pad.\n\t\t//\n\t\tif (pad) {\n\t\t\tmemset(curbuf, 0, pad);\n\t\t\tcurbuf += pad;\n\t\t}\n\n\t\tcurrent->Net_To_Host();\n\t}\n\treturn(retval);\n}\n\n\n/**************************************************************************\n * PACKETCLASS::FIND_FIELD -- Finds a field if it exists in the packets   *\n *                                                                        *\n * INPUT:\t\tchar *  - the id of the field we are looking for.\t\t\t  *\n *                                                                        *\n * OUTPUT:     FieldClass * pointer to the field class                    *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nFieldClass *PacketClass::Find_Field(char *id)\n{\n\tfor (FieldClass *current = Head; current; current = current->Next) {\n\t\tif ( strncmp(id, current->ID, 4) == 0)\n\t\t\treturn current;\n\t}\n\treturn NULL;\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tchar &   - the reference to store the data into\t\t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, char &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned char &   - the reference to store the data into\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned char &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tshort &   - the reference to store the data into\t        *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, short &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((short *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned short &   - the reference to store the data into  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned short &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned short *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tlong &   - the reference to store the data into  \t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, long &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((long *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data as a string          *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tchar *   - the string to store the data into\t\t\t\t\t  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe string is not changed if the field is not found.  It   *\n *\t\t\t\t\tis assumed that the string variabled specified by the      *\n *\t\t\t\t\tpointer is large enough to hold the data.\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, char *data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tstrcpy(data, (char *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t  *\n *\t\t\t\t\tunsigned long &   - the reference to store the data into   *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t  *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t  *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                        *\n * HISTORY:                                                               *\n *   04/23/1996 PWG : Created.                                            *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, unsigned long &data)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tdata = *((unsigned long *)field->Data);\n\t}\n\treturn((field) ? true : false);\n}\n\n\n/**************************************************************************\n * GET_FIELD -- Find specified name and returns data                      *\n *                                                                        *\n * INPUT:\t\tchar *   - the id of the field that holds the data.\t\t    *\n *\t\t\t\tvoid * - the reference to store the data into                *\n *           int    - the length of the buffer passed in                  *\n *                                                                        *\n * OUTPUT:\t\ttrue if the field was found, false if it was not.\t\t\t *\n *                                                                        *\n * WARNINGS:\tThe data reference is not changed if the field is not\t\t    *\n *\t\t\t\t\tfound.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t *\n *                                                                        *\n * HISTORY:                                                               *\n *   6/4/96 4:46PM ST : Created                                           *\n *========================================================================*/\nbool PacketClass::Get_Field(char *id, void *data, int &length)\n{\n\tFieldClass *field = Find_Field(id);\n\tif (field) {\n\t\tmemcpy (data, field->Data, min(field->Size, length));\n\t\tlength = (int) field->Size;\n\t}\n\treturn((field) ? true : false);\n}\n#endif"
  },
  {
    "path": "REDALERT/PACKET.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/***************************************************************************\n *                                                                         *\n *                 Project Name : Westwood Auto Registration App           *\n *                                                                         *\n *                    File Name : PACKET.H                                 *\n *                                                                         *\n *                   Programmer : Philip W. Gorrow                         *\n *                                                                         *\n *                   Start Date : 04/19/96                                 *\n *                                                                         *\n *                  Last Update : April 19, 1996 [PWG]                     *\n *                                                                         *\n * This header defines the functions for the PacketClass.  The packet      *\n * class is used to create a linked list of field entries which can be     *\n * converted to a linear packet in a COMMS API compatible format.          *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * Packets can be created empty and then have fields added to them or can  *\n * be created from an existing linear packet.  \t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *-------------------------------------------------------------------------*\n * Functions:                                                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef __PACKET_H\n#define __PACKET_H\n\n\n#include \"field.h\"\n\nclass PacketClass {\n\tpublic:\n\t\tPacketClass(short id = 0)\n\t\t{\n\t\t\tSize \t\t\t= 0;\n\t\t\tID\t\t\t\t= id;\n\t\t\tHead\t\t\t= 0;\n\t\t}\n\t\tPacketClass(char *cur_buf);\n\t\t~PacketClass(void);\n\n\t\t//\n\t\t// This function allows us to add a field to the start of the list.  As the field is just\n\t\t//   a big linked list it makes no difference which end we add a member to.\n\t\t//\n\t\tvoid Add_Field(FieldClass *field);\n\n\t\t//\n\t\t// These conveniance functions allow us to add a field directly to the list without\n\t\t// having to worry about newing one first.\n\t\t//\n\t\tvoid Add_Field(char *field, char data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned char data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, short data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned short data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, long data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, unsigned long data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, char *data) {Add_Field(new FieldClass(field, data));};\n\t\tvoid Add_Field(char *field, void *data, int length) {Add_Field(new FieldClass(field, data, length));};\n\n\t\t//\n\t\t// These functions search for a field of a given name in the list and\n\t\t// return the data via a reference value.\n\t\t//\n\t\tFieldClass *Find_Field(char *id);\n\t\tbool Get_Field(char *id, char &data);\n\t\tbool Get_Field(char *id, unsigned char &data);\n\t\tbool Get_Field(char *id, short &data);\n\t\tbool Get_Field(char *id, unsigned short &data);\n\t\tbool Get_Field(char *id, long &data);\n\t\tbool Get_Field(char *id, unsigned long &data);\n\t\tbool Get_Field(char *id, char *data);\n\t\tbool Get_Field(char *id, void *data, int &length);\n\n\t\tchar *Create_Comms_Packet(int &size);\n\n\tprivate:\n\t\tunsigned short \tSize;\n\t\tshort \t\t\t\tID;\n\t\tFieldClass\t\t\t*Head;\n\t\tFieldClass\t\t\t*Current;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/PALETTEC.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/palette.cpp 2     9/23/97 11:00p Steve_t $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PALETTE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : February 5, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PaletteClass::Adjust -- Adjusts the palette toward another palette.                       *\n *   PaletteClass::Adjust -- Adjusts this palette toward black.                                *\n *   PaletteClass::Closest_Color -- Finds closest match to color specified.                    *\n *   PaletteClass::Set -- Fade the display palette to this palette.                            *\n *   PaletteClass::PaletteClass -- Constructor that fills palette with color specified.        *\n *   PaletteClass::operator = -- Assignment operator for palette objects.                      *\n *   PaletteClass::operator == -- Equality operator for palette objects.                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef NOINITCLASS\n#define NOINITCLASS\nstruct NoInitClass {\n\tpublic:\n\t\tvoid operator () (void) const {};\n};\n#endif\n\nvoid __cdecl Set_Palette(void * palette);\n\n\n#ifndef BITMAPCLASS\n#define BITMAPCLASS\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n#include\t\"function.h\"\n#include\t\"watcom.h\"\n#include\t\"palette.h\"\n#include\t\"palettec.h\"\n#include\t\"ftimer.h\"\n//#define TIMER_H\n#include\t\"wwlib32.h\"\n//#include\t\"timer.h\"\n#include\t<string.h>\n\n#ifndef SYSTEM_TIMER_CLASS\n#define SYSTEM_TIMER_CLASS\n\n#ifdef WIN32\nextern WinTimerClass\t*\t\tWindowsTimer;\n#endif\n\nclass SystemTimerClass\n{\n\tpublic:\n\t\t#ifdef WIN32\n\t\t\tlong operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t\toperator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());};\n\t\t#else\n\t\t\tlong operator () (void) const {return(Get_System_Tick_Count());};\n\t\t\toperator long (void) const {return(Get_System_Tick_Count());};\n\t\t#endif\n};\n#endif\n\n\n//PaletteClass const PaletteClass::CurrentPalette;\nextern \"C\" unsigned char CurrentPalette[];\n\nPaletteClass const & PaletteClass::CurrentPalette = *(PaletteClass *)&::CurrentPalette[0];\n\n\n/***********************************************************************************************\n * PaletteClass::PaletteClass -- Constructor that fills palette with color specified.          *\n *                                                                                             *\n *    This constructor will fill the palette with the color specified.                         *\n *                                                                                             *\n * INPUT:   rgb   -- Reference to the color to fill the entire palette with.                   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nPaletteClass::PaletteClass(RGBClass const & rgb)\n{\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\tPalette[index] = rgb;\n\t}\n}\n\n\n/***********************************************************************************************\n * PaletteClass::operator == -- Equality operator for palette objects.                         *\n *                                                                                             *\n *    This is the comparison for equality operator. It will compare palette objects to         *\n *    determine if they are identical.                                                         *\n *                                                                                             *\n * INPUT:   palette  -- Reference to the palette to compare to this palette.                   *\n *                                                                                             *\n * OUTPUT:  Are the two palettes identical?                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PaletteClass::operator == (PaletteClass const & palette) const\n{\n\tif (this == &palette) return(true);\n\treturn(memcmp(&Palette[0], &palette.Palette[0], sizeof(Palette)) == 0);\n}\n\n\n/***********************************************************************************************\n * PaletteClass::operator = -- Assignment operator for palette objects.                        *\n *                                                                                             *\n *    This is the assignment operator for palette objects. Although the default C++ generated  *\n *    assignment operator would function correctly, it would not check for self-assignment    *\n *    and thus this routine can be faster.                                                     *\n *                                                                                             *\n * INPUT:   palette  -- Reference to that palette that will be copied into this palette.       *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the newly copied to palette.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nPaletteClass & PaletteClass::operator = (PaletteClass const & palette)\n{\n\tif (this == &palette) return(*this);\n\n\tmemcpy(&Palette[0], &palette.Palette[0], sizeof(Palette));\n\treturn(*this);\n}\n\n\n/***********************************************************************************************\n * PaletteClass::Adjust -- Adjusts this palette toward black.                                  *\n *                                                                                             *\n *    This routine is used to adjust this palette toward black. Typical use of this routine    *\n *    is when fading the palette to black.                                                     *\n *                                                                                             *\n * INPUT:   ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255    *\n *                   means 100% faded to black.                                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine doesn't actually set the palette to the video card. Use the Set()  *\n *             function to achieve that purpose.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PaletteClass::Adjust(int ratio)\n{\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\tPalette[index].Adjust(ratio, BlackColor);\n\t}\n}\n\n\n/***********************************************************************************************\n * PaletteClass::Adjust -- Adjusts the palette toward another palette.                         *\n *                                                                                             *\n *    This routine is used to adjust a palette toward a destination palette by the ratio       *\n *    specified. This is primarily used by the palette fading routines.                        *\n *                                                                                             *\n * INPUT:   palette  -- Reference to the destination palette.                                  *\n *                                                                                             *\n *          ratio    -- The ratio to adjust this palette toward the destination palette. A     *\n *                      value of 0 means no adjustment at all. A value of 255 means 100%       *\n *                      adjustment.                                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PaletteClass::Adjust(int ratio, PaletteClass const & palette)\n{\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\n//if (index == 1) {\n//\tMono_Printf(\"From R=%d,G=%d,B=%d \", Palette[index].Red_Component(), Palette[index].Green_Component(), Palette[index].Blue_Component());\n//\tMono_Printf(\"To R=%d,G=%d,B=%d [%d] \", palette[index].Red_Component(), palette[index].Green_Component(), palette[index].Blue_Component(), ratio);\n//}\n\t\tPalette[index].Adjust(ratio, palette[index]);\n\n//if (index == 1) {\n//\tMono_Printf(\"Equals R=%d,G=%d,B=%d.\\n\", Palette[index].Red_Component(), Palette[index].Green_Component(), Palette[index].Blue_Component());\n//}\n\n\t}\n}\n\n\n/***********************************************************************************************\n * PaletteClass::Partial_Adjust -- Adjusts the specified parts of this palette toward black.   *\n *                                                                                             *\n *    This routine is used to adjust this palette toward black. Typical use of this routine    *\n *    is when fading the palette to black. The input lookup table is used to determine         *\n *    which entries should fade and which should stay the same                                 *\n *                                                                                             *\n * INPUT:   ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255    *\n *                   means 100% faded to black.                                                *\n *                                                                                             *\n *          lookup\t-- ptr to lookup table                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine doesn't actually set the palette to the video card. Use the Set()  *\n *             function to achieve that purpose.                                               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PaletteClass::Partial_Adjust(int ratio, char *lut)\n{\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\tif (lut[index]) {\n\t\t\tPalette[index].Adjust(ratio, BlackColor);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * PaletteClass::Partial_Adjust -- Adjusts the palette toward another palette.                 *\n *                                                                                             *\n *    This routine is used to adjust a palette toward a destination palette by the ratio       *\n *    specified. This is primarily used by the palette fading routines.  The input lookup      *\n *    table is used to determine which entries should fade and which should stay the same      *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   palette  -- Reference to the destination palette.                                  *\n *                                                                                             *\n *          ratio    -- The ratio to adjust this palette toward the destination palette. A     *\n *                      value of 0 means no adjustment at all. A value of 255 means 100%       *\n *                      adjustment.                                                            *\n *                                                                                             *\n *          lookup   -- ptr to lookup table                                                    *\n *                                                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PaletteClass::Partial_Adjust(int ratio, PaletteClass const & palette, char *lut)\n{\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\tif (lut[index]) {\n\t\t\tPalette[index].Adjust(ratio, palette[index]);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * PaletteClass::Closest_Color -- Finds closest match to color specified.                      *\n *                                                                                             *\n *    This routine will examine the palette and return with the color index number for the     *\n *    color that most closely matches the color specified. Remap operations rely heavily on    *\n *    this routine to allow working with a constant palette.                                   *\n *                                                                                             *\n * INPUT:   rgb   -- Reference to a color to search for in the current palette.                *\n *                                                                                             *\n * OUTPUT:  Returns with a color index value to most closely matches the specified color.      *\n *                                                                                             *\n * WARNINGS:   This routine will quite likely not find an exact match.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PaletteClass::Closest_Color(RGBClass const & rgb) const\n{\n\tint closest = 0;\n\tint value = -1;\n\n\tRGBClass const * ptr = &Palette[0];\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\tint difference = rgb.Difference(*ptr++);\n\t\tif (value == -1 || difference < value) {\n\t\t\tvalue = difference;\n\t\t\tclosest = index;\n\t\t}\n\t}\n\treturn(closest);\n}\n\n\n#ifndef\tWIN32\nextern void Vsync(void);\n#pragma aux Vsync modify [edx ebx eax] = \\\n\t\"mov\tedx,03DAh\"\t\t\t\t\\\n\t\"mov\tebx,[VertBlank]\"\t\t\\\n\t\"and\tbl,001h\"\t\t\t\t\t\\\n\t\"shl\tbl,3\"\t\t\t\t\t\t\\\n\t\"in_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"je\tin_vbi\"\t\t\t\t\t\\\n\t\"out_vbi:\"\t\t\t\t\t\t\\\n\t\"in\tal,dx\"\t\t\t\t\t\\\n\t\"and\tal,008h\"\t\t\t\t\t\\\n\t\"xor\tal,bl\"\t\t\t\t\t\\\n\t\"jne\tout_vbi\"\n#endif\t//WIN32\n\n\n/***********************************************************************************************\n * PaletteClass::Set -- Fade the display palette to this palette.                              *\n *                                                                                             *\n *    This routine will fade the display palette to match this palette over the time period    *\n *    specified. For smooth palette transitions, this is the routine to call.                  *\n *                                                                                             *\n * INPUT:   time  -- The time period (in system tick increments) to fade the display palette   *\n *                   to match this palette.                                                    *\n *                                                                                             *\n *          callback -- Optional pointer to callback function that, if non-null, will be       *\n *                      called as often as possible during the fading process.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine will not return until the palette is completely faded to the       *\n *             destination palette.                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *   02/05/1996 JLB : Uses new timer system.                                                   *\n *=============================================================================================*/\nvoid PaletteClass::Set(int time, void (* callback)(void)) const\n{\n\tCDTimerClass<SystemTimerClass> timer = time;\n\tPaletteClass original = CurrentPalette;\n\n\twhile (timer) {\n\n\t\t/*\n\t\t**\tBuild an intermediate palette that is as close to the destination palette\n\t\t**\tas the current time is proportional to the ending time.\n\t\t*/\n\t\tPaletteClass palette = original;\n\t\tint adjust = ((time - timer) * 256) / time;\n\t\tpalette.Adjust(adjust, *this);\n\n\t\t/*\n\t\t**\tRemember the current time so that multiple palette sets within the same game\n\t\t**\ttime tick won't occur. This is probably unnecessary since the palette setting\n\t\t**\tcode, at the time of this writing, delays at least one game tick in the process\n\t\t**\tof setting the palette.\n\t\t*/\n\t\tlong holdtime = timer;\n\n\t\t/*\n\t\t**\tSet the palette to this intermediate palette and then loop back\n\t\t**\tto calculate and set a new intermediate palette.\n\t\t*/\n#ifdef WIN32\n\t\tSet_Palette((void*)&palette[0]);\n#else\n\t\tpalette.Set();\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tIf the callback routine was specified, then call it once per palette\n\t\t**\tsetting loop.\n\t\t*/\n\t\tif (callback) {\n\t\t\tcallback();\n\t\t}\n\n\t\t/*\n\t\t**\tThis loop ensures that the palette won't be set more than once per game tick. Setting\n\t\t**\tthe palette more than once per game tick will have no effect since the calculation will\n\t\t**\tresult in the same intermediate palette that was previously calculated.\n\t\t*/\n\t\twhile (timer == holdtime && holdtime != 0) {\n\t\t\tif (callback) callback();\n\t\t}\n\t}\n\n\t/*\n\t**\tEnsure that the final palette exactly matches the requested\n\t**\tpalette before exiting the fading routine.\n\t*/\n#ifndef WIN32\n\tVsync();\n\tRGBClass const * rgbptr = &Palette[0];\n\tRGBClass::Raw_Color_Prep(0);\n\tfor (int index = 0; index < COLOR_COUNT; index++) {\n\t\trgbptr->Raw_Set();\n\t\trgbptr++;\n\t}\n\t((PaletteClass &)CurrentPalette) = *this;\n#else\t//WIN32\n\tSet_Palette((void*)&Palette[0]);\n#endif\n}\n"
  },
  {
    "path": "REDALERT/PALETTEC.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PALETTE.H 2     9/23/97 11:00p Steve_t $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PALETTE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : December 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef PALETTE_Hx\n#define PALETTE_Hx\n\n#include\t\"rgb.h\"\n\n/*\n**\tThe palette class is used to manipulate a palette as a whole. All 256 colors are\n**\trepresented by the palette class object.\n*/\nclass PaletteClass\n{\n\tpublic:\n\t\tenum {\n\t\t\tCOLOR_COUNT=256\t\t\t// Number of color indices on the palette.\n\t\t};\n\n\t\tPaletteClass(void) {};\n\t\tPaletteClass(RGBClass const & rgb);\n\n\t\tRGBClass & operator[] (unsigned index) {return(Palette[index % COLOR_COUNT]);};\n\t\tconst RGBClass & operator[] (unsigned index) const {return(Palette[index % COLOR_COUNT]);};\n\t\tint operator == (PaletteClass const & palette) const;\n\t\tint operator != (PaletteClass const & palette) const {return(!(operator ==(palette)));};\n\t\tPaletteClass & operator = (PaletteClass const & palette);\n\t\t\n\t\t// Removed these and replaced with function for clarity. ST - 5/9/2019\n\t\t//operator const unsigned char * (void) const {return((const unsigned char *)&Palette[0]);};\n\t\t//operator unsigned char * (void) {return((unsigned char *)&Palette[0]);};\n\t\tconst void *Get_Data(void) const { return &Palette[0]; }\n\t\tvoid *Get_Data(void) { return &Palette[0]; }\n\n\t\tvoid Adjust(int ratio);\n\t\tvoid Adjust(int ratio, PaletteClass const & palette);\n\t\tvoid Partial_Adjust(int ratio, char *lut);\n\t\tvoid Partial_Adjust(int ratio, PaletteClass const & palette, char *lut);\n\t\tvoid Set(int time = 0, void (*callback)(void) = 0) const;\n\t\tint Closest_Color(RGBClass const & rgb) const;\n\n\t\tstatic PaletteClass const & CurrentPalette;\n\n\tprotected:\n\t\tRGBClass Palette[COLOR_COUNT];\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/PIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PIPE.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Pipe::Put_To -- Connect a pipe to flow data into from this pipe.                          *\n *   Pipe::Flush -- Flush all pending data out the pipe.                                       *\n *   Pipe::Put -- Feed some data through the pipe.                                             *\n *   Pipe::~Pipe -- Destructor for pipe class object.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"pipe.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Pipe::~Pipe -- Destructor for pipe class object.                                            *\n *                                                                                             *\n *    This destructor will unlink itself from any other pipes that it may be chained to. In    *\n *    the process, it will flush any output it may have pending.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPipe::~Pipe(void)\n{\n\tif (ChainTo != NULL) {\n\t\tChainTo->ChainFrom = ChainFrom;\n\t}\n\tif (ChainFrom != NULL) {\n\t\tChainFrom->Put_To(ChainTo);\n\t}\n\n\tChainFrom = NULL;\n\tChainTo = NULL;\n}\n\n\n/***********************************************************************************************\n * Pipe::Put_To -- Connect a pipe to flow data into from this pipe.                            *\n *                                                                                             *\n *    This routine will link two pipes together. The specified pipe will be fed data from      *\n *    this pipe.                                                                               *\n *                                                                                             *\n * INPUT:   pipe  -- Pointer to the pipe that data will flow to.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Pipe::Put_To(Pipe * pipe)\n{\n\tif (ChainTo != pipe) {\n\t\tif (pipe != NULL && pipe->ChainFrom != NULL) {\n\t\t\tpipe->ChainFrom->Put_To(NULL);\n\t\t\tpipe->ChainFrom = NULL;\n\t\t}\n\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = NULL;\n\t\t\tChainTo->Flush();\n\t\t}\n\n\t\tChainTo = pipe;\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Pipe::Put -- Feed some data through the pipe.                                               *\n *                                                                                             *\n *    Use this to force feed data through the pipe. It is guaranteed to accept data as fast    *\n *    as you can supply it.                                                                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to feed to this routine.                           *\n *                                                                                             *\n *          length   -- The number of bytes of data to submit.                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes actually output at the other far distant final    *\n *          end of the pipe.                                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Pipe::Put(void const * source, int length)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Put(source, length));\n\t}\n\treturn(length);\n}\n\n\n/***********************************************************************************************\n * Pipe::Flush -- Flush all pending data out the pipe.                                         *\n *                                                                                             *\n *    Then the pipe needs to be flushed, this routine will be called. Since pipe segments      *\n *    might have internal staging buffer for the data, this routine is necessary to force      *\n *    all staging buffers to be clear. This routine is called when the pipe is being           *\n *    destroyed.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes output at the far distant final end of the pipe   *\n *          chain.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Pipe::Flush(void)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Flush());\n\t}\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "REDALERT/PIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PIPE.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/29/96                                                     *\n *                                                                                             *\n *                  Last Update : June 29, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef PIPE_H\n#define PIPE_H\n\n#include\t<stddef.h>\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n/*\n**\tA \"push through\" pipe interface abstract class used for such purposes as compression\n**\tand translation of data. In STL terms, this is functionally similar to an output\n**\titerator but with a few enhancements. A pipe class object that is not derived into\n**\tanother useful class serves only as a pseudo null-pipe. It will accept data but\n**\tjust throw it away but pretend that it sent it somewhere.\n*/\nclass Pipe\n{\n\tpublic:\n\t\tPipe(void) : ChainTo(0), ChainFrom(0) {}\n\t\tvirtual ~Pipe(void);\n\n\t\tvirtual int Flush(void);\n\t\tvirtual int End(void) {return(Flush());}\n\t\tvirtual void Put_To(Pipe * pipe);\n\t\tvoid Put_To(Pipe & pipe) {Put_To(&pipe);}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t/*\n\t\t**\tPointer to the next pipe segment in the chain.\n\t\t*/\n\t\tPipe * ChainTo;\n\t\tPipe * ChainFrom;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tDisable the copy constructor and assignment operator.\n\t\t*/\n\t\tPipe(Pipe & rvalue);\n\t\tPipe & operator = (Pipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/PK.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PK.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PK.CPP                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKey::Decode_Exponent -- Decodes the exponent back into the key.                          *\n *   PKey::Decode_Modulus -- Decodes the modulus value back into the key.                      *\n *   PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext.                 *\n *   PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer.            *\n *   PKey::Encode_Modulus -- Encode the modulus portion of the key.                            *\n *   PKey::Encrypt -- Encrypt blocks of plaintext.                                             *\n *   PKey::Generate -- Generate a public and private key.                                      *\n *   PKey::PKey -- Construct a key using encoded strings.                                      *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"pk.h\"\n#include\t\"rndstraw.h\"\n\n\n/***********************************************************************************************\n * PKey::PKey -- Construct a key using encoded strings.                                        *\n *                                                                                             *\n *    This constructor will construct a key based on the encoded strings supplied.             *\n *                                                                                             *\n * INPUT:   exponent -- The encoded string for the exponent portion of the key.                *\n *                                                                                             *\n *          modulus  -- The encoded string for the modulus portion of the key.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKey::PKey(void const * exponent, void const * modulus)\n{\n\tModulus.DERDecode((unsigned char *)modulus);\n\tExponent.DERDecode((unsigned char *)exponent);\n\tBitPrecision = Modulus.BitCount()-1;\n}\n\n\n/***********************************************************************************************\n * PKey::Encode_Modulus -- Encode the modulus portion of the key.                              *\n *                                                                                             *\n *    This will store the modulus portion of the key into a buffer. The number of bytes        *\n *    stored into the buffer depends on the value of the key.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will hold the encoded modulus value.        *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored to the buffer.                             *\n *                                                                                             *\n * WARNINGS:   Be sure that the buffer can hold the encoded bytes. This is normally around the *\n *             same size as the Crypt_Block_Size() (plus a byte or two).                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encode_Modulus(void * buffer) const\n{\n\tif (buffer == NULL) {\n\t\treturn(0);\n\t}\n\treturn(Modulus.DEREncode((unsigned char *)buffer));\n}\n\n\n/***********************************************************************************************\n * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer.              *\n *                                                                                             *\n *    This routine will encode the exponent portion of the key. This is only necessary for the *\n *    slow key since the fast key always has an exponent of 65537.                             *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that will be filled with the encoded exponent.   *\n *                                                                                             *\n * OUTPUT:  Returns with the nuber of bytes stored into the buffer.                            *\n *                                                                                             *\n * WARNINGS:   Be sure the buffer is big enough to hold the encoded exponent. Usually this is  *\n *             about the same size as the Crypt_Block_Size (plus a byte or two).               *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encode_Exponent(void * buffer) const\n{\n\tif (buffer == NULL) {\n\t\treturn(0);\n\t}\n\treturn(Exponent.DEREncode((unsigned char *)buffer));\n}\n\n\n/***********************************************************************************************\n * PKey::Decode_Modulus -- Decodes the modulus value back into the key.                        *\n *                                                                                             *\n *    This is the counterpart to the Encode_Modulus() function. It will initialize the         *\n *    modulus portion of the key with the encoded data supplied.                               *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the previously encoded modulus value. *\n *                                                                                             *\n * OUTPUT:  void                                                                               *\n *                                                                                             *\n * WARNINGS:   void                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKey::Decode_Modulus(void * buffer)\n{\n\tModulus.DERDecode((unsigned char *)buffer);\n\tBitPrecision = Modulus.BitCount()-1;\n}\n\n\n/***********************************************************************************************\n * PKey::Decode_Exponent -- Decodes the exponent back into the key.                            *\n *                                                                                             *\n *    This is the counterpart to the Encode_Exponent function. It will decode a previously     *\n *    encoded exponent portion back into the key.                                              *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer that holds the encoded exponent value.           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKey::Decode_Exponent(void * buffer)\n{\n\tExponent.DERDecode((unsigned char *)buffer);\n}\n\n\n/***********************************************************************************************\n * PKey::Generate -- Generate a public and private key.                                        *\n *                                                                                             *\n *    Public key cryptography relies on having two paired keys. The key used to encrypt        *\n *    data must be decrypted by using the other key. Which key designated as the public or     *\n *    private key is arbitrary. However, one is faster than the other. Use the faster key for  *\n *    the more common operation.                                                               *\n *                                                                                             *\n * INPUT:   random   -- Reference to a source of random data.                                  *\n *                                                                                             *\n *          bits     -- The number of bits to use for key generation. Use a number greater     *\n *                      than 16 but less than 2048. The ideal bit size is one that is evenly   *\n *                      divisible by 8 and then add one. Practical numbers range from 65 to    *\n *                      1025 bits.                                                             *\n *                                                                                             *\n *          fastkey  -- Reference to the key that has fast encryption/decryption properties.   *\n *                                                                                             *\n *          slowkey  -- Reference to the mate key of the other.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine can take a very long time. It can take MINUTES to generate a       *\n *             1024 bit key (even on a Pentium Pro 200Mghz machine).                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Must supply source of random data.                                       *\n *=============================================================================================*/\nvoid PKey::Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey)\n{\n\t//PG_TO_FIX\n\tfastkey;\n\tslowkey;\n#if (0)\n\t/*\n\t**\tKey generation consists of create a key pair and then testing the key\n\t**\tpair. If the test fails, then repeat the process. The test and repeat\n\t**\tmethod is required since the prime number generating process can't\n\t**\tguarantee the generation of a prime number -- it can only generate a\n\t**\thighly likely prime number.\n\t*/\n\tfor (;;) {\n\t\t/*\n\t\t**\tGenerate the two random prime numbers. This is the longest\n\t\t**\tstep.\n\t\t*/\n\t\tBigInt p = Generate_Prime(random, bits, &p);\n\t\tBigInt q = Generate_Prime(random, bits, &q);\n\n\t\t/*\n\t\t**\tThe exponent factors are easy to calculate from the prime numbers.\n\t\t*/\n\t\tBigInt e = Fast_Exponent();\n\t\tBigInt n = p * q;\n\t\tBigInt pqmin = (p-(unsigned short)1)*(q-(unsigned short)1);\n\t\tBigInt d = e.Inverse(pqmin);\n\n\t\t/*\n\t\t**\tStore the data into the key objects. Notice that the modulus is the\n\t\t**\tsame for both the fast and slow keys. Also notice that the exponent for\n\t\t**\tthe fast key is ALWAYS 65537. Given this, it is possible to economize the\n\t\t**\tfast key into being just the modulus and the slow key to being just the\n\t\t**\texponent (presuming the slow key also has access to the fast key so that\n\t\t**\tit can get the modulus).\n\t\t*/\n\t\tfastkey.Exponent = e;\n\t\tfastkey.Modulus = n;\n\t\tfastkey.BitPrecision = n.BitCount()-1;\n\n\t\tslowkey.Exponent = d;\n\t\tslowkey.Modulus = n;\n\t\tslowkey.BitPrecision = fastkey.BitPrecision;\n\n\t\t/*\n\t\t**\tTest the keys by encrypting a block of random bytes. If it decrypts\n\t\t**\tcorrectly, then a valid key pair has been generated -- bail.\n\t\t*/\n\t\tchar before[256];\n\t\tchar after[256];\n\n\t\tfor (int index = 0; index < fastkey.Plain_Block_Size(); index++) {\n\t\t\tbefore[index] = (char)rand();\n\t\t}\n\t\tfastkey.Encrypt(before, fastkey.Plain_Block_Size(), after);\n\t\tslowkey.Decrypt(after, slowkey.Crypt_Block_Size(), after);\n\n\t\t/*\n\t\t**\tCompare the pre and post processing buffer. A match indicates\n\t\t**\ta valid key pair.\n\t\t*/\n\t\tif (memcmp(before, after, fastkey.Plain_Block_Size()) == 0) break;\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * PKey::Encrypt -- Encrypt blocks of plaintext.                                               *\n *                                                                                             *\n *    This routine will encrypt the supplied plaintext into cyphertext by processing the input *\n *    in block. The source is processed in whole blocks. Partial blocks are not supported by   *\n *    public key cryptography.                                                                 *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the source plaintext that will be encrypted.                *\n *                                                                                             *\n *          length   -- The length of the plaintext to encrypt.                                *\n *                                                                                             *\n *          dest     -- Pointer to the buffer that will hold the encrypted data.               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of cypher text bytes placed into the destination buffer.   *\n *                                                                                             *\n * WARNINGS:   Be sure that the destination buffer is big enough to hold the output.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Encrypt(void const * source, int slen, void * dest) const\n{\n\tint total = 0;\n\n\t/*\n\t**\tEncrypt the source data in full blocks. Partial blocks are not processed and are not\n\t**\tcopied to the destination buffer.\n\t*/\n\twhile (slen >= Plain_Block_Size()) {\n\n\t\t/*\n\t\t**\tPerform the encryption of the block.\n\t\t*/\n\t\tBigInt temp = 0;\n\t\tmemmove(&temp, source, Plain_Block_Size());\n\t\ttemp = temp.exp_b_mod_c(Exponent, Modulus);\n\n\t\t/*\n\t\t**\tMove the cypher block to the destination.\n\t\t*/\n\t\tmemmove(dest, &temp, Crypt_Block_Size());\n\t\tslen -= Plain_Block_Size();\n\t\tsource = (char *)source + Plain_Block_Size();\n\t\tdest = (char *)dest + Crypt_Block_Size();\n\t\ttotal += Crypt_Block_Size();\n\t}\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext.                   *\n *                                                                                             *\n *    This routine will process the supplied cyphertext by breaking it up into blocks and      *\n *    then decrypting each block in turn. The block size is dependant upon the key. By NOT     *\n *    embedding this information into the cypher data, it makes the encryption more secure.    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the cypher text to be decrypted.                            *\n *                                                                                             *\n *          length   -- The number of cypher text bytes supplied to this routine.              *\n *                                                                                             *\n *          dest     -- Pointer to the buffer to hold the plaintext.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of plaintext bytes output to the destination buffer.       *\n *                                                                                             *\n * WARNINGS:   Only whole blocks are processed. If the source has any partial block sized      *\n *             data, then it will be left unprocessed.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKey::Decrypt(void const * source, int slen, void * dest) const\n{\n\tint total = 0;\n\tBigInt temp;\n\n\t/*\n\t**\tDecrypt the source data in full blocks. Partial blocks are not processed in any way.\n\t*/\n\twhile (slen >= Crypt_Block_Size()) {\n\n\t\t/*\n\t\t**\tPerform the encryption.\n\t\t*/\n\t\ttemp = 0;\n\t\tmemmove(&temp, source, Crypt_Block_Size());\n\t\ttemp = temp.exp_b_mod_c(Exponent, Modulus);\n\n\t\t/*\n\t\t**\tMove the cypher block to the destination.\n\t\t*/\n\t\tmemmove(dest, &temp, Plain_Block_Size());\n\t\tslen -= Crypt_Block_Size();\n\t\tsource = (char *)source + Crypt_Block_Size();\n\t\tdest = (char *)dest + Plain_Block_Size();\n\t\ttotal += Plain_Block_Size();\n\t}\n\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/PK.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PK.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PK.H                                                         *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/03/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PK_H\n#define PK_H\n\n#include\t\"int.h\"\n\n/*\n**\tThis class holds a public or private key used in Public Key Cryptography. It also serves\n**\tas the conduit for encrypting/decrypting data using that key. Cryptography, using this\n**\tmethod, has a couple of characteristics that affect how it is used. One, the process of\n**\tencrypting/decrypting is very slow. This limits the effective quantity of data that can\n**\tbe processed. Two, the ciphertext is larger than the plaintext. This property generally\n**\tlimits its use to streaming data as opposed to random access data. The data is processed\n**\tin blocks. The size of the ciphertext and plaintext blocks can be determined only from\n**\tthe key itself.\n**\n**\tA reasonable use of this technology would be to encrypt only critical data such as the\n**\tpassword for a fast general purpose cryptographic algorithm.\n*/\nclass PKey\n{\n\tpublic:\n\t\tPKey(void) : Modulus(0), Exponent(0), BitPrecision(0) {}\n\t\tPKey(void const * exponent, void const * modulus);\t\t// DER initialization.\n\n\t\tint Encrypt(void const * source, int slen, void * dest) const;\n\t\tint Decrypt(void const * source, int slen, void * dest) const;\n\n\t\tstatic void Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey);\n\n\t\tint Plain_Block_Size(void) const {return((BitPrecision-1)/8);}\n\t\tint Crypt_Block_Size(void) const {return(Plain_Block_Size()+1);}\n\t\tint Block_Count(int plaintext_length) const {return((((plaintext_length-1)/Plain_Block_Size())+1));}\n\n\t\tint Encode_Modulus(void * buffer) const;\n\t\tint Encode_Exponent(void * buffer) const;\n\n\t\tvoid Decode_Modulus(void * buffer);\n\t\tvoid Decode_Exponent(void * buffer);\n\n\t\tstatic long Fast_Exponent(void) {return(65537L);}\n\n\tprivate:\n\n\t\t// p*q\n\t\tBigInt Modulus;\n\n\t\t// 65537 or\n\t\t// inverse of (p-1)(q-1).\n\t\tBigInt Exponent;\n\n\t\t// Maximum bits allowed for block.\n\t\tint BitPrecision;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/PKPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PKPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                                                                                             *\n *                    File Name : PKPIPE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/07/96                                                     *\n *                                                                                             *\n *                  Last Update : July 12, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length.                           *\n *   PKPipe::Key -- Submit a key to enable processing of data flow.                            *\n *   PKPipe::PKPipe -- Constructor for the public key pipe object.                             *\n *   PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key.                   *\n *   PKPipe::Put -- Submit data to the pipe for processing.                                    *\n *   PKPipe::Put_To -- Chains one pipe to another.                                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"pkpipe.h\"\n\n\n/***********************************************************************************************\n * PKPipe::PKPipe -- Constructor for the public key pipe object.                               *\n *                                                                                             *\n *    This will construct the public key pipe object.                                          *\n *                                                                                             *\n * INPUT:   control  -- The method used to process the data flow (encrypt or decrypt).         *\n *                                                                                             *\n *          rnd      -- Reference to a random number generate used to create the internal      *\n *                      blowfish key.                                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKPipe::PKPipe(CryptControl control, RandomStraw & rnd) :\n\tIsGettingKey(true),\n\tRand(rnd),\n\tBF((control == ENCRYPT) ? BlowPipe::ENCRYPT : BlowPipe::DECRYPT),\n\tControl(control),\n\tCipherKey(NULL),\n\tCounter(0),\n\tBytesLeft(0)\n{\n}\n\n\n/***********************************************************************************************\n * PKPipe::Put_To -- Chains one pipe to another.                                               *\n *                                                                                             *\n *    This handles linking of one pipe to this pipe. Data will flow from this PKPipe to the    *\n *    pipe segment specified. Special handling is done so that piping actually flows to the    *\n *    embedded blowfish pipe and then flows to the designated pipe.                            *\n *                                                                                             *\n * INPUT:   pipe  -- Pointer to the pipe that this pipe segment is to send data to.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKPipe::Put_To(Pipe * pipe)\n{\n\tif (BF.ChainTo != pipe) {\n\t\tif (pipe != NULL && pipe->ChainFrom != NULL) {\n\t\t\tpipe->ChainFrom->Put_To(NULL);\n\t\t\tpipe->ChainFrom = NULL;\n\t\t}\n\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = NULL;\n\t\t}\n\t\tBF.ChainTo = pipe;\n\t\tif (pipe != NULL) {\n\t\t\tpipe->ChainFrom = &BF;\n\t\t}\n\t\tBF.ChainFrom = this;\n\t\tChainTo = &BF;\n\t}\n}\n\n\n/***********************************************************************************************\n * PKPipe::Key -- Submit a key to enable processing of data flow.                              *\n *                                                                                             *\n *    This routine must be called with a valid key pointer in order for encryption/description *\n *    to be performed on the data stream. Prior to calling this routine or after calling this  *\n *    routine with a NULL pointer, the data stream will pass through this pipe without         *\n *    modification.                                                                            *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to use for processing. Pass NULL if process is to be   *\n *                   terminated.                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKPipe::Key(PKey const * key)\n{\n\tif (key == NULL) {\n\t\tFlush();\n\t\tIsGettingKey = false;\n\t}\n\tCipherKey = key;\n\n\tif (CipherKey != NULL) {\n\t\tIsGettingKey = true;\n\t\tif (Control == DECRYPT) {\n\t\t\tCounter = BytesLeft = Encrypted_Key_Length();\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * PKPipe::Put -- Submit data to the pipe for processing.                                      *\n *                                                                                             *\n *    This routine (if processing as been enabled by a previous key submission) will           *\n *    encrypt or decrypt the data stream that passes through it. When encrypting, the data     *\n *    stream will increase in size by about 10% (bit it varies according to the key used).     *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to be submitted to the pipe stream.                *\n *                                                                                             *\n *          length   -- The number of bytes submitted.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of byte output at the final end of the pipe.        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/07/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Put(void const * source, int length)\n{\n\t/*\n\t**\tIf the parameter seem illegal, then pass the pipe request to the\n\t**\tnext pipe in the chain and let them deal with it.\n\t*/\n\tif (source == NULL || length < 1 || CipherKey == NULL) {\n\t\treturn(Pipe::Put(source, length));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tPerform a special process if the this is the first part of the data flow. The special\n\t**\tkey must be processed first. After this initial key processing, the rest of the data flow\n\t**\tis processed by the blowfish pipe and ignored by the PKPipe.\n\t*/\n\tif (IsGettingKey) {\n\n\t\t/*\n\t\t**\tWhen encrypting, first make the key block and then pass the data through the\n\t\t**\tnormal blowfish processor.\n\t\t*/\n\t\tif (Control == ENCRYPT) {\n\n\t\t\t/*\n\t\t\t**\tGenerate the largest blowfish key possible.\n\t\t\t*/\n\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tmemset(buffer, '\\0', sizeof(buffer));\n\t\t\tRand.Get(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t/*\n\t\t\t**\tEncrypt the blowfish key (along with any necessary pad bytes).\n\t\t\t*/\n\t\t\tint didput = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);\n\t\t\ttotal += Pipe::Put(Buffer, didput);\n\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\tIsGettingKey = false;\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tFirst try to accumulate a full key.\n\t\t\t*/\n\t\t\tint toget = (BytesLeft < length) ? BytesLeft : length;\n\t\t\tmemmove(&Buffer[Counter-BytesLeft], source, toget);\n\t\t\tlength -= toget;\n\t\t\tBytesLeft -= toget;\n\t\t\tsource = (char *)source + toget;\n\n\t\t\t/*\n\t\t\t**\tIf a full key has been accumulated, then decrypt it and feed the\n\t\t\t**\tkey to the blowfish engine.\n\t\t\t*/\n\t\t\tif (BytesLeft == 0) {\n\t\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\t\tCipherKey->Decrypt(Buffer, Counter, buffer);\n\t\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t\tIsGettingKey = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are any remaining bytes to pipe through, then\n\t**\tpipe them through now -- they will be processed by the\n\t**\tblowfish engine.\n\t*/\n\ttotal += Pipe::Put(source, length);\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length.                             *\n *                                                                                             *\n *    This returns the total number of bytes (after encryption) that the blowfish key will     *\n *    consume. It should be possible to get a block of this size, then pass it to the          *\n *    public key decrypter and the result will be the full blowfish key.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the encrypted blowfish key required.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Encrypted_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());\n}\n\n\n/***********************************************************************************************\n * PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key.                     *\n *                                                                                             *\n *    This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *\n *    is actually the number of plain blocks minimum that can contain the full blowfish        *\n *    key. The public key cryptography system encrypts in whole blocks only.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes that will contain the full blowfish key     *\n *          and still be an even block size for the public key cryptography process.           *\n *                                                                                             *\n * WARNINGS:   This value is probably be larger than the actual blowfish key length.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKPipe::Plain_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());\n}\n"
  },
  {
    "path": "REDALERT/PKPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PKPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKPIPE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/06/96                                                     *\n *                                                                                             *\n *                  Last Update : July 6, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef PKPIPE_H\n#define PKPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"pk.h\"\n#include \"rndstraw.h\"\n#include\t\"blowpipe.h\"\n\n\n/*\n**\tThis pipe will encrypt/decrypt the data stream. The data is encrypted by generating a\n**\tsymetric key that is then encrypted using the public key system. This symetric key is then\n**\tused to encrypt the remaining data.\n*/\nclass PKPipe : public Pipe\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tPKPipe(CryptControl control, RandomStraw & rnd);\n\n\t\tvirtual void Put_To(Pipe * pipe);\n\t\tvirtual void Put_To(Pipe & pipe) {Put_To(&pipe);}\n\n\t\t// Feed data through for processing.\n\t\tvirtual int Put(void const * source, int length);\n\n\t\t// Submit key for encryption/decryption.\n\t\tvoid Key(PKey const * key);\n\n\tprivate:\n\t\tenum {\n\t\t\tBLOWFISH_KEY_SIZE=BlowfishEngine::MAX_KEY_LENGTH,\n\t\t\tMAX_KEY_BLOCK_SIZE=256\t\t// Maximum size of pk encrypted blowfish key.\n\t\t};\n\n\t\t/*\n\t\t**\tThis flag indicates whether the PK (fetch blowfish key) phase is\n\t\t**\tin progress or not.\n\t\t*/\n\t\tbool IsGettingKey;\n\n\t\t/*\n\t\t**\tThis is the random straw that is needed to generate the\n\t\t**\tblowfish key.\n\t\t*/\n\t\tRandomStraw & Rand;\n\n\t\t/*\n\t\t**\tThis is the attached blowfish pipe. After the blowfish key has been\n\t\t**\tdecrypted, then the PK processor goes dormant and the blowfish processor\n\t\t**\ttakes over the data flow.\n\t\t*/\n\t\tBlowPipe BF;\n\n\t\t/*\n\t\t**\tControls the method of processing the data stream.\n\t\t*/\n\t\tCryptControl Control;\n\n\t\t/*\n\t\t**\tPointer to the key to use for encryption/decryption. The actual process\n\t\t**\tperformed is controlled by the Control member. A key can be used for\n\t\t**\teither encryption or decryption -- it makes no difference. However, whichever\n\t\t**\tprocess is performed, the opposite process must be performed using the\n\t\t**\tother key.\n\t\t*/\n\t\tPKey const * CipherKey;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for the block of data. This block must be as large as\n\t\t**\tthe largest possible key size or the largest blowfish key (whichever is greater).\n\t\t*/\n\t\tchar Buffer[MAX_KEY_BLOCK_SIZE];\n\n\t\t/*\n\t\t**\tThe working counter that holds the number of bytes in the staging buffer.\n\t\t*/\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tThis records the number of bytes remaining in the current block. This\n\t\t**\twill be the number of bytes left to accumulate before the block can be\n\t\t**\tprocessed either for encryption or decryption.\n\t\t*/\n\t\tint BytesLeft;\n\n\t\tint Encrypted_Key_Length(void) const;\n\t\tint Plain_Key_Length(void) const;\n\n\t\tPKPipe(PKPipe & rvalue);\n\t\tPKPipe & operator = (PKPipe const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/PKSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PKSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKSTRAW.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/08/96                                                     *\n *                                                                                             *\n *                  Last Update : July 11, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length.                          *\n *   PKStraw::Get -- Fetch data and process it accordingly.                                    *\n *   PKStraw::Get_From -- Chains one straw to another.                                         *\n *   PKStraw::Key -- Assign a key to the cipher process straw.                                 *\n *   PKStraw::PKStraw -- Initialize the public key straw object.                               *\n *   PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include \"pkstraw.h\"\n#include\t\"rndstraw.h\"\n#include\t\"blwstraw.h\"\n\n\n/***********************************************************************************************\n * PKStraw::PKStraw -- Initialize the public key straw object.                                 *\n *                                                                                             *\n *    This constructs the public key straw object. The operation to perform (encrypt or        *\n *    decrypt) as well as a random number generator must be provided.                          *\n *                                                                                             *\n * INPUT:   control  -- What operation to perform on the data. Pass in either ENCRYPT or       *\n *                      DECRYPT.                                                               *\n *                                                                                             *\n *          rnd      -- Reference to a random number straw that is used internally to          *\n *                      generate the sub-key. The final strength of the cipher depends on      *\n *                      quality of this random number generator.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nPKStraw::PKStraw(CryptControl control, RandomStraw & rnd) :\n\tIsGettingKey(true),\n\tRand(rnd),\n\tBF((control == ENCRYPT) ? BlowStraw::ENCRYPT : BlowStraw::DECRYPT),\n\tControl(control),\n\tCipherKey(NULL),\n\tCounter(0),\n\tBytesLeft(0)\n{\n\tStraw::Get_From(BF);\n}\n\n\n/***********************************************************************************************\n * PKStraw::Get_From -- Chains one straw to another.                                           *\n *                                                                                             *\n *    This routine handles the special case of this straw object in that there is an           *\n *    embedded blowfish straw segment. It must be chained on correctly.                        *\n *                                                                                             *\n * INPUT:   straw -- Pointer to the straw segment that this segment is to receive data from.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKStraw::Get_From(Straw * straw)\n{\n\tif (BF.ChainTo != straw) {\n\t\tif (straw != NULL && straw->ChainFrom != NULL) {\n\t\t\tstraw->ChainFrom->Get_From(NULL);\n\t\t\tstraw->ChainFrom = NULL;\n\t\t}\n\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = NULL;\n\t\t}\n\n\t\tBF.ChainTo = straw;\n\t\tBF.ChainFrom = this;\n\t\tChainTo = &BF;\n\t\tif (BF.ChainTo != NULL) {\n\t\t\tBF.ChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n\n/***********************************************************************************************\n * PKStraw::Key -- Assign a key to the cipher process straw.                                   *\n *                                                                                             *\n *    This routine will assign the key (or NULL if the current key is to be removed) to the    *\n *    cipher stream process. When a key has been assigned, encryption or decryption will       *\n *    take place. In the absence (NULL key pointer) of a key, the data passes through          *\n *    unchanged.                                                                               *\n *                                                                                             *\n * INPUT:   key   -- Pointer to the key to assign to the stream. If the key pointer is NULL,   *\n *                   then this causes the cipher stream to stop processing the data and will   *\n *                   pass the data through unchanged.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure that the key passed to this routine is the opposite key to that used    *\n *             to process the stream originally (when decrypting).                             *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PKStraw::Key(PKey const * key)\n{\n\tCipherKey = key;\n\tif (key != NULL) {\n\t\tIsGettingKey = true;\n\t}\n\tCounter = 0;\n\tBytesLeft = 0;\n}\n\n\n/***********************************************************************************************\n * PKStraw::Get -- Fetch data and process it accordingly.                                      *\n *                                                                                             *\n *    This routine will fetch the number of bytes requested. If a valid key has been assigned  *\n *    to this stream, then the data will be processed as it passes through.                    *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the requested data.               *\n *                                                                                             *\n *          length   -- The number of data bytes requested.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of data bytes stored to the destination buffer. If  *\n *          this number is less than that requested, then it indicates that the data source    *\n *          has been exhausted.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Get(void * source, int length)\n{\n\t/*\n\t**\tIf the parameters seem invalid, then pass the request on so that someone\n\t**\telse can deal with it.\n\t*/\n\tif (source == NULL || length < 1 || CipherKey == NULL) {\n\t\treturn(Straw::Get(source, length));\n\t}\n\n\tint total = 0;\n\n\t/*\n\t**\tThe first part of the data flow must process the special key. After the special\n\t**\tkey has been processed, the data flows through this straw without direct\n\t**\tmodification (the blowfish straw will process the data).\n\t*/\n\tif (IsGettingKey) {\n\n\t\tif (Control == DECRYPT) {\n\n\t\t\t/*\n\t\t\t**\tRetrieve the pk encrypted blowfish key block.\n\t\t\t*/\n\t\t\tchar cbuffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tint got = Straw::Get(cbuffer, Encrypted_Key_Length());\n\n\t\t\t/*\n\t\t\t**\tIf the entire key block could not be retrieved, then this indicates\n\t\t\t**\ta major data flow error -- just return with no action performed.\n\t\t\t*/\n\t\t\tif (got != Encrypted_Key_Length()) return(0);\n\n\t\t\t/*\n\t\t\t**\tDecrypt the blowfish key and then activate the blowfish straw\n\t\t\t**\twith that key.\n\t\t\t*/\n\t\t\tCipherKey->Decrypt(cbuffer, got, Buffer);\n\t\t\tBF.Key(Buffer, BLOWFISH_KEY_SIZE);\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tGenerate the blowfish key by using random numbers.\n\t\t\t*/\n\t\t\tchar buffer[MAX_KEY_BLOCK_SIZE];\n\t\t\tmemset(buffer, '\\0', sizeof(buffer));\n\t\t\tRand.Get(buffer, BLOWFISH_KEY_SIZE);\n\n\t\t\t/*\n\t\t\t**\tEncrypt the blowfish key (along with any necessary pad bytes).\n\t\t\t*/\n\t\t\tCounter = BytesLeft = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);\n\t\t\tBF.Key(buffer, BLOWFISH_KEY_SIZE);\n\t\t}\n\n\t\t/*\n\t\t**\tThe first phase of getting the special key has been accomplished. Now, all\n\t\t**\tsubsequent data is passed (unmodified) though this straw segment. The blowfish\n\t\t**\tstraw takes over the compression/decompression from this point forward.\n\t\t*/\n\t\tIsGettingKey = false;\n\t}\n\n\t/*\n\t**\tIf there are any pending bytes in the buffer, then pass\n\t**\tthese on first. The only time this should be is when the blowfish\n\t**\tkey has first been generated.\n\t*/\n\tif (BytesLeft > 0) {\n\t\tint tocopy = (length < BytesLeft) ? length : BytesLeft;\n\t\tmemmove(source, &Buffer[Counter-BytesLeft], tocopy);\n\t\tsource = (char *)source + tocopy;\n\t\tBytesLeft -= tocopy;\n\t\tlength -= tocopy;\n\t\ttotal += tocopy;\n\t}\n\n\t/*\n\t**\tAny requested bytes that haven't been satisfied are copied over now by\n\t**\tdrawing the data through the blowfish engine. The blowfish engine happens\n\t**\tto be linked to the chain so a normal Get() operation is sufficient.\n\t*/\n\ttotal += Straw::Get(source, length);\n\n\treturn(total);\n}\n\n\n/***********************************************************************************************\n * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length.                            *\n *                                                                                             *\n *    This returns the total number of bytes (after encryption) that the blowfish key will     *\n *    consume. It should be possible to get a block of this size, then pass it to the          *\n *    public key decrypter and the result will be the full blowfish key.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the encrypted blowfish key required.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Encrypted_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());\n}\n\n\n/***********************************************************************************************\n * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key.                    *\n *                                                                                             *\n *    This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *\n *    is actually the number of plain blocks minimum that can contain the full blowfish        *\n *    key. The public key cryptography system encrypts in whole blocks only.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the total number of bytes that will contain the full blowfish key     *\n *          and still be an even block size for the public key cryptography process.           *\n *                                                                                             *\n * WARNINGS:   This value is probably be larger than the actual blowfish key length.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PKStraw::Plain_Key_Length(void) const\n{\n\tif (CipherKey == NULL) return(0);\n\treturn(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());\n}\n"
  },
  {
    "path": "REDALERT/PKSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PKSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PKSTRAW.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/08/96                                                     *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef PKSTRAW_H\n#define PKSTRAW_H\n\n#include\t\"pk.h\"\n#include \"pkstraw.h\"\n#include \"rndstraw.h\"\n#include\t\"blwstraw.h\"\n\nclass PKStraw : public Straw\n{\n\tpublic:\n\t\ttypedef enum CryptControl {\n\t\t\tENCRYPT,\n\t\t\tDECRYPT\n\t\t} CryptControl;\n\n\t\tPKStraw(CryptControl control, RandomStraw & rnd);\n\n\t\tvirtual void Get_From(Straw * straw);\n\t\tvirtual void Get_From(Straw & straw) {Get_From(&straw);}\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Submit key to be used for encryption/decryption.\n\t\tvoid Key(PKey const * key);\n\n\tprivate:\n\t\tenum {\n\t\t\tBLOWFISH_KEY_SIZE=BlowfishEngine::MAX_KEY_LENGTH,\n\t\t\tMAX_KEY_BLOCK_SIZE=256\t\t// Maximum size of pk encrypted blowfish key.\n\t\t};\n\n\t\t/*\n\t\t**\tThis flag indicates whether the PK (fetch blowfish key) phase is\n\t\t**\tin progress or not.\n\t\t*/\n\t\tbool IsGettingKey;\n\n\t\t/*\n\t\t**\tThis is the random straw that is needed to generate the\n\t\t**\tblowfish key.\n\t\t*/\n\t\tRandomStraw & Rand;\n\n\t\t/*\n\t\t**\tThis is the attached blowfish pipe. After the blowfish key has been\n\t\t**\tdecrypted, then the PK processor goes dormant and the blowfish processor\n\t\t**\ttakes over the data flow.\n\t\t*/\n\t\tBlowStraw BF;\n\n\t\t/*\n\t\t**\tThis control member tells what method (encryption or decryption) that should\n\t\t**\tbe performed on the data stream.\n\t\t*/\n\t\tCryptControl Control;\n\n\t\t/*\n\t\t**\tPointer to the key to use for encryption or decryption. If this pointer is NULL, then\n\t\t**\tthe data passing through this segment will not be modified.\n\t\t*/\n\t\tPKey const * CipherKey;\n\n\t\t/*\n\t\t**\tThis is the staging buffer for the block of data. This block must be as large as\n\t\t**\tthe largest possible key size or the largest blowfish key size (whichever is\n\t\t**\tgreater).\n\t\t*/\n\t\tchar Buffer[256];\n\n\t\tint Counter;\n\n\t\t/*\n\t\t**\tThis records the number of bytes remaining in the current block. This\n\t\t**\twill be the number of bytes left to accumulate before the block can be\n\t\t**\tprocessed either for encryption or decryption.\n\t\t*/\n\t\tint BytesLeft;\n\n\t\tint Encrypted_Key_Length(void) const;\n\t\tint Plain_Key_Length(void) const;\n\n\t\tPKStraw(PKStraw & rvalue);\n\t\tPKStraw & operator = (PKStraw const & straw);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/POWER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/POWER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : POWER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : October 14, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   PowerClass::AI -- Process the power bar logic.                                            *\n *   PowerClass::Draw_It -- Renders the power bar graphic.                                     *\n *   PowerClass::Init_Clear -- Clears all the power bar variables.                             *\n *   PowerClass::One_Time -- One time processing for the power bar.                            *\n *   PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area.        *\n *   PowerClass::PowerClass -- Default constructor for the power bar class.                    *\n *   PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. *\n *   PowerClass::Power_Height -- Given a value figure where it falls on bar                    *\n *   PowerClass::Flash_Power -- Flag the power bar to flash.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tPoints to the shape to use for the \"desired\" power level indicator.\n*/\nvoid const * PowerClass::PowerShape;\nvoid const * PowerClass::PowerBarShape;\n\nPowerClass::PowerButtonClass PowerClass::PowerButton;\n\n\n/***********************************************************************************************\n * PowerClass::PowerClass -- Default constructor for the power bar class.                      *\n *                                                                                             *\n *    This is the default constructor for the power bar class. It doesn't really do anything.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nPowerClass::PowerClass(void) :\n\tIsToRedraw(false),\n\tIsActive(false),\n\tFlashTimer(0),\n\tRecordedDrain(-1),\n\tRecordedPower(-1),\n\tDesiredDrainHeight(0),\n\tDesiredPowerHeight(0),\n\tDrainHeight(0),\n\tPowerHeight(0),\n\tDrainBounce(0),\n\tPowerBounce(0),\n\tPowerDir(0),\n\tDrainDir(0)\n{\n}\n\n\n/***********************************************************************************************\n * PowerClass::Init_Clear -- Clears all the power bar variables.                               *\n *                                                                                             *\n *    This routine is called in preparation for the start of a scenario. The power bar is      *\n *    initialized into the null state by this routine. As soon as the scenario starts, the     *\n *    power bar will rise to reflect the actual power output and drain.                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Init_Clear(void)\n{\n\tRadarClass::Init_Clear();\n\tRecordedDrain = -1;\n\tRecordedPower = -1;\n\tDesiredDrainHeight = 0;\n\tDesiredPowerHeight = 0;\n\tDrainHeight = 0;\n\tPowerHeight = 0;\n\tPowerBounce = 0;\n\tDrainBounce = 0;\n\tDrainDir = 0;\n\tPowerDir = 0;\n\tFlashTimer = 0;\n}\n\n\n/***********************************************************************************************\n * PowerClass::One_Time -- One time processing for the power bar.                              *\n *                                                                                             *\n * This routine is for code that truly only needs to be done once per game run.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/26/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::One_Time(void)\n{\n\tRadarClass::One_Time();\n\tPowerButton.X = POWER_X * RESFACTOR;\n\tPowerButton.Y = POWER_Y * RESFACTOR;\n\tPowerButton.Width = (POWER_WIDTH * RESFACTOR)-1;\n\tPowerButton.Height = POWER_HEIGHT * RESFACTOR;\n\tPowerShape = MFCD::Retrieve(\"POWER.SHP\");\n\tPowerBarShape = MFCD::Retrieve(\"POWERBAR.SHP\");\n}\n\n\n/***********************************************************************************************\n * PowerClass::Draw_It -- Renders the power bar graphic.                                       *\n *                                                                                             *\n *    This routine will draw the power bar graphic to the LogicPage.                           *\n *                                                                                             *\n * INPUT:   complete -- Should the power bar be redrawn even if it isn't specifically flagged  *\n *                      to do so?                                                              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *   12/27/1994 JLB : Changes power bar color depending on amount of power.                    *\n *=============================================================================================*/\nvoid PowerClass::Draw_It(bool complete)\n{\n\tstatic int _modtable[]={\n\t\t0, -1, 0, 1, 0, -1, -2, -1, 0, 1, 2, 1 ,0\n\t};\n\n\tif (complete || IsToRedraw) {\n\t\tBStart(BENCH_POWER);\n\n\t\tif (LogicPage->Lock()) {\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tIsToRedraw = false;\n\t\t\t\tShapeFlags_Type flags = SHAPE_NORMAL;\n\t\t\t\tvoid const * remap = NULL;\n\n\t\t\t\tif (FlashTimer > 1 && ((FlashTimer % 3) & 0x01) != 0) {\n\t\t\t\t\tflags = flags | SHAPE_FADING;\n\t\t\t\t\tremap = Map.FadingRed;\n\t\t\t\t}\n\n//\t\t\t\tLogicPage->Fill_Rect(POWER_X, POWER_Y, POWER_X+POWER_WIDTH-1, POWER_Y+POWER_HEIGHT-1, LTGREY);\n\t\t\t\tCC_Draw_Shape(PowerBarShape, 0, 240 * RESFACTOR, 88 * RESFACTOR, WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);\n\n#ifdef WIN32\n\t\t\t\t/*\n\t\t\t\t** Hires power strip is too big to fit into a shape so it is in two parts\n\t\t\t\t*/\n\t\t\t\tCC_Draw_Shape(PowerBarShape, 1, 240 * RESFACTOR, (88 * RESFACTOR) + (56*RESFACTOR), WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);\n#endif\n\t\t\t\t/*\n\t\t\t\t**\tDetermine how much the power production exceeds or falls short\n\t\t\t\t**\tof power demands.\n\t\t\t\t*/\n\t\t\t\tint bottom       = (POWER_Y + POWER_HEIGHT - 1) * RESFACTOR;\n\t\t\t\tint power_height  = (PowerHeight == DesiredPowerHeight) ? PowerHeight + (_modtable[PowerBounce] * PowerDir) : PowerHeight;\n\t\t\t\tint drain_height  = (DrainHeight == DesiredDrainHeight) ? DrainHeight + (_modtable[DrainBounce] * DrainDir) : DrainHeight;\n\t\t\t\tpower_height = Bound(power_height, 0, POWER_HEIGHT - 2);\n\t\t\t\tdrain_height = Bound(drain_height, 0, POWER_HEIGHT - 2);\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the power output graphic on top of the power bar framework.\n\t\t\t\t*/\n\t\t\t\tif (power_height) {\n\t\t\t\t\tint color1 = 3;\n\t\t\t\t\tint color2 = 4;\n\n\t\t\t\t\tif (PlayerPtr->Drain > PlayerPtr->Power) {\n\t\t\t\t\t\tcolor1 = 214;\n\t\t\t\t\t\tcolor2 = 211;\n\t\t\t\t\t}\n\t\t\t\t\tif (PlayerPtr->Drain > (PlayerPtr->Power * 2)) {\n\t\t\t\t\t\tcolor1 = 235;\n\t\t\t\t\t\tcolor2 = 230;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t** New power bar is in slightly different place\n\t\t\t\t\t**\n\t\t\t\t\t** Old power bar was 107 pixels high. New bar is 153 pixels high.\n\t\t\t\t\t**\n\t\t\t\t\t** ST - 5/2/96 11:23AM\n\t\t\t\t\t*/\n#ifdef WIN32\n\t\t\t\t\tpower_height = (power_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);\n\t\t\t\t\tdrain_height = (drain_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);\n#endif\n\t\t\t\t\tbottom = (175*RESFACTOR)+1;\n\n\t\t\t\t\tLogicPage->Fill_Rect(245*RESFACTOR, bottom-power_height, 245*RESFACTOR+1, bottom, color2);\n\t\t\t\t\tLogicPage->Fill_Rect(246*RESFACTOR, bottom-power_height, 246*RESFACTOR+1, bottom, color1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tDraw the power drain threshold marker.\n\t\t\t\t*/\n\t\t\t\tCC_Draw_Shape(PowerShape, 0, (POWER_X * RESFACTOR)+RESFACTOR, bottom - (drain_height + (2 * RESFACTOR)), WINDOW_MAIN, flags | SHAPE_NORMAL, remap);\n\t\t\t}\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t\tBEnd(BENCH_POWER);\n\t}\n\tRadarClass::Draw_It(complete);\n}\n\n\n/***********************************************************************************************\n * PowerClass::AI -- Process the power bar logic.                                              *\n *                                                                                             *\n *    Use this routine to process the power bar logic. This consists of animation effects.     *\n *                                                                                             *\n * INPUT:   input -- The player input value to be consumed or ignored as appropriate.          *\n *                                                                                             *\n *          x,y   -- Mouse coordinate parameters to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/20/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nvoid PowerClass::AI(KeyNumType &input, int x, int y)\n{\n\tif (Map.IsSidebarActive /*IsActive*/) {\n\t\tint olddrain = DrainHeight;\n\t\tint oldpower  = PowerHeight;\n\n\n\t\t/*\n\t\t** If the recorded power value has changed we need to adjust for\n\t\t** it.\n\t\t*/\n\t\tif (PlayerPtr->Power != RecordedPower) {\n\t\t\tDesiredPowerHeight = Power_Height(PlayerPtr->Power);\n\t\t\tRecordedPower\t\t = PlayerPtr->Power;\n\t\t\tPowerBounce\t\t\t = 12;\n\t\t\tif (PowerHeight > DesiredPowerHeight) {\n\t\t\t\tPowerDir = -1;\n\t\t\t} else if (PowerHeight < DesiredPowerHeight) {\n\t\t\t\tPowerDir = 1;\n\t\t\t} else {\n\t\t\t\tPowerBounce = 0;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** If the recorded drain value has changed we need to adjust for\n\t\t** it.\n\t\t*/\n\t\tif (PlayerPtr->Drain != RecordedDrain) {\n\t\t\tDesiredDrainHeight = Power_Height(PlayerPtr->Drain);\n\t\t\tRecordedDrain\t\t = PlayerPtr->Drain;\n\t\t\tDrainBounce\t\t\t = 12;\n\t\t\tif (DrainHeight > DesiredDrainHeight) {\n\t\t\t\tDrainDir = -1;\n\t\t\t} else if (DrainHeight < DesiredDrainHeight) {\n\t\t\t\tDrainDir = 1;\n\t\t\t} else {\n\t\t\t\tDrainBounce = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (DrainBounce && DrainHeight == DesiredDrainHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tDrainBounce--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If we need to move the drain height then do so.\n\t\t\t*/\n\t\t\tif (DrainHeight != DesiredDrainHeight) {\n\t\t\t\tDrainHeight += DrainDir;\n\t\t\t}\n\t\t}\n\n\t\tif (PowerBounce && PowerHeight == DesiredPowerHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tPowerBounce--;\n\t\t} else {\n\t\t\t/*\n\t\t\t** If we need to move the power height then do so.\n\t\t\t*/\n\t\t\tif (PowerHeight != DesiredPowerHeight) {\n\t\t\t\tPowerHeight += PowerDir;\n\t\t\t}\n\t\t}\n\n\t\tif (olddrain != DrainHeight || oldpower != PowerHeight) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\n\t\t/*\n\t\t**\tFlag to redraw if the power bar flash effect has expired.\n\t\t*/\n//\t\tif (FlashTimer == 1) {\n\t\tif (FlashTimer > 0) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\tRadarClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too.   *\n *                                                                                             *\n *    This routine will examine a refresh list request and determine if the sidebar would be   *\n *    affect. If so, it will flag the sidebar to be redrawn.                                   *\n *                                                                                             *\n * INPUT:   cell  -- The cell that the offset list is base on.                                 *\n *                                                                                             *\n *          list  -- The list of cell offset used to flag for redraw. If the special sidebar   *\n *                   affecting cell magic offset number is detected, the sidebar is flagged    *\n *                   for redraw and the magic offset is removed.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tRadarClass::Refresh_Cells(cell, list);\n}\n\n\n/***************************************************************************\n * PowerClass::Power_Height -- Given a value figure where it falls on bar  *\n *                                                                         *\n * INPUT:\t\tint value - the value we are testing                        *\n *                                                                         *\n * OUTPUT:     int the height of the point that this value is on graph     *\n *                                                                         *\n * WARNINGS:   none                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/14/1995 PWG : Created.                                             *\n *=========================================================================*/\nint PowerClass::Power_Height(int value)\n{\n\tint num\t\t= value/ POWER_STEP_LEVEL;\t\t// figure out the initial num of DRAIN_VALUE's\n\tint retval\t= 0;\t\t\t\t\t\t\t\t\t// currently there is no power\n\n\t/*\n\t** Loop through the different hundreds figuring out the fractional piece\n\t** of each.\n\t*/\n\tfor (int lp = 0; lp < num; lp ++)  {\n\t\tretval  = retval + (((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR);\n\t\tvalue  -= POWER_STEP_LEVEL;\n\t}\n\n\t/*\n\t** Adjust the retval to factor in the remainder\n\t*/\n\tif (value) {\n\t\tretval = retval + (((((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR) * value) / POWER_STEP_LEVEL);\n\t}\n\n\tretval = Bound(retval, 0, POWER_HEIGHT-2);\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area.          *\n *                                                                                             *\n *    This routine handles input on the power bar area. Since no input is used for the power   *\n *    bar, this routine just pops up appropriate help text for the power bar.                  *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that triggered this action call.                       *\n *                                                                                             *\n *          key      -- The key code (if any) associated with the trigger event.               *\n *                                                                                             *\n * OUTPUT:  Should further button processing be stopped?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/07/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint PowerClass::PowerButtonClass::Action(unsigned flags, KeyNumType & key)\n{\n\tif (!Map.IsSidebarActive) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tForce any help label to disappear when the mouse is held over the\n\t**\tradar map.\n\t*/\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tif (PlayerPtr->Power_Fraction() < 1 && PlayerPtr->Power > 0) {\n\t\tMap.Help_Text(TXT_POWER_OUTPUT_LOW, -1, -1, GadgetClass::Get_Color_Scheme()->Color);\n\t} else {\n\t\tMap.Help_Text(TXT_POWER_OUTPUT, -1, -1, GadgetClass::Get_Color_Scheme()->Color);\n\t}\n\tGadgetClass::Action(flags, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * PowerClass::Flash_Power -- Flag the power bar to flash.                                     *\n *                                                                                             *\n *    This will cause the power bar to display with a flash so as to draw attention to         *\n *    itself. Typical use of this effect is when power is low.                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/14/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PowerClass::Flash_Power(void)\n{\n\tFlashTimer = TICKS_PER_SECOND;\n\tIsToRedraw = true;\n\tFlag_To_Redraw(false);\n}\n"
  },
  {
    "path": "REDALERT/POWER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/POWER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : POWER.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef POWER_H\n#define POWER_H\n\n#include\t\"radar.h\"\n\nclass PowerClass : public RadarClass\n{\n\tpublic:\n\t\tPowerClass(void);\n\t\tPowerClass(NoInitClass const & x) : RadarClass(x), FlashTimer(x) {};\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvoid Flash_Power(void);\n\n\t\tunsigned IsToRedraw:1;\n\n\tprotected:\n\t\t/*\n\t\t**\tThis gadget is used to capture mouse input on the power bar.\n\t\t*/\n\t\tclass PowerButtonClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tPowerButtonClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\tfriend class PowerClass;\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\n\t\tstatic PowerButtonClass PowerButton;\n\n\t\tenum PowerEnums {\n\t\t\tPOWER_X=10*ICON_PIXEL_W,\n#ifdef WIN32\n\t\t\tPOWER_Y= (7+70+13),\n\t\t\tPOWER_HEIGHT=(200-(7+70+13)),\n#else\n\t\t\tPOWER_Y= (88+9),\n\t\t\tPOWER_HEIGHT=80,\n#endif\n\t\t\tPOWER_WIDTH=8,\n\t\t\tPOWER_LINE_SPACE=5,\n\t\t\tPOWER_LINE_WIDTH=3,\n\t\t\tPOWER_STEP_LEVEL=100,\n\t\t\tPOWER_STEP_FACTOR=5\n\t\t};\n\n\tprivate:\n\t\tint Power_Height(int value);\n\n\t\tunsigned IsActive:1;\n\n\t\t/*\n\t\t**\tIf the power bar should be rendered with some flash effect then\n\t\t**\tthis specifies the duration that the flash will occur.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> FlashTimer;\n\n\t\tint RecordedDrain;\n\t\tint RecordedPower;\n\t\tint DesiredDrainHeight;\n\t\tint DesiredPowerHeight;\n\t\tint DrainHeight;\n\t\tint PowerHeight;\n\t\tint DrainBounce;\n\t\tint PowerBounce;\n\t\tshort PowerDir;\n\t\tshort DrainDir;\n\n\t\t/*\n\t\t**\tPoints to the shape to use for the \"desired\" power level indicator.\n\t\t*/\n\t\tstatic void const * PowerShape;\n\t\tstatic void const * PowerBarShape;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/PROFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/PROFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : PROFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : September 10, 1993   [JLB]                                   *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   WWGetPrivateProfileInt -- Fetches integer value from INI.                                 *\n *   WWGetPrivateProfileString -- Fetch string from INI.                                       *\n *   WWWritePrivateProfileInt -- Write a profile int to the profile data block.                *\n *   WWWritePrivateProfileString -- Write a string to the profile data block.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nstatic char * WriteBinBuffer = NULL;\nstatic int WriteBinBufferLen = 0;\nstatic int WriteBinBufferPos = 0;\nstatic int WriteBinBufferMax = 0;\nstatic char * ReadBinBuffer = NULL;\nstatic int ReadBinBufferLen = 0;\nstatic int ReadBinBufferPos = 0;\nstatic int ReadBinBufferMax = 0;\n\n\n/***************************************************************************\n * Read_Private_Config_Struct -- Fetches override integer value.           *\n *                                                                         *\n * INPUT:                                                                  *\n * OUTPUT:                                                                 *\n * WARNINGS:                                                               *\n * HISTORY:                                                                *\n *   08/05/1992 JLB : Created.                                             *\n *=========================================================================*/\nbool Read_Private_Config_Struct(FileClass & file, NewConfigType * config)\n{\n\tINIClass ini;\n\tini.Load(file);\n\n\tconfig->DigitCard \t= ini.Get_Hex(\"Sound\", \"Card\", 0);\n\tconfig->IRQ \t\t\t= ini.Get_Int(\"Sound\", \"IRQ\", 0);\n\tconfig->DMA \t\t\t= ini.Get_Int(\"Sound\", \"DMA\", 0);\n\tconfig->Port \t\t\t= ini.Get_Hex(\"Sound\", \"Port\", 0);\n\tconfig->BitsPerSample= ini.Get_Int(\"Sound\", \"BitsPerSample\", 0);\n\tconfig->Channels \t\t= ini.Get_Int(\"Sound\", \"Channels\", 0);\n\tconfig->Reverse      = ini.Get_Int(\"Sound\", \"Reverse\", 0);\n\tconfig->Speed        = ini.Get_Int(\"Sound\", \"Speed\", 0);\n\tini.Get_String(\"Language\", \"Language\", NULL, config->Language, sizeof(config->Language));\n\n\n//\tconfig->DigitCard \t= WWGetPrivateProfileHex(\"Sound\", \"Card\", \t\t\t profile);\n//\tconfig->IRQ \t\t\t= WWGetPrivateProfileInt(\"Sound\", \"IRQ\", \t\t\t 0,profile);\n//\tconfig->DMA \t\t\t= WWGetPrivateProfileInt(\"Sound\", \"DMA\", \t\t\t 0,profile);\n//\tconfig->Port \t\t\t= WWGetPrivateProfileHex(\"Sound\", \"Port\", \t\t\t profile);\n//\tconfig->BitsPerSample= WWGetPrivateProfileInt(\"Sound\", \"BitsPerSample\",0,profile);\n//\tconfig->Channels \t\t= WWGetPrivateProfileInt(\"Sound\", \"Channels\",\t\t 0,profile);\n//\tconfig->Reverse      = WWGetPrivateProfileInt(\"Sound\", \"Reverse\", \t\t 0,profile);\n//\tconfig->Speed        = WWGetPrivateProfileInt(\"Sound\", \"Speed\", \t\t 0,profile);\n//\tWWGetPrivateProfileString(\"Language\", \"Language\", NULL, config->Language, 3, profile);\n\n\treturn((config->DigitCard == 0) && (config->IRQ == 0) && (config->DMA == 0));\n}\n\n\n/***************************************************************************\n * Get_Private_Profile_Hex -- Fetches override integer value.              *\n *                                                                         *\n * INPUT:                                                                  *\n * OUTPUT:                                                                 *\n * WARNINGS:                                                               *\n * HISTORY:                                                                *\n *   08/05/1992 MML : Created.                                             *\n *=========================================================================*/\nunsigned WWGetPrivateProfileHex (char const * section, char const * entry, char * profile)\n{\n\tchar\tbuffer[16];\t\t\t\t\t// Integer staging buffer.\n\tunsigned card;\n\n\tmemset (buffer, '0', sizeof(buffer));\t\t// MAX_ENTRY_SIZE = 15\n\tbuffer[sizeof(buffer)-1] = '\\0';\n\n\tWWGetPrivateProfileString(section, entry, \"0\", buffer, sizeof(buffer), profile);\n\n\tif (strlen (buffer) > 0) {\n\t\tsscanf (buffer, \"%x\", &card);\n\t} else {\n\t\tcard = 0;\n\t}\n\n\treturn(card);\n}\n\n\n/***********************************************************************************************\n * WWGetPrivateProfileInt -- Fetches integer value.                                            *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section to read from                                                      *\n *                                                                                             *\n *      entry         name of entry to read                                                    *\n *                                                                                             *\n *      def         default value, if entry isn't found                                        *\n *                                                                                             *\n *      profile      buffer containing INI data                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      integer requested                                                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nint WWGetPrivateProfileInt(char const * section, char const * entry, int def, char * profile)\n{\n\tchar\tbuffer[16];\t\t\t// Integer staging buffer.\n\n\t/*\n\t**\tStore the default in the buffer.\n\t*/\n\tsprintf(buffer, \"%d\", def);\n\n\t/*\n\t**\tGet the buffer; use itself as the default.\n\t*/\n\tWWGetPrivateProfileString(section, entry, buffer, buffer, sizeof(buffer)-1, profile);\n\n\t/*\n\t**\tConvert to int & return.\n\t*/\n\treturn(atoi(buffer));\n}\n\n\n/***********************************************************************************************\n * WWWritePrivateProfileInt -- Write a profile int to the profile data block.                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to write to                                                  *\n *                                                                                             *\n *      entry         name of entry to write; if NULL, the entire section is deleted           *\n *                                                                                             *\n *      value         value to write                                                           *\n *                                                                                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWWritePrivateProfileInt(char const * section, char const * entry, int value, char * profile)\n{\n\tchar\tbuffer[250];\t\t\t// Working section buffer.\n\n\t/*\n\t**\tJust return if nothing to do.\n\t*/\n\tif (!profile || !section) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tGenerate string to save.\n\t*/\n\tsprintf(buffer, \"%d\", value);\n\n\t/*\n\t**\tSave the string.\n\t*/\n\treturn(WWWritePrivateProfileString(section, entry, buffer, profile));\n}\n\n\n/***********************************************************************************************\n * WWGetPrivateProfileString -- Fetch game override string.                                    *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to read from                                                 *\n *                                                                                             *\n *      entry         name of entry to read; if NULL, all entry names are returned             *\n *                                                                                             *\n *      def         default string to use if not found; can be NULL                            *\n *                                                                                             *\n *      retbuffer   buffer to store result in                                                  *\n *                                                                                             *\n *      retlen      max length of return buffer                                                *\n *                                                                                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      ptr to entry found in INI buf; NULL if not found                                       *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      On the PC, the \"\\n\" (10) is translated to \"\\r\\n\" (13,10) when it's written             *\n *      to disk. This routine must take this into consideration, by searching                  *\n *      for \\n when scanning backward, and for \\r when scanning forward.                       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar * WWGetPrivateProfileString(char const * section, char const * entry, char const * def, char * retbuffer, int retlen, char const * profile)\n{\n\tchar const * workptr;\t\t// Working pointer into profile block.\n\tchar * altworkptr;\t// Alternate work pointer.\n\tchar\tsec[50];\t\t\t// Working section buffer.\n\tchar\tconst * retval;\t\t\t// Start of section or entry pointer.\n\tchar\t* next;\t\t\t// Pointer to start of next section (or EOF).\n\tchar\tc,c2;\t\t\t\t// Working character values.\n\tint\tlen;\t\t\t\t// Working substring length value.\n\tint\tentrylen;\t\t// Byte length of specified entry.\n\tchar * orig_retbuf;\t// original retbuffer ptr\n\n//\tif (!retlen) return(NULL);\n\n\t/*\n\t**\tFill in the default value just in case the entry could not be found.\n\t*/\n\tif (retbuffer) {\n\t\tretbuffer[0] = '\\0';\n\t\tif (retlen > 1 || retlen == 0) retbuffer[1] = '\\0';\n\t\tif (def) {\n\t\t\tstrncpy(retbuffer, def, retlen);\n\t\t}\n\t\tretbuffer[retlen-1] = '\\0';\n\t\torig_retbuf = retbuffer;\n\t}\n\n\t/*\n\t**\tMake sure a profile string was passed in\n\t*/\n\tif (!profile || !section) {\n\t\treturn(retbuffer);\n\t}\n\n\t/*\n\t**\tBuild section string to match file image.\n\t*/\n\tsprintf(sec, \"[%s]\", section);\t// sec = section name including []'s\n\tstrupr(sec);\n\tlen = strlen(sec);\t\t\t\t\t// len = section name length, incl []'s\n\n\t/*\n\t**\tScan for a matching section\n\t*/\n\tretval = profile;\n\tworkptr = profile;\n\tfor (;;) {\n\n\t\t/*\n\t\t**\t'workptr' = start of next section\n\t\t*/\n\t\tworkptr = strchr(workptr, '[');\n\n\t\t/*\n\t\t**\tIf the end has been reached without finding the desired section\n\t\t**\tthen abort with a failure flag.\n\t\t*/\n\t\tif (!workptr) {\n\t\t\treturn(NULL);\n\t\t}\n\n\t\t/*\n\t\t**\t'c' = character just before the '['\n\t\t*/\n\t\tif (workptr==profile) {\n\t\t\tc = '\\n';\n\t\t} else {\n\t\t\tc = *(workptr-1);\n\t\t}\n\n\t\t/*\n\t\t**\tIf this is the section name & the character before is a newline,\n\t\t**\tprocess this section\n\t\t*/\n\t\tif (memicmp(workptr, sec, len) == 0 && (c == '\\n')) {\n\n\t\t\t/*\n\t\t\t**\tSkip work pointer to start of first valid entry.\n\t\t\t*/\n\t\t\tworkptr += len;\n\t\t\twhile (isspace(*workptr)) {\n\t\t\t\tworkptr++;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf the section name is empty, we will have stepped onto the start\n\t\t\t**\tof the next section name; inserting new entries here will leave\n\t\t\t**\ta blank line between this section's name & 1st entry. So, check\n\t\t\t**\tfor 2 newlines in a row & step backward.\n\t\t\t*/\n\t\t\tif (workptr - profile > 4) {\n\t\t\t\tif ( *(workptr-1)=='\\n' && *(workptr-3)=='\\n')\n\t\t\t\t\tworkptr -= 2;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\t'next = end of section or end of file.\n\t\t\t*/\n\t\t\tnext = (char*)strchr(workptr, '[');\n\t\t\tfor (;;) {\n\t\t\t\tif (next) {\n\n\t\t\t\t\tc = *(next-1);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf character before '[' is newline, this is the start of the\n\t\t\t\t\t**\tnext section\n\t\t\t\t\t*/\n\t\t\t\t\tif (c == '\\n') {\n\t\t\t\t\t\tif (*(next-1)=='\\n' && *(next-3)=='\\n') {\n\t\t\t\t\t\t\tnext -= 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tThis bracket was in the section; keep looking\n\t\t\t\t\t*/\n\t\t\t\t\tnext = strchr(next+1, '[');\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tNo bracket found; set 'next' to the end of the file\n\t\t\t\t\t*/\n\t\t\t\t\tnext = (char*)workptr + strlen(workptr)-1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf a specific entry was specified then return with the associated\n\t\t\t**\tstring.\n\t\t\t*/\n\t\t\tif (entry) {\n\t\t\t\tretval = workptr;\n\t\t\t\tentrylen = strlen(entry);\n\n\t\t\t\tfor (;;) {\n\t\t\t\t\t/*\n\t\t\t\t\t** Search for the 1st character of the entry\n\t\t\t\t\t*/\n\t\t\t\t\tworkptr = strchr(workptr, *entry);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the end of the file has been reached or we have spilled\n\t\t\t\t\t**\tinto the next section, then abort\n\t\t\t\t\t*/\n\t\t\t\t\tif (!workptr || workptr >= next) {\n\t\t\t\t\t\treturn(NULL);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\t'c' = character before possible entry; must be a newline\n\t\t\t\t\t**\t'c2' = character after possible entry; must be '=' or space\n\t\t\t\t\t*/\n\t\t\t\t\tc = *(workptr-1);\n\t\t\t\t\tc2 = *(workptr+entrylen);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tEntry found; extract it\n\t\t\t\t\t*/\n\t\t\t\t\tif (memicmp(workptr, entry, entrylen) == 0 && (c == '\\n') &&\n\t\t\t\t\t\t(c2 == '=' || isspace(c2))) {\n\t\t\t\t\t\tretval = workptr;\n\t\t\t\t\t\tworkptr += entrylen;\t\t\t\t\t\t\t// skip entry name\n\t\t\t\t\t\tworkptr = strchr(workptr, '=');\t\t\t// find '='\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** 'altworkptr' = next newline; \\r is used here since we're\n\t\t\t\t\t\t** scanning forward!\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (workptr) {\n\t\t\t\t\t\t\taltworkptr = (char*)strchr(workptr, '\\r');\t// find next newline\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tReturn if there was no '=', or if the newline is before\n\t\t\t\t\t\t**\tthe next '='\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (workptr == NULL || altworkptr < workptr) {\n\t\t\t\t\t\t\treturn((char *)retval);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tSkip any white space after the '=' and before the first\n\t\t\t\t\t\t**\tvalid character of the parameter.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tworkptr++;\t\t\t\t\t\t\t\t\t\t// Skip the '='.\n\t\t\t\t\t\twhile (isspace(*workptr)) {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tJust return if there's no entry past the '='.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (workptr >= altworkptr)\n\t\t\t\t\t\t\t\treturn((char*)retval);\n\n\t\t\t\t\t\t\tworkptr++;\t\t\t\t\t\t\t\t\t// Skip the whitespace\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tCopy the entry into the return buffer.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tlen = (int)(altworkptr - workptr);\n\t\t\t\t\t\tif (len > retlen-1) {\n\t\t\t\t\t\t\tlen = retlen-1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (retbuffer) {\n\t\t\t\t\t\t\tmemcpy(retbuffer, workptr, len);\n\t\t\t\t\t\t\t*(retbuffer + len) = '\\0';\t\t// Insert trailing null.\n\t\t\t\t\t\t\tstrtrim(retbuffer);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn((char*)retval);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tEntry was not found; go to the next one\n\t\t\t\t\t*/\n\t\t\t\t\tworkptr++;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo entry was specified, so build a list of all entries.\n\t\t\t\t**\t'workptr' is at 1st entry after section name\n\t\t\t\t**\t'next' is next bracket, or end of file\n\t\t\t\t*/\n\t\t\t\tretval = workptr;\n\n\t\t\t\tif (retbuffer) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tKeep accumulating the identifier strings in the retbuffer.\n\t\t\t\t\t*/\n\t\t\t\t\twhile (workptr && workptr < next) {\n\t\t\t\t\t\taltworkptr = (char*)strchr(workptr, '=');\t\t// find '='\n\n\t\t\t\t\t\tif (altworkptr && altworkptr < next) {\n\t\t\t\t\t\t\tint\tlength;\t\t\t\t\t\t\t\t// Length of ID string.\n\n\t\t\t\t\t\t\tlength = (int)(altworkptr - workptr);\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tMake sure we don't write past the end of the retbuffer;\n\t\t\t\t\t\t\t**\tadd '3' for the 3 NULL's at the end\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tif (retbuffer - orig_retbuf + length + 3 < retlen) {\n\t\t\t\t\t\t\t\tmemcpy(retbuffer, workptr, length);\t// copy entry name\n\t\t\t\t\t\t\t\t*(retbuffer+length) = '\\0';\t\t\t// NULL-terminate it\n\t\t\t\t\t\t\t\tstrtrim(retbuffer);\t\t\t\t\t\t// trim spaces\n\t\t\t\t\t\t\t\tretbuffer += strlen(retbuffer)+1;\t// next pos in dest buf\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tAdvance the work pointer to the start of the next line\n\t\t\t\t\t\t\t**\tby skipping the end of line character.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tworkptr = strchr(altworkptr, '\\n');\n\t\t\t\t\t\t\tif (!workptr) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tworkptr++;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tIf no '=', break out of loop\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tFinal trailing terminator. Make double sure the double\n\t\t\t\t\t**\ttrailing null is added.\n\t\t\t\t\t*/\n\t\t\t\t\t*retbuffer++ = '\\0';\n\t\t\t\t\t*retbuffer++ = '\\0';\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tSection name not found; go to the next bracket & try again\n\t\t\t**\tAdvance past '[' and keep scanning.\n\t\t\t*/\n\t\t\tworkptr++;\n\t\t}\n\t}\n\n\treturn((char*)retval);\n}\n\n\n/***********************************************************************************************\n * WritePrivateProfileString -- Write a string to the profile data block.                      *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      section      section name to write to                                                  *\n *      entry         name of entry to write; if NULL, the section is deleted                  *\n *      string      string to write; if NULL, the entry is deleted                             *\n *      profile      INI buffer                                                                *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = success, false = failure                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      This function has to translate newlines into \\r\\n sequences.                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool WWWritePrivateProfileString(char const * section, char const * entry, char const * string, char * profile)\n{\n\tchar\tbuffer[250];\t\t\t// Working section buffer\n\tchar const * offset;\n\tchar const * next;\t\t\t\t\t\t// ptr to next section\n\tchar\tc;\t\t\t\t\t\t\t// Working character value\n\n\t/*\n\t**\tJust return if nothing to do.\n\t*/\n\tif (!profile || !section) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tTry to find the section. WWGetPrivateProfileString with NULL entry name\n\t**\twill return all entry names in the given buffer, truncated to the given\n\t**\tbuffer length. 'offset' will point to 1st entry in the section, NULL if\n\t**\tsection not found.\n\t*/\n\toffset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);\n\n\t/*\n\t**\tIf the section could not be found, then add it to the end. Don't add\n\t**\tanything if a removal of an entry is requested (it is obviously already\n\t**\tnon-existent). Make sure two newlines precede the section name.\n\t*/\n\tif (!offset && entry) {\n\t\tsprintf(buffer, \"\\r\\n[%s]\\r\\n\", section);\n\t\tstrcat(profile, buffer);\n\t}\n\n\t/*\n\t**\tIf the section is there and 'entry' is NULL, remove the entire section\n\t*/\n\tif (offset && !entry) {\n\n\t\t/*\n\t\t**\t'next = end of section or end of file.\n\t\t*/\n\t\tnext = strchr(offset, '[');\n\t\tfor (;;) {\n\t\t\tif (next) {\n\t\t\t\tc = *(next-1);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf character before '[' is newline, this is the start of the\n\t\t\t\t**\tnext section\n\t\t\t\t*/\n\t\t\t\tif (c == '\\n') {\n\t\t\t\t\tif ( *(next-1)=='\\n' && *(next-3)=='\\n') {\n\t\t\t\t\t\tnext -= 2;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tThis bracket was in the section; keep looking\n\t\t\t\t*/\n\t\t\t\tnext = strchr(next+1, '[');\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo bracket found; set 'next' to the end of the file\n\t\t\t\t*/\n\t\t\t\tnext = offset + strlen(offset);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tRemove the section\n\t\t*/\n\t\tstrcpy((char*)offset, (char*)next);\n\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tFind the matching entry within the desired section. A NULL return buffer\n\t**\twith 0 length will just return the offset of the found entry, NULL if\n\t**\tentry not found.\n\t*/\n\toffset = WWGetPrivateProfileString(section, entry, NULL, NULL, 0, profile);\n\n\t/*\n\t**\tRemove any existing entry\n\t*/\n\tif (offset) {\n\t\tint\teol;\t\t\t// Working EOL offset.\n\n\t\t/*\n\t\t**\tGet # characters up to newline; \\n is used since we're after the end\n\t\t**\tof this line\n\t\t*/\n\t\teol = strcspn(offset, \"\\n\");\n\n\t\t/*\n\t\t**\tErase the entry by strcpy'ing the entire INI file over this entry\n\t\t*/\n\t\tif (eol) {\n\t\t\tstrcpy((char*)offset, offset + eol + 1);\n\t\t}\n\t} else {\n\n\t\t/*\n\t\t**\tEntry doesn't exist, so point 'offset' to the 1st entry position in\n\t\t**\tthe section.\n\t\t*/\n\t\toffset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile);\n\t}\n\n\t/*\n\t**\tAdd the desired entry.\n\t*/\n\tif (entry && string) {\n\n\t\t/*\n\t\t**\tGenerate entry string.\n\t\t*/\n\t\tsprintf(buffer, \"%s=%s\\r\\n\", entry, string);\n\n\t\t/*\n\t\t**\tMake room for new entry.\n\t\t*/\n\t\tmemmove((char*)offset+strlen(buffer), offset, strlen(offset)+1);\n\n\t\t/*\n\t\t**\tCopy the entry into the INI buffer.\n\t\t*/\n\t\tmemcpy((char*)offset, buffer, strlen(buffer));\n\t}\n\n\treturn(true);\n}\n\n\nchar * Read_Bin_Buffer( void )\n{\n\treturn( ReadBinBuffer );\n}\n\n\nbool Read_Bin_Init( char * buffer, int length )\n{\n\tReadBinBuffer = buffer;\n\tReadBinBufferLen = length;\n\tReadBinBufferPos = 0;\n\tReadBinBufferMax = 0;\n\treturn( true );\n}\n\n\nint Read_Bin_Length( char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( ReadBinBufferMax );\n\t}\n}\n\n\nbool Read_Bin_Num( void * num, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != ReadBinBuffer || length <= 0 || length > 4 ||\n\t\t (ReadBinBufferPos + length) >= ReadBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = ReadBinBuffer + ReadBinBufferPos;\n\t\tmemcpy( num, ptr, length );\n\t\tReadBinBufferPos += length;\n\n\t\tif (ReadBinBufferPos > ReadBinBufferMax) {\n\t\t\tReadBinBufferMax = ReadBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n\nint Read_Bin_Pos( char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( ReadBinBufferPos );\n\t}\n}\n\n\nint Read_Bin_PosSet( unsigned int pos, char * buffer )\n{\n\tif (buffer != ReadBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\tReadBinBufferPos = pos;\n\t\treturn( ReadBinBufferPos );\n\t}\n}\n\n\nbool Read_Bin_String( char * string, char * buffer )\n{\n\tchar * ptr;\n\tunsigned char length;\n\n\tif (buffer != ReadBinBuffer ||\n\t\t ReadBinBufferPos >= ReadBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = ReadBinBuffer + ReadBinBufferPos;\n\t\tlength = (unsigned char)*ptr++;\n\t\tif ( (ReadBinBufferPos + length + 2) <= ReadBinBufferLen) {\n\t\t\tmemcpy( string, ptr, (unsigned int)(length + 1) );\n\t\t\tReadBinBufferPos += (length + 2);\n\n\t\t\tif (ReadBinBufferPos > ReadBinBufferMax) {\n\t\t\t\tReadBinBufferMax = ReadBinBufferPos;\n\t\t\t}\n\n\t\t\treturn( true );\n\t\t} else {\n\t\t\treturn( false );\n\t\t}\n\t}\n}\n\n\nchar * Write_Bin_Buffer( void )\n{\n\treturn( WriteBinBuffer );\n}\n\n\nbool Write_Bin_Init( char * buffer, int length )\n{\n\tWriteBinBuffer = buffer;\n\tWriteBinBufferLen = length;\n\tWriteBinBufferPos = 0;\n\tWriteBinBufferMax = 0;\n\treturn( true );\n}\n\n\nint Write_Bin_Length( char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( WriteBinBufferMax );\n\t}\n}\n\n\nbool Write_Bin_Num( void * num, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != WriteBinBuffer || length <= 0 || length > 4 ||\n\t\t (WriteBinBufferPos + length) > WriteBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = WriteBinBuffer + WriteBinBufferPos;\n\t\tmemcpy( ptr, num, length );\n\t\tWriteBinBufferPos += length;\n\n\t\tif (WriteBinBufferPos > WriteBinBufferMax) {\n\t\t\tWriteBinBufferMax = WriteBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n\nint Write_Bin_Pos( char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\treturn( WriteBinBufferPos );\n\t}\n}\n\n\nint Write_Bin_PosSet( unsigned int pos, char * buffer )\n{\n\tif (buffer != WriteBinBuffer) {\n\t\treturn( -1 );\n\t} else {\n\t\tWriteBinBufferPos = pos;\n\t\treturn( WriteBinBufferPos );\n\t}\n}\n\n\nbool Write_Bin_String( char * string, int length, char * buffer )\n{\n\tchar * ptr;\n\n\tif (buffer != WriteBinBuffer || length < 0 || length > 255 ||\n\t\t (WriteBinBufferPos + length + 2) > WriteBinBufferLen) {\n\t\treturn( false );\n\t} else {\n\t\tptr = WriteBinBuffer + WriteBinBufferPos;\n\t\t*ptr++ = (char)length;\n\t\tmemcpy( ptr, string, (length + 1) );\n\t\tWriteBinBufferPos += (length + 2);\n\n\t\tif (WriteBinBufferPos > WriteBinBufferMax) {\n\t\t\tWriteBinBufferMax = WriteBinBufferPos;\n\t\t}\n\n\t\treturn( true );\n\t}\n}\n\n"
  },
  {
    "path": "REDALERT/QUEUE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/QUEUE.CPP 6     3/14/97 5:12p Steve_tall $ */\n/***************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : QUEUE.CPP                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 11/28/95                                 *\n *                                                                         *\n *                  Last Update : October 14, 1996 [BRR]                   *\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions for Queueing Events:                                          *\n *   Queue_Mission -- Queue a mega mission event.                          *\n *   Queue_Options -- Queue the options event.                             *\n *   Queue_Exit -- Add the exit game event to the queue.                   *\n *                                                                         *\n * Functions for processing Queued Events:\t\t\t\t\t\t\t\t\t\t\t*\n *   Queue_AI -- Process all queued events.                                *\n *   Queue_AI_Normal -- Process all queued events.                         *\n *   Queue_AI_Multiplayer -- Process all queued events.                    *\n *                                                                         *\n * Main Multiplayer Queue Logic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Wait_For_Players -- Waits for other systems to come on-line           *\n *   Generate_Timing_Event -- computes & queues a RESPONSE_TIME event      *\n *   Process_Send_Period -- timing for sending packets every 'n' frames    *\n *   Send_Packets -- sends out events from the OutList                     *\n *   Send_FrameSync -- Sends a FRAMESYNC packet                            *\n *   Process_Receive_Packet -- processes an incoming packet                *\n *   Process_Serial_Packet -- Handles an incoming serial packet            *\n *   Can_Advance -- determines if it's OK to advance to the next frame     *\n *   Process_Reconnect_Dialog -- processes the reconnection dialog         *\n *   Handle_Timeout -- attempts to reconnect; if fails, bails.             *\n *   Stop_Game -- stops the game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Packet Compression / Decompression:\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Build_Send_Packet -- Builds a big packet from a bunch of little ones.\t*\n *   Add_Uncompressed_Events -- adds uncompressed events to a packet       *\n *   Add_Compressed_Events -- adds compressed events to a packet        \t*\n *   Breakup_Receive_Packet -- Splits a big packet into little ones.\t\t\t*\n *   Extract_Uncompressed_Events -- extracts events from a packet\t\t\t\t*\n *   Extract_Compressed_Events -- extracts events from a packet            *\n *                                                                         *\n * DoList Management:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Execute_DoList -- Executes commands from the DoList                   *\n *   Clean_DoList -- Cleans out old events from the DoList                 *\n *   Queue_Record -- Records the DoList to disk                            *\n *   Queue_Playback -- plays back queue entries from a record file         *\n *                                                                         *\n * Debugging:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *   Compute_Game_CRC -- Computes a CRC value of the entire game.\t\t\t\t*\n *   Add_CRC -- Adds a value to a CRC                                      *\n *   Print_CRCs -- Prints a data file for finding Sync Bugs\t\t\t\t\t\t*\n *   Init_Queue_Mono -- inits mono display                                 *\n *   Update_Queue_Mono -- updates mono display                             *\n *   Print_Framesync_Values -- displays frame-sync variables               *\n *   Check_Mirror -- Checks mirror memory                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#include\t\"function.h\"\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n\nbool bReconnectDialogCancelled;\n#endif\n\n\n/********************************** Defines *********************************/\n#define SHOW_MONO\t0\n\n\n/********************************** Globals *********************************/\n//---------------------------------------------------------------------------\n//\tGameCRC is the current computed CRC value for this frame.\n//\tCRC[] is a record of our last 32 game CRC's.\n// ColorNames is for debug output in Print_CRCs\n//---------------------------------------------------------------------------\nstatic unsigned long GameCRC;\nstatic unsigned long CRC[32] =\n\t{0,0,0,0,0,0,0,0,0,0,\n\t 0,0,0,0,0,0,0,0,0,0,\n\t 0,0,0,0,0,0,0,0,0,0,\n\t 0,0};\nstatic char *ColorNames[8] = {\n\t\"Yellow\",\n\t\"LtBlue\",\n\t\"Red\",\n\t\"Green\",\n\t\"Orange\",\n\t\"Grey\",\n\t\"Blue\",\n\t\"Brown\"\n};\n\n//...........................................................................\n// Mono debugging variables:\n// NetMonoMode: 0 = show connection output, 1 = flowcount output\n// NewMonoMode: set by anything that toggles NetMonoMode; re-inits screen\n// IsMono: used for taking control of Mono screen away from the engine\n//...........................................................................\nint NetMonoMode = 1;\nint NewMonoMode = 1;\nstatic int IsMono = 0;\n\n//---------------------------------------------------------------------------\n// Several routines return various codes; here's an enum for all of them.\n//---------------------------------------------------------------------------\ntypedef enum RetcodeEnum {\n\tRC_NORMAL,\t\t\t\t\t\t// no news is good news\n\tRC_PLAYER_READY,\t\t\t\t// a new player has been heard from\n\tRC_SCENARIO_MISMATCH,\t\t// scenario mismatch\n\tRC_DOLIST_FULL,\t\t\t\t// DoList is full\n\tRC_SERIAL_PROCESSED,\t\t\t// modem: SERIAL packet was processed\n\tRC_PLAYER_LEFT,\t\t\t\t// modem: other player left the game\n\tRC_HUNG_UP,\t\t\t\t\t\t// modem has hung up\n\tRC_NOT_RESPONDING,\t\t\t// other player not responding (timeout/hung up)\n\tRC_CANCEL,\t\t\t\t\t\t// user cancelled\n} RetcodeType;\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern void Enable_Secret_Units(void);\n#endif\n\n/********************************* Prototypes *******************************/\n//...........................................................................\n// Main multiplayer queue logic\n//...........................................................................\nstatic void Queue_AI_Normal(void);\nstatic void Queue_AI_Multiplayer(void);\nstatic RetcodeType Wait_For_Players(int first_time, ConnManClass *net,\n\tint resend_delta, int dialog_time, int timeout, char *multi_packet_buf,\n\tint my_sent, long *their_frame,  unsigned short *their_sent,\n\tunsigned short *their_recv);\nstatic void Generate_Timing_Event(ConnManClass *net, int my_sent);\nstatic void Generate_Real_Timing_Event(ConnManClass *net, int my_sent);\nstatic void Generate_Process_Time_Event(ConnManClass *net);\nstatic int Process_Send_Period(ConnManClass *net);\t//, int init);\nstatic int Send_Packets(ConnManClass *net, char *multi_packet_buf,\n\tint multi_packet_max, int max_ahead, int my_sent);\nstatic void Send_FrameSync(ConnManClass *net, int cmd_count);\nstatic RetcodeType Process_Receive_Packet(ConnManClass *net,\n\tchar *multi_packet_buf, int id, int packetlen, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic RetcodeType Process_Serial_Packet(char *multi_packet_buf,\n\tint first_time);\nstatic int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,\n\tlong *their_frame, int num_conn, int reconn, int fresh);\nstatic int Handle_Timeout(ConnManClass *net, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv);\nstatic void Stop_Game(void);\n\n//...........................................................................\n// Packet compression/decompression:\n//...........................................................................\nstatic int Build_Send_Packet(void *buf, int bufsize, int frame_delay,\n\tint num_cmds, int cap);\nint Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay, int size,\n\tint cap);\nint Add_Compressed_Events(void *buf, int bufsize, int frame_delay, int size,\n\tint cap);\nstatic int Breakup_Receive_Packet(void *buf, int bufsize );\nint Extract_Uncompressed_Events(void *buf, int bufsize);\nint Extract_Compressed_Events(void *buf, int bufsize);\n\n//...........................................................................\n// DoList management:\n//...........................................................................\nstatic int Execute_DoList(int max_houses, HousesType base_house,\n\tConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,\n//\tConnManClass *net, TCountDownTimerClass *skip_crc,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv);\nstatic void Clean_DoList(ConnManClass *net);\nstatic void Queue_Record(void);\nstatic void Queue_Playback(void);\n\n//...........................................................................\n// Debugging:\n//...........................................................................\nstatic void Compute_Game_CRC(void);\nvoid Add_CRC(unsigned long *crc, unsigned long val);\nstatic void Print_CRCs(EventClass *ev);\nstatic void Init_Queue_Mono(ConnManClass *net);\nstatic void Update_Queue_Mono(ConnManClass *net, int flow_index);\nstatic void Print_Framesync_Values(long curframe, unsigned long max_ahead,\n\tint num_connections, unsigned short *their_recv,\n\tunsigned short *their_sent, unsigned short my_sent);\n\nextern void Keyboard_Process(KeyNumType &input);\nvoid Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv);\nvoid Check_Mirror(void);\n\n\n/***************************************************************************\n * Queue_Mission -- Queue a mega mission event.                            *\n *                                                                         *\n * This routine is called when the player causes a change to a game unit. \t*\n * The event that initiates the change is queued to as a result of a call \t*\n * to this routine.                 \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\twhom\t\tWhom this mission request applies to (a friendly unit).     *\n *    mission\tThe mission to assign to this object.                       *\n *    target\tThe target of this mission (if any).                        *\n *    dest\t\tThe movement destination for this mission (if any).         *\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the mission request queued successfully?                         *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.                                                                *\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination)\n{\n\tif (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination)))) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***********************************************************************************************\n * Queue_Mission -- Queue a mega mission event, formation override for common speed.           *\n *                                                                                             *\n *    This routine is called when the player causes a change to a game unit. The event that    *\n *    initiates the change is queued to as a result of a call to this routine.                 *\n *                                                                                             *\n * INPUT:   whom     -- Whom this mission request applies to (a friendly unit).                *\n *                                                                                             *\n *          mission  -- The mission to assign to this object.                                  *\n *                                                                                             *\n *          target   -- The target of this mission (if any).                                   *\n *                                                                                             *\n *          dest     -- The movement destination for this mission (if any).                    *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\tspeed\t   -- The override speed for this unit.\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\t\t\tmaxspeed -- The override maximum speed for this unit.\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  Was the mission request queued successfully?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination, SpeedType speed, MPHType maxspeed)\n{\n\tif (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination), speed, maxspeed))) {\n\t\treturn(false);\n\t} else {\n\t\treturn(true);\n\t}\n}\n\n\n/***************************************************************************\n * Queue_Options -- Queue the options event.                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the options screen event queued successfully?                    *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Options(void)\n{\n\tif (! OutList.Add(EventClass(EventClass::OPTIONS))) {\n\t\treturn(false);\n\t}\n\telse {\n\t\treturn(true);\n\t}\n\n}\t\t/* end of Queue_Options */\n\n\n/***************************************************************************\n * Queue_Exit -- Add the exit game event to the queue.                     *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tWas the exit event queued successfully?                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nbool Queue_Exit(void)\n{\n\tif (! OutList.Add(EventClass(EventClass::EXIT))) {\n\t\treturn(false);\n\t}\n\telse {\n\t\treturn(true);\n\t}\n\n}\t\t/* end of Queue_Exit */\n\n\n/***************************************************************************\n * Queue_AI -- Process all queued events.                                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nvoid Queue_AI(void)\n{\n\tif (Session.Play) {\n\t\tQueue_Playback();\n\t}\n\n\telse {\n\n\t\tswitch (Session.Type) {\n\n\t\t\tcase GAME_SKIRMISH:\n\t\t\tcase GAME_NORMAL:\n\t\t\t\tQueue_AI_Normal();\n\t\t\t\tbreak;\n\n\t\t\tcase GAME_MODEM:\n\t\t\tcase GAME_NULL_MODEM:\n\t\t\tcase GAME_IPX:\n\t\t\tcase GAME_INTERNET:\n\t\t\tcase GAME_TEN:\n\t\t\tcase GAME_MPATH:\n\t\t\t\tQueue_AI_Multiplayer();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\t/* end of Queue_AI */\n\n\n/***************************************************************************\n * Queue_AI_Normal -- Process all queued events.                           *\n *                                                                         *\n * This is the \"normal\" version of the queue management routine.  It does \t*\n * the following:\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Transfers items in the OutList to the DoList\t\t\t\t\t\t\t\t\t*\n * - Executes any commands in the DoList that are supposed to be done on \t*\n *   this frame #\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Cleans out the DoList\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/21/1995 JLB : Created.                                             *\n *=========================================================================*/\nstatic void Queue_AI_Normal(void)\n{\n\t//------------------------------------------------------------------------\n\t//\tMove events from the OutList (events generated by this player) into the\n\t//\tDoList (the list of events to execute).\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count) {\n\t\tOutList.First().IsExecuted = false;\n\t\tif (!DoList.Add(OutList.First())) {\n\t\t\t;\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\t\tOutList.Next();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Save the DoList to disk, if we're in \"Record\" mode\n\t//------------------------------------------------------------------------\n\tif (Session.Record) {\n\t\tQueue_Record();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (!Execute_DoList(1, PlayerPtr->Class->House, NULL, NULL, NULL,\n\t\tNULL, NULL)) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(NULL);\n\n}\t/* end of Queue_AI_Normal */\n\n\n/***************************************************************************\n * Queue_AI_Multiplayer -- Process all queued events.                      *\n *                                                                         *\n * This is the network version of the queue management routine.  It does \t*\n * the following:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If this is the 1st frame, waits for other systems to signal ready\t\t*\n * - Generates a timing event, to allow the connection time to be dynamic\t*\n * - Handles timing related to sending packets every 'n' frames\t\t\t\t*\n * - Sends outgoing events\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Frame-syncs to the other systems (see below)\t\t\t\t\t\t\t\t\t*\n * - Executes & cleans out the DoList\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The Frame-Sync'ing logic is the heart & soul of network play.  It works\t*\n * by ensuring that any system won't out-run the other system by more than\t*\n * 'Session.MaxAhead' frames; this in turn ensures that a packet's \t\t\t*\n * execution frame # won't have been passed by the time that packet is \t\t*\n * received by all systems.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * To achieve this, the system must keep track of all other system's \t\t*\n * current frame #'s; these are stored in an array called 'their_frame[]'. *\n * However, because current frame #'s are sent in FRAMEINFO packets, which *\n * don't require an ACK, and command packets are sent in packets requiring *\n * an ACK, it's possible for a command packet to get lost, and the next \t*\n * frame's FRAMEINFO packet to not get lost; the other system may then \t\t*\n * advance past the frame # the command is to execute on!  So, to prevent \t*\n * this, all FRAMEINFO packets include a CommandCount field.  This value \t*\n * tells the other system how many events it should have received by this \t*\n * time.  This system can therefore keep track of how many commands it's\t*\n * actually received, and compare it to the CommandCount field, to see if \t*\n * it's missed an event packet.  The # of events we've received from each \t*\n * system is stored in 'their_recv[]', and the # events they say they've \t*\n * sent is stored in 'their_sent[]'.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Thus, two conditions must be met in order to advance to the next frame:\t*\n * - Our current frame # must be < their_frame + Session.MaxAhead\t\t\t\t*\n * - their_recv[i] must be >= their_sent[i]\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * 'their_frame[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'their_recv[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'their_sent[] is updated by Process_Receive_Packet()\t\t\t\t\t\t\t*\n * 'my_sent' is updated by this routine.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The order of the arrays their_frame[] etc is the same order the \t\t\t*\n * connections are created in.  The Sender's ID is passed to \t\t\t\t\t*\n * Connection_Index() to obtain the array index.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The only routines allowed to pop up dialogs are:\t\t\t\t\t\t\t\t*\n * \tWait_For_Players() (only pops up the reconnect dialog)\t\t\t\t\t*\n * \tExecute_DoList() (tells if out of sync, or packet recv'd too late)\t*\n *                                                                         *\n * Sign-off's are detected by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Timing out while waiting for a packet\t\t\t\t\t\t\t\t\t\t\t*\n * - Detecting that the other player is now at the score screen or \t\t\t*\n *   connection dialog (serial)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If we see an EventClass::EXIT event on the private channel\t\t\t\t*\n *                                                                         *\n * The current communications protocol, COMM_PROTOCOL_MULTI_E_COMP, has \t*\n * the following properties:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - It compresses packets, so that the minimum number of bytes are \t\t\t*\n *   transmitted.  Packets are compressed by extracting all info common to *\n *   the events into the packet header, and then sending only the bytes \t*\n *   relevant to each type of event.  For instance, if 100 infantry guys \t*\n *   are told to move to the same location, the command itself & the \t\t*\n *   location will be included in the 1st movement command only; after \t\t*\n *   that, there will be a rep count then 99 infantry TARGET numbers, \t\t*\n *   identifying all the infantry told to move.\t\t\t\t\t\t\t\t\t\t*\n * - The protocol also only sends packets out every 'n' frames.  This cuts *\n *   the data rate dramatically.  It means that 'Session.MaxAhead' must be *\n *   divisible by 'n'; also, the minimum value for 'Session.MaxAhead' is \t*\n *   'n * 2', to give both sides some \"breathing\" room in case a FRAMEINFO\t*\n *   packet gets missed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Note:  For synchronization-waiting loops (like waiting to hear from all *\n * other players, waiting to advance to the next frame, etc), use \t\t\t*\n * Net.Num_Connections() rather than Session.NumPlayers; this reflects the *\n * actual # of connections, and can be \"faked\" into playing even when \t\t*\n * there aren't any other players actually there.  A typical example of \t*\n * this is playing back a recorded game.  For command-execution loops, use *\n * Session.NumPlayers.  This ensures all commands get executed, even if \t*\n * there isn't a human generating those commands.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The modem works a little differently from the network in this respect:\t*\n * - The connection has to stay \"alive\" even if the other player exits to \t*\n *   the join dialog.  This prevents each system from timing out & hanging *\n *   the modem up.  Thus, packets are sent back & forth & just thrown away,*\n *   but each system knows the other is still there.  Messages may be sent\t*\n *   between systems, though. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Destroy_Null_Connection doesn't hang up the modem, so \t\t\t\t\t\t*\n *   Num_Connections() still reports a value of 1 even though the other \t*\n *   player has left.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Any waits on Num_Connections() must also check for \t\t\t\t\t\t\t*\n *   Session.NumPlayers > 1, to keep from waiting forever if the other \t\t*\n *   guy has left\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Packets sent to a player who's left require no ACK\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_AI_Multiplayer(void)\n{\n\tif(Session.Type == GAME_SKIRMISH) return;\n\n\treturn;\n#if (0)//PG\n\t//........................................................................\n\t// Enums:\n\t//........................................................................\n\tenum {\n\t\tMIXFILE_RESEND_DELTA = 120,\t// ticks b/w resends\n\t\tMIXFILE_TIMEOUT = 3600*2,\t\t// timeout waiting for mixfiles.\n\t\tFRAMESYNC_DLG_TIME = (3*60),\t// time until displaying reconnect dialog\n\t\tFRAMESYNC_TIMEOUT = (15*60),\t// timeout waiting for frame sync packet\n\t};\n\n\tint timeout_factor = (Session.Type == GAME_INTERNET) ? 6 : 1;\n\n\t//........................................................................\n\t// Variables for sending, receiving & parsing packets:\n\t//........................................................................\n\tConnManClass *net;\t\t\t\t\t// ptr to access all multiplayer functions\n\tEventClass packet;\t\t\t\t\t// for sending single frame-sync's\n\tchar *multi_packet_buf;\t\t\t\t// buffer for sending/receiving\n\tint multi_packet_max;\t\t\t\t// max length of multi_packet_buf\n\n\t//........................................................................\n\t// Frame-sync'ing variables\n\t//........................................................................\n\tstatic long\n\t\ttheir_frame[MAX_PLAYERS - 1];\t// other players' frame #'s\n\tstatic unsigned short\n\t\ttheir_sent[MAX_PLAYERS - 1];\t// # cmds other player claims to have sent\n\tstatic unsigned short\n\t\ttheir_recv[MAX_PLAYERS - 1];\t// # cmds actually received from others\n\tstatic unsigned short\n\t\tmy_sent;\t\t\t\t\t\t\t\t// # cmds I've sent out\n\n\t//........................................................................\n\t// Timing variables\n\t//........................................................................\n\tstatic CDTimerClass<FrameTimerClass> skip_crc;\t// to delay the CRC check\n//\tstatic TCountDownTimerClass skip_crc;\t// to delay the CRC check\n\n\t//........................................................................\n\t// Other misc variables\n\t//........................................................................\n\tint i;\n\tRetcodeType rc;\n\tint reconnect_dlg = 0;\t\t\t\t// 1 = the reconnect dialog is displayed\n\n\t//------------------------------------------------------------------------\n\t//\tInitialize the packet buffer pointer & its max size\n\t//------------------------------------------------------------------------\n#if (0)//PG\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tmulti_packet_buf = NullModem.BuildBuf;\n\t\tmulti_packet_max = NullModem.MaxLen - sizeof (CommHeaderType);\n\t\tnet = &NullModem;\n\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\tmulti_packet_buf = Session.MetaPacket;\n\t\tmulti_packet_max = Session.MetaSize;\n\t\tnet = &Ipx;\n\t}\n#endif\n#if(TEN)\n\telse if (Session.Type == GAME_TEN) {\n\t\tmulti_packet_buf = Session.TenPacket;\n\t\tmulti_packet_max = Session.TenSize;\n\t\tnet = Ten;\n\t}\n#endif\n#if(MPATH)\n\telse if (Session.Type == GAME_MPATH) {\n\t\tmulti_packet_buf = Session.MPathPacket;\n\t\tmulti_packet_max = Session.MPathSize;\n\t\tnet = MPath;\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tDebug stuff\n\t//------------------------------------------------------------------------\n\tInit_Queue_Mono(net);\n\tUpdate_Queue_Mono (net, 0);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the Game's CRC\n\t//------------------------------------------------------------------------\n\tCompute_Game_CRC();\n\tCRC[Frame & 0x001f] = GameCRC;\n\n\t//------------------------------------------------------------------------\n\t//\tIf we've just started a game, or loaded a multiplayer game, we must\n\t// wait for all other systems to signal ready.\n\t//------------------------------------------------------------------------\n\tif (Frame==0 || Session.LoadGame) {\n\t\t//.....................................................................\n\t\t//\tInitialize static locals\n\t\t//.....................................................................\n\t\tfor (i = 0; i < MAX_PLAYERS - 1; i++) {\n\t\t\ttheir_frame[i] = -1;\n\t\t\ttheir_sent[i] = 0;\n\t\t\ttheir_recv[i] = 0;\n\t\t}\n\t\tmy_sent = 0;\n#ifdef FIXIT_MULTI_SAVE\n\t\tskip_crc = 32;\n#else\n\t\tskip_crc = Frame + 32;\n#endif\t// FIXIT_MULTI_SAVE\n\t\tfor (i = 0; i < 32; i++)\n\t\t\tCRC[i] = 0;\n\n\t\t//.....................................................................\n\t\t// If we've loaded a saved game:\n\t\t// - If this game was saved as the result of a lost connection, clear\n\t\t//   the CRC value so it will always match the other system's\n\t\t// - Otherwise, use the GameCRC value, so we'll compare save-game files\n\t\t//   rather than scenario INI files\n\t\t//.....................................................................\n\t\tif (Session.LoadGame) {\n\t\t\tif (Session.EmergencySave)\n\t\t\t\tScenarioCRC = 0;\n\t\t\telse\n\t\t\t\tScenarioCRC = GameCRC;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Send our initial FRAMESYNC packet\n\t\t//.....................................................................\n\t\tSend_FrameSync(net, my_sent);\n\n\t\t//.....................................................................\n\t\t// Wait for the other guys\n\t\t//.....................................................................\n\t\trc = Wait_For_Players (1, net, MIXFILE_RESEND_DELTA, FRAMESYNC_DLG_TIME*timeout_factor,\n\t\t\tMIXFILE_TIMEOUT, multi_packet_buf, my_sent, their_frame,\n\t\t\ttheir_sent, their_recv);\n\n\t\tif (rc != RC_NORMAL) {\n#ifdef WIN32\n\t\t\tif (Session.Type == GAME_INTERNET){\n\t\t\t\tRegister_Game_End_Time();\n\t\t\t}\n#endif\t//WIN32\n\n\t\t\tif (rc == RC_NOT_RESPONDING) {\n\t\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t\t}\n\t\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\t\tWWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);\n\t\t\t}\n\t\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\t\tWWMessageBox().Process(TXT_QUEUE_FULL);\n\t\t\t}\n\t\t\tStop_Game();\n\t\t\treturn;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tRe-initialize frame numbers (in case somebody signed off while I was\n\t\t//\twaiting for MIX files to load; we would have fallen through, but\n\t\t//\ttheir frame # would still be -1).\n\t\t//.....................................................................\n\t\tfor (i = 0; i < MAX_PLAYERS - 1; i++)\n\t\t\ttheir_frame[i] = 0;\n\n\t\t//.....................................................................\n\t\t//\tReset the network response time computation, now that we're both\n\t\t// sending data again  (loading MIX files will have introduced\n\t\t// deceptively large values).\n\t\t//.....................................................................\n\t\tnet->Reset_Response_Time();\n\n\t\t//.....................................................................\n\t\t// Initialize the frame timers\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tProcess_Send_Period(net);//, 1);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Turn off our special load-game flags\n\t\t//.....................................................................\n\t\tif (Session.LoadGame) {\n\t\t\tSession.EmergencySave = false;\n\t\t\tSession.LoadGame = false;\n\t\t}\n\n\t} \t// end of Frame 0 wait\n\n\t//------------------------------------------------------------------------\n\t// Adjust connection timing parameters every 128 frames.\n\t//------------------------------------------------------------------------\n\n\telse if ( (Frame & 0x007f) == 0) {\n\t\t//\n\t\t// If we're using the new spiffy protocol, do proper timing handling.\n\t\t// If we're the net \"master\", compute our desired frame rate & new\n\t\t// 'MaxAhead' value.\n\t\t//\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\n\t\t\t//\n\t\t\t// All systems will transmit their required process time.\n\t\t\t//\n\t\t\tGenerate_Process_Time_Event(net);\n\n\t\t\t//\n\t\t\t// The game \"host\" will transmit timing adjustment events.\n\t\t\t//\n\t\t\tif (Session.Am_I_Master()) {\n\t\t\t\tGenerate_Real_Timing_Event(net, my_sent);\n\t\t\t}\n\t\t} else {\n\t\t\t//\n\t\t\t// For the older protocols, do the old broken timing handling.\n\t\t\t//\n\t\t\tGenerate_Timing_Event(net, my_sent);\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Only process every 'FrameSendRate' frames\n\t//------------------------------------------------------------------------\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tif (!Process_Send_Period(net)) {\t//, 0)) {\n\t\t\tif (IsMono) {\n\t\t\t\tMonoClass::Disable();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Send our data packet(s); update my command-sent counter\n\t//------------------------------------------------------------------------\n\tmy_sent += Send_Packets(net, multi_packet_buf, multi_packet_max,\n\t\tSession.MaxAhead, my_sent);\n\n\t//------------------------------------------------------------------------\n\t//\tIf this is our first time through, we're done.\n\t//------------------------------------------------------------------------\n\tif (Frame==0) {\n\t\tif (IsMono) {\n\t\t\tMonoClass::Disable();\n\t\t}\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFrame-sync'ing: wait until it's OK to advance to the next frame.\n\t//------------------------------------------------------------------------\n#ifdef FIXIT_VERSION_3\n\tint iFramesyncTimeout;\n\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.iPlayerCount > 2 )\n\t\t//\tShortened resync timeout for non-2 player games.\n\t\tiFramesyncTimeout = 5 * 60;\t\t//\tOne minute.\n\telse\n\t\tiFramesyncTimeout = FRAMESYNC_TIMEOUT;\n\n\trc = Wait_For_Players (0, net,\n\t\t(Session.MaxAhead << 3),\n\t\tMAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),\n\t\tiFramesyncTimeout * (2*timeout_factor),\n\t\tmulti_packet_buf, my_sent, their_frame,\n\t\ttheir_sent, their_recv);\n#else\n\t\trc = Wait_For_Players (0, net,\n\t\t(Session.MaxAhead << 3),\n\t\tMAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),\n\t\tFRAMESYNC_TIMEOUT* (2*timeout_factor),\n\t\tmulti_packet_buf, my_sent, their_frame,\n\t\ttheir_sent, their_recv);\n#endif\n\n\tif (rc != RC_NORMAL) {\n#ifdef WIN32\n\t\t\tif (Session.Type == GAME_INTERNET){\n\t\t\t\tRegister_Game_End_Time();\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\tNew rule - if you cancel a waiting to reconnect dialog, you lose.\n\t\t\t\tbReconnectDialogCancelled = ( rc == RC_CANCEL );\n#endif\n\t\t\t}\n#endif\t//WIN32\n\t\tif (rc == RC_NOT_RESPONDING) {\n\t\t\tWWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);\n\t\t}\n\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\tWWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);\n\t\t}\n\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\tWWMessageBox().Process(TXT_QUEUE_FULL);\n\t\t}\n\t\tStop_Game();\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the DoList to disk, if we're in \"Record\" mode\n\t//------------------------------------------------------------------------\n\tif (Session.Record) {\n\t\tQueue_Record();\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (!Execute_DoList(Session.MaxPlayers, HOUSE_MULTI1, net, &skip_crc,\n\t\ttheir_frame, their_sent, their_recv)) {\n#ifdef WIN32\n\t\tif (Session.Type == GAME_INTERNET){\n\t\t\tRegister_Game_End_Time();\n\t\t}\n#endif\t//WIN32\n\t\tStop_Game();\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(net);\n\n\tif (IsMono) {\n\t\tMonoClass::Disable();\n\t}\n#endif\n}\t// end of Queue_AI_Multiplayer\n\n\n/***************************************************************************\n * Wait_For_Players -- Waits for other systems to come on-line             *\n *                                                                         *\n * This routine performs the most critical logic in multiplayer; that of\t*\n * synchronizing my frame number with those of the other systems.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfirst_time\t\t\t\t1 = 1st time this routine is called\t\t\t\t\t*\n *\t\tnet\t\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t*\n *\t\tresend_delta\t\t\ttime (ticks) between FRAMESYNC resends\t\t\t\t*\n *\t\tdialog_time\t\t\t\ttime (ticks) until pop up a reconnect dialog\t\t*\n *\t\ttimeout\t\t\t\t\ttime (ticks) until we give up the ghost\t\t\t*\n *\t\tmulti_packet_buf\t\tbuffer to store packets in\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent so far\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\t\tarray of their frame #'s\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\t\t\t\tarray of their CommandCount values\t\t\t\t\t*\n *\t\ttheir_recv\t\t\t\tarray of # cmds I've received from them\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL\t\t\t\tOK to advance to the next frame\t\t\t\t\t\t*\n *\t\tRC_CANCEL\t\t\t\tuser hit 'Cancel' at the timeout countdown dlg\t*\n *\t\tRC_NOT_RESPONDING\t\tother player(s) not responding\t\t\t\t\t\t*\n *\t\tRC_SCENARIO_MISMATCH\tscenario's don't match (first_time only)\t\t\t*\n *\t\tRC_DOLIST_FULL\t\t\tDoList was full\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Wait_For_Players(int first_time, ConnManClass *net,\n\tint resend_delta, int dialog_time, int timeout, char *multi_packet_buf,\n\tint my_sent, long *their_frame, unsigned short *their_sent,\n\tunsigned short *their_recv)\n{\n\t//........................................................................\n\t// Variables for sending, receiving & parsing packets:\n\t//........................................................................\n\tEventClass *event;\t\t\t\t\t// event ptr for parsing incoming packets\n\tint packetlen;\t\t\t\t\t\t\t// size of meta-packet sent, & received\n\tint id;\t\t\t\t\t\t\t\t\t// id of other player\n\tint messages_this_loop;\t\t\t\t// to limit # messages processed each loop\n\tint message_limit;\t\t\t\t\t// max # messages we'll read each frame\n\n\t//........................................................................\n\t// Variables used only if 'first_time':\n\t//........................................................................\n\tint num_ready;\t\t\t\t\t\t\t// # players signalling ready\n\n\t//........................................................................\n\t// Timing variables\n\t//........................................................................\n\tCDTimerClass<SystemTimerClass> retry_timer;\t\t// time between FRAMESYNC packet resends\n\tCDTimerClass<SystemTimerClass> dialog_timer;\t// time to pop up a dialog\n\tCDTimerClass<SystemTimerClass> timeout_timer;\t// general-purpose timeout\n\n\t//........................................................................\n\t// Dialog variables\n\t//........................................................................\n\tint reconnect_dlg = 0;\t\t\t\t// 1 = the reconnect dialog is displayed\n\n\t//........................................................................\n\t// Other misc variables\n\t//........................................................................\n\tKeyNumType input;\t\t\t\t\t\t// for user input\n\tint x,y;\t\t\t\t\t\t\t\t\t// for map input\n\tRetcodeType rc;\n\n\t//------------------------------------------------------------------------\n\t// Wait to hear from all other players\n\t//------------------------------------------------------------------------\n\tnum_ready = 0;\n\tretry_timer = resend_delta;\t// time to retry\n\tdialog_timer = dialog_time;\t// time to show dlg\n\ttimeout_timer = timeout;\t\t// time to bail out\n\n\twhile (1) {\n\t\tKeyboard->Check();\n\n\t\tUpdate_Queue_Mono (net, 2);\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tResend a frame-sync packet if longer than one propagation delay goes\n\t\t// by; this prevents a \"deadlock\".  If he's waiting for me to advance,\n\t\t// but has missed my last few FRAMEINFO packets, I may be waiting for\n\t\t// him to advance.  Resending a FRAMESYNC ensures he knows what frame\n\t\t// number I'm on.\n\t\t//---------------------------------------------------------------------\n\t\tif (!retry_timer) {\n\t\t\tretry_timer = resend_delta;\t\t// time to retry\n\t\t\tUpdate_Queue_Mono (net, 3);\n\t\t\tSend_FrameSync(net, my_sent);\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tService the connections\n\t\t//---------------------------------------------------------------------\n\t\tnet->Service();\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tPop up a reconnect dialog if enough time goes by\n\t\t//---------------------------------------------------------------------\n\t\tif (!dialog_timer && SpecialDialog==SDLG_NONE) {\n\t\t\tif (reconnect_dlg == 0 && first_time == 0) {\n\t\t\t\tFILE *fp;\n\t\t\t\tint i;\n\t\t\t\tHouseClass *housep;\n\n\t\t\t\tfp = fopen(\"recon.txt\",\"wt\");\n\t\t\t\tif (fp) {\n\t\t\t\t\tfprintf(fp,\"# Connections: %d\\n\",net->Num_Connections());\n\t\t\t\t\tfprintf(fp,\"   My Frame #: %d\\n\",Frame);\n\t\t\t\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\t\t\t\thousep = HouseClass::As_Pointer((HousesType)(net->Connection_ID(i)));\n\t\t\t\t\t\tfprintf(fp,\"%15s: Their Sent:%d  Their Recv:%d  Their Frame:%d\\n\",\n\t\t\t\t\t\t\thousep->IniName, their_sent[i], their_recv[i], their_frame[i]);\n\t\t\t\t\t}\n\t\t\t\t\tfclose(fp);\n\t\t\t\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\t\"Reconnecting\" dialog is about to be shown.\n\t\t\t\t//\tAt this point, begin wolapi \"disconnect pinging\", if appropriate.\n\t\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )\n\t\t\t\t\tpWolapi->Init_DisconnectPinging();\n#endif\n\t\t\t}\n\n\t\t\tif (Process_Reconnect_Dialog(&timeout_timer, their_frame,\t\t\t\t//\t(Returns immediately.)\n\t\t\t\tnet->Num_Connections(), (first_time==0), (reconnect_dlg==0))) {\n\t\t\t\treturn (RC_CANCEL);\n\t\t\t}\n\t\t\treconnect_dlg = 1;\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t//\tContinue wolapi \"disconnect pinging\", if appropriate.\n\t\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && pWolapi->bDoingDisconnectPinging )\n\t\t\t\t\tpWolapi->Pump_DisconnectPinging();\n#endif\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tExit if too much time goes by (the other system has crashed or\n\t\t// bailed)\n\t\t//---------------------------------------------------------------------\n\t\tif (!timeout_timer) {\n\t\t\t//..................................................................\n\t\t\t// For the first-time run, just give up; something's wrong.\n\t\t\t//..................................................................\n\t\t\tif (first_time) {\n\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Otherwise, we're in the middle of a game; so, the modem &\n\t\t\t// network must deal with a timeout differently.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tUpdate_Queue_Mono (net, 4);\n\n\t\t\t\tif (Handle_Timeout(net, their_frame, their_sent, their_recv)) {\n\t\t\t\t\tMap.Flag_To_Redraw(true);\t// erase modem reconnect dialog\n\t\t\t\t\tMap.Render();\n\t\t\t\t\tretry_timer = resend_delta;\n\t\t\t\t\tdialog_timer = dialog_time;\n\t\t\t\t\ttimeout_timer = timeout;\n\t\t\t\t}\n#ifdef FIXIT_MULTI_SAVE\n#ifdef FIXIT_VERSION_3\n\t\t\t\telse if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) ) {\n#else\n\t\t\t\telse if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) &&\n\t\t\t\t\t        PlayingAgainstVersion != VERSION_RED_ALERT_104) {\n#endif\n\t\t\t\t\tif (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING,\n\t\t\t\t\t\tTXT_YES, TXT_NO, TXT_NONE) == 0) {\n\t\t\t\t\t\tSession.EmergencySave = 1;\n//printf(\"Saving emergency game; frame:%d, CRC:%d\\n\",Frame,GameCRC);\n//Print_CRCs(NULL);\n//printf(\"Before Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n//\tScen.RandomNumber.Count1,\n//\tScen.RandomNumber.Count2,\n//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\tSave_Game(-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n//printf(\"After Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n//\tScen.RandomNumber.Count1,\n//\tScen.RandomNumber.Count2,\n//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\tSession.EmergencySave = 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn (RC_CANCEL);\n\t\t\t\t}\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\telse {\n\t\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tCheck for an incoming message.  We must still process commands\n\t\t// even if 'first_time' is set, in case the other system got my 1st\n\t\t// FRAMESYNC, but I didn't get his; he'll be at the next frame, and\n\t\t// may be sending commands.\n\t\t// We have to limit the number of incoming messages we handle; it's\n\t\t// possible to go into an infinite loop processing modem messages.\n\t\t// (This feature is disabled for Ten; we need to keep the TCP buffers\n\t\t// clear, so we read all the packets we can every time.)\n\t\t//---------------------------------------------------------------------\n\t\tmessages_this_loop = 0;\n\t\tmessage_limit = 5;\n\n\t\tif (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\t\tmessage_limit = 9999;\n\t\t}\n\n\t\twhile ( (messages_this_loop++ < message_limit) &&\n\t\t\tnet->Get_Private_Message (multi_packet_buf, &packetlen, &id) ) {\n\n\t\t\tKeyboard->Check();\n\n\t\t\tUpdate_Queue_Mono (net, 5);\n\n\t\t\t/*..................................................................\n\t\t\tGet an event ptr to the incoming message\n\t\t\t..................................................................*/\n\t\t\tevent = (EventClass *)multi_packet_buf;\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t// Special processing for a modem game: process SERIAL packets\n\t\t\t//------------------------------------------------------------------\n\t\t\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\t\t\trc = Process_Serial_Packet(multi_packet_buf, first_time);\n\t\t\t\t//...............................................................\n\t\t\t\t// SERIAL packet received & processed\n\t\t\t\t//...............................................................\n\t\t\t\tif (rc == RC_SERIAL_PROCESSED) {\n\t\t\t\t\tnet->Service();\n\t\t\t\t\tretry_timer = resend_delta;\n\t\t\t\t\tdialog_timer = dialog_time;\n\t\t\t\t\ttimeout_timer = timeout;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// other player has left the game\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc == RC_PLAYER_LEFT) {\n\t\t\t\t\tif (first_time) {\n\t\t\t\t\t\tnum_ready++;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Connection was lost\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc == RC_HUNG_UP) {\n#ifdef FIXIT_MULTI_SAVE\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\tif (PlayingAgainstVersion != VERSION_RED_ALERT_104){\n#endif\n\t\t\t\t\t\tif (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_HUNG_UP,\n\t\t\t\t\t\t\tTXT_YES, TXT_NO, TXT_NONE) == 0) {\n\t\t\t\t\t\t\tSession.EmergencySave = 1;\n\t//printf(\"Saving emergency game; frame:%d, CRC:%d\\n\",Frame,GameCRC);\n\t//Print_CRCs(NULL);\n\t//printf(\"Before Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n\t//\tScen.RandomNumber.Count1,\n\t//\tScen.RandomNumber.Count2,\n\t//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\t\tSave_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t//printf(\"After Save: Count1:%d, Count2:%d, Seed:%d\\n\",\n\t//\tScen.RandomNumber.Count1,\n\t//\tScen.RandomNumber.Count2,\n\t//\tScen.RandomNumber.Seed);\n\t\t\t\t\t\t\tSession.EmergencySave = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn (RC_CANCEL);\n#ifndef FIXIT_VERSION_3\n\t\t\t\t\t}else{\n\t\t\t\t\t\treturn (RC_NOT_RESPONDING);\n\t\t\t\t\t}\n#endif\n\n#else\n\t\t\t\t\treturn (RC_NOT_RESPONDING);\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// If it was any other type of serial packet, break\n\t\t\t\t//...............................................................\n\t\t\t\telse if (rc != RC_NORMAL) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//------------------------------------------------------------------\n\t\t\t//\tProcess the incoming packet\n\t\t\t//------------------------------------------------------------------\n\t\t\trc = Process_Receive_Packet(net, multi_packet_buf, id, packetlen,\n\t\t\t\ttheir_frame, their_sent, their_recv);\n\t\t\t//..................................................................\n\t\t\t// New player heard from\n\t\t\t//..................................................................\n\t\t\tif (rc == RC_PLAYER_READY) {\n\t\t\t\tnum_ready++;\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Scenario's don't match\n\t\t\t//..................................................................\n\t\t\telse if (rc == RC_SCENARIO_MISMATCH) {\n\t\t\t\treturn (RC_SCENARIO_MISMATCH);\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// DoList was full\n\t\t\t//..................................................................\n\t\t\telse if (rc == RC_DOLIST_FULL) {\n\t\t\t\treturn (RC_DOLIST_FULL);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t//\tService the connection, to clean out the receive queues\n\t\t\t//..................................................................\n\t\t\tnet->Service();\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t// Debug output\n\t\t//---------------------------------------------------------------------\n\t\tPrint_Framesync_Values(Frame, Session.MaxAhead, net->Num_Connections(),\n\t\t\ttheir_recv, their_sent, my_sent);\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tAttempt to advance to the next frame.\n\t\t//---------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t// For the first-time run, just check to see if we've heard from\n\t\t// everyone.\n\t\t//.....................................................................\n\t\tif (first_time) {\n\t\t\tif (num_ready >= net->Num_Connections()) {\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// For in-game processing, we have to check their_sent, their_recv,\n\t\t// their_frame, etc.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tif (Can_Advance(net, Session.MaxAhead, their_frame, their_sent,\n\t\t\t\ttheir_recv)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t//\tService game stuff.  Servicing the map's input, and rendering the\n\t\t//\tmap, allows the map to scroll even though we're hung up waiting for\n\t\t//\tpackets.  Don't do this if 'first_time' is set, since users could be\n\t\t// waiting a very long time for all systems to load the scenario, and\n\t\t// it gets frustrating being able to scroll around without doing\n\t\t// anything.\n\t\t//---------------------------------------------------------------------\n\t\tCall_Back();\n\t\tif (!first_time && SpecialDialog == SDLG_NONE && reconnect_dlg==0) {\n#ifdef WIN32\n\t\t\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n#endif\t//WIN32\n\t\t\tMap.Input(input, x, y);\n\t\t\tif (input)\n\t\t\t\tKeyboard_Process(input);\n\t\t\tMap.Render();\n\t\t}\n\n\t}\t/* end of while */\n\n\t//------------------------------------------------------------------------\n\t//\tIf the reconnect dialog was shown, force the map to redraw.\n\t//------------------------------------------------------------------------\n\tif (reconnect_dlg) {\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n\n\treturn (RC_NORMAL);\n\n}\t// end of Wait_For_Players\n\n\n/***************************************************************************\n * Generate_Timing_Event -- computes & queues a RESPONSE_TIME event        *\n *                                                                         *\n * This routine adjusts the connection timing on the local system; it also\t*\n * optionally generates a RESPONSE_TIME event, to tell all systems to\t\t*\n * dynamically adjust the current MaxAhead value.  This allows both the\t\t*\n * MaxAhead & the connection retry logic to have dynamic timing, to adjust\t*\n * to varying line conditions.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t# commands I've sent out so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Timing_Event(ConnManClass *net, int my_sent)\n{\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\tEventClass ev;\n\n\t//\n\t// For now, TEN & MPATH don't measure the net's response time, so there's\n\t// no point in adjusting our timing.  Do nothing.\n\t//\n\tif (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, divide again by 4, assuming a game rate of 15 fps.\n\t//------------------------------------------------------------------------\n\tresp_time = net->Response_Time();\n\n\t//------------------------------------------------------------------------\n\t//\tAdjust my connection retry timing; only do this if I've sent out more\n\t//\tthan 5 commands, so I know I have a measure of the response time.\n\t//------------------------------------------------------------------------\n\tif (my_sent > 5) {\n\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\n\t\t//.....................................................................\n\t\t// If I'm the network \"master\", I'm also responsible for updating the\n\t\t// MaxAhead value on all systems, so do that here too.\n\t\t//.....................................................................\n\t\tif (Session.Am_I_Master()) {\n\t\t\tev.Type = EventClass::RESPONSE_TIME;\n\t\t\t//..................................................................\n\t\t\t// For multi-frame compressed events, the MaxAhead must be an even\n\t\t\t// multiple of the FrameSendRate.\n\t\t\t//..................................................................\n\t\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\t\tev.Data.FrameInfo.Delay = max( ((((resp_time / 8) +\n\t\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\t\tSession.FrameSendRate), (Session.FrameSendRate * 2) );\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// For sending packets every frame, just use the 1-way connection\n\t\t\t// response time.\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t MODEM_MIN_MAX_AHEAD );\n\t\t\t\t} else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t NETWORK_MIN_MAX_AHEAD );\n\t\t\t\t}\n\t\t\t\telse if (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\t\t\t\tev.Data.FrameInfo.Delay = max( (resp_time / 8),\n\t\t\t\t\t\t MODEM_MIN_MAX_AHEAD );\n\t\t\t\t}\n\t\t\t}\n\t\t\tOutList.Add(ev);\n\t\t}\n\t}\n\n}\t// end of Generate_Timing_Event\n\n\n/***************************************************************************\n * Generate_Real_Timing_Event -- Generates a TIMING event                  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t# commands I've sent out so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1996 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Real_Timing_Event(ConnManClass *net, int my_sent)\n{\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\tEventClass ev;\n\tint highest_ticks;\n\tint i;\n\tint specified_frame_rate;\n\tint maxahead;\n\n\t//\n\t// If we haven't sent out at least 5 guaranteed-delivery packets, don't\n\t// bother trying to measure our connection response time; just return.\n\t//\n\tif (my_sent < 5) {\n\t\treturn;\n\t}\n\n\t//\n\t// Find the highest processing time we have stored\n\t//\n\thighest_ticks = 0;\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t//\n\t\t// If we haven't heard from all systems yet, bail out.\n\t\t//\n\t\tif (Session.Players[i]->Player.ProcessTime == -1) {\n\t\t\treturn;\n\t\t}\n\t\tif (Session.Players[i]->Player.ProcessTime > highest_ticks) {\n\t\t\thighest_ticks = Session.Players[i]->Player.ProcessTime;\n\t\t}\n\t}\n\n\t//\n\t// Compute our \"desired\" frame rate as the lower of:\n\t// - What the user has dialed into the options screen\n\t// - What we're really able to run at\n\t//\n\tif (highest_ticks == 0) {\n\t\tSession.DesiredFrameRate = 60;\n\t} else {\n\t\tSession.DesiredFrameRate = 60 / highest_ticks;\n\t}\n\n\tif (Options.GameSpeed == 0) {\n\t\tspecified_frame_rate = 60;\n\t} else {\n\t\tspecified_frame_rate = 60 / Options.GameSpeed;\n\t}\n\n\tSession.DesiredFrameRate = MIN (Session.DesiredFrameRate, specified_frame_rate);\n\n\t//\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, ....uh....\n\t//\n\tresp_time = net->Response_Time();\n\n\t//\n\t// Compute our new 'MaxAhead' value, based upon the response time of our\n\t// connection and our desired frame rate.\n\t// 'MaxAhead' in frames is:\n\t//\n\t// (resp_time / 2 ticks) * (1 sec/60 ticks) * (n Frames / sec)\n\t//\n\t// resp_time is divided by 2 because, as reported, it represents a round-\n\t// trip, and we only want to use a one-way trip.\n\t//\n\tmaxahead = (resp_time * Session.DesiredFrameRate) / (2 * 60);\n\n\t//\n\t// Now, we have to round 'maxahead' so it's an even multiple of our\n\t// send rate.  It also must be at least thrice the FrameSendRate.\n\t// (Isn't \"thrice\" a cool word?)\n\t//\n\tmaxahead = ((maxahead + Session.FrameSendRate - 1) / Session.FrameSendRate) * Session.FrameSendRate;\n\tmaxahead = MAX (maxahead, (int)Session.FrameSendRate * 3);\n\n\tev.Type = EventClass::TIMING;\n\tev.Data.Timing.DesiredFrameRate = Session.DesiredFrameRate;\n\tev.Data.Timing.MaxAhead = maxahead;\n\n\tOutList.Add(ev);\n\n\t//\n\t//\tAdjust my connection retry timing.  These values set the retry timeout\n\t// to just over one round-trip time, the 'maxretries' to -1, and the\n\t// connection timeout to allow for about 4 retries.\n\t//\n\t//net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\n\tif (Session.Type == GAME_INTERNET) {\n\t\tnet->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);\n\t}else{\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\t}\n\n}\n\n\n/***************************************************************************\n * Generate_Process_Time_Event -- Generates a PROCESS_TIME event           *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   07/02/1996 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Generate_Process_Time_Event(ConnManClass *net)\n{\n\tEventClass ev;\n\tint avgticks;\n\tunsigned long resp_time;\t\t\t// connection response time, in ticks\n\n\t//\n\t// Measure the current connection response time.  This time will be in\n\t// 60ths of a second, and represents full round-trip time of a packet.\n\t// To convert to one-way packet time, divide by 2; to convert to game\n\t// frames, ....uh....\n\t//\n\tresp_time = net->Response_Time();\n\n\t//\n\t//\tAdjust my connection retry timing.  These values set the retry timeout\n\t// to just over one round-trip time, the 'maxretries' to -1, and the\n\t// connection timeout to allow for about 4 retries.\n\t//\n\t//net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\tif (Session.Type == GAME_INTERNET) {\n\t\tnet->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);\n\t}else{\n\t\tnet->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);\n\t}\n\n\n\tif (IsMono) {\n\t\tMonoClass::Enable();\n\t\tMono_Set_Cursor(0,23);\n\t\tMono_Printf(\"Processing Ticks:%03d Frames:%03d\\n\", Session.ProcessTicks,Session.ProcessFrames);\n\t\tMonoClass::Disable();\n\t}\n\n\tavgticks = Session.ProcessTicks / Session.ProcessFrames;\n\n\tev.Type = EventClass::PROCESS_TIME;\n\tev.Data.ProcessTime.AverageTicks = avgticks;\n\tOutList.Add(ev);\n\n\tSession.ProcessTicks = 0;\n\tSession.ProcessFrames = 0;\n}\n\n\n/***************************************************************************\n * Process_Send_Period -- timing for sending packets every 'n' frames      *\n *                                                                         *\n * This function is for a CommProtocol of COMM_PROTOCOL_MULTI_E_COMP only.\t*\n * It determines if it's time to send a packet or not.\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = it's time to send a packet; 0 = don't send a packet this frame.\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Process_Send_Period(ConnManClass *net)\t//, int init)\n{\n\t//------------------------------------------------------------------------\n\t// If the current frame # is not an even multiple of 'FrameSendRate', then\n\t// it's not time to send a packet; just return.\n\t//------------------------------------------------------------------------\n\tif (Frame != (((Frame + (Session.FrameSendRate - 1)) /\n\t\tSession.FrameSendRate) * Session.FrameSendRate) ) {\n\n\t\tnet->Service();\n\n\t\tif (IsMono) {\n\t\t\tMonoClass::Disable();\n\t\t}\n\n\t\treturn (0);\n\t}\n\n\treturn (1);\n\n\n}\t// end of Process_Send_Period\n\n\n/***************************************************************************\n * Send_Packets -- sends out events from the OutList                       *\n *                                                                         *\n * This routine computes how many events can be sent this frame, and then\t*\n * builds the \"meta-packet\" & sends it.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The 'cap' value is the max # of events we can send.  Ideally, it should\t*\n * be based upon the bandwidth of our connection.  Currently, it's just\t\t*\n * hardcoded to prevent the modem from having to resend \"too much\" data,\t*\n * which is about 200 bytes per frame.\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_buf\t\tbuffer to store packets in\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_max\t\tmax size of multi_packet_buf\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\t\t\tcurrent game MaxAhead value\t\t\t\t\t\t\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent this game\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events sent, NOT including the FRAMEINFO event\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Send_Packets(ConnManClass *net, char *multi_packet_buf,\n\tint multi_packet_max, int max_ahead, int my_sent)\n{\n\tint cap;\t\t\t\t// max # events to send, NOT including FRAMEINFO event\n\tint do_once;\t\t// true: only go through packet loop once\n\tint ack_req;\t\t// 0 = no ack required on outgoing packet\n\tint packetlen;\t\t// size of meta-packet sent\n\n\t//------------------------------------------------------------------------\n\t//\tDetermine how many events it's OK to send this frame.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// If we have 4 or more packets queued for sending, don't add any more\n\t// this frame.\n\t//........................................................................\n\tif (net->Private_Num_Send() >= 4) {\n\t\tcap = 0;\n\t\tdo_once = 1;\n\t}\n\t//........................................................................\n\t// If there are 2 or more packets queued, the entire packet we send must\n\t// fit within a single ComQueue buffer, so limit # events to 5.\n\t// (The Modem connection manager has a max buffer size of 200 bytes, which\n\t// is large enough for 6 uncompressed events, which leaves room for 5\n\t// events plus a FRAMEINFO.)\n\t//........................................................................\n\telse if (net->Private_Num_Send() >= 2) {\n\t\tcap = 5;\n\t\tdo_once = 1;\n\n\t}\n\t//........................................................................\n\t// Otherwise, just send all events in the OutList\n\t//........................................................................\n\telse {\n\t\tcap = OutList.Count;\n\t\tdo_once = 0;\n\t}\n\n\t//........................................................................\n\t// Make sure we aren't sending more events than are in the OutList\n\t//........................................................................\n\tif (cap > OutList.Count) {\n\t\tcap = OutList.Count;\n\t}\n\n\t//........................................................................\n\t// Make sure we don't send so many events that our DoList fills up\n\t//........................................................................\n\tif (cap > (MAX_EVENTS * 64) - DoList.Count) {\n\t\tcap = (MAX_EVENTS * 64) - DoList.Count;\n\t}\n\n\t//\n\t// 10/21/96 5:12PM - ST\n\t//\n\tif (Session.Type == GAME_INTERNET || Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM){\n\t\tcap = OutList.Count;\n\t\tdo_once = 0;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tBuild our meta-packet & transmit it.\n\t//------------------------------------------------------------------------\n\twhile (1) {\n\t\tKeyboard->Check();\n\n\t\tUpdate_Queue_Mono (net, 1);\n\n\t\t//.....................................................................\n\t\t//\tIf there are no commands this frame, we'll just be sending a FRAMEINFO\n\t\t//\tpacket; no ack is required.  For the modem's sake, check\n\t\t// Session.NumPlayers; no ACK is needed if we're just sending to someone\n\t\t// who's left the game.\n\t\t//.....................................................................\n\t\tif (cap == 0 || OutList.Count == 0 || Session.NumPlayers == 1) {\n\t\t\tack_req = 0;\n\t\t}\n\t\telse {\n\t\t\tack_req = 1;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tBuild & send out our message\n\t\t//.....................................................................\n\t\tpacketlen = Build_Send_Packet (multi_packet_buf, multi_packet_max,\n\t\t\tmax_ahead, my_sent, cap);\n\t\tnet->Send_Private_Message (multi_packet_buf, packetlen, ack_req);\n\n\t\t//.....................................................................\n\t\t//\tCall Service() to actually send the packet\n\t\t//.....................................................................\n\t\tnet->Service();\n\n\t\t//.....................................................................\n\t\t//\tStop if there's no more data to send, or if our send queue is\n\t\t// filling up.\n\t\t//.....................................................................\n\t\tif (OutList.Count == 0 || do_once) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn (cap);\n\n}\t// end of Send_Packets\n\n\n/***************************************************************************\n * Send_FrameSync -- Sends a FRAMESYNC packet                              *\n *                                                                         *\n * This routine is used to periodically remind the other systems that \t\t*\n * we're still here, and to tell them what frame # we're on, in case\t\t\t*\n * they've missed my FRAMEINFO packets.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tcmd_count\t\t# commands I've sent so far\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Send_FrameSync(ConnManClass *net, int cmd_count)\n{\n\tEventClass packet;\n\n\t//------------------------------------------------------------------------\n\t//\tBuild a frame-sync event to send.  FRAMESYNC packets contain a\n\t// scenario-based CRC rather than a game-state-based CRC, to let the\n\t// games compare scenario CRC's on startup.\n\t//------------------------------------------------------------------------\n\tmemset (&packet, 0, sizeof(EventClass));\n\tpacket.Type = EventClass::FRAMESYNC;\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tpacket.Frame = ((Frame + Session.MaxAhead + (Session.FrameSendRate - 1)) /\n\t\t\t Session.FrameSendRate) * Session.FrameSendRate;\n\t}\n\telse {\n\t\tpacket.Frame = Frame + Session.MaxAhead;\n\t}\n\tpacket.ID = PlayerPtr->ID;\n\tpacket.Data.FrameInfo.CRC = ScenarioCRC;\n\tpacket.Data.FrameInfo.CommandCount = cmd_count;\n\tpacket.Data.FrameInfo.Delay = Session.MaxAhead;\n\n\t//------------------------------------------------------------------------\n\t// Send the event.  For modem, this just sends to the other player;\n\t// for network, it sends to everyone we're connected to.\n\t//------------------------------------------------------------------------\n\n\tnet->Send_Private_Message (&packet, (offsetof(EventClass, Data) +\n\t\tsize_of(EventClass, Data.FrameInfo)), 0 );\n\n\treturn;\n\n}\t// end of Send_FrameSync\n\n\n/***************************************************************************\n * Process_Receive_Packet -- processes an incoming packet                  *\n *                                                                         *\n * This routine receives a packet from another system, adds it to our\t\t*\n * execution queue (the DoList), and updates my arrays of their frame #,\t*\n * their commands-sent, and their commands-received.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t*\n *\t\tmulti_packet_buf\tbuffer containing packet(s) to parse\t\t\t\t\t*\n *\t\tid\t\t\t\t\t\tid of sender\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\tarray containing frame #'s of other players\t\t\t*\n *\t\ttheir_sent\t\t\tarray containing command count of other players\t\t*\n *\t\ttheir_recv\t\t\tarray containing # recv'd cmds from other players\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL:\t\t\t\t\tnothing unusual happened, although \t\t\t\t*\n * \t\t\t\t\t\t\t\t\ttheir_sent or their_recv may have been \t\t*\n *\t\t\t\t\t\t\t\t\t\taltered\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tRC_PLAYER_READY:\t\t\tplayer has been heard from for the 1st time; *\n * \t\t\t\t\t\t\t\t\tthis presumes that his original \t\t\t\t\t*\n * \t\t\t\t\t\t\t\t\t'their_frame[]' value was -1 when this \t\t*\n * \t\t\t\t\t\t\t\t\troutine was called\t\t\t\t\t\t\t\t\t*\n *\t\tRC_SCENARIO_MISMATCH:\tFRAMEINFO scenario CRC doesn't match; \t\t\t*\n * \t\t\t\t\t\t\t\t\tnormally only applies after loading a new \t*\n * \t\t\t\t\t\t\t\t\tscenario or save-game\t\t\t\t\t\t\t\t*\n *\t\tRC_DOLIST_FULL:\t\t\tfatal error; unable to add events to DoList\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Process_Receive_Packet(ConnManClass *net,\n\tchar *multi_packet_buf, int id, int packetlen, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tEventClass *event;\n\tint index;\n\tRetcodeType retcode = RC_NORMAL;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tGet an event ptr to the incoming message\n\t//------------------------------------------------------------------------\n\tevent = (EventClass *)multi_packet_buf;\n\n\t//------------------------------------------------------------------------\n\t//\tGet the index of the sender\n\t//------------------------------------------------------------------------\n\tindex = net->Connection_Index(id);\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the other player's frame # (at the time this packet was sent)\n\t//------------------------------------------------------------------------\n\tif (their_frame[index] <\n\t\t(int)(event->Frame - event->Data.FrameInfo.Delay)) {\n\n\t\t//.....................................................................\n\t\t// If the original frame # for this player is -1, it means we've heard\n\t\t// from this player for the 1st time; return the appropriate value.\n\t\t//.....................................................................\n\t\tif (their_frame[index]==-1) {\n\t\t\tretcode = RC_PLAYER_READY;\n\t\t}\n\n\t\ttheir_frame[index] = event->Frame - event->Data.FrameInfo.Delay;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tExtract the other player's CommandCount.  This count will include\n\t//\tthe commands in this packet, if there are any.\n\t//------------------------------------------------------------------------\n\tif (event->Data.FrameInfo.CommandCount > their_sent[index]) {\n\n\t\tif ( abs(their_sent[index] - event->Data.FrameInfo.CommandCount) > 500) {\n\t\t\tFILE *fp;\n\t\t\tfp = fopen(\"badcount.txt\",\"wt\");\n\t\t\tif (fp) {\n\t\t\t\tfprintf(fp,\"Event Type:%s\\n\",EventClass::EventNames[event->Type]);\n\t\t\t\tfprintf(fp,\"Frame:%d  ID:%d  IsExec:%d\\n\",\n\t\t\t\t\tevent->Frame,\n\t\t\t\t\tevent->ID,\n\t\t\t\t\tevent->IsExecuted);\n\t\t\t\tif (event->Type != EventClass::FRAMEINFO) {\n\t\t\t\t\tfprintf(fp,\"Wrong Event Type!\\n\");\n\t\t\t\t} else {\n\t\t\t\t\tfprintf(fp,\"CRC:%x  CommandCount:%d  Delay:%d\\n\",\n\t\t\t\t\t\tevent->Data.FrameInfo.CRC,\n\t\t\t\t\t\tevent->Data.FrameInfo.CommandCount,\n\t\t\t\t\t\tevent->Data.FrameInfo.Delay);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheir_sent[index] = event->Data.FrameInfo.CommandCount;\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tif (event->Type == EventClass::FRAMESYNC) {\n\t\t\tprintf(\"(%d) Received FRAMESYNC: \", Frame);\n\t\t} else {\n\t\t\tprintf(\"(%d) Received FRAMEINFO: \", Frame);\n\t\t}\n\t\tprintf(\"EvFrame:%d ID:%d CRC:%x CmdCount:%d Delay:%d\\n\",\n\t\t\tevent->Frame,\n\t\t\tevent->ID,\n\t\t\tevent->Data.FrameInfo.CRC,\n\t\t\tevent->Data.FrameInfo.CommandCount,\n\t\t\tevent->Data.FrameInfo.Delay);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf this packet was not a FRAMESYNC packet:\n\t//\t- Add the events in it to our DoList\n\t//\t- Increment our commands-received counter by the number of non-\n\t//\t  FRAMEINFO packets received\n\t//------------------------------------------------------------------------\n\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t//.....................................................................\n\t\t// Break up the packet into its component events.  A returned packet\n\t\t// count of -1 indicates a fatal queue-full error.\n\t\t//.....................................................................\n\t\ti = Breakup_Receive_Packet( multi_packet_buf, packetlen);\n\t\tif (i==-1) {\n\t\t\treturn (RC_DOLIST_FULL);\n\t\t}\n\t\t//.....................................................................\n\t\t// Compute the actual # commands in the packet by subtracting off the\n\t\t// FRAMEINFO event\n\t\t//.....................................................................\n\t\tif ( (event->Type==EventClass::FRAMEINFO) && (i > 0)) {\n\t\t\ti--;\n\t\t}\n\n\t\ttheir_recv[index] += i;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tIf the event was a FRAMESYNC packet, there will be no commands to add,\n\t//\tbut we must check the ScenarioCRC value.\n\t//------------------------------------------------------------------------\n\telse if (event->Data.FrameInfo.CRC != ScenarioCRC) {\n\t\treturn (RC_SCENARIO_MISMATCH);\n\t}\n\n\treturn (retcode);\n\n}\t// end of Process_Receive_Packet\n\n\n/***************************************************************************\n * Process_Serial_Packet -- Handles an incoming serial packet              *\n *                                                                         *\n * This routine is needed because the modem classes don't support a \t\t\t*\n * \"global channel\" like the network classes do, but that functionality is\t*\n * still needed for modem communications.  Specifically, the modem dialogs\t*\n * transmit their own special packets back & forth, and messages are sent\t*\n * using a special packet type.  Thus, we have to call this routine when\t*\n * we receive a modem packet, to allow it to process messages & dialog\t\t*\n * packets.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tmulti_packet_buf\t\tpacket buffer to process\t\t\t\t\t\t\t\t*\n *\t\tfirst_time\t\t\t\t1 = this is the 1st game frame\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tRC_NORMAL:\t\t\t\tthis wasn't a SERIAL-type packet\t\t\t\t\t\t*\n *\t\tRC_SERIAL_PROCESSED:\tthis was a SERIAL-type packet, and was \t\t\t*\n * \t\t\t\t\t\t\t\tprocessed; the other player is still connected,\t*\n * \t\t\t\t\t\t\t\teven if he's not in the game.\t\t\t\t\t\t\t*\n *\t\tRC_PLAYER_LEFT:\t\tother player has left the game\t\t\t\t\t\t*\n *\t\tRC_HUNG_UP:\t\t\t\twe're getting our own packets back; thus, the \t*\n * \t\t\t\t\t\t\t\tmodem is mirroring our packets, which means the *\n * \t\t\t\t\t\t\t\tmodem hung up!\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic RetcodeType Process_Serial_Packet(char *multi_packet_buf,\n\tint first_time)\n{\n\tmulti_packet_buf;\n\tfirst_time;\n\treturn (RC_NORMAL);\n#if (0) // ST - 5/13/2019\n\tSerialPacketType *serial_packet;\t\t// for parsing serial packets\n\tint player_gone;\n\tEventClass *event;\n\n\t//------------------------------------------------------------------------\n\t//\tDetermine if this packet means that the other player has left the game\n\t//------------------------------------------------------------------------\n\tserial_packet = (SerialPacketType *)multi_packet_buf;\n\tplayer_gone = 0;\n\t//........................................................................\n\t// On Frame 0, only a SIGN_OFF means the other player left; the other\n\t// packet types may be left over from a previous session.\n\t//........................................................................\n\tif (first_time) {\n\t\tif (serial_packet->Command == SERIAL_SIGN_OFF) {\n\t\t\tplayer_gone = 1;\n\t\t}\n\t}\n\t//........................................................................\n\t// On subsequent frames, any of SIGN_OFF, TIMING, or SCORE_SCREEN means\n\t// the other player is gone.\n\t//........................................................................\n\telse {\n\t\tif (serial_packet->Command == SERIAL_SIGN_OFF ||\n\t\t\tserial_packet->Command == SERIAL_TIMING ||\n\t\t\tserial_packet->Command == SERIAL_SCORE_SCREEN ) {\n\t\t\tplayer_gone = 1;\n\t\t}\n\t}\n\tif (player_gone) {\n\t\tDestroy_Null_Connection(serial_packet->ScenarioInfo.Color, 0);\n\t\treturn (RC_PLAYER_LEFT);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Process an incoming message\n\t//------------------------------------------------------------------------\n\tif (serial_packet->Command == SERIAL_MESSAGE) {\n\t\tif (!Session.Messages.Concat_Message(serial_packet->Name,\n\t\t\tserial_packet->ID, serial_packet->Message.Message, Rule.MessageDelay * TICKS_PER_MINUTE)) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Appears to do nothing\n\tchar *ptr = &serial_packet->Message.Message[0];\n\tif (!strncmp(ptr,\"SECRET UNITS ON \",15) && NewUnitsEnabled) {\n\t\tEnable_Secret_Units();\n\t}\n#endif\n\t\t\tSession.Messages.Add_Message (serial_packet->Name,\n\t\t\t\tserial_packet->ID, serial_packet->Message.Message,\n\t\t\t\t(PlayerColorType)serial_packet->ID,\n\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);\n\n\t\t\tSound_Effect(VOC_INCOMING_MESSAGE);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tSave this message in our last-message buffer\n\t\t//.....................................................................\n\t\tif (strlen (serial_packet->Message.Message)) {\n\t\t\tstrcpy (Session.LastMessage, serial_packet->Message.Message);\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tTell the map to do a partial update (just to force the\n\t\t// messages to redraw).\n\t\t//.....................................................................\n\t\t//Map.Flag_To_Redraw(false);\n\t\tMap.Flag_To_Redraw(true);\n\t\treturn (RC_SERIAL_PROCESSED);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Any other SERIAL-type packet means the other player is still there;\n\t// throw them away, but let the caller know the connection is OK.\n\t//------------------------------------------------------------------------\n\tif ( (serial_packet->Command >= SERIAL_CONNECT &&\n\t\tserial_packet->Command < SERIAL_LAST_COMMAND) ||\n\t\t(serial_packet->Command >= SERIAL_REQ_SCENARIO &&\n\t\t serial_packet->Command <= SERIAL_NO_SCENARIO) ||\n\t\tSession.NumPlayers == 1) {\n\t\treturn (RC_SERIAL_PROCESSED);\n\t}\n\n\t//........................................................................\n\t//\tare we getting our own packets back??\n\t//........................................................................\n\tevent = (EventClass *)multi_packet_buf;\n\n\tif (event->Type <= EventClass::EMPTY || event->Type >= EventClass::LAST_EVENT) return (RC_SERIAL_PROCESSED);\n\n\tif (event->ID == PlayerPtr->ID) {\n\t\treturn (RC_HUNG_UP);\n\t}\n\n\treturn (RC_NORMAL);\n#endif\n}\t// end of Process_Serial_Packet\n\n\n/***************************************************************************\n * Can_Advance -- determines if it's OK to advance to the next frame       *\n *                                                                         *\n * This routine uses the current values stored in their_frame[], \t\t\t\t*\n * their_send[], and their_recv[] to see if it's OK to advance to the next\t*\n * game frame.  We must not advance if:\t\t\t\t\t\t\t\t\t\t\t\t*\n * - If our frame # would be too far ahead of the slowest player (the \t\t*\n *   lowest their_frame[] value).  \"Too far\" means \t\t\t\t\t\t\t\t*\n *   (Frame >= their_frame + MaxAhead).\t\t\t\t\t\t\t\t\t\t\t\t*\n * - our current command count doesn't match the sent command count of one\t*\n *   other player (meaning that we've missed a command packet from that \t*\n *   player, and thus the frame # we're receiving from him may be due to a\t*\n *   FRAMEINFO packet sent later than the command, so we shouldn't use \t\t*\n *   this frame # to see if we should advance; we should wait until we \t\t*\n *   have all the commands before we advance.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Of course, this routine assumes the values in their_frame[] etc are\t\t*\n * kept current by the caller.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\tmax frames ahead\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\tarray of their frame #'s\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\t\tarray of their sent command count\t\t\t\t\t\t\t*\n *\t\ttheir_recv\t\tarray of their # received commands\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK to advance; 0 = not OK\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tlong their_oldest_frame;\t\t\t// other players' oldest frame #\n\tint count_ok;\t\t\t\t\t\t\t// true = my cmd count matches theirs\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Special case for modem: if the other player has left, go ahead and\n\t// advance to the next frame; don't wait on him.\n\t//------------------------------------------------------------------------\n\tif (Session.NumPlayers == 1) {\n\t\treturn (1);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFind the oldest frame # in 'their_frame'\n\t//------------------------------------------------------------------------\n\ttheir_oldest_frame = Frame + 1000;\n\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\tif (their_frame[i] < their_oldest_frame)\n\t\t\ttheir_oldest_frame = their_frame[i];\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tI can advance to the next frame IF:\n\t//\t1) I'm less than a one-way propagation delay ahead of the other\n\t//    players' frame numbers, AND\n\t//\t2) their_recv[i] >= their_sent[i] (ie I've received all the commands\n\t//\t   the other players have sent so far).\n\t//------------------------------------------------------------------------\n\tcount_ok = 1;\n\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\tif (their_recv[i] < their_sent[i]) {\n\t\t\tcount_ok = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (count_ok && (Frame < (their_oldest_frame + max_ahead))) {\n\t\treturn (1);\n\t}\n\n\treturn (0);\n\n}\t// end of Can_Advance\n\n\n/***************************************************************************\n * Process_Reconnect_Dialog -- processes the reconnection dialog           *\n *                                                                         *\n * This routine [re]draws the reconnection dialog; if 'reconn' is set,\t\t*\n * it tells the user who we're trying to reconnect to; otherwise, is just\t*\n * says something generic like \"Waiting for connections\".\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\ttimeout_timer\tptr to count down timer, showing time remaining\t\t\t*\n *\t\ttheir_frame\t\tarray of other players' frame #'s\t\t\t\t\t\t\t*\n *\t\tnum_conn\t\t\t# connections in 'their_frame'\t\t\t\t\t\t\t\t*\n *\t\treconn\t\t\t1 = reconnect, 0 = waiting for first-time connection\t*\n *\t\tfresh\t\t\t\t1 = draw from scratch, 0 = only update time counter\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = user wants to cancel, 0 = not\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,\n\tlong *their_frame, int num_conn, int reconn, int fresh)\n{\n\tstatic int displayed_time = 0;\t// time value currently displayed\n\tint new_time;\n\tint oldest_index;\t\t\t\t\t\t// index of person requiring a reconnect\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t// Convert the timer to seconds\n\t//------------------------------------------------------------------------\n\tnew_time = *timeout_timer / 60;\n\n\t//------------------------------------------------------------------------\n\t// If the timer has changed, or 'fresh' is set, redraw the dialog\n\t//------------------------------------------------------------------------\n\tif (fresh || (new_time != displayed_time)) {\n\t\t//.....................................................................\n\t\t// Find the index of the person we're trying to reconnect to\n\t\t//.....................................................................\n\t\tif (reconn) {\n\t\t\tj = 0x7fffffff;\n\t\t\toldest_index = 0;\n\t\t\tfor (i = 0; i < num_conn; i++) {\n\t\t\t\tif (their_frame[i] < j) {\n\t\t\t\t\tj = their_frame[i];\n\t\t\t\t\toldest_index = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tNet_Reconnect_Dialog(reconn, fresh, oldest_index, new_time);\n\t}\n\tdisplayed_time = new_time;\n\n\t//........................................................................\n\t//\tIf user hits ESC, bail out\n\t//........................................................................\n\tif (Keyboard->Check()) {\n\t\tif (Keyboard->Get() == KN_ESC) {\n\t\t\treturn (1);\n\t\t}\n\t}\n\n\treturn (0);\n\n}\t// end of Process_Reconnect_Dialog\n\n\n/***************************************************************************\n * Handle_Timeout -- handles a timeout in the wait-for-players loop\t\t\t*\n *                                                                         *\n * This routine \"gracefully\" handles a timeout in the frame-sync loop.\t\t*\n * The timeout must be handled differently by a modem game or network \t\t*\n * game.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The modem game must detect if the other player is still connected\t\t\t*\n * physically, even if he's not playing the game any more; if so, this\t\t*\n * routine returns an OK status.  If the other player isn't even \t\t\t\t*\n * physically connected, an error is returned.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * The network game must find the connection that's causing the timeout,\t*\n * and destroy it.  The game continues, even if there are no more human\t\t*\n * players left.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_frame\t\t\tarray containing frame #'s of other players\t\t\t*\n *\t\ttheir_sent\t\t\tarray containing command count of other players\t\t*\n *\t\ttheir_recv\t\t\tarray containing # recv'd cmds from other players\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = it's OK; reset timeout timers & keep processing\t\t\t\t\t\t*\n *\t\t0 = game over, man\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Handle_Timeout(ConnManClass *net, long *their_frame,\n\tunsigned short *their_sent, unsigned short *their_recv)\n{\n\tint oldest_index;\t\t\t\t\t\t// index of person requiring a reconnect\n\tint i,j;\n\tint id;\n\n\t//------------------------------------------------------------------------\n\t// For modem, attempt to reconnect; if that fails, save the game & bail.\n\t//------------------------------------------------------------------------\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tif ( net->Num_Connections() ) {\n\t\t\tif (!Reconnect_Modem()) {\n#ifndef FIXIT_MULTI_SAVE\n\t\t\t\t//...............................................................\n\t\t\t\t// Set 'Session.EmergencySave', so when this game is loaded, we\n\t\t\t\t// won't check the CRC of the game state (this system & the\n\t\t\t\t// other may be on different frames, in which case the CRC\n\t\t\t\t// won't match).\n\t\t\t\t//...............................................................\n\t\t\t\tSession.EmergencySave = 1;\n\t\t\t\t//Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));\n\t\t\t\tSession.EmergencySave = 0;\n#endif\t// FIXIT_MULTI_SAVE\n\t\t\t\treturn (0);\n\t\t\t} else {\n\t\t\t\treturn (1);\n\t\t\t}\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tFor network, destroy the oldest connection\n\t//------------------------------------------------------------------------\n\telse if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET ||\n\t\tSession.Type == GAME_TEN || Session.Type == GAME_MPATH) {\n\t\tj = 0x7fffffff;\n\t\toldest_index = 0;\n\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\tif (their_frame[i] < j) {\n\t\t\t\tj = their_frame[i];\n\t\t\t\toldest_index = i;\n\t\t\t}\n\t\t}\n\n\t\tid = net->Connection_ID(oldest_index);\n#ifdef WIN32\n\t\t/*\n\t\t** Send the game statistics packet now if the game is effectivly over\n\t\t*/\n\t\tif (Session.Players.Count() == 2 &&\n\t\t\t\tSession.Type == GAME_INTERNET &&\n\t\t\t\t!GameStatisticsPacketSent) {\n\t\t\tRegister_Game_End_Time();\n\t\t\tConnectionLost = true;\n\t\t\tSend_Statistics_Packet();\t\t//\tDisconnect, and I'll be the only one left.\n\t\t}\n#endif\t//WIN32\n\n\t\tif (id != ConnManClass::CONNECTION_NONE) {\n\t\t\tfor (i = oldest_index; i < net->Num_Connections() - 1; i++) {\n\t\t\t\ttheir_frame[i] = their_frame[i+1];\n\t\t\t\ttheir_sent[i] = their_sent[i+1];\n\t\t\t\ttheir_recv[i] = their_recv[i+1];\n\t\t\t}\n\t\t\tif (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {\n\t\t\t\tDestroy_Connection(id,1);\n\t\t\t}\n#if(TEN)\n\t\t\telse if (Session.Type == GAME_TEN) {\n\t\t\t\tDestroy_TEN_Connection(id,1);\n\t\t\t}\n#endif\n#if(MPATH)\n\t\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\t\tDestroy_MPATH_Connection(id,1);\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Handle_Timeout\n\n\n/***************************************************************************\n * Stop_Game -- stops the game\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine clears any global flags that need it, in preparation for\t*\n * halting the game prematurely.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/22/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Stop_Game(void)\n{\n\tSession.LoadGame = false;\n\tSession.EmergencySave = false;\n\tGameActive = 0;\n\tif (IsMono) {\n\t\tMonoClass::Disable();\n\t}\n#ifdef WIN32\n\tif (Session.Type == GAME_INTERNET){\n\t\tConnectionLost = true;\n\t\tSend_Statistics_Packet();\t\t\t//\tStop_Game()\n\t}\n#endif\t//WIN32\n\n\treturn;\n\n}\t// end of Stop_Game\n\n\n/***************************************************************************\n * Build_Send_Packet -- Builds a big packet from a bunch of little ones.\t*\n *                                                                         *\n * This routine takes events from the OutList, and puts them into a \t\t\t*\n * \"meta-packet\", which is transmitted to all systems we're connected to.\t*\n * Also, these events are added to our own DoList.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * Every Meta-Packet we send uses a FRAMEINFO packet as a header; this \t\t*\n * tells the other systems what frame we're on, as well as serving as a \t*\n * standard packet header.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tnum_cmds\t\t\tvalue to use for the CommandCount field\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to send\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size of packet\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n * 'num_cmds' should be the total of of commands, including all those sent *\n * this frame!\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Build_Send_Packet(void *buf, int bufsize, int frame_delay,\n\tint num_cmds, int cap)\n{\n\tint size = 0;\n\tEventClass *finfo;\n\n\t//------------------------------------------------------------------------\n\t// All events start with a FRAMEINFO event; fill this part in.\n\t//------------------------------------------------------------------------\n\t//........................................................................\n\t// Set the event type\n\t//........................................................................\n\tfinfo = (EventClass *)buf;\n\tfinfo->Type = EventClass::FRAMEINFO;\n\t//........................................................................\n\t// Set the frame to execute this event on; this is protocol-specific\n\t//........................................................................\n\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tfinfo->Frame = ((Frame + frame_delay + (Session.FrameSendRate - 1)) /\n\t\t\t Session.FrameSendRate) * Session.FrameSendRate;\n\t}\n\telse {\n\t\tfinfo->Frame = Frame + frame_delay;\n\t}\n\t//........................................................................\n\t// Fill in the rest of the event\n\t//........................................................................\n\tfinfo->ID = PlayerPtr->ID;\n\tfinfo->Data.FrameInfo.CRC = GameCRC;\n\tfinfo->Data.FrameInfo.CommandCount = num_cmds;\n\tfinfo->Data.FrameInfo.Delay = frame_delay;\n\n\t//------------------------------------------------------------------------\n\t// Initialize the # of bytes processed; this is protocol-specific\n\t//------------------------------------------------------------------------\n\tif (Session.CommProtocol==COMM_PROTOCOL_SINGLE_NO_COMP) {\n\t\tsize += sizeof(EventClass);\n\t}\n\telse {\n\t\tsize += (offsetof(EventClass, Data) +\n\t\t\tsize_of(EventClass, Data.FrameInfo));\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tTransfer all events from the OutList into the DoList, building our\n\t//\tpacket while we go.\n\t//------------------------------------------------------------------------\n\tswitch (Session.CommProtocol) {\n\t\t//.....................................................................\n\t\t// COMM_PROTOCOL_SINGLE_NO_COMP:\n\t\t// We'll send at least a FRAMEINFO every single frame, no compression\n\t\t//.....................................................................\n\t\tcase (COMM_PROTOCOL_SINGLE_NO_COMP):\n\t\t\tsize = Add_Uncompressed_Events(buf, bufsize, frame_delay, size, cap);\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// COMM_PROTOCOL_SINGLE_E_COMP:\n\t\t//   Compress a group of packets into our send buffer; send out\n\t\t//   compressed packets every frame.\n\t\t// COMM_PROTOCOL_MULTI_E_COMP:\n\t\t//   Compress a group of packets into our send buffer; send out\n\t\t//   compressed packets every 'n' frames.\n\t\t//.....................................................................\n\t\tcase (COMM_PROTOCOL_SINGLE_E_COMP):\n\t\tcase (COMM_PROTOCOL_MULTI_E_COMP):\n\t\t\tsize = Add_Compressed_Events(buf, bufsize, frame_delay, size, cap);\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Default: We have no idea what to do, so do nothing.\n\t\t//.....................................................................\n\t\tdefault:\n\t\t\tsize = 0;\n\t\t\tbreak;\n\t}\n\n\treturn( size );\n\n}\t/* end of Build_Send_Packet */\n\n\n/***************************************************************************\n * Add_Uncompressed_Events -- adds uncompressed events to a packet         *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tsize\t\t\t\tcurrent packet size\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThis routine MUST check to be sure it doesn't overflow the buffer.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay,\n\tint size, int cap)\n{\n\tint num = 0;\t\t\t// # of events processed\n\tint ev_size;\t\t\t// size of event we're adding\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events, or we've processed our max # of\n\t// events, or the buffer is full.\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count && (num < cap)) {\n\n\t\tKeyboard->Check();\n\n\t\tif (OutList.First().Type==EventClass::ADDPLAYER) {\n\t\t\tev_size = sizeof(EventClass) + OutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tev_size = sizeof(EventClass);\n\t\t}\n\t\t//.....................................................................\n\t\t// Will the next event exceed the size of the buffer?  If so, break.\n\t\t//.....................................................................\n\t\tif ( (size + ev_size) > bufsize ) {\n\t\t\treturn (size);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Set the event's frame delay\n\t\t//.....................................................................\n\t\tOutList.First().Frame = Frame + frame_delay;\n\n\t\t//.....................................................................\n\t\t// Set the event's ID\n\t\t//.....................................................................\n\t\tOutList.First().ID = PlayerPtr->ID;\n\n\t\t//.....................................................................\n\t\t// Transfer the event in OutList to DoList, un-queue the OutList\n\t\t// event.  If the DoList is full, stop transferring immediately.\n\t\t//.....................................................................\n\t\tOutList.First().IsExecuted = 0;\n\t\tif (!DoList.Add(OutList.First())) {\n\t\t\treturn (size);\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\n\t\t//.....................................................................\n\t\t// Add event to the send packet\n\t\t//.....................................................................\n\t\tif (OutList.First().Type==EventClass::ADDPLAYER) {\n\t\t\tmemcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );\n\t\t\tsize += sizeof(EventClass);\n\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\tOutList.First().Data.Variable.Pointer,\n\t\t\t\tOutList.First().Data.Variable.Size);\n\t\t\tsize += OutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tmemcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );\n\t\t\tsize += sizeof(EventClass);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Increment our event counter; delete the last event from the queue\n\t\t//.....................................................................\n\t\tnum++;\n\t\tOutList.Next();\n\t}\n\n\treturn (size);\n\n}\t// end of Add_Uncompressed_Events\n\n\n/***************************************************************************\n * Add_Compressed_Events -- adds an compressed events to a packet          *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\t\tbuffer to store packet in\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\t\tmax size of buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tframe_delay\t\tdesired frame delay to attach to all outgoing packets\t*\n *\t\tsize\t\t\t\treference to current packet size\t\t\t\t\t\t\t\t*\n *\t\tcap\t\t\t\tmax # events to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnew size value\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tThis routine MUST check to be sure it doesn't overflow the buffer.\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Add_Compressed_Events(void *buf, int bufsize, int frame_delay,\n\tint size, int cap)\n{\n\tint num = 0;\t\t\t\t\t\t\t// # of events processed\n\tEventClass::EventType eventtype;\t// type of event being compressed\n\tEventClass prevevent;\t\t\t\t// last event processed\n\tint datasize;\t\t\t\t\t\t\t// size of element plucked from event union\n\tint storedsize;\t\t\t\t\t\t// actual # bytes stored from event\n\tunsigned char *unitsptr = NULL;\t// ptr to buffer pos to store mega. rep count\n\tunsigned char numunits = 0;\t\t// megamission rep count value\n\tbool missiondup = false;\t\t\t// flag: is this event a megamission repeat?\n\n\t//------------------------------------------------------------------------\n\t// clear previous event\n\t//------------------------------------------------------------------------\n\tmemset (&prevevent, 0, sizeof(EventClass));\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n(%d) Building Send Packet\\n\", Frame);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events, we've processed our max # of\n\t// events, or the buffer is full.\n\t//------------------------------------------------------------------------\n\twhile (OutList.Count && (num < cap)) {\n\n\t\tKeyboard->Check();\n\n\t\teventtype = OutList.First().Type;\n\t\tdatasize = EventClass::EventLength[ eventtype ];\n\t\t//.....................................................................\n\t\t// For a variable-sized event, pull the size from the event; otherwise,\n\t\t// the size will be the data element size plus the event type value.\n\t\t// (The other data elements in the event, Frame, ID, etc, are stored\n\t\t// in the packet header.)\n\t\t//.....................................................................\n\t\tif (eventtype==EventClass::ADDPLAYER) {\n\t\t\tstoredsize = datasize + sizeof (EventClass::EventType) +\n\t\t\t\tOutList.First().Data.Variable.Size;\n\t\t}\n\t\telse {\n\t\t\tstoredsize = datasize + sizeof (EventClass::EventType);\n\t\t}\n\n\t\t//.....................................................................\n\t\t// MegaMission compression:  MegaMissions are stored as:\n\t\t//   EventType\n\t\t//   Rep Count\n\t\t//   MegaMission structure (event # 1 only)\n\t\t//   Whom #2\n\t\t//   Whom #3\n\t\t//   Whom #4\n\t\t//   ...\n\t\t//   Whom #n\n\t\t//.....................................................................\n\t\tif (prevevent.Type == EventClass::MEGAMISSION) {\n\t\t\t//..................................................................\n\t\t\t// If previous & current events are both MegaMissions:\n\t\t\t//..................................................................\n\t\t\tif (eventtype == EventClass::MEGAMISSION) {\n\t\t\t\t//...............................................................\n\t\t\t\t// If the Mission, Target, & Destination are the same, compress\n\t\t\t\t// the events into one:\n\t\t\t\t// - Change datasize to the size of the 'Whom' field only\n\t\t\t\t// - set total # bytes to store to the size of the 'Whom' only\n\t\t\t\t// - increment the MegaMission rep count\n\t\t\t\t// - set the MegaMission rep flag\n\t\t\t\t//...............................................................\n\t\t\t\tif (OutList.First().Data.MegaMission.Mission ==\n\t\t\t\t\tprevevent.Data.MegaMission.Mission &&\n\t\t\t\t\tOutList.First().Data.MegaMission.Target ==\n\t\t\t\t\t\tprevevent.Data.MegaMission.Target &&\n\t\t\t\t\tOutList.First().Data.MegaMission.Destination ==\n\t\t\t\t\t\tprevevent.Data.MegaMission.Destination) {\n#if (0)//PG\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tprintf(\"      adding Whom:%x (%x) Mission:%s Target:%x (%x) Dest:%x (%x)\\n\",\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Whom.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Whom,\n\t\t\t\t\t\tMissionClass::Mission_Name(OutList.First().Data.MegaMission.Mission),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Target.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Target,\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Destination.As_TARGET(),\n\t\t\t\t\t\tOutList.First().Data.MegaMission.Destination);\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tdatasize = sizeof(prevevent.Data.MegaMission.Whom);\n\t\t\t\t\tstoredsize = datasize;\n\t\t\t\t\tnumunits++;\n\t\t\t\t\tmissiondup = true;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// Data doesn't match; start a new run of MegaMissions:\n\t\t\t\t// - Store previous MegaMission rep count\n\t\t\t\t// - Init 'unitsptr' to buffer pos after next EventType\n\t\t\t\t// - set total # bytes to store to 'datasize' + sizeof(EventType) +\n\t\t\t\t//   sizeof (numunits)\n\t\t\t\t// - init the MegaMission rep count to 1\n\t\t\t\t// - clear the MegaMission rep flag\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tprintf(\"  New MEGAMISSION run:\\n\");\n\t\t\t\t\t}\n\n\t\t\t\t\t*unitsptr = numunits;\n\t\t\t\t\tunitsptr = ((unsigned char *)buf) + size +\n\t\t\t\t\t\tsizeof(EventClass::EventType);\n\t\t\t\t\tstoredsize += sizeof(numunits);\n\t\t\t\t\tnumunits = 1;\n\t\t\t\t\tmissiondup = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// Previous event was a MegaMission, but this one isn't: end the\n\t\t\t// run of MegaMissions:\n\t\t\t// - Store previous MegaMission rep count\n\t\t\t// - Clear variables\n\t\t\t//..................................................................\n\t\t\telse {\n\t\t\t\t*unitsptr = numunits;\t\t// save # events in our run\n\t\t\t\tunitsptr = NULL;\t\t\t\t// init other values\n\t\t\t\tnumunits = 0;\n\t\t\t\tmissiondup = false;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t// The previous event is not a MEGAMISSION but the current event is:\n\t\t// Set up a new run of MegaMissions:\n\t\t// - Init 'unitsptr' to buffer pos after next EventType\n\t\t// - set total # bytes to store to 'datasize' + sizeof(EventType) +\n\t\t//   sizeof (numunits)\n\t\t// - init the MegaMission rep count to 1\n\t\t// - clear the MegaMission rep flag\n\t\t//.....................................................................\n\t\telse if (eventtype == EventClass::MEGAMISSION) {\n\n\t\t\tif (Debug_Print_Events) {\n\t\t\t\tprintf(\"  New MEGAMISSION run:\\n\");\n\t\t\t}\n\n\t\t\tunitsptr = ((unsigned char *)buf) + size +\n\t\t\t\tsizeof(EventClass::EventType);\n\t\t\tstoredsize += sizeof(numunits);\n\t\t\tnumunits = 1;\n\t\t\tmissiondup = false;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Will the next event exceed the size of the buffer?  If so,\n\t\t// stop compressing.\n\t\t//.....................................................................\n\t\tif ( (size + storedsize) > bufsize )\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Set the event's frame delay (this is protocol-dependent)\n\t\t//.....................................................................\n\t\tif (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\t\tOutList.First().Frame = ((Frame + frame_delay +\n\t\t\t\t(Session.FrameSendRate - 1)) / Session.FrameSendRate) *\n\t\t\t\tSession.FrameSendRate;\n\t\t}\n\t\telse {\n\t\t\tOutList.First().Frame = Frame + frame_delay;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Set the event's ID\n\t\t//.....................................................................\n\t\tOutList.First().ID = PlayerPtr->ID;\n\n\t\t//.....................................................................\n\t\t// Transfer the event in OutList to DoList, un-queue the OutList event.\n\t\t// If the DoList is full, stop transferring immediately.\n\t\t//.....................................................................\n\t\tOutList.First().IsExecuted = 0;\n\t\tif ( !DoList.Add( OutList.First() ) ) {\n\t\t\tbreak;\n\t\t}\n\t\t#ifdef MIRROR_QUEUE\n\t\tMirrorList.Add(OutList.First());\n\t\t#endif\n\n\t\t//---------------------------------------------------------------------\n\t\t// Compress the event into the send packet buffer\n\t\t//---------------------------------------------------------------------\n\t\tswitch ( eventtype ) {\n\t\t\t//..................................................................\n\t\t\t// RESPONSE_TIME: just use the Delay field of the FrameInfo union\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::RESPONSE_TIME):\n\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data.FrameInfo.Delay, datasize );\n\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// MEGAMISSION:\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::MEGAMISSION):\n\t\t\t\t//...............................................................\n\t\t\t\t// Repeated mission in a run:\n\t\t\t\t//   - Update the rep count (in case we break out)\n\t\t\t\t//   - Copy the Whom field only\n\t\t\t\t//...............................................................\n\t\t\t\tif (missiondup) {\n\t\t\t\t\t*unitsptr = numunits;\n\n\t\t\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\t\t\t&OutList.First().Data.MegaMission.Whom, datasize );\n\n\t\t\t\t\tsize += datasize;\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t// 1st mission in a run:\n\t\t\t\t//   - Init the rep count (in case we break out)\n\t\t\t\t//   - Set the EventType\n\t\t\t\t//   - Copy the MegaMission structure, leaving room for 'numunits'\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\t*unitsptr = numunits;\n\n\t\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\t\tmemcpy ( ((char *)buf) + size +\n\t\t\t\t\t\tsizeof(EventClass::EventType) + sizeof(numunits),\n\t\t\t\t\t\t&OutList.First().Data.MegaMission, datasize );\n\n\t\t\t\t\tsize += (datasize + sizeof(EventClass::EventType) + sizeof(numunits));\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Variable-sized packets: Copy the packet Size & the buffer\n\t\t\t//..................................................................\n\t\t\tcase (EventClass::ADDPLAYER):\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data.Variable.Size, datasize );\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\n\t\t\t\tmemcpy ( ((char *)buf) + size,\n\t\t\t\t\tOutList.First().Data.Variable.Pointer,\n\t\t\t\t\tOutList.First().Data.Variable.Size);\n\t\t\t\tsize += OutList.First().Data.Variable.Size;\n\n\t\t\t\tbreak;\n\n\t\t\t//..................................................................\n\t\t\t// Default case: Just copy over the data field from the union\n\t\t\t//..................................................................\n\t\t\tdefault:\n\t\t\t\t*(EventClass::EventType *)( ((char *)buf) + size) = eventtype;\n\n\t\t\t\tmemcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),\n\t\t\t\t\t&OutList.First().Data, datasize );\n\n\t\t\t\tsize += (datasize + sizeof(EventClass::EventType));\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//---------------------------------------------------------------------\n\t\t// update # events processed\n\t\t//---------------------------------------------------------------------\n\t\tnum++;\n\n\t\t//---------------------------------------------------------------------\n\t\t// Update 'prevevent'\n\t\t//---------------------------------------------------------------------\n\t\tmemcpy ( &prevevent, &OutList.First(), sizeof(EventClass) );\n\n\t\t//---------------------------------------------------------------------\n\t\t// Go to the next event to process\n\t\t//---------------------------------------------------------------------\n\t\tOutList.Next();\n\t}\n\n\tif (Debug_Print_Events) {\n\t\tprintf(\"\\n\");\n\t}\n\n\treturn (size);\n\n}\t// end of Add_Compressed_Events\n\n\n/***************************************************************************\n * Breakup_Receive_Packet -- Splits a big packet into little ones.\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to break up\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events added to queue, -1 if fatal error (queue is full)\t\t\t\t*\n *    (return value includes any FRAMEINFO packets encountered; \t\t\t\t*\n *\t\tFRAMESYNC's are ignored)\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Breakup_Receive_Packet(void *buf, int bufsize )\n{\n\tint count = 0;\n\n\t/*\n\t** is there enough leftover for another record\n\t*/\n\tswitch (Session.CommProtocol) {\n\t\tcase (COMM_PROTOCOL_SINGLE_NO_COMP):\n\t\t\tcount = Extract_Uncompressed_Events(buf, bufsize);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcount = Extract_Compressed_Events(buf, bufsize);\n\t\t\tbreak;\n\t}\n\n\treturn (count);\n\n}\t/* end of Breakup_Receive_Packet */\n\n\n/***************************************************************************\n * Extract_Uncompressed_Events -- extracts events from a packet            *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing events to extract\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events extracted\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Extract_Uncompressed_Events(void *buf, int bufsize)\n{\n\tint count = 0;\n\tint pos = 0;\n\tint leftover = bufsize;\n\tEventClass *event;\n\n\t//------------------------------------------------------------------------\n\t// Loop until there are no more events in the packet\n\t//------------------------------------------------------------------------\n\twhile (leftover >= sizeof(EventClass) ) {\n\n\t\tKeyboard->Check();\n\n\t\tevent = (EventClass *)(((char *)buf) + pos);\n\n\t\t//.....................................................................\n\t\t// add event to the DoList, only if it's not a FRAMESYNC\n\t\t// (but FRAMEINFO's do get added.)\n\t\t//.....................................................................\n\t\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t\tevent->IsExecuted = 0;\n\n\t\t\t//..................................................................\n\t\t\t// Special processing for variable-sized events\n\t\t\t//..................................................................\n\t\t\tif (event->Type == EventClass::ADDPLAYER) {\n\t\t\t\tevent->Data.Variable.Pointer = new char[event->Data.Variable.Size];\n\t\t\t\tmemcpy (event->Data.Variable.Pointer,\n\t\t\t\t\t((char *)buf) + sizeof(EventClass),\n\t\t\t\t\tevent->Data.Variable.Size);\n\n\t\t\t\tpos += event->Data.Variable.Size;\n\t\t\t\tleftover -= event->Data.Variable.Size;\n\t\t\t}\n\n\t\t\tif (!DoList.Add( *event )) {\n\t\t\t\tif (event->Type == EventClass::ADDPLAYER) {\n\t\t\t\t\tdelete [] event->Data.Variable.Pointer;\n\t\t\t\t}\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Add(*event);\n\t\t\t#endif\n\n\t\t\t//..................................................................\n\t\t\t// Keep count of how many events we add to the queue\n\t\t\t//..................................................................\n\t\t\tcount++;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Point to the next position in the buffer; decrement our 'leftover'\n\t\t//.....................................................................\n\t\tpos += sizeof(EventClass);\n\t\tleftover -= sizeof(EventClass);\n\t}\n\n\treturn (count);\n\n}\t// end of Extract_Uncompressed_Events\n\n\n/***************************************************************************\n * Extract_Compressed_Events -- extracts events from a packet   \t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer containing events to extract\t\t\t\t\t\t\t\t*\n *\t\tbufsize\t\tlength of 'buf'\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t# events extracted\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 DRD : Created.                                             *\n *=========================================================================*/\nstatic int Extract_Compressed_Events(void *buf, int bufsize)\n{\n\tint pos = 0;\t\t\t\t\t\t// current buffer parsing position\n\tint leftover = bufsize;\t\t\t// # bytes left to process\n\tEventClass *event;\t\t\t\t// event ptr for parsing buffer\n\tint count = 0;\t\t\t\t\t\t// # events processed\n\tint datasize = 0;\t\t\t\t\t// size of data to copy\n\tEventClass eventdata;\t\t\t// stores Frame, ID, etc\n\tunsigned char numunits = 0;\t// # units stored in compressed MegaMissions\n\n\t//------------------------------------------------------------------------\n\t// Clear work event structure\n\t//------------------------------------------------------------------------\n\tmemset (&eventdata, 0, sizeof(EventClass));\n\n\t//------------------------------------------------------------------------\n\t// Assume the first event is a FRAMEINFO event\n\t// Init 'datasize' to the amount of data to copy, minus the EventType value\n\t// For the 1st packet only, this will include all info before the Data\n\t// union, plus the size of the FrameInfo structure, minus the EventType size.\n\t//------------------------------------------------------------------------\n\tdatasize = (offsetof(EventClass, Data) +\n\t\tsize_of(EventClass, Data.FrameInfo)) - sizeof(EventClass::EventType);\n\tevent = (EventClass *)(((char *)buf) + pos);\n\n\twhile (leftover >= (datasize + (int)sizeof(EventClass::EventType)) ) {\n\n\t\tKeyboard->Check();\n\n\t\t//.....................................................................\n\t\t// add event to the DoList, only if it's not a FRAMESYNC\n\t\t// (but FRAMEINFO's do get added.)\n\t\t//.....................................................................\n\t\tif (event->Type != EventClass::FRAMESYNC) {\n\t\t\t//..................................................................\n\t\t\t// initialize the common data from the FRAMEINFO event\n\t\t\t// keeping IsExecuted 0\n\t\t\t//..................................................................\n\t\t\tif (event->Type == EventClass::FRAMEINFO) {\n\t\t\t\teventdata.Frame = event->Frame;\n\t\t\t\teventdata.ID = event->ID;\n\n\t\t\t\t//...............................................................\n\t\t\t\t// Adjust position past the common data\n\t\t\t\t//...............................................................\n\t\t\t\tpos += (offsetof(EventClass, Data) -\n\t\t\t\t\t\t sizeof(EventClass::EventType));\n\t\t\t\tleftover -= (offsetof(EventClass, Data) -\n\t\t\t\t\t\t\t\tsizeof(EventClass::EventType));\n\t\t\t}\n\t\t\t//..................................................................\n\t\t\t// if MEGAMISSION event get the number of units (events to generate)\n\t\t\t//..................................................................\n\t\t\telse if (event->Type == EventClass::MEGAMISSION) {\n\t\t\t\tnumunits = *(((unsigned char *)buf) + pos + sizeof(eventdata.Type));\n\t\t\t\tpos += sizeof(numunits);\n\t\t\t\tleftover -= sizeof(numunits);\n\t\t\t}\n\n\t\t\t//..................................................................\n\t\t\t// clear the union data portion of the event\n\t\t\t//..................................................................\n\t\t\tmemset (&eventdata.Data, 0, sizeof(eventdata.Data));\n\t\t\teventdata.Type = event->Type;\n\t\t\tdatasize = EventClass::EventLength[ eventdata.Type ];\n\n\t\t\tswitch (eventdata.Type) {\n\t\t\t\tcase (EventClass::RESPONSE_TIME):\n\t\t\t\t\tmemcpy ( &eventdata.Data.FrameInfo.Delay,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (EventClass::ADDPLAYER):\n\n\t\t\t\t\tmemcpy ( &eventdata.Data.Variable.Size,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\n\t\t\t\t\teventdata.Data.Variable.Pointer =\n\t\t\t\t\t\tnew char[eventdata.Data.Variable.Size];\n\t\t\t\t\tmemcpy (eventdata.Data.Variable.Pointer,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType) + datasize,\n\t\t\t\t\t\teventdata.Data.Variable.Size);\n\n\t\t\t\t\tpos += eventdata.Data.Variable.Size;\n\t\t\t\t\tleftover -= eventdata.Data.Variable.Size;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (EventClass::MEGAMISSION):\n\t\t\t\t\tmemcpy ( &eventdata.Data.MegaMission,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\n\t\t\t\t\tif (numunits > 1) {\n\t\t\t\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\t\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\t\t\t\t\t\tdatasize = sizeof(eventdata.Data.MegaMission.Whom);\n\n\t\t\t\t\t\twhile (numunits) {\n\n\t\t\t\t\t\t\tKeyboard->Check();\n\n\t\t\t\t\t\t\tif ( !DoList.Add( eventdata ) ) {\n\t\t\t\t\t\t\t\treturn (-1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\t\t\t\tMirrorList.Add( eventdata );\n\t\t\t\t\t\t\t#endif\n\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// Keep count of how many events we add to the queue\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\tnumunits--;\n\t\t\t\t\t\t\tmemcpy ( &eventdata.Data.MegaMission.Whom,\n\t\t\t\t\t\t\t\t((char *)buf) + pos, datasize );\n\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\t// if one unit left fall thru to normal code\n\t\t\t\t\t\t\t//......................................................\n\t\t\t\t\t\t\tif (numunits == 1) {\n\t\t\t\t\t\t\t\tdatasize -= sizeof(EventClass::EventType);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tpos += datasize;\n\t\t\t\t\t\t\t\tleftover -= datasize;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tmemcpy ( &eventdata.Data,\n\t\t\t\t\t\t((char *)buf) + pos + sizeof(EventClass::EventType),\n\t\t\t\t\t\tdatasize );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ( !DoList.Add( eventdata ) ) {\n\t\t\t\tif (eventdata.Type == EventClass::ADDPLAYER) {\n\t\t\t\t\tdelete [] eventdata.Data.Variable.Pointer;\n\t\t\t\t}\n\t\t\t\treturn (-1);\n\t\t\t}\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Add( eventdata );\n\t\t\t#endif\n\n\t\t\t//..................................................................\n\t\t\t// Keep count of how many events we add to the queue\n\t\t\t//..................................................................\n\t\t\tcount++;\n\n\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\n\t\t\tif (leftover) {\n\t\t\t\tevent = (EventClass *)(((char *)buf) + pos);\n\t\t\t\tdatasize = EventClass::EventLength[ event->Type ];\n\t\t\t\tif (event->Type == EventClass::MEGAMISSION) {\n\t\t\t\t\tdatasize += sizeof(numunits);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t// FRAMESYNC event: This >should< be the only event in the buffer,\n\t\t// and it will be uncompressed.\n\t\t//.....................................................................\n\t\telse {\n\t\t\tpos += (datasize + sizeof(EventClass::EventType));\n\t\t\tleftover -= (datasize + sizeof(EventClass::EventType));\n\t\t\tevent = (EventClass *)(((char *)buf) + pos);\n\n\t\t\t//..................................................................\n\t\t\t// size of FRAMESYNC event - EventType size\n\t\t\t//..................................................................\n\t\t\tdatasize = (offsetof(EventClass, Data) +\n\t\t\t\t\t\t\tsize_of(EventClass, Data.FrameInfo)) -\n\t\t\t\t\t\t\tsizeof(EventClass::EventType);\n\t\t}\n\t}\n\n\treturn (count);\n\n}\t// end of Extract_Compressed_Events\n\n\n/***************************************************************************\n * Execute_DoList -- Executes commands from the DoList                     *\n *                                                                         *\n * This routine executes any events in the DoList that need to be executed\t*\n * on the current game frame.  The events must be executed in a special\t\t*\n * order, so that all systems execute all events in exactly the same\t\t\t*\n * order.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This routine also handles checking the Game CRC sent by other systems\t*\n * against my own, to be sure we're still in sync.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tmax_houses\t# houses to execute commands for\t\t\t\t\t\t\t\t\t*\n *\t\tbase_house\tHousesType to start with\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnet\t\t\tptr to connection manager; NULL if none\t\t\t\t\t\t*\n *\t\tskip_crc\t\ta frame-based countdown timer; if it's non-zero, the\t\t*\n *\t\t\t\t\t\tCRC check will be skipped.  Ignored if NULL.\t\t\t\t\t*\n *\t\ttheir_frame\tarray of their frame #'s\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_sent\tarray of # commands they've sent\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_recv\tarray of # commands I've received from them\t\t\t\t\t*\n *                                                                         *\n * (their_xxx are ignored if 'net' is NULL.)\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = some error occurred (CRC error, packet rcv'd too late.)\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Execute_DoList(int max_houses, HousesType base_house,\n\tConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv)\n{\n\tHousesType house;\n\tHouseClass *hptr;\n\tint i,j,k;\n\tint index;\n\tint check_crc;\n\n\tCheck_Mirror();\n\n#if(TIMING_FIX)\n\t//\n\t// If MPlayerMaxAhead is recomputed such that it increases, the systems\n\t// may try to free-run to the new MaxAhead value.  If so, they may miss\n\t// an event that was generated after the TIMING event was created, but\n\t// before it executed; this event will be scheduled with the older,\n\t// shorter MaxAhead value.  If a system doesn't receive this event, it\n\t// may execute past the frame it's scheduled to execute on, creating\n\t// a Packet-Recieved-Too-Late error.  To prevent this, find any events\n\t// that are scheduled to execute during this \"period of vulnerability\",\n\t// and re-schedule for the end of that period.\n\t//\n\tfor (j = 0; j < DoList.Count; j++) {\n\t\tif (DoList[j].Type != EventClass::FRAMEINFO &&\n\t\t\tDoList[j].Frame > (unsigned)NewMaxAheadFrame1 &&\n\t\t\tDoList[j].Frame < (unsigned)NewMaxAheadFrame2) {\n\t\t\tDoList[j].Frame = (unsigned)NewMaxAheadFrame2;\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList[j].Frame = NewMaxAheadFrame2;\n\t\t\t#endif\n\t\t}\n\t}\n#endif\n\n\t//------------------------------------------------------------------------\n\t//\tExecute the DoList.  Events must be executed in the same order on all\n\t//\tsystems; so, execute them in the order of the HouseClass array.  This\n\t//\tarray is stored in the same order on all systems.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < max_houses; i++) {\n\t\t//.....................................................................\n\t\t//\tConvert our index into a HousesType value\n\t\t//.....................................................................\n\t\thouse = (HousesType)(i + base_house);\n\t\thptr = HouseClass::As_Pointer(house);\n\n\t\t//.....................................................................\n\t\t// If for some reason this house doesn't exist, skip it.\n\t\t// Also, if this house has exited the game, skip it.  (The user can\n\t\t// generate events after he exits, because the exit event is scheduled\n\t\t// at least FrameSendRate*3 frames ahead.  If one system gets these\n\t\t// packets & another system doesn't, they'll go out of sync because\n\t\t// they aren't checking the CommandCount for that house, since that\n\t\t// house isn't connected any more.)\n\t\t//.....................................................................\n\t\tif (!hptr) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hptr->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//.....................................................................\n\t\t//\tLoop through all events\n\t\t//.....................................................................\n\t\tfor (j = 0; j < DoList.Count; j++) {\n\n\t\t\tif (net)\n\t\t\t\tUpdate_Queue_Mono (net, 6);\n\n\t\t\t//..................................................................\n\t\t\t//\tIf this event was from the currently-executing player ID, and it's\n\t\t\t//\ttime to execute it, execute it.\n\t\t\t//..................................................................\n\t\t\tif (DoList[j].ID == hptr->ID && (unsigned) Frame >= DoList[j].Frame &&\n\t\t\t\t!DoList[j].IsExecuted) {\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tError if it's too late to execute this packet!\n\t\t\t\t// (Hack: disable this check for solo or skirmish mode.)\n\t\t\t\t//...............................................................\n\t\t\t\tif ((unsigned)Frame > DoList[j].Frame && DoList[j].Type !=\n\t\t\t\t\tEventClass::FRAMEINFO && Session.Type != GAME_NORMAL &&\n\t\t\t\t\tSession.Type != GAME_SKIRMISH) {\n\n#if(TEN)\n\t\t\t\t\tSend_TEN_Packet_Too_Late();\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t//Send_MPATH_Packet_Too_Late();\n#endif\t// MPATH\n\n\t\t\t\t\tDump_Packet_Too_Late_Stuff(&DoList[j], net, their_frame,\n\t\t\t\t\t\ttheir_sent, their_recv);\n\t\t\t\t\tWWMessageBox().Process (TXT_PACKET_TOO_LATE);\n\t\t\t\t\treturn (0);\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tOnly execute EXIT & OPTIONS commands if they're from myself.\n\t\t\t\t//...............................................................\n\t\t\t\tif (DoList[j].Type==EventClass::EXIT ||\n\t\t\t\t\t\tDoList[j].Type==EventClass::OPTIONS) {\n\n#ifdef WIN32\n\t\t\t\t\tif (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Flag that this house lost because it quit.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tHousesType quithouse;\n\t\t\t\t\t\tHouseClass *quithptr;\n\n\t\t\t\t\t\tfor (int player = 0; player < max_houses ; player++) {\n\t\t\t\t\t\t\tquithouse = (HousesType)(player + base_house);\n\t\t\t\t\t\t\tquithptr = HouseClass::As_Pointer(quithouse);\n\t\t\t\t\t\t\tif (!quithptr) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (quithptr->ID == DoList[j].ID) {\n\t\t\t\t\t\t\t\tquithptr->IsGiverUpper = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Send the game statistics packet now since the game is effectivly over\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Session.Players.Count() == 2 &&\n\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET &&\n\t\t\t\t\t\t\t\t!GameStatisticsPacketSent) {\n\t\t\t\t\t\t\tRegister_Game_End_Time();\n\t\t\t\t\t\t\tSend_Statistics_Packet();\t\t//\tEvent - player aborted, and there were only 2 left.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\t//WIN32\n\n\t\t\t\t\tif (Debug_Print_Events) {\n\t\t\t\t\t\tif (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t\tprintf(\"(%d) Executing EXIT, ID:%d (%s), EvFrame:%d\\n\",\n\t\t\t\t\t\t\t\tFrame,\n\t\t\t\t\t\t\t\tDoList[j].ID,\n\t\t\t\t\t\t\t\t(HouseClass::As_Pointer((HousesType)(DoList[j].ID)))->IniName,\n\t\t\t\t\t\t\t\tDoList[j].Frame);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (DoList[j].ID == PlayerPtr->ID) {\n\t\t\t\t\t\tDoList[j].Execute();\n\t\t\t\t\t} else if (DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t//\tIf this EXIT event isn't from myself, destroy the connection\n\t\t\t\t\t//\tfor that player.  The HousesType for this event is the\n\t\t\t\t\t// connection ID.\n\t\t\t\t\t//............................................................\n\t\t\t\t\t\tif (Session.Type == GAME_MODEM ||\n\t\t\t\t\t\t\tSession.Type == GAME_NULL_MODEM) {\n\t\t\t\t\t\t\t//PG Destroy_Null_Connection( house, 0 );\n\t\t\t\t\t\t} else if ((Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\tSession.Type == GAME_INTERNET ||\n\t\t\t\t\t\t\tSession.Type == GAME_TEN ||\n\t\t\t\t\t\t\tSession.Type == GAME_MPATH) && net) {\n\t\t\t\t\t\t\tindex = net->Connection_Index (house);\n\t\t\t\t\t\t\tif (index != -1) {\n\t\t\t\t\t\t\t\tfor (k = index; k < net->Num_Connections() - 1; k++) {\n\t\t\t\t\t\t\t\t\ttheir_frame[k] = their_frame[k+1];\n\t\t\t\t\t\t\t\t\ttheir_sent[k] = their_sent[k+1];\n\t\t\t\t\t\t\t\t\ttheir_recv[k] = their_recv[k+1];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET) {\n\t\t\t\t\t\t\t\t\tDestroy_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#if(TEN)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_TEN) {\n\t\t\t\t\t\t\t\t\tDestroy_TEN_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#endif\t// TEN\n#if(MPATH)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_MPATH) {\n\t\t\t\t\t\t\t\t\tDestroy_MPATH_Connection(house,0);\n\t\t\t\t\t\t\t\t}\n#endif\t// MPATH\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Special case for recording playback: turn the house over\n\t\t\t\t\t\t// to the computer.\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (Session.Play && DoList[j].Type==EventClass::EXIT) {\n\t\t\t\t\t\t\thptr->IsHuman = false;\n\t\t\t\t\t\t\thptr->IQ = Rule.MaxIQ;\n\t\t\t\t\t\t\thptr->Computer_Paranoid();\n\t\t\t\t\t\t\tstrcpy (hptr->IniName,Text_String(TXT_COMPUTER));\n\t\t\t\t\t\t\tSession.NumPlayers--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tFor a FRAMEINFO event, check the CRC value.\n\t\t\t\t//...............................................................\n\t\t\t\telse if (DoList[j].Type == EventClass::FRAMEINFO) {\n\t\t\t\t\t//............................................................\n\t\t\t\t\t// Skip the CRC check if we're less than 32 frames into the game;\n\t\t\t\t\t// this will prevent a newly-loaded modem game from instantly\n\t\t\t\t\t// going out of sync, if the games were saved at different\n\t\t\t\t\t// frame numbers.\n\t\t\t\t\t//............................................................\n\t\t\t\t\tif (!skip_crc || *skip_crc == 0) {\n\t\t\t\t\t\tcheck_crc = 1;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcheck_crc = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (check_crc\n\t\t\t\t\t\t&& DoList[j].Frame == Frame\n\t\t\t\t\t\t&& DoList[j].Data.FrameInfo.Delay < 32) {\n\t\t\t\t\t\tindex = ((DoList[j].Frame - DoList[j].Data.FrameInfo.Delay) &\n\t\t\t\t\t\t\t0x001f);\n\t\t\t\t\t\tif (CRC[index] != DoList[j].Data.FrameInfo.CRC) {\n\t\t\t\t\t\t\tPrint_CRCs(&DoList[j]);\n\n#if(TEN)\n\t\t\t\t\t\t\tSend_TEN_Out_Of_Sync();\n#endif\t// TEN\n\n#if(MPATH)\n\t\t\t\t\t\t\t//Send_MPATH_Out_Of_Sync();\n#endif\t// MPATH\n#if (0)//PG\n\t\t\t\t\t\t\tif (WWMessageBox().Process (TXT_OUT_OF_SYNC,\n\t\t\t\t\t\t\t\tTXT_CONTINUE, TXT_STOP) == 0) {\n\t\t\t\t\t\t\t\tif (Session.Type == GAME_MODEM ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_NULL_MODEM) {\n\t\t\t\t\t\t\t\t\t//PG Destroy_Null_Connection( house, -1 );\n\t\t\t\t\t\t\t\t\tShutdown_Modem();\n\t\t\t\t\t\t\t\t\tSession.Type = GAME_NORMAL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if ((Session.Type == GAME_IPX ||\n\t\t\t\t\t\t\t\t\tSession.Type == GAME_INTERNET) && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tKeyboard->Check();\n\t\t\t\t\t\t\t\t\t\tDestroy_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#if(TEN)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_TEN && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tDestroy_TEN_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#endif\n#if(MPATH)\n\t\t\t\t\t\t\t\telse if (Session.Type == GAME_MPATH && net) {\n\t\t\t\t\t\t\t\t\twhile (net->Num_Connections()) {\n\t\t\t\t\t\t\t\t\t\tDestroy_MPATH_Connection (net->Connection_ID(0), -1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\treturn (0);\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\treturn (1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//...............................................................\n\t\t\t\t//\tExecute other commands\n\t\t\t\t//...............................................................\n\t\t\t\telse {\n\t\t\t\t\tDoList[j].Execute();\n\t\t\t\t}\n\n\t\t\t\t//...............................................................\n\t\t\t\t//\tMark this event as executed.\n\t\t\t\t//...............................................................\n\t\t\t\tDoList[j].IsExecuted = 1;\n\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\tMirrorList[j].IsExecuted = 1;\n\t\t\t\t#endif\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Execute_DoList\n\n\n/***************************************************************************\n * Clean_DoList -- Cleans out old events from the DoList                   *\n *                                                                         *\n * Currently, an event can only be removed from the DoList if it's at the\t*\n * head of the list; and event can't be removed from the middle.  So,\t\t*\n * this routine loops as long as the next event in the DoList has been\t\t*\n * executed, it's removed.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager; ignored if NULL\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Clean_DoList(ConnManClass *net)\n{\n\twhile (DoList.Count) {\n\n\t\tKeyboard->Check();\n\n\t\tif (net)\n\t\t\tUpdate_Queue_Mono (net, 7);\n\n\t\t//.....................................................................\n\t\t//\tDiscard events that have been executed, OR it's too late to execute.\n\t\t//\t(This happens if another player exits the game; he'll leave FRAMEINFO\n\t\t//\tevents lying around in my queue.  They won't have been \"executed\",\n\t\t//\tbecause his IPX connection was destroyed.)\n\t\t//.....................................................................\n\t\tif ( (DoList.First().IsExecuted) || ((unsigned)Frame > DoList.First().Frame) ) {\n\t\t\tDoList.Next();\n\t\t\t#ifdef MIRROR_QUEUE\n\t\t\tMirrorList.Next();\n\t\t\t#endif\n\t\t}\n\t\telse {\n\t\t\tbreak;\n\t\t}\n\t}\n\n}\t// end of Clean_DoList\n\n\n/***************************************************************************\n * Queue_Record -- Records the DoList to disk                              *\n *                                                                         *\n * This routine just saves any events in the DoList to disk; we can later\t*\n * \"play back\" the recording just be pulling events from disk rather than\t*\n * from the network!\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   08/14/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_Record(void)\n{\n\tint i,j;\n\n\t//------------------------------------------------------------------------\n\t//\tCompute # of events to save this frame\n\t//------------------------------------------------------------------------\n\tj = 0;\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {\n\t\t\tj++;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the # of events, then all events.\n\t//------------------------------------------------------------------------\n\tSession.RecordFile.Write (&j,sizeof(j));\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {\n\t\t\tSession.RecordFile.Write (&DoList[i],sizeof (EventClass));\n\t\t\tj--;\n\t\t}\n\t}\n\n}\t/* end of Queue_Record */\n\n\n/***************************************************************************\n * Queue_Playback -- plays back queue entries from a record file           *\n *                                                                         *\n * This routine reads events from disk, putting them into the DoList;\t\t*\n * it then executes the DoList just like the network version does.  The\t\t*\n * result is that the game \"plays back\" like a recording.\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine detects mouse motion and stops playback, so it can work\t\t*\n * like an \"attract\" mode, showing a demo of the game itself.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/15/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Queue_Playback(void)\n{\n\tint numevents;\n\tEventClass event;\n\tint i;\n\tint ok;\n  \tstatic int mx,my;\n\tint max_houses;\n\tHousesType base_house;\n\tint key;\n\tint testframe;\n\n\t//------------------------------------------------------------------------\n\t//\tIf the user hits ESC, stop the playback\n\t//------------------------------------------------------------------------\n\tif (Keyboard->Check()) {\n\t\tkey = Keyboard->Get();\n\t\tif (key == KA_ESC || Session.Attract) {\n\t\t\tGameActive = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t// If we're in \"Attract\" mode, and the user moves the mouse, stop the\n\t// playback.\n\t//------------------------------------------------------------------------\n\tif (Session.Attract && Frame > 0 &&\n\t\t(mx != Get_Mouse_X() || my != Get_Mouse_Y())) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\tmx = Get_Mouse_X();\n\tmy = Get_Mouse_Y();\n\n\t//------------------------------------------------------------------------\n\t//\tCompute the Game's CRC\n\t//------------------------------------------------------------------------\n\tCompute_Game_CRC();\n\tCRC[Frame & 0x001f] = GameCRC;\n\n\t//------------------------------------------------------------------------\n\t// If we've reached the CRC print frame, do so & exit\n\t//------------------------------------------------------------------------\n\tif (Frame >= Session.TrapPrintCRC) {\n\t\tPrint_CRCs(NULL);\n\t\tProg_End(\"Queue_Playback reached CRC print frame\", true);\n\t\tEmergency_Exit(0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tDon't read anything the first time through (since the Queue_AI_Network\n\t//\troutine didn't write anything the first time through); do this after the\n\t//\tCRC is computed, since we'll still need a CRC for Frame 0.\n\t//------------------------------------------------------------------------\n\tif (Frame==0 && Session.Type!=GAME_NORMAL) {\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Only process every 'FrameSendRate' frames\n\t//------------------------------------------------------------------------\n\ttestframe = ((Frame + (Session.FrameSendRate - 1)) /\n\t\tSession.FrameSendRate) * Session.FrameSendRate;\n\tif ( (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) &&\n\t\tSession.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {\n\t\tif (Frame != testframe) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tRead the DoList from disk\n\t//------------------------------------------------------------------------\n\tok = 1;\n\tif (Session.RecordFile.Read (&numevents, sizeof(numevents)) ==\n\t\tsizeof(numevents)) {\n\t\tfor (i = 0; i < numevents; i++) {\n\t\t\tif (Session.RecordFile.Read (&event, sizeof(EventClass)) ==\n\t\t\t\tsizeof(EventClass)) {\n\t\t\t\tevent.IsExecuted = 0;\n\t\t\t\tDoList.Add (event);\n\t\t\t\t#ifdef MIRROR_QUEUE\n\t\t\t\tMirrorList.Add(event);\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse {\n\t\t\t\tok = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tok = 0;\n\t}\n\n\tif (!ok) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\n\t//------------------------------------------------------------------------\n\t// Execute the DoList; if an error occurs, bail out.\n\t//------------------------------------------------------------------------\n\tif (Session.Type == GAME_NORMAL) {\n\t\tmax_houses = 1;\n\t\tbase_house = PlayerPtr->Class->House;\n\t}\n\telse {\n\t\tmax_houses = Session.MaxPlayers;\n\t\tbase_house = HOUSE_MULTI1;\n\t}\n\tif (!Execute_DoList(max_houses, base_house, NULL, NULL, NULL, NULL, NULL)) {\n\t\tGameActive = 0;\n\t\treturn;\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClean out the DoList\n\t//------------------------------------------------------------------------\n\tClean_DoList(NULL);\n\n}\t/* end of Queue_Playback */\n\n\n/***************************************************************************\n * Compute_Game_CRC -- Computes a CRC value of the entire game.\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Compute_Game_CRC(void)\n{\n\tint i,j;\n\tVesselClass *vessp;\n\tInfantryClass *infp;\n\tUnitClass *unitp;\n\tBuildingClass *bldgp;\n\tObjectClass *objp;\n\tHouseClass *housep;\n\n\tGameCRC = 0;\n\n\t//------------------------------------------------------------------------\n\t//\tInfantry\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\tinfp = (InfantryClass *)Infantry.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);\n\t\tAdd_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);\n\t\tAdd_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tUnits\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Units.Count(); i++) {\n\t\tunitp = (UnitClass *)Units.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +\n\t\t\t(int)unitp->SecondaryFacing);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tShippies\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\tvessp = (VesselClass *)Vessels.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Coord + (int)vessp->PrimaryFacing);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Speed + (int)vessp->NavCom);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Strength);\n\t\tAdd_CRC (&GameCRC, (int)vessp->Mission + (int)vessp->TarCom);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tBuildings\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\tbldgp = (BuildingClass *)Buildings.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tHouses\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Houses.Count(); i++) {\n\t\thousep = (HouseClass *)Houses.Active_Ptr(i);\n\t\tAdd_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +\n\t\t\t(int)housep->Drain);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMap Layers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tfor (j = 0; j < Map.Layer[i].Count(); j++) {\n\t\t\tobjp = Map.Layer[i][j];\n\t\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\t}\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tLogic Layers\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Logic.Count(); i++) {\n\t\tobjp = Logic[i];\n\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tA random #\n\t//------------------------------------------------------------------------\n//\tAdd_CRC(&GameCRC, Scen.RandomNumber.Seed);\n\tAdd_CRC(&GameCRC, Scen.RandomNumber);\n\n}\t/* end of Compute_Game_CRC */\n\n\n/***************************************************************************\n * Add_CRC -- Adds a value to a CRC                                        *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcrc\t\tptr to crc\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tval\t\tvalue to add\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid Add_CRC(unsigned long *crc, unsigned long val)\n{\n\tint hibit;\n\n\tif ( (*crc) & 0x80000000) {\n\t\thibit = 1;\n\t}\n\telse {\n\t\thibit = 0;\n\t}\n\n\t(*crc) <<= 1;\n\t(*crc) += val;\n\t(*crc) += hibit;\n\n}\t/* end of Add_CRC */\n\n/***************************************************************************\n * Print_CRCs -- Prints a data file for finding Sync Bugs\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tev -- event to display\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   05/09/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Print_CRCs(EventClass *ev)\n{\n\tint i,j;\n\tInfantryClass *infp;\n\tUnitClass *unitp;\n\tVesselClass *vesselp;\n\tBuildingClass *bldgp;\n\tObjectClass *objp;\n\tFILE *fp;\n\tHouseClass *housep;\n\tHousesType house;\n\tint color;\n\n\tMono_Clear_Screen();\n\tMono_Set_Cursor (0,0);\n\tfp = fopen(\"OUT.TXT\",\"wt\");\n\tif (fp==NULL) {\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < 32; i++) {\n\t\tfprintf(fp,\"CRC[%d]=%x\\n\",i,CRC[i]);\n\t}\n\n\t//\n\t// Houses\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\tGameCRC = 0;\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tHousesType actlike = housep->ActLike;\n\t\t\tcolor = housep->RemapColor;\n\t\t\tfprintf(fp,\"%s: IsHuman:%d  Color:%s  ID:%d  ActLike:%s\\n\",\n\t\t\t\thousep->IniName,\n\t\t\t\thousep->IsHuman,\n\t\t\t\tColorNames[color],\n\t\t\t\thousep->ID,\n\t\t\t\tHouseClass::As_Pointer(actlike)->Class->Name());\n\t\t\tAdd_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +\n\t\t\t\t(int)housep->Drain);\n\t\t\tMono_Printf(\"House %s:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Infantry\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Infantry -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tinfp = (InfantryClass *)Infantry.Active_Ptr(i);\n\t\t\t\tif (infp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);\n\t\t\t\t\tfprintf(fp,\"COORD:%x   Facing:%d   Mission:%d   Type:%d   Tgt:%x Speed:%d NavCom:%x\\n\",\n\t\t\t\t\t\tinfp->Coord,(int)infp->PrimaryFacing,infp->Get_Mission(),\n\t\t\t\t\t\tinfp->Class->Type, infp->As_Target(), infp->Speed, infp->NavCom);\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Infantry:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Units\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Units -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tunitp = (UnitClass *)Units.Active_Ptr(i);\n\t\t\t\tif (unitp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +\n\t\t\t\t\t\t(int)unitp->SecondaryFacing);\n\t\t\t\t\tfprintf(fp,\n\t\t\t\t\t\t\"COORD:%x   Facing:%d   Facing2:%d   Mission:%d   Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tunitp->Coord,(int)unitp->PrimaryFacing,\n\t\t\t\t\t\t(int)unitp->SecondaryFacing,unitp->Get_Mission(),\n\t\t\t\t\t\tunitp->Class->Type, unitp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Units:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Vessels\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Vessels -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Vessels.Count(); i++) {\n\t\t\t\tvesselp = (VesselClass *)Vessels.Active_Ptr(i);\n\t\t\t\tif (vesselp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Coord + (int)vesselp->PrimaryFacing);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Speed + (int)vesselp->NavCom);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Strength);\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)vesselp->Mission + (int)vesselp->TarCom);\n\t\t\t\t\tfprintf(fp,\n\t\t\t\t\t\t\"COORD:%x   Facing:%d   Mission:%d   Strength:%d Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tvesselp->Coord,(int)vesselp->PrimaryFacing,\n\t\t\t\t\t\tvesselp->Get_Mission(), vesselp->Strength,\n\t\t\t\t\t\tvesselp->Class->Type, vesselp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Vessels:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Buildings\n\t//\n\tfor (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep) {\n\t\t\tGameCRC = 0;\n\t\t\tfprintf(fp,\"-------------------- %s Buildings -------------------\\n\",\n\t\t\t\thousep->Class->Name());\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tbldgp = (BuildingClass *)Buildings.Active_Ptr(i);\n\t\t\t\tif (bldgp->Owner()==house) {\n\t\t\t\t\tAdd_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);\n\t\t\t\t\tfprintf(fp,\"COORD:%x   Facing:%d   Mission:%d   Type:%d   Tgt:%x\\n\",\n\t\t\t\t\t\tbldgp->Coord,(int)bldgp->PrimaryFacing,bldgp->Get_Mission(),\n\t\t\t\t\t\tbldgp->Class->Type, bldgp->As_Target());\n\t\t\t\t}\n\t\t\t}\n\t\t\tMono_Printf(\"%s Buildings:%x\\n\",housep->Class->Name(),GameCRC);\n\t\t}\n\t}\n\n\t//\n\t// Animations\n\t//\n\tAnimClass *animp;\n\t\tfprintf(fp,\"-------------------- Animations -------------------\\n\");\n\tfor (i = 0; i < Anims.Count(); i++) {\n\t\tanimp = (AnimClass *)Anims.Active_Ptr(i);\n\t\tfprintf(fp,\"Target:%x OwnerHouse:%d Loops:%d\\n\",\n\t\t\tanimp->xObject,\n\t\t\tanimp->OwnerHouse,\n\t\t\tanimp->Loops);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tMap Layers\n\t//------------------------------------------------------------------------\n\tGameCRC = 0;\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tfprintf(fp,\">>>> MAP LAYER %d <<<<\\n\",i);\n\t\tfor (j = 0; j < Map.Layer[i].Count(); j++) {\n\t\t\tobjp = Map.Layer[i][j];\n\t\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\t\tfprintf(fp,\"Object %d: %x \",j,objp->Coord);\n\n\t\t\tif (objp->What_Am_I() == RTTI_AIRCRAFT)\n\t\t\t\tfprintf(fp,\"Aircraft  (Type:%d) \",\n\t\t\t\t\t(AircraftType)(*((AircraftClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_ANIM)\n\t\t\t\tfprintf(fp,\"Anim      (Type:%d) \",\n\t\t\t\t\t(AnimType)(*((AnimClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_BUILDING)\n\t\t\t\tfprintf(fp,\"Building  (Type:%d) \",\n\t\t\t\t\t(StructType)(*((BuildingClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_BULLET)\n\t\t\t\tfprintf(fp,\"Bullet    (Type:%d) \",\n\t\t\t\t\t(BulletType)(*((BulletClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_INFANTRY)\n\t\t\t\tfprintf(fp,\"Infantry  (Type:%d) \",\n\t\t\t\t\t(InfantryType)(*((InfantryClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_OVERLAY)\n\t\t\t\tfprintf(fp,\"Overlay   (Type:%d) \",\n\t\t\t\t\t(OverlayType)(*((OverlayClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_SMUDGE)\n\t\t\t\tfprintf(fp,\"Smudge    (Type:%d) \",\n\t\t\t\t\t(SmudgeType)(*((SmudgeClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_TEMPLATE)\n\t\t\t\tfprintf(fp,\"Template  (Type:%d) \",\n\t\t\t\t\t(TemplateType)(*((TemplateClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_TERRAIN)\n\t\t\t\tfprintf(fp,\"Terrain   (Type:%d) \",\n\t\t\t\t\t(TerrainType)(*((TerrainClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_UNIT)\n\t\t\t\tfprintf(fp,\"Unit      (Type:%d) \",\n\t\t\t\t\t(UnitType)(*((UnitClass *)objp)));\n\t\t\telse if (objp->What_Am_I() == RTTI_VESSEL)\n\t\t\t\tfprintf(fp,\"Vessel    (Type:%d) \",\n\t\t\t\t\t(VesselType)(*((VesselClass *)objp)));\n\n\t\t\thouse = objp->Owner();\n\t\t\tif (house!=HOUSE_NONE) {\n\t\t\t\thousep = HouseClass::As_Pointer (house);\n\t\t\t\tfprintf(fp,\"Owner: %s\\n\",housep->Class->IniName);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfprintf(fp,\"Owner: NONE\\n\");\n\t\t\t}\n\t\t}\n\t}\n\tMono_Printf(\"Map Layers:%x  \\n\",GameCRC);\n\n\t//------------------------------------------------------------------------\n\t//\tLogic Layers\n\t//------------------------------------------------------------------------\n\tGameCRC = 0;\n\tfprintf(fp,\">>>> LOGIC LAYER <<<<\\n\");\n\tfor (i = 0; i < Logic.Count(); i++) {\n\t\tobjp = Logic[i];\n\t\tAdd_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());\n\t\tfprintf(fp,\"Object %d: %x \",i,objp->Coord);\n\n\t\tif (objp->What_Am_I() == RTTI_AIRCRAFT)\n\t\t\tfprintf(fp,\"Aircraft  (Type:%d) \",\n\t\t\t\t(AircraftType)(*((AircraftClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_ANIM)\n\t\t\tfprintf(fp,\"Anim      (Type:%d) \",\n\t\t\t\t(AnimType)(*((AnimClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_BUILDING)\n\t\t\tfprintf(fp,\"Building  (Type:%d) \",\n\t\t\t\t(StructType)(*((BuildingClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_BULLET)\n\t\t\tfprintf(fp,\"Bullet    (Type:%d) \",\n\t\t\t\t(BulletType)(*((BulletClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_INFANTRY)\n\t\t\tfprintf(fp,\"Infantry  (Type:%d) \",\n\t\t\t\t(InfantryType)(*((InfantryClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_OVERLAY)\n\t\t\tfprintf(fp,\"Overlay   (Type:%d) \",\n\t\t\t\t(OverlayType)(*((OverlayClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_SMUDGE)\n\t\t\tfprintf(fp,\"Smudge    (Type:%d) \",\n\t\t\t\t(SmudgeType)(*((SmudgeClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_TEMPLATE)\n\t\t\tfprintf(fp,\"Template  (Type:%d) \",\n\t\t\t\t(TemplateType)(*((TemplateClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_TERRAIN)\n\t\t\tfprintf(fp,\"Terrain   (Type:%d) \",\n\t\t\t\t(TerrainType)(*((TerrainClass *)objp)));\n\t\telse if (objp->What_Am_I() == RTTI_UNIT)\n\t\t\tfprintf(fp,\"Unit      (Type:%d) \",\n\t\t\t\t(UnitType)(*((UnitClass *)objp)));\n\n\t\thouse = objp->Owner();\n\t\tif (house!=HOUSE_NONE) {\n\t\t\thousep = HouseClass::As_Pointer (house);\n\t\t\tfprintf(fp,\"Owner: %s\\n\",housep->Class->IniName);\n\t\t}\n\t\telse {\n\t\t\tfprintf(fp,\"Owner: NONE\\n\");\n\t\t}\n\t}\n\tMono_Printf(\"Logic:%x  \\n\",GameCRC);\n\n\t//------------------------------------------------------------------------\n\t//\tRandom # generator, frame #\n\t//------------------------------------------------------------------------\n\tMono_Printf(\"Random Number:%x  \\n\",Scen.RandomNumber.Seed);\n#ifdef RANDOM_COUNT\n\tfprintf(fp,\"\\nRandom Number:%x (Count1:%d, Count2:%d)\\n\",\n\t\tScen.RandomNumber.Seed,\n\t\tScen.RandomNumber.Count1,\n\t\tScen.RandomNumber.Count2);\n#else\n\tfprintf(fp,\"\\nRandom Number:%x\\n\",Scen.RandomNumber.Seed);\n#endif\n\n\tMono_Printf(\"My Frame:%d  \\n\",Frame);\n\tfprintf(fp,\"My Frame:%d\\n\",Frame);\n\n\tif (ev) {\n\t\tfprintf(fp,\"\\n\");\n\t\tfprintf(fp,\"Offending event:\\n\");\n\t\tfprintf(fp,\"  Type:         %d\\n\",ev->Type);\n\t\tfprintf(fp,\"  Frame:        %d\\n\",ev->Frame);\n\t\tfprintf(fp,\"  ID:           %x\\n\",ev->ID);\n\t\tfprintf(fp,\"  CRC:          %x\\n\",ev->Data.FrameInfo.CRC);\n\t\tfprintf(fp,\"  CommandCount: %d\\n\",ev->Data.FrameInfo.CommandCount);\n\t\tfprintf(fp,\"  Delay:        %d\\n\",ev->Data.FrameInfo.Delay);\n\t}\n\n\tfclose(fp);\n\n}\t/* end of Print_CRCs */\n\n\n/***************************************************************************\n * Init_Queue_Mono -- inits mono display                                   *\n *                                                                         *\n * This routine steals control of the mono screen away from the rest of\t\t*\n * the engine, by setting the global IsMono; if IsMono is set, the other\t*\n * routines in this module turn off the Mono display when they're done\t\t*\n * with it, so the rest of the engine won't over-write what we're writing.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Init_Queue_Mono(ConnManClass *net)\n{\n#if(SHOW_MONO)\n\t//------------------------------------------------------------------------\n\t// Set 'IsMono' so we can steal the mono screen from the engine\n\t//------------------------------------------------------------------------\n\tif ((Frame==0 || Session.LoadGame) && MonoClass::Is_Enabled()) {\n\t\tIsMono = true;\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Enable mono output for our stuff; we must Disable it before we return\n\t// control to the engine.\n\t//------------------------------------------------------------------------\n\tif (IsMono)\n\t\tMonoClass::Enable();\n\n\tif (net->Num_Connections() > 0) {\n\t\t//.....................................................................\n\t\t//\tNetwork mono debugging screen\n\t\t//.....................................................................\n\t\tif (NetMonoMode==0) {\n\t\t\tif (Frame==0 || Session.LoadGame || NewMonoMode) {\n\t\t\t\tnet->Configure_Debug (0, sizeof (CommHeaderType),\n\t\t\t\t\tsizeof(EventClass::EventType), EventClass::EventNames, 0, 27);\n\t\t\t\tnet->Mono_Debug_Print (0,1);\n\t\t\t\tNewMonoMode = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnet->Mono_Debug_Print (0,0);\n\t\t\t}\n\t\t}\n\t\t//.....................................................................\n\t\t//\tFlow control debugging output\n\t\t//.....................................................................\n\t\telse {\n\t\t\tif (NewMonoMode) {\n\t\t\t\tMono_Clear_Screen();\n\t\t\t\tMono_Printf(\"                         Queue AI:\\n\");\t// flowcount[0]\n\t\t\t\tMono_Printf(\"                Build Packet Loop:\\n\");\t// flowcount[1]\n\t\t\t\tMono_Printf(\"                       Frame Sync:\\n\");\t// flowcount[2]\n\t\t\t\tMono_Printf(\"                Frame Sync Resend:\\n\");\t// flowcount[3]\n\t\t\t\tMono_Printf(\"               Frame Sync Timeout:\\n\");\t// flowcount[4]\n\t\t\t\tMono_Printf(\"           Frame Sync New Message:\\n\");\t// flowcount[5]\n\t\t\t\tMono_Printf(\"                 DoList Execution:\\n\");\t// flowcount[6]\n\t\t\t\tMono_Printf(\"                  DoList Cleaning:\\n\");\t// flowcount[7]\n\t\t\t\tMono_Printf(\"\\n\");\n\t\t\t\tMono_Printf(\"                            Frame:\\n\");\n\t\t\t\tMono_Printf(\"                 Session.MaxAhead:\\n\");\n\t\t\t\tMono_Printf(\"                       their_recv:\\n\");\n\t\t\t\tMono_Printf(\"                       their_sent:\\n\");\n\t\t\t\tMono_Printf(\"                          my_sent:\\n\");\n\t\t\t\tNewMonoMode = 0;\n\t\t\t}\n\t\t}\n\t}\n#else\n\tnet = net;\n#endif\n}\t// end of Init_Queue_Mono\n\n\n/***************************************************************************\n * Update_Queue_Mono -- updates mono display                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnet\t\t\t\tptr to connection manager\t\t\t\t\t\t\t\t\t\t*\n *\t\tflow_index\t\tindex # for flow-count updates\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t-1: display\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Update_Queue_Mono(ConnManClass *net, int flow_index)\n{\n#if(SHOW_MONO)\n\tstatic int flowcount[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n\n\t//------------------------------------------------------------------------\n\t// If 'NetMonoMode' is 1, display flowcount info\n\t//------------------------------------------------------------------------\n\tif (NetMonoMode==1) {\n\t\tif (flow_index >= 0 && flow_index < 20) {\n\t\t\tMono_Set_Cursor(35,flow_index);\n\t\t\tflowcount[flow_index]++;\n\t\t\tMono_Printf(\"%d\",flowcount[flow_index]);\n\t\t}\n\t}\n\t//------------------------------------------------------------------------\n\t// Otherwise, display the connection debug screen\n\t//------------------------------------------------------------------------\n\telse {\n\t\tnet->Mono_Debug_Print (0,0);\n\t}\n\n#else\n\tflow_index = flow_index;\n\tnet = net;\n#endif\n\n}\t// end of Update_Queue_Mono\n\n\n/***************************************************************************\n * Print_Framesync_Values -- displays frame-sync variables                 *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tcurframe\t\t\t\t\tcurrent game Frame #\t\t\t\t\t\t\t\t\t\t*\n *\t\tmax_ahead\t\t\t\tmax-ahead value\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tnum_connections\t\t# connections\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\ttheir_recv\t\t\t\t# commands I've received from my connections\t\t*\n *\t\ttheir_sent\t\t\t\t# commands each connection claims to have sent\t*\n *\t\tmy_sent\t\t\t\t\t# commands I've sent\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/21/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic void Print_Framesync_Values(long curframe, unsigned long max_ahead,\n\tint num_connections, unsigned short *their_recv,\n\tunsigned short *their_sent, unsigned short my_sent)\n{\n#if(SHOW_MONO)\n\tint i;\n\n\tif (NetMonoMode==1) {\n\t\tMono_Set_Cursor(35,9);\n\t\tMono_Printf(\"%d\",curframe);\n\n\t\tMono_Set_Cursor(35,10);\n\t\tMono_Printf(\"%d\",max_ahead);\n\n\t\tfor (i = 0; i < num_connections; i++) {\n\t\t\tMono_Set_Cursor(35 + i*5,11);\n\t\t\tMono_Printf(\"%4d\",(int)their_recv[i]);\n\t\t}\n\n\t\tfor (i = 0; i < num_connections; i++) {\n\t\t\tMono_Set_Cursor(35 + i*5,12);\n\t\t\tMono_Printf(\"%4d\",(int)their_sent[i]);\n\t\t}\n\n\t\tMono_Set_Cursor(35,13);\n\t\tMono_Printf(\"%4d\",(int)my_sent);\n\t}\n#else\n\tcurframe = curframe;\n\tmax_ahead = max_ahead;\n\tnum_connections = num_connections;\n\ttheir_recv = their_recv;\n\ttheir_sent = their_sent;\n\tmy_sent = my_sent;\n#endif\n}\t// end of Print_Framesync_Values\n\n\n/***************************************************************************\n * Dump_Packet_Too_Late_Stuff -- Dumps a debug file to disk                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tevent\t\tptr to event to print\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/28/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,\n\tlong *their_frame, unsigned short *their_sent, unsigned short *their_recv)\n{\n\tFILE *fp;\n\tint i;\n\tHousesType house;\n\n\tfp = fopen(\"toolate.txt\", \"wt\");\n\tif (!fp) {\n\t\treturn;\n\t}\n\tfprintf(fp,\"----------------- Event data: ----------------------\\n\");\n\tfprintf(fp,\"Type:       %s\\n\",EventClass::EventNames[event->Type]);\n\tfprintf(fp,\"Frame:      %d\\n\",event->Frame);\n\tfprintf(fp,\"ID:         %d\\n\",event->ID);\n\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tif (event->ID == Session.Players[i]->Player.ID) {\n\t\t\tfprintf(fp,\"Player's Name: %s\",Session.Players[i]->Name);\n\t\t}\n\t}\n\tfprintf(fp,\"\\n\");\n\n\tfprintf(fp,\"--------------------- My data: ---------------------\\n\");\n\tfprintf(fp,\"My Frame:%d\\n\",Frame);\n\tfprintf(fp,\"My MaxAhead:%d\\n\",Session.MaxAhead);\n\n\tif (net) {\n\t\tfprintf(fp,\"-------------------- Frame Stats: ------------------\\n\");\n\t\tfprintf(fp,\"Name          ID  TheirFrame  TheirSent  TheirRecv\\n\");\n\t\tfor (i = 0; i < net->Num_Connections(); i++) {\n\t\t\thouse = (HousesType)(net->Connection_ID(i));\n\t\t\tfprintf(fp,\"%12s  %2d    %6d      %6d      %6d\\n\",\n\t\t\t\t(HouseClass::As_Pointer(house))->IniName,\n\t\t\t\tnet->Connection_ID(i),\n\t\t\t\ttheir_frame[i],\n\t\t\t\ttheir_sent[i],\n\t\t\t\ttheir_recv[i]);\n\t\t}\n\t}\n\n\tfclose(fp);\n}\n\n/***************************************************************************\n * Check_Mirror -- Checks mirror memory                                    *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/14/1996 BRR : Created.                                             *\n *=========================================================================*/\nvoid Check_Mirror(void)\n{\n#ifdef MIRROR_QUEUE\n\tint i;\n\tchar txt[80];\n\tunsigned long *ptr;\n\tint found_5s = 0;\n\n\tptr = (unsigned long *)(DoList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0x55555555) {\n\t\t\tsprintf(txt,\"55555555 found in DoList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(MirrorList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0x55555555) {\n\t\t\tsprintf(txt,\"55555555 found in MirrorList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(DoList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0xAAAAAAAA) {\n\t\t\tsprintf(txt,\"AAAAAAAA found in DoList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tptr = (unsigned long *)(MirrorList.Get_Array());\n\tfor (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /\n\t\tsizeof(unsigned long); i++) {\n\t\tif (ptr[i] == 0xAAAAAAAA) {\n\t\t\tsprintf(txt,\"AAAAAAAA found in MirrorList! Addr:%p\", &(ptr[i]));\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tfound_5s = 1;\n\t\t}\n\t}\n\n\tfor (i = 0; i < DoList.Count; i++) {\n\t\tif (memcmp(&DoList[i], &MirrorList[i], sizeof(EventClass)) != 0) {\n\t\t\tsprintf(txt,\"Queue Memory Trashed!  Head:%d Tail:%d, Addr:%p or %p\",\n\t\t\t\tDoList.Get_Head(),\n\t\t\t\tDoList.Get_Tail(),\n\t\t\t\tDoList.Get_Array() + i,\n\t\t\t\tMirrorList.Get_Array() + i);\n\t\t\tWWMessageBox().Process (txt);\n\t\t\tProg_End(\"Check_Mirror\", true);\n\t\t\tEmergency_Exit(0);\n\t\t}\n\t}\n\n\tif (found_5s) {\n\t\t//Prog_End();\n\t\tEmergency_Exit(0);\n\t}\n\n#endif\n}\t// end of Check_Mirror\n\n\n/*************************** end of queue.cpp ******************************/"
  },
  {
    "path": "REDALERT/QUEUE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/QUEUE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : QUEUE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/08/94                                                     *\n *                                                                                             *\n *                  Last Update : December 9, 1994 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   QueueClass<T,size>::Add -- Add object to queue.                                           *\n *   QueueClass<T,size>::First -- Fetches reference to first object in list.                   *\n *   QueueClass<T,size>::Init -- Initializes queue to empty state.                             *\n *   QueueClass<T,size>::Next -- Throws out the head of the line.                              *\n *   QueueClass<T,size>::operator[] -- Fetches reference to sub object in queue.               *\n *   QueueClass<T,size>::QueueClass -- Default constructor for QueueClass objects.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef QUEUE_H\n#define QUEUE_H\n\n#include\t\"mission.h\"\n#include\t\"target.h\"\n#include\t\"defines.h\"\n\n//#pragma warn -inl\n\n/*\n**\tThis class implements a classic FIFO queue (also known as - standing in line). Objects\n**\tare added to the end (tail) of the line. Objects are removed from the start (first) of\n**\tthe line. A keyboard buffer is a good example of a common computer use of a queue. There\n**\tis no provision for \"taking cuts\" or leaving the line once an object has been added.\n**\n**\tThe implementation uses a circular list of objects. This allows adding and deleting of\n**\telements without any maintenance moves of remaining objects that would otherwise be\n**\tnecessary in a simple array storage method. A side effect of this means that accessing the\n**\tinternal array directly is not allowed. Supporting functions are provided for this purpose.\n**\n**\tWARNING WARNING WARNING WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n**\tThe size parameter MUST be an exact power of two (2, 4, 8, 16, etc.) otherwise the internal\n**\tindexing algorithm will fail.\n*/\ntemplate<class T, int size>\nclass QueueClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is the count of the number of objects in the queue. If this count is zero,\n\t\t**\tthen the operator[], First(), and Next() functions are undefined. Check this\n\t\t**\tvalue BEFORE calling these functions.\n\t\t*/\n\t\tconst int Count;\n\n\t\t//-------------- Functions --------------------\n\t\tQueueClass(void);\t\t\t\t\t\t// Default constructor.\n\n\t\t/*\n\t\t**\tThe bracket subscript operator functions similarly to the way a normal subscript\n\t\t**\toperator works except that entry [0] matches the first-in-line and entry\n\t\t**\t[Count-1] matches the last-in-line. This is ensured regardless of the actual position\n\t\t**\tof the object in the circular internal list.\n\t\t*/\n\t\tT & operator[](int);\n\n\t\t/*\n\t\t**\tThis function will return a reference to the \"head of the line\" object.\n\t\t*/\n\t\tT & First(void);\n\n\t\t/*\n\t\t**\tThis function clears the list of objects.\n\t\t*/\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t**\tThis function discards the head-of-the-line object and advances all the remaining\n\t\t**\tobjects up by one. Mnemonic: Imagine a broadway audition and the director yells\n\t\t**\t\"NEXT!\"\n\t\t*/\n\t\tint Next(void);\n\n\t\t/*\n\t\t**\tThis will add an object to the tail of the line. If there is no more room to add\n\t\t**\tthe object, then false will be returned.\n\t\t*/\n\t\tint Add(T const &);\n\n\t\tint Get_Head(void);\n\t\tint Get_Tail(void);\n\t\tT * Get_Array(void);\n\n\tprivate:\n\t\tint Head;\t\t\t\t\t\t\t\t// Index of element in list the longest.\n\t\tint Tail;\t\t\t\t\t\t\t\t// Index where next new addition will go.\n\n\t\tT Array[size];\t\t\t\t\t\t\t// Raw array of objects.\n};\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::QueueClass -- Default constructor for QueueClass objects.               *\n *                                                                                             *\n *    This default constructor for QueueClass objects initializes the queue to an empty        *\n *    state.                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline QueueClass<T,size>::QueueClass(void) : Count(0)\n{\n\tInit();\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Init -- Initializes queue to empty state.                               *\n *                                                                                             *\n *    This function resets the queue to an empty state.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline void QueueClass<T,size>::Init(void)\n{\n\t((int &)Count) = 0;\n\tHead = 0;\n\tTail = 0;\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Add -- Add object to queue.                                             *\n *                                                                                             *\n *    This function is used to add an object to the tail of the line. If the queue cannot      *\n *    accept any more entries, then the object won't be added and false will be returned.      *\n *                                                                                             *\n * INPUT:   object   -- The object that is to be added to the queue.                           *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added successfully?                                           *\n *                                                                                             *\n * WARNINGS:   If the queue is full, then the object won't be added. Be sure to check for this.*\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Add(T const &q)\n{\n\tif (Count < size) {\n\t\tArray[Tail] = q;\n\t\tTail = (Tail + 1) & (size-1);\n\t\t((int &)Count) = Count + 1;\n\t\treturn(true);\n\t}\n\treturn (false);\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::Next -- Throws out the head of the line.                                *\n *                                                                                             *\n *    This routine is used to discard the object at the head of the line. All remaining        *\n *    objects \"move up\" one. No actual movement occurs, merely the index is adjusted, but      *\n *    the affect is that the next oldest object in the queue will now be returned with the     *\n *    next call to the First() function.                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns the number of object remaining in the queue.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Next(void)\n{\n\tif (Count) {\n\t\tHead = (Head + 1) & (size-1);\n\t\t((int &)Count) = Count - 1;\n\t}\n\treturn (Count);\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::operator[] -- Fetches reference to sub object in queue.                 *\n *                                                                                             *\n *    Use this routine to examine individual objects within the queue. The oldest object in    *\n *    the queue is referenced by an index value of zero. The newest object in the queue is     *\n *    referenced by a value of Count-1. If there are no objects in the queue, then this        *\n *    operator is undefined. Although this operator allows examination of the queue, there is  *\n *    no corresponding ability to insert or delete objects from the middle of the queue.       *\n *                                                                                             *\n * INPUT:   index -- The index into the queue of objects. Valid values range from zero to      *\n *                   Count-1. All other values return an undefined reference!                  *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the object indicated by the index.                     *\n *                                                                                             *\n * WARNINGS:   Check to make sure that Count is not zero before using this operator. Failure   *\n *             to do so will return a reference to an undefined object.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline T & QueueClass<T,size>::operator[](int index)\n{\n\treturn Array[(Head + index) & (size-1)];\n}\n\n\n/***********************************************************************************************\n * QueueClass<T,size>::First -- Fetches reference to first object in list.                     *\n *                                                                                             *\n *    This routine is used to fetch the first object in the list (head of the line). This      *\n *    object is the oldest in the list. Typical use of this function is to get and process     *\n *    the first object so that it may be discarded with the Next() function in order to bring  *\n *    subsequent objects to the first position.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the oldest object in the queue.                        *\n *                                                                                             *\n * WARNINGS:   If there are no objects in the queue, then this function returns an undefined   *\n *             reference. Be sure to check Count against zero before calling this function.    *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T, int size>\ninline T & QueueClass<T,size>::First(void)\n{\n\treturn Array[Head];\n}\n\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Get_Head(void)\n{\n\treturn Head;\n}\n\ntemplate<class T, int size>\ninline int QueueClass<T,size>::Get_Tail(void)\n{\n\treturn Tail;\n}\n\ntemplate<class T, int size>\ninline T * QueueClass<T,size>::Get_Array(void)\n{\n\treturn Array;\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/RADAR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RADAR.CPP 3     3/12/97 2:35p Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADAR.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : September 16, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Get_Multi_Color -- Get the multi color offset number                                      *\n *   RadarClass::AI -- Processes radar input (non-tactical).                                   *\n *   RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar.          *\n *   RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over.         *\n *   RadarClass::Click_In_Radar -- Check to see if a click is in radar map                     *\n *   RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate.        *\n *   RadarClass::Draw_It -- Displays the radar map of the terrain.                             *\n *   RadarClass::Draw_Names -- draws players' names on the radar map                           *\n *   RadarClass::Get_Jammed -- Fetch the current radar jammed state for the player.            *\n *   RadarClass::Init_Clear -- Sets the radar map to a known state                             *\n *   RadarClass::Is_Radar_Active -- Determines if the radar map is currently being displayed.  *\n *   RadarClass::Is_Radar_Existing -- Queries to see if radar map is available.                *\n *   RadarClass::Is_Zoomable -- Determines if the map can be zoomed.                           *\n *   RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped.                     *\n *   RadarClass::One_Time -- Handles one time processing for the radar map.                    *\n *   RadarClass::Player_Names -- toggles the Player-Names mode of the radar map                *\n *   RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel.               *\n *   RadarClass::RTacticalClass::Action -- I/O function for the radar map.                     *\n *   RadarClass::RadarClass -- Default constructor for RadarClass object.                      *\n *   RadarClass::Radar_Activate -- Controls radar activation.                                  *\n *   RadarClass::Radar_Anim -- Renders current frame of radar animation                        *\n *   RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor.                  *\n *   RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map.                 *\n *   RadarClass::Radar_Position -- Returns with the current position of the radar map.         *\n *   RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed       *\n *   RadarClass::Render_Infantry -- Displays objects on the radar map.                         *\n *   RadarClass::Render_Overlay -- Renders an icon for given overlay                           *\n *   RadarClass::Render_Terrain -- Render the terrain over the given cell                      *\n *   RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions.                       *\n *   RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell.*\n *   RadarClass::Set_Tactical_Position -- Called when setting the tactical display position.   *\n *   RadarClass::Set_Tactical_Position -- Called when setting the tactical display position.   *\n *   RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to*\n *   RadarClass::Zoom_Mode(void) -- Handles toggling zoom on the map                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n//void const * RadarClass::CoverShape;\nRadarClass::RTacticalClass RadarClass::RadarButton;\n\nvoid const * RadarClass::RadarAnim  = NULL;\nvoid const * RadarClass::RadarPulse = NULL;\nvoid const * RadarClass::RadarFrame = NULL;\n\nstatic bool FullRedraw = false;\n\nstatic GraphicBufferClass _IconStage(3,3);\nstatic GraphicBufferClass _TileStage(24,24);\n\n\n/***********************************************************************************************\n * RadarClass::RadarClass -- Default constructor for RadarClass object.                        *\n *                                                                                             *\n *    This default constructor merely sets the radar specific values to default settings. The  *\n *    radar must be deliberately activated in order for it to be displayed.                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/16/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadarClass::RadarClass(void) :\n\tIsToRedraw(false),\n\tRadarCursorRedraw(false),\n\tIsPulseActive(false),\n\tRadarPulseFrame(0),\n\tDoesRadarExist(false),\n\tIsRadarActive(false),\n\tIsRadarActivating(false),\n\tIsRadarDeactivating(false),\n\tIsRadarJammedByPlayerMask(0U),\n\tSpecialRadarFrame(0),\n\tRadarAnimFrame(0),\n\tRadarX(0),\n\tRadarY(0),\n\tRadarCellWidth(0),\n\tRadarCellHeight(0),\n\tRadarCell(0),\n\tBaseX(0),\n\tBaseY(0),\n\tRadarWidth(0),\n\tRadarHeight(0),\n\tIsZoomed(true),\n\tZoomFactor(0),\n\tIsPlayerNames(false),\n\tIsHouseSpy(false),\n\tSpyingOn(HOUSE_SPAIN),\n\tPixelPtr(0)\n{\n}\n\n\n/***********************************************************************************************\n * RadarClass::One_Time -- Handles one time processing for the radar map.                      *\n *                                                                                             *\n *    This routine handles any one time processing required in order for the radar map to      *\n *    function. This actually only requires an allocation of the radar staging buffer. This    *\n *    buffer is needed for those cases where the radar area of the page is being destroyed     *\n *    and it needs to be destroyed.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Be sure to call this routine only ONCE.                                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::One_Time(void)\n{\n\tRadWidth\t\t= 80 * RESFACTOR;\n\tRadHeight \t= 70 * RESFACTOR;\n\tRadX \t\t\t= SeenBuff.Get_Width() - RadWidth;\n\tRadY \t\t\t= 7 * RESFACTOR;\n\tRadPWidth \t= 64 * RESFACTOR;\n\tRadPHeight \t= 64 * RESFACTOR;\n\t#ifdef WIN32\n\t\tRadOffX \t\t= 6;\n\t\tRadOffY \t\t= 7;\n\t\tRadIWidth \t= 128+18;//************\n\t\tRadIHeight\t= 128+2;//************\n\t#else\n\t\tRadOffX \t\t= 4;\n\t\tRadOffY \t\t= 1;\n\t\tRadIWidth \t= 72;\n\t\tRadIHeight\t= 69;\n\t#endif\n\n\tDisplayClass::One_Time();\n#ifdef OBSOLETE\n\tRadarButton.X\t\t\t= RadX+RadOffX;\n\tRadarButton.Y \t\t\t= RadY+RadOffY;\n\tRadarButton.Width \t= RadIWidth;\n\tRadarButton.Height \t= RadIHeight;\n#else\n\tRadarButton.X\t\t\t= RadX;\n\tRadarButton.Y \t\t\t= RadY;\n\tRadarButton.Width \t= RadWidth;\n\tRadarButton.Height \t= RadHeight;\n#endif\n}\n\n\n/***********************************************************************************************\n * RadarClass::Init_Clear -- Sets the radar map to a known state.                              *\n *                                                                                             *\n *    This routine is used to initialize the radar map at the start of the scenario. It        *\n *    sets the radar map position and starts it in the disabled state.                         *\n *                                                                                             *\n * INPUT:   theater  -- The theater that the scenario is starting (unused by this routine).    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Init_Clear(void)\n{\n\tDisplayClass::Init_Clear();\n\tIsRadarActive\t\t\t= false;\n\tIsToRedraw \t\t\t\t= true;\n\tRadarCursorRedraw    = true;\n\tIsRadarActivating \t= false;\n\tIsRadarDeactivating \t= false;\n\tDoesRadarExist \t\t= false;\n\tPixelPtr \t\t\t\t= 0;\n\tIsPlayerNames\t\t\t= false;\n\n\t/*\n\t** If we have a valid map lets make sure that we set it correctly\n\t*/\n\tif (MapCellWidth || MapCellHeight) {\n#ifdef WIN32\n\t\tIsZoomed = false;\n#else\n\t\tIsZoomed = true;\n#endif\n\t\tZoom_Mode(Coord_Cell(Map.TacticalCoord));\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Activate -- Controls radar activation.                                    *\n *                                                                                             *\n *    Use this routine to turn the radar map on or off.                                        *\n *                                                                                             *\n * INPUT:   control  -- What to do with the radar map:                                         *\n *                      0 = Turn radar off.                                                    *\n *                      1 = Turn radar on.                                                     *\n *                      2 = Remove Radar Gadgets                                               *\n *                      3 = Add Radar Gadgets                                                  *\n *                      4 = Remove radar.                                                      *\n *                      -1= Toggle radar on or off.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the radar map already on?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/11/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Radar_Activate(int control)\n{\n\tbool old = IsRadarActive;\n\n\tswitch (control) {\n\n\t\t/*\n\t\t** Toggle the state of the radar map on or off.\n\t\t*/\n\t\tcase -1:\n\t\t\t{\n\t\t\t\tint temp = (IsRadarActive == false);\n\t\t\t\tif (temp) {\n\t\t\t\t\tRadar_Activate(1);\n\t\t\t\t} else {\n\t\t\t\t\tRadar_Activate(0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t** Turn the radar map off properly.\n\t\t*/\n\t\tcase 0:\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tif (IsRadarActive && !IsRadarDeactivating) {\n\t\t\t\t\t// Sound_Effect(VOC_RADAR_OFF); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure.\n\t\t\t\t\tIsRadarDeactivating = true;\n\t\t\t\t\tIsRadarActive = false;\n\t\t\t\t\tif (IsRadarActivating == true) {\n\t\t\t\t\t\tIsRadarActivating = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tRadar_Activate(2);\n\t\t\t}\n\t\t\treturn(old);\n\n\t\tcase 1:\n\t\t\tif (Map.IsSidebarActive) {\n\t\t\t\tif (!IsRadarActivating && !IsRadarActive) {\n\t\t\t\t\t// Sound_Effect(VOC_RADAR_ON); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure.\n\t\t\t\t\tIsRadarActivating = true;\n\t\t\t\t\tif (IsRadarDeactivating == true) {\n\t\t\t\t\t\tIsRadarDeactivating = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (DoesRadarExist) {\n\t\t\t\t\t\t\tRadarAnimFrame = MAX_RADAR_FRAMES;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRadarAnimFrame = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t\treturn(old);\n\n\t\tcase 2:\n\t\t\tif (Session.Type==GAME_NORMAL) {\n\t\t\t\tSidebarClass::Zoom.Disable();\n\t\t\t} else {\n\t\t\t\tSidebarClass::Zoom.Enable();\n\t\t\t}\n\t\t\tIsRadarActive = false;\n\t\t\tIsRadarActivating = false;\n\t\t\tIsRadarDeactivating = false;\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tif (Session.Type == GAME_NORMAL && Is_Zoomable()) {\n\t\t\t\tSidebarClass::Zoom.Enable();\n\t\t\t}\n\t\t\tIsRadarActive = true;\n\t\t\tIsRadarActivating = false;\n\t\t\tIsRadarDeactivating = false;\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tIsRadarActive\t\t\t= false;\n\t\t\tIsRadarActivating\t\t= false;\n\t\t\tIsRadarDeactivating\t= false;\n\t\t\tDoesRadarExist \t\t= false;\n\t\t\tFlag_To_Redraw(false);\n\t\t\tIsToRedraw = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (IsRadarActive != old) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tFullRedraw = IsRadarActive;\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Draw_It -- Displays the radar map of the terrain.                               *\n *                                                                                             *\n *    This is used to display the radar map that appears in the lower                          *\n *    right corner. The main changes to this map are the vehicles and                          *\n *    structure pixels.                                                                        *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/24/1991 JLB : Created.                                                                 *\n *   05/08/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid RadarClass::Draw_It(bool forced)\n{\n\tDisplayClass::Draw_It(forced);\n\n#if (0)\t                               // Legacy radar rendering not used. ST - 2/26/2020 3:53PM\n\n\tstatic char * _hiresradarnames[]={\n\t\t\"natoradr.shp\",\t//HOUSE_SPAIN,\n\t\t\"natoradr.shp\",   //HOUSE_GREECE,\n\t\t\"ussrradr.shp\",   //HOUSE_USSR,\n\t\t\"natoradr.shp\",   //HOUSE_ENGLAND,\n\t\t\"ussrradr.shp\",   //HOUSE_UKRAINE,\n\t\t\"natoradr.shp\",   //HOUSE_GERMANY,\n\t\t\"natoradr.shp\",   //HOUSE_FRANCE,\n\t\t\"natoradr.shp\",\t//HOUSE_TURKEY,\n\t\t\"natoradr.shp\",\t//HOUSE_GOOD\n\t\t\"ussrradr.shp\",\t//HOUSE_BAD\n\t};\n\tstatic char * _frames[]={\n\t\t\"nradrfrm.shp\",   //HOUSE_SPAIN,\n\t\t\"nradrfrm.shp\",   //HOUSE_GREECE,\n\t\t\"uradrfrm.shp\",   //HOUSE_USSR,\n\t\t\"nradrfrm.shp\",   //HOUSE_ENGLAND,\n\t\t\"uradrfrm.shp\",   //HOUSE_UKRAINE,\n\t\t\"nradrfrm.shp\",   //HOUSE_GERMANY,\n\t\t\"nradrfrm.shp\",   //HOUSE_FRANCE,\n\t\t\"nradrfrm.shp\",   //HOUSE_TURKEY,\n\t\t\"nradrfrm.shp\",\t//HOUSE_GOOD\n\t\t\"uradrfrm.shp\",\t//HOUSE_BAD\n\t};\n\n\tint radarforced = 0;\n\n\t/*\n\t**\tDon't perform any rendering if none is requested.\n\t*/\n\tif (!forced && !IsToRedraw && !FullRedraw) return;\n\n\tBStart(BENCH_RADAR);\n\n\tstatic HousesType _house = HOUSE_NONE;\n\n\tif (PlayerPtr->ActLike != _house) {\n\t\tchar name[_MAX_FNAME + _MAX_EXT];\n\n//\t\tstrcpy(name, \"NATORADR.SHP\" );\n//\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tstrcpy(name, _hiresradarnames[PlayerPtr->ActLike]);\n//\t\t}\n\t\t#ifndef NDEBUG\n\t\t\tRawFileClass file(name);\n\t\t\tif (file.Is_Available()) {\n\t\t\t\tRadarAnim = Load_Alloc_Data(file);\n\t\t\t} else {\n\t\t\t\tRadarAnim = MFCD::Retrieve(name);\n\t\t\t}\n\t\t\tstrcpy(name, \"PULSE.SHP\");\n\t\t\tRawFileClass file2(name);\n\t\t\tif (file2.Is_Available()) {\n\t\t\t\tRadarPulse = Load_Alloc_Data(file2);\n\t\t\t} else {\n\t\t\t\tRadarPulse = MFCD::Retrieve(name);\n\t\t\t}\n\t\t\tstrcpy(name, _frames[PlayerPtr->ActLike]);\n\t\t\tRawFileClass file3(name);\n\t\t\tif (file3.Is_Available()) {\n\t\t\t\tRadarFrame = Load_Alloc_Data(file3);\n\t\t\t} else {\n\t\t\t\tRadarFrame = MFCD::Retrieve(_frames[PlayerPtr->ActLike]);\n\t\t\t}\n\t\t#else\n\t\t\tRadarAnim = MFCD::Retrieve(name);\n\t\t\tstrcpy(name, \"PULSE.SHP\");\n\t\t\tRawFileClass file3(name);\n\t\t\tif (file3.Is_Available()) {\n\t\t\t\tRadarPulse = Load_Alloc_Data(file3);\n\t\t\t} else {\n\t\t\t\tRadarPulse = MFCD::Retrieve(name);\n\t\t\t}\n\t\tRadarFrame = MFCD::Retrieve(_frames[PlayerPtr->ActLike]);\n\t\t#endif\n\t\t_house = PlayerPtr->ActLike;\n\t}\n\n\t/*\n\t** If in player name mode, just draw player names\n\t*/\n\tif (IsPlayerNames) {\n\t\tDraw_Names();\n\t\tIsToRedraw = false;\n\t\tBEnd(BENCH_RADAR);\n\t\treturn;\n\t}\n\n\t/*\n\t** If in spy-on-radar facility mode, draw the appropriate info.\n\t*/\n\tif (IsHouseSpy) {\n\t\tIsToRedraw = false;\n\t\tif (Draw_House_Info()) {\n\t\t\tBEnd(BENCH_RADAR);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (IsRadarActivating || IsRadarDeactivating || IsRadarJammed) {\n\t\tRadar_Anim();\n\t\tMap.Repair.Draw_Me(true);\n\t\tMap.Upgrade.Draw_Me(true);\n\t\tMap.Zoom.Draw_Me(true);\n\t\tIsToRedraw = false;\n\t\tBEnd(BENCH_RADAR);\n\t\treturn;\n\t}\n\n\tif (Map.IsSidebarActive) {\n\t\tif (IsRadarActive) {\n\t\t\t\n\t\t\tif (RunningAsDLL) {\n\t\t\t\tBEnd(BENCH_RADAR);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf only a few of the radar pixels need to be redrawn, then find and redraw\n\t\t\t**\tonly these.\n\t\t\t*/\n\t\t\tif (!forced && IsToRedraw && !FullRedraw && !IsPulseActive) {\n\t\t\t\tIsToRedraw = false;\n\n\t\t\t\tif (PixelPtr) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRender all pixels in the \"to redraw\" stack.\n\t\t\t\t\t*/\n\t\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\t\tfor (int index = 0; index < (int)PixelPtr; index++) {\n\t\t\t\t\t\t\tCELL cell = PixelStack[index];\n\t\t\t\t\t  \t\tif (Cell_On_Radar(cell)) {\n\t\t\t\t\t\t\t\t(*this)[cell].IsPlot = false;\n\t\t\t\t\t\t\t\tPlot_Radar_Pixel(cell);\n\t\t\t\t\t\t\t\tRadarCursorRedraw |= (*this)[cell].IsRadarCursor;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tRefill the stack if there is pending pixels yet to be plotted.\n\t\t\t\t\t**\tThis should only process in sections for speed reasons\n\t\t\t\t\t*/\n\t\t\t\t\tif (PixelPtr == PIXELSTACK) {\n\t\t\t\t\t\tPixelPtr = 0;\n\n\t\t\t\t\t\tfor (int y = 0; y < MapCellHeight; y++) {\n\t\t\t\t\t\t\tfor (int x = 0; x < MapCellWidth; x++) {\n\t\t\t\t\t\t\t\tCELL cell = XY_Cell(MapCellX + x, MapCellY + y);\n\t\t\t\t\t\t\t  \tif (Cell_On_Radar(cell)) {\n\n\t\t\t\t\t\t\t\t\tif ((*this)[cell].IsPlot) {\n\t\t\t\t\t\t\t\t\t\tPixelStack[PixelPtr++] = cell;\n\t\t\t\t\t\t\t\t\t\tIsToRedraw = true;\n\t\t\t\t\t\t\t\t\t\tif\t(PixelPtr == PIXELSTACK) break;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif\t(PixelPtr == PIXELSTACK) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPixelPtr = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tRadar_Cursor(RadarCursorRedraw);\n\n\t\t\t} else {\n\n#ifdef WIN32\n\t\t\t\tGraphicViewPortClass * oldpage\t= Set_Logic_Page(HidPage);\n#else\n\t\t\t\tGraphicBufferClass * oldpage\t= Set_Logic_Page(HidPage);\n#endif\n\n\t\t\t\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY+(1 * RESFACTOR), WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\t\tif (BaseX || BaseY) {\n\n\t\t\t\t\tif (!IsZoomed && BaseX && BaseY && (int)RadarWidth< (RadIWidth-1) && (int)RadarHeight < (RadIHeight-1)) {\n#ifdef WIN32\n\t\t\t\t\t\tLogicPage->Draw_Rect(RadX + RadOffX + BaseX -1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY -1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + RadarWidth,\n//\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + RadarWidth +1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + RadarHeight,\n//\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + RadarHeight +1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHITE);\n#endif\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tLogicPage->Fill_Rect(\tRadX + RadOffX,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + RadIWidth - 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + RadIHeight - 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\tBLACK);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Draw the entire radar map.\n\t\t\t\t*/\n\t\t\t\tif (LogicPage->Lock()) {\n\t\t\t\t\tfor (int index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\t\t\t\t\tif (In_Radar(index) && Cell_On_Radar(index)) {\n\t\t\t\t\t\t\tPlot_Radar_Pixel(index);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (IsPulseActive) {\n\t\t\t\t\t\tCC_Draw_Shape(RadarPulse, RadarPulseFrame++, RadX + RadOffX, RadY+1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\t\t\t}\n\t\t\t\t\tLogicPage->Unlock();\n\t\t\t\t}\n\n\t\t\t\tRadar_Cursor(true);\n\t\t\t\tFullRedraw = false;\n\t\t\t\tIsToRedraw = false;\n\n\t\t\t\tMap.Repair.Draw_Me(true);\n\t\t\t\tMap.Upgrade.Draw_Me(true);\n\t\t\t\tMap.Zoom.Draw_Me(true);\n\n\t\t\t\tif (oldpage == &SeenBuff) {\n\t\t\t\t\tHide_Mouse();\n\t\t\t\t\tLogicPage->Blit(SeenBuff, RadX, RadY, RadX, RadY, RadWidth, RadHeight);\n\t\t\t\t\tShow_Mouse();\n\t\t\t\t}\n\n\t\t\t\tSet_Logic_Page(oldpage);\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf the radar is not active, then only draw the cover plate if forced to do so.\n\t\t\t*/\n\t\t\tint val = (DoesRadarExist) ?  MAX_RADAR_FRAMES : 0;\n\t\t\tCC_Draw_Shape(RadarAnim, val, RadX, RadY + (1 * RESFACTOR), WINDOW_MAIN, SHAPE_NORMAL);\n\t\t\tFullRedraw = false;\n\t\t\tIsToRedraw = false;\n\n\t\t\tif (RunningAsDLL) {\n\t\t\t\tBEnd(BENCH_RADAR);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDisplay the country name on the cover plate when in multi play only.\n\t\t\t*/\n\t\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\t\tFancy_Text_Print(Text_String(HouseTypeClass::As_Reference(PlayerPtr->ActLike).Full_Name()), RadX+RadWidth/2, RadY+RadHeight-10*RESFACTOR, &ColorRemaps[PlayerPtr->RemapColor], TBLACK, TPF_CENTER|TPF_TEXT|TPF_DROPSHADOW);\n\t\t\t}\n\n\t\t\tMap.Repair.Draw_Me(true);\n\t\t\tMap.Upgrade.Draw_Me(true);\n\t\t\tMap.Zoom.Draw_Me(true);\n\n\t\t}\n\n\t}\n\tBEnd(BENCH_RADAR);\n#endif\n}\n\n\n/***************************************************************************\n * RadarClass::Render_Terrain -- Render the terrain over the given cell    *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/12/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Render_Terrain(CELL cell, int x, int y, int size)\n{\n\tTerrainClass\t* list[4] = {0,0,0,0};\n\tint\t\t\t\tlistidx = 0;\n\tint\t\t\t\tlp,lp2;\n\n\n\tObjectClass * obj = Map[cell].Cell_Occupier();\n\n\t/*\n\t** If the cell is occupied by a terrain type, add it to the sortable\n\t** list.\n\t*/\n\tif (obj && obj->What_Am_I() == RTTI_TERRAIN)\n\t\tlist[listidx++] = (TerrainClass *)obj;\n\n\t/*\n\t** Now loop through all the occupiers and add them to the list if they\n\t** are terrain type.\n\t*/\n\tfor (lp = 0; lp < ARRAY_SIZE(Map[cell].Overlapper); lp ++) {\n\t\tobj = Map[cell].Overlapper[lp];\n\t\tif (obj && obj->What_Am_I() == RTTI_TERRAIN)\n\t\t\tlist[listidx++] = (TerrainClass *)obj;\n\t}\n\n\t/*\n\t** If there are no entries in our list then just get out.\n\t*/\n\tif (!listidx) return;\n\n\t/*\n\t**\tIf there is terrain in this cell then draw a dark pixel to\n\t** represent it.\n\t*/\n\tif (size == 1) {\n\t\tLogicPage->Put_Pixel(x, y, 21);\n//\t\tLogicPage->Put_Pixel(x, y, 60);\n\t\treturn;\n\t}\n\n\t/*\n\t** Sort the list by its sort Y value so that we can render in the proper\n\t** order.\n\t*/\n\tfor (lp = 0; lp < listidx - 1; lp ++) {\n\t\tfor (lp2 = lp + 1; lp2 < listidx; lp2++) {\n\t\t\tif (list[lp]->Sort_Y() > list[lp2]->Sort_Y()) {\n\t\t\t\tTerrainClass * terrain = list[lp];\n\t\t\t\tlist[lp] = list[lp2];\n\t\t\t\tlist[lp2] = terrain;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** loop through the list and take care of rendering the correct icon.\n\t*/\n\tfor (lp = 0; lp < listidx; lp ++) {\n\t\tunsigned char * icon = list[lp]->Radar_Icon(cell);\n\t\tif (!icon) continue;\n#ifdef WIN32\n\t\tBuffer_To_Page(0, 0, 3, 3, icon, _IconStage);\n\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, ZoomFactor, ZoomFactor, TRUE, (char *)&FadingBrighten[0]);\n#else\n\t\tfor (int lpy = 0; lpy < 3; lpy++) {\n\t\t\tfor (int lpx = 0; lpx < 3; lpx++) {\n\t\t\t\tif (*icon) {\n\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingBrighten[*icon]);\n\t\t\t\t}\n\t\t\t\ticon++;\n\t\t\t}\n\t\t}\n#endif\t//WIN32\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Render_Infantry -- Displays objects on the radar map.                           *\n *                                                                                             *\n *    This routine will display an object imagery at the location specified according to the   *\n *    condition of the specified cell.                                                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell to use as reference when drawing the radar pixel.                *\n *                                                                                             *\n *          x,y   -- The pixel coordinate to render the radar \"pixel\" at.                      *\n *                                                                                             *\n *          size  -- The size of the \"pixel\". When zoomed in, this value will be \"3\".          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Render_Infantry(CELL cell, int x, int y, int size)\n{\n\tObjectClass * obj;\n\n\tobj = (ObjectClass *)Map[cell].Cell_Occupier();\n\twhile (obj) {\n\t\tif (obj->Is_Techno() && ((TechnoClass *)obj)->Is_Visible_On_Radar()) {\n\t\t\tint color = ColorRemaps[((InfantryClass *)obj)->House->RemapColor].Bar;\n//\t\t\tint color = ColorRemaps[((InfantryClass *)obj)->House->RemapColor].BrightColor;\n\t\t\tint xoff;\n\t\t\tint yoff;\n\t\t\tint subsize = max(1, size/3);\n\n\t\t\tswitch (obj->What_Am_I()) {\n\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\txoff = (Coord_XLepton(obj->Coord) / (CELL_LEPTON_W/(size+1))) - subsize/2;\n\t\t\t\t\txoff = max(xoff, 0);\n\t\t\t\t\txoff = min(xoff, size-subsize);\n\t\t\t\t\tyoff = (Coord_YLepton(obj->Coord) / (CELL_LEPTON_H/(size+1))) - subsize/2;\n\t\t\t\t\tyoff = max(yoff, 0);\n\t\t\t\t\tyoff = min(yoff, size-subsize);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Draw the infantryman's pixel.  If he's a spy, draw in my house color\n\t\t\t\t\t*/\n\t\t\t\t\tif (*(InfantryClass *)obj == INFANTRY_SPY) {\n\t\t\t\t\t\tcolor = ColorRemaps[PlayerPtr->RemapColor].Bar;\n//\t\t\t\t\t\tcolor = ColorRemaps[PlayerPtr->RemapColor].BrightColor;\n\t\t\t\t\t}\n\t\t\t\t\tLogicPage->Fill_Rect(x+xoff, y+yoff, x+xoff+(subsize-1), y+yoff+(subsize-1), color);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RTTI_UNIT:\n\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\tLogicPage->Fill_Rect(x, y, x+size-1, y+size-1, color);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tobj = obj->Next;\n\t}\n\n}\n\n\n/***************************************************************************\n * RadarClass::Render_Overlay -- Renders an icon for given overlay         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/18/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Render_Overlay(CELL cell, int x, int y, int size)\n{\n\t//int lpx,lpy;\n\n\tOverlayType overlay = (*this)[cell].Overlay;\n \tif (overlay != OVERLAY_NONE) {\n\t\tOverlayTypeClass const * otype = &OverlayTypeClass::As_Reference(overlay);\n\n\t\tif (otype->IsRadarVisible) {\n\t\t\tunsigned char * icon = otype->Radar_Icon((*this)[cell].OverlayData);\n\t\t\tif (!icon) return;\n#ifdef WIN32\n\t\t\tBuffer_To_Page(0, 0, 3, 3, icon, _IconStage);\n\t\t\tif (otype->IsTiberium) {\n\t\t\t\tif (size == 1) {\n\t\t\t\t\tLogicPage->Put_Pixel(x, y, DKGREY);\n\n//\t\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingShade[0]);\n\t\t\t\t} else {\n\t\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingYellow[0]);\n\t\t\t\t}\n//\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingGreen[0]);\n//\t\t\t} else {\n//\t\t\t\t_IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingBrighten[0]);\n\t\t\t}\n\n#else\n\t\t\tfor (int lpy = 0; lpy < size; lpy++) {\n\t\t\t\tfor (int lpx = 0; lpx < size; lpx++) {\n\t\t\t\t\tif (size == 1) icon+=4;\n\t\t\t\t\tif (*icon) {\n\t\t\t\t\t\tif (otype->IsTiberium) {\n\t\t\t\t\t\t\tif (size == 1) {\n\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, DKGREY);\n//\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingShade[*icon]);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingYellow[*icon]);\n\t\t\t\t\t\t\t}\n//\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingGreen[*icon]);\n//\t\t\t\t\t\t} else {\n//\t\t\t\t\t\t\tLogicPage->Put_Pixel(x + lpx, y + lpy, FadingBrighten[*icon]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (size == 1) {\n\t\t\t\t\t\ticon+=5;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ticon++;\n\t\t\t\t\t}\n\t\t\t\t\ticon++;\n\t\t\t\t}\n\t\t\t}\n#endif\t//WIN32\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * RadarClass::Zoom_Mode -- Handles toggling zoom on the map               *\n *                                                                         *\n * INPUT:      none                                                        *\n *                                                                         *\n * OUTPUT:  \tnone                                                        *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/29/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Zoom_Mode(CELL cell)\n{\n\tint map_c_width;\n\tint map_c_height;\n\n\t/*\n\t** Set all of the initial zoom mode variables to the correct\n\t** setting.\n\t*/\n#ifdef WIN32\n\tif (Is_Zoomable()) {\n\t\tIsZoomed\t\t\t\t= !IsZoomed;\n\t} else {\n\t\tIsZoomed = true;\n\t}\n#else\n\tIsZoomed\t\t\t\t= false;\n#endif\n\tBaseX\t\t\t\t\t= 0;\n\tBaseY\t\t\t\t\t= 0;\n\n\t/*\n\t** Figure out exactly what size we need to zoom the map to.\n\t*/\n\tif (!IsZoomed) {\n\t\tint xfactor\t\t\t= RadIWidth / MapCellWidth;\n\t\tint yfactor\t\t\t= RadIHeight / MapCellHeight;\n\t\tZoomFactor\t\t\t= max(min(xfactor, yfactor) , 1);\n\t\tmap_c_width\t\t\t= MapCellWidth;\n\t\tmap_c_height      = MapCellHeight;\n\t} else {\n\t\tZoomFactor\t\t\t= 3;\n//\t\tZoomFactor\t\t\t= 6;\n\t\tmap_c_width\t\t\t= RadIWidth / ZoomFactor;\n\t\tmap_c_height\t\t= RadIHeight / ZoomFactor;\n\t}\n\n\t/*\n\t** Make sure we do not show more cells than are on the map.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n\tmap_c_width\t\t\t= min(map_c_width, RadIWidth);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, RadIHeight);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#else\n\tmap_c_width\t\t\t= min(map_c_width, 62 * RESFACTOR);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, 62 * RESFACTOR);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#endif\n#else\n\tmap_c_width\t\t\t= min(map_c_width, 62 * RESFACTOR);\n\tmap_c_width\t\t\t= min(map_c_width, MapCellWidth);\n\tmap_c_height\t\t= min(map_c_height, 62 * RESFACTOR);\n\tmap_c_height\t\t= min(map_c_height, MapCellHeight);\n#endif\n\n\t/*\n\t** Find the amount of remainder because this will let us calculate\n\t** how to center the thing.\n\t*/\n\tint rem_x \t\t\t= RadIWidth - (map_c_width * ZoomFactor);\n\tint rem_y \t\t\t= RadIHeight - (map_c_height * ZoomFactor);\n\n\t/*\n\t** Finally mark the map so it shows just as much as it is supposed\n\t** to.\n\t*/\n\tBaseX\t\t\t\t\t= rem_x / 2;\n\tBaseY\t\t\t\t\t= rem_y / 2;\n\tRadarCellWidth \t= map_c_width;\n\tRadarCellHeight \t= map_c_height;\n\tRadarWidth\t\t\t= RadIWidth - rem_x;\n\tRadarHeight\t\t\t= RadIHeight - rem_y;\n\n\t/*\n\t** Set the radar position to the current cell.\n\t*/\n\tSet_Radar_Position(cell);\n\n\t/*\n\t** When zoom mode changes then we need to redraw the radar\n\t** area.\n\t*/\n\tIsToRedraw = true;\n\n\t/*\n\t** Notify the map that we need to redraw a portion\n\t*/\n\tFlag_To_Redraw(false);\n\n\t/*\n\t** Since we have made a vast change we must redraw everything\n\t*/\n\tFullRedraw = true;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Zoomable -- Determines if the map can be zoomed.                             *\n *                                                                                             *\n *    This will check to see if the zoomed mode of the map would be just the same size as      *\n *    the non-zoomed mode. If this is true, then zooming would have no effect, so return       *\n *    false indicating that zooming is not allowed.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is zooming allowed?                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Zoomable(void) const\n{\n\tint xfactor = RadIWidth / MapCellWidth;\n\tint yfactor = RadIHeight / MapCellHeight;\n\tint factor = max(min(xfactor, yfactor) , 1);\n\tif (factor == 3) {\n\t\treturn(false);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel.                 *\n *                                                                                             *\n *    This will update the radar map with a pixel. It is used to display                       *\n *    vehicle positions on the radar map.                                                      *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to unit to render at the given position. If                       *\n *                   NULL is passed in, then the underlying terrain is                         *\n *                   displayed instead.                                                        *\n *                                                                                             *\n *          pos   -- Position on the map to update.                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   This routine does NOT hide the mouse. It is up to you to                        *\n *             do so.                                                                          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/04/1991 JLB : Created.                                                                 *\n *   06/21/1991 JLB : Large blips for units & buildings.                                       *\n *   02/14/1994 JLB : Revamped.                                                                *\n *   04/17/1995 PWG : Created.                                                                 *\n *   04/18/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Plot_Radar_Pixel(CELL cell)\n{\n\tif (cell == -1) cell = 1;\n\n\tint\tx,y;\t\t\t\t\t// Coordinate of cell location.\n\n\t/*\n\t**\tPerform any clipping on the cell coordinate.\n\t*/\n\tif (!IsRadarActive || (unsigned)cell > MAP_CELL_TOTAL) {\n\t\treturn;\n\t}\n\n\tif (!In_Radar(cell) || !Cell_On_Radar(cell)) {\n\t\treturn;\n\t}\n\n\t/*\n\t** If we are zoomed in then calculate the pixel based off of the portion\n\t** of the map the radar is viewing.\n\t*/\n\tx = Cell_X(cell) - RadarX;\n\ty = Cell_Y(cell) - RadarY;\n\tif ((unsigned)x >= RadarCellWidth || (unsigned)y >= RadarCellHeight) {\n\t\treturn;\n\t}\n\n\tbool usjamming = false;\n\tif (LogicPage->Lock()) {\n\t\tCellClass * cellptr = &(*this)[cell];\n \t\tx = RadX + RadOffX + BaseX + (x * ZoomFactor);\n \t\ty = RadY + RadOffY + BaseY + (y * ZoomFactor);\n\n \t\t/*\n \t\t**\tDetermine what (if any) vehicle or unit should be rendered in this blip.\n \t\t*/\n\t\tint color=TBLACK;\t\t// Color of the pixel to plot.\n\t\tint housebit = (1 << PlayerPtr->Class->House);\n\t\tint celljammed = (*this)[cell].Jammed;\n\t\tint jammed = celljammed & (0xFFFF - housebit);\n \t\tif (!jammed && ((*this)[cell].IsMapped || Debug_Unshroud)) {\n// \t\tif (!jammed && ((*this)[cell].IsVisible || Debug_Unshroud)) {\n \t\t\tcolor = cellptr->Cell_Color(true);\n\t\t\tif ( (celljammed & housebit) && (color == TBLACK) ) {\n\t\t\t\tcolor = BLACK;//FadingWayDark[color];\n\t\t\t\tusjamming = true;\n\t\t\t}\n \t\t} else  {\n \t\t\tcolor = BLACK;\n \t\t}\n\n \t\t/*\n \t\t**\tIf no color override occurs for this cell, then render the underlying\n \t\t**\tterrain.\n \t\t*/\n\t\tif (color == TBLACK) {\n\t\t\tif (ZoomFactor > 1) {\n\t\t\t\tvoid const * ptr = NULL;\n\t\t\t\tint icon;\n\n\t\t\t\t/*\n\t\t\t\t**\tFetch the template pointer and template icon number for the\n\t\t\t\t**\tspecified cell.\n\t\t\t\t*/\n\t\t\t\tif (cellptr->TType != TEMPLATE_NONE && cellptr->TType != 255) {\n\t\t\t\t\tptr = TemplateTypeClass::As_Reference(cellptr->TType).Get_Image_Data();\n\t\t\t\t\ticon = cellptr->TIcon;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the template pointer is still NULL, then this means either a clear\n\t\t\t\t**\ttemplate or an illegal one. Setup for a clear template.\n\t\t\t\t*/\n\t\t\t\tif (ptr == NULL) {\n\t\t\t\t\tptr = TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1).Get_Image_Data();\n\t\t\t\t\ticon = cellptr->Clear_Icon();\n\t\t\t\t}\n\n\t\t\t\tIconsetClass const * iconset = (IconsetClass const *)ptr;\n\t\t\t\tunsigned char const * icondata = iconset->Icon_Data();\n\n\n\t\t\t\t/*\n\t\t\t\t**\tConvert the logical icon number into the actual icon number.\n\t\t\t\t*/\n\t\t\t\ticon &= 0x00FF;\n\t\t\t\ticon = *(iconset->Map_Data() + icon);\n\n\t\t\t\tunsigned char * data = (unsigned char *)icondata + icon*(24*24);\n\t\t\t\tBuffer_To_Page(0, 0, 24, 24, data, _TileStage);\n\t\t\t\t_TileStage.Scale(*LogicPage, 0, 0, x, y, 24, 24, ZoomFactor, ZoomFactor, TRUE);\n\t\t\t} else {\n//\t\t\t\tLogicPage->Fill_Rect(x, y, x+ZoomFactor-1, y+ZoomFactor-1, cellptr->Cell_Color(false));\n/*BG*/\t\tLogicPage->Put_Pixel(x, y, cellptr->Cell_Color(false));\n\t\t\t}\n\t\t} else {\n\t\t\tLogicPage->Fill_Rect(x, y, x+ZoomFactor-1, y+ZoomFactor-1, color);\n///*BG*/\t\tLogicPage->Put_Pixel(x, y, color);\n\t\t}\n\t\tif (color != BLACK) {\n\t\t\tRender_Overlay(cell, x, y, ZoomFactor);\n\t \t\tRender_Terrain(cell, x, y, ZoomFactor);\n\t\t\tRender_Infantry(cell, x, y, ZoomFactor);\n\t\t} else {\n\t\t\tif(usjamming) {\n\t\t\t\tRender_Infantry(cell, x, y, ZoomFactor);\n\t\t\t}\n\t\t}\n\t\tLogicPage->Unlock();\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map.                   *\n *                                                                                             *\n *    This routine is used to inform the system that a pixel needs to be                       *\n *    rerendered on the radar map. The pixel(s) will be rendered the                           *\n *    next time the map is refreshed.                                                          *\n *                                                                                             *\n * INPUT:   cell  -- The map cell to be rerendered.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/12/1992 JLB : Created.                                                                 *\n *   05/08/1994 JLB : Converted to member function.                                            *\n *=============================================================================================*/\nvoid RadarClass::Radar_Pixel(CELL cell)\n{\n\tif (IsRadarActive && Map.IsSidebarActive && Cell_On_Radar(cell)) {\n\t\tIsToRedraw = true;\n\t\t(*this)[cell].IsPlot = true;\n\t\tif (PixelPtr < PIXELSTACK) {\n\t\t\tPixelStack[PixelPtr++] = cell;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate.          *\n *                                                                                             *\n *    This routine will examine the X and Y coordinate and convert them into the X and Y       *\n *    cell coordinate value that corresponds to the location.                                  *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y mouse coordinate already normalized to the radar upper left   *\n *                   corner.                                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with success rating in addition, the X and Y values will now hold the      *\n *          cell coordinates of the cell the pixel offsets indicated.                          *\n *             Result 1 = click was in radar region                                            *\n *             Result 0 = click was outside radar region completely                            *\n *             Result-1 = click in radar area but not on clickable region of radar.            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/30/1995 PWG : Created.                                                                 *\n *   07/16/1995 JLB : Recognizes when sidebar is closed now.                                   *\n *=============================================================================================*/\nint RadarClass::Click_In_Radar(int &ptr_x, int &ptr_y, bool change) const\n{\n\tint x\t= ptr_x;\n\tint y\t= ptr_y;\n\n\t/*\n\t** If radar is not active the click could have been on a radar point\n\t*/\n\tif (!IsRadarActive || !Map.IsSidebarActive) return(0);\n\n\tx -= (RadX + RadOffX);\n\ty -= (RadY + RadOffY);\n\tif (x < RadIWidth && y < RadIHeight) {\n\t\tx -= BaseX;\n\t\ty -= BaseY;\n\n\t\tif ((unsigned)x < RadarWidth + (ZoomFactor-1) && (unsigned)y < RadarHeight + (ZoomFactor-1)) {\n//\t\tif ((unsigned)x < RadarWidth && (unsigned)y < RadarHeight) {\n\t\t\tx = RadarX + (x / ZoomFactor);\n\t\t\ty = RadarY + (y / ZoomFactor);\n\t\t\tif (change) {\n\t\t\t\tptr_x = x;\n\t\t\t\tptr_y = y;\n\t\t\t}\n\t\t\treturn(1);\n\t\t}\n\t\treturn(-1);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over.           *\n *                                                                                             *\n *    This routine will examine the pixel coordinate provided and determine what cell it       *\n *    represents. If the radar map is not active or the coordinates are not positioned over    *\n *    the radar map, then it will fall into the base class corresponding routine.              *\n *                                                                                             *\n * INPUT:   x,y   -- The pixel coordinate to convert into a cell number.                       *\n *                                                                                             *\n * OUTPUT:  Returns with the cell number that the coordinate is over or -1 if not over any     *\n *          cell.                                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL RadarClass::Click_Cell_Calc(int x, int y) const\n{\n\tint result = Click_In_Radar(x, y, true);\n\tswitch (result) {\n\t\tcase 1:\n\t\t\treturn(XY_Cell(x, y));\n\n\t\tcase -1:\n\t\t\treturn(-1);\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(DisplayClass::Click_Cell_Calc(x, y));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped.                       *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes mapped.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being mapped.                                            *\n *                                                                                             *\n *          house -- The house that is doing the mapping.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the cell mapped (for the first time) by this routine?                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/22/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Map_Cell(CELL cell, HouseClass * house, bool check_radar_spied, bool and_for_allies)\n{\n\tif (DisplayClass::Map_Cell(cell, house, check_radar_spied, and_for_allies)) {\n\t\tRadar_Pixel(cell);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n\nvoid RadarClass::Cursor_Cell(CELL cell, int value)\n{\n\t/*\n\t** If this cell is not on the radar don't bother doing anything.\n\t*/\n\tif (Cell_On_Radar(cell)) {\n\n\t\tint temp = (*this)[cell].IsRadarCursor;\n\n\t\tif (temp != value) {\n\n\t\t\t/*\n\t\t\t**\tRecord the new state of this cell.\n\t\t\t*/\n\t\t\t(*this)[cell].IsRadarCursor\t= value;\n\n\t\t\t/*\n\t\t\t**\tIf we are erasing then erase the cell.\n\t\t\t*/\n\t\t\tif (value == FALSE) \t{\n\t\t\t\tPlot_Radar_Pixel(cell);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid RadarClass::Mark_Radar(int x1, int y1, int x2, int y2, int value, int barlen)\n{\n\tint x, y;\n\t/*\n\t** First step is to convert pixel coordinates back to a CellX and CellY.\n\t*/\n\tx1 = RadarX + (x1 / ZoomFactor);\n\ty1 = RadarY + (y1 / ZoomFactor);\n\tx2 = RadarX + (x2 / ZoomFactor);\n\ty2 = RadarY + (y2 / ZoomFactor);\n\n\t/*\n\t** Now we need to convert the Pixel length to a cell length.\n\t*/\n\tbarlen = (barlen / ZoomFactor) + 1;\n\n\t/*\n\t** Now lets loop through and mark the map with the proper value.\n\t*/\n\tfor (int lp = 0; lp <= barlen; lp++) {\n\t\t/*\n\t\t** Do Horizontal action to upper and lower left corners.\n\t\t*/\n\t\tx = x1 + lp;\n\t\tCursor_Cell(XY_Cell(x, y1), value);\n\t\tCursor_Cell(XY_Cell(x, y2), value);\n\t\t/*\n\t\t** Do Horizontal Action to upper and lower right corners\n\t\t*/\n\t\tx = x2 - lp;\n\t\tCursor_Cell(XY_Cell(x, y1), value);\n\t\tCursor_Cell(XY_Cell(x, y2), value);\n\t\t/*\n\t\t** Do Vertical Action to left and right upper corners\n\t\t*/\n\t\ty = y1 + lp;\n\t\tCursor_Cell(XY_Cell(x1, y), value);\n\t\tCursor_Cell(XY_Cell(x2, y), value);\n\n\t\t/*\n\t\t** Do Vertical action to left and right lower corners.\n\t\t*/\n\t\ty = y2 - lp;\n\t\tCursor_Cell(XY_Cell(x1, y), value);\n\t\tCursor_Cell(XY_Cell(x2, y), value);\n\t}\n}\n\n\n\n/***********************************************************************************************\n * RadarClass::Cell_XY_To_Radar_Pixel-- Adjust the position of the radar map cursor.           *\n *                                                                                             *\n *    This routine will adjust the location (and visibility) of the radar                      *\n *    map cursor. It handles all restoration, drawing, and flashing.                           *\n *                                                                                             *\n * INPUT:   pos   - Cell position for the cursor. If the value is -1 then                      *\n *                  the cursor will be hidden. If the value is equal to                        *\n *                  the last value passed in then cursor flashing will                         *\n *                  be maintained.                                                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   11/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Cell_XY_To_Radar_Pixel(int cellx, int celly, int &x, int &y)\n{\n\tx = (cellx - RadarX) * ZoomFactor;\n\ty = (celly - RadarY) * ZoomFactor;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Jam_Cell -- Updates radar map when a cell becomes jammed.                       *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes jammed.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being jammed.                                            *\n *                                                                                             *\n *          house -- The house that is doing the jamming.                                      *\n *                                                                                             *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Jam_Cell(CELL cell, HouseClass * house/*KO, bool shadeit*/)\n{\n\tunsigned short jam = 1 << house->Class->House;\n\t(*this)[cell].Jammed |= jam;\n\t\n\t/*\n\t** Updated for client/server multiplayer. ST - 8/12/2019 11:00AM\n\t*/\n\tif (Session.Type != GAME_GLYPHX_MULTIPLAYER) {\n\t\tif (house != PlayerPtr) Shroud_Cell(cell, PlayerPtr/*KO, shadeit*/);\n\t\n\t} else {\n\t\t\n\t\tfor (int i = 0; i < Session.Players.Count(); i++) {\n\t\t\tHouseClass *player_house = HouseClass::As_Pointer(Session.Players[i]->Player.ID);\n\t\t\tif (player_house->IsHuman && player_house != house && !house->Is_Ally(player_house)) {\n\t\t\t\tShroud_Cell(cell, player_house);\n\t\t\t}\n\t\t}\n\t}\t\n\n\tRadar_Pixel(cell);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::UnJam_Cell -- Updates radar map when a cell becomes jammed.                     *\n *                                                                                             *\n *    This routine will update the radar map if a cell becomes jammed.                         *\n *                                                                                             *\n * INPUT:   cell  -- The cell that is being jammed.                                            *\n *                                                                                             *\n *          house -- The house that is doing the jamming.                                      *\n *                                                                                             *\n * OUTPUT:  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/09/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::UnJam_Cell(CELL cell, HouseClass * house)\n{\n\tunsigned short jam = 1 << house->Class->House;\n\t(*this)[cell].Redraw_Objects();\n\t(*this)[cell].Jammed &= (0xFFFF - jam);\n\tRadar_Pixel(cell);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor.                    *\n *                                                                                             *\n *    This routine will adjust the location (and visibility) of the radar                      *\n *    map cursor. It handles all restoration, drawing, and flashing.                           *\n *                                                                                             *\n * INPUT:   pos   - Cell position for the cursor. If the value is -1 then                      *\n *                  the cursor will be hidden. If the value is equal to                        *\n *                  the last value passed in then cursor flashing will                         *\n *                  be maintained.                                                             *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1991 JLB : Created.                                                                 *\n *   11/17/1995 PWG : Created.                                                                 *\n *=============================================================================================*/\n//#pragma argsused\nvoid RadarClass::Radar_Cursor(int forced)\n{\n\tstatic \t\t\t\t\tint _last_pos = -1;\n\tstatic \t\t\t\t\tint _last_frame = -1;\n#ifdef WIN32\n\tGraphicViewPortClass \t* oldpage;\n#else\n\tGraphicBufferClass \t* oldpage;\n#endif\n\tint\t\t\t\t\t\tx1, y1, x2, y2;\n\n\t/*\n\t** figure out these function calls as we will need to call them multiple times.\n\t*/\n\tint\ttac_cell    = Coord_Cell(TacticalCoord);\n\tint\ttac_cell_x\t= Cell_X(tac_cell);\n\tint\ttac_cell_y\t= Cell_Y(tac_cell);\n\tint\tbarlen      = 6;\n\n\t/*\n\t** If the current tactical cell is invalid or we haven't moved and we are not forced to redraw then\n\t** just skip the redraw process.\n\t*/\n\tif (tac_cell != -1 && _last_pos == tac_cell && _last_frame == SpecialRadarFrame && !forced) return;\n\n\tif ( _last_pos != -1 ) {\n\t\t/*\n\t\t** The first thing we need to do is take care of erasing the last radar cell position.  We do this\n\t\t** by converting to pixel coordinates, then adjusting for the pixel coords for the current frame and\n\t\t** finally taking care of calling the erase procedure which will convert the pixel coordinates back\n\t\t** to the cells that need to be redraw.\n\t\t**/\n\t\tint last_cell_x\t= Cell_X(_last_pos);\n\t\tint last_cell_y\t= Cell_Y(_last_pos);\n\n\t\tCell_XY_To_Radar_Pixel(last_cell_x, last_cell_y, x1, y1);\n\t\tCell_XY_To_Radar_Pixel(last_cell_x + Lepton_To_Cell(TacLeptonWidth), last_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2);\n\t\tx2--;\n\t\ty2--;\n\n\t\t/*\n\t\t** Adjust the current coordinates based on the last animation frame.\n\t\t*/\n\t\tx1-= _last_frame;\n\t\ty1-= _last_frame;\n\t\tx2+= _last_frame;\n\t\ty2+= _last_frame;\n\n\t\t/*\n\t\t** Finally mark the map (actually remove the marks that indicate the radar cursor was there\n\t\t*/\n\t\tMark_Radar(x1, y1, x2, y2, FALSE, barlen);\n\t}\n\n\n\t/*\n\t** Find the upper left and lower right corners of the radar cursor.\n\t** Remember to adjust x2 and y2 back by one pixel as they will not be\n\t** pointing to the right value otherwise.  They point one cell ahead\n\t** of where they should.\n\t*/\n\tCell_XY_To_Radar_Pixel(tac_cell_x, tac_cell_y, x1, y1);\n\tCell_XY_To_Radar_Pixel(tac_cell_x + Lepton_To_Cell(TacLeptonWidth), tac_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2);\n\tx2--;\n\ty2--;\n\n\t/*\n\t** Adjust the coordinates based on the current frame of radar animation.\n\t*/\n\tx1-= SpecialRadarFrame;\n\ty1-= SpecialRadarFrame;\n\tx2+= SpecialRadarFrame;\n\ty2+= SpecialRadarFrame;\n\n\tMark_Radar(x1, y1, x2, y2, TRUE, barlen);\n\n\t/*\n\t** setup a graphic view port class so we can write all the pixels relative\n\t** to 0,0 rather than relative to full screen coordinates.\n\t*/\n\toldpage = Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + BaseX + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + BaseY + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadarWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadarHeight);\n\n\tdraw_window.Draw_Line(x1, \ty1,\tx1 + barlen,\ty1, \tLTGREEN);\n\tdraw_window.Draw_Line(x1,\ty1,\tx1,\ty1 + barlen,\tLTGREEN);\n\n\t// Draw upper right hand corner\n\tdraw_window.Draw_Line(x2 - barlen,\ty1,\tx2,\ty1, \tLTGREEN);\n\tdraw_window.Draw_Line(x2, \ty1, \tx2, \ty1 + barlen,\tLTGREEN);\n\n\t// Draw lower left hand corner\n\tdraw_window.Draw_Line(x1,\ty2 - barlen,\tx1,\ty2,\tLTGREEN);\n\tdraw_window.Draw_Line(x1,\ty2,\tx1 + barlen,\ty2, \tLTGREEN);\n\n\t// Draw lower right hand corner\n\tdraw_window.Draw_Line(x2,\ty2 - barlen,\tx2, \ty2, \tLTGREEN);\n\tdraw_window.Draw_Line(x2 - barlen, \ty2,\tx2,\ty2, \tLTGREEN);\n\n\tSet_Logic_Page(oldpage);\n\t_last_pos = tac_cell;\n\t_last_frame = SpecialRadarFrame;\n\tRadarCursorRedraw = FALSE;\n}\n\n\n/***************************************************************************\n * RadarClass::Radar_Anim -- Renders current frame of radar animation      *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/19/1995 PWG : Created.                                             *\n *=========================================================================*/\nvoid RadarClass::Radar_Anim(void)\n{\n\t/*\n\t** Do nothing if we're in player-name mode\n\t*/\n\tif (IsPlayerNames)\n\t\treturn;\n\n\tif (!Map.IsSidebarActive) return;\n\n#ifdef WIN32\n\tGraphicViewPortClass \t* oldpage= Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX + LogicPage->Get_XPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY + LogicPage->Get_YPos(),\n\t\t\t\t\t\t\t\t\t\t\t\tRadIWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIHeight);\n#else\n\tGraphicBufferClass \t* oldpage= Set_Logic_Page(HidPage);\n\tGraphicViewPortClass draw_window(LogicPage,\n\t\t\t\t\t\t\t\t\t\t\t\tRadX + RadOffX,\n\t\t\t\t\t\t\t\t\t\t\t\tRadY + RadOffY,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tRadIHeight-2);\n#endif\n//Mono_Set_Cursor(0,0);\n#ifdef WIN32\n\tDraw_Box(RadX+RadOffX-1, RadY+RadOffY-1, RadIWidth+2, RadIHeight+2, BOXSTYLE_RAISED, true);\n#endif\n\tdraw_window.Clear();\n\tCC_Draw_Shape(RadarAnim, RadarAnimFrame, RadX, RadY+1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\tFlag_To_Redraw(false);\n\tSet_Logic_Page(oldpage);\n}\n\n\n/***********************************************************************************************\n * RadarClass::AI -- Processes radar input (non-tactical).                                     *\n *                                                                                             *\n *    This routine intercepts any player input that concerns the radar map, but not those      *\n *    areas that represent the tactical map. These are handled by the tactical map AI          *\n *    processor. Primarily, this routine handles the little buttons that border the radar      *\n *    map.                                                                                     *\n *                                                                                             *\n * INPUT:   input -- The player input code.                                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinate parameters to use.                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/23/1994 JLB : Created.                                                                 *\n *   12/26/1994 JLB : Moves tactical map with click or drag.                                   *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nvoid RadarClass::AI(KeyNumType & input, int x, int y)\n{\n\t/*\n\t** Check to see if we need to animate the radar cursor\n\t*/\n\tif (IsRadarActive && Map.IsSidebarActive && SpecialRadarFrame) {\n\t\tSpecialRadarFrame--;\n\t\tRadarCursorRedraw = TRUE;\n\t\tIsToRedraw = TRUE;\n\t\tFlag_To_Redraw(FALSE);\n\t}\n\n\t/*\n\t** Check goes here to see if there is enough power to run the radar\n\t*/\n\tif (IsRadarActivating) {\n\t\tif (!DoesRadarExist) {\n\t\t\tRadarAnimFrame++;\n\t\t\tif (RadarAnimFrame < RADAR_ACTIVATED_FRAME) {\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t} else {\n\t\t\t\tDoesRadarExist = true;\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t} else {\n\t\t\tRadarAnimFrame--;\n\t\t\tif (RadarAnimFrame > RADAR_ACTIVATED_FRAME) {\n\t\t\t\tIsToRedraw = true;\n\t\t\t\tFlag_To_Redraw(false);\n\t\t\t} else {\n\t\t\t\tRadar_Activate(3);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Check goes here to see if there is enough power to run the radar\n\t*/\n\tif (IsRadarDeactivating) {\n\t\tRadarAnimFrame++;\n\t\tif (RadarAnimFrame == MAX_RADAR_FRAMES) {\n\t\t\tIsRadarDeactivating = false;\n\t\t} else {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\n\t/*\n\t** Check here to see if radar is being jammed, so we can update the\n\t** animation with snow.\n\t*/\n\tif (!IsRadarActivating && !IsRadarDeactivating) {\n\t\tRadarAnimFrame++;\n\t\tif (RadarAnimFrame < RADAR_ACTIVATED_FRAME) RadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\tif (RadarAnimFrame > (3 + RADAR_ACTIVATED_FRAME)) RadarAnimFrame = RADAR_ACTIVATED_FRAME;\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\n\t/*\n\t** Check here to see if the sonar pulse is active, and if it is, flag the\n\t** radar to redraw so the pulse ping will display.\n\t*/\n\tif (IsPulseActive) {\n\t\tFlag_To_Redraw(true);\n\t\tIsToRedraw = true;\n\t\tif (RadarPulseFrame >= 8) {\n\t\t\tRadarPulseFrame = 0;\n\t\t\tIsPulseActive = false;\n\t\t}\n\t}\n\n\tDisplayClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * RadarClass::RTacticalClass::Action -- I/O function for the radar map.                       *\n *                                                                                             *\n *    This is the main action function for handling player I/O on the radar map. It processes  *\n *    mouse clicks as well as mouse moves.                                                     *\n *                                                                                             *\n * INPUT:   flags -- The event flags that trigger this function call.                          *\n *                                                                                             *\n *          key   -- Reference the keyboard event that applies to the trigger event.           *\n *                                                                                             *\n * OUTPUT:  Should further processing of the input list be aborted?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RadarClass::RTacticalClass::Action(unsigned flags, KeyNumType & key)\n{\n\tCELL\t\t\tcell;\t\t\t\t\t\t\t// cell num click happened over\n\tint\t\t\tx,y;\t\t\t\t\t\t\t// Sub cell pixel coordinates.\n\tint\t\t\tcellx,celly;\t\t\t\t// Sub cell pixel coordinates.\n\tbool\t\t\tshadow;\t\t\t\t\t\t// is the cell in shadow or not\n\tObjectClass * object = 0;\t\t\t\t// what object is in the cell\n\tActionType \taction = ACTION_NONE;\t// Action possible with currently selected object.\n\n\t/*\n\t**\tForce any help label to disappear when the mouse is held over the\n\t**\tradar map.\n\t*/\n\tif (Map.IsSidebarActive) {\n\t\tMap.Help_Text(TXT_NONE);\n\t}\n\n\tif (!Map.IsRadarActive) {\n\t\tif (Map.IsSidebarActive) {\n\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n//\t\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\t/*\n\t** Disable processing if the player names are up\n\t*/\n\tif (Map.Is_Player_Names()) {\n\t\tGadgetClass::Action(0, key);\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tSet some working variables that depend on the mouse position. For the press\n\t**\tor release event, special mouse queuing storage variables are used. Other\n\t**\tevents must use the current mouse position globals.\n\t*/\n\tif (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) {\n\t\tx = Keyboard->MouseQX;\n\t\ty = Keyboard->MouseQY;\n\t} else {\n\t\tx = Get_Mouse_X();\n\t\ty = Get_Mouse_Y();\n\t}\n\n\t/*\n\t**\tSee if the mouse is over the radar general area, but not yet\n\t**\tover the active region of the radar map. In such a case, the\n\t**\tmouse is overridden to be the normal cursor and no other\n\t**\taction is performed.\n\t*/\n\tif (x < Map.RadX+Map.RadOffX || x >= Map.RadX+Map.RadIWidth || y < Map.RadY+Map.RadOffY || y >= Map.RadY+Map.RadIHeight) {\n\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\t\treturn(false);\n\t}\n\n\tint result = Map.RadarClass::Click_In_Radar(x, y, false);\n\n\tif (result == 1) {\n\t\tcell = Map.RadarClass::Click_Cell_Calc(x, y);\n\t\tif (cell != -1 && Map.In_Radar(cell)) {\n\t\t\tshadow\t= (!Map[cell].IsMapped && !Debug_Unshroud);\n//\t\t\tshadow\t= (!Map[cell].IsVisible && !Debug_Unshroud);\n\t\t\tcellx\t   = 12;\n\t\t\tcelly\t   = 12;\n\n\t\t\t/*\n\t\t\t**\tDetermine the object that the mouse is currently over.\n\t\t\t*/\n\t\t\tif (!shadow) {\n\t\t\t\tobject = Map.Cell_Object(cell, cellx, celly);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf there is a currently selected object, then the action to perform if\n\t\t\t**\tthe left mouse button were clicked must be determined.\n\t\t\t*/\n\t\t\tif (CurrentObject.Count()) {\n\t\t\t\tif (object) {\n\t\t\t\t\taction = CurrentObject[0]->What_Action(object);\n\t\t\t\t} else {\n\t\t\t\t\taction = CurrentObject[0]->What_Action(cell);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If this is not a valid radar map action then we are not going to do\n\t\t\t\t** anything.\n\t\t\t\t*/\n\t\t\t\tswitch (action) {\n\t\t\t\t\tcase ACTION_MOVE:\n\t\t\t\t\tcase ACTION_NOMOVE:\n\t\t\t\t\tcase ACTION_ATTACK:\n\t\t\t\t\tcase ACTION_ENTER:\n\t\t\t\t\tcase ACTION_CAPTURE:\n\t\t\t\t\tcase ACTION_SABOTAGE:\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\taction = ACTION_NONE;\n\t\t\t\t\t\tobject = NULL;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** On the radar map the only reason we would want the normal cursor to\n\t\t\t\t** appear is if we were over one of our own selected units.  Otherwise\n\t\t\t\t** we can't move there.\n\t\t\t\t**/\n\t\t\t\tif (action == ACTION_NONE) {\n\t\t\t\t\tif (object && object->Is_Selected_By_Player()) {\n\t\t\t\t\t\tobject = NULL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taction = ACTION_NOMOVE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA right mouse button press toggles the zoom mode.\n\t\t\t\t*/\n\t\t\t\tif (flags & RIGHTPRESS) {\n\t\t\t\t\tMap.Mouse_Right_Press();\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tWhen the mouse buttons aren't pressed, only the mouse cursor shape is processed.\n\t\t\t\t**\tThe shape changes depending on what object the mouse is currently over and what\n\t\t\t\t**\tobject is currently selected.\n\t\t\t\t*/\n\t\t\t\tif (flags & LEFTUP) {\n\t\t\t\t\tMap.Mouse_Left_Up(-1, shadow, object, action, true);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tNormal actions occur when the mouse button is released. The press event is\n\t\t\t\t**\tintercepted and possible rubber-band mode is flagged.\n\t\t\t\t*/\n\t\t\t\tif (flags & LEFTPRESS) {\n\t\t\t\t\tMap.Mouse_Left_Release(cell, cellx, celly, object, action, true);\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tMap.Set_Default_Mouse(MOUSE_RADAR_CURSOR, !Map.IsZoomed);\n\n\t\t\t\tif (flags & LEFTPRESS) {\n\n\t\t\t\t\tcell = Map.RadarClass::Click_Cell_Calc(x, y);\n\t\t\t\t\tif (cell != -1) {\n\t\t\t\t\t\tint cellx = Cell_X(cell);\n\t\t\t\t\t\tint celly = Cell_Y(cell);\n\t\t\t\t\t\tcellx -= Lepton_To_Cell(Map.TacLeptonWidth) / 2;\n\t\t\t\t\t\tcellx = max(cellx, Map.MapCellX);\n\t\t\t\t\t\tcelly -= Lepton_To_Cell(Map.TacLeptonHeight) / 2;\n\t\t\t\t\t\tcelly = max(celly, Map.MapCellY);\n\t\t\t\t\t\tcell = XY_Cell(cellx, celly);\n\t\t\t\t\t\tshadow = (!Map[cell].IsMapped && !Debug_Unshroud);\n//\t\t\t\t\t\tshadow = (!Map[cell].IsVisible && !Debug_Unshroud);\n\t\t\t\t\t\tMap.Set_Tactical_Position(Cell_Coord(cell));\n\t\t\t\t\t\tcell = Coord_Cell(Map.DesiredTacticalCoord);\n\t\t\t\t\t\tMap.DisplayClass::IsToRedraw = true;\n\t\t\t\t\t\tMap.Flag_To_Redraw(true);\n\t\t\t\t\t\tMap.SpecialRadarFrame = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tA right mouse button press toggles the zoom mode.\n\t\t\t\t*/\n\t\t\t\tif (flags & RIGHTPRESS) {\n\t\t\t\t\tMap.Zoom_Mode(cell);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (result == -1) {\n\t\tMap.Override_Mouse_Shape(MOUSE_NORMAL, true);\n\t}\n\tGadgetClass::Action(0, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed         *\n *                                                                                             *\n *    This routine intercepts the refresh cells request and if it detects that the sidebar     *\n *    should be rerendered, it flags the radar map to redraw during the next draw operation.   *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell that the refresh cell offset list is based upon.          *\n *                                                                                             *\n *          list  -- Pointer to the list of offsets from the origin cell that specifies the    *\n *                   cells to be flagged for redraw. If the list starts with the special       *\n *                   code to refresh the sidebar, then this routine recognizes it and flags    *\n *                   the radar map to be redrawn accordingly.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tDisplayClass::Refresh_Cells(cell, list);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell.  *\n *                                                                                             *\n *    This routine will try to center the radar map around the cell position specified.        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to try and position the radar map around.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Radar_Position(CELL cell)\n{\n#ifdef WIN32\n\tint oldx, oldy;\n\tint newx, newy;\n\tint newcell;\n\n\tif (ZoomFactor != 1) {\n\t\toldx = (Cell_X(cell) - MapCellX);\n\t\toldy = (Cell_Y(cell) - MapCellY);\n\t} else {\n\t\toldx = 0;\n\t\toldy = 0;\n\t}\n\n\tConfine_Rect(&oldx, &oldy, RadarCellWidth, RadarCellHeight, MapCellWidth, MapCellHeight);\n\n\tnewx \t\t= oldx + MapCellX;\n\tnewy \t\t= oldy + MapCellY;\n\tnewcell\t= XY_Cell(newx, newy);\n\n\tif (RadarCell != newcell) {\n   \tint forced = FALSE;\n\t\tint xmod = newx;\n\t\tint ymod = newy;\n\n\t\tint radx = (Cell_X(RadarCell)) - xmod;\n\t\tint rady = (Cell_Y(RadarCell)) - ymod;\n\n\t\tRadarX \t\t= newx;\n\t\tRadarY \t\t= newy;\n\t\tRadarCell \t= newcell;\n\n\t\tif (Map.IsSidebarActive && Map.IsRadarActive) {\n\t\t\tint radw = RadarCellWidth-ABS(radx);\t\t\t// Replicable width.\n\t\t\tint radh = RadarCellHeight-ABS(rady);\t\t// Replicable height.\n\n\t\t\tif (radw < 1) forced = true;\n\t\t\tif (radh < 1) forced = true;\n\n\t\t\tif (!forced && (radw != RadarWidth || radh != RadarHeight)) {\n\t\t\t\t/*\n\t\t\t\t** Blit the section that is actually overlapping.\n\t\t\t\t**\n\t\t\t\t** If the video card isnt able to blit overlapped regions then we have\n\t\t\t\t** to do the blit in two stages via an intermediate buffer. The test to allow\n\t\t\t\t** overlapped blits is done in the library at the time of setting the video mode.\n\t\t\t\t*/\n\t\t\t\tif (OverlappedVideoBlits || !HidPage.Get_IsDirectDraw()) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Overlapped blits are OK or we dont have a video memory hid page so blits are\n\t\t\t\t\t** always done in software by the library anyway.\n\t\t\t\t\t*/\n\t\t\t\t\tHidPage.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? 0 : radx) * ZoomFactor) + RadX+ RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\tradw * ZoomFactor,\n\t\t\t\t\t\t\t\t\tradh * ZoomFactor);\n\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t** Create a temporary intermediate surface\n\t\t\t\t\t*/\n\t\t\t\t\tGraphicBufferClass temp_surface;\n\t\t\t\t\ttemp_surface.Init((RadarWidth + 16) & 0xfffffff0,\n\t\t\t\t\t\t\t\t\t\t\t(RadarHeight + 16) & 0xfffffff0,\n\t\t\t\t\t\t\t\t\t\t\tNULL, 0, (GBC_Enum) GBC_VIDEOMEM);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Do the blit in 2 stages.\n\t\t\t\t\t*/\n\t\t\t\t\tHidPage.Blit(temp_surface,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tRadarWidth,\n\t\t\t\t\t\t\t\t\tRadarHeight);\n\n\t\t\t\t\ttemp_surface.Blit(HidPage,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t(((radx < 0) ? 0 : radx) * ZoomFactor) + RadX+ RadOffX + BaseX,\n\t\t\t\t\t\t\t\t\t(((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY,\n\t\t\t\t\t\t\t\t\tradw * ZoomFactor,\n\t\t\t\t\t\t\t\t\tradh * ZoomFactor);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Now we need to flag the section of the map that is going to redraw.\n\t\t\t\t*/\n\t\t\t\tif ( radx != 0 ) {\n\t\t\t\t\tint min;\n\t\t\t\t\tint max;\n\t\t\t\t\tif ( radx < 0 ) {  \t\t\t\t\t\t\t\t// this mean regen the right edge\n\t\t\t\t\t\tmin = radw;\n\t\t\t\t\t\tmax = radw+ABS(radx);\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t//\tthis mean regen the left edge\n\t\t\t\t\t\tmin = 0;\n\t\t\t\t\t\tmax = radx;\n\t\t\t\t\t}\n\t\t\t\t\tfor (int x = min; x < max; x++ ) {\n\t\t\t\t\t\tfor (int y = 0; y < (int)RadarCellHeight; y++ ) {\n\t\t\t\t\t\t\tRadar_Pixel(XY_Cell(newx + x, newy + y));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( newy != 0 ) {\n\t\t\t\t\tint min;\n\t\t\t\t\tint max;\n\t\t\t\t\tif ( rady < 0 ) {  \t\t\t\t\t\t\t\t// this mean regen the bottom edge\n\t\t\t\t\t\tmin = radh;\n\t\t\t\t\t\tmax = radh+ABS(rady);\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// this mean regen the top edge\n\t\t\t\t\t\tmin = 0;\n\t\t\t\t\t\tmax = rady;\n\t\t\t\t\t}\n\t\t\t\t\tfor (int y = min; y < max; y++ ) {\n\t\t\t\t\t\tfor ( int x = 0; x < (int)RadarCellWidth; x++ ) {\n\t\t\t\t\t\t\tRadar_Pixel(XY_Cell(newx + x, newy + y));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tRadarCursorRedraw = IsRadarActive;\n\t\tIsToRedraw \t= IsRadarActive;\n\t\tFlag_To_Redraw(false);\n\t\tif (ZoomFactor > 4) {\n\t\t\tFullRedraw = forced;\n\t\t}\n\t} else {\n\t\tRadarCursorRedraw = IsRadarActive;\n\t\tIsToRedraw \t= IsRadarActive;\n\t\tFlag_To_Redraw(false);\n\t}\n#else\n\n\tif (cell != RadarCell) {\n\t\tint oldx = RadarX;\n\t\tint oldy = RadarY;\n\t\tCELL oldcell = RadarCell;\n\t\tint x = Cell_X(cell);\n\t\tint y = Cell_Y(cell);\n\n\t\t/*\n\t\t**\tIf the new radar position is not too close to the edge of the\n\t\t**\tcurrent radar display, then don't bother to change the radar position.\n\t\t*/\n\t\tif ((unsigned)(x - (RadarX+10)) > RadarCellWidth-20) {\n\t\t\toldx = (Cell_X(cell)-MapCellX)-RadarCellWidth/2;\n\t\t} else {\n\t\t\toldx = Cell_X(RadarCell)-MapCellX;\n\t\t}\n\t\tif ((unsigned)(y - (RadarY+10)) > RadarCellHeight-20) {\n\t\t\toldy = (Cell_Y(cell)-MapCellY)-RadarCellHeight/2;\n\t\t} else {\n\t\t\toldy = Cell_Y(RadarCell)-MapCellY;\n\t\t}\n\n#ifdef NEVER\n\t\tif ((unsigned)(x - (RadarX+10)) > RadarWidth-20 || (unsigned)(y - (RadarY+10)) > RadarHeight-20) {\n\t\t\toldx = (Cell_X(cell)-MapCellX)-RadarCellWidth/2;\n\t\t\toldy = (Cell_Y(cell)-MapCellY)-RadarCellHeight/2;\n\t\t} else {\n\t\t\toldx = Cell_X(RadarCell)-MapCellX;\n\t\t\toldy = Cell_Y(RadarCell)-MapCellY;\n\t\t}\n#endif\n\n\t\tConfine_Rect(&oldx, &oldy, RadarCellWidth, RadarCellHeight, MapCellWidth, MapCellHeight);\n\t\tRadarX = oldx + MapCellX;\n\t\tRadarY = oldy + MapCellY;\n\t\tRadarCell = XY_Cell(RadarX, RadarY);\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t\tif (oldcell != RadarCell) {\n\t\t\tFullRedraw = IsRadarActive;\n\t\t}\n\t}\n#endif\n}\n\n\n/***********************************************************************************************\n * RadarClass::Radar_Position -- Returns with the current position of the radar map.           *\n *                                                                                             *\n *    This returns the cell number of the upper left corner of the radar map.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the radar map upper left corner cell position.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL RadarClass::Radar_Position(void)\n{\n\treturn(RadarCell);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions.                         *\n *                                                                                             *\n *    This routine is called when the tactical map changes its dimensions. This occurs when    *\n *    the tactical map moves and when the sidebar pops on or off.                              *\n *                                                                                             *\n * INPUT:   x,y   -- The cell coordinate of the upper left corner of the tactical map.         *\n *                                                                                             *\n *          w,y   -- The cell width and height of the tactical map.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Map_Dimensions(int x, int y, int w, int h)\n{\n\tSet_Radar_Position(XY_Cell(x, y));\n\tDisplayClass::Set_Map_Dimensions(x, y, w, h);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to  *\n *                                                                                             *\n *    This routine is called when the tactical map is to change position. The radar map might  *\n *    be adjusted as well by this routine.                                                     *\n *                                                                                             *\n * INPUT:   coord -- The new coordinate to use for the upper left corner of the tactical       *\n *                   map.                                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/17/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Set_Tactical_Position(COORDINATE coord)\n{\n\tDisplayClass::Set_Tactical_Position(coord);\n\tSet_Radar_Position(Coord_Cell(TacticalCoord));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar.            *\n *                                                                                             *\n *    This routine will examine the specified cell number and return whether it is visible     *\n *    on the radar map. This depends on the radar map position.                                *\n *                                                                                             *\n * INPUT:   cell  -- The cell number to check.                                                 *\n *                                                                                             *\n * OUTPUT:  Is the specified cell visible on the radar map currently?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/03/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Cell_On_Radar(CELL cell)\n{\n\tif ((unsigned)cell > MAP_CELL_TOTAL)\n\t\treturn(false);\n\n\tif (!IsZoomed) {\n\t\treturn(true);\n\t}\n\treturn(!(((Cell_X(cell) - RadarX) > RadarCellWidth) || ((Cell_Y(cell) - RadarY) > RadarCellHeight)));\n}\n\n\n/***********************************************************************************************\n * RadarClass::Player_Names -- toggles the Player-Names mode of the radar map                  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      on         true = turn on; false = turn off                                            *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Player_Names(bool on)\n{\n\tIsPlayerNames = on;\n\tIsToRedraw = true;\n\tif (on) {\n\t\tFlag_To_Redraw(true);\n//\t\tFlag_To_Redraw(false);\n\t} else {\n\t\tFlag_To_Redraw(true);\t\t// force drawing of the plate\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Spy_Next_House -- advances to the next house we're spying on, or returns NULL\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      0 = no house to spy on, 1 = found house to spy on                                      *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Spy_Next_House(void)\n{\n\tbool\ttospy = false;\n\tint spiedby = (1<<(PlayerPtr->Class->House));\n\n\tIsPlayerNames = false;\n\tIsToRedraw = true;\n\n\tHousesType maxhouse;\n\tHousesType firsthouse;\n\tHousesType house;\n\n\tif (Session.Type == GAME_NORMAL) {\n\t\tfirsthouse = HOUSE_SPAIN;\n\t\tmaxhouse = HOUSE_GOOD;\n\t} else {\n\t\tfirsthouse = HOUSE_MULTI1;\n\t\tmaxhouse = HOUSE_COUNT;\n\t}\n\n\tif (IsHouseSpy) {\n\t \thouse = (HousesType)(SpyingOn+1);\n\t} else {\n\t\thouse = firsthouse;\n\t}\n\n\tif (house < firsthouse) house = firsthouse;\n\n\twhile (house < maxhouse && !tospy) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr && hptr->IsActive && hptr != PlayerPtr) {\n\t\t\tif (hptr->RadarSpied & spiedby) {\n\t\t\t\ttospy = true;\n\t\t\t\tSpyingOn = house;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\thouse++;\n\t}\n\n\tIsHouseSpy = tospy;\n\n\tFlag_To_Redraw(true);\t\t// force drawing of the plate\n\treturn(tospy);\n}\n\n\n/***********************************************************************************************\n * Draw_House_Info -- Print house statistics on the radar map\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Draw_House_Info(void)\n{\n\tint y;\n\tchar txt[40];\n\t/*\n\t** Do nothing if the sidebar isn't there\n\t*/\n\tif (!Map.IsSidebarActive) {\n\t\treturn false;\n\t}\n\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY + 1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\ty = RadY + RadOffY + (2*RESFACTOR);\n\n\tMap.Repair.Draw_Me(true);\n\tMap.Upgrade.Draw_Me(true);\n\tMap.Zoom.Draw_Me(true);\n\n\tFancy_Text_Print (TXT_SPY_INFO, RadX + RadOffX + (6 * RESFACTOR), y,\n\t\t&ColorRemaps[PCOLOR_GREY], TBLACK,\n\t\tTPF_6PT_GRAD | TPF_NOSHADOW);\n\ty += 7*RESFACTOR;\n\n\tHouseClass * ptr = HouseClass::As_Pointer(SpyingOn);\n\tif (ptr && (ptr->RadarSpied & (1<<(PlayerPtr->Class->House))) ) {\n\t\tPlayerColorType c_idx;\n\t\tRemapControlType * color;\n\t\tTextPrintType style;\n\n\t\tc_idx = ptr->RemapColor;\n\t\tcolor = &ColorRemaps[c_idx];\n\t\tstyle = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW;\n\n\t\t/*\n\t\t** Print house's name below 'spy report'\n\t\t*/\n\t\ttxt[0] = 0;\n\t\tsprintf(txt, \"%s\", ptr->IniName);//Text_String(ptr->Class->FullName));\n//\t\tsprintf(txt, \"%s\", ptr->Name());//Text_String(ptr->Class->FullName));\n\t\tif (strlen(txt)) {\n\t\t\tif (strlen(txt) > 9) {\n\t\t\t\ttxt[9] = '.';\n\t\t\t\ttxt[10] = '\\0';\n\t\t\t}\n\t\t\tFancy_Text_Print (txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n\t\t} else {\n\t\t\tstrcpy(txt,\"________\");\n\t\t}\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_BUILDNGS, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n\n// count & print buildings\n\t\titoa(ptr->CurBuildings, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_UNITS, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print units\n\t\titoa(ptr->CurUnits, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + 6 * RESFACTOR, y, color, BLACK, style);\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_INFANTRY, RadX + RadOffX + (6 * RESFACTOR), y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print infantry\n\t\titoa(ptr->CurInfantry, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX + (6 * RESFACTOR), y, color, BLACK, style);\n#if(0)\n\t\ty += (6 * RESFACTOR) + 1;\n\n\t\tFancy_Text_Print(TXT_AIRCRAFT, RADAR_X + RADAR_OFF_X + 6, y,\n\t\t\t\t\t\t\t\t&ColorRemaps[PCOLOR_GREY], TBLACK,\n\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_NOSHADOW);\n\t\ty += (6 * RESFACTOR) + 1;\n// count & print aircraft\n\t\tfor (i = AIRCRAFT_NONE+1, count = 0; i < AIRCRAFT_COUNT; i++) {\n\t\t\tcount += ptr->AQuantity[i];\n\t\t}\n\t\titoa(count, txt, 10);\n\t\tFancy_Text_Print(txt, RadX + RadOffX, y,\n\t\t\t\tcolor, BLACK, style);\n#endif\n\t\treturn(true);\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * Draw_Names -- draws players' names on the radar map                                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/07/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid RadarClass::Draw_Names(void)\n{\n\tPlayerColorType c_idx;\n\tHousesType house;\n\tHouseClass * ptr;\n\tint y;\n\tchar txt[40];\n\tHousesType h;\n\tint kills;\n\tRemapControlType * color;\n\tTextPrintType style;\n\n\t/*\n\t** Do nothing if the sidebar isn't there\n\t*/\n\tif (!Map.IsSidebarActive) {\n\t\treturn;\n\t}\n\n//\tCC_Draw_Shape(RadarAnim, RADAR_ACTIVATED_FRAME, RADAR_X, RADAR_Y+1,\n//\t\tWINDOW_MAIN, SHAPE_NORMAL);\n\tCC_Draw_Shape(RadarFrame, 1, RadX, RadY + 1*RESFACTOR, WINDOW_MAIN, SHAPE_NORMAL);\n\n\ty = RadY + RadOffY+(2*RESFACTOR);\n\n\tFancy_Text_Print (TXT_NAME_COLON, RadX + RadOffX, y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);\n\tFancy_Text_Print (TXT_KILLS_COLON, RadX + RadOffX + RadIWidth - 2, y, &ColorRemaps[PCOLOR_GREY], TBLACK, TPF_RIGHT | TPF_6PT_GRAD | TPF_NOSHADOW);\n\ty += 6*RESFACTOR+1;\n\n\tLogicPage->Draw_Line(RadX + RadOffX, y, RadX + RadOffX + RadIWidth - 1, y, LTGREY);\n\ty += 2*RESFACTOR;\n\n\tfor (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\t\tptr = HouseClass::As_Pointer(house);\n\n\t\tif (!ptr) continue;\n\n\t\t/*\n\t\t**\tDecode this house's color\n\t\t*/\n\t\tc_idx = ptr->RemapColor;\n\n\t\tif (ptr->IsDefeated) {\n\t\t\tcolor = &GreyScheme;\n\t\t\tstyle = TPF_6PT_GRAD | TPF_NOSHADOW;\n\t\t} else {\n\t\t\tcolor = &ColorRemaps[c_idx];\n\t\t\tstyle = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW;\n\t\t}\n\n\t\t/*\n\t\t**\tInitialize our message\n\t\t*/\n\t\ttxt[0] = 0;\n//\t\tsprintf(txt, \"%s\", ptr->Name());\n\t\tsprintf(txt, \"%s\", ptr->IsHuman ? ptr->IniName : Text_String(TXT_COMPUTER));\n\n\t\tif (strlen(txt) == 0) {\n\t\t\tstrcpy(txt,\"________\");\n\t\t}\n\n\t\t/*\n\t\t**\tPrint the player name, and the # of kills\n\t\t*/\n#ifdef WIN32\n\t\tif (strlen(txt) > 9) {\n\t\t\ttxt[9] = '.';\n\t\t\ttxt[10] = '\\0';\n\t\t}\n#else\n\t\tif (strlen(txt) > 8) {\n\t\t\ttxt[8] = '.';\n\t\t\ttxt[9] = '\\0';\n\t\t}\n#endif\n\t\tFancy_Text_Print (txt, RadX + RadOffX, y, color, TBLACK, style);\n\n\t\tkills = 0;\n\t\tfor (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\t\tkills += ptr->UnitsKilled[h];\n\t\t\tkills += ptr->BuildingsKilled[h];\n\t\t}\n\t\tsprintf(txt, \"%2d\", kills);\n\t\tFancy_Text_Print (txt, RadX + RadOffX + RadIWidth - 2, y, color, TBLACK, style | TPF_RIGHT);\n\n\t\ty += 6*RESFACTOR+1;\n\n\t}\n\n\tMap.Repair.Draw_Me(true);\n\tMap.Upgrade.Draw_Me(true);\n\tMap.Zoom.Draw_Me(true);\n}\n\n\nvoid RadarClass::Activate_Pulse(void)\n{\n\tif (IsRadarActive || PlayerPtr->IsGPSActive) {\n\t\tIsPulseActive = true;\n\t\tRadarPulseFrame = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Radar_Active -- Determines if the radar map is currently being displayed.    *\n *                                                                                             *\n *    Determines if the radar map is currently being displayed.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar map currently being displayed as active?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Radar_Active(void)\n{\n\treturn(IsRadarActive || PlayerPtr->IsGPSActive);\n//\treturn IsRadarActive || PlayerPtr->IsGPSActive;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Radar_Activating -- Determines if the radar map is being activated.          *\n *                                                                                             *\n *    Determines if the radar map is being activated.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar map currently being activated?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/2019 SKY : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Radar_Activating(void)\n{\n\treturn IsRadarActivating;\n}\n\n\n/***********************************************************************************************\n * RadarClass::Is_Radar_Existing -- Queries to see if radar map is available.                  *\n *                                                                                             *\n *    This will determine if the radar map is available. If available, the radar will show     *\n *    representations of terrain, units, and buildings.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar map available to be displayed?                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Is_Radar_Existing(void)\n{\n\treturn(DoesRadarExist || PlayerPtr->IsGPSActive);\n}\n\n\n/***********************************************************************************************\n * RadarClass::Get_Jammed -- Fetch the current radar jammed state for the player.              *\n *                                                                                             *\n *    This will fetch the current state of the radar jamming for the player.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the radar currently jammed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadarClass::Get_Jammed(HousesType house) const\n{\n\tfor (int i = 0; i < Houses.Count(); ++i) {\n\t\tHouseClass* player = Houses.Ptr(i);\n\t\tif (player && player->Class->House == house) {\n\t\t\treturn Get_Jammed(player);\n\t\t}\n\t}\n\treturn false;\n}\n\nbool RadarClass::Get_Jammed(HouseClass *player) const\n{\n\tassert(player);\n\tif (player->IsGPSActive) return(false);\n\tint shift = (int)player->Class->House;\n\treturn (IsRadarJammedByPlayerMask & (1 << shift)) ? true : false;\n}\n\nvoid RadarClass::Set_Jammed(HousesType house, bool jam)\n{\n\tint shift = (int)house;\n\tif (jam) {\n\t\tIsRadarJammedByPlayerMask |= (1 << shift);\n\t}\n\telse {\n\t\tIsRadarJammedByPlayerMask &= ~(1 << shift);\n\t}\n}\n\nvoid RadarClass::Set_Jammed(HouseClass *player, bool jam)\n{\n\tif (player && player->Class) {\n\t\tSet_Jammed(player->Class->House, jam);\n\t}\n}\n\nvoid RadarClass::Flag_Cell(CELL cell)\n{\n//\tRadar_Pixel(cell);\n\tDisplayClass::Flag_Cell(cell);\n}"
  },
  {
    "path": "REDALERT/RADAR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RADAR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADAR.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RADAR_H\n#define RADAR_H\n\n#include\t\"display.h\"\n\nclass RadarClass: public DisplayClass\n{\n\tpublic:\n\t\tRadarClass(void);\n\t\tRadarClass(NoInitClass const & x) : DisplayClass(x) {};\n\n\t\t/*\n\t\t**\tThe dimensions and coordinates of the radar map.\n\t\t*/\n\t\tint RadX;\n\t\tint RadOffX;\n\t\tint RadY;\n\t\tint RadOffY;\n\t\tint RadWidth;\n\t\tint RadHeight;\n\t\tint RadIWidth;\n\t\tint RadIHeight;\n\t\tint RadPWidth;\n\t\tint RadPHeight;\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\n\t\tvirtual void Flag_Cell(CELL cell);\n\t\tvirtual bool Map_Cell(CELL cell, HouseClass *house, bool check_radar_spied = true, bool and_for_allies = true);\t\t// Added check_radar_spied parameter to prevent recursion. ST - 8/6/2019 10:16AM. Added and_for_allies ST - 10/31/2019 1:18PM\n\t\tvirtual bool Jam_Cell(CELL cell, HouseClass * house);\n\t\tvirtual bool UnJam_Cell(CELL cell, HouseClass * house);\n\t\tvirtual CELL Click_Cell_Calc(int x, int y) const;\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\t\tvirtual void Set_Map_Dimensions(int x, int y, int w, int h);\n\t\tvirtual void Set_Tactical_Position(COORDINATE coord);\n\t\tvoid\tZoom_Mode(CELL cell);\n\t\tint Click_In_Radar(int &x, int &y, bool change=false) const;\n\t\tvoid Cell_XY_To_Radar_Pixel(int cellx, int celly, int &x, int &y);\n\n\t\tbool Is_Zoomable(void) const;\n\t\tvoid Set_Radar_Position(CELL cell);\n\t\tCELL Radar_Position(void);\n\t\tbool Radar_Activate(int control);\n\t\tvoid Plot_Radar_Pixel(CELL cell);\n\t\tvoid Radar_Pixel(CELL cell);\n\t\tvoid Coord_To_Radar_Pixel(COORDINATE coord, int &x, int &y);\n\t\tvoid Cursor_Cell(CELL cell, int value);\n\t\tvoid RadarClass::Mark_Radar(int x1, int y1, int x2, int y2, int value, int barlen);\n\t\tvoid Radar_Cursor(int forced = false);\n\t\tvoid Render_Terrain(CELL cell, int x, int y, int size);\n\t\tbool Cell_On_Radar(CELL cell);\n\t\tvoid Render_Infantry(CELL cell, int x, int y, int size);\n\t\tvoid Render_Overlay(CELL cell, int x, int y, int size);\n\t\tvoid Radar_Anim(void);\n\t\tbool Is_Radar_Active(void);\n\t\tbool Is_Radar_Activating(void);\n\t\tbool Is_Radar_Existing(void);\n\n\t\t/*\n\t\t** Toggles player names on & off\n\t\t*/\n\t\tvoid Player_Names(bool on);\n\t\tint Is_Player_Names(void) {return IsPlayerNames;}\n\t\tbool Spying_On_House(void) {return IsHouseSpy;}\n\t\tvoid Draw_Names(void);\n\t\tbool Draw_House_Info(void);\n\t\tint Is_Zoomed(void) {return IsZoomed;}\n\t\tbool Get_Jammed(HousesType house) const;\n\t\tbool Get_Jammed(HouseClass *player) const;\n\t\tvoid Set_Jammed(HousesType house, bool jam);\n\t\tvoid Set_Jammed(HouseClass *player, bool jam);\n\t\tbool Spy_Next_House(void);\n\t\tvoid Activate_Pulse(void);\n\n\tprotected:\n\n\t\t/*\n\t\t**\tRadar map constant values.\n\t\t*/\n\t\tenum RadarClassEnums {\n\t\t\tRADAR_ACTIVATED_FRAME=22,\n\t\t\tMAX_RADAR_FRAMES = 41\n\t\t};\n\n\t\t/*\n\t\t**\tIf the radar map must be completely redrawn, then this flag will be true.\n\t\t**\tTypical causes of this would be when the radar first appears, or when the\n\t\t**\tscreen has been damaged.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\t\tunsigned RadarCursorRedraw:1;\n\n\t\t/*\n\t\t**\tIf the radar map is visible then this flag is true.\n\t\t*/\n\t\tunsigned DoesRadarExist:1;\n\t\tunsigned IsRadarActive:1;\n\t\tunsigned IsRadarActivating:1;\n\t\tunsigned IsRadarDeactivating:1;\n\n\t\t/*\n\t\t**\tPer-player radar jammed flag.\n\t\t*/\n\t\tunsigned int IsRadarJammedByPlayerMask;\n\n\t\t/*\n\t\t** Flag to tell whether sonar pulse should be displayed on radar map\n\t\t*/\n\t\tunsigned IsPulseActive:1;\n\t\tint\tRadarPulseFrame;\n\n\t\t/*\n\t\t** Special radar frame is set when a new location is selected on the\n\t\t** radar map.  It counts down through the special radar cursors until\n\t\t** either the radar cursor becomes normal or the radar cursor is moved\n\t\t** again.\n\t\t*/\n\t\tint SpecialRadarFrame;\n\t\tint RadarAnimFrame;\n\n\t\tstatic void const * RadarAnim;\n\t\tstatic void const * RadarPulse;\n\t\tstatic void const * RadarFrame;\n\n\t\t/*\n\t\t**\tThis gadget class is used for capturing input to the tactical map. All mouse input\n\t\t**\twill be routed through this gadget.\n\t\t*/\n\t\tclass RTacticalClass : public GadgetClass {\n\t\t\tpublic:\n\t\t\t\tRTacticalClass(void) : GadgetClass(0,0,0,0,LEFTPRESS|LEFTRELEASE|LEFTHELD|LEFTUP|RIGHTPRESS,true) {};\n\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\tfriend class RadarClass;\n\t\t};\n\t\tfriend class RTacticalClass;\n\n\t\t/*\n\t\t**\tThis is the \"button\" that tracks all input to the tactical map.\n\t\t** It must be available to derived classes, for Save/Load purposes.\n\t\t*/\n\t\tstatic RTacticalClass RadarButton;\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThe current radar position as the upper left corner cell for the\n\t\t**\tradar map display. The width and height is controlled by the\n\t\t**\tactual dimensions of the radar map display box (in pixels).\n\t\t*/\n\t\tunsigned RadarX;\n\t\tunsigned RadarY;\n\t\tunsigned RadarCellWidth;\n\t\tunsigned RadarCellHeight;\n\t\tunsigned RadarCell;\n\n\t\t/*\n\t\t**\tThis is the origin (pixel offsets) for the upper left corner\n\t\t**\tof the radar map within the full radar map area of the screen.\n\t\t**\tThis is biased so that the radar map, when smaller than full\n\t\t**\tsize will appear centered.\n\t\t*/\n\t\tunsigned BaseX;\n\t\tunsigned BaseY;\n\n\t\tunsigned RadarWidth;\n\t\tunsigned RadarHeight;\n\n\t\t/*\n\t\t**\tIf the radar map is in zoom mode, then this value will be true.\n\t\t*/\n\t\tunsigned IsZoomed:1;\n\n\t\t/*\n\t\t** This flag is true if the radar map is in its special show-the-player\n\t\t** names mode.\n\t\t*/\n\t\tunsigned IsPlayerNames:1;\n\n\t\t/*\n\t\t** This flag is true if the radar map is in its special show-the-units\n\t\t** of-another-house mode.\n\t\t*/\n\t\tunsigned IsHouseSpy:1;\n\n\t\t/*\n\t\t**\tThis is the zoom factor to use. This value is the number of pixels wide\n\t\t**\teach cell will occupy on the radar map. Completely zoomed out would be a\n\t\t**\tvalue of 1.\n\t\t*/\n\t\tint ZoomFactor;\n\n\t\t/*\n\t\t** If we're spying on a house's radar facility, this field shows the\n\t\t** name of the house we're spying on.\n\t\t*/\n\t\tHousesType SpyingOn;\n\n\t\t/*\n\t\t**\tThis is the list of radar pixels that need to be updated. Only a partial\n\t\t**\tlist is maintained for maximum speed.\n\t\t*/\n\t\tunsigned PixelPtr;\n\t\tenum PixelStackEnums {PIXELSTACK=400};\n\t\tCELL PixelStack[PIXELSTACK];\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/RADIO.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RADIO.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADIO.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : June 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RadioClass::Debug_Dump -- Displays the current status of the radio to the mono monitor.   *\n *   RadioClass::Limbo -- When limboing a unit will always break radio contact.                *\n *   RadioClass::Receive_Message -- Handles receipt of a radio message.                        *\n *   RadioClass::Transmit_Message -- Transmit message from one object to another.              *\n *   RadioClass::Transmit_Message -- Transmits a message to the object specified.              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/*\n**\tThese are the text representations of the radio messages that can be transmitted.\n*/\nchar const * RadioClass::Messages[RADIO_COUNT] = {\n\t\"static (no message)\",\n\t\"Roger.\",\n\t\"Come in.\",\n\t\"Over and out.\",\n\t\"Requesting transport.\",\n\t\"Attach to transport.\",\n\t\"I've got a delivery for you.\",\n\t\"I'm performing load/unload maneuver. Be careful.\",\n\t\"I'm clear.\",\n\t\"You are clear to unload. Driving away now.\",\n\t\"Am unable to comply.\",\n\t\"I'm starting construction now... act busy.\",\n\t\"I've finished construction. You are free.\",\n\t\"We bumped, redraw yourself please.\",\n\t\"I'm trying to load up now.\",\n\t\"May I become a passenger?\",\n\t\"Are you ready to receive shipment?\",\n\t\"Are you trying to become a passenger?\",\n\t\"Move to location X.\",\n\t\"Do you need to move?\",\n\t\"All right already. Now what?\",\n\t\"I'm a passenger now.\",\n\t\"Backup into refinery now.\",\n\t\"Run away!\",\n\t\"Tether established.\",\n\t\"Tether broken.\",\n\t\"Repair one step.\",\n\t\"Are you prepared to fight?\",\n\t\"Attack this target please.\",\n\t\"Reload one step.\",\n\t\"Circumstances prevent success.\",\n\t\"All done with the request.\",\n\t\"Do you need service depot work?\",\n\t\"Are you sitting on service depot?\"\n};\n\n\n#ifdef CHEAT_KEYS\n/***********************************************************************************************\n * RadioClass::Debug_Dump -- Displays the current status of the radio to the mono monitor.     *\n *                                                                                             *\n *    This displays the radio connection value to the monochrome monitor.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RadioClass::Debug_Dump(MonoClass * mono) const\n{\n\tassert(IsActive);\n\n\tmono->Set_Cursor(29, 7);mono->Printf(\"0-%-47s\", Messages[Old[0]]);\n\tmono->Set_Cursor(29, 8);mono->Printf(\"1-%-47s\", Messages[Old[1]]);\n\tmono->Set_Cursor(29, 9);mono->Printf(\"2-%-47s\", Messages[Old[2]]);\n\tif (Radio) {\n\t\tmono->Set_Cursor(20, 7);mono->Printf(\"%08X\", Radio->As_Target());\n\t}\n\tMissionClass::Debug_Dump(mono);\n}\n#endif\n\n\n/***********************************************************************************************\n * RadioClass::Receive_Message -- Handles receipt of a radio message.                          *\n *                                                                                             *\n *    This is the base version of what should happen when a radio message is received. It      *\n *    turns the radio off when the \"OVER_OUT\" message is received. All other messages are      *\n *    merely acknowledged with a \"ROGER\".                                                      *\n *                                                                                             *\n * INPUT:   from     -- The object that is initiating this radio message (always valid).       *\n *                                                                                             *\n *          message  -- The radio message received.                                            *\n *                                                                                             *\n *          param    -- Reference to optional value that might be used to return more          *\n *                      information than can be conveyed in the simple radio response          *\n *                      messages.                                                              *\n *                                                                                             *\n * OUTPUT:  Returns with the response radio message.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   09/24/1994 JLB : Streamlined to be only a communications carrier.                         *\n *   05/22/1995 JLB : Recognized who is sending the message                                    *\n *   06/05/1996 JLB : Radio message history tracking.                                          *\n *=============================================================================================*/\nRadioMessageType RadioClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)\n{\n\tassert(IsActive);\n\n\t/*\n\t**\tKeep a record of the last message received by this radio.\n\t*/\n\tif (message != Old[0]) {\n\t\tOld[2] = Old[1];\n\t\tOld[1] = Old[0];\n\t\tOld[0] = message;\n\t}\n\n\t/*\n\t**\tWhen this message is received, it means that the other object\n\t**\thas already turned its radio off. Turn this radio off as well.\n\t**\tThis only applies if the message is coming from the object that\n\t**\thas an established conversation with this object.\n\t*/\n\tif (from == Radio && message == RADIO_OVER_OUT) {\n\t\tMissionClass::Receive_Message(from, message, param);\n\t\tRadio_Off();\n\t\treturn(RADIO_ROGER);\n\t}\n\n\t/*\n\t**\tThe \"hello\" message is an attempt to establish contact. If this radio\n\t**\tis already in an established conversation with another object, then\n\t**\treturn with \"negative\". If all is well, return with \"roger\".\n\t*/\n\tif (message == RADIO_HELLO && Strength) {\n\t\tif (Radio == from || Radio == NULL) {\n\t\t\tRadio = from;\n\t\t\treturn(RADIO_ROGER);\n\t\t}\n\t\treturn(RADIO_NEGATIVE);\n\t}\n\n\treturn(MissionClass::Receive_Message(from, message, param));\n}\n\n\n/***********************************************************************************************\n * RadioClass::Transmit_Message -- Transmit message from one object to another.                *\n *                                                                                             *\n *    This routine is used to transmit a radio message from this object to another. Most       *\n *    inter object coordination is handled through this mechanism.                             *\n *                                                                                             *\n * INPUT:   to       -- Pointer to the object that will receive the radio message.             *\n *                                                                                             *\n *          message  -- The message itself (see RadioType).                                    *\n *                                                                                             *\n *          param    -- Optional reference to parameter that might be used to pass or          *\n *                      receive additional information.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the response radio message from the receiving object.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType RadioClass::Transmit_Message(RadioMessageType message, long & param, RadioClass * to)\n{\n\tassert(IsActive);\n\n\tif (to == NULL) {\n\t\tto = Contact_With_Whom();\n\t}\n\n\t/*\n\t**\tIf there is no target for the radio message, then always return static.\n\t*/\n\tif (to == NULL) return(RADIO_STATIC);\n\n\t/*\n\t**\tHandle some special case processing that occurs when certain messages\n\t**\tare transmitted.\n\t*/\n\tif (to == Radio && message == RADIO_OVER_OUT) {\n\t\tRadio = 0;\n\t}\n\n\t/*\n\t**\tIf this object is not in radio contact but the message\n\t**\tindicates that radio contact should be established, then\n\t**\ttry to do so. If the other party agrees then contact\n\t**\tis established.\n\t*/\n\tif (message == RADIO_HELLO) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t\tif (to->Receive_Message(this, message, param) == RADIO_ROGER) {\n\t\t\tRadio = to;\n\t\t\treturn(RADIO_ROGER);\n\t\t}\n\t\treturn(RADIO_NEGATIVE);\n\t}\n\n\treturn(to->Receive_Message(this, message, param));\n}\n\n\n/***********************************************************************************************\n * RadioClass::Limbo -- When limboing a unit will always break radio contact.                  *\n *                                                                                             *\n *    This routine will break radio contact as the object is entering limbo state.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the object successfully limboed?                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RadioClass::Limbo(void)\n{\n\tassert(IsActive);\n\n\tif (!IsInLimbo) {\n\t\tTransmit_Message(RADIO_OVER_OUT);\n\t}\n\treturn(MissionClass::Limbo());\n}\n\n\n/***********************************************************************************************\n * RadioClass::Transmit_Message -- Transmits a message to the object specified.                *\n *                                                                                             *\n *    This routine will transmit the specified message to the object. This routine differs     *\n *    from the normal Transmit_Message in that the LParam value is \"faked\" into the            *\n *    parameter list. It is presumed that the message sent with this function does not         *\n *    require the LParam.                                                                      *\n *                                                                                             *\n * INPUT:   message  -- The message to transmit.                                               *\n *                                                                                             *\n *          to       -- The requested receiver of this message.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the radio response from the receiver.                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nRadioMessageType RadioClass::Transmit_Message(RadioMessageType message, RadioClass * to)\n{\n\tassert(IsActive);\n\n\treturn(Transmit_Message(message, LParam, to));\n}\n"
  },
  {
    "path": "REDALERT/RADIO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RADIO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RADIO.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 23, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 23, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RADIO_H\n#define RADIO_H\n\n#include\t\"mission.h\"\n\nclass ObjectClass;\nclass TechnoClass;\n\n\n/****************************************************************************\n**\tRadio contact is controlled by this class. It handles the mundane chore\n**\tof keeping the radio contact alive as well as broadcasting messages\n**\tto the receiving radio. Radio contact is primarily used when one object\n**\tis in \"command\" of another.\n*/\nclass RadioClass : public MissionClass {\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is a record of the last message received by this receiver.\n\t\t*/\n\t\tRadioMessageType Old[3];\n\n\t\t/*\n\t\t**\tThis is the object that radio communication has been established\n\t\t**\twith. Although is is only a one-way reference, it is required that\n\t\t**\tthe receiving radio is also tuned to the object that contains this\n\t\t**\tradio set.\n\t\t*/\n\t\tRadioClass * Radio;\n\n\t\t/*\n\t\t**\tThis is a text representation of all the possible radio messages. This\n\t\t**\ttext is used for monochrome debug printing.\n\t\t*/\n\t\tstatic char const * Messages[RADIO_COUNT];\n\n\tpublic:\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tConstructors, Destructors, and overloaded operators.\n\t\t*/\n\t\tRadioClass(RTTIType rtti, int id) : MissionClass(rtti, id), Radio(0) {};\n\t\tRadioClass(NoInitClass const & x) : MissionClass(x) {};\n\t\tvirtual ~RadioClass(void) {Radio=0;};\n\n\t\t/*---------------------------------------------------------------------\n\t\t**\tMember function prototypes.\n\t\t*/\n\t\tbool In_Radio_Contact(void) const {return (Radio != 0);};\n\t\tvoid Radio_Off(void) {Radio = 0;};\n\t\tTechnoClass * Contact_With_Whom(void) const {return (TechnoClass *)Radio;};\n\n\t\t// Inherited from base class(es).\n\t\tvirtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);\n\t\tvirtual RadioMessageType Transmit_Message(RadioMessageType message, long & param=LParam, RadioClass * to=NULL);\n\t\tvirtual RadioMessageType Transmit_Message(RadioMessageType message, RadioClass * to);\n\t\t#ifdef CHEAT_KEYS\n\t\tvirtual void Debug_Dump(MonoClass *mono) const;\n\t\t#endif\n\t\tvirtual bool Limbo(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvirtual void Code_Pointers(void);\n\t\tvirtual void Decode_Pointers(void);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/RAMFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RAMFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAMFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RAMFileClass::Close -- This will 'close' the ram file.                                    *\n *   RAMFileClass::Create -- Effectively clears the buffer of data.                            *\n *   RAMFileClass::Delete -- Effectively clears the buffer of data.                            *\n *   RAMFileClass::Is_Available -- Determines if the \"file\" is available.                      *\n *   RAMFileClass::Is_Open -- Is the file open?                                                *\n *   RAMFileClass::Open -- Opens a RAM based file for read or write.                           *\n *   RAMFileClass::Open -- Opens the RAM based file.                                           *\n *   RAMFileClass::RAMFileClass -- Construct a RAM buffer based \"file\" object.                 *\n *   RAMFileClass::Read -- Read data from the file.                                            *\n *   RAMFileClass::Seek -- Controls the ram file virtual read position.                        *\n *   RAMFileClass::Size -- Returns with the size of the ram file.                              *\n *   RAMFileClass::Write -- Copies data to the ram file.                                       *\n *   RAMFileClass::~RAMFileClass -- Destructor for the RAM file class.                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"FUNCTION.H\"\n#include \"ramfile.h\"\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * RAMFileClass::RAMFileClass -- Construct a RAM buffer based \"file\" object.                   *\n *                                                                                             *\n *    This routine will construct a \"file\" object that actually is just a front end processor  *\n *    for a buffer. Access to the buffer will appear as if it was accessing a file. This       *\n *    is different from the caching ability of the buffered file class in that this file       *\n *    class has no real file counterpart. Typical use of this is for algorithms that were      *\n *    originally designed for file processing, but are now desired to work with a buffer.      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to use for this file. The buffer will already    *\n *                      contain data if the file is opened for READ. It will be considered     *\n *                      a scratch buffer if opened for WRITE. If the buffer pointer is NULL    *\n *                      but the length parameter is not, then a buffer will be allocated       *\n *                      of the specified length. This case is only useful for opening the      *\n *                      file for WRITE.                                                        *\n *                                                                                             *\n *          length   -- The length of the buffer submitted to this routine.                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRAMFileClass::RAMFileClass(void * buffer, int len) :\n\tBuffer((char *)buffer),\n\tMaxLength(len),\n\tLength(len),\n\tOffset(0),\n\tAccess(READ),\n\tIsOpen(false),\n\tIsAllocated(false)\n{\n\tif (buffer == NULL && len > 0) {\n\t\tBuffer = new char[len];\n\t\tIsAllocated = true;\n\t}\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class.                           *\n *                                                                                             *\n *    The destructor will deallocate any buffer that it allocated. Otherwise it does nothing.  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRAMFileClass::~RAMFileClass(void)\n{\n\tClose();\n\tif (IsAllocated) {\n\t\tdelete [] Buffer;\n\t\tBuffer = NULL;\n\t\tIsAllocated = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Create -- Effectively clears the buffer of data.                              *\n *                                                                                             *\n *    This routine \"clears\" the buffer of data. It only makes the buffer appear empty by       *\n *    resetting the internal length to zero.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the file reset in this fashion?                                                *\n *                                                                                             *\n * WARNINGS:   If the file was open, then resetting by this routine is not allowed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Create(void)\n{\n\tif (!Is_Open()) {\n\t\tLength = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Delete -- Effectively clears the buffer of data.                              *\n *                                                                                             *\n *    This routine \"clears\" the buffer of data. It only makes the buffer appear empty by       *\n *    resetting the internal length to zero.                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the file reset in this fashion?                                                *\n *                                                                                             *\n * WARNINGS:   If the file was open, then resetting by this routine is not allowed.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Delete(void)\n{\n\tif (!Is_Open()) {\n\t\tLength = 0;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Is_Available -- Determines if the \"file\" is available.                        *\n *                                                                                             *\n *    RAM files are always available.                                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  TRUE                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Is_Available(int )\n{\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Is_Open -- Is the file open?                                                  *\n *                                                                                             *\n *    This answers the question whether the file is open or not.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Is_Open(void) const\n{\n\treturn(IsOpen);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Open -- Opens a RAM based file for read or write.                             *\n *                                                                                             *\n *    This routine will open the ram file. The name is meaningless so that parameter is        *\n *    ignored. If the access mode is for write, then the pseudo-file can be written until the  *\n *    buffer is full. If the file is opened for read, then the buffer is presumed to be full   *\n *    of the data to be read.                                                                  *\n *                                                                                             *\n * INPUT:   name  -- ignored.                                                                  *\n *                                                                                             *\n *          access-- The access method to use for the data buffer -- either READ or WRITE.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the open successful?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Open(char const * , int access)\n{\n\treturn(Open(access));\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Open -- Opens the RAM based file.                                             *\n *                                                                                             *\n *    This will open the ram based file for read or write. If the file is opened for write,    *\n *    the the 'file' can be written up to the limit of the buffer's size. If the file is       *\n *    opened for read, then the buffer is presumed to hold the data to be read.                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RAMFileClass::Open(int access)\n{\n\tif (Buffer == NULL || Is_Open()) {\n\t\treturn(false);\n\t}\n\n\tOffset = 0;\n\tAccess = access;\n\tIsOpen = true;\n\n\tswitch (access) {\n\t\tdefault:\n\t\tcase READ:\n\t\t\tbreak;\n\n\t\tcase WRITE:\n\t\t\tLength = 0;\n\t\t\tbreak;\n\n\t\tcase READ|WRITE:\n\t\t\tbreak;\n\t}\n\n\treturn(Is_Open());\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Read -- Read data from the file.                                              *\n *                                                                                             *\n *    Use this routine just like a normal file read. It will copy the bytes from the ram       *\n *    buffer to the destination specified. When the ram buffer is exhausted, less bytes than   *\n *    requested will be read.                                                                  *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to store the data to.                            *\n *                                                                                             *\n *          size     -- The number of bytes to 'read' into the specified buffer.               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied to the destination buffer. If the number   *\n *          of bytes returned is less than requested, then this indicates that the source      *\n *          buffer is exhausted.                                                               *\n *                                                                                             *\n * WARNINGS:   The read function only applies to ram 'files' opened for read access.           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Read(void * buffer, long size)\n{\n\tif (Buffer == NULL || buffer == NULL || size == 0) {\n\t\treturn(0);\n\t}\n\n\tbool hasopened = false;\n\tif (!Is_Open()) {\n\t\tOpen(READ);\n\t\thasopened = true;\n\t} else {\n\t\tif ((Access & READ) == 0) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tint tocopy = (size < (Length-Offset)) ? size : (Length-Offset);\n\tmemmove(buffer, &Buffer[Offset], tocopy);\n\tOffset += tocopy;\n\n\tif (hasopened) {\n\t\tClose();\n\t}\n\n\treturn(tocopy);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Seek -- Controls the ram file virtual read position.                          *\n *                                                                                             *\n *    This routine will move the read/write position of the ram file to the location specified *\n *    by the offset and direction parameters. It functions similarly to the regular file       *\n *    seek method.                                                                             *\n *                                                                                             *\n * INPUT:   pos   -- The signed offset from the home position specified by the \"dir\"           *\n *                   parameter.                                                                *\n *                                                                                             *\n *          dir   -- The home position to base the position offset on. This will either be     *\n *                   the start of the file, the end of the file, or the current read/write     *\n *                   position.                                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with the new file position.                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Seek(long pos, int dir)\n{\n\tif (Buffer == NULL || !Is_Open()) {\n\t\treturn(Offset);\n\t}\n\n\tint maxoffset = Length;\n\tif ((Access & WRITE) != 0) {\n\t\tmaxoffset = MaxLength;\n\t}\n\n\tswitch (dir) {\n\t\tcase SEEK_CUR:\n\t\t\tOffset += pos;\n\t\t\tbreak;\n\n\t\tcase SEEK_SET:\n\t\t\tOffset = 0 + pos;\n\t\t\tbreak;\n\n\t\tcase SEEK_END:\n\t\t\tOffset = maxoffset + pos;\n\t\t\tbreak;\n\t}\n\n\tif (Offset < 0) Offset = 0;\n\tif (Offset > maxoffset) Offset = maxoffset;\n\n\tif (Offset > Length) {\n\t\tLength = Offset;\n\t}\n\n\treturn(Offset);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Size -- Returns with the size of the ram file.                                *\n *                                                                                             *\n *    This will return the size of the 'real' data in the ram file. The real data is either    *\n *    the entire buffer, if opened for READ, or just the written data if opened for WRITE.     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes that the ram file system considers to be valid    *\n *          data of the 'file'.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Size(void)\n{\n\treturn(Length);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Write -- Copies data to the ram file.                                         *\n *                                                                                             *\n *    This function similarly to the regular write operation supported for files. It copies    *\n *    the data specified to the current write position in the ram file.                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the data to be written.                                     *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes written. This will be less than requested  *\n *          if the buffer is exhausted of space prematurely.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RAMFileClass::Write(void const * buffer, long size)\n{\n\tif (Buffer == NULL || buffer == NULL || size == 0) {\n\t\treturn(0);\n\t}\n\n\tbool hasopened = false;\n\tif (!Is_Open()) {\n\t\tOpen(WRITE);\n\t\thasopened = true;\n\t} else {\n\t\tif ((Access & WRITE) == 0) {\n\t\t\treturn(0);\n\t\t}\n\t}\n\n\tint maxwrite = MaxLength - Offset;\n\tint towrite = (size < maxwrite) ? size : maxwrite;\n\tmemmove(&Buffer[Offset], buffer, towrite);\n\tOffset += towrite;\n\n\tif (Offset > Length) {\n\t\tLength = Offset;\n\t}\n\n\tif (hasopened) {\n\t\tClose();\n\t}\n\n\treturn(towrite);\n}\n\n\n/***********************************************************************************************\n * RAMFileClass::Close -- This will 'close' the ram file.                                      *\n *                                                                                             *\n *    Closing a ram file actually does nothing but record that it is now closed.               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RAMFileClass::Close(void)\n{\n\tIsOpen = false;\n}\n"
  },
  {
    "path": "REDALERT/RAMFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RAMFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAMFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RAMFILE_H\n#define RAMFILE_H\n\n\n#include\t\"wwfile.h\"\n\n\nclass RAMFileClass : public FileClass\n{\n\tpublic:\n\t\tRAMFileClass(void * buffer, int len);\n\t\tvirtual ~RAMFileClass(void);\n\n\t\tvirtual char const * File_Name(void) const {return(\"UNKNOWN\");}\n\t\tvirtual char const * Set_Name(char const * ) {return(File_Name());}\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const * filename, int access=READ);\n\t\tvirtual int Open(int access=READ);\n\t\tvirtual long Read(void * buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const * buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void) {return(0);}\n\t\tvirtual bool Set_Date_Time(unsigned long ) {return(true);}\n\t\tvirtual void Error(int , int = false, char const * =NULL) {}\n\n\t\toperator char const * () {return File_Name();}\n\n\tprivate:\n\n\t\t/*\n\t\t**\tPointer to the buffer that the \"file\" will reside in.\n\t\t*/\n\t\tchar * Buffer;\n\n\t\t/*\n\t\t**\tThe maximum size of the buffer. The file occupying the buffer\n\t\t**\tmay be smaller than this size.\n\t\t*/\n\t\tint MaxLength;\n\n\t\t/*\n\t\t**\tThe number of bytes in the sub-file occupying the buffer.\n\t\t*/\n\t\tint Length;\n\n\t\t/*\n\t\t**\tThe current file position offset within the buffer.\n\t\t*/\n\t\tint Offset;\n\n\t\t/*\n\t\t**\tThe file was opened with this access mode.\n\t\t*/\n\t\tint Access;\n\n\t\t/*\n\t\t**\tIs the file currently open?\n\t\t*/\n\t\tbool IsOpen;\n\n\t\t/*\n\t\t**\tWas the file buffer allocated during construction of this object?\n\t\t*/\n\t\tbool IsAllocated;\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/RAND.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c0\\vcs\\code\\rand.cpv   4.35   04 Jul 1996 16:14:56   JOE_BOSTIC  $ */\n/*************************************************************************** \n *                                                                         * \n *                 Project Name : Command & Conquer                        * \n *                                                                         * \n *                    File Name : RAND.CPP                                 * \n *                                                                         * \n *                   Programmer : Bill R. Randolph                         * \n *                                                                         * \n *                   Start Date : 04/25/95                                 * \n *                                                                         * \n *                  Last Update : June 17, 1995 [JLB]                      * \n *                                                                         * \n *-------------------------------------------------------------------------* \n * Functions:                                                              * \n *   Sim_IRandom -- Returns minval to maxval, inclusive                    *\n *   Sim_Random -- Returns 0 - 255                                         * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include \"COORDA.h\"\nint SimRandIndex = 0;\n\n/*************************************************************************** \n * Sim_Random -- Returns 0 - 255                                           * \n *                                                                         * \n * INPUT:                                                                  * \n *      none.                                                              *\n *                                                                         * \n * OUTPUT:                                                                 * \n *      0 - 255, at random                                                 *\n *                                                                         * \n * WARNINGS:                                                               * \n *      none.                                                              *\n *                                                                         * \n * HISTORY:                                                                * \n *   04/25/1995 BRR : Created.                                             * \n *   06/17/1995 JLB : Takes advantage of character math wrap.              * \n *=========================================================================*/\nint Sim_Random(void)\n{\n\tstatic unsigned char _randvals[] = {\n\t\t0x47, 0xce, 0xc6, 0x6e, 0xd7, 0x9f, 0x98, 0x29, 0x92, 0x0c, 0x74, 0xa2, \n\t\t0x65, 0x20, 0x4b, 0x4f, 0x1e, 0xed, 0x3a, 0xdf, 0xa5, 0x7d, 0xb5, 0xc8,\n\t\t0x86, 0x01, 0x81, 0xca, 0xf1, 0x17, 0xd6, 0x23, 0xe1, 0xbd, 0x0e, 0xe4, \n\t\t0x62, 0xfa, 0xd9, 0x5c, 0x68, 0xf5, 0x7f, 0xdc, 0xe7, 0xb9, 0xc4, 0xb3,\n\t\t0x7a, 0xd8, 0x06, 0x3e, 0xeb, 0x09, 0x1a, 0x31, 0x3f, 0x46, 0x28, 0x12, \n\t\t0xf0, 0x10, 0x84, 0x76, 0x3b, 0xc5, 0x53, 0x18, 0x14, 0x73, 0x7e, 0x59,\n\t\t0x48, 0x93, 0xaa, 0x1d, 0x5d, 0x79, 0x24, 0x61, 0x1b, 0xfd, 0x2b, 0xa8, \n\t\t0xc2, 0xdb, 0xe8, 0x2a, 0xb0, 0x25, 0x95, 0xab, 0x96, 0x83, 0xfc, 0x5f,\n\t\t0x9c, 0x32, 0x78, 0x9a, 0x9e, 0xe2, 0x8e, 0x35, 0x4c, 0x41, 0xa1, 0x69, \n\t\t0x5a, 0xfe, 0xa7, 0xa4, 0xf6, 0x6d, 0xc1, 0x58, 0x0a, 0xcf, 0xea, 0xc3,\n\t\t0xba, 0x85, 0x99, 0x8d, 0x36, 0xb6, 0xdd, 0xd3, 0x04, 0xe6, 0x45, 0x0d,\n\t\t0x60, 0xae, 0xa3, 0x22, 0x4d, 0xe9, 0xc9, 0x9b, 0xb7, 0x0f, 0x02, 0x42,\n\t\t0xf9, 0x0b, 0x8f, 0x43, 0x44, 0x87, 0x70, 0xbe, 0xe3, 0xf8, 0xee, 0xa9, \n\t\t0xbc, 0xc0, 0x67, 0x33, 0x16, 0x37, 0x57, 0xad, 0x5e, 0x9d, 0x64, 0x40,\n\t\t0x54, 0x05, 0x2c, 0xe0, 0xb2, 0x97, 0x08, 0xaf, 0x75, 0x8a, 0x5b, 0xfb,\n\t\t0x4e, 0xbf, 0x91, 0xf3, 0xcb, 0x7c, 0x63, 0xef, 0x89, 0x52, 0x6c, 0x2f,\n\t\t0x21, 0x4a, 0xf7, 0xcd, 0x2e, 0xf4, 0xc7, 0x6f, 0x19, 0xb1, 0x66, 0xcc,\n\t\t0x90, 0x8c, 0x50, 0x51, 0x26, 0x7b, 0xda, 0x49, 0x80, 0x30, 0x55, 0x1f, \n\t\t0xd2, 0xb4, 0xd1, 0xd5, 0x6b, 0xf2, 0x72, 0xbb, 0x13, 0x3d, 0xff, 0x15,\n\t\t0x38, 0xe5, 0xd4, 0xde, 0x2d, 0x27, 0x94, 0xa0, 0xd0, 0x39, 0x82, 0x8b,\n\t\t0x03, 0xac, 0x3c, 0x34, 0x77, 0xb8, 0xec, 0x00, 0x07, 0x1c, 0x88, 0xa6,\n\t\t0x56, 0x11, 0x71, 0x6a,\n\t};\n\n\t((unsigned char&)SimRandIndex)++;\n//\tSimRandIndex &= 0xff;\n\treturn(_randvals[SimRandIndex]);\n}\n\n\n/*************************************************************************** \n * Sim_IRandom -- returns minval to maxval, inclusive                      *\n *                                                                         * \n * INPUT:                                                                  * \n *      minval,maxval      range limits                                    *\n *                                                                         * \n * OUTPUT:                                                                 * \n *      random value                                                       *\n *                                                                         * \n * WARNINGS:                                                               * \n *      none.                                                              *\n *                                                                         * \n * HISTORY:                                                                * \n *   04/25/1995 BRR : Created.                                             * \n *   06/17/1995 JLB : Uses fixed point math helper routine.                * \n *=========================================================================*/\nint Sim_IRandom(int minval, int maxval)\n{\n\treturn(Fixed_To_Cardinal((maxval-minval), Sim_Random()) + minval);\n}\n\n\n/*\n**\tThis routine can be used to create the _RandVals[] table.  It will be \n**\tdifferent every time it's run.\n*/\n#if 0\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include <conio.h>\n\nvoid main(void);\n\nvoid main(void)\n{\n\tint i;\n\tFILE *fp;\n\tint r;\n\tchar is_used[256];\n\tchar rand_val[256];\n\n\tsrand ( time ( NULL ) ) ;\n\n\tfor (i = 0; i < 256; i++) {\n\t\tis_used[i] = 0;\n\t}\n\n\t/*\n\t** Store the digits 0 to 255 in a random order within the 'rand_val' array\n\t** This ensures our random number sequence represents every value.\n\t*/\n\tfor (i = 0; i < 256; i++) {\n\t\tif (kbhit()!=0) {\n\t\t\tprintf(\"ABORTED!\\n\");\n\t\t\tbreak;\n\t\t}\n\t\tr = (rand() * 256) / RAND_MAX;\t\t// r is the index into array\n\t\tif (is_used[r]==0) {\n\t\t\tis_used[r] = 1;\n\t\t\trand_val[r] = i;\n\t\t} else {\n\t\t\ti--;\n\t\t}\n\t}\n\n\tfp = fopen(\"rand.cpp\",\"wt\");\n\tif (fp==NULL) {\n\t\tprintf(\"File error\\n\");\n\t\texit(0);\n\t}\n\n\tfprintf(fp, \"unsigned char _RandVals[] = {\\n\");\n\tfor (i = 0; i < 256; i++) {\n\t\tfprintf(fp,\"0x%02x,\\n\",rand_val[i]);\n\t}\n\tfprintf(fp,\"};\\n\");\n\tfclose(fp);\n\n}\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/RANDOM.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RANDOM.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RAND.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/28/96                                                     *\n *                                                                                             *\n *                  Last Update : February 28, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RandomClass::RandomClass -- Constructor for the random number class.                      *\n *   RandomClass::operator() -- Fetches the next random number in the sequence.                *\n *   RandomClass::operator() -- Ranged random number generator.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"random.h\"\n#ifdef RANDOM_COUNT\n#include <stdio.h>\nextern long Frame;\n#endif\n\n/***********************************************************************************************\n * RandomClass::RandomClass -- Constructor for the random number class.                        *\n *                                                                                             *\n *    This constructor can take an integer as a parameter. This allows the class to be         *\n *    constructed by assigning an integer to an existing object. The compiler creates a        *\n *    temporary with the constructor and then performs a copy constructor operation.           *\n *                                                                                             *\n * INPUT:   seed  -- The optional starting seed value to use.                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomClass::RandomClass(unsigned seed) :\n\tSeed(seed)\n{\n#ifdef RANDOM_COUNT\n\tCount1 = 0;\n\tCount2 = 0;\n#endif\n}\n\n\n/***********************************************************************************************\n * RandomClass::operator() -- Fetches the next random number in the sequence.                  *\n *                                                                                             *\n *    This routine will fetch the next random number in the sequence.                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the next random number.                                               *\n *                                                                                             *\n * WARNINGS:   This routine modifies the seed value so that subsequent calls will not return   *\n *             the same value. Take note that this routine only returns 15 bits of             *\n *             random number.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomClass::operator ()(void)\n{\n#ifdef RANDOM_COUNT\n\tCount1++;\n\tprintf(\"Frame %d: Random Count1:%d Count2:%d (%x)\\n\",Frame,Count1,Count2,Seed);\n#endif\n\n\t/*\n\t**\tTransform the seed value into the next number in the sequence.\n\t*/\n\tSeed = (Seed * MULT_CONSTANT) + ADD_CONSTANT;\n\n\t/*\n\t**\tExtract the 'random' bits from the seed and return that value as the\n\t**\trandom number result.\n\t*/\n\treturn((Seed >> THROW_AWAY_BITS) & (~((~0) << SIGNIFICANT_BITS)));\n}\n\n\n/***********************************************************************************************\n * RandomClass::operator() -- Ranged random number generator.                                  *\n *                                                                                             *\n *    This function will return with a random number within the range specified. This replaces *\n *    the functionality of IRandom() in the old library.                                       *\n *                                                                                             *\n * INPUT:   minval   -- The minimum value to return from the function.                         *\n *                                                                                             *\n *          maxval   -- The maximum value to return from the function.                         *\n *                                                                                             *\n * OUTPUT:  Returns with a random number that falls between the minval and maxval (inclusive). *\n *                                                                                             *\n * WARNINGS:   The range specified must fall within the maximum bit significance of the        *\n *             random number algorithm (15 bits), otherwise the value returned will be         *\n *             decidedly non-random.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/27/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomClass::operator() (int minval, int maxval)\n{\n#ifdef RANDOM_COUNT\n\tCount2++;\n\tprintf(\"Frame %d: Random Count1:%d Count2:%d (%x)\\n\",Frame,Count1,Count2,Seed);\n#endif\n\n\t/*\n\t**\tTest for shortcut case where the range is null and thus\n\t**\tthe number to return is actually implicit from the\n\t**\tparameters.\n\t*/\n\tif (minval == maxval) return(minval);\n\n\t/*\n\t**\tEnsure that the min and max range values are in proper order.\n\t*/\n\tif (minval > maxval) {\n\t\tint temp = minval;\n\t\tminval = maxval;\n\t\tmaxval = temp;\n\t}\n\n\t/*\n\t**\tFind the highest bit that fits within the magnitude of the\n\t**\trange of random numbers desired. Notice that the scan is\n\t**\tlimited to the range of significant bits returned by the\n\t**\trandom number algorithm.\n\t*/\n\tint magnitude = maxval - minval;\n\tint highbit = SIGNIFICANT_BITS-1;\n\twhile ((magnitude & (1 << highbit)) == 0 && highbit > 0) {\n\t\thighbit--;\n\t}\n\n\t/*\n\t**\tCreate a full bit mask pattern that has all bits set that just\n\t**\tbarely covers the magnitude of the number range desired.\n\t*/\n\tint mask = ~( (~0L) << (highbit+1) );\n\n\t/*\n\t**\tKeep picking random numbers until it fits within the magnitude desired.\n\t*/\n\tint pick = magnitude+1;\n\twhile (pick > magnitude) {\n\t\tpick = operator()() & mask;\n\t}\n\n\t/*\n\t**\tFinally, bias the random number pick to the start of the range\n\t**\trequested.\n\t*/\n\treturn(pick + minval);\n}\n\n"
  },
  {
    "path": "REDALERT/RANDOM.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RANDOM.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RANDOM.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/27/96                                                     *\n *                                                                                             *\n *                  Last Update : February 27, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RANDOM_H\n#define RANDOM_H\n\n/**********************************************************************\n** Enable this define to turn on the random # counters.  This must not\n** be defined for the release version, or saved games won't work!\n*/\n//#define RANDOM_COUNT\n\n\n/*\n**\tThis class functions like a 'magic' int value that returns a random number\n**\tevery time it is read. To set the \"random seed\" for this, just assign a number\n**\tto the object (just as you would if it were a true 'int' value). Take note that although\n**\tthis class will return an 'int', the actual significance of the random number is\n**\tlimited to 15 bits (0..32767).\n*/\nclass RandomClass {\n\tpublic:\n\t\tRandomClass(unsigned seed=0);\n\n\t\toperator int(void) {return(operator()());};\n\t\tint operator() (void);\n\t\tint operator() (int minval, int maxval);\n\n\t\tenum {\n\t\t\tSIGNIFICANT_BITS=15\t\t\t\t// Random number bit significance.\n\t\t};\n\n\t\tunsigned long Seed;\n\n#ifdef RANDOM_COUNT\n\t\tunsigned long Count1;\n\t\tunsigned long Count2;\n#endif\n\n\tprotected:\n\t\t/*\n\t\t**\tInternal working constants that are used to generate the next\n\t\t**\trandom number.\n\t\t*/\n\t\tenum {\n\t\t\tMULT_CONSTANT=0x41C64E6D,\t\t// K multiplier value.\n\t\t\tADD_CONSTANT=0x00003039,\t\t// K additive value.\n\t\t\tTHROW_AWAY_BITS=10\t\t\t\t// Low bits to throw away.\n\t\t};\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/RAWFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RAWFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 4, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::Bias -- Bias a file with a specific starting position and length.           *\n *   RawFileClass::Close -- Perform a closure of the file.                                     *\n *   RawFileClass::Create -- Creates an empty file.                                            *\n *   RawFileClass::Delete -- Deletes the file object from the disk.                            *\n *   RawFileClass::Error -- Handles displaying a file error message.                           *\n *   RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.         *\n *   RawFileClass::Is_Available -- Checks to see if the specified file is available to open.   *\n *   RawFileClass::Open -- Assigns name and opens file in one operation.                       *\n *   RawFileClass::Open -- Opens the file object with the rights specified.                    *\n *   RawFileClass::RawFileClass -- Simple constructor for a file object.                       *\n *   RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                            *\n *   RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.           *\n *   RawFileClass::Seek -- Reposition the file pointer as indicated.                           *\n *   RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.         *\n *   RawFileClass::Set_Name -- Manually sets the name for a file object.                       *\n *   RawFileClass::Size -- Determines size of file (in bytes).                                 *\n *   RawFileClass::Write -- Writes the specified data to the buffer specified.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<direct.h>\n#include\t<share.h>\n#include\t<stddef.h>\n\n#include\t\"rawfile.h\"\n\n#ifndef WIN32\n#include\t<fcntl.h>\n#include\t<io.h>\n#include\t<dos.h>\nextern short Hard_Error_Occured;\n#endif\n\n\n/***********************************************************************************************\n * RawFileClass::Error -- Handles displaying a file error message.                             *\n *                                                                                             *\n *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *\n *    will return from this function. Otherwise, it will exit the program with \"exit()\".       *\n *                                                                                             *\n * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *\n *                                                                                             *\n *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *\n *                      false, then the program WILL exit in this routine.                     *\n *                                                                                             *\n *          filename -- Optional filename to report with this error. If no filename is         *\n *                      supplied, then no filename is listed in the error message.             *\n *                                                                                             *\n * OUTPUT:  none, but this routine might not return at all if the \"canretry\" parameter is      *\n *          false or the player pressed ESC.                                                   *\n *                                                                                             *\n * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *\n *             if in a graphic mode.                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Error(int , int , char const * )\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Simple constructor for a file object.                         *\n *                                                                                             *\n *    This constructor is called when a file object is created with a supplied filename, but   *\n *    not opened at the same time. In this case, an assumption is made that the supplied       *\n *    filename is a constant string. A duplicate of the filename string is not created since   *\n *    it would be wasteful in that case.                                                       *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nRawFileClass::RawFileClass(char const * filename) :\n\tRights(0),\n\tBiasStart(0),\n\tBiasLength(-1),\n\tHandle(NULL_HANDLE),\n\tFilename(filename),\n\tDate(0),\n\tTime(0),\n\tAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Name -- Manually sets the name for a file object.                         *\n *                                                                                             *\n *    This routine will set the name for the file object to the name specified. This name is   *\n *    duplicated in free store. This allows the supplied name to be a temporarily constructed  *\n *    text string. Setting the name in this fashion doesn't affect the closed or opened state  *\n *    of the file.                                                                             *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the allocated copy of this filename. This pointer is     *\n *          guaranteed to remain valid for the duration of this file object or until the name  *\n *          is changed -- whichever is sooner.                                                 *\n *                                                                                             *\n * WARNINGS:   Because of the allocation this routine must perform, memory could become        *\n *             fragmented.                                                                     *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nchar const * RawFileClass::Set_Name(char const * filename)\n{\n\tif (Filename != NULL && Allocated) {\n\t\tfree((char *)Filename);\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n\n\tif (filename == NULL) return(NULL);\n\n\tBias(0);\n\n\t((char *&)Filename) = strdup(filename);\n\tif (Filename == NULL) {\n\t\tError(ENOMEM, false, filename);\n\t}\n\tAllocated = true;\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Assigns name and opens file in one operation.                         *\n *                                                                                             *\n *    This routine will assign the specified filename to the file object and open it at the    *\n *    same time. If the file object was already open, then it will be closed first. If the     *\n *    file object was previously assigned a filename, then it will be replaced with the new    *\n *    name. Typically, this routine is used when an anonymous file object has been crated and  *\n *    now it needs to be assigned a name and opened.                                           *\n *                                                                                             *\n * INPUT:   filename -- The filename to assign to this file object.                            *\n *                                                                                             *\n *          rights   -- The open file access rights to use.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *\n *          is designed to never return unless it succeeded.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(char const * filename, int rights)\n{\n\tSet_Name(filename);\n\treturn(Open(rights));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Open -- Opens the file object with the rights specified.                      *\n *                                                                                             *\n *    This routine is used to open the specified file object with the access rights indicated. *\n *    This only works if the file has already been assigned a filename. It is guaranteed, by   *\n *    the error handler, that this routine will always return with success.                    *\n *                                                                                             *\n * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *\n *                      combination of READ and/or WRITE bit flags.                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *\n *          the error handler.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Open(int rights)\n{\n\tClose();\n\n\t/*\n\t**\tVerify that there is a filename associated with this file object. If not, then this is a\n\t**\tbig error condition.\n\t*/\n\tif (Filename == NULL) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRecord the access rights used for this open call. These rights will be used if the\n\t**\tfile object is duplicated.\n\t*/\n\tRights = rights;\n\n\t/*\n\t**\tRepetitively try to open the file. Abort if a fatal error condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tTry to open the file according to the access rights specified.\n\t\t*/\n\t\t#ifndef WIN32\n\t\t\tHard_Error_Occured = 0;\n\t\t#endif\n\t\tswitch (rights) {\n\n\t\t\t/*\n\t\t\t**\tIf the access rights are not recognized, then report this as\n\t\t\t**\tan invalid access code.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\terrno = EINVAL;\n\t\t\t\tbreak;\n\n\t\t\tcase READ:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\tcase WRITE:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_creat(Filename, 0, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\n\t\t\tcase READ|WRITE:\n\t\t\t\t#ifdef WIN32\n\t\t\t\t\tHandle = CreateFile(Filename, GENERIC_READ | GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\t\t\t#else\n\t\t\t\t\t_dos_open(Filename, O_RDWR|O_CREAT|SH_DENYWR, &Handle);\n\t\t\t\t#endif\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tBiased files must be positioned past the bias start position.\n\t\t*/\n\t\tif (BiasStart != 0 || BiasLength != -1) {\n\t\t\tSeek(0, SEEK_SET);\n\t\t}\n\n\t\t/*\n\t\t**\tIf the handle indicates the file is not open, then this is an error condition.\n\t\t**\tFor the case of the file cannot be found, then allow a retry. All other cases\n\t\t**\tare fatal.\n\t\t*/\n\t\tif (Handle == NULL_HANDLE) {\n\n#ifdef WIN32\n//\t\t\treturn(false);\n\t\t\tError(GetLastError(), false, Filename);\n//\t\t\tcontinue;\n#else\n\t\t\t/*\n\t\t\t**\tIf this flag is set, then some hard error occurred. Just assume that the error\n\t\t\t**\tis probably a removed CD-ROM and allow a retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t} else {\n\t\t\t\tif (errno == ENOENT) {\n\t\t\t\t\tError(ENOENT, true, Filename);\n\t\t\t\t} else {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n#endif\n\t\t}\n\t\tbreak;\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Available -- Checks to see if the specified file is available to open.     *\n *                                                                                             *\n *    This routine will examine the disk system to see if the specified file can be opened     *\n *    or not. Use this routine before opening a file in order to make sure that is available   *\n *    or to perform other necessary actions.                                                   *\n *                                                                                             *\n * INPUT:   force -- Should this routine keep retrying until the file becomes available? If    *\n *                   in this case it doesn't become available, then the program will abort.    *\n *                                                                                             *\n * OUTPUT:  bool; Is the file available to be opened?                                          *\n *                                                                                             *\n * WARNINGS:   Depending on the parameter passed in, this routine may never return.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Is_Available(int forced)\n{\n#ifndef WIN32\n\tbool open_failed;\n#endif\n\n\tif (Filename == NULL) return(false);\n\n\t/*\n\t**\tIf the file is already open, then is must have already passed the availability check.\n\t**\tReturn true in this case.\n\t*/\n\tif (Is_Open()) return(true);\n\n\t/*\n\t**\tIf this is a forced check, then go through the normal open channels, since those\n\t**\tchannels ensure that the file must exist.\n\t*/\n\tif (forced) {\n\t\tRawFileClass::Open(READ);\n\t\tRawFileClass::Close();\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a raw open of the file. If this open fails for ANY REASON, including a missing\n\t**\tCD-ROM, this routine will return a failure condition. In all but the missing file\n\t**\tcondition, go through the normal error recover channels.\n\t*/\n\tfor (;;) {\n\n#ifdef WIN32\n\t\tHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\t\t\tNULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\t\tif (Handle == NULL_HANDLE) {\n\t\t\treturn(false);\n\t\t}\n\t\tbreak;\n#else\n\n\t\tHard_Error_Occured = 0;\n\t\topen_failed = _dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);\n\n\t\t/*\n\t\t**\tIf DOS reports that everything is just fine except that the file is not present,\n\t\t**\tthen return with this fact. Any other case will fall through to the error handler\n\t\t**\troutine.\n\t\t*/\n\t\tif (open_failed && errno == ENOENT) return(false);\n\n\t\t/*\n\t\t** If we got an access error it could be because there is no cd in\n\t\t** the drive.  Call the error handler but allow a continue if it\n\t\t** returns.\n\t\t*/\n\t\tif (open_failed && errno == EACCES) {\n\t\t\tError(errno, true, Filename);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tIf the file could not be found, then return with this information. If a more\n\t\t**\tserious error occurred, then display the error message and abort.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tif (open_failed) {\n\t\t\t\t/*\n\t\t\t\t**\tAn unhandled error condition is fatal. Display the error message and then\n\t\t\t\t**\tabort.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\t\t}\n\t\tif (!open_failed) break;\n#endif\n\t}\n\n\t/*\n\t**\tSince the file could be opened, then close it and return that the file exists.\n\t*/\n#ifdef WIN32\n\tif (!CloseHandle(Handle)) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n#else\n\tif (_dos_close(Handle)) {\n\t\tError(errno, false, Filename);\n\t}\n#endif\n\tHandle = NULL_HANDLE;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Close -- Perform a closure of the file.                                       *\n *                                                                                             *\n *    Close the file object. In the rare case of an error, handle it as appropriate.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Some rare error conditions may cause this routine to abort the program.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Close(void)\n{\n\t/*\n\t**\tIf the file is open, then close it. If the file is already closed, then just return. This\n\t**\tisn't considered an error condition.\n\t*/\n\tif (Is_Open()) {\n\n#ifdef WIN32\n\t\t/*\n\t\t**\tTry to close the file. If there was an error (who knows what that could be), then\n\t\t**\tcall the error routine.\n\t\t*/\n\t\tif (!CloseHandle(Handle)) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t}\n#else\n\t\tfor (;;) {\n\t\t\t/*\n\t\t\t**\tClose the file. If there was an error in the close operation -- abort.\n\t\t\t*/\n\t\t\tHard_Error_Occured = 0;\n\t\t\tif (_dos_close(Handle)) {\n\n\t\t\t\t/*\n\t\t\t\t**\tBy definition, this error can only be a bad file handle. This a fatal condition\n\t\t\t\t**\tof course, so abort with an error message.\n\t\t\t\t*/\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIn the condition (if it is even possible) of a hard error occurring, then\n\t\t\t**\tassume it is the case of missing media. Display an error message and try\n\t\t\t**\tagain if indicated.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n#endif\n\n\t\t/*\n\t\t**\tAt this point the file must have been closed. Mark the file as empty and return.\n\t\t*/\n\t\tHandle = NULL_HANDLE;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.             *\n *                                                                                             *\n *    This routine will read the specified number of bytes and place the data into the buffer  *\n *    indicated. It is legal to call this routine with a request for more bytes than are in    *\n *    the file. This condition can result in fewer bytes being read than requested. Determine  *\n *    this by examining the return value.                                                      *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the buffer to read data into. If NULL is passed, no read    *\n *                      is performed.                                                          *\n *                                                                                             *\n *          size     -- The number of bytes to read. If NULL is passed, then no read is        *\n *                      performed.                                                             *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes read into the buffer. If this number is less      *\n *          than requested, it indicates that the file has been exhausted.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Read(void * buffer, long size)\n{\n\tlong\tbytesread = 0;\t\t\t// Running count of the number of bytes read into the buffer.\n\tint\topened = false;\t\t// Was the file opened by this routine?\n\n\t/*\n\t**\tIf the file isn't opened, open it. This serves as a convenience\n\t**\tfor the programmer.\n\t*/\n\tif (!Is_Open()) {\n\n\t\t/*\n\t\t**\tThe error check here is moot. Open will never return unless it succeeded.\n\t\t*/\n\t\tif (!Open(READ)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n\t/*\n\t**\tA biased file has the requested read length limited to the bias length of\n\t**\tthe file.\n\t*/\n\tif (BiasLength != -1) {\n\t\tint remainder = BiasLength - Seek(0);\n\t\tsize = size < remainder ? size : remainder;\n\t}\n\n#ifdef WIN32\n\tlong total = 0;\n\twhile (size > 0) {\n\t\tbytesread = 0;\n\n\t\tSetErrorMode(SEM_FAILCRITICALERRORS);\n\t\tif (!ReadFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {\n\t\t\tsize -= bytesread;\n\t\t\ttotal += bytesread;\n\t\t\tError(GetLastError(), true, Filename);\n\t\t\tSetErrorMode(0);\n\t\t\tcontinue;\n\t\t}\n\t\tSetErrorMode(0);\n\t\tsize -= bytesread;\n\t\ttotal += bytesread;\n\t\tif (bytesread == 0) break;\n\t}\n\tbytesread = total;\n\n#else\n\n\tint\treadresult;\n\n\t/*\n\t**\tRead the file in convenient chunk sizes. When the actual number\n\t**\tof bytes read does not match the desired, then assume that the file\n\t**\tis exhausted and bail. This loop was adjusted to take into\n\t**\tconsideration the fact that \"read\" returns a SIGNED value whereas\n\t**\tit takes an UNSIGNED value as the byte count.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be read this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes read.\n\n\t\t/*\n\t\t**\tBreak the read request into chunks no bigger than the low level DOS read\n\t\t**\tcan handle.\n\t\t*/\n\t\tdesired = size < 32000L ? size : 32000L;\n\n\t\tHard_Error_Occured = 0;\n\t\treadresult = _dos_read(Handle, buffer, desired, &actual);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of the CD-ROM or\n\t\t**\tfloppy media having been removed. Display the error and retry as directed.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned from the read operation, then this indicates\n\t\t\t**\teither a bad file number or invalid access. These are fatal conditions, so\n\t\t\t**\tdisplay the error and then abort.\n\t\t\t*/\n\t\t\tif (readresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tNo error occurred during the read. Adjust the pointers and size counters and\n\t\t\t\t**\tloop again if more data is needed to be read.\n\t\t\t\t*/\n\t\t\t\tbuffer = (char *)buffer + actual;\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\t\t\t\tif (actual != desired) break;\t\t// No more data?\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tClose the file if it was opened by this routine and return\n\t**\tthe actual number of bytes read into the buffer.\n\t*/\n\tif (opened) Close();\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Write -- Writes the specified data to the buffer specified.                   *\n *                                                                                             *\n *    This routine will write the data specified to the file.                                  *\n *                                                                                             *\n * INPUT:   buffer   -- The buffer that holds the data to write.                               *\n *                                                                                             *\n *          size     -- The number of bytes to write to the file.                              *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes written to the file. This routine catches the     *\n *          case of a disk full condition, so this routine will always return with the number  *\n *          matching the size request.                                                         *\n *                                                                                             *\n * WARNINGS:   A fatal file condition could cause this routine to never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Write(void const * buffer, long size)\n{\n\tlong\tbytesread = 0;\n\tint\topened = false;\t\t// Was the file manually opened?\n\n\t/*\n\t**\tCheck to open status of the file. If the file is open, then merely write to\n\t**\tit. Otherwise, open the file for writing and then close the file when the\n\t**\toutput is finished.\n\t*/\n\tif (!Is_Open()) {\n\t\tif (!Open(WRITE)) {\n\t\t\treturn(0);\n\t\t}\n\t\topened = true;\n\t}\n\n#ifdef WIN32\n\tif (!WriteFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n\n#else\n\n\tint\twriteresult;\n\t/*\n\t**\tWrite the data to the file in chunks no bigger than what the low level DOS write\n\t**\tcan handle.\n\t*/\n\twhile (size) {\n\t\tunsigned\tdesired;\t\t// Bytes desired to be write this pass.\n\t\tunsigned actual;\t\t// Actual number of bytes written.\n\n\t\tHard_Error_Occured = 0;\n//\t\tdesired = (unsigned)MIN(size, Transfer_Block_Size());\n\t\tdesired = size;\n\t\twriteresult = _dos_write(Handle, buffer, desired, &actual);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume it is the case of the media being\n\t\t**\tremoved. Print the error message an retry as directed.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\t\t\t// Not technically needed, but to be consistent...\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf negative one is returned by the DOS read, then this indicates a bad file\n\t\t\t**\thandle or invalid access. Either condition is fatal -- display error condition\n\t\t\t**\tand abort.\n\t\t\t*/\n\t\t\tif (writeresult != 0) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tA successful write occurred. Update pointers and byte counter as appropriate.\n\t\t\t\t*/\n\t\t\t\tbuffer = (char *)buffer + actual;\n\t\t\t\tbytesread += actual;\n\t\t\t\tsize -= actual;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the actual bytes written is less than requested, assume this is a case of\n\t\t\t\t**\tthe disk being full. Consider this a fatal error condition.\n\t\t\t\t*/\n\t\t\t\tif (actual != desired) {\n\t\t\t\t\tError(ENOSPC, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\t//WIN32\n\n\t/*\n\t**\tFixup the bias length if necessary.\n\t*/\n\tif (BiasLength != -1) {\n\t\tif (Raw_Seek(0) > BiasStart+BiasLength) {\n\t\t\tBiasLength = Raw_Seek(0) - BiasStart;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf this routine had to open the file, then close it before returning.\n\t*/\n\tif (opened) {\n\t\tClose();\n\t}\n\n\t/*\n\t**\tReturn with the number of bytes written. This will always be the number of bytes\n\t**\trequested, since the case of the disk being full is caught by this routine.\n\t*/\n\treturn(bytesread);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Seek -- Reposition the file pointer as indicated.                             *\n *                                                                                             *\n *    Use this routine to move the filepointer to the position indicated. It can move either   *\n *    relative to current position or absolute from the beginning or ending of the file. This  *\n *    routine will only return if it successfully performed the seek.                          *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek to. This is interpreted as relative to the position  *\n *                   indicated by the \"dir\" parameter.                                         *\n *                                                                                             *\n *          dir   -- The relative position to relate the seek to. This can be either SEEK_SET  *\n *                   for the beginning of the file, SEEK_CUR for the current position, or      *\n *                   SEEK_END for the end of the file.                                         *\n *                                                                                             *\n * OUTPUT:  This routine returns the position that the seek ended up at.                       *\n *                                                                                             *\n * WARNINGS:   If there was a file error, then this routine might never return.                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Seek(long pos, int dir)\n{\n\n\t/*\n\t**\tA file that is biased will have a seek operation modified so that the file appears to\n\t**\texist only within the bias range. All bytes outside of this range appear to be\n\t**\tnon-existant.\n\t*/\n\tif (BiasLength != -1) {\n\t\tswitch (dir) {\n\t\t\tcase SEEK_SET:\n\t\t\t\tif (pos > BiasLength) {\n\t\t\t\t\tpos = BiasLength;\n\t\t\t\t}\n\t\t\t\tpos += BiasStart;\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_CUR:\n\t\t\t\tbreak;\n\n\t\t\tcase SEEK_END:\n\t\t\t\tdir = SEEK_SET;\n\t\t\t\tpos += BiasStart + BiasLength;\n//\t\t\t\tpos = (pos <= BiasStart+BiasLength) ? pos : BiasStart+BiasLength;\n//\t\t\t\tpos = (pos >= BiasStart) ? pos : BiasStart;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t**\tPerform the modified raw seek into the file.\n\t\t*/\n\t\tlong newpos = Raw_Seek(pos, dir) - BiasStart;\n\n\t\t/*\n\t\t**\tPerform a final double check to make sure the file position fits with the bias range.\n\t\t*/\n\t\tif (newpos < 0) {\n\t\t\tnewpos = Raw_Seek(BiasStart, SEEK_SET) - BiasStart;\n\t\t}\n\t\tif (newpos > BiasLength) {\n\t\t\tnewpos = Raw_Seek(BiasStart+BiasLength, SEEK_SET) - BiasStart;\n\t\t}\n\t\treturn(newpos);\n\t}\n\n\t/*\n\t**\tIf the file is not biased in any fashion, then the normal seek logic will\n\t**\twork just fine.\n\t*/\n\treturn(Raw_Seek(pos, dir));\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Size -- Determines size of file (in bytes).                                   *\n *                                                                                             *\n *    Use this routine to determine the size of the file. The file must exist or this is an    *\n *    error condition.                                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes in the file.                                      *\n *                                                                                             *\n * WARNINGS:   This routine handles error conditions and will not return unless the file       *\n *             exists and can successfully be queried for file length.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Size(void)\n{\n\tlong\tsize = 0;\n\n\t/*\n\t**\tA biased file already has its length determined.\n\t*/\n\tif (BiasLength != -1) {\n\t\treturn(BiasLength);\n\t}\n\n\t/*\n\t**\tIf the file is open, then proceed normally.\n\t*/\n\tif (Is_Open()) {\n\n#ifdef WIN32\n\t\tsize = GetFileSize(Handle, NULL);\n\n\t\t/*\n\t\t**\tIf there was in internal error, then call the error function.\n\t\t*/\n\t\tif (size == 0xFFFFFFFF) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t}\n#else\n\n\t\t/*\n\t\t**\tRepetitively try to determine the file size until a fatal error condition or success\n\t\t**\tis achieved.\n\t\t*/\n\t\tfor (;;) {\n\t\t\tHard_Error_Occured = 0;\n\t\t\tsize = filelength(Handle);\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume it is the case of removed media. Display an\n\t\t\t**\terror condition and allow retry.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tif (size == -1) {\n\t\t\t\t\tError(errno, false, Filename);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t} else {\n\n\t\t/*\n\t\t**\tIf the file wasn't open, then open the file and call this routine again. Count on\n\t\t**\tthe fact that the open function must succeed.\n\t\t*/\n\t\tif (Open()) {\n\t\t\tsize = Size();\n\n\t\t\t/*\n\t\t\t**\tSince we needed to open the file we must remember to close the file when the\n\t\t\t**\tsize has been determined.\n\t\t\t*/\n\t\t\tClose();\n\t\t}\n\t}\n\n\tBiasLength = size-BiasStart;\n\treturn(BiasLength);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Create -- Creates an empty file.                                              *\n *                                                                                             *\n *    This routine will create an empty file from the file object. The file object's filename  *\n *    must already have been assigned before this routine will function.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file successfully created? This routine will always return true.     *\n *                                                                                             *\n * WARNINGS:   A fatal error condition could occur with this routine. Especially if the disk   *\n *             is full or a read-only media was selected.                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Create(void)\n{\n\tClose();\n\tif (Open(WRITE)) {\n\n\t\t/*\n\t\t**\tA biased file must be at least as long as the bias offset. Seeking to the\n\t\t**\tappropriate start offset has the effect of lengthening the file to the\n\t\t**\tcorrect length.\n\t\t*/\n\t\tif (BiasLength != -1) {\n\t\t\tSeek(0, SEEK_SET);\n\t\t}\n\n\t\tClose();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Delete -- Deletes the file object from the disk.                              *\n *                                                                                             *\n *    This routine will delete the file object from the disk. If the file object doesn't       *\n *    exist, then this routine will return as if it had succeeded (since the effect is the     *\n *    same).                                                                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the file deleted? If the file was already missing, the this value will   *\n *                be false.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RawFileClass::Delete(void)\n{\n\t/*\n\t**\tIf the file was open, then it must be closed first.\n\t*/\n\tClose();\n\n\t/*\n\t**\tIf there is no filename associated with this object, then this indicates a fatal error\n\t**\tcondition. Report this and abort.\n\t*/\n\tif (!Filename) {\n\t\tError(ENOENT, false);\n\t}\n\n\t/*\n\t**\tRepetitively try to delete the file if possible. Either return with success, or\n\t**\tabort the program with an error.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tIf the file is already missing, then return with this fact. No action is necessary.\n\t\t**\tThis can occur as this section loops if the file exists on a floppy and the floppy\n\t\t**\twas removed, the file deleted on another machine, and then the floppy was\n\t\t**\treinserted. Admittedly, this is a rare case, but is handled here.\n\t\t*/\n\t\tif (!Is_Available()) {\n\t\t\treturn(false);\n\t\t}\n\n#ifdef WIN32\n\t\tif (!DeleteFile(Filename)) {\n\t\t\tError(GetLastError(), false, Filename);\n\t\t\treturn(false);\n\t\t}\n#else\n\t\tHard_Error_Occured = 0;\n\t\tif (remove(Filename) == -1) {\n\n\t\t\t/*\n\t\t\t**\tIf a hard error occurred, then assume that the media has been removed. Display\n\t\t\t**\terror message and retry as directed.\n\t\t\t*/\n\t\t\tif (Hard_Error_Occured) {\n\t\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tIf at this point, DOS says the file doesn't exist, then just exit with this\n\t\t\t**\tfact. It should have been caught earlier, but in any case, this is a legal\n\t\t\t**\tcondition.\n\t\t\t*/\n\t\t\tif (errno == ENOENT) break;\n\n\t\t\t/*\n\t\t\t**\tThe only way it can reach this point is if DOS indicates that access is denied\n\t\t\t**\ton the file. This occurs when trying to delete a file on a read-only media such\n\t\t\t**\tas a CD-ROM. Report this as a fatal error and then abort.\n\t\t\t*/\n\t\t\tError(errno, false, Filename);\n\t\t}\n#endif\n\t\tbreak;\n\t}\n\n\t/*\n\t**\tDOS reports that the file was successfully deleted. Return with this fact.\n\t*/\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.           *\n *                                                                                             *\n *    Use this routine to get the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the file date and time as a long.                                     *\n *          Use the YEAR(long), MONTH(),....                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *   07/13/1996 JLB : Handles win32 method.                                                    *\n *=============================================================================================*/\nunsigned long RawFileClass::Get_Date_Time(void)\n{\n#ifdef WIN32\n\tBY_HANDLE_FILE_INFORMATION info;\n\n\tif (GetFileInformationByHandle(Handle, &info)) {\n\t\tWORD dosdate;\n\t\tWORD dostime;\n\t\tFileTimeToDosDateTime(&info.ftLastWriteTime, &dosdate, &dostime);\n\t\treturn((dosdate << 16) | dostime);\n\t}\n\treturn(0);\n#else\n\tunsigned short time;\n\tunsigned short date;\n\tunsigned long datetime = 0;\n\n\n\t//\n\t//\tIf the file is open, then proceed normally.\n\t//\n\tif ( RawFileClass::Is_Open() ) {\n\t\tif ( _dos_getftime( Handle, &date, &time ) ) {\n\t\t\t//\n\t\t\t// return 0 indicating error with no date and time\n\t\t\t//\n\t\t\treturn( datetime );\n\t\t}\n\t} else {\n\n\t\t//\n\t\t//\tIf the file wasn't open, then see if the file exists.\n\t\t//\n\t\tif ( RawFileClass::Is_Available() ) {\n\t\t\tRawFileClass::Open();\n\n\t\t\tif ( _dos_getftime( Handle, &date, &time ) ) {\n\t\t\t\tRawFileClass::Close();\n\t\t\t\t//\n\t\t\t\t// return 0 indicating error with no date and time\n\t\t\t\t//\n\t\t\t\treturn( datetime );\n\t\t\t}\n\n\t\t\tRawFileClass::Close();\n\t\t} else {\n\t\t\t//\n\t\t\t// return 0 indicating error with no date and time\n\t\t\t//\n\t\t\treturn( datetime );\n\t\t}\n\t}\n\n\t//\n\t// combine the date and time as a long\n\t//\n\tdatetime = (date << 16) + time;\n\n\treturn( datetime );\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.           *\n *                                                                                             *\n *    Use this routine to set the date and time of the file.                                   *\n *                                                                                             *\n * INPUT:   the file date and time as a long                                                   *\n *                                                                                             *\n * OUTPUT:  successful or not if the file date and time was changed.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/14/1995 DRD : Created.                                                                 *\n *   07/13/1996 JLB : Handles win 32 method                                                    *\n *=============================================================================================*/\nbool RawFileClass::Set_Date_Time(unsigned long datetime)\n{\n#ifdef WIN32\n\tif (RawFileClass::Is_Open()) {\n\t\tBY_HANDLE_FILE_INFORMATION info;\n\n\t\tif (GetFileInformationByHandle(Handle, &info)) {\n\t\t\tFILETIME filetime;\n\t\t\tif (DosDateTimeToFileTime((WORD)(datetime >> 16), (WORD)(datetime & 0x0FFFF), &filetime)) {\n\t\t\t\treturn(SetFileTime(Handle, &info.ftCreationTime, &filetime, &filetime));\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n#else\n\tunsigned short time;\n\tunsigned short date;\n\n\t//\n\t//\tIf the file is open, then proceed normally.\n\t//\n\tif ( RawFileClass::Is_Open() ) {\n\t\t//\n\t\t// only set the date and time if open for READ only\n\t\t//\n\t\tif ( Rights == READ ) {\n\t\t\ttime = (unsigned short)(datetime & 0xFFFF);\n\t\t\tdate = (unsigned short)((datetime >> 16) & 0xFFFF);\n\n\t\t\tif ( !_dos_setftime( Handle, date, time ) ) {\n\t\t\t\t//\n\t\t\t\t// return true indicating success\n\t\t\t\t//\n\t\t\t\treturn( true );\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\t//\n\t\t//\tIf the file wasn't open, then see if the file exists.\n\t\t//\n\t\tif ( RawFileClass::Is_Available() ) {\n\t\t\tRawFileClass::Open();\n\n\t\t\ttime = (unsigned short)(datetime & 0xFFFF);\n\t\t\tdate = (unsigned short)((datetime >> 16) & 0xFFFF);\n\n\t\t\tif ( !_dos_setftime( Handle, date, time ) ) {\n\t\t\t\tRawFileClass::Close();\n\t\t\t\t//\n\t\t\t\t// return true indicating success\n\t\t\t\t//\n\t\t\t\treturn( true );\n\t\t\t}\n\n\t\t\tRawFileClass::Close();\n\t\t}\n\t}\n\n\t//\n\t// return false indicating error\n\t//\n\treturn( false );\n#endif\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Bias -- Bias a file with a specific starting position and length.             *\n *                                                                                             *\n *    This will bias a file by giving it an artificial starting position and length. By        *\n *    using this routine, it is possible to 'fool' the file into ignoring a header and         *\n *    trailing extra data. An example of this would be a file inside of a mixfile.             *\n *                                                                                             *\n * INPUT:   start    -- The starting offset that will now be considered the start of the       *\n *                      file.                                                                  *\n *                                                                                             *\n *          length   -- The forced length of the file. For files that are opened for write,    *\n *                      this serves as the artificial constraint on the file's length. For     *\n *                      files opened for read, this limits the usable file size.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RawFileClass::Bias(int start, int length)\n{\n\tif (start == 0) {\n\t\tBiasStart = 0;\n\t\tBiasLength = -1;\n\t\treturn;\n\t}\n\n\tBiasLength = RawFileClass::Size();\n\tBiasStart += start;\n\tif (length != -1) {\n\t\tBiasLength = BiasLength < length ? BiasLength : length;\n\t}\n\tBiasLength = BiasLength > 0 ? BiasLength : 0;\n\n\t/*\n\t**\tMove the current file offset to a legal position if necessary and the\n\t**\tfile was open.\n\t*/\n\tif (Is_Open()) {\n\t\tRawFileClass::Seek(0, SEEK_SET);\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                              *\n *                                                                                             *\n *    This will perform a seek on the file as if it were unbiased. This is in spite of any     *\n *    bias setting the file may have. The ability to perform a raw seek in this fasion is      *\n *    necessary to maintain the bias ability.                                                  *\n *                                                                                             *\n * INPUT:   pos   -- The position to seek the file relative to the \"dir\" parameter.            *\n *                                                                                             *\n *          dir   -- The origin of the seek operation.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the new position of the seek operation.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/04/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nlong RawFileClass::Raw_Seek(long pos, int dir)\n{\n\t/*\n\t**\tIf the file isn't opened, then this is a fatal error condition.\n\t*/\n\tif (!Is_Open()) {\n\t\tError(EBADF, false, Filename);\n\t}\n\n#ifdef WIN32\n\tswitch (dir) {\n\t\tcase SEEK_SET:\n\t\t\tdir = FILE_BEGIN;\n\t\t\tbreak;\n\n\t\tcase SEEK_CUR:\n\t\t\tdir = FILE_CURRENT;\n\t\t\tbreak;\n\n\t\tcase SEEK_END:\n\t\t\tdir = FILE_END;\n\t\t\tbreak;\n\t}\n\n\tpos = SetFilePointer(Handle, pos, NULL, dir);\n\n\t/*\n\t**\tIf there was an error in the seek, then bail with an error condition.\n\t*/\n\tif (pos == 0xFFFFFFFF) {\n\t\tError(GetLastError(), false, Filename);\n\t}\n#else\n\n\t/*\n\t**\tKeep trying to seek until a non-retry condition occurs.\n\t*/\n\tfor (;;) {\n\n\t\t/*\n\t\t**\tPerform the low level seek on the file.\n\t\t*/\n\t\tHard_Error_Occured = 0;\n\t\tpos = lseek(Handle, pos, dir);\n\n\t\t/*\n\t\t**\tIf a hard error occurred, then assume that it is the case of removed media. Display\n\t\t**\terror message and retry.\n\t\t*/\n\t\tif (Hard_Error_Occured) {\n\t\t\tError(Hard_Error_Occured, true, Filename);\n\t\t\tcontinue;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tA negative one indicates a fatal error with the seek operation. Display error\n\t\t\t**\tcondition and then abort.\n\t\t\t*/\n\t\t\tif (pos == -1) {\n\t\t\t\tError(errno, false, Filename);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n#endif\n\n\t/*\n\t**\tReturn with the new position of the file. This will range between zero and the number of\n\t**\tbytes the file contains.\n\t*/\n\treturn(pos);\n}\n"
  },
  {
    "path": "REDALERT/RAWFILE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RAWFILE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Westwood Library                                             *\n *                                                                                             *\n *                    File Name : RAWFILE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 8, 1994                                               *\n *                                                                                             *\n *                  Last Update : October 18, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RawFileClass::File_Name -- Returns with the filename associate with the file object.      *\n *   RawFileClass::RawFileClass -- Default constructor for a file object.                      *\n *   RawFileClass::~RawFileClass -- Default deconstructor for a file object.                   *\n *   RawFileClass::Is_Open -- Checks to see if the file is open or not.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RAWFILE_Hx\n#define RAWFILE_Hx\n\n#include\t<limits.h>\n#include\t<errno.h>\n#include\t<stddef.h>\n#include\t<stdlib.h>\n\n#ifdef WIN32\n#include\t<windows.h>\n\n#define\tNULL_HANDLE\t\tINVALID_HANDLE_VALUE\n#define\tHANDLE_TYPE\t\tHANDLE\n#else\n#define\tNULL_HANDLE\t\t-1\n#define\tHANDLE_TYPE\t\tint\n#endif\n\n#include\t\"wwfile.h\"\n\n#ifdef NEVER\n\t/*\n\t**\tThis is a duplicate of the error numbers. The error handler for the RawFileClass handles\n\t**\tthese errors. If the error routine is overridden and additional errors are defined, then\n\t**\tuse numbers starting with 100. Note that these errors here are listed in numerical order.\n\t**\tThese errors are defined in the standard header file \"ERRNO.H\".\n\t*/\n\tEZERO,\t\t\t\t// Non-error.\n\tEINVFNC,\t\t\t\t// Invalid function number.\n\tENOFILE,\t\t\t\t// File not found.\n\tENOENT=ENOFILE,\t// No such file or directory.\n\tENOPATH,\t\t\t\t// Path not found.\n\tEMFILE,\t\t\t\t// Too many open files.\n\tEACCES,\t\t\t\t// Permission denied.\n\tEBADF,\t\t\t\t// Bad file number.\n\tECONTR,\t\t\t\t// Memory blocks destroyed.\n\tENOMEM,\t\t\t\t// Not enough core memory.\n\tEINVMEM,\t\t\t\t// Invalid memory block address.\n\tEINVENV,\t\t\t\t// Invalid environment.\n\tEINVFMT,\t\t\t\t// Invalid format.\n\tEINVACC,\t\t\t\t// Invalid access code.\n\tEINVDAT,\t\t\t\t// Invalid data.\n\tEFAULT,\t\t\t\t// Unknown error.\n\tEINVDRV,\t\t\t\t// Invalid drive specified.\n\tENODEV=EINVDRV,\t// No such device.\n\tECURDIR,\t\t\t\t// Attempt to remove CurDir.\n\tENOTSAM,\t\t\t\t// Not same device.\n\tENMFILE,\t\t\t\t// No more files.\n\tEINVAL,\t\t\t\t// Invalid argument.\n\tE2BIG,\t\t\t\t// Argument list too long.\n\tENOEXEC,\t\t\t\t// exec format error.\n\tEXDEV,\t\t\t\t// Cross-device link.\n\tENFILE,\t\t\t\t// Too many open files.\n\tECHILD,\t\t\t\t// No child process.\n\tENOTTY,\t\t\t\t// not used\n\tETXTBSY,\t\t\t\t// not used\n\tEFBIG,\t\t\t\t// not used\n\tENOSPC,\t\t\t\t// No space left on device.\n\tESPIPE,\t\t\t\t// Illegal seek.\n\tEROFS,\t\t\t\t// Read-only file system.\n\tEMLINK,\t\t\t\t// not used\n\tEPIPE,\t\t\t\t// Broken pipe.\n\tEDOM,\t\t\t\t\t// Math argument.\n\tERANGE,\t\t\t\t// Result too large.\n\tEEXIST,\t\t\t\t// File already exists.\n\tEDEADLOCK,\t\t\t// Locking violation.\n\tEPERM,\t\t\t\t// Operation not permitted.\n\tESRCH,\t\t\t\t// not used\n\tEINTR,\t\t\t\t// Interrupted function call.\n\tEIO,\t\t\t\t\t// Input/output error.\n\tENXIO,\t\t\t\t// No such device or address.\n\tEAGAIN,\t\t\t\t// Resource temporarily unavailable.\n\tENOTBLK,\t\t\t\t// not used\n\tEBUSY,\t\t\t\t// Resource busy.\n\tENOTDIR,\t\t\t\t// not used\n\tEISDIR,\t\t\t\t// not used\n\tEUCLEAN,\t\t\t\t// not used\n#endif\n\n#ifndef WWERROR\n#define WWERROR\t-1\n#endif\n\n/*\n**\tThis is the definition of the raw file class. It is derived from the abstract base FileClass\n**\tand handles the interface to the low level DOS routines. This is the first class in the\n**\tchain of derived file classes that actually performs a useful function. With this class,\n**\tI/O is possible. More sophisticated features, such as packed files, CD-ROM support,\n**\tfile caching, and XMS/EMS memory support, are handled by derived classes.\n**\n**\tOf particular importance is the need to override the error routine if more sophisticated\n**\terror handling is required. This is more than likely if greater functionality is derived\n**\tfrom this base class.\n*/\nclass RawFileClass : public FileClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis is a record of the access rights used to open the file. These rights are\n\t\t**\tused if the file object is duplicated.\n\t\t*/\n\t\tint Rights;\n\n\t\tRawFileClass(char const *filename);\n\t\tRawFileClass(void);\n\t\tRawFileClass (RawFileClass const & f);\n\t\tRawFileClass & operator = (RawFileClass const & f);\n\t\tvirtual ~RawFileClass(void);\n\n\t\tvirtual char const * File_Name(void) const;\n\t\tvirtual char const * Set_Name(char const *filename);\n\t\tvirtual int Create(void);\n\t\tvirtual int Delete(void);\n\t\tvirtual int Is_Available(int forced=false);\n\t\tvirtual int Is_Open(void) const;\n\t\tvirtual int Open(char const *filename, int rights=READ);\n\t\tvirtual int Open(int rights=READ);\n\t\tvirtual long Read(void *buffer, long size);\n\t\tvirtual long Seek(long pos, int dir=SEEK_CUR);\n\t\tvirtual long Size(void);\n\t\tvirtual long Write(void const *buffer, long size);\n\t\tvirtual void Close(void);\n\t\tvirtual unsigned long Get_Date_Time(void);\n\t\tvirtual bool Set_Date_Time(unsigned long datetime);\n\t\tvirtual void Error(int error, int canretry = false, char const * filename=NULL);\n\n\t\tvoid Bias(int start, int length=-1);\n\n\t\tHANDLE_TYPE Get_File_Handle(void) { return (Handle); };\n\n\t\t/*\n\t\t**\tThese bias values enable a sub-portion of a file to appear as if it\n\t\t**\twere the whole file. This comes in very handy for multi-part files such as\n\t\t**\tmixfiles.\n\t\t*/\n\t\tint BiasStart;\n\t\tint BiasLength;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis function returns the largest size a low level DOS read or write may\n\t\t**\tperform. Larger file transfers are performed in chunks of this size or less.\n\t\t*/\n\t\tlong Transfer_Block_Size(void) {return (long)((unsigned)UINT_MAX)-16L;};\n\n\t\tlong Raw_Seek(long pos, int dir=SEEK_CUR);\n\n\tprivate:\n\n\t\t/*\n\t\t**\tThis is the low level DOS handle. A -1 indicates an empty condition.\n\t\t*/\n\t\tHANDLE_TYPE Handle;\n\n\t\t/*\n\t\t**\tThis points to the filename as a NULL terminated string. It may point to either a\n\t\t**\tconstant or an allocated string as indicated by the \"Allocated\" flag.\n\t\t*/\n\t\tchar const * const Filename;\n\n\t\t//\n\t\t// file date and time are in the following formats:\n\t\t//\n\t\t//      date   bits 0-4   day (0-31)\n\t\t//             bits 5-8   month (1-12)\n\t\t//             bits 9-15  year (0-119 representing 1980-2099)\n\t\t//\n\t\t//      time   bits 0-4   second/2 (0-29)\n\t\t//             bits 5-10  minutes (0-59)\n\t\t//             bits 11-15 hours (0-23)\n\t\t//\n\t\tunsigned short Date;\n\t\tunsigned short Time;\n\n\t\t/*\n\t\t**\tFilenames that were assigned as part of the construction process\n\t\t**\tare not allocated. It is assumed that the filename string is a\n\t\t**\tconstant in that case and thus making duplication unnecessary.\n\t\t**\tThis value will be non-zero if the filename has be allocated\n\t\t**\t(using strdup()).\n\t\t*/\n\t\tunsigned Allocated:1;\n};\n\n\n/***********************************************************************************************\n * RawFileClass::File_Name -- Returns with the filename associate with the file object.        *\n *                                                                                             *\n *    Use this routine to determine what filename is associated with this file object. If no   *\n *    filename has yet been assigned, then this routing will return NULL.                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the file name associated with this file object or NULL   *\n *          if one doesn't exist.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline char const * RawFileClass::File_Name(void) const\n{\n\treturn(Filename);\n}\n\n\n/***********************************************************************************************\n * RawFileClass::RawFileClass -- Default constructor for a file object.                        *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::RawFileClass(void) :\n\tRights(READ),\n\tBiasStart(0),\n\tBiasLength(-1),\n\t#ifdef WIN32\n\tHandle(INVALID_HANDLE_VALUE),\n\t#else\n\tHandle(-1),\n\t#endif\n\tFilename(0),\n\tDate(0),\n\tTime(0),\n\tAllocated(false)\n{\n}\n\n\n/***********************************************************************************************\n * RawFileClass::~RawFileClass -- Default deconstructor for a file object.                     *\n *                                                                                             *\n *    This constructs a null file object. A null file object has no file handle or filename    *\n *    associated with it. In order to use a file object created in this fashion it must be     *\n *    assigned a name and then opened.                                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline RawFileClass::~RawFileClass(void)\n{\n\tClose();\n\tif (Allocated && Filename) {\n\t\tfree((char *)Filename);\n\t\t((char *&)Filename) = 0;\n\t\tAllocated = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * RawFileClass::Is_Open -- Checks to see if the file is open or not.                          *\n *                                                                                             *\n *    Use this routine to determine if the file is open. It returns true if it is.             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Is the file open?                                                            *\n *                                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/18/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\ninline int RawFileClass::Is_Open(void) const\n{\n#ifdef WIN32\n\treturn(Handle != INVALID_HANDLE_VALUE);\n#else\n\treturn (Handle >= 0);\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/RAWOLAPI.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n//\trawolapi.cpp - Core WOLAPI interface functions stuff.\n//\tDefinitions for RAChatEventSink, RADownloadEventSink, RANetUtilEventSink.\n//\tajw 07/10/98\n\n#include \"RAWolapi.h\"\n#define IID_DEFINED\n#include \"wolapi\\wolapi_i.c\"\n#include \"WolapiOb.h\"\n#include \"WolStrng.h\"\n#include \"Wol_gsup.h\"\n#include \"wolapi\\netutildefs.h\"\n\n#include \"WolDebug.h\"\n\nbool operator<( const User& u1, const User& u2 );\n\nconst char* Game_Registry_Key();\n\n//\tThe definitions of QueryInterface, AddRef, and Release are needed because we are not including\n//\tfiles that ordinarily (under MSVC) would define these for us, as part of CComObjectRoot, I believe.\n//\tThis Watcom has no equivalent we can use, so we do it manually...\n\n//***********************************************************************************************\nRAChatEventSink::RAChatEventSink( WolapiObject* pOwnerIn ) : m_cRef( 0 ), \t//\tinit the reference count\n\tbRequestServerListWait( false ),\n\tpOwner( pOwnerIn ),\n\tpServer( NULL ),\n\tbConnected( false ),\n\thresRequestConnectionError( 0 ),\n\tpChannelList( NULL ),\n\tpUserList( NULL ),\n\tpUserTail( NULL ),\n\tszMotd( NULL ),\n\tbJoined( false ),\n\tbGotKickedTrigger( false ),\n\tbIgnoreChannelLists( false ),\n\tbRequestChannelListForLobbiesWait( false ),\n\tpGameUserList( NULL ),\n\tbRequestGameStartWait( false ),\n\tpUserIPList( NULL ),\n\tpUserIPListTail( NULL ),\n\tiGameID( 0 )\n{\n}\n\n//***********************************************************************************************\nRAChatEventSink::~RAChatEventSink()\n{\n//\tdebugprint( \"RAChatEventSink destructor\\n\" );\n\tdelete pServer;\n\tdelete [] szMotd;\n\tDeleteChannelList();\n\tDeleteUserList();\n\tDeleteUserIPList();\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRAChatEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n//\tdebugprint( \"RAChatEventSink::QueryInterface\\n\" );\n\tif ((iid == IID_IUnknown) ||(iid == IID_IChatEvent))\n\t{\n\t\t*ppv = (IChatEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRAChatEventSink::AddRef()\n{\n//\tdebugprint( \"RAChatEventSink::AddRef\\n\" );\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRAChatEventSink::Release()\n{\n//\tdebugprint( \"RAChatEventSink::Release\\n\" );\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerList( HRESULT hRes, Server* pServerHead )\n{\n\t//strcpy( szLadderServerHost, \"games.westwood.com\" );\n\t//iLadderServerPort = 3840;\n\t//strcpy( szGameResServerHost, \"games.westwood.com\" );\n\n//\tdebugprint( \">>> OnServerList got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( pServer )\n\t{\n\t\tdelete pServer;\n\t\tpServer = NULL;\n\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\twhile( pServerHead )\n\t\t{\n\t\t\t//\tCopy the first IRC Server to use in the RequestConnection() call.\n\t\t\tif( !pServer && ( strcmp( (char*)pServerHead->connlabel, \"IRC\" ) == 0 ) )\n\t\t\t{\n\t\t\t\tpServer = new Server;\n\t\t\t\t*pServer = *pServerHead;\n\t\t\t}\n\t\t\telse if( !*pOwner->szLadderServerHost && ( strcmp( (char*)pServerHead->connlabel, \"LAD\" ) == 0 ) )\n\t\t\t{\n//\t\t\t\tdebugprint( \"Scanning '%s'\\n\", (char*)pServerHead->conndata );\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szLadderServerHost, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iLadderServerPort = atoi( token );\n//\t\t\t\tdebugprint( \"Ladder is at: %s, port %i\\n\", pOwner->szLadderServerHost, pOwner->iLadderServerPort );\n\t\t\t}\n\t\t\telse if( !*pOwner->szGameResServerHost1 && ( strcmp( (char*)pServerHead->connlabel, \"GAM\" ) == 0 ) )\n\t\t\t{\n\t\t\t\t//\tThis is the Red Alert game results port.\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szGameResServerHost1, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iGameResServerPort1 = atoi( token );\n//\t\t\t\tdebugprint( \"GameRes is at: %s, port %i\\n\", pOwner->szGameResServerHost, pOwner->iGameResServerPort );\n\t\t\t}\n\t\t\telse if( !*pOwner->szGameResServerHost2 && ( strcmp( (char*)pServerHead->connlabel, \"GAM\" ) == 0 ) )\n\t\t\t{\n\t\t\t\t//\tThis is the Aftermath game results port.\n\t\t\t\tchar* token;\n\t\t\t\ttoken = strtok( (char*)pServerHead->conndata, \";\" );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tstrcpy( pOwner->szGameResServerHost2, token );\n\t\t\t\ttoken = strtok( NULL, \";\" );\n\t\t\t\tpOwner->iGameResServerPort2 = atoi( token );\n//\t\t\t\tdebugprint( \"GameRes is at: %s, port %i\\n\", pOwner->szGameResServerHost, pOwner->iGameResServerPort );\n\t\t\t}\n\t\t\tpServerHead = pServerHead->next;\n\t\t}\n\t}\n\n\tbRequestServerListWait = false;\n\treturn(S_OK);\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPageSend( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnPageSend got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( hRes != CHAT_S_PAGE_NOTHERE && hRes != CHAT_S_PAGE_OFF && hRes != S_OK )\n\t\thRes = E_FAIL;\n\n\thresRequestPageResult = hRes;\n\n\tbRequestPageWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPaged( HRESULT, User* pUser, LPCSTR szMessage )\n{\n//\tdebugprint( \">>> OnPaged got: %s \", szMessage );\n\n\tchar* szPrint = new char[ strlen( (char*)pUser->name ) + strlen( szMessage ) + strlen( TXT_WOL_ONPAGE ) ];\n\tsprintf( szPrint, TXT_WOL_ONPAGE, (char*)pUser->name, szMessage );\n\tif( !pOwner->bInGame )\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PAGE );\n\telse\n\t{\n\t\tSession.Messages.Add_Message( NULL, 0, szPrint, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );\n\t\tif( !pOwner->bFreezeExternalPager )\n\t\t\tstrcpy( pOwner->szExternalPager, (char*)pUser->name );\n\t\tMap.Flag_To_Redraw(true);\n\t}\n\n\tdelete [] szPrint;\n\n\tSound_Effect( WOLSOUND_ONPAGE );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnFind( HRESULT hRes, Channel* pChannel )\n{\n//\tdebugprint( \">>> OnFind got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n\tif( hRes != CHAT_S_FIND_NOTHERE && hRes != CHAT_S_FIND_NOCHAN && hRes != CHAT_S_FIND_OFF && hRes != S_OK )\n\t\thRes = E_FAIL;\n\n\tif( hRes == S_OK )\n\t\tOnFindChannel = *pChannel;\n\n\thresRequestFindResult = hRes;\n\n\tbRequestFindWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnLogout( HRESULT hRes, User* pUser )\n{\n//\tdebugprint( \">>> OnLogout got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\t\t//\tSomeone has been logged out by the chat server due to inactivity.\n\t\t//\tFake a call to OnChannelLeave(), as the processing is identical.\n//\t\tdebugprint( \"OnLogout calling OnChannelLeave for %s, owner=%i\\n\", (char*)pUser->name, ( pUser->flags & CHAT_USER_CHANNELOWNER ) );\n\t\tOnChannelLeave( S_OK, NULL, pUser );\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnBusy(HRESULT)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnIdle(HRESULT)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnConnection( HRESULT hRes, LPCSTR motd )\n{\n//\tdebugprint( \">>> OnConnection got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\n\t\t//\tPrepare a new string for a modified version of motd.\n\t\tszMotd = new char[ strlen( motd ) + 1 ];\n\t\t//\tReplace single line breaks with a space.\n\t\t//\tReplace double line breaks with double carriage returns.\n\n\t\tbool\tbJustDidBreak = false;\n\t\tconst char*\tszIn = motd;\n\t\tchar*   szOut = szMotd;\n\n\t\twhile( *szIn )\n\t\t{\n\t\t\tif( *szIn == '\\r' && *( szIn + 1 ) == '\\n' )\n\t\t\t{\n\t\t\t\tif( !bJustDidBreak )\n\t\t\t\t{\n\t\t\t\t\t*szOut++ = ' ';\n\t\t\t\t\tbJustDidBreak = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tszOut--;\n\t\t\t\t\t*szOut++ = '\\r';\n\t\t\t\t\t*szOut++ = '\\r';\n\t\t\t\t\tbJustDidBreak = false;\n//\t\t\t\t\tdebugprint( \"^\" );\n\t\t\t\t}\n\t\t\t\tszIn += 2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*szOut++ = *szIn++;\n\t\t\t\tbJustDidBreak = false;\n\t\t\t}\n//\t\t\tdebugprint( \"%c\", *( szOut - 1 ) );\n\t\t}\n\t\t*szOut = 0;\t\t//\tNull-terminate.\n//\t\tdebugprint( \"\\n\" );\n\n//\t\tpOwner->PrintMessage( szMotd );\n\n\t\tbConnected = true;\n\t}\n\telse\n\t{\n\t\thresRequestConnectionError = hRes;\n\n\t\tchar szError[150];\n\t\tChatDefAsText( szError, hRes );\n\t\tstrcat( szError, \" (Connect Error)\" );\n//\t\tdebugprint( szError );\n\t}\n\n\tbRequestConnectionWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelCreate( HRESULT hRes, Channel* )\n{\n//\tdebugprint( \">>> OnChannelCreate got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n//\tif( bJoined )\n//\t{\n//\t\tWWMessageBox().Process( \"RAChatEventSink::OnChannelCreate called when bJoined is true!\" );\n//\t\tFatal( \"RAChatEventSink::OnChannelCreate called when bJoined is true!\" );\n//\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tbJoined = true;\n\t}\n\tbRequestChannelCreateWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelModify(HRESULT, Channel *)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelJoin( HRESULT hRes, Channel* /*pChannel*/, User* pUser )\n{\n//\tif( SUCCEEDED( hRes ) )\n//\t\tdebugprint( \">>> OnChannelJoin got: channel '%s', user '%s', %i \", (char*)pChannel->name, (char*)pUser->name, hRes );\n//\telse\n//\t\tdebugprint( \">>> OnChannelJoin got: %i \", hRes );\n\tDebugChatDef( hRes );\n\n//\t//\tSpecial case - ignore OnChannelJoin when waiting for a UserList.\n//\tif( bRequestUserListWait )\n//\t{\n//\t\tdebugprint( \"bRequestUserListWait is true - ignoring join.\\n\" );\n//\t\treturn S_OK;\n//\t}\n\n\thresRequestJoinResult = hRes;\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tif( pUser->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\tbJoined = true;\n\t\t\tbRequestChannelJoinWait = false;\n\t\t\tif( pUserList )\n\t\t\t{\n\t\t\t\t//\tShould never happen.\n//\t\t\t\tdebugprint( \"pUserList should be NULL (as I am the joiner)!!! Deleting user list...\\n\" );\n\t\t\t\tDeleteUserList();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\tif( pOwner->pGSupDlg && \n\t\t\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t\t\t{\n\t\t\t\t\t//\tA game has this moment entered the \"must start\" phase. We can ignore the fact that others are leaving the channel.\n//\t\t\t\t\tdebugprint( \"Ignoring leave because game is starting.\\n\" );\n\t\t\t\t\treturn S_OK;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//\tAdd user to our current channel users list.\n\t\t\tif( !pUserList )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelJoin - ignoring %s join... \\n\", (char*)pUser->name );\n\t\t\t\treturn S_OK;\n\t\t\t}\n//\t\t\tif( !pUserList )\n//\t\t\t{\n//\t\t\t\t//\tThere has to be at least one user there - you.\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelJoin!!! users: %s\\n\", (char*)pUser->name );\n//\t\t\t\tFatal( \"pUserList is null in OnChannelJoin!!!\\n\" );\n//\t\t\t}\n\t\t\t\n\t\t\tUser* pUserNew = new User;\n\t\t\t*pUserNew = *pUser;\n\t\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\n\t\t\t//\tInsert user into list alphabetically.\n\t\t\tInsertUserSorted( pUserNew );\n\n\t\t\t//\tUpdate the shown list.\n\t\t\tpOwner->ListChannelUsers();\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\t_ASSERTE( pOwner->pGSupDlg );\n\t\t\t\tpOwner->pGSupDlg->OnGuestJoin( pUser );\n\n\t\t\t\t//\tAsk for this player's IP address.\n\t\t\t\tpOwner->RequestIPs( (char*)pUser->name );\n\t\t\t}\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL || pOwner->CurrentLevel == WOL_LEVEL_INLOBBY )\n\t\t\t{\n\t\t\t\t//\tRequest ladder results for new user.\n\t\t\t\tpOwner->RequestLadders( (char*)pUser->name );\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tbRequestChannelJoinWait = false;\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::InsertUserSorted( User* pUserNew )\n{\n\tif( !pUserList )\n\t{\n\t\tpUserList = pUserNew;\n\t\tpUserTail = pUserNew;\n\t}\n\telse\n\t{\n\t\tif( *pUserNew < *pUserList )\n\t\t{\n\t\t\t//\tInsert user at beginning.\n\t\t\tpUserNew->next = pUserList;\n\t\t\tpUserList = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tUser* pUserCheck = pUserList;\n\t\t\tUser* pUserInsertAfter = NULL;\n\t\t\twhile( pUserCheck->next )\n\t\t\t{\n\t\t\t\tif( *pUserNew < *pUserCheck->next )\n\t\t\t\t{\n\t\t\t\t\tpUserInsertAfter = pUserCheck;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpUserCheck = pUserCheck->next;\n\t\t\t}\n\t\t\tif( pUserInsertAfter )\n\t\t\t{\n\t\t\t\tpUserNew->next = pUserInsertAfter->next;\n\t\t\t\tpUserInsertAfter->next = pUserNew;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tAdd user to end.\n\t\t\t\tpUserTail->next = pUserNew;\n\t\t\t\tpUserTail = pUserNew;\n\t\t\t}\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nbool operator<( const User& u1, const User& u2 )\n{\n\tif( u1.flags & CHAT_USER_CHANNELOWNER && !( u2.flags & CHAT_USER_CHANNELOWNER ) )\n\t\treturn true;\n\tif( !( u1.flags & CHAT_USER_CHANNELOWNER ) && u2.flags & CHAT_USER_CHANNELOWNER )\n\t\treturn false;\n\tif( u1.flags & CHAT_USER_VOICE && !( u2.flags & CHAT_USER_VOICE ) )\n\t\treturn true;\n\tif( !( u1.flags & CHAT_USER_VOICE ) && u2.flags & CHAT_USER_VOICE )\n\t\treturn false;\n\treturn ( _stricmp( (char*)u1.name, (char*)u2.name ) < 0 );\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelLeave( HRESULT hRes, Channel*, User* pUser )\n{\n\t//\tNote: This is also called directly from OnUserKick(), below, when someone is kicked from a channel.\n\t//\tAlso now from OnLogout().\n\n//\tdebugprint( \">>> OnChannelLeave got %s: \", (char*)pUser->name );\n\tDebugChatDef( hRes );\n\n//\t//\tSpecial case - ignore OnChannelLeave when waiting for a UserList.\n//\tif( bRequestUserListWait )\n//\t{\n//\t\tdebugprint( \"bRequestUserListWait is true - ignoring leave.\\n\" );\n//\t\treturn S_OK;\n//\t}\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\tif( pUser->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\tbJoined = false;\n\t\t\tbRequestChannelLeaveWait = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tRemove user from our current channel users list.\n\t\t\tif( !pUserList )\n\t\t\t{\n//\t\t\t\tdebugprint( \"pUserList is null in OnChannelLeave - ignoring %s leave... \\n\", (char*)pUser->name );\n\t\t\t\treturn S_OK;\n\t\t\t}\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\tif( pOwner->pGSupDlg && \n\t\t\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t\t\t{\n\t\t\t\t\t//\tA game has this moment entered the \"must start\" phase. We must ignore the fact that others are leaving the channel.\n//\t\t\t\t\tdebugprint( \"Ignoring leave because game is starting.\\n\" );\n\t\t\t\t\treturn S_OK;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUser* pUserSearch = pUserList;\n\t\t\tUser* pUserPrevious = NULL;\n\t\t\tbool bFound = false;\n\t\t\twhile( pUserSearch )\n\t\t\t{\n\t\t\t\tif( _stricmp( (char*)pUserSearch->name, (char*)pUser->name ) == 0 )\n\t\t\t\t{\n\t\t\t\t\t//\tRemove from list.\n\t\t\t\t\tif( !pUserPrevious )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tHead of list is being removed.\n\t\t\t\t\t\tpUserList = pUserSearch->next;\n\t\t\t\t\t\tif( !pUserList )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//\tThis means all entries were removed. Can't happen, as you are still there.\n//\t\t\t\t\t\t\tdebugprint( \"This means all entries were removed. Can't happen, as you are still there. (OnChannelLeave)\\n\" );\n\t\t\t\t\t\t\tFatal( \"This means all entries were removed. Can't happen, as you are still there. (OnChannelLeave)\\n\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpUserPrevious->next = pUserSearch->next;\n\t\t\t\t\t\tif( !pUserPrevious->next )\n\t\t\t\t\t\t\tpUserTail = pUserPrevious;\t\t//\tNew list tail.\n\t\t\t\t\t}\n\t\t\t\t\t//\tDestroy removed user.\n\t\t\t\t\tdelete pUserSearch;\n\t\t\t\t\tbFound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpUserPrevious = pUserSearch;\n\t\t\t\tpUserSearch = pUserSearch->next;\n\t\t\t}\n\t\t\tif( !bFound )\n\t\t\t{\n\t\t\t\t//\tUser has to be found. This should not happen.\n//\t\t\t\tdebugprint( \"User not found for removal in OnChannelLeave!!!\\n\" );\n\t\t\t\treturn S_OK;\n\t\t\t}\n\n\t\t\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t\t\t{\n\t\t\t\t//\tNote that the following is done before removing the user from the playerlist.\n\t\t\t\tchar* szPrint = new char[ strlen( TXT_WOL_PLAYERLEFTGAME ) + strlen( (char*)pUser->name ) + 5 ];\n\t\t\t\tsprintf( szPrint, TXT_WOL_PLAYERLEFTGAME, (char*)pUser->name );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\tdelete [] szPrint;\n\t\t\t\tpOwner->pGSupDlg->OnGuestLeave( pUser );\n\t\t\t}\n\n\t\t\t//\tUpdate the shown list.\n\t\t\tpOwner->ListChannelUsers();\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelTopic(HRESULT, Channel *, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnGroupList(HRESULT, Group *)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicMessage( HRESULT, Channel*, User* pUserSender, LPCSTR szMessage )\n{\n\tif( *szMessage )\n\t{\n\t\tif( strlen( szMessage ) > 3 && szMessage[0] == 35 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t\t{\n\t\t\tif( strlen( szMessage ) > 4 )\n\t\t\t{\n\t\t\t\tint i = atoi( szMessage + 4 );\n\t\t\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 && pOwner->bEggSounds )\n\t\t\t\t\tSpeak( (VoxType)i );\n\t\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + 16 ];\n\t\t\t\tsprintf( szPrint, \"%s!\", (char*)pUserSender->name );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );\n\t\t\t\tdelete [] szPrint;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 110 ];\n\t\t\tsprintf( szPrint, \"%s: %s\", (char*)pUserSender->name, szMessage );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PUBLICMESSAGE );\n\t\t\tdelete [] szPrint;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateMessage( HRESULT, User* pUserSender, LPCSTR szMessage )\n{\n\t//\tIgnore private messages sent to myself by myself.\n\tif( pUserSender->flags & CHAT_USER_MYSELF )\n\t\treturn S_OK;\n\n\tif( *szMessage )\n\t{\n\t\tchar ci1[] = \"VGhpcyBpcyBBZGFtLiBIYXZlIHdlIG5vdCBwZXJjaGFuY2UgbWV0IGJlZm9yZT8=\";\n\t\tchar co1[48];\n\t\tBase64_Decode( ci1, strlen( ci1 ), co1, 47 );\n\t\tco1[47] = 0;\n\t\tif( strcmp( szMessage, co1 ) == 0 )\n\t\t{\n\t\t\tSYSTEMTIME SysTime;\n\t\t\t::GetSystemTime( &SysTime );\n\t\t\tchar szOut[60];\n\t\t\tchar ci2[] = \"SSBhbSB5b3VyIGFibGUgYW5kIHdpbGxpbmcgc2xhdmUu\";\n\t\t\tchar co2[34];\n\t\t\tBase64_Decode( ci2, strlen( ci2 ), co2, 33 );\n\t\t\tco2[33] = 0;\n\t\t\tsprintf( szOut, \"%s (%i/%i/%i)\", co2, SysTime.wMonth, SysTime.wDay, SysTime.wYear );\n\t\t\tUser UserReply;\n\t\t\tUserReply = *pUserSender;\n\t\t\tUserReply.next = NULL;\n\t\t\tpOwner->pChat->RequestPrivateMessage( &UserReply, szOut );\n\t\t\treturn S_OK;\n\t\t}\n\t\tif( !bSpecialMessage( szMessage ) )\n\t\t{\n\t\t\tif( strlen( szMessage ) > 3 && szMessage[0] == 35 && szMessage[1] == 97 && szMessage[2] == 106 && szMessage[3] == 119 )\n\t\t\t{\n\t\t\t\tif( strlen( szMessage ) > 4 )\n\t\t\t\t{\n\t\t\t\t\tint i = atoi( szMessage + 4 );\n\t\t\t\t\tif( i >= VOX_ACCOMPLISHED && i <= VOX_LOAD1 && pOwner->bEggSounds )\n\t\t\t\t\t\tSpeak( (VoxType)i );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 116 ];\n\t\t\t\tsprintf( szPrint, \"%s%s: %s\", (char*)pUserSender->name, TXT_WOL_PRIVATE, szMessage );\n\t\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_PRIVATEMESSAGE );\n\t\t\t\tSound_Effect( VOC_INCOMING_MESSAGE );\n\t\t\t\tdelete [] szPrint;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szOut = new char[ strlen( szMessage ) + 10 ];\n\t\t\tstrcpy( szOut, &szMessage[8] );\n\t\t\tpOwner->pChat->RequestPublicMessage( szOut );\n\t\t\tchar* szPrint = new char[ strlen( szOut ) + strlen( pOwner->szMyName ) + 10 ];\n\t\t\tsprintf( szPrint, \"%s: %s\", pOwner->szMyName, szOut );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_SELFSPEAKING );\n\t\t\tdelete [] szPrint;\n\t\t\tdelete [] szOut;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nbool RAChatEventSink::bSpecialMessage( const char* szMessage )\n{\n\tif( strlen( szMessage ) < 9 )\n\t\treturn false;\n\tif( szMessage[0] != 33 || szMessage[1] != 97 || szMessage[2] != 106 || szMessage[3] != 119 )\n\t\treturn false;\n\tSYSTEMTIME SysTime;\n\t::GetSystemTime( &SysTime );\n\tchar szCode[5];\n\tmemcpy( (void*)szCode, (void*)&szMessage[4], 4 );\n\tszCode[4] = 0;\n\tint iCode = atoi( szCode );\n\treturn ( iCode == ( ( SysTime.wMonth * 99 ^ SysTime.wDay * 33 ) ^ SysTime.wYear ) );\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnSystemMessage(HRESULT, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnNetStatus( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnNetStatus got: \" );\n\tDebugChatDef( hRes );\n\n\tif( !SUCCEEDED( hRes ) )\n\t{\n\t\t//\tIf we are waiting for a server list, this error might indicate that we're not going to\n\t\t//\tget one, so bail out of waiting for it.\n\t\tbRequestServerListWait = false;\n\t\t//\tSame for logout.\n\t\tbRequestLogoutWait = false;\n\t}\n\n\tif( hRes == CHAT_S_CON_DISCONNECTED )\n\t{\n\t\tif( bRequestLogoutWait || !bConnected )\n\t\t{\n\t\t\t//\tOk. We are waiting to logout or already have.\n\t\t\tbRequestLogoutWait = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tUh oh. We got disconnected unexpectedly.\n\t\t\tif( pOwner->bInGame )\n\t\t\t\t//\tSet flag for wolapi destruction if connection is lost during game.\n\t\t\t\tpOwner->bConnectionDown = true;\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( !pOwner->bSelfDestruct )\n\t\t\t\t{\n\t\t\t\t\t//\tSet flag for wolapi destruction.\n\t\t\t\t\tWWMessageBox().Process( TXT_WOL_WOLAPIGONE );\n\t\t\t\t\tpOwner->bSelfDestruct = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelList( HRESULT, Channel* pChannelListIn )\n{\n\tif( bIgnoreChannelLists )\t\t//\tResponse to channel lists has been temporarily turned off.\n\t{\n//\t\tdebugprint( \">>> IGNORED OnChannelList, filter = %i, WO's LastUpdateChannelCallLevel = %i \\n\", ChannelFilter, pOwner->LastUpdateChannelCallLevel );\n\t\treturn S_OK;\n\t}\n\n\t//\tSpecial case for modal GetLobbyChannels(). Because we want to be sure this OnChannelList is one that was caused\n\t//\tby a Request for gametype 0, and not one arriving from an earlier Request for games.\n\t//\tThis OnChannelList might not actually match the Request in GetLobbyChannels(), but as long as it's type 0 it'll do.\n\tif( bRequestChannelListForLobbiesWait )\n\t{\n\t\tif( pChannelListIn && pChannelListIn->type != 0 )\n\t\t{\n//\t\t\tdebugprint( \">>> IGNORED OnChannelList, bRequestChannelListForLobbiesWait if\\n\" );\n\t\t\treturn S_OK;\n\t\t}\n\t\t//\tNote: if no channels in list, can't tell what kind of Request call gave us this list.\n\t\t//\t(In our case assume it was the one asking for lobbies and allow to fail later naturally due to no lobbies available.)\n\t}\n\n\tDeleteChannelList();\n//\tdebugprint( \">>> OnChannelList, filter = %i, WO's LastUpdateChannelCallLevel = %i \\n\", ChannelFilter, pOwner->LastUpdateChannelCallLevel );\n\n\tint iLobbyCur = iChannelLobbyNumber( (unsigned char*)pOwner->szChannelNameCurrent );\n\n\tChannel* pChannelListTail = NULL;\n\n\t//\tCopy channel list to our own list.\n\twhile( pChannelListIn )\n\t{\n//\t\tdebugprint( \"OnChannelList got %s\\n\", pChannelListIn->name );\n\t\tswitch( ChannelFilter )\n\t\t{\n\t\tcase CHANNELFILTER_OFFICIAL:\n\t\t\tif( pChannelListIn->official != 1 || iChannelLobbyNumber( pChannelListIn->name ) != -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase CHANNELFILTER_UNOFFICIAL:\n\t\t\tif( pChannelListIn->official == 1 || iChannelLobbyNumber( pChannelListIn->name ) != -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase CHANNELFILTER_LOBBIES:\n\t\t{\n\t\t\tint iLobby = iChannelLobbyNumber( pChannelListIn->name );\n\t\t\tif( iLobby == -1 )\n\t\t\t{\n//\t\t\t\tdebugprint( \"(OnChannelList filtered this one.)\\n\", pChannelListIn->name );\n\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase CHANNELFILTER_LOCALLOBBYGAMES:\n\t\t\t//\tWe are listing games of our type, and may have to filter out non-local-lobby games.\n\t\t\tif( !pOwner->bAllGamesShown )\n\t\t\t{\n\t\t\t\tint iGameSourceLobby = pChannelListIn->reserved & 0x00FFFFFF;\n\t\t\t\tif( iLobbyCur == -1 || iGameSourceLobby != iLobbyCur )\n\t\t\t\t{\n\t\t\t\t\tpChannelListIn = pChannelListIn->next;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tChannel* pChannelNew = new Channel;\n\t\t*pChannelNew = *pChannelListIn;\n\t\tpChannelNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pChannelListTail )\n\t\t{\n\t\t\t//\tFirst channel in list.\n\t\t\tpChannelList = pChannelNew;\t\t//\tThis is the head of our channel list.\n\t\t\tpChannelListTail = pChannelNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpChannelListTail->next = pChannelNew;\n\t\t\tpChannelListTail = pChannelNew;\n\t\t}\n\t\tpChannelListIn = pChannelListIn->next;\n\t}\n\n//\tbRequestChannelListWait = false;\n\n\tif( bRequestChannelListForLobbiesWait )\n\t\tbRequestChannelListForLobbiesWait = false;\n\telse\n\t\tpOwner->OnChannelList();\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteChannelList()\n{\n\t//\tDelete all channels allocated on the heap.\n\t//\tpChannelList points to the head element of a linked list of channels, copied during OnChannelList().\n//\tdebugprint( \"DeleteChannelList\\n\" );\n\twhile( pChannelList )\n\t{\n\t\tChannel* pChannelHead = pChannelList;\n\t\tpChannelList = pChannelHead->next;\n\t\tdelete pChannelHead;\n\t}\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserList(HRESULT, Channel*, User* pUserListIn )\n{\n\t//\tMaintenance of users list is like that for channels list.\n//\tdebugprint( \">>> OnUserList\\n\" );\n\tDeleteUserList();\n\n\t//\tCopy channel list to our own list.\n\twhile( pUserListIn )\n\t{\n//\t\tdebugprint( \"OnUserList got %s\\n\", pUserListIn->name );\n\t\tUser* pUserNew = new User;\n\t\t*pUserNew = *pUserListIn;\n\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pUserTail )\n\t\t{\n\t\t\t//\tFirst User in list.\n\t\t\tpUserList = pUserNew;\t\t//\tThis is the head of our User list.\n\t\t\tpUserTail = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpUserTail->next = pUserNew;\n\t\t\tpUserTail = pUserNew;\n\t\t}\n\t\tpUserListIn = pUserListIn->next;\n\t}\n\n//\tbRequestUserListWait = false;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteUserList()\n{\n\t//\tDelete all Users allocated on the heap.\n\t//\tpUserList points to the head element of a linked list of Users, copied during OnUserList().\n//\tdebugprint( \"DeleteUserList\\n\" );\n\twhile( pUserList )\n\t{\n\t\tUser* pUserHead = pUserList;\n\t\tpUserList = pUserHead->next;\n\t\tdelete pUserHead;\n\t}\n\tpUserTail = NULL;\n}\n\n\n//***********************************************************************************************\n// We got a list of updates to apply\n//\nSTDMETHODIMP RAChatEventSink::OnUpdateList( HRESULT hRes, Update* pUpdateList )\n{\n//\tdebugprint( \">>> OnUpdateList got: \" );\n\tDebugChatDef( hRes );\n\n\tif( !pUpdateList )\t\t//\tShouldn't happen.\n\t\treturn S_OK;\n\n\t//\tCount the updates.\n\tint iUpdates = 0;\n\tUpdate* pUpdate\t= pUpdateList;\n\n\twhile( pUpdate != NULL )\n\t{\n\t\tpUpdate = pUpdate->next;\n\t\t++iUpdates;\n\t}\n//\tdebugprint( \"%i updates\\n\", iUpdates );\n\n\tif( WWMessageBox().Process( TXT_WOL_PATCHQUESTION, TXT_YES, TXT_NO ) == 0 )\n\t{\n\t\t//\tGet the updates. (I ignore the concept of \"optional\" downloads here.)\n\t\tif( DownloadUpdates( pUpdateList, iUpdates ) )\n\t\t\tpOwner->hresPatchResults = PATCHDOWNLOADED;\n\t\telse\n\t\t\tpOwner->hresPatchResults = PATCHAVOIDED;\n\t}\n\telse\n\t\t//\tUser says don't do the download.\n\t\t//\tSet flag to tell WolapiObject what has happened.\n\t\tpOwner->hresPatchResults = PATCHAVOIDED;\n\n\treturn S_OK;\n}\n\nextern bool WOL_Download_Dialog( IDownload* pDownload, RADownloadEventSink* pDownloadSink, const char* szTitle );\n//***********************************************************************************************\nbool RAChatEventSink::DownloadUpdates( Update* pUpdateList, int iUpdates )\n{\n\t//\tFirst we create a Download and Download Sink interface object, like Chat and ChatSink.\n\tbool bReturn = true;\n\t//\tThis is all like WolapiObject::bSetupCOMStuff().\n//debugprint( \"Do all the COM stuff.\\n\" );\n\tIDownload* pDownload;\n\tCoCreateInstance( CLSID_Download, NULL, CLSCTX_INPROC_SERVER, IID_IDownload, (void**)&pDownload );\n\t_ASSERTE( pDownload );\n\tRADownloadEventSink* pDownloadSink = new RADownloadEventSink();\n\tpDownloadSink->AddRef();\n\tIConnectionPoint*\t\t\tpConnectionPoint = NULL;\n\tIConnectionPointContainer*\tpContainer = NULL;\n\tHRESULT hRes = pDownload->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n\thRes = pContainer->FindConnectionPoint( IID_IDownloadEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n\tDWORD dwDownloadAdvise;\n\thRes = pConnectionPoint->Advise( (IDownloadEvent*)pDownloadSink, &dwDownloadAdvise );\n\t_ASSERTE(SUCCEEDED(hRes));\n\t//\tPresumably the above calls will succeed, because they did so when we did bSetupComStuff().\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\n\tUpdate* pUpdate = pUpdateList;\n\tint iUpdateCurrent = 0;\n\t//\tSave current directory.\n\tchar szCurDirSave[_MAX_PATH];\n\t::GetCurrentDirectory( _MAX_PATH, szCurDirSave );\n\twhile( pUpdate )\n\t{\n\t\t++iUpdateCurrent;\n\t\tchar szTitle[ 120 ];\n\t\tsprintf( szTitle, TXT_WOL_DOWNLOADING, iUpdateCurrent, iUpdates );\n\t\tchar fullpath[ _MAX_PATH ];\n\t\tsprintf( fullpath, \"%s\\\\%s\", pUpdate->patchpath, pUpdate->patchfile );\n\t\t//\tDownloading in WOLAPI is in a state of disarray somewhat.\n\t\t//\tMake sure the destination directory exists, and make it the current directory during the download.\n//debugprint( \"Switching to %s dir.\\n\", (char*)pUpdate->localpath );\n\t\tif( !::SetCurrentDirectory( (char*)pUpdate->localpath ) )\n\t\t{\n\t\t\t//\tCreate the destination directory.\n//\t\t\tdebugprint( \"Creating dir.\\n\" );\n\t\t\t::CreateDirectory( (char*)pUpdate->localpath, NULL );\n\t\t\t::SetCurrentDirectory( (char*)pUpdate->localpath );\n\t\t}\n\t\t//\tNote: Unknown what the reg key value is actually used for...\n//debugprint( \"Asking to download %s to %s. Server '%s', login '%s', password '%s'\\n\", fullpath, (char*)pUpdate->patchfile,\n//\t\t   (char*)pUpdate->server, (char*)pUpdate->login, (char*)pUpdate->password );\n\t\tpDownload->DownloadFile( (char*)pUpdate->server, (char*)pUpdate->login, (char*)pUpdate->password, fullpath, \n\t\t\t\t\t\t\t\t\t(char*)pUpdate->patchfile, Game_Registry_Key() );\n//\t\tdebugprint( \"Call WOL_Download_Dialog()\\n\" );\n\t\tif( !WOL_Download_Dialog( pDownload, pDownloadSink, szTitle ) )\n\t\t{\n\t\t\tbReturn = false;\n\t\t\tbreak;\n\t\t}\n\t\tpUpdate = pUpdate->next;\n\t}\n\t::SetCurrentDirectory( szCurDirSave );\n\n\t//\tUndo all the COM stuff.\n//debugprint( \"Undo all the COM stuff.\\n\" );\n\tpConnectionPoint = NULL;\n\tpContainer = NULL;\n\thRes = pDownload->QueryInterface( IID_IConnectionPointContainer, (void**)&pContainer );\n\t_ASSERTE(SUCCEEDED(hRes));\n\thRes = pContainer->FindConnectionPoint( IID_IDownloadEvent, &pConnectionPoint );\n\t_ASSERTE(SUCCEEDED(hRes));\n\tpConnectionPoint->Unadvise( dwDownloadAdvise );\n\n\tpContainer->Release();\n\tpConnectionPoint->Release();\n\t\n\tpDownload->Release();\n\tpDownloadSink->Release();\t//\tThis results in pDownloadSink deleting itself for us.\n\n\treturn bReturn;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerError( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnServerError got: \" );\n\tDebugChatDef( hRes );\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnMessageOfTheDay(HRESULT, LPCSTR)\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::ActionEggSound( const char* szMessage )\n{\n\t//\tEaster egg related.\n\tif( strstr( szMessage, \"<<groans>>\" ) || strstr( szMessage, \"<<groaning>>\" ) || \n\t\tstrstr( szMessage, \"<<dies>>\" ) || strstr( szMessage, \"<<dying>>\" ) || strstr( szMessage, \"<<groan>>\" ) ||\n\t\tstrstr( szMessage, \"<<died>>\" ) )\n\t{\n\t\tint i = rand() % 30;\n\t\tif( i == 0 )\n\t\t\tSound_Effect( VOC_DOG_HURT );\n\t\telse if( i == 1 )\n\t\t\tSound_Effect( VOC_ANTDIE );\n\t\telse\n\t\t\tSound_Effect( (VocType)( VOC_SCREAM1 + rand() % 9 ) );\n\t}\n\telse if( strstr( szMessage, \"<<whines>>\" ) || strstr( szMessage, \"<<whining>>\" ) \n\t\t|| strstr( szMessage, \"<<bitching>>\" ) || strstr( szMessage, \"<<whine>>\" ) )\n\t\tSound_Effect( VOC_DOG_WHINE );\n\telse if( strstr( szMessage, \"<<shoots>>\" ) || strstr( szMessage, \"<<shooting>>\" ) || \n\t\tstrstr( szMessage, \"<<shoot>>\" ) || strstr( szMessage, \"<<shot>>\" ) )\n\t{\n\t\tswitch( rand() % 6 )\n\t\t{\n\t\tcase 0:\t\t\tSound_Effect( VOC_CANNON1 );\t\t\tbreak;\n\t\tcase 1:\t\t\tSound_Effect( VOC_CANNON2 );\t\t\tbreak;\n\t\tcase 2:\t\t\tSound_Effect( VOC_GUN_RIFLE );\t\t\tbreak;\n\t\tcase 3:\t\t\tSound_Effect( VOC_SILENCER );\t\t\tbreak;\n\t\tcase 4:\t\t\tSound_Effect( VOC_CANNON6 );\t\t\tbreak;\n\t\tcase 5:\t\t\tSound_Effect( VOC_CANNON8 );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<explodes>>\" ) || strstr( szMessage, \"<<exploding>>\" ) || \n\t\tstrstr( szMessage, \"<<explode>>\" ) || strstr( szMessage, \"<<exploded>>\" ) ||\n\t\tstrstr( szMessage, \"<<boom>>\" ) || strstr( szMessage, \"<<nukes>>\" ) )\n\t{\n\t\tswitch( rand() % 5 )\n\t\t{\n\t\tcase 0:\t\t\tSound_Effect( VOC_KABOOM1 );\t\t\tbreak;\n\t\tcase 1:\t\t\tSound_Effect( VOC_KABOOM12 );\t\t\tbreak;\n\t\tcase 2:\t\t\tSound_Effect( VOC_KABOOM15 );\t\t\tbreak;\n\t\tcase 3:\t\t\tSound_Effect( VOC_KABOOM30 );\t\t\tbreak;\n\t\tcase 4:\t\t\tSound_Effect( VOC_KABOOM25 );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<aye>>\" ) || strstr( szMessage, \"<<ok>>\" ) ||\n\t\tstrstr( szMessage, \"<<yes>>\" ) || strstr( szMessage, \"<<yeah>>\" ) )\n\t{\n\t\tswitch( rand() % 8 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_E_AH );\t\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_E_YES );\t\t\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_THIEF_YEA );\t\t\t\tbreak;\n\t\tcase 3:\t\tSound_Effect( VOC_SPY_YESSIR );\t\t\t\tbreak;\n\t\tcase 4:\t\tSound_Effect( VOC_SPY_INDEED );\t\t\t\tbreak;\n\t\tcase 5:\t\tSound_Effect( VOC_ENG_YES );\t\t\t\tbreak;\n\t\tcase 6:\t\tSound_Effect( VOC_MED_YESSIR );\t\t\t\tbreak;\n\t\tcase 7:\t\tSound_Effect( VOC_MED_AFFIRM );\t\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<incredible>>\" ) || strstr( szMessage, \"<<adam>>\" ) || strstr( szMessage, \"<<Adam>>\" ))\n\t\tSound_Effect( VOC_E_OK );\n\telse if( strstr( szMessage, \"<<coming>>\" )|| strstr( szMessage, \"<<on my way>>\" ) || strstr( szMessage, \"<<moving out>>\" ) )\n\t{\n\t\tswitch( rand() % 5 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_SPY_ONWAY );\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_ENG_MOVEOUT );\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_SPY_KING );\t\t\t\tbreak;\n\t\tcase 3:\t\tSound_Effect( VOC_MED_MOVEOUT );\t\t\tbreak;\n\t\tcase 4:\t\tSound_Effect( VOC_THIEF_MOVEOUT );\t\t\tbreak;\n\t\t}\n\t}\n\telse if( strstr( szMessage, \"<<water>>\" ) )\n\t\tSound_Effect( VOC_SPLASH );\n\telse if( strstr( szMessage, \"<<charging>>\" ) || strstr( szMessage, \"<<powering>>\" ) )\n\t\tSound_Effect( VOC_TESLA_POWER_UP );\n\telse if( strstr( szMessage, \"<<zap>>\" ) || strstr( szMessage, \"<<zaps>>\" ) )\n\t\tSound_Effect( VOC_TESLA_ZAP );\n\telse if( strstr( szMessage, \"<<torpedo>>\" ) || strstr( szMessage, \"<<torpedoes>>\" ) )\n\t\tSound_Effect( VOC_TORPEDO );\n\telse if( strstr( szMessage, \"<<appears>>\" ) || strstr( szMessage, \"<<surfaces>>\" ) || strstr( szMessage, \"<<emerges>>\" ))\n\t\tSound_Effect( VOC_SUBSHOW );\n\telse if( strstr( szMessage, \"<<bark>>\" ) || strstr( szMessage, \"<<barks>>\" ) )\n\t\tSound_Effect( VOC_DOG_BARK );\n\telse if( strstr( szMessage, \"<<growl>>\" ) || strstr( szMessage, \"<<growls>>\" ) )\n\t\tSound_Effect( VOC_DOG_GROWL2 );\n\telse if( strstr( szMessage, \"<<chronoshift>>\" ) || strstr( szMessage, \"<<disappears>>\" ) )\n\t\tSound_Effect( VOC_CHRONO );\n\telse if( strstr( szMessage, \"<<crumble>>\" ) || strstr( szMessage, \"<<crumbles>>\" ) ||\n\t\tstrstr( szMessage, \"<<collapse>>\" ) || strstr( szMessage, \"<<collapses>>\" ) )\n\t\tSound_Effect( VOC_CRUMBLE );\n\telse if( strstr( szMessage, \"<<sell>>\" ) || strstr( szMessage, \"<<sells>>\" ) ||\n\t\tstrstr( szMessage, \"<<cash>>\" ) || strstr( szMessage, \"<<money>>\" ) )\n\t\tSound_Effect( VOC_CASHTURN );\n\telse if( strstr( szMessage, \"<<heal>>\" ) || strstr( szMessage, \"<<heals>>\" ) )\n\t\tSound_Effect( VOC_HEAL );\n\telse if( strstr( szMessage, \"<<missile>>\" ) )\n\t{\n\t\tswitch( rand() % 3 )\n\t\t{\n\t\tcase 0:\t\tSound_Effect( VOC_MISSILE_1 );\t\t\t\tbreak;\n\t\tcase 1:\t\tSound_Effect( VOC_MISSILE_2 );\t\t\t\tbreak;\n\t\tcase 2:\t\tSound_Effect( VOC_MISSILE_3 );\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateAction( HRESULT, User* pUserSender, LPCSTR szMessage )\n{\n\t//\tIgnore private messages sent to myself by myself.\n\tif( pUserSender->flags & CHAT_USER_MYSELF )\n\t\treturn S_OK;\n\n\tif( *szMessage )\n\t{\n\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 116 ];\n\t\tsprintf( szPrint, \"%s %s %s\", TXT_WOL_PRIVATE, (char*)pUserSender->name, szMessage );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\tdelete [] szPrint;\n\t\t//\tEaster egg related.\n\t\tif( pOwner->bEggSounds )\n\t\t\tActionEggSound( szMessage );\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicAction( HRESULT, Channel*, User* pUserSender, LPCSTR szMessage )\n{\n\tif( *szMessage )\n\t{\n\t\tchar* szPrint = new char[ strlen( (char*)pUserSender->name ) + strlen( szMessage ) + 110 ];\n\t\tsprintf( szPrint, \"%s %s\", (char*)pUserSender->name, szMessage );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_ACTION );\n\t\tdelete [] szPrint;\n\t\t//\tEaster egg related.\n\t\tif( pOwner->bEggSounds )\n\t\t\tActionEggSound( szMessage );\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPrivateGameOptions( HRESULT, User* pUser, LPCSTR szRequest )\n{\n//\tdebugprint( \">>> OnPrivateGameOptions\\n\" );\n//\tDebugChatDef( hRes );\n\n\tchar szRequestCopy[ 600 ];\n\tstrcpy( szRequestCopy, szRequest );\n\n\tif( pOwner->pGSupDlg )\n\t{\n\t\tif( pOwner->pGSupDlg->bHost )\n\t\t\tpOwner->pGSupDlg->ProcessGuestRequest( pUser, szRequestCopy );\n\t\telse\n\t\t\tpOwner->pGSupDlg->ProcessInform( szRequestCopy );\t\t//\tMust be private message to guest from game host.\n\t}\n//\telse\n//\t\tdebugprint( \"OnPrivateGameOptions bizarreness.\\n\" );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnPublicGameOptions( HRESULT, Channel*, User*, LPCSTR szInform )\n{\n//\tdebugprint( \">>> OnPublicGameOptions: %s\\n\", szInform );\n\n\tchar szInformCopy[ 600 ];\n\tstrcpy( szInformCopy, szInform );\n\n\tif( pOwner->pGSupDlg )\n\t{\n\t\tpOwner->pGSupDlg->ProcessInform( szInformCopy );\n\t}\n//\telse\n//\t\tdebugprint( \"OnPublicGameOptions bizarreness.\\n\" );\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnGameStart( HRESULT hRes, Channel*, User* pUserIn, int iGameID )\n{\n\t//\tNote: All players receive this, not just the host that requested it.\n\n//\tdebugprint( \">>> OnGameStart got: \" );\n\tDebugChatDef( hRes );\n\n//\tif( bRequestGameStartWait )\t\t//\tImplies user is the host that did RequestGameStart().\n//\t{\n\n\t\t//\tCreate the list of users that are actually involved in a game.\n\t\t//\tMost likely will always match pUserList, but there is a chance of someone leaving or joining\n\t\t//\tat the wrong moment, so from this point on, the pGameUserList is used.\n\n\t\t//\tNote: pUserIPList was added later, for pre-start pinging. It duplicates pGameUserList ip information,\n\t\t//\tstrictly speaking.\n\n\t\t//\tDelete any existing list.\n\t\twhile( pGameUserList )\n\t\t{\n\t\t\tUser* pGameUserHead = pGameUserList;\n\t\t\tpGameUserList = pGameUserList->next;\n\t\t\tdelete pGameUserHead;\n\t\t}\n\t\t//\tCopy incoming user list.\n\t\tUser* pGameUserListTail = NULL;\n\t\twhile( pUserIn )\n\t\t{\n//\t\t\tdebugprint( \"OnGameStart got %s\\n\", (char*)pUserIn->name );\n\t\t\tUser* pUserNew = new User;\n\t\t\t*pUserNew = *pUserIn;\n\t\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\t\tif( !pGameUserListTail )\n\t\t\t{\n\t\t\t\t//\tFirst User in list.\n\t\t\t\tpGameUserList = pUserNew;\t\t//\tThis is the head of our User list.\n\t\t\t\tpGameUserListTail = pUserNew;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpGameUserListTail->next = pUserNew;\n\t\t\t\tpGameUserListTail = pUserNew;\n\t\t\t}\n\t\t\tpUserIn = pUserIn->next;\n\t\t}\n\n\t\tbRequestGameStartWait = false;\n//\t}\n\n//\tdebugprint( \"iGameID is %i\\n\", iGameID );\n\tthis->iGameID = iGameID;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nunsigned long RAChatEventSink::GetPlayerGameIP( const char* szPlayerName ) const\n{\n\t//\tReturns ipaddr value of player if found in pGameUserList, else 0.\n\tUser* pUser = pGameUserList;\n\twhile( pUser )\n\t{\n\t\tif( _stricmp( (char*)pUser->name, szPlayerName ) == 0 )\n\t\t\treturn pUser->ipaddr;\n\t\tpUser = pUser->next;\n\t}\n\treturn 0;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserKick( HRESULT hRes, Channel*, User* pUserKicked,  User* pUserKicker )\n{\n//\tdebugprint( \">>> OnUserKick got: \" );\n\tDebugChatDef( hRes );\n\n\tif( hRes == S_OK )\n\t{\n\t\t//\tSomeone was kicked.\n\t\t//\tFake a call to OnChannelLeave(), as the processing is identical.\n\t\tOnChannelLeave( S_OK, NULL, pUserKicked );\n\t\tif( pUserKicked->flags & CHAT_USER_MYSELF )\n\t\t{\n\t\t\t//\tTrigger a channel exit later on, when we have left this callback.\n\t\t\tbGotKickedTrigger = true;\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserKicker->name ) + strlen( TXT_WOL_USERKICKEDYOU ) + 5 ];\n\t\t\tsprintf( szPrint, TXT_WOL_USERKICKEDYOU, (char*)pUserKicker->name );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\t\tdelete [] szPrint;\n\t\t\t//\tEnsure that the bGotKickedTrigger is acted upon immediately...\n\t\t\tpOwner->dwTimeNextWolapiPump = ::timeGetTime();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchar* szPrint = new char[ strlen( (char*)pUserKicker->name ) + strlen( (char*)pUserKicked->name ) + \n\t\t\t\t\t\t\t\t\t\tstrlen( TXT_WOL_USERKICKEDUSER ) + 5 ];\n\t\t\tsprintf( szPrint, TXT_WOL_USERKICKEDUSER, (char*)pUserKicker->name, (char*)pUserKicked->name );\n\t\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\t\tdelete [] szPrint;\n\t\t}\n\t\tswitch( rand() % 4 )\n\t\t{\n\t\tcase 0:\n\t\t\tSound_Effect( VOC_TANYA_CHEW );\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tSound_Effect( VOC_TANYA_LAUGH );\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tSound_Effect( VOC_TANYA_CHING );\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tSound_Effect( VOC_TANYA_KISS );\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t//\tYou tried to kick someone, but the user wasn't found.\n\t\t//\tIgnore.\n//\t\tdebugprint( \"OnUserKick non S_OK value\\n\" );\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserIP( HRESULT hRes, User* pUser )\n{\n\t//\tA list of users is kept, separate from other user lists, to preserve the ipaddr's we've found through this\n\t//\tcallback. OnUserList (for some dumb reason) doesn't hold valid ipaddr's, so we have to go through\n\t//\tall this rigamarole...\n\t//\t(List is cleared when entering game channel. Users are added initially and on joins, not removed on leaves.)\n//\tdebugprint( \">>> OnUserIP got: \" );\n\tDebugChatDef( hRes );\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n\t\t//\tLook for user in our current users list.\n\t\tUser* pUserSearch = pUserIPList;\n\t\twhile( pUserSearch )\n\t\t{\n\t\t\tif( _stricmp( (char*)pUserSearch->name, (char*)pUser->name ) == 0 )\n\t\t\t{\n\t\t\t\t//\tFound matching user. Replace it's ipaddr value, in case it changed.(?)\n\t\t\t\tpUserSearch->ipaddr = pUser->ipaddr;\n\t\t\t\treturn S_OK;\n\t\t\t}\n\t\t\tpUserSearch = pUserSearch->next;\n\t\t}\n\t\t//\tUser not found in current list. Add.\n\t\tUser* pUserNew = new User;\n\t\t*pUserNew = *pUser;\n\t\tpUserNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\tif( !pUserIPListTail )\n\t\t{\n\t\t\t//\tFirst user in list.\n\t\t\tpUserIPList = pUserNew;\t\t//\tThis is the head of our list.\n\t\t\tpUserIPListTail = pUserNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpUserIPListTail->next = pUserNew;\n\t\t\tpUserIPListTail = pUserNew;\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RAChatEventSink::DeleteUserIPList()\n{\n\t//\tSame as DeleteUserList but for pUserIPList.\n//\tdebugprint( \"DeleteUserIPList\\n\" );\n\twhile( pUserIPList )\n\t{\n\t\tUser* pUserHead = pUserIPList;\n\t\tpUserIPList = pUserHead->next;\n\t\tdelete pUserHead;\n\t}\n\tpUserIPListTail = NULL;\n}\n\n//***********************************************************************************************\nunsigned long RAChatEventSink::GetUserIP( const char* szName ) const\n{\n\t//\tLooks in pUserIPList for the ipaddr of user with name szName.\n\t//\tThis is used only while in game channels.\n\t//\tThis is for step 2 in acquiring fellow player ping times. To get the IP addresses into pUserIPList\n\t//\twe had to go through request/callbacks. Now pings are requested on these addresses, and the results\n\t//\ttallied in NetUtilSink for our retrieval later.\n\t//\tReturns 0 if not found.\n\n\t//\tFind szName in list.\n\tUser* pUser = pUserIPList;\n\twhile( pUser )\n\t{\n\t\tif( _stricmp( (char*)pUser->name, szName ) == 0 )\n\t\t\treturn pUser->ipaddr;\n\t\tpUser = pUser->next;\n\t}\n\treturn 0;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerError(HRESULT , LPCSTR )\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnServerBannedYou(HRESULT , time_t )\n{\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnUserFlags( HRESULT hRes, LPCSTR name, unsigned int flags, unsigned int )\n{\n//\tdebugprint( \">>> OnUserFlags got: \" );\n\tDebugChatDef( hRes );\n\n\tif( pOwner->CurrentLevel == WOL_LEVEL_INGAMECHANNEL )\n\t{\n\t\tif( pOwner->pGSupDlg && \n\t\t\t( pOwner->pGSupDlg->bHostSayGo || pOwner->pGSupDlg->bHostWaitingForGoTrigger || \n\t\t\t\tpOwner->pGSupDlg->bExitForGameTrigger || iGameID ) )\n\t\t{\n\t\t\t//\tA game has this moment entered the \"must start\" phase. We must ignore the fact that others are leaving the channel.\n//\t\t\tdebugprint( \"Ignoring OnUserFlags because game is starting.\\n\" );\t\t//\t(Shouldn't ever happen.)\n\t\t\treturn S_OK;\n\t\t}\n\t}\n\n\t//\tFind user in our current users list.\n\tUser* pUserPrior = NULL;\n\tUser* pUserSearch = pUserList;\n\twhile( pUserSearch )\n\t{\n\t\tif( _stricmp( (char*)pUserSearch->name, name ) == 0 )\n\t\t{\n\t\t\t//\tSet user's flags to new value.\n\t\t\tpUserSearch->flags = flags;\n\t\t\t\n\t\t\t//\tRemove user from userlist and reinsert appropriately sorted.\n\t\t\tif( !pUserPrior )\n\t\t\t{\n\t\t\t\t//\tUser was head of list.\n\t\t\t\tpUserList = pUserSearch->next;\n\t\t\t\tif( pUserSearch == pUserTail )\n\t\t\t\t\t//\tUser was also tail of list.\n\t\t\t\t\tpUserTail = NULL;\n\t\t\t\telse\n\t\t\t\t\tpUserSearch->next = NULL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//\tUser was not head of list.\n\t\t\t\tpUserPrior->next = pUserSearch->next;\n\t\t\t\tif( pUserSearch == pUserTail )\n\t\t\t\t\t//\tUser was tail of list.\n\t\t\t\t\tpUserTail = pUserPrior;\n\t\t\t\telse\n\t\t\t\t\tpUserSearch->next = NULL;\n\t\t\t}\n\t\t\tInsertUserSorted( pUserSearch );\n\n\t\t\t//\tUpdate shown list.\n\t\t\tpOwner->ListChannelUsers();\n\t\t\tbreak;\n\t\t}\n\t\tpUserPrior = pUserSearch;\n\t\tpUserSearch = pUserSearch->next;\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RAChatEventSink::OnChannelBan( HRESULT , LPCSTR name, int banned )\n{\n\tif( banned && strcmp( name, \"*\" ) != 0 )\n\t{\n\t\tchar* szPrint = new char[ strlen( name ) + strlen( TXT_WOL_USERWASBANNED ) + 5 ];\n\t\tsprintf( szPrint, TXT_WOL_USERWASBANNED, name );\n\t\tpOwner->PrintMessage( szPrint, WOLCOLORREMAP_KICKORBAN );\n\t\tdelete [] szPrint;\n\t}\n\t\n\treturn S_OK;\n}\n\n\n//***********************************************************************************************\n//***********************************************************************************************\nRADownloadEventSink::RADownloadEventSink() :\n\tbFlagEnd( false ),\n\tbFlagError( false ),\n\tbFlagProgressUpdate( false ),\n\tbFlagStatusUpdate( false ),\n\tbFlagQueryResume( false )\n{\n\tm_cRef=0;\t\t// Ref counter\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRADownloadEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n\tif ((iid == IID_IUnknown) ||(iid == IID_IDownloadEvent))\n\t{\n\t\t*ppv = (IDownloadEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRADownloadEventSink::AddRef()\n{\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRADownloadEventSink::Release()\n{\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnEnd(void)\n{\n//\tdebugprint( \">>> OnEnd\\n\" );\n\tbFlagEnd = true;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnError( int /*iCode*/ )\n{\n//\tdebugprint( \">>> OnError got: %i\\n\", iCode );\n//#define DOWNLOADEVENT_NOSUCHSERVER\t\t1\n//#define DOWNLOADEVENT_COULDNOTCONNECT\t\t2\n//#define DOWNLOADEVENT_LOGINFAILED\t\t\t3\n//#define DOWNLOADEVENT_NOSUCHFILE\t\t\t4\n//#define DOWNLOADEVENT_LOCALFILEOPENFAILED\t5\n//#define DOWNLOADEVENT_TCPERROR\t\t\t6\n//#define DOWNLOADEVENT_DISCONNECTERROR\t\t7\n\n\tbFlagError = true;\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft )\n{\n//\tdebugprint( \">>> OnProgressUpdate\\n\" );\n\tbFlagProgressUpdate = true;\n\n\tiBytesRead = bytesread;\n\tiTotalSize = totalsize;\n\tiTimeTaken = timetaken;\n\tiTimeLeft = timeleft;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RADownloadEventSink::OnStatusUpdate( int status )\n{\n//\tdebugprint( \">>> OnStatusUpdate, status = %i\\n\", status );\n\tbFlagStatusUpdate = true;\n\n\tiStatus = status;\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\n// Just tell the FTP module to go ahead and resume\n//\nSTDMETHODIMP RADownloadEventSink::OnQueryResume()\n{\n//\tdebugprint( \">>> OnQueryResume\\n\" );\n\tbFlagQueryResume = true;\n\n\tbResumed = true;\n\n\treturn DOWNLOADEVENT_RESUME;\n}\n\n\n//***********************************************************************************************\n//***********************************************************************************************\nRANetUtilEventSink::RANetUtilEventSink( WolapiObject* pOwnerIn ) : m_cRef( 0 ), \t//\tinit the reference count\n\tpOwner( pOwnerIn ),\n\tpLadderList( NULL ),\n\tpLadderTail( NULL ),\n\tpLadderListAM( NULL ),\n\tpLadderTailAM( NULL )\n{\n//\tdebugprint( \"RANetUtilEventSink constructor\\n\" );\n}\n\n//***********************************************************************************************\nRANetUtilEventSink::~RANetUtilEventSink()\n{\n//\tdebugprint( \"RANetUtilEventSink destructor\\n\" );\n\tDeleteLadderList();\n}\n\n//\t\t\tInterface IUnknown Methods\n//***********************************************************************************************\n// QueryInterface\n//\nHRESULT __stdcall\nRANetUtilEventSink::QueryInterface(const IID& iid, void** ppv)\n{\n//\tdebugprint( \"RANetUtilEventSink::QueryInterface\\n\" );\n\tif ((iid == IID_IUnknown) ||(iid == IID_INetUtilEvent))\n\t{\n\t\t*ppv = (INetUtilEvent*)this;\t\t//\tRemoved static_cast<> ajw\n\t}\n\telse\n\t{\n\t\t*ppv = NULL;\n\t\treturn E_NOINTERFACE;\n\t}\n\t((IUnknown*)(*ppv))->AddRef();\t\t//\tRemoved reinterpret_cast<> ajw\n\treturn S_OK ;\n}\n\n//***********************************************************************************************\n// AddRef\n//\nULONG __stdcall\nRANetUtilEventSink::AddRef()\n{\n//\tdebugprint( \"RANetUtilEventSink::AddRef\\n\" );\n\treturn InterlockedIncrement(&m_cRef) ;\n}\n\n//***********************************************************************************************\n// Release\n//\nULONG __stdcall\nRANetUtilEventSink::Release()\n{\n//\tdebugprint( \"RANetUtilEventSink::Release\\n\" );\n\tif (InterlockedDecrement(&m_cRef) == 0)\n\t{\n\t\tdelete this ;\n\t\treturn 0 ;\n\t}\n\treturn m_cRef;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnGameresSent( HRESULT hRes )\n{\n//\tdebugprint( \">>> OnGameresSent got: \" );\n\tDebugChatDef( hRes );\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnLadderList( HRESULT hRes, Ladder* pLadderListIn, int /*totalCount*/, long /*timeStamp*/, int /*keyRung*/ )\n{\n\t//\tMaintenance of ladders list is like that for channels list above.\n\t//\tDeleteLadderList();\t\t-> This is done once, before a set of RequestLadderList() calls are made.\n//\tdebugprint( \">>> OnLadderList got: \" );\n\tDebugChatDef( hRes );\n\n\tif( SUCCEEDED( hRes ) )\n\t{\n//\t\tdebugprint( \"(SUCCEEDED)\\n\" );\n\t\t//\tCopy ladder list to our own list.\n\t\twhile( pLadderListIn )\n\t\t{\n//\t\t\tdebugprint( \"OnLadderList got %s, rung %u\\n\", pLadderListIn->login_name, pLadderListIn->rung );\n\t\t\tif( *pLadderListIn->login_name != 0 && pLadderListIn->rung != -1 )\n\t\t\t{\n\t\t\t\tLadder* pLadderNew = new Ladder;\n\t\t\t\t*pLadderNew = *pLadderListIn;\n\t\t\t\tpLadderNew->next = NULL;\t\t\t//\t(We don't want the value that was just copied!)\n\t\t\t\tif( pLadderNew->sku == LADDER_CODE_RA )\n\t\t\t\t{\n\t\t\t\t\tif( !pLadderTail )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tFirst Ladder in list.\n\t\t\t\t\t\tpLadderList = pLadderNew;\t\t//\tThis is the head of our Ladder list.\n\t\t\t\t\t\tpLadderTail = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpLadderTail->next = pLadderNew;\n\t\t\t\t\t\tpLadderTail = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\tif( _stricmp( (char*)pLadderNew->login_name, pOwner->szMyName ) == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tSet up local player's win/loss string.\n\t\t\t\t\t\tsprintf( pOwner->szMyRecord, TXT_WOL_PERSONALWINLOSSRECORD, pOwner->szMyName, \n\t\t\t\t\t\t\t\t\tpLadderNew->rung, pLadderNew->wins, pLadderNew->losses, pLadderNew->points );\n\t\t\t\t\t\tpOwner->bMyRecordUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\t\t//\tsku must be LADDER_CODE_AM\n\t\t\t\t{\n\t\t\t\t\tif( !pLadderTailAM )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tFirst Ladder in list.\n\t\t\t\t\t\tpLadderListAM = pLadderNew;\t\t//\tThis is the head of our Ladder list.\n\t\t\t\t\t\tpLadderTailAM = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpLadderTailAM->next = pLadderNew;\n\t\t\t\t\t\tpLadderTailAM = pLadderNew;\n\t\t\t\t\t}\n\t\t\t\t\tif( _stricmp( (char*)pLadderNew->login_name, pOwner->szMyName ) == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t//\tSet up local player's win/loss string for Aftermath.\n\t\t\t\t\t\tsprintf( pOwner->szMyRecordAM, TXT_WOL_PERSONALWINLOSSRECORDAM, pOwner->szMyName, \n\t\t\t\t\t\t\t\t\tpLadderNew->rung, pLadderNew->wins, pLadderNew->losses, pLadderNew->points );\n\t\t\t\t\t\tpOwner->bMyRecordUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tpLadderListIn = pLadderListIn->next;\n\t\t}\n\t\t//\tUpdate shown list.\n\t\tpOwner->ListChannelUsers();\n\t}\n\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nSTDMETHODIMP RANetUtilEventSink::OnPing( HRESULT hRes, int time, unsigned long ip, int /*handle*/ )\n{\n\tif( pOwner->bDoingDisconnectPinging )\n\t{\n//\t\tdebugprint( \">>> OnPing got : ip %i, time %i, \", ip, time );\n\t\tDebugChatDef( hRes );\n\n\t\tif( ip == pOwner->TournamentOpponentIP )\n\t\t{\n\t\t\t//\tThis is the result of the opponent ping.\n\t\t\tif( time != -1 )\n\t\t\t\tpOwner->DisconnectPingResult_Opponent[ pOwner->iDisconnectPingCurrent ] = PING_GOOD;\n\t\t\telse\n\t\t\t\tpOwner->DisconnectPingResult_Opponent[ pOwner->iDisconnectPingCurrent ] = PING_BAD;\n//\t\t\tdebugprint( \"Set ping #%i for Opponent\\n\", pOwner->iDisconnectPingCurrent );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//\tThis is the result of the game server ping.\n\t\t\tif( time != -1 )\n\t\t\t\tpOwner->DisconnectPingResult_Server[ pOwner->iDisconnectPingCurrent ] = PING_GOOD;\n\t\t\telse\n\t\t\t\tpOwner->DisconnectPingResult_Server[ pOwner->iDisconnectPingCurrent ] = PING_BAD;\n//\t\t\tdebugprint( \"Set ping #%i for Server\\n\", pOwner->iDisconnectPingCurrent );\n\t\t}\n\t}\n\treturn S_OK;\n}\n\n//***********************************************************************************************\nvoid RANetUtilEventSink::DeleteLadderList()\n{\n//\tdebugprint( \"DeleteLadderList()\\n\" );\n\t//\tDelete all Ladders allocated on the heap.\n\twhile( pLadderList )\n\t{\n\t\tLadder* pLadderHead = pLadderList;\n\t\tpLadderList = pLadderHead->next;\n\t\tdelete pLadderHead;\n\t}\n\tpLadderTail = NULL;\n}\n\n//***********************************************************************************************\nunsigned int RANetUtilEventSink::GetUserRank( const char* szName, bool bRankRA )\n{\n\t//\tSearches for szName in ladder list, returns player rank if found, else 0.\n\t//\tSlow linear search.\n\t//\tIf bRankRA, returns RA rank, else returns AM rank.\n//\tdebugprint( \"GetUserRank: Asked for %s, \", szName );\n\tLadder* pLad;\n\tif( bRankRA )\n\t\tpLad = pLadderList;\n\telse\n\t\tpLad = pLadderListAM;\n\n\twhile( pLad )\n\t{\n//\t\tdebugprint( \"  comparing %s\\n\", (char*)pLad->login_name );\n\t\tif( _stricmp( (char*)pLad->login_name, szName ) == 0 )\n\t\t{\n//\t\t\tdebugprint( \"found rung value %u\\n\", pLad->rung );\n\t\t\treturn pLad->rung;\n\t\t}\n\t\tpLad = pLad->next;\n\t}\n//\tdebugprint( \"couldn't find in my ladder list.\\n\", szName );\n\n\treturn 0;\n}\n\n//***********************************************************************************************\n//***********************************************************************************************\nvoid ChatDefAsText( char* szDesc, HRESULT hRes )\n{\n\t//\tSets szDesc to the text meaning of hRes.\n\t//\tMake sure szDesc is as long as the longest of the below.\n\tswitch( hRes )\n\t{\n\tcase CHAT_E_NICKINUSE       :\n\t\tsprintf( szDesc, \"Your nick is still logged into chat\" );\n\t\tbreak;\n\tcase CHAT_E_BADPASS         :\n\t\tsprintf( szDesc, \"Your password is incorrect during login\" );\n\t\tbreak;\n\tcase CHAT_E_NONESUCH\t\t   :\n\t\tsprintf( szDesc, \"Reference made to non-existant user or channel\" );\n\t\tbreak;\n\tcase CHAT_E_CON_NETDOWN        :\n\t\tsprintf( szDesc, \"The network layer is down or cannot be initialized for some reason\" );\n\t\tbreak;\n\tcase CHAT_E_CON_LOOKUP_FAILED  :\n\t\tsprintf( szDesc, \"Name lookup (e.g DNS) failed for some reason\" );\n\t\tbreak;\n\tcase CHAT_E_CON_ERROR          :\n\t\tsprintf( szDesc, \"Some fatal error occured with the net connection\" );\n\t\tbreak;\n\tcase CHAT_E_TIMEOUT            :\n\t\tsprintf( szDesc, \"General request timeout for a request\" );\n\t\tbreak;\n\tcase CHAT_E_MUSTPATCH        :\n\t\tsprintf( szDesc, \"Must patch before continuing\" );\n\t\tbreak;\n\tcase CHAT_E_STATUSERROR\t\t:\n\t\tsprintf( szDesc, \"Miscellaneous internal status error\" );\n\t\tbreak;\n\tcase CHAT_E_UNKNOWNRESPONSE\t:\n\t\tsprintf( szDesc, \"Server has returned something we don't recognise\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELFULL\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel that has enough players already\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELEXISTS\t:\n\t\tsprintf( szDesc, \"Tried to create a channel that already exists\" );\n\t\tbreak;\n\tcase CHAT_E_CHANNELDOESNOTEXIST\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel that does not exist\" );\n\t\tbreak;\n\tcase CHAT_E_BADCHANNELPASSWORD\t\t:\n\t\tsprintf( szDesc, \"Tried to join a channel with the wrong password\" );\n\t\tbreak;\n\tcase CHAT_E_BANNED            :\n\t\tsprintf( szDesc, \"You've been banned from the server / channel\" );\n\t\tbreak;\n\tcase CHAT_E_NOT_OPER           :\n\t\tsprintf( szDesc, \"You tried to do something that required operator status\" );\n\t\tbreak;\n\n\tcase CHAT_S_CON_CONNECTING     :\n\t\tsprintf( szDesc, \"A network connection is underway\" );\n\t\tbreak;\n\tcase CHAT_S_CON_CONNECTED      :\n\t\tsprintf( szDesc, \"A network connection is complete\" );\n\t\tbreak;\n\tcase CHAT_S_CON_DISCONNECTING  :\n\t\tsprintf( szDesc, \"A network connection is going down\" );\n\t\tbreak;\n\tcase CHAT_S_CON_DISCONNECTED   :\n\t\tsprintf( szDesc, \"A network connection is closed\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_NOTHERE   :\n\t\tsprintf( szDesc, \"Find - Nick not in system\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_NOCHAN   :\n\t\tsprintf( szDesc, \"Find - Not in any channels\" );\n\t\tbreak;\n\tcase CHAT_S_FIND_OFF   :\n\t\tsprintf( szDesc, \"Find - user has find turned off\" );\n\t\tbreak;\n\tcase CHAT_S_PAGE_NOTHERE   :\n\t\tsprintf( szDesc, \"Page - Nick not in system\" );\n\t\tbreak;\n\tcase CHAT_S_PAGE_OFF   :\n\t\tsprintf( szDesc, \"Page - user has page turned off\" );\n\t\tbreak;\n\tcase CHAT_E_NOTCONNECTED    :\n\t\tsprintf( szDesc, \"You are not connected to the chat server\" );\n\t\tbreak;\n\tcase CHAT_E_NOCHANNEL       :\n\t\tsprintf( szDesc, \"You are not in a channel\" );\n\t\tbreak;\n\tcase CHAT_E_NOTIMPLEMENTED  :\n\t\tsprintf( szDesc, \"Feature is not implemented\" );\n\t\tbreak;\n\tcase CHAT_E_PENDINGREQUEST  :\n\t\tsprintf( szDesc, \"The request was made while while a conflicting request was still pending\" );\n\t\tbreak;\n\tcase CHAT_E_PARAMERROR\t   :\n\t\tsprintf( szDesc, \"Invalid parameter passed - usually a NULL pointer\" );\n\t\tbreak;\n\tcase CHAT_E_LEAVECHANNEL\t\t:\n\t\tsprintf( szDesc, \"Tried to create or join a channel before leaving the previous one\" );\n\t\tbreak;\n\tcase CHAT_E_JOINCHANNEL\t\t:\n\t\tsprintf( szDesc, \"Tried to send something to a channel when not a member of any channel\" );\n\t\tbreak;\n\tcase CHAT_E_UNKNOWNCHANNEL\t:\n\t\tsprintf( szDesc, \"Tried to join a non-existant channel\" );\n\t\tbreak;\n\tcase S_OK:\n\t\tsprintf( szDesc, \"S_OK\" );\n\t\tbreak;\n\tcase E_FAIL:\n\t\tsprintf( szDesc, \"E_FAIL\" );\n\t\tbreak;\n\tdefault:\n\t\tsprintf( szDesc, \"ERROR - Value not recognized!\" );\n\t\tbreak;\n\t}\n\t//\tAppend NetUtil errors.\n\tswitch( hRes )\n\t{\n\tcase NETUTIL_E_ERROR:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_E_ERROR\" );\n\t\tbreak;\n\tcase NETUTIL_E_BUSY:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_E_BUSY\"  );\n\t\tbreak;\n\tcase NETUTIL_S_FINISHED:\n\t\tstrcat( szDesc, \"  NetUtil: NETUTIL_S_FINISHED\" );\n\t\tbreak;\n\t}\n}\n\n//***********************************************************************************************\nvoid DebugChatDef( HRESULT hRes )\n{\n\tchar szText[200];\n\tChatDefAsText( szText, hRes );\n//\tdebugprint( \"%s\\n\", szText );\n}\n\n//***********************************************************************************************\nint iChannelLobbyNumber( const unsigned char* szChannelName )\n{\n\t//\tReturns lobby number of channel, or -1 for \"channel is not a lobby\".\n\tif( strncmp( (char*)szChannelName, LOB_PREFIX, strlen( LOB_PREFIX ) ) == 0 )\n\t{\n\t\tchar szNum[10];\n\t\tstrcpy( szNum, (char*)szChannelName + strlen( LOB_PREFIX ) );\n//\t\tdebugprint( \" ^ iChannelLobbyNumber returning atoi of %s\\n\", szNum );\n\t\treturn atoi( szNum );\n\t}\n\telse\n\t\treturn -1;\n}\n\n//***********************************************************************************************\nvoid InterpretLobbyNumber( char* szLobbyNameToSet, int iLobby )\n{\n\t//\tHard-coded translation of lobby number to apparent lobby name.\n\tswitch( iLobby )\n\t{\n\tcase 0:\n\t\tstrcpy( szLobbyNameToSet, \"Combat Alley\" );\n\t\tbreak;\n\tcase 1:\n\t\tstrcpy( szLobbyNameToSet, \"No Man's Land\" );\n\t\tbreak;\n\tcase 2:\n\t\tstrcpy( szLobbyNameToSet, \"Hell's Pass\" );\n\t\tbreak;\n\tcase 3:\n\t\tstrcpy( szLobbyNameToSet, \"Lost Vegas\" );\n\t\tbreak;\n\tcase 4:\n\t\tstrcpy( szLobbyNameToSet, \"Death Valley\" );\n\t\tbreak;\n\tcase 5:\n\t\tstrcpy( szLobbyNameToSet, \"The Wastelands\" );\n\t\tbreak;\n\tcase 6:\n\t\tstrcpy( szLobbyNameToSet, \"Isle of Fury\" );\n\t\tbreak;\n\tcase 7:\n\t\tstrcpy( szLobbyNameToSet, \"Armourgarden\" );\n\t\tbreak;\n\tcase 8:\n\t\tstrcpy( szLobbyNameToSet, \"The Hive\" );\n\t\tbreak;\n\tcase 9:\n\t\tstrcpy( szLobbyNameToSet, \"North by Northwest\" );\n\t\tbreak;\n\tcase 10:\n\t\tstrcpy( szLobbyNameToSet, \"Decatur High\" );\n\t\tbreak;\n\tcase 11:\n\t\tstrcpy( szLobbyNameToSet, \"Damnation Alley\" );\n\t\tbreak;\n\tdefault:\n\t\tsprintf( szLobbyNameToSet, \"%ith Division\", iLobby );\n\t\tbreak;\n\t}\n}\n\n#endif"
  },
  {
    "path": "REDALERT/RAWOLAPI.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n#ifndef WIN32\n#error WOLAPI_INTEGRATION can't be specified for non WIN32 version!\n#endif\n\n//\trawolapi.h - WOLAPI sinks declarations.\n//\tajw 07/10/98\n\n//\tBased somewhat on Neal's Borlandized version, \"chatapi.h\".\n\n#ifndef RAWOLAPI_H\n#define RAWOLAPI_H\n\n#include \"function.h\"\n\n//#include \"cominit.h\"\n#include <stdio.h>\n\n//\tFrom OBJBASE.H\n#define interface struct\n\n//\tFrom RPCNDR.H\n#define DECLSPEC_UUID(x)\n\n#include <commctrl.h>\n\n//namespace WOL\t\t//\tnamespace is workaround due to the use of \"Server\" as a global in Red Alert.\n//\tajw - Can't use namespaces in Watcom 10.5 it seems...\n//{\n\t#include \"wolapi\\wolapi.h\"\n\t#define IID_DEFINED\n\t//#include \"wlib/wdebug.h\"\n\t#include \"wolapi\\chatdefs.h\"\n\t#include \"wolapi\\downloaddefs.h\"\n\t#include \"wolapi\\ftpdefs.h\"\n//};\n//using namespace WOL;\n#include <winerror.h>\n//#include <ocidl.h>\n#include <olectl.h>\n\n//***********************************************************************************************\n//\tFor debugging chat defined hresults...\nvoid ChatDefAsText( char* szDesc, HRESULT hRes );\nvoid DebugChatDef( HRESULT hRes );\n\nint iChannelLobbyNumber( const unsigned char* szChannelName );\n#define REASONABLELOBBYINTERPRETEDNAMELEN\t50\nvoid InterpretLobbyNumber( char* szLobbyNameToSet, int iLobby );\n\nclass WolapiObject;\n\n#define MAXCHATSENDLENGTH 71\t//\tMainly aesthetic, and because of the length of edit line.\n\nenum CHANNELFILTER\n{\n\tCHANNELFILTER_NO,\n\tCHANNELFILTER_OFFICIAL,\n\tCHANNELFILTER_UNOFFICIAL,\n\tCHANNELFILTER_LOBBIES,\n\tCHANNELFILTER_LOCALLOBBYGAMES,\n};\n\n#define WOLCOLORREMAP_ACTION\t\t\tPCOLOR_GREY\n#define WOLCOLORREMAP_SELFSPEAKING\t\tPCOLOR_RED\n#define WOLCOLORREMAP_LOCALMACHINEMESS\tPCOLOR_REALLY_BLUE\t\t//\tColor of system messages that originate locally.\n#define WOLCOLORREMAP_PAGE\t\t\t\tPCOLOR_GOLD\n#define WOLCOLORREMAP_KICKORBAN\t\t\tPCOLOR_GREEN\t//LTBLUE\n#define WOLCOLORREMAP_PUBLICMESSAGE\t\tPCOLOR_NONE\n#define WOLCOLORREMAP_PRIVATEMESSAGE\tPCOLOR_ORANGE\n\n#define WOLSOUND_ERROR\t\t\t\t\tVOC_SYS_ERROR\n#define WOLSOUND_LOGIN\t\t\t\t\tVOC_RADAR_ON\n#define WOLSOUND_LOGOUT\t\t\t\t\tVOC_RADAR_OFF\n#define WOLSOUND_ENTERCHAN\t\t\t\tVOC_PLAYER_JOINED\n#define WOLSOUND_EXITCHAN\t\t\t\tVOC_PLAYER_LEFT\n#define WOLSOUND_ONPAGE\t\t\t\t\tVOC_INCOMING_MESSAGE\n#define WOLSOUND_KICKORBAN\t\t\t\tVOC_TANYA_KISS\n#define WOLSOUND_ENTERGAME\t\t\t\tVOC_INVULNERABLE\n#define WOLSOUND_EXITGAME\t\t\t\tVOC_DOOR\n\nenum DISCONNECT_PING_STATUS\n{\n\tPING_UNSTARTED,\n\tPING_WAITING,\n\tPING_GOOD,\n\tPING_BAD,\n};\n#define DISCONNECT_PING_COUNT\t\t5\n\n//***********************************************************************************************\nclass RAChatEventSink : /////public CComObjectRoot, /////public IConnectionPoint,\n\tpublic IChatEvent\n{\n public:\n\tRAChatEventSink( WolapiObject* pOwner );\n\tvirtual ~RAChatEventSink();\n\n//    BEGIN_COM_MAP(RAChatEventSink)\n//\t  COM_INTERFACE_ENTRY(IChatEvent)\n//    END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// IChatEvent\n\tSTDMETHOD(OnServerList)(HRESULT res, Server* servers);\n\tSTDMETHOD(OnLogout)(HRESULT r, User *user);\n\tSTDMETHOD(OnBusy)(HRESULT r);\n\tSTDMETHOD(OnIdle)(HRESULT r);\n\tSTDMETHOD(OnPageSend)(HRESULT r);\n\tSTDMETHOD(OnPaged)(HRESULT r, User *, LPCSTR);\n\tSTDMETHOD(OnFind)(HRESULT r, Channel *);\n\tSTDMETHOD(OnConnection)(HRESULT r,LPCSTR motd);\n\tSTDMETHOD(OnChannelCreate)(HRESULT r, Channel *channel);\n\tSTDMETHOD(OnChannelModify)(HRESULT r, Channel *channel);\n\tSTDMETHOD(OnChannelJoin)(HRESULT r,  Channel *channel,  User *user);\n\tSTDMETHOD(OnChannelLeave)(HRESULT r, Channel *channel,  User *user);\n\tSTDMETHOD(OnChannelTopic)(HRESULT r, Channel *channel,  LPCSTR topic);\n\tSTDMETHOD(OnGroupList)(HRESULT r,  Group *);\n\tSTDMETHOD(OnPublicMessage)(HRESULT r,  Channel *channel, User *user, LPCSTR text);\n\tSTDMETHOD(OnPrivateMessage)(HRESULT r,  User *user,LPCSTR text);\n\tSTDMETHOD(OnSystemMessage)(HRESULT r, LPCSTR);\n\tSTDMETHOD(OnNetStatus)(HRESULT r);\n\tSTDMETHOD(OnChannelList)(HRESULT r, Channel* channels);\n\tSTDMETHOD(OnUserList)(HRESULT r, Channel* channel, User* users);\n\tSTDMETHOD(OnUpdateList)(HRESULT res, Update *);\n\tSTDMETHOD(OnServerError)(HRESULT res);\n\tSTDMETHOD(OnMessageOfTheDay)(HRESULT res, LPCSTR);\n\tSTDMETHOD(OnPrivateAction)(HRESULT r, User *,  LPCSTR);\n\tSTDMETHOD(OnPublicAction)(HRESULT r, Channel *, User *,  LPCSTR);\n\tSTDMETHOD(OnPrivateGameOptions)(HRESULT r, User *,  LPCSTR);\n\tSTDMETHOD(OnPublicGameOptions)(HRESULT r, Channel *, User *,  LPCSTR);\n\tSTDMETHOD(OnGameStart)(HRESULT r, Channel *, User *,  int);\n\tSTDMETHOD(OnUserKick)(HRESULT r, Channel *, User *,  User *);\n\tSTDMETHOD(OnUserIP)(HRESULT r, User *);\n\tSTDMETHOD(OnServerError)(HRESULT res, LPCSTR ircmsg);\n\tSTDMETHOD(OnServerBannedYou)(HRESULT r, time_t bannedTill);\n\tSTDMETHOD(OnUserFlags)(HRESULT r, LPCSTR name, unsigned int flags, unsigned int mask);\n\tSTDMETHOD(OnChannelBan)(HRESULT r, LPCSTR name, int banned);\n\n\tunsigned long\tGetPlayerGameIP( const char* szPlayerName ) const;\n\tvoid\t\t\tDeleteUserList();\t\t//\tDeletes from heap all users pointed to through pUserList.\n\tvoid\t\t\tDeleteUserIPList();\n\tunsigned long\tGetUserIP( const char* szName ) const;\n\t\n\tvoid\t\t\tActionEggSound( const char* szMessage );\n\npublic:\n\t//\tThese vars are rather hackish. Basically, they are set before a callback is expected to be fired, and\n\t//\tthen checked immediately afterwards. The rest of the time, their values are meaningless.\n\t//\tThe idea is to force wolapi act in a modal way. In many places I \"block\" until a callback response to a \n\t//\twolapi request has been received.\n\tbool\tbRequestServerListWait;\n\tbool\tbRequestConnectionWait;\n\tbool\tbRequestLogoutWait;\n//\tbool\tbRequestChannelListWait;\n\tbool\tbRequestChannelJoinWait;\n\tbool\tbRequestChannelLeaveWait;\n\tbool\tbRequestUserListWait;\n\tbool\tbRequestChannelCreateWait;\n\tbool\tbRequestFindWait;\n\tbool\tbRequestPageWait;\n\n\tbool\tbRequestChannelListForLobbiesWait;\n\n\tbool\tbIgnoreChannelLists;\t\t\t//\tUsed to temporarily turn off response to channel lists, when we are in the midst\n\t\t\t\t\t\t\t\t\t\t\t//\tof some processing that depends on pChannelList remaining constant.\n\n\tbool\tbRequestGameStartWait;\n\n\tServer*\t\t\tpServer;\t\t\t\t//\tServer to connect to, acquired from OnServerList.\n\tbool\t\t\tbConnected;\t\t\t\t//\tTrue when user is logged in to chat server.\n\tbool\t\t\tbJoined;\t\t\t\t//\tTrue when user has joined a channel.\n\n\tChannel*\t\tpChannelList;\t\t\t//\tFirst element of channel list, or null.\n\tCHANNELFILTER\tChannelFilter;\t\t\t//\tAffects what channels are included in channel list when built.\n\n\tUser*\t\t\tpUserList;\t\t\t\t//\tFirst element of user list, or null.\n\tUser*\t\t\tpUserTail;\t\t\t\t//\tLast element of user list, or null.\n\n\tchar*\t\t\tszMotd;\t\t\t\t\t//\tMessage of the day.\n\tHRESULT\t\t\thresRequestConnectionError;\t\t//\tUsed to pass error hresult.\n\t\n\tHRESULT\t\t\thresRequestFindResult;\t//\tUsed to pass hresult.\n\tChannel\t\t\tOnFindChannel;\n\n\tHRESULT\t\t\thresRequestPageResult;\t//\tUsed to pass hresult.\n\n\tHRESULT\t\t\thresRequestJoinResult;\t//\tUsed to pass hresult.\n\n\tbool\t\t\tbGotKickedTrigger;\t\t//\tSpecial flag meaning do some more processing after callback has exited.\n\n\tUser*\t\t\tpGameUserList;\t\t\t//\tFirst element of start game user list, or null.\n\tint\t\t\t\tiGameID;\t\t\t\t//\tWW Online game id received from OnGameStart.\n\t\t\t\t\t\t\t\t\t\t\t//\tIs also a flag indicating \"OnGameStart() called, TriggerGameStart() not yet called\".\n\n\tUser*\t\t\tpUserIPList;\t\t\t//\tList that holds user IP's, used for pinging in game channel.\n\tUser*\t\t\tpUserIPListTail;\n\nprotected:\n\tWolapiObject*\tpOwner;\t\t\t\t\t//\tLink back to the object that contains me.\n\n\tvoid\t\t\tDeleteChannelList();\t//\tDeletes from heap all channels pointed to through pChannelList.\n\tbool\t\t\tDownloadUpdates( Update* pUpdateList, int iUpdates );\n\tbool\t\t\tbSpecialMessage( const char* szMessage );\n\tvoid\t\t\tInsertUserSorted( User* pUserNew );\n\nprivate:\n\tlong m_cRef;  // Reference Count\n\n};\n\n//***********************************************************************************************\nclass RADownloadEventSink : \n///////////\tpublic CComObjectRoot,\n\tpublic IDownloadEvent\n{\npublic:\n\tRADownloadEventSink();\n\tvirtual ~RADownloadEventSink() {};\n\n//  BEGIN_COM_MAP(RADownloadEventSink)\n//    COM_INTERFACE_ENTRY(IDownloadEvent)\n//  END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// IDownloadEvent\n\tSTDMETHOD(OnEnd)(void);\n\tSTDMETHOD(OnError)(int error);\n\tSTDMETHOD(OnProgressUpdate)(int bytesread, int totalsize, int timetaken, int timeleft);\n\tSTDMETHOD(OnStatusUpdate)(int status);\n\tSTDMETHOD(OnQueryResume)(void);\n\npublic:\n\tbool\t\tbFlagEnd;\n\tbool\t\tbFlagError;\n\tbool\t\tbFlagProgressUpdate;\n\tbool\t\tbFlagStatusUpdate;\n\tbool\t\tbFlagQueryResume;\n\tint\t\t\tiBytesRead;\n\tint\t\t\tiTotalSize;\n\tint\t\t\tiTimeTaken;\n\tint\t\t\tiTimeLeft;\n\tint\t\t\tiStatus;\n\tbool\t\tbResumed;\n\nprivate:\n\tlong m_cRef;  // Ref count\n};\n\n//***********************************************************************************************\nclass RANetUtilEventSink :\n//    public CComObjectRoot,\n    public INetUtilEvent\n{\npublic:\n\tRANetUtilEventSink( WolapiObject* pOwner );\n\tvirtual ~RANetUtilEventSink();\n\n//BEGIN_COM_MAP(CNetUtilEventSink)\n//\tCOM_INTERFACE_ENTRY(INetUtilEvent)\n//END_COM_MAP()\n\n\t// IUnknown\n\tSTDMETHOD(QueryInterface)(const IID& iid, void **ppv);\n\tSTDMETHOD_(ULONG,AddRef)();\n\tSTDMETHOD_(ULONG,Release)();\n\n\t// INetUtilEvent\n\n\tSTDMETHOD(OnGameresSent)(HRESULT res);\n\tSTDMETHOD(OnLadderList)(HRESULT res, Ladder *list, int totalCount, long timeStamp, int keyRung);\n\tSTDMETHOD(OnPing)(HRESULT res, int time, unsigned long ip, int handle);\n\n\n\tvoid\t\t\tDeleteLadderList();\t\t//\tDeletes from heap all users pointed to through pUserList.\n\tunsigned int\tGetUserRank( const char* szName, bool bRankRA );\n\n\tLadder*\t\t\tpLadderList;\t\t\t\t//\tFirst element of Ladder list, or null.\n\tLadder*\t\t\tpLadderTail;\t\t\t\t//\tLast element of Ladder list, or null.\n\tLadder*\t\t\tpLadderListAM;\t\t\t\t//\tFirst element of Aftermath Ladder list, or null.\n\tLadder*\t\t\tpLadderTailAM;\t\t\t\t//\tLast element of Aftermath Ladder list, or null.\n\nprotected:\n\tWolapiObject*\tpOwner;\t\t\t\t\t//\tLink back to the object that contains me.\n\nprivate:\n\tlong m_cRef;  // Reference Count\n};\n\n//***********************************************************************************************\n\n//\tSKU, reported to WOLAPI for the purpose of finding patches.\n#ifdef ENGLISH\n#define GAME_SKU\t\t0x1500\n#else\n#ifdef GERMAN\n#define GAME_SKU\t\t0x1502\n#else\n#define GAME_SKU\t\t0x1503\n#endif\n#endif\n\n#define GAME_VERSION\t0x00030003\n#define GAME_TYPE\t\t21\n#define LOB_PREFIX\t\t\"Lob_21_\"\n\n//\tSent to gameres server in order to receive Red Alert or Aftermath ladder rankings. (Sent in RequestLadderList.)\n#define LADDER_CODE_RA\t\t1005\n#define LADDER_CODE_AM\t\t500\n\n#endif\n\n#endif\n"
  },
  {
    "path": "REDALERT/READLINE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#include \"function.h\"\n#include\t<ctype.h>\n#include\t<string.h>\n#include\t\"wwfile.h\"\n#include\t\"xstraw.h\"\n#include\t\"readline.h\"\n\n\n// Disable the \"temporary object used to initialize a non-constant reference\" warning.\n//#pragma warning 665 9\n\n\nvoid strtrimcpp(char * buffer)\n{\n\tif (buffer) {\n\n\t\t/*\n\t\t**\tStrip leading white space from the string.\n\t\t*/\n\t\tchar * source = buffer;\n\t\twhile (isspace(*source)) {\n\t\t\tsource++;\n\t\t}\n\t\tif (source != buffer) {\n\t\t\tstrcpy(buffer, source);\n\t\t}\n\n\t\t/*\n\t\t**\tClip trailing white space from the string.\n\t\t*/\n\t\tfor (int index = strlen(buffer)-1; index >= 0; index--) {\n\t\t\tif (isspace(buffer[index])) {\n\t\t\t\tbuffer[index] = '\\0';\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\nint Read_Line(FileClass & file, char * buffer, int len, bool & eof)\n{\n\treturn(Read_Line(FileStraw(file), buffer, len, eof));\n}\n\n\nint Read_Line(Straw & file, char * buffer, int len, bool & eof)\n{\n\tif (len == 0 || buffer == NULL) return(0);\n\n\tint count = 0;\n\tfor (;;) {\n\t\tchar c;\n\t\tif (file.Get(&c, sizeof(c)) != sizeof(c)) {\n\t\t\teof = true;\n\t\t\tbuffer[0] = '\\0';\n\t\t\tbreak;\n\t\t}\n\n\t\tif (c == '\\x0A') break;\n\t\tif (c != '\\x0D' && count+1 < len) {\n\t\t\tbuffer[count++] = c;\n\t\t}\n\t}\n\tbuffer[count] = '\\0';\n\n\tstrtrimcpp(buffer);\n\treturn(strlen(buffer));\n}\n"
  },
  {
    "path": "REDALERT/READLINE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n#include\t\"wwfile.h\"\n#include\t\"straw.h\"\n\nvoid strtrim(char * buffer);\nint Read_Line(FileClass & file, char * buffer, int len, bool & eof);\nint Read_Line(Straw & file, char * buffer, int len, bool & eof);\n\n"
  },
  {
    "path": "REDALERT/RECT.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RECT.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RECT.CPP                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/22/96                                                     *\n *                                                                                             *\n *                  Last Update : July 22, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Rect::Rect -- Constructs a rectangle object.                                              *\n *   Rect::Is_Valid -- Determines if the rectangle is valid.                                   *\n *   Rect::Intersect -- Find the intersection between two rectangles.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"rect.h\"\n\n\n/***********************************************************************************************\n * Rect::Rect -- Constructs a rectangle object.                                                *\n *                                                                                             *\n *    This will construct a rectangle object according to the parameters specified.            *\n *                                                                                             *\n * INPUT:   x,y   -- The X and Y values of the upper left corner of the rectangle.             *\n *                                                                                             *\n *          w,h   -- The width and height values of the rectangle.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect::Rect(int x, int y, int w, int h) :\n\tX(x),\n\tY(y),\n\tWidth(w),\n\tHeight(h)\n{\n}\n\n\n/***********************************************************************************************\n * Rect::Is_Valid -- Determines if the rectangle is valid.                                     *\n *                                                                                             *\n *    An invalid rectangle has values that do not make any sense. This is a useful state since *\n *    this can be used to determine if a rectangle has been initialized correctly or for       *\n *    detecting an error return condition for rectangle manipulation routines.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Does this rectangle appear valid?                                            *\n *                                                                                             *\n * WARNINGS:   An invalid rectangle is one that has a width or height of less than one.        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Rect::Is_Valid(void) const\n{\n\treturn(Width > 0 && Height > 0);\n}\n\n\n/***********************************************************************************************\n * Rect::Intersect -- Find the intersection between two rectangles.                            *\n *                                                                                             *\n *    This routine will take the specified rectangle and use it like a \"cookie cutter\" on this *\n *    rectangle. The intersection of these two rectangles is returned. An optional X and       *\n *    Y parameter is supplied so that an absolute coordinate can be maintained to the new      *\n *    rectangle.                                                                               *\n *                                                                                             *\n * INPUT:   rectangle   -- Reference to the rectangle to use as a cookie cutter.               *\n *                                                                                             *\n *          x,y         -- Optional pointer to a coordinate that will be adjusted to stay      *\n *                         in an absolute position in coordinates even though it is a          *\n *                         relative offset.                                                    *\n *                                                                                             *\n * OUTPUT:  Returns with the rectangle that is the intersection of the one specified and       *\n *          this rectangle.                                                                    *\n *                                                                                             *\n * WARNINGS:   The rectangle returned may be invalid. This can occur if there is no legal      *\n *             intersection between the rectangles.                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRect const Rect::Intersect(Rect const & rectangle, int * x, int * y) const\n{\n\tRect rect(0, 0, 0, 0);\t\t\t// Dummy (illegal) rectangle.\n\tRect r = rectangle;\t\t\t\t// Working rectangle.\n\n\t/*\n\t**\tBoth rectangles must be valid or else no intersection can occur. In such\n\t**\ta case, return an illegal rectangle.\n\t*/\n\tif (!Is_Valid() || !rectangle.Is_Valid()) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the left edge.\n\t*/\n\tif (r.X < X) {\n\t\tr.Width -= X - r.X;\n\t\tr.X = X;\n\t}\n\tif (r.Width < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past top edge.\n\t*/\n\tif (r.Y < Y) {\n\t\tr.Height -= Y - r.Y;\n\t\tr.Y = Y;\n\t}\n\tif (r.Height < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the right edge.\n\t*/\n\tif (r.X + r.Width > X + Width) {\n\t\tr.Width -= (r.X + r.Width) - (X + Width);\n\t}\n\tif (r.Width < 1) return(rect);\n\n\t/*\n\t**\tThe rectangle spills past the bottom edge.\n\t*/\n\tif (r.Y + r.Height > Y + Height) {\n\t\tr.Height -= (r.Y + r.Height) - (Y + Height);\n\t}\n\tif (r.Height < 1) return(rect);\n\n\t/*\n\t**\tAdjust Height relative draw position according to Height new rectangle\n\t**\tunion.\n\t*/\n\tif (x != NULL) {\n\t\t*x -= (r.X-X);\n\t}\n\tif (y != NULL) {\n\t\t*y -= (r.Y-Y);\n\t}\n\n\treturn(r);\n}\n\n\nRect const Union(Rect const & rect1, Rect const & rect2)\n{\n\tif (rect1.Is_Valid()) {\n\t\tif (rect2.Is_Valid()) {\n\t\t\tRect result = rect1;\n\n\t\t\tif (result.X > rect2.X) {\n\t\t\t\tresult.Width += result.X-rect2.X;\n\t\t\t\tresult.X = rect2.X;\n\t\t\t}\n\t\t\tif (result.Y > rect2.Y) {\n\t\t\t\tresult.Height += result.Y-rect2.Y;\n\t\t\t\tresult.Y = rect2.Y;\n\t\t\t}\n\t\t\tif (result.X+result.Width < rect2.X+rect2.Width) {\n\t\t\t\tresult.Width = ((rect2.X+rect2.Width)-result.X)+1;\n\t\t\t}\n\t\t\tif (result.Y+result.Height < rect2.Y+rect2.Height) {\n\t\t\t\tresult.Height = ((rect2.Y+rect2.Height)-result.Y)+1;\n\t\t\t}\n\t\t\treturn(result);\n\t\t}\n\t\treturn(rect1);\n\t}\n\treturn(rect2);\n}\n"
  },
  {
    "path": "REDALERT/RECT.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RECT.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RECT.H                                                       *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/21/96                                                     *\n *                                                                                             *\n *                  Last Update : July 21, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RECT_H\n#define RECT_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#include\t<stddef.h>\n\nclass Rect\n{\n\tpublic:\n\t\tRect(int x=0, int y=0, int w=0, int h=0);\n\n\t\tRect const Intersect(Rect const & rectangle, int * x=NULL, int * y=NULL) const;\n\t\tfriend Rect const Union(Rect const & rect1, Rect const & rect2);\n\n\t\tbool Is_Valid(void) const;\n\t\tint Size(void) const {return(Width*Height);}\n\n//\tprivate:\n\t\tint X;\n\t\tint Y;\n\t\tint Width;\n\t\tint Height;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/REGION.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/REGION.H 1     3/03/97 10:25a Joe_bostic $ */\n/*********************************************************************************************** \n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n *********************************************************************************************** \n *                                                                                             * \n *                 Project Name : Command & Conquer                                            * \n *                                                                                             * \n *                    File Name : REGION.H                                                     * \n *                                                                                             * \n *                   Programmer : Joe L. Bostic                                                * \n *                                                                                             * \n *                   Start Date : 03/09/95                                                     * \n *                                                                                             * \n *                  Last Update : March 9, 1995 [JLB]                                          * \n *                                                                                             * \n *---------------------------------------------------------------------------------------------* \n * Functions:                                                                                  * \n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef REGION_H\n#define REGION_H\n\n\nclass RegionClass {\n\tpublic:\n\t\tRegionClass(void) {Threat = 0;};\n\t\t~RegionClass(void) {};\n\t\tint operator != (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass));};\n\t\tint operator == (RegionClass const & region) {return !memcmp(this, &region, sizeof(RegionClass));};\n\t\tint operator > (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass)) > 0;};\n\t\tint operator < (RegionClass const & region) {return memcmp(this, &region, sizeof(RegionClass)) < 0;};\n\n\t\tvoid Reset_Threat(void) {Threat = 0;};\n\t\tvoid Adjust_Threat(int threat, int neg) {if (neg) Threat -= threat; else Threat+= threat;};\n\t\tint Threat_Value(void) const {return Threat;};\n\n\tprotected:\n\t\tlong  Threat;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/REINF.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/REINF.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : REINF.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : May 24, 1994                                                 *\n *                                                                                             *\n *                  Last Update : July 26, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Create_Air_Reinforcement -- Creates air strike reinforcement                              *\n *   Create_Special_Reinforcement -- Ad hoc reinforcement handler.                             *\n *   Do_Reinforcements -- Create and place a reinforcement team.                               *\n *   _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.          *\n *   _Create_Group -- Create a group given team specification.                                 *\n *   _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                  *\n *   _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                     *\n *   _Need_To_Take -- Examines unit to determine if it should be confiscated.                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                    *\n *                                                                                             *\n *    This routine will cause the group to pop out of the object specified.                    *\n *                                                                                             *\n * INPUT:   group    -- Pointer to the first object in the group to be popped out.             *\n *                                                                                             *\n *          object   -- Pointer to the object that the group is to pop out of.                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the group popped out of the specified object?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Pop_Group_Out_Of_Object(FootClass * group, TechnoClass * object)\n{\n\tassert(group != NULL && object != NULL);\n\tint quantity = 0;\n\n\t/*\n\t**\tTake every infantry member of this group and detach it from the group list\n\t**\tand then make it pop out of the candidate source.\n\t*/\n\twhile (group != NULL) {\n\t\tTechnoClass * todo = group;\n\t\tgroup = (FootClass *)(ObjectClass *)group->Next;\n\t\ttodo->Next = NULL;\n\n\t\tswitch (object->What_Am_I()) {\n\n\t\t\t/*\n\t\t\t**\tThe infantry just walks out of a building.\n\t\t\t*/\n\t\t\tcase RTTI_BUILDING:\n\t\t\t\tif (object->Exit_Object(todo) != 2) {\n\t\t\t\t\tdelete todo;\n\t\t\t\t} else {\n\t\t\t\t\t++quantity;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tInfantry get attached to transport vehicles and then unload.\n\t\t\t*/\n\t\t\tcase RTTI_UNIT:\n\t\t\tcase RTTI_VESSEL:\n\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\tobject->Attach((FootClass *)todo);\n\t\t\t\tobject->Assign_Mission(MISSION_UNLOAD);\n\t\t\t\t++quantity;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tdelete todo;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn (quantity != 0);\n}\n\n\n/***********************************************************************************************\n * _Need_To_Take -- Examines unit to determine if it should be confiscated.                    *\n *                                                                                             *\n *    The unit is examined and if the owning house needs to confiscate it, then this routine   *\n *    will return TRUE. In other cases, the unit should be left to its own devices.            *\n *                                                                                             *\n * INPUT:   unit  -- Pointer to the object to examine.                                         *\n *                                                                                             *\n * OUTPUT:  bool; Should the object be confiscated by the player so that it becomes one of     *\n *                his normal game objects?                                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool _Need_To_Take(AircraftClass const * air)\n{\n\tif (*air == AIRCRAFT_YAK || *air == AIRCRAFT_MIG) {\n\t\tint deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP);\n//\t\tint deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP) - (air->House->Get_Quantity(AIRCRAFT_YAK)+air->House->Get_Quantity(AIRCRAFT_MIG));\n\n\t\t/*\n\t\t**\tLoop through all aircraft and subtract all the ones that are NOT loaners.\n\t\t*/\n\t\tfor (int index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass const * airptr = Aircraft.Ptr(index);\n\t\t\tif ((*airptr == AIRCRAFT_YAK || *airptr == AIRCRAFT_MIG) && airptr->IsOwnedByPlayer && !airptr->IsALoaner && airptr != air) {\n\t\t\t\tdeficit -= 1;\n\t\t\t\tif (deficit == 0) break;\n\t\t\t}\n\t\t}\n\n\t\tif (deficit > 0) return(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * _Create_Group -- Create a group given team specification.                                   *\n *                                                                                             *\n *    This routine will create all members of the group as specified by the team type.         *\n *                                                                                             *\n * INPUT:   teamtype -- Pointer to the team type that specifies what objects should be         *\n *                      created in this group.                                                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the first member of the group created.                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic FootClass * _Create_Group(TeamTypeClass const * teamtype)\n{\n\tassert(teamtype != NULL);\n\n\tTeamClass * team = new TeamClass(teamtype);\n\tif (team != NULL) {\n\t\tteam->Force_Active();\n\t}\n\n\tbool hasunload = false;\n\tfor (int tm = 0; tm < teamtype->MissionCount; tm++) {\n\t\tif (teamtype->MissionList[tm].Mission == TMISSION_UNLOAD) {\n\t\t\thasunload = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tNow that the official source for the reinforcement has been determined, the\n\t**\tobjects themselves must be created.\n\t*/\n\tFootClass * transport = NULL;\n\tFootClass * object = NULL;\n\tfor (int index = 0; index < teamtype->ClassCount; index++) {\n\t\tTechnoTypeClass const * tclass = teamtype->Members[index].Class;\n\n\t\tfor (int sub = 0; sub < teamtype->Members[index].Quantity; sub++) {\n\t\t\tScenarioInit++;\n\t\t\tFootClass * temp = (FootClass *)tclass->Create_One_Of(HouseClass::As_Pointer(teamtype->House));\n\t\t\tScenarioInit--;\n\n\t\t\tif (temp != NULL) {\n\n\t\t\t\t/*\n\t\t\t\t**\tAdd the member to the team.\n\t\t\t\t*/\n\t\t\t\tif (team != NULL) {\n\t\t\t\t\tScenarioInit++;\n\t\t\t\t\tbool ok = team->Add(temp);\n//Mono_Printf(\"Added to team = %d.\\n\", ok);Keyboard->Get();\n\n\t\t\t\t\tScenarioInit--;\n\t\t\t\t\ttemp->IsInitiated = true;\n\t\t\t\t}\n\n\t\t\t\tif (temp->What_Am_I() == RTTI_AIRCRAFT && !_Need_To_Take((AircraftClass const *)temp)) {\n\t\t\t\t\ttemp->IsALoaner = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tBuild the list of transporters and passengers.\n\t\t\t\t*/\n\t\t\t\tif (tclass->Max_Passengers() > 0) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLink to the list of transports.\n\t\t\t\t\t*/\n\t\t\t\t\ttemp->Next = transport;\n\t\t\t\t\ttransport = temp;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tLink to the list of normal objects.\n\t\t\t\t\t*/\n\t\t\t\t\ttemp->Next = object;\n\t\t\t\t\tobject = temp;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the group consists of transports and normal objects, then assign the normal\n\t**\tobjects to be passengers on the transport.\n\t*/\n\tif (transport != NULL && object != NULL) {\n\t\ttransport->Attach(object);\n\n\t\t/*\n\t\t**\tHACK ALERT! If the this team has an unload mission, then flag the transport\n\t\t**\tas a loaner so that it will exit from the map when the unload process is\n\t\t**\tcomplete, but only if the transport is an aircraft type.\n\t\t*/\n\t\tif (hasunload && (transport->What_Am_I() == RTTI_AIRCRAFT || transport->What_Am_I() == RTTI_VESSEL)) {\n\t\t\ttransport->IsALoaner = true;\n\t\t}\n\t}\n\n\t/*\n\t**\tFor JUST transport helicopters, consider the loaner a gift if there are\n\t**\tno passengers.\n\t*/\n\tif (transport != NULL && object == NULL && transport->What_Am_I() == RTTI_AIRCRAFT && *((AircraftClass *)transport) == AIRCRAFT_TRANSPORT) {\n\t\ttransport->IsALoaner = false;\n\t}\n\n\tif (transport == 0 && object == 0) {\n\t\tif (team != NULL) delete team;\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t**\tIf this group consists only of non-transport object, then just return with a pointer\n\t**\tto the first member of the group.\n\t*/\n\tif (transport == NULL) {\n\t\treturn(object);\n\t}\n\n\treturn(transport);\n}\n\n\n/***********************************************************************************************\n * _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.            *\n *                                                                                             *\n *    Use this to determine if the specified group only contains infantry. Such a reinforcement*\n *    group is a candidate for popping out of a building or transport vehicle rather than      *\n *    driving/walking/sailing/flying onto the map under its own power.                         *\n *                                                                                             *\n * INPUT:   first -- Pointer to the first object in the group to examine.                      *\n *                                                                                             *\n * OUTPUT:  bool; Is the entire group composed of infantry type units?                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic bool _Consists_Only_Of_Infantry(FootClass const * first)\n{\n\twhile (first != NULL) {\n\t\tif (first->What_Am_I() != RTTI_INFANTRY) {\n\t\t\treturn(false);\n\t\t}\n\t\tfirst = (FootClass const *)((ObjectClass *)first->Next);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                       *\n *                                                                                             *\n *    This routine is used to scan nearby locations to determine if there is a suitable host   *\n *    for these reinforcements to \"pop out of\" (apologies to Aliens). Typical hosts include    *\n *    buildings and transport vehicles (of any kind).                                          *\n *                                                                                             *\n * INPUT:   origin   -- The cell that should be scanned from. Only this location and immediate *\n *                      adjacent locations will be scanned.                                    *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a suitable host. If none could be found then NULL is     *\n *          returned.                                                                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/25/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic TechnoClass * _Who_Can_Pop_Out_Of(CELL origin)\n{\n\tCellClass * cellptr = &Map[origin];\n\tTechnoClass * candidate = NULL;\n\n\tfor (int f = -1; f < 8; f++) {\n\t\tCellClass * ptr = cellptr;\n\t\tif (f != -1) {\n\t\t\tptr = ptr->Adjacent_Cell(FacingType(f));\n\t\t\tif (!ptr) continue;\n\t\t}\n\n\t\tBuildingClass * building = ptr->Cell_Building();\n\t\tif (building && building->Strength > 0) {\n\t\t\tcandidate = building;\n\t\t}\n\n\t\tUnitClass * unit = ptr->Cell_Unit();\n\t\tif (unit && unit->Strength && unit->Class->Max_Passengers() > 0) {\n\t\t\treturn(unit);\n\t\t}\n\t}\n\treturn(candidate);\n}\n\n\n/***********************************************************************************************\n * Do_Reinforcements -- Create and place a reinforcement team.                                 *\n *                                                                                             *\n *    This routine is called when a reinforcement team must be created and placed on the map.  *\n *    It will create all members of the team and place them at the location determined from    *\n *    the team composition. The reinforcement team should follow team orders until overridden  *\n *    by AI or player intervention.                                                            *\n *                                                                                             *\n * INPUT:   teamtype -- Pointer to the team type to create as a reinforcement.                 *\n *                                                                                             *\n * OUTPUT:  Was the reinforcement successfully created and placed?                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/08/1995 JLB : Created.                                                                 *\n *   05/18/1995 JLB : Returns success or failure condition.                                    *\n *   06/19/1995 JLB : Announces reinforcements.                                                *\n *   02/15/1996 JLB : Recognizes team reinforcement location.                                  *\n *=============================================================================================*/\nbool Do_Reinforcements(TeamTypeClass const * teamtype)\n{\n\tassert(teamtype != 0);\n\n\t/*\n\t**\tperform some preliminary checks for validity.\n\t*/\n\tif (!teamtype || !teamtype->ClassCount) return(false);\n\n\t/*\n\t**\tHACK ALERT!\n\t**\tGive this team an attack waypoint mission that will attack the waypoint location of this\n\t**\tteam if there are no team missions previously assigned.\n\t*/\n\tif (teamtype->MissionCount == 0) {\n\t\tTeamTypeClass * tt = (TeamTypeClass *)teamtype;\n\t\ttt->MissionCount = 1;\n\t\ttt->MissionList[0].Mission = TMISSION_ATT_WAYPT;\n\t\ttt->MissionList[0].Data.Value = teamtype->Origin;\n\t}\n\n\tFootClass * object = _Create_Group(teamtype);\n\n\n//Mono_Printf(\"%d-%s (object=%p, team=%d).\\n\", __LINE__, __FILE__, object, object->Team.Is_Valid());Keyboard->Get();\n\n\n\t/*\n\t**\tBail on this reinforcement if no reinforcements could be created.\n\t**\tThis is probably because the object maximum was reached.\n\t*/\n\tif (!object) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSpecial case code to handle infantry types that run from a building. This presumes\n\t**\tthat infantry are never a transport (which is safe to do).\n\t*/\n\tif (object != NULL && teamtype->Origin != -1 && _Consists_Only_Of_Infantry(object)) {\n\n\t\t/*\n\t\t**\tSearch for an object that these infantry can pop out of.\n\t\t*/\n\t\tTechnoClass * candidate = _Who_Can_Pop_Out_Of(Scen.Waypoint[teamtype->Origin]);\n\n\t\tif (candidate != NULL) {\n\t\t\treturn(_Pop_Group_Out_Of_Object(object, candidate));\n\t\t}\n\t}\n\n\t/*\n\t**\tThe reinforcements must be delivered the old fashioned way -- by moving onto the\n\t**\tmap using their own power. First order of business is to determine where they\n\t**\tshould arrive from.\n\t*/\n\tSourceType source = HouseClass::As_Pointer(teamtype->House)->Control.Edge;\n\tif (source == SOURCE_NONE) {\n\t\tsource = SOURCE_NORTH;\n\t}\n\n\t/*\n\t**\tPick the location where the reinforcements appear and then place\n\t**\tthem there.\n\t*/\n\tbool placed = false;\n\n\tFacingType eface = (FacingType)(source << 1);\t// Facing to enter map.\n\n\tCELL cell = Map.Calculated_Cell(source, teamtype->Origin, -1, object->Techno_Type_Class()->Speed);\n#ifdef FIXIT_ANTS\n\t/*\n\t**\tFor the ants, they will pop out of the ant hill directly.\n\t*/\n\tif (teamtype->Origin != -1 && object->What_Am_I() == RTTI_UNIT && \n\t\t\t(*((UnitClass*)object) == UNIT_ANT1 ||\n\t\t\t*((UnitClass*)object) == UNIT_ANT2 ||\n\t\t\t*((UnitClass*)object) == UNIT_ANT3))  {\n\t\tCELL newcell = Scen.Waypoint[teamtype->Origin];\n\t\tif (newcell != -1)  {\n\t\t\tif (Map[newcell].TType == TEMPLATE_HILL01)  {\n\t\t\t\tcell = newcell;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tCELL newcell = cell;\n\n\tFootClass * o = (FootClass *)(ObjectClass *)object->Next;\n\tobject->Next = 0;\n\tbool okvoice = false;\n\twhile (newcell > 0 && object != NULL) {\n\t\tDirType desiredfacing = Facing_Dir(eface);\n\t\tif (object->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\tdesiredfacing = Random_Pick(DIR_N, DIR_MAX);\n\t\t}\n\n\t\tScenarioInit++;\n\t\tif (object->Unlimbo(Cell_Coord(newcell), desiredfacing)) {\n\t\t\tokvoice = true;\n\n\t\t\t/*\n\t\t\t**\tIf this object is part of a team, then the mission for this\n\t\t\t**\tobject will be guard. The team handler will assign the proper\n\t\t\t**\tmission that it should follow.\n\t\t\t*/\n\t\t\tif (object->What_Am_I() != RTTI_AIRCRAFT) {\n\t\t\t\tobject->Assign_Mission(MISSION_GUARD);\n\t\t\t\tobject->Commence();\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tCould not unlimbo at location specified so find an adjacent location that it can\n\t\t\t**\tbe unlimboed at. If this fails, then abort the whole placement process.\n\t\t\t*/\n\t\t\tFacingType adj;\n\t\t\tfor (adj = FACING_N; adj < FACING_COUNT; adj++) {\n\t\t\t\tCELL trycell = Adjacent_Cell(newcell, adj);\n\t\t\t\tif (!Map.In_Radar(trycell) && object->Can_Enter_Cell(trycell, adj) == MOVE_OK) {\n\t\t\t\t\tnewcell = trycell;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (adj < FACING_COUNT) continue;\n\t\t\tnewcell = 0;\n\t\t}\n\t\tScenarioInit--;\n\n\t\tobject = o;\n\t\tif (object != NULL) {\n\t\t\to = (FootClass *)(ObjectClass *)object->Next;\n\t\t\tobject->Next = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are still objects that could not be placed, then delete them.\n\t*/\n\tif (o != NULL) {\n\t\twhile (o != NULL) {\n\t\t\tFootClass * old = o;\n\t\t\to = (FootClass *)(ObjectClass *)o->Next;\n\t\t\told->Next = 0;\n\n\t\t\tdelete old;\n\t\t}\n\t}\n\n\t/*\n\t**\tAnnounce when the reinforcements have arrived.\n\t*/\n\tif (okvoice && teamtype->House == PlayerPtr->Class->House) {\n\t\tSpeak(VOX_REINFORCEMENTS, NULL, newcell ? Cell_Coord(newcell) : 0);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Create_Special_Reinforcement -- Ad hoc reinforcement handler.                               *\n *                                                                                             *\n *    Use this routine to bring on a reinforcement that hasn't been anticipated by the trigger *\n *    system. An example of this would be replacement harvesters or airfield ordered units.    *\n *    The appropriate transport is created (if necessary) and a mission is assigned such that  *\n *    the object will legally bring itself onto the playing field.                             *\n *                                                                                             *\n * INPUT:   house    -- The owner of this reinforcement.                                       *\n *                                                                                             *\n *          type     -- The object to bring on.                                                *\n *                                                                                             *\n *          another  -- This is reserved for the transport class in those cases where the      *\n *                      transport MUST be forced to a specific type.                           *\n *                                                                                             *\n *          mission  -- The mission to assign this reinforcement team.                         *\n *                                                                                             *\n *          argument -- Optional team mission argument (usually a waypoint).                   *\n *                                                                                             *\n * OUTPUT:  Was the special reinforcement created without error?                               *\n *                                                                                             *\n * WARNINGS:   This routine will fail if a team type cannot be created.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Create_Special_Reinforcement(HouseClass * house, TechnoTypeClass const * type, TechnoTypeClass const * another, TeamMissionType mission, int argument)\n{\n\tassert(house != 0);\n\tassert(type != 0);\n\n\tif (house && type) {\n\t\tTeamTypeClass * team = new TeamTypeClass();\n\n\t\tif (team) {\n\n\t\t\t/*\n\t\t\t**\tIf there is no overridden mission assign to this special reinforcement, then\n\t\t\t**\twe must assign something. If not, the reinforcement will just sit at the edge\n\t\t\t**\tof the map.\n\t\t\t*/\n\t\t\tif (!another && mission == TMISSION_NONE) {\n\t\t\t\tmission = TMISSION_MOVECELL;\n\t\t\t\targument = Map.Calculated_Cell(house->Control.Edge);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFill in the team characteristics.\n\t\t\t*/\n\t\t\tstrcpy((char *)&team->IniName[0], \"TEMP\");\n\t\t\tteam->IsReinforcable = false;\n\t\t\tteam->IsTransient = true;\n\t\t\tteam->ClassCount = 1;\n\t\t\tteam->Members[0].Class = type;\n\t\t\tteam->Members[0].Quantity = 1;\n\t\t\tteam->MissionCount = 1;\n\t\t\tif (mission == TMISSION_NONE) {\n\t\t\t\tteam->MissionList[0].Mission\t= TMISSION_UNLOAD;\n\t\t\t\tteam->MissionList[0].Data.Value = WAYPT_REINF;\n\t\t\t} else {\n\t\t\t\tteam->MissionList[0].Mission\t= mission;\n\t\t\t\tteam->MissionList[0].Data.Value = argument;\n\t\t\t}\n\t\t\tteam->House = house->Class->House;\n\t\t\tif (another) {\n\t\t\t\tteam->ClassCount++;\n\t\t\t\tteam->Members[1].Class = another;\n\t\t\t\tteam->Members[1].Quantity = 1;\n\t\t\t}\n\n\t\t\tbool ok = Do_Reinforcements(team);\n\t\t\tif (!ok) delete team;\n\t\t\treturn(ok);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Create_Air_Reinforcement -- Creates air strike reinforcement                                *\n *                                                                                             *\n *    This routine is used to launch an airstrike. It will create the necessary aircraft and   *\n *    assign them to attack the target specified. This routine bypasses the normal             *\n *    reinforcement logic since it doesn't need the sophistication of unloading and following  *\n *    team mission lists.                                                                      *\n *                                                                                             *\n * INPUT:   house    -- The perpetrator of this air strike.                                    *\n *                                                                                             *\n *          air      -- The type of aircraft to make up this airstrike.                        *\n *                                                                                             *\n *          number   -- The number of aircraft in this airstrike.                              *\n *                                                                                             *\n *          mission  -- The mission to assign the aircraft.                                    *\n *                                                                                             *\n *          tarcom   -- The target to assign these aircraft.                                   *\n *                                                                                             *\n *          navcom   -- The navigation target to assign (if necessary).                        *\n *                                                                                             *\n * OUTPUT:  Returns the number of aircraft created for this airstrike.                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Commented.                                                               *\n *=============================================================================================*/\nint Create_Air_Reinforcement(HouseClass * house, AircraftType air, int number, MissionType mission, TARGET tarcom, TARGET navcom, InfantryType passenger)\n{\n\tassert(house != 0);\n\tassert((unsigned)air < AIRCRAFT_COUNT);\n\tassert(number != 0);\n\tassert((unsigned)mission < MISSION_COUNT);\n\t/*\n\t** Get a pointer to the class of the object that we are going to create.\n\t*/\n\tTechnoTypeClass const * type = (TechnoTypeClass *)&AircraftTypeClass::As_Reference(air);\n\n\t/*\n\t** Abort the airstrike if Tanya is the passenger and she's dead.\n\t*/\n\tif (passenger == INFANTRY_TANYA && IsTanyaDead) {\n\t\tnumber = 0;\n\t}\n\n\t/*\n\t** Loop through the number of objects we are supposed to create and\n\t** \tcreate and place them on the map.\n\t*/\n\tint sub;\n\tfor (sub = 0; sub < number; sub++) {\n\n\t\t/*\n\t\t** Create one of the required objects.  If this fails we could have\n\t\t** a real problem.\n\t\t*/\n\t\tScenarioInit++;\n\t\tTechnoClass * obj = (TechnoClass *)type->Create_One_Of(house);\n\t\tScenarioInit--;\n\t\tif (!obj) return(sub);\n\n\t\t/*\n\t\t** Flying objects always have the IsALoaner bit set.\n\t\t*/\n\t\tobj->IsALoaner = true;\n\n\t\t/*\n\t\t** Find a cell for the object to come in on.  This is stolen from the\n\t\t** the code that handles a SOURCE_AIR in the normal logic.\n\t\t*/\n\t\tSourceType source = house->Control.Edge;\n\t\tswitch (source) {\n\t\t\tcase SOURCE_NORTH:\n\t\t\tcase SOURCE_EAST:\n\t\t\tcase SOURCE_SOUTH:\n\t\t\tcase SOURCE_WEST:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tsource = SOURCE_NORTH;\n\t\t\t\tbreak;\n\t\t}\n\t\tCELL newcell = Map.Calculated_Cell(source, -1, -1, SPEED_WINGED);\n\n\t\t/*\n\t\t** Try and place the object onto the map.\n\t\t*/\n\t\tScenarioInit++;\n\t\tint placed = obj->Unlimbo(Cell_Coord(newcell), DIR_N);\n\t\tScenarioInit--;\n\t\tif (placed) {\n\n\t\t\t/*\n\t\t\t** If we succeeded in placing the obj onto the map then\n\t\t\t** now we need to give it a mission and destination.\n\t\t\t*/\n\t\t\tobj->Assign_Mission(mission);\n\n\t\t\t/*\n\t\t\t** If a navcom was specified then set it.\n\t\t\t*/\n\t\t\tif (navcom != TARGET_NONE) {\n\t\t\t\tobj->Assign_Destination(navcom);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If a tarcom was specified then set it.\n\t\t\t*/\n\t\t\tif (tarcom != TARGET_NONE) {\n\t\t\t\tobj->Assign_Target(tarcom);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tAssign generic passenger value here. This value is used to determine\n\t\t\t**\tif this aircraft should drop parachute reinforcements.\n\t\t\t*/\n\t\t\tif (obj->What_Am_I() == RTTI_AIRCRAFT) {\n\t\t\t\tAircraftClass * aircraft = (AircraftClass *)obj;\n\t\t\t\tif (passenger != INFANTRY_NONE) {\n\t\t\t\t\taircraft->Passenger = passenger;\n\t\t\t\t}\n//\t\t\t\tif (Passenger == INFANTRY_TANYA) {\n//\t\t\t\t\taircraft->Ammo = 1;\n\t\t\t\t\t//aircraft->AttacksRemaining = 1;\n//\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Start the object into action.\n\t\t\t*/\n\t\t\tobj->Commence();\n\t\t} else {\n\t\t\tdelete obj;\n\t\t\tsub--;\n\t\t\treturn(sub);\n\t\t}\n\t}\n\treturn(sub);\n}\n"
  },
  {
    "path": "REDALERT/RESOURCE/RedAlert.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"afxres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (United States) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#include \"\"afxres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION 1,0,0,1\n PRODUCTVERSION 1,0,0,1\n FILEFLAGSMASK 0x17L\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x4L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904b0\"\n        BEGIN\n            VALUE \"CompanyName\", \"Petroglyph Games Inc.\"\n            VALUE \"FileDescription\", \"Command & Conquer(TM) Remastered Collection RedAlert DLL\"\n            VALUE \"FileVersion\", \"1, 0, 0, 1\"\n            VALUE \"InternalName\", \"Command & Conquer(TM) Remastered Collection\"\n            VALUE \"LegalCopyright\", \"(C) 2020 Electronic Arts Inc. All rights reserved.\"\n            VALUE \"OriginalFilename\", \"RedAlert.DLL\"\n            VALUE \"ProductName\", \"Command & Conquer(TM) Remastered Collection\"\n            VALUE \"ProductVersion\", \"1, 0, 0, 1\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1200\n    END\nEND\n\n#endif    // English (United States) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "REDALERT/RESOURCE/resource.h",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by RedAlert.rc\n//\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        101\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "REDALERT/RGB.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RGB.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RGB.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : February 20, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RGBClass::Adjust -- Adjust one RGB value toward another.                                  *\n *   RGBClass::Difference -- Determines the \"distance\" between two colors.                     *\n *   RGBClass::Set -- Set the color index to the RGB object specified.                         *\n *   RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"watcom.h\"\n#include \"rgb.h\"\n#include\t\"hsv.h\"\n#include\t\"palettec.h\"\n\nRGBClass const BlackColor(0, 0, 0);\n\n\n/***********************************************************************************************\n * RGBClass::Adjust -- Adjust one RGB value toward another.                                    *\n *                                                                                             *\n *    This routine is used to modify an RGB value to proportionately match another RGB value   *\n *    according to the ratio parameter specified. Typical use of this routine is in palette    *\n *    fading from one palette to another or to black.                                          *\n *                                                                                             *\n * INPUT:   ratio    -- The ration of transformation. This value is in the form of 0 to 255,   *\n *                      with 0 being no change, and 255 being 100% transformed into the        *\n *                      destination color.                                                     *\n *                                                                                             *\n *          rgb      -- Reference to the destination RGB color to transform this color into.   *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RGBClass::Adjust(int ratio, RGBClass const & rgb)\n{\n\t/*\n\t**\tRatio conversion is limited to 0 through 100%. This is\n\t**\tthe range of 0 to 255.\n\t*/\n\tratio &= 0x00FF;\n\n\t/*\n\t**\tAdjust the color guns by the ratio specified toward the\n\t**\tdestination color.\n\t*/\n\tint value = (int)rgb.Red - (int)Red;\n\tRed = (int)Red + (value * ratio) / 256;\n\n\tvalue = (int)rgb.Green - (int)Green;\n\tGreen = (int)Green + (value * ratio) / 256;\n\n\tvalue = (int)rgb.Blue - (int)Blue;\n\tBlue = (int)Blue + (value * ratio) / 256;\n}\n\n\n/***********************************************************************************************\n * RGBClass::Difference -- Determines the \"distance\" between two colors.                       *\n *                                                                                             *\n *    This routine is used to calculate a relative distance between two colors. The value is   *\n *    relative only to itself and thus is useful only for determining the magnitude of         *\n *    color difference rather than the nature of the color difference. Palette remapping       *\n *    code uses this routine to find closest matches for colors.                               *\n *                                                                                             *\n * INPUT:   rgb   -- Reference to the color to be compared to this color.                      *\n *                                                                                             *\n * OUTPUT:  Returns the difference between the two colors. The value returned is zero if the   *\n *          colors exactly match. The greater the positive value the greater the difference    *\n *          between the colors.                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/02/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RGBClass::Difference(RGBClass const & rgb) const\n{\n\tint r = (int)Red - (int)rgb.Red;\n\tif (r < 0) r = -r;\n\n\tint g = (int)Green - (int)rgb.Green;\n\tif (g < 0) g = -g;\n\n\tint b = (int)Blue - (int)rgb.Blue;\n\tif (b < 0) b = -b;\n\n\treturn(r*r + g*g + b*b);\n}\n\n\n/***********************************************************************************************\n * RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object.                   *\n *                                                                                             *\n *    This conversion operator will convert an RGBClass object into an HSVClass object.        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a reference (implicit) to the HSVClass object that most closely       *\n *          represents the RGBClass object.                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRGBClass::operator HSVClass (void) const\n{\n\tint hue;\n\tint saturation;\n\tint value;\n\n\t/*\n\t**\tFetch working component values for the color guns.\n\t*/\n\tint red = Red_Component();\n\tint green = Green_Component();\n\tint blue = Blue_Component();\n\n\t/*\n\t**\tThe hue defaults to none. Only if there is a saturation value will the\n\t**\thue be calculated.\n\t*/\n\thue = 0;\n\n\t/*\n\t**\tSet the value (brightness) to match the brightest color gun.\n\t*/\n\tvalue = (red > green) ? red : green;\n\tif (blue > value) value = blue;\n\n\t/*\n\t**\tDetermine the amount of true white present in the color. This is the\n\t**\tminimum color gun value. The white component is used to determine\n\t**\tcolor saturation.\n\t*/\n\tint white = (red < green) ? red : green;\n\tif (blue < white) white = blue;\n\n\t/*\n\t**\tDetermine the saturation (intensity) of the color by comparing the\n\t**\tratio of true white as a component of the overall color. The more\n\t**\twhite component, the less saturation.\n\t*/\n\tsaturation = 0;\n\tif (value) {\n\t\tsaturation = ((value - white) * 255) / value;\n\t}\n\n\t/*\n\t** If there is any saturation at all, then the hue must be calculated. The\n\t**\thue is based on a six sided color wheel.\n\t*/\n\tif (saturation != 0) {\n\t\tunsigned int tmp = value - white;\n\t \tunsigned int r1 = ((value - red) * 255) / tmp;\n\t \tunsigned int g1 = ((value - green) * 255) / tmp;\n\t \tunsigned int b1 = ((value - blue) * 255) / tmp;\n\n\t\t// Find effect of second most predominant color.\n\t\t// In which section of the hexagon of colors does the color lie?\n\t\tif (value == red) {\n\t\t \tif (white == green) {\n\t\t\t\ttmp = 5 * 256 + b1;\n\t\t\t} else {\n\t\t\t\ttmp = 1 * 256 - g1;\n\t\t\t}\n\t\t} else {\n\t\t\tif (value == green) {\n\t\t\t \tif (white == blue) {\n\t\t\t\t\ttmp = 1 * 256 + r1;\n\t\t\t\t} else {\n\t\t\t\t\ttmp = 3 * 256 - b1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t \tif (white == red) {\n\t\t\t\t\ttmp = 3 * 256 + g1;\n\t\t\t\t} else {\n\t\t\t\t\ttmp = 5 * 256 - r1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Divide by six and round.\n\t\thue = tmp / 6;\n\t}\n\n\treturn(HSVClass(hue, saturation, value));\n}\n\n\n/***********************************************************************************************\n * RGBClass::Set -- Set the color index to the RGB object specified.                           *\n *                                                                                             *\n *    This routine will set the specified color index with this RGBClass object. Use this      *\n *    routine to set one color.                                                                *\n *                                                                                             *\n * INPUT:   color -- The color index to set with this RGBClass object.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   02/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RGBClass::Set(int color) const\n{\n\tRaw_Color_Prep(color);\n\tRaw_Set();\n\n\t((RGBClass &)PaletteClass::CurrentPalette[color]) = *this;\n}\n\n"
  },
  {
    "path": "REDALERT/RGB.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RGB.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RGB.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/02/95                                                     *\n *                                                                                             *\n *                  Last Update : December 2, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RGB_H\n#define RGB_H\n\nclass PaletteClass;\nclass HSVClass;\n\n#if (0)\n\n#ifndef OUTPORTB\n#define OUTPORTB\nextern void outportb(int port, unsigned char data);\n#pragma aux outportb parm [edx] [al] =\t\t\\\n\t\t\"out\tdx,al\"\n\nextern void outport(int port, unsigned short data);\n#pragma aux outport parm [edx] [ax] =\t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"inc\tdx\"\t\t\t\\\n\t\t\"mov\tal,ah\"\t\t\\\n\t\t\"out\tdx,al\"\n#endif\n\nextern void outrgb(unsigned char red, unsigned char green, unsigned char blue);\n#pragma aux outrgb parm [al] [bl] [cl] \\\n\t\tmodify [dx al] = \\\n\t\t\"mov\tdx,03C9h\"\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te1\"\t\t\t\\\n\t\t\"e1:\"\t\t\t\t\t\\\n\t\t\"mov\tal,bl\" \t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te2\"\t\t\t\\\n\t\t\"e2:\" \t\t\t\t\\\n\t\t\"mov\tal,cl\" \t\t\\\n\t\t\"out\tdx,al\"\t\t\\\n\t\t\"jmp\te3\"\t\t\t\\\n\t\t\"e3:\"\n\n#endif\n\n/*\n**\tEach color entry is represented by this class. It holds the values for the color\n**\tguns. The gun values are recorded in device dependant format, but the interface\n**\tuses gun values from 0 to 255.\n*/\nclass RGBClass\n{\n//\tstatic RGBClass const BlackColor;\n\n\tpublic:\n\t\tRGBClass(void) : Red(0), Green(0), Blue(0) {};\n\t\tRGBClass(unsigned char red, unsigned char green, unsigned char blue) :\n\t\t\t\tRed((unsigned char)(red>>2)),\n\t\t\t\tGreen((unsigned char)(green>>2)),\n\t\t\t\tBlue((unsigned char)(blue>>2))\n\t\t\t{};\n\t\toperator HSVClass (void) const;\n\t\tRGBClass & operator = (RGBClass const & rgb) {\n\t\t\tif (this == &rgb) return(*this);\n\n\t\t\tRed = rgb.Red;\n\t\t\tGreen = rgb.Green;\n\t\t\tBlue = rgb.Blue;\n\t\t\treturn(*this);\n\t\t};\n\n\t\tenum {\n\t\t\tMAX_VALUE=255\n\t\t};\n\n\t\tvoid Adjust(int ratio, RGBClass const & rgb);\n//\t\tvoid Adjust(int ratio, RGBClass const & rgb = BlackColor);\n\t\tint Difference(RGBClass const & rgb) const;\n\t\tint Red_Component(void) const {return ((Red << 2) | (Red >> 6));};\n\t\tint Green_Component(void) const {return((Green << 2) | (Green >> 6));};\n\t\tint Blue_Component(void) const {return((Blue << 2) | (Blue >> 6));};\n\t\tvoid Set(int color) const;\n\n\tprivate:\n\n\t\tfriend class PaletteClass;\n\n\t\tvoid Raw_Set(void) const {\n\t\t\t//outrgb(Red, Green, Blue);\n\n//\t\t\toutportb(0x03C9, Red);\n//\t\t\toutportb(0x03C9, Green);\n//\t\t\toutportb(0x03C9, Blue);\n\t\t};\n\n\t\tstatic void Raw_Color_Prep(unsigned char color) {\n\t\t\t//outportb(0x03C8, color);\n\t\t};\n\n\t\t/*\n\t\t**\tThese hold the actual color gun values in machine dependant scale. This\n\t\t**\tmeans the values range from 0 to 63.\n\t\t*/\n\t\tunsigned char Red;\n\t\tunsigned char Green;\n\t\tunsigned char Blue;\n};\n\nextern RGBClass const BlackColor;\n\n#endif\n"
  },
  {
    "path": "REDALERT/RNDSTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RNDSTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNDSTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 10, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   RandomStraw::Get -- Fetch random data.                                                    *\n *   RandomStraw::RandomStraw -- Constructor for the random straw class.                       *\n *   RandomStraw::Reset -- Reset the data to known initial state.                              *\n *   RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits.                *\n *   RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value.                  *\n *   RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed.                  *\n *   RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed.                        *\n *   RandomStraw::Seed_Long -- Submit 32 bits to the random number seed.                       *\n *   RandomStraw::Seed_Short -- Submit 16 bits to the random number seed.                      *\n *   RandomStraw::~RandomStraw -- Destructor for random straw class.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<limits.h>\n#include\t<string.h>\n#include\t\"rndstraw.h\"\n#include\t\"sha.h\"\n\n\n/***********************************************************************************************\n * RandomStraw::RandomStraw -- Constructor for the random straw class.                         *\n *                                                                                             *\n *    This will initialize the random straw into a known state. The initial state is useless   *\n *    for cryptographic purposes. It must be seeded before it should be used.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomStraw::RandomStraw(void) :\n\tSeedBits(0),\n\tCurrent(0)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * RandomStraw::~RandomStraw -- Destructor for random straw class.                             *\n *                                                                                             *\n *    This destructor will clear out the seed data so that there won't be any sensitive        *\n *    information left over in the memory this object occupied.                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRandomStraw::~RandomStraw(void)\n{\n\tReset();\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Reset -- Reset the data to known initial state.                                *\n *                                                                                             *\n *    This routine is functionally equivalent to performing an placement new on the object. It *\n *    clears out all the seed data.                                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must reseed it before fetching random numbers.                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Reset(void)\n{\n\tSeedBits = 0;\n\tCurrent = 0;\n\tmemset(Random, '\\0', sizeof(Random));\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed.                    *\n *                                                                                             *\n *    This routine is used when seeding the random straw. Keep feeding random bits to this     *\n *    class until the Seed_Bits_Needed value returns zero. Random bits should be gathered from *\n *    sources external to the immediate program. Examples would be the system clock (good for  *\n *    a few bits), the delay between player keystrokes (good for a few bits per keystroke),    *\n *    etc. When gathering random bits from integers, use the low order bits (since they        *\n *    characteristically are less predictable and more 'random' than the others).              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bits required in order to fully seed this random        *\n *          number generator.                                                                  *\n *                                                                                             *\n * WARNINGS:   Even if this routine returns zero, you are still allowed and encouraged to feed *\n *             more random bits when the opportunity arrises.                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint RandomStraw::Seed_Bits_Needed(void) const\n{\n\tconst int total = sizeof(Random) * CHAR_BIT;\n\tif (SeedBits < total) {\n\t\treturn(total - SeedBits);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value.                    *\n *                                                                                             *\n *    This routine should be called to feed a single random bit to the random straw object.    *\n *    You must feed as many bits as requested by the Seed_Bits_Needed() function. Submitting   *\n *    additional bits is not only allowed, but encouraged.                                     *\n *                                                                                             *\n * INPUT:   seed  -- The bit (lowest order bit) to feed to the random number seed.             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Bit(int seed)\n{\n\tchar * ptr = ((char *)&Random[0]) + ((SeedBits / CHAR_BIT) % sizeof(Random));\n\tchar frac = (char)(1 << (SeedBits & (CHAR_BIT-1)));\n\n\tif (seed & 0x01) {\n\t\t*ptr ^= frac;\n\t}\n\tSeedBits++;\n\n\tif (SeedBits == (sizeof(Random) * CHAR_BIT)) {\n\t\tScramble_Seed();\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed.                          *\n *                                                                                             *\n *    This will submit 8 bits (as specified) to the random number seed.                        *\n *                                                                                             *\n * INPUT:   seed  -- The seed bits to submit.                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Byte(char seed)\n{\n\tfor (int index = 0; index < CHAR_BIT; index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Short -- Submit 16 bits to the random number seed.                        *\n *                                                                                             *\n *    This will submit 16 bits to the accumulated seed.                                        *\n *                                                                                             *\n * INPUT:   seed  -- The 16 bits to submit to the seed.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Short(short seed)\n{\n\tfor (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Seed_Long -- Submit 32 bits to the random number seed.                         *\n *                                                                                             *\n *    This will submit a full 32 bits to the accumulated seed value.                           *\n *                                                                                             *\n * INPUT:   seed  -- The 32 bits to submit.                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Seed_Long(long seed)\n{\n\tfor (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) {\n\t\tSeed_Bit(seed);\n\t\tseed >>= 1;\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits.                  *\n *                                                                                             *\n *    This routine is called when a full set of seed bits has been accumulated. It will take   *\n *    the existing seed and scramble the bits. An effective way of doing this is to use the    *\n *    Secure Hash Algorithm. It is necessary to have this routine because there might be       *\n *    some coorelation in the seed bits. Even more important is that this routine will result  *\n *    in every bit of the seed having a scrambling effect on every other bit.                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid RandomStraw::Scramble_Seed(void)\n{\n\tSHAEngine sha;\n\n\tfor (int index = 0; index < sizeof(Random); index++) {\n\t\tchar digest[20];\n\n\t\tsha.Hash(&Random[0], sizeof(Random));\n\t\tsha.Result(digest);\n\n\t\tint tocopy = sizeof(digest) < (sizeof(Random)-index) ? sizeof(digest) : (sizeof(Random)-index);\n\t\tmemmove(((char *)&Random[0]) + index, digest, tocopy);\n\t}\n}\n\n\n/***********************************************************************************************\n * RandomStraw::Get -- Fetch random data.                                                      *\n *                                                                                             *\n *    This routine will fetch random data and store it into the buffer specified.              *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to fill with random data.                        *\n *                                                                                             *\n *          length   -- The number of bytes to store into the buffer.                          *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes stored into the buffer. This will always   *\n *          be the number of bytes requested since random numbers are unexhaustible.           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1996 JLB : Created.                                                                 *\n *   07/10/1996 JLB : Revamped to make cryptographically secure.                               *\n *=============================================================================================*/\nint RandomStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(Straw::Get(source, slen));\n\t}\n\n\tint total = 0;\n\twhile (slen > 0) {\n\t\t*(char *)source = (char)Random[Current++];\n\t\tCurrent = Current % (sizeof(Random) / sizeof(Random[0]));\n\t\tsource = (char*)source + sizeof(char);\n\t\tslen--;\n\t\ttotal++;\n\t}\n\treturn(total);\n}\n"
  },
  {
    "path": "REDALERT/RNDSTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RNDSTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNDSTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/04/96                                                     *\n *                                                                                             *\n *                  Last Update : July 4, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RNDSTRAW_H\n#define RNDSTRAW_H\n\n\n#include\t\"straw.h\"\n#include\t\"random.h\"\n\n/*\n**\tThis is a straw terminator class. It will generate random numbers to fill the data request.\n**\tUnlike regular straw terminators, this class will never run out of \"data\".\n*/\nclass RandomStraw : public Straw\n{\n\tpublic:\n\t\tRandomStraw(void);\n\t\tvirtual ~RandomStraw(void);\n\n\t\tvirtual int Get(void * source, int slen);\n\n\t\tvoid Reset(void);\n\t\tvoid Seed_Bit(int seed);\n\t\tvoid Seed_Byte(char seed);\n\t\tvoid Seed_Short(short seed);\n\t\tvoid Seed_Long(long seed);\n\n\t\tint Seed_Bits_Needed(void) const;\n\n\tprivate:\n\t\t/*\n\t\t**\tCounter of the number of seed bits stored to this random number\n\t\t**\tgenerator.\n\t\t*/\n\t\tint SeedBits;\n\n\t\t/*\n\t\t**\tThe current random generator to use when fetching the next random\n\t\t**\tbyte of data.\n\t\t*/\n\t\tint Current;\n\n\t\t/*\n\t\t**\tArray of generators. There must be at least 448 bits of random number seed\n\t\t**\tin order to be reasonably secure, however, using 1024 bits would be best.\n\t\t*/\n\t\tRandomClass Random[32];\n\n\t\tvoid Scramble_Seed(void);\n\n\t\tRandomStraw(RandomStraw & rvalue);\n\t\tRandomStraw & operator = (RandomStraw const & pipe);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/RNG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RNG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RNG.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef RNG_H\n#define RNG_H\n\n/*\n**\tThis is an abstract interface class for a random number generator. It serves only to\n**\tprovide random numbers.\n*/\nclass RandomNumberGenerator {\n\tpublic:\n\t\tvirtual ~RandomNumberGenerator() {}\n\n\t\tvirtual void Get_Block(void * output, unsigned int size) = 0;\n};\n\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/ROTBMP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/ROTBMP.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ROTBMP.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/05/96                                                     *\n *                                                                                             *\n *                  Last Update : July 5, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#if (0)//PG\n//#include\t\"function.h\"\n#include\t\"watcom.h\"\n#include \"rotbmp.h\"\n#define FILE_H\n#define WWMEM_H\n#include\t<wwlib32.h>\n\n\nint Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int angle);\n\nstruct WPPOINT {\n\tint x;\n\tint y;\n};\n\n/***************************************************************************\n * Rotate_bitmap -- rotate a bitmap from srcvp to destvp                   *\n *                                                                         *\n * INPUT: note that angles are 0 - 255 (best if used in increments of 4!)  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *\t   destvp should be a square. width and height should be equal to : \t \t*\n * \tMAX(srcvp->width,srcvp->height) * 1.7 (square root of 2!!)    \t\t \t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t*\n * HISTORY:                                                                *\n *   01/02/1996  BP : Created.                                             *\n *=========================================================================*/\nRotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int a)\n{\n\tint shift = 7;\n\tint fixpoint1 = 1 << shift; // this is a fixed point 1\n\tint Deltax;\n\tint Deltay;\n\tint sx,sy,dx,dy;\n\tint Error = 0;\n\tint Decimal = 0;\n\t// this is used if I walk in Y\n\tint buffwidth = srcvp->Get_Width() + srcvp->Get_XAdd();\n\tint buffwid2 = destvp->Get_Width() + destvp->Get_XAdd();\n\tchar * dest;\n\tchar * src;\n\tint sa,ca;\n\tint t;\n\tint x,y;\n\tint rx,ry;\n\tint w,h;\n\tint dw = destvp->Get_Width();\n\tint dh = destvp->Get_Height();\n\tWPPOINT sp[4];\n\tWPPOINT dp[4];\n\tsa = Sin256[a];\n\tca = Cos256[a];\n\t// get rectangle size\n\tx = 0;\n\ty = 0;\n\tw = srcvp->Get_Width();\n\th = srcvp->Get_Height();\n\n\tint halfws = w >> 1;\n\tint halfhs = h >> 1;\n\tint halfwd = dw >> 1;\n\tint halfhd = dh >> 1;\n\n\n\t// make the src rectangle\n\tsp[0].x = x;\n\tsp[0].y = y;\n\n\tsp[1].x = x + w;\n\tsp[1].y = y;\n\n\t// now calculate the rotated rectangle\n\tdp[0].x = ( ((sp[0].x - halfws) * ca) - ((sp[0].y - halfhs) * sa) ) >> shift;\n\tdp[0].x += halfwd;\n\n\tdp[0].y = ( ((sp[0].x - halfws) * sa) + ((sp[0].y - halfhs) * ca) ) >> shift;\n\tdp[0].y += halfhd;\n\n\tdp[1].x = ( ((sp[1].x - halfws) * ca) - ((sp[1].y - halfhs) * sa) ) >> shift;\n\tdp[1].x += halfwd;\n\n\tdp[1].y = ( ((sp[1].x - halfws) * sa) + ((sp[1].y - halfhs) * ca) ) >> shift;\n\tdp[1].y += halfhd;\n\n\trx = dp[0].x;\n\try = dp[0].y;\n\t// now calculate slope\n\n\t// diff from new to old x\n\n\tDeltax = (dp[1].x - dp[0].x);\n\n\t// diff from new to old y\n\n\tDeltay = (dp[1].y - dp[0].y);\n\n\t// handle the easy cases\n\n\t// no change in x\n\tint r;\n\tif (!Deltax) { // must be 90 or 270 degree transpose!\n\t\tif (Deltay < 0) {\n\t\t\t// walk across source in the x + dir\n\t\t\t// walk across dest in the y - dir\n\n\t\t\tx = 0;\n\t\t\tdy = 0;\n\t\t\tdx = 0;\n\t\t\tfor (t = 0; t< h; t++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx + dx, ry - dy);\n\t\t\t\tfor (r = 0; r< w; r++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (* src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tsrc++;\n\t\t\t\t\tdest -= buffwid2;\n\t\t\t\t}\n\t\t\t\ty++;\n\t\t\t\tdx++;\n\t\t\t}\n\t\t} else {\n\t\t\t// walk across source in the x + dir\n\t\t\t// walk across dest in the y + dir\n\n\t\t\tx = 0;\n\t\t\tdy = 0;\n\t\t\tdx = 0;\n\t\t\tfor (t = 0; t< h; t++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx - dx, ry + dy);\n\t\t\t\tfor (r = 0; r< w; r++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tsrc++;\n\t\t\t\t\tdest += buffwid2;\n\t\t\t\t}\n\t\t\t\ty++;\n\t\t\t\tdx++;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\t// no change in y\n\n\tif (!Deltay) { // must be 0 or 180 degree transpose !\n\t\tif (Deltax < 0) {\n\t\t\ty = 0;\n\t\t\tfor (y = 0; y< h; y++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx - x , ry - y);\n\t\t\t\tfor (x = 0 ; x< w; x++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest--;\n\t\t\t\t\tsrc++;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (y = 0; y< h; y++) {\n\t\t\t\tx = 0;\n\t\t\t\tsrc = MAKE_PTR(srcvp, x, y);\n\t\t\t\tdest = MAKE_PTR(destvp, rx + x, ry + y);\n\t\t\t\tfor (x = 0 ; x< w; x++) {\n\t\t\t\t\t// transparency\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest++;\n\t\t\t\t\tsrc++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\t// ok now the hard part\n\n\t// make them 16.16\n\tif ( ABS(Deltax) < ABS(Deltay)) { // ok this means we want to walk in y\n\n\t\t// walk in  + x in the src and\n\t\t// walk in  + y in the dest\n\t\tError = 0;\n\t\t// start at left top corner in src and dest\n\n\t\tsx = 0;\n\t\tsy = 0;\n\n\t\tdx = 0;\n\t\tdy = 0;\n\n\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\n\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t// this gets added to error each inc of x\n\t\t// when error is > 1 then inc y!\n\t\tint xinc = 1;\n\t\tif (Deltax < 0) {\n\t\t\tDeltax = -Deltax;\n\t\t\txinc = -1;\n\t\t}\n\t\tint yinc = 1;\n\t\tint yinc1 = 1;\n\t\tif (Deltay < 0) {\n\t\t\tDeltay = - Deltay;\n\t\t\tbuffwid2 = - buffwid2;\n\t\t}\n\t\tDecimal = ( Deltax << shift) / Deltay ;\n\t\t// walk in X\n\n\t\tint Deltax2 = Deltax << shift;\n\t\tint Deltay2 = Deltay << shift;\n\n\t\t// this is the ratio between the source height and the dest height\n\t\t// as the rectangle rotates the height and width change\n\t\tint DeltaH = (w << shift) / Deltay;\n\t\tint Error2 = 0;\n\t\tsy = 0;\n\t\tfor (int r = 0; r< h ;r++) {\n\t\t\t// now we walk across the top calculating each rotated point\n\t\t\t// along the side\n\t\t\t// the use delta formula to walk in x and y in destination space\n\t\t\t// always walking in the x in the source!\n\t\t\t// figure out rotated location to start in dest\n\t\t\trx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\t\t\trx += halfwd;\n\t\t\try = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\try += halfhd;\n\n\t\t\t// this is the end point of the line\n\n\t\t\tint y2 = ( ( ((w) - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\ty2 += halfhd;\n\n\t\t\t// length of line\n\n\t\t\tint diff = ABS(y2 - ry);\n\n\t\t\t// if walking backwards reveres diff to reflect sign\n\n\t\t\tsrc = MAKE_PTR(srcvp, x, y + sy);\n\n\t\t\tdest = MAKE_PTR(destvp, rx, ry);\n\n\t\t\tError = 0;\n\t\t\tError2 = 0;\n\t\t\tchar * baseptr = src;\n\t\t\t// while walking line\n\t\t\twhile (diff--) {\n\t\t\t\tchar c = *src;\n\t\t\t\t// transparency\n\t\t\t\tif (c)\n\t\t\t\t\t*dest = *src;\n\t\t\t\tError2 += DeltaH;\n\t\t\t\tdest += buffwid2;\n\t\t\t\tError += Decimal;\n\t\t\t\tsrc = baseptr + (Error2 >> shift) ;\n\t\t\t\t// this is time to inc x in src y in dest\n\t\t\t\tif (Error >= fixpoint1) {\n\t\t\t\t\tError -= fixpoint1;\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest += xinc;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsy += yinc;\n\t\t}\n\t\treturn 0;\n\t} else { // else we walk in X\n\t\tint lasterror = 0;\n\t\tError = 0;\n\t\t// start at left top corner in src and dest\n\n\t\tsx = 0;\n\t\tsy = 0;\n\n\t\tdx = 0;\n\t\tdy = 0;\n\n\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\n\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t// this gets added to error each inc of x\n\t\t// when error is > 1 then inc y!\n\t\tint xinc = 1;\n\t\tif (Deltax < 0) {\n\t\t\tDeltax = -Deltax;\n\t\t\txinc = -1;\n\t\t}\n\t\tint yinc = 1;\n\t\tif (Deltay < 0) {\n\t\t\tDeltay = - Deltay;\n\t\t\tbuffwid2 = - buffwid2;\n\t\t\tsy = sy + h - 1;\n\t\t\tyinc = -1;\n\t\t}\n\n\n\t\tDecimal = ( Deltay << shift) / Deltax ;\n\t\t// walk in X\n\n\t\tint Deltax2 = Deltax << shift;\n\t\tint Deltay2 = Deltay << shift;\n\n\t\t// this is the ratios between the source width and the dest width\n\t\t// as the rectangle rotates the actual size changes!\n\n\t\tint DeltaW = (w << shift) / Deltax;\n\t\tint Error2 = 0;\n\t\tfor (int r = 0; r< h ;r++) {\n\t\t\tsx = 0;\n\n\t\t\t// now we walk across the side calculating each rotated point\n\t\t\t// along the side\n\t\t\t// the use delta formula to walk in x and y in destination space\n\t\t\t// always walking in the x in the source!\n\t\t\t// figure out rotated location to start\n\n\t\t\trx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\t\t\trx += halfwd;\n\t\t\try = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;\n\t\t\try += halfhd;\n\t\t\t// this is the other side of the box\n\n\t\t\tint x2 = ( ( ((sx + w) - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;\n\n\t\t\tx2 += halfwd;\n\n\t\t\tint diff = x2 - rx;\n\n\n\t\t\tdx = 0;\n\t\t\tdy = 0;\n\n\t\t\tif (xinc == -1) {\n\t\t\t\tdiff = -diff;\n\t\t\t}\n\n\t\t\tsrc = MAKE_PTR(srcvp, x + sx, y + sy);\n\n\t\t\tdest = MAKE_PTR(destvp, rx + dx, ry + dy);\n\t\t\tError = 0;\n\t\t\tError2 = 0;\n\t\t\tchar * baseptr = src;\n\n\t\t\twhile (diff--) {\n\t\t\t\tchar c = *src;\n\t\t\t\t// transparency\n\t\t\t\tif (c)\n\t\t\t\t\t*dest = *src;\n\t\t\t\tError2 += DeltaW;\n \t\t\t\trx++;\n\t\t\t\tdest += xinc;\n\t\t\t\tError += Decimal;\n\t\t\t\tsrc = baseptr + (Error2 >> shift);\n\t\t\t\tif (Error >= fixpoint1) {\n\t\t\t\t\tError -= fixpoint1;\n\t\t\t\t\tif (*src)\n\t\t\t\t\t\t*dest = *src;\n\t\t\t\t\tdest += buffwid2;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsy += yinc;\n\t\t}\n\t}\n\treturn 0;\n}\n#endif"
  },
  {
    "path": "REDALERT/ROTBMP.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n// list of 256 sines\n\n#define MAKE_PTR(vp,x,y) (char *) (vp->Get_Offset() + ((y) * (vp->Get_Width() + vp->Get_XAdd())) + (x))\n#define MAKE_PTR2(vp,x,y) (char *) (vp->Get_Offset() + (((y)<<1) * (vp->Get_Width() + vp->Get_XAdd())) + ((x)<<1))\n\n#ifndef WIN32\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\nlong Cos256[] = {\n     128,     127,     127,     127,     127,     127,     126,     126,\n     125,     124,     124,     123,     122,     121,     120,     119,\n     118,     116,     115,     114,     112,     111,     109,     107,\n     106,     104,     102,     100,      98,      96,      94,      92,\n      90,      87,      85,      83,      80,      78,      75,      73,\n      70,      68,      65,      62,      59,      57,      54,      51,\n      48,      45,      42,      39,      36,      33,      30,      27,\n      24,      21,      18,      14,      11,       8,       5,       2,\n       0,      -3,      -7,     -10,     -13,     -16,     -19,     -22,\n     -25,     -28,     -31,     -35,     -38,     -41,     -44,     -46,\n     -49,     -52,     -55,     -58,     -61,     -63,     -66,     -69,\n     -72,     -74,     -77,     -79,     -82,     -84,     -86,     -89,\n     -91,     -93,     -95,     -97,     -99,    -101,    -103,    -105,\n    -107,    -108,    -110,    -112,    -113,    -114,    -116,    -117,\n    -118,    -119,    -120,    -121,    -122,    -123,    -124,    -125,\n    -125,    -126,    -126,    -127,    -127,    -127,    -127,    -127,\n    -127,    -127,    -127,    -127,    -127,    -126,    -126,    -125,\n    -125,    -124,    -123,    -122,    -121,    -120,    -119,    -118,\n    -117,    -116,    -114,    -113,    -112,    -110,    -108,    -107,\n    -105,    -103,    -101,     -99,     -97,     -95,     -93,     -91,\n     -89,     -86,     -84,     -82,     -79,     -77,     -74,     -72,\n     -69,     -66,     -64,     -61,     -58,     -55,     -52,     -49,\n     -46,     -44,     -41,     -38,     -35,     -31,     -28,     -25,\n     -22,     -19,     -16,     -13,     -10,      -7,      -3,       0,\n       2,       5,       8,      11,      14,      18,      21,      24,\n      27,      30,      33,      36,      39,      42,      45,      48,\n      51,      54,      57,      59,      62,      65,      68,      70,\n      73,      75,      78,      80,      83,      85,      87,      90,\n      92,      94,      96,      98,     100,     102,     104,     106,\n     107,     109,     111,     112,     114,     115,     116,     118,\n     119,     120,     121,     122,     123,     124,     124,     125,\n     126,     126,     127,     127,     127,     127,     127,     127,\n};\nlong Sin256[] = {\n       0,       3,       6,       9,      12,      15,      18,      21,\n      25,      28,      31,      34,      37,      40,      43,      46,\n      49,      52,      54,      57,      60,      63,      66,      68,\n      71,      73,      76,      79,      81,      83,      86,      88,\n      90,      92,      95,      97,      99,     101,     103,     104,\n     106,     108,     110,     111,     113,     114,     115,     117,\n     118,     119,     120,     121,     122,     123,     124,     125,\n     125,     126,     126,     127,     127,     127,     127,     127,\n     127,     127,     127,     127,     127,     126,     126,     125,\n     125,     124,     123,     123,     122,     121,     120,     119,\n     117,     116,     115,     113,     112,     110,     109,     107,\n     105,     104,     102,     100,      98,      96,      94,      91,\n      89,      87,      85,      82,      80,      77,      75,      72,\n      70,      67,      64,      61,      59,      56,      53,      50,\n      47,      44,      41,      38,      35,      32,      29,      26,\n      23,      20,      17,      14,      11,       7,       4,       1,\n      -1,      -4,      -7,     -11,     -14,     -17,     -20,     -23,\n     -26,     -29,     -32,     -35,     -38,     -41,     -44,     -47,\n     -50,     -53,     -56,     -59,     -61,     -64,     -67,     -70,\n     -72,     -75,     -77,     -80,     -82,     -85,     -87,     -89,\n     -91,     -94,     -96,     -98,    -100,    -102,    -104,    -105,\n    -107,    -109,    -110,    -112,    -113,    -115,    -116,    -117,\n    -119,    -120,    -121,    -122,    -123,    -123,    -124,    -125,\n    -125,    -126,    -126,    -127,    -127,    -127,    -127,    -127,\n    -127,    -127,    -127,    -127,    -127,    -126,    -126,    -125,\n    -125,    -124,    -123,    -122,    -121,    -120,    -119,    -118,\n    -117,    -115,    -114,    -113,    -111,    -110,    -108,    -106,\n    -104,    -103,    -101,     -99,     -97,     -95,     -92,     -90,\n     -88,     -86,     -83,     -81,     -79,     -76,     -73,     -71,\n     -68,     -66,     -63,     -60,     -57,     -54,     -52,     -49,\n     -46,     -43,     -40,     -37,     -34,     -31,     -28,     -25,\n     -21,     -18,     -15,     -12,      -9,      -6,      -3,       0,\n};\n"
  },
  {
    "path": "REDALERT/RULES.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RULES.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RULES.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/12/96                                                     *\n *                                                                                             *\n *                  Last Update : September 10, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Difficulty_Get -- Fetch the difficulty bias values.                                       *\n *   RulesClass::AI -- Processes the AI control constants from the database.                   *\n *   RulesClass::General -- Process the general main game rules.                               *\n *   RulesClass::Heap_Maximums -- Fetch and process the heap override values.                  *\n *   RulesClass::IQ -- Fetches the IQ control values from the INI database.                    *\n *   RulesClass::Land_Types -- Inits the land type values.                                     *\n *   RulesClass::MPlayer -- Fetch and process the multiplayer default settings.                *\n *   RulesClass::Powerups -- Process the powerup values from the database.                     *\n *   RulesClass::Process -- Fetch the bulk of the rule data from the control file.             *\n *   RulesClass::Recharge -- Process the super weapon recharge statistics.                     *\n *   RulesClass::RulesClass -- Default constructor for rules class object.                     *\n *   RulesClass::Themes -- Fetches the theme control values from the INI database.             *\n *   Techno_Get -- Get rule data common for all techno type objects.                           *\n *   _Scale_To_256 -- Scales a 1..100 number into a 1..255 number.                             *\n *   RulesClass::Difficulty -- Fetch the various difficulty group settings.                    *\n *   RulesClass::Objects -- Fetch all the object characteristic values.                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n\n\n/***********************************************************************************************\n * _Scale_To_256 -- Scales a 1..100 number into a 1..255 number.                               *\n *                                                                                             *\n *    This is a helper routine that will take a decimal percentage number and convert it       *\n *    into a game based fixed point number.                                                    *\n *                                                                                             *\n * INPUT:   val   -- Decimal percent number to convert.                                        *\n *                                                                                             *\n * OUTPUT:  Returns with the decimal percent number converted to a game fixed point number.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic inline int _Scale_To_256(int val)\n{\n\tval = fixed(100, 256) * val;\n\tval = min(val, 255);\n\treturn(val);\n}\n\n\n/***********************************************************************************************\n * RulesClass::RulesClass -- Default constructor for rules class object.                       *\n *                                                                                             *\n *    This is the default constructor for the rules class object. Although it initializes the  *\n *    rule data with default values, it is expected that they will all be overridden by the    *\n *    rules control file.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nRulesClass::RulesClass(void) :\n\tTurboBoost(\"1.5\"),\n\tAttackInterval(3),\n\tAttackDelay(5),\n\tPowerEmergencyFraction(fixed::_3_4),\n\tBadgerBombCount(1),\n\tAirstripRatio(\".12\"),\n\tAirstripLimit(5),\n\tHelipadRatio(\".12\"),\n\tHelipadLimit(5),\n\tTeslaRatio(\".16\"),\n\tTeslaLimit(10),\n\tAARatio(\".14\"),\n\tAALimit(10),\n\tDefenseRatio(\".5\"),\n\tDefenseLimit(40),\n\tWarRatio(\".1\"),\n\tWarLimit(2),\n\tBarracksRatio(\".16\"),\n\tBarracksLimit(2),\n\tRefineryLimit(4),\n\tRefineryRatio(\".16\"),\n\tBaseSizeAdd(3),\n\tPowerSurplus(50),\n\tInfantryReserve(2000),\n\tInfantryBaseMult(2),\n\tChronoDuration(3),\n\tWaterCrateChance(\".2\"),\n\tSoloCrateMoney(2000),\n\tGPSTechLevel(0),\n\tUnitCrateType(UNIT_NONE),\n\tPatrolTime(\".016\"),\n\tTeamDelay(\".6\"),\n\tCloakDelay(0),\n\tGameSpeedBias(1),\n\tNervousBias(1),\n\tVortexRange(10*CELL_LEPTON_W),\n\tVortexSpeed((MPHType)10),\n\tVortexDamage(200),\n\tVortexChance(\".2\"),\n\tExplosionSpread(fixed::_1_2),\n\tSupressRadius(CELL_LEPTON_W),\n\tParaInfantryTechLevel(10),\n\tSpyPlaneTechLevel(10),\n\tParaBombTechLevel(10),\n\tMaxIQ(5),\n\tIQSuperWeapons(4),\n\tIQProduction(5),\n\tIQGuardArea(4),\n\tIQRepairSell(3),\n\tIQCrush(2),\n\tIQScatter(3),\n\tIQContentScan(4),\n\tIQAircraft(4),\n\tIQHarvester(3),\n\tIQSellBack(2),\n\tSilverCrate(CRATE_HEAL_BASE),\n\tWoodCrate(CRATE_MONEY),\n\tWaterCrate(CRATE_MONEY),\n\tCrateMinimum(1),\n\tCrateMaximum(255),\n\tLZScanRadius(16*CELL_LEPTON_W),\n\tMPDefaultMoney(3000),\n\tMPMaxMoney(10000),\n\tIsMPShadowGrow(true),\n\tIsMPBasesOn(true),\n\tIsMPTiberiumGrow(true),\n\tIsMPCrates(true),\n\tIsMPAIPlayers(false),\n\tIsMPCaptureTheFlag(false),\n\tDropZoneRadius(4*CELL_LEPTON_W),\n\tMessageDelay(\".6\"),\n\tSavourDelay(\".03\"),\n\tAVMineDamage(1200),\n\tAPMineDamage(1000),\n\tMaxPlayers(8),\n\tBaseDefenseDelay(fixed::_1_4),\n\tSuspendPriority(20),\n\tSuspendDelay(2),\n\tSurvivorFraction(fixed::_1_2),\n\tReloadRate(\".05\"),\n\tAutocreateTime(5),\n\tBuildupTime(\".05\"),\n\tOreDumpRate(2),\n\tAtomDamage(1000),\n\tIsComputerParanoid(true),\n\tIsCurleyShuffle(false),\n\tIsFlashLowPower(true),\n\tIsCompEasyBonus(true),\n\tIsFineDifficulty(false),\n\tIsExplosiveHarvester(false),\n\tIsMCVDeploy(false),\n\tIsAllyReveal(true),\n\tIsSeparate(false),\n\tIsTreeTarget(false),\n\tIsMineAware(true),\n\tIsTGrowth(true),\n\tIsTSpread(true),\n\tIsNamed(false),\n\tIsAutoCrush(false),\n\tIsSmartDefense(false),\n\tIsScatter(false),\n\tIsChronoKill(true),\n\tProneDamageBias(fixed::_1_2),\n\tQuakeDamagePercent(\".33\"),\n\tQuakeChance(\".2\"),\n\tGrowthRate(2),\n\tShroudRate(4),\n\tCrateTime(10),\n\tTimerWarning(2),\n\tChronoTechLevel(1),\n\tSonarTime(14),\n\tChronoTime(3),\n\tParaBombTime(14),\n\tParaInfantryTime(2),\n\tParaSaboteurTime(14),\n\tSpyTime(2),\n\tIronCurtainTime(14),\n\tGPSTime(1),\n\tNukeTime(14),\n\tSpeakDelay(2),\n\tDamageDelay(1),\n\tGravity(3),\n\tGapShroudRadius(10),\n\tGapRegenInterval(\".1\"),\n\tRadarJamRadius(10*CELL_LEPTON_W),\n\tIncoming(MPH_IMMOBILE),\n\tMinDamage(1),\n\tMaxDamage(1000),\n\tRepairStep(5),\n\tRepairPercent(fixed::_1_4),\n\tURepairStep(5),\n\tURepairPercent(fixed::_1_4),\n\tRepairRate(\".016\"),\n\tConditionGreen(1),\n\tConditionYellow(fixed::_1_2),\n\tConditionRed(fixed::_1_4),\n\tRandomAnimateTime(\".083\"),\n\tBailCount(28),\n\tGoldValue(35),\n\tGemValue(110),\n\tAircraftMax(100),\n\tAnimMax(100),\n\tBuildingMax(500),\n\tBulletMax(40),\n\tFactoryMax(20),\n\tInfantryMax(500),\n\tOverlayMax(1),\n\tSmudgeMax(1),\n\tTeamMax(60),\n\tTeamTypeMax(60),\n\tTemplateMax(1),\n\tTerrainMax(500),\n\tTriggerMax(60),\n\tUnitMax(500),\n\tVesselMax(100),\n\tProjectileMax(20),\n\tWeaponMax(20),\n\tWarheadMax(20),\n\tTrigTypeMax(80),\n\tCloseEnoughDistance(0x0280),\n\tStrayDistance(0x0200),\n\tCrushDistance(0x0180),\n\tCrateRadius(0x0280),\n\tHomingScatter(0x0200),\n\tBallisticScatter(0x0100),\n\tRefundPercent(fixed::_1_2),\n\tIronCurtainDuration(fixed::_1_2),\n\tBridgeStrength(1000),\n\tBuildSpeedBias(1),\n\tC4Delay(\".03\"),\n\tRepairThreshhold(1000),\n\tPathDelay(\".016\"),\n\tMovieTime(fixed::_1_4),\n\tTiberiumShortScan(0x0600),\n\tTiberiumLongScan(0x2000),\n\tHealthBarDisplayMode(HB_SELECTED),\n\tResourceBarDisplayMode(RB_SELECTED)\n{\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tNewUnitsEnabled = SecretUnitsEnabled = 0;\n\tMTankDistance = 30;\n\tQuakeUnitDamage = 0x080;\n\tQuakeBuildingDamage = 0x040;\n\tQuakeInfantryDamage = 0;\n\tQuakeDelay      = 120;\n\tChronoTankDuration = 0x300;\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\tEngineerDamage=(fixed)1 / (fixed)3;\t// Amount of damage an engineer does\n\tEngineerCaptureLevel=ConditionRed;\t// Building damage level before engineer can capture\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tCarrierLaunchDelay = 60;\n#endif\n#endif\n}\n\n\n/***********************************************************************************************\n * Difficulty_Get -- Fetch the difficulty bias values.                                         *\n *                                                                                             *\n *    This will fetch the difficulty bias values for the section specified.                    *\n *                                                                                             *\n * INPUT:   ini   -- Reference the INI database to fetch the values from.                      *\n *                                                                                             *\n *          diff  -- Reference to the difficulty class object to fill in with the values.      *\n *                                                                                             *\n *          section  -- The section identifier to lift the values from.                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Difficulty_Get(CCINIClass & ini, DifficultyClass & diff, char const * section)\n{\n\tif (ini.Is_Present(section)) {\n\t\tdiff.FirepowerBias = ini.Get_Fixed(section, \"FirePower\", 1);\n\t\tdiff.GroundspeedBias = ini.Get_Fixed(section, \"Groundspeed\", 1);\n\t\tdiff.AirspeedBias = ini.Get_Fixed(section, \"Airspeed\", 1);\n\t\tdiff.ArmorBias = ini.Get_Fixed(section, \"Armor\", 1);\n\t\tdiff.ROFBias = ini.Get_Fixed(section, \"ROF\", 1);\n\t\tdiff.CostBias = ini.Get_Fixed(section, \"Cost\", 1);\n\t\tdiff.RepairDelay = ini.Get_Fixed(section, \"RepairDelay\", \".02\");\n\t\tdiff.BuildDelay = ini.Get_Fixed(section, \"BuildDelay\", \".03\");\n\t\tdiff.IsBuildSlowdown = ini.Get_Bool(section, \"BuildSlowdown\", false);\n\t\tdiff.BuildSpeedBias = ini.Get_Fixed(section, \"BuildTime\", 1);\n\t\tdiff.IsWallDestroyer = ini.Get_Bool(section, \"DestroyWalls\", true);\n\t\tdiff.IsContentScan = ini.Get_Bool(section, \"ContentScan\", false);\n\t}\n}\n\n\n/***********************************************************************************************\n * RulesClass::Process -- Fetch the bulk of the rule data from the control file.               *\n *                                                                                             *\n *    This routine will fetch the rule data from the control file.                             *\n *                                                                                             *\n * INPUT:   file  -- Reference to the rule file to process.                                    *\n *                                                                                             *\n * OUTPUT:  bool; Was the rule file processed?                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/17/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Process(CCINIClass & ini)\n{\n\tBStart(BENCH_RULES);\n\n\tGeneral(ini);\n\tMPlayer(ini);\n\tRecharge(ini);\n\tHeap_Maximums(ini);\n\tAI(ini);\n\tPowerups(ini);\n\tLand_Types(ini);\n\tThemes(ini);\n\tIQ(ini);\n\tObjects(ini);\n\tDifficulty(ini);\n\n\tBEnd(BENCH_RULES);\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::General -- Process the general main game rules.                                 *\n *                                                                                             *\n *    This fetches the control constants uses for regular game processing. Any game behavior   *\n *    controlling values that don't properly fit in any of the other catagories will be        *\n *    stored here.                                                                             *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database to fetch the values from.                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the general section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::General(CCINIClass & ini)\n{\n\tstatic char const * const GENERAL = \"General\";\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tstatic char const * const AFTERMATH = \"Aftermath\";\n\n\tif(ini.Is_Present(AFTERMATH)) {\n//debugprint( \"NewUnitsEnabled previously %i\\n\", NewUnitsEnabled );\n\t\tNewUnitsEnabled = ini.Get_Int(AFTERMATH, \"NewUnitsEnabled\", 0);\n//debugprint( \"NewUnitsEnabled set to %i by Rules\\n\", NewUnitsEnabled );\n\t\tMTankDistance = ini.Get_Int(AFTERMATH,\"MTankDistance\",MTankDistance);\n\t\tQuakeUnitDamage = ini.Get_Fixed(AFTERMATH, \"QuakeUnitDamage\", QuakeUnitDamage);\n\t\tQuakeBuildingDamage = ini.Get_Fixed(AFTERMATH, \"QuakeBuildingDamage\", QuakeBuildingDamage);\n\t\tQuakeInfantryDamage = ini.Get_Int(AFTERMATH,\"QuakeInfantryDamage\",QuakeInfantryDamage);\n\t\tQuakeDelay      = ini.Get_Int(AFTERMATH,\"QuakeDelay\",QuakeDelay);\n\t\tChronoTankDuration = ini.Get_Fixed(AFTERMATH, \"ChronoTankDuration\", ChronoTankDuration);\n//Mono_Set_Cursor(0,0);Mono_Printf(\"Chrono duration: %08x \\n\",ChronoTankDuration);Keyboard->Get();Keyboard->Get();\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\t\tCarrierLaunchDelay = ini.Get_Int(AFTERMATH,\"CarrierLaunchDelay\",120);\n#endif\n#ifdef FIXIT_ENGINEER\t//\tchecked - ajw 9/28/98\n\t\t//\tEngineer changing fields were specifically left out of Aftrmath.ini, thus these values are not found to set. ajw\n\t\t//\tImplies interesting security hole if user creates a separate Aftrmath.ini file!\n\t\tEngineerDamage = ini.Get_Fixed(AFTERMATH, \"EngineerDamage\", EngineerDamage);\t// Amount of damage an engineer does\n\t\tEngineerCaptureLevel = ini.Get_Fixed(AFTERMATH, \"EngineerCaptureLevel\", EngineerCaptureLevel);\t// Building damage level before engineer can capture\n#endif\n\t}\n\n#endif\n\n\tif (ini.Is_Present(GENERAL)) {\n\t\tTurboBoost = ini.Get_Fixed(GENERAL, \"TurboBoost\", TurboBoost);\n\t\tBadgerBombCount = ini.Get_Int(GENERAL, \"BadgerBombCount\", BadgerBombCount);\n\t\tIsCurleyShuffle = ini.Get_Bool(GENERAL, \"CurleyShuffle\", IsCurleyShuffle);\n\t\tIsFlashLowPower = ini.Get_Bool(GENERAL, \"FlashLowPower\", IsFlashLowPower);\n\t\tIsChronoKill = ini.Get_Bool(GENERAL, \"ChronoKillCargo\", IsChronoKill);\n\t\tChronoDuration = ini.Get_Fixed(GENERAL, \"ChronoDuration\", ChronoDuration);\n\t\tIsFineDifficulty = ini.Get_Bool(GENERAL, \"FineDiffControl\", IsFineDifficulty);\n\t\tWaterCrateChance = ini.Get_Fixed(GENERAL, \"WaterCrateChance\", WaterCrateChance);\n\t\tSoloCrateMoney = ini.Get_Int(GENERAL, \"SoloCrateMoney\", SoloCrateMoney);\n\t\tParaBombTechLevel = ini.Get_Int(GENERAL, \"ParabombTech\", ParaBombTechLevel);\n\t\tGPSTechLevel = ini.Get_Int(GENERAL, \"GPSTechLevel\", GPSTechLevel);\n\t\tUnitCrateType = ini.Get_UnitType(GENERAL, \"UnitCrateType\", UnitCrateType);\n\t\tIsExplosiveHarvester = ini.Get_Fixed(GENERAL, \"OreExplosive\", IsExplosiveHarvester);\n\t\tGapRegenInterval = ini.Get_Fixed(GENERAL, \"GapRegenInterval\", GapRegenInterval);\n\t\tTeamDelay = ini.Get_Fixed(GENERAL, \"TeamDelay\", TeamDelay);\n\t\tCloakDelay = ini.Get_Fixed(GENERAL, \"SubmergeDelay\", CloakDelay);\n\t\tGameSpeedBias = ini.Get_Fixed(GENERAL, \"GameSpeedBias\", GameSpeedBias);\n\t\tNervousBias = ini.Get_Fixed(GENERAL, \"BaseBias\", NervousBias);\n\t\tExplosionSpread = ini.Get_Fixed(GENERAL, \"ExpSpread\", ExplosionSpread);\n\t\tSupressRadius = ini.Get_Lepton(GENERAL, \"FireSupress\", SupressRadius);\n\t\tParaInfantryTechLevel = ini.Get_Int(GENERAL, \"ParaTech\", ParaInfantryTechLevel);\n\t\tSpyPlaneTechLevel = ini.Get_Int(GENERAL, \"SpyPlaneTech\", SpyPlaneTechLevel);\n\t\tSilverCrate = ini.Get_CrateType(GENERAL, \"SilverCrate\", SilverCrate);\n\t\tWoodCrate = ini.Get_CrateType(GENERAL, \"WoodCrate\", WoodCrate);\n\t\tWaterCrate = ini.Get_CrateType(GENERAL, \"WaterCrate\", WaterCrate);\n\t\tCrateMinimum = ini.Get_Int(GENERAL, \"CrateMinimum\", CrateMinimum);\n\t\tCrateMaximum = ini.Get_Int(GENERAL, \"CrateMaximum\", CrateMaximum);\n\t\tIsScatter = ini.Get_Bool(GENERAL, \"PlayerScatter\", IsScatter);\n\t\tIsSmartDefense = ini.Get_Bool(GENERAL, \"PlayerReturnFire\", IsSmartDefense);\n\t\tIsAutoCrush = ini.Get_Bool(GENERAL, \"PlayerAutoCrush\", IsAutoCrush);\n\t\tIsNamed = ini.Get_Bool(GENERAL, \"NamedCivilians\", IsNamed);\n\t\tIsTGrowth = ini.Get_Bool(GENERAL, \"OreGrows\", IsTGrowth);\n\t\tIsTSpread = ini.Get_Bool(GENERAL, \"OreSpreads\", IsTSpread);\n\t\tIsMineAware = ini.Get_Bool(GENERAL, \"MineAware\", IsMineAware);\n\t\tIsTreeTarget = ini.Get_Bool(GENERAL, \"TreeTargeting\", IsTreeTarget);\n\t\tIsSeparate = ini.Get_Bool(GENERAL, \"SeparateAircraft\", IsSeparate);\n\t\tDropZoneRadius = ini.Get_Lepton(GENERAL, \"DropZoneRadius\", DropZoneRadius);\n\t\tMessageDelay = ini.Get_Fixed(GENERAL, \"MessageDelay\", MessageDelay);\n\t\tSavourDelay = ini.Get_Fixed(GENERAL, \"SavourDelay\", SavourDelay);\n\t\tAVMineDamage = ini.Get_Int(GENERAL, \"AVMineDamage\", AVMineDamage);\n\t\tAPMineDamage = ini.Get_Int(GENERAL, \"APMineDamage\", APMineDamage);\n\t\tBaseDefenseDelay = ini.Get_Fixed(GENERAL, \"BaseDefenseDelay\", BaseDefenseDelay);\n\t\tSuspendPriority = ini.Get_Int(GENERAL, \"SuspendPriority\", SuspendPriority);\n\t\tSuspendDelay = ini.Get_Fixed(GENERAL, \"SuspendDelay\", SuspendDelay);\n\t\tSurvivorFraction = ini.Get_Fixed(GENERAL, \"SurvivorRate\", SurvivorFraction);\n\t\tRadarJamRadius = ini.Get_Lepton(GENERAL, \"RadarJamRadius\", RadarJamRadius);\n\t\tReloadRate = ini.Get_Fixed(GENERAL, \"ReloadRate\", ReloadRate);\n\t\tRandomAnimateTime = ini.Get_Fixed(GENERAL, \"IdleActionFrequency\", RandomAnimateTime);\n\t\tBuildupTime = ini.Get_Fixed(GENERAL, \"BuildupTime\", BuildupTime);\n\t\tOreDumpRate = ini.Get_Int(GENERAL, \"OreTruckRate\", OreDumpRate);\n\t\tAtomDamage = ini.Get_Int(GENERAL, \"AtomDamage\", AtomDamage);\n\t\tBailCount = ini.Get_Int(GENERAL, \"BailCount\", BailCount);\n\t\tBallisticScatter = ini.Get_Lepton(GENERAL, \"BallisticScatter\", BallisticScatter);\n\t\tBridgeStrength = ini.Get_Int(GENERAL, \"BridgeStrength\", BridgeStrength);\n\t\tBuildSpeedBias = ini.Get_Fixed(GENERAL, \"BuildSpeed\", BuildSpeedBias);\n\t\tConditionGreen = 1;\n\t\tConditionRed = ini.Get_Fixed(GENERAL, \"ConditionRed\", ConditionRed);\n\t\tConditionYellow = ini.Get_Fixed(GENERAL, \"ConditionYellow\", ConditionYellow);\n\t\tCrateRadius = ini.Get_Lepton(GENERAL, \"CrateRadius\", CrateRadius);\n\t\tCrushDistance = ini.Get_Lepton(GENERAL, \"Crush\", CrushDistance);\n\t\tDamageDelay = ini.Get_Fixed(GENERAL, \"DamageDelay\", DamageDelay);\n\t\tGapShroudRadius = ini.Get_Int(GENERAL, \"GapRadius\", GapShroudRadius);\n\t\tGemValue = ini.Get_Int(GENERAL, \"GemValue\", GemValue);\n\t\tGoldValue = ini.Get_Int(GENERAL, \"GoldValue\", GoldValue);\n\t\tGravity = ini.Get_Int(GENERAL, \"Gravity\", Gravity);\n\t\tGrowthRate = ini.Get_Fixed(GENERAL, \"GrowthRate\", GrowthRate);\n\t\tHomingScatter = ini.Get_Lepton(GENERAL, \"HomingScatter\", HomingScatter);\n\t\tIncoming = ini.Get_MPHType(GENERAL, \"Incoming\", MPH_IMMOBILE);\n\t\tIronCurtainDuration = ini.Get_Fixed(GENERAL, \"IronCurtain\", IronCurtainDuration);\n\t\tIsAllyReveal = ini.Get_Bool(GENERAL, \"AllyReveal\", IsAllyReveal);\n\t\tIsMCVDeploy = ini.Get_Bool(GENERAL, \"MCVUndeploy\", IsMCVDeploy);\n\t\tMaxDamage = ini.Get_Int(GENERAL, \"MaxDamage\", MaxDamage);\n\t\tMinDamage = ini.Get_Int(GENERAL, \"MinDamage\", MinDamage);\n\t\tProneDamageBias = ini.Get_Fixed(GENERAL, \"ProneDamage\", ProneDamageBias);\n\t\tQuakeDamagePercent = ini.Get_Fixed(GENERAL, \"QuakeDamage\", QuakeDamagePercent);\n\t\tQuakeChance = ini.Get_Fixed(GENERAL, \"QuakeChance\", QuakeChance);\n\t\tRefundPercent = ini.Get_Fixed(GENERAL, \"RefundPercent\", RefundPercent);\n\t\tRepairPercent = ini.Get_Fixed(GENERAL, \"RepairPercent\", RepairPercent);\n\t\tRepairStep = ini.Get_Int(GENERAL, \"RepairStep\", RepairStep);\n\t\tURepairPercent = ini.Get_Fixed(GENERAL, \"URepairPercent\", URepairPercent);\n\t\tURepairStep = ini.Get_Int(GENERAL, \"URepairStep\", URepairStep);\n\t\tRepairRate = ini.Get_Fixed(GENERAL, \"RepairRate\", RepairRate);\n\t\tShroudRate = ini.Get_Fixed(GENERAL, \"ShroudRate\", ShroudRate);\n\t\tSpeakDelay = ini.Get_Fixed(GENERAL, \"SpeakDelay\", SpeakDelay);\n\t\tStrayDistance = ini.Get_Lepton(GENERAL, \"Stray\", StrayDistance);\n\t\tCloseEnoughDistance = ini.Get_Lepton(GENERAL, \"CloseEnough\", CloseEnoughDistance);\n\t\tTimerWarning = ini.Get_Fixed(GENERAL, \"TimerWarning\", TimerWarning);\n\t\tMovieTime = ini.Get_Fixed(GENERAL, \"MovieTime\", MovieTime);\n\t\tC4Delay = ini.Get_Fixed(GENERAL, \"C4Delay\", C4Delay);\n\t\tChronoTechLevel = ini.Get_Int(GENERAL, \"ChronoTechLevel\", ChronoTechLevel);\n\t\tCrateTime = ini.Get_Fixed(GENERAL, \"CrateRegen\", CrateTime);\n\t\tVortexRange = ini.Get_Lepton(GENERAL, \"VortexRange\", VortexRange);\n\t\tVortexSpeed = MPHType(_Scale_To_256(ini.Get_Int(GENERAL, \"VortexSpeed\", VortexSpeed)));\n\t\tVortexDamage = ini.Get_Int(GENERAL, \"VortexDamage\", VortexDamage);\n\t\tVortexChance = ini.Get_Fixed(GENERAL, \"VortexChance\", VortexChance);\n\n\t\tChronalVortex.Set_Range(VortexRange / CELL_LEPTON_W);\n\t\tChronalVortex.Set_Speed(VortexSpeed);\n\t\tChronalVortex.Set_Damage(VortexDamage);\n\n\t\t//ChronalVortex.Set_Range ( ini.Get_Int (GENERAL, \"VortexRange\", ChronalVortex.Get_Range() ) );\n\t\t//ChronalVortex.Set_Speed ( ini.Get_Int (GENERAL, \"VortexSpeed\", ChronalVortex.Get_Speed() ) );\n\t\t//ChronalVortex.Set_Damage ( ini.Get_Int (GENERAL, \"VortexDamage\", ChronalVortex.Get_Damage() ) );\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::MPlayer -- Fetch and process the multiplayer default settings.                  *\n *                                                                                             *\n *    This is used to set the default settings for the multiplayer system.                     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the multiplayer default override section found and processed?            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::MPlayer(CCINIClass & ini)\n{\n\tstatic char const * const MPLAYER = \"MultiplayerDefaults\";\n\tif (ini.Is_Present(MPLAYER)) {\n\t\tMPDefaultMoney = ini.Get_Int(MPLAYER, \"Money\", MPDefaultMoney);\n\t\tMPMaxMoney = ini.Get_Int(MPLAYER, \"MaxMoney\", MPMaxMoney);\n\t\tIsMPShadowGrow = ini.Get_Bool(MPLAYER, \"ShadowGrow\", IsMPShadowGrow);\n\t\tIsMPBasesOn = ini.Get_Bool(MPLAYER, \"Bases\", IsMPBasesOn);\n\t\tIsMPTiberiumGrow = ini.Get_Bool(MPLAYER, \"OreGrows\", IsMPTiberiumGrow);\n\t\tIsMPCrates = ini.Get_Bool(MPLAYER, \"Crates\", IsMPCrates);\n\t\tIsMPCaptureTheFlag = ini.Get_Bool(MPLAYER, \"CaptureTheFlag\", IsMPCaptureTheFlag);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Recharge -- Process the super weapon recharge statistics.                       *\n *                                                                                             *\n *    Use this to set the recharge times for the various super weapons available.              *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the recharge section found and processed?                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Recharge(CCINIClass & ini)\n{\n\tstatic char const * const RECHARGE = \"Recharge\";\n\tif (ini.Is_Present(RECHARGE)) {\n\t\tSonarTime = ini.Get_Fixed(RECHARGE, \"Sonar\", SonarTime);\n\t\tChronoTime = ini.Get_Fixed(RECHARGE, \"Chrono\", ChronoTime);\n\t\tParaBombTime = ini.Get_Fixed(RECHARGE, \"ParaBomb\", ParaBombTime);\n\t\tParaInfantryTime = ini.Get_Fixed(RECHARGE, \"Paratrooper\", ParaInfantryTime);\n\t\tSpyTime = ini.Get_Fixed(RECHARGE, \"SpyPlane\", SpyTime);\n\t\tIronCurtainTime = ini.Get_Fixed(RECHARGE, \"IronCurtain\", IronCurtainTime);\n\t\tGPSTime = ini.Get_Fixed(RECHARGE, \"GPS\", GPSTime);\n\t\tNukeTime = ini.Get_Fixed(RECHARGE, \"Nuke\", NukeTime);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Heap_Maximums -- Fetch and process the heap override values.                    *\n *                                                                                             *\n *    This fetches the maximum heap sizes from the database specified. The heaps will be       *\n *    initialized by this routine as indicated.                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database.                                            *\n *                                                                                             *\n * OUTPUT:  bool; Was the maximum section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   This process is catastrophic to any data currently existing in the heaps        *\n *             modified. This should only be processed during the game initialization stage.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Heap_Maximums(CCINIClass & ini)\n{\n\t/*\n\t**\tHeap maximum values.\n\t*/\n\tstatic char const * const MAXIMUMS = \"Maximums\";\n\tif (ini.Is_Present(MAXIMUMS)) {\n\t\tMaxPlayers = ini.Get_Int(MAXIMUMS, \"Players\", MaxPlayers);\n\t\tAircraftMax = ini.Get_Int(MAXIMUMS, \"Aircraft\", AircraftMax);\n\t\tAnimMax = ini.Get_Int(MAXIMUMS, \"Anim\", AnimMax);\n\t\tBuildingMax = ini.Get_Int(MAXIMUMS, \"Building\", BuildingMax);\n\t\tBulletMax = ini.Get_Int(MAXIMUMS, \"Bullet\", BulletMax);\n\t\tFactoryMax = ini.Get_Int(MAXIMUMS, \"Factory\", FactoryMax);\n\t\tInfantryMax = ini.Get_Int(MAXIMUMS, \"Infantry\", InfantryMax);\n\t\tOverlayMax = ini.Get_Int(MAXIMUMS, \"Overlay\", OverlayMax);\n\t\tSmudgeMax = ini.Get_Int(MAXIMUMS, \"Smudge\", SmudgeMax);\n\t\tTeamMax = ini.Get_Int(MAXIMUMS, \"Team\", TeamMax);\n\t\tTeamTypeMax = ini.Get_Int(MAXIMUMS, \"TeamType\", TeamTypeMax);\n\t\tTemplateMax = ini.Get_Int(MAXIMUMS, \"Template\", TemplateMax);\n\t\tTerrainMax = ini.Get_Int(MAXIMUMS, \"Terrain\", TerrainMax);\n\t\tTriggerMax = ini.Get_Int(MAXIMUMS, \"Trigger\", TriggerMax);\n\t\tUnitMax = ini.Get_Int(MAXIMUMS, \"Unit\", UnitMax);\n\t\tVesselMax = ini.Get_Int(MAXIMUMS, \"Vessel\", VesselMax);\n\t\tProjectileMax = ini.Get_Int(MAXIMUMS, \"Projectile\", ProjectileMax);\n\t\tWeaponMax = ini.Get_Int(MAXIMUMS, \"Weapon\", WeaponMax);\n\t\tWarheadMax = ini.Get_Int(MAXIMUMS, \"Warhead\", WarheadMax);\n\t\tTrigTypeMax = ini.Get_Int(MAXIMUMS, \"TrigType\", TrigTypeMax);\n\t}\n\n\t/*\n\t**\tSpecial case: double maximum animations to accomodate lots of action\n\t*/\n\tAnimMax = max(AnimMax, 200);\n\n\t/*\n\t**\tAny heaps that use the maximums that were just loaded, must\n\t**\tbe initialized as necessary.\n\t*/\n\tWarheads.Set_Heap(WarheadMax);\n\tnew WarheadTypeClass(\"SA\");\n\tnew WarheadTypeClass(\"HE\");\n\tnew WarheadTypeClass(\"AP\");\n\tnew WarheadTypeClass(\"Fire\");\n\tnew WarheadTypeClass(\"HollowPoint\");\n\tnew WarheadTypeClass(\"Super\");\n\tnew WarheadTypeClass(\"Organic\");\n\tnew WarheadTypeClass(\"Nuke\");\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew WarheadTypeClass(\"Mechanical\");\n#endif\n\n\tWeapons.Set_Heap(WeaponMax);\n\tnew WeaponTypeClass(\"Colt45\");\n\tnew WeaponTypeClass(\"ZSU-23\");\n\tnew WeaponTypeClass(\"Vulcan\");\n\tnew WeaponTypeClass(\"Maverick\");\n\tnew WeaponTypeClass(\"Camera\");\n\tnew WeaponTypeClass(\"FireballLauncher\");\n\tnew WeaponTypeClass(\"Sniper\");\n\tnew WeaponTypeClass(\"ChainGun\");\n\tnew WeaponTypeClass(\"Pistol\");\n\tnew WeaponTypeClass(\"M1Carbine\");\n\tnew WeaponTypeClass(\"Dragon\");\n\tnew WeaponTypeClass(\"Hellfire\");\n\tnew WeaponTypeClass(\"Grenade\");\n\tnew WeaponTypeClass(\"75mm\");\n\tnew WeaponTypeClass(\"90mm\");\n\tnew WeaponTypeClass(\"105mm\");\n\tnew WeaponTypeClass(\"120mm\");\n\tnew WeaponTypeClass(\"TurretGun\");\n\tnew WeaponTypeClass(\"MammothTusk\");\n\tnew WeaponTypeClass(\"155mm\");\n\tnew WeaponTypeClass(\"M60mg\");\n\tnew WeaponTypeClass(\"Napalm\");\n\tnew WeaponTypeClass(\"TeslaZap\");\n\tnew WeaponTypeClass(\"Nike\");\n\tnew WeaponTypeClass(\"8Inch\");\n\tnew WeaponTypeClass(\"Stinger\");\n\tnew WeaponTypeClass(\"TorpTube\");\n\tnew WeaponTypeClass(\"2Inch\");\n\tnew WeaponTypeClass(\"DepthCharge\");\n\tnew WeaponTypeClass(\"ParaBomb\");\n\tnew WeaponTypeClass(\"DogJaw\");\n\tnew WeaponTypeClass(\"Heal\");\n\tnew WeaponTypeClass(\"SCUD\");\n\tnew WeaponTypeClass(\"Flamer\");\n\tnew WeaponTypeClass(\"RedEye\");\n\n#ifdef FIXIT_ANTS\n\tnew WeaponTypeClass(\"Mandible\");\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tnew WeaponTypeClass(\"PortaTesla\");\n\tnew WeaponTypeClass(\"GoodWrench\");\n\tnew WeaponTypeClass(\"SubSCUD\");\n\tnew WeaponTypeClass(\"TTankZap\");\n\tnew WeaponTypeClass(\"APTusk\");\n\tnew WeaponTypeClass(\"Democharge\");\n#endif\n#ifdef FIXIT_CARRIER\t//\tchecked - ajw 9/28/98\n\tnew WeaponTypeClass(\"AirAssault\");\n#endif\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::AI -- Processes the AI control constants from the database.                     *\n *                                                                                             *\n *    This will examine the database specified and set the AI override values accordingly.     *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that holds the AI overrides.                *\n *                                                                                             *\n * OUTPUT:  bool; Was the AI section found and processed?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::AI(CCINIClass & ini)\n{\n\tstatic char const * const AI = \"AI\";\n\tif (ini.Is_Present(AI)) {\n\t\tAttackInterval = ini.Get_Fixed(AI, \"AttackInterval\", AttackInterval);\n\t\tAttackDelay = ini.Get_Fixed(AI, \"AttackDelay\", AttackDelay);\n\t\tPatrolTime = ini.Get_Fixed(AI, \"PatrolScan\", PatrolTime);\n\t\tRepairThreshhold = ini.Get_Int(AI, \"CreditReserve\", RepairThreshhold);\n\t\tPathDelay = ini.Get_Fixed(AI, \"PathDelay\", PathDelay);\n\t\tTiberiumShortScan = ini.Get_Lepton(AI, \"OreNearScan\", TiberiumShortScan);\n\t\tTiberiumLongScan = ini.Get_Lepton(AI, \"OreFarScan\", TiberiumLongScan);\n\t\tAutocreateTime = ini.Get_Fixed(AI, \"AutocreateTime\", AutocreateTime);\n\t\tInfantryReserve = ini.Get_Int(AI, \"InfantryReserve\", InfantryReserve);\n\t\tInfantryBaseMult = ini.Get_Int(AI, \"InfantryBaseMult\", InfantryBaseMult);\n\t\tPowerSurplus = ini.Get_Int(AI, \"PowerSurplus\", PowerSurplus);\n\t\tBaseSizeAdd = ini.Get_Int(AI, \"BaseSizeAdd\", BaseSizeAdd);\n\t\tRefineryRatio = ini.Get_Fixed(AI, \"RefineryRatio\", RefineryRatio);\n\t\tRefineryLimit = ini.Get_Int(AI, \"RefineryLimit\", RefineryLimit);\n\t\tBarracksRatio = ini.Get_Fixed(AI, \"BarracksRatio\", BarracksRatio);\n\t\tBarracksLimit = ini.Get_Int(AI, \"BarracksLimit\", BarracksLimit);\n\t\tWarRatio = ini.Get_Fixed(AI, \"WarRatio\", WarRatio);\n\t\tWarLimit = ini.Get_Int(AI, \"WarLimit\", WarLimit);\n\t\tDefenseRatio = ini.Get_Fixed(AI, \"DefenseRatio\", DefenseRatio);\n\t\tDefenseLimit = ini.Get_Int(AI, \"DefenseLimit\", DefenseLimit);\n\t\tAARatio = ini.Get_Fixed(AI, \"AARatio\", AARatio);\n\t\tAALimit = ini.Get_Int(AI, \"AALimit\", AALimit);\n\t\tTeslaRatio = ini.Get_Fixed(AI, \"TeslaRatio\", TeslaRatio);\n\t\tTeslaLimit = ini.Get_Int(AI, \"TeslaLimit\", TeslaLimit);\n\t\tHelipadRatio = ini.Get_Fixed(AI, \"HelipadRatio\", HelipadRatio);\n\t\tHelipadLimit = ini.Get_Int(AI, \"HelipadLimit\", HelipadLimit);\n\t\tAirstripRatio = ini.Get_Fixed(AI, \"AirstripRatio\", AirstripRatio);\n\t\tAirstripLimit = ini.Get_Int(AI, \"AirstripLimit\", AirstripLimit);\n\t\tIsCompEasyBonus = ini.Get_Bool(AI, \"CompEasyBonus\", IsCompEasyBonus);\n\t\tIsComputerParanoid = ini.Get_Bool(AI, \"Paranoid\", IsComputerParanoid);\n\t\tPowerEmergencyFraction = ini.Get_Fixed(AI, \"PowerEmergency\", PowerEmergencyFraction);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Powerups -- Process the powerup values from the database.                       *\n *                                                                                             *\n *    This will examine the database and initialize the powerup override values accordingly.   *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database the the powerup values are to be            *\n *                   initialized from.                                                         *\n *                                                                                             *\n * OUTPUT:  bool; Was the powerup section found and processed?                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Powerups(CCINIClass & ini)\n{\n\tstatic char const * const POWERUPS = \"Powerups\";\n\tif (ini.Is_Present(POWERUPS)) {\n\t\tfor (CrateType crate = CRATE_FIRST; crate < CRATE_COUNT; crate++) {\n\t\t\tchar buffer[128];\n\t\t\tif (ini.Get_String(POWERUPS, CrateNames[crate], \"0,NONE\", buffer, sizeof(buffer))) {\n\n\t\t\t\t/*\n\t\t\t\t**\tShare odds.\n\t\t\t\t*/\n\t\t\t\tchar * token = strtok(buffer, \",\");\n\t\t\t\tif (token) {\n\t\t\t\t\tstrtrim(token);\n\t\t\t\t\tCrateShares[crate] = atoi(token);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAnimation to use.\n\t\t\t\t*/\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token) {\n\t\t\t\t\tstrtrim(token);\n\t\t\t\t\tCrateAnims[crate] = Anim_From_Name(token);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tOptional data number.\n\t\t\t\t*/\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\tif (strpbrk(token, \".%\") != NULL) {\n\t\t\t\t\t\tCrateData[crate] = fixed(token) * 256;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrtrim(token);\n\t\t\t\t\t\tCrateData[crate] = atoi(token);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Land_Types -- Inits the land type values.                                       *\n *                                                                                             *\n *    This will set the land movement attributes from the database specified.                  *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the database that has the land value overrides.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the land type sections found and processed?                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Land_Types(CCINIClass & ini)\n{\n\t/*\n\t**\tFetch the movement characteristic data for terrain types.\n\t*/\n\tfor (LandType land = LAND_FIRST; land < LAND_COUNT; land++) {\n\t\tstatic char const * _lands[LAND_COUNT] = {\n\t\t\t\"Clear\",\n\t\t\t\"Road\",\n\t\t\t\"Water\",\n\t\t\t\"Rock\",\n\t\t\t\"Wall\",\n\t\t\t\"Ore\",\n\t\t\t\"Beach\",\n\t\t\t\"Rough\",\n\t\t\t\"River\"\n\t\t};\n\n\t\tGroundType * gptr = &Ground[land];\n\n\t\tif (ini.Is_Present(_lands[land])) {\n\t\t\tgptr->Cost[SPEED_FOOT] = ini.Get_Fixed(_lands[land], \"Foot\", 1);\n\t\t\tgptr->Cost[SPEED_TRACK] = ini.Get_Fixed(_lands[land], \"Track\", 1);\n\t\t\tgptr->Cost[SPEED_WHEEL] = ini.Get_Fixed(_lands[land], \"Wheel\", 1);\n\t\t\tgptr->Cost[SPEED_WINGED] = fixed(1);\n\t\t\tgptr->Cost[SPEED_FLOAT] = ini.Get_Fixed(_lands[land], \"Float\", 1);\n\t\t\tgptr->Build = ini.Get_Bool(_lands[land], \"Buildable\", false);\n\t\t}\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Themes -- Fetches the theme control values from the INI database.               *\n *                                                                                             *\n *    The musical theme availability is controlled by the scenario and the player's house      *\n *    choice. These controls can be specified in the theme control section of the INI          *\n *    database.                                                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to process.                                 *\n *                                                                                             *\n * OUTPUT:  bool; Was the theme section found and processed?                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Themes(CCINIClass & ini)\n{\n\tstatic char const * const THEMECONTROL = \"ThemeControl\";\n\n\tif (ini.Is_Present(THEMECONTROL)) {\n\t\tfor (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {\n\t\t\tif (ini.Is_Present(THEMECONTROL, Theme.Base_Name(theme))) {\n\n\t\t\t\tchar buffer[128];\n\t\t\t\tint scen = 1;\n\t\t\t\tint owners = HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS;\n\n\t\t\t\tini.Get_String(THEMECONTROL, Theme.Base_Name(theme), \"\", buffer, sizeof(buffer));\n\t\t\t\tchar const * token = strtok(buffer, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\tscen = atoi(token);\n\t\t\t\t}\n\n\t\t\t\ttoken = strtok(NULL, \",\");\n\t\t\t\tif (token != NULL) {\n\t\t\t\t\towners = Owner_From_Name(token);\n\t\t\t\t}\n\n\t\t\t\tTheme.Set_Theme_Data(theme, scen, owners);\n\t\t\t}\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::IQ -- Fetches the IQ control values from the INI database.                      *\n *                                                                                             *\n *    This will scan the database specified and retrieve the IQ control values from it. These  *\n *    IQ control values are what gives the IQ rating meaning. It fundimentally controls how    *\n *    the computer behaves.                                                                    *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database to read the IQ controls from.               *\n *                                                                                             *\n * OUTPUT:  bool; Was the IQ section found and processed?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/11/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::IQ(CCINIClass & ini)\n{\n\tstatic char const * const IQCONTROL = \"IQ\";\n\tif (ini.Is_Present(IQCONTROL)) {\n\t\tMaxIQ = ini.Get_Int(IQCONTROL, \"MaxIQLevels\", MaxIQ);\n\t\tIQSuperWeapons = ini.Get_Int(IQCONTROL, \"SuperWeapons\", IQSuperWeapons);\n\t\tIQProduction = ini.Get_Int(IQCONTROL, \"Production\", IQProduction);\n\t\tIQGuardArea = ini.Get_Int(IQCONTROL, \"GuardArea\", IQGuardArea);\n\t\tIQRepairSell = ini.Get_Int(IQCONTROL, \"RepairSell\", IQRepairSell);\n\t\tIQCrush = ini.Get_Int(IQCONTROL, \"AutoCrush\", IQCrush);\n\t\tIQScatter = ini.Get_Int(IQCONTROL, \"Scatter\", IQScatter);\n\t\tIQContentScan = ini.Get_Int(IQCONTROL, \"ContentScan\", IQContentScan);\n\t\tIQAircraft = ini.Get_Int(IQCONTROL, \"Aircraft\", IQAircraft);\n\t\tIQHarvester = ini.Get_Int(IQCONTROL, \"Harvester\", IQHarvester);\n\t\tIQSellBack = ini.Get_Int(IQCONTROL, \"SellBack\", IQSellBack);\n\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Objects -- Fetch all the object characteristic values.                          *\n *                                                                                             *\n *    This will parse the specified INI database and fetch all the object characteristic       *\n *    values specified therein.                                                                *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the ini database to scan.                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Objects(CCINIClass & ini)\n{\n\t/*\n\t**\tFetch the game object values from the rules file.\n\t*/\n\tfor (int index = 0; index < Warheads.Count(); index++) {\n\t\tWarheads.Ptr(index)->Read_INI(ini);\n\t}\n\n\tfor (int proj = 0; proj < BulletTypes.Count(); proj++) {\n\t\tBulletTypes.Ptr(proj)->Read_INI(ini);\n\t}\n\n\tfor (int windex = 0; windex < Weapons.Count(); windex++) {\n\t\tWeapons.Ptr(windex)->Read_INI(ini);\n\t}\n\n\tfor (int uindex = 0; uindex < UnitTypes.Count(); uindex++) {\n\t\tUnitTypes.Ptr(uindex)->Read_INI(ini);\n\t}\n\n\tfor (int iindex = 0; iindex < InfantryTypes.Count(); iindex++) {\n\t\tInfantryTypes.Ptr(iindex)->Read_INI(ini);\n\t}\n\n\tfor (int vindex = 0; vindex < VesselTypes.Count(); vindex++) {\n\t\tVesselTypes.Ptr(vindex)->Read_INI(ini);\n\t}\n\n\tfor (int aindex = 0; aindex < AircraftTypes.Count(); aindex++) {\n\t\tAircraftTypes.Ptr(aindex)->Read_INI(ini);\n\t}\n\n\tfor (int bindex = 0; bindex < BuildingTypes.Count(); bindex++) {\n\t\tBuildingTypes.Ptr(bindex)->Read_INI(ini);\n\t}\n\n\t/*\n\t**\tFetch the house attribute override values.\n\t*/\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseTypeClass::As_Reference(house).Read_INI(ini);\n\t}\n\n\t/*\n\t**\tFetch the mission control values.\n\t*/\n\tfor (MissionType mission = MISSION_FIRST; mission < MISSION_COUNT; mission++) {\n\t\tMissionControlClass * miss = &MissionControl[mission];\n\t\tmiss->Mission = mission;\n\t\tmiss->Read_INI(ini);\n\t}\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * RulesClass::Difficulty -- Fetch the various difficulty group settings.                      *\n *                                                                                             *\n *    This routine is used to fetch the various group settings for the difficulty levels.      *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database that has the difficulty setting values.     *\n *                                                                                             *\n * OUTPUT:  bool; Was the difficulty section found and processed.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/10/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool RulesClass::Difficulty(CCINIClass & ini)\n{\n#if 0\n\tDifficulty_Get(ini, Diff[DIFF_EASY], \"Easy\");\n\tDifficulty_Get(ini, Diff[DIFF_NORMAL], \"Normal\");\n\tDifficulty_Get(ini, Diff[DIFF_HARD], \"Difficult\");\n#endif\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Is_MCV_Deploy -- Check if MCV can be deployed.                                              *\n *                                                                                             *\n *    This routine is used to check if the Construction Yard can revert back into an MCV.      *\n *    It allows the special variables to override anything set by the rules.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Can the Construction Yard revert back into an MCV.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/24/2019 SKY : Created.                                                                 *\n *=============================================================================================*/\nbool Is_MCV_Deploy()\n{\n\treturn Special.UseMCVDeploy ? Special.IsMCVDeploy : Rule.IsMCVDeploy;\n}"
  },
  {
    "path": "REDALERT/RULES.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/RULES.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : RULES.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/12/96                                                     *\n *                                                                                             *\n *                  Last Update : May 12, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef RULES_H\n#define RULES_H\n\n#include\t\"ccini.h\"\n\nclass DifficultyClass\n{\n\tpublic:\n\t\tfixed FirepowerBias;\n\t\tfixed GroundspeedBias;\n\t\tfixed AirspeedBias;\n\t\tfixed ArmorBias;\n\t\tfixed ROFBias;\n\t\tfixed CostBias;\n\t\tfixed BuildSpeedBias;\n\n\t\tfixed RepairDelay;\n\t\tfixed BuildDelay;\n\n\t\tunsigned IsBuildSlowdown:1;\n\t\tunsigned IsWallDestroyer:1;\n\t\tunsigned IsContentScan:1;\n};\n\nclass RulesClass {\n\tpublic:\n\n\t\tRulesClass(void);\n\n\t\tbool Process(CCINIClass & file);\n\t\tbool General(CCINIClass & ini);\n\t\tbool MPlayer(CCINIClass & ini);\n\t\tbool Recharge(CCINIClass & ini);\n\t\tbool Heap_Maximums(CCINIClass & ini);\n\t\tbool AI(CCINIClass & ini);\n\t\tbool Powerups(CCINIClass & ini);\n\t\tbool Land_Types(CCINIClass & ini);\n\t\tbool Themes(CCINIClass & ini);\n\t\tbool IQ(CCINIClass & ini);\n\t\tbool Objects(CCINIClass & ini);\n\t\tbool Difficulty(CCINIClass & ini);\n\n\t\t/*\n\t\t**\tThis specifies the turbo boost speed for missiles when they are fired upon\n\t\t**\taircraft and the weapon is specified as having a turbo boost bonus.\n\t\t*/\n\t\tfixed TurboBoost;\n\n\t\t/*\n\t\t**\tThis specifies the average number of minutes between each computer attack.\n\t\t*/\n\t\tfixed AttackInterval;\n\n\t\t/*\n\t\t**\tThis specifies the average minutes delay before the computer will begin\n\t\t**\tits first attack upon the player. The duration is also modified by the\n\t\t**\tdifficulty level.\n\t\t*/\n\t\tfixed AttackDelay;\n\n\t\t/*\n\t\t**\tIf the power ratio falls below this percentage, then a power emergency is\n\t\t**\tin effect. At such times, the computer might decide to sell off some\n\t\t**\tpower hungry buildings in order to alleviate the situation.\n\t\t*/\n\t\tfixed PowerEmergencyFraction;\n\n\t\t/*\n\t\t**\tThe number of badgers that arrive when the parabomb option is used.\n\t\t*/\n\t\tint BadgerBombCount;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of airstrips.\n\t\t*/\n\t\tfixed AirstripRatio;\n\n\t\t/*\n\t\t**\tLimit the number of airstrips to this amount.\n\t\t*/\n\t\tint AirstripLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of helipads.\n\t\t*/\n\t\tfixed HelipadRatio;\n\n\t\t/*\n\t\t**\tLimit the number of helipads to this amount.\n\t\t*/\n\t\tint HelipadLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of Tesla Coils.\n\t\t*/\n\t\tfixed TeslaRatio;\n\n\t\t/*\n\t\t**\tLimit tesla coil production to this maximum.\n\t\t*/\n\t\tint TeslaLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of anti-aircraft defense.\n\t\t*/\n\t\tfixed AARatio;\n\n\t\t/*\n\t\t**\tLimit anti-aircraft building quantity to this amount.\n\t\t*/\n\t\tint AALimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of defensive structures.\n\t\t*/\n\t\tfixed DefenseRatio;\n\n\t\t/*\n\t\t**\tThis is the limit to the number of defensive building that can be built.\n\t\t*/\n\t\tint DefenseLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of war factories.\n\t\t*/\n\t\tfixed WarRatio;\n\n\t\t/*\n\t\t**\tWar factories are limited to this quantity for the computer controlled player.\n\t\t*/\n\t\tint WarLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of infantry producing structures.\n\t\t*/\n\t\tfixed BarracksRatio;\n\n\t\t/*\n\t\t**\tNo more than this many barracks can be built.\n\t\t*/\n\t\tint BarracksLimit;\n\n\t\t/*\n\t\t**\tRefinery building is limited to this many refineries.\n\t\t*/\n\t\tint RefineryLimit;\n\n\t\t/*\n\t\t**\tThis specifies the percentage of the base (by building quantity) that should\n\t\t**\tbe composed of refineries.\n\t\t*/\n\t\tfixed RefineryRatio;\n\n\t\t/*\n\t\t**\tThe computer is limited in the size of the base it can build. It is limited to the\n\t\t**\tsize of the largest human opponent base plus this surplus count.\n\t\t*/\n\t\tint BaseSizeAdd;\n\n\t\t/*\n\t\t**\tIf the power surplus is less than this amount, then the computer will\n\t\t**\tbuild power plants.\n\t\t*/\n\t\tint PowerSurplus;\n\n\t\t/*\n\t\t**\tThe computer will build infantry if their cash reserve is greater than this amount.\n\t\t*/\n\t\tint InfantryReserve;\n\n\t\t/*\n\t\t**\tThis factor is multiplied by the number of buildings in the computer's base and infantry\n\t\t**\tare always built until it matches that number.\n\t\t*/\n\t\tint InfantryBaseMult;\n\n\t\t/*\n\t\t**\tThis specifies the duration that a unit will remain chronoshifted before it\n\t\t**\twill be returned to its starting location.\n\t\t*/\n\t\tfixed ChronoDuration;\n\n\t\t/*\n\t\t**\tPercent chance that a water crate will be generated instead of a land\n\t\t**\tcrate when crates are on and in a multiplay game.\n\t\t*/\n\t\tfixed WaterCrateChance;\n\n\t\t/*\n\t\t**\tSolo play has money crate amount fixed according to this rule value.\n\t\t*/\n\t\tint SoloCrateMoney;\n\n\t\t/*\n\t\t**\tGPS tech level control.\n\t\t*/\n\t\tint GPSTechLevel;\n\n\t\t/*\n\t\t**\tIf a unit type is specified here, then the unit crate will generate\n\t\t**\ta unit of this type (always).\n\t\t*/\n\t\tUnitType UnitCrateType;\n\n\t\t/*\n\t\t**\tThis is the time to delay between patrol-to-waypoint target scanning.\n\t\t*/\n\t\tfixed PatrolTime;\n\n\t\t/*\n\t\t**\tThis is the time interval that checking to create teams will span. The\n\t\t**\tsmaller this number, the more often checking for team creation will occur.\n\t\t*/\n\t\tfixed TeamDelay;\n\n\t\t/*\n\t\t**\tThis is the arbitrary delay to make all cloaking objects remain uncloaked\n\t\t**\tbefore having it recloak.\n\t\t*/\n\t\tfixed CloakDelay;\n\n\t\t/*\n\t\t**\tThis is an overall game apparent speed bias to use for object\n\t\t**\tmovement purposes.\n\t\t*/\n\t\tfixed GameSpeedBias;\n\n\t\t/*\n\t\t**\tIf a potential target is close to the base then increase\n\t\t**\tthe likelyhood of attacking it by this bias factor.\n\t\t*/\n\t\tfixed NervousBias;\n\n\t\t/*\n\t\t**\tControls the Chronal vortex characteristics.\n\t\t*/\n\t\tLEPTON VortexRange;\n\t\tMPHType VortexSpeed;\n\t\tint VortexDamage;\n\t\tfixed VortexChance;\n\n\t\t/*\n\t\t**\tWhen an explosive object explodes, the damage will spread out\n\t\t**\tby this factor. The value represents the number of cells radius\n\t\t**\tthat the damage will spread for every 100 points of raw damage at\n\t\t**\tthe explosion center point.\n\t\t*/\n\t\tfixed ExplosionSpread;\n\n\t\t/*\n\t\t**\tFor weapons specially marked to check for nearby friendly buildings\n\t\t**\twhen scanning for good targets, this indicates the scan radius. Such\n\t\t**\tweapons will supress firing on enemies if they are in close proximity\n\t\t**\tto allied buildings.\n\t\t*/\n\t\tLEPTON SupressRadius;\n\n\t\t/*\n\t\t**\tThis is the tech level that para infantry are granted free to the owner\n\t\t**\tof an airstrip.\n\t\t*/\n\t\tint ParaInfantryTechLevel;\n\n\t\t/*\n\t\t**\tThis is the tech level that spy planes are granted free to the owner of\n\t\t**\tan airstrip.\n\t\t*/\n\t\tint SpyPlaneTechLevel;\n\n\t\t/*\n\t\t**\tThis is the tech level that the parabombs are granted free to the owner\n\t\t**\tof an airstrip.\n\t\t*/\n\t\tint ParaBombTechLevel;\n\n\t\t/*\n\t\t**\tThis is the maximum number of IQ settings available. The human player is\n\t\t**\tpresumed to be at IQ level zero.\n\t\t*/\n\t\tint MaxIQ;\n\n\t\t/*\n\t\t**\tThe IQ level at which super weapons will be automatically fired by the computer.\n\t\t*/\n\t\tint IQSuperWeapons;\n\n\t\t/*\n\t\t**\tThe IQ level at which production is automatically controlled by the computer.\n\t\t*/\n\t\tint IQProduction;\n\n\t\t/*\n\t\t**\tThe IQ level at which newly produced units start out in guard area mode instead\n\t\t**\tof normal guard mode.\n\t\t*/\n\t\tint IQGuardArea;\n\n\t\t/*\n\t\t**\tThe IQ level at which the computer will be able to decide what gets repaired\n\t\t**\tor sold.\n\t\t*/\n\t\tint IQRepairSell;\n\n\t\t/*\n\t\t**\tAt this IQ level or higher, a unit is allowed to automatically try to crush\n\t\t**\tan atagonist if possible.\n\t\t*/\n\t\tint IQCrush;\n\n\t\t/*\n\t\t**\tThe unit/infantry will try to scatter if an incoming threat\n\t\t**\tis detected.\n\t\t*/\n\t\tint IQScatter;\n\n\t\t/*\n\t\t**\tTech level at which the computer will scan the contents of a transport\n\t\t**\tin order to pick the best target to fire upon.\n\t\t*/\n\t\tint IQContentScan;\n\n\t\t/*\n\t\t**\tAircraft replacement production occurs at this IQ level or higher.\n\t\t*/\n\t\tint IQAircraft;\n\n\t\t/*\n\t\t**\tChecks for and replaces lost harvesters.\n\t\t*/\n\t\tint IQHarvester;\n\n\t\t/*\n\t\t**\tIs allowed to sell a structure being damaged.\n\t\t*/\n\t\tint IQSellBack;\n\n\t\t/*\n\t\t**\tThe silver and wood crates in solo play will have these powerups.\n\t\t*/\n\t\tCrateType SilverCrate;\n\t\tCrateType WoodCrate;\n\t\tCrateType WaterCrate;\n\n\t\t/*\n\t\t**\tThis specifies the minimum number of crates to place on the map in spite\n\t\t**\tof the number of actual human players.\n\t\t*/\n\t\tint CrateMinimum;\n\n\t\t/*\n\t\t**\tThis specifies the crate maximum quantity to use.\n\t\t*/\n\t\tint CrateMaximum;\n\n\t\t/*\n\t\t**\tLanding zone maximum alternate zone scan radius.\n\t\t*/\n\t\tLEPTON LZScanRadius;\n\n\t\t/*\n\t\t**\tMultiplayer default settings.\n\t\t*/\n\t\tint MPDefaultMoney;\n\t\tint MPMaxMoney;\n\t\tunsigned IsMPShadowGrow:1;\n\t\tunsigned IsMPBasesOn:1;\n\t\tunsigned IsMPTiberiumGrow:1;\n\t\tunsigned IsMPCrates:1;\n\t\tunsigned IsMPAIPlayers:1;\n\t\tunsigned IsMPCaptureTheFlag:1;\n\n\t\t/*\n\t\t**\tDrop zone reveal radius.\n\t\t*/\n\t\tLEPTON DropZoneRadius;\n\n\t\t/*\n\t\t**\tThis is the delay that multiplayer messages will remain on the screen.\n\t\t*/\n\t\tfixed MessageDelay;\n\n\t\t/*\n\t\t**\tSavour delay between when scenario detects end and the actual\n\t\t**\tend of the play.\n\t\t*/\n\t\tfixed SavourDelay;\n\n\t\t/*\n\t\t**\tThis specifies the damage to inflict for two differnt styles of\n\t\t**\tland mine.\n\t\t*/\n\t\tint AVMineDamage;\n\t\tint APMineDamage;\n\n\t\t/*\n\t\t**\tThis is the maximum number of multiplayers allowed.\n\t\t*/\n\t\tint MaxPlayers;\n\n\t\t/*\n\t\t**\tThis is the delay between 'panic attacks' when the computer's base is under\n\t\t**\tattack. This delay gives the previously assigned units a chance to affect the\n\t\t**\tattacker before the computer sends more.\n\t\t*/\n\t\tfixed BaseDefenseDelay;\n\n\t\t/*\n\t\t**\tThese values control the team suspension logic for dealing with immedate base threats.\n\t\t**\tWhen the base is attacked, all teams with less than the specified priority will be\n\t\t**\ttemporarily put on hold for the number of minutes specified.\n\t\t*/\n\t\tint SuspendPriority;\n\t\tfixed SuspendDelay;\n\n\t\t/*\n\t\t**\tThis serves as the fraction of a building's original cost that is converted\n\t\t**\tinto survivors (of some fashion). There are rounding and other marginal\n\t\t**\tfudge effects, but this value is the greatest control over the survivor rate.\n\t\t*/\n\t\tfixed SurvivorFraction;\n\n\t\t/*\n\t\t**\tThis is the aircraft reload rate expressed in minutes per ammo load.\n\t\t*/\n\t\tfixed ReloadRate;\n\n\t\t/*\n\t\t**\tThe average time (in minutes) between the computer autocreating a team\n\t\t**\tfrom the team's autocreate list.\n\t\t*/\n\t\tfixed AutocreateTime;\n\n\t\t/*\n\t\t**\tBuild up time for buildings (minutes).\n\t\t*/\n\t\tfixed BuildupTime;\n\n\t\t/*\n\t\t**\tOre truck speed for dumping.\n\t\t*/\n\t\tint OreDumpRate;\n\n\t\t/*\n\t\t**\tThis is the amount of damage done by the atom bomb in solo missions. The\n\t\t**\tdamage done during multiplay will be 1/5th this value.\n\t\t*/\n\t\tint AtomDamage;\n\n\t\t/*\n\t\t**\tThis array controls the difficulty affects on the game. There is one\n\t\t**\tdifficulty class object for each difficulty level.\n\t\t*/\n\t\tDifficultyClass Diff[DIFF_COUNT];\n\n\t\t/*\n\t\t**\tIs the computer paranoid? If so, then it will band together with other computer\n\t\t**\tparanoid players when the situation looks rough.\n\t\t*/\n\t\tbool IsComputerParanoid:1;\n\n\t\t/*\n\t\t**\tShould helicopters shuffle their position between firing on their\n\t\t**\ttarget?\n\t\t*/\n\t\tbool IsCurleyShuffle:1;\n\n\t\t/*\n\t\t**\tFlash the power bar when the power goes below 100%.\n\t\t*/\n\t\tbool IsFlashLowPower:1;\n\n\t\t/*\n\t\t**\tIf the computer players will go to easy mode if there is more\n\t\t**\tthan one human player, this flag will be true.\n\t\t*/\n\t\tbool IsCompEasyBonus:1;\n\n\t\t/*\n\t\t**\tIf fine control of difficulty settings is desired, then set this value to true.\n\t\t**\tFine control allows 5 settings. The coarse control only allows three settings.\n\t\t*/\n\t\tbool IsFineDifficulty:1;\n\n\t\t/*\n\t\t**\tIf the harvester is to explode more violently than normal\n\t\t**\tif it is carrying cargo, then this flag will be true.\n\t\t*/\n\t\tunsigned IsExplosiveHarvester:1;\n\n\t\t/*\n\t\t**\tIf this flag is true, then the construction yard can undeploy back into an MCV.\n\t\t*/\n\t\tunsigned IsMCVDeploy:1;\n\n\t\t/*\n\t\t**\tIf the base is to be revealed to a new ally, then this\n\t\t**\tflag will be true.\n\t\t*/\n\t\tunsigned IsAllyReveal:1;\n\n\t\t/*\n\t\t**\tCan the helipad (and airfield) be purchased separately from the associated\n\t\t**\taircraft.\n\t\t*/\n\t\tunsigned IsSeparate:1;\n\n\t\t/*\n\t\t**\tGive target cursor for trees? Doing this will make targetting of trees easier.\n\t\t*/\n\t\tunsigned IsTreeTarget:1;\n\n\t\t/*\n\t\t**\tAre friendly units automatically aware of mines so that they can avoid them?\n\t\t*/\n\t\tunsigned IsMineAware:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to grow, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTGrowth:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to spread, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTSpread:1;\n\n\t\t/*\n\t\t**\tShould civilan buildings and civilians display their true name rather than\n\t\t**\tthe generic \"Civilian Building\" and \"Civilain\"?\n\t\t*/\n\t\tunsigned IsNamed:1;\n\n\t\t/*\n\t\t**\tShould player controlled vehicles automatically try to crush nearby infantry\n\t\t**\tinstead of required the player to manually direct them to crush.\n\t\t*/\n\t\tunsigned IsAutoCrush:1;\n\n\t\t/*\n\t\t**\tShould the player controlled buildings and units automatically return fire when\n\t\t**\tfired upon?\n\t\t*/\n\t\tunsigned IsSmartDefense:1;\n\n\t\t/*\n\t\t**\tShould player controlled units try to scatter more easily in order to\n\t\t**\tavoid damage or threats?\n\t\t*/\n\t\tunsigned IsScatter:1;\n\n\t\t/*\n\t\t**\tIf the chronoshift effect should kill all cargo, then this flag will\n\t\t**\tbe set to true.\n\t\t*/\n\t\tunsigned IsChronoKill:1;\n\n\t\t/*\n\t\t**\tWhen infantry are prone or when civilians are running around like crazy,\n\t\t**\tthey are less prone to damage. This specifies the multiplier to the damage\n\t\t**\t(as a fixed point number).\n\t\t*/\n\t\tfixed ProneDamageBias;\n\n\t\t/*\n\t\t**\tThe time quake will do this percentage of damage to all units and buildings\n\t\t**\tin the game. The number is expressed as a fixed point percentage.\n\t\t*/\n\t\tfixed QuakeDamagePercent;\n\n\t\t/*\n\t\t**\tPercentage chance that a time quake will occur with each chronoshift use.\n\t\t*/\n\t\tfixed QuakeChance;\n\n\t\t/*\n\t\t**\tOre (Tiberium) growth rate. The value is the number of minutes between\n\t\t**\tgrowth steps.\n\t\t*/\n\t\tfixed GrowthRate;\n\n\t\t/*\n\t\t**\tThis specifies the number of minutes between each shroud regrowth process.\n\t\t*/\n\t\tfixed ShroudRate;\n\n\t\t/*\n\t\t**\tThis is the average minutes between each generation of a random crate\n\t\t**\tto be placed on the map if generating of random crates is indicated.\n\t\t*/\n\t\tfixed CrateTime;\n\n\t\t/*\n\t\t**\tThis specifies the number of minutes remaining before that if the mission timer\n\t\t**\tgets to this level or below, it will be displayed in red.\n\t\t*/\n\t\tfixed TimerWarning;\n\n\t\t/*\n\t\t**\tThis specifies the minutes of delay between recharges for these\n\t\t**\tspecial weapon types.\n\t\t*/\n\t\tfixed SonarTime;\n\t\tfixed ChronoTime;\n\t\tfixed ParaBombTime;\n\t\tfixed ParaInfantryTime;\n\t\tfixed ParaSaboteurTime;\n\t\tfixed SpyTime;\n\t\tfixed IronCurtainTime;\n\t\tfixed GPSTime;\n\t\tfixed NukeTime;\n\n\t\t/*\n\t\t**\tOther miscellaneous delay times.\n\t\t*/\n\t\tfixed SpeakDelay;\n\t\tfixed DamageDelay;\n\n\t\t/*\n\t\t**\tThis is the gravity constant used to control the arcing and descent of ballistic\n\t\t**\tobject such as grenades and artillery.\n\t\t*/\n\t\tint Gravity;\n\n\t\t/*\n\t\t**\tGap generators have a shroud radius of this many cells.\n\t\t*/\n\t\tint GapShroudRadius;\n\n\t\t/*\n\t\t**\tThis is the minute interval between the gap generators refreshing\n\t\t**\ttheir zones of gapping.\n\t\t*/\n\t\tfixed GapRegenInterval;\n\n\t\t/*\n\t\t**\tMobile radar jammer radius of effect.\n\t\t*/\n\t\tLEPTON RadarJamRadius;\n\n\t\t/*\n\t\t**\tThe speed at which a projectile that travels at or slower will cause\n\t\t**\tobjects in the target location to scatter. This simulates the ability\n\t\t**\tof targets to run for cover if the projectile gives them enough time\n\t\t**\tto react.\n\t\t*/\n\t\tMPHType Incoming;\n\n\t\t/*\n\t\t**\tMinimum and maximum damage allowed per shot.\n\t\t*/\n\t\tint MinDamage;\n\t\tint MaxDamage;\n\n\t\t/*\n\t\t**\tThis is the rate of repair for units and buildings. The rate is the\n\t\t**\tnumber of strength points repaired per repair clock tick. The cost of\n\t\t**\trepair is the (fixed point) fractional cost to repair the object based\n\t\t**\ton the full price of the object. Example; a value of 50% means that to\n\t\t**\trepair the object from 1 damage point to full strength would cost 50% of\n\t\t**\tthe cost to build it from scratch.\n\t\t*/\n\t\tint RepairStep;\n\t\tfixed RepairPercent;\n\t\tint URepairStep;\n\t\tfixed URepairPercent;\n\n\t\t/*\n\t\t**\tThis is the rate that objects with self healing will heal. They will repair a bit\n\t\t**\tevery 'this' number of minutes.\n\t\t*/\n\t\tfixed RepairRate;\n\n\t\t/*\n\t\t**\tThese fixed point values are used to determine the status (health bar\n\t\t**\tcolor) of the game objects. Objects in the 'yellow' are in a cautionary\n\t\t**\tstate. Object in the 'red' are in a danger state.\n\t\t*/\n\t\tfixed ConditionGreen;\n\t\tfixed ConditionYellow;\n\t\tfixed ConditionRed;\n\n\t\t/*\n\t\t**\tAverage number of minutes between infantry random idle animations.\n\t\t*/\n\t\tfixed RandomAnimateTime;\n\n\t\t/*\n\t\t**\tThese control the capacity and value of the ore types that a harvester\n\t\t**\tmay carry. The harvester carries a maximum discrete number of 'bails'.\n\t\t**\tThe value of each bail depends on the ore it is composed of.\n\t\t*/\n\t\tint BailCount;\t\t// was STEP_COUNT\n\t\tint GoldValue;\t\t// was GOLD_WORTH\n\t\tint GemValue;\t\t// was GEM_WORTH\n\n\t\t/*\n\t\t**\tThis specifies the heap maximum for the various game objects.\n\t\t*/\n\t\tint AircraftMax;\n\t\tint AnimMax;\n\t\tint BuildingMax;\n\t\tint BulletMax;\n\t\tint FactoryMax;\n\t\tint InfantryMax;\n\t\tint OverlayMax;\n\t\tint SmudgeMax;\n\t\tint TeamMax;\n\t\tint TeamTypeMax;\n\t\tint TemplateMax;\n\t\tint TerrainMax;\n\t\tint TriggerMax;\n\t\tint UnitMax;\n\t\tint VesselMax;\n\t\tint ProjectileMax;\n\t\tint WeaponMax;\n\t\tint WarheadMax;\n\t\tint TrigTypeMax;\n\n\t\t/*\n\t\t**\tClose enough distance that is used to determine if the object should\n\t\t**\tstop movement when blocked. If the distance to the desired destination\n\t\t**\tis equal to this distance or less, but the path is blocked, then consider\n\t\t**\tthe object to have gotten \"close enough\" to the destination to stop.\n\t\t*/\n\t\tLEPTON CloseEnoughDistance;\n\n\t\t/*\n\t\t**\tStray distance to group team members within. The larger the distance,\n\t\t**\tthe looser the teams will move.\n\t\t*/\n\t\tLEPTON StrayDistance;\n\n\t\t/*\n\t\t**\tIf a vehicle is closer than this range to a target that it can crush\n\t\t**\tby driving over it, then it will try to drive over it instead of firing\n\t\t**\tupon it. The larger the value, the greater the 'bigfoot crush syndrome' is\n\t\t**\thas.\n\t\t*/\n\t\tLEPTON CrushDistance;\n\n\t\t/*\n\t\t**\tFor area effect crate bonus items will affect all objects within this radius.\n\t\t*/\n\t\tLEPTON CrateRadius;\n\n\t\t/*\n\t\t**\tMaximum scatter distances for homing and non-homing projectiles.\n\t\t*/\n\t\tLEPTON HomingScatter;\n\t\tLEPTON BallisticScatter;\n\n\t\t/*\n\t\t**\tThis is the refund percentage when selling off buildings and units\n\t\t**\ton the repair pad (service depot).\n\t\t*/\n\t\tfixed RefundPercent;\n\n\t\t/*\n\t\t**\tThe Iron Curtain invulnerability effect lasts for this many minutes.\n\t\t*/\n\t\tfixed IronCurtainDuration;\n\n\t\t/*\n\t\t**\tThe strength of bridges is held here. By corollary, the strength of the\n\t\t**\tdemolition charge carried by Tanya is equal to this value as well.\n\t\t*/\n\t\tint BridgeStrength;\n\n\t\t/*\n\t\t**\tThis is the overall build speed bias. Multiply this value by the normal build\n\t\t**\tdelay to get the effective build delay.\n\t\t*/\n\t\tfixed BuildSpeedBias;\n\n\t\t/*\n\t\t**\tWeapon type array pointer should go here. Dynamic type.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tWarhead type class array pointer should go here. Dynamic type.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tGround type and speed affect data should go here.\n\t\t*/\n\n\n\t\t/*\n\t\t**\tThis is the delay between the time a C4 bomb is planted and the time it will\n\t\t**\texplode. The longer the delay, the greater safety margin for a demolitioner\n\t\t**\ttype. The short the delay, the less time the victim has to sell the building\n\t\t**\toff.\n\t\t*/\n\t\tfixed C4Delay;\n\n\t\t/*\n\t\t**\tThe computer will only repair a structure if it has spare money greater than this\n\t\t**\tamount. The thinking is that this will prevent the computer from frittering away\n\t\t**\tall it's cash on repairing and thus leaving nothing for production of defenses.\n\t\t*/\n\t\tint RepairThreshhold;\n\n\t\t/*\n\t\t**\tThis is the delay (in minutes) between retries of a failed path. The longer the\n\t\t**\tdelay the faster the system, but the longer the units take to react to a blocked\n\t\t**\tterrain event.\n\t\t*/\n\t\tfixed PathDelay;\n\n\t\t/*\n\t\t**\tThis is the special (debug version only) movie recorder timeout value. Each second\n\t\t**\tresults in about 2-3 megabytes.\n\t\t*/\n\t\tfixed MovieTime;\n\n\t\t/*\n\t\t** This is the level at or above which the chronosphere facility can\n\t\t** actually produce the chronosphere effect.  Below this tech level,\n\t\t** the facility is merely a showpiece and has no effect.\n\t\t*/\n\t\tint ChronoTechLevel;\n\n\t\t/*\n\t\t**\tThese are the Tiberium scan distances. The short range scan is used to determine if the\n\t\t**\tcurrent field has been exhausted. The long range scan is used when finding a Tiberium\n\t\t**\tfield to harvest. Keep these ranges as small as possible.\n\t\t*/\n\t\tLEPTON TiberiumShortScan;\n\t\tLEPTON TiberiumLongScan;\n\n\t\t/*\n\t\t**\tHealth bar display mode\n\t\t*/\n\t\tenum eHealthBarDisplayMode\n\t\t{\n\t\t\tHB_DAMAGED = 0,\n\t\t\tHB_ALWAYS,\n\t\t\tHB_SELECTED\n\t\t} HealthBarDisplayMode;\n\n\t\t/*\n\t\t**\tResource bar display mode\n\t\t*/\n\t\tenum eResourceBarDisplayMode\n\t\t{\n\t\t\tRB_SELECTED = 0,\n\t\t\tRB_ALWAYS,\n\t\t} ResourceBarDisplayMode;\n};\n\n\n#endif"
  },
  {
    "path": "REDALERT/RedAlert.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{DA948ED9-EF67-4813-94B7-995BE956786E}</ProjectGuid>\n    <RootNamespace>RedAlert</RootNamespace>\n    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\n    <SccProjectName>SAK</SccProjectName>\n    <SccAuxPath>SAK</SccAuxPath>\n    <SccLocalPath>SAK</SccLocalPath>\n    <SccProvider>SAK</SccProvider>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n    <Import Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.props\" />\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>..\\bin\\$(PlatformName)\\</OutDir>\n    <IntDir>$(PlatformName)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>..\\bin\\$(PlatformName)\\</OutDir>\n    <IntDir>$(PlatformName)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)I</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <ConformanceMode>false</ConformanceMode>\n      <AdditionalIncludeDirectories>./win32lib</AdditionalIncludeDirectories>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n      <WholeProgramOptimization>false</WholeProgramOptimization>\n      <PreprocessorDefinitions>TRUE_FALSE_DEFINED;ENGLISH;WIN32;NDEBUG;_WINDOWS;_USRDLL;REDALERT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StructMemberAlignment>1Byte</StructMemberAlignment>\n      <ExceptionHandling>false</ExceptionHandling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <DisableSpecificWarnings>4800;4244;4996</DisableSpecificWarnings>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <TreatWarningAsError>true</TreatWarningAsError>\n    </ClCompile>\n    <Link>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>winmm.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <GenerateDebugInformation>DebugFull</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n      <DataExecutionPrevention>false</DataExecutionPrevention>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <ConformanceMode>false</ConformanceMode>\n      <AdditionalIncludeDirectories>./win32lib</AdditionalIncludeDirectories>\n      <SDLCheck>false</SDLCheck>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <PreprocessorDefinitions>TRUE_FALSE_DEFINED;ENGLISH;WIN32;_DEBUG;_WINDOWS;_USRDLL;REDALERT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ExceptionHandling>false</ExceptionHandling>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <StructMemberAlignment>1Byte</StructMemberAlignment>\n      <DisableSpecificWarnings>4800;4244;4996</DisableSpecificWarnings>\n      <TreatWarningAsError>true</TreatWarningAsError>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>winmm.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <GenerateDebugInformation>DebugFull</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n      <ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n      <DataExecutionPrevention>false</DataExecutionPrevention>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"2KEYFRAM.CPP\" />\n    <ClCompile Include=\"AADATA.CPP\" />\n    <ClCompile Include=\"ABSTRACT.CPP\" />\n    <ClCompile Include=\"ADATA.CPP\" />\n    <ClCompile Include=\"ADPCM.CPP\" />\n    <ClCompile Include=\"AIRCRAFT.CPP\" />\n    <ClCompile Include=\"ANIM.CPP\" />\n    <ClCompile Include=\"AUDIO.CPP\" />\n    <ClCompile Include=\"B64PIPE.CPP\" />\n    <ClCompile Include=\"B64STRAW.CPP\" />\n    <ClCompile Include=\"BAR.CPP\" />\n    <ClCompile Include=\"BASE.CPP\" />\n    <ClCompile Include=\"BASE64.CPP\" />\n    <ClCompile Include=\"BBDATA.CPP\" />\n    <ClCompile Include=\"BDATA.CPP\" />\n    <ClCompile Include=\"BENCH.CPP\" />\n    <ClCompile Include=\"BFIOFILE.CPP\" />\n    <ClCompile Include=\"BIGCHECK.CPP\" />\n    <ClCompile Include=\"BLOWFISH.CPP\" />\n    <ClCompile Include=\"BLOWPIPE.CPP\" />\n    <ClCompile Include=\"BLWSTRAW.CPP\" />\n    <ClCompile Include=\"BUFF.CPP\" />\n    <ClCompile Include=\"BUILDING.CPP\" />\n    <ClCompile Include=\"BULLET.CPP\" />\n    <ClCompile Include=\"CARGO.CPP\" />\n    <ClCompile Include=\"CARRY.CPP\" />\n    <ClCompile Include=\"CCDDE.CPP\" />\n    <ClCompile Include=\"CCFILE.CPP\" />\n    <ClCompile Include=\"CCINI.CPP\" />\n    <ClCompile Include=\"CCMPATH.CPP\" />\n    <ClCompile Include=\"CCPTR.CPP\" />\n    <ClCompile Include=\"CCTEN.CPP\" />\n    <ClCompile Include=\"CDATA.CPP\" />\n    <ClCompile Include=\"CDFILE.CPP\" />\n    <ClCompile Include=\"CELL.CPP\" />\n    <ClCompile Include=\"CHECKBOX.CPP\" />\n    <ClCompile Include=\"CHEKLIST.CPP\" />\n    <ClCompile Include=\"CLASS.CPP\" />\n    <ClCompile Include=\"COLRLIST.CPP\" />\n    <ClCompile Include=\"COMBAT.CPP\" />\n    <ClCompile Include=\"COMBUF.CPP\" />\n    <ClCompile Include=\"COMINIT.CPP\" />\n    <ClCompile Include=\"COMQUEUE.CPP\" />\n    <ClCompile Include=\"CONFDLG.CPP\" />\n    <ClCompile Include=\"CONNECT.CPP\" />\n    <ClCompile Include=\"CONQUER.CPP\" />\n    <ClCompile Include=\"CONST.CPP\" />\n    <ClCompile Include=\"CONTROL.CPP\" />\n    <ClCompile Include=\"COORD.CPP\" />\n    <ClCompile Include=\"CRATE.CPP\" />\n    <ClCompile Include=\"CRC.CPP\" />\n    <ClCompile Include=\"CRCPIPE.CPP\" />\n    <ClCompile Include=\"CRCSTRAW.CPP\" />\n    <ClCompile Include=\"CREDITS.CPP\" />\n    <ClCompile Include=\"CREW.CPP\" />\n    <ClCompile Include=\"CSTRAW.CPP\" />\n    <ClCompile Include=\"DDE.CPP\" />\n    <ClCompile Include=\"DEBUG.CPP\" />\n    <ClCompile Include=\"DESCDLG.CPP\" />\n    <ClCompile Include=\"DIAL8.CPP\" />\n    <ClCompile Include=\"DIALOG.CPP\" />\n    <ClCompile Include=\"DIBFILE.CPP\" />\n    <ClCompile Include=\"DIBUTIL.CPP\" />\n    <ClCompile Include=\"DISPLAY.CPP\" />\n    <ClCompile Include=\"DLLInterface.cpp\" />\n    <ClCompile Include=\"DLLInterfaceEditor.cpp\" />\n    <ClCompile Include=\"DOOR.CPP\" />\n    <ClCompile Include=\"DPMI.CPP\" />\n    <ClCompile Include=\"DRIVE.CPP\" />\n    <ClCompile Include=\"DROP.CPP\" />\n    <ClCompile Include=\"DTABLE.CPP\" />\n    <ClCompile Include=\"DYNAVEC.CPP\" />\n    <ClCompile Include=\"EDIT.CPP\" />\n    <ClCompile Include=\"EGOS.CPP\" />\n    <ClCompile Include=\"ENDING.CPP\" />\n    <ClCompile Include=\"EVENT.CPP\" />\n    <ClCompile Include=\"EXPAND.CPP\" />\n    <ClCompile Include=\"FACE.CPP\" />\n    <ClCompile Include=\"FACING.CPP\" />\n    <ClCompile Include=\"FACTORY.CPP\" />\n    <ClCompile Include=\"FIELD.CPP\" />\n    <ClCompile Include=\"FINDPATH.CPP\" />\n    <ClCompile Include=\"FIXED.CPP\" />\n    <ClCompile Include=\"FLASHER.CPP\" />\n    <ClCompile Include=\"FLY.CPP\" />\n    <ClCompile Include=\"FOOT.CPP\" />\n    <ClCompile Include=\"FUSE.CPP\" />\n    <ClCompile Include=\"GADGET.CPP\" />\n    <ClCompile Include=\"GAMEDLG.CPP\" />\n    <ClCompile Include=\"GAUGE.CPP\" />\n    <ClCompile Include=\"GETCPU.CPP\" />\n    <ClCompile Include=\"GLOBALS.CPP\" />\n    <ClCompile Include=\"GOPTIONS.CPP\" />\n    <ClCompile Include=\"GSCREEN.CPP\" />\n    <ClCompile Include=\"HDATA.CPP\" />\n    <ClCompile Include=\"HEAP.CPP\" />\n    <ClCompile Include=\"HELP.CPP\" />\n    <ClCompile Include=\"HOUSE.CPP\" />\n    <ClCompile Include=\"HSV.CPP\" />\n    <ClCompile Include=\"ICONLIST.CPP\" />\n    <ClCompile Include=\"IDATA.CPP\" />\n    <ClCompile Include=\"INFANTRY.CPP\" />\n    <ClCompile Include=\"INI.CPP\" />\n    <ClCompile Include=\"INIBIN.CPP\" />\n    <ClCompile Include=\"INICODE.CPP\" />\n    <ClCompile Include=\"INIT.CPP\" />\n    <ClCompile Include=\"INT.CPP\" />\n    <ClCompile Include=\"INTERNET.CPP\" />\n    <ClCompile Include=\"INTERPAL.CPP\" />\n    <ClCompile Include=\"INTRO.CPP\" />\n    <ClCompile Include=\"IOMAP.CPP\" />\n    <ClCompile Include=\"IOOBJ.CPP\" />\n    <ClCompile Include=\"IPX.CPP\" />\n    <ClCompile Include=\"IPX95.CPP\" />\n    <ClCompile Include=\"IPXADDR.CPP\" />\n    <ClCompile Include=\"IPXCONN.CPP\" />\n    <ClCompile Include=\"IPXGCONN.CPP\" />\n    <ClCompile Include=\"IPXMGR.CPP\" />\n    <ClCompile Include=\"ITABLE.CPP\" />\n    <ClCompile Include=\"JSHELL.CPP\" />\n    <ClCompile Include=\"KEY.CPP\" />\n    <ClCompile Include=\"LAYER.CPP\" />\n    <ClCompile Include=\"LCW.CPP\" />\n    <ClCompile Include=\"LCWPIPE.CPP\" />\n    <ClCompile Include=\"LCWSTRAW.CPP\" />\n    <ClCompile Include=\"LCWUNCMP.CPP\" />\n    <ClCompile Include=\"LINK.CPP\" />\n    <ClCompile Include=\"LIST.CPP\" />\n    <ClCompile Include=\"LOADDLG.CPP\" />\n    <ClCompile Include=\"LOGIC.CPP\" />\n    <ClCompile Include=\"LZO1X_C.CPP\" />\n    <ClCompile Include=\"LZO1X_D.CPP\" />\n    <ClCompile Include=\"LZOPIPE.CPP\" />\n    <ClCompile Include=\"LZOSTRAW.CPP\" />\n    <ClCompile Include=\"LZW.CPP\" />\n    <ClCompile Include=\"LZWPIPE.CPP\" />\n    <ClCompile Include=\"LZWSTRAW.CPP\" />\n    <ClCompile Include=\"MAP.CPP\" />\n    <ClCompile Include=\"MAPEDDLG.CPP\" />\n    <ClCompile Include=\"MAPEDIT.CPP\" />\n    <ClCompile Include=\"MAPEDPLC.CPP\" />\n    <ClCompile Include=\"MAPEDSEL.CPP\" />\n    <ClCompile Include=\"MAPEDTM.CPP\" />\n    <ClCompile Include=\"MAPSEL.CPP\" />\n    <ClCompile Include=\"MCI.CPP\" />\n    <ClCompile Include=\"MCIMOVIE.CPP\" />\n    <ClCompile Include=\"MENUS.CPP\" />\n    <ClCompile Include=\"MiscAsm.cpp\" />\n    <ClCompile Include=\"MISSION.CPP\" />\n    <ClCompile Include=\"MIXFILE.CPP\" />\n    <ClCompile Include=\"MONOC.CPP\" />\n    <ClCompile Include=\"MOUSE.CPP\" />\n    <ClCompile Include=\"MP.CPP\" />\n    <ClCompile Include=\"MPGSET.CPP\" />\n    <ClCompile Include=\"MPLAYER.CPP\" />\n    <ClCompile Include=\"MPMGRW.CPP\" />\n    <ClCompile Include=\"MPU.CPP\" />\n    <ClCompile Include=\"MSGBOX.CPP\" />\n    <ClCompile Include=\"MSGLIST.CPP\" />\n    <ClCompile Include=\"NETDLG.CPP\" />\n    <ClCompile Include=\"NULLCONN.CPP\" />\n    <ClCompile Include=\"NULLDLG.CPP\" />\n    <ClCompile Include=\"NULLMGR.CPP\" />\n    <ClCompile Include=\"OBJECT.CPP\" />\n    <ClCompile Include=\"ODATA.CPP\" />\n    <ClCompile Include=\"OPTIONS.CPP\" />\n    <ClCompile Include=\"OVERLAY.CPP\" />\n    <ClCompile Include=\"PACKET.CPP\" />\n    <ClCompile Include=\"PALETTEC.CPP\" />\n    <ClCompile Include=\"PIPE.CPP\" />\n    <ClCompile Include=\"PK.CPP\" />\n    <ClCompile Include=\"PKPIPE.CPP\" />\n    <ClCompile Include=\"PKSTRAW.CPP\" />\n    <ClCompile Include=\"POWER.CPP\" />\n    <ClCompile Include=\"PROFILE.CPP\" />\n    <ClCompile Include=\"QUEUE.CPP\" />\n    <ClCompile Include=\"RADAR.CPP\" />\n    <ClCompile Include=\"RADIO.CPP\" />\n    <ClCompile Include=\"RAMFILE.CPP\" />\n    <ClCompile Include=\"RAND.CPP\" />\n    <ClCompile Include=\"RANDOM.CPP\" />\n    <ClCompile Include=\"RAWFILE.CPP\" />\n    <ClCompile Include=\"RAWOLAPI.CPP\" />\n    <ClCompile Include=\"READLINE.CPP\" />\n    <ClCompile Include=\"RECT.CPP\" />\n    <ClCompile Include=\"REINF.CPP\" />\n    <ClCompile Include=\"RGB.CPP\" />\n    <ClCompile Include=\"RNDSTRAW.CPP\" />\n    <ClCompile Include=\"ROTBMP.CPP\" />\n    <ClCompile Include=\"RULES.CPP\" />\n    <ClCompile Include=\"SAVELOAD.CPP\" />\n    <ClCompile Include=\"SCENARIO.CPP\" />\n    <ClCompile Include=\"SCORE.CPP\" />\n    <ClCompile Include=\"SCROLL.CPP\" />\n    <ClCompile Include=\"SDATA.CPP\" />\n    <ClCompile Include=\"SEDITDLG.CPP\" />\n    <ClCompile Include=\"SENDFILE.CPP\" />\n    <ClCompile Include=\"SEQCONN.CPP\" />\n    <ClCompile Include=\"SESSION.CPP\" />\n    <ClCompile Include=\"SHA.CPP\" />\n    <ClCompile Include=\"Shape.cpp\" />\n    <ClCompile Include=\"SHAPEBTN.CPP\" />\n    <ClCompile Include=\"SHAPIPE.CPP\" />\n    <ClCompile Include=\"SHASTRAW.CPP\" />\n    <ClCompile Include=\"SIDEBAR.CPP\" />\n    <ClCompile Include=\"SIDEBARGlyphx.CPP\" />\n    <ClCompile Include=\"SLIDER.CPP\" />\n    <ClCompile Include=\"SMUDGE.CPP\" />\n    <ClCompile Include=\"SOUNDDLG.CPP\" />\n    <ClCompile Include=\"SPECIAL.CPP\" />\n    <ClCompile Include=\"SPRITE.CPP\" />\n    <ClCompile Include=\"STARTUP.CPP\" />\n    <ClCompile Include=\"STATBTN.CPP\" />\n    <ClCompile Include=\"STATS.CPP\" />\n    <ClCompile Include=\"STRAW.CPP\" />\n    <ClCompile Include=\"STUB.CPP\" />\n    <ClCompile Include=\"SUPER.CPP\" />\n    <ClCompile Include=\"SURFACE.CPP\" />\n    <ClCompile Include=\"TAB.CPP\" />\n    <ClCompile Include=\"TACTION.CPP\" />\n    <ClCompile Include=\"TARGET.CPP\" />\n    <ClCompile Include=\"TCPIP.CPP\" />\n    <ClCompile Include=\"TDATA.CPP\" />\n    <ClCompile Include=\"TEAM.CPP\" />\n    <ClCompile Include=\"TEAMTYPE.CPP\" />\n    <ClCompile Include=\"TECHNO.CPP\" />\n    <ClCompile Include=\"TEMPLATE.CPP\" />\n    <ClCompile Include=\"TENMGR.CPP\" />\n    <ClCompile Include=\"TERRAIN.CPP\" />\n    <ClCompile Include=\"TEVENT.CPP\" />\n    <ClCompile Include=\"TEXTBTN.CPP\" />\n    <ClCompile Include=\"THEME.CPP\" />\n    <ClCompile Include=\"TOGGLE.CPP\" />\n    <ClCompile Include=\"TOOLTIP.CPP\" />\n    <ClCompile Include=\"TRACKER.CPP\" />\n    <ClCompile Include=\"TRIGGER.CPP\" />\n    <ClCompile Include=\"TRIGTYPE.CPP\" />\n    <ClCompile Include=\"TXTLABEL.CPP\" />\n    <ClCompile Include=\"UDATA.CPP\" />\n    <ClCompile Include=\"UDPADDR.CPP\" />\n    <ClCompile Include=\"UNIT.CPP\" />\n    <ClCompile Include=\"UTRACKER.CPP\" />\n    <ClCompile Include=\"VDATA.CPP\" />\n    <ClCompile Include=\"VECTOR.CPP\" />\n    <ClCompile Include=\"VERSION.CPP\" />\n    <ClCompile Include=\"VESSEL.CPP\" />\n    <ClCompile Include=\"VISUDLG.CPP\" />\n    <ClCompile Include=\"VORTEX.CPP\" />\n    <ClCompile Include=\"W95TRACE.CPP\" />\n    <ClCompile Include=\"WARHEAD.CPP\" />\n    <ClCompile Include=\"WEAPON.CPP\" />\n    <ClCompile Include=\"Win32Lib\\ALLOC.CPP\" />\n    <ClCompile Include=\"Win32Lib\\BUFFER.CPP\" />\n    <ClCompile Include=\"Win32Lib\\BUFFGLBL.CPP\" />\n    <ClCompile Include=\"Win32Lib\\DDRAW.CPP\" />\n    <ClCompile Include=\"Win32Lib\\DELAY.CPP\" />\n    <ClCompile Include=\"Win32Lib\\DIPTHONG.CPP\" />\n    <ClCompile Include=\"Win32Lib\\DrawMisc.cpp\" />\n    <ClCompile Include=\"Win32Lib\\DRAWRECT.CPP\" />\n    <ClCompile Include=\"Win32Lib\\FONT.CPP\" />\n    <ClCompile Include=\"Win32Lib\\GBUFFER.CPP\" />\n    <ClCompile Include=\"Win32Lib\\GETSHAPE.CPP\" />\n    <ClCompile Include=\"Win32Lib\\ICONSET.CPP\" />\n    <ClCompile Include=\"Win32Lib\\IFF.CPP\" />\n    <ClCompile Include=\"Win32Lib\\IRANDOM.CPP\" />\n    <ClCompile Include=\"Win32Lib\\LOAD.CPP\" />\n    <ClCompile Include=\"Win32Lib\\LOADFONT.CPP\" />\n    <ClCompile Include=\"Win32Lib\\MOUSEWW.CPP\" />\n    <ClCompile Include=\"Win32Lib\\PALETTE.CPP\" />\n    <ClCompile Include=\"Win32Lib\\SET_FONT.CPP\" />\n    <ClCompile Include=\"Win32Lib\\TIMER.CPP\" />\n    <ClCompile Include=\"Win32Lib\\TIMERDWN.CPP\" />\n    <ClCompile Include=\"Win32Lib\\TIMERINI.CPP\" />\n    <ClCompile Include=\"Win32Lib\\WINDOWS.CPP\" />\n    <ClCompile Include=\"Win32Lib\\WINHIDE.CPP\" />\n    <ClCompile Include=\"Win32Lib\\WRITEPCX.CPP\" />\n    <ClCompile Include=\"Win32Lib\\_DIPTABL.CPP\" />\n    <ClCompile Include=\"WINSTUB.CPP\" />\n    <ClCompile Include=\"WOLAPIOB.CPP\" />\n    <ClCompile Include=\"WOLEDIT.CPP\" />\n    <ClCompile Include=\"WOLSTRNG.CPP\" />\n    <ClCompile Include=\"WOL_CGAM.CPP\" />\n    <ClCompile Include=\"WOL_CHAT.CPP\" />\n    <ClCompile Include=\"WOL_DNLD.CPP\" />\n    <ClCompile Include=\"WOL_GSUP.CPP\" />\n    <ClCompile Include=\"WOL_LOGN.CPP\" />\n    <ClCompile Include=\"WOL_MAIN.CPP\" />\n    <ClCompile Include=\"WOL_OPT.CPP\" />\n    <ClCompile Include=\"WSPIPX.CPP\" />\n    <ClCompile Include=\"WSPROTO.CPP\" />\n    <ClCompile Include=\"WSPUDP.CPP\" />\n    <ClCompile Include=\"XPIPE.CPP\" />\n    <ClCompile Include=\"XSTRAW.CPP\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"ABSTRACT.H\" />\n    <ClInclude Include=\"AIRCRAFT.H\" />\n    <ClInclude Include=\"ANIM.H\" />\n    <ClInclude Include=\"AUDIO.H\" />\n    <ClInclude Include=\"B64PIPE.H\" />\n    <ClInclude Include=\"B64STRAW.H\" />\n    <ClInclude Include=\"BAR.H\" />\n    <ClInclude Include=\"BASE.H\" />\n    <ClInclude Include=\"BASE64.H\" />\n    <ClInclude Include=\"BENCH.H\" />\n    <ClInclude Include=\"BFIOFILE.H\" />\n    <ClInclude Include=\"BIGCHECK.H\" />\n    <ClInclude Include=\"BLOWFISH.H\" />\n    <ClInclude Include=\"BLOWPIPE.H\" />\n    <ClInclude Include=\"BLWSTRAW.H\" />\n    <ClInclude Include=\"BUFF.H\" />\n    <ClInclude Include=\"BUFFERX.H\" />\n    <ClInclude Include=\"BUILDING.H\" />\n    <ClInclude Include=\"BULLET.H\" />\n    <ClInclude Include=\"CARGO.H\" />\n    <ClInclude Include=\"CARRY.H\" />\n    <ClInclude Include=\"CBN_.H\" />\n    <ClInclude Include=\"CCDDE.H\" />\n    <ClInclude Include=\"CCFILE.H\" />\n    <ClInclude Include=\"CCINI.H\" />\n    <ClInclude Include=\"CCPTR.H\" />\n    <ClInclude Include=\"CDFILE.H\" />\n    <ClInclude Include=\"CELL.H\" />\n    <ClInclude Include=\"CHECKBOX.H\" />\n    <ClInclude Include=\"CHEKLIST.H\" />\n    <ClInclude Include=\"COLRLIST.H\" />\n    <ClInclude Include=\"COMBUF.H\" />\n    <ClInclude Include=\"COMINIT.H\" />\n    <ClInclude Include=\"COMPAT.H\" />\n    <ClInclude Include=\"COMQUEUE.H\" />\n    <ClInclude Include=\"CONFDLG.H\" />\n    <ClInclude Include=\"CONNECT.H\" />\n    <ClInclude Include=\"CONNMGR.H\" />\n    <ClInclude Include=\"CONQUER.H\" />\n    <ClInclude Include=\"CONTROL.H\" />\n    <ClInclude Include=\"COORDA.h\" />\n    <ClInclude Include=\"CRATE.H\" />\n    <ClInclude Include=\"CRC.H\" />\n    <ClInclude Include=\"CRCPIPE.H\" />\n    <ClInclude Include=\"CRCSTRAW.H\" />\n    <ClInclude Include=\"CREDITS.H\" />\n    <ClInclude Include=\"CREW.H\" />\n    <ClInclude Include=\"CSTRAW.H\" />\n    <ClInclude Include=\"DDE.H\" />\n    <ClInclude Include=\"DEBUG.H\" />\n    <ClInclude Include=\"DEFINES.H\" />\n    <ClInclude Include=\"DESCDLG.H\" />\n    <ClInclude Include=\"DIAL8.H\" />\n    <ClInclude Include=\"DIBAPI.H\" />\n    <ClInclude Include=\"DIBUTIL.H\" />\n    <ClInclude Include=\"DISPLAY.H\" />\n    <ClInclude Include=\"DLLInterface.h\" />\n    <ClInclude Include=\"DLLInterfaceVersion.h\" />\n    <ClInclude Include=\"DOOR.H\" />\n    <ClInclude Include=\"DPMI.H\" />\n    <ClInclude Include=\"DRIVE.H\" />\n    <ClInclude Include=\"DROP.H\" />\n    <ClInclude Include=\"EDIT.H\" />\n    <ClInclude Include=\"EGOS.H\" />\n    <ClInclude Include=\"ENDING.H\" />\n    <ClInclude Include=\"EVENT.H\" />\n    <ClInclude Include=\"EXTERNS.H\" />\n    <ClInclude Include=\"FACE.H\" />\n    <ClInclude Include=\"FACING.H\" />\n    <ClInclude Include=\"FACTORY.H\" />\n    <ClInclude Include=\"FAKESOCK.H\" />\n    <ClInclude Include=\"FIELD.H\" />\n    <ClInclude Include=\"FILEPCX.H\" />\n    <ClInclude Include=\"FIXED.H\" />\n    <ClInclude Include=\"FLASHER.H\" />\n    <ClInclude Include=\"FLY.H\" />\n    <ClInclude Include=\"FOOT.H\" />\n    <ClInclude Include=\"FTIMER.H\" />\n    <ClInclude Include=\"FUNCTION.H\" />\n    <ClInclude Include=\"FUSE.H\" />\n    <ClInclude Include=\"GADGET.H\" />\n    <ClInclude Include=\"GAMEDLG.H\" />\n    <ClInclude Include=\"GAUGE.H\" />\n    <ClInclude Include=\"GOPTIONS.H\" />\n    <ClInclude Include=\"GSCREEN.H\" />\n    <ClInclude Include=\"HEAP.H\" />\n    <ClInclude Include=\"HELP.H\" />\n    <ClInclude Include=\"HOUSE.H\" />\n    <ClInclude Include=\"HSV.H\" />\n    <ClInclude Include=\"ICONLIST.H\" />\n    <ClInclude Include=\"INFANTRY.H\" />\n    <ClInclude Include=\"INI.H\" />\n    <ClInclude Include=\"INLINE.H\" />\n    <ClInclude Include=\"INT.H\" />\n    <ClInclude Include=\"INTERNET.H\" />\n    <ClInclude Include=\"INTRO.H\" />\n    <ClInclude Include=\"IPX.H\" />\n    <ClInclude Include=\"IPX95.H\" />\n    <ClInclude Include=\"IPXADDR.H\" />\n    <ClInclude Include=\"IPXCONN.H\" />\n    <ClInclude Include=\"IPXGCONN.H\" />\n    <ClInclude Include=\"IPXMGR.H\" />\n    <ClInclude Include=\"JSHELL.H\" />\n    <ClInclude Include=\"KEY.H\" />\n    <ClInclude Include=\"LANGUAGE.H\" />\n    <ClInclude Include=\"LAYER.H\" />\n    <ClInclude Include=\"LCW.H\" />\n    <ClInclude Include=\"LCWPIPE.H\" />\n    <ClInclude Include=\"LCWSTRAW.H\" />\n    <ClInclude Include=\"LED.H\" />\n    <ClInclude Include=\"LINK.H\" />\n    <ClInclude Include=\"LINT.H\" />\n    <ClInclude Include=\"LIST.H\" />\n    <ClInclude Include=\"LISTNODE.H\" />\n    <ClInclude Include=\"LOADDLG.H\" />\n    <ClInclude Include=\"LOGIC.H\" />\n    <ClInclude Include=\"LZO.H\" />\n    <ClInclude Include=\"LZO1X.H\" />\n    <ClInclude Include=\"LZOCONF.H\" />\n    <ClInclude Include=\"LZOPIPE.H\" />\n    <ClInclude Include=\"LZOSTRAW.H\" />\n    <ClInclude Include=\"LZO_CONF.H\" />\n    <ClInclude Include=\"LZW.H\" />\n    <ClInclude Include=\"LZWPIPE.H\" />\n    <ClInclude Include=\"LZWSTRAW.H\" />\n    <ClInclude Include=\"MAP.H\" />\n    <ClInclude Include=\"MAPEDIT.H\" />\n    <ClInclude Include=\"MCI.H\" />\n    <ClInclude Include=\"MCIMOVIE.H\" />\n    <ClInclude Include=\"MEMCHECK.H\" />\n    <ClInclude Include=\"MESSAGE.H\" />\n    <ClInclude Include=\"MISSION.H\" />\n    <ClInclude Include=\"MIXFILE.H\" />\n    <ClInclude Include=\"MONOC.H\" />\n    <ClInclude Include=\"MOUSE.H\" />\n    <ClInclude Include=\"MOVIE.H\" />\n    <ClInclude Include=\"MP.H\" />\n    <ClInclude Include=\"MPGSET.H\" />\n    <ClInclude Include=\"MPMGRD.H\" />\n    <ClInclude Include=\"MPMGRW.H\" />\n    <ClInclude Include=\"MPU.H\" />\n    <ClInclude Include=\"MSGBOX.H\" />\n    <ClInclude Include=\"MSGLIST.H\" />\n    <ClInclude Include=\"NULLCONN.H\" />\n    <ClInclude Include=\"NULLMGR.H\" />\n    <ClInclude Include=\"OBJECT.H\" />\n    <ClInclude Include=\"OCIDL.H\" />\n    <ClInclude Include=\"OPTIONS.H\" />\n    <ClInclude Include=\"OVERLAY.H\" />\n    <ClInclude Include=\"PACKET.H\" />\n    <ClInclude Include=\"PALETTEC.H\" />\n    <ClInclude Include=\"PIPE.H\" />\n    <ClInclude Include=\"PK.H\" />\n    <ClInclude Include=\"PKPIPE.H\" />\n    <ClInclude Include=\"PKSTRAW.H\" />\n    <ClInclude Include=\"POWER.H\" />\n    <ClInclude Include=\"QUEUE.H\" />\n    <ClInclude Include=\"RADAR.H\" />\n    <ClInclude Include=\"RADIO.H\" />\n    <ClInclude Include=\"RAMFILE.H\" />\n    <ClInclude Include=\"RANDOM.H\" />\n    <ClInclude Include=\"RAWFILE.H\" />\n    <ClInclude Include=\"RAWOLAPI.H\" />\n    <ClInclude Include=\"READLINE.H\" />\n    <ClInclude Include=\"RECT.H\" />\n    <ClInclude Include=\"REGION.H\" />\n    <ClInclude Include=\"Resource\\resource.h\" />\n    <ClInclude Include=\"RGB.H\" />\n    <ClInclude Include=\"RNDSTRAW.H\" />\n    <ClInclude Include=\"RNG.H\" />\n    <ClInclude Include=\"ROTBMP.H\" />\n    <ClInclude Include=\"RULES.H\" />\n    <ClInclude Include=\"SAVEDLG.H\" />\n    <ClInclude Include=\"SCENARIO.H\" />\n    <ClInclude Include=\"SCORE.H\" />\n    <ClInclude Include=\"SCREEN.H\" />\n    <ClInclude Include=\"SCROLL.H\" />\n    <ClInclude Include=\"SEARCH.H\" />\n    <ClInclude Include=\"SEDITDLG.H\" />\n    <ClInclude Include=\"SEQCONN.H\" />\n    <ClInclude Include=\"SESSION.H\" />\n    <ClInclude Include=\"SHA.H\" />\n    <ClInclude Include=\"SHAPEBTN.H\" />\n    <ClInclude Include=\"SHAPIPE.H\" />\n    <ClInclude Include=\"SHASTRAW.H\" />\n    <ClInclude Include=\"SIDEBAR.H\" />\n    <ClInclude Include=\"SIDEBARGlyphx.H\" />\n    <ClInclude Include=\"SLIDER.H\" />\n    <ClInclude Include=\"SMUDGE.H\" />\n    <ClInclude Include=\"SOUNDDLG.H\" />\n    <ClInclude Include=\"SPECIAL.H\" />\n    <ClInclude Include=\"STAGE.H\" />\n    <ClInclude Include=\"STATBTN.H\" />\n    <ClInclude Include=\"STRAW.H\" />\n    <ClInclude Include=\"STYLE.H\" />\n    <ClInclude Include=\"SUPER.H\" />\n    <ClInclude Include=\"SURFACE.H\" />\n    <ClInclude Include=\"TAB.H\" />\n    <ClInclude Include=\"TACTION.H\" />\n    <ClInclude Include=\"TARGET.H\" />\n    <ClInclude Include=\"TCPIP.H\" />\n    <ClInclude Include=\"TEAM.H\" />\n    <ClInclude Include=\"TEAMTYPE.H\" />\n    <ClInclude Include=\"TECHNO.H\" />\n    <ClInclude Include=\"TEMPLATE.H\" />\n    <ClInclude Include=\"TENMGR.H\" />\n    <ClInclude Include=\"TERRAIN.H\" />\n    <ClInclude Include=\"TEVENT.H\" />\n    <ClInclude Include=\"TEXTBTN.H\" />\n    <ClInclude Include=\"THEME.H\" />\n    <ClInclude Include=\"TOGGLE.H\" />\n    <ClInclude Include=\"TOOLTIP.H\" />\n    <ClInclude Include=\"TRIGGER.H\" />\n    <ClInclude Include=\"TRIGTYPE.H\" />\n    <ClInclude Include=\"TXTLABEL.H\" />\n    <ClInclude Include=\"TYPE.H\" />\n    <ClInclude Include=\"UNIT.H\" />\n    <ClInclude Include=\"UTRACKER.H\" />\n    <ClInclude Include=\"VECTOR.H\" />\n    <ClInclude Include=\"VERSION.H\" />\n    <ClInclude Include=\"VESSEL.H\" />\n    <ClInclude Include=\"VISUDLG.H\" />\n    <ClInclude Include=\"VORTEX.H\" />\n    <ClInclude Include=\"W95TRACE.H\" />\n    <ClInclude Include=\"WARHEAD.H\" />\n    <ClInclude Include=\"WATCOM.H\" />\n    <ClInclude Include=\"WEAPON.H\" />\n    <ClInclude Include=\"Win32Lib\\AUDIO.H\" />\n    <ClInclude Include=\"Win32Lib\\BUFFER.H\" />\n    <ClInclude Include=\"Win32Lib\\DDRAW.H\" />\n    <ClInclude Include=\"Win32Lib\\DEFINES.H\" />\n    <ClInclude Include=\"Win32Lib\\DESCMGMT.H\" />\n    <ClInclude Include=\"Win32Lib\\DIPTHONG.H\" />\n    <ClInclude Include=\"Win32Lib\\DPLAY.H\" />\n    <ClInclude Include=\"Win32Lib\\DRAWBUFF.H\" />\n    <ClInclude Include=\"Win32Lib\\DSETUP.H\" />\n    <ClInclude Include=\"Win32Lib\\DSOUND.H\" />\n    <ClInclude Include=\"Win32Lib\\EXTERNS.H\" />\n    <ClInclude Include=\"Win32Lib\\FASTFILE.H\" />\n    <ClInclude Include=\"Win32Lib\\FILE.H\" />\n    <ClInclude Include=\"Win32Lib\\FILEPCX.H\" />\n    <ClInclude Include=\"Win32Lib\\FILETEMP.H\" />\n    <ClInclude Include=\"Win32Lib\\FONT.H\" />\n    <ClInclude Include=\"Win32Lib\\FUNCTION.H\" />\n    <ClInclude Include=\"Win32Lib\\GBUFFER.H\" />\n    <ClInclude Include=\"Win32Lib\\ICONCACH.H\" />\n    <ClInclude Include=\"Win32Lib\\IFF.H\" />\n    <ClInclude Include=\"Win32Lib\\KEYBOARD.H\" />\n    <ClInclude Include=\"Win32Lib\\MEMFLAG.H\" />\n    <ClInclude Include=\"Win32Lib\\MISC.H\" />\n    <ClInclude Include=\"Win32Lib\\MODEMREG.H\" />\n    <ClInclude Include=\"Win32Lib\\MONO.H\" />\n    <ClInclude Include=\"Win32Lib\\MOUSE.H\" />\n    <ClInclude Include=\"Win32Lib\\PALETTE.H\" />\n    <ClInclude Include=\"Win32Lib\\PLAYCD.H\" />\n    <ClInclude Include=\"Win32Lib\\PROFILE.H\" />\n    <ClInclude Include=\"Win32Lib\\RAWFILE.H\" />\n    <ClInclude Include=\"Win32Lib\\SHAPE.H\" />\n    <ClInclude Include=\"Win32Lib\\SOS.H\" />\n    <ClInclude Include=\"Win32Lib\\SOSCOMP.H\" />\n    <ClInclude Include=\"Win32Lib\\SOSDATA.H\" />\n    <ClInclude Include=\"Win32Lib\\SOSDEFS.H\" />\n    <ClInclude Include=\"Win32Lib\\SOSFNCT.H\" />\n    <ClInclude Include=\"Win32Lib\\SOSRES.H\" />\n    <ClInclude Include=\"Win32Lib\\SOUND.H\" />\n    <ClInclude Include=\"Win32Lib\\SOUNDINT.H\" />\n    <ClInclude Include=\"Win32Lib\\STRUCTS.H\" />\n    <ClInclude Include=\"Win32Lib\\TILE.H\" />\n    <ClInclude Include=\"Win32Lib\\TIMER.H\" />\n    <ClInclude Include=\"Win32Lib\\VIDEO.H\" />\n    <ClInclude Include=\"Win32Lib\\WINCOMM.H\" />\n    <ClInclude Include=\"Win32Lib\\WSA.H\" />\n    <ClInclude Include=\"Win32Lib\\WWFILE.H\" />\n    <ClInclude Include=\"Win32Lib\\WWLIB32.H\" />\n    <ClInclude Include=\"Win32Lib\\WWMEM.H\" />\n    <ClInclude Include=\"Win32Lib\\wwstd.h\" />\n    <ClInclude Include=\"Win32Lib\\WW_WIN.H\" />\n    <ClInclude Include=\"WOLAPIOB.H\" />\n    <ClInclude Include=\"WOLDEBUG.H\" />\n    <ClInclude Include=\"WOLEDIT.H\" />\n    <ClInclude Include=\"WOLSTRNG.H\" />\n    <ClInclude Include=\"WOL_GSUP.H\" />\n    <ClInclude Include=\"WSNWLINK.H\" />\n    <ClInclude Include=\"WSPIPX.H\" />\n    <ClInclude Include=\"WSPROTO.H\" />\n    <ClInclude Include=\"WSPUDP.H\" />\n    <ClInclude Include=\"WWALLOC.H\" />\n    <ClInclude Include=\"WWFILE.H\" />\n    <ClInclude Include=\"XPIPE.H\" />\n    <ClInclude Include=\"XSTRAW.H\" />\n    <ClInclude Include=\"_WSPROTO.H\" />\n  </ItemGroup>\n  <ItemGroup>\n    <MASM Include=\"LCWCOMP.ASM\" />\n    <MASM Include=\"MMX.ASM\" />\n    <MASM Include=\"TXTPRNT.ASM\" />\n    <MASM Include=\"Win32Lib\\LCWCOMP.ASM\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n    </MASM>\n    <MASM Include=\"Win32Lib\\TOBUFF.ASM\" />\n    <None Include=\"COORDA.ASM\" />\n    <MASM Include=\"KEYFBUFF.ASM\">\n      <FileType>Document</FileType>\n      <EnableMASM51Compatibility Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</EnableMASM51Compatibility>\n      <PreserveIdentifierCase Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">1</PreserveIdentifierCase>\n      <EnableMASM51Compatibility Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</EnableMASM51Compatibility>\n      <PreserveIdentifierCase Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">1</PreserveIdentifierCase>\n    </MASM>\n    <None Include=\"Win32Lib\\DIFFTB.INC\" />\n    <None Include=\"Win32Lib\\DRAWBUFF.INC\" />\n    <None Include=\"Win32Lib\\GBUFFER.INC\" />\n    <None Include=\"Win32Lib\\INDEXTB.INC\" />\n    <None Include=\"Win32Lib\\KEYBOARD.INC\" />\n    <None Include=\"Win32Lib\\KEYSTRUC.INC\" />\n    <None Include=\"Win32Lib\\MCGAPRIM.INC\" />\n    <None Include=\"Win32Lib\\MOUSE.INC\" />\n    <None Include=\"Win32Lib\\NYBBTB.INC\" />\n    <None Include=\"Win32Lib\\PROFILE.INC\" />\n    <None Include=\"Win32Lib\\SHAPE.INC\" />\n    <None Include=\"Win32Lib\\STAMP.INC\" />\n    <None Include=\"Win32Lib\\SVGAPRIM.INC\" />\n    <None Include=\"Win32Lib\\WWMEM.INC\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"Resource\\RedAlert.rc\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n    <Import Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.targets\" />\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "REDALERT/RedAlert.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Source Files\\win32lib\">\n      <UniqueIdentifier>{fd6d77c9-ab70-415f-80a5-2f3e9fafc730}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Resource\">\n      <UniqueIdentifier>{f4599de7-e877-410c-943f-afc4bef70eb6}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"AADATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ABSTRACT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ADATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ADPCM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"AIRCRAFT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ANIM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"AUDIO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"B64PIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"B64STRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BAR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BASE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BASE64.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BBDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BENCH.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BFIOFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BIGCHECK.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BLOWFISH.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BLOWPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BLWSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BUFF.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BUILDING.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"BULLET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CARGO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CARRY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCDDE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCINI.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCMPATH.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCPTR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CCTEN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CDFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CELL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CHECKBOX.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CHEKLIST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CLASS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COLRLIST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COMBAT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COMBUF.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COMINIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COMQUEUE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CONFDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CONNECT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CONQUER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CONST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CONTROL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"COORD.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CRATE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CRC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CRCPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CRCSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CREDITS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CREW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DDE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DEBUG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DESCDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DIAL8.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DIALOG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DIBFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DIBUTIL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DISPLAY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DOOR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DPMI.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DRIVE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DROP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DTABLE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DYNAVEC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"EDIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"EGOS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ENDING.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"EVENT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"EXPAND.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FACE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FACING.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FACTORY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FIELD.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FINDPATH.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FIXED.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FLASHER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FLY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FOOT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FUSE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GADGET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GAMEDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GAUGE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GETCPU.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GLOBALS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GOPTIONS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"GSCREEN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"HDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"HEAP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"HELP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"HOUSE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"HSV.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ICONLIST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INFANTRY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INI.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INIBIN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INICODE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INTERNET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INTERPAL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"INTRO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IOMAP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IOOBJ.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPX.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPX95.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPXADDR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPXCONN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPXGCONN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"IPXMGR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ITABLE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"JSHELL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"KEY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LAYER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LCW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LCWPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LCWSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LCWUNCMP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LINK.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LIST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LOADDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LOGIC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZO1X_C.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZO1X_D.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZOPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZOSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZWPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZWSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPEDDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPEDIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPEDPLC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPEDSEL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPEDTM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MAPSEL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MCI.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MCIMOVIE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MENUS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MISSION.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MIXFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MONOC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MOUSE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MPGSET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MPLAYER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MPMGRW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MPU.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MSGBOX.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MSGLIST.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"NETDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"NULLCONN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"NULLDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"NULLMGR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"OBJECT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ODATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"OPTIONS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"OVERLAY.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PACKET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PK.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PKPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PKSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"POWER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PROFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"QUEUE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RADAR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RADIO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RAMFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RAND.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RANDOM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RAWFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RAWOLAPI.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"READLINE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RECT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"REINF.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RGB.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RNDSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ROTBMP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RULES.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SAVELOAD.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SCENARIO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SCORE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SCROLL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SEDITDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SENDFILE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SEQCONN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SESSION.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SHA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SHAPEBTN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SHAPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SHASTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SIDEBAR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SLIDER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SMUDGE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SOUNDDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SPECIAL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SPRITE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"STARTUP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"STATBTN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"STATS.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"STRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"STUB.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SUPER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SURFACE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TAB.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TACTION.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TARGET.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TCPIP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TEAM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TEAMTYPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TECHNO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TEMPLATE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TENMGR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TERRAIN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TEVENT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TEXTBTN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"THEME.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TOGGLE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TOOLTIP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TRACKER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TRIGGER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TRIGTYPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"TXTLABEL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"UDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"UDPADDR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"UNIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"UTRACKER.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VDATA.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VECTOR.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VERSION.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VESSEL.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VISUDLG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"VORTEX.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"W95TRACE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WARHEAD.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WEAPON.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WINSTUB.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_CGAM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_CHAT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_DNLD.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_GSUP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_LOGN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_MAIN.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOL_OPT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOLAPIOB.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOLEDIT.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WOLSTRNG.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WSPIPX.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WSPROTO.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WSPUDP.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"XPIPE.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"XSTRAW.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"MiscAsm.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"2KEYFRAM.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\ALLOC.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\DrawMisc.cpp\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\GBUFFER.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\MOUSEWW.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\BUFFGLBL.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\DRAWRECT.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\TIMER.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\TIMERINI.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\WRITEPCX.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\SET_FONT.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\DDRAW.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\DIPTHONG.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\TIMERDWN.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\LOADFONT.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Shape.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\WINHIDE.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\FONT.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\WINDOWS.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\GETSHAPE.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\IRANDOM.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\LOAD.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\ICONSET.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\IFF.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\DELAY.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PALETTEC.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\PALETTE.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\BUFFER.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Win32Lib\\_DIPTABL.CPP\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DLLInterface.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SIDEBARGlyphx.CPP\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DLLInterfaceEditor.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"ABSTRACT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"AIRCRAFT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ANIM.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"AUDIO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"B64PIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"B64STRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BAR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BASE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BASE64.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BENCH.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BFIOFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BIGCHECK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BLOWFISH.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BLOWPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BLWSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BUFF.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BUFFERX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BUILDING.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BULLET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CARGO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CARRY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CBN_.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CCDDE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CCFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CCINI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CCPTR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CDFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CELL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CHECKBOX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CHEKLIST.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COLRLIST.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COMBUF.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COMINIT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COMPAT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COMQUEUE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CONFDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CONNECT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CONNMGR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CONQUER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CONTROL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CRATE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CRC.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CRCPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CRCSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CREDITS.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CREW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DDE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DEBUG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DEFINES.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DESCDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DIAL8.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DIBAPI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DIBUTIL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DISPLAY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DOOR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DPMI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DRIVE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DROP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"EDIT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"EGOS.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ENDING.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"EVENT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"EXTERNS.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FACE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FACING.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FACTORY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FAKESOCK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FIELD.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FILEPCX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FIXED.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FLASHER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FLY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FOOT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FTIMER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FUNCTION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FUSE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GADGET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GAMEDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GAUGE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GOPTIONS.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GSCREEN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"HEAP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"HELP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"HOUSE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"HSV.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ICONLIST.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INFANTRY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INLINE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INTERNET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"INTRO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPX95.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPXADDR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPXCONN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPXGCONN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"IPXMGR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"JSHELL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"KEY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LANGUAGE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LAYER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LCW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LCWPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LCWSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LED.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LINK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LINT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LIST.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LISTNODE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LOADDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LOGIC.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZO_CONF.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZO1X.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZOCONF.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZOPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZOSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZWPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZWSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MAP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MAPEDIT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MCI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MCIMOVIE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MEMCHECK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MESSAGE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MISSION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MIXFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MONOC.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MOUSE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MOVIE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MPGSET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MPMGRW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MPU.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MSGBOX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MSGLIST.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"NULLCONN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"NULLMGR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OBJECT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OCIDL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OPTIONS.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OVERLAY.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PACKET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PKPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PKSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"POWER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"QUEUE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RADAR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RADIO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RAMFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RANDOM.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RAWFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RAWOLAPI.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"READLINE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RECT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"REGION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RGB.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RNDSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RNG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ROTBMP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RULES.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SAVEDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SCENARIO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SCORE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SCREEN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SCROLL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SEARCH.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SEDITDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SEQCONN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SESSION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SHA.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SHAPEBTN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SHAPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SHASTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SIDEBAR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SLIDER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SMUDGE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SOUNDDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SPECIAL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"STAGE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"STATBTN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"STRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"STYLE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SUPER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SURFACE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TAB.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TACTION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TARGET.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TCPIP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TEAM.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TEAMTYPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TECHNO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TEMPLATE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TENMGR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TERRAIN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TEVENT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TEXTBTN.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"THEME.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TOGGLE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TOOLTIP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TRIGGER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TRIGTYPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TXTLABEL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"TYPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"UNIT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"UTRACKER.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"VECTOR.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"VERSION.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"VESSEL.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"VISUDLG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"VORTEX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"W95TRACE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WARHEAD.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WATCOM.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WEAPON.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WOL_GSUP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WOLAPIOB.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WOLDEBUG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WOLEDIT.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WOLSTRNG.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WSNWLINK.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WSPIPX.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WSPROTO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WSPUDP.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WWALLOC.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WWFILE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"XPIPE.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"XSTRAW.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\AUDIO.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\BUFFER.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DDRAW.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DEFINES.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DESCMGMT.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DIPTHONG.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DPLAY.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DRAWBUFF.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DSETUP.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\DSOUND.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\EXTERNS.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FASTFILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FILEPCX.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FILETEMP.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FONT.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\FUNCTION.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\GBUFFER.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\ICONCACH.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\IFF.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\KEYBOARD.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\MEMFLAG.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\MISC.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\MODEMREG.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\MONO.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\MOUSE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\PALETTE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\PLAYCD.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\PROFILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\RAWFILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SHAPE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOS.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOSCOMP.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOSDATA.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOSDEFS.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOSFNCT.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOSRES.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOUND.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\SOUNDINT.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\STRUCTS.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\TILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\TIMER.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\VIDEO.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WINCOMM.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WSA.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WW_WIN.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WWFILE.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WWLIB32.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\WWMEM.H\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Win32Lib\\wwstd.h\">\n      <Filter>Source Files\\win32lib</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PALETTEC.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DLLInterface.h\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SIDEBARGlyphx.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Resource\\resource.h\">\n      <Filter>Source Files\\Resource</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DLLInterfaceVersion.h\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"_WSPROTO.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"COORDA.h\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"MPMGRD.H\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"COORDA.ASM\">\n      <Filter>Source Files</Filter>\n    </None>\n    <None Include=\"Win32Lib\\DIFFTB.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\DRAWBUFF.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\GBUFFER.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\INDEXTB.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\KEYBOARD.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\KEYSTRUC.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\MCGAPRIM.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\MOUSE.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\NYBBTB.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\PROFILE.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\SHAPE.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\STAMP.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\SVGAPRIM.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n    <None Include=\"Win32Lib\\WWMEM.INC\">\n      <Filter>Source Files\\win32lib</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <MASM Include=\"KEYFBUFF.ASM\">\n      <Filter>Source Files</Filter>\n    </MASM>\n    <MASM Include=\"TXTPRNT.ASM\">\n      <Filter>Source Files</Filter>\n    </MASM>\n    <MASM Include=\"MMX.ASM\">\n      <Filter>Source Files</Filter>\n    </MASM>\n    <MASM Include=\"Win32Lib\\LCWCOMP.ASM\">\n      <Filter>Source Files\\win32lib</Filter>\n    </MASM>\n    <MASM Include=\"LCWCOMP.ASM\">\n      <Filter>Source Files</Filter>\n    </MASM>\n    <MASM Include=\"Win32Lib\\TOBUFF.ASM\">\n      <Filter>Source Files\\win32lib</Filter>\n    </MASM>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"Resource\\RedAlert.rc\">\n      <Filter>Source Files\\Resource</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "REDALERT/SAVEDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SAVEDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SAVEDLG.H                                                    *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  * \n *                                                                                             *\n *                  Last Update : Jan 18, 1995   [MML]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SAVEDLG_H\n#define SAVEDLG_H\n\n#include \"gadget.h\"\n\nclass SaveOptionsClass \n{\n\tprivate:\n\n\t\tenum SaveOptionsClassEnums {\n\t\t\tBUTTON_CANCEL=200,\n\t\t\tBUTTON_SAVE,\n\t\t\tOPTION_WIDTH=216,\n\t\t\tOPTION_HEIGHT=122,\n\t\t\tOPTION_X=((320 - OPTION_WIDTH) / 2) & ~7,\n\t\t\tOPTION_Y=(200 - OPTION_HEIGHT) / 2,\n\t\t\tNUMBER_OF_BUTTONS=2,\n\t\t\tCAPTION_Y_POS=5,\n\t\t\tBORDER1_LEN=49,\n\t\t\tBUTTON_CANCEL_X=90,\n\t\t\tBUTTON_CANCEL_Y=103,\n\t\t\tLISTBOX_X=40,\n\t\t\tLISTBOX_Y=24,\n\t\t\tLISTBOX_W=136,\n\t\t\tLISTBOX_H=72\n\t\t};\n\n\tpublic:\n\t\tSaveOptionsClass (void) { };\n\t\tvoid Process (void);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/SAVELOAD.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/SAVELOAD.CPP 9     3/17/97 1:04a Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SAVELOAD.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 23, 1994                                              *\n *                                                                                             *\n *                  Last Update : July 8, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Code_All_Pointers -- Code all pointers.                                                   *\n *   Decode_All_Pointers -- Decodes all pointers.                                              *\n *   Get_Savefile_Info -- gets description, scenario #, house                                  *\n *   Load_Game -- loads a saved game                                                           *\n *   Load_MPlayer_Values -- Loads multiplayer-specific values                                  *\n *   Load_Misc_Values -- loads miscellaneous variables                                         *\n *   MPlayer_Save_Message -- pops up a \"saving...\" message                                     *\n *   Put_All -- Store all save game data to the pipe.                                          *\n *   Reconcile_Players -- Reconciles loaded data with the 'Players' vector\t\t\t\t\t\t\t  *\n *   Save_Game -- saves a game to disk                                                         *\n *   Save_MPlayer_Values -- Saves multiplayer-specific values                                  *\n *   Save_Misc_Values -- saves miscellaneous variables                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"vortex.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\n//#include \"WolDebug.h\"\n\nextern bool DLLSave(Pipe &file);\nextern bool DLLLoad(Straw &file);\n\nextern bool SpawnedFromWChat;\n#endif\n\n//#define\tSAVE_BLOCK_SIZE\t512\n#define\tSAVE_BLOCK_SIZE\t4096\n//#define\tSAVE_BLOCK_SIZE\t1024\n\n/*\n********************************** Defines **********************************\n*/\n#define\tSAVEGAME_VERSION\t\t(DESCRIP_MAX + \\\n\t\t\t\t\t\t\t\t\t\t0x01000006 + ( \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AircraftClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AircraftTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AnimClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(AnimTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BaseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BuildingClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BuildingTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BulletClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(BulletTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(CellClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(FactoryClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(HouseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(HouseTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(InfantryClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(InfantryTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(LayerClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(MouseClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(OverlayClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(OverlayTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(SmudgeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(SmudgeTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TeamClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TeamTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TemplateClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TemplateTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TerrainClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TerrainTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TriggerClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(TriggerTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(UnitClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(UnitTypeClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(VesselClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(ScenarioClass) + \\\n\t\t\t\t\t\t\t\t\t\tsizeof(ChronalVortexClass)))\n//\t\t\t\t\t\t\t\t\t\tsizeof(Waypoint)))\n\n\nstatic int Reconcile_Players(void);\nextern bool Is_Mission_Counterstrike (char *file_name);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * Put_All -- Store all save game data to the pipe.                                            *\n *                                                                                             *\n *    This is the bulk processor of the game related save game data. All the game object       *\n *    and state data is stored to the pipe specified.                                          *\n *                                                                                             *\n * INPUT:   pipe  -- Reference to the pipe that will receive the save game data.               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nstatic void Put_All(Pipe & pipe, int save_net)\n{\n\t/*\n\t**\tSave the scenario global information.\n\t*/\n\tpipe.Put(&Scen, sizeof(Scen));\n\n\t/*\n\t**\tSave the map.  The map must be saved first, since it saves the Theater.\n\t*/\n\tif (!save_net) Call_Back();\n\tMap.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave all game objects.  This code saves every object that's stored in a\n\t**\tTFixedIHeap class.\n\t*/\n\tHouses.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTeamTypes.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTeams.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTriggerTypes.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTriggers.Save(pipe);\n\tif (!save_net) Call_Back();\n\tAircraft.Save(pipe);\n\tif (!save_net) Call_Back();\n\tAnims.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\tBuildings.Save(pipe);\n\tif (!save_net) Call_Back();\n\tBullets.Save(pipe);\n\tif (!save_net) Call_Back();\n\tInfantry.Save(pipe);\n\tif (!save_net) Call_Back();\n\tOverlays.Save(pipe);\n\tif (!save_net) Call_Back();\n\tSmudges.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTemplates.Save(pipe);\n\tif (!save_net) Call_Back();\n\tTerrains.Save(pipe);\n\tif (!save_net) Call_Back();\n\tUnits.Save(pipe);\n\tif (!save_net) Call_Back();\n\tFactories.Save(pipe);\n\tif (!save_net) Call_Back();\n\tVessels.Save(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the Logic & Map layers\n\t*/\n\tLogic.Save(pipe);\n\n\tint count = MapTriggers.Count();\n\tpipe.Put(&count, sizeof(count));\n\tint index;\n\tfor (int index = 0; index < MapTriggers.Count(); index++) {\n\t\tTARGET target = MapTriggers[index]->As_Target();\n\t\tpipe.Put(&target, sizeof(target));\n\t}\n\tif (!save_net) Call_Back();\n\tcount = LogicTriggers.Count();\n\tpipe.Put(&count, sizeof(count));\n\tfor (index = 0; index < LogicTriggers.Count(); index++) {\n\t\tTARGET target = LogicTriggers[index]->As_Target();\n\t\tpipe.Put(&target, sizeof(target));\n\t}\n\tif (!save_net) Call_Back();\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tcount = HouseTriggers[h].Count();\n\t\tpipe.Put(&count, sizeof(count));\n\t\tfor (index = 0; index < HouseTriggers[h].Count(); index++) {\n\t\t\tTARGET target = HouseTriggers[h][index]->As_Target();\n\t\t\tpipe.Put(&target, sizeof(target));\n\t\t}\n\t}\n\tif (!save_net) Call_Back();\n\n\tfor (int i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Save(pipe);\n\t}\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the Score\n\t*/\n\tpipe.Put(&Score, sizeof(Score));\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave the AI Base\n\t*/\n\tBase.Save(pipe);\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave out the carry over list (if present). First see how\n\t**\tmany carry over objects are in the list.\n\t*/\n\tint carry_count = 0;\n\tCarryoverClass const * cptr = Carryover;\n\twhile (cptr != NULL) {\n\t\tcarry_count++;\n\t\tcptr = (CarryoverClass const *)cptr->Get_Next();\n\t}\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave out the number of objects in the list.\n\t*/\n\tpipe.Put(&carry_count, sizeof(carry_count));\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tNow write out the objects themselves.\n\t*/\n\tCarryoverClass const * object_to_write = Carryover;\n\twhile (object_to_write != NULL) {\n\t\tpipe.Put(object_to_write, sizeof(*object_to_write));\n\t\tobject_to_write = (CarryoverClass const *)object_to_write->Get_Next();\n\t}\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave miscellaneous variables.\n\t*/\n\tSave_Misc_Values(pipe);\n\n\tif (!save_net) Call_Back();\n\n\t/*\n\t**\tSave multiplayer values\n\t*/\n\tpipe.Put(&save_net, sizeof(save_net));\t\t// Write out whether we saved the net values so we know if we have to load them again. ST - 10/22/2019 2:10PM\n\tif (save_net) {\n\t\tSave_MPlayer_Values(pipe);\n\t}\n\n\tpipe.Flush();\n}\n\n\n/***************************************************************************\n * Save_Game -- saves a game to disk                                       *\n *                                                                         *\n * Saving the Map:                                                         *\n *     DisplayClass::Save() invokes CellClass's Write() for every cell     *\n *     that needs to be saved.  A cell needs to be saved if it contains    *\n *     any special data at all, such as a TIcon, or an Occupier.           *\n *   The cell saves its own CellTrigger pointer, converted to a TARGET.    *\n *                                                                         *\n * Saving game objects:                                                    *\n *   - Any object stored in an ArrayOf class needs to be saved.  The ArrayOf*\n *     Save() routine invokes each object's Write() routine, if that       *\n *     object's IsActive is set.                                           *\n *                                                                         *\n * Saving the layers:                                                      *\n *   The Map's Layers (Ground, Air, etc) of things that are on the map,    *\n *     and the Logic's Layer of things to process both need to be saved.   *\n *     LayerClass::Save() writes the entire layer array to disk            *\n *                                                                         *\n * Saving the houses:                                                      *\n *   Each house needs to be saved, to record its Credits, Power, etc.      *\n *                                                                         *\n * Saving miscellaneous data:                                              *\n *   There are a lot of miscellaneous variables to save, such as the       *\n *     map's dimensions, the player's house, etc.                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      id      numerical ID, for the file extension                       *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/28/1994 BR : Created.                                              *\n *   02/27/1996 JLB : Uses simpler game control value save operation.      *\n *=========================================================================*/\nbool Save_Game(int id, char const * descr, bool )\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\n\t/*\n\t**\tGenerate the filename to save.  If 'id' is -1, it means save a\n\t** network/modem game; otherwise, use 'id' as the file extension.\n\t*/\n\tif (id==-1) {\n\t\tstrcpy(name, NET_SAVE_FILE_NAME);\n\t\t//save_net = 1;\n\t} else {\n\t\tsprintf(name, \"SAVEGAME.%03d\", id);\n\t}\n\n\treturn Save_Game(name, descr);\n}\n\n\n\n/*\n** Version that takes file name. ST - 9/9/2019 11:10AM\n*/\nbool NowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve\nbool Save_Game(const char *file_name, const char *descr)\n{\n\tNowSavingGame = true; // TEMP MBL: Need to discuss better solution with Steve\n\n\tint save_net = 0;\t\t\t\t\t\t\t\t\t// 1 = save network/modem game\n\t\n\tif (Session.Type  == GAME_GLYPHX_MULTIPLAYER) {\n\t\tsave_net = 1;\n\t}\n\t\n\tunsigned scenario;\n\tHousesType house;\n\n\tscenario = Scen.Scenario;\t\t\t\t\t\t// get current scenario #\n\thouse = PlayerPtr->Class->House;\t\t\t\t// get current house\n\n\t/*\n\t**\tCode everybody's pointers\n\t*/\n\tCode_All_Pointers();\n\n\t/*\n\t**\tOpen the file\n\t*/\n\tBufferIOFileClass file(file_name);\n\n\tFilePipe fpipe(&file);\n\n\t/*\n\t** Save the DLLs variables first, so we can do a version check in the DLL when we begin the load\n\t*/\n\tif (RunningAsDLL) {\n\t\tDLLSave(fpipe);\n\t}\n\n\t/*\n\t**\tSave the description, scenario #, and house\n\t**\t(scenario # & house are saved separately from the actual Scenario &\n\t**\tPlayerPtr globals for convenience; we can quickly find out which\n\t**\thouse & scenario this save-game file is for by reading these values.\n\t**\tAlso, PlayerPtr is stored in a coded form in Save_Misc_Values(),\n\t**\twhich may or may not be a HousesType number; so, saving 'house'\n\t**\there ensures we can always pull out the house for this file.)\n\t*/\n\tchar descr_buf[DESCRIP_MAX];\n\tmemset(descr_buf, '\\0', sizeof(descr_buf));\n\tsprintf(descr_buf, \"%s\\r\\n\", descr);\t\t\t// put CR-LF after text\n\t//descr_buf[strlen(descr_buf) + 1] = 26;\t\t// put CTRL-Z after NULL\n\tfpipe.Put(descr_buf, DESCRIP_MAX);\n\n\tfpipe.Put(&scenario, sizeof(scenario));\n\n\tfpipe.Put(&house, sizeof(house));\n\n\t/*\n\t**\tSave the save-game version, for loading verification\n\t*/\n\tunsigned long version = SAVEGAME_VERSION;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tversion++;\n#endif\n\tfpipe.Put(&version, sizeof(version));\n\n\tint pos = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tStore a dummy message digest.\n\t*/\n\tchar digest[20];\n\tfpipe.Put(digest, sizeof(digest));\n\n\n\t/*\n\t**\tDump the save game data to the file. The data is compressed\n\t**\tand then encrypted. The message digest is calculated in the\n\t**\tprocess by using the data just as it is written to disk.\n\t*/\n\tSHAPipe sha;\n\tBlowPipe bpipe(BlowPipe::ENCRYPT);\n\tLZOPipe pipe(LZOPipe::COMPRESS, SAVE_BLOCK_SIZE);\n//\tLZWPipe pipe(LZWPipe::COMPRESS, SAVE_BLOCK_SIZE);\n//\tLCWPipe pipe(LCWPipe::COMPRESS, SAVE_BLOCK_SIZE);\n\tbpipe.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);\n\n\tsha.Put_To(fpipe);\n\tbpipe.Put_To(sha);\n\tpipe.Put_To(bpipe);\n\tPut_All(pipe, save_net);\n\n\t/*\n\t**\tOutput the real final message digest. This is the one that is of\n\t**\tthe data image as it exists on the disk.\n\t*/\n\tpipe.Flush();\n\tfile.Seek(pos, SEEK_SET);\n\tsha.Result(digest);\n\tfpipe.Put(digest, sizeof(digest));\n\n\tpipe.End();\n\n\tDecode_All_Pointers();\n\n\tNowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Load_Game -- loads a saved game                                         *\n *                                                                         *\n * This routine loads the data in the same way it was saved out.           *\n *                                                                         *\n * Loading the Map:                                                        *\n *   - DisplayClass::Load() invokes CellClass's Load() for every cell      *\n *     that was saved.                                                     *\n * - The cell loads its own CellTrigger pointer.                           *\n *                                                                         *\n * Loading game objects:                                                   *\n * - IHeap's Load() routine loads the # of objects stored, and loads       *\n *   each object.                                                          *\n * - Triggers: Add themselves to the HouseTriggers if they're associated   *\n *   with a house                                                          *\n *                                                                         *\n * Loading the layers:                                                     *\n *     LayerClass::Load() reads the entire layer array to disk             *\n *                                                                         *\n * Loading the houses:                                                     *\n *   Each house is loaded in its entirety.                                 *\n *                                                                         *\n * Loading miscellaneous data:                                             *\n *   There are a lot of miscellaneous variables to load, such as the       *\n *     map's dimensions, the player's house, etc.                          *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         numerical ID, for the file extension                    *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error                                           *\n *                                                                         *\n * WARNINGS:                                                               *\n *      If this routine returns false, the entire game will be in an       *\n *      unknown state, so the scenario will have to be re-initialized.     *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/28/1994 BR : Created. \t\t\t\t\t\t   \t\t\t\t\t\t\t\t*\n *   1/20/97  V.Grippi Added expansion CD check                            *\n *=========================================================================*/\nbool Load_Game(int id)\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\n\t/*\n\t**\tGenerate the filename to load.  If 'id' is -1, it means save a\n\t** network/modem game; otherwise, use 'id' as the file extension.\n\t*/\n\tif (id == -1) {\n\t\tstrcpy(name, NET_SAVE_FILE_NAME);\n\t\t//load_net = 1;\n\t} else {\n\t\tsprintf(name, \"SAVEGAME.%03d\", id);\n\t}\n\treturn Load_Game(name);\n}\n\n\n/*\n** Version that takes a file name instead. ST - 9/9/2019 11:13AM\n*/\nbool Load_Game(const char *file_name)\n{\t\t\n\tint i;\n\tunsigned scenario;\n\tHousesType house;\n\tchar descr_buf[DESCRIP_MAX];\n\tint load_net = 0;\t\t\t\t\t\t\t\t\t// 1 = save network/modem game\n\t\n\t/*\n\t**\tOpen the file\n\t*/\n\tRawFileClass file(file_name);\n\tif (!file.Is_Available()) {\n\t\treturn(false);\n\t}\n\n\tFileStraw fstraw(file);\n\n\tCall_Back();\n\n\t/*\n\t** Load the DLLs variables first, in case we need to do something different based on version\n\t*/\n\tif (RunningAsDLL) {\n\t\tDLLLoad(fstraw);\n\t}\n\n\t/*\n\t**\tRead & discard the save-game's header info\n\t*/\n\tif (fstraw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {\n\t\treturn(false);\n\t}\n\n\tif (fstraw.Get(&scenario, sizeof(scenario)) != sizeof(scenario)) {\n\t\treturn(false);\n\t}\n\n\tif (fstraw.Get(&house, sizeof(house)) != sizeof(house)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead in & verify the save-game ID code\n\t*/\n\tunsigned long version;\n\tif (fstraw.Get(&version, sizeof(version)) != sizeof(version)) {\n\t\treturn(false);\n\t}\n\tGameVersion = version;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (version != SAVEGAME_VERSION && ((version-1) != SAVEGAME_VERSION) ) {\n\t      \treturn(false);\n\t}\n#else\n\tif (version != SAVEGAME_VERSION /*&& version != 0x0100616D*/){\n\t      \treturn(false);\n\t}\n#endif\n\t/*\n\t**\tGet the message digest that is embedded in the file.\n\t*/\n\tchar digest[20];\n\tfstraw.Get(digest, sizeof(digest));\n\n\t/*\n\t**\tRemember the file position since we must seek back here to\n\t**\tperform the real saved game read.\n\t*/\n\tlong pos = file.Seek(0, SEEK_CUR);\n\n\t/*\n\t**\tPass the rest of the file through the hash straw so that\n\t**\tthe digest can be compaired to the one in the file.\n\t*/\n\tSHAStraw sha;\n\tsha.Get_From(fstraw);\n\tfor (;;) {\n\t\tif (sha.Get(_staging_buffer, sizeof(_staging_buffer)) != sizeof(_staging_buffer)) break;\n\t}\n\tchar actual[20];\n\tsha.Result(actual);\n\tsha.Get_From(NULL);\n\n\tCall_Back();\n\n\t/*\n\t**\tCompare the two digests. If they differ then return a failure condition\n\t**\tbefore any damage could be done.\n\t*/\n\tif (memcmp(actual, digest, sizeof(digest)) != 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSet up the pipe so that the scenario data can be read.\n\t*/\n\tfile.Seek(pos, SEEK_SET);\n\tBlowStraw bstraw(BlowStraw::DECRYPT);\n\tLZOStraw straw(LZOStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n//\tLZWStraw straw(LZWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n//\tLCWStraw straw(LCWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);\n\n\tbstraw.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);\n\tbstraw.Get_From(fstraw);\n\tstraw.Get_From(bstraw);\n\n\t/*\n\t**\tClear the scenario so we start fresh; this calls the Init_Clear() routine\n\t**\tfor the Map, and all object arrays.  It has the following important\n\t**\teffects:\n\t**\t- Every cell is cleared to 0's, via MapClass::Init_Clear()\n\t**\t- All heap elements' are cleared\n\t**\t- The Houses are Initialized, which also clears their HouseTriggers\n\t**\t  array\n\t**\t- The map's Layers & Logic Layer are cleared to empty\n\t**\t- The list of currently-selected objects is cleared\n\t*/\n\tClear_Scenario();\n\n\t/*\n\t**\tLoad the scenario global information.\n\t*/\n\tstraw.Get(&Scen, sizeof(Scen));\n\n\t/*\n\t**\tFixup the Sessionclass scenario info so we can work out which\n\t** CD to request later\n\t*/\n\tif ( load_net ){\n\n\t\tCCFileClass scenario_file (Scen.ScenarioName);\n\t\tif ( !scenario_file.Is_Available() ){\n\n\t\t\tint cd = -1;\n\t\t\tif (Is_Mission_Counterstrike (Scen.ScenarioName)) {\n\t\t\t\tcd = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif (Expansion_AM_Present()) {\n\t\t\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\t\t\tint index = Get_CD_Index(current_drive, 1*60);\n\t\t\t\t\tif (index == 3) cd = 3;\n\t\t\t\t}\n#endif\n\t\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\tif (Is_Mission_Aftermath (Scen.ScenarioName)) {\n\t\t\t\tcd = 3;\n#ifdef BOGUSCD\n\tcd = -1;\n#endif\n\t\t\t}\n#endif\n\t\t\tRequiredCD = cd;\n\t\t\tif (!Force_CD_Available (RequiredCD)) {\n\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** Update the internal list of scenarios to include the counterstrike\n\t\t\t** list.\n\t\t\t*/\n\t\t\tSession.Read_Scenario_Descriptions();\n\t\t} else {\n\t\t\t/*\n\t\t\t** The scenario is available so set RequiredCD to whatever is currently\n\t\t\t** in the drive.\n\t\t\t*/\n\t\t\tint current_drive = CCFileClass::Get_CD_Drive();\n\t\t\tRequiredCD = Get_CD_Index(current_drive, 1*60);\n\t\t}\n\t}\n\n\t/*\n\t**\tLoad the map.  The map comes first, since it loads the Theater & init's\n\t**\tmixfiles.  The map calls all the type-class's Init routines, telling them\n\t**\twhat the Theater is; this must be done before any objects are created, so\n\t**\tthey'll be properly created.\n\t*/\n\tMap.Load(straw);\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad the object data.\n\t*/\n\tHouses.Load(straw);\n\tTeamTypes.Load(straw);\n\tTeams.Load(straw);\n\tTriggerTypes.Load(straw);\n\tTriggers.Load(straw);\n\tAircraft.Load(straw);\n\tAnims.Load(straw);\n\tBuildings.Load(straw);\n\tBullets.Load(straw);\n\n\tCall_Back();\n\n\tInfantry.Load(straw);\n\tOverlays.Load(straw);\n\tSmudges.Load(straw);\n\tTemplates.Load(straw);\n\tTerrains.Load(straw);\n\tUnits.Load(straw);\n\tFactories.Load(straw);\n\tVessels.Load(straw);\n\n\t/*\n\t**\tLoad the Logic & Map Layers\n\t*/\n\tLogic.Load(straw);\n\n\tint count;\n\tstraw.Get(&count, sizeof(count));\n\tMapTriggers.Clear();\n\tint index;\n\tfor (index = 0; index < count; index++) {\n\t\tTARGET target;\n\t\tstraw.Get(&target, sizeof(target));\n\t\tMapTriggers.Add(As_Trigger(target));\n\t}\n\n\tstraw.Get(&count, sizeof(count));\n\tLogicTriggers.Clear();\n\tfor (index = 0; index < count; index++) {\n\t\tTARGET target;\n\t\tstraw.Get(&target, sizeof(target));\n\t\tLogicTriggers.Add(As_Trigger(target));\n\t}\n\n\tfor (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {\n\t\tstraw.Get(&count, sizeof(count));\n\t\tHouseTriggers[h].Clear();\n\t\tfor (index = 0; index < count; index++) {\n\t\t\tTARGET target;\n\t\t\tstraw.Get(&target, sizeof(target));\n\t\t\tHouseTriggers[h].Add(As_Trigger(target));\n\t\t}\n\t}\n\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Load(straw);\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad the Score\n\t*/\n\tstraw.Get(&Score, sizeof(Score));\n\tnew(&Score) ScoreClass(NoInitClass());\n\n\t/*\n\t**\tLoad the AI Base\n\t*/\n\tBase.Load(straw);\n\n\t/*\n\t**\tDelete any carryover pseudo-saved game list.\n\t*/\n\twhile (Carryover != NULL) {\n\t\tCarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();\n\t\tCarryover->Remove();\n\t\tdelete Carryover;\n\t\tCarryover = cptr;\n\t}\n\n\t/*\n\t**\tLoad any carryover pseudo-saved game list.\n\t*/\n\tint carry_count = 0;\n\tstraw.Get(&carry_count, sizeof(carry_count));\n\twhile (carry_count) {\n\t\tCarryoverClass * cptr = new CarryoverClass;\n\t\tassert(cptr != NULL);\n\n\t\tstraw.Get(cptr, sizeof(CarryoverClass));\n\t\tnew (cptr) CarryoverClass(NoInitClass());\n\t\tcptr->Zap();\n\n\t\tif (!Carryover) {\n\t\t\tCarryover = cptr;\n\t\t} else {\n\t\t\tcptr->Add_Tail(*Carryover);\n\t\t}\n\t\tcarry_count--;\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tLoad miscellaneous variables, including the map size & the Theater\n\t*/\n\tLoad_Misc_Values(straw);\n\n\t/*\n\t**\tLoad multiplayer values\n\t*/\n\tstraw.Get(&load_net, sizeof(load_net));\n\tif (load_net) {\n\t\tLoad_MPlayer_Values(straw);\n\t}\n\n\tfile.Close();\n\tDecode_All_Pointers();\n\tMap.Init_IO();\n\tMap.Flag_To_Redraw(true);\n\n\t/*\n\t**\tFixup any expediency data that can be inferred from the physical\n\t**\tdata loaded.\n\t*/\n\tPost_Load_Game(load_net);\n\n\t/*\n\t** Re-init unit trackers. They will be garbage pointers after the load\n\t*/\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr && hptr->IsActive) {\n\t\t\thptr->Init_Unit_Trackers();\n\t\t}\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tSet the required CD to be in the drive according to the scenario\n\t**\tloaded.\n\t*/\n\tif (RequiredCD != -2 && !load_net) {\n\n#ifdef FIXIT_ANTS\n\t\t/*\n\t\t**\tDetermines if this an ant mission. Since the ant mission looks no different from\n\t\t**\ta regular mission, examining of the scenario name is the only way to tell.\n\t\t*/\n\t\tif (toupper(Scen.ScenarioName[0]) == 'S' &&\n\t\t\ttoupper(Scen.ScenarioName[1]) == 'C' &&\n\t\t\ttoupper(Scen.ScenarioName[2]) == 'A' &&\n\t\t\ttoupper(Scen.ScenarioName[3]) == '0' &&\n\t\t\ttoupper(Scen.ScenarioName[5]) == 'E' &&\n\t\t\ttoupper(Scen.ScenarioName[6]) == 'A') {\n\n\t\t\tAntsEnabled = true;\n\t\t} else{\n\t\t\tAntsEnabled = false;\n\t\t}\n#endif\n\n\t\tif (Scen.Scenario == 1) {\n\t\t\tRequiredCD = -1;\n\t\t} else {\n#ifdef FIXIT_ANTS\n\t\t\tif (Scen.Scenario > 19 || AntsEnabled) {\n\t\t\t   RequiredCD = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tif(Scen.Scenario >= 36) {\n\t\t\t\t\tRequiredCD = 3;\n#ifdef BOGUSCD\n\tRequiredCD = -1;\n#endif\n\t\t\t\t}\n#endif\n\t\t\t} else {\n#endif\t//FIXIT_ANTS\n\t\t\t\tif (PlayerPtr->Class->House != HOUSE_USSR  && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\t\t\t\tRequiredCD = 0;\n\t\t\t\t} else {\n\t\t\t\t\tRequiredCD = 1;\n\t\t\t\t}\n#ifdef FIXIT_ANTS\n\t\t\t}\n#endif\t//FIXIT_ANTS\n\t\t}\n\n\t}else{\n\n\t\tif ( load_net ){\n\n\t\t\tCCFileClass scenario_file (Scen.ScenarioName);\n\n\t\t\t/*\n\t\t\t** Fix up the session class variables\n\t\t\t*/\n\t\t\tfor ( int s=0 ; s<Session.Scenarios.Count() ; s++ ) {\n\t\t\t\tif (Session.Scenarios[s]->Description() == Scen.Description){\n\n\t\t\t\t\tmemcpy (Session.Options.ScenarioDescription, Scen.Description,\n\t\t\t\t\t\t\t\tsizeof (Session.Options.ScenarioDescription));\n\t\t\t\t\tmemcpy (Session.ScenarioFileName, Scen.ScenarioName,\n\t\t\t\t\t\t\t\tsizeof (Session.ScenarioFileName));\n\t\t\t\t\tSession.ScenarioFileLength = scenario_file.Size();\n\t\t\t\t\tmemcpy (Session.ScenarioDigest, Session.Scenarios[s]->Get_Digest(),\n\t\t\t\t\t\t\t\tsizeof (Session.ScenarioDigest));\n\t\t\t\t\tSession.ScenarioIsOfficial = Session.Scenarios[s]->Get_Official();\n\t\t\t\t\tScen.Scenario = s;\n\t\t\t\t\tSession.Options.ScenarioIndex = s;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Force_CD_Available(RequiredCD)) {\n\t\tProg_End(\"Load_Game Force_CD_Available failed\", true);\n\t\tEmergency_Exit(EXIT_FAILURE);\n\t}\n\n\tScenarioInit = 0;\n\n\tif (load_net) {\n\n\t\t// Removed as this is ensured by the GlyphX & DLL save/load code. ST - 10/22/2019 5:20PM\n\t\t//if (!Reconcile_Players()) {\t// (must do after Decode pointers)\n\t\t//\treturn(false);\n\t\t//}\n\t\t\n\t\t//!!!!!!!!!! put Fixup_Player_Units() here\n\t\tSession.LoadGame = true;\n\t}\n\n\tMap.Reload_Sidebar();\t// re-load sidebar art.\n\n\t/*\n\t**\tRescan the scenario file for any rules updates.\n\t*/\n\tCCINIClass ini;\n\tint result = ini.Load(CCFileClass(Scen.ScenarioName), true);\n\n\t/*\n\t**\tReset the rules values to their initial settings.\n\t*/\n\tRule.General(RuleINI);\n\tRule.Recharge(RuleINI);\n\tRule.AI(RuleINI);\n\tRule.Powerups(RuleINI);\n\tRule.Land_Types(RuleINI);\n\tRule.Themes(RuleINI);\n\tRule.IQ(RuleINI);\n\tRule.Objects(RuleINI);\n\tRule.Difficulty(RuleINI);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - But does this incorporate *changes*? - NO.\n\tRule.General(AftermathINI);\n\tRule.Recharge(AftermathINI);\n\tRule.AI(AftermathINI);\n\tRule.Powerups(AftermathINI);\n\tRule.Land_Types(AftermathINI);\n\tRule.Themes(AftermathINI);\n\tRule.IQ(AftermathINI);\n\tRule.Objects(AftermathINI);\n\tRule.Difficulty(AftermathINI);\n#endif\n\n\t/*\n\t**\tOverride any rules values specified in this\n\t**\tparticular scenario file.\n\t*/\n\tRule.General(ini);\n\tRule.Recharge(ini);\n\tRule.AI(ini);\n\tRule.Powerups(ini);\n\tRule.Land_Types(ini);                               \\\n\tRule.Themes(ini);\n\tRule.IQ(ini);\n\tRule.Objects(ini);\n\tRule.Difficulty(ini);\n#ifdef FIXIT_CSII\t//\tajw - Added runtime check for Aftermath to skirmish mode.\n\tif (load_net) {\n\t\tbool readini = false;\n\t\tswitch(Session.Type) {\n\t\t\tcase GAME_NORMAL:\n\t\t\t\treadini = false;\n\t\t\t\tbreak;\n\t\t\tcase GAME_SKIRMISH:\n\t\t\t\treadini = Is_Aftermath_Installed();\n\t\t\t\tbreak;\n\t\t\tdefault:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#else\n\t\t\t\tif (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {\n\t\t\t\t\treadini = true;\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t\tif(readini) {\n\t\t\t/*\n\t\t\t** Find out if the CD in the current drive is the Aftermath disc.\n\t\t  \t*/\n\t\t\tif(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {\n\t\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t\t\tif (!Force_CD_Available(3)) {\t// force Aftermath CD in drive.\n\t\t\t\t\tProg_End(\"Load_Game Force_CD_Available(3) failed\", true);\n#ifndef FIXIT_VERSION_3\t\t\t//\tWChat eliminated.\n#ifdef WIN32\nif(Special.IsFromWChat || SpawnedFromWChat) {\n\tchar packet[10] = {\"Hello\"};\n\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n}\n#endif\n#endif\n\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t     \t}\n\t\t\t}\n\t\t\tCCINIClass mpini;\n\t\t\tif (mpini.Load(CCFileClass(\"MPLAYER.INI\"), false)) {\n\t\t\t\tRule.General(mpini);\n\t\t\t\tRule.Recharge(mpini);\n\t\t\t\tRule.AI(mpini);\n\t\t\t\tRule.Powerups(mpini);\n\t\t\t\tRule.Land_Types(mpini);\n\t\t\t\tRule.Themes(mpini);\n\t\t\t\tRule.IQ(mpini);\n\t\t\t\tRule.Objects(mpini);\n\t\t\t\tRule.Difficulty(mpini);\n\t\t\t}\n\t\t}\n\n\t}\n#endif\n\n\tif (Scen.TransitTheme == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_FIRST);\n\t} else {\n\t\tTheme.Queue_Song(Scen.TransitTheme);\n\t}\n\t\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\tRule.IsSmartDefense = true;\n\t}\n\t\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Save_Misc_Values -- saves miscellaneous variables                       *\n *                                                                         *\n * INPUT:                                                                  *\n *      file      file to use for writing                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = success, false = failure                                    *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   12/29/1994 BR : Created.                                              *\n *   03/12/1996 JLB : Simplified.                                          *\n *=========================================================================*/\nbool Save_Misc_Values(Pipe & file)\n{\n\tint i, j;\n\tint count;\t\t\t\t\t\t\t\t// # ptrs in 'CurrentObject'\n\tObjectClass * ptr;\t\t\t\t\t// for saving 'CurrentObject' ptrs\n\n\t/*\n\t**\tPlayer's House.\n\t*/\n\tint x = PlayerPtr->Class->House;\n\tfile.Put(&x, sizeof(x));\n\n\t/*\n\t**\tSave frame #.\n\t*/\n\tfile.Put(&Frame, sizeof(Frame));\n\n\t/*\n\t**\tSave currently-selected objects list.\n\t**\tSave the # of ptrs in the list.\n\t*/\n\tfor (i = 0; i < SelectedObjectsType::COUNT; i++) {\n\t\tDynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);\n\t\tcount = selection.Count();\n\t\tfile.Put(&count, sizeof(count));\n\n\t\t/*\n\t\t**\tSave the pointers.\n\t\t*/\n\t\tfor (j = 0; j < count; j++) {\n\t\t\tptr = selection[j];\n\t\t\tfile.Put(&ptr, sizeof(ptr));\n\t\t}\n\t}\n\n\t/*\n\t** Save the chronal vortex\n\t*/\n\tChronalVortex.Save(file);\n\n\t/*\n\t**\tSave Tanya flags.\n\t*/\n\tfile.Put(&IsTanyaDead, sizeof(IsTanyaDead));\n\tfile.Put(&SaveTanya, sizeof(SaveTanya));\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Load_Misc_Values -- Loads miscellaneous variables.                                          *\n *                                                                                             *\n * INPUT:   file  -- The file to load the misc values from.                                    *\n *                                                                                             *\n * OUTPUT:  Was the misc load process successful?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *   03/12/1996 JLB : Simplified.                                                              *\n *=============================================================================================*/\nbool Load_Misc_Values(Straw & file)\n{\n\tObjectClass * ptr;\t\t\t\t\t// for loading 'CurrentObject' ptrs\n\n\t/*\n\t**\tPlayer's House.\n\t*/\n\tint x;\n\tfile.Get(&x, sizeof(x));\n//\tfile.Get(&PlayerPtr, sizeof(PlayerPtr));\n\tPlayerPtr = HouseClass::As_Pointer((HousesType)x);\n\n\t/*\n\t**\tLoad frame #.\n\t*/\n\tfile.Get(&Frame, sizeof(Frame));\n\n\tfor (int i = 0; i < SelectedObjectsType::COUNT; i++) {\n\t\t/*\n\t\t**\tLoad currently-selected objects list.\n\t\t**\tLoad the # of ptrs in the list.\n\t\t*/\n\t\tDynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);\n\t\tint count;\t\t\t\t\t\t\t\t// # ptrs in 'CurrentObject'\n\t\tfile.Get(&count, sizeof(count));\n\n\t\t/*\n\t\t**\tLoad the pointers.\n\t\t*/\n\t\tfor (int j = 0; j < count; j++) {\n\t\t\tfile.Get(&ptr, sizeof(ptr));\n\t\t\tselection.Add(ptr);\t// add to the list\n\t\t}\n\t}\n\n\t/*\n\t** Load the chronal vortex\n\t*/\n\tChronalVortex.Load(file);\n\n\t/*\n\t**\tSave Tanya flags.\n\t*/\n\tfile.Get(&IsTanyaDead, sizeof(IsTanyaDead));\n\tfile.Get(&SaveTanya, sizeof(SaveTanya));\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Save_MPlayer_Values -- Saves multiplayer-specific values                *\n *                                                                         *\n * This routine saves multiplayer values that need to be restored for a\t\t*\n * save game.  In addition to saving the random # seed for this scenario, \t*\n * it saves the contents of the actual random number generator; this \t\t*\n * ensures that the random # sequencer will pick up where it left off when\t*\n * the game was saved.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * This routine also saves the header for a Recording file, so it must \t\t*\n * save some data not needed specifically by a save-game file (ie Seed).\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Save_MPlayer_Values(Pipe & file)\n{\n\tSession.Save(file);\n\tfile.Put(&BuildLevel, sizeof(BuildLevel));\n\tfile.Put(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Put(&Seed, sizeof(Seed));\n\tfile.Put(&Whom, sizeof(Whom));\n\tfile.Put(&Special, sizeof(SpecialClass));\n\tfile.Put(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n\n/***************************************************************************\n * Load_MPlayer_Values -- Loads multiplayer-specific values                *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = success, false = failure\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/28/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool Load_MPlayer_Values(Straw & file)\n{\n\tSession.Load(file);\n\tfile.Get(&BuildLevel, sizeof(BuildLevel));\n\tfile.Get(&Debug_Unshroud, sizeof(Debug_Unshroud));\n\tfile.Get(&Seed, sizeof(Seed));\n\tfile.Get(&Whom, sizeof(Whom));\n\tfile.Get(&Special, sizeof(SpecialClass));\n\tfile.Get(&Options, sizeof(GameOptionsClass));\n\n\treturn (true);\n}\n\n/*\n** ST - 9/26/2019 11:43AM\n*/\nextern void DLL_Code_Pointers(void);\nextern void DLL_Decode_Pointers(void);\n\n/***********************************************************************************************\n * Code_All_Pointers -- Code all pointers.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid Code_All_Pointers(void)\n{\n\tint i, j;\n\n\t/*\n\t**\tThe Map.\n\t*/\n\tMap.Code_Pointers();\n\n\t/*\n\t**\tThe ArrayOf's.\n\t*/\n\tTeamTypes.Code_Pointers();\n\tTeams.Code_Pointers();\n\tTriggers.Code_Pointers();\n\tAircraft.Code_Pointers();\n\tAnims.Code_Pointers();\n\tBuildings.Code_Pointers();\n\tBullets.Code_Pointers();\n\tInfantry.Code_Pointers();\n\tOverlays.Code_Pointers();\n\tSmudges.Code_Pointers();\n\tTemplates.Code_Pointers();\n\tTerrains.Code_Pointers();\n\tUnits.Code_Pointers();\n\tFactories.Code_Pointers();\n\tVessels.Code_Pointers();\n\n\t/*\n\t**\tThe Layers.\n\t*/\n\tLogic.Code_Pointers();\n\tfor (i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Code_Pointers();\n\t}\n\n\t/*\n\t**\tThe Score.\n\t*/\n\tScore.Code_Pointers();\n\n\t/*\n\t**\tThe Base.\n\t*/\n\tBase.Code_Pointers();\n\n\t/*\n\t**\tPlayerPtr.\n\t*/\n//\tPlayerPtr = (HouseClass *)(PlayerPtr->Class->House);\n\n\t/*\n\t**\tCurrently-selected objects.\n\t*/\n\tfor (i = 0; i < SelectedObjectsType::COUNT; i++) {\n\t\tDynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);\n\t\tfor (j = 0; j < selection.Count(); j++) {\n\t\t\tselection[j] = (ObjectClass *)selection[j]->As_Target();\n\t\t}\n\t}\n\n\t/*\n\t** DLL data\n\t*/\n\tDLL_Code_Pointers();\n\n\t/*\n\t** Houses must be coded last, because the Class->House member of the HouseClass\n\t** is used to code HouseClass pointers for all other objects, and if Class is\n\t** coded, it will point to a meaningless value.\n\t*/\n\tHouses.Code_Pointers();\n}\n\n\n/***********************************************************************************************\n * Decode_All_Pointers -- Decodes all pointers.                                                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/24/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nvoid Decode_All_Pointers(void)\n{\n\t/*\n\t**\tThe Map.\n\t*/\n\tMap.Decode_Pointers();\n\n\t/*\n\t** Decode houses first, so we can properly decode all other objects'\n\t** House pointers\n\t*/\n\tHouses.Decode_Pointers();\n\n\t/*\n\t** DLL data\n\t*/\n\tDLL_Decode_Pointers();\n\n\t/*\n\t**\tThe ArrayOf's.\n\t*/\n\tTeamTypes.Decode_Pointers();\n\tTeams.Decode_Pointers();\n\tTriggers.Decode_Pointers();\n\tAircraft.Decode_Pointers();\n\tAnims.Decode_Pointers();\n\tBuildings.Decode_Pointers();\n\tBullets.Decode_Pointers();\n\tInfantry.Decode_Pointers();\n\tOverlays.Decode_Pointers();\n\tSmudges.Decode_Pointers();\n\tTemplates.Decode_Pointers();\n\tTerrains.Decode_Pointers();\n\tUnits.Decode_Pointers();\n\tFactories.Decode_Pointers();\n\tVessels.Decode_Pointers();\n\n\t/*\n\t**\tThe Layers.\n\t*/\n\tLogic.Decode_Pointers();\n\tfor (int i = 0; i < LAYER_COUNT; i++) {\n\t\tMap.Layer[i].Decode_Pointers();\n\t}\n\n\t/*\n\t**\tThe Score.\n\t*/\n\tScore.Decode_Pointers();\n\n\t/*\n\t**\tThe Base.\n\t*/\n\tBase.Decode_Pointers();\n\n\t/*\n\t**\tPlayerPtr.\n\t*/\n//\tPlayerPtr = HouseClass::As_Pointer((HousesType)PlayerPtr);\n\tWhom = PlayerPtr->Class->House;\n\tassert(PlayerPtr != NULL);\n\n\t/*\n\t**\tCurrently-selected objects.\n\t*/\n\tfor (int index = 0; index < SelectedObjectsType::COUNT; index++) {\n\t\tDynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(index);\n\t\tfor (int j = 0; j < selection.Count(); j++) {\n\t\t\tselection[j] = As_Object((TARGET)selection[j]);\n\t\t\tassert(selection[j] != NULL);\n\t\t}\n\t}\n\n\t/*\n\t**\tLast-Minute Fixups; to resolve these pointers properly requires all other\n\t**\tpointers to be loaded & decoded.\n\t*/\n\tif (Map.PendingObjectPtr) {\n\t\tMap.PendingObject = &Map.PendingObjectPtr->Class_Of();\n\t\tassert(Map.PendingObject != NULL);\n\t\tMap.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));\n#ifdef BG\n\t\tMap.Set_Placement_List(Map.PendingObject->Placement_List(true));\n#endif\n\t} else {\n\t\tMap.PendingObject = 0;\n\t\tMap.Set_Cursor_Shape(0);\n\t}\n}\n\n\n/***************************************************************************\n * Get_Savefile_Info -- gets description, scenario #, house                *\n *                                                                         *\n * INPUT:                                                                  *\n *      id         numerical ID, for the file extension                    *\n *      buf      buffer to store description in                            *\n *      scenp      ptr to variable to hold scenario                        *\n *      housep   ptr to variable to hold house                             *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      true = OK, false = error (save-game file invalid)                  *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   01/12/1995 BR : Created.                                              *\n *=========================================================================*/\nbool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep)\n{\n\tchar name[_MAX_FNAME+_MAX_EXT];\n\tunsigned long version;\n\tchar descr_buf[DESCRIP_MAX];\n\n\t/*\n\t**\tGenerate the filename to load\n\t*/\n\tsprintf(name, \"SAVEGAME.%03d\", id);\n\tBufferIOFileClass file(name);\n\n\tFileStraw straw(file);\n\n\t/*\n\t**\tRead in the description, scenario #, and the house\n\t*/\n\tif (straw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {\n\t\treturn(false);\n\t}\n\n\tdescr_buf[strlen(descr_buf) - 2] = '\\0';\t// trim off CR/LF\n\tstrcpy(buf, descr_buf);\n\n\tif (straw.Get(scenp, sizeof(unsigned)) != sizeof(unsigned)) {\n\t\treturn(false);\n\t}\n\n\tif (straw.Get(housep, sizeof(HousesType)) != sizeof(HousesType)) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tRead & verify the save-game version #\n\t*/\n\tif (straw.Get(&version, sizeof(version)) != sizeof(version)) {\n\t\treturn(false);\n\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tif (version != SAVEGAME_VERSION && ((version-1 != SAVEGAME_VERSION)) ) {\n#else\n\tif (version != SAVEGAME_VERSION) {\n#endif\n\t\treturn(false);\n\t}\n\treturn(true);\n}\n\n\n/***************************************************************************\n * Reconcile_Players -- Reconciles loaded data with the 'Players' vector\t*\n *                                                                         *\n * This function is for supporting loading a saved multiplayer game.  \t\t*\n * When the game is loaded, we have to figure out which house goes with\t\t*\n * which entry in the Players vector.  We also have to figure out if \t\t*\n * everyone who was originally in the game is still with us, and if not, \t*\n * turn their stuff over to the computer.\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * So, this function does the following:\t\t\t\t\t\t\t\t\t\t\t\t*\n * - For every name in 'Players', makes sure that name is in the House\t\t*\n *   array; if not, it's a fatal error.\t\t\t\t\t\t\t\t\t\t\t\t*\n * - For every human-controlled house, makes sure there's a player\t \t\t*\n *   with that name; if not, it turns that house over to the computer.\t\t*\n * - Fills in the Player's house ID\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * This assumes that each player MUST keep their name the same as it was\t*\n * when the game was saved!  It's also assumed that the network \t\t\t\t*\n * connections have not been formed yet, since Player[i]->Player.ID will\t*\n * be invalid until this routine has been called.\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\ttrue = OK, false = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   09/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nstatic int Reconcile_Players(void)\n{\n\tint i;\n\tint found;\n\tHousesType house;\n\tHouseClass * housep;\n\n\t/*\n\t**\tIf there are no players, there's nothing to do.\n\t*/\n\tif (Session.Players.Count()==0)\n\t\treturn (true);\n\n\t/*\n\t**\tMake sure every name we're connected to can be found in a House\n\t*/\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\tfound = 0;\n\t\tfor (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +\n\t\t\tSession.MaxPlayers; house++) {\n\n\t\t\thousep = HouseClass::As_Pointer(house);\n\t\t\tif (!housep) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!stricmp(Session.Players[i]->Name, housep->IniName)) {\n\t\t\t\tfound = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t\treturn (false);\n\t}\n\n\t//\n\t// Loop through all Houses; if we find a human-owned house that we're\n\t// not connected to, turn it over to the computer.\n\t//\n\tfor (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +\n\t\tSession.MaxPlayers; house++) {\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (!housep) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//\n\t\t// Skip this house if it wasn't human to start with.\n\t\t//\n\t\tif (!housep->IsHuman) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//\n\t\t// Try to find this name in the Players vector; if it's found, set\n\t\t// its ID to this house.\n\t\t//\n\t\tfound = 0;\n\t\tfor (i = 0; i < Session.Players.Count(); i++) {\n\t\t\tif (!stricmp(Session.Players[i]->Name, housep->IniName)) {\n\t\t\t\tfound = 1;\n\t\t\t\tSession.Players[i]->Player.ID = house;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tIf this name wasn't found, remove it\n\t\t*/\n\t\tif (!found) {\n\n\t\t\t/*\n\t\t\t**\tTurn the player's house over to the computer's AI\n\t\t\t*/\n\t\t\thousep->IsHuman = false;\n\t\t\thousep->IsStarted = true;\n//\t\t\thousep->Smartness = IQ_MENSA;\n\t\t\thousep->IQ = Rule.MaxIQ;\n\t\t\tstrcpy (housep->IniName, Text_String(TXT_COMPUTER));\n\n\t\t\tSession.NumPlayers--;\n\t\t}\n\t}\n\n\t//\n\t// If all went well, our Session.NumPlayers value should now equal the value\n\t// from the saved game, minus any players we removed.\n\t//\n\tif (Session.NumPlayers == Session.Players.Count()) {\n\t\treturn (true);\n\t} else {\n\t\treturn (false);\n\t}\n}\n\n\n/***************************************************************************\n * MPlayer_Save_Message -- pops up a \"saving...\" message                   *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   10/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid MPlayer_Save_Message(void)\n{\n\t//char *txt = Text_String(\n}"
  },
  {
    "path": "REDALERT/SCENARIO.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n//Mono_Printf(\"%d %s\\n\",__LINE__,__FILE__);\n/* $Header: /CounterStrike/SCENARIO.CPP 15    3/13/97 2:06p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCENARIO.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : October 21, 1996 [JLB]                                       *\n *                                                                                             *\n * This module handles the scenario reading and writing. Scenario related                      *\n * code that is executed between scenario play can also be here.                               *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Assign_Houses -- Assigns multiplayer houses to various players                            *\n *   Clear_Flag_Spots -- Clears flag overlays off the map                                      *\n *   Clear_Scenario -- Clears all data in preparation for scenario load.                       *\n *   Clip_Move -- moves in given direction from given cell; clips to map                       *\n *   Clip_Scatter -- randomly scatters from given cell; won't fall off map                     *\n *   Create_Units -- Creates infantry & units, for non-base multiplayer                        *\n *   Do_Lose -- Display losing comments.                                                       *\n *   Do_Restart -- Handle the restart mission process.                                         *\n *   Do_Win -- Display winning congratulations.                                                *\n *   Fill_In_Data -- Recreate all data that is not loaded with scenario.                       *\n *   Post_Load_Game -- Fill in an inferred data from the game state.                           *\n *   Read_Scenario -- Reads a scenario from disk.                                              *\n *   Read_Scenario_INI -- Read specified scenario INI file.                                    *\n *   Remove_AI_Players -- Removes the computer AI houses & their units                         *\n *   Restate_Mission -- Handles restating the mission objective.                               *\n *   Scan_Place_Object -- places an object >near< the given cell                               *\n *   ScenarioClass::ScenarioClass -- Constructor for the scenario control object.              *\n *   ScenarioClass::Set_Global_To -- Set scenario global to value specified.                   *\n *   Set_Scenario_Name -- Creates the INI scenario name string.                                *\n *   Start_Scenario -- Starts the scenario.                                                    *\n *   Write_Scenario_INI -- Write the scenario INI file.                                        *\n *   ScenarioClass::Do_BW_Fade -- Cause the palette to temporarily shift to B/W.               *\n *   ScenarioClass::Do_Fade_AI -- Process the palette fading effect.                           *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#ifdef WIN32\n#include \"tcpip.h\"\n#include \"ccdde.h\"\n\nextern bool SpawnedFromWChat;\n#endif\nextern int PreserveVQAScreen;\n\nvoid Display_Briefing_Text_GlyphX();\n\nextern void GlyphX_Assign_Houses(void);\t//ST - 8/8/2019 12:35PM\nextern bool UseGlyphXStartLocations;\t\t//ST - 3/31/2020 9:54AM\n\n//#include \"WolDebug.h\"\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n#include \"WolStrng.h\"\n#endif\n\nstatic void Remove_AI_Players(void);\nstatic void Create_Units(bool official);\nstatic CELL Clip_Scatter(CELL cell, int maxdist);\nstatic CELL Clip_Move(CELL cell, FacingType facing, int dist);\n\n// Made this non-static so we can access it from the updated assign players function. ST - 8/9/2019 10:35AM\nint _build_tech[11] = {\n\t2,2,\t\t\t// Tech level 0 and 1 are the same (tech 0 is never used).\n\t4,\n\t5,\n\t7,\n\t8,\n\t9,\n\t10,\n\t11,\n\t12,\n\t13\n};\n\n\n#ifdef FRENCH\n#define TXT_HACKHACK  \"Accomplie\"\n#endif\n#if defined(ENGLISH) || defined(GERMAN)\n#define TXT_HACKHACK  Text_String(TXT_ACCOMPLISHED)\n#endif\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_Counterstrike (char *file_name);\nbool Is_Mission_Aftermath (char *file_name);\n#endif\n\n/***********************************************************************************************\n * ScenarioClass::ScenarioClass -- Constructor for the scenario control object.                *\n *                                                                                             *\n *    This constructs the default scenario control object. Normally, all the default values    *\n *    are meaningless since the act of starting a scenario will fill in all of the values with *\n *    settings retrieved from the scenario control file.                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nScenarioClass::ScenarioClass(void) :\n\tDifficulty(DIFF_NORMAL),\n\tCDifficulty(DIFF_NORMAL),\n\tTimer(0),\n\tMissionTimer(0),\n\tShroudTimer(TICKS_PER_MINUTE * Rule.ShroudRate),\n\tScenario(1),\n\tTheater(THEATER_TEMPERATE),\n\tIntroMovie(VQ_NONE),\n\tBriefMovie(VQ_NONE),\n\tWinMovie(VQ_NONE),\n\tWinMovie2(VQ_NONE),\n\tWinMovie3(VQ_NONE),\n\tWinMovie4(VQ_NONE),\n\tLoseMovie(VQ_NONE),\n\tActionMovie(VQ_NONE),\n\tTransitTheme(THEME_NONE),\n\tPlayerHouse(HOUSE_GREECE),\n\tCarryOverPercent(0),\n\tCarryOverMoney(0),\n\tCarryOverCap(0),\n\tPercent(0),\n\tBridgeCount(0),\n\tCarryOverTimer(0),\n\tIsBridgeChanged(false),\n\tIsGlobalChanged(false),\n\tIsToCarryOver(false),\n\tIsToInherit(false),\n\tIsTanyaEvac(false),\n\tIsFadingBW(false),\n\tIsFadingColor(false),\n\tIsEndOfGame(false),\n\tIsInheritTimer(false),\n\tIsNoSpyPlane(false),\n\tIsSkipScore(false),\n\tIsOneTimeOnly(false),\n\tIsNoMapSel(false),\n\tIsTruckCrate(false),\n\tIsMoneyTiberium(false),\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n#define AUTOSONAR_PERIOD\tTICKS_PER_SECOND * 40\n\tAutoSonarTimer( AUTOSONAR_PERIOD ),\n#endif\n\tFadeTimer(0)\n{\n\tfor (int index = 0; index < ARRAY_SIZE(Waypoint); index++) {\n\t\tWaypoint[index] = -1;\n\t}\n\tstrcpy(Description, \"\");\n\tstrcpy(ScenarioName, \"\");\n\tstrcpy(BriefingText, \"\");\n\tmemset(GlobalFlags, '\\0', sizeof(GlobalFlags));\n\tmemset(Views, '\\0', sizeof(Views));\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Do_BW_Fade -- Cause the palette to temporarily shift to B/W.                 *\n *                                                                                             *\n *    This routine will start the palette to fade to B/W for a brief moment.                   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ScenarioClass::Do_BW_Fade(void)\n{\n\tIsFadingBW = true;\n\tIsFadingColor = false;\n\tFadeTimer = GRAYFADETIME;\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Do_Fade_AI -- Process the palette fading effect.                             *\n *                                                                                             *\n *    This routine will handle the maintenance of the palette fading effect. It should be      *\n *    called once per game frame.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/21/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ScenarioClass::Do_Fade_AI(void)\n{\n\tif (IsFadingColor) {\n\t\tif (FadeTimer == 0) {\n\t\t\tIsFadingColor = false;\n\t\t}\n\t\tfixed newsat = Options.Get_Saturation() * fixed(GRAYFADETIME-FadeTimer, GRAYFADETIME);\n\t\tOptions.Adjust_Palette(OriginalPalette, GamePalette, Options.Get_Brightness(), newsat, Options.Get_Tint(), Options.Get_Contrast());\n\t\tGamePalette.Set();\n\t}\n\tif (IsFadingBW) {\n\t\tif (FadeTimer == 0) {\n\t\t\tIsFadingBW = false;\n\t\t}\n\t\tfixed newsat = Options.Get_Saturation() * fixed(FadeTimer, GRAYFADETIME);\n\t\tOptions.Adjust_Palette(OriginalPalette, GamePalette, Options.Get_Brightness(), newsat, Options.Get_Tint(), Options.Get_Contrast());\n\t\tGamePalette.Set();\n\t\tif (!IsFadingBW) {\n\t\t\tIsFadingColor = true;\n\t\t\tFadeTimer = GRAYFADETIME;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * ScenarioClass::Set_Global_To -- Set scenario global to value specified.                     *\n *                                                                                             *\n *    This routine will set the global flag to the falue (true/false) specified. It will       *\n *    also scan for and spring any triggers that are dependant upon that global.               *\n *                                                                                             *\n * INPUT:   global   -- The global flag to change.                                             *\n *                                                                                             *\n *          value    -- The value to change the global flag to.                                *\n *                                                                                             *\n * OUTPUT:  Returns with the previous value of the flag.                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/26/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ScenarioClass::Set_Global_To(int global, bool value)\n{\n\tif ((unsigned)global < ARRAY_SIZE(Scen.GlobalFlags)) {\n\n\t\tbool previous = GlobalFlags[global];\n\t\tif (previous != value) {\n\t\t\tGlobalFlags[global] = value;\n\t\t\tIsGlobalChanged = true;\n\n\t\t\t/*\n\t\t\t**\tSpecial case to scan through all triggers and if any are found that depend on this\n\t\t\t**\tglobal being set/cleared, then if there is an elapsed time event associated, it\n\t\t\t**\twill be reset at this time.\n\t\t\t*/\n\t\t\tfor (int index = 0; index < Triggers.Count(); index++) {\n\t\t\t\tTriggerClass * tp = Triggers.Ptr(index);\n\t\t\t\tif ((tp->Class->Event1.Event == TEVENT_GLOBAL_SET || tp->Class->Event1.Event == TEVENT_GLOBAL_CLEAR) && tp->Class->Event1.Data.Value == global) {\n\t\t\t\t\ttp->Class->Event2.Reset(tp->Event1);\n\t\t\t\t}\n\t\t\t\tif ((tp->Class->Event2.Event == TEVENT_GLOBAL_SET || tp->Class->Event2.Event == TEVENT_GLOBAL_CLEAR) && tp->Class->Event2.Data.Value == global) {\n\t\t\t\t\ttp->Class->Event1.Reset(tp->Event1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn(previous);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Start_Scenario -- Starts the scenario.                                                      *\n *                                                                                             *\n *    This routine will start the scenario. In addition to loading the scenario data, it will  *\n *    play the briefing and action movies.                                                     *\n *                                                                                             *\n * INPUT:   root     -- Pointer to the filename root for this scenario (e.g., \"SCG01EA\").      *\n *                                                                                             *\n *          briefing -- Should the briefing be played? Normally this is true except when the   *\n *                      scenario is restarting.                                                *\n *                                                                                             *\n * OUTPUT:  Was the scenario started without error?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Start_Scenario(char * name, bool briefing)\n{\n//BG\tTheme.Queue_Song(THEME_QUIET);\nTheme.Stop();\n\tIsTanyaDead = SaveTanya;\n\tif (!Read_Scenario(name)) {\n\t\treturn(false);\n\t}\n\n\t/* Swap Lt. Blue and Blue color remaps in skirmish/multiplayer */\n\tif (Session.Type != GAME_NORMAL) {\n\t\tRemapControlType temp;\n\t\tmemcpy(&temp, &ColorRemaps[PCOLOR_LTBLUE], sizeof(RemapControlType));\n\t\tmemcpy(&ColorRemaps[PCOLOR_LTBLUE], &ColorRemaps[PCOLOR_BLUE], sizeof(RemapControlType));\n\t\tmemcpy(&ColorRemaps[PCOLOR_BLUE], &temp, sizeof(RemapControlType));\n\t}\n\n\t/*\n\t**\tPlay the winning movie and then start the next scenario.\n\t*/\n\tRequiredCD = -1;\n//\tif (RequiredCD != -2 && Session.Type == GAME_NORMAL) {\n//\t\tif (Scen.Scenario == 1)\n//\t\t\tRequiredCD = -1;\n//\t\telse {\n//\t\t\t if((Scen.Scenario >= 20 && Scen.ScenarioName[2] == 'G' || Scen.ScenarioName[2] == 'U') || Scen.ScenarioName[2] == 'A'\n//\t\t\t\t|| (Scen.ScenarioName[2] == 'M' && Scen.Scenario >= 25))\n//\t\t       \t    RequiredCD = 2;\n//\t\t\t else if(Scen.ScenarioName[2] == 'U')\n//\t\t\t    RequiredCD = 1;\n//\t\t\t else if(Scen.ScenarioName[2] == 'G')\n//\t\t\t    RequiredCD = 0;\n//\t\t\t}\n//\n//#ifdef FIXIT_FORCE_CD\n// Forces the CD to be inserted according to the scenario being loaded.\n//Hide_Mouse();\n//VisiblePage.Clear();\n//Show_Mouse();\n//GamePalette.Set();\n//if (!Force_CD_Available(RequiredCD)) {\n//       \tProg_End();\n//       \texit(EXIT_FAILURE);\n//}\n//#endif\n\n\n\n//   \t}\n\tTheme.Stop();\n\n\tif (briefing) {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(Scen.IntroMovie);\n\t\tPlay_Movie(Scen.BriefMovie);\n\t}\n\n\t/*\n\t** If there's no briefing movie, restate the mission at the beginning.\n\t*/\n#if 1 // 12/04/2019 - LLL\n\tif (Session.Type == GAME_NORMAL && Scen.BriefMovie == VQ_NONE) {\n\t\tDisplay_Briefing_Text_GlyphX();\n\t}\n#else\n\tchar buffer[25];\n\tif (Scen.BriefMovie != VQ_NONE) {\n\t\tsprintf(buffer, \"%s.VQA\", VQName[Scen.BriefMovie]);\n\t}\n\tif (Session.Type == GAME_NORMAL && Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available()) {\n\t\t/*\n\t\t** Make sure the mouse is visible before showing the restatement.\n\t\t*/\n\t\twhile(Get_Mouse_State()) {\n\t\t\tShow_Mouse();\n\t\t}\n\t\tRestate_Mission(Scen.ScenarioName, TXT_OK, TXT_NONE);\n\t}\n#endif\n\n\tif (briefing) {\n\t\tHide_Mouse();\n\t\tVisiblePage.Clear();\n\t\tShow_Mouse();\n\t\tPlay_Movie(Scen.ActionMovie, Scen.TransitTheme);\n\t}\n\n\tif (Scen.TransitTheme == THEME_NONE) {\n\t\tTheme.Queue_Song(THEME_FIRST);\n\t}\n\n\t/*\n\t** Set the options values, since the palette has been initialized by Read_Scenario\n\t*/\n\tOptions.Set();\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Set_Scenario_Difficulty -- Sets the difficulty of the scenario.                             *\n *                                                                                             *\n *    Updates the player's difficulty in single-player mode.                                   *\n *                                                                                             *\n * INPUT:   difficulty     -- Scenario difficulty                                              *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   Only works in single-player.                                                    *\n *             Must call Start_Scenario first to initialize the player.                        *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/02/2019 SKY : Created.                                                                 *\n *=============================================================================================*/\nvoid Set_Scenario_Difficulty(int difficulty)\n{\n\tif (Session.Type == GAME_NORMAL) {\n\t\tswitch (difficulty) {\n\t\t\tcase 0:\n\t\t\t\tPlayerPtr->Assign_Handicap(DIFF_EASY);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tPlayerPtr->Assign_Handicap(DIFF_NORMAL);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tPlayerPtr->Assign_Handicap(DIFF_HARD);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Read_Scenario -- Reads a scenario from disk.                                                *\n *                                                                                             *\n *    This will read a scenario from disk. Use this to begin a scenario.                       *\n *    It doesn't perform any rendering, it merely sets up the system                           *\n *    with the proper data. Setting of the right game state will start                         *\n *    the scenario running.                                                                    *\n *                                                                                             *\n * INPUT:   root     -- Scenario root filename                                                 *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   You must clear out the system variables before calling                          *\n *             this function. Use the Clear_Scenario() function.                               *\n *               It is assumed that Scenario is set to the current scenario number.            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1991     : Created.                                                                 *\n *   02/03/1992 JLB : Uses house identification.                                               *\n *=============================================================================================*/\nbool Read_Scenario(char * name)\n{\n\tBStart(BENCH_SCENARIO);\n\tClear_Scenario();\n\tScenarioInit++;\n\tif (Read_Scenario_INI(name)) {\n#ifdef FIXIT_CSII\t//\tajw - Added runtime check for Aftermath to skirmish mode case.\n\t\tbool readini = false;\n\t\tswitch(Session.Type) {\n\t\t\tcase GAME_NORMAL:\n\t\t\t\treadini = false;\n\t\t\t\tbreak;\n\t\t\tcase GAME_SKIRMISH:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#endif\n\t\t\t\tbreak;\n\t\t\tcase GAME_INTERNET:\n#ifndef FIXIT_VERSION_3\t\t\t//\tLoading of Aftermath rules depends on bAftermathMultiplayer now.\n\t\t\t\tif (Is_Mission_Counterstrike(name)) {\n\t\t\t\t\treadini = false;\t// Don't allow AM units on a CS map in WChat\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\t\t//\t( Note lack of break; )\n\t\t\tdefault:\n#ifdef FIXIT_VERSION_3\n\t\t\t\treadini = bAftermathMultiplayer;\n#else\n\t\t\t\tif (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {\n\t\t\t\t\treadini = true;\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t\tif(readini) {\n\t\t\t/*\n\t\t\t** Find out if the CD in the current drive is the Aftermath disc.\n\t\t  \t*/\n#ifdef FIXIT_VERSION_3\n\t\t\tint cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);\n\t\t\tif( !( Using_DVD() && cd_index == 5 ) && cd_index != 3 ) {\n#else\n\t\t\tif(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {\n#endif\n\t\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t\t\tRequiredCD = 3;\n\t\t\t\tif (!Force_CD_Available(RequiredCD)) {\t// force Aftermath CD in drive.\n#ifndef WOLAPI_INTEGRATION\n\t\t\t\t\t#ifdef WIN32\n\t\t\t\t\tif(Special.IsFromWChat || SpawnedFromWChat) {\n\t\t\t\t\t\tchar packet[10] = {\"Hello\"};\n\t\t\t\t\tSend_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n#endif\n\t\t\t\t\tif (!RunningAsDLL) {\t//PG\n\t\t\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t\t\t}\n\t\t     \t}\n\t\t\t}\n\t\t\tCCINIClass ini;\n\t\t\tif (ini.Load(CCFileClass(\"MPLAYER.INI\"), false)) {\n\t\t\t\tRule.General(ini);\n\t\t\t\tRule.Recharge(ini);\n\t\t\t\tRule.AI(ini);\n\t\t\t\tRule.Powerups(ini);\n\t\t\t\tRule.Land_Types(ini);\n\t\t\t\tRule.Themes(ini);\n\t\t\t\tRule.IQ(ini);\n\t\t\t\tRule.Objects(ini);\n\t\t\t\tRule.Difficulty(ini);\n\t\t\t}\n\t\t}\n#endif\n\t\tFill_In_Data();\n\t\tMap.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight);\n\t} else {\n\t\t\n#if (1)\n\t\tchar message[200];\n\t\tif (name) {\n\t\t\tsprintf(message, \"Failed to load scenario %s\", name);\n\t\t\tGlyphX_Debug_Print(message);\n\t\t} else {\n\t\t\tGlyphX_Debug_Print(\"Failed to load scenario\");\n\t\t}\n#else\t\t\n\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n//\t\tFade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);\n\t\tShow_Mouse();\n\t\tWWMessageBox().Process(TXT_UNABLE_READ_SCENARIO);\n\t\tHide_Mouse();\n#endif\n\t\t\n\t\tBEnd(BENCH_SCENARIO);\n\t\treturn(false);\n\t}\n\tScenarioInit--;\n\tBEnd(BENCH_SCENARIO);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Fill_In_Data -- Recreate all data that is not loaded with scenario.                         *\n *                                                                                             *\n *    This routine is called after the INI file for the scenario has been processed. It will   *\n *    infer the game state from the scenario INI data.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Fill_In_Data(void)\n{\n\t/*\n\t**\tThe basic scenario data load does not contain the full set of\n\t**\tgame data. We now must fill in the missing pieces.\n\t*/\n\tScenarioInit++;\n\tint index;\n\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\tBuildings.Ptr(index)->Update_Buildables();\n\t}\n\n\tMap.Flag_To_Redraw(true);\n\n\t/*\n\t**\tReset the movement zones according to the terrain passability.\n\t*/\n\tMap.Zone_Reset(MZONEF_ALL);\n\n\n#ifdef WIN32\n\t/*\n\t**\tSince the sidebar starts up activated, adjust the home start position so that\n\t**\tthe right edge of the map will still be visible.\n\t*/\n\tif (!Debug_Map) {\n\t\tMap.SidebarClass::Activate(1);\n//\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tScen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME];\n\t\t\tMap.Set_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR)));\n//\t\t}\n\t}\n#endif\n\n\t/*\n\t**\tHandle any data resetting that can be safely inferred from the actual\n\t**\tdata that has been loaded.\n\t*/\n\t/*\n\t**\tDistribute the trigger pointers to the appropriate working lists.\n\t*/\n\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\tTriggerTypeClass * tp = TriggerTypes.Ptr(index);\n\n\t\tassert(tp != NULL);\n\n\t\tif (tp->Attaches_To() & ATTACH_MAP) {\n\t\t\tMapTriggers.Add(Find_Or_Make(tp));\n\t\t}\n\t\tif (tp->Attaches_To() & ATTACH_GENERAL) {\n\t\t\tLogicTriggers.Add(Find_Or_Make(tp));\n\t\t}\n\t\tif (tp->Attaches_To() & ATTACH_HOUSE) {\n\t\t\tHouseTriggers[tp->House].Add(Find_Or_Make(tp));\n\t\t}\n\t}\n\n\tScenarioInit--;\n\n\t/*\n\t** Now go through and set all the cells ringing the map to be visible, so\n\t** we won't get the wall of shadow at the edge of the map.\n\t*/\n\tint x,y;\n\tfor (x = Map.MapCellX-1; x < ((Map.MapCellX + Map.MapCellWidth + 1)); x++) {\n\t\tMap[XY_Cell(x, Map.MapCellY-1)].IsVisible =\n\t\t\tMap[XY_Cell(x, Map.MapCellY-1)].IsMapped = true;\n\n\t\tMap[XY_Cell(x, Map.MapCellY+Map.MapCellHeight)].IsVisible =\n\t\t\tMap[XY_Cell(x, Map.MapCellY+Map.MapCellHeight)].IsMapped = true;\n\t}\n\tfor (y = Map.MapCellY; y < (Map.MapCellY + Map.MapCellHeight); y++) {\n\t\tMap[XY_Cell(Map.MapCellX-1, y)].IsVisible =\n\t\t\tMap[XY_Cell(Map.MapCellX-1, y)].IsMapped = true;\n\t\tMap[XY_Cell(Map.MapCellX+Map.MapCellWidth, y)].IsVisible =\n\t\t\tMap[XY_Cell(Map.MapCellX+Map.MapCellWidth, y)].IsMapped = true;\n\t}\n\n\t/*\n\t**\tIf inheriting from a previous scenario was indicated, then create the carry over\n\t**\tobjects at this time.\n\t*/\n\tif (Scen.IsToInherit) {\n\t\tCarryoverClass * cptr = Carryover;\n\t\twhile (cptr != NULL) {\n\t\t\tcptr->Create();\n\t\t\tcptr = (CarryoverClass *)cptr->Get_Next();\n\t\t}\n\t}\n\n\t/*\n\t**\tThe \"allow win\" action is a special case that is handled here. The total number\n\t**\tof triggers that have this action must be recorded.\n\t*/\n\tfor (index = 0; index < TriggerTypes.Count(); index++) {\n\t\tTriggerTypeClass * tp = TriggerTypes.Ptr(index);\n\t\tif (tp->Action1.Action == TACTION_ALLOWWIN ||\n\t\t\t(tp->ActionControl != MULTI_ONLY && tp->Action2.Action == TACTION_ALLOWWIN)) {\n\n\t\t\tHouseClass::As_Pointer(tp->House)->Blockage++;\n\t\t}\n\t}\n\n\t/*\n\t**\tMove available money to silos, if the scenario flag so indicates.\n\t*/\n\tif (Scen.IsMoneyTiberium) {\n\t\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\t\tif (hptr != NULL) {\n\t\t\t\tint tomove = hptr->Capacity - hptr->Tiberium;\n\t\t\t\thptr->Credits -= tomove;\n\t\t\t\thptr->Tiberium += tomove;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tCount all non-destroyed bridges on the map.\n\t*/\n\tScen.BridgeCount = Map.Intact_Bridge_Count();\n\n\tMap.All_To_Look(PlayerPtr, true);\n}\n\n\n/***********************************************************************************************\n * Post_Load_Game -- Fill in an inferred data from the game state.                             *\n *                                                                                             *\n *    This routine is typically called after a game has been loaded. Some working data lists   *\n *    can be rebuild from the game state. This working data is rebuilt rather than being       *\n *    stored with the game data file.                                                          *\n *                                                                                             *\n * INPUT:   load_multi -- true if we're loading a multiplayer game                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Although it is safe to call this routine whenever, it is only needed after a    *\n *             game load.                                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Post_Load_Game(int load_multi)\n{\n\tMap.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight);\n\t//\n\t// Do NOT call Overpass if we're loading a multiplayer game; it calls the\n\t// random # generator, which throws the games out of sync if they were\n\t// saved on different frame #'s.\n\t//\n\tif (!load_multi) {\n\t\tMap.Overpass();\n\t}\n\tScen.BridgeCount = Map.Intact_Bridge_Count();\n\tMap.Zone_Reset(MZONEF_ALL);\n}\n\n\n/***********************************************************************************************\n * Clear_Scenario -- Clears all data in preparation for scenario load.                         *\n *                                                                                             *\n *    This routine will clear out all data specific to a scenario in                           *\n *    preparation for a subsequent scenario data load. This will free                          *\n *    all units, animations, and icon maps.                                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/22/1991     : Created.                                                                 *\n *   03/21/1992 JLB : Changed buffer allocations, so changes memset code.                      *\n *   07/13/1995 JLB : End count down moved here.                                               *\n *=============================================================================================*/\nvoid Clear_Scenario(void)\n{\n// TCTCTC -- possibly just use in-place new of scenario object?\n\n\tScen.MissionTimer = 0;\n\tScen.MissionTimer.Stop();\n\tScen.Timer = 0;\n\tScen.ShroudTimer = 0;\n\tScen.IntroMovie = VQ_NONE;\n\tScen.BriefMovie = VQ_NONE;\n\tScen.WinMovie = VQ_NONE;\n\tScen.WinMovie2 = VQ_NONE;\n\tScen.WinMovie3 = VQ_NONE;\n\tScen.WinMovie4 = VQ_NONE;\n\tScen.LoseMovie = VQ_NONE;\n\tScen.ActionMovie = VQ_NONE;\n\tScen.IsNoSpyPlane = false;\n\tScen.IsTanyaEvac = false;\n\tScen.IsEndOfGame = false;\n\tScen.IsInheritTimer = false;\n\tScen.IsToCarryOver = false;\n\tScen.IsSkipScore = false;\n\tScen.IsOneTimeOnly = false;\n\tScen.IsTruckCrate = false;\n\tScen.IsMoneyTiberium = false;\n\tScen.IsNoMapSel = false;\n\tScen.CarryOverCap = 0;\n\tScen.CarryOverPercent = 0;\n\tScen.TransitTheme = THEME_NONE;\n\tScen.Percent = 0;\n\n\tmemset(Scen.GlobalFlags, 0, sizeof(Scen.GlobalFlags));\n\n\tMapTriggers.Clear();\n\tLogicTriggers.Clear();\n\n\tfor (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {\n\t\tHouseTriggers[house].Clear();\n\t}\n\n\t/*\n\t** Call everyone's Init routine, except the Map's; for the Map, only call\n\t** MapClass::Init, which clears the Cell array.  The Display::Init requires\n\t** a Theater argument, and the theater is not known at this point; also, it\n\t** would reload MixFiles, which isn't desired.  Display::Read_INI calls its\n\t** own Init, which will Init the entire Map hierarchy.\n\t*/\n\tMap.Init_Clear();\n\tScore.Init();\n\tLogic.Init();\n\n\tHouseClass::Init();\n\tObjectClass::Init();\n\tTeamTypeClass::Init();\n\tTeamClass::Init();\n\tTriggerClass::Init();\n\tTriggerTypeClass::Init();\n\tAircraftClass::Init();\n\tAnimClass::Init();\n\tBuildingClass::Init();\n\tBulletClass::Init();\n\tInfantryClass::Init();\n\tOverlayClass::Init();\n\tSmudgeClass::Init();\n\tTemplateClass::Init();\n\tTerrainClass::Init();\n\tUnitClass::Init();\n\tVesselClass::Init();\n\n\tFactoryClass::Init();\n\n\tBase.Init();\n\n\tCurrentObject.Clear_All();\n\n\tfor (int index = 0; index < WAYPT_COUNT; index++) {\n\t\tScen.Waypoint[index] = -1;\n\t}\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\tbAutoSonarPulse = false;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tScen.bLocalProposesDraw = false;\n\tScen.bOtherProposesDraw = false;\n#endif\n\n}\n\n\n/***********************************************************************************************\n * Do_Win -- Display winning congratulations.                                                  *\n *                                                                                             *\n *    Perform the win the mission process. This will display any winning movies and the score  *\n *    screen. Followed by the map selection screen and then the load of the new scenario.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *   01/01/1995 JLB : Carries money forward into next scenario.                                *\n *=============================================================================================*/\nvoid Do_Win(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t** Hack section.  If it's allied scenario 10, variation A, then skip the\n\t** score and map selection, don't increment scenario, and set it to\n\t** variation B.\n\t*/\n#ifdef FIXIT_ANTS\n\tif (Session.Type != GAME_NORMAL || !Scen.IsSkipScore || AntsEnabled) {\n#else\n\tif (Session.Type != GAME_NORMAL || !Scen.IsSkipScore ) {\n#endif\t//FIXIT_ANTS\n\n\t\t/*\n\t\t**\tAnnounce win to player.\n\t\t*/\n\t\tSet_Logic_Page(SeenBuff);\n\t\tMap.Flag_To_Redraw (true);\n\t\tMap.Render();\n#ifdef WIN32\n\t\tFancy_Text_Print(TXT_SCENARIO_WON, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n#else\n\t\tFancy_Text_Print(TXT_MISSION, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\t\tFancy_Text_Print(TXT_HACKHACK, x, 110*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n#endif\n\t\tCountDownTimer = TIMER_SECOND * 3;\n\t\twhile (Is_Speaking()) {};\n\t\tSpeak(VOX_ACCOMPLISHED);\n\t\twhile (CountDownTimer || Is_Speaking()) {\n\t\t\tCall_Back();\n\t\t}\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif (!Session.Play) {\n\t\t\tSession.GamesPlayed++;\n\t\t\tMulti_Score_Presentation();\n\t\t\tSession.CurGame++;\n\t\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t\t}\n\t\t}\n\t\tGameActive = 0;\n\t\tShow_Mouse();\n\t\treturn;\n\t}\n\n\tHide_Mouse();\n\tVisiblePage.Clear();\n\tShow_Mouse();\n\tPlay_Movie(Scen.WinMovie);\n\tPlay_Movie(Scen.WinMovie2);\n\tPlay_Movie(Scen.WinMovie3);\n\tPlay_Movie(Scen.WinMovie4);\n\n\tKeyboard->Clear();\n\n\tSaveTanya = IsTanyaDead;\n\tScen.CarryOverTimer = Scen.MissionTimer;\n//\tint timer = Scen.MissionTimer;\n\n\t/*\n\t**\tDo the ending screens only if not playing back a recorded game.\n\t*/\n\tif (!Session.Play) {\n\t\t/*\n\t\t**\tIf the score presentation should be performed, then do\n\t\t**\tso now.\n\t\t*/\n\t\tKeyboard->Clear();\n\t\tif (!Scen.IsSkipScore) {\n\t\t\tScore.Presentation();\n\t\t}\n\n\n\t\tif (Scen.IsOneTimeOnly) {\n\t\t\tGameActive = false;\n\t\t\tShow_Mouse();\n#ifdef FIXIT_ANTS\n\t\t\tAntsEnabled = false;\n//\t\t\tMono_Printf(\"Scenario.cpp one time only antsenabled is false\\n\");\n#endif\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t** If this scenario is flagged as ending the game then print the credits and exit.\n\t\t*/\n#if (0)//PG\n\t\tif (Scen.IsEndOfGame) {\n\t\t\tif (PlayerPtr->ActLike == HOUSE_USSR) {\n\t\t\t\tPlay_Movie(VQ_SOVFINAL);\n\t\t\t} else {\n\t\t\t\tPlay_Movie(VQ_ALLYEND);\n\t\t\t}\n\t\t\tShow_Who_Was_Responsible();\n\t\t\tGameActive = false;\n\t\t\tShow_Mouse();\n#ifdef FIXIT_ANTS\n\t\t\tAntsEnabled = false;\n#endif\n\t\t\treturn;\n\t\t}\n#endif\n\t\t/*\n\t\t** Hack section.  If it's allied scenario 10, variation A, then skip the\n\t\t** score and map selection, don't increment scenario, and set it to\n\t\t** variation B.\n\t\t*/\n\t\tif (Scen.IsNoMapSel) {\n\t\t\t// force it to play the second half of scenario 10\n#ifdef FIXIT_ANTS\n\t\t\tif (AntsEnabled) {\n\t\t\t\tchar scenarioname[24];\n\t\t\t\tstrcpy(scenarioname, Scen.ScenarioName);\n\t\t\t\tchar buf[10];\n\t\t\t\tScen.Scenario++;\n\t\t\t\tsprintf(buf, \"%02d\", Scen.Scenario);\n\t\t\t\tmemcpy(&scenarioname[3], buf, 2);\n\t\t\t\tScen.Set_Scenario_Name(scenarioname);\n\t\t\t} else {\n\t\t\t\tScen.ScenarioName[6] = 'B';\n\t\t\t}\n\n#else\n\t\t\tScen.ScenarioName[6] = 'B';\n#endif\n\n\t\t} else {\n\t\t\tScen.Set_Scenario_Name(Map_Selection());\n\t\t}\n\n\t\tKeyboard->Clear();\n\t}\n\n\tScen.CarryOverMoney = PlayerPtr->Credits;\n\n\t/*\n\t**\tIf requested, record the scenario's objects in the carry over list\n\t**\tfor possible use in a future scenario.\n\t*/\n\tif (Scen.IsToCarryOver) {\n\n\t\t/*\n\t\t**\tFirst delete any existing carry over list. Any old list will be\n\t\t**\tblasted over by the new list -- there is only one logic carryover\n\t\t**\tlist to be maintained.\n\t\t*/\n\t\twhile (Carryover) {\n\t\t\tCarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();\n\t\t\tCarryover->Remove();\n\t\t\tdelete Carryover;\n\t\t\tCarryover = cptr;\n\t\t}\n\n\t\t/*\n\t\t**\tRecord all objects, that are to be part of the carry over set, into\n\t\t**\tthe carry over list.\n\t\t*/\n\t\tfor (int building_index = 0; building_index < Buildings.Count(); building_index++) {\n\t\t\tBuildingClass * building = Buildings.Ptr(building_index);\n\n\t\t\tif (building && !building->IsInLimbo && building->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(building);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int unit_index = 0; unit_index < Units.Count(); unit_index++) {\n\t\t\tUnitClass * unit = Units.Ptr(unit_index);\n\n\t\t\tif (unit && !unit->IsInLimbo && unit->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(unit);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int infantry_index = 0; infantry_index < Infantry.Count(); infantry_index++) {\n\t\t\tInfantryClass * infantry = Infantry.Ptr(infantry_index);\n\n\t\t\tif (infantry && !infantry->IsInLimbo && infantry->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(infantry);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int vessel_index = 0; vessel_index < Vessels.Count(); vessel_index++) {\n\t\t\tVesselClass * vessel = Vessels.Ptr(vessel_index);\n\n\t\t\tif (vessel && !vessel->IsInLimbo && vessel->Strength > 0) {\n\t\t\t\tCarryoverClass * cptr = new CarryoverClass(vessel);\n\n\t\t\t\tif (cptr) {\n\t\t\t\t\tif (Carryover) {\n\t\t\t\t\t\tcptr->Add_Tail(*Carryover);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCarryover = cptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t** Generate a new scenario filename\n\t*/\n//\tScen.Set_Scenario_Name(Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, Scen.ScenVar);\n\tStart_Scenario(Scen.ScenarioName);\n\n\t/*\n\t**\tIf the mission timer is to be inheriteded from the previous scenario then do it now.\n\t*/\n\tif (Scen.IsInheritTimer) {\n\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\tScen.MissionTimer.Start();\n\t}\n\n//\tPlayerPtr->NukePieces = nukes;\n\n\tMap.Render();\n\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n//\tFade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);\n\tShow_Mouse();\n}\n\n\n/***********************************************************************************************\n * Do_Lose -- Display losing comments.                                                         *\n *                                                                                             *\n *    Performs the lose mission processing. This will generally display a \"would you like      *\n *    to replay\" dialog and then either reload the scenario or set flags such that the main    *\n *    menu will appear.                                                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/05/1992 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Do_Lose(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t**\tAnnounce win to player.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tFancy_Text_Print(TXT_SCENARIO_LOST, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\tCountDownTimer = TIMER_SECOND * 3;\n\twhile (Is_Speaking()) {};\n\tSpeak(VOX_FAIL);\n\twhile (CountDownTimer || Is_Speaking()) {\n\t\tCall_Back();\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tif (!Session.Play) {\n\t\t\tSession.GamesPlayed++;\n\t\t\tMulti_Score_Presentation();\n\t\t\tSession.CurGame++;\n\t\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t\t}\n\t\t}\n\t\tGameActive = 0;\n\t\tShow_Mouse();\n\t\treturn;\n\t}\n\n\tHide_Mouse();\n\tVisiblePage.Clear();\n\tShow_Mouse();\n#ifdef CHEAT_KEYS\n//\tMono_Printf(\"Trying to play lose movie\\n\");\n#endif //CHEAT_KEYS\n\tPlay_Movie(Scen.LoseMovie);\n\n\t/*\n\t** Start same scenario again\n\t*/\n\tGamePalette.Set();\n\tShow_Mouse();\n\tif (!Session.Play && !WWMessageBox().Process(TXT_TO_REPLAY, TXT_YES, TXT_NO)) {\n\t\tHide_Mouse();\n\t\tKeyboard->Clear();\n\t\tStart_Scenario(Scen.ScenarioName, false);\n\n\t\t/*\n\t\t**\tStart the scenario timer with the carried over value if necessary.\n\t\t*/\n\t\tif (Scen.IsInheritTimer) {\n\t\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\t\tScen.MissionTimer.Start();\n\t\t}\n\n\t\tMap.Render();\n\t} else {\n\t\tHide_Mouse();\n\t\tGameActive = 0;\n\t}\n\n\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\tShow_Mouse();\n}\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n/***********************************************************************************************\n * Do_Draw -- Parallels Do_Win and Do_Lose, for multiplayer games that end in a draw.\n *=============================================================================================*/\nvoid Do_Draw(void)\n{\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tHide_Mouse();\n\n\tTheme.Queue_Song(THEME_QUIET);\n\n\t/*\n\t** If this is a multiplayer game, clear the game's name so we won't respond\n\t** to game queries any more (in Call_Back)\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tSession.GameName[0] = 0;\n\t}\n\n\t/*\n\t**\tDetermine a cosmetic center point for the text.\n\t*/\n\tint x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);\n\n\t/*\n\t**\tAnnounce win to player.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tFancy_Text_Print(TXT_WOL_DRAW, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW);\n\tCountDownTimer = TIMER_SECOND * 3;\n\twhile (Is_Speaking()) {};\n\tSpeak(VOX_CONTROL_EXIT);\n\twhile (CountDownTimer || Is_Speaking()) {\n\t\tCall_Back();\n\t}\n\n\t/*\n\t** Stop here if this is a multiplayer game.\n\t*/\n\tif (!Session.Play) {\n\t\tSession.GamesPlayed++;\n\t\tMulti_Score_Presentation();\n\t\tSession.CurGame++;\n\t\tif (Session.CurGame >= MAX_MULTI_GAMES) {\n\t\t\tSession.CurGame = MAX_MULTI_GAMES - 1;\n\t\t}\n\t}\n\tGameActive = 0;\n\tShow_Mouse();\n}\n#endif\n\n/***********************************************************************************************\n * Do_Restart -- Handle the restart mission process.                                           *\n *                                                                                             *\n *    This routine is called in the main game loop when the mission must be restarted. This    *\n *    routine will throw away the current game and reload the appropriate mission. The         *\n *    game will \"resume\" at the start of the mission.                                          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/24/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Do_Restart(void)\n{\n\t/*\n\t** Start a timer going, before we restart the scenario\n\t*/\n\tCDTimerClass<SystemTimerClass> timer;\n\ttimer = TICKS_PER_SECOND * 4;\n\tTheme.Queue_Song(THEME_QUIET);\n\n\tWWMessageBox().Process(TXT_RESTARTING, TXT_NONE);\n\n\tMap.Set_Default_Mouse(MOUSE_NORMAL);\n\tKeyboard->Clear();\n\tStart_Scenario(Scen.ScenarioName, false);\n\n\t/*\n\t**\tStart the scenario timer with the carried over value if necessary.\n\t*/\n\tif (Scen.IsInheritTimer) {\n\t\tScen.MissionTimer = Scen.CarryOverTimer;\n\t\tScen.MissionTimer.Start();\n\t}\n\n\t/*\n\t** Make sure the message stays displayed for at least 1 second\n\t*/\n\twhile (timer > 0) {\n\t\tCall_Back();\n\t}\n\tKeyboard->Clear();\n\n\tMap.Render();\n}\n\n\n/***********************************************************************************************\n * Restate_Mission -- Handles restating the mission objective.                                 *\n *                                                                                             *\n *    This routine will display the mission objective (as text). It will also give the         *\n *    option to redisplay the mission briefing video.                                          *\n *                                                                                             *\n * INPUT:   name  -- The scenario name. This is the unique identifier for the scenario         *\n *                   briefing text as it appears in the \"MISSION.INI\" file.                    *\n *                                                                                             *\n * OUTPUT:  Returns the response from the dialog. This will either be 1 if the video was       *\n *          requested, or 0 if the return to game options button was selected.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/23/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Uses preloaded briefing text.                                            *\n *=============================================================================================*/\nbool Restate_Mission(char const * name, int button1, int button2)\n{\n\tif (name) {\n\n\t\tbool brief = true;\n\t\tchar buffer[25];\n\t\tif (Scen.BriefMovie != VQ_NONE) {\n\t\t\tsprintf(buffer, \"%s.VQA\", VQName[Scen.BriefMovie]);\n\t\t}\n\n\t\tif (Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available()) {\n\t\t\tbutton2 = TXT_OK;\n\t\t\tbutton1 = TXT_NONE;\n\t\t\tbrief = false;\n\t\t}\n\n\t\t/*\n\t\t**\tIf mission object text was found, then display it.\n\t\t*/\n\t\tif (strlen(Scen.BriefingText)) {\n\t\t\tstrcpy(_ShapeBuffer, Scen.BriefingText);\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\t\t\tif (BGMessageBox(_ShapeBuffer, button2, button1)) {\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\tif (!brief) return(true);\n\t\t\treturn(false);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n#define\tBUTTON_1\t\t1\n#define\tBUTTON_2\t\t2\n#define\tBUTTON_3\t\t3\n#define\tBUTTON_FLAG\t0x8000\nint BGMessageBox(char const * msg, int btn1, int btn2)\n{\n#define BUFFSIZE 511\n\tchar buffer[BUFFSIZE];\n\tint retval;\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tKeyNumType input;\t\t\t\t\t\t\t// user input\n\tint selection;\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass * buttons[3];\n\tBOOL display;\t\t\t\t\t\t\t\t\t// display level\n\tint  realval[5];\n\tint  morebutton = 3;\t\t\t\t\t\t// which button says \"more\": 2 or 3?\n\n\tconst char * b1txt = Text_String(btn1);\n\tconst char * b2txt = Text_String(btn2);\n#ifdef FRENCH\n\tconst char * b3txt = \"SUITE\";\n#else\n#ifdef GERMAN\n\tconst char * b3txt = \"MEHR\";\n#else\n\tconst char * b3txt = \"MORE\";\n#endif\n#endif\n\n\tconst void *briefsnd = MFCD::Retrieve(\"BRIEFING.AUD\");\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_TYPE]);\n\n\t/*\n\t** If the message won't be needing the 'more' button, get rid of it.\n\t*/\n\tif (strlen(msg) <= BUFFSIZE-1) {\n\t\tb3txt = \"\";\n\t}\n\n#ifdef WIN32\n\tGraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);\n#endif\n\n\t/*\n\t** If there's no text for button one, zero it out.\n\t*/\n\tif (*b1txt == '\\0') {\n\t\tb1txt = b2txt;\n\t\tb2txt = \"\";\n\t\tif(*b1txt == '\\0') {\n\t\t\tb1txt=0;\n\t\t}\n\t}\n\n\t/*\n\t** If there's no text for button two, zero it out.  However, if there\n\t** is text for button three, move its text (always \"MORE\") to button two,\n\t** and set the morebutton flag to point to button two.  Then, clear out\n\t** button 3.\n\t*/\n\tif (*b2txt == '\\0') {\n\t\tb2txt = 0;\n\t\tif (*b3txt != '\\0') {\n\t\t\tb2txt = b3txt;\n\t\t\tb3txt = \"\";\n\t\t\tmorebutton = 1;\n\t\t}\n\t}\n\n\t/*\n\t** If there's no text for button three, zero it out.\n\t*/\n\tif (*b3txt == '\\0') b3txt = 0;\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[PCOLOR_TYPE], TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL);\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tchar b1char, b2char, b3char;\t// 1st char of each string\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\tint numbuttons = 0;\n\tif (b1txt) {\n\t\tb1char = toupper(b1txt[0]);\n\n\t\t/*\n\t\t**\tBuild the button list.\n\t\t*/\n\t\tbheight = FontHeight + FontYSpacing + 2;\n\t\tbwidth = max((String_Pixel_Width(b1txt) + 8), 80);\n\t\tif (b2txt) {\n\t\t\tnumbuttons = 2;\n\t\t\tb2char = toupper(b2txt[0]);\n\t\t\tbwidth = max(((int)String_Pixel_Width( b2txt ) + 8), bwidth);\n//\t\t\tb1x = x + 10;\t\t\t\t\t\t\t\t// left side\n\n\t\t\tif (b3txt) {\n\t\t\t\tnumbuttons = 3;\n\t\t\t\tb3char = toupper(b3txt[0]);\n\t\t\t\tbwidth = max(((int)String_Pixel_Width( b3txt ) + 8), bwidth);\n\t\t\t}\n\n\t\t} else {\n\t\t\tnumbuttons = 1;\n//\t\t\tb1x = x + ((width - bwidth) >> 1);\t\t// centered\n\t\t}\n\t}\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tint buffend = BUFFSIZE-1;\n\tstrncpy(buffer, msg, BUFFSIZE-1);\n\t/*\n\t** Scan through the string to see if it got clipped, and if so, we'll\n\t** trim it back to the last space so it'll clip on a word.\n\t*/\n\tif (strlen(buffer) != strlen(msg)) {\n\t\twhile (buffer[buffend] != ' ') buffend--;\n\t\tbuffer[buffend]=0;\n\t}\n\tFancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[PCOLOR_TYPE], TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, 300, width, height);\n\theight += (numbuttons == 0) ? 30 : 60;\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*\n\t**\tOther inits.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tInitialize the button structures. All are initialized, even though one (or none) may\n\t**\tactually be added to the button list.\n\t*/\n\tTextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,\n\t\tx + ((numbuttons == 1) ? ((width - bwidth) >> 1) : 10), y + height - (bheight + 5), bwidth);\n\n\tTextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,\n\t\tx + width - (bwidth + 10), y + height - (bheight + 5), bwidth);\n\n\tTextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON,\n\t\t0, y + height - (bheight + 5));\n\tbutton3.X = x + ((width - button3.Width) >> 1);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tif (numbuttons) {\n\t\tbuttonlist = &button1;\n\t\tbuttons[0] = &button1;\n\t\trealval[0] = BUTTON_1;\n\t\tif (numbuttons > 2) {\n\t\t\tbutton3.Add(*buttonlist);\n\t\t\tbuttons[1] = &button3;\n\t\t\trealval[1] = BUTTON_3;\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[2] = &button2;\n\t\t\trealval[2] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t} else if (numbuttons == 2) {\n\t\t\tbutton2.Add(*buttonlist);\n\t\t\tbuttons[1] = &button2;\n\t\t\trealval[1] = BUTTON_2;\n\t\t\tbuttons[curbutton]->Turn_On();\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the dialog.\n\t*/\n\tHide_Mouse();\n\n\tPaletteClass temp;\n#ifdef WIN32\n\tchar *filename = \"SOVPAPER.PCX\";\n\tif (PlayerPtr->Class->House != HOUSE_USSR && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\tfilename = \"ALIPAPER.PCX\";\n\t}\n\tLoad_Title_Screen(filename, &HidPage, (unsigned char*)temp.Get_Data());\n#else\n\tchar *filename = \"SOVPAPER.CPS\";\n\tif (PlayerPtr->Class->House != HOUSE_USSR && PlayerPtr->Class->House != HOUSE_UKRAINE) {\n\t\tfilename = \"ALIPAPER.CPS\";\n\t}\n\tLoad_Uncompress(CCFileClass(filename), HidPage, HidPage, temp);\n#endif\n\tHidPage.Blit(SeenPage);\n\n\t#ifdef WIN32\n\tVisiblePage.Blit(seen_buff_save);\n\t#endif\n\n\tstatic unsigned char _scorepal[]={0,1,12,13,4,5,6,7,8,9,10,255,252,253,14,248};\n\tSet_Font_Palette(_scorepal);\n\ttemp.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\n\tint bufindex = 0;\n\n\tKeyboard->Clear();\n\n\tSet_Font_Palette(_scorepal);\n\tint xprint = x + 20;\n\tint yprint = y + 25;\n\tdo {\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\tHide_Mouse();\n\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\tdisplay = true;\n\t\t\tShow_Mouse();\n\t\t}\n\t\t#endif\n\t\tchar bufprint[2];\n\t\tbufprint[1]=0;\n\t\tbufprint[0] = buffer[bufindex];\n\t\tif (bufprint[0] == '\\r' || bufprint[0] == '@') {\n\t\t\txprint = x + 20;\n\t\t\typrint += FontHeight + FontYSpacing;\n\n\t\t} else {\n\t\t\tif (bufprint[0] != 20) {\n\t\t\t\tSeenPage.Print(bufprint, xprint, yprint, TBLACK, TBLACK);\n#ifdef WIN32\n\t\t\t\tseen_buff_save.Print(bufprint, xprint, yprint, TBLACK, TBLACK);\n#endif\n\t\t\t\txprint += Char_Pixel_Width(bufprint[0]);\n\t\t\t}\n\t\t}\n\t\tif (bufprint[0] == '\\r' || bufprint[0] == '@') {\n#ifdef WIN32\n\t\t\tPlay_Sample(briefsnd, 255, Options.Normalize_Volume(135));\n#else\n\t\t\tPlay_Sample(briefsnd, 255, Options.Normalize_Volume(45));\n#endif\n\t\t\tCDTimerClass<SystemTimerClass> cd;\n\t\t\tcd = 5;\n\t\t\tdo {\n\t\t\t\tCall_Back();\n\t\t\t} while(!Keyboard->Check() && cd);\n\t\t}\n\t} while (buffer[++bufindex]);\n\n\tShow_Mouse();\n\tKeyboard->Clear();\n\n\tif (buttonlist) {\n\t\tprocess = true;\n\t\tpressed = false;\n\t\twhile (process) {\n\t\t\t#ifdef WIN32\n\t\t\t/*\n\t\t\t** If we have just received input focus again after running in the background then\n\t\t\t** we need to redraw.\n\t\t\t*/\n\t\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\t\tAllSurfaces.SurfacesRestored = false;\n\t\t\t\tHide_Mouse();\n\t\t\t\tseen_buff_save.Blit(VisiblePage);\n\t\t\t\tdisplay = true;\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif (display) {\n\t\t\t\tdisplay = false;\n\n\t\t\t\tHide_Mouse();\n\n\t\t\t\t/*\n\t\t\t\t**\tRedraw the buttons.\n\t\t\t\t*/\n\t\t\t\tif (buttonlist) {\n\t\t\t\t\tbuttonlist->Draw_All();\n\t\t\t\t}\n\t\t\t\tShow_Mouse();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tInvoke game callback.\n\t\t\t*/\n\t\t\tCall_Back();\n\n\t\t\t/*\n\t\t\t**\tFetch and process input.\n\t\t\t*/\n\t\t\tinput = buttonlist->Input();\n\t\t\tswitch (input) {\n\t\t\t\tcase (BUTTON_1|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[0];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_ESC):\n\t\t\t\t\tif (numbuttons > 2) {\n\t\t\t\t\t\tselection = realval[1];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselection = realval[2];\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_2|BUTTON_FLAG):\n\t\t\t\t\tselection = BUTTON_2;\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (BUTTON_3|BUTTON_FLAG):\n\t\t\t\t\tselection = realval[1];\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_LEFT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton--;\n\t\t\t\t\t\tif (curbutton < 0) {\n\t\t\t\t\t\t\tcurbutton = numbuttons - 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RIGHT):\n\t\t\t\t\tif (numbuttons > 1) {\n\t\t\t\t\t\tbuttons[curbutton]->Turn_Off();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\n\t\t\t\t\t\tcurbutton++;\n\t\t\t\t\t\tif (curbutton > (numbuttons - 1) ) {\n\t\t\t\t\t\t\tcurbutton = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuttons[curbutton]->Turn_On();\n\t\t\t\t\t\tbuttons[curbutton]->Flag_To_Redraw();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase (KN_RETURN):\n\t\t\t\t\tselection = curbutton + BUTTON_1;\n\t\t\t\t\tpressed = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t**\tCheck 'input' to see if it's the 1st char of button text\n\t\t\t\t*/\n\t\t\t\tdefault:\n\t\t\t\t\tif (b1char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_1;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else if (b2txt!=NULL &&\n\t\t\t\t\t\tb2char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_2;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t} else if (b3txt!=NULL &&\n\t\t\t\t\t\tb3char == toupper(Keyboard->To_ASCII((KeyNumType)(input & 0xFF)))) {\n\t\t\t\t\t\tselection = BUTTON_3;\n\t\t\t\t\t\tpressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (pressed) {\n\t\t\t\tswitch (selection) {\n\t\t\t\t\tcase (BUTTON_1):\n\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase (BUTTON_2):\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase BUTTON_3:\n\t\t\t\t\t\tretval = 2;\n\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tpressed = false;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tKeyboard->Clear();\n\t}\n\n\tif (retval == (morebutton-1) && strlen(msg) > BUFFSIZE-1) {\n\t\tretval = BGMessageBox(msg + buffend + 1, btn1, btn2);\n\t}\n\t/*\n\t** Restore the screen.\n\t*/\n\tHide_Mouse();\n\t/*\n\t** Now set the palette, depending on if we're going to show the video or\n\t** go back to the main menu.\n\t*/\n\tswitch (retval) {\n\t\tcase 0:\n//\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n//\t\t\tSeenPage.Clear();\n////\t\t\tCCPalette.Set();\n//\t\t\tbreak;\n\t\tcase 1:\n\t\t\tBlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);\n\t\t\tSeenPage.Clear();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tShow_Mouse();\n\n\tGadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);\n\n\treturn(retval);\n}\n\n\n/***********************************************************************************************\n * Set_Scenario_Name -- Creates the INI scenario name string.                                  *\n *                                                                                             *\n *    This routine is used by the scenario loading and saving code. It generates the scenario  *\n *    INI root file name for the specified scenario parameters.                                *\n *                                                                                             *\n * INPUT:                                                                                      *\n *         buf         buffer to store filename in; must be long enough for root.ext           *\n *       scenario      scenario number                                                         *\n *       player      player type for this game (GDI, NOD, multi-player, ...)                   *\n *       dir         directional parameter for this game (East/West)                           *\n *       var         variation of this game (Lose, A/B/C/D, etc)                               *\n *                                                                                             *\n * OUTPUT:  none.                                                                              *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/28/1994 JLB : Created.                                                                 *\n *   05/01/1995 BRR : 2-player scenarios use same names as multiplayer                         *\n *=============================================================================================*/\nvoid ScenarioClass::Set_Scenario_Name(int scenario, ScenarioPlayerType player, ScenarioDirType dir, ScenarioVarType var)\n{\n\tScenario = scenario;\n//\tScenPlayer = player;\n//\tScenDir = dir;\n//\tScenVar = var;\n\n\tchar c_player;\t\t\t// character representing player type\n\tchar c_dir;\t\t\t\t// character representing direction type\n\tchar c_var;\t\t\t\t// character representing variation type\n\tScenarioVarType i;\n\tchar fname[_MAX_FNAME+_MAX_EXT];\n\n\t/*\n\t** Set the player-type value.\n\t*/\n\tswitch (player) {\n\t\tcase SCEN_PLAYER_SPAIN:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_SPAIN).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_GREECE:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_GREECE).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_USSR:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_USSR).Prefix;\n\t\t\tbreak;\n\n\t\tcase SCEN_PLAYER_JP:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_JP).Prefix;\n\t\t\tbreak;\n\n\t\t/*\n\t\t**\tMulti player scenario.\n\t\t*/\n\t\tdefault:\n\t\t\tc_player = HouseTypeClass::As_Reference(HOUSE_MULTI1).Prefix;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Set the directional character value.\n\t** If SCEN_DIR_NONE is specified, randomly pick a direction; otherwise, use 'E' or 'W'\n\t*/\n\tswitch (dir) {\n\t\tcase SCEN_DIR_EAST:\n\t\t\tc_dir = 'E';\n\t\t\tbreak;\n\n\t\tcase SCEN_DIR_WEST:\n\t\t\tc_dir = 'W';\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase SCEN_DIR_NONE:\n\t\t\tc_dir = Percent_Chance(50) ? 'W' : 'E';\n\t\t\tbreak;\n\t}\n\n\t/*\n\t** Set the variation value.\n\t*/\n\tif (var == SCEN_VAR_NONE) {\n\n\t\t/*\n\t\t** Find which variations are available for this scenario\n\t\t*/\n\t\tfor (i = SCEN_VAR_FIRST; i < SCEN_VAR_COUNT; i++) {\n\t\t\tsprintf(fname, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, 'A' + i);\n\t\t\tif (!CCFileClass(fname).Is_Available()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (i==SCEN_VAR_FIRST) {\n\t\t\tc_var = 'X';\t\t\t\t\t\t// indicates an error\n\t\t} else {\n\t\t\tc_var = 'A' + Random_Pick(0, i-1);\n//\t\t\tScenVar = (ScenarioVarType)i;\n\t\t}\n\t} else {\n\t\tswitch (var) {\n\t\t\tcase SCEN_VAR_A:\n\t\t\t\tc_var = 'A';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_B:\n\t\t\t\tc_var = 'B';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_C:\n\t\t\t\tc_var = 'C';\n\t\t\t\tbreak;\n\n\t\t\tcase SCEN_VAR_D:\n\t\t\t\tc_var = 'D';\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tc_var = 'L';\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\t/*\n\t** generate the filename\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n//Mono_Printf(\"In set_scenario_name, scenario # = %d\\n\",scenario);Keyboard->Get();Keyboard->Get();\n\tif (scenario < 100) {\n\t\tsprintf(ScenarioName, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, c_var);\n\t} else {\n\t\tchar first = (scenario / 36) + 'A';\n\t\tchar second = scenario % 36;\n\n\t\tif (second < 10) {\n\t\t\tsecond += '0';\n\t\t} else {\n\t\t\tsecond = (second - 10) + 'A';\n\t\t}\n\n\t\tsprintf(ScenarioName, \"SC%c%c%c%c%c.INI\", c_player, first, second, c_dir, c_var);\n\t}\n#else\n\tsprintf(ScenarioName, \"SC%c%02d%c%c.INI\", c_player, scenario, c_dir, c_var);\n#endif\n}\n\n\nvoid ScenarioClass::Set_Scenario_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tstrncpy(ScenarioName, name, sizeof(ScenarioName));\n\t\tScenarioName[ARRAY_SIZE(ScenarioName)-1] = '\\0';\n\n\t\tchar buf[3];\n\t\tmemcpy(buf, &ScenarioName[3], 2);\n\t\tbuf[2] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (buf[0] > '9' || buf[1] > '9') {\n\t\t\tchar first = buf[0];\n\t\t\tchar second = buf[1];\n\t\t\tif (first <= '9') {\n\t\t\t\tfirst -= '0';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\n\t\t\tif (second <= '9') {\n\t\t\t\tsecond -= '0';\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\n\t\t\tScenario = (36 * first) + second;\n\t\t} else {\n\t\t\tScenario = atoi(buf);\n\t\t}\n#else\n\t\tScenario = atoi(buf);\n#endif\n\t}\n}\n\n\n\n/***********************************************************************************************\n * Read_Scenario_INI -- Read specified scenario INI file.                                      *\n *                                                                                             *\n *    Read in the scenario INI file. This routine only sets the game                           *\n *    globals with that data that is explicitly defined in the INI file.                       *\n *    The remaining necessary interpolated data is generated elsewhere.                        *\n *                                                                                             *\n * INPUT:                                                                                      *\n *          root      root filename for scenario file to read                                  *\n *                                                                                             *\n *          fresh      true = should the current scenario be cleared?                          *\n *                                                                                             *\n * OUTPUT:  bool; Was the scenario read successful?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.  V.Grippi added CS check 2/5/97                                                               *\n *=============================================================================================*/\nbool Read_Scenario_INI(char * fname, bool )\n{\n//\tchar fname[_MAX_FNAME+_MAX_EXT];\t\t\t// full INI filename\n\n\n\tScenarioInit++;\n\n\tClear_Scenario();\n#ifdef OBSOLETE\n\t/*\n\t** If we are not dealing with scenario 1, or a multi player scenario\n\t** then make sure the correct disk is in the drive.\n\t*/\n\tif (RequiredCD != -2) {\n\t\tRequiredCD = -1;\n\t}\n#endif\n\n\t/*\n\t** Only force a CD check if this is a single player game or if its\n\t** a multiplayer game on an official scenario. If its non-official\n\t** (a user scenario) then we dont care which CD is in because the\n\t** scenario is stored locally on the hard drive. In this case, we\n\t** have already verified its existance. ST 3/1/97 4:52PM.\n\t*/\n#ifdef FIXIT_VERSION_3\t\t//\tAvoid CD check if official scenario was downloaded.\n\tif( ( Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial ) && _stricmp( Scen.ScenarioName, \"download.tmp\" ) ){\n#else\n\tif (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial){\n#endif\n\n\t\t/*\n\t\t** If this is scenario 1 then it should be on all CDs unless its an ant scenario\n\t\t*/\n\t\tif (Scen.Scenario == 1 && Scen.ScenarioName[2] != 'A') {\n\t   \tRequiredCD = -1;\n\t\t} else {\n//\t\t\tMono_Printf(\"Read_SCen_INI scenario is: %s\\n\", Scen.ScenarioName);\n\t\t\t/*\n\t\t\t** If this is a multiplayer scenario we need to find out if its a counterstrike\n\t\t\t** scenario. If so then we need CD 2. The original multiplayer scenarios are on\n\t\t\t** all CDs.\n\t\t\t*/\n\t\t\tif (Session.Type != GAME_NORMAL) {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\t\t\tRequiredCD = -1;\t// default that any CD will do.\n// If it's a counterstrike mission, require the counterstrike CD, unless the\n// Aftermath CD is already in the drive, in which case, leave it there.\n// Note, this works because this section only tests for multiplayer scenarios.\n\t\t\t\tif (Is_Mission_Counterstrike(Scen.ScenarioName)) {\n\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t\tif( Is_Aftermath_Installed() || Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) == 3 )\n\t\t\t\t\t{\n\t\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(Is_Mission_Aftermath(Scen.ScenarioName)) {\n\t\t\t\t\tRequiredCD = 3;\n\t\t\t\t}\n#else\n\t\t\t\tif (Scen.Scenario > 24) {\n\t\t\t\t\tRequiredCD = 2;\n\t\t\t\t} else {\n\t\t\t\t\tRequiredCD = -1;\n\t\t\t\t}\n#endif\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t** This is a solo game. If the scenario number is >= 20 or its an ant mission\n\t\t\t\t** then we need the counterstrike CD (2)\n\t\t\t\t*/\n     \t\t\tif (Scen.Scenario >= 20 || Scen.ScenarioName[2] == 'A') {\n\t\t\t\t\tRequiredCD = 2;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n     \t\t\t\tif (Scen.Scenario >= 36 && Scen.ScenarioName[2] != 'A') {\n\t\t\t\t\t\tRequiredCD = 3;\n#ifdef BOGUSCD\n\tRequiredCD = -1;\n#endif\n\t\t\t\t\t}\n#endif\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t** This is a solo mission from the original Red Alert. Choose the Soviet or\n\t\t\t\t\t** allied CD depending on the scenario name.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Scen.ScenarioName[2] == 'U') {\n\t\t\t\t\t\tRequiredCD = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Scen.ScenarioName[2] == 'G') {\n//\t\t\t\t\t\t\tMono_Printf(\"We are setting REquiredCD to 0\");\n\t\t\t\t\t\t\tRequiredCD = 0;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n     \t\t\t}\n\t\t\t}\n\t\t}\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're asking for a CD swap, check to see if we need to set the palette\n// to avoid a black screen.  If this is a normal RA game, and the CD being\n// requested is an RA CD, then don't set the palette, leave the map screen up.\n\n#ifdef FIXIT_VERSION_3\n\t\tint cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);\n\t\tif( !( Using_DVD() && cd_index == 5 ) && cd_index != RequiredCD ) {\n#else\n\t\tif (Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != RequiredCD) {\n#endif\n\t\t\tif ((RequiredCD == 0 || RequiredCD == 1) && Session.Type == GAME_NORMAL) {\n\t\t\t\tSeenPage.Clear();\n\t\t\t}\n\t\t\tGamePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\t\t}\n#endif\n\t\tif (!Force_CD_Available(RequiredCD)) {\n\t\t\tProg_End(\"Read_Scenario_INI Force_CD_Available failed\", true);\n\t\t\tif (!RunningAsDLL) {\t//PG\n\t\t\t\tEmergency_Exit(EXIT_FAILURE);\n\t\t\t}\n     \t}\n\t} else {\n\t\t/*\n\t\t** This is a user scenario so any old CD will do.\n\t\t*/\n\t\tRequiredCD = -1;\n\t}\n\n\n\t/*\n\t**\tCreate scenario filename and read the file.\n\t*/\n//\tsprintf(fname, \"%s.INI\", root);\n\tCCINIClass ini;\n\tCCFileClass file(fname);\n//\tfile.Cache();\n\n\tint result = ini.Load(file, true);\n\tif (result == 0) {\n//\t\tMono_Printf(\"ini.Load failed\");\n\t\tGlyphX_Debug_Print(\"Failed to load scenario file\");\n\t\tGlyphX_Debug_Print(fname);\n\t\treturn(false);\n\t}\n\n\tGlyphX_Debug_Print(\"Loaded scenario file\");\n\tGlyphX_Debug_Print(file);\n\n\t/*\n\t** If the scenario digest is wrong then the return code will be a 2.\n\t*/\n\tif (result == 2) {\n//\t\tif (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial) {\n\t\t\t/*\n\t\t\t**\tMake a special exception so that multiplayer maps from 1 through\n\t\t\t**\t24 will not care if the message digest is in error. All other\n\t\t\t**\tmaps will abort the scenario load.\n\t\t\t*/\n\t\t\tif (Scen.ScenarioName[2] != 'M' || Scen.Scenario >= 25) {\n#if (1)\t\t\t\t\n\t\t\t\tGlyphX_Debug_Print(\"Scenario digest is wrong\");\n#else\t\t\t\t\n\t\t\t\tGamePalette.Set();\n\t\t\t\tWWMessageBox().Process(TXT_SCENARIO_ERROR, TXT_OK);\n#endif\n#ifdef RELEASE_VERSION\n\t\t\t\treturn(false);\n#endif\n\t\t\t}\n//\t\t}\n\t}\n\n\t/*\n\t**\tReset the rules values to their initial settings.\n\t*/\n#ifdef FIXIT_NAME_OVERRIDE\n\tfor (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {\n\t\tif (NameOverride[index] != NULL) free((void*)NameOverride[index]);\n\t\tNameOverride[index] = NULL;\n\t\tNameIDOverride[index] = 0;\n\t}\n\tif (Session.Type == GAME_NORMAL)  {\n\t\tSpecial.IsShadowGrow = false;\n\t}\n#endif\n\n#ifdef FIXIT_ANTS\n\tSession.Messages.Reset();\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n//\tSession.Messages.Add_Message(NULL, 0, NULL, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1);\n\tWeaponTypeClass::As_Pointer(WEAPON_FLAMER)->Sound = VOC_NONE;\n\tInfantryTypeClass::As_Reference(INFANTRY_THIEF).IsDoubleOwned = false;\n\tInfantryTypeClass::As_Reference(INFANTRY_E4).IsDoubleOwned = false;\n\tInfantryTypeClass::As_Reference(INFANTRY_SPY).PrimaryWeapon = NULL;\n\tInfantryTypeClass::As_Reference(INFANTRY_SPY).SecondaryWeapon = NULL;\n\tInfantryTypeClass::As_Reference(INFANTRY_GENERAL).IsBomber = false;\n\tUnitTypeClass::As_Reference(UNIT_HARVESTER).IsExploding = false;\n\tUnitTypeClass::As_Reference(UNIT_ANT1).Level = -1;\n\tUnitTypeClass::As_Reference(UNIT_ANT2).Level = -1;\n\tUnitTypeClass::As_Reference(UNIT_ANT3).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_QUEEN).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_LARVA1).Level = -1;\n\tBuildingTypeClass::As_Reference(STRUCT_LARVA2).Level = -1;\n#endif\n\n\n\tRule.General(RuleINI);\n\tRule.Recharge(RuleINI);\n\tRule.AI(RuleINI);\n\tRule.Powerups(RuleINI);\n\tRule.Land_Types(RuleINI);\n\tRule.Themes(RuleINI);\n\tRule.IQ(RuleINI);\n\tRule.Objects(RuleINI);\n\tRule.Difficulty(RuleINI);\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Except does this _change_ any rules, or just add to them? - Just adds.\n\tRule.General(AftermathINI);\n\tRule.Recharge(AftermathINI);\n\tRule.AI(AftermathINI);\n\tRule.Powerups(AftermathINI);\n\tRule.Land_Types(AftermathINI);\n\tRule.Themes(AftermathINI);\n\tRule.IQ(AftermathINI);\n\tRule.Objects(AftermathINI);\n\tRule.Difficulty(AftermathINI);\n#endif\n\n\t/*\n\t**\tFor civilians, remove the graphics name override from the base rules (can still be overridden in scenario-specific INI).\n\t*/\n\tfor (int iindex = 0; iindex < InfantryTypes.Count(); iindex++) {\n\t\tInfantryTypeClass* itype = InfantryTypes.Ptr(iindex);\n\t\tif (itype->IsCivilian) {\n\t\t\titype->GraphicName[0] = '\\0';\n\t\t}\n\t}\n\n\t/*\n\t**\tOverride any rules values specified in this\n\t**\tparticular scenario file.\n\t*/\n\tRule.General(ini);\n\tRule.Recharge(ini);\n\tRule.AI(ini);\n\tRule.Powerups(ini);\n\tRule.Land_Types(ini);\n\tRule.Themes(ini);\n\tRule.IQ(ini);\n\tRule.Objects(ini);\n\tRule.Difficulty(ini);\n\n\t/*\n\t**\t- Fix a legacy bug with England and France country bonuses.\n\t**\t- Use ore growth and spread values from the special settings.\n\t*/\n\tif (Session.Type != GAME_NORMAL) {\n\t\tHouseTypeClass::As_Reference(HOUSE_ENGLAND).ArmorBias = fixed(9, 10);\n\t\tHouseTypeClass::As_Reference(HOUSE_FRANCE).ROFBias = fixed(9, 10);\n\n\t\tRule.IsTGrowth = Special.IsTGrowth;\n\t\tRule.IsTSpread = Special.IsTSpread;\n\t}\n\n\t/*\n\t** Init the Scenario CRC value\n\t*/\n\tScenarioCRC = 0;\n#ifdef TOFIX\n\tlen = strlen(buffer);\n\tfor (int i = 0; i < len; i++) {\n\t\tval = (unsigned char)buffer[i];\n\t\tAdd_CRC(&ScenarioCRC, (unsigned long)val);\n\t}\n#endif\n\n\t/*\n\t**\tFetch the appropriate movie names from the INI file.\n\t*/\n\tconst char * const BASIC = \"Basic\";\n\tini.Get_String(BASIC, \"Name\", \"<none>\", Scen.Description, sizeof(Scen.Description));\n\tScen.IntroMovie = ini.Get_VQType(BASIC, \"Intro\", Scen.IntroMovie);\n\tScen.BriefMovie = ini.Get_VQType(BASIC, \"Brief\", Scen.BriefMovie);\n\tScen.WinMovie = ini.Get_VQType(BASIC, \"Win\", Scen.WinMovie);\n\tScen.WinMovie2 = ini.Get_VQType(BASIC, \"Win2\", Scen.WinMovie2);\n\tScen.WinMovie3 = ini.Get_VQType(BASIC, \"Win3\", Scen.WinMovie3);\n\tScen.WinMovie4 = ini.Get_VQType(BASIC, \"Win4\", Scen.WinMovie4);\n\tScen.LoseMovie = ini.Get_VQType(BASIC, \"Lose\", Scen.LoseMovie);\n\tScen.ActionMovie = ini.Get_VQType(BASIC, \"Action\", Scen.ActionMovie);\n\tScen.IsToCarryOver = ini.Get_Bool(BASIC, \"ToCarryOver\", Scen.IsToCarryOver);\n\tScen.IsToInherit = ini.Get_Bool(BASIC, \"ToInherit\", Scen.IsToInherit);\n\tScen.IsInheritTimer = ini.Get_Bool(BASIC, \"TimerInherit\", Scen.IsInheritTimer);\n\tScen.IsEndOfGame = ini.Get_Bool(BASIC, \"EndOfGame\", Scen.IsEndOfGame);\n\tScen.IsTanyaEvac = ini.Get_Bool(BASIC, \"CivEvac\", Scen.IsTanyaEvac);\n\tScen.TransitTheme = ini.Get_ThemeType(BASIC, \"Theme\", THEME_NONE);\n\tNewINIFormat = ini.Get_Int(BASIC, \"NewINIFormat\", 0);\n\tScen.CarryOverPercent = ini.Get_Fixed(BASIC, \"CarryOverMoney\", Scen.CarryOverPercent);\n\tScen.CarryOverPercent = Saturate(Scen.CarryOverPercent, 1);\n\tScen.CarryOverCap = ini.Get_Int(BASIC, \"CarryOverCap\", Scen.CarryOverCap);\n\tScen.IsNoSpyPlane = ini.Get_Bool(BASIC, \"NoSpyPlane\", Scen.IsNoSpyPlane);\n\tScen.IsSkipScore = ini.Get_Bool(BASIC, \"SkipScore\", Scen.IsSkipScore);\n\tScen.IsOneTimeOnly = ini.Get_Bool(BASIC, \"OneTimeOnly\", Scen.IsOneTimeOnly);\n\tScen.IsNoMapSel = ini.Get_Bool(BASIC, \"SkipMapSelect\", Scen.IsNoMapSel);\n\tScen.IsTruckCrate = ini.Get_Bool(BASIC, \"TruckCrate\", Scen.IsTruckCrate);\n\tScen.IsMoneyTiberium = ini.Get_Bool(BASIC, \"FillSilos\", Scen.IsMoneyTiberium);\n\tScen.Percent = ini.Get_Int(BASIC, \"Percent\", Scen.Percent);\n\n\t/*\n\t**\tRead in the specific information for each of the house types.  This creates\n\t**\tthe houses of different types.\n\t*/\n\tHouseClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the team-type data. The team types must be created before any\n\t**\ttriggers can be created.\n\t*/\n\tTeamTypeClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the trigger data. The triggers must be created before any other\n\t**\tobjects can be initialized.\n\t*/\n\tTriggerTypeClass::Read_INI(ini);\n\tCall_Back();\n\n\n\t/*\n\t**\tRead in the map control values. This includes dimensions\n\t**\tas well as theater information.\n\t*/\n\tMap.Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tAssign PlayerPtr by reading the player's house from the INI;\n\t**\tMust be done before any TechnoClass objects are created.\n\t*/\n\tif (Session.Type == GAME_NORMAL) {\n\t\tPlayerPtr = HouseClass::As_Pointer(ini.Get_HousesType(BASIC, \"Player\", HOUSE_GREECE));\n\t\tPlayerPtr->Assign_Handicap(Scen.Difficulty);\n\t\tint carryover;\n\t\tif (Scen.CarryOverCap != -1) {\n\t\t\tcarryover = min(Scen.CarryOverMoney * Scen.CarryOverPercent, Scen.CarryOverCap);\n\t\t} else {\n\t\t\tcarryover = Scen.CarryOverMoney * Scen.CarryOverPercent;\n\t\t}\n\t\tPlayerPtr->Credits += carryover;\n\t\tPlayerPtr->Control.InitialCredits += carryover;\n\t} else {\n\t\t//Call the new Assign_Houses function. ST - 8/8/2019 12:35PM\n\t\t//Assign_Houses();\n\t\tGlyphX_Assign_Houses();\n\t}\n\tPlayerPtr->IsHuman = true;\n\tPlayerPtr->IsPlayerControl = true;\n\n//\tif (NewINIFormat < 2 || !ini.Is_Present(\"MapPack\")) {\n//\t\tMap.Read_Binary(root, &ScenarioCRC);\n//\t}\n\n\n\t/*\n\t**\tRead in and place the 3D terrain objects.\n\t*/\n\tTerrainClass::Read_INI(ini);\n\tCall_Back();\n\t/*\n\t**\tRead in and place the units (all sides).\n\t*/\n\tUnitClass::Read_INI(ini);\n\tCall_Back();\n\n\tAircraftClass::Read_INI(ini);\n\tCall_Back();\n\n\tVesselClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in and place the infantry units (all sides).\n\t*/\n\tInfantryClass::Read_INI(ini);\n\tCall_Back();\n\n\n\n\t/*\n\t**\tRead in and place all the buildings on the map.\n\t*/\n\tBuildingClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in the AI's base information.\n\t*/\n\tBase.Read_INI(ini);\n\tCall_Back();\n\n      \t/*\n\t**\tRead in any normal overlay objects.\n\t*/\n\tOverlayClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\n\t**\tRead in any smudge overlays.\n\t*/\n\tSmudgeClass::Read_INI(ini);\n\tCall_Back();\n\n\t/*\tMoved above ini.Get_TextBlock(...) so Xlat mission.ini could be loaded\n\t**\tIf the briefing text could not be found in the INI file, then search\n\t**\tthe mission.ini file.  VG 10/17/96\n\t*/\n\tINIClass mini;\n\tmini.Load(CCFileClass(\"MISSION.INI\"));\n\tmini.Get_TextBlock(fname, Scen.BriefingText, sizeof(Scen.BriefingText));\n\n\t/*\n\t**\tRead in any briefing text.\n\t*/\n\tif (Scen.BriefingText[0] == '\\0') {\n\t\tini.Get_TextBlock(\"Briefing\", Scen.BriefingText, sizeof(Scen.BriefingText));\n\t}\n\t/*\n\t**\tPerform a final overpass of the map. This handles smoothing of certain\n\t**\ttypes of terrain (tiberium).\n\t*/\n\tMap.Overpass();\n\tCall_Back();\n\n\t/*\n\t**\tSpecial cases:\n\t**\t\tGold Rush multiplayer map cell 9033 - LAND_ROCK\n\t**\t\tThe Lake District multiplayer map cell 8482 - LAND_ROCK\n\t**\t\tBlue Lakes multiplayer map cell 11937 - LAND_RIVER\n\t**\t\tUSSR mission 13 - fixup trigger action\n\t**\t\tAllied mission 5B - fail mission if spy re-boards the transport at mission start\n\t**\t\tAllied mission 8A - Germany is allied with Greece and itself\n\t**\t\tAllied mission 9A - fail mission if tech center is destroyed before being spied\n\t**\t\tAftermath: Brother in Arms - have transports move to separate waypoints\n\t**\t\tAftermath: Let's Make a Steal - Make the pillboxes un-capturable\n\t**\t\tCounterstrike: Soviet Soldier Volkov and Chitzkoi / Deus Ex Machina - Sniper burst fix\n\t*/\n\tif (_stricmp(Scen.ScenarioName, \"scmh8ea.ini\") == 0) {\n\t\tMap[(CELL)9033].Override_Land_Type(LAND_ROCK);\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scm93ea.ini\") == 0) {\n\t\tMap[(CELL)8482].Override_Land_Type(LAND_ROCK);\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scmh4ea.ini\") == 0) {\n\t\tMap[(CELL)11937].Override_Land_Type(LAND_RIVER);\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scu13ea.ini\") == 0) {\n\t\tTriggerTypeClass* trigger = TriggerTypes.Ptr(11);\n\t\ttrigger->Action1.Trigger.Set_Raw(39);\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scg05eb.ini\") == 0) {\n\t\tTeamTypeClass* spy1_team = TeamTypeClass::From_Name(\"spy1\");\n\t\tassert(spy1_team != NULL);\n\t\tspy1_team->MissionList[spy1_team->MissionCount].Mission = TMISSION_SET_GLOBAL;\n\t\tspy1_team->MissionList[spy1_team->MissionCount].Data.Value = 16;\n\t\tspy1_team->MissionCount++;\n\n\t\tTriggerTypeClass* los3_trigger = new TriggerTypeClass();\n\t\tlos3_trigger->IsPersistant = TriggerTypeClass::VOLATILE;\n\t\tlos3_trigger->House = HOUSE_GREECE;\n\t\tlos3_trigger->EventControl = MULTI_AND;\n\t\tlos3_trigger->ActionControl = MULTI_AND;\n\t\tlos3_trigger->Event1.Event = TEVENT_GLOBAL_SET;\n\t\tlos3_trigger->Event1.Data.Value = 16;\n\t\tlos3_trigger->Event2.Event = TEVENT_ALL_DESTROYED;\n\t\tlos3_trigger->Event2.Data.House = HOUSE_GREECE;\n\t\tlos3_trigger->Action1.Action = TACTION_LOSE;\n\t\tlos3_trigger->Action1.Data.Value = -255;\n\t\tlos3_trigger->Action2.Action = TACTION_NONE;\n\t\tlos3_trigger->Action2.Data.Value = -1;\n\n\t\tTriggerTypeClass* frc1_trigger = TriggerTypeClass::From_Name(\"frc1\");\n\t\tassert(frc1_trigger != NULL);\n\t\tfrc1_trigger->Action1.Trigger = los3_trigger;\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scg08ea.ini\") == 0) {\n\t\tfor (int house = HOUSE_FIRST; house < HOUSE_COUNT; ++house) {\n\t\t\tHouseClass* ptr = Houses.Ptr(house);\n\t\t\tif (ptr != NULL && ptr->IsActive) {\n\t\t\t\tif (ptr->Class->House == HOUSE_GREECE || ptr->Class->House == HOUSE_GERMANY) {\n\t\t\t\t\tptr->Make_Ally(HOUSE_GERMANY);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scg09ea.ini\") == 0) {\n\t\tTriggerTypeClass* spyd_trigger = TriggerTypeClass::From_Name(\"Spyd\");\n\t\tassert(spyd_trigger != NULL);\n\n\t\tTriggerTypeClass* kos_trigger = new TriggerTypeClass();\n\t\tkos_trigger->IsPersistant = spyd_trigger->IsPersistant;\n\t\tkos_trigger->House = spyd_trigger->House;\n\t\tkos_trigger->EventControl = MULTI_LINKED;\n\t\tkos_trigger->ActionControl = MULTI_ONLY;\n\t\tkos_trigger->Event1.Event = spyd_trigger->Event1.Event;\n\t\tkos_trigger->Event1.Data = spyd_trigger->Event1.Data;\n\t\tkos_trigger->Event2.Event = TEVENT_DESTROYED;\n\t\tkos_trigger->Event2.Data.Value = 0;\n\t\tkos_trigger->Action1.Action = TACTION_SET_GLOBAL;\n\t\tkos_trigger->Action1.Data.Value = 22;\n\t\tkos_trigger->Action2.Action = TACTION_SET_GLOBAL;\n\t\tkos_trigger->Action2.Data.Value = 23;\n\n\t\tspyd_trigger->Event1.Event = TEVENT_GLOBAL_SET;\n\t\tspyd_trigger->Event1.Data.Value = 22;\n\n\t\tfor (int index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass* building = Buildings.Ptr(index);\n\t\t\tif (building->Trigger.Is_Valid() && (building->Trigger->Class == spyd_trigger)) {\n\t\t\t\tbuilding->Attach_Trigger(Find_Or_Make(kos_trigger));\n\t\t\t}\n\t\t}\n\n\t\tTriggerTypeClass* los3_trigger = new TriggerTypeClass();\n\t\tlos3_trigger->IsPersistant = spyd_trigger->IsPersistant;\n\t\tlos3_trigger->House = spyd_trigger->House;\n\t\tlos3_trigger->EventControl = MULTI_AND;\n\t\tlos3_trigger->ActionControl = MULTI_AND;\n\t\tlos3_trigger->Event1.Event = TEVENT_GLOBAL_SET;\n\t\tlos3_trigger->Event1.Data.Value = 23;\n\t\tlos3_trigger->Event2.Event = TEVENT_GLOBAL_CLEAR;\n\t\tlos3_trigger->Event2.Data.Value = 22;\n\t\tlos3_trigger->Action1.Action = TACTION_LOSE;\n\t\tlos3_trigger->Action1.Data.Value = -255;\n\t\tlos3_trigger->Action2.Action = TACTION_TEXT_TRIGGER;\n\t\tlos3_trigger->Action2.Data.Value = 54;\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scu46ea.ini\") == 0) {\n\t\tScen.Waypoint[20] = 9915;\n\t\tScen.Waypoint[21] = 9919;\n\t\tMap[Scen.Waypoint[20]].IsWaypoint = 1;\n\t\tMap[Scen.Waypoint[21]].IsWaypoint = 1;\n\n\t\tTeamTypeClass* rnf1_team = TeamTypeClass::From_Name(\"rnf1\");\n\t\tassert(rnf1_team != NULL);\n\t\trnf1_team->MissionList[0].Data.Value = 20;\n\n\t\tTeamTypeClass* rnf2_team = TeamTypeClass::From_Name(\"rnf2\");\n\t\tassert(rnf2_team != NULL);\n\t\trnf2_team->MissionList[0].Data.Value = 21;\n\t}\n\n\tif (_stricmp(Scen.ScenarioName, \"scu42ea.ini\") == 0) {\n\t\tBuildingTypeClass::As_Reference(STRUCT_PILLBOX).IsCaptureable = false;\n\t}\n\n\tif ((_stricmp(Scen.ScenarioName, \"scu35ea.ini\") == 0) || (_stricmp(Scen.ScenarioName, \"scu47ea.ini\") == 0)) {\n\t\tWeaponTypeClass::As_Pointer(Weapon_From_Name(\"Sniper\"))->Burst = 2;\n\t}\n\n\t/*\n\t**\tMulti-player last-minute fixups:\n\t**\t- If computer players are disabled, remove all computer-owned houses\n\t**\t- If bases are disabled, create the scenario dynamically\n\t**\t- Remove any flag spot overlays lying around\n\t**\t- If capture-the-flag is enabled, assign flags to cells.\n\t*/\n\tif (Session.Type != GAME_NORMAL /*|| Scen.ScenPlayer == SCEN_PLAYER_2PLAYER || Scen.ScenPlayer == SCEN_PLAYER_MPLAYER*/) {\n\n\t\t/*\n\t\t**\tIf Ghosts are disabled and we're not editing, remove computer players\n\t\t**\t(Must be done after all objects are read in from the INI)\n\t\t*/\n\t\tif ( (Session.Options.AIPlayers + Session.Players.Count() < Rule.MaxPlayers) && !Debug_Map) {\n\t\t\tRemove_AI_Players();\n\t\t}\n\n\t\t/*\n\t\t**\tUnits must be created for each house.  If bases are ON, this routine\n\t\t**\twill create an MCV along with the units; otherwise, it will just create\n\t\t**\ta whole bunch of units.  Session.Options.UnitCount is the total # of units\n\t\t**\tto create.\n\t\t*/\n\t\tif (!Debug_Map) {\n\t\t\tint save_init = ScenarioInit;\t\t\t// turn ScenarioInit off\n\t\t\tScenarioInit = 0;\n\t\t\tCreate_Units(ini.Get_Bool(\"Basic\", \"Official\", false));\n\t\t\tScenarioInit = save_init;\t\t\t\t// turn ScenarioInit back on\n\t\t}\n\n\t\t/*\n\t\t**\tPlace crates if random crates are enabled for\n\t\t**\tthis scenario.\n\t\t*/\n\t\tif (Session.Options.Goodies) {\n\t\t\tint count = max(Rule.CrateMinimum, Session.NumPlayers);\n\t\t\tcount = min(count, Rule.CrateMaximum);\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tMap.Place_Random_Crate();\n\t\t\t}\n\t\t}\n\t}\n\n\tCall_Back();\n\n\t/*\n\t**\tReturn with flag saying that the scenario file was read.\n\t*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98 - Added runtime check.\n\tif( Is_Aftermath_Installed() )\n\t{\n\t\tif (Session.Type == GAME_SKIRMISH || Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\t\tbAftermathMultiplayer = NewUnitsEnabled = OverrideNewUnitsEnabled;\n\t\t}\n\t}\t\n#endif\n\tScenarioInit--;\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * Write_Scenario_INI -- Write the scenario INI file.                                          *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      root      root filename for the scenario                                               *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/07/1992 JLB : Created.                                                                 *\n *   05/11/1995 JLB : Updates movie data.                                                      *\n *=============================================================================================*/\nvoid Write_Scenario_INI(char * fname)\n{\n#ifndef CHEAT_KEYS\n\tfname = fname;\n#else\n//\tCCFileClass file(fname);\n\n\tCCINIClass ini;\n\n\t/*\n\t**\tPreload the old scenario if it is present because there may\n\t**\tbe some fields in the INI that are processed but not written\n\t**\tout. Preloading the scenario will preserve these manually\n\t**\tmaintained entries.\n\t*/\n\tif (CCFileClass(fname).Is_Available()) {\n\t\tini.Load(CCFileClass(fname), true);\n\t}\n\n\tstatic char const * const BASIC = \"Basic\";\n\tini.Clear(BASIC);\n\tini.Put_String(BASIC, \"Name\", Scen.Description);\n\tini.Put_VQType(BASIC, \"Intro\", Scen.IntroMovie);\n\tini.Put_VQType(BASIC, \"Brief\", Scen.BriefMovie);\n\tini.Put_VQType(BASIC, \"Win\", Scen.WinMovie);\n\tini.Put_VQType(BASIC, \"Lose\", Scen.LoseMovie);\n\tini.Put_VQType(BASIC, \"Action\", Scen.ActionMovie);\n\tini.Put_HousesType(BASIC, \"Player\", PlayerPtr->Class->House);\n\tini.Put_ThemeType(BASIC, \"Theme\", Scen.TransitTheme);\n\tini.Put_Fixed(BASIC, \"CarryOverMoney\", Scen.CarryOverPercent);\n\tini.Put_Bool(BASIC, \"ToCarryOver\", Scen.IsToCarryOver);\n\tini.Put_Bool(BASIC, \"ToInherit\", Scen.IsToInherit);\n\tini.Put_Bool(BASIC, \"TimerInherit\", Scen.IsInheritTimer);\n\tini.Put_Bool(BASIC, \"CivEvac\", Scen.IsTanyaEvac);\n\tini.Put_Int(BASIC, \"NewINIFormat\", 3);\n\tini.Put_Int(BASIC, \"CarryOverCap\", Scen.CarryOverCap/100);\n\tini.Put_Bool(BASIC, \"EndOfGame\", Scen.IsEndOfGame);\n\tini.Put_Bool(BASIC, \"NoSpyPlane\", Scen.IsNoSpyPlane);\n\tini.Put_Bool(BASIC, \"SkipScore\", Scen.IsSkipScore);\n\tini.Put_Bool(BASIC, \"OneTimeOnly\", Scen.IsOneTimeOnly);\n\tini.Put_Bool(BASIC, \"SkipMapSelect\", Scen.IsNoMapSel);\n\tini.Put_Bool(BASIC, \"Official\", true);\n\tini.Put_Bool(BASIC, \"FillSilos\", Scen.IsMoneyTiberium);\n\tini.Put_Bool(BASIC, \"TruckCrate\", Scen.IsTruckCrate);\n\tini.Put_Int(BASIC, \"Percent\", Scen.Percent);\n\n\tHouseClass::Write_INI(ini);\n\tTeamTypeClass::Write_INI(ini);\n\tTriggerTypeClass::Write_INI(ini);\n\tMap.Write_INI(ini);\n\tTerrainClass::Write_INI(ini);\n\tUnitClass::Write_INI(ini);\n\tVesselClass::Write_INI(ini);\n\tInfantryClass::Write_INI(ini);\n\tBuildingClass::Write_INI(ini);\n\tBase.Write_INI(ini);\n\tOverlayClass::Write_INI(ini);\n\tSmudgeClass::Write_INI(ini);\n\n\tif (strlen(Scen.BriefingText)) {\n\t\tini.Put_TextBlock(\"Briefing\", Scen.BriefingText);\n\t}\n//\tsprintf(fname, \"%s.INI\", root);\n\tRawFileClass rawfile(fname);\n\tini.Save(rawfile, true);\n#endif\n}\n\n\n/***********************************************************************************************\n * Assign_Houses -- Assigns multiplayer houses to various players                              *\n *                                                                                             *\n * This routine assigns all players to a multiplayer house slot; it forms network connections  *\n * to each player.  The Connection ID used is the value for that player's HousesType.\t\t\t  *\n *                                                                                             *\n * PlayerPtr is also set here.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *\t\tThis routine assumes the 'Players' vector has been properly filled in with players'\t\t  *\n *\t\tnames, addresses, color, etc.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *\t\tAlso, it's assumed that the HouseClass's have all been created & initialized.\t\t\t\t  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *   07/14/1995 JLB : Records name of player in house structure.                               *\n *=============================================================================================*/\nvoid Assign_Houses(void)\n{\n\tint assigned[MAX_PLAYERS];\n\tint color_used[8];\n\tint i,j;\n\tHousesType house;\n\tHouseClass * housep;\n\tint lowest_color;\n\tint index;\n\tHousesType pref_house;\n\tint color;\n\n\t//------------------------------------------------------------------------\n\t// Initialize\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\tassigned[i] = 0;\n\t\tcolor_used[i] = 0;\n\t}\n\n//\tdebugprint( \"Assign_Houses()\\n\" );\n\t//------------------------------------------------------------------------\n\t// Assign each player in 'Players' to a multiplayer house.  Players will\n\t// be sorted by their chosen color value (this value must be unique among\n\t// all the players).\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.Players.Count(); i++) {\n\n\t\t//.....................................................................\n\t\t// Find the player with the lowest color index\n\t\t//.....................................................................\n\t\tindex = 0;\n\t\tlowest_color = 255;\n\t\tfor (j = 0; j < Session.Players.Count(); j++) {\n\t\t\t//..................................................................\n\t\t\t// If we've already assigned this house, skip it.\n\t\t\t//..................................................................\n\t\t\tif (assigned[j]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (Session.Players[j]->Player.Color < lowest_color) {\n\t\t\t\tlowest_color = Session.Players[j]->Player.Color;\n\t\t\t\tindex = j;\n\t\t\t}\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Mark this player as having been assigned.\n\t\t//.....................................................................\n\t\tassigned[index] = 1;\n\t\tcolor_used[Session.Players[index]->Player.Color] = 1;\n\n\t\t//.....................................................................\n\t\t// Assign the lowest-color'd player to the next available slot in the\n\t\t// HouseClass array.\n\t\t//.....................................................................\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tmemset((char *)housep->IniName, 0, MPLAYER_NAME_MAX);\n\t\tstrncpy((char *)housep->IniName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tMake another copy of name, permanent throughout entire game.\n\t\tstrncpy((char *)housep->InitialName, Session.Players[index]->Name, MPLAYER_NAME_MAX - 1);\n#endif\n\t\thousep->IsHuman = true;\n\t\thousep->Init_Data((PlayerColorType)(Session.Players[index]->Player.Color),\n\t\t\tSession.Players[index]->Player.House, Session.Options.Credits);\n\t\tif (index == 0) {\n\t\t\tPlayerPtr = housep;\n\t\t}\n\t\t/*\n\t\t**\tConvert the build level into an actual tech level to assign to the house.\n\t\t**\tThere isn't a one-to-one correspondence.\n\t\t*/\n\t\thousep->Control.TechLevel = _build_tech[BuildLevel];\n\n\t\thousep->Assign_Handicap(Scen.Difficulty);\n\n\t\t//.....................................................................\n\t\t// Record where we placed this player\n\t\t//.....................................................................\n\t\tSession.Players[index]->Player.ID = house;\n\n//\t\tdebugprint( \"Assigned ID of %i to %s\\n\", house, Session.Players[index]->Name );\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Now assign computer players to the remaining houses.\n\t//------------------------------------------------------------------------\n\tfor (i = Session.Players.Count(); i < Session.Players.Count() + Session.Options.AIPlayers; i++) {\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (Percent_Chance(50)) {\n\t\t\tpref_house = HOUSE_GREECE;\n\t\t} else {\n\t\t\tpref_house = HOUSE_USSR;\n\t\t}\n\n\t\t//.....................................................................\n\t\t// Pick a color for this house; keep looping until we find one.\n\t\t//.....................................................................\n\t\twhile (1) {\n\t\t\tcolor = Random_Pick(0, 7);\n\t\t\tif (color_used[color] == false) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcolor_used[color] = true;\n\n\t\t//.....................................................................\n\t\t// Set up the house\n\t\t//.....................................................................\n//\t\thousep->Control.MaxUnit = 80;\n//\t\thousep->Control.MaxInfantry = 60;\n//\t\thousep->Control.MaxBuilding = 60;\n//\t\thousep->Control.MaxVessel = 60;\n\t\thousep->IsHuman = false;\n\t\thousep->IsStarted = true;\n\n\t\tstrcpy(housep->IniName, Text_String(TXT_COMPUTER));\n\n\t\tif (Session.Type != GAME_NORMAL) {\n\t\t\thousep->IQ = Rule.MaxIQ;\n\t\t}\n\n\t\thousep->Init_Data((PlayerColorType)color, pref_house, Session.Options.Credits);\n\t\thousep->Control.TechLevel = _build_tech[BuildLevel];\n//\t\thousep->Control.TechLevel = BuildLevel;\n\n\t\tDiffType difficulty = Scen.CDifficulty;\n\n\t\tif (Session.Players.Count() > 1 && Rule.IsCompEasyBonus && difficulty > DIFF_EASY) {\n\t\t\tdifficulty = (DiffType)(difficulty - 1);\n\t\t}\n\t\thousep->Assign_Handicap(difficulty);\n\t}\n\n\tfor (i = Session.Players.Count()+Session.Options.AIPlayers; i < Rule.MaxPlayers; i++) {\n\t\thouse = (HousesType)(i + HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer(house);\n\t\tif (housep != NULL) {\n\t\t\thousep->IsDefeated = true;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Remove_AI_Players -- Removes the computer AI houses & their units                           *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      none.                                                                                  *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic void Remove_AI_Players(void)\n{\n\tint i;\n\tint aicount = 0;\n\tHousesType house;\n\tHouseClass * housep;\n\n#if (0)\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\thouse = (HousesType)(i + (int)HOUSE_MULTI1);\n\t\thousep = HouseClass::As_Pointer (house);\n\t\tif (housep->IsHuman == false) {\n\t\t\taicount++;\n\t\t\tif(aicount > Session.Options.AIPlayers) {\n\t\t\t\thousep->Clobber_All();\n\t\t\t}\n\t\t}\n\t}\n#else\n\t/*\n\t** AI players are set up like human players now. ST - 8/13/2019 1:32PM\n\t*/\n\tfor (i = 0; i < MAX_PLAYERS; i++) {\n\t\tif (i >= Session.Players.Count()) {\n\t\t\thouse = (HousesType)(i + (int)HOUSE_MULTI1);\n\t\t\thousep = HouseClass::As_Pointer (house);\n\t\t\tif (housep->IsHuman == false) {\n\t\t\t\thousep->Clobber_All();\n\t\t\t}\n\t\t}\n\t}\n\n#endif\n}\n\n\n#define USE_GLYPHX_START_LOCATIONS 1\n\n\n/***********************************************************************************************\n * Create_Units -- Creates infantry & units, for non-base multiplayer                          *\n *                                                                                             *\n * This routine uses data tables to determine which units to create for either                 *\n * a GDI or NOD house, and how many of each.                                                   *\n *                                                                                             *\n * It also sets each house's FlagHome & FlagLocation to the Waypoint selected                  *\n * as that house's \"home\" cell.                                                                *\n *                                                                                             *\n * INPUT:   official -- Directs the placement logic to use the full set of waypoints rather    *\n *                      than biasing toward the first four.                                    *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      none.                                                                                  *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic int ReserveInfantryIndex = 0;\nstatic void Reserve_Infantry()\n{\n\tif (Infantry.Count() == Infantry.Length()) {\n\t\tdelete Infantry.Ptr(ReserveInfantryIndex);\n\t\tReserveInfantryIndex = (ReserveInfantryIndex + 1) % Infantry.Length();\n\t}\n}\n\nstatic int ReserveUnitIndex = 0;\nstatic void Reserve_Unit()\n{\n\tif (Units.Count() == Units.Length()) {\n\t\tdelete Units.Ptr(ReserveUnitIndex);\n\t\tReserveUnitIndex = (ReserveUnitIndex + 1) % Units.Length();\n\t}\n}\n\nstatic void Create_Units(bool official)\n{\n\tstatic struct {\n\t\tint MinLevel;\n\t\tUnitType AllyType[2];\n\t\tUnitType SovietType[2];\n\t} utable[] = {\n\t\t{4,\t{UNIT_MTANK2,   UNIT_LTANK}, \t{UNIT_MTANK,\t\t UNIT_NONE}},\n\t\t{5,\t{UNIT_APC,      UNIT_NONE},  \t{UNIT_V2_LAUNCHER, UNIT_NONE}},\n\t\t{8,\t{UNIT_ARTY,     UNIT_JEEP},  \t{UNIT_MTANK,\t\t UNIT_NONE}},\n\t\t{10,\t{UNIT_MTANK2,   UNIT_MTANK2},\t{UNIT_HTANK,\t\t UNIT_NONE}}\n\t};\n\tstatic int num_units[ARRAY_SIZE(utable)];\t\t// # of each type of unit to create\n\tint tot_units;\t\t\t\t\t\t\t\t\t\t\t\t// total # units to create\n\n\tstatic struct {\n\t\tint MinLevel;\n\t\tint AllyCount;\n\t\tInfantryType AllyType;\n\t\tint SovietCount;\n\t\tInfantryType SovietType;\n\t} itable[] = {\n\t\t{0,\t1,INFANTRY_E1,\t\t\t\t1,INFANTRY_E1},\n\t\t{2,\t1,INFANTRY_E3,\t\t\t\t1,INFANTRY_E2},\n\t\t{4,\t1,INFANTRY_E3,\t\t\t\t1,INFANTRY_E4},\n\n// removed because of bug B478 (inappropriate infantry given in a bases off scenario).\n//\t\t{5,\t1,INFANTRY_RENOVATOR,\t1,INFANTRY_RENOVATOR},\n//\t\t{6,\t1,INFANTRY_SPY,\t\t\t1,INFANTRY_DOG},\n//\t\t{10,\t1,INFANTRY_THIEF,\t\t\t1,INFANTRY_DOG},\n//\t\t{12,\t1,INFANTRY_MEDIC,\t\t\t2,INFANTRY_DOG}\n\t};\n\tstatic int num_infantry[ARRAY_SIZE(itable)];// # of each type of infantry to create\n\tint tot_infantry;\t\t\t\t\t\t\t\t\t\t\t// total # infantry to create\n\n\n\tCELL centroid;\t\t\t// centroid of this house's stuff\n\tCELL centerpt;\t\t\t// centroid for a category of objects, as a CELL\n\n\tint u_limit=0;\t\t\t// last allowable index of units for this BuildLevel\n\tint i_limit=0;\t\t\t// last allowable index of infantry for this BuildLevel\n\tTechnoClass * obj;\t\t// newly-created object\n\tint i,j,k;\t\t\t\t// loop counters\n\tint scaleval;\t\t\t// value to scale # units or infantry\n\n\tReserveInfantryIndex = ReserveUnitIndex = 0;\n\n\t/*\n\t**\tFor the current BuildLevel, find the max allowable index into the tables\n\t*/\n\tfor (i = 0; i < ARRAY_SIZE(utable); i++) {\n\t\tif (PlayerPtr->Control.TechLevel >= utable[i].MinLevel) {\n\t\t\tu_limit = i+1;\n\t\t}\n\t}\n\tfor (i = 0; i < ARRAY_SIZE(itable); i++) {\n\t\tif (PlayerPtr->Control.TechLevel >= itable[i].MinLevel) {\n\t\t\ti_limit = i+1;\n\t\t}\n\t}\n\n\t/*\n\t**\tCompute how many of each buildable category to create\n\t*/\n\t/*\n\t**\tCompute allowed # units\n\t*/\n\ttot_units = (Session.Options.UnitCount * 2) / 3;\n\tif (u_limit == 0) tot_units = 0;\n\n\t/*\n\t**\tInit # of each category to 0\n\t*/\n\tfor (i = 0; i < u_limit; i++) {\n\t\tnum_units[i] = 0;\n\t}\n\n\t/*\n\t**\tIncrement # of each category, until we've used up all units\n\t*/\n\tj = 0;\n\tfor (i = 0; i < tot_units; i++) {\n\t\tnum_units[j]++;\n\t\tj++;\n\t\tif (j >= u_limit) {\n\t\t\tj = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tCompute allowed # infantry\n\t*/\n\ttot_infantry = Session.Options.UnitCount - tot_units;\n\n\t/*\n\t**\tInit # of each category to 0\n\t*/\n\tfor (i = 0; i < i_limit; i++) {\n\t\tnum_infantry[i] = 0;\n\t}\n\n\t/*\n\t**\tIncrement # of each category, until we've used up all infantry\n\t*/\n\tj = 0;\n\tfor (i = 0; i < tot_infantry; i++) {\n\t\tnum_infantry[j]++;\n\t\tj++;\n\t\tif (j >= i_limit) {\n\t\t\tj = 0;\n\t\t}\n\t}\n\n\t/*\n\t**\tBuild a list of the valid waypoints. This normally shouldn't be\n\t**\tnecessary because the scenario level designer should have assigned\n\t**\tvalid locations to the first N waypoints, but just in case, this\n\t**\tloop verifies that.\n\t*/\n\n\tconst unsigned int MAX_STORED_WAYPOINTS = 26;\n\n\tbool taken[MAX_STORED_WAYPOINTS];\n\tCELL waypts[MAX_STORED_WAYPOINTS];\n\tassert(Rule.MaxPlayers < ARRAY_SIZE(waypts));\n\tint num_waypts = 0;\n\n\t/*\n\t**\tCalculate the number of waypoints (as a minimum) that will be lifted from the\n\t**\tmission file. Bias this number so that only the first 4 waypoints are used\n\t**\tif there are 4 or fewer players. Unofficial maps will pick from all the\n\t**\tavailable waypoints.\n\t*/\n#ifndef USE_GLYPHX_START_LOCATIONS\n\tint look_for = max(4, Session.Players.Count()+Session.Options.AIPlayers);\n\tif (!official) {\n\t\tlook_for = 8;\n\t}\n#else\n\t/*\n\t** We allow the users to choose from all available start positions, even on official maps. ST - 1/15/2020 9:19AM\n\t*/\n\tint look_for = Session.Players.Count();\n#endif\n\t\t\n\tfor (int waycount = 0; waycount < 26; waycount++) {\n//\tfor (int waycount = 0; waycount < max(4, Session.Players.Count()+Session.Options.AIPlayers); waycount++) {\n\t\tif (Scen.Waypoint[waycount] != -1) {\n\t\t\twaypts[num_waypts] = Scen.Waypoint[waycount];\n\t\t\ttaken[num_waypts] = false;\n\t\t\tnum_waypts++;\n\n\t\t\tif (num_waypts >= MAX_STORED_WAYPOINTS)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there are insufficient waypoints to account for all players, then randomly assign\n\t**\tstarting points until there is enough.\n\t*/\n\tint deficiency = look_for - num_waypts;\n//\tint deficiency = (Session.Players.Count() + Session.Options.AIPlayers) - num_waypts;\n\tif (deficiency > 0) {\n\t\tfor (int index = 0; index < deficiency; index++) {\n\t\t\tCELL trycell = XY_Cell(Map.MapCellX + Random_Pick(0, Map.MapCellWidth-1), Map.MapCellY + Random_Pick(0, Map.MapCellHeight-1));\n\n\t\t\ttrycell = Map.Nearby_Location(trycell, SPEED_TRACK);\n\t\t\twaypts[num_waypts] = trycell;\n\t\t\ttaken[num_waypts] = false;\n\t\t\tnum_waypts++;\n\t\t}\n\t}\n\n\t/*\n\t**\tLoop through all houses.  Computer-controlled houses, with Session.Options.Bases\n\t**\tON, are treated as though bases are OFF (since we have no base-building\n\t**\tAI logic.)\n\t*/\n\tint numtaken = 0;\n\tfor (HousesType house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + Session.MaxPlayers); house++) {\n\n\t\t/*\n\t\t**\tGet a pointer to this house; if there is none, go to the next house\n\t\t*/\n\t\tHouseClass * hptr = HouseClass::As_Pointer(house);\n\t\tif (hptr == NULL) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t**\tPick the starting location for this house. The first house just picks\n\t\t**\tone of the valid locations at random. The other houses pick the furthest\n\t\t**\twapoint from the existing houses.\n\t\t*/\n\t\tif (!UseGlyphXStartLocations) {\n\t\t\n\t\t\tif (numtaken == 0) {\n\t\t\t\tint pick = Random_Pick(0, num_waypts-1);\n\t\t\t\tcentroid = waypts[pick];\n\t\t\t\thptr->StartLocationOverride = pick;\n\t\t\t\ttaken[pick] = true;\n\t\t\t\tnumtaken++;\n\t\t\t} else {\n\n\t\t\t\t/*\n\t\t\t\t**\tSet all waypoints to have a score of zero in preparation for giving\n\t\t\t\t**\ta distance score to all waypoints.\n\t\t\t\t*/\n\t\t\t\tint score[26];\n\t\t\t\tmemset(score, '\\0', sizeof(score));\n\n\t\t\t\t/*\n\t\t\t\t**\tScan through all waypoints and give a score as a value of the sum\n\t\t\t\t**\tof the distances from this waypoint to all taken waypoints.\n\t\t\t\t*/\n\t\t\t\tfor (int index = 0; index < num_waypts; index++) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf this waypoint has not already been taken, then accumulate the\n\t\t\t\t\t**\tsum of the distance between this waypoint and all other taken\n\t\t\t\t\t**\twaypoints.\n\t\t\t\t\t*/\n\t\t\t\t\tif (!taken[index]) {\n\t\t\t\t\t\tfor (int trypoint = 0; trypoint < num_waypts; trypoint++) {\n\n\t\t\t\t\t\t\tif (taken[trypoint]) {\n\t\t\t\t\t\t\t\tscore[index] += Distance(Cell_Coord(waypts[index]), Cell_Coord(waypts[trypoint]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tNow find the waypoint with the largest score. This waypoint is the one\n\t\t\t\t**\tthat is furthest from all other taken waypoints.\n\t\t\t\t*/\n\t\t\t\tint best = 0;\n\t\t\t\tint bestvalue = 0;\n\t\t\t\tfor (int searchindex = 0; searchindex < num_waypts; searchindex++) {\n\t\t\t\t\tif (score[searchindex] > bestvalue || bestvalue == 0) {\n\t\t\t\t\t\tbestvalue = score[searchindex];\n\t\t\t\t\t\tbest = searchindex;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tAssign this best position to the house.\n\t\t\t\t*/\n\t\t\t\tcentroid = waypts[best];\n\t\t\t\thptr->StartLocationOverride = best;\n\t\t\t\ttaken[best] = true;\n\t\t\t\tnumtaken++;\n\t\t\t}\n\t\t} else {\n\t\t\t\n\t\t\t/*\n\t\t\t** New code that respects the start locations passed in from GlyphX.\n\t\t\t**\n\t\t\t** ST - 1/8/2020 3:39PM\n\t\t\t*/\n\t\t\tcentroid = waypts[hptr->StartLocationOverride];\n\t\t}\n\n\t\t/*\n\t\t**\tAssign the center of this house to the waypoint location.\n\t\t*/\n\t\thptr->Center = Cell_Coord(centroid);\n\n\t\t/*\n\t\t**\tIf Bases are ON, human & computer houses are treated differently\n\t\t*/\n\t\tif (Session.Options.Bases) {\n\n\t\t\t/*\n\t\t\t**\t- For a human-controlled house:\n\t\t\t**\t  - Set 'scaleval' to 1\n\t\t\t**\t  - Create an MCV\n\t\t\t**\t  - Attach a flag to it for capture-the-flag mode\n\t\t\t*/\n\t\t\tscaleval = 1;\n\t\t\tReserve_Unit();\n\t\t\tobj = new UnitClass (UNIT_MCV, house);\n\t\t\tif (!obj->Unlimbo(Cell_Coord(centroid), DIR_N)) {\n\t\t\t\tif (!Scan_Place_Object(obj, centroid)) {\n\t\t\t\t\tdelete obj;\n\t\t\t\t\tobj = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (obj != NULL) {\n\t\t\t\thptr->FlagHome = 0;\n\t\t\t\thptr->FlagLocation = 0;\n\t\t\t\tif (Special.IsCaptureTheFlag) {\n\t\t\t\t\thptr->Flag_Attach((UnitClass *)obj, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tIf bases are OFF, set 'scaleval' to 1 & create a Mobile HQ for\n\t\t\t**\tcapture-the-flag mode.\n\t\t\t*/\n\t\t\tscaleval = 1;\n#ifdef TOFIX\n\t\t\tif (Special.IsCaptureTheFlag) {\n\t\t\t\tobj = new UnitClass (UNIT_TRUCK, house);\n\t\t\t\tobj->Unlimbo(Cell_Coord(centroid), DIR_N);\n\t\t\t\thptr->FlagHome = 0;\t\t\t\t\t// turn house's flag off\n\t\t\t\thptr->FlagLocation = 0;\n\t\t\t}\n#endif\n\t\t}\n\n\t\t/*\n\t\t**\tCreate units for this house\n\t\t*/\n\t\tfor (i = 0; i < u_limit; i++) {\n\n\t\t\t/*\n\t\t\t**\tFind the center point for this category.\n\t\t\t*/\n\t\t\tcenterpt = Clip_Scatter(centroid, 4);\n\n\t\t\t/*\n\t\t\t**\tPlace objects; loop through all unit in this category\n\t\t\t*/\n\t\t\tfor (j = 0; j < num_units[i] * scaleval; j++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCreate an Ally unit\n\t\t\t\t*/\n\t\t\t\tif (hptr->ActLike != HOUSE_USSR && hptr->ActLike != HOUSE_UKRAINE) {\n\t\t\t\t\tfor (k = 0; k < 2; k++) if(utable[i].AllyType[k] != UNIT_NONE) {\n\t\t\t\t\t\tReserve_Unit();\n\t\t\t\t\t\tobj = new UnitClass (utable[i].AllyType[k], house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate a Soviet unit\n\t\t\t\t\t*/\n\t\t\t\t\tfor (k = 0; k < 2; k++) if(utable[i].SovietType[k] != UNIT_NONE) {\n\t\t\t\t\t\tReserve_Unit();\n\t\t\t\t\t\tobj = new UnitClass (utable[i].SovietType[k], house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tCreate infantry\n\t\t*/\n\t\tfor (i = 0; i < i_limit; i++) {\n\t\t\t/*\n\t\t\t**\tFind the center point for this category.\n\t\t\t*/\n\t\t\tcenterpt = Clip_Scatter(centroid, 4);\n\n\t\t\t/*\n\t\t\t**\tPlace objects; loop through all unit in this category\n\t\t\t*/\n\t\t\tfor (j = 0; j < num_infantry[i] * scaleval; j++) {\n\n\t\t\t\t/*\n\t\t\t\t**\tCreate Ally infantry (Note: Unlimbo calls Enter_Idle_Mode(), which\n\t\t\t\t**\tassigns the infantry to HUNT; we must use Set_Mission() to override\n\t\t\t\t**\tthis state.)\n\t\t\t\t*/\n\t\t\t\tif (hptr->ActLike != HOUSE_USSR && hptr->ActLike != HOUSE_UKRAINE) {\n\t\t\t\t\tfor (k = 0; k < itable[i].AllyCount; k++) {\n\t\t\t\t\t\tReserve_Infantry();\n\t\t\t\t\t\tobj = new InfantryClass (itable[i].AllyType, house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCreate Soviet infantry\n\t\t\t\t\t*/\n\t\t\t\t\tfor (k = 0; k < itable[i].SovietCount; k++) {\n\t\t\t\t\t\tReserve_Infantry();\n\t\t\t\t\t\tobj = new InfantryClass (itable[i].SovietType, house);\n\t\t\t\t\t\tif (!Scan_Place_Object(obj, centerpt)) {\n\t\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!hptr->IsHuman) {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD_AREA);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tobj->Set_Mission(MISSION_GUARD);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Scan_Place_Object -- places an object >near< the given cell                                 *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      obj      ptr to object to Unlimbo                                                      *\n *      cell      center of search area                                                        *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      true = object was placed; false = it wasn't                                            *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/09/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nint Scan_Place_Object(ObjectClass * obj, CELL cell)\n{\n\tint dist;\t\t\t\t// for object placement\n\tFacingType rot;\t\t// for object placement\n\tFacingType fcounter;\t// for object placement\n\tint tryval;\n\tCELL newcell;\n\tTechnoClass * techno;\n\tint skipit;\n\n\t/*\n\t**\tFirst try to unlimbo the object in the given cell.\n\t*/\n\tif (Map.In_Radar(cell)) {\n\t\ttechno = Map[cell].Cell_Techno();\n\t\tif (!techno || (techno->What_Am_I()==RTTI_INFANTRY &&\n\t\t\tobj->What_Am_I()==RTTI_INFANTRY)) {\n\t\t\tif (obj->Unlimbo(Cell_Coord(cell), DIR_N)) {\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tLoop through distances from the given center cell; skip the center cell.\n\t**\tFor each distance, try placing the object along each rotational direction;\n\t**\tif none are available, try each direction with a random scatter value.\n\t**\tIf that fails, go to the next distance.\n\t**\tThis ensures that the closest coordinates are filled first.\n\t*/\n\tfor (dist = 1; dist < 32; dist++) {\n\n\t\t/*\n\t\t**\tPick a random starting direction\n\t\t*/\n\t\trot = Random_Pick(FACING_N, FACING_NW);\n\n\t\t/*\n\t\t**\tTry all directions twice\n\t\t*/\n\t\tfor (tryval = 0 ; tryval < 2; tryval++) {\n\n\t\t\t/*\n\t\t\t**\tLoop through all directions, at this distance.\n\t\t\t*/\n\t\t\tfor (fcounter = FACING_N; fcounter <= FACING_NW; fcounter++) {\n\n\t\t\t\tskipit = false;\n\n\t\t\t\t/*\n\t\t\t\t**\tPick a coordinate along this directional axis\n\t\t\t\t*/\n\t\t\t\tnewcell = Clip_Move(cell, rot, dist);\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this is our second try at this distance, add a random scatter\n\t\t\t\t**\tto the desired cell, so our units aren't all aligned along spokes.\n\t\t\t\t*/\n\t\t\t\tif (tryval > 0) {\n\t\t\t\t\tnewcell = Clip_Scatter (newcell, 1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf, by randomly scattering, we've chosen the exact center, skip\n\t\t\t\t**\tit & try another direction.\n\t\t\t\t*/\n\t\t\t\tif (newcell==cell) {\n\t\t\t\t\tskipit = true;\n\t\t\t\t}\n\n\t\t\t\tif (!skipit) {\n\t\t\t\t\t/*\n\t\t\t\t\t**\tOnly attempt to Unlimbo the object if:\n\t\t\t\t\t**\t- there is no techno in the cell\n\t\t\t\t\t**\t- the techno in the cell & the object are both infantry\n\t\t\t\t\t*/\n\t\t\t\t\ttechno = Map[newcell].Cell_Techno();\n\t\t\t\t\tif (!techno || (techno->What_Am_I()==RTTI_INFANTRY &&\n\t\t\t\t\t\tobj->What_Am_I()==RTTI_INFANTRY)) {\n\t\t\t\t\t\tif (obj->Unlimbo(Cell_Coord(newcell), DIR_N)) {\n\t\t\t\t\t\t\treturn(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trot++;\n\t\t\t\tif (rot > FACING_NW) {\n\t\t\t\t\trot = FACING_N;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Clip_Scatter -- randomly scatters from given cell; won't fall off map                       *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell      cell to scatter from                                                         *\n *      maxdist   max distance to scatter                                                      *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      new cell number                                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic CELL Clip_Scatter(CELL cell, int maxdist)\n{\n\tint x,y;\n\tint xdist;\n\tint ydist;\n\tint xmin,xmax;\n\tint ymin,ymax;\n\n\t/*\n\t**\tGet X & Y coords of given starting cell\n\t*/\n\tx = Cell_X(cell);\n\ty = Cell_Y(cell);\n\n\t/*\n\t**\tCompute our x & y limits\n\t*/\n\txmin = Map.MapCellX;\n\txmax = xmin + Map.MapCellWidth - 1;\n\tymin = Map.MapCellY;\n\tymax = ymin + Map.MapCellHeight - 1;\n\n\t/*\n\t**\tAdjust the x-coordinate\n\t*/\n\txdist = Random_Pick(0, maxdist);\n\tif (Percent_Chance(50)) {\n\t\tx += xdist;\n\t\tif (x > xmax) {\n\t\t\tx = xmax;\n\t\t}\n\t} else {\n\t\tx -= xdist;\n\t\tif (x < xmin) {\n\t\t\tx = xmin;\n\t\t}\n\t}\n\n\t/*\n\t**\tAdjust the y-coordinate\n\t*/\n\tydist = Random_Pick(0, maxdist);\n\tif (Percent_Chance(50)) {\n\t\ty += ydist;\n\t\tif (y > ymax) {\n\t\t\ty = ymax;\n\t\t}\n\t} else {\n\t\ty -= ydist;\n\t\tif (y < ymin) {\n\t\t\ty = ymin;\n\t\t}\n\t}\n\n\treturn (XY_Cell(x, y));\n}\n\n\n/***********************************************************************************************\n * Clip_Move -- moves in given direction from given cell; clips to map                         *\n *                                                                                             *\n * INPUT:                                                                                      *\n *      cell      cell to start from                                                           *\n *      facing   direction to move                                                             *\n *      dist      distance to move                                                             *\n *                                                                                             *\n * OUTPUT:                                                                                     *\n *      new cell number                                                                        *\n *                                                                                             *\n * WARNINGS:                                                                                   *\n *      none.                                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/30/1995 BRR : Created.                                                                 *\n *=============================================================================================*/\nstatic CELL Clip_Move(CELL cell, FacingType facing, int dist)\n{\n\tint x,y;\n\tint xmin,xmax;\n\tint ymin,ymax;\n\n\t/*\n\t**\tGet X & Y coords of given starting cell\n\t*/\n\tx = Cell_X(cell);\n\ty = Cell_Y(cell);\n\n\t/*\n\t**\tCompute our x & y limits\n\t*/\n\txmin = Map.MapCellX;\n\txmax = xmin + Map.MapCellWidth - 1;\n\tymin = Map.MapCellY;\n\tymax = ymin + Map.MapCellHeight - 1;\n\n\t/*\n\t**\tAdjust the x-coordinate\n\t*/\n\tswitch (facing) {\n\t\tcase FACING_N:\n\t\t\ty -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_NE:\n\t\t\tx += dist;\n\t\t\ty -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_E:\n\t\t\tx += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_SE:\n\t\t\tx += dist;\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_S:\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_SW:\n\t\t\tx -= dist;\n\t\t\ty += dist;\n\t\t\tbreak;\n\n\t\tcase FACING_W:\n\t\t\tx -= dist;\n\t\t\tbreak;\n\n\t\tcase FACING_NW:\n\t\t\tx -= dist;\n\t\t\ty -= dist;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tClip to the map\n\t*/\n\tif (x > xmax)\n\t\tx = xmax;\n\tif (x < xmin)\n\t\tx = xmin;\n\n\tif (y > ymax)\n\t\ty = ymax;\n\tif (y < ymin)\n\t\ty = ymin;\n\n\treturn (XY_Cell(x, y));\n}\n\n\nvoid Disect_Scenario_Name(char const * name, int & scenario, ScenarioPlayerType & player, ScenarioDirType & dir, ScenarioVarType & var)\n{\n\tif (name == NULL) return;\n\n\t/*\n\t**\tFetch the scenario number.\n\t*/\n\tchar buf[3];\n\tmemcpy(buf, &name[3], 2);\n\tbuf[2] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\tchar first = buf[0];\n\tchar second = buf[1];\n\tif (first <= '9' && second <= '9') {\n\t\tscenario = atoi(buf);\n\t} else {\n\t\tif (first <= '9') {\n\t\t\tfirst -= '0';\n\t\t} else {\n\t\t\tif (first >= 'a' && first <= 'z') {\n\t\t\t\tfirst -= 'a';\n\t\t\t} else {\n\t\t\t\tfirst -= 'A';\n\t\t\t}\n\t\t}\n\t\tif (second <= '9') {\n\t\t\tsecond -= '0';\n\t\t} else {\n\t\t\tif (second >= 'a' && second <= 'z') {\n\t\t\t\tsecond = (second - 'a') + 10;\n\t\t\t} else {\n\t\t\t\tsecond = (second - 'A') + 10;\n\t\t\t}\n\t\t}\n\t\tscenario = (36 * first) + second;\n\t}\n#else\n\tscenario = atoi(buf);\n#endif\n\n\t/*\n\t**\tFetch the scenario player (side).\n\t*/\n\tplayer = SCEN_PLAYER_GREECE;\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_SPAIN).Prefix) {\n\t\tplayer = SCEN_PLAYER_SPAIN;\n\t}\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_GREECE).Prefix) {\n\t\tplayer = SCEN_PLAYER_GREECE;\n\t}\n\tif (name[2] == HouseTypeClass::As_Reference(HOUSE_USSR).Prefix) {\n\t\tplayer = SCEN_PLAYER_USSR;\n\t}\n\n\t/*\n\t**\tFetch the direction.\n\t*/\n\tdir = SCEN_DIR_EAST;\n\tif (name[5] == 'E') {\n\t\tdir = SCEN_DIR_EAST;\n\t} else {\n\t\tdir = SCEN_DIR_WEST;\n\t}\n\n\t/*\n\t**\tFetch the variation.\n\t*/\n\tvar = SCEN_VAR_A;\n\tvar = ScenarioVarType((name[6] - 'A') + SCEN_VAR_A);\n}"
  },
  {
    "path": "REDALERT/SCENARIO.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SCENARIO.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCENARIO.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/26/96                                                     *\n *                                                                                             *\n *                  Last Update : February 26, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SCENARIO_H\n#define SCENARIO_H\n\n\n/*\n**\tThis class holds the information about the current game being played. This information is\n**\tglobal to the scenario and is generally of a similar nature to the information that was held\n**\tin the controlling scenario INI file. It is safe to write this structure out as a whole since\n**\tit doesn't contain any embedded pointers.\n*/\nclass ScenarioClass {\n\tpublic:\n\n\t\t// Constructor.\n\t\tScenarioClass(void);\n\t\tvoid Set_Scenario_Name(int scenario, ScenarioPlayerType player, ScenarioDirType dir = SCEN_DIR_NONE, ScenarioVarType var = SCEN_VAR_NONE);\n\t\tvoid Set_Scenario_Name(char const * name);\n\n\t\tbool Set_Global_To(int global, bool value);\n\t\tvoid Do_BW_Fade(void);\n\t\tvoid Do_Fade_AI(void);\n\n\t\t/*\n\t\t**\tThis is the source of the random numbers used in the game. This controls\n\t\t**\tthe game logic and thus must be in sync with any networked machines.\n\t\t*/\n\t\tRandomClass RandomNumber;\n\n\t\t/*\n\t\t**\tThis is the difficulty setting of the game.\n\t\t*/\n\t\tDiffType Difficulty;\t\t\t// For human player.\n\t\tDiffType CDifficulty;\t\t// For computer players.\n\n\t\t/*\n\t\t**\tThis is the main mission timer. This is the timer that is reset at the\n\t\t**\tstart of the mission. It, effectively, holds the elapsed time of the\n\t\t**\tmission.\n\t\t*/\n\t\tTTimerClass<FrameTimerClass> Timer;\n\n\t\t/*\n\t\t**\tThis is an array of waypoints; each waypoint corresponds to a letter of\n\t\t** the alphabet, and points to a cell number.  -1 means unassigned.\n\t\t** The CellClass has a bit that tells if that cell has a waypoint attached to\n\t\t** it; the only way to find which waypoint it is, is to scan this array.  This\n\t\t** shouldn't be needed often; usually, you know the waypoint & you want the CELL.\n\t\t*/\n\t\tCELL Waypoint[WAYPT_COUNT];\n\n\t\t/*\n\t\t**\tThis holds the system wide mission countdown timer. Time based missions\n\t\t**\tare governed by this timer. Various trigger events can modify and examine\n\t\t**\tthis timer. The current value of this timer will display on the game\n\t\t**\tscreen.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> MissionTimer;\n\n\t\t/*\n\t\t**\tThe shroud regrowth (if enabled) is regulated by this timer. When the\n\t\t**\ttimer expires, the shroud will regrow one step.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> ShroudTimer;\n\n\t\t/*\n\t\t**\tThe scenario number.\n\t\t*/\n\t\tint Scenario;\n\n\t\t/*\n\t\t**\tThe theater of the current scenario.\n\t\t*/\n\t\tTheaterType Theater;\n\n\t\t/*\n\t\t**\tThe full name of the scenario (as it exists on disk).\n\t\t*/\n\t\tchar ScenarioName[_MAX_FNAME+_MAX_EXT];\n\n\t\t/*\n\t\t**\tDescription of the scenario.\n\t\t*/\n\t\tchar Description[DESCRIP_MAX];\n\n\t\t/*\n\t\t**\tThe filename of the introduction movie.\n\t\t*/\n\t\tVQType IntroMovie;\n\n\t\t/*\n\t\t**\tThe filename of the briefing movie.\n\t\t*/\n\t\tVQType BriefMovie;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is won.\n\t\t*/\n\t\tVQType WinMovie;\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is won.\n\t\t*/\n\t\tVQType WinMovie2;\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is won.\n\t\t*/\n\t\tVQType WinMovie3;\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is won.\n\t\t*/\n\t\tVQType WinMovie4;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play if the scenario is lost.\n\t\t*/\n\t\tVQType LoseMovie;\n\n\t\t/*\n\t\t**\tThe filename of the movie to play right after the briefing and\n\t\t**\tjust before the game.\n\t\t*/\n\t\tVQType ActionMovie;\n\n\t\t/*\n\t\t**\tThis is the full text of the briefing. This text will be\n\t\t**\tdisplayed when the player commands the \"restate mission\n\t\t**\tobjectives\" operation.\n\t\t*/\n\t\tchar BriefingText[1024];\n\n\t\t/*\n\t\t**\tThis is the theme to start playing at the beginning of the action\n\t\t**\tmovie. A score started in this fashion will continue to play as\n\t\t**\tthe game progresses.\n\t\t*/\n\t\tThemeType TransitTheme;\n\n\t\t/*\n\t\t**\tThe house that the player is to be (obsolete).\n\t\t*/\n\t\tHousesType PlayerHouse;\n\n\t\t/*\n\t\t**\tThe percentage of money that is allowed to be carried over into the\n\t\t**\tfollowing scenario.\n\t\t*/\n\t\tfixed CarryOverPercent;\n\n\t\t/*\n\t\t**\tThis is the amount of money that was left over in the previous\n\t\t**\tscenario.\n\t\t*/\n\t\tint CarryOverMoney;\n\n\t\t/*\n\t\t**\tThis specifies the maximum amount of money that is allowed to be\n\t\t**\tcarried over from the previous scenario. This limits the amount\n\t\t**\tregardless of what the carry over percentage is set to.\n\t\t*/\n\t\tint CarryOverCap;\n\n\t\t/*\n\t\t**\tThis is the percent that the computer controlled base is to be\n\t\t**\tbuilt up to at the scenario start.\n\t\t*/\n\t\tint Percent;\n\n\t\t/*\n\t\t**\tGlobal flags that are used in the trigger system and are persistent\n\t\t**\tover the course of the game.\n\t\t*/\n\t\tbool GlobalFlags[30];\n\n\t\t/*\n\t\t**\tThis records the bookmark view locations the player has recorded.\n\t\t*/\n\t\tCELL Views[4];\n\n\t\t/*\n\t\t**\tThis is the number of active passable bridges in the current game.\n\t\t*/\n\t\tint BridgeCount;\n\n\t\t/*\n\t\t**\tThis records the carry over timer value that is used when the mission\n\t\t**\tstarts (presuming the appropriate flag is set) and also used when the\n\t\t**\tscenario restarts.\n\t\t*/\n\t\tint CarryOverTimer;\n\n\t\t/*\n\t\t**\tIf a bridge has been destroyed, then this flag will be set to true.\n\t\t**\tIf there is a trigger that depends on this, it might be triggered.\n\t\t*/\n\t\tunsigned IsBridgeChanged:1;\n\n\t\t/*\n\t\t**\tIf a global has changed and global change trigger events must be\n\t\t**\tprocessed, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsGlobalChanged:1;\n\n\t\t/*\n\t\t**\tAre the buildings and units in this scenario to carry over into\n\t\t**\tsome (unspecified) later scenario and thus have to be recorded\n\t\t**\tat the end?\n\t\t*/\n\t\tunsigned IsToCarryOver:1;\n\n\t\t/*\n\t\t**\tIs this scenario to begin by taking the previously recorded\n\t\t**\tcarryover objects and creating them onto the map?\n\t\t*/\n\t\tunsigned IsToInherit:1;\n\n\t\t/*\n\t\t**\tIf Tanya or a civilian is to be automatically evacuated when they enter\n\t\t**\ta transport vehicle, then this flag will be true.\n\t\t*/\n\t\tunsigned IsTanyaEvac:1;\n\n\t\t/*\n\t\t** These variables are assigned to the chronosphere effect, and control\n\t\t** whether the palette should be fading towards b&w or towards color.\n\t\t*/\n\t\tunsigned IsFadingBW:1;\n\t\tunsigned IsFadingColor:1;\n\n\t\t/*\n\t\t**\tIf this scenario is to be the last mission of the game (for this side), then\n\t\t**\tthis flag will be true.\n\t\t*/\n\t\tunsigned IsEndOfGame:1;\n\n\t\t/*\n\t\t**\tIf the mission countdown timer is to be inherited from the previous\n\t\t**\tscenario, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsInheritTimer:1;\n\n\t\t/*\n\t\t**\tIf the spy plane is to be disabled in this scenario even though circumstances\n\t\t**\tmight otherwise indicate that it should appear, then this flag will be true.\n\t\t*/\n\t\tunsigned IsNoSpyPlane:1;\n\n\t\t/*\n\t\t**\tIf the score screen (and \"mission accomplished\" voice) is to be skipped when\n\t\t**\tthis scenario is finished, then this flag will be true.\n\t\t*/\n\t\tunsigned IsSkipScore:1;\n\n\t\t/*\n\t\t**\tIf this is to be a one time only mission such that when it is completed, the game\n\t\t**\twill return to the main menu, then this flag will be set to true.\n\t\t*/\n\t\tunsigned IsOneTimeOnly:1;\n\n\t\t/*\n\t\t**\tIf the map selection is to be skipped then this flag will be true. If this\n\t\t**\tins't a one time only scenario, then the next scenario will have the same\n\t\t**\tname as the current one but will be for variation \"B\".\n\t\t*/\n\t\tunsigned IsNoMapSel:1;\n\n\t\t/*\n\t\t**\tIf trucks are supposed to drop wood crates when they explode, then this flag\n\t\t**\twill be set to true.\n\t\t*/\n\t\tunsigned IsTruckCrate:1;\n\n\t\t/*\n\t\t**\tIf the initial money is to be assigned as ore in available silos, then\n\t\t**\tthis flag will be set to true.\n\t\t*/\n\t\tunsigned IsMoneyTiberium:1;\n\n\t\t/*\n\t\t**\tThis is the fading countdown timer.  As this timer counts down, the\n\t\t**\tfading to b&w or color will progress.  This timer represents a\n\t\t** percentage of the Options.Get_Saturation() to fade towards.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> FadeTimer;\n\n#ifdef FIXIT_VERSION_3\t\t\t//\tFor endgame auto-sonar pulse.\n\t\t//\tTimer to set the period for checking if an auto-sonar pulse should be performed.\n\t\t//\tThis will take place if a player has nothing but subs left in the game.\n\t\tCDTimerClass<FrameTimerClass> AutoSonarTimer;\n#endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\tbool\tbLocalProposesDraw;\t\t\t\t//\tTrue if the local player in a 2-player game has a draw offer extended.\n\t\tbool\tbOtherProposesDraw;\t\t\t\t//\tTrue if the other player in a 2-player game has a draw offer extended.\n#endif\n\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/SCORE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/SCORE.CPP 3     3/14/97 12:02a Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCORE.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : May 3, 1995   [BWG]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Call_Back_Delay -- Combines Call_Back() and Delay() functions                             *\n *   Draw_Bar_Graphs -- Draw \"Casualties\" bar graphs                                           *\n *   Draw_InfantryMan -- Draw one guy in score screen, update animation                        *\n *   Draw_Infantrymen -- Draw all the guys on the score screen                                 *\n *   New_Infantry_Anim -- Start up a new animation for one of the infantrymen                  *\n *   ScoreClass::Count_Up_Print -- Prints a number (up to its max) into a string, cleanly      *\n *   ScoreClass::DO_GDI_GRAPH -- Show # of people or buildings killed on GDI score screen      *\n *   ScoreClass::Delay -- Pauses waiting for keypress.                                         *\n *   ScoreClass::Presentation -- Main routine to display score screen.                         *\n *   ScoreClass::Print_Graph_Title -- Prints title on score screen.                            *\n *   ScoreClass::Print_Minutes -- Print out hours/minutes up to max                            *\n *   ScoreClass::Pulse_Bar_Graph -- Pulses the bargraph color.                                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif\n\n#include\t\"function.h\"\n\n#define SCORETEXT_X\t\t184\n#define SCORETEXT_Y\t\t8\n#define CASUALTY_Y\t\t88\n#define BUILDING_X\t\t256\n#define BUILDING_Y\t\t128\n#define BARGRAPH_X\t\t266\n#define MAX_BAR_X\t\t\t318\t\t// max possible is 319 because of bar's right shadow\n#define SIZEGBAR\t\t\t118\n#define HALLFAME_X\t\t11\n#define HALLFAME_Y\t\t120\n\n#define\tMULTISCOREX\t\t30\n\n#define TEDIT_FAME\t\t\t\t1\n#define NUMINFANTRYMEN\t\t\t10\n#define NUMFAMENAMES\t\t\t\t7\n#define MAX_FAMENAME_LENGTH\t11\n\n#ifndef WIN32\nextern short StreamLowImpact;\n#endif  //WIN32\n\nGraphicBufferClass *PseudoSeenBuff;\n\nstruct InfantryAnim {\n\tint xpos;\n\tint ypos;\n\tvoid const *shapefile;\n\tvoid const *remap;\n\tint anim;\n\tint stage;\n\tchar delay;\n\tInfantryTypeClass const *Class;\n} InfantryMan[NUMINFANTRYMEN];\nvoid Draw_InfantryMen(void);\nvoid Draw_InfantryMan(int index);\nvoid New_Infantry_Anim(int index, int anim);\nvoid Draw_Bar_Graphs(int i, int gkilled, int nkilled);\nvoid Animate_Cursor(int pos, int ypos);\nvoid Animate_Score_Objs(void);\nvoid Cycle_Wait_Click(bool cycle=true);\n\n#ifdef FIXIT_SCORE_CRASH\n//void Disable_Uncompressed_Shapes (void);\n//void Enable_Uncompressed_Shapes (void);\n#endif\t//FIXIT\n\nvoid const * Beepy6;\nint ControlQ;\t// cheat key to skip past score/mapsel screens\nbool StillUpdating;\n\n#ifdef WIN32\nchar *ScreenNames[2]={\"ALIBACKH.PCX\", \"SOVBACKH.PCX\"};\n#else\nchar *ScreenNames[2]={\"ALI-TRAN.WSA\", \"SOV-TRAN.WSA\"};\n#endif\n\n//#ifdef WIN32\n//TextBlitClass BlitList;\n//#endif\n\n\nstruct Fame {\n\tchar\tname[MAX_FAMENAME_LENGTH];\n\tint\tscore;\n\tint\tlevel;\n\tint\tside;\n};\n\nScoreAnimClass *ScoreObjs[MAXSCOREOBJS];\n\n\nScoreAnimClass::ScoreAnimClass(int x, int y, void const * data)\n{\n\tXPos = x * RESFACTOR;\n\tYPos = y * RESFACTOR;\n\tTimer = 0;\n\tDataPtr = data;\n}\n\n\nScoreTimeClass::ScoreTimeClass(int xpos, int ypos, void const * data, int maxval, int xtimer) :\n\tScoreAnimClass(xpos, ypos, data)\n{\n\tStage = 0;\n\tMaxStage = maxval;\n\tTimerReset = xtimer;\n}\n\nvoid ScoreTimeClass::Update(void)\n{\n#ifdef WIN32\n\tGraphicViewPortClass *oldpage;\n#else\n\tGraphicBufferClass *oldpage;\n#endif\n\tif (!Timer) {\n\t\tTimer = TimerReset;\n\t\tif (++Stage >= MaxStage) Stage = 0;\n\t\toldpage = LogicPage;\n\t\tSet_Logic_Page(SeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#endif\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\nScoreCredsClass::ScoreCredsClass(int xpos, int ypos, void const * data, int maxval, int xtimer) :\n\tScoreAnimClass(xpos, ypos, data)\n{\n\tStage = 0;\n\tMaxStage = maxval;\n\tTimerReset = xtimer;\n\tClock1 = MFCD::Retrieve(\"CLOCK1.AUD\");\n\tCashTurn = MFCD::Retrieve(\"CASHTURN.AUD\");\n}\n\n\nvoid ScoreCredsClass::Update(void)\n{\n#ifdef WIN32\n\tGraphicViewPortClass *oldpage;\n#else\n\tGraphicBufferClass *oldpage;\n#endif\n\tif (!Timer) {\n\t\tTimer = TimerReset;\n\t\tif (++Stage >= MaxStage) Stage = 0;\n\t\toldpage = LogicPage;\n\t\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\t\tPlay_Sample(Clock1, 255, Options.Normalize_Volume(130));\n#else\n\t\tPlay_Sample(Clock1, 255, Options.Normalize_Volume(50));\n#endif\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\tCC_Draw_Shape(DataPtr, Stage, XPos, YPos, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#endif\n\t\tSet_Logic_Page(oldpage);\n\t}\n}\n\n\nScorePrintClass::ScorePrintClass(int string, int xpos, int ypos, void const * palette, int background) :\n\tScoreAnimClass(xpos, ypos, Text_String(string))\n{\n\tBackground = background;\n\tPrimaryPalette = palette;\n\tStage = 0;\n}\n\n\nScorePrintClass::ScorePrintClass(void const * string, int xpos, int ypos, void const * palette, int background) :\n\tScoreAnimClass(xpos, ypos, string)\n{\n\tBackground = background;\n\tPrimaryPalette = palette;\n\tStage = 0;\n}\n\n\nvoid ScorePrintClass::Update(void)\n{\n\tstatic char localstr[2]={0,0};\n\tstatic char _whitepal[]={0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F};\n\n\tif (Stage && (((char *)DataPtr)[Stage-1]==0) ) {\n\t\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\t\tif (ScoreObjs[i] == this) {\n\t\t\t\tScoreObjs[i] = 0;\n\t\t\t}\n\t\t}\n\t\tdelete this;\n\t\treturn;\n\t}\n\n#ifdef WIN32\n\tStillUpdating = true;\n#endif\n\tif (!Timer) {\n\t\tTimer = 1;\n\n\t\tint pos = XPos+(Stage*(6*RESFACTOR));\n// print the letter properly\n\t\tif (Stage) {\n\t\t\tSet_Font_Palette(PrimaryPalette);\n\t\t\tlocalstr[0]=((char *)DataPtr)[Stage-1];\n\t\t\tHidPage.Print(localstr, pos-6*RESFACTOR, YPos,   TBLACK, TBLACK);\n\t\t\tHidPage.Blit(SeenPage, pos-6*RESFACTOR, YPos-1*RESFACTOR, pos-6*RESFACTOR, YPos-1*RESFACTOR, 7*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, pos-6*RESFACTOR, YPos-1*RESFACTOR, pos-6*RESFACTOR, YPos-1*RESFACTOR, 7*RESFACTOR, 8*RESFACTOR);\n\t\t\tPseudoSeenBuff->Print(localstr, pos-6*RESFACTOR, YPos,   TBLACK, TBLACK);\n#endif\n\t\t}\n\t\tif (((char *)DataPtr)[Stage]) {\n\t\t\tlocalstr[0]=((char *)DataPtr)[Stage];\n\t\t\tSet_Font_Palette(_whitepal);\n\t\t\tSeenPage.Print(localstr, pos,  YPos-1, TBLACK, TBLACK);\n\t\t\tSeenPage.Print(localstr, pos,  YPos+1, TBLACK, TBLACK);\n\t\t\tSeenPage.Print(localstr, pos+1, YPos  , TBLACK, TBLACK);\n#ifdef WIN32\n\t\t\tPseudoSeenBuff->Print(localstr, pos,  YPos-1, TBLACK, TBLACK);\n\t\t\tPseudoSeenBuff->Print(localstr, pos,  YPos+1, TBLACK, TBLACK);\n\t\t\tPseudoSeenBuff->Print(localstr, pos+1, YPos  , TBLACK, TBLACK);\n#endif\n\t\t}\n\t\tStage++;\n\t}\n}\n\n\nScoreScaleClass::ScoreScaleClass(void const * string, int xpos, int ypos, char const palette[]) :\n\tScoreAnimClass(xpos, ypos, string)\n{\n\tPalette = &palette[0];\n#ifdef WIN32\n\tStage = 0;\n#else\n\tStage = 5;\n#endif\n}\n\n\nvoid ScoreScaleClass::Update(void)\n{\n\tstatic int _destx[]={0,80,107,134,180,228};\n\tstatic int _destw[]={6,20, 30, 40, 60, 80};\n\n\t/*\n\t** Restore the background for the scaled-up letter\n\t*/\n\tif (!Timer) {\n\t\tTimer = 1;\n#ifndef WIN32\n\t\tif (Stage != 5) {\n\t\t\tint destx = _destx[Stage+1]*RESFACTOR;\n\t\t\tint destw = _destw[Stage+1]*RESFACTOR;\n\t\t\tHidPage.Blit(SeenPage, destx, YPos, destx, YPos, (destx + destw) <= 320 * RESFACTOR ? destw : (320 * RESFACTOR) - destx, (YPos + destw) <= 200 * RESFACTOR ? destw : (200 * RESFACTOR) - YPos);\n\t\t}\n#endif\n\t\tif (Stage) {\n\t\t\tSet_Font_Palette(Palette);\n\t\t\tHidPage.Fill_Rect(0, 0, 7*RESFACTOR, 7*RESFACTOR, TBLACK);\n\t\t\tHidPage.Print((char *)DataPtr, 0, 0,   TBLACK, TBLACK);\n\t\t\tHidPage.Scale(SeenPage, 0, 0, _destx[Stage]*RESFACTOR, YPos, 5*RESFACTOR, 6*RESFACTOR, _destw[Stage]*RESFACTOR, _destw[Stage]*RESFACTOR, true);\n\t\t\tStage--;\n\t\t} else {\n\t\t\tSet_Font_Palette(Palette);\n\t\t\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\t\t\tif (ScoreObjs[i]==this) ScoreObjs[i] = 0;\n\t\t\t}\n\t\t\tHidPage.Print((char *)DataPtr, XPos, YPos,   TBLACK, TBLACK);\n\t\t\tHidPage.Blit(SeenPage, XPos, YPos, XPos, YPos, 6*RESFACTOR, 6*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, XPos, YPos, XPos, YPos, 6*RESFACTOR, 6*RESFACTOR);\n#endif\n\t\t\tdelete this;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nint Alloc_Object(ScoreAnimClass *obj)\n{\n\tint i,ret;\n\n\tfor (i = ret = 0; i < MAXSCOREOBJS; i++) {\n\t\tif (!ScoreObjs[i]) {\n\t\t\tScoreObjs[i] = obj;\n\t\t\tret = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn(ret);\n}\n\n\n\n/***********************************************************************************************\n * ScoreClass::Presentation -- Main routine to display score screen.                           *\n *                                                                                             *\n *    This is the main routine that displays the score screen graphics.                        *\n *    It gets called at the end of each scenario and is used to present                        *\n *    the results and a rating of the player's battle.                                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/02/1994     : Created.                                                                 *\n *=============================================================================================*/\nstatic unsigned char const  _bluepal[]={0xC0,0xC1,0xC1,0xC3,0xC2,0xC5,0xC3,0xC7,0xC4,0xC9,0xCA,0xCB,0xCC,0xCD,0xC0,0xCF};\nstatic unsigned char const _greenpal[]={0x70,0x71,0x7C,0x73,0x7D,0x75,0x7E,0x77,0x7F,0x79,0x7A,0x7B,0x7C,0x7D,0x7C,0x7F};\nstatic unsigned char const   _redpal[]={0xD0,0xD1,0xD7,0xD3,0xD9,0xD5,0xDA,0xD7,0xDB,0xD9,0xDA,0xDB,0xDC,0xDD,0xD6,0xDF};\nstatic unsigned char const _yellowpal[]={0x0,0x0,0xEC,0x0,0xEB,0x0,0xEA,0x0,0xE9,0x0,0x0,0x0,0x0,0x0,0xED,0x0};\nvoid ScoreClass::Presentation(void)\n{\n#if (0)//PG\n#ifdef WIN32\n//\tif (Keyboard != NULL) return;\n#endif\n\tstatic int const _casuax[2]={144,150};\n\tstatic int const _casuay[2]={ 78, 78};\n\tstatic int const _gditxy[2]={ 90, 90};\n\n#if defined(FRENCH) || defined(GERMAN)\n\tstatic int const _gditxx[2]={130,150};\n\tstatic int const _nodtxx[2]={130,150};\n#else\n\tstatic int const _gditxx[2]={135,150};\n\tstatic int const _nodtxx[2]={135,150};\n#endif\n\tstatic int const _nodtxy[2]={102,102};\n\tstatic int const _bldggy[2]={138,138};\n\tstatic int const _bldgny[2]={150,150};\n\n#ifdef WIN32\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tDisable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\tPseudoSeenBuff = new GraphicBufferClass(SeenBuff.Get_Width(),SeenBuff.Get_Height(),(void*)NULL);\n#endif\n\tint i;\n\tvoid const * yellowptr;\n\tvoid const * redptr;\n\tCCFileClass file(FAME_FILE_NAME);\n\tstruct Fame hallfame[NUMFAMENAMES];\n\tvoid *oldfont;\n\tint oldfontxspacing = FontXSpacing;\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\t\t// 0 or 1\n#ifdef WIN32\n\tchar inter_pal[15];\n\tsprintf(inter_pal, \"SCORPAL1.PAL\");\n#endif\n\n\tControlQ = 0;\n\tFontXSpacing = 0;\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tTheme.Queue_Song(THEME_SCORE);\n\n#ifdef WIN32\n\tVisiblePage.Clear();\n\tSysMemPage.Clear();\n\tWWMouse->Erase_Mouse(&HidPage, TRUE);\n\tHiddenPage.Clear();\n\tSet_Logic_Page(SysMemPage);\n#else\n\tSeenPage.Clear();\n\tHidPage.Clear();\n\tSet_Logic_Page(HidPage);\n#endif\n\tBlackPalette.Set();\n\n\n\tvoid const * country4 = MFCD::Retrieve(\"COUNTRY4.AUD\");\n\tvoid const * sfx4 = MFCD::Retrieve(\"SFX4.AUD\");\n\tBeepy6 = MFCD::Retrieve(\"BEEPY6.AUD\");\n\n\t/*\n\t** Load the background for the score screen\n\t*/\n#ifndef WIN32\n\tvoid *anim = Open_Animation(ScreenNames[house], NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), ScorePalette);\n#endif\n\n\tunsigned minutes = (unsigned)((ElapsedTime / (long)TIMER_MINUTE))+1;\n\n// Load up the shapes for the Nod score screen\n#ifdef WIN32\n\tyellowptr = MFCD::Retrieve(\"BAR3BHR.SHP\");\n\tredptr = MFCD::Retrieve(\"BAR3RHR.SHP\");\n#else\n\tif (!house) {\n\t\tyellowptr = MFCD::Retrieve(\"BAR3BLU.SHP\");\n\t\tredptr = MFCD::Retrieve(\"BAR3RED.SHP\");\n\t}\n#endif\n\n/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\tCall_Back();\n\n/* --- Now display the background animation --- */\n\tHide_Mouse();\n#ifdef WIN32\n\tLoad_Title_Screen(ScreenNames[house], &HidPage, ScorePalette);\n\tIncrease_Palette_Luminance (ScorePalette , 30, 30, 30, 63);\n\tHidPage.Blit(SeenPage);\n\tHidPage.Blit(*PseudoSeenBuff);\n#else\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\tScorePalette.Set(FADE_PALETTE_FAST, Call_Back);\n#ifdef WIN32\n\tPlay_Sample(country4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(country4, 255, Options.Normalize_Volume(60));\n#endif\n\n#ifndef WIN32\n\tint frame = 1;\n\tStreamLowImpact = true;\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n\t\tCall_Back_Delay(2);\n\t}\n\tStreamLowImpact = false;\n\tCall_Back();\n\tClose_Animation(anim);\n#endif\n\n\t/*\n\t** Background's up, so now load various shapes and animations\n\t*/\n#ifdef WIN32\n\tvoid const * timeshape = \t  MFCD::Retrieve(\"TIMEHR.SHP\");\n\tvoid const * hiscore1shape = MFCD::Retrieve(\"HISC1-HR.SHP\");\n\tvoid const * hiscore2shape = MFCD::Retrieve(\"HISC2-HR.SHP\");\n#else\n\tvoid const * timeshape = \t  MFCD::Retrieve(\"TIME.SHP\");\n\tvoid const * hiscore1shape = MFCD::Retrieve(\"HISCORE1.SHP\");\n\tvoid const * hiscore2shape = MFCD::Retrieve(\"HISCORE2.SHP\");\n#endif\n\tScoreObjs[0] = new ScoreTimeClass(238, 2, timeshape, 30, 4);\n\tScoreObjs[1] = new ScoreTimeClass(4, 89, hiscore1shape, 10, 4);\n\tScoreObjs[2] = new ScoreTimeClass(4, 180, hiscore2shape, 10, 4);\n\n\t/* Now display the stuff */\n#ifdef WIN32\n#else\n\tSeenPage.Blit(HidPage);\n#endif\n\tSet_Logic_Page(SeenBuff);\n\n\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TIME, 198,  9, _greenpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TIME, 204,  9, _greenpal));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_LEAD, 164, 26, _greenpal));\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_EFFI, 164, 38, _greenpal));\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOTA, 164, 50, _greenpal));\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tCall_Back_Delay(13);\n\n\tint scorecounter = 0;\n\n\tKeyboard->Clear();\n\n\t/*\n\t**\tDetermine leadership rating.\n\t*/\n\tint leadership = 0;\n\tfor (int index = 0; index < Logic.Count(); index++) {\n\t\tObjectClass * object = Logic[index];\n\t\tHousesType owner = object->Owner();\n\t\tif ( (house) && (owner == HOUSE_USSR || owner == HOUSE_BAD || owner == HOUSE_UKRAINE) ) {\n\t\t\tleadership++;\n\t\t} else {\n\t\t\tif ( (!house) && (object->Owner() == HOUSE_GREECE) ) {\n\t\t\t\tleadership++;\n\t\t\t}\n\t\t}\n\t}\n\tint uspoints = 0;\n\n\tfor (HousesType hous = HOUSE_SPAIN; hous <= HOUSE_BAD; hous++) {\n\t\tHouseClass *hows = HouseClass::As_Pointer(hous);\n\t\tif (hous == HOUSE_USSR || hous == HOUSE_BAD || hous == HOUSE_UKRAINE) {\n\t\t\tNKilled += hows->UnitsLost;\n\t\t\tNBKilled += hows->BuildingsLost;\n\t\t} else {\n\t\t\tGKilled += hows->UnitsLost;\n\t\t\tGBKilled += hows->BuildingsLost;\n\t\t}\n\t\tif (PlayerPtr->Is_Ally(hous) ) {\n\t\t\tuspoints += hows->PointTotal;\n\t\t}\n\t}\n//\tif(uspoints < 0) uspoints = 0;\n//\tuspoints += 1000; //BG 1000 bonus points for winning mission\n\n\t/*\n\t**\tBias the base score upward according to the difficulty level.\n\t*/\n\tswitch (PlayerPtr->Difficulty) {\n\t\tcase DIFF_EASY:\n\t\t\tuspoints += 500;\n\t\t\tbreak;\n\n\t\tcase DIFF_NORMAL:\n\t\t\tuspoints += 1500;\n\t\t\tbreak;\n\n\t\tcase DIFF_HARD:\n\t\t\tuspoints += 3500;\n\t\t\tbreak;\n\t}\n\n\n\tif (!leadership) leadership++;\n\tleadership = 100*fixed(leadership, (house ? NKilled+NBKilled+leadership : GKilled+GBKilled+leadership));\n\tleadership = min(150,leadership);\n\n\t/*\n\t**\tDetermine economy rating.\n\t*/\n\tint init = PlayerPtr->Control.InitialCredits;\n\tint cred = PlayerPtr->Available_Money();\n\n\tint economy = 100*fixed((unsigned)PlayerPtr->Available_Money()+1+PlayerPtr->StolenBuildingsCredits, PlayerPtr->HarvestedCredits + (unsigned)PlayerPtr->Control.InitialCredits+1);\n\teconomy=min(economy,150);\n\n\tint total = ((uspoints * leadership) / 100) + ((uspoints * economy) / 100);\n\tif (total < -9999) total = -9999;\n\ttotal = min(total, 99999);\n\nKeyboard->Clear();\n\tfor (i = 0; i <= 130; i++) {\n\t\tSet_Font_Palette(_greenpal);\n\t\tint lead = (leadership * i) / 100;\n\t\tCount_Up_Print(\"%3d%%\", lead, leadership,     244, 26);\n\t\tif (i>=30) {\n\t\t\tint econo = (economy * (i-30)) / 100;\n\t\t\tCount_Up_Print(\"%3d%%\", econo, economy, 244, 38);\n\t\t}\n\t\tPrint_Minutes(minutes);\n\t\tCall_Back_Delay(1);\n#ifdef WIN32\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(100));\n#else\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(40));\n#endif\n\t\tif ( (i >= 30) && (i >= leadership) && ((i-30) >= economy) ) break;\n//BG\t\tif (Keyboard->Check()) break;\n\t}\n\tCount_Up_Print(\"%3d%%\", leadership, leadership, 244, 26);\n\tCount_Up_Print(\"%3d%%\", economy,    economy,    244, 38);\n\n\tchar buffer[16];\n\tsprintf(buffer, \"x %5d\",uspoints);\n\tAlloc_Object(new ScorePrintClass(buffer, 274,  26, _greenpal));\n\tAlloc_Object(new ScorePrintClass(buffer, 274,  38, _greenpal));\n\tCall_Back_Delay(8);\n\tSeenBuff.Draw_Line(274*RESFACTOR, 48*RESFACTOR, 313*RESFACTOR, 48*RESFACTOR, WHITE);\n\tCall_Back_Delay(1);\n\tSeenBuff.Draw_Line(274*RESFACTOR, 48*RESFACTOR, 313*RESFACTOR, 48*RESFACTOR, GREEN);\n\n\tsprintf(buffer,\"%5d\", total);\n\tAlloc_Object(new ScorePrintClass(buffer, 286,  50, _greenpal));\n\n//BG\tif (!Keyboard->Check()) {\n\t\tCall_Back_Delay(60);\n//BG\t}\n\n\tif (house) Show_Credits(house, _greenpal);\n\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(60);\n\n\t/*\n\t** Show stats on # of units killed\n\t*/\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tint indx = house;\n#ifdef WIN32\n\tindx = 0;\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_CASU, _casuax[indx], _casuay[indx], _greenpal));\n\tCall_Back_Delay(9);\n\tif (house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _nodtxx[indx], _gditxy[indx], _redpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _nodtxy[indx], _bluepal));\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _gditxy[indx], _bluepal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _nodtxx[indx], _nodtxy[indx], _redpal));\n\t}\n\tCall_Back_Delay(6);\n\n\tSet_Font_Palette(_redpal);\n#ifdef WIN32\n\t\tDo_GDI_Graph(yellowptr, redptr, GKilled + CKilled, NKilled, 89);\n#else\n\tif (house) {\n\t\tDo_Nod_Casualties_Graph();\n\t} else {\n\t\tDo_GDI_Graph(yellowptr, redptr, GKilled + CKilled, NKilled, 89);\n\t}\n#endif\n\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t** Print out stats on buildings destroyed\n\t*/\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n#ifdef WIN32\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL, 144, 126, _greenpal));\n\t\tCall_Back_Delay(9);\n#else\n\tif (!house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL, 144, 126, _greenpal));\n\t\tCall_Back_Delay(9);\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL1, 150, 118, _greenpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SCORE_BUIL2, 150, 126, _greenpal));\n\t\tCall_Back_Delay(13);\n\t}\n#endif\n\tif(house) {\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _gditxx[indx], _bldggy[indx], _redpal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _bldgny[indx], _bluepal));\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_ALLIES, _gditxx[indx], _bldggy[indx], _bluepal));\n\t\tAlloc_Object(new ScorePrintClass(TXT_SOVIET, _gditxx[indx], _bldgny[indx], _redpal));\n\t}\n\tCall_Back_Delay(7);\n#ifdef WIN32\n\t\tDo_GDI_Graph(yellowptr, redptr, GBKilled + CBKilled, NBKilled, 137);\n#else\n\tif (house) {\n\t\tCall_Back_Delay(6);\n\t\tSet_Font_Palette(_greenpal);\n\t\tDo_Nod_Buildings_Graph();\n\t} else {\n\t\tDo_GDI_Graph(yellowptr, redptr, GBKilled + CBKilled, NBKilled, 137);\n\t}\n#endif\n\n#ifdef WIN32\n\t// Wait for text printing to complete\n\twhile (StillUpdating) {\n\t\tCall_Back_Delay(1);\n\t}\n#endif\n\n\tKeyboard->Clear();\n\n\tif (!house) Show_Credits(house, _greenpal);\n\t/*\n\t** Hall of fame display and processing\n\t*/\n#ifdef WIN32\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(150));\n#else\n\tPlay_Sample(sfx4, 255, Options.Normalize_Volume(60));\n#endif\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP, 28, 110, _greenpal));\n\tCall_Back_Delay(9);\n\n\t/*\n\t** First check for the existence of the file, and if there isn't one,\n\t** make a new one filled with blanks.\n\t*/\n\tif (!file.Is_Available()) {\n\n\t\t// hall of fame doesn't exist, so blank it out & write it\n\t\tfile.Open(WRITE);\n\n\t\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\t\thallfame[i].name[0] =\n\t\t\thallfame[i].score   =\n\t\t\thallfame[i].level   = 0;\n\t\t\thallfame[i].side\t  = 0;\n\t\t\tfile.Write(&hallfame[i], sizeof(struct Fame));\n\t\t}\n\n\t\tfile.Close();\n\t}\n\n\tfile.Open(READ);\n\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\tfile.Read(&hallfame[i], sizeof(struct Fame));\n\t}\n\tfile.Close();\n\n\t/*\n\t** If the player's score is good enough to bump someone off the list,\n\t** remove their data, move everyone down a notch, and set index = where\n\t** their info goes\n\t*/\n\tif (hallfame[NUMFAMENAMES-1].score >= total)\n\t\t\t\t\t\t\t\thallfame[NUMFAMENAMES-1].score = 0;\n\tint index;\n\tfor (index = 0; index < NUMFAMENAMES; index++) {\n\t\tif (total > hallfame[index].score) {\n\t\t\tif (index < (NUMFAMENAMES-1)) for (i = (NUMFAMENAMES-1); i > index; i--) hallfame[i] = hallfame[i-1];\n\t\t\thallfame[index].score = total;\n\t\t\thallfame[index].level = Scen.Scenario;\n\t\t\thallfame[index].name[0] = 0;\t// blank out the name\n\t\t\thallfame[index].side = house;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t** Now display the hall of fame\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef WIN32\n\tchar maststr[NUMFAMENAMES*32];\n#endif\n\tchar const *pal;\n\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\tpal = hallfame[i].side ? _redpal : _bluepal;\n\t\tAlloc_Object(new ScorePrintClass(hallfame[i].name, HALLFAME_X, HALLFAME_Y + (i*8), pal));\n\t\tif (hallfame[i].score) {\n#ifdef WIN32\n\t\t\tchar *str = maststr + i*32;\n#else\n\t\t\tchar *str = (char *)(HidPage.Get_Buffer()) + i*32;\n#endif\n\t\t\tsprintf(str, \"%d\", hallfame[i].score);\n\t\t\tAlloc_Object(new ScorePrintClass(str, HALLFAME_X+(6*14), HALLFAME_Y + (i*8), pal, BLACK));\n\t\t\tif (hallfame[i].level < 20) {\n\t\t\t\tsprintf(str+16, \"%d\", hallfame[i].level);\n\t\t\t} else {\n\t\t\t\tstrcpy(str+16, \"**\");\n\t\t\t}\n\t\t\tAlloc_Object(new ScorePrintClass(str+16, HALLFAME_X+(6*11), HALLFAME_Y + (i*8), pal, BLACK));\n\t\t\tCall_Back_Delay(13);\n\t\t}\n\t}\n#ifdef WIN32\n\t// Wait for text printing to complete\n\twhile (StillUpdating) {\n\t\tCall_Back_Delay(1);\n\t}\n#endif\n\t/*\n\t** If the player's on the hall of fame, have him enter his name now\n\t*/\n\tKeyboard->Clear();\n\n\tif (index < NUMFAMENAMES) {\n\t\tpal = hallfame[index].side ? _redpal : _bluepal;\n\t\tInput_Name(hallfame[index].name, HALLFAME_X, HALLFAME_Y + (index*8), pal);\n\n\t\tfile.Open(WRITE);\n\t\tfor (i = 0; i < NUMFAMENAMES; i++) {\n\t\t\tfile.Write(&hallfame[i], sizeof(struct Fame));\n\t\t}\n\t\tfile.Close();\n\t} else {\n\t\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 149, 190, _yellowpal));\n\t\tControlQ = false;\n\t\tCycle_Wait_Click();\n\t}\n\n\tKeyboard->Clear();\n\n/* get rid of all the animating objects */\n\tfor (i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n#ifdef WIN32\n\tVisiblePage.Clear();\n#else\n\tSeenPage.Clear();\n#endif\n\tShow_Mouse();\n//\tMap_Selection();\n//\tScen.ScenVar = SCEN_VAR_A;\n//\tScen.ScenDir = SCEN_DIR_EAST;\n\n\tTheme.Queue_Song(THEME_NONE);\n\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n#ifdef WIN32\n\tVisiblePage.Clear();\n#else\n\tSeenPage.Clear();\n#endif\n\tGamePalette.Set();\n\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tControlQ = 0;\n\n#ifdef WIN32\n\tdelete PseudoSeenBuff;\n#ifdef FIXIT_SCORE_CRASH\n\t/*\n\t** Fix for the score screen crash due to uncompressed shape buffer overflow.\n\t*/\n\tEnable_Uncompressed_Shapes();\n#endif\t//FIXIT\n\n#endif\n#endif\n}\n\n\nvoid Cycle_Wait_Click(bool cycle)\n{\n\tint counter = 0;\n\tint minclicks = 20;\n\tunsigned long timingtime = TickCount;\n\t//PG SerialPacketType sendpacket;\n\t//PG SerialPacketType receivepacket;\n\t//PG int packetlen;\n\n\n\tKeyboard->Clear();\n\twhile (minclicks || (!Keyboard->Check() && !ControlQ) ) {\n#if (0)\t//PG\n\t\tif (Session.Type == GAME_NULL_MODEM ||\n\t\t\tSession.Type == GAME_MODEM) {\n\n\t\t\t//\n\t\t\t// send a timing packet if enough time has gone by.\n\t\t\t//\n\t\t\tif ( (TickCount - timingtime) > PACKET_TIMING_TIMEOUT) {\n\t\t\t\tmemset (&sendpacket, 0, sizeof(SerialPacketType));\n\t\t\t\tsendpacket.Command = SERIAL_SCORE_SCREEN;\n\t\t\t\tsendpacket.ScenarioInfo.ResponseTime = NullModem.Response_Time();\n\t\t\t\tsendpacket.ID = Session.ModemType;\n\n\t\t\t\tNullModem.Send_Message (&sendpacket, sizeof(sendpacket), 0);\n\t\t\t\ttimingtime = TickCount;\n\t\t\t}\n\n\t\t\tif (NullModem.Get_Message (&receivepacket, &packetlen) > 0) {\n\t\t\t\t// throw packet away\n\t\t\t\tpacketlen = packetlen;\n\t\t\t}\n\n\t\t\tNullModem.Service();\n\t\t}\n#endif\n\t\tCall_Back_Delay(1);\n\t\tif (minclicks) {\n\t\t\tminclicks--;\n\t\t\tKeyboard->Clear();\n\t\t}\n\n\t\tif(cycle) {\n\t\t\tcounter = ((++counter) & 7);\n\t\t\tif (counter == 0 && Options.IsPaletteScroll) {\n\t\t\t\tRGBClass rgb = ScorePalette[233];\n\t\t\t\tfor (int i = 233; i < 237; i++) {\n\t\t\t\t\tScorePalette[i] = ScorePalette[i+1];\n\t\t\t\t}\n\t\t\t\tScorePalette[237] = rgb;\n\t\t\t\tScorePalette.Set();\n\t\t\t}\n\t\t}\n\t}\n\tKeyboard->Clear();\n}\n\nvoid ScoreClass::Do_Nod_Buildings_Graph(void)\n{\n\tint shapenum;\n\tInfantryTypeClass const *ramboclass;\n\n\tvoid const * factptr   = MFCD::Retrieve(\"POWR.SHP\");\n\tvoid const * rmboptr   = MFCD::Retrieve(\"E7.SHP\");\n\tvoid const * fball1ptr = MFCD::Retrieve(\"FBALL1.SHP\");\n\tramboclass = &InfantryTypeClass::As_Reference(INFANTRY_TANYA);\n\n\t/*\n\t** Print the # of buildings on the hidpage so we only need to do it once\n\t*/\n\tSeenPage.Blit(HidPage);\n\tSet_Logic_Page(HidPage);\n\tCall_Back_Delay(30);\n\tSet_Font_Palette(_redpal);\n\tHidPage.Print( 0, BUILDING_X + 16, BUILDING_Y + 10, TBLACK, TBLACK);\n\tSet_Font_Palette(_bluepal);\n\tHidPage.Print( 0, BUILDING_X + 16, BUILDING_Y + 22, TBLACK, TBLACK);\n\n\t/*\n\t** Here's the animation/draw loop for blowing up the factory\n\t*/\n\tint i;\n\tfor (i=0; i<98; i++) {\n\t\tHidPage.Blit(HidPage, BUILDING_X, BUILDING_Y, 0, 0, 320-BUILDING_X, 48);\n\t\tshapenum = 0;\t// no damage\n\t\tif (i >= 60) {\n\t\t\tshapenum = Extract_Shape_Count(factptr) - 2;\t// some damage\n\t\t\tif (i == 60) {\n\t\t\t\tShake_The_Screen(6);\n\t\t\t\tSound_Effect(VOC_CRUMBLE);\n\t\t\t}\n\t\t\tif (i > 65) {\n\t\t\t\tshapenum = Extract_Shape_Count(factptr) - 1;\t// mega damage\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Draw the building before Rambo\n\t\t*/\n\t\tif (i < 68) {\n\t\t\tCC_Draw_Shape(factptr, shapenum, 0, 0, WINDOW_MAIN,\n\t\t\t\t\t  SHAPE_GHOST|SHAPE_FADING|SHAPE_WIN_REL, ColorRemaps[PCOLOR_GOLD].RemapTable, DisplayClass::UnitShadow);\n\n\t\t}\n\n\t\t/*\n\t\t** Now draw some fires, if appropriate\n\t\t*/\n\t\tif (i >= 61) {\n\t\t\tint firecount = Extract_Shape_Count(fball1ptr);\n\t\t\tint shapeindex = (i-61) / 2;\n\t\t\tif (shapeindex < firecount) {\n\t\t\t\tCC_Draw_Shape(fball1ptr, shapeindex, 10, 10, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t}\n\t\t\tif (i > 64) {\n\t\t\t\tshapeindex = (i-64) / 2;\n\t\t\t\tif (shapeindex < firecount) {\n\t\t\t\t\tCC_Draw_Shape(fball1ptr, shapeindex, 50, 30, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_CENTER|SHAPE_WIN_REL);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t** Draw the Tanya character running away from the building\n\t\t*/\n\t\tCC_Draw_Shape(rmboptr, (ramboclass->DoControls[DO_WALK].Frame + ramboclass->DoControls[DO_WALK].Jump*6) + ((unsigned(i)>>1)%ramboclass->DoControls[DO_WALK].Count),\n\t\t\t\t\t\t  i+32, 40, WINDOW_MAIN,\n\t\t\t\t\t\t  SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t  ColorRemaps[PCOLOR_RED].RemapTable, DisplayClass::UnitShadow);\n\t\tHidPage.Blit(SeenPage, 0, 0, BUILDING_X, BUILDING_Y, 320-BUILDING_X, 48);\n/*BG\t\tif (!Keyboard->Check()) */ Call_Back_Delay(1);\n\t}\n\n\ti = max(GBKilled, NBKilled);\n\tfor (int q = 0; q <= i; q++) {\n\t\tSet_Font_Palette(_redpal);\n\t\tCount_Up_Print( \"%d\", q, NBKilled, BUILDING_X + 16, BUILDING_Y + 10);\n\t\tSet_Font_Palette(_bluepal);\n\t\tCount_Up_Print( \"%d\", q, GBKilled, BUILDING_X + 16, BUILDING_Y + 22);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(1);\n//BG\t\t}\n\t}\n\tSet_Font_Palette(_redpal);\n\tCount_Up_Print( \"%d\", NBKilled, NBKilled, BUILDING_X + 16, BUILDING_Y + 10);\n\tSet_Font_Palette(_bluepal);\n\tCount_Up_Print( \"%d\", GBKilled, GBKilled, BUILDING_X + 16, BUILDING_Y + 22);\n}\n\n\n/***************************************************************************\n * DO_GDI_GRAPH -- Show # of people or buildings killed on GDI score screen*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   yellowptr, redptr = pointers to shape file for graphs          *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   05/03/1995 BWG : Created.                                             *\n *=========================================================================*/\n\nvoid ScoreClass::Do_GDI_Graph(void const * yellowptr, void const * redptr, int gkilled, int nkilled, int ypos)\n{\n\tint i, maxval;\n#ifdef WIN32\n\tint xpos = 174;\n\tint house = (PlayerPtr->Class->House == HOUSE_USSR || PlayerPtr->Class->House == HOUSE_UKRAINE);\t\t// 0 or 1\n\tif(house) {\n\t\tint temp = gkilled;\n\t\tgkilled = nkilled;\n\t\tnkilled = temp;\n\t\tvoid const *tempptr = yellowptr;\n\t\tyellowptr = redptr;\n\t\tredptr = tempptr;\n\t}\n#else\n\tint xpos = 173;\n#endif\n\tint gdikilled = gkilled, nodkilled=nkilled;\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\tgdikilled = (gdikilled * SIZEGBAR) / maxval;\n\tnodkilled = (nodkilled * SIZEGBAR) / maxval;\n\tif (maxval < 20) {\n\t\tgdikilled = gkilled * 5;\n\t\tnodkilled = nkilled * 5;\n\t}\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\t// Draw the white-flash shape on the hidpage\n\tSet_Logic_Page(HidPage);\n\tHidPage.Fill_Rect(0, 0, 124*RESFACTOR, 9*RESFACTOR, TBLACK);\n\tCC_Draw_Shape(redptr, 119, 0, 0, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#ifdef WIN32\n\tSet_Font_Palette(house ? _redpal : _bluepal);\n#else\n\tSet_Font_Palette(_bluepal);\n#endif\n\n\tfor (i = 1; i <= gdikilled; i++) {\n\t\tif (i != gdikilled) {\n#ifdef WIN32\n\t\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\t\tCC_Draw_Shape(yellowptr, i, xpos*RESFACTOR, ypos*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t\tSet_Logic_Page(SeenBuff);\n#endif\n\t\t\tCC_Draw_Shape(yellowptr, i, xpos*RESFACTOR, ypos*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t} else {\n\t\t\tHidPage.Blit(SeenPage, 0, 0, xpos*RESFACTOR, ypos*RESFACTOR, (3+gdikilled)*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, 0, 0, xpos*RESFACTOR, ypos*RESFACTOR, (3+gdikilled)*RESFACTOR, 8*RESFACTOR);\n#endif\n\t\t}\n\n\t\tCount_Up_Print(\"%d\", (i*gkilled) / maxval, gkilled, 297, ypos+2);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(2);\n//BG\t\t}\n\t}\n\tCC_Draw_Shape(yellowptr, gdikilled, xpos*RESFACTOR, ypos*RESFACTOR   , WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n#ifdef WIN32\n\tSet_Logic_Page(*PseudoSeenBuff);\n\tCC_Draw_Shape(yellowptr, gdikilled, xpos*RESFACTOR, ypos*RESFACTOR   , WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#endif\n\tCount_Up_Print(\"%d\", gkilled, gkilled, 297, ypos+ 2);\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(40);\n\n#ifdef WIN32\n\tSet_Font_Palette(house ? _bluepal : _redpal);\n#else\n\tSet_Font_Palette(_redpal);\n#endif\n\tfor (i = 1; i <= nodkilled; i++) {\n\t\tif (i != nodkilled) {\n#ifdef WIN32\n\t\t\tSet_Logic_Page(*PseudoSeenBuff);\n\t\t\tCC_Draw_Shape(redptr, i, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t\tSet_Logic_Page(SeenBuff);\n#endif\n\t\t\tCC_Draw_Shape(redptr, i, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\t\t} else {\n\t\t\tHidPage.Blit(SeenPage, 0, 0, xpos*RESFACTOR, (ypos+12)*RESFACTOR, (3+nodkilled)*RESFACTOR, 8*RESFACTOR);\n#ifdef WIN32\n\t\t\tHidPage.Blit(*PseudoSeenBuff, 0, 0, xpos*RESFACTOR, (ypos+12)*RESFACTOR, (3+nodkilled)*RESFACTOR, 8*RESFACTOR);\n#endif\n\t\t}\n\n\t\tCount_Up_Print(\"%d\", (i*nkilled) / maxval, nkilled, 297, ypos+14);\n//BG\t\tif (!Keyboard->Check()) {\n#ifdef WIN32\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t\t\tCall_Back_Delay(2);\n//BG\t\t}\n\t}\n\n//\tif (Keyboard::Check()) Keyboard::Clear();\n\n\t/*\n\t** Make sure accurate count is printed at end\n\t*/\n#ifdef WIN32\n\tSet_Logic_Page(*PseudoSeenBuff);\n\tCC_Draw_Shape(   redptr, nodkilled, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tSet_Logic_Page(SeenBuff);\n#endif\n\tCC_Draw_Shape(   redptr, nodkilled, xpos*RESFACTOR, (ypos+12)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL, 0, 0);\n\tCount_Up_Print(\"%d\", nkilled, nkilled, 297, ypos+14);\n/*BG\tif (!Keyboard->Check()) */ Call_Back_Delay(40);\n}\n\n\nvoid ScoreClass::Do_Nod_Casualties_Graph(void)\n{\n\tint i, gdikilled, nodkilled, maxval;\n\n\tvoid const * e1ptr = MFCD::Retrieve(\"E1.SHP\");\n\n\tgdikilled = GKilled;\n\tnodkilled = NKilled;\n\tmaxval = max(gdikilled, nodkilled);\n\n\tif (!maxval) maxval=1;\n\tif ((gdikilled > (MAX_BAR_X - BARGRAPH_X)) || (nodkilled > (MAX_BAR_X - BARGRAPH_X)) ) {\n\t\tgdikilled = (gdikilled * (MAX_BAR_X - BARGRAPH_X)) / maxval;\n\t\tnodkilled = (nodkilled * (MAX_BAR_X - BARGRAPH_X)) / maxval;\n\t}\n\n\tmaxval = max(gdikilled, nodkilled);\n\tif (!maxval) maxval=1;\n\n\t/*\n\t** Initialize a bunch of objects for the infantrymen who pose for the bar\n\t** graphs of casualties.\n\t*/\n\tint r = NUMINFANTRYMEN/2;\n\tfor (i = 0; i < NUMINFANTRYMEN/2; i++) {\n\t\tInfantryMan[i+0].xpos =\n\t\tInfantryMan[i+r].xpos =  (i*10) + 7;\n\t\tInfantryMan[i+0].ypos = 11;\n\t\tInfantryMan[i+r].ypos = 21;\n\t\tInfantryMan[i+0].shapefile =\n\t\tInfantryMan[i+r].shapefile = e1ptr;\n\t\tInfantryMan[i+0].remap = ColorRemaps[PCOLOR_RED].RemapTable;\n\t\tInfantryMan[i+r].remap = ColorRemaps[PCOLOR_BLUE].RemapTable;\n\t\tInfantryMan[i+0].anim  =\n\t\tInfantryMan[i+r].anim  = 0;\n\t\tInfantryMan[i+0].stage =\n\t\tInfantryMan[i+r].stage = 0;\n\t\tInfantryMan[i+0].delay =\n\t\tInfantryMan[i+r].delay = NonCriticalRandomNumber & 0x1F;\n\t\tInfantryMan[i+0].Class =\n\t\tInfantryMan[i+r].Class = &InfantryTypeClass::As_Reference(INFANTRY_E1);\n\t}\n\n\t/*\n\t** Draw the infantrymen and pause briefly before running the graph\n\t*/\n\tDraw_InfantryMen();\n\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\tCall_Back_Delay(40);\n\n\tfor (i = 1; i <= maxval; i++) {\n\t\t// Draw & update infantrymen 3 times for every tick on the graph (i)\n\t\tfor (int index = 0; index < 3; index++) {\n\t\t\tDraw_InfantryMen();\n\t\t\tDraw_Bar_Graphs(i, nodkilled, gdikilled);\n\t\t\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\n\t\t\tSet_Font_Palette(_redpal);\n\t\t\tCount_Up_Print(\"%d\", (i*NKilled) / maxval, NKilled, SCORETEXT_X+64, CASUALTY_Y +  2);\n\t\t\tSet_Font_Palette(_bluepal);\n\t\t\tCount_Up_Print(\"%d\", (i*GKilled) / maxval, GKilled, SCORETEXT_X+64, CASUALTY_Y + 14);\n/*BG\t\t\tif (!Keyboard->Check()) */ Call_Back_Delay(3);\n\t\t}\n#ifdef WIN32\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(150));\n#else\n\t\tPlay_Sample(Beepy6, 255, Options.Normalize_Volume(60));\n#endif\n\t}\n//BG\tif (Keyboard->Check()) Keyboard->Clear();\n\n\t/*\n\t** Make sure accurate count is printed at end\n\t*/\n\tSet_Font_Palette(_redpal);\n\tCount_Up_Print(\"%d\", NKilled, NKilled, SCORETEXT_X+64, CASUALTY_Y +  2);\n\tSet_Font_Palette(_bluepal);\n\tCount_Up_Print(\"%d\", GKilled, GKilled, SCORETEXT_X+64, CASUALTY_Y + 14);\n\n\t/*\n\t** Finish up death animations, if there are any active\n\t*/\n\tint k = 1;\n\twhile (k) {\n\t\tfor (i=k=0; i<NUMINFANTRYMEN; i++) {\n\t\t\tif (InfantryMan[i].anim >= DO_GUN_DEATH) {\n\t\t\t\tk=1;\n\t\t\t}\n\t\t}\n\t\tif (k) {\n\t\t\tDraw_InfantryMen();\n\t\t}\n\t\tDraw_Bar_Graphs(maxval, nodkilled, gdikilled);\n\t\tHidPage.Blit(SeenPage, 0, 0, BARGRAPH_X, CASUALTY_Y, 320-BARGRAPH_X, 34);\n\t\tCall_Back_Delay(1);\n\t}\n}\n\n\nvoid ScoreClass::Show_Credits(int house, char const pal[])\n{\n\tstatic int _credsx[2]={276,276};\n\tstatic int _credsy[2]={173,58};\n\tstatic int _credpx[2]={228,236};\n#ifdef GERMAN\n\tstatic int _credpy[2]={181, 74};\n\tstatic int _credtx[2]={162,162};\n\tstatic int _credty[2]={173, 62};\n#else\n\tstatic int _credpy[2]={189-12, 74};\n\tstatic int _credtx[2]={182,182};\n\tstatic int _credty[2]={179-12, 62};\n#endif\n\n\tint credobj,i;\n\tint minval,add;\n\n#ifdef WIN32\n\tvoid const * credshape = MFCD::Retrieve(house ? \"CREDSUHR.SHP\" : \"CREDSAHR.SHP\");\n#else\n\tvoid const * credshape = MFCD::Retrieve(house ? \"CREDSU.SHP\" : \"CREDSA.SHP\");\n#endif\n\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_ENDCRED, _credtx[house], _credty[house], pal));\n\tCall_Back_Delay(15);\n\n\tcredobj = Alloc_Object(new ScoreCredsClass(_credsx[house], _credsy[house], credshape, 32, 2));\n\tminval = PlayerPtr->Available_Money() / 100;\n\n\t/*\n\t** Print out total credits left at end of scenario\n\t*/\n\ti = -50;\n\n\tdo {\n\t\tadd = 5;\n\t\tif ((PlayerPtr->Available_Money() - i) > 100 ) add += 15;\n\t\tif ((PlayerPtr->Available_Money() - i) > 500 ) add += 30;\n\t\tif ((PlayerPtr->Available_Money() - i) > 1000) add += PlayerPtr->Available_Money() / 40;\n\t\tif (add < minval) add = minval;\n\t\ti += add;\n\n\t\tif (i < 0) i=0;\n\n\t\tSet_Font_Palette(pal);\n\t\tCount_Up_Print(\"%d\", i, PlayerPtr->Available_Money(), _credpx[house], _credpy[house]);\n\t\tCall_Back_Delay(2);\n/*BG\t\tif (Keyboard->Check()) {\n\t\t\tCount_Up_Print(\"%d\", PlayerPtr->Available_Money(), PlayerPtr->Available_Money(), _credpx[house], _credpy[house]);\n\t\t\tKeyboard->Clear();\n\t\t\tbreak;\n\t\t}*/\n\t} while (i < PlayerPtr->Available_Money()) ;\n\n\tdelete ScoreObjs[credobj];\n\tScoreObjs[credobj] = 0;\n}\n\n\n/***************************************************************************\n * SCORECLASS::PRINT_MINUTES -- Print out hours/minutes up to max          *\n *                                                                         *\n *    Same as count-up-print, but for the time                             *\n *                                                                         *\n * INPUT:   current minute count and maximum                               *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid ScoreClass::Print_Minutes(int minutes)\n{\n\tchar str[20];\n\tif (minutes >= 60) {\n\t\tif ((minutes/60) > 9) minutes = (9*60 + 59);\n\t\tsprintf(str, Text_String(TXT_SCORE_TIMEFORMAT1), (minutes / 60), (minutes % 60));\n\t} else {\n\t\tsprintf(str, Text_String(TXT_SCORE_TIMEFORMAT2), minutes);\n\t}\n\tSeenPage.Print(str, 275*RESFACTOR, 9*RESFACTOR, TBLACK, TBLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Print(str, 275*RESFACTOR, 9*RESFACTOR, TBLACK, TBLACK);\n#endif\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Count_Up_Print -- Prints a number (up to its max) into a string, cleanly.       *\n *                                                                                             *\n *    This routine prints out a number (like 70) or its maximum number, into a string,   onto  *\n *    the screen, on a clean section of the screen, and blits it forward to the seenpage so you*\n *    can print without flashing and can print over something (to count up %'s).               *\n *                                                                                             *\n * INPUT:   str = string to print into                                                         *\n *            percent = # to print                                                             *\n *            max = # to print if percent > max                                                *\n *            xpos = x pixel coord                                                             *\n *            ypos = y pixel coord                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   04/07/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid ScoreClass::Count_Up_Print(char *str, int percent, int maxval, int xpos, int ypos)\n{\n\tchar destbuf[64];\n\n\tsprintf(destbuf, str, percent <= maxval ? percent : maxval);\n\tSeenPage.Print(\tdestbuf, xpos * RESFACTOR, ypos * RESFACTOR, TBLACK, BLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Print(\tdestbuf, xpos * RESFACTOR, ypos * RESFACTOR, TBLACK, BLACK);\n#endif\n}\n\n\n/***********************************************************************************************\n * ScoreClass::Input_Name -- Gets the name from the keyboard                                   *\n *                                                                                             *\n *      This routine handles keyboard input, and does a nifty zooming letter effect too.       *\n *                                                                                             *\n * INPUT:   str = string to put user's typing into                                             *\n *            xpos = x pixel coord                                                             *\n *            ypos = y pixel coord                                                             *\n *            pal  = text remapping palette to print using                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/15/1995 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid ScoreClass::Input_Name(char str[], int xpos, int ypos, char const pal[])\n{\n\tint key = 0;\n\tint ascii, index=0;\n\n\tvoid const * keystrok = MFCD::Retrieve(\"KEYSTROK.AUD\");\n\n\t/*\n\t** Ready the hidpage so it can restore background under zoomed letters\n\t*/\n\tSeenPage.Blit(HidPage);\n\n\t/*\n\t** Put a copy of the high score area on a spare area of the hidpage, so\n\t** we can use it to restore the letter's background instead of filling\n\t** with black.\n\t*/\n\tHidPage.Blit(HidPage, 0, 100*RESFACTOR, 0, 0, 100*RESFACTOR, 100*RESFACTOR);\n\n\tdo {\n\t\tCall_Back();\n\t\tAnimate_Score_Objs();\n\t\tAnimate_Cursor(index, ypos);\n\t\tif (Keyboard->Check()) {\n\t\t\tkey = Keyboard->To_ASCII(Keyboard->Get()) & 0xFF;\n\t\t\tCall_Back();\n\n\t\t\tif (index == MAX_FAMENAME_LENGTH-2) {\n\t\t\t\twhile (Keyboard->Check()) {\n\t\t\t\t\tKeyboard->Get();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If they hit 'backspace' when they're on the last letter,\n\t\t\t** turn it into a space instead.\n\t\t\t*/\n\t\t\tif ((key == KA_BACKSPACE) && (index == MAX_FAMENAME_LENGTH-2) ) {\n\t\t\t\tif (str[index] && str[index]!=32) key = 32;\n\t\t\t}\n\t\t\tif (key == KA_BACKSPACE) {\t\t\t\t\t\t\t//if (key == KN_BACKSPACE) {\n\t\t\t\tif (index) {\n\t\t\t\t\tstr[--index] = 0;\n\n\t\t\t\t\tint xposindex6 = (xpos+(index*6))*RESFACTOR;\n\t\t\t\t\tHidPage.Blit(SeenPage, xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#ifdef WIN32\n\t\t\t\t\tHidPage.Blit(*PseudoSeenBuff, xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#endif\n\t\t\t\t\tHidPage.Blit(HidPage,  xposindex6, (ypos-100)*RESFACTOR, xposindex6, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t\t\t}\n\n\t\t\t} else if (key != KA_RETURN) {\t\t\t//else if (key != KN_RETURN && key!=KN_KEYPAD_RETURN) {\n\t\t\t\tascii = key;\t\t\t\t\t//ascii = KN_To_KA(key);\n\t\t\t\tif (ascii >= 'a' && ascii <= 'z') ascii -= ('a' - 'A');\n\t\t\t\tif ( (ascii >= '!' && ascii <= KA_TILDA) || ascii == ' ') {\n\t\t\t\t\tHidPage.Blit(SeenPage, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#ifdef WIN32\n\t\t\t\t\tHidPage.Blit(*PseudoSeenBuff, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t#endif\n\t\t\t\t\tHidPage.Blit(HidPage, (xpos + (index*6))*RESFACTOR, (ypos-100)*RESFACTOR, (xpos + (index*6))*RESFACTOR, ypos*RESFACTOR, 6*RESFACTOR, 6*RESFACTOR);\n\t\t\t\t\tstr[index] = ascii;\n\t\t\t\t\tstr[index+1] = 0;\n\n\t\t\t\t\tint objindex;\n#ifdef WIN32\n\t\t\t\t\tPlay_Sample(keystrok, 255, Options.Normalize_Volume(150));\n#else\n\t\t\t\t\tPlay_Sample(keystrok, 255, Options.Normalize_Volume(105));\n#endif\n\t\t\t\t\tobjindex = Alloc_Object(new ScoreScaleClass(str+index, xpos+(index*6), ypos, pal));\n\t\t\t\t\twhile (ScoreObjs[objindex]) Call_Back_Delay(1);\n\n\t\t\t\t\tif (index < (MAX_FAMENAME_LENGTH-2) ) index++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} while (key != KA_RETURN);\t\t\t\t\t//\t} while(key != KN_RETURN && key!=KN_KEYPAD_RETURN);\n}\n\n\nvoid Animate_Cursor(int pos, int ypos)\n{\n\tstatic int _lastpos = 0, _state;\n\tstatic CDTimerClass<SystemTimerClass> _timer;\n\n\typos += 6;\t// move cursor to bottom of letter\n\n\typos *= RESFACTOR;\n\n\t// If they moved the cursor, erase old one and force state=0, to make green draw right away\n\tif (pos != _lastpos) {\n\t\tHidPage.Blit(SeenPage, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos-100*RESFACTOR, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos, 6*RESFACTOR, 1*RESFACTOR);\n#ifdef WIN32\n\t\tHidPage.Blit(*PseudoSeenBuff, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos-100*RESFACTOR, (HALLFAME_X + (_lastpos*6))*RESFACTOR, ypos, 6*RESFACTOR, 1*RESFACTOR);\n#endif\n\t\t_lastpos = pos;\n\t\t_state = 0;\n\t}\n\tSeenBuff.Draw_Line((HALLFAME_X + (pos*6))*RESFACTOR, ypos, (HALLFAME_X + (pos*6)+5)*RESFACTOR, ypos, _state ? LTBLUE : TBLACK);\n#ifdef WIN32\n\tPseudoSeenBuff->Draw_Line((HALLFAME_X + (pos*6))*RESFACTOR, ypos, (HALLFAME_X + (pos*6)+5)*RESFACTOR, ypos, _state ? LTBLUE : TBLACK);\n#endif\n\t/*\n\t** Toggle the color of the cursor, green or black, if it's time to do so.\n\t*/\n\tif (!_timer) {\n\t\t_state ^= 1;\n\t\t_timer = 5;\n\t}\n}\n\n\n/***************************************************************************\n * Draw_InfantryMen -- Draw all the guys on the score screen               *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Draw_InfantryMen()\n{\n\tint k;\n\n// Only draw the infantrymen if we're playing USSR... Allies wouldn't execute\n//\tpeople like that.\n\n\t/*\n\t** First restore the background\n\t*/\n\tHidPage.Blit(HidPage, BARGRAPH_X, CASUALTY_Y, 0, 0, 320-BARGRAPH_X, 34);\n\tSet_Logic_Page(HidPage);\n\n\t/*\n\t** Then draw all the infantrymen on the clean hidpage\n\t*/\n\tfor (k = 0; k < NUMINFANTRYMEN; k++) Draw_InfantryMan(k);\n\t/*\n\t** They'll all be blitted over to the seenpage after the graphs are drawn\n\t*/\n}\n\n/***************************************************************************\n * Draw_InfantryMan -- Draw one guy in score screen, update animation      *\n *                                                                         *\n *    This routine draws one of the infantrymen in the \"Casualties\" area   *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Draw_InfantryMan(int index)\n{\n\tint stage;\n\n\t/* If the infantryman's dead, just abort this function */\n\tif (InfantryMan[index].anim == -1) return;\n\n\tstage = InfantryMan[index].stage + InfantryMan[index].Class->DoControls[InfantryMan[index].anim].Frame;\n\n\tCC_Draw_Shape(InfantryMan[index].shapefile,\n\t\t\t\t\t  stage,\n\t\t\t\t\t  InfantryMan[index].xpos,\n\t\t\t\t\t  InfantryMan[index].ypos,\n\t\t\t\t\t  WINDOW_MAIN,\n\t\t\t\t\t  SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t  InfantryMan[index].remap,\n\t\t\t\t\t  DisplayClass::UnitShadow);\n\t/*\n\t** see if it's time to run a new anim\n\t*/\n\tif (--InfantryMan[index].delay <= 0) {\n\t\tInfantryMan[index].delay = 3;\n\t\tif (++InfantryMan[index].stage >= InfantryMan[index].Class->DoControls[InfantryMan[index].anim].Count) {\n\n\t\t\t/*\n\t\t\t** was he playing a death anim? If so, and it's done, erase him\n\t\t\t*/\n\t\t\tif (InfantryMan[index].anim >= DO_GUN_DEATH) {\n\t\t\t\tInfantryMan[index].anim = -1;\n\t\t\t} else {\n\t\t\t\tNew_Infantry_Anim(index, DO_STAND_READY);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * New_Infantry_Anim -- Start up a new animation for one of the infantrymen*\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   index: which of the 30 infantrymen to affect                   *\n *          anim:  which animation sequence to start him into              *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid New_Infantry_Anim(int index, int anim)\n{\n\tInfantryMan[index].anim = anim;\n\tInfantryMan[index].stage = 0;\n\tif (anim >= DO_GUN_DEATH) {\n\t\tInfantryMan[index].delay = 1;\t// start right away\n\t} else {\n\t\tInfantryMan[index].delay = NonCriticalRandomNumber & 15;\n\t}\n}\n\n\n/***************************************************************************\n * Draw_Bar_Graphs -- Draw \"Casualties\" bar graphs                         *\n *                                                                         *\n *                                                                         *\n *                                                                         *\n * INPUT:   i = current count of how far to draw graph                     *\n *          gkilled = # of GDI forces killed (adjusted to fit in space)    *\n *          nkilled = # of Nod forces killed (adjusted to fit in space)    *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *   07/02/1996 BWG : Removed references to civilians.                     *\n *=========================================================================*/\nvoid Draw_Bar_Graphs(int i, int gkilled, int nkilled)\n{\n\n\tif (gkilled) {\n\t\tLogicPage->Fill_Rect(0,   0+4*RESFACTOR, 0+min(i, gkilled)*RESFACTOR,   0+5*RESFACTOR, RED);\n\t\tLogicPage->Draw_Line(0+1*RESFACTOR, 0+6*RESFACTOR, (0+min(i, gkilled)+1)*RESFACTOR, 0+6*RESFACTOR, TBLACK);\n\t\tLogicPage->Draw_Line((0+MIN(i, gkilled)+1)*RESFACTOR, 0+5*RESFACTOR, (0+min(i, gkilled)+1)*RESFACTOR, 0+5*RESFACTOR, TBLACK);\n\t\tif (i <= gkilled) {\n\t\t\tint anim = InfantryMan[i/11].anim;\n\t\t\tif (anim!=-1 && anim < DO_GUN_DEATH) {\n\t\t\t\tif (i/11) {\n\t\t\t\t\tNew_Infantry_Anim(i/11, DO_GUN_DEATH + (NonCriticalRandomNumber & 3));\n\t\t\t\t} else {\n\t\t\t\t\tNew_Infantry_Anim(i/11, DO_GUN_DEATH);\n\t\t\t\t}\n//\t\t\t\tSound_Effect(Random_Pick(VOC_SCREAM1, VOC_SCREAM5));\n\t\t\t}\n\t\t}\n\t}\n\tif (nkilled) {\n\t\tLogicPage->Fill_Rect( 0,          0+16*RESFACTOR,  0+min(i, nkilled)*RESFACTOR,    0+17*RESFACTOR, LTCYAN);\n\t\tLogicPage->Draw_Line( 0+1*RESFACTOR, 0+18*RESFACTOR, (0+min(i, nkilled)+1)*RESFACTOR, 0+18*RESFACTOR, TBLACK);\n\t\tLogicPage->Draw_Line((0+MIN(i, nkilled)+1)*RESFACTOR, 0+17*RESFACTOR, (0+min(i, nkilled)+1)*RESFACTOR, 0+17*RESFACTOR, TBLACK);\n\t\tif (i <= nkilled) {\n\t\t\tint anim = InfantryMan[(NUMINFANTRYMEN/2)+(i/11)].anim;\n\t\t\tif (anim!=-1 && anim < DO_GUN_DEATH) {\n\t\t\t\tif (i/11) {\n\t\t\t\t\tNew_Infantry_Anim((NUMINFANTRYMEN/2)+(i/11), DO_GUN_DEATH + (NonCriticalRandomNumber & 3));\n\t\t\t\t} else {\n\t\t\t\t\tNew_Infantry_Anim((NUMINFANTRYMEN/2)+(i/11), DO_GUN_DEATH);\n\t\t\t\t}\n//\t\t\t\tSound_Effect(Random_Pick(VOC_SCREAM1, VOC_SCREAM5));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***************************************************************************\n * Call_Back_Delay -- Combines Call_Back() and Delay() functions           *\n *                                                                         *\n *    This is just to cut down on code size and typing a little.           *\n *                                                                         *\n * INPUT:                                                                  *\n *                                                                         *\n * OUTPUT:                                                                 *\n *                                                                         *\n * WARNINGS:                                                               *\n *                                                                         *\n * HISTORY:                                                                *\n *   04/13/1995 BWG : Created.                                             *\n *=========================================================================*/\nvoid Call_Back_Delay(int time)\n{\n\ttime;\n#if (0)//PG\n\tif (time < 0 ) time = 0;\n\tif (time > 60) time = 60;\n\tCDTimerClass<SystemTimerClass> cd;\n\tCDTimerClass<SystemTimerClass> callbackcd = 0;\n\n\tif (!ControlQ) {\n\t\tif (Keyboard->Down(KN_LCTRL) && Keyboard->Down(KN_Q)) {\n\t\t\tControlQ = 1;\n\t\t\tKeyboard->Clear();\n\t\t}\n\t}\n\tif (ControlQ) time=0;\n\n\tcd = time;\n\tStreamLowImpact = true;\n\tdo {\n\t\tif (callbackcd == 0) {\n\t\t\tCall_Back();\n\t\t\tcallbackcd = TIMER_SECOND/4;\n\t\t}\n\t\tAnimate_Score_Objs();\n\t} while (cd);\n\tStreamLowImpact = false;\n#endif\n}\n\n\nvoid Animate_Score_Objs()\n{\n#ifdef WIN32\n\tStillUpdating = false;\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tPseudoSeenBuff->Blit(SeenPage);\n\t\t}\n#endif\n\tfor (int i = 0; i < MAXSCOREOBJS; i++) {\n\t\tif (ScoreObjs[i]) {\n\t\t\tScoreObjs[i]->Update();\n\t\t}\n\t}\n}\n\nchar *Int_Print(int a)\n{\n\tstatic char str[10];\n\n\tsprintf(str, \"%d\", a);\n\treturn str;\n}\n\n\n/***********************************************************************************************\n * Multi_Score_Presentation -- Multiplayer routine to display score screen.                    *\n *                                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/11/1995  BWG: Created.                                                                 *\n *=============================================================================================*/\nextern int CopyType;\n\nvoid Multi_Score_Presentation(void)\n{\n#if (0)//PG\n\tchar remap[16];\n#ifdef WIN32\n\tGraphicBufferClass *pseudoseenbuff = new GraphicBufferClass(320, 200, (void*)NULL);\n\tPseudoSeenBuff = new GraphicBufferClass(SeenBuff.Get_Width(),SeenBuff.Get_Height(),(void*)NULL);\n#endif\n\n\tint i,k;\n\tvoid *oldfont;\n\tint oldfontxspacing = FontXSpacing;\n\n\tFontXSpacing = 0;\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n//\tTheme.Queue_Song(THEME_WIN);\n\n\tBlackPalette.Set();\n\tSeenPage.Clear();\n\tHidPage.Clear();\n\tHide_Mouse();\n\tvoid *anim = Open_Animation(\"MLTIPLYR.WSA\", NULL, 0L, (WSAOpenType)(WSA_OPEN_FROM_MEM | WSA_OPEN_TO_PAGE), ScorePalette);\n\t/*\n\t** Display the background animation\n\t*/\n#ifdef WIN32\n\tpseudoseenbuff->Clear();\n\tAnimate_Frame(anim, *pseudoseenbuff, 1);\nfor(int x=0; x<256; x++) memset(&PaletteInterpolationTable[x][0],x,256);\nCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , 0);\n#else\n\tAnimate_Frame(anim, HidPage, 1);\n\tHidPage.Blit(SeenPage);\n#endif\n\tScorePalette.Set(FADE_PALETTE_FAST, Call_Back);\n\n\tint frame = 1;\n\twhile (frame < Get_Animation_Frame_Count(anim)) {\n#ifdef WIN32\n\t\tAnimate_Frame(anim, *pseudoseenbuff, frame++);\n\t\tCopyType = 1;\n\t\tInterpolate_2X_Scale(pseudoseenbuff , &SeenBuff , NULL);\n\t\tCopyType = 0;\n#else\n\t\tAnimate_Frame(anim, SeenPage, frame++);\n#endif\n\t\tCall_Back_Delay(2);\n\t}\n\tClose_Animation(anim);\n\n#ifdef WIN32\n\tCopyType = 1;\n\tInterpolate_2X_Scale(pseudoseenbuff , PseudoSeenBuff , NULL);\n\tCopyType = 0;\n#endif\n\n\t/* Change to the six-point font for Text_Print */\n\toldfont = Set_Font(ScoreFontPtr);\n\tCall_Back();\n\n\tSet_Logic_Page(SeenBuff);\n\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP,   113,  13, _greenpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_SCORE_TOP,   130,  13, _greenpal));\n#endif\n\tCall_Back_Delay(5);\n\tAlloc_Object(new ScorePrintClass(TXT_COMMANDER,    27,  31, _greenpal));\n\tCall_Back_Delay(10);\n#ifdef FRENCH\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 113,  31, _greenpal));\n#endif\n#ifdef GERMAN\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 118,  31, _greenpal));\n#endif\n#ifdef ENGLISH\n\tAlloc_Object(new ScorePrintClass(TXT_BATTLES_WON, 126,  31, _greenpal));\n#endif\n\tCall_Back_Delay(13);\n\tAlloc_Object(new ScorePrintClass(TXT_KILLS_COLON, 249,  31, _greenpal));\n\tCall_Back_Delay(6);\n\n\t/*\n\t** Move all the scores over a notch if there's more games than can be\n\t** shown (which is known by Session.CurGame == MAX_MULTI_GAMES-1);\n\t*/\n\tif (Session.CurGame == MAX_MULTI_GAMES-1) {\n\t\tfor (i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\t\tfor (k = 0; k < MAX_MULTI_GAMES-1; k++) {\n\t\t\t\tSession.Score[i].Kills[k] = Session.Score[i].Kills[k+1];\n\t\t\t}\n\t\t}\n\t}\n\n\tint y = 41;\n\tfor (i = 0; i < MAX_MULTI_NAMES; i++) {\n\t\tif (strlen(Session.Score[i].Name)) {\n\t\t\tint color = Session.Score[i].Color;\n\t\t\tremap[ 8] = ColorRemaps[color].FontRemap[11];\n\t\t\tremap[ 6] = ColorRemaps[color].FontRemap[12];\n\t\t\tremap[ 4] = ColorRemaps[color].FontRemap[13];\n\t\t\tremap[ 2] = ColorRemaps[color].FontRemap[14];\n\t\t\tremap[14] = ColorRemaps[color].FontRemap[15];\n\n\t\t\tAlloc_Object(new ScorePrintClass(Session.Score[i].Name, 15,  y, remap));\n\t\t\tCall_Back_Delay(20);\n\n\t\t\tAlloc_Object(new ScorePrintClass(Int_Print(Session.Score[i].Wins), 118, y, remap));\n\t\t\tCall_Back_Delay(6);\n\n\t\t\tfor (k = 0; k <= min(Session.CurGame, MAX_MULTI_GAMES-2); k++) {\n\t\t\t\tif (Session.Score[i].Kills[k] >= 0) {\n\t\t\t\t\tAlloc_Object(new ScorePrintClass(Int_Print(Session.Score[i].Kills[k]), 225+(24*k), y, remap));\n\t\t\t\t\tCall_Back_Delay(6);\n\t\t\t\t}\n\t\t\t}\n\t\t\ty += 12;\n\t\t}\n\t}\n\n#if defined(GERMAN) || defined(FRENCH)\n\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 95 /*(320-strlen(Text_String(TXT_MAP_CLICK2)))/2*/, 190, _yellowpal));\n#else\n\tAlloc_Object(new ScorePrintClass(TXT_CLICK_CONTINUE, 109 /*(320-strlen(Text_String(TXT_MAP_CLICK2)))/2*/, 190, _yellowpal));\n#endif\n\tCycle_Wait_Click(false);\n\n/* get rid of all the animating objects */\n\tfor (i = 0; i < MAXSCOREOBJS; i++) if (ScoreObjs[i]) {\n\t\tdelete ScoreObjs[i];\n\t\tScoreObjs[i] = 0;\n\t}\n\n\tTheme.Queue_Song(THEME_NONE);\n\n\tBlackPalette.Set(FADE_PALETTE_FAST, NULL);\n\tSeenPage.Clear();\n\tGamePalette.Set();\n#ifdef WIN32\n\tdelete PseudoSeenBuff;\n#endif\n\tSet_Font(oldfont);\n\tFontXSpacing = oldfontxspacing;\n\tControlQ = 0;\n\tShow_Mouse();\n#endif\n}\n\nvoid ScoreClass::Init(void)\n{\n\tScore = 0;\n\tNKilled = 0;\n\tGKilled = 0;\n\tCKilled = 0;\n\tNBKilled = 0;\n\tGBKilled = 0;\n\tCBKilled = 0;\n\tNHarvested = 0;\n\tGHarvested = 0;\n\tCHarvested = 0;\n\tElapsedTime = 0;\n\tRealTime = 0;\n\tChangingGun = 0;\n}\n"
  },
  {
    "path": "REDALERT/SCORE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SCORE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCORE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : April 19, 1994                                               *\n *                                                                                             *\n *                  Last Update : April 19, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCORE_H\n#define SCORE_H\n\n#include\t\"unit.h\"\n#include\t\"building.h\"\n\nclass ScoreClass {\n\tpublic:\n\t\tScoreClass(void) {};\n\t\tScoreClass(NoInitClass const &) {};\n\n\t\tint Score;\n\t\tint NKilled;\n\t\tint GKilled;\n\t\tint CKilled;\n\t\tint NBKilled;\n\t\tint GBKilled;\n\t\tint CBKilled;\n\t\tint NHarvested;\n\t\tint GHarvested;\n\t\tint CHarvested;\n\t\tunsigned long ElapsedTime;\n\t\tTTimerClass<SystemTimerClass> RealTime;\n\n\t\tvoid Init(void);\n\t\tvoid Presentation(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\t\tvoid Code_Pointers(void);\n\t\tvoid Decode_Pointers(void);\n\n\tprivate:\n\t\tunsigned char *ChangingGun;\n\n\t\tvoid ScoreDelay(int ticks);\n\t\tvoid Pulse_Bar_Graph(void);\n\t\tvoid Print_Graph_Title(int,int);\n\t\tvoid Print_Minutes(int minutes);\n\t\tvoid Count_Up_Print(char *str, int percent, int max, int xpos, int ypos);\n\t\tvoid Show_Credits(int house, char const pal[]);\n\t\tvoid Do_GDI_Graph(void const * yellowptr, void const * redptr, int gdikilled, int nodkilled, int ypos);\n\t\tvoid Do_Nod_Casualties_Graph(void);\n\t\tvoid Do_Nod_Buildings_Graph(void);\n\t\tvoid Input_Name(char str[], int xpos, int ypos, char const pal[]);\n};\n\nclass ScoreAnimClass {\n\tpublic:\n\t\tScoreAnimClass(int x, int y, void const * data);\n\t\tint XPos;\n\t\tint YPos;\n\t\tCDTimerClass<SystemTimerClass> Timer;\n\t\tvoid const * DataPtr;\n\t\tvirtual void Update(void) {} ;\n\t\tvirtual ~ScoreAnimClass(void) {DataPtr=0;} ;\n};\n\nclass ScoreCredsClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tint MaxStage;\n\t\tint TimerReset;\n\t\tvoid const * CashTurn;\n\t\tvoid const * Clock1;\n\n\t\tvirtual void Update(void);\n\t\tScoreCredsClass(int xpos, int ypos, void const * data, int max, int timer);\n\t\tvirtual ~ScoreCredsClass(void) {CashTurn=0;Clock1=0;};\n};\n\nclass ScoreTimeClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tint MaxStage;\n\t\tint TimerReset;\n\t\tvirtual void Update(void);\n\t\tScoreTimeClass(int xpos, int ypos, void const * data, int max, int timer);\n\t\tvirtual ~ScoreTimeClass(void) {};\n};\n\nclass ScorePrintClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Background;\n\t\tint Stage;\n\t\tvoid const * PrimaryPalette;\n\t\tvirtual void Update(void);\n\t\tScorePrintClass(void const * string, int xpos, int ypos, void const * palette, int background=TBLACK);\n\t\tScorePrintClass( int  string, int xpos, int ypos, void const * palette, int background=TBLACK);\n\t\tvirtual ~ScorePrintClass(void) {PrimaryPalette=0;};\n};\n\nclass ScoreScaleClass : public ScoreAnimClass {\n\tpublic:\n\t\tint Stage;\n\t\tchar const * Palette;\n\t\tvirtual void Update(void);\n\t\tScoreScaleClass(void const * data, int xpos, int ypos, char const pal[]);\n\t\tvirtual ~ScoreScaleClass(void) {Palette=0;};\n\n};\n\n#define MAXSCOREOBJS\t\t8\nextern ScoreAnimClass *ScoreObjs[MAXSCOREOBJS];\n\nvoid Multi_Score_Presentation(void);\n\n#endif\n"
  },
  {
    "path": "REDALERT/SCREEN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SCREEN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               *** \n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCREEN.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 2, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 2, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCREEN_H\n#define SCREEN_H\n\n\nclass ScreenClass\n{\n\t\t/*\n\t\t**\tThe mouse shape is controlled by these variables. These\n\t\t**\thold the current mouse shape (so resetting won't be needlessly performed) and\n\t\t**\tthe normal default mouse shape (when arrow shapes are needed).\n\t\t*/\n\t\tMouseShapeType CurrentMouseShape;\n\t\tMouseShapeType NormalMouseShape;\n\n\tpublic:\n\n\t\tScreenClass(void) {\n\t\t\tCurrentMouseShape = SHP_NONE;\n\t\t\tNormalMouseShape = SHP_MOUSE;\n\t\t};\n\t\t\n\n\t\tInit(void);\n\t\tSet_Default_Mouse(MouseShapeType mouse);\n\t\tForce_Mouse_Shape(MouseShapeType mouse);\n\n\t\tunsigned char *GamePalette;\n\t\tunsigned char *BlackPalette;\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SCROLL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SCROLL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCROLL.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/08/95                                                     *\n *                                                                                             *\n *                  Last Update : August 25, 1995 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ScrollClass::AI -- Handles scroll AI processing.                                          *\n *   ScrollClass::ScrollClass -- Constructor for the scroll class object.                      *\n *   ScrollClass::Set_Autoscroll -- Turns autoscrolling on or off.                             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef WIN32\n#define\tSCROLL_DELAY\t1\n#else\n#define\tSCROLL_DELAY\t2\n#endif\n\nCDTimerClass<SystemTimerClass> ScrollClass::Counter;\n\n\n/***********************************************************************************************\n * ScrollClass::ScrollClass -- Constructor for the scroll class object.                        *\n *                                                                                             *\n *    This is the constructor for the scroll class object.                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nScrollClass::ScrollClass(void) :\n\tIsAutoScroll(true)\n{\n\tCounter = SCROLL_DELAY;\n\tInertia = 0;\n}\n\n\n/***********************************************************************************************\n * ScrollClass::AI -- Handles scroll AI processing.                                            *\n *                                                                                             *\n *    This routine is called every game frame for purposes of input processing.                *\n *                                                                                             *\n * INPUT:   input    -- Reference to the keyboard/mouse event that just occurred.              *\n *                                                                                             *\n *          x,y      -- The mouse coordinates.                                                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *   08/10/1995 JLB : Revamped for free smooth scrolling.                                      *\n *   08/25/1995 JLB : Handles new scrolling option.                                            *\n *=============================================================================================*/\n#define\tEVA_WIDTH\t\t80\nvoid ScrollClass::AI(KeyNumType &input, int x, int y)\n{\n#if 0\n\tbool\t\tplayer_scrolled=false;\n\tstatic \tDirType\tdirection;\n\tint\t\trate;\n\n\n\t/*\n\t**\tIf rubber band mode is in progress, then don't allow scrolling of the tactical map.\n\t*/\n\tif (!IsRubberBand /*&& !IsTentative*/) {\n\n\t\t/*\n\t\t**\tSpecial check to not scroll within the special no-scroll regions.\n\t\t*/\n\t\tbool noscroll = false;\n\n\t\tif (!noscroll) {\n\t\t\tbool at_screen_edge = (y == 0 || x == 0 || x >= SeenBuff.Get_Width()-1 || y >= SeenBuff.Get_Height()-1);\n\n\t\t\t/*\n\t\t\t**\tVerify that the mouse is over a scroll region.\n\t\t\t*/\n\t\t\tif (Inertia || at_screen_edge) {\n\t\t\t\tif (at_screen_edge) {\n\n\t\t\t\t\tplayer_scrolled=true;\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tAdjust the mouse coordinates to emphasize the\n\t\t\t\t\t**\tcardinal directions over the diagonals.\n\t\t\t\t\t*/\n\t\t\t\t\tint altx = x;\n\t\t\t\t\tif (altx < 50 * RESFACTOR) altx -= ((50 * RESFACTOR)-altx);\n\t\t\t\t\taltx = max(altx, 0);\n\t\t\t\t\tif (altx > ((320-50) * RESFACTOR)) altx += altx-((320-50) * RESFACTOR);\n\t\t\t\t\taltx = min(altx, (320 * RESFACTOR));\n\t\t\t\t\tif (altx > (50 * RESFACTOR) && altx < ((320-50) * RESFACTOR)) {\n\t\t\t\t\t\taltx += (((320/2) * RESFACTOR)-altx)/2;\n\t\t\t\t\t}\n\n\t\t\t\t\tint alty = y;\n\t\t\t\t\tif (alty < (50 * RESFACTOR)) alty -= (50 * RESFACTOR)-alty;\n\t\t\t\t\talty = max(alty, 0);\n\t\t\t\t\tif (alty > (150 * RESFACTOR)) alty += alty-(150 * RESFACTOR);\n\t\t\t\t\talty = min(alty, 200 * RESFACTOR);\n\n\t\t\t\t\tdirection = (DirType)Desired_Facing256((320/2) * RESFACTOR, (200/2) * RESFACTOR, altx, alty);\n\t\t\t\t}\n\n\t\t\t\tint control = Dir_Facing(direction);\n\n\t\t\t\t/*\n\t\t\t\t**\tThe mouse is over a scroll region so set the mouse shape accordingly if the map\n\t\t\t\t**\tcan be scrolled in the direction indicated.\n\t\t\t\t*/\n\t\t\t\tstatic int _rate[9] = {\n\t\t\t\t\t0x00E0*RESFACTOR,\n\t\t\t\t\t0x00C0*RESFACTOR,\n\t\t\t\t\t0x00A0*RESFACTOR,\n\t\t\t\t\t0x0080*RESFACTOR,\n\t\t\t\t\t0x0060*RESFACTOR,\n\t\t\t\t\t0x0040*RESFACTOR,\n\t\t\t\t\t0x0020*RESFACTOR,\n\t\t\t\t\t0x0010*RESFACTOR,\n\t\t\t\t\t0x0008*RESFACTOR\n\t\t\t\t};\n\t\t\t\tif (Debug_Map) {\n\t\t\t\t\trate = Options.ScrollRate+1;\n\t\t\t\t} else {\n\t\t\t\t\trate = 8-Inertia;\n\t\t\t\t}\n\n\t\t\t\tif (rate < Options.ScrollRate+1) {\n\t\t\t\t\trate = Options.ScrollRate+1;\n\t\t\t\t\tInertia = 8-rate;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIncrease the scroll rate if the mouse button is held down.\n\t\t\t\t*/\n\t//\t\t\tif (Keyboard->Down(KN_LMOUSE)) {\n\t//\t\t\t\trate = Bound(rate-3, 0, 4);\n\t//\t\t\t}\n\t\t\t\tif (Keyboard->Down(KN_RMOUSE)) {\n\t\t\t\t\trate = Bound(rate+1, 4, (int)(sizeof(_rate)/sizeof(_rate[0]))-1);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t**\tIf options indicate that scrolling should be forced to\n\t\t\t\t**\tone of the 8 facings, then adjust the direction value\n\t\t\t\t**\taccordingly.\n\t\t\t\t*/\n\t\t\t\tdirection = Facing_Dir(Dir_Facing(direction));\n\n\t\t\t\tint distance = _rate[rate]/2;\n\n\t\t\t\tif (!Scroll_Map(direction, distance, false)) {\n\t\t\t\t\tOverride_Mouse_Shape((MouseType)(MOUSE_NO_N+control), false);\n\t\t\t\t} else {\n\t\t\t\t\tOverride_Mouse_Shape((MouseType)(MOUSE_N+control), false);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf the mouse button is pressed or auto scrolling is active, then scroll\n\t\t\t\t\t**\tthe map if the delay counter indicates.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Keyboard->Down(KN_LMOUSE) || IsAutoScroll) {\n\t\t\t\t\t\tdistance = _rate[rate];\n\n\t\t\t\t\t\tif (Debug_Map) {\n\t\t\t\t\t\t\tScroll_Map(direction, distance, true);\n\t\t\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdistance = _rate[rate];\n\t\t\t\t\t\t\tScroll_Map(direction, distance, true);\n\n\t\t\t\t\t\t\tif (Counter == 0 && player_scrolled) {\n\t\t\t\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t\t\t\t\tInertia++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif (!Debug_Map && !player_scrolled) {\n\t\t\t\tif (!Counter) {\n\t\t\t\t\tInertia--;\n\t\t\t\t\tif (Inertia<0) Inertia++;\n\t\t\t\t\tCounter = SCROLL_DELAY;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n#endif\n\tHelpClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * ScrollClass::Set_Autoscroll -- Turns autoscrolling on or off.                               *\n *                                                                                             *\n *    This routine controls the autoscrolling setting. Autoscroll, when active, will cause the *\n *    map to scroll if the mouse is held over the scroll region. This is regardless of whether *\n *    any mouse button is held down or not.                                                    *\n *                                                                                             *\n * INPUT:   control  -- Should the autoscroll be turned on?                                    *\n *                      0  = turn off                                                          *\n *                      1  = turn on                                                           *\n *                      -1 = toggle current setting                                            *\n *                                                                                             *\n * OUTPUT:  Returns with the old setting of the autoscroll flag.                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/10/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool ScrollClass::Set_Autoscroll(int control)\n{\n\tbool old = IsAutoScroll;\n\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsAutoScroll = !IsAutoScroll;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tIsAutoScroll = control;\n\t\t\tbreak;\n\t}\n\treturn(old);\n}\n\n\n"
  },
  {
    "path": "REDALERT/SCROLL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SCROLL.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SCROLL.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/18/94                                                     *\n *                                                                                             *\n *                  Last Update : November 18, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SCROLL_H\n#define SCROLL_H\n\n#include\t\"help.h\"\n\n\nclass ScrollClass: public HelpClass\n{\n\t\t/*\n\t\t**\tIf map scrolling is automatic, then this flag is true. Automatic scrolling will\n\t\t**\tcause the map to scroll if the mouse is in the scroll region, regardless of\n\t\t**\twhether or not the mouse button is held down.\n\t\t*/\n\t\tunsigned IsAutoScroll:1;\n\n\t\t/*\n\t\t**\tScroll speed is regulated by this count down timer. When this value reaches zero,\n\t\t**\tscroll the map in the direction required and reset this timer.\n\t\t*/\n\t\tstatic CDTimerClass<SystemTimerClass> Counter;\n\n\t\t/*\n\t\t** Inertia control for scrolling\n\t\t*/\n\t\tint\tInertia;\n\n\tpublic:\n\t\tScrollClass(void);\n\t\tScrollClass(NoInitClass const & x) : HelpClass(x) {};\n\n\t\tbool Set_Autoscroll(int control);\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Init_IO(void) {Counter = 0;HelpClass::Init_IO();};\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SDATA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SDATA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SDATA.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 9, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SmudgeTypeClass::As_Reference -- Fetches a reference to the smudge type specified.        *\n *   SmudgeTypeClass::Create_And_Place -- Creates and places on map, a smudge object.          *\n *   SmudgeTypeClass::Create_One_Of -- Creates a smudge object of this type.                   *\n *   SmudgeTypeClass::Display -- Draws a generic version of this smudge type.                  *\n *   SmudgeTypeClass::Draw_It -- Renders the smudge image at the coordinate specified.         *\n *   SmudgeTypeClass::From_Name -- Converts an ASCII name into a smudge type.                  *\n *   SmudgeTypeClass::Init -- Performs theater specific initializations.                       *\n *   SmudgeTypeClass::Init_Heap -- Initialize the smudge type class object heap.               *\n *   SmudgeTypeClass::One_Time -- Performs one-time initialization                             *\n *   SmudgeTypeClass::Prep_For_Add -- Prepares the scenario editor for adding a smudge object. *\n *   SmudgeTypeClass::SmudgeTypeClass -- Constructor for smudge type objects.                  *\n *   SmudgeTypeClass::operator delete -- Returns a smudge type class object to the pool.       *\n *   SmudgeTypeClass::operator new -- Allocate a smudge type object from the memory pool.      *\n *   SmudgetypeClass::Occupy_List -- Determines occupation list for smudge object.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"type.h\"\n\n\nstatic SmudgeTypeClass const Crater1 (\n\tSMUDGE_CRATER1,\n\t\"CR1\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater2 (\n\tSMUDGE_CRATER2,\n\t\"CR2\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater3 (\n\tSMUDGE_CRATER3,\n\t\"CR3\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater4 (\n\tSMUDGE_CRATER4,\n\t\"CR4\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater5 (\n\tSMUDGE_CRATER5,\n\t\"CR5\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Crater6 (\n\tSMUDGE_CRATER6,\n\t\"CR6\",\n\tTXT_CRATER,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\ttrue\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch1 (\n\tSMUDGE_SCORCH1,\n\t\"SC1\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch2 (\n\tSMUDGE_SCORCH2,\n\t\"SC2\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch3 (\n\tSMUDGE_SCORCH3,\n\t\"SC3\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch4 (\n\tSMUDGE_SCORCH4,\n\t\"SC4\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch5 (\n\tSMUDGE_SCORCH5,\n\t\"SC5\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Scorch6 (\n\tSMUDGE_SCORCH6,\n\t\"SC6\",\n\tTXT_SCORCH,\n\t1,1,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\tfalse,\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\n\nstatic SmudgeTypeClass const Bibx1 (\n\tSMUDGE_BIB1,\n\t\"BIB1\",\n\tTXT_BIB,\n\t4,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Bibx2 (\n\tSMUDGE_BIB2,\n\t\"BIB2\",\n\tTXT_BIB,\n\t3,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\nstatic SmudgeTypeClass const Bibx3 (\n\tSMUDGE_BIB3,\n\t\"BIB3\",\n\tTXT_BIB,\n\t2,2,\t\t\t\t\t\t\t// Width and height of smudge (in icons).\n\ttrue,\t\t\t\t\t\t\t// Is this a building bib?\n\tfalse\t\t\t\t\t\t\t// Is this a crater smudge?\n);\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::SmudgeTypeClass -- Constructor for smudge type objects.                    *\n *                                                                                             *\n *    This constructor is used to create the smudge type objects. These type objects contain   *\n *    static information about the various smudge types supported in the game.                 *\n *                                                                                             *\n * INPUT:   see below...                                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeTypeClass::SmudgeTypeClass(\n\tSmudgeType smudge,\n\tchar const * ininame,\n\tint fullname,\n\tint width,\n\tint height,\n\tbool isbib,\n\tbool iscrater) :\n\t\tObjectTypeClass(\n\t\t\tRTTI_SMUDGETYPE,\n\t\t\tint(smudge),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\tfullname,\n\t\t\tininame),\n\tType(smudge),\n\tWidth(width),\n\tHeight(height),\n\tIsCrater(iscrater),\n\tIsBib(isbib)\n{\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::operator new -- Allocate a smudge type object from the memory pool.        *\n *                                                                                             *\n *    This will allocate a smudge type class object from the special memory pool for that      *\n *    purpose.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the newly allocated smudge type class object. If there is insufficient*\n *          memory in the pool to fulfill the request, then NULL is returned.                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * SmudgeTypeClass::operator new(size_t)\n{\n\treturn(SmudgeTypes.Alloc());\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::operator delete -- Returns a smudge type class object to the pool.         *\n *                                                                                             *\n *    This will return the smudge type class object back to the memory pool from whence it     *\n *    was originally allocated.                                                                *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the smudge type class object to return the pool.            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::operator delete(void * pointer)\n{\n\tSmudgeTypes.Free((SmudgeTypeClass *)pointer);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Init_Heap -- Initialize the smudge type class object heap.                 *\n *                                                                                             *\n *    This will initialize the special heap for smudge type class objects, by pre-allocated    *\n *    all known smudge types.                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Call this routine only once and before the rules.ini file is processed.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Init_Heap(void)\n{\n\t/*\n\t**\tThese smudge type class objects must be allocated in the exact order that they\n\t**\tare specified in the SmudgeType enumeration. This is necessary because the heap\n\t**\tallocation block index serves double duty as the type number index.\n\t*/\n\tnew SmudgeTypeClass(Crater1);\t\t\t// SMUDGE_CRATER1\n\tnew SmudgeTypeClass(Crater2);\t\t\t// SMUDGE_CRATER2\n\tnew SmudgeTypeClass(Crater3);\t\t\t// SMUDGE_CRATER3\n\tnew SmudgeTypeClass(Crater4);\t\t\t// SMUDGE_CRATER4\n\tnew SmudgeTypeClass(Crater5);\t\t\t// SMUDGE_CRATER5\n\tnew SmudgeTypeClass(Crater6);\t\t\t// SMUDGE_CRATER6\n\tnew SmudgeTypeClass(Scorch1);\t\t\t// SMUDGE_SCORCH1\n\tnew SmudgeTypeClass(Scorch2);\t\t\t// SMUDGE_SCORCH2\n\tnew SmudgeTypeClass(Scorch3);\t\t\t// SMUDGE_SCORCH3\n\tnew SmudgeTypeClass(Scorch4);\t\t\t// SMUDGE_SCORCH4\n\tnew SmudgeTypeClass(Scorch5);\t\t\t// SMUDGE_SCORCH5\n\tnew SmudgeTypeClass(Scorch6);\t\t\t// SMUDGE_SCORCH6\n\tnew SmudgeTypeClass(Bibx1);\t\t\t// SMUDGE_BIB1\n\tnew SmudgeTypeClass(Bibx2);\t\t\t//\tSMUDGE_BIB2\n\tnew SmudgeTypeClass(Bibx3);\t\t\t// SMUDGE_BIB3\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::From_Name -- Converts an ASCII name into a smudge type.                    *\n *                                                                                             *\n *    This converts an ASCII name into a smudge type number. This is typically necessary       *\n *    when processing scenario INI files and not used otherwise.                               *\n *                                                                                             *\n * INPUT:   name  -- Pointer to the name to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the SmudgeType number that matches the name supplied. If no match     *\n *          was found, then SMUDGE_NONE is returned.                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeType SmudgeTypeClass::From_Name(char const * name)\n{\n\tif (name != NULL) {\n\t\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\t\tif (stricmp(As_Reference(index).IniName, name) == 0) {\n\t\t\t\treturn(index);\n\t\t\t}\n\t\t}\n\t}\n\treturn(SMUDGE_NONE);\n}\n\n\n/***********************************************************************************************\n * SmudgetypeClass::Occupy_List -- Determines occupation list for smudge object.               *\n *                                                                                             *\n *    Smudges are always only one icon in dimension, so this routine always returns a cell     *\n *    occupation offset list of the center cell.                                               *\n *                                                                                             *\n * INPUT:   placement   -- Is this for placement legality checking only? The normal condition  *\n *                         is for marking occupation flags.                                    *\n *                                                                                             *\n * OUTPUT:  Returns occupation list specifying all the cells that the overlay occupies. This   *\n *          is just the center cell.                                                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nshort const * SmudgeTypeClass::Occupy_List(bool) const\n{\n\tstatic short _occupy[4*4];\n\tshort * ptr = &_occupy[0];\n\n\tfor (int x = 0; x < Width; x++) {\n\t\tfor (int y = 0; y < Height; y++) {\n\t\t\t*ptr++ = x + (y*MAP_CELL_W);\n\t\t}\n\t}\n\t*ptr = REFRESH_EOL;\n\treturn(_occupy);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Init -- Performs theater specific initializations.                         *\n *                                                                                             *\n *    Smudge object imagery varies between theaters. This routine will load the appropriate    *\n *    imagery for the theater specified.                                                       *\n *                                                                                             *\n * INPUT:   theater  -- The theater to prepare for.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Init(TheaterType theater)\n{\n\tif (theater != LastTheater) {\n\t\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\t\tSmudgeTypeClass const & smudge = As_Reference(index);\n\t\t\tchar fullname[_MAX_FNAME+_MAX_EXT];\t// Fully constructed smudge data set name.\n\n\t\t\t_makepath(fullname, NULL, NULL, smudge.IniName, Theaters[theater].Suffix);\n\t\t\t((void const *&)smudge.ImageData) = MFCD::Retrieve(fullname);\n\t\t}\n\t}\n}\n\n\n#ifdef SCENARIO_EDITOR\n/***********************************************************************************************\n * SmudgeTypeClass::Display -- Draws a generic version of this smudge type.                    *\n *                                                                                             *\n *    The scenario object editor will call this routine to display a typical imagery of this   *\n *    smudge object for graphical identification purposes.                                     *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate to render the smudge at.                                       *\n *                                                                                             *\n *          window-- The window to base the coordinate rendering upon.                         *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const\n{\n\tvoid const * ptr = Get_Image_Data();\n\n\tx += WindowList[window][WINDOWX];\n\ty += WindowList[window][WINDOWY];\n\n\tIsTheaterShape = true;\t\t// Smudges are theater specific\n\tif (ptr != NULL) {\n\t\tfor (int w = 0; w < Width; w++) {\n\t\t\tfor (int h = 0; h < Height; h++) {\n\t\t\t\tCC_Draw_Shape(ptr, w + (h*Width), x + w*ICON_PIXEL_W, y + h*ICON_PIXEL_H, WINDOW_TACTICAL, SHAPE_WIN_REL);\n\t\t\t}\n\t\t}\n\t}\n\tIsTheaterShape = false;\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Prep_For_Add -- Prepares the scenario editor for adding a smudge object.   *\n *                                                                                             *\n *    This routine adds smudge objects to the list of objects that the scenario editor can     *\n *    place upon the ground. It is only called from the scenario editor.                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Prep_For_Add(void)\n{\n\tfor (SmudgeType index = SMUDGE_FIRST; index < SMUDGE_COUNT; index++) {\n\t\tif (As_Reference(index).Get_Image_Data()) {\n\t\t\tMap.Add_To_List(&As_Reference(index));\n\t\t}\n\t}\n}\n#endif\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Create_And_Place -- Creates and places on map, a smudge object.            *\n *                                                                                             *\n *    This routine will, in one motion, create a smudge object and place it upon the map.      *\n *    Since placing a smudge on the map will destroy the object, this routine will leave the   *\n *    smudge object count unchanged. Typically, this routine is used by the scenario editor    *\n *    for creating smudges and placing them on the map.                                        *\n *                                                                                             *\n * INPUT:   cell  -- The cell to place the smudge object.                                      *\n *                                                                                             *\n * OUTPUT:  bool; Was the placement successful?                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SmudgeTypeClass::Create_And_Place(CELL cell, HousesType ) const\n{\n\tif (new SmudgeClass(Type, Cell_Coord(cell))) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Create_One_Of -- Creates a smudge object of this type.                     *\n *                                                                                             *\n *    This routine will create a smudge object of the appropriate type. Smudge objects are     *\n *    transitory in nature. They exist only from the point of creation until they are given    *\n *    a spot on the map to reside. At that time the map data is updated and the smudge         *\n *    object is destroyed.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a created smudge object. If none could be created, then  *\n *          NULL is returned.                                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * SmudgeTypeClass::Create_One_Of(HouseClass *) const\n{\n\treturn(new SmudgeClass(Type, -1));\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::Draw_It -- Renders the smudge image at the coordinate specified.           *\n *                                                                                             *\n *    This routine will draw the smudge overlay image at the coordinate (upper left)           *\n *    specified. The underlying terrain icon is presumed to have already been rendered.        *\n *                                                                                             *\n * INPUT:   x,y   -- Coordinate of the upper left corner of icon to render the smudge object.  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::Draw_It(int x, int y, int data) const\n{\n\tvoid const * ptr = Get_Image_Data();\n\tif (ptr != NULL) {\n\t\tIsTheaterShape = true;\t\t// Smudges are theater specific\n\t\tCC_Draw_Shape(ptr, data, x, y, WINDOW_TACTICAL, SHAPE_WIN_REL);\n\t\tIsTheaterShape = false;\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::One_Time -- Performs one-time initialization                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/12/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeTypeClass::One_Time(void)\n{\n}\n\n\n/***********************************************************************************************\n * SmudgeTypeClass::As_Reference -- Fetches a reference to the smudge type specified.          *\n *                                                                                             *\n *    Use this routine to get a reference to the smudge type class object when given just      *\n *    the smudge type identifier.                                                              *\n *                                                                                             *\n * INPUT:   type  -- The smudge type identifier to convert into a reference.                   *\n *                                                                                             *\n * OUTPUT:  Returns with a reference to the smudge type class object.                          *\n *                                                                                             *\n * WARNINGS:   Be sure that the smudge type specified is legal. An illegal type value will     *\n *             produce undefined results.                                                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/09/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeTypeClass & SmudgeTypeClass::As_Reference(SmudgeType type)\n{\n\treturn(*SmudgeTypes.Ptr(type));\n}\n"
  },
  {
    "path": "REDALERT/SEARCH.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SEARCH.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SEARCH.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/02/96                                                     *\n *                                                                                             *\n *                  Last Update : November 2, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   IndexClass<T>::Add_Index -- Add element to index tracking system.                         *\n *   IndexClass<T>::Clear -- Clear index handler to empty state.                               *\n *   IndexClass<T>::Count -- Fetch the number of index entries recorded.                       *\n *   IndexClass<T>::Fetch_Index -- Fetch data from specified index.                            *\n *   IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity.         *\n *   IndexClass<T>::IndexClass -- Constructor for index handler.                               *\n *   IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer.                      *\n *   IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index.      *\n *   IndexClass<T>::Is_Present -- Checks for presense of index entry.                          *\n *   IndexClass<T>::Remove_Index -- Find matching index and remove it from system.             *\n *   IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID              *\n *   IndexClass<T>::Set_Archive -- Records the node pointer into the archive.                  *\n *   IndexClass<T>::Sort_Nodes -- Sorts nodes in preparation for a binary search.              *\n *   IndexClass<T>::~IndexClass -- Destructor for index handler object.                        *\n *   compfunc -- Support function for bsearch and bsort.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SEARCH_H\n#define SEARCH_H\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n#ifndef __BORLANDC__\n#define\t_USERENTRY\n#endif\n\n/*\n**\tThis class is used to create and maintain an index. It does this by assigning a unique\n**\tidentifier number to the type objects that it is indexing. The regular binary sort and search\n**\tfunction are used for speedy index retreival. Typical use of this would be to index pointers to\n**\tnormal data objects, but it can be used to hold the data objects themselves. Keep in mind that\n**\tthe data object \"T\" is copied around by this routine in the internal tables so not only must\n**\tit have a valid copy constructor, it must also be efficient. The internal algorithm will\n**\tcreate an arbitrary number of default constructed objects of type \"T\". Make sure it has a\n**\tdefault constructor that is effecient. The constructor need not perform any actual\n**\tinitialization since this class has prior knowledge about the legality of these temporary\n**\tobjects and doesn't use them until after the copy constructor is used to initialize them.\n*/\n\ntemplate<class T>\nclass IndexClass\n{\n\tpublic:\n\t\tIndexClass(void);\n\t\t~IndexClass(void);\n\n\t\t/*\n\t\t**\tAdd element to index table.\n\t\t*/\n\t\tbool Add_Index(int id, T data);\n\n\t\t/*\n\t\t**\tRemoves an index entry from the index table.\n\t\t*/\n\t\tbool Remove_Index(int id);\n\n\t\t/*\n\t\t**\tCheck to see if index is present.\n\t\t*/\n\t\tbool Is_Present(int id) const;\n\n\t\t/*\n\t\t**\tFetch number of indexes in the table.\n\t\t*/\n\t\tint Count(void) const;\n\n\t\t/*\n\t\t**\tActually a fetch an index data element from the table.\n\t\t*/\n\t\tT Fetch_Index(int id) const;\n\n\t\t/*\n\t\t**\tClear out the index table to null (empty) state.\n\t\t*/\n\t\tvoid Clear(void);\n\n\tprivate:\n\t\t/*\n\t\t**\tThis node object is used to keep track of the connection between the data\n\t\t**\tobject and the index identifier number.\n\t\t*/\n\t\tstruct NodeElement {\n\t\t\tint ID;\t\t\t// ID number (must be first element in this structure).\n\t\t\tT Data;\t\t\t// Data element assigned to this ID number.\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the pointer to the allocated index table. It contains all valid nodes in\n\t\t**\ta sorted order.\n\t\t*/\n\t\tNodeElement * IndexTable;\n\n\t\t/*\n\t\t**\tThis records the number of valid nodes within the index table.\n\t\t*/\n\t\tint IndexCount;\n\n\t\t/*\n\t\t**\tThe total size (in nodes) of the index table is recorded here. If adding a node\n\t\t**\twould cause the index count to exceed this value, the index table must be resized\n\t\t**\tto make room.\n\t\t*/\n\t\tint IndexSize;\n\n\t\t/*\n\t\t**\tIf the index table is sorted and ready for searching, this flag will be true. Sorting\n\t\t**\tof the table only occurs when absolutely necessary.\n\t\t*/\n\t\tbool IsSorted;\n\n\t\t/*\n\t\t**\tThis records a pointer to the last element found by the Is_Present() function. Using\n\t\t**\tthis last recorded value can allow quick fetches of data whenever possible.\n\t\t*/\n\t\tNodeElement const * Archive;\n\n\t\t//-------------------------------------------------------------------------------------\n\t\tIndexClass(IndexClass const & rvalue);\n\t\tIndexClass * operator = (IndexClass const & rvalue);\n\n\t\t/*\n\t\t**\tIncrease size of internal index table by amount specified.\n\t\t*/\n\t\tbool Increase_Table_Size(int amount);\n\n\t\t/*\n\t\t**\tCheck if archive pointer is the same as that requested.\n\t\t*/\n\t\tbool Is_Archive_Same(int id) const;\n\n\t\t/*\n\t\t**\tInvalidate the archive pointer.\n\t\t*/\n\t\tvoid Invalidate_Archive(void);\n\n\t\t/*\n\t\t**\tSet archive to specified value.\n\t\t*/\n\t\tvoid Set_Archive(NodeElement const * node);\n\n\t\t/*\n\t\t**\tSearch for the node in the index table.\n\t\t*/\n\t\tNodeElement const * Search_For_Node(int id) const;\n\n\t\tstatic int _USERENTRY search_compfunc(void const * ptr, void const * ptr2);\n};\n\n\n/***********************************************************************************************\n * IndexClass<T>::IndexClass -- Constructor for index handler.                                 *\n *                                                                                             *\n *    This constructs an empty index handler.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nIndexClass<T>::IndexClass(void) :\n\tIndexTable(0),\n\tIndexCount(0),\n\tIndexSize(0),\n\tIsSorted(false),\n\tArchive(0)\n{\n\tInvalidate_Archive();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::~IndexClass -- Destructor for index handler object.                          *\n *                                                                                             *\n *    This will destruct and free any resources managed by this index handler.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nIndexClass<T>::~IndexClass(void)\n{\n\tClear();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Clear -- Clear index handler to empty state.                                 *\n *                                                                                             *\n *    This routine will free all internal resources and bring the index handler into a         *\n *    known empty state. After this routine, the index handler is free to be reused.           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Clear(void)\n{\n\tdelete [] IndexTable;\n\tIndexTable = 0;\n\tIndexCount = 0;\n\tIndexSize = 0;\n\tIsSorted = false;\n\tInvalidate_Archive();\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity.           *\n *                                                                                             *\n *    This helper function will increase the capacity of the internal index table without      *\n *    performing any alterations to the index data. Use this routine prior to adding a new     *\n *    element if the existing capacity is insufficient.                                        *\n *                                                                                             *\n * INPUT:   amount   -- The number of index element spaces to add to its capacity.             *\n *                                                                                             *\n * OUTPUT:  bool; Was the internal capacity increased without error?                           *\n *                                                                                             *\n * WARNINGS:   If there is insufficient RAM, then this routine will fail.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Increase_Table_Size(int amount)\n{\n\t/*\n\t**\tCheck size increase parameter for legality.\n\t*/\n\tif (amount < 0) return(false);\n\n\tNodeElement * table = new NodeElement[IndexSize + amount];\n\tif (table != NULL) {\n\n\t\t/*\n\t\t**\tCopy all valid nodes into the new table.\n\t\t*/\n\t\tfor (int index = 0; index < IndexCount; index++) {\n\t\t\ttable[index] = IndexTable[index];\n\t\t}\n\n\t\t/*\n\t\t**\tMake the new table the current one (and delete the old one).\n\t\t*/\n\t\tdelete [] IndexTable;\n\t\tIndexTable = table;\n\t\tIndexSize += amount;\n\t\tInvalidate_Archive();\n\n\t\t/*\n\t\t**\tReturn with success flag.\n\t\t*/\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tFailure to allocate the memory results in a failure to increase\n\t**\tthe size of the index table.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Count -- Fetch the number of index entries recorded.                         *\n *                                                                                             *\n *    This will return the quantity of index entries that have been recored by this index      *\n *    handler.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with number of recored indecies present.                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint IndexClass<T>::Count(void) const\n{\n\treturn(IndexCount);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Is_Present -- Checks for presense of index entry.                            *\n *                                                                                             *\n *    This routine will scan for the specified index entry. If it was found, then 'true' is    *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Was the index entry found in this index handler object?                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Is_Present(int id) const\n{\n\t/*\n\t**\tIf there are no data elements in the index table, then it can\n\t**\tnever find the specified index. Check for and return failure\n\t**\tin this case.\n\t*/\n\tif (IndexCount == 0) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tCheck to see if this same index element was previously searched for. If\n\t**\tso and it was previously found, then there is no need to search for it\n\t**\tagain -- just return true.\n\t*/\n\tif (Is_Archive_Same(id)) {\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tPerform a binary search on the index nodes in order to look for a\n\t**\tmatching index value.\n\t*/\n\tNodeElement const * nodeptr = Search_For_Node(id);\n\n\t/*\n\t**\tIf a matching index was found, then record it for future reference and return success.\n\t*/\n\tif (nodeptr != 0) {\n\t\t((IndexClass<T> *)this)->Set_Archive(nodeptr);\n\t\treturn(true);\n\t}\n\n\t/*\n\t**\tCould not find element so return failure condition.\n\t*/\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Fetch_Index -- Fetch data from specified index.                              *\n *                                                                                             *\n *    This routine will find the specified index and return the data value associated with it. *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with the data value associated with the index value.                       *\n *                                                                                             *\n * WARNINGS:   This routine presumes that the index exists. If it doesn't exist, then the      *\n *             default constructed object \"T\" is returned instead. To avoid this problem,      *\n *             always verfiy the existance of the index by calling Is_Present() first.         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nT IndexClass<T>::Fetch_Index(int id) const\n{\n\tif (Is_Present(id)) {\n\n\t\t/*\n\t\t**\tCount on the fact that the archive pointer is always valid after a call to Is_Present\n\t\t**\tthat returns \"true\".\n\t\t*/\n\t\treturn(Archive->Data);\n\t}\n\treturn(T());\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index.        *\n *                                                                                             *\n *    This routine compares the specified index ID with the previously recorded index archive  *\n *    pointer in order to determine if they match.                                             *\n *                                                                                             *\n * INPUT:   id -- The index ID to compare to the archive index object pointer.                 *\n *                                                                                             *\n * OUTPUT:  bool; Does the specified index match the archive pointer?                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Is_Archive_Same(int id) const\n{\n\tif (Archive != 0 && Archive->ID == id) {\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer.                        *\n *                                                                                             *\n *    This routine will set the archive pointer to an invalid state. This must be performed    *\n *    if ever the archive pointer would become illegal (such as when the element it refers to  *\n *    is deleted).                                                                             *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Invalidate_Archive(void)\n{\n\tArchive = 0;\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Set_Archive -- Records the node pointer into the archive.                    *\n *                                                                                             *\n *    This routine records the specified node pointer. Use this routine when there is a        *\n *    good chance that the specified node will be requested in the immediate future.           *\n *                                                                                             *\n * INPUT:   node  -- Pointer to the node to assign to the archive.                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nvoid IndexClass<T>::Set_Archive(NodeElement const * node)\n{\n\tArchive = node;\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Add_Index -- Add element to index tracking system.                           *\n *                                                                                             *\n *    This routine will record the index information into this index manager object. It        *\n *    associates the index number with the data specified. The data is copied to an internal   *\n *    storage location.                                                                        *\n *                                                                                             *\n * INPUT:   id    -- The ID number to associate with the data.                                 *\n *                                                                                             *\n *          data  -- The data to store.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the element added without error? Failure indicates that RAM has been     *\n *                exhausted.                                                                   *\n *                                                                                             *\n * WARNINGS:   The data is COPIED to internal storage. This means that the data object must    *\n *             have a functional and efficient copy constructor and assignment operator.       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Add_Index(int id, T data)\n{\n\t/*\n\t**\tEnsure that there is enough room to add this index. If not, then increase the\n\t**\tcapacity of the internal index table.\n\t*/\n\tif (IndexCount + 1 > IndexSize) {\n\t\tif (!Increase_Table_Size(IndexSize == 0 ? 10 : IndexSize)) {\n\n\t\t\t/*\n\t\t\t**\tFailure to increase the size of the index table means failure to add\n\t\t\t**\tthe index element.\n\t\t\t*/\n\t\t\treturn(false);\n\t\t}\n\t}\n\n\t/*\n\t**\tAdd the data to the end of the index data and then sort the index table.\n\t*/\n\tIndexTable[IndexCount].ID = id;\n\tIndexTable[IndexCount].Data = data;\n\tIndexCount++;\n\tIsSorted = false;\n\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Remove_Index -- Find matching index and remove it from system.               *\n *                                                                                             *\n *    This will scan through the previously added index elements and if a match was found, it  *\n *    will be removed.                                                                         *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for and remove.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the index element found and removed?                                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nbool IndexClass<T>::Remove_Index(int id)\n{\n\t/*\n\t**\tFind the array index into the table that matches the specified id value.\n\t*/\n\tint found_index = -1;\n\tfor (int index = 0; index < IndexCount; index++) {\n\t\tif (IndexTable[index].ID == id) {\n\t\t\tfound_index = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the array index was found, then copy all higher index entries\n\t**\tdownward to fill the vacated location. We cannot use memcpy here because the type\n\t**\tobject may not support raw copies. C++ defines the assignment operator to deal\n\t**\twith this, so that is what we use.\n\t*/\n\tif (found_index != -1) {\n\n\t\tfor (int index = found_index+1; index < IndexCount; index++) {\n\t\t\tIndexTable[index-1] = IndexTable[index];\n\t\t}\n\t\tIndexCount--;\n\n\t\tNodeElement fake;\n\t\tfake.ID = 0;\n\t\tfake.Data = T();\n\t\tIndexTable[IndexCount] = fake;\t\t// zap last (now unused) element\n\n\t\tInvalidate_Archive();\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * compfunc -- Support function for bsearch and bsort.                                         *\n *                                                                                             *\n *    This compare function presumes that its parameters are pointing to NodeElements and that *\n *    the first \"int\" in the node is the index ID number to be used for comparison.            *\n *                                                                                             *\n * INPUT:   ptr1  -- Pointer to first node.                                                    *\n *                                                                                             *\n *          ptr2  -- Pointer to second node.                                                   *\n *                                                                                             *\n * OUTPUT:  Returns with the comparision value between the two nodes.                          *\n *                                                                                             *\n * WARNINGS:   This is highly dependant upon the layout of the NodeElement structure.          *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T>\nint _USERENTRY IndexClass<T>::search_compfunc(void const * ptr1, void const * ptr2)\n{\n\tif (*(int const *)ptr1 == *(int const *)ptr2) {\n\t\treturn(0);\n\t}\n\tif (*(int const *)ptr1 < *(int const *)ptr2) {\n\t\treturn(-1);\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID                *\n *                                                                                             *\n *    This routine will perform a binary search on the previously recorded index values and    *\n *    if a match was found, it will return a pointer to the NodeElement.                       *\n *                                                                                             *\n * INPUT:   id -- The index ID to search for.                                                  *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the NodeElement that matches the index ID specified. If  *\n *          no matching index could be found, then NULL is returned.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/02/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\ntemplate<class T> \ntypename IndexClass<T>::NodeElement const * IndexClass<T>::Search_For_Node(int id) const\n{\n\t/*\n\t**\tIf there are no elements in the list, then it certainly can't find any matches.\n\t*/\n\tif (IndexCount == 0) {\n\t\treturn(0);\n\t}\n\n\t/*\n\t**\tIf the list has not yet been sorted, then do so now. Binary searching requires\n\t**\tthe list to be sorted.\n\t*/\n\tif (!IsSorted) {\n\t\tqsort(&IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc);\n\t\t((IndexClass<T> *)this)->Invalidate_Archive();\n\t\t((IndexClass<T> *)this)->IsSorted = true;\n\t}\n\n\t/*\n\t**\tThis list is sorted and ready to perform a binary search upon it.\n\t*/\n\tNodeElement node;\n\tnode.ID = id;\n\treturn((NodeElement const *)bsearch(&node, &IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc));\n}\n\n\n#endif\n\n\n"
  },
  {
    "path": "REDALERT/SEDITDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tSEditDlg.cpp - \"SimpleEditDlgClass\": An ok/cancel type dialog with 1 or 2 edit boxes.\n//\t\t\t\t\tMostly a hack for what I need right now - not necessarily very flexible.\n//\t\t\t\t\tStill - I can't believe there isn't a set of dialog classes in here already.\n//\tajw 07/21/98\n\n#include \"SEditDlg.h\"\n#include \"WOLEdit.h\"\n\nextern bool cancel_current_msgbox;\nbool disable_current_msgbox = false;\n\n//***********************************************************************************************\nSimpleEditDlgClass::SimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept,\n\t\t\t\t\t\t\t\t\t\t\tconst char* szPrompt2 /* = NULL */, int iEditCharsAccept2 /* = 0 */ )\n\t: iDialogWidth( iDialogWidth ), iEditCharsAccept( iEditCharsAccept ), iEditCharsAccept2( iEditCharsAccept2 )\n{\n\t//\tCopy strings.\n\tif( szTitle )\n\t{\n\t\tthis->szTitle = new char[ strlen( szTitle ) + 1 ];\n\t\tstrcpy( this->szTitle, szTitle );\n\t}\n\telse\n\t\tthis->szTitle = NULL;\n\n\tif( szPrompt )\n\t{\n\t\tthis->szPrompt = new char[ strlen( szPrompt ) + 1 ];\n\t\tstrcpy( this->szPrompt, szPrompt );\n\t}\n\telse\n\t\tthis->szPrompt = NULL;\t\t//\tI wouldn't try this ... not totally implemented.\n\n\tif( szPrompt2 )\n\t{\n\t\tthis->szPrompt2 = new char[ strlen( szPrompt2 ) + 1 ];\n\t\tstrcpy( this->szPrompt2, szPrompt2 );\n\t}\n\telse\n\t\tthis->szPrompt2 = NULL;\t\t//\tThis is the flag for whether or not there is a second edit box.\n\n\t*szEdit = 0;\n\t*szEdit2 = 0;\n\n\tszOkButton = Text_String( TXT_OK );\n\tszCancelButton = Text_String( TXT_CANCEL );\n\tszMiddleButton = NULL;\n}\n\n//***********************************************************************************************\nSimpleEditDlgClass::~SimpleEditDlgClass()\n{\n\tdelete [] szTitle;\n\tdelete [] szPrompt;\n\tdelete [] szPrompt2;\n}\n\n//***********************************************************************************************\nvoid SimpleEditDlgClass::SetButtons( const char* szOk, const char* szCancel, const char* szMiddle /*= NULL*/ )\n{\n\tszOkButton = szOk;\n\tszCancelButton = szCancel;\n\tszMiddleButton = szMiddle;\n}\n\n//***********************************************************************************************\nconst char* SimpleEditDlgClass::Show()\n{\n\t//\tShows dialog, returns text of button pressed.\n\t//\tUnless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values.\n\n\tbool bEscapeDown = false;\n\tbool bReturnDown = false;\n\n\t/*\n\t**\tDialog & button dimensions\n\t*/\n\tint x_margin = 18 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint y_margin = 10 * RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t\t// margin width/height\n\tint d_gap_y = 5 * RESFACTOR;\n\n\tint d_dialog_w = iDialogWidth;\n\tint d_dialog_h = szPrompt2 ? ( 29 * RESFACTOR ) + 2 * d_gap_y + 2 * y_margin : ( 19 * RESFACTOR ) + d_gap_y + 2 * y_margin;\n\tif( szTitle )\n\t\td_dialog_h += 10 * RESFACTOR + 2 * d_gap_y;\n\tint d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);\n\tint d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// coord of x-center\n\n/*\n\tif( szTitle )\n\t{\n\t\td_title_w = String_Pixel_Width( szTitle );\n\t\td_title_h = 10 * RESFACTOR;\n\t\td_title_x = d_dialog_cx - d_title_w / 2;\n\t\td_title_y = d_dialog_y + d_gap_y;\n\t}\n*/\n\n\tint d_prompt_w = String_Pixel_Width( szPrompt );\n\tint d_prompt_h = 10 * RESFACTOR;\n\tint d_prompt_x = d_dialog_x + x_margin;\n\tint d_prompt_y = szTitle ? ( d_dialog_y + 3 * d_gap_y + 10 * RESFACTOR ) : ( d_dialog_y + d_gap_y );\n\n\tint d_edit_w = d_dialog_w - d_prompt_w - 2 * x_margin;\n\tint d_edit_h = 10 * RESFACTOR;\n\tint d_edit_x = d_dialog_x + d_prompt_w + x_margin;\n\tint d_edit_y = d_prompt_y;\n\n\tint d_prompt2_w = szPrompt2 ? String_Pixel_Width( szPrompt2 ) : 0;\n\tint d_prompt2_h = 10 * RESFACTOR;\n\tint d_prompt2_x = d_dialog_x + x_margin;\n\tint d_prompt2_y = d_prompt_y + d_prompt2_h + d_gap_y;\n\n\tint d_edit2_w = d_dialog_w - d_prompt2_w - 2 * x_margin;\n\tint d_edit2_h = 10 * RESFACTOR;\n\tint d_edit2_x = d_dialog_x + d_prompt2_w + x_margin;\n\tint d_edit2_y = d_prompt2_y;\n\n\tint d_ok_w, d_ok_h,\td_ok_x, d_ok_y, d_cancel_w, d_cancel_h, d_cancel_x, d_cancel_y, d_mid_x, d_mid_y, d_mid_w, d_mid_h;\n\n\tif( !szMiddleButton )\n\t{\n\t\td_ok_w = 40 * RESFACTOR;\n\t\td_ok_h = 9 * RESFACTOR;\n\t\td_ok_x = d_dialog_cx - d_ok_w - 10 * RESFACTOR;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;\n\n\t\td_cancel_w = 40 * RESFACTOR;\n\t\td_cancel_h = 9 * RESFACTOR;\n\t\td_cancel_x = d_dialog_cx + 10 * RESFACTOR;\n\t\td_cancel_y = d_ok_y;\n\t}\n\telse\n\t{\n\t\td_ok_w = 40 * RESFACTOR;\n\t\td_ok_h = 9 * RESFACTOR;\n\t\td_ok_x = d_dialog_cx - d_ok_w - 30 * RESFACTOR;\n\t\td_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;\n\n\t\td_mid_w = 40 * RESFACTOR;\n\t\td_mid_h = 9 * RESFACTOR;\n\t\td_mid_x = d_dialog_cx - ( d_mid_w / 2 );\n\t\td_mid_y = d_ok_y;\n\n\t\td_cancel_w = 40 * RESFACTOR;\n\t\td_cancel_h = 9 * RESFACTOR;\n\t\td_cancel_x = d_dialog_cx + 30 * RESFACTOR;\n\t\td_cancel_y = d_ok_y;\n\t}\n\n\t/*\n\t**\tButton enumerations\n\t*/\n\tenum {\n\t\tBUTTON_OK = 100,\n\t\tBUTTON_CANCEL,\n\t\tBUTTON_MIDDLE,\n\t\tBUTTON_EDIT,\n\t\tBUTTON_EDIT2\n\t};\n\n\t/*\n\t**\tRedraw values: in order from \"top\" to \"bottom\" layer of the dialog\n\t*/\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\t/*\n\t**\tDialog variables\n\t*/\n\tconst char* szReturn = NULL;\n\n\t/*\n\t**\tButtons\n\t*/\n\tControlClass* commands = NULL;\t\t// the button list\n\n\tTextButtonClass OkBtn( BUTTON_OK, szOkButton, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w );\n\tTextButtonClass CancelBtn( BUTTON_CANCEL, szCancelButton, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );\n\tTextButtonClass MiddleBtn( BUTTON_MIDDLE, szMiddleButton, TPF_BUTTON, d_mid_x, d_mid_y, d_mid_w );\n\n\tWOLEditClass EditBox( BUTTON_EDIT, szEdit, min( sizeof(szEdit), iEditCharsAccept ), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC );\n\tWOLEditClass EditBox2( BUTTON_EDIT2, szEdit2, min( sizeof(szEdit2), iEditCharsAccept2 ), TPF_6PT_GRAD|TPF_NOSHADOW, \n\t\t\t\t\t\t\td_edit2_x, d_edit2_y, d_edit2_w, -1, EditClass::ALPHANUMERIC );\n\n\t/*\n\t**\tInitialize.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate the button list.\n\t*/\n\tcommands = &OkBtn;\n\tCancelBtn.Add_Tail(*commands);\n\tif( szMiddleButton )\n\t\tMiddleBtn.Add_Tail(*commands);\n\tEditBox.Add_Tail(*commands);\n\tif( szPrompt2 )\n\t\tEditBox2.Add_Tail(*commands);\n\tEditBox.Set_Focus();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tKeyboard->Clear();\n\tbool firsttime = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the dialog box.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tif (display) {\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\t\t\t\tif( szTitle )\n\t\t\t\t\tDraw_Caption( szTitle, d_dialog_x, d_dialog_y, d_dialog_w );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (display) {\n\t\t\t\tFancy_Text_Print( szPrompt, d_prompt_x, d_prompt_y,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );\n\t\t\t\tif( szPrompt2 )\n\t\t\t\t\tFancy_Text_Print( szPrompt2, d_prompt2_x, d_prompt2_y,\n\t\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );\n\n\t\t\t\tcommands->Flag_List_To_Redraw();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = commands->Input();\n\n\t\t/*\n\t\t**\tThe first time through the processing loop, set the edit\n\t\t**\tgadget to have the focus. The\n\t\t**\tfocus must be set here since the gadget list has changed\n\t\t**\tand this change will cause any previous focus setting to be\n\t\t**\tcleared by the input processing routine.\n\t\t*/\n\t\tif (firsttime ) {\n\t\t\tfirsttime = false;\n\t\t\tEditBox.Set_Focus();\n\t\t\tEditBox.Flag_To_Redraw();\n\t\t}\n\n\t\t//\tMy hack for triggering escape and return on key up instead of down...\n\t\t//\tThe problem that was occurring was that the calling dialog would act on the key up,\n\t\t//\tthough this dialog handled the key down. ajw\n\t\tif( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) )\n\t\t{\n\t\t\tbEscapeDown = true;\n\t\t}\n\t\telse if( bEscapeDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );\n\t\t\tbEscapeDown = false;\n\t\t}\n\t\tif( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )\n\t\t{\n\t\t\tbReturnDown = true;\n\t\t}\n\t\telse if( bReturnDown )\n\t\t{\n\t\t\tinput = (KeyNumType)( BUTTON_OK | KN_BUTTON );\n\t\t\tbReturnDown = false;\n\t\t}\n\n\t\t//\tI really hate to do this, but...      ajw\n\t\tif( cancel_current_msgbox )\n\t\t{\n\t\t\tcancel_current_msgbox = false;\n\t\t\tinput = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );\n\t\t}\n\n\t\tif( disable_current_msgbox )\n\t\t{\n\t\t\tdisable_current_msgbox = false;\n\t\t\tEditBox.Disable();\n\t\t\t//\tThese do not actually draw. I am actually clearing the \"draw\" flag!\n\t\t\t//\tProblem is Disable sets them to redraw, and I don't want to, and there is no Flag_To_Redraw( false ).\n\t\t\tEditBox.GadgetClass::Draw_Me( true );\n\t\t\tif( szPrompt2 )\n\t\t\t{\n\t\t\t\tEditBox2.Disable();\n\t\t\t\tEditBox2.GadgetClass::Draw_Me( true );\n\t\t\t}\n\t\t\tOkBtn.Disable();\n\t\t\tOkBtn.GadgetClass::Draw_Me( true );\n\t\t\tCancelBtn.Disable();\n\t\t\tCancelBtn.GadgetClass::Draw_Me( true );\n\t\t\tif( szMiddleButton )\n\t\t\t{\n\t\t\t\tMiddleBtn.Disable();\n\t\t\t\tMiddleBtn.GadgetClass::Draw_Me( true );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t**\tProcess input.\n\t\t*/\n\t\tswitch( input )\n\t\t{\n//\t\tcase ( KN_ESC ):\n\t\tcase ( BUTTON_CANCEL | KN_BUTTON ):\n\t\t\tszReturn = szCancelButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n//\t\tcase KN_RETURN:\n\t\tcase ( BUTTON_EDIT | KN_BUTTON ):\t\t\t//\t(Return pressed while on edit.)\n\t\tcase ( BUTTON_OK | KN_BUTTON ):\n\t\t\tszReturn = szOkButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n\t\tcase ( BUTTON_MIDDLE | KN_BUTTON ):\n\t\t\tszReturn = szMiddleButton;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn szReturn;\n}\n\n#endif\n"
  },
  {
    "path": "REDALERT/SEDITDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#ifdef WOLAPI_INTEGRATION\n\n//\tSEditDlg.h - \"SimpleEditDlgClass\": An ok/cancel type dialog with a single edit box.\n//\tajw 07/21/98\n\n#include \"function.h\"\n\nclass SimpleEditDlgClass\n{\npublic:\n\tSimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept,\n\t\t\t\t\t\t\tconst char* szPrompt2 = NULL, int iEditCharsAccept2 = 0 );\n\tvirtual ~SimpleEditDlgClass();\n\n\tconst char* Show();\t\t\t\t\t//\tShows dialog, returns text of button pressed.\n\t\t\t\t\t\t\t\t\t\t//\tUnless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values.\n\n\tvoid\t\tSetButtons( const char* szOk, const char* szCancel, const char* szMiddle = NULL );\n\n\tchar\t\tszEdit[ 300 ];\t\t\t//\tiEditCharsAccept upper limit.\n\tchar\t\tszEdit2[ 300 ];\n\nprotected:\n\tint\t\t\tiDialogWidth;\t\t\t//\tX pixels width of entire dialog.\n\tchar*\t\tszTitle;\t\t\t\t//\tTitle of dialog, or NULL for no title.\n\n\tchar*\t\tszPrompt;\t\t\t\t//\tText appearing to the left of edit box.\n\tint\t\t\tiEditCharsAccept;\t\t//\tMax length of string allowed in edit, includes null-terminator.\n\n\tchar*\t\tszPrompt2;\n\tint\t\t\tiEditCharsAccept2;\n\n\tconst char*\tszOkButton;\t\t\t\t//\tText of button that acts like an Ok button. Appears on left.\n\tconst char*\tszCancelButton;\t\t\t//\tText of button that acts like an Cancel button. Appears on right.\n\tconst char* szMiddleButton;\t\t\t//\tOptional middle button text. Null = no middle button.\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SENDFILE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/*************************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S                  **\n *************************************************************************************\n *                                                                                   *\n *                 Project Name : Command & Conquer - Red Alert                      *\n *                                                                                   *\n *                    File Name : SENDFILE.CPP                                       *\n *                                                                                   *\n *                   Programmer : Steve Tall                                         *\n *                                                                                   *\n *                   Start Date : Audust 20th, 1996                                  *\n *                                                                                   *\n *                  Last Update : August 20th, 1996 [ST]                             *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Overview:                                                                         *\n *                                                                                   *\n *  Functions for scenario file transfer between machines                            *\n *                                                                                   *\n *-----------------------------------------------------------------------------------*\n * Functions:                                                             \t \t\t\t*\n *                                                                         \t\t\t\t*\n *                                                                         \t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#if (0)//PG\n#include \"function.h\"\n\n//#include \"WolDebug.h\"\n\n#ifdef WINSOCK_IPX\n#include \"WSProto.h\"\n#else\n\n#ifdef WIN32\n#include\t\"tcpip.h\"\n#else\n#include\t\"fakesock.h\"\n#endif\t//WIN32\n\n#endif\t//WINSOCK_IPX\n\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype);\nbool Send_Remote_File ( char *file_name, int gametype );\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nextern bool Is_Mission_Counterstrike (char *file_name);\nextern bool Is_Mission_Aftermath (char *file_name);\n#endif\n\n#define RESPONSE_TIMEOUT\t60*60\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n#endif\n\n/***********************************************************************************************\n * Get_Scenario_File_From_Host -- Initiates download of scenario file from game host           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    ptr to buffer to copy file name into                                              *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * OUTPUT:   true if file sucessfully downloaded                                               *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/22/96 3:06PM ST : Created                                                              *\n *=============================================================================================*/\nbool Get_Scenario_File_From_Host(char *return_name, int gametype)\n{\n\t//WWDebugString (\"RA95 - In Get_Scenario_From_Host\\n\");\n\n\tunsigned int file_length;\n\n\tSerialPacketType \tsend_packet;\n\tSerialPacketType \treceive_packet;\n\tGlobalPacketType\tnet_send_packet;\n\tGlobalPacketType\tnet_receive_packet;\n\tunsigned int\t\tpacket_len;\n\tunsigned short\t\tproduct_id;\n\n\tIPXAddressClass\tsender_address;\n\n\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\n\t/*\n\t** Send the scenario request using guaranteed delivery.\n\t*/\n\tif (!gametype) {\n\t\tmemset ((void*)&send_packet, 0, sizeof (send_packet));\n\t\tsend_packet.Command = SERIAL_REQ_SCENARIO;\n\t\tNullModem.Send_Message (&send_packet, sizeof(send_packet), 1);\n\t} else {\n\t\tmemset ((void*)&net_send_packet, 0, sizeof (net_send_packet));\n\t\tnet_send_packet.Command = NET_REQ_SCENARIO;\n\t\tIpx.Send_Global_Message (&net_send_packet, sizeof (net_send_packet),\n\t\t\t1, &(Session.HostAddress) );\n\t}\n\n\n\n\t//WWDebugString (\"RA95 - Waiting for response from host\\n\");\n\n\t/*\n\t** Wait for host to respond with a file info packet\n\t*/\n\tresponse_timer = RESPONSE_TIMEOUT;\n\tif (!gametype){\n\t\tdo {\n\t\t\tNullModem.Service();\n\n\t\t\tif (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {\n\n\t\t\t\tif (receive_packet.Command == SERIAL_FILE_INFO){\n\t\t\t\t\tstrcpy (return_name, receive_packet.ScenarioInfo.ShortFileName);\n\t\t\t\t\tfile_length = receive_packet.ScenarioInfo.FileLength;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( response_timer );\n\t}else{\n\t\tdo {\n\t\t\tIpx.Service();\n\t\t\tint receive_packet_length = sizeof (net_receive_packet);\n\t\t\tif (Ipx.Get_Global_Message (&net_receive_packet, &receive_packet_length,\n\t\t\t\t&sender_address, &product_id)){\n\n//WWDebugString (\"RA95 - Got packet from host\\n\");\n#ifdef WINSOCK_IPX\n\t\t\t\tif (net_receive_packet.Command == NET_FILE_INFO && sender_address == Session.HostAddress) {\n#else\t//WINSOCK_IPX\n\t\t\t\tif (net_receive_packet.Command == NET_FILE_INFO &&\n\t\t\t\t\t\t(Winsock.Get_Connected() || sender_address == Session.HostAddress)){\n#endif\t//WINSOCK_IPX\n\t\t\t\t\tstrcpy (return_name, net_receive_packet.ScenarioInfo.ShortFileName);\n\t\t\t\t\tfile_length = net_receive_packet.ScenarioInfo.FileLength;\n//WWDebugString (\"RA95 - Got file info packet from host\\n\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t\t{\n\t\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t\t}\n#endif\n\t\t} while ( response_timer );\n\t}\n\n//char rt[80];\n//sprintf (rt, \"RA95 - response_timer = %d\\n\", response_timer );\n//WWDebugString (rt);\n\n\t/*\n\t** If we timed out then something horrible has happened to the other player so just\n\t** return failure.\n\t*/\n\tif (!response_timer) return (false);\n\n//\tdebugprint( \"about to download '%s'\\n\", return_name );\n\n\t/*\n\t** Receive the file from the host\n\t*/\n\treturn (Receive_Remote_File ( return_name, file_length, gametype));\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Receive_Remote_File -- Handles incoming file download packets from the game host            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    file name to save as                                                              *\n *           length of file to expect                                                          *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * OUTPUT:   true if file downloaded was completed                                             *\n *                                                                                             *\n * WARNINGS: This fuction can modify the file name passed in                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   8/22/96 3:07PM ST : Created                                                               *\n *=============================================================================================*/\nbool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype)\n{\n\n\t//WWDebugString (\"RA95 - In Receive_Remote_File\\n\");\n\tunsigned short\t\tproduct_id;\n\tIPXAddressClass\tsender_address;\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint d_dialog_w = 200 *RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90*RESFACTOR;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*RESFACTOR;\n#else\n\tint d_cancel_w = 40*RESFACTOR;\n#endif\n\tint d_cancel_h = 9*RESFACTOR;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;\n\n\tint d_progress_w = 100*RESFACTOR;\n\tint d_progress_h = 10*RESFACTOR;\n\tint d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;\n\tint d_progress_y = d_dialog_y + 45*RESFACTOR;\n\n\tint\twidth;\n\tint\theight;\n\n\tchar *info_string = (char*)Text_String (TXT_RECEIVING_SCENARIO);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String(info_string, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t\tBUTTON_PROGRESS\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n#if (GERMAN | FRENCH)\n\t\td_cancel_x, d_cancel_y);\n#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#endif\n\n\tGaugeClass progress_meter (BUTTON_PROGRESS,\n\t\td_progress_x, d_progress_y, d_progress_w, d_progress_h);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PROGRESS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\n\tbool \t\t\tprocess = true;\n\tRedrawType \tdisplay = REDRAW_ALL;\t\t// redraw level\n\tKeyNumType \tinput;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\tbool\t\t\treturn_code;\n\tint\t\t\tupdate_time = 0;\n\n\n\n\tRemoteFileTransferType receive_packet;\n\n\tint \t\t\t\tlast_received_block = -1;\t\t//No blocks received yet\n\tunsigned int \ttotal_length = 0;\n\tunsigned int\tpacket_len;\n\n\t/*\n\t** If the file name is already in use, use the temp file name\n\t*/\n\tCCFileClass test_file (file_name);\n\tif (test_file.Is_Available()){\n\t\tstrcpy (file_name, \"DOWNLOAD.TMP\");\n\t}\n\n\tRawFileClass save_file (file_name);\n\n\t/*\n\t** If the file already exists then delete it and re-create it.\n\t*/\n\tif (save_file.Is_Available()) save_file.Delete();\n\n\t/*\n\t** Open the file for write\n\t*/\n\tsave_file.Open ( WRITE );\n\n\tcommands = &cancelbtn;\n\tcommands->Add_Tail (progress_meter);\n\n\tprogress_meter.Set_Maximum(100);\t\t// Max is 100%\n\tprogress_meter.Set_Value(0);\t\t\t// Current is 0%\n\n\t/*\n\t** Wait for all the blocks to arrive\n\t*/\n\n\tdo\t{\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t{\n\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n#endif\n\n\t\tif (display){\n\n\t\t\tif (display >= REDRAW_BACKGROUND){\n\n\t\t\t\tHide_Mouse();\n\t\t\t\t/*\n\t\t\t\t** Redraw backgound & dialog box\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t\tShow_Mouse();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_BUTTONS){\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_PROGRESS){\n\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t}\n\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\n\t\tif (!gametype){\n\t\t\tNullModem.Service();\n\n\t\t\tif (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {\n\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK){\n\n\t\t\t\t\tif (receive_packet.BlockNumber == last_received_block + 1){\n\n\t\t\t\t\t\tsave_file.Write ( receive_packet.RawData, receive_packet.BlockLength );\n\t\t\t\t\t\ttotal_length += receive_packet.BlockLength;\n\t\t\t\t\t\tlast_received_block ++;\n\n\t\t\t\t\t\tupdate_time++;\n\t\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( (total_length*100) / file_length );\n\t\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (total_length >= file_length){\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\treturn_code = true;\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tIpx.Service();\n\n\t\t\tint receive_packet_len = sizeof (receive_packet);\n\t\t\tif (Ipx.Get_Global_Message (&receive_packet, &receive_packet_len,\n\t\t\t\t&sender_address, &product_id)){\n\n#ifdef WINSOCK_IPX\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK && sender_address == Session.HostAddress){\n#else\t//WINSOCK_IPX\n\t\t\t\tif (receive_packet.Command == NET_FILE_CHUNK &&\n\t\t\t\t\t\t\t(Winsock.Get_Connected() || sender_address == Session.HostAddress)){\n#endif\t//WINSOCK_IPX\n\n\t\t\t\t\tif (receive_packet.BlockNumber == last_received_block + 1){\n\n\t\t\t\t\t\tsave_file.Write ( receive_packet.RawData, receive_packet.BlockLength );\n\t\t\t\t\t\ttotal_length += receive_packet.BlockLength;\n\t\t\t\t\t\tlast_received_block ++;\n\n\t\t\t\t\t\tupdate_time++;\n\t\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( (total_length*100) / file_length );\n\t\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (total_length >= file_length){\n\t\t\t\t\t\t\tprocess = false;\n\t\t\t\t\t\t\treturn_code = true;\n\t\t\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\tif (process){\n\t\t\tinput = cancelbtn.Input();\n\n\t\t\t/*\n\t\t\t---------------------------- Process input ----------------------------\n\t\t\t*/\n\t\t\tswitch (input) {\n\n\t\t\t\t/*\n\t\t\t\t** Cancel. Just return to the main menu\n\t\t\t\t*/\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\n\t} while ( process );\n\n\tsave_file.Close();\n\n\t/*\n\t** Update the internal list of scenarios to include the downloaded one so we know about it\n\t**  for the next game.\n\t*/\n\tSession.Read_Scenario_Descriptions();\n\n\treturn (return_code);\n}\n\n\n\n\n\n\n/***********************************************************************************************\n * Send_Remote_File -- Sends a file to game clients                                            *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    File name                                                                         *\n *                                                                                             *\n * OUTPUT:   true if file transfer was successfully completed                                  *\n *           game type - 0 for modem/null modem, 1 otherwise                                   *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    8/22/96 3:09PM ST : Created                                                              *\n *=============================================================================================*/\nbool Send_Remote_File ( char *file_name, int gametype )\n{\n\t//WWDebugString (\"RA95 - In Send_Remote_File\\n\");\n\n\t/*\n\t** Dialog & button dimensions\n\t*/\n\tint factor\t\t\t= (SeenBuff.Get_Width() == 320) ? 1 : 2;\n\n\tint d_dialog_w = 240 *factor;\t\t\t\t\t\t\t\t\t\t\t// dialog width\n\tint d_dialog_h = 90*factor;\t\t\t\t\t\t\t\t\t\t\t// dialog height\n\tint d_dialog_x = ((320*factor - d_dialog_w) / 2);\t\t\t\t// dialog x-coord\n\tint d_dialog_y = ((200*factor - d_dialog_h) / 2);\t\t\t\t// centered y-coord\n\tint d_dialog_cx = d_dialog_x + (d_dialog_w / 2);\t\t// center x-coord\n\n\tint d_margin1=10;\n\tint d_txt6_h=15;\n\n#if (GERMAN | FRENCH)\n\tint d_cancel_w = 50*factor;\n#else\n\tint d_cancel_w = 40*factor;\n#endif\n\tint d_cancel_h = 9*factor;\n\tint d_cancel_x = d_dialog_cx - d_cancel_w / 2;\n\tint d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;\n\n\tint d_progress_w = 100*factor;\n\tint d_progress_h = 10*factor;\n\tint d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;\n\tint d_progress_y = d_dialog_y + 45*factor;\n\n\tint\twidth;\n\tint\theight;\n\n\tchar *info_string = (char*)Text_String (TXT_SENDING_SCENARIO);\n\n\tCDTimerClass<SystemTimerClass> response_timer;\t\t// timeout timer for waiting for responses\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\tFormat_Window_String(info_string, SeenBuff.Get_Height(), width, height);\n\n\n\t/*\n\t** Button Enumerations\n\t*/\n\tenum {\n\t\tBUTTON_CANCEL = 100,\n\t\tBUTTON_PROGRESS\n\t};\n\n\t/*\n\t** Buttons\n\t*/\n\t//TextButtonClass *buttons;\t\t\t\t\t\t\t\t\t\t// button list\n\n\tTextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,\n\t\tTPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,\n#if (GERMAN | FRENCH)\n\t\td_cancel_x, d_cancel_y);\n#else\n\t\td_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);\n#endif\n\n\tGaugeClass progress_meter (BUTTON_PROGRESS,\n\t\td_progress_x, d_progress_y, d_progress_w, d_progress_h);\n\n\tFancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),\n\t\tTBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\n\ttypedef enum {\n\t\tREDRAW_NONE = 0,\n\t\tREDRAW_PROGRESS,\n\t\tREDRAW_BUTTONS,\n\t\tREDRAW_BACKGROUND,\n\t\tREDRAW_ALL = REDRAW_BACKGROUND\n\t} RedrawType;\n\n\n\tbool \t\t\tprocess = true;\n\tRedrawType \tdisplay = REDRAW_ALL;\t\t// redraw level\n\tKeyNumType \tinput;\n\tGadgetClass *commands;\t\t\t\t\t// button list\n\tbool\t\t\treturn_code;\n\tint\t\t\tupdate_time = 0;\n\n\n\tint file_length;\n\tint block_number;\n\tint max_chunk_size;\n\tint total_blocks;\n\tint bytes_left;\n\n\tvoid *read_ptr;\n\n\tRemoteFileTransferType\tsend_packet;\n\tSerialPacketType\t\t\tfile_info;\n\tGlobalPacketType\t\t\tnet_file_info;\n\n\n\tCCFileClass send_file (file_name);\n\n\tif ( !send_file.Is_Available() ){\n\t\t//WWDebugString (\"RA95 - Error - could not find file to send to client\\n\");\n//\t\tdebugprint(\"RA95 - Error - could not find file to send to client\\n\");\n\t\treturn (false);\n\t}\n\tfile_length = send_file.Size();\n\n\tresponse_timer = RESPONSE_TIMEOUT;\n\n\t/*\n\t** Send the file info to the remote machine(s)\n\t*/\n\tif (!gametype){\n\t\tfile_info.Command = SERIAL_FILE_INFO;\n\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], file_name);\n#ifdef FIXIT_VERSION_3\n\t\t//\tIf we're sending an official map, always send it to 'download.tmp'.\n\t\tif( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're sending an Aftermath map, always send it to 'download.tmp'.\n\t\tif (Is_Mission_Aftermath(file_name)) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#endif\n#endif\n\t\tfile_info.ScenarioInfo.FileLength = file_length;\n\t\tNullModem.Send_Message (&file_info, sizeof (file_info), 1);\n\t\twhile (NullModem.Num_Send() > 0 && response_timer){\n\t\t\tNullModem.Service();\n\t\t}\n\t} else {\n\t\tnet_file_info.Command = NET_FILE_INFO;\n\t\tstrcpy (&net_file_info.ScenarioInfo.ShortFileName[0], file_name);\n//\t\tdebugprint( \"Uploading '%s'\\n\", file_name );\n#ifdef FIXIT_VERSION_3\n\t\t//\tIf we're sending an official map, always send it to 'download.tmp'.\n\t\tif( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {\n\t\t\tstrcpy (&net_file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t}\n#else\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If we're sending an Aftermath map, always send it to 'download.tmp'.\n\t\tif (Is_Mission_Aftermath(file_name)) {\n\t\t\tstrcpy (&file_info.ScenarioInfo.ShortFileName[0], \"DOWNLOAD.TMP\");\n\t\t\t//\tThere was a bug here: s/b net_file_info. This means that players that don't have Aftermath could have been \n\t\t\t//\taccumulating Aftermath maps all this time!!! (File wasn't getting renamed to \"DOWNLOAD.TMP\".)\n\t\t}\n#endif\n#endif\n//\t\tdebugprint( \"ShortFileName is '%s'\\n\", net_file_info.ScenarioInfo.ShortFileName );\n\t\tnet_file_info.ScenarioInfo.FileLength = file_length;\n\n\t\tfor (int i=0 ; i<Session.RequestCount ; i++){\n\t\t\tIpx.Send_Global_Message (&net_file_info, sizeof (GlobalPacketType),\n\t\t\t\t1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );\n\t\t}\n\n\t\twhile (Ipx.Global_Num_Send() > 0 && response_timer) {\n\t\t\tIpx.Service();\n\t\t}\n\t}\n\n\n\tmax_chunk_size = MAX_SEND_FILE_PACKET_SIZE;\n\ttotal_blocks = (file_length + max_chunk_size-1) / max_chunk_size;\n\tbytes_left = file_length;\n\n\tsend_file.Open ( READ );\n\n\n\tcommands = &cancelbtn;\n\tcommands->Add_Tail (progress_meter);\n\n\tprogress_meter.Set_Maximum(100);\t\t// Max is 100%\n\tprogress_meter.Set_Value(0);\t\t\t// Current is 0%\n\n\n\tblock_number = 0;\n\n\twhile ( process ){\n\n#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = REDRAW_ALL;\n\t\t}\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\tif( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )\n\t\t{\n\t\t\tpWolapi->pChat->PumpMessages();\n\t\t\tpWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;\n\t\t}\n#endif\n\n\t\tif (display){\n\n\t\t\tif (display >= REDRAW_BACKGROUND){\n\n\t\t\t\tHide_Mouse();\n\t\t\t\t/*\n\t\t\t\t** Redraw backgound & dialog box\n\t\t\t\t*/\n\t\t\t\tLoad_Title_Page(true);\n\t\t\t\tSet_Palette(CCPalette);\n\n\t\t\t\tDialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);\n\n\t\t\t\t/*\n\t\t\t\t** Dialog & Field labels\n\t\t\t\t*/\n\t\t\t\tDraw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);\n\n\t\t\t\tFancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*factor,\n\t\t\t\t\t\t\t\t\tGadgetClass::Get_Color_Scheme(), TBLACK,\n\t\t\t\t\t\t\t\t\tTPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);\n\n\t\t\t\tShow_Mouse();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_BUTTONS){\n\n\t\t\t\tcommands->Draw_All();\n\n\t\t\t}\n\n\t\t\tif (display >= REDRAW_PROGRESS){\n\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t}\n\n\t\t\tdisplay = REDRAW_NONE;\n\t\t}\n\n\n\t\tif (!gametype){\n\t\t\tNullModem.Service();\n\n\n\t\t\tif (block_number < total_blocks){\n\n\t\t\t\tif ( NullModem.Num_Send() <2 ){\n\n\t\t\t\t\tsend_packet.Command = SERIAL_FILE_CHUNK;\n\t\t\t\t\tsend_packet.BlockNumber = block_number;\n\t\t\t\t\tsend_packet.BlockLength = MIN (file_length, max_chunk_size);\n\n\t\t\t\t\tfile_length -= send_packet.BlockLength;\n\n\t\t\t\t\tread_ptr = &send_packet.RawData[0];\n\n\t\t\t\t\tif (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){\n\t\t\t\t\t\tNullModem.Send_Message ((void*)&send_packet, sizeof(send_packet), 1);\n\t\t\t\t\t}\n\n\t\t\t\t\tblock_number++;\n\n\t\t\t\t\tupdate_time++;\n\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\tprogress_meter.Set_Value ( (block_number*100) / total_blocks );\n\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif (NullModem.Num_Send() == 0){\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = true;\n\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\tprogress_meter.Draw_Me(true);\n\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t}else{\n\t\t\tIpx.Service();\n\n\t\t\tif (block_number < total_blocks){\n\n\t\t\t\tif ( Ipx.Global_Num_Send() == 0 ){\n\n\t\t\t\t\tsend_packet.Command = SERIAL_FILE_CHUNK;\n\t\t\t\t\tsend_packet.BlockNumber = block_number;\n\t\t\t\t\tsend_packet.BlockLength = MIN (file_length, max_chunk_size);\n\n\t\t\t\t\tfile_length -= send_packet.BlockLength;\n\n\t\t\t\t\tread_ptr = &send_packet.RawData[0];\n\n\t\t\t\t\tif (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){\n\t\t\t\t\t\tfor (int i=0 ; i<Session.RequestCount ; i++){\n\t\t\t\t\t\t\tIpx.Send_Global_Message (&send_packet, sizeof (send_packet),\n\t\t\t\t\t\t\t\t1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tblock_number++;\n\n\t\t\t\t\tupdate_time++;\n\t\t\t\t\tif (update_time >7){\n\t\t\t\t\t\tprogress_meter.Set_Value ( (block_number*100) / total_blocks );\n\t\t\t\t\t\tdisplay = REDRAW_PROGRESS;\n\t\t\t\t\t\tupdate_time = 0;;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif (Ipx.Global_Num_Send() == 0){\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = true;\n\t\t\t\t\tprogress_meter.Set_Value ( 100 );\n\t\t\t\t\tprogress_meter.Draw_Me(true);\n\t\t\t\t}\n\t\t\t}\n\n\n\n\t\t}\n\n\n\t\tif (process){\n\t\t\tinput = cancelbtn.Input();\n\n\t\t\t/*\n\t\t\t---------------------------- Process input ----------------------------\n\t\t\t*/\n\t\t\tswitch (input) {\n\n\t\t\t\t/*\n\t\t\t\t** Cancel. Just return to the main menu\n\t\t\t\t*/\n\t\t\t\tcase (KN_ESC):\n\t\t\t\tcase (BUTTON_CANCEL | KN_BUTTON):\n\t\t\t\t\tprocess = false;\n\t\t\t\t\treturn_code = false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t}\n\n\treturn (return_code);\n}\n#endif"
  },
  {
    "path": "REDALERT/SEQCONN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\seqconn.cpv   1.10   01 Mar 1996 18:29:54   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.CPP                              *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 20, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995 [BRR]\t\t\t\t\t\t\t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n * Functions:    \t\t\t                                                   *\n *   SequencedConnClass::SequencedConnClass -- class constructor           *\n *   SequencedConnClass::~SequencedConnClass -- class destructor           *\n *   SequencedConnClass::Init -- Initializes connection queue to empty\t\t*\n *   SequencedConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *   SequencedConnClass::Receive_Packet -- adds packet to receive queue\t\t*\n *   SequencedConnClass::Get_Packet -- gets a packet from receive queue\t\t*\n *   SequencedConnClass::Service_Send_Queue -- services the send queue\t\t*\n *   SequencedConnClass::Service_Receive_Queue -- services recieve queue\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0)//PG\n#include \"function.h\"\n\n#include \"WolDebug.h\"\n\n/***************************************************************************\n * SequencedConnClass::SequencedConnClass -- class constructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnumsend\t\t\tdesired # of entries for the send queue\t\t\t\t\t*\n *\t\tnumreceive\t\tdesired # of entries for the recieve queue\t\t\t\t*\n *\t\tmaxlen\t\t\tmax length of an application packet\t\t\t\t\t\t\t*\n *\t\tmagicnum\t\t\tthe packet \"magic number\" for this connection\t\t\t*\n *\t\tretry_delta\t\tthe time to wait between sends\t\t\t\t\t\t\t\t*\n *\t\tmax_retries\t\tthe max # of retries allowed for a packet\t\t\t\t\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *\t\ttimeout\t\t\tthe max amount of time before we give up on a packet\t*\n *\t\t\t\t\t\t\t(-1 means retry forever, based on this parameter)\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSequencedConnClass::SequencedConnClass (int numsend, int numreceive, \n\tint maxlen, unsigned short magicnum, unsigned long retry_delta,\n\tunsigned long max_retries, unsigned long timeout) :\n\tConnectionClass (maxlen, magicnum, retry_delta, max_retries, timeout)\n{\n\tNumRecNoAck = 0;\n\tNumRecAck = 0;\n\tNumSendNoAck = 0;\n\tNumSendAck = 0;\n\n\t/*------------------------------------------------------------------------\n\tAllocate the packet Queue.  This will store incoming packets (which will\n\tbe placed there by the Connection Manager), and outgoing packets (which\n\tare placed there by this class when it \"sends\" a packet).\n\t------------------------------------------------------------------------*/\n\tQueue = new CommQueueClass (numsend, numreceive, MaxPacketLen);\n\n}\t/* end of SequencedConnClass */\n\n\n/***************************************************************************\n * SequencedConnClass::~SequencedConnClass -- class destructor             *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nSequencedConnClass::~SequencedConnClass ()\n{\n\tdelete Queue;\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Init -- Initializes connection queue to empty\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nvoid SequencedConnClass::Init (void)\n{\n\tQueue->Init();\n\n}\t/* end of Init */\n\n\n/***************************************************************************\n * SequencedConnClass::Send_Packet -- adds a packet to the send queue\t\t*\n *                                                                         *\n * This routine prefixes the given buffer with a CommHeaderType and\t\t\t*\n * queues the resulting packet into the Send Queue.  (It's actually the\t\t*\n * Service() routine that handles the hardware-dependent Send of the data).*\n * The packet's MagicNumber, Code, and PacketID are set here.\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\t\tbuffer to send\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\t\tlength of buffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tack_req\t\ttrue = ACK is required for this packet; false = isn't\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was queue'd OK, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Send_Packet (void * buf, int buflen, int ack_req)\n{\n\t/*........................................................................\n\tSet the magic # for the packet\n\t........................................................................*/\n\t((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;\n\n\t/*........................................................................\n\tSet the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't\n\tSet the packet ID to the appropriate counter value.\n\t........................................................................*/\n\tif (ack_req) {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;\n\t} else {\n\t\t((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;\n\t\t((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;\n\t}\n\n\t/*........................................................................\n\tNow build the packet\n\t........................................................................*/\n\tmemcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);\n\n\t/*........................................................................\n\tAdd it to the queue.\n\t........................................................................*/\n\tif (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType))) {\n\t\tif (ack_req) {\n\t\t\tNumSendAck++;\n\t\t} else {\n\t\t\tNumSendNoAck++;\n\t\t}\n\t\treturn(true);\n\n\t} else {\n\t\treturn(false);\n\t}\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Receive_Packet -- adds packet to the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tbuffer to process (already includes CommHeaderType)\t\t\t*\n *\t\tbuflen\tlength of buffer to process\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was processed OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Receive_Packet (void * buf, int buflen)\n{\n\tCommHeaderType *packet;\t\t\t\t\t// ptr to this packet\n\tSendQueueType *send_entry;\t\t\t\t// ptr to send entry header\n\tReceiveQueueType *rec_entry;\t\t\t// ptr to receive entry header\n\tCommHeaderType *entry_data;\t\t\t// ptr to queue entry data\n\tint save_packet = 1;\t\t\t\t\t\t// 0 = this is a resend, or \n\t\t\t\t\t\t\t\t\t\t\t\t\t//  out-of-order packet\n\n\t/*\n\t--------------------------- Check the magic # ----------------------------\n\t*/\n\tpacket = (CommHeaderType *)buf;\n\tif (packet->MagicNumber!=MagicNum)\n\t\treturn(false);\n\t\n\t/*------------------------------------------------------------------------\n\tProcess the packet based on its Code\n\t------------------------------------------------------------------------*/\n\tswitch (packet->Code) {\n\t\t/*.....................................................................\n\t\tDATA: If this is a No-Ack packet, always save it.  Otherwise, only\n\t\tsave it if it's received in the proper sequence.\n\t\t.....................................................................*/\n\t\tcase PACKET_DATA_ACK:\n\t\tcase PACKET_DATA_NOACK:\n\t\t\tif (packet->Code == PACKET_DATA_NOACK) {\n#ifdef DEBUG_SEQ\nprintf(\"PACKET_DATA_NOACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t\tsave_packet = 1;\n\t\t\t} else {\n#ifdef DEBUG_SEQ\nprintf(\"PACKET_DATA_ACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t\tif ((packet->PacketID == NumRecAck)) {\n\t\t\t\t\tsave_packet = 1;\n\t\t\t\t} else {\n\t\t\t\t\tsave_packet = 0;\n\t\t\t\t\t/*...............................................................\n\t\t\t\t\tIf this is a resend of our next-available received message, it \n\t\t\t\t\tmeans the other app didn't get our ACK, so mark it as \n\t\t\t\t\tnon-acknowledged to tell Service_Receive_Queue to send an ACK.\n\t\t\t\t\t...............................................................*/\n\t\t\t\t\trec_entry = Queue->Next_Receive();\n\t\t\t\t\tif (rec_entry) {\n\t\t\t\t\t\tentry_data = (CommHeaderType *)rec_entry->Buffer;\n\t\t\t\t\t\tif (entry_data->PacketID==packet->PacketID &&\n\t\t\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\t\t\trec_entry->IsACK = 0;\n#ifdef DEBUG_SEQ\nprintf(\"(Resend)\\n\");\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t...................... queue this packet ........................\n\t\t\t*/\n\t\t\tif (save_packet) {\n\t\t\t\tif (!Queue->Queue_Receive(buf, buflen)) {\n\t\t\t\t\treturn(false);\n\t\t\t\t}\n\t\t\t\tif (packet->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tNumRecAck++;\n\t\t\t\t} else {\n\t\t\t\t\tNumRecNoAck++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*.....................................................................\n\t\tACK: If this ACK is for the latest-sent packet, mark that packet as \n\t\tacknowledged, then throw this packet away.  Otherwise, ignore the ACK \n\t\t(if we re-sent before we received the other system's first ACK, this \n\t\tACK will be a leftover)\n\t\t.....................................................................*/\n\t\tcase PACKET_ACK:\n#ifdef DEBUG_SEQ\nprintf(\"ACK received (%d)\\n\",packet->PacketID);\n#endif\n\t\t\t/*\n\t\t\t....................... Get queue entry ptr ........................\n\t\t\t*/\n\t\t\tsend_entry = Queue->Next_Send();\n\t\t\t/*\n\t\t\t............... If ptr is valid, get ptr to its data ...............\n\t\t\t*/\n\t\t\tif (send_entry!=NULL) {\n\t\t\t\tentry_data = (CommHeaderType *)send_entry->Buffer;\n\n\t\t\t\t/*\n\t\t\t\t.............. If ACK is for this entry, mark it ................\n\t\t\t\t*/\n\t\t\t\tif (packet->PacketID==entry_data->PacketID && \n\t\t\t\t\tentry_data->Code == PACKET_DATA_ACK) {\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t\n\t\t/*.....................................................................\n\t\tDefault: ignore the packet\n\t\t.....................................................................*/\n\t\tdefault:\n\t\t\tbreak;\n\n\t}\t/* end of switch */\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Get_Packet -- gets a packet from the receive queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tbuf\t\tlocation to store buffer\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\tbuflen\tfilled in with length of 'buf'\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = packet was read, 0 = wasn't\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Get_Packet (void * buf, int *buflen)\n{\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tint packetlen;\t\t\t\t\t\t\t\t\t\t// size of received packet\n\n\t/*\n\t------------------ Get ptr to the next available entry -------------------\n\t*/\n\trec_entry = Queue->Next_Receive();\n\n\t/*\n\t------------------------ Read it if it's un-read -------------------------\n\t*/\n\tif (rec_entry!=NULL && rec_entry->IsRead==0) {\n\t\t/*\n\t\t........................... Mark as read ..............................\n\t\t*/\n\t\trec_entry->IsRead = 1;\n\n\t\t/*\n\t\t.......................... Copy data packet ...........................\n\t\t*/\n\t\tpacketlen = rec_entry->BufLen - sizeof(CommHeaderType);\n\t\tif (packetlen > 0) {\n\t\t\tmemcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType), packetlen);\n\t\t}\n\t\t(*buflen) = packetlen;\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Service_Send_Queue -- services the send queue\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Service_Send_Queue (void)\n{\n\tSendQueueType *send_entry;\t\t\t\t\t\t// ptr to send queue entry\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\tunsigned long curtime;\t\t\t\t\t\t\t// current time\n\n\t/*------------------------------------------------------------------------\n\t- If the next packet is ACK'd remove it from the queue\n\t- If the next packet isn't ACK'd, [re-]send it\n\t------------------------------------------------------------------------*/\n\t/*\n\t......................... Get ptr to data to send ........................\n\t*/\n\tsend_entry = Queue->Next_Send();\n\tif (send_entry==NULL)\n\t\treturn(true);\n\n\t/*\n\t------------------ If ACK has been received, unqueue it ------------------\n\t*/\n\tif (send_entry->IsACK) {\n\n\t\t/*\n\t\t.................. Update this queue's response time ..................\n\t\t*/\n\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\tif (packet_hdr->Code == PACKET_DATA_ACK) {\n\t\t\tQueue->Add_Delay(Time() - send_entry->FirstTime);\n\t\t}\n\n\t\t/*\n\t\t......................... unqueue the packet ..........................\n\t\t*/\n#ifdef DEBUG_SEQ\nprintf(\">>>Unqueueing Receive packet #%d<<<\\n\",packet_hdr->PacketID);\n#endif\n\t\tQueue->UnQueue_Send(NULL,NULL);\n\t} else {\n\n\t\t/*\n\t\t----------------- ACK not received yet, [re-]send packet -----------------\n\t\t*/\n\t\t/*.....................................................................\n\t\tOnly send the message if time has elapsed.  (The message's Time\n\t\tfields are init'd to 0 when a message is queue'd or unqueue'd, so the\n\t\tfirst time through, the delta time will appear large.)\n\t\t.....................................................................*/\n\t\tcurtime = Time();\n\t\tif (curtime - send_entry->LastTime > RetryDelta) {\n\t\t\t/*\n\t\t\t......................... Send the message .........................\n\t\t\t*/\n\t\t\tSend (send_entry->Buffer, send_entry->BufLen);\n\t\t\t/*\n\t\t\t....................... Fill in Time fields ........................\n\t\t\t*/\n\t\t\tsend_entry->LastTime = curtime;\n\t\t\tif (send_entry->SendCount==0) {\n\t\t\t\tsend_entry->FirstTime = curtime;\n\t\t\t\t/*...............................................................\n\t\t\t\tIf this is the 1st time we're sending this packet, and it doesn't\n\t\t\t\trequire an ACK, mark it as ACK'd; then, the next time through,\n\t\t\t\tit will just be removed from the queue.\n\t\t\t\t...............................................................*/\n\t\t\t\tpacket_hdr = (CommHeaderType *)send_entry->Buffer;\n\t\t\t\tif (packet_hdr->Code == PACKET_DATA_NOACK)\n\t\t\t\t\tsend_entry->IsACK = 1;\n\t\t\t}\n\n#ifdef DEBUG_SEQ\npacket_hdr = (CommHeaderType *)send_entry->Buffer;\nif (packet_hdr->Code == PACKET_DATA_NOACK) {\n\tprintf(\"Sending PACKET_DATA_NOACK (%d)\\n\",packet_hdr->PacketID);\n} else {\n\tprintf(\"Sending PACKET_DATA_ACK (%d)\\n\",packet_hdr->PacketID);\n}\n#endif\n\t\t\t/*\n\t\t\t......................... Update SendCount .........................\n\t\t\t*/\n\t\t\tsend_entry->SendCount++;\n\t\t\t/*..................................................................\n\t\t\tPerform error detection, based on either MaxRetries or Timeout\n\t\t\t..................................................................*/\n\t\t\tif (MaxRetries != -1 && send_entry->SendCount > MaxRetries)\n\t\t\t\treturn(false);\n\t\t\tif (Timeout != -1 && send_entry->LastTime - \n\t\t\t\tsend_entry->FirstTime > Timeout)\n\t\t\t\treturn(false);\n\n\t\t}\n\t}\n\n\treturn(true);\n}\n\n\n/***************************************************************************\n * SequencedConnClass::Service_Receive_Queue -- services the recieve queue\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/20/1994 BR : Created.                                              *\n *=========================================================================*/\nint SequencedConnClass::Service_Receive_Queue (void)\n{\n\tCommHeaderType ackpacket;\t\t\t\t\t\t// ACK packet to send\n\tReceiveQueueType *rec_entry;\t\t\t\t\t// ptr to receive entry header\n\tCommHeaderType *packet_hdr;\t\t\t\t\t// packet header\n\n\t/*------------------------------------------------------------------------\n\tGet a pointer to the next received entry\n\t------------------------------------------------------------------------*/\n\trec_entry = Queue->Next_Receive();\n\tif (rec_entry==NULL)\n\t\treturn(true);\n\n\t/*------------------------------------------------------------------------\n\tIf this packet doesn't require an ACK, mark it as ACK'd.\n\t------------------------------------------------------------------------*/\n\tpacket_hdr = (CommHeaderType *)(rec_entry->Buffer);\n\tif (packet_hdr->Code==PACKET_DATA_NOACK)\n\t\trec_entry->IsACK = 1;\n\n\t/*------------------------------------------------------------------------\n\tIf this packet hasn't been ACK'd, send an ACK:\n\t- Fill in the MagicNum & the Code\n\t- Set the PacketID to the same ID that the sending system used, so the\n\t  sending system knows which packet the ACK is for\n\t------------------------------------------------------------------------*/\n\tif (rec_entry->IsACK==0) {\n#ifdef DEBUG_SEQ\nprintf(\"Sending ACK (%d)\\n\",packet_hdr->PacketID);\n#endif\n\t\tackpacket.MagicNumber = MagicNum;\n\t\tackpacket.Code = PACKET_ACK;\n\t\tackpacket.PacketID = packet_hdr->PacketID;\n\n\t\tSend((char *)&ackpacket, sizeof(CommHeaderType));\n\n\t\trec_entry->IsACK = 1;\n\t}\n\t\t\t\n\t/*------------------------------------------------------------------------\n\tIf this packet has been read by the application, and has been ACK'd, and\n\tthere is another packet in the queue behind this one, it means the other\n\tsystem got the ACK we sent for this packet; remove this packet from the\n\tqueue.\n\t------------------------------------------------------------------------*/\n\tif (rec_entry!=NULL && rec_entry->IsRead && rec_entry->IsACK &&\n\t\tQueue->Num_Receive() > 1) {\n#ifdef DEBUG_SEQ\nprintf(\">>>Unqueueing Send packet #%d<<<\\n\",packet_hdr->PacketID);\n#endif\n\t\tQueue->UnQueue_Receive(NULL,NULL);\n\t}\n\n\treturn(true);\n}\n\n#endif"
  },
  {
    "path": "REDALERT/SEQCONN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\seqconn.h_v   1.13   01 Mar 1996 17:45:24   JOE_BOSTIC  $ */\n/***************************************************************************\n **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n ***************************************************************************\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SEQCONN.H                                *\n *                                                                         *\n *                   Programmer : Bill Randolph                            *\n *                                                                         *\n *                   Start Date : December 19, 1994                        *\n *                                                                         *\n *                  Last Update : April 9, 1995   [BR]                 \t\t*\n *                                                                         *\n *-------------------------------------------------------------------------*\n *                                                                         *\n * This class provides a \"Sequenced\" ACK/Retry approach to packet\t\t\t\t*\n * transmission.  It waits until the last packet has been ACK'd before\t\t*\n * sending another packet.  Thus, it guarantees order of delivery of\t\t\t*\n * packets, but its performance will be slower than the Non-Sequenced\t\t*\n * approach.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\tA derived class must provide:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - Init: Initialization of any hardware-specific values.\t\t\t\t\t\t*\n * - Send: a hardware-dependent send routine.\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SEQCONN_H\n#define SEQCONN_H\n\n#include \"connect.h\"\n#include \"comqueue.h\"\n\n\n/*\n***************************** Class Declaration *****************************\n*/\nclass SequencedConnClass : public ConnectionClass\n{\n\t/*\n\t---------------------------- Public Interface ----------------------------\n\t*/\n\tpublic:\n\t\t/*.....................................................................\n\t\tConstructor/destructor.\n\t\t.....................................................................*/\n\t\tSequencedConnClass (int numsend, int numrecieve, int maxlen, \n\t\t\tunsigned short magicnum, unsigned long retry_delta,\n\t\t\tunsigned long max_retries, unsigned long timeout);\n\t\tvirtual ~SequencedConnClass ();\n\n\t\t/*.....................................................................\n\t\tInitialization.\n\t\t.....................................................................*/\n\t\tvirtual void Init (void);\n\n\t\t/*.....................................................................\n\t\tSend/Receive routines.\n\t\t.....................................................................*/\n\t\tvirtual int Send_Packet (void * buf, int buflen, int ack_req);\n\t\tvirtual int Receive_Packet (void * buf, int buflen);\n\t\tvirtual int Get_Packet (void * buf, int *buflen);\n\n\t\t/*.....................................................................\n\t\tThe packet queue.\n\t\t.....................................................................*/\n\t\tCommQueueClass *Queue;\n\n\t/*\n\t-------------------------- Protected Interface ---------------------------\n\t*/\n\tprotected:\n\t\t/*.....................................................................\n\t\tRoutines to service the Send & Receive queues.\n\t\t.....................................................................*/\n\t\tvirtual int Service_Send_Queue (void);\n\t\tvirtual int Service_Receive_Queue (void);\n\n\t\t/*.....................................................................\n\t\tRunning totals of # of packets we send & receive which require an ACK, \n\t\tand those that don't.\n\t\t.....................................................................*/\n\t\tunsigned long NumRecNoAck;\n\t\tunsigned long NumRecAck;\n\t\tunsigned long NumSendNoAck;\n\t\tunsigned long NumSendAck;\n\n};\n\n#endif\n/*************************** end of seqconn.h ******************************/\n"
  },
  {
    "path": "REDALERT/SESSION.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/SESSION.CPP 3     3/10/97 6:23p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SESSION.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Bill R. Randolph                                             *\n *                                                                                             *\n *                   Start Date : 11/30/95                                                     *\n *                                                                                             *\n *                  Last Update : September 10, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SessionClass::SessionClass -- Constructor                                                 *\n *   SessionClass::~SessionClass -- Destructor                                                 *\n *   SessionClass::One_Time -- one-time initializations                                        *\n *   SessionClass::Init -- Initializes all values                                              *\n *   SessionClass::Create_Connections -- forms connections to other players                    *\n *   SessionClass::Am_I_Master -- tells if the local system is the \"master\"                    *\n *   SessionClass::Save -- Saves this class to a file                                          *\n *   SessionClass::Load -- Loads this class from a file                                        *\n *   SessionClass::Read_MultiPlayer_Settings -- reads settings from INI                        *\n *   SessionClass::Write_MultiPlayer_Settings -- writes settings to INI                        *\n *   SessionClass::Read_Scenario_Descriptions -- reads scen. descriptions                      *\n *   SessionClass::Free_Scenario_Descriptions -- frees scen. descriptions                      *\n *   SessionClass::Trap_Object -- searches for an object, for debugging                        *\n *   SessionClass::Compute_Unique_ID -- computes unique local ID number                        *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include \"function.h\"\n#include <dos.h>\t\t\t// for station ID computation\n#include <time.h>\t\t\t// for station ID computation\n\n//#include \"WolDebug.h\"\n\n/***************************** Globals *************************************/\n//---------------------------------------------------------------------------\n//\tThis is the array of remap colors.  Each player in a network game is\n// assigned one of these colors.  The 'G' is for graphics drawing; the 'T'\n// is for text printing (indicates a remap table for the font to use).\n//---------------------------------------------------------------------------\n//int SessionClass::GColors[MAX_MPLAYER_COLORS] = {\n\t//5, \t\t\t// Yellow\n\t//127, \t\t\t// Red\n\t//135, \t\t\t// BlueGreen\n\t//26,\t\t\t// Orange\n\t//4,\t\t\t\t// Green\n\t//202\t\t\t// Blue-Grey\n//};\n\n//int SessionClass::TColors[MAX_MPLAYER_COLORS] = {\n\t//CC_GDI_COLOR, \t\t\t// Yellow\n\t//CC_NOD_COLOR, \t\t\t// Red\n\t//CC_BLUE_GREEN, \t\t// BlueGreen\n\t//CC_ORANGE,\t\t\t\t// Orange\n\t//CC_GREEN,\t\t\t\t// Green\n\t//CC_BLUE_GREY,\t\t\t// Blue\n//};\n\n/*---------------------------------------------------------------------------\nMin & Max unit count values; index0 = bases OFF, index1 = bases ON\n---------------------------------------------------------------------------*/\nint SessionClass::CountMin[2] = {1,0};\nint SessionClass::CountMax[2] = {50,12};\n\n//---------------------------------------------------------------------------\n//\tThis is a list of all the names of the multiplayer scenarios\n//---------------------------------------------------------------------------\nchar SessionClass::Descriptions[100][40];\n\n//---------------------------------------------------------------------------\n// These values are used purely for the Mono debug display.  They show the\n// names of the Global Channel packet types, and the event types.\n//---------------------------------------------------------------------------\nchar * SessionClass::GlobalPacketNames[] = {\n\t\"Game?\",\n\t\"Game!\",\n\t\"Player?\",\n\t\"Player!\",\n\t\"Join?\",\n\t\"Join!\",\n\t\"Reject\",\n\t\"GameOptions\",\n\t\"Sign Off\",\n\t\"GO!\",\n\t\"Message\",\n\t\"Ping\",\n\t\"Load\"\n};\n\nchar * SessionClass::SerialPacketNames[] = {\n\t\"CONNECT\",\n\t\"GAME_OPTIONS\",\n\t\"SIGN_OFF\",\n\t\"GO\",\n\t\"MESSAGE\",\n\t\"TIMING\",\n\t\"SCORE_SCREEN\",\n\t\"LOADGAME\",\n\t\"LAST_COMMAND\",\n};\n\n\nchar * SessionClass::DialMethodCheck[ DIAL_METHODS ] = {\n\t\"T\",\n\t\"P\"\n};\n\nchar *SessionClass::CallWaitStrings[ CALL_WAIT_STRINGS_NUM ] = {\n\t\"*70,\",\n\t\"70#,\",\n\t\"1170,\",\n\t\"CUSTOM -                \"\n};\n\n/***************************************************************************\n * SessionClass::SessionClass -- Constructor                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::SessionClass(void)\n{\n\tType = GAME_NORMAL;\n\tCommProtocol = DEFAULT_COMM_PROTOCOL;\n\n\tOptions.ScenarioIndex = 0;\n\tOptions.Bases = 0;\n\tOptions.Credits = 0;\n\tOptions.Tiberium = 0;\n\tOptions.Goodies = 0;\n\tOptions.Ghosts = 0;\n\tOptions.UnitCount = 0;\n\n\tUniqueID = 0;\n\n\tHandle[0] = 0;\n\tPrefColor = PCOLOR_FIRST;\n\tColorIdx = PCOLOR_FIRST;\n\tHouse = HOUSE_GOOD;\n\tObiWan = 0;\n\tSolo = 0;\n\n\tMaxPlayers = 8;\n\tNumPlayers = 0;\n\n\tMaxAhead = 5;\n\tFrameSendRate = DEFAULT_FRAME_SEND_RATE;\n\n\tLoadGame = 0;\n\tEmergencySave = 0;\n\n\tLastMessage[0] = 0;\n\tWWChat = 0;\n\n\tRecordFile.Set_Name(\"RECORD.BIN\");\t\t// always uses this name\n\tRecord= 0;\t\t\t\t\t\t\t\t\t\t// set via command line\n\tPlay = 0;\t\t\t\t\t\t\t\t\t\t// set via command line\n\tAttract = 0;\t\t\t\t\t\t\t\t\t// set via command line\n\n\tIsBridge = 0;\n\tNetStealth = 0;\n\tNetProtect = 1;\n\tNetOpen = 0;\n\tGameName[0] = 0;\n\tGProductID = 0;\n\n\tMetaSize = MAX_IPX_PACKET_SIZE;\n\n\tModemService = true;\n\tCurPhoneIdx = 0;\t\t\t\t\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.Port = 0x2f8;\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.IRQ = 3;\t\t\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.Baud = 9600;\t\t\t\t\t\t// set from INI file\n\tSerialDefaults.DialMethod = DIAL_TOUCH_TONE;\t// set from INI file\n\tSerialDefaults.InitStringIndex = 0;\t\t\t\t// set from INI file\n\tSerialDefaults.CallWaitStringIndex = 0;\t\t// set from INI file\n\tstrcpy(SerialDefaults.CallWaitString,\"\");\n\tModemType = MODEM_NULL_HOST;\t\t\t\t\t\t// set from INI file\n\n\tTrapFrame = 0x7fffffff;\t\t// frame to start trapping object values at\n\tTrapObjType = RTTI_NONE;\t// type of object to trap\n\tTrapObject.Ptr.All = NULL;\t// ptr to object being trapped\n\tTrapCoord = 0;\t\t\t\t\t// COORDINATE of object to trap\n\tTrapTarget = TARGET_NONE;\t// TARGET value of object to trap\n\tTrapCell = NULL;\t\t\t\t// for trapping a cell\n\tTrapCheckHeap = 0;\t\t\t// start checking the Heap\n\tTrapPrintCRC = 0;\t\t\t\t// output CRC file\n\n#if(TEN)\n\tTenPacket = NULL;\n\tTenSize = 200;\n\tTenPlayerID = -1;\n\tOptionsFile[0] = 0;\n\tAllowSolo = 0;\n\tNetResponseTime = 600;\n#endif\t// TEN\n\n#if(MPATH)\n\tMPathPacket = NULL;\n\tMPathSize = 200;\n\tOptionsFile[0] = 0;\n\tAllowSolo = 0;\n\tNetResponseTime = 600;\n#endif\t// MPATH\n\n}\t// end of SessionClass\n\n\n/***************************************************************************\n * SessionClass::~SessionClass -- Destructor                               *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nSessionClass::~SessionClass(void)\n{\n}\t// end of ~SessionClass\n\n\n/***************************************************************************\n * SessionClass::One_Time -- one-time initializations                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/01/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::One_Time(void)\n{\n\tRead_MultiPlayer_Settings();\n\tRead_Scenario_Descriptions();\n\n\tUniqueID = Compute_Unique_ID();\n\n}\t// end of One_Time\n\n\n/***************************************************************************\n * SessionClass::Init -- Initializes all values                            *\n *                                                                         *\n * This function should be called for every new game played; it only sets\t*\n * those variables that should be set for a new game.\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Init(void)\n{\n\n}\t// end of Init\n\n\n/***************************************************************************\n * SessionClass::Create_Connections -- forms connections to other players  *\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_Connections(void)\n{\n#if (0)//PG\n\tint i;\n\n\tif (Session.Type != GAME_IPX && Session.Type != GAME_INTERNET) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tIpx.Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\t&(Players[i]->Address) );\n\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n#endif\n\treturn (1);\n\n}\t// end of Create_Connections\n\n\n#if(TEN)\n/***************************************************************************\n * SessionClass::Create_TEN_Connections -- forms connections to TEN players*\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_TEN_Connections(void)\n{\n\tint i;\n\n\tif (Session.Type != GAME_TEN) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tTen->Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\tPlayers[i]->TenAddress);\n\t\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Create_TEN_Connections\n\n#endif\t// TEN\n\n\n#if(MPATH)\n/***************************************************************************\n * SessionClass::Create_MPATH_Connections -- forms connections to MPATH players*\n *                                                                         *\n * This routine uses the contents of the Players vector, combined with\t\t*\n * that of the Houses array, to create connections to each other player.\t*\n * It is assumed that 'Players' contains all the other players to connect\t*\n * to, and that the HouseClass's have been filled in with players' data.\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = success, 0 = failure\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/30/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Create_MPATH_Connections(void)\n{\n\tint i;\n\n\tif (Session.Type != GAME_MPATH) {\n\t\treturn (0);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Loop through all entries in 'Players'.  To avoid connecting to myself,\n\t// skip the 1st entry.\n\t//------------------------------------------------------------------------\n\tfor (i = 1; i < Players.Count(); i++) {\n\t\t//.....................................................................\n\t\t// Make sure the name matches before creating the connection\n\t\t//.....................................................................\n\t\tif (!stricmp (Players[i]->Name,\n\t\t\tHouseClass::As_Pointer(Players[i]->Player.ID)->IniName)) {\n\t\t\tMPath->Create_Connection((int)Players[i]->Player.ID, Players[i]->Name,\n\t\t\t\tPlayers[i]->MPathAddress);\n\t\t\tPlayers[i]->Player.ProcessTime = -1;\n\t\t}\n\t\telse {\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\treturn (1);\n\n}\t// end of Create_MPATH_Connections\n\n#endif\t// MPATH\n\n\n/***************************************************************************\n * SessionClass::Am_I_Master -- tells if the local system is the \"master\"  *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   11/29/1995 BRR : Created.                                             *\n *=========================================================================*/\nbool SessionClass::Am_I_Master(void)\n{\n\tint i;\n\tHousesType house;\n\tHouseClass *hptr;\n\n\t//------------------------------------------------------------------------\n\t// Check every house; if PlayerPtr points to the first human house, we're\n\t// the master.\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < Session.MaxPlayers; i++) {\n\t\thouse = (HousesType)((int)HOUSE_MULTI1 + i);\n\t\thptr = HouseClass::As_Pointer(house);\n\t\tif (hptr->IsHuman) {\n\t\t\tif (PlayerPtr == hptr) {\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (false);\n\n}\t// end of Am_I_Master\n\n\n/***************************************************************************\n * SessionClass::Save -- Saves this class to a file                        *\n *                                                                         *\n * Only certain members of this class should be saved into a save-game\t\t*\n * file; this routine saves only those members.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Save(Pipe & file) const\n{\n#ifdef FIXIT_MULTI_SAVE\n\tfile.Put(&CommProtocol, sizeof(CommProtocol));\n\tfile.Put(&MaxAhead, sizeof(MaxAhead));\n\tfile.Put(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Put(&DesiredFrameRate, sizeof(DesiredFrameRate));\n#endif\t// FIXIT_MULTI_SAVE\n\tfile.Put(&PrefColor, sizeof(PrefColor));\n\tfile.Put(&ColorIdx, sizeof(ColorIdx));\n\tfile.Put(&House, sizeof(House));\n\tfile.Put(&NumPlayers, sizeof(NumPlayers));\n\tfile.Put(&Options.Bases, sizeof(Options.Bases));\n\tfile.Put(&Options.Credits, sizeof(Options.Credits));\n\tfile.Put(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Put(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Put(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Put(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Put(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Put(&ObiWan, sizeof(ObiWan));\n\tfile.Put(&EmergencySave, sizeof(EmergencySave));\n\n\treturn (1);\n\n}\t// end of Save\n\n\n/***************************************************************************\n * SessionClass::Load -- Loads this class from a file                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Load(Straw & file)\n{\n#ifdef FIXIT_MULTI_SAVE\n//\tif(GameVersion != 0x0100616D){\n\tfile.Get(&CommProtocol, sizeof(CommProtocol));\n\tfile.Get(&MaxAhead, sizeof(MaxAhead));\n\tfile.Get(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Get(&DesiredFrameRate, sizeof(DesiredFrameRate));\n//\t}\n#endif\t// FIXIT_MULTI_SAVE\n\tfile.Get(&PrefColor, sizeof(PrefColor));\n\tfile.Get(&ColorIdx, sizeof(ColorIdx));\n\tfile.Get(&House, sizeof(House));\n\tfile.Get(&NumPlayers, sizeof(NumPlayers));\n\tfile.Get(&Options.Bases, sizeof(Options.Bases));\n\tfile.Get(&Options.Credits, sizeof(Options.Credits));\n\tfile.Get(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Get(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Get(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Get(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Get(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Get(&ObiWan, sizeof(ObiWan));\n\tfile.Get(&EmergencySave, sizeof(EmergencySave));\n\n\treturn (1);\n\n}\t// end of Load\n\n\n/***************************************************************************\n * SessionClass::Save -- Saves this class to a file                        *\n *                                                                         *\n * Only certain members of this class should be saved into a save-game\t\t*\n * file; this routine saves only those members.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to save to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Save(CCFileClass & file)\n{\n\tint i;\n\n\tfile.Write(&Type, sizeof(Type));\n\tfile.Write(&CommProtocol, sizeof(CommProtocol));\n\tfile.Write(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Write(&PrefColor, sizeof(PrefColor));\n\tfile.Write(&ColorIdx, sizeof(ColorIdx));\n\tfile.Write(&House, sizeof(House));\n\tfile.Write(&NumPlayers, sizeof(NumPlayers));\n\tfile.Write(&Options.Bases, sizeof(Options.Bases));\n\tfile.Write(&Options.Credits, sizeof(Options.Credits));\n\tfile.Write(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Write(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Write(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Write(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Write(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Write(&ObiWan, sizeof(ObiWan));\n\tfile.Write(&EmergencySave, sizeof(EmergencySave));\n\n\ti = Players.Count();\n\tfile.Write(&i, sizeof(i));\n\tfor (i = 0; i < Players.Count(); i++) {\n\t\tfile.Write(Players[i], sizeof(NodeNameType));\n\t}\n\n\treturn (1);\n\n}\t// end of Save\n\n\n/***************************************************************************\n * SessionClass::Load -- Loads this class from a file                      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tfile\t\tfile to load from\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\t1 = OK, 0 = error\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/04/1995 BRR : Created.                                             *\n *=========================================================================*/\nint SessionClass::Load(CCFileClass & file)\n{\n\tint count;\n\tint i;\n\tNodeNameType *node;\n\n\tfile.Read(&Type, sizeof(Type));\n\tfile.Read(&CommProtocol, sizeof(CommProtocol));\n\tfile.Read(&FrameSendRate, sizeof(FrameSendRate));\n\tfile.Read(&PrefColor, sizeof(PrefColor));\n\tfile.Read(&ColorIdx, sizeof(ColorIdx));\n\tfile.Read(&House, sizeof(House));\n\tfile.Read(&NumPlayers, sizeof(NumPlayers));\n\tfile.Read(&Options.Bases, sizeof(Options.Bases));\n\tfile.Read(&Options.Credits, sizeof(Options.Credits));\n\tfile.Read(&Options.Tiberium, sizeof(Options.Tiberium));\n\tfile.Read(&Options.Goodies, sizeof(Options.Goodies));\n\tfile.Read(&Options.Ghosts, sizeof(Options.Ghosts));\n\tfile.Read(&Options.UnitCount, sizeof(Options.UnitCount));\n\tfile.Read(&Options.AIPlayers, sizeof(Options.AIPlayers));\n\tfile.Read(&ObiWan, sizeof(ObiWan));\n\tfile.Read(&EmergencySave, sizeof(EmergencySave));\n\n\tfile.Read(&count, sizeof(count));\n\tfor (i = 0; i < count; i++) {\n\t\tnode = new NodeNameType;\n\t\tfile.Read(node, sizeof(NodeNameType));\n\t\tPlayers.Add(node);\n\t}\n\n\treturn (1);\n\n}\t// end of Load\n\n\n/***************************************************************************\n * SessionClass::Read_MultiPlayer_Settings -- reads settings INI           *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid SessionClass::Read_MultiPlayer_Settings (void)\n{\n#if (0)//PG\n\tchar *tokenptr;\t\t\t\t\t\t// ptr to token\n\tPhoneEntryClass *phone;\t\t\t\t// a phone book entry\n\tchar *entry;\t\t\t\t\t\t\t// a phone book entry\n\tchar buf[128];\t\t\t\t\t\t\t// buffer for parsing INI entry\n\tint i;\n\tCELL cell;\n\n\n//\tCCFileClass file (CONFIG_FILE_NAME);\n\n\t//------------------------------------------------------------------------\n\t//\tClear the initstring entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < InitStrings.Count(); i++) {\n\t\tdelete[] InitStrings[i];\n\t}\n\tInitStrings.Clear();\n\n\t//\tClear the dialing entries\n\tfor (i = 0; i < PhoneBook.Count(); i++) {\n\t\tdelete[] PhoneBook[i];\n\t}\n\tPhoneBook.Clear();\n\n\t//\tCreate filename and read the file.\n\tINIClass ini;\n\tif (ini.Load(RawFileClass(CONFIG_FILE_NAME))) {\n\n\t\t//\tGet the player's last-used Handle\n\t\tini.Get_String(\"MultiPlayer\", \"Handle\", \"Noname\", Handle, sizeof(Handle));\n\n\t\t//\tGet the player's last-used Color\n\t\tPrefColor = (PlayerColorType)ini.Get_Int(\"MultiPlayer\", \"Color\", 0);\n#ifdef FIXIT_VERSION_3\n\t\tint iSide = ini.Get_Int(\"MultiPlayer\", \"Side\", HOUSE_USSR);\n\t\tiSide = max( 2, min( 6, iSide ) );\n\t\tHouse = (HousesType)iSide;\n#else\n\t\tHouse = (HousesType)ini.Get_Int(\"MultiPlayer\", \"Side\", HOUSE_USSR);\n#endif\n\t\tCurPhoneIdx = ini.Get_Int(\"MultiPlayer\", \"PhoneIndex\", -1);\n\t\tTrapCheckHeap = ini.Get_Int(\"MultiPlayer\", \"CheckHeap\", 0);\n\n\t\t//\tRead in default serial settings\n\t\tini.Get_String(\"SerialDefaults\", \"ModemName\", \"NoName\", SerialDefaults.ModemName, MODEM_NAME_MAX);\n\t\tif (!strcmp ( SerialDefaults.ModemName, \"NoName\")) {\n\t\t\tSerialDefaults.ModemName[0] = 0;\n\t\t}\n\t\tSerialDefaults.Port = ini.Get_Int(\"SerialDefaults\", \"Port\", 0);\n\t\tSerialDefaults.IRQ = ini.Get_Int(\"SerialDefaults\", \"IRQ\", -1);\n\t\tSerialDefaults.Baud = ini.Get_Int(\"SerialDefaults\", \"Baud\", -1);\n\t\tSerialDefaults.Compression = ini.Get_Int (\"SerialDefaults\", \"Compression\", 0);\n\t\tSerialDefaults.ErrorCorrection = ini.Get_Int (\"SerialDefaults\", \"ErrorCorrection\", 0);\n\t\tSerialDefaults.HardwareFlowControl = ini.Get_Int (\"SerialDefaults\", \"HardwareFlowControl\", 1);\n\n\t\tini.Get_String(\"SerialDefaults\", \"DialMethod\", \"T\", buf, 2);\n\n#ifndef WIN32\n\t\t/*\n\t\t** Ignore any modem name in DOS. This should only be nessasary if the user\n\t\t** previously set up the modem in the windows version.\n\t\t*/\n\t\tif (SerialDefaults.ModemName[0] && SerialDefaults.Port == 1) {\n\t\t\tSerialDefaults.Port = 0x3F8;\n\t\t\tSerialDefaults.ModemName[0] = 0;\n\t\t}\n#endif\t//WIN32\n\n\t\t// find dial method\n\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\tSerialDefaults.DialMethod = (DialMethodType)i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// if method not found set to touch tone\n\t\tif (i == DIAL_METHODS) {\n\t\t\tSerialDefaults.DialMethod = DIAL_TOUCH_TONE;\n\t\t}\n\n\t\tSerialDefaults.InitStringIndex = ini.Get_Int(\"SerialDefaults\", \"InitStringIndex\", 0);\n\n\t\tSerialDefaults.CallWaitStringIndex = ini.Get_Int(\"SerialDefaults\", \"CallWaitStringIndex\", CALL_WAIT_CUSTOM);\n\n\t\tini.Get_String(\"SerialDefaults\", \"CallWaitString\", \"\", SerialDefaults.CallWaitString, CWAITSTRBUF_MAX);\n\n\t\tif (SerialDefaults.IRQ == 0 || SerialDefaults.Baud == 0) {\n\t\t\tSerialDefaults.Port = 0;\n\t\t\tSerialDefaults.IRQ = -1;\n\t\t\tSerialDefaults.Baud = -1;\n\t\t}\n\n\t\tint initcount = ini.Entry_Count(\"InitStrings\");\n\t\tfor (int index = 0; index < initcount; index++) {\n\t\t\tentry = new char[ INITSTRBUF_MAX ];\n\t\t\tentry[0] = 0;\n\t\t\tini.Get_String(\"InitStrings\", ini.Get_Entry(\"InitStrings\", index), NULL, entry, INITSTRBUF_MAX);\n\t\t\tstrupr( entry );\n\t\t\tInitStrings.Add( entry );\n\t\t}\n\n\t\t//\tif no entries then have at least one\n\t\tif (initcount == 0) {\n\t\t\tentry = new char[ INITSTRBUF_MAX ];\n\t\t\tstrcpy( entry, \"ATZ\" );\n\t\t\tInitStrings.Add( entry );\n\t\t\tSerialDefaults.InitStringIndex = 0;\n\t\t}\n\n\t\t//\tRead the entry names in\n\t\tint phonecount = ini.Entry_Count(\"PhoneBook\");\n\t\tfor (int index = 0; index < phonecount; index++) {\n\t\t\t//\tCreate a new phone book entry\n\t\t\tphone = new PhoneEntryClass();\n\n\t\t\t//\tRead the entire entry in\n\t\t\tini.Get_String(\"PhoneBook\", ini.Get_Entry(\"PhoneBook\", index), NULL, buf, sizeof(buf));\n\n\t\t\t//\tExtract name, phone # & serial port settings\n\t\t\ttokenptr = strtok( buf, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( phone->Name, tokenptr );\n\t\t\t\tstrupr( phone->Name );\n\t\t\t} else {\n\t\t\t\tphone->Name[0] = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( phone->Number, tokenptr );\n\t\t\t\tstrupr( phone->Number );\n\t\t\t} else {\n\t\t\t\tphone->Number[0] = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tsscanf( tokenptr, \"%x\", &phone->Settings.Port );\n\t\t\t} else {\n\t\t\t\tphone->Settings.Port = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.IRQ = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.IRQ = -1;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.Baud = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.Baud = -1;\n\t\t\t}\n\n\t\t\tphone->Settings.Compression = 0;\n\t\t\tphone->Settings.ErrorCorrection = 0;\n\t\t\tphone->Settings.HardwareFlowControl = 1;\n\n\t\t\t/*\n\t\t\t** Find out if this phonebook entry has the new settings included. If not\n\t\t\t** then we need to skip this section.\n\t\t\t*/\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr){\n\t\t\t\tstrcpy( buf, tokenptr );\n\n\t\t\t\t// find dial method\n\n\t\t\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** This must be an old phonebook entry\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** Method wasnt found - assume its a new phonebook entry so get the extra settings\n\t\t\t\t*/\n\t\t\t\t// if method not found set to touch tone\n\n\t\t\t\tif (i == DIAL_METHODS) {\n\n\t\t\t\t\tphone->Settings.Compression = atoi( tokenptr );\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t\tif (tokenptr) {\n\t\t\t\t\t\tphone->Settings.ErrorCorrection = atoi( tokenptr );\n\t\t\t\t\t}\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t\tif (tokenptr) {\n\t\t\t\t\t\tphone->Settings.HardwareFlowControl = atoi( tokenptr );\n\t\t\t\t\t}\n\n\t\t\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy( buf, tokenptr );\n\n\t\t\t\t//\tfind dial method\n\t\t\t\tfor (i = 0; i < DIAL_METHODS; i++) {\n\t\t\t\t\tif ( !strcmpi( buf, DialMethodCheck[ i ]) ) {\n\t\t\t\t\t\tphone->Settings.DialMethod = (DialMethodType)i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//\tif method not found set to touch tone\n\t\t\t\tif (i == DIAL_METHODS) {\n\t\t\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tphone->Settings.DialMethod = DIAL_TOUCH_TONE;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.InitStringIndex = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.InitStringIndex = 0;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tphone->Settings.CallWaitStringIndex = atoi( tokenptr );\n\t\t\t} else {\n\t\t\t\tphone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;\n\t\t\t}\n\n\t\t\ttokenptr = strtok( NULL, \"|\" );\n\t\t\tif (tokenptr) {\n\t\t\t\tstrcpy (phone->Settings.CallWaitString, tokenptr);\n\t\t\t} else {\n\t\t\t\tphone->Settings.CallWaitString[0] = 0;\n\t\t\t}\n\n\t\t\t//\tAdd it to our list\n\t\t\tPhoneBook.Add(phone);\n\t\t}\n\n\t\t//\tRead special recording playback values, to help find sync bugs\n\t\tTrapFrame = ini.Get_Int(\"SyncBug\", \"Frame\", 0x7fffffff);\n\n\t\tini.Get_String(\"SyncBug\", \"Type\", \"NONE\", buf, 80);\n\n\t\tif (!stricmp(buf,\"AIRCRAFT\"))\n\t\t\tTrapObjType = RTTI_AIRCRAFT;\n\t\telse if (!stricmp(buf,\"ANIM\"))\n\t\t\tTrapObjType = RTTI_ANIM;\n\t\telse if (!stricmp(buf,\"BUILDING\"))\n\t\t\tTrapObjType = RTTI_BUILDING;\n\t\telse if (!stricmp(buf,\"BULLET\"))\n\t\t\tTrapObjType = RTTI_BULLET;\n\t\telse if (!stricmp(buf,\"INFANTRY\"))\n\t\t\tTrapObjType = RTTI_INFANTRY;\n\t\telse if (!stricmp(buf,\"UNIT\"))\n\t\t\tTrapObjType = RTTI_UNIT;\n\t\telse {\n\t\t\tTrapObjType = RTTI_NONE;\n\t\t}\n\n\t\tini.Get_String(\"SyncBug\", \"Coord\", \"0\", buf, 80);\n\t\tsscanf(buf,\"%x\",&TrapCoord);\n\n\t\tini.Get_String(\"SyncBug\", \"Target\", \"0\", buf, 80);\n\t\tsscanf(buf,\"%x\",&TrapTarget);\n\n\t\tini.Get_String(\"SyncBug\", \"Cell\", \"0\", buf, 80);\n\t\tcell = atoi(buf);\n\t\tif (cell) {\n\t\t\tTrapCell = &(Map[cell]);\n\t\t}\n\n\t\tTrapPrintCRC = ini.Get_Int(\"SyncBug\", \"PrintCRC\", 0x7fffffff);\n\t}\n#endif\n}\n\n\n/***************************************************************************\n * SessionClass::Write_MultiPlayer_Settings -- writes settings INI         *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *=========================================================================*/\nvoid SessionClass::Write_MultiPlayer_Settings (void)\n{\n#ifdef NEVER\n\tchar * buffer;\t\t\t\t\t// INI staging buffer pointer.\n\tCCFileClass file;\n\tint i;\n\tchar entrytext[4];\n\tchar buf[128];\t\t\t\t\t// buffer for parsing INI entry\n\n\t//------------------------------------------------------------------------\n\t//\tGet a working pointer to the INI staging buffer. Make sure that the\n\t// buffer starts cleared out of any data.\n\t//------------------------------------------------------------------------\n\tbuffer = (char *)_ShapeBuffer;\n\tmemset(buffer, '\\0', _ShapeBufferSize);\n\n\tfile.Set_Name(CONFIG_FILE_NAME);\n\tif (file.Is_Available()) {\n\t\tfile.Open(READ);\n\t\tfile.Read(buffer, _ShapeBufferSize-1);\n\t\tfile.Close();\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tSave the player's last-used Handle & Color\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileInt(\"MultiPlayer\", \"PhoneIndex\", CurPhoneIdx, buffer);\n\tWWWritePrivateProfileInt (\"MultiPlayer\", \"Color\", (int)PrefColor, buffer);\n\tWWWritePrivateProfileInt (\"MultiPlayer\", \"Side\", House, buffer);\n\tWWWritePrivateProfileString(\"MultiPlayer\", \"Handle\", Handle, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing Settings.SerialDefault entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"SerialDefaults\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave default serial settings in opposite order you want to see them\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"CallWaitString\", SerialDefaults.CallWaitString, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"CallWaitStringIndex\", SerialDefaults.CallWaitStringIndex, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"InitStringIndex\", SerialDefaults.InitStringIndex, buffer);\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"DialMethod\", DialMethodCheck[ SerialDefaults.DialMethod ], buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"Baud\", SerialDefaults.Baud, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"IRQ\", SerialDefaults.IRQ, buffer);\n\tsprintf(buf, \"%x\", SerialDefaults.Port);\n\tWWWritePrivateProfileString(\"SerialDefaults\", \"Port\", buf, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"Compression\", SerialDefaults.Compression , buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"ErrorCorrection\", SerialDefaults.ErrorCorrection, buffer);\n\tWWWritePrivateProfileInt (\"SerialDefaults\", \"HardwareFlowControl\", SerialDefaults.HardwareFlowControl, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing InitString entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"InitStrings\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave all InitString entries.  In descending order so they come out in\n\t//\tascending order.\n\t//------------------------------------------------------------------------\n\tfor (i = (InitStrings.Count() - 1); i >= 0; i--) {\n\t\tsprintf( buf, \"%03d\", i);\n\t\tWWWritePrivateProfileString (\"InitStrings\", buf, InitStrings[i], buffer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tClear all existing Phone Book entries.\n\t//------------------------------------------------------------------------\n\tWWWritePrivateProfileString (\"PhoneBook\", NULL, NULL, buffer);\n\n\t//------------------------------------------------------------------------\n\t//\tSave all Phone Book entries.\n\t//\tFormat: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString\n\t//------------------------------------------------------------------------\n\tfor (i = (PhoneBook.Count() - 1); i >= 0; i--) {\n\t\tsprintf(buf,\"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s\",\n\t\t\tPhoneBook[i]->Name,\n\t\t\tPhoneBook[i]->Number,\n\t\t\tPhoneBook[i]->Settings.Port,\n\t\t\tPhoneBook[i]->Settings.IRQ,\n\t\t\tPhoneBook[i]->Settings.Baud,\n\t\t\tPhoneBook[i]->Settings.Compression,\n\t\t\tPhoneBook[i]->Settings.ErrorCorrection,\n\t\t\tPhoneBook[i]->Settings.HardwareFlowControl,\n\t\t\tDialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],\n\t\t\tPhoneBook[i]->Settings.InitStringIndex,\n\t\t\tPhoneBook[i]->Settings.CallWaitStringIndex,\n\t\t\tPhoneBook[i]->Settings.CallWaitString);\n\t\tsprintf( entrytext, \"%03d\", i );\n\t\tWWWritePrivateProfileString (\"PhoneBook\", entrytext, buf, buffer);\n\t}\n\n\t//------------------------------------------------------------------------\n\t//\tWrite the INI data out to a file.\n\t//------------------------------------------------------------------------\n\tfile.Open(WRITE);\n\tfile.Write(buffer,strlen(buffer));\n\tfile.Close();\n#endif\n\n#if (0)//PG\n\tINIClass ini;\n\tRawFileClass file(CONFIG_FILE_NAME);\n\tif (ini.Load(file)) {\n\n\t\t//\tSave the player's last-used Handle & Color\n\t\tini.Put_Int(\"MultiPlayer\", \"PhoneIndex\", CurPhoneIdx);\n\t\tini.Put_Int(\"MultiPlayer\", \"Color\", (int)PrefColor);\n\t\tini.Put_Int(\"MultiPlayer\", \"Side\", House);\n\t\tini.Put_String(\"MultiPlayer\", \"Handle\", Handle);\n\n\t\t//\tClear all existing Settings.SerialDefault entries.\n\t\tini.Clear(\"SerialDefaults\");\n\n\t\t//\tSave default serial settings in opposite order you want to see them\n\t\tini.Put_String(\"SerialDefaults\", \"CallWaitString\", SerialDefaults.CallWaitString);\n\t\tini.Put_Int(\"SerialDefaults\", \"CallWaitStringIndex\", SerialDefaults.CallWaitStringIndex);\n\t\tini.Put_Int(\"SerialDefaults\", \"InitStringIndex\", SerialDefaults.InitStringIndex);\n\t\tini.Put_String(\"SerialDefaults\", \"DialMethod\", DialMethodCheck[ SerialDefaults.DialMethod ]);\n\t\tini.Put_Int(\"SerialDefaults\", \"Baud\", SerialDefaults.Baud);\n\t\tini.Put_Int(\"SerialDefaults\", \"IRQ\", SerialDefaults.IRQ);\n\t\tini.Put_Int(\"SerialDefaults\", \"Port\", SerialDefaults.Port, 1);\n\t\tini.Put_String(\"SerialDefaults\", \"ModemName\", SerialDefaults.ModemName);\n\t\tini.Put_Int (\"SerialDefaults\", \"Compression\", SerialDefaults.Compression );\n\t\tini.Put_Int (\"SerialDefaults\", \"ErrorCorrection\", SerialDefaults.ErrorCorrection );\n\t\tini.Put_Int (\"SerialDefaults\", \"HardwareFlowControl\", SerialDefaults.HardwareFlowControl );\n\n\t\t//\tClear all existing InitString entries.\n\t\tini.Clear(\"InitStrings\");\n\n\t\t//\tSave all InitString entries.\n\t\tfor (int index = 0; index < InitStrings.Count(); index++) {\n\t\t\tchar buf[10];\n\t\t\tsprintf( buf, \"%03d\", index);\n\t\t\tini.Put_String(\"InitStrings\", buf, InitStrings[index]);\n\t\t}\n\n\t\t//\tClear all existing Phone Book entries.\n\t\tini.Clear(\"PhoneBook\");\n\n\t\t//\tSave all Phone Book entries.\n\t\t//\tFormat: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString\n\t\tfor (int i = (PhoneBook.Count() - 1); i >= 0; i--) {\n\t\t\tchar buf[128];\n\t\t\tchar entrytext[10];\n\t\t\tsprintf(buf,\"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s\",\n\t\t\t\tPhoneBook[i]->Name,\n\t\t\t\tPhoneBook[i]->Number,\n\t\t\t\tPhoneBook[i]->Settings.Port,\n\t\t\t\tPhoneBook[i]->Settings.IRQ,\n\t\t\t\tPhoneBook[i]->Settings.Baud,\n\t\t\t\tPhoneBook[i]->Settings.Compression,\n\t\t\t\tPhoneBook[i]->Settings.ErrorCorrection,\n\t\t\t\tPhoneBook[i]->Settings.HardwareFlowControl,\n\t\t\t\tDialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],\n\t\t\t\tPhoneBook[i]->Settings.InitStringIndex,\n\t\t\t\tPhoneBook[i]->Settings.CallWaitStringIndex,\n\t\t\t\tPhoneBook[i]->Settings.CallWaitString);\n\t\t\tsprintf( entrytext, \"%03d\", i );\n\t\t\tini.Put_String(\"PhoneBook\", entrytext, buf);\n\t\t}\n\n\t\t//\tWrite the INI data out to a file.\n\t\tini.Save(file);\n\t}\n#endif\n}\n\n\n// Determine if a mission is from counterstrike or aftermath, or either.\n// Multiplayer maps >24, with a numerical name, are Counterstrike.\n// Multiplayer maps with an alphabetical name, like SCMJGEA.INI, are Aftermath.\n\nbool Is_Mission_Counterstrike (char *file_name)\n{\n\tint scenario_number = 0;\n\n\tif ( isdigit ( file_name[5] )){\n\t\tsscanf (file_name, \"SCM%03d\", &scenario_number);\n\t} else {\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n\t\tif (!isdigit(file_name[3]) || !isdigit(file_name[4])) {\n\t\t\treturn(false);\n\t\t}\n#endif\n\t\tsscanf (file_name, \"SCM%02d\", &scenario_number);\n\t}\n\treturn ( scenario_number > 24 );\n}\n\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nbool Is_Mission_Aftermath (char *file_name)\n{\n\t//\tajw added\n\t//\tMust start with \"scm\".\n\tchar szCopy[ _MAX_PATH + 1 ];\n\tstrcpy( szCopy, file_name );\n\t_strlwr( szCopy );\n\tif( strstr( szCopy, \"scm\" ) != szCopy )\n\t\treturn false;\n\n\tif (isdigit(file_name[5])) {\n\t\treturn(false);\n\t}\n\n\tif ( !isdigit(file_name[3]) || !isdigit(file_name[4]) ) {\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\n/*\n** Certain missions are 126x126 size, and those can't be downloaded to a\n** non-Aftermath player, so this function checks to see if the map in\n** question is one of those.  We'll know that by the file name: if it's\n** K0 -> M9, it's 126x126.\n*/\nbool Is_Mission_126x126 (char *file_name)\t\t//\tThis is no longer used. ajw\n{\n\tif (isdigit(file_name[5])) {\n\t\treturn(false);\n\t}\n\n\tif ( (file_name[3] >= 'k' && file_name[3] <= 'm') ||\n\t\t\t(file_name[3] >= 'K' && file_name[3] <= 'M') ) {\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\n#endif\n\n\n\n\n\n/***************************************************************************\n * SessionClass::Read_Scenario_Descriptions -- reads scen. descriptions    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   02/14/1995 BR : Created.                                              *\n *   09/10/1996 JLB : Searches using different method.                     *\n *=========================================================================*/\nvoid SessionClass::Read_Scenario_Descriptions (void)\n{\n\n\t//\tClear the scenario description lists\n\tScenarios.Clear();\n\n\t/*\n\t**\tFetch the main multiplayer scenario packet data.\n\t*/\n\tCCFileClass file(\"MISSIONS.PKT\");\n\tif (file.Is_Available()) {\n\t\tINIClass ini;\n\t\tini.Load(file);\n\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in Missions.pkt\\n\", count );\n\t\tfor (int index = 0; index < count; index++) {\n\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\tchar buffer[128];\n\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_VERSION_3\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\tif (!official) {\n\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t}\n\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\t\t}\n/*\t\t//\tajw Copy file for viewing.\n\t\tCCFileClass fileCopy( \"msns_pkt.txt\" );\n\t\tfile.Seek( 0, SEEK_SET );\n\t\tlong lSize = file.Size();\n\t\tchar* pData = new char[ lSize + 1 ];\n\t\tfile.Read( pData, lSize );\n\t\tfileCopy.Write( pData, lSize );\n\t\tfileCopy.Close();\n*/\t}\n\n\t/*\n\t**\tFetch any scenario packet lists and apply them first.\n\t*/\n#ifdef WIN32\n\tWIN32_FIND_DATA block;\n\tHANDLE handle = FindFirstFile(\"*.PKT\", &block);\n\twhile (handle != INVALID_HANDLE_VALUE) {\n\t\tif ((block.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY)) == 0) {\n\t\t\tchar const * name = &block.cAlternateFileName[0];\n\t\t\tif (*name == '\\0') name = &block.cFileName[0];\n//Mono_Printf(\"Found file '%s'.\\n\", block.cAlternateFileName);\n//Mono_Printf(\"Found file '%s'.\\n\", block.cFileName);\n//debugprint(\"Found file '%s'.\\n\", block.cAlternateFileName);\n//debugprint(\"Found file '%s'.\\n\", block.cFileName);\n//debugprint( \"Found alternate PKT file.\\n\" );\n\t\t\tCCFileClass file(name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\n#ifdef FIXIT_VERSION_3\n\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\t//\tFIXIT_VERSION_3\n#ifdef FIXIT_CSII\t//\tchecked - ajw\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n#endif\t//\tFIXIT_VERSION_3\n\t\t\t}\n\t\t}\n\n\t\tif (FindNextFile(handle, &block) == 0) break;\n\t}\n\n\n  #ifdef FIXIT_CSII\t\t//\tchecked - ajw\n\t/*\n\t**\tFetch the Counterstrike multiplayer scenario packet data.\n\t** Load the scenarios regardless of whether counterstrike's installed,\n\t** and at the point of hosting a network game, enable the counterstrike\n\t** maps only if they have CS installed.  If they don't, then the maps\n\t** are available as a guest, but not as a host, which fixes a multitude\n\t** of problems without obviously giving the maps away to non-CS owners.\n\t*/\n#ifdef FIXIT_VERSION_3\n\tif( Is_Counterstrike_Installed() )\n\t{\n#endif\n\t\tCCFileClass file2(\"CSTRIKE.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in cstrike.pkt\\n\", count );\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_VERSION_3\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n\t\t\t}\n/*\t\t\t//\tajw Copy file for viewing.\n\t\t\tCCFileClass fileCopy( \"cs_pkt.txt\" );\n\t\t\tfile2.Seek( 0, SEEK_SET );\n\t\t\tlong lSize = file2.Size();\n\t\t\tchar* pData = new char[ lSize + 1 ];\n\t\t\tfile2.Read( pData, lSize );\n\t\t\tfileCopy.Write( pData, lSize );\n\t\t\tfileCopy.Close();\n*/\t\t}\n#ifdef FIXIT_VERSION_3\n\t}\n#endif\n  #endif\n\n#ifdef FIXIT_VERSION_3\t\t//\tAftermath scenarios are now in their own pkt file.\n\tif( Is_Aftermath_Installed() )\n\t{\n\t\tCCFileClass file2(\"AFTMATH.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n//debugprint( \"Found %i missions in aftmath.pkt\\n\", count );\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\t/*\n\t** Scan the current directory for any loose .MPR files and build the appropriate entries\n\t**  into the scenario list list\n\t*/\n\tchar const * file_name;\n\tchar name_buffer[128];\n\tchar digest_buffer[32];\n\n\thandle = FindFirstFile ( \"*.MPR\" , &block );\n\twhile (handle != INVALID_HANDLE_VALUE) {\n\t\tif ((block.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY)) == 0) {\n\t\t\tfile_name = &block.cAlternateFileName[0];\n\t\t\tif (*file_name == '\\0') file_name = &block.cFileName[0];\n//debugprint( \"Found MPR '%s'\\n\", file_name );\n\t\t\tCCFileClass file(file_name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\n\t\t\tini.Get_String (\"Basic\", \"Name\", \"No Name\", name_buffer, sizeof (name_buffer) );\n\t\t\tini.Get_String (\"Digest\", \"1\", \"No Digest\", digest_buffer, sizeof (digest_buffer) );\n\t\t\tScenarios.Add (new MultiMission (file_name, name_buffer, digest_buffer,ini.Get_Bool(\"Basic\", \"Official\", false), false ));\n\t\t}\n\n\t\tif (FindNextFile(handle, &block) == 0) break;\n\t}\n\n#else\t//WIN32\n\n#error\tWhat? You think you can still build the DOS version after all this time?\n\n\tchar name_buffer[128];\n\tchar digest_buffer[32];\n\n\tstruct find_t block;\n\tif (_dos_findfirst(\"*.PKT\", _A_NORMAL, &block) == 0) {\n\t\tdo {\n\t\t\tCCFileClass file(block.name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n#ifdef FIXIT_CSII\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#else\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, true,\n\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n#endif\n\t\t\t}\n\n\t\t} while(_dos_findnext(&block) == 0);\n\t}\n\n\n\t/*\n\t** Scan the current directory for any loose .MPR files and build the appropriate entries\n\t**  into the scenario list list\n\t*/\n\tif (_dos_findfirst(\"*.MPR\", _A_NORMAL, &block) == 0) {\n\t\tdo {\n\t\t\tCCFileClass file(block.name);\n\t\t\tINIClass ini;\n\t\t\tini.Load(file);\n\t\t\tini.Get_String (\"Basic\", \"Name\", \"No Name\", name_buffer, sizeof (name_buffer) );\n\t\t\tini.Get_String (\"Digest\", \"1\", \"No Digest\", digest_buffer, sizeof (digest_buffer) );\n\t\t\tbool official = ini.Get_Bool(\"Basic\", \"Official\", false);\n\t\t\tScenarios.Add (new MultiMission (block.name, name_buffer, digest_buffer, official, false ));\n\t\t} while(_dos_findnext(&block) == 0);\n\t}\n\n  #ifdef FIXIT_CSII\n\t/*\n\t**\tFetch the Counterstrike multiplayer scenario packet data.\n\t** Load the scenarios regardless of whether counterstrike's installed,\n\t** and at the point of hosting a network game, enable the counterstrike\n\t** maps only if they have CS installed.  If they don't, then the maps\n\t** are available as a guest, but not as a host, which fixes a multitude\n\t** of problems without obviously giving the maps away to non-CS owners.\n\t*/\n//\tif (Is_Counterstrike_Installed()) {\n\t\tCCFileClass file2(\"CSTRIKE.PKT\");\n\t\tif (file2.Is_Available()) {\n\t\t\tINIClass ini;\n\t\t\tini.Load(file2);\n\t\t\tint count = ini.Entry_Count(\"Missions\");\n\t\t\tfor (int index = 0; index < count; index++) {\n\t\t\t\tchar const * fname = ini.Get_Entry(\"Missions\", index);\n\t\t\t\tchar buffer[128];\n\t\t\t\tini.Get_String(\"Missions\", fname, \"\", buffer, sizeof(buffer));\n\t\t\t\tbool official = Is_Mission_126x126( (char *)fname);\n\t\t\t\tif (!official) {\n\t\t\t\t\tofficial = !Is_Mission_Aftermath((char *)fname);\n\t\t\t\t}\n\n\t\t\t\tScenarios.Add(new MultiMission(fname, buffer, NULL, official,\n\t\t\t\t\t\t\t\t\t\tIs_Mission_Counterstrike ((char*)fname)));\n\t\t\t}\n\t\t}\n//\t}\n  #endif\n\n#endif\t//WIN32\n}\n\n\n/***************************************************************************\n * SessionClass::Free_Scenario_Descriptions -- frees scen. descriptions    *\n *                                                                         *\n * INPUT:                                                                  *\n *      none.                                                              *\n *                                                                         *\n * OUTPUT:                                                                 *\n *      none.                                                              *\n *                                                                         *\n * WARNINGS:                                                               *\n *      none.                                                              *\n *                                                                         *\n * HISTORY:                                                                *\n *   06/05/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Free_Scenario_Descriptions(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t//\tClear the scenario descriptions & filenames\n\t//------------------------------------------------------------------------\n\tfor (int index = 0; index < Scenarios.Count(); index++) {\n\t\tdelete Scenarios[index];\n\t}\n\tScenarios.Clear();\n//\tFilenum.Clear();\n\n\t//------------------------------------------------------------------------\n\t//\tClear the initstring entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < InitStrings.Count(); i++) {\n\t\tdelete InitStrings[i];\n\t}\n\tInitStrings.Clear();\n#if (0)//PG\n\t//------------------------------------------------------------------------\n\t//\tClear the dialing entries\n\t//------------------------------------------------------------------------\n\tfor (i = 0; i < PhoneBook.Count(); i++) {\n\t\tdelete PhoneBook[i];\n\t}\n\tPhoneBook.Clear();\n#endif\n}\t/* end of Free_Scenario_Descriptions */\n\n\n/***************************************************************************\n * SessionClass::Trap_Object -- searches for an object, for debugging\t\t*\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   06/02/1995 BRR : Created.                                             *\n *=========================================================================*/\nvoid SessionClass::Trap_Object(void)\n{\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Initialize\n\t//------------------------------------------------------------------------\n\tTrapObject.Ptr.All = NULL;\n\n\t//------------------------------------------------------------------------\n\t// Search for the object based upon its type, then its coordinate or\n\t// 'this' pointer value.\n\t//------------------------------------------------------------------------\n\tswitch (TrapObjType) {\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tfor (i = 0; i < Aircraft.Count(); i++) {\n\t\t\t\tif (Aircraft.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAircraft.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Aircraft = Aircraft.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tfor (i = 0; i < Anims.Count(); i++) {\n\t\t\t\tif (Anims.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAnims.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Anim = Anims.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tif (Buildings.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBuildings.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Building = Buildings.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tfor (i = 0; i < Bullets.Count(); i++) {\n\t\t\t\tif (Bullets.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBullets.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Bullet = Bullets.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tif (Infantry.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tInfantry.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Infantry = Infantry.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tif (Units.Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tUnits.Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Unit = Units.Ptr(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\t//.....................................................................\n\t\t// Last-ditch find-the-object-right-now-darnit loop\n\t\t//.....................................................................\n\t\tcase RTTI_NONE:\n\t\t\tfor (i = 0; i < Aircraft.Count(); i++) {\n\t\t\t\tif (Aircraft.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAircraft.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Aircraft = Aircraft.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_AIRCRAFT;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Anims.Count(); i++) {\n\t\t\t\tif (Anims.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tAnims.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Anim = Anims.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_ANIM;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Buildings.Count(); i++) {\n\t\t\t\tif (Buildings.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBuildings.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Building = Buildings.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_BUILDING;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Bullets.Count(); i++) {\n\t\t\t\tif (Bullets.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tBullets.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Bullet = Bullets.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_BULLET;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Infantry.Count(); i++) {\n\t\t\t\tif (Infantry.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tInfantry.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Infantry = Infantry.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_INFANTRY;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < Units.Count(); i++) {\n\t\t\t\tif (Units.Raw_Ptr(i)->Coord == TrapCoord ||\n\t\t\t\t\tUnits.Raw_Ptr(i)->As_Target()==TrapTarget) {\n\t\t\t\t\tTrapObject.Ptr.Unit = Units.Raw_Ptr(i);\n\t\t\t\t\tTrapObjType = RTTI_UNIT;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n/***************************************************************************\n * SessionClass::Compute_Unique_ID -- computes unique local ID number      *\n *                                                                         *\n * INPUT:                                                                  *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * OUTPUT:                                                                 *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * WARNINGS:                                                               *\n *\t\tnone.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * HISTORY:                                                                *\n *   12/07/1995 BRR : Created.                                             *\n *=========================================================================*/\nunsigned long SessionClass::Compute_Unique_ID(void)\n{\n\treturn 1;//PG\n#if (0) //PG\n\ttime_t tm;\n\tunsigned long id;\n\tstruct diskfree_t dtable;\n\tchar *path;\n\tint i;\n\n\t//------------------------------------------------------------------------\n\t// Start with the seconds since Jan 1, 1970 (system local time)\n\t//------------------------------------------------------------------------\n\ttime(&tm);\n\tid = (unsigned long)tm;\n\n\t//------------------------------------------------------------------------\n\t// Now add in the free space on the hard drive\n\t//------------------------------------------------------------------------\n\tif (_dos_getdiskfree(3, &dtable) == 0) {\n\t\tAdd_CRC(&id, (unsigned long)dtable.avail_clusters);\n\t\tAdd_CRC(&id, (unsigned long)dtable.total_clusters);\n\t\tAdd_CRC(&id, (unsigned long)dtable.bytes_per_sector);\n\t\tAdd_CRC(&id, (unsigned long)dtable.sectors_per_cluster);\n\t}\n\n\t//------------------------------------------------------------------------\n\t// Add in every byte in the user's path environment variable\n\t//------------------------------------------------------------------------\n\tpath = getenv(\"PATH\");\n\tif (path) {\n\t\tfor (i = 0; i < strlen(path); i++) {\n\t\t\tAdd_CRC(&id, (unsigned long)path[i]);\n\t\t}\n\t}\n\n\treturn (id);\n#endif\n}\t// end of Compute_Unique_ID\n\n\n\n\nMultiMission::MultiMission(char const * filename, char const * description, char const * digest, bool official, bool expansion)\n{\n\tSet_Filename(filename);\n\tSet_Description(description);\n\tSet_Digest(digest);\n\tSet_Official(official);\n\tSet_Expansion(expansion);\n}\n\n\nvoid MultiMission::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\tstatic int _tabs[] = {35, 60, 80, 100};\n\tif ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print(ScenarioDescription, x, y, scheme, TBLACK, flags, width, _tabs);\n\t} else {\n\t\tConquer_Clip_Text_Print(ScenarioDescription, x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);\n\t}\n}\n\n\nvoid MultiMission::Set_Description(char const * description)\n{\n\tif (description != NULL) {\n\t\tstrncpy(ScenarioDescription, description, ARRAY_SIZE(ScenarioDescription));\n\t\tScenarioDescription[ARRAY_SIZE(ScenarioDescription)-1] = '\\0';\n\t}\n}\n\n\nvoid MultiMission::Set_Filename(char const * filename)\n{\n\tif (filename != NULL) {\n\t\tstrncpy(Filename, filename, ARRAY_SIZE(Filename));\n\t\tFilename[ARRAY_SIZE(Filename)-1] = '\\0';\n\t}\n}\n\nvoid MultiMission::Set_Digest(char const * digest)\n{\n\tif (digest != NULL) {\n\t\tstrncpy(Digest, digest, ARRAY_SIZE(Digest));\n\t\tDigest[ARRAY_SIZE(Digest)-1] = '\\0';\n\t}\n\telse\n\t{\n\t\tstrcpy( Digest, \"NODIGEST\" );\n\t}\n}\n\nvoid MultiMission::Set_Official (bool official)\n{\n\tIsOfficial = official;\n}\n\nvoid MultiMission::Set_Expansion (bool expansion)\n{\n\tIsExpansion = expansion;\n}\n\n\n/************************** end of session.cpp *****************************/\n"
  },
  {
    "path": "REDALERT/SESSION.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/SESSION.H 4     3/10/97 6:23p Steve_tall $ */\n/***************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n *                                                                         *\n *                 Project Name : Command & Conquer                        *\n *                                                                         *\n *                    File Name : SESSION.H                                *\n *                                                                         *\n *                   Programmer : Bill R. Randolph                         *\n *                                                                         *\n *                   Start Date : 11/30/95                                 *\n *                                                                         *\n *                  Last Update : November 30, 1995 [BRR]                  *\n *                                                                         *\n * The purpose of this class is to contain those variables & routines\t\t*\n * specifically related to a multiplayer game.\t\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#ifndef SESSION_H\n#define SESSION_H\n\n#include \"ipxaddr.h\"\n#include \"msglist.h\"\n#include \"connect.h\"\n\n//---------------------------------------------------------------------------\n// Forward declarations\n//---------------------------------------------------------------------------\nclass AircraftClass;\nclass AnimClass;\nclass BuildingClass;\nclass BulletClass;\nclass InfantryClass;\nclass UnitClass;\nclass PhoneEntryClass;\nclass CellClass;\n\n//---------------------------------------------------------------------------\n// Defines\n//---------------------------------------------------------------------------\n//...........................................................................\n// Various limiting values\n//...........................................................................\n#define\tMPLAYER_BUILD_LEVEL_MAX\t\t10\t\t// max build level in multiplay\n#define\tMAX_MPLAYER_COLORS\t\t\t8\t\t// max # of colors\n\n//...........................................................................\n// Max sizes of packets we want to send\n// The IPX packet's size is IPX's max size (546), rounded down to accommodate\n// the max number of events possible.\n//...........................................................................\n#define\tMAX_IPX_PACKET_SIZE\t\t\t(((546 - sizeof(CommHeaderType)) / \\\n\t\t\t\t\t\t\t\t\t\t\t\tsizeof(EventClass) ) * sizeof(EventClass))\n#define\tMAX_SERIAL_PACKET_SIZE\t\t256\n\n//...........................................................................\n// Max length of player names fields; attempt to use the constant for the\n// HouseClass, if it's been defined; otherwise, define it myself.\n//...........................................................................\n#ifdef HOUSE_NAME_MAX\n#define\tMPLAYER_NAME_MAX\t\t\t\tHOUSE_NAME_MAX\n#else\n#define\tMPLAYER_NAME_MAX\t\t\t\t12\t\t// max length of a player's name\n#endif\n\n//...........................................................................\n// Values to control the multiplayer score screen\n//...........................................................................\n#define\tMAX_MULTI_NAMES\t8\t\t// max # names (rows) on the score screen\n#define\tMAX_MULTI_GAMES\t4\t\t// max # games (columns) on the score screen\n\n//...........................................................................\n// Min value for MaxAhead, for both net & modem; only applies for\n// COMM_PROTOCOL_MULTI_E_COMP.\n//...........................................................................\n#define MODEM_MIN_MAX_AHEAD\t\t\t5\n#define NETWORK_MIN_MAX_AHEAD\t\t\t2\n\n//...........................................................................\n// Send period (in frames) for COMM_PROTOCOL_MULTI_E_COMP and above\n//...........................................................................\n#define DEFAULT_FRAME_SEND_RATE\t\t3\n\n//...........................................................................\n// Modem-specific constants\n//...........................................................................\n#define\tPORTBUF_MAX\t\t\t\t\t\t64\t\t// dialog field sizes\n#define\tIRQBUF_MAX\t\t\t\t\t\t3\n#define\tBAUDBUF_MAX\t\t\t\t\t\t7\n#define\tINITSTRBUF_MAX\t\t\t\t\t41\n#define\tCWAITSTRBUF_MAX\t\t\t\t16\n#define\tCREDITSBUF_MAX\t\t\t\t\t5\n#define\tPACKET_TIMING_TIMEOUT\t\t40\t\t// ticks b/w sending a timing packet\n#define\tMODEM_NAME_MAX\t\t\t\t\tPORTBUF_MAX - 1\t// Max length of modem name in list box\n\n//---------------------------------------------------------------------------\n// Enums\n//---------------------------------------------------------------------------\n//...........................................................................\n// Types of games; used to tell which protocol we're using\n//...........................................................................\ntypedef enum GameEnum {\n\tGAME_NORMAL,\t\t\t\t\t\t\t\t\t// not multiplayer\n\tGAME_MODEM,\t\t\t\t\t\t\t\t\t\t// modem game\n\tGAME_NULL_MODEM,\t\t\t\t\t\t\t\t// NULL-modem\n\tGAME_IPX,\t\t\t\t\t\t\t\t\t\t// IPX Network game\n\tGAME_INTERNET,\t\t\t\t\t\t\t\t\t// Internet H2H\n\tGAME_SKIRMISH,\t\t\t\t\t\t\t\t\t// 1 plr vs. AI's\n\tGAME_TEN,\t\t\t\t\t\t\t\t\t\t// TEN Network game\n\tGAME_MPATH,\t\t\t\t\t\t\t\t\t\t// MPath Network game\n\tGAME_GLYPHX_MULTIPLAYER\t\t\t\t\t\t// Multiplayer game controlled by the GLYPHX engine. ST - 5/14/2019 11:41AM\n} GameType;\n\n//...........................................................................\n// Various Modem-specific enums\n//...........................................................................\ntypedef enum DetectPortType {\n\tPORT_VALID = 0,\n\tPORT_INVALID,\n\tPORT_IRQ_INUSE\n} DetectPortType;\n\ntypedef enum DialStatusType {\n\tDIAL_CONNECTED\t\t\t= 0,\n\tDIAL_NO_CARRIER,\n\tDIAL_BUSY,\n\tDIAL_ERROR,\n\tDIAL_NO_DIAL_TONE,\n\tDIAL_CANCELED\n} DialStatusType;\n\ntypedef enum DialMethodType {\n\tDIAL_TOUCH_TONE = 0,\n\tDIAL_PULSE,\n\tDIAL_METHODS\n} DialMethodType;\n\ntypedef enum CallWaitStringType {\n\tCALL_WAIT_TONE_1 = 0,\n\tCALL_WAIT_TONE_2,\n\tCALL_WAIT_PULSE,\n\tCALL_WAIT_CUSTOM,\n\tCALL_WAIT_STRINGS_NUM\n} CallWaitStringType;\n\ntypedef enum ModemGameType {\n\tMODEM_NULL_HOST = 0,\n\tMODEM_NULL_JOIN,\n\tMODEM_DIALER,\n\tMODEM_ANSWERER\n} ModemGameType;\n\n//...........................................................................\n// Commands sent over the serial Global Channel\n//...........................................................................\ntypedef enum SerialCommandType {\n\tSERIAL_CONNECT\t\t\t= 100,\t// Are you there?  Hello?  McFly?\n\tSERIAL_GAME_OPTIONS\t= 101,\t// Hey, dudes, here's some new game options\n\tSERIAL_SIGN_OFF\t\t= 102,\t// Bogus, dudes, my boss is coming; I'm outta here!\n\tSERIAL_GO\t\t\t\t= 103,\t// OK, dudes, jump into the game loop!\n\tSERIAL_MESSAGE\t\t\t= 104,\t// Here's a message\n\tSERIAL_TIMING\t\t\t= 105,\t// timimg packet\n\tSERIAL_SCORE_SCREEN\t= 106,\t// player at score screen\n\tSERIAL_LOADGAME\t\t= 107,\t// Start the game, loading a saved game first\n\tSERIAL_LAST_COMMAND,\t\t\t\t// last command\n\tSERIAL_REQ_SCENARIO\t= 1000,\t// Reqest that host sends the scenario file to the other players.\n\tSERIAL_FILE_INFO\t\t= 1001,\t// Info about the file that is going to be transferred\n\tSERIAL_FILE_CHUNK\t\t= 1002,\t// A chunk of scenario\n\tSERIAL_READY_TO_GO\t= 1003,\t// Sent in response to a 'GO' command\n\tSERIAL_NO_SCENARIO\t= 1004\t// Scenario isnt available on remote machine so we cant play\n} SerialCommandType;\n\n//...........................................................................\n// Commands sent over the network Global Channel\n//...........................................................................\ntypedef enum NetCommandType {\n\tNET_QUERY_GAME,\t\t\t// Hey, what games are out there?\n\tNET_ANSWER_GAME,\t\t\t// Yo, Here's my game's name!\n\tNET_QUERY_PLAYER,\t\t\t// Hey, what players are in this game?\n\tNET_ANSWER_PLAYER,\t\t// Yo, I'm in that game!\n\tNET_CHAT_ANNOUNCE,\t\t// I'm at the chat screen\n\tNET_CHAT_REQUEST,\t\t\t// Respond with a CHAT_ANNOUNCE, please.\n\tNET_QUERY_JOIN,\t\t\t// Hey guys, can I play too?\n\tNET_CONFIRM_JOIN,\t\t\t// Well, OK, if you really want to.\n\tNET_REJECT_JOIN,\t\t\t// No, you can't join; sorry, dude.\n\tNET_GAME_OPTIONS,\t\t\t// Hey, dudes, here's some new game options\n\tNET_SIGN_OFF,\t\t\t\t// Bogus, dudes, my boss is coming; I'm outta here!\n\tNET_GO,\t\t\t\t\t\t// OK, jump into the game loop!\n\tNET_MESSAGE,\t\t\t\t// Here's a message\n\tNET_PING,\t\t\t\t\t// I'm pinging you to take a time measurement\n\tNET_LOADGAME,\t\t\t\t// start a game by loading a saved game\n\tNET_REQ_SCENARIO  =1000,// Reqest that host sends the scenario file to the other players.\n\tNET_FILE_INFO\t\t=1001,// Info about the file that is going to be transferred\n\tNET_FILE_CHUNK\t\t=1002,// A chunk of scenario\n\tNET_READY_TO_GO\t=1003,// Sent in response to a 'GO' command\n\tNET_NO_SCENARIO\t=1004\t// Scenario isnt available on remote machine so we cant play\n} NetCommandType;\n\n//---------------------------------------------------------------------------\n// Structures\n//---------------------------------------------------------------------------\n//...........................................................................\n// An entry on the score screen is defined by this structure\n//...........................................................................\ntypedef struct {\n\tchar Name[MPLAYER_NAME_MAX];\n\tint Wins;\n\tint Kills[MAX_MULTI_GAMES];\n\tPlayerColorType Color;\n} MPlayerScoreType;\n\n//...........................................................................\n// Settings for the serial port\n//...........................................................................\ntypedef struct {\n\tint Port;\n\tint IRQ;\n\tint Baud;\n\tDialMethodType DialMethod;\n\tint InitStringIndex;\n\tint CallWaitStringIndex;\n\tchar CallWaitString[ CWAITSTRBUF_MAX ];\n\tbool Compression;\n\tbool ErrorCorrection;\n\tbool HardwareFlowControl;\n\tchar ModemName [ MODEM_NAME_MAX ];\n} SerialSettingsType;\n\n//...........................................................................\n//\tThis is a \"node\", used for the lists of available games & players.  The\n//\t'Game' structure is used for games; the 'Player' structure for players.\n//...........................................................................\ntypedef struct NodeNameTag {\n\tchar Name[MPLAYER_NAME_MAX];\t\t// player or game name\n\t\tIPXAddressClass Address;\n#if(TEN)\n\t\tint TenAddress;\n#endif\n#if(MPATH)\n\t\tint MPathAddress;\n#endif\n\tunion {\n\t\tstruct {\n\t\t\tunsigned char IsOpen;\t\t// is the game open?\n\t\t\tunsigned long LastTime;\t\t// last time we heard from this guy\n\t\t} Game;\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t// \"ActLike\" House of this player\n\t\t\tPlayerColorType Color;\t\t// Color of this player\n\t\t\tHousesType ID;\t\t\t\t\t// Actual House of this player\n\t\t\tint ProcessTime;\t\t\t\t// Length of time to process players main loop\n\t\t} Player;\n\t\tstruct {\n\t\t\tunsigned long LastTime;\t\t// last time we heard from this guy\n\t\t\tunsigned char LastChance;\t// we're about to remove him from the list\n\t\t\tPlayerColorType Color;\t\t// chat player's color\n\t\t} Chat;\n\t};\n} NodeNameType;\n\n\n//...........................................................................\n// Packet sent over the serial Global Channel\n//...........................................................................\ntypedef struct {\n\tSerialCommandType Command;\t\t\t\t\t// One of the enum's defined above\n\tchar Name[MPLAYER_NAME_MAX];\t\t\t\t// Player or Game Name\n\tunsigned char ID;\t\t\t\t\t\t\t\t// unique ID of sender of message\n\tunion {\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t\t\t\t\t// player's House\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t\tunsigned long MinVersion;\t\t\t\t\t// min version this game supports\n\t\t\tunsigned long MaxVersion;\t\t\t\t\t// max version this game supports\n\t\t\tchar Scenario[DESCRIP_MAX];\t\t\t\t// Scenario name\n\t\t\tunsigned int Credits;\t\t\t\t\t\t// player's credits\n\t\t\tunsigned int IsBases\t\t: 1;\t\t\t\t// 1 = bases are allowed\n\t\t\tunsigned int IsTiberium\t: 1;\t\t\t\t// 1 = tiberium is allowed\n\t\t\tunsigned int IsGoodies\t: 1;\t\t\t\t// 1 = goodies are allowed\n\t\t\tunsigned int IsGhosties\t: 1;\t\t\t\t// 1 = ghosts are allowed\n\t\t\tunsigned int OfficialScenario : 1;\t\t//\tIs this scenario an official Westwood one?\n\t\t\tint CheatCheck;\t\t\t\t\t\t\t\t// Unique ID of \"rules.ini\" file.\n\t\t\tunsigned char BuildLevel;\t\t\t\t\t// buildable level\n\t\t\tunsigned char UnitCount;\t\t\t\t\t// max # units\n\t\t\tunsigned char AIPlayers;\t\t\t\t\t// # of AI players allowed\n\t\t\tint Seed;\t\t\t\t\t\t\t\t\t\t// random number seed\n\t\t\tSpecialClass Special;\t\t\t\t\t\t// command-line options\n\t\t\tunsigned int GameSpeed;\t\t\t\t\t\t// Game Speed\n\t\t\tunsigned long ResponseTime;\t\t\t\t// packet response time\n\t\t\tunsigned int FileLength;\t\t\t\t\t// Length of scenario file to expect from host.\n#ifdef WOLAPI_INTEGRATION\n\t\t\tchar ShortFileName[13];\t\t\t\t\t\t// Name of scenario file to expect from host\n#else\n\t\t\tchar ShortFileName[12];\t\t\t\t\t\t// Name of scenario file to expect from host\n#endif\n\t\t\tunsigned char FileDigest[32];\t\t\t\t// Digest of scenario file to expect from host\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//\tajw - This is not necessarily null-terminated.\n\t\t} ScenarioInfo;\n\t\tstruct {\n\t\t\tchar Message[MAX_MESSAGE_LENGTH];\t\t// inter-player message\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t} Message;\n\t\tstruct {\n\t\t\tPlayerColorType Color;\t\t\t\t\t\t// player's color or SIGNOFF ID\n\t\t} Chat;\n\t};\n} SerialPacketType;\n\n//...........................................................................\n// Other packet sent over the serial global channel (for file transfers)\n//...........................................................................\n#define MAX_SEND_FILE_PACKET_SIZE MAX_SERIAL_PACKET_SIZE - 64\ntypedef struct {\n\tSerialCommandType\tCommand;\t\t\t\t\t// Enum defined above. Should be a file transfer enum.\n\tunsigned short \tBlockNumber;\t\t\t// Index position of this file chunk in the file\n\tunsigned short\t\tBlockLength;\t\t\t// Length of data in the RawData buffer\n\tunsigned char \t\tRawData\t[MAX_SEND_FILE_PACKET_SIZE];\n} RemoteFileTransferType;\n\n\n//...........................................................................\n// Packet sent over the network Global Channel\n//...........................................................................\ntypedef struct GlobalPacketType {\n\tNetCommandType Command;\t\t\t\t\t\t// One of the enum's defined above\n\tchar Name[MPLAYER_NAME_MAX];\t\t\t\t// Player or Game Name\n\tunion {\n\t\tstruct {\n\t\t\tunsigned int IsOpen\t\t: 1;\t\t// 1 = game is open for joining\n\t\t} GameInfo;\n\t\tstruct {\n\t\t\tHousesType House;\t\t\t\t\t\t// player's House\n\t\t\tPlayerColorType Color;\t\t\t\t// player's color\n\t\t\tunsigned long NameCRC;\t\t\t\t// CRC of player's game's name\n\t\t\tunsigned long MinVersion;\t\t\t// game's min supported version\n\t\t\tunsigned long MaxVersion;\t\t\t// game's max supported version\n\t\t\tint CheatCheck;\t\t\t\t\t\t// Unique ID of \"rules.ini\" file.\n\t\t} PlayerInfo;\n\t\tstruct {\n\t\t\tchar Scenario[DESCRIP_MAX];\t\t// Scenario Name\n\t\t\tunsigned int Credits;\t\t\t\t// player's credits\n\t\t\tunsigned int IsBases\t\t: 1;\t\t// 1 = bases are allowed\n\t\t\tunsigned int IsTiberium\t: 1;\t\t// 1 = tiberium is allowed\n\t\t\tunsigned int IsGoodies\t: 1;\t\t// 1 = goodies are allowed\n\t\t\tunsigned int IsGhosties\t: 1;\t\t// 1 = ghosts are allowed\n\t\t\tunsigned int OfficialScenario :1;// Is this scenario an official Westwood one?\n\t\t\tunsigned char BuildLevel;\t\t\t// buildable level\n\t\t\tunsigned char UnitCount;\t\t\t// max # units\n\t\t\tunsigned char AIPlayers;\t\t\t// # of AI players allowed\n\t\t\tint Seed;\t\t\t\t\t\t\t\t// random number seed\n\t\t\tSpecialClass Special;\t\t\t\t// command-line options\n\t\t\tunsigned int GameSpeed;\t\t\t\t// Game Speed\n\t\t\tunsigned long Version;\t\t\t\t// version # common to all players\n\t\t\tunsigned int FileLength;\t\t\t// Length of scenario file to expect from host.\n#ifdef WOLAPI_INTEGRATION\n\t\t\tchar ShortFileName[13];\t\t\t\t// Name of scenario file to expect from host\n#else\n\t\t\tchar ShortFileName[12];\t\t\t\t// Name of scenario file to expect from host\n#endif\n\t\t\tunsigned char FileDigest[32];\t\t// Digest of scenario file to expect from host\n\t\t\t\t\t\t\t\t\t\t\t\t//\tajw - This is not necessarily null-terminated.\n\t\t} ScenarioInfo;\n\t\tstruct {\n\t\t\tchar Buf[MAX_MESSAGE_LENGTH];\t\t// inter-user message\n\t\t\tPlayerColorType Color;\t\t\t\t\t// color of sender of message\n\t\t\tunsigned long NameCRC;\t\t\t\t// CRC of sender's Game Name\n\t\t} Message;\n\t\tstruct {\n\t\t\tint OneWay;\t\t\t\t\t\t\t\t// one-way response time\n\t\t} ResponseTime;\n\t\tstruct {\n\t\t\tint Why;\t\t\t\t\t\t\t\t\t// why were we rejected from the game?\n\t\t} Reject;\n\t\tstruct {\n\t\t\tunsigned long ID;\t\t\t\t\t\t// unique ID for this chat node\n\t\t\tPlayerColorType Color;\t\t\t\t// my color\n\t\t} Chat;\n\t};\n} GlobalPacketType;\n\n\n//...........................................................................\n// For finding sync bugs; filled in by the engine when certain conditions\n// are met; the pointers allow examination of objects in the debugger.\n//...........................................................................\ntypedef struct {\n\tunion {\n\t\tAircraftClass *Aircraft;\n\t\tAnimClass *Anim;\n\t\tBuildingClass *Building;\n\t\tBulletClass *Bullet;\n\t\tInfantryClass *Infantry;\n\t\tUnitClass *Unit;\n\t\tvoid *All;\n\t} Ptr;\n} TrapObjectType;\n\n/*\n**\tThis is the identifier for a multiplayer mission. This can be used to\n**\tidentify the filename of the mission as well as display the mission in a\n**\tmission selection list.\n*/\nclass MultiMission\n{\n\tpublic:\n\t\tMultiMission(char const * filename = NULL, char const * description = NULL, char const *digest = NULL, bool official = true, bool expansion = false);\n\n\t\tvoid Set_Description(char const * description);\n\t\tvoid Set_Filename(char const * filename);\n\t\tvoid Set_Digest(char const * digest);\n\t\tvoid Set_Official(bool official);\n\t\tvoid Set_Expansion(bool expansion);\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\t\tchar const * Description(void) const {return(ScenarioDescription);}\n\t\tchar const * Get_Filename(void) const {return(Filename);}\n\t\tchar const * Get_Digest(void) const {return(Digest);}\n\t\tbool Get_Official(void) { return (IsOfficial); }\n\t\tbool Get_Expansion(void) { return (IsExpansion); }\t//\tImplied \"IsCounterstrike\". No longer used. -ajw\n\n\tprivate:\n\t\tchar ScenarioDescription[DESCRIP_MAX];\n\t\tchar Filename[_MAX_FNAME+_MAX_EXT];\n\t\tchar Digest[32];\n\t\tbool IsOfficial;\n\t\tbool IsExpansion;\n};\n\n\ntypedef struct {\n\tint \tScenarioIndex;\t\t//Used on host machine only as index into scenario list\n\tint \tBases;\n\tint \tCredits;\n\tint \tTiberium;\n\tint \tGoodies;\n\tint \tGhosts;\n\tint \tUnitCount;\n\tint \tAIPlayers;\t\t\t// # of AI players allowed to be built\n\tchar\tScenarioDescription [DESCRIP_MAX];\t//Used on client machines only\n} GameOptionsType;\n\n//---------------------------------------------------------------------------\n// Class Definition\n//---------------------------------------------------------------------------\nclass SessionClass\n{\n\t//------------------------------------------------------------------------\n\t// Public interface\n\t//------------------------------------------------------------------------\n\tpublic:\n\t\t//.....................................................................\n\t\t// Constructor/Destructor\n\t\t//.....................................................................\n\t\tSessionClass(void);\n\t\t~SessionClass(void);\n\n\t\t//.....................................................................\n\t\t// Initialization\n\t\t//.....................................................................\n\t\tvoid One_Time(void);\n\t\tvoid Init(void);\n\n\t\t//.....................................................................\n\t\t// Reads/writes to the INI file\n\t\t//.....................................................................\n\t\tvoid Read_MultiPlayer_Settings (void);\n\t\tvoid Write_MultiPlayer_Settings (void);\n\t\tvoid Read_Scenario_Descriptions (void);\n\t\tvoid Free_Scenario_Descriptions(void);\n\n\t\t//.....................................................................\n\t\t// Utility functions\n\t\t//.....................................................................\n\t\tint Create_Connections(void);\n\t\tbool Am_I_Master(void);\n\t\tunsigned long Compute_Unique_ID(void);\n\n#if(TEN)\n\t\tint Create_TEN_Connections(void);\n#endif\t// TEN\n\n#if(MPATH)\n\t\tint Create_MPATH_Connections(void);\n#endif\t// MPATH\n\n\t\t//.....................................................................\n\t\t// File I/O\n\t\t//.....................................................................\n\t\tint Save(Pipe & file) const;\n\t\tint Load(Straw & file);\n\t\tint Save(CCFileClass & file);\n\t\tint Load(CCFileClass & file);\n\n\t\t//.....................................................................\n\t\t// Debugging / Sync Bugs\n\t\t//.....................................................................\n\t\tvoid Trap_Object(void);\n\n\t\t//---------------------------------------------------------------------\n\t\t// Public Data\n\t\t//---------------------------------------------------------------------\n\t\t//.....................................................................\n\t\t// The type of session being played\n\t\t//.....................................................................\n\t\tGameType Type;\n\n\t\t//.....................................................................\n\t\t// The current communications protocol\n\t\t//.....................................................................\n\t\tCommProtocolType CommProtocol;\n\n\t\t//.....................................................................\n\t\t// Game options\n\t\t//.....................................................................\n\t\tGameOptionsType Options;\n\n\t\t//.....................................................................\n\t\t// Unique workstation ID, for detecting my own packets\n\t\t//.....................................................................\n\t\tunsigned long UniqueID;\n\n\t\t//.....................................................................\n\t\t// Player's local options\n\t\t//.....................................................................\n\t\tchar Handle[MPLAYER_NAME_MAX];\t\t// player name\n\t\tPlayerColorType PrefColor;\t\t\t\t// preferred color index\n\t\tPlayerColorType ColorIdx;\t\t\t\t// actual color index\n\t\tHousesType House;\t\t\t\t\t\t\t// GDI / NOD\n\t\tint ObiWan;\t\t\t\t\t\t\t\t\t// 1 = player can see all\n\t\tint Solo;\t\t\t\t\t\t\t\t\t// 1 = player can play alone\n\n\t\t//.....................................................................\n\t\t// Max allowable # of players & actual # of (human) players\n\t\t//.....................................................................\n\t\tint MaxPlayers;\n\t\tint NumPlayers;\n\n\t\t//.....................................................................\n\t\t// Frame-sync'ing timing variables\n\t\t// 'MaxAhead' is the number of frames ahead of this one to execute\n\t\t// a given packet.  It's set by the RESPONSE_TIME event.\n\t\t// 'FrameSendRate' is the # frames between data packets\n\t\t//.....................................................................\n\t\tunsigned long MaxAhead;\n\t\tunsigned long FrameSendRate;\n\n\t\tint\t\t\tDesiredFrameRate;\n\n\t\tint\t\t\tProcessTimer;\n\t\tint\t\t\tProcessTicks;\n\t\tint\t\t\tProcessFrames;\n\n\t\t//.....................................................................\n\t\t// This flag is set when we've loaded a multiplayer game.\n\t\t//.....................................................................\n\t\tint LoadGame;\n\n\t\t//.....................................................................\n\t\t// This flag is set when the modem game saves the game due to a lost\n\t\t// connection.\n\t\t//.....................................................................\n\t\tint EmergencySave;\n\n\t\t//.....................................................................\n\t\t// List of scenarios & their file numbers\n\t\t//.....................................................................\n\t\tDynamicVectorClass<MultiMission *> Scenarios;\n//\t\tDynamicVectorClass <char *> Scenarios;\n//\t\tDynamicVectorClass <int> Filenum;\n\n\t\tchar ScenarioFileName[_MAX_FNAME+_MAX_EXT+1];\t//File name of scenario to load\n\n\t\tchar ScenarioDigest [32];\t\t\t\t\t\t\t\t//Digest of scenario to load\n\t\tunsigned int ScenarioFileLength;\n\t\tbool ScenarioIsOfficial;\n\n\t\tchar ScenarioRequests[20];\t\t//Which players requested scenario files\n\t\tint  RequestCount;\n\t\tIPXAddressClass\tHostAddress;\n\n\t\t//.....................................................................\n\t\t// This is the multiplayer messaging system\n\t\t//.....................................................................\n\t\tMessageListClass Messages;\n\t\tIPXAddressClass MessageAddress;\n\t\tchar LastMessage[MAX_MESSAGE_LENGTH];\n\t\tunsigned WWChat\t\t: 1;\t// 1 = go into special WW Chat mode\n\n\t\t//.....................................................................\n\t\t// This is the multiplayer scorekeeping system\n\t\t//.....................................................................\n\t\tMPlayerScoreType Score[MAX_MULTI_NAMES];\n\t\tint GamesPlayed;\t\t// # games played this run\n\t\tint NumScores;\t\t\t// # active entries in MPlayerScore\n\t\tint Winner;\t\t\t\t// index of winner of last game\n\t\tint CurGame;\t\t\t// index of current game being played\n\n\t\t//.....................................................................\n\t\t// Static arrays\n\t\t//.....................................................................\n\t\tstatic char Descriptions[100][40];\n\t\tstatic int CountMin[2];\n\t\tstatic int CountMax[2];\n\t\tstatic char * GlobalPacketNames[];\n\t\tstatic char * SerialPacketNames[];\n\n\t\t//.....................................................................\n\t\t// For Recording & Playing back a file\n\t\t//.....................................................................\n\t\tCCFileClass RecordFile;\n\t\tunsigned Record\t\t\t\t: 1;\n\t\tunsigned Play\t\t\t\t \t: 1;\n\t\tunsigned Attract\t\t\t \t: 1;\n\n\t\t//.....................................................................\n\t\t// IPX-specific variables\n\t\t//.....................................................................\n\t\tint IsBridge;\t\t\t\t\t\t\t\t// 1 = we're crossing a bridge\n\t\tIPXAddressClass BridgeNet;\t\t\t\t// address of bridge\n\t\tbool NetStealth;\t\t\t\t\t\t\t// makes us invisible\n\t\tbool NetProtect;\t\t\t\t\t\t\t// keeps others from messaging us\n\t\tbool NetOpen;\t\t\t\t\t\t\t\t// 1 = game is open for joining\n\t\tchar GameName[MPLAYER_NAME_MAX];\t\t// game's name\n\t\tGlobalPacketType GPacket;\t\t\t\t// global packet\n\t\tint GPacketlen;\t\t\t\t\t\t\t// global packet length\n\t\tIPXAddressClass GAddress;\t\t\t\t// address of sender\n\t\tunsigned short GProductID;\t\t\t\t// product ID of sender\n\t\tchar MetaPacket[MAX_IPX_PACKET_SIZE]; // packet building buffer\n\t\tint MetaSize;\t\t\t\t\t\t\t\t// size of MetaPacket\n\t\tDynamicVectorClass <NodeNameType *> Games;\t// list of games\n\t\tDynamicVectorClass <NodeNameType *> Players;\t// list of players\n\t\tDynamicVectorClass <NodeNameType *> Chat;\t\t// list of chat nodes\n\n\t\t//.....................................................................\n\t\t// Modem-specific variables\n\t\t//.....................................................................\n\t\tunsigned ModemService\t\t: 1;\t\t\t\t// 1 = service modem in Call_Back\n\t\tint CurPhoneIdx;\t\t\t\t\t\t\t// phone listing index\n\t\tSerialSettingsType SerialDefaults;\t// default serial settings\n\t\tModemGameType ModemType;\t\t\t\t// caller or answerer?\n\n\t\tDynamicVectorClass<PhoneEntryClass *> PhoneBook;\n\t\tDynamicVectorClass <char *> InitStrings;\n\t\tstatic char * DialMethodCheck[ DIAL_METHODS ];\n\t\tstatic char * CallWaitStrings[ CALL_WAIT_STRINGS_NUM ];\n\n\t\t//.....................................................................\n\t\t// For finding Sync Bugs\n\t\t//.....................................................................\n\t\tlong TrapFrame;\t\t\t\t// frame # to start trapping 'TrapObject'\n\t\tRTTIType TrapObjType;\t\t// type of object to trap\n\t\tTrapObjectType TrapObject;\t// ptr to object to trap (watch)\n\t\tCOORDINATE TrapCoord;\t\t// coord of object, 0 = ignore\n\t\tTARGET TrapTarget;\t\t\t// Target # of object, 0 = ignore\n\t\tCellClass * TrapCell;\t\t// Ptr to cell to trap (watch)\n\t\tint TrapCheckHeap;\t\t\t// true = check the heap as of TrapFrame\n\t\tlong TrapPrintCRC;\t\t\t// Frame # to print CRC state file\n\n#if(TEN)\n\t\t//\n\t\t// TEN-specific variables\n\t\t//\n\t\tchar *TenPacket;\n\t\tint TenSize;\n\t\tint TenMessageAddress;\n\t\tint TenAddress;\n\t\tint TenPlayerID;\n\t\tchar OptionsFile[256];\n\t\tint AllowSolo;\n\t\tint NetResponseTime;\n#endif\t// TEN\n\n#if(MPATH)\n\t\t//\n\t\t// MPATH-specific variables\n\t\t//\n\t\tchar *MPathPacket;\n\t\tint MPathSize;\n\t\tint MPathMessageAddress;\n\t\tint MPathAddress;\n\t\tchar OptionsFile[256];\n\t\tint AllowSolo;\n\t\tint NetResponseTime;\n#endif\t// MPATH\n};\n\n#endif\t\t// SESSION_H\n\n/*************************** end of session.h ******************************/\n"
  },
  {
    "path": "REDALERT/SHA.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHA.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHA.CPP                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/03/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAEngine::Result -- Fetch the current digest.                                            *\n *   SHAEngine::Hash -- Process an arbitrarily long data block.                                *\n *   SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data blo*\n *   SHAEngine::Process_Block -- Process a full data block into the hash accumulator.          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t<stdlib.h>\n//#include\t<iostream.h>\n#include\t\"sha.h\"\n\n\n\n#if !defined(__BORLANDC__) && !defined(min)\n#define\tmin(a, b)\t\t((a)<(b))?(a):(b)\n#endif\n\n\n/***********************************************************************************************\n * SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data bloc *\n *                                                                                             *\n *    This routine will see if there is a partial block already accumulated in the holding     *\n *    buffer. If so, then the data is fetched from the source such that a full buffer is       *\n *    accumulated and then processed. If there is insufficient data to fill the buffer, then   *\n *    it accumulates what data it can and then returns so that this routine can be called      *\n *    again later.                                                                             *\n *                                                                                             *\n * INPUT:   data  -- Reference to a pointer to the data. This pointer will be modified if      *\n *                   this routine consumes any of the data in the buffer.                      *\n *                                                                                             *\n *          length-- Reference to the length of the data available. If this routine consumes   *\n *                   any of the data, then this length value will be modified.                 *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Process_Partial(void const * & data, long & length)\n{\n\tif (length == 0 || data == NULL) return;\n\n\t/*\n\t**\tIf there is no partial buffer and the source is greater than\n\t**\ta source block size, then partial processing is unnecessary.\n\t**\tBail out in this case.\n\t*/\n\tif (PartialCount == 0 && length >= SRC_BLOCK_SIZE) return;\n\n\t/*\n\t**\tAttach as many bytes as possible from the source data into\n\t**\tthe staging buffer.\n\t*/\n\tint add_count = min((int)length, SRC_BLOCK_SIZE - PartialCount);\n\tmemcpy(&Partial[PartialCount], data, add_count);\n\tdata = ((char const *&)data) + add_count;\n\tPartialCount += add_count;\n\tlength -= add_count;\n\n\t/*\n\t**\tIf a full staging buffer has been accumulated, then process\n\t**\tthe staging buffer and then bail.\n\t*/\n\tif (PartialCount == SRC_BLOCK_SIZE) {\n\t\tProcess_Block(&Partial[0], Acc);\n\t\tLength += (long)SRC_BLOCK_SIZE;\n\t\tPartialCount = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * SHAEngine::Hash -- Process an arbitrarily long data block.                                  *\n *                                                                                             *\n *    This is the main access routine to the SHA engine. It will take the arbitrarily long     *\n *    data block and process it. The hash value is accumulated with any previous calls to      *\n *    this routine.                                                                            *\n *                                                                                             *\n * INPUT:   data     -- Pointer to the data block to process.                                  *\n *                                                                                             *\n *          length   -- The number of bytes to process.                                        *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Hash(void const * data, long length)\n{\n\tIsCached = false;\n\n\t/*\n\t**\tCheck for and handle any smaller-than-512bit blocks. This can\n\t**\tresult in all of the source data submitted to this routine to be\n\t**\tconsumed at this point.\n\t*/\n\tProcess_Partial(data, length);\n\n\t/*\n\t**\tIf there is no more source data to process, then bail. Speed reasons.\n\t*/\n\tif (length == 0) return;\n\n\t/*\n\t**\tFirst process all the whole blocks available in the source data.\n\t*/\n\tlong blocks = (length / SRC_BLOCK_SIZE);\n\tlong const * source = (long const *)data;\n\tfor (int bcount = 0; bcount < blocks; bcount++) {\n\t\tProcess_Block(source, Acc);\n\t\tLength += (long)SRC_BLOCK_SIZE;\n\t\tsource += SRC_BLOCK_SIZE/sizeof(long);\n\t\tlength -= (long)SRC_BLOCK_SIZE;\n\t}\n\n\t/*\n\t**\tProcess any remainder bytes. This data is stored in the source\n\t**\taccumulator buffer for future processing.\n\t*/\n\tdata = source;\n\tProcess_Partial(data, length);\n}\n\n\n#define\tReverse_LONG(a)\t((a>>24)&0x000000FFL) | ((a>>8)&0x0000FF00L) | ((a<<8)&0x00FF0000L) | ((a<<24)&0xFF000000L)\n\n\n/***********************************************************************************************\n * SHAEngine::Result -- Fetch the current digest.                                              *\n *                                                                                             *\n *    This routine will return the digest as it currently stands.                              *\n *                                                                                             *\n * INPUT:   pointer  -- Pointer to the buffer that will hold the digest -- 20 bytes.           *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied into the buffer. This will always be       *\n *          20.                                                                                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAEngine::Result(void * result) const\n{\n\t/*\n\t**\tIf the final hash result has already been calculated for the\n\t**\tcurrent data state, then immediately return with the precalculated\n\t**\tvalue.\n\t*/\n\tif (IsCached) {\n\t\tmemcpy(result, &FinalResult, sizeof(FinalResult));\n\t}\n\n\tlong length = Length + PartialCount;\n\tint partialcount = PartialCount;\n\tchar partial[SRC_BLOCK_SIZE];\n\tmemcpy(partial, Partial, sizeof(Partial));\n\n\t/*\n\t**\tCap the end of the source data stream with a 1 bit.\n\t*/\n\tpartial[partialcount] = (char)0x80;\n\n\t/*\n\t**\tDetermine if there is insufficient room to append the\n\t**\tdata length number to the hash source. If not, then\n\t**\tfill out the rest of the accumulator and flush it to\n\t**\tthe hash so that there will be room for the final\n\t**\tcount value.\n\t*/\n\tSHADigest acc = Acc;\n\tif ((SRC_BLOCK_SIZE - partialcount) < 9) {\n\t\tif (partialcount+1 < SRC_BLOCK_SIZE) {\n\t\t\tmemset(&partial[partialcount+1], '\\0', SRC_BLOCK_SIZE - (partialcount+1));\n\t\t}\n\t\tProcess_Block(&partial[0], acc);\n\t\tpartialcount = 0;\n\t} else {\n\t\tpartialcount++;\n\t}\n\n\t/*\n\t**\tPut the length of the source data as a 64 bit integer in the\n\t**\tlast 8 bytes of the pseudo-source data.\n\t*/\n\tmemset(&partial[partialcount], '\\0', SRC_BLOCK_SIZE - partialcount);\n\t*(long *)(&partial[SRC_BLOCK_SIZE-4]) = Reverse_LONG((length*8));\n\tProcess_Block(&partial[0], acc);\n\n\tmemcpy((char *)&FinalResult, &acc, sizeof(acc));\n\tfor (int index = 0; index < sizeof(FinalResult)/sizeof(long); index++) {\n//\tfor (int index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {\n\t\t(long &)FinalResult.Long[index] = Reverse_LONG(FinalResult.Long[index]);\n\t}\n\t(bool&)IsCached = true;\n\tmemcpy(result, &FinalResult, sizeof(FinalResult));\n\treturn(sizeof(FinalResult));\n}\n\n/*\n**\tThis pragma to turn off the warning \"Conversion may lose significant digits\" is to\n**\twork around a bug within the Borland compiler. It will give this warning when the\n**\t_rotl() function is called but will NOT give the warning when the _lrotl() function\n**\tis called even though they both have the same parameters and declaration attributes.\n*/\n//#pragma warn -sig\ntemplate<class T>\nT _rotl(T X, int n)\n{\n\treturn(T)( ( X << n ) | ( (unsigned)X >> ((sizeof(T)*8) - n) ) );\n}\n//unsigned long _RTLENTRY _rotl(unsigned long X, int n)\n//{\n//\treturn(unsigned long)( (unsigned long)( (unsigned long)( (unsigned long)X ) << (int)n ) | (unsigned long)( ((unsigned long) X ) >> ( (int)((int)(sizeof(long)*(long)8) - (long)n) ) ) );\n//}\nvoid memrev(char * buffer, size_t length);\n\n\n/***********************************************************************************************\n * SHAEngine::Process_Block -- Process a full data block into the hash accumulator.            *\n *                                                                                             *\n *    This helper routine is called when a full block of data is available for processing      *\n *    into the hash.                                                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the block of data to process.                               *\n *                                                                                             *\n *          acc      -- Reference to the hash accumulator that this hash step will be          *\n *                      accumulated into.                                                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SHAEngine::Process_Block(void const * source, SHADigest & acc) const\n{\n\t/*\n\t**\tThe hash is generated by performing operations on a\n\t**\tblock of generated/seeded data.\n\t*/\n\tlong block[PROC_BLOCK_SIZE/sizeof(long)];\n\n\t/*\n\t**\tExpand the source data into a large 80 * 32bit buffer. This is the working\n\t**\tdata that will be transformed by the secure hash algorithm.\n\t*/\n\tlong const * data = (long const *)source;\n\tint index;\n\tfor (index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {\n\t\tblock[index] = Reverse_LONG(data[index]);\n\t}\n\n\tfor (index = SRC_BLOCK_SIZE/sizeof(long); index < PROC_BLOCK_SIZE/sizeof(long); index++) {\n//\t\tblock[index] = _rotl(block[(index-3)&15] ^ block[(index-8)&15] ^ block[(index-14)&15] ^ block[(index-16)&15], 1);\n\t\tblock[index] = _rotl(block[index-3] ^ block[index-8] ^ block[index-14] ^ block[index-16], 1);\n\t}\n\n\t/*\n\t**\tThis is the core algorithm of the Secure Hash Algorithm. It is a block\n\t**\ttransformation of 512 bit source data with a 2560 bit intermediate buffer.\n\t*/\n\tSHADigest alt = acc;\n\tfor (index = 0; index < PROC_BLOCK_SIZE/sizeof(long); index++) {\n\t\tlong temp = _rotl(alt.Long[0], 5) + Do_Function(index, alt.Long[1], alt.Long[2], alt.Long[3]) + alt.Long[4] + block[index] + Get_Constant(index);\n\t\talt.Long[4] = alt.Long[3];\n\t\talt.Long[3] = alt.Long[2];\n\t\talt.Long[2] = _rotl(alt.Long[1], 30);\n\t\talt.Long[1] = alt.Long[0];\n\t\talt.Long[0] = temp;\n\t}\n\tacc.Long[0] += alt.Long[0];\n\tacc.Long[1] += alt.Long[1];\n\tacc.Long[2] += alt.Long[2];\n\tacc.Long[3] += alt.Long[3];\n\tacc.Long[4] += alt.Long[4];\n}\n\n"
  },
  {
    "path": "REDALERT/SHA.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHA.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHA.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 04/26/96                                                     *\n *                                                                                             *\n *                  Last Update : April 26, 1996 [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHA_H\n#define SHA_H\n\n\n/*\n**\tThe \"bool\" integral type was defined by the C++ committee in\n**\tNovember of '94. Until the compiler supports this, use the following\n**\tdefinition.\n*/\n#ifndef __BORLANDC__\n#ifndef TRUE_FALSE_DEFINED\n#define TRUE_FALSE_DEFINED\nenum {false=0,true=1};\ntypedef int bool;\n#endif\n#endif\n\n\n#include\t<stdio.h>\n#include\t<string.h>\n#include\t<stdlib.h>\n#include\t<new.h>\n\n\n/*\n**\tThis implements the Secure Hash Algorithm. It is a cryptographically\n**\tsecure hash with no known weaknesses. It generates a 160 bit hash\n**\tresult given an arbitrary length data source.\n*/\nclass SHAEngine\n{\n\tpublic:\n\t\tSHAEngine(void) : IsCached(false), Length(0), PartialCount(0) {\n\t\t\tAcc.Long[0] = SA;\n\t\t\tAcc.Long[1] = SB;\n\t\t\tAcc.Long[2] = SC;\n\t\t\tAcc.Long[3] = SD;\n\t\t\tAcc.Long[4] = SE;\n\t\t};\n\n\t\tvoid Init(void) {\n\t\t\tnew ((void*)this) SHAEngine;\n\t\t};\n\n\t\t// Fetch result as if source data were to stop now.\n\t\tint Result(void * result) const;\n\n\t\tvoid Hash(void const * data, long length);\n\n\t\tstatic int Digest_Size(void) {return(sizeof(SHADigest));}\n\n\tprivate:\n\n\t\ttypedef union {\n\t\t\tunsigned long Long[5];\n\t\t\tunsigned char Char[20];\n\t\t} SHADigest;\n\n\t\t/*\n\t\t**\tThis holds the calculated final result. It is cached\n\t\t**\there to avoid the overhead of recalculating it over\n\t\t**\tmultiple sequential requests.\n\t\t*/\n\t\tbool IsCached;\n\t\tSHADigest FinalResult;\n\n\t\tenum {\n\t\t\t// These are the initial seeds to the block accumulators.\n\t\t\tSA=0x67452301L,\n\t\t\tSB=0xefcdab89L,\n\t\t\tSC=0x98badcfeL,\n\t\t\tSD=0x10325476L,\n\t\t\tSE=0xc3d2e1f0L,\n\n\t\t\t// These are the constants used in the block transformation.\n\t\t\tK1=0x5a827999L,\t\t// t=0..19\t\t2^(1/2)/4\n\t\t\tK2=0x6ed9eba1L,\t\t// t=20..39\t\t3^(1/2)/4\n\t\t\tK3=0x8f1bbcdcL,\t\t// t=40..59\t\t5^(1/2)/4\n\t\t\tK4=0xca62c1d6L,\t\t// t=60..79\t\t10^(1/2)/4\n\n\t\t\t// Source data is grouped into blocks of this size.\n\t\t\tSRC_BLOCK_SIZE=16*sizeof(long),\n\n\t\t\t// Internal processing data is grouped into blocks this size.\n\t\t\tPROC_BLOCK_SIZE=80*sizeof(long)\n\t\t};\n\n\t\tlong Get_Constant(int index) const {\n\t\t\tif (index < 20) return K1;\n\t\t\tif (index < 40) return K2;\n\t\t\tif (index < 60) return K3;\n\t\t\treturn K4;\n\t\t};\n\n\t\t// Used for 0..19\n\t\tlong Function1(long X, long Y, long Z) const {\n\t\t\treturn(Z ^ ( X & ( Y ^ Z ) ) );\n\t\t};\n\n\t\t// Used for 20..39\n\t\tlong Function2(long X, long Y, long Z) const {\n\t\t\treturn( X ^ Y ^ Z );\n\t\t};\n\n\t\t// Used for 40..59\n\t\tlong Function3(long X, long Y, long Z) const {\n\t\t\treturn( (X & Y) | (Z & (X | Y) ) );\n\t\t};\n\n\t\t// Used for 60..79\n\t\tlong Function4(long X, long Y, long Z) const {\n\t\t\treturn( X ^ Y ^ Z );\n\t\t};\n\n\t\tlong Do_Function(int index, long X, long Y, long Z) const {\n\t\t\tif (index < 20) return Function1(X, Y, Z);\n\t\t\tif (index < 40) return Function2(X, Y, Z);\n\t\t\tif (index < 60) return Function3(X, Y, Z);\n\t\t\treturn Function4(X, Y, Z);\n\t\t};\n\n\t\t// Process a full source data block.\n\t\tvoid Process_Block(void const * source, SHADigest & acc) const;\n\n\t\t// Processes a partially filled source accumulator buffer.\n\t\tvoid Process_Partial(void const * & data, long & length);\n\n\t\t/*\n\t\t**\tThis is the running accumulator values. These values\n\t\t**\tare updated by a block processing step that occurs\n\t\t**\tevery 512 bits of source data.\n\t\t*/\n\t\tSHADigest Acc;\n\n\t\t/*\n\t\t**\tThis is the running length of the source data\n\t\t**\tprocessed so far. This total is used to modify the\n\t\t**\tresulting hash value as if it were appended to the end\n\t\t**\tof the source data.\n\t\t*/\n\t\tlong Length;\n\n\t\t/*\n\t\t**\tThis holds any partial source block. Partial source blocks are\n\t\t**\ta consequence of submitting less than block sized data chunks\n\t\t**\tto the SHA Engine.\n\t\t*/\n\t\tint PartialCount;\n\t\tchar Partial[SRC_BLOCK_SIZE];\n};\n\n\n#define\tSHA_SOURCE1\t\t\"abc\"\n#define\tSHA_DIGEST1a\t\"\\xA9\\x99\\x3E\\x36\\x47\\x06\\x81\\x6A\\xBA\\x3E\\x25\\x71\\x78\\x50\\xC2\\x6C\\x9C\\xD0\\xD8\\x9D\"\n#define\tSHA_DIGEST1b\t\"\\x01\\x64\\xB8\\xA9\\x14\\xCD\\x2A\\x5E\\x74\\xC4\\xF7\\xFF\\x08\\x2C\\x4D\\x97\\xF1\\xED\\xF8\\x80\"\n\n\n#define\tSHA_SOURCE2\t\t\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"\n#define\tSHA_DIGEST2a\t\"\\x84\\x98\\x3E\\x44\\x1C\\x3B\\xD2\\x6E\\xBA\\xAE\\x4A\\xA1\\xF9\\x51\\x29\\xE5\\xE5\\x46\\x70\\xF1\"\n#define\tSHA_DIGEST2b\t\"\\xD2\\x51\\x6E\\xE1\\xAC\\xFA\\x5B\\xAF\\x33\\xDF\\xC1\\xC4\\x71\\xE4\\x38\\x44\\x9E\\xF1\\x34\\xC8\"\n\n#define\tSHA_SOURCE3\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n#define\tSHA_DIGEST3a\t\"\\x34\\xAA\\x97\\x3C\\xD4\\xC4\\xDA\\xA4\\xF6\\x1E\\xEB\\x2B\\xDB\\xAD\\x27\\x31\\x65\\x34\\x01\\x6F\"\n#define\tSHA_DIGEST3b\t\"\\x32\\x32\\xAF\\xFA\\x48\\x62\\x8A\\x26\\x65\\x3B\\x5A\\xAA\\x44\\x54\\x1F\\xD9\\x0D\\x69\\x06\\x03\"\n\n#endif\n"
  },
  {
    "path": "REDALERT/SHAPEBTN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHAPEBTN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPEBTN.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : September 20, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   ShapeButtonClass::Draw_Me -- Renders the shape button's imagery.                          *\n *   ShapeButtonClass::Set_Shape -- Assigns a shape to this shape button.                      *\n *   ShapeButtonClass::ShapeButtonClass -- Constructor for a shape type button.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"shapebtn.h\"\n\n\n/***********************************************************************************************\n * ShapeButtonClass::ShapeButtonClass -- Default Constructor for a shape type button.          *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   You must call Set_Shape() before using a button constructed with this function, *\n *             and you must set X & Y, and ID.                                                 *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nShapeButtonClass::ShapeButtonClass(void) :\n\tToggleClass(0, 0, 0, 0, 0),\n\tReflectButtonState(false)\n{\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::ShapeButtonClass -- Constructor for a shape type button.                  *\n *                                                                                             *\n *    This is the normal constructor for a shape type button. Shape buttons are ones that      *\n *    have their imagery controlled by a shape file. The various states of the button are      *\n *    given a visual form as one of these shapes. Button dimensions are controlled by the      *\n *    first shape.                                                                             *\n *                                                                                             *\n * INPUT:   id    -- The button ID.                                                            *\n *                                                                                             *\n *          shape -- Pointer to the shape file that controls the button's display.             *\n *                                                                                             *\n *          x,y   -- The pixel coordinate of the upper left corner of the button.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The width and height of the shape is controlled by the first shape in the       *\n *             shape file provided. This means that all the shapes in the shape file must be   *\n *             the same size.                                                                  *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nShapeButtonClass::ShapeButtonClass(unsigned id, void const * shape, int x, int y) :\n\tToggleClass(id, x, y, 0, 0),\n\tReflectButtonState(false)\n{\n//\tWidth = 0;\n//\tHeight = 0;\n\tSet_Shape(shape);\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::Set_Shape -- Assigns a shape to this shape button.                        *\n *                                                                                             *\n *    This routine will assign the specified shape to this shape object.                       *\n *                                                                                             *\n * INPUT:   data  -- Pointer to the shape to assign.                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid ShapeButtonClass::Set_Shape(void const * data)\n{\n\tShapeData = data;\n\tif (ShapeData) {\n\t\tWidth = Get_Build_Frame_Width(ShapeData);\n\t\tHeight = Get_Build_Frame_Height(ShapeData);\n\t}\n}\n\n\n/***********************************************************************************************\n * ShapeButtonClass::Draw_Me -- Renders the shape button's imagery.                            *\n *                                                                                             *\n *    This function is called when the button detects that it must be redrawn. The actual      *\n *    shape to use is controled by the button's state and the shape file provided when then    *\n *    button was constructed.                                                                  *\n *                                                                                             *\n * INPUT:   forced   -- Should the button be redrawn regardless of the redraw flag?            *\n *                                                                                             *\n * OUTPUT:  bool; Was the shape redrawn?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/15/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint ShapeButtonClass::Draw_Me(int forced)\n{\n\tif (ControlClass::Draw_Me(forced) && ShapeData) {\n\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width-1, Y+Height-1);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the body & set text color.\n\t\t*/\n\t\tint shapenum = 0;\n\t\tif (IsDisabled) {\n\t\t\tshapenum = DISABLED_SHAPE;\n\t\t} else {\n\n\t\t\tif (!ReflectButtonState) {\n\n\t\t\t\tif (IsPressed) {\n\t\t\t\t\tshapenum = DOWN_SHAPE;\n\t\t\t\t} else {\n\t\t\t\t\tshapenum = UP_SHAPE;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tshapenum = IsOn;\n\t\t\t}\n\n\t\t}\n\t\tCC_Draw_Shape(ShapeData, shapenum, X, Y, WINDOW_MAIN, SHAPE_NORMAL);\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n\n"
  },
  {
    "path": "REDALERT/SHAPEBTN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHAPEBTN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPEBTN.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SHAPEBTN_H\n#define SHAPEBTN_H\n\n#include\t\"toggle.h\"\n\nclass ShapeButtonClass : public ToggleClass\n{\n\tpublic:\n\t\tShapeButtonClass(void);\n\t\tShapeButtonClass(unsigned id, void const * shapes, int x, int y);\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual void Set_Shape(void const * data);\n\t\tvoid const * Get_Shape_Data(void) {return(ShapeData);};\n\n\t\tenum ShapeButtonClassEnums {\n\t\t\tUP_SHAPE,\t\t\t\t// Shape to use when button is \"up\".\n\t\t\tDOWN_SHAPE,\t\t\t\t// Shape to use when button is \"down\".\n\t\t\tDISABLED_SHAPE\t\t\t// Shape to use when button is disabled.\n\t\t};\n\n\t\tunsigned ReflectButtonState:1;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tThis points to the shape data file. This file contains the appropriate shapes\n\t\t**\tfor this button in the offsets specified above.\n\t\t*/\n\t\tvoid const * ShapeData;\n};\n#endif\n"
  },
  {
    "path": "REDALERT/SHAPIPE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHAPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPIPE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAPipe::Result -- Fetches the current SHA value.                                         *\n *   SHAPipe::Put -- Pass data through the pipe, but use it to build a SHA digest.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"shapipe.h\"\n\n\n/***********************************************************************************************\n * SHAPipe::Put -- Pass data through the pipe, but use it to build a SHA digest.               *\n *                                                                                             *\n *    This pipe segment will not modify the data, but it will examine the data and use it when *\n *    building a SHA digest.                                                                   *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the data to flow through the pipe.                          *\n *                                                                                             *\n *          length   -- The number of bytes to submit.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the actual number of bytes output at the distant final end of the     *\n *          pipe chain.                                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAPipe::Put(void const * source, int slen)\n{\n\tSHA.Hash(source, slen);\n\treturn(Pipe::Put(source, slen));\n}\n\n\n/***********************************************************************************************\n * SHAPipe::Result -- Fetches the current SHA value.                                           *\n *                                                                                             *\n *    This routine will return the SHA digest for the data that has passed through this        *\n *    link in the pipe chain. It is a non-destructive read.                                    *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the SHA digest. This buffer must be      *\n *                      20 bytes long.                                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes copied into the buffer. This will be 20.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAPipe::Result(void * result) const\n{\n\treturn(SHA.Result(result));\n}\n\n\n"
  },
  {
    "path": "REDALERT/SHAPIPE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHAPIPE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHAPIPE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 06/30/96                                                     *\n *                                                                                             *\n *                  Last Update : June 30, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHAPIPE_H\n#define SHAPIPE_H\n\n#include\t\"pipe.h\"\n#include\t\"sha.h\"\n\n/*\n**\tThis class serves as a pipe that generates a Secure Hash from the data stream that flows\n**\tthrough it. It doesn't modify the data stream in any fashion.\n*/\nclass SHAPipe : public Pipe\n{\n\tpublic:\n\t\tSHAPipe(void) {}\n\t\tvirtual int Put(void const * source, int slen);\n\n\t\t// Fetch the SHA hash value (stored in result buffer -- 20 bytes long).\n\t\tint Result(void * result) const;\n\n\tprotected:\n\t\tSHAEngine SHA;\n\n\tprivate:\n\t\tSHAPipe(SHAPipe & rvalue);\n\t\tSHAPipe & operator = (SHAPipe const & pipe);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SHASTRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHASTRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHASTRAW.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SHAStraw::Get -- Fetch data from the straw and process the SHA with the data.             *\n *   SHAStraw::Result -- Fetches the current SHA digest.                                       *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"shastraw.h\"\n\n\n/***********************************************************************************************\n * SHAStraw::Get -- Fetch data from the straw and process the SHA with the data.               *\n *                                                                                             *\n *    This routine will fetch the requested data and as it passes through this straw it will   *\n *    submit it to the SHA processor. The data that passes through is unmodified by this       *\n *    straw segment.                                                                           *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer that will hold the requested data.               *\n *                                                                                             *\n *          length   -- The length of the data requested.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored in the buffer. If this number is less      *\n *          than the number requested, then this indicates that the data stream has been       *\n *          exhausted.                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAStraw::Get(void * source, int slen)\n{\n\tif (source == NULL || slen < 1) {\n\t\treturn(0);\n\t}\n\n\tint counter = Straw::Get(source, slen);\n\tSHA.Hash(source, counter);\n\treturn(counter);\n}\n\n\n/***********************************************************************************************\n * SHAStraw::Result -- Fetches the current SHA digest.                                         *\n *                                                                                             *\n *    Use this routine to fetch the current SHA digest from the straw. It will return the      *\n *    digest of the data that has passed through this straw segment.                           *\n *                                                                                             *\n * INPUT:   result   -- Pointer to the buffer to hold the message digest. The buffer must be   *\n *                      20 bytes long.                                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the digest buffer. This will always   *\n *          be 20.                                                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SHAStraw::Result(void * result) const\n{\n\treturn(SHA.Result(result));\n}\n"
  },
  {
    "path": "REDALERT/SHASTRAW.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SHASTRAW.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SHASTRAW.H                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 2, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SHASTRAW_H\n#define SHASTRAW_H\n\n\n#include\t\"straw.h\"\n#include\t\"sha.h\"\n\n/*\n**\tThis class serves as a straw that generates a Secure Hash from the data stream that flows\n**\tthrough it. It doesn't modify the data stream in any fashion.\n*/\nclass SHAStraw : public Straw\n{\n\tpublic:\n\t\tSHAStraw(void) {}\n\t\tvirtual int Get(void * source, int slen);\n\n\t\t// Fetch the SHA hash value (stored in result buffer -- 20 bytes long).\n\t\tint Result(void * result) const;\n\n\tprotected:\n\t\tSHAEngine SHA;\n\n\tprivate:\n\t\tSHAStraw(SHAStraw & rvalue);\n\t\tSHAStraw & operator = (SHAStraw const & straw);\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/SIDEBAR.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/SIDEBAR.CPP 2     3/17/97 1:05a Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBAR.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 20, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 9, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SidebarClass::AI -- Handles player clicking on sidebar area.                              *\n *   SidebarClass::Abandon_Production -- Stops production of the object specified.             *\n *   SidebarClass::Activate -- Controls the sidebar activation.                                *\n *   SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.           *\n *   SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.               *\n *   SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.             *\n *   SidebarClass::Add -- Adds a game object to the sidebar list.                              *\n *   SidebarClass::Draw_It -- Renders the sidebar display.                                     *\n *   SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                         *\n *   SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state               *\n *   SidebarClass::Init_IO -- Adds buttons to the button list                                  *\n *   SidebarClass::Init_Theater -- Performs theater-specific initialization                    *\n *   SidebarClass::One_Time -- Handles the one time game initializations.                      *\n *   SidebarClass::One_Time -- Handles the one time game initializations.                      *\n *   SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.            *\n *   SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.      *\n *   SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the s*\n *   SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                       *\n *   SidebarClass::Set_Current -- Sets a specified object that controls the sidebar display.   *\n *   SidebarClass::SidebarClass -- Default constructor for the sidebar.                        *\n *   SidebarClass::SidebarClass -- This is the no initialization constructor for the sidebar.  *\n *   SidebarClass::StripClass::AI -- Input and AI processing for the side strip.               *\n *   SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.   *\n *   SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.         *\n *   SidebarClass::StripClass::Add -- Add an object to the side strip.                         *\n *   SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syst*\n *   SidebarClass::StripClass::Draw_It -- Render the sidebar display.                          *\n *   SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.            *\n *   SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.         *\n *   SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.     *\n *   SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state   *\n *   SidebarClass::StripClass::Init_IO -- Adds buttons to the button list                      *\n *   SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization        *\n *   SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side str*\n *   SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.      *\n *   SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                      *\n *   SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selecte*\n *   SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select bu*\n *   SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                *\n *   SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.     *\n *   SidebarClass::Which_Column -- Determines which column a given type should appear.         *\n *   SidebarClass::Zoom_Mode_Control -- Handles the zoom mode toggle operation.                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\nvoid * SidebarClass::SidebarShape = NULL;\nvoid * SidebarClass::SidebarMiddleShape = NULL;\nvoid * SidebarClass::SidebarBottomShape = NULL;\n\n\n/***************************************************************************\n**\tThis holds the translucent table for use with the construction clock\n**\tanimation.\n*/\nchar SidebarClass::StripClass::ClockTranslucentTable[(1+1)*256];\n\n\n/***************************************************************************\n**\tThis points to the main sidebar shapes. These include the upgrade and\n**\trepair buttons.\n*/\n//TheaterType SidebarClass::StripClass::LastTheater = THEATER_NONE;\n\ntypedef enum ButtonNumberType {\n\tBUTTON_RADAR = 100,\n\tBUTTON_REPAIR,\n\tBUTTON_DEMOLISH,\n\tBUTTON_UPGRADE,\n\tBUTTON_SELECT,\n\tBUTTON_ZOOM\n} ButtonNumberType;\n\n/*\n** Sidebar buttons\n*/\nSidebarClass::SBGadgetClass SidebarClass::Background;\nShapeButtonClass SidebarClass::Repair;\nShapeButtonClass SidebarClass::Upgrade;\nShapeButtonClass SidebarClass::Zoom;\nShapeButtonClass SidebarClass::StripClass::UpButton[COLUMNS];\nShapeButtonClass SidebarClass::StripClass::DownButton[COLUMNS];\nSidebarClass::StripClass::SelectClass\nSidebarClass::StripClass::SelectButton[COLUMNS][MAX_VISIBLE];\n\n/*\n** Shape data pointers\n*/\nvoid * SidebarClass::StripClass::LogoShapes = NULL;\nvoid const * SidebarClass::StripClass::ClockShapes;\nvoid const * SidebarClass::StripClass::SpecialShapes[SPC_COUNT];\n\n\n/***********************************************************************************************\n * SidebarClass::SidebarClass -- Default constructor for the sidebar.                          *\n *                                                                                             *\n *    Constructor for the sidebar handler. It basically sets up the sidebar to the empty       *\n *    condition.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::SidebarClass(void) :\n\tIsSidebarActive(false),\n\tIsToRedraw(true),\n\tIsRepairActive(false),\n\tIsUpgradeActive(false),\n\tIsDemolishActive(false)\n{\n\t/*\n\t**\tThis sets up the clipping window. This window is used by the shape drawing\n\t**\tcode so that as the sidebar buildable buttons scroll, they get properly\n\t**\tclipped at the top and bottom edges.\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWX] = (SIDE_X+8);\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] = SIDE_Y + 1 + TOP_HEIGHT;\n\tWindowList[WINDOW_SIDEBAR][WINDOWWIDTH] = SIDE_WIDTH;\n\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT;\n//\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT-1;\n\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n\tnew (&Column[0]) StripClass(InitClass());\n\tnew (&Column[1]) StripClass(InitClass());\n\n\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n}\n\n\n/***********************************************************************************************\n * SidebarClass::SidebarClass -- This is the no initialization constructor for the sidebar.    *\n *                                                                                             *\n *    Unlike the normal constructor, this one doesn't do any initialization. There is one      *\n *    exception to this. The stip classes can't call an explicit NoInitClass constructor       *\n *    since they are an array. Since the default constructor is called for these strips, we    *\n *    must reset the X and Y location to what we know they should be.                          *\n *                                                                                             *\n * INPUT:   flag to indicate that this is a no initialization constructor.                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/06/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::SidebarClass(NoInitClass const & x) : PowerClass(x)\n{\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n//\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n//\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n//\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n//\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n}\n\n\n/***********************************************************************************************\n * SidebarClass::One_Time -- Handles the one time game initializations.                        *\n *                                                                                             *\n *    This routine is used to load the graphic data that is needed by the sidebar display. It  *\n *    should only be called ONCE.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Only call this routine once when the game first starts.                         *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::One_Time(void)\n{\n\tPowerClass::One_Time();\n\n\t/*\n\t**\tThis sets up the clipping window. This window is used by the shape drawing\n\t**\tcode so that as the sidebar buildable buttons scroll, they get properly\n\t**\tclipped at the top and bottom edges.\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWX] = ((SIDE_X+8))  * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] = (SIDE_Y + 1 + TOP_HEIGHT) * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWWIDTH] = (SIDE_WIDTH) * RESFACTOR;\n\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = (StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT) * RESFACTOR;\n//\tWindowList[WINDOW_SIDEBAR][WINDOWHEIGHT] = (StripClass::MAX_VISIBLE * StripClass::OBJECT_HEIGHT-1) * RESFACTOR;\n\n\t/*\n\t** Top of the window seems to be wrong for the new sidebar. ST - 5/2/96 2:49AM\n\t*/\n\tWindowList[WINDOW_SIDEBAR][WINDOWY] -= 1*RESFACTOR;\n\n\t/*\n\t**\tSet up the coordinates for the sidebar strips. These coordinates are for\n\t**\tthe upper left corner.\n\t*/\n//\tColumn[0].X = COLUMN_ONE_X * RESFACTOR;\n//\tColumn[0].Y = COLUMN_ONE_Y * RESFACTOR;\n//\tColumn[1].X = COLUMN_TWO_X * RESFACTOR;\n//\tColumn[1].Y = COLUMN_TWO_Y * RESFACTOR;\n\tColumn[0].One_Time(0);\n\tColumn[1].One_Time(1);\n\n\t/*\n\t**\tLoad the sidebar shape in at this time. (Hi-Res sidebar is theater dependant)\n\t*/\n\tif (SidebarShape == NULL) {\n\t\tSidebarShape = (void*)MFCD::Retrieve(\"SIDEBAR.SHP\");\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_Clear(void)\n{\n\n\tPowerClass::Init_Clear();\n\n\tIsToRedraw = true;\n\tIsRepairActive = false;\n\tIsUpgradeActive = false;\n\tIsDemolishActive = false;\n\n\tColumn[0].Init_Clear();\n\tColumn[1].Init_Clear();\n\n\tActivate(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_IO -- Adds buttons to the button list                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_IO(void)\n{\n\tPowerClass::Init_IO();\n\n\t/*\n\t** Add the sidebar's buttons only if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\n\t\tRepair.IsSticky = true;\n\t\tRepair.ID = BUTTON_REPAIR;\n\t\tRepair.X = (0x1f2/2)*RESFACTOR;\n\t\tRepair.Y = (0x96/2)*RESFACTOR;\n\t\tRepair.IsPressed = false;\n\t\tRepair.IsToggleType = true;\n\t\tRepair.ReflectButtonState = true;\n\t\tRepair.Set_Shape(MFCD::Retrieve(\"REPAIR.SHP\"));\n\n\t\tUpgrade.IsSticky = true;\n\t\tUpgrade.ID = BUTTON_UPGRADE;\n#ifdef WIN32\n\t\tUpgrade.X = 0x21f;\n#else\n\t\tUpgrade.X = ((0x21f/2)+1)*RESFACTOR;\n#endif\n\t\tUpgrade.Y = (0x96/2)*RESFACTOR;\n\t\tUpgrade.IsPressed = false;\n\t\tUpgrade.IsToggleType = true;\n\t\tUpgrade.ReflectButtonState = true;\n\t\tUpgrade.Set_Shape(MFCD::Retrieve(\"SELL.SHP\"));\n\n\t\tZoom.IsSticky = true;\n\t\tZoom.ID = BUTTON_ZOOM;\n\t\tZoom.X = (0x24c/2)*RESFACTOR;\n\t\tZoom.Y = (0x96/2)*RESFACTOR;\n\t\tZoom.IsPressed = false;\n\t\tZoom.Set_Shape(MFCD::Retrieve(\"MAP.SHP\"));\n\n\t\tif ((IsRadarActive && Is_Zoomable()) || Session.Type != GAME_NORMAL) {\n\t\t\tZoom.Enable();\n\t\t} else {\n\t\t\tZoom.Disable();\n\t\t}\n\t\tColumn[0].Init_IO(0);\n\t\tColumn[1].Init_IO(1);\n\n\t\t/*\n\t\t** If a game was loaded & the sidebar was enabled, pop it up now\n\t\t*/\n\t\tif (IsSidebarActive) {\n\t\t\tIsSidebarActive = false;\n\t\t\tActivate(1);\n//\t\t\tBackground.Zap();\n//\t\t\tAdd_A_Button(Background);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Init_Theater -- Performs theater-specific initialization                      *\n *                                                                                             *\n * INPUT:   theater  -- The theater that is being initialized. Sometimes this has an effect on *\n *                      the data that is loaded.                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Init_Theater(TheaterType theater)\n{\n\tReload_Sidebar();\n\n\tPowerClass::Init_Theater(theater);\n\n\tColumn[0].Init_Theater(theater);\n\tColumn[1].Init_Theater(theater);\n}\n\n/***********************************************************************************************\n * SidebarClass::Reload_Sidebar -- Loads appropriate sidebar shapes depending on house\t\t\t  *\n *                                                                                             *\n * INPUT:  none \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/18/1996 BWG : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Reload_Sidebar(void)\n{\n\tstatic char * sidebarnames[]={\n\t\t\"SIDE?NA.SHP\",\t\t//NATO\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?US.SHP\",\t\t//USSR\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?US.SHP\",\t\t//UKRAINE\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\n\t\t\"SIDE?NA.SHP\",\t\t//HOUSE_GOOD\n\t\t\"SIDE?US.SHP\"\t\t//HOUSE_BAD\n\t};\n\tint houseloaded = 0;\n\n\tif(PlayerPtr) {\n\t\thouseloaded = PlayerPtr->ActLike;\n\t}\n\n\t/*  Don't have write access to the static char array. ST - 5/20/2019 */\n#if (0)\n\tchar * sidename = sidebarnames[houseloaded];\n\t*(sidename+4) = '1';\n\tSidebarShape = (void*)MFCD::Retrieve(sidename);\n\t*(sidename+4) = '2';\n\tSidebarMiddleShape = (void*)MFCD::Retrieve(sidename);\n\t*(sidename+4) = '3';\n\tSidebarBottomShape = (void*)MFCD::Retrieve(sidename);\n#else\n\tchar sb_name[16];\n\tstrcpy(sb_name, sidebarnames[houseloaded]);\n\tsb_name[4] = '1';\n\tSidebarShape = (void*)MFCD::Retrieve(sb_name);\n\tsb_name[4] = '2';\n\tSidebarMiddleShape = (void*)MFCD::Retrieve(sb_name);\n\tsb_name[4] = '3';\n\tSidebarBottomShape = (void*)MFCD::Retrieve(sb_name);\n\n#endif\n\n\n\n\n\tColumn[0].Reload_LogoShapes();\n\tColumn[1].Reload_LogoShapes();\n}\n\n/***********************************************************************************************\n * SidebarClass::Which_Column -- Determines which column a given type should appear.           *\n *                                                                                             *\n *    Use this function to resolve what column the specified object type should be placed      *\n *    into.                                                                                    *\n *                                                                                             *\n * INPUT:   otype -- Pointer to the object type class of the object in question.               *\n *                                                                                             *\n * OUTPUT:  Returns with the column number that the object should be placed in.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SidebarClass::Which_Column(RTTIType type)\n{\n\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {\n\t\treturn(0);\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                           *\n *                                                                                             *\n *    This routine will link the specified factory to the sidebar strip. A factory must be     *\n *    linked to the sidebar so that as the factory production progresses, the sidebar will     *\n *    show the production progress.                                                            *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to attach.                                          *\n *                                                                                             *\n *          type     -- The object type number.                                                *\n *                                                                                             *\n *          id       -- The object sub-type number.                                            *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached to the sidebar strip?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\tassert((unsigned)type < RTTI_COUNT);\n\tassert(id >= 0);\n\n\treturn(Column[Which_Column(type)].Factory_Link(factory, type, id));\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.        *\n *                                                                                             *\n *    This routine intercepts the Refresh_Cells call in order to see if the sidebar needs      *\n *    to be refreshed as well. If the special code to refresh the sidebar was found, it        *\n *    flags the sidebar to be redrawn and then removes the code from the list.                 *\n *                                                                                             *\n * INPUT:   cell  -- The cell to base the refresh list on.                                     *\n *                                                                                             *\n *          list  -- Pointer to the cell offset list that elaborates all the cells that        *\n *                   need to be flagged for redraw.                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Refresh_Cells(CELL cell, short const * list)\n{\n\tif (*list == REFRESH_SIDEBAR) {\n\t\tIsToRedraw = true;\n\t\tColumn[0].IsToRedraw = true;\n\t\tColumn[1].IsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n\tPowerClass::Refresh_Cells(cell, list);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.                 *\n *                                                                                             *\n *    Use this routine to turn the repair sidebar button on and off. Typically, the button     *\n *    is enabled when the currently selected structure is friendly and damaged.                *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Repair(int control)\n{\n\tbool old = IsRepairActive;\n\n\tif (control == -1) {\n\t\tcontrol = IsRepairActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsRepairActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsRepairActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsRepairActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\n\t\tif (!IsRepairActive) {\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.               *\n *                                                                                             *\n *    Use this routine to turn the upgrade sidebar button on and off. Typically, the button    *\n *    is enabled when the currently selected structure can be upgraded and disabled otherwise. *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Upgrade(int control)\n{\n\tbool old = IsUpgradeActive;\n\tif (control == -1) {\n\t\tcontrol = IsUpgradeActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsUpgradeActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsUpgradeActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsUpgradeActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\t\tif (!IsUpgradeActive) {\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.             *\n *                                                                                             *\n *    Use this routine to turn the demolish/dismantle sidebar button on and off. Typically,    *\n *    the button is enabled when a friendly building is selected and disabled otherwise.       *\n *                                                                                             *\n * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *\n *                      0  -- Turn button off.                                                 *\n *                      1  -- Turn button on.                                                  *\n *                      -1 -- Toggle button state.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the button previously activated?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate_Demolish(int control)\n{\n\tbool old = IsDemolishActive;\n\n\tif (control == -1) {\n\t\tcontrol = IsDemolishActive ? 0 : 1;\n\t}\n\tswitch (control) {\n\t\tcase 1:\n\t\t\tIsDemolishActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsDemolishActive = false;\n\t\t\tbreak;\n\t}\n\tif (old != IsDemolishActive) {\n\t\tFlag_To_Redraw(false);\n\t\tIsToRedraw = true;\n\t\tif (!IsDemolishActive) {\n\t\t\tSet_Default_Mouse(MOUSE_NORMAL, false);\n\t\t}\n\t}\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Add -- Adds a game object to the sidebar list.                                *\n *                                                                                             *\n *    This routine is used to add a game object to the sidebar. Call this routine when a       *\n *    factory type building is created. It handles the case of adding an item that has already *\n *    been added -- it just ignores it.                                                        *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is being added.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added to the sidebar?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *   9/24/2019 3:17PM : Added via capture parameter for new sidebar functionality              *\n *=============================================================================================*/\nbool SidebarClass::Add(RTTIType type, int id, bool via_capture)\n{\n\tassert((unsigned)type < RTTI_COUNT);\n\n\t/*\n\t** Add the sidebar only if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\t\tint column = Which_Column(type);\n\n\t\tif (Column[column].Add(type, id, via_capture)) {\n\t\t\tActivate(1);\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                         *\n *                                                                                             *\n *    This routine is used to scroll the sidebar strip of objects. The strip appears whenever  *\n *    a building is selected that can produce units. If the number of units to produce is      *\n *    greater than what the sidebar can hold, this routine is used to scroll the other object  *\n *    into view so they can be selected.                                                       *\n *                                                                                             *\n * INPUT:   up -- Should the scroll be upwards? Upward scrolling reveals object that are       *\n *                later in the list of objects.                                                *\n *                                                                                             *\n * OUTPUT:  bool; Did scrolling occur?                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Scroll(bool up, int column)\n{\n\tif (column == -1) {\n\t\tbool scr = false;\n\t\tscr |= Column[0].Scroll(up);\n\t\tscr |= Column[1].Scroll(up);\n\t\tif (!scr) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t\tif (scr) {\n\t\t\tIsToRedraw = true;\n\t\t\tFlag_To_Redraw(false);\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\tif (Column[column].Scroll(up)) {\n\t\t// No need to redraw the whole sidebar juts because we scrolled a strip is there? ST - 10/15/96 7:29PM\n\t\t//IsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Draw_It -- Renders the sidebar display.                                       *\n *                                                                                             *\n *    This routine performs the actual drawing of the sidebar display.                         *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; Was the sidebar imagery changed at all?                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *   12/31/1994 JLB : Split rendering off into the sidebar strip class.                        *\n *=============================================================================================*/\nvoid SidebarClass::Draw_It(bool complete)\n{\n\tPowerClass::Draw_It(complete);\n\n\tBStart(BENCH_SIDEBAR);\n\n\tif (IsSidebarActive && (IsToRedraw || complete) && !Debug_Map) {\n\t\tIsToRedraw = false;\n\n\t\tif (LogicPage->Lock()) {\n\t\t\t/*\n\t\t\t**\tDraw the outline box around the sidebar buttons.\n\t\t\t*/\n\t\t\tint shape = complete ? 0 : 1;\n\n\t\t\t/*\n\t\t\t** The sidebar shape is too big in 640x400 so it needs to be drawn in three chunks.\n\t\t\t*/\n\t\t\tCC_Draw_Shape(SidebarShape, 0, SIDE_X * RESFACTOR, 8*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\t\t\tCC_Draw_Shape(SidebarMiddleShape, shape, SIDE_X * RESFACTOR, (8+80)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\t\t\tCC_Draw_Shape(SidebarBottomShape, shape, SIDE_X * RESFACTOR, (8+80+50)*RESFACTOR, WINDOW_MAIN, SHAPE_WIN_REL);\n\n\t\t\tRepair.Draw_Me(true);\n\t\t\tUpgrade.Draw_Me(true);\n\t\t\tZoom.Draw_Me(true);\n\t\t\tLogicPage->Unlock();\n\t\t}\n\t}\n\n\t/*\n\t**\tDraw the side strip elements by calling their respective draw functions.\n\t*/\n\tif (IsSidebarActive) {\n\t\tColumn[0].Draw_It(complete);\n\t\tColumn[1].Draw_It(complete);\n\n\t\tif (complete || IsToRedraw) {\n\t\t\tRepair.Draw_Me(true);\n\t\t\tUpgrade.Draw_Me(true);\n\t\t\tZoom.Draw_Me(true);\n\t\t}\n\t}\n\tIsToRedraw = false;\n\n\tBEnd(BENCH_SIDEBAR);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::AI -- Handles player clicking on sidebar area.                                *\n *                                                                                             *\n *    This routine handles the processing necessary when the player clicks on the sidebar.     *\n *    Typically, this is selection of the item to build.                                       *\n *                                                                                             *\n * INPUT:   input -- Reference to the keyboard input value.                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinates at time of input.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the click handled?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *   11/11/1994 JLB : Processes input directly.                                                *\n *   12/26/1994 JLB : Uses factory manager class for construction handling.                    *\n *   12/31/1994 JLB : Simplified to use the sidebar strip class handlers.                      *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   06/27/1995 JLB : <TAB> key toggles sidebar.                                               *\n *=============================================================================================*/\nvoid SidebarClass::AI(KeyNumType & input, int x, int y)\n{\n\tbool redraw = false;\n\n\t//\n\t// We need to process the sidebar differently in multiplayer. ST - 8/7/2019 10:48AM\n\t//\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\tPowerClass::AI(input, x, y);\n\t\treturn;\n\t}\n\n\t/*\n\t**\tToggle the sidebar in and out with the <TAB> key.\n\t*/\n#ifndef WIN32\n\tif (input == KN_TAB) {\n\t\tActivate(-1);\n\t}\n#else\n\tif (!Debug_Map) {\n\t\tActivate(1);\t// Force the sidebar always on in Win95 mode\n\t}\n#endif\t//WIN32\n\tif (!Debug_Map) {\n\t\tColumn[0].AI(input, x, y);\n\t\tColumn[1].AI(input, x, y);\n\t}\n\n#ifdef NEVER\n\tif (IsSidebarActive && !Debug_Map) {\n\n\t\tif (input == KN_DOWN) {\n\t\t\tint scr = 0;\n\t\t\tscr |= Column[0].Scroll(false);\n\t\t\tscr |= Column[1].Scroll(false);\n\t\t\tif (!scr) {\n\t\t\t\tSound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tredraw |= scr;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t\tif (input == KN_UP) {\n\t\t\tint scr = 0;\n\t\t\tscr |= Column[0].Scroll(true);\n\t\t\tscr |= Column[1].Scroll(true);\n\t\t\tif (!scr) {\n\t\t\t\tSound_Effect(VOC_SCOLD);\n\t\t\t}\n\t\t\tredraw |= scr;\n\t\t\tinput = KN_NONE;\n\t\t}\n\t}\n#endif\n\n\n\tif (IsSidebarActive) {\n\n\t\t/*\n\t\t**\tIf there are any buildings in the payer's inventory, then allow the repair\n\t\t**\toption.\n\t\t*/\n\t\tif (PlayerPtr->BScan) {\n\t\t\tActivate_Repair(true);\n\t\t} else {\n\t\t\tActivate_Repair(false);\n\t\t}\n\n\t\tif (input == (BUTTON_REPAIR|KN_BUTTON)) {\n\t\t\tRepair_Mode_Control(-1);\n\t\t}\n\n\t\tif (input == (BUTTON_ZOOM|KN_BUTTON)) {\n\t\t\tZoom_Mode_Control();\n\t\t}\n\n\t\tif (input == (BUTTON_UPGRADE|KN_BUTTON)) {\n\t\t\tSell_Mode_Control(-1);\n\t\t}\n\n\t\tif (redraw) {\n\t\t\t//IsToRedraw = true;\n\t\t\tColumn[0].Flag_To_Redraw();\n\t\t\tColumn[1].Flag_To_Redraw();\n\n\t\t\tFlag_To_Redraw(false);\n\t\t}\n\t}\n\n\tif ((!IsRepairMode) && Repair.IsOn) {\n\t\tRepair.Turn_Off();\n\t}\n\n\tif ((!IsSellMode) && Upgrade.IsOn) {\n\t\tUpgrade.Turn_Off();\n\t}\n\n\tPowerClass::AI(input, x, y);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.              *\n *                                                                                             *\n *    Occasionally a factory gets destroyed. This routine must be called in such a case        *\n *    because it might be possible that sidebar object need to be removed. This routine will   *\n *    examine all existing objects in the sidebar class and if no possible factory can         *\n *    produce it, then it will be removed.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is exhaustive and thus time consuming. Only call it when really    *\n *             necessary. Such as when a factory is destroyed rather than when a non-factory   *\n *             is destroyed.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Recalc(void)\n{\n\tbool redraw = false;\n\n\t// Done elsewhere for new multiplayer. ST - 8/7/2019 10:49AM\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\treturn;\n\t}\n\n\tredraw |= Column[0].Recalc();\n\tredraw |= Column[1].Recalc();\n\n\tif (redraw) {\n\t\tIsToRedraw = true;\n\t\tFlag_To_Redraw(false);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Activate -- Controls the sidebar activation.                                  *\n *                                                                                             *\n *    Use this routine to turn the sidebar on or off. This routine handles updating the        *\n *    necessary flags.                                                                         *\n *                                                                                             *\n * INPUT:   control  -- Tells what to do with the sidebar according to the following:          *\n *                         0 = Turn sidebar off.                                               *\n *                         1 = Turn sidebar on.                                                *\n *                         -1= Toggle sidebar on or off.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the sidebar already on?                                                  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/09/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Activate(int control)\n{\n\t//\n\t// We don't want the original sidebar to be visible. ST - 1/31/2019 11:28AM\n\t//\n\tif (control < 100) {\n\t\treturn IsSidebarActive;\n\t}\n\n\tbool old = IsSidebarActive;\n\n\tif (Session.Play)\n\t\treturn (old);\n\n\t/*\n\t**\tDetermine the new state of the sidebar.\n\t*/\n\tswitch (control) {\n\t\tcase -1:\n\t\t\tIsSidebarActive = IsSidebarActive == false;\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tIsSidebarActive = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\tcase 0:\n\t\t\tIsSidebarActive = false;\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tOnly if there is a change in the state of the sidebar will anything\n\t**\tbe done to change it.\n\t*/\n\tif (IsSidebarActive != old) {\n\n\t\t/*\n\t\t**\tIf the sidebar is activated but was on the right side of the screen, then\n\t\t**\tactivate it on the left side of the screen.\n\t\t*/\n\t\tif (IsSidebarActive /*&& X*/) {\n\t\t\tSet_View_Dimensions(0, 8 * RESFACTOR, ((320-SIDE_WIDTH)/ICON_PIXEL_W) * RESFACTOR);\n\t\t\tIsToRedraw = true;\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tRepair.Zap();\n\t\t\tAdd_A_Button(Repair);\n\t\t\tUpgrade.Zap();\n\t\t\tAdd_A_Button(Upgrade);\n\t\t\tZoom.Zap();\n\t\t\tAdd_A_Button(Zoom);\n\t\t\tColumn[0].Activate();\n\t\t\tColumn[1].Activate();\n\t\t\tBackground.Zap();\n\t\t\tAdd_A_Button(Background);\n\t\t\tMap.RadarButton.Zap();\n\t\t\tAdd_A_Button(Map.RadarButton);\n\t\t\tMap.PowerButton.Zap();\n\t\t\tAdd_A_Button(Map.PowerButton);\n\t\t} else  {\n\t\t\tHelp_Text(TXT_NONE);\n\t\t\tSet_View_Dimensions(0, 8 * RESFACTOR);\n\t\t\tRemove_A_Button(Repair);\n\t\t\tRemove_A_Button(Upgrade);\n\t\t\tRemove_A_Button(Zoom);\n\t\t\tRemove_A_Button(Background);\n\t\t\tColumn[0].Deactivate();\n\t\t\tColumn[1].Deactivate();\n\t\t\tRemove_A_Button(Map.RadarButton);\n\t\t\tRemove_A_Button(Map.PowerButton);\n\t\t}\n\n\t\t/*\n\t\t**\tSince the sidebar status has changed, update the map so that the graphics\n\t\t**\twill be rendered correctly.\n\t\t*/\n\t\tFlag_To_Redraw(true);\n\t}\n\n\treturn(old);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.       *\n *                                                                                             *\n *    This constructor is used to reset the side strip to default empty state.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::StripClass::StripClass(InitClass const & ) :\n\tX(0),\n\tY(0),\n\tID(0),\n\tIsToRedraw(true),\n\tIsBuilding(false),\n\tIsScrollingDown(false),\n\tIsScrolling(false),\n\tFlasher(-1),\n\tTopIndex(0),\n\tScroller(0),\n\tSlid(0),\n\tBuildableCount(0)\n{\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t\tBuildables[index].BuildableViaCapture = false;\t\t// Added for new sidebar functionality. ST - 9/24/2019 3:10PM \n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side stri *\n *                                                                                             *\n *    Call this routine ONCE at the beginning of the game. It handles retrieving pointers to   *\n *    the shape files it needs for rendering.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::One_Time(int )\n{\n\t/*\n\t** Sidebar is player team specific in Hires\n\t*/\n\tClockShapes = MFCD::Retrieve(\"CLOCK.SHP\");\n\n\tfor (SpecialWeaponType lp = SPC_FIRST; lp < SPC_COUNT; lp++) {\n\t\tchar buffer[_MAX_FNAME];\n\t\tsprintf(buffer, \"%sICON\", SpecialWeaponFile[lp]);\n\n\t\tchar\tfullname[_MAX_FNAME+_MAX_EXT];\n\t\t_makepath(fullname, NULL, NULL, buffer, \".SHP\");\n\t\tSpecialShapes[lp] = MFCD::Retrieve(fullname);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.       *\n *                                                                                             *\n *    This routine will return with a pointer to the cameo data for the special objects that   *\n *    can appear on the sidebar (e.g., nuclear bomb).                                          *\n *                                                                                             *\n * INPUT:   type  -- The special type to fetch the cameo imagery for.                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the cameo imagery for the specified special object.      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : commented                                                                *\n *=============================================================================================*/\nvoid const * SidebarClass::StripClass::Get_Special_Cameo(SpecialWeaponType type)\n{\n\tif ((unsigned)type < SPC_COUNT) {\n\t\treturn(SpecialShapes[type]);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_Clear(void)\n{\n\tIsScrollingDown = false;\n\tIsScrolling = false;\n\tIsBuilding = false;\n\tFlasher = -1;\n\tTopIndex = 0;\n\tSlid = 0;\n\tBuildableCount = 0;\n\n\t/*\n\t** Since we're resetting the strips, clear out all the buildables & factory pointers.\n\t*/\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t\tBuildables[index].BuildableViaCapture = false;\t\t// Added for new sidebar functionality. ST - 9/24/2019 3:10PM \n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_IO -- Initializes the strip's buttons                        *\n *                                                                                             *\n * This routine doesn't actually add any buttons to the list.                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_IO(int id)\n{\n\tID = id;\n\n\tUpButton[ID].IsSticky = true;\n\tUpButton[ID].ID = BUTTON_UP+id;\n\tUpButton[ID].X = X+(UP_X_OFFSET * RESFACTOR);\n\tUpButton[ID].Y = Y+(UP_Y_OFFSET * RESFACTOR);\n\n#if (FRENCH)\n#ifdef WIN32\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPUP.SHP\"));\n#else\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STUP_FIX.SHP\"));\n#endif\n#else\t//FRENCH\n\tUpButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPUP.SHP\"));\n#endif\t//FRENCH\n\n\tDownButton[ID].IsSticky = true;\n\tDownButton[ID].ID = BUTTON_DOWN+id;\n\tDownButton[ID].X = X+(DOWN_X_OFFSET * RESFACTOR);\n\tDownButton[ID].Y = Y+(DOWN_Y_OFFSET * RESFACTOR);\n\n\t/*\n\t** Buttons are in a slightly different position in the new sidebar\n\t*/\n\tUpButton[ID].Y--;\n\tDownButton[ID].Y--;\n\n\tDownButton[ID].Set_Shape(MFCD::Retrieve(\"STRIPDN.SHP\"));\n\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tSelectClass & g = SelectButton[ID][index];\n\t\tg.ID = BUTTON_SELECT;\n\t\tg.X = X;\n\t\tg.Y = Y + ((OBJECT_HEIGHT*index) * RESFACTOR);\n\t\tg.Width = OBJECT_WIDTH * RESFACTOR;\n\t\tg.Height = OBJECT_HEIGHT * RESFACTOR;\n\t\tg.Set_Owner(*this, index);\n\t}\n\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization          *\n *                                                                                             *\n * INPUT:   theater                                                                            *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Init_Theater(TheaterType theater)\n{\n\n\tReload_LogoShapes();\n\n\tif ( (theater != THEATER_NONE) && (theater != ::LastTheater)) {\n\n\t\tstatic TLucentType const ClockCols[1] = {\n\t\t\t{GREEN, BLACK, 100, 0}\n//\t\t\t{GREEN, LTGREY, 180, 0}\n\t\t};\n\n\t\t/*\n\t\t**\tMake sure that remapping doesn't occur on the colors that cycle.\n\t\t*/\n\t\tPaletteClass pal = OriginalPalette;\n\t\tmemset(&pal[CYCLE_COLOR_START*3], 0x3f, CYCLE_COLOR_COUNT*3);\n\t\tBuild_Translucent_Table(pal, &ClockCols[0], 1, (void*)ClockTranslucentTable);\n\n//\t\tMem_Copy(GamePalette, OriginalPalette, 768);\n//\t\tmemset(&GamePalette[CYCLE_COLOR_START*3], 0x3f, CYCLE_COLOR_COUNT*3);\n\n\t\t/*\n\t\t**\tCreate the translucent table used for the sidebar.\n\t\t*/\n//\t\tBuild_Translucent_Table(GamePalette, &ClockCols[0], 1, (void*)ClockTranslucentTable);\n//\t\tGamePalette = OriginalPalette;\n\n\t\tConquer_Build_Fading_Table(GamePalette, &ClockTranslucentTable[256], BLACK, 100);\n\t}\n}\n\nvoid SidebarClass::StripClass::Reload_LogoShapes(void)\n{\n\t/*\n\t** Load hi-res strip art here since it is player side specific\n\t*/\n\tstatic char * stripnames[]={\n\t\t\"stripna.shp\",\t\t//Nato\n\t\t\"stripna.shp\",\n\t\t\"stripus.shp\",\t\t//USSR\n\t\t\"stripna.shp\",\n\t\t\"stripus.shp\",\t\t//UKRAINE\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\n\t\t\"stripna.shp\",\t\t//HOUSE_GOOD\n\t\t\"stripus.shp\",\t\t//HOUSE_BAD\n\t};\n\tint houseloaded = 0;\n\n\t/*\n\t** Sidebar art is dependent on the side of the player\n\t*/\n\n\tif(PlayerPtr) {\n\t\thouseloaded = PlayerPtr->ActLike;\n\t}\n\tLogoShapes = (void*)MFCD::Retrieve(stripnames[houseloaded]);\n}\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.           *\n *                                                                                             *\n *    This routine will add the side strip buttons to the map's input system. This routine     *\n *    should be called once when the sidebar activates.                                        *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Never call this routine a second time without first calling Deactivate().       *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Activate(void)\n{\n\tUpButton[ID].Zap();\n\tMap.Add_A_Button(UpButton[ID]);\n\n\tDownButton[ID].Zap();\n\tMap.Add_A_Button(DownButton[ID]);\n\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tSelectButton[ID][index].Zap();\n\t\tMap.Add_A_Button(SelectButton[ID][index]);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syste *\n *                                                                                             *\n *    Call this routine to remove all the buttons on the side strip from the map's input       *\n *    system.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   Never call this routine unless the Activate() function was previously called.   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Deactivate(void)\n{\n\tMap.Remove_A_Button(UpButton[ID]);\n\tMap.Remove_A_Button(DownButton[ID]);\n\tfor (int index = 0; index < MAX_VISIBLE; index++) {\n\t\tMap.Remove_A_Button(SelectButton[ID][index]);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Add -- Add an object to the side strip.                           *\n *                                                                                             *\n *    Use this routine to add a buildable object to the side strip.                            *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object type that can be built and is to be added to     *\n *                      the side strip.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully added to the side strip? Failure could be the    *\n *                result of running out of room in the side strip array or the object might    *\n *                already be in the list.                                                      *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   9/24/2019 3:17PM : Added via capture parameter for new sidebar functionality              *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Add(RTTIType type, int id, bool via_capture)\n{\n\tif (BuildableCount <= MAX_BUILDABLES) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t\tif (!ScenarioInit && type != RTTI_SPECIAL) {\n\t\t\tSpeak(VOX_NEW_CONSTRUCT);\n\t\t}\n\t\tBuildables[BuildableCount].BuildableType = type;\n\t\tBuildables[BuildableCount].BuildableID = id;\n\t\tBuildables[BuildableCount].BuildableViaCapture = via_capture;\n\t\tBuildableCount++;\n\t\tIsToRedraw = true;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                        *\n *                                                                                             *\n *    Use this routine to flag the side strip to scroll. The direction scrolled is controlled  *\n *    by the parameter. Scrolling is merely initiated by this routine. Subsequent calls to     *\n *    the AI function and the Draw_It function are required to properly give the appearance    *\n *    of scrolling.                                                                            *\n *                                                                                             *\n * INPUT:   bool; Should the side strip scroll UP? If it is to scroll down then pass false.    *\n *                                                                                             *\n * OUTPUT:  bool; Was the side strip started to scroll in the desired direction?               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   07/29/1995 JLB : Simplified scrolling logic.                                              *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Scroll(bool up)\n{\n\tif (up) {\n\t\tif (!TopIndex) return(false);\n\t\tScroller--;\n\t} else {\n\t\tif (TopIndex+MAX_VISIBLE >= BuildableCount) return(false);\n\t\tScroller++;\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.           *\n *                                                                                             *\n *    This utility routine is called when something changes on the sidebar and it must be      *\n *    reflected the next time drawing is performed.                                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Flag_To_Redraw(void)\n{\n\tIsToRedraw = true;\n\t//Map.SidebarClass::IsToRedraw = true;\n\tMap.Flag_To_Redraw(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::AI -- Input and AI processing for the side strip.                 *\n *                                                                                             *\n *    The side strip AI processing is performed by this function. This function not only       *\n *    checks for player input, but also handles any graphic logic updating necessary as a      *\n *    result of flashing or construction animation.                                            *\n *                                                                                             *\n * INPUT:   input -- The player input code.                                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinate to use.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Did the AI detect that it will need a rendering change? If this routine      *\n *                returns true, then the Draw_It function should be called at the              *\n *                earliest opportunity.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nbool SidebarClass::StripClass::AI(KeyNumType & input, int , int )\n{\n\tbool redraw = false;\n\n\t/*\n\t**\tIf this is scroll button for this side strip, then scroll the strip as\n\t**\tindicated.\n\t*/\n\tif (input == (UpButton[ID].ID|KN_BUTTON)) {\t// && !IsScrolling\n\t\tUpButton[ID].IsPressed = false;\n\t\tif (!Scroll(true)) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t}\n\tif (input == (DownButton[ID].ID|KN_BUTTON)) {\t// && !IsScrolling\n\t\tDownButton[ID].IsPressed = false;\n\t\tif (!Scroll(false)) {\n\t\t\tSound_Effect(VOC_SCOLD);\n\t\t}\n\t}\n\n\t/*\n\t**\tReflect the scroll desired direction/value into the scroll\n\t**\tlogic handler. This might result in up or down scrolling.\n\t*/\n\tif (!IsScrolling && Scroller) {\n\t\tif (BuildableCount <= MAX_VISIBLE) {\n\t\t\tScroller = 0;\n\t\t} else {\n\n\t\t\t/*\n\t\t\t**\tTop of list is moving toward lower ordered entries in the object list. It looks like\n\t\t\t**\tthe \"window\" to the object list is moving up even though the actual object images are\n\t\t\t**\tscrolling downward.\n\t\t\t*/\n\t\t\tif (Scroller < 0) {\n\t\t\t\tif (!TopIndex) {\n\t\t\t\t\tScroller = 0;\n\t\t\t\t} else {\n\t\t\t\t\tScroller++;\n\t\t\t\t\tIsScrollingDown = false;\n\t\t\t\t\tIsScrolling = true;\n\t\t\t\t\tTopIndex--;\n\t\t\t\t\tSlid = 0;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tif (TopIndex+MAX_VISIBLE >= BuildableCount) {\n\t\t\t\t\tScroller = 0;\n\t\t\t\t} else {\n\t\t\t\t\tScroller--;\n\t\t\t\t\tSlid = OBJECT_HEIGHT;\n\t\t\t\t\tIsScrollingDown = true;\n\t\t\t\t\tIsScrolling = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tScroll logic is handled here.\n\t*/\n\tif (IsScrolling) {\n\t\tif (IsScrollingDown) {\n\t\t\tSlid -= SCROLL_RATE;\n\t\t\tif (Slid <= 0) {\n\t\t\t\tIsScrolling = false;\n\t\t\t\tSlid = 0;\n\t\t\t\tTopIndex++;\n\t\t\t}\n\t\t} else {\n\t\t\tSlid += SCROLL_RATE;\n\t\t\tif (Slid >= OBJECT_HEIGHT) {\n\t\t\t\tIsScrolling = false;\n\t\t\t\tSlid = 0;\n\t\t\t}\n\t\t}\n\t\tredraw = true;\n\t}\n\n\t/*\n\t**\tHandle any flashing logic. Flashing occurs when the player selects an object\n\t**\tand provides the visual feedback of a recognized and legal selection.\n\t*/\n\tif (Flasher != -1) {\n\t\tif (Graphic_Logic()) {\n\t\t\tredraw = true;\n\t\t\tif (Fetch_Stage() >= 7) {\n\t\t\t\tSet_Rate(0);\n\t\t\t\tSet_Stage(0);\n\t\t\t\tFlasher = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tHandle any building clock animation logic.\n\t*/\n\tif (IsBuilding) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tint factoryid = Buildables[index].Factory;\n\n\t\t\tif (factoryid != -1) {\n\t\t\t\tFactoryClass * factory = Factories.Raw_Ptr(factoryid);\n\n\t\t\t\tif (factory && (factory->Has_Changed() || factory->Is_Blocked())) {\n\t\t\t\t\tredraw = true;\n\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tConstruction has been completed. Announce this fact to the player and\n\t\t\t\t\t\t**\ttry to get the object to automatically leave the factory. Buildings are\n\t\t\t\t\t\t**\tthe main exception to the ability to leave the factory under their own\n\t\t\t\t\t\t**\tpower.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\tif (pending != NULL) {\n\t\t\t\t\t\t\tswitch (pending->What_Am_I()) {\n\t\t\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tif (!factory->Is_Blocked()) {\n\t\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\t\t\tSpeak(VOX_CONSTRUCTION);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tif (!factory->Is_Blocked()) {\n\t\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf any of the logic determined that this side strip needs to be redrawn, then\n\t**\tset the redraw flag for this side strip.\n\t*/\n\tif (redraw) {\n\t\tFlag_To_Redraw();\n\t}\n\treturn(redraw);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Draw_It -- Render the sidebar display.                            *\n *                                                                                             *\n *    Use this routine to render the sidebar display. It checks to see if it needs to be       *\n *    redrawn and only redraw if necessary. If the \"complete\" parameter is true, then it       *\n *    will force redraw the entire strip.                                                      *\n *                                                                                             *\n * INPUT:   complete -- Should the redraw be forced? A force redraw will ignore the redraw     *\n *                      flag.                                                                  *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   08/06/1995 JLB : Handles multi factory tracking in same strip.                            *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::Draw_It(bool complete)\n{\n\tif (IsToRedraw || complete) {\n\t\tIsToRedraw = false;\n\n\t\tif (RunningAsDLL) {\n\t\t\treturn;\n\t\t}\n\n\t\tSidebarRedraws++;\n\n\t\t/*\n\t\t**\tFills the background to the side strip. We shouldnt need to do this if the strip\n\t\t** has a full complement of icons.\n\t\t*/\n\t\t/*\n\t\t** New sidebar needs to be drawn not filled\n\t\t*/\n\t\tif (BuildableCount < MAX_VISIBLE) {\n\t\t\tCC_Draw_Shape(LogoShapes, ID,\tX+(2*RESFACTOR),\tY,\tWINDOW_MAIN, SHAPE_WIN_REL|SHAPE_NORMAL,\t0);\n\t\t}\n\n\t\t/*\n\t\t**\tRedraw the scroll buttons.\n\t\t*/\n\t\tUpButton[ID].Draw_Me(true);\n\t\tDownButton[ID].Draw_Me(true);\n\n\t\t/*\n\t\t**\tLoop through all the buildable objects that are visible in the strip and render\n\t\t**\tthem. Their Y offset may be adjusted if the strip is in the process of scrolling.\n\t\t*/\n\t\tfor (int i = 0; i < MAX_VISIBLE + (IsScrolling ? 1 : 0); i++) {\n\t\t\tbool production;\n\t\t\tbool completed;\n\t\t\tint  stage;\n\t\t\tbool darken = false;\n\t\t\tvoid const * shapefile = 0;\n\t\t\tint shapenum = 0;\n\t\t\tvoid const * remapper = 0;\n\t\t\tFactoryClass * factory = 0;\n\t\t\tint index = i+TopIndex;\n\t\t\tint x = X;\n\t\t\tint y = Y + (i*OBJECT_HEIGHT * RESFACTOR);\n\n\t\t\t/*\n\t\t\t**\tIf the strip is scrolling, then the offset is adjusted accordingly.\n\t\t\t*/\n\t\t\tif (IsScrolling) {\n\t\t\t\ty -= (OBJECT_HEIGHT - Slid)  * RESFACTOR;\n//\t\t\t\ty -= OBJECT_HEIGHT - Slid;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tFetch the shape number for the object type located at this current working\n\t\t\t**\tslot. This shape pointer is used to draw the underlying graphic there.\n\t\t\t*/\n\t\t\tif (index < BuildableCount) {\n\t\t\t\tObjectTypeClass const * obj = NULL;\n\t\t\t\tSpecialWeaponType spc = SPC_NONE;\n\n\t\t\t\tif (Buildables[index].BuildableType != RTTI_SPECIAL) {\n\n\t\t\t\t\tobj = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\t\t\t\tif (obj != NULL) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFetch the remap table that is appropriate for this object\n\t\t\t\t\t\t**\ttype.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tremapper = PlayerPtr->Remap_Table(false, ((TechnoTypeClass const *)obj)->Remap);\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf there is already a factory producing this kind of object, then all\n\t\t\t\t\t\t**\tobjects of this type are displays in a disabled state.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbool isbusy = (PlayerPtr->Fetch_Factory(Buildables[index].BuildableType) != NULL);\n\t\t\t\t\t\tif (!isbusy && PlayerPtr->Is_Hack_Prevented(Buildables[index].BuildableType, Buildables[index].BuildableID)) {\n\t\t\t\t\t\t\tisbusy = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tInfantry don't get remapped in the sidebar (special case).\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (Buildables[index].BuildableType == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tremapper = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshapefile = obj->Get_Cameo_Data();\n\t\t\t\t\t\tshapenum  = 0;\n\t\t\t\t\t\tif (Buildables[index].Factory != -1) {\n\t\t\t\t\t\t\tfactory \t\t= Factories.Raw_Ptr(Buildables[index].Factory);\n\t\t\t\t\t\t\tproduction\t= true;\n\t\t\t\t\t\t\tcompleted\t= factory->Has_Completed();\n\t\t\t\t\t\t\tstage\t\t\t= factory->Completion();\n\t\t\t\t\t\t\tdarken\t\t= false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tproduction  = false;\n//\t\t\t\t\t\t\tdarken      = IsBuilding;\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t**\tDarken the imagery if a factory of a matching type is\n\t\t\t\t\t\t\t**\talready busy.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tdarken = isbusy;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdarken = PlayerPtr->Is_Hack_Prevented(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\t\t\t\t}\n\n\t\t\t\t} else  {\n\n\t\t\t\t\tspc = SpecialWeaponType(Buildables[index].BuildableID);\n\t\t\t\t\tshapefile = Get_Special_Cameo(spc);\n\t\t\t\t\tshapenum = 0;\n\n\t\t\t\t\tproduction = true;\n\t\t\t\t\tcompleted = PlayerPtr->SuperWeapon[spc].Is_Ready();\n\t\t\t\t\tstage = PlayerPtr->SuperWeapon[spc].Anim_Stage();\n\t\t\t\t\tdarken = false;\n\t\t\t\t}\n\n\t\t\t\tif (obj != NULL || spc != SPC_NONE) {\n\t\t\t\t\t/*\n\t\t\t\t\t** If this item is flashing then take care of it.\n\t\t\t\t\t**\n\t\t\t\t\t*/\n\t\t\t\t\tif (Flasher == index && (Fetch_Stage() & 0x01)) {\n\t\t\t\t\t\tremapper = Map.FadingLight;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tshapefile\t= LogoShapes;\n\t\t\t\t\tif (!darken) {\n\t\t\t\t\t\tshapenum\t\t= SB_BLANK;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tshapefile\t= LogoShapes;\n\t\t\t\tshapenum\t\t= SB_BLANK;\n\t\t\t\tproduction\t= false;\n\t\t\t}\n\n\t\t\tremapper = 0;\n\t\t\t/*\n\t\t\t**\tNow that the shape of the object at the current working slot has been found,\n\t\t\t**\tdraw it and any graphic overlays as necessary.\n\t\t\t**\n\t\t\t** Don't draw blank shapes over the new 640x400 sidebar art - ST 5/1/96 6:01PM\n\t\t\t*/\n\t\t\tif (shapenum != SB_BLANK || shapefile != LogoShapes) {\n\t\t\t\tCC_Draw_Shape(shapefile, shapenum,\n\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL| (remapper ? SHAPE_FADING : SHAPE_NORMAL),\n\t\t\t\t\tremapper);\n\n\t\t\t\t/*\n\t\t\t\t**\tDarken this object because it cannot be produced or is otherwise\n\t\t\t\t**\tunavailable.\n\t\t\t\t*/\n\t\t\t\tif (darken) {\n\t\t\t\t\tCC_Draw_Shape(ClockShapes, 0,\n\t\t\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t\tNULL, ClockTranslucentTable);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the overlapping clock shape if this is object is being constructed.\n\t\t\t**\tIf the object is completed, then display \"Ready\" with no clock shape.\n\t\t\t*/\n\t\t\tif (production) {\n\t\t\t\tif (completed) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay text showing that the object is ready to place.\n\t\t\t\t\t*/\n\t\t\t\t\tCC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_READY,\n\t\t\t\t\t(x-(WindowList[WINDOW_SIDEBAR][WINDOWX]))+(LEFT_EDGE_OFFSET+15) * RESFACTOR,\n\t\t\t\t\t(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+(4 * RESFACTOR),\n\t\t\t\t\tWINDOW_SIDEBAR, SHAPE_CENTER);\n\t\t\t\t} else {\n\n\t\t\t\t\tCC_Draw_Shape(ClockShapes, stage+1,\n\t\t\t\t\t\t\tx-(WindowList[WINDOW_SIDEBAR][WINDOWX])+(LEFT_EDGE_OFFSET * RESFACTOR),\n\t\t\t\t\t\t\ty-WindowList[WINDOW_SIDEBAR][WINDOWY],\n\t\t\t\t\t\t\tWINDOW_SIDEBAR,\n\t\t\t\t\t\t\tSHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,\n\t\t\t\t\t\t\tNULL, ClockTranslucentTable);\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tDisplay text showing that the construction is temporarily on hold.\n\t\t\t\t\t*/\n\t\t\t\t\tif (factory && !factory->Is_Building()) {\n\t\t\t\t\t\tCC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_HOLDING,\n\t\t\t\t\t\t(x-(WindowList[WINDOW_SIDEBAR][WINDOWX])) + ((LEFT_EDGE_OFFSET+15) * RESFACTOR),\n\t\t\t\t\t\t(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+(4 * RESFACTOR),\n\t\t\t\t\t\tWINDOW_SIDEBAR, SHAPE_CENTER);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tLastSlid = Slid;\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.        *\n *                                                                                             *\n *    This routine will revalidate all the buildable objects in the sidebar. This routine      *\n *    comes in handy when a factory has been destroyed, and the sidebar needs to reflect any   *\n *    change that this requires. It checks every object to see if there is a factory available *\n *    that could produce it. If none can be found, then the object is removed from the         *\n *    sidebar.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; The sidebar has changed as a result of this call?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Doesn't collapse sidebar when buildables removed.                        *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Recalc(void)\n{\n\tint ok;\n\n\tif (Debug_Map || !BuildableCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSweep through all objects listed in the sidebar. If any of those object can\n\t**\tnot be created -- even in theory -- then they must be removed form the sidebar and\n\t**\tany current production must be abandoned.\n\t*/\n\tbool redraw = false;\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\tif (tech != NULL) {\n\t\t\tok = tech->Who_Can_Build_Me(true, false, PlayerPtr->Class->House) != NULL;\n\t\t} else {\n\t\t\tif ((unsigned)Buildables[index].BuildableID < SPC_COUNT) {\n\t\t\t\tok = PlayerPtr->SuperWeapon[Buildables[index].BuildableID].Is_Present();\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t}\n\n\t\tif (!ok) {\n\n\t\t\t/*\n\t\t\t**\tRemoves this entry from the list.\n\t\t\t*/\n\t\t\tif (BuildableCount > 1 && index < BuildableCount-1) {\n\t\t\t\tmemcpy(&Buildables[index], &Buildables[index+1], sizeof(Buildables[0])*((BuildableCount-index)-1));\n\t\t\t}\n\t\t\tTopIndex = 0;\n\t\t\tIsToRedraw = true;\n\t\t\tredraw = true;\n\t\t\tBuildableCount--;\n\t\t\tindex--;\n\t\t}\n\t}\n\n#ifdef NEVER\n\t/*\n\t**\tIf there are no more buildable objects to display, make the sidebar go away.\n\t*/\n\tif (!BuildableCount) {\n\t\tMap.SidebarClass::Activate(0);\n\t}\n#endif\n\treturn(redraw);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                  *\n *                                                                                             *\n *    This is the default constructor for the button that controls the buildable cameos on     *\n *    the sidebar strip.                                                                       *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The coordinates are set to zero by this routine. They must be set to the        *\n *             correct values before this button will function.                                *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarClass::StripClass::SelectClass::SelectClass(void) :\n\tControlClass(0, 0, 0, (OBJECT_WIDTH-1) * RESFACTOR, OBJECT_HEIGHT * RESFACTOR, LEFTPRESS|RIGHTPRESS|LEFTUP),\n\tStrip(0),\n\tIndex(0)\n{\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select but *\n *                                                                                             *\n *    Use this routine to set custom buildable vars for this particular select button. It      *\n *    uses this information to properly know what buildable object to start or stop production *\n *    on.                                                                                      *\n *                                                                                             *\n * INPUT:   strip    -- Reference to the strip that owns this buildable button.                *\n *                                                                                             *\n *          index    -- The index (0 .. MAX_VISIBLE-1) of this button. This is used to let     *\n *                      the owning strip know what index this button refers to.                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::StripClass::SelectClass::Set_Owner(StripClass & strip, int index)\n{\n\tStrip = &strip;\n\tIndex = index;\n\tX = strip.X;\n\tY = strip.Y + ((index * OBJECT_HEIGHT) * RESFACTOR);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selected *\n *                                                                                             *\n *    This function is called when the buildable icon (cameo) is clicked on. It handles        *\n *    starting and stopping production as indicated.                                           *\n *                                                                                             *\n * INPUT:   flags -- The input event that triggered the call.                                  *\n *                                                                                             *\n *          key   -- The keyboard value at the time of the input.                              *\n *                                                                                             *\n * OUTPUT:  Returns with whether the input list should be scanned further.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   10/09/1996 JLB : Sonar pulse converted to regular event type.                             *\n *=============================================================================================*/\nint SidebarClass::StripClass::SelectClass::Action(unsigned flags, KeyNumType & key)\n{\n\tint index = Strip->TopIndex + Index;\n\tRTTIType otype = Strip->Buildables[index].BuildableType;\n\tint oid = Strip->Buildables[index].BuildableID;\n\tint fnumber = Strip->Buildables[index].Factory;\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tObjectTypeClass const * choice = NULL;\n\tSpecialWeaponType spc = SPC_NONE;\n\n\t/*\n\t**\tDetermine the factory number that would apply to objects of the type\n\t**\tthe mouse is currently addressing. This doesn't mean that the factory number\n\t**\tfetched is actually producing the indicated object, merely that that particular\n\t**\tkind of factory is specified by the \"genfactory\" value. This can be used to see\n\t**\tif the factory type is currently busy or not.\n\t*/\n\tFactoryClass * factory = PlayerPtr->Fetch_Factory(otype);\n\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\n\tif (index < Strip->BuildableCount) {\n\t\tif (otype != RTTI_SPECIAL) {\n\t\t\tchoice  = Fetch_Techno_Type(otype, oid);\n\t\t} else {\n\t\t\tspc = SpecialWeaponType(oid);\n\t\t}\n\n\t\tif (fnumber != -1) {\n\t\t\tfactory = Factories.Raw_Ptr(fnumber);\n\t\t}\n\n  \t} else {\n  \t\tMap.Help_Text(TXT_NONE);\n  \t}\n\n\tif (spc != SPC_NONE) {\n\n\t\t/*\n\t\t**\tDisplay the help text if the mouse is over the button.\n\t\t*/\n\t\tif (flags & LEFTUP) {\n\t\t\tMap.Help_Text(SpecialWeaponHelp[spc], X, Y, scheme->Color, true);\n\t\t\tflags &= ~LEFTUP;\n\t\t}\n\n\t\t/*\n\t\t**\tA right mouse button signals \"cancel\".  If we are in targeting\n\t\t** mode then we don't want to be any more.\n\t\t*/\n\t\tif (flags & RIGHTPRESS) {\n\t\t\tMap.IsTargettingMode = SPC_NONE;\n\t\t}\n\t\t/*\n\t\t**\tA left mouse press signal \"activate\".  If our weapon type is\n\t\t** available then we should activate it.\n\t\t*/\n\t\tif (flags & LEFTPRESS) {\n\n\t\t\tif ((unsigned)spc < SPC_COUNT) {\n\t\t\t\tif (PlayerPtr->SuperWeapon[spc].Is_Ready()) {\n\t\t\t\t\tif (spc != SPC_SONAR_PULSE) {\n\t\t\t\t\t\tMap.IsTargettingMode = spc;\n\t\t\t\t\t\tUnselect_All();\n\t\t\t\t\t\tSpeak(VOX_SELECT_TARGET);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_SONAR_PULSE, 0));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tPlayerPtr->SuperWeapon[spc].Impatient_Click();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tif (choice != NULL) {\n\n\t\t\t/*\n\t\t\t**\tDisplay the help text if the mouse is over the button.\n\t\t\t*/\n\t\t\tif (flags & LEFTUP) {\n\t\t\t\tMap.Help_Text(choice->Full_Name(), X, Y, scheme->Color, true);\n\t\t\t\tMap.Set_Cost(choice->Cost_Of() * PlayerPtr->CostBias);\n\t\t\t\tflags &= ~LEFTUP;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tA right mouse button signals \"cancel\".\n\t\t\t*/\n\t\t\tif (flags & RIGHTPRESS) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf production is in progress, put it on hold. If production is already\n\t\t\t\t**\ton hold, then abandon it. Money will be refunded, the factory\n\t\t\t\t**\tmanager deleted, and the object under construction is returned to\n\t\t\t\t**\tthe free pool.\n\t\t\t\t*/\n\t\t\t\tif (factory != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tCancels placement mode if the sidebar factory is abandoned or\n\t\t\t\t\t**\tsuspended.\n\t\t\t\t\t*/\n\t\t\t\t\tif (Map.PendingObjectPtr && Map.PendingObjectPtr->Is_Techno()) {\n\t\t\t\t\t\tMap.PendingObjectPtr = 0;\n\t\t\t\t\t\tMap.PendingObject = 0;\n\t\t\t\t\t\tMap.PendingHouse = HOUSE_NONE;\n\t\t\t\t\t\tMap.Set_Cursor_Shape(0);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!factory->Is_Building()) {\n\t\t\t\t\t\tSpeak(VOX_CANCELED);\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, otype, oid));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSpeak(VOX_SUSPENDED);\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::SUSPEND, otype, oid));\n\t\t\t\t\t\tMap.Column[0].IsToRedraw = true;\n\t\t\t\t\t\tMap.Column[1].IsToRedraw = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (flags & LEFTPRESS) {\n\n\t\t\t\t/*\n\t\t\t\t**\tIf there is already a factory attached to this strip but the player didn't click\n\t\t\t\t**\ton the icon that has the attached factory, then say that the factory is busy and\n\t\t\t\t**\tignore the click.\n\t\t\t\t*/\n\t\t\t\tif (fnumber == -1 && factory != NULL) {\n\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\tControlClass::Action(flags, key);\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\n\t\t\t\tif (factory != NULL) {\n\n\t\t\t\t\t/*\n\t\t\t\t\t**\tIf this object is currently being built, then give a scold sound and text and then\n\t\t\t\t\t**\tbail.\n\t\t\t\t\t*/\n\t\t\t\t\tif (factory->Is_Building()) {\n\t\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf production has completed, then attempt to have the object exit\n\t\t\t\t\t\t**\tthe factory or go into placement mode.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\t\tif (!pending && factory->Get_Special_Item()) {\n\t\t\t\t\t\t\t\tMap.IsTargettingMode = SPC_ANY;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tBuildingClass * builder = pending->Who_Can_Build_Me(false, false);\n\t\t\t\t\t\t\t\tif (!builder) {\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::ABANDON, otype, oid));\n\t\t\t\t\t\t\t\t\tSpeak(VOX_NO_FACTORY);\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tIf the completed object is a building, then change the\n\t\t\t\t\t\t\t\t\t**\tgame state into building placement mode. This fact is\n\t\t\t\t\t\t\t\t\t**\tnot transmitted to any linked computers until the moment\n\t\t\t\t\t\t\t\t\t**\tthe building is actually placed down.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (pending->What_Am_I() == RTTI_BUILDING) {\n\t\t\t\t\t\t\t\t \t\tPlayerPtr->Manual_Place(builder, (BuildingClass *)pending);\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t**\tFor objects that can leave the factory under their own\n\t\t\t\t\t\t\t\t\t\t**\tpower, queue this event and process through normal house\n\t\t\t\t\t\t\t\t\t\t**\tproduction channels.\n\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, otype, -1));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tif (PlayerPtr->Is_Hack_Prevented(otype, oid)) {\n\t\t\t\t\t\t\t\t// Eva scolds the player here.\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t**\tThe factory must have been in a suspended state. Resume construction\n\t\t\t\t\t\t\t\t**\tnormally.\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tif (otype == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\t\t\tSpeak(VOX_TRAINING);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tSpeak(VOX_BUILDING);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (PlayerPtr->Is_Hack_Prevented(otype, oid)) {\n\t\t\t\t\t\t// Eva scolds the player here.\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tIf this side strip is already busy with production, then ignore the\n\t\t\t\t\t\t**\tinput and announce this fact.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif (otype == RTTI_INFANTRYTYPE) {\n\t\t\t\t\t\t\tSpeak(VOX_TRAINING);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSpeak(VOX_BUILDING);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflags = 0;\n\t\t}\n\t}\n\n\tControlClass::Action(flags, key);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the si *\n *                                                                                             *\n *    This routine is called whenever the mouse is over the sidebar. It makes sure that the    *\n *    mouse is always the normal shape while over the sidebar.                                 *\n *                                                                                             *\n * INPUT:   flags -- The event flags that resulted in this routine being called.               *\n *                                                                                             *\n *          key   -- Reference the keyboard code that may be present.                          *\n *                                                                                             *\n * OUTPUT:  Returns that no further keyboard processing is necessary.                          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SidebarClass::SBGadgetClass::Action(unsigned , KeyNumType & )\n{\n\tMap.Help_Text(TXT_NONE);\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL, false);\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.              *\n *                                                                                             *\n *    This routine will link the specified factory to this sidebar strip. The exact button to  *\n *    link to is determined from the object type and id specified. A linked button is one that *\n *    will show appropriate construction animation (clock shape) that matches the state of     *\n *    the factory.                                                                             *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to link to the sidebar.                             *\n *                                                                                             *\n *          type     -- The object type that this factory refers to.                           *\n *                                                                                             *\n *          id       -- The object sub-type that this factory refers to.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached? Failure would indicate that there is no     *\n *          object of the specified type and sub-type in the sidebar list.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\tBuildables[index].Factory = factory;\n\t\t\tIsBuilding = true;\n\t\t\t/*\n\t\t\t** Flag that all the icons on this strip need to be redrawn\n\t\t\t*/\n\t\t\tFlag_To_Redraw();\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Abandon_Production -- Stops production of the object specified.               *\n *                                                                                             *\n *    This routine is used to abandon production of the object specified. The factory will     *\n *    be completely disabled by this call.                                                     *\n *                                                                                             *\n * INPUT:   type     -- The object type that is to be abandoned. The sub-type is not needed    *\n *                      since it is presumed there can be only one type in production at any   *\n *                      one time.                                                              *\n *                                                                                             *\n *          factory  -- The factory number that is doing the production.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully abandoned?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarClass::Abandon_Production(RTTIType type, int factory)\n{\n\treturn(Column[Which_Column(type)].Abandon_Production(factory));\n}\n\n\n/***********************************************************************************************\n * SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.     *\n *                                                                                             *\n *    Production of the object associated with this sidebar is abandoned when this routine is  *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   factory  -- The factory index that is to be suspended.                             *\n *                                                                                             *\n * OUTPUT:  Was the production abandonment successful?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : More intelligent abandon logic for multiple factories.                   *\n *=============================================================================================*/\nbool SidebarClass::StripClass::Abandon_Production(int factory)\n{\n\tbool noprod = true;\n\tbool abandon = false;\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].Factory == factory) {\n\t\t\tFactories.Raw_Ptr(factory)->Abandon();\n\t\t\tBuildables[index].Factory = -1;\n\t\t\tabandon = true;\n\t\t} else {\n\t\t\tif (Buildables[index].Factory != -1) {\n\t\t\t\tnoprod = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there was a change to the strip, then flag the strip to be redrawn.\n\t*/\n\tif (abandon) {\n\t\tFlag_To_Redraw();\n\t}\n\n\t/*\n\t**\tIf there is no production whatsoever on this strip, then flag it so.\n\t*/\n\tif (noprod) {\n\t\tIsBuilding = false;\n\t}\n\treturn(abandon);\n}\n\n\n/***********************************************************************************************\n * SidebarClass::Zoom_Mode_Control -- Handles the zoom mode toggle operation.                  *\n *                                                                                             *\n *    This is the function that is called when the map button is pressed. It will toggle       *\n *    between the different modes that the radar map can assume.                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/31/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarClass::Zoom_Mode_Control(void)\n{\n#ifdef WIN32\n\t/*\n\t** If radar is active, cycle as follows:\n\t** Zoomed => not zoomed\n\t** not zoomed => player status (multiplayer only)\n\t** player status => radar spying readout\n\t** radar spying readout => zoomed\n\t*/\n\tif (IsRadarActive) {\n\t\tif (Is_Zoomed() || Session.Type==GAME_NORMAL) {\n\t\t\tif (Is_Zoomed() || !Spy_Next_House()) {\n\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Spying_On_House() && !Is_Player_Names()) {\n\t\t\t\tPlayer_Names(1);\n\t\t\t} else {\n\t\t\t\tPlayer_Names(0);\n\t\t\t\tif (!Spy_Next_House()) {\n\t\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (Session.Type!=GAME_NORMAL) {\n\t\t\tPlayer_Names(Is_Player_Names()==0);\n\t\t}\n\t}\n#else\n\t/*\n\t** If radar is active, cycle as follows:\n\t** not zoomed => player status (multiplayer only)\n\t** player status => radar spying readout\n\t** radar spying readout => not zoomed\n\t*/\n\tif (IsRadarActive) {\n\t\tif (Session.Type==GAME_NORMAL) {\n\t\t\tif (!Spy_Next_House()) {\n\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t}\n\t\t} else {\n\t\t\tif (!Spying_On_House() && !Is_Player_Names()) {\n\t\t\t\tPlayer_Names(1);\n\t\t\t} else {\n\t\t\t\tPlayer_Names(0);\n\t\t\t\tif (!Spy_Next_House()) {\n\t\t\t\t\tZoom_Mode(Coord_Cell(TacticalCoord));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (Session.Type!=GAME_NORMAL) {\n\t\t\tPlayer_Names(Is_Player_Names()==0);\n\t\t}\n\t}\n#endif\n}"
  },
  {
    "path": "REDALERT/SIDEBAR.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SIDEBAR.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBAR.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 20, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 20, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SIDEBAR_H\n#define SIDEBAR_H\n\n#include\t\"function.h\"\n#include\t\"power.h\"\n#include\t\"factory.h\"\n\nclass InitClass {};\n\nclass SidebarClass: public PowerClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThese constants are used to control the sidebar rendering. They are instantiated\n\t\t**\tas enumerations since C++ cannot use \"const\" in this context.\n\t\t*/\n\t\tenum SideBarClassEnums {\n\t\t\tBUTTON_ACTIVATOR=100,\t\t\t// Button ID for the activator.\n\t\t\tSIDE_X=320-80,\t\t\t\t\t// The X position of sidebar upper left corner.\n\t\t\tSIDE_Y=7+70,\t// The Y position of sidebar upper left corner.\n\t\t\tSIDE_WIDTH=SIDEBAR_WID,\t\t\t// Width of the entire sidebar (in pixels).\n\t\t\tSIDE_HEIGHT=200-(7+70),\t\t\t// Height of the entire sidebar (in pixels).\n\t\t\tTOP_HEIGHT=13,\t\t\t\t\t\t// Height of top section (with repair/sell buttons).\n\t\t\tCOLUMN_ONE_X=(320-80)+8,\t\t\t// Sidestrip upper left coordinates...\n\t\t\tCOLUMN_ONE_Y=int(SIDE_Y)+int(TOP_HEIGHT),\n\t\t\tCOLUMN_TWO_X=(320-80)+8+((80-16)/2)+3,\n\t\t\tCOLUMN_TWO_Y=7+70+13,\n\n//BGA: changes to all buttons\n#ifdef GERMAN\n\t\t\tBUTTON_ONE_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=27,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=26,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=SIDE_X+24,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=SIDE_X+53,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n#ifdef FRENCH\n\t\t\tBUTTON_ONE_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=27,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=26,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=SIDE_X+24,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=SIDE_X+53,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n#ifdef ENGLISH\n\t\t\tBUTTON_ONE_WIDTH=32,\t\t\t\t// Button width.\n\t\t\tBUTTON_TWO_WIDTH=20,\t\t\t\t// Button width.\n\t\t\tBUTTON_THREE_WIDTH=20,\t\t\t// Button width.\n\t\t\tBUTTON_HEIGHT=9,\t\t\t\t\t// Button height.\n\t\t\tBUTTON_ONE_X=(int)SIDE_X+2,\t\t\t// Left button X coordinate.\n\t\t\tBUTTON_ONE_Y=(int)SIDE_Y+2,\t\t\t// Left button Y coordinate.\n\t\t\tBUTTON_TWO_X=(int)SIDE_X+36,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_TWO_Y=(int)SIDE_Y+2,\t\t\t// Right button Y coordinate.\n\t\t\tBUTTON_THREE_X=(int)SIDE_X+58,\t\t\t// Right button X coordinate.\n\t\t\tBUTTON_THREE_Y=(int)SIDE_Y+2,\t\t\t// Right button Y coordinate.\n#endif\n\n\t\t\tCOLUMNS=2\t\t\t\t\t\t\t// Number of side strips on sidebar.\n\t\t};\n\n\t\tstatic void * SidebarShape;\n\t\tstatic void * SidebarMiddleShape;\t//Only used in Win95 version\n\t\tstatic void * SidebarBottomShape;\t//Only used in Win95 version\n\n\t\tSidebarClass(void);\n\t\tSidebarClass(NoInitClass const & x);\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvirtual void Init_Clear(void);\t\t\t\t\t\t// Clears all to known state\n\t\tvirtual void Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\t\tvirtual void Init_Theater(TheaterType theater);\t// Theater-specific inits\n\t\tvoid Reload_Sidebar(void);\t\t\t\t\t\t\t\t// Loads house-specific sidebar art\n\n\t\tvirtual void AI(KeyNumType & input, int x, int y);\n\t\tvirtual void Draw_It(bool complete);\n\t\tvirtual void Refresh_Cells(CELL cell, short const *list);\n\n\t\tvoid Zoom_Mode_Control(void);\n\t\tbool Abandon_Production(RTTIType type, int factory);\n\t\tbool Activate(int control);\n\t\tbool Add(RTTIType type, int ID, bool via_capture = false);\t\t// Added via_capture for new sidebar functionality. ST - 9/24/2019 3:15PM  );\n\t\tbool Sidebar_Click(KeyNumType & input, int x, int y);\n\t\tvoid Recalc(void);\n\t\tbool Factory_Link(int factory, RTTIType type, int id);\n\n\t\t/*\n\t\t**\tEach side strip is managed by this class. It handles all strip specific\n\t\t**\tactions.\n\t\t*/\n\t\tclass StripClass : public StageClass\n\t\t{\n\t\t\tclass SelectClass : public ControlClass\n\t\t\t{\n\t\t\t\tpublic:\n\t\t\t\t\tSelectClass(void);\n\t\t\t\t\tSelectClass(NoInitClass const & x) : ControlClass(x) {};\n\n\t\t\t\t\tvoid Set_Owner(StripClass & strip, int index);\n\n\t\t\t\t\tStripClass * Strip;\n\t\t\t\t\tint Index;\n\n\t\t\t\tprotected:\n\t\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t\t};\n\n\t\t\tpublic:\n\t\t\t\tStripClass(void) {}\n\t\t\t\tStripClass(InitClass const &);\n\t\t\t\tStripClass(NoInitClass const & ) {};\n\n\t\t\t\tbool Add(RTTIType type, int ID, bool via_capture);\t\t// Added via_capture for new sidebar functionality. ST - 9/24/2019 3:15PM  );\n\t\t\t\tbool Abandon_Production(int factory);\n\t\t\t\tbool Scroll(bool up);\n\t\t\t\tbool AI(KeyNumType & input, int x, int y);\n\t\t\t\tvoid Draw_It(bool complete);\n\t\t\t\tvoid One_Time(int id);\n\t\t\t\tvoid Init_Clear(void);\n\t\t\t\tvoid Init_IO(int id);\n\t\t\t\tvoid Init_Theater(TheaterType theater);\n\t\t\t\tvoid Reload_LogoShapes(void);\n\t\t\t\tbool Recalc(void);\n\t\t\t\tvoid Activate(void);\n\t\t\t\tvoid Deactivate(void);\n\t\t\t\tvoid Flag_To_Redraw(void);\n\t\t\t\tbool Factory_Link(int factory, RTTIType type, int id);\n\t\t\t\tvoid const * Get_Special_Cameo(SpecialWeaponType type);\n\n\t\t\t\t/*\n\t\t\t\t**\tFile I/O.\n\t\t\t\t*/\n\t\t\t\tbool Load(Straw & file);\n\t\t\t\tbool Save(Pipe & file) const;\n\n\t\t\t\t/*\n\t\t\t\t**\tWorking numbers used when rendering and processing the side strip.\n\t\t\t\t*/\n\t\t\t\tenum SideBarGeneralEnums {\n\t\t\t\t\tBUTTON_UP=200,\n\t\t\t\t\tBUTTON_DOWN=210,\n\t\t\t\t\tBUTTON_SELECT=220,\n\t\t\t\t\tMAX_BUILDABLES=75,\t\t\t// Maximum number of object types in sidebar.\n\t\t\t\t\tOBJECT_HEIGHT=24,\t\t\t\t// Pixel height of each buildable object.\n\t\t\t\t\tOBJECT_WIDTH=32,\t\t\t\t// Pixel width of each buildable object.\n\t\t\t\t\tSTRIP_WIDTH=35,\t\t\t\t// Width of strip (not counting border lines).\n\t\t\t\t\tMAX_VISIBLE=4,\t\t\t\t\t// Number of object slots visible at any one time.\n#ifdef WIN32\n\t\t\t\t\tSCROLL_RATE=12,\t\t\t\t// The pixel jump while scrolling (larger is faster).\n#else\n\t\t\t\t\tSCROLL_RATE=8,\t\t\t\t\t// The pixel jump while scrolling (larger is faster).\n#endif\n\t\t\t\t\tUP_X_OFFSET=2,\t\t\t\t\t// Scroll up arrow coordinates.\n#ifdef WIN32\n\t\t\t\t\tUP_Y_OFFSET=int(MAX_VISIBLE)*int(OBJECT_HEIGHT)+1,\n#else\n\t\t\t\t\tUP_Y_OFFSET=int(MAX_VISIBLE)*int(OBJECT_HEIGHT)+2,\n#endif\n\t\t\t\t\tDOWN_X_OFFSET=18,\t\t\t\t// Scroll down arrow coordinates.\n\t\t\t\t\tDOWN_Y_OFFSET=UP_Y_OFFSET,//BGint(MAX_VISIBLE)*int(OBJECT_HEIGHT)+1,\n\t\t\t\t\tSBUTTON_WIDTH=16,\t\t\t\t// Width of the mini-scroll button.\n\t\t\t\t\tSBUTTON_HEIGHT=12,\t\t\t\t// Height of the mini-scroll button.\n\t\t\t\t\tLEFT_EDGE_OFFSET=2,\t\t\t// Offset from left edge for building shapes.\n\t\t\t\t\tTEXT_X_OFFSET=18,\t\t\t\t// X offset to print \"ready\" text.\n\t\t\t\t\tTEXT_Y_OFFSET=15,\t\t\t\t// Y offset to print \"ready\" text.\n\t\t\t\t\tTEXT_COLOR=255\t\t\t\t\t// Color to use for the \"Ready\" text.\n\t\t\t\t};\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the coordinate of the upper left corner that this side strip\n\t\t\t\t**\tuses for rendering.\n\t\t\t\t*/\n\t\t\t\tint X,Y;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is a unique identifier for the sidebar strip. Using this identifier,\n\t\t\t\t**\tit is possible to differentiate the button messages that arrive from the\n\t\t\t\t**\tcommon input button list.  It >MUST< be equal to the strip's index into\n\t\t\t\t** the Column[] array, because the strip uses it to access the stripclass\n\t\t\t\t** buttons.\n\t\t\t\t*/\n\t\t\t\tint ID;\n\n\t\t\t\t/*\n\t\t\t\t**\tShape numbers for the shapes in the STRIP.SHP file.\n\t\t\t\t*/\n\t\t\t\tenum SideBarStipShapeEnums {\n\t\t\t\t\tSB_BLANK,\t\t\t// The blank rectangle to use if there are no objects present.\n\t\t\t\t\tSB_FRAME\n\t\t\t\t};\n\n\t\t\t\t/*\n\t\t\t\t**\tIf this particular side strip needs to be redrawn, then this flag\n\t\t\t\t**\twill be true.\n\t\t\t\t*/\n\t\t\t\tunsigned IsToRedraw:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf construction is in progress (no other objects in this strip can\n\t\t\t\t**\tbe started), then this flag will be true. It will be cleared when\n\t\t\t\t**\tthe strip is free to start production again.\n\t\t\t\t*/\n\t\t\t\tunsigned IsBuilding:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis controls the sidebar slide direction. If this is true, then the sidebar\n\t\t\t\t**\twill scroll downward -- revealing previous objects.\n\t\t\t\t*/\n\t\t\t\tunsigned IsScrollingDown:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf the sidebar is scrolling, then this flag is true. Otherwise it is false.\n\t\t\t\t*/\n\t\t\t\tunsigned IsScrolling:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the object (sidebar slot) that is flashing. Only one slot can be flashing\n\t\t\t\t**\tat any one instant. This is usually the result of a click on the slot and construction\n\t\t\t\t**\thas commenced.\n\t\t\t\t*/\n\t\t\t\tint Flasher;\n\n\t\t\t\t/*\n\t\t\t\t**\tAs the sidebar scrolls up and down, this variable holds the index for the topmost\n\t\t\t\t**\tvisible sidebar slot.\n\t\t\t\t*/\n\t\t\t\tint TopIndex;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the queued scroll direction and amount. The sidebar\n\t\t\t\t**\twill scroll the number of slots indicated by this value. This\n\t\t\t\t**\tvalue is set according to the scroll buttons.\n\t\t\t\t*/\n\t\t\t\tint Scroller;\n\n\t\t\t\t/*\n\t\t\t\t**\tThe sidebar has smooth scrolling. This is the number of pixels the sidebar\n\t\t\t\t**\thas slide down. Thus, if this value were 5, then there would be 5 pixels of\n\t\t\t\t**\tthe TopIndex-1 sidebar object visible. When the Slid value reaches 24, then\n\t\t\t\t**\tthe value resets to zero and the TopIndex is decremented. For sliding in the\n\t\t\t\t**\topposite direction, change the IsScrollingDown flag.\n\t\t\t\t*/\n\t\t\t\tint Slid;\n\n\t\t\t\t/*\n\t\t\t\t** The value of Slid the last time we rendered the sidebar.\n\t\t\t\t*/\n\t\t\t\tint LastSlid;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the count of the number of sidebar slots that are active.\n\t\t\t\t*/\n\t\t\t\tint BuildableCount;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the array of buildable object types. This array is sorted in the order\n\t\t\t\t**\tthat it is to be displayed. This array keeps track of which objects are building\n\t\t\t\t**\tand ready to be placed. The very nature of this method precludes simultaneous\n\t\t\t\t**\tconstruction of the same object type.\n\t\t\t\t*/\n\t\t\t\ttypedef struct BuildType {\n\t\t\t\t\tint BuildableID;\n\t\t\t\t\tRTTIType BuildableType;\n\t\t\t\t\tint Factory;\t\t\t\t\t\t\t\t// Production manager.\n\t\t\t\t\tbool BuildableViaCapture;\t\t\t\t// Added for new sidebar functionality. ST - 9/24/2019 3:10PM\n\t\t\t\t} BuildType;\n\t\t\t\tBuildType Buildables[MAX_BUILDABLES];\n\n\t\t\t\t/*\n\t\t\t\t**\tPointer to the shape data for small versions of the logos. These are used as\n\t\t\t\t**\tplaceholder pieces on the side bar.\n\t\t\t\t*/\n\t\t\t\tstatic void * LogoShapes;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis points to the animation sequence of frames used to mark the passage of time\n\t\t\t\t**\tas an object is undergoing construction.\n\t\t\t\t*/\n\t\t\t\tstatic void const * ClockShapes;\n\n\t\t\t\t/*\n\t\t\t\t** This points to the animation sequence which deals with special\n\t\t\t\t** shapes which handle non-production based icons.\n\t\t\t\t*/\n\t\t\t\tstatic void const * SpecialShapes[SPC_COUNT];\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the last theater that the special palette remap table was loaded\n\t\t\t\t**\tfor. If the current theater differs from this recorded value, then the\n\t\t\t\t**\tremap tables are reloaded.\n\t\t\t\t*/\n//\t\t\t\tstatic TheaterType LastTheater;\n\n\t\t\t\tstatic ShapeButtonClass UpButton[COLUMNS];\n\t\t\t\tstatic ShapeButtonClass DownButton[COLUMNS];\n\t\t\t\tstatic SelectClass SelectButton[COLUMNS][MAX_VISIBLE];\n\n\t\t\t\t/*\n\t\t\t\t**\tThis points to the shapes that are used for the clock overlay. This displays\n\t\t\t\t**\tprogress of construction.\n\t\t\t\t*/\n\t\t\t\tstatic char ClockTranslucentTable[(1+1)*256];\n\n\t\t} Column[COLUMNS];\n\n\n\t\t/*\n\t\t**\tIf the sidebar is active then this flag is true.\n\t\t*/\n\t\tunsigned IsSidebarActive:1;\n\n\t\t/*\n\t\t**\tThis flag tells the rendering system that the sidebar needs to be redrawn.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\t\tclass SBGadgetClass: public GadgetClass {\n\t\t\tpublic:\n//#ifdef WIN32\n\t\t\t\tSBGadgetClass(void) : GadgetClass((int)((int)SIDE_X+8)*RESFACTOR, (int)SIDE_Y*RESFACTOR, (int)((int)SIDE_WIDTH-1)*RESFACTOR-1, (int)((int)SIDE_HEIGHT-1)*RESFACTOR, LEFTUP) {};\n//#else\n//\t\t\t\tSBGadgetClass(void) : GadgetClass((int)SIDE_X+8, (int)SIDE_Y, (int)SIDE_WIDTH-1, (int)SIDE_HEIGHT-1, LEFTUP) {};\n//#endif\n\t\t\tprotected:\n\t\t\t\tvirtual int Action(unsigned flags, KeyNumType & key);\n\t\t};\n\n\t\t/*\n\t\t**\tThis is the button that is used to collapse and expand the sidebar.\n\t\t** These buttons must be available to derived classes, for Save/Load.\n\t\t*/\n\t\tstatic ShapeButtonClass Repair;\n\t\tstatic ShapeButtonClass Upgrade;\n\t\tstatic ShapeButtonClass Zoom;\n\t\tstatic SBGadgetClass Background;\n\n\t\tbool Scroll(bool up, int column);\n\n\tprivate:\n\t\tbool Activate_Repair(int control);\n\t\tbool Activate_Upgrade(int control);\n\t\tbool Activate_Demolish(int control);\n\t\tint Which_Column(RTTIType type);\n\n\t\tunsigned IsRepairActive:1;\n\t\tunsigned IsUpgradeActive:1;\n\t\tunsigned IsDemolishActive:1;\n};\n\n#endif"
  },
  {
    "path": "REDALERT/SIDEBARGlyphx.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\sidebar.cpv   2.13   02 Aug 1995 17:03:22   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBARGlyphx.CPP                                            *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : March 14th, 2019                                             *\n *                                                                                             *\n *                  Last Update : March 14th, 2019                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"SidebarGlyphx.h\"\n\n\n/*\n**  ST - 3/14/2019 10:49AM\n** \n**  We are going to need one sidebar per player for multiplayer with GlyphX. We can't have different maps / cell arrays per \n**  player though, so SidebarClass being in the middle of the map/display class hierarchy is a problem.\n** \n**  All the class static data will have to be made non-static so we can have multiple instances.\n** \n**  So, this is a stub sidebar class with the functionality we need just to support the exporting of production data to the\n**  GlyphX client.\n** \n** \n*/\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::SidebarGlyphxClass -- Default constructor for the sidebar.              *\n *                                                                                             *\n *    Constructor for the sidebar handler. It basically sets up the sidebar to the empty       *\n *    condition.                                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarGlyphxClass::SidebarGlyphxClass(void)\n{\n\t//IsRepairActive = false;\n\t//IsUpgradeActive = false;\n\t//IsDemolishActive = false;\n}\n\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Init_Clear -- Sets sidebar to a known (and deactivated) state           *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::Init_Clear(HouseClass *player_ptr)\n{\n\tSidebarPlayerPtr = player_ptr;\n\t\n\t//IsRepairActive = false;\n\t//IsUpgradeActive = false;\n\t//IsDemolishActive = false;\n\n\tColumn[0].Set_Parent_Sidebar(this);\n\tColumn[1].Set_Parent_Sidebar(this);\n\n\tColumn[0].Init_Clear();\n\tColumn[1].Init_Clear();\n\n\n\t//Activate(false);\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Init_IO -- Adds buttons to the button list                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::Init_IO(void)\n{\n\t/*\n\t** If a game was loaded & the sidebar was enabled, pop it up now\n\t*/\n\t//if (IsSidebarActive) {\n\t//\tIsSidebarActive = false;\n\t//\tActivate(1);\n\t//}\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Which_Column -- Determines which column a given type should appear.     *\n *                                                                                             *\n *    Use this function to resolve what column the specified object type should be placed      *\n *    into.                                                                                    *\n *                                                                                             *\n * INPUT:   otype -- Pointer to the object type class of the object in question.               *\n *                                                                                             *\n * OUTPUT:  Returns with the column number that the object should be placed in.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/01/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nint SidebarGlyphxClass::Which_Column(RTTIType type)\n{\n\tif (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {\n\t\treturn(0);\n\t}\n\treturn(1);\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Factory_Link -- Links a factory to a sidebar strip.                     *\n *                                                                                             *\n *    This routine will link the specified factory to the sidebar strip. A factory must be     *\n *    linked to the sidebar so that as the factory production progresses, the sidebar will     *\n *    show the production progress.                                                            *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to attach.                                          *\n *                                                                                             *\n *          type     -- The object type number.                                                *\n *                                                                                             *\n *          id       -- The object sub-type number.                                            *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached to the sidebar strip?                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarGlyphxClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\treturn(Column[Which_Column(type)].Factory_Link(factory, type, id));\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Add -- Adds a game object to the sidebar list.                          *\n *                                                                                             *\n *    This routine is used to add a game object to the sidebar. Call this routine when a       *\n *    factory type building is created. It handles the case of adding an item that has already *\n *    been added -- it just ignores it.                                                        *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object that is being added.                             *\n *                                                                                             *\n * OUTPUT:  bool; Was the object added to the sidebar?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarGlyphxClass::Add(RTTIType type, int id, bool via_capture)\n{\n\tint column;\n\n\t/*\n\t** Add the sidebar only if we're not in editor mode.\n\t*/\n\tif (!Debug_Map) {\n\t\tcolumn = Which_Column(type);\n\n\t\tif (Column[column].Add(type, id, via_capture)) {\n\t\t\t//Activate(1);\n\t\t\treturn(true);\n\t\t}\n\t\treturn(false);\n\t}\n\n\treturn(false);\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::AI -- Handles player clicking on sidebar area.                          *\n *                                                                                             *\n *    This routine handles the processing necessary when the player clicks on the sidebar.     *\n *    Typically, this is selection of the item to build.                                       *\n *                                                                                             *\n * INPUT:   input -- Reference to the keyboard input value.                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinates at time of input.                                       *\n *                                                                                             *\n * OUTPUT:  bool; Was the click handled?                                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/28/94   JLB : Created.                                                                 *\n *   11/11/1994 JLB : Processes input directly.                                                *\n *   12/26/1994 JLB : Uses factory manager class for construction handling.                    *\n *   12/31/1994 JLB : Simplified to use the sidebar strip class handlers.                      *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *   06/27/1995 JLB : <TAB> key toggles sidebar.                                               *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::AI(KeyNumType & input, int x, int y)\n{\n\tif (!Debug_Map) {\n\t\tColumn[0].AI(input, x, y);\n\t\tColumn[1].AI(input, x, y);\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Recalc -- Examines the sidebar data and updates it as necessary.        *\n *                                                                                             *\n *    Occasionally a factory gets destroyed. This routine must be called in such a case        *\n *    because it might be possible that sidebar object need to be removed. This routine will   *\n *    examine all existing objects in the sidebar class and if no possible factory can         *\n *    produce it, then it will be removed.                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This routine is exhaustive and thus time consuming. Only call it when really    *\n *             necessary. Such as when a factory is destroyed rather than when a non-factory   *\n *             is destroyed.                                                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   11/30/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::Recalc(void)\n{\n\tColumn[0].Recalc();\n\tColumn[1].Recalc();\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::StripClass -- Default constructor for the side strip class. *\n *                                                                                             *\n *    This constructor is used to reset the side strip to default empty state.                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSidebarGlyphxClass::StripClass::StripClass(void)\n{\n\tIsBuilding = false;\n\tBuildableCount = 0;\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t\tBuildables[index].BuildableViaCapture = false;\n\t}\n\tParentSidebar = NULL;\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state*\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/24/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::StripClass::Init_Clear(void)\n{\n\tIsBuilding = false;\n\tBuildableCount = 0;\n\n\t/*\n\t** Since we're resetting the strips, clear out all the buildables & factory pointers.\n\t*/\n\tfor (int index = 0; index < MAX_BUILDABLES; index++) {\n\t\tBuildables[index].BuildableID = 0;\n\t\tBuildables[index].BuildableType = RTTI_NONE;\n\t\tBuildables[index].Factory = -1;\n\t\tBuildables[index].BuildableViaCapture = false;\n\t}\n}\n\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::Add -- Add an object to the side strip.                     *\n *                                                                                             *\n *    Use this routine to add a buildable object to the side strip.                            *\n *                                                                                             *\n * INPUT:   object   -- Pointer to the object type that can be built and is to be added to     *\n *                      the side strip.                                                        *\n *                                                                                             *\n * OUTPUT:  bool; Was the object successfully added to the side strip? Failure could be the    *\n *                result of running out of room in the side strip array or the object might    *\n *                already be in the list.                                                      *\n *                                                                                             *\n * WARNINGS:   none.                                                                           *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarGlyphxClass::StripClass::Add(RTTIType type, int id, bool via_capture)\n{\n\tif (BuildableCount <= MAX_BUILDABLES) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\t\treturn(false);\n\t\t\t}\n\t\t}\n\t\tif (!ScenarioInit && type != RTTI_SPECIAL) {\n\t\t\tSpeak(VOX_NEW_CONSTRUCT);\n\t\t}\n\t\tBuildables[BuildableCount].BuildableType = type;\n\t\tBuildables[BuildableCount].BuildableID = id;\n\t\tBuildables[BuildableCount].Factory = -1;\n\t\tBuildables[BuildableCount].BuildableViaCapture = via_capture;\n\t\tBuildableCount++;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::AI -- Input and AI processing for the side strip.                 *\n *                                                                                             *\n *    The side strip AI processing is performed by this function. This function not only       *\n *    checks for player input, but also handles any graphic logic updating necessary as a      *\n *    result of flashing or construction animation.                                            *\n *                                                                                             *\n * INPUT:   input -- The player input code.                                                    *\n *                                                                                             *\n *          x,y   -- Mouse coordinate to use.                                                  *\n *                                                                                             *\n * OUTPUT:  bool; Did the AI detect that it will need a rendering change? If this routine      *\n *                returns true, then the Draw_It function should be called at the              *\n *                earliest opportunity.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   12/31/1994 JLB : Created.                                                                 *\n *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *\n *=============================================================================================*/\nbool SidebarGlyphxClass::StripClass::AI(KeyNumType & input, int , int )\n{\n\t/*\n\t** This is needed as it's where units get queued for structure exit. ST -3/14/2019 12:03PM\n\t*/\n\t\n\t\n\tif (IsBuilding) {\n\t\tfor (int index = 0; index < BuildableCount; index++) {\n\t\t\tint factoryid = Buildables[index].Factory;\n\n\t\t\tif (factoryid != -1) {\n\t\t\t\tFactoryClass * factory = Factories.Raw_Ptr(factoryid);\n\n\t\t\t\tif (factory && (factory->Has_Changed() || factory->Is_Blocked())) {\n\t\t\t\t\t\n\t\t\t\t\tif (factory->Has_Completed()) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tConstruction has been completed. Announce this fact to the player and\n\t\t\t\t\t\t**\ttry to get the object to automatically leave the factory. Buildings are\n\t\t\t\t\t\t**\tthe main exception to the ability to leave the factory under their own\n\t\t\t\t\t\t**\tpower.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tTechnoClass * pending = factory->Get_Object();\n\t\t\t\t\t\tif (pending) {\n\t\t\t\t\t\t\tswitch (pending->What_Am_I()) {\n\t\t\t\t\t\t\t\tcase RTTI_VESSEL:\n\t\t\t\t\t\t\t\tcase RTTI_UNIT:\n\t\t\t\t\t\t\t\tcase RTTI_AIRCRAFT:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tif (!factory->Is_Blocked()) {\n\t\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_BUILDING:\n\t\t\t\t\t\t\t\t\tif (!factory->Is_Blocked()) {\n\t\t\t\t\t\t\t\t\t\tSpeak(VOX_CONSTRUCTION);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase RTTI_INFANTRY:\n\t\t\t\t\t\t\t\t\tOutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));\n\t\t\t\t\t\t\t\t\tif (!factory->Is_Blocked()) {\n\t\t\t\t\t\t\t\t\t\tSpeak(VOX_UNIT_READY);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.  *\n *                                                                                             *\n *    This routine will revalidate all the buildable objects in the sidebar. This routine      *\n *    comes in handy when a factory has been destroyed, and the sidebar needs to reflect any   *\n *    change that this requires. It checks every object to see if there is a factory available *\n *    that could produce it. If none can be found, then the object is removed from the         *\n *    sidebar.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  bool; The sidebar has changed as a result of this call?                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *   06/26/1995 JLB : Doesn't collapse sidebar when buildables removed.                        *\n *=============================================================================================*/\nbool SidebarGlyphxClass::StripClass::Recalc(void)\n{\n\tint ok;\n\n\tif (Debug_Map || !BuildableCount) {\n\t\treturn(false);\n\t}\n\n\t/*\n\t**\tSweep through all objects listed in the sidebar. If any of those object can\n\t**\tnot be created -- even in theory -- then they must be removed form the sidebar and\n\t**\tany current production must be abandoned.\n\t*/\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tTechnoTypeClass const * tech = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);\n\t\tif (tech) {\n\t\t\tok = tech->Who_Can_Build_Me(true, false, ParentSidebar->SidebarPlayerPtr->Class->House) != NULL;\n\t\t} else {\n\t\t\t\n\t\t\tif ((unsigned)Buildables[index].BuildableID < SPC_COUNT) {\n\t\t\t\tok = ParentSidebar->SidebarPlayerPtr->SuperWeapon[Buildables[index].BuildableID].Is_Present();\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t}\n\n\t\tif (!ok) {\n\n\t\t\t/*\n\t\t\t**\tRemoves this entry from the list.\n\t\t\t*/\n\t\t\tif (BuildableCount > 1 && index < BuildableCount-1) {\n\t\t\t\tmemcpy(&Buildables[index], &Buildables[index+1], sizeof(Buildables[0])*((BuildableCount-index)-1));\n\t\t\t}\n\t\t\tBuildableCount--;\n\t\t\tindex--;\n\n\t\t\tBuildables[BuildableCount].BuildableID = 0;\n\t\t\tBuildables[BuildableCount].BuildableType = RTTI_NONE;\n\t\t\tBuildables[BuildableCount].Factory = -1;\n\t\t\tBuildables[BuildableCount].BuildableViaCapture = false;\n\t\t}\n\t}\n\n\treturn(false);\n}\n\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::Factory_Link -- Links a factory to a sidebar button.              *\n *                                                                                             *\n *    This routine will link the specified factory to this sidebar strip. The exact button to  *\n *    link to is determined from the object type and id specified. A linked button is one that *\n *    will show appropriate construction animation (clock shape) that matches the state of     *\n *    the factory.                                                                             *\n *                                                                                             *\n * INPUT:   factory  -- The factory number to link to the sidebar.                             *\n *                                                                                             *\n *          type     -- The object type that this factory refers to.                           *\n *                                                                                             *\n *          id       -- The object sub-type that this factory refers to.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully attached? Failure would indicate that there is no     *\n *          object of the specified type and sub-type in the sidebar list.                     *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarGlyphxClass::StripClass::Factory_Link(int factory, RTTIType type, int id)\n{\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {\n\t\t\tBuildables[index].Factory = factory;\n\t\t\tIsBuilding = true;\n\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Abandon_Production -- Stops production of the object specified.               *\n *                                                                                             *\n *    This routine is used to abandon production of the object specified. The factory will     *\n *    be completely disabled by this call.                                                     *\n *                                                                                             *\n * INPUT:   type     -- The object type that is to be abandoned. The sub-type is not needed    *\n *                      since it is presumed there can be only one type in production at any   *\n *                      one time.                                                              *\n *                                                                                             *\n *          factory  -- The factory number that is doing the production.                       *\n *                                                                                             *\n * OUTPUT:  Was the factory successfully abandoned?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SidebarGlyphxClass::Abandon_Production(RTTIType type, int factory)\n{\n\treturn(Column[Which_Column(type)].Abandon_Production(factory));\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.     *\n *                                                                                             *\n *    Production of the object associated with this sidebar is abandoned when this routine is  *\n *    called.                                                                                  *\n *                                                                                             *\n * INPUT:   factory  -- The factory index that is to be suspended.                             *\n *                                                                                             *\n * OUTPUT:  Was the production abandonment successful?                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/18/1995 JLB : Created.                                                                 *\n *   08/06/1995 JLB : More intelligent abandon logic for multiple factories.                   *\n *=============================================================================================*/\nbool SidebarGlyphxClass::StripClass::Abandon_Production(int factory)\n{\n\tbool noprod = true;\n\tbool abandon = false;\n\tfor (int index = 0; index < BuildableCount; index++) {\n\t\tif (Buildables[index].Factory == factory) {\n\t\t\tFactories.Raw_Ptr(factory)->Abandon();\n\t\t\tBuildables[index].Factory = -1;\n\t\t\tabandon = true;\n\t\t} else {\n\t\t\tif (Buildables[index].Factory != -1) {\n\t\t\t\tnoprod = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is no production whatsoever on this strip, then flag it so.\n\t*/\n\tif (noprod) {\n\t\tIsBuilding = false;\n\t}\n\treturn(abandon);\n}\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Code_Pointers -- Converts classes pointers to savable representation    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/25/2019 5:36PM ST : Created.                                                            *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::Code_Pointers(void)\n{\n\tif (SidebarPlayerPtr) {\n\t\t((HouseClass *&)SidebarPlayerPtr) = (HouseClass *)SidebarPlayerPtr->Class->House;\n\t} else {\n\t\t((HouseClass *&)SidebarPlayerPtr) = (HouseClass *)HOUSE_NONE;\n\t}\t\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Decode_Pointers -- Converts classes savable representation to run-time  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/25/2019 5:36PM ST : Created.                                                            *\n *=============================================================================================*/\nvoid SidebarGlyphxClass::Decode_Pointers(void)\n{\n\tif (*((HousesType*)&SidebarPlayerPtr) == HOUSE_NONE) {\n\t\tSidebarPlayerPtr = NULL;\n\t} else {\n\t\t((HouseClass *&)SidebarPlayerPtr) = HouseClass::As_Pointer(*((HousesType*)&SidebarPlayerPtr));\n\t}\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Load -- Loads from a save game file.                                    *\n *                                                                                             *\n * INPUT:   file  -- The file to read the data from.                                           *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/26/2019 10:57AM ST : Created.                                                           *\n *=============================================================================================*/\nbool SidebarGlyphxClass::Load(Straw &file)\n{\n\t::new (this) SidebarGlyphxClass();\n\n\t//bool ok = Read_Object(this, sizeof(*this), file, false);\n\tif (file.Get(this, sizeof(*this)) != sizeof(*this)) {\n\t\treturn false;\n\t}\n\n\tColumn[0].Set_Parent_Sidebar(this);\n\tColumn[1].Set_Parent_Sidebar(this);\n\n\treturn true;\n}\n\n\n/***********************************************************************************************\n * SidebarGlyphxClass::Save -- Write to a save game file.                                      *\n *                                                                                             *\n * INPUT:   file  -- The file to write the data to.                                            *\n *                                                                                             *\n * OUTPUT:  true = success, false = failure                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   9/26/2019 10:57AM ST : Created.                                                           *\n *=============================================================================================*/\nbool SidebarGlyphxClass::Save(Pipe &file)\n{\n\t//return(Write_Object(this, sizeof(*this), file));\n\t\n\tfile.Put(this, sizeof(*this));\n\t\n\treturn true;\n}\n\n\nextern SidebarGlyphxClass *Get_Current_Context_Sidebar(HouseClass *player_ptr);\n\nvoid Sidebar_Glyphx_Init_Clear(HouseClass *player_ptr)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\tsidebar->Init_Clear(player_ptr);\n\t}\n}\n\nvoid Sidebar_Glyphx_Init_IO(HouseClass *player_ptr)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\tsidebar->Init_IO();\n\t}\n}\n\nbool Sidebar_Glyphx_Abandon_Production(RTTIType type, int factory, HouseClass *player_ptr)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\treturn sidebar->Abandon_Production(type, factory);\n\t}\n\n\treturn false;\n}\n\nbool Sidebar_Glyphx_Add(RTTIType type, int id, HouseClass *player_ptr, bool via_capture)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\treturn sidebar->Add(type, id, via_capture);\n\t}\n\n\treturn false;\n}\n\nvoid Sidebar_Glyphx_Recalc(HouseClass *player_ptr)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\tsidebar->Recalc();\n\t}\n}\n\nvoid Sidebar_Glyphx_AI(HouseClass *player_ptr, KeyNumType & input)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\tsidebar->AI(input, 0, 0);\n\t}\n}\n\nbool Sidebar_Glyphx_Factory_Link(int factory, RTTIType type, int id, HouseClass *player_ptr)\n{\n\tSidebarGlyphxClass *sidebar = Get_Current_Context_Sidebar(player_ptr);\n\tif (sidebar) {\n\t\treturn sidebar->Factory_Link(factory, type, id);\n\t}\n\n\treturn false;\n}\n\nbool Sidebar_Glyphx_Save(Pipe &file, SidebarGlyphxClass *sidebar)\n{\n\tif (sidebar) {\n\t\treturn sidebar->Save(file);\n\t}\n\treturn false;\n}\t\t\t  \n\nbool Sidebar_Glyphx_Load(Straw &file, SidebarGlyphxClass *sidebar)\n{\n\tif (sidebar) {\n\t\treturn sidebar->Load(file);\n\t}\n\treturn false;\n}\t\t\t  \n\nvoid Sidebar_Glyphx_Code_Pointers(SidebarGlyphxClass *sidebar)\n{\n\tif (sidebar) {\n\t\tsidebar->Code_Pointers();\n\t}\n}\t\t\t  \n\nvoid Sidebar_Glyphx_Decode_Pointers(SidebarGlyphxClass *sidebar)\n{\n\tif (sidebar) {\n\t\tsidebar->Decode_Pointers();\n\t}\n}"
  },
  {
    "path": "REDALERT/SIDEBARGlyphx.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header:   F:\\projects\\c&c\\vcs\\code\\sidebar.h_v   2.18   16 Oct 1995 16:45:24   JOE_BOSTIC  $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SIDEBAR.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 20, 1994                                             *\n *                                                                                             *\n *                  Last Update : October 20, 1994   [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SIDEBAR_GLYPHX_H\n#define SIDEBAR_GLYPHX_H\n\n#pragma once\n\n#include\t\"function.h\"\n#include\t\"power.h\"\n#include\t\"factory.h\"\n\n\n/*\n**  ST - 3/14/2019 10:49AM\n** \n**  We are going to need one sidebar per player for multiplayer with GlyphX. We can't have different maps / cell arrays per \n**  player though, so SidebarClass being in the middle of the map/display class hierarchy is a problem.\n** \n**  All the class static data will have to be made non-static so we can have multiple instances.\n** \n**  So, this is a stub sidebar class with the functionality we need just to support the exporting of production data to the\n**  GlyphX client.\n** \n** \n*/\n\n\n\n\nclass SidebarGlyphxClass\n{\n\tpublic:\n\t\t\n\t\tenum SideBarClassEnums {\n\t\t\tCOLUMNS=2\t\t\t\t\t\t\t// Number of side strips on sidebar.\n\t\t};\n\t\n\t\tSidebarGlyphxClass(void);\n\n\t\t/*\n\t\t** Initialization\n\t\t*/\n\t\tvoid Init_Clear(HouseClass *player_ptr);\t\t\t\t\t\t// Clears all to known state\n\t\tvoid Init_IO(void);\t\t\t\t\t\t\t// Inits button list\n\n\t\tvoid AI(KeyNumType & input, int x, int y);\n\n\t\tbool  Abandon_Production(RTTIType type, int factory);\n\t\tbool  Add(RTTIType type, int ID, bool via_capture = false);\n\t\tvoid  Recalc(void);\n\t\tbool  Factory_Link(int factory, RTTIType type, int id);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tvoid Code_Pointers(void);\n\t  \tvoid Decode_Pointers(void);\n\t\tbool Load(Straw &file);\n\t\tbool Save(Pipe &pipe);\n\n\t\t/*\n\t\t**\tEach side strip is managed by this class. It handles all strip specific\n\t\t**\tactions.\n\t\t*/\n\t\tclass StripClass : public StageClass\n\t\t{\n\t\t\tclass SelectClass : public ControlClass\n\t\t\t{\n\t\t\t\tpublic:\n\t\t\t\t\tSelectClass(void);\n\n\t\t\t\t\tvoid Set_Owner(StripClass & strip, int index);\n\t\t\t\t\tStripClass * Strip;\n\t\t\t\t\tint Index;\n\n\t\t\t\tprotected:\n\t\t\t\t\tint Action(unsigned flags, KeyNumType & key);\n\t\t\t};\n\n\t\t\tpublic:\n\n\t\t\t\tStripClass(void);\n\t\t\t\tbool  Add(RTTIType type, int ID, bool via_capture);\n\t\t\t\tbool  Abandon_Production(int factory);\n\t\t\t\tbool  AI(KeyNumType & input, int x, int y);\n\t\t\t\tvoid  One_Time(int id);\n\t\t\t\tvoid  Init_Clear(void);\n\t\t\t\tvoid  Init_IO(int id);\n\t\t\t\tvoid  Init_Theater(TheaterType theater);\n\t\t\t\tbool  Recalc(void);\n\t\t\t\tbool  Factory_Link(int factory, RTTIType type, int id);\n\t\t\t\tvoid const * Get_Special_Cameo(int type);\n\n\t\t\t\tvoid Set_Parent_Sidebar(SidebarGlyphxClass *parent) {ParentSidebar = parent;}\n\n\t\t\t\t/*\n\t\t\t\t**\tFile I/O.\n\t\t\t\t*/\n\t\t\t\tbool  Load(FileClass & file);\n\t\t\t\tbool  Save(FileClass & file);\n\t\t\t\t//void  Code_Pointers(void);\n\t\t\t\t//void  Decode_Pointers(void);\n\n\n\t\t\t\t/*\n\t\t\t\t**\tWorking numbers used when rendering and processing the side strip.\n\t\t\t\t*/\n\t\t\t\tenum SideBarGeneralEnums {\n\t\t\t\t\tMAX_BUILDABLES = 75\t\t\t// Maximum number of object types in sidebar.\n\t\t\t\t};\n\n\t\t\t\tSidebarGlyphxClass *ParentSidebar;\n\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is a unique identifier for the sidebar strip. Using this identifier,\n\t\t\t\t**\tit is possible to differentiate the button messages that arrive from the\n\t\t\t\t**\tcommon input button list.  It >MUST< be equal to the strip's index into\n\t\t\t\t** the Column[] array, because the strip uses it to access the stripclass\n\t\t\t\t** buttons.\n\t\t\t\t*/\n\t\t\t\tint ID;\n\n\t\t\t\t/*\n\t\t\t\t**\tIf construction is in progress (no other objects in this strip can\n\t\t\t\t**\tbe started), then this flag will be true. It will be cleared when\n\t\t\t\t**\tthe strip is free to start production again.\n\t\t\t\t*/\n\t\t\t\tunsigned IsBuilding:1;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the count of the number of sidebar slots that are active.\n\t\t\t\t*/\n\t\t\t\tint BuildableCount;\n\n\t\t\t\t/*\n\t\t\t\t**\tThis is the array of buildable object types. This array is sorted in the order\n\t\t\t\t**\tthat it is to be displayed. This array keeps track of which objects are building\n\t\t\t\t**\tand ready to be placed. The very nature of this method precludes simultaneous\n\t\t\t\t**\tconstruction of the same object type.\n\t\t\t\t*/\n\t\t\t\ttypedef struct BuildType {\n\t\t\t\t\tint BuildableID;\n\t\t\t\t\tRTTIType BuildableType;\n\t\t\t\t\tint Factory;\t\t\t\t\t\t\t\t// Production manager.\n\t\t\t\t\tbool BuildableViaCapture;\t\t\t\t\t\t\t// Added for new sidebar functionality. ST - 9/24/2019 3:10PM\n\t\t\t\t} BuildType;\n\t\t\t\tBuildType Buildables[MAX_BUILDABLES];\n\n\t\t} Column[COLUMNS];\n\n\n\tprivate:\n\t\tint  Which_Column(RTTIType type);\n\n\t\tHouseClass *SidebarPlayerPtr;\n};\n\n\n\nvoid Sidebar_Glyphx_Init_Clear(HouseClass *player_ptr = NULL);\nvoid Sidebar_Glyphx_Init_IO(HouseClass *player_ptr = NULL);\t\t\t\t\t\t\t// Inits button list\nbool Sidebar_Glyphx_Abandon_Production(RTTIType type, int factory, HouseClass *player_ptr = NULL);\nbool Sidebar_Glyphx_Add(RTTIType type, int ID, HouseClass *player_ptr = NULL, bool via_capture = false);\nvoid Sidebar_Glyphx_Recalc(HouseClass *player_ptr = NULL);\nbool Sidebar_Glyphx_Factory_Link(int factory, RTTIType type, int id, HouseClass *player_ptr = NULL);\nvoid Sidebar_Glyphx_AI(HouseClass *player_ptr, KeyNumType & input);\nbool Sidebar_Glyphx_Save(Pipe &file, SidebarGlyphxClass *sidebar);\nbool Sidebar_Glyphx_Load(Straw &file, SidebarGlyphxClass *sidebar);\nvoid Sidebar_Glyphx_Code_Pointers(SidebarGlyphxClass *sidebar);\nvoid Sidebar_Glyphx_Decode_Pointers(SidebarGlyphxClass *sidebar);\n\n\n\n\n\n#endif //SIDEBAR_GLYPHX_H"
  },
  {
    "path": "REDALERT/SLIDER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SLIDER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SLIDER.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : September 20, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SliderClass::Action -- Handles input processing for the slider.                           *\n *   SliderClass::Bump -- Bumps the slider one \"thumb size\" up or down.                        *\n *   SliderClass::Recalc_Thumb -- Recalculates the thumb pixel size and starting offset.       *\n *   SliderClass::Set_Maximum -- Sets the maximum value for this slider.                       *\n *   SliderClass::Set_Thumb_Size -- Sets the size of the thumb in \"slider units\".              *\n *   SliderClass::Set_Value -- Sets the current thumb position for the slider.                 *\n *   SliderClass::SliderClass -- Normal constructor for a slider (with thumb) gadget.          *\n *   SliderClass::Step -- Steps the slider one value up or down.                               *\n *   SliderClass::Draw_Thumb -- Draws the \"thumb\" for this slider.                             *\n *   SliderClass::~SliderClass -- Destructor for slider object.                                *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include \"slider.h\"\n\n\n/***********************************************************************************************\n * SliderClass::SliderClass -- Normal constructor for a slider (with thumb) gadget.            *\n *                                                                                             *\n *    This is the normal constructor for the slider gadget.                                    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this gadget.                                   *\n *          x,y   -- The pixel coordinate of the upper left corner for this gadget.            *\n *          w,h   -- The width and height of the slider gadget. The slider automatically       *\n *                   adapts for horizontal or vertical operation depending on which of these   *\n *                   dimensions is greater.                                                    *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nSliderClass::SliderClass(unsigned id, int x, int y, int w, int h, int belong_to_list)\n\t: GaugeClass(id, x, y, w, h)\n{\n\tBelongToList = belong_to_list ? true : false;\n\n\tPlusGadget = 0;\n\tMinusGadget = 0;\n\tif (!BelongToList) {\n\t\tPlusGadget  = new ShapeButtonClass(id, MFCD::Retrieve(\"BTN-PLUS.SHP\"), X+Width+2, Y);\n\t\tMinusGadget = new ShapeButtonClass(id, MFCD::Retrieve(\"BTN-MINS.SHP\"), X-6, Y);\n\n\t\tif (PlusGadget) {\n\t\t\tPlusGadget->Make_Peer(*this);\n\t\t\tPlusGadget->Add(*this);\n\t\t\tPlusGadget->Flag_To_Redraw();\n\t\t}\n\t\tif (MinusGadget) {\n\t\t\tMinusGadget->Make_Peer(*this);\n\t\t\tMinusGadget->Add(*this);\n\t\t\tMinusGadget->Flag_To_Redraw();\n\t\t}\n\t}\n\tSet_Thumb_Size(1);\n\tRecalc_Thumb();\n\n\t/*\n\t** Gauges have at least 2 colors, but sliders should only have one.\n\t*/\n\tIsColorized = 0;\n}\n\n\n/***********************************************************************************************\n * SliderClass::~SliderClass -- Destructor for slider object.                                  *\n *                                                                                             *\n *    This cleans up the slider object in preparation for deletion.                            *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nSliderClass::~SliderClass(void)\n{\n\tif (PlusGadget) {\n\t\tdelete PlusGadget;\n\t\tPlusGadget = 0;\n\t}\n\tif (MinusGadget) {\n\t\tdelete MinusGadget;\n\t\tMinusGadget = 0;\n\t}\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Maximum -- Sets the maximum value for this slider.                         *\n *                                                                                             *\n *    This sets the maximum value that the slider can be set at. The maximum value controls    *\n *    the size of the thumb and the resolution of the thumb's movement.                        *\n *                                                                                             *\n * INPUT:   value -- The value to set for the slider's maximum.                                *\n * OUTPUT:  bool; Was the maximum value changed? A false indicates a set to the value it       *\n *                is currently set to already.                                                 *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Set_Maximum(int value)\n{\n\tif (GaugeClass::Set_Maximum(value)) {\n\t\tRecalc_Thumb();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Thumb_Size -- Sets the size of the thumb in \"slider units\".                *\n *                                                                                             *\n *    This routine will set the size of the thumb as it relates to the maximum value the       *\n *    slider can achieve. This serves to display a proportionally sized thumb as well as       *\n *    control how the slider \"bumps\" up or down.                                               *\n *                                                                                             *\n * INPUT:   value -- The new value of the thumb. It should never be larger than the slider     *\n *                   maximum.                                                                  *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Set_Thumb_Size(int value)\n{\n\tThumb = min(value, MaxValue);\n\tThumb = max(Thumb, 1);\n\tFlag_To_Redraw();\n\tRecalc_Thumb();\n}\n\n\n/***********************************************************************************************\n * SliderClass::Set_Value -- Sets the current thumb position for the slider.                   *\n *                                                                                             *\n *    This routine will set the thumb position for the slider.                                 *\n *                                                                                             *\n * INPUT:   value -- The position to set the slider. This position is relative to the maximum  *\n *                   value for the slider.                                                     *\n *                                                                                             *\n * OUTPUT:  bool; Was the slider thumb position changed at all?                                *\n * WARNINGS:  none                                                                             *\n * HISTORY:   01/15/1995 JLB : Created.                                                        *\n *=============================================================================================*/\nint SliderClass::Set_Value(int value)\n{\n\tvalue = min(value, MaxValue-Thumb);\n\n\tif (GaugeClass::Set_Value(value)) {\n\t\tRecalc_Thumb();\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Recalc_Thumb -- Recalculates the thumb pixel size and starting offset.         *\n *                                                                                             *\n *    This takes the current thumb logical size and starting value and calculates the pixel    *\n *    size and starting offset accordingly. This function should be called whenever one of     *\n *    these elements has changed.                                                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n * OUTPUT:     none                                                                            *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Recalc_Thumb(void)\n{\n\tint length = IsHorizontal ? Width : Height;\n\tint size   = length * fixed(Thumb, MaxValue);\n//\tint size   = Fixed_To_Cardinal(length, Cardinal_To_Fixed(MaxValue, Thumb));\n\tThumbSize  = max(size, 4);\n\tint start  = length * fixed(CurValue, MaxValue);\n//\tint start  = Fixed_To_Cardinal(length, Cardinal_To_Fixed(MaxValue, CurValue));\n\tThumbStart = min(start, length-ThumbSize);\n}\n\n\n/***********************************************************************************************\n * SliderClass::Action -- Handles input processing for the slider.                             *\n *                                                                                             *\n *    This routine is called when a qualifying input event has occurred. This routine will     *\n *    process that event and make any adjustments to the slider as necessary.                  *\n *                                                                                             *\n * INPUT:   flags -- Flag bits that tell the input event that caused this function to          *\n *                   be called.                                                                *\n *          key   -- Reference to the key that caused the input event.                         *\n * OUTPUT:  bool; Was the event consumed and further processing of the gadget list should be   *\n *                aborted?                                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Action(unsigned flags, KeyNumType &key)\n{\n\t/*\n\t**\tHandle the mouse click in a special way. If the click was not on the thumb, then\n\t**\tjump the thumb position one \"step\" in the appropriate direction. Otherwise, let normal\n\t**\tprocessing take place -- the slider then \"sticks\" and the thumb moves according to\n\t**\tmouse position.\n\t*/\n\tif (flags & LEFTPRESS) {\n\t\tint mouse;\t\t// Mouse pixel position.\n\t\tint edge;\t\t// Edge of slider.\n\n\t\tif (IsHorizontal) {\n\t\t\tmouse = Get_Mouse_X();\n\t\t\tedge = X;\n\t\t} else {\n\t\t\tmouse = Get_Mouse_Y();\n\t\t\tedge = Y;\n\t\t}\n\t\tedge += 1;\n\n\t\t/*\n\t\t** Clicking outside the thumb: invoke parent's Action to process flags etc,\n\t\t** but turn off the event & return true so processing stops at this button.\n\t\t*/\n\t\tif (mouse < edge+ThumbStart) {\n\t\t\tBump(true);\n\t\t\tGaugeClass::Action(0, key);\n\t\t\tkey = KN_NONE;\n\t\t\treturn(true);\n\t\t} else {\n\t\t\tif (mouse > edge+ThumbStart+ThumbSize) {\n\t\t\t\tBump(false);\n\t\t\t\tGaugeClass::Action(0, key);\n\t\t\t\tkey = KN_NONE;\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tGaugeClass::Action(flags, key);\n\t\t\t\tkey = KN_NONE;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t**  CHANGE GAUGECLASS::ACTION -- REMOVE (LEFTRELEASE) FROM IF STMT\n\t*/\n\treturn(GaugeClass::Action(flags, key));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Bump -- Bumps the slider one \"thumb size\" up or down.                          *\n *                                                                                             *\n *    This support function will bump the slider one \"step\" or the size of the thumb up or     *\n *    down as specified. It is typically called when the slider is clicked outside of the      *\n *    thumb region but still inside of the slider.                                             *\n *                                                                                             *\n * INPUT:   up -- Should the bump be to increase the current position?                         *\n * OUTPUT:  bool; Was the slider changed at all? A false indicates that the slider is already  *\n *                at one end or the other.                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Bump(int up)\n{\n\tif (up) {\n\t\treturn(Set_Value(CurValue - Thumb));\n\t}\n\treturn(Set_Value(CurValue + Thumb));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Step -- Steps the slider one value up or down.                                 *\n *                                                                                             *\n *    This routine will move the slider thumb one step in the direction specified.             *\n *                                                                                             *\n * INPUT:   up -- Should the step be up (i.e., forward)?                                       *\n * OUTPUT:  bool; Was the slider changed at all? A false indicates that the slider is already  *\n *                at one end or the other.                                                     *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/15/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Step(int up)\n{\n\tif (up) {\n\t\treturn(Set_Value(CurValue - 1));\n\t}\n\treturn(Set_Value(CurValue + 1));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Draw_Thumb -- Draws the \"thumb\" for this slider.                               *\n *                                                                                             *\n *    This will draw the thumb graphic for this slider. Sometimes the thumb requires special   *\n *    drawing, thus the need for this function separate from the normal Draw_Me function.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   The mouse is guaranteed to be hidden when this routine is called.               *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Draw_Thumb(void)\n{\n\tif (IsHorizontal) {\n\t\tDraw_Box(X+ThumbStart, Y, ThumbSize, Height, BOXSTYLE_RAISED, true);\n\t} else {\n\t\tDraw_Box(X, Y+ThumbStart, Width, ThumbSize, BOXSTYLE_RAISED, true);\n\t}\n}\n\n\n/***********************************************************************************************\n * SliderClass::Draw_Me -- Draws the body of the gauge.                                        *\n *                                                                                             *\n *    This routine will draw the body of the gauge if necessary.                               *\n *                                                                                             *\n * INPUT:   forced   -- Should the gauge be redrawn regardless of the current redraw flag?     *\n * OUTPUT:  bool; Was the gauge redrawn?                                                       *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nint SliderClass::Draw_Me(int forced)\n{\n\tif (BelongToList) {\n\t\tif (ControlClass::Draw_Me(forced)) {\n\n\t\t\t/*\n\t\t\t**\tHide the mouse.\n\t\t\t*/\n\t\t\tif (LogicPage == &SeenBuff) {\n\t\t\t\tConditional_Hide_Mouse(X, Y, X+Width, Y+Height);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tDraw the body & set text color.\n\t\t\t*/\n\t\t\tDraw_Box (X, Y, Width, Height, BOXSTYLE_DOWN, true);\n\t\t\tDraw_Thumb();\n\n\t\t\t/*\n\t\t\t**\tDisplay the mouse.\n\t\t\t*/\n\t\t\tif (LogicPage == &SeenBuff) {\n\t\t\t\tConditional_Show_Mouse();\n\t\t\t}\n\t\t\treturn(true);\n\t\t}\n\t}\n\n\t/*\n\t**\tIf it does not belong to a listbox...\n\t*/\n\treturn(GaugeClass::Draw_Me(forced));\n}\n\n\n/***********************************************************************************************\n * SliderClass::Peer_To_Peer -- A peer gadget was touched -- make adjustments.                 *\n *                                                                                             *\n *    This routine is called when one of the peer gadgets (the scroll arrows or the slider)    *\n *    was touched in some fashion. This routine will sort out whom and why and then make       *\n *    any necessary adjustments to the list box.                                               *\n *                                                                                             *\n * INPUT:   flags    -- The event flags that affected the peer gadget.                         *\n *          key      -- The key value at the time of the event.                                *\n *          whom     -- Which gadget is being touched.                                         *\n * OUTPUT:  none                                                                               *\n * WARNINGS:   none                                                                            *\n * HISTORY:    01/16/1995 JLB : Created.                                                       *\n *=============================================================================================*/\nvoid SliderClass::Peer_To_Peer(unsigned flags, KeyNumType & , ControlClass & whom)\n{\n\tif (flags & LEFTRELEASE) {\n\t\tif (&whom == PlusGadget) {\n\t\t\tStep(false);\n\t\t}\n\t\tif (&whom == MinusGadget) {\n\t\t\tStep(true);\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "REDALERT/SLIDER.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SLIDER.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SLIDER.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SLIDER_H\n#define SLIDER_H\n\n#include \"gauge.h\"\n#include \"shapebtn.h\"\n\n\n/***************************************************************************\n * SliderClass -- Like a Windows ListBox structure\t\t\t\t\t\t\t\t\t*\n *                                                                         *\n * INPUT:      int id-- id of gadget\t\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint x -- x position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint y -- y position of gadget\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint w -- width of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint h -- height of gadget\t\t\t\t\t\t\t\t\t\t\t\t*\n *\t\t\t\t\tint belong_to_list -- does this slider go with a listclass? *\n *                                                                         *\n * OUTPUT:     none.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n * WARNINGS:\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t*\n * HISTORY:    01/03/1995 MML : Created.                                   *\n *=========================================================================*/\nclass SliderClass : public GaugeClass\n{\n\tpublic:\n\t\tSliderClass(unsigned id, int x, int y, int w, int h, int belong_to_list=false);\n\t\tvirtual ~SliderClass(void);\n\n\t\tvirtual void Set_Thumb_Size(int value);\n\t\tvirtual int  Set_Maximum(int value);\n\t\tvirtual int  Set_Value(int);\n\t\tvirtual int  Bump(int up);\n\t\tvirtual int  Step(int up);\n\t\tvirtual int  Draw_Me(int forced);\n\t\tvirtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);\n\n\t\tvirtual int Thumb_Pixels(void) { return (ThumbSize);}\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the slider bar has been created, these point to the respective gadgets\n\t\t**\tthat it is composed of.\n\t\t*/\n\t\tShapeButtonClass * PlusGadget;\n\t\tShapeButtonClass * MinusGadget;\n\n\t\t/*\n\t\t**\tIf I belong to a listbox, I have to draw myself differently...\n\t\t**/\n\t\tunsigned BelongToList:1;\n\n\t\t/*\n\t\t**\tThis is the logical size of the thumb. This value is used when drawing\n\t\t**\tthe thumb imagery. It is also the amount that is bumped when the\n\t\t**\tBump() function is called.  (This value is in application units.)\n\t\t*/\n\t\tint Thumb;\n\n\t\t/*\n\t\t**\tThis is the current thumb pixel size and starting offset from beginning\n\t\t**\tof slider region.  (These values are in pixels.)\n\t\t*/\n\t\tint ThumbSize;\n\t\tint ThumbStart;\t\t\t// x or y position for the thumb\n\n\t\tvirtual int  Action(unsigned flags, KeyNumType &key);\n\t\tvirtual void Draw_Thumb(void);\n\n\tprivate:\n\t\tvoid Recalc_Thumb(void);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SMUDGE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SMUDGE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SMUDGE.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SmudgeClass::Disown -- Disowns (removes) a building bib piece.                            *\n *   SmudgeClass::Init -- Initialize the smudge tracking system.                               *\n *   SmudgeClass::Mark -- Marks a smudge down on the map.                                      *\n *   SmudgeClass::Read_INI -- Reads smudge data from an INI file.                              *\n *   SmudgeClass::SmudgeClass -- Constructor for smudge objects.                               *\n *   SmudgeClass::Write_INI -- Store all the smudge data to the INI database.                  *\n *   SmudgeClass::operator delete -- Deletes the smudge from the tracking system.              *\n *   SmudgeClass::operator new -- Creator of smudge objects.                                   *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"smudge.h\"\n\n\n\nHousesType SmudgeClass::ToOwn = HOUSE_NONE;\n\n\n/***********************************************************************************************\n * SmudgeClass::operator new -- Creator of smudge objects.                                     *\n *                                                                                             *\n *    This routine will allocate a smudge object from the smudge tracking pool.                *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to a newly allocated smudge object. If one couldn't be      *\n *          found, then NULL is returned.                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid * SmudgeClass::operator new(size_t )\n{\n\tvoid * ptr = Smudges.Allocate();\n\tif (ptr != NULL) {\n\t\t((SmudgeClass *)ptr)->Set_Active();\n\t}\n\treturn(ptr);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::operator delete -- Deletes the smudge from the tracking system.                *\n *                                                                                             *\n *    This routine is used to remove the smudge from the tracking system.                      *\n *                                                                                             *\n * INPUT:   ptr   -- Pointer to the smudge to delete.                                          *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::operator delete(void * ptr)\n{\n\tif (ptr != NULL) {\n\t\t((SmudgeClass *)ptr)->IsActive = false;\n\t}\n\tSmudges.Free((SmudgeClass *)ptr);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::SmudgeClass -- Constructor for smudge objects.                                 *\n *                                                                                             *\n *    This is the typical constructor for smudge objects. If the position to place the         *\n *    smudge is not given, then the smudge will be initialized in a limbo state. If the        *\n *    smudge is placed on the map, then this operation causes the smudge object itself to be   *\n *    deleted and special map values updated to reflect the presence of a smudge.              *\n *                                                                                             *\n * INPUT:   type  -- The type of smudge to construct.                                          *\n *                                                                                             *\n *          pos   -- The position to place the smudge. If -1, then the smudge is initialized   *\n *                   into a limbo state.                                                       *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nSmudgeClass::SmudgeClass(SmudgeType type, COORDINATE pos, HousesType house) :\n\tObjectClass(RTTI_SMUDGE, Smudges.ID(this)),\n\tClass(SmudgeTypes.Ptr((int)type))\n{\n\tif (pos != -1) {\n\t\tToOwn = house;\n\t\tif (!Unlimbo(pos)) {\n\t\t\tdelete this;\n\t\t} else {\n\t\t\tToOwn = HOUSE_NONE;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Init -- Initialize the smudge tracking system.                                 *\n *                                                                                             *\n *    This routine is used during the scenario clearing process to initialize the smudge       *\n *    object tracking system to a null state.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Init(void)\n{\n\tSmudges.Free_All();\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Mark -- Marks a smudge down on the map.                                        *\n *                                                                                             *\n *    This routine will place the smudge on the map. If the map cell allows.                   *\n *                                                                                             *\n * INPUT:   mark  -- The type of marking to perform. Only MARK_DOWN is supported.              *\n *                                                                                             *\n * OUTPUT:  bool; Was the smudge marked successfully? Failure occurs if the smudge isn't       *\n *                marked DOWN.                                                                 *\n *                                                                                             *\n * WARNINGS:   The smudge object is DELETED by this routine.                                   *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1994 JLB : Created.                                                                 *\n *   12/23/1994 JLB : Checks low level legality before proceeding.                             *\n *=============================================================================================*/\nbool SmudgeClass::Mark(MarkType mark)\n{\n\tassert(Smudges.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (ObjectClass::Mark(mark)) {\n\t\tif (mark == MARK_DOWN) {\n\t\t\tCELL origin = Coord_Cell(Coord);\n\n\t\t\tfor (int w = 0; w < Class->Width; w++) {\n\t\t\t\tfor (int h = 0; h < Class->Height; h++) {\n\t\t\t\t\tCELL newcell = origin + w + (h*MAP_CELL_W);\n\t\t\t\t\tif (Map.In_Radar(newcell)) {\n\t\t\t\t\t\tCellClass * cell = &Map[newcell];\n\n\t\t\t\t\t\tif (Class->IsBib) {\n\t\t\t\t\t\t\tcell->Smudge = Class->Type;\n\t\t\t\t\t\t\tcell->SmudgeData = w + (h*Class->Width);\n\t\t\t\t\t\t\tcell->Owner = ToOwn;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (cell->Is_Clear_To_Move(SPEED_TRACK, true, true)) {\n\t\t\t\t\t\t\t\tif (Class->IsCrater && cell->Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(cell->Smudge).IsCrater) {\n\t\t\t\t\t\t\t\t\tcell->SmudgeData++;\n\t\t\t\t\t\t\t\t\tcell->SmudgeData = (int)min((int)cell->SmudgeData, (int)4);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (cell->Smudge == SMUDGE_NONE) {\n\n\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t**\tSpecial selection of a crater that starts as close to the\n\t\t\t\t\t\t\t\t\t**\tspecified coordinate as possible.\n\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\tif (Class->IsCrater) {\n\t\t\t\t\t\t\t\t\t\tcell->Smudge = (SmudgeType)(SMUDGE_CRATER1 + CellClass::Spot_Index(Coord));\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcell->Smudge = Class->Type;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcell->SmudgeData = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t**\tFlag everything that might be overlapping this cell to redraw itself.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcell->Redraw_Objects();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t**\tWhether it was successful in placing, or not, delete the smudge object. It isn't\n\t\t\t**\tneeded once the map has been updated with the proper smudge data. Fake this object\n\t\t\t**\tas if it were never placed down!\n\t\t\t*/\n\t\t\tMap.Overlap_Up(Coord_Cell(Coord), this);\n\t\t\tIsDown = false;\n\t\t\tIsInLimbo = true;\n\t\t\tdelete this;\n\t\t\treturn(true);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Disown -- Disowns (removes) a building bib piece.                              *\n *                                                                                             *\n *    This routine is used when a building is removed from the game. If there was any bib      *\n *    attached, this routine will be called to disown the cells and remove the bib artwork.    *\n *                                                                                             *\n * INPUT:   cell  -- The origin cell for this bib removal.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   This is actually working on a temporary bib object. It is created for the sole  *\n *             purpose of calling this routine. It will be deleted immediately afterward.      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/04/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Disown(CELL cell)\n{\n\tassert(Smudges.ID(this) == ID);\n\tassert(IsActive);\n\n\tif (Class->IsBib) {\n\t\tfor (int w = 0; w < Class->Width; w++) {\n\t\t\tfor (int h = 0; h < Class->Height; h++) {\n\t\t\t\tCellClass & cellptr = Map[(CELL)(cell + w + (h*MAP_CELL_W))];\n\n\t\t\t\tif (cellptr.Overlay == OVERLAY_NONE || !OverlayTypeClass::As_Reference(cellptr.Overlay).IsWall) {\n\t\t\t\t\tcellptr.Smudge = SMUDGE_NONE;\n\t\t\t\t\tcellptr.SmudgeData = 0;\n\t\t\t\t\tif (!cellptr.IsFlagged) {\n\t\t\t\t\t\tcellptr.Owner = HOUSE_NONE;\n\t\t\t\t\t}\n\t\t\t\t\tcellptr.Redraw_Objects();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Read_INI -- Reads smudge data from an INI file.                                *\n *                                                                                             *\n *    This routine is used by the scenario loader to read the smudge data in an INI file and   *\n *    create the appropriate smudge objects on the map.                                        *\n *                                                                                             *\n * INPUT:   buffer   -- Pointer to the INI file staging buffer.                                *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/01/1994 JLB : Created.                                                                 *\n *   07/24/1995 JLB : Sets the smudge data value as well.                                      *\n *=============================================================================================*/\nvoid SmudgeClass::Read_INI(CCINIClass & ini)\n{\n\tchar\tbuf[128];\t// Working string staging buffer.\n\n\tint len = ini.Entry_Count(INI_Name());\n\tfor (int index = 0; index < len; index++) {\n\t\tchar const * entry = ini.Get_Entry(INI_Name(), index);\n\t\tSmudgeType\tsmudge;\t\t// Smudge type.\n\n\t\tini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));\n\t\tsmudge = SmudgeTypeClass::From_Name(strtok(buf, \",\"));\n\t\tif (smudge != SMUDGE_NONE) {\n\t\t\tchar * ptr = strtok(NULL, \",\");\n\t\t\tif (ptr != NULL) {\n\t\t\t\tint data = 0;\n\t\t\t\tCELL cell = atoi(ptr);\n\t\t\t\tptr = strtok(NULL, \",\");\n\t\t\t\tif (ptr != NULL) data = atoi(ptr);\n\t\t\t\tnew SmudgeClass(smudge, Cell_Coord(cell));\n\t\t\t\tif (Map[cell].Smudge == smudge && data != 0) {\n\t\t\t\t\tMap[cell].SmudgeData = data;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * SmudgeClass::Write_INI -- Store all the smudge data to the INI database.                    *\n *                                                                                             *\n *    This routine will output all the smudge data to the INI database.                        *\n *                                                                                             *\n * INPUT:   ini   -- Reference to the INI database object.                                     *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SmudgeClass::Write_INI(CCINIClass & ini)\n{\n\t/*\n\t**\tFirst, clear out all existing template data from the ini file.\n\t*/\n\tini.Clear(INI_Name());\n\n\t/*\n\t**\tFind all templates and write them to the file.\n\t*/\n\tfor (CELL index = 0; index < MAP_CELL_TOTAL; index++) {\n\t\tCellClass * ptr;\n\n\t\tptr = &Map[index];\n\t\tif (ptr->Smudge != SMUDGE_NONE) {\n\t\t\tSmudgeTypeClass const * stype = &SmudgeTypeClass::As_Reference(ptr->Smudge);\n\t\t\tif (!stype->IsBib) {\n\t\t\t\tchar\tuname[10];\n\t\t\t\tchar\tbuf[127];\n\n\t\t\t\tsprintf(uname, \"%d\", index);\n\t\t\t\tsprintf(buf, \"%s,%d,%d\", stype->IniName, index, ptr->SmudgeData);\n\t\t\t\tini.Put_String(INI_Name(), uname, buf);\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "REDALERT/SMUDGE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SMUDGE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SMUDGE.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : August 9, 1994                                               *\n *                                                                                             *\n *                  Last Update : August 9, 1994   [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SMUDGE_H\n#define SMUDGE_H\n\n#include\t\"object.h\"\n#include\t\"type.h\"\n\n\n/******************************************************************************\n**\tThis is the transitory form for smudges. They exist as independent objects\n**\tonly in the transition stage from creation to placement upon the map. Once\n**\tthey are placed on the map, they merely become 'smudges' in the cell data. This\n**\tobject is then destroyed.\n*/\nclass SmudgeClass : public ObjectClass\n{\n\tpublic:\n\t\t/*\n\t\t**\tThis is a pointer to the template object's class.\n\t\t*/\n\t\tCCPtr<SmudgeTypeClass> Class;\n\n\t\t/*-------------------------------------------------------------------\n\t\t**\tConstructors and destructors.\n\t\t*/\n\t\tstatic void * operator new(size_t size);\n\t\tstatic void * operator new(size_t , void * ptr) {return(ptr);};\n\t\tstatic void operator delete(void *ptr);\n\t\tSmudgeClass(SmudgeType type, COORDINATE pos=0xFFFFFFFFUL, HousesType house = HOUSE_NONE);\n\t\tSmudgeClass(NoInitClass const & x) : ObjectClass(x), Class(x) {};\n\t\toperator SmudgeType(void) const {return Class->Type;};\n\t\tvirtual ~SmudgeClass(void) {if (GameActive) SmudgeClass::Limbo();Class=0;};\n\n\t\tstatic void Init(void);\n\n\t\t/*\n\t\t**\tFile I/O.\n\t\t*/\n\t\tstatic void Read_INI(CCINIClass & ini);\n\t\tstatic void Write_INI(CCINIClass & ini);\n\t\tstatic char *INI_Name(void) {return \"SMUDGE\";};\n\t\tbool Load(Straw & file);\n\t\tbool Save(Pipe & file) const;\n\n\t\tvirtual ObjectTypeClass const & Class_Of(void) const {return *Class;};\n\t\tvirtual bool Mark(MarkType);\n\t\tvirtual void Draw_It(int , int , WindowNumberType ) const {};\n\n\t\tvoid Disown(CELL cell);\n\n\tprivate:\n\n\t\tstatic HousesType ToOwn;\n\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\tunsigned char SaveLoadPadding[8];\n\n};\n\n#endif"
  },
  {
    "path": "REDALERT/SOUNDDLG.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SOUNDDLG.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SOUNDDLG.CPP                                                 *\n *                                                                                             *\n *                   Programmer : Maria del Mar McCready-Legg, Joe L. Bostic                   *\n *                                                                                             *\n *                   Start Date : Jan 8, 1995                                                  *\n *                                                                                             *\n *                  Last Update : September 22, 1995 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   MusicListClass::Draw_Entry -- Draw the score line in a list box.                          *\n *   SoundControlsClass::Process -- Handles all the options graphic interface.                 *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"sounddlg.h\"\n\nclass MusicListClass : public ListClass\n{\n\tpublic:\n\t\tMusicListClass(int id, int x, int y, int w, int h) :\n\t\t\tListClass(id, x, y, w, h, TPF_6PT_GRAD|TPF_NOSHADOW, MFCD::Retrieve(\"BTN-UP.SHP\"), MFCD::Retrieve(\"BTN-DN.SHP\"))\n\t\t{};\n\t\tvirtual ~MusicListClass(void) {};\n\n\tprotected:\n\t\tvirtual void Draw_Entry(int index, int x, int y, int width, int selected);\n};\n\n\n/***********************************************************************************************\n * SoundControlsClass::Process -- Handles all the options graphic interface.                   *\n *                                                                                             *\n *    This routine is the main control for the visual representation of the options            *\n *    screen. It handles the visual overlay and the player input.                              *\n *                                                                                             *\n * INPUT:      none                                                                            *\n *                                                                                             *\n * OUTPUT:     none                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:    12/31/1994 MML : Created.                                                       *\n *=============================================================================================*/\nvoid SoundControlsClass::Process(void)\n{\n\n\t/*\n\t** Adjust dialog controls for resolution\n\t*/\n\tint option_width=   \tOPTION_WIDTH * RESFACTOR;\n\tint option_height=  \tOPTION_HEIGHT * RESFACTOR;\n\n\tint option_x=       \tOPTION_X * RESFACTOR;\n\tint option_y=       \tOPTION_Y * RESFACTOR;\n\n\tint listbox_x=      \tLISTBOX_X * RESFACTOR;\n\tint listbox_y=      \tLISTBOX_Y * RESFACTOR;\n\tint listbox_w=      \tLISTBOX_W * RESFACTOR;\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n#ifdef WIN32\n\tint listbox_h=      \t(LISTBOX_H * RESFACTOR)+2;\n#else\n\tint listbox_h=      \tLISTBOX_H * RESFACTOR;\n#endif\n#else\n\tint listbox_h=      \tLISTBOX_H * RESFACTOR;\n#endif\n\n\tint button_width=   \tBUTTON_WIDTH * RESFACTOR;\n\tint button_x=       \tBUTTON_X * RESFACTOR;\n\tint button_y=       \tBUTTON_Y * RESFACTOR;\n\n\tint stop_x=         \tSTOP_X * RESFACTOR;\n\tint stop_y=         \tSTOP_Y * RESFACTOR;\n\n\tint play_x=         \tPLAY_X * RESFACTOR;\n\tint play_y=         \tPLAY_Y * RESFACTOR;\n\n\tint onoff_width=    \tONOFF_WIDTH * RESFACTOR;\n\tint shuffle_x=      \tSHUFFLE_X * RESFACTOR;\n\tint shuffle_y=      \tSHUFFLE_Y * RESFACTOR;\n\tint repeat_x=       \tREPEAT_X * RESFACTOR;\n\tint repeat_y=       \tREPEAT_Y * RESFACTOR;\n\n\tint mslider_x=      \tMSLIDER_X * RESFACTOR;\n\tint mslider_y=      \tMSLIDER_Y * RESFACTOR;\n\tint mslider_w=      \tMSLIDER_W * RESFACTOR;\n\tint mslider_height= \tMSLIDER_HEIGHT * RESFACTOR;\n\n\tint fxslider_x=     \tFXSLIDER_X * RESFACTOR;\n\tint fxslider_y=     \tFXSLIDER_Y * RESFACTOR;\n\tint fxslider_w=     \tFXSLIDER_W * RESFACTOR;\n\tint fxslider_height=\tFXSLIDER_HEIGHT * RESFACTOR;\n\n\tint button_stop=    \tBUTTON_STOP;\n\tint button_play=    \tBUTTON_PLAY;\n\tint button_shuffle= \tBUTTON_SHUFFLE;\n\tint button_repeat=  \tBUTTON_REPEAT;\n\tint button_options= \tBUTTON_OPTIONS;\n\tint slider_music=   \tSLIDER_MUSIC;\n\tint slider_sound=   \tSLIDER_SOUND;\n\tint button_listbox= \tBUTTON_LISTBOX;\n\n\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n//\tThemeType theme;\n\n\t/*\n\t**\tList box that holds the score text strings.\n\t*/\n\tMusicListClass listbox(0, option_x+listbox_x, option_y+listbox_y, listbox_w, listbox_h);\n\n\t/*\n\t**\tReturn to options menu button.\n\t*/\n\tTextButtonClass returnto(BUTTON_OPTIONS, TXT_OK, TPF_BUTTON, option_x+button_x, option_y+button_y, button_width);\n//\tTextButtonClass returnto(BUTTON_OPTIONS, TXT_OPTIONS_MENU, TPF_BUTTON,\n\n\t/*\n\t**\tStop playing button.\n\t*/\n\tShapeButtonClass stopbtn(BUTTON_STOP, MFCD::Retrieve(\"BTN-ST.SHP\"), option_x+stop_x, option_y+stop_y);\n\n\t/*\n\t**\tStart playing button.\n\t*/\n\tShapeButtonClass playbtn(BUTTON_PLAY, MFCD::Retrieve(\"BTN-PL.SHP\"), option_x+play_x, option_y+play_y);\n\n\t/*\n\t**\tShuffle control.\n\t*/\n\tTextButtonClass shufflebtn(BUTTON_SHUFFLE, TXT_OFF, TPF_BUTTON, option_x+shuffle_x, option_y+shuffle_y, onoff_width);\n//\tTextButtonClass shufflebtn(BUTTON_SHUFFLE, TXT_OFF, TPF_BUTTON, option_x+shuffle_x, option_y+shuffle_y, ONOFF_WIDTH);\n\n\t/*\n\t**\tRepeat control.\n\t*/\n\tTextButtonClass repeatbtn(BUTTON_REPEAT, TXT_OFF, TPF_BUTTON, option_x+repeat_x, option_y+repeat_y, onoff_width);\n\n\t/*\n\t**\tMusic volume slider.\n\t*/\n\tSliderClass music(SLIDER_MUSIC, option_x+mslider_x, option_y+mslider_y, mslider_w, mslider_height, true);\n\n\t/*\n\t**\tSound volume slider.\n\t*/\n\tSliderClass sound(SLIDER_SOUND, option_x+fxslider_x, option_y+fxslider_y, fxslider_w, fxslider_height, true);\n\n\t/*\n\t**\tCauses left mouse clicks inside the dialog area, but not on any\n\t**\tparticular button, to be ignored.\n\t*/\n\tGadgetClass area(option_x, option_y, option_width, option_height, GadgetClass::LEFTPRESS);\n\n\t/*\n\t**\tCauses right clicks anywhere or left clicks outside of the dialog\n\t**\tbox area to be the same a clicking the return to game options button.\n\t*/\n\tControlClass ctrl(BUTTON_OPTIONS, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(), GadgetClass::RIGHTPRESS|GadgetClass::LEFTPRESS);\n\n\t/*\n\t**\tThe repeat and shuffle buttons are of the toggle type. They toggle\n\t**\tbetween saying \"on\" and \"off\".\n\t*/\n\tshufflebtn.IsToggleType = true;\n\tif (Options.IsScoreShuffle) {\n\t\tshufflebtn.Turn_On();\n\t} else {\n\t\tshufflebtn.Turn_Off();\n\t}\n\tshufflebtn.Set_Text(shufflebtn.IsOn ? TXT_ON : TXT_OFF);\n\n\trepeatbtn.IsToggleType = true;\n\tif (Options.IsScoreRepeat) {\n\t\trepeatbtn.Turn_On();\n\t} else {\n\t\trepeatbtn.Turn_Off();\n\t}\n\trepeatbtn.Set_Text(repeatbtn.IsOn ? TXT_ON : TXT_OFF);\n\n\t/*\n\t**\tSet the initial values of the sliders.\n\t*/\n\tmusic.Set_Maximum(255);\n\tmusic.Set_Thumb_Size(16);\n\tmusic.Set_Value(Options.ScoreVolume * 256);\n\tsound.Set_Maximum(255);\n\tsound.Set_Thumb_Size(16);\n\tsound.Set_Value(Options.Volume * 256);\n\n\t/*\n\t**\tSet up the window.  Window x-coords are in bytes not pixels.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\n\t/*\n\t**\tCreate Buttons.\n\t*/\n\tGadgetClass * optionsbtn = &returnto;\n\tlistbox.Add_Tail(*optionsbtn);\n\tstopbtn.Add_Tail(*optionsbtn);\n\tplaybtn.Add_Tail(*optionsbtn);\n\tshufflebtn.Add_Tail(*optionsbtn);\n\trepeatbtn.Add_Tail(*optionsbtn);\n\tmusic.Add_Tail(*optionsbtn);\n\tsound.Add_Tail(*optionsbtn);\n\tarea.Add_Tail(*optionsbtn);\n\tctrl.Add_Tail(*optionsbtn);\n\n\t/*\n\t**\tAdd all the themes to the list box. The list box entries are constructed\n\t**\tand then stored into allocated EMS memory blocks.\n\t*/\n\tfor (ThemeType index = THEME_FIRST; index < Theme.Max_Themes(); index++) {\n\t\tif (Theme.Is_Allowed(index)) {\n\t\t\tchar buffer[100];\n\t\t\tint length = Theme.Track_Length(index);\n\t\t\tchar const * fullname = Theme.Full_Name(index);\n\n\t\t\tvoid * ptr = new char [sizeof(buffer)];\n\t\t\tif (ptr) {\n\t\t\t\tsprintf((char *)ptr, \"%cTrack %d\\t%d:%02d\\t%s\", index, listbox.Count()+1, length / 60, length % 60, fullname);\n\t\t\t\tlistbox.Add_Item((char const *)ptr);\n\t\t\t}\n\n\t\t\tif (Theme.What_Is_Playing() == index) {\n\t\t\t\tlistbox.Set_Selected_Index(listbox.Count()-1);\n\t\t\t}\n\t\t}\n\t}\n\tstatic int _tabs[] = {\n\t\t55 * RESFACTOR, 72 * RESFACTOR, 90 * RESFACTOR\n\t};\n\tlistbox.Set_Tabs(_tabs);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tbool display = true;\n\tbool process = true;\n\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tif (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\t#ifdef WIN32\n\t\t/*\n\t\t** If we have just received input focus again after running in the background then\n\t\t** we need to redraw.\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tdisplay = true;\n\t\t}\n\t\t#endif\n\t\t/*\n\t\t**\tRefresh display if needed.\n\t\t*/\n\t\tif (display) {\n\n\t\t\tHide_Mouse();\n\n\t\t\t/*\n\t\t\t**\tDraw the background.\n\t\t\t*/\n\t\t\tDialog_Box(option_x, option_y, option_width, option_height);\n\n\t\t\tDraw_Caption(TXT_SOUND_CONTROLS, option_x, option_y, option_width);\n\n\t\t\t/*\n\t\t\t** Draw the Music, Speech & Sound titles.\n\t\t\t*/\n\t\t\tFancy_Text_Print(TXT_MUSIC_VOLUME, option_x+mslider_x-(5 * RESFACTOR), option_y+mslider_y-(2 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\t\t\tFancy_Text_Print(TXT_SOUND_VOLUME, option_x+fxslider_x-(5 * RESFACTOR), option_y+fxslider_y-(2 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n#if defined(GERMAN) || defined(FRENCH)\n\t\t\tFancy_Text_Print(TXT_SHUFFLE, option_x+4+shuffle_x-(5 * RESFACTOR), option_y+shuffle_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n#else\n\t\t\tFancy_Text_Print(TXT_SHUFFLE, option_x+shuffle_x-(5 * RESFACTOR), option_y+shuffle_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n#endif\n\t\t\tFancy_Text_Print(TXT_REPEAT, option_x+repeat_x-(5 * RESFACTOR), option_y+repeat_y+(1 * RESFACTOR), scheme, TBLACK, TPF_TEXT|TPF_RIGHT);\n\n\t\t\toptionsbtn->Draw_All();\n\t\t\tShow_Mouse();\n\t\t\tdisplay = false;\n\t\t}\n\n\t\t/*\n\t\t**\tGet user input.\n\t\t*/\n\t\tKeyNumType input = optionsbtn->Input();\n\n\t\t/*\n\t\t**\tProcess Input.\n\t\t*/\n\t\tswitch (input) {\n\n\t\t\tcase KN_ESC:\n\t\t\tcase BUTTON_OPTIONS|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tControl music volume.\n\t\t\t*/\n\t\t\tcase SLIDER_MUSIC|KN_BUTTON:\n\t\t\t\tOptions.Set_Score_Volume(fixed(music.Get_Value(), 256), true);\n#ifdef FIXIT_VERSION_3\n\t\t\t\tif( Session.Type != GAME_NORMAL )\n\t\t\t\t\tOptions.MultiScoreVolume = Options.ScoreVolume;\n#endif\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tControl sound volume.\n\t\t\t*/\n\t\t\tcase SLIDER_SOUND|KN_BUTTON:\n\t\t\t\tOptions.Set_Sound_Volume(fixed(sound.Get_Value(), 256), true);\n\t\t\t\tbreak;\n\n\t\t\tcase BUTTON_LISTBOX|KN_BUTTON:\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tStop all themes from playing.\n\t\t\t*/\n\t\t\tcase BUTTON_STOP|KN_BUTTON:\n\t\t\t\tTheme.Stop();\n\t\t\t\tTheme.Queue_Song(THEME_QUIET);\n//\t\t\t\tTheme.Queue_Song(THEME_NONE);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tStart the currently selected theme to play.\n\t\t\t*/\n\t\t\tcase KN_SPACE:\n\t\t\tcase BUTTON_PLAY|KN_BUTTON:\n\t\t\t\tTheme.Queue_Song( (ThemeType)*((unsigned char *)listbox.Current_Item()) );\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tToggle the shuffle button.\n\t\t\t*/\n\t\t\tcase BUTTON_SHUFFLE|KN_BUTTON:\n\t\t\t\tshufflebtn.Set_Text(shufflebtn.IsOn ? TXT_ON : TXT_OFF);\n\t\t\t\tOptions.Set_Shuffle(shufflebtn.IsOn);\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t**\tToggle the repeat button.\n\t\t\t*/\n\t\t\tcase BUTTON_REPEAT|KN_BUTTON:\n\t\t\t\trepeatbtn.Set_Text(repeatbtn.IsOn ? TXT_ON : TXT_OFF);\n\t\t\t\tOptions.Set_Repeat(repeatbtn.IsOn);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t**\tIf the score volume was turned all the way down, then actually\n\t**\tstop the scores from being played.\n\t*/\n\tif (Options.ScoreVolume == 0) {\n\t\tTheme.Stop();\n\t}\n\n\t/*\n\t**\tFree the items from the list box.\n\t*/\n\twhile (listbox.Count()) {\n\t\tchar const * ptr = listbox.Get_Item(0);\n\t\tlistbox.Remove_Item(ptr);\n\t\tdelete [] (void*)ptr;\n\t}\n}\n\n\n/***********************************************************************************************\n * MusicListClass::Draw_Entry -- Draw the score line in a list box.                            *\n *                                                                                             *\n *    This routine will display the score line in a list box. It overrides the list box        *\n *    handler for line drawing.                                                                *\n *                                                                                             *\n * INPUT:   index    -- The index within the list box that is being drawn.                     *\n *                                                                                             *\n *          x,y      -- The pixel coordinates of the upper left position of the line.          *\n *                                                                                             *\n *          width    -- The width of the line that drawing is allowed to use.                  *\n *                                                                                             *\n *          selected-- Is the current line selected?                                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/22/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid MusicListClass::Draw_Entry(int index, int x, int y, int width, int selected)\n{\n\tRemapControlType * scheme = GadgetClass::Get_Color_Scheme();\n\n\tif (TextFlags & TPF_6PT_GRAD) {\n\t\tTextPrintType flags = TextFlags;\n\n\t\tif (selected) {\n\t\t\tflags = flags | TPF_BRIGHT_COLOR;\n\t\t\tLogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1,\n\t\t\t\tGadgetClass::Get_Color_Scheme()->Shadow);\n\t\t} else {\n\t\t\tif (!(flags & TPF_USE_GRAD_PAL)) {\n\t\t\t\tflags = flags | TPF_MEDIUM_COLOR;\n\t\t\t}\n\t\t}\n\n\t\tConquer_Clip_Text_Print((char *)List[index] + 1, x, y, scheme, TBLACK, flags, width, Tabs);\n\n\t} else {\n\t\tConquer_Clip_Text_Print((char *)List[index] + 1, x, y,\n\t\t\t(selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, TextFlags, width, Tabs);\n\t}\n}\n"
  },
  {
    "path": "REDALERT/SOUNDDLG.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SOUNDDLG.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : OPTIONS.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 8, 1994                                                 *\n *                                                                                             *\n *                  Last Update : June 8, 1994   [JLB]                                         *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SOUNDDLG_H\n#define SOUNDDLG_H\n\n#include \"gadget.h\"\n\nclass SoundControlsClass\n{\n\tenum SoundControlsClassEnums {\n#ifdef FRENCH\n\t\tOPTION_WIDTH=308,\n#else\n\t\tOPTION_WIDTH=292,\n#endif\n\t\tOPTION_HEIGHT=146,\n\n\t\tOPTION_X=((320 - OPTION_WIDTH) / 2),\n\t\tOPTION_Y=(200 - OPTION_HEIGHT) / 2,\n\n\t\tLISTBOX_X=17,\n\t\tLISTBOX_Y=54,\n\t\tLISTBOX_W=OPTION_WIDTH-(LISTBOX_X*2),\n\t\tLISTBOX_H=72,\n\n\t\tBUTTON_WIDTH=70,\n\t\tBUTTON_X=OPTION_WIDTH-(BUTTON_WIDTH+17),\t \t\t\t\t// Options button x pos\n\t\tBUTTON_Y=128, \t\t\t\t\t// Options button y pos\n\n\t\tSTOP_X=17,\t\t\t\t\t\t// Stop button X.\n\t\tSTOP_Y=128,\t\t\t\t\t\t//\tStop button Y.\n\n\t\tPLAY_X=35,\n\t\tPLAY_Y=128,\n\n\t\tONOFF_WIDTH=25,\n#ifdef GERMAN\n\t\tSHUFFLE_X=79,//BGA:91,\n#else\n#ifdef FRENCH\n\t\tSHUFFLE_X=99,\n#else\n\t\tSHUFFLE_X=97,\n#endif\n#endif\n\t\tSHUFFLE_Y=128,\n\n#ifdef FRENCH\n\t\tREPEAT_X=169,\n#else\n\t\tREPEAT_X=164,\n#endif\n\t\tREPEAT_Y=128,\n\n\t\tMSLIDER_X=147,\n\t\tMSLIDER_Y=28,\n\t\tMSLIDER_W=108,\n\t\tMSLIDER_HEIGHT=5,\n\n\t\tFXSLIDER_X=147,\n\t\tFXSLIDER_Y=40,\n\t\tFXSLIDER_W=108,\n\t\tFXSLIDER_HEIGHT=5,\n\n\t\tBUTTON_STOP = 605,\n\t\tBUTTON_PLAY,\n\t\tBUTTON_SHUFFLE,\n\t\tBUTTON_REPEAT,\n\t\tBUTTON_OPTIONS,\n\t\tSLIDER_MUSIC,\n\t\tSLIDER_SOUND,\n\t\tBUTTON_LISTBOX,\n\t};\n\n\tpublic:\n\t\tSoundControlsClass(void) {}\n\t\tvoid Process(void);\n};\n\n#endif\n"
  },
  {
    "path": "REDALERT/SPECIAL.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SPECIAL.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SPECIAL.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 05/27/95                                                     *\n *                                                                                             *\n *                  Last Update : August 20, 1996 [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Fetch_Difficulty -- Fetches the difficulty setting desired.                               *\n *   Fetch_Password -- Prompts for a password entry from client.                               *\n *   PWEditClass::Draw_Text -- Draws password style obscured text.                             *\n *   Special_Dialog -- Handles the special options dialog.                                     *\n *   SpecialClass::Init -- Initialize the special class of options.                            *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n#ifdef WIN32\n#define\tOPTION_WIDTH\t236*2\n#define\tOPTION_HEIGHT\t162*2\n#define\tOPTION_X\t\t\t((640 - OPTION_WIDTH) / 2)\n#define\tOPTION_Y\t\t\t(400 - OPTION_HEIGHT) / 2\n#else\n#define\tOPTION_WIDTH\t236\n#define\tOPTION_HEIGHT\t162\n#define\tOPTION_X\t\t\t((320 - OPTION_WIDTH) / 2)\n#define\tOPTION_Y\t\t\t(200 - OPTION_HEIGHT) / 2\n#endif\n\n\n/***********************************************************************************************\n * SpecialClass::Init -- Initialize the special class of options.                              *\n *                                                                                             *\n *    This initialization function is required (as opposed to using a constructor) because     *\n *    the SpecialClass is declared as part of a union. A union cannot have a member with a     *\n *    constructor. Other than this anomoly, the function serves the same purpose as a          *\n *    normal constructor.                                                                      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/20/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SpecialClass::Init(void)\n{\n\tIsShadowGrow = false;\n\tIsSpeedBuild = false;\n\tIsFromInstall = false;\n\tIsCaptureTheFlag = false;\n\tIsInert = false;\n\tIsThreePoint = false;\n\tIsTGrowth = true;\n\tIsTSpread = true;\n\tUseMCVDeploy = false;\n\tIsMCVDeploy = false;\n\tIsEarlyWin = false;\n\tModernBalance = false;\n}\n\n\n/***********************************************************************************************\n * Special_Dialog -- Handles the special options dialog.                                       *\n *                                                                                             *\n *    This dialog is used when setting the special game options. It does not appear in the     *\n *    final version of the game.                                                               *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   09/21/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Special_Dialog(bool simple)\n{\n\tsimple;\n#if (0)//PG\n\tSpecialClass oldspecial = Special;\n\tGadgetClass * buttons = NULL;\n\tstatic struct {\n\t\tint Description;\n\t\tint Setting;\n\t\tCheckBoxClass * Button;\n\t} _options[] = {\n\t\t{TXT_THREE_POINT, 0, 0},\n\t\t{TXT_SPEED_BUILD, 0, 0},\n\t};\n\n\tTextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+15*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR);\n\tTextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-60*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR);\n\tbuttons = &ok;\n\tcancel.Add(*buttons);\n\n\tfor (int index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t_options[index].Button = new CheckBoxClass(100+index, OPTION_X+17*RESFACTOR, OPTION_Y+20*RESFACTOR+(index*10*RESFACTOR));\n\t\tif (_options[index].Button) {\n\t\t\t_options[index].Button->Add(*buttons);\n\n\t\t\tbool value = false;\n\t\t\tswitch (_options[index].Description) {\n\t\t\t\tcase TXT_THREE_POINT:\n\t\t\t\t\tvalue = Special.IsThreePoint;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TXT_SPEED_BUILD:\n\t\t\t\t\tvalue = Special.IsSpeedBuild;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t_options[index].Setting = value;\n\t\t\tif (value) {\n\t\t\t\t_options[index].Button->Turn_On();\n\t\t\t} else {\n\t\t\t\t_options[index].Button->Turn_Off();\n\t\t\t}\n\t\t}\n\t}\n\n\tMap.Override_Mouse_Shape(MOUSE_NORMAL);\n\tSet_Logic_Page(SeenBuff);\n\tbool recalc = true;\n\tbool display = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\tif (Session.Type == GAME_NORMAL) {\n\t\t\tCall_Back();\n\t\t} else {\n\t\t\tif (Main_Loop()) {\n\t\t\t\tprocess = false;\n\t\t\t}\n\t\t}\n\n\t\tif (display) {\n\t\t\tdisplay = false;\n\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT);\n\t\t\tDraw_Caption(TXT_SPECIAL_OPTIONS, OPTION_X, OPTION_Y, OPTION_WIDTH);\n\n\t\t\tfor (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t\t\tFancy_Text_Print(_options[index].Description, _options[index].Button->X+10*RESFACTOR, _options[index].Button->Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t\t}\n\t\t\tbuttons->Draw_All();\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\tKeyNumType input = buttons->Input();\n\t\tswitch (input) {\n\t\t\tcase KN_ESC:\n\t\t\tcase 200|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tfor (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) {\n\t\t\t\t\tbool setting = _options[index].Setting;\n\t\t\t\t\tswitch (_options[index].Description) {\n\t\t\t\t\t\tcase TXT_THREE_POINT:\n\t\t\t\t\t\t\toldspecial.IsThreePoint = setting;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TXT_SPEED_BUILD:\n\t\t\t\t\t\t\toldspecial.IsSpeedBuild = setting;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!simple) {\n\t\t\t\t\tOutList.Add(EventClass(oldspecial));\n\t\t\t\t} else {\n\t\t\t\t\tSpecial = oldspecial;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 201|KN_BUTTON:\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase KN_NONE:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tindex = (input & ~KN_BUTTON) - 100;\n\t\t\t\tif ((unsigned)index < sizeof(_options)/sizeof(_options[0])) {\n\t\t\t\t\t_options[index].Setting = _options[index].Button->IsOn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!simple) {\n\t\tMap.Revert_Mouse_Shape();\n\t\tHidPage.Clear();\n\t\tMap.Flag_To_Redraw(true);\n\t\tMap.Render();\n\t}\n#endif\n}\n\n\n/*\n**\tDerived from the edit class, this class allows entry of passwords style text\n**\tas an edit box. This style is characterized by \"*\" being displayed for every\n**\treal character entered.\n*/\nclass PWEditClass : public EditClass\n{\n\tpublic:\n\t\tPWEditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1) :\n\t\t\tEditClass(id, text, max_len, flags, x, y, w, h, ALPHANUMERIC) {};\n\n\tprotected:\n\t\tvirtual void Draw_Text(char const * text);\n};\n\n\n/***********************************************************************************************\n * PWEditClass::Draw_Text -- Draws password style obscured text.                               *\n *                                                                                             *\n *    This routine is used by the password style edit box in order to display the entered      *\n *    text. The text will be displayed as asterisks instead of the actual characters the       *\n *    edit box may contain. This is necessary to obscure the password entry from glancing      *\n *    eyes.                                                                                    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text that is to be rendered.                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid PWEditClass::Draw_Text(char const * text)\n{\n\tchar buffer[80];\n\n\tmemset(buffer, '\\0', sizeof(buffer));\n\tmemset(buffer, '*', strlen(text));\n\n\tif (FontPtr == GradFont6Ptr) {\n\t\tTextPrintType flags;\n\n\t\tif (Has_Focus()) {\n\t\t\tflags = TPF_BRIGHT_COLOR;\n\t\t} else {\n\t\t\tflags = (TextPrintType)0;\n\t\t}\n\n\t\tConquer_Clip_Text_Print(buffer, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);\n\n\t\tif (Has_Focus() && (int)strlen(buffer) < MaxLength) {\n\t\t\tConquer_Clip_Text_Print( \"_\", X+1+String_Pixel_Width(buffer), Y+1, Color, TBLACK, TextFlags | flags);\n\t\t}\n\t} else {\n\t\tConquer_Clip_Text_Print(buffer, X+1, Y+1, Has_Focus() ?\n\t\t\t&ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY],\n\t\t\tTBLACK, TextFlags, Width-2);\n\n\t\tif (Has_Focus() && (int)strlen(buffer) < MaxLength) {\n\t\t\tConquer_Clip_Text_Print(\"_\", X+1+String_Pixel_Width(buffer), Y+1,\n\t\t\t\t&ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TextFlags);\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Fetch_Password -- Prompts for a password entry from client.                                 *\n *                                                                                             *\n *    This routine will prompt for and return a password entry from the player.                *\n *                                                                                             *\n * INPUT:   caption  -- The  caption to use for the top of the prompt dialog.                  *\n *                                                                                             *\n *          message  -- The body of the message to display in the dialog.                      *\n *                                                                                             *\n *          btext    -- The button text to use to finish the dialog box entry.                 *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the password text entered. This pointer is valid         *\n *          only until the next time that this routine is called.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#define BUFFSIZE (511)\nchar const * Fetch_Password(int caption, int message, int btext)\n{\n\tchar buffer[BUFFSIZE];\n\tbool process;\t\t\t\t\t\t\t\t// loop while true\n\tKeyNumType input;\t\t\t\t\t\t\t// user input\n\tbool pressed;\n\tint curbutton;\n\tTextButtonClass ok;\n\n\tif (btext == TXT_NONE) btext = TXT_OK;\n\t\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\n\t/*\n\t**\tExamine the optional button parameters. Fetch the width and starting\n\t**\tcharacters for each.\n\t*/\n\tint bwidth, bheight;\t\t\t\t// button width and height\n\n\t/*\n\t**\tBuild the button list.\n\t*/\n\tbheight = FontHeight + FontYSpacing + 2*RESFACTOR;\n\tbwidth = max((String_Pixel_Width(Text_String(btext)) + 8*RESFACTOR), 30*RESFACTOR);\n\n\t/*\n\t**\tDetermine the dimensions of the text to be used for the dialog box.\n\t**\tThese dimensions will control how the dialog box looks.\n\t*/\n\tbuffer[BUFFSIZE-1] = 0;\n\tstrncpy(buffer, Text_String(message), BUFFSIZE-1);\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, 255, width, height);\n\n\twidth = max(width, 50*RESFACTOR);\n\twidth += 40*RESFACTOR;\n\theight += (60+25)*RESFACTOR;\n\n\tint x = (SeenBuff.Get_Width() - width) / 2;\n\tint y = (SeenBuff.Get_Height() - height) / 2;\n\n\t/*\n\t**\tCreate the \"ok\" and password edit buttons.\n\t*/\n\tTextButtonClass button1(1, btext, TPF_BUTTON,\n\t\tx + ((width - bwidth) >> 1), y + height - (bheight + 5*RESFACTOR), bwidth);\n\n\tstatic char pbuffer[45];\n\tmemset(pbuffer, '\\0', sizeof(pbuffer));\n\tint editx = x+26*RESFACTOR;\n\tint editwidth = (SeenBuff.Get_Width()/2 - editx) * 2;\n\tPWEditClass button2(2, &pbuffer[0], sizeof(pbuffer), TPF_6PT_GRAD|TPF_NOSHADOW, editx, (y+height)-35*RESFACTOR, editwidth, 10*RESFACTOR);\n\n\tTextButtonClass * buttonlist = 0;\n\tcurbutton = 0;\n\n\t/*\n\t**\tAdd and initialize the buttons to the button list.\n\t*/\n\tbuttonlist = &button1;\n\tbutton2.Add(*buttonlist);\n\n\t/*\n\t**\tDraw the background of the dialog.\n\t*/\n\tHide_Mouse();\n\tSet_Logic_Page(SeenBuff);\n\tDialog_Box(x, y, width, height);\n\tDraw_Caption(caption, x, y, width);\n\n\t/*\n\t**\tDraw the body of the message box.\n\t*/\n\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\n\t/*\n\t**\tRedraw the buttons.\n\t*/\n\tif (buttonlist) {\n\t\tbuttonlist->Draw_All();\n\t}\n\tShow_Mouse();\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tprocess = true;\n\tpressed = false;\n\tbool first = true;\n\twhile (process) {\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n#ifdef WIN32\n\t\t/*\n\t\t** Handle possible surface loss due to a focus switch\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tprocess = false;\n\t\t\tbreak;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tFetch and process input.\n\t\t*/\n\t\tinput = buttonlist->Input();\n\t\tif (first) {\n\t\t\tbutton2.Set_Focus();\n\t\t\tbutton2.Flag_To_Redraw();\n\t\t\tfirst = false;\n\t\t}\n\t\tswitch (input) {\n\t\t\tcase (1|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_ESC):\n\t\t\tcase (2|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tcase (KN_RETURN):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(pbuffer);\n}\n\n\n/***********************************************************************************************\n * Fetch_Difficulty -- Fetches the difficulty setting desired.                                 *\n *                                                                                             *\n *    This will display a dialog box that requests the player to specify a difficulty          *\n *    setting.                                                                                 *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a difficulty setting of 0 for easiest and 4 for hardest.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/13/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\nint Fetch_Difficulty(bool amath)\n#else\nint Fetch_Difficulty(void)\n#endif\n{\n\tint const w = 250 * RESFACTOR;\n\tint const h = 80 * RESFACTOR;\n\tint const x = ((320 * RESFACTOR)/2) - w/2;\n\tint const y = ((200 * RESFACTOR)/2) - h/2;\n\tint const bwidth = 30 * RESFACTOR;\n\n\t/*\n\t**\tFill the description buffer with the description text. Break\n\t**\tthe text into appropriate spacing.\n\t*/\n\tchar buffer[512];\n\tstrncpy(buffer, Text_String(TXT_DIFFICULTY), sizeof(buffer)-1);\n\tbuffer[sizeof(buffer)-1] = '\\0';\n#ifdef FIXIT_CSII\t//\tchecked - ajw 9/28/98\n// If it's an aftermath mission, trim the sentence to get rid of the campaign stuff.\n\tif (amath) {\n\t\tint index=0;\n\t\twhile (buffer[index] && buffer[index]!='.') index++;\n\t\tif (buffer[index]=='.') {\n\t\t\tbuffer[index+1]=0;\n\t\t}\n\t}\n#endif\n\t//PG_TO_FIX\n\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\tint width;\n\tint height;\n\tFormat_Window_String(buffer, w-60*RESFACTOR, width, height);\n\n\t/*\n\t**\tCreate the OK button.\n\t*/\n\tTextButtonClass okbutton(1, TXT_OK, TPF_BUTTON, (x+w) - (bwidth+20*RESFACTOR) , (y+h) - (18*RESFACTOR), bwidth);\n\tGadgetClass * buttonlist = &okbutton;\n\n\t/*\n\t**\tCreate the slider button.\n\t*/\n\tSliderClass slider(2, x+20*RESFACTOR, y+h - 29*RESFACTOR, w - 40*RESFACTOR, 8*RESFACTOR, true);\n\tif (Rule.IsFineDifficulty) {\n\t\tslider.Set_Maximum(5);\n\t\tslider.Set_Value(2);\n\t} else {\n\t\tslider.Set_Maximum(3);\n\t\tslider.Set_Value(1);\n\t}\n\tslider.Add(*buttonlist);\n\n\t/*\n\t**\tMain Processing Loop.\n\t*/\n\tSet_Logic_Page(SeenBuff);\n\tbool redraw = true;\n\tbool process = true;\n\twhile (process) {\n\n\t\tif (redraw) {\n\t\t\tredraw = false;\n\n\t\t\t/*\n\t\t\t**\tDraw the background of the dialog.\n\t\t\t*/\n\t\t\tHide_Mouse();\n\t\t\tDialog_Box(x, y, w, h);\n\n\t\t\t/*\n\t\t\t**\tDraw the body of the message.\n\t\t\t*/\n//\t\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);\n\t\t\tFancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW);\n\n\t\t\t/*\n\t\t\t**\tDisplay the descripton of the slider range.\n\t\t\t*/\n\t\t\tFancy_Text_Print(TXT_HARD, slider.X+slider.Width, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_RIGHT|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\t\t\tFancy_Text_Print(TXT_EASY, slider.X, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_DROPSHADOW);\n\t\t\tFancy_Text_Print(TXT_NORMAL, slider.X + (slider.Width/2), slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_DROPSHADOW);\n\n\t\t\t/*\n\t\t\t**\tRedraw the buttons.\n\t\t\t*/\n\t\t\tif (buttonlist) {\n\t\t\t\tbuttonlist->Draw_All();\n\t\t\t}\n\t\t\tShow_Mouse();\n\t\t}\n\n\t\t/*\n\t\t**\tInvoke game callback.\n\t\t*/\n\t\tCall_Back();\n\n#ifdef WIN32\n\t\t/*\n\t\t** Handle possible surface loss due to a focus switch\n\t\t*/\n\t\tif (AllSurfaces.SurfacesRestored) {\n\t\t\tAllSurfaces.SurfacesRestored=FALSE;\n\t\t\tredraw = true;\n\t\t\tcontinue;\n\t\t}\n#endif\t//WIN32\n\n\t\t/*\n\t\t**\tFetch and process input.\n\t\t*/\n\t\tKeyNumType input = buttonlist->Input();\n\n\t\tswitch (input) {\n\t\t\tcase KN_RETURN:\n\t\t\tcase (1|BUTTON_FLAG):\n\t\t\t\tprocess = false;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn(slider.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2));\n}\n"
  },
  {
    "path": "REDALERT/SPECIAL.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SPECIAL.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SPECIAL.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 02/27/95                                                     *\n *                                                                                             *\n *                  Last Update : February 27, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef SPECIAL_H\n#define SPECIAL_H\n\nclass SpecialClass\n{\n\tpublic:\n\n\t\t/*\n\t\t**\tThis initializes all members just like a constructor. A constructor\n\t\t**\tcannot be used for this class because it is part of a union.\n\t\t*/\n\t\tvoid Init(void);\n\n\t\t/*\n\t\t**\tIf the shroud should regenerated, then this flag will be true.\n\t\t*/\n\t\tunsigned IsShadowGrow:1;\n\n\t\t/*\n\t\t**\tControls the speedy build option -- used for testing.\n\t\t*/\n\t\tunsigned IsSpeedBuild:1;\n\n\t\t/*\n\t\t** If from install, then play the special installation movie and\n\t\t** skip asking them what type of game they want to play.\n\t\t*/\n\t\tunsigned IsFromInstall:1;\n\n\t\t/*\n\t\t**\tIf capture the flag mode is on, this flag will be true. With this\n\t\t**\tflag enabled, then the flag is initially placed at the start of\n\t\t**\tthe scenario.\n\t\t*/\n\t\tunsigned IsCaptureTheFlag:1;\n\n\t\t/*\n\t\t**\tThis flags controls whether weapons are inert. An inert weapon doesn't do any\n\t\t**\tdamage. Effectively, if this is true, then the units never die.\n\t\t*/\n\t\tunsigned IsInert:1;\n\n\t\t/*\n\t\t**\tIf wheeled vehicles should do a 3-point turn when rotating in place, then\n\t\t**\tthis flag is true.\n\t\t*/\n\t\tunsigned IsThreePoint:1;\n\n\t\t/*\n\t\t**\tIf Tiberium is allowed to spread and grow, then these flags will be true.\n\t\t**\tThese are duplicated from the rules.ini file and also controlled by the\n\t\t**\tmultiplayer dialog box.\n\t\t*/\n\t\tunsigned IsTGrowth:1;\n\t\tunsigned IsTSpread:1;\n\n\t\t/*\n\t\t** Flag that we were spawned from WChat.\n\t\t*/\n\t\tunsigned IsFromWChat:1;\n\n\t\t/*\n\t\t**\tIf this flag is true, then the construction yard can undeploy back into an MCV.\n\t\t**\tUsed to override the rules setting.\n\t\t*/\n\t\tunsigned UseMCVDeploy:1;\n\t\tunsigned IsMCVDeploy:1;\n\n\t\t/*\n\t\t** New anti-griefing early win mode. ST - 1/31/2020 3:42PM\n\t\t*/\n\t\tunsigned IsEarlyWin:1;\n\n\t\t/*\n\t\t** New modern balance setting.\n\t\t*/\n\t\tunsigned ModernBalance:1;\n\n\t\t/*\n\t\t** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load\n\t\t*/\n\t\t// MBL 07.21.2020 - https://jaas.ea.com/browse/TDRA-7537\n\t\t// Loading save files from Live and July Patch 3 Beta versions results in a crash\n\t\t// Fixes issue from Change 738397 2020/07/17 14:06:03\n\t\t// \n\t\t// unsigned char SaveLoadPadding[128]; // Note: Never changed to 127 like TD did\n\t\t//\n\t\t// unsigned char SaveLoadPadding[124]; // Trying 124 like we did with TD - Failed\n\t\tunsigned char SaveLoadPadding[128]; \t// Works with With last weeks saves (7/16/2020) and newest saves; Skyler says go with this.\n};\n\n\n#endif"
  },
  {
    "path": "REDALERT/SPRITE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SPRITE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/**********************************************************************\n\n\tSprite.cpp\n\n\tDec 28,1995\n\n\tGraphicBufferClass member functions for blitting, scaling,\n\tand rotating bitmaps\n\n**********************************************************************/\n\n#ifndef WIN32\nclass BitmapClass\n{\n\tpublic:\n\t\tBitmapClass(int w, int h, unsigned char * data) :\n\t\t\tWidth(w), Height(h), Data(data) {};\n\n\t\tint Width;\n\t\tint Height;\n\t\tunsigned char * Data;\n};\n\nclass TPoint2D\n{\n\tpublic:\n\t\tTPoint2D(int xx, int yy) : x(xx), y(yy) {};\n\t\tTPoint2D(void) : x(0), y(0) {};\n\n\t\tint x;\n\t\tint y;\n};\n#endif\n\n\n//#include\t\"function.h\"\n#define FILE_H\n#define RAWFILE_H\n#define WWMEM_H\n#define WWFILE_Hx\n#include\t<wwlib32.h>\n#include <stdio.h>\n//#include \"gbuffer.h\"\n//#include \"math.h\"\n\n\nlong _SineTab[256] = {\n0 ,6 ,12 , 18 , 25 , 31 , 37 , 43 , 49 , 56 , 62 , 68 , 74 , 80 , 86 ,\n92 , 97 , 103 , 109 , 115 , 120 , 126 , 131 , 136 , 142 , 147 , 152 ,\n157 , 162 , 167 , 171 , 176 , 180 , 185 , 189 , 193 , 197 , 201 , 205 ,\n209 , 212 , 216 , 219 , 222 , 225 , 228 , 231 , 233 , 236 , 238 , 240 ,\n243 , 244 , 246 , 248 , 249 , 251 , 252 , 253 , 254 , 254 , 255 , 255 ,\n255 , 255 , 255 , 255 , 255 , 254 , 254 , 253 , 252 , 251 , 249 , 248 ,\n246 , 245 , 243 , 241 , 238 , 236 , 234 , 231 , 228 , 225 , 222 , 219 ,\n216 , 213 , 209 , 205 , 201 , 198 , 194 , 189 , 185 , 181 , 176 , 172 ,\n167 , 162 , 157 , 152 , 147 , 142 , 137 , 131 , 126 , 120 , 115 , 109 ,\n104 , 98 , 92 , 86 , 80 , 74 , 68 , 62 , 56 , 50 , 44 , 37 , 31 , 25 ,\n19 , 12 , 6 , 0 , -5 , -12 , -18 , -24 , -30 , -37 , -43 , -49 , -55 ,\n-61 , -67 , -73 , -79 , -85 , -91 , -97 , -103 , -109 , -114 , -120 ,\n-125 , -131 , -136 , -141 , -147 , -152 , -157 , -162 , -166 , -171 ,\n-176 , -180 , -185 , -189 , -193 , -197 , -201 , -205 , -208 , -212 ,\n-215 , -219 , -222 , -225 , -228 , -231 , -233 , -236 , -238 , -240 ,\n-242 , -244 , -246 , -248 , -249 , -250 , -252 , -253 , -254 , -254 ,\n-255 , -255 , -255 , -255 , -255 , -255 , -255 , -254 , -254 , -253 ,\n-252 , -251 , -249 , -248 , -246 , -245 , -243 , -241 , -239 , -236 ,\n-234 , -231 , -228 , -226 , -223 , -219 , -216 , -213 , -209 , -206 ,\n-202 , -198 , -194 , -190 , -185 , -181 , -177 , -172 , -167 , -162 ,\n-158 , -153 , -148 , -142 , -137 , -132 , -126 , -121 , -115 , -110 ,\n-104 , -98 , -92 , -86 , -81 , -75 , -69 , -62 , -56 , -50 , -44 ,\n-38 , -32 , -25 , -19 , -13 , -7 ,\n};\n\nlong _CosineTab[256] = {\n256 , 255 , 255 , 255 , 254 , 254 , 253 , 252 , 251 , 249 , 248 , 246 ,\n244 , 243 , 241 , 238 , 236 , 234 , 231 , 228 , 225 , 222 , 219 , 216 ,\n212 , 209 , 205 , 201 , 197 , 193 , 189 , 185 , 181 , 176 , 171 , 167 ,\n162 , 157 , 152 , 147 , 142 , 137 , 131 , 126 , 120 , 115 , 109 , 103 ,\n98 , 92 , 86 , 80 , 74 , 68 , 62 , 56 , 50 , 43 , 37 , 31 , 25 , 19 ,\n12 , 6 , 0 , -6 , -12 , -18 , -24 , -31 , -37 , -43 , -49 , -55 , -61 ,\n-68 , -74 , -80 , -86 , -91 , -97 , -103 , -109 , -114 , -120 , -125 , -131 ,\n-136 , -141 , -147 , -152 , -157 , -162 , -166 , -171 , -176 , -180 ,\n-185 , -189 , -193 , -197 , -201 , -205 , -209 , -212 , -216 , -219 , -222 ,\n-225 , -228 , -231 , -233 , -236 , -238 , -240 , -242 , -244 , -246 ,\n-248 , -249 , -251 , -252 , -253 , -254 , -254 , -255 , -255 , -255 ,\n-255 , -255 , -255 , -255 , -254 , -254 , -253 , -252 , -251 , -249 , -248 ,\n-246 , -245 , -243 , -241 , -239 , -236 , -234 , -231 , -228 , -225 ,\n-222 , -219 , -216 , -213 , -209 , -205 , -202 , -198 , -194 , -190 , -185 ,\n-181 , -176 , -172 , -167 , -162 , -157 , -152 , -147 , -142 , -137 , -132 ,\n-126 , -121 , -115 , -109 , -104 , -98 , -92 , -86 , -80 , -74 , -68 ,\n-62 , -56 , -50 , -44 , -38 , -31 , -25 , -19 , -13 , -6 , 0 , 5 , 11 ,\n18 , 24 , 30 , 36 , 43 , 49 , 55 , 61 , 67 , 73 , 79 , 85 , 91 , 97 , 103 ,\n108 , 114 , 120 , 125 , 131 , 136 , 141 , 146 , 151 , 156 , 161 , 166 ,\n171 , 176 , 180 , 184 , 189 , 193 , 197 , 201 , 205 , 208 , 212 , 215 ,\n219 , 222 , 225 , 228 , 231 , 233 , 236 , 238 , 240 , 242 , 244 , 246 ,\n248 , 249 , 250 , 252 , 253 , 253 , 254 , 255 , 255 , 255 ,\n};\n\n\n\n/***************************************************************\n*\n*\tScale_Rotate\n*\n*\tFUNCTION:\n*\n*\tUsing Bi-Linear Interpolation, draws a scaled and rotated\n*\tbitmap onto the buffer.  No clipping is performed so beware.\n*\n*\tINPUTS\n*\n*\tbmp\t\t- bitmap to draw\n*\tpt\t\t\t- desired position of the center\n*\tscale\t\t- 24.8 fixed point scale factor\n*\tangle\t\t- 8bit angle (0=0deg, 255=360deg)\n*\n***************************************************************/\n\nvoid GraphicBufferClass::Scale_Rotate(BitmapClass &bmp,TPoint2D const &pt,long scale,unsigned char angle)\n{\n\tunsigned int scrpos;\n\tunsigned int temp;\n\n\tint i,j;\t\t\t// counter vars\n\tint pxerror\t=0;\t\t// these three vars will be used in an\n\tint pyerror\t=0;\t\t// integer difference alg to keep track\n\tint pixpos\t=0;\t\t// of what pixel to draw.\n\tunsigned char pixel;\n\n\tTPoint2D p0;\t// \"upper left\" corner of the rectangle\n\tTPoint2D p1;\t// \"upper right\" corner of the rectangle\n\tTPoint2D p2;\t// \"lower left\" corner of the rectangle\n\n\t/*-------------------------------------------------\n\t\tCompute three corner points of the rectangle\n\t-------------------------------------------------*/\n\t{\n\t\tangle &= 0x0FF;\n\t\tlong c = _CosineTab[angle];\n \t\tlong s = _SineTab[angle];\n\t\tlong W = (scale*bmp.Width)>>1;\n\t\tlong L = (scale*bmp.Height)>>1;\n\n\t\tp0.x = (pt.x + ((( (L*c) >> 8)-((W*s) >> 8)) >> 8));\n\t\tp0.y = (pt.y + (((-(L*s) >> 8)-((W*c) >> 8)) >> 8));\n\t\tp1.x = (pt.x + ((( (L*c) >> 8)+((W*s) >> 8)) >> 8));\n\t\tp1.y = (pt.y + (((-(L*s) >> 8)+((W*c) >> 8)) >> 8));\n\t\tp2.x = (pt.x + (((-(L*c) >> 8)-((W*s) >> 8)) >> 8));\n\t\tp2.y = (pt.y + ((( (L*s) >> 8)-((W*c) >> 8)) >> 8));\n\t}\n\n\t/*-----------------------------------\n\t\tInitialize Breshnam constants\n\t-----------------------------------*/\n\n\t// This breshnam line goes across the FRONT of the rectangle\n\t// In the bitmap, this will step from left to right\n\n\tint f_deltax\t=(p1.x-p0.x);\n\tint f_deltay\t=(p1.y-p0.y);\n\tint f_error\t\t=0;\n\tint f_xstep\t\t=1;\n\tint f_ystep\t\t=Width;\n\n\t// This breshnam line goes down the SIDE of the rectangle\n\t// In the bitmap, this line will step from top to bottom\n\n\tint s_deltax\t=(p2.x-p0.x);\n\tint s_deltay\t=(p2.y-p0.y);\n\tint s_error\t\t=0;\n\tint s_xstep\t\t=1;\n\tint s_ystep\t\t=Width;\n\n\t/*--------------------------------\n\t\tfixup deltas and step values\n\t--------------------------------*/\n\n\tif (f_deltay<0) {\n\t\tf_deltay=-f_deltay;\n\t\tf_ystep=-Width;\n\t};\n\n\tif (f_deltax<0) {\n\t\tf_deltax=-f_deltax;\n\t\tf_xstep=-1;\n\t};\n\n\tif (s_deltay<0) {\n\t\ts_deltay=-s_deltay;\n\t\ts_ystep=-Width;\n\t};\n\n\tif (s_deltax<0) {\n\t\ts_deltax=-s_deltax;\n\t\ts_xstep=-1;\n\t};\n\n\tscrpos=p0.x+Width*p0.y; \t//address of initial screen pos.\n\ttemp=scrpos;\n\n\t/*---------------------------------------------------------------------\n\t\tNow all of the differences, errors, and steps are set up so we can\n\t\tbegin drawing the bitmap...\n\n\t\tThere are two cases here,\n\t\t1 - the \"Front\" line has a slope of <  1.0 (45 degrees)\n\t\t2 - the \"Front\" line has a slope of >= 1.0\n\n\t\tFor case 1, we step along the X direction, for case 2, step in y\n\t---------------------------------------------------------------------*/\n\n\tif (f_deltax>f_deltay) {\t\t//CASE 1, step front in X, side in Y\n\n\t\t// outer loop steps from top to bottom of the rectangle\n\t\tfor (j=0;j<s_deltay;j++)\n\t\t{\n\t\t\ttemp=scrpos;\n\n\t\t\t// The inner loop steps across the rectangle\n\t\t\tfor (i=0;i<f_deltax;i++)\n\t\t\t{\n\t\t\t\tpixel=bmp.Data[pixpos];\t\t\t\t//read pixel\n\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\t//draw if not transparent\n//\t\t\t\tif (pixel) Data[scrpos]=pixel;\t//draw if not transparent\n\t\t\t\tpxerror+=bmp.Width;\t\t \t\t\t//update position in bitmap\n\t\t\t\twhile (pxerror>f_deltax)\n\t\t\t\t{\n\t\t\t\t\tpixpos++;\n\t\t\t\t\tpxerror-=f_deltax;\n\t\t\t\t};\n\t\t\t\tscrpos+=f_xstep;\t\t\t\t\t\t//step to next screen pos\n\t\t\t\tf_error+=f_deltay;\n\t\t\t\tif (f_error>f_deltax)\n\t\t\t\t{\n\t\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\n\t\t\t\t\tf_error-=f_deltax;\n\t\t\t\t\tscrpos+=f_ystep;\n\t\t\t\t};\n\t\t\t};\n\t\t\tpxerror=0;\n\t\t\tpixpos-=bmp.Width-1;\n\t\t\tpyerror+=bmp.Height;\n\n\t\t\twhile (pyerror>s_deltay)\n\t\t\t{\n\t\t\t\tpixpos+=bmp.Width;\n\t\t\t\tpyerror-=s_deltay;\n\t\t\t};\n\n\t\t\tf_error=0;\n\t\t\tscrpos=temp;\n\t\t\tscrpos+=s_ystep;\n\t\t\ts_error+=s_deltax;\n\n\t\t\tif (s_error>s_deltay)\n\t\t\t{\n\t\t\t\ts_error-=s_deltay;\n\t\t\t\tscrpos+=s_xstep;\n\t\t\t};\n\t\t}\n\n\t} else {\t\t// CASE 2, Step front line in X, side line in Y\n\n\t\t// outer loop steps from top to bottom of the rectangle\n\t\tfor (j=0;j<s_deltax;j++)\n\t\t{\n\t\t\ttemp=scrpos;\n\n\t\t\t// The inner loop steps across the rectangle\n\t\t\tfor (i=0;i<f_deltay;i++)\n\t\t\t{\n\t\t\t\tpixel=bmp.Data[pixpos];\t\t\t\t//read pixel\n\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\t//draw if not transparent\n\t\t\t\tpxerror+=bmp.Width;\t\t\t\t\t//update position in bitmap\n\t\t\t\twhile (pxerror>f_deltay)\n\t\t\t\t{\n\t\t\t\t\tpixpos++;\n\t\t\t\t\tpxerror-=f_deltay;\n\t\t\t\t};\n\n\t\t\t\tscrpos+=f_ystep;\t\t\t\t\t\t//step to next screen pos\n\t\t\t\tf_error+=f_deltax;\n\t\t\t\tif (f_error>f_deltay)\n\t\t\t\t{\n\t\t\t\t\tif (pixel) ((unsigned char *)Get_Buffer())[scrpos]=pixel;\n\t\t\t\t\tf_error-=f_deltay;\n\t\t\t\t\tscrpos+=f_xstep;\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tpxerror=0;\n\t\t\tpixpos-=bmp.Width-1;\n\t\t\tpyerror+=bmp.Height;\n\t\t\twhile (pyerror>s_deltax)\n\t\t\t{\n\t\t\t\tpixpos+=bmp.Width;\n\t\t\t\tpyerror-=s_deltax;\n\t\t\t};\n\n\t\t\tscrpos=temp;\n\t\t\tscrpos+=s_xstep;\n\t\t\ts_error+=s_deltay;\n\t\t\tf_error=0;\n\t\t\tif (s_error>s_deltax)\n\t\t\t{\n\t\t\t\ts_error-=s_deltax;\n\t\t\t\tscrpos+=s_ystep;\n\t\t\t};\n\t\t}\n\t}\n}"
  },
  {
    "path": "REDALERT/STAGE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/STAGE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STAGE.H                                                      *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : June 17, 1994                                                *\n *                                                                                             *\n *                  Last Update : June 17, 1994   [JLB]                                        *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef STAGE_H\n#define STAGE_H\n\nclass StageClass {\n\n\t\t/*\n\t\t**\tThis handles the animation stage of the object. This includes smoke, walking,\n\t\t**\tflapping, and rocket flames.\n\t\t*/\n\t\tunsigned Stage;\n\n\t\t/*\n\t\t**\tThis is the countdown timer for stage animation. When this counts down\n\t\t**\tto zero, then the stage increments by one and the time cycle starts\n\t\t**\tover again.\n\t\t*/\n\t\tCDTimerClass<FrameTimerClass> Timer;\n\n\t\t/*\n\t\t**\tThis is the value to assign the StageTimer whenever it needs to be reset. Thus,\n\t\t**\tthis value is the control of how fast the stage value increments.\n\t\t*/\n\t\tint Rate;\n\n\tpublic:\n\t\tStageClass(void) : Stage(0), Timer(0), Rate(0) {};\n\t\tStageClass(NoInitClass const & x) : Timer(x) {};\n\n\t\tint Fetch_Stage(void) const {return(Stage);};\n\t\tint Fetch_Rate(void) const {return(Rate);};\n\t\tvoid Set_Stage(int stage) {Stage = stage;};\n\t\tvoid Set_Rate(int rate) {Timer = rate; Rate = rate;};\n\t\tvoid AI(void) {};\n\t\tbool About_To_Change(void) const {return(Timer == 0 && Rate != 0);}\n\t\tbool Graphic_Logic(void) {\n\t\t\tif (About_To_Change()) {\n\t\t\t\tStage++;\n\t\t\t\tTimer = Rate;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t\treturn(false);\n\t\t};\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/STARTUP.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /counterstrike/STARTUP.CPP 6     3/15/97 7:18p Steve_tall $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STARTUP.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : October 3, 1994                                              *\n *                                                                                             *\n *                  Last Update : September 30, 1996 [JLB]                                     *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Prog_End -- Cleans up library systems in prep for game exit.                              *\n *   main -- Initial startup routine (preps library systems).                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t<conio.h>\n#include\t<io.h>\n\n#ifdef WIN32\n#include  \"ccdde.h\"\n#include\t\"ipx95.h\"\n#endif\t//WIN32\n\n#ifdef MCIMPEG // Denzil 6/15/98\n#include \"mcimovie.h\"\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n//#include \"WolDebug.h\"\n#endif\n\nextern char RedAlertINI[_MAX_PATH];\n\nbool Read_Private_Config_Struct(FileClass & file, NewConfigType * config);\nvoid Print_Error_End_Exit(char * string);\nvoid Print_Error_Exit(char * string);\n\n#ifdef WIN32\n//WinTimerClass * WinTimer;\nextern void Create_Main_Window ( HANDLE instance , int command_show , int width , int height);\nextern bool RA95AlreadyRunning;\nHINSTANCE\tProgramInstance;\nvoid Check_Use_Compressed_Shapes (void);\nvoid Read_Setup_Options(RawFileClass *config_file);\nbool VideoBackBufferAllowed = true;\n#else\nBOOL Init_Timer_System(unsigned int freq, int partial = FALSE);\nBOOL Remove_Timer_System(VOID);\n#endif\t//WIN32\n\nconst char* Game_Registry_Key();\n\n#if (ENGLISH)\n#define WINDOW_NAME\t\t\"Red Alert\"\n#endif\n\n#if (FRENCH)\n#define WINDOW_NAME\t\t\"Alerte Rouge\"\n#endif\n\n#if (GERMAN)\n#define WINDOW_NAME\t\t\"Alarmstufe Rot\"\n#endif\n\n// Added. ST - 5/14/2019\nbool ProgEndCalled = false;\n\nextern \"C\"{\n\textern char\t\t*BigShapeBufferStart;\n\textern char\t\t*TheaterShapeBufferStart;\n\textern BOOL\t\tUseBigShapeBuffer;\n\textern bool\t\tIsTheaterShape;\n}\n\nextern void Free_Heaps(void);\nextern void DLL_Shutdown(void);\n\nBOOL WINAPI DllMain(HINSTANCE instance, unsigned int fdwReason, void *lpvReserved)\n{\n\tlpvReserved;\n\n\tswitch (fdwReason) {\n\n\tcase DLL_PROCESS_ATTACH:\n\t\tProgramInstance = instance;\n\t\tbreak;\n\n\tcase DLL_PROCESS_DETACH:\n\t\tif (WindowsTimer) {\n\t\t\tdelete WindowsTimer;\n\t\t\tWindowsTimer = NULL;\n\t\t}\n\t\t\n\t\t/*\n\t\t** Red Alert doesn't clean up memory. Do some of that here.\n\t\t*/\n\t\tMFCD::Free_All();\n\n\t\tif (BigShapeBufferStart) {\n\t\t\tFree(BigShapeBufferStart);\n\t\t\tBigShapeBufferStart = NULL;\n\t\t}\n\n\t\tif (TheaterShapeBufferStart) {\n\t\t\tFree(TheaterShapeBufferStart);\n\t\t\tTheaterShapeBufferStart = NULL;\n\t\t}\n\n\t\tif (_ShapeBuffer) {\n\t\t\tdelete [] _ShapeBuffer;\n\t\t\t_ShapeBuffer = NULL;\n\t\t}\n\n\t\tDLL_Shutdown();\n\t\tFree_Heaps();\n\t\tbreak;\n\n\tcase DLL_THREAD_ATTACH:\n\tcase DLL_THREAD_DETACH:\n\t\tbreak;\n\t}\n\t  \n\treturn true;\n}\n\n\n\n/***********************************************************************************************\n * main -- Initial startup routine (preps library systems).                                    *\n *                                                                                             *\n *    This is the routine that is first called when the program starts up. It basically        *\n *    handles the command line parsing and setting up library systems.                         *\n *                                                                                             *\n * INPUT:   argc  -- Number of command line arguments.                                         *\n *                                                                                             *\n *          argv  -- Pointer to array of command line argument strings.                        *\n *                                                                                             *\n * OUTPUT:  Returns with execution failure code (if any).                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\n#ifdef WIN32\n//int PASCAL WinMain(HINSTANCE, HINSTANCE, char *, int )\n//PG int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int command_show )\nint DLL_Startup(const char * command_line_in)\n\n#else\t//WIN32\nint main(int argc, char * argv[])\n#endif\t//WIN32\n\n{\n#ifdef WIN32\n\n\tRunningAsDLL = true;\n\tint command_show = SW_HIDE;\n\tHINSTANCE instance = ProgramInstance;\n\tchar command_line[1024];\n\tstrcpy(command_line, command_line_in);\n\n\n\n\t#ifndef MPEGMOVIE // Denzil 6/10/98\n\t//PG DDSCAPS\tsurface_capabilities;\n\t#endif\n\n\t/*\n\t** First thing to do is check if there is another instance of Red Alert already running\n\t**  and if so, switch to the existing instance and terminate ourselves.\n\t*/\n\tSpawnedFromWChat = false;\n#if (0)//PG\n\tif (RA95AlreadyRunning) {\t//Set in the DDEServer constructor\n\t\t//MessageBox (NULL, \"Error - attempt to restart Red Alert 95 when already running.\", \"Red Alert\", MB_ICONEXCLAMATION|MB_OK);\n\n\t\tHWND ccwindow;\n    \tccwindow = FindWindow (WINDOW_NAME, WINDOW_NAME);\n    \tif (ccwindow) {\n    \t\tSetForegroundWindow ( ccwindow );\n    \t\tShowWindow ( ccwindow, SW_RESTORE );\n    \t}\n\n\t\treturn (EXIT_SUCCESS);\n\t}\n#endif\n\n#endif\n//printf(\"in program.\\n\");getch();\n//printf(\"ram free = %ld\\n\",Ram_Free(MEM_NORMAL));getch();\n#ifdef WIN32\n\tif (Ram_Free(MEM_NORMAL) < 7000000) {\n#else\n\n\tvoid *temp_mem = malloc (13*1024*1024);\n\tif (temp_mem) {\n\t\tfree (temp_mem);\n\t}else{\n\n\t//if (Ram_Free(MEM_NORMAL) < 13000000) {\n//\tif (Ram_Free(MEM_NORMAL) < 3500000) {\n#endif\n\t\tprintf (TEXT_NO_RAM);\n\n#ifndef WIN32\n\t\tprintf (TEXT_USE_START_MENU);\n\t\tgetch();\n#endif\n\n#if (0)\n\n\t\t/*\n\t\t** Take a stab at finding out how much memory there is available.\n\t\t*/\n\n\t\tfor ( int mem = 13*1024*1024 ; mem >0 ; mem -=1024 ) {\n\t\t\ttemp_mem = malloc (mem);\n\t\t\tif (temp_mem){\n\t\t\t\tfree (temp_mem);\n\t\t\t\tprintf (\"Memory available: %d\", mem);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tgetch();\n#endif\t//(0)\n\t\treturn(EXIT_FAILURE);\n\t}\n\n#ifdef WIN32\n\n\tif (strstr(command_line, \"f:\\\\projects\\\\c&c0\") != NULL ||\n\t\t\tstrstr(command_line, \"F:\\\\PROJECTS\\\\C&C0\") != NULL) {\n\t\tMessageBox(0, \"Playing off of the network is not allowed.\", \"Red Alert\", MB_OK|MB_ICONSTOP);\n\t\treturn(EXIT_FAILURE);\n\t}\n\n\tint\t\targc;\t\t\t\t//Command line argument count\n\tunsigned\tcommand_scan;\n\tchar\t\tcommand_char;\n\tchar *\targv[20];\t\t//Pointers to command line arguments\n\tchar\t\tpath_to_exe[132];\n\n\tProgramInstance = instance;\n\n\t/*\n\t** Get the full path to the .EXE\n\t*/\n\tGetModuleFileName (instance, &path_to_exe[0], 132);\n\n\t/*\n\t** First argument is supposed to be a pointer to the .EXE that is running\n\t**\n\t*/\n\targc=1;\t\t\t\t\t\t\t//Set argument count to 1\n\targv[0]=&path_to_exe[0];\t//Set 1st command line argument to point to full path\n\n\t/*\n\t** Get pointers to command line arguments just like if we were in DOS\n\t**\n\t** The command line we get is cr/zero? terminated.\n\t**\n\t*/\n\n\tcommand_scan=0;\n\n\tdo {\n\t\t/*\n\t\t** Scan for non-space character on command line\n\t\t*/\n\t\tdo {\n\t\t\tcommand_char = *( command_line+command_scan++ );\n\t\t} while ( command_char==' ' );\n\n\t\tif ( command_char!=0 && command_char != 13 ) {\n\t\t\targv[argc++]=command_line+command_scan-1;\n\n\t\t\t/*\n\t\t\t** Scan for space character on command line\n\t\t\t*/\n\t\t\tbool in_quotes = false;\n\t\t\tdo {\n\t\t\t\tcommand_char = *( command_line+command_scan++ );\n\t\t\t\tif (command_char == '\"') {\n\t\t\t\t\tin_quotes = !in_quotes;\n\t\t\t\t}\n\t\t\t} while ( (in_quotes || command_char!=' ') && command_char != 0 && command_char!=13 );\n\t\t*( command_line+command_scan-1 ) = 0;\n\t\t}\n\n\t} while ( command_char != 0 && command_char != 13 && argc<20 );\n\n#endif\t//WIN32\n\n\t/*\n\t**\tRemember the current working directory and drive.\n\t*/\n#if (0)//PG\n\tunsigned olddrive;\n\tchar oldpath[MAX_PATH];\n\tgetcwd(oldpath, sizeof(oldpath));\n\t_dos_getdrive(&olddrive);\n\n\t/*\n\t**\tChange directory to the where the executable is located. Handle the\n\t**\tcase where there is no path attached to argv[0].\n\t*/\n\tchar drive[_MAX_DRIVE];\n\tchar path[_MAX_PATH];\n\tunsigned drivecount;\n\t_splitpath(argv[0], drive, path, NULL, NULL);\n\tif (!drive[0]) {\n\t\tdrive[0] = ('A' + olddrive)-1;\n\t}\n\tif (!path[0]) {\n\t\tstrcpy(path, \".\");\n\t}\n\t_dos_setdrive(toupper((drive[0])-'A')+1, &drivecount);\n\tif (path[strlen(path)-1] == '\\\\') {\n\t\tpath[strlen(path)-1] = '\\0';\n\t}\n\tchdir(path);\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t//\tLook for special wolapi install program, used after the patch to version 3, to install \"Shared Internet Components\".\n\tWIN32_FIND_DATA wfd;\n\tHANDLE hWOLSetupFile = FindFirstFile( \"wolsetup.exe\", &wfd );\n\tbool bWOLSetupFile = ( hWOLSetupFile != INVALID_HANDLE_VALUE );\n//\tif( bWOLSetupFile )\n//\t\tdebugprint( \"Found wolsetup.exe\\n\" );\n\tFindClose( hWOLSetupFile );\n\t//\tLook for special registry entry that tells us when the setup exe has done its thing.\n\tHKEY hKey;\n\tRegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey );\n\tDWORD dwValue;\n\tDWORD dwBufSize = sizeof( DWORD );\n\tif( RegQueryValueEx( hKey, \"WolapiInstallComplete\", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) == ERROR_SUCCESS )\n\t{\n//\t\tdebugprint( \"Found WolapiInstallComplete in registry\\n\" );\n\t\t//\tSetup has finished. Delete the setup exe and remove reg key.\n\t\tif( bWOLSetupFile )\n\t\t{\n\t\t\tif( DeleteFile( \"wolsetup.exe\" ) )\n\t\t\t\tRegDeleteValue( hKey, \"WolapiInstallComplete\" );\n\t\t}\n\t\telse\n\t\t\tRegDeleteValue( hKey, \"WolapiInstallComplete\" );\n\t}\n\tRegCloseKey( hKey );\n\n\t//\tI've been having problems getting the patch to delete \"conquer.eng\", which is present in the game\n\t//\tdirectory for 1.08, but which must NOT be present for this version (Aftermath mix files provide the\n\t//\tstring overrides that the 1.08 separate conquer.eng did before Aftermath).\n\t//\tDelete conquer.eng if it's found.\n\tif( FindFirstFile( \"conquer.eng\", &wfd ) != INVALID_HANDLE_VALUE )\n\t\tDeleteFile( \"conquer.eng\" );\n\n#endif\n\n\tif (Parse_Command_Line(argc, argv)) {\n\n#if(TEN)\n\t//\n\t// Only allow the TEN version of the game to run if the TEN\n\t// or AllowSoloPlayOptions arguments are specified.\n\t//\n\tif (Session.AllowSolo==0 && Session.Type != GAME_TEN) {\n#ifdef WIN32\n\t\tMessageBox(NULL, \"Red Alert for TEN\\n (c) 1996 Westwood Studios\",\n\t\t\t\"Red Alert\", MB_OK);\n\t\texit(0);\n#else\n\t\tprintf(\"\\n\");\n\t\tprintf(\"                         Red Alert for TEN\\n\");\n\t\tprintf(\"                     (c) 1996 Westwood Studios\\n\");\n\t\tprintf(\"\\n\");\n\t\texit(0);\n#endif\t// WIN32\n\t}\n#endif\t// TEN\n\n#if(MPATH)\n\t//\n\t// Only allow the MPATH version of the game to run if the MPATH\n\t// or AllowSoloPlayOptions arguments are specified.\n\t//\n\tif (Session.AllowSolo==0 && Session.Type != GAME_MPATH) {\n#ifdef WIN32\n\t\tMessageBox(NULL, \"Red Alert for MPATH\\n (c) 1996 Westwood Studios\",\n\t\t\t\"Red Alert\", MB_OK);\n\t\texit(0);\n#else\n\t\tprintf(\"\\n\");\n\t\tprintf(\"                        Red Alert for MPATH\\n\");\n\t\tprintf(\"                     (c) 1996 Westwood Studios\\n\");\n\t\tprintf(\"\\n\");\n\t\texit(0);\n#endif\t// WIN32\n\t}\n#endif\t// MPATH\n\n#ifdef WIN32\n\n\t\tWindowsTimer = new WinTimerClass(60, FALSE);\n#if (0)//PG\n\t\tint time_test = WindowsTimer->Get_System_Tick_Count();\n\t\tSleep (1000);\n\t\tif (WindowsTimer->Get_System_Tick_Count() == time_test){\n\t\t\tMessageBox(0, TEXT_ERROR_TIMER, TEXT_SHORT_TITLE, MB_OK|MB_ICONSTOP);\n\t\t\treturn(EXIT_FAILURE);\n\t\t}\n#endif\n#else\t//WIN32\n\t\tInit_Timer_System(60, true);\n#endif\t//WIN32\n\n\t\t////////////////////////////////////////\n\t\t// The editor needs to load the Red Alert ini file from a different location than the real game. - 7/18/2019 JAS \n\t\tchar* red_alert_file_path = nullptr;\n\t\tif (RunningFromEditor)\n\t\t{\n\t\t\tred_alert_file_path = RedAlertINI;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tred_alert_file_path = CONFIG_FILE_NAME;\n\t\t}\n\n\t\tRawFileClass cfile(red_alert_file_path);\n\t\t//RawFileClass cfile(CONFIG_FILE_NAME);\n\t\t// end of change - 7/18/2019 JAS\n\t\t////////////////////////////////////////\n\n#ifndef WIN32\n\t\tInstall_Keyboard_Interrupt(Get_RM_Keyboard_Address(), Get_RM_Keyboard_Size());\n#endif\t//WIN32\n\n#ifdef NEVER\n\t\tKeyboard->IsLibrary = true;\n\t\tif (Debug_Flag) {\n\t\t\tKeyboard_Attributes_On(DEBUGINT);\n\t\t}\n#endif\n\n\t\tKeyboard = new KeyboardClass();\n\n#ifdef WIN32\n\t\t/*\n\t\t** If there is loads of memory then use uncompressed shapes\n\t\t*/\n\t\tCheck_Use_Compressed_Shapes();\n#endif\n\n\t\t/*\n\t\t** If there is not enough disk space free, don't allow the product to run.\n\t\t*/\n\t\tif (Disk_Space_Available() < INIT_FREE_DISK_SPACE) {\n\n#ifdef WIN32\n#if (0)//PG\n\t\t\tchar\tdisk_space_message [512];\n\t\t\tsprintf(disk_space_message, TEXT_CRITICALLY_LOW);\t//PG , (INIT_FREE_DISK_SPACE) / (1024 * 1024));\n\t\t\tint reply = MessageBox(NULL, disk_space_message, TEXT_SHORT_TITLE, MB_ICONQUESTION|MB_YESNO);\n\t\t\tif (reply == IDNO) {\n\t\t\t\tif ( WindowsTimer )\n\t\t\t\t\tdelete WindowsTimer;\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t}\n#endif\n#else\n\t\t\tprintf(TEXT_INSUFFICIENT);\n\t\t\tprintf(TEXT_MUST_HAVE, INIT_FREE_DISK_SPACE / (1024 * 1024));\n\t\t\tprintf(\"\\n\");\n\t\t\tif (Keyboard) Keyboard->Get();\n//\t\t\tKeyboard::IsLibrary = false;\n\t\t\tRemove_Keyboard_Interrupt();\n\t\t\tRemove_Timer_System();\n\t\t\treturn(EXIT_FAILURE);\n#endif\n\t\t}\n\n\t\tif (cfile.Is_Available()) {\n\n\t\t\tRead_Private_Config_Struct(cfile, &NewConfig);\n\n#ifdef WIN32\n\n\t\t\t/*\n\t\t\t** Set the options as requested by the ccsetup program\n\t\t\t*/\n\t\t\tRead_Setup_Options( &cfile );\n\n\t\t\tCreate_Main_Window( instance , command_show , ScreenWidth , ScreenHeight );\n\t\t\tSoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );\n#else\t//WIN32\n\t\t\tif (!Debug_Quiet) {\n\t\t\t\tAudio_Init(NewConfig.DigitCard,\n\t\t\t\t\t\tNewConfig.Port,\n\t\t\t\t\t\tNewConfig.IRQ,\n\t\t\t\t\t\tNewConfig.DMA,\n\t\t\t\t\t\tPLAYBACK_RATE_NORMAL,\n//\t\t\t\t\t\t(NewConfig.Speed) ? PLAYBACK_RATE_SLOW : PLAYBACK_RATE_NORMAL,\n\t\t\t\t\t\tNewConfig.BitsPerSample,\n//\t\t\t\t\t\t4,\n\t\t\t\t\t\t(Get_CPU() < 5) ? 3 : 5,\n//\t\t\t\t\t\t(NewConfig.Speed) ? 3 : 5,\n\t\t\t\t\t\tNewConfig.Reverse);\n\t\t\t\tSoundOn = true;\n\t\t\t} else {\n\t\t\t\tAudio_Init(0, -1, -1, -1, PLAYBACK_RATE_NORMAL, 8, 5, false);\n\t\t\t}\n#endif\t//WIN32\n\n\n#ifdef WIN32\n\t\t\t#ifdef MPEGMOVIE // Denzil 6/10/98\n\t\t\tif (!InitDDraw())\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t#else\n\t\t\tBOOL video_success = FALSE;\n\t\t\t/*\n\t\t\t** Set 640x400 video mode. If its not available then try for 640x480\n\t\t\t*/\n\t\t\tif (ScreenHeight == 400) {\n\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {\n\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t} else {\n\t\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, 480, 8)) {\n\t\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t\t\tScreenHeight = 480;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {\n\t\t\t\t\tvideo_success = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!video_success) {\n\t\t\t\tMessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\tif (WindowsTimer) delete WindowsTimer;\n\t\t\t\t//if (Palette) delete Palette;\n\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t}\n\n\t\t\tif (ScreenWidth==320) {\n\t\t\t\tVisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\tModeXBuff.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));\n\t\t\t} else {\n\n#if (1)\t//ST - 1/3/2019 2:11PM\n\n\t\t\t\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\n#else\n\t\t\t\tVisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));\n\n\t\t\t\t/*\n\t\t\t\t** Check that we really got a video memory page. Failure is fatal.\n\t\t\t\t*/\n\t\t\t\tmemset (&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\t\tVisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {\n\t\t\t\t\t/*\n\t\t\t\t\t** Aaaarrgghh!\n\t\t\t\t\t*/\n\t\t\t\t\tWWDebugString(TEXT_DDRAW_ERROR);WWDebugString(\"\\n\");\n\t\t\t\t\tMessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\t\t\t\t\tif (WindowsTimer) delete WindowsTimer;\n\t\t\t\t\treturn (EXIT_FAILURE);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t** If we have enough left then put the hidpage in video memory unless...\n\t\t\t\t**\n\t\t\t\t** If there is no blitter then we will get better performance with a system\n\t\t\t\t** memory hidpage\n\t\t\t\t**\n\t\t\t\t** Use a system memory page if the user has specified it via the ccsetup program.\n\t\t\t\t*/\n\t\t\t\tunsigned video_memory = Get_Free_Video_Memory();\n\t\t\t\tunsigned video_capabilities = Get_Video_Hardware_Capabilities();\n\t\t\t\tif (video_memory < (unsigned int)(ScreenWidth*ScreenHeight) ||\n\t\t\t\t\t\t(! (video_capabilities & VIDEO_BLITTER)) ||\n\t\t\t\t\t\t(video_capabilities & VIDEO_NO_HARDWARE_ASSIST) ||\n\t\t\t\t\t\t!VideoBackBufferAllowed) {\n\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t} else {\n\t\t\t\t\t//HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)GBC_VIDEOMEM);\n\n\t\t\t\t\t/*\n\t\t\t\t\t** Make sure we really got a video memory hid page. If we didnt then things\n\t\t\t\t\t** will run very slowly.\n\t\t\t\t\t*/\n\t\t\t\t\tmemset (&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\t\t\tHiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Oh dear, big trub. This must be an IBM Aptiva or something similarly cruddy.\n\t\t\t\t\t\t** We must redo the Hidden Page as system memory.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tAllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface());  // Remove the old surface from the AllSurfaces list\n\t\t\t\t\t\tHiddenPage.Get_DD_Surface()->Release();\n\t\t\t\t\t\tHiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tVisiblePage.Attach_DD_Surface(&HiddenPage);\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tScreenHeight = 3072;\n\n\t\t\tif (VisiblePage.Get_Height() == 480) {\n\t\t\t\tSeenBuff.Attach(&VisiblePage, 0, 40, 3072, 3072);\n\t\t\t\tHidPage.Attach(&HiddenPage, 0, 40, 3072, 3072);\n\t\t\t} else {\n\t\t\t\tSeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);\n\t\t\t\tHidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);\n\t\t\t}\n\t\t\t#endif // MPEGMOVIE - Denzil 6/10/98\n\t\t\t\n\t\t\tOptions.Adjust_Variables_For_Resolution();\n\n\t\t\t/*\n\t\t\t** Install the memory error handler\n\t\t\t*/\n\t\t\tMemory_Error = &Memory_Error_Handler;\n\n\t\t\tWindowList[0][WINDOWWIDTH] \t= SeenBuff.Get_Width();\n\t\t\tWindowList[0][WINDOWHEIGHT]\t= SeenBuff.Get_Height();\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWWIDTH] = SeenBuff.Get_Width();\n\t\t\tWindowList[WINDOW_EDITOR][WINDOWHEIGHT]= SeenBuff.Get_Height();\n\n\t\t\t////////////////////////////////////////\n\t\t\t// The editor needs to not start the mouse up. - 7/22/2019 JAS \n\t\t\tif (!RunningFromEditor)\n\t\t\t{\n\t\t\t\tWWMouse = new WWMouseClass(&SeenBuff, 48, 48);\n\t\t\t\tMouseInstalled = TRUE;\n\t\t\t}\n\n\t\t\t//PG CDFileClass::Set_CD_Drive (CDList.Get_First_CD_Drive());\n\n#else\t//WIN32\n\n\t\t\tOptions.Adjust_Variables_For_Resolution();\n\t\t\tif (!Special.IsFromInstall) {\n\t\t\t\tBlackPalette.Set();\n//\t\t\t\tSet_Palette(Palette);\n\t\t\t\tSet_Video_Mode(MCGA_MODE);\n\t\t\t}\n\t\t\tMouseInstalled = Install_Mouse(32, 24, 320, 200);\n#endif\t//WIN32\n\n\t\t\t/*\n\t\t\t** See if we should run the intro\n\t\t\t*/\n\t\t\tINIClass ini;\n\t\t\tini.Load(cfile);\n\n\t\t\t/*\n\t\t\t**\tCheck for forced intro movie run disabling. If the conquer\n\t\t\t**\tconfiguration file says \"no\", then don't run the intro.\n\t\t\t** Don't do this for TEN & MPath.\n\t\t\t*/\n\t\t\tif (!Special.IsFromInstall && Session.Type != GAME_TEN &&\n\t\t\t\tSession.Type != GAME_MPATH) {\n\t\t\t\tSpecial.IsFromInstall = ini.Get_Bool(\"Intro\", \"PlayIntro\", true);\n\t\t\t}\n\t\t\tSlowPalette = ini.Get_Bool(\"Options\", \"SlowPalette\", false);\n\n\t\t\t/*\n\t\t\t** Regardless of whether we should run it or not, here we're\n\t\t\t** gonna change it to say \"no\" in the future.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) {\n\t\t\t\tBreakoutAllowed = true;\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t\tini.Put_Bool(\"Intro\", \"PlayIntro\", false);\n\t\t\t\tini.Save(cfile);\n\t\t\t}\n\n#ifndef WOLAPI_INTEGRATION\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** If WChat has been trying to send us a game start packet then receive it and\n\t\t\t** flag that we were spawned from WCHat so we dont play the into movie.\n\t\t\t*/\n\t\t\tif (DDEServer.Get_MPlayer_Game_Info()){\n\t\t\t\tCheck_From_WChat(NULL);\n\t\t\t}else{\n\t\t\t\t//Check_From_WChat(\"C&CSPAWN.INI\");\n\t\t\t\t//if (Special.IsFromWChat){\n\t\t\t\t//\tDDEServer.Disable();\n\t\t\t\t//}\n\t\t\t}\n#endif\t//WIN32\n#endif\n\t\t\t/*\n\t\t\t**\tIf the intro is being run for the first time, then don't\n\t\t\t**\tallow breaking out of it with the <ESC> key.\n\t\t\t*/\n\t\t\tif (Special.IsFromInstall) {\n\t\t\t\tBreakoutAllowed = true;\n//\t\t\t\tBreakoutAllowed = false;\n\t\t\t}\n\n\t\t\tMemory_Error_Exit = Print_Error_End_Exit;\n\n\t\t\tMain_Game(argc, argv);\n\n\t\t\tif (RunningAsDLL) {\t//PG\n\t\t\t\treturn (EXIT_SUCCESS);\n\t\t\t}\n\n\t\t\t#ifdef MPEGMOVIE // Denzil 6/15/98\n\t\t\tif (MpgSettings != NULL)\n\t\t\t\tdelete MpgSettings;\n\t\n\t\t\t#ifdef MCIMPEG\n\t\t\tif (MciMovie != NULL)\n\t\t\t\tdelete MciMovie;\n\t\t\t#endif\n\t\t\t#endif\n\t\t\t\n#ifdef WIN32\n\t\t\tVisiblePage.Clear();\n\t\t\tHiddenPage.Clear();\n#else\t//WIN32\n\t\t\tSeenPage.Clear();\n\t\t\tSet_Video_Mode(RESET_MODE);\n#endif\t//WIN32\n\t\t\tMemory_Error_Exit = Print_Error_Exit;\n\n#ifdef WIN32\n\t\t\t/*\n\t\t\t** Flag that this is a clean shutdown (not killed with Ctrl-Alt-Del)\n\t\t\t*/\n\t\t\tReadyToQuit = 1;\n\n\t\t\t/*\n\t\t\t** Post a message to our message handler to tell it to clean up.\n\t\t\t*/\n\t\t\tPostMessage(MainWindow, WM_DESTROY, 0, 0);\n\n\t\t\t/*\n\t\t\t** Wait until the message handler has dealt with the message\n\t\t\t*/\n\t\t\tdo\n\t\t\t{\n\t\t\t\tKeyboard->Check();\n\t\t\t}while (ReadyToQuit == 1);\n\n\t\t\treturn (EXIT_SUCCESS);\n\n#else\t//WIN32\n\t\t\tRemove_Mouse();\n\t\t\tSound_End();\n#endif\t//WIN32\n\t\t} else {\n\t\t\tif (!RunningFromEditor)\n\t\t\t{\n\t\t\t\tputs(TEXT_SETUP_FIRST);\n\t\t\t\tKeyboard->Get();\n\t\t\t}\n\t\t}\n\n#ifdef WIN32\n\t\tif (WindowsTimer) {\n\t\t \tdelete WindowsTimer;\n\t\t \tWindowsTimer = NULL;\n\t\t}\n\n#else\t//WIN32\n\t\tRemove_Keyboard_Interrupt();\n\t\tRemove_Timer_System();\n#endif\t//WIN32\n\t}\n\t/*\n\t**\tRestore the current drive and directory.\n\t*/\n#ifndef WIN32\n\t_dos_setdrive(olddrive, &drivecount);\n\tchdir(oldpath);\n#endif\t//WIN32\n\treturn(EXIT_SUCCESS);\n}\n\n\n/* Initialize DirectDraw and surfaces */\nbool InitDDraw(void)\n\t{\n\n\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));\n\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);\n\tVisiblePage.Attach_DD_Surface(&HiddenPage);\n\tSeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);\n\tHidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);\n\n#if (0)//PG\n\tDDSCAPS\tsurface_capabilities;\n\tBOOL video_success = FALSE;\n\n\t/* Set 640x400 video mode. If its not available then try for 640x480 */\n\tif (ScreenHeight == 400)\n\t\t{\n\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))\n\t\t\t{\n\t\t\tvideo_success = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, 480, 8))\n\t\t\t\t{\n\t\t\t\tvideo_success = TRUE;\n\t\t\t\tScreenHeight = 480;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))\n\t\t\t{\n\t\t\tvideo_success = TRUE;\n\t\t\t}\n\t\t}\n\n\tif (!video_success)\n\t\t{\n\t\tMessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\n\t\tif (WindowsTimer)\n\t\t\tdelete WindowsTimer;\n\n\t\treturn false;\n\t\t}\n\n\tif (ScreenWidth == 320)\n\t\t{\n\t\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\tModeXBuff.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\t\t}\n\telse\n\t\t{\n\t\tVisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));\n\n\t\t/* Check that we really got a video memory page. Failure is fatal. */\n\t\tmemset(&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\tVisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\n\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)\n\t\t\t{\n\t\t\t/* Aaaarrgghh! */\n\t\t\tWWDebugString(TEXT_DDRAW_ERROR);WWDebugString(\"\\n\");\n\t\t\tMessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);\n\n\t\t\tif (WindowsTimer)\n\t\t\t\tdelete WindowsTimer;\n\t\t\t\t\n\t\t\treturn false;\n\t\t\t}\n\n\t\t/* If we have enough left then put the hidpage in video memory unless...\n\t\t *\n\t\t * If there is no blitter then we will get better performance with a system\n\t\t * memory hidpage\n\t\t *\n\t\t * Use a system memory page if the user has specified it via the ccsetup program.\n\t\t */\n\t\tunsigned video_memory = Get_Free_Video_Memory();\n\t\tunsigned video_capabilities = Get_Video_Hardware_Capabilities();\n\n\t\tif (video_memory < ScreenWidth * ScreenHeight\n\t\t\t\t|| (!(video_capabilities & VIDEO_BLITTER))\n\t\t\t\t|| (video_capabilities & VIDEO_NO_HARDWARE_ASSIST)\n\t\t\t\t|| !VideoBackBufferAllowed)\n\t\t\t{\n\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);\n\n\t\t\t/* Make sure we really got a video memory hid page. If we didnt then things\n\t\t\t * will run very slowly.\n\t\t\t */\n\t\t\tmemset(&surface_capabilities, 0, sizeof(surface_capabilities));\n\t\t\tHiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);\n\t\t\t\n\t\t\tif (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)\n\t\t\t\t{\n\t\t\t\t/* Oh dear, big trub. This must be an IBM Aptiva or something similarly cruddy.\n\t\t\t\t * We must redo the Hidden Page as system memory.\n\t\t\t\t */\n\t\t\t\tAllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface());  // Remove the old surface from the AllSurfaces list\n\t\t\t\tHiddenPage.Get_DD_Surface()->Release();\n\t\t\t\tHiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tVisiblePage.Attach_DD_Surface(&HiddenPage);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tScreenHeight = 400;\n\n\tif (VisiblePage.Get_Height() == 480)\n\t\t{\n\t\tSeenBuff.Attach(&VisiblePage, 0, 40, 3072, 3072);\n\t\tHidPage.Attach(&HiddenPage, 0, 40, 3072, 3072);\n\t\t}\n\telse\n\t\t{\n\t\tSeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);\n\t\tHidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);\n\t\t}\n#endif\n\treturn true;\n\t}\n\n\n/***********************************************************************************************\n * Prog_End -- Cleans up library systems in prep for game exit.                                *\n *                                                                                             *\n *    This routine should be called before the game terminates. It handles cleaning up         *\n *    library systems so that a graceful return to the host operating system is achieved.      *\n *                                                                                             *\n * INPUT:   why - text description of exit reason                                              *\n *          fatal - indicates a fatal error                                                    *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/20/1995 JLB : Created.                                                                 *\n *   08/07/2019  ST : Added why and fatal params                                               *\n *=============================================================================================*/\n#ifdef WIN32\nvoid __cdecl Prog_End(const char *why, bool fatal)\n{\n\tGlyphX_Debug_Print(\"Prog_End()\");\n\t\n\tif (why) {\n\t\tGlyphX_Debug_Print(why);\n\t}\n\tif (fatal) {\n\t\t*((int*)0) = 0;\n\t}\n\n\tif (Session.Type == GAME_GLYPHX_MULTIPLAYER) {\n\t\treturn;\n\t}\n\n\tSound_End();\n\tif (WWMouse) {\n\t\tdelete WWMouse;\n\t\tWWMouse = NULL;\n\t}\n\tif (WindowsTimer) {\n\t\t delete WindowsTimer;\n\t\t WindowsTimer = NULL;\n\t}\n\n\tProgEndCalled = true;\n}\n#else\t//WIN32\n\nvoid Prog_End(void)\n{\n\tif (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {\n\t\tNullModem.Change_IRQ_Priority(0);\n\t}\n\n\tSet_Video_Mode(RESET_MODE);\n\tRemove_Keyboard_Interrupt();\n\tRemove_Mouse();\n\tSound_End();\n\tRemove_Timer_System();\n}\n#endif\t//WIN32\n\n\nvoid Print_Error_End_Exit(char * string)\n{\n\tProg_End(string, true);\n\tprintf( \"%s\\n\", string );\n\tif (!RunningAsDLL) {\n\t\texit(1);\n\t}\n}\n\n\nvoid Print_Error_Exit(char * string)\n{\n\tGlyphX_Debug_Print(string);\n\t\n\tprintf( \"%s\\n\", string );\n\tif (!RunningAsDLL) {\n\t\texit(1);\n\t}\n}\n\n\n\n\n\n\n\n/***********************************************************************************************\n * Emergency_Exit -- Function to call when we want to exit unexpectedly.                       *\n *                   Use this function instead of exit(n) so everything is properly cleaned up.*\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Code to return to the OS                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    3/13/97 1:32AM ST : Created                                                              *\n *=============================================================================================*/\nvoid Emergency_Exit ( int code )\n{\n\tif (RunningAsDLL) {\t//PG\n\t\treturn;\n\t}\n\n#ifdef WIN32\n\n\t/*\n\t** Clear out the video buffers so we dont glitch when we lose focus\n\t*/\n\tVisiblePage.Clear();\n\tHiddenPage.Clear();\n\tBlackPalette.Set();\n\tMemory_Error_Exit = Print_Error_Exit;\n\n\t/*\n\t** Flag that this is an emergency shut down - not a clean shutdown but\n\t** not killed with Ctrl-Alt-Del either.\n\t*/\n\tReadyToQuit = 3;\n\n\t/*\n\t** Post a message to our message handler to tell it to clean up.\n\t*/\n\tPostMessage(MainWindow, WM_DESTROY, 0, 0);\n\n\t/*\n\t** Wait until the message handler has dealt with the message\n\t*/\n\tdo\n\t{\n\t\tKeyboard->Check();\n\t}while (ReadyToQuit == 3);\n\n\n#else\t//WIN32\n\t/*\n\t** Do the DOS end\n\t*/\n\tProg_End();\n\n#endif\t//WIN32\n\n\texit ( code );\n}\n\n\n\n\n\n\n\n\n\n\n\n#ifdef WIN32\n\n/***********************************************************************************************\n * Read_Setup_Options -- Read stuff in from the INI file that we need to know sooner           *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Ptr to config file class                                                          *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    6/7/96 4:09PM ST : Created                                                               *\n *   09/30/1996 JLB : Uses INI class.                                                          *\n *=============================================================================================*/\nvoid Read_Setup_Options( RawFileClass *config_file )\n{\n\tif (config_file->Is_Available()) {\n\n\t\tINIClass ini;\n\n\t\tini.Load(*config_file);\n\n\t\t/*\n\t\t** Read in the boolean options\n\t\t*/\n\t\tVideoBackBufferAllowed = ini.Get_Bool(\"Options\", \"VideoBackBuffer\", true);\n\t\tAllowHardwareBlitFills = ini.Get_Bool(\"Options\", \"HardwareFills\", true);\n\t\tScreenHeight = ini.Get_Bool(\"Options\", \"Resolution\", false) ? 3072 : 3072;\n\n\t\t/*\n\t\t** See if an alternative socket number has been specified\n\t\t*/\n\t\tint socket = ini.Get_Int(\"Options\", \"Socket\", 0);\n\t\tif (socket >0 ) {\n\t\t\tsocket += 0x4000;\n\t\t\tif (socket >= 0x4000 && socket < 0x8000) {\n\t\t\t\tIpx.Set_Socket (socket);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** See if a destination network has been specified\n\t\t*/\n\t\tchar netbuf [512];\n\t\tmemset(netbuf, 0, sizeof(netbuf));\n\t\tchar * netptr = netbuf;\n\t\tbool found = ini.Get_String(\"Options\", \"DestNet\", NULL, netbuf, sizeof(netbuf));\n\n\t\tif (found && netptr != NULL && strlen(netbuf)) {\n\t\t\tNetNumType net;\n\t\t\tNetNodeType node;\n\n\t\t\t/*\n\t\t\t** Scan the string, pulling off each address piece\n\t\t\t*/\n\t\t\tint i = 0;\n\t\t\tchar * p = strtok(netbuf,\".\");\n\t\t\tint x;\n\t\t\twhile (p != NULL) {\n\t\t\t\tsscanf(p,\"%x\",&x);\t\t\t// convert from hex string to int\n\t\t\t\tif (i < 4) {\n\t\t\t\t\tnet[i] = (char)x;\t\t\t// fill NetNum\n\t\t\t\t} else {\n\t\t\t\t\tnode[i-4] = (char)x;\t\t// fill NetNode\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tp = strtok(NULL,\".\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t** If all the address components were successfully read, fill in the\n\t\t\t** BridgeNet with a broadcast address to the network across the bridge.\n\t\t\t*/\n\t\t\tif (i >= 4) {\n\t\t\t\tSession.IsBridge = 1;\n\t\t\t\tmemset(node, 0xff, 6);\n\t\t\t\tSession.BridgeNet = IPXAddressClass(net, node);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Get_OS_Version (void)\n{\n\t//PG\n\t//WindowsNT = ((GetVersion() & 0x80000000) == 0) ? true : false;\n\n#if (0)\n\tOSVERSIONINFO\tosversion;\n\tif ( GetVersionEx (&osversion) ){\n\t\tWindowsNT = (osversion.dwPlatformId == VER_PLATFORM_WIN32_NT) ? true : false;\n\t\tOutputDebugString (\"RA95 - Got OS version\\n\");\n\t}else{\n\t\tOutputDebugString (\"RA95 - Failed to get OS version\\n\");\n\t\tchar debugstr [128];\n\t\tsprintf (debugstr, \"RA95 - Error code is %d\\n\", GetLastError());\n\t\tOutputDebugString (debugstr);\n\n\t}\n#endif\t//(0)\n\n}\n\n\n#endif\t//WIN32"
  },
  {
    "path": "REDALERT/STATBTN.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/STATBTN.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TEXTBTN.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 19, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   StaticButtonClass::Draw_Background -- Draws the background to the text button.            *\n *   StaticButtonClass::Draw_Me -- Draws the text buttons as indicated.                        *\n *   StaticButtonClass::Draw_Text -- This draws the text for the text button.                  *\n *   StaticButtonClass::Set_Text -- Assigns a new text string to this button.                  *\n *   StaticButtonClass::StaticButtonClass -- Normal constructor for a text button.             *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"function.h\"\n#include \"statbtn.h\"\n\n\n/***********************************************************************************************\n * StaticButtonClass::StaticButtonClass -- Normal constructor for a text button.               *\n *                                                                                             *\n *    This is the constructor for text buttons if the text is provided as a string pointer.    *\n *                                                                                             *\n * INPUT:   id    -- The ID number to assign to this button.                                   *\n *                                                                                             *\n *          text  -- Pointer to the text string to display on top of the button.               *\n *                                                                                             *\n *          x,y   -- Pixel coordinate of button's upper left corner.                           *\n *                                                                                             *\n *          w,h   -- Dimensions of the button. If these are not filled in (or with -1), then   *\n *                   the dimensions are adapted to fit the text assigned to the button.        *\n *                                                                                             *\n *          style -- The print style for the text in the button. These are the TPF_ flags      *\n *                   used by Fancy_Text_Print().                                               *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: Call Set_Text & Set_Style, & init X,Y,Width,Height,ID before using this button.\t  *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nStaticButtonClass::StaticButtonClass(unsigned , char const * text, TextPrintType style, int x, int y, int w, int h) :\n\tGadgetClass(x, y, w, h, FlagEnum(0)),\n\tString(NULL),\n\tPrintFlags(style)\n{\n\t/*\n\t**\tMake a duplicate of the string to display.\n\t*/\n\tSet_Text(text, false);\n\n\tif (w == -1 || h == -1) {\n\t\t//PG_TO_FIX\n\t\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tif (w == -1) {\n\t\t\tWidth = String_Pixel_Width(String);\n\t\t}\n\t\tif (h == -1) {\n\t\t\tHeight = FontHeight;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::StaticButtonClass -- Default constructor for a text button.              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:   none                                                                              *\n *                                                                                             *\n * WARNINGS: none                                                                              *\n *                                                                                             *\n * HISTORY:  01/15/1995 JLB : Created.                                                         *\n *=============================================================================================*/\nStaticButtonClass::StaticButtonClass(void) :\n\tGadgetClass(0, 0, 0, 0, FlagEnum(0)),\n\tString(NULL),\n\tPrintFlags(TPF_8POINT)\n{\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Me -- Draws the text buttons as indicated.                          *\n *                                                                                             *\n *    This routine will draw the text button.                                                  *\n *                                                                                             *\n * INPUT:   forced   -- If the button is to be redrawn regardless of the state of the redraw   *\n *                      flag, then this parameter will be true.                                *\n *                                                                                             *\n * OUTPUT:  bool; Was the button redrawn?                                                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/03/1995 MML : Created.                                                                 *\n *   01/16/1995 JLB : Modified                                                                 *\n *=============================================================================================*/\nint StaticButtonClass::Draw_Me(int forced)\n{\n\tif (GadgetClass::Draw_Me(forced)) {\n\t\t/*\n\t\t**\tHide the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Hide_Mouse(X, Y, X+Width-1, Y+Height-1);\n\t\t}\n\n\t\t/*\n\t\t**\tDraw the background and overlaying text. These are virtual function\n\t\t**\tcalls so that they may be overridden.\n\t\t*/\n\t\tDraw_Background();\n\t\tDraw_Text(String);\n\n\t\t/*\n\t\t**\tDisplay the mouse.\n\t\t*/\n\t\tif (LogicPage == &SeenBuff) {\n\t\t\tConditional_Show_Mouse();\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Set_Text -- Assigns a new text string to this button.                    *\n *                                                                                             *\n *    Use this routine to assign a new text string to this button. By using this function it   *\n *    is possible to dynamically change the button's text. An example of this would be an      *\n *    on/off button that every time it is clicked, the text toggles between \"on\" and \"off\".    *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to assign to this button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   The text is NOT copied to this button. You must make sure that the text         *\n *             remains valid throughout the lifetime of this text button.                      *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/16/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Set_Text(char const * text, bool resize)\n{\n\tif (String != NULL) {\n\t\tdelete [] String;\n\t\tString = NULL;\n\t}\n\n\tif (text != NULL) {\n\t\tString = new char[strlen(text)+1];\n\t\tif (String != NULL) {\n\t\t\tstrcpy(String, text);\n\t\t}\n\t}\n\n\tFlag_To_Redraw();\n\tif (resize && String != NULL) {\n\t\tDraw_Background();\n\t\t//PG_TO_FIX\n\t\t//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, PrintFlags);\n\t\tWidth = String_Pixel_Width(String);\n\t\tHeight = FontHeight + FontYSpacing;\n\t\tBackground = Buffer();\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Background -- Draws the background to the text button.              *\n *                                                                                             *\n *    This localizes the drawing of the background for the text button. By overriding this     *\n *    function you can give a different background to the button. The text is drawn using      *\n *    a different routine. The mouse is hidden, if necessary, before this routine is called.   *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Draw_Background(void)\n{\n\t/*\n\t**\tIf the background hasn't been recorded from the buffer, then\n\t**\tallocate and record the background image now.\n\t*/\n\tif (Background.Get_Buffer() == NULL && Width > 0 && Height > 0) {\n\t\tnew(&Background) Buffer(Width*Height);\n\t\tif (Background.Get_Buffer() != NULL) {\n\t\t\tLogicPage->To_Buffer(X, Y, Width, Height, Background, Background.Get_Size());\n\t\t}\n\t}\n\n\t/*\n\t**\tIf there is a background image present, then restore it to the buffer now.\n\t*/\n\tif (Background.Get_Buffer() != NULL && LogicPage->Lock()) {\n\t\tBuffer_To_Page(X, Y, Width, Height, Background, *LogicPage);\n\t\tLogicPage->Unlock();\n\t}\n}\n\n\n/***********************************************************************************************\n * StaticButtonClass::Draw_Text -- This draws the text for the text button.                    *\n *                                                                                             *\n *    This routine draws the text for the text button. You can override this routine if you    *\n *    wish different text rendering styles or colors. The background has already been drawn    *\n *    by the time this function is called. The mouse is hidden, if necessary, as well.         *\n *                                                                                             *\n * INPUT:   text  -- Pointer to the text string to print over the button.                      *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   01/19/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid StaticButtonClass::Draw_Text(char const * text)\n{\n\t/*\n\t**\tDisplay the text.\n\t*/\n\tif (String != NULL) {\n\t\tint x = X;\n\n\t\tif (PrintFlags & TPF_CENTER) {\n\t\t\tx += Width/2;\n\t\t}\n\t\tif (PrintFlags & TPF_RIGHT) {\n\t\t\tx += Width-1;\n\t\t}\n\n\t\tFancy_Text_Print(text, x, Y, GadgetClass::Get_Color_Scheme(), TBLACK, PrintFlags);\n\t}\n}\n"
  },
  {
    "path": "REDALERT/STATBTN.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/STATBTN.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STATBTN.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 01/15/95                                                     *\n *                                                                                             *\n *                  Last Update : January 15, 1995 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef STATBTN_H\n#define STATBTN_H\n\n#include\t\"gadget.h\"\n#include\t\"buff.h\"\n\nclass StaticButtonClass : public GadgetClass\n{\n\tpublic:\n\t\tStaticButtonClass(void);\n\t\tStaticButtonClass(unsigned id, char const * text, TextPrintType style, int x, int y, int w=-1, int h=-1);\n\t\tvirtual int Draw_Me(int forced=false);\n\t\tvirtual void Set_Text(char const * text, bool resize = false);\n\n\tprotected:\n\n\t\tvirtual void Draw_Background(void);\n\t\tvirtual void Draw_Text(char const * text);\n\n\t\t/*\n\t\t**\tIf a background is to be preserved for this button, then this will point to\n\t\t**\ta buffer that holds a pristine background image.\n\t\t*/\n\t\tBuffer Background;\n\n\t\t/*\n\t\t**\tThis points to a copy of the string that is used for the button's text.\n\t\t*/\n\t\tchar * String;\n\n\t\t/*\n\t\t**\tThis is the print flags to use when rendering this button's text.\n\t\t*/\n\t\tTextPrintType PrintFlags;\n};\n\n#endif\n\n"
  },
  {
    "path": "REDALERT/STATS.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : WINSTUB.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Steve Tall                                                   *\n *                                                                                             *\n *                   Start Date : 05/29/1996                                                   *\n *                                                                                             *\n *                  Last Update : May 29th 1996 [ST]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Overview:                                                                                   *\n *  Internet game statistics to collect and upload to the server                               *\n *                                                                                             *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n *                                                                                             *\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifdef WIN32\n\n#include\t\"function.h\"\n#include \"tcpip.h\"\n#include \"packet.h\"\n#include \"ccdde.h\"\n\n#define FIELD_PACKET_TYPE\t\t\t\t\t\t\"TYPE\"\n#define FIELD_GAME_ID\t\t\t\t\t\t\t\"IDNO\"\n#define FIELD_START_CREDITS\t\t\t\t\t\t\"CRED\"\n#define FIELD_BASES\t\t\t\t\t\t\t\t\"BASE\"\n#define FIELD_TIBERIUM\t\t\t\t\t\t\t\"TIBR\"\n#define FIELD_CRATES\t\t\t\t\t\t\t\"CRAT\"\n#define FIELD_AI_PLAYERS\t\t\t\t\t\t\"AIPL\"\n#define FIELD_CAPTURE_THE_FLAG\t\t\t\t\t\"FLAG\"\n#define FIELD_START_UNIT_COUNT\t\t\t\t\t\"UNIT\"\n#define FIELD_TECH_LEVEL\t\t\t\t\t\t\"TECH\"\n#define FIELD_SCENARIO\t\t\t\t\t\t\t\"SCEN\"\n#define FIELD_COMPLETION\t\t\t\t\t\t\"CMPL\"\n#define FIELD_START_TIME\t\t\t\t\t\t\"TIME\"\n#define FIELD_GAME_DURATION\t\t\t\t\t\t\"DURA\"\n#define FIELD_FRAME_RATE\t\t\t\t\t\t\"AFPS\"\n#define FIELD_SPEED_SETTING\t\t\t\t\t\t\"SPED\"\n#define FIELD_GAME_VERSION\t\t\t\t\t\t\"VERS\"\n#define FIELD_GAME_BUILD_DATE\t\t\t\t\t\"DATE\"\n#define FIELD_COVERT_PRESENT\t\t\t\t\t\"COVT\"\n#define FIELD_CPU_TYPE\t\t\t\t\t\t\t\"PROC\"\n#define FIELD_MEMORY\t\t\t\t\t\t\t\"MEMO\"\n#define FIELD_VIDEO_MEMORY\t\t\t\t\t\t\"VIDM\"\n#define FIELD_SHADOW_REGROWS\t\t\t\t\t\"SHAD\"\n\n#ifdef WOLAPI_INTEGRATION\n#define FIELD_HOSTORNOT\t\t\t\t\t\t\t\"SDFX\"\n#define FIELD_TOURNAMENT\t\t\t\t\t\t\"TRNY\"\n#define FIELD_NUM_INITIAL_PLAYERS\t\t\t\t\"NUMP\"\n#define FIELD_NUM_REMAINING_PLAYERS\t\t\t\t\"REMN\"\n#define FIELD_DISCONNECT_PINGS\t\t\t\t\t\"PING\"\n#define FIELD_COMPUTERTOOKOVER\t\t\t\t\t\"QUIT\"\n//#define FIELD_HARDWARE_GUID\t\t\t\t\t\"GUID\"\n#define FIELD_PLAYER1_IP\t\t\t\t\t\t\"ADR1\"\n#define FIELD_PLAYER2_IP\t\t\t\t\t\t\"ADR2\"\n#endif\n\n//\tajw The following were never used (thank god).\n#define FIELD_PLAYER1_HANDLE\t\t\t\t\t\"NAM1\"\n#define FIELD_PLAYER2_HANDLE\t\t\t\t\t\"NAM2\"\n#define FIELD_PLAYER1_TEAM\t\t\t\t\t\t\"SID1\"\n#define FIELD_PLAYER2_TEAM\t\t\t\t\t\t\"SID2\"\n#define FIELD_PLAYER1_COLOR\t\t\t\t\t\t\"COL1\"\n#define FIELD_PLAYER2_COLOR\t\t\t\t\t\t\"COL2\"\n#define FIELD_PLAYER1_CREDITS\t\t\t\t\t\"CRD1\"\n#define FIELD_PLAYER2_CREDITS\t\t\t\t\t\"CRD2\"\n\n#define FIELD_PLAYER1_UNITS_LEFT\t\t\t\t\"UNL1\"\n#define FIELD_PLAYER2_UNITS_LEFT\t\t\t\t\"UNL2\"\n#define FIELD_PLAYER1_INFANTRY_LEFT\t\t\t\t\"INL1\"\n#define FIELD_PLAYER2_INFANTRY_LEFT\t\t\t\t\"INL2\"\n#define FIELD_PLAYER1_PLANES_LEFT\t\t\t\t\"PLL1\"\n#define FIELD_PLAYER2_PLANES_LEFT\t\t\t\t\"PLL2\"\n#define FIELD_PLAYER1_BUILDINGS_LEFT\t\t\t\"BLL1\"\n#define FIELD_PLAYER2_BUILDINGS_LEFT\t\t\t\"BLL2\"\n#define FIELD_PLAYER1_VESSELS_LEFT\t\t\t\t\"VSL1\"\n#define FIELD_PLAYER2_VESSELS_LEFT\t\t\t\t\"VSL2\"\n\n#define FIELD_PLAYER1_UNITS_BOUGHT\t\t\t\t\"UNB1\"\n#define FIELD_PLAYER2_UNITS_BOUGHT\t\t\t\t\"UNB2\"\n#define FIELD_PLAYER1_INFANTRY_BOUGHT\t\t\t\"INB1\"\n#define FIELD_PLAYER2_INFANTRY_BOUGHT\t\t\t\"INB2\"\n#define FIELD_PLAYER1_PLANES_BOUGHT\t\t\t\t\"PLB1\"\n#define FIELD_PLAYER2_PLANES_BOUGHT\t\t\t\t\"PLB2\"\n#define FIELD_PLAYER1_BUILDINGS_BOUGHT\t\t\t\"BLB1\"\n#define FIELD_PLAYER2_BUILDINGS_BOUGHT\t\t\t\"BLB2\"\n#define FIELD_PLAYER1_VESSELS_BOUGHT\t\t\t\"VSB1\"\n#define FIELD_PLAYER2_VESSELS_BOUGHT\t\t\t\"VSB2\"\n\n#define FIELD_PLAYER1_UNITS_KILLED\t\t\t\t\"UNK1\"\n#define FIELD_PLAYER2_UNITS_KILLED\t\t\t\t\"UNK2\"\n#define FIELD_PLAYER1_INFANTRY_KILLED\t\t\t\"INK1\"\n#define FIELD_PLAYER2_INFANTRY_KILLED\t\t\t\"INK2\"\n#define FIELD_PLAYER1_PLANES_KILLED\t\t\t\t\"PLK1\"\n#define FIELD_PLAYER2_PLANES_KILLED\t\t\t\t\"PLK2\"\n#define FIELD_PLAYER1_BUILDINGS_KILLED\t\t\t\"BLK1\"\n#define FIELD_PLAYER2_BUILDINGS_KILLED\t\t\t\"BLK2\"\n#define FIELD_PLAYER1_VESSELS_KILLED\t\t\t\"VSK1\"\n#define FIELD_PLAYER2_VESSELS_KILLED\t\t\t\"VSK2\"\n\n#define FIELD_PLAYER1_BUILDINGS_CAPTURED\t\t\"BLC1\"\n#define FIELD_PLAYER2_BUILDINGS_CAPTURED\t\t\"BLC2\"\n\n#define FIELD_PLAYER1_CRATES_FOUND\t\t\t\t\"CRA1\"\n#define FIELD_PLAYER2_CRATES_FOUND\t\t\t\t\"CRA2\"\n#define FIELD_PLAYER1_HARVESTED\t\t\t\t\t\"HRV1\"\n#define FIELD_PLAYER2_HARVESTED\t\t\t\t\t\"HRV2\"\n\n\n#define\tPACKET_TYPE_HOST_GAME_INFO\t\t(unsigned char) 50\n#define\tPACKET_TYPE_GUEST_GAME_INFO\t\t(unsigned char) 51\n\n//\tNote: These enums match those in the game results server code.\nenum {\n\tCOMPLETION_CONNECTION_LOST,\n\tCOMPLETION_PLAYER_1_WON,\n\tCOMPLETION_PLAYER_1_WON_BY_RESIGNATION,\n\tCOMPLETION_PLAYER_1_WON_BY_DISCONNECTION,\n\tCOMPLETION_PLAYER_2_WON,\n\tCOMPLETION_PLAYER_2_WON_BY_RESIGNATION,\n\tCOMPLETION_PLAYER_2_WON_BY_DISCONNECTION,\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\tCOMPLETION_WASH = 64,\n#endif\n};\n\n\nextern unsigned long \tPlanetWestwoodGameID;\nextern HINSTANCE\t\tProgramInstance;\nextern unsigned long \tPlanetWestwoodStartTime;\n\nextern \"C\" char\tCPUType;\n\n\nbool\t\t\tGameTimerInUse = false;\nTimerClass\tGameTimer;\nlong\t\t\tGameEndTime;\nvoid\t\t\t*PacketLater = NULL;\n\n//#include \"WolDebug.h\"\n\n#ifdef WOLAPI_INTEGRATION\n#include \"WolapiOb.h\"\nextern WolapiObject* pWolapi;\n\nextern bool bReconnectDialogCancelled;\n#endif\n\n/***********************************************************************************************\n * Send_Statistics_To_Server -- sends internet game statistics to the Westeood server          *\n *                                                                                             *\n *                                                                                             *\n *                                                                                             *\n * INPUT:    Nothing                                                                           *\n *                                                                                             *\n * OUTPUT:   Nothing                                                                           *\n *                                                                                             *\n * WARNINGS: None                                                                              *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *    5/29/96 12:38PM ST : Created                                                             *\n *=============================================================================================*/\n\nvoid Send_Statistics_Packet(void)\n{\n#if (0)//PG\n//\tdebugprint( \"Stats: Send_Statistics_Packet() called.\\n\" );\n#ifndef INTERNET_OFF // Denzil 5/4/98\n\n#ifdef WOLAPI_INTEGRATION\n\tif( !pWolapi )\t\t\t//\tShould no longer ever happen.\n\t\treturn;\n#endif\n\n\tPacketClass\tstats;\n\tHouseClass\t*player;\n\tstatic int\tpacket_size;\n\tint\t\t\tindex;\n\tbool\t\t\tpacket_later = false;\t// Should the packet be sent later\n\tvoid\t\t\t*packet;\n\n\tstatic char\tfield_player_handle[5] \t\t\t\t= { \"NAM?\" };\n\tstatic char\tfield_player_team[5] \t\t\t\t= { \"SID?\" };\n\tstatic char\tfield_player_color[5]\t\t\t\t= { \"COL?\" };\n\tstatic char field_player_credits[5]\t\t\t\t= { \"CRD?\" };\n\tstatic char field_player_units_left[5]\t\t\t= { \"UNL?\" };\n\tstatic char field_player_infantry_left[5]\t\t= { \"INL?\" };\n\tstatic char field_player_planes_left[5]\t\t= { \"PLL?\" };\n\tstatic char field_player_buildings_left[5]\t= { \"BLL?\" };\n\tstatic char field_player_vessels_left[5]\t\t= { \"VSL?\" };\n\tstatic char field_player_units_bought[5] \t\t= { \"UNB?\" };\n\tstatic char field_player_infantry_bought[5] \t= { \"INB?\" };\n\tstatic char field_player_planes_bought[5]\t\t= { \"PLB?\" };\n\tstatic char field_player_buildings_bought[5]\t= { \"BLB?\" };\n\tstatic char field_player_vessels_bought[5]\t= { \"VSB?\" };\n\tstatic char field_player_units_killed[5] \t\t= { \"UNK?\" };\n\tstatic char field_player_infantry_killed[5] \t= { \"INK?\" };\n\tstatic char field_player_planes_killed[5]\t\t= { \"PLK?\" };\n\tstatic char field_player_buildings_killed[5]\t= { \"BLK?\" };\n\tstatic char field_player_vessels_killed[5]\t= { \"VSK?\" };\n\tstatic char field_player_buildings_captured[5] = { \"BLC?\" };\n\tstatic char field_player_crates_found[5]\t\t= { \"CRA?\" };\n\tstatic char field_player_harvested[5]\t\t\t= { \"HRV?\" };\n\n\tstatic char *houses[] = {\n\t\t\"SPA\",\n\t\t\"GRE\",\n\t\t\"USS\",\n\t\t\"ENG\",\n\t\t\"ITA\",\n\t\t\"GER\",\n\t\t\"FRA\",\n\t\t\"TKY\",\n\t\t\"GUD\",\n\t\t\"BAD\",\n\t\t\"CIV\",\n\t\t\"JP \",\n\t\t\"M01\",\n\t\t\"M02\",\n\t\t\"M03\",\n\t\t\"M04\",\n\t\t\"M05\",\n\t\t\"M06\",\n\t\t\"M07\",\n\t\t\"M08\"\n\t};\n\n\tif (!PacketLater){\n\n\t\t/*\n\t\t** Field to identify this as C&C 95 internet game statistics packet\n\t\t*/\n#ifdef WOLAPI_INTEGRATION\n\t\tif( pWolapi->bGameServer )\n\t\t{\n\t\t\tstats.Add_Field( FIELD_HOSTORNOT, (unsigned char)0 );\t\t//\tReversed meaning of this for Neal.\n\t\t}else{\n\t\t\tstats.Add_Field( FIELD_HOSTORNOT, (unsigned char)1 );\n\t\t}\n#else\n\t\tif (Server){\n\t\t\tstats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_HOST_GAME_INFO);\n\t\t}else{\n\t\t\tstats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_GUEST_GAME_INFO);\n\t\t}\n#endif\n\n\t\t/*\n\t\t** Game ID. A unique game identifier assigned by WChat.\n\t\t*/\n\t\tstats.Add_Field(FIELD_GAME_ID, PlanetWestwoodGameID);\n\n#ifdef WOLAPI_INTEGRATION\n\n\t\t//\tNumber of players initially in game.\n\t\tstats.Add_Field( FIELD_NUM_INITIAL_PLAYERS, (unsigned long)pWolapi->GameInfoCurrent.iPlayerCount );\n//debugprint( \"Stats: number of initial players is %i\\n\", pWolapi->GameInfoCurrent.iPlayerCount );\n\n\t\t//\tNumber of players remaining in game. Not sure of what use this will be statistically...\n\t\tstats.Add_Field( FIELD_NUM_REMAINING_PLAYERS, (unsigned long)Session.Players.Count() );\n//debugprint( \"Stats: number of remaining players is %i\\n\", Session.Players.Count() );\n\n\t\t//\tWhether or not this was a tournament game.\n\t\tstats.Add_Field( FIELD_TOURNAMENT, (unsigned char)( pWolapi->GameInfoCurrent.bTournament ? 1 : 0 ) );\n\n//\tajw This is now in WOLAPI...\n//\t\t//\tA unique value that identifies the machine that the game was played on.\n//\t\tHW_PROFILE_INFO hwinfo;\n//\t\t::GetCurrentHwProfile( &hwinfo );\n//\t\tstats.Add_Field( FIELD_HARDWARE_GUID, hwinfo.szHwProfileGuid );\n#endif\n\n\t\t/*\n\t\t** Start credits.\n\t\t*/\n\t\tstats.Add_Field(FIELD_START_CREDITS, (unsigned long)Session.Options.Credits);\n\n\t\t/*\n\t\t** Bases (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_BASES, Session.Options.Bases ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Tiberium (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_TIBERIUM, Session.Options.Tiberium ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Crates (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_CRATES, Session.Options.Goodies ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** AI Players (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_AI_PLAYERS, (unsigned long) Session.Options.AIPlayers);\n\n\t\t/*\n\t\t** Shadow regrowth enabled\n\t\t*/\n\t\tstats.Add_Field(FIELD_SHADOW_REGROWS, Special.IsShadowGrow ? \"ON\" : \"OFF\" );\n\n\t\t/*\n\t\t** Capture the flag mode (On/Off)\n\t\t*/\n\t\tstats.Add_Field(FIELD_CAPTURE_THE_FLAG, Special.IsCaptureTheFlag ? \"ON\" : \"OFF\");\n\n\t\t/*\n\t\t** Start unit count\n\t\t*/\n\t\tstats.Add_Field(FIELD_START_UNIT_COUNT, (unsigned long)Session.Options.UnitCount);\n\n\t\t/*\n\t\t** Tech level.\n\t\t*/\n\t\tstats.Add_Field(FIELD_TECH_LEVEL, (unsigned long)BuildLevel);\n\n\t\t/*\n\t\t** Scenario\n\t\t*/\n#if (1)\n\n\t\tstats.Add_Field(FIELD_SCENARIO, Session.Options.ScenarioDescription);\n\n#else //(1)\n\t\tchar fname[128];\n\t\tchar namebuffer[40];\n\t\tchar *abuffer = (char *)_ShapeBuffer;\n\t\tmemset(abuffer, '\\0', _ShapeBufferSize);\n\t\tsprintf(fname,\"%s.INI\",Scen.ScenarioName);\n\t\tCCFileClass fileo;\n\t\tfileo.Set_Name (fname);\n\t\tfileo.Read(abuffer, _ShapeBufferSize-1);\n\t\tfileo.Close();\n\t\tWWGetPrivateProfileString(\"Basic\", \"Name\", \"Nulls-Ville\", namebuffer, 40, abuffer);\n\t\tstats.Add_Field(FIELD_SCENARIO, namebuffer);\n\t\t//stats.Add_Field(FIELD_SCENARIO, MPlayerScenarios[ScenarioIdx]);\n#endif\t//(1)\n\n#ifdef WOLAPI_INTEGRATION\n\t\t//\tCompletion status is set for Tournament games only - ajw.\n\t\tif( pWolapi->GameInfoCurrent.bTournament )\n\t\t{\n#endif\n\n\t\t\t/*\n\t\t\t** Game completion status.\t\t\n\t\t\t**\n\t\t\t**  Connection lost.\n\t\t\t**  Player 1 won\n\t\t\t**  Player 2 won\n\t\t\t**  Player 1 won by resignation\n\t\t\t**  Player 2 won by resignation\n\t\t\t**  Player 1 aborted\n\t\t\t**  Player 2 aborted\n\t\t\t**\n\t\t\t**\tGame was a draw\n\t\t\t*/\n\t\t\tHouseClass *player1 = NULL;\n\t\t\tHouseClass *player2 = NULL;\n\t\t\tfor (int h=0 ; h<Session.Players.Count(); h++){\n\t\t\t\tHouseClass *ptr = HouseClass::As_Pointer ((HousesType)(h + HOUSE_MULTI1));\n\t\t\t\tif (ptr->IsHuman){\n\t\t\t\t\tif (player1){\n\t\t\t\t\t\tplayer2 = ptr;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tplayer1 = ptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tint completion = -1;\n\n\t\t\tif (player1 && player2){\t\t\t//\tCan this ever fail?\t\tajw\n#ifdef FIXIT_VERSION_3\n\t\t\t\t//\tSend IP addresses of both players.\n\t\t\t\tNetNumType net;\n\t\t\t\tNetNodeType node;\n\t\t\t\tchar szIPAddress[ 30 ];\n\t\t\t\tSession.Players[ 0 ]->Address.Get_Address( net, node );\n\t\t\t\tsprintf( szIPAddress, \"%i.%i.%i.%i\", node[0], node[1], node[2], node[3] );\n\t\t\t\tif( strcmp( szIPAddress, \"255.255.255.255\" ) == 0 )\n\t\t\t\t{\n\n\t\t\t\t\t//\tOk. It's not set. Let's try to get it ourselves...\n\t\t\t\t\tchar szHostName[ 512 ];\n\t\t\t\t\tint iRes = gethostname( szHostName, 512 );\n\t\t\t\t\tif( iRes != SOCKET_ERROR )\t//\telse forget about trying\n\t\t\t\t\t{\n//\t\t\t\t\t\tdebugprint( \"gethostname got me %s\\n\", szHostName );\n\t\t\t\t\t\tstruct hostent* pHostent = gethostbyname( szHostName );\n\t\t\t\t\t\tif( pHostent )\t//\telse forget about trying\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint i = 0;\n\t\t\t\t\t\t\tint* piAddress = (int*)pHostent->h_addr_list[ i ];\n\t\t\t\t\t\t\twhile( piAddress )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//\tThere is a non-null value for this h_addr_list entry.\n\t\t\t\t\t\t\t\tchar szAsciiIP[ 30 ];\n\t\t\t\t\t\t\t\tstrcpy( szAsciiIP, inet_ntoa( *( (struct in_addr*)piAddress ) ) );\n\t\t\t\t\t\t\t\t//\tWe have an address in the right form.\n\t\t\t\t\t\t\t\t//\tNow, is it an address in a private network? If so we should ignore it.\n\t\t\t\t\t\t\t\tunsigned char q1 = ( (char*)piAddress )[ 0 ];\t//\tFirst digit.\n\t\t\t\t\t\t\t\tunsigned char q2 = ( (char*)piAddress )[ 1 ];\t//\tSecond digit.\n//\t\t\t\t\t\t\t\tdebugprint( \"ip: %s\\n\", szAsciiIP );\n\t\t\t\t\t\t\t\tif( q1 == 10 || ( q1 == 172 && ( q2 >= 16 && q2 <= 31 ) ) || ( q1 == 192 && q2 == 168 ) )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t//\tThis is a private network address - ignore it and go on to next.\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstrcpy( szIPAddress, szAsciiIP );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpiAddress = (int*)pHostent->h_addr_list[ ++i ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n//\t\t\t\t\t\t\tdebugprint( \"gethostbyname failed. Error %i\\n\", WSAGetLastError() );\n\t\t\t\t\t}\n//\t\t\t\t\telse\n//\t\t\t\t\t\tdebugprint( \"gethostname failed with %i, error %i\\n\", iRes, WSAGetLastError() );\n\t\t\t\t}\n\t\t\t\tstats.Add_Field( FIELD_PLAYER1_IP, (char*)szIPAddress );\n\t\t\t\tSession.Players[ 1 ]->Address.Get_Address( net, node );\n\t\t\t\tsprintf( szIPAddress, \"%i.%i.%i.%i\", node[0], node[1], node[2], node[3] );\n\t\t\t\tstats.Add_Field( FIELD_PLAYER2_IP, (char*)szIPAddress );\n#endif\t\t\t\t\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\tif( Scen.bLocalProposesDraw && Scen.bOtherProposesDraw )\n\t\t\t\t{\n\t\t\t\t\tcompletion = COMPLETION_WASH;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n#endif\n\t\t\t\tif (ConnectionLost){\n#ifdef WOLAPI_INTEGRATION\n\t\t\t\t\tif( bReconnectDialogCancelled )\n\t\t\t\t\t{\n\t\t\t\t\t\tif( Session.Players[ 0 ]->Player.ID == HOUSE_MULTI1 )\n\t\t\t\t\t\t\t//\tI am player1.\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tcompletion = COMPLETION_CONNECTION_LOST;\n\t\t\t\t\t\tif( pWolapi->bDisconnectPingingCompleted )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchar szPingResult[ 8 ];\t\t//\tFormat is \"x/y a/b\", e.g., \"3/5 4/5\"\n\t\t\t\t\t\t\tpWolapi->DisconnectPingResultsString( szPingResult );\n\t\t\t\t\t\t\tstats.Add_Field( FIELD_DISCONNECT_PINGS, (char*)szPingResult );\n\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n//\t\t\t\t\t\t\tdebugprint( \"Stats: bDisconnectPingingCompleted is false! Should be finished!!!!!!!!!!!!!!!\\n\" );\n\t\t\t\t\t}\n#else\n\t\t\t\t\tcompletion = COMPLETION_CONNECTION_LOST;\n#endif\n\t\t\t\t}else{\n\n\t\t\t\t\tif (player1->IsGiverUpper){\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (player2->IsGiverUpper){\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t}\n\n\n\t\t\t\t\tif (player2->IsDefeated){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t** Player 1 won. Find out how.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON;\n\t\t\t\t\t\tif (player2->IsResigner){\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_RESIGNATION;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tif (player2->IsGiverUpper){\n\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t}else{\n\n\t\t\t\t\t\tif (player1->IsDefeated){\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t** Player 2 won. Find out how.\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON;\n\t\t\t\t\t\t\tif (player1->IsResigner){\n\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_RESIGNATION;\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\tif (player1->IsGiverUpper){\n\t\t\t\t\t\t\t\t\tcompletion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef FIXIT_VERSION_3\t\t//\tStalemate games.\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tstats.Add_Field (FIELD_COMPLETION, (char) completion);\n//debugprint( \"Stats: Tournament game completion value: %i\\n\", completion );\n\n#ifdef WOLAPI_INTEGRATION\n\t\t}\n#endif\n\n\n\t\t/*\n\t\t** Game start time (GMT or Pacific?)\n\t\t**\n\t\t** Passed from WChat\n\t\t*/\n\t\tstats.Add_Field (FIELD_START_TIME, (long) PlanetWestwoodStartTime);\n\n\t\t/*\n\t\t** Game duration (seconds).\n\t\t*/\n\t\tstats.Add_Field (FIELD_GAME_DURATION, (long) GameEndTime/60);\n\n\t\t/*\n\t\t** Avg. frame rate.\n\t\t*/\n#ifdef FIXIT_IP_CRASH\n\t\tlong divisor = GameEndTime / 60;\n\t\tif (divisor != 0) {\n\t\t\tstats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );\n\t\t} else {\n\t\t\tstats.Add_Field (FIELD_FRAME_RATE, 0l);\n\t\t}\n#else\n\t\tstats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );\n#endif\n\n\n\t\t/*\n\t\t** CPU type\n\t\t*/\n\t\tstats.Add_Field (FIELD_CPU_TYPE, (char)CPUType);\n\n\t\t/*\n\t\t** Memory\n\t\t*/\n\t\tMEMORYSTATUS\tmem_info;\n\t\tmem_info.dwLength=sizeof(mem_info);\n\t\tGlobalMemoryStatus(&mem_info);\n\t\tstats.Add_Field (FIELD_MEMORY, (long)mem_info.dwTotalPhys);\n\n\t\t/*\n\t\t** Video memory\n\t\t*/\n\t\tDDCAPS\tvideo_capabilities;\n\t\tlong\t\tvideo_memory;\n\n\t\tif (DirectDrawObject){\n\t\t\tvideo_capabilities.dwSize = sizeof (video_capabilities);\n\t\t\tif (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){\n\t\t\t\tvideo_memory = video_capabilities.dwVidMemTotal;\n\t\t\t\tvideo_memory += 1024*1024 -1;\n\t\t\t\tvideo_memory &= 0xfff00000;\n\t\t\t\tstats.Add_Field (FIELD_VIDEO_MEMORY, (long) video_memory);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Game speed setting.\n\t\t*/\n\t\tstats.Add_Field (FIELD_SPEED_SETTING, (char)Options.GameSpeed);\n\n\t\t/*\n\t\t** Red Alert version/build date\n\t\t*/\n\t\tchar\tversion[128];\n\t\tsprintf (version, \"V%s\", VerNum.Version_Name() );\n\t\tstats.Add_Field (FIELD_GAME_VERSION, (char*)version);\n\n\t\tchar path_to_exe[280];\n\t\tFILETIME write_time;\t\t//File time is 64 bits\n\n\t\tGetModuleFileName (ProgramInstance, path_to_exe, 280);\n\t\tRawFileClass file;\n\t\tfile.Set_Name(path_to_exe);\n\t\tfile.Open();\n\t\tHANDLE handle = file.Get_File_Handle();\n\n\t\tif (handle != INVALID_HANDLE_VALUE){\n\t\t\tif (GetFileTime (handle, NULL, NULL, &write_time)){\n\t\t\t\twrite_time.dwLowDateTime = htonl (write_time.dwLowDateTime);\n\t\t\t\twrite_time.dwHighDateTime = htonl (write_time.dwHighDateTime);\n\t\t\t\tstats.Add_Field (FIELD_GAME_BUILD_DATE, (void*)&write_time, sizeof (write_time));\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t** Covert installed? (Yes/No)\n\t\t*/\n\t\t//stats.Add_Field(FIELD_COVERT_PRESENT, (char) Expansion_Present());\n\n\t\t/*\n\t\t** Build the player specific statistics\n\t\t**\n\t\t*/\n#ifdef WOLAPI_INTEGRATION\n\t\tfor (int house = 0 ; house < 8 ; house++){\n#else\n\t\tfor (int house = 0 ; house < 2 ; house++){\n#endif\n\t\t\tplayer = HouseClass::As_Pointer((HousesType) (house + HOUSE_MULTI1));\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\tif( !player )\n\t\t\t\tcontinue;\n#endif\n\n\t\t\t/*\n\t\t\t** Player handle.\n\t\t\t*/\n\t\t\tfield_player_handle[3] = '1' + (char)house;\n#ifdef WOLAPI_INTEGRATION\n\t\t\tstats.Add_Field (field_player_handle, (char*) player->InitialName);\n//debugprint( \"Stats: Player %i name %s\\n\", house, (char*) player->InitialName );\n//debugprint( \"Stats: Player %i ending name %s\\n\", house, (char*) player->IniName );\n#else\n\t\t\tstats.Add_Field (field_player_handle, (char*) player->IniName);\n#endif\n\n#ifdef WOLAPI_INTEGRATION\n\t\t\t//\tWhether or not this player was taken over by the computer, due to his quitting the game.\n\t\t\tif( strcmp( player->IniName, player->InitialName ) )\n\t\t\t\tstats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)1 );\n\t\t\telse\n\t\t\t\tstats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)0 );\n#endif\n\t\t\t/*\n\t\t\t** Player team. (NOD or GDI)\n\t\t\t*/\n\t\t\tfield_player_team[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_team, houses[player->ActLike]);\n\n\t\t\t/*\n\t\t\t** Player color\n\t\t\t*/\n\t\t\tfield_player_color[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_color, (unsigned char) (player->Class->House - HOUSE_MULTI1));\n\n\t\t\t/*\n\t\t\t** Player end credits.\n\t\t\t*/\n\t\t\tfield_player_credits[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_credits, player->Credits + player->Tiberium);\n\n\t\t\t/*\n\t\t\t** Number of each unit/building type built\n\t\t\t*/\n\t\t\tfield_player_infantry_bought[3] = '1' + (char)house;\n\t\t\tfield_player_units_bought[3] = '1' + (char)house;\n\t\t\tfield_player_planes_bought[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_bought[3] = '1' + (char)house;\n\t\t\tfield_player_vessels_bought[3] = '1' + (char)house;\n\n\t\t\tplayer->InfantryTotals->To_Network_Format();\n\t\t\tplayer->UnitTotals->To_Network_Format();\n\t\t\tplayer->AircraftTotals->To_Network_Format();\n\t\t\tplayer->BuildingTotals->To_Network_Format();\n\t\t\tplayer->VesselTotals->To_Network_Format();\n\n\t\t\tstats.Add_Field (field_player_infantry_bought, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_bought, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_bought, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_bought, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_vessels_bought, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);\n\n\t\t\tplayer->InfantryTotals->To_PC_Format();\n\t\t\tplayer->UnitTotals->To_PC_Format();\n\t\t\tplayer->AircraftTotals->To_PC_Format();\n\t\t\tplayer->BuildingTotals->To_PC_Format();\n\n\t\t\t/*\n\t\t\t** Clear out the counts and use the space to count up the current number of units/buildings\n\t\t\t*/\n\t\t\tplayer->InfantryTotals->Clear_Unit_Total();\n\t\t\tplayer->AircraftTotals->Clear_Unit_Total();\n\t\t\tplayer->UnitTotals->Clear_Unit_Total();\n\t\t\tplayer->BuildingTotals->Clear_Unit_Total();\n\t\t\tplayer->VesselTotals->Clear_Unit_Total();\n\n\t\t\t/*\n\t\t\t** Number of units remaining to player\n\t\t\t*/\n\t\t\tfor (index = 0; index < Units.Count(); index++) {\n\t\t\t\tUnitClass const * unit = Units.Ptr(index);\n\t\t\t\tif (player == unit->House){\n\t\t\t\t\tplayer->UnitTotals->Increment_Unit_Total (unit->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Infantry.Count(); index++) {\n\t\t\tInfantryClass const * infantry = Infantry.Ptr(index);\n\t\t\t\tif (player == infantry->House && !infantry->Class->IsCivilian){\n\t\t\t\t\tplayer->InfantryTotals->Increment_Unit_Total (infantry->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Aircraft.Count(); index++) {\n\t\t\tAircraftClass const * aircraft = Aircraft.Ptr(index);\n\t\t\t\tif (player == aircraft->House){\t// &&\taircraft->Class->Type != AIRCRAFT_CARGO){\n\t\t\t\t\tplayer->AircraftTotals->Increment_Unit_Total (aircraft->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Buildings.Count(); index++) {\n\t\t\tBuildingClass const * building = Buildings.Ptr(index);\n\t\t\t\tif (player == building->House){\n\t\t\t\t\tplayer->BuildingTotals->Increment_Unit_Total (building->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (index = 0; index < Vessels.Count(); index++) {\n\t\t\tVesselClass const * vessel = Vessels.Ptr(index);\n\t\t\t\tif (player == vessel->House){\n\t\t\t\t\tplayer->VesselTotals->Increment_Unit_Total (vessel->Class->Type);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tplayer->InfantryTotals->To_Network_Format();\n\t\t\tplayer->UnitTotals->To_Network_Format();\n\t\t\tplayer->AircraftTotals->To_Network_Format();\n\t\t\tplayer->BuildingTotals->To_Network_Format();\n\t\t\tplayer->VesselTotals->To_Network_Format();\n\n\t\t\tfield_player_infantry_left[3] = '1' + (char)house;\n\t\t\tfield_player_units_left[3] = '1' + (char)house;\n\t\t\tfield_player_planes_left[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_left[3] = '1' + (char)house;\n#ifdef FIXIT_IP_STATS\n\t\t\tfield_player_vessels_left[3] = '1' + (char)house;\n#endif\n\t\t\tstats.Add_Field (field_player_infantry_left, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_left, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_left, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_left, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_vessels_left, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);\n\n\n\t\t\t/*\n\t\t\t** Number of enemy units/buildings of each type destroyed.\n\t\t\t*/\n\n\t\t\tplayer->DestroyedInfantry->To_Network_Format();\n\t\t\tplayer->DestroyedUnits->To_Network_Format();\n\t\t\tplayer->DestroyedAircraft->To_Network_Format();\n\t\t\tplayer->DestroyedBuildings->To_Network_Format();\n\t\t\tplayer->DestroyedVessels->To_Network_Format();\n\n\t\t\tfield_player_infantry_killed[3] = '1' + (char)house;\n\t\t\tfield_player_units_killed[3] = '1' + (char)house;\n\t\t\tfield_player_planes_killed[3] = '1' + (char)house;\n\t\t\tfield_player_buildings_killed[3] = '1' + (char)house;\n\t\t\tfield_player_vessels_killed[3] = '1' + (char)house;\n\n\t\t\tstats.Add_Field (field_player_infantry_killed, (void*) player->DestroyedInfantry->Get_All_Totals(), player->DestroyedInfantry->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_units_killed, (void*) player->DestroyedUnits->Get_All_Totals(), player->DestroyedUnits->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_planes_killed, (void*) player->DestroyedAircraft->Get_All_Totals(), player->DestroyedAircraft->Get_Unit_Count()*4);\n\t\t\tstats.Add_Field (field_player_buildings_killed, (void*) player->DestroyedBuildings->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);\n#ifdef FIXIT_VERSION_3\n\t\t\tstats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedVessels->Get_Unit_Count()*4);\n#else\n\t\t\tstats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);\n#endif\n\n\n\t\t\t/*\n\t\t\t** Number and type of enemy buildings captured\n\t\t\t*/\n\t\t\tfield_player_buildings_captured[3] = '1' + (char)house;\n\t\t\tplayer->CapturedBuildings->To_Network_Format();\n\t\t\tstats.Add_Field (field_player_buildings_captured, (void*) player->CapturedBuildings->Get_All_Totals(), player->CapturedBuildings->Get_Unit_Count()*4);\n\n\t\t\t/*\n\t\t\t** Number of crates discovered and their contents\n\t\t\t*/\n\t\t\tfield_player_crates_found[3] = '1' + (char)house;\n\t\t\tplayer->TotalCrates->To_Network_Format();\n\t\t\tstats.Add_Field (field_player_crates_found, (void*) player->TotalCrates->Get_All_Totals(), player->TotalCrates->Get_Unit_Count()*4);\n\n\t\t\t/*\n\t\t\t** Amount of tiberium turned into credits\n\t\t\t*/\n\t\t\tfield_player_harvested[3] = '1' + (char)house;\n\t\t\tstats.Add_Field (field_player_harvested, (unsigned long) player->HarvestedCredits);\n\n\t\t}\n\n\t\t/*\n\t\t** Create the comms packet to be sent\n\t\t*/\n\t\tpacket = stats.Create_Comms_Packet(packet_size);\n\n#ifndef WOLAPI_INTEGRATION\t//\tajw - 'PacketLater' is no longer ever used.\n\t\t/*\n\t\t** If a player disconnected then dont send the packet at this time - save it for later\n\t\t*/\n\t\tif (completion == COMPLETION_PLAYER_1_WON_BY_DISCONNECTION\n\t\t\t|| completion == COMPLETION_PLAYER_2_WON_BY_DISCONNECTION){\n\t\t\tPacketLater = packet;\n\t\t\treturn;\n\t\t}\n#endif\n\n\t}else{\t\t//else for if (!PacketLater)\n\n\t\t/*\n\t\t** Send the packet we calculated earlier when the disconnect occurred\n\t\t*/\n\t\tpacket = PacketLater;\n\t\tPacketLater = NULL;\n\t}\n\n\t/*\n\t** Send it.....\n\t*/\n\tconst char* szGameResServer;\n\tint iPort;\n\tif( pWolapi->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME )\n\t{\n\t\tszGameResServer = pWolapi->szGameResServerHost2;\n\t\tiPort = pWolapi->iGameResServerPort2;\n\t}\n\telse\n\t{\n\t\tszGameResServer = pWolapi->szGameResServerHost1;\n\t\tiPort = pWolapi->iGameResServerPort1;\n\t}\n\n\tif( *szGameResServer )\n\t{\n\t\tif( pWolapi->pNetUtil->RequestGameresSend( szGameResServer, iPort, (unsigned char*)packet, packet_size ) != S_OK )\n\t\t\t//debugprint( \"RequestGameresSend( %s, %i ) failed!!!\\n\", szGameResServer, iPort );\n\t\t\t;\n\t}\n\n\t/*\n\t** Save it to disk as well so I can see it\n\t*/\n//\tRawFileClass anotherfile (\"packet.net\");\n//\tanotherfile.Write(packet, packet_size);\n//debugprint( \"Wrote out packet.net\\n\" );\n\n\t/*\n\t** Tidy up\n\t*/\n\tdelete [] packet;\n\n\tGameStatisticsPacketSent = true;\n#endif // INTERNET_OFF\n#endif\n}\n\n\n\nvoid Register_Game_Start_Time(void)\n{\n\n\tGameTimer.Set (0, true);\n\tGameTimerInUse = true;\n}\n\nextern void Register_Game_End_Time(void)\n{\n\tGameEndTime = GameTimer.Time();\n\tGameTimerInUse = false;\n}\n\n\n#endif\t//WIN32\n"
  },
  {
    "path": "REDALERT/STRAW.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/STRAW.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : STRAW.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/02/96                                                     *\n *                                                                                             *\n *                  Last Update : July 3, 1996 [JLB]                                           *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   Straw::Get_From -- Connect one straw segment to another.                                  *\n *   Straw::Get -- Fetch some data from the straw chain.                                       *\n *   Straw::~Straw -- Destructor for a straw segment.                                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#include\t\"straw.h\"\n#include\t<stddef.h>\n#include\t<string.h>\n\n\n/***********************************************************************************************\n * Straw::~Straw -- Destructor for a straw segment.                                            *\n *                                                                                             *\n *    This destructor will remove this segment from the straw chain. If there were any         *\n *    connected segments to either side, they will be joined so that the straw chain will      *\n *    still remain linked.                                                                     *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nStraw::~Straw(void)\n{\n\tif (ChainTo != NULL) {\n\t\tChainTo->ChainFrom = ChainFrom;\n\t}\n\tif (ChainFrom != NULL) {\n\t\tChainFrom->Get_From(ChainTo);\n\t}\n\n\tChainFrom = NULL;\n\tChainTo = NULL;\n}\n\n\n/***********************************************************************************************\n * Straw::Get_From -- Connect one straw segment to another.                                    *\n *                                                                                             *\n *    Use this routine to connect straw segments together. The straw segment specified as the  *\n *    parameter will be linked to the chain such that when data is requested, it will be       *\n *    fetched from the specified link before being processed by this link.                     *\n *                                                                                             *\n * INPUT:   straw -- Pointer to the straw segment that data will be fetched from.              *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid Straw::Get_From(Straw * straw)\n{\n\tif (ChainTo != straw) {\n\t\tif (straw != NULL && straw->ChainFrom != NULL) {\n\t\t\tstraw->ChainFrom->Get_From(NULL);\n\t\t\tstraw->ChainFrom = NULL;\n\t\t}\n\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = NULL;\n\t\t}\n\n\t\tChainTo = straw;\n\t\tif (ChainTo != NULL) {\n\t\t\tChainTo->ChainFrom = this;\n\t\t}\n\t}\n}\n\n\n/***********************************************************************************************\n * Straw::Get -- Fetch some data from the straw chain.                                         *\n *                                                                                             *\n *    Use this routine to fetch some data from the straw. It is presumed that this routine     *\n *    will be overridden to provide some useful functionality. At this level, the straw chain  *\n *    merely passes the request on to the next straw in the chain.                             *\n *                                                                                             *\n * INPUT:   source   -- Pointer to the buffer to hold the requested data.                      *\n *                                                                                             *\n *          length   -- The number of bytes requested.                                         *\n *                                                                                             *\n * OUTPUT:  Returns with the number of bytes stored into the buffer. If the number returned    *\n *          is less than the number requested, then this indicates that the straw data has     *\n *          been exhausted.                                                                    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/03/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nint Straw::Get(void * source, int slen)\n{\n\tif (ChainTo != NULL) {\n\t\treturn(ChainTo->Get(source, slen));\n\t}\n\treturn(0);\n}\n\n\n"
  },
  {
    "path": "REDALERT/STUB.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n#include\t<stdlib.h>\n#include\t<stdio.h>\n\nvoid main(void)\n{\n\tprintf(\"Run C&C.COM.\\n\");\n}\n"
  },
  {
    "path": "REDALERT/STYLE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/*\n       STYLE GUIDE FOR COMMAND & CONQUER : TIBERIAN SUN\n\nIn addition to the standard Westwood programmer's style guide, the following\nguidelines apply.\n\n> Use every feature the compiler has that will help catch bugs and encourage\nsolid portable coding practices. i.e., turn on all warnings and treat all warnings\nas errors. Use helper programs such as Lint, BoundsChecker, or CodeGuard whenever\npossible.\n\n> Keep related items together. Examples: Declare variables right before they are\nused. Keep functions that work on the same subsystem, within the same module.\n\n> Use consistent commenting and spacing style. Examples: see existing Red Alert\ncode. Creative freedom does not extend to formatting.\n\n> Use descriptive variable names. Examples: Use \"index\" rather than \"i\". Use\n\"unit_index\" rather than \"index\".\n\n> Use a consistent variable and function naming convention. Examples; boolean\nvariables should begin with \"Is\" (e.g., \"IsActive\", \"IsFiring\"). Functions that\nexist solely to return a similar boolean query should begin with \"Is_\".\n\n> If you have a variable that only serves a boolean function, then declare it\nas \"bool\" rather than as \"int\" and assign it \"true\" or \"false\" rather than \"1\"\nor \"0\".\n\n> Choose function and variable names that are precise, descriptive, and concise (in that\norder).\n\n> Hide data where possible: Examples: If a global is only used in one module, make\nit static to that module. If a helper function is only used in one module, make it\nstatic as well. Hide class members in the private section if they aren't needed\npublic. Most variables aren't needed as public.\n\n> Keep function bodies short. It is often times, more easy to understand and maintain\nif a very long function is broken up into helper functions with descriptive names.\nA clue if a function is too long is if you can page down 5 times and still be somewhere\nin the middle of the function. If you can page down 10 times and still be in the\nfunction, you've got a serious function size problem.\n\n> Compare pointers to NULL and integer types to zero (NULL) instead of using the\n\"if (x)\" or \"if (!x)\" format. This short format should only be used for boolean\nvalues and expressions. It is just as efficient and it makes it more clear to the\nreader that the variable is a pointer and not a simple boolean value.\n\n> Use \"const\" when declaring any member functions that do not modify data. Corollary --\nmake sure any function that appears like it will not modify data will, in fact, NOT\nmodify any data. Example; A function called Is_Able_To_Move() shouldn't modify the\nobject nor should it actually cause something to start moving! The use of \"const\" is a\nvariation on style guide rule #1 (use the compiler to help ensure proper code).\n\n> Shun using assembly language except in extreme cases. Such would be if a\nfunction can only be performed by using assembly (requires special opcodes), or\nif performance would be PROVEABLY dramatically improved. Don't code in assembly for\nperformance reasons if there isn't benchmarking code in place to analyze the results.\nAs a corollary, design a better algorithm as the first recourse.\n\n> Keep class interfaces small and simple.\n\n> Organize algorithms to use as few special case \"if\" statements as possible. Data\ntables or data files are preferred. This follows the generally good guideline of offloading\nas much processing as possible to compile-time rather than run-time.\n\n*/\n"
  },
  {
    "path": "REDALERT/SUPER.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SUPER.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SUPER.CPP                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 07/28/95                                                     *\n *                                                                                             *\n *                  Last Update : October 11, 1996 [JLB]                                       *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   SuperClass::AI -- Process the super weapon AI.                                            *\n *   SuperClass::Anim_Stage -- Fetches the animation stage for this super weapon.              *\n *   SuperClass::Discharged -- Handles discharged action for special super weapon.             *\n *   SuperClass::Enable -- Enable this super special weapon.                                   *\n *   SuperClass::Forced_Charge -- Force the super weapon to full charge state.                 *\n *   SuperClass::Impatient_Click -- Called when player clicks on unfinished super weapon.      *\n *   SuperClass::Recharge -- Starts the special super weapon recharging.                       *\n *   SuperClass::Remove -- Removes super weapon availability.                                  *\n *   SuperClass::SuperClass -- Constructor for special super weapon objects.                   *\n *   SuperClass::Suspend -- Suspend the charging of the super weapon.                          *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n\n\n/***********************************************************************************************\n * SuperClass::SuperClass -- Constructor for special super weapon objects.                     *\n *                                                                                             *\n *    This is the constructor for the super weapons.                                           *\n *                                                                                             *\n * INPUT:   recharge    -- The recharge delay time (in game frames).                           *\n *                                                                                             *\n *          charging    -- Voice to announce that the weapon is charging.                      *\n *                                                                                             *\n *          ready       -- Voice to announce that the weapon is fully charged.                 *\n *                                                                                             *\n *          impatient   -- Voice to announce current charging state.                           *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nSuperClass::SuperClass(int recharge, bool powered, VoxType charging, VoxType ready, VoxType impatient, VoxType suspend) :\n\tIsPowered(powered),\n\tIsPresent(false),\n\tIsOneTime(false),\n\tIsReady(false),\n\tControl(0),\n\tOldStage(-1),\n\tVoxRecharge(ready),\n\tVoxCharging(charging),\n\tVoxImpatient(impatient),\n\tVoxSuspend(suspend),\n\tRechargeTime(recharge)\n{\n}\n\n\n/***********************************************************************************************\n * SuperClass::Suspend -- Suspend the charging of the super weapon.                            *\n *                                                                                             *\n *    This will temporarily put on hold the charging of the special weapon. This might be the  *\n *    result of insufficient power.                                                            *\n *                                                                                             *\n * INPUT:   on -- Should the weapon charging be suspended? Else, it will unsuspend.            *\n *                                                                                             *\n * OUTPUT:  Was the weapon suspend state changed?                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Suspend(bool on)\n{\n\tif (IsPresent && !IsReady && !IsOneTime && on == Control.Is_Active()) {\n\t\tif (!on) {\n\t\t\tControl.Start();\n\t\t} else {\n\t\t\tControl.Stop();\n\t\t}\n//\t\tif (on != IsSuspended) {\n//\t\t\tif (on) {\n//\t\t\t\tSuspendTime = Control;\n//\t\t\t} else {\n//\t\t\t\tControl = SuspendTime;\n//\t\t\t}\n//\t\t\tIsSuspended = on;\n\t\t\treturn(true);\n//\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Enable -- Enable this super special weapon.                                     *\n *                                                                                             *\n *    This routine is called when the special weapon needs to be activated. This is used for   *\n *    both the normal super weapons and the special one-time super weapons (from crates).      *\n *                                                                                             *\n * INPUT:   onetime  -- Is this a special one time super weapon?                               *\n *                                                                                             *\n *          player   -- Is this weapon for the player? If true, then there might be a voice    *\n *                      announcement of this weapon's availability.                            *\n *                                                                                             *\n *          quiet    -- Request that the weapon start in suspended state (quiet mode).         *\n *                                                                                             *\n * OUTPUT:  Was the special super weapon enabled? Failure might indicate that the weapon was   *\n *          already available.                                                                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Enable(bool onetime, bool player, bool quiet)\n{\n\tif (!IsPresent) {\n\t\tIsPresent = true;\n\t\tIsOneTime = onetime;\n\t\tbool retval = Recharge(player && !quiet);\n\t\tif (quiet) Suspend(true);\n\t\treturn(retval);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Remove -- Removes super weapon availability.                                    *\n *                                                                                             *\n *    Call this routine when the super weapon should be removed because of some outside        *\n *    force. For one time special super weapons, they can never be removed except as the       *\n *    result of discharging them.                                                              *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Was the special weapon removed and disabled?                                       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Remove(bool forced)\n{\n\tif (IsPresent && (!IsOneTime || forced)) {\n\t\tIsReady = false;\n\t\tIsPresent = false;\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Recharge -- Starts the special super weapon recharging.                         *\n *                                                                                             *\n *    This routine is called when the special weapon is allowed to recharge. Suspension will   *\n *    be disabled and the animation process will begin.                                        *\n *                                                                                             *\n * INPUT:   player   -- Is this for a player owned super weapon? If so, then a voice           *\n *                      announcement might be in order.                                        *\n *                                                                                             *\n * OUTPUT:  Was the super weapon begun charging up?                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Recharge(bool player)\n{\n\tif (IsPresent && !IsReady) {\n//\t\tIsSuspended = false;\n\t\tOldStage = -1;\n\t\tControl.Start();\n\t\tControl = RechargeTime;\n\n#ifdef CHEAT_KEYS\n\t\tif (Special.IsSpeedBuild) {\n\t\t\tControl = 1;\n\t\t}\n#endif\n\n\t\tif (player) {\n\t\t\tSpeak(VoxCharging);\n\t\t}\n\t\treturn(true);\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * Superclass::Discharged -- Handles discharged action for special super weapon.               *\n *                                                                                             *\n *    This routine should be called when the special super weapon has been discharged. The     *\n *    weapon will either begin charging anew or will be removed entirely -- depends on the     *\n *    one time flag for the weapon.                                                            *\n *                                                                                             *\n * INPUT:   player   -- Is this special weapon for the player? If so, then there might be a    *\n *                      voice announcement.                                                    *\n *                                                                                             *\n * OUTPUT:  Should the sidebar be reprocessed because the special weapon has been eliminated?  *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::Discharged(bool player)\n{\n\tif (Control.Is_Active() && IsPresent && IsReady) {\n\t\tIsReady = false;\n\t\tif (IsOneTime) {\n\t\t\tIsOneTime = false;\n\t\t\treturn(Remove());\n\t\t} else {\n\t\t\tRecharge(player);\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::AI -- Process the super weapon AI.                                              *\n *                                                                                             *\n *    This routine will process the charge up AI for this super weapon object. If the weapon   *\n *    has advanced far enough to change any sidebar graphic that might represent it, then      *\n *    \"true\" will be returned. Use this return value to intelligently update the sidebar.      *\n *                                                                                             *\n * INPUT:   player   -- Is this for the player? If it is and the weapon is now fully charged,  *\n *                      then this fully charged state will be announced to the player.         *\n *                                                                                             *\n * OUTPUT:  Was the weapon's state changed such that a sidebar graphic update will be          *\n *          necessary?                                                                         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool SuperClass::AI(bool player)\n{\n\tif (IsPresent && !IsReady) {\n\t\tif (!Control.Is_Active()) {\n\t\t\tif (OldStage != -1) {\n\t\t\t\tOldStage = -1;\n\t\t\t\treturn(true);\n\t\t\t}\n\t\t} else {\n\t\t\tif (Control == 0) {\n\t\t\t\tIsReady = true;\n\t\t\t\tif (player) {\n\t\t\t\t\tSpeak(VoxRecharge);\n\t\t\t\t}\n\t\t\t\treturn(true);\n\t\t\t} else {\n\t\t\t\tif (Anim_Stage() != OldStage) {\n\t\t\t\t\tOldStage = Anim_Stage();\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn(false);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Anim_Stage -- Fetches the animation stage for this super weapon.                *\n *                                                                                             *\n *    This will return the current animation stage for this super weapon. The value will be    *\n *    between zero (uncharged) to ANIMATION_STAGES (fully charged). Use this value to render   *\n *    the appropriate graphic on the sidebar.                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with the current animation stage for this special super weapon powerup.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *   10/11/1996 JLB : Doesn't show complete until really complete.                             *\n *=============================================================================================*/\nint SuperClass::Anim_Stage(void) const\n{\n\tif (IsPresent) {\n\t\tif (IsReady) {\n\t\t\treturn(ANIMATION_STAGES);\n\t\t}\n//\t\tint time = Control;\n//\t\tif (IsSuspended) {\n//\t\t\ttime = SuspendTime;\n//\t\t}\n\n\t\tint stage = ANIMATION_STAGES * fixed(RechargeTime-Control.Value(), RechargeTime);\n\t\tstage = min(stage, ANIMATION_STAGES-1);\n\t\treturn(stage);\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * SuperClass::Impatient_Click -- Called when player clicks on unfinished super weapon.        *\n *                                                                                             *\n *    This routine is called when the player clicks on the super weapon icon on the sidebar    *\n *    when the super weapon is not ready yet. This results in a voice message feedback to the  *\n *    player.                                                                                  *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/28/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SuperClass::Impatient_Click(void) const\n{\n\tif (!Control.Is_Active()) {\n\t\tSpeak(VoxSuspend);\n\t} else {\n\t\tSpeak(VoxImpatient);\n\t}\n}\n\n\n/***********************************************************************************************\n * SuperClass::Forced_Charge -- Force the super weapon to full charge state.                   *\n *                                                                                             *\n *    This routine will force the special weapon to full charge state. Call it when the weapon *\n *    needs to be instantly charged. The airstrike (when it first becomes available) is a      *\n *    good example.                                                                            *\n *                                                                                             *\n * INPUT:   player   -- Is this for the player? If true, then the full charge state will be    *\n *                      announced.                                                             *\n *                                                                                             *\n * OUTPUT:  none                                                                               *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/29/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nvoid SuperClass::Forced_Charge(bool player)\n{\n\tif (IsPresent) {\n\t\tIsReady = true;\n\t\tControl.Start();\n\t\tControl = 0;\n//\t\tIsSuspended = false;\n\t\tif (player) {\n\t\t\tSpeak(VoxRecharge);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "REDALERT/SUPPORT.ASM",
    "content": ";\n; Copyright 2020 Electronic Arts Inc.\n;\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n; software: you can redistribute it and/or modify it under the terms of \n; the GNU General Public License as published by the Free Software Foundation, \n; either version 3 of the License, or (at your option) any later version.\n\n; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n; in the hope that it will be useful, but with permitted additional restrictions \n; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n; distributed with this program. You should have received a copy of the \n; GNU General Public License along with permitted additional restrictions \n; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.\n\n; $Header:   F:\\projects\\c&c0\\vcs\\code\\support.asv   5.0   11 Nov 1996 09:40:30   JOE_BOSTIC  $\n;***************************************************************************\n;**   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **\n;***************************************************************************\n;*                                                                         *\n;*                 Project Name : Command & Conquer                        *\n;*                                                                         *\n;*                    File Name : SUPPORT.ASM                              *\n;*                                                                         *\n;*                   Programmer : Joe L. Bostic                            *\n;*                                                                         *\n;*                   Start Date : September 23, 1993                       *\n;*                                                                         *\n;*                  Last Update : May 10, 1994   [JLB]                     *\n;*                                                                         *\n;*-------------------------------------------------------------------------*\n;* Functions:                                                              *\n;*   strtrim -- Remove the trailing white space from a string.             *\n;*   Fat_Put_Pixel -- Draws a fat pixel.                                   *\n;*   Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*\n;*   Remove_From_List -- Removes a pointer from a list of pointers.        *\n;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\n\nIDEAL\nP386\nMODEL USE32 FLAT\n\nINCLUDE \"gbuffer.inc\"\n\tDISPLAY\t\"Command & Conquer assembly support routines.\"\n\n\tCODESEG\n\n\n;***************************************************************************\n;* Fat_Put_Pixel -- Draws a fat pixel.                                     *\n;*                                                                         *\n;*    Use this routine to draw a \"pixel\" that is bigger than 1 pixel       *\n;*    across.  This routine is faster than drawing a similar small shape   *\n;*    and faster than calling Fill_Rect.                                   *\n;*                                                                         *\n;* INPUT:   x,y       -- Screen coordinates to draw the pixel's upper      *\n;*                       left corner.                                      *\n;*                                                                         *\n;*          color     -- The color to render the pixel in.                 *\n;*                                                                         *\n;*          size      -- The number of pixels width of the big \"pixel\".    *\n;*                                                                         *\n;*          page      -- The pointer to a GraphicBuffer class or something *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   03/17/1994 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)\n\tGLOBAL\tC Fat_Put_Pixel:NEAR\n\tPROC\tFat_Put_Pixel C near\n\tUSES\teax, ebx, ecx, edx, edi, esi\n\n\tARG\tx:DWORD\t\t; X coordinate of upper left pixel corner.\n\tARG\ty:DWORD\t\t; Y coordinate of upper left pixel corner.\n\tARG\tcolor:DWORD\t; Color to use for the \"pixel\".\n\tARG\tsiz:DWORD\t; Size of \"pixel\" to plot (square).\n\tARG\tgpage:DWORD\t; graphic page address to plot onto\n\n\tcmp\t[siz],0\n\tje\tshort ??exit\n\n\t; Set EDI to point to start of logical page memory.\n\t;*===================================================================\n\t; Get the viewport information and put bytes per row in ecx\n\t;*===================================================================\n\tmov\tebx,[gpage]\t\t\t\t; get a pointer to viewport\n\tmov\tedi,[(GraphicViewPort ebx).GVPOffset]\t; get the correct offset\n\n\t; Verify the the Y pixel offset is legal.\n\tmov\teax,[y]\n\tcmp\teax,[(GraphicViewPort ebx).GVPHeight]\t;YPIXEL_MAX\n\tjae\tshort ??exit\n\tmul\t[(GraphicViewPort ebx).GVPWidth]\n\tadd\tedi,eax\n\n\t; Verify the the X pixel offset is legal.\n\tmov\tedx,[(GraphicViewPort ebx).GVPWidth]\n\tcmp\tedx,[x]\n\tjbe\tshort ??exit\n\tadd\tedi,[x]\n\n\t; Write the pixel to the screen.\n\tmov\tebx,[siz]\t\t; Copy of pixel size.\n\tsub\tedx,ebx\t\t\t; Modulo to reach start of next row.\n\tmov\teax,[color]\n??again:\n\tmov\tecx,ebx\n\trep stosb\n\tadd\tedi,edx\t\t\t; EDI points to start of next row.\n\tdec\t[siz]\n\tjnz\tshort ??again\n\n??exit:\n\tret\n\n\tENDP\tFat_Put_Pixel\n\n\nif 0\n\n;***************************************************************************\n;* strtrim -- Remove the trailing white space from a string.               *\n;*                                                                         *\n;*    Use this routine to remove white space characters from the beginning *\n;*    and end of the string.        The string is modified in place by     *\n;*    this routine.                                                        *\n;*                                                                         *\n;* INPUT:   buffer   -- Pointer to the string to modify.                   *\n;*                                                                         *\n;* OUTPUT:     none                                                        *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*\n; VOID cdecl strtrim(BYTE *buffer);\n\tGLOBAL\tC strtrim :NEAR\n\tPROC\tstrtrim C near\n\tUSES\tax, edi, esi\n\n\tARG\tbuffer:DWORD\t\t; Pointer to string to modify.\n\n\tcmp\t[buffer],0\n\tje\tshort ??fini\n\n\t; Prepare for string scanning by loading pointers.\n\tcld\n\tmov\tesi,[buffer]\n\tmov\tedi,esi\n\n\t; Strip white space from the start of the string.\n??looper:\n\tlodsb\n\tcmp\tal,20h\t\t\t; Space\n\tje\tshort ??looper\n\tcmp\tal,9\t\t\t; TAB\n\tje\tshort ??looper\n\tstosb\n\n\t; Copy the rest of the string.\n??gruntloop:\n\tlodsb\n\tstosb\n\tor\tal,al\n\tjnz\tshort ??gruntloop\n\tdec\tedi\n\t; Strip the white space from the end of the string.\n??looper2:\n\tmov\t[edi],al\n\tdec\tedi\n\tmov\tah,[edi]\n\tcmp\tah,20h\n\tje\tshort ??looper2\n\tcmp\tah,9\n\tje\tshort ??looper2\n\n??fini:\n\tret\n\n\tENDP\tstrtrim\n\n\n;***************************************************************************\n;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.  *\n;*                                                                         *\n;*    This routine is used to build a special fading table for C&C.  There *\n;*    are certain colors that get faded to and cannot be faded again.      *\n;*    With this rule, it is possible to draw a shadow multiple times and   *\n;*    not have it get any lighter or darker.                               *\n;*                                                                         *\n;* INPUT:   palette  -- Pointer to the 768 byte IBM palette to build from. *\n;*                                                                         *\n;*          dest     -- Pointer to the 256 byte remap table.               *\n;*                                                                         *\n;*          color    -- Color index of the color to \"fade to\".             *\n;*                                                                         *\n;*          frac     -- The fraction to fade to the specified color        *\n;*                                                                         *\n;* OUTPUT:  Returns with pointer to the remap table.                       *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   10/07/1992 JLB : Created.                                             *\n;*=========================================================================*/\n;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);\n\tGLOBAL\tC Conquer_Build_Fading_Table : NEAR\n\tPROC\tConquer_Build_Fading_Table C near\n\tUSES\tebx, ecx, edi, esi\n\n\tARG\tpalette:DWORD\n\tARG\tdest:DWORD\n\tARG\tcolor:DWORD\n\tARG\tfrac:DWORD\n\n\tLOCAL\tmatchvalue:DWORD\t; Last recorded match value.\n\tLOCAL\ttargetred:BYTE\t\t; Target gun red.\n\tLOCAL\ttargetgreen:BYTE\t; Target gun green.\n\tLOCAL\ttargetblue:BYTE\t\t; Target gun blue.\n\tLOCAL\tidealred:BYTE\n\tLOCAL\tidealgreen:BYTE\n\tLOCAL\tidealblue:BYTE\n\tLOCAL\tmatchcolor:BYTE\t\t; Tentative match color.\n\nALLOWED_COUNT\tEQU\t16\nALLOWED_START\tEQU\t256-ALLOWED_COUNT\n\n\tcld\n\n\t; If the source palette is NULL, then just return with current fading table pointer.\n\tcmp\t[palette],0\n\tje\t??fini1\n\tcmp\t[dest],0\n\tje\t??fini1\n\n\t; Fractions above 255 become 255.\n\tmov\teax,[frac]\n\tcmp\teax,0100h\n\tjb\tshort ??ok\n\tmov\t[frac],0FFh\n??ok:\n\n\t; Record the target gun values.\n\tmov\tesi,[palette]\n\tmov\tebx,[color]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tlodsb\n\tmov\t[targetred],al\n\tlodsb\n\tmov\t[targetgreen],al\n\tlodsb\n\tmov\t[targetblue],al\n\n\t; Main loop.\n\txor\tebx,ebx\t\t\t; Remap table index.\n\n\t; Transparent black never gets remapped.\n\tmov\tedi,[dest]\n\tmov\t[edi],bl\n\tinc\tedi\n\n\t; EBX = source palette logical number (1..255).\n\t; EDI = running pointer into dest remap table.\n??mainloop:\n\tinc\tebx\n\tmov\tesi,[palette]\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\tadd\tesi,ebx\n\n\tmov\tedx,[frac]\n\tshr\tedx,1\n\t; new = orig - ((orig-target) * fraction);\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetred]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealred],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetgreen]\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealgreen],dh\t\t; preserve ideal color gun value.\n\n\tlodsb\t\t\t\t; orig\n\tmov\tdh,al\t\t\t; preserve it for later.\n\tsub\tal,[targetblue]\t\t; al = (orig-target)\n\timul\tdl\t\t\t; ax = (orig-target)*fraction\n\tshl\teax,1\n\tsub\tdh,ah\t\t\t; dh = orig - ((orig-target) * fraction)\n\tmov\t[idealblue],dh\t\t; preserve ideal color gun value.\n\n\t; Sweep through a limited set of existing colors to find the closest\n\t; matching color.\n\n\tmov\teax,[color]\n\tmov\t[matchcolor],al\t\t; Default color (self).\n\tmov\t[matchvalue],-1\t\t; Ridiculous match value init.\n\tmov\tecx,ALLOWED_COUNT\n\n\tmov\tesi,[palette]\t\t; Pointer to original palette.\n\tadd\tesi,(ALLOWED_START)*3\n\n\t; BH = color index.\n\tmov\tbh,ALLOWED_START\n??innerloop:\n\n\txor\tedx,edx\t\t\t; Comparison value starts null.\n\n\t; Build the comparison value based on the sum of the differences of the color\n\t; guns squared.\n\tlodsb\n\tsub\tal,[idealred]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealgreen]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\n\tlodsb\n\tsub\tal,[idealblue]\n\tmov\tah,al\n\timul\tah\n\tadd\tedx,eax\n\tjz\tshort ??perfect\t\t; If perfect match found then quit early.\n\n\tcmp\tedx,[matchvalue]\n\tjae\tshort ??notclose\n\tmov\t[matchvalue],edx\t; Record new possible color.\n\tmov\t[matchcolor],bh\n??notclose:\n\tinc\tbh\t\t\t; Checking color index.\n\tloop\t??innerloop\n\tmov\tbh,[matchcolor]\n??perfect:\n\tmov\t[matchcolor],bh\n\txor\tbh,bh\t\t\t; Make BX valid main index again.\n\n\t; When the loop exits, we have found the closest match.\n\tmov\tal,[matchcolor]\n\tstosb\n\tcmp\tebx,ALLOWED_START-1\n\tjne\t??mainloop\n\n\t; Fill the remainder of the remap table with values\n\t; that will remap the color to itself.\n\tmov\tecx,ALLOWED_COUNT\n??fillerloop:\n\tinc\tbl\n\tmov\tal,bl\n\tstosb\n\tloop\t??fillerloop\n\n??fini1:\n\tmov\tesi,[dest]\n\tmov\teax,esi\n\tret\n\n\tENDP\tConquer_Build_Fading_Table\n\n\n;***************************************************************************\n;* Remove_From_List -- Removes a pointer from a list of pointers.          *\n;*                                                                         *\n;*    This low level routine is used to remove a pointer from a list of    *\n;*    pointers.  The trailing pointers are moved downward to fill the      *\n;*    hole.                                                                *\n;*                                                                         *\n;* INPUT:   list     -- Pointer to list of pointer.                        *\n;*                                                                         *\n;*          index    -- Pointer to length of pointer list.                 *\n;*                                                                         *\n;*          ptr      -- The pointer value to search for and remove.        *\n;*                                                                         *\n;* OUTPUT:  none                                                           *\n;*                                                                         *\n;* WARNINGS:   none                                                        *\n;*                                                                         *\n;* HISTORY:                                                                *\n;*   04/11/1994 JLB : Created.                                             *\n;*   04/22/1994 JLB : Convert to assembly language.                        *\n;*   05/10/1994 JLB : Short pointers now.                                  *\n;*=========================================================================*/\n;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);\n\tGLOBAL\tC Remove_From_List:NEAR\n\tPROC\tRemove_From_List C near\n\tUSES\tedi, esi, ecx, eax\n\tARG\tlist:DWORD\t\t; Pointer to list.\n\tARG\tindex:DWORD\t\t; Pointer to count.\n\tARG\telement:DWORD\t\t; Element to remove.\n\n\t; Fetch the number of elements in the list.  If there are no\n\t; elements, then just exit quickly.\n\tmov\tedi,[index]\n\tmov\tecx,[edi]\n\tjcxz\tshort ??fini2\n\n\t; Fetch pointer to list.\n\tcmp\t[list],0\n\tje\tshort ??fini2\n\tmov\tedi,[list]\n\n\t; Loop through all elements searching for a match.\n\tmov\teax,[element]\n\trepne scasd\n\tjne\tshort ??fini2\t\t; No match found.\n\n\t; Copy all remaining elements down.  If this is the\n\t; last element in the list then nothing needs to be\n\t; copied -- just decrement the list size.\n\tjcxz\tshort ??nocopy\t\t; No copy necessary.\n\tmov\tesi,edi\n\tsub\tedi,4\n\trep movsd\n\n\t; Reduce the list count by one.\n??nocopy:\n\tmov\tedi,[index]\n\tdec\t[DWORD PTR edi]\n\n??fini2:\n\tret\n\n\tENDP\tRemove_From_List\n\n\n; long cdecl Get_EAX();\n\tGLOBAL\tC Get_EAX :NEAR\n\tPROC\tGet_EAX C near\n\tret\n\n\tENDP\tGet_EAX\nendif\n\n\n\tDATASEG\n\nTabA\tDD 6949350\n\tDD 4913933\n\tDD 3474675\n\tDD 2456966\n\tDD 1737338\n\tDD 1228483\n\tDD 868669\n\tDD 614242\n\tDD 434334\n\tDD 307121\n\tDD 217167\n\tDD 153560\n\tDD 108584\n\tDD 76780\n\tDD 54292\n\tDD 38390\n\tDD 27146\n\tDD 19195\n\tDD 13573\n\tDD 9598\n\tDD 6786\n\tDD 4799\n\tDD 3393\n\tDD 2399\n\tDD 1697\n\tDD 1200\n\tDD 848\n\tDD 600\n\tDD 424\n\tDD 300\n\tDD 212\n\tDD 150\n\tDD 106\n\nTabB\tDD 154\n\tDD 218\n\tDD 309\n\tDD 437\n\tDD 618\n\tDD 874\n\tDD 1236\n\tDD 1748\n\tDD 2472\n\tDD 3496\n\tDD 4944\n\tDD 6992\n\tDD 9888\n\tDD 13983\n\tDD 19775\n\tDD 27967\n\tDD 39551\n\tDD 55933\n\tDD 79101\n\tDD 111866\n\tDD 158203\n\tDD 223732\n\tDD 316405\n\tDD 447465\n\tDD 632811\n\tDD 894929\n\tDD 1265621\n\tDD 1789859\n\tDD 2531243\n\tDD 3579718\n\tDD 5062486\n\tDD 7159436\n\tDD 10124971\n\n\tCODESEG\n\n;***********************************************************************************************\n;* Square_Root -- Finds the square root of the fixed pointer parameter.                        *\n;*                                                                                             *\n;* INPUT:   val   -- The fixed point (16:16) value to find the square root of.                 *\n;*                                                                                             *\n;* OUTPUT:  Returns with the square root of the fixed pointer parameter.                       *\n;*                                                                                             *\n;* WARNINGS:   none                                                                            *\n;*                                                                                             *\n;* HISTORY:                                                                                    *\n;*   10/04/1995 JLB : Adapted.                                                                 *\n;*=============================================================================================*/\n;unsigned Square_Root(unsigned val);\n\tGLOBAL\tC Square_Root :NEAR\n\tPROC\tSquare_Root C near\n\tUSES\tebx,edx\n\n\tbsr ebx,eax\n\tjz ??zero\n\n\tmul [DWORD 4*ebx + OFFSET TabA]\n\tshrd eax,edx,10h\n\tadd eax, [4*ebx + OFFSET TabB]\n??zero:\n\tret\n\n\tENDP\tSquare_Root\n\n;----------------------------------------------------------------------------\n\n\tEND\n\n"
  },
  {
    "path": "REDALERT/SURFACE.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SURFACE.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SURFACE.CPP                                                  *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 09/08/96                                                     *\n *                                                                                             *\n *                  Last Update : September 8, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n#if (0)//PG\n#include \"FUNCTION.H\"\n#include \"surface.h\"\n\n\nSurface::Surface(int w, int h, Buffer const * buffer, int pitch) :\n\tWidth(w),\n\tHeight(h),\n\tPitch(pitch)\n{\n\t/*\n\t**\tIf a buffer was specified, then this means that the surface will use the buffer memory\n\t**\tand thus not allocate and manage its own memory.\n\t*/\n\tif (buffer != NULL) {\n\t\tSurfaceData = *buffer;\n\n\t\t/*\n\t\t**\tReduce the dimensions if the buffer is not big enough. This size bounding is only\n\t\t**\tpossible if the buffer size is known. Otherwise, presume that it is big enough.\n\t\t*/\n\t\tif (buffer->Get_Size() > 0 && Get_Size() > buffer->Get_Size()) {\n\n\t\t\tHeight = buffer->Get_Size() / (Width+Pitch);\n\t\t\tif (Height == 0) {\n\t\t\t\tHeight = 1;\n\t\t\t\tWidth = buffer->Get_Size();\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*\n\t\t**\tA new buffer without existing memory specified, will allocate and manage its\n\t\t**\town memory for the surface.\n\t\t*/\n\t\tnew(&SurfaceData) Buffer(Logical_Size());\n\t}\n}\n\n\nSurface::Surface(Surface const & surface, int x, int y, int w, int h) :\n\tWidth(w),\n\tHeight(h),\n\tPitch(surface.Bytes_Per_Line() % w)\n{\n\tnew(&SurfaceData) Buffer((char*)surface.Get_Buffer() + y*surface.Bytes_Per_Line() + x);\n}\n\n\nvoid Surface::Copy_To(Buffer & buffer, int x, int y, int w, int h) const\n{\n\tassert(buffer.Is_Valid());\n\n\t/*\n\t**\tDetermine the width of the region to copy from this surface.\n\t*/\n\tint width = w;\n\tif (width == -1) {\n\t\twidth = Width;\n\t}\n\n\t/*\n\t**\tDetermine the height of the region to copy from this surface.\n\t*/\n\tint height = h;\n\tif (height == -1) {\n\t\theight = Height;\n\t}\n\n\tCopy_To(Rect(x, y, width, height), buffer);\n}\n\n\nvoid Surface::Copy_To(Rect const & fromrect, Buffer & tobuffer) const\n{\n\tassert(fromrect.Is_Valid());\n\tassert(tobuffer.Is_Valid());\n\n\t/*\n\t**\tDetermine the copy-from rectangle. The size is bounded to the source\n\t**\tsize of the surface, regardless of what was specified as the source\n\t**\trectangle.\n\t*/\n\tRect rect = fromrect.Intersect(Rect(0, 0, Width, Height));\n\n\t/*\n\t**\tDetermine the number of bytes to copy. If this number would be\n\t**\tlarger than the size of the destination buffer (presuming the size\n\t**\tof the destination buffer is known), then limit the copy size\n\t**\tto the buffer size.\n\t*/\n\tint tocopy = rect.Size();\n\tif (tobuffer.Get_Size() > 0 && tobuffer.Get_Size() > tocopy) {\n\t\ttocopy = tobuffer.Get_Size();\n\t}\n\n\t/*\n\t**\tDetermine the source starting byte pointer.\n\t*/\n\tchar * source = (char*)Get_Buffer() + rect.Y*Bytes_Per_Line() + rect.X;\n\n\t/*\n\t**\tDetermine the destination buffer pointer. This will always be the\n\t**\tstart of the destination buffer object specified.\n\t*/\n\tchar * dest = tobuffer;\n\n\t/*\n\t**\tDetermine the working pitch value to use. For full width surface\n\t**\tcopies on surfaces that have no inherent pitch, then a very fast\n\t**\tcopy-in-one-fast-step operation can be performed.\n\t*/\n\tint pitch = Bytes_Per_Line() % rect.Width;\n\tif (pitch == 0) {\n\t\tmemmove(dest, source, tocopy);\n\t} else {\n\n\t\t/*\n\t\t**\tCopy the source to the destination in line segments.\n\t\t*/\n\t\tfor (int y = 0; y < rect.Height; y++) {\n\t\t\tmemmove(dest, source, width);\n\t\t\tdest += rect.Width;\n\t\t\tsource += rect.Width + pitch;\n\t\t}\n\t}\n}\n#endif"
  },
  {
    "path": "REDALERT/SURFACE.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/SURFACE.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : SURFACE.H                                                    *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 09/08/96                                                     *\n *                                                                                             *\n *                  Last Update : September 8, 1996 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef SURFACE_H\n#define SURFACE_H\n\n#include\t\"buff.h\"\n#include\t\"rect.h\"\n\n/*\n**\tThis class is used to represent an arbitrary rectangle in a graphic memory space. Typically,\n**\tthis represents what could be called a graphic buffer or even a portion of a graphic buffer.\n**\tIt can also represent a piece of artwork (such as a shape image) to be used to construct a\n**\tdisplay image. This wide range of use is possible, because this class is a very minimal\n**\trepresentation of the graphic data. It holds only the information is absolutely needs and\n**\thas the minimum member functions possible.\n*/\nclass Surface\n{\n\tpublic:\n\t\tSurface(void) : Width(0), Height(0), Pitch(0) {}\n\t\tSurface(int w, int h, Buffer const * buffer=NULL, int pitch=0);\n\t\tSurface(Surface const & surface, int x, int y, int w, int h);\n\t\tvirtual ~Surface(void) {}\n\n\t\t/*\n\t\t**\tBasic manipulation routines for copying entire surfaces or\n\t\t**\ta sub-region.\n\t\t*/\n\t\tvoid Copy_To(Rect const & fromrect, Surface & tosurface, Rect const & torect) const;\n\t\tvoid Copy_To(Rect const & fromrect, Buffer & tobuffer) const;\n\n\t\t/*\n\t\t**\tConvenience routines that make presumptions on what is desired so that a\n\t\t**\tminimum of parameters can be specified. These routine ultimately map to the\n\t\t**\tbasic copy routines.\n\t\t*/\n\t\tvoid Copy_To(Buffer & buffer, int x=0, int y=0, int w=-1, int h=-1) const;\n\t\tvoid Copy_From(Buffer const & buffer, int x=0, int y=0, int w=-1, int h=-1);\n\n\t\t/*\n\t\t**\tBasic query functions. Support routines that will manipulate the underlying\n\t\t**\timage data will require access to this information.\n\t\t*/\n\t\tvoid * Get_Buffer(void) const {return(SurfaceData.Get_Buffer());}\n\t\tint Get_Size(void) const {return(Bytes_Per_Line() * Height);}\n\t\tint Get_Width(void) const {return(Width);}\n\t\tint Get_Height(void) const {return(Height);}\n\t\tint Get_Pitch(void) const {return(Pitch);}\n\n\tprotected:\n\t\tint Bytes_Per_Line(void) const {return(Width+Pitch);}\n\n\t\t/*\n\t\t**\tThis is the pointer to the surface memory. Sometimes this could be allocated memory\n\t\t**\tmanaged by this class but more likely, it is memory that is merely referred to by\n\t\t**\tthis class.\n\t\t*/\n\t\tBuffer SurfaceData;\n\n\t\t/*\n\t\t**\tThis is the width (columns) of the surface (in pixels).\n\t\t*/\n\t\tint Width;\n\n\t\t/*\n\t\t**\tThis ithe height (rows) of the surface (in pixels).\n\t\t*/\n\t\tint Height;\n\n\t\t/*\n\t\t**\tThis is the modulus of the surface underlying memory 'display surface' width\n\t\t**\tdivided by this surface's width. For a surface that is full width, this value\n\t\t**\twill be 0. This value will be non-zero if this surface is referring to a\n\t\t**\tsub-region within another surface.\n\t\t*/\n\t\tint Pitch;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/TAB.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/TAB.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TAB.H                                                        *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 12/15/94                                                     *\n *                                                                                             *\n *                  Last Update : December 15, 1994 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#ifndef TAB_H\n#define TAB_H\n\n#include\t\"sidebar.h\"\n#include\t\"credits.h\"\n\nclass TabClass: public SidebarClass\n{\n\tpublic:\n\t\tTabClass(void);\n\t\tTabClass(NoInitClass const & x) : SidebarClass(x), Credits(x), FlasherTimer(x), MoneyFlashTimer(x) {};\n\n\t\tvirtual void AI(KeyNumType &input, int x, int y);\n\t\tvirtual void Draw_It(bool complete=false);\n\t\tstatic void Draw_Credits_Tab(void);\n\t\tstatic void Hilite_Tab(int tab);\n\t\tvoid Flash_Money(void);\n\n\t\tvirtual void One_Time(void);\t\t\t\t\t\t\t// One-time inits\n\t\tvoid Redraw_Tab(void) {IsToRedraw = true;Flag_To_Redraw(false);};\n\n\t\tCreditClass Credits;\n\n\t\tCDTimerClass<FrameTimerClass> FlasherTimer;\n\n\tprotected:\n\n\t\t/*\n\t\t**\tIf the tab graphic is to be redrawn, then this flag is true.\n\t\t*/\n\t\tunsigned IsToRedraw:1;\n\n\tprivate:\n\t\tvoid Set_Active(int select);\n\n\t\tCDTimerClass<FrameTimerClass> MoneyFlashTimer;\n\n\t\tstatic void const * TabShape;\n};\n\n\n#endif\n"
  },
  {
    "path": "REDALERT/TACTION.H",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/TACTION.H 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : ACTION.H                                                     *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : 11/28/95                                                     *\n *                                                                                             *\n *                  Last Update : November 28, 1995 [JLB]                                      *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n\n#ifndef ACTION_H\n#define ACTION_H\n\ntypedef enum TActionType : unsigned char {\n\tTACTION_NONE,\n\n\tTACTION_WIN,\t\t\t\t\t\t\t\t// player wins!\n\tTACTION_LOSE,\t\t\t\t\t\t\t\t// player loses.\n\tTACTION_BEGIN_PRODUCTION,\t\t\t\t// computer begins factory production.\n\tTACTION_CREATE_TEAM,\t\t\t\t\t\t// computer creates a certain type of team\n\tTACTION_DESTROY_TEAM,\n\tTACTION_ALL_HUNT,\t\t\t\t\t\t\t// all enemy units go into hunt mode (teams destroyed).\n\tTACTION_REINFORCEMENTS,\t\t\t\t\t// player gets reinforcements\n\t\t\t\t\t\t\t\t\t\t\t\t\t// (house that gets them is determined by\n\t\t\t\t\t\t\t\t\t\t\t\t\t// the Reinforcement instance)\n\tTACTION_DZ,\t\t\t\t\t\t\t\t\t// Deploy drop zone smoke.\n\tTACTION_FIRE_SALE,\t\t\t\t\t\t// Sell all buildings and go on rampage.\n\tTACTION_PLAY_MOVIE,\t\t\t\t\t\t//\tPlay movie (temporarily suspend game).\n\tTACTION_TEXT_TRIGGER,\t\t\t\t\t// Triggers a text message display.\n\tTACTION_DESTROY_TRIGGER,\t\t\t\t// Destroy specified trigger.\n\tTACTION_AUTOCREATE,\t\t\t\t\t\t// Computer to autocreate teams.\n\tTACTION_WINLOSE,\t\t\t\t\t\t\t// Win if captured, lose if destroyed.\n\tTACTION_ALLOWWIN,\t\t\t\t\t\t\t// Allows winning if triggered.\n\n\tTACTION_REVEAL_ALL,\t\t\t\t\t\t// Reveal the entire map.\n\tTACTION_REVEAL_SOME,\t\t\t\t\t\t// Reveal map around cell #.\n\tTACTION_REVEAL_ZONE,\t\t\t\t\t\t// Reveal all of specified zone.\n\tTACTION_PLAY_SOUND,\t\t\t\t\t\t// Play sound effect.\n\tTACTION_PLAY_MUSIC,\t\t\t\t\t\t// Play musical score.\n\tTACTION_PLAY_SPEECH,\t\t\t\t\t\t// Play EVA speech.\n\tTACTION_FORCE_TRIGGER,\t\t\t\t\t// Force trigger to activate.\n\tTACTION_START_TIMER,\t\t\t\t\t\t// Start mission timer.\n\tTACTION_STOP_TIMER,\t\t\t\t\t\t// Stop mission timer.\n\tTACTION_ADD_TIMER,\t\t\t\t\t\t// Increase mission timer time.\n\tTACTION_SUB_TIMER,\t\t\t\t\t\t// Decrease mission timer time.\n\tTACTION_SET_TIMER,\t\t\t\t\t\t// Set and start the mission timer.\n\tTACTION_SET_GLOBAL,\t\t\t\t\t\t// Set global variable.\n\tTACTION_CLEAR_GLOBAL,\t\t\t\t\t// Clear global variable.\n\tTACTION_BASE_BUILDING,\t\t\t\t\t// Automated base building.\n\tTACTION_CREEP_SHADOW,\t\t\t\t\t// Shadow grows back one 'step'.\n\n\tTACTION_DESTROY_OBJECT,\t\t\t\t\t// Destroys the building this trigger is attached to.\n\tTACTION_1_SPECIAL,\t\t\t\t\t\t// Add a one-time special weapon ability to house.\n\tTACTION_FULL_SPECIAL,\t\t\t\t\t// Add a repeating special weapon ability to house.\n\n\tTACTION_PREFERRED_TARGET,\t\t\t\t// Designates preferred target for house.\n\tTACTION_LAUNCH_NUKES,\t\t\t\t\t// Launch fake nuclear missiles from all silos\n\n\tTACTION_COUNT,\n\tTACTION_FIRST=0\n} TActionType;\n\nTActionType Action_From_Name(char const * name);\nchar const * Name_From_Action(TActionType action);\nNeedType Action_Needs(TActionType action);\n\nclass TriggerTypeClass;\nclass TeamTypeClass;\n\n/*\n**\tThis elaborates the information necessary to carry out\n**\ta trigger's action.\n*/\nstruct TActionClass {\n\tTActionType\t\tAction;\t// Action to perform.\n\n\tCCPtr<TeamTypeClass> Team;\t// Team type pointer for this action (if needed).\n\n\tCCPtr<TriggerTypeClass> Trigger;\t// Trigger type pointer for this action (if needed).\n\n\tunion {\n\t\tThemeType\t\t\tTheme;\t\t// Musical theme.\n\t\tVocType\t\t\t\tSound;\t\t// Sound effect.\n\t\tVoxType\t\t\t\tSpeech;\t\t// Speech identifier.\n\t\tHousesType\t\t\tHouse;\t\t// House to be affected.\n\t\tSpecialWeaponType Special;\t\t// Special weapon ability.\n\t\tQuarryType\t\t\tQuarry;\t\t// Preferred target for attack.\n\t\tVQType\t\t\t\tMovie;\t\t// The movie to play.\n\t\tbool\t\t\t\t\tBool;\t\t\t// Boolean value.\n\t\tlong\t\t\t\t\tValue;\n\t} Data;\n\n\tTActionClass(void) : Action(TACTION_NONE) {\n\t\tData.Theme = THEME_NONE;\n\t\tData.Value = -1;\n\t};\n\tTActionClass(NoInitClass const & x) : Team(x), Trigger(x) {};\n\n\tvoid Detach(TARGET target);\n\tvoid Code_Pointers(void);\n\tvoid Decode_Pointers(void);\n\tvoid Read_INI(void);\n\tvoid Build_INI_Entry(char * buffer) const;\n\n\tbool operator() (HousesType house, ObjectClass * object, int id, CELL cell);\n};\n\n\nclass ActionChoiceClass {\n\tpublic:\n\t\tActionChoiceClass(TActionType event=TACTION_NONE) : Action(event) {}\n\n\t\toperator TActionType (void) const {return(Action);}\n\t\tbool operator == (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action);}\n\t\tbool operator != (ActionChoiceClass const & rvalue) const {return(Action != rvalue.Action);}\n\t\tbool operator > (ActionChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) > 0);}\n\t\tbool operator < (ActionChoiceClass const & rvalue) const {return(stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator <= (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action || stricmp(Description(), rvalue.Description()) < 0);}\n\t\tbool operator >= (ActionChoiceClass const & rvalue) const {return(Action == rvalue.Action || stricmp(Description(), rvalue.Description()) > 0);}\n\t\tchar const * Description(void) const {return(Name_From_Action(Action));}\n\t\tvoid Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags) const;\n\n\t\tTActionType Action;\n};\n\n\nextern ActionChoiceClass ActionChoices[TACTION_COUNT];\n\n#endif\n"
  },
  {
    "path": "REDALERT/TARGET.CPP",
    "content": "//\n// Copyright 2020 Electronic Arts Inc.\n//\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free \n// software: you can redistribute it and/or modify it under the terms of \n// the GNU General Public License as published by the Free Software Foundation, \n// either version 3 of the License, or (at your option) any later version.\n\n// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed \n// in the hope that it will be useful, but with permitted additional restrictions \n// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT \n// distributed with this program. You should have received a copy of the \n// GNU General Public License along with permitted additional restrictions \n// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection\n\n/* $Header: /CounterStrike/TARGET.CPP 1     3/03/97 10:25a Joe_bostic $ */\n/***********************************************************************************************\n ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***\n ***********************************************************************************************\n *                                                                                             *\n *                 Project Name : Command & Conquer                                            *\n *                                                                                             *\n *                    File Name : TARGET.CPP                                                   *\n *                                                                                             *\n *                   Programmer : Joe L. Bostic                                                *\n *                                                                                             *\n *                   Start Date : September 10, 1993                                           *\n *                                                                                             *\n *                  Last Update : July 16, 1996 [JLB]                                          *\n *                                                                                             *\n *---------------------------------------------------------------------------------------------*\n * Functions:                                                                                  *\n *   As_Aircraft -- Converts the target value into an aircraft pointer.                        *\n *   As_Animation -- Converts target value into animation pointer.                             *\n *   As_Building -- Converts a target value into a building object pointer.                    *\n *   As_Bullet -- Converts the target into a bullet pointer.                                   *\n *   As_Cell -- Converts a target value into a cell number.                                    *\n *   As_Coord -- Converts a target value into a coordinate value.                              *\n *   As_Infantry -- If the target is infantry, return a pointer to it.                         *\n *   As_Movement_Coord -- Fetches coordinate if trying to move to this target.                 *\n *   As_Object -- Converts a target value into an object pointer.                              *\n *   As_Target -- Converts a cell into a target value.                                         *\n *   As_Target -- Converts a coordinate into a target value.                                   *\n *   As_Team -- Converts a target number into a team pointer.                                  *\n *   As_TeamType -- Converts a target into a team type pointer.                                *\n *   As_Techno -- Converts a target value into a TechnoClass pointer.                          *\n *   As_TechnoType -- Convert the target number into a techno type class pointer.              *\n *   As_Trigger -- Converts specified target into a trigger pointer.                           *\n *   As_TriggerType -- Convert the specified target into a trigger type.                       *\n *   As_Unit -- Converts a target value into a unit pointer.                                   *\n *   As_Vessel -- Converts a target number into a vessel pointer.                              *\n *   TClass::TClass -- Constructor for target from object pointer.                             *\n *   TargetClass::As_Object -- Converts a target into an object pointer.                       *\n *   TargetClass::As_Techno -- Converts a target into a techno object pointer.                 *\n *   Target_Legal -- Determines if the specified target is legal.                              *\n * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\n\n#include\t\"function.h\"\n#include\t\"target.h\"\n\n\nTargetClass::TargetClass(TARGET target)\n{\n\tTarget.Target = target;\n}\n\n\nTargetClass::TargetClass(AbstractClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = ptr->RTTI;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nTargetClass::TargetClass(AbstractTypeClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = ptr->RTTI;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nTargetClass::TargetClass(CellClass const * ptr) {\n\tif (ptr != NULL) {\n\t\tTarget.Sub.Exponent = RTTI_CELL;\n\t\tTarget.Sub.Mantissa = ptr->ID;\n\t} else {\n\t\tTarget.Sub.Exponent = RTTI_NONE;\n\t}\n}\n\nCellClass * xTargetClass::As_Cell(void) const\n{\n\tif (Target.Sub.Exponent == RTTI_CELL) {\n\t\treturn(&Map[(CELL)Target.Sub.Mantissa]);\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_Trigger -- Converts specified target into a trigger pointer.                             *\n *                                                                                             *\n *    This routine will convert the specified target number into a trigger pointer.            *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the trigger pointer that the specified target number represents. If   *\n *          it doesn't represent a legal trigger object, then NULL is returned.                *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerClass * As_Trigger(TARGET target, bool check_active)\n{\n\tTriggerClass* trigger = Is_Target_Trigger(target) ? Triggers.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && trigger != NULL && !trigger->IsActive) {\n\t\ttrigger = NULL;\n\t}\n\treturn(trigger);\n}\n\n\n/***********************************************************************************************\n * As_Team -- Converts a target number into a team pointer.                                    *\n *                                                                                             *\n *    This routine will convert the specified target number into a team pointer.               *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with the team object that the specified target number represents. If it    *\n *          doesn't represent a legal team then NULL is returned.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamClass * As_Team(TARGET target, bool check_active)\n{\n\tTeamClass* team = Is_Target_Team(target) ? Teams.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && team != NULL && !team->IsActive) {\n\t\tteam = NULL;\n\t}\n\treturn(team);\n}\n\n\n/***********************************************************************************************\n * As_TeamType -- Converts a target into a team type pointer.                                  *\n *                                                                                             *\n *    This routine will convert the specified target number into a team type pointer.          *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the team type represented by the target number. If the   *\n *          target number doesn't represent a legal team type, then NULL is returned.          *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nTeamTypeClass * As_TeamType(TARGET target)\n{\n\treturn(Is_Target_TeamType(target) ? TeamTypes.Raw_Ptr(Target_Value(target)) : NULL);\n}\n\n\n/***********************************************************************************************\n * As_Animation -- Converts target value into animation pointer.                               *\n *                                                                                             *\n *    This routine will convert the specified target number into an animation pointer.         *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert into an animation pointer.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the legal animation that this target represents. If it   *\n *          doesn't represent a legal animation, then NULL is returned.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAnimClass * As_Animation(TARGET target, bool check_active)\n{\n\tAnimClass* anim = Is_Target_Animation(target) ? Anims.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && anim != NULL && !anim->IsActive) {\n\t\tanim = NULL;\n\t}\n\treturn(anim);\n}\n\n\n/***********************************************************************************************\n * As_Bullet -- Converts the target into a bullet pointer.                                     *\n *                                                                                             *\n *    This routine will convert the specified target number into a bullet pointer.             *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the bullet it specifies. If the target doesn't refer to  *\n *          a legal bullet, then NULL is returned.                                             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/08/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nBulletClass * As_Bullet(TARGET target, bool check_active)\n{\n\tBulletClass* bullet = Is_Target_Bullet(target) ? Bullets.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && bullet != NULL && !bullet->IsActive) {\n\t\tbullet = NULL;\n\t}\n\treturn(bullet);\n}\n\n\n/***********************************************************************************************\n * As_Aircraft -- Converts the target value into an aircraft pointer.                          *\n *                                                                                             *\n *    This routine will convert the specified target value into an aircraft object pointer.    *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the aircraft that this target value represents. If the   *\n *          specified target value doesn't represent an aircraft, then NULL is returned.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nAircraftClass * As_Aircraft(TARGET target, bool check_active)\n{\n\tAircraftClass* aircraft = Is_Target_Aircraft(target) ? Aircraft.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && aircraft != NULL && !aircraft->IsActive) {\n\t\taircraft = NULL;\n\t}\n\treturn(aircraft);\n}\n\n\n/***********************************************************************************************\n * As_Techno -- Converts a target value into a TechnoClass pointer.                            *\n *                                                                                             *\n *    This routine will take the target value specified and convert it into a TechnoClass      *\n *    pointer if the target represents an object that has a TechnoClass.                       *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a TechnoClass pointer.                *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the associated object's TechnoClass. If the target       *\n *          cannot be converted into a TechnoClass pointer, then NULL is returned.             *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   06/02/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * As_Techno(TARGET target, bool check_active)\n{\n\tObjectClass * obj = As_Object(target, check_active);\n\n\tif (obj && obj->Is_Techno()) {\n\t\treturn(TechnoClass *)obj;\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_Object -- Converts a target value into an object pointer.                                *\n *                                                                                             *\n *    This routine is used to convert the target value specified into an object pointer. If    *\n *    the target doesn't represent an object or the target value is illegal, then NULL is      *\n *    returned.                                                                                *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert from.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object it represent, or NULL if not an object.       *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nObjectClass * As_Object(TARGET target, bool check_active)\n{\n\tint val = Target_Value(target);\n\tObjectClass * object = NULL;\n\tswitch (Target_Kind(target)) {\n\t\tcase RTTI_INFANTRY:\n\t\t\tobject = Infantry.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tobject = Units.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tobject = Vessels.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tobject = Buildings.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tobject = Aircraft.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tobject = Terrains.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tobject = Bullets.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tobject = Anims.Raw_Ptr(val);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t/*\n\t**\tSpecial check to ensure that a target value that references an\n\t**\tinvalid object will not be converted back into an object pointer.\n\t**\tThis condition is rare, but could occur in a network game if the\n\t**\tobject it refers to is destroyed between the time an event message\n\t**\tis sent and when it is received.\n\t*/\n\tif (check_active && object != NULL && !object->IsActive) {\n\t\tobject = NULL;\n\t}\n\n\treturn(object);\n}\n\n\n/***********************************************************************************************\n * As_Unit -- Converts a target value into a unit pointer.                                     *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a pointer to a unit      *\n *    object.                                                                                  *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a unit pointer.                       *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the unit the target value represents or NULL if not      *\n *          a unit.                                                                            *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nUnitClass * As_Unit(TARGET target, bool check_active)\n{\n\tUnitClass* unit = Is_Target_Unit(target) ? Units.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && unit != NULL && !unit->IsActive) {\n\t\tunit = NULL;\n\t}\n\treturn(unit);\n}\n\n\n/***********************************************************************************************\n * As_Vessel -- Converts a target number into a vessel pointer.                                *\n *                                                                                             *\n *    Use this routine to conver the specified target number into a pointer to a vessel object *\n *    that it represents.                                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert to a vessel pointer.                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the vessel object that this target value represents. If  *\n *          the target number does not represent a vessel, then null is returned.              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nVesselClass * As_Vessel(TARGET target, bool check_active)\n{\n\tVesselClass* vessel = Is_Target_Vessel(target) ? Vessels.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && vessel != NULL && !vessel->IsActive) {\n\t\tvessel = NULL;\n\t}\n\treturn(vessel);\n}\n\n\n/***********************************************************************************************\n * As_Infantry -- If the target is infantry, return a pointer to it.                           *\n *                                                                                             *\n *    This routine will translate the specified target value into an infantry pointer if the   *\n *    target actually represents an infantry object.                                           *\n *                                                                                             *\n * INPUT:   target   -- The target to convert to a pointer.                                    *\n *                                                                                             *\n * OUTPUT:  Returns a pointer to the infantry object that this target value represents. If     *\n *          the target doesn't represent an infantry object, then return NULL.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   10/17/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nInfantryClass * As_Infantry(TARGET target, bool check_active)\n{\n\tInfantryClass* infantry = Is_Target_Infantry(target) ? Infantry.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && infantry != NULL && !infantry->IsActive) {\n\t\tinfantry = NULL;\n\t}\n\treturn(infantry);\n}\n\n\n/***********************************************************************************************\n * As_Building -- Converts a target value into a building object pointer.                      *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a building pointer.      *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert from.                                      *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the building object that the target value represents.    *\n *          If it doesn't represent a building, then return NULL.                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nBuildingClass * As_Building(TARGET target, bool check_active)\n{\n\tBuildingClass* building = Is_Target_Building(target) ? Buildings.Raw_Ptr(Target_Value(target)) : NULL;\n\tif (check_active && building != NULL && !building->IsActive) {\n\t\tbuilding = NULL;\n\t}\n\treturn(building);\n}\n\n\n/***********************************************************************************************\n * Target_Legal -- Determines if the specified target is legal.                                *\n *                                                                                             *\n *    This routine is used to check for the legality of the target value specified. It is      *\n *    necessary to call this routine if there is doubt about the the legality of the target.   *\n *    It is possible for the unit that a target value represents to be eliminated and thus     *\n *    rendering the target value invalid.                                                      *\n *                                                                                             *\n * INPUT:   target   -- The target value to check.                                             *\n *                                                                                             *\n * OUTPUT:  bool; Is the target value legal?                                                   *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nbool Target_Legal(TARGET target)\n{\n\tif (target == TARGET_NONE) return(false);\n\n\tObjectClass * obj = As_Object(target, false);\n\tif (obj) {\n\t\treturn(obj->IsActive);\n\t}\n\treturn(true);\n}\n\n\n/***********************************************************************************************\n * As_Cell -- Converts a target value into a cell number.                                      *\n *                                                                                             *\n *    This routine is used to convert the target value specified, into a cell value. This is   *\n *    necessary for find path and other procedures that need a cell value.                     *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert to a cell value.                           *\n *                                                                                             *\n * OUTPUT:  Returns with the target value expressed as a cell location.                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *=============================================================================================*/\nCELL As_Cell(TARGET target)\n{\n\treturn(Coord_Cell(As_Coord(target)));\n}\n\n\n/***********************************************************************************************\n * As_Coord -- Converts a target value into a coordinate value.                                *\n *                                                                                             *\n *    This routine is used to convert the target value specified into a coordinate value. It   *\n *    is necessary for those procedures that require a coordinate value.                       *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert.                                           *\n *                                                                                             *\n * OUTPUT:  Returns with the target expressed as a COORDINATE value.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   05/27/1994 JLB : Created.                                                                 *\n *   11/16/1994 JLB : Simplified.                                                              *\n *=============================================================================================*/\nCOORDINATE As_Coord(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\t/*\n\t\t**\tCell target values are handled as a special case. The value of the target number is\n\t\t**\tactually the cell index number.\n\t\t*/\n\t\tif (Is_Target_Cell(target)) {\n\t\t\tint v = Target_Value(target);\n\n\t\t\tint x = ((v & 0x0FFF) << 4) + 0x0008;\n\t\t\tint y = (((v>>12) & 0x0FFF) << 4) + 0x0008;\n\t\t\treturn(XY_Coord(x, y));\n\n//\t\t\treturn(Cell_Coord((CELL)Target_Value(target)));\n\t\t}\n\n\t\t/*\n\t\t**\tNormal targets correspond to game objects. Fetch the object pointer and then ask it\n\t\t**\tfor the center coordinate. Return the center coordinate as the target's coordinate.\n\t\t*/\n\t\tObjectClass * obj = As_Object(target);\n\t\tif (obj != NULL) {\n\t\t\tassert(obj->IsActive);\n\t\t\treturn(obj->Target_Coord());\n\t\t}\n\t}\n\n\t/*\n\t**\tAn unrecognized target value results in a null coordinate value.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * As_Movement_Coord -- Fetches coordinate if trying to move to this target.                   *\n *                                                                                             *\n *    This routine will convert the specified target into a coordinate location. This location *\n *    is used when moving to the target specified. For cells, this is the center of the cell.  *\n *    For special buildings that allow docking, it is the center location of the docking       *\n *    bay.                                                                                     *\n *                                                                                             *\n * INPUT:   target   -- The target to convert into a coordinate value.                         *\n *                                                                                             *\n * OUTPUT:  Returns with the docking coordinate of the target value specified.                 *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   08/27/1995 JLB : Created.                                                                 *\n *=============================================================================================*/\nCOORDINATE As_Movement_Coord(TARGET target)\n{\n\tif (Target_Legal(target)) {\n\t\t/*\n\t\t**\tCell target values are handled as a special case. The value of the target number is\n\t\t**\tactually the cell index number.\n\t\t*/\n\t\tif (Is_Target_Cell(target)) {\n\t\t\treturn(Cell_Coord((CELL)Target_Value(target)));\n\t\t}\n\n\t\t/*\n\t\t**\tNormal targets correspond to game objects. Fetch the object pointer and then ask it\n\t\t**\tfor the center coordinate. Return the center coordinate as the target's coordinate.\n\t\t*/\n\t\tObjectClass * obj = As_Object(target);\n\t\tif (obj) {\n\t\t\treturn(obj->Docking_Coord());\n\t\t}\n\t}\n\n\t/*\n\t**\tAn unrecognized target value results in a null coordinate value.\n\t*/\n\treturn(0x00000000L);\n}\n\n\n/***********************************************************************************************\n * TargetClass::As_Object -- Converts a target into an object pointer.                         *\n *                                                                                             *\n *    If the target represents an object of some type, then this routine will return a         *\n *    pointer to the object. Otherwise it will return NULL.                                    *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the object that this target represents or NULL if it     *\n *          doesn't represent a target.                                                        *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nAbstractClass * xTargetClass::As_Abstract(bool check_active) const\n{\n\tAbstractClass* abst = NULL;\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TEAM:\n\t\t\tabst = Teams.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tabst = Bullets.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_OVERLAY:\n\t\t\tabst = Overlays.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_SMUDGE:\n\t\t\tabst = Smudges.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tabst = Units.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tabst = Vessels.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tabst = Buildings.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tabst = Infantry.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tabst = Aircraft.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_TERRAIN:\n\t\t\tabst = Terrains.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tabst = Anims.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (check_active && abst != NULL && !abst->IsActive) {\n\t\tabst = NULL;\n\t}\n\treturn(abst);\n}\n\n\nAbstractTypeClass * xTargetClass::As_TypeClass(void) const\n{\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TEAMTYPE:\n\t\t\treturn(TeamTypes.Raw_Ptr(Value()));\n\n\t\tcase RTTI_TRIGGERTYPE:\n\t\t\treturn(TriggerTypes.Raw_Ptr(Value()));\n\n\t\tcase RTTI_BULLETTYPE:\n\t\t\treturn((BulletTypeClass *)&BulletTypeClass::As_Reference(BulletType(Value())));\n\n\t\tcase RTTI_OVERLAY:\n\t\t\treturn((OverlayTypeClass *)&OverlayTypeClass::As_Reference(OverlayType(Value())));\n\n\t\tcase RTTI_SMUDGE:\n\t\t\treturn((SmudgeTypeClass *)&SmudgeTypeClass::As_Reference(SmudgeType(Value())));\n\n\t\tcase RTTI_UNIT:\n\t\t\treturn((UnitTypeClass *)&UnitTypeClass::As_Reference(UnitType(Value())));\n\n\t\tcase RTTI_VESSEL:\n\t\t\treturn((VesselTypeClass *)&VesselTypeClass::As_Reference(VesselType(Value())));\n\n\t\tcase RTTI_BUILDING:\n\t\t\treturn((BuildingTypeClass *)&BuildingTypeClass::As_Reference(StructType(Value())));\n\n\t\tcase RTTI_INFANTRY:\n\t\t\treturn((InfantryTypeClass *)&InfantryTypeClass::As_Reference(InfantryType(Value())));\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\treturn((AircraftTypeClass *)&AircraftTypeClass::As_Reference(AircraftType(Value())));\n\n\t\tcase RTTI_TERRAIN:\n\t\t\treturn((TerrainTypeClass *)&TerrainTypeClass::As_Reference(TerrainType(Value())));\n\n\t\tcase RTTI_ANIM:\n\t\t\treturn((AnimTypeClass *)&AnimTypeClass::As_Reference(AnimType(Value())));\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn(0);\n}\n\n\n/***********************************************************************************************\n * TargetClass::As_Techno -- Converts a target into a techno object pointer.                   *\n *                                                                                             *\n *    This routine is used to convert the target object into a pointer to a techno class       *\n *    object. If the target doesn't specify a techno class object, then NULL is returned.      *\n *                                                                                             *\n * INPUT:   none                                                                               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the techno class object that this target represents or   *\n *          else it returns NULL.                                                              *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoClass * xTargetClass::As_Techno(bool check_active) const\n{\n\tTechnoClass* techno = NULL;\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_UNIT:\n\t\t\ttechno = Units.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\ttechno = Vessels.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\ttechno = Buildings.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\ttechno = Infantry.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\ttechno = Aircraft.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (check_active && techno != NULL && !techno->IsActive) {\n\t\ttechno = NULL;\n\t}\n\treturn(techno);\n}\n\n\nObjectClass * xTargetClass::As_Object(bool check_active) const\n{\n\tObjectClass* object = NULL;\n\tswitch ((RTTIType)*this) {\n\t\tcase RTTI_TERRAIN:\n\t\t\tobject = Terrains.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_SMUDGE:\n\t\t\tobject = Smudges.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_OVERLAY:\n\t\t\tobject = Overlays.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_BULLET:\n\t\t\tobject = Bullets.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_ANIM:\n\t\t\tobject = Anims.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_UNIT:\n\t\t\tobject = Units.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_VESSEL:\n\t\t\tobject = Vessels.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_BUILDING:\n\t\t\tobject = Buildings.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_INFANTRY:\n\t\t\tobject = Infantry.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tcase RTTI_AIRCRAFT:\n\t\t\tobject = Aircraft.Raw_Ptr(Value());\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (check_active && object != NULL && !object->IsActive) {\n\t\tobject = NULL;\n\t}\n\treturn(object);\n}\n\n\n\n\n/***********************************************************************************************\n * As_Target -- Converts a cell into a target value.                                           *\n *                                                                                             *\n *    This routine will convert a cell into a target value.                                    *\n *                                                                                             *\n * INPUT:   cell  -- The cell number that will be coerced into a target value.                 *\n *                                                                                             *\n * OUTPUT:  Returns with the target value that this cell represents.                           *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET As_Target(CELL cell)\n{\n\tint x = Cell_X(cell);\n\tint y = Cell_Y(cell);\n\n\tx <<= 4;\n\ty <<= 4;\n\n\tx += 0x0008;\n\ty += 0x0008;\n\n\treturn(Build_Target(RTTI_CELL, ((y << 12) | x) ));\n}\n\n\n/***********************************************************************************************\n * As_Target -- Converts a coordinate into a target value.                                     *\n *                                                                                             *\n *    This routine is used to convert the specified coordinate into a target value.            *\n *                                                                                             *\n * INPUT:   coord -- The coordinate that is to be converted into a target value.               *\n *                                                                                             *\n * OUTPUT:  Returns with the target value that represents the coordinate.                      *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   03/05/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTARGET As_Target(COORDINATE coord)\n{\n\tint x = Coord_X(coord);\n\tint y = Coord_Y(coord);\n\n\tx >>= 4;\n\ty >>= 4;\n\n\treturn(Build_Target(RTTI_CELL, ((y << 12) | x) ));\n}\n\n\n/***********************************************************************************************\n * As_TechnoType -- Convert the target number into a techno type class pointer.                *\n *                                                                                             *\n *    This routine will conver the specified target number into a pointer to the techno        *\n *    type class that it represents.                                                           *\n *                                                                                             *\n * INPUT:   target   -- The target number to convert.                                          *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the TechnoTypeClass object that the target number        *\n *          represents. If it doesn't represent that kind of object, then NULL is returned.    *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTechnoTypeClass const * As_TechnoType(TARGET target)\n{\n\tint val = Target_Value(target);\n\tswitch (Target_Kind(target)) {\n\t\tcase RTTI_INFANTRYTYPE:\n\t\t\treturn(&InfantryTypeClass::As_Reference(InfantryType(val)));\n\n\t\tcase RTTI_UNITTYPE:\n\t\t\treturn(&UnitTypeClass::As_Reference(UnitType(val)));\n\n\t\tcase RTTI_VESSELTYPE:\n\t\t\treturn(&VesselTypeClass::As_Reference(VesselType(val)));\n\n\t\tcase RTTI_AIRCRAFTTYPE:\n\t\t\treturn(&AircraftTypeClass::As_Reference(AircraftType(val)));\n\n\t\tcase RTTI_BUILDINGTYPE:\n\t\t\treturn(&BuildingTypeClass::As_Reference(StructType(val)));\n\n\t}\n\treturn(NULL);\n}\n\n\n/***********************************************************************************************\n * As_TriggerType -- Convert the specified target into a trigger type.                         *\n *                                                                                             *\n *    This routine will conver the target number into a pointer to the trigger type it         *\n *    represents.                                                                              *\n *                                                                                             *\n * INPUT:   target   -- The target value to convert into a trigger type pointer.               *\n *                                                                                             *\n * OUTPUT:  Returns with a pointer to the trigger type object that the specified target value  *\n *          represents. If it doesn't represent a trigger type, then NULL is returned.         *\n *                                                                                             *\n * WARNINGS:   none                                                                            *\n *                                                                                             *\n * HISTORY:                                                                                    *\n *   07/16/1996 JLB : Created.                                                                 *\n *=============================================================================================*/\nTriggerTypeClass * As_TriggerType(TARGET target)\n{\n\tif (Target_Kind(target) == RTTI_TRIGGERTYPE) {\n\t\treturn(TriggerTypes.Raw_Ptr(Target_Value(target)));\n\t}\n\treturn(NULL);\n}"
  }
]